"""The kill switch: resp+0x17c. userInfo deser base is resp+0xd8, so the byte is
userInfo_struct + 0xa4. Find (a) its default in the userInfo init FUN_18010ea80 and
(b) which atom writes it in the userInfo deser FUN_18013ec10.

WHY IT MATTERS: the response ctor defaults tradingEnabled (resp+0x50) to 1, yet
model+0x1fd2e reads 0 live while we serve {"configs": []}. The settings deser only
touches resp+0x50 via atom 0x336, which we never send. The ONLY other writer is
    if (*(char *)(resp + 0x17c) != 0) *(u32 *)(resp + 0x50) = 0;
at the tail of FUN_180174630. So that branch is taken. Something sets +0x17c.

CONTROL for the offset arithmetic: resp+0x2f4 has ctor default 1 and is read by the
callback as *(u8*)(resp+0x2f4); the outer parser sets it to 0 in case 0x2cf. That is
an independently visible byte field in the same object, confirming that single-byte
fields in this struct are addressed exactly the way I am reading +0x17c.
"""
import traceback
for a, tag in [(0x18010ea80, "userInfo sub-struct init (resp+0xd8)"),
               (0x18013ec10, "userInfo deserialiser")]:
    try:
        s = dec(a, 300)
        print("\n\n########## %#x %s len=%d ##########" % (a, tag, len(s)))
        print(s)
    except Exception:
        traceback.print_exc()
