--- title: "Tasword with Form Feed (SMUG)" id: 72012 type: "computer_media" slug: "tasword-with-form-feed-smug" url: "http://localhost/computer_media/tasword-with-form-feed-smug/" markdown_url: "http://localhost/computer_media/tasword-with-form-feed-smug.md" published_at: "2026-10-20T15:00:10+00:00" modified_at: "2026-10-20T15:00:10+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2026/10/TASWORD_w_FF-scaled.jpg" excerpt: "A user group's copy of the Tasword Two word processor altered for form-feed printing, with a separate tape holding a Tasword data file for member sign-up." 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: "Cassette" download_url: "https://archive.org/download/timex-sinclair-software-archive/Tasword%20with%20Form%20Feed%20%281985%29%28SMUG%29%28TS2068%29%28US%29%28Cassette%29.zip" tsrun_member: "Tasword with Form Feed (1985)(SMUG)(TS2068)(US)(Cassette)/TASWORD_w_FF.tap" mediadate: "1985" producer_company: - id: 22398 title: "Tasman Software" type: "company" url: "http://localhost/company/tasman-software/" images: - url: "http://localhost/wp-content/uploads/2026/10/TASWORD_w_FF-scaled.jpg" - url: "http://localhost/wp-content/uploads/2026/10/SMUG-scaled.jpg" related_content: - id: 51793 title: "Tasword II" type: "computer_media" url: "http://localhost/computer_media/tasword-ii/" - id: 24825 title: "Sinclair Milwaukee Users Group (SMUG)" type: "usergroup" url: "http://localhost/usergroup/sinclair-milwaukee-users-group-smug/" - id: 37935 title: "SMUG Bytes" type: "periodical" url: "http://localhost/periodical/smug-bytes/" media_type_tags: "Word Processor" --- # Tasword with Form Feed (SMUG) Holds a copy of the Tasword Two word processor, credited on its menu screen to Tasman Software 1983, in a version a user group altered for form-feed printing. The BASIC menu prints, saves, loads and merges text files, returns to the editor, defines printer control codes and graphics-character printer codes, saves a fresh copy of Tasword to tape, or exits to BASIC; a separate find-and-replace entry takes a single word and an optional replacement and hands them to the machine code. Text is stored as 64-character lines, and the print routine asks for line spacing and the first and last lines to print. This item comes from two cassettes connected with the Sinclair Milwaukee Users Group (SMUG). The first is labeled by hand “TASWORD” W/FORM FEED 2-12-85, with an earlier note crossed out, and holds a BASIC loader, saved as `tasword` with auto-start at line 15, and a 10,751-byte machine-code block at 54784. The second is labeled “SIGN-UP” SMUG REGISTRATION, DATA: TASWORD and holds a Tasword text file for the group’s member sign-up. It survives only as a raw direct recording and has not been decoded. ## Program Analysis ### Program Structure - 10–190: entry from the editor (`USR 64330`), rounding of the text length to whole 64-byte lines, and the main menu, which flashes the chosen key and asks for ENTER to confirm or C to change. - 200–290: print options, then sending the text to the printer through the machine code, with optional interface codes sent before and after. - 300–490: printer-code tables for the 16 block-graphic characters (128–143), and the interface control codes, carriage return, line feed and left margin. - 700–790: `SAVE` and `VERIFY` of both the BASIC and the code block. - 1000–2030: save, verify and load or merge text files. - 3000–3060: find-and-replace, passing the strings through the printer buffer area at 23296. - 6000–6210: a line-input routine with a flashing cursor, delete and a key-click `BEEP`. ### Notable Techniques - Every numeric constant is written as `VAL "n"`, which stores fewer bytes than a literal number. - `DEF FN p(x)=PEEK x+VAL "256"*PEEK (x+VAL "1")` reads 16-bit pointers from the code block, and line 950 writes them back. - Printing calls an interface driver through an address stored in the code, `RANDOMIZE USR (FN p(VAL "62472"))`, so the same program can drive different printer interfaces. - `POKE 23609,2` sets a short keyboard click before loading. ### Potential Issues - The form-feed change is not visible in the BASIC, and the before-and-after interface codes at 62470 and 62471 are 0 in this save, so the patch is presumably in the machine code. ## Source Code ``` 10 CLS : LET a=USR VAL "64330": GO TO VAL "20" 11 FOR i=VAL "1" TO VAL "9": BEEP VAL ".2",VAL "3": BEEP VAL ".3",VAL "2": NEXT i: RETURN 15 POKE VAL "23609",VAL "2": CLEAR VAL "33279": GO SUB VAL "4000": PRINT AT VAL "10",VAL "5"; FLASH VAL "1";"Do NOT stop the tape";AT VAL "1",VAL "0": LOAD "tasword"CODE : CLS : PRINT AT VAL "10",VAL "6"; FLASH VAL "1";"Stop the tape": GO SUB VAL "11": LET a=USR VAL "59081": GO TO VAL "10" 20 CLS : LET a=64*INT (a/64+VAL "0.99"): IF a=VAL "0" THEN GO TO VAL "3000" 25 GO SUB VAL "4000": PRINT AT VAL "4",VAL "0";"print text file p" 28 PRINT : PRINT "save text file s" 30 PRINT : PRINT "load text file j" 35 PRINT : PRINT "merge text file m" 40 PRINT : PRINT "return to text file y" 45 PRINT : PRINT "define graphics/printer g" 50 PRINT : PRINT "save tasword t" 55 PRINT : PRINT "into Basic b" 70 PRINT AT VAL "20",VAL "0";" press key " 80 LET a$=INKEY$: IF a$="" THEN GO TO VAL "80" 90 LET i=VAL "0": LET b=CODE a$: IF bVAL "0" THEN PRINT AT i,VAL "31"; FLASH VAL "1";CHR$ b;: GO TO VAL "500" 190 GO TO VAL "80" 200 CLS : GO SUB VAL "4000": PRINT AT VAL "4",VAL "8";"PRINT OPTIONS": PRINT " just press ENTER for default values given in brackets" 210 LET i=VAL "8": LET j0=VAL "23": PRINT AT i,VAL "0";"Line spacing? (1)": GO SUB VAL "6000": IF a$="" THEN LET a$="1" 215 POKE VAL "62235",VAL a$ 220 LET i=VAL "10": PRINT AT i,VAL "0";"Start at line? (1)": GO SUB VAL "6000": IF a$="" THEN LET a$="1" 230 LET c=64*(INT VAL a$-VAL "1"): LET b=c+FN p(VAL "62216"): LET x=VAL "60045": GO SUB VAL "950" 240 LET i=VAL "12": PRINT AT i,VAL "0";"Finish at line? (last)": GO SUB VAL "6000": IF a$="" THEN LET b=a-c: GO TO VAL "250" 245 LET b=64*INT VAL a$-c 250 RANDOMIZE USR VAL "59806": RANDOMIZE USR (FN p(VAL "62472")) 260 CLS : PRINT AT VAL "20",VAL "0";"Press the q key to quit printing" 270 LET x=VAL "60049": GO SUB VAL "950" 275 LET c=PEEK VAL "62470": IF c<>VAL "0" THEN LPRINT CHR$ c 280 RANDOMIZE USR VAL "60038" 285 LET c=PEEK VAL "62471": IF c<>VAL "0" THEN LPRINT CHR$ c 290 RANDOMIZE USR VAL "59806": GO TO VAL "10" 300 CLS : GO SUB VAL "4000": PRINT "Printer control graphics chars:" 305 LET b=VAL "4": FOR i=VAL "0" TO VAL "15": LET b=ABS (b-VAL "4"): PRINT AT i+VAL "4",b;i+VAL "128";CHR$ (i+VAL "128") 307 FOR j=VAL "0" TO VAL "3": LET c=PEEK (VAL "60860"+i*VAL "4"+j): LET a$=STR$ c: IF c=VAL "255" THEN LET a$="" 308 PRINT AT i+VAL "4",VAL "10"+VAL "4"*j;a$: NEXT j: NEXT i 320 INPUT "Type graphics character code 128-143 (ENTER if finished)";a$ 325 IF a$="" THEN GO TO VAL "400" 340 LET b=VAL a$: IF bVAL "143" THEN GO TO VAL "320" 350 PRINT AT VAL "21",VAL "3"; FLASH VAL "1";b; FLASH VAL "0";" ";CHR$ b 355 FOR j=VAL "0" TO VAL "3": POKE (VAL "60348"+b*VAL "4"+j),VAL "255": NEXT j 360 FOR j=VAL "0" TO VAL "3": INPUT "Code? (ENTER if finished)";a$: IF a$="" THEN GO TO VAL "300" 370 POKE (VAL "60348"+b*VAL "4"+j),VAL a$: PRINT AT VAL "21",VAL "10"+VAL "4"*j;VAL a$: NEXT j: GO TO VAL "300" 400 CLS : GO SUB VAL "4000": PRINT AT VAL "3",VAL "0";"Reset interface/printer codes?": LET i=VAL "5": GO SUB VAL "920": CLS : IF i=VAL "0" THEN GO TO VAL "25" 401 GO SUB VAL "4000": PRINT AT VAL "3",VAL "0";"just ENTER to keep values given:" 403 LET j0=VAL "27": LET i=VAL "8": LET j=VAL "0": LET a$="Interface control code1=": LET x=VAL "60924": GO SUB VAL "850" 404 LET i=VAL "9": LET j=VAL "18": LET a$="code2=": LET x=VAL "62470": GO SUB VAL "850" 405 LET i=VAL "10": LET j=VAL "18": LET a$="code3=": LET x=VAL "62471": GO SUB VAL "850" 406 LET i=VAL "11": PRINT AT i,VAL "18";"code4=";FN p(VAL "62472"): LET i=VAL "12": LET j0=VAL "24": GO SUB VAL "6000": LET j0=VAL "27": IF a$<>"" THEN LET b=VAL a$: LET x=VAL "62472": GO SUB VAL "950" 410 LET i=VAL "14": LET j=VAL "0": LET a$="Printer carriage return=": LET x=VAL "60925": GO SUB VAL "850" 420 LET i=VAL "16": LET j=VAL "0": LET a$="Printer linefeed=": LET x=VAL "60926": GO SUB VAL "850" 430 LET i=VAL "18": LET j=VAL "0": LET a$="Left margin on printing=": LET x=VAL "60927": GO SUB VAL "850" 490 GO TO VAL "20" 500 PRINT AT VAL "20",VAL "0";" press the "; FLASH VAL "1";"ENTER"; FLASH VAL "0";" key to proceed";AT VAL "21",VAL "0";" press "; FLASH VAL "1";"c"; FLASH VAL "0";" to change the choice " 510 LET a$=INKEY$: IF a$="c" OR a$="C" THEN GO TO VAL "20" 520 IF CODE a$=VAL "13" THEN GO TO VAL "600" 530 GO TO VAL "510" 600 IF b=VAL "116" THEN GO TO VAL "700" 610 IF b=VAL "121" THEN CLS : GO TO VAL "10" 620 IF b=VAL "115" THEN CLS : GO TO VAL "1000" 630 IF b=VAL "109" THEN GO TO VAL "2000" 640 IF b=VAL "106" THEN LET a=USR VAL "59081": LET a=VAL "0": GO TO VAL "2000" 650 IF b=VAL "112" THEN GO TO VAL "200" 660 IF b=VAL "103" THEN GO TO VAL "300" 699 CLS : STOP 700 CLS : LET i=VAL "8": GO SUB VAL "800": LET a$="tasword": SAVE a$ LINE VAL "15" 710 SAVE a$CODE VAL "54784",VAL "10751": GO SUB VAL "900" 770 PRINT AT VAL "19",VAL "0"; 780 VERIFY a$: PRINT AT VAL "21",VAL "0";"tasword: basic O.K.;";AT VAL "19",VAL "0"; 790 VERIFY a$CODE VAL "54784",VAL "10751": PRINT AT VAL "21",VAL "20";" m/code O.K.": GO TO VAL "25" 800 PRINT AT i,VAL "0";"Remove ear plug from cassette.": RETURN 850 PRINT AT i,j;a$;PEEK x: GO SUB VAL "6000": IF a$<>"" THEN POKE x,VAL a$ 860 RETURN 900 PRINT AT VAL "8",VAL "0";"Reconnect ear plug, and rewind";AT VAL "10",VAL "0";"and play the tape to verify";AT VAL "12",VAL "0";a$: RETURN 920 PRINT AT i,VAL "4";"press y for yes";AT i+VAL "2",VAL "11";"n for no" 930 IF INKEY$="n" OR INKEY$="N" THEN LET i=VAL "0": RETURN 940 IF INKEY$="y" OR INKEY$="Y" THEN LET i=VAL "1": RETURN 945 GO TO VAL "930" 950 POKE x,b-VAL "256"*INT (b/VAL "256"): POKE (x+VAL "1"),INT (b/VAL "256"): RETURN 1000 LET b=FN p(VAL "62216"): CLS 1005 PRINT AT VAL "8",VAL "0";"Name of text file for saving?": LET i=VAL "10": LET j0=VAL "0": GO SUB VAL "6000" 1010 IF LEN a$>VAL "10" THEN CLS : PRINT AT VAL "12",VAL "0";"too many characters - max is 10": GO TO VAL "1005" 1020 IF LEN a$=VAL "0" THEN : CLS : PRINT AT VAL "12",VAL "0";"there must be a name": GO TO VAL "1005" 1030 LET i=VAL "12": GO SUB VAL "800": SAVE a$CODE b,a: CLS 1040 PRINT AT VAL "8",VAL "0";"text file ";a$;" saved:";AT VAL "10",VAL "0";a;" bytes,",a/PEEK VAL "62237";" lines" 1050 PRINT AT VAL "12",VAL "0";"do you want to verify ";a$;" ?": LET i=VAL "14": GO SUB VAL "920": IF i=VAL "0" THEN GO TO VAL "20" 1100 CLS : GO SUB VAL "900": VERIFY a$CODE b,a 1110 PRINT AT VAL "21",VAL "6";"text file verified": GO TO VAL "25" 2000 CLS : PRINT AT VAL "8",VAL "0";"type the name of the text file";AT VAL "10",VAL "0";"and press ENTER" 2010 PRINT AT VAL "12",VAL "2";"just press ENTER to load the";AT VAL "14",VAL "2";"first text file on the tape" 2020 LET j0=VAL "0": LET i=VAL "16": GO SUB VAL "6000": PRINT AT VAL "18",VAL "9";"Play the tape" 2030 LET b=FN p(VAL "62216"): LOAD a$CODE (a+b),((FN p(VAL "62221")+VAL "22")*VAL "64"-a): GO TO VAL "10" 3000 FOR i=VAL "23296" TO VAL "23361": POKE i,VAL "32": NEXT i 3005 POKE VAL "23362",VAL "0" 3010 PRINT AT VAL "8",VAL "0";"type word to be replaced / found" 3012 LET j0=VAL "0": LET i=VAL "10": GO SUB VAL "6000": IF a$="" THEN GO TO VAL "10" 3020 LET j=VAL "0": FOR i=VAL "1" TO LEN a$: POKE VAL "23297"+i,CODE a$(i): IF a$(i)=" " THEN LET j=j+VAL "1" 3021 NEXT i 3022 IF j<>VAL "0" THEN CLS : PRINT AT VAL "12",VAL "0";"just a word - no spaces allowed": GO TO VAL "3000" 3025 POKE VAL "23297",LEN a$ 3030 PRINT AT VAL "12",VAL "0";"with (just ENTER for find only)": LET i=VAL "14": GO SUB VAL "6000" 3040 IF a$="" THEN POKE VAL "23362",VAL "1": GO TO VAL "3060" 3050 FOR i=VAL "1" TO LEN a$: POKE VAL "23329"+i,CODE a$(i): NEXT i 3060 LET a=USR VAL "64955": LET a=USR VAL "64333": GO TO VAL "20" 4000 PRINT AT VAL "0",VAL "9";"Tasword Two";AT VAL "1",VAL "4";"* Tasman Software 1983": RETURN 6000 LET a$="": PRINT AT i,j0; FLASH VAL "1";" " 6010 LET j=j0: IF INKEY$<>"" THEN GO TO VAL "6010" 6020 LET b$=INKEY$ 6030 IF b$="" THEN GO TO VAL "6020" 6040 IF CODE b$=VAL "13" THEN PRINT AT i,j;" ": RETURN 6050 IF CODE b$<>VAL "12" THEN GO TO VAL "6170" 6060 IF j=j0 THEN GO TO VAL "6200" 6070 LET j=j-VAL "1": PRINT AT i,j; FLASH VAL "1";" "; FLASH VAL "0";" ": LET a$=a$( TO j-j0): GO TO VAL "6200" 6170 IF CODE b$VAL "127" THEN GO TO VAL "6200" 6180 BEEP VAL ".005",VAL "5": PRINT AT i,j;b$; FLASH VAL "1";" ": LET j=j+VAL "1": LET a$=a$+b$ 6190 IF j=VAL "32" THEN PRINT AT i+VAL "1",VAL "0";" ": RETURN 6200 IF INKEY$<>"" THEN GO TO VAL "6200" 6210 GO TO VAL "6020" 7000 DEF FN p(x)=PEEK x+VAL "256"*PEEK (x+VAL "1") ```