"""Q: FUN_1800eb850 pushes BOTH "DISCARD_CREDITS" (3 refs) and
"CALCULATED_DISCARD_CREDITS" (1 ref) to the UI. Which item offset feeds each?

H1 predicts DISCARD_CREDITS <- item+0x38 (the wire discardValue) and
CALCULATED_DISCARD_CREDITS <- item+0x3c (the client's fcc_discardcoins result),
two independent UI properties with no native fallback between them. If so, which
one the card tile shows is decided in the Flash/Scaleform asset, not in native
code, and the "Quick Sell 0" observation means the tile binds DISCARD_CREDITS.

METHOD: full decompile plus the raw instruction stream around every reference to
the two names, so the register feeding the third argument is visible rather than
inferred from decompiler variable naming. Also the callers of FUN_1800eb850, and
the same treatment for the sibling names DISCARD / COINS_AWARDED.

CONTROL: FUN_18013fe00's own two sites are the reference semantics: the guard
reads [RBP+0x198] (= item+0x38) and the store writes [RBP+0x19c] (= item+0x3c).
Any offsets this query reports must be interpretable against a struct base held
in a register; I print the full function so the base can be traced, rather than
quoting a fragment.
"""
import traceback

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

try:
    lines = []
    def P(*a):
        lines.append(" ".join(str(x) for x in a))

    for nm, a in (("DISCARD_CREDITS", 0x1802161C8),
                  ("CALCULATED_DISCARD_CREDITS", 0x1802161D8),
                  ("DISCARD", 0x1801F4D28)):
        P("=== xrefs to %r (%#x) ===" % (nm, a))
        for frm, typ, fn, ent in xrefs_to(a):
            P("   %#x %-12s %s @ %#x" % (frm, typ, fn, ent))
        P("")

    f = func(0x1800EB850)
    b = f.getBody()
    lo = int(b.getMinAddress().getOffset())
    hi = int(b.getMaxAddress().getOffset())
    P("FUN_1800eb850 body [%#x..%#x] size=%d" % (lo, hi, int(b.getNumAddresses())))

    src = dec(0x1800EB850)
    P("")
    P("=== FUN_1800eb850 FULL DECOMPILE, len=%d ===" % len(src))
    P(src)

    P("")
    P("=== FUN_1800eb850 FULL DISASSEMBLY ===")
    p = lo
    while p <= hi:
        ins = listing.getInstructionAt(addr(p))
        if ins is None:
            P("%#x  <none>" % p)
            p += 1
            continue
        extra = ""
        for r in ins.getReferencesFrom():
            t = int(r.getToAddress().getOffset())
            if 0x1801E5000 <= t <= 0x180290000:
                try:
                    s = rd_str(t, 60)
                except Exception:
                    s = ""
                if s:
                    extra = "   ; %r" % s
        P("%#x  %s%s" % (p, ins, extra))
        p += ins.getLength()

    P("")
    P("=== CALLERS OF FUN_1800eb850 ===")
    for frm, typ, fn, ent in xrefs_to(0x1800EB850):
        P("   %#x %-12s %s @ %#x" % (frm, typ, fn, ent))

    with open(OUT, "w") as fh:
        fh.write("\n".join(lines))
    print("wrote %s (%d lines)" % (OUT, len(lines)))
except Exception:
    traceback.print_exc()
