--- title: "The Coupon Manager" id: 51441 type: "computer_media" slug: "the-coupon-manager" url: "http://localhost/computer_media/the-coupon-manager/" markdown_url: "http://localhost/computer_media/the-coupon-manager.md" published_at: "2023-08-05T14:59:57+00:00" modified_at: "2026-04-04T20:18:06+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A practical coupon-organizer program that stores up to 180 coupons across 18 product categories, with machine code tricks for fast display and search-by-store functionality." 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/Coupon%20Manager%2C%20The%20%281982%29%28Timex%29%28US%29%28TS1000%29%28Program%29.zip" mediadate: "1982" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" images: - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260404-ewsy.png" - url: "http://localhost/wp-content/uploads/2023/08/SCR-20260404-ewrl.png" - url: "http://localhost/wp-content/uploads/2023/08/Timex-The-Coupon-Manager.jpg" related_products: - id: 14300 title: "Coupon Manager" type: "product" url: "http://localhost/product/coupon-manager/" media_type_tags: "Home" --- # The Coupon Manager The Coupon Manager is a household coupon organizer that stores up to 10 coupons each across 18 product categories, recording store name, brand description, start date, and expiration date for each coupon. Data is held in a 180-row by 46-column string array T$, with a parallel 18-element C$ array holding category names. The program embeds Z80 machine code in the REM statement at line 100, invoked via USR 16720, which appears to implement a custom display or memory-clear routine; additional POKE sequences at addresses 16707–16712 configure machine code parameters before each USR call. Coupons can be retrieved either by category or by store name, with a linear search through T$ comparing entered store names against stored records. The program includes tape save functionality, writing the entire program (including the T$ data array) to cassette using the SAVE command. *** ## Program Analysis ### Program Structure The program is organized into clearly delineated functional blocks accessed via `GOSUB`. The main loop runs from line `500` through `580`, repeatedly calling menu and function-selection routines. The overall flow is: 1. Lines `300–320`: Declare the two primary arrays (`C$` and `T$`). 2. Lines `500–580`: Main control loop — initialize display, load categories, show splash, display master menu, display function menu, dispatch to add/delete/display. 3. Lines `1000–1180`: Display utility routines (machine code invocation with POKE configurations). 4. Lines `1200–1299`: Splash/title screen. 5. Lines `1300–1399`: Master menu with 18 categories plus special entries for store listing, save, and quit. 6. Lines `1400–1499`: Function selection menu (add, delete, display). 7. Lines `2000–2999`: Coupon add logic, including slot-finding subroutine at `2500`. 8. Lines `3000–3499`: Delete logic. 9. Lines `3500–3590`: Display-all-of-type logic. 10. Lines `8000–8050`: Populate category name array `C$`. 11. Lines `8500–8520`: Quit confirmation. 12. Lines `9000–9060`: Tape save routine. 13. Lines `9100–9240`: Search and display by store name. ### Data Model Two string arrays carry all persistent data: | Array | Dimensions | Purpose | | --- | --- | --- | | `C$(18,12)` | 18 rows × 12 chars | Category names (e.g., “RESTAURANT”, “MEAT”) | | `T$(180,46)` | 180 rows × 46 chars | Coupon records, 10 per category | Each row of `T$` uses fixed-width substring slices: | Columns | Field | | --- | --- | | 1–2 | Category number (zero-padded) | | 3–5 | Record number (zero-padded) | | 6–15 | Store/place of usage (10 chars) | | 16–30 | Brand name / description (15 chars) | | 31–38 | Start date MM/DD/YY (8 chars) | | 39–46 | Expiration date MM/DD/YY (8 chars) | Category `A` uses rows `A*10-9` through `A*10`, giving exactly 10 slots per category for a total of 180 records. ### Machine Code Usage Line `100` contains a large block of Z80 machine code embedded in a `REM` statement. The entry point is at address 16720 (decimal), called via `USR 16720` at lines `1070` and `1170`. Before each call, six consecutive memory locations (16707–16712) are POKEd with either `128` (lines `1010–1060`, routine at `1000`) or `0` (lines `1110–1160`, routine at `1100`). The machine code likely uses these bytes as parameters to control the display — possibly toggling a custom display driver or clearing/setting a screen region. The REM data also includes what appear to be multiple independent routines at different offsets within the block, given the presence of several `C9` (RET) opcodes interspersed throughout. ### Key BASIC Idioms - **Fixed-width substring assignment**: Fields are stored by writing into specific column slices of `T$(X, col TO col)`. Because BASIC string arrays are fixed-width, this acts as a simple flat-file record format. - **Zero-padding**: Lines `2212–2218` manually prepend “0” characters to category and record numbers when they are less than 10 or 100, respectively, ensuring consistent 2- and 3-digit file numbers for reliable string comparison during search. - **Linear search**: The delete routine (line `3090–3150`) and the store-name search (line `9182–9200`) both use `FOR N=1 TO 180` loops with conditional branching — a straightforward sequential scan. - **Delay loops**: Empty `FOR/NEXT` loops (e.g., lines `1230–1235`, `2820–2840`) serve as timing delays for display pauses. ### Notable Techniques The tape save at line `9050` uses `SAVE "COUPO%N"` — the `%N` renders as an inverse-video “N” in the filename. Saving the program with its data arrays intact means the entire coupon database is preserved on tape alongside the code, providing a simple persistence mechanism without needing a separate data file. Lines `150` and `270` interact in a noteworthy way: line `150` jumps to `270`, but line `270` does not exist in the listing. This is used as a technique to skip over the `INPUT/POKE` loader utility at lines `200–260` during normal execution, while still allowing those lines to be accessed manually if needed. The store-name search at line `9184` compares `D$` against `T$(N,6 TO D)` where `D=5+LEN D$`. This dynamically sizes the comparison window to match the entered store name length, avoiding false mismatches due to trailing spaces — a careful approach to variable-length string matching within a fixed-width field. ### Bugs and Anomalies - **Delete uses wrong variable**: Line `3410` writes the blank string to `T$(X)`, but the correct variable found during the search loop (line `3100`) is `N`, not `X`. `X` is the add-routine’s slot pointer and may hold an unrelated value, so the wrong record could be blanked. - **C$(13) out of sequence**: In the category initialization block (lines `8000–8044`), `C$(13)` (“PET FOOD”) is assigned at line `8040`, after `C$(14)` through `C$(17)`. This is cosmetically inconsistent but functionally harmless. - **Category 13 missing from add/display**: No `C$(13)` row is declared between `C$(12)` and `C$(14)` in sequential order, but the array is populated correctly at line `8040`; the master menu does list “13=PET FOOD”, so this is not a real omission. - **Instructions branch unreachable**: Lines `1241–1250` (the “DO YOU NEED INSTRUCTIONS?” prompt) are skipped by an unconditional `GOTO 1299` at line `1240`, making the instruction pathway dead code. Line `7000`, which would contain the instructions, does not appear in the listing at all. - **B=4 accepted silently**: The function menu guard at line `1450` rejects `B<1 OR B>4`, meaning `B=4` passes through but has no corresponding `IF B=4` handler in the dispatch block (lines `570–578`), causing it to loop back to `560` doing nothing. ## Source Code ``` 100 REM 2AC40231591ED4A3680C900002AC40231591ED4A6F36802B5C29D402AC40231591ED4A6F3680235C2AF40C900000000000002AC402312A1ED4A6F3680235C2CF40C9000000000E162AC402311210620ED5A22FF403688235C2F0402AFF40DC2E940C95610000000002AC40231F011210ED4AE15ED5A3680DC21841C9000000000000000000000000000795C600108080808080800000000ED5BC4013ED533C413E6323E413E163240413E5324141ED4B3E41214341EDB03A41413DC265412A3C4111210ED5A223C41EB3A40413D3240413C475C26341C9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000 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$(18,12) 320 DIM T$(180,46) 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;"COUPON" 1220 PRINT AT 11,10;"MANAGEMENT" 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;"COUPON MANAGEMENT" 1330 PRINT AT 2,6;"MASTER MENU DISPLAY" 1340 PRINT AT 18,1;"ENTER NUMBER OF TYPE" 1350 PRINT AT 4,1;"1=RESTAURANT 10=CONDIMENTS" 1352 PRINT AT 5,1;"2=PASTA PROD. 11=DAIRY GOODS" 1354 PRINT AT 6,1;"3=DRINKS 12=BAKING ITEMS" 1356 PRINT AT 7,1;"4=CEREALS 13=PET FOOD" 1358 PRINT AT 8,1;"5=SNACKS 14=COSMETICS" 1360 PRINT AT 9,1;"6=MEAT 15=PAPER GOODS" 1362 PRINT AT 10,1;"7=POULTRY 16=CLEANING" 1364 PRINT AT 11,1;"8=FISH 17=MEDICINE" 1366 PRINT AT 12,1;"9=VEGETABLES 18=OTHER" 1367 PRINT AT 14,1;"***ENTER 40 TO LIST BY STORE" 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>99 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,4;"1=ADD A COUPON" 1428 PRINT AT 12,4;"2=DELETE A COUPON" 1440 PRINT AT 14,4;"3=DISPLAY ALL OF TYPE ";A 1442 PRINT AT 18,4;"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,5;"COUPON ADD DISPLAY" 2030 PRINT AT 2,5;"FOR TYPE ";C$(A) 2040 PRINT AT 5,0;"ENTER PLACE OF USAGE" 2045 INPUT P$ 2048 PRINT P$ 2049 PRINT 2050 PRINT "ENTER BRAND NAME OR DESCRIPT." 2060 INPUT D$ 2062 PRINT D$ 2063 PRINT 2064 PRINT "ENTER START DATE--MM/DD/YY" 2066 INPUT S$ 2068 PRINT S$ 2069 PRINT 2070 PRINT "ENTER EXPIRE DATE--MM/DD/YY" 2072 INPUT E$ 2074 PRINT E$ 2100 PRINT AT 20,1;"ALL ABOVE CORRECT ? Y/N" 2110 INPUT Y$ 2120 PRINT Y$ 2130 IF Y$="N" THEN GOTO 2000 2150 LET X=A*10-9 2152 GOSUB 2500 2200 LET T$(X,6 TO 15)=P$ 2202 LET T$(X,16 TO 30)=D$ 2204 LET T$(X,31 TO 38)=S$ 2206 LET T$(X,39 TO 46)=E$ 2208 LET T$(X,1 TO 2)=STR$ A 2210 LET T$(X,3 TO 5)=STR$ X 2212 IF A<10 THEN LET T$(X,1 TO 1)="0" 2214 IF A<10 THEN LET T$(X,2 TO 2)=STR$ A 2216 IF X<100 THEN LET T$(X,3 TO 3)="0" 2218 IF X<100 THEN LET T$(X,4 TO 5)=STR$ X 2220 GOSUB 1000 2225 PRINT AT 2,2;"NUMBER ASSIGNED IS ";T$(X,1 TO 5) 2227 PRINT "FILE BY THIS NUMBER" 2229 PRINT 2232 PRINT "HIT ENTER KEY WHEN READY" 2234 INPUT G$ 2236 GOSUB 1000 2499 RETURN 2500 REM 2510 IF X>A*10 THEN GOTO 2800 2515 IF T$(X,1 TO 2)<>" " THEN GOTO 2700 2520 RETURN 2700 LET X=X+1 2710 GOTO 2510 2800 GOSUB 1000 2810 PRINT AT 2,2;"NO MORE ROOM IN ";C$(A) 2815 PRINT "YOU MUST DELETE ONE" 2817 PRINT "TO MAKE ROOM" 2820 FOR N=1 TO 40 2840 NEXT N 2850 GOTO 560 2999 RETURN 3000 REM 3010 GOSUB 1000 3020 PRINT AT 2,8;"DELETE SCREEN" 3030 PRINT 3040 PRINT AT 4,8;"TYPE IS ";C$(A) 3050 PRINT AT 6,2;"ENTER FILE NUMBER" 3060 INPUT Q$ 3070 PRINT AT 15,2;Q$ 3080 LET V$=Q$ 3084 LET S1=LEN V$ 3086 IF S1<5 THEN LET V$=V$+" " 3090 FOR N=1 TO 180 3100 IF V$=T$(N,1 TO 5) THEN GOTO 3400 3150 NEXT N 3170 PRINT AT 18,2;"COUPON NOT ON FILE" 3180 FOR N=1 TO 40 3190 NEXT N 3200 GOSUB 1000 3210 RETURN 3400 LET Z$=" " 3410 LET T$(X)=Z$ 3412 PRINT AT 17,2;"COUPON DELETED" 3415 FOR N=1 TO 30 3420 NEXT N 3499 RETURN 3500 REM 3510 GOSUB 1100 3515 CLS 3530 FOR N=A*10-9 TO A*10 3531 IF T$(N,1 TO 5)=" " THEN GOTO 3565 3535 PRINT "STORE ";T$(N,6 TO 15) 3540 PRINT "BRAND ";T$(N,16 TO 30) 3545 PRINT "START ";T$(N,31 TO 38) 3550 PRINT "END ";T$(N,39 TO 46) 3555 PRINT "FILE ";T$(N,1 TO 5) 3560 PRINT 3565 NEXT N 3570 PRINT "HIT ENTER KEY WHEN READY" 3580 INPUT Y$ 3590 GOTO 560 8000 REM 8010 LET C$(1)="RESTAURANT" 8012 LET C$(2)="PASTA PROD." 8014 LET C$(3)="DRINKS" 8016 LET C$(4)="CEREALS" 8018 LET C$(5)="SNACKS" 8020 LET C$(6)="MEAT" 8022 LET C$(7)="POULTRY" 8024 LET C$(8)="FISH" 8026 LET C$(9)="VEGETABLES" 8028 LET C$(10)="CONDIMENTS" 8030 LET C$(11)="DAIRY PRODUCTS" 8032 LET C$(12)="BAKING ITEMS" 8034 LET C$(14)="COSMETICS" 8036 LET C$(15)="PAPER GOODS" 8038 LET C$(16)="CLEANING" 8040 LET C$(13)="PET FOOD" 8042 LET C$(17)="MEDICINE" 8044 LET C$(18)="OTHER" 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 "COUPO%N" 9060 GOTO 500 9100 REM 9110 GOSUB 1000 9120 PRINT AT 2,2;"ENTER STORE NAME DESIRED" 9130 INPUT D$ 9140 PRINT AT 4,8;D$ 9150 LET D=5+LEN D$ 9160 FOR N=1 TO 20 9170 NEXT N 9174 GOSUB 1100 9176 PRINT AT 1,2;D$ 9178 PRINT 9180 PRINT "BRAND FILE NO." 9182 FOR N=1 TO 180 9184 IF D$<>T$(N,6 TO D) THEN GOTO 9200 9186 PRINT T$(N,16 TO 30);" ";T$(N,1 TO 5) 9190 PRINT 9200 NEXT N 9220 PRINT "HIT ENTER WHEN READY" 9230 INPUT Y$ 9240 GOTO 550 ```