"""Decompile the gate accessors themselves. The publisher calls virtuals on the object returned by the service locator: +0x270 IS_TRADING_ENABLED +0x280 IS_STORE_ENABLED (CONTROL: works today) +0x2b0 IS_FRIENDLY_SEASON_ENABLED +0x2b8 IS_TOURNAMENT_QUIT_ENABLED +0x2c0 IS_PROCESSING_STATE_ENABLED +0x2c8 IS_DRAFT_MODE_ENABLED +0x2d8 IS_STORY_MODE_REWARD_ENABLED +0x2f0 IS_RETURNING_USER_REWARDS_... FutDataManagerImpl's ctor installs three vtables (multiple inheritance): PTR_LAB_18021c2a0 at +0, PTR_FUN_18021cda8 at +8, PTR_LAB_18021cdb8 at +0x10. The locator hands back one of the sub-objects, so try all three and keep whichever resolves these slots to real functions. Reading the accessor settles what each gate actually reads, which the field-offset arithmetic can only guess at. """ SLOTS = {0x270: "IS_TRADING_ENABLED", 0x280: "IS_STORE_ENABLED (CONTROL)", 0x2B0: "IS_FRIENDLY_SEASON_ENABLED", 0x2B8: "IS_TOURNAMENT_QUIT_ENABLED", 0x2C0: "IS_PROCESSING_STATE_ENABLED", 0x2C8: "IS_DRAFT_MODE_ENABLED", 0x2D8: "IS_STORY_MODE_REWARD_ENABLED", 0x2F0: "IS_RETURNING_USER_REWARDS"} for vt in (0x18021C2A0, 0x18021CDA8, 0x18021CDB8): print("#" * 78) print("# vtable %#x" % vt) print("#" * 78) ok = 0 for off, name in sorted(SLOTS.items()): try: t = qword(vt + off) except Exception as e: print(" +%#05x %-34s " % (off, name)) continue f = fm.getFunctionAt(addr(t)) if 0x180000000 <= t < 0x181000000 else None print(" +%#05x %-34s -> %#x %s" % (off, name, t, f.getName() if f else "(not a function)")) if f: ok += 1 print(" resolved %d/%d" % (ok, len(SLOTS))) if ok >= len(SLOTS) - 1: print("\n -- accessor bodies --") for off, name in sorted(SLOTS.items()): t = qword(vt + off) if fm.getFunctionAt(addr(t)): print("\n === +%#05x %s ===" % (off, name)) print(dec(t)) print()