"""DIMENSION 2 batch 9: the pile enum, the discard request class, and the
duplicate-field reader.

HYPOTHESES
 H1 FUN_180142650 is the pile string->enum for atom 0x226 in the MoveCard
    verdict record. Its table names every destination a move can target, which
    is exactly the value 'send to transfer list' has to carry.
 H2 The .rdata block 0x180220470-0x180220780 holds both the FutDiscardCard
    request vtable and the response vtable; a slot on the request side is the
    completion handler that reads totalCredits.
 H3 DAT_1802def18's concrete class is installed by a caller of FUN_180039b40 /
    FUN_180039ba0; its vtable slot +0x18 is GetCardDuplicate, the only reader of
    the card field that duplicateItemIdList writes.

CONTROL: FutSquadSaveServerResponse -> 0x180171a60.
"""
import traceback, os

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres"

try:
    print("CONTROL FutSquadSaveServerResponse ->",
          [hex(a) for a, v, e in class_deser("FutSquadSaveServerResponse")])

    print("=" * 78)
    print("SECTION 1 -- pile enum FUN_180142650")
    s = dec(0x180142650)
    print(s)
    # try to find the table it walks
    for ln in s.splitlines():
        if "PTR_" in ln or "DAT_" in ln:
            print("   >>", ln.strip())

    print("=" * 78)
    print("SECTION 2 -- .rdata 0x180220470-0x180220790")
    for va in range(0x180220470, 0x180220790, 8):
        q = qword(va)
        note = ""
        if 0x1801E5000 <= q <= 0x180290000:
            t = rd_str(q, 60)
            if t and all(0x20 <= ord(c) < 0x7F for c in t):
                note = "STR %r" % t
        if not note and 0x180001000 <= q < 0x1801E5000:
            f = fm.getFunctionAt(addr(q))
            note = "FUNC %s" % (f.getName() if f else "(mid)")
        print("   %#x : %#018x  %s" % (va, q, note))

    print("=" * 78)
    print("SECTION 3 -- discard request/response class functions")
    for lbl, va in (("0x180127160", 0x180127160), ("0x180127630", 0x180127630),
                    ("0x180126f00 dtor", 0x180126F00)):
        print("---- %s ----" % lbl)
        print(dec(va))

    print("=" * 78)
    print("SECTION 4 -- who installs DAT_1802def18")
    for setter in (0x180039B40, 0x180039BA0):
        print("  setter %#x:" % setter)
        print(dec(setter))
        for r in xrefs_to(setter):
            print("     caller %#x %s %s %#x" % (r[0], r[1], r[2], r[3]))
        for e in sorted({r[3] for r in xrefs_to(setter) if r[3]}):
            s = dec(e)
            print("  ---- caller %#x len=%d ----" % (e, len(s)))
            print(s if len(s) < 5000 else s[:5000] + "\n...TRUNCATED len=%d" % len(s))

except Exception:
    traceback.print_exc()
