Power Pack 1

Products: Power Pack 1
Date: 1983
Type: Cassette
Platform(s): TS 1000

Power Pack 1 is a collection of four separate BASIC programs: a scrolling “TIMEX” logo display, a bar chart generator, a ten-slot memory calculator with save capability, and a function plotter. The logo program uses POKE and RAND USR calls into the system ROM (addresses 16514, 16560, 16683) to drive display effects, cycling through characters in a string via a looping CODE lookup. The bar chart program accepts up to 12 named bars with values, scales them to fit a 20-row display using computed column widths, and optionally prints bar labels and values alongside the bars. The function plotter evaluates user-supplied equations via VAL on a 64-point X axis, auto-scales the result range to fit the 44-row pixel display, and uses PLOT to render the curve.


Program Analysis

Power Pack 1 contains four independent programs concatenated into a single listing. Each program uses common ZX81/TS1000 BASIC idioms such as LET O=PI/PI (to obtain 1 without embedding a literal), LET Z=O-O (for 0), and VAL "number" in GO TO/GO SUB targets as a memory optimization. These constants are referenced throughout to avoid storing repeated numeric literals in the token stream.

Program 1: Scrolling Logo / Display Driver (lines 90–9080)

This program displays an animated “TIMEX” framed logo and then cycles through characters of an input string, poking each character code into a system address and invoking machine code via RAND USR.

  • LET H=CODE "▒" (line 100) stores a specific character code used as a display attribute or control value.
  • LET T=VAL "16671" and LET CT=T+VAL "4" (lines 110–120) target system memory locations; LET SF=T-O derives the USR entry point at 16670.
  • Lines 9005–9050 use POKE T,H / POKE CT,VAL "168" to configure a display register, then call RAND USR SF (address 16670) to invoke machine code, likely a ROM routine for a screen effect.
  • Line 1050 uses POKE VAL "16514",CODE A$(C) to place a character code into the keyboard buffer or display register at address 16514, feeding it to the machine code called on line 1060.
  • Line 1060 calls RAND USR VAL "16560"+USR VAL "16683" — the addition of two USR results produces a combined machine-code address, a compact way to build a dynamic call target.
  • The main loop (lines 1020–1110) cycles index C through A$, wrapping at the end, and exits on any keypress.
  • Subroutine 8000 draws a receding nested border spelling “TIMEX” using PRINT AT with decreasing indentation.
  • Subroutine 9000 constructs a decorative box border using block graphics characters (▛▜▟▙▌▐█) placed with PRINT AT.

Program 2: Bar Chart Generator (lines 10–910)

This program collects up to 12 named bars with numeric values, then renders a scaled bar chart on screen using block graphics.

  • LET Q=VAL "12" sets the maximum bar count; DIM B(Q) and DIM B$(Q,VAL "4") allocate parallel numeric and string arrays.
  • Scaling is computed as B(J)/(M/(H-O)) inside the K loop (line 260), where M is the running maximum and H=VAL "20" is the chart height in rows.
  • Column width per bar is W/Y where W=VAL "25", distributing bars evenly across 25 columns.
  • Line 265 substitutes a solid block for the fill character at the rightmost column of each bar when Y<=T (10 or fewer bars), creating a visual border.
  • Subroutine 700 prints bar name labels and value strings alongside the bars; lines 805 and 900 handle fallback positions when the bar is too short to contain the label, using computed AT expressions with string literals like VAL "12+N" — note that VAL "12+N" is a bug: VAL on a string containing an unresolved variable name will cause an error at runtime, since N is not a string variable in scope for VAL.
  • Line 243 switches to FAST mode before rendering for speed.

Program 3: Memory Calculator (lines 80–2040)

A simple ten-slot numeric memory store. The user enters arithmetic expressions as strings; VAL A$ evaluates them, and the result can be stored in any of the ten slots displayed on screen.

  • DIM A(10) holds the ten memory slots, displayed in a two-column table (slot number and value) by subroutine 1000.
  • Line 115 guards against empty input; line 116 branches to SAVE "TSCALC" (line 2030) if the user enters "S", persisting the program.
  • Subroutine 2000 stores V into A(R) and updates the on-screen table in place using PRINT AT R,9, avoiding a full redraw.
  • Line 170 clears the result line with a string of spaces before looping, keeping the display tidy.
  • This program does not use the O/Z constant idiom — it uses literal 1 and 0 directly, suggesting it was written independently of the others.

Program 4: Function Plotter (lines 90–3030)

