From d49762d27ee7308caeb4d11ec4870eb44b713403 Mon Sep 17 00:00:00 2001 From: jackchentwkh Date: Wed, 19 May 2021 19:20:39 +0800 Subject: [PATCH] Rebase Code and State Segments in EffectMaps. fix PGR2 --- .../hle/DSOUND/DirectSound/DirectSound.cpp | 68 ++++++++++++++++--- .../hle/DSOUND/DirectSound/DirectSound.hpp | 48 ++++++++++++- .../DSOUND/DirectSound/XFileMediaObject.cpp | 33 ++++++++- src/core/hle/Patches.cpp | 3 +- 4 files changed, 136 insertions(+), 16 deletions(-) diff --git a/src/core/hle/DSOUND/DirectSound/DirectSound.cpp b/src/core/hle/DSOUND/DirectSound/DirectSound.cpp index 5ecaa7fc6..8ec17b6e9 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSound.cpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSound.cpp @@ -514,9 +514,9 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSound_SetEffectData) } // ****************************************************************** -// * patch: IDirectSound_DownloadEffectsImage +// * patch: CDirectSound_DownloadEffectsImage // ****************************************************************** -xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSound_DownloadEffectsImage) +xbox::hresult_xt WINAPI xbox::EMUPATCH(CDirectSound_DownloadEffectsImage) ( LPDIRECTSOUND8 pThis, LPCVOID pvImageBuffer, @@ -536,22 +536,68 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(IDirectSound_DownloadEffectsImage) // This function is relative to DSP for Interactive 3-D Audio Level 2 (I3DL2) - LOG_NOT_SUPPORTED(); + LOG_INCOMPLETE(); if(ppImageDesc)//If the guest code request a pointer to ImageDesc structure to be returned, then we should allocate a memory and create ImageDesc. { // Code block below is reversed from Otogi. // ImageBuffer header starts from offset ox800 and ends in offset 0x817. actual DSP code segment starts from offset 0x818. // DWORD at offset 0x804 and offset 0x80C should be the code segment sizes in dwords. // ImageDesc is appended after code segments. There are additional two DWORDs data for each effect appended after ImageDesc which I have no idea what they are for. - DWORD N1 = *(DWORD *)((BYTE *)pvImageBuffer + 0x804); //first code segment size in dwords - DWORD N2 = *(DWORD *)((BYTE *)pvImageBuffer + 0x80C); //2nd code segment size in dwords - BYTE * pImageDesc = ((BYTE *)pvImageBuffer + 0x818 + 4 * (N1 + N2)); //calculate the starting address of ImageDesc inside the imagebuffer - DWORD EffectCount = *(DWORD *)pImageDesc; //the first DWORD in ImageDesc is EffectCount. - DWORD ImageDescSize = 8 + 32 * EffectCount; //The size of ImageDesc is two Dwords (8 bytes) + 8 DWORS (32 bytes) for each effects. - if (*ppImageDesc = malloc(ImageDescSize)) //allocate a new memory to keep the ImageDesc for guest code since the imagebuffer should be freed after the image were downloaded. - { - memcpy(*ppImageDesc, pImageDesc, ImageDescSize); //copy the ImageDesc from ImageBuffer. + + // Image buffer must be copied to internal and backed up 1st. the data might be referenced by the guest code later. + // The Code Segment Address and State address in DSEFFECTMAP aEffectMaps[1] must be rebased to the internal buffer. + + + // NOTE: this buffer should also be freed in IDirectSound_Release when the ref counter drops to zero, but that function is currently not implemented. + static PBYTE ImageBufferBackup = zeroptr; //The image buffer must be backed up since some game might reference ths data. ex. PGR2. + if (ImageBufferBackup != zeroptr) { + ExFreePool(ImageBufferBackup); } + + ImageBufferBackup = static_cast(ExAllocatePool(dwImageSize)); + if (ImageBufferBackup == zeroptr) { + return E_OUTOFMEMORY; + } + + std::memcpy(ImageBufferBackup, pvImageBuffer, dwImageSize); //Copy the ImageBuffer to internal backup Buffer. + + //from here, all process should base on internal image buffer. + + dword_xt N1 = *(PDWORD)(ImageBufferBackup + 0x804); //Total code segment size in dwords + dword_xt N2 = *(PDWORD)(ImageBufferBackup + 0x80C); //Total state segment size in dwords + PBYTE pImageDesc = ImageBufferBackup + 0x818 + 4 * (N1 + N2); //calculate the starting address of ImageDesc in image buffer + DWORD EffectCount = ((LPDSEFFECTIMAGEDESC)pImageDesc)->dwEffectCount; //the first DWORD in ImageDesc is EffectCount. + dword_xt ImageDescSize = 8 + 32 * EffectCount; //The size of ImageDesc is two Dwords (8 bytes) + 8 DWORS (32 bytes) for each effects. + + //Process the DSEFFECTMAP in internal image buffer, rebase code segmemt address and state segment address of each effect. + PBYTE pEffectMaps = (pImageDesc + 8); //EffectMaps array start from here. + for (int effect_loop = 0; effect_loop < EffectCount; effect_loop++) + { + + PBYTE pCodeSeg = pEffectMaps + effect_loop * 32; + *(PDWORD)pCodeSeg += (DWORD)ImageBufferBackup; + + PBYTE pStateSeg = pEffectMaps + effect_loop * 32+8; + *(PDWORD)pStateSeg += (DWORD)ImageBufferBackup; + + } + + + // NOTE: this buffer should also be freed in IDirectSound_Release when the ref counter drops to zero, but that function is currently not implemented. + static PBYTE ImageDescBuffer = zeroptr; + if (ImageDescBuffer != zeroptr) { + ExFreePool(ImageDescBuffer); + } + + ImageDescBuffer = static_cast(ExAllocatePool(ImageDescSize)); + if (ImageDescBuffer == zeroptr) { + return E_OUTOFMEMORY; + } + + // NOTE: this is very wrong. The dsp image is encrypted, and thus simply copying the original encrypted image won't do any good. + *ppImageDesc = ImageDescBuffer; + std::memcpy(*ppImageDesc, pImageDesc, ImageDescSize); + // with the code above, we could easily retrieve the address and size of ImageDesc within the image buffer. // then we can allocate a new memory, copy the imageDesc from the image buffer to the newly allocated memory, // then assign the newly allocated memory to the ppImageDesc. that's all. diff --git a/src/core/hle/DSOUND/DirectSound/DirectSound.hpp b/src/core/hle/DSOUND/DirectSound/DirectSound.hpp index e87167707..cefdaf186 100644 --- a/src/core/hle/DSOUND/DirectSound/DirectSound.hpp +++ b/src/core/hle/DSOUND/DirectSound/DirectSound.hpp @@ -127,6 +127,50 @@ struct SharedDSBuffer : DSBUFFER_S { } }; +typedef struct _DSEFFECTMAP { + LPVOID lpvCodeSegment; + DWORD dwCodeSize; + LPVOID lpvStateSegment; + DWORD dwStateSize; + LPVOID lpvYMemorySegment; + DWORD dwYMemorySize; + LPVOID lpvScratchSegment; + DWORD dwScratchSize; +} DSEFFECTMAP, *LPDSEFFECTMAP; +/*Members +lpvCodeSegment +Starting address of the DSP code segment for this effect. +dwCodeSize +Value that contains the code segment size, in DWORDs. +lpvStateSegment +Starting address of the effect state segment. +dwStateSize +Value that contains the size of the effect state segment, in DWORDs. +lpvYMemorySegment +Starting address of the DSP Y-memory segment. +dwYMemorySize +Value that contains the Y-memory segment size, in DWORDs. +lpvScratchSegment +Starting address of the scratch memory segment. +dwScratchSize +Value that contains the size of the scratch segment, in DWORDs. +*/ + +typedef struct _DSEFFECTIMAGEDESC { + DWORD dwEffectCount; + DWORD dwTotalScratchSize; + DSEFFECTMAP aEffectMaps[1]; +} DSEFFECTIMAGEDESC, *LPDSEFFECTIMAGEDESC; + +/*Members +dwEffectCount +Value that contains the number of effects in the image. +dwTotalScratchSize +Value that contains the total amount of space required by effects that use scratch space for delay lines. +aEffectMaps +Variable-length array that contains the effect descriptions. +*/ + //Custom flags (4 bytes support up to 31 shifts,starting from 0) #define DSE_FLAG_PCM (1 << 0) #define DSE_FLAG_XADPCM (1 << 1) @@ -414,9 +458,9 @@ xbox::hresult_xt WINAPI EMUPATCH(IDirectSound_SynchPlayback) ); // ****************************************************************** -// * patch: IDirectSound_DownloadEffectsImage +// * patch: CDirectSound_DownloadEffectsImage // ****************************************************************** -xbox::hresult_xt WINAPI EMUPATCH(IDirectSound_DownloadEffectsImage) +xbox::hresult_xt WINAPI EMUPATCH(CDirectSound_DownloadEffectsImage) ( LPDIRECTSOUND8 pThis, LPCVOID pvImageBuffer, diff --git a/src/core/hle/DSOUND/DirectSound/XFileMediaObject.cpp b/src/core/hle/DSOUND/DirectSound/XFileMediaObject.cpp index fb85b8a66..bae6f286a 100644 --- a/src/core/hle/DSOUND/DirectSound/XFileMediaObject.cpp +++ b/src/core/hle/DSOUND/DirectSound/XFileMediaObject.cpp @@ -38,6 +38,8 @@ #include "DirectSoundInline.hpp" +#include + // TODO: Tasks need to do for DirectSound HLE // * Need create patches // * Ac97CreateMediaObject (Need OOVPA) @@ -115,9 +117,36 @@ xbox::hresult_xt WINAPI xbox::EMUPATCH(XAudioDownloadEffectsImage) LOG_FUNC_ARG(ppImageDesc) LOG_FUNC_END; - LOG_NOT_SUPPORTED(); + LOG_INCOMPLETE(); + LPDIRECTSOUND8 pThis_tmp= zeroptr; + PBYTE pvImageBuffer; + dword_xt dwImageSize; - return S_OK; + HANDLE hFile; + DWORD dwBytesRead; + LPSTR pszScratchFile; + + //convert_pszImageName_to_pszScratchFile(); + std::string hostpath = CxbxConvertXboxToHostPath(std::string_view (pszImageName)); + + hFile = CreateFile(hostpath.c_str(),GENERIC_READ,0,NULL,OPEN_EXISTING,0,NULL); + + dwImageSize = GetFileSize(hFile, NULL); + + pvImageBuffer = new BYTE[dwImageSize]; + + BOOL bResult = ReadFile(hFile,pvImageBuffer,dwImageSize,&dwBytesRead,0); + + xbox::hresult_xt result = xbox::EMUPATCH(CDirectSound_DownloadEffectsImage)(pThis_tmp, pvImageBuffer,dwImageSize,pImageLoc,ppImageDesc); + + delete[] pvImageBuffer; + + if (hFile != INVALID_HANDLE_VALUE) + { + CloseHandle(hFile); + } + + return result;// result; } // ****************************************************************** diff --git a/src/core/hle/Patches.cpp b/src/core/hle/Patches.cpp index e27f43424..7fa2bb3f3 100644 --- a/src/core/hle/Patches.cpp +++ b/src/core/hle/Patches.cpp @@ -312,7 +312,8 @@ std::map g_PatchTable = { PATCH_ENTRY("IDirectSound_CommitEffectData", xbox::EMUPATCH(IDirectSound_CommitEffectData), PATCH_HLE_DSOUND), PATCH_ENTRY("IDirectSound_CreateSoundBuffer", xbox::EMUPATCH(IDirectSound_CreateSoundBuffer), PATCH_HLE_DSOUND), PATCH_ENTRY("IDirectSound_CreateSoundStream", xbox::EMUPATCH(IDirectSound_CreateSoundStream), PATCH_HLE_DSOUND), - PATCH_ENTRY("IDirectSound_DownloadEffectsImage", xbox::EMUPATCH(IDirectSound_DownloadEffectsImage), PATCH_HLE_DSOUND), +// PATCH_ENTRY("IDirectSound_DownloadEffectsImage", xbox::EMUPATCH(IDirectSound_DownloadEffectsImage), PATCH_HLE_DSOUND), + PATCH_ENTRY("CDirectSound_DownloadEffectsImage", xbox::EMUPATCH(CDirectSound_DownloadEffectsImage), PATCH_HLE_DSOUND), PATCH_ENTRY("IDirectSound_EnableHeadphones", xbox::EMUPATCH(IDirectSound_EnableHeadphones), PATCH_HLE_DSOUND), PATCH_ENTRY("IDirectSound_GetCaps", xbox::EMUPATCH(IDirectSound_GetCaps), PATCH_HLE_DSOUND), PATCH_ENTRY("IDirectSound_GetEffectData", xbox::EMUPATCH(IDirectSound_GetEffectData), PATCH_HLE_DSOUND),