"""DIMENSION 2 batch 5: resolve the two service objects the UI layer calls into.

HYPOTHESES
 H1 DAT_1802de4d0 is the FUT request service. Slots seen from the Scaleform
    handlers: +0x20 DiscardCard(id) - +0x28 DiscardCardList(ids[],n) -
    +0x30 DiscardCardByRes - +0x38 MoveCard(id,?,pile) -
    +0x40 MoveMultipleCards(ids[],n,pile) - +0x48 MoveCardByRes(res,pile) -
    +0x70 RefreshUserCredit - +0x78 SellCard(id,a,b,c) -
    +0xb0 GetLastMoveCardId - +0x190 RemoveFromTradePile(tradeId) -
    +0x198 RemoveAllSoldFromTradePile.
 H2 DAT_1802def18 is the card/UI data provider. +0x18 GetCardDuplicate,
    +0xc8 GetTradePileResults, +0xd8 AddCardBackToTradePile.
 Find each object's vtable by locating the store to the global, then dump slots.

CONTROL: FutCreateMatchServerResponse -> 0x180120380.
"""
import traceback, os, struct

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)


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

    for g in (0x1802DE4D0, 0x1802DEF18):
        print("=" * 78)
        print("global %#x  xrefs:" % g)
        seen = set()
        for r in xrefs_to(g):
            print("   %#x %s %s %#x" % (r[0], r[1], r[2], r[3]))
            if r[3]:
                seen.add(r[3])
        print("  containing functions:", [hex(x) for x in sorted(seen)])
        for fn in sorted(seen):
            s = dec(fn)
            if len(s) < 3000:
                print("---- %#x len=%d ----" % (fn, len(s)))
                print(s)

    print("=" * 78)
    print("SECTION 2 -- candidate vtables: any .rdata table whose slot +0x198 and "
          "+0x190 are functions and which is referenced by a ctor storing to "
          "0x1802de4d0. Fallback: scan .rdata for PTR tables near known impls.")
    # The Scaleform layer calls through the object; find the ctor by looking for
    # functions that write the global.  Print raw instruction text around each ref.
    for g in (0x1802DE4D0, 0x1802DEF18):
        for r in xrefs_to(g):
            ins = listing.getInstructionAt(addr(r[0]))
            print("  %#x  %s" % (r[0], ins))

except Exception:
    traceback.print_exc()
