summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorPierre Bourdon <delroth@gmail.com>2012-11-20 03:13:55 +0100
committerPierre Bourdon <delroth@gmail.com>2012-11-20 03:13:55 +0100
commit954c55e35afbb1191f97e6da2f2b05be3696e2c4 (patch)
tree96c2a767c1032328462f7d1b8e612ef69618afc7 /Source/Core
parente750bed2a996bfe13cc4f33656f967209b94c5c5 (diff)
New AXWii now working properly in some games I tested
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp61
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h104
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp423
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h62
-rw-r--r--Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h74
5 files changed, 414 insertions, 310 deletions
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
index 8c2e05dce4..54bd50830d 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.cpp
@@ -16,9 +16,11 @@
// http://code.google.com/p/dolphin-emu/
#include "UCode_AX.h"
-#include "UCode_AX_Voice.h"
#include "../../DSP.h"
+#define AX_GC
+#include "UCode_AX_Voice.h"
+
CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
: IUCode(dsp_hle, crc)
, m_cmdlist_size(0)
@@ -123,7 +125,7 @@ void CUCode_AX::HandleCommandList()
addr_lo = m_cmdlist[curr_idx++];
addr2_hi = m_cmdlist[curr_idx++];
addr2_lo = m_cmdlist[curr_idx++];
- MixAUXSamples(cmd == CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2));
+ MixAUXSamples(cmd - CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2));
break;
case CMD_UPLOAD_LRS:
@@ -327,40 +329,41 @@ void CUCode_AX::ProcessPBList(u32 pb_addr)
}
}
-void CUCode_AX::MixAUXSamples(bool AUXA, u32 write_addr, u32 read_addr)
+void CUCode_AX::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr)
{
- int buffers[3][5 * 32];
+ int temp[3][5 * 32];
+ int* buffers[3] = { 0 };
+
+ switch (aux_id)
+ {
+ case 0:
+ buffers[0] = m_samples_auxA_left;
+ buffers[1] = m_samples_auxA_right;
+ buffers[2] = m_samples_auxA_surround;
+ break;
+
+ case 1:
+ buffers[0] = m_samples_auxB_left;
+ buffers[1] = m_samples_auxB_right;
+ buffers[2] = m_samples_auxB_surround;
+ break;
+ }
// First, we need to send the contents of our AUX buffers to the CPU.
if (write_addr)
{
- for (u32 i = 0; i < 5 * 32; ++i)
- {
- if (AUXA)
- {
- buffers[0][i] = Common::swap32(m_samples_auxA_left[i]);
- buffers[1][i] = Common::swap32(m_samples_auxA_right[i]);
- buffers[2][i] = Common::swap32(m_samples_auxA_surround[i]);
- }
- else
- {
- buffers[0][i] = Common::swap32(m_samples_auxB_left[i]);
- buffers[1][i] = Common::swap32(m_samples_auxB_right[i]);
- buffers[2][i] = Common::swap32(m_samples_auxB_surround[i]);
- }
- }
- memcpy(HLEMemory_Get_Pointer(write_addr), buffers, sizeof (buffers));
+ for (u32 i = 0; i < 3 * 32; ++i)
+ for (u32 j = 0; j < 3; ++j)
+ temp[j][i] = Common::swap32(buffers[j][i]);
+ memcpy(HLEMemory_Get_Pointer(write_addr), temp, sizeof (temp));
}
- // Then, we read the new buffers from the CPU and add to our current
- // buffers.
- memcpy(buffers, HLEMemory_Get_Pointer(read_addr), sizeof (buffers));
+ // Then, we read the new temp from the CPU and add to our current
+ // temp.
+ memcpy(temp, HLEMemory_Get_Pointer(read_addr), sizeof (temp));
for (u32 i = 0; i < 5 * 32; ++i)
- {
- m_samples_left[i] += Common::swap32(buffers[0][i]);
- m_samples_right[i] += Common::swap32(buffers[1][i]);
- m_samples_surround[i] += Common::swap32(buffers[2][i]);
- }
+ for (u32 j = 0; j < 3; ++j)
+ buffers[j][i] += Common::swap32(temp[j][i]);
}
void CUCode_AX::UploadLRS(u32 dst_addr)
@@ -495,5 +498,7 @@ void CUCode_AX::DoState(PointerWrap& p)
{
std::lock_guard<std::mutex> lk(m_processing);
+ // TODO
+
DoStateShared(p);
}
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h
index 29509661ed..23bc786111 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX.h
@@ -29,7 +29,40 @@
#include "UCodes.h"
#include "UCode_AXStructs.h"
-#include "UCode_AX_Voice.h"
+
+// We can't directly use the mixer_control field from the PB because it does
+// not mean the same in all AX versions. The AX UCode converts the
+// mixer_control value to an AXMixControl bitfield.
+enum AXMixControl
+{
+ MIX_L = 0x000001,
+ MIX_L_RAMP = 0x000002,
+ MIX_R = 0x000004,
+ MIX_R_RAMP = 0x000008,
+ MIX_S = 0x000010,
+ MIX_S_RAMP = 0x000020,
+
+ MIX_AUXA_L = 0x000040,
+ MIX_AUXA_L_RAMP = 0x000080,
+ MIX_AUXA_R = 0x000100,
+ MIX_AUXA_R_RAMP = 0x000200,
+ MIX_AUXA_S = 0x000400,
+ MIX_AUXA_S_RAMP = 0x000800,
+
+ MIX_AUXB_L = 0x001000,
+ MIX_AUXB_L_RAMP = 0x002000,
+ MIX_AUXB_R = 0x004000,
+ MIX_AUXB_R_RAMP = 0x008000,
+ MIX_AUXB_S = 0x010000,
+ MIX_AUXB_S_RAMP = 0x020000,
+
+ MIX_AUXC_L = 0x040000,
+ MIX_AUXC_L_RAMP = 0x080000,
+ MIX_AUXC_R = 0x100000,
+ MIX_AUXC_R_RAMP = 0x200000,
+ MIX_AUXC_S = 0x400000,
+ MIX_AUXC_S_RAMP = 0x800000
+};
class CUCode_AX : public IUCode
{
@@ -37,16 +70,16 @@ public:
CUCode_AX(DSPHLE* dsp_hle, u32 crc);
virtual ~CUCode_AX();
- void HandleMail(u32 mail);
- void MixAdd(short* out_buffer, int nsamples);
- void Update(int cycles);
- void DoState(PointerWrap& p);
+ virtual void HandleMail(u32 mail);
+ virtual void MixAdd(short* out_buffer, int nsamples);
+ virtual void Update(int cycles);
+ virtual void DoState(PointerWrap& p);
// Needed because StdThread.h std::thread implem does not support member
// pointers.
static void SpawnAXThread(CUCode_AX* self);
-private:
+protected:
enum MailType
{
MAIL_RESUME = 0xCDD10000,
@@ -59,31 +92,7 @@ private:
MAIL_CMDLIST_MASK = 0xFFFF0000
};
- enum CmdType
- {
- CMD_SETUP = 0x00,
- CMD_UNK_01 = 0x01,
- CMD_PB_ADDR = 0x02,
- CMD_PROCESS = 0x03,
- CMD_MIX_AUXA = 0x04,
- CMD_MIX_AUXB = 0x05,
- CMD_UPLOAD_LRS = 0x06,
- CMD_SBUFFER_ADDR = 0x07,
- CMD_UNK_08 = 0x08,
- CMD_MIX_AUXB_NOWRITE = 0x09,
- CMD_COMPRESSOR_TABLE_ADDR = 0x0A,
- CMD_UNK_0B = 0x0B,
- CMD_UNK_0C = 0x0C,
- CMD_MORE = 0x0D,
- CMD_OUTPUT = 0x0E,
- CMD_END = 0x0F,
- CMD_UNK_10 = 0x10,
- CMD_UNK_11 = 0x11,
- CMD_UNK_12 = 0x12,
- CMD_UNK_13 = 0x13,
- };
-
- // 32 * 5 because 32 samples per millisecond, for 5 milliseconds.
+ // 32 * 5 because 32 samples per millisecond, for max 5 milliseconds.
int m_samples_left[32 * 5];
int m_samples_right[32 * 5];
int m_samples_surround[32 * 5];
@@ -119,12 +128,39 @@ private:
void NotifyAXThread();
void AXThread();
- void HandleCommandList();
- void SetupProcessing(u32 studio_addr);
+
+ virtual void HandleCommandList();
+
+ void SetupProcessing(u32 init_addr);
void ProcessPBList(u32 pb_addr);
- void MixAUXSamples(bool AUXA, u32 write_addr, u32 read_addr);
+ void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr);
void UploadLRS(u32 dst_addr);
void OutputSamples(u32 out_addr);
+
+private:
+ enum CmdType
+ {
+ CMD_SETUP = 0x00,
+ CMD_UNK_01 = 0x01,
+ CMD_PB_ADDR = 0x02,
+ CMD_PROCESS = 0x03,
+ CMD_MIX_AUXA = 0x04,
+ CMD_MIX_AUXB = 0x05,
+ CMD_UPLOAD_LRS = 0x06,
+ CMD_SBUFFER_ADDR = 0x07,
+ CMD_UNK_08 = 0x08,
+ CMD_MIX_AUXB_NOWRITE = 0x09,
+ CMD_COMPRESSOR_TABLE_ADDR = 0x0A,
+ CMD_UNK_0B = 0x0B,
+ CMD_UNK_0C = 0x0C,
+ CMD_MORE = 0x0D,
+ CMD_OUTPUT = 0x0E,
+ CMD_END = 0x0F,
+ CMD_UNK_10 = 0x10,
+ CMD_UNK_11 = 0x11,
+ CMD_UNK_12 = 0x12,
+ CMD_UNK_13 = 0x13,
+ };
};
#endif // !_UCODE_AX_H
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
index 73abc392df..a47d9b279b 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.cpp
@@ -23,249 +23,294 @@
#include "UCodes.h"
#include "UCode_AXStructs.h"
#include "UCode_AXWii.h"
+
+#define AX_WII
#include "UCode_AX_Voice.h"
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
- : IUCode(dsp_hle, l_CRC)
- , m_addressPBs(0xFFFFFFFF)
+ : CUCode_AX(dsp_hle, l_CRC)
{
- // we got loaded
- m_rMailHandler.PushMail(DSP_INIT);
-
- templbuffer = new int[1024 * 1024];
- temprbuffer = new int[1024 * 1024];
-
- wiisportsHack = m_CRC == 0xfa450138;
+ WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
}
CUCode_AXWii::~CUCode_AXWii()
{
- m_rMailHandler.Clear();
- delete [] templbuffer;
- delete [] temprbuffer;
}
-void CUCode_AXWii::HandleMail(u32 _uMail)
+void CUCode_AXWii::HandleCommandList()
{
- if (m_UploadSetupInProgress)
- {
- PrepareBootUCode(_uMail);
- return;
- }
- else if ((_uMail & 0xFFFF0000) == MAIL_AX_ALIST)
- {
- // We are expected to get a new CmdBlock
- DEBUG_LOG(DSPHLE, "GetNextCmdBlock (%ibytes)", (u16)_uMail);
- }
- else switch(_uMail)
+ // Temp variables for addresses computation
+ u16 addr_hi, addr_lo;
+ u16 addr2_hi, addr2_lo;
+ u16 volume;
+
+// WARN_LOG(DSPHLE, "Command list:");
+// for (u32 i = 0; m_cmdlist[i] != CMD_END; ++i)
+// WARN_LOG(DSPHLE, "%04x", m_cmdlist[i]);
+// WARN_LOG(DSPHLE, "-------------");
+
+ u32 curr_idx = 0;
+ bool end = false;
+ while (!end)
{
- case 0xCDD10000: // Action 0 - AX_ResumeTask()
- m_rMailHandler.PushMail(DSP_RESUME);
- break;
+ u16 cmd = m_cmdlist[curr_idx++];
- case 0xCDD10001: // Action 1 - new ucode upload
- DEBUG_LOG(DSPHLE,"DSP IROM - New Ucode!");
- // TODO find a better way to protect from HLEMixer?
- soundStream->GetMixer()->SetHLEReady(false);
- m_UploadSetupInProgress = true;
- break;
+ switch (cmd)
+ {
+ // Some of these commands are unknown, or unused in this AX HLE.
+ // We still need to skip their arguments using "curr_idx += N".
+
+ case CMD_SETUP:
+ addr_hi = m_cmdlist[curr_idx++];
+ addr_lo = m_cmdlist[curr_idx++];
+ SetupProcessing(HILO_TO_32(addr));
+ break;
+
+ case CMD_UNK_01: curr_idx += 2; break;
+ case CMD_UNK_02: curr_idx += 2; break;
+ case CMD_UNK_03: curr_idx += 2; break;
+
+ case CMD_PROCESS:
+ addr_hi = m_cmdlist[curr_idx++];
+ addr_lo = m_cmdlist[curr_idx++];
+ ProcessPBList(HILO_TO_32(addr));
+ break;
+
+ case CMD_MIX_AUXA:
+ case CMD_MIX_AUXB:
+ case CMD_MIX_AUXC:
+ curr_idx++; // TODO: Unknown u16
+ addr_hi = m_cmdlist[curr_idx++];
+ addr_lo = m_cmdlist[curr_idx++];
+ addr2_hi = m_cmdlist[curr_idx++];
+ addr2_lo = m_cmdlist[curr_idx++];
+ MixAUXSamples(cmd - CMD_MIX_AUXA, HILO_TO_32(addr), HILO_TO_32(addr2));
+ break;
+
+ // These two go together and manipulate some AUX buffers.
+ case CMD_UNK_08: curr_idx += 13; break;
+ case CMD_UNK_09: curr_idx += 13; break;
+
+ case CMD_UNK_0A: curr_idx += 4; break;
+
+ case CMD_OUTPUT:
+ volume = m_cmdlist[curr_idx++];
+ addr_hi = m_cmdlist[curr_idx++];
+ addr_lo = m_cmdlist[curr_idx++];
+ addr2_hi = m_cmdlist[curr_idx++];
+ addr2_lo = m_cmdlist[curr_idx++];
+ OutputSamples(HILO_TO_32(addr2), HILO_TO_32(addr), volume);
+ break;
+
+ case CMD_UNK_0C: curr_idx += 5; break;
+
+ case CMD_UNK_0D:
+ // Wiimote output?
+ curr_idx += 8;
+ break;
+
+ case CMD_END:
+ end = true;
+ break;
+ }
+ }
+}
- case 0xCDD10002: // Action 2 - IROM_Reset(); ( WII: De Blob, Cursed Mountain,...)
- DEBUG_LOG(DSPHLE,"DSP IROM - Reset!");
- m_DSPHLE->SetUCode(UCODE_ROM);
- return;
+void CUCode_AXWii::SetupProcessing(u32 init_addr)
+{
+ // TODO: should be easily factorizable with AX
+ s16 init_data[60];
+
+ for (u32 i = 0; i < 60; ++i)
+ init_data[i] = HLEMemory_Read_U16(init_addr + 2 * i);
+
+ // List of all buffers we have to initialize
+ int* buffers[] = {
+ m_samples_left,
+ m_samples_right,
+ m_samples_surround,
+ m_samples_auxA_left,
+ m_samples_auxA_right,
+ m_samples_auxA_surround,
+ m_samples_auxB_left,
+ m_samples_auxB_right,
+ m_samples_auxB_surround,
+ m_samples_auxC_left,
+ m_samples_auxC_right,
+ m_samples_auxC_surround
+ };
+
+ u32 init_idx = 0;
+ for (u32 i = 0; i < sizeof (buffers) / sizeof (buffers[0]); ++i)
+ {
+ s32 init_val = (s32)((init_data[init_idx] << 16) | init_data[init_idx + 1]);
+ s16 delta = (s16)init_data[init_idx + 2];
- case 0xCDD10003: // Action 3 - AX_GetNextCmdBlock()
- break;
+ init_idx += 3;
- default:
- DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
- AXTask(_uMail);
- break;
+ if (!init_val)
+ memset(buffers[i], 0, 3 * 32 * sizeof (int));
+ else
+ {
+ for (u32 j = 0; j < 3 * 32; ++j)
+ {
+ buffers[i][j] = init_val;
+ init_val += delta;
+ }
+ }
}
}
-void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
+AXMixControl CUCode_AXWii::ConvertMixerControl(u32 mixer_control)
{
- AXPBWii PB;
-
- if (_iSize > 1024 * 1024)
- _iSize = 1024 * 1024;
-
- memset(templbuffer, 0, _iSize * sizeof(int));
- memset(temprbuffer, 0, _iSize * sizeof(int));
+ u32 ret = 0;
+
+ if (mixer_control & 0x00000001) ret |= MIX_L;
+ if (mixer_control & 0x00000002) ret |= MIX_R;
+ if (mixer_control & 0x00000004) ret |= MIX_L_RAMP | MIX_R_RAMP;
+ if (mixer_control & 0x00000008) ret |= MIX_S;
+ if (mixer_control & 0x00000010) ret |= MIX_S_RAMP;
+ if (mixer_control & 0x00010000) ret |= MIX_AUXA_L;
+ if (mixer_control & 0x00020000) ret |= MIX_AUXA_R;
+ if (mixer_control & 0x00040000) ret |= MIX_AUXA_L_RAMP | MIX_AUXA_R_RAMP;
+ if (mixer_control & 0x00080000) ret |= MIX_AUXA_S;
+ if (mixer_control & 0x00100000) ret |= MIX_AUXA_S_RAMP;
+ if (mixer_control & 0x00200000) ret |= MIX_AUXB_L;
+ if (mixer_control & 0x00400000) ret |= MIX_AUXB_R;
+ if (mixer_control & 0x00800000) ret |= MIX_AUXB_L_RAMP | MIX_AUXB_R_RAMP;
+ if (mixer_control & 0x01000000) ret |= MIX_AUXB_S;
+ if (mixer_control & 0x02000000) ret |= MIX_AUXB_S_RAMP;
+ if (mixer_control & 0x04000000) ret |= MIX_AUXC_L;
+ if (mixer_control & 0x08000000) ret |= MIX_AUXC_R;
+ if (mixer_control & 0x10000000) ret |= MIX_AUXC_L_RAMP | MIX_AUXC_R_RAMP;
+ if (mixer_control & 0x20000000) ret |= MIX_AUXC_S;
+ if (mixer_control & 0x40000000) ret |= MIX_AUXC_S_RAMP;
+
+ return (AXMixControl)ret;
+}
- u32 blockAddr = m_addressPBs;
- if (!blockAddr)
- return;
+void CUCode_AXWii::ProcessPBList(u32 pb_addr)
+{
+ const u32 spms = 32;
- AXBuffers buffers = {{
- templbuffer,
- temprbuffer,
- NULL
- }};
+ AXPBWii pb;
- for (int i = 0; i < NUMBER_OF_PBS; i++)
+ while (pb_addr)
{
- if (!ReadPB(blockAddr, PB))
+ AXBuffers buffers = {{
+ m_samples_left,
+ m_samples_right,
+ m_samples_surround,
+ m_samples_auxA_left,
+ m_samples_auxA_right,
+ m_samples_auxA_surround,
+ m_samples_auxB_left,
+ m_samples_auxB_right,
+ m_samples_auxB_surround,
+ m_samples_auxC_left,
+ m_samples_auxC_right,
+ m_samples_auxC_surround
+ }};
+
+ if (!ReadPB(pb_addr, pb))
break;
-// if (wiisportsHack)
-// MixAddVoice(*(AXPBWiiSports*)&PB, buffers, _iSize);
-// else
-// MixAddVoice(PB, buffers, _iSize);
-
- if (!WritePB(blockAddr, PB))
- break;
-
- // next PB, or done
- blockAddr = (PB.next_pb_hi << 16) | PB.next_pb_lo;
- if (!blockAddr)
- break;
- }
-
- // We write the sound to _pBuffer
- if (_pBuffer)
- {
- for (int i = 0; i < _iSize; i++)
+ for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
{
- // 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;
- else if (left > 32767) left = 32767;
- if (right < -32767) right = -32767;
- else if (right > 32767) right = 32767;
- *_pBuffer++ = left;
- *_pBuffer++ = right;
+ Process1ms(pb, buffers, ConvertMixerControl(HILO_TO_32(pb.mixer_control)));
+
+ // Forward the buffers
+ for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
+ buffers.ptrs[i] += spms;
}
+
+ WritePB(pb_addr, pb);
+ pb_addr = HILO_TO_32(pb.next_pb);
}
}
-
-void CUCode_AXWii::Update(int cycles)
+void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr)
{
- if (NeedsResumeMail())
+ int temp[3][3 * 32];
+ int* buffers[3] = { 0 };
+
+ switch (aux_id)
{
- m_rMailHandler.PushMail(DSP_RESUME);
- DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
+ case 0:
+ buffers[0] = m_samples_auxA_left;
+ buffers[1] = m_samples_auxA_right;
+ buffers[2] = m_samples_auxA_surround;
+ break;
+
+ case 1:
+ buffers[0] = m_samples_auxB_left;
+ buffers[1] = m_samples_auxB_right;
+ buffers[2] = m_samples_auxB_surround;
+ break;
+
+ case 2:
+ buffers[0] = m_samples_auxC_left;
+ buffers[1] = m_samples_auxC_right;
+ buffers[2] = m_samples_auxC_surround;
+ break;
}
- // check if we have to send something
- else if (!m_rMailHandler.IsEmpty())
+
+ // Send the content of AUX buffers to the CPU
+ if (write_addr)
{
- DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
+ for (u32 i = 0; i < 3 * 32; ++i)
+ for (u32 j = 0; j < 3; ++j)
+ temp[j][i] = Common::swap32(buffers[j][i]);
+ memcpy(HLEMemory_Get_Pointer(write_addr), temp, sizeof (temp));
}
+
+ // Then read the buffers from the CPU and add to our current buffers.
+ memcpy(temp, HLEMemory_Get_Pointer(read_addr), sizeof (temp));
+ for (u32 i = 0; i < 3 * 32; ++i)
+ for (u32 j = 0; j < 3; ++j)
+ buffers[j][i] += Common::swap32(temp[j][i]);
}
-// 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)
+void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume)
{
- u32 uAddress = _uMail;
- u32 Addr__AXStudio;
- u32 Addr__AXOutSBuffer;
- bool bExecuteList = true;
-
-/*
- for (int i=0;i<64;i++) {
- NOTICE_LOG(DSPHLE,"%x - %08x",uAddress+(i*4),HLEMemory_Read_U32(uAddress+(i*4)));
- }
-*/
-
- while (bExecuteList)
- {
- u16 iCommand = HLEMemory_Read_U16(uAddress);
- uAddress += 2;
- //NOTICE_LOG(DSPHLE,"AXWII - AXLIST CMD %X",iCommand);
+ int surround_buffer[3 * 32] = { 0 };
- switch (iCommand)
- {
- case 0x0000:
- Addr__AXStudio = HLEMemory_Read_U32(uAddress);
- uAddress += 4;
- break;
-
- case 0x0001:
- uAddress += 4;
- break;
-
- case 0x0003:
- uAddress += 4;
- break;
-
- case 0x0004:
- // PBs are here now
- m_addressPBs = HLEMemory_Read_U32(uAddress);
- soundStream->GetMixer()->SetHLEReady(true);
-// soundStream->Update();
- uAddress += 4;
- break;
-
- case 0x0005:
- if (!wiisportsHack)
- uAddress += 10;
- break;
-
- case 0x0006:
- uAddress += 10;
- break;
-
- case 0x0007: // AXLIST_SBUFFER
- Addr__AXOutSBuffer = HLEMemory_Read_U32(uAddress);
- uAddress += 10;
- break;
-
- case 0x0008:
- uAddress += 26;
- break;
+ for (u32 i = 0; i < 3 * 32; ++i)
+ surround_buffer[i] = Common::swap32(m_samples_surround[i]);
+ memcpy(HLEMemory_Get_Pointer(surround_addr), surround_buffer, sizeof (surround_buffer));
- case 0x000a:
- uAddress += wiisportsHack ? 4 : 8; // AXLIST_COMPRESSORTABLE
- break;
+ short buffer[3 * 32 * 2];
- case 0x000b:
- uAddress += wiisportsHack ? 2 : 10;
- break;
-
- case 0x000c:
- uAddress += wiisportsHack ? 8 : 10;
- break;
-
- case 0x000d:
- uAddress += 16;
- break;
+ // Clamp internal buffers to 16 bits.
+ for (u32 i = 0; i < 3 * 32; ++i)
+ {
+ int left = m_samples_left[i];
+ int right = m_samples_right[i];
- case 0x000e:
- if (wiisportsHack)
- uAddress += 16;
- else
- bExecuteList = false;
- break;
+ if (left < -32767) left = -32767;
+ if (left > 32767) left = 32767;
+ if (right < -32767) right = -32767;
+ if (right > 32767) right = 32767;
- case 0x000f: // only for Wii Sports uCode
- bExecuteList = false;
- break;
+ m_samples_left[i] = left;
+ m_samples_right[i] = right;
+ }
- default:
- INFO_LOG(DSPHLE,"DSPHLE - AXwii - AXLIST - Unknown CMD: %x",iCommand);
- // unknown command so stop the execution of this TaskList
- bExecuteList = false;
- break;
- }
+ for (u32 i = 0; i < 3 * 32; ++i)
+ {
+ buffer[2 * i] = Common::swap16(m_samples_left[i]);
+ buffer[2 * i + 1] = Common::swap16(m_samples_right[i]);
}
- m_rMailHandler.PushMail(DSP_YIELD); //its here in case there is a CMD fuckup
- return true;
+ memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof (buffer));
}
void CUCode_AXWii::DoState(PointerWrap &p)
{
std::lock_guard<std::mutex> lk(m_csMix);
- p.Do(m_addressPBs);
- p.Do(wiisportsHack);
+ // TODO
DoStateShared(p);
}
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
index 1e6cffcba0..d488bd046c 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AXWii.h
@@ -12,44 +12,58 @@
// 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
+// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
-#ifndef _UCODE_AXWII
-#define _UCODE_AXWII
+#ifndef _UCODE_AXWII_H
+#define _UCODE_AXWII_H
-#include "UCode_AXStructs.h"
+#include "UCode_AX.h"
-#define NUMBER_OF_PBS 128
-
-class CUCode_AXWii : public IUCode
+class CUCode_AXWii : public CUCode_AX
{
public:
CUCode_AXWii(DSPHLE *dsp_hle, u32 _CRC);
virtual ~CUCode_AXWii();
- void HandleMail(u32 _uMail);
- void MixAdd(short* _pBuffer, int _iSize);
- void Update(int cycles);
- void DoState(PointerWrap &p);
+ virtual void DoState(PointerWrap &p);
-private:
- enum
- {
- MAIL_AX_ALIST = 0xBABE0000,
- };
+protected:
+ int m_samples_auxC_left[32 * 3];
+ int m_samples_auxC_right[32 * 3];
+ int m_samples_auxC_surround[32 * 3];
- // PBs
- u32 m_addressPBs;
+ // Convert a mixer_control bitfield to our internal representation for that
+ // value. Required because that bitfield has a different meaning in some
+ // versions of AX.
+ AXMixControl ConvertMixerControl(u32 mixer_control);
- bool wiisportsHack;
+ virtual void HandleCommandList();
- int *templbuffer;
- int *temprbuffer;
+ void SetupProcessing(u32 init_addr);
+ void ProcessPBList(u32 pb_addr);
+ void MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr);
+ void OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume);
- // ax task message handler
- bool AXTask(u32& _uMail);
- void SendMail(u32 _uMail);
+private:
+ enum CmdType
+ {
+ CMD_SETUP = 0x00,
+ CMD_UNK_01 = 0x01,
+ CMD_UNK_02 = 0x02,
+ CMD_UNK_03 = 0x03,
+ CMD_PROCESS = 0x04,
+ CMD_MIX_AUXA = 0x05,
+ CMD_MIX_AUXB = 0x06,
+ CMD_MIX_AUXC = 0x07,
+ CMD_UNK_08 = 0x08,
+ CMD_UNK_09 = 0x09,
+ CMD_UNK_0A = 0x0A,
+ CMD_OUTPUT = 0x0B,
+ CMD_UNK_0C = 0x0C,
+ CMD_UNK_0D = 0x0D,
+ CMD_END = 0x0E
+ };
};
#endif // _UCODE_AXWII
diff --git a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
index 20fea41677..22ef0583ce 100644
--- a/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
+++ b/Source/Core/Core/Src/HW/DSPHLE/UCodes/UCode_AX_Voice.h
@@ -15,13 +15,27 @@
// Official Git repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
+// This file is UGLY (full of #ifdef) so that it can be used with both GC and
+// Wii version of AX. Maybe it would be better to abstract away the parts that
+// can be made common.
+
#ifndef _UCODE_AX_VOICE_H
#define _UCODE_AX_VOICE_H
+#if !defined(AX_GC) && !defined(AX_WII)
+#error UCode_AX_Voice.h included without specifying version
+#endif
+
#include "Common.h"
#include "UCode_AXStructs.h"
#include "../../DSP.h"
+#ifdef AX_GC
+# define PB_TYPE AXPB
+#else
+# define PB_TYPE AXPBWii
+#endif
+
// Useful macro to convert xxx_hi + xxx_lo to xxx for 32 bits.
#define HILO_TO_32(name) \
((name##_hi << 16) | name##_lo)
@@ -42,41 +56,23 @@ union AXBuffers
int* auxB_left;
int* auxB_right;
int* auxB_surround;
+
+#ifdef AX_WII
+ int* auxC_left;
+ int* auxC_right;
+ int* auxC_surround;
+#endif
};
+#ifdef AX_GC
int* ptrs[9];
-};
-
-// We can't directly use the mixer_control field from the PB because it does
-// not mean the same in all AX versions. The AX UCode converts the
-// mixer_control value to an AXMixControl bitfield.
-enum AXMixControl
-{
- MIX_L = 0x00001,
- MIX_L_RAMP = 0x00002,
- MIX_R = 0x00004,
- MIX_R_RAMP = 0x00008,
- MIX_S = 0x00010,
- MIX_S_RAMP = 0x00020,
-
- MIX_AUXA_L = 0x00040,
- MIX_AUXA_L_RAMP = 0x00080,
- MIX_AUXA_R = 0x00100,
- MIX_AUXA_R_RAMP = 0x00200,
- MIX_AUXA_S = 0x00400,
- MIX_AUXA_S_RAMP = 0x00800,
-
- MIX_AUXB_L = 0x01000,
- MIX_AUXB_L_RAMP = 0x02000,
- MIX_AUXB_R = 0x04000,
- MIX_AUXB_R_RAMP = 0x08000,
- MIX_AUXB_S = 0x10000,
- MIX_AUXB_S_RAMP = 0x20000
+#else
+ int* ptrs[12];
+#endif
};
// Read a PB from MRAM/ARAM
-template <typename PBType>
-bool ReadPB(u32 addr, PBType& pb)
+bool ReadPB(u32 addr, PB_TYPE& pb)
{
u16* dst = (u16*)&pb;
const u16* src = (const u16*)Memory::GetPointer(addr);
@@ -90,8 +86,7 @@ bool ReadPB(u32 addr, PBType& pb)
}
// Write a PB back to MRAM/ARAM
-template <typename PBType>
-inline bool WritePB(u32 addr, const PBType& pb)
+inline bool WritePB(u32 addr, const PB_TYPE& pb)
{
const u16* src = (const u16*)&pb;
u16* dst = (u16*)Memory::GetPointer(addr);
@@ -107,10 +102,10 @@ inline bool WritePB(u32 addr, const PBType& pb)
// Simulated accelerator state.
static u32 acc_loop_addr, acc_end_addr;
static u32* acc_cur_addr;
-static AXPB* acc_pb;
+static PB_TYPE* acc_pb;
// Sets up the simulated accelerator.
-inline void AcceleratorSetup(AXPB* pb, u32* cur_addr)
+inline void AcceleratorSetup(PB_TYPE* pb, u32* cur_addr)
{
acc_pb = pb;
acc_loop_addr = HILO_TO_32(pb->audio_addr.loop_addr);
@@ -216,7 +211,7 @@ inline u16 AcceleratorGetSample()
}
// Read 32 input samples from ARAM, decoding and converting rate if required.
-inline void GetInputSamples(AXPB& pb, s16* samples)
+inline void GetInputSamples(PB_TYPE& pb, s16* samples)
{
u32 cur_addr = HILO_TO_32(pb.audio_addr.cur_addr);
AcceleratorSetup(&pb, &cur_addr);
@@ -319,7 +314,7 @@ inline void MixAdd(int* out, const s16* input, u16* pvol, bool ramp)
}
// Process 1ms of audio (32 samples) from a PB and mix it to the buffers.
-inline void Process1ms(AXPB& pb, const AXBuffers& buffers, AXMixControl mctrl)
+void Process1ms(PB_TYPE& pb, const AXBuffers& buffers, AXMixControl mctrl)
{
// If the voice is not running, nothing to do.
if (!pb.running)
@@ -370,6 +365,15 @@ inline void Process1ms(AXPB& pb, const AXBuffers& buffers, AXMixControl mctrl)
if (mctrl & MIX_AUXB_S)
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
+#ifdef AX_WII
+ if (mctrl & MIX_AUXC_L)
+ MixAdd(buffers.auxC_left, samples, &pb.mixer.auxC_left, mctrl & MIX_AUXC_L_RAMP);
+ if (mctrl & MIX_AUXC_R)
+ MixAdd(buffers.auxC_right, samples, &pb.mixer.auxC_right, mctrl & MIX_AUXC_R_RAMP);
+ if (mctrl & MIX_AUXC_S)
+ MixAdd(buffers.auxC_surround, samples, &pb.mixer.auxC_surround, mctrl & MIX_AUXC_S_RAMP);
+#endif
+
// Optionally, phase shift left or right channel to simulate 3D sound.
if (pb.initial_time_delay.on)
{