"""D3 Q7: the eight card-action flags, and the code that switches on itemState.

ESTABLISHED. FUN_18003e370 publishes eight per-card booleans to Flash under the names
DISCARD, MODIFY, TO_ACTIVE_SQUAD, TO_TRADE_PILE, TO_STICKER_BOOK, MAY_BE_REMOVED,
QUICK_SEARCH, DREAM_REPLACE, filled by FUN_1800e2a40 in that byte order:
  [0] FUN_1801a71c0  [1] FUN_1801a7210  [2] inline (isPlayer && squad room && not in
  squad)  [3] FUN_1801a7260  [4] FUN_1801a7180  [5] constant 1  [6] FUN_1801a7320
  [7] FUN_1801a71e0
and a precise, controlled scan (control displacements 0x3c and 0x4c returned 25 and 37
load/compare pairs) showed that item+0x49 is compared in EXACTLY TWO places in the
whole DLL -- the getter FUN_1801a8940 and the TO_TRADE_PILE predicate FUN_1801a7260 --
while item+0x5c is compared against 0x64..0x68 in six functions.

POLARITY IS THE OPEN QUESTION. Byte [2] is computed inline as
  isPlayer && squadHasRoom && !alreadyInSquad -> 1
which can only be an ENABLE flag, so 1 = action offered. Under that reading
FUN_1801a7260 returns 1 (offered) whenever item+0x49 is 0, which is the opposite of
what "tradeable" should do. Either the flag array is a DISABLE mask, or the service
call at vtable+0x270 inverts the sense. This query decompiles all eight predicates and
the service so the polarity is READ, not assumed.

CONTROL: FUN_1801a7250 is already known to be the +0x4c (card family) accessor and byte
[2] uses it as "is a player". If the decompile of FUN_1801a7250 is not a +0x4c read the
whole byte-order attribution is wrong and nothing here counts.
"""
import traceback, os

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/cards/"
os.makedirs(OUT, exist_ok=True)


def dump(tag, va, full=6000):
    f = func(va)
    if f is None:
        print("%s %#x -> NO FUNCTION" % (tag, va))
        return ""
    src = dec(va)
    print("=" * 78)
    print("%s  %#x  %s  len(src)=%d" % (tag, va, f.getName(), len(src)))
    print("=" * 78)
    with open(OUT + "q7_%s_%x.c" % (tag, va), "w") as fh:
        fh.write(src)
    if len(src) <= full:
        print(src, "  [PRINTED IN FULL]")
    else:
        print("  [TOO LONG TO PRINT IN FULL -- written to q7_%s_%x.c; printing every"
              " line mentioning 0x5c plus 6 lines of context]" % (tag, va))
        lines = src.split("\n")
        keep = set()
        for i, l in enumerate(lines):
            if "0x5c" in l or "0x49" in l or "0x48" in l:
                for j in range(max(0, i - 6), min(len(lines), i + 7)):
                    keep.add(j)
        prev = -2
        for i in sorted(keep):
            if i != prev + 1:
                print("   ...")
            print("   %4d %s" % (i, lines[i]))
            prev = i
    return src


try:
    print("###### A. the eight card-action predicates, in Flash byte order")
    for tag, va in (("a0_DISCARD_1801a71c0", 0x1801a71c0),
                    ("a1_MODIFY_1801a7210", 0x1801a7210),
                    ("a2_family_acc_1801a7250", 0x1801a7250),
                    ("a3_TO_TRADE_PILE_1801a7260", 0x1801a7260),
                    ("a4_TO_STICKER_BOOK_1801a7180", 0x1801a7180),
                    ("a6_QUICK_SEARCH_1801a7320", 0x1801a7320),
                    ("a7_DREAM_REPLACE_1801a71e0", 0x1801a71e0),
                    ("view_init_1801a78f0", 0x1801a78f0),
                    ("view_isnull_1801a8850", 0x1801a8850),
                    ("view_4c_1801a8110", 0x1801a8110),
                    ("helper_1801aa190", 0x1801aa190)):
        dump(tag, va)

    print()
    print("###### B. the itemState (0x5c) switches")
    for tag, va in (("s_180084720", 0x180084720), ("s_180094220", 0x180094220),
                    ("s_180043880", 0x180043880), ("s_180094ae0", 0x180094ae0),
                    ("s_180113870", 0x180113870), ("s_1801c3480", 0x1801c3480),
                    ("s_1801b3640", 0x1801b3640), ("s_18011dc50", 0x18011dc50),
                    ("s_180051cd0", 0x180051cd0)):
        dump(tag, va)

    print()
    print("###### C. the CardInventoryAdapter registration (what else it publishes)")
    dump("adapter_18003ec30", 0x18003ec30)
    dump("listpanel_18003e550", 0x18003e550)

    print()
    print("###### D. the service behind FUN_180009c80 -- what is vtable slot 0x270?")
    dump("svc_ctor_180009c80", 0x180009c80)
    dump("svc_ctor_180009b60", 0x180009b60)
except Exception:
    traceback.print_exc()
