Bat Cage is an action game in which the player catches a falling egg and then traps a bat inside a cage. The program is driven almost entirely by machine code embedded in the REM statement at line 1, with BASIC serving only as a loader that calls the routine via USR 17387 at line 10. The machine code handles all gameplay logic, graphics rendering, collision detection, and input processing directly. A SAVE command at line 20 preserves the program, and RUN 10 at line 30 restarts the game loop.
Program Analysis
Program Structure
The BASIC listing is minimal by design, consisting of just three lines:
1 REM— contains the entire machine code payload (several hundred bytes) embedded as the body of the remark.10 LET K=USR 17387— transfers control to the machine code. The address 17387 (decimal) corresponds to the start of the machine code bytes stored in the REM line’s data area.20 SAVE "CAGE"— saves the program to tape.30 RUN 10— restarts the program by jumping to line 10.
All game logic — movement, collision detection, graphics, timing, and scoring — is implemented entirely in the machine code within the REM statement. BASIC is used solely as a vehicle to load and launch that code.
Machine Code Embedding via REM
Storing machine code in a REM statement is a well-established technique. The BASIC interpreter skips REM line content entirely, so arbitrary binary data can be placed there without interference. The USR function at line 10 computes the Z80 entry point address (17387) and performs a CALL to it, handing control to the machine code. The return value is stored in K, though the game does not use it in BASIC.
Machine Code Analysis
The REM data is a dense Z80 routine. Notable structural features visible in the hex stream include:
- CB-prefixed instructions — extensive use of
CBopcodes indicates heavy reliance on bit manipulation instructions (BIT,SET,RES,RLC, etc.), consistent with sprite/character-level graphics and flag-based state machines. - ED-prefixed instructions —
EDopcodes appear frequently, covering 16-bit loads (LD BC,(nn),LD DE,(nn)), block moves (LDIR), andLD A,R/LD A,Iused for pseudo-random number generation or timing. - Block memory operations — sequences ending in
\ED\B0(LDIR) suggest bulk copying of sprite or screen data. - Internal subroutine calls — numerous
CD xx xx(CALL) instructions with targets within the REM block point to a well-structured internal subroutine architecture covering rendering, input reading, collision, and movement. - Address constants — repeated references to addresses in the
43xxand44xxhex range (roughly 17000–17600 decimal) indicate game-state variables stored within or just after the REM block itself.
Key Address Map (inferred)
| Hex Address | Decimal | Inferred Role |
|---|---|---|
43CB | 17355 | Sprite/object X or position low byte |
43CC | 17356 | Sprite/object Y or position high byte |
43CD | 17357 | Secondary object coordinate |
43D0 | 17360 | Game state / direction flag |
43D1 | 17361 | Velocity or delta counter |
43D2 | 17362 | Additional state variable |
44B6 | 17590 | Screen buffer or sprite data table |
44D8 | 17624 | Graphics/shape data |
Notable Techniques
- LD A,R (
ED 5F) — used as a source of pseudo-randomness by reading the Z80 refresh register, a common technique for seeding movement or timing variation without a dedicated RNG. - Bit-field state machine — the heavy use of
BIT,SET, andRESon single bytes (visible in theCB 4x,CB 5x,CB 6x,CB 7xranges) suggests individual bits of state bytes encode direction, phase, and collision flags compactly. - Self-contained variable storage — game variables are stored at fixed offsets within the REM block’s memory region rather than in BASIC variables, avoiding BASIC overhead entirely.
- Loop unrolling with
DJNZ— several10 Fxbyte pairs (DJNZwith negative offset) implement tight delay or drawing loops without BASIC’s overhead. - Exx / DI shadow registers —
D9(EXX) appears in the code, indicating use of the Z80 alternate register set for temporary storage during interrupt-sensitive sections.
BASIC Idioms
The use of LET K=USR 17387 rather than a bare RAND USR is a minor stylistic choice; both transfer control identically. The RUN 10 at line 30 provides a simple restart mechanism: if the machine code ever returns to BASIC (e.g., after a game over), the program loops back to re-invoke the machine code rather than halting.
Bugs and Anomalies
No significant BASIC-level bugs are present. The program is straightforward as a loader. Any bugs would reside entirely within the machine code and cannot be fully assessed from a static hex listing alone.
Source Code
1 REM \CB\38\30\0A\CB\39\30\03\3E\87\C9\3E\04\C9\CB\39\30\03\3E\02\C9\3E\01\C9\0E\80\06\02\E5\79\AE\77\23\10\FA\E1\C9\ED\43\CB\43\22\CD\43\C9\CB\6C\28\32\21\D0\43\AF\BE\C8\2B\3E\E8\BE\C8\77\EB\2A\CB\43\22\E7\43\21\D3\43\3A\D1\43\C6\15\86\D8\77\13\AF\12\C9\12\C9\79\FE\37\C8\D5\E1\0C\CB\47\28\0E\23\18\0B\0D\C8\79\D5\E1\CB\47\28\02\2B\1B\CD\A7\40\4F\EB\CD\82\40\4F\18\61\CD\BB\02\ED\4B\CB\43\ED\5B\CD\43\CB\5D\28\A5\CB\65\20\58\CB\5C\28\C5\7C\EB\11\21\00\CB\67\28\1F\CB\4F\CA\91\43\78\FE\26\C8\04\E5\0F\30\1B\19\D1\CD\A7\40\C5\0E\03\CD\9C\40\EB\CD\9C\40\18\13\05\C8\E5\78\0F\30\03\A7\ED\52\D1\CD\A7\40\EB\07\38\E2\C5\CD\9A\40\C1\CB\41\C8\0E\04\CD\5C\41\EB\0E\01\06\02\79\AE\77\23\23\10\F9\C9\11\D1\43\CB\6D\20\06\1A\A7\C8\3D\18\08\CB\45\C0\1A\FE\23\C8\3C\47\3A\D0\43\A7\C8\3E\1C\80\32\B7\44\78\12\C9\3A\D0\43\A7\C0\E5\2A\D5\43\7E\FE\03\28\0D\3C\FE\26\30\03\77\E1\C9\36\1C\2B\18\EE\36\1D\21\D5\43\35\2B\34\34\2B\AF\77\2B\CB\3E\E1\C9\CD\FB\40\C1\CB\09\30\02\AF\47\C5\21\3C\40\01\50\40\D9\21\D7\43\4E\23\46\04\0C\11\00\28\78\BA\CC\82\44\3A\D4\43\BD\38\0A\1E\80\3A\D0\43\AA\B8\CC\81\44\3E\21\B8\28\56\30\20\2F\B8\28\54\38\1A\3E\17\B9\28\51\30\24\2F\B9\28\4F\38\14\3E\24\B9\28\50\30\50\2F\B9\28\46\38\4A\79\FE\3C\28\08\30\0A\ED\5F\2F\B8\20\04\79\ED\44\4F\3A\CC\43\B8\28\04\2F\B8\20\65\3A\CB\43\3D\B9\30\5E\C6\04\B9\30\0B\C6\01\2F\B9\30\53\C6\04\B9\38\4E\18\6E\CB\C3\18\AE\CB\C2\18\AA\CB\CB\18\0A\CB\CA\18\06\CB\D3\18\02\CB\D2\CB\7B\20\71\CB\43\20\67\CB\4B\20\20\CB\53\20\1C\CD\15\43\F1\F5\B3\A2\AA\CB\47\28\09\F5\78\ED\44\47\CD\8A\41\F1\CB\4F\28\09\CD\8A\41\79\ED\44\4F\18\04\CB\57\20\F3\CD\3B\43\3E\E8\BD\DA\B6\41\3A\D1\43\A7\CA\CB\41\0E\0F\CB\7B\28\02\0E\0A\47\79\3D\20\FD\10\FA\C3\CB\41\CB\7B\28\26\CB\78\20\D6\ED\5F\FE\C0\30\3D\FE\95\30\30\3E\20\32\D0\43\78\ED\44\47\18\C1\7B\B2\D1\B2\57\3A\D2\43\5F\D5\5A\18\B4\3E\E6\32\CF\43\C6\02\95\28\AA\C5\4F\AF\47\E5\D1\1B\23\ED\B0\C1\2B\18\9C\C5\FE\80\D4\7A\44\C1\18\CC\C5\4F\3A\D1\43\CB\3F\81\30\02\06\FF\2F\A0\28\06\47\CD\8A\41\10\FB\C1\18\B3\1E\80\3A\CC\43\FE\21\D8\20\02\CB\C3\3A\CB\43\FE\14\30\03\CB\83\C9\FE\25\30\F9\FE\18\30\02\CB\CB\FE\21\D8\CB\D3\C9\E5\70\2B\71\3E\80\A3\5F\16\FF\3A\CF\43\BD\30\01\14\CB\78\28\03\78\2F\47\CB\79\28\03\79\2F\4F\CD\82\40\AB\A2\F5\CD\7C\43\E5\D9\5E\23\56\EB\0A\AE\77\E1\F1\02\AE\77\EB\72\2B\73\23\23\03\D9\E1\23\C9\58\79\80\01\00\05\51\CB\23\CB\12\10\FA\21\D8\44\19\51\5F\19\C9\CD\3A\44\01\20\00\11\B6\44\21\5A\44\ED\B0\0E\1E\11\CB\43\21\AD\43\ED\B0\CD\3A\44\C9\1C\24\38\47\E8\20\12\80\00\D8\D4\44\1D\03\13\13\13\EA\EA\13\EA\EA\27\13\27\EA\D6\13\D6\EA\1C\24\38\47\E8\20\12\80\00\D8\D4\44\CB\F9\CD\F7\25\10\E2\E9\10\1E\06\E8\0A\DB\C5\F6\CD\0F\83\81\CD\2B\0F\CD\2A\0A\11\CB\43\06\16\C5\D5\01\20\00\CD\6B\0B\D1\C1\10\F4\11\85\05\3E\80\21\B6\44\06\15\C5\06\1E\72\23\77\23\10\FC\73\23\23\C1\10\F1\11\01\00\D5\21\17\21\E5\23\01\00\0C\CD\47\44\11\00\01\CD\45\44\E1\CD\45\44\CD\94\43\C3\B9\41\2A\CB\43\11\01\00\01\00\04\18\02\06\07\E5\D9\C1\CD\82\40\F5\CD\7C\43\F1\AE\77\D9\19\10\EF\C9\03\07\2E\03\03\03\03\03\03\03\03\04\39\00\2E\00\32\00\2A\00\3D\87\03\03\03\03\03\03\03\1C\1C\1C\84\01\1E\26\ED\43\E7\43\78\ED\44\47\C9
10 LET K=USR 17387
20 SAVE "CAG%E"
30 RUN 10
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