Plots a user-defined mathematical function by evaluating the input string as an expression for each integer X from 0 to 63, auto-scaling the result to fit the display.

  • LET P=VAL "63" sets the X range; DIM D(P+O) allocates 64 elements to store computed Y values.
  • Line 580 uses LET D=VAL E$ inside the X loop — since X is a live numeric variable, any formula referencing X (e.g., "X*X") is evaluated correctly by the BASIC interpreter’s VAL.
  • The auto-scaling pass (lines 600–640) finds M (max) and MI (min), then computes SC=(M-MI)/32 to map the value range onto 32 pixel rows.
  • Line 660 computes the plot Y position as (D(X+O)+MI)/SC — note the sign: adding MI (the minimum, which may be negative) effectively shifts all values up so the minimum maps to zero. However, if MI is negative, adding it reduces the value; the correct offset should subtract MI. This is a bug that will produce a vertically misplaced or compressed plot for functions with negative minima.
  • Subroutine 1000 draws axis lines using PLOT across the full X range at row S=43 and 38, plus vertical end markers.
  • Subroutine 3000 (lines 3000–3030) unplots the previous curve using the same formula, providing a clear-before-redraw capability, though it is never called from the main loop — it appears to be dead code in this listing.
  • LET U=VAL "3000" serves double duty: as a large numeric sentinel for max/min initialization (LET M=-U, LET MI=U) and as the line number for GOSUB U at line 500, calling subroutine 3000 to unplot the old curve before re-entering the input loop.

Notable Techniques Across All Programs

TechniqueUsage
LET O=PI/PICompact way to store integer 1 without a literal token
VAL "number" in GO TO/GO SUBMemory saving: numeric literals in strings are shorter than in-line constants
RAND USR addressMachine code invocation without a dedicated USR variable
POKE + RAND USR for ROM callsProgram 1 uses system addresses 16514, 16560, 16670, 16683 for display control
Block graphics via PRINT ATPrograms 1 and 2 use ▌▐▛▜▟▙█ for borders and bar fills
VAL E$ in a loopProgram 4 evaluates user formula strings with the current X in scope

Content

Appears On

Related Products

Calculator, bar graph generator, banner and polynomial equation grapher. 2K.

Related Articles

Related Content

Image Gallery

