ZX Scramble is a side-scrolling shoot-em-up game in which the player pilots a spacecraft through enemy territory, shooting missiles and avoiding obstacles across multiple defense zones. The BASIC wrapper manages score display, high score tracking, joystick or keyboard input selection, and speed selection (1–10), then launches the game engine via RAND USR 18628, which transfers control entirely to a machine code routine embedded in the REM statement at line 5. Score and high score data are read back from fixed memory addresses using PEEK (16396/16397 for the score pointer, 18475–18479 for the high score, 18280–18293 for a zone message), and the high score is updated in-place via POKE 16436/16437. The program uses DIM to allocate string arrays A$, B$, and C$ for score and message storage retrieved directly from machine code memory regions.
Program Analysis
Program Structure
The program is divided into a BASIC shell (lines 10–260) and a large machine code payload stored in the REM statement at line 5. The BASIC portion handles the title screen, input method selection, speed selection, score retrieval, high score comparison, and game restart. All actual gameplay is delegated to the machine code routine invoked at line 60.
- Lines 10–42: Title/input selection screen. Displays “ZX SCRAMBLE” in a diagonal pattern using a
FORloop, prompts for keyboard (“K”) or joystick (“J”), and waits for any keypress before branching. - Line 50–51:
SAVEblock (bypassed during normal play; used for tape saving). - Line 60:
RAND USR 18628— launches the machine code game engine. - Lines 70–96: Post-game setup: displays speed selection prompt, handles speed input via
USR 18767, and configures speed POKEs. - Lines 100–210: Score and high score retrieval from machine code memory via
PEEK. - Lines 215–260: Score display, high score comparison and update, new game loop.
Machine Code Integration
The machine code for the game is stored in the REM statement at line 5, which is standard practice for embedding executable Z80 code in a BASIC program. RAND USR 18628 at line 60 jumps directly into this routine, bypassing BASIC entirely for gameplay. A second machine code call, USR 18767, at line 90 handles the speed/input reading, returning a negative value or responding to the space key as a signal to NEW (reset).
Memory Map and PEEK/POKE Usage
The program accesses specific fixed addresses to exchange data between the machine code and BASIC:
| Address(es) | Purpose |
|---|---|
| 16396, 16397 | Pointer to the current score string (low/high byte); used to compute X for reading A$ |
| 16436, 16437 | Speed control POKEs; also used to conditionally store high score |
| 18475–18479 | High score digits (5 characters, with B$(6) hardcoded to “0”) |
| 18280–18293 | Zone/message string (14 characters, e.g., “DEFENCE ZONE A PASSED”) |
| 18628 | Entry point for main game machine code |
| 18767 | Entry point for speed selection machine code |
Score and High Score Handling
The current score is located dynamically: PEEK 16396 + 256*PEEK 16397 + 741 computes the address of the score string in memory, which is then read character by character into A$(6). The high score B$(6) is read from a fixed address (18475–18479), with the sixth character forced to "0". If the current score equals the high score (A$=B$), a congratulatory message is displayed and the high score region is updated via POKEs to addresses 16437 and 16436.
Key BASIC Idioms
- Diagonal title display:
FOR N=10 TO 20 STEP 2 / PRINT AT N, 2*N-20;"ZX SCRAMBLE"produces a diagonal arrangement across the screen. - Keypress wait:
IF INKEY$="" THEN GOTO 41— busy-loops until any key is pressed. - New game / reset:
IF USR 18767<0 OR INKEY$=" " THEN NEW— pressing space or a machine code signal resets the system. - High score update gate: Lines 252–253 use
POKE 16436,30andPOKE 16437,0in sequence; the program then polls for CHR$ 118 (Enter/Newline) before proceeding. - CHR$ 118 detection: Line 255 uses
IF INKEY$<>CHR$ 118 THEN GOTO 253to wait for the Enter key (character code 118 = newline on this platform) before restarting.
Notable Techniques
The POKE 16437,255 at line 81 sets the high byte of the display file pointer or a system flag to 255 before entering speed selection, and is restored to 0 or 1 after the game ends. This is a machine code coordination technique, using system variables as communication registers between BASIC and the Z80 routine.
The speed selection loop (lines 80–96) allows a range of 1 (fast) to 10 (slow, mapped to key “0”), directly controlling game difficulty through the machine code, with the POKE pair at 16436/16437 encoding the chosen speed.
Anomalies and Notes
- Line 42 (
GOTO 60) immediately follows the keypress wait, skipping line 50–51 (theSAVEblock). This is intentional: the save block is only reachable by directGOTO 50, not during normal execution. B$(6)is always set to"0"(line 180) regardless of what is stored in memory, suggesting the high score is stored as a 5-digit value and the sixth character is a terminator or padding enforced by the BASIC shell.- Line 257 POKEs 16437 twice in succession (first to 1, then to 255), which appears to be a deliberate two-step signal to the machine code to indicate game restart mode.
Content
Image Gallery
Source Code
5 REM Y RUN <= RETURNACS #C;ACS #""E#RND▞▖Q 7( CLSFFFF▘5 \,,6#RNDTAN E#RND▞▖Q 7( CLSFFFF▘ TO COPY\,, GOSUB #£RND[B] GOSUB #K▀[B] GOSUB PI;6#RNDTAN E#RND# RETURN▚C? RETURN C" RETURN▝C▛ RETURN█C▀#USR INKEY$ Q▝7# RETURN█C? RETURN C" RETURN▚C▛ RETURN▄C▀#USR INKEY$ Q▚7# RETURN▄C" RETURN C▛ RETURN█C▀#USR INKEY$ Q█7# RETURN C▛ RETURN▄C▀#USR INKEY$ Q▄TAN Y-E£RND7 FASTSGN 7▘3 GOSUB [K]FQ XCOS 777<</ LOAD Y LOAD <= RETURNACS #C:E#RNDFY#[Y]C.6#RND/-E#RNDY#Q 7Q 777[Y]C▞FFF6#RND#0INKEY$ RNDTAN [Y]COS FFF6#RNDTAN [Y]""5#RNDPTAN 5#UORNDM█INKEY$ U>=▞ NEW? RETURN▞S. RETURN\~~SIE#INKEY$ ▘#▘[B] GOSUB PIY#[Y]4▀▘C▘\,,6#INKEY$ /*E#INKEY$ ▘# \,,Y#[Y]4▀▘# [B] GOSUB PI6#INKEY$ / E#INKEY$ ▘4 Y#Q▒7[Y]""\,,/ SAVE TAN TAN Q ▝W▘ REM E#RNDQ>7Q*7Q*7Q<# PRINT #TAN E£RND▘[P]▝\,,Y. GOSUB [T]"" FASTVAL 7Q 7# RETURN 4▞Q.AT LPRINT / REM RETURN#4▝/ PLOT RETURN▒C PAUSE RETURN▐4\,,Q*▞▘LN MPI/ FAST RETURNA4" FAST▞▀LN MPI LPRINT Q*/CHR$ Q./ABS VAL ) DIM ▝LN INKEY$ PIAT ) NEXT ▝LN INKEY$ PITAN E£RND;# RETURN9C\,,OVAL LN CLEAR#AT ( LOAD TAN Q0F/ GOSUB ▘. \,,6#INKEY$ ▘#▘\,,▞47Q▒( CLS▘( \,,▞▞Q07( CLSTAN 4U#PIXC▖M#PITAN ▞▘LN MPIY4M#PITAN UORNDM[<]PIU>=▛ NEW? RETURN?**E#INKEY$ ▘5 [B] GOSUB PIQ▐TAN E£RND▘5 Y▐ GOSUB [L]4▞FQ 7/ PLOT E£RND▘[R]▝VAL AT )5 Y▐ GOSUB [L]""VAL Y▒;F[Y]4▞[B] GOSUB #7/ DIM [B] GOSUB #Q GOSUB ## RETURN 4▞Q▐;7/NOT RETURN.C- RETURNAC£ RETURN▐C▒ RETURN*C▖AT #USR INKEY$ ;Q▐7/[X]Q STR$ FAST▞▙LN MPI LPRINT SGN /STR$ ▀#▘ REM E#RNDUORNDM2#U<=▛ NEW?W#7( CLEARY#[Y]4▘F▘5 Y▒\,,[Y]4 UNPLOT [B] GOSUB PIY▐[Y]""Q [B] GOSUB PIY [Y]C▘\,,Q▐TAN ############[I]U##WM## RETURN▀**Y LOAD <= RETURNACS #""E#RND▘▖ \,,Y [Y]""Q.7[Y]""Q.M##TAN 7[Y]""Q.M##TAN LN PI#LN #[J]M█YLN ▀#$COS LN ▄RNDY*LN ##LN QINKEY$ LN TAN RND$COS LN LOAD #LN ##LN #INKEY$ LN ##LN [£]PILN USR #LN [A]PI$COS LN =#LN ##LN ##1ATN [1]#:▘▞ ( RETURN$4 RAND /[S]ASN ▛ NEW? RETURN?**UORND NEW?E£RND)5 F#Y ;( CLEAR[Y]4▀QATAN Y▄[Y]""/ RUN INKEY$ LN INT #LN [A]PI$E£RND▘[P]▝YA GOSUB [L]"" FASTVAL FQ F# RETURN 4▞QAAT LPRINT / REM RETURN▄4▌ LPRINT AT #USR INKEY$ RETURN.4\,,Q ▞▀LN MPI/ NEW RETURN#C LLIST RETURN▒4▞▘ TO COPY\,,/SGN 7QA/PEEK E£RND▘CHR$ ▝ GOSUB [L]""FQ 7/ RUN 11111111111111111111111111111 ▖#▘ REM ,?2 U##XC▖M##TAN Y4M##▞▘LN MPIU##XC▖M##TAN 2▘TAN ▘ LIST ▝\,,▞▖Q07( CLS5##YP[Y]""QATAN +CM RETURN 4▀7/ PRINT RETURN▒4▖AT LPRINT / STEP RETURN#C SAVE RETURN▐4\,,Q*▞▘LN MPI/ FOR RETURNA4\,,Q*▞▀LN MPI/ THENQ 7/ASN FQ./USR ▘U INPUT #XCOS Y LOAD <= RETURNACS #"" LN STEP #E£RND▘(▀\,,▞▌Q 7( CLSY▘M INPUT #Y[A]-▀LN 8#Y▌-▘LN 8#LN STEP #TAN E£RND▘[Q]▝ GOSUB [L]"" FASTVAL PRINT PIFQ[*]LN MPI LET AT LPRINT / INPUT LET AT LPRINT / INPUT TAN E£RND▘# \,,6#RND▘B▘\,,6#INKEY$ ▘#▘\,,▞4Q▒7( CLS7Q▒▘: \,,▞▞Q07( CLS▘$ \,,Q▒▞▀77Q▝7Q▚7Q█7Q▄( LET #▒# INPUT #XCODE CLS#Y M INPUT #Y▐LN ##YALN ##5##PE£RND76#RND▘?▀\,,QS7QM7QA7QR7QT▞2Y▄F[Y]C▌( IF :▘TAN ▞▖Q F( CLSY>LN ##Y<LN ### PRINT #Y# ▌;▝ REM E£RND:-▞█-47#█#+4 RAND 7$4 NEXT TAN LN [U]INKEY$ U INPUT #XC\~~LN UNPLOT #Y.LN ##/\,,▞2VAL LN NEWINKEY$ AT ( RAND Y*LN ##Y>LN ##Y<LN ##E£RND▘"▀\,,▞=Y▄F[Y]C▌( IF :▘TAN : ▞ ( RETURN$4 RAND ▞▖Q F( CLSY>LN ##Y<LN ##E£RND76#RND▘?▀\,,QS7QM7QA7QR7QTY▐LN ##YALN ##Y"M INPUT #:#TAN #:#TAN ??:?::$:$$$£"?£££"£\~~"\~~\~~\~~\,,▛▛▌ ##▞4VAL [J]M█YLN ▀#$C#LN ▄RNDY*LN ##LN QINKEY$ LN TAN RND$CPILN LOAD #LN ##LN #INKEY$ LN ##LN [A]PI$CKLN =#LN ##:▘▞ ( RETURN$4 RAND AT (""E£RND▘# \,,)## FOR STR$ ▘+ GOSUB [K]5##O#LEN <>#LN MPI// LPRINT LPRINT TAN Y\~~M5RNDE£RND7 FASTYAM##5##6[.]#E[.]##M[/]PI7#M STEP #7▘[.]#[B] GOSUB PIS▌5##/▘\,,6[.]#Y.LN ##Y▀: ▞ ( RETURN$4 RAND X4 POKE LPRINT ▞-Q 7( CLSE#RND▞▖Q 7( CLSE£RND76#RNDY)M##LN [3]#TAN DEFENCE ZONE A PASSEDE£RND▘[P]▝\,,Y. GOSUB [T]"" FASTVAL 7Q 7-▀#+CZ RETURN 4▀7/ PRINT RETURN▒4▖AT LPRINT / STEP RETURN#C SAVE RETURN▐4-Q*▘5 \,,# RETURN▒4▖▞▘/▝▞▝LN MPI/ THEN RETURNA4\,,Q*▞▀LN MPI/SGN Q 7/[X]FQ./SIN OOOOOOOOOOOOOOOOOOOOOOOOOOOOOO ▛▒▘ REM U5RNDXCOS E£RND▘ SCROLL▝\,,Y4[Y]SQR ▘5 \,,▘) Y▄ GOSUB [T]777Q▝7Q▚7Q█7#Y▘M5RNDTAN 00006E£RND▘ OR ▝\,,)F# FOR ▘▌ STR$ FAST GOSUB [K] FOR Q0LN [▒]#SGN LPRINT ▘£ \,,▞▌,[Y]S▞""7<( RUN TAN 7<( UNPLOT .F▘▌ GOSUB [S]TAN 5█Y#Q▘ NEW# RETURNH AND [A]RND RETURN#ABS [(]RNDTAN U█Y NEW# RETURN#ABS #INKEY$ #YINKEY$ 5▄RNDQ#7Q#7Q#5QINKEY$ Q#7Q#7Q#)##5[P]#▘▛ GOSUB [K]) POKE #5[W]#▘▒ GOSUB [K]TAN \,,#U█Y[B] LIST U█Y[B] LIST RETURN[C]SQR Y[Z]<= RETURNACS #ASN ▚#ACS #COS / LIST UORNDM<=#U>=▛ NEW? RETURN?**UORND NEW?E£RND)5 F#Y ;( CLEAR[Y]4▀QATAN Y▄[Y]""/ RUN ▝ REM ▒PI REM :▝Y RUN <= RETURN5+#▞▌ACS #C)-▒O+4 UNPLOT ( POKE Q#$C SLOWY LOAD / SLOWQ#$C▖Y▞/▌Y▌█/▘[(]MATN #MUSR #LN E\~~#K#QQQQQ
2 MICRO-GEN ZX SCRAMBLE
10 PRINT AT 5,2;"PRESS ""K"" TO USE THE KEYBOARD";AT 3,3;"PRESS ""J"" TO USE JOY STICKS"
20 FOR N=10 TO 20 STEP 2
30 PRINT AT N,2*N-20;"ZX SCRAMBLE"
40 NEXT N
41 IF INKEY$ ="" THEN GOTO 41
42 GOTO 60
50 SAVE "SCRAMBL[E]"
51 GOTO 10
60 RAND USR 18628
70 CLS
80 PRINT AT 13,10;"GOOD LUCK";AT 7,3;"1=FAST 10(KEY 0)=SLOW";AT 5,5;"ENTER SPEED 1 TO 10"
81 POKE 16437,255
90 IF USR 18767<0 OR INKEY$ =" " THEN NEW
95 POKE 16436,200
96 POKE 16437,0
100 LET X=PEEK 16396+256*PEEK 16397+741
110 DIM A$(6)
120 FOR N=X TO X+5
130 LET A$(N-X+1)=CHR$ PEEK N
140 NEXT N
145 DIM B$(6)
150 FOR N=18475 TO 18479
160 LET B$(N-18474)=CHR$ PEEK N
170 NEXT N
180 LET B$(6)="0"
185 DIM C$(14)
190 FOR N=18280 TO 18293
200 LET C$(N-18279)=CHR$ PEEK N
210 NEXT N
215 CLS
220 PRINT AT 15,5;"PRESS N/L FOR NEXT GAME";AT 5,7;"YOUR SCORE ";A$;AT 11,5;C$;" REACHED"
230 IF A$=B$ THEN GOTO 250
240 PRINT AT 7,7;"HIGH SCORE ";B$
245 GOTO 255
250 PRINT AT 7,5;"WELL DONE YOU NOW HAVE";AT 8,7;"THE NEW HIGH SCORE"
252 POKE 16437,0
253 POKE 16436,30
255 IF INKEY$ <>CHR$ 118 THEN GOTO 253
256 POKE 16437,1
257 POKE 16437,255
260 GOTO 70
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.