import ctypes
from ctypes import wintypes
import struct

PROCESS_ALL_ACCESS = 0x1F0FFF

kernel32 = ctypes.windll.kernel32
OpenProcess = kernel32.OpenProcess
ReadProcessMemory = kernel32.ReadProcessMemory
WriteProcessMemory = kernel32.WriteProcessMemory
CloseHandle = kernel32.CloseHandle

def rpm(h_process, addr, size):
    buf = ctypes.create_string_buffer(size)
    bytes_read = ctypes.c_size_t(0)
    if ReadProcessMemory(h_process, ctypes.c_void_p(addr), buf, size, ctypes.byref(bytes_read)):
        return buf.raw
    return None

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

# PID 43084
pid = 43084
h_proc = OpenProcess(PROCESS_ALL_ACCESS, False, pid)
print(f"OpenProcess: {h_proc}")

# Base: 0x7FF6AFC20000
mod_base = 0x7FF6AFC20000
in_game_state_rva = 0x4430108
igs = rpm_u64(h_proc, mod_base + in_game_state_rva)
print(f"InGameState: {hex(igs)}")

area_instance_290 = rpm_u64(h_proc, igs + 0x290)
area_instance_2a0 = rpm_u64(h_proc, igs + 0x2A0)
print(f"AreaInstance (+0x290): {hex(area_instance_290)}")
print(f"AreaInstance (+0x2a0): {hex(area_instance_2a0)}")

area = area_instance_290 if area_instance_290 > 0x10000 else area_instance_2a0
print(f"Using AreaInstance: {hex(area)}")

# Check buffers around 0x980 .. 0xa50
offsets = [0x980, 0x998, 0x9a0, 0x9b8, 0x9d0, 0x9e8, 0xa00, 0xa18, 0xa30]
for off in offsets:
    start = rpm_u64(h_proc, area + off)
    end = rpm_u64(h_proc, area + off + 8)
    cap = rpm_u64(h_proc, area + off + 16)
    sz = (end - start) if (start and end and end >= start) else 0
    if 1000 < sz < 20000000:
        first_16 = rpm(h_proc, start, 16)
        hex_str = first_16.hex() if first_16 else "fail"
        # Sample non-zero count in first 10000 bytes
        sample_sz = min(sz, 10000)
        sample = rpm(h_proc, start, sample_sz)
        nz = sum(1 for b in sample if b != 0) if sample else 0
        pct = (nz / sample_sz) * 100 if sample_sz else 0
        print(f"Offset +{hex(off)}: start={hex(start)}, end={hex(end)}, size={sz:,} bytes | non-zero: {pct:.1f}% | first16: {hex_str}")
    else:
        print(f"Offset +{hex(off)}: invalid (sz={sz})")

CloseHandle(h_proc)
