Created
November 28, 2011 08:05
-
-
Save ssube/1399555 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
//----------------------------------------------- | |
// Hook startup code | |
//----------------------------------------------- | |
HMODULE WINAPI LoadSystemLibrary(const LPTSTR libname) | |
{ | |
TCHAR path[MAX_PATH]; | |
GetSystemDirectory(path, MAX_PATH); | |
StringCchCat(path, MAX_PATH, TEXT("\\")); | |
StringCchCat(path, MAX_PATH, libname); | |
return LoadLibrary(path); | |
} | |
/** | |
* Most DirectX libraries use an identical loading function, with only the name varying. This function takes an SDK | |
* version, library name and function name, loads and calls the proper init function. | |
*/ | |
void * WINAPI VoodooDXCreateGeneric(UINT sdkVersion, const LPTSTR lib, const LPCSTR func) | |
{ | |
typedef void * (WINAPI * DXInitFunc) (UINT); | |
HMODULE baselib = LoadSystemLibrary(lib); | |
if (!baselib) | |
{ | |
MessageBox(nullptr, L"Voodoo Loader: Unable to load system DLL.", L"Loader Error", MB_ICONERROR | MB_OK); | |
exit(1); | |
} | |
DXInitFunc initFunc = (DXInitFunc) GetProcAddress(baselib, func); | |
if (!initFunc) | |
{ | |
MessageBox(nullptr, L"Voodoo Loader: Unable to find system EP.", L"Loader Error", MB_ICONERROR | MB_OK); | |
exit(1); | |
} | |
return (*initFunc) (sdkVersion); | |
} | |
/** | |
* Direct3D 9 | |
*/ | |
void * WINAPI Voodoo3DCreate9(UINT sdkVersion) | |
{ | |
void * pD3D9 = VoodooDXCreateGeneric(sdkVersion, L"d3d9.dll", "Direct3DCreate9"); | |
if (LoadVoodoo()) | |
{ | |
VoodooShader::Variant D3DObj; | |
D3DObj.Type = VoodooShader::UT_PVoid; | |
D3DObj.Value.VPVoid = pD3D9; | |
gVoodooCore->GetAdapter()->SetProperty(L"IDirect3D9", D3DObj); | |
if (D3DObj.Value.VPVoid != pD3D9) | |
{ | |
pD3D9 = D3DObj.Value.VPVoid; | |
} | |
} | |
return pD3D9; | |
} | |
//------------------------------------------ | |
// D3D9 wrapper call | |
//------------------------------------------ | |
HRESULT STDMETHODCALLTYPE CVoodoo3DDevice9::Present | |
( | |
THIS_ CONST RECT * pSourceRect, | |
CONST RECT * pDestRect, | |
HWND hDestWindowOverride, | |
CONST RGNDATA * pDirtyRegion | |
) | |
{ | |
if (gpVoodooCore && testShader) | |
{ | |
ILoggerRef logger = gpVoodooCore->GetLogger(); | |
IAdapterRef adapter = gpVoodooCore->GetAdapter(); | |
// IDirect3DBaseTexture9 * tex; | |
// IDirect3DSurface9 * rts; | |
// ; | |
// m_RealDevice->GetTexture(0, &tex); | |
// m_RealDevice->GetRenderTarget(0, &rts); | |
HRESULT hr = m_RealDevice->StretchRect(backbufferSurf, nullptr, surface_ThisFrame, nullptr, D3DTEXF_NONE); | |
if (FAILED(hr)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to stretch backbuffer to scratch texture."); | |
} | |
/*hr = m_RealDevice->SetRenderTarget(0, backbufferSurf); | |
if (FAILED(hr)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to set render target."); | |
}*/ | |
VoodooShader::ITechniqueRef tech = testShader->GetDefaultTechnique(); | |
VoodooShader::IPassRef pass = tech->GetPass(0); | |
adapter->SetPass(pass.get()); | |
adapter->DrawGeometry(2, (VertexStruct*)gpFSQuadVerts, (VertexFlags)(VF_Buffer|VF_Transformed)); | |
adapter->ResetPass(pass.get()); | |
} | |
return m_RealDevice->Present(pSourceRect, pDestRect, hDestWindowOverride, pDirtyRegion); | |
} | |
//----------------------------------------------------- | |
// DX9Adapter stuff | |
//----------------------------------------------------- | |
bool DX9Adapter::SetPass(_In_ IPass * const pPass) | |
{ | |
ILoggerRef logger = m_Core->GetLogger(); | |
if (!pPass) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Unable to set null pass."); | |
return false; | |
} | |
if (m_BoundPass && m_BoundPass != pPass) | |
{ | |
logger->Log(LL_ModWarn, VOODOO_DX9_NAME, L"Setting pass without resetting previously bound pass."); | |
} | |
cgSetPassState(pPass->GetCgPass()); | |
CGerror cgerr = cgGetError(); | |
assert(cgerr == CG_NO_ERROR); | |
HRESULT cgd3derr = cgD3D9GetLastError(); | |
assert(cgd3derr == D3D_OK); | |
// Bind render targets | |
//this->SetTarget(0, m_BoundPass->GetTarget()); | |
m_BoundPass = pPass; | |
return true; | |
} | |
bool DX9Adapter::ResetPass(_In_ IPass * pPass) | |
{ | |
ILoggerRef logger = m_Core->GetLogger(); | |
if (!pPass) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Unable to reset null pass."); | |
return false; | |
} | |
if (m_BoundPass && m_BoundPass != pPass) | |
{ | |
logger->Log(LL_ModWarn, VOODOO_DX9_NAME, L"Resetting pass different than the previously bound pass."); | |
} | |
cgResetPassState(pPass->GetCgPass()); | |
CGerror cgerr = cgGetError(); | |
assert(cgerr == CG_NO_ERROR); | |
HRESULT cgd3derr = cgD3D9GetLastError(); | |
assert(cgd3derr == D3D_OK); | |
m_BoundPass = nullptr; | |
return true; | |
} | |
bool DX9Adapter::DrawGeometry | |
( | |
_In_ const uint32_t count, | |
_In_count_(count) VertexStruct * const pVertexData, | |
_In_ const VertexFlags flags | |
) | |
{ | |
if (!pVertexData) | |
{ | |
m_Core->GetLogger()->Log(LL_ModError, VOODOO_DX9_NAME, L"No geometry given to draw."); | |
return false; | |
} | |
HRESULT hr; | |
IDirect3DStateBlock9 * deviceState = nullptr; | |
hr = m_Device->CreateStateBlock(D3DSBT_ALL, &deviceState); | |
hr = m_CleanState->Apply(); | |
// Set the necessary states | |
hr = m_Device->SetRenderState(D3DRS_CLIPPING, FALSE); | |
hr = m_Device->SetRenderState(D3DRS_ZENABLE, FALSE); | |
hr = m_Device->SetRenderState(D3DRS_ZFUNC, D3DCMP_ALWAYS); | |
hr = m_Device->SetRenderState(D3DRS_CULLMODE, D3DCULL_NONE); | |
if (flags & VF_Transformed) | |
{ | |
m_Device->SetVertexDeclaration(m_VertDeclT); | |
} else { | |
m_Device->SetVertexDeclaration(m_VertDecl); | |
} | |
if (flags & VF_Buffer) | |
{ | |
IDirect3DVertexBuffer9 * pVertexBuffer = reinterpret_cast<IDirect3DVertexBuffer9*>(pVertexData); | |
hr = m_Device->SetStreamSource(0, pVertexBuffer, 0, sizeof(VertexStruct)); | |
hr = m_Device->BeginScene(); | |
if (SUCCEEDED(hr)) | |
{ | |
hr = m_Device->DrawPrimitive(D3DPT_TRIANGLELIST, 0, count); | |
hr = m_Device->EndScene(); | |
} | |
else | |
{ | |
gpVoodooCore->GetLogger()->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to draw quad."); | |
hr = deviceState->Release(); | |
return false; | |
} | |
} else { | |
hr = m_Device->BeginScene(); | |
if (SUCCEEDED(hr)) | |
{ | |
hr = m_Device->DrawPrimitiveUP(D3DPT_TRIANGLELIST, count, pVertexData, sizeof(VertexStruct)); | |
hr = m_Device->EndScene(); | |
} | |
else | |
{ | |
gpVoodooCore->GetLogger()->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to draw quad."); | |
hr = deviceState->Release(); | |
return false; | |
} | |
} | |
hr = deviceState->Apply(); | |
hr = deviceState->Release(); | |
return true; | |
} | |
bool DX9Adapter::SetProperty(_In_ const wchar_t * name, _In_ Variant & value) | |
{ | |
String strname(name); | |
if (strname == L"SdkVersion" && value.Type == UT_UInt32) | |
{ | |
m_SdkVersion = value.Value.VUInt32; | |
return true; | |
} else if (strname == L"IDirect3D8" && value.Type == UT_PVoid) { | |
using VoodooShader::VoodooDX8::CVoodoo3D8; | |
IDirect3D9 * origObj = reinterpret_cast<IDirect3D9 *>(value.Value.VPVoid); | |
CVoodoo3D8 * fakeObj = new CVoodoo3D8(m_SdkVersion, origObj); | |
value.Value.VPVoid = fakeObj; | |
return true; | |
} else if (strname == L"IDirect3D9" && value.Type == UT_PVoid) { | |
IDirect3D9 * origObj = reinterpret_cast<IDirect3D9 *>(value.Value.VPVoid); | |
CVoodoo3D9 * fakeObj = new CVoodoo3D9(m_SdkVersion, origObj); | |
value.Value.VPVoid = fakeObj; | |
return true; | |
} | |
return false; | |
} | |
bool DX9Adapter::SetDXDevice(IDirect3DDevice9 * pDevice) | |
{ | |
if (pDevice == m_Device) | |
{ | |
return true; | |
} | |
else if (pDevice == nullptr || (pDevice && m_Device)) | |
{ | |
if (m_VertDecl) m_VertDecl->Release(); | |
if (m_VertDeclT) m_VertDeclT->Release(); | |
if (!pDevice) return true; | |
} | |
m_Device = pDevice; | |
HRESULT errors = m_Device->CreateStateBlock(D3DSBT_ALL, &m_CleanState); | |
ILoggerRef logger = m_Core->GetLogger(); | |
CGcontext context = m_Core->GetCgContext(); | |
if (!cgIsContext(context)) | |
{ | |
context = cgCreateContext(); | |
m_Core->SetCgContext(context); | |
} | |
errors = cgD3D9SetDevice(m_Device); | |
if (!SUCCEEDED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Unable to set Cg D3D9 device."); | |
} | |
else | |
{ | |
logger->Log(LL_ModInfo, VOODOO_DX9_NAME, L"Cg D3D9 device set successfully."); | |
} | |
cgD3D9RegisterStates(context); | |
cgD3D9EnableDebugTracing(CG_TRUE); | |
cgD3D9SetManageTextureParameters(context, CG_TRUE); | |
errors = cgD3D9GetLastError(); | |
if (!SUCCEEDED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Errors registering Cg states."); | |
} | |
else | |
{ | |
logger->Log(LL_ModInfo, VOODOO_DX9_NAME, L"Cg states registered successfully."); | |
} | |
// Setup profiles | |
CGprofile bestFrag = cgD3D9GetLatestPixelProfile(); | |
CGprofile bestVert = cgD3D9GetLatestVertexProfile(); | |
const char * bestVertStr = cgGetProfileString(bestVert); | |
const char * bestFragStr = cgGetProfileString(bestFrag); | |
logger->Log | |
( | |
LL_ModInfo, VOODOO_DX9_NAME, | |
L"Detected latest profiles with %S as vertex and %S as fragment.", | |
bestVertStr, bestFragStr | |
); | |
// Create vertex declaration | |
D3DVERTEXELEMENT9 vertDeclElems[] = | |
{ | |
{ 0, 0, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_POSITION, 0 }, | |
{ 0, 16, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_COLOR, 0 }, | |
{ 0, 32, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 0 }, | |
{ 0, 48, D3DDECLTYPE_FLOAT4, D3DDECLMETHOD_DEFAULT, D3DDECLUSAGE_TEXCOORD, 1 }, | |
D3DDECL_END() | |
}; | |
errors = m_Device->CreateVertexDeclaration(vertDeclElems, &m_VertDecl); | |
if (!SUCCEEDED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Unable to create standard vertex declaration."); | |
} | |
vertDeclElems[0].Usage = D3DDECLUSAGE_POSITIONT; | |
errors = m_Device->CreateVertexDeclaration(vertDeclElems, &m_VertDeclT); | |
if (!SUCCEEDED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Unable to create transformed vertex declaration."); | |
} | |
// Get params | |
D3DVIEWPORT9 viewport; | |
m_Device->GetViewport(&viewport); | |
float fx = (viewport.Width / 2) + 0.5f; | |
float fy = (viewport.Height / 2) + 0.5f; | |
logger->Log(LL_ModInfo, VOODOO_DX9_NAME, L"Prepping for %d by %d target.", viewport.Width, viewport.Height); | |
// Get buffers | |
if (!SUCCEEDED(m_Device->GetBackBuffer(0, 0, D3DBACKBUFFER_TYPE_MONO, &m_BackBuffer[0]))) { m_BackBuffer[0] = nullptr; } | |
//if (!SUCCEEDED(m_Device->GetBackBuffer(0, 1, D3DBACKBUFFER_TYPE_MONO, &m_BackBuffer[1]))) { m_BackBuffer[1] = nullptr; } | |
//if (!SUCCEEDED(m_Device->GetBackBuffer(0, 2, D3DBACKBUFFER_TYPE_MONO, &m_BackBuffer[2]))) { m_BackBuffer[2] = nullptr; } | |
//if (!SUCCEEDED(m_Device->GetBackBuffer(0, 3, D3DBACKBUFFER_TYPE_MONO, &m_BackBuffer[3]))) { m_BackBuffer[3] = nullptr; } | |
// Create fullscreen vbuffer | |
VertexStruct fsVertData[6] = | |
{ | |
// POSITION COLOR TEXCOORD[0] TEXCOORD[1] | |
{{-0.5f, fy, 0.5f, 0.0f}, {0.0f, 1.0f, 0.0f, 1.0f}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
{{-0.5f, -0.5f, 0.5f, 0.0f}, {0.0f, 0.0f, 1.0f, 1.0f}, {{0.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
{{ fx, -0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
{{-0.5f, fy, 0.5f, 0.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {{0.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
{{ fx, -0.5f, 0.5f, 0.0f}, {1.0f, 0.0f, 0.0f, 1.0f}, {{1.0f, 0.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
{{ fx, fy, 0.5f, 0.0f}, {1.0f, 1.0f, 0.0f, 1.0f}, {{1.0f, 1.0f, 0.0f, 0.0f}, {0.0f, 0.0f, 0.0f, 0.0f}}}, | |
}; | |
errors = m_Device->CreateVertexBuffer | |
( | |
sizeof(fsVertData), D3DUSAGE_WRITEONLY, NULL, D3DPOOL_DEFAULT, &gpFSQuadVerts, NULL | |
); | |
if (FAILED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to create vertex buffer."); | |
} | |
VertexStruct * pVertices = nullptr; | |
errors = gpFSQuadVerts->Lock(0, 0, (void**)&pVertices, 0); | |
if (FAILED(errors)) | |
{ | |
logger->Log(LL_ModError, VOODOO_DX9_NAME, L"Failed to lock vertex buffer to fsquad."); | |
} else { | |
memcpy(pVertices, fsVertData, sizeof(fsVertData)); | |
gpFSQuadVerts->Unlock(); | |
} | |
return true; | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment