Plot

Developer(s): Owen Christianson
Date: 198x
Type: Program
Platform(s): TS 2068
Tags: Demo, Graphics

This program implements an interactive XY scatter-plot and line-graph routine that accepts user-defined axis ranges, data point coordinates, and axis labels, then renders the chart on the high-resolution graphics screen. It draws a bordered plot area (200×150 pixels) with nine evenly spaced tick marks on each axis using PLOT and DRAW commands. Data points are scaled proportionally to fit the defined axis extents, with an option to either plot individual points or connect them with line segments using DRAW. A notable feature is the Y-axis label rendering: three Z80 machine-code routines—loaded via DATA statements into RAM at address 64256—are called with RANDOMIZE USR to initialize, rotate, and mirror the character set, allowing the Y-axis label characters to be printed vertically, one per row. Axis scale values are printed using INT to strip decimal places, with the label position calculated to center text based on string length.


Program Analysis

Program Structure

The program is organized into clearly delineated sections accessed via GOSUB. Execution begins at line 5 with a jump to the initialization routine at line 9000, which loads machine code into RAM before branching back to line 6 to set address constants. Lines 10–130 handle all user input (axis bounds, data points, labels, and connect option). Line 200 clears the screen and dispatches to the relevant subroutines.

LinesPurpose
5–8Entry point; define MC routine addresses
10–130User input: ranges, data, labels, connect flag
200–300Main display driver; calls subroutines
1000–1150Draw axes and tick marks
2000–2030Plot individual data points
3000–3040Connect data points with DRAW
5000–5150Label axes; invoke MC for vertical Y label
9000–9040CLEAR, load machine code via DATA, return to line 6

Machine Code Routines

Lines 9000–9030 load 80 bytes of Z80 machine code into addresses 64256–64335 using a READ/POKE loop, after a CLEAR 64255 protects that RAM from BASIC. Three entry points are defined at lines 6–8:

  • init = 64324 — restores the standard character set pointer
  • rot = 64256 — rotates character bitmaps 90 degrees, enabling vertical text
  • mir = 64281 — mirrors the rotated character bitmaps

The routines work by copying and transforming the ROM character set into a RAM buffer at address 64000 (0xFA00) and redirecting the system variable at addresses 23606–23607 to point to it (line 5080: POKE 23606,0: POKE 23607,251, giving address 0xFB00). This is a well-known technique for custom character sets. After the Y label is printed vertically, RANDOMIZE USR init restores the original character set pointer.

Axis Drawing and Scaling

The plot area is anchored at pixel coordinate (33, 25) and spans 200 pixels wide by 150 pixels tall (lines 1000–1040). Nine tick marks are drawn at equal intervals on both axes: every 20 pixels horizontally (lines 1050–1090) and every 15 pixels vertically (lines 1100–1140). Data coordinates are scaled linearly to pixel space using the formula:

  • X pixel: 33 + (x(d)-xmin)/(xmax-xmin)*200
  • Y pixel: 25 + (y(d)-ymin)/(ymax-ymin)*150

The connected-line subroutine (lines 3000–3040) uses relative DRAW offsets computed from successive data point differences, avoiding the need to recalculate absolute positions on each step.

Axis Labeling

The X label is centered at row 21 by computing xp = 16 - xl/2 (line 5010), placing it beneath the plot. Axis scale values (min, mid-range, max) are printed at fixed column positions for both axes (lines 5040 and 5140). The Y-axis scale labels are left-justified so that their right edges align with column 4, achieved by subtracting the string length of each value from 4 (e.g., AT 18, 4-lw).

The Y label is printed vertically by iterating over each character of y$ and printing it at a different row (lines 5100–5120). The vertical position is centered with yp = 9 + yl/2.

Key BASIC Idioms and Techniques

  • Input validation loops: lines 117 and 127 re-prompt if label strings exceed display width limits (25 and 18 characters respectively).
  • RANDOMIZE USR is used as a side-effect-free machine code call, discarding the return value.
  • Axis mid-point labels print INT ((xmax-xmin)/2) rather than the true midpoint value — this is the half-range, not the midpoint of the axis. A correct mid-axis label would be xmin + (xmax-xmin)/2. This is a bug.
  • DIM x(n): DIM y(n) at line 42 allocates arrays after n is entered, correctly supporting variable-size data sets.

Bugs and Anomalies

  • Mid-axis label values (lines 5040, 5140): The program prints INT ((xmax-xmin)/2) and INT ((ymax-ymin)/2) as the middle tick label. This is the half-range, not the actual mid-axis value. The correct expression would be INT (xmin+(xmax-xmin)/2). For axis ranges that start at zero this is coincidentally correct, but for non-zero minimums the label will be wrong.
  • Subroutine mir (64281) is defined at line 8 but never called in the program body. It appears to be an unused mirror/flip transformation that was perhaps intended for an alternate vertical-text style.
  • Y-label length check at line 127 enforces a maximum of 18 characters, consistent with the 18 available plot rows, but the centering formula at line 5060 could place the label partially off-screen if yl is odd and large.

