Super Marbles is a game loader and screen-save/load utility that uses machine code routines stored at address 37900 and above. The BASIC stub at line 30 jumps to a machine code entry point via RANDOMIZE USR 37900, while line 9010 locates and executes a second routine by reading the BASIC program’s own start address from system variables at 23627–23628, adding 6 bytes for the line header. Screen data (14080 bytes from address 50400, covering the Spectrum’s display file and attributes) can be saved and loaded by name using the SUBroutine at line 2000. The bootstrap at line 9999 saves both the BASIC loader (autostarting at line 9000) and the machine code block in a single sequence, followed by two VERIFY passes to confirm integrity.
Program Structure
The program is divided into several functional regions:
- Lines 10–40: Main entry point and dispatcher. Reads
PEEK 23681to decide which routine to jump to, or falls through to machine code viaRANDOMIZE USR 37900. - Lines 100–145: Screen save routine — prompts for a filename, saves 14080 bytes from address 50400, verifies, then re-enters machine code.
- Lines 150–160: Screen load routine — prompts for a filename and loads the screen data back to address 50400.
- Line 255–260: Quit handler — issues
CLEAR 65535andNEW. - Lines 2000–2020: Shared filename input subroutine with a length guard (max 10 characters).
- Lines 9000–9020: Tape loader — sets black border/paper/ink, self-locates, executes a machine code initialiser, then loads the main code block and restarts.
- Line 9999: Bootstrap saver — writes both the BASIC file (autostart line 9000) and the machine code block, then verifies both.
Machine Code Integration
Three distinct RANDOMIZE USR calls are used to invoke machine code:
| Address | Context | Purpose |
|---|---|---|
| 37900 | Line 30 | Main game entry point after normal boot |
| 45181 | Line 140 | Called after screen save/load to return to game |
| Computed | Line 9010 | Self-located initialiser within the BASIC program area |
The self-locating technique at line 9010 is notable: LET a=6+PEEK 23627+256*PEEK 23628 reads system variables PROG (23627–23628), which holds the start address of the BASIC program, then adds 6 to skip past the line number (2 bytes), line length (2 bytes), and REM token plus space (2 bytes) to reach embedded machine code stored inside a REM statement at the very first line of the program when loaded from tape.
System Variable Usage
PEEK 23681 is used twice (lines 40 and 145) as a dispatch value. Address 23681 is RASP/the printer buffer area — its use here as a state variable to control program flow is an unconventional but functional technique, avoiding the need to maintain a separate BASIC variable across CLS or machine code calls that might corrupt memory.
Screen Data Handling
The save/load routines target address 50400 for 14080 bytes. The standard Spectrum display file starts at 16384 and is 6912 bytes; 50400 is well above the normal screen area, suggesting the machine code copies or manages an off-screen display buffer at this address. 14080 bytes is slightly larger than two full Spectrum screens (2 × 6912 = 13824), indicating possibly compressed or extended screen data including additional game state.
Bootstrap and Distribution (Line 9999)
Line 9999 packages the game for tape distribution in one command sequence:
SAVE "MARBLES" LINE 9000— saves the BASIC program with autostart at the loader (line 9000)SAVE "MARBLES"CODE 37900,27635— saves 27635 bytes of machine code starting at 37900VERIFY ""andVERIFY ""CODE— verifies both blocks immediately
The machine code block of 27635 bytes is substantial, running from 37900 to approximately 65535, filling almost the entire upper half of the 64 KB address space.
Protection and Integrity Check
Lines 20–30 implement a simple integrity guard: if PEEK 23681 is zero (i.e., the program has been RUN directly rather than loaded via the tape loader), it resets the font pointer system variables (23606–23607 to 0 and 60, giving address 15360), sets a neutral display state, and prints a warning not to use CLEAR, directing the user to GO TO 9999 instead. This protects the machine code which would be destroyed by an inadvertent CLEAR below 37900.
Notable BASIC Idioms
INPUT "FILE NAME:"; LINE a$— usesLINEto accept the full input as a string without quote-stripping.PRINT #1;AT 0,0;— writes to the lower screen (stream 1) to display the rewind tape prompt without disturbing the main screen.CLEAR 65535in the quit handler sets RAMTOP to the top of RAM, which effectively reclaims all memory beforeNEWresets the interpreter.
Content
Source Code
10 REM SUPER MARBLES
20 IF PEEK 23681=0 THEN POKE 23606,0: POKE 23607,60: BORDER 7: INK 0: PAPER 7: CLS : LIST 9999: PRINT ''"DO NOT USE CLEAR..."''"JUST GOTO 9999": STOP
30 PRINT AT 0,0;: RANDOMIZE USR 37900
40 CLS : GO TO PEEK 23681
100 REM SAVE SCREENS
110 GO SUB 2000
120 IF a$="" THEN GO TO 110
130 SAVE a$CODE 50400,14080
135 PRINT #1;AT 0,0;"REWIND TAPE TO VERIFY": PRINT AT 20,0;: VERIFY A$CODE 50400
140 CLS : PRINT AT 0,0;: RANDOMIZE USR 45181
145 CLS : GO TO PEEK 23681
150 REM LOAD SCREENS
160 GO SUB 2000: LOAD A$CODE 50400: GO TO 140
255 REM QUIT
260 CLEAR 65535: NEW
2000 REM get string
2010 INPUT "FILE NAME:"; LINE a$: IF LEN a$>10 THEN GO TO 2010
2020 RETURN
9000 REM LOADER
9010 BORDER 0: PAPER 0: INK 0: CLS : LET a=6+PEEK 23627+256*PEEK 23628: RANDOMIZE USR a
9020 LOAD "MARBLES"CODE : OVER 0: GO TO 10
9999 SAVE "MARBLES" LINE 9000: SAVE "MARBLES"CODE 37900,27635: VERIFY "": VERIFY ""CODE
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
