Two coupled fixes so the condenser valve gauge (ValveSetting -> coolantFlowScale @0x15C) reads its authentic value instead of garbage/zero. STEP 7 (gating dedup): heat.cpp carried STUB Condenser ctor/dtor/TestClass/ TestInstance/CreateStreamedSubsystem that ODR-duplicated the REAL bodies in heatfamily_reslice.cpp and WON under /FORCE (heat.obj links first) -> the real ctor (which sets valveState=1) was shadowed, leaving valveState=0xCDCDCDCD. #if 0'd the heat.cpp stubs so the reslice ctor (@4ae568, byte-verified: valveState=1, coolantFlowScale=0, massScale=refrigerationFactor, condenserNumber from name) is the sole definition. DefaultData/GetClassDerivations/ResetToInitialState (not duplicated) stay in heat.cpp. STEP 9 (the real writer): FinishConstruction() at the Mech ctor tail was a no-op template stub in place of FUN_0049f788 = RecomputeCondenserValves -> coolantFlowScale was never written (stayed 0). Reconstructed it (byte-verified vs part_012.c:9264): distribute coolant flow across the mech's condensers, coolantFlowScale_i = valveState_i / sum(valveState), with the condenserAlarm@0x1DC change pulse (2-if-flow<=old-else-1, then 0). Walks the populated subsystem roster filtering Condensers via IsDerivedFrom (behaviorally identical to the binary's @mech+0x7cc condenser chain, GUID 0x50e4fc). Wired as BTRecomputeCondenserValves(this) at the Mech ctor post-init pass (binary @9457). _DAT_0049f850 fallback confirmed 0.0f (PE read). Verified: [valve] the Blackhawk's 6 condensers each read flow=0.166667 (=1/6, total=6) for both player + spawned enemy, no every-mech crash; combat TARGET DESTROYED, un-regressed. Diagnostic BT_VALVE_LOG added. Co-Authored-By: Claude Opus 4.8 (1M context) <noreply@anthropic.com>
22 lines
783 B
Python
22 lines
783 B
Python
import struct,sys
|
|
va=int(sys.argv[1],16)
|
|
f=open('content/BTL4OPT.EXE','rb').read()
|
|
# PE header
|
|
pe=struct.unpack_from('<I',f,0x3c)[0]
|
|
assert f[pe:pe+4]==b'PE\0\0'
|
|
numsec=struct.unpack_from('<H',f,pe+6)[0]
|
|
optsz=struct.unpack_from('<H',f,pe+20)[0]
|
|
imgbase=struct.unpack_from('<I',f,pe+0x34)[0]
|
|
sectab=pe+24+optsz
|
|
for i in range(numsec):
|
|
off=sectab+i*40
|
|
name=f[off:off+8].rstrip(b'\0').decode(errors='replace')
|
|
vsz,vaddr,rsz,raddr=struct.unpack_from('<IIII',f,off+8)
|
|
if imgbase+vaddr <= va < imgbase+vaddr+max(vsz,rsz):
|
|
fo=raddr+(va-imgbase-vaddr)
|
|
raw=f[fo:fo+4]
|
|
print(f"VA {va:#x} sec={name} bytes={raw.hex()} float={struct.unpack('<f',raw)[0]} int={struct.unpack('<i',raw)[0]}")
|
|
break
|
|
else:
|
|
print("not found; imgbase",hex(imgbase))
|