This program is a cassette tape cataloguing system that stores metadata for up to 100 programs in a 10×32 string array. Each record in the array holds a program name (columns 1–8), subject (10–15), counter location (17–22), tape number/side (24–27), and miscellaneous info (29–32). The main menu dispatches to six routines via a computed GOTO using GOTO 1000*VAL B$, covering data entry, viewing, tape save, clear, print, and sort. A Shell sort (gap-halving) at line 6200 allows sorting records by any of the five fields. Data is persisted to tape using the SAVE command at line 3050.
Program Analysis
Program Structure
The program is organised as a menu-driven application with a central dispatch loop and separate numbered subroutine blocks. The main menu lives at lines 20–260; six functional modules begin at multiples of 1000 (1000, 2000, 3000, 4000, 5000, 6000). A second sub-menu for viewing/editing begins at line 2000, itself dispatching via GOTO (VAL B$*200)+2100 to lines 2300, 2500, 2700, and 2900. Utility subroutines are at lines 9000 (scroll 10 lines) and 9800 (press-enter pause).
Data Model
All records are held in the string array A$, dimensioned at line 10 as DIM A$(10,32). Note that the first dimension is 10, yet the entry loop runs up to N=100 — this is a clear bug; the array can only hold 10 records before an index-out-of-range error occurs. The counter R1 tracks how many records have been entered and is preserved across menu returns.
Each 32-character row is laid out as a fixed-width record:
| Columns | Field | Max Length |
|---|---|---|
| 1–8 | Program name | 8 |
| 9 | Separator (space) | — |
| 10–15 | Subject | 6 |
| 16 | Separator | — |
| 17–22 | Counter location | 6 |
| 23 | Separator | — |
| 24–27 | Tape no./side | 4 |
| 28 | Separator | — |
| 29–32 | Miscellaneous info | 4 |
Menu Dispatch Technique
The main menu reads a single keypress and validates it by checking CODE B$ against the range 29–34 (ZX81 character codes for digits 1–6). The computed jump at line 260, GOTO 1000*VAL B$, routes directly to the correct module in a single statement — a classic and efficient ZX81 BASIC idiom. The secondary menu at line 2260 uses GOTO (VAL B$*200)+2100 with valid range 29–32 (digits 1–4), landing at lines 2300, 2500, 2700, and 2900. VAL B$ here works because B$ holds a single digit character.
Inverse Video Title Screen
The screen background effect at lines 40–60 fills the display by PRINTing "% % % % % % % % " in a loop 96 times — each % is an inverse space, alternating with normal spaces to produce a checkerboard pattern. The title text and menu options are then written using PRINT AT over this background. A similar 192-iteration loop appears in the sub-menu screen at line 2000. POKE 16418,0 sets the border colour and POKE 16418,2 changes it when entering a module.
Shell Sort Implementation
Lines 6200–6370 implement a Shell sort on the array. The gap N starts at INT(R1/2) and is halved each outer pass (line 6220). The inner loop compares A$(I, A TO B) with A$(L, A TO B), where A and B are set by the earlier field-selection block (lines 6070–6160) to the appropriate column slice for the chosen sort key. Swaps exchange the full 32-character row via the temporary B$. Note that B$ is reused for both menu input and sort temporary storage throughout the program.
Key BASIC Idioms
POKE 16418,N— direct memory write to the system variable controlling the display file border (TV colour register on ZX81).SCROLLused extensively to advance the display without clearing it, providing a rolling-log entry style.FAST/SLOWmode switching aroundINPUTstatements —SLOWis required for the display to work during input;FASTis used otherwise to speed up computations and screen fills.- Left-padding of the miscellaneous field in lines 1376–1385 using a prepend loop:
LET B$=" "+B$repeated4-LEN B$times. - The ruler string
Z$at line 12 is a 32-character row of inverse dashes used as a visual separator wherever data is displayed.
Bugs and Anomalies
- Array size mismatch:
DIM A$(10,32)at line 10 allocates only 10 rows, but the entry loop at line 1000 iterates up toN=100. Entering more than 10 programs will cause a subscript error. - Dead code at lines 8000/8100: Lines 8842 and 8844 call
GOSUB 8000andGOSUB 8100, but neither subroutine exists in the listing. Editing the counter field will produce an error. - Unreachable STOP at line 1999: Line 1999 contains
STOPbut can only be reached by falling through from line 1420’sNEXT Nloop completing atN=100; in practice execution goes to line 1500 when the user enters an empty name. - Line 2560 is missing: The search loop at line 2530 branches to
GOTO 2560on a name match, but line 2560 does not exist — execution falls through to line 2660, which works correctly as the next defined line, making this a deliberate gap-jump technique. - Typo in label at line 8700: The prompt reads
"WHAT IS THE NEW STUBJECT?"— “STUBJECT” instead of “SUBJECT”. - Print format mismatch at line 8660: The header printed reads
"NAME PART NO. COST IT/UN IN/S", suggesting a parts-inventory header was copied from another program rather than the tape-catalogue header used elsewhere. - Module 4 (line 4000): The “clear all data” option simply executes
RUN, which re-initialises all variables and arrays — a functional but destructive implementation with no confirmation prompt.
Content
Source Code
10 DIM A$(10,32)
11 LET R1=0
12 LET Z$="%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-%-"
20 FAST
25 CLS
30 POKE 16418,0
40 FOR N=1 TO 96
50 PRINT "% % % % % % % % ";
60 NEXT N
70 PRINT AT 2,5;" PROGRAM TAPE FILE "
80 PRINT AT 5,1;"%T%O% %E%N%T%E%R% %P%R%O%G%R%A%M%S";TAB 26;"%-% %1"
90 PRINT AT 7,1;"%T%O% %S%E%E% %P%R%O%G%R%A%M%S";TAB 26;"%-% %2"
100 PRINT AT 9,1;"%T%O% %S%A%V%E% %D%A%T%A% %O%N% %T%A%P%E";TAB 26;"%-% %3"
110 PRINT AT 11,1;"%T%O% %C%L%E%A%R% %A%L%L% %D%A%T%A";AT 11,26;"%-% %4"
120 PRINT AT 13,1;"%T%O% %P%R%I%N%T% %D%A%T%A% ";TAB 26;"%-% %5"
130 PRINT AT 15,1;"%T%O% %S%O%R%T% %D%A%T%A% ";TAB 26;"%-% %6"
180 PRINT AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:";AT 22,4;"ENTER ONE OF ABOVE :::";AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:"
190 SLOW
200 LET B$=INKEY$
210 IF B$="" THEN GOTO 180
220 IF CODE B$<29 OR CODE B$>34 THEN GOTO 180
230 FAST
240 POKE 16418,2
250 CLS
260 GOTO 1000*VAL B$
1000 FOR N=R1+1 TO 100
1010 GOSUB 9000
1020 PRINT "WHAT IS THE PROGRAM NAME?"
1030 SCROLL
1040 PRINT "PROGRAM NO. ";N;" (8 CHAR. MAX.)"
1050 SCROLL
1055 SLOW
1060 INPUT B$
1065 FAST
1070 IF B$="" THEN GOTO 1500
1080 LET A$(N, TO 8)=B$
1090 PRINT A$(N)
1100 GOSUB 9000
1110 SCROLL
1120 PRINT "WHAT IS THE PROGRAM SUBJECT?"
1125 SCROLL
1126 PRINT "(6 CHAR MAX)"
1130 SCROLL
1135 SLOW
1140 INPUT B$
1142 FAST
1145 IF LEN B$>6 THEN GOTO 1135
1150 LET A$(N,10 TO 15)=B$
1160 PRINT A$(N)
1170 GOSUB 9000
1190 PRINT "WHAT IS THE COUNTER LOCATION?"
1195 SCROLL
1196 PRINT "(6 CHAR MAX)"
1200 SCROLL
1205 SLOW
1210 INPUT B$
1212 FAST
1214 IF LEN B$>6 THEN GOTO 1205
1220 SCROLL
1230 LET A$(N,17 TO 22)=B$
1240 PRINT A$(N)
1250 GOSUB 9000
1260 PRINT "TAPE NO./SIDE? ";N;" (4 CHAR. MAX.)"
1270 SCROLL
1275 SLOW
1280 INPUT B$
1285 FAST
1290 IF LEN B$>4 THEN GOTO 1275
1300 SCROLL
1320 LET A$(N,24 TO 27)=B$
1330 PRINT A$(N)
1340 GOSUB 9000
1350 PRINT "MISC. INFO. OR CODE ?"
1351 SCROLL
1352 PRINT "(4 CHAR MAX)"
1355 SLOW
1360 INPUT B$
1365 FAST
1370 IF LEN B$>4 THEN GOTO 1355
1374 IF LEN B$=4 THEN GOTO 1390
1376 FOR I=1 TO 4-LEN B$
1380 LET B$=" "+B$
1385 NEXT I
1390 SCROLL
1400 LET A$(N,29 TO 32)=B$
1410 PRINT A$(N)
1420 NEXT N
1500 FAST
1510 CLS
1520 LET R1=N-1
1530 SLOW
1540 GOTO 20
1999 STOP
2000 FAST
2010 CLS
2020 POKE 16418,0
2030 FOR N=1 TO 192
2040 PRINT "% % % % ";
2050 NEXT N
2060 PRINT AT 2,8;" PROGRAM DATA "
2070 PRINT AT 5,1;"%T%O% %S%E%E% %A%L%L% %P%R%O%G%R%A%M% %D%A%T%A";TAB 28;"%-% %1"
2080 PRINT AT 7,1;"%T%O% %C%H%A%N%G%E% %P%R%O%G%R%A%M% %N%A%M%E";TAB 28;"%-% %2"
2090 PRINT AT 9,1;"%T%O% %S%E%E% %I%T%E%M% %D%A%T%A";TAB 28;"%-% %3"
2100 PRINT AT 11,1;"%T%O% %E%D%I%T% %D%A%T%A% %I%T%E%M%S";TAB 28;"%-% %4"
2180 PRINT AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:";AT 22,4;"ENTER ONE OF ABOVE :::";AT 22,4;"%E%N%T%E%R% %O%N%E% %O%F% %A%B%O%V%E% %:%:%:"
2190 SLOW
2200 LET B$=INKEY$
2210 IF B$="" THEN GOTO 2180
2220 IF CODE B$<29 OR CODE B$>32 THEN GOTO 2180
2230 FAST
2240 POKE 16418,2
2250 CLS
2260 GOTO (VAL B$*200)+2100
2300 SLOW
2310 FOR N=1 TO R1
2320 SCROLL
2340 SCROLL
2350 PRINT "NAME SUBJECT C/L T/NO MISC"
2360 SCROLL
2365 PRINT Z$
2370 SCROLL
2380 PRINT A$(N)
2382 SCROLL
2384 SCROLL
2386 SCROLL
2388 NEXT N
2390 PRINT "PRESS ENTER TO CONTINUE :::"
2392 INPUT B$
2395 GOTO 20
2500 PRINT AT 10,0;"WHAT IS THE PROGRAM NAME?"
2505 SLOW
2510 INPUT B$
2515 FAST
2520 FOR N=1 TO R1
2525 FAST
2530 IF A$(N, TO LEN B$)=B$ THEN GOTO 2560
2540 NEXT N
2542 CLS
2544 GOSUB 9000
2546 PRINT "PROGRAM NAME NOT IN FILE :::"
2547 GOSUB 9000
2548 GOSUB 9800
2550 GOTO 20
2660 FAST
2662 CLS
2664 GOSUB 9000
2666 PRINT "NAME SUBJECT C/L T/NO. MISC"
2668 SCROLL
2670 PRINT Z$
2672 SCROLL
2674 PRINT A$(N)
2676 GOSUB 9000
2678 PRINT AT 20,0;"IS THIS THE CORRECT PROGRAM NAME?"
2679 SLOW
2680 INPUT Y$
2682 FAST
2683 IF Y$(1)="N" THEN GOTO 2540
2684 SCROLL
2685 SCROLL
2686 PRINT "WHAT IS THE CORRECT NAME?"
2687 SLOW
2688 INPUT B$
2689 FAST
2690 LET A$(N, TO 8)=B$
2691 SCROLL
2692 SCROLL
2693 PRINT Z$
2694 SCROLL
2695 PRINT A$(N)
2696 SCROLL
2697 SCROLL
2698 GOSUB 9800
2699 GOTO 20
2700 CLS
2705 PRINT AT 10,1;"WHAT IS THE PROGRAM NAME?"
2710 SLOW
2715 INPUT B$
2720 FAST
2725 IF LEN B$>8 THEN GOTO 2710
2730 FOR N=1 TO R1
2735 IF A$(N, TO LEN B$)=B$ THEN GOTO 2760
2740 NEXT N
2745 SCROLL
2750 PRINT TAB 16-((LEN B$)/2);B$
2755 GOTO 2544
2760 CLS
2765 PRINT ,,,,"PROGRAM -";TAB 24;A$(N, TO 8)
2770 PRINT ,,"SUBJECT -";TAB 24;A$(N,10 TO 15)
2775 PRINT ,,"CTR. LOC. -";TAB 24;A$(N,17 TO 22)
2780 PRINT ,,"TP. NO/SD -";TAB 24;A$(N,24 TO 27)
2785 PRINT ,,"MISC. -";TAB 24;A$(N,29 TO 32)
2815 GOSUB 9800
2820 GOTO 20
2900 CLS
2905 PRINT AT 10,1;"WHAT IS THE PROGRAM NAME?"
2910 SLOW
2915 INPUT B$
2920 FAST
2925 IF LEN B$>6 THEN GOTO 2910
2930 FOR N=1 TO R1
2935 IF A$(N, TO LEN B$)=B$ THEN GOTO 2950
2940 NEXT N
2945 GOTO 2745
2950 CLS
2955 PRINT "NAME SUBJECT C/L T/NO. MISC"
2960 PRINT Z$;A$(N)
2965 PRINT ,,,,"<1> MISC","<3> CTR LOC","<2> SUBJECT","<4> TP NUM/SD",,,,"CHOOSE ONE?"
2967 SLOW
2970 INPUT B$
2972 FAST
2974 IF CODE B$<29 OR CODE B$>32 THEN GOTO 2967
2975 GOTO 8500+(100*VAL B$)
2999 GOTO 2999
3000 FAST
3002 CLS
3006 PRINT AT 10,10;"FILE NAME?"
3010 SLOW
3020 INPUT C$
3030 PRINT AT 12,0;"PREPARE THE RECORDER AND THEN PRESS ENTER :::"
3040 INPUT B$
3050 SAVE C$
3060 FAST
3070 CLS
3080 GOTO 20
4000 FAST
4010 CLS
4020 RUN
5000 PRINT AT 10,0;"SET UP PRINTER AND PRESS ENTER."
5010 INPUT B$
5020 FOR N=1 TO R1
5030 LPRINT
5040 LPRINT "NAME SUBJECT C/L T/NO. MISC"
5050 LPRINT "--------------------------------"
5060 LPRINT A$(N)
5070 NEXT N
5080 GOTO 20
6000 PRINT AT 8,0;"SORT BY?"
6010 PRINT ,"NAME (1)"
6020 PRINT ,"SUBJECT (2)"
6030 PRINT ,"CTR. LOC. (3)"
6040 PRINT ,"TP NUM/SD (4)"
6050 PRINT ,"MISC. (5)"
6055 SLOW
6060 LET B$=INKEY$
6065 IF CODE B$<29 OR CODE B$>33 THEN GOTO 6060
6066 FAST
6070 IF B$="1" THEN LET A=1
6080 IF B$="1" THEN LET B=8
6090 IF B$="2" THEN LET A=10
6100 IF B$="2" THEN LET B=15
6110 IF B$="3" THEN LET A=17
6120 IF B$="3" THEN LET B=22
6130 IF B$="4" THEN LET A=24
6140 IF B$="4" THEN LET B=27
6150 IF B$="5" THEN LET A=29
6160 IF B$="5" THEN LET B=32
6200 CLS
6210 LET N=R1
6220 LET N=INT (N/2)
6230 IF N=0 THEN GOTO 20
6240 LET J=1
6250 LET K=R1-N
6260 LET I=J
6270 LET L=I+N
6280 IF A$(I,A TO B)<A$(L,A TO B) THEN GOTO 6350
6290 LET B$=A$(I)
6300 LET A$(I)=A$(L)
6310 LET A$(L)=B$
6320 LET I=I-N
6330 IF I<1 THEN GOTO 6350
6340 GOTO 6270
6350 LET J=J+1
6360 IF J>K THEN GOTO 6220
6370 GOTO 6260
8600 PRINT ,,"WHAT IS THE NEW <MISC> INFO?"
8610 SLOW
8620 INPUT B$
8630 FAST
8640 IF LEN B$>4 THEN GOTO 8610
8650 LET A$(N,29 TO 32)=B$
8660 PRINT ,,"NAME PART NO. COST IT/UN IN/S";Z$;A$(N)
8670 GOSUB 9800
8680 GOTO 20
8700 PRINT ,,"WHAT IS THE NEW STUBJECT?"
8710 SLOW
8720 INPUT B$
8730 FAST
8740 IF LEN B$>6 THEN GOTO 8710
8750 LET A$(N,10 TO 15)=B$
8760 GOTO 8660
8800 PRINT ,,"WHAT IS THE NEW COUNTER?"
8810 SLOW
8820 INPUT B$
8830 FAST
8840 IF LEN B$>6 THEN GOTO 8810
8842 GOSUB 8000
8844 IF LEN B$<6 THEN GOSUB 8100
8850 LET A$(N,17 TO 22)=B$
8860 GOTO 8660
8900 PRINT ,,"WHAT IS THE NEW TAPE NO./SIDE?"
8910 SLOW
8920 INPUT B$
8930 FAST
8940 IF LEN B$>4 THEN GOTO 8910
8950 LET A$(N,24 TO 27)=B$
8960 GOTO 8660
9000 FOR I=1 TO 10
9010 SCROLL
9020 NEXT I
9030 RETURN
9800 PRINT AT 21,0;"PRESS ENTER TO CONTINUE :::"
9810 INPUT B$
9820 CLS
9830 RETURN
9998 SAVE "TAPE FIL%E"
9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
