diff --git a/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp b/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp index 3cb06070f..a2165dcdd 100644 --- a/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp +++ b/src/core/hle/DSOUND/DirectSound/DSStream_PacketManager.cpp @@ -217,6 +217,10 @@ bool DSStream_Packet_Process( return 0; } + if (pThis->EmuFlags & DSE_FLAG_IS_FLUSHING) { + return 0; + } + if (!(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED)) { pThis->EmuFlags |= DSE_FLAG_IS_ACTIVATED; } @@ -347,7 +351,9 @@ bool DSStream_Packet_Flush( xbox::X_CDirectSoundStream* pThis ) { - + if ((pThis->EmuFlags & DSE_FLAG_IS_FLUSHING) == 0) { + pThis->EmuFlags |= DSE_FLAG_IS_FLUSHING; + } // If host's audio is still playing then return busy-state until buffer has stop playing. DWORD dwStatus; pThis->EmuDirectSoundBuffer8->GetStatus(&dwStatus); @@ -373,5 +379,6 @@ bool DSStream_Packet_Flush( if ((pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED) != 0) { pThis->EmuFlags &= ~(DSE_FLAG_PAUSE | DSE_FLAG_IS_ACTIVATED); } + pThis->EmuFlags &= ~DSE_FLAG_IS_FLUSHING; return false; } diff --git a/src/core/hle/DSOUND/DirectSound/DirectSound.hpp b/src/core/hle/DSOUND/DirectSound/DirectSound.hpp index 207e166ad..e87167707 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSound.hpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSound.hpp @@ -139,6 +139,7 @@ struct SharedDSBuffer : DSBUFFER_S { #define DSE_FLAG_ENVELOPE2 (1 << 15) // NOTE: This flag is a requirement for GetStatus to return X_DSSSTATUS_ENVELOPECOMPLETE value. #define DSE_FLAG_RECIEVEDATA (1 << 20) #define DSE_FLAG_IS_ACTIVATED (1 << 21) // Only used for DirectSoundStream class, to acknowledge pause's no activate flag. +#define DSE_FLAG_IS_FLUSHING (1 << 22) // Only used for DirectSoundStream class, to acknowledge pause's no activate flag. #define DSE_FLAG_DEBUG_MUTE (1 << 30) // Cxbx-R debugging usage only #define DSE_FLAG_BUFFER_EXTERNAL (1 << 31) #define DSE_FLAG_AUDIO_CODECS (DSE_FLAG_PCM | DSE_FLAG_XADPCM | DSE_FLAG_PCM_UNKNOWN) diff --git a/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp b/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp index fcf13a303..c6cc99711 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSoundStream.cpp @@ -380,6 +380,18 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_Discontinuity) return DS_OK; } +xbox::hresult_xt CxbxrImpl_CDirectSoundStream_Flush +( + xbox::X_CDirectSoundStream* pThis) +{ + + DSoundBufferSynchPlaybackFlagRemove(pThis->EmuFlags); + + while (DSStream_Packet_Flush(pThis)); + + return DS_OK; +} + // ****************************************************************** // * patch: CDirectSoundStream_Flush // ****************************************************************** @@ -391,11 +403,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_Flush) LOG_FUNC_ONE_ARG(pThis); - DSoundBufferSynchPlaybackFlagRemove(pThis->EmuFlags); - - while (DSStream_Packet_Flush(pThis)); - - return DS_OK; + return CxbxrImpl_CDirectSoundStream_Flush(pThis); } // ****************************************************************** @@ -422,22 +430,20 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_FlushEx) // Cannot use rtTimeStamp here, it must be flush. if (dwFlags == X_DSSFLUSHEX_IMMEDIATE) { - hRet = xbox::EMUPATCH(CDirectSoundStream_Flush)(pThis); + hRet = CxbxrImpl_CDirectSoundStream_Flush(pThis); } // Remaining flags require X_DSSFLUSHEX_ASYNC to be include. - else if ((dwFlags & X_DSSFLUSHEX_ASYNC) > 0) { + else if ((dwFlags & X_DSSFLUSHEX_ASYNC) > 0 && !pThis->Host_BufferPacketArray.empty()) { // 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; - } xbox::LARGE_INTEGER getTime; xbox::KeQuerySystemTime(&getTime); pThis->Xb_rtFlushEx = getTime.QuadPart; + pThis->EmuFlags |= DSE_FLAG_IS_FLUSHING; + // HACK: Need to find a way to remove Flush call without break Obscure. + // Otherwise, it will behave like on hardware. + DSStream_Packet_Flush(pThis); } else { pThis->Xb_rtFlushEx = rtTimeStamp; @@ -549,15 +555,16 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_GetStatus__r2) // Convert host to xbox status flag. if (hRet == DS_OK) { - if (!pThis->Host_BufferPacketArray.empty() && (pThis->EmuFlags & (DSE_FLAG_PAUSE | DSE_FLAG_PAUSENOACTIVATE)) == 0) { - dwStatusXbox |= X_DSSSTATUS_PLAYING; - - } if (pThis->Host_BufferPacketArray.size() != pThis->X_MaxAttachedPackets) { dwStatusXbox |= X_DSSSTATUS_READY; } - if (!pThis->Host_BufferPacketArray.empty() && (pThis->EmuFlags & DSE_FLAG_PAUSE) != 0) { - dwStatusXbox |= X_DSSSTATUS_PAUSED; + if (!pThis->Host_BufferPacketArray.empty()) { + if ((pThis->EmuFlags & DSE_FLAG_PAUSE) != 0) { + dwStatusXbox |= X_DSSSTATUS_PAUSED; + } + else if ((pThis->EmuFlags & (DSE_FLAG_PAUSE | DSE_FLAG_PAUSENOACTIVATE | DSE_FLAG_IS_FLUSHING)) == 0) { + dwStatusXbox |= X_DSSSTATUS_PLAYING; + } } } else { dwStatusXbox = 0; @@ -735,6 +742,7 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSoundStream_Process) if ((pThis->Xb_Status & X_DSSSTATUS_STARVED) > 0) { pThis->Xb_Status &= ~X_DSSSTATUS_STARVED; } + pThis->EmuFlags &= ~DSE_FLAG_IS_FLUSHING; DSStream_Packet_Process(pThis); // Once full it needs to change status to flushed when cannot hold any more packets. } else {