Laurie

This file is part of and ISTUG Public Domain Library 6. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 2068

Laurie is an interactive frame-by-frame animation drawing tool that uses the joystick (STICK function) to move a cursor around the screen and plot pixels or filled squares. The user can toggle drawing on or off, adjust the brush block size with ‘+’/’-‘ keys, and save completed frames as raw CODE at address 16384 with a length of 2048 bytes. A small machine code routine is poked into RAM at address 65000 and called via RANDOMIZE USR to copy display memory between two frame buffers located at 32000 and 65005/65002 address parameters. Line 410 bootstraps the machine code by parsing a packed decimal string into 12 bytes starting at address 65000, then re-runs the program.


Program Analysis

Program Structure

The program is organized into several distinct phases:

  1. Initialization / intro (lines 10–80): Clears memory above address 32000, displays a two-screen instruction sequence with BEEP/PAUSE 0 keypresses between pages.
  2. Drawing loop setup (lines 90–130): Draws a reference line, seeds cursor position at x=125, y=165, sets draw flag a=1 and block size b=0.
  3. Machine code call (lines 140–140): Calls the routine at 65000 via RANDOMIZE USR 65000 to perform a frame-buffer operation using parameters POKEd at 65002 and 65005.
  4. Main drawing loop (lines 150–330): Reads joystick and keyboard, moves cursor, and plots pixels or inverse-video squares.
  5. Frame save (lines 340–400): Copies the frame buffer back via the machine code, saves the display as CODE 16384,2048, then loops back to drawing.
  6. Bootstrap (line 410): Installs the machine code routine from a packed decimal string, then re-runs the program.

Machine Code Bootstrap

Line 410 is the entry point when the program is first loaded. It clears memory to 65000, then decodes a 12-byte machine code routine from the string literal "033000125017000064001000008237176201". The string is consumed three characters at a time using VAL a$( TO PI) — since PI truncates to 3 in integer contexts here — extracting each byte value and POKEing it sequentially from address 65000. After installation the program re-runs from line 10 with RUN.

The 12 bytes decode as follows:

AddressByte (decimal)Z80 Mnemonic (approximate)
65000033LD HL, nn (low byte follows)
65001000(low byte of address)
65002125(high byte — POKEd to 125=32000 high)
65003017LD DE, nn
65004000(low byte)
65005064(high byte — POKEd to 64=16384 high)
65006001LD BC, nn
65007000(low byte = 0)
65008008(high byte = 8, so BC=2048)
65009237ED prefix
65010176LDIR — block copy HL→DE, BC bytes
65011201RET

This is a simple Z80 LDIR block copy. By changing the high bytes at 65002 and 65005 before calling the routine, the program can copy either from the display (16384) to the frame buffer (32000) or vice versa, effectively implementing a double-buffer flip for animation.

STICK-Based Joystick Input

Lines 210–280 use the TS2068 STICK function (rendered as |) to read joystick port 1. The return values follow the standard numeric encoding: 1=up, 2=down, 4=left, 8=right, with diagonals as sums (9=up-right, 10=down-right, 5=up-left, 6=down-left). Line 210 uses |(1,1)=0 to detect the neutral (no movement) state and loop back to line 150 without moving or drawing.

Line 220 checks |(2,1)=1 (fire button) and inverts the draw flag a, toggling between draw and erase mode.

Drawing Logic and Block Size

The cursor is represented by a single pixel plotted with PLOT OVER 1 (XOR mode) twice in succession at line 150, which acts as a visible cursor that does not permanently alter the canvas. The block size variable b is adjusted by pressing ‘k’ (increase) or ‘j’ (decrease). When drawing (a=1), lines 300–310 plot the anchor pixel and then draw a square of side b using four DRAW calls. When erasing (a<>1), lines 290 and 320 use INVERSE 1 to erase the same square.

Key BASIC Idioms

  • LET x=x+(|(1,1)=8)-(|(1,1)=4) — Boolean expression used as ±1 delta, a compact idiom replacing IF/THEN chains for cardinal movement.
  • VAL a$( TO PI) — Using the constant PI (≈3.14159) as a slice index; BASIC truncates it to 3, extracting three-digit substrings for byte decoding.
  • RANDOMIZE USR 65000 — Standard idiom for calling a machine code subroutine; the return value from Z80 RET is discarded by RANDOMIZE.
  • PAUSE 0 at lines 50 and 80 — Waits indefinitely until any key is pressed, gating the instruction screens.

