"""Q10: the fcc_ table vocabulary and the classifier's neighbourhood.

Q8/Q9 changed the picture: inside the item deserializer, cardtype 9 items whose
cardsubtypeid is in [0x91,0x95) take a custom-image path, and a SEPARATE
deserializer FUN_180108c00 computes subtype = wireValue + 0x91 and then picks the
loc format by range:
    0x91 <= s < 0x95  ->  "TOURNY_LOC_%d"
    0x95 <= s < 0x97  ->  "SEASON_LOC_%d"
so 0x91..0x96 look like TROPHIES, not badges/kits/stadia/balls. Also, cardtype 7
(subtypes 9,10,11) has an arm that defaults a field to 0x23 = 35, and 35 is the
kit cardassetid recorded in tools/fut_clubitems.py.

This query gathers the vocabulary needed to test that:
  A. every "fcc_" table name literal in the binary, with the function that queries
     it -- the merge's per-family table map;
  B. every literal starting "cardsubtype" / "cardtype" (column names);
  C. the small helpers around the classifier: FUN_1800d84e0 (called right after it
     in the deser), FUN_1800d7b30/b50/af0/b10, FUN_1800d7170.

CONTROL: "fcc_discardcoins" must appear in A, and its query site must be
FUN_18013fe00 (line 784 of the Q8 decompile). If it does not, the literal scan is
not seeing the same code the decompiler is.
"""
import traceback

try:
    print("=== A: fcc_ table literals ===")
    seen = set()
    for h in find_all(b"fcc_"):
        s = rd_str(h, 64)
        if not s or s in seen:
            continue
        seen.add(s)
        xs = xrefs_to(h)
        who = ",".join(sorted({"%s(%#x)" % (fn, ent) for _f, _t, fn, ent in xs}))
        print("  %#x %-28r <- %s" % (h, s, who or "-"))
    print("  total distinct: %d" % len(seen))

    print()
    print("=== B: cardtype / cardsubtype column literals ===")
    for pat in (b"cardtype", b"cardsubtype", b"carddbid", b"cardassetid"):
        for h in find_all(pat):
            s = rd_str(h, 64)
            xs = xrefs_to(h)
            who = ",".join(sorted({"%s(%#x)" % (fn, ent) for _f, _t, fn, ent in xs}))
            print("  %#x %-28r <- %s" % (h, s, who or "-"))

    print()
    print("=== C: helpers ===")
    for a in (0x1800D84E0, 0x1800D7B30, 0x1800D7B50, 0x1800D7AF0, 0x1800D7B10):
        src = dec(a)
        print("-" * 70)
        print("FUN_%x len=%d" % (a, len(src)))
        print(src if len(src) < 2500 else src[:2500] + "\n...[TRUNCATED, len above]")
except Exception:
    traceback.print_exc()
