Bi-Plot Demo is a demonstration program for the WRX16 hi-res graphics system, which splits an 8K display file into two 4K buffers (DF1 and DF2) displayed on alternating frames to create a superimposed overlay effect. The program draws axes and tick markers directly via POKE into both display buffers, then plots three mathematical curves: a sine wave (SIN(H*PI/40)) into DF1, a decaying exponential (EXP(-H/80)) into DF2, and their product into both simultaneously using machine code routines PLT1, PLT2, and PL12. Pixel coordinates are passed to the machine code via memory locations XP (16438) and PL12 (16721), with all hi-res entry points stored as named variables at lines 10–23 for readability. A low-resolution shadow of all three curves is also drawn using standard PLOT commands scaled to the bottom six lines of the display. An interactive menu (lines 600–690) lets the user switch between viewing DF1 alone, DF2 alone, both together, reversed, or normal low-res mode, with each option invoking the appropriate machine code routine.
Program Analysis
Program Structure
The program is organized into several distinct phases:
- Lines 1–3: REMs containing encoded WRX16 machine code (the routines called throughout the program reside here as data).
- Lines 4–5: Descriptive REM labels for the module and address table.
- Lines 10–24: Symbolic constant definitions — all machine code entry points and coordinate POKEs are assigned to named variables for clean referencing throughout.
- Lines 100–520: Main drawing sequence: clear both display files, draw axes, tick markers, plot three mathematical functions in hi-res and lo-res.
- Lines 525–710: Print an interactive menu, activate dual hi-res display, then loop on keypress to switch display modes.
- Lines 9990–9999: Save/startup block — saves the program, prompts the user to enable 8–16K SRAM, pauses, then auto-runs from line 10.
Machine Code Interface (WRX16 Routines)
All graphics operations are performed by calling machine code routines embedded in the REM lines via RAND USR. Pixel coordinates are passed by POKEing values into XP (address 16438, X coordinate) and YP (address 16439, Y coordinate) immediately before each call. The named entry points are:
| Variable | Address | Function |
|---|---|---|
HR1 | 16648 | Display DF1 only |
HR2 | 16653 | Display DF2 only |
HR12 | 16658 | Display both DF1 and DF2 (alternating frames) |
HRES | 16664 | Enter hi-res mode |
NRML | 16672 | Return to normal lo-res display |
CLS1 | 16681 | Clear display file 1 |
CLS2 | 16686 | Clear display file 2 |
RVRS | 16701 | Reverse hi-res displays |
PLT1 | 16713 | Plot pixel in DF1 |
PLT2 | 16717 | Plot pixel in DF2 |
PL12 | 16721 | Plot pixel in both DF1 and DF2 |
UPL1 | 16726 | Unplot (clear) pixel in DF1 |
UPL2 | 16730 | Unplot pixel in DF2 |
UP12 | 16734 | Unplot pixel in both DFs |
XP | 16438 | X coordinate register |
YP | 16439 | Y coordinate register |
Using named LET variables for machine code addresses (lines 10–24) rather than embedding raw numbers in each RAND USR call is a significant readability and maintainability technique, making the BASIC code self-documenting and easy to retarget if the routine addresses change.
Display File Layout
The WRX16 system divides an 8K hi-res display into two 4K buffers. DF1 occupies the lower 4K of the hi-res region and DF2 the upper 4K. When both are active, the hardware alternates between them on successive frames, producing a visual overlay — effectively 128×128 pixels with two independent logical layers. The horizontal axis baseline is drawn at byte offset 10240 to 10271 (line 130–160), and the corresponding row in DF2 is at offset +5984 (line 150). Vertical tick markers are placed with offsets of 2048 and 4096 bytes (lines 232–237), consistent with the 4K DF layout.
Mathematical Plotting
Three curves are plotted over H = 0 to 251 (lines 415–520):
- F1:
SIN(H*PI/40)— a sine wave covering about two full periods, plotted in DF1. - F2:
EXP(-H/80)— a decaying exponential envelope, plotted in DF2. - F1 × F2: Their product (a damped sine), plotted in both DFs simultaneously via
PL12.
The functions are stored as strings A$ and B$ and evaluated with VAL A$ and VAL B$ (lines 420–425). This is a classic BASIC technique for passing arbitrary expressions as first-class values, enabling the plotting loop to remain generic. The Y coordinate is scaled to 63 + 60*Z, centering the 128-pixel-tall hi-res display. A parallel lo-res shadow is plotted with standard PLOT at 1/4 horizontal resolution (lines 485–495), scaled to 27 + 15*Z for the six lower display lines.
Axes and Tick Marks
The horizontal axis is drawn in both DFs by POKEing 255 (all bits set) into each byte of the appropriate scan line (lines 130–160). The vertical axis is drawn using the PL12 routine with X fixed at 4, stepping Y from 0 to 127 (lines 170–210). Tick marks along the vertical axis use a bitmask of 60 (binary 00111100) POKEd at four DF offsets (lines 220–240). Horizontal tick marks are applied to DF2 (top axis) and DF1 (bottom axis) using PLT2 and PLT1 respectively across J=2 to 6 and J+59 (lines 250–330).
Interactive Menu and Mode Switching
After plotting, line 525 POKEs 0 into address 16418, then the program prints a full-screen menu using a single large PRINT AT string (line 530). The loop at lines 600–690 waits for a keypress (with a flush at line 610 to discard any held key) and dispatches to the appropriate mode-switch routine. Keys 1–5 each invoke a different RAND USR call; key 6 restores normal display and halts. Any unrecognized key simply re-enters the wait loop at line 610.
Startup and Save Block
Lines 9990–9999 form a self-contained save and launch sequence. The program saves itself (line 9991), prints a prompt requiring the user to confirm that 8–16K SRAM expansion is present (line 9993), pauses for approximately 200 seconds (PAUSE 4E4, line 9994), clears the screen, and then issues RUN (line 9999) to restart from line 10, bypassing the save block entirely on subsequent runs.
Notable Techniques and Observations
- Use of
VALon string-stored expressions (A$,B$) as a functional abstraction for the plotting loop. - All machine code entry points named with
LETat the top of the program — acts as a symbol table. - Direct memory POKE for horizontal line drawing is faster than looping through plot routines for bulk fills.
- The POKE to address 16418 at line 525 likely signals a display mode register within the WRX16 system.
- The lo-res shadow plot (lines 485–495) uses
INT(H/4)+1to downsample the 252-step hi-res X range to the 63-column lo-res display. FASTmode is engaged at line 105 for the drawing phase but the display is not returned toSLOWbefore the menu — the WRX16 display driver manages its own refresh independently of the CPU speed flag.
Content
Image Gallery
Source Code
1 REM GOSUB # <> DIM NEXT Y▛# ( CLEARLEN PAUSE W4 CLEAR▞█)4 5 4UORND NEW▘****▜# <>5ATN RND/▒)4 ▌ASN <=RND;# GOSUB ###▙"" GOSUB # GOSUB #7E£RND)L▙;Y2 GOSUB #Y PRINT ▘▛▒LN [P]▝LN [>]▝LN 4▝<>5[A]RND#[8]▝
2 REM 5Y /▒5Y▘/▀5 NEW▘6[X]RNDLN [C]INKEY$ <>5[A]RNDTAN LN [C]INKEY$ <>5▟▝TAN 5 4/▀5 K▘ (Q "##< GOSUB [K]TAN 5▜RND▘4 #LEN █#/ GOSUB A4/-AK/>LN #INKEY$ / RUN A4/?AK/"LN #INKEY$ / RUN CLEARACS VCHR$ /▖ CLEARACS V[-] GOSUB #QRNDY█X[(] AND [H]:##ACS UACS .ACS UACS .ACS UACS .I ;## NEW▛W▘ ▒ACS ▝ACS )X4£ CLEARACS V#C▖ACS AT /▝ACS ▟( FOR #TAN LN F? CLEAR#OUORND[S]C IF Y2 GOSUB #TAN
3 REM [C]INKEY$ WAIT[8]INKEY$ NXBT[6]INKEY$ RSBT[2]INKEY$ STBT[)]INKEY$ BTLP#INKEY$ GADR#INKEY$ PLBC#INKEY$ PLT*#INKEY$ UNPL#INKEY$ PLOT#INKEY$ UP12#INKEY$ UPL2#INKEY$ UPL1#INKEY$ PL12#INKEY$ PLT2#INKEY$ PLT1XINKEY$ RVRSQINKEY$ LDIRLINKEY$ CLS*IINKEY$ CLS2DINKEY$ CLS14INKEY$ NRML/INKEY$ HRES+INKEY$ SMOD>INKEY$ HR12$INKEY$ HR-2▒INKEY$ HR-1<=RNDDP-3USR RNDDP-2ATN RNDDP-1[X]RNDMODE[J]RNDDP-A[E]RNDDP-0[A]RNDDPLY▙RNDDUMYVRNDCDFGQRNDCOORORNDFRMS£RNDDFILF?SLOW[H]:ERRB
4 REM WRX16-V2D DUAL HIRES
5 REM NAMES 44A4-4494
10 LET HR1 =16648
11 LET HR2 =16653
12 LET HR12=16658
13 LET HRES=16664
14 LET NRML=16672
15 LET CLS1=16681
16 LET CLS2=16686
17 LET RVRS=16701
18 LET PLT1=16713
19 LET PLT2=16717
20 LET PL12=16721
21 LET UPL1=16726
22 LET UPL2=16730
23 LET UP12=16734
24 LET XP =16438
25 LET YP =16439
100 REM [G][R][E][Y][P][L][O][T]█[D][E][M][O]
105 FAST
108 REM CLEAR BOTH DF"S
110 RAND USR CLS1
120 RAND USR CLS2
130 FOR I=10240 TO 10271
135 REM H-LINE, DF1
140 POKE I,255
145 REM H-LINE,DF2
150 POKE I+5984,255
160 NEXT I
165 REM V-LINE, BOTH DF"S
170 POKE XP,4
180 FOR I=0 TO 127
190 POKE YP,I
200 RAND USR PL12
210 NEXT I
215 REM V-MARKERS
220 FOR I=10080 TO 8192 STEP -192
230 POKE I,60
232 POKE I+2048,60
235 POKE I+4096,60
237 POKE I+6144,60
240 NEXT I
245 REM H-MARKERS
250 FOR I=4 TO 244 STEP 10
260 POKE XP,I
270 FOR J=2 TO 6
280 POKE YP,J
290 RAND USR PLT2
300 POKE YP,J+59
310 RAND USR PLT1
320 NEXT J
330 NEXT I
340 REM LO-RES AXES
350 FOR I=0 TO 63
360 PLOT I,12
370 PLOT I,27
375 IF I>12 AND I<43 THEN PLOT 0,I
380 NEXT I
390 REM PLOT CURVES
395 REM F1:SINE CURVE
400 LET A$="SIN (H*PI/40)"
405 REM F2:DECAYING EXPONENTIAL
410 LET B$="EXP (-H/80)"
415 FOR H=0 TO 251
420 LET Z1=VAL A$
425 LET Z2=VAL B$
430 POKE XP,H+4
435 REM FUNCTION NO. 1 (DF 1)
440 POKE YP,63+60*Z1
445 RAND USR PLT1
450 REM FUNCTION NO.2 (DF 2)
455 POKE YP,63+60*Z2
460 RAND USR PLT2
465 REM FCTN.1 * FCTN.2 (BOTH)
470 POKE YP,63+60*Z1*Z2
475 RAND USR PL12
480 REM LO-RES PLOTTING
485 PLOT INT (H/4)+1,27+15*Z1
490 PLOT INT (H/4)+1,27+15*Z2
495 PLOT INT (H/4)+1,27+15*Z1*Z2
520 NEXT H
525 POKE 16418,0
530 PRINT AT 17,0;"[,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][,,][▒][1][:]█[D][I][S][P][L][A][Y]█[D][F][1]██[2][:]█[D][I][S][P][L][A][Y]█[D][F][2][▒][▒][3][:]█[D][I][S][P][L][A][Y]█[B][O][T][H]█[D][I][S][P][L][A][Y]█[F][I][L][E][S]█[▒][▒][4][:]█[R][E][V][E][R][S][E]█[H][I][G][H]█[-]█[R][E][S]█[D][I][S][P][L][A][Y][S][▒][▒][5][:]█[R][E][T][U][R][N]█[T][O]█[N][O][R][M][A][L]█[L][R]█[D][I][S][P][L][A][Y][▒][▒][6][:]█[Q][U][I][T]█[T][O]█[B][A][S][I][C]██████████████[▒][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~][~~]"
600 RAND USR HR12
610 IF INKEY$ <>"" THEN GOTO 610
620 LET Z$=INKEY$
630 IF Z$="" THEN GOTO 620
640 IF Z$="1" THEN RAND USR HR1
650 IF Z$="2" THEN RAND USR HR2
660 IF Z$="3" THEN RAND USR HR12
670 IF Z$="4" THEN RAND USR RVRS
680 IF Z$="5" THEN RAND USR NRML
690 IF Z$<>"6" THEN GOTO 610
700 RAND USR NRML
710 STOP
9990 LET S$="BIPLOT"
9991 SAVE S$
9992 PRINT S$
9993 PRINT ,,"BE SURE THAT 8-16K SRAM ENABLED,THEN PRESS ANY KEY TO START DEMO"
9994 PAUSE 4E4
9995 CLS
9996 PRINT "PLEASE WAIT ABOUT 75 SECONDS...."
9997 PAUSE 200
9998 CLS
9999 RUN
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.