"""VERIFY-5. Last batch: the vtable-shape evidence D3 gave, the CreatePack mode
derivation, and the MEDIUM-graded first-party-store claims.

  H22 D3 says "the class vtable at 0x180228260 has no accessor (slot 0 and slot
      +0x40 are deleting destructors, ... the rest are the shared base slots also
      present on the store response)". D5 says that vtable is only TWO slots and the
      ServerCall vtable starts at 0x180228270. Both cannot be right. Settle it from
      the two constructors.
  H23 CreatePack req serializer mode derivation (mode 0/1/2/4).
  H24 0x180220400 is "PURCHASEERROR".
  H25 descriptor 0x1801f0458 + inline literal "CARDPACK" at 0x1801f0490.
  H26 FUN_18003ed70 registers the five store script bindings.
  H27 which vtable slot index carries the HTTP-status handler.

CONTROL: FUN_1801623d0 must reference 0x180228270 and FUN_180162420 must reference
0x180228260, as the xref dump in VERIFY-3 already showed.
"""
import traceback
OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/packres/"

try:
    print("=" * 74)
    print("H22 the two constructors, verbatim")
    for e, tag in [(0x180162420, "resp_ctor"), (0x1801623d0, "call_ctor"),
                   (0x1801624a0, "f1801624a0"), (0x180162490, "f180162490")]:
        s = dec(e)
        print()
        print("---- %s %#x len=%d ----" % (tag, e, len(s)))
        print(s)

    print()
    print("--- raw qwords 0x180228240..0x1802282e0 with symbols ---")
    st = prog.getSymbolTable()
    for a in range(0x180228240, 0x1802282e8, 8):
        q = qword(a)
        f = fm.getFunctionAt(addr(q)) if 0x180000000 <= q < 0x181000000 else None
        syms = [str(s) for s in st.getSymbols(addr(a))]
        print("  %010x  %016x  %-40s %s" % (a, q, f.getName() if f else "", syms))

    print()
    print("=" * 74)
    print("H27 which slot of 0x180228270 / 0x1802202f8 holds the status handler")
    for base, nm in [(0x180228270, "CreatePack call vtbl"), (0x1802202f8, "PurchaseItems call vtbl")]:
        for i in range(24):
            q = qword(base + i * 8)
            f = fm.getFunctionAt(addr(q)) if 0x180000000 <= q < 0x181000000 else None
            mark = ""
            if q in (0x18016c060, 0x1801267b0): mark = "   <== HTTP STATUS HANDLER"
            print("  %s slot %2d (+%03x) %016x %s%s" % (nm, i, i * 8, q, f.getName() if f else "", mark))
        print()

    print("=" * 74)
    print("H23 CreatePack request serializer, verbatim")
    s = dec(0x180162530)
    open(OUT + "v5_createpack_reqser.txt", "w").write(s)
    print("len=%d lines=%d" % (len(s), s.count("\n")))
    print(s)

    print("=" * 74)
    print("H24 literals")
    for a in (0x180220400, 0x1802203f8, 0x1801eae8c, 0x1801f0490, 0x1801efeb0):
        print("  %010x = %r  rawbytes=%s" % (a, rd_str(a, 40), read_bytes(a, 16).hex()))

    print()
    print("=" * 74)
    print("H25 descriptor 0x1801f0458")
    for k in range(-2, 12):
        a = 0x1801f0458 + k * 8
        q = qword(a)
        f = fm.getFunctionAt(addr(q)) if 0x180000000 <= q < 0x181000000 else None
        print("  %010x [%+3d] %016x %-30s ascii=%r" % (a, k * 8, q, f.getName() if f else "",
              read_bytes(a, 8)))

    print()
    print("=" * 74)
    print("H26 FUN_18003ed70")
    s = dec(0x18003ed70)
    open(OUT + "v5_scriptreg.txt", "w").write(s)
    print("len=%d" % len(s))
    print(s[:5000])

except Exception:
    traceback.print_exc()
