Budgeter

Products: The Budgeter
Date: 1982
Type: Cassette
Platform(s): TS 1000
Tags: Home

Budgeter is a home accounts program that tracks budgeted and actual expenditures across 18 spending categories, including food, clothing, rent, utilities, and savings. It uses a two-dimensional numeric array T(18,2) to store budget and actual figures, and a string array C$(18,10) for category names. A machine code routine embedded in the REM statement at line 100 is called via USR at lines 1070 and 1170, toggling six consecutive memory locations (16707–16712) between 128 and 0, likely to control screen borders or perform a display-clearing operation. The program supports tape save and load operations, allowing budget data to persist across sessions, and includes a listing screen that displays all 18 categories with their budget totals, actual totals, and remaining balance.


Program Analysis

Program Structure

The program is organized into several functional blocks, each accessed via GOSUB from the main flow. The top-level logic begins at line 262 after a deliberate initialization guard, progresses through date verification at line 274, and then enters the main menu loop starting around line 500.

Line RangePurpose
100Machine code in REM statement
140–160Halt/warning message (machine code clobber guard)
200–260POKE loop utility (manual data entry via INPUT)
262–299Initialization, date entry, intro screen
500–580Main program loop
1000–1080Subroutine: set display bytes to 128 (inverse), call USR
1100–1180Subroutine: set display bytes to 0, call USR
1200–1299Title/intro screen subroutine
1300–1399Master menu display and category selection
1400–1499Function menu (Budget/Actual adjust)
2000–2499Amount entry and confirmation logic
2500–2999Update and display new budget/actual values
7000–7099Error message for oversized input
8000–8100Initialize category name strings
8500–8530Quit with confirmation and optional save
8800–8899Short delay loop (FOR N=1 TO 20)
9000–9060Save to tape
9100–9240Full listing display of all 18 categories

Machine Code in REM

Line 100 contains an extensive machine code routine embedded in a REM statement, a well-known technique for storing executable Z80 code within BASIC. The routine is invoked via USR 16720 at lines 1070 and 1170. The two subroutines at lines 1000 and 1100 differ only in the values POKEd into addresses 16707–16712 (128 vs. 0) before the USR call, suggesting the machine code performs a display or memory operation whose behavior is parameterized by those six bytes. The pattern of setting multiple consecutive memory locations to \x80 (binary 10000000) or \x00 is consistent with border color or attribute manipulation.

Data Structures

The program uses two arrays declared at lines 264–266:

  • DIM C$(18,10) — a string array holding the 10-character names of 18 budget categories, populated in the subroutine at line 8000.
  • DIM T(18,2) — a numeric array with two columns per category: column 1 for budgeted amount and column 2 for actual expenditure.

The variables Z and G accumulate budget and actual totals respectively in the listing loop (lines 9105–9133), and F holds the remaining balance computed as Z-G.

Key BASIC Idioms

The program uses several characteristic idioms:

  • INKEY$ polling loops: Lines like IF INKEY$="" THEN GOTO 1442 busy-wait for a keypress without consuming an INPUT prompt, giving a responsive feel to menu navigation.
  • VAL A$ for string-to-number conversion: Used at line 1385 to convert the menu selection string to a numeric index.
  • AT coordinates in PRINT: Extensively used throughout for precise screen layout.
  • Inverse video in PRINT strings: The listing screen header at line 9112 uses inverse characters (e.g., %A%C%C%O%U%N%T) to create highlighted column headers.

Navigation and Menu Flow

The main loop (lines 500–580) calls subroutines in sequence: a screen clear (1000), the main display init (8000), another clear, the master menu (1300), then the function menu (1400). After function selection, control passes to the add/adjust logic at line 2000 if B is 1 or 2. The loop returns to line 560 repeatedly, with GOTO 550 used as a soft reset to the top of the main loop.

Budget Adjustment Logic

