The recovered system: fire channels = LBE4ControlsManager buttonGroups (0x40/0x45/0x46/0x47); default groups = the per-mech type-6 controls-map resource in BTL4.RES, installed by the T0 CreateStreamedMappings the port already called -- it needed only the TriggerState attribute (id 0x13 PINNED to the binary value; fireImpulse@0x31C is the binary's TriggerState) and an input feed. Keyboard/harness now push press/release edges into the button groups; the gBT*Trigger bypasses, per-type keyboard split and 1,0 pulse hack are retired -- weapons sharing a button fire TOGETHER (madcat Trigger = 4 weapons). Myomers @4b9550/@4b95b8 misattribution corrected (they are MechWeapon ConfigureMappables/ChooseButton). Verified 2-node: kill through the authentic chain (12 hits vs ~36 pre-groups). Config-mode session (regrouping UI) = the remaining stage, KB-scoped. Co-Authored-By: Claude Fable 5 <noreply@anthropic.com>
53 lines
2.0 KiB
Python
53 lines
2.0 KiB
Python
import struct,glob
|
|
|
|
def walk(d, p, end, depth, out):
|
|
while p+3<=end:
|
|
tw=struct.unpack_from("<H",d,p)[0]; p+=2
|
|
cid=tw&0x2fff
|
|
lw=4 if(tw&0x8000)else(2 if(tw&0x4000)else 1)
|
|
if p+lw>end:return
|
|
ln=d[p] if lw==1 else (struct.unpack_from("<H",d,p)[0] if lw==2 else struct.unpack_from("<I",d,p)[0])
|
|
p+=lw
|
|
if p+ln>end:return
|
|
out.append((depth,cid,p,ln,d[p:p+ln]))
|
|
if cid in (0x03,0x40,0x41,0x42,0x46,0x20,0x30,0x31,0x10,0x70,0x48,0x21):
|
|
walk(d,p,p+ln,depth+1,out)
|
|
p+=ln
|
|
if cid==0x0005:break
|
|
|
|
def dump_ramp_named(fn, want="softer"):
|
|
d=open(fn,"rb").read()
|
|
out=[]; walk(d,8,len(d),0,out)
|
|
# find RAMP container (0x30/0x31) whose NAME==want
|
|
results=[]
|
|
i=0
|
|
cur_name=None
|
|
for idx,(depth,cid,p,ln,body) in enumerate(out):
|
|
if cid in (0x30,0x31):
|
|
# look ahead for child NAME + endpoint colors
|
|
nm=None; cols=[]
|
|
for d2,c2,p2,l2,b2 in out[idx+1:]:
|
|
if d2<=depth: break
|
|
if c2==0x2008: nm=b2.split(bytes([0]))[0].decode(errors='replace')
|
|
elif c2 in (0x23,0x24,0x25,0x26,0x32,0x33) and l2>=12:
|
|
cols.append((hex(c2),struct.unpack_from("<3f",b2,0)))
|
|
elif l2>=12 and l2%12==0 and c2 not in (0x2008,):
|
|
# generic color-ish payload
|
|
pass
|
|
if nm and want in nm:
|
|
results.append((nm,cols,p,ln,body[:64].hex()))
|
|
return results
|
|
|
|
print("Searching for 'softer' ramp definition across skin BMFs...")
|
|
for fn in ["content/VIDEO/MAT/AVASKIN.BMF","content/VIDEO/MAT/BLXSKIN.BMF",
|
|
"content/VIDEO/MAT/ARENA/BTVEH.BMF","content/VIDEO/MAT/AVAFX.BMF"]:
|
|
try:
|
|
r=dump_ramp_named(fn)
|
|
except Exception as e:
|
|
print(fn,"ERR",e); continue
|
|
print(f"\n{fn}: {len(r)} 'softer' ramp defs")
|
|
for nm,cols,p,ln,hx in r:
|
|
print(f" RAMP {nm!r} @off{p} len{ln}")
|
|
for c in cols: print(" ",c)
|
|
print(" rawhead:",hx)
|