ZX-Galaxians

Products: ZX Galaxians
Date: 1982
Type: Cassette
Platform(s): TS 1000
Tags: Arcade, Game

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.

  1. Line 0 — A REM statement 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.
  2. Line 10SAVE "ZXGAL" saves the program to tape.
  3. Line 15STOP halts execution so that a plain RUN or GO TO 10 does not accidentally execute the game entry point.
  4. Line 20RAND USR 18508 is 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> and HIGH 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 by RUN or GO TO 20.
  • STOP guard at line 15: Placing STOP between the SAVE line and the USR launcher prevents accidental execution of the machine code during a sequential RUN from line 10, though in practice SAVE at 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

Appears On

Related Products

ZX Galaxia is a good adaption to the ZX81 of the popular arcade game. You are being attacked in deep...

Related Articles

Related 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.

People

No people associated with this content.

Scroll to Top