Skip to content

Instantly share code, notes, and snippets.

@ssube
Created November 28, 2011 08:05
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save ssube/1399555 to your computer and use it in GitHub Desktop.
Save ssube/1399555 to your computer and use it in GitHub Desktop.
//-----------------------------------------------
// 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