ZCALC

Date: 198x
Type: Program
Platform(s): TS 1000

This program implements a spreadsheet application called “Z CALC”, supporting a grid of named columns and rows with numeric data entry, scrolling display, formula-based cell computation, named constants, and column/row totalling. The main data store is a single large two-dimensional string array A$(22,149), which packs cell values, row labels, and column headers into fixed-width fields within its columns. Formula evaluation at lines 6700–7210 supports four arithmetic operators and an assignment operator, with operands drawn either from other cells or from a 24-element constant bank stored in W$(120). A custom title-screen routine (lines 9550–9680) manually renders bitmap characters from the ROM font by PEEKing character data at address 7680, printing block graphics pixel by pixel. Division by zero is silently handled by substituting 0.01 for a zero divisor.


Program Structure

The program is organised as a menu-driven application entered at line 500 after the title screen at 9550. A numeric menu at line 565 dispatches to one of seven functional modules at fixed line-number offsets computed by 700+((Q-1)*1000):

QModule startFunction
1700Data input (columns, rows, values)
21700Change a single cell value
32700Change column/row function strings
43700Edit named constants
54700Column total and average
65700Row total and average
76700Formula recalculation (ANS)

Shared subroutines occupy lines 1082: GOSUB 10 waits 200 frames, GOSUB 12 clears the status line, GOSUB 16 computes the column byte-range into X and U, and GOSUB 22 prints the column-header labels. The scroll/view routine beginning at line 28 is used by the change-cell module via GOSUB 46 (branching into the middle of the subroutine block).

Data Layout in A$

All spreadsheet data lives in one array DIM A$(22,149) declared at line 702. The layout within each row of A$ is:

  • Row 1: column names, stored in 7-character fields starting at positions (H*7)-6 for column H (columns 1–3, positions 1–21).
  • Row 2: column function strings, same positional encoding.
  • Rows 3–22: data rows. Positions 1–(H1*7) hold numeric cell values in 7-character fields. Positions 141–144 hold a 4-character row name; positions 145–149 hold a 5-character row function string.

The column index formula X=(H*7)-6, U=X+6 (lines 1620) consistently maps a 1-based column number to its byte slice in A$. This same offset I=(H*7)-6 is recomputed inline at line 997 without calling the subroutine, a minor inconsistency.

Scrolling Display

The scrolling view (lines 2882) shows up to three columns side by side in screen positions K=11,18,25 (controlled by FOR K=11 TO 25 STEP 7). Horizontal position is tracked by H (column index) and vertical by V (row index). Navigation keys are numeric: 5=left, 8=right, 7=up, 6=down, 0=exit. The wrapping logic uses a compact idiom:

  • LET H=-(H1=H)+H+1 — increments H and wraps to 1 when H equals H1.
  • LET H=H-1+(H=1) — decrements H and wraps to H1 when H is 1.
  • Similar logic applies to V with boundary at 4 (minimum) and V1 (maximum).

Formula Evaluation Engine

The recalculation module (lines 67007210) performs two passes: first across columns (lines 67006950), then across rows (lines 69607210). Each pass reads a 6-character function string. The first character is the operator (+, -, *, /, or =). The second character identifies the operand source: a column letter or W for a named constant. If = and there is a second operand (position 3 is not a space), a pointer K1 is advanced by 2 and the lookup is repeated, allowing a two-operand chain.

Results are stored back into A$(V,K TO K+6) as strings via STR$, with rounding to one decimal place using the idiom INT(value*10)/10. Division by zero substitutes 0.01 for the divisor (line 6830), silently corrupting results rather than reporting an error.

A column function starting with £ (line 6710) and a row function starting with £ (line 6980) cause that column or row to be skipped entirely during recalculation, serving as a “no formula” sentinel.

Named Constants

Up to 24 named constants are stored in DIM W$(120), each occupying 5 characters at position (Z*5)-4. They are labelled WAWX (using CHR$(37+Z) for the suffix letter). The constant-entry screen at lines 10671125 and the edit screen at 37003870 both display 12 constants per column. Referencing a constant in a formula uses the character W as a flag, with the following character decoded via CODE(...)-37 to obtain the index.

Title Screen Bitmap Renderer

