diff --git a/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp b/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp index 0c0cd65de..af9731ee7 100644 --- a/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp +++ b/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp @@ -349,17 +349,14 @@ void DSStream_Packet_FlushEx_Reset( ) { // Remove flags only (This is the only place it will remove other than FlushEx perform set/remove the flags.) - pThis->EmuFlags &= ~(DSE_FLAG_FLUSH_ASYNC | DSE_FLAG_ENVELOPE | DSE_FLAG_ENVELOPE2 | DSE_FLAG_PAUSE); + pThis->EmuFlags &= ~(DSE_FLAG_FLUSH_ASYNC | DSE_FLAG_ENVELOPE | DSE_FLAG_ENVELOPE2); pThis->Xb_rtFlushEx = 0LL; - pThis->Xb_Status = 0; } bool DSStream_Packet_Flush( XTL::X_CDirectSoundStream* pThis ) { - DSStream_Packet_FlushEx_Reset(pThis); - // If host's audio is still playing then return busy-state until buffer has stop playing. DWORD dwStatus; pThis->EmuDirectSoundBuffer8->GetStatus(&dwStatus); @@ -376,5 +373,9 @@ bool DSStream_Packet_Flush( for (auto buffer = pThis->Host_BufferPacketArray.begin(); buffer != pThis->Host_BufferPacketArray.end();) { DSStream_Packet_Clear(buffer, XMP_STATUS_FLUSHED, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis); } + // Clear flags and set status to zero. + DSStream_Packet_FlushEx_Reset(pThis); + pThis->EmuFlags &= ~DSE_FLAG_PAUSE; + pThis->Xb_Status = 0; return false; } diff --git a/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp b/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp index fcca1d21e..cf5c0e953 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp @@ -110,7 +110,7 @@ void DirectSoundDoWork_Stream(xboxkrnl::LARGE_INTEGER& time) if (pThis->Xb_rtFlushEx == 0LL) { EmuLog(LOG_LEVEL::WARNING, "Attempted to flush without Xb_rtFlushEx set to non-zero"); } - while(DSStream_Packet_Flush(pThis)); + DSStream_Packet_Flush(pThis); } else { DSStream_Packet_Process(pThis); } @@ -393,10 +393,14 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_FlushEx) } // Remaining flags require X_DSSFLUSHEX_ASYNC to be include. else if ((dwFlags & X_DSSFLUSHEX_ASYNC) > 0) { - - pThis->EmuFlags |= DSE_FLAG_FLUSH_ASYNC; - // If rtTimeStamp is zero'd, then it must be flush in worker thread right away. + // If rtTimeStamp is zero'd, then call flush once and allow process flush in worker thread. if (rtTimeStamp == 0LL) { + bool isBusy = DSStream_Packet_Flush(pThis); + if (!isBusy) { + // testcase: Obscure will crash after new game's video if not call DSStream_Packet_Flush in same thread. + // If flush is not busy, then we don't need worker thread to continue flushing. + return hRet; + } xboxkrnl::LARGE_INTEGER getTime; xboxkrnl::KeQuerySystemTime(&getTime); pThis->Xb_rtFlushEx = getTime.QuadPart; @@ -405,6 +409,8 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_FlushEx) pThis->Xb_rtFlushEx = rtTimeStamp; } + pThis->EmuFlags |= DSE_FLAG_FLUSH_ASYNC; + // Set or remove flags (This is the only place it will set/remove other than flush perform remove the flags.) if ((dwFlags & X_DSSFLUSHEX_ENVELOPE) > 0) { pThis->Xb_rtFlushEx += (pThis->Xb_EnvolopeDesc.dwRelease * 512) / 48000;