Attempted fixup for Ghost Recon titles

I believe there is unauthorized write to xbox pass-down memory since it
show different result from time to time for some reason...

However... Rayman 3 and Rayman Arena titles now shows 2nd intro
properly! 👀 I personally believe this is the best commit for ANY
FMV (background musics are not verified).
This commit is contained in:
RadWolfie 2018-04-01 12:36:41 -05:00
parent 2de464fc1b
commit 393703f9d1
2 changed files with 80 additions and 72 deletions

View File

@ -971,7 +971,6 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateBuffer)
pDSBufferDesc->dwSize = sizeof(DSBUFFERDESC); pDSBufferDesc->dwSize = sizeof(DSBUFFERDESC);
pDSBufferDesc->dwFlags = (pdsbd->dwFlags & dwAcceptableMask) | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY; pDSBufferDesc->dwFlags = (pdsbd->dwFlags & dwAcceptableMask) | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY;
pDSBufferDesc->dwBufferBytes = pdsbd->dwBufferBytes;
pDSBufferDesc->lpwfxFormat = nullptr; pDSBufferDesc->lpwfxFormat = nullptr;
// TODO: Garbage Collection // TODO: Garbage Collection
@ -980,7 +979,7 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateBuffer)
DSoundBufferSetDefault((*ppBuffer), pDSBufferDesc, 0, 0); DSoundBufferSetDefault((*ppBuffer), pDSBufferDesc, 0, 0);
(*ppBuffer)->Host_lock = { 0 }; (*ppBuffer)->Host_lock = { 0 };
GeneratePCMFormat(pDSBufferDesc, pdsbd->lpwfxFormat, (*ppBuffer)->EmuFlags, &(*ppBuffer)->X_BufferCache, &(*ppBuffer)->X_BufferCacheSize); GeneratePCMFormat(pDSBufferDesc, pdsbd->lpwfxFormat, (*ppBuffer)->EmuFlags, pdsbd->dwBufferBytes, &(*ppBuffer)->X_BufferCache, (*ppBuffer)->X_BufferCacheSize);
DSoundBufferRegionSetDefault(*ppBuffer); DSoundBufferRegionSetDefault(*ppBuffer);
DbgPrintf("EmuDSound: DirectSoundCreateBuffer, *ppBuffer := 0x%.08X, bytes := 0x%.08X\n", *ppBuffer, pDSBufferDesc->dwBufferBytes); DbgPrintf("EmuDSound: DirectSoundCreateBuffer, *ppBuffer := 0x%.08X, bytes := 0x%.08X\n", *ppBuffer, pDSBufferDesc->dwBufferBytes);
@ -1038,9 +1037,6 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
LOG_FUNC_ARG(dwBufferBytes) LOG_FUNC_ARG(dwBufferBytes)
LOG_FUNC_END; LOG_FUNC_END;
//TODO: Current workaround method since dwBufferBytes do set to zero. Otherwise it will produce lock error message.
if (dwBufferBytes == 0) {
// Release old buffer if exists, this is needed in order to set lock pointer buffer to nullptr. // Release old buffer if exists, this is needed in order to set lock pointer buffer to nullptr.
if (pThis->Host_lock.pLockPtr1 != nullptr) { if (pThis->Host_lock.pLockPtr1 != nullptr) {
@ -1055,6 +1051,9 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
pThis->X_lock.dwLockBytes2); pThis->X_lock.dwLockBytes2);
} }
//TODO: Current workaround method since dwBufferBytes do set to zero. Otherwise it will produce lock error message.
if (dwBufferBytes == 0) {
leaveCriticalSection; leaveCriticalSection;
return DS_OK; return DS_OK;
} }
@ -1066,11 +1065,19 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
ResizeIDirectSoundBuffer(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc, ResizeIDirectSoundBuffer(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc,
pThis->EmuPlayFlags, dwBufferBytes, pThis->EmuDirectSound3DBuffer8, pThis->EmuFlags, pThis->X_BufferCache, pThis->X_BufferCacheSize); pThis->EmuPlayFlags, dwBufferBytes, pThis->EmuDirectSound3DBuffer8, pThis->EmuFlags, pThis->X_BufferCache, pThis->X_BufferCacheSize);
XTL::EMUPATCH(IDirectSoundBuffer_Lock)(pThis, 0, dwBufferBytes, &pThis->X_lock.pLockPtr1, DWORD pcmSize = DSoundBufferGetPCMBufferSize(pThis->EmuFlags, dwBufferBytes);
&pThis->X_lock.dwLockBytes1, nullptr, NULL, pThis->X_lock.dwLockFlags);
pThis->EmuDirectSoundBuffer8->Lock(0, pcmSize, &pThis->Host_lock.pLockPtr1, &pThis->Host_lock.dwLockBytes1, &pThis->Host_lock.pLockPtr2, &pThis->Host_lock.dwLockBytes2, DSBLOCK_ENTIREBUFFER);
memcpy_s(pThis->X_BufferCache, pThis->X_BufferCacheSize, pvBufferData, dwBufferBytes); memcpy_s(pThis->X_BufferCache, pThis->X_BufferCacheSize, pvBufferData, dwBufferBytes);
pThis->Host_lock.dwLockOffset = 0;
pThis->Host_lock.dwLockFlags = DSBLOCK_ENTIREBUFFER;
pThis->X_lock.dwLockOffset = 0;
pThis->X_lock.dwLockBytes1 = DSoundBufferGetXboxBufferSize(pThis->EmuFlags, pThis->Host_lock.dwLockBytes1);
pThis->X_lock.dwLockBytes2 = DSoundBufferGetXboxBufferSize(pThis->EmuFlags, pThis->Host_lock.dwLockBytes2);
DSoundGenericUnlock(pThis->EmuFlags, DSoundGenericUnlock(pThis->EmuFlags,
pThis->EmuDirectSoundBuffer8, pThis->EmuDirectSoundBuffer8,
pThis->EmuBufferDesc, pThis->EmuBufferDesc,
@ -1080,6 +1087,9 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
pThis->X_lock.dwLockBytes1, pThis->X_lock.dwLockBytes1,
pThis->X_lock.dwLockBytes2); pThis->X_lock.dwLockBytes2);
pThis->X_lock.pLockPtr1 = nullptr;
pThis->X_lock.pLockPtr2 = nullptr;
leaveCriticalSection; leaveCriticalSection;
return S_OK; return S_OK;
@ -1490,41 +1500,41 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Play)
// Process Play/Loop Region buffer (Region Buffer creation can be only place inside Play function // Process Play/Loop Region buffer (Region Buffer creation can be only place inside Play function
if (pThis->EmuDirectSoundBuffer8Region == nullptr && pThis->EmuBufferToggle != X_DSB_TOGGLE_DEFAULT) { if (pThis->EmuDirectSoundBuffer8Region == nullptr && pThis->EmuBufferToggle != X_DSB_TOGGLE_DEFAULT) {
DWORD byteLength; DWORD Xb_byteLength;
DWORD startOffset; DWORD Xb_startOffset;
LPDSBUFFERDESC emuBufferDescRegion = (LPDSBUFFERDESC)malloc(sizeof(DSBUFFERDESC)); LPDSBUFFERDESC emuBufferDescRegion = (LPDSBUFFERDESC)malloc(sizeof(DSBUFFERDESC));
memcpy_s(emuBufferDescRegion, sizeof(DSBUFFERDESC), pThis->EmuBufferDesc, sizeof(DSBUFFERDESC)); memcpy_s(emuBufferDescRegion, sizeof(DSBUFFERDESC), pThis->EmuBufferDesc, sizeof(DSBUFFERDESC));
switch (pThis->EmuBufferToggle) { switch (pThis->EmuBufferToggle) {
case X_DSB_TOGGLE_LOOP: case X_DSB_TOGGLE_LOOP:
startOffset = pThis->EmuRegionPlayStartOffset + pThis->EmuRegionLoopStartOffset; Xb_startOffset = pThis->EmuRegionPlayStartOffset + pThis->EmuRegionLoopStartOffset;
// Must check for zero length, then apply true length. // Must check for zero length, then apply true length.
if (pThis->EmuRegionLoopLength == 0) { if (pThis->EmuRegionLoopLength == 0) {
if (pThis->EmuRegionPlayLength != 0) { if (pThis->EmuRegionPlayLength != 0) {
byteLength = pThis->EmuRegionPlayLength; Xb_byteLength = pThis->EmuRegionPlayLength;
} else { } else {
byteLength = pThis->EmuBufferDesc->dwBufferBytes - startOffset; Xb_byteLength = pThis->X_BufferCacheSize - Xb_startOffset;
} }
} else { } else {
byteLength = pThis->EmuRegionLoopLength; Xb_byteLength = pThis->EmuRegionLoopLength;
} }
break; break;
case X_DSB_TOGGLE_PLAY: case X_DSB_TOGGLE_PLAY:
startOffset = pThis->EmuRegionPlayStartOffset; Xb_startOffset = pThis->EmuRegionPlayStartOffset;
// Must check for zero length, then apply true length. // Must check for zero length, then apply true length.
if (pThis->EmuRegionPlayLength != 0) { if (pThis->EmuRegionPlayLength != 0) {
byteLength = pThis->EmuRegionPlayLength; Xb_byteLength = pThis->EmuRegionPlayLength;
} else { } else {
byteLength = pThis->EmuBufferDesc->dwBufferBytes - startOffset; Xb_byteLength = pThis->X_BufferCacheSize - Xb_startOffset;
} }
break; break;
default: default:
free(emuBufferDescRegion); free(emuBufferDescRegion);
CxbxKrnlCleanup("Unknown TOGGLE region for DirectSoundBuffer class usage."); CxbxKrnlCleanup("Unknown TOGGLE region for DirectSoundBuffer class usage.");
} }
emuBufferDescRegion->dwBufferBytes = DSoundBufferGetPCMBufferSize(pThis->EmuFlags, byteLength); emuBufferDescRegion->dwBufferBytes = DSoundBufferGetPCMBufferSize(pThis->EmuFlags, Xb_byteLength);
DSoundBufferCreate(emuBufferDescRegion, pThis->EmuDirectSoundBuffer8Region); DSoundBufferCreate(emuBufferDescRegion, pThis->EmuDirectSoundBuffer8Region);
if (pThis->EmuDirectSound3DBuffer8 != nullptr) { if (pThis->EmuDirectSound3DBuffer8 != nullptr) {
@ -1539,7 +1549,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Play)
CxbxKrnlCleanup("Unable to lock region buffer!"); CxbxKrnlCleanup("Unable to lock region buffer!");
} }
if (pThis->Host_lock.pLockPtr1 != nullptr) { if (pThis->Host_lock.pLockPtr1 != nullptr) {
DSoundBufferOutputXBtoHost(pThis->EmuFlags, pThis->EmuBufferDesc, (PVOID)((PBYTE)pThis->X_BufferCache + startOffset), byteLength, pThis->Host_lock.pLockPtr1, pThis->Host_lock.dwLockBytes1); DSoundBufferOutputXBtoHost(pThis->EmuFlags, emuBufferDescRegion, (PVOID)((PBYTE)pThis->X_BufferCache + Xb_startOffset), Xb_byteLength, pThis->Host_lock.pLockPtr1, pThis->Host_lock.dwLockBytes1);
pThis->EmuDirectSoundBuffer8Region->Unlock(pThis->Host_lock.pLockPtr1, pThis->Host_lock.dwLockBytes1, nullptr, 0); pThis->EmuDirectSoundBuffer8Region->Unlock(pThis->Host_lock.pLockPtr1, pThis->Host_lock.dwLockBytes1, nullptr, 0);
pThis->Host_lock.pLockPtr1 = nullptr; pThis->Host_lock.pLockPtr1 = nullptr;
} }
@ -1635,7 +1645,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_StopEx)
hRet = pThis->EmuDirectSoundBuffer8Region->Stop(); hRet = pThis->EmuDirectSoundBuffer8Region->Stop();
pThis->EmuDirectSoundBuffer8Region->GetCurrentPosition(&dwValue, nullptr); pThis->EmuDirectSoundBuffer8Region->GetCurrentPosition(&dwValue, nullptr);
dwValue += pThis->EmuRegionLoopStartOffset + pThis->EmuRegionPlayStartOffset; dwValue += DSoundBufferGetPCMBufferSize(pThis->EmuFlags, pThis->EmuRegionLoopStartOffset + pThis->EmuRegionPlayStartOffset);
pThis->EmuDirectSoundBuffer8->SetCurrentPosition(dwValue); pThis->EmuDirectSoundBuffer8->SetCurrentPosition(dwValue);
if (dwStatus & DSBSTATUS_PLAYING) { if (dwStatus & DSBSTATUS_PLAYING) {
@ -1738,7 +1748,7 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
DSoundBufferSetDefault((*ppStream), pDSBufferDesc, 0, DSBPLAY_LOOPING); DSoundBufferSetDefault((*ppStream), pDSBufferDesc, 0, DSBPLAY_LOOPING);
GeneratePCMFormat(pDSBufferDesc, pdssd->lpwfxFormat, (*ppStream)->EmuFlags, xbnullptr, xbnullptr); GeneratePCMFormat(pDSBufferDesc, pdssd->lpwfxFormat, (*ppStream)->EmuFlags, 0, xbnullptr, (*ppStream)->X_BufferCacheSize);
// Allocate at least 5 second worth of bytes in PCM format. // Allocate at least 5 second worth of bytes in PCM format.
pDSBufferDesc->dwBufferBytes = pDSBufferDesc->lpwfxFormat->nAvgBytesPerSec * 5; pDSBufferDesc->dwBufferBytes = pDSBufferDesc->lpwfxFormat->nAvgBytesPerSec * 5;

View File

@ -50,8 +50,8 @@ CRITICAL_SECTION g_DSoundCriticalSection;
#define enterCriticalSection EnterCriticalSection(&g_DSoundCriticalSection) #define enterCriticalSection EnterCriticalSection(&g_DSoundCriticalSection)
#define leaveCriticalSection LeaveCriticalSection(&g_DSoundCriticalSection) #define leaveCriticalSection LeaveCriticalSection(&g_DSoundCriticalSection)
#define DSoundBufferGetPCMBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? TXboxAdpcmDecoder_guess_output_size(size) : size #define DSoundBufferGetPCMBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? DWORD((size / float(XBOX_ADPCM_SRCSIZE)) * XBOX_ADPCM_DSTSIZE) : size
#define DSoundBufferGetXboxBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? ((size / XBOX_ADPCM_DSTSIZE) * XBOX_ADPCM_SRCSIZE) : size #define DSoundBufferGetXboxBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? DWORD((size / float(XBOX_ADPCM_DSTSIZE)) * XBOX_ADPCM_SRCSIZE) : size
void DSoundBufferOutputXBtoHost(DWORD emuFlags, DSBUFFERDESC* pDSBufferDesc, LPVOID pXBaudioPtr, DWORD dwXBAudioBytes, LPVOID pPCaudioPtr, DWORD dwPCMAudioBytes) { void DSoundBufferOutputXBtoHost(DWORD emuFlags, DSBUFFERDESC* pDSBufferDesc, LPVOID pXBaudioPtr, DWORD dwXBAudioBytes, LPVOID pPCaudioPtr, DWORD dwPCMAudioBytes) {
if ((emuFlags & DSB_FLAG_XADPCM) > 0) { if ((emuFlags & DSB_FLAG_XADPCM) > 0) {
@ -131,16 +131,38 @@ inline void XADPCM2PCMFormat(LPWAVEFORMATEX lpwfxFormat)
#endif #endif
} }
inline void GenerateXboxBufferCache(
DSBUFFERDESC* pDSBufferDesc,
DWORD &dwEmuFlags,
DWORD X_BufferSizeRequest,
LPVOID* X_BufferCache,
DWORD &X_BufferCacheSize) {
// Generate xbox buffer cache size
// If the size is the same, don't realloc
if (X_BufferCacheSize != X_BufferSizeRequest) {
// Check if buffer cache exist, then copy over old ones.
if (*X_BufferCache != xbnullptr) {
LPVOID tempBuffer = *X_BufferCache;
*X_BufferCache = malloc(X_BufferSizeRequest);
memcpy_s(*X_BufferCache, X_BufferSizeRequest, tempBuffer, X_BufferCacheSize);
} else {
*X_BufferCache = malloc(X_BufferSizeRequest);
}
X_BufferCacheSize = X_BufferSizeRequest;
}
}
inline void GeneratePCMFormat( inline void GeneratePCMFormat(
DSBUFFERDESC* pDSBufferDesc, DSBUFFERDESC* pDSBufferDesc,
LPCWAVEFORMATEX lpwfxFormat, LPCWAVEFORMATEX lpwfxFormat,
DWORD &dwEmuFlags, DWORD &dwEmuFlags,
DWORD X_BufferSizeRequest,
LPVOID* X_BufferCache, LPVOID* X_BufferCache,
LPDWORD X_BufferCacheSize) DWORD &X_BufferCacheSize)
{ {
bool bIsSpecial = false; bool bIsSpecial = false;
DWORD checkAvgBps; DWORD checkAvgBps;
DWORD X_BufferSizeRequest = pDSBufferDesc->dwBufferBytes;
// convert from Xbox to PC DSound // convert from Xbox to PC DSound
{ {
@ -184,14 +206,6 @@ inline void GeneratePCMFormat(
dwEmuFlags |= DSB_FLAG_PCM_UNKNOWN; dwEmuFlags |= DSB_FLAG_PCM_UNKNOWN;
break; break;
} }
if (pDSBufferDesc->dwBufferBytes < DSBSIZE_MIN) {
pDSBufferDesc->dwBufferBytes = DSBSIZE_MIN;
} else if (pDSBufferDesc->dwBufferBytes > DSBSIZE_MAX) {
pDSBufferDesc->dwBufferBytes = DSBSIZE_MAX;
} else {
pDSBufferDesc->dwBufferBytes = DSoundBufferGetPCMBufferSize(dwEmuFlags, pDSBufferDesc->dwBufferBytes);
}
} else { } else {
bIsSpecial = true; bIsSpecial = true;
dwEmuFlags |= DSB_FLAG_RECIEVEDATA; dwEmuFlags |= DSB_FLAG_RECIEVEDATA;
@ -258,24 +272,16 @@ inline void GeneratePCMFormat(
} }
} }
if (X_BufferCache == xbnullptr) { if (X_BufferSizeRequest < DSBSIZE_MIN) {
return; X_BufferSizeRequest = DSBSIZE_MIN;
} else if (X_BufferSizeRequest > DSBSIZE_MAX) {
X_BufferSizeRequest = DSBSIZE_MAX;
}
if (X_BufferCache != nullptr) {
GenerateXboxBufferCache(pDSBufferDesc, dwEmuFlags, X_BufferSizeRequest, X_BufferCache, X_BufferCacheSize);
} }
// Generate xbox buffer cache size pDSBufferDesc->dwBufferBytes = DSoundBufferGetPCMBufferSize(dwEmuFlags, X_BufferCacheSize);
// If the size is the same, don't realloc
if (*X_BufferCacheSize == X_BufferSizeRequest) {
return;
}
// Check if buffer cache exist, then copy over old ones.
if (*X_BufferCache != xbnullptr) {
LPVOID tempBuffer = *X_BufferCache;
*X_BufferCache = malloc(X_BufferSizeRequest);
memcpy_s(*X_BufferCache, X_BufferSizeRequest, tempBuffer, *X_BufferCacheSize);
} else {
*X_BufferCache = malloc(X_BufferSizeRequest);
}
*X_BufferCacheSize = X_BufferSizeRequest;
} }
inline void DSoundGenericUnlock( inline void DSoundGenericUnlock(
@ -503,21 +509,13 @@ inline void ResizeIDirectSoundBuffer(
LPVOID &X_BufferCache, LPVOID &X_BufferCache,
DWORD &X_BufferCacheSize) DWORD &X_BufferCacheSize)
{ {
DWORD pcmSize = DSoundBufferGetPCMBufferSize(EmuFlags, Xbox_dwBytes); if (Xbox_dwBytes == 0 || X_BufferCacheSize == Xbox_dwBytes) {
if (Xbox_dwBytes == 0 || pcmSize == pDSBufferDesc->dwBufferBytes) {
return; return;
} }
DbgPrintf("EmuResizeIDirectSoundBuffer8 : Resizing! (0x%.08X->0x%.08X)\n", pDSBufferDesc->dwBufferBytes, pcmSize);
pDSBufferDesc->dwBufferBytes = pcmSize; GenerateXboxBufferCache(pDSBufferDesc, EmuFlags, Xbox_dwBytes, &X_BufferCache, X_BufferCacheSize);
LPVOID X_tempBuffer = X_BufferCache; pDSBufferDesc->dwBufferBytes = DSoundBufferGetPCMBufferSize(EmuFlags, X_BufferCacheSize);
X_BufferCache = malloc(Xbox_dwBytes);
if (X_tempBuffer != xbnullptr) {
memcpy_s(X_BufferCache, Xbox_dwBytes, X_tempBuffer, X_BufferCacheSize);
free(X_tempBuffer);
}
X_BufferCacheSize = Xbox_dwBytes;
DSoundBufferReplace(pDSBuffer, pDSBufferDesc, PlayFlags, pDS3DBuffer); DSoundBufferReplace(pDSBuffer, pDSBufferDesc, PlayFlags, pDS3DBuffer);
} }
@ -1023,10 +1021,10 @@ inline HRESULT HybridDirectSoundBuffer_SetFormat(
enterCriticalSection; enterCriticalSection;
if (X_BufferAllocate) { if (X_BufferAllocate) {
GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, &X_BufferCache, &X_BufferCacheSize); GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, X_BufferCacheSize, xbnullptr, X_BufferCacheSize);
// Don't allocate for DS Stream class, it is using straight from the source. // Don't allocate for DS Stream class, it is using straight from the source.
} else { } else {
GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, xbnullptr, xbnullptr); GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, 0, xbnullptr, X_BufferCacheSize);
} }
HRESULT hRet = DS_OK; HRESULT hRet = DS_OK;
if (g_pDSoundPrimaryBuffer == pDSBuffer) { if (g_pDSoundPrimaryBuffer == pDSBuffer) {