"""DIMENSION 1 / query 6: who sets the selected category (+0x290) and where do
a pack's NAME / DESCRIPTION / CONTENT come from.

ESTABLISHED: FUN_18007dab0 renders the store list from
FUN_1800147f0(model, *(int*)(screen+0x290), dataProvider, 0, 0). Ordinal 0 means
"list the group tiles". So screen+0x290 IS the drill-down selector and the whole
bug reduces to what value the UI puts there.

Live: pack records have EMPTY strings at +0xd8/+0x108/+0x138, which are exactly
the slots FUN_180015d80 pushes as NAME / DESCRIPTION / CONTENT, so a pack's
caption must be produced elsewhere -> FUN_18002cc90, the tail of the pack model
builder, and FUN_180016a80/bf0/840 for the group tiles.

CONTROL: FUN_180016a80/FUN_180016bf0/FUN_180016840 are three same-shape setters
called on the SAME group strings; if they do not land on three different offsets
among +0xd8/+0x108/+0x138 the reading of FUN_180014610 is wrong.
"""
import traceback

OUT = "/tmp/claude-1000/-home-alex-Documents-OpenFUT/8e521ca1-ca3e-4138-bb96-df1744dd1d30/scratchpad/store/q6_out.txt"
buf = []
def P(*a):
    s = " ".join(str(x) for x in a)
    buf.append(s)
    print(s)

def C(a, label, show_callers=True):
    P("=" * 78)
    P(label, hex(a))
    P("=" * 78)
    s = dec(a)
    P("len(src) =", len(s))
    P(s)
    if show_callers:
        P("--- callers ---")
        for ent, nm in callers(a):
            P("   %-30s %s" % (nm, hex(ent)))

try:
    for a in (0x18007dbd0, 0x18007ddd0, 0x18007da30, 0x18007e230, 0x18007d930):
        C(a, "store msg handler FUN_%x" % a)
    C(0x18002cc90, "pack model tail FUN_18002cc90")
    for a in (0x180016a80, 0x180016bf0, 0x180016840):
        C(a, "CONTROL string setter FUN_%x" % a, False)
except Exception:
    P(traceback.format_exc())

open(OUT, "w").write("\n".join(buf))
print("WROTE", OUT)
