diff --git a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
index 89e9453269..00ffeb27e2 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
+++ b/Source/Plugins/Plugin_DSP_HLE/Plugin_DSP_HLE.vcproj
@@ -682,10 +682,26 @@
RelativePath=".\Src\UCodes\UCode_AX.h"
>
+
+
+
+
+
+
+
+
> 1);
- samplePos += 2;
- newSamplePos += 2;
- }
-
- int scale = 1 << (adpcm.pred_scale & 0xF);
- int coef_idx = adpcm.pred_scale >> 4;
-
- s32 coef1 = adpcm.coefs[coef_idx * 2 + 0];
- s32 coef2 = adpcm.coefs[coef_idx * 2 + 1];
-
- int temp = (samplePos & 1) ?
- (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) & 0xF) :
- (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) >> 4);
-
- if (temp >= 8)
- temp -= 16;
-
- // 0x400 = 0.5 in 11-bit fixed point
- int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11);
-
- if (val > 0x7FFF)
- val = 0x7FFF;
- else if (val < -0x7FFF)
- val = -0x7FFF;
-
- adpcm.yn2 = adpcm.yn1;
- adpcm.yn1 = val;
-
- samplePos++;
- }
-
- return adpcm.yn1;
-}
-
-void ADPCM_Loop(AXParamBlock& pb)
-{
- if (!pb.is_stream)
- {
- pb.adpcm.yn1 = pb.adpcm_loop_info.yn1;
- pb.adpcm.yn2 = pb.adpcm_loop_info.yn2;
- pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale;
- }
- //else stream and we should not attempt to replace values
-}
-
-
-// =======================================================================================
-// Volume control (ramping)
-// --------------
-u16 ADPCM_Vol(u16 vol, u16 delta, u16 mixer_control)
-{
- int x = vol;
- if (delta && delta < 0x5000)
- x += delta * 20 * 8; // unsure what the right step is
- else if (delta && delta > 0x5000)
- //x -= (0x10000 - delta); // this is to small, it's often 1
- x -= (0x10000 - delta) * 20 * 16; // if this was 20 * 8 the sounds in Fire Emblem and Paper Mario
- // did not have time to go to zero before the were closed
-
- // make lower limits
- if (x < 0) x = 0;
- //if (pb.mixer_control < 1000 && x < pb.mixer_control) x = pb.mixer_control; // does this make
- // any sense?
-
- // make upper limits
- //if (mixer_control > 1000 && x > mixer_control) x = mixer_control; // maybe mixer_control also
- // has a volume target?
- //if (x >= 0x7fff) x = 0x7fff; // this seems a little high
- if (x >= 0x4e20) x = 0x4e20; // add a definitive limit at 20 000
- return x; // update volume
-}
-// ==============
-
-void MixAddVoice(AXParamBlock &pb, int *templbuffer, int *temprbuffer, int _iSize)
-{
-#ifdef _WIN32
- ratioFactor = 32000.0f / (float)DSound::DSound_GetSampleRate();
-#else
- ratioFactor = 32000.0f / 44100.0f;
-#endif
-
// get necessary values
const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
@@ -260,159 +171,51 @@ void MixAddVoice(AXParamBlock &pb, int *templbuffer, int *temprbuffer, int _iSiz
pb.adpcm_loop_info.pred_scale = 0;
pb.adpcm_loop_info.yn1 = 0; pb.adpcm_loop_info.yn2 = 0;
}
- // =============
- if (pb.running)
+}
+
+int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num)
+{
+ int count = 0;
+ u32 blockAddr = pbs_address;
+
+ // reading and 'halfword' swap
+ for (int i = 0; i < _num; i++)
{
- // =======================================================================================
- // Set initial parameters
- // ------------
- //constants
- const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor);
-
- //variables
- u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo;
- u32 frac = pb.src.cur_addr_frac;
- // =============
-
- // =======================================================================================
- // Handle no-src streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0
- // and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This
- // makes samplePos update in the correct way. I'm unsure how we are actually supposed to
- // detect that this setting. Updates did not fix this automatically.
- // ---------------------------------------------------------------------------------------
- // Stream settings
- // src_type = 2 (most other games have src_type = 0)
- // ------------
- // Affected games:
- // Baten Kaitos - Eternal Wings (2003)
- // Baten Kaitos - Origins (2006)?
- // Soul Calibur 2: The movie music use src_type 2 but it needs no adjustment, perhaps
- // the sound format plays in to, Baten use ADPCM SC2 use PCM16
- // ------------
- if(pb.src_type == 2 && (pb.src.ratio_hi == 0 && pb.src.ratio_lo == 0))
+ const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
+ if (pSrc != NULL)
{
- pb.src.ratio_hi = 1;
- }
- // =============
-
-
- // =======================================================================================
- // Games that use looping to play non-looping music streams - SSBM has info in all
- // pb.adpcm_loop_info parameters but has pb.audio_addr.looping = 0. If we treat these streams
- // like any other looping streams the music works. I'm unsure how we are actually supposed to
- // detect that these kinds of blocks should be looping. It seems like pb.mixer_control == 0 may
- // identify these types of blocks. Updates did not write any looping values.
- // --------------
- if(
- (pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2)
- && pb.mixer_control == 0
- && gSSBM
- )
- {
- pb.audio_addr.looping = 1;
- }
- // ==============
-
- // =======================================================================================
- // Walk through _iSize. _iSize = numSamples. If the game goes slow _iSize will be higher to
- // compensate for that. _iSize can be as low as 100 or as high as 2000 some cases.
- for (int s = 0; s < _iSize; s++)
- {
- int sample = 0;
- frac += ratio;
- u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac
-
- // =======================================================================================
- // Process sample format
- // --------------
- switch (pb.audio_addr.sample_format)
+ short *pDest = (short *)&_pPBs[i];
+ for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
{
- case AUDIOFORMAT_PCM8:
- pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
- pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8;
-
- if (pb.src_type == SRCTYPE_NEAREST)
- {
- sample = pb.adpcm.yn1;
- }
- else //linear interpolation
- {
- sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
- }
-
- samplePos = newSamplePos;
- break;
-
- case AUDIOFORMAT_PCM16:
- pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
- pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1))));
- if (pb.src_type == SRCTYPE_NEAREST)
- sample = pb.adpcm.yn1;
- else //linear interpolation
- sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
-
- samplePos = newSamplePos;
- break;
-
- case AUDIOFORMAT_ADPCM:
- sample = ADPCM_Step(pb, samplePos, newSamplePos, frac);
- break;
-
- default:
- break;
+ pDest[p] = Common::swap16(pSrc[p]);
}
- // ================
-
- // =======================================================================================
- // Volume control
- frac &= 0xffff;
-
- int vol = pb.vol_env.cur_volume >> 9;
- sample = sample * vol >> 8;
-
- if (pb.mixer_control & MIXCONTROL_RAMPING)
- {
- int x = pb.vol_env.cur_volume;
- x += pb.vol_env.cur_volume_delta; // I'm not sure about this, can anybody find a game
- // that use this? Or how does it work?
- if (x < 0) x = 0;
- if (x >= 0x7fff) x = 0x7fff;
- pb.vol_env.cur_volume = x; // maybe not per sample?? :P
- }
-
- int leftmix = pb.mixer.volume_left >> 5;
- int rightmix = pb.mixer.volume_right >> 5;
- // ===============
- int left = sample * leftmix >> 8;
- int right = sample * rightmix >> 8;
- //adpcm has to walk from oldSamplePos to samplePos here
- templbuffer[s] += left;
- temprbuffer[s] += right;
-
- if (samplePos >= sampleEnd)
- {
- if (pb.audio_addr.looping == 1)
- {
- samplePos = loopPos;
- if (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM)
- ADPCM_Loop(pb);
- }
- else
- {
- pb.running = 0;
- break;
- }
- }
- } // end of the _iSize loop
- // ============
- if (gVolume) // allow us to turn this off in the debugger
- {
- pb.mixer.volume_left = ADPCM_Vol(pb.mixer.volume_left, pb.mixer.unknown, pb.mixer_control);
- pb.mixer.volume_right = ADPCM_Vol(pb.mixer.volume_right, pb.mixer.unknown2, pb.mixer_control);
+ blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
+ count++;
}
- pb.src.cur_addr_frac = (u16)frac;
- pb.audio_addr.cur_addr_hi = samplePos >> 16;
- pb.audio_addr.cur_addr_lo = (u16)samplePos;
+ else
+ break;
+ }
+
+ // return the number of read PBs
+ return count;
+}
+
+void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num)
+{
+ u32 blockAddr = pbs_address;
+
+ // write back and 'halfword'swap
+ for (int i = 0; i < _num; i++)
+ {
+ short* pSrc = (short*)&_pPBs[i];
+ short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr);
+ for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
+ {
+ pDest[p] = Common::swap16(pSrc[p]);
+ }
+
+ // next block
+ blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
}
}
@@ -421,7 +224,7 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
AXParamBlock PBs[NUMBER_OF_PBS];
// read out pbs
- int numberOfPBs = ReadOutPBs(1, PBs, NUMBER_OF_PBS);
+ int numberOfPBs = ReadOutPBs(m_addressPBs, PBs, NUMBER_OF_PBS);
if (_iSize > 1024 * 1024)
_iSize = 1024 * 1024;
@@ -435,6 +238,34 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
CUCode_AX::Logging(_pBuffer, _iSize, 0);
}
+ // ---------------------------------------------------------------------------------------
+ // Make the updates we are told to do
+ // This code is buggy, TODO - fix. If multiple updates in a ms, only does first.
+ // ------------
+ for (int i = 0; i < numberOfPBs; i++) {
+ u16 *pDest = (u16 *)&PBs[i];
+ u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates
+ u16 upd3 = pDest[37]; u16 upd4 = pDest[38];
+ u16 upd_hi = pDest[39]; // update addr
+ u16 upd_lo = pDest[40];
+ const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
+ const u16 updpar = Memory_Read_U16(updaddr);
+ const u16 upddata = Memory_Read_U16(updaddr + 2);
+ // some safety checks, I hope it's enough, how long does the memory go?
+ if(updaddr > 0x80000000 && updaddr < 0x82000000
+ && updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
+ // 0-3, those are important
+ && (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think
+ // but I don't know how or when
+ && gSequenced) // on and off option
+ {
+ pDest[updpar] = upddata;
+ }
+ }
+
+ //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
+ // ------------
+
for (int i = 0; i < numberOfPBs; i++)
{
AXParamBlock& pb = PBs[i];
@@ -442,7 +273,7 @@ void CUCode_AX::MixAdd(short* _pBuffer, int _iSize)
}
// write back out pbs
- WriteBackPBs(PBs, numberOfPBs);
+ WriteBackPBs(m_addressPBs, PBs, numberOfPBs);
for (int i = 0; i < _iSize; i++)
{
@@ -490,6 +321,8 @@ bool CUCode_AX::AXTask(u32& _uMail)
u32 Addr__12;
u32 Addr__4_1;
u32 Addr__4_2;
+ u32 Addr__4_3;
+ u32 Addr__4_4;
u32 Addr__5_1;
u32 Addr__5_2;
u32 Addr__6;
@@ -507,12 +340,10 @@ bool CUCode_AX::AXTask(u32& _uMail)
case AXLIST_STUDIOADDR: //00
Addr__AXStudio = Memory_Read_U32(uAddress);
uAddress += 4;
- if (wii_mode)
- uAddress += 6;
DebugLog("AXLIST studio address: %08x", Addr__AXStudio);
break;
- case 0x001:
+ case 0x001: // 2byte x 10
{
u32 address = Memory_Read_U32(uAddress);
uAddress += 4;
@@ -549,7 +380,7 @@ bool CUCode_AX::AXTask(u32& _uMail)
DebugLog("AXLIST command 0x0003 ????");
break;
- case 0x0004:
+ case 0x0004: // AUX?
Addr__4_1 = Memory_Read_U32(uAddress);
uAddress += 4;
Addr__4_2 = Memory_Read_U32(uAddress);
@@ -572,12 +403,8 @@ bool CUCode_AX::AXTask(u32& _uMail)
break;
case AXLIST_SBUFFER:
- // Hopefully this is where in main ram to write.
Addr__AXOutSBuffer = Memory_Read_U32(uAddress);
uAddress += 4;
- if (wii_mode) {
- uAddress += 12;
- }
DebugLog("AXLIST OutSBuffer address: %08x", Addr__AXOutSBuffer);
break;
@@ -590,10 +417,6 @@ bool CUCode_AX::AXTask(u32& _uMail)
case AXLIST_COMPRESSORTABLE: // 0xa
Addr__A = Memory_Read_U32(uAddress);
uAddress += 4;
- if (wii_mode) {
- // There's one more here.
-// uAddress += 4;
- }
DebugLog("AXLIST CompressorTable address: %08x", Addr__A);
break;
@@ -632,22 +455,7 @@ bool CUCode_AX::AXTask(u32& _uMail)
uAddress += 6 * 4; // 6 Addresses.
break;
- case 0x000d:
- if (wii_mode) {
- uAddress += 4 * 4; // 4 addresses. another aux?
- break;
- }
- // non-wii : fall through
-
- case 0x000b:
- if (wii_mode) {
- uAddress += 2; // one 0x8000 in rabbids
- uAddress += 4 * 2; // then two RAM addressses
- break;
- }
- // non-wii : fall through
-
- default:
+ default:
{
static bool bFirst = true;
if (bFirst == true)
@@ -665,8 +473,8 @@ bool CUCode_AX::AXTask(u32& _uMail)
}
// Wii AX will always show this
- //PanicAlert(szTemp);
- bFirst = false;
+ PanicAlert(szTemp);
+ // bFirst = false;
}
// unknown command so stop the execution of this TaskList
@@ -683,81 +491,3 @@ bool CUCode_AX::AXTask(u32& _uMail)
m_rMailHandler.PushMail(0xDCD10001);
return true;
}
-
-int CUCode_AX::ReadOutPBs(int a, AXParamBlock* _pPBs, int _num)
-{
- int count = 0;
- u32 blockAddr = m_addressPBs;
-
- // reading and 'halfword' swap
- for (int i = 0; i < _num; i++)
- {
- const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
- if (pSrc != NULL)
- {
- short *pDest = (short *)&_pPBs[i];
- for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
- {
- pDest[p] = Common::swap16(pSrc[p]);
-
- // To avoid a performance drop in the Release build I place this in the debug
- // build only
- #if defined(_DEBUG) || defined(DEBUGFAST)
- gLastBlock = blockAddr + p*2 + 2; // save last block location
- #endif
- }
- // ---------------------------------------------------------------------------------------
- // Make the updates we are told to do
- // ------------
- if(a) // only do this once every 5 ms
- {
- u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates
- u16 upd3 = pDest[37]; u16 upd4 = pDest[38];
- u16 upd_hi = pDest[39]; // update addr
- u16 upd_lo = pDest[40];
- const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
- const u16 updpar = Memory_Read_U16(updaddr);
- const u16 upddata = Memory_Read_U16(updaddr + 2);
- // some safety checks, I hope it's enough, how long does the memory go?
- if(updaddr > 0x80000000 && updaddr < 0x82000000
- && updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
- // 0-3, those are important
- && (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think
- // but I don't know how or when
- && gSequenced) // on and off option
- {
- pDest[updpar] = upddata;
- }
- }
- //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
- // ------------
-
- blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
- count++;
- }
- else
- break;
- }
-
- // return the number of read PBs
- return count;
-}
-
-void CUCode_AX::WriteBackPBs(AXParamBlock* _pPBs, int _num)
-{
- u32 blockAddr = m_addressPBs;
-
- // write back and 'halfword'swap
- for (int i = 0; i < _num; i++)
- {
- short* pSrc = (short*)&_pPBs[i];
- short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr);
- for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
- {
- pDest[p] = Common::swap16(pSrc[p]);
- }
-
- // next block
- blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
- }
-}
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.h
index 6614f8b034..8d10824462 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.h
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX.h
@@ -28,7 +28,7 @@ enum
class CUCode_AX : public IUCode
{
public:
- CUCode_AX(CMailHandler& _rMailHandler, bool wii = false);
+ CUCode_AX(CMailHandler& _rMailHandler);
virtual ~CUCode_AX();
void HandleMail(u32 _uMail);
@@ -55,14 +55,13 @@ private:
int *templbuffer;
int *temprbuffer;
- bool wii_mode;
-
// ax task message handler
bool AXTask(u32& _uMail);
-
void SendMail(u32 _uMail);
- int ReadOutPBs(int a, AXParamBlock *_pPBs, int _num);
- void WriteBackPBs(AXParamBlock *_pPBs, int _num);
};
+int ReadOutPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num);
+void WriteBackPBs(u32 pbs_address, AXParamBlock* _pPBs, int _num);
+
+
#endif // _UCODE_AX
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXStructs.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXStructs.h
index a2ca4b1d66..f1e24384c3 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXStructs.h
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXStructs.h
@@ -15,8 +15,8 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#ifndef UCODE_AX_STRUCTS
-#define UCODE_AX_STRUCTS
+#ifndef _UCODE_AX_STRUCTS_H
+#define _UCODE_AX_STRUCTS_H
struct PBMixer
{
@@ -203,5 +203,4 @@ enum {
MIXCONTROL_RAMPING = 8,
};
-
-#endif
+#endif // _UCODE_AX_STRUCTS_H
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp
new file mode 100644
index 0000000000..6ff90ee0c4
--- /dev/null
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.cpp
@@ -0,0 +1,396 @@
+// 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 "../Debugger/Debugger.h"
+#include "../Logging/Console.h" // for aprintf
+
+#ifdef _WIN32
+#include "../PCHW/DSoundStream.h"
+#endif
+#include "../PCHW/Mixer.h"
+#include "../MailHandler.h"
+
+#include "UCodes.h"
+#include "UCode_AXStructs.h"
+#include "UCode_AXWii.h"
+#include "UCode_AX_Voice.h"
+
+CUCode_AXWii::CUCode_AXWii(CMailHandler& _rMailHandler)
+ : IUCode(_rMailHandler)
+ , m_addressPBs(0xFFFFFFFF)
+{
+ // we got loaded
+ m_rMailHandler.PushMail(0xDCD10000);
+ m_rMailHandler.PushMail(0x80000000); // handshake ??? only (crc == 0xe2136399) needs it ...
+
+ templbuffer = new int[1024 * 1024];
+ temprbuffer = new int[1024 * 1024];
+}
+
+CUCode_AXWii::~CUCode_AXWii()
+{
+ m_rMailHandler.Clear();
+ delete [] templbuffer;
+ delete [] temprbuffer;
+}
+
+void CUCode_AXWii::HandleMail(u32 _uMail)
+{
+ if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
+ {
+ // a new List
+ }
+ else
+ {
+ AXTask(_uMail);
+ }
+}
+
+int ReadOutPBsWii(u32 pbs_address, AXParamBlockWii* _pPBs, int _num)
+{
+ int count = 0;
+ u32 blockAddr = pbs_address;
+
+ // reading and 'halfword' swap
+ for (int i = 0; i < _num; i++)
+ {
+ const short *pSrc = (const short *)g_dspInitialize.pGetMemoryPointer(blockAddr);
+ if (pSrc != NULL)
+ {
+ short *pDest = (short *)&_pPBs[i];
+ for (size_t p = 0; p < sizeof(AXParamBlock) / 2; p++)
+ {
+ pDest[p] = Common::swap16(pSrc[p]);
+ }
+ blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
+ count++;
+ }
+ else
+ break;
+ }
+
+ // return the number of read PBs
+ return count;
+}
+
+void WriteBackPBsWii(u32 pbs_address, AXParamBlockWii* _pPBs, int _num)
+{
+ u32 blockAddr = pbs_address;
+
+ // write back and 'halfword'swap
+ for (int i = 0; i < _num; i++)
+ {
+ short* pSrc = (short*)&_pPBs[i];
+ short* pDest = (short*)g_dspInitialize.pGetMemoryPointer(blockAddr);
+ for (size_t p = 0; p < sizeof(AXParamBlockWii) / 2; p++)
+ {
+ pDest[p] = Common::swap16(pSrc[p]);
+ }
+
+ // next block
+ blockAddr = (_pPBs[i].next_pb_hi << 16) | _pPBs[i].next_pb_lo;
+ }
+}
+
+void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
+{
+ AXParamBlockWii PBs[NUMBER_OF_PBS];
+
+ // read out pbs
+ int numberOfPBs = ReadOutPBsWii(m_addressPBs, PBs, NUMBER_OF_PBS);
+
+ if (_iSize > 1024 * 1024)
+ _iSize = 1024 * 1024;
+
+ memset(templbuffer, 0, _iSize * sizeof(int));
+ memset(temprbuffer, 0, _iSize * sizeof(int));
+
+ // write logging data to debugger
+ //if (m_frame)
+ {
+// CUCode_AXWii::Logging(_pBuffer, _iSize, 0);
+ }
+
+ // ---------------------------------------------------------------------------------------
+ // Make the updates we are told to do
+ // This code is buggy, TODO - fix. If multiple updates in a ms, only does first.
+ // ------------
+ /*
+ for (int i = 0; i < numberOfPBs; i++) {
+ u16 *pDest = (u16 *)&PBs[i];
+ u16 upd0 = pDest[34]; u16 upd1 = pDest[35]; u16 upd2 = pDest[36]; // num_updates
+ u16 upd_hi = pDest[39]; // update addr
+ u16 upd_lo = pDest[40];
+ const u32 updaddr = (u32)(upd_hi << 16) | upd_lo;
+ const u16 updpar = Memory_Read_U16(updaddr);
+ const u16 upddata = Memory_Read_U16(updaddr + 2);
+ // some safety checks, I hope it's enough, how long does the memory go?
+ if(updaddr > 0x80000000 && updaddr < 0x82000000
+ && updpar < 63 && updpar > 3 && upddata >= 0 // updpar > 3 because we don't want to change
+ // 0-3, those are important
+ && (upd0 || upd1 || upd2 || upd3 || upd4) // We should use these in some way to I think
+ // but I don't know how or when
+ && gSequenced) // on and off option
+ {
+ pDest[updpar] = upddata;
+ }
+ }*/
+
+ //aprintf(1, "%08x %04x %04x\n", updaddr, updpar, upddata);
+ // ------------
+
+ for (int i = 0; i < numberOfPBs; i++)
+ {
+ AXParamBlockWii& pb = PBs[i];
+ MixAddVoice(pb, templbuffer, temprbuffer, _iSize);
+ }
+
+ // write back out pbs
+ WriteBackPBsWii(m_addressPBs, PBs, numberOfPBs);
+
+ for (int i = 0; i < _iSize; i++)
+ {
+ // Clamp into 16-bit. Maybe we should add a volume compressor here.
+ int left = templbuffer[i] + _pBuffer[0];
+ int right = temprbuffer[i] + _pBuffer[1];
+ if (left < -32767) left = -32767;
+ if (left > 32767) left = 32767;
+ if (right < -32767) right = -32767;
+ if (right > 32767) right = 32767;
+ *_pBuffer++ = left;
+ *_pBuffer++ = right;
+ }
+
+ // write logging data to debugger again after the update
+ //if (m_frame)
+ {
+// CUCode_AXWii::Logging(_pBuffer, _iSize, 1);
+ }
+}
+
+
+void CUCode_AXWii::Update()
+{
+ // check if we have to sent something
+ if (!m_rMailHandler.IsEmpty())
+ {
+ g_dspInitialize.pGenerateDSPInterrupt();
+ }
+}
+
+// AX seems to bootup one task only and waits for resume-callbacks
+// everytime the DSP has "spare time" it sends a resume-mail to the CPU
+// and the __DSPHandler calls a AX-Callback which generates a new AXFrame
+bool CUCode_AXWii::AXTask(u32& _uMail)
+{
+ u32 uAddress = _uMail;
+ DebugLog("AXTask - AXCommandList-Addr: 0x%08x", uAddress);
+
+ u32 Addr__AXStudio;
+ u32 Addr__AXOutSBuffer;
+ u32 Addr__AXOutSBuffer_1;
+ u32 Addr__AXOutSBuffer_2;
+ u32 Addr__A;
+ u32 Addr__12;
+ u32 Addr__4_1;
+ u32 Addr__4_2;
+ u32 Addr__4_3;
+ u32 Addr__4_4;
+ u32 Addr__5_1;
+ u32 Addr__5_2;
+ u32 Addr__6;
+ u32 Addr__9;
+
+ bool bExecuteList = true;
+
+ if (true)
+ {
+ // PanicAlert("%i", sizeof(AXParamBlockWii)); // 252 ??
+ FILE *f = fopen("D:\\axdump.txt", "a");
+ if (!f)
+ f = fopen("D:\\axdump.txt", "w");
+
+ u32 addr = uAddress;
+ for (int i = 0; i < 100; i++) {
+ fprintf(f, "%02x\n", Memory_Read_U16(addr + i * 2));
+ }
+ fprintf(f, "===========------------------------------------------------=\n");
+ fclose(f);
+ }
+ else
+ {
+ // PanicAlert("%i", sizeof(AXParamBlock)); // 192
+ }
+
+ while (bExecuteList)
+ {
+ static int last_valid_command = 0;
+ u16 iCommand = Memory_Read_U16(uAddress);
+ uAddress += 2;
+ switch (iCommand)
+ {
+ case 0x0000: //00
+ Addr__AXStudio = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ DebugLog("AXLIST studio address: %08x", Addr__AXStudio);
+ break;
+
+ case 0x0001:
+ {
+ u32 address = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ DebugLog("AXLIST 1: %08x", address);
+ }
+ break;
+
+ //
+ // Somewhere we should be getting a bitmask of AX_SYNC values
+ // that tells us what has been updated
+ // Dunno if important
+ //
+ case 0x0002: //02
+ {
+ m_addressPBs = Memory_Read_U32(uAddress);
+ uAddress += 4;
+
+ mixer_HLEready = true;
+ DebugLog("AXLIST PB address: %08x", m_addressPBs);
+#ifdef _WIN32
+ DebugLog("Update the SoundThread to be in sync");
+ DSound::DSound_UpdateSound(); //do it in this thread to avoid sync problems
+#endif
+ }
+ break;
+
+ case 0x0003:
+ DebugLog("AXLIST command 0x0003 ????");
+ break;
+
+ case 0x0004: // AUX?
+ Addr__4_1 = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ DebugLog("AXLIST 4 address: %08x", Addr__4_1);
+ break;
+
+ case 0x0005:
+ Addr__5_1 = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ Addr__5_2 = Memory_Read_U32(uAddress);
+ uAddress += 4;
+
+ uAddress += 2;
+ DebugLog("AXLIST 5_1 5_2 addresses: %08x %08x", Addr__5_1, Addr__5_2);
+ break;
+
+ case 0x0006:
+ Addr__6 = Memory_Read_U32(uAddress);
+ uAddress += 10;
+ DebugLog("AXLIST 6 address: %08x", Addr__6);
+ break;
+
+ case 0x0007: // AXLIST_SBUFFER
+ Addr__AXOutSBuffer = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ // uAddress += 12;
+ DebugLog("AXLIST OutSBuffer address: %08x", Addr__AXOutSBuffer);
+ break;
+
+ case 0x0009:
+ Addr__9 = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ DebugLog("AXLIST 6 address: %08x", Addr__9);
+ break;
+
+ case 0x000a: // AXLIST_COMPRESSORTABLE
+ Addr__A = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ //Addr__A = Memory_Read_U32(uAddress);
+ uAddress += 4;
+ DebugLog("AXLIST CompressorTable address: %08x", Addr__A);
+ break;
+
+ case 0x000b:
+ uAddress += 2; // one 0x8000 in rabbids
+ uAddress += 4 * 2; // then two RAM addressses
+ break;
+
+ case 0x000d:
+ uAddress += 4 * 4;
+ break;
+
+ case 0x000e:
+ // This is the end.
+ bExecuteList = false;
+ DebugLog("AXLIST end, wii stylee.");
+ break;
+
+ case 0x0010: //Super Monkey Ball 2
+ DebugLog("AXLIST unknown");
+ //should probably read/skip stuff here
+ uAddress += 8;
+ break;
+
+ case 0x0011:
+ uAddress += 4;
+ break;
+
+ case 0x0012:
+ Addr__12 = Memory_Read_U16(uAddress);
+ uAddress += 2;
+ break;
+
+ case 0x0013:
+ uAddress += 6 * 4; // 6 Addresses.
+ break;
+
+
+ default:
+ {
+ static bool bFirst = true;
+ if (bFirst == true)
+ {
+ char szTemp[2048];
+ sprintf(szTemp, "Unknown AX-Command 0x%x (address: 0x%08x). Last valid: %02x\n",
+ iCommand, uAddress - 2, last_valid_command);
+ int num = -32;
+ while (num < 64+32)
+ {
+ char szTemp2[128] = "";
+ sprintf(szTemp2, "%s0x%04x\n", num == 0 ? ">>" : " ", Memory_Read_U16(uAddress + num));
+ strcat(szTemp, szTemp2);
+ num += 2;
+ }
+
+ // Wii AX will always show this
+ PanicAlert(szTemp);
+ // bFirst = false;
+ }
+
+ // unknown command so stop the execution of this TaskList
+ bExecuteList = false;
+ }
+ break;
+ }
+ if (bExecuteList)
+ last_valid_command = iCommand;
+ }
+ DebugLog("AXTask - done, send resume");
+
+ // i hope resume is okay AX
+ m_rMailHandler.PushMail(0xDCD10001);
+ return true;
+}
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.h
new file mode 100644
index 0000000000..7445e68ed8
--- /dev/null
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AXWii.h
@@ -0,0 +1,58 @@
+// 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/
+
+#ifndef _UCODE_AXWII
+#define _UCODE_AXWII
+
+#include "UCode_AXStructs.h"
+
+#define NUMBER_OF_PBS 64
+
+class CUCode_AXWii : public IUCode
+{
+public:
+ CUCode_AXWii(CMailHandler& _rMailHandler);
+ virtual ~CUCode_AXWii();
+
+ void HandleMail(u32 _uMail);
+ void MixAdd(short* _pBuffer, int _iSize);
+ void Update();
+
+ // this is a little ugly perhaps, feel free to move it out of here
+ void Logging(short* _pBuffer, int _iSize, int a);
+
+private:
+ enum
+ {
+ MAIL_AX_ALIST = 0xBABE0000,
+ };
+
+ // PBs
+ u32 m_addressPBs;
+
+ int *templbuffer;
+ int *temprbuffer;
+
+ // ax task message handler
+ bool AXTask(u32& _uMail);
+ void SendMail(u32 _uMail);
+};
+
+int ReadOutPBsWii(u32 pbs_address, AXParamBlockWii* _pPBs, int _num);
+void WriteBackPBsWii(u32 pbs_address, AXParamBlockWii* _pPBs, int _num);
+
+#endif // _UCODE_AXWII
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h
new file mode 100644
index 0000000000..ab69842595
--- /dev/null
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_ADPCM.h
@@ -0,0 +1,89 @@
+// 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/
+
+#ifndef _UCODE_AX_ADPCM_H
+#define _UCODE_AX_ADPCM_H
+
+inline s16 ADPCM_Step(PBADPCMInfo &adpcm, u32& samplePos, u32 newSamplePos, u16 frac)
+{
+ while (samplePos < newSamplePos)
+ {
+ if ((samplePos & 15) == 0)
+ {
+ adpcm.pred_scale = g_dspInitialize.pARAM_Read_U8((samplePos & ~15) >> 1);
+ samplePos += 2;
+ newSamplePos += 2;
+ }
+
+ int scale = 1 << (adpcm.pred_scale & 0xF);
+ int coef_idx = adpcm.pred_scale >> 4;
+
+ s32 coef1 = adpcm.coefs[coef_idx * 2 + 0];
+ s32 coef2 = adpcm.coefs[coef_idx * 2 + 1];
+
+ int temp = (samplePos & 1) ?
+ (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) & 0xF) :
+ (g_dspInitialize.pARAM_Read_U8(samplePos >> 1) >> 4);
+
+ if (temp >= 8)
+ temp -= 16;
+
+ // 0x400 = 0.5 in 11-bit fixed point
+ int val = (scale * temp) + ((0x400 + coef1 * adpcm.yn1 + coef2 * adpcm.yn2) >> 11);
+
+ if (val > 0x7FFF)
+ val = 0x7FFF;
+ else if (val < -0x7FFF)
+ val = -0x7FFF;
+
+ adpcm.yn2 = adpcm.yn1;
+ adpcm.yn1 = val;
+
+ samplePos++;
+ }
+
+ return adpcm.yn1;
+}
+
+// =======================================================================================
+// Volume control (ramping)
+// --------------
+inline u16 ADPCM_Vol(u16 vol, u16 delta, u16 mixer_control)
+{
+ int x = vol;
+ if (delta && delta < 0x5000)
+ x += delta * 20 * 8; // unsure what the right step is
+ else if (delta && delta > 0x5000)
+ //x -= (0x10000 - delta); // this is to small, it's often 1
+ x -= (0x10000 - delta) * 20 * 16; // if this was 20 * 8 the sounds in Fire Emblem and Paper Mario
+ // did not have time to go to zero before the were closed
+
+ // make lower limits
+ if (x < 0) x = 0;
+ //if (pb.mixer_control < 1000 && x < pb.mixer_control) x = pb.mixer_control; // does this make
+ // any sense?
+
+ // make upper limits
+ //if (mixer_control > 1000 && x > mixer_control) x = mixer_control; // maybe mixer_control also
+ // has a volume target?
+ //if (x >= 0x7fff) x = 0x7fff; // this seems a little high
+ if (x >= 0x4e20) x = 0x4e20; // add a definitive limit at 20 000
+ return x; // update volume
+}
+// ==============
+
+#endif // _UCODE_AX_ADPCM_H
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h
new file mode 100644
index 0000000000..1362ea9635
--- /dev/null
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCode_AX_Voice.h
@@ -0,0 +1,196 @@
+// 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/
+
+#ifndef _UCODE_AX_VOICE_H
+#define _UCODE_AX_VOICE_H
+
+#include "UCode_AX_ADPCM.h"
+
+
+template
+inline void MixAddVoice(ParamBlockType &pb, int *templbuffer, int *temprbuffer, int _iSize)
+{
+#ifdef _WIN32
+ float ratioFactor = 32000.0f / (float)DSound::DSound_GetSampleRate();
+#else
+ float ratioFactor = 32000.0f / 44100.0f;
+#endif
+
+ // DoVoiceHacks(pb);
+
+ // =============
+ if (pb.running)
+ {
+ // =======================================================================================
+ // Read initial parameters
+ // ------------
+ //constants
+ const u32 ratio = (u32)(((pb.src.ratio_hi << 16) + pb.src.ratio_lo) * ratioFactor);
+ const u32 sampleEnd = (pb.audio_addr.end_addr_hi << 16) | pb.audio_addr.end_addr_lo;
+ const u32 loopPos = (pb.audio_addr.loop_addr_hi << 16) | pb.audio_addr.loop_addr_lo;
+
+ //variables
+ u32 samplePos = (pb.audio_addr.cur_addr_hi << 16) | pb.audio_addr.cur_addr_lo;
+ u32 frac = pb.src.cur_addr_frac;
+ // =============
+
+ // =======================================================================================
+ // Handle no-src streams - No src streams have pb.src_type == 2 and have pb.src.ratio_hi = 0
+ // and pb.src.ratio_lo = 0. We handle that by setting the sampling ratio integer to 1. This
+ // makes samplePos update in the correct way. I'm unsure how we are actually supposed to
+ // detect that this setting. Updates did not fix this automatically.
+ // ---------------------------------------------------------------------------------------
+ // Stream settings
+ // src_type = 2 (most other games have src_type = 0)
+ // ------------
+ // Affected games:
+ // Baten Kaitos - Eternal Wings (2003)
+ // Baten Kaitos - Origins (2006)?
+ // Soul Calibur 2: The movie music use src_type 2 but it needs no adjustment, perhaps
+ // the sound format plays in to, Baten use ADPCM SC2 use PCM16
+ // ------------
+ if (pb.src_type == 2 && (pb.src.ratio_hi == 0 && pb.src.ratio_lo == 0))
+ {
+ pb.src.ratio_hi = 1;
+ }
+ // =============
+
+ // =======================================================================================
+ // Games that use looping to play non-looping music streams - SSBM has info in all
+ // pb.adpcm_loop_info parameters but has pb.audio_addr.looping = 0. If we treat these streams
+ // like any other looping streams the music works. I'm unsure how we are actually supposed to
+ // detect that these kinds of blocks should be looping. It seems like pb.mixer_control == 0 may
+ // identify these types of blocks. Updates did not write any looping values.
+ // --------------
+ if (
+ (pb.adpcm_loop_info.pred_scale || pb.adpcm_loop_info.yn1 || pb.adpcm_loop_info.yn2)
+ && pb.mixer_control == 0
+
+ )
+ {
+ pb.audio_addr.looping = 1;
+ }
+ // ==============
+
+ // =======================================================================================
+ // Walk through _iSize. _iSize = numSamples. If the game goes slow _iSize will be higher to
+ // compensate for that. _iSize can be as low as 100 or as high as 2000 some cases.
+ for (int s = 0; s < _iSize; s++)
+ {
+ int sample = 0;
+ frac += ratio;
+ u32 newSamplePos = samplePos + (frac >> 16); //whole number of frac
+
+ // =======================================================================================
+ // Process sample format
+ // --------------
+ switch (pb.audio_addr.sample_format)
+ {
+ case AUDIOFORMAT_PCM8:
+ // TODO - the linear interpolation code below is somewhat suspicious
+ pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
+ pb.adpcm.yn1 = ((s8)g_dspInitialize.pARAM_Read_U8(samplePos)) << 8;
+
+ if (pb.src_type == SRCTYPE_NEAREST)
+ {
+ sample = pb.adpcm.yn1;
+ }
+ else //linear interpolation
+ {
+ sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
+ }
+
+ samplePos = newSamplePos;
+ break;
+
+ case AUDIOFORMAT_PCM16:
+ // TODO - the linear interpolation code below is somewhat suspicious
+ pb.adpcm.yn2 = pb.adpcm.yn1; //save last sample
+ pb.adpcm.yn1 = (s16)(u16)((g_dspInitialize.pARAM_Read_U8(samplePos * 2) << 8) | (g_dspInitialize.pARAM_Read_U8((samplePos * 2 + 1))));
+ if (pb.src_type == SRCTYPE_NEAREST)
+ sample = pb.adpcm.yn1;
+ else //linear interpolation
+ sample = (pb.adpcm.yn1 * (u16)frac + pb.adpcm.yn2 * (u16)(0xFFFF - frac)) >> 16;
+
+ samplePos = newSamplePos;
+ break;
+
+ case AUDIOFORMAT_ADPCM:
+ sample = ADPCM_Step(pb.adpcm, samplePos, newSamplePos, frac);
+ break;
+
+ default:
+ break;
+ }
+ // ================
+
+ // =======================================================================================
+ // Volume control
+ frac &= 0xffff;
+
+ int vol = pb.vol_env.cur_volume >> 9;
+ sample = sample * vol >> 8;
+
+ if (pb.mixer_control & MIXCONTROL_RAMPING)
+ {
+ int x = pb.vol_env.cur_volume;
+ x += pb.vol_env.cur_volume_delta; // I'm not sure about this, can anybody find a game
+ // that use this? Or how does it work?
+ if (x < 0) x = 0;
+ if (x >= 0x7fff) x = 0x7fff;
+ pb.vol_env.cur_volume = x; // maybe not per sample?? :P
+ }
+
+ int leftmix = pb.mixer.volume_left >> 5;
+ int rightmix = pb.mixer.volume_right >> 5;
+ // ===============
+ int left = sample * leftmix >> 8;
+ int right = sample * rightmix >> 8;
+ //adpcm has to walk from oldSamplePos to samplePos here
+ templbuffer[s] += left;
+ temprbuffer[s] += right;
+
+ if (samplePos >= sampleEnd)
+ {
+ if (pb.audio_addr.looping == 1)
+ {
+ samplePos = loopPos;
+ if (pb.audio_addr.sample_format == AUDIOFORMAT_ADPCM)
+ {
+ if (!pb.is_stream)
+ {
+ pb.adpcm.yn1 = pb.adpcm_loop_info.yn1;
+ pb.adpcm.yn2 = pb.adpcm_loop_info.yn2;
+ pb.adpcm.pred_scale = pb.adpcm_loop_info.pred_scale;
+ }
+ }
+ }
+ else
+ {
+ pb.running = 0;
+ break;
+ }
+ }
+ } // end of the _iSize loop
+
+ pb.src.cur_addr_frac = (u16)frac;
+ pb.audio_addr.cur_addr_hi = samplePos >> 16;
+ pb.audio_addr.cur_addr_lo = (u16)samplePos;
+ }
+}
+
+#endif // _UCODE_AX_VOICE_H
diff --git a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
index 6079db9438..2016e1bca8 100644
--- a/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
+++ b/Source/Plugins/Plugin_DSP_HLE/Src/UCodes/UCodes.cpp
@@ -20,6 +20,7 @@
#include "UCodes.h"
#include "UCode_AX.h"
+#include "UCode_AXWii.h"
#include "UCode_Zelda.h"
#include "UCode_Jac.h"
#include "UCode_ROM.h"
@@ -72,8 +73,8 @@ IUCode* UCodeFactory(u32 _CRC, CMailHandler& _rMailHandler)
return new CUCode_Zelda(_rMailHandler);
case 0x347112ba: // raving rabbits
- DebugLog("Wii - AX chosen");
- return new CUCode_AX(_rMailHandler, true);
+ DebugLog("Wii - AXWii chosen");
+ return new CUCode_AXWii(_rMailHandler);
default:
PanicAlert("Unknown ucode (CRC = %08x) - forcing AX", _CRC);