Interlude: Spectrum vs. C64 Basic Showdown

ibobev1 pts0 comments

Interlude: Spectrum vs. C64 BASIC Showdown | Bumbershoot Software

Before moving on to commanding the ZX Spectrum’s graphics hardware more directly, it’s time to settle some scores.

One of the things I particularly liked about the ZX Spectrum’s BASIC is that it provides pretty powerful commands that let you directly work with everything the system has to offer, and it lets you do it quite easily. The closest we got to having to do an end run around BASIC here was POKE ing in the graphics for the umbrella—and even that was just using it to fill a buffer that BASIC itself gave us. Commodore 64 BASIC, rather infamously, offers basically no direct support for its own hardware. Everything is done via memory-mapped I/O with POKE and PEEK , directly. Furthermore, in an unpleasant number of cases, it’s really necessary to supplement the BASIC program with some machine language support programs to keep everything running at an acceptable speed.

So I got to thinking. What does it take to match this simple display from the TI-99/4A, and later the MSX and ZX Spectrum, on the C64? Obviously it can do it. But what does it take to do it in 100% BASIC, and how idiomatic can we make it?

Defining the Problem

The C64’s default text mode is markedly unlike the ones offered by the TMS9918A chip in the TI and MSX, and it also differs from the ZX Spectrum’s treatment of character attributes. When in its normal text mode, there is a single background for the entire screen, and only the foreground color may vary. This can be bent in its Extended Background Color Mode, or bypassed entirely in its full bitmap mode. The C64’s bitmap mode uses what is normally the text display almost exactly the same way the ZX Spectrum uses its attribute table, in fact, so the most direct solution would be to switch into the bitmap mode and draw the display directly there.

This is an extremely drastic step, though, and the C64 Programmer’s Reference Guide is quite explicit that the bitmap mode is impractical to use in BASIC. We just need to shift our perspective a bit. Instead of thinking of this as a screen split between regions with a green background and regions with a black background, we should think of it as a screen where the whole background is black, but most of the screen is covered with solid green foreground. We don’t even need extended color mode for this one.

To get the umbrella graphic itself, we redefined four characters and assigned them appropriate colors. This is a bit of legerdemain on the part of the ZX Spectrum, since its display is always exclusively a bitmap mode and "characters" are simply conveniently predefined bit patterns, but the end result matches what we saw on the TI and what we intend here on the C64: the actual rendering of the banner graphic is done purely with PRINT statements.

So, for a graphic that matches the original TI display and logic as closely as possible, here is our general plan:

Copy the mixed-case character set out of ROM and into RAM.

Redefine a few of the characters in our RAM copy to give us our graphic.

Switch the active character set to our modified RAM copy. At this point we have replicated the CALL CHAR code in the TI original.

Turn the screen black, the border green, and fill the screen with green inverted spaces.

Draw the banner with a series of print statements.

Wait for a keypress.

Set the active character set back to default PETSCII, restore the border, background, and text colors, and clear the screen so that BASIC has returned to its normal state.

Seems easy enough, and we can prove the strategy out first by writing it in assembly language. The whole program is about 100 lines long—a bit under twice as long as the ZX Spectrum version we made last week—but it shows our idea here is sound.

A First Draft

Setting up a custom character set in BASIC is a task that’s common enough that there’s stock code for doing it. Here’s a typical one, very lightly adapted from Sheldon Leemon’s Mapping the C64 and encoded using the input format that the VICE project’s petcat utility expects:

10 poke 828,peek(56):poke 56,48:clr:z=peek(828)<br>20 poke 56333,127:poke 1,peek(1) and 251:for i=0 to 2047<br>30 poke 12288+i,peek(55296+i):next:poke 1,peek(1) or 4:poke 56333,129<br>40 for i=0 to 31:read a:poke 12568+i,a:next:poke 53272,28<br>1000 rem bumbershoot graphic<br>1010 data 3,15,31,63,127,127,255,255<br>1020 data 192,240,248,248,240,224,192,128<br>1030 data 255,254,124,120,48,0,0,0<br>1040 data 128,192,96,48,24,8,56,0

We need to set aside some RAM to hold our custom character set, and to do that we’ll need to modify BASIC’s memory layout. We’d like to restore it afterwards, though, so line 10 here prepares that. It records the original top of BASIC RAM in a scratch byte inside what is normally the cassette loading buffer, reconfigures BASIC to only have 10KB of memory (2048-12287, more than enough for us), then reloads the value out of the buffer into a proper BASIC variable. That little jaunt through the...

basic poke spectrum mode screen peek

Related Articles