--- title: "General Purpose Graph Plotter" id: 71052 type: "computer_media" slug: "general-purpose-graph-plotter" url: "http://localhost/computer_media/general-purpose-graph-plotter/" markdown_url: "http://localhost/computer_media/general-purpose-graph-plotter.md" published_at: "2026-08-27T00:55:01+00:00" modified_at: "2026-08-27T00:57:54+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/general-purpose-graph-plotter-1.png" alt: "General Purpose Graph Plotter screen" excerpt: "A 12-file, 12-month bar chart plotter with a two-character command menu, three simultaneous plot positions, and tape save/verify support — all in BASIC." 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 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" genre: - name: "Graphics" slug: "graphics" taxonomy: "genre" url: "http://localhost/type/graphics/" media_type: "Program" programmers: - name: "James DuPuy" slug: "james-dupuy" taxonomy: "indiv" url: "http://localhost/indiv/james-dupuy/" download_url: "https://archive.org/download/timex-sinclair-software-archive/General%20Purpose%20Graph%20Plotter%20%281984%29%28Dupuy%2C%20James%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "1984" images: - url: "http://localhost/wp-content/uploads/2026/08/general-purpose-graph-plotter-1.png" alt: "General Purpose Graph Plotter screen" - url: "http://localhost/wp-content/uploads/2026/08/general-purpose-graph-plotter-2.png" alt: "General Purpose Graph Plotter screen" - url: "http://localhost/wp-content/uploads/2026/08/general-purpose-graph-plotter-3.png" alt: "General Purpose Graph Plotter screen" media_type_tags: "Graphics" --- # General Purpose Graph Plotter General Purpose Graph Plotter is a bar-chart program that plots up to three data series simultaneously on a shared axis, each representing 12 months of numeric data. Up to 12 named files (labeled A–L) can be stored in a two-dimensional array `g(12,12)`, with five-character labels held in the string array `g$(12,5)`. The program uses a two-character instruction-code menu system (e.g., “e(a-l)” to enter data, “1-3(a-l)” to plot, “sv” to save, “fl” to view file values) and draws bars using PLOT/DRAW with INK color and OVER mode to distinguish the three plot positions. A sentinel value of −0.1 is used to mark uninitialized or “stop” data entries within a file. *** ## Program Analysis ### Program Structure The program is organized into clearly labeled sections accessed via `GO TO` and `GO SUB`. Execution begins at line 10 with a splash screen, then jumps to the Initialize Routine at line 1360 before entering the main menu loop at line 250. The major sections are: 1. **Lines 10–60:** Splash screen and startup 2. **Lines 70–90:** Subroutine to draw horizontal grid lines 3. **Lines 110–240:** Bar plotting routine 4. **Lines 250–560:** Main menu input loop and screen setup 5. **Lines 570–800:** Data entry (file input) routine 6. **Lines 810–920:** Plot dispatch routine 7. **Lines 930–1270:** File value display routine 8. **Lines 1280–1340:** Subroutine to print file list on main screen 9. **Lines 1350–1350:** Subroutine to draw screen border 10. **Lines 1360–1450:** Initialization routine 11. **Lines 1460–1640:** Instruction screen and final SAVE line ### Data Storage All data is held in two arrays declared at initialization: - `DIM g(12,12)` — a 12×12 numeric array storing up to 12 data points (months) for each of 12 named files (A–L). - `DIM g$(12,5)` — a 12-element string array holding a five-character label for each file. Files are addressed by converting the letter code (a–l) to an array index via `CODE a$(2)-96`, exploiting the ASCII layout where `CODE "a"` = 97, yielding index 1 through 12. The sentinel value `s=-.1` (line 1450) marks uninitialized or terminating data entries, allowing partial-month datasets. ### Menu System The menu at line 250 uses a two-character string `a$` entered via `INPUT`. Commands are dispatched through a cascade of `IF` tests. The full command set is: | Code | Action | | --- | --- | | `st` | STOP the program | | `in` | Show instruction screen | | `cl` | Clear plots (new screen setup) | | `e(a-l)` | Enter/update a data file | | `1-3(a-l)` | Plot file in position 1, 2, or 3 | | `sv` | SAVE program with data, auto-running at line 1460 | | `vr` | VERIFY tape save | | `fl` | Display file values | | `co` | COPY screen to printer | | `mx` | Enter new maximum Y-axis value | | `nt` | Enter a new chart title | ### Bar Plotting Routine (Lines 110–240) The plotting routine draws three-pixel-wide bars for each of the 12 months. For each month `n`, the X position is `n*16` and the bar height is scaled as `z*(100/m)`, where `m` is the current Y-axis maximum. The three plot positions `p1`, `p2`, `p3` (values 44, 49, 53) provide a small horizontal offset so bars for different series sit side by side. INK colors differentiate the series: INK 1 for position 1, INK 2 for position 2, INK 8 (black) for position 3. The middle pixel of each bar is drawn with `OVER 1` (line 220), which XORs it onto the display — this is used to provide a visual highlight stripe down the center of each bar. A bar that would exceed the maximum is clamped to `m` with a flag `za=1` that adds one extra pixel to indicate clipping. Negative or zero values are handled at line 230: if `z<=0`, a single pixel is plotted at the baseline (y=49) using `OVER o`. ### Month Label Strings Month abbreviations are stored across three string variables that together spell out the months vertically: - `l$` = `" J F M A M J J A S O N D"` - `m$` = `" a e a p a u u g e c o e "` - `n$` = `" n b r l y n l t p t v c"` These are printed as three rows on the graph screen (line 530) and also used in the file values display (lines 1060–1090), where individual characters are accessed by index `v=d*2` to step through the two-character-spaced string. ### File Values Display (Lines 930–1270) The file viewer at line 930 uses a column counter `c` starting at 5 to position up to three file columns on screen, incrementing by 9 each time a file is selected (line 1190). A guard at line 1120 wraps back to the start if `c>=29`. Files A–L are listed using `CHR$` arithmetic to print the letter labels alongside their stored names from `g$`. ### ON ERR and RESET Usage Line 280 opens with `ON ERR RESET` before the `INPUT` statement. This ensures that if a BASIC error occurs during input (such as a type mismatch), the system resets the error handler rather than crashing, providing a degree of robustness to the menu loop. ### Bugs and Anomalies - **Line 400 — erroneous `AT` syntax:**`PRINT AT 1,8,, AT 1,8;h$` contains a double comma which is syntactically odd; the intent is to clear then reprint the title, but the double comma is likely a typo for a separate statement or a semicolon. - **Line 900 — incorrect offset:**`LET t=(CODE a$-48)` operates on the full string `a$` rather than `a$(1)`, so `CODE a$` returns the code of the first character — which for “1”, “2”, “3” gives 49, 50, 51, yielding `t` values of 1, 2, 3. This happens to work correctly but is not explicit in its intent. - **Line 1200 — misplaced PLOT:**`PLOT 255,0` plots to the bottom-right corner of the screen, which appears to be a stray or accidental statement unrelated to the displayed data. - **Line 1640 — unreachable SAVE:**`CLEAR :SAVE "GPGP" LINE 10` at line 1640 is never reached during normal execution (no `GO TO 1640` exists); it appears to be a developer convenience line to re-save the program from the editor. - **Line 970–990 — label arithmetic off-by-one risk:** The file list display in the `fl` routine uses `CHR$(48+e)`, `CHR$(52+e)`, `CHR$(56+e)` for `e` from 17 to 20, producing characters at codes 65–68, 69–72, 73–76 — the uppercase letters A–L spread across three columns. This is clever but fragile if the loop range changes. ### POKE Usage Lines 20 and 260 both execute `POKE 23609,15`, which sets the border color attribute byte (system variable BORDCR) to 15 — white paper, black ink — ensuring consistent border rendering after screen operations that might alter it. Line 950 uses `POKE 23693,7`, which sets the system variable ATTR_T (temporary color attributes) to value 7 (white paper, black ink, no flash/bright) before the file values display. ## Source Code ``` 10 REM "GPGP"by James G. DuPuy DATE 1/20/84 20 POKE 23609,15 30 INK 0:PAPER 7:BORDER 1:CLS 40 CLS :PRINT FLASH 1;" STOP TAPE!", 50 PRINT AT 12,0; PAPER 6; INK 2;" General Purpose Graph Plotter By James G. DuPuy 1/20/84 " 60 PAUSE 200:CLS :GO TO 1360 70 FOR u=50 TO 150 STEP 10 80 PLOT 56,u:DRAW 199,0 90 NEXT u:RETURN 110 REM Plotting Routine 120 LET f= CODE a$(2)-96 130 IF p=p1 THEN LET i=1 140 IF p=p2 THEN LET i=2 150 IF p=p3 THEN LET i=8 160 FOR n=1 TO 12 170 LET x=n*16:LET z=g(f,n) 180 LET za=0:IF z>m THEN LET z=m:LET za=1 190 FOR k=1 TO 3 200 PLOT INK i;x+k+p,50 210 LET o=0:IF k=2 THEN LET o=1 220 DRAW INK i; OVER o;0,z*(100/m)+za 230 IF z <=0 THEN PLOT OVER o;x+k+p,49 240 NEXT k:NEXT n 250 REM Menu Input Routine 260 POKE 23609,15 270 LET c$="gpgp" 280 ON ERR RESET :INPUT "ENTER INSTRUCTION CODE:";a$:IF LEN a$<2 OR LEN a$>2 THEN GO TO 280 290 IF a$="st" THEN STOP 300 IF a$="in" THEN GO TO 1460 310 IF a$="cl" THEN GO TO 440 320 IF a$(1)="e" THEN GO TO 570 330 IF a$(1)="1" OR a$(1)="2" OR a$(1)="3" THEN GO TO 810 340 IF a$="sv" THEN SAVE c$ LINE 1460 350 IF a$="vr" THEN VERIFY c$ 360 IF a$="fl" THEN GO TO 930 370 IF a$="co" THEN COPY 380 IF a$="mx" THEN GO TO 420 390 IF a$="nt" THEN INPUT "Title?:";h$:IF LEN h$>22 THEN GO TO 390 400 IF a$="nt" THEN PRINT AT 1,8,, AT 1,8;h$ 410 GO TO 250 420 REM New max routine 430 INPUT "Enter new Max value:";m 440 REM Set up new screen 450 PAPER 7:CLS 460 BORDER 1 470 PRINT AT 1,8; INK 1;h$ 480 GO SUB 1280 490 PRINT INK 2; AT 17,1;"Plot:"; AT 18,0;"1-"; AT 19,0;"2-"; AT 20,0;"3-" 500 PLOT 56,150 510 DRAW 0,-100:DRAW 199,0 520 GO SUB 70 530 PRINT INK 1; AT 16,7;l$; AT 17,7;m$; AT 18,7;n$ 540 PRINT AT 3,2; INK 2; BRIGHT 1;m 550 PLOT 0,0:DRAW 255,0:DRAW 0,175:DRAW -255,0:DRAW 0,-175 560 GO TO 250 570 REM Input Routine 580 IF CODE a$(2)>108 OR CODE a$(2)<97 THEN GO TO 250 590 LET st=1 600 IF g$(CODE a$(2)-96)=" " THEN GO TO 670 610 IF g$(CODE a$(2)-96) <>" " THEN INPUT "New file(Y)/Update old(N):";t$:IF t$="y" THEN GO TO 670 620 LET st=1 630 FOR w=1 TO 12 640 IF g(CODE a$(2)-96,w)=-.1 THEN LET st=w:GO TO 740 650 NEXT w 660 GO TO 740 670 INPUT "Enter file name(5char):";g$(CODE a$(2)-96) 680 PRINT AT 4+ CODE a$(2)-96,2;g$(CODE a$(2)-96) 690 PLOT 56,150:DRAW 0,-100 700 GO SUB 70 710 FOR b=1 TO 12 720 LET g(CODE a$(2)-96,b)=0 730 NEXT b 740 FOR a=st TO 12 750 PRINT AT 20,9;"Data for month- ";a;" ?" 760 INPUT g(CODE a$(2)-96,a) 770 IF g(CODE a$(2)-96,a)=s THEN GO TO 790 780 NEXT a 790 PRINT AT 20,8," " 800 GO TO 250 810 REM Set up for plot routine 820 IF CODE a$(2)<97 OR CODE a$(2)>108 THEN GO TO 250 830 FOR y=1 TO 12 840 IF g(CODE a$(2)-96,y) <>0 THEN GO TO 870 850 NEXT y 860 PRINT AT 20,9;"No file at:"; CHR$ (CODE a$(2)-32):PAUSE 100:PRINT AT 20,9;" ":GO TO 250 870 IF a$(1)="1" THEN LET p=p1 880 IF a$(1)="2" THEN LET p=p2 890 IF a$(1)="3" THEN LET p=p3 900 LET t=(CODE a$-48) 910 PRINT AT 17+t,2;g$(CODE a$(2)-96) 920 GO TO 110 930 REM File value on sceen 940 LET c=5 950 POKE 23693,7:CLS :PRINT AT 0,10; BRIGHT 1;" File Values " 960 FOR e=17 TO 20 970 PRINT AT e,3; CHR$ (48+e);"-";g$(e-16) 980 PRINT AT e,12; CHR$ (52+e);"-";g$(e-12) 990 PRINT AT e,21; CHR$ (56+e);"-";g$(e-8) 1000 NEXT e 1010 PLOT 0,52:DRAW 255,0 1020 GO SUB 1350 1030 PRINT AT 0,10; BRIGHT 1;" File Values " 1040 FOR d=1 TO 12 1050 LET v=d*2 1060 PRINT AT 2+d,1;l$(v) 1070 PRINT AT 2+d,2;m$(v) 1080 PRINT AT 2+d,3;n$(v);"-" 1090 NEXT d 1100 PRINT AT 16,12; BRIGHT 1;" Files: " 1110 PLOT 0,164:DRAW 255,0 1120 IF c >=29 THEN GO TO 930 1130 INPUT "Enter file (A-L):";o$:IF CODE o$<97 OR CODE o$>108 THEN GO TO 1130 1140 PRINT AT 2,c; CHR$ (CODE o$-32);"-";g$(CODE o$-96) 1150 FOR q=1 TO 12 1160 IF g(CODE o$-96,q)=s THEN PRINT AT q+2,c;"0":GO TO 1180 1170 PRINT AT q+2,c;g(CODE o$-96,q) 1180 NEXT q 1190 LET c=c+9 1200 PLOT 255,0:DRAW 0,175 1210 INPUT "(f)-File;(c)-Copy;(p)-plot:";r$ 1220 IF r$="s" THEN STOP 1230 IF r$="f" THEN GO TO 1120 1240 IF r$="c" THEN COPY 1250 IF r$="p" THEN GO TO 440 1260 IF r$="in" THEN GO TO 1460 1270 GO TO 1210 1280 INK 2 1290 PRINT AT 4,1;"Files:" 1300 FOR n=5 TO 16 1310 PRINT AT n,0; CHR$ (60+n);"-"; AT n,2;g$(n-4) 1320 NEXT n 1330 INK 0 1340 RETURN 1350 PLOT 0,0:DRAW 255,0:DRAW 0,175:DRAW -255,0:DRAW 0,-175:RETURN 1360 REM Initialize Routine 1370 DIM g(12,12) 1380 DIM g$(12,5) 1390 LET p1=44:LET p2=49:LET p3=53:LET m=100 1400 LET l$=" J F M A M J J A S O N D" 1410 LET m$=" a e a p a u u g e c o e " 1420 LET n$=" n b r l y n l t p t v c" 1430 LET c$="gpgp" 1440 LET h$="Enter your title." 1450 LET s=-.1 1460 BORDER 2:PAPER 6:CLS 1470 PRINT FLASH 1;" Instruction Codes:", 1480 PRINT "Enter ""e(a-l)"" to load a file." 1490 PRINT '"Enter ""1-3(a-l)"" to plot a file." 1500 PRINT "(1-3) is the position ploted." 1510 PRINT '"Enter ""nt"" for a new name." 1520 PRINT '"Enter ""fl"" to get file values." 1530 PRINT '"Enter ""mx"" to get new max value." 1540 PRINT "This will erase any old plots." 1550 PRINT '"Enter ""sv"" to save on tape." 1560 PRINT "This will save GPGP with Files." 1570 PRINT '"Enter ""cl"" to clear plots." 1580 PRINT '"Enter ""in"" to see Intructions." 1590 PRINT '"Enter ""co"" to copy on paper." 1600 PRINT FLASH 1;"Press C for copy,ENT to continue" 1610 PAUSE 0 1620 IF INKEY$="c" THEN COPY 1630 GO TO 440 1640 CLEAR :SAVE "GPGP" LINE 10 ```