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>
This commit is contained in:
+22
@@ -15,3 +15,25 @@ __pycache__/
|
||||
|
||||
# 4.10 source reconstruction build outputs (rebuild: bash restoration/source410/build410.sh all)
|
||||
/restoration/build410/
|
||||
|
||||
# firmware-decomp build/run artifacts
|
||||
# emu860c.pyd: rebuild via the gcc line in emu860c/emu860c.c's header
|
||||
# *.log/*.pkl/*.png: renderer run outputs + caches (regenerated by the scripts)
|
||||
/emulator/firmware-decomp/emu860c/*.pyd
|
||||
/emulator/firmware-decomp/emu860c/*.log
|
||||
/emulator/firmware-decomp/emu860c/*.pkl
|
||||
/emulator/firmware-decomp/emu860c/*.png
|
||||
/emulator/firmware-decomp/igc_stream.bin
|
||||
|
||||
# editor / build junk
|
||||
/restoration/.obj.obj
|
||||
/.finf/
|
||||
|
||||
# game runtime state written by running the pod (logs, egg backups)
|
||||
/ALPHA_1/REL410/BT/LOG
|
||||
/ALPHA_1/REL410/BT/NN.LOG
|
||||
/ALPHA_1/REL410/BT/RUN.LOG
|
||||
/ALPHA_1/REL410/RP/NN.LOG
|
||||
/ALPHA_1/VWETEST/VGLTEST/REPORT/TEST.LOG
|
||||
/ALPHA_1/WEAPONLO.TXT
|
||||
/ALPHA_1/REL410/BT/TESTARN.EGG.pre_pilot
|
||||
|
||||
@@ -0,0 +1,62 @@
|
||||
"""Find where the production build stores texels: run the battle wire to the
|
||||
first sizable set_texmap_texels + its 0x1a bulk run, watching ALL DRAM writes
|
||||
during those commands -> the texel destination + layout + format."""
|
||||
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:]))
|
||||
# find first set_texmap_texels with header n_texels>0 (mode field) then following 0x1a runs
|
||||
def w32(p,o): return struct.unpack_from('<I',p,o)[0]
|
||||
tex_idx=None
|
||||
for i,(a,p) in enumerate(recs):
|
||||
if ANAME.get(a)=='set_texmap_texels' and len(p)>=20:
|
||||
h=[w32(p,4*k) for k in range(5)]
|
||||
# header: remote, n_texels, u, v, mode
|
||||
if h[1]>16 and h[2]*h[3]==h[1]:
|
||||
tex_idx=i; hdr=h; break
|
||||
print("first real texmap @cmd %d: remote=%#x n=%d u=%d v=%d mode=%d"%((tex_idx,)+tuple(hdr)))
|
||||
r=boot(fw='vrend410', queue=recs); shim=CpuShim()
|
||||
RECV=emu_main.MAPS['vrend410']['receive']
|
||||
# advance to just before tex_idx
|
||||
while r.qi < tex_idx:
|
||||
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)
|
||||
# now watch writes across tex_idx and the next ~10 commands (the 0x1a bulk)
|
||||
emu860c.watch_add(0x08000000, 0x0c000000)
|
||||
emu860c.watch_drain()
|
||||
stop_qi=tex_idx+12
|
||||
while r.qi < stop_qi:
|
||||
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]
|
||||
pages=collections.Counter(a>>12 for a in addrs)
|
||||
print("write pages during texmap upload (top 12):")
|
||||
for pg,n in pages.most_common(12):
|
||||
print(" %#x000 : %d"%(pg,n))
|
||||
# dump a sample of the biggest page's writes to see texel format
|
||||
top=pages.most_common(1)[0][0]<<12
|
||||
sample=[(addrs[k], vals[2*k+1]) for k in range(len(addrs)) if (addrs[k]>>12)==(top>>12)][:8]
|
||||
print("sample writes @%#x:"%top)
|
||||
for a,v in sample: print(" %#010x <- %08x"%(a,v))
|
||||
@@ -0,0 +1,55 @@
|
||||
"""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))
|
||||
@@ -0,0 +1,53 @@
|
||||
"""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))
|
||||
Binary file not shown.
Reference in New Issue
Block a user