From 6d1c9aeb67b499229d4e4f6aea96c18a89f44724 Mon Sep 17 00:00:00 2001 From: jpd002 Date: Wed, 23 Jun 2010 03:55:01 +0000 Subject: [PATCH] PsfPlayer: Added basic reverb support in PSP/SasCore emulation. git-svn-id: http://svn.purei.org/purei/trunk@670 b36208d7-6611-0410-8bec-b1987f11c4a2 --- Source/iop/Iop_Spu.cpp | 38 +------ Source/iop/Iop_SpuBase.cpp | 36 ++++++ Source/iop/Iop_SpuBase.h | 5 +- tools/PsfPlayer/Source/psp/PspBios.cpp | 4 + tools/PsfPlayer/Source/psp/Psp_SasCore.cpp | 123 ++++++++++++++++++++- tools/PsfPlayer/Source/psp/Psp_SasCore.h | 28 +++++ 6 files changed, 194 insertions(+), 40 deletions(-) diff --git a/Source/iop/Iop_Spu.cpp b/Source/iop/Iop_Spu.cpp index 5f2e8bd1..9d8b042e 100644 --- a/Source/iop/Iop_Spu.cpp +++ b/Source/iop/Iop_Spu.cpp @@ -89,42 +89,6 @@ static const char* g_generalRegisterName[MAX_GENERAL_REG_NAME] = "IN_COEF_R" }; -static bool g_reverbParamIsAddress[CSpuBase::REVERB_PARAM_COUNT] = -{ - true, - true, - false, - false, - false, - false, - false, - false, - false, - false, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - true, - false, - false -}; - CSpu::CSpu(CSpuBase& base) : m_base(base) { @@ -192,7 +156,7 @@ void CSpu::WriteRegister(uint32 address, uint16 value) { uint32 registerId = (address - REVERB_START) / 2; uint32 result = value; - if(g_reverbParamIsAddress[registerId]) + if(CSpuBase::g_reverbParamIsAddress[registerId]) { result *= 8; } diff --git a/Source/iop/Iop_SpuBase.cpp b/Source/iop/Iop_SpuBase.cpp index 1ef1c3cb..eda00711 100644 --- a/Source/iop/Iop_SpuBase.cpp +++ b/Source/iop/Iop_SpuBase.cpp @@ -9,6 +9,42 @@ using namespace std; #define INIT_SAMPLE_RATE (44100) #define LOG_NAME ("iop_spubase") +bool CSpuBase::g_reverbParamIsAddress[REVERB_PARAM_COUNT] = +{ + true, + true, + false, + false, + false, + false, + false, + false, + false, + false, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + true, + false, + false +}; + CSpuBase::CSpuBase(uint8* ram, uint32 ramSize) : m_ram(ram), m_ramSize(ramSize), diff --git a/Source/iop/Iop_SpuBase.h b/Source/iop/Iop_SpuBase.h index f336dca0..a0cbeb9c 100644 --- a/Source/iop/Iop_SpuBase.h +++ b/Source/iop/Iop_SpuBase.h @@ -176,7 +176,6 @@ namespace Iop void SetChannelOnHi(uint16); UNION32_16 GetChannelReverb() const; - void SetChannelReverb(uint16, uint16); void SetChannelReverbLo(uint16); void SetChannelReverbHi(uint16); @@ -194,7 +193,9 @@ namespace Iop void Render(int16*, unsigned int, unsigned int); - private: + static bool g_reverbParamIsAddress[REVERB_PARAM_COUNT]; + + private: class CSampleReader { public: diff --git a/tools/PsfPlayer/Source/psp/PspBios.cpp b/tools/PsfPlayer/Source/psp/PspBios.cpp index 7c5ddd7c..1e1873b7 100644 --- a/tools/PsfPlayer/Source/psp/PspBios.cpp +++ b/tools/PsfPlayer/Source/psp/PspBios.cpp @@ -106,6 +106,10 @@ CBios::MODULEFUNCTION CBios::g_SasCoreFunctions[] = { 0x07F58C24, "sasGetAllEnvelope" }, { 0xA3589D81, "sasCore" }, { 0x42778A9F, "sasInit" }, + { 0x33D4AB37, "sasSetEffectType" }, + { 0x267A6DD2, "sasSetEffectParam" }, + { 0xD5A229C9, "sasSetEffectVolume" }, + { 0xF983B186, "sasSetEffect" }, { NULL, NULL }, }; diff --git a/tools/PsfPlayer/Source/psp/Psp_SasCore.cpp b/tools/PsfPlayer/Source/psp/Psp_SasCore.cpp index e3855abf..540219ae 100644 --- a/tools/PsfPlayer/Source/psp/Psp_SasCore.cpp +++ b/tools/PsfPlayer/Source/psp/Psp_SasCore.cpp @@ -5,6 +5,30 @@ using namespace Psp; +#define SPURAM_ALLOC_BASEADDRESS (0x40000) + +CSasCore::REVERBINFO CSasCore::g_ReverbStudioC = +{ + 0x6FE0, + { + 0x00E3, 0x00A9, 0x6F60, 0x4FA8, 0xBCE0, 0x4510, 0xBEF0, 0xA680, + 0x5680, 0x52C0, 0x0DFB, 0x0B58, 0x0D09, 0x0A3C, 0x0BD9, 0x0973, + 0x0B59, 0x08DA, 0x08D9, 0x05E9, 0x07EC, 0x04B0, 0x06EF, 0x03D2, + 0x05EA, 0x031D, 0x031C, 0x0238, 0x0154, 0x00AA, 0x8000, 0x8000, + } +}; + +CSasCore::REVERBINFO CSasCore::g_ReverbSpace = +{ + 0xF6C0, + { + 0x033D, 0x0231, 0x7E00, 0x5000, 0xB400, 0xB000, 0x4C00, 0xB000, + 0x6000, 0x5400, 0x1ED6, 0x1A31, 0x1D14, 0x183B, 0x1BC2, 0x16B2, + 0x1A32, 0x15EF, 0x15EE, 0x1055, 0x1334, 0x0F2D, 0x11F6, 0x0C5D, + 0x1056, 0x0AE1, 0x0AE0, 0x07A2, 0x0464, 0x0232, 0x8000, 0x8000, + } +}; + CSasCore::CSasCore(uint8* ram) : m_spuRam(NULL) , m_spuRamSize(0) @@ -68,7 +92,7 @@ uint32 CSasCore::AllocMemory(uint32 size) { assert(m_spuRamSize != 0); - const uint32 startAddress = 0x1000; + const uint32 startAddress = SPURAM_ALLOC_BASEADDRESS; uint32 currentAddress = startAddress; MemBlockList::iterator blockIterator(m_blocks.begin()); while(blockIterator != m_blocks.end()) @@ -123,6 +147,26 @@ void CSasCore::VerifyAllocationMap() #endif +void CSasCore::SetupReverb(const REVERBINFO& reverbInfo) +{ + for(unsigned int spuIdx = 0; spuIdx < 2; spuIdx++) + { + uint32 endAddress = 0x20000 + (spuIdx * 0x20000); + uint32 startAddress = endAddress - reverbInfo.workAreaSize; + m_spu[spuIdx]->SetReverbWorkAddressStart(startAddress); + m_spu[spuIdx]->SetReverbWorkAddressEnd(endAddress - 1); + for(unsigned int i = 0; i < Iop::CSpuBase::REVERB_PARAM_COUNT; i++) + { + uint32 param = reverbInfo.params[i]; + if(Iop::CSpuBase::g_reverbParamIsAddress[i]) + { + param *= 8; + } + m_spu[spuIdx]->SetReverbParam(i, param); + } + } +} + uint32 CSasCore::Init(uint32 contextAddr, uint32 grain, uint32 unknown2, uint32 unknown3, uint32 frequency) { #ifdef _DEBUG @@ -341,6 +385,60 @@ uint32 CSasCore::GetEndFlag(uint32 contextAddr) return result; } +uint32 CSasCore::SetEffectType(uint32 contextAddr, uint32 effectType) +{ +#ifdef _DEBUG + CLog::GetInstance().Print(LOGNAME, "SetEffectType(contextAddr = 0x%0.8X, effectType = 0x%0.8X);\r\n", + contextAddr, effectType); +#endif + switch(effectType) + { + case REVERB_STUDIOC: + SetupReverb(g_ReverbStudioC); + break; + case REVERB_SPACE: + SetupReverb(g_ReverbSpace); + break; + } + return 0; +} + +uint32 CSasCore::SetEffectParam(uint32 contextAddr, uint32 dt, uint32 fb) +{ +#ifdef _DEBUG + CLog::GetInstance().Print(LOGNAME, "SetEffectParam(contextAddr = 0x%0.8X, dt = 0x%0.2X, fb = 0x%0.2X);\r\n", + contextAddr, dt, fb); +#endif + return 0; +} + +uint32 CSasCore::SetEffectVolume(uint32 contextAddr, uint32 volumeLeft, uint32 volumeRight) +{ +#ifdef _DEBUG + CLog::GetInstance().Print(LOGNAME, "SetEffectVolume(contextAddr = 0x%0.8X, left = 0x%0.2X, right = 0x%0.2X);\r\n", + contextAddr, volumeLeft, volumeRight); +#endif + return 0; +} + +uint32 CSasCore::SetEffect(uint32 contextAddr, uint32 drySwitch, uint32 wetSwitch) +{ +#ifdef _DEBUG + CLog::GetInstance().Print(LOGNAME, "SetEffect(contextAddr = 0x%0.8X, dry = %d, wet = %d);\r\n", + contextAddr, drySwitch, wetSwitch); +#endif + if(drySwitch) + { + for(unsigned int spuIdx = 0; spuIdx < 2; spuIdx++) + { + m_spu[spuIdx]->SetControl(Iop::CSpuBase::CONTROL_REVERB); + m_spu[spuIdx]->SetChannelReverbLo(0xFFFF); + m_spu[spuIdx]->SetChannelReverbHi(0xFFFF); + } + } + return 0; +} + void CSasCore::Invoke(uint32 methodId, CMIPS& context) { switch(methodId) @@ -411,6 +509,29 @@ void CSasCore::Invoke(uint32 methodId, CMIPS& context) context.m_State.nGPR[CMIPS::V0].nV0 = GetEndFlag( context.m_State.nGPR[CMIPS::A0].nV0); break; + case 0x33D4AB37: + context.m_State.nGPR[CMIPS::V0].nV0 = SetEffectType( + context.m_State.nGPR[CMIPS::A0].nV0, + context.m_State.nGPR[CMIPS::A1].nV0); + break; + case 0x267A6DD2: + context.m_State.nGPR[CMIPS::V0].nV0 = SetEffectParam( + context.m_State.nGPR[CMIPS::A0].nV0, + context.m_State.nGPR[CMIPS::A1].nV0, + context.m_State.nGPR[CMIPS::A2].nV0); + break; + case 0xD5A229C9: + context.m_State.nGPR[CMIPS::V0].nV0 = SetEffectVolume( + context.m_State.nGPR[CMIPS::A0].nV0, + context.m_State.nGPR[CMIPS::A1].nV0, + context.m_State.nGPR[CMIPS::A2].nV0); + break; + case 0xF983B186: + context.m_State.nGPR[CMIPS::V0].nV0 = SetEffect( + context.m_State.nGPR[CMIPS::A0].nV0, + context.m_State.nGPR[CMIPS::A1].nV0, + context.m_State.nGPR[CMIPS::A2].nV0); + break; default: CLog::GetInstance().Print(LOGNAME, "Unknown function called 0x%0.8X\r\n", methodId); break; diff --git a/tools/PsfPlayer/Source/psp/Psp_SasCore.h b/tools/PsfPlayer/Source/psp/Psp_SasCore.h index a7ffbf29..eda0bb36 100644 --- a/tools/PsfPlayer/Source/psp/Psp_SasCore.h +++ b/tools/PsfPlayer/Source/psp/Psp_SasCore.h @@ -18,6 +18,26 @@ namespace Psp void SetSpuInfo(Iop::CSpuBase*, Iop::CSpuBase*, uint8*, uint32); private: + enum REVERBTYPES + { + REVERB_OFF = -1, + REVERB_ROOM = 0, + REVERB_STUDIOA = 1, + REVERB_STUDIOB = 2, + REVERB_STUDIOC = 3, + REVERB_HALL = 4, + REVERB_SPACE = 5, + REVERB_ECHO = 6, + REVERB_DELAY = 7, + REVERB_PIPE = 8 + }; + + struct REVERBINFO + { + uint32 workAreaSize; + uint16 params[Iop::CSpuBase::REVERB_PARAM_COUNT]; + }; + struct SPUMEMBLOCK { uint32 address; @@ -37,12 +57,17 @@ namespace Psp uint32 GetPauseFlag(uint32); uint32 GetEndFlag(uint32); uint32 GetAllEnvelope(uint32, uint32); + uint32 SetEffectType(uint32, uint32); + uint32 SetEffectParam(uint32, uint32, uint32); + uint32 SetEffectVolume(uint32, uint32, uint32); + uint32 SetEffect(uint32, uint32, uint32); uint32 AllocMemory(uint32); void FreeMemory(uint32); #ifdef _DEBUG void VerifyAllocationMap(); #endif + void SetupReverb(const REVERBINFO&); Iop::CSpuBase::CHANNEL* GetSpuChannel(uint32); @@ -53,6 +78,9 @@ namespace Psp uint32 m_grain; MemBlockList m_blocks; + + static REVERBINFO g_ReverbStudioC; + static REVERBINFO g_ReverbSpace; }; typedef std::tr1::shared_ptr SasCoreModulePtr;