From bc565e693baa2256b155f42f5c3cef5201152003 Mon Sep 17 00:00:00 2001 From: Elisha Riedlinger Date: Thu, 15 Aug 2024 19:59:02 -0700 Subject: [PATCH] Add some basic ProcessVertices() support --- Dllmain/BuildNo.rc | 2 +- Libraries/d3dx9.cpp | 38 +++++++ Libraries/d3dx9.h | 12 +++ ddraw/IDirect3DTypes.cpp | 175 +++++++++++++++++++++++++++++++ ddraw/IDirect3DTypes.h | 1 + ddraw/IDirect3DVertexBufferX.cpp | 153 ++++++++++++++++++++++++--- 6 files changed, 363 insertions(+), 18 deletions(-) diff --git a/Dllmain/BuildNo.rc b/Dllmain/BuildNo.rc index 2dd78727..8eda527c 100644 --- a/Dllmain/BuildNo.rc +++ b/Dllmain/BuildNo.rc @@ -1 +1 @@ -#define BUILD_NUMBER 7093 +#define BUILD_NUMBER 7094 diff --git a/Libraries/d3dx9.cpp b/Libraries/d3dx9.cpp index 05de26c3..9ec66a39 100644 --- a/Libraries/d3dx9.cpp +++ b/Libraries/d3dx9.cpp @@ -29,7 +29,11 @@ typedef HRESULT(WINAPI* PFN_D3DXLoadSurfaceFromMemory)(LPDIRECT3DSURFACE9 pDestS typedef HRESULT(WINAPI* PFN_D3DXLoadSurfaceFromSurface)(LPDIRECT3DSURFACE9 pDestSurface, const PALETTEENTRY* pDestPalette, const RECT* pDestRect, LPDIRECT3DSURFACE9 pSrcSurface, const PALETTEENTRY* pSrcPalette, const RECT* pSrcRect, DWORD Filter, D3DCOLOR ColorKey); typedef HRESULT(WINAPI* PFN_D3DXSaveSurfaceToFileInMemory)(LPD3DXBUFFER* ppDestBuf, D3DXIMAGE_FILEFORMAT DestFormat, LPDIRECT3DSURFACE9 pSrcSurface, const PALETTEENTRY* pSrcPalette, const RECT* SrcRect); typedef HRESULT(WINAPI* PFN_D3DXSaveTextureToFileInMemory)(LPD3DXBUFFER* ppDestBuf, D3DXIMAGE_FILEFORMAT DestFormat, LPDIRECT3DBASETEXTURE9 pSrcTexture, const PALETTEENTRY* pSrcPalette); + typedef HRESULT(WINAPI* PFN_D3DXDeclaratorFromFVF)(DWORD FVF, D3DVERTEXELEMENT9 pDeclarator[MAX_FVF_DECL_SIZE]); +typedef D3DXMATRIX*(WINAPI* PFN_D3DXMatrixMultiply)(_Inout_ D3DXMATRIX* pOut, _In_ const D3DXMATRIX* pM1, _In_ const D3DXMATRIX* pM2); +typedef D3DXVECTOR3*(WINAPI* PFN_D3DXVec3TransformCoord)(_Inout_ D3DXVECTOR3* pOut, _In_ const D3DXVECTOR3* pV, _In_ const D3DXMATRIX* pM); + typedef HRESULT(WINAPI* PFN_D3DXCompileShaderFromFileA)(LPCSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); typedef HRESULT(WINAPI* PFN_D3DXCompileShaderFromFileW)(LPCWSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); typedef HRESULT(WINAPI* PFN_D3DXAssembleShader)(LPCSTR pSrcData, UINT SrcDataLen, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); @@ -50,6 +54,8 @@ PFN_D3DXLoadSurfaceFromSurface p_D3DXLoadSurfaceFromSurface = nullptr; PFN_D3DXSaveSurfaceToFileInMemory p_D3DXSaveSurfaceToFileInMemory = nullptr; PFN_D3DXSaveTextureToFileInMemory p_D3DXSaveTextureToFileInMemory = nullptr; PFN_D3DXDeclaratorFromFVF p_D3DXDeclaratorFromFVF = nullptr; +PFN_D3DXMatrixMultiply p_D3DXMatrixMultiply = nullptr; +PFN_D3DXVec3TransformCoord p_D3DXVec3TransformCoord = nullptr; PFN_D3DXCompileShaderFromFileA p_D3DXCompileShaderFromFileA = nullptr; PFN_D3DXCompileShaderFromFileW p_D3DXCompileShaderFromFileW = nullptr; PFN_D3DXAssembleShader p_D3DXAssembleShader = nullptr; @@ -89,6 +95,8 @@ void LoadD3dx9() p_D3DXSaveSurfaceToFileInMemory = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXSaveSurfaceToFileInMemory")); p_D3DXSaveTextureToFileInMemory = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXSaveTextureToFileInMemory")); p_D3DXDeclaratorFromFVF = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXDeclaratorFromFVF")); + p_D3DXMatrixMultiply = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXMatrixMultiply")); + p_D3DXVec3TransformCoord = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXVec3TransformCoord")); p_D3DXCompileShaderFromFileA = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXCompileShaderFromFileA")); p_D3DXCompileShaderFromFileW = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXCompileShaderFromFileW")); p_D3DXAssembleShader = reinterpret_cast(MemoryGetProcAddress(d3dx9Module, "D3DXAssembleShader")); @@ -251,6 +259,36 @@ HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD FVF, D3DVERTEXELEMENT9 pDeclarator[MA return hr; } +D3DXMATRIX* WINAPI D3DXMatrixMultiply(_Inout_ D3DXMATRIX* pOut, _In_ const D3DXMATRIX* pM1, _In_ const D3DXMATRIX* pM2) +{ + Logging::LogDebug() << __FUNCTION__; + + LoadD3dx9(); + + if (!p_D3DXMatrixMultiply) + { + LOG_ONCE(__FUNCTION__ << " Error: Could not find ProcAddress!"); + return nullptr; + } + + return p_D3DXMatrixMultiply(pOut, pM1, pM2); +} + +D3DXVECTOR3* WINAPI D3DXVec3TransformCoord(_Inout_ D3DXVECTOR3* pOut, _In_ const D3DXVECTOR3* pV, _In_ const D3DXMATRIX* pM) +{ + Logging::LogDebug() << __FUNCTION__; + + LoadD3dx9(); + + if (!p_D3DXVec3TransformCoord) + { + LOG_ONCE(__FUNCTION__ << " Error: Could not find ProcAddress!"); + return nullptr; + } + + return p_D3DXVec3TransformCoord(pOut, pV, pM); +} + HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable) { Logging::LogDebug() << __FUNCTION__; diff --git a/Libraries/d3dx9.h b/Libraries/d3dx9.h index 9a62925d..cf5d2431 100644 --- a/Libraries/d3dx9.h +++ b/Libraries/d3dx9.h @@ -71,6 +71,12 @@ typedef ID3DInclude* LPD3DINCLUDE; #define D3D_DISASM_ENABLE_INSTRUCTION_CYCLE 0x00000008 #define D3D_DISASM_DISABLE_DEBUG_INFO 0x00000010 +typedef struct D3DXVECTOR3 { + FLOAT x; + FLOAT y; + FLOAT z; +} D3DXVECTOR3, * LPD3DXVECTOR3; + typedef enum D3DXIMAGE_FILEFORMAT { D3DXIFF_BMP = 0, D3DXIFF_JPG = 1, @@ -119,6 +125,8 @@ typedef HRESULT(WINAPI* LPD3DXFILL3D)(D3DXVECTOR4* pOut, const D3DXVECTOR2* pTex using D3DXMACRO = D3D_SHADER_MACRO; +using D3DXMATRIX = D3DMATRIX; + using ID3DXBuffer = ID3DBlob; using LPD3DXBUFFER = ID3DXBuffer*; @@ -130,7 +138,11 @@ HRESULT WINAPI D3DXLoadSurfaceFromMemory(LPDIRECT3DSURFACE9 pDestSurface, const HRESULT WINAPI D3DXLoadSurfaceFromSurface(LPDIRECT3DSURFACE9 pDestSurface, const PALETTEENTRY* pDestPalette, const RECT* pDestRect, LPDIRECT3DSURFACE9 pSrcSurface, const PALETTEENTRY* pSrcPalette, const RECT* pSrcRect, DWORD Filter, D3DCOLOR ColorKey); HRESULT WINAPI D3DXSaveSurfaceToFileInMemory(LPD3DXBUFFER* ppDestBuf, D3DXIMAGE_FILEFORMAT DestFormat, LPDIRECT3DSURFACE9 pSrcSurface, const PALETTEENTRY* pSrcPalette, const RECT* SrcRect); HRESULT WINAPI D3DXSaveTextureToFileInMemory(LPD3DXBUFFER* ppDestBuf, D3DXIMAGE_FILEFORMAT DestFormat, LPDIRECT3DBASETEXTURE9 pSrcTexture, const PALETTEENTRY* pSrcPalette); + HRESULT WINAPI D3DXDeclaratorFromFVF(DWORD FVF, D3DVERTEXELEMENT9 pDeclarator[MAX_FVF_DECL_SIZE]); +D3DXMATRIX* WINAPI D3DXMatrixMultiply(_Inout_ D3DXMATRIX* pOut, _In_ const D3DXMATRIX* pM1, _In_ const D3DXMATRIX* pM2); +D3DXVECTOR3* WINAPI D3DXVec3TransformCoord(_Inout_ D3DXVECTOR3* pOut, _In_ const D3DXVECTOR3* pV, _In_ const D3DXMATRIX* pM); + HRESULT WINAPI D3DXCompileShaderFromFileA(LPCSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); HRESULT WINAPI D3DXCompileShaderFromFileW(LPCWSTR pSrcFile, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, LPCSTR pFunctionName, LPCSTR pProfile, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs, LPD3DXCONSTANTTABLE* ppConstantTable); HRESULT WINAPI D3DXAssembleShader(LPCSTR pSrcData, UINT SrcDataLen, const D3DXMACRO* pDefines, LPD3DXINCLUDE pInclude, DWORD Flags, LPD3DXBUFFER* ppShader, LPD3DXBUFFER* ppErrorMsgs); diff --git a/ddraw/IDirect3DTypes.cpp b/ddraw/IDirect3DTypes.cpp index d6811a9a..c35964fd 100644 --- a/ddraw/IDirect3DTypes.cpp +++ b/ddraw/IDirect3DTypes.cpp @@ -573,6 +573,181 @@ bool CheckRenderStateType(D3DRENDERSTATETYPE dwRenderStateType) } } +void ConvertVertex(BYTE* pDestVertex, DWORD DestFVF, const BYTE* pSrcVertex, DWORD SrcFVF) +{ + DWORD SrcOffset = 0; + DWORD DestOffset = 0; + + // Copy Position XYZ + *(D3DXVECTOR3*)pDestVertex = *(D3DXVECTOR3*)pSrcVertex; + DestOffset += 3 * sizeof(float); + + // Update source offset for Position + SrcOffset += 3 * sizeof(float); + + // Copy Position data (XYZW, XYZRHW, etc.) + switch (DestFVF & D3DFVF_POSITION_MASK_9) + { + case D3DFVF_XYZW: + case D3DFVF_XYZRHW: + if ((DestFVF & D3DFVF_POSITION_MASK_9) == (SrcFVF & D3DFVF_POSITION_MASK_9)) + { + *(float*)(pDestVertex + DestOffset) = *(float*)(pSrcVertex + SrcOffset); + } + DestOffset += sizeof(float); + break; + case D3DFVF_XYZB1: + case D3DFVF_XYZB2: + case D3DFVF_XYZB3: + case D3DFVF_XYZB4: + case D3DFVF_XYZB5: + { + // Get number of blending weights + DWORD SrcNumBlending = + (SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB1 ? 1 : + (SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB2 ? 2 : + (SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB3 ? 3 : + (SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB4 ? 4 : + (SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB5 ? 5 : 0; + DWORD DestNumBlending = + (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB1 ? 1 : + (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB2 ? 2 : + (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB3 ? 3 : + (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB4 ? 4 : + (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZB5 ? 5 : 0; + // Copy matching blending weights + for (UINT x = 0; x < min(SrcNumBlending, DestNumBlending); x++) + { + *(float*)(pDestVertex + DestOffset + x * sizeof(float)) = *(float*)(pSrcVertex + SrcOffset + x * sizeof(float)); + } + DestOffset += DestNumBlending * sizeof(float); + break; + } + } + + // Update source offset for Position data + switch (SrcFVF & D3DFVF_POSITION_MASK_9) + { + case D3DFVF_XYZW: + case D3DFVF_XYZRHW: + case D3DFVF_XYZB1: + SrcOffset += sizeof(float); + break; + case D3DFVF_XYZB2: + SrcOffset += 2 * sizeof(float); + break; + case D3DFVF_XYZB3: + SrcOffset += 3 * sizeof(float); + break; + case D3DFVF_XYZB4: + SrcOffset += 4 * sizeof(float); + break; + case D3DFVF_XYZB5: + SrcOffset += 5 * sizeof(float); + break; + } + + // Normal + if (DestFVF & D3DFVF_NORMAL) + { + if (SrcFVF & D3DFVF_NORMAL) + { + *(D3DXVECTOR3*)(pDestVertex + DestOffset) = *(D3DXVECTOR3*)(pSrcVertex + SrcOffset); + SrcOffset += 3 * sizeof(float); + } + DestOffset += 3 * sizeof(float); + } + else if (SrcFVF & D3DFVF_NORMAL) + { + SrcOffset += 3 * sizeof(float); + } + + // Point Size + if (DestFVF & D3DFVF_PSIZE) + { + if (SrcFVF & D3DFVF_PSIZE) + { + *(float*)(pDestVertex + DestOffset) = *(float*)(pSrcVertex + SrcOffset); + SrcOffset += sizeof(float); + } + DestOffset += sizeof(float); + } + else if (SrcFVF & D3DFVF_PSIZE) + { + SrcOffset += sizeof(float); + } + + // Diffuse color + if (DestFVF & D3DFVF_DIFFUSE) + { + if (SrcFVF & D3DFVF_DIFFUSE) + { + *(DWORD*)(pDestVertex + DestOffset) = *(DWORD*)(pSrcVertex + SrcOffset); + SrcOffset += sizeof(DWORD); + } + DestOffset += sizeof(DWORD); + } + else if (SrcFVF & D3DFVF_DIFFUSE) + { + SrcOffset += sizeof(DWORD); + } + + // Specular color + if (DestFVF & D3DFVF_SPECULAR) + { + if (SrcFVF & D3DFVF_SPECULAR) + { + *(DWORD*)(pDestVertex + DestOffset) = *(DWORD*)(pSrcVertex + SrcOffset); + SrcOffset += sizeof(DWORD); + } + DestOffset += sizeof(DWORD); + } + else if (SrcFVF & D3DFVF_SPECULAR) + { + SrcOffset += sizeof(DWORD); + } + + // Texture coordinates + int SrcNumTexCoords = (SrcFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + int DestNumTexCoords = (DestFVF & D3DFVF_TEXCOUNT_MASK) >> D3DFVF_TEXCOUNT_SHIFT; + int y = 0; + for (int x = 0; x < DestNumTexCoords; x++) + { + // Get number of destination texture coordinates + int DestCord = (DestFVF & (D3DFVF_TEXCOORDSIZE1(x) | D3DFVF_TEXCOORDSIZE2(x) | D3DFVF_TEXCOORDSIZE3(x) | D3DFVF_TEXCOORDSIZE4(x))); + int DestSize = + DestCord == D3DFVF_TEXCOORDSIZE1(x) ? 1 : + DestCord == D3DFVF_TEXCOORDSIZE2(x) ? 2 : + DestCord == D3DFVF_TEXCOORDSIZE3(x) ? 3 : + DestCord == D3DFVF_TEXCOORDSIZE4(x) ? 4 : 0; + // Find matching source texture coordinates + while (y < SrcNumTexCoords) + { + int SrcCord = (SrcFVF & (D3DFVF_TEXCOORDSIZE1(y) | D3DFVF_TEXCOORDSIZE2(y) | D3DFVF_TEXCOORDSIZE3(y) | D3DFVF_TEXCOORDSIZE4(y))); + int SrcSize = + SrcCord == D3DFVF_TEXCOORDSIZE1(y) ? 1 : + SrcCord == D3DFVF_TEXCOORDSIZE2(y) ? 2 : + SrcCord == D3DFVF_TEXCOORDSIZE3(y) ? 3 : + SrcCord == D3DFVF_TEXCOORDSIZE4(y) ? 4 : 0; + // Copy matching texture coordinates + if (SrcSize && DestSize == SrcSize) + { + for (int i = 0; i < SrcSize; i++) + { + *(float*)(pDestVertex + DestOffset + i * sizeof(float)) = *(float*)(pSrcVertex + SrcOffset + i * sizeof(float)); + } + SrcOffset += SrcSize * sizeof(float); + y++; + break; + } + SrcOffset += SrcSize * sizeof(float); + y++; + } + // Increase destination offset + DestOffset += DestSize * sizeof(float); + } +} + DWORD ConvertVertexTypeToFVF(D3DVERTEXTYPE d3dVertexType) { switch (d3dVertexType) diff --git a/ddraw/IDirect3DTypes.h b/ddraw/IDirect3DTypes.h index 1087266d..33293e94 100644 --- a/ddraw/IDirect3DTypes.h +++ b/ddraw/IDirect3DTypes.h @@ -61,6 +61,7 @@ void ConvertVertices(D3DLVERTEX* lFVF, D3DLVERTEX9* lFVF9, DWORD NumVertices); void ConvertVertices(D3DLVERTEX9* lFVF9, D3DLVERTEX* lFVF, DWORD NumVertices); bool CheckTextureStageStateType(D3DTEXTURESTAGESTATETYPE dwState); bool CheckRenderStateType(D3DRENDERSTATETYPE dwRenderStateType); +void ConvertVertex(BYTE* pDestVertex, DWORD DestFVF, const BYTE* pSrcVertex, DWORD SrcFVF); DWORD ConvertVertexTypeToFVF(D3DVERTEXTYPE d3dVertexType); UINT GetVertexStride(DWORD dwVertexTypeDesc); UINT GetNumberOfPrimitives(D3DPRIMITIVETYPE dptPrimitiveType, DWORD dwVertexCount); diff --git a/ddraw/IDirect3DVertexBufferX.cpp b/ddraw/IDirect3DVertexBufferX.cpp index e15d5aec..d302f4bb 100644 --- a/ddraw/IDirect3DVertexBufferX.cpp +++ b/ddraw/IDirect3DVertexBufferX.cpp @@ -289,38 +289,157 @@ HRESULT m_IDirect3DVertexBufferX::ProcessVertices(DWORD dwVertexOp, DWORD dwDest LOG_LIMIT(100, __FUNCTION__ << " Error: could not get d3d9 source vertex buffer!"); return DDERR_GENERIC; } + LPDIRECT3DVERTEXBUFFER9 d3d9DestVertexBuffer = d3d9VertexBuffer; - DWORD FVF = pSrcVertexBufferX->GetFVF9(); - D3DVERTEXELEMENT9 decl[MAX_FVF_DECL_SIZE] = {}; - if (FAILED(D3DXDeclaratorFromFVF(FVF, decl))) + // Get and verify FVF + DWORD SrcFVF = pSrcVertexBufferX->GetFVF9(); + DWORD DestFVF = GetFVF9(); + if (FAILED((*d3d9Device)->SetFVF(SrcFVF)) || FAILED((*d3d9Device)->SetFVF(DestFVF))) { - LOG_LIMIT(100, __FUNCTION__ << " Error: could not create vertex declaration!"); + LOG_LIMIT(100, __FUNCTION__ << " Error: could not set vertex declaration: " << Logging::hex(SrcFVF) << " -> " << Logging::hex(DestFVF)); return D3DERR_INVALIDVERTEXTYPE; } + UINT SrcStride = GetVertexStride(SrcFVF); + UINT DestStride = GetVertexStride(DestFVF); - IDirect3DVertexDeclaration9* pVertexDecl = nullptr; - if (FAILED((*d3d9Device)->CreateVertexDeclaration(decl, &pVertexDecl))) + // Check the dwDestIndex, dwSrcIndex and dwCount to make sure they won't cause an overload + DWORD SrcNumVertices = pSrcVertexBufferX->VBDesc.dwNumVertices; + DWORD DestNumVertices = VBDesc.dwNumVertices; + if (dwSrcIndex > SrcNumVertices || dwDestIndex > DestNumVertices) { - LOG_LIMIT(100, __FUNCTION__ << " Error: could not create vertex declaration!"); + LOG_LIMIT(100, __FUNCTION__ << " Error: vertex index is too large: " << + SrcNumVertices << " -> " << dwSrcIndex << " " << + DestNumVertices << " -> " << dwDestIndex); return D3DERR_INVALIDVERTEXTYPE; } + dwCount = min(dwCount, SrcNumVertices - dwSrcIndex); + dwCount = min(dwCount, DestNumVertices - dwDestIndex); - // Set stream source - (*d3d9Device)->SetStreamSource(0, d3d9SrcVertexBuffer, 0, GetVertexStride(FVF)); + D3DMATRIX matWorldViewProj = {}; + { + D3DMATRIX matWorld, matView, matProj, matWorldView = {}; + if (FAILED((*d3d9Device)->GetTransform(D3DTS_WORLD, &matWorld)) || + FAILED((*d3d9Device)->GetTransform(D3DTS_VIEW, &matView)) || + FAILED((*d3d9Device)->GetTransform(D3DTS_PROJECTION, &matProj))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to get world, view or projection matrix!"); + return DDERR_GENERIC; + } + + // Multiply the world, view and projection matrices + D3DXMatrixMultiply(&matWorldViewProj, D3DXMatrixMultiply(&matWorldView, &matWorld, &matView), &matProj); + } - // Process vertices - HRESULT hr = (*d3d9Device)->ProcessVertices(dwSrcIndex, dwDestIndex, dwCount, d3d9VertexBuffer, pVertexDecl, dwFlags); + void* pSrcVertices = nullptr; + void* pDestVertices = nullptr; - pVertexDecl->Release(); + HRESULT hr = D3D_OK; - if (FAILED(hr)) + do { + // Lock the source vertex buffer + if (FAILED(d3d9SrcVertexBuffer->Lock(0, 0, &pSrcVertices, D3DLOCK_READONLY))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to lock source vertex"); + hr = DDERR_GENERIC; + break; + } + + // Lock the destination vertex buffer + if (FAILED(d3d9DestVertexBuffer->Lock(0, 0, &pDestVertices, 0))) + { + LOG_LIMIT(100, __FUNCTION__ << " Error: failed to lock destination vertex"); + hr = DDERR_GENERIC; + break; + } + + bool CopyRHW = (((SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZRHW && (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZRHW) || + ((SrcFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZW && (DestFVF & D3DFVF_POSITION_MASK_9) == D3DFVF_XYZW)); + + BYTE* pSrcVertex = (BYTE*)pSrcVertices + (dwSrcIndex * SrcStride); + BYTE* pDestVertex = (BYTE*)pDestVertices + (dwDestIndex * DestStride); + + // Copy only position data + if ((dwFlags & D3DPV_DONOTCOPYDATA) && !CopyRHW) + { + for (UINT i = 0; i < dwCount; ++i) + { + // Apply the transformation to the position + D3DXVec3TransformCoord(reinterpret_cast(pDestVertex), reinterpret_cast(pSrcVertex), &matWorldViewProj); + + // Move to the next vertex + pSrcVertex = pSrcVertex + SrcStride; + pDestVertex = pDestVertex + DestStride; + } + } + // Copy position and RHW/W data + else if (dwFlags & D3DPV_DONOTCOPYDATA) + { + for (UINT i = 0; i < dwCount; ++i) + { + // Apply the transformation to the position + D3DXVec3TransformCoord(reinterpret_cast(pDestVertex), reinterpret_cast(pSrcVertex), &matWorldViewProj); + + // Copy RHW/W data + *(float*)(pDestVertex + 3 * sizeof(float)) = *(float*)(pSrcVertex + 3 * sizeof(float)); + + // Move to the next vertex + pSrcVertex = pSrcVertex + SrcStride; + pDestVertex = pDestVertex + DestStride; + } + } + // Copy all data + else if (SrcFVF == DestFVF) + { + memcpy(pDestVertex, pSrcVertex, DestStride * dwCount); + + for (UINT i = 0; i < dwCount; ++i) + { + // Apply the transformation to the position + D3DXVec3TransformCoord(reinterpret_cast(pDestVertex), reinterpret_cast(pSrcVertex), &matWorldViewProj); + + // Move to the next vertex + pSrcVertex = pSrcVertex + SrcStride; + pDestVertex = pDestVertex + DestStride; + } + } + // Copy all data converting vertices + else + { + for (UINT i = 0; i < dwCount; ++i) + { + // Convert and copy all vertex data + ConvertVertex(pDestVertex, DestFVF, pSrcVertex, SrcFVF); + + // Apply the transformation to the position + D3DXVec3TransformCoord(reinterpret_cast(pDestVertex), reinterpret_cast(pSrcVertex), &matWorldViewProj); + + // Move to the next vertex + pSrcVertex = pSrcVertex + SrcStride; + pDestVertex = pDestVertex + DestStride; + } + } + + // Handle D3DFVF_LVERTEX + if (VBDesc.dwFVF == D3DFVF_LVERTEX) + { + BYTE* pDestData = VertexData.data() + (dwDestIndex * LVERTEX_SIZE); + BYTE* pSrcData = (BYTE*)pDestVertices + (dwDestIndex * DestStride); // Destination vertex is the source for this copy + + ConvertVertices((D3DLVERTEX*)pDestData, (D3DLVERTEX9*)pSrcData, dwCount); + } + + } while (false); + + if (pSrcVertices) + { + d3d9SrcVertexBuffer->Unlock(); + } + if (pDestVertices) { - LOG_LIMIT(100, __FUNCTION__ << " Warning: 'ProcessVertices' call failed: " << (D3DERR)hr); + d3d9DestVertexBuffer->Unlock(); } - // ToDo: Fix this - // Just return OK for now - return D3D_OK; // hr; + return hr; } if (lpSrcBuffer)