"""Dump unique caller of camera-copy. 11/09/2026."""
from __future__ import annotations

import ctypes
import ctypes.wintypes as w
import struct

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} ===")
    if not b:
        print("unreadable")
        return
    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}")
    i = 0
    while i + 7 <= len(b):
        if b[i] in (0x48, 0x4C) and b[i + 1] in (0x8B, 0x8D) and b[i + 2] in (
            0x05, 0x0D, 0x15, 0x1D, 0x25, 0x2D, 0x35, 0x3D
        ):
            disp = struct.unpack_from("<i", b, i + 3)[0]
            va = addr + 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}")
            if 0x10000 < val < 0x00007FFFFFFFFFFF:
                obj = rpm(h, val, 0x50)
                if obj:
                    vt = struct.unpack_from("<Q", obj, 0)[0]
                    floats = struct.unpack_from("<ffffff", obj, 0x2C)
                    print(
                        f"    obj vt={vt:#x} cur={floats[0]:.2f} min={floats[1]:.2f} "
                        f"max={floats[2]:.2f} fov={floats[3]:.4f} zn={floats[4]:.3f} zf={floats[5]:.1f}"
                    )
                    # also try deref as pointer to camera
                    if 0x10000 < vt < 0x00007FFFFFFFFFFF:
                        inner = rpm(h, vt, 0x50)
                        if inner:
                            vt2 = struct.unpack_from("<Q", inner, 0)[0]
                            f2 = struct.unpack_from("<ffffff", inner, 0x2C)
                            print(
                                f"    deref vt={vt2:#x} cur={f2[0]:.2f} min={f2[1]:.2f} "
                                f"max={f2[2]:.2f} fov={f2[3]:.4f}"
                            )
            i += 7
            continue
        i += 1


def main():
    h = k32.OpenProcess(0x410, False, 3132)
    dump(h, 0x7FF6AFE82100, 0x200, "caller of camera-copy")
    dump(h, 0x7FF6AFE82080, 0x80, "fn start guess")


if __name__ == "__main__":
    main()