Lines 95509680 contain a hand-written ROM-font renderer. The string X$="CAL" is rendered as large characters by reading each character’s 8×8 bitmap from the ROM character table at base address 7680 using PEEK(7680+C*8+H). Each bit is extracted by repeated halving of a bitmask (V=128 down to 1), printing a block graphic for set bits and a space for clear bits. The three characters are placed at screen columns 5, 12, and 19 (via FOR L=5 TO 19 STEP 7), producing oversized pixel-art lettering.

Key BASIC Idioms

  • Boolean arithmetic for wrapping: -(H1=H) evaluates to -1 when true, effectively adding 1 after subtraction.
  • Computed GOTO: GOTO 700+((Q-1)*1000) dispatches to modules without a chain of IF statements.
  • Fixed-width string fields within a single array row substitute for a two-dimensional numeric array, conserving memory at the cost of needing VAL and STR$ conversions.
  • Character encoding: column letters are stored and decoded via CHR$(H+37) / CODE(...)-37, mapping A=1, B=2, etc. Row letters similarly use offset 35.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Source Code

  10 PAUSE 200
  12 PRINT AT 0,0;"                                "
  14 RETURN 
  16 LET X=(H*7)-6
  18 LET U=X+6
  20 RETURN 
  22 PRINT AT 2,6;"NAME"
  24 PRINT AT 3,0;"  NAME%F%U%N%C="
  26 RETURN 
  28 GOSUB 12
  30 PRINT AT 0,0;"SCROLL:U=7,D=6,R=8,L=5,NONE=0"
  32 INPUT Q
  34 GOSUB 12
  36 IF Q=0 THEN RETURN 
  38 IF Q=5 THEN LET H=-(H1=H)+H+1
  40 IF Q=8 THEN LET H=H-1+(H=1)
  42 IF Q=7 THEN LET V=V+1-(V>V1)
  44 IF Q=6 THEN LET V=V-1+(V<4)
  46 LET H2=H
  47 FOR K=11 TO 25 STEP 7
  48 IF H>H1 THEN GOTO 76
  50 GOSUB 16
  52 PRINT AT 1,K+3;CHR$ (H+37)
  54 PRINT AT 2,K;A$(1,X TO U)
  56 PRINT AT 3,K;A$(2,X TO U)
  57 LET V2=V
  58 FOR J=4 TO 18
  60 IF V>V1 THEN GOTO 73
  61 PRINT AT J,0;CHR$ (V+35);".";A$(V,141 TO 149)
  62 PRINT AT J,K;A$(V,X TO U)
  64 LET V=V+1
  66 NEXT J
  68 LET H=H+1
  69 LET V=V2
  70 NEXT K
  71 LET H=H2
  72 GOTO 30
  73 PRINT AT J,0;"                              "
  74 GOTO 68
  76 FOR J=1 TO 18
  78 PRINT AT J,K;"       "
  80 NEXT J
  82 GOTO 71
 500 PRINT AT 10,0;" %C%A%U%T%I%O%N: REFER TO INSTRUCTIONS     FOR RULES AND PROCEDURES"
 510 PAUSE 200
 520 CLS 
 565 PRINT AT 0,0;"1=IN,2=C,3=F,4=W,5=TC,6=TR,7=ANS" 
 580 INPUT Q
 590 IF Q<1 OR Q>7 THEN GOTO 570
 600 GOSUB 12
 610 GOTO 700+((Q-1)*1000)
 700 LET Q1=0
 701 CLS 
 702 DIM A$(22,149)
 705 LET H=1
 710 GOSUB 22
 715 FOR K=11 TO 25 STEP 7
 716 DIM X$(6)
 717 PRINT AT 0,0;"INPUT COLUMN NAME;*=END"
 720 PRINT AT 1,K+3;CHR$ (H+37)
 725 PRINT AT 2,K;"%       "
 727 PRINT AT 3,K;"       "
 730 INPUT X$
 732 GOSUB 12
 735 IF X$(1)="*" THEN GOTO 805
 740 GOSUB 16
 745 LET A$(1,X TO U)=X$(1 TO 6)
 750 PRINT AT 2,K;A$(1,X TO U)
 765 PRINT AT 0,0;"INPUT COLUMN FUNCTION"
 767 PRINT AT 3,K;"%     "
 770 INPUT A$(2,X TO U)
 775 GOSUB 12
 785 LET H=H+1
 790 PRINT AT 3,K;A$(2,X TO U)
 792 LET V=1
 795 NEXT K
 800 GOTO 715
 805 LET H1=H-1
 810 LET H=1
 820 LET V=3
 825 LET L=18
 830 FOR K=4 TO L
 835 PRINT AT 0,0;"INPUT ROW NAME;*=END"
 837 PRINT AT K,0;CHR$ (V+35);"."
 840 PRINT AT K,2;"%    "
 845 INPUT X$
 850 GOSUB 12
 855 IF X$(1)="*" THEN GOTO 920
 860 LET A$(V,141 TO 144)=X$(1 TO 4)
 865 PRINT AT K,2;A$(V,141 TO 144)
 870 PRINT AT 0,0;"INPUT ROW FUNCTION"
 875 PRINT AT K,6;"%     "
 880 INPUT A$(V,145 TO 149)
 885 GOSUB 12
 890 PRINT AT K,6;A$(V,145 TO 149)
 895 LET V=V+1
 900 NEXT K
 905 IF L=8 THEN GOTO 820
 910 LET L=8
 915 GOTO 830
 920 LET V1=V-1
 925 LET H=1
 930 LET V=3
 935 PRINT AT 0,0;"INPUT VALUES"
 940 FOR K=11 TO 25 STEP 7
 945 IF H>H1 THEN GOTO 1065
 950 GOSUB 16
 952 PRINT AT 1,K+3;CHR$ (H+37)
 955 PRINT AT 2,K;A$(1,X TO U)
 957 PRINT AT 3,K;A$(2,X TO U)
 960 FOR J=4 TO 18
 965 PRINT AT J,K;"       "
 970 NEXT J
 980 LET L=18
 985 FOR J=4 TO L
 986 IF V>V1 THEN GOTO 1045
 995 PRINT AT J,0;CHR$ (V+35);".";A$(V,141 TO 149)
 997 LET I=(H*7)-6
 998 IF A$(V,145)="=" OR A$(2,X)="=" THEN GOTO 1130
 1000 PRINT AT J,K;"%       "
 1010 INPUT A$(V,I TO I+6)
 1015 PRINT AT J,K;A$(V,I TO I+6)
 1020 LET V=V+1
 1025 NEXT J
 1030 IF V1<16 OR L=8 THEN GOTO 1045
 1035 LET L=8
 1040 GOTO 985
 1045 LET H=H+1
 1050 LET V=3
 1055 NEXT K
 1060 GOTO 940
 1065 GOSUB 12
 1067 PRINT AT 0,0;"INPUT CONSTANTS"
 1070 LET Z=1
 1075 DIM W$(120)
 1080 FOR K=0 TO 24 STEP 8
 1085 FOR J=19 TO 21
 1090 PRINT AT J,K;"W";CHR$ (37+Z);"=";
 1095 LET W1=(5*Z)-4
 1100 INPUT X$
 1105 IF X$(1)="*" THEN GOTO 565
 1107 LET W$(W1 TO W1+4)=X$(1 TO 4)
 1110 LET Z=Z+1
 1112 PRINT W$(W1 TO W1+4)
 1115 NEXT J
 1120 NEXT K
 1125 GOTO 565
 1130 LET A$(V,I)="0"
 1135 GOTO 1015
 1700 LET H=1
 1710 LET V=3
 1720 PRINT AT 0,0;"MOVE CELL TO 1ST COL £ ROW"
 1725 GOSUB 10
 1730 GOSUB 46
 1740 GOSUB 12
 1750 PRINT AT 0,0;"INPUT NEW VALUE"
 1760 GOSUB 16
 1770 INPUT A$(V,X TO U)
 1780 PRINT AT 4,11;A$(V,X TO U)
 1790 PRINT AT 0,0;"ANOTHER CHANGE Y OR N"
 1800 INPUT X$
 1810 IF X$(1)="Y" THEN GOTO 1730
 1820 GOTO 565
 2700 CLS 
 2705 FOR H=1 TO H1
 2710 GOSUB 16
 2720 PRINT AT H,0;CHR$ (H+37);".";A$(1,X TO U);" ";A$(2,X TO U)
 2730 NEXT H
 2740 PRINT AT 0,0;"INPUT COLUMN LETTER,*=FINISHED"
 2750 INPUT X$
 2760 IF X$(1)="*" THEN GOTO 2860
 2770 LET H=(CODE X$)-37
 2780 PRINT AT H,10;"%     "
 2800 GOSUB 12
 2810 PRINT AT 0,0;"INPUT VALUE"
 2820 GOSUB 16
 2830 INPUT A$(2,X TO U)
 2835 GOSUB 12
 2840 PRINT AT H,10;A$(2,X TO U)
 2850 GOTO 2740
 2860 CLS 
 2870 FOR V=3 TO V1
 2880 PRINT AT V-2,0;CHR$ (V+35);".";A$(V,141 TO 149)
 2900 NEXT V
 2910 PRINT AT 0,0;"INPUT ROW LETTER,*=FINISHED"
 2920 INPUT X$
 2930 IF X$(1)<>"*" THEN GOTO 2955
 2940 CLS 
 2950 GOTO 565
 2955 LET V=CODE X$(1)-37
 2960 PRINT AT V,6;"%     "
 2970 GOSUB 12
 2980 PRINT AT 0,0;"INPUT VALUE"
 2990 INPUT A$(V+2,145 TO 149)
 3000 PRINT AT V,6;A$(V+2,145 TO 149)
 3010 GOTO 2910
 3700 CLS 
 3710 FOR K=1 TO 12
 3720 PRINT AT K,0;"W";CHR$ (37+K);"=";W$((K*5)-4 TO K*5)
 3730 PRINT AT K,15;"W";CHR$ (49+K);"=";W$(((K+12)*5)-4 TO (K+12)*5)
 3740 NEXT K
 3750 PRINT AT 0,0;"INPUT CONSTANT"
 3770 INPUT X$
 3775 GOSUB 12
 3780 LET Z=CODE X$(2)-37
 3790 PRINT AT Z-(12*(Z>12)),3+(15*(Z>12));"%        "
 3800 PRINT AT 0,0;"INPUT VALUE"
 3810 INPUT X$
 3820 IF X$(1)="*" THEN GOTO 565
 3830 GOSUB 12
 3840 LET W1=(Z*5)-4
 3850 LET W$(W1 TO W1+4)=X$
 3860 PRINT AT Z-(12*(Z>12)),3+(15*(Z>12));W$(W1 TO W1+4)
 3870 GOTO 3750
 4700 CLS 
 4710 PRINT AT 0,0;"INPUT COLUMN LETTER=";
 4720 INPUT X$
 4730 PRINT X$
 4740 LET H=CODE X$(1)-37
 4750 GOSUB 16
 4760 PRINT AT 2,0;"COLUMN NAME=";A$(1,X TO U)
 4765 LET Z=0
 4770 FOR V=3 TO V1
 4775 IF A$(V,X)=" " THEN GOTO 4790
 4780 LET Z=Z+VAL A$(V,X TO U)
 4790 NEXT V
 4800 PRINT AT 4,0;"COLUMN TOTAL=";Z
 4820 PRINT AT 6,0;"COLUMN AVERAGE=";(INT ((Z*100)/(V1-2)))/100
 4830 PRINT AT 8,0;"ANOTHER COLUMN TOTAL Y OR N"
 4840 INPUT X$
 4850 IF X$(1)="N" THEN GOTO 520
 4860 CLS 
 4870 GOTO 4700
 5700 CLS 
 5710 PRINT AT 0,0;"INPUT ROW LETTER=";
 5720 INPUT X$
 5730 PRINT X$
 5740 LET V=CODE X$(1)-35
 5760 PRINT AT 2,0;"ROW NAME=";A$(V,141 TO 144)
 5765 LET Z=0
 5770 FOR H=1 TO H1
 5775 GOSUB 16
 5777 IF A$(V,X)=" " THEN GOTO 5790
 5780 LET Z=Z+VAL A$(V,X TO U)
 5790 NEXT H
 5800 PRINT AT 4,0;"ROW TOTAL=";Z
 5820 PRINT AT 6,0;"ROW AVERAGE=";(INT ((Z*100)/H1))/100
 5830 PRINT AT 8,0;"ANOTHER ROW TOTAL Y OR N"
 5840 INPUT X$
 5850 IF X$(1)="N" THEN GOTO 520
 5860 CLS 
 5870 GOTO 5700
 6700 FOR K=1 TO (H1*7)-6 STEP 7
 6710 IF A$(2,K)="£" THEN GOTO 6950
 6720 FOR V=3 TO V1
 6722 LET K1=K
 6730 IF A$(2,K1+1)="W" THEN GOTO 6770
 6740 LET H=CODE (A$(2,K1+1))-37
 6745 GOSUB 16
 6750 LET X=VAL A$(V,X TO U)
 6760 GOTO 6800
 6770 LET Z=CODE (A$(2,K1+2))-37
 6780 LET Z=(Z*5)-4
 6790 LET X=VAL W$(Z TO Z+4)
 6800 IF A$(2,K1)="+" THEN LET A$(V,K TO K+6)=STR$ ((INT (((VAL A$(V,K TO K+6))+X)*10))/10)
 6810 IF A$(2,K1)="-" THEN LET A$(V,K TO K+6)=STR$ ((INT (((VAL A$(V,K TO K+6))-X)*10))/10)
 6820 IF A$(2,K1)="*" THEN LET A$(V,K TO K+6)=STR$ ((INT (((VAL A$(V,K TO K+6))*X)*10))/10)
 6830 IF A$(2,K1)="/" AND X=0 THEN LET X=.01
 6850 IF A$(2,K1)="/" THEN LET A$(V,K TO K+6)=STR$ ((INT (((VAL A$(V,K TO K+6))*X)/10))/10)
 6870 IF A$(2,K1)<>"=" THEN GOTO 6940
 6890 LET A$(V,K TO K+6)=STR$ X
 6910 IF A$(2,K1+1)="W" OR A$(2,K1+2)=" " THEN GOTO 6940
 6920 LET K1=K+2
 6930 GOTO 6730
 6940 NEXT V
 6950 NEXT K
 6960 FOR V=3 TO V1
 6980 IF A$(V,145)="£" THEN GOTO 7210
 6990 FOR H=1 TO (H1*7)-6 STEP 7
 6995 LET K1=145
 7010 IF A$(V,K1+1)="W" THEN GOTO 7050
 7020 LET Z=CODE A$(V,K1+1)-35
 7030 LET X=VAL (A$(Z,H TO H+6))
 7040 GOTO 7080
 7050 LET Z=CODE A$(V,K1+2)-37
 7060 LET Z=(Z*5)-4
 7070 LET X=VAL W$(Z TO Z+4)
 7080 IF A$(V,K1)="+" THEN LET A$(V,H TO H+6)=STR$ ((INT (((VAL A$(V,H TO H+6))+X)*10))/10)
 7090 IF A$(V,K1)="-" THEN LET A$(V,H TO H+6)=STR$ ((INT (((VAL A$(V,H TO H+6))-X)*10))/10)
 7100 IF A$(V,K1)="*" THEN LET A$(V,H TO H+6)=STR$ ((INT (((VAL A$(V,H TO H+6))*X)*10))/10)
 7110 IF A$(V,K1)="/" AND X=0 THEN LET X=.01
 7120 IF A$(V,K1)="/" THEN LET A$(V,H TO H+6)=STR$ ((INT (((VAL A$(V,H TO H+6))/X)*10))/10)
 7130 IF A$(V,K1)<>"=" THEN GOTO 7200
 7150 LET A$(V,H TO H+6)=STR$ X
 7160 IF A$(V,K1+1)="W" OR A$(V,K1+2)=" " THEN GOTO 7200
 7180 LET K1=147
 7190 GOTO 7010
 7200 NEXT H
 7210 NEXT V
 7710 LET H=1
 7720 LET V=3
 7730 GOSUB 46
 7740 GOTO 565
 9550 SAVE "CA%L"
 9555 LET X$="CAL"
 9560 FAST 
 9565 LET N=0
 9570 FOR L=5 TO 19 STEP 7
 9575 LET N=N+1
 9580 LET C=CODE X$(N)
 9585 FOR H=0 TO 7
 9590 LET P=PEEK (7680+C*8+H)
 9595 LET V=128
 9600 FOR G=0 TO 7
 9605 IF P<V THEN GOTO 9625
 9610 PRINT AT H+3,G+L;"% "
 9615 LET P=P-V
 9620 GOTO 9630
 9625 PRINT AT H+3,G+L;"@@"
 9630 LET V=V/2
 9635 NEXT G
 9640 NEXT H
 9645 NEXT L
 9650 PRINT "      Z CALC COPYRIGHT UAS"
 9655 PRINT "BOX 612 HADDONFIELD,N.J. 08033"
 9660 PAUSE 200
 9670 CLS 
 9680 GOTO 500

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

People

No people associated with this content.

Scroll to Top