Bugs and Anomalies

  • Line 320 executes unconditionally when a<>1, but line 290 already branches with GO TO 320, meaning line 320’s IF a<>1 guard is redundant — though harmless.
  • Cursor boundary checking is absent; moving beyond x=0, x=255, y=0, or y=175 will cause an “Out of screen” error from PLOT/DRAW.
  • The ‘+’/’-‘ keys mentioned in the instructions (line 60) are not actually tested in the main loop; instead lines 190–200 use ‘k’ and ‘j’. This is a discrepancy between the documentation and the code.
  • Line 340 uses PRINT AT 10,0; FLASH 1; BRIGHT 1;" " with a single space — it prints only one flashing space, likely intended as a visual indicator but has minimal visible effect.
  • The SAVE "p"CODE 16384,2048 at line 380 saves only the first third of the display file (2048 bytes covers the pixel area but not the attribute area, which starts at 22528).

Content

Appears On

Library tape of the Indiana Sinclair Timex User’s Group.

Related Products

Related Articles

Related Content

Image Gallery

Laurie

Source Code

   10 CLEAR 125*256: REM 32000
   20 REM 32000 TO 34048=oldfram
   30 REM 65000=prog
   40 CLS : PRINT "This is Laurie"''"Laurie is used to facilitate theanimation process."'"You simply move the cursor with the stick and draw."''"To save a frame, press the BREAK key."
   50 BEEP .01,15: PAUSE 0
   60 PRINT '"To erase, press '0'"'"To continue drawing, press '9'"''"To increase/decrease block size,press '+' or '-'."
   70 PRINT "Once a frame is completed, and anew one is begun, the previous  frame will appear."'"You are left to erase this."
   80 BEEP .05,15: PAUSE 0
   90 CLS : REM draw
  100 PLOT 0,175-64: DRAW 255,0: LET x=125: LET y=165
  110 LET a=1
  120 LET b=0
  130 POKE 65002,125: POKE 65005,64
  140 RANDOMIZE USR 65000
  150 PLOT OVER 1,x,y: PLOT OVER 1,x,y
  160 IF INKEY$=" " THEN GO TO 340
  170 IF INKEY$="0" THEN LET a=0
  180 IF INKEY$="9" THEN LET a=1
  190 IF INKEY$="k" THEN LET b=b+1
  200 IF INKEY$="j" THEN LET b=b-1: IF b<0 THEN LET b=0
  210 IF |(1,1)=0 THEN GO TO 150
  220 IF |(2,1)=1 THEN LET a=-a
  230 LET x=x+(|(1,1)=8)-(|(1,1)=4)
  240 LET y=y+(|(1,1)=1)-(|(1,1)=2)
  250 IF |(1,1)=9 THEN LET x=x+1: LET y=y+1
  260 IF |(1,1)=10 THEN LET x=x+1: LET y=y-1
  270 IF |(1,1)=5 THEN LET x=x-1: LET y=y+1
  280 IF |(1,1)=6 THEN LET x=x-1: LET y=y-1
  290 IF a<>1 THEN PLOT INVERSE 1,x,y: GO TO 320
  300 PLOT x,y
  310 IF a=1 THEN DRAW 0,b: DRAW b,0: DRAW 0,-b: DRAW -b,0
  320 IF a<>1 THEN INVERSE 1: DRAW 0,b: DRAW b,0: DRAW 0,-b: DRAW -b,0: INVERSE 0
  330 GO TO 150
  340 PRINT AT 10,0; FLASH 1; BRIGHT 1;" "
  350 POKE 65002,64: POKE 65005,125
  360 RANDOMIZE USR 65000
  370 PRINT AT 10,1;"The drawing is copied."'"Now it will be saved under ""p""."
  380 SAVE "p"CODE 16384,2048
  390 PRINT AT 20,0;"Remember CODE not SCREEN$ "
  400 BEEP .05,15: PAUSE 0: GO TO 90
  410 CLEAR 65000: LET a$="033000125017000064001000008237176201": FOR f=65000 TO 65011: POKE f,VAL a$( TO PI): LET a$=a$(4 TO ): NEXT f: RUN 
  420 SAVE "Laurie" LINE 410

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

People

No people associated with this content.

Scroll to Top