"""DIMENSION 4 (duplicates), pass 8: name the request emitted on the NOT-duplicate branch. The FUT item-manager singleton's vtable was resolved from the LIVE process (read-only): DAT_1802e6398 -> object 0xb81b0940 -> vtable live 0x6ffffc35c2a0 = static 0x18021c2a0, control-checked against the RS4:FutSquadSaveServerResponse literal. Slots: +0x0c0 -> 0x1801180a0 <- called on the NOT-duplicate branch of FUN_18009bc40 +0x160 -> 0x18011b780 <- container the CreatePack fixup writes into +0x7d8 -> 0x18011b500 <- container the HAS_DUPLICATE providers read +0xa08 -> 0x18011cca0 <- item registration (called by the item deser) +0xa40 -> 0x18011bf40 HYPOTHESIS: 0x1801180a0 issues a server call, and the 0x20-byte record {itemId:int64, 7:int32, 0, 0} it is handed is an item-action list entry (7 being an action/pile enum). If so the duplicate flag GATES an existing endpoint rather than unlocking a new one. CONTROL: 0x18011b780 must be a small getter returning an object whose +0x30 is a vector (that is how FUN_180162880 uses it), and 0x18011b500 likewise; if those two do not look like getters, the live vtable read is wrong and nothing here stands. """ import traceback OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/store/dup8_out.txt" def w(fh, s=""): fh.write(str(s) + "\n") def dump(fh, a, label, depth=0): s = dec(a) w(fh, "") w(fh, "#" * 70) w(fh, "# %s %#x len(src)=%d FULL" % (label, a, len(s))) w(fh, "#" * 70) w(fh, s) try: fh = open(OUT, "w") dump(fh, 0x18011B780, "CONTROL vt+0x160 container getter") dump(fh, 0x18011B500, "CONTROL vt+0x7d8 container getter") dump(fh, 0x1801180A0, "vt+0x0c0 the call made when NOT a duplicate") dump(fh, 0x18011CCA0, "vt+0xa08 item registration") w(fh, "") w(fh, "=== callees of 0x1801180a0 ===") f = func(0x1801180A0) if f is not None: seen = set() it = listing.getInstructions(f.getBody(), True) while it.hasNext(): ins = it.next() for r in ins.getReferencesFrom(): t = int(r.getToAddress().getOffset()) g = fm.getFunctionAt(addr(t)) if g is not None and t not in seen: seen.add(t) w(fh, " %#x %s" % (t, g.getName())) for t in sorted(seen): dump(fh, t, "callee of vt+0xc0") fh.close() print("WROTE", OUT) except Exception: traceback.print_exc()