"""DIMENSION 2 batch 3. HYPOTHESES H1 FUN_180028b50 is the Scaleform command registrar (CardsDiscardCard, CardsDiscardCardList, CardsDiscardCardByRes, CardsSwapCards, CardsMoveCard, RemoveFromTradePile, RemoveAllSoldFromTradePile). Each registration row carries the C++ handler, which is the UI entry point for quick sell / move. H2 FUN_1800394c0 is the Scaleform getter registrar (GetCardDuplicate, GetTradePileResults, AddCardBackToTradePile). GetCardDuplicate's handler reads the card field that createPack's duplicateItemIdList post-pass wrote. H3 The int at row+8 of the action table 0x1802cb000 indexes the ut/%s/... URL template array. Print that array so DiscardCard=0xf etc. can be resolved rather than guessed from .rdata ordering. H4 The request factories 0x180123cc0/cd0/ce0 (DiscardACard/DiscardCard/ DiscardCardByRes), 0x1801241f0 (MoveCard), 0x180124830 (SwapCard) build the request objects; their serializers give the request body. CONTROL: FutSquadSaveServerResponse -> 0x180171a60 (re-checked in this batch). """ import traceback, os OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres" def dump(name, text): with open(os.path.join(OUT, name), "w") as f: f.write(text) print("[wrote %s %d chars]" % (name, len(text))) def show(label, va, save=None): s = dec(va) print("-" * 74) print("%s %#x len(src)=%d" % (label, va, len(s))) print(s) if save: dump(save, s) return s try: print("CONTROL FutSquadSaveServerResponse ->", [hex(a) for a, v, e in class_deser("FutSquadSaveServerResponse")]) print("=" * 78) print("SECTION 1 -- URL template pointer array (find the array that holds " "0x18021e490 'ut/%s/item')") tgt = 0x18021E490 for r in xrefs_to(tgt): print(" xref to ut/%%s/item %#x %s %s %#x" % (r[0], r[1], r[2], r[3])) # scan .data/.rdata for a qword equal to the auctionhouse template, then walk for probe in (0x18021E308,): import struct hits = find_all(struct.pack(" %#x %r" % (i, va, q, s)) print("=" * 78) print("SECTION 2 -- Scaleform command registrar FUN_180028b50") s = dec(0x180028B50) print("len(src) =", len(s)) dump("d2_scaleform_cmd_registrar.txt", s) for ln in s.splitlines(): if any(k in ln for k in ("Discard", "SwapCard", "MoveCard", "TradePile", "Duplicate", "QuickSell", "Sell")): print(" ", ln.strip()) print("=" * 78) print("SECTION 3 -- Scaleform getter registrar FUN_1800394c0") s = dec(0x1800394C0) print("len(src) =", len(s)) dump("d2_scaleform_get_registrar.txt", s) for ln in s.splitlines(): if any(k in ln for k in ("Duplicate", "TradePile", "Discard", "Sell")): print(" ", ln.strip()) print("=" * 78) print("SECTION 4 -- request factories") for lbl, va in (("DiscardACard", 0x180123CC0), ("DiscardCard", 0x180123CD0), ("DiscardCardByRes", 0x180123CE0), ("MoveCard", 0x1801241F0), ("MoveCardByRes", 0x180124200), ("SwapCard", 0x180124830), ("ViewCards", 0x180124900)): show("factory " + lbl, va) print("=" * 78) print("SECTION 5 -- FutDiscardCard response vtable 0x180220488") for off, t, n in vtable(0x180220488, 12): print(" +%#04x -> %#x %s" % (off, t, n)) print(" ctor/xrefs to vtable:") for r in xrefs_to(0x180220488): print(" ", hex(r[0]), r[1], r[2], hex(r[3])) print(" xrefs to factory 0x180127160 / 0x180127630:") for f in (0x180127160, 0x180127630): for r in xrefs_to(f): print(" ", hex(f), "<-", hex(r[0]), r[1], r[2], hex(r[3])) except Exception: traceback.print_exc()