Lines 2542–2544 perform the actual update: T(A,B)=T(A,B)+P is written twice, once for B=1 and once for B=2, which is functionally redundant — a single unconditional statement would suffice since only one branch executes. The same pattern is repeated for the undo at lines 2562–2564. This redundancy appears to be a defensive coding style rather than a bug.

Tape Save

The SAVE at line 9050 uses the filename "HOMEACC%T", where %T represents the inverse-video character T. This is the auto-run flag technique. The save routine prompts the user to prepare the recorder before executing the save, then returns to the main flow at line 270.

Initialization Guard and POKE Utility

Lines 140–160 display a warning message if the program is run without jumping past them. The comment at line 152 instructs the user to GOTO 262 if they wish to zero all values, or to reload the tape if data has been clobbered — indicating the machine code at line 100 can overwrite data if the program starts from the beginning. Lines 200–260 implement a raw POKE loop via INPUT, presumably used during development to install or patch the machine code bytes interactively.

Bugs and Anomalies

  • Line 2047 references GOTO 2044, but line 2044 does not exist. Execution would fall through to the next line, making the error branch non-functional. The intent was likely to re-prompt for input after the “TOO BIG” message.
  • Line 1383 is a REM comment: REM IF A$<"1" OR A$>"18" THEN GOTO 550. This range check was disabled, replaced by the numeric check at line 1390, but the string comparison would not have worked correctly for two-digit values anyway (e.g., “9” > “18” lexicographically).
  • Lines 8517–8519 in the quit handler have a logic issue: IF INKEY$="N" THEN GOTO 270 fires immediately after setting L$=INKEY$, meaning the same keypress is re-read. This can cause unpredictable behavior depending on key release timing.
  • Lines 3000 and 3999 define an empty subroutine that is never called, likely a placeholder left from development.
  • The delay subroutine at lines 8800–8899 loops only 20 times, which provides a negligible pause — effectively no delay at normal execution speed.

Content

Appears On

Related Products

Tracks actual vs. budgeted expenditures and computes the difference. Up to 18 categories of expenses can be recorded for a...

Related Articles

Related Content

Image Gallery

Budgeter

