Check

Developer(s): James DuPuy
Date: 1984
Type: Program
Platform(s): TS 2068
Tags: Finance

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):

ArrayTypeContent
D$(cx,4)StringDate as 4-character string (MMDD)
c(cx)NumericCheck number (0 = credit)
N$(cx,15)StringPayee or payer name (up to 15 chars)
s(cx)NumericAmount (negative = debit)
Z(cx)NumericTax-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.

Image Gallery

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

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.