diff --git a/Cxbx.opt b/Cxbx.opt index 93b51b99a..787b0ad0a 100644 Binary files a/Cxbx.opt and b/Cxbx.opt differ diff --git a/Source/Win32/CxbxKrnl/EmuD3D8.cpp b/Source/Win32/CxbxKrnl/EmuD3D8.cpp index 94e5b6e2d..7f7ca7fa5 100644 --- a/Source/Win32/CxbxKrnl/EmuD3D8.cpp +++ b/Source/Win32/CxbxKrnl/EmuD3D8.cpp @@ -3633,6 +3633,7 @@ HRESULT WINAPI XTL::EmuIDirect3DResource8_Register // TODO: HACK: Temporary? if(X_Format == 0x2E) { + EmuCleanup("D3DFMT_LIN_D24S8 not yet supported!"); X_Format = 0x12; Format = D3DFMT_A8R8G8B8; } @@ -3852,19 +3853,19 @@ HRESULT WINAPI XTL::EmuIDirect3DResource8_Register { if(bSwizzled) { - if((DWORD)pSrc == 0x80000000) - { - // TODO: Fix or handle this situation..? - } - else - { - XTL::EmuXGUnswizzleRect - ( - pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits, - LockedRect.Pitch, iRect, iPoint, dwBPP - ); - } + if((DWORD)pSrc == 0x80000000) + { + // TODO: Fix or handle this situation..? } + else + { + XTL::EmuXGUnswizzleRect + ( + pSrc + dwMipOffs, dwMipWidth, dwMipHeight, dwDepth, LockedRect.pBits, + LockedRect.Pitch, iRect, iPoint, dwBPP + ); + } + } else if(bCompressed) { // NOTE: compressed size is (dwWidth/2)*(dwHeight/2)/2, so each level divides by 4 diff --git a/Source/Win32/CxbxKrnl/EmuD3D8/PushBuffer.cpp b/Source/Win32/CxbxKrnl/EmuD3D8/PushBuffer.cpp index 87d54ff59..c115c48ba 100644 --- a/Source/Win32/CxbxKrnl/EmuD3D8/PushBuffer.cpp +++ b/Source/Win32/CxbxKrnl/EmuD3D8/PushBuffer.cpp @@ -44,6 +44,8 @@ bool XTL::g_bBrkPush = false; bool g_bPBSkipPusher = false; +static void DbgDumpMesh(WORD *pIndexData, DWORD dwCount); + // pushbuffer execution emulation void XTL::EmuExecutePushBuffer ( @@ -58,6 +60,10 @@ void XTL::EmuExecutePushBuffer EmuCleanup("PushBuffer has fixups\n"); DWORD *pdwPushData = (DWORD*)pPushBuffer->Data; + PVOID pIndexData = 0; + + // cache of last 4 indices + WORD pIBMem[4] = {0xFFFF, 0xFFFF, 0xFFFF, 0xFFFF}; D3DPRIMITIVETYPE PCPrimitiveType = (D3DPRIMITIVETYPE)-1; X_D3DPRIMITIVETYPE XBPrimitiveType = X_D3DPT_INVALID; @@ -65,10 +71,6 @@ void XTL::EmuExecutePushBuffer // TODO: This technically should be enabled XTL::EmuUpdateDeferredStates(); -// g_pD3DDevice8->Clear(0, NULL, D3DCLEAR_ZBUFFER, 0, 1.0, NULL); -// g_pD3DDevice8->SetRenderState(D3DRS_ZENABLE, FALSE); -// g_pD3DDevice8->SetRenderState(D3DRS_CULLMODE, D3DCULL_CCW); - #ifdef _DEBUG_TRACK_PB bool bShowPB = false; @@ -87,7 +89,8 @@ void XTL::EmuExecutePushBuffer } #endif - // NOTE: I believe 0x1808 is actually a seperate command, but I need to verify this. + static LPDIRECT3DINDEXBUFFER8 pIndexBuffer=0; + static uint maxIBSize = 0; while(true) { @@ -129,29 +132,135 @@ void XTL::EmuExecutePushBuffer PCPrimitiveType = EmuPrimitiveType(XBPrimitiveType); } } - else // NVPB_InlineArray + else if(dwMethod == 0x1808) // NVPB_FixLoop { - PVOID pIndexData = 0; - BOOL bInc = *pdwPushData & 0x40000000; - - BOOL bFix = (dwMethod != 0x00001818); - - if(bFix) + #ifdef _DEBUG_TRACK_PB + if(bShowPB) { - if(bInc) - dwCount = ((*pdwPushData - (0x40000000 | 0x00001818)) >> 18); + printf(" NVPB_FixLoop(%d)\n", dwCount); + printf("\n"); + printf(" Index Array Data...\n"); - dwMethod = 0x1818; + WORD *pwVal = (WORD*)(pdwPushData + 1); + + for(uint s=0;s maxIBSize) + { + if(pIndexBuffer != 0) + { + pIndexBuffer->Release(); + } + + hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*2 + 2*2, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer); + + maxIBSize = dwCount*2 + 2*2; + } + else + { + hRet = D3D_OK; + } + + if(FAILED(hRet)) + EmuCleanup("Unable to create index buffer for PushBuffer emulation (0x1808, dwCount : %d)", dwCount); + + // copy index data + { + WORD *pData=0; + + pIndexBuffer->Lock(0, dwCount*2 + 2*2, (UCHAR**)&pData, NULL); + + memcpy(pData, pIBMem, dwCount*2 + 2*2); + + pIndexBuffer->Unlock(); + } + + // render indexed vertices + { + UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount + 2); + VertexPatchDesc VPDesc; + + VPDesc.dwVertexCount = dwCount; + VPDesc.PrimitiveType = XBPrimitiveType; + VPDesc.dwPrimitiveCount = PrimitiveCount; + VPDesc.dwOffset = 0; + VPDesc.pVertexStreamZeroData = 0; + VPDesc.uiVertexStreamZeroStride = 0; + // TODO: Set the current shader and let the patcher handle it.. + VPDesc.hVertexShader = g_CurrentVertexShader; + + VertexPatcher VertPatch; + + bool bPatched = VertPatch.Apply(&VPDesc); + + g_pD3DDevice8->SetIndices(pIndexBuffer, 0); + + #ifdef _DEBUG_TRACK_PB + if(!g_PBTrackDisable.exists((PVOID)pPushBuffer->Data)) + { + #endif + + if(!g_bPBSkipPusher) + { + if(IsValidCurrentShader()) + { + g_pD3DDevice8->DrawIndexedPrimitive + ( + PCPrimitiveType, 0, 8*1024*1024, 0, PrimitiveCount +// PCPrimitiveType, 0, dwCount*2, 0, PrimitiveCount + ); + } + } + + #ifdef _DEBUG_TRACK_PB + } + #endif + + VertPatch.Restore(); + + g_pD3DDevice8->SetIndices(0, 0); + } + } + + pdwPushData += dwCount; + } + else if(dwMethod == 0x1800) // NVPB_InlineArray + { + BOOL bInc = *pdwPushData & 0x40000000; + + if(bInc) + { + dwCount = ((*pdwPushData - (0x40000000 | 0x00001818)) >> 18)*2 + 2; + } + + pIndexData = ++pdwPushData; #ifdef _DEBUG_TRACK_PB if(bShowPB) { - printf(" NVPB_InlineArray(0x%.08X)...\n", pIndexData); + printf(" NVPB_InlineArray(0x%.08X, %d)...\n", pIndexData, dwCount); printf("\n"); printf(" Index Array Data...\n"); @@ -198,29 +307,28 @@ void XTL::EmuExecutePushBuffer // release ptr pActiveVB->Unlock(); + + DbgDumpMesh(pIndexData, dwCount); } #endif - - pdwPushData += dwCount - (bInc ? 0 : 1); - + + pdwPushData += (dwCount/2) - (bInc ? 0 : 2); + // perform rendering { - static LPDIRECT3DINDEXBUFFER8 pIndexBuffer=0; - static uint maxSize = 0; - HRESULT hRet; - // TODO: depreciate maxSize after N milliseconds..then N milliseconds later drop down to new highest - if(dwCount*4 > maxSize) + // TODO: depreciate maxIBSize after N milliseconds..then N milliseconds later drop down to new highest + if(dwCount*2 > maxIBSize) { if(pIndexBuffer != 0) { pIndexBuffer->Release(); } - hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*4, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer); + hRet = g_pD3DDevice8->CreateIndexBuffer(dwCount*2, 0, D3DFMT_INDEX16, D3DPOOL_MANAGED, &pIndexBuffer); - maxSize = dwCount*4; + maxIBSize = dwCount*2; } else { @@ -234,19 +342,30 @@ void XTL::EmuExecutePushBuffer { WORD *pData=0; - pIndexBuffer->Lock(0, dwCount*4, (UCHAR**)&pData, NULL); + pIndexBuffer->Lock(0, dwCount*2, (UCHAR**)&pData, NULL); - memcpy(pData, pIndexData, dwCount*4); + memcpy(pData, pIndexData, dwCount*2); + + // remember last 2 indices + if(dwCount >= 2) + { + pIBMem[0] = pData[dwCount - 2]; + pIBMem[1] = pData[dwCount - 1]; + } + else + { + pIBMem[0] = 0xFFFF; + } pIndexBuffer->Unlock(); } // render indexed vertices { - UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount * 2); + UINT PrimitiveCount = EmuD3DVertex2PrimitiveCount(XBPrimitiveType, dwCount); VertexPatchDesc VPDesc; - VPDesc.dwVertexCount = dwCount * 2; + VPDesc.dwVertexCount = dwCount; VPDesc.PrimitiveType = XBPrimitiveType; VPDesc.dwPrimitiveCount = PrimitiveCount; VPDesc.dwOffset = 0; @@ -309,6 +428,12 @@ void XTL::EmuExecutePushBuffer g_pD3DDevice8->SetIndices(0, 0); } } + + pdwPushData--; + } + else + { + EmuCleanup("Unknown PushBuffer Operation (0x%.04X, %d)", dwMethod, dwCount); } pdwPushData++; @@ -329,3 +454,129 @@ void XTL::EmuExecutePushBuffer Sleep(500); } } + +#ifdef _DEBUG_TRACK_PB +void DbgDumpMesh(WORD *pIndexData, DWORD dwCount) +{ + if(!XTL::IsValidCurrentShader() || (dwCount == 0)) + return; + + XTL::IDirect3DVertexBuffer8 *pActiveVB = NULL; + + XTL::D3DVERTEXBUFFER_DESC VBDesc; + + BYTE *pVBData = 0; + UINT uiStride; + + // retrieve stream data + g_pD3DDevice8->GetStreamSource(0, &pActiveVB, &uiStride); + + char szFileName[128]; + sprintf(szFileName, "C:\\TurokMesh-0x%.08X.x", pIndexData); + FILE *dbgVertices = fopen(szFileName, "wt"); + + // retrieve stream desc + pActiveVB->GetDesc(&VBDesc); + + // unlock just in case + pActiveVB->Unlock(); + + // grab ptr + pActiveVB->Lock(0, 0, &pVBData, D3DLOCK_READONLY); + + // print out stream data + { + uint32 maxIndex = 0; + + WORD *pwChk = (WORD*)pIndexData; + + for(uint chk=0;chk maxIndex) + maxIndex = x; + } + + if(maxIndex > ((VBDesc.Size/uiStride) - 1)) + maxIndex = (VBDesc.Size / uiStride) - 1; + + fprintf(dbgVertices, "xof 0303txt 0032\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, "//\n"); + fprintf(dbgVertices, "// Vertex Stream Data (0x%.08X)...\n", pActiveVB); + fprintf(dbgVertices, "//\n"); + fprintf(dbgVertices, "// Format : %d\n", VBDesc.Format); + fprintf(dbgVertices, "// Size : %d bytes\n", VBDesc.Size); + fprintf(dbgVertices, "// FVF : 0x%.08X\n", VBDesc.FVF); + fprintf(dbgVertices, "// iCount : %d\n", dwCount/2); + fprintf(dbgVertices, "//\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, "Frame SCENE_ROOT {\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, " FrameTransformMatrix {\n"); + fprintf(dbgVertices, " 1.000000,0.000000,0.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,1.000000,0.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,0.000000,1.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,0.000000,0.000000,1.000000;;\n"); + fprintf(dbgVertices, " }\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, " Frame Turok1 {\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, " FrameTransformMatrix {\n"); + fprintf(dbgVertices, " 1.000000,0.000000,0.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,1.000000,0.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,0.000000,1.000000,0.000000,\n"); + fprintf(dbgVertices, " 0.000000,0.000000,0.000000,1.000000;;\n"); + fprintf(dbgVertices, " }\n"); + fprintf(dbgVertices, "\n"); + fprintf(dbgVertices, " Mesh {\n"); + fprintf(dbgVertices, " %d;\n", maxIndex+1); + + uint max = maxIndex+1; + for(uint v=0;vUnlock(); +} +#endif diff --git a/Source/Win32/CxbxKrnl/ResourceTracker.cpp b/Source/Win32/CxbxKrnl/ResourceTracker.cpp index 230cf8c85..a18c64de5 100644 --- a/Source/Win32/CxbxKrnl/ResourceTracker.cpp +++ b/Source/Win32/CxbxKrnl/ResourceTracker.cpp @@ -226,4 +226,4 @@ uint32 ResourceTracker::get_count(void) this->Unlock(); return uiCount; -} \ No newline at end of file +}