import ctypes
import struct

PROCESS_ALL_ACCESS = 0x1F0FFF
kernel32 = ctypes.windll.kernel32
hProc = kernel32.OpenProcess(PROCESS_ALL_ACCESS, False, 43084)

def rpm(addr, size):
    buf = (ctypes.c_char * size)()
    read = ctypes.c_size_t()
    if kernel32.ReadProcessMemory(hProc, ctypes.c_uint64(addr), buf, size, ctypes.byref(read)):
        return bytes(buf[:read.value])
    return b""

def rpm_u64(addr):
    b = rpm(addr, 8)
    return struct.unpack("<Q", b)[0] if len(b) == 8 else 0

def rpm_u32(addr):
    b = rpm(addr, 4)
    return struct.unpack("<I", b)[0] if len(b) == 4 else 0

def rpm_f32(addr):
    b = rpm(addr, 4)
    return struct.unpack("<f", b)[0] if len(b) == 4 else 0.0

area_instance = 0x2AFF1831800
print(f"AreaInstance @ 0x{area_instance:X}")

# Inspect first 0x800 bytes of AreaInstance
for off in range(0x0, 0x500, 8):
    val = rpm_u64(area_instance + off)
    val32_0 = rpm_u32(area_instance + off)
    val32_1 = rpm_u32(area_instance + off + 4)
    f0 = rpm_f32(area_instance + off)
    f1 = rpm_f32(area_instance + off + 4)
    
    # Check if pointer
    if 0x100000000 <= val <= 0x7FFFFFFFFFFF:
        # Check size of buffer if std::vector
        p_end = rpm_u64(area_instance + off + 8)
        sz = (p_end - val) if (p_end >= val and p_end - val < 100000000) else 0
        extra = f" (sz={sz})" if sz > 0 else ""
        print(f"  +0x{off:03X} -> ptr: 0x{val:X}{extra}")
    elif 50 <= val32_0 <= 5000 and 50 <= val32_1 <= 5000:
        print(f"  +0x{off:03X} -> grid dims? cols={val32_0}, rows={val32_1}")
    elif 0.1 <= f0 <= 10.0 and 0.1 <= f1 <= 10.0:
        print(f"  +0x{off:03X} -> floats? {f0:.3f}, {f1:.3f}")

kernel32.CloseHandle(hProc)
