--- title: "Text1" id: 70954 type: "computer_media" slug: "text1" url: "http://localhost/computer_media/text1/" markdown_url: "http://localhost/computer_media/text1.md" published_at: "2026-08-24T23:18:34+00:00" modified_at: "2026-08-24T23:21:34+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/08/text-1.png" alt: "TEST screen" excerpt: "A full word processor with tape load/save, screen editing, search-and-replace, and machine code block-move routines crammed into a single BASIC program." 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/" genre: - name: "Word Processor" slug: "word-processor" taxonomy: "genre" url: "http://localhost/type/word-processor/" media_type: "Program" download_url: "https://archive.org/download/timex-sinclair-software-archive/Text1%20%28198x%29%28-%29%28TS2068%29%28US%29%28Program%29.zip" mediadate: "198x" images: - url: "http://localhost/wp-content/uploads/2026/08/text-1.png" alt: "TEST screen" media_type_tags: "Word Processor" --- # Text1 Text1 is a full-featured word processor program that supports text entry, tape-based load and save, screen editing, printing, and search-and-replace operations. It stores text in a raw memory buffer starting at address 38000, using POKE and PEEK extensively to manipulate bytes directly, and employs machine code routines loaded from tape (via `LOAD “text1 C” CODE`) for block-move and search operations triggered through `RANDOMIZE USR`. Special characters encoded as bytes 128–144 are used to represent formatting markers such as line breaks, paragraph breaks, and page breaks. The program detects a printer by polling port 251 via `IN` and adjusts its output mode accordingly, and it uses a cursor-navigation subroutine driven by keys 5–8 for screen editing in the scan/edit mode. *** ### Program Structure Text1 is organized as a menu-driven word processor with subroutines at low line numbers and major functional sections branched to via `GO TO VAL b$*1000` from line 930. The six operational modes map to line ranges as follows: | Menu Choice | Line Range | Function | | --- | --- | --- | | 1 | 1000–1500 | Enter text | | 2 | 2000–2050 | LOAD text from tape | | 3 | 3000–3420 | PRINT text | | 4 | 4000–4800 | Scan/edit text | | 5 | 5000–5030 | SAVE text on tape | | 6 | 6010–6030 | Set parameters | | 7 | 7000 | STOP work | Initialization runs through lines 5800–6030 on first load: a UDG is defined at line 5800 (a small bracket character for UDG-A), the machine code overlay is loaded from tape at line 5810, and workspace variables are set at line 6010. The main menu loop sits at lines 900–930. ### Memory Layout The program uses a fixed memory map for its text buffer and scratch areas: - `te = 38000` — base address of the text buffer - `li = 37000` — line input scratch buffer (used by the `GO SUB 60` keyboard entry routine) - `37998–37999` — two-byte little-endian word storing the current text length `c1` (written before SAVE, read after LOAD) - `37001–37002` — stores a byte count used during the Move operation (line 4800) - `c2 = 15000` — maximum number of characters the buffer can hold - `q = 23670`, `r = 23671` — system variables SEED (low and high bytes), tapped after each `RANDOMIZE` to extract a 16-bit value for machine code parameter passing ### Machine Code Interface All block-memory operations and search functions are handled by a machine code binary loaded separately from tape as `"text1 C" CODE`. Parameters are passed to the routines by a consistent idiom: `RANDOMIZE` is called with the desired value, then `PEEK q` and `PEEK r` (the SEED system variable, low and high bytes) are POKEd into argument slots within the machine code block, and finally `RANDOMIZE USR address` calls the routine. Two main entry points are used: - `USR 60000` (subroutine at line 30) — forward block move; takes three parameters: count `v1`, destination `v2`, source `v3` - `USR 60014` (subroutine at line 35) — reverse block move (for inserting/overlapping regions) - `USR 60028` (subroutine at line 81) — string search; takes start address `li`, text base `te+c2`, and end position `c3`; returns result flag in `PEEK 60143` and found position via `PEEK 60135/60136` - `USR 60151` (subroutine at line 100) — adjusts scroll/display parameters for edge-of-buffer conditions Subroutine 85 (lines 85–87) clamps the cursor position `c` to the valid range `[1, c1]` before any machine code call that uses `c` as an offset. ### Key BASIC Idioms The program makes heavy use of arithmetic on boolean-like expressions to avoid explicit numeric literals, following a common Sinclair BASIC space-saving convention: - `SGN PI` evaluates to `1` (since PI > 0) - `NOT PI` evaluates to `0` - `PI + PI` evaluates to approximately `6.28`, which truncates to `6` when used in `PRINT AT` - `VAL "number"` in `GO TO`, `GO SUB`, and `POKE` targets is a well-known memory optimization that avoids storing the floating-point number in the BASIC line - The keypress-wait idiom at lines 10–11 (`PAUSE 0` is not used here; instead line 10 waits for key-up then line 11 waits for key-down) is a clean debounce sequence ### Text Entry (Lines 1000–1500) Characters are POKEd directly into the buffer at `37999 + c` where `c` is a one-based character index. The display position `b` tracks column (0–32); every 33rd character, `POKE 23692, 9` suppresses the scroll prompt. The ENTER key opens a sub-menu (line 1100) offering line break (`▀`, code 131), paragraph break (`▜`, code 134), and page break (`▞`, code 139) markers — these special bytes drive the printer routine at lines 3000–3420. The quote character (code 34) is remapped to UDG-A (code 144) since bare quotes would interfere with string handling. ### Print Routine (Lines 3000–3420) The printer section walks the buffer byte by byte, assembling words into lines of up to 32 characters using a look-ahead to avoid splitting words. The variable `x` is the current buffer pointer; `y` is the tentative end of the next print segment. Special marker bytes branch to distinct handlers: - Codes >127 (other than 144/UDG-A) signal a formatting marker; code 139 triggers a paragraph break (lines 3200–3230), code 134 triggers a page break (lines 3300–3320) - Page formatting at lines 3400–3420 prints a five-line footer/header with a page number stored in `x2` - The printer-present flag `p` (set at line 901 via `IN 251`) controls whether `COPY` is issued (line 21) or INPUT is used to pause (line 22) ### Scan/Edit Mode (Lines 4000–4800) The scan/edit mode uses the machine code scroll routine (via `GO SUB 95`) to display a 320-character window centered on the cursor position `c`. Movement keys 5/6/7/8 (via `GO SUB 40`, lines 40–50) move a flashing cursor through the displayed text, updating both screen position `(m, n)` and buffer index `c` together. Additional single-letter commands from the sub-menu at line 4600 provide: - **Type** (`z`) — inserts from current position using the machine code block-move routines - **Seek** — calls the machine code search (line 4610) - **Alter** (search-and-replace) — lines 4630–4670 search for one string and replace with another using block moves - **Move** — relocates a previously cut block stored in the scratch buffer at address 37003 (lines 4800–4820) - **Delete** — marks start with `g`, moves cursor to end with repeated `d` keypresses, then shifts the remainder of the buffer left (line 4230) ### Save and Load (Lines 2000–2050, 5000–5030) Before saving, the two-byte text length `c1` is written to addresses 37998–37999 using the `RANDOMIZE`/`PEEK q`/`PEEK r` parameter idiom, so the entire block from 37998 is saved as a self-describing chunk. The SAVE covers `c1 + 2` bytes. After loading, line 2040 reconstructs `c1` from those same two bytes. A VERIFY step is offered after SAVE (line 5020–5030). ### Notable Techniques and Anomalies - Line 901 uses a compound `IN 251` test (checking for both `58` and `126`) to detect printer presence; result is stored as `0` or `1` in `p` using boolean arithmetic rather than IF/THEN. - Line 2 fills `a$` with 320 spaces and returns immediately — this string is PRINTed in display mode to blank the screen efficiently before the machine code fills it. - `POKE 23692, 9` at lines 1020 and 6030 resets the scroll counter, preventing the “scroll?” prompt from appearing during rapid text output. - Line 4160 has a subtle off-by-one guard: when `c` reaches 1 it clears the screen and goes to entry mode, preventing the reverse scroll machine code from being called with an invalid address. - The REM at line 3220 contains code that was commented out (alternative page-break formatting), which is an unusual but valid approach to preserving old code within the listing. - Line 1500 checks `INKEY$ <> "z"` to loop — this is a deliberate pause at buffer-full, requiring the user to press Z to force a tape save, after which `GO TO SGN PI` (line 1510) jumps to line 1, which is a non-existent target — likely intended as a program termination or reset point. ## Source Code ``` 1 GO TO 900 2 LET a$=" ":RETURN 10 IF INKEY$ <>"" THEN GO TO VAL "10" 11 LET b$= INKEY$:IF b$="" THEN GO TO VAL "11" 12 BEEP .02, NOT PI:RETURN 20 PRINT b$( TO y-x):LET x=y+1 21 IF x1=22 AND p= SGN PI THEN COPY :CLS :LET x1= NOT PI 22 IF x1=22 AND p= NOT PI THEN INPUT c$:CLS :LET x1= NOT PI 23 LET x1=x1+ SGN PI:LET x4=x4+ SGN PI:RETURN 25 PRINT AT PI+ PI, PI+ PI;" KEEP TAPE RUNNING " 30 GO SUB 85:RANDOMIZE v1:POKE VAL "60001", PEEK q:POKE VAL "60002", PEEK r:RANDOMIZE v2:POKE VAL "60004", PEEK q:POKE VAL "60005", PEEK r:RANDOMIZE v3:POKE VAL "60009", PEEK q:POKE VAL "60010", PEEK r:RANDOMIZE USR VAL "60000":RETURN 35 GO SUB 85:RANDOMIZE v1:POKE VAL "60015", PEEK q:POKE VAL "60016", PEEK r:RANDOMIZE v2:POKE VAL "60018", PEEK q:POKE VAL "60019", PEEK r:RANDOMIZE v3:POKE VAL "60023", PEEK q:POKE VAL "60024", PEEK r:RANDOMIZE USR VAL "60014":RETURN 40 LET c$= SCREEN$ (m,n):PRINT FLASH SGN PI; AT m,n;c$ 41 GO SUB 11:PRINT AT m,n;c$ 42 IF b$="5" THEN LET n=n- SGN PI:LET c=c- SGN PI 43 IF b$="6" THEN LET m=m+ SGN PI:LET c=c+32 44 IF b$="7" THEN LET m=m- SGN PI:LET c=c-32 45 IF b$="8" THEN LET n=n+ SGN PI:LET c=c+1 46 IF n<0 THEN LET n=n+32:LET m=m-1 47 IF n>31 THEN LET n=n-32:LET m=m+1 48 IF m<0 THEN LET c=c+32:LET m=m+ SGN PI:GO TO 48 49 IF m>19 THEN LET c=c-32:LET m=m- SGN PI:GO TO 49 50 RETURN 60 PRINT AT 20, NOT PI;" KEY TEXT " 61 PRINT ;:LET c3=li:LET b= NOT PI 62 GO SUB 10:LET a= CODE b$:IF a=13 THEN RETURN 63 IF CODE b$=34 THEN LET a=144:LET b$= CHR$ a 64 IF a=12 THEN GO TO 70 65 IF a<32 OR (a>127 AND a <>144) THEN GO TO 62 66 PRINT b$;:POKE c3,a:LET b=b+ SGN PI:LET c3=c3+ SGN PI:IF b=32 THEN LET b= NOT PI:POKE 23692,9 67 IF c3=37997 THEN RETURN 68 GO TO 62 70 LET c3=c3- SGN PI:IF c3