"""D4 Q1e: many FutDataManagerImpl accessors are 8-byte leaf stubs that Ghidra never turned into functions, so dec() returned nothing for them in q_pack_reveal_4. Decode their bytes directly instead: `0f b6 81 c3` = movzx eax,byte ptr [rcx+disp32]. Goal: the full slot -> gate-byte map for vtable 0x18021c2a0, and specifically which slot (if any) returns byte 0x1fd45, the byte written from settings field [0x1d], which is the packOpeningAnimationEnabled arm. CONTROL: slot +0x2b0 must decode to 0x1fd3a and slot +0x2c8 to 0x1fd3d, because FUN_18006cc60 calls exactly those two slots to publish IS_FRIENDLY_SEASON_ENABLED and IS_DRAFT_MODE_ENABLED, and FUN_18011dc50 writes those two bytes from fields [0x16] and [0x17], the two documented worked examples. Then: xrefs to whichever stub returns 0x1fd45. """ import traceback, struct OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres/" BUF = [] def p(*a): s = " ".join(str(x) for x in a) print(s) BUF.append(s) def stub_offset(t): """decode a leaf accessor stub -> (kind, byte offset) or (None, raw hex).""" b = read_bytes(t, 24) h = b.hex() # movzx eax, byte ptr [rcx+disp32] ; ret if b[0:3] == b"\x0f\xb6\x81" and b[7:8] == b"\xc3": return ("movzx byte", struct.unpack(" %#x %-12s field_byte=%#x" % (off, t, kind, o)) found[off] = (t, kind, o) else: fn = fm.getFunctionAt(addr(t)) p(" +%#05x -> %#x NOT-A-STUB %s bytes=%s" % (off, t, fn.getName() if fn else "?", h[:32])) p("=== CONTROL CHECK ===") for slot, want, name in ((0x2B0, 0x1FD3A, "IS_FRIENDLY_SEASON_ENABLED"), (0x2C8, 0x1FD3D, "IS_DRAFT_MODE_ENABLED")): got = found.get(slot, (0, "?", -1))[2] p(" slot %#x expect %#x got %#x %s %s" % (slot, want, got, "PASS" if got == want else "FAIL", name)) p("=== slots returning the settings gate bytes 0x1fd2c..0x1fd48 ===") for off, (t, kind, o) in sorted(found.items()): if 0x1FD00 <= o <= 0x1FD70: p(" slot +%#05x stub %#x byte %#x" % (off, t, o)) p("=== who reads 0x1fd45 ? ===") hits = [(off, t) for off, (t, k, o) in found.items() if o == 0x1FD45] p(" stubs returning 0x1fd45: %s" % [(hex(a), hex(b)) for a, b in hits]) for off, t in hits: xs = xrefs_to(t) p(" xrefs to stub %#x : %d" % (t, len(xs))) for frm, typ, fn, ent in xs: p(" from %#x %s in %s @ %#x" % (frm, typ, fn, ent)) # also: xrefs to the vtable slot address itself (indirect call sites are in the # packed exe, so expect few/none) for off, t in hits: xs = xrefs_to(VT + off) p(" xrefs to vtable slot %#x : %d -> %s" % (VT + off, len(xs), xs[:10])) except Exception: traceback.print_exc() finally: with open(OUT + "d4_fdm_stubs.txt", "w") as f: f.write("\n".join(BUF)) print("WROTE d4_fdm_stubs.txt")