PixelPrint

Developer(s): Cameron Hayne
Date: 1984
Type: Program
Platform(s): TS 2068

This program demonstrates “pixelprint,” a machine code routine that renders text strings at arbitrary pixel coordinates on the screen rather than being constrained to the fixed character grid. The BASIC loader at line 9001 loads the machine code block into memory starting at address 40960 (decimal) and sets up a GOSUB-callable interface at line 9000, which passes parameters via POKEs to consecutive bytes at that address. Characters are rendered using two UDG slots (“T” and “U”) as intermediate buffers, splitting each 8×8 character into four quadrants before printing with OVER 1 to allow precise sub-character positioning. Variables p and q specify the pixel-coordinate top-left corner of the first character, while xdisp and ydisp control inter-character displacement, enabling effects like diagonal or scrolling text as demonstrated in line 9005. The program saves itself in two parts: the BASIC demonstration as “PixelPrnt” with an auto-run line, and the 395-byte machine code block as “PixelprntC” at address 40960.


Program Analysis

Program Structure

The listing is a self-contained demonstration and save utility for a machine code character renderer. It splits into four logical sections:

  1. Lines 9000: The BASIC wrapper (GOSUB target) that POKEs parameters into the machine code’s variable area and calls RANDOMIZE USR 40976 in a loop over each character of s$.
  2. Lines 9001–9003: Loader and introductory screen — loads the CODE block, sets up paper/ink, and displays usage documentation.
  3. Lines 9004–9005: Demonstration routines showing pixel-positioned strings, including a two-pass “I am not a crook!” example and an animated scrolling “BEWARE THE IDES OF MARCH” sequence.
  4. Lines 9006–9998: Comments, technical documentation, and the SAVE/CLEAR commands to package the program for distribution.

Machine Code Interface

The machine code block resides at address 40960 (0xA000). The first 16 bytes act as a parameter block, with each byte mapped to a named variable:

Address (hex)BASIC variablePurpose
A000pX pixel coordinate of first character
A001qY pixel coordinate of first character
A002xdispHorizontal displacement between characters
A003ydispVertical displacement between characters
A004s$(i)Character code for current glyph
A005rowInternal: computed row
A006colInternal: computed column
A007p’Internal: working x
A008q’Internal: working y
A009dpInternal: x pixel offset within cell
A00AdqInternal: y pixel offset within cell
A00B8-dpInternal: complement of dp
A00C8-dqInternal: complement of dq
A00Daddress of graphicPointer into ROM font data

The actual entry point called by BASIC is at address 40976 (0xA010), 16 bytes past the start of the block, leaving the first 16 bytes as the parameter/variable scratchpad. The total machine code block is 395 bytes (SAVE "PixelprntC" CODE 40960,395).

Rendering Technique

The routine uses UDG characters “T” and “U” as a two-cell working buffer. Each 8×8 source glyph is split into four quadrants based on the sub-character pixel offsets dp and dq. The quadrant data is composed into UDGs “T” and “U,” which are then PRINTed with OVER 1 at the appropriate character-grid position. Because OVER 1 XORs pixels, any previously rendered content must be erased by a second pass (explaining the repeated GO SUB pix calls in line 9005 before moving to the next string).

Key BASIC Idioms

  • Symbolic GOSUB target via variable: LET pix=9000 followed by GO SUB pix makes the subroutine address easily relocatable without editing every call site.
  • Per-character loop at GOSUB level: Line 9000 iterates FOR i=1 TO LEN s$, POKEing CODE s$(i) and invoking the machine code for each character individually, keeping the machine code routine simple (single-character input).
  • PAUSE 0 before INKEY$ pattern: Line 9003 uses PAUSE 0 as an efficient keypress wait before clearing the lower screen prompt.
  • Double-GOSUB erase pattern: In line 9005, each string is rendered twice (once to draw, once to erase with OVER 1 XOR) before the next string is placed, producing a simple animation effect.

