MenuE is a disk-directory manager that Bob Swoger wrote to organize his 24 boxes of disks. Each box held 20 named slots stored in a large string array, allowing Bob to add, delete, and move entries between boxes via single-keypress commands. The program uses a packed string storage scheme where each box occupies 260 characters in the master string G$, with each slot consuming 13 characters, accessed through arithmetic index expressions. Two user-defined graphics are defined at startup — UDG “a” with an alternating checkerboard pattern via BIN literals and UDG “b” as a stylized diagonal shape — used to fill the background billboard display. Screen layout relies on POKE 23659 to suppress the lower editing area during prompts, and POKE 23562/23609/23658 to configure display behavior at startup. The SAVE section includes a VERIFY pass with audible BEEP cues to confirm tape integrity.
Program Analysis
Program Structure
The program is organized into clearly labeled subroutine blocks, each prefixed with a REM line. The main flow begins at line 8000 (initialization), proceeds to the billboard display at line 9010, then enters an input loop at line 9120. Navigation between sections is driven entirely by single-keypress detection.
| Line Range | Section |
|---|---|
| 710–720 | Entry point and paper setup |
| 810–820 | PROMPT subroutine |
| 910–930 | DISPLAY subroutine |
| 1010–1050 | ADD section |
| 2010–2030 | ERASE/DELETE section |
| 3010–3140 | MOVE section |
| 4010–4090 | LPRINT section |
| 8010–8280 | Initialization and UDG definition |
| 9010–9360 | Billboard display and main key loop |
| 9991–9999 | SAVE/VERIFY section |
Data Storage Scheme
All directory entries are stored in a single large string G$ (dimensioned externally as DIM G$(6241), commented out at line 8020). The layout packs 24 boxes × 260 characters each. Within each box, 20 slots of 13 characters each occupy the first 260 characters. The index formula used throughout is:
- Slot start:
((I*260)-258)+((J*13)-13) - Slot end:
((I*260)-259)+(J*13)
Where I is the box number (1–24) and J is the slot number (1–20). The display section also reads a second column of entries offset by (J+B)*13, suggesting each box stores two parallel columns of 10 entries.
Variable Roles
| Variable | Role |
|---|---|
A | Constant 0 (reused as zero) |
B | Constant 10 (slots per column) |
C | Constant 20 (total slots per box) |
D | Constant 1 (lower bound / step) |
E | Constant 2 (row multiplier) |
I | Current box number (1–13 active range, 24 max) |
J | Current slot number |
G$ | Master directory string (packed storage) |
S$ | Temporary slot title string (12 chars) |
Key BASIC Idioms
The program makes extensive use of VAL "number" in place of numeric literals for constants assigned to variables at initialization (line 8030). This is a recognized memory-saving technique, as string tokens consume less tokenized storage than numeric literals in certain contexts.
The main input loop at line 9130 uses INKEY$ in a tight polling loop rather than INPUT, providing immediate single-keypress response without requiring Enter. Multiple keys are mapped to the same action (e.g., "7", "D", "0", "-" all invoke DELETE), accommodating different keyboard layouts or preferences.
POKE 23659 is used to control the lower screen area: setting it to A (0) suppresses the prompt line, and setting it to E (2) restores it, bracketing PRINT statements that write to line 22.
UDG Definitions
Two UDGs are defined at startup. UDG "a" is built with alternating BIN 10101010 and BIN 01010101 rows in a loop (lines 8110–8140), producing a checkerboard texture. Note that the loop runs H=0 TO 7 but writes to both USR "a"+H and USR "a"+(H+1), meaning the 8th row is overwritten and the pattern cycles correctly across 8 bytes. UDG "b" is defined with hand-coded BIN values (lines 8210–8280) producing a diagonal or stylized glyph.
The billboard fill at line 9040 prints 32 copies of UDG \a per row across 22 rows, creating a textured background. The border is then drawn over this with PLOT/DRAW calls forming a double-rectangle frame (line 9060).
Navigation Logic
Box navigation wraps around: pressing the “next” key (mapped to "8" and "N") increments I and wraps at 13 back to 1 (line 9110). The “previous” key (mapped to "5") decrements and wraps at 1 back to 13 (line 9350). The active browse range is thus boxes 1–13 rather than the full 1–24, with the upper boxes only reachable via the MOVE operation’s direct INPUT.
LPRINT Section
Lines 4010–4090 iterate over all 13 browsable boxes and use LPRINT with AT positioning to produce a formatted printed directory listing. This mirrors the screen display logic from the DISPLAY subroutine but outputs to a printer rather than the screen.
Bugs and Anomalies
- Line 9160 maps
"D"toGO TO 2000(DELETE), but"D"more intuitively suggests “Down” or another navigation action; the prompt at line 820 labels the option as “Delete,” so this is intentional though mnemonic-ambiguous. - The
DIM S$(12)at line 8020 allocates 12 characters for the title, but the slot storage formula writes 13 characters (J*13span). The extra character may serve as a delimiter or padding byte, but the off-by-one between DIM and the index range could cause string-length mismatches on assignment. - Line 3110 validates
Jand jumps to3170on failure, but line 3170 does not exist in the listing — this would cause a runtime error on an out-of-range slot entry in MOVE mode. GO TO VAL "9000"at line 9999 targets line 9000, which does not exist in the listing; execution would fall through to the next available line (9010), which is the billboard redraw — this is likely intentional.
Content
Image Gallery
Source Code
710 REM MENUE
720 PAPER VAL "7": GO TO 8000
810 REM PROMPT Section
820 POKE 23659,A: PRINT AT 22,A; INK A; PAPER VAL "4";'" Add Delete Move Next Save": POKE 23659,E: RETURN
910 REM DISPLAY Section
920 PRINT AT A,13; FLASH D;"BOX ";AT A,17+(I<B);I
930 FOR J=D TO B: PRINT PAPER A; INK VAL "7";AT J*E,D;G$(((I*260)-259)+((J*13)-13) TO ((I*260)-259)+(J*13));AT J*E,17;G$(((I*260)-259)+(((J+B)*13)-13) TO ((I*260)-259)+((J+B)*13)): NEXT J: RETURN
1010 REM ADD Section
1020 INPUT " ADD MODE - SLOT(1 - 20)?";J: IF J<D OR J>C THEN GO TO 1020
1030 INPUT " TITLE?";S$
1040 IF S$(D)=" " THEN GO TO 1030
1050 LET G$(((I*260)-258)+((J*13)-13) TO ((I*260)-259)+(J*13))=S$: GO TO 3130
2010 REM ERASE Section
2020 INPUT " DELETE MODE - SLOT(1 - 20)?";J: IF J<D OR J>C THEN GO TO 2020
2030 LET G$(((I*260)-258)+((J*13)-13) TO ((I*260)-259)+(J*13))="": GO TO 3130
3010 REM MOVE Section
3020 INPUT " MOVE FROM SLOT(1 - 20)?";J: IF J<D OR J>C THEN GO TO 3020
3030 LET S$=G$(((I*260)-258)+((J*13)-13) TO ((I*260)-259)+(J*13))
3040 INPUT " DELETE FROM OLD SLOT?";Y$
3050 IF Y$(1)="Y" THEN LET G$(((I*260)-258)+((J*13)-13) TO ((I*260)-259)+(J*13))=""
3080 INPUT " MOVE TO BOX(1 - 24)?";I
3090 GO SUB 900
3110 INPUT " MOVE INTO SLOT(1 - 20)?";J: IF J<D OR J>C THEN GO TO 3170
3120 LET G$(((I*260)-258)+((J*13)-13) TO ((I*260)-259)+(J*13))=S$
3130 GO SUB 820
3140 GO TO 9120
4010 REM LPRINT Section
4020 FOR I=D TO 13
4040 LPRINT AT A,13;"BOX ";AT A,17+(I<B);I
4050 FOR J=D TO B
4060 LPRINT AT J*E,D;G$(((I*260)-259)+((J*13)-13) TO ((I*260)-259)+(J*13));AT J*E,17;G$(((I*260)-259)+(((J+B)*13)-13) TO ((I*260)-259)+((J+B)*13))
4070 NEXT J
4080 NEXT I
4090 GO TO 3130
8010 REM Custom Keyboard Section
8020 DIM S$(12): REM DIM G$(6241)
8030 INK 0: BORDER VAL "4": CLS : LET A=VAL "0": LET B=VAL "10": LET C=VAL "20": LET D=VAL "1": LET E=VAL "2": REM 0-BOXS-SLOTS-1-2
8040 POKE VAL "23562",E: POKE VAL "23609",VAL "50": POKE VAL "23658",VAL "24"
8110 FOR H=0 TO 7
8120 POKE USR "a"+H,BIN 10101010
8130 POKE USR "a"+(H+1),BIN 01010101
8140 NEXT H
8210 POKE USR "b"+0,BIN 01000000
8220 POKE USR "b"+1,BIN 10100010
8230 POKE USR "b"+2,BIN 10000100
8240 POKE USR "b"+3,BIN 10101000
8250 POKE USR "b"+4,BIN 01010000
8260 POKE USR "b"+5,BIN 00101100
8270 POKE USR "b"+6,BIN 01010010
8280 POKE USR "b"+7,BIN 10001100
9010 REM BILLBOARD Section
9020 PRINT AT A,A;
9030 FOR I=A TO VAL "21"
9040 PRINT "\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a\a"
9050 NEXT I
9060 PLOT A,A: DRAW A,175: DRAW 255,A: DRAW A,-175: DRAW -254,A: DRAW A,174: DRAW 253,A: DRAW A,-173: DRAW -252,A: DRAW A,174
9070 GO SUB 800
9090 LET I=A
9110 LET I=I+D: IF I>13 THEN LET I=D
9120 GO SUB 900
9130 LET I$=INKEY$: IF I$="" THEN GO TO 9130
9140 IF I$="A" THEN GO TO 1000
9150 IF I$="7" THEN GO TO 2000
9160 IF I$="D" THEN GO TO 2000
9170 IF I$="M" THEN GO TO 3000
9180 IF I$="Z" THEN COPY
9190 IF I$="P" THEN COPY
9210 IF I$="K" THEN GO TO 4000
9220 IF I$="L" THEN GO TO 4000
9230 IF I$="S" THEN GO TO 9990
9240 IF I$="0" THEN GO TO 2000
9250 IF I$="6" THEN GO TO 3000
9260 IF I$="-" THEN GO TO 2000
9270 IF I$="+" THEN GO TO 1000
9280 IF I$="5" THEN GO TO 9350
9290 IF I$="8" THEN GO TO 9110
9310 IF I$="C" THEN GO TO 4000
9320 IF I$="V" THEN GO TO 4000
9330 IF I$<>"N" THEN GO TO 9130
9340 GO TO 9110
9350 LET I=I-D: IF I<1 THEN LET I=13
9360 GO TO 9120
9991 REM SAVE Section
9992 BEEP .15,5
9993 SAVE "MENUE" LINE 8000
9994 BEEP .042,50: PAUSE 2.8: BEEP .042,50
9995 POKE 23659,A: PRINT PAPER 4;''" Rewind & Play tape to VERIFY ": POKE 23659,E: PRINT AT A,A;
9996 VERIFY "MENUE"
9997 BEEP .042,50: PAUSE 2.8: BEEP .042,50
9999 GO TO VAL "9000"
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.