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);