#!/usr/bin/env python3 # decryptDisk.py - undo the Electronic Arts sector cipher used by the Modem Wars 1541 loader # (drive code at $0531): every sector except track 18 is XORed with a rolling key. import os, sys, glob SECTORS_PER_TRACK = [21]*17 + [19]*7 + [18]*6 + [17]*5 def decryptSector(track, sector, data): if track == 18: return bytes(data) # lda track ; ora #$C0 ; asl a (carry = 1 since bit 7 is set) ; adc sector a = (track | 0xC0) << 1 carry = (a >> 8) & 1 a &= 0xFF a = a + sector + carry carry = (a >> 8) & 1 a &= 0xFF out = bytearray(256) key = 0 for y in range(256): if y != 0: a = y ^ key # tya ; eor key # rol a (carry from the previous rol / adc) newCarry = (a >> 7) & 1 a = ((a << 1) | carry) & 0xFF carry = newCarry key = a # sta key out[y] = data[y] ^ key return bytes(out) def main(): src = sys.argv[1] dst = sys.argv[2] os.makedirs(dst, exist_ok=True) img = bytearray() for track in range(1, 36): n = SECTORS_PER_TRACK[track-1] trackBytes = bytearray() for s in range(n): raw = open(f"{src}/t{track:02d}s{s:02d}.bin", "rb").read() dec = decryptSector(track, s, raw) open(f"{dst}/t{track:02d}s{s:02d}.bin", "wb").write(dec) trackBytes += dec open(f"{dst}/track{track:02d}.bin", "wb").write(trackBytes) img += trackBytes open(f"{dst}/decrypted.d64", "wb").write(img) print(f"wrote {len(img)} bytes") main()