#!/usr/bin/env python3 """Extract 0x4b2980-0x4b2d8b from section_dump.txt and disassemble (x86-32). Dump line format: ' 4b2980 558bec83 c4d85356 578b5d08 d94510d8 U.....SVW.]..E..' address (hex, no 0x) then up to 4 groups of 4 bytes (8 hex chars each).""" import re, sys from capstone import Cs, CS_ARCH_X86, CS_MODE_32 DUMP = r"C:\git\bt411\reference\decomp\section_dump.txt" START = 0x4b2980 END = 0x4b2d8c # exclusive # named symbols for annotation SYMS = { 0x4b2d8c: "Gyroscope::ApplyDamageImpulse", 0x4b2de4: "Gyroscope::ApplyDamageTorque", 0x4b2e50: "Gyroscope::ApplyVerticalImpulse", 0x408440: "vec3_copy_A", 0x408e90: "vec3_copy_B", 0x4085ec: "vec3_add", 0x408644: "vec3_sub", 0x4086ac: "vec3_scale", 0x4092fc: "vec3_scale_B", 0x4086d0: "vec3_mul_cw", 0x408744: "vec3_x_mat34_rows", 0x40aadc: "mat34_identity", 0x40ab44: "mat34_from_placement", 0x409a00: "quat_from_rot", 0x4091f4: "eps_cmp_A", 0x4084fc: "eps_cmp_B", 0x409390: "lerp", 0x40b104: "mat34_affine_mult", } GYRO = { 0x1D8:"exageration",0x1DC:"eyePosition",0x1E8:"springConstant",0x1F4:"dampingConstant", 0x200:"eyeClampUpper",0x20C:"eyeClampLower",0x218:"posSpring",0x224:"negSpring", 0x230:"eyeForce",0x23C:"eyeVelocity",0x248:"eyeWork",0x254:"spare0", 0x258:"externalPitchPtr",0x25C:"workMatrix",0x28C:"placePos",0x298:"placeQuat", 0x2A8:"placeRot",0x2B4:"bodyOrientation",0x2C0:"rotationSpringConstant", 0x2CC:"rotationDampingConstant",0x2D8:"bodyClampUpper",0x2E4:"bodyClampLower", 0x2F0:"rotationPosSpring",0x2FC:"rotationNegSpring",0x308:"bodyForce", 0x314:"bodyVelocity",0x320:"bodyWork",0x32C:"damageMultiplier",0x340:"damageResponse", 0x3A8:"swayBias",0x3BC:"swayAngle",0x3C8:"eyeJointNode",0x3CC:"mechJointNode", } def gyro_annot(off): best = None for k,v in GYRO.items(): if k <= off: if best is None or k > best[0]: best = (k,v) if best and off - best[0] < 0x50: d = off - best[0] return f"{best[1]}" + (f"+0x{d:x}" if d else "") return None mem = {} pat = re.compile(r'^\s*([0-9a-f]{6,8})\s((?:[0-9a-f]{2,8}\s?)+)') with open(DUMP) as f: for line in f: m = pat.match(line) if not m: continue addr = int(m.group(1), 16) if addr + 16 < START or addr > END: continue hexpart = m.group(2).split() b = bytes.fromhex(''.join(hexpart)) for i, byte in enumerate(b): mem[addr+i] = byte code = bytes(mem.get(a, 0x90) for a in range(START, END)) missing = [a for a in range(START, END) if a not in mem] if missing: print(f"WARNING: {len(missing)} missing bytes, first at {missing[0]:#x}", file=sys.stderr) md = Cs(CS_ARCH_X86, CS_MODE_32) md.detail = True # jump table at 0x4b2b10 (5 dwords) -- disassemble around it segs = [(START, 0x4b2b10), (0x4b2b24, END)] insns = [] for s,e in segs: insns.extend(md.disasm(bytes(mem[a] for a in range(s,e)), s)) if e == 0x4b2b10: import struct for i in range(5): d = struct.unpack('