--- title: "Carpooler" id: 51710 type: "computer_media" slug: "carpooler" url: "http://localhost/computer_media/carpooler/" markdown_url: "http://localhost/computer_media/carpooler.md" published_at: "2023-08-13T23:14:28+00:00" modified_at: "2026-04-03T07:59:18+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A fully-featured carpool scheduling database with add, delete, and date-filtered display, packing all records into a single two-dimensional string array." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - name: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" genre: - name: "Home" slug: "home" taxonomy: "genre" url: "http://localhost/type/home/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Carpooler (1982)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" related_products: - id: 12034 title: "The Carpooler" type: "product" url: "http://localhost/product/car-pooler/" media_type_tags: "Home" --- 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 `Q` and `W` are computed as `8+LEN D$` and `28+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 whether `A=1` or `A=2`, allowing a single display loop to serve both categories. - Input validation uses `LEN P$<8` to enforce date format length before accepting the value. - Delay loops such as `FOR N=1 TO 20: NEXT N` provide 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 the `DO 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 1000` is called immediately before `GOTO 560` at 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 `RETURN` at line 2999 is never reached in normal flow, as all paths from subroutine 2800 either GOTO 560 or GOTO 2550. ## 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 ```