"""D3: the SETTINGS SUB-STRUCT constructor and the standalone /settings path.

The massinfo response ctor FUN_180173a50 calls FUN_18014e320(param_1 + 5), i.e.
on response+0x28 -- which is exactly the base the settings deserializer
FUN_18013c6d0 is handed and exactly the base the gate applier FUN_18011dc50
reads. So FUN_18014e320 holds the DEFAULT of every gate the client will adopt
when `configs` is empty.

WHY THIS MATTERS: with FUT_SETTINGS unset the server serves {"configs": []}, and
live the gate bytes are model+0x1fd28=60, +0x1fd2c=1, +0x1fd2e=0, +0x1fd2f=1,
+0x1fd3a..+0x1fd45=1. If those are FUN_18014e320's defaults, the applier ran and
simply copied defaults -- which both proves the apply path is live and means
sending extra config rows cannot regress a gate that is currently on.

FALSIFIER: if FUN_18014e320 leaves index [7] (settings+0x1c) at something other
than 60, the "60 came from the default" story is wrong and model+0x1fd28 must
have another source.

CONTROL, non-boolean and therefore not coincidence: index [7] -> model+0x1fd28
must be 60 and index [4] -> model+0x1fd54 must be 480 in the constructor.

Also: is the standalone /settings response applied at all?
FUN_18014e490 references RS4:FutGetSettingsServerResponse and 0x18014e473
references the "/settings" route literal. Decompile that whole family.
"""
import traceback

try:
    for label, a in [
        ("FUN_18014e320  SETTINGS STRUCT CTOR (defaults)", 0x18014E320),
        ("FUN_18014e490  /settings response factory", 0x18014E490),
        ("FUN_180152350  other FutGetSettings ref", 0x180152350),
    ]:
        src = dec(a)
        print("=" * 78)
        print("### %s  @ %#x  len(src)=%d" % (label, a, len(src)))
        print("=" * 78)
        print(src)
        print()

    f = fm.getFunctionContaining(addr(0x18014E473))
    print("### function containing the /settings literal ref 0x18014e473: %s"
          % (f.getName() if f else "NONE"))
    if f:
        ent = int(f.getEntryPoint().getOffset())
        src = dec(ent)
        print("### %#x len(src)=%d" % (ent, len(src)))
        print(src)
    else:
        # not inside a recognised function; dump the surrounding vtable-ish data
        print("raw around 0x18014e460..0x18014e4e0:")
        print(read_bytes(0x18014E460, 0x80).hex())
except Exception:
    traceback.print_exc()
