local key = require 'vkeys'
local ffi = require 'ffi'
ffi.cdef[[
typedef unsigned long DWORD;
struct d3ddeviceVTBL {
void *QueryInterface;
void *AddRef;
void *Release;
void *TestCooperativeLevel;
void *GetAvailableTextureMem;
void *EvictManagedResources;
void *GetDirect3D;
void *GetDeviceCaps;
void *GetDisplayMode;
void *GetCreationParameters;
void *SetCursorProperties;
void *SetCursorPosition;
void *ShowCursor;
void *CreateAdditionalSwapChain;
void *GetSwapChain;
void *GetNumberOfSwapChains;
void *Reset;
void *Present;
void *GetBackBuffer;
void *GetRasterStatus;
void *SetDialogBoxMode;
void *SetGammaRamp;
void *GetGammaRamp;
void *CreateTexture;
void *CreateVolumeTexture;
void *CreateCubeTexture;
void *CreateVertexBuffer;
void *CreateIndexBuffer;
void *CreateRenderTarget;
void *CreateDepthStencilSurface;
void *UpdateSurface;
void *UpdateTexture;
void *GetRenderTargetData;
void *GetFrontBufferData;
void *StretchRect;
void *ColorFill;
void *CreateOffscreenPlainSurface;
void *SetRenderTarget;
void *GetRenderTarget;
void *SetDepthStencilSurface;
void *GetDepthStencilSurface;
void *BeginScene;
void *EndScene;
void *Clear;
void *SetTransform;
void *GetTransform;
void *MultiplyTransform;
void *SetViewport;
void *GetViewport;
void *SetMaterial;
void *GetMaterial;
void *SetLight;
void *GetLight;
void *LightEnable;
void *GetLightEnable;
void *SetClipPlane;
void *GetClipPlane;
void *SetRenderState;
void *GetRenderState;
void *CreateStateBlock;
void *BeginStateBlock;
void *EndStateBlock;
void *SetClipStatus;
void *GetClipStatus;
void *GetTexture;
void *SetTexture;
void *GetTextureStageState;
void *SetTextureStageState;
void *GetSamplerState;
void *SetSamplerState;
void *ValidateDevice;
void *SetPaletteEntries;
void *GetPaletteEntries;
void *SetCurrentTexturePalette;
void *GetCurrentTexturePalette;
void *SetScissorRect;
void *GetScissorRect;
void *SetSoftwareVertexProcessing;
void *GetSoftwareVertexProcessing;
void *SetNPatchMode;
void *GetNPatchMode;
void *DrawPrimitive;
void* DrawIndexedPrimitive;
void *DrawPrimitiveUP;
void *DrawIndexedPrimitiveUP;
void *ProcessVertices;
void *CreateVertexDeclaration;
void *SetVertexDeclaration;
void *GetVertexDeclaration;
void *SetFVF;
void *GetFVF;
void *CreateVertexShader;
void *SetVertexShader;
void *GetVertexShader;
void *SetVertexShaderConstantF;
void *GetVertexShaderConstantF;
void *SetVertexShaderConstantI;
void *GetVertexShaderConstantI;
void *SetVertexShaderConstantB;
void *GetVertexShaderConstantB;
void *SetStreamSource;
void *GetStreamSource;
void *SetStreamSourceFreq;
void *GetStreamSourceFreq;
void *SetIndices;
void *GetIndices;
void *CreatePixelShader;
void *SetPixelShader;
void *GetPixelShader;
void *SetPixelShaderConstantF;
void *GetPixelShaderConstantF;
void *SetPixelShaderConstantI;
void *GetPixelShaderConstantI;
void *SetPixelShaderConstantB;
void *GetPixelShaderConstantB;
void *DrawRectPatch;
void *DrawTriPatch;
void *DeletePatch;
};
struct d3ddevice {
struct d3ddeviceVTBL** vtbl;
};
struct RECT {
long left;
long top;
long right;
long bottom;
};
struct POINT {
long x;
long y;
};
int __stdcall GetSystemMetrics(
int nIndex
);
int __stdcall GetClientRect(
int hWnd,
struct RECT* lpRect
);
int __stdcall ClientToScreen(
int hWnd,
struct POINT* lpPoint
);
int __stdcall D3DXSaveSurfaceToFileA(
const char* pDestFile,
int DestFormat,
void* pSrcSurface,
void* pSrcPalette,
struct RECT *pSrcRect
);
]]
local d3dx9_43 = ffi.load('d3dx9_43.dll')
function main()
sampRegisterChatCommand("mycmd", cmd_mycmd)
wait(-1)
end
function cmd_mycmd(arg)
local pDevice = ffi.cast("struct d3ddevice*", 0xC97C28)
local CreateOffscreenPlainSurface = ffi.cast("long(__stdcall*)(void*, unsigned long, unsigned long, unsigned long, unsigned long, void**, void*)", pDevice.vtbl[0].CreateOffscreenPlainSurface)
local GetFrontBufferData = ffi.cast("long(__stdcall*)(void*, unsigned long, void*)", pDevice.vtbl[0].GetFrontBufferData)
local pSurface = ffi.cast("void**", ffi.new('unsigned long[1]'))
local sx = ffi.C.GetSystemMetrics(0);
local sy = ffi.C.GetSystemMetrics(1);
CreateOffscreenPlainSurface(pDevice, sx, sy, 21, 3, pSurface, ffi.cast("void*", 0))
if GetFrontBufferData(pDevice, 0, pSurface[0]) < 0 then
print("Screenshot cannot be created")
else
local Point = ffi.new("struct POINT[1]")
local Rect = ffi.new("struct RECT[1]")
local HWND = ffi.cast("int*", 0xC97C1C)[0]
ffi.C.ClientToScreen(HWND, Point)
ffi.C.GetClientRect(HWND, Rect)
Rect[0].left = Rect[0].left + Point[0].x
Rect[0].right = Rect[0].right + Point[0].x
Rect[0].top = Rect[0].top + Point[0].y
Rect[0].bottom = Rect[0].bottom + Point[0].y
d3dx9_43.D3DXSaveSurfaceToFileA("filename.png", 3, pSurface[0], ffi.cast("void*", 0), Rect) -- second parameter(3) is D3DXIMAGE_FILEFORMAT, checkout https://docs.microsoft.com/en-us/windows/win32/direct3d9/d3dximage-fileformat
end
end