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>
43 lines
1.6 KiB
Python
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)
|