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 TOwithGO TO 1000*landGO SUB 1000+100*INT xfor clean menu dispatch without IF chains. POKE 23658,8andPOKE 23658,0toggle caps lock on and off to control input case duringINPUTprompts.POKE 23692,0resets the scroll counter to prevent the “scroll?” prompt from interrupting output.POKE 23609,10sets 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, thoughlis 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 namedz, whilezis also used as aFORloop variable (lines 25, 65). This works because BASIC evaluatesz(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 elementz(z)wherezis 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 usesCHR$(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 2020to 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.
Content
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
Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.
