This program is a mailing-list manager for a Timex/Sinclair User Group (T/SUG) based in Fort Worth, Texas, storing up to 50 member records of 90 characters each and up to 20 T/SUG records of 120 characters each in two fixed-length string arrays. An eight-option menu dispatches to subroutines via the idiom `GO SUB c*1000`, where the user’s numeric choice directly computes the target line number. The program loads a companion machine-code file at startup (line 1) and POKEs two bytes at addresses 26703–26704, likely to redirect or patch the LPRINT routine for a specific printer interface. Data is persisted to tape as named DATA files (`SAVE “Members” DATA m$()` / `SAVE “T/S U.G.” DATA g$()`), and the program itself plus the printer machine-code block (`SAVE “pr” CODE 64256,1111`) can also be saved from within the menu.
Program Structure
The program is organized around a central menu loop occupying lines 1–80, with eight subroutine blocks each anchored at a multiple of 1000:
| Lines | Purpose |
|---|---|
| 1–2 | Load machine-code file, POKE printer patch bytes |
| 3–8 | Variable documentation (REM), string constants, DIM arrays |
| 9–80 | Main menu display and dispatch loop |
| 1000–1060 | Compile membership list (keyboard input) |
| 2000–2580 | Print/view membership list |
| 3000–3080 | Compile T/SUG address list |
| 4000–4590 | Print/view T/SUG list |
| 5000–5080 | Print return address labels |
| 6000–6160 | Load both DATA files from tape |
| 7000–7060 | Save both DATA files to tape |
| 8000–8060 | Save program and printer machine-code block |
Key BASIC Idioms
Computed GO SUB: Line 60 uses GO SUB c*1000, where c is the user’s menu choice (1–8). This elegantly maps each integer directly to its subroutine entry point without a chain of IF statements, and is validated by the range check at line 50.
Fixed-length string array slicing: Both arrays use fixed 30-character field widths packed into a single string row. For example, m$(n, TO 30) is the name field, m$(n,31 TO 60) is the address, and m$(n,61 TO ) is the city/state/ZIP. This is a classic database-in-a-DIM technique that avoids the overhead of separate arrays.
Record-count recovery after LOAD: Because the DATA file always fills all 50 (or 20) rows, lines 6030–6070 iterate through the array after loading and count non-blank first characters to reconstruct the active record count into m (and similarly g). This compensates for the fact that a simple LOAD DATA restores raw bytes with no embedded length metadata.
Machine Code Usage
Line 1 loads an unnamed CODE block from tape immediately on startup. Lines 2 POKEs addresses 26703 and 26704 with values 5 and 251 respectively. Address 26703 (0x684F) falls in the upper RAM / system variable region and the two-byte value 0xFB05 is consistent with patching a jump or pointer — most likely redirecting the LPRINT channel to a specific printer interface port, a common requirement for third-party TS2068 printer add-ons.
Line 8050 saves the machine-code block back to tape: SAVE "pr" CODE 64256,1111. The start address 64256 (0xFB00) is in the high RAM / ROM shadow area, further confirming this is a small printer driver residing near the top of RAM.
Data Storage Design
DIM m$(50,90)— 50 members × 90 characters = 4,500 bytes for the membership array.DIM g$(20,120)— 20 T/SUG entries × 120 characters = 2,400 bytes; each entry has four 30-character address lines.- Arrays are saved and loaded by name:
SAVE "Members" DATA m$()andSAVE "T/S U.G." DATA g$(), matching the string constants ina$andb$. - The program itself is saved with
SAVE "mail list" LINE 1, causing auto-run from line 1 on reload.
Return Label Printing
Subroutine 5000 computes z=m+g (line 5000) to determine how many return address labels are needed — one for each member and one for each T/SUG entry — then LPRINTs the same hard-coded “T/SUG of Fort Worth, Texas / David Baulch / 4424 Geddes Ave. / Fort Worth, TX 76107” block z times. This is a simple but effective mailshot technique.
View/Print Toggle Logic
Both the membership (lines 2000–2580) and T/SUG (lines 4000–4590) output sections share an identical pattern: the user first chooses View or Print; View mode displays records on screen then offers a prompt that can loop back to redisplay (N), proceed to print (Y), or return to the menu (M). The GO TO 2020 / GO TO 4020 jumps re-enter the LPRINT loop after a screen-view session, avoiding code duplication for the print path.
Content
Source Code
1 CLS : PRINT AT 10,6; FLASH 1;"DO NOT STOP THE TAPE"; FLASH 0: LOAD ""CODE
2 POKE 26703,5: POKE 26704,251
3 REM Variables used- n,i,l,r=used for loops; b,d=used for counters; c=used for gosub to reach sub- routines; z=m+g for return labels; m=number of members; g=number of T/SUG's
4 LET t$="Mail List"
5 LET a$="Members"
6 LET b$="T/S U.G."
7 DIM m$(50,90)
8 DIM g$(20,120)
9 CLS
10 PRINT INVERSE 1;AT 2,(32-LEN t$)/2;t$
20 PRINT AT 4,4;"1) Compile Membership List";AT 6,4;"2) Print Membership List";AT 8,4;"3) Compile T/S U.G. List";AT 10,4;"4) Print T/S U.G. List";AT 12,4;"5) Print Return Labels";AT 14,4;"6) Load Data Files";AT 16,4;"7) Save Data Files";AT 18,4;"8) Save Program Logic"
30 PRINT FLASH 1;AT 20,6;"<ENTER> Your Choice."
40 INPUT c
50 IF c<1 OR c>8 THEN GO TO 40
60 CLS : GO SUB c*1000
70 GO TO 9
80 STOP
1000 PRINT "How many people are on the"'"membership list? ": INPUT m
1010 CLS : FOR n=1 TO m
1020 INPUT "Name: ";m$(n, TO 30): PRINT n;".";m$(n, TO 30)
1030 INPUT "Address: ";m$(n,31 TO 60): PRINT m$(n,31 TO 60)
1040 INPUT "City, State, ZIP Code: ";m$(n,61 TO ): PRINT m$(n,61 TO )
1050 PRINT : NEXT n
1060 RETURN
2000 PRINT "Would you like to (V)iew the","list or (P)rint the list? (V/P)": INPUT q$
2010 IF q$="V" OR q$="v" THEN GO TO 2500
2020 FOR n=1 TO m
2030 LPRINT m$(n, TO 30)
2040 LPRINT m$(n,31 TO 60)
2050 LPRINT m$(n,61 TO )
2060 LPRINT : LPRINT : LPRINT
2070 NEXT n
2080 RETURN
2500 CLS : FOR n=1 TO m
2510 PRINT m$(n, TO 30)
2520 PRINT m$(n,31 TO 60)
2530 PRINT m$(n,61 TO )
2540 PRINT
2550 NEXT n
2560 INPUT "PRINT? (Y/N) OR M FOR MENU ";q$
2570 IF q$="N" OR q$="n" THEN GO TO 2500
2575 IF q$="M" OR q$="m" THEN RETURN
2580 GO TO 2020
3000 PRINT "How many people are on the"'"T/S U.G. list? ": INPUT g
3010 CLS : FOR i=1 TO g
3020 INPUT "Address Line 1: ";g$(i, TO 30): PRINT i;".";g$(i, TO 30)
3030 INPUT "Address Line 2: ";g$(i,31 TO 60): PRINT g$(i,31 TO 60)
3040 INPUT "Address Line 3: ";g$(i,61 TO 90): PRINT g$(i,61 TO 90)
3050 INPUT "Address Line 4: ";g$(i,91 TO ): PRINT g$(i,91 TO )
3060 PRINT
3070 NEXT i
3080 RETURN
4000 PRINT "Would you like to (V)iew the"'"list or (P)rint the list? (V/P)": INPUT q$
4010 IF q$="V" OR q$="v" THEN GO TO 4500
4020 FOR i=1 TO g
4030 LPRINT g$(i, TO 30)
4040 LPRINT g$(i,31 TO 60)
4050 LPRINT g$(i,61 TO 90)
4060 LPRINT g$(i,91 TO )
4070 LPRINT : LPRINT
4080 NEXT i
4090 RETURN
4500 CLS : FOR i=1 TO g
4510 PRINT g$(i, TO 30)
4520 PRINT g$(i,31 TO 60)
4530 PRINT g$(i,61 TO 90)
4540 PRINT g$(i,91 TO )
4550 PRINT
4560 NEXT i
4570 INPUT "PRINT? (Y/N) OR M FOR MENU ";q$
4580 IF q$="N" OR q$="n" THEN GO TO 4500
4585 IF q$="M" OR q$="m" THEN RETURN
4590 GO TO 4020
5000 LET z=m+g
5010 FOR r=1 TO z
5020 LPRINT "T/SUG of Fort Worth, Texas"
5030 LPRINT "David Baulch"
5040 LPRINT "4424 Geddes Ave."
5050 LPRINT "Fort Worth, TX 76107"
5060 LPRINT : LPRINT
5070 NEXT r
5080 RETURN
6000 PRINT "Press <ENTER> to ""LOAD"" the"'"membership list.": INPUT d$
6010 LOAD a$ DATA m$()
6020 LET b=0
6030 FOR l=1 TO 50
6040 IF m$(l,1)=" " THEN GO TO 6060
6050 LET b=b+1
6060 NEXT l
6070 LET m=b
6080 CLS : PRINT "Press <ENTER> to ""LOAD"" the"'"T/S U.G. list.": INPUT d$
6090 LOAD b$ DATA g$()
6100 LET d=0
6110 FOR l=1 TO 20
6120 IF g$(l,1)=" " THEN GO TO 6140
6130 LET d=d+1
6140 NEXT l
6150 LET g=d
6160 RETURN
7000 PRINT "Set recorder up for a ""SAVE""."''"Put a new tape in the recorder."
7010 PRINT : PRINT "You will be saving two data"''"files. The first is the member-"''"ship list, and the second is the"''"T/S U.G. list."
7020 INPUT "Press <ENTER> to ""SAVE"" file 1";d$
7030 SAVE a$ DATA m$()
7040 INPUT "Press <ENTER> to ""SAVE"" file 2";d$
7050 SAVE b$ DATA g$()
7060 RETURN
8000 PRINT "Set recorder up for a ""SAVE""."''"Put a new tape in the recorder."
8010 PRINT : PRINT "You will be saving two parts of"''"the program. The first is the"''"program it self and the second"''"is the ""printer"" code."
8020 INPUT "Press <ENTER> to ""SAVE"" program ";d$
8030 SAVE "mail list" LINE 1
8040 INPUT "Press <ENTER> to ""SAVE"" ""pr"" CODE";d$
8050 SAVE "pr"CODE 64256,1111
8060 RETURN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
