This program prints large “banner” text on a 2040 printer by reading the pixel data stored in User Defined Graphic (UDG) character shapes. It accepts a message string, validates that every character is either a space or a UDG (letters “a” through “u”), then for each character it PEEKs the 8 bytes of bitmap data from the UDG address returned by USR. The 8×8 pixel grid is transposed — columns become rows — and each pixel is expanded to a 4-character-wide block (using Spectrum block graphic █), with each expanded row sent to the printer three times via LPRINT to also triple the height. Spaces in the input cause the current screen buffer to be printed with COPY before continuing.
Program Structure
The program divides into four logical phases:
- Introduction (lines 1–4): Displays a description and waits for any keypress before clearing the screen.
- Setup & validation (lines 150–190): Builds a powers-of-two lookup array
a()and inputs the message string, checking each character is either a space or a valid UDG. - Bitmap extraction & transposition (lines 200–410): For each character, PEEKs its 8-byte UDG definition, converts each byte to an 8-element binary string row in array
b$(), then transposes the grid into arraye$()so that columns become rows. - Output (lines 450–500): Expands each bit of the transposed grid to a 4-space or 4-█ run and sends three copies of each row to the printer with
LPRINT, producing a tall blocky glyph.
UDG Bitmap Decoding
Line 150 initialises a(1..8) with the values 128, 64, 32, 16, 8, 4, 2, 1 — the eight bit-weights of a byte, MSB first. For each character, line 260 uses PEEK (y+i) (where y = USR a$(p)) to read one row of the UDG bitmap. The inner loop at lines 270–290 performs a simple greedy binary decomposition: if the remaining value x is ≥ the current weight, that bit is set to "1" and the weight is subtracted. This reconstructs the 8-bit pattern as a character string row in b$(i+1).
Transposition Technique
After filling the 8×8 string array b$() (rows = scan lines, columns = bits), lines 340–410 transpose it into e$() so that bit-column k of the original becomes scan-line i of the output. This rotates the glyph 90°, which — combined with reading rows in reverse order at line 380 (FOR n=8 TO 1 STEP -1) — effectively mirrors and rotates the image. The net result is that the glyph is printed in a portrait orientation suitable for a banner where characters are rendered tall.
Banner Expansion
Line 470 uses the Spectrum BASIC string-multiplication idiom with AND:
(" " AND e$(i,n)="0")— four spaces for an unset pixel.("████" AND e$(i,n)="1")— four solid-block characters (█, chr 143) for a set pixel.
This expands each pixel to 4 characters wide. Line 480 then prints the resulting 32-character string three times on a single LPRINT line (c$'c$'c$, where ' is the comma separator in Spectrum BASIC’s LPRINT), tripling the printed height as well. The combined 4-wide × 3-tall expansion gives chunky, readable banner characters.
Input Validation
Line 180 contains a compound validity check using CODE a$(s). The intended logic is to reject anything that is not a UDG character (codes 144–164, corresponding to UDGs \a–\u). However, the Boolean operator precedence in Spectrum BASIC causes the condition to be evaluated differently from what a straightforward reading suggests. The four sub-conditions connected by OR and AND are:
| Sub-condition | Intended meaning |
|---|---|
CODE a$(s)<65 | Below “A” (not alpha at all) |
CODE a$(s)<97 AND CODE a$(s)>85 | Between “Z”+1 and “a”-1 (non-letter gap) |
CODE a$(s)>117 AND CODE a$(s)<144 | Between “v” and first UDG |
CODE a$(s)>164 | Above last UDG \u |
Due to AND binding more tightly than OR, the check does function broadly correctly for the ASCII printable range, though it accepts uppercase letters A–U (codes 65–85) as if they were valid, since those ranges are not blocked. In practice this only matters if the UDG table has not been populated for uppercase equivalents.
Space Handling
A space character in the input message triggers a different code path: line 210 issues CLS : COPY to print the current screen contents before jumping to NEXT p via GO TO 490. This uses the screen as a temporary buffer for COPY-based printing, rather than building the space character as a blank glyph.
Notable BASIC Idioms
USR a$(p)— returns the address of the UDG bitmap for charactera$(p), used directly as a PEEK base address.- String array slice assignment:
LET b$(i+1)="00000000"initialises an entire 8-character row of a 2D string array in one statement. - The
ANDconditional string trick on line 470 is a classic Spectrum idiom that returns the left-hand string if the condition is true (numeric 1), or an empty string if false (numeric 0). BEEP 1,-20on the error path produces a low-pitched warning tone;BEEP 1,20at line 500 signals successful completion.
Content
Source Code
1 PRINT "This is a ""banner"" program for the 2040 printer. It makes niceblocky letters. However, it will only work with the letters ""a"" thru ""u""."
2 PRINT : PRINT "Press any key to begin......"
3 IF INKEY$="" THEN GO TO 3
4 CLS
150 DIM a(8): LET a(1)=128: LET a(2)=64: LET a(3)=32: LET a(4)=16: LET a(5)=8: LET a(6)=4: LET a(7)=2: LET a(8)=1
160 INPUT "Enter message > ";a$
170 FOR s=1 TO LEN a$: IF a$(s)=" " THEN GO TO 190
180 IF CODE a$(s)<65 OR CODE a$(s)<97 AND CODE a$(s)>85 OR CODE a$(s)>117 AND CODE a$(s)<144 OR CODE a$(s)>164 THEN PRINT a$(s);" isn't a user graphic character": BEEP 1,-20: STOP
190 NEXT s
200 FOR p=1 TO LEN a$
210 IF a$(p)=" " THEN CLS : COPY : GO TO 490
220 LET y=USR a$(p)
230 DIM b$(8,8)
240 FOR i=0 TO 7
250 LET b$(i+1)="00000000"
260 LET x=PEEK (y+i)
270 FOR n=1 TO 8
280 IF x>=a(n) THEN LET b$(i+1,n)="1": LET x=x-a(n)
290 NEXT n
300 NEXT i
340 DIM e$(8,8)
350 LET k=1
360 FOR i=1 TO 8
370 LET f$=""
380 FOR n=8 TO 1 STEP -1
390 LET f$=f$+b$(n,k): NEXT n
400 LET e$(i)=f$
410 LET k=k+1: NEXT i
450 FOR i=1 TO 8
460 LET c$="": FOR n=1 TO 8
470 LET c$=c$+(" " AND e$(i,n)="0")+("████" AND e$(i,n)="1")
480 NEXT n: LPRINT c$'c$'c$: NEXT i
490 NEXT p
500 BEEP 1,20: STOP
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
