[Figure: Figure 1. Actual Display (screen grid showing rows 8-23, the playfield starting at P+9, the “ceiling”, 0 height, the carrier at P+193, and the HT/DIST/LINE print lines)]
“How to make a million dollars and NEVER pay taxes,” by Steven Martin. “First, get a million dollars…”
As computerists, the million-dollar question that you and I had after learning ZX80 fundamentals was, “Okay, now what do I do with it?”
First…Get an Idea
The general idea for Flattop Lander was a natural progression from my other “aircraft” games. Good ideas are all around you—take a look.
Probably everyone has seen a movie showing landings on aircraft carriers, whether of WWII propcraft or of modern-Navy jets. There are two images that we retain: the view from the aircraft (pilot’s view) and the scene from deck or from another ship. Your first decision after getting an idea is to choose a display image.
For a descent pilot’s view sequence with its separate “frames” for a three dimensional effect, several hundred addresses in RAM must be used to store the different characters needed. With only 1K of RAM available for both display and basic program, the pilot’s view option is out.
The next best thing is to combine a 2-D display (side-view) of the landing with a routine that requires the player to “get into” the display. In other words, require an input that involves the player, making him/her construct a mental image or “mind’s eye” picture as in Figures 1 and 2.
[Figure: Figure 2. Mental “Window” (3 x 3 grid numbered 1-9 with the aircraft carrier at the bottom centre)]
This “window” is recognizable as the standard 3 x 3 input matrix, but with a 3-D twist: 5 means straight ahead and 9 means down to the right, etc. The Basic display of Height and Distance are not really necessary, because the player can see his position on screen. But the LINE is not optional—that tells the pilot which way to turn: left “<“, right “>”, or “X” for on-line for a straight landing. (That is part of the deck flagman’s job.)
So, in the planning stage for your display, refine your idea to a scene that allows both room for movement and room for the Basic statements and any Basic printouts you may need.
Display Construction
First, you must estimate just how much display you can have—enough to make the “play” visually interesting, but not so much that the program will crash or stop on error code 5 (no more room on screen).
Remember that each space assigned to a screen display means one less address that can be used in the Basic program (and vice versa).
In Flattop Lander, since the last 400 feet in height are the most important to a pilot, the actual “play field” can be set up as 5 rows of 32 spaces for aircraft movement, 1 row for the zero-height of the flight deck and carrier characters, and 1 row of sea surface. Thus, 7 rows of 32 spaces plus 7 “118’s” as end-line markers plus 8 “118’s” to move the play field to mid-screen totals 239 addresses—leaving 700+ for the Basic program.
Second, work out how you would construct your display in Basic. For Flattop Lander, it would take around 20 statement lines and 2 or 3 seconds in execution time. The obvious advantage of an MCD version is that, while it may take more “know-how” to write, execution time is typically less than half a second…short enough for anyone’s attention span.
Next, translate your Basic display into Machine Code decimal values.
Z80 Source Coding for Flattop Lander (4K/1K)
This subroutine produces instantly a blank field and 1 row of seasurface characters. The aircraft and carrier will be POKEd in later via Basic, enabling movement experiments of the aircraft and/or carrier. The idea is to produce 239 spaces on screen quickly so that by POKEing only 9 characters in different places, the whole display will be accomplished in the minimum of time. See Figure 5.
Figure 5.
Decimal Z80 Source Comment
Code Statement
Step 1: Initialize the subroutine with the address held in "D-FILE"
42 LD HL,(nn) ;put display address
12 n=12 ;held at 16396 (D-FILE)
64 =16396 n=64 ;into HL register-pair
35 INC HL ;point to next screen address
Step 2: Loop eight times for a column of "118's"
6 LD B,n ;put the following number
8 n=8 ;into the b register/counter
62 LD A,n ;put the following number
117 n=117 ;into the A register
60 INC A ;add 1 for "118"
119 LD(HL),A ;put number in A into the
;address in HL
35 INC HL ;point to next address
16 DJNZ e ;subtract 1 from B and if not
249 (e=255-249) ;zero, jump back 6 values (to 62)
This roundabout way of loading “118” into a screen address is necessary because “118” in Z80 means “HALT” processing, while in ZX80, it means “end of line.” Either way, you cannot use it in a 1 REM subroutine.
Step 3: Loop six times for 6 rows of 32 spaces (blank play field).
6 LD B,n ;B is row counter
6 n=6
197 PUSH BC ;put the number in B into the
6 LD B,n ;"save" stack
32 n=32 ;B is now free to count spaces
54 LD(HL),n ;put chr code into screen address
0 n=0 ;chr code is for a "space"
35 INC HL ;point to next screen address
16 DJNZ e ;decrement B and Jump Non-Zero
251 e=4 ;minus 4 values (to 54)
62
117
60 (same as above) ;same as above but for 1-"118"
119
35
193 POP BC ;put number saved on the stack
16 DJNZ 3 ;into the B register, subtract 1
240 e=15 ;and jump back if not 0 (to 197)
Step 4: PRINT 1 row of sea surface, CHR$(11)
6 LD B,n ;load B with 32
32 n=32
54 LD(HL),n ;load screen address with chr "n"
11 n=11
35 INC HL ;point to next address
16 DJNZ e ;subtract, test, and jump not-0
251 e=4 ;backwards 4 values (to 54)
62
117
60 (same as above) ;for end of line "118"
119
35 ;point to next address available
;after MCD
Step 5: Reset system variable addresses and exit subroutine.
34 LD (nn),HL ;load the last address in HL
14 =16398 n=14 ;into both "DF-EA"
64 (DF-EA) n=64
34 LD (nn),HL ;and "DF-END"
16 =16400 n=16
64 (DF-END) n=64
62 LD A, n ;load A with the row number
8 n=8 ;after MCD (23-15=8 for F.L.)
50 LD (nn),A ;put that row number into 16421
37 n=37 ;meaning #8 is the next available
;row
64 =16421 n=64
201 RET ;return to Basic program
Entering and Testing an MCD
Count the number of values in the subroutine (55 for Flattop Lander) and enter that many “boxes” into line 1:
1 REM □□□ etc. :□ = shifted A
You can use any character, or even 1, 2, 3, etc. The idea is to reserve some non-changeable addresses so they can hold MC values. The first box’s address is 16427. (16424=21, 16425=0 16426=254 or “REM”.)
Line 2 in Flattop Lander holds 8 boxes in REM for storing carrier characters. Otherwise, use 2 REM B as a buffer against accidently moving the cursor to line 1: that’s a big “no-no” after you enter the MC values!
Okay, you have 1 REM with a line of boxes and 2 REM with either more boxes for character storage or “B” for buffer. The next step is to scroll line 1 off-screen. “How?” you may ask. “I only have the 4K chip.”
You do not need the 8K ROM chip to scroll one of only two lines off screen, and you do not have to enter a lot of “dummy PRINTs” as bulk, either.
Here is the trick—with the cursor below line 1, enter this command on the edit line:
POKE 16403,2
and ZAP!, line 2 is now at the top and line 1 is off-screen. (Look on page 122 of your ZX80 manual for the reason it works. Hint: 16404 always contains 0 when the line number is less than 256.)
Now enter the input routine to POKE the 1 REM boxes with MC values. See Figure 3.
If you write down your MC values in a 4-column table (read left to right) and then “INPUT” from it, one 4-value row at a time, it is easy to spot entry errors.
GOTO 100 and enter the MC values, then SAVE on tape in case of entry or coding errors. Lastly, on the edit line:
LET Q=USR(16427)
and BINGO! your initial display springs instantly to life from a lot of no-longer-mysterious numbers.
Well, maybe it doesn’t…in which case, unplug your “crashed” ZX80, plug it back in to reset the ROM from hardware, LOAD the partial program, and edit out lines 110 and 120. GOTO 100 for a complete printout of the MC code table and look for entry error. If none, recheck the decimal values of your subroutine. (My usual mistake is to miscalculate the offset values for DJNZ and other “Jump Relatives.”)
Now that you have an instant MCD, you have to POKE some characters into it. If you use 2 REM for character storage, you can use the same input routine by changing line 100. Add 5 to the address of the last box in 1 REM for the address of the first box in 2 REM. Flattop Lander has eight characters in 2 REM, so line 100 is FOR X=16486 TO 16493.
Finishing an MCD with POKEd Characters
For reasons of scale and lack of RAM, only one character is used for the aircraft in Flattop Lander: 27, or a period. 20, or a “-“, looked better airborne, but not landed. The more characters you have moving around the screen, the more complicated and lengthy your Basic POKE-routine will be.
How the game’s display is tied together is shown in Figure 4.
Before and after the above statements are game routines for entering values from the input matrix and changing the value of “C”; one line to assign a random value to “L” as “wind current”; lines to calculate Height, Distance and which way to turn to stay on the approach Line; a Score, Crash, or new-approach input routine; and an end-game/exit routine, all in Basic. That sounds like a lot of processing between displays, but “flicker” time remains under half a second! See the advantage of an MCD, now?
For your own games, you can invent or modify displays and rules to suit yourself. In this way you can see one of the best reasons for buying a microcomputer rather than a “game machine.” With a computer, you are not restricted by someone else’s viewpoint of what is FUN.
In Part 2, we will see how to develop “game” routines in Basic that will make your program do what you want it to do.
Figure 3.
100 FOR X=16427 TO (16427+(XX-1)) ;XX=the number of MC values
110 INPUT Y ;FLATTOP LANDER = "TO 16481"
120 POKE X,Y ;this loads the box w/value
130 PRINT PEEK (X), ;for a 4-column "running" display
140 NEXT X ;of POKED address-values
Figure 4.
40 LET C=9 ;9 added to "P" = 1st field addr.
90 LET Q=USR(16427) ;call subroutine in 1 REM
100 LET P=PEEK(16396)+PEEK ;"P" = 0th address of screen
(16397)*256 display
110 POKE P+163,132 ;132 is "bridge" chr of carrier
120 LET Y=16486 ;Y = first address in 2 REM
130 FOR X=P+193 TO P+200 ;start carrier at 193rd space
140 POKE X,PEEK(Y) ;"print" chr held in 2 REM
150 LET Y=Y+1 ;point to next chr address
160 NEXT X
170 POKE P+C,27 ;aircraft position and chr
180 PRINT "HT","DIST","LINE" ;1st of 3 Basic print lines
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.