--- title: "Tomorrow Lies In Ambush!" id: 54537 type: "computer_media" slug: "tomorrow" url: "http://localhost/computer_media/tomorrow/" markdown_url: "http://localhost/computer_media/tomorrow.md" published_at: "2024-06-02T16:37:43+00:00" modified_at: "2026-03-30T21:46:03+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A menu-driven word processor stores up to 600 lines of text with tape save/load, printer output, and a line-by-line editor — all in BASIC." category: - name: "Archived Media" slug: "archived-media" taxonomy: "category" url: "http://localhost/category/archived-media/" post_tag: - name: "Downloadable" slug: "downloadable" taxonomy: "post_tag" url: "http://localhost/tag/downloadable/" - name: "TS 2068" slug: "ts2068" taxonomy: "post_tag" url: "http://localhost/tag/ts2068/" model: - name: "Timex/Sinclair 2068" slug: "ts-2068" taxonomy: "model" url: "http://localhost/model/ts-2068/" indiv: - name: "Emmett Jenkins" slug: "emmett-jenkins" taxonomy: "indiv" url: "http://localhost/indiv/emmett-jenkins/" genre: - name: "Word Processor" slug: "word-processor" taxonomy: "genre" url: "http://localhost/type/word-processor/" media_contents: - id: 51213 title: "CATS Library Tape 3" type: "computer_media" url: "http://localhost/computer_media/cats-library-tape-3/" media_type: "Program" programmers: - name: "Emmett Jenkins" slug: "emmett-jenkins" taxonomy: "indiv" url: "http://localhost/indiv/emmett-jenkins/" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2024/06/Tomorrow-1.png" - url: "http://localhost/wp-content/uploads/2024/06/Tomorrow-2.png" - url: "http://localhost/wp-content/uploads/2024/06/Tomorrow-3.png" media_type_tags: "Word Processor" --- # Tomorrow Lies In Ambush! This program is a line-based word processor that stores up to 600 lines of 32-character text in a string array T$(600,32). It provides a menu-driven interface with eight options covering text entry, printer output via LPRINT, tape SAVE/LOAD of the array, on-screen display, editing, and appending. Color setup at startup uses a small subroutine dispatch table (lines 9000–9005) that increments a pointer variable G by 2 each iteration to step through BORDER, PAPER, and INK label strings. The edit routine uses POKE 23692,255 to suppress the “scroll?” prompt during line display, and the search routine (line 8000) scans for a sentinel “END” string padded to 32 characters to determine how many lines have been entered. *** ## Program Analysis ### Program Structure The program is divided into clearly delineated functional blocks separated by REM statements and large line-number gaps, a common BASIC organizational convention: 1. **Lines 1–7:** Title screen, color setup initialization 2. **Lines 8–80:** Color selection loop (BORDER, PAPER, INK) 3. **Lines 200–370:** Main menu dispatcher 4. **Lines 705–750:** On-screen display routine (Option 7) 5. **Lines 1000–1051:** Text input routine (Options 1 and 8) 6. **Lines 2000–2120:** Printer output routine (Option 2) 7. **Lines 3000–3040:** Tape save routine (Option 3) 8. **Lines 4000–4040:** Tape load routine (Option 4) 9. **Lines 5000–5240:** Edit routine (Option 5) 10. **Lines 6000–6010:** End/NEW routine (Option 6) 11. **Lines 8000–8040:** Search/count subroutine 12. **Lines 9000–9005:** Color-label dispatch table 13. **Lines 9100–9160:** Input instructions subroutine ### Data Storage All text is held in `T$(600,32)`, a two-dimensional string array declared at line 6 with 600 rows of exactly 32 characters each. The capacity advertised on the title screen (“578 LINES DEEP”) is slightly less than the 600 allocated, with the gap unexplained in the code. A sentinel row containing the word `END` padded to 32 characters is used to mark the logical end of entered text; the search subroutine at line 8000 scans for this sentinel and stores the found index in variable `X`, which is then used as the upper bound in print and edit loops. ### Color Selection Dispatch Table Lines 9000–9005 implement a rudimentary dispatch table for the color setup loop. Variable `G` is initialized to 9000 and incremented by 2 after each of the three color inputs (lines 40 and 20), so successive `GO SUB G` calls land on lines 9000, 9002, and 9004, each setting `A$` to `"BORDER"`, `"PAPER"`, or `"INK"` respectively before returning. This is an unconventional but functional use of a computed `GO SUB`. ### Key BASIC Idioms - **Key-release/key-press pair:** Lines 280–290 use the standard idiom of first waiting for `INKEY$` to be empty, then waiting for it to be non-empty, ensuring a clean single keypress detection before the dispatch chain at lines 300–370. - **Scroll suppression:** Line 5050 uses `POKE 23692,255` to reset the line count in system variable SCRCT, preventing the “scroll?” prompt from appearing while printing lines during the edit routine. - **Tape array save/load:** Lines 3030 and 4030 use `SAVE S$ DATA T$()` and `LOAD S$ DATA T$()` to persist and restore the entire text array directly by name. - **PAUSE 0 for keypress wait:** Used at lines 745 and 9150 to halt execution until any key is pressed. ### Notable Bugs and Anomalies | Location | Issue | | --- | --- | | Lines 300–366 | After the key-release/key-press idiom at lines 280–290, the dispatch chain at lines 300–366 re-reads `INKEY$` independently on each line. Because `INKEY$` is instantaneous and the key may no longer be held, many dispatches may be silently skipped, and execution can fall through to `GO TO 290` at line 370, requiring the user to press the key again. | | Line 366 | Option 8 (Add Text) performs a `CLS` before checking `INKEY$="8"`, which clears the screen unnecessarily on every pass through the dispatcher for any non-8 key that reaches that line. | | Lines 1005–1050 | Variable `C` is initialized to 1 unconditionally in the input routine, so Option 8 (“ADD TEXT”) which jumps to line 1010 bypasses line 1005 and preserves `C`, but the title screen note “TO ADD TO TEXT; PRESS ‘8’ TWICE!” is needed because the menu dispatch at line 366 itself only reaches that `GO TO 1010` after the user presses 8 a second time (due to the `INKEY$` re-read problem above). | | Lines 5070 and 5150 | Both lines use `NEXT F` inline within an `IF` statement. While syntactically valid in Spectrum BASIC, embedding loop control inside a conditional can cause confusing control flow, especially when combined with the `GO TO 5125` targets at lines 5170–5180, which reference line 5125 — a non-existent line number that falls through to line 5130. | | Line 9160 | Contains `RETURN : GO TO 1010`. The `GO TO 1010` is unreachable because `RETURN` transfers control back to the caller, making the trailing statement dead code. | | Line 1020 | The `END` sentinel comparison string includes trailing spaces padded to 32 characters (e.g., `"END "`), which is correct given the fixed-width string array, but the literal appears to contain 29 trailing spaces rather than 31, potentially causing a mismatch depending on how the editor stored them. | ### Subroutine at Line 8999 Line 8999 contains `GO TO 9998`, which references a non-existent line and sits between the search subroutine (ending at line 8040) and the color-label table (starting at 9000). This acts as a fall-through guard to prevent execution from accidentally entering the color-label subroutines, a known technique for protecting lookup tables from unintended execution. ## Source Code ``` 1 REM EMMETT JENKINS 04/15/84 2 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 3 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" 4 PAUSE 4000 5 LET X=0: LET B=0: LET G=9000: DIM A (3) 6 DIM T$(600,32) 7 CLS 8 FOR L=0 TO 32 9 BRIGHT 1 10 FOR F=1 TO 3 13 CLS 20 GO SUB G 30 PRINT AT 10,3;"INPUT:",A$;AT 12,7;"COLOR" 40 LET G=G+2 50 INPUT A(F) 55 CLS 60 NEXT F 70 BORDER A(1): PAPER A(2): INK A(3) 80 CLS 150 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 NEW 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 ```