"""The gate accessors are one-line getters Ghidra never turned into functions, so read their bytes and decode by hand. Expected shape for a bool getter: 0F B6 81 C3 (movzx eax,byte [rcx+d]) or 8A 41 C3 (mov al,[rcx+d]). The disp is the field offset inside FutDataManagerImpl, which is what identifies which flag each IS_* key publishes. CONTROL: +0x280 IS_STORE_ENABLED, whose screen is live-proven working while the server sends an empty configs array. Its offset anchors the mapping and its default is known-good by observation. """ TARGETS = [(0x270, "IS_TRADING_ENABLED", 0x18011C670), (0x280, "IS_STORE_ENABLED (CONTROL)", 0x18011C600), (0x2B0, "IS_FRIENDLY_SEASON_ENABLED", 0x18011C500), (0x2B8, "IS_TOURNAMENT_QUIT_ENABLED", 0x18011C660), (0x2C0, "IS_PROCESSING_STATE_ENABLED", 0x18011C5B0), (0x2C8, "IS_DRAFT_MODE_ENABLED", 0x18011C4B0), (0x2D8, "IS_STORY_MODE_REWARD_ENABLED", 0x18011C640), (0x2F0, "IS_RETURNING_USER_REWARDS", 0x18011C5C0)] def decode(b): """Return (field_offset, note) for the simple getter forms.""" if b[0:3] == b"\x0f\xb6\x81": return int.from_bytes(b[3:7], "little"), "movzx eax,byte[rcx+d32]" if b[0:3] == b"\x0f\xb6\x41": return b[3], "movzx eax,byte[rcx+d8]" if b[0:2] == b"\x8b\x81": return int.from_bytes(b[2:6], "little"), "mov eax,[rcx+d32]" if b[0:2] == b"\x8b\x41": return b[2], "mov eax,[rcx+d8]" if b[0:2] == b"\x8a\x41": return b[2], "mov al,[rcx+d8]" if b[0:2] == b"\x8a\x81": return int.from_bytes(b[2:6], "little"), "mov al,[rcx+d32]" return None, "UNRECOGNISED" print("%-6s %-32s %-12s %-10s %s" % ("SLOT", "KEY", "ADDR", "FIELD@", "FORM / BYTES")) print("-" * 110) rows = [] for slot, name, va in TARGETS: b = read_bytes(va, 12) off, form = decode(b) rows.append((slot, name, va, off)) print("+%#05x %-32s %#-12x %-10s %s | %s" % (slot, name, va, hex(off) if off is not None else "?", form, b.hex())) # Field offset -> flag-table index, anchored on the struct base used by the parser. print("\nIf the flag struct starts at object+0x28, index = (offset-0x28)/4:") for slot, name, va, off in rows: if off is None: continue idx = (off - 0x28) / 4 print(" %-32s offset %#-6x -> field[%s]" % (name, off, idx if idx % 1 else int(idx))) print("\n=== 0x18011c600 (the one Ghidra did define) ===") print(dec(0x18011C600))