--- title: "Triangle To Square" id: 56323 type: "computer_media" slug: "triangle2square" url: "http://localhost/computer_media/triangle2square/" markdown_url: "http://localhost/computer_media/triangle2square.md" published_at: "2024-08-04T10:50:00+00:00" modified_at: "2026-03-31T22:46:16+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "Watch a triangle smoothly morph into a square across 20 interpolated frames, driven by a machine code dual-screen buffer that eliminates flicker entirely." 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: "John Bell" slug: "bell-john" taxonomy: "indiv" url: "http://localhost/indiv/bell-john/" genre: - name: "Demo" slug: "demo" taxonomy: "genre" url: "http://localhost/type/demo/" media_contents: - id: 56277 title: "Timex Sinclair Public Domain Library Tape 2001" type: "computer_media" url: "http://localhost/computer_media/timex-sinclair-public-domain-library-tape-2001/" media_type: "Program" programmers: - name: "John Bell" slug: "bell-john" taxonomy: "indiv" url: "http://localhost/indiv/bell-john/" download_url: "https://archive.org/download/timex-sinclair-software-archive/Triangle2Square%20%281986%29%28Bell%2C%20John%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "1986" images: - url: "http://localhost/wp-content/uploads/2024/08/SCR-20260331-qjtd.png" article_media: - id: 8544 title: "In Sync: Exploring 2068 Video Modes" type: "article" url: "http://localhost/article/in-sync-exploring-2068-video-modes/" media_type_tags: "Demo" --- # Triangle To Square This program animates a morphing shape that transitions from a triangle to a square over 20 frames by interpolating PLOT/DRAW coordinates stored in DATA statements. Each frame’s coordinates are computed by dividing the difference between the start and end positions by the number of frames minus one, accumulating the offset each iteration. A machine code routine (53 bytes, POKEd to address 60000) is used to implement a dual-screen buffer mechanism, with port 255 toggled via OUT instructions to flip between display pages, producing flicker-free animation. The checksum of the machine code bytes is verified against 7805 before execution begins, providing a basic integrity check. *** ## Program Analysis ### Program Structure The program is divided into four logical phases: 1. **Machine code setup** (lines 140, 520–600): POKEs 53 bytes of M/C into address 60000 and verifies a checksum. 2. **Initialisation** (lines 160–280): Enters dual-screen mode, reads frame/point counts and starting coordinates into array `a()`, reads ending coordinates into `b()`. 3. **Offset computation** (lines 290–350): Overwrites `b()` with per-frame increments (the difference divided by `frames-1`). 4. **Animation loop** (lines 370–500): Draws each frame, flips the display buffer, then advances coordinates by the precomputed offsets. ### DATA Layout | Line | Contents | | --- | --- | | `100` | `frames=20`, `points=4` (incremented to 5 at line 205) | | `110` | Starting shape coordinates: PLOT origin + 4 DRAW vectors (triangle/square start) | | `120` | Ending shape coordinates: PLOT origin + 4 DRAW vectors (destination shape) | | `610` | 53 machine code bytes for the dual-screen routine | ### Coordinate Initialisation Bug Line 240 reads two values but mixes up the arrays: `READ a(a,1): READ b(a,2)`. The second READ should populate `a(a,2)`, not `b(a,2)`. As written, the first pass deposits the starting Y-coordinates directly into the `b()` array, which is then overwritten during the offset computation phase (lines 300–350). Whether the animation still produces the intended morphing depends on the specific values, but it is a clear coding error. ### Variable Name Reuse The program reuses the scalar variable `b` (lines 310, 330) as a temporary while `b()` is a two-dimensional array. This is valid BASIC because scalars and arrays occupy separate namespaces, but it makes the code harder to follow. Similarly, the loop counter `a` (a scalar) coexists with the array `a()`. ### Machine Code Dual-Screen Mechanism The 53-byte routine POKEd to address 60000 implements a page-flipping display buffer. Key OUT/IN port usage: - `OUT 255,1` / `OUT 255,0` — selects which of two video pages is visible. - `RANDOMIZE USR 60000` at line 160 initialises the dual-screen mode. - `RANDOMIZE USR 60041` at line 430 (mid-loop) performs the page flip after drawing, eliminating flicker by never displaying a partially-drawn frame. The routine also copies 27×256 bytes (the display file) using the Z80 `LDIR` instruction, visible from the byte sequence `33,0,64,17,0,96,1,0,27,237,176` (`LD HL,16384 / LD DE,24576 / LD BC,6912 / LDIR`), which copies one screen buffer to the other. ### Checksum Verification Lines 540–590 accumulate the sum of all 53 POKEd bytes into `c` and halt with `STOP` if the total does not equal 7805. This is a simple but effective guard against DATA entry errors corrupting the machine code before execution. ### Animation Interpolation The morphing is achieved by linear interpolation: for each of the 5 points, the per-frame step is `(end − start) / (frames − 1)`, stored back into `b()`. During the draw loop the step is added to `a()` each frame, so over 20 frames the shape moves smoothly from its starting to its ending geometry. Using `frames-1` as the divisor ensures the final frame exactly reaches the target coordinates. ### RESTORE Usage `RESTORE 100` at line 170 resets the DATA pointer to line 100 after the machine code subroutine has consumed the DATA at line 610 via its own `RESTORE 600` at line 530. This ensures the animation setup reads from the correct DATA lines without conflict. ## Source Code ``` 1 REM triangle to square 2 REM By John Bell-May/June 1986 T-S Horizons 100 DATA 20,4 105 REM DATA statements contain the coordinates of the PLOT and DRAW statements 110 DATA 70,40,100,0,0,100,-100,0,0,-100 120 DATA 70,40,100,0,-50,87,-25,-44,-25,-43 130 REM set up M/C 140 GO SUB 520 150 REM DUAL SCREEN MODE 160 RANDOMIZE USR 60000: OUT 255,1 170 RESTORE 100 180 REM Initalizes variables 190 READ frames 200 READ points 205 LET points=points+1 210 DIM a(points,2) 220 DIM b(points,2) 230 FOR a=1 TO points 240 READ a(a,1): READ b(a,2) 250 NEXT a 260 FOR a=1 TO points 270 READ b(a,1): READ b(a,2) 280 NEXT a 290 REM Makes the "B" array contain the offset of offset of each PLOT-DRAW point 300 FOR a=1 TO points 310 LET b=(b(a,1)-a(a,1)) 320 LET b(a,1)=b/(frames-1) 330 LET b=(b(a,2)-a(a,2)) 340 LET b(a,2)=b/(frames-1) 350 NEXT a 360 REM Draws each frame of the picture 370 FOR a=1 TO frames 380 CLS 390 PLOT a(1,1),a(1,2) 400 FOR c=2 TO points 410 DRAW a(c,1),a(c,2) 420 NEXT c 430 OUT 255,0: RANDOMIZE USR 60041: OUT 255,1 440 REM Changes coordinates for next frame 450 FOR b=1 TO points 460 LET a(b,1)=a(b,1)+b(b,1) 470 LET a(b,2)=a(b,2)+b(b,2) 480 NEXT b 490 NEXT a 500 OUT 255,0 510 STOP 520 REM POKEs M/C 530 RESTORE 600 540 LET c=0 550 FOR a=60000 TO 60052 560 READ b: POKE a,b 570 LET c=c+b 580 NEXT a 590 IF c<>7805 THEN STOP 600 RETURN 610 DATA 62,128,243,245,219,255,203,255,211,255,219,244,50,72,238,62,1,211,244,241,205,142,14,62,128,50,194,92,58,72,238,211,244,219,255,203,191,211,255,251,0,33,0,64,17,0,96,1,0,27,237,176,201 9998 STOP 9999 SAVE "ANIM" LINE 1 ```