"""Q7: every caller of the cardtype classifier, and how each treats cardtype 9.

FUN_1800d8330(cardsubtypeid) -> cardtype. Anything that needs to know "this is a
club item" must either call it or test cardsubtypeid directly. Enumerate its
callers, decompile each, and print EVERY line mentioning a 9 in any comparison or
switch form (case 9:, ==9, !=9, -9, <9, >9), so an arm written as != does not hide.

Also decompile the shared item deserializer FUN_18013fe00 fully? No: too long for
one batch. Instead print its length and the lines around the FUN_1800d8330 call and
around the itemState helper call at 0x1801406e3.

CONTROL: FUN_1800d8330 itself is excluded; the caller list must be non-empty and
must include the item deserializer FUN_18013fe00 (which is documented to compute
the family into item+0x4c). If FUN_18013fe00 is absent from the caller list, the
xref enumeration is broken.
"""
import re
import traceback

try:
    seen = {}
    for frm, typ, fn, ent in xrefs_to(0x1800D8330):
        if ent and ent != 0x1800D8330:
            seen.setdefault(ent, fn)
    print("=== callers of FUN_1800d8330: %d ===" % len(seen))
    pat = re.compile(r"(case\s+9\s*:|[=!<>]=\s*9\b|==\s*9\b|!=\s*9\b|\b9\s*[=!<>]|-\s*9\b)")
    for ent, fn in sorted(seen.items()):
        src = dec(ent)
        lines = src.splitlines()
        hits = [(i, l.strip()) for i, l in enumerate(lines) if pat.search(l)]
        print("-" * 70)
        print("%s @%#x  len=%d  nine-lines=%d" % (fn, ent, len(src), len(hits)))
        for i, l in hits[:40]:
            print("   %4d: %s" % (i, l))
    print("=" * 70)
    src = dec(0x18013FE00)
    print("item deser FUN_18013fe00 len=%d" % len(src))
    for i, l in enumerate(src.splitlines()):
        if "1800d8330" in l or "180166660" in l or "1801666f0" in l:
            print("   %4d: %s" % (i, l.strip()))
except Exception:
    traceback.print_exc()
