Files
TeslaRel410/emulator/firmware-decomp/emu860c/txdn_probe.py
T
CydandClaude Opus 4.8 a89d08e1c9 Commit the vrend410 firmware asset + RE tooling; gitignore run artifacts
- 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>
2026-07-20 11:43:46 -05:00

54 lines
2.1 KiB
Python

"""Capture the full per-tile DMA stream (incl TXDN, opcode 3) for one battle
draw -> the texture source addresses, to key the texid->texture binding."""
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:]))
TARGET=6234
r=boot(fw='vrend410', queue=recs); shim=CpuShim()
RECV=emu_main.MAPS['vrend410']['receive']
while r.qi < TARGET:
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 pc==RECV and r.qi>=TARGET-1 and ANAME.get(r.queue[r.qi][0])=='draw_scene':
emu860c.watch_add(0x08020000,0x08160000); emu860c.watch_drain()
h(shim)
while True:
reason,_=emu860c.run(500_000_000)
if reason==3: continue
if emu860c.getstate()['pc']==RECV: break
hh=r.hooks.get(emu860c.getstate()['pc'])
if hh: hh(shim)
else: break
break
if h: h(shim)
raw=emu860c.watch_drain()
vals=struct.unpack('<%dI'%(len(raw)//4),raw)
# DMA pairs {addr, opcode}; opcodes: 1/9 SEND, 2 TILE, 3 TXDN, 0 GOTO, 6 FLUSH, f STOP
opnames={0:'GOTO',1:'SEND',2:'TILE',3:'TXDN',6:'FLUSH',8:'WAIT',9:'SENDE',0xf:'STOP'}
txdn=collections.Counter(); tiles=[]
for i in range(0,len(vals)-1,2):
a,op=vals[i],vals[i+1]; c=(op>>28)&0xf
if c==3: txdn[a]+=1
elif c==2: tiles.append(a)
print("distinct TXDN source addresses: %d"%len(txdn))
for a,n in txdn.most_common(12):
print(" TXDN src %#010x : %d tiles"%(a,n))
print("tiles: %d"%len(tiles))