VU-Calc

Products: VU-CALC
Date: 1981
Type: Cassette
Platform(s): TS 1000

VU-Calc is a spreadsheet application that runs entirely in machine code, with the BASIC program serving primarily as a loader and menu system. The program stores a large machine code payload across REM statements in lines 1–13, which is then executed via USR calls at addresses in the 16000–19000 range. The menu system allows the user to enter the spreadsheet fresh (clearing memory with CLEAR and dimensioning a 9,825-byte string array B$ for data storage), continue a previously loaded session, or save the spreadsheet with or without data to tape. An error-handler routine at line 9000 uses PEEK calls on system variables 16601 and 16523 to report the current column and row when a calculation error occurs.


Program Analysis

Program Structure

The program is divided into several logical sections:

  1. Lines 1–13: REM statements containing the entire machine code payload for the spreadsheet engine.
  2. Lines 110–330: Main menu — presents options E (Enter), C (Continue), S (Save with data), W (Save without data), and loops on invalid input.
  3. Lines 1000–1030: “Enter” path — clears memory, allocates the data array, sets entry point address, and falls through to the execution dispatcher.
  4. Lines 2000–2010: “Continue” path — sets a different entry point address and jumps to the dispatcher.
  5. Lines 3000–3050: Save-with-data routine — prompts the user to ready the tape, then performs a SAVE.
  6. Lines 4000–4010: Save-without-data path — calls CLEAR first, then jumps to the save routine.
  7. Lines 5000–5140: Main execution dispatcher loop — calls machine code via USR Z, interprets the return value to decide whether to switch modes, trigger a screen copy, or exit.
  8. Lines 9000–9080: Error handler — displays column/row context for a calculation error using PEEKed system variables, then relaunches the Continue path.
  9. Line 9990: Emergency save line.

Machine Code Payload in REM Statements

Lines 1 through 13 contain dense Z80 machine code embedded in REM statements. This is a standard technique for storing executable binary data within a BASIC program. The code spans roughly 13 × ~120 bytes, giving approximately 1,500+ bytes of machine code. The dispatcher at line 5005 uses USR Z to call into this code at varying entry points, with Z set to different addresses depending on context.

Key addresses referenced in the BASIC loader:

AddressContext
16770Fresh-entry point (after CLEAR, “Enter” path)
16812Continue-session entry point
17334Main loop re-entry point (set after first USR call)
18929Called via RAND USR in FAST mode for initialisation

Data Storage via DIM B$

On the “Enter” path, line 1010 allocates DIM B$(9825) — a single string variable used as a flat byte array to hold the spreadsheet cell data. This is a classic technique for obtaining a contiguous block of RAM accessible both from BASIC and from machine code via a known address. Line 1015 uses POKE 16606,0 to adjust a system variable (the RAMTOP or error pointer area) as part of the initialisation.

Execution Dispatcher Loop (Lines 5000–5140)

The loop at line 5005 calls USR Z and examines the integer return value I:

  • I = 63479 — triggers a mode switch: enters FAST mode, calls RAND USR 18929 for reinitialisation, then returns to SLOW mode and re-enters the loop.
  • I = 0 — exits to the main menu (line 110).
  • I = 255 — triggers a COPY (screen print to ZX Printer).
  • Any other value — updates Z to 17334 and continues looping.

Line 5000 uses the idiom LET B$(1 TO 1)=B$(1 TO 1) to force BASIC to verify that the array exists and is accessible before jumping into machine code; this will raise an error gracefully if the array has not been dimensioned (i.e., if “Continue” is chosen without prior data in memory).

Error Handler (Lines 9000–9080)

The error handler at line 9000 reads two system variables to report where a calculation error occurred:

  • PEEK 16601 — holds the current column number (0-based); line 9015 adds 1 for display, and line 9020 converts it to two display characters using CHR$ arithmetic with offset 28 (the ZX81 character code for digit “0” minus zero).
  • PEEK 16523 — holds the current row, displayed similarly with offset 38.

After user acknowledgement, line 9080 jumps back to the “Continue” path, allowing the session to be resumed.

Save Mechanism

The SAVE "VU-CALC" on line 3040 saves the entire BASIC program including the REM-embedded machine code and the populated B$ array, effectively checkpointing the spreadsheet state to tape. The save-without-data path (line 4000) calls CLEAR first, which collapses the variable area and removes B$, saving only the program code.

