"""Inspect real POE2 Camera object at 0x48514f60e00.
"""
import ctypes
import ctypes.wintypes as w
import struct
import subprocess

k32 = ctypes.WinDLL("kernel32", use_last_error=True)
k32.OpenProcess.restype = w.HANDLE
k32.ReadProcessMemory.argtypes = [
    w.HANDLE, ctypes.c_void_p, ctypes.c_void_p, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)
]
k32.ReadProcessMemory.restype = w.BOOL

def rpm(h, addr, size):
    buf = (ctypes.c_ubyte * size)()
    got = ctypes.c_size_t(0)
    if not k32.ReadProcessMemory(h, ctypes.c_void_p(addr), buf, size, ctypes.byref(got)):
        return None
    return bytes(buf[: got.value])

out = subprocess.check_output(['powershell', '-Command', '(Get-Process -Name *PathOfExile*).Id'])
pid = int(out.decode().split()[0])
h = k32.OpenProcess(0x1F0FFF, False, pid)

cam_addr = 0x48514f60e00
b = rpm(h, cam_addr, 0x600)
if not b:
    print("Failed to read camera")
    exit(1)

print(f"=== POE2 CAMERA DUMP @ {cam_addr:#x} ===")
vtable = struct.unpack_from("<Q", b, 0)[0]
print(f"Vtable: {vtable:#x}")

# Print Matrix4x4 at +0x1A0
print("\n--- WorldToScreen Matrix at +0x1A0 ---")
for r in range(4):
    row = [struct.unpack_from("<f", b, 0x1A0 + r * 16 + c * 4)[0] for c in range(4)]
    print(f"  [{row[0]:10.4f}, {row[1]:10.4f}, {row[2]:10.4f}, {row[3]:10.4f}]")

# Print Zoom at +0x528
z528 = struct.unpack_from("<f", b, 0x528)[0]
print(f"\nZoom @ +0x528: {z528}")

# Scan all floats in camera object
print("\n--- Significant float fields in Camera ---")
for off in range(0, 0x600, 4):
    val = struct.unpack_from("<f", b, off)[0]
    if -5000.0 <= val <= 5000.0 and abs(val) > 0.001 and val != 0.0:
        # filter out denormals / inf / nan
        if abs(val) < 1e5 and not (1e-6 < abs(val) < 1e-3):
            print(f"  +{off:#04x}: {val:12.4f}")

