Spinning Wheel renders an animated rotating wheel graphic by combining TS2068 BASIC drawing routines with a Z80 machine code routine loaded into RAM at address 30000. The machine code block (47 bytes) performs fast memory copies between the display file area and a buffer at address 30720 (0x7800), enabling smooth frame updates. The BASIC side draws concentric circles and radial spokes using CIRCLE and PLOT/DRAW, with a phase variable `q` incrementing each frame to simulate rotation. The program loops continuously through line 60, calling the machine code via USR to swap display buffers, creating a double-buffering effect.
Program Structure
The program is divided into three logical phases:
- Initialization (lines 20–50): Clears memory to address 29999 and POKEs 47 bytes of Z80 machine code into addresses 30000–30046, then jumps to the main setup loop at line 140.
- Animation loop (lines 60–240): Calls machine code at
USR 30000to copy the display buffer, redraws the wheel with an incremented phase variableq, and loops back to line 60 indefinitely. - Save line (line 250): Saves the program with auto-run from line 1 (which does not exist, so execution falls through to line 10/20).
Machine Code Routine
The 47 bytes loaded at address 30000 implement two entry points:
- Entry at 30000 (called via
USR 30000in line 60): Copies 6144 bytes from address 16384 (0x4000, the display file) to address 30720 (0x7800), preserving the current frame. - Entry at 30012 (called via
USR 30012in line 120): Copies 6144 bytes back from 30720 to 16384, restoring the saved frame. This implements a basic double-buffer scheme.
The copy is performed using the Z80 LDIR instruction (opcode ED B0), which is the standard block-move idiom on Z80 systems. The loop within the machine code (bytes at offsets 31–46) includes a delay loop using DJNZ and decrements, likely timed to synchronize with the display or slow the animation.
Display Buffer Address Calculation
Line 70 uses an unusual indirect PEEK pattern to read the destination address from within the machine code itself:
LET r= VAL "PEEK 30004+256* PEEK 30005+6144"
This reads the 16-bit address stored at bytes 30004–30005 (the DE register pair loaded by the second LD DE,nn instruction) and adds 6144 to advance it by one screen-file worth of bytes. Lines 80–90 then POKE the updated address back into the machine code, effectively walking the destination pointer forward each frame.
Wheel Drawing Technique
The wheel is constructed in two parts each frame:
- Rim: Five concentric CIRCLE calls (radii 80–84) plus an inner hub circle at radius 10, all centered at pixel coordinates (126, 85).
- Spokes: A FOR loop (line 170) iterates
tfromqto95+qin steps of 5, computing spoke endpoints with SIN/COS at anglet/50*PIradians, then drawing each spoke withPLOT 126,85: DRAW sx-126, sy-85.
The phase variable q is incremented by 1 each pass through the loop (line 230), which shifts all spoke angles by a small amount, producing the spinning illusion over successive frames.
Key BASIC Idioms
VAL "PEEK 30004+256* PEEK 30005+6144"— evaluates an expression stored as a string, a memory-saving technique that also allows dynamic expression construction.USR 30000andUSR 30012— calls machine code entry points and returns the BC register value, assigned to the dummy variablel(the return value is not used).- The
NEXT fat line 100 closes theFOR floop opened at line 160, with the loop body spanning lines 170–230 and the unconditional branch at line 240 back to line 60 bypassing theNEXTuntil the FOR loop naturally terminates — though in practiceGO TO 60keeps re-entering the FOR at line 160 via the jump, makingfeffectively unused as a counter.
Anomalies and Notes
- Line 130 (
STOP) and line 110 (CLS) are present but never reached during normal animation, as the loop at line 240 never terminates naturally. - The
FOR f=1 TO 5at line 150 and line 160 both open loops for variablef; the secondFOR fat line 160 overwrites the first, so the loop at line 150 is effectively dead code. - The destination address manipulation in lines 70–90 walks the machine code’s destination pointer by 6144 bytes each frame; over many iterations this pointer will overflow 16-bit address space unless the machine code itself resets it, which the delay/reset logic in the latter portion of the routine (bytes 31–46, including the
DEC A / JR NZsequence) appears to handle.
Source Code
10 REM \{20}\{1}>> Spinning Wheel <<\{20}\{0} by Charles Goyette \* Time Designs J/F 87
20 CLEAR 29999
30 FOR a=30000 TO 30046:READ q:POKE a,q:NEXT a
40 DATA 33,0,64,17,0,120,1,0,24,237,176,201,1,0,40,197,62,5,33,0,120,0,17,0,64,1,0,24,237,176,6,20,14,220,13,32,253,16,249,61,32,235,0,193,16,225,201
50 GO TO 140
60 LET l= USR 30000
70 LET r= VAL "PEEK 30004+256* PEEK 30005+6144"
80 POKE 30005, INT (r/256)
90 POKE 30004,r-256* PEEK 30005
100 NEXT f
110 CLS
120 LET l= USR 30012
130 STOP
140 LET q=0
150 FOR f=1 TO 5:CLS :FOR a=80 TO 84:CIRCLE 126,85,a:NEXT a:CIRCLE 126,85,10
160 FOR f=1 TO 5:CLS :CIRCLE 126,85,80:CIRCLE 126,85,81:CIRCLE 126,85,82:CIRCLE 126,85,10
170 FOR t=0+q TO 95+q STEP 5
180 LET a=t/50* PI
190 LET sx=126+79* SIN a
200 LET sy=85+79* COS a
210 PLOT 126,85:DRAW sx-126,sy-85
220 NEXT t
230 LET q=q+1
240 GO TO 60
250 SAVE "Wheel" LINE 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
