--- title: "Check" id: 71454 type: "computer_media" slug: "check-2" url: "http://localhost/computer_media/check-2/" markdown_url: "http://localhost/computer_media/check-2.md" published_at: "2026-09-09T09:05:58+00:00" modified_at: "2026-09-09T09:35:55+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/check-2.png" excerpt: "A configurable checkbook ledger program that tracks debits, credits, check fees, and tax-deductible entries — with on-screen statements, printer output, and automatic file compaction." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "1984" slug: "year-1984" taxonomy: "post_tag" url: "http://localhost/tag/year-1984/" - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" genre: - name: "Finance" slug: "finance" taxonomy: "genre" url: "http://localhost/type/finance/" media_type: "Program" programmers: - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Check%20%281986%29%28Dupuy%2C%20James%29%28TS2068%29%28US%29%28Program%29.zip" tsrun_member: "Check (1986)(Dupuy, James)(TS2068)(US)(Program).tap" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2026/09/check-2.png" - url: "http://localhost/wp-content/uploads/2026/09/check.png" media_type_tags: "Finance" --- # Check Check is a checkbook management program that tracks debits, credits, check fees, and tax-deductible entries across a user-configurable file of 100 to 500 records. It stores transaction data in parallel arrays: date strings in `D$()`, check numbers in `c()`, payee/payer names in `N$()`, amounts in `s()`, and tax-deductibility flags in `Z()`. The statement routine displays up to five transactions at a time centered on the most recent entry, calculates a running balance, and flags overdrafts with an “OD” marker. When the file fills completely, a compaction routine retains the last 10 entries, carries forward the accumulated balance into a `reset` variable, and renumbers from entry 11 onward. Printer output is handled via `OPEN #2,"p"` and `CLOSE #2` stream I/O, printing a formatted statement with balance and optional tax-deductible totals. *** ### Program Structure The program is organized into clearly labeled sections separated by REM statements. Control flow is largely handled by a central menu dispatcher at line `280`, stored in the variable `menu` and reached via `GO TO menu` throughout. The main sections are: - Lines 10–150: Initialization — dimension arrays, set defaults, branch to menu - Lines 160–210: Date print subroutine - Lines 220–270: Dollar/cents formatting subroutine - Lines 280–490: Menu and dispatch loop - Lines 500–760: Debit entry routine - Lines 770–980: Credit entry routine - Lines 990–1390: On-screen statement and review - Lines 1400–1610: File-full compaction routine - Lines 1620–2030: LPRINT (printer) statement routine - Line 2040: Final `CLEAR`/`SAVE` (never reached during normal execution) ### Data Storage All transaction data is held in parallel arrays dimensioned at startup based on user-supplied `cx` (100–500): | Array | Type | Content | | --- | --- | --- | | `D$(cx,4)` | String | Date as 4-character string (MMDD) | | `c(cx)` | Numeric | Check number (0 = credit) | | `N$(cx,15)` | String | Payee or payer name (up to 15 chars) | | `s(cx)` | Numeric | Amount (negative = debit) | | `Z(cx)` | Numeric | Tax-deductible flag (0 or 1) | The variable `i` tracks the current number of entries; `j` is used as the working index into all arrays for a given transaction. ### Date Formatting Dates are stored as 4-character strings in MMDD format (e.g., `"0819"` for August 19). The print date subroutine at lines 160–210 suppresses leading zeros by checking whether the first or third character is `"0"` before printing it. The year is stored globally in `a$` (e.g., `"/85"`) and appended at line `200`, so changing the year via the “yr” menu option updates all subsequently printed dates without touching stored data. ### Dollar/Cents Formatting The subroutine at lines 220–270 uses `INT ABS s(j)` for the whole-dollar part and computes cents as `INT(100 * ABS s(j) - 100 * INT ABS s(j) + 0.5)`, adding 0.5 before truncating to round correctly. A leading zero is printed for cent values of 9 or less (lines 250–260). This subroutine is reused for both screen display and printer output, as well as for the balance line and tax-deductible total. ### Check Fee Handling An optional per-check fee (`cf`) is subtracted from each debit entry at line `670`. The fee is stored as a dollar amount and its cent value is reconstructed inline using `cf*100` fed into the `GO SUB 250` zero-padding test. The fee is also excluded when computing tax-deductible totals: line `1220` subtracts `cf` from the absolute amount before accumulating into `tax`. ### Statement and Review The on-screen statement (lines 990–1390) finds the highest populated entry by scanning backward from `cx` to the first non-zero `s(k)` value (lines 1040–1060), then displays a window of five entries from `q-4` to `q` (lines 1070–1170). The user can jump to any entry by typing a number; line `1380` limits direct navigation to entries 1–200. The balance line (lines 1240–1280) uses a separately computed `t$` string for alignment, with cents extracted from a fresh `ABS total` calculation. ### File Compaction When the file reaches capacity (`i=cx`), the compaction routine at lines 1460–1610 copies the last 10 entries to positions 1–10 in all five arrays, clears entries 11 through `cx`, and stores the accumulated balance of the dropped entries in `reset`. Subsequently, the total routine initializes `total=reset` (line 1190) so the balance carries forward correctly across compactions. ### Printer Output The LPRINT routine (lines 1620–2030) uses `OPEN #2,"p"` and `CLOSE #2` for stream-based printer output. The current value of `j` is saved into `p` at line `1730` and restored at line `1880` so the shared subroutines at lines 160 and 220 (which use `j`) do not corrupt the caller’s loop state. The printer routine recalculates `total` and `tax` independently from scratch rather than relying on previously computed values. ### Notable Techniques and Idioms - `LET reset=I` at line `40` initializes `reset` to zero using the already-set variable `i`, saving a literal. - The menu target is stored in `LET menu=280` (line `110`), allowing `GO TO menu` throughout — a common BASIC idiom for maintainability. - `f$= CHR$ 18+ CHR$ 1` (line `40`) builds a flash-attribute control sequence used repeatedly to highlight labels on screen. - Line `400` uses `INPUT ... LINE y$` for case-sensitive string input, with a special check for `"STOP "` (with trailing space) to allow graceful termination. - Correction handling in both debit (line `730`) and credit (line `950`) routines simply re-enters the entry loop at the PRINT header, reusing the same `j=i` index — effectively overwriting the current slot. - Line `2040` (`CLEAR :SAVE "CHECK" LINE 10`) exists outside normal program flow and acts as a development/reset utility line. ### Bugs and Anomalies - Line `730`: The correction branch (`y$="cor"`) goes to line `520` (PRINT header) without decrementing `i`, so `i` was already incremented at line `510`. Re-entering via `520` reuses the same `j`, so data is overwritten correctly, but `i` is not re-incremented — this works only because `j=i` was set at line `510` and `j` is not reset on the correction path. - Line `1380`: Navigation is capped at entry 200 regardless of `cx`, so if the user set `cx` above 200, entries 201 onward cannot be directly accessed via the review input. - Lines `1280` and `2000`: The `\\{16}\\{0}` token preceding `tax` suggests an `INK 0` attribute control code has been embedded before the variable name, likely a display artifact that may interfere with the conditional evaluation depending on interpreter handling. - The credit entry routine (lines 770–980) does not set `z(j)=0` or prompt for tax-deductibility, so credit entries always have whatever value was previously in `Z(j)` — likely zero from array initialization, but potentially non-zero after a compaction that reused the slot. ## Source Code ``` 10 REM \{20}\{1}"check" by James DuPuy\{20}\{0} 20 REM \{20}\{1}10/21/84 Version 1.3 \{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0}\{20}\{0} 30 INK 0:PAPER 7:BORDER 1:CLS 40 LET i=0:LET reset=I:LET cf=I:LET f$= CHR$ 18+ CHR$ 1 50 PRINT "Enter number of total files to be kept in this program."''"You must enter 100-500 and it should be about what you would use in a year or a given time orperiod of use. Also bear in mind that the more files there are, the longer it will take to save and load.":INPUT cx 60 IF cx<100 OR cx>500 THEN INPUT F$;"Enter 100-500 only! ";cx:GO TO 60 70 DIM D$(CX,4):DIM c(cx) 80 DIM N$(CX,15):DIM s(cx) 90 DIM Z(cx) 100 LET tax=0 110 LET menu=280 120 LET total=0 130 LET a$="/85" 140 LET k=0 150 GO TO menu 160 REM \{20}\{1}PRINT DATE ROUTINE\{20}\{0} 170 IF d$(j,1) <>"0" THEN PRINT D$(J,1); 180 PRINT d$(j,2);"/"; 190 IF d$(j,3) <>"0" THEN PRINT D$(J,3); 200 PRINT d$(j,4);a$ 210 RETURN 220 REM \{20}\{1}DOLLARS/CENTS ROUTINE\{20}\{0} 230 PRINT "$"; INT ABS s(j);"."; 240 LET cents= INT (100* ABS s(j)-100* INT ABS s(j)+.5) 250 IF cents <=9 THEN PRINT "0"; 260 PRINT cents; 270 RETURN 280 REM \{20}\{1}MENU ROUTINE\{20}\{1}\{20}\{0} 290 BORDER 6:BRIGHT 1:POKE 23609,20 300 CLS 310 PRINT AT 1,7;F$;"CHECK BOOK PROGRAM" 320 PRINT 330 PRINT TAB 9;"for the year 19";a$(2 TO 3) 340 PRINT AT 5,2;"CR - FOR CREDIT ENTRY"''" DB - FOR DEBIT ENTRY" 350 IF I <>0 THEN PRINT AT 9,2;"ST - FOR STATEMENT"''" PR - TO LPRINT STATEMENT"''" SV - TO SAVE PROGRAM & DATA"; AT 14,7;"BACK ON TO TAPE" 360 PRINT AT 16,2;"YR - TO CHANGE YEAR" 370 IF i=cx-1 THEN PRINT AT 18,2;F$;"LAST ENTRY BEFORE FULL FILE!" 380 PRINT AT 18,2;"CF - TO ENTER CHECK FEE.(";cf;")" 390 PLOT 0,0:DRAW 255,0:DRAW 0,175:DRAW -255,0:DRAW 0,-175 400 INPUT "Enter choice in lower case:"; LINE Y$:IF y$="STOP " THEN STOP 410 CLS 420 IF Y$="yr" THEN INPUT "Enter new year as (84):"; LINE a$:LET a$="/"+a$ 430 IF y$="cf" THEN INPUT "Enter check fee:";cf 440 IF y$="pr" THEN GO SUB 1620 450 IF y$="cr" THEN GO TO 770 460 IF y$="db" THEN GO TO 500 470 IF y$="st" THEN GO TO 990 480 IF y$="sv" THEN SAVE "check" LINE 280 490 GO TO 280 500 REM \{20}\{1}DEBIT ENTRY\{20}\{0} 510 LET i=i+1:LET j=i 520 PRINT AT 2,6;F$;"*** DEBIT ENTRY ***" 530 PRINT AT 5,0;"DATE: "; 540 INPUT "DATE? (0819)no \{20}\{1}/\{20}\{0} or year:"; LINE z$:IF LEN z$ <>4 THEN GO TO 540 550 LET d$(j)=z$ 560 GO SUB 160 570 PRINT 580 PRINT AT 7,0;"CHECK NUMBER: "; 590 INPUT "\{20}\{0}Enter CHECK # :";c(j):PRINT c(j) 600 PRINT AT 9,0;"PAYEE: "; 610 INPUT "Name?:"; LINE z$:IF z$="" THEN GO TO 610 620 LET n$(j)=z$ 630 PRINT n$(j) 640 PRINT AT 11,0;"AMOUNT: "; 650 INPUT "Amount? :";s(j) 660 LET s(j)=-s(j):GO SUB 220 670 IF cf>0 THEN LET s(j)=s(j)-cf:PRINT :PRINT "+ .";:LET cents=cf*100:GO SUB 250:PRINT " Fee= ";:GO SUB 220:PRINT " TOTAL" 680 LET z(j)=0:INPUT F$;"Tax Deductable?(Y/\{20}\{1}ENT\{20}\{0}) :";y$:IF y$="y" OR y$="Y" THEN LET Z(j)=1:PRINT AT 14,10;F$;"TAX DEDUCTABLE" 690 FOR n=1 TO 60:NEXT n 700 PRINT AT 18,0;"ENTER (DB) FOR ANOTHER DEBIT,","ENTER (COR) FOR CORRECTION,","PRESS \{20}\{1}ENTER\{20}\{0} FOR MENU." 710 INPUT "Enter in lower case:"; LINE y$:IF y$="c" THEN COPY 720 CLS 730 IF y$="cor" THEN GO TO 520 740 IF i=cx THEN GO TO 990 750 IF y$="db" THEN GO TO 500 760 GO TO menu 770 REM \{20}\{1}CREDIT ENTRY\{20}\{0} 780 LET i=i+1:LET j=i 790 PRINT AT 2,6;F$;"*** CREDIT ENTRY ***" 800 PRINT AT 5,0;"DATE: "; 810 INPUT "DATE? (0819)no \{20}\{1}/\{20}\{0} or year:"; LINE z$:IF LEN z$ <>4 THEN GO TO 810 820 LET d$(j)=z$ 830 GO SUB 160 840 PRINT 850 PRINT AT 7,0;"PAYER: "; 860 INPUT "Name?:"; LINE z$:IF z$="" THEN GO TO 860 870 LET n$(j)=z$ 880 PRINT n$(j) 890 PRINT AT 9,0;"AMOUNT: "; 900 INPUT "Amount? ";s(j) 910 GO SUB 220 920 PRINT AT 18,0;"ENTER (COR) FOR CORRECTION","ENTER (CR) FOR ANOTHER CREDIT","PRESS \{20}\{1}ENTER\{20}\{0} FOR MENU" 930 INPUT "Enter in lower case:"; LINE y$:IF y$="c" THEN COPY 940 CLS 950 IF y$="cor" THEN GO TO 790 960 IF i=cx THEN GO TO 990 970 IF y$="cr" THEN GO TO 770 980 GO TO menu 990 REM \{20}\{1}STATEMENT ROUTINE\{20}\{0} 1000 CLS 1010 PRINT AT 0,7;F$;"**** STATEMENT****" 1020 IF cf>0 THEN PRINT "Check fee is included in amount.":GO TO 1040 1030 PRINT 1040 FOR k=cx TO 1 STEP -1 1050 IF s(k)=0 THEN NEXT k 1060 LET q=k 1070 FOR j=q-4 TO q 1080 IF j<1 THEN NEXT j 1090 GO SUB 160 1100 IF c(j)=0 THEN PRINT :GO TO 1130 1110 IF z(j) THEN PRINT TAB 10;"CHECK #: ";c(j);" ";F$;"\{20}\{1}TD\{20}\{0}":GO TO 1130 1120 PRINT TAB 10;"CHECK #: ";C(J) 1130 PRINT " ";n$(j); TAB (24- LEN STR$ INT ABS s(j)); 1140 GO SUB 220 1150 IF S(J)>0 THEN PRINT "CR"; 1160 PRINT 1170 NEXT J 1180 REM \{20}\{1}TOTAL ROUTINE\{20}\{0} 1190 LET total=reset:LET tax=reset 1200 FOR t=1 TO k 1210 LET total=total+s(t) 1220 IF z(t) THEN LET tax=tax+(ABS s(t))-cf 1230 NEXT t 1240 LET cents= INT (100*(ABS total- INT ABS total)+.5) 1250 LET t$= STR$ INT (ABS total) 1260 PRINT AT 18,0;"\{20}\{1}BALANCE:\{20}\{0}$";T$;".";:GO SUB 250 1270 IF total<0 THEN PRINT "\{20}\{1}*OD\{20}\{0}"; 1280 IF \{16}\{0}tax <>0 THEN LET t$= STR$ INT (tax):LET cents= INT (100*(tax- INT tax)+.5):PRINT ":\{20}\{1}TD:\{20}\{0}$";t$;".";:GO SUB 250 1290 PRINT AT 19,0;"LAST ENTRY:";q 1300 IF i=cx-1 THEN PAUSE 100:PRINT AT 19,0;F$;"FINAL ENTRY BEFORE FULL FILE" 1310 PRINT AT 20,0;"Enter number to review, ENTER"; AT 21,0;"for menu, C to copy." 1320 IF i=cx THEN PAUSE 100:PRINT AT 21,0;F$;"File Full:\{20}\{1}ENTER\{20}\{0} to Renumber" 1330 INPUT "Enter in lower case(#,C):";y$ 1340 IF y$="c" THEN COPY :GO TO 1330 1350 CLS 1360 IF y$="" AND i=cx THEN GO TO 1400 1370 IF CODE y$<48 OR CODE y$>57 THEN GO TO menu 1380 IF VAL y$ >=1 AND VAL y$<201 THEN LET q= VAL y$:GO TO 1070 1390 CLS :GO TO menu 1400 PRINT F$;"FILE IS NOW FULL." 1410 PRINT AT 6,0;"\{20}\{1}ENTER\{20}\{0} - to dump all but last"'"10 entries." 1420 PRINT AT 9,0;"MU - for menu"; AT 11,0;"PR - to print out all ";cx;" checks" 1430 INPUT y$:IF y$="" THEN PAUSE 60:INPUT "Are you sure?(Y/N):"; LINE y$:IF y$="n" THEN GO TO 1430 1440 IF y$="mu" THEN GO TO menu 1450 IF y$="pr" THEN LET u=1:GO SUB 1730:CLS :GO TO 1400 1460 LET t2=0 1470 FOR j=cx-9 TO cx 1480 LET d$(j-(cx-10))=d$(j) 1490 LET c(j-(cx-10))=c(j) 1500 LET n$(j-(cx-10))=n$(j) 1510 LET s(j-(cx-10))=s(j) 1520 LET t2=t2+s(j) 1530 NEXT j 1540 LET reset=total-t2 1550 FOR j=11 TO cx 1560 LET d$(j)="" 1570 LET c(j)=0 1580 LET n$(j)="" 1590 LET s(j)=0 1600 NEXT j 1610 LET i=10:CLS :GO TO 990 1620 REM \{20}\{1}\{20}\{1}LPRINT ROUTINE\{20}\{0} 1630 CLS 1640 PRINT F$;" STATEMENT TO PRINTER", 1650 PRINT AT 3,0;"MU - for menu"; AT 5,0;"ALL - to print entire file."; AT 7,0;"1-";cx;" - to print out from that number to present." 1660 PRINT AT 18,0;"Enter choice in lower case." 1670 INPUT y$:IF y$="" THEN GO TO 1620 1680 IF y$="mu" THEN GO TO menu 1690 IF y$="all" THEN LET u=1:GO TO 1730 1700 IF CODE y$<48 OR CODE y$>57 THEN GO TO 1620 1710 LET u= VAL y$ 1720 IF s(u)=0 THEN PRINT AT 20,0;"There are no files at ";u'"Please reenter.":PAUSE 120:GO TO 1620 1730 LET p=j:OPEN #2,"p" 1740 PRINT "\{20}\{1}********** STATEMENT ***********\{20}\{0}":PRINT 1750 IF cf>0 THEN PRINT "Check fee is included in amount.":PRINT 1760 FOR j=u TO i 1770 IF s(j)=0 THEN GO TO 1860 1780 GO SUB 160 1790 IF c(j)=0 THEN PRINT :GO TO 1820 1800 IF z(j) THEN PRINT TAB 10;"CHECK #: ";c(j);" ";"\{20}\{1}TD\{20}\{0}":GO TO 1820 1810 PRINT TAB 10;"CHECK #: ";c(j) 1820 PRINT " ";n$(j); TAB (24- LEN STR$ INT ABS s(j)); 1830 GO SUB 220 1840 IF s(j)>0 THEN PRINT "CR"; 1850 PRINT 1860 NEXT j 1870 PRINT :PRINT 1880 LET j=p 1890 LET total=0 1900 LET tax=0 1910 FOR t=1 TO i 1920 IF s(t)=0 THEN GO TO 1950 1930 IF z(t) THEN LET tax=tax+(ABS s(t))-cf 1940 LET total=total+s(t) 1950 NEXT t 1960 LET cents= INT (100*(ABS total- INT ABS total)+.5) 1970 LET t$= STR$ ABS INT total 1980 PRINT "\{20}\{1}\{20}\{0}\{20}\{0}\{20}\{1}BALANCE :\{20}\{0} $\{20}\{0}";T$;".";:GO SUB 250 1990 IF TOTAL<0 THEN PRINT "\{20}\{1}*OD\{20}\{0}" 2000 IF \{16}\{0}tax <>0 THEN LET t$= STR$ INT (tax):LET cents= INT (100*(tax- INT tax)+.5):PRINT "\{20}\{1}TAX DEDUCTABLE \{20}\{0} $";t$;".";:GO SUB 250 2010 PRINT ''''' 2020 CLOSE #2 2030 RETURN 2040 CLEAR :SAVE "CHECK" LINE 10 ```