This program is a menu-driven tape loader that presents eight programs for selection and then LOADs the chosen one from cassette. The screen is decorated with a bordered frame built from block graphics: a top row of inverse semicolons, 22 rows of a repeating checkerboard pattern stored in B$, and a bottom row of inverse exclamation marks. Menu item names are displayed in normal video alongside inverse-video equivalents that animate over them to highlight the prompt. Selection is validated by checking that the INKEY$ code falls between 29 and 37 (the digit characters 1–8 on the ZX81 keyboard), then a computed GO TO of VAL A$*1000 dispatches directly to the appropriate LOAD statement.
Program Analysis
Program Structure
The program is organised into four logical phases:
- Initialisation (line 1):
POKE 16418,0sets the system variable controlling the display file position, effectively resetting the screen output cursor to the top. - Screen decoration (lines 2–8): A bordered frame is drawn using block graphics stored in a string and printed via a loop.
- Menu display and input loop (lines 9–110): Program names and numbers are printed, then a tight polling loop waits for a valid digit keypress.
- Dispatch and tape loading (lines 120, 1000–8000): A computed
GO TOselects the appropriateLOADstatement.
Screen Border Construction
Three distinct graphic rows form the frame:
- Top row (line 4): A
PRINTstatement fills the line with inverse semicolons (\;;block graphic = ▄ repeated) flanked by inverse spaces, producing a solid top border. - Middle rows (lines 2, 5–7):
B$holds a string of\@@block graphic characters (checkerboard pattern) between inverse spaces. TheFOR N=1 TO 22loop prints this 22 times to fill the body of the screen. - Bottom row (line 8): Inverse exclamation marks (
\!!) produce a contrasting bottom border.
Menu Display Technique
Line 9 prints the title “2/83 PROGRAM LOADER” entirely in inverse video using the %X escape sequences. Line 10 uses a single PRINT statement with multiple AT and TAB clauses to place all eight menu entries and their corresponding digit labels in one operation, minimising execution overhead. Line 20 first prints a normal-video prompt, then immediately overwrites it with an inverse-video version at the same AT position — a common ZX81 technique to render text in inverse without using a separate PRINT statement.
Input Validation
The input loop at lines 100–110 uses INKEY$ for non-blocking polling. Validation checks three conditions in one IF:
A$=""— no key pressed yetCODE A$<29— key code below the digit “1” (ZX81 codes 29–37 map to digits 1–9)CODE A$>37— key code above digit “9”, rejecting any non-numeric input
This means digits 1–8 are accepted (and implicitly digit 9, though line 9000 is a catch-all LOAD "").
Computed GO TO Dispatch
Line 120 uses GOTO VAL A$*1000 to calculate the target line number at runtime. Since VAL A$ returns the numeric value of the single digit entered (1–8), multiplying by 1000 produces exactly the line numbers 1000–8000 where each LOAD statement resides. This is a compact and efficient dispatch table requiring no IF/THEN chain.
Utility Lines
| Line | Purpose |
|---|---|
9000 | LOAD "" — loads the next program from tape regardless of name (fallback / digit 9) |
9998 | SAVE "LOADER" — re-saves this loader program to tape for duplication |
9999 | RUN — restarts the loader after returning from a saved program or after saving |
Notable Idioms and Anomalies
- The program names in the
LOADstatements (e.g.,"ADDITIO%N") contain the%Ninverse-video escape, meaning the final letter “N” is stored as an inverse character in the tape header name. This must match exactly with how those programs were originally saved. POKE 16418,0at line 1 directly manipulates theDF_CCsystem variable (display file current character address low byte), which resets the print position — a lower-level approach thanCLS.- The single long
PRINTat line 10 is a memory optimisation; each additionalPRINTstatement costs extra bytes for the line header overhead.
Content
Source Code
1 POKE 16418,0
2 LET B$="% \@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@\@@% "
4 PRINT "% \;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;\;;% "
5 FOR N=1 TO 22
6 PRINT B$
7 NEXT N
8 PRINT "% \!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!\!!% "
9 PRINT AT 1,5;"% %2%/%8%3% %P%R%O%G%R%A%M% %L%O%A%D%E%R% "
10 PRINT AT 3,5;" ADDITIO%N ";TAB 28;"1";AT 5,5;" SUBTRACTIO%N ";TAB 28;"2";AT 7,5;" WHITE-HOL%E ";TAB 28;"3";AT 9,5;" TAPESTR%Y ";TAB 28;"4";AT 11,5;" PAYROL%L ";TAB 28;"5";AT 13,5;" SUPERSCROL%L ";TAB 28;"6";AT 15,5;" INVERSCROL%L ";TAB 28;"7";AT 17,5;" BULLETI%N ";TAB 28;"8"
20 PRINT AT 22,5;" ENTER ONE OF ABOVE ";AT 22,5;"% %E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% "
100 LET A$=INKEY$
110 IF A$="" OR CODE A$<29 OR CODE A$>37 THEN GOTO 20
120 GOTO VAL A$*1000
\n1000 LOAD "ADDITIO%N"
\n2000 LOAD "SUBTRACTIO%N"
\n3000 LOAD "WHITE-HOL%E"
\n4000 LOAD "TAPESTR%Y"
\n5000 LOAD "PAYROL%L"
\n6000 LOAD "SUPERSCROL%L"
\n7000 LOAD "INVERSCROL%L"
\n8000 LOAD "BULLETI%N"
\n9000 LOAD ""
\n9998 SAVE "LOADE%R"
\n9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
