# Q16: FutComponentServicesImpl::FutSquadServiceImpl -- get its ctor + vtable and
# decompile SaveCurrentSquad(+0x50) / AddPlayerToSquad(+0x168) for real.
out = open("/tmp/ghidra_fut/squad_impl.txt", "w")
P = lambda *a: print(*a, file=out)

P("=== all FutComponentServicesImpl::* service classes ===")
for a in find_all(b"FutComponentServicesImpl::", blocks=(".rdata", ".data")):
    P("  %#x  %s" % (a, rd_str(a, 90)))

P("\n=== ctor/factory FUN_180189be0 ===")
P(dec(0x180189be0)[:3000])

NAME = None
for a in find_all(b"FutComponentServicesImpl::FutSquadServiceImpl", blocks=(".rdata", ".data")):
    NAME = a
P("\nclass-name string @ %#x; xrefs:" % NAME)
for frm, typ, fn, ent in xrefs_to(NAME):
    P("  %#x %s in %s @ %#x" % (frm, typ, fn, ent))

# The ctor writes the vtable into the object. Find vtables whose slot count is
# large and that live near other Fut service vtables; verify by checking that
# +0x50 / +0x168 / +0x198 / +0x1b8 / +0x1c8 are all real functions.
P("\n=== candidate FutSquadServiceImpl vtables (>=58 slots) ===")
TXT_LO, TXT_HI = 0x180001000, 0x1801e4fff


def is_fn(v):
    return TXT_LO <= v <= TXT_HI and fm.getFunctionAt(addr(v)) is not None


p, cur, runs = 0x1801e5000, None, []
while p < 0x2891f0 + 0x180000000:
    try:
        v = qword(p)
    except Exception:
        v = 0
    if is_fn(v):
        if cur is None:
            cur = [p, 0]
        cur[1] += 1
    else:
        if cur and cur[1] >= 58:
            runs.append(tuple(cur))
        cur = None
    p += 8
if cur and cur[1] >= 58:
    runs.append(tuple(cur))

for s, n in runs:
    nm = rd_str(s + n * 8, 60)
    P("  vtable %#x  %d slots  trailing=%r" % (s, n, nm[:45]))

P("\n=== slot decompiles for every candidate ===")
for s, n in runs:
    nm = rd_str(s + n * 8, 60)
    P("\n##### vtable %#x (%d slots, %r) #####" % (s, n, nm[:40]))
    for off, tag in ((0x50, "SaveCurrentSquad"), (0x168, "AddPlayerToSquad")):
        if off // 8 >= n:
            continue
        t = qword(s + off)
        f = fm.getFunctionAt(addr(t))
        P("--- +%#05x %s -> %#x %s ---" % (off, tag, t, f.getName() if f else ""))
        P(dec(t)[:3000])
out.close()
print("wrote squad_impl.txt")
