"""probe_imgtex.py Walk s_Resources, find ImgTex entries (vfptr=0x007cab04 — GR-view). Split live vs lost, sample which fields are still non-NULL when "lost". ImgTex members (primary-relative): +0x58 m_SourceLevels.m_data (SmartArray) => entry+0x28 (heap buffer) +0x5c m_SourceLevels.m_sizeAndDeallocate => entry+0x2c +0x60 m_SourceLevels.m_num => entry+0x30 +0x64 m_pImageData (RenderSurface*) => entry+0x34 (PurgeResource releases) +0x68 m_pPalette (Palette*) => entry+0x38 (PurgeResource MISSES) +0x6c m_cPitch +0x70 m_TextureCode (8 bytes) +0x78 m_pD3DTexture => entry+0x48 (PurgeResource releases) +0x7c m_pRenderTexture => entry+0x4c (PurgeResource releases) +0x80 m_pSystemMemTexture => entry+0x50 (PurgeResource MISSES) """ import ctypes, ctypes.wintypes as wt, sys, struct PROCESS_VM_READ = 0x10 PROCESS_QUERY_INFORMATION = 0x400 k = ctypes.windll.kernel32 k.OpenProcess.argtypes = [wt.DWORD, wt.BOOL, wt.DWORD]; k.OpenProcess.restype = wt.HANDLE k.ReadProcessMemory.argtypes = [wt.HANDLE, wt.LPCVOID, wt.LPVOID, ctypes.c_size_t, ctypes.POINTER(ctypes.c_size_t)] k.ReadProcessMemory.restype = wt.BOOL S_RESOURCES_M_DATA = 0x008398C4 S_RESOURCES_M_NUM = 0x008398CC IMGTEX_GR_VTABLE = 0x007cab04 def rd_u32(h, va): buf = (ctypes.c_ubyte * 4)(); sz = ctypes.c_size_t(0) if not k.ReadProcessMemory(h, va, buf, 4, ctypes.byref(sz)) or sz.value != 4: return None return struct.unpack('