"""Dump candidate camera write sites on 6AA2213C. 11/09/2026."""
from __future__ import annotations

import ctypes
import ctypes.wintypes as w
import struct
import sys

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, n):
    buf = (ctypes.c_ubyte * n)()
    got = ctypes.c_size_t(0)
    if not k32.ReadProcessMemory(h, ctypes.c_void_p(addr), buf, n, ctypes.byref(got)):
        return None
    return bytes(buf[: got.value])


def dump(h, addr, n, label):
    b = rpm(h, addr, n)
    print(f"\n=== {label} @ {addr:#x} ===", flush=True)
    if not b:
        print("unreadable", flush=True)
        return b
    for i in range(0, len(b), 16):
        hx = " ".join(f"{x:02x}" for x in b[i:i + 16])
        print(f"  {addr+i:016x}  {hx}", flush=True)
    return b


def scan_rip(h, blob, blob_va):
    i = 0
    while i + 7 <= len(blob):
        if blob[i] in (0x48, 0x4C) and blob[i + 1] in (0x8B, 0x8D) and blob[i + 2] in (
            0x05, 0x0D, 0x15, 0x1D, 0x25, 0x2D, 0x35, 0x3D
        ):
            disp = struct.unpack_from("<i", blob, i + 3)[0]
            va = blob_va + i
            slot = va + 7 + disp
            pb = rpm(h, slot, 8)
            val = struct.unpack("<Q", pb)[0] if pb else 0
            print(f"  rip {va:#x} slot={slot:#x} *={val:#x}", flush=True)
            if 0x10000 < val < 0x00007FFFFFFFFFFF:
                obj = rpm(h, val, 0x50)
                if obj:
                    vt = struct.unpack_from("<Q", obj, 0)[0]
                    cur, mn, mx, fov, zn, zf = struct.unpack_from("<ffffff", obj, 0x2C)
                    print(
                        f"    obj vt={vt:#x} cur={cur:.2f} min={mn:.2f} max={mx:.2f} "
                        f"fov={fov:.4f} zn={zn:.3f} zf={zf:.1f}",
                        flush=True,
                    )
            i += 7
            continue
        i += 1


def main():
    pid = int(sys.argv[1]) if len(sys.argv) > 1 else 3132
    h = k32.OpenProcess(0x410, False, pid)
    sites = [
        (0x7FF6AFE82380, 0x180, "store rdi+2C / rdi+34 cluster"),
        (0x7FF6AFDCAD20, 0x80, "store rdi+34 then comiss"),
        (0x7FF6AFDCA5E0, 0x100, "store rcx+34 cluster"),
        (0x7FF6AFE69C20, 0xC0, "known cmp +2F maxDistance"),
        (0x7FF6AFD47870, 0x60, "store rbx+34 comiss"),
    ]
    for addr, n, label in sites:
        b = dump(h, addr, n, label)
        if b:
            scan_rip(h, b, addr)


if __name__ == "__main__":
    main()
