Picture zapper: an end to black holes and venetian blinds. William Tenney.
While developing a game program in Applesoft recently, I came up against a rather thorny problem which left me stumped. My particular game requires a fairly complex hi-res game board across which pieces are moved by the players.
My thorny problem arises when moving a game piece from one position to another on the game board; the piece must be erased or xdrawn before it can be drawn in the next position. However, in doing this, part of the background of the game board itself is also erased, leaving a gaping black hole. Since my game is not of the interstellar or galactic warfare type, black holes are definitely not wanted.
There are a few options for overcoming this little problem with my 48K Apple II Plus. One, and perhaps the most obvious to the reader, is to plan always to have a black background for the game board, and to plan the size, shape, and positions of the game pieces so that they never overlap any other image elements.
This is fine, but since my game board is rather complicated with many small pieces on it, and since I am quite tired of seeing other game boards on black backgrounds, this option is less than satisfactory.
A second option is to redraw the game board after each move and then redraw the game pieces in their new positions. But with a complex board with many color blocks, lines, and figures, it takes a full minute to draw the board and all its parts--not practical at all to wait a full minute after each move before going on with the game.
A third option is to store the entire game board image on the disk using a BSAVE command, and then to call it back to the hi-res screen using a BLOAD command. This works fine, but although the time of loading and drawing the game board is reduced from one minute to about thirteen seconds, the disk drive is in motion for each move of the game--far too much wear and tear on the disk and drive, and still to much time wasted waiting for the disk to turn on and draw the image on the screen with its venetian blind imitation.
So these three options proved to be unworkable for me from both hardware andaesthetic points of view. But, I thought to myself, why could't I attempt what the memory expansion boards are touting with their disk simulators? Couldn't I move the 8K hi-res image to another part of memory, store it there, and call it back to the same hi-res screen whenever I needed it, and faster than using a BLOAD?
To accomplish this from Basic was the problem, because all it would be was a simple memory move in the monitor. With this in mind, I wrote a short machine language program which very successfully does just what I wanted.
The program uses an Applesoft routine called COMBYTE which resides in $E74C (thanks to Roger Wagner for pointing it out). COMBYTE checks for a comma, reads the expression which follows, and returns with a single byte ($00 to $FF) in the X-register, which can then be stored in a zero-page location. The four zero-page locations used are shown in Figure 1.
The program cycles 32 times ($20 in line $0315), each pass reading and moving a 256-byte page of memory. It runs incredibly fast, moving all 32 pages, or an entire 8K image, in about .3 seconds.
Since I am using hi-res screen 2 ($4000-$5FFF) for my game image, but need the region of the hi-res screen 1 for my program and variables, I decided that a good place to store my image would be right above hi-res screen 2, at $6000. This location is well below the HIMEM of $95FF (with DOS in effect), and since the image is $2000 bytes long, it does not bump into any string variables stored from HIMEM on down.
To use this routine from Applesoft--to move an image from hi-res screen 2 to the storage area at $6000--my syntax is as follows:
CALL 768,0,64,0,96 where 768 is equal to $300, the starting point of the routine, 0 is the SOURCE-LO, 64 is the SOURCE-HI (remember that 64 = $40), 0 is the DESTIN-LO, and 96 is the DESTIN-HI (96 = $60).
To move the image back to the hi-res screen 2 (while keeping it at the storage location as well)8 the syntax is
To really speed up your programming, you could set up a "p' hook:
POKE 1014,0: POKE 1015,3 which sets a Jump instruction to $300 Then your syntax would be
&,0,64,0,96 and &,0,96,0,64
Now I can erase a game piece by redrawing the entire game board using this routine, and then draw the game pieces in their respective places, all in less than a second. The game proceeds at a good clip.
Of course, this short program can be used to move any block of memory anywhere, since it is merely a memory move routine. You need only work in blocks of 256 bytes and know the starting point and number of memory pages (store this number in $0315).
A low-res image, for example, is only four pages long. The machine language coding is completely relocatable to any spare 40 bytes of memory (remember that at a different location your CALL would be to the start of your routine). Try it, you'll like it. For moving pictures around, the program is superb--and no more black holes or venetian blinds.
Table: Figure 1.
Table: Listing 1. Picture Zapper.