Attribution

Line 9040 contains a REM crediting the program to Owen Christianson of Buffalo, NY, suggesting this was a user-submitted or personally distributed program rather than commercial software.

Content

Appears On

Related Products

Related Articles

Related Content

Image Gallery

Plot

Source Code

    5 GO TO 9000
    6 LET init=64324
    7 LET rot=64256
    8 LET mir=64281
   10 PRINT "Plotting Routine"
   11 PRINT 
   20 INPUT "Xmax ";xmax,"Xmin ";xmin
   21 PRINT "Xmin=";xmin,"Xmax=";xmax
   30 INPUT "Ymax ";ymax,"Ymin ";ymin
   31 PRINT "Ymin=";ymin,"Ymax=";ymax
   40 INPUT "number of data points ",n
   41 PRINT "number of data points=";n
   42 DIM x(n): DIM y(n)
   50 FOR d=1 TO n
   55 PRINT AT 21,0;"data point number ";d
   60 INPUT "x=";x(d),"y=";y(d)
   70 NEXT d
  110 INPUT "input X label ";x$
  115 PRINT AT 6,0;"X label: ";x$
  116 LET xl=LEN x$
  117 IF xl>25 THEN GO TO 110
  120 INPUT "input Y label ";y$
  125 PRINT "Y label: ";y$
  126 LET yl=LEN y$
  127 IF yl>18 THEN GO TO 120
  130 INPUT "connect data points?";c$
  131 IF c$="y" THEN PRINT "data points will be connected"
  200 CLS 
  210 GO SUB 1000
  220 IF c$<>"y" THEN GO SUB 2000
  230 IF c$="y" THEN GO SUB 3000
  250 GO SUB 5000
  300 STOP 
 1000 PLOT 33,25
 1010 DRAW 200,0
 1020 DRAW 0,150
 1030 DRAW -200,0
 1040 DRAW 0,-150
 1050 FOR i=1 TO 9
 1060 PLOT 33+20*i,25
 1070 DRAW 0,2
 1080 PLOT 33+20*i,175
 1090 DRAW 0,-2
 1100 PLOT 33,25+15*i
 1110 DRAW 2,0
 1120 PLOT 233,25+15*i
 1130 DRAW -2,0
 1140 NEXT i
 1150 RETURN 
 2000 FOR d=1 TO n
 2010 PLOT 33+(x(d)-xmin)/(xmax-xmin)*200,25+(y(d)-ymin)/(ymax-ymin)*150
 2020 NEXT d
 2030 RETURN 
 3000 PLOT 33+(x(1)-xmin)/(xmax-xmin)*200,25+(y(1)-ymin)/(ymax-ymin)*150
 3010 FOR d=2 TO n
 3020 DRAW (x(d)-x(d-1))/(xmax-xmin)*200,(y(d)-y(d-1))/(ymax-ymin)*150
 3030 NEXT d
 3040 RETURN 
 5000 LET xl=LEN x$
 5010 LET xp=16-xl/2
 5030 PRINT AT 21,xp;x$
 5040 PRINT AT 19,4;INT xmin;AT 19,16;INT ((xmax-xmin)/2);AT 19,29;INT xmax
 5050 LET yl=LEN y$
 5060 LET yp=9+yl/2
 5070 RANDOMIZE USR init
 5080 POKE 23606,0: POKE 23607,251
 5090 RANDOMIZE USR rot
 5100 FOR p=1 TO yl
 5110 PRINT AT yp-p,0;y$(p)
 5120 NEXT p
 5130 RANDOMIZE USR init
 5131 LET p$=STR$ INT ymin
 5132 LET lw=LEN p$
 5133 LET p$=STR$ INT ((ymax-ymin)/2)
 5134 LET md=LEN p$
 5135 LET p$=STR$ INT ymax
 5136 LET up=LEN p$
 5140 PRINT AT 18,4-lw;INT ymin;AT 9,4-md;INT ((ymax-ymin)/2);AT 0,4-up;INT ymax
 5150 RETURN 
 9000 CLEAR 64255
 9010 DATA 033,000,252,001,000,252,197,221
 9011 DATA 033,080,251,006,001,022,008,229
 9012 DATA 014,000,126,160,040,002,203,193
 9013 DATA 203,001,121,035,021,032,243,221
 9014 DATA 119,000,221,035,225,203,000,048
 9015 DATA 228,035,035,035,035,035,035,035
 9016 DATA 035,209,229,033,080,251,001,008
 9017 DATA 000,237,176,225,213,124,254,255
 9018 DATA 032,197,193,201,033,000,061,017
 9019 DATA 000,252,001,000,003,237,176,201
 9020 FOR a=64256 TO 64335
 9030 READ d: POKE a,d: NEXT a: GO TO 6
 9040 REM "plot" by Owen Christianson  822 Richmond Ave.  Buffalo NY  14222

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

Scroll to Top