import ctypes
import struct

k32 = ctypes.windll.kernel32
pid = 43084
h = k32.OpenProcess(0x10 | 0x400, False, pid)
assert h, "cannot open process"

ingame = 0x2AF3CDF0558
br = ctypes.c_size_t()

def rpm(addr, size):
    buf = (ctypes.c_char * size)()
    if k32.ReadProcessMemory(h, ctypes.c_void_p(addr), buf, size, ctypes.byref(br)):
        return bytes(buf)
    return None

data = rpm(ingame, 0x1000)
for off in range(0, 0x1000, 8):
    q = struct.unpack_from('<Q', data, off)[0]
    if 0x10000 <= q <= 0x7FFFFFFFFFFF:
        sub = rpm(q, 64)
        if sub:
            sub_q = struct.unpack_from('<Q', sub, 0)[0]
            s = ""
            for c in sub[:64]:
                if 0x20 <= c <= 0x7E:
                    s += chr(c)
                elif c == 0:
                    break
            # also check wide string
            ws = ""
            for i in range(0, 64, 2):
                wc = struct.unpack_from('<H', sub, i)[0]
                if 0x20 <= wc <= 0x7E:
                    ws += chr(wc)
                elif wc == 0:
                    break
            info = f"sub_q=0x{sub_q:X}"
            if len(s) >= 3:
                info += f' str="{s}"'
            if len(ws) >= 3 and len(ws) > len(s):
                info += f' wstr="{ws}"'
            print(f"InGameState+0x{off:03X}: 0x{q:012X} -> {info}")

k32.CloseHandle(h)
