Print Sizer is a demonstration program for a machine code routine that renders BASIC strings at arbitrary sizes on screen. The machine code, 1,500 bytes long, resides at address 63000 (48K) or 31000 (16K) and is invoked via RANDOMIZE USR 63000. Seven consecutive memory locations starting at address 63010 control print parameters: character height (1–20 rows), width (1–16 columns), slant direction (−1, 0, or +1), foreground shade (0–7), background shade (0–7), attribute printing toggle, and inverse video flag. The demo program walks through progressively more complex examples—scaling, mixed dimensions, all 64 foreground/background combinations, inverse mode, and slanting—before displaying the parameter reference and optionally listing its own source. The SAVE lines at 9875 preserve both the BASIC loader and the machine code as a separate CODE file named “P. sizer C”.
Program Structure
The program is organized into three logical blocks. Lines 10–820 form the sequential demo and information display. Lines 9800–9845 are the POKE/USR subroutine that configures and invokes the machine code. Lines 9850–9875 contain utility routines: a “Press Space” pause (9850–9865), a code loader (9870), and SAVE statements (9875).
Machine Code Interface
All rendering is delegated to 1,500 bytes of machine code stored at address 63000. The BASIC side communicates with it through seven consecutive POKEs:
| Address (48K) | Address (16K) | Variable | Parameter |
|---|---|---|---|
| 63010 | 31010 | H | Height (1–20) |
| 63011 | 31011 | W | Width (1–16) |
| 63012 | 31012 | S | Slant (−1, 0, +1) |
| 63013 | 31013 | F | Foreground shade (0–7) |
| 63014 | 31014 | B | Background shade (0–7) |
| 63015 | 31015 | A | Attributes on/off (1/0) |
| 63016 | 31016 | I | Inverse (1/0) |
The machine code reads the string from Z$ and prints from the current PRINT AT position without updating it afterward, which is noted explicitly in the demo text at line 590.
Subroutine at 9805
The central subroutine at line 9805 performs all seven POKEs in sequence, then calls RANDOMIZE USR 63000 (line 9840). Using RANDOMIZE USR rather than the return value of USR avoids cluttering the display with a numeric result and discards the return value silently. The subroutine ends with RETURN at line 9845.
Key BASIC Idioms
- All seven rendering parameters are held in short single-letter variables (
H,W,S,F,B,A,I) to minimize typing and token storage. - Multiple assignments are chained on single lines (e.g.,
LET Z$="...":LET H=2:LET W=H:LET S=0:...) to reduce line overhead. PRINT AT row,col;immediately beforeGO SUB 9805sets the print cursor without advancing to a new line, exploiting the fact that the machine code prints from the current position.- The “Press Space” pause routine (9850–9865) first flushes any held key with a
INKEY$ <> ""loop, then waits for a space, a clean debounce pattern. POKE 23692,19at line 800 prevents the automatic scroll prompt when listing more than one screenful of program, allowing a full page of LIST output before pausing.
Demo Sequence
- Title screen with scaled “A PRINT UTILITY” and “DEMO” text.
- Height scaling: normal, double, treble (lines 90–130).
- Extreme height: 22-row characters (lines 140–160).
- Width scaling: normal through 16× (lines 170–220).
- Mixed height and width (lines 230–260).
- All 64 foreground/background shade combinations in a grid (lines 300–360).
- Inverse mode over the same grid (lines 380–430).
- Slant in both directions (lines 440–470).
- Attribute printing toggle to control jagged edges on slanted text (lines 480–520).
- Parameter reference screen and optional self-listing (lines 570–820).
Variable Aliasing and Case Inconsistency
The Spectrum treats uppercase and lowercase variable names as identical for single-letter variables, so H and h, Z$ and z$, etc., refer to the same storage locations. The listing uses both cases interchangeably (e.g., LET Z$= in early lines, LET z$= from line 100 onward), which is valid but inconsistent. This does not cause any runtime errors.
Notable Anomalies
- Line 760 contains
STOP :CLEAR 65367:LOAD "". TheSTOPhalts execution immediately, soCLEARandLOAD ""on the same line are unreachable dead code. - Line 9865 uses
INPUT ""solely as a pause mechanism after the space key is detected; it displays nothing but consumes a keypress, acting as an extra guard against immediately re-triggering the next section. - The REM at line 9800 is split across what appear to be continuation characters within the REM text (“CAN BE USED IN YOUR OWN PROGRAMS”), formatted to align within the 32-column display.
- Line 9870 is a self-contained loader: it clears RAM below 63000, prints a loading message, loads the code file, and restarts — designed to be the autostart line when the BASIC file is saved with
LINE 9870.
Source Code
10 REM PRINT UTILITY PROGRAM
20 REM Pete Cooke April 85
30 PAPER 6:INK 1:BORDER 6:CLS
40 LET Z$="A PRINT UTILITY":LET H=2:LET W=H:LET S=0:LET F=4:LET B=5:LET A=S:LET I=A:PRINT AT A,1;:GO SUB 9805
50 LET Z$="DEMO":LET H=8:LET W=6:LET S=0:LET F=7:LET B=S:LET A=S:LET I=A:PRINT AT 5,4;:GO SUB 9805
60 GO SUB 9850
70 REM demo
80 CLS
90 PRINT "Using this program you can printcharacters at any size, from"
100 LET z$="Normal Height":LET H=1:LET W=1:LET F=4:LET B=0:LET S=b:LET A=b:LET I=b:PRINT AT 5,5;:GO SUB 9805
110 LET z$="Double Height":LET H=2:PRINT AT 7,5;:GO SUB 9805
120 LET z$="Treble Height":LET H=3:PRINT AT 10,5;:GO SUB 9805
130 GO SUB 9850:CLS
140 PRINT "Up to 22 characters high!"
150 LET z$="Really high man":LET h=22:PRINT AT 1,0;:GO SUB 9805
160 GO SUB 9850:CLS
170 PRINT "You can also use any width..."
180 LET z$="Normal":LET h=1:LET w=h:PRINT AT 5,5;:GO SUB 9805
190 LET z$="Double width":LET w=2:PRINT AT 7,5;:GO SUB 9805
200 LET z$="Treble !":LET w=3:PRINT AT 9,5;:GO SUB 9805
210 LET z$="W":LET w=16:PRINT AT 11,5;:GO SUB 9805
220 GO SUB 9850:CLS
230 PRINT "and you can mix these sizes.."
240 LET z$="Mixed":LET h=3:LET w=4:PRINT AT 5,5;:GO SUB 9805
250 LET z$="More mixed":LET h=5:LET w=2:PRINT AT 11,5;:GO SUB 9805
260 GO SUB 9850:CLS
270 PRINT "Now you may be saying 'So what! the free tape with the horizons program could do all of that!', and this is where this program takes over..."
280 PRINT ''"Apart from simple black on whitecharacters you can choose from 8 foreground and background"'"shades"
290 LET z$=" ":LET h=2:LET w=h:FOR n=0 TO 7:PRINT AT 12,1+3*n;:LET b=n:GO SUB 9805:NEXT n
300 GO SUB 9850:CLS
310 PRINT "and mix any pair of these..."
320 LET z$="A":LET w=4:LET h=2
330 FOR f=0 TO 7:FOR b=0 TO 7
340 PRINT AT 2*b+3,4*f;:GO SUB 9805
350 NEXT b:NEXT f
360 PRINT AT 19,0;"as you can see, some"'"combinations work better than"'"others!";
370 GO SUB 9850:CLS
380 PRINT "You can also print the"'"characters in inverse!"
390 LET i=1
400 FOR f=0 TO 7:FOR b=0 TO 7
410 PRINT AT 2*b+3,4*f;:GO SUB 9805
420 NEXT b:NEXT f
430 GO SUB 9850:CLS
440 PRINT "and you can also slant the"'"letters to left or right."
450 LET z$="Slanted text":LET h=3:LET w=2:LET f=4:LET b=1:LET i=0:LET s=b:PRINT AT f,b;:GO SUB 9805
460 LET z$="and the other way":LET h=4:LET w=1:LET f=h:LET b=0:LET i=b:LET s=-1:PRINT AT 10,w;:GO SUB 9805
470 GO SUB 9850:CLS
480 PRINT "finally you can turn attribute printing on and off (this cuts the jagged edges on slanted"'"characters)"
490 LET z$="Attributes on":LET a=1:LET h=3:LET w=2:LET i=a:LET f=4:LET b=a:PRINT AT 5,a;:PAPER 5:INK a:BRIGHT a:GO SUB 9805
500 LET z$="Attributes off":LET a=0:LET h=4:LET w=2:LET i=a:LET s=-1:LET f=h:LET b=1:PRINT AT 12,b;:GO SUB 9805
510 PAPER 7:INK 0:BRIGHT 0
520 GO SUB 9850:CLS
530 LET h=10:LET w=8:LET i=0:LET f=3:LET b=1:LET s=i:LET a=b:PAPER 6:INK b:LET z$="MORE":PRINT AT i,i;:GO SUB 9805
540 LET h=2:LET w=h:LET i=1:LET f=3:LET b=i:LET z$="Information":PAPER 4:INK 0:PRINT AT 16,4;:GO SUB 9805
550 LET z$="Follows ...":PRINT AT 18,4;:GO SUB 9805
560 PAPER 7:INK 0:GO SUB 9850:CLS
570 PRINT ''"The machine code is 1500 bytes long and is at 63000 (for 48k) and 31000 (for 16k)"
580 PRINT ''"to pass a string to the code"'"simply build it up in z$ and"'"call USR 63000."
590 PRINT ''"The code will print from the"'"latest print position (USE AT)"'"but will not alter it."
600 GO SUB 9850:CLS
610 PRINT "The code uses 7 locations"'"to define the type of printing (16k in brackets)"
620 PRINT '"63010 (31010) Height (1-20)"
630 PRINT '"63011 (31011) Width (1-16)"
640 PRINT '"63012 (31012) Slant +1 or -1"; TAB 14;"(0=No slant)"
650 PRINT '"63013 (31013) Foreground"; TAB 14;"Shading (0-7)"
660 PRINT '"63014 (31014) Background"; TAB 14;"Shading (0-7)"
670 PRINT '"63015 (31015) Attributes"; TAB 14;"1=On 0=Off"
680 PRINT '"63016 (31016) Inverse"; TAB 14;"1=On 0=Off"
690 GO SUB 9850:CLS
700 PRINT ''"To see how these are used simplyLIST the program."'''"The subroutine at line 9000"'"pokes in these values from"'"basic variables."
710 GO SUB 9850:CLS
720 LET z$="The End":LET h=15:LET w=4:LET s=0:LET a=1:LET i=s:LET f=7:LET b=a:INK 2:PAPER 6:PRINT AT 2,2;:GO SUB 9805
730 LET h=1:LET w=h:LET z$=" Space to list prog.:q to quit ":LET f=4:LET b=0:LET s=-1:LET a=1:LET i=a:PRINT AT 20,b;:GO SUB 9805
740 IF INKEY$ <>"" THEN GO TO 740
750 LET i$= INKEY$
760 IF i$="q" THEN STOP :CLEAR 65367:LOAD ""
770 IF INKEY$="" THEN GO TO 750
780 IF INKEY$ <>" " THEN GO TO 780
790 PAPER 7:INK 0:PRINT ''
800 POKE 23692,19:REM stop scroll for 1 page
810 LIST
820 STOP
9800 REM SUBROUTINE TO POKE IN THEDATA ... CAN BE USED IN YOUR OWN PROGRAMS....
9805 POKE 63010,H:POKE 63011,W
9810 REM heigth^ width^
9815 POKE 63012,S:REM SLANT
9820 POKE 63013,F:REM FORGROUND SHADE
9825 POKE 63014,B:REM BACKGROUND SHADE
9830 POKE 63015,A:REM 0=DON'TPRINT ATTRIBUTES
9835 POKE 63016,I:REM INVERSE
9840 RANDOMIZE USR 63000
9845 RETURN
9850 PRINT #1; AT 0,8;"Press Space";
9855 IF INKEY$ <>"" THEN GO TO 9855
9860 IF INKEY$ <>" " THEN GO TO 9860
9865 INPUT "":RETURN
9870 CLEAR 62999:PRINT ''''" Loading CODE "''" Please wait..":LOAD "P. sizer C"CODE :RUN
9875 CLEAR :SAVE "P. sizer" LINE 9870:SAVE "P. sizer C"CODE 63000,1500
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.