Notable Techniques and Idioms

  • Using RAND USR (line 5110) rather than plain USR in an expression discards the return value, suitable for a call that does not need to report back to BASIC.
  • The inverse-video characters in PRINT statements (e.g., %E%N%T%E%R) are used throughout to create highlighted labels on the menu and status screens.
  • VAL "number" is not used here; all GO TO targets are literal line numbers.
  • The FOR I=0 TO 60 / NEXT I delay loop at lines 310–320 provides a brief pause to display the “INVALID” error message before clearing and re-prompting.

Content

Appears On

Related Products

Construct and generate, calculate large tables for budget sheets, financial analysis, and projections. 16K.

Related Articles

Related Content

Image Gallery

Source Code

   1 REM 00000975479511A56571D521C1D1C1E1C1F1C201C211C221C231C241C251D1C1D1D1D1E1D1F1D201D211D221D231D241D251E1C1E1D1E1E1E1F1E201E211E221E231E241E251F1C1F1D1F1E1F1F1F201F211F22FF08A7F75300303099795F416011E7BE7B1D301930303030303030303030303030303030303030907F750A2750C5750E8750B7602E760517607476097760BA760DD76007702377046770697708C770AF770D2770F5770187803B7805E78081780A4780C7780EA780D7903079053790767909979030303030303030303030303030303030303030303030303030303030
   2 REM 218240AF7723772377237723772A1040160ED4A2287402AC40232289402A87401E820ED4A22DB403E831EA14202A8940912209161F772315C2BD41231DC2BA412A894018F093E51E9771A0977138091DC2D34100CD824CCD1942CD4542CDC542C3B6432A8940184091E93A8440C62616577237211E091685723C123091DC2042C9342C92A8940147090EB219040603A85404F909063EB1A7723131A7713C519090C15C23242C93A8440CD824B3E9CD824BEF434CDB44B2A874090E53A8540CD824B3EEACD824BEF434CDB44BE19023228C402A8940C382423030
   3 REM 186090228E4063E9ED5B8E402A8C40C5180EDB023EB13A090EBC1DC29542C52A8E401A090228E402A8C401EA090228C40C15C28C42C93A8240CD824B3E42CD824BEF434C35C4C2A894090E53A8340CD824B3EACD824BEF434CDB44BE1901650903ADA401E877231DC2FA42CD66433ADA40FE83C8CD32437EFEFFC8FE0C8604F2104199905E23562A89401D6290C3BD4600000003E9CD824B3A8440CD824B3A8240CD824BEFF4343EEACD824B3A8540CD824B3A8340CD824BEFF4F34CDB44B2A874090C92A89401D62903E01620772315C27243C9303030
   4 REM CDBB2444D5114CA8243CDBD77EC92A89403E801620772315C29843C9CD9143E1EB2A89401AFEFFCAB343772313C3A74313D5C9CD9F43AB94ABB4B7B2BAB1A68080B194A9A6B9A68080A894A8A6B1A8BAB1A6B9AA80FFCD8243FE23CA6544FE24CAFD44FE22CA9A44FE21CACE44FE2DCA4944FE31CA1A45FE28C800FE2CCA1949FE38CA8A49FE36CA4144FE35CA4544C3204CD445CD9F43AEB3BBA6B1AEA996B4B5B9AEB4B3FF640CD3244C3B643210102B7DFE0C235445C23244C9100C91FF0C9CDC744AF77237723772377C3E3413E8332DA40CDC5423E8A32DA40C93A8240FE0CA8244F5CD5744F13D328240CDC542C3B744
   5 REM 3A8440FE0CAD9433D328440CDF241CD4542CD043C3BF443A8240FE8CAAB44F5CD5744F13CC373443A8440FE11CAD9433CC38B446ACD3244C3D9436ACD3244C3D943CD5744218240C93A8340FE0CAE544F5CD5744F13D328340CDC542C3B7443A8540FE0CAD9433D328540CD1942CD4542CD043C3BF443A8340FE2CAE45F5CD5744F13CC3DC443A8540FE21CAD9433CC3EE44CD9F43B1B4A6A980A9A6B9A6809880B9AEB9B1AAB880FFC34C4CE53A8240CD824B3E42CD824BEF4343E44CD824B3A8340CD824B3EACD824BEF4FF34C36A4C2A89409D113D5E53E068771223135C26745E1D1E0C3C545620C3824530
   6 REM CD3244CD8243E1D1C1FE0CA9A45FE76CACE45FE77CAAD45FE40D2C54577122313C79FE8CABD45C3C54579FE0CAC5453E0772B1BD12C3C545634CD3244C3B6433E877C5D5E5C376453E077C3BD453A8640FE28C2046CD9F43B4B3B1BE80A09C80ABB4B7B2BAB1A6AA80A6B1B1B4BCAAA9FF632CD3244C3B6433C3286403D2ADB40FE0CA1546123093DC2104622E140CD9F43AAB3B9AAB780ABB4B7B2BAB1A6FF2AE140EB2A89401D62C3AE463E877C5D5E5620CD3244CD8243E1D1C1FE0CA5646FE76CA8246FE77CA6946FE40D2364677122313C79FE20CA8546C3364679FE0CA36463E0772B1BD12C33646303030
   7 REM 3E0773A86404F60C3F54B21041999ED5BE1407B77237A77233E07722E340CD32433A864077C33647C5D5E5CD6643E1D1C19E0C336461AFEFFC8FE40D2CC46772313C3BD46131AE5D5473A84404F3A8240573E26808182D1E1CD2B47E5D51A473A85404F3A83408081F5160D6ADAFC4614C3F34642F115FA94714D6A15C23474F78D1E100CD1C477900CD1C4713C3BD460FE40DA24473E64473E1C807723C9FE40DA32473E80772313C9620CD3244CD9F4390B791AAB1A6B9AEBBAA80B4B78090A691A7B8B4B1BAB9AAFFCD8243FE26CAE947FE37CA8247CD9F43AEB3BBA6B1AEA9809680B4B5B9AEB4B3FFC3364730
   8 REM 2AE1407EFEFFC304C23C38547F5C6807723CDB447CDD1473A8B4047F190D6267723CDDD473AD940473AE540907723C38547E57ED61C47FE0CAC747EAAF80DC2C14747237ED61C8032E540E1C93A8440473A824080328B40C93A8540473A83408032D940C9620CD3244CD9F43B2B4BBAA80A7BE8090B791B4BC8090A891B4B1BAB2B380B4B78090AA91BDAEB9FFCD8243FE28CA3B48FE37CA4D48FE2ACA149CD9F43AEB3BBA6B1AEA9809680B4B5B9AEB4B3FFC3E947CD9F43B9B480A8B4B18FFF1EEAE3C35C48CD9F43B9B480B7B4BC8FFF1E9E2D5C5CD6643C1E12A89401D62C38248CAE947FE26D28F47C38B473030303030
   9 REM 9E5D5C53E877620CD3244CD8243C1D1E1FE77CA5C48FE76CAA948FE40D283487723DC283482A89401D6297BFEEACACB487ED626DAE947FE1AD2E94732E540CDD1474FC3DF48CDB4473AE5403D32E5400FE24D2E947CDDD474F3AE540B9CA149DA14947160D5C5CD3243C1D1193A864077C79B8C2F348C3149CD0433AE640FE0CABD453AE740328640AF32E640C3BD45620CD3244CD9F4390B291A6B0AA80A8BAB7B7AAB3B980B4B78090A891ADA6B3ACAAFFCD8243FE32CA6049FE28CA6A49CD9F43AEB3BBA6B1AEA9809680B4B5B9AEB4B3FFC31949CD32437E32DE40C3BD453A864032E7403E132E640CD3243C3824930
  10 REM 7EC3CA4900003ADE40FE0C2AB49CD9F43B3B480A8BAB7B7AAB3B980ABB4B7B2BAB1A6FFC3BD45CD32433ADE4077CD9F43ABB4B7B2BAB1A680B1B4A6A9AAA9FFCD043C3BD45FE0C2EA49CD9F43B3B480ABB4B7B2BAB1A680B9B480A8ADA6B3ACAAFFC3BD453D328640C3D4452A8740228C40228E40AF32D940328B402A8E407EFE0C2434A1EA02A8E409228E403AD9403C32D940FE24C214A1902A8C409228C40228E40AF32D9403A8B403C328B40FE1AC214ACD4542640C94F60210419995E23562A1A4022E8402A1C4022EA401001AFEFFCA824AFE26D2E24A772331332EC40C35E4A303030303030303030
  11 REM 3E7677233AEC4077221A4023E52AEA40EBE17323722371237023221C40EF1A2A342A8E4023E52A1C402B462B4E2B562B5E79FE9DABD4A60E8EBD1C5EDB02AEA40221C402AE840221A402A8E40C192379FE8CAA4A3E07723CC3D44AFE80D2FB4AD62632EE40E5EB23C5CDB447EBC1E11313C35F4B131AC5473A8B4000000800032EE40131A473AD940000080032E540C113C35F4B2A87403AEE40FE0CA354B19057915C2304B3AE540FE0CA464B1EA057915C2414BD123180EDB0E11809E5C1EBD12B7E32EC4023C35E4A3AE5403D32E540D5C5E5C3214B30303030303030303030303030303030
  12 REM E5D5C568FE0CAAF4BA7517D28C4B4A71F4F78C6802A1C4077792377AF23772377237723221C40C1D1E1C9AF4FC3994BE5D502A1C4011FBFF19E57EFE0CADF4BD680473E1090572346234EC3E54B0000E1221C400D1E1C9100C3D74B78F68047A7CB18CB1915C2E94BC3D74B3EFF1213121312C38E4630CAE947FEDCA104CFE26D28F47C38B473E07723C38B47303030303030303030FE2BCAD445FE29CA2D4CC31844CD32433E077CD9F43ABB4B7B2BAB1A680A9AAB1AAB9AAA9FFCD6643C32A44CD32433E077E5CD6643E1C334453030CDB44BC5E114209E5C1C3D642CDB44BC5E114209E5C1C35B4530303030
  13 REM 2A89401A6091E93E82771A097797793E8177124091DC28B4CCDF241C93030303030303030303030303030303030303030303030303030303030
 110 SLOW 
 120 CLS 
 130 PRINT "         V U - C A L C"
 132 PRINT 
 133 PRINT 
 134 PRINT 
 140 PRINT 
 150 PRINT "%E%N%T%E%R  E : TO ENTER VU-CALC"
 160 PRINT 
 170 PRINT "       C : TO CONTINUE VU-CALC"
 180 PRINT 
 190 PRINT "       S : TO SAVE WITH DATA"
 200 PRINT 
 210 PRINT "       W : TO SAVE WITHOUT DATA"
 240 PRINT AT 21,0;"%O%P%T%I%O%N%?"
 250 INPUT O$
 260 IF O$="E" THEN GOTO 1000
 270 IF O$="C" THEN GOTO 2000
 280 IF O$="S" THEN GOTO 3000
 290 IF O$="W" THEN GOTO 4000
 300 PRINT AT 21,0;"%I%N%V%A%L%I%D"
 310 FOR I=0 TO 60
 320 NEXT I
 330 GOTO 240
 1000 CLEAR 
 1010 DIM B$(9825)
 1015 POKE 16606,0
 1020 LET Z=16770
 1030 GOTO 5000
 2000 LET Z=16812
 2010 GOTO 5000
 3000 CLS 
 3005 PRINT "%P%U%T% %T%A%P%E% %O%N% %R%E%C%O%R%D"
 3010 PRINT 
 3020 PRINT "%T%H%E%N% %P%R%E%S%S% %N%E%W%L%I%N%E"
 3030 INPUT O$
 3040 SAVE "VU-CAL%C"
 3050 GOTO 110
 4000 CLEAR 
 4010 GOTO 3000
 5000 LET B$(1 TO 1)=B$(1 TO 1)
 5002 CLS 
 5005 LET I=USR Z
 5010 IF I=63479 THEN GOTO 5100
 5020 IF I=0 THEN GOTO 110
 5030 IF I=255 THEN COPY 
 5040 LET Z=17334
 5050 GOTO 5005
 5100 FAST 
 5110 RAND USR 18929
 5120 LET Z=17334
 5130 SLOW 
 5140 GOTO 5005
 9000 CLS 
 9002 SLOW 
 9005 PRINT "%E%R%R%O%R% %W%H%I%L%E% %C%A%L%C%U%L%A%T%I%N%G"
 9010 PRINT 
 9015 LET A=PEEK (16601)+1
 9020 PRINT "%C%O%L ";CHR$ (INT (A/10)+28);CHR$ (A-INT (A/10)*10+28)
 9030 PRINT 
 9040 PRINT "%R%O%W ";CHR$ (PEEK 16523+38)
 9050 PRINT 
 9060 PRINT "%P%R%E%S%S% %N%E%W%L%I%N%E% %T%O% %C%O%N%T%I%N%U%E"
 9070 INPUT O$
 9080 GOTO 2000
 9990 SAVE "VU-CAL%C"

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

Scroll to Top