Super-Cipher 2068 V3.1

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 V3.1 is a Vigenère-style text encryption and decryption program that accepts keyboard input character by character, applies a password-derived numeric key array, and encodes or decodes messages stored in a 2600-character string array. The cipher uses a modular arithmetic formula — `x – 91 * INT(x/91)` — to wrap encoded character values into a printable ASCII range, with the key array built from a combination of the password’s first, last, and current characters plus its length. Messages can be printed to a printer, saved to tape as a DATA array, or loaded back from tape for decoding. Two custom UDG characters (“a” and “b”) are defined at startup via POKEs into USR memory, used for menu selection indicators.


Program Analysis

Program Structure

The program is organized into clearly separated functional blocks, entered via computed GO TO from the main menu. The entry point at line 9500 initializes UDGs and jumps to the main menu at line 200. The four menu options dispatch via GO TO 1000*l (line 270), directing to lines 1000, 2000, 3000, and 4000.

  • Lines 2–9: Custom keyboard input subroutine (GO SUB 2)
  • Lines 20–50: Encoding subroutine (GO SUB 20)
  • Lines 60–100: Decoding subroutine (GO SUB 60)
  • Lines 110–160: Password entry and key array generation (GO SUB 110)
  • Lines 200–270: Main menu display and dispatch
  • Lines 1000–1410: Option handlers (code on screen, printer, tape save, re-code, re-decode, sub-menu)
  • Lines 2000–2040: Decode on screen
  • Lines 3000–3060: Decode from tape
  • Lines 4000–4090: Termination sequence
  • Lines 9500–9990: Initialization and UDG setup

Cipher Algorithm

The password processing subroutine at line 110 builds a numeric array z(t) where t is the password length. For each position z, the key value is computed as:

x = CODE y$(1) + CODE y$(z) + CODE y$(t) + t - 32

then reduced modulo 91: z(z) = x - 91*INT(x/91). This mixes the first character, current character, and last character of the password, making the key non-trivially derived from the password string.

Encoding (subroutine at line 20) applies: x = z(y) + t + 9, then wraps with CHR$(x - 91*INT(x/91) + 32), where t is the code of the plaintext character. Decoding (subroutine at line 60) reverses this: x = t - z(y) - 42, then adds 91 repeatedly until x >= 31 via a loop at lines 85–90, finally producing CHR$(x+1). The asymmetry between the +9/+32 encoding offset and the -42/+1 decoding offset is notable and must be internally consistent for round-tripping.

Custom Keyboard Input Subroutine

Lines 2–9 implement a fully custom line-input routine. It uses ON ERR GO TO 4 at line 2 to handle out-of-bounds errors when the message buffer m$ fills. The subroutine supports:

  • ENTER (code 13): terminates input, stores the carriage return, and RETURNs
  • DELETE/backspace (code 12): moves back one character, prints a PAPER 6 space to visually erase, and decrements l
  • Code 0 (no key or SHIFT): ignored
  • All other characters: stored in m$(l), displayed in PAPER 3 / INK 7, and l incremented

The POKE 23692,0 call resets the scroll counter, preventing the “scroll?” prompt from interrupting output.

Message Storage

The message is stored in a single DIM m$(2600) string declared at line 3. The variable l tracks the current length of the typed message. The terminating carriage return (code 13) at m$(l) serves as the end-of-message sentinel, checked in both encode and decode loops at lines 35 and 75. Tape operations use SAVE x$ DATA m$() and LOAD x$ DATA m$() (lines 1220, 3045), saving the full 2600-byte array regardless of message length.

UDG Initialization

Lines 9500–9600 define two custom UDG characters using a DATA block at line 9900. Eight bytes each for UDGs “a” and “b” are POKEd into USR "a" and USR "b" via a loop. These characters are used at line 1075 and 250 as menu selection arrow/pointer graphics printed beside the chosen option.

Termination Sequence

Option 4 triggers an elaborate termination at lines 4000–4090. It uses SOUND commands to produce tones, cycles through PAPER and BORDER colors in a loop (lines 4025–4030), flashes the screen several times, prints a “Program Terminated” message, calls DELETE 0,4000 (which attempts to delete line range 0–4000), and finally executes NEW to wipe all variables and program state. The CLEAR at line 4000 also clears all variables before the sound/visual sequence.

Notable Techniques and Idioms

  • ON ERR GO TO 4 and ON ERR RESET are used for error trapping — the former recovers from a buffer overflow, the latter clears the error handler on a clean RETURN from input.
  • Computed dispatch: GO TO 1000*l eliminates an explicit IF/THEN chain for the four main menu options.
  • VAL "number" is not used; line numbers are given as literals in GO TO/GO SUB statements.
  • POKE 23658,0 disables CAPS LOCK before INPUT statements to ensure consistent case handling.
  • The sub-menu at line 1055 uses GO SUB 1000+100*INT x (line 1085) for computed subroutine dispatch across options 1–4.
  • The scroll suppression POKE 23692,0 is used in multiple places to prevent interactive scroll prompts during long output sequences.

Potential Issues

  • At line 3060, PRINT m$( TO 672) displays only the first 672 characters of a potentially 2600-character message before pausing, which may truncate longer decoded messages on screen.
  • The key-stream cycling at lines 30/70 resets y=1 when y > LEN y$, but the increment of y happens after the check, meaning the last key byte is used once before wrapping — a standard Vigenère cycling pattern.
  • In the decode formula, line 80 uses uppercase X (LET X=t-z(y)-42) while subsequent lines reference lowercase x — on this platform, BASIC variable names are case-insensitive, so this is not a bug.
  • The DELETE 0,4000 at line 4080 is a TS2068-specific command; its effect before NEW is largely cosmetic since NEW clears everything anyway.

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

Source Code

    1 GO TO 9500
    2 LET l=1: ON ERR GO TO 4
    3 DIM m$(2600): 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-91*INT (x/91)+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+91: 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-91*INT (x/91)
  160 NEXT z: PRINT : RETURN 
  200 BORDER 5: POKE 23658,0: PAPER 3: CLS : POKE 23609,10
  210 PRINT PAPER 6;AT 2,3;"\:'\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\''\':";AT 3,3;"\:  SUPER-CIPHER 2068 V3.1 \ :";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,0
 1220 SAVE x$ DATA m$()
 1230 BEEP 0.1,22: PRINT AT 5,2;"File: "; PAPER 6;x$; PAPER 7;" 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,0
 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,0
 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 "cipher2" LINE 9500

Note: Type-in program listings on this website use ZMAKEBAS notation for graphics characters.

Scroll to Top