#!/usr/bin/env python3 """Neutralize the shipped-in debug crash macros in BTL4OPT.EXE. The Rel 4.10 BattleTech binary was built with the RIO serial driver's `DIE_ON_ERROR equ 1` diagnostic enabled (CODE/RP/MUNGA_L4/PCSPAK.ASM). Its `DISABLE_AND_DIE` macro deliberately faults ("crash loudly to the debugger") on any serial-transmit anomaly: push eax; push edx mov edx, 0FFFFFFFFh ; crash loudly mov eax, mov [edx], eax ; write to 0xFFFFFFFF -> Exception 0E On the real pod a clean cockpit harness never tripped these; through the DOSBox-X serial passthrough a RIO glitch (e.g. during a board reset) hits error 3 (PCSPAK.ASM:1630, "body char > 0x7F") and halts the whole game. The release build (`DIE_ON_ERROR equ 0`) compiles the macro to nothing and lets the normal recovery path (`and al,07Fh`) continue. This tool finds every DISABLE_AND_DIE site by its exact 14-byte signature and replaces it with NOPs -- exactly the release-build behavior -- writing a .orig backup first. Idempotent. Usage: patch_btl4opt.py """ import re import sys SIG = re.compile( rb'\x50\x52\xBA\xFF\xFF\xFF\xFF\xB8(.)\x00\x00\x00\x89\x02', re.DOTALL) def main(): if len(sys.argv) != 2: raise SystemExit(__doc__) path = sys.argv[1] data = bytearray(open(path, 'rb').read()) sites = list(SIG.finditer(bytes(data))) if not sites: print("no DISABLE_AND_DIE sites found (already patched?)") return import os bak = path + '.orig' if not os.path.exists(bak): open(bak, 'wb').write(data) print(f"backup written: {bak}") for m in sites: code = m.group(1)[0] va = 0x401000 + m.start() - 0xe00 # CODE VA 0x401000 @ file 0xe00 print(f" NOP VA 0x{va:06x} (error code {code})") data[m.start():m.end()] = b'\x90' * (m.end() - m.start()) open(path, 'wb').write(data) print(f"patched {len(sites)} sites") if __name__ == "__main__": main()