--- title: "Super-Cipher 2068 V2.2" id: 55041 type: "computer_media" slug: "super-cipher-2068-v2-2" url: "http://localhost/computer_media/super-cipher-2068-v2-2/" markdown_url: "http://localhost/computer_media/super-cipher-2068-v2-2.md" published_at: "2024-06-11T13:41:03+00:00" modified_at: "2026-03-30T21:45:52+00:00" author: "David Anderson" featured_image: url: "http://localhost/wp-content/uploads/2019/02/20230809-041332.jpg" excerpt: "A password-driven cipher program encodes and decodes secret messages using modular arithmetic, with tape storage, printer support, and a self-destruct termination sequence." 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: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" genre: - name: "Entertainment" slug: "entertainment" taxonomy: "genre" url: "http://localhost/type/entertainment/" media_contents: - id: 55036 title: "TS-2068 Computer Programs" type: "computer_media" url: "http://localhost/computer_media/ts-2068-computer-programs/" media_type: "Program" programmers: - name: "Imre Auersbacher" slug: "imre-auersbacher" taxonomy: "indiv" url: "http://localhost/indiv/imre-auersbacher/" mediadate: "1985" images: - url: "http://localhost/wp-content/uploads/2024/06/SCR-20260330-mouc.png" media_type_tags: "Entertainment" --- # Super-Cipher 2068 V2.2 Super-Cipher 2068 V2.2 is a text encryption and decryption program that uses a user-supplied password to generate a numeric key array, then applies a modular arithmetic cipher to encode or decode messages stored in a 2500-character string array. The password processing at line 140 builds a key array by combining character codes from the first, last, and current positions of the password with its length, reducing each value modulo 59 to produce key values. Encryption (subroutine at line 20) and decryption (subroutine at line 60) each walk through the message string, XOR-like combining character codes with cycling key values and wrapping the result into the printable ASCII range using modulo 59 arithmetic. The program supports printing encoded messages to a printer, saving and loading message files to tape, and a multi-level re-encoding option; it also uses two custom UDG characters (“a” and “b”) defined via POKEs from DATA at line 9900 for menu selection markers. Termination (option 4) triggers an elaborate SOUND and color-cycling sequence before issuing DELETE and NEW to wipe the program from memory. *** ## Program Analysis ### Program Structure The program is organized into distinct functional blocks, with a startup routine at line 9500 that initializes UDGs and jumps to the main menu at line 200. Menu dispatch uses the idiom `GO TO 1000*l` at line 270 to jump directly to one of four top-level sections (lines 1000, 2000, 3000, 4000). A secondary sub-menu at line 1055 uses `GO SUB 1000+100*INT x` at line 1085 to reach subsidiary routines at lines 1100, 1200, 1300, and 1400. | Line Range | Purpose | | --- | --- | | 2–9 | Keyboard input subroutine (builds message in `m$`) | | 20–50 | Encryption subroutine | | 60–100 | Decryption subroutine | | 110–160 | Password entry and key array generation | | 200–270 | Main menu display and dispatch | | 1000–1090 | Option 1: Code message on screen + sub-menu | | 1100 | Sub-option: Print message | | 1200–1240 | Sub-option: Save message to tape | | 1300–1310 | Sub-option: Re-encode to higher level | | 1400–1410 | Sub-option: Decode to lower level | | 2000–2040 | Option 2: Decode message on screen | | 3000–3060 | Option 3: Decode message from tape | | 4000–4090 | Option 4: Terminate with self-destruct sequence | | 9500–9600 | Startup: BEEP, POKE, UDG setup, jump to menu | | 9900 | DATA for UDG characters “a” and “b” | ### Cipher Algorithm The password subroutine (lines 110–160) prompts for a password of at least two characters, then constructs a numeric array `z()` of the same length. Each element is computed as: `x = CODE y$(1) + CODE y$(z) + CODE y$(t) + t - 32`, then reduced modulo 59: `z(z) = x - 59*INT(x/59)`. This means every key element blends the first character code, the last character code, the current character code, and the password length. Encryption (lines 20–50) cycles through the message string and for each character computes `x = z(y) + t + 9` (where `t` is the character’s code), then maps it into a printable range with `CHR$(x - 59*INT(x/59) + 32)`. Decryption (lines 60–100) reverses this: `x = t - z(y) - 42`, then adds 59 repeatedly while `x < 31` to keep the value in a valid range, yielding `CHR$(x+1)`. Both routines terminate on encountering a carriage-return character (code 13) stored as an end-of-message sentinel. ### Key Input Subroutine Lines 2–9 implement a custom keyboard input routine that bypasses the standard `INPUT` statement. It uses the `PAUSE 0`/`INKEY$` wait idiom across lines 4–5 to detect a keypress. Characters are stored one by one into the pre-dimensioned string array `m$(2500)`. The Delete key (code 12) is handled at line 7: it prints CHR$ 8 (cursor left), overwrites with a PAPER 6 space to visually erase, and decrements the position counter `l`. Enter (code 13) stores the sentinel and exits via `RETURN`. `ON ERR RESET` at line 6 guards against array bounds overrun when the message fills `m$`. ### ON ERR Usage Line 2 sets up `ON ERR GO TO 4` before dimensioning `m$`; if `m$` already exists from a prior run, the `DIM` at line 3 would cause an error, and execution jumps directly to the input wait at line 4, effectively skipping the re-dimension. Line 6 uses `ON ERR RESET` to silently handle any array overflow at the end of the message buffer. ### UDG Characters Lines 9500–9600 define two UDGs. Eight bytes each are read from the DATA at line 9900 and POKEd into the UDG table for characters “a” (CHR$ 144) and “b” (CHR$ 145). These are used at lines 250 and 1075 to display a selection arrow/indicator next to the currently chosen menu option, printed with contrasting INK colors (0 and 6). ### SOUND Usage The termination sequence (lines 4000–4060) makes extensive use of SOUND to produce an elaborate audio effect. Line 4000 calls `SOUND 7,62;8,15`, line 4020 cycles SOUND within a FOR loop using the loop variable, and line 4040 chains multiple SOUND channels. This provides dramatic audio feedback during the program’s self-destruction sequence. ### Self-Destruct Termination Option 4 (line 4000) performs a theatrical shutdown. After a color-cycling loop (lines 4020–4030) that rapidly changes PAPER and BORDER colors, a series of BORDER/PAPER/CLS flashes creates a strobe effect. Finally, `DELETE 0,4000` at line 4080 attempts to remove lines 0–4000 from memory, followed by `NEW` at line 4090 to wipe all remaining BASIC, making the program irretrievable without a fresh load from tape. ### Notable Techniques and Idioms - Computed `GO TO` with `GO TO 1000*l` and `GO SUB 1000+100*INT x` for clean menu dispatch without IF chains. - `POKE 23658,8` and `POKE 23658,0` toggle caps lock on and off to control input case during `INPUT` prompts. - `POKE 23692,0` resets the scroll counter to prevent the “scroll?” prompt from interrupting output. - `POKE 23609,10` sets the keyboard repeat delay. - The decryption loop at lines 85–90 uses a `GO TO`-based while loop to add 59 until the value is in range, rather than a direct modulo formula — functionally equivalent but typical of space-constrained BASIC. - Message end is detected by a CR sentinel (code 13) stored in `m$` rather than tracking a separate length variable, though `l` is also maintained as a length counter for printing and saving. - The tape load option at line 3060 previews only the first 672 characters of the loaded message (`m$(TO 672)`) before proceeding to decode, to avoid screen overflow. ### Potential Bugs and Anomalies - At line 40, `z(y)` references a numeric array named `z`, while `z` is also used as a `FOR` loop variable (lines 25, 65). This works because BASIC evaluates `z(y)` as an array element subscript, but it is an unusual and potentially confusing overloading of the variable name. - Similarly at line 150, `z(z)=x-...` assigns to array element `z(z)` where `z` is also the loop counter — functional, but relies on the BASIC interpreter correctly distinguishing array from scalar usage of the same name. - The decryption formula produces `CHR$(x+1)` while encryption uses `CHR$(x+32)` as a base offset. The asymmetry (offsets 9 vs. 42, and base adjustments +32 vs. +1) is intentional to the modular arithmetic but makes the relationship between encode and decode non-obvious at first glance. - Line 3060 re-uses `GO TO 2020` to jump mid-subroutine into the decode flow rather than calling it as a subroutine, meaning the stack is not cleaned up; this is not a problem in practice since this path never returns. ## Source Code ``` 1 GO TO 9500 2 LET l=1: ON ERR GO TO 4 3 DIM m$(2500): POKE 23692,0 4 IF INKEY$<>"" THEN GO TO 4 5 IF INKEY$="" THEN GO TO 5 6 LET q$=INKEY$: IF CODE q$=13 THEN LET m$(l)=q$: ON ERR RESET : RETURN 7 IF CODE q$=12 THEN PRINT CHR$ 8;: LET l=l-1: PRINT PAPER 6;" ";CHR$ 8;: GO TO 4 8 IF CODE q$=0 THEN GO TO 4 9 LET m$(l)=q$: LET l=l+1: PRINT PAPER 3; INK 7;q$;: GO TO 4 20 CLS : PRINT PAPER 6;"Coded message --> ": PRINT : 22 LET y=1: POKE 23692,0 25 FOR z=1 TO LEN m$ 30 IF y>LEN y$ THEN LET y=1 35 LET t=CODE m$(z): IF t=13 THEN LET l=z-1: RETURN 40 LET x=z(y)+t+9 45 LET q$=CHR$ (x-59*INT (x/59)+32): LET m$(z)=q$: PRINT q$; 50 LET y=y+1: NEXT z: RETURN 60 CLS : PRINT PAPER 6;"Decoded Message --> ": PRINT : 62 LET y=1: POKE 23692,0 65 FOR z=1 TO LEN m$ 70 IF y>LEN y$ THEN LET y=1 75 LET t=CODE m$(z): IF t=13 THEN LET l=z-1: RETURN 80 LET X=t-z(y)-42 85 IF x>=31 THEN GO TO 95 90 LET x=x+59: GO TO 85 95 LET q$=CHR$ (x+1): LET m$(z)=q$: PRINT q$;: LET y=y+1 100 NEXT z: RETURN 110 PRINT : PRINT "Password? "; 120 INPUT y$: IF LEN y$<=1 THEN BEEP 0.6,-22: GO TO 120 125 PRINT FLASH 1;" Secret " 130: LET t=LEN y$: DIM z(t) 140 FOR z=1 TO t: LET x=CODE y$(1)+CODE y$(z)+CODE y$(t)+t-32 150 LET z(z)=x-59*INT (x/59) 160 NEXT z: PRINT : RETURN 200 BORDER 5: POKE 23658,8: PAPER 3: CLS : POKE 23609,10 210 PRINT PAPER 6;AT 2,3;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";AT 3,3;"\: SUPER-CIPHER 2068 V2.2 \ :";AT 4,3;"\: \ :";AT 5,3;"\: \* 1985 I. AUERSBACHER \ :";AT 6,3;"\:.\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\..\.:" 220 PRINT PAPER 7;AT 9,12;" MENU "; PAPER 3;AT 10,12;"\''\''\''\''\''\''"; PAPER 7;AT 12,4;"1-Code a message on screen";AT 13,4;"2-Decode message on screen";AT 14,4;"3-Decode message from tape";AT 15,4;"4-Terminate the program "; PAPER 6;AT 21,3;"Please Choose Option (1-4)" 230 LET q$=INKEY$: IF q$="" THEN GO TO 230 240 LET l=CODE q$-48: IF (l<1)+(l>4) THEN BEEP 0.5,-15: BEEP 0.5,-20: GO TO 230 245 BEEP 0.05,25 250 PRINT INK 0;AT 11+l,1;CHR$ 144; INK 6;CHR$ 145: PAUSE 60 260 BEEP 0.04,20: BEEP 0.04,20 270 PAPER 7: GO TO 1000*l 1000 CLS : PRINT PAPER 6;" 1. Code Message on Screen " 1010 GO SUB 110: PRINT PAPER 6;"Enter Message-->": GO SUB 2 1020 GO SUB 20: PRINT 1030 PRINT : PRINT FLASH 1;" Coding Complete ": PRINT : PRINT 1040 PRINT PAPER 6;AT 21,3;"Press any key to continue" 1050 IF INKEY$="" THEN GO TO 1050 1055 BEEP 0.1,25: PAPER 3: CLS : PRINT PAPER 1; INK 7;AT 2,4;" Super-Cipher Sub-MENU " 1060 PRINT PAPER 7;AT 6,10;" Options "; PAPER 3;AT 7,10;"\''\''\''\''\''\''\''\''\''"; PAPER 7;AT 9,4;"1-Copy Message to Printer";AT 10,4;"2-Save Message to Tape ";AT 11,4;"3-Code to Higher Level ";AT 12,4;"4-Decode to Lower Level ";AT 13,4;"5-Return to Main Menu "; PAPER 6;AT 21,3;"Please Enter Option (1-5)" 1065 LET q$=INKEY$: IF q$="" THEN GO TO 1065 1070 LET x=CODE q$-48: IF (x<1)+(x>5) THEN BEEP 0.5,-15: BEEP 0.6,-20: GO TO 1065 1075 BEEP 0.05,25: PRINT INK 0;AT 8+x,1;CHR$ 144; INK 6;CHR$ 145 1080 PAUSE 60: PAPER 7: BEEP 0.05,22: IF x=5 THEN GO TO 200 1085 GO SUB 1000+100*INT x 1090 GO TO 1055 1100 LPRINT : LPRINT m$( TO l): LPRINT : LPRINT : RETURN 1200 CLS : PRINT PAPER 6;AT 2,2;"Name of this message file? " 1205 POKE 23658,0 1210 INPUT x$: IF LEN x$>10 OR x$="" THEN BEEP 1,-20: GO TO 1210 1215 PRINT " ";x$: POKE 23658,8 1220 SAVE x$ DATA m$() 1230 BEEP 0.1,22: PRINT AT 5,2;"File ";x$;" Saved."; FLASH 1;AT 8,8;" Stop Recorder " 1240 PAUSE 500: RETURN 1300 CLS : GO SUB 110: GO SUB 20 1310 PRINT : PRINT : PRINT FLASH 1;" Coding Complete ": PRINT : PRINT : PAUSE 2000: RETURN 1400 CLS : GO SUB 110: GO SUB 60 1410 PRINT : PRINT : PRINT FLASH 1;" Decoding Complete ": PRINT : PRINT : PAUSE 2000: RETURN 2000 CLS : PRINT PAPER 6;" 2. Decode Message on Screen " 2010 GO SUB 110: PRINT PAPER 6;"Enter Message-->": GO SUB 2 2020 GO SUB 60: PRINT 2030 PRINT : PRINT FLASH 1;" Decoding Complete ": PRINT : PRINT 2040 GO TO 1040 3000 CLS : PRINT PAPER 6;" 3. Decode Message from Tape " 3010 GO SUB 110: PRINT "What is file name? ";: POKE 23658,0 3020 INPUT x$: IF LEN x$>10 OR x$="" THEN BEEP 1,-20: GO TO 3020 3030 PRINT x$: POKE 23658,8 3035 INPUT "Press ENTER & Start Recorder "; LINE q$ 3040 PRINT : PRINT FLASH 1;AT 6,2;" Loading ";x$;" " 3045 LOAD x$ DATA m$() 3050 BEEP 0.1,22: PRINT : PRINT FLASH 1;" Please Stop Recorder " 3060 PAUSE 300: CLS : PRINT m$( TO 672): PAUSE 120: GO TO 2020 4000 CLEAR : SOUND 7,62;8,15 4020 FOR l=40 TO 120: SOUND 0,l 4025 LET x=l-6*INT (l/6)+1 4028 PAPER x: BORDER 7-x: CLS 4030 PAUSE 1: NEXT l 4040 SOUND 6,6;7,7;8,16;9,16;10,16;12,56;13,8 4045 BORDER 0: PAPER 0: CLS 4050 PAUSE 30: BORDER 7: PAPER 7: CLS : PAUSE 30: BORDER 0 4055 PAPER 0: CLS : PAUSE 30 4058 BORDER 7: PAPER 7: CLS 4060 SOUND 8,0;9,0;10,0 4070 PRINT FLASH 1;AT 10,5;" Program Terminated " 4080 PRINT PAPER 6;AT 14,6;" Security Risk = 0 ": DELETE 0,4000 4090 PAUSE 300: NEW 9500 BEEP 0.05,22: BEEP 0.06,20: POKE 23609,10: POKE 23658,8 9600 RESTORE 9900: FOR l=0 TO 7: READ x,y: POKE USR "a"+l,x: POKE USR "b"+l,y: NEXT l: GO TO 200 9900 DATA 0,24,0,48,127,96,127,255,127,255,115,248,115,248,127,240 9990 SAVE "cipher" LINE 9500 ```