"""DIMENSION 4 q5: map model vtable slots +0x2b0..+0x320 to their accessor displacements, so slot +0x2d0 (the offline-draft-specific gate in FUN_1800b2680) and slot +0x320 (cVar9) can be measured live. Model vtable static = 0x18021c2a0 (from ground truth / card doc). For each slot read the target function's first bytes; if it is the accessor stub 0f b6 81 c3 (movzx eax,byte [rcx+disp]; ret) decode disp. Control: slot +0x270 must decode to disp 0x1fd2e (IS_TRADING), slot +0x2c8 to 0x1fd3d (IS_DRAFT_MODE_ENABLED) -- both established in the card-subsystem doc. """ import traceback try: VT = 0x18021c2a0 names = {0x270:"IS_TRADING(+0x1fd2e)", 0x280:"IS_STORE", 0x2b0:"FRIENDLY_SEASON(+0x1fd3a)", 0x2b8:"TOURNAMENT_QUIT(+0x1fd3b)", 0x2c0:"PROCESSING(+0x1fd3c)", 0x2c8:"DRAFT_MODE(+0x1fd3d)", 0x2d0:"?offline-draft gate?", 0x2d8:"STORY_MODE_REWARD", 0x2e0:"packAnim(+0x1fd45)", 0x2f0:"RETURNING_USER", 0x320:"cVar9(FUN_1800b2680)"} for slot in range(0x2a0, 0x330, 8): tgt = qword(VT + slot) b = read_bytes(tgt, 8) disp = None if b[:3] == b"\x0f\xb6\x81": # movzx eax, byte [rcx+disp32] import struct disp = struct.unpack(" %#012x stub=%s disp=%s %s" % (slot, tgt, b.hex(), hex(disp) if disp is not None else "(not a byte-accessor)", note)) if disp is None: # decompile non-trivial accessors (offline draft gate / cVar9 may compute) if slot in (0x2d0, 0x320): print(" --- dec slot +%#x target ---" % slot) print(dec(tgt)) except Exception: traceback.print_exc() print("QUERY_DONE")