mirror of
https://github.com/jkdansereau/goldeneye-pc-port.git
synced 2026-10-23 15:52:42 +02:00
- D48 finding in PCPortResearch.md §F: d43_convert.py does not emit bytes (layout+remap validation only); Plan B = Python emit pass -> data/pcmodels-<region>/ RZ sidecars served via port-layer hw_address/rom_size table patch (no C converter); Plan A kept as fallback with corrected staging guard (D_N64+D_PC<=avail) - Moved all 23 d43_*.py investigation scripts from gitignored build-pc/ to tracked tools_pc/ (spec is now versioned); d43_cover.py path ref updated; converter re-run from new location: ALL CLEAN - HANDOFF.md rewritten as two-session prompt: Session A = independent review of Plan B (8 claims, each with falsification criterion -> finding D49), Session B = execute (emit pass + round-trip validator, romdata plumbing, one-line hook, pixel-assert soak); verified-facts converter spec preserved - AGENTS.md phase status updated to D48 re-plan
110 lines
4.2 KiB
Python
110 lines
4.2 KiB
Python
#!/usr/bin/env python3
|
|
"""Seg-5 G_VTX analysis WITH LOD/SWITCH rewiring (as in d43_gdlorder.py).
|
|
Question: does every seg-5 G_VTX offset point INSIDE a vertex array of the same file?
|
|
(vo + d where d % 16 == 0 and d < 16*nv) — i.e. is it (array_base_file_offset + displacement)?"""
|
|
import csv, struct, zlib, os, re
|
|
from collections import Counter
|
|
|
|
rom = open('data/ge007.ntsc-final.z64','rb').read()
|
|
rows = list(csv.reader(open(r"scripts/filelist.u.csv")))
|
|
hdrfiles = set()
|
|
for root, dirs, files in os.walk("assets"):
|
|
for fn in files:
|
|
if fn.lower().endswith("modelfileheader.inc.c"):
|
|
hdrfiles.add(os.path.join(root, fn))
|
|
nsnt = {}
|
|
for f in sorted(hdrfiles):
|
|
for line in open(f):
|
|
m = re.search(r"MODELFILEHEADER\((.*)\)\s*;?\s*$", line)
|
|
if not m: continue
|
|
a = [x.strip() for x in m.group(1).split(",")]
|
|
if len(a) < 9: continue
|
|
try: nsnt[a[0]] = (int(a[4], 0), int(a[8], 0))
|
|
except ValueError: pass
|
|
|
|
def be32(b,o): return struct.unpack_from(">I",b,o)[0] & 0xFFFFFF
|
|
def be32r(b,o): return struct.unpack_from(">I",b,o)[0]
|
|
|
|
total_seg5 = 0; inside = 0; outside = []
|
|
files_with = set()
|
|
vtx_regions = Counter() # (d mod 16) histogram of displacement
|
|
for r in rows:
|
|
if len(r) < 3 or not r[2]: continue
|
|
base = r[2].rsplit("/",1)[-1]
|
|
if base.endswith(".bin"): base = base[:-4]
|
|
if not (base[0] in "CGP" and base.endswith("Z") and "_stan" not in base): continue
|
|
key=None
|
|
for cand in (base, base[1:], base[:-1], base[1:-1]):
|
|
if cand in nsnt: key=cand; break
|
|
if not key: continue
|
|
NS,NT = nsnt[key]
|
|
try: addr,size=int(r[0]),int(r[1])
|
|
except ValueError: continue
|
|
try: out=zlib.decompress(rom[addr:addr+size][2:],-15)
|
|
except Exception: continue
|
|
D=len(out); R0=4*NS+12*NT
|
|
|
|
# walk with LOD/SWITCH rewiring; collect vertex regions (vo, nv) and GDL offsets per record
|
|
seen=set(); stack=[R0]; regions=[]; gdls=[]
|
|
while stack:
|
|
o=stack.pop()
|
|
if o in seen or o>=D: continue
|
|
seen.add(o)
|
|
op=struct.unpack_from(">H",out,o)[0]&0xff
|
|
data=be32(out,o+4)
|
|
child = be32(out,o+0x14); nxt = be32(out,o+0xC)
|
|
if op==8: # LOD: Child := Affects (data+8)
|
|
a = be32(out,data+8)
|
|
if a: stack.append(a)
|
|
elif op==18: # SWITCH: Child := Controls (data+0)
|
|
c = be32(out,data)
|
|
if c: stack.append(c)
|
|
else:
|
|
if child: stack.append(child)
|
|
if nxt: stack.append(nxt)
|
|
if op==4:
|
|
nv=struct.unpack_from(">H",out,data+0x10)[0]
|
|
vo=be32(out,data+0xC)
|
|
regions.append((vo,nv))
|
|
gdls += [x for x in (be32(out,data), be32(out,data+4)) if x]
|
|
elif op==24:
|
|
nv=struct.unpack_from(">h",out,data+0xC)[0]
|
|
cv=struct.unpack_from(">h",out,data+0xE)[0]
|
|
vo=be32(out,data+8); cvo=be32(out,data+0x10)
|
|
regions.append((vo,nv))
|
|
if cv: regions.append((cvo,cv))
|
|
gdls += [x for x in (be32(out,data), be32(out,data+4)) if x]
|
|
elif op==22:
|
|
nv=struct.unpack_from(">i",out,data)[0]
|
|
vo=be32(out,data+4)
|
|
regions.append((vo,nv))
|
|
p=be32(out,data+8)
|
|
if p: gdls.append(p)
|
|
|
|
gs = sorted(set(gdls))
|
|
for i,g in enumerate(gs):
|
|
end = gs[i+1] if i+1 < len(gs) else D
|
|
o=g
|
|
while o+8<=end:
|
|
w0=be32r(out,o); c=w0>>24
|
|
if c==0x04:
|
|
w1=be32r(out,o+4)
|
|
if (w1>>24)&0xf == 5:
|
|
off = w1 & 0xFFFFFF
|
|
total_seg5 += 1; files_with.add(base)
|
|
hit=False
|
|
for vo,nv in regions:
|
|
d = off - vo
|
|
if 0 <= d < 16*nv and nv>0:
|
|
vtx_regions[d & 0xf]+=1
|
|
hit=True; break
|
|
if hit: inside+=1
|
|
elif len(outside)<12: outside.append((base, hex(off), [(hex(a),b) for a,b in regions[:8]]))
|
|
o+=8
|
|
|
|
print("seg5 G_VTX total:", total_seg5, "files:", len(files_with))
|
|
print("pointing inside a vertex array (vo+d, d<16nv):", inside)
|
|
print("displacement mod 16 histogram:", dict(vtx_regions))
|
|
print("outside samples:")
|
|
for s in outside: print(" ", s)
|