Carpooler is a carpool management database program that stores up to 100 records, each tracking assignment date, destination, driver, riders’ initials, and departure time. Records are packed into a 100×65 character string array T$, with fixed-width fields allocated across each row (date at columns 1–8, destination 9–28, driver 29–38, riders 39–58, time 59–65). The program supports adding, deleting, and displaying records either by category (destinations or drivers) or filtered by date, with a tape save facility for data persistence. A machine code routine is invoked via USR 16720, called through a sequence of POKEs to addresses 16707–16712 that configure its behavior, likely implementing a fast screen clear or display routine.
Program Analysis
Program Structure
The program is organized into clearly separated functional modules accessed via GOSUB. The top-level flow lives at lines 500–580, which calls initialization, setup, menu, and function-dispatch routines in sequence. The main loop at line 580 returns to line 560 (the function display), making the menu system re-entrant.
| Line Range | Purpose |
|---|---|
| 100–150 | REM block containing embedded machine code (or data), GOTO 270 (non-existent line, falls through to 300) |
| 200–260 | Utility POKE loader: reads address/value pairs via INPUT and POKEs them into memory |
| 300–320 | Array dimensioning: C$(2,12) for category names, T$(100,65) for records |
| 500–580 | Main program loop: initialization, menu, function dispatch |
| 1000–1080 | Machine code call with POKE values 128 (enable mode) |
| 1100–1180 | Machine code call with POKE values 0 (disable/reset mode) |
| 1200–1299 | Title/splash screen with “CAR-POOL” and car graphic |
| 1300–1399 | Master menu display |
| 1400–1499 | Function selection display (Add/Delete/Display) |
| 2000–2999 | Add record logic, including duplicate detection |
| 3000–3499 | Delete record logic |
| 3500–3590 | Display all records for a category |
| 8000–8050 | Initialize category name array C$ |
| 8500–8520 | Quit confirmation |
| 9000–9060 | Save data to tape |
| 9100–9240 | List records by date |
Data Storage
All carpool records are stored in the two-dimensional string array T$(100,65), giving space for 100 records of 65 characters each. Fields within each row use fixed-width substrings:
- Columns 1–8: Date (MM/DD/YY)
- Columns 9–28: Destination (20 chars)
- Columns 29–38: Driver (10 chars)
- Columns 39–58: Riders’ initials (20 chars)
- Columns 59–65: Departure time (7 chars)
An empty record slot is detected by checking whether columns 1–8 equal eight spaces (" "). Deletion is implemented by overwriting an entire row with a 65-character blank string Z$ at line 3400.
Machine Code Interface
Two routines, at lines 1000–1080 and 1100–1180, POKE values into addresses 16707–16712 before calling USR 16720. The first routine POKEs 128 into all six locations; the second POKEs 0. The result is stored in C (unused thereafter), suggesting the USR call’s return value is incidental. This pattern is consistent with configuring a parameter block for a machine code screen utility — likely a fast CLS or inverse-video border effect — residing at address 16720. Addresses 16707–16712 fall in the ZX81 system variable region (specifically in the RAMTOP/display file area), which is an unusual choice and implies the machine code was loaded into RAM at a fixed address by the POKE loader at lines 200–260.
The line 100 REM block contains what appears to be the machine code payload: the REM statement holds binary data that the POKE loader routine (lines 200–260) would transfer to address 16720, bootstrapping the USR routine before the main program runs at line 500.
Key BASIC Idioms
- Dynamic field-width substring matching: variables
QandWare computed as8+LEN D$and28+LEN S$respectively, so that string comparisons match exactly the stored field width rather than requiring the user input to be padded. This avoids false mismatches due to trailing spaces. - The category display routine at lines 3500–3590 uses conditional assignments to swap the roles of driver and destination labels (
B$,K$) and field slice variables (L,H,Z,T) depending on whetherA=1orA=2, allowing a single display loop to serve both categories. - Input validation uses
LEN P$<8to enforce date format length before accepting the value. - Delay loops such as
FOR N=1 TO 20: NEXT Nprovide brief pauses for user feedback messages.
Duplicate Detection
Before adding a record, the subroutine at lines 2500–2999 scans all 100 slots for an existing record with the same date, destination, and driver. If a duplicate is found, it is displayed and the user is asked whether to proceed anyway. If the user confirms, execution jumps to line 2550 to find the next free slot, effectively allowing intentional duplicates.
Tape Save
The save routine at lines 9000–9060 prompts the user to prepare the recorder, then executes SAVE "CARPOO[L]" (where [L] is an inverse-L character encoding in the source). After saving, it jumps to line 500 to reinitialize, which re-dimensions the arrays — this would destroy any data not yet saved, so the save-before-quit workflow is important.
Bugs and Anomalies
- Line 150 executes
GOTO 270, which does not exist. On a ZX81/TS1000, this causes execution to continue at the next higher line, which is line 300. This is the intended behavior — it skips the POKE loader at lines 200–260 during normal program startup. - The instructions branch at lines 1241–1250 is unreachable: line 1240 always executes
GOTO 1299(RETURN), so theDO YOU NEED INSTRUCTIONS?prompt and the routine at 7000 (which does not appear in the listing) are never reached. - Line 1384 checks
IF A<1 OR A>2 THEN GOTO 550, but the menu also offers options 40, 50, and 99, which are handled by earlier IF statements. Any other out-of-range value correctly re-displays the menu. - At line 3496,
GOSUB 1000is called immediately beforeGOTO 560at line 3499 — the screen clear happens but the display is then immediately redrawn by line 560’s function display routine, making this call redundant. - The
RETURNat line 2999 is never reached in normal flow, as all paths from subroutine 2800 either GOTO 560 or GOTO 2550.
Content
Image Gallery
Source Code
100 REM E£RND7▘#▘ GOSUB #Q█TAN E£RND7▘#▘ GOSUB #▞?Q█F▌TAB [1]RNDE£RND7▘#▘ GOSUB #▞?Q█7▌TAB [J]RNDTAN E£RND7▘E▘ GOSUB #▞?Q█7▌TAB INT RNDTAN :-E£RND7)5 ▞4 GOSUB #6 COPYRNDQ[▒]7▌TAB LIST RNDE COPYRND$TAB DIM RNDTAN ▌# E£RND7▘? )5 GOSUB #:+ GOSUB #Q█$TAB /INKEY$ TAN <=#▞ ▘ ██████ GOSUB #£RND< GOSUB #WINKEY$ Y▞MYINKEY$ Y-MRNDINKEY$ Y▌MINKEY$ INKEY$ GOSUB #YINKEY$ 5#INKEY$ GOSUB [K]UINKEY$ INKEY$ XTAB #INKEY$ EWINKEY$ )5 GOSUB #6WINKEY$ FOR URNDINKEY$ XMRNDINKEY$ W#▌TAB #INKEY$ TAN
150 GOTO 270
200 INPUT A
220 INPUT B
230 PRINT B
240 POKE A,B
250 LET A=A+1
260 GOTO 220
300 DIM C$(2,12)
320 DIM T$(100,65)
500 GOSUB 1000
505 GOSUB 8000
510 GOSUB 1200
520 GOSUB 1000
550 GOSUB 1300
560 GOSUB 1400
570 IF B=1 THEN GOSUB 2000
576 IF B=2 THEN GOSUB 3000
578 IF B=3 THEN GOSUB 3500
580 GOTO 560
999 STOP
1000 REM
1010 POKE 16707,128
1020 POKE 16708,128
1030 POKE 16709,128
1040 POKE 16710,128
1050 POKE 16711,128
1060 POKE 16712,128
1070 LET C=USR 16720
1080 RETURN
1100 REM
1110 POKE 16707,0
1120 POKE 16708,0
1130 POKE 16709,0
1140 POKE 16710,0
1150 POKE 16711,0
1160 POKE 16712,0
1170 LET C=USR 16720
1180 RETURN
1200 REM
1210 PRINT AT 10,12;"CAR-POOL"
1220 PRINT AT 11,9;" "
1225 PRINT AT 12,11;"O██████O"
1228 PRINT AT 20,2;"HIT ENTER WHEN READY"
1229 INPUT Y$
1230 FOR N=1 TO 50
1235 NEXT N
1240 GOTO 1299
1241 PRINT AT 1,1;"DO YOU NEED INSTRUCTIONS ?"
1244 INPUT A$
1246 PRINT AT 3,1;A$
1248 IF A$="N" THEN GOTO 550
1250 GOTO 7000
1299 RETURN
1300 REM
1310 GOSUB 1000
1320 PRINT AT 1,7;"CAR-POOL CONTROL"
1330 PRINT AT 2,6;"MASTER MENU DISPLAY"
1340 PRINT AT 18,1;"ENTER NUMBER OF TYPE"
1342 PRINT AT 6,5;"1=MAINTAIN DESTINATIONS"
1344 PRINT AT 8,5;"2=MAINTAIN DRIVERS"
1366 PRINT AT 14,1;"***ENTER 40 TO LIST BY DATE"
1368 PRINT AT 15,1;"***ENTER 50 TO SAVE TO TAPE"
1369 PRINT AT 16,1;"***ENTER 99 TO QUIT "
1370 INPUT A
1372 PRINT AT 19,1;A
1377 IF A=40 THEN GOTO 9100
1380 IF A=99 THEN GOTO 8500
1382 IF A=50 THEN GOTO 9000
1384 IF A<1 OR A>2 THEN GOTO 550
1399 RETURN
1400 REM
1410 GOSUB 1000
1420 PRINT AT 1,8;"FUNCTION DISPLAY"
1422 PRINT AT 3,1;"ENTER NUMBER FOR FUNCTION"
1424 PRINT AT 4,1;"YOU WISH TO PERFORM"
1425 PRINT AT 6,5;"TYPE= ";C$(A)
1426 PRINT AT 10,2;"1=ADD A ";C$(A)
1428 PRINT AT 12,2;"2=DELETE A ";C$(A)
1440 PRINT AT 14,2;"3=DISPLAY ALL ";C$(A)
1442 PRINT AT 18,2;"99=QUIT THIS SECTION"
1444 INPUT B
1446 PRINT AT 20,1;B
1448 IF B=99 THEN GOTO 550
1450 IF B<1 OR B>4 THEN GOTO 560
1499 RETURN
2000 REM ADD LOGIC
2010 GOSUB 1000
2020 PRINT AT 1,10;C$(A)
2025 PRINT AT 2,10;"ADD DISPLAY"
2040 PRINT AT 5,0;"DATE OF ASSIGNMENT--MM/DD/YY"
2045 INPUT P$
2046 IF LEN P$<8 THEN GOTO 2040
2048 PRINT P$
2049 PRINT
2050 PRINT "DESTINATION"
2060 INPUT D$
2062 PRINT D$
2063 PRINT
2064 PRINT "DRIVER"
2066 INPUT S$
2068 PRINT S$
2069 PRINT
2070 PRINT "RIDERS INITIALS--E.G. GBG,BCS"
2072 INPUT E$
2074 PRINT E$
2080 PRINT "TIME OF DEPARTURE"
2082 INPUT F$
2084 PRINT F$
2100 PRINT AT 20,1;"ALL ABOVE CORRECT ? Y/N"
2110 INPUT Y$
2120 PRINT Y$
2130 IF Y$="N" THEN GOTO 2000
2152 GOSUB 2500
2200 LET T$(X,1 TO 8)=P$
2202 LET T$(X,9 TO 28)=D$
2204 LET T$(X,29 TO 38)=S$
2206 LET T$(X,39 TO 58)=E$
2208 LET T$(X,59 TO 65)=F$
2220 GOSUB 1000
2225 PRINT AT 2,2;"RECORD ADDED"
2229 PRINT
2232 PRINT "HIT ENTER KEY WHEN READY"
2234 INPUT G$
2236 GOSUB 1000
2499 RETURN
2500 REM
2510 GOSUB 1000
2512 LET Q=8+LEN D$
2514 LET W=28+LEN S$
2520 FOR N=1 TO 100
2530 IF D$=T$(N,9 TO Q) AND S$=T$(N,29 TO W) AND P$=T$(N,1 TO 8) THEN GOTO 2800
2540 NEXT N
2550 FOR R=1 TO 100
2560 IF T$(R,1 TO 8)=" " THEN GOTO 2700
2580 NEXT R
2600 PRINT AT 2,2;"NO MORE ROOM IN FILE"
2610 PRINT AT 4,2;"MUST DO SOME DELETES"
2620 FOR N=1 TO 20
2640 NEXT N
2642 GOTO 560
2700 LET X=R
2710 RETURN
2800 GOSUB 1000
2810 PRINT AT 2,2;"RECORD WITH SAME DATE"
2820 PRINT AT 3,2;"DEST, DRIVER EXISTS"
2840 PRINT
2842 PRINT "DATE: ";T$(N,1 TO 8)
2844 PRINT "DEST: ";T$(N,9 TO 28)
2846 PRINT "DRIVER: ";T$(N,29 TO 38)
2848 PRINT "TIME: ";T$(N,59 TO 65)
2850 PRINT AT 15,2;"SHOULD ADD STILL BE DONE ?"
2852 INPUT Y$
2854 PRINT Y$
2856 IF Y$="N" THEN GOTO 560
2858 IF Y$="Y" THEN GOTO 2550
2860 GOTO 2800
2999 RETURN
3000 REM
3010 GOSUB 1000
3020 PRINT AT 3,8;"DELETE SCREEN"
3030 PRINT
3040 PRINT AT 2,8;C$(A)
3050 PRINT AT 5,2;"DATE--MM/DD/YY"
3060 INPUT P$
3062 IF LEN P$<8 THEN GOTO 3050
3070 PRINT P$
3080 PRINT AT 8,2;"DESTINATION"
3082 INPUT D$
3084 PRINT D$
3086 PRINT AT 11,2;"DRIVER"
3088 INPUT S$
3090 PRINT S$
3095 LET G=1
3100 LET Q=8+LEN D$
3110 LET W=28+LEN S$
3112 FOR N=G TO 100
3114 IF P$=T$(N,1 TO 8) AND D$=T$(N,9 TO Q) AND S$=T$(N,29 TO W) THEN GOTO 3200
3116 NEXT N
3120 GOSUB 1000
3122 PRINT AT 2,2;"RECORD IS NOT ON FILE"
3124 FOR J=1 TO 20
3126 NEXT J
3130 GOTO 560
3200 GOSUB 1000
3210 PRINT AT 2,2;"IS THIS THE RECORD"
3211 PRINT AT 3,2;"TO DELETE ?"
3212 PRINT
3214 PRINT "DATE :";T$(N,1 TO 8)
3216 PRINT "DEST :";T$(N,9 TO 28)
3218 PRINT "DRIVER :";T$(N,29 TO 38)
3220 PRINT "TIME :";T$(N,59 TO 65)
3240 PRINT
3244 PRINT "ANSWER Y/N"
3246 INPUT Y$
3248 PRINT Y$
3250 IF Y$="Y" THEN GOTO 3400
3252 IF Y$="N" THEN LET G=N+1
3254 IF Y$="N" THEN GOTO 3112
3400 LET Z$=" "
3410 LET T$(N)=Z$
3411 GOSUB 1000
3412 PRINT AT 17,2;"RECORD DELETED"
3415 FOR N=1 TO 30
3420 NEXT N
3496 GOSUB 1000
3499 GOTO 560
3500 REM
3510 GOSUB 1100
3515 CLS
3517 LET B$="DRIVER :"
3518 LET K$="DEST :"
3520 IF A=1 THEN LET B$="DEST :"
3522 IF A=1 THEN LET K$="DRIVER :"
3524 LET Z=29
3525 LET T=38
3526 LET L=9
3527 LET H=28
3528 IF A=1 THEN LET L=29
3529 IF A=1 THEN LET H=38
3530 IF A=1 THEN LET Z=9
3531 IF A=1 THEN LET T=28
3532 FOR N=1 TO 100
3533 IF T$(N,1 TO 8)=" " THEN GOTO 3565
3534 PRINT B$;T$(N,Z TO T)
3535 PRINT K$;T$(N,L TO H)
3540 PRINT "DATE : ";T$(N,1 TO 8)
3545 PRINT "RIDERS ";T$(N,39 TO 58)
3550 PRINT "TIME :";T$(N,59 TO 65)
3560 PRINT
3565 NEXT N
3570 PRINT "HIT ENTER KEY WHEN READY"
3580 INPUT Y$
3590 GOTO 560
8000 REM
8010 LET C$(1)="DESTINATION"
8020 LET C$(2)="DRIVER"
8050 RETURN
8500 GOSUB 1000
8510 PRINT AT 2,2;"ARE YOU SURE QUIT IS"
8512 PRINT AT 3,2;"WHAT YOU WANT ? Y/N"
8514 INPUT L$
8516 PRINT AT 5,2;L$
8517 IF L$="Y" THEN STOP
8520 GOTO 550
9000 REM
9010 GOSUB 1000
9020 PRINT AT 2,2;"SET RECORDER FOR SAVE MODE"
9030 PRINT AT 4,2;"WHEN READY HIT ENTER KEY"
9040 INPUT L$
9050 SAVE "CARPOO[L]"
9060 GOTO 500
9100 REM
9110 GOSUB 1000
9120 PRINT AT 2,2;"ENTER DATE DESIRED"
9130 INPUT D$
9140 PRINT AT 4,8;D$
9160 FOR N=1 TO 20
9170 NEXT N
9174 GOSUB 1100
9176 PRINT AT 1,2;D$
9178 PRINT
9182 FOR N=1 TO 100
9184 IF D$<>T$(N,1 TO 8) THEN GOTO 9200
9185 PRINT "DEST.: ";T$(N,9 TO 28)
9186 PRINT "DRIVER: ";T$(N,29 TO 38)
9187 PRINT "RIDERS: ";T$(N,39 TO 58)
9188 PRINT "TIME: ";T$(N,59 TO 65)
9190 PRINT
9200 NEXT N
9220 PRINT "HIT ENTER WHEN READY"
9230 INPUT Y$
9240 GOTO 550
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.