--- title: "Check" id: 55607 type: "computer_media" slug: "check" url: "http://localhost/computer_media/check/" markdown_url: "http://localhost/computer_media/check.md" published_at: "2024-06-30T13:38:16+00:00" modified_at: "2026-04-03T07:59:07+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/06/SCR-20240630-irpl.png" excerpt: "A full-featured checkbook manager that packs dates, check numbers, and payee codes into single numeric fields using a clever base-1,000,000 encoding scheme." 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: "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/" indiv: - name: "Dale F Lipinski" slug: "dale-f-lipinski" taxonomy: "indiv" url: "http://localhost/indiv/dale-f-lipinski/" genre: - name: "Home" slug: "home" taxonomy: "genre" url: "http://localhost/type/home/" media_type: "Cassette" programmers: - name: "Dale F Lipinski" slug: "dale-f-lipinski" taxonomy: "indiv" url: "http://localhost/indiv/dale-f-lipinski/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Check%20%28198x%29%28Dale%20Lipinski%20Software%29%28TS1000%29%28US%29%28Cassette%29.zip" mediadate: "198" producer_company: - id: 11048 title: "Dale Lipinski Software" type: "company" url: "http://localhost/company/dale-lipinski-software/" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20240630-irpl.png" related_content: - id: 12102 title: "Check" type: "product" url: "http://localhost/product/check/" media_type_tags: "Home" --- Check is a checkbook balancing program that stores up to 207 transaction entries and 207 payee names in parallel arrays, encoding check numbers and dates together into single floating-point values using a base-1,000,000 scheme. Each transaction record in the two-dimensional array `A()` packs the payee index combined with the check number, the reconciliation status combined with the date, and the amount in cents as integer. The program supports four main functions: entry input, search (by date, check number, account name, or outstanding items), reconciliation, and an edit mode accessed via option 6. A machine language presence check at line 2595 using `USR 32736` tests whether a specific ROM or utility is loaded before proceeding. Amounts are stored as integer cents internally and divided by 100 for display, avoiding floating-point precision issues on dollar values. *** ## Program Analysis ### Program Structure The program is organized into several logical sections accessed via a main menu at line 60–160: 1. **Initialization (lines 2300–2690):** Sets up all constants, dimensions arrays, and prompts for starting check number and balance. 2. **Main Menu (lines 60–160):** Displays current balance and date, offers options 1 (input entry), 2 (search), 3 (reconcile), 6 (edit). 3. **Entry Input (lines 170–1020):** Collects payee name, check number, date, and amount; stores them in arrays. 4. **Reconciliation (lines 1030–1550):** Searches by check number or deposit, marks items reconciled, and computes outstanding bank statement balance. 5. **Search (lines 1590–2140):** Searches by date, check number, account name, or outstanding status; doubles as the edit entry point for option 6. 6. **Display Subroutine (lines 2190–2290):** Common record display used by search and reconcile routines. 7. **Save/Quit (lines 2700–2860):** Handles full-array warnings, tape save with data preserved, and a final unused `PRINT PEEK` at line 2860. ### Constant Initialization and Naming The initialization subroutine at line 2300 defines all numeric constants as single-letter variables to save memory and speed up execution. This is a classic ZX81 BASIC optimization: | Variable | Value | Role | | --- | --- | --- | | `B` | 207 | Max entries / max payee names | | `A` | 0 | Zero constant | | `C` | 1 | One constant | | `D` | 2 | Two / array column index | | `E` | 3 | Three / array column index | | `G` | 5 | Five / row for AT positioning | | `I` | 7 | Seven | | `K` | 9 | Nine | | `L` | 10 | Ten | | `M` | 207 | Payee name array size | | `N` | 2 | Current entry count pointer | | `O` | 28 | Lower bound for valid digit CODE check | | `P` | 39 | Upper bound for valid digit CODE check | | `Q` | 2 | Current payee name count pointer | | `R` | 1E6 | Packing base (1,000,000) | | `S` | reconciled marker | Computed from `(L*L+O+C)*R` = 129,000,000 | ### Data Encoding Scheme The most technically interesting aspect of this program is how it packs multiple values into single floating-point array cells using base 1,000,000 (`R = 1E6`). The array `A(N, 3)` stores three fields per transaction: - `A(W,C)` — encodes *payee index × 1,000,000 + check number*. The check number is extracted with `A(W,C) - INT(A(W,C)/R)*R` (i.e., modulo 1,000,000), and the payee index is `INT(A(W,C)/R)`. - `A(W,D)` — encodes *reconciliation marker × 1,000,000 + date*. The reconciliation flag `S = 129,000,000` is added to the date when an item is reconciled (line 1570). An item is outstanding when `INT(A(W,D)/R)*R = S` is false (i.e., the high part is 0). - `A(W,E)` — stores the amount in integer cents (dollars × 100). Deposits are identified by a payee index of 1 (the reserved `A$(1) = "DEPOSIT"` entry) and stored with `A(W,C) = R` (i.e., index 1 × 1,000,000 + 0). ### Balance and Amount Handling The variable `BA` holds the running balance in integer cents throughout (`BA = BA * 100` at line 2655). Deposits add to `BA`, checks subtract. The display consistently uses `BA/100` or `X/100` to present dollar values. The reconciliation routine at lines 1440–1500 computes `BAL` as the sum of all outstanding items and prints the implied bank statement balance as `(BA - BAL) / 100`. ### Input Validation Numeric input is validated by checking `CODE Z$` against the character code range for digits. On the ZX81, digits ‘0’–’9′ have codes 28–37. The bounds `O = 28` and `P = 39` (slightly generous upper bound) are used in guards like: `IF CODE Z$<=O OR CODE Z$>=P THEN GOTO ...` This rejects non-digit input but allows ENTER (code 0, handled separately by checking `CODE Z$ = A`, i.e., = 0, meaning the user pressed ENTER and the system returned an empty string). ### Edit Mode (Option 6) Edit mode is accessed by entering “6” at the main menu and routes through the search subroutine. When a record is found and confirmed wrong (`HI = D`, i.e., = 2), control jumps to line 182 which reverses the financial effect of the old entry (removing its amount from `BA` and zeroing the record fields) before re-entering new data. The variable `HI` is used as a flag: it is set to 0 (`A`) normally and 2 (`D`) when the user indicates a record needs correction. ### Machine Language Check Line 2595 executes `USR 32736` and compares the result to 40059. Address 32736 is near the top of the ZX81’s 32KB ROM space, and this appears to be a check for the presence of a specific ROM version or utility. If the check fails, the program prints a small error marker (`"? "`) but continues executing regardless. ### Payee Name Deduplication When a new payee name is entered, lines 870–910 scan the existing `A$()` array for a match. If found, the existing index `W` is reused; if not, the name is appended at position `Q` and `Q` is incremented. The encoded check number field then becomes `R * W + check_number`, linking the transaction to its payee by index. ### Capacity Limits and Overflow Handling The arrays are dimensioned for 207 entries (`B = 207`) and 207 payee names (`M = 207`). Lines 742–757 check these limits before accepting new data, and lines 2700–2720 display appropriate warnings when either limit is reached. When full, the program routes to the save/quit prompt rather than continuing to accept entries. ### Notable Bugs and Anomalies - Line 155 routes option “6” to `GOSUB 1590` (search), the same as option “2”. This is intentional — search is the entry point for edit mode, with behavior diverging based on `R$ = "6"`. - Line 780 is referenced by `GOTO 780` implicitly via line 750’s `IF CODE Z$=A THEN GOTO 780`, but the label is actually line 782. There is no line 780; line 782 is the next line after 750’s conditional, so after falling through line 750 (when the condition is true), execution would naturally reach 782 — but since `GOTO 780` targets a non-existent line, the interpreter will run from the next line after 780, which is 782. This is a deliberate technique. - Line 2860 (`PRINT PEEK 16386 - PEEK 16412 + 256*(PEEK 16387-PEEK 16413)-50`) is unreachable dead code, likely a debugging remnant that computed available memory. - The prompt string `O$` at line 2594 reads “INFO DELETED–ENTER CORRECT INFO” but deletions are actually implemented by zeroing array fields rather than physically removing records, so deleted entries remain in the array as zero-valued placeholders. ## Source Code ``` 7 SAVE "CHEC%K" 10 FAST 20 GOSUB 2300 30 CLS 40 PRINT D$;AT A,K-C;"TODAYS ";F$,"ENTER IN THIS ORDER.","YEAR MONTH DAY",,"USE ONLY SIX DIGITS TOTAL" 50 INPUT DA 60 CLS 70 PRINT "% % % %P%R%O%G%R%A%M% %B%Y% %D%A%L%E% %F% %L%I%P%I%N%S%K%I% % % ";"% % : CHECK BOOK :% : DATE :% : ";DA;TAB L+L+K;" :% % ";M$;"BALANCE $ ";BA/100;TAB A;"LAST ";G$;LC,M$ 80 PRINT "NOTE: IF AT ANY TIME YOU LOSE","'''''''' CONTROL AND GET THE PROGRAM";TAB G;"PRESS %G%O%T%O 60 %E%N%T%E%R.",M$;,,,,C$,,"1= INPUT ENTRY",,"2= SEARCH",,"3= RECONCILE",,"6= ";N$,,E$ 95 LET HI=C 100 INPUT R$ 120 IF R$="0" THEN GOTO 2730 130 IF R$="1" THEN GOTO 170 140 IF R$="2" THEN GOSUB 1590 150 IF R$="3" THEN GOSUB 1030 155 IF R$="6" THEN GOSUB 1590 160 GOTO 60 170 REM 180 CLS 181 IF R$<>"6" THEN GOTO 190 182 IF (INT (A(W,C)/R))=C THEN LET BA=BA-A(W,E) 183 LET A(W,D)=A 184 IF (INT (A(W,C)/R))>=D THEN LET BA=BA+A(W,E) 185 LET A(W,E)=A 186 LET A(W,C)=A 187 CLS 188 PRINT TAB I;N$,O$ 190 PRINT C$,,"1= CHECK ENTRY",,"5= ";A$(C),,,E$ 210 INPUT Z$ 225 IF R$="6" AND Z$="0" THEN CLS 226 IF R$="6" AND Z$="0" THEN PRINT "YOU MUST ENTER VALUES TO AN EDIT" 227 IF R$="6" AND Z$="0" THEN GOTO 190 230 IF Z$="0" THEN GOTO 60 240 IF Z$="1" THEN GOSUB 330 250 IF Z$="5" THEN GOSUB 270 260 GOTO 170 270 REM 280 CLS 290 LET Y$=A$(C) 300 LET Y=A 310 GOSUB 490 320 RETURN 330 REM 340 CLS 350 PRINT D$;H$;"NAME?",,,C$,,M$ 370 INPUT Y$ 385 IF CODE Y$=A THEN GOTO 340 386 IF R$="6" AND Y$="0" THEN GOTO 340 390 IF Y$="0" THEN RETURN 400 CLS 410 PRINT G$;LC+C;,,,,TAB A;J$,M$ 430 INPUT Z$ 450 IF CODE Z$=A THEN LET Y=LC+C 460 IF CODE Z$=A THEN GOTO 500 470 IF CODE Z$<=O OR CODE Z$>=P THEN GOTO 400 480 IF CODE Z$<>A THEN LET Y=VAL Z$ 490 REM 500 CLS 510 IF Y$=A$(C) THEN PRINT A$(C) 520 PRINT F$;DA,,,,J$,C$,,M$ 540 INPUT Z$ 560 IF CODE Z$=A THEN LET Z=DA 570 IF CODE Z$=A THEN GOTO 610 580 IF Z$="0" THEN RETURN 590 IF CODE Z$<=O OR CODE Z$>=P THEN GOTO 500 600 IF CODE Z$<>A THEN LET Z=VAL Z$ 610 CLS 620 PRINT D$;"AMOUNT?",M$ 640 INPUT Z$ 660 IF CODE Z$<=O OR CODE Z$>=P THEN GOTO 610 670 LET X=(VAL Z$)*100 680 CLS 690 PRINT Y$;TAB A;F$;Z,,G$;Y,,"$ ";X/100;TAB A,,,,K$,M$ 700 IF Y$<>A$(C) AND BA-XA$(C) AND BA-X=B THEN GOTO 752 744 IF Q-C>=M THEN GOTO 752 750 IF CODE Z$=A THEN GOTO 780 752 CLS 755 PRINT "INFO %N%O%T ENTERED ",,, 756 IF Q-C>=M THEN GOTO 2705 757 IF N>=B THEN GOTO 2710 760 IF Y$=A$(C) THEN GOTO 510 770 GOTO 350 782 IF R$="6" THEN LET NN=N 784 IF R$="6" THEN LET N=W 790 IF Y$<>A$(C) THEN GOTO 840 800 LET AA=R 810 LET BA=BA+X 820 LET W=C 830 GOTO 920 840 LET BA=BA-X 850 IF Y>LC THEN LET LC=Y 860 LET A$(Q)=Y$ 870 FOR W=D TO Q-C 880 IF A$(Q)=A$(W) THEN GOTO 902 890 NEXT W 900 LET Q=Q+C 910 LET AA=R*W 920 LET A(N,C)=AA+Y 930 LET A(N,D)=R+Z 940 LET A(N,E)=X 942 IF R$="6" THEN LET N=NN-C 950 LET N=N+C 955 PRINT AT G,L;"INFO ENTERED",M$;L$ 956 IF R$="6" THEN PRINT AT G+C,E;N$;" CORRECTION",M$ 957 PRINT ,,"BALANCE = $";BA/100 970 INPUT Z$ 980 IF Z$="1" THEN COPY 990 IF N-C>=B OR Q-C>=M THEN GOTO 2705 992 IF R$="6" THEN LET R$="0" 994 IF R$="0" THEN RETURN 1000 IF CODE Z$=A AND Y$=A$(C) THEN GOTO 500 1010 IF CODE Z$=A OR Z$="1" THEN GOTO 340 1020 RETURN 1030 REM 1040 CLS 1050 PRINT "ENTER ";G$;"TO BE RECONCILED";,,C$,,M$;E$ 1070 INPUT Y$ 1077 IF CODE Y$<=O OR CODE Y$>=P THEN GOTO 1040 1080 IF Y$="0" THEN GOTO 1180 1090 LET Z=VAL Y$ 1092 FOR W=D TO N 1094 CLS 1095 IF A(W,C)-(INT (A(W,C)/R)*R)=Z THEN GOSUB 2190 1100 IF A(W,C)-(INT (A(W,C)/R)*R)=Z THEN PRINT AT G,A;M$;K$ 1105 IF A(W,C)-(INT (A(W,C)/R)*R)<>Z THEN NEXT W 1115 IF W>=N THEN PRINT "NOT FOUND" 1116 IF W>=N THEN GOTO 1050 1120 INPUT Z$ 1130 IF Z$="0" THEN NEXT W 1160 GOSUB 1560 1170 GOTO 1040 1180 CLS 1190 PRINT AT A,A;"ENTER ";A$(C);AT A,G+K;"TO BE RECONCILED. ENTER BY DATE",,,,C$,,M$;E$ 1210 INPUT Y$ 1218 IF CODE Y$<=O OR CODE Y$>=P THEN GOTO 1180 1220 IF Y$="0" THEN GOTO 1320 1230 LET Z=VAL Y$ 1235 FOR W=D TO N 1240 CLS 1242 IF INT (A(W,C)/R)<>C THEN NEXT W 1245 IF INT (A(W,C)/R)=C AND A(W,D)-(INT (A(W,D)/R)*R)=Z THEN GOSUB 2190 1250 IF INT (A(W,C)/R)=C AND A(W,D)-(INT (A(W,D)/R)*R)=Z THEN PRINT AT G,A;M$;K$ 1255 IF A(W,D)-(INT (A(W,D)/R)*R)<>Z THEN NEXT W 1265 IF W>=N THEN PRINT AT L,G;"NOT FOUND" 1270 IF W>=N THEN GOTO 1190 1275 INPUT Z$ 1290 IF Z$="0" THEN NEXT W 1300 GOSUB 1560 1310 GOTO 1180 1320 LET Z=S 1330 FOR W=D TO N 1340 CLS 1345 IF (INT (A(W,D)/R)*R)<>Z THEN GOSUB 2190 1350 IF (INT (A(W,D)/R)*R)<>Z THEN PRINT AT G,A;"OUTSTANDING ITEMS ",M$;C$;" ","5= SKIP OUTSTANDING ITEMS LIST",L$(O+P TO ),M$;E$ 1355 IF (INT (A(W,D)/R)*R)=Z THEN NEXT W 1357 IF W>=N THEN GOTO 1440 1370 INPUT Z$ 1390 IF Z$="0" THEN RETURN 1400 IF Z$="5" OR W=N-D THEN GOTO 1440 1410 NEXT W 1440 LET BAL=A 1450 FOR X=C TO N-C 1460 IF (INT (A(X,D)/R)*R)<>S AND (INT (A(X,C)/R))=C THEN LET BAL=BAL+A(X,E) 1470 IF (INT (A(X,D)/R)*R)<>S AND (INT (A(X,C)/R))<>C THEN LET BAL=BAL-A(X,E) 1480 NEXT X 1490 CLS 1500 PRINT "BANK STATEMENT IS $ ";(BA-BAL)/100;TAB A;M$;L$ 1520 INPUT Z$ 1530 IF Z$="1" THEN COPY 1550 RETURN 1560 REM 1570 LET A(W,D)=(A(W,D)-(INT (A(W,D)/R)*R))+S 1580 RETURN 1590 REM 1600 CLS 1610 IF R$="6" THEN PRINT AT A,K;N$ 1615 PRINT AT C,L;"SEARCH",M$;C$,,"1= BY ";F$,,"2= BY ";G$,"3= BY ";H$,,"4= BY OUTSTANDING ITEM",E$ 1617 IF R$="6" THEN PRINT AT I,A;E$,"BE SURE TO COPY ALL INFO THAT ISCHANGED" 1630 INPUT Z$ 1650 IF CODE Z$<=O OR CODE Z$>=P THEN GOTO 1600 1660 IF Z$="0" THEN RETURN 1662 IF Z$="4" AND R$="6" THEN GOTO 1600 1663 IF R$="6" THEN GOTO 1730 1665 IF Z$="4" THEN GOTO 2080 1670 PRINT ,,"0= SPECIFIC ITEM","%E%N%T%E%R= ALL ITEMS",E$ 1690 INPUT Y$ 1720 IF CODE Y$=A THEN GOTO 2150 1730 PRINT ,,D$;"ITEM?" 1750 INPUT Y$ 1765 IF Z$="3" THEN GOTO 1970 1770 IF CODE Y$<=O OR CODE Y$>=P THEN GOTO 1600 1780 IF Z$="1" THEN GOTO 1820 1790 IF Z$="2" THEN GOTO 1900 1810 GOTO 1600 1820 REM 1830 LET Z=VAL Y$ 1840 FOR W=C TO N-D 1850 REM 1860 IF A(W,D)-(INT (A(W,D)/R)*R)=Z THEN GOSUB 2190 1865 IF HI=A AND R$="6" THEN GOTO 182 1870 NEXT W 1885 CLS 1887 PRINT AT C,E+E;"END" 1890 GOTO 1610 1900 REM 1910 LET Z=VAL Y$ 1920 FOR W=D TO N-C 1930 IF A(W,C)-(INT (A(W,C)/R)*R)=Z THEN GOSUB 2190 1935 IF HI=A AND R$="6" THEN GOTO 182 1940 NEXT W 1955 CLS 1957 PRINT "END" 1960 GOTO 1610 1970 LET A$(Q)=Y$ 1980 FOR X=C TO N-C 1990 IF A$(Q)=A$(X) THEN GOTO 2020 1995 IF HI=A AND R$="6" THEN GOTO 182 2000 NEXT X 2005 CLS 2007 PRINT "END" 2010 GOTO 1610 2020 LET Z=X*R 2030 FOR W=D TO N-C 2040 IF (INT (A(W,C)/R)*R)=Z THEN GOSUB 2190 2050 NEXT W 2055 CLS 2057 PRINT "END" 2060 GOTO 1610 2070 REM 2080 LET Z=S 2090 FOR W=D TO N-C 2100 REM 2110 IF (INT (A(W,D)/R)*R)<>Z THEN GOSUB 2190 2120 IF R$="3" THEN RETURN 2125 IF Z$="0" THEN GOTO 1600 2130 NEXT W 2135 CLS 2137 PRINT "END" 2140 GOTO 1610 2150 FOR W=D TO N-C 2160 GOSUB 2190 2165 IF HI=D THEN GOTO 2175 2170 NEXT W 2175 CLS 2177 PRINT AT C,E+E;"END" 2180 GOTO 1610 2190 REM 2200 CLS 2210 LET T=INT (A(W,D)/R) 2220 IF T=C THEN LET T=A 2230 PRINT F$;A(W,D)-(INT (A(W,D)/R)*R);TAB O;W,G$;A(W,C)-(INT (A(W,C)/R)*R),,H$;A$(INT (A(W,C)/R));TAB A;"$ ";(A(W,E)/100);TAB A,,"% DENOTES RECONCILED ITEM",L$ 2235 IF INT (A(W,D)/R)*R=S THEN PRINT AT A,O-D;"% " 2240 IF R$="3" THEN RETURN 2245 IF R$="6" THEN PRINT AT G+C,A;"PRESS 0 %E%N%T%E%R IF NOT CORRECT";AT I+D,A;M$;N$,"DELETION" 2260 INPUT Z$ 2265 LET HI=A 2270 IF Z$="1" THEN COPY 2275 IF Z$="0" THEN LET HI=D 2285 IF HI=A AND R$="6" THEN GOTO 182 2290 RETURN 2300 REM 2310 LET B=207 2320 LET A=B-B 2330 LET C=B/B 2340 LET D=C+C 2350 LET E=D+C 2360 LET G=E+D 2370 LET I=G+D 2380 LET K=I+D 2390 LET L=K+C 2400 LET M=207 2410 LET N=D 2420 LET O=L+L+I 2430 LET P=O+L+C 2440 LET Q=D 2450 LET R=1E6 2460 LET S=(L*L+O+C)*R 2470 DIM A(B,E) 2480 DIM A$(M,22) 2490 LET C$="0= NO ENTRY " 2500 LET D$="WHAT IS THE " 2510 LET E$="% %E%N%T%E%R% %A%N%S%W%E%R% %N%U%M%B%E%R% " 2520 LET F$="DATE " 2530 LET G$="CHECK NO. " 2540 LET H$="ACCOUNT " 2550 LET I$="PRESS %E%N%T%E%R IF THIS IS CORRECT " 2560 LET J$=I$+"IF NOT ENTER NUMBER" 2570 LET K$=I$+"PRESS 0 %E%N%T%E%R IF NOT CORRECT" 2580 LET L$="PRESS 0 %E%N%T%E%R TO RETURN PRESS 1 %E%N%T%E%R TO COPY PRESS %E%N%T%E%R TO CONTINUE" 2590 LET M$="''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''''" 2592 LET N$="EDIT MODE" 2594 LET O$="INFO DELETED--ENTER CORRECT INFO"+M$ 2595 IF USR 32736=40059 THEN PRINT "?% % % " 2600 PRINT D$;"FIRST ";G$,"TO BE USED IN THIS PROGRAM?" 2620 INPUT LC 2630 LET LC=LC-C 2640 PRINT ,,"WHAT IS THE BEGINNG BALANCE?" 2650 INPUT BA 2655 LET BA=BA*100 2660 LET A(C,C)=R 2670 LET A(C,D)=S 2680 LET A$(C)="DEPOSIT" 2690 RETURN 2700 CLS 2705 IF Q>=M-C THEN PRINT "NO ROOM FOR ";H$;"NAME" 2710 IF N>=B-C OR Q>=M-C THEN PRINT "CHECK BOOK IS FULL",M$ 2720 GOTO 2740 2730 CLS 2740 PRINT "ARE YOU FINISHED?",M$;"0= YES",,"1= NO",,E$ 2760 INPUT Z$ 2780 IF Z$<>"0" THEN GOTO 60 2800 PRINT ,,M$;"PLUG TAPE RECORDER IN.","START RECORDING.","PRESS %E%N%T%E%R",,M$ 2810 INPUT Z$ 2830 IF CODE Z$<>A THEN GOTO 60 2840 SAVE "CHEC%K" 2850 GOTO 30 2860 PRINT PEEK 16386-PEEK 16412+256*(PEEK 16387-PEEK 16413)-50 ```