- vrend410.mng: the production firmware, a HARD dependency of the committed
live pipeline (emu_main.py MAPS['vrend410'].fw loads it) -- the repo couldn't
run the live renderer without it.
- txdn_probe.py / texstore_trace.py / texel_trace.py: standalone reverse-
engineering probes (texture-source/DRAM-write/texel tracing) documenting the
texid-binding and texel-format investigations.
- .gitignore: exclude the firmware-decomp run artifacts (emu860c.pyd rebuildable
from source, *.log/*.pkl/*.png renderer outputs + caches), editor junk, and
the game runtime state/logs written by running the pod.
Left untouched deliberately: the parallel Mech session's in-progress
restoration/source410/BT/{EMITTER,BTPLAYER}.CPP edits (theirs to commit) and
the tracked game runtime state (LAST.EGG/CTMIX.CFG etc. -- transient).
Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
56 lines
2.3 KiB
Python
56 lines
2.3 KiB
Python
"""Where does the production build store 0x1a texels? Watch DRAM writes during
|
|
one texture's header+bulk upload -> the storage base per handle."""
|
|
import sys, os, struct, collections
|
|
HERE=os.path.dirname(os.path.abspath(__file__))
|
|
sys.path.insert(0,HERE); sys.path.insert(0,os.path.dirname(HERE))
|
|
sys.path.insert(0,r'C:\VWE\TeslaRel410\dpl3-revive\patha')
|
|
import emu860, emu_main, emu860c
|
|
from driver import boot, CpuShim
|
|
from vrboard import A
|
|
ANAME={int(a):a.name for a in A}
|
|
emu860.Mem.log=lambda self,*a,**k:None
|
|
data=open(r'C:/VWE/TeslaRel410/emulator/render-bridge/captures/netdeath-20260708.fifodump','rb').read()
|
|
recs=[]; off=0
|
|
while True:
|
|
i=data.find(b'VPXM',off)
|
|
if i<0: break
|
|
ln=struct.unpack_from('<I',data,i+4)[0]; body=data[i+8:i+8+ln]; off=i+8+ln
|
|
if len(body)>=4:
|
|
a=struct.unpack_from('<I',body,0)[0]
|
|
if a<0x100: recs.append((a,body[4:]))
|
|
# first 0x1a header (cmd 55, handle 0xc)
|
|
tex_start=None
|
|
for i,(a,p) in enumerate(recs):
|
|
if a==0x1a and len(p)==32:
|
|
tex_start=i; hdr=[struct.unpack_from('<I',p,4*k)[0] for k in range(8)]; break
|
|
print("texture upload @cmd %d handle=%#x u=%d v=%d"%(tex_start,hdr[0],hdr[2],hdr[3]))
|
|
r=boot(fw='vrend410', queue=recs); shim=CpuShim()
|
|
while r.qi < tex_start:
|
|
reason,_=emu860c.run(500_000_000)
|
|
if reason==3: continue
|
|
pc=emu860c.getstate()['pc']; h=r.hooks.get(pc)
|
|
if h is None: break
|
|
if h: h(shim)
|
|
emu860c.watch_add(0x08000000,0x0c000000); emu860c.watch_drain()
|
|
# run through the whole texture (header + 64 rows)
|
|
stop=tex_start+66
|
|
while r.qi < stop:
|
|
reason,_=emu860c.run(200_000_000)
|
|
if reason==3: continue
|
|
pc=emu860c.getstate()['pc']; h=r.hooks.get(pc)
|
|
if h is None: break
|
|
if h: h(shim)
|
|
raw=emu860c.watch_drain()
|
|
vals=struct.unpack('<%dI'%(len(raw)//4),raw)
|
|
addrs=vals[0::2]; wvals=vals[1::2]
|
|
pages=collections.Counter(a>>12 for a in addrs)
|
|
print("write pages during upload:")
|
|
for pg,n in pages.most_common(8):
|
|
lo=min(a for a in addrs if a>>12==pg); hi=max(a for a in addrs if a>>12==pg)
|
|
print(" %#x000 : %d writes span %#x..%#x"%(pg,n,lo,hi))
|
|
# find contiguous run matching texel pattern (0x00BBGGRR grayscale)
|
|
top=pages.most_common(1)[0][0]
|
|
run=[(addrs[k],wvals[k]) for k in range(len(addrs)) if addrs[k]>>12==top][:6]
|
|
print("sample @page %#x000:"%top)
|
|
for a,v in run: print(" %#010x <- %08x"%(a,v))
|