2020-12-02 16:19:16 -05:00
|
|
|
/* Slightly modified version of https://github.com/Rebzzel/kiero
|
|
|
|
|
|
|
|
MIT License
|
|
|
|
|
|
|
|
Copyright(c) 2014 - 2020 Rebzzel
|
|
|
|
|
|
|
|
Permission is hereby granted, free of charge, to any person obtaining a copy
|
|
|
|
of this software and associated documentation files(the "Software"), to deal
|
|
|
|
in the Software without restriction, including without limitation the rights
|
|
|
|
to use, copy, modify, merge, publish, distribute, sublicense, and / or sell
|
|
|
|
copies of the Software, and to permit persons to whom the Software is
|
|
|
|
furnished to do so, subject to the following conditions :
|
|
|
|
|
|
|
|
The above copyright notice and this permission notice shall be included in all
|
|
|
|
copies or substantial portions of the Software.
|
|
|
|
|
|
|
|
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
|
|
|
|
IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
|
|
|
FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.IN NO EVENT SHALL THE
|
|
|
|
AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
|
|
|
|
LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
|
|
|
OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
|
|
|
|
SOFTWARE.
|
|
|
|
*/
|
|
|
|
|
|
|
|
#include "kiero.h"
|
|
|
|
#include <Windows.h>
|
|
|
|
#include <assert.h>
|
|
|
|
#include "Renderware.h"
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_D3D9
|
|
|
|
# include <d3d9.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_D3D10
|
|
|
|
# include <dxgi.h>
|
|
|
|
# include <d3d10_1.h>
|
|
|
|
# include <d3d10.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_D3D11
|
|
|
|
# include <dxgi.h>
|
|
|
|
# include <d3d11.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_D3D12
|
|
|
|
# include <dxgi.h>
|
|
|
|
# include <d3d12.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_OPENGL
|
|
|
|
# include <gl/GL.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_INCLUDE_VULKAN
|
|
|
|
# include <vulkan/vulkan.h>
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
2021-01-07 16:28:48 -05:00
|
|
|
#include "minhook/MinHook.h"
|
2020-12-02 16:19:16 -05:00
|
|
|
#endif
|
|
|
|
|
|
|
|
#ifdef _UNICODE
|
|
|
|
# define KIERO_TEXT(text) L##text
|
|
|
|
#else
|
|
|
|
# define KIERO_TEXT(text) text
|
|
|
|
#endif
|
|
|
|
|
|
|
|
#define KIERO_ARRAY_SIZE(arr) ((size_t)(sizeof(arr)/sizeof(arr[0])))
|
|
|
|
|
|
|
|
static kiero::RenderType::Enum g_renderType = kiero::RenderType::None;
|
|
|
|
static uint150_t* g_methodsTable = NULL;
|
|
|
|
|
|
|
|
kiero::Status::Enum kiero::init(RenderType::Enum _renderType)
|
|
|
|
{
|
|
|
|
if (g_renderType != RenderType::None)
|
|
|
|
{
|
|
|
|
return Status::AlreadyInitializedError;
|
|
|
|
}
|
|
|
|
|
|
|
|
if (_renderType != RenderType::None)
|
|
|
|
{
|
|
|
|
if (_renderType >= RenderType::D3D9 && _renderType <= RenderType::D3D12)
|
|
|
|
{
|
|
|
|
if (_renderType == RenderType::D3D9)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_D3D9
|
|
|
|
|
|
|
|
if (GetModuleHandle(KIERO_TEXT("d3d9.dll")) == NULL)
|
|
|
|
{
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(119, sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable, *(uint150_t**)GetD3DDevice(), 119 * sizeof(uint150_t));
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
g_renderType = RenderType::D3D9;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (_renderType == RenderType::D3D10)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_D3D10
|
|
|
|
HMODULE libDXGI;
|
|
|
|
HMODULE libD3D10;
|
|
|
|
if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D10 = ::GetModuleHandle(KIERO_TEXT("d3d10.dll"))) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* CreateDXGIFactory;
|
|
|
|
if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDXGIFactory* factory;
|
|
|
|
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDXGIAdapter* adapter;
|
|
|
|
if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* D3D10CreateDeviceAndSwapChain;
|
|
|
|
if ((D3D10CreateDeviceAndSwapChain = ::GetProcAddress(libD3D10, "D3D10CreateDeviceAndSwapChain")) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
DXGI_RATIONAL refreshRate;
|
|
|
|
refreshRate.Numerator = 60;
|
|
|
|
refreshRate.Denominator = 1;
|
|
|
|
|
|
|
|
DXGI_MODE_DESC bufferDesc;
|
|
|
|
bufferDesc.Width = 100;
|
|
|
|
bufferDesc.Height = 100;
|
|
|
|
bufferDesc.RefreshRate = refreshRate;
|
|
|
|
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
|
|
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
|
|
|
|
|
|
DXGI_SAMPLE_DESC sampleDesc;
|
|
|
|
sampleDesc.Count = 1;
|
|
|
|
sampleDesc.Quality = 0;
|
|
|
|
|
|
|
|
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
|
|
|
swapChainDesc.BufferDesc = bufferDesc;
|
|
|
|
swapChainDesc.SampleDesc = sampleDesc;
|
|
|
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
swapChainDesc.BufferCount = 1;
|
|
|
|
swapChainDesc.OutputWindow = window;
|
|
|
|
swapChainDesc.Windowed = 1;
|
|
|
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
|
|
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
|
|
|
|
|
|
IDXGISwapChain* swapChain;
|
|
|
|
ID3D10Device* device;
|
|
|
|
|
|
|
|
if (((long(__stdcall*)(
|
|
|
|
IDXGIAdapter*,
|
|
|
|
D3D10_DRIVER_TYPE,
|
|
|
|
HMODULE,
|
|
|
|
UINT,
|
|
|
|
UINT,
|
|
|
|
DXGI_SWAP_CHAIN_DESC*,
|
|
|
|
IDXGISwapChain**,
|
|
|
|
ID3D10Device**))(D3D10CreateDeviceAndSwapChain))(adapter, D3D10_DRIVER_TYPE_HARDWARE, NULL, 0, D3D10_SDK_VERSION, &swapChainDesc, &swapChain, &device) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(116, sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 18, *(uint150_t**)device, 98 * sizeof(uint150_t));
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
swapChain->Release();
|
|
|
|
swapChain = NULL;
|
|
|
|
|
|
|
|
device->Release();
|
|
|
|
device = NULL;
|
|
|
|
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
|
|
|
|
g_renderType = RenderType::D3D10;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (_renderType == RenderType::D3D11)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_D3D11
|
|
|
|
HMODULE libD3D11;
|
|
|
|
if ((libD3D11 = ::GetModuleHandle(KIERO_TEXT("d3d11.dll"))) == NULL)
|
|
|
|
{
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* D3D11CreateDeviceAndSwapChain;
|
|
|
|
if ((D3D11CreateDeviceAndSwapChain = ::GetProcAddress(libD3D11, "D3D11CreateDeviceAndSwapChain")) == NULL)
|
|
|
|
{
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3D_FEATURE_LEVEL featureLevel;
|
|
|
|
const D3D_FEATURE_LEVEL featureLevels[] = { D3D_FEATURE_LEVEL_10_1, D3D_FEATURE_LEVEL_11_0 };
|
|
|
|
|
|
|
|
DXGI_RATIONAL refreshRate;
|
|
|
|
refreshRate.Numerator = 60;
|
|
|
|
refreshRate.Denominator = 1;
|
|
|
|
|
|
|
|
DXGI_MODE_DESC bufferDesc;
|
|
|
|
bufferDesc.Width = 100;
|
|
|
|
bufferDesc.Height = 100;
|
|
|
|
bufferDesc.RefreshRate = refreshRate;
|
|
|
|
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
|
|
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
|
|
|
|
|
|
DXGI_SAMPLE_DESC sampleDesc;
|
|
|
|
sampleDesc.Count = 1;
|
|
|
|
sampleDesc.Quality = 0;
|
|
|
|
|
|
|
|
DXGI_SWAP_CHAIN_DESC swapChainDesc;
|
|
|
|
swapChainDesc.BufferDesc = bufferDesc;
|
|
|
|
swapChainDesc.SampleDesc = sampleDesc;
|
|
|
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
swapChainDesc.BufferCount = 1;
|
|
|
|
swapChainDesc.OutputWindow = RsGlobal.ps->window;
|
|
|
|
swapChainDesc.Windowed = 1;
|
|
|
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_DISCARD;
|
|
|
|
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
|
|
|
|
|
|
IDXGISwapChain* swapChain;
|
|
|
|
ID3D11Device* device;
|
|
|
|
ID3D11DeviceContext* context;
|
|
|
|
|
|
|
|
if (((long(__stdcall*)(
|
|
|
|
IDXGIAdapter*,
|
|
|
|
D3D_DRIVER_TYPE,
|
|
|
|
HMODULE,
|
|
|
|
UINT,
|
|
|
|
const D3D_FEATURE_LEVEL*,
|
|
|
|
UINT,
|
|
|
|
UINT,
|
|
|
|
const DXGI_SWAP_CHAIN_DESC*,
|
|
|
|
IDXGISwapChain**,
|
|
|
|
ID3D11Device**,
|
|
|
|
D3D_FEATURE_LEVEL*,
|
|
|
|
ID3D11DeviceContext**))(D3D11CreateDeviceAndSwapChain))(NULL, D3D_DRIVER_TYPE_HARDWARE, NULL, 0, featureLevels, 2, D3D11_SDK_VERSION, &swapChainDesc, &swapChain, &device, &featureLevel, &context) < 0)
|
|
|
|
{
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(205, sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 18, *(uint150_t**)device, 43 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 18 + 43, *(uint150_t**)context, 144 * sizeof(uint150_t));
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
swapChain->Release();
|
|
|
|
swapChain = NULL;
|
|
|
|
|
|
|
|
device->Release();
|
|
|
|
device = NULL;
|
|
|
|
|
|
|
|
context->Release();
|
|
|
|
context = NULL;
|
|
|
|
|
|
|
|
g_renderType = RenderType::D3D11;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (_renderType == RenderType::D3D12)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_D3D12
|
|
|
|
HMODULE libDXGI;
|
|
|
|
HMODULE libD3D12;
|
|
|
|
if ((libDXGI = ::GetModuleHandle(KIERO_TEXT("dxgi.dll"))) == NULL || (libD3D12 = ::GetModuleHandle(KIERO_TEXT("d3d12.dll"))) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* CreateDXGIFactory;
|
|
|
|
if ((CreateDXGIFactory = ::GetProcAddress(libDXGI, "CreateDXGIFactory")) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDXGIFactory* factory;
|
|
|
|
if (((long(__stdcall*)(const IID&, void**))(CreateDXGIFactory))(__uuidof(IDXGIFactory), (void**)&factory) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
IDXGIAdapter* adapter;
|
|
|
|
if (factory->EnumAdapters(0, &adapter) == DXGI_ERROR_NOT_FOUND)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void* D3D12CreateDevice;
|
|
|
|
if ((D3D12CreateDevice = ::GetProcAddress(libD3D12, "D3D12CreateDevice")) == NULL)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D12Device* device;
|
|
|
|
if (((long(__stdcall*)(IUnknown*, D3D_FEATURE_LEVEL, const IID&, void**))(D3D12CreateDevice))(adapter, D3D_FEATURE_LEVEL_11_0, __uuidof(ID3D12Device), (void**)&device) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
D3D12_COMMAND_QUEUE_DESC queueDesc;
|
|
|
|
queueDesc.Type = D3D12_COMMAND_LIST_TYPE_DIRECT;
|
|
|
|
queueDesc.Priority = 0;
|
|
|
|
queueDesc.Flags = D3D12_COMMAND_QUEUE_FLAG_NONE;
|
|
|
|
queueDesc.NodeMask = 0;
|
|
|
|
|
|
|
|
ID3D12CommandQueue* commandQueue;
|
|
|
|
if (device->CreateCommandQueue(&queueDesc, __uuidof(ID3D12CommandQueue), (void**)&commandQueue) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D12CommandAllocator* commandAllocator;
|
|
|
|
if (device->CreateCommandAllocator(D3D12_COMMAND_LIST_TYPE_DIRECT, __uuidof(ID3D12CommandAllocator), (void**)&commandAllocator) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
ID3D12GraphicsCommandList* commandList;
|
|
|
|
if (device->CreateCommandList(0, D3D12_COMMAND_LIST_TYPE_DIRECT, commandAllocator, NULL, __uuidof(ID3D12GraphicsCommandList), (void**)&commandList) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
DXGI_RATIONAL refreshRate;
|
|
|
|
refreshRate.Numerator = 60;
|
|
|
|
refreshRate.Denominator = 1;
|
|
|
|
|
|
|
|
DXGI_MODE_DESC bufferDesc;
|
|
|
|
bufferDesc.Width = 100;
|
|
|
|
bufferDesc.Height = 100;
|
|
|
|
bufferDesc.RefreshRate = refreshRate;
|
|
|
|
bufferDesc.Format = DXGI_FORMAT_R8G8B8A8_UNORM;
|
|
|
|
bufferDesc.ScanlineOrdering = DXGI_MODE_SCANLINE_ORDER_UNSPECIFIED;
|
|
|
|
bufferDesc.Scaling = DXGI_MODE_SCALING_UNSPECIFIED;
|
|
|
|
|
|
|
|
DXGI_SAMPLE_DESC sampleDesc;
|
|
|
|
sampleDesc.Count = 1;
|
|
|
|
sampleDesc.Quality = 0;
|
|
|
|
|
|
|
|
DXGI_SWAP_CHAIN_DESC swapChainDesc = {};
|
|
|
|
swapChainDesc.BufferDesc = bufferDesc;
|
|
|
|
swapChainDesc.SampleDesc = sampleDesc;
|
|
|
|
swapChainDesc.BufferUsage = DXGI_USAGE_RENDER_TARGET_OUTPUT;
|
|
|
|
swapChainDesc.BufferCount = 2;
|
|
|
|
swapChainDesc.OutputWindow = window;
|
|
|
|
swapChainDesc.Windowed = 1;
|
|
|
|
swapChainDesc.SwapEffect = DXGI_SWAP_EFFECT_FLIP_DISCARD;
|
|
|
|
swapChainDesc.Flags = DXGI_SWAP_CHAIN_FLAG_ALLOW_MODE_SWITCH;
|
|
|
|
|
|
|
|
IDXGISwapChain* swapChain;
|
|
|
|
if (factory->CreateSwapChain(commandQueue, &swapChainDesc, &swapChain) < 0)
|
|
|
|
{
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(150, sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable, *(uint150_t**)device, 44 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 44, *(uint150_t**)commandQueue, 19 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 44 + 19, *(uint150_t**)commandAllocator, 9 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 44 + 19 + 9, *(uint150_t**)commandList, 60 * sizeof(uint150_t));
|
|
|
|
::memcpy(g_methodsTable + 44 + 19 + 9 + 60, *(uint150_t**)swapChain, 18 * sizeof(uint150_t));
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
device->Release();
|
|
|
|
device = NULL;
|
|
|
|
|
|
|
|
commandQueue->Release();
|
|
|
|
commandQueue = NULL;
|
|
|
|
|
|
|
|
commandAllocator->Release();
|
|
|
|
commandAllocator = NULL;
|
|
|
|
|
|
|
|
commandList->Release();
|
|
|
|
commandList = NULL;
|
|
|
|
|
|
|
|
swapChain->Release();
|
|
|
|
swapChain = NULL;
|
|
|
|
|
|
|
|
::DestroyWindow(window);
|
|
|
|
::UnregisterClass(windowClass.lpszClassName, windowClass.hInstance);
|
|
|
|
|
|
|
|
g_renderType = RenderType::D3D12;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::NotSupportedError;
|
|
|
|
}
|
|
|
|
else if (_renderType != RenderType::Auto)
|
|
|
|
{
|
|
|
|
if (_renderType == RenderType::OpenGL)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_OPENGL
|
|
|
|
HMODULE libOpenGL32;
|
|
|
|
if ((libOpenGL32 = ::GetModuleHandle(KIERO_TEXT("opengl32.dll"))) == NULL)
|
|
|
|
{
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* const methodsNames[] = {
|
|
|
|
"glAccum", "glAlphaFunc", "glAreTexturesResident", "glArrayElement", "glBegin", "glBindTexture", "glBitmap", "glBlendFunc", "glCallList", "glCallLists", "glClear", "glClearAccum",
|
|
|
|
"glClearColor", "glClearDepth", "glClearIndex", "glClearStencil", "glClipPlane", "glColor3b", "glColor3bv", "glColor3d", "glColor3dv", "glColor3f", "glColor3fv", "glColor3i", "glColor3iv",
|
|
|
|
"glColor3s", "glColor3sv", "glColor3ub", "glColor3ubv", "glColor3ui", "glColor3uiv", "glColor3us", "glColor3usv", "glColor4b", "glColor4bv", "glColor4d", "glColor4dv", "glColor4f",
|
|
|
|
"glColor4fv", "glColor4i", "glColor4iv", "glColor4s", "glColor4sv", "glColor4ub", "glColor4ubv", "glColor4ui", "glColor4uiv", "glColor4us", "glColor4usv", "glColorMask", "glColorMaterial",
|
|
|
|
"glColorPointer", "glCopyPixels", "glCopyTexImage1D", "glCopyTexImage2D", "glCopyTexSubImage1D", "glCopyTexSubImage2D", "glCullFaceglCullFace", "glDeleteLists", "glDeleteTextures",
|
|
|
|
"glDepthFunc", "glDepthMask", "glDepthRange", "glDisable", "glDisableClientState", "glDrawArrays", "glDrawBuffer", "glDrawElements", "glDrawPixels", "glEdgeFlag", "glEdgeFlagPointer",
|
|
|
|
"glEdgeFlagv", "glEnable", "glEnableClientState", "glEnd", "glEndList", "glEvalCoord1d", "glEvalCoord1dv", "glEvalCoord1f", "glEvalCoord1fv", "glEvalCoord2d", "glEvalCoord2dv",
|
|
|
|
"glEvalCoord2f", "glEvalCoord2fv", "glEvalMesh1", "glEvalMesh2", "glEvalPoint1", "glEvalPoint2", "glFeedbackBuffer", "glFinish", "glFlush", "glFogf", "glFogfv", "glFogi", "glFogiv",
|
|
|
|
"glFrontFace", "glFrustum", "glGenLists", "glGenTextures", "glGetBooleanv", "glGetClipPlane", "glGetDoublev", "glGetError", "glGetFloatv", "glGetIntegerv", "glGetLightfv", "glGetLightiv",
|
|
|
|
"glGetMapdv", "glGetMapfv", "glGetMapiv", "glGetMaterialfv", "glGetMaterialiv", "glGetPixelMapfv", "glGetPixelMapuiv", "glGetPixelMapusv", "glGetPointerv", "glGetPolygonStipple",
|
|
|
|
"glGetString", "glGetTexEnvfv", "glGetTexEnviv", "glGetTexGendv", "glGetTexGenfv", "glGetTexGeniv", "glGetTexImage", "glGetTexLevelParameterfv", "glGetTexLevelParameteriv",
|
|
|
|
"glGetTexParameterfv", "glGetTexParameteriv", "glHint", "glIndexMask", "glIndexPointer", "glIndexd", "glIndexdv", "glIndexf", "glIndexfv", "glIndexi", "glIndexiv", "glIndexs", "glIndexsv",
|
|
|
|
"glIndexub", "glIndexubv", "glInitNames", "glInterleavedArrays", "glIsEnabled", "glIsList", "glIsTexture", "glLightModelf", "glLightModelfv", "glLightModeli", "glLightModeliv", "glLightf",
|
|
|
|
"glLightfv", "glLighti", "glLightiv", "glLineStipple", "glLineWidth", "glListBase", "glLoadIdentity", "glLoadMatrixd", "glLoadMatrixf", "glLoadName", "glLogicOp", "glMap1d", "glMap1f",
|
|
|
|
"glMap2d", "glMap2f", "glMapGrid1d", "glMapGrid1f", "glMapGrid2d", "glMapGrid2f", "glMaterialf", "glMaterialfv", "glMateriali", "glMaterialiv", "glMatrixMode", "glMultMatrixd",
|
|
|
|
"glMultMatrixf", "glNewList", "glNormal3b", "glNormal3bv", "glNormal3d", "glNormal3dv", "glNormal3f", "glNormal3fv", "glNormal3i", "glNormal3iv", "glNormal3s", "glNormal3sv",
|
|
|
|
"glNormalPointer", "glOrtho", "glPassThrough", "glPixelMapfv", "glPixelMapuiv", "glPixelMapusv", "glPixelStoref", "glPixelStorei", "glPixelTransferf", "glPixelTransferi", "glPixelZoom",
|
|
|
|
"glPointSize", "glPolygonMode", "glPolygonOffset", "glPolygonStipple", "glPopAttrib", "glPopClientAttrib", "glPopMatrix", "glPopName", "glPrioritizeTextures", "glPushAttrib",
|
|
|
|
"glPushClientAttrib", "glPushMatrix", "glPushName", "glRasterPos2d", "glRasterPos2dv", "glRasterPos2f", "glRasterPos2fv", "glRasterPos2i", "glRasterPos2iv", "glRasterPos2s",
|
|
|
|
"glRasterPos2sv", "glRasterPos3d", "glRasterPos3dv", "glRasterPos3f", "glRasterPos3fv", "glRasterPos3i", "glRasterPos3iv", "glRasterPos3s", "glRasterPos3sv", "glRasterPos4d",
|
|
|
|
"glRasterPos4dv", "glRasterPos4f", "glRasterPos4fv", "glRasterPos4i", "glRasterPos4iv", "glRasterPos4s", "glRasterPos4sv", "glReadBuffer", "glReadPixels", "glRectd", "glRectdv", "glRectf",
|
|
|
|
"glRectfv", "glRecti", "glRectiv", "glRects", "glRectsv", "glRenderMode", "glRotated", "glRotatef", "glScaled", "glScalef", "glScissor", "glSelectBuffer", "glShadeModel", "glStencilFunc",
|
|
|
|
"glStencilMask", "glStencilOp", "glTexCoord1d", "glTexCoord1dv", "glTexCoord1f", "glTexCoord1fv", "glTexCoord1i", "glTexCoord1iv", "glTexCoord1s", "glTexCoord1sv", "glTexCoord2d",
|
|
|
|
"glTexCoord2dv", "glTexCoord2f", "glTexCoord2fv", "glTexCoord2i", "glTexCoord2iv", "glTexCoord2s", "glTexCoord2sv", "glTexCoord3d", "glTexCoord3dv", "glTexCoord3f", "glTexCoord3fv",
|
|
|
|
"glTexCoord3i", "glTexCoord3iv", "glTexCoord3s", "glTexCoord3sv", "glTexCoord4d", "glTexCoord4dv", "glTexCoord4f", "glTexCoord4fv", "glTexCoord4i", "glTexCoord4iv", "glTexCoord4s",
|
|
|
|
"glTexCoord4sv", "glTexCoordPointer", "glTexEnvf", "glTexEnvfv", "glTexEnvi", "glTexEnviv", "glTexGend", "glTexGendv", "glTexGenf", "glTexGenfv", "glTexGeni", "glTexGeniv", "glTexImage1D",
|
|
|
|
"glTexImage2D", "glTexParameterf", "glTexParameterfv", "glTexParameteri", "glTexParameteriv", "glTexSubImage1D", "glTexSubImage2D", "glTranslated", "glTranslatef", "glVertex2d",
|
|
|
|
"glVertex2dv", "glVertex2f", "glVertex2fv", "glVertex2i", "glVertex2iv", "glVertex2s", "glVertex2sv", "glVertex3d", "glVertex3dv", "glVertex3f", "glVertex3fv", "glVertex3i", "glVertex3iv",
|
|
|
|
"glVertex3s", "glVertex3sv", "glVertex4d", "glVertex4dv", "glVertex4f", "glVertex4fv", "glVertex4i", "glVertex4iv", "glVertex4s", "glVertex4sv", "glVertexPointer", "glViewport"
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t size = KIERO_ARRAY_SIZE(methodsNames);
|
|
|
|
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
g_methodsTable[i] = (uint150_t)::GetProcAddress(libOpenGL32, methodsNames[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
g_renderType = RenderType::OpenGL;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
else if (_renderType == RenderType::Vulkan)
|
|
|
|
{
|
|
|
|
#if KIERO_INCLUDE_VULKAN
|
|
|
|
HMODULE libVulkan;
|
|
|
|
if ((libVulkan = GetModuleHandle(KIERO_TEXT("vulkan-1.dll"))) == NULL)
|
|
|
|
{
|
|
|
|
return Status::ModuleNotFoundError;
|
|
|
|
}
|
|
|
|
|
|
|
|
const char* const methodsNames[] = {
|
|
|
|
"vkCreateInstance", "vkDestroyInstance", "vkEnumeratePhysicalDevices", "vkGetPhysicalDeviceFeatures", "vkGetPhysicalDeviceFormatProperties", "vkGetPhysicalDeviceImageFormatProperties",
|
|
|
|
"vkGetPhysicalDeviceProperties", "vkGetPhysicalDeviceQueueFamilyProperties", "vkGetPhysicalDeviceMemoryProperties", "vkGetInstanceProcAddr", "vkGetDeviceProcAddr", "vkCreateDevice",
|
|
|
|
"vkDestroyDevice", "vkEnumerateInstanceExtensionProperties", "vkEnumerateDeviceExtensionProperties", "vkEnumerateDeviceLayerProperties", "vkGetDeviceQueue", "vkQueueSubmit", "vkQueueWaitIdle",
|
|
|
|
"vkDeviceWaitIdle", "vkAllocateMemory", "vkFreeMemory", "vkMapMemory", "vkUnmapMemory", "vkFlushMappedMemoryRanges", "vkInvalidateMappedMemoryRanges", "vkGetDeviceMemoryCommitment",
|
|
|
|
"vkBindBufferMemory", "vkBindImageMemory", "vkGetBufferMemoryRequirements", "vkGetImageMemoryRequirements", "vkGetImageSparseMemoryRequirements", "vkGetPhysicalDeviceSparseImageFormatProperties",
|
|
|
|
"vkQueueBindSparse", "vkCreateFence", "vkDestroyFence", "vkResetFences", "vkGetFenceStatus", "vkWaitForFences", "vkCreateSemaphore", "vkDestroySemaphore", "vkCreateEvent", "vkDestroyEvent",
|
|
|
|
"vkGetEventStatus", "vkSetEvent", "vkResetEvent", "vkCreateQueryPool", "vkDestroyQueryPool", "vkGetQueryPoolResults", "vkCreateBuffer", "vkDestroyBuffer", "vkCreateBufferView", "vkDestroyBufferView",
|
|
|
|
"vkCreateImage", "vkDestroyImage", "vkGetImageSubresourceLayout", "vkCreateImageView", "vkDestroyImageView", "vkCreateShaderModule", "vkDestroyShaderModule", "vkCreatePipelineCache",
|
|
|
|
"vkDestroyPipelineCache", "vkGetPipelineCacheData", "vkMergePipelineCaches", "vkCreateGraphicsPipelines", "vkCreateComputePipelines", "vkDestroyPipeline", "vkCreatePipelineLayout",
|
|
|
|
"vkDestroyPipelineLayout", "vkCreateSampler", "vkDestroySampler", "vkCreateDescriptorSetLayout", "vkDestroyDescriptorSetLayout", "vkCreateDescriptorPool", "vkDestroyDescriptorPool",
|
|
|
|
"vkResetDescriptorPool", "vkAllocateDescriptorSets", "vkFreeDescriptorSets", "vkUpdateDescriptorSets", "vkCreateFramebuffer", "vkDestroyFramebuffer", "vkCreateRenderPass", "vkDestroyRenderPass",
|
|
|
|
"vkGetRenderAreaGranularity", "vkCreateCommandPool", "vkDestroyCommandPool", "vkResetCommandPool", "vkAllocateCommandBuffers", "vkFreeCommandBuffers", "vkBeginCommandBuffer", "vkEndCommandBuffer",
|
|
|
|
"vkResetCommandBuffer", "vkCmdBindPipeline", "vkCmdSetViewport", "vkCmdSetScissor", "vkCmdSetLineWidth", "vkCmdSetDepthBias", "vkCmdSetBlendConstants", "vkCmdSetDepthBounds",
|
|
|
|
"vkCmdSetStencilCompareMask", "vkCmdSetStencilWriteMask", "vkCmdSetStencilReference", "vkCmdBindDescriptorSets", "vkCmdBindIndexBuffer", "vkCmdBindVertexBuffers", "vkCmdDraw", "vkCmdDrawIndexed",
|
|
|
|
"vkCmdDrawIndirect", "vkCmdDrawIndexedIndirect", "vkCmdDispatch", "vkCmdDispatchIndirect", "vkCmdCopyBuffer", "vkCmdCopyImage", "vkCmdBlitImage", "vkCmdCopyBufferToImage", "vkCmdCopyImageToBuffer",
|
|
|
|
"vkCmdUpdateBuffer", "vkCmdFillBuffer", "vkCmdClearColorImage", "vkCmdClearDepthStencilImage", "vkCmdClearAttachments", "vkCmdResolveImage", "vkCmdSetEvent", "vkCmdResetEvent", "vkCmdWaitEvents",
|
|
|
|
"vkCmdPipelineBarrier", "vkCmdBeginQuery", "vkCmdEndQuery", "vkCmdResetQueryPool", "vkCmdWriteTimestamp", "vkCmdCopyQueryPoolResults", "vkCmdPushConstants", "vkCmdBeginRenderPass", "vkCmdNextSubpass",
|
|
|
|
"vkCmdEndRenderPass", "vkCmdExecuteCommands"
|
|
|
|
};
|
|
|
|
|
|
|
|
size_t size = KIERO_ARRAY_SIZE(methodsNames);
|
|
|
|
|
|
|
|
g_methodsTable = (uint150_t*)::calloc(size, sizeof(uint150_t));
|
|
|
|
|
|
|
|
for (int i = 0; i < size; i++)
|
|
|
|
{
|
|
|
|
g_methodsTable[i] = (uint150_t)::GetProcAddress(libVulkan, methodsNames[i]);
|
|
|
|
}
|
|
|
|
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_Initialize();
|
|
|
|
#endif
|
|
|
|
|
|
|
|
g_renderType = RenderType::Vulkan;
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::NotSupportedError;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
RenderType::Enum type = RenderType::None;
|
|
|
|
|
|
|
|
if (::GetModuleHandle(KIERO_TEXT("d3d9.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::D3D9;
|
|
|
|
}
|
|
|
|
else if (::GetModuleHandle(KIERO_TEXT("d3d10.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::D3D10;
|
|
|
|
}
|
|
|
|
else if (::GetModuleHandle(KIERO_TEXT("d3d11.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::D3D11;
|
|
|
|
}
|
|
|
|
else if (::GetModuleHandle(KIERO_TEXT("d3d12.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::D3D12;
|
|
|
|
}
|
|
|
|
else if (::GetModuleHandle(KIERO_TEXT("opengl32.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::OpenGL;
|
|
|
|
}
|
|
|
|
else if (::GetModuleHandle(KIERO_TEXT("vulkan-1.dll")) != NULL)
|
|
|
|
{
|
|
|
|
type = RenderType::Vulkan;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
{
|
|
|
|
return Status::NotSupportedError;
|
|
|
|
}
|
|
|
|
|
|
|
|
return init(type);
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kiero::shutdown()
|
|
|
|
{
|
|
|
|
if (g_renderType != RenderType::None)
|
|
|
|
{
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_DisableHook(MH_ALL_HOOKS);
|
|
|
|
#endif
|
|
|
|
|
|
|
|
::free(g_methodsTable);
|
|
|
|
g_methodsTable = NULL;
|
|
|
|
g_renderType = RenderType::None;
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kiero::Status::Enum kiero::bind(uint16_t _index, void** _original, void* _function)
|
|
|
|
{
|
|
|
|
// TODO: Need own detour function
|
|
|
|
|
|
|
|
assert(_original != NULL && _function != NULL);
|
|
|
|
|
|
|
|
if (g_renderType != RenderType::None)
|
|
|
|
{
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
void* target = (void*)g_methodsTable[_index];
|
|
|
|
if (MH_CreateHook(target, _function, _original) != MH_OK || MH_EnableHook(target) != MH_OK)
|
|
|
|
{
|
|
|
|
return Status::UnknownError;
|
|
|
|
}
|
|
|
|
#endif
|
|
|
|
|
|
|
|
return Status::Success;
|
|
|
|
}
|
|
|
|
|
|
|
|
return Status::NotInitializedError;
|
|
|
|
}
|
|
|
|
|
|
|
|
void kiero::unbind(uint16_t _index)
|
|
|
|
{
|
|
|
|
if (g_renderType != RenderType::None)
|
|
|
|
{
|
|
|
|
#if KIERO_USE_MINHOOK
|
|
|
|
MH_DisableHook((void*)g_methodsTable[_index]);
|
|
|
|
#endif
|
|
|
|
}
|
|
|
|
}
|
|
|
|
|
|
|
|
kiero::RenderType::Enum kiero::getRenderType()
|
|
|
|
{
|
|
|
|
return g_renderType;
|
|
|
|
}
|
|
|
|
|
|
|
|
uint150_t* kiero::getMethodsTable()
|
|
|
|
{
|
|
|
|
return g_methodsTable;
|
|
|
|
}
|