import sys, struct, ctypes

output_file = r"C:\Projects\JX\logs\inspect_candidate_output.txt"

def run():
    lines = []
    def log(msg):
        print(msg)
        lines.append(str(msg))

    kernel32 = ctypes.windll.kernel32
    advapi32 = ctypes.windll.advapi32

    # Enable SeDebugPrivilege
    from ctypes import wintypes
    hToken = wintypes.HANDLE()
    if advapi32.OpenProcessToken(kernel32.GetCurrentProcess(), 0x0020 | 0x0008, ctypes.byref(hToken)):
        luid = wintypes.LARGE_INTEGER()
        if advapi32.LookupPrivilegeValueW(None, "SeDebugPrivilege", ctypes.byref(luid)):
            class TP(ctypes.Structure):
                _fields_ = [('Count', wintypes.DWORD), ('Luid', wintypes.LARGE_INTEGER), ('Attr', wintypes.DWORD)]
            tp = TP(1, luid, 2)
            advapi32.AdjustTokenPrivileges(hToken, False, ctypes.byref(tp), ctypes.sizeof(tp), None, None)
        kernel32.CloseHandle(hToken)

    pid = 32572
    hProc = kernel32.OpenProcess(0x0010 | 0x0400 | 0x0008, False, pid)
    if not hProc:
        log(f"Cannot open PID {pid}")
        return

    candidates = [
        0x00734957,
        0x10B786BC,
        0x10B88974,
        0x2D23C774,
        0x2D23C7E1,
        0x2D23C8B2
    ]

    bytesRead = ctypes.c_size_t()

    for cand in candidates:
        base = cand - 256
        size = 512
        buf = (ctypes.c_char * size)()
        if kernel32.ReadProcessMemory(hProc, ctypes.c_void_p(base), buf, size, ctypes.byref(bytesRead)):
            data = bytes(buf)[:bytesRead.value]
            log(f"\n=======================================================")
            log(f"INSPECTING CANDIDATE: 0x{cand:08X} (Dump range: 0x{base:08X} - 0x{base+size:08X})")
            log(f"=======================================================")
            
            # Print as 4-byte integers aligned
            # First let's find alignment of cand
            for offset in range(0, len(data) - 4, 4):
                addr = base + offset
                rel = addr - cand
                val_i32 = struct.unpack_from('<i', data, offset)[0]
                val_u16 = struct.unpack_from('<H', data, offset)[0]
                val_u16_hi = struct.unpack_from('<H', data, offset + 2)[0]
                
                tags = []
                if val_i32 == 3215 or val_u16 == 3215: tags.append("HP: 3215")
                if val_i32 == 846 or val_u16 == 846: tags.append("STAMINA: 846")
                if val_i32 == 924 or val_u16 == 924: tags.append("MAX MANA: 924")
                if 700 <= val_i32 <= 950: tags.append(f"MANA?: {val_i32}")
                if 700 <= val_u16 <= 950: tags.append(f"MANA_u16?: {val_u16}")
                
                tag_str = " <=== " + ", ".join(tags) if tags else ""
                log(f"  0x{addr:08X} [{rel:+4d}]: i32 = {val_i32:<10} | u16 = ({val_u16:<5}, {val_u16_hi:<5}){tag_str}")

    kernel32.CloseHandle(hProc)

    with open(output_file, 'w', encoding='utf-8') as f:
        f.write("\n".join(lines))
    print("Done inspecting.")

if __name__ == '__main__':
    run()
