From 8d30e3f3c041d1f29b918f8d37c034e8058a18b0 Mon Sep 17 00:00:00 2001 From: hrydgard Date: Sat, 20 Jun 2009 10:39:45 +0000 Subject: [PATCH] DSP HLE: Break out the ADPCM decoder, add a few comments. git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@3504 8ced0084-cf51-0410-be5f-012b33b47a6e --- .../Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj | 28 +- .../Plugin_DSP_HLE/Src/UCodes/UCode_Jac.h | 4 + .../Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.cpp | 338 ++++++------------ .../Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h | 87 ++--- .../Src/UCodes/UCode_Zelda_ADPCM.cpp | 97 +++++ .../Src/UCodes/UCode_Zelda_ADPCM.h | 20 ++ .../Plugin_DSP_HLE/Src/UCodes/UCodes.cpp | 9 +- 7 files changed, 286 insertions(+), 297 deletions(-) create mode 100644 Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.cpp create mode 100644 Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.h diff --git a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj index f36f96995f..322fcbdc00 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj +++ b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj @@ -593,14 +593,6 @@ RelativePath=".\Src\UCodes\UCode_ROM.h" > - - - - @@ -673,6 +665,26 @@ > + + + + + + + + + + sample_queue; int m_queueSize; int m_mode; - }; - - CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) : IUCode(_rMailHandler) , m_numSteps(0) @@ -107,7 +102,7 @@ CUCode_Zelda::CUCode_Zelda(CMailHandler& _rMailHandler) m_rMailHandler.PushMail(0xF3551111); // handshake memset(m_Buffer, 0, sizeof(m_Buffer)); - for (int i=0; i<0x10; i++) + for (int i = 0; i < 0x10; i++) m_PBMask[i] = false; templbuffer = new int[1024 * 1024]; @@ -151,10 +146,11 @@ void CUCode_Zelda::UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _ // zelda: // perhaps init or "has played before" pTest[0x32] = 0x00; - pTest[0x66] = 0x00; // history1 + pTest[0x66] = 0x00; // history1 pTest[0x67] = 0x00; // history2 // samplerate? length? num of samples? i dunno... + // Likely length... pTest[0x3a] = pTest[0x8a]; pTest[0x3b] = pTest[0x8b]; @@ -163,66 +159,29 @@ void CUCode_Zelda::UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _ pTest[0x39] = pTest[0x8d]; } - if (pTest[0x01] != 0) // early out... i dunno if this can happen because we filter it above - { + if (pTest[0x01] != 0) // 0747 early out... i dunno if this can happen because we filter it above return; - } - u32 t1 = pTest[0x39]; - u32 t2 = pTest[0x38]; - u32 ARAMAddr = (t2<<16) | t1; + u32 ARAMAddr = (pTest[0x38] << 16) | pTest[0x39]; + u32 NumberOfSamples = (pTest[0x3a] << 16) | pTest[0x3b]; - // ???????????????????????????????? - u32 t3 = pTest[0x3a]; - u32 t4 = pTest[0x3b]; - u32 NumberOfSamples = (t3<<16) | t4; + // round upwards how many samples we need to copy, 0759 NumberOfSamples = (NumberOfSamples + 0xf) >> 4; // i think the lower 4 are the fraction - - - u32 frac = NumberOfSamples& 0xF; - + u32 frac = NumberOfSamples & 0xF; u8 inBuffer[9]; short outbuf[16]; u32 sampleCount = 0; + // It must be something like this: + + // The PB contains a small sample buffer of 0x4D decoded samples. + // If it's empty or "used", decode to it. + // Then, resample from this buffer to the output as you go. When it needs + // wrapping, decode more. + #define USE_RESAMPLE 1 -#if USE_RESAMPLE == 1 - - while(NumberOfSamples > 0) - { - for (int i=0; i<9; i++) - { - inBuffer[i] = g_dspInitialize.pARAM_Read_U8(ARAMAddr); - ARAMAddr++; - } - - AFCdecodebuffer((char*)inBuffer, outbuf, (short*)&pTest[0x66], (short*)&pTest[0x67]); - CResampler Sampler(outbuf, 16, 48000); - - - while (Sampler.m_queueSize > 0) - { - int sample = Sampler.sample_queue.front(); - Sampler.sample_queue.pop(); - Sampler.m_queueSize-=1; - - templbuffer[sampleCount] += sample; - temprbuffer[sampleCount] += sample; - sampleCount++; - - if (sampleCount > _Size) - break; - } - - if (sampleCount > _Size) - break; - - NumberOfSamples--; - } - -#else - +#if USE_RESAMPLE != 1 for (int s=0; s<(_Size/16);s++) { for (int i=0; i<9; i++) @@ -246,9 +205,38 @@ void CUCode_Zelda::UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _ if (NumberOfSamples<=0) break; } +#else + while (NumberOfSamples > 0) + { + for (int i = 0; i < 9; i++) + { + inBuffer[i] = g_dspInitialize.pARAM_Read_U8(ARAMAddr); + ARAMAddr++; + } + AFCdecodebuffer(m_AFCCoefTable, (char*)inBuffer, outbuf, (short*)&pTest[0x66], (short*)&pTest[0x67], 9); + CResampler Sampler(outbuf, 16, 48000); + + while (Sampler.m_queueSize > 0) + { + int sample = Sampler.sample_queue.front(); + Sampler.sample_queue.pop(); + Sampler.m_queueSize-=1; + + templbuffer[sampleCount] += sample; + temprbuffer[sampleCount] += sample; + sampleCount++; + + if (sampleCount > _Size) + break; + } + + if (sampleCount > _Size) + break; + + NumberOfSamples--; + } #endif - if (NumberOfSamples == 0) { pTest[0x01] = 1; // we are done ?? @@ -256,6 +244,7 @@ void CUCode_Zelda::UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _ // write back NumberOfSamples = (NumberOfSamples << 4); // missing fraction + pTest[0x38] = ARAMAddr >> 16; pTest[0x39] = ARAMAddr & 0xFFFF; pTest[0x3a] = NumberOfSamples >> 16; @@ -268,7 +257,7 @@ void CUCode_Zelda::UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _ static u8 Buffer[500000]; for (int i =0; i> 16) & 0x000F; m_PBMask[Slot] = _uMail & 0xFFFF; m_MailState = WaitForMail; @@ -368,48 +346,38 @@ void CUCode_Zelda::HandleMail(u32 _uMail) m_MailState = WaitForMail; } break; - } - - } void CUCode_Zelda::MixAdd(short* _pBuffer, int _iSize) { - //TODO(XK): Zelda UCode MixAdd? if (m_NumberOfFramesToRender > 0) { if (m_NumPBs <= m_MaxSyncedPB) // we just render if all PBs are synced...Zelda does it in steps of 0x10 PBs but hey this is HLE { - if (_iSize > 1024 * 1024) _iSize = 1024 * 1024; memset(templbuffer, 0, _iSize * sizeof(int)); memset(temprbuffer, 0, _iSize * sizeof(int)); + CopyPBsFromRAM(); + // render frame... + for (u32 i = 0; i < m_NumPBs; i++) { - CopyPBsFromRAM(); - - // render frame... - for (u32 i=0; i> 4; + int Mask = i & 0x0F; + if (m_PBMask[Slot] & Mask)) */ { - // masking of PBs is done in zelda 0272... skip it for the moment - /* int Slot = i >> 4; - int Mask = i & 0x0F; - if (m_PBMask[Slot] & Mask))*/ - { - UpdatePB(m_PBs[i], templbuffer, temprbuffer, _iSize); - } - } - - CopyPBsToRAM(); - m_MaxSyncedPB = 0; + UpdatePB(m_PBs[i], templbuffer, temprbuffer, _iSize); + } } + CopyPBsToRAM(); + m_MaxSyncedPB = 0; - - if(_pBuffer) { + if (_pBuffer) { for (int i = 0; i < _iSize; i++) { // Clamp into 16-bit. Maybe we should add a volume compressor here. @@ -430,7 +398,6 @@ void CUCode_Zelda::MixAdd(short* _pBuffer, int _iSize) return; } - m_CurrentFrameToRender++; // sync, we are ready @@ -450,9 +417,6 @@ void CUCode_Zelda::MixAdd(short* _pBuffer, int _iSize) m_CurrentFrameToRender = 0; } } - - - } // zelda debug ..803F6418 @@ -480,29 +444,29 @@ void CUCode_Zelda::ExecuteList() m_NumPBs = 0x40; } - u32 tmp[4]; - m_PBAddress = tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); - tmp[3] = Read32(); + m_PBAddress = Read32(); + u32 DSPADPCM_FILTER = Read32(); + u32 DSPRES_FILTER = Read32(); + m_PBAddress2 = Read32(); + // What is this stuff? u16 Buffer[0x280]; - for (int i=0; i<0x280;i++) + for (int i = 0; i < 0x280; i++) { - Buffer[i] = Memory_Read_U16(tmp[1] + (i*2)); + Buffer[i] = Memory_Read_U16(DSPADPCM_FILTER + (i*2)); } u16* pTmp = (u16*)m_AFCCoefTable; - for (int i=0; i<0x20;i++) + for (int i = 0; i < 0x20; i++) { - pTmp[i] = Memory_Read_U16(tmp[2] + (i*2)); + pTmp[i] = Memory_Read_U16(DSPRES_FILTER + (i*2)); } DEBUG_LOG(DSPHLE, "DsetupTable"); - DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[0]); - DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[1]); - DEBUG_LOG(DSPHLE, "DSPRES_FILTER (size: 0x40): 0x%08x", tmp[2]); - DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[3]); + DEBUG_LOG(DSPHLE, "Param Blocks 1: 0x%08x", m_PBAddress); + DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp1); + DEBUG_LOG(DSPHLE, "DSPRES_FILTER (size: 0x40): 0x%08x", tmp2); + DEBUG_LOG(DSPHLE, "Param Blocks 2: 0x%08x", m_PBAddress2); } break; @@ -510,52 +474,47 @@ void CUCode_Zelda::ExecuteList() // SyncFrame doesn't send a 0xDCD10004 SYNC at all ... just the 0xDCD10005 for "frame end" case 0x02: { - u32 tmp[3]; - tmp[0] = Read32(); - tmp[1] = Read32(); - tmp[2] = Read32(); + m_MixingBufferLeft = Read32(); + m_MixingBufferRight = Read32(); m_NumberOfFramesToRender = (CmdMail >> 16) & 0xFF; m_MaxSyncedPB = 0; DEBUG_LOG(DSPHLE, "DsyncFrame"); - DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[0]); - DEBUG_LOG(DSPHLE, "???: 0x%08x", tmp[1]); - DEBUG_LOG(DSPHLE, "DSPADPCM_FILTER (size: 0x500): 0x%08x", tmp[2]); + DEBUG_LOG(DSPHLE, "Left Mixing Buffer: 0x%08x", m_MixingBufferLeft); + DEBUG_LOG(DSPHLE, "Right Mixing Buffer: 0x%08x", m_MixingBufferRight); + // This is where we should render. soundStream->GetMixer()->SetHLEReady(true); } return; /* - case 0x03: break; // dunno ... zelda ww jmps to 0x0073 - case 0x04: break; // dunno ... zelda ww jmps to 0x0580 - case 0x05: break; // dunno ... zelda ww jmps to 0x0592 - case 0x06: break; // dunno ... zelda ww jmps to 0x0469 - - case 0x07: break; // dunno ... zelda ww jmps to 0x044d - case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 - case 0x09: break; // dunno ... zelda ww jmps to 0x044d + case 0x03: break; // dunno ... zelda ww jmps to 0x0073 + case 0x04: break; // dunno ... zelda ww jmps to 0x0580 + case 0x05: break; // dunno ... zelda ww jmps to 0x0592 + case 0x06: break; // dunno ... zelda ww jmps to 0x0469 + case 0x07: break; // dunno ... zelda ww jmps to 0x044d + case 0x08: break; // Mixer ... zelda ww jmps to 0x0485 + case 0x09: break; // dunno ... zelda ww jmps to 0x044d */ // DsetDolbyDelay ... zelda ww jumps to 0x00b2 case 0x0d: { - u32 tmp[2]; + u32 tmp[1]; tmp[0] = Read32(); - tmp[1] = Read32(); - DEBUG_LOG(DSPHLE, "DSetDolbyDelay"); DEBUG_LOG(DSPHLE, "DOLBY2_DELAY_BUF (size 0x960): 0x%08x", tmp[0]); - DEBUG_LOG(DSPHLE, "DSPRES_FILTER (size 0x500): 0x%08x", tmp[1]); } break; - // Set VARAM - // Luigi__: in the real Zelda ucode, this opcode is dummy - // however, in the ucode used by SMG it isn't + // Set VARAM + // Luigi__: in the real Zelda ucode, this opcode is dummy + // however, in the ucode used by SMG it isn't case 0x0e: { + DEBUG_LOG(DSPHLE, "Set VARAM - ???"); /* 00b0 0080 037d lri $AR0, #0x037d 00b2 0e01 lris $AC0.M, #0x01 @@ -581,8 +540,6 @@ void CUCode_Zelda::ExecuteList() m_rMailHandler.PushMail(0xF3550000 | Sync); } - - void CUCode_Zelda::CopyPBsFromRAM() { for (u32 i = 0; i < m_NumPBs; i++) @@ -619,100 +576,11 @@ void CUCode_Zelda::CopyPBsToRAM() // input = location of encoded source samples // out = location of destination buffer (16 bits / sample) - // I am sure that there are 5 bytes of input for 16 samples output too... just check the UCode // if (type == 5) -> 5 input bytes // if (type == 9) -> 9 input bytes // -int CUCode_Zelda::AFCdecodebuffer(char *input, signed short *out, short * histp, short * hist2p, int type) -{ - int sample; - short nibbles[16]; - int i,j; - char *src,*dst; - short idx; - short delta; - short hist=*histp; - short hist2=*hist2p; - - dst = (char*)out; - - src=input; - delta = 1<<(((*src)>>4)&0xf); - idx = (*src)&0xf; - - src++; - - if (type == 9) - { - for(i = 0; i < 16; i = i + 2) { - j = ( *src & 255) >> 4; - nibbles[i] = j; - j = *src & 255 & 15; - nibbles[i+1] = j; - src++; - } - - for(i = 0; i < 16; i = i + 1) { - if(nibbles[i] >= 8) - nibbles[i] = nibbles[i] - 16; - } - } - else - { - // untested !!! i havnt seen such a sample yet :) - for(i = 0; i < 16; i = i + 4) - { - - j = (*src >> 0) & 0x02; - nibbles[i] = j; - - j = (*src >> 2) & 0x02; - nibbles[i+1] = j; - - j = (*src >> 4) & 0x02; - nibbles[i+2] = j; - - j = (*src >> 6) & 0x02; - nibbles[i+3] = j; - - src++; - } - - for(i = 0; i < 16; i = i + 1) - { - if(nibbles[i] >= 2) - nibbles[i] = nibbles[i] - 4; - } - } - - for(i = 0; i<16 ; i = i + 1) { - - sample = (delta * nibbles[i])<<11; - sample += ((long)hist * m_AFCCoefTable[idx][0]) + ((long)hist2 * m_AFCCoefTable[idx][1]); - sample = sample >> 11; - - if(sample > 32767) { - sample = 32767; - } - if(sample < -32768) { - sample = -32768; - } - - *(short*)dst = (short)sample; - dst = dst + 2; - - hist2 = hist; - hist = (short)sample; - - } - *histp=hist; - *hist2p=hist2; - - return((int)src); -} - /////////////////////////////////////////////////////////////////////////////////////////////////// // // --- Debug Helper @@ -722,14 +590,18 @@ int CUCode_Zelda::AFCdecodebuffer(char *input, signed short *out, short * histp, void CUCode_Zelda::DumpPB(const ZPB& _rPB) { u16* pTmp = (u16*)&_rPB; - FILE* pF = fopen("e:\\PB.txt", "wt"); + FILE* pF = fopen("d:\\dump\\PB.txt", "a"); if (pF) { - for (int i=0; i<0xc0;i++) - { - fprintf(pF, "[0x%02x] 0x%04x\n", i, pTmp[i]); - } - fclose(pF); + if (_rPB.addr_high) + { + for (int i = 0; i < 0xc0; i += 4) + { + fprintf(pF, "[0x%02x] %04x %04x %04x %04x\n", i, pTmp[i], pTmp[i + 1], pTmp[i + 2], pTmp[i + 3]); + } + fprintf(pF, "\n"); + fclose(pF); + } } } @@ -755,7 +627,6 @@ int CUCode_Zelda::DumpAFC(u8* pIn, const int size, const int srate) 0x02, 0x00, 0x10, 0x00, 0x64, 0x61, 0x74, 0x61, 0x00, 0x00, 0x00, 0x00 }; - outfile = fopen("d:/supa.wav","wb"); if (!outfile) return 1; @@ -771,7 +642,7 @@ int CUCode_Zelda::DumpAFC(u8* pIn, const int size, const int srate) memcpy(inbuf, pIn, 9); pIn += 9; - AFCdecodebuffer((char*)inbuf,outbuf,&hist,&hist2); + AFCdecodebuffer(m_AFCCoefTable, (char*)inbuf,outbuf,&hist,&hist2,9); if (fwrite(outbuf,1,16*2,outfile) != 16*2) return 1; @@ -782,7 +653,6 @@ int CUCode_Zelda::DumpAFC(u8* pIn, const int size, const int srate) return 0; } - void CUCode_Zelda::DoState(PointerWrap &p) { p.Do(m_MailState); p.Do(m_PBMask); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h index 5227bfe2ec..c8d8c9db5f 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda.h @@ -21,8 +21,6 @@ #include "Common.h" #include "UCodes.h" - - struct ZPB { // R/W data ============= @@ -35,17 +33,18 @@ struct ZPB u16 unk5; u16 unk6; - u16 unk7[0x2C]; // 0x033 - u16 SampleData[0x4D]; + u16 unk7[0x2C]; // 0x033 + u16 SampleData[0x4D]; // 0x4D = 9 * 8 - // Read only data(0x80 to the end) - u16 type; // 0x5, 0x9 = AFC. + // From here, "read only" data (0x80 to the end) + // 0x88, 0x89 could be volume + u16 type; // 0x5, 0x9 = AFC. There are more types but we've only seen AFC so far. u16 r_unknown1; u16 r_unknown2[0x14 / 2]; - // Not sure what addresses this is, hopefully to sample data in ARAM. - // These are the only things in the param blocks that look a lot like pointers. + // Pointer to sample data in ARAM. + // These are the only things in the param blocks that look a lot like pointers. u16 addr_high; // at 0x18 = 0xC * 2 u16 addr_low; @@ -60,6 +59,28 @@ namespace { class CUCode_Zelda : public IUCode { +public: + CUCode_Zelda(CMailHandler& _rMailHandler); + virtual ~CUCode_Zelda(); + + void HandleMail(u32 _uMail); + void Update(int cycles); + void MixAdd(short* buffer, int size); + + void UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _Size); + + void CopyPBsFromRAM(); + void CopyPBsToRAM(); + + void DoState(PointerWrap &p); + + int *templbuffer; + int *temprbuffer; + + // simple dump ... + void DumpPB(const ZPB& _rPB); + int DumpAFC(u8* pIn, const int size, const int srate); + private: enum EDSP_Codes { @@ -72,7 +93,7 @@ private: }; // AFC CoefTable - short m_AFCCoefTable[16][2]; + s16 m_AFCCoefTable[32]; // Command 0x2: SyncFrame int m_NumberOfFramesToRender; @@ -86,7 +107,6 @@ private: u32 m_readOffset; - enum EMailState { WaitForMail, @@ -94,63 +114,28 @@ private: ReadingMessage, ReadingSystemMsg }; + EMailState m_MailState; u16 m_PBMask[0x10]; u32 m_NumPBs; - u32 m_PBAddress; + u32 m_PBAddress; // The main param block array + u32 m_PBAddress2; // 4 smaller param blocks + + u32 m_MixingBufferLeft; + u32 m_MixingBufferRight; u32 m_MaxSyncedPB; ZPB m_PBs[0x40]; - - - u8 Read8() - { - return m_Buffer[m_readOffset++]; - } - - u16 Read16() - { - u16 res = *(u16*)&m_Buffer[m_readOffset]; - m_readOffset += 2; - return res; - } - u32 Read32() { u32 res = *(u32*)&m_Buffer[m_readOffset]; m_readOffset += 4; return res; } -public: - - CUCode_Zelda(CMailHandler& _rMailHandler); - virtual ~CUCode_Zelda(); - - void HandleMail(u32 _uMail); - void Update(int cycles); - void MixAdd(short* buffer, int size); - - - void UpdatePB(ZPB& _rPB, int *templbuffer, int *temprbuffer, u32 _Size); - - void CopyPBsFromRAM(); - void CopyPBsToRAM(); - - void DoState(PointerWrap &p); - - int AFCdecodebuffer(char *input, signed short *out, short * histp, short * hist2p, int type = 9); - - - int *templbuffer; - int *temprbuffer; - - // simple dump ... - void DumpPB(const ZPB& _rPB); - int DumpAFC(u8* pIn, const int size, const int srate); }; #endif diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.cpp new file mode 100644 index 0000000000..a3160f3c79 --- /dev/null +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.cpp @@ -0,0 +1,97 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" +#include "UCode_Zelda_ADPCM.h" + +void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type) +{ + short nibbles[16]; + short hist = *histp; + short hist2 = *hist2p; + + const char *src = input; + char *dst = (char*)out; + + // First 2 nibbles are ADPCM scale etc. + short delta = 1 << (((*src) >> 4) & 0xf); + short idx = (*src) & 0xf; + + src++; + + if (type == 9) + { + for (int i = 0; i < 16; i = i + 2) { + int j = (*src & 255) >> 4; + nibbles[i] = j; + j = *src & 255 & 15; + nibbles[i+1] = j; + src++; + } + + for (int i = 0; i < 16; i = i + 1) { + if (nibbles[i] >= 8) + nibbles[i] = nibbles[i] - 16; + } + } + else + { + // untested !!! i havnt seen such a sample yet :) + for (int i = 0; i < 16; i += 4) + { + int j = (*src >> 0) & 0x02; + nibbles[i] = j; + + j = (*src >> 2) & 0x02; + nibbles[i+1] = j; + + j = (*src >> 4) & 0x02; + nibbles[i+2] = j; + + j = (*src >> 6) & 0x02; + nibbles[i+3] = j; + + src++; + } + + for (int i = 0; i < 16; i++) + { + if (nibbles[i] >= 2) + nibbles[i] = nibbles[i] - 4; + } + } + + for (int i = 0; i < 16; i++) + { + int sample = (delta * nibbles[i]) << 11; + sample += ((long)hist * coef[idx * 2]) + ((long)hist2 * coef[idx * 2 + 1]); + sample = sample >> 11; + if (sample > 32767) { + sample = 32767; + } + if (sample < -32768) { + sample = -32768; + } + *(short*)dst = (short)sample; + dst = dst + 2; + hist2 = hist; + hist = (short)sample; + } + + *histp=hist; + *hist2p=hist2; +} diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.h new file mode 100644 index 0000000000..1839ff4eae --- /dev/null +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_Zelda_ADPCM.h @@ -0,0 +1,20 @@ +// Copyright (C) 2003-2008 Dolphin Project. + +// This program is free software: you can redistribute it and/or modify +// it under the terms of the GNU General Public License as published by +// the Free Software Foundation, version 2.0. + +// This program is distributed in the hope that it will be useful, +// but WITHOUT ANY WARRANTY; without even the implied warranty of +// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the +// GNU General Public License 2.0 for more details. + +// A copy of the GPL 2.0 should have been included with the program. +// If not, see http://www.gnu.org/licenses/ + +// Official SVN repository and contact information can be found at +// http://code.google.com/p/dolphin-emu/ + +#include "Common.h" + +void AFCdecodebuffer(const s16 *coef, const char *input, signed short *out, short *histp, short *hist2p, int type); diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp index 13e0c6020a..2f141a383c 100644 --- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp +++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp @@ -56,13 +56,14 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler) case 0xd73338cf: // IPL case 0x42f64ac4: // Luigi (after fix) case 0x4be6a5cb: // AC, Pikmin (after fix) - INFO_LOG(CONSOLE, "JAC ucode chosen\n"); + INFO_LOG(CONSOLE, "JAC (early Zelda) ucode chosen\n"); return new CUCode_Jac(_rMailHandler); +// return new CUCode_Zelda(_rMailHandler, false); case 0x6CA33A6D: // DK Jungle Beat - case 0x86840740: // zelda - case 0x56d36052: // mario - case 0x2fcdf1ec: // mariokart, zelda 4 swords + case 0x86840740: // Zelda WW + case 0x56d36052: // Mario Sunshine + case 0x2fcdf1ec: // Mario Kart, zelda 4 swords INFO_LOG(CONSOLE, "Zelda ucode chosen\n"); return new CUCode_Zelda(_rMailHandler);