"""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()