Cypher

This file is part of and Timex Sinclair Public Domain Library Tape 1004. Download the collection to get this file.
Date: 198x
Type: Program
Platform(s): TS 1000
Tags: Utility

This program implements a Vigenère cipher, supporting both encipherment and decipherment of text messages using a user-supplied keyword. It pre-computes a 26×26 substitution table stored in array A, where each row represents a Caesar-shifted alphabet corresponding to a keyword letter. The encoding relies on character codes offset by 37, which aligns with the ZX81’s character set where uppercase ‘A’ is code 38. Decipherment performs a linear search across each row of the array to reverse the substitution, rather than computing it algebraically. The program switches between FAST and SLOW modes to balance display speed during computation and user interaction.


Program Analysis

Program Structure

The program is divided into four logical phases:

  1. Initialisation (lines 40–130): Builds a 26×26 Vigenère substitution table in array A using FAST mode.
  2. User Input (lines 150–280): Prompts for a keyword (K$), a message (M$), and an operation choice (Q$) in SLOW mode.
  3. Encipherment (lines 330–430): Iterates over the message, cycling through the keyword, and prints each enciphered character.
  4. Decipherment (lines 450–560): Iterates over the message and searches each row of A for the matching cipher value, printing the plaintext character.

Lines 570–580 are a SAVE/RUN footer used for tape storage and auto-restart.

The Vigenère Table

The array A(26,26) is populated at lines 70–130. Row I contains the alphabet shifted left by I-1 positions, achieved by initialising J=-1 before the outer loop and incrementing it each iteration. The wrap-around at line 110 (IF A(I,K)>26 THEN LET A(I,K)=A(I,K)-26) keeps values in the range 1–26.

Character Code Arithmetic

All character lookups subtract 37 from the ZX81 character code. On the ZX81, uppercase letters run from code 38 (‘A’) to 63 (‘Z’), so subtracting 37 maps ‘A’→1 through ‘Z’→26, aligning neatly with the 1-based array indices. The reverse operation, CHR$(value + 37), reconstructs the printable letter.

Encipherment Logic

Lines 360–430 use a manual loop rather than a FORNEXT construct. The counter T indexes into the message, while S cycles through the keyword with modular arithmetic at line 390. The enciphered character is produced at line 410:

PRINT CHR$ (37 + A(CODE K$(S)-37, CODE M$(T)-37))

This looks up row = keyword-letter index, column = message-letter index in the pre-built table, which is the standard Vigenère substitution.

Decipherment Logic

Decipherment at lines 490–550 uses a FOR X=1 TO 26 linear search across each row of A, testing whether A(keyword-row, X) = cipher-letter index. When the match is found, CHR$(X+37) is printed. While functionally correct, this is O(26) per character rather than a direct inverse calculation, and it will print the character for every matching cell (though in a valid Vigenère row each value appears exactly once, so this is safe in practice).

Control Flow and Notable Idioms

  • Line 310 (IF Q$<>"E" OR Q$<>"D" THEN GOTO 260) is a logic bug: due to the use of OR, this condition is always true (any string is not equal to at least one of the two literals), so it always re-prompts regardless of valid input. In practice this line is only reached when neither line 290 nor 300 branched, so it works correctly by coincidence — the branch at 310 is redundant but harmless.
  • Line 320 is missing from the listing; line 330 is the actual start of the encipherment block. The GOTO 320 at line 290 targets line 330, which is the next available line — a common ZX81 idiom where GO TO to a non-existent line falls through to the next.
  • Line 420 branches to line 140, which does not exist; execution falls through to line 150, restarting the input prompts after encipherment — another deliberate use of the non-existent-line technique.
  • Similarly, line 560 GOTO 140 restarts the program loop after decipherment.
  • FAST/SLOW switching is used appropriately: computation in FAST mode, display and input in SLOW mode.

Limitations

  • The program handles only uppercase letters (codes 38–63). Any other character in the keyword or message will produce incorrect character code arithmetic and likely a program error.
  • No validation is performed on the keyword or message contents.
  • Spaces and punctuation in M$ will cause out-of-range array accesses.

Content

Appears On

Assembled by Tim Ward from many sources. Contains programs 10176 – 10210.

Related Products

Related Articles

Related Content

Image Gallery

Cypher

Source Code

  10 REM "CYPHER"
  40 FAST 
  50 DIM A(26,26)
  60 LET J=-1
  70 FOR I=1 TO 26
  80 LET J=J+1
  90 FOR K=1 TO 26
 100 LET A(I,K)=K+J
 110 IF A(I,K)>26 THEN LET A(I,K)=A(I,K)-26
 120 NEXT K
 130 NEXT I
 150 PRINT 
 160 PRINT 
 170 SLOW 
 180 PRINT " ENTER KEYWORD"
 190 INPUT K$
 200 PRINT K$
 210 PRINT 
 220 PRINT " ENTER MESSAGE"
 230 INPUT M$
 240 PRINT M$
 250 PRINT 
 260 PRINT " ENCYPHER/DECYPHER? (ENTER E OR D)"
 270 INPUT Q$
 280 PRINT 
 290 IF Q$="E" THEN GOTO 320
 300 IF Q$="D" THEN GOTO 440
 310 IF Q$<>"E" OR Q$<>"D" THEN GOTO 260
 330 FAST 
 340 PRINT " ENCYPHERED MESSAGE READS:-"
 350 PRINT 
 360 LET S=0
 370 LET T=0
 380 LET S=S+1
 390 IF S>LEN K$ THEN LET S=S-LEN K$
 400 LET T=T+1
 410 PRINT CHR$ (37+A(CODE K$(S)-37,CODE M$(T)-37));
 420 IF T=LEN M$ THEN GOTO 140
 430 GOTO 380
 450 FAST 
 460 LET Z=0
 470 PRINT " DECYPHERED MESSAGE READS:-"
 480 PRINT 
 490 FOR W=1 TO LEN M$
 500 LET Z=Z+1
 510 IF Z>LEN K$ THEN LET Z=Z-LEN K$
 520 FOR X=1 TO 26
 530 IF A(CODE K$(Z)-37,X)=CODE M$(W)-37 THEN PRINT CHR$ (X+37);
 540 NEXT X
 550 NEXT W
 560 GOTO 140
 570 SAVE "1017%7"
 580 RUN 

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

People

No people associated with this content.

Scroll to Top