58 lines
2.6 KiB
Python
58 lines
2.6 KiB
Python
#!/usr/bin/env python3
|
|
# buildImage.py - replay the boot loader ($C145) on the decrypted sectors to produce the exact
|
|
# 64K memory image that exists when control reaches the game entry at $0800.
|
|
import json
|
|
SPT = [21]*17 + [19]*7 + [18]*6 + [17]*5
|
|
|
|
def sec(t, s):
|
|
return open(f"decrypted/t{t:02d}s{s:02d}.bin", "rb").read()
|
|
|
|
mem = bytearray(65536)
|
|
origin = [None]*256 # per page provenance
|
|
loadPrg = open("files/load.prg", "rb").read()
|
|
lo, hi = loadPrg[0], loadPrg[1]
|
|
body = loadPrg[2:]
|
|
mem[0x9800:0x9800+len(body)] = body
|
|
for p in range(0x98, 0xC4):
|
|
origin[p] = f"load.prg@{p:02X}00"
|
|
|
|
def loadRun(dest, track, firstSector, count, note):
|
|
for i in range(count):
|
|
s = firstSector + i
|
|
mem[dest:dest+0x100] = sec(track, s)
|
|
origin[dest >> 8] = f"T{track:02d}S{s:02d}"
|
|
dest += 0x100
|
|
|
|
# $C23F: colour RAM <- $9800-$9BFF ; $8C00-$8FFF <- $9C00-$9FFF
|
|
colorRam = bytes(mem[0x9800:0x9C00])
|
|
mem[0x8C00:0x9000] = mem[0x9C00:0xA000]
|
|
for p in range(0x8C, 0x90): origin[p] = f"copy of load.prg@{p+0x10:02X}00"
|
|
|
|
# main sequence ($C190..)
|
|
for t in range(22, 28):
|
|
loadRun(0x0800 + (t-22)*18*0x100, t, 0, 18, "main")
|
|
mem[0x0400:0x0800] = mem[0x6F00:0x7300] # $C1B3 copy loop
|
|
for p in range(4, 8): origin[p] = f"copy of {origin[p+0x6B]} (via $6F00)"
|
|
loadRun(0x6F00, 33, 0, 17, "")
|
|
loadRun(0x8000, 32, 8, 8, "")
|
|
loadRun(0x9300, 28, 0, 13, "")
|
|
loadRun(0xFA00, 29, 11, 5, "")
|
|
# $C1FE: move 16 pages from $xx1A -> $xx1A+$1B8, top page first ($FD1A..$FE19 -> $FED2..$FFD1)
|
|
for i in range(16):
|
|
srcHi = 0xFD - i
|
|
dstHi = 0xFE - i
|
|
for y in range(256):
|
|
mem[(dstHi << 8) + ((0xD2 + y) & 0xFF) + (0x100 if 0xD2 + y > 0xFF else 0)] = mem[(srcHi << 8) + ((0x1A + y) & 0xFF) + (0x100 if 0x1A + y > 0xFF else 0)]
|
|
for p in range(0xFB, 0x100): origin[p] = "T29S11-15 moved up $1B8 (garbage below $FBB8)"
|
|
open("bootImage.bin", "wb").write(mem)
|
|
open("bootImage_colorRam.bin", "wb").write(colorRam)
|
|
json.dump({f"{p:02X}00": o for p, o in enumerate(origin) if o}, open("bootImage_origin.json", "w"), indent=1)
|
|
|
|
# verify against VICE
|
|
ram = open("vice/ram_at_0800.bin", "rb").read()
|
|
diffs = [(a, mem[a], ram[a]) for a in range(0x0400, 0xA000) if mem[a] != ram[a]]
|
|
print("diffs $0400-$9FFF vs VICE:", [(f"${a:04X}", f"{m:02X}", f"{r:02X}") for a, m, r in diffs])
|
|
diffs = [(a, mem[a], ram[a]) for a in range(0xA000, 0xC400) if mem[a] != ram[a]]
|
|
print("diffs $A000-$C3FF:", [(f"${a:04X}", f"{m:02X}", f"{r:02X}") for a, m, r in diffs])
|
|
diffs = [(a, mem[a], ram[a]) for a in range(0xFBB8, 0xFFD2) if mem[a] != ram[a]]
|
|
print("diffs $FBB8-$FFD1:", [(f"${a:04X}", f"{m:02X}", f"{r:02X}") for a, m, r in diffs][:10])
|