MenuE

Developer(s): Bob Swoger (K9WVY)
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Database

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 RangeSection
710–720Entry point and paper setup
810–820PROMPT subroutine
910–930DISPLAY subroutine
1010–1050ADD section
2010–2030ERASE/DELETE section
3010–3140MOVE section
4010–4090LPRINT section
8010–8280Initialization and UDG definition
9010–9360Billboard display and main key loop
9991–9999SAVE/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

VariableRole
AConstant 0 (reused as zero)
BConstant 10 (slots per column)
CConstant 20 (total slots per box)
DConstant 1 (lower bound / step)
EConstant 2 (row multiplier)
ICurrent box number (1–13 active range, 24 max)
JCurrent 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" to GO 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*13 span). 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 J and jumps to 3170 on 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

Appears On

Related Products

Related Articles

Related 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.

Scroll to Top