Namtir Raiders is a space shooter game that loads and executes machine code via RAND USR 16514, with the BASIC loader storing the game data in a large string array dimensioned to 1790 bytes using DIM A$(1790). The program uses POKE 16477 to adjust system variables and checks memory configuration with PEEK 16386 and PEEK 16387 before proceeding, branching to NEW if the expected values aren’t found. The REM statement in line 1 contains the bulk of the machine code payload, encoded as tokenized BASIC—a common technique for embedding binary data in listings. A smaller DIM A$(20) and SAVE command in line 45 suggest a two-stage loading process, with the initial short array used before the full game array is allocated. The title screen data is stored in REM line 100, containing inverse-video block graphics that form a decorative splash screen including a high score display area.
Program Analysis
Program Structure
The loader is organized into a small number of BASIC lines that perform a carefully sequenced initialization before handing control to machine code:
Line 1— A REM statement containing the machine code payload, encoded as tokenized BASIC keywords and characters. This is the largest block in the program.Line 2— An empty REM, acting as a separator or padding.Line 10—POKE 16418,0resets the error register (ERR NR system variable) to clear any prior error state.Line 20—PRINT A$outputs the string array, which at this point is uninitialized; likely used to verify or display something before clearing.Line 30—CLEARreclaims memory.Line 40—DIM A$(20)allocates a small 20-byte string array, used as staging before the full allocation.Line 45—SAVE "NAMTIR RAIDERS"saves the loader to tape.Line 50—CLEARfrees memory again.Line 55— Memory check:IF PEEK 16386<>252 OR PEEK 16387<>127 THEN NEWverifies that 16K of RAM is present (RAMTOP at address &7FFC = 32764), aborting withNEWif not.Line 60—DIM A$(1790)allocates the full 1790-byte array to hold game data or machine code workspace.Line 70—POKE 16477,26sets the system variable PROG (or a related variable) to adjust the interpreter’s view of program memory.Line 80—RAND USR 16514transfers execution to machine code at address 16514, which is within the REM statement of line 1.Line 100— A large REM containing the title screen, rendered using inverse-video block graphic characters, and ending with a “HIGH SCORE -” prompt.Line 101— An empty REM terminator.
Machine Code Embedding Technique
The primary technique used here is storing the machine code inside the REM statement at line 1. Because a REM line is not executed by the BASIC interpreter, arbitrary bytes can be stored there without causing syntax errors. The address 16514 corresponds to a location inside that REM’s data area (the ZX81 program area starts at 16509, and the REM content begins 5 bytes into line 1 after the line number, length, and REM token). RAND USR 16514 jumps directly into this embedded Z80 machine code.
Memory Configuration Check
Line 55 inspects system variables at addresses 16386–16387, which hold the RAMTOP value. The expected values 252 and 127 correspond to the high and low bytes of address 32764 (&7FFC), the standard RAMTOP for a 16K RAM machine. If this condition is not met—indicating insufficient or unexpected memory—the program executes NEW to halt safely rather than corrupting memory.
Two-Stage Array Allocation
The loader performs two distinct array allocations: a small DIM A$(20) at line 40, followed after a CLEAR by the full DIM A$(1790) at line 60. This pattern is consistent with a save-then-reload workflow: the small array is allocated before the SAVE so that the tape image includes a minimal footprint, while the large array is only needed at runtime to provide the machine code with a safe workspace or data buffer.
System Variable Manipulation
POKE 16418,0 writes to ERR NR (the error number system variable), clearing any pending error condition before the program proceeds. POKE 16477,26 targets the system variable at that address; adjusting this before the USR call likely repositions the interpreter’s internal pointer to ensure the machine code executes in the correct memory context.
Title Screen in REM
Line 100 contains an elaborate title screen encoded entirely within a REM statement using block graphic characters (▀, ▛, ▜, ▌, ▐, ▗, ▘, ▟, etc.) and inverse-video letters spelling out game title elements. Since this data is never directly printed by BASIC—the machine code handles display—the REM serves as a convenient read-only data area accessible via PEEK or direct memory read from Z80 code. The line ends with the text HIGH SCORE - , suggesting the machine code reads from this REM to construct the HUD display.
Notable Idioms and Techniques
- USR entry into REM: The canonical ZX81 technique for embedding and executing machine code without a separate loader file.
- Memory guard with NEW: Using
THEN NEWrather than a GOSUB or error message is a compact way to abort on hardware mismatch. - SAVE mid-loader: Placing
SAVEat line 45, after the initial small DIM but before the large one, produces a tape image that is self-contained and minimal. - RAND USR vs. USR: Using
RAND USRdiscards the return value silently, avoiding a “0 OK” report thatPRINT USRwould produce.
Potential Anomalies
Line 20: PRINT A$executes beforeA$is dimensioned (it is dimensioned at line 40). On a fresh run this would print an empty or zero-filled string, or trigger an error ifA$doesn’t exist—suggesting this line is vestigial or only meaningful in a reload scenario whereA$was previously set.- The
SAVEat line 45 would pause execution awaiting a tape; in normal use the operator would save here and then allow the program to continue running, which is an unusual but workable design.
Content
Image Gallery
Source Code
1 REM E(RND)▞ ;6>RND5<>#)(#Y▌LN [A]INKEY$ 5F#6##5[:]#6##E#RND6IRND[J]M6RNDLN RNDPILN ▘INKEY$ #▝#Y█E>RND:▞▞ COPY#7( UNPLOT $4 RUN TAN FASTLN PRINT ▒ LPRINT #7##LN SLOWRND#LN REM RND#LN SLOWRND#LN REM RNDY0NOT NOT TAN NEW LIST ???? NEW?LEN 0ACS [R]NOT TAN E(RNDFFFU##LEN 0ACS [R]#TAN UARNDW4 IF E9RND8C IF # RETURN RUN ""# RETURN RETURN4▖Y▘/$ RETURN UNPLOT 4▖YH/▌ RETURN SAVE ""Y#M)#TAN E£RND:*▞47Y█▚#( RAND $COS 7/ PAUSE 5###7▚B#7Y [:]B#TAN 5###P PRINT LN FINKEY$ LET RETURN C▖LN PAUSE RNDTAN ▘ LN PRINT ▒LN D#E## GOSUB ###[J] GOSUB #K▖ GOSUB ###5##LN ATN RND[J]NOT NOT NOT NOT LN ▘INKEY$ LN RNDPITAN 5█#▞\~~)\,, ACS LEN ;( CLSTAN 5 AND #▞▌)\,, ACS ▚;( CLSTAN ▘▒ #7#\,,X4 RAND TAN ▞\~~)\,, 5##;ACS #""( IF [J]TAN )\,, #;( UNPLOT TAN ▞▌)\,, 5SGN #;ACS #COS ( IF TAN ACS LEN )▛ ;#7#TAN )1#Y\~~5▟#LN [A]INKEY$ LN [Q]RNDLN [~~]INKEY$ LN [/]INKEY$ 5 6▐#I▞6[:]#I£6[*]#5 ▖6[4]#I▞6[D]#I£6[M]#5▀▝6[V]#I\,,6CODE #A▞6LN #I▀6CHR$ #Y▘M##5▌ 6##6##5Q#6\~~#TAN 5 6##▞*:\~~5##LN SIN RNDY▖M##LN PAUSE RNDLN LLIST INKEY$ I7A,6##5##ACS [:]ACS ▚Y;M(#TAN LN [Q]RNDLN [~~]INKEY$ 5▌ 6##6##5(#PPP#WM## RETURN▞>=#INKEY$ TAN )>#5▟#Y\~~LN [A]INKEY$ LN [~~]INKEY$ 5▌ 6##5[)]#6\~~#Y▝M##TAN )##5▟#Y\~~LN [A]INKEY$ 5##Q▒LN [~~]INKEY$ 5▌ 6##6▐#A▝6[:]#A▖6[*]#5?▀6[4]#A▌6[D]#A▛6[M]#5; 6[V]#A▝6CODE #A▖6LN #5SGN #ACS ▚5ABS #6\~~#Y▌M##TAN 5##6▟#5█#ACS LEN 5##Q(5\~~▖6##5 6▐#5 IF #6\~~#TAN EDRND77#7#77"" FOR LN #"TAN #▞ #▛▛▛#D##D;\,, GOSUB #>RND;TAN Y#<= RETURN3 CLEARQ#,E>RND) PRINT ; GOSUB #£RND<Y*▘4 GOSUB [K]XCOS ▘( \,,</ PAUSE GOSUB #QRNDLN U# FOR EMRND#VAL 7# CLEARACS 5#4▝Y█>7▞ # FOR \,, FOR AT ( REM TAN #3SQR FAST7#7# GOSUB #MRND7#7#777#7# GOSUB #QRND LPRINT 3S6 FOR ▘[Y]#STR$ VAL DIM CLEARACS 5▚LN ## CLEARACS 5LEN )▛ LPRINT ;#7# GOSUB #QRNDLN ##TAN ACS ▚ACS [:]3K▝ACS LEN PRINT CLEARACS 5▚LN ## LET 3SQR 3K▖LN #INKEY$ TAN LN YINKEY$ ▞*:\~~5##LN SIN RNDTAN EIRND#F#FY COPY[U]4▒E#RND6IRND/ GOTO 6IRND FOR LN [;]# CLEARP#ATN ##U)##( RETURN/NOT 5▛ ;Y RAND <= RETURN RETURN#C▞Y▌[Y]K▘PY[3]<= RETURN RETURN#C▞Y7[Y]S▘O7Y<=<= RETURN RETURN#C▞Y:[Y]K▘PY[X]<= RETURN RETURN#C▛U(#[Y]S▘OY#<= RETURN RETURN#4▌ CLEARACS 5[:]TAN CLEARACS 5#""5##ACS #""ACS LEN E##6## CLEARACS 5EXP TAN GOSUB ###LN U## RETURN["] FASTC£LN [X]#C▛ LPRINT 5##ACS EXP TAN 5##PC NEXT )K LPRINT GOSUB ## RETURN█COS LN [X]#COS / SLOWLN [L]INKEY$ COS FAST;FU##[Y]C▞ LPRINT LN [X]INKEY$ / LIST FU##[Y]C▖X[Y]4 LOAD LPRINT ACS EXP WTAN 5▌ ;#7)##,▚77##▖F.,▟##UORND3SQR 3SQR 3SQR VAL LN TAN INKEY$ AT ""UPRND NEW▘▟#LN **INKEY$ TAN 5▒ ;O# RETURN2S▖ FOR ACS EXP TAN #F#5###[T]""7#[S]C▀W[S]""5##ACS EXP / SLOW GOSUB ###5### RETURN▀4$Q COPY GOSUB ### GOSUB ### LPRINT LPRINT TAN F# RETURN;S5Q▘$VAL LN [L]INKEY$ AT 4▌LN [?]PI/ CONT ▖▖# RETURN;S▌LN #PI/>= GOSUB ###/ABS RETURN▌K▌Q £/ OR [J][Y]7#4▀▚/▘[-]O# GOSUB ###/[V]E### RETURN;S7Y▘HM## FASTLN [L]INKEY$ LPRINT 4▞LN [J]PI LPRINT LPRINT TAN 8# RETURN,S▌LN #PI/ PAUSE 6##/ GOSUB RETURN▌K▌Y G/NOT U## RETURN 4▀G/ CONT H/ FAST5##PC▀ LPRINT LPRINT TAN Q\~~LN [L]INKEY$ 4▌LN ▞#/ LET 5##OY;[Y]K CONT LN #PI5SGN #ACS ▚/ THEN5█#ACS #4£LN LLIST INKEY$ 5##OLN PAUSE RND/#5##P4?UORND# NEW? PLOT ▀##7 NEW▀#F7 GOSUB ####3K▝££$3K▝▖▖▌# RETURN8S▝ACS ▚ RETURN▌K▝ACS LEN # RETURN▝K▝ACS EXP RETURN=S▝ACS [:] GOSUB ### LPRINT LPRINT TAN \,,▘▐▘["]▘[*]▝▘▘▝▛▖▛▖ COPY▖▘ 1B#F# 7, ##[:]# 3<\,,1# STEP # ▛▖\,,1# STEP #▞ $▖\,,1# STEP #£ <▖\,,1# STEP # ▖▛▒\,,1# STEP #▞▖$▒\,,1# STEP #£▖<▒\,,1# STEP #▀▝\~~▞\,,1# STEP #\,,▝(▞\,,1# STEP #\,,▞(\~~\,,1# STEP #▀▞\~~\~~▘##(#4"\~~?▘##(#>?▖?▘##(#\~~?:<▘##(#$):?▘##(#,)▒?▘ Q# ;#▖▚▘▞J[~~]▘[~~],YO▖▛▘▜J▄▘▄ST▖ J▌▘\,,▘▐ HIGH CORE = 0:=▘=H[,,]▘O▘O▘O▘O▘[,,]F▙▘[,,]▘[*]▘[*]▘[,,]▘▟ ▞[,,]▘[,,]I▚▘▖▘▗▘▞0000 COPY COPY##█#[,,]#[>]#[.]#[8]#[H]#[Q]#[Z]#COS #SGN # AND # STOP# GOTO # PRINT # RETURN####### AND # STOP# GOTO # PRINT # RETURN#▛###000000000000
2 REM
10 POKE 16418,0
20 PRINT A$
30 CLEAR
40 DIM A$(20)
45 SAVE "NAMTIR RAIDER[S]"
50 CLEAR
55 IF PEEK 16386<>252 OR PEEK 16387<>127 THEN NEW
60 DIM A$(1790)
70 POKE 16477,26
80 RAND USR 16514
100 REM [N][A][M][T][I][R]█[R][A][I][D][E][R][S][.][A][U][T][H][O][R]█[-][J][.][R][I][T][M][A][N][.]█[(][C][)]█[1][9][8][2]█[A][R][T][I][C]█[C][O][M][P][U][T][I][N][G]█[L][T][D][.]████████████████████[*]█████████████████[P][R][E][S][S]█[O][N][E][,][T][W][O]█[O][R]█[T][H][R][E][E]████████████[T][O]█[C][H][A][N][G][E]█[S][P][E][E][D][.]██[*]████████████████████████████████████████[*]██▀▜▛█▜▛▀██████[*]██████████████████▌█▌▀▐▌▜█████████████[*]███████████▌█▌█▐▌▀████████████████████████████▛▀█▜▛█▀█████████████████████[*]███▌▜█▗▘█▐▐█████[*]███████▛▀▀▀███████▌▀█▐▌█▝▟█████████▀▀ ████████████████████▛▀ ████████[*]█████████▀ ▞▚ ████████████████▀ ▐ ▞ ██████████████▛ ▀ ██[*]██████████▛ ▗██████[*]█████▛ ▗▘████████████ ▌ ███████████▌ ▝▄███████████ ██████████▌ █████████HIGH SCORE -
101 REM
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.