Trap is a machine code game that loads and executes a routine stored in the REM statement at line 1. The program uses the common ZX81/TS1000 technique of embedding machine code bytes directly inside a REM statement, then jumping into it with LET K=USR 17606, where 17606 is the memory address of the first byte of that REM’s data area. Line 20 saves the program (including the machine code payload in the REM) to tape under the name “TRAP”. Lines 25 and 30 provide a simple stop/restart loop so the USR call can be re-entered. The title screen text visible in the REM data — “T I M E X” and “T R A P” surrounded by block graphics — suggests a branded title display is rendered by the machine code routine.
Program Analysis
Program Structure
The BASIC portion of this program is minimal — just five lines — but the real content is the large machine code payload embedded in the REM statement at line 1. The BASIC lines serve purely as a loader and tape-save utility:
- Line 1 —
REMcontaining the entire machine code payload (and apparent title-screen data). - Line 10 —
LET K=USR 17606: jumps into the machine code. - Line 20 —
SAVE "TRAP": saves the complete program, including the REM payload, to tape. - Line 25 —
STOP: halts execution after saving. - Line 30 —
GOTO 10: provides a restart path back to the USR call.
Machine Code Delivery via REM
Storing machine code inside a REM statement is a classic technique. The tokenizer ignores everything after the REM keyword, so arbitrary byte values can be placed there without interference from the BASIC interpreter. The address 17606 (decimal) corresponds to the first data byte of line 1’s REM body in the system’s memory map, assuming the program starts at the standard BASIC area base address. When USR 17606 is evaluated, the Z80 CPU executes a CALL to that address, transferring control directly to the machine code.
Title Screen Evidence in REM Data
Portions of the REM data, when interpreted as character codes, produce recognizable display strings. The sequences render as:
- A row of
▀block graphics forming a top border. - The text
T I M E Xflanked by▝and▌graphics. - A row of
█block graphics forming a separator. - The text
T R A Pflanked by▙and▌graphics. - A closing row of block graphics.
These are almost certainly printed by the machine code routine as a title/splash screen when the game starts.
Save and Restart Logic
The sequence at lines 20–30 is a deliberate distribution pattern. Running the program from line 10 launches the game. If the user instead runs from line 20, the SAVE command writes the entire program — including the machine code REM — to tape, producing a distributable copy. STOP at line 25 prevents accidental fall-through to GOTO 10 after a save. GOTO 10 at line 30 is reachable by CONTINUE or direct GOTO to re-launch the game without reloading.
Notable Techniques
- USR as game launcher: Using
LET K=USR addrrather than justRAND USR addris functionally equivalent for launching machine code but stores the return value inK, which is harmless. - Self-contained distribution: Because the machine code lives in the REM and the SAVE is part of the same program, a single tape file contains both loader and game payload.
- Address calculation: The address
17606is hard-coded, meaning the program must always reside at a fixed location in RAM. Moving the program (e.g., by adding lines before line 1) would shift the REM body and break the USR address — a known fragility of this technique.
Potential Anomalies
The hard-coded USR 17606 address is the most notable fragility. If the program is loaded after other programs have altered the system variable state, or if additional BASIC lines are inserted before line 1, the REM body will no longer start at address 17606 and the machine code will not execute correctly. No error-checking or dynamic address calculation (such as USR (PEEK 16396 + 256*PEEK 16397 + offset)) is employed.
Key Variables
| Variable | Role |
|---|---|
K | Receives the return value of the USR call (result discarded in practice) |
Content
Image Gallery
Source Code
1 REM ▗ 2[R]#[R]#[R]#[R]#[R]#V#[A]#########▙### RETURN PLOT LOAD LET PAUSE SLOWB PRINT RETURN\~~N\,, POKE PAUSE ) PRINT 67777777 ▘0ACS SK\~~ACS TK▀Y▗TAN Y▖TAN ACS TK▀Y▝TAN Y▘TAN #█- #▞▌ACS 7ACS >( IF E[.]RND;- #;TAN ▖#E[.]RND\,,TAN GOSUB #[▒]RND# RETURNTCOS £ GOSUB #[▒]RNDE[;]RNDACS TSP76[;]RNDF/. GOSUB #[▒]RND# RETURN▘COS $ GOSUB #[▒]RNDE[;]RNDACS TK*F6[;]RND FAST)5 ACS S▘▐▖S▖Y▐/5Y▗/F)5 ACS S▘█▖K▖Y▄/▛#[I]#;( IF TAN LN #INKEY$ Y▀[I]#TAN LN #INKEY$ Y▌ LPRINT 7▘▌▖LN #INKEY$ TAN LN #INKEY$ Y▝[I]#Y▖ LPRINT LN #INKEY$ Y▘[I]#TAN #[I]#)▞ ;#[I]#TAN GOSUB #▙RND# RETURN▘COS $ GOSUB #▙RNDE[<]RNDACS TK(F6[<]RNDACS SS▖Y▝/USR Y▗/SQR ACS SS▖Y▘/COS Y▖/CODE GOSUB #▙RND# RETURNICOS £ GOSUB #▙RNDE[<]RNDACS TS THEN76[<]RNDF/ACS 6B666677777777778888888888999 GOSUB #[▒]RND# RETURN▘COS ▌ GOSUB #[▒]RNDE[;]RNDACS SK+)5 [B] GOSUB #6[;]RNDACS TS▖Y▖/LY▗/HACS TS▖Y▘/9Y▝/5 GOSUB #[▒]RND# RETURN3COS ▖ GOSUB #[▒]RNDE[;]RNDACS SS STEP )5 ;6[;]RND[B] GOSUB #/COS ##[I]#)▜ ;#[I]#TAN GOSUB #▙RND# RETURN▘COS ▌ GOSUB #▙RNDE[<]RNDACS SKP)5 [B] GOSUB #6[<]RND;/. GOSUB #▙RND# RETURNACOS ▖ GOSUB #▙RNDE[<]RNDACS SS+)5 ;6[<]RND▞▞ACS TS▖Y▀/XY▝/2▞▞ACS TK▖Y▐/\~~Y█##[I]#7( IF TAN :█LN [W]PIY▌[I]#TAN FAST:▀LN [W]PIY▘[I]# LPRINT [B] GOSUB #Y▗▘▄▞LN [W]PIY▖[I]#TAN FASTLN [U]PI LPRINT [B] GOSUB #Y▄▞▞/VAL [J]▘ ▖[J]▘ \~~[S]CODE ##LN [V]▝# RETURN COPYCOS RETURN RUN C# RETURN LOAD C# RETURN CLS4\,,5▙RND)[<]RND#EXP # RETURN#4\,,5▜RND)[+]RND#EXP # RETURN CLEAR4\,,5▚RND)[*]RND#,# RETURN[Z]4\,,5[▒]RND)[;]RND#,#)COS RND RETURN TO 4▛, RETURN0COS X/▒ RETURN RETURN"", RETURNZCOS W#E[.]RND,[I][C]##>CHR$ 0MH#TAN ( CLEARTAN # RETURN TO 4;#[*]INKEY$ # RETURN TO 4▀#▐PI RETURN LOAD 4▀##PI RETURN RUN 4(#TAN INKEY$ RETURN CLEAR""U"# RETURN[)]COS W#/£ RETURN CLEAR""U"# RETURN[~~]C)X#USIN RND RETURN COS [J]MSIN RND#M"#TAN USIN RND RETURN COS LPRINT 5▙RND▞▒[J][Y]4▖7( IF TAN #LEN # 6[;]INKEY$ 6[6]INKEY$ 6ACS INKEY$ 6USR INKEY$ 6#PI6#PI6▗PI6[(]PI FOR 6[9]INKEY$ 6[H]INKEY$ 6NOT INKEY$ 6 TO INKEY$ 6#PI6█PI6[<]PI6[2]PIYTAN M[,,]#Y[*]M##Y#M▙#Y▐M##Y▘MSIN RNDTAN 65INKEY$ 6EINKEY$ 6▀INKEY$ 6£INKEY$ 6▀PI6£PI6SPI6INKEY$ PI FOR 6HINKEY$ 6PINKEY$ 6?INKEY$ 6*INKEY$ 6?PI60PI6#PI6#PIY▘M[,,]#Y3M##Y▘M▙#YQM##Y▘MSIN RNDTAN ▛▀▀▀▀▀▀▀▀▀▘T I M E X▝▀▀▀▀▀▀▀▀▀▀▌█████████████████████████████▌▌▙▄▄▄▄▄▄▄▄▄▄▖T R A P▗▄▄▄▄▄▄▄▄▄▄▄▌ LN 7?LN E\~~)##▘4 LN #"▞=)▜#VAL ▘4 LN #"AT ( NEXT )[8]#▘4 LN #"E£RND)7 ;6[.]RNDLN F?/▛WM##▘/=▘/= GOSUB #▙RND GOSUB #▜RND▘£\~~LN LLIST RND6[<]RND6[+]RND▘2( GOSUB #[▒]RND GOSUB #▚RND▘?▒LN LLIST RND6[*]RND6[;]RND[J]5[~~]RND▞▒#7( UNPLOT 5[H]RND▞▒[J]#7#W7( RAND Y[~~]M"#YAMCOS RNDE[.]RNDYA#Y\~~MH#### AT # GOSUB ##/▌AT # GOSUB ##5LEN RND#W# RETURN 4; LPRINT LN ▘#[J]MLEN RND OR 5[1]RND▘[~~]RND OR 5[H]RND#G# FAST▖£VAL #[B] PAUSE [.]#J RETURNCABS ####[B] PAUSE [B]#J RETURNVABS ###U▄RND[S]4$U▙RNDX[T]K▞LEN $[T]ABS ##U▐RND[S]4$U▜RNDX[T]K▞LEN $[T]ABS ##U▚RND[T]4$U▗RNDX[S]K▞LEN \,,[S]ABS ##U[▒]RND[T]4$U[,,]RNDX[S]K▞LEN \,,[S]ABS ##LN TAN RND PRINT LN LLIST RND FAST OR #7# FOR \~~[I]# LPRINT Y[~~][T]K▀ LET [J] PRINT LET ▝[I]# FOR #F#£GG OR AT LPRINT #H#GGY[W][X] AND ##▘= [J][S]C▒#X RETURN 4 CLS( SAVE #[:]##OO5D#OO5/\~~OO59#OO▘█ LLIST [J][S]ASN [=]##X RETURN C CLS( SAVE #[=]# 000000001111111111222222222233333333334444444444555555555566666666667777777777888888888899999999990000000000
10 LET K=USR 17606
20 SAVE "TRA[P]"
25 STOP
30 GOTO 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.