UDG Demo

Date: 198x
Type: Program
Platform(s): TS 2068

This program is a demonstration of UDG (User Defined Graphics) character rendering modes on the TS2068, using machine code invoked via RANDOMIZE USR to display characters in different screen positions and modes. The machine code routine is stored in line 1’s REM statement and located via a DEF FN that reads the system variable PROG pointer (PEEK 23635 + 256*PEEK 23636 + 5). Three POKE addresses — 23728 (column), 23729 (row), and 23723 (mode) — act as parameters passed to the machine code before each RANDOMIZE USR call. The program cycles through multiple UDG rendering demonstrations, including three character modes (modes 1, 2, and 3), and concludes with a TS2068-specific SAVE that stores both the BASIC program and the UDG data as a separate CODE file at address 65368 for 168 bytes.


Program Analysis

Program Structure

The program is divided into several functional phases:

  1. Lines 1–2: Machine code payload embedded in a REM statement; a DEF FN a() that locates the machine code dynamically.
  2. Lines 10–200: First demonstration sequence — renders UDG characters at various positions and modes, spelling out fragments of text (“ONG”, “SLAND”, “inclair”, ” SPECTRUM “, “IMEX”, etc.).
  3. Lines 202–220: Draws a border frame using PLOT/DRAW and waits for a keypress before continuing.
  4. Lines 500–540: Renders “GROUP” text, then falls through to the frame-drawing sequence.
  5. Lines 600–690: A nested loop over three modes and multiple column positions, rendering “TS2068” UDG text across the screen, followed by another keypress pause.
  6. Lines 700–799: Demonstrates three character modes with labels, then STOPs.
  7. Lines 810–820: Load entry point — loads the UDG CODE block and jumps to line 2.
  8. Line 9998: Save block — saves the BASIC with autorun at line 810, then saves the UDG data as a separate CODE file.

Machine Code Location Technique

Line 2 defines DEF FN a()=PEEK 23635+256*PEEK 23636+5. System variables at addresses 23635–23636 hold the PROG pointer — the address of the start of the BASIC program in RAM. Adding 5 skips past the line number (2 bytes), line length (2 bytes), and REM token (1 byte) of line 1, landing directly on the first byte of the embedded machine code. This is a standard self-relocating machine code idiom that makes the routine position-independent regardless of where BASIC is loaded in memory.

Parameter Passing Convention

Before each RANDOMIZE USR FN a() call, three system-variable locations are POKEd as parameters for the machine code routine:

AddressPurpose
23728Column / X position for the character
23729Row / Y position for the character
23723Rendering mode (1, 2, or 3)

The machine code reads these locations directly rather than receiving arguments on the stack, which is a common pattern when calling short ML routines from BASIC where passing multiple parameters cleanly is awkward.

UDG Data Storage

The UDG graphics data lives at address 65368 for 168 bytes — this is near the top of the TS2068’s 64 KB address space. 168 bytes accommodates 21 UDG character definitions (8 bytes each), matching the full set of UDGs (\a through \u). The SAVE "udg" CODE 65368,168 at line 9998 preserves this data separately from the BASIC listing so it can be reloaded at line 810 with LOAD "udg" CODE before execution begins.

REM Statement as Code Carrier

Line 1 contains the machine code as a REM statement. The zmakebas source shows it begins with !VAL \FREE !CODE \ — these are token sequences embedded directly in the REM body. Because BASIC never interprets REM content, arbitrary byte sequences including tokenised keywords and raw machine code bytes can coexist safely. The trailing \bxxxxxxxxx... sequence at the end of line 1 represents a run of UDG \b characters used as padding or data filler.

Rendering Demonstration Loop

The nested loop at lines 610–680 iterates over three modes (m = 1 TO 3) and columns (n = 0 TO 18 STEP 2). A subtle offset is applied at line 635: when m=1, the column is set to nx=n+1, staggering mode-1 characters by one pixel column relative to modes 2 and 3. This likely demonstrates sub-character horizontal positioning capability of the machine code renderer.

Notable Idioms and Anomalies

  • PAUSE 4e4 is used as a long pause (40000 frames ≈ 13 minutes) standing in for an effective “wait for keypress” — though no explicit INKEY$ check is paired with it; the PAUSE on the TS2068 is interruptible by a keypress, so this is the intended idiom.
  • Line 201 is jumped over by GO TO 500 at line 201 and GO TO 202 at line 540, so the PLOT/DRAW border-drawing code at 202–216 is shared between the two entry paths.
  • The REM strings scattered through the listing (e.g., REM "ONG", REM "SLAND") are the text data that the machine code reads from the REM body immediately following each RANDOMIZE USR call — a well-known technique where ML code uses PC advancement past the following BASIC statement to consume inline string data.
  • Line 820 jumps to line 2, not line 10, ensuring DEF FN a() is re-registered after loading before the demo begins.

Content

Appears On

Capital Area Timex Sinclair User Group’s Library Tape.

