--- title: "Data Storage and Display System" id: 58368 type: "computer_media" slug: "data-storage-and-display-system" url: "http://localhost/computer_media/data-storage-and-display-system/" markdown_url: "http://localhost/computer_media/data-storage-and-display-system.md" published_at: "2024-11-17T03:35:09+00:00" modified_at: "2026-04-03T07:58:05+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2024/11/DS_DS.jpeg" excerpt: "A complete data-management suite with menus, up to 25 named files of 60 points each, statistics, bar graphing, and cassette save." 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: "TS 1000" slug: "ts1000" taxonomy: "post_tag" url: "http://localhost/tag/ts1000/" - name: "ZX-Panding" slug: "zx-panding" taxonomy: "post_tag" url: "http://localhost/tag/zx-panding/" model: - name: "Timex/Sinclair 1000" slug: "ts-1000" taxonomy: "model" url: "http://localhost/model/ts-1000/" indiv: - name: "Al Bandy" slug: "al-bandy" taxonomy: "indiv" url: "http://localhost/indiv/al-bandy/" genre: - name: "Database" slug: "database" taxonomy: "genre" url: "http://localhost/type/database/" media_type: "Program" programmers: - name: "Al Bandy" slug: "al-bandy" taxonomy: "indiv" url: "http://localhost/indiv/al-bandy/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Data%20Storage%20and%20Display%20System%20%281982%29%28Al%20Bandy%29%28TS1000%29%28US%29%28Program%29.zip" mediadate: "1982" producer_company: - id: 11477 title: "ZX-Panding, Ltd." type: "company" url: "http://localhost/company/zx-panding/" images: - url: "http://localhost/wp-content/uploads/2024/11/DS_DS.jpeg" - url: "http://localhost/wp-content/uploads/2024/11/Tape-3.jpg" related_products: - id: 12315 title: "Data Storage and Display System" type: "product" url: "http://localhost/product/data-storage-and-display-system/" media_type_tags: "Database" --- # Data Storage and Display System This is a multi-file data storage and display system for the ZX81/TS1000, written in 1982 by Al Bandy for ZX-Panding, Ltd. of Newton, NC. It manages up to 25 named files, each holding up to 60 numeric data points, with menu-driven options to open, enter, correct, list, graph, and save files to cassette tape. The program tracks per-file minimum and maximum value indices in separate arrays (L and N arrays), computes running means and sums, and renders a column bar graph using PLOT with dynamic scaling to fit the display. Initialization is separated into lines 2000–2090, which must be run first via GOTO 50 (actually line 2000 area), then the main program re-entered at line 50 after dimensioning. *** ## Program Structure The program is split into three logical regions: 1. **Lines 1–5:** Boot-guard warning. If the user accidentally hits RUN, these lines print a warning not to do so, then `STOP`. They advise re-entering via `GOTO 50` (which would reach line 100 via the nearest executable line). 2. **Lines 100–970:** Main menu loop and all user-facing operations (open file, list titles, enter data, correct data, tabular list, graph, save, end). 3. **Lines 1000–1920:** Subroutines — data entry (1000), min/max tracking (1200), file-title lister (1300), file stats/tabular display (1400), graphing engine (1500–1670), return-to-menu prompt (1800), and keypress-wait input (1900). 4. **Lines 2000–2090:** One-time initialization: dimensions all arrays and seeds `L` and `H` to 1, then `STOP`s. ## Array Layout | Array | Dimensions | Purpose | | --- | --- | --- | | `D(F,60)` | 25×60 | Numeric data points per file | | `E(60)` | 60 | Scaled copy of a file’s data for graphing | | `H(F)` | 25 | Index of highest value in each file | | `L(F)` | 25 | Index of lowest value in each file | | `N(F+1)` | 26 | Point count per file (dimensioned F+1 for safety) | | `Q$(F,10)` | 25 strings of 10 chars | File titles | ## Key BASIC Idioms - **Keyword-highlighted text:** Strings like `"%D%A%T%A%"` use the ZX81’s inverse-video character encoding triggered by `%` — each `%`-prefixed letter prints in inverse, producing bold/highlighted words on screen. - **GOSUB 1900 keypress wait:** Lines 1903–1905 first flush any held key (`IF INKEY$<>"" THEN GOTO 1903`), then wait for a fresh keypress (`IF INKEY$="" THEN GOTO 1905`), storing the result in `U$`. This is a standard ZX81 single-key input pattern. - **File-title display in two columns (lines 1310–1350):** The subroutine at 1300 increments `I` twice per printed line, using `TAB 16` for the second column. - **FAST/SLOW toggling:**`FAST` is set during computation-heavy sections; `SLOW` is restored before interactive input and display, as required for the ZX81’s video generation. ## Graphing Engine (Lines 1500–1670) The graphing routine copies file `I`‘s data into array `E`, then iteratively scales it to fit within a 24–37 unit display range. If the data spread (`X`) exceeds 37, values are divided by 1.5; if below 24, they are multiplied by 1.5. The loop at lines 1540–1570 feeds back into line 1520 until the range fits. This is a heuristic convergence loop with no guaranteed termination if data is pathological, though for typical datasets it converges quickly. The actual graph is drawn with `PLOT J+1, K` inside a nested loop (lines 1640–1665), drawing a vertical bar from row 4 up to the scaled value for each data point. The X-axis label at line 1637 uses block-graphic characters (`\''` = ▀) to mark positions 1, 10, 20, 30, 40, 50, 60. ## Min/Max Tracking Subroutine (Lines 1200–1220) Rather than scanning the whole array, the subroutine at 1200 updates `H(I)` and `L(I)` incrementally each time a new data point is entered. This is efficient for sequential entry but means corrections (option 4) do not recalculate the min/max indices — a known limitation. If a corrected value changes the true minimum or maximum, `H` and `L` will be stale. ## Bugs and Anomalies - **GOTO 50 vs. line 50:** Lines 1–5 and 2020–2030 instruct the user to `GOTO 50`, but there is no line 50 in the program. The ZX81 will jump to the next available line, which is line 100 (main menu). This works correctly only if initialization (line 2000) has already been run; otherwise arrays are undimensioned. - **Stale min/max after correction:** Option 4 (correct a point) calls `GOSUB 1200` after the fix, which only updates `H`/`L` if the new value exceeds the current tracked extremes. A correction that lowers the current maximum or raises the current minimum will leave incorrect range indices. - **Line 1020 references `L(I)` before any data is entered:** On a freshly opened file, `L(I)=1` and `H(I)=1`, so `D(I,1)` is displayed as both low and high (value 0). This is cosmetically odd but not a crash. - **Graphing uses `E(H(I))` and `E(L(I))` after copy (line 1520):**`H(I)` and `L(I)` are indices into the original `D` array, reused as indices into `E`. Since `E(J)=D(I,J)` is a direct copy, the same indices are valid — this is correct but relies on the positional correspondence being preserved. - **Line 130:** Three menu options (3, 4, 5) are concatenated into a single `PRINT` string with no separating newlines in the source, relying on the 32-character line wrap to produce the appearance of separate lines. This is fragile if display width assumptions change. - **`DIM N(F+1)` at line 2046:** Dimensioned as 26 elements while all other file arrays are size 25 (`F`). The extra element provides a buffer against off-by-one access but is never explicitly used. ## Source Code ``` 1 PRINT AT 6,9;"DO NOT HIT %R%U%N" 2 PRINT AT 8,1;"%Y%O%U% %H%A%V%E% %L%O%S%T% %D%A%T%A% %S%I%N%C%E% %L%A%S%T" 3 PRINT AT 10,5;"%L%O%A%D%I%N%G% %F%R%O%M% %C%A%S%S%E%T%T%E" 4 PRINT AT 13,4;"REENTER AND USE %G%O%T%O% %5%0" 5 STOP 100 FAST 105 CLS 108 PRINT 110 PRINT "%D%A%T%A% %S%T%O%R%A%G%E% %A%N%D% %D%I%S%P%L%A%Y% %S%Y%S%T%E%M COPYRIGHT 1982 BY AL BANDY FOR:%Z%X%-%P%A%N%D%I%N%G%,%L%T%D%.,BOX 25" 112 PRINT TAB 7;"NEWTON,NC 28658" 120 PRINT AT 7,11;"%M%E%N%U" 125 PRINT AT 9,0;"1-OPEN A NEW FILE" 128 PRINT "2-LIST FILE TITLES" 130 PRINT "3-ENTER DATA INTO EXISTING FILE 4-CORRECT A POINT IN A FILE 5-TABULAR LISTING OF A FILE 6-GRAPH A FILE" 136 PRINT "7-SAVE ON TO TAPE" 137 PRINT "8-%C%L%O%S%E% %O%U%T% %A% %F%I%L%E" 138 PRINT "9-%E%N%D" 140 PRINT 145 PRINT " %T%O%U%C%H% %J%O%B% %N%U%M%B%E%R% %D%E%S%I%R%E%D" 150 GOSUB 1900 160 IF U$="1" THEN GOTO 300 162 IF U$="2" THEN GOTO 550 164 IF U$="3" THEN GOTO 450 166 IF U$="4" THEN GOTO 600 168 IF U$="5" THEN GOTO 700 170 IF U$="6" THEN GOTO 750 174 IF U$="7" THEN GOTO 850 175 IF U$="8" THEN GOTO 200 176 IF U$="9" THEN GOTO 900 180 GOTO 150 200 CLS 205 GOSUB 1300 208 PRINT 210 PRINT "WHICH FILE DO YOU NEED CLOSED ?" 215 INPUT I 220 FOR J=1 TO 60 225 LET D(I,J)=0 230 NEXT J 235 LET N(I)=0 240 LET Q$(I)="" 250 GOTO 100 300 CLS 305 LET I=0 310 LET I=I+1 320 IF N(I)=0 THEN GOTO 330 325 GOTO 310 330 PRINT "WHAT IS THE TITLE OF FILE ";I 335 INPUT Q$(I) 340 PRINT TAB 4;Q$(I) 350 PRINT "HOW MANY POINTS WILL YOU ENTER INTO FILE NUMBER ";I;" ?" 360 INPUT N(I) 363 IF N(I)>60 THEN PRINT " %O%N%L%Y% %6%0% %P%O%I%N%T%S% %C%A%N% %B%E% %E%N%T%E%R%E%D%." 366 IF N(I)>60 THEN GOTO 350 370 CLS 380 LET J=0 390 LET J=J+1 395 IF J=N(I)+1 THEN GOTO 100 400 GOSUB 1000 405 GOTO 390 450 CLS 453 GOSUB 1300 456 PRINT 460 PRINT "ENTER DATA INTO WHICH FILE NO.?" 465 INPUT I 467 CLS 470 PRINT "NUMBER ";I;" IS ";Q$(I) 475 PRINT 480 PRINT N(I);" POINTS HAVE BEEN ENTERED." 485 LET J=N(I) 490 PRINT "%H%O%W% %M%A%N%Y% %M%O%R%E% %P%O%I%N%T%S% %D%O% %Y%O%U% %W%I%S%H %T%O% %E%N%T%E%R% %?" 500 INPUT A 505 LET N(I)=N(I)+A 510 IF N(I)>60 THEN GOTO 530 512 CLS 515 GOTO 390 530 LET N(I)=N(I)-A 535 PRINT "%O%N%L%Y% %6%0% %P%O%I%N%T%S% %C%A%N% %B%E% %E%N%T%E%R%E%D" 540 GOTO 475 550 CLS 555 GOSUB 1300 570 GOTO 1800 600 CLS 602 GOSUB 1300 604 PRINT 605 PRINT "CORRECTION IN WHICH FILE NUMBER?"; 610 INPUT I 620 GOSUB 1400 625 PRINT 630 PRINT 640 PRINT "WHICH POINT NUMBER IS INCORRECT ?"; 645 INPUT J 650 PRINT J 655 PRINT "WHAT IS THE CORRECT DATA ?" 660 INPUT D(I,J) 670 GOSUB 1200 680 GOTO 100 700 CLS 703 GOSUB 1300 704 PRINT 705 PRINT "WHICH FILE NUMBER DO YOU WANT LISTED ?"; 710 INPUT I 715 GOSUB 1400 720 GOTO 1800 750 CLS 753 GOSUB 1300 755 PRINT 760 PRINT "WHICH FILE NUMBER DO YOU WANT GRAPHED ?" 765 INPUT I 770 GOTO 1500 850 CLS 860 PRINT AT 3,1;"%D%O% %Y%O%U% %N%E%E%D% %T%O% %R%E%T%U%R%N% %T%O% %M%E%N%U% %?" 862 PRINT TAB 12;"%(%Y% %O%R% %N%)" 865 PRINT AT 7,5;"IF %N IS TOUCHED THEN THE" 867 PRINT AT 9,1;"%D%A%T%A% %S%T%O%R%A%G%E% %A%N%D% %D%I%S%P%L%A%Y% %S%Y%S%T%E%M" 868 PRINT AT 11,9;"WILL BE SAVED." 870 GOSUB 1900 875 LET A$="DS AND DS" 880 IF U$="N" THEN SAVE A$ 890 GOTO 100 900 CLS 910 PRINT AT 4,0;"%D%O% %Y%O%U% %N%E%E%D% %T%O% %R%E%T%U%R%N% %T%O% %M%E%N%U% %?" 913 PRINT TAB 12;"%(%Y% %O%R% %N%)" 920 PRINT 925 PRINT "IF %N IS TOUCHED THEN THE PROGRAM";TAB 12;"WILL %E%N%D." 930 GOSUB 1900 940 IF U$<>"N" THEN GOTO 100 945 PRINT 950 PRINT "%T%H%E% %P%R%O%G%R%A%M% %H%A%S% %E%N%D%E%D" 955 PRINT 960 PRINT "ENTER %G%O%T%O% %5%0 IF NEED TO CONT." 970 STOP 1000 PRINT AT 0,0;" "; 1010 PRINT " FILE ";I;" IS ";Q$(I);" " 1020 PRINT "CURRENT RANGE IS ";D(I,L(I));" TO ";D(I,H(I)) 1035 SCROLL 1040 PRINT "WHAT IS DATA POINT-";J 1045 INPUT D(I,J) 1050 GOSUB 1200 1060 PRINT AT 21,0;" DATA POINT ";J;" IS ";D(I,J) 1070 RETURN 1200 IF D(I,J)>D(I,H(I)) THEN LET H(I)=J 1210 IF D(I,J)37 THEN LET Z=1 1533 IF X>=24 AND X<=37 THEN GOTO 1600 1536 IF X<24 THEN LET Z=2 1540 FOR J=1 TO N(I) 1550 IF Z=1 THEN LET E(J)=E(J)/1.5 1555 IF Z=2 THEN LET E(J)=E(J)*1.5 1560 NEXT J 1570 GOTO 1520 1600 CLS 1610 PRINT "FILE ";I;" IS ";Q$(I);" :SUM=";V 1620 PRINT " LOW=";D(I,L(I));" HIGH=";D(I,H(I));" MEAN=";V/N(I) 1625 PRINT " CLOSING=";D(I,N(I));" (NUMBER ";N(I);" )" 1628 PRINT AT 0,0;"" 1630 FOR K=1 TO 19 1631 PRINT ": " 1633 NEXT K 1635 SLOW 1637 PRINT AT 20,0;"''1''''''10''''''20''''''30''''''40''''''50''''''60" 1640 FOR J=1 TO N(I) 1650 FOR K=4 TO (INT (E(J)-E(L(I))+4)) 1655 PLOT J+1,K 1660 NEXT K 1665 NEXT J 1668 FAST 1670 GOTO 1800 1800 PRINT AT 21,1;"%P%R%E%S%S% %E%N%T%E%R% %T%O% %R%E%T%U%R%N% %T%O% %M%E%N%U" 1810 INPUT K$ 1820 GOTO 100 1900 SLOW 1903 IF INKEY$<>"" THEN GOTO 1903 1905 IF INKEY$="" THEN GOTO 1905 1910 LET U$=INKEY$ 1915 FAST 1920 RETURN 2000 PRINT AT 8,3;"THIS IS THE INITIALIZATION" 2010 PRINT AT 10,4;"TO DIMENSION THE MEMORY." 2020 PRINT AT 13,5;"ENTER %G%O%T%O% %5%0 TO CONT." 2030 LET F=25 2040 DIM D(F,60) 2043 DIM E(60) 2045 DIM H(F) 2046 DIM N(F+1) 2049 DIM Q$(F,10) 2050 DIM L(F) 2052 FOR I=1 TO F 2055 LET L(I)=1 2058 LET H(I)=1 2060 NEXT I 2090 STOP ```