ZX-Galaxians is a Space Invaders-style shoot-em-up in which the player defends Earth against a formation of alien Galaxians that break ranks and dive toward the player’s cannon. The program is almost entirely machine code: the BASIC section consists of just three executable lines — a SAVE command, a STOP, and a RAND USR call that jumps to machine code loaded at address 18508. The lengthy REM statement at line 0 serves as the machine code store, containing the game logic, graphics data, sprite routines, score display, high-score entry, and all game text packed into its bytes. Controls are defined in the REM data as LEFT (key 5), RIGHT (key 8), and FIRE (key 0), consistent with a one-handed layout common in ZX81 games of this type.
Program Analysis
Program Structure
The program has an unusually compact BASIC section: only four lines exist as true executable statements.
Line 0— AREMstatement that spans the entire program listing. This is not documentary text; it is the machine code binary for the game, stored as raw bytes in the REM body. The human-readable fragments visible in the listing (score display template, instructions, control keys, game narrative) are either string data embedded in the machine code or coincidentally printable byte sequences within it.Line 10—SAVE "ZXGAL"saves the program to tape.Line 15—STOPhalts execution so that a plainRUNorGO TO 10does not accidentally execute the game entry point.Line 20—RAND USR 18508is the sole game launcher. It transfers control to address 18508, which falls inside the REM statement’s byte payload, where the machine code entry point resides.
Machine Code Storage in REM
Storing machine code in a REM statement is the standard technique for self-contained ZX81/TS1000 machine code games distributed as BASIC files. The interpreter skips REM bodies entirely, so arbitrary binary data can be embedded without interfering with BASIC parsing. The address 18508 (decimal) corresponds to a position within the system RAM where the REM content is mapped; the exact offset depends on the program’s load address and the length of the tokenized line 0 header, but on a standard 16 KB machine this places execution squarely inside the REM payload.
Embedded Data Visible in the REM Body
Several regions of the REM content decode as human-readable strings, indicating they are in-game text or data tables rather than code:
- Score and high-score display template:
SCORE:<0000>andHIGH SCORE:<0000> - Control key assignments:
LEFT: 5,RIGHT: 8,FIRE: 0 - Attribution and copyright notice for the title and publisher
- Story/mission briefing paragraph presented before gameplay
- High-score name entry prompt (
MAX 6 LETTERS) - Block-graphic sequences that represent sprite or title-screen data using the ZX81 character set
Control Scheme
The embedded text specifies a three-key control layout: key 5 for left, key 8 for right, and key 0 for fire. On the standard membrane keyboard, 5 and 8 sit on the bottom numeric row, allowing one-handed play with the right hand, while 0 is conveniently placed at the right end of the same row for the thumb or a second finger.
BASIC Entry Point
The use of RAND USR 18508 rather than PRINT USR 18508 or a POKE/CALL equivalent is a common ZX81 idiom. RAND USR discards the return value silently, whereas PRINT USR would attempt to display the integer result on screen after the machine code returns. This keeps the display clean and avoids a spurious number appearing if the routine ever exits back to BASIC.
Notable Techniques
- Self-contained binary distribution: The entire game — engine, sprites, text, sound logic — ships as one BASIC file with no separate binary block, simplifying tape loading to a single
LOAD ""followed byRUNorGO TO 20. - STOP guard at line 15: Placing
STOPbetween the SAVE line and the USR launcher prevents accidental execution of the machine code during a sequentialRUNfrom line 10, though in practiceSAVEat line 10 would pause execution anyway; the STOP provides an explicit safety barrier. - Graphic characters as sprite data: The block-graphic runs near the start of the REM body, visible as dense sequences of quadrant-block characters, correspond to sprite shape data for the alien and player cannon graphics encoded using the ZX81’s 2×2 block character set.
Anomalies and Observations
Because the REM body is machine code, the BASIC tokenizer’s escaping rules do not apply to its contents, and many byte sequences that coincidentally match BASIC keyword tokens appear in the disassembly as BASIC keywords — this is an artifact of the listing tool rendering the raw bytes through the keyword token table, not actual BASIC syntax. All keyword-like tokens visible in line 0 should be interpreted as raw machine code bytes.
There are no other BASIC lines; the program deliberately avoids any BASIC overhead beyond the minimum needed to store and invoke the machine code, which is consistent with the tight memory constraints of a 16 KB machine running a full arcade-style game.
Content
Image Gallery
Source Code
0 REM ▀▘▝▖ B-- ▐##4▀EE4:SCORE:<0000>------ HIGH SCORE:<0000> BY ??????------LEFT: 5 RIGHT: 8 FIRE: 0 ------▗▚▗▚▗▚▗▚▗▚▗▚▝▝▝▝▝▝▀▜▝▖▞ ▞▀▖▞▀▖▌ ▗▀▚▝▖▞▝▛▗▀▚▐▖▐▗▀▘▗▘ ▞▖▀▘▌▗▖▙▄▌▌ ▐▄▟ ▞▖ ▌▐▄▟▐▜▟ ▀▖▙▄▐ ▐ ▚▄▘▌ ▌▙▄▐ ▐▐ ▐▗▙▐ ▐▐ ▜▝▄▘.....AUTHOR-WILLIAM J. WRAY.....*COPYRIGHT ARTIC COMPUTING 1982*A HOSTILE GROUP OF GALAXIANSHAS BEEN SPOTTED IN A BATTLEFORMATION CLOSE TO THE EARTH YOUR MISSION IS TO PREVENTAN ATTACK BY ZAPPING THEM ASTHEY BREAK OUT OF FORMATION AND HURTLE TOWARDS THE EARTH ▛▘▛▌▛▌▛▖ ▌ ▌▌▛▘▙▘▙▌▙▌▙▌▙▘ ▙▖▙▌▙▖▌▌PRESS ANY KEY TO START THE GAMEYOU HAVE ATTAINED THE HIGH SCOREPLEASE ENTER YOUR NAME THEN N/L:(MAX 6 LETTERS) GOSUB #▙RND GOSUB #▜RND#X▙ RETURN 4▖:▝/▞ RETURN▛4▝: 14▌2▖#/▝-▘5▙RND#7#7#7#7 FOR E£RND▘# \,,#\,, FOR :▖▞▒VAL ACS #C+<<ACS ▞AT ( POKE $COS VAL FOR ▘M \,, FOR 77AT / SLOW FOR FASTLN AND #C▝Q F GOSUB #▄RND▞ \,,LN AND #CTQV GOSUB #CHR$ ▟KL FASTSTR$ GOSUB # GOSUB #[-]RNDCHR$ █▄[B] GOSUB #[:]RND[<]K0Y# NEW▀2▙C:2▟ RETURN▘C▒2▜ RETURN▝C▝2▛#SGN STR$ FOR ACS RETURNSGN LPRINT LPRINT FOR /[/]# RETURN▛COS RETURN▟COS RETURN▙COS RETURN▜COS TAN E£RND▞/7# RETURN C: RETURN▛C▒ RETURN▜4▞Q▟/▝Q▙( REM )5 ▞/# RETURN C: RETURN▜C▒ RETURN▟4▞Q▙/▝Q▛;( REM E£RND7▞/# RETURN C: RETURN▛C▒ RETURN▙4▞Q▟/▝Q▜;( REM TAN E£RND▘ SAVE ▝\,,2/# RETURN CINKEY$ RETURN*4▝Q RETURN+4▝Q* RETURN.4▝Q+ RETURN▟C▖ RETURN▙4BQ FAST5▗RND:▖▞▒#F[I]ACS #C\,,ACS [A]ACS ▞( UNPLOT LPRINT /$ACS ▛ACS ▞( GOSUB 777$4 LLIST LPRINT 714[Q]TAN )4 Y▜LN [N]#TAN )4 Y▙LN USR #TAN )6 Y▛LN [N]#TAN )6 Y▟LN USR #TAN E£RND▘PI▘ GOSUB [L] STEP FAST PRINT FQ [B] GOSUB #LN AND #C▌ LET # LPRINT / FOR ;# LET LPRINT / FASTE£RND▘ LOAD ▝\,,▀ GOSUB [T] STEP FAST PRINT 7Q ;LN AND #CL GOSUB #CHR$ [4]KASTR$ FAST GOSUB #CHR$ [4]K0 GOSUB #£RND[B] GOSUB #)6▘[B] GOSUB #S$ LPRINT FAST)5 ;LN AND #C▝Q. LPRINT SGN LET # LPRINT /AT [B] GOSUB ## LET LPRINT /[T]E£RND▘ INPUT ▝\,,▘[A]▘Y. GOSUB [T] STEP FAST7Q )5 ;LN AND #C▝Q. LPRINT / DIM 5[?]RND#7#F[J]▞ SCROLL: RETURN GOSUB ##ACS #4▖X4▘WACS #4▞W RETURNH4▘X#E£RND▘[+]▝\,,ACS J▞ #\,, FASTE[?]RND#ACS #C▛[H]ACS #CE/,[H]ACS #C(/ LPRINT LN NOT #)# [J] GOSUB #LN RETURN#TAN LPRINT LN NOT #TAN LPRINT LN [K]#)INKEY$ [J] GOSUB #LN RETURN#TAN LPRINT LN [K]#TAN )4 LN <#Q▗7LN <#Q▚;LN <#Q▗7LN <#Q▚;LN <#Q▝7LN <#Q▝TAN )4 LN <#Q▞7LN <#Q▖;LN <#Q▞7LN <#Q▖;LN <#Q▘7LN <#Q▘TAN )5 LN <#Q ;LN <#Q ;LN <#Q TAN LN AND #C▌ RETURN.C▘TAN LPRINT E[?]RNDACS H▞ #E£RND\,,▘[+]▝\,, FAST:=F▞▀#X RETURN#C▝Q 7Q 7Q 7# RETURN[▒]C▝Q )2 ;( SLOW$C4A\,,LN CHR$ #5[?]RNDACS # LPRINT FASTC▌LN [K]#/▀LN NOT #A▞LN CHR$ # LPRINT FAST#L#5[?]RND)5 Y▗ACS #C▀.Y▖ LPRINT [B] GOSUB ##)4 ;#77#;#;#77#;F#77#A COPYLN CHR$ #5▗RND▞▖#F#777( SAVE 5[*]RNDP4▌ LPRINT LPRINT #[A]##5:INKEY$ #▞ \,,\,,▘▌ [J]#7#\,,#7#\,,#7# LPRINT LPRINT # COPY#I COPYH4 CLEAR94 SAVE TAN E[=]RND# RETURN C<# RETURN*4▝Q RETURNX4▝Q* RETURN+4▝QXE[)]RND# RETURN 4L[J]▞ SCROLL: RETURN-# GOSUB #ACS PI""E[?]RND6[/]RND5[?]RND)#▝Y▐ACS #C▀<Y▌#ACS D▞ E£RND\,,;#M[<]RND/,U[<]RND##[V]4XQ ▘5 [J] GOSUB PI FAST GOSUB #£RND GOSUB PIS" LPRINT # RETURN 4A#6[)]RNDTAN LPRINT ▘5 \,, FASTE[=]RNDLN AND #C▞ RETURNVC▝Q LPRINT 6[=]RNDQ+5 6[)]RNDTAN # RETURN.C TO LN AND #4CLN ##5[$]RND:▖▞▒#F[I]7ACS #C\~~ACS NEWACS ▞( UNPLOT ▞▝/#ACS ▛ACS ▞( GOTO FF$4 LPRINT TAN RETURNV4###LN ##E£RND▘E▘\,,▞▖ FAST[J] GOSUB #S" LPRINT VAL ▘PI GOSUB PIAT ( LIST TAN LPRINT U[/]RNDWACS J5▐RND[-]WW5▄RND[-]ACS J5▜RND77( UNPLOT #ACS ▞7ACS ▞F( SAVE ACS LEN 7ACS LEN F#ACS :7ACS :F( SAVE ▞▘E£RND)# ;:▀[J]#█ RETURNAS"CHR$ \~~#▞▘F$4 LIST /▘#E£RND)# ;)[7]RND▘▀ GOSUB [K]5[,]RND#X4▖ LPRINT # GOTO ##TAN E£RND▘[9] \,,##▘5 \,,▘#▝ GOSUB [K]TAN GOSUB #£RND54INKEY$ Y▌▘4 < GOSUB [K]X4 RUN FOR E£RND▘ OR ▝\,, FOR Y▒STR$ ▘0 GOSUB [K] FASTA\~~LN CHR$ #LN T#A\~~LN CHR$ #LN T# LPRINT SGN X4 SLOW FASTA COPYLN CHR$ # LPRINT FOR E£RND▘[0]▝\,, FOR ▘) GOSUB [K] FOR ▘( \,, FOR ▘) GOSUB [K] FOR ▘E \,, FOR ▘3 GOSUB [K]LN ## 5[7]RND▞▖Y0#7( UNPLOT 5[:]RNDQA5[*]RNDQ▀5:INKEY$ ▞▞Q▗77( IF 5?INKEY$ ▞▞Q▚77( IF ▞▞FQ▝7( CLS5▚RND▞▒Q 7( CLS5[,]RNDQ45[:]RNDO5[?]RNDQ-7Q-5▙RNDQ▘7Q▘7Q▝7Q▀5[)]RND▞▌Q ( UNPLOT LN [C]#E£RND); ;:/▞▒Q[▒]7( CLS;$4 PRINT E£RND)V ; FOR 5[0]RNDY-▘▞ GOSUB [K] FOR ▘. \,, FOR X4 PAUSE LN K#LN ##ACOS LN CHR$ #A\~~LN CHR$ #LN K#LN TO #LN ##LN CONT #LN [?]#LN 7#LN TO #LN CONT #LN [/]#A\~~LN CHR$ #LN ##LN CONT #LN [5]#LN 7#LN TO #LN CONT #LN [E]#LN ##LN TO #LN V#UORNDM[T]#/[P]E£RND▘[I]▝\,,)4 ▞▀Q 7Q ;( SAVE E£RND▘CHR$ ▘\,,QG7QA7QM7QE777QO7QV7QE7QRA COPYLN CHR$ #A COPYLN CHR$ #LN [C]#▞▀5[7]RND)[V]RND,[-]C▌ PAUSE ##S▛7<( NEXT ###5[7]RND)[V]RND▘▀ GOSUB [K]E£RND▘#▘\,, FOR 5 LPRINT PI▘4 GOSUB [K] FOR ▘6 \,, FOR ▘4 GOSUB [K] FOR ▘E \,, FOR ▘? GOSUB [K]E£RND▘8▝\,,Q>▘▛ [J] GOSUB PIQ<▞▛7LN ##W RETURN#4>E£RND▘2▝\,,)LEN RND▘▞ GOSUB [K]### RETURN#C\~~X#(<>Q>F▖/NOT # RETURN▛C▝▖FQ F/ACS FASTSTR$ VAL ▘ █UQ RETURN▜4\,,LN M? CLEARQP COPY/▀LN P? GOSUB #9RNDLN [X]▛#AT SGN LPRINT ACS #COS RETURN#COS RETURN#COS ###E£RND:/▞47Q ( CLS7$4 PRINT TAN
10 SAVE "ZXGA[L]"
15 STOP
20 RAND USR 18508
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.