--- title: "Power Pack 1" id: 51757 type: "computer_media" slug: "power-pack-1" url: "http://localhost/computer_media/power-pack-1/" markdown_url: "http://localhost/computer_media/power-pack-1.md" published_at: "2023-08-13T23:14:30+00:00" modified_at: "2026-04-04T20:18:03+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2022/04/20230809-041332.jpg" excerpt: "Four programs in one pack: a scrolling logo display, an auto-scaling bar chart generator, a 10-slot memory calculator, and a live equation plotter." 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: "Timex Computer Corporation" slug: "timex-computer-corporation" taxonomy: "post_tag" url: "http://localhost/tag/timex-computer-corporation/" - 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/" genre: - name: "Collection" slug: "collection" taxonomy: "genre" url: "http://localhost/type/collection/" media_type: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Power Pack 1 (1983)(Timex)(US)(TS1000)(Cassette).zip" mediadate: "1983" producer_company: - id: 11401 title: "Timex Computer Corporation" type: "company" url: "http://localhost/company/timex-computer-corporation/" related_products: - id: 13617 title: "Power Pack 1" type: "product" url: "http://localhost/product/power-pack-1/" media_type_tags: "Collection" --- # Power Pack 1 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 | Technique | Usage | | --- | --- | | `LET O=PI/PI` | Compact way to store integer 1 without a literal token | | `VAL "number"` in GO TO/GO SUB | Memory saving: numeric literals in strings are shorter than in-line constants | | `RAND USR address` | Machine code invocation without a dedicated USR variable | | POKE + RAND USR for ROM calls | Program 1 uses system addresses 16514, 16560, 16670, 16683 for display control | | Block graphics via PRINT AT | Programs 1 and 2 use ▌▐▛▜▟▙█ for borders and bar fills | | VAL E$ in a loop | Program 4 evaluates user formula strings with the current X in scope | ## 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=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