This program rotates a user-defined graphic (UDG) character 90 degrees and writes the transformed pixel data back into UDG memory. The user selects a UDG by letter (“a” through “u”), and the program reads its 8×8 pixel bitmap from RAM using PEEK, stores it in a two-dimensional array Z(8,8), then recomputes the rotated byte values and POKEs them back with POKE. A DATA block at lines 1000–1040 preloads UDG “a” with an F-shaped pattern (bytes 252,128,128,248,128,128,128,252) to serve as a demonstration. After rotation, the new glyph is displayed on-screen using block graphic characters, and the program loops back to allow repeated rotations.
Program Structure
The program divides into three functional sections:
- Setup and UDG preload (lines 1000–1040): A
FOR/READ/POKEloop loads eight bytes into UDG “a”, providing a ready-made test character. - Input and validation (lines 1–6): The user is prompted to enter a UDG letter. A boundary check on line 6 is intended to restrict input to “a”–”u”.
- Rotation engine and display (lines 10–155): The core algorithm reads pixel bits from UDG RAM, stores them in a 2D array, then writes the 90-degree-rotated result back and displays it.
Rotation Algorithm
The rotation proceeds in two passes. The first pass (lines 40–90) PEEKs each of the eight bytes of the selected UDG starting at USR A$, and decodes individual pixel bits by repeatedly subtracting powers of two (starting from 128, halving each iteration). Each bit is stored in array Z(Q,W) where Q is the column index (1–8) and W is the row index counting down from 8 to 1, effectively transposing the bit matrix.
The second pass (lines 100–140) iterates over rows of Z, accumulates each row back into a byte by multiplying set-bit positions by descending powers of two, and POKEs the result into UDG RAM. This achieves a 90-degree clockwise rotation of the character bitmap.
Key BASIC Idioms
LET A=USR A$on line 10 retrieves the RAM address of the UDG corresponding to the entered letter, using the built-inUSRfunction with a string argument.- The bit-extraction loop uses successive halving of
X(128, 64, 32, … 1) and a conditional subtraction to test each bit without bitwise operators, a common technique in Spectrum BASIC. POKE C,Aon line 140 writes the reconstructed rotated byte directly into UDG memory, immediately affecting how the character renders.- Line 130 prints a block graphic
█character for set pixels, giving a visual preview of the rotated glyph.
Bugs and Anomalies
| Location | Issue |
|---|---|
| Line 6 | The validation condition IF A$<"a" OR "a">"u" is incorrect. The second operand should be A$>"u"; as written, "a">"u" is always false, so only the lower bound is enforced. Any letter after “a” passes without an upper-bound check. |
| Line 155 | GO TO 10 jumps back into the rotation loop rather than to the input prompt (line 5), re-running the rotation on the same character infinitely without asking for new input. Line 160 is unreachable under normal flow. |
| Line 160 | IF "R"="N" is a literal string comparison that is always false; it should presumably read IF R$="N". |
| Lines 1000–1040 | This subroutine is never called from the main program; it must be run first manually or invoked via GO SUB from the command line to preload UDG “a”. |
Notable Techniques
Using DIM Z(8,8) as an intermediate pixel store avoids the need for any machine code; the entire rotation is accomplished in pure BASIC with arithmetic. The approach of saving the original UDG address in variable C at line 10 and advancing C in the write-back loop (line 140) mirrors the read-loop pointer A, keeping the two passes symmetric and avoiding address recalculation.
Source Code
1 INK 7: PAPER 0: BORDER 0
2 PRINT TAB 8;"ROTATE CHARACTER"'''
5 PRINT TAB 5;"GO TO GRAPHICS MODE !!!": PAUSE 180: CLS : INPUT "CHARACTER TO BE ROTATED ? "; LINE A$
6 IF A$<"a" OR "a">"u" THEN GO TO 5
10 LET A=USR A$: LET C=A
20 LET Q=1: LET W=8
40 DIM Z(8,8): FOR D=1 TO 8
50 LET X=128: LET B=PEEK A
60 FOR F=1 TO 8
70 IF (B-X)>=0 THEN LET B=B-X: LET Z(Q,W)=1
80 LET X=X/2: LET Q=Q+1
90 NEXT F: LET Q=1: LET W=W-1: LET A=A+1: NEXT D
100 FOR X=1 TO 8: LET A=0: LET B=128
110 FOR Y=1 TO 8
120 IF Z(X,Y)=0 THEN PRINT " ";: GO TO 140
130 LET A=A+B: PRINT "█";
140 LET B=B/2: NEXT Y: POKE C,A: LET C=C+1: PRINT : NEXT X
150 PRINT : PRINT "LOOK AT THE NEW GRAPHIC '";a$;"'!"''''
155 PAUSE 120: CLS : GO TO 10
160 INPUT "Y OR N ";R$: CLS : IF R$="Y" THEN GO TO 5: IF "R"="N" THEN STOP
170 STOP
1000 FOR n=USR "a" TO USR "a"+7
1010 READ user: POKE n,user
1030 NEXT n
1040 DATA 252,128,128,248,128,128,128,252
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
