#!/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])
