Rebase Code and State Segments in EffectMaps. fix PGR2

This commit is contained in:
jackchentwkh 2021-05-19 19:20:39 +08:00
parent a04a079f19
commit d49762d27e
4 changed files with 136 additions and 16 deletions

View File

@ -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<PBYTE>(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<PBYTE>(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.

View File

@ -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,

View File

@ -38,6 +38,8 @@
#include "DirectSoundInline.hpp"
#include <core\kernel\support\EmuFile.h>
// 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;
}
// ******************************************************************

View File

@ -312,7 +312,8 @@ std::map<const std::string, const xbox_patch_t> 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),