fix Discontinuity and GetStatus
This commit is contained in:
parent
4a27006ce6
commit
0bf0e32df0
|
@ -152,12 +152,37 @@ static inline void DSStream_Packet_UploadPartial(
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
static inline void DSStream_Packet_Starved(
|
static inline void DSStream_Packet_Stop_Internal(
|
||||||
XTL::X_CDirectSoundStream* pThis
|
XTL::X_CDirectSoundStream* pThis
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
pThis->Host_isProcessing = false;
|
pThis->Host_isProcessing = false;
|
||||||
pThis->EmuDirectSoundBuffer8->Stop();
|
pThis->EmuDirectSoundBuffer8->Stop();
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void DSStream_Packet_Stop(
|
||||||
|
XTL::X_CDirectSoundStream* pThis
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DSStream_Packet_Stop_Internal(pThis);
|
||||||
|
|
||||||
|
if (pThis->Host_BufferPacketArray.size() == 0) {
|
||||||
|
if ((pThis->EmuFlags & DSE_FLAG_ENVELOPE2) > 0) {
|
||||||
|
pThis->Xb_Status |= X_DSSSTATUS_ENVELOPECOMPLETE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
// We need to log this info since some titles may have stop/played audio often in middle of processing (relative to videos).
|
||||||
|
EmuLog(LOG_LEVEL::INFO, "Stopped: pThis = %08X; Remaining packet(s): %d",
|
||||||
|
pThis, pThis->Host_BufferPacketArray.size()
|
||||||
|
);
|
||||||
|
}
|
||||||
|
|
||||||
|
static inline void DSStream_Packet_Starved(
|
||||||
|
XTL::X_CDirectSoundStream* pThis
|
||||||
|
)
|
||||||
|
{
|
||||||
|
DSStream_Packet_Stop_Internal(pThis);
|
||||||
|
pThis->Xb_Status |= X_DSSSTATUS_STARVED | X_DSSSTATUS_PAUSED;
|
||||||
// We need to log this info since some titles may have stop/played audio often in middle of processing (relative to videos).
|
// We need to log this info since some titles may have stop/played audio often in middle of processing (relative to videos).
|
||||||
EmuLog(LOG_LEVEL::INFO, "Starved: pThis = %08X;",
|
EmuLog(LOG_LEVEL::INFO, "Starved: pThis = %08X;",
|
||||||
pThis
|
pThis
|
||||||
|
@ -191,6 +216,11 @@ bool DSStream_Packet_Process(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
|
|
||||||
|
// Do not allow to process if there is no packets.
|
||||||
|
if (pThis->Host_BufferPacketArray.size() == 0) {
|
||||||
|
return 0;
|
||||||
|
}
|
||||||
|
|
||||||
// If title want to pause, then don't process the packets.
|
// If title want to pause, then don't process the packets.
|
||||||
// If media object is being used as playback synch, then don't process the packets.
|
// If media object is being used as playback synch, then don't process the packets.
|
||||||
if ((pThis->EmuFlags & DSE_FLAG_PAUSE) > 0 ||
|
if ((pThis->EmuFlags & DSE_FLAG_PAUSE) > 0 ||
|
||||||
|
@ -201,9 +231,14 @@ bool DSStream_Packet_Process(
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Do not allow to process if there is no packets.
|
if ((pThis->Xb_Status & X_DSSSTATUS_PAUSED) > 0) {
|
||||||
if (pThis->Host_BufferPacketArray.size() == 0) {
|
pThis->Xb_Status &= ~X_DSSSTATUS_PAUSED;
|
||||||
return 0;
|
}
|
||||||
|
|
||||||
|
if (pThis->Host_isProcessing == false) {
|
||||||
|
if (!(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED)) {
|
||||||
|
pThis->EmuFlags |= DSE_FLAG_IS_ACTIVATED;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
DWORD dwAudioBytes;
|
DWORD dwAudioBytes;
|
||||||
|
@ -253,10 +288,16 @@ bool DSStream_Packet_Process(
|
||||||
// Once bufPlayed is equal to dwMaxSize, we know the packet is completed.
|
// Once bufPlayed is equal to dwMaxSize, we know the packet is completed.
|
||||||
if (packetCurrent->bufPlayed == packetCurrent->xmp_data.dwMaxSize) {
|
if (packetCurrent->bufPlayed == packetCurrent->xmp_data.dwMaxSize) {
|
||||||
|
|
||||||
|
bool isStreamEnd = packetCurrent->isStreamEnd;
|
||||||
DSStream_Packet_Clear(packetCurrent, XMP_STATUS_SUCCESS, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis);
|
DSStream_Packet_Clear(packetCurrent, XMP_STATUS_SUCCESS, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis);
|
||||||
|
|
||||||
if (pThis->Host_BufferPacketArray.size() == 0) {
|
if (pThis->Host_BufferPacketArray.size() == 0) {
|
||||||
DSStream_Packet_Starved(pThis);
|
if (isStreamEnd) {
|
||||||
|
DSStream_Packet_Stop(pThis);
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
DSStream_Packet_Starved(pThis);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
#if 0 // Extend debug verification
|
#if 0 // Extend debug verification
|
||||||
|
@ -304,8 +345,9 @@ void DSStream_Packet_FlushEx_Reset(
|
||||||
)
|
)
|
||||||
{
|
{
|
||||||
// Remove flags only (This is the only place it will remove other than FlushEx perform set/remove the flags.)
|
// 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);
|
pThis->EmuFlags &= ~(DSE_FLAG_FLUSH_ASYNC | DSE_FLAG_ENVELOPE | DSE_FLAG_ENVELOPE2 | DSE_FLAG_PAUSE);
|
||||||
pThis->Xb_rtFlushEx = 0LL;
|
pThis->Xb_rtFlushEx = 0LL;
|
||||||
|
pThis->Xb_Status = 0;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool DSStream_Packet_Flush(
|
bool DSStream_Packet_Flush(
|
||||||
|
|
|
@ -122,6 +122,7 @@ struct X_CDirectSoundBuffer
|
||||||
#define DSE_FLAG_ENVELOPE (1 << 13)
|
#define DSE_FLAG_ENVELOPE (1 << 13)
|
||||||
#define DSE_FLAG_ENVELOPE2 (1 << 14) // NOTE: This flag is a requirement for GetStatus to return X_DSSSTATUS_ENVELOPECOMPLETE value.
|
#define DSE_FLAG_ENVELOPE2 (1 << 14) // NOTE: This flag is a requirement for GetStatus to return X_DSSSTATUS_ENVELOPECOMPLETE value.
|
||||||
#define DSE_FLAG_RECIEVEDATA (1 << 20)
|
#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_DEBUG_MUTE (1 << 30) // Cxbx-R debugging usage only
|
#define DSE_FLAG_DEBUG_MUTE (1 << 30) // Cxbx-R debugging usage only
|
||||||
#define DSE_FLAG_BUFFER_EXTERNAL (1 << 31)
|
#define DSE_FLAG_BUFFER_EXTERNAL (1 << 31)
|
||||||
#define DSE_FLAG_AUDIO_CODECS (DSE_FLAG_PCM | DSE_FLAG_XADPCM | DSE_FLAG_PCM_UNKNOWN)
|
#define DSE_FLAG_AUDIO_CODECS (DSE_FLAG_PCM | DSE_FLAG_XADPCM | DSE_FLAG_PCM_UNKNOWN)
|
||||||
|
@ -174,6 +175,7 @@ struct host_voice_packet {
|
||||||
DWORD bufPlayed;
|
DWORD bufPlayed;
|
||||||
DWORD bufWrittenBytes;
|
DWORD bufWrittenBytes;
|
||||||
bool isPlayed;
|
bool isPlayed;
|
||||||
|
bool isStreamEnd;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
@ -266,6 +268,7 @@ class X_CDirectSoundStream
|
||||||
DWORD Xb_Frequency;
|
DWORD Xb_Frequency;
|
||||||
DWORD Host_dwLastWritePos;
|
DWORD Host_dwLastWritePos;
|
||||||
DWORD Xb_Flags;
|
DWORD Xb_Flags;
|
||||||
|
DWORD Xb_Status;
|
||||||
};
|
};
|
||||||
|
|
||||||
// ******************************************************************
|
// ******************************************************************
|
||||||
|
|
|
@ -81,7 +81,7 @@ void DirectSoundDoWork_Buffer(xboxkrnl::LARGE_INTEGER &time)
|
||||||
// TODO: Do we need this in async thread loop?
|
// TODO: Do we need this in async thread loop?
|
||||||
if (pThis->Xb_rtPauseEx != 0LL && pThis->Xb_rtPauseEx <= time.QuadPart) {
|
if (pThis->Xb_rtPauseEx != 0LL && pThis->Xb_rtPauseEx <= time.QuadPart) {
|
||||||
pThis->Xb_rtPauseEx = 0LL;
|
pThis->Xb_rtPauseEx = 0LL;
|
||||||
pThis->EmuFlags ^= DSE_FLAG_PAUSE;
|
pThis->EmuFlags &= ~DSE_FLAG_PAUSE;
|
||||||
pThis->EmuDirectSoundBuffer8->Play(0, 0, pThis->EmuPlayFlags);
|
pThis->EmuDirectSoundBuffer8->Play(0, 0, pThis->EmuPlayFlags);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -102,7 +102,7 @@ void DirectSoundDoWork_Stream(xboxkrnl::LARGE_INTEGER& time)
|
||||||
// TODO: Do we need this in async thread loop?
|
// TODO: Do we need this in async thread loop?
|
||||||
if (pThis->Xb_rtPauseEx != 0LL && pThis->Xb_rtPauseEx <= time.QuadPart) {
|
if (pThis->Xb_rtPauseEx != 0LL && pThis->Xb_rtPauseEx <= time.QuadPart) {
|
||||||
pThis->Xb_rtPauseEx = 0LL;
|
pThis->Xb_rtPauseEx = 0LL;
|
||||||
pThis->EmuFlags ^= DSE_FLAG_PAUSE;
|
pThis->EmuFlags &= ~DSE_FLAG_PAUSE;
|
||||||
// Don't call play here, let DSStream_Packet_Process deal with it.
|
// Don't call play here, let DSStream_Packet_Process deal with it.
|
||||||
}
|
}
|
||||||
if ((pThis->EmuFlags & DSE_FLAG_FLUSH_ASYNC) == 0) {
|
if ((pThis->EmuFlags & DSE_FLAG_FLUSH_ASYNC) == 0) {
|
||||||
|
@ -251,6 +251,7 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
|
||||||
(*ppStream)->Host_isProcessing = false;
|
(*ppStream)->Host_isProcessing = false;
|
||||||
(*ppStream)->Xb_lpfnCallback = pdssd->lpfnCallback;
|
(*ppStream)->Xb_lpfnCallback = pdssd->lpfnCallback;
|
||||||
(*ppStream)->Xb_lpvContext = pdssd->lpvContext;
|
(*ppStream)->Xb_lpvContext = pdssd->lpvContext;
|
||||||
|
(*ppStream)->Xb_Status = 0;
|
||||||
//TODO: Implement mixbin variable support. Or just merge pdssd struct into DS Stream class.
|
//TODO: Implement mixbin variable support. Or just merge pdssd struct into DS Stream class.
|
||||||
|
|
||||||
EmuLog(LOG_LEVEL::DEBUG, "DirectSoundCreateStream, *ppStream := 0x%.08X", *ppStream);
|
EmuLog(LOG_LEVEL::DEBUG, "DirectSoundCreateStream, *ppStream := 0x%.08X", *ppStream);
|
||||||
|
@ -337,11 +338,9 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Discontinuity)
|
||||||
|
|
||||||
// default ret = DSERR_GENERIC
|
// default ret = DSERR_GENERIC
|
||||||
|
|
||||||
// Perform check if has pending data. if so, clear pending packets.
|
// Perform check if packets exist, then mark the last submited packet as end of stream.
|
||||||
if (pThis->Host_BufferPacketArray.size() > 1) {
|
if (!pThis->Host_BufferPacketArray.empty()) {
|
||||||
for (auto buffer = pThis->Host_BufferPacketArray.begin() + 1; buffer != pThis->Host_BufferPacketArray.end();) {
|
pThis->Host_BufferPacketArray.back().isStreamEnd = true;
|
||||||
DSStream_Packet_Clear(buffer, XMP_STATUS_FLUSHED, pThis->Xb_lpfnCallback, pThis->Xb_lpvContext, pThis);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
return DS_OK;
|
return DS_OK;
|
||||||
|
@ -462,32 +461,15 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_GetStatus)
|
||||||
LOG_FUNC_ARG_OUT(pdwStatus)
|
LOG_FUNC_ARG_OUT(pdwStatus)
|
||||||
LOG_FUNC_END;
|
LOG_FUNC_END;
|
||||||
|
|
||||||
DWORD dwStatusXbox = 0, dwStatusHost;
|
DWORD dwStatusXbox = pThis->Xb_Status, dwStatusHost;
|
||||||
HRESULT hRet = pThis->EmuDirectSoundBuffer8->GetStatus(&dwStatusHost);
|
HRESULT hRet = pThis->EmuDirectSoundBuffer8->GetStatus(&dwStatusHost);
|
||||||
|
|
||||||
// Convert host to xbox status flag.
|
// Convert host to xbox status flag.
|
||||||
if (hRet == DS_OK) {
|
if (hRet == DS_OK) {
|
||||||
DWORD testSize = pThis->Host_BufferPacketArray.size();
|
DWORD testSize = pThis->Host_BufferPacketArray.size();
|
||||||
if ((dwStatusHost & DSBSTATUS_PLAYING) > 0) {
|
if ((dwStatusHost & DSBSTATUS_PLAYING) > 0 && !(dwStatusXbox & X_DSSSTATUS_PAUSED)) {
|
||||||
dwStatusXbox |= X_DSSSTATUS_PLAYING;
|
dwStatusXbox |= X_DSSSTATUS_PLAYING;
|
||||||
|
|
||||||
} else {
|
|
||||||
|
|
||||||
if ((pThis->EmuFlags & DSE_FLAG_PAUSE) > 0) {
|
|
||||||
dwStatusXbox |= X_DSSSTATUS_PAUSED;
|
|
||||||
|
|
||||||
// Set to paused when has packet(s) queued and is not processing.
|
|
||||||
} else if (pThis->Host_BufferPacketArray.size() != 0 && pThis->Host_isProcessing == false) {
|
|
||||||
dwStatusXbox |= X_DSSSTATUS_PAUSED;
|
|
||||||
}
|
|
||||||
|
|
||||||
if (pThis->Host_BufferPacketArray.size() == 0) {
|
|
||||||
dwStatusXbox |= X_DSSSTATUS_STARVED;
|
|
||||||
|
|
||||||
if ((pThis->EmuFlags & DSE_FLAG_ENVELOPE2) > 0) {
|
|
||||||
dwStatusXbox |= X_DSSSTATUS_ENVELOPECOMPLETE;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
if (pThis->Host_BufferPacketArray.size() != pThis->X_MaxAttachedPackets) {
|
if (pThis->Host_BufferPacketArray.size() != pThis->X_MaxAttachedPackets) {
|
||||||
dwStatusXbox |= X_DSSSTATUS_READY;
|
dwStatusXbox |= X_DSSSTATUS_READY;
|
||||||
|
@ -552,6 +534,21 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Pause)
|
||||||
HRESULT hRet = HybridDirectSoundBuffer_Pause(pThis->EmuDirectSoundBuffer8, dwPause, pThis->EmuFlags, pThis->EmuPlayFlags,
|
HRESULT hRet = HybridDirectSoundBuffer_Pause(pThis->EmuDirectSoundBuffer8, dwPause, pThis->EmuFlags, pThis->EmuPlayFlags,
|
||||||
pThis->Host_isProcessing, 0LL, pThis->Xb_rtPauseEx);
|
pThis->Host_isProcessing, 0LL, pThis->Xb_rtPauseEx);
|
||||||
|
|
||||||
|
if (dwPause == X_DSSPAUSE_PAUSENOACTIVATE) {
|
||||||
|
if (pThis->Host_BufferPacketArray.size() == 0 && !(pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED)) {
|
||||||
|
pThis->EmuFlags |= DSE_FLAG_PAUSE;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if ((pThis->EmuFlags & DSE_FLAG_PAUSE) > 0) {
|
||||||
|
pThis->Host_isProcessing = false;
|
||||||
|
if ((pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED) > 0) {
|
||||||
|
if (pThis->Host_BufferPacketArray.size() != 0) {
|
||||||
|
pThis->Xb_Status |= X_DSSSTATUS_PAUSED;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return hRet;
|
return hRet;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -626,6 +623,7 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Process)
|
||||||
packet_input.bufWrittenBytes = 0;
|
packet_input.bufWrittenBytes = 0;
|
||||||
packet_input.bufPlayed = 0;
|
packet_input.bufPlayed = 0;
|
||||||
packet_input.isPlayed = false;
|
packet_input.isPlayed = false;
|
||||||
|
packet_input.isStreamEnd = false;
|
||||||
|
|
||||||
DSoundBufferOutputXBtoHost(pThis->EmuFlags, pThis->EmuBufferDesc, pInputBuffer->pvBuffer, pInputBuffer->dwMaxSize, packet_input.pBuffer_data, packet_input.xmp_data.dwMaxSize);
|
DSoundBufferOutputXBtoHost(pThis->EmuFlags, pThis->EmuBufferDesc, pInputBuffer->pvBuffer, pInputBuffer->dwMaxSize, packet_input.pBuffer_data, packet_input.xmp_data.dwMaxSize);
|
||||||
|
|
||||||
|
@ -640,10 +638,17 @@ HRESULT WINAPI XTL::EMUPATCH(CDirectSoundStream_Process)
|
||||||
if (pThis->Host_isProcessing == false && pThis->Host_BufferPacketArray.size() == 1) {
|
if (pThis->Host_isProcessing == false && pThis->Host_BufferPacketArray.size() == 1) {
|
||||||
pThis->EmuDirectSoundBuffer8->SetCurrentPosition(packet_input.nextWriteOffset);
|
pThis->EmuDirectSoundBuffer8->SetCurrentPosition(packet_input.nextWriteOffset);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if ((pThis->Xb_Status & X_DSSSTATUS_STARVED) > 0) {
|
||||||
|
pThis->Xb_Status &= ~X_DSSSTATUS_STARVED;
|
||||||
|
}
|
||||||
|
if ((pThis->EmuFlags & DSE_FLAG_IS_ACTIVATED) > 0 && (pThis->EmuFlags & DSE_FLAG_PAUSE) > 0) {
|
||||||
|
pThis->Xb_Status |= X_DSSSTATUS_PAUSED;
|
||||||
|
}
|
||||||
// Once full it needs to change status to flushed when cannot hold any more packets.
|
// Once full it needs to change status to flushed when cannot hold any more packets.
|
||||||
} else {
|
} else {
|
||||||
if (pInputBuffer->pdwStatus != xbnullptr) {
|
if (pInputBuffer->pdwStatus != xbnullptr) {
|
||||||
(*pInputBuffer->pdwStatus) = XMP_STATUS_FLUSHED;
|
(*pInputBuffer->pdwStatus) = XMP_STATUS_FAILURE;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
Loading…
Reference in New Issue