This program is a 32-column word processor capable of storing up to 600 lines of text in a string array, with options to enter, edit, print (to printer via LPRINT), save, load, and display text on screen. It loads a font (“BOLD.COD”) and patches the system variable at address 23607 to redirect printer output through the bold character generator; POKEing 23607 back to 60 restores normal printing. The program uses a subroutine dispatch pattern with a variable G (initialized to 9000) that increments by 2 each iteration to step through labeled LET/RETURN pairs at lines 9000–9004, providing a simple string-lookup mechanism for color attribute names. Text storage uses a DIM T$(600,32) array, and end-of-text is detected by searching for the sentinel string “END” (padded to 32 characters).
The word processor was authored by Emmett Jenkins in April 1984 and merged with the bold print routine from the LIST 3.5 library tape.
The name of the word processor comes from a collection of short stories with the same title.
Program Analysis
Program Structure
The program is organized into clearly separated functional blocks, each anchored at a round-line-number boundary. Control flows through a central menu at line 200 and dispatches to numbered routines:
| Line Range | Purpose |
|---|---|
| 10–40 | Startup: load machine code, patch printer vector, title pause |
| 101–107 | Title screen (“TOMORROW LIES IN AMBUSH!”) and array initialization |
| 108–199 | Color setup loop using the G-dispatch subroutine |
| 200–370 | Main menu with 8 options |
| 700–750 | Option 7: display stored text on screen |
| 1000–1051 | Option 1: text input routine |
| 2000–2120 | Option 2: printer output via LPRINT |
| 3000–3040 | Option 3: save text array to tape |
| 4000–4040 | Option 4: load text array from tape |
| 5000–5240 | Option 5: line-by-line editor |
| 6000–6010 | Option 6: STOP |
| 8000–8040 | Search routine — finds end-of-text sentinel, sets X |
| 9000–9005 | G-dispatch table for color attribute name strings |
| 9100–9160 | Input instructions subroutine |
| 9990–9998 | STOP and SAVE commands |
Machine Code Usage
Lines 20–30 handle the machine code component. CLEAR 56575 protects RAM from address 56576 upward, and LOAD "BOLD.COD" CODE 56576,768 places a 768-byte routine there. POKE 23607,220 writes to the system variable CHARS (the character set base pointer, stored as the high byte), redirecting the ROM’s character lookup to the custom bold font at 56576. Restoring the value to 60 (i.e., high byte pointing to the ROM font at 15360) reverts to normal characters. This is an elegant, non-destructive way to substitute an entire font for both screen and printer output without patching any ROM vectors directly.
Text Storage and Sentinel Detection
Text is stored in DIM T$(600,32), a fixed-width string array of 600 rows each 32 characters wide. Since the Spectrum pads fixed-length strings with spaces, the end-of-text sentinel comparison must match the full padded string: T$(N)="END " (31 trailing spaces). This same pattern appears in the input routine (line 1020), edit routine (line 5040), and search routine (line 8020). The search subroutine at line 8000 sets the global variable X to the index of the sentinel line, which is then used as the loop bound in print and edit loops.
G-Dispatch Subroutine Pattern
Lines 9000–9005 implement a rudimentary computed-GOSUB table. The variable G is initialized to 9000 at line 105 and incremented by 2 after each call (LET G=G+2 at line 140), so the three iterations of the color-setup loop call lines 9000, 9002, and 9004 in sequence, each setting A$ to "BORDER", "PAPER", and "INK" respectively. This drives the prompt at line 130: PRINT AT 10,3;"INPUT:",A$;AT 12,7;"COLOR", asking the user to enter a numeric value for each attribute in turn.
Key BASIC Idioms
- Keypress debounce pattern: Lines 280–290 use the standard idiom of waiting for INKEY$ to be empty then non-empty before reading a key, preventing held-key false triggers.
- POKE 23692,255: Used at line 5050 to reset the FRAMES-based scroll counter, suppressing the “scroll?” prompt during the edit display loop.
- PAUSE 0 at line 9150: Halts until any key is pressed, used after instructions screen.
- Line 366 layout:
CLS : IF INKEY$="8" THEN GO TO 1010— the CLS before the INKEY$ test means a brief flash of a cleared screen occurs even for other keypresses, a minor cosmetic side effect of the structure.
Bugs and Anomalies
- Lines 5125 and 700 unreachable/missing: Lines 5170 and 5180 branch to line 5125, which does not exist in the listing; this will cause a “Line does not exist” error if the user presses 3 or 4 in the edit menu. Line 705 exists but line 700 is the target of line 365 — the actual code begins at 705, so branching to 700 simply falls through to 705, which works correctly.
- Line 5070 logic:
IF LEN INKEY$=0 THEN NEXT F: PRINT LEN INKEY$: GO TO 205— theNEXT Fis executed inside the IF branch, then falls through toPRINT LEN INKEY$(which will always print 0 here) and jumps to the menu. The intent appears to be to advance to the next line silently, but the extra PRINT and GO TO 205 make this a premature exit from the edit loop rather than a quiet continuation. - Line 1020 sentinel match: The string
"END "has 31 trailing spaces but the array width is 32, so the padded stored string would be 32 characters. The comparison string is one character short and will never match, meaning the user cannot exit text input by typing “END”. The same issue affects line 5040. The search routine at line 8020 shares the same mismatch. - Line 9160:
RETURN : GO TO 1010— theGO TO 1010after RETURN is unreachable dead code. - Line 8999:
GO TO 9998redirects to the SAVE command line, which would execute a tape save if ever reached from normal flow — this appears to be a utility line for the author’s own use rather than program logic.
Save / Persistence
Line 9997 saves the BASIC program itself as "BOLDTOMORO" with LINE 1 for auto-run. Line 9998 saves the machine code block from address 56576 for 768 bytes as "BOLD.COD". Text data is saved and loaded via SAVE/LOAD S$ DATA T$() at lines 3030 and 4030, using the array save/load facility to persist the full 600×32 text buffer to tape.
Content
Source Code
10 REM bold print
20 CLEAR 56575
30 LOAD "BOLD.COD"CODE 56576,768: POKE 23607,220
35 PRINT "Bold print now loaded"
37 PRINT "Please use this program for all listings you send to LIST"
38 PRINT "To return to regular printing, just POKE 23607,60"
39 PRINT "To get these heavy characters, Poke 23607,220"
40 PAUSE 390: CLS
101 REM "tomorrow" by EMMETT JENKINS 04/15/84 merged with "bold" from LIST 3.5 library tape--renamed "BOLDTOMORO"
102 PRINT AT 1,5; FLASH 1;"TOMORROW LIES IN AMBUSH!"; FLASH 0;AT 4,5;"WORD PROCESSOR",AT 6,5;"CREATED FOR:",AT 8,5; FLASH 1;"L.I.S.T!": FLASH 0
103 FLASH 1: PRINT AT 12,5;"BY EMMETT JENKINS": FLASH 0: PRINT AT 15,5;"PRESS ANY KEY TO START!",AT 18,5;"32 CHARACTERS",AT 20,5;"578 LINES DEEP"
104 PAUSE 4000
105 LET X=0: LET B=0: LET G=9000: DIM A (3)
106 DIM T$(600,32)
107 CLS
108 FOR L=0 TO 32
109 BRIGHT 1
110 FOR F=1 TO 3
113 CLS
120 GO SUB G
130 PRINT AT 10,3;"INPUT:",A$;AT 12,7;"COLOR"
140 LET G=G+2
150 INPUT A(F)
155 CLS
160 NEXT F
170 BORDER A(1): PAPER A(2): INK A(3)
180 CLS
199 CLS
200 REM OPTIONS
205 CLS : PRINT AT 1,5; FLASH 1;"PRESS NUMBER OF OPTION": FLASH 0
210 PRINT AT 5,0;"OPTION 1";TAB 10;"ENTER TEXT"
215 PRINT
220 PRINT "OPTION 2";TAB 10;"PRINTOUT TEXT"
225 PRINT
230 PRINT "OPTION 3";TAB 10;"SAVE TEXT"
235 PRINT
240 PRINT "OPTION 4";TAB 10;"LOAD TEXT"
245 PRINT
250 PRINT "OPTION 5";TAB 10;"EDIT TEXT"
255 PRINT
270 PRINT "OPTION 6";TAB 10;"END"
275 PRINT AT 17,0;"OPTION 7";TAB 10;"PRINT TEXT ON SCREEN"
276 PRINT AT 19,0;"OPTION 8";TAB 10;"ADD TEXT"
277 PRINT AT 21,0; FLASH 1;"TO ADD TO TEXT; PRESS '8' TWICE!"
280 IF INKEY$<>"" THEN GO TO 280
290 IF INKEY$="" THEN GO TO 290
300 IF INKEY$="1" THEN GO TO 1000
310 IF INKEY$="2" THEN GO TO 2000
330 IF INKEY$="3" THEN GO TO 3000
340 IF INKEY$="4" THEN GO TO 4000
350 IF INKEY$="5" THEN GO TO 5000
360 IF INKEY$="6" THEN GO TO 6000
365 IF INKEY$="7" THEN GO TO 700
366 CLS : IF INKEY$="8" THEN GO TO 1010
370 GO TO 290
705 CLS
710 GO SUB 8000
720 FOR F=1 TO X
730 PRINT T$(F)
740 NEXT F
745 PRINT AT 21,3; FLASH 1;"PRESS ANY KEY TO CONTINUE"; FLASH 0: PAUSE 0
750 GO TO 200
1000 REM INPUT ROUTINE
1001 CLS
1002 GO SUB 9100
1005 LET C=1
1008 IF T$(C)=CHR$ 32 THEN BEEP .03,6
1009 IF C=578 THEN PRINT AT 10,0; FLASH 1;"THAT WAS YOUR LAST LINE"; FLASH 0; FLASH 1;AT 13,0;"PRESS ANY KEY TO CONTINUE"; FLASH 0: PAUSE 500: GO TO 1051
1010 INPUT T$(C):
1020 IF T$(C)="END " OR T$(C)="end " THEN GO TO 205:
1030 PRINT T$(C):
1040 LET C=C+1
1050 GO TO 1009
1051 PRINT AT 15,3; FLASH 1;"NOW TYPE END"; FLASH 0: GO TO 1010
2000 REM OUTPUT ROUTINE
2050 GO SUB 8000
2100 FOR F=1 TO X
2110 LPRINT T$(F)
2115 NEXT F
2120 GO TO 200
3000 REM SAVE ROUTINE
3010 CLS : PRINT AT 10,0; FLASH 1;"INPUT NAME OF TEXT"; FLASH 0
3020 INPUT S$
3030 SAVE S$ DATA T$()
3040 GO TO 200
4000 REM LOAD TEXT ROUTINE
4010 CLS : PRINT AT 10,0; FLASH 1;"INPUT NAME OF TEXT"; FLASH 0
4020 INPUT S$
4025 PRINT FLASH 1;"START TAPE"; FLASH 0
4030 LOAD S$ DATA T$()
4035 PRINT AT 16,10; FLASH 1;"STOP TAPE"; FLASH 0: PAUSE 500
4040 GO TO 200
5000 REM EDIT ROUTINE
5001 CLS
5010 GO SUB 8000
5020 PRINT FLASH 1;"TO EDIT LAST LINE PRESS '0'"; FLASH 0
5025 PRINT
5030 FOR F=1 TO X
5040 IF T$(F)="END " OR T$(F)="end " THEN GO TO 205
5050 PRINT T$(F): POKE 23692,255
5060 PAUSE 300
5070 IF LEN INKEY$=0 THEN NEXT F: PRINT LEN INKEY$: GO TO 205
5080 CLS : PRINT FLASH 1;"PRESS APPROPRIATE KEY"; FLASH 0
5090 PRINT : PRINT "1 TO CONTINUE"
5100 PRINT : PRINT "2 TO EDIT THIS LINE"
5110 PRINT : PRINT "3 UP ONE LINE"
5120 PRINT : PRINT "4 DOWN ONE LINE"
5130 IF INKEY$<>"" THEN GO TO 5130
5140 IF INKEY$="" THEN GO TO 5140
5150 IF INKEY$="1" THEN CLS : NEXT F
5160 IF INKEY$="2" THEN GO TO 5200
5170 IF INKEY$="3" THEN LET F=F-1: GO TO 5125
5180 IF INKEY$="4" THEN LET F=F+1: GO TO 5125
5190 GO TO 5130
5200 CLS : PRINT AT 5,0; FLASH 1;"RE-WRITE THIS LINE CORRECTLY!"; FLASH 0
5210 PRINT AT 16,0;T$(F)
5220 INPUT T$(F)
5225 CLS : PRINT FLASH 1;"TO EDIT LAST LINE PRESS '0'"; FLASH 0: PRINT : PRINT T$(F)
5230 NEXT F
5240 GO TO 200
6000 REM END ROUTINE
6010 STOP
8000 REM SEARCH ROUTINE
8010 FOR N=1 TO 600
8020 IF T$(N)="END " OR T$(N)="end " THEN LET X=N: RETURN
8030 NEXT N
8040 RETURN
8999 GO TO 9998
9000 LET A$="BORDER"
9001 RETURN
9002 LET A$="PAPER"
9003 RETURN
9004 LET A$="INK"
9005 RETURN
9100 PRINT AT 0,5;"THIS WORD PROCESSOR",AT 2,3;"WORKS JUST LIKE A TYPEWRITER",AT 4,5;"AT THE END OF EACH LINE",AT 6,5;"YOU PRESS THE ENTER KEY",AT 8,0;"YOU MAY ONLY ENTER 32 CHARACTERS",AT 12,2; INVERSE 1;"TO END TEXT INPUT,TYPE 'END'"; INVERSE 0
9110 PRINT : PRINT : PRINT : PRINT
9130 PRINT AT 17,3; FLASH 1;"PRESS ANY KEY TO CONTINUE!": FLASH 0
9140 PRINT
9150 PAUSE 0
9155 CLS
9160 RETURN : GO TO 1010
9990 STOP
9997 SAVE "BOLDTOMORO" LINE 1
9998 SAVE "BOLD.COD"CODE 56576,768
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

