This program renders text in a three-dimensional block-letter style on screen, using pixel-level POINT detection and sequences of PLOT/DRAW commands to construct each character’s 3D face, top, and side. It loads a 1,300-byte machine code routine from tape into address 64000, which handles screen printing (COPY) via a specific printer interface (AERCO with Star SG-10). The BASIC loop scans each character’s pixel map at line 150 using POINT, then at lines 160–180 draws a three-face 3D box for every set pixel using relative DRAW commands, including diagonal strokes (DRAW 5,5 and DRAW -5,-5) to form the depth effect. The program includes an introductory sequence that renders “3D”, “-“, and “LETTERS” as a demo before prompting the user to enter up to seven characters of their own. POKEs to addresses 23609 and 23658 adjust system parameters for border color timing and caps lock behavior.
Program Analysis
Program Structure
The program is organized into three distinct phases: an introduction/demo sequence, a user input loop, and a shared rendering subroutine. Control flow is summarized below:
- Initialization (line 10): Loads machine code from tape, sets system POKEs, configures display, then jumps to line 310.
- Introduction (lines 310–350): Displays a title screen explaining printer interface requirements, then jumps to line 20.
- Demo sequence (lines 20–50): Calls the rendering subroutine (line 130) three times with preset strings
" 3D"," -", and"LETTERS"at staggered vertical offsets, then displays instructional text. - User input loop (lines 100–300): Prompts for vertical offset
pand a stringa$(1–7 characters), renders it, optionally prints a hard copy, and loops. - Rendering subroutine (lines 130–200): Shared by both the demo and the user input loop; returns via
RETURNonly when called from the demo (lines 210–230 check for the demo strings), otherwise continues to the copy/loop prompts. - Save/Verify (lines 360–370): Saves the BASIC program and machine code block to tape; these lines are not reached during normal execution.
The Rendering Subroutine (Lines 130–200)
The core technique uses the built-in POINT function to read individual pixels from the character set as printed in the lower portion of the screen. At line 130, a$ is printed invisibly at row 21 using PRINT AT 21,0;a$. The double loop at line 140 iterates over each pixel column (f, 0 to 8*a-1) and each pixel row (n, 0 to 7), sampling the character bitmap one pixel at a time.
When POINT (f,n) returns non-zero (a set pixel), three groups of DRAW commands construct the 3D appearance:
- Line 160: Draws the front face of the pixel block — a filled square outline — and removes internal lines, using
PI(≈3.14159, truncated to 3) as a shorthand integer constant inDRAW 0,-PI,DRAW PI,0, etc. - Line 170: Draws the top face using diagonal strokes (
DRAW 5,5andDRAW -5,-5) to simulate depth, plus vertical lines connecting front-face top edge to top-face top edge. - Line 180: Draws the right-side face using a diagonal start, a horizontal line, and a return diagonal.
Each pixel block is scaled 4× (f*4, n*4), and the vertical position is controlled by the parameter p (pixels from top, default 32 for the demo calls).
Use of PI as an Integer Constant
Several DRAW arguments use PI rather than the literal integer 3. Since DRAW truncates its arguments to integers, PI (3.14159…) evaluates to 3. This is a well-known Spectrum BASIC space-saving idiom: PI is a single token, whereas 3 is stored as a token plus a 5-byte floating-point number inline. This saves bytes in each occurrence where the value 3 is needed.
Machine Code Usage
A 1,300-byte machine code block is loaded from a separate tape file ("3dcharsetC") into address 64000. The entry point used at line 250 is RANDOMIZE USR 64009 (offset +9 into the block), which triggers a screen dump to the printer. The program’s own comments (lines 310–340) instruct users to replace this with COPY or their own printer interface command if not using the AERCO/Star SG-10 combination for which it was originally configured.
System POKEs
| Address | System Variable | Value | Effect |
|---|---|---|---|
| 23609 | BORDCR | 50 | Sets border/lower-screen color attributes |
| 23658 | FLAGS2 | 8 | Sets caps lock on |
Control Flow Anomalies
The subroutine starting at line 130 is used both as a proper GO SUB target (lines 20–40) and as a fall-through target from GO TO 120 (line 120 → 130). The RETURN statements at lines 210–230 only execute when the string matches one of the three demo strings; for user-entered strings, execution falls through to the input/copy prompts at lines 240–300. This dual-use pattern means the “subroutine” is not a clean subroutine for user input — it acts as a subroutine only during the demo phase.
Line 90 uses PAUSE NOT PI: NOT PI evaluates to 0 (since PI is non-zero, NOT returns 0), so PAUSE 0 waits indefinitely for a keypress — a standard idiom for halting until input.
Input Validation
At line 120, the entered string is validated: if its length exceeds 7 or is less than 1, a low beep (BEEP 1,-30) is sounded and input is requested again. The 7-character limit corresponds to the maximum width that can be rendered across the 256-pixel-wide screen at 4× scaling with 3D depth offsets without overflow.
Notable Techniques
- Using
PRINT AT 21,0;a$to render the system character set into screen memory, then reading it back pixel-by-pixel withPOINT— an elegant way to access font bitmaps without storing them separately. VAL "280"andVAL "20"inPAUSEandGO TOat line 350 as a token-saving technique (the string"280"is shorter in tokenized form than the inline floating-point representation of 280).- Diagonal DRAW commands (
DRAW 5,5) used to create isometric-style depth faces on each pixel block.
Source Code
10 CLS : PRINT AT 10,2;"LOADING - 3D-LETTERS - CODE": LOAD "3dcharsetC"CODE 64000,1300: POKE 23609,50: POKE 23658,8: BORDER 2: INK 0: PAPER 6: CLS : GO TO 310
20 LET a$=" 3D": LET p=0: GO SUB 130
30 LET a$=" -": LET p=30: GO SUB 130
40 LET a$="LETTERS": LET p=60: GO SUB 130
50 PRINT PAPER 1; INK 7;AT 13,0;" NOW YOU CAN WRITE YOUR OWN 3D - LETTERS",
60 PRINT '' PAPER 0; INK 7;" FOLLOW THE INSTRUCTIONS",
70 PRINT PAPER 4; INK 7;AT 19,17;"ALGIS E. GEDRIS"
80 PRINT INK 7; PAPER 2;AT 21,9;"PRESS ANY KEY"
90 PAUSE NOT PI
100 PAPER 6: BORDER 2: INK NOT PI: CLS
110 INPUT "PIXELS FROM TOP I=32 PIXELS:";p
120 INPUT "LETTERS (7 MAX) ";a$: IF LEN a$>7 OR LEN a$<1 THEN BEEP 1,-30: GO TO 120
130 LET a=LEN a$: PRINT AT 21,0;a$
140 FOR f=0 TO 8*a-1: FOR n=0 TO 7
150 IF POINT (f,n)=0 THEN GO TO 190
160 PLOT f*4,n*4+135-p: DRAW 4,0: DRAW 0,4: DRAW -4,0: DRAW 0,-PI: DRAW PI,0: DRAW 0,2: DRAW -2,0: DRAW 0,-1: DRAW 2,0: DRAW -2,-2
170 DRAW 5,5: DRAW 0,4: DRAW 0,-4: DRAW 4,0: DRAW 0,4: DRAW 0,-4: DRAW -5,-5
180 DRAW 0,4: DRAW 5,5: DRAW -4,0: DRAW -5,-5
190 NEXT n: NEXT f
200 PRINT AT 21,0;" "
210 IF a$=" 3D" THEN RETURN
220 IF a$=" -" THEN RETURN
230 IF a$="LETTERS" THEN RETURN
240 INPUT "COPY OF THE SCREEN (Y/N) :";Z$
250 IF Z$="Y" OR Z$="y" THEN RANDOMIZE USR 64009
260 INPUT "WRITE SOME MORE ? (Y/N) ";w$
270 IF w$="n" OR w$="N" THEN STOP
280 INPUT "CLEAR THE SCREEN ? (Y/N) ";c$
290 IF c$="y" OR c$="Y" THEN CLS
300 GO TO 100
310 PRINT AT 4,PI;"THIS ""3D-LETTERS"" PROGRAM"'TAB 5;"IS SPECIALLY MADE FOR"'TAB 8;"AERCO INTERFACE"'TAB 14;" AND "'TAB 7;"STAR SG-10 PRINTER"
320 PRINT '" REMOVE SECOND PART OF LINE 9998 SAVE ""3D-LETTERS"" CODE 64000,1300 AND REPLACE WITH YOUR PRINTER INTERFACE"
330 PRINT '" REPLACE ** RANDOMIZE USR 64009 WITH "" COPY "" OR EQUIVALENT"
340 PRINT AT 17,15;"IN ";AT 18,12;" LINE 250"
350 PAUSE VAL "280": CLS : GO TO VAL "20"
360 SAVE "3Dcharset" LINE 10: SAVE "3dcharsetC"CODE 64000,1300
370 PRINT #1,AT 0,8;"REWIND THE TAPE ****AND PLAY***": VERIFY "": VERIFY "3D-LETTERS"CODE 64000,1300
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.