Files
BT411/scratchpad/scan_maptables.py
T
arcattackandClaude Fable 5 8ed6184d65 Combat: AUTHENTIC weapon groups -- streamed per-mech button bindings + the real fire chain (task #5)
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>
2026-07-11 13:06:29 -05:00

43 lines
1.6 KiB
Python

import struct
data = open(r'C:/git/bt411/content/BTL4OPT.EXE','rb').read()
pe = struct.unpack_from('<I', data, 0x3c)[0]
nsec = struct.unpack_from('<H', data, pe+6)[0]
opt = struct.unpack_from('<H', data, pe+20)[0]
secs = []
for i in range(nsec):
o = pe+24+opt+i*40
name = data[o:o+8].rstrip(b'\0').decode()
vsz, vaddr_, rsz, roff = struct.unpack_from('<4I', data, o+8)
secs.append((name, vaddr_+0x400000, vsz, roff, rsz))
def vaddr(o):
for name, va, vsz, roff, rsz in secs:
if roff <= o < roff+rsz: return o - roff + va
return None
n = len(data)
def valid_entry(i):
if i+24 > n: return False
k, ch, t, ridx, mask, mid = struct.unpack_from('<6I', data, i)
return (k in (0,1,3) and ch < 0x60 and t in (0,1)
and (ridx < 0x100 or ridx == 0xffffffff)
and mask != 0
and mid < 0x1000)
found = 0
i = 0
while i < n - 8:
cnt = struct.unpack_from('<I', data, i)[0]
if 3 <= cnt <= 80:
ok = all(valid_entry(i+4+j*24) for j in range(cnt))
# also require the NEXT dword after table to NOT be a valid entry (table boundary) - skip, just report
if ok:
print(f"--- table @VA 0x{vaddr(i):06x} count={cnt}")
for j in range(cnt):
o = i+4+j*24
k, ch, t, ridx, mask, mid = struct.unpack_from('<6I', data, o)
r = 'SELF' if ridx == 0xffffffff else f'{ridx}'
print(f" kind={k} chan=0x{ch:02x} typ={'evt' if t==1 else 'dir'} roster={r} mask=0x{mask:x} id/ofs=0x{mid:x}")
found += 1
i += 4 + cnt*24
continue
i += 4
print('tables:', found)