Vertical Write is a BASIC program that renders text as large, vertically-scrolling graphics drawn with PLOT and DRAW commands on a black background. The program first displays a built-in demo string (“ENTER A STRING NO SPECIAL CHARACTERS OR NUMBERS”) read from DATA at line 9500, then loops to accept user input via INPUT and render each letter in the same style. Each uppercase letter A–Z is encoded as a series of line-drawing commands stored in DATA lines 9000–9250, with each letter’s DATA block located by computing an offset from the character’s ASCII code: L=(CODE A$(N)-65)*10+9000, then RESTOREing to that line. The numeric constants 8 and 48 are pre-computed into variables L8 and LS, and NOT PI evaluates to 0 to avoid storing explicit zeros in the DATA statements. Colors are randomized per letter, and horizontal column position is randomized per space character, creating a kinetic display effect.
Program Structure
The program divides into three phases:
- Initialization (lines 1–20): Sets up constants, dimensions the array, configures display attributes, and RESTOREs to the demo message DATA at line 9500.
- Demo loop (lines 25–200): Reads ASCII codes from DATA into array
A()and renders the built-in prompt string vertically. - Interactive loop (lines 300–430): Accepts user INPUT, then renders each character of the entered string using the same PLOT/DRAW engine, repeating indefinitely via
GO TO 300.
Note that line 300 does not exist in the listing — control jumps there from line 430 via GO TO 300, which is a well-known technique that causes execution to resume at the next line after 300, which is line 310.
Letter Shape Encoding
Each uppercase letter A–Z has its own DATA block at lines 9000–9250 (spaced 10 lines apart). The block begins with a count CT of line segments, followed by CT groups of four values: A, B, E, F representing a PLOT offset (C+A, R+B) and a DRAW delta (E, F). The correct DATA block for a character is located by computing:
L = (CODE A$(N) - 65) * 10 + 9000
then executing RESTORE L to seek directly to that line’s DATA. This avoids any lookup table and makes adding or modifying letters straightforward.
Notable Techniques
NOT PIas zero: SincePIis non-zero,NOT PIevaluates to 0. This is used extensively throughout the DATA lines to encode zero offsets without the character overhead of the digit0— a byte-saving idiom for DATA-heavy programs.- Pre-computed constants
L8andLS:L8is set to 8 (viaVAL "8") andLSto 48, both stored as variables so that their use in DATA statements is evaluated at READ time, reducing the number of integer literals in DATA and saving memory. - Vertical scroll via PRINT with quote-images: Lines 105 and 405 use a chain of apostrophes in a PRINT statement (
PRINT '''''''') to advance the display scroll by multiple lines, pushing previously plotted graphics upward to simulate vertical movement. POKE 23692,0: This resets the scroll counter (SCRCT in the system variables) to prevent the “scroll?” prompt from interrupting the display during the PRINT-driven scrolling.- Randomized color and column:
INKis randomized to a value 1–7 (avoiding black) for each letter. On encountering a space character, both the ink color and horizontal column positionCare re-randomized, creating visual variety between words. - Array pre-loading for demo: The demo message is read from DATA into
A(100)before display, allowing RESTORE to be reused for letter shape lookups during the render loop without losing the message data.
PLOT/DRAW Attribute Usage
The PLOT and DRAW commands specify both INK and PAPER attributes inline. Notably, PLOT uses INK INK; PAPER INK; — setting both ink and paper to the same color — while DRAW alternates the ink/paper ordering between the demo loop (line 100) and the interactive loop (line 360), though the effect is the same since both colors are identical. This makes each character’s cell block appear as a solid color rather than a two-tone line on a contrasting background.
Input Limitations
The program only handles uppercase letters A–Z. The demo message warns “NO SPECIAL CHARACTERS OR NUMBERS.” Any character outside the A–Z range will cause the offset calculation at line 355 to produce an incorrect RESTORE target, potentially RESTOREing to an unintended DATA line or causing an error. No input validation or error handling is implemented.
Potential Anomalies
- Line 200 uses
INK 9before CLS — ink value 9 is a transparent/contrast attribute. This is used to reset the ink setting to a neutral state before clearing the screen and entering the interactive phase. - The interactive loop starts at
GO TO 300but line 300 is absent; execution falls through to line 310 as intended. - The variable
Ris initialized to 0 at line 8 and never changed, so all letters are plotted with a fixed vertical base offset of 0 — vertical movement is achieved entirely through PRINT-driven scrolling, not by incrementingR.
Source Code
1 REM "VERT-RITE"
5 RANDOMIZE :LET LS=48:LET L8= VAL "8":POKE 23658,L8
7 DIM A(100):PAPER 0:BORDER 0:BRIGHT 0:CLS
8 LET C=8* INT (RND*25):LET R=0
10 LET INK= INT (RND*7)+1:PRINT AT 21,0
20 RESTORE 9500:FOR J=1 TO LS:READ A(J):NEXT J
25 FOR N=1 TO LS
30 POKE 23692,0
35 IF A(N)=32 THEN LET INK= INT (RND*7)+1:LET C=8* INT (RND*25):GO TO 105
40 LET L=(A(N)-65)*10+9000
100 RESTORE L:READ CT:FOR D=1 TO CT:READ A,B,E,F:PLOT INK INK; PAPER INK;C+A,R+B:DRAW PAPER ink; INK INK;E,F:NEXT D
105 PRINT ''''''''
200 NEXT N:PRINT ''''''''''''''':INK 9:CLS
310 INPUT A$:LET C=8* INT (RND*25):PRINT AT 21,0
320 LET INK= INT (RND*7)+1
330 FOR N=1 TO LEN A$
340 POKE 23692,0
350 IF CODE A$(N)=32 THEN LET INK= INT (RND*7)+1:LET C=8* INT (RND*25):GO TO 405
355 LET L=(CODE A$(N)-65)*10+9000
360 RESTORE L:READ CT:FOR D=1 TO CT:READ A,B,E,F:PLOT INK INK; PAPER INK;C+A,R+B:DRAW INK INK; PAPER INK;E,F:NEXT D
405 PRINT ''''''''
410 NEXT N
420 PRINT '''''''''''''''
430 CLS :GO TO 300
9000 DATA 4,L8,L8, NOT PI,32,52,L8, NOT PI,32,L8,24,32, NOT PI,16,LS,24,0
9010 DATA 6,L8,L8, NOT PI,40,L8,L8,32, NOT PI,L8,LS,32, NOT PI,L8,32,32, NOT PI,LS,40, NOT PI, NOT PI,LS,16, NOT PI,8
9020 DATA 5,L8,16, NOT PI,24,16,LS,24, NOT PI,LS,40, NOT PI, NOT PI,16,L8,24, NOT PI,LS,16, NOT PI,0
9030 DATA 5,L8,L8, NOT PI,40,L8,L8,24, NOT PI,L8,LS,16, NOT PI,47,23,L8,L8,39,LS,16,-16
9040 DATA 4,L8,L8, NOT PI,40,L8,L8,40, NOT PI,L8,LS,40, NOT PI,L8,32,32,0
9050 DATA 3,L8,L8, NOT PI,40,L8,LS,40, NOT PI,L8,32,32,0
9060 DATA 6,L8,16, NOT PI,24,16,LS,24, NOT PI,LS,40, NOT PI, NOT PI,16,L8,24, NOT PI,LS,16, NOT PI, NOT PI,LS,24,-16,0
9070 DATA 3,L8,L8, NOT PI,40,52,L8, NOT PI,40,L8,32,32,0
9080 DATA 3,16,L8,32, NOT PI,32,L8, NOT PI,40,16,LS,32,0
9090 DATA 3,16,L8,24, NOT PI,L8,16, NOT PI,L8,LS,16, NOT PI,32
9100 DATA 4,L8,L8, NOT PI,40,16,32,L8, NOT PI,40,LS,-8,-8,LS,15,-16,16
9110 DATA 2,L8,L8, NOT PI,40,L8,L8,40,0
9120 DATA 4,L8,L8, NOT PI,40,LS,L8, NOT PI,40,15,LS,16,-16,LS,LS,-16,-16
9130 DATA 3,L8,L8, NOT PI,40,LS,L8, NOT PI,40,47,16,-32,32
9140 DATA 4,16,L8,24, NOT PI,L8,19, NOT PI,24,LS,16, NOT PI,24,16,LS,24,0
9150 DATA 4,L8,L8, NOT PI,40,L8,LS,32, NOT PI,LS,40, NOT PI,-8,40,24,-32,0
9160 DATA 6,16,L8,24, NOT PI,L8,19, NOT PI,24,LS,16, NOT PI,24,16,LS,24, NOT PI,32,16, NOT PI, NOT PI,24,24, NOT PI,0
9170 DATA 6,L8,L8, NOT PI,40,L8,LS,32, NOT PI,LS,40, NOT PI,-8,40,24,-32, NOT PI,40,16, NOT PI, NOT PI,LS,L8, NOT PI,0
9180 DATA 6,L8,16, NOT PI, NOT PI,16,L8,24, NOT PI,L8,40, NOT PI, NOT PI,LS,16, NOT PI,L8,16,32,24, NOT PI,16,LS,24,0
9190 DATA 2,24,L8, NOT PI,32, NOT PI,LS,LS,0
9200 DATA 3,16,L8,24, NOT PI,L8,16, NOT PI,32,LS,16, NOT PI,32
9210 DATA 5,L8,24, NOT PI,24,16,16, NOT PI, NOT PI,24,L8,L8, NOT PI,40,16, NOT PI, NOT PI,LS,24, NOT PI,24
9220 DATA 4,L8,16, NOT PI,32,LS,16, NOT PI,32,16,L8,L8,L8,40,15,-8,8
9230 DATA 2,L8,L8,40,40,15,LS,40,-40
9240 DATA 3,24,L8, NOT PI,16,16,39,-16,16,39,39,16,16
9250 DATA 3,L8,L8,40, NOT PI,L8,L8,40,40,L8,LS,40,0
9500 DATA 69,78,84,69,82,32,65,32,83,84,82,73,78,71,32,32,78,79,32
9550 DATA 83,80,69,67,73,65,76,32,67,72,65,82,65,67,84,69,82,83
9600 DATA 32,79,82,32,78,85,77,66,69,82,83
9998 SAVE "VERT-RITE" LINE 1:GO TO 1:REM PRINT INK 2;FLASH 1;AT 20,7;" REWIND THE TAPE ";AT 21,7;"*** TO VERIFY ***":BEEP 1,20:VERIFY "":GO TO 1
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
