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->dwFlags = (pdsbd->dwFlags & dwAcceptableMask) | DSBCAPS_CTRLVOLUME | DSBCAPS_GETCURRENTPOSITION2 | DSBCAPS_CTRLFREQUENCY;
pDSBufferDesc->dwBufferBytes = pdsbd->dwBufferBytes;
pDSBufferDesc->lpwfxFormat = nullptr;
// TODO: Garbage Collection
@ -980,7 +979,7 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateBuffer)
DSoundBufferSetDefault((*ppBuffer), pDSBufferDesc, 0, 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);
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_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.
if (pThis->Host_lock.pLockPtr1 != nullptr) {
@ -1055,6 +1051,9 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
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;
return DS_OK;
}
@ -1066,11 +1065,19 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
ResizeIDirectSoundBuffer(pThis->EmuDirectSoundBuffer8, pThis->EmuBufferDesc,
pThis->EmuPlayFlags, dwBufferBytes, pThis->EmuDirectSound3DBuffer8, pThis->EmuFlags, pThis->X_BufferCache, pThis->X_BufferCacheSize);
XTL::EMUPATCH(IDirectSoundBuffer_Lock)(pThis, 0, dwBufferBytes, &pThis->X_lock.pLockPtr1,
&pThis->X_lock.dwLockBytes1, nullptr, NULL, pThis->X_lock.dwLockFlags);
DWORD pcmSize = DSoundBufferGetPCMBufferSize(pThis->EmuFlags, dwBufferBytes);
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);
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,
pThis->EmuDirectSoundBuffer8,
pThis->EmuBufferDesc,
@ -1080,6 +1087,9 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_SetBufferData)
pThis->X_lock.dwLockBytes1,
pThis->X_lock.dwLockBytes2);
pThis->X_lock.pLockPtr1 = nullptr;
pThis->X_lock.pLockPtr2 = nullptr;
leaveCriticalSection;
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
if (pThis->EmuDirectSoundBuffer8Region == nullptr && pThis->EmuBufferToggle != X_DSB_TOGGLE_DEFAULT) {
DWORD byteLength;
DWORD startOffset;
DWORD Xb_byteLength;
DWORD Xb_startOffset;
LPDSBUFFERDESC emuBufferDescRegion = (LPDSBUFFERDESC)malloc(sizeof(DSBUFFERDESC));
memcpy_s(emuBufferDescRegion, sizeof(DSBUFFERDESC), pThis->EmuBufferDesc, sizeof(DSBUFFERDESC));
switch (pThis->EmuBufferToggle) {
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.
if (pThis->EmuRegionLoopLength == 0) {
if (pThis->EmuRegionPlayLength != 0) {
byteLength = pThis->EmuRegionPlayLength;
Xb_byteLength = pThis->EmuRegionPlayLength;
} else {
byteLength = pThis->EmuBufferDesc->dwBufferBytes - startOffset;
Xb_byteLength = pThis->X_BufferCacheSize - Xb_startOffset;
}
} else {
byteLength = pThis->EmuRegionLoopLength;
Xb_byteLength = pThis->EmuRegionLoopLength;
}
break;
case X_DSB_TOGGLE_PLAY:
startOffset = pThis->EmuRegionPlayStartOffset;
Xb_startOffset = pThis->EmuRegionPlayStartOffset;
// Must check for zero length, then apply true length.
if (pThis->EmuRegionPlayLength != 0) {
byteLength = pThis->EmuRegionPlayLength;
Xb_byteLength = pThis->EmuRegionPlayLength;
} else {
byteLength = pThis->EmuBufferDesc->dwBufferBytes - startOffset;
Xb_byteLength = pThis->X_BufferCacheSize - Xb_startOffset;
}
break;
default:
free(emuBufferDescRegion);
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);
if (pThis->EmuDirectSound3DBuffer8 != nullptr) {
@ -1539,7 +1549,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_Play)
CxbxKrnlCleanup("Unable to lock region buffer!");
}
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->Host_lock.pLockPtr1 = nullptr;
}
@ -1635,7 +1645,7 @@ HRESULT WINAPI XTL::EMUPATCH(IDirectSoundBuffer_StopEx)
hRet = pThis->EmuDirectSoundBuffer8Region->Stop();
pThis->EmuDirectSoundBuffer8Region->GetCurrentPosition(&dwValue, nullptr);
dwValue += pThis->EmuRegionLoopStartOffset + pThis->EmuRegionPlayStartOffset;
dwValue += DSoundBufferGetPCMBufferSize(pThis->EmuFlags, pThis->EmuRegionLoopStartOffset + pThis->EmuRegionPlayStartOffset);
pThis->EmuDirectSoundBuffer8->SetCurrentPosition(dwValue);
if (dwStatus & DSBSTATUS_PLAYING) {
@ -1738,7 +1748,7 @@ HRESULT WINAPI XTL::EMUPATCH(DirectSoundCreateStream)
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.
pDSBufferDesc->dwBufferBytes = pDSBufferDesc->lpwfxFormat->nAvgBytesPerSec * 5;

View File

@ -50,8 +50,8 @@ CRITICAL_SECTION g_DSoundCriticalSection;
#define enterCriticalSection EnterCriticalSection(&g_DSoundCriticalSection)
#define leaveCriticalSection LeaveCriticalSection(&g_DSoundCriticalSection)
#define DSoundBufferGetPCMBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? TXboxAdpcmDecoder_guess_output_size(size) : size
#define DSoundBufferGetXboxBufferSize(EmuFlags, size) (EmuFlags & DSB_FLAG_XADPCM) > 0 ? ((size / XBOX_ADPCM_DSTSIZE) * XBOX_ADPCM_SRCSIZE) : 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 ? DWORD((size / float(XBOX_ADPCM_DSTSIZE)) * XBOX_ADPCM_SRCSIZE) : size
void DSoundBufferOutputXBtoHost(DWORD emuFlags, DSBUFFERDESC* pDSBufferDesc, LPVOID pXBaudioPtr, DWORD dwXBAudioBytes, LPVOID pPCaudioPtr, DWORD dwPCMAudioBytes) {
if ((emuFlags & DSB_FLAG_XADPCM) > 0) {
@ -131,16 +131,38 @@ inline void XADPCM2PCMFormat(LPWAVEFORMATEX lpwfxFormat)
#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(
DSBUFFERDESC* pDSBufferDesc,
LPCWAVEFORMATEX lpwfxFormat,
DWORD &dwEmuFlags,
DWORD X_BufferSizeRequest,
LPVOID* X_BufferCache,
LPDWORD X_BufferCacheSize)
DWORD &X_BufferCacheSize)
{
bool bIsSpecial = false;
DWORD checkAvgBps;
DWORD X_BufferSizeRequest = pDSBufferDesc->dwBufferBytes;
// convert from Xbox to PC DSound
{
@ -184,14 +206,6 @@ inline void GeneratePCMFormat(
dwEmuFlags |= DSB_FLAG_PCM_UNKNOWN;
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 {
bIsSpecial = true;
dwEmuFlags |= DSB_FLAG_RECIEVEDATA;
@ -258,24 +272,16 @@ inline void GeneratePCMFormat(
}
}
if (X_BufferCache == xbnullptr) {
return;
if (X_BufferSizeRequest < DSBSIZE_MIN) {
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
// 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;
pDSBufferDesc->dwBufferBytes = DSoundBufferGetPCMBufferSize(dwEmuFlags, X_BufferCacheSize);
}
inline void DSoundGenericUnlock(
@ -503,21 +509,13 @@ inline void ResizeIDirectSoundBuffer(
LPVOID &X_BufferCache,
DWORD &X_BufferCacheSize)
{
DWORD pcmSize = DSoundBufferGetPCMBufferSize(EmuFlags, Xbox_dwBytes);
if (Xbox_dwBytes == 0 || pcmSize == pDSBufferDesc->dwBufferBytes) {
if (Xbox_dwBytes == 0 || X_BufferCacheSize == Xbox_dwBytes) {
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;
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;
pDSBufferDesc->dwBufferBytes = DSoundBufferGetPCMBufferSize(EmuFlags, X_BufferCacheSize);
DSoundBufferReplace(pDSBuffer, pDSBufferDesc, PlayFlags, pDS3DBuffer);
}
@ -1023,10 +1021,10 @@ inline HRESULT HybridDirectSoundBuffer_SetFormat(
enterCriticalSection;
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.
} else {
GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, xbnullptr, xbnullptr);
GeneratePCMFormat(pBufferDesc, pwfxFormat, dwEmuFlags, 0, xbnullptr, X_BufferCacheSize);
}
HRESULT hRet = DS_OK;
if (g_pDSoundPrimaryBuffer == pDSBuffer) {