"""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 <disp32> C3  (movzx eax,byte [rcx+d])
or 8A 41 <disp8> 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))
