--- title: "Spinning Wheel" id: 71483 type: "computer_media" slug: "spinning-wheel" url: "http://localhost/computer_media/spinning-wheel/" markdown_url: "http://localhost/computer_media/spinning-wheel.md" published_at: "2026-09-09T09:07:55+00:00" modified_at: "2026-09-09T09:07:56+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/09/spinning-wheel.png" excerpt: "A continuously animated spinning wheel built from concentric circles and rotating spokes, driven by a Z80 machine code double-buffering routine for smooth animation." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "1987" slug: "year-1987" taxonomy: "post_tag" url: "http://localhost/tag/year-1987/" - 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: "Charles Eric Goyette" slug: "charles-eric-goyette" taxonomy: "indiv" url: "http://localhost/indiv/charles-eric-goyette/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_type: "Program" programmers: - name: "Charles Eric Goyette" slug: "charles-eric-goyette" taxonomy: "indiv" url: "http://localhost/indiv/charles-eric-goyette/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Spinning%20Wheel%20(1987)(Goyette%2C%20Charles)(TS2068)(US)(Program).zip" tsrun_member: "Spinning Wheel (1987)(Goyette, Charles)(TS2068)(US)(Program).tap" mediadate: "1987" images: - url: "http://localhost/wp-content/uploads/2026/09/spinning-wheel.png" media_type_tags: "Demo" --- # Spinning Wheel 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: 1. **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. 2. **Animation loop (lines 60–240):** Calls machine code at `USR 30000` to copy the display buffer, redraws the wheel with an incremented phase variable `q`, and loops back to line 60 indefinitely. 3. **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 30000` in 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 30012` in 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 `t` from `q` to `95+q` in steps of 5, computing spoke endpoints with SIN/COS at angle `t/50*PI` radians, then drawing each spoke with `PLOT 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 30000` and `USR 30012` — calls machine code entry points and returns the BC register value, assigned to the dummy variable `l` (the return value is not used). - The `NEXT f` at line 100 closes the `FOR f` loop opened at line 160, with the loop body spanning lines 170–230 and the unconditional branch at line 240 back to line 60 bypassing the `NEXT` until the FOR loop naturally terminates — though in practice `GO TO 60` keeps re-entering the FOR at line 160 via the jump, making `f` effectively 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 5` at line 150 and line 160 both open loops for variable `f`; the second `FOR f` at 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 NZ` sequence) 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 ```