"""What sets the gate bytes, and what are they born as?

The IS_* keys read single bytes in a contiguous block inside FutDataManagerImpl:
  0x1fd2e tradingEnabled   0x1fd2f storeEnabled  0x1fd30 storeEnabled_JP
  0x1fd3a friendlySeasons  0x1fd3b tournamentQuit  0x1fd3c processingState
  0x1fd3d draftMode        0x1fd3f storyModeReward  0x1fd40 returningUserRewards
These are NOT the int fields the /settings parser fills, so something copies
across. Two questions, and the second is the one that decides whether an empty
configs array blocks Seasons:

  (1) who WRITES these bytes (the applier, and the constructor default)
  (2) what value does the constructor give them

CONTROL: 0x1fd2f storeEnabled. Its screen works today under an empty configs
array, so whatever the ctor gives it is a non-blocking default, and any other
byte born the same way is equally non-blocking.
"""
import re, struct

OFFS = {0x1FD2E: "tradingEnabled", 0x1FD2F: "storeEnabled (CONTROL)",
        0x1FD30: "storeEnabled_JP", 0x1FD3A: "friendlySeasonsEnabled",
        0x1FD3B: "tournamentQuitEnabled", 0x1FD3C: "processingStateEnabled",
        0x1FD3D: "enableDraftMode", 0x1FD3F: "storyModeRewardEnabled",
        0x1FD40: "returningUserRewardsScreenEnabled"}

print("#" * 78)
print("# (1) every function whose code embeds one of these offsets")
print("#" * 78)
for off, name in sorted(OFFS.items()):
    pat = struct.pack("<I", off)
    fns = {}
    for h in find_all(pat, blocks=(".text",)):
        f = fm.getFunctionContaining(addr(h))
        key = int(f.getEntryPoint().getOffset()) if f else 0
        fns.setdefault(key, []).append(h)
    print("\n  %#x %s" % (off, name))
    for a, hs in sorted(fns.items()):
        label = fname(a) if a else "(no function)"
        print("      %-16s %s  at %s" % (hex(a) if a else "-", label,
                                         ", ".join(hex(x) for x in hs)))

print("\n\n" + "#" * 78)
print("# (2) the FutDataManagerImpl ctor, every line touching this block")
print("#" * 78)
src = dec(0x18010CDC0)
print("  (ctor decompile is %d chars; ALL of it is scanned below)" % len(src))
hit = False
for i, line in enumerate(src.splitlines()):
    if re.search(r"0x1fd[0-9a-f][0-9a-f]", line):
        print("   %5d | %s" % (i, line.strip()))
        hit = True
if not hit:
    print("   NO line in the ctor mentions this block.")
    print("   That is a POSITIVE finding only if the whole ctor was scanned, and it")
    print("   was (see char count). It means the bytes are zero-initialised by the")
    print("   allocator or set elsewhere -- resolve via the writers in (1).")
