diff --git a/Doc/Changelog.txt b/Doc/Changelog.txt index dea246d07..48ce03b04 100644 --- a/Doc/Changelog.txt +++ b/Doc/Changelog.txt @@ -1,5 +1,10 @@ cxbx website: http://www.caustik.com/xbox/ +version: 0.7.9 (??/??/??) +-------------------------------- + +- Spontaneous CreateDevice failures fixed (many, at least) + version: 0.7.8b (08/30/03) -------------------------------- diff --git a/Doc/Todo.txt b/Doc/Todo.txt index 4acd1e50f..2705482c6 100644 --- a/Doc/Todo.txt +++ b/Doc/Todo.txt @@ -1,5 +1,8 @@ Cxbx Todo (* denotes high priority, + denotes medium priority) + * CreateDevice/Release must be called in the context of the same thread, + so there needs to be a proxy CreateDevice and Release thread. + * Go lower level with mutants (maybe unnecessary), use \??\ and also set root directory to null. diff --git a/Include/Cxbx.h b/Include/Cxbx.h index 8537f7f37..5ee400ae0 100644 --- a/Include/Cxbx.h +++ b/Include/Cxbx.h @@ -68,9 +68,9 @@ typedef signed long sint32; // * Version information // ****************************************************************** #ifndef _DEBUG_TRACE -#define _CXBX_VERSION "0.7.8b" +#define _CXBX_VERSION "0.7.9-Pre1" #else -#define _CXBX_VERSION "0.7.8b-Trace" +#define _CXBX_VERSION "0.7.9-Pre1-Trace" #endif // ****************************************************************** diff --git a/Source/Win32/CxbxKrnl/EmuD3D8.cpp b/Source/Win32/CxbxKrnl/EmuD3D8.cpp index 9b05ffa46..f38f92402 100644 --- a/Source/Win32/CxbxKrnl/EmuD3D8.cpp +++ b/Source/Win32/CxbxKrnl/EmuD3D8.cpp @@ -68,6 +68,7 @@ HWND XTL::g_hEmuWindow = NULL; // Rendering Window // * Static Function(s) // ****************************************************************** static DWORD WINAPI EmuRenderWindow(LPVOID); +static DWORD WINAPI EmuCreateDeviceProxy(LPVOID); static LRESULT WINAPI EmuMsgProc(HWND hWnd, UINT msg, WPARAM wParam, LPARAM lParam); static DWORD WINAPI EmuUpdateTickCount(LPVOID); static DWORD EmuCheckAllocationSize(LPVOID); @@ -114,6 +115,22 @@ DWORD *XTL::EmuD3DDeferredRenderState; // ****************************************************************** DWORD *XTL::EmuD3DDeferredTextureState; +// ****************************************************************** +// * EmuD3D8CreateDeviceProxyData +// ****************************************************************** +struct EmuD3D8CreateDeviceProxyData +{ + XTL::UINT Adapter; + XTL::D3DDEVTYPE DeviceType; + HWND hFocusWindow; + XTL::DWORD BehaviorFlags; + XTL::X_D3DPRESENT_PARAMETERS *pPresentationParameters; + XTL::IDirect3DDevice8 **ppReturnedDeviceInterface; + volatile bool bReady; + volatile HRESULT hRet; +} +g_EmuD3D8CreateDeviceProxyData = {0}; + // ****************************************************************** // * func: XTL::EmuD3DInit // ****************************************************************** @@ -136,6 +153,15 @@ VOID XTL::EmuD3DInit(Xbe::Header *XbeHeader, uint32 XbeHeaderSize) CreateThread(NULL, NULL, EmuUpdateTickCount, NULL, NULL, &dwThreadId); } + // ****************************************************************** + // * create a thread dedicated to creating devices + // ****************************************************************** + { + DWORD dwThreadId; + + CreateThread(NULL, NULL, EmuCreateDeviceProxy, NULL, NULL, &dwThreadId); + } + // ****************************************************************** // * spark up a new thread to handle window message processing // ****************************************************************** @@ -416,6 +442,223 @@ static DWORD WINAPI EmuUpdateTickCount(LPVOID) timeEndPeriod(0); } +// ****************************************************************** +// * func: EmuCreateDeviceProxy +// ****************************************************************** +static DWORD WINAPI EmuCreateDeviceProxy(LPVOID) +{ + printf("EmuD3D8 (0x%X): CreateDevice proxy thread is running.\n", GetCurrentThreadId()); + + while(true) + { + // if we have been signalled, create the device with cached parameters + if(g_EmuD3D8CreateDeviceProxyData.bReady) + { + printf("EmuD3D8 (0x%X): CreateDevice proxy thread recieved request.\n", GetCurrentThreadId()); + + // only one device should be created at once + // TODO: ensure all surfaces are somehow cleaned up? + if(g_pD3DDevice8 != 0) + { + printf("EmuD3D8 (0x%X): CreateDevice proxy thread releasing old Device.\n", GetCurrentThreadId()); + + g_pD3DDevice8->EndScene(); + + while(g_pD3DDevice8->Release() != 0); + + g_pD3DDevice8 = 0; + } + + // ****************************************************************** + // * verify no ugly circumstances + // ****************************************************************** + if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BufferSurfaces[0] != NULL || g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->DepthStencilSurface != NULL) + EmuWarning("DepthStencilSurface != NULL and/or BufferSurfaces[0] != NULL"); + + // ****************************************************************** + // * make adjustments to parameters to make sense with windows d3d + // ****************************************************************** + { + g_EmuD3D8CreateDeviceProxyData.DeviceType =(g_XBVideo.GetDirect3DDevice() == 0) ? XTL::D3DDEVTYPE_HAL : XTL::D3DDEVTYPE_REF; + g_EmuD3D8CreateDeviceProxyData.Adapter = g_XBVideo.GetDisplayAdapter(); + + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Windowed = !g_XBVideo.GetFullscreen(); + + if(g_XBVideo.GetVSync()) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->SwapEffect = XTL::D3DSWAPEFFECT_COPY_VSYNC; + + g_EmuD3D8CreateDeviceProxyData.hFocusWindow = XTL::g_hEmuWindow; + + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::EmuXB2PC_D3DFormat(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat); + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->AutoDepthStencilFormat = XTL::EmuXB2PC_D3DFormat(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->AutoDepthStencilFormat); + + if(!g_XBVideo.GetVSync() && (g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) && g_XBVideo.GetFullscreen()) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; + else + { + if(g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE && g_XBVideo.GetFullscreen()) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; + else + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; + } + + // TODO: Support Xbox extensions if possible + if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType != 0) + { + EmuWarning("MultiSampleType 0x%.08X is not supported!", g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType); + + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->MultiSampleType = XTL::D3DMULTISAMPLE_NONE; + + // TODO: Check card for multisampling abilities + // if(pPresentationParameters->MultiSampleType == 0x00001121) + // pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; + // else + // EmuCleanup("Unknown MultiSampleType (0x%.08X)", pPresentationParameters->MultiSampleType); + } + + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; + + // ****************************************************************** + // * Retrieve Resolution from Configuration + // ****************************************************************** + if(g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->Windowed) + { + sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferWidth, &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferHeight); + + XTL::D3DDISPLAYMODE D3DDisplayMode; + + g_pD3D8->GetAdapterDisplayMode(g_XBVideo.GetDisplayAdapter(), &D3DDisplayMode); + + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = D3DDisplayMode.Format; + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_RefreshRateInHz = 0; + } + else + { + char szBackBufferFormat[16]; + + sscanf(g_XBVideo.GetVideoResolution(), "%d x %d %*dbit %s (%d hz)", + &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferWidth, + &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferHeight, + szBackBufferFormat, + &g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->FullScreen_RefreshRateInHz); + + if(strcmp(szBackBufferFormat, "x1r5g5b5") == 0) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X1R5G5B5; + else if(strcmp(szBackBufferFormat, "r5g6r5") == 0) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_R5G6B5; + else if(strcmp(szBackBufferFormat, "x8r8g8b8") == 0) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_X8R8G8B8; + else if(strcmp(szBackBufferFormat, "a8r8g8b8") == 0) + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters->BackBufferFormat = XTL::D3DFMT_A8R8G8B8; + } + } + + // ****************************************************************** + // * Detect vertex processing capabilities + // ****************************************************************** + if((g_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && g_EmuD3D8CreateDeviceProxyData.DeviceType == XTL::D3DDEVTYPE_HAL) + { + #ifdef _DEBUG_TRACE + printf("EmuD3D8 (0x%X): Using hardware vertex processing\n", GetCurrentThreadId()); + #endif + g_EmuD3D8CreateDeviceProxyData.BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; + g_dwVertexShaderUsage = 0; + } + else + { + #ifdef _DEBUG_TRACE + printf("EmuD3D8 (0x%X): Using software vertex processing\n", GetCurrentThreadId()); + #endif + g_EmuD3D8CreateDeviceProxyData.BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; + g_dwVertexShaderUsage = D3DUSAGE_SOFTWAREPROCESSING; + } + + // ****************************************************************** + // * redirect to windows d3d + // ****************************************************************** + g_EmuD3D8CreateDeviceProxyData.hRet = g_pD3D8->CreateDevice + ( + g_EmuD3D8CreateDeviceProxyData.Adapter, + g_EmuD3D8CreateDeviceProxyData.DeviceType, + g_EmuD3D8CreateDeviceProxyData.hFocusWindow, + g_EmuD3D8CreateDeviceProxyData.BehaviorFlags, + (XTL::D3DPRESENT_PARAMETERS*)g_EmuD3D8CreateDeviceProxyData.pPresentationParameters, + g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface + ); + + // ****************************************************************** + // * report error + // ****************************************************************** + if(FAILED(g_EmuD3D8CreateDeviceProxyData.hRet)) + { + if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_INVALIDCALL) + EmuCleanup("IDirect3D8::CreateDevice failed (Invalid Call)"); + else if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_NOTAVAILABLE) + EmuCleanup("IDirect3D8::CreateDevice failed (Not Available)"); + else if(g_EmuD3D8CreateDeviceProxyData.hRet == D3DERR_OUTOFVIDEOMEMORY) + EmuCleanup("IDirect3D8::CreateDevice failed (Out of Video Memory)"); + + EmuCleanup("IDirect3D8::CreateDevice failed (Unknown)"); + } + + // ****************************************************************** + // * it is necessary to store this pointer globally for emulation + // ****************************************************************** + g_pD3DDevice8 = *g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface; + + // ****************************************************************** + // * check for YUY2 overlay support + // ****************************************************************** + { + XTL::D3DDISPLAYMODE DisplayMode; + + if(g_pD3DDevice8->GetDisplayMode(&DisplayMode) != D3D_OK) + g_bSupportsYUY2 = FALSE; + else + { + ::HRESULT hRet = g_pD3D8->CheckDeviceFormat + ( + g_EmuD3D8CreateDeviceProxyData.Adapter, g_EmuD3D8CreateDeviceProxyData.DeviceType, + (XTL::D3DFORMAT)DisplayMode.Format, 0, XTL::D3DRTYPE_TEXTURE, XTL::D3DFMT_YUY2 + ); + + g_bSupportsYUY2 = SUCCEEDED(hRet); + + if(!g_bSupportsYUY2) + EmuWarning("YUY2 overlays are not supported in hardware, could be slow!"); + } + } + + // ****************************************************************** + // * Update Caches + // ****************************************************************** + { + g_pCachedRenderTarget = new XTL::X_D3DSurface(); + g_pD3DDevice8->GetRenderTarget(&g_pCachedRenderTarget->EmuSurface8); + + g_pCachedZStencilSurface = new XTL::X_D3DSurface(); + g_pD3DDevice8->GetDepthStencilSurface(&g_pCachedZStencilSurface->EmuSurface8); + } + + // ****************************************************************** + // * Begin Scene + // ****************************************************************** + g_pD3DDevice8->BeginScene(); + + // ****************************************************************** + // * Initially, show a black screen + // ****************************************************************** + g_pD3DDevice8->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0); + g_pD3DDevice8->Present(0, 0, 0, 0); + + // signal completion + g_EmuD3D8CreateDeviceProxyData.bReady = false; + } + + Sleep(1); + } +} + // ****************************************************************** // * func: EmuCheckAllocationSize // ****************************************************************** @@ -517,183 +760,22 @@ HRESULT WINAPI XTL::EmuIDirect3D8_CreateDevice } #endif - // only one device should be created at once - // TODO: ensure all surfaces are somehow cleaned up? - if(g_pD3DDevice8 != 0) - { - g_pD3DDevice8->Release(); - g_pD3DDevice8 = 0; - } + // Cache parameters + g_EmuD3D8CreateDeviceProxyData.Adapter = Adapter; + g_EmuD3D8CreateDeviceProxyData.DeviceType = DeviceType; + g_EmuD3D8CreateDeviceProxyData.hFocusWindow = hFocusWindow; + g_EmuD3D8CreateDeviceProxyData.pPresentationParameters = pPresentationParameters; + g_EmuD3D8CreateDeviceProxyData.ppReturnedDeviceInterface = ppReturnedDeviceInterface; - // ****************************************************************** - // * verify no ugly circumstances - // ****************************************************************** - if(pPresentationParameters->BufferSurfaces[0] != NULL || pPresentationParameters->DepthStencilSurface != NULL) - EmuWarning("DepthStencilSurface != NULL and/or BufferSurfaces[0] != NULL"); + // Signal proxy thread, and wait for completion + g_EmuD3D8CreateDeviceProxyData.bReady = true; - // ****************************************************************** - // * make adjustments to parameters to make sense with windows d3d - // ****************************************************************** - { - DeviceType =(g_XBVideo.GetDirect3DDevice() == 0) ? D3DDEVTYPE_HAL : D3DDEVTYPE_REF; - Adapter = g_XBVideo.GetDisplayAdapter(); - - pPresentationParameters->Windowed = !g_XBVideo.GetFullscreen(); - - if(g_XBVideo.GetVSync()) - pPresentationParameters->SwapEffect = D3DSWAPEFFECT_COPY_VSYNC; - - hFocusWindow = g_hEmuWindow; - - pPresentationParameters->BackBufferFormat = EmuXB2PC_D3DFormat(pPresentationParameters->BackBufferFormat); - pPresentationParameters->AutoDepthStencilFormat = EmuXB2PC_D3DFormat(pPresentationParameters->AutoDepthStencilFormat); - - if(!g_XBVideo.GetVSync() && (g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_IMMEDIATE) && g_XBVideo.GetFullscreen()) - pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE; - else - { - if(g_D3DCaps.PresentationIntervals & D3DPRESENT_INTERVAL_ONE && g_XBVideo.GetFullscreen()) - pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_ONE; - else - pPresentationParameters->FullScreen_PresentationInterval = D3DPRESENT_INTERVAL_DEFAULT; - } - - // TODO: Support Xbox extensions if possible - if(pPresentationParameters->MultiSampleType != 0) - { - EmuWarning("MultiSampleType 0x%.08X is not supported!", pPresentationParameters->MultiSampleType); - - pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_NONE; - - // TODO: Check card for multisampling abilities -// if(pPresentationParameters->MultiSampleType == 0x00001121) -// pPresentationParameters->MultiSampleType = D3DMULTISAMPLE_2_SAMPLES; -// else -// EmuCleanup("Unknown MultiSampleType (0x%.08X)", pPresentationParameters->MultiSampleType); - } - - pPresentationParameters->Flags |= D3DPRESENTFLAG_LOCKABLE_BACKBUFFER; - - // ****************************************************************** - // * Retrieve Resolution from Configuration - // ****************************************************************** - if(pPresentationParameters->Windowed) - { - sscanf(g_XBVideo.GetVideoResolution(), "%d x %d", &pPresentationParameters->BackBufferWidth, &pPresentationParameters->BackBufferHeight); - - D3DDISPLAYMODE D3DDisplayMode; - - g_pD3D8->GetAdapterDisplayMode(g_XBVideo.GetDisplayAdapter(), &D3DDisplayMode); - - pPresentationParameters->BackBufferFormat = D3DDisplayMode.Format; - pPresentationParameters->FullScreen_RefreshRateInHz = 0; - } - else - { - char szBackBufferFormat[16]; - - sscanf(g_XBVideo.GetVideoResolution(), "%d x %d %*dbit %s (%d hz)", - &pPresentationParameters->BackBufferWidth, - &pPresentationParameters->BackBufferHeight, - szBackBufferFormat, - &pPresentationParameters->FullScreen_RefreshRateInHz); - - if(strcmp(szBackBufferFormat, "x1r5g5b5") == 0) - pPresentationParameters->BackBufferFormat = D3DFMT_X1R5G5B5; - else if(strcmp(szBackBufferFormat, "r5g6r5") == 0) - pPresentationParameters->BackBufferFormat = D3DFMT_R5G6B5; - else if(strcmp(szBackBufferFormat, "x8r8g8b8") == 0) - pPresentationParameters->BackBufferFormat = D3DFMT_X8R8G8B8; - else if(strcmp(szBackBufferFormat, "a8r8g8b8") == 0) - pPresentationParameters->BackBufferFormat = D3DFMT_A8R8G8B8; - } - } - - // ****************************************************************** - // * Detect vertex processing capabilities - // ****************************************************************** - if((g_D3DCaps.DevCaps & D3DDEVCAPS_HWTRANSFORMANDLIGHT) && DeviceType == D3DDEVTYPE_HAL) - { - #ifdef _DEBUG_TRACE - printf("EmuD3D8 (0x%X): Using hardware vertex processing\n", GetCurrentThreadId()); - #endif - BehaviorFlags = D3DCREATE_HARDWARE_VERTEXPROCESSING; - g_dwVertexShaderUsage = 0; - } - else - { - #ifdef _DEBUG_TRACE - printf("EmuD3D8 (0x%X): Using software vertex processing\n", GetCurrentThreadId()); - #endif - BehaviorFlags = D3DCREATE_SOFTWARE_VERTEXPROCESSING; - g_dwVertexShaderUsage = D3DUSAGE_SOFTWAREPROCESSING; - } - - // ****************************************************************** - // * redirect to windows d3d - // ****************************************************************** - HRESULT hRet = g_pD3D8->CreateDevice - ( - Adapter, - DeviceType, - hFocusWindow, - BehaviorFlags, - (XTL::D3DPRESENT_PARAMETERS*)pPresentationParameters, - ppReturnedDeviceInterface - ); - - if(FAILED(hRet)) - EmuCleanup("IDirect3D8::CreateDevice failed (Invalid Display Settings?)"); - - // ****************************************************************** - // * it is necessary to store this pointer globally for emulation - // ****************************************************************** - g_pD3DDevice8 = *ppReturnedDeviceInterface; - - // ****************************************************************** - // * check for YUY2 overlay support - // ****************************************************************** - { - D3DDISPLAYMODE DisplayMode; - - if(g_pD3DDevice8->GetDisplayMode(&DisplayMode) != D3D_OK) - g_bSupportsYUY2 = FALSE; - else - { - HRESULT hRet = g_pD3D8->CheckDeviceFormat(Adapter, DeviceType, (XTL::D3DFORMAT)DisplayMode.Format, 0, D3DRTYPE_TEXTURE, D3DFMT_YUY2); - - g_bSupportsYUY2 = SUCCEEDED(hRet); - - if(!g_bSupportsYUY2) - EmuWarning("YUY2 overlays are not supported in hardware, could be slow!"); - } - } - - // ****************************************************************** - // * Update Caches - // ****************************************************************** - { - g_pCachedRenderTarget = new X_D3DSurface(); - g_pD3DDevice8->GetRenderTarget(&g_pCachedRenderTarget->EmuSurface8); - - g_pCachedZStencilSurface = new X_D3DSurface(); - g_pD3DDevice8->GetDepthStencilSurface(&g_pCachedZStencilSurface->EmuSurface8); - } - - // ****************************************************************** - // * Begin Scene - // ****************************************************************** - g_pD3DDevice8->BeginScene(); - - // ****************************************************************** - // * Initially, show a black screen - // ****************************************************************** - g_pD3DDevice8->Clear(0, 0, D3DCLEAR_TARGET, 0, 0, 0); - g_pD3DDevice8->Present(0, 0, 0, 0); + while(g_EmuD3D8CreateDeviceProxyData.bReady) + Sleep(10); EmuSwapFS(); // XBox FS - return hRet; + return g_EmuD3D8CreateDeviceProxyData.hRet; } // ****************************************************************** @@ -1313,18 +1395,18 @@ HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface X_D3DSurface **ppZStencilSurface ) { + EmuSwapFS(); // Win2k/XP FS + // ****************************************************************** // * debug trace // ****************************************************************** #ifdef _DEBUG_TRACE { - EmuSwapFS(); // Win2k/XP FS printf("EmuD3D8 (0x%X): EmuIDirect3DDevice8_GetDepthStencilSurface\n" "(\n" " ppZStencilSurface : 0x%.08X\n" ");\n", GetCurrentThreadId(), ppZStencilSurface); - EmuSwapFS(); // Xbox FS } #endif @@ -1335,6 +1417,8 @@ HRESULT WINAPI XTL::EmuIDirect3DDevice8_GetDepthStencilSurface *ppZStencilSurface = g_pCachedZStencilSurface; + EmuSwapFS(); // Xbox FS + return D3D_OK; } @@ -3308,6 +3392,7 @@ ULONG WINAPI XTL::EmuIDirect3DDevice8_Release() } #endif + EmuCleanup("Release should use proxy..."); ULONG uRet = g_pD3DDevice8->Release(); EmuSwapFS(); // XBox FS