68 lines
2.1 KiB
Python
68 lines
2.1 KiB
Python
#!/usr/bin/env python3
|
|
# injectDriver.py - write a 4096-byte $E000 opponent-module image into a copy of the Modem Wars disk.
|
|
#
|
|
# python3 injectDriver.py <module.bin> <in.d64> <out.d64>
|
|
#
|
|
# The module occupies track 18 sector 7 ($E000-$E0FF, stored in the clear because the loader never
|
|
# encrypts track 18) followed by track 34 sectors 1-15 ($E100-$EFFF, stored with the EA sector cipher).
|
|
import sys, os
|
|
|
|
SECTORS_PER_TRACK = [21]*17 + [19]*7 + [18]*6 + [17]*5 # tracks 1..35
|
|
|
|
|
|
def trackOffset(track):
|
|
return sum(SECTORS_PER_TRACK[:track-1]) * 256
|
|
|
|
|
|
def sectorOffset(track, sector):
|
|
return trackOffset(track) + sector * 256
|
|
|
|
|
|
def encryptSector(track, sector, plain):
|
|
"""The cipher the drive code applies at $0531; track 18 is stored in the clear."""
|
|
if track == 18:
|
|
return bytes(plain)
|
|
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
|
|
newCarry = (a >> 7) & 1
|
|
a = ((a << 1) | carry) & 0xFF
|
|
carry = newCarry
|
|
key = a
|
|
out[y] = plain[y] ^ key
|
|
return bytes(out)
|
|
|
|
|
|
# where each page of the module lives on the disk
|
|
def placement():
|
|
places = [(18, 7)] # $E000-$E0FF
|
|
places += [(34, s) for s in range(1, 16)] # $E100-$EFFF
|
|
return places
|
|
|
|
|
|
def main():
|
|
modulePath, inPath, outPath = sys.argv[1], sys.argv[2], sys.argv[3]
|
|
module = open(modulePath, "rb").read()
|
|
if len(module) != 4096:
|
|
raise SystemExit(f"module must be exactly 4096 bytes, got {len(module)}")
|
|
image = bytearray(open(inPath, "rb").read())
|
|
if len(image) < 174848:
|
|
raise SystemExit("not a 35-track .d64")
|
|
for i, (track, sector) in enumerate(placement()):
|
|
plain = module[i*256:(i+1)*256]
|
|
off = sectorOffset(track, sector)
|
|
image[off:off+256] = encryptSector(track, sector, plain)
|
|
open(outPath, "wb").write(image)
|
|
print(f"wrote {outPath}: module installed in track 18 sector 7 and track 34 sectors 1-15")
|
|
|
|
|
|
if __name__ == "__main__":
|
|
main()
|