Source Code

 100 REM 2AC40231591ED4A3680C900002AC40231591ED4A6F36802B5C29D402AC40231591ED4A6F3680235C2AF40C900000000000002AC402312A1ED4A6F3680235C2CF40C9000000000E162AC402311210620ED5A22FF403688235C2F0402AFF40DC2E940C95610000000002AC40231F011210ED4AE15ED5A3680DC21841C9000000000000000000000000000275B600108080808080800000000ED5BC4013ED533C413E6323E413E163240413E5324141ED4B3E41214341EDB03A41413DC265412A3C4111210ED5A223C41EB3A40413D3240413C475C26341C9000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000000
 140 SLOW 
 150 PRINT "HALTED--TYPE GOTO 262 IF YOU"
 152 PRINT "WISH TO ZERO ALL VALUES"
 153 PRINT 
 154 PRINT "OTHERWISE RELOAD TAPE AS YOUR "
 156 PRINT "DATA HAS BEEN CLOBBERED"
 160 STOP 
 200 INPUT A
 220 INPUT B
 230 PRINT B
 240 POKE A,B
 250 LET A=A+1
 260 GOTO 220
 262 LET D$="MM/YY"
 264 DIM C$(18,10)
 266 DIM T(18,2)
 267 LET Z=0
 268 LET G=0
 270 GOSUB 1000
 272 GOSUB 1200
 273 GOSUB 1000
 274 PRINT AT 2,2;"THIS TAPE IS FOR ";D$
 276 PRINT AT 4,2;"IS THIS OK ?  Y/N"
 278 IF INKEY$="" THEN GOTO 276
 279 IF INKEY$="Y" THEN GOTO 500
 280 IF INKEY$<>"N" THEN GOTO 276
 281 DIM C$(18,10)
 282 PRINT AT 6,2;"TYPE IN NEW DATE  E.G. 02/82"
 283 DIM T(18,2)
 284 INPUT D$
 286 PRINT D$
 288 GOSUB 1000
 299 GOTO 274
 500 GOSUB 1000
 505 GOSUB 8000
 520 GOSUB 1000
 550 GOSUB 1300
 560 GOSUB 1400
 570 IF B=1 THEN GOSUB 2000
 576 IF B=2 THEN GOSUB 2000
 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;"HOME"
 1220 PRINT AT 11,10;"ACCOUNTS"
 1228 PRINT AT 20,2;"HIT ENTER WHEN READY"
 1229 INPUT Y$
 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,9;"HOME ACCOUNTS"
 1330 PRINT AT 2,6;"MASTER MENU DISPLAY"
 1340 PRINT AT 18,1;"ENTER NUMBER/LETTER OF TYPE"
 1342 PRINT AT 4,1;"1=FOOD      10=EDUCATION"
 1344 PRINT AT 5,1;"2=CLOTHING  11=TELEPHONE"
 1346 PRINT AT 6,1;"3=RENT/MORT.12=AUTO"
 1348 PRINT AT 7,1;"4=HEAT      13=ENTERTAIN"
 1350 PRINT AT 8,1;"5=ELECTRIC  14=VACATION"
 1352 PRINT AT 9,1;"6=WATER     15=GOODS"
 1354 PRINT AT 10,1;"7=TAXES     16=SERVICES"
 1356 PRINT AT 11,1;"8=DENTAL    17=INSURANCE"
 1358 PRINT AT 12,1;"9=MEDICAL   18=SAVINGS"
 1367 PRINT AT 14,1;"ENTER L TO LIST ALL ENTRIES"
 1368 PRINT AT 15,1;"ENTER S TO SAVE TO TAPE"
 1369 PRINT AT 16,1;"ENTER Q TO QUIT "
 1370 INPUT A$
 1372 PRINT AT 19,1;A$
 1379 IF A$="L" THEN GOTO 9100
 1380 IF A$="Q" THEN GOTO 8500
 1382 IF A$="S" THEN GOTO 9000
 1383 REM IF A$<"1" OR A$>"18" THEN GOTO 550
 1385 LET A=VAL A$
 1390 IF A<1 OR A>18 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=ADJUST BUDGET ";C$(A)
 1428 PRINT AT 12,2;"2=ADJUST ACTUAL ";C$(A)
 1442 PRINT AT 18,2;"9=QUIT THIS SECTION"
 1443 IF INKEY$="" THEN GOTO 1442
 1444 IF INKEY$<>"1" AND INKEY$<>"2" AND INKEY$<>"9" THEN GOTO 1442
 1445 LET B=VAL INKEY$
 1446 PRINT AT 20,1;B
 1448 IF B=9 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)
 2022 IF B=1 THEN LET S$="BUDGET"
 2024 IF B=2 THEN LET S$="ACTUAL"
 2025 PRINT AT 2,8;S$;" DISPLAY"
 2040 PRINT AT 5,0;"ENTER ADJUST AMOUNT "
 2045 INPUT P
 2046 IF P>999999 THEN GOSUB 7000
 2047 IF P>999999 THEN GOTO 2044
 2048 PRINT AT 6,0;"% % % % % % % "
 2049 PRINT AT 6,0;P
 2050 PRINT 
 2100 PRINT AT 20,1;"ALL ABOVE CORRECT ? Y/N"
 2110 IF INKEY$="" THEN GOTO 2110
 2112 LET Y$=INKEY$
 2120 PRINT Y$
 2130 IF Y$="N" THEN GOTO 2000
 2152 GOSUB 2500
 2220 GOSUB 1000
 2232 PRINT "HIT ENTER KEY WHEN READY"
 2234 INPUT G$
 2236 GOSUB 1000
 2499 RETURN 
 2500 REM 
 2510 GOSUB 1000
 2520 PRINT AT 2,2;C$(A)
 2530 PRINT 
 2535 PRINT "PREVIOUS BUDGET= ";T(A,1)
 2538 PRINT "PREVIOUS ACTUAL= ";T(A,2)
 2540 PRINT 
 2542 IF B=1 THEN LET T(A,B)=T(A,B)+P
 2544 IF B=2 THEN LET T(A,B)=T(A,B)+P
 2546 PRINT "NEW BUDGET= ";T(A,1)
 2548 PRINT "NEW ACTUAL= ";T(A,2)
 2552 PRINT "AMOUNT REMAINING= ";T(A,1)-T(A,2)
 2554 PRINT AT 20,2;"OK ?  Y/N"
 2556 IF INKEY$="" THEN GOTO 2556
 2557 LET Y$=INKEY$
 2558 PRINT Y$
 2560 IF Y$="Y" THEN GOTO 560
 2562 IF B=1 THEN LET T(A,B)=T(A,B)-P
 2564 IF B=2 THEN LET T(A,B)=T(A,B)-P
 2566 GOTO 560
 2999 RETURN 
 3000 REM 
 3999 RETURN 
 7000 REM 
 7010 PRINT AT 6,0;"TOO BIG"
 7099 RETURN 
 8000 REM 
 8010 LET C$(1)="FOOD"
 8020 LET C$(2)="CLOTHING"
 8022 LET C$(3)="RENT/MORT."
 8024 LET C$(4)="HEAT"
 8026 LET C$(5)="ELECTRIC"
 8028 LET C$(6)="WATER"
 8030 LET C$(7)="TAXES"
 8032 LET C$(8)="DENTAL"
 8034 LET C$(9)="MEDICAL"
 8036 LET C$(10)="EDUCATION"
 8038 LET C$(11)="TELEPHONE"
 8040 LET C$(12)="AUTO"
 8042 LET C$(13)="ENTERTAIN"
 8044 LET C$(14)="VACATION"
 8046 LET C$(15)="GOODS"
 8048 LET C$(16)="SERVICES"
 8050 LET C$(17)="INSURANCE"
 8052 LET C$(18)="SAVINGS"
 8100 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 IF INKEY$="" THEN GOTO 8514
 8515 LET L$=INKEY$
 8516 PRINT AT 5,2;L$
 8517 IF INKEY$="N" THEN GOTO 270
 8518 IF L$="Y" THEN PRINT AT 7,2;"SAVE TO TAPE ? Y/N"
 8519 GOSUB 8800
 8521 IF INKEY$="" THEN GOTO 8521
 8522 LET X$=INKEY$
 8523 IF X$="Y" THEN GOTO 9000
 8525 PRINT AT 18,2;"OK-QUIT IS DONE"
 8528 STOP 
 8530 GOTO 550
 8800 FOR N=1 TO 20
 8810 NEXT N
 8899 RETURN 
 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 "HOMEACC%T"
 9060 GOTO 270
 9100 REM 
 9105 LET Z=0
 9107 LET G=0
 9110 CLS 
 9112 PRINT AT 0,0;"%A%C%C%O%U%N%T";AT 0,14;"%B%U%D%G%E%T";AT 0,23;"%A%C%T%U%A%L"
 9120 FOR N=1 TO 18
 9122 PRINT AT N,1;C$(N);" ";AT N,14;T(N,1);" ";AT N,23;T(N,2)
 9125 LET Z=T(N,1)+Z
 9130 LET G=T(N,2)+G
 9132 LET F=Z-G
 9133 NEXT N
 9134 PRINT "TOTALS ";AT 19,14;Z;AT 19,23;G
 9138 PRINT "REMAINING BALANCE= ";F
 9220 PRINT AT 21,2;"%P%R%E%S%S% %E%N%T%E%R% %W%H%E%N% %R%E%A%D%Y"
 9230 INPUT Y$
 9235 CLS 
 9240 GOTO 550

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

People

No people associated with this content.

Scroll to Top