"""DIMENSION 2 Q3/Q4 finish: draft-tile gating in FUN_1800b2680; SBC/Objectives accessor slots and whether any native code reads them. HYPOTHESIS: IS_DRAFT_MODE_ENABLED (cVar7) gates whether the draft hub tile is drawn / enabled. SBC(0x1fd2c,0x1fd42) and Objectives(0x1fd44) have accessor stubs at some model vtable slots but NO IS_* publisher name; either a vtable-slot caller reads them or they are consumed only by their own accessor (i.e. no native mode gate). CONTROL: draft accessor is model slot 0x2c8 (proven). Walking the vtable and matching disp must reproduce 0x2c8->0x1fd3d and 0x270->0x1fd2e. """ import traceback try: MODEL_VT = 0x18021c2a0 # find slots for the SBC/objectives displacements by walking vtable want = {0x1fd2c: "allowUntradeableForSBC", 0x1fd42: "allowGracePeriodForSBC", 0x1fd44: "enableObjectives", 0x1fd28: "sbcGracePeriodMinutes", 0x1fd3e: "offlineDraft(0x2d0?)", 0x1fd2e: "trading(ctl)", 0x1fd3d: "draft(ctl)"} slot_for_disp = {} print("=" * 70) print("vtable walk: slot -> accessor disp (0x200..0x340)") print("=" * 70) for slot in range(0x200, 0x340, 8): tgt = qword(MODEL_VT + slot) if not (0x180000000 <= tgt < 0x181000000): continue stub = read_bytes(tgt, 8) disp = None if stub[0:3] == b"\x0f\xb6\x81" and stub[7] == 0xc3: disp = int.from_bytes(stub[3:7], "little") elif stub[0:2] == b"\x8b\x81" and stub[6] == 0xc3: disp = int.from_bytes(stub[2:6], "little") if disp in want: slot_for_disp[disp] = slot print("slot +%#05x -> %#011x disp %#x %s" % (slot, tgt, disp, want[disp])) # scan slot-callers for the objectives + SBC slots print() print("=" * 70) print("slot-call readers for SBC/Objectives accessor slots") print("=" * 70) call_modrm = [0x90, 0x91, 0x92, 0x93, 0x95, 0x96, 0x97] for disp in (0x1fd44, 0x1fd2c, 0x1fd42): slot = slot_for_disp.get(disp) if slot is None: print("\ndisp %#x: no vtable slot found in range" % disp) continue pat_disp = slot.to_bytes(4, "little") found = [] for pre in ([], [0x41]): for mrm in call_modrm: pat = bytes(pre + [0xff, mrm]) + pat_disp for h in find_all(pat, blocks=(".text",)): f = fm.getFunctionContaining(addr(h)) found.append((h, f.getName() if f else "?", int(f.getEntryPoint().getOffset()) if f else 0)) print("\ndisp %#x slot +%#05x %-24s (%d call-site(s))" % (disp, slot, want[disp], len(found))) for h, fn, ent in found: print(" %#011x in %-16s (%#x)" % (h, fn, ent)) # rest of the draft hub-tile builder: how cVar7/8/9 gate the tile print() print("=" * 70) print("FUN_1800b2680 draft/tile gating region (search cVar / DRAFT in decompile)") print("=" * 70) d = dec(0x1800b2680) lines = d.splitlines() for i, ln in enumerate(lines): if any(k in ln for k in ("cVar7", "cVar8", "cVar9", "DRAFT", "0x70", "0x60", "DESTINATION", "GOTO_", "SBC", "OBJECTIVE", "case 0xc", "caseD_")): print("%4d: %s" % (i, ln.strip())) except Exception: traceback.print_exc()