Demonstration Sequences

Line 9004 demonstrates sub-character offset rendering: “I am not a crook!” is printed at pixel (75,67), then again at (65,63) with ydisp=-2, creating a slight diagonal repetition. Line 9005 animates “BEWARE THE IDES OF MARCH” by scrolling upward (ydisp=-8, xdisp=0), printing each word and erasing it before moving to the next, all starting from pixel column 0.

Save Structure

Line 9998 uses CLEAR before saving, which resets the RAMTOP and clears variables. Two files are saved:

  • "PixelPrnt" — the BASIC program with LINE 9001 auto-run.
  • "PixelprntC" — raw CODE at address 40960, length 395 bytes.

Line 9001 loads "PixelprntC" from tape before the demonstration begins, making the pair a self-bootstrapping distribution package.

Copyright Notice

A \* (©) symbol and “1984 Cameron Hayne” appear in the REM at the end of line 9000, embedding a machine-readable copyright notice directly in the source.

Content

Appears On

Pilot a flight from London, lay pipes against an AI opponent, find planets in the night sky, or teach a computer to guess animals — ISTUG Library 7 mixes strategy and science with some of the most inventive programs in the series.

Related Products

Related Articles

Related Content

Image Gallery

Source Code

 9000 POKE 40960,p: POKE 40961,q: POKE 40962,xdisp: POKE 40963,ydisp: FOR i=1 TO LEN s$: POKE 40964,CODE s$(i): RANDOMIZE USR 40976: NEXT i: RETURN : REM        \* 1984 Cameron Hayne
 9001 CLS : PRINT AT 10,1;"Leave recorder running","     data now loading": LOAD "PixelprntC"CODE : BEEP .7,4: PAPER 7: INK 0: CLS : LET pix=9000
 9002 PRINT AT 0,0;"pixelprint enables you to print a string "; INK 2;"s$"; INK 0;"  starting at pixel  position "; INK 2;"(p,q)"; INK 0;". Here p is the x coordinate of the top left      corner of the imaginary 8 x 8   square which will enclose the   first character of s$. Similarlyq is the y coordinate."' INK 2;"xdisp "; INK 0;"is the displacement "'"between characters in the x "'"direction (normally 8)."'"Similarly  "; INK 2;"ydisp"; INK 0;"  (normally 0)"'" Example of use:"
 9003 PRINT #1;AT 0,0;"PRESS ANY KEY": PAUSE 0: PRINT #1;AT 0,0;"             "
 9004 LET s$="I am not a crook!": LET p=75: LET q=67: LET xdisp=8: LET ydisp=0: GO SUB pix: LET p=65: LET q=63: LET ydisp=-2: GO SUB pix
 9005 PAUSE 40: LET xdisp=0: LET ydisp=-8: LET s$="BEWARE": LET p=0: LET q=60: GO SUB pix: PAUSE 5: GO SUB pix: LET s$="THE": GO SUB pix: PAUSE 5: GO SUB pix: LET s$="IDES": GO SUB pix: PAUSE 5: GO SUB pix: LET s$="OF": GO SUB pix: PAUSE 5: GO SUB pix: LET s$="MARCH": GO SUB pix: PAUSE 5: GO SUB pix
 9006 STOP : REM  Technical info:pixelprint uses user defined    graphics "T" and "U". The character is divided up into 4 parts- the top two are put into "T","U"then printed, then the bottom   two. The printing is done with  OVER 1 ,so anything already on  the screen must first be erased
 9007 REM m/c variables:  A000,p A001,q  A002,xdisp  A003,ydisp  A004,s$(i)  A005,row  A006,col  A007,p'  A008,q'  A009,dp       A00A,dq  A00B,8-dp  A00C,8-dq   A00D,address of graphic
 9998 CLEAR : SAVE "PixelPrnt" LINE 9001: BEEP .4,15: SAVE "PixelprntC"CODE 40960,395

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

Scroll to Top