"""DIMENSION 4, pass 10: NAME the endpoint on the not-duplicate branch.

Chain established so far:
  FUN_18009bc40  (branches on item->duplicateItemId != 0)
    not-duplicate -> builds a server-call object whose vtable is 0x1801f3158,
       pushes one 0x20-byte record {itemId:int64, 7:int32, 0, 0} into its
       "FUT Vector", and calls manager vt+0xc0 (FUN_1801180a0)
    FUN_1801180a0 -> stores the delegate and calls FUN_18016c730
    FUN_18016c730 -> the generic dispatcher: vt+0x38 writes the URL into a 0x200
       buffer, then the body into a 0xaf0 buffer, then hands both to the HTTP
       layer (FUN_180122550 vt+0x28).

So vtable 0x1801f3158 IS the request class. Dump it, decompile its URL builder
(slot +0x38) and its body serializer, and find its RS4: class name.

CONTROL: a known-good request class is dumped alongside -- the CreatePack
request, whose serializer is 0x180162530 and whose class name literal
"RS4:FutCreatePackServerResponse" is already established -- so the slot layout
interpretation is checked against something with a known answer.
"""
import traceback

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/store/dup10_out.txt"

def w(fh, s=""):
    fh.write(str(s) + "\n")

def dumpvt(fh, a, label, n=32):
    w(fh, "")
    w(fh, "=== vtable %s @ %#x ===" % (label, a))
    for off, tgt, nm in vtable(a, n):
        w(fh, "   +%#05x -> %#x  %s" % (off, tgt, nm))

def dump(fh, a, label):
    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")
    dumpvt(fh, 0x1801F3158, "the not-duplicate request class", 40)

    w(fh, "")
    w(fh, "=== xrefs to the vtable 0x1801f3158 (ctor sites) ===")
    for frm, typ, fn, ent in xrefs_to(0x1801F3158):
        w(fh, "   %#x %s in %s @ %#x" % (frm, typ, fn, ent))

    # decompile the interesting slots
    for off in (0x08, 0x10, 0x30, 0x38, 0x40, 0x48, 0x50, 0x58, 0x60):
        try:
            t = qword(0x1801F3158 + off)
        except Exception:
            continue
        if fm.getFunctionAt(addr(t)) is not None:
            dump(fh, t, "vt+%#04x of the request class" % off)
        else:
            w(fh, "// vt+%#04x -> %#x  (no function)" % (off, t))

    w(fh, "")
    w(fh, "=== every RS4: literal within +-0x400 of nothing; instead: all RS4: names ===")
    hits = find_all(b"RS4:")
    w(fh, "RS4: literals: %d" % len(hits))
    for h in hits:
        nm = rd_str(h, 80)
        xr = xrefs_to(h)
        if xr:
            w(fh, "   %#x %-52s  %s" % (h, nm, ",".join("%#x" % e for _, _, _, e in xr[:4])))

    fh.close()
    print("WROTE", OUT)
except Exception:
    traceback.print_exc()
