Lprint

This file is part of and Timex Sinclair Public Domain Library Tape 1007. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Demo

This program installs a custom character set into memory and uses it to send text to a line printer (LPRINT) via machine code. It copies 113 bytes of machine code from address 2161 into RAM at 31744, then patches two bytes (at 31800 and 31857) to customize the routine. The user enters a string of up to 32 characters; each character’s 8-byte bitmap is looked up from arrays U() or S() depending on whether it is a standard or graphics character (CODE > 127), then packed into a buffer at 32255. Finally, the character-code mapping table at 16444 is set to a sequential 0–31 identity map and the machine code routine is invoked via USR 31744.


Program Analysis

Program Structure

The program has three distinct phases: machine code installation (lines 5–50), user input and character lookup (lines 505–700), and buffer preparation plus printer invocation (lines 9990–9999).

  1. Lines 5–50: Switches to FAST mode, copies 113 bytes of machine code from ROM/RAM at address 2161 to 31744, then patches byte at 31800 to 63 and byte at 31857 to 201 (a Z80 RET instruction).
  2. Lines 505–520: Returns to SLOW mode, prompts the user for a string to print.
  3. Lines 522–700: Re-enters FAST mode; iterates over each character of the input string, populating a 32×8 array A with bitmap rows drawn from either array U (standard characters, CODE ≤ 127) or array S (graphics/special characters, CODE > 127, offset by 155).
  4. Lines 9990–9999: Packs array A into a contiguous 256-byte buffer at 32255, writes an identity map (0–31) to the printer character table at 16444, calls the machine code via USR 31744, then loops back to line 500 (which does not exist — likely intended as 505, causing the program to restart the input prompt).

Machine Code Usage

The core printer driver is a 113-byte Z80 routine relocated from address 2161 (within the ZX81/TS1000 ROM or a previously loaded area) to 31744 in user RAM. Two bytes are patched after copying:

AddressValueLikely Purpose
3180063Operand patch (e.g. port number or jump offset)
31857201Z80 RET instruction — terminates the routine

The routine is invoked at line 9998 with USR 31744; its return value is stored in HPRINT but is not subsequently used. The system variable area at 16444 (the printer buffer or character mapping table) is pre-loaded with an identity sequence 0–31 so the routine can index characters directly.

Character Lookup Arrays

The program relies on two pre-existing numeric arrays, U and S, which must have been loaded or defined before this program runs — they are not dimensioned or populated here. Array U(code, row) provides 8-row bitmaps for standard characters (CODE 0–127). Array S(code-155, row) provides bitmaps for graphics characters whose CODE exceeds 127, with the offset of 155 normalising the index.

Output Buffer Layout

The 32-character × 8-row bitmap is packed sequentially into memory starting at address 32255. The POKE at line 9992 computes the target address as 32255 + K + 8*(J-1), placing character J‘s row K at successive bytes. This produces a 256-byte block (32 chars × 8 bytes) laid out in character-major, row-minor order, which the machine code routine then streams to the printer port.

Key BASIC Idioms and Techniques

  • FAST/SLOW switching is used carefully: FAST during memory-intensive POKE loops, SLOW during user-facing PRINT/INPUT.
  • DIM A(32,8) at line 525 allocates a fresh 2D array each time the input loop runs, effectively clearing any previous character data.
  • The space character is handled by a short-circuit GOTO 700 at line 540, leaving the corresponding row in A as all zeros (blank bitmap).
  • Line 9999 performs GOTO 500 targeting a non-existent line; execution will fall through to line 505, restarting the input prompt — a deliberate loop-back technique.

Bugs and Anomalies

  • The DIM A(32,8) statement is inside what becomes an effective loop (lines 505–9999 repeat), so the array is re-dimensioned on every pass. On a ZX81/TS1000 this is legal and clears the array, but it wastes time re-allocating memory on each iteration.
  • Array U is indexed as U(CODE X$(X), Y), but CODE of a printable character starts at 28 (space) on the ZX81. If U is not large enough to accommodate these indices, an out-of-bounds error will occur.
  • The buffer at 32255 spans addresses 32255–32510, which overlaps with the top of available RAM on a 1 KB machine; a 16 KB RAM pack is implicitly required.
  • LET HPRINT=USR 31744 stores the machine code’s return value but it is never read, making the assignment redundant.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10294-10335.

Related Products

Related Articles

Related Content

Image Gallery

Lprint

Source Code

   1 SAVE "1033%2"
   5 FAST 
  10 FOR I=0 TO 112
  20 POKE 31744+I,PEEK (2161+I)
  30 NEXT I
  40 POKE 31800,63
  50 POKE 31857,201
 505 SLOW 
 510 PRINT "ENTER TEXT TO BE LPRINTED USING NEW CHARACTER SET:"
 520 INPUT X$
 522 FAST 
 525 DIM A(32,8)
 530 FOR X=1 TO LEN X$
 540 IF X$(X)=" " THEN GOTO 700
 550 IF CODE X$(X)>127 THEN GOTO 600
 560 FOR Y=1 TO 8
 570 LET A(X,Y)=U(CODE X$(X),Y)
 580 NEXT Y
 590 GOTO 700
 600 FOR Y=1 TO 8
 610 LET A(X,Y)=S(CODE X$(X)-155,Y)
 620 NEXT Y
 700 NEXT X
\n9990 FOR J=1 TO 32
\n9991 FOR K=1 TO 8
\n9992 POKE 32255+K+8*(J-1),A(J,K)
\n9993 NEXT K
\n9994 NEXT J
\n9995 FOR H=0 TO 31
\n9996 POKE 16444+H,H
\n9997 NEXT H
\n9998 LET HPRINT=USR 31744
\n9999 GOTO 500

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

People

No people associated with this content.

Scroll to Top