"""Q21: the FUT data-manager vtable slots that name a club item. FUN_1800f6c40 (the pack/award tile builder) does: if (item+0x4c == 1) -> ITEM_RARITY / ITEM_LEVEL else if (item+0x50 == 9) -> "IS_KIT_%d" = 1 <-- names subtype 9 name = mgr->vt[0x490](out, item+0x4c cardtype, item+0x50 subtype, item+0x18) if (name empty && item+0x4c == 7) name = mgr->vt[0x498](out, item+0x50 subtype, item+0x94 teamid, item+0x20) where mgr = FUN_18011a830(). Slots 0x490 and 0x498 are therefore the club-item name resolvers and must switch on the subtype. Resolve the manager's vtable, then decompile slots 0x490, 0x498, 0xa08, 0xa38, 0xa40. CONTROL: slot 0xa08 is the one the item deserializer calls to file a parsed item (FUN_18013fe00 line 825), and slot 0xa40 is the lookup FUN_18011e3c0 uses with a resourceId. If the resolved vtable's 0xa08/0xa40 are not functions, the vtable resolution is wrong. """ import traceback try: src = dec(0x18011A830) print("=== FUN_18011a830 (manager accessor) len=%d ===" % len(src)) print(src) # find the vtable it installs / the object's class print() print("=== candidate vtables referenced from FUN_18011a830 and its callees ===") f = func(0x18011A830) cands = set() for ad in f.getBody().getAddresses(True): ins = listing.getInstructionAt(ad) if ins is None: continue for r in ins.getReferencesFrom(): t = int(r.getToAddress().getOffset()) if 0x1801E5000 <= t <= 0x1802891FF: cands.add(t) for t in sorted(cands): try: v0, v1 = qword(t), qword(t + 8) except Exception: continue print(" %#x -> %#x %#x (%s / %s)" % (t, v0, v1, fname(v0) if 0x180000000 <= v0 < 0x181000000 else "-", fname(v1) if 0x180000000 <= v1 < 0x181000000 else "-")) except Exception: traceback.print_exc()