Source Code

  10 REM B▘.... ▗▖▄▝▐▞▟▘▚▌▙▀▜▛█    E£RND7▘#▘U▄RND RETURN▘TAB [K]RND GOSUB #6:RND5▙RND#[B]*****- ACS >#5 2;:▖▞▖#7#7 FAST[J]ACS >*ACS >*ACS <*ACS <*5[▒]RND▐##E:RND#76:RND( STOPSTR$ )1 ;6:RNDSGN  LPRINT $4INT )█ COPYE:RND;6:RND#TAN E£RND7▘#▘,, ▞▖VAL Y ##< FOR ▘3  GOSUB [K]>7AT ( LOAD TAN Y ▞▖:KNOT $4 UNPLOT ( SAVE TAN LN ▘INKEY$ LN ▘INKEY$ LN ▘INKEY$ LN ▘INKEY$ TAN 
  90 LET O=PI/PI
  95 LET Z=O-O
 100 LET H=CODE "▒"
 110 LET T=VAL "16671"
 120 LET CT=T+VAL "4"
 130 LET SF=T-O
 140 LET B$="▜██████████████████████████████▛"
 150 LET J=VAL "21"
 160 LET W=VAL "31"
 900 SLOW
 905 CLS
 907 GOSUB VAL "8000"
 910 GOSUB VAL "9000"
 940 INPUT A$
 950 SLOW
 1000 REM 
 1010 LET C=Z
 1020 LET C=C+O
 1040 IF C>LEN A$ THEN LET C=O
 1050 POKE VAL "16514",CODE A$(C)
 1055 PRINT AT VAL "10",VAL "28";
 1060 RAND USR VAL "16560"+USR VAL "16683"
 1070 IF INKEY$ <>"" THEN GOTO VAL "900"
 1110 GOTO VAL "1020"
 8000 FOR G=J-O TO O STEP -O
 8010 PRINT AT G+O,G+O;"       ";AT G,G;" TIMEX "
 8020 NEXT G
 8999 RETURN
 9000 PRINT AT Z,Z;"                                ";
 9005 POKE T,H
 9006 POKE CT,VAL "168"
 9010 RAND USR SF
 9020 POKE T,Z
 9030 POKE CT,VAL "48"
 9040 PRINT AT VAL "9",Z;
 9050 RAND USR SF
 9060 PRINT AT VAL "8",Z;B$;AT VAL "15",Z;"▟";B$(O+O TO W);"▙"
 9065 FOR G=1 TO 6
 9066 PRINT AT G+O,Z;"▌";AT G+O,W;"▐";AT VAL "22"-G,Z;"▌";AT VAL "22"-G,W;"▐"
 9067 NEXT G
 9070 PRINT AT O,Z;"█";AT O,W;"█";AT J,Z;"█";AT J,W;"█";
 9080 RETURN
 
  10 LET T=VAL "10"
  11 LET O=PI/PI
  12 LET Z=O-O
  13 LET Q=VAL "12"
  14 LET H=VAL "20"
  15 LET W=VAL "25"
 110 SLOW
 120 CLS
 130 PRINT AT T,T;"BAR-[G][R][A][P][H]"
 140 PAUSE 100
 160 CLS
 172 DIM B(Q)
 175 LET M=Z
 180 DIM B$(Q,VAL "4")
 181 PRINT "HOW MANY BARS ?"
 182 INPUT Y
 183 PRINT Y
 184 IF Y>Q OR Y=Z THEN GOTO VAL "160"
 185 FOR N=1 TO Y
 190 PRINT "[V][A][L][U][E] ";N;" ";
 195 INPUT B(N)
 197 IF B(N)>M THEN LET M=B(N)
 200 PRINT B(N);
 210 PRINT " [N][A][M][E] ";N;" ";
 220 INPUT B$(N)
 230 PRINT B$(N)
 235 NEXT N
 237 PRINT "TITLE"
 238 INPUT T$
 242 CLS
 243 FAST
 244 GOSUB VAL "500"
 245 FOR J=O TO Y
 247 LET S$="[▒]"
 250 FOR X=O TO W/Y-O
 260 FOR K=O TO B(J)/(M/(H-O))
 262 IF Y>T THEN GOTO VAL "270"
 265 IF X=INT (W/Y-O) THEN LET S$="█"
 270 PRINT AT H-K,X+O+((J-O)*W/Y);S$
 280 NEXT K
 290 NEXT X
 295 IF Y<VAL "09" THEN GOSUB VAL "700"
 300 NEXT J
 499 STOP
 500 FOR N=O TO W+O
 510 PRINT AT H,N;"█"
 520 NEXT N
 565 PRINT AT H+O,Z;T$
 570 RETURN
 700 REM 
 710 FOR N=1 TO LEN B$(J)
 715 IF K<LEN B$(J)+VAL "1" THEN GOTO VAL "900"
 720 PRINT AT H-K+N+1,X+((J-O)*W/Y);B$(J,N TO N)
 730 NEXT N
 732 LET Q$=STR$ B(J)
 735 FOR N=1 TO LEN Q$
 743 IF K<LEN Q$+VAL "1" THEN GOTO VAL "805"
 745 PRINT AT H-K+N,X-2+((J-O)*W/Y);Q$(N)
 750 NEXT N
 799 RETURN
 805 PRINT AT VAL "12+N",X-VAL "2"+((J-O)*W/Y);Q$(N)
 810 GOTO VAL "750"
 900 PRINT AT VAL "13+N",X+((J-O)*W/Y);B$(J,N TO N)
 910 GOTO VAL "730"
  80 SLOW
  90 DIM A(10)
 100 GOSUB 1000
 110 INPUT A$
 115 IF A$="" THEN GOTO 110
 116 IF A$="S" THEN GOTO 2030
 120 LET V=VAL A$
 130 PRINT AT 16,0;"THE RESULT IS: ";V
 140 PRINT "INTO WHAT MEMORY SHOULD I PLACE THIS VALUE?"
 150 INPUT R
 160 IF R>=1 AND R<=10 THEN GOSUB 2000
 170 PRINT AT 16,0;"                                                                              "
 180 GOTO 110
 1000 CLS
 1010 PRINT AT 0,0;"MEMORY";TAB 9;"VALUE"
 1020 FOR G=1 TO 10
 1030 PRINT G;TAB 9;A(G)
 1040 NEXT G
 1050 RETURN
 2000 LET A(R)=V
 2010 PRINT AT R,9;"            ";AT R,9;V
 2020 RETURN
 2030 SAVE "TSCAL[C]"
 2040 GOTO 110
 
  90 SLOW
 100 LET O=PI/PI
 110 LET Z=O-O
 120 LET P=VAL "63"
 130 LET E$="TSGRAPH"
 140 LET U=VAL "3000"
 150 DIM D(P+O)
 160 LET S=VAL "43"
 170 LET F=VAL "4"
 180 LET S$="                             "
 480 GOSUB VAL "1000"
 490 GOTO VAL "550"
 500 GOSUB U
 550 PRINT AT VAL "21",Z;"YOUR EQUATION?"
 560 INPUT E$
 561 PRINT AT VAL "21",Z;S$
 562 FAST
 563 GOSUB VAL "2000"
 565 LET M=-U
 567 LET MI=U
 570 FOR X=Z TO P
 580 LET D=VAL E$
 590 LET D(X+O)=D
 600 IF D>M THEN LET M=D
 610 IF D<MI THEN LET MI=D
 620 NEXT X
 630 LET D=M-MI
 640 LET SC=D/VAL "32"
 645 SLOW
 650 FOR X=F TO P-F
 660 LET Y=((D(X+O)+MI)/SC)
 665 PLOT X,Y
 670 NEXT X
 680 PAUSE U
 690 GOTO VAL "500"
 1000 FOR X=Z TO P
 1010 PLOT X,S
 1020 PLOT X,VAL "38"
 1040 NEXT X
 1050 FOR Y=S TO S-VAL "4" STEP -O
 1060 PLOT Z,Y
 1070 PLOT P,Y
 1080 NEXT Y
 2000 PRINT AT O,O;S$;AT O,O;"Y=";E$
 2010 RETURN
 3000 FOR X=F TO P-F
 3010 UNPLOT X,((D(X+O)+MI)/SC)
 3020 NEXT X
 3030 RETURN

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

People

No people associated with this content.

Scroll to Top