Related Products

Related Articles

Related Content

Image Gallery

UDG Demo

Source Code

    1 REM !VAL \FREE !CODE \ RETURN ( RETURN ( THEN ▚ THEN AND *U\>"PEEK #( IF RESTORE !LEN \N!@ RESTORE !VAL \FREE  NEW o>& THEN % THEN gSTR$ RESTORE !VAL \FREE  LLIST RETURN 8 RETURN "TAB \ LLIST RESTORE FREE = OR RETURN \a8p\aSTR$ X COPY OR  \ao> THEN % THEN gSTR$ RESTORE !ATTR \FREE  LLIST RETURN (r CAT >2AT \ RESTORE FREE W!ATTR \FREE  RETURN z(ON ERR*TAB \ OR STR$ r#s+:AT \ RETURN (% RETURN  x RETURN  RESTORE !CODE \ THEN F LLIST OR  LPRINT PI GO SUB BSTR$ LPRINT PI GO SUB BSTR$ "TAB \ LLIST #:AT \=2AT \ POINT !CODE \ THEN F*TAB \(PI GO SUB BA▄PI GO SUB B\ RETURN  #"TAB \ LLIST #>"PEEK >= DATA ▐! THEN ? THEN THEN - THEN ? THEN THEN ,T]!ATTR \FREE  RETURN ( FLASH OR RESTORE FREE  VERIFY *TAB \r#s+"TAB \ LLIST #STR$ *TAB \ RETURN PI GO SUB B"TAB \ LLIST #>"PEEK >=\bxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx
    2 DEF FN a()=PEEK 23635+256*PEEK 23636+5
   10 POKE 23728,4: POKE 23729,2
   20 POKE 23723,3
   30 RANDOMIZE USR FN A()
   40 REM "\l"
   50 POKE 23728,5: POKE 23729,4
   54 POKE 23723,1
   60 RANDOMIZE USR FN a()
   62 REM "ONG"
   70 POKE 23728,6: POKE 23729,3
   72 POKE 23723,3
   80 RANDOMIZE USR FN a()
   90 REM "\i"
   92 POKE 23728,7: POKE 23729,5
  100 POKE 23723,1
  110 RANDOMIZE USR FN a()
  120 REM "SLAND"
  130 POKE 23728,8: POKE 23729,4
  140 POKE 23723,3
  150 RANDOMIZE USR FN a()
  160 REM "\s"
  170 POKE 23728,9: POKE 23729,6
  180 POKE 23723,1
  185 RANDOMIZE USR FN a()
  190 REM "inclair"
  192 POKE 23728,10: POKE 23729,5
  194 POKE 23723,3
  195 RANDOMIZE USR FN a()
  196 REM " SPECTRUM "
  197 POKE 23728,11: POKE 23729,7
  198 POKE 23723,1
  199 RANDOMIZE USR FN a()
  200 REM "IMEX"
  201 GO TO 500
  202 PLOT 0,152: DRAW 255,0
  203 PLOT 0,153: DRAW 255,0
  204 PLOT 0,66: DRAW 255,0
  206 PLOT 0,65: DRAW 255,0
  210 PLOT 0,66: DRAW 0,86
  212 PLOT 1,66: DRAW 0,86
  214 PLOT 255,66: DRAW 0,86
  216 PLOT 254,66: DRAW 0,86
  220 PRINT AT 21,0;"    Hit any Key to Proceed": PAUSE 4e4: CLS : GO TO 600
  500 POKE 23728,6: POKE 23729,20
  510 POKE 23723,3
  520 RANDOMIZE USR FN a()
  530 REM "GROUP"
  540 GO TO 202
  600 DATA 0,13,20
  610 FOR m=1 TO 3
  620 READ s
  630 FOR n=0 TO 18 STEP 2
  635 LET nx=n: IF m=1 THEN LET nx=n+1
  640 POKE 23728,nx: POKE 23729,s: POKE 23723,m
  650 RANDOMIZE USR FN a()
  660 REM "TS2068"
  670 NEXT n
  680 NEXT m
  690 PRINT AT 21,0;"    Hit any Key to Proceed": PAUSE 4e4: CLS 
  700 PRINT AT 4,0;"Regular Characters"
  710 POKE 23728,6: POKE 23729,0: POKE 23723,2
  720 RANDOMIZE USR FN a()
  730 REM "Mode 2  Character"
  740 POKE 23728,9: POKE 23723,1
  750 RANDOMIZE USR FN a()
  760 REM "Mode 1 Char$"
  770 POKE 23728,11: POKE 23723,3
  780 RANDOMIZE USR FN a()
  790 REM "Mode 3 Char$"
  799 STOP 
  810 LOAD "udg"CODE 
  814 CLS 
  820 GO TO 2
 9998 SAVE "udg-demo" LINE 810: SAVE "udg"CODE 65368,168

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

People

No people associated with this content.

Scroll to Top