Super-Cipher 2068 V2.2

This file is part of and TS-2068 Computer Programs. Download the collection to get this file.
Developer(s): Imre Auersbacher
Date: 1985
Type: Program
Platform(s): TS 2068

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 RangePurpose
2–9Keyboard input subroutine (builds message in m$)
20–50Encryption subroutine
60–100Decryption subroutine
110–160Password entry and key array generation
200–270Main menu display and dispatch
1000–1090Option 1: Code message on screen + sub-menu
1100Sub-option: Print message
1200–1240Sub-option: Save message to tape
1300–1310Sub-option: Re-encode to higher level
1400–1410Sub-option: Decode to lower level
2000–2040Option 2: Decode message on screen
3000–3060Option 3: Decode message from tape
4000–4090Option 4: Terminate with self-destruct sequence
9500–9600Startup: BEEP, POKE, UDG setup, jump to menu
9900DATA 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.

Content

Appears On

Predict eclipses across four millennia, track planetary positions through five centuries, calculate loan amortization schedules, or encode secret messages with modular arithmetic — Imre Auersbacher's collection brings scientific precision and practical utility to the TS 2068.

Related Products

Related Articles

Related Content

Image Gallery

Super-Cipher 2068 V2.2

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.

Scroll to Top