"""ADVERSARIAL BATCH 4 -- the settings RESPONSE object, not the model-side deser.
FUN_180173e00 reads its param_2 (the FutGetSettings response) at +0x1c (error gate),
copies +0x28..+0xc0 and hands &<copy of +0x28> to the gate applier vt+0x988, and
copies +0xc8..+0xd4 and hands &<copy of +0xc8> to vt+0x998.
So model+0x1fd2e <- response+0x50, and model+0x1fd1c <- response+0xd0.
HYPOTHESIS: the FutGetSettings response deserializer writes response+0x50 and +0xd0
from specific atoms. Find them.
CONTROL: the same RS4-name -> vtable -> slot+0x08 resolution that reproduced
FutISSearch 0x180163420 and FutGetTradePile 0x180170810 in batch 2.
"""
import traceback, re

try:
    for nm in (b"RS4:FutGetSettingsServerResponse\x00", b"RS4:FutSettingsServerResponse\x00",
               b"RS4:FutISSearchServerResponse\x00"):
        locs = find_all(nm, blocks=(".rdata", ".data"))
        print("\n### %s -> %s" % (nm.decode().rstrip("\x00"), [hex(x) for x in locs]))
        for L in locs:
            for a, t, f, ent in xrefs_to(L):
                if not ent: continue
                s = dec(ent)
                m = set(re.findall(r"(?:PTR_[A-Za-z_0-9]*_|DAT_|&)([0-9a-fA-F]{9})", s))
                print("   fn %s @%#x installs %s" % (f, ent, m))
                for c in m:
                    v = int(c, 16)
                    if 0x180200000 <= v < 0x180290000:
                        print("      vtable %#x slot+0x08 = %#x" % (v, qword(v + 8)))
except Exception:
    traceback.print_exc()
