"""D2 QUICK SELL, batch 6: FUN_180141660, the derived-field filler.

RESOLUTION OF THE CONTRADICTION. [RBP+0x1b4] (item+0x54, the "level" query key) is
never written through an RBP displacement, but at 0x180141019/0x180141020 the code
does

    LEA RCX,[RBP + 0x160]        ; = the item struct base
    CALL 0x180141660
    CMP dword ptr [RBP + 0x198],0x0   ; the discardValue guard, immediately after

so FUN_180141660 receives a POINTER to the item and can write item+0x54 through
RCX, which no RBP-displacement search could ever see. It also carries four xrefs
to the "rare" literal 0x18022315c, i.e. it does its own db lookups.

DUMP IT AND EVERYTHING IT CALLS, in full.

CONTROL: FUN_180141660 must contain at least one store to [RCX/RAX/RBX + 0x54]
or an equivalent; and the known-good sibling fact is that the caller loads
item+0x54 at 0x180141099 straight afterwards. Also decompile FUN_1801356c0, the
other function referencing "rare".
"""
import traceback, os

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/store/qs/"


def dump(tag, va, path=None):
    try:
        src = dec(va)
    except Exception as e:
        src = "// threw %r" % (e,)
    print("=" * 78)
    print("%s %#x fname=%s len(src)=%d (FULL)" % (tag, va, fname(va), len(src)))
    print("=" * 78)
    print(src)
    if path:
        open(OUT + path, "w").write(src)
    return src


try:
    src = dump("derived-field filler", 0x180141660, "qs_141660.txt")
    print("\n--- raw asm of FUN_180141660 ---")
    f = func(0x180141660)
    it = listing.getInstructions(f.getBody(), True)
    n = 0
    while it.hasNext():
        i = it.next()
        print("  %#x  %s" % (int(i.getAddress().getOffset()), str(i)))
        n += 1
    print("  (%d instructions)" % n)

    print("\n--- callees ---")
    seen = set()
    it = listing.getInstructions(f.getBody(), True)
    while it.hasNext():
        i = it.next()
        t = str(i)
        if t.startswith("CALL 0x"):
            try:
                tgt = int(t.split()[1], 16)
            except Exception:
                continue
            if tgt not in seen:
                seen.add(tgt)
    for t in sorted(seen):
        dump("callee", t, "qs_141660_callee_%x.txt" % t)

    print("\n--- other 'rare' consumer ---")
    dump("FUN_1801356c0", 0x1801356c0, "qs_1356c0.txt")

except Exception:
    traceback.print_exc()
