"""DIMENSION 2 batch 10: the discard request URL, and every caller of the FUT
client-model singleton (to locate the reader of the duplicate field and of
totalCredits).

HYPOTHESES
 H1 FUN_180127530 is the DiscardCard ServerCall's request builder; the literal
    "/%llu" at 0x180220638 is appended to ut/delete/%s/item, so quick sell is
    DELETE ut/delete/game/fifa17/item/<itemId>.
 H2 Every consumer of the pack-reveal collection and of the card's duplicate
    field goes through FUN_18011a830(). Enumerating its callers bounds the set
    of readers; the ones that call slot 0x160 are the reveal-screen consumers.

CONTROL: FutSquadListServerResponse -> 0x180172140.
"""
import traceback, os, re

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

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

    print("=" * 78)
    print("SECTION 1 -- discard request builders")
    for lbl, va in (("FUN_180127530 (DiscardCard req)", 0x180127530),
                    ("FUN_180127290", 0x180127290),
                    ("FUN_1801277c0 (ByRes req)", 0x1801277C0),
                    ("FUN_180163750", 0x180163750),
                    ("FUN_1801631e0 (shared)", 0x1801631E0)):
        s = dec(va)
        print("---- %s len=%d ----" % (lbl, len(s)))
        print(s)

    print("=" * 78)
    print("SECTION 2 -- xrefs to the '/%llu' literal 0x180220638")
    for r in xrefs_to(0x180220638):
        print("   %#x %s %s %#x" % (r[0], r[1], r[2], r[3]))

    print("=" * 78)
    print("SECTION 3 -- all callers of the model singleton FUN_18011a830, with the "
          "vtable slot each one invokes")
    calls = {}
    for r in xrefs_to(0x18011A830):
        ent = r[3]
        if not ent:
            continue
        calls.setdefault(ent, 0)
        calls[ent] += 1
    print("  %d distinct callers" % len(calls))
    slotpat = re.compile(r"\*plVar\d+ \+ (0x[0-9a-f]+)\)|\+ (0x[0-9a-f]+)\)\)\(plVar")
    for ent in sorted(calls):
        s = dec(ent)
        slots = sorted(set(re.findall(r"\(\*\*\(code \*\*\)\(\*\w+ \+ (0x[0-9a-f]+)\)\)", s)))
        print("   %#x  %-24s calls=%d  slots=%s"
              % (ent, fname(ent), calls[ent], slots))

    print("=" * 78)
    print("SECTION 4 -- functions that invoke model slot 0x160 or 0xa30 or 0xa08")
    for ent in sorted(calls):
        s = dec(ent)
        for slot in ("0x160", "0xa30", "0xa08", "0xa38", "0x168"):
            if "+ %s)" % slot in s:
                print("   %#x %s uses slot %s" % (ent, fname(ent), slot))

except Exception:
    traceback.print_exc()
