49 lines
1.6 KiB
Python
49 lines
1.6 KiB
Python
#!/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()
|