New AXWii now working properly in some games I tested
This commit is contained in:
parent
e750bed2a9
commit
954c55e35a
|
@ -16,9 +16,11 @@
|
||||||
// http://code.google.com/p/dolphin-emu/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#include "UCode_AX.h"
|
#include "UCode_AX.h"
|
||||||
#include "UCode_AX_Voice.h"
|
|
||||||
#include "../../DSP.h"
|
#include "../../DSP.h"
|
||||||
|
|
||||||
|
#define AX_GC
|
||||||
|
#include "UCode_AX_Voice.h"
|
||||||
|
|
||||||
CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
|
CUCode_AX::CUCode_AX(DSPHLE* dsp_hle, u32 crc)
|
||||||
: IUCode(dsp_hle, crc)
|
: IUCode(dsp_hle, crc)
|
||||||
, m_cmdlist_size(0)
|
, m_cmdlist_size(0)
|
||||||
|
@ -123,7 +125,7 @@ void CUCode_AX::HandleCommandList()
|
||||||
addr_lo = m_cmdlist[curr_idx++];
|
addr_lo = m_cmdlist[curr_idx++];
|
||||||
addr2_hi = m_cmdlist[curr_idx++];
|
addr2_hi = m_cmdlist[curr_idx++];
|
||||||
addr2_lo = 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;
|
break;
|
||||||
|
|
||||||
case CMD_UPLOAD_LRS:
|
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.
|
// First, we need to send the contents of our AUX buffers to the CPU.
|
||||||
if (write_addr)
|
if (write_addr)
|
||||||
{
|
{
|
||||||
for (u32 i = 0; i < 5 * 32; ++i)
|
for (u32 i = 0; i < 3 * 32; ++i)
|
||||||
{
|
for (u32 j = 0; j < 3; ++j)
|
||||||
if (AUXA)
|
temp[j][i] = Common::swap32(buffers[j][i]);
|
||||||
{
|
memcpy(HLEMemory_Get_Pointer(write_addr), temp, sizeof (temp));
|
||||||
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));
|
|
||||||
}
|
}
|
||||||
|
|
||||||
// Then, we read the new buffers from the CPU and add to our current
|
// Then, we read the new temp from the CPU and add to our current
|
||||||
// buffers.
|
// temp.
|
||||||
memcpy(buffers, HLEMemory_Get_Pointer(read_addr), sizeof (buffers));
|
memcpy(temp, HLEMemory_Get_Pointer(read_addr), sizeof (temp));
|
||||||
for (u32 i = 0; i < 5 * 32; ++i)
|
for (u32 i = 0; i < 5 * 32; ++i)
|
||||||
{
|
for (u32 j = 0; j < 3; ++j)
|
||||||
m_samples_left[i] += Common::swap32(buffers[0][i]);
|
buffers[j][i] += Common::swap32(temp[j][i]);
|
||||||
m_samples_right[i] += Common::swap32(buffers[1][i]);
|
|
||||||
m_samples_surround[i] += Common::swap32(buffers[2][i]);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_AX::UploadLRS(u32 dst_addr)
|
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);
|
std::lock_guard<std::mutex> lk(m_processing);
|
||||||
|
|
||||||
|
// TODO
|
||||||
|
|
||||||
DoStateShared(p);
|
DoStateShared(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -29,7 +29,40 @@
|
||||||
|
|
||||||
#include "UCodes.h"
|
#include "UCodes.h"
|
||||||
#include "UCode_AXStructs.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
|
class CUCode_AX : public IUCode
|
||||||
{
|
{
|
||||||
|
@ -37,16 +70,16 @@ public:
|
||||||
CUCode_AX(DSPHLE* dsp_hle, u32 crc);
|
CUCode_AX(DSPHLE* dsp_hle, u32 crc);
|
||||||
virtual ~CUCode_AX();
|
virtual ~CUCode_AX();
|
||||||
|
|
||||||
void HandleMail(u32 mail);
|
virtual void HandleMail(u32 mail);
|
||||||
void MixAdd(short* out_buffer, int nsamples);
|
virtual void MixAdd(short* out_buffer, int nsamples);
|
||||||
void Update(int cycles);
|
virtual void Update(int cycles);
|
||||||
void DoState(PointerWrap& p);
|
virtual void DoState(PointerWrap& p);
|
||||||
|
|
||||||
// Needed because StdThread.h std::thread implem does not support member
|
// Needed because StdThread.h std::thread implem does not support member
|
||||||
// pointers.
|
// pointers.
|
||||||
static void SpawnAXThread(CUCode_AX* self);
|
static void SpawnAXThread(CUCode_AX* self);
|
||||||
|
|
||||||
private:
|
protected:
|
||||||
enum MailType
|
enum MailType
|
||||||
{
|
{
|
||||||
MAIL_RESUME = 0xCDD10000,
|
MAIL_RESUME = 0xCDD10000,
|
||||||
|
@ -59,31 +92,7 @@ private:
|
||||||
MAIL_CMDLIST_MASK = 0xFFFF0000
|
MAIL_CMDLIST_MASK = 0xFFFF0000
|
||||||
};
|
};
|
||||||
|
|
||||||
enum CmdType
|
// 32 * 5 because 32 samples per millisecond, for max 5 milliseconds.
|
||||||
{
|
|
||||||
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.
|
|
||||||
int m_samples_left[32 * 5];
|
int m_samples_left[32 * 5];
|
||||||
int m_samples_right[32 * 5];
|
int m_samples_right[32 * 5];
|
||||||
int m_samples_surround[32 * 5];
|
int m_samples_surround[32 * 5];
|
||||||
|
@ -119,12 +128,39 @@ private:
|
||||||
void NotifyAXThread();
|
void NotifyAXThread();
|
||||||
|
|
||||||
void AXThread();
|
void AXThread();
|
||||||
void HandleCommandList();
|
|
||||||
void SetupProcessing(u32 studio_addr);
|
virtual void HandleCommandList();
|
||||||
|
|
||||||
|
void SetupProcessing(u32 init_addr);
|
||||||
void ProcessPBList(u32 pb_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 UploadLRS(u32 dst_addr);
|
||||||
void OutputSamples(u32 out_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
|
#endif // !_UCODE_AX_H
|
||||||
|
|
|
@ -23,249 +23,294 @@
|
||||||
#include "UCodes.h"
|
#include "UCodes.h"
|
||||||
#include "UCode_AXStructs.h"
|
#include "UCode_AXStructs.h"
|
||||||
#include "UCode_AXWii.h"
|
#include "UCode_AXWii.h"
|
||||||
|
|
||||||
|
#define AX_WII
|
||||||
#include "UCode_AX_Voice.h"
|
#include "UCode_AX_Voice.h"
|
||||||
|
|
||||||
|
|
||||||
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
|
CUCode_AXWii::CUCode_AXWii(DSPHLE *dsp_hle, u32 l_CRC)
|
||||||
: IUCode(dsp_hle, l_CRC)
|
: CUCode_AX(dsp_hle, l_CRC)
|
||||||
, m_addressPBs(0xFFFFFFFF)
|
|
||||||
{
|
{
|
||||||
// we got loaded
|
WARN_LOG(DSPHLE, "Instantiating CUCode_AXWii");
|
||||||
m_rMailHandler.PushMail(DSP_INIT);
|
|
||||||
|
|
||||||
templbuffer = new int[1024 * 1024];
|
|
||||||
temprbuffer = new int[1024 * 1024];
|
|
||||||
|
|
||||||
wiisportsHack = m_CRC == 0xfa450138;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
CUCode_AXWii::~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)
|
// 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)
|
||||||
{
|
{
|
||||||
PrepareBootUCode(_uMail);
|
u16 cmd = m_cmdlist[curr_idx++];
|
||||||
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)
|
|
||||||
{
|
|
||||||
case 0xCDD10000: // Action 0 - AX_ResumeTask()
|
|
||||||
m_rMailHandler.PushMail(DSP_RESUME);
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0xCDD10001: // Action 1 - new ucode upload
|
switch (cmd)
|
||||||
DEBUG_LOG(DSPHLE,"DSP IROM - New Ucode!");
|
|
||||||
// TODO find a better way to protect from HLEMixer?
|
|
||||||
soundStream->GetMixer()->SetHLEReady(false);
|
|
||||||
m_UploadSetupInProgress = 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;
|
|
||||||
|
|
||||||
case 0xCDD10003: // Action 3 - AX_GetNextCmdBlock()
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
DEBUG_LOG(DSPHLE, " >>>> u32 MAIL : AXTask Mail (%08x)", _uMail);
|
|
||||||
AXTask(_uMail);
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
void CUCode_AXWii::MixAdd(short* _pBuffer, int _iSize)
|
|
||||||
{
|
|
||||||
AXPBWii PB;
|
|
||||||
|
|
||||||
if (_iSize > 1024 * 1024)
|
|
||||||
_iSize = 1024 * 1024;
|
|
||||||
|
|
||||||
memset(templbuffer, 0, _iSize * sizeof(int));
|
|
||||||
memset(temprbuffer, 0, _iSize * sizeof(int));
|
|
||||||
|
|
||||||
u32 blockAddr = m_addressPBs;
|
|
||||||
if (!blockAddr)
|
|
||||||
return;
|
|
||||||
|
|
||||||
AXBuffers buffers = {{
|
|
||||||
templbuffer,
|
|
||||||
temprbuffer,
|
|
||||||
NULL
|
|
||||||
}};
|
|
||||||
|
|
||||||
for (int i = 0; i < NUMBER_OF_PBS; i++)
|
|
||||||
{
|
|
||||||
if (!ReadPB(blockAddr, 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++)
|
|
||||||
{
|
{
|
||||||
// Clamp into 16-bit. Maybe we should add a volume compressor here.
|
// Some of these commands are unknown, or unused in this AX HLE.
|
||||||
int left = templbuffer[i] + _pBuffer[0];
|
// We still need to skip their arguments using "curr_idx += N".
|
||||||
int right = temprbuffer[i] + _pBuffer[1];
|
|
||||||
if (left < -32767) left = -32767;
|
case CMD_SETUP:
|
||||||
else if (left > 32767) left = 32767;
|
addr_hi = m_cmdlist[curr_idx++];
|
||||||
if (right < -32767) right = -32767;
|
addr_lo = m_cmdlist[curr_idx++];
|
||||||
else if (right > 32767) right = 32767;
|
SetupProcessing(HILO_TO_32(addr));
|
||||||
*_pBuffer++ = left;
|
break;
|
||||||
*_pBuffer++ = right;
|
|
||||||
|
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;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void CUCode_AXWii::SetupProcessing(u32 init_addr)
|
||||||
void CUCode_AXWii::Update(int cycles)
|
|
||||||
{
|
{
|
||||||
if (NeedsResumeMail())
|
// 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)
|
||||||
{
|
{
|
||||||
m_rMailHandler.PushMail(DSP_RESUME);
|
s32 init_val = (s32)((init_data[init_idx] << 16) | init_data[init_idx + 1]);
|
||||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
s16 delta = (s16)init_data[init_idx + 2];
|
||||||
}
|
|
||||||
// check if we have to send something
|
init_idx += 3;
|
||||||
else if (!m_rMailHandler.IsEmpty())
|
|
||||||
{
|
if (!init_val)
|
||||||
DSP::GenerateDSPInterruptFromDSPEmu(DSP::INT_DSP);
|
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;
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// AX seems to bootup one task only and waits for resume-callbacks
|
AXMixControl CUCode_AXWii::ConvertMixerControl(u32 mixer_control)
|
||||||
// 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;
|
u32 ret = 0;
|
||||||
u32 Addr__AXStudio;
|
|
||||||
u32 Addr__AXOutSBuffer;
|
|
||||||
bool bExecuteList = true;
|
|
||||||
|
|
||||||
/*
|
if (mixer_control & 0x00000001) ret |= MIX_L;
|
||||||
for (int i=0;i<64;i++) {
|
if (mixer_control & 0x00000002) ret |= MIX_R;
|
||||||
NOTICE_LOG(DSPHLE,"%x - %08x",uAddress+(i*4),HLEMemory_Read_U32(uAddress+(i*4)));
|
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;
|
||||||
|
|
||||||
while (bExecuteList)
|
return (AXMixControl)ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUCode_AXWii::ProcessPBList(u32 pb_addr)
|
||||||
|
{
|
||||||
|
const u32 spms = 32;
|
||||||
|
|
||||||
|
AXPBWii pb;
|
||||||
|
|
||||||
|
while (pb_addr)
|
||||||
{
|
{
|
||||||
u16 iCommand = HLEMemory_Read_U16(uAddress);
|
AXBuffers buffers = {{
|
||||||
uAddress += 2;
|
m_samples_left,
|
||||||
//NOTICE_LOG(DSPHLE,"AXWII - AXLIST CMD %X",iCommand);
|
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
|
||||||
|
}};
|
||||||
|
|
||||||
switch (iCommand)
|
if (!ReadPB(pb_addr, pb))
|
||||||
|
break;
|
||||||
|
|
||||||
|
for (int curr_ms = 0; curr_ms < 3; ++curr_ms)
|
||||||
{
|
{
|
||||||
case 0x0000:
|
Process1ms(pb, buffers, ConvertMixerControl(HILO_TO_32(pb.mixer_control)));
|
||||||
Addr__AXStudio = HLEMemory_Read_U32(uAddress);
|
|
||||||
uAddress += 4;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x0001:
|
// Forward the buffers
|
||||||
uAddress += 4;
|
for (u32 i = 0; i < sizeof (buffers.ptrs) / sizeof (buffers.ptrs[0]); ++i)
|
||||||
break;
|
buffers.ptrs[i] += spms;
|
||||||
|
|
||||||
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;
|
|
||||||
|
|
||||||
case 0x000a:
|
|
||||||
uAddress += wiisportsHack ? 4 : 8; // AXLIST_COMPRESSORTABLE
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000b:
|
|
||||||
uAddress += wiisportsHack ? 2 : 10;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000c:
|
|
||||||
uAddress += wiisportsHack ? 8 : 10;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000d:
|
|
||||||
uAddress += 16;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000e:
|
|
||||||
if (wiisportsHack)
|
|
||||||
uAddress += 16;
|
|
||||||
else
|
|
||||||
bExecuteList = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
case 0x000f: // only for Wii Sports uCode
|
|
||||||
bExecuteList = false;
|
|
||||||
break;
|
|
||||||
|
|
||||||
default:
|
|
||||||
INFO_LOG(DSPHLE,"DSPHLE - AXwii - AXLIST - Unknown CMD: %x",iCommand);
|
|
||||||
// unknown command so stop the execution of this TaskList
|
|
||||||
bExecuteList = false;
|
|
||||||
break;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
|
WritePB(pb_addr, pb);
|
||||||
|
pb_addr = HILO_TO_32(pb.next_pb);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUCode_AXWii::MixAUXSamples(int aux_id, u32 write_addr, u32 read_addr)
|
||||||
|
{
|
||||||
|
int temp[3][3 * 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;
|
||||||
|
|
||||||
|
case 2:
|
||||||
|
buffers[0] = m_samples_auxC_left;
|
||||||
|
buffers[1] = m_samples_auxC_right;
|
||||||
|
buffers[2] = m_samples_auxC_surround;
|
||||||
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
m_rMailHandler.PushMail(DSP_YIELD); //its here in case there is a CMD fuckup
|
// Send the content of AUX buffers to the CPU
|
||||||
return true;
|
if (write_addr)
|
||||||
|
{
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
void CUCode_AXWii::OutputSamples(u32 lr_addr, u32 surround_addr, u16 volume)
|
||||||
|
{
|
||||||
|
int surround_buffer[3 * 32] = { 0 };
|
||||||
|
|
||||||
|
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));
|
||||||
|
|
||||||
|
short buffer[3 * 32 * 2];
|
||||||
|
|
||||||
|
// 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];
|
||||||
|
|
||||||
|
if (left < -32767) left = -32767;
|
||||||
|
if (left > 32767) left = 32767;
|
||||||
|
if (right < -32767) right = -32767;
|
||||||
|
if (right > 32767) right = 32767;
|
||||||
|
|
||||||
|
m_samples_left[i] = left;
|
||||||
|
m_samples_right[i] = right;
|
||||||
|
}
|
||||||
|
|
||||||
|
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]);
|
||||||
|
}
|
||||||
|
|
||||||
|
memcpy(HLEMemory_Get_Pointer(lr_addr), buffer, sizeof (buffer));
|
||||||
}
|
}
|
||||||
|
|
||||||
void CUCode_AXWii::DoState(PointerWrap &p)
|
void CUCode_AXWii::DoState(PointerWrap &p)
|
||||||
{
|
{
|
||||||
std::lock_guard<std::mutex> lk(m_csMix);
|
std::lock_guard<std::mutex> lk(m_csMix);
|
||||||
|
|
||||||
p.Do(m_addressPBs);
|
// TODO
|
||||||
p.Do(wiisportsHack);
|
|
||||||
|
|
||||||
DoStateShared(p);
|
DoStateShared(p);
|
||||||
}
|
}
|
||||||
|
|
|
@ -12,44 +12,58 @@
|
||||||
// A copy of the GPL 2.0 should have been included with the program.
|
// A copy of the GPL 2.0 should have been included with the program.
|
||||||
// If not, see http://www.gnu.org/licenses/
|
// 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/
|
// http://code.google.com/p/dolphin-emu/
|
||||||
|
|
||||||
#ifndef _UCODE_AXWII
|
#ifndef _UCODE_AXWII_H
|
||||||
#define _UCODE_AXWII
|
#define _UCODE_AXWII_H
|
||||||
|
|
||||||
#include "UCode_AXStructs.h"
|
#include "UCode_AX.h"
|
||||||
|
|
||||||
#define NUMBER_OF_PBS 128
|
class CUCode_AXWii : public CUCode_AX
|
||||||
|
|
||||||
class CUCode_AXWii : public IUCode
|
|
||||||
{
|
{
|
||||||
public:
|
public:
|
||||||
CUCode_AXWii(DSPHLE *dsp_hle, u32 _CRC);
|
CUCode_AXWii(DSPHLE *dsp_hle, u32 _CRC);
|
||||||
virtual ~CUCode_AXWii();
|
virtual ~CUCode_AXWii();
|
||||||
|
|
||||||
void HandleMail(u32 _uMail);
|
virtual void DoState(PointerWrap &p);
|
||||||
void MixAdd(short* _pBuffer, int _iSize);
|
|
||||||
void Update(int cycles);
|
protected:
|
||||||
void DoState(PointerWrap &p);
|
int m_samples_auxC_left[32 * 3];
|
||||||
|
int m_samples_auxC_right[32 * 3];
|
||||||
|
int m_samples_auxC_surround[32 * 3];
|
||||||
|
|
||||||
|
// 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);
|
||||||
|
|
||||||
|
virtual void HandleCommandList();
|
||||||
|
|
||||||
|
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);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
enum
|
enum CmdType
|
||||||
{
|
{
|
||||||
MAIL_AX_ALIST = 0xBABE0000,
|
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
|
||||||
};
|
};
|
||||||
|
|
||||||
// PBs
|
|
||||||
u32 m_addressPBs;
|
|
||||||
|
|
||||||
bool wiisportsHack;
|
|
||||||
|
|
||||||
int *templbuffer;
|
|
||||||
int *temprbuffer;
|
|
||||||
|
|
||||||
// ax task message handler
|
|
||||||
bool AXTask(u32& _uMail);
|
|
||||||
void SendMail(u32 _uMail);
|
|
||||||
};
|
};
|
||||||
|
|
||||||
#endif // _UCODE_AXWII
|
#endif // _UCODE_AXWII
|
||||||
|
|
|
@ -15,13 +15,27 @@
|
||||||
// Official Git 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/
|
// 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
|
#ifndef _UCODE_AX_VOICE_H
|
||||||
#define _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 "Common.h"
|
||||||
#include "UCode_AXStructs.h"
|
#include "UCode_AXStructs.h"
|
||||||
#include "../../DSP.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.
|
// Useful macro to convert xxx_hi + xxx_lo to xxx for 32 bits.
|
||||||
#define HILO_TO_32(name) \
|
#define HILO_TO_32(name) \
|
||||||
((name##_hi << 16) | name##_lo)
|
((name##_hi << 16) | name##_lo)
|
||||||
|
@ -42,41 +56,23 @@ union AXBuffers
|
||||||
int* auxB_left;
|
int* auxB_left;
|
||||||
int* auxB_right;
|
int* auxB_right;
|
||||||
int* auxB_surround;
|
int* auxB_surround;
|
||||||
|
|
||||||
|
#ifdef AX_WII
|
||||||
|
int* auxC_left;
|
||||||
|
int* auxC_right;
|
||||||
|
int* auxC_surround;
|
||||||
|
#endif
|
||||||
};
|
};
|
||||||
|
|
||||||
|
#ifdef AX_GC
|
||||||
int* ptrs[9];
|
int* ptrs[9];
|
||||||
};
|
#else
|
||||||
|
int* ptrs[12];
|
||||||
// We can't directly use the mixer_control field from the PB because it does
|
#endif
|
||||||
// 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
|
|
||||||
};
|
};
|
||||||
|
|
||||||
// Read a PB from MRAM/ARAM
|
// Read a PB from MRAM/ARAM
|
||||||
template <typename PBType>
|
bool ReadPB(u32 addr, PB_TYPE& pb)
|
||||||
bool ReadPB(u32 addr, PBType& pb)
|
|
||||||
{
|
{
|
||||||
u16* dst = (u16*)&pb;
|
u16* dst = (u16*)&pb;
|
||||||
const u16* src = (const u16*)Memory::GetPointer(addr);
|
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
|
// Write a PB back to MRAM/ARAM
|
||||||
template <typename PBType>
|
inline bool WritePB(u32 addr, const PB_TYPE& pb)
|
||||||
inline bool WritePB(u32 addr, const PBType& pb)
|
|
||||||
{
|
{
|
||||||
const u16* src = (const u16*)&pb;
|
const u16* src = (const u16*)&pb;
|
||||||
u16* dst = (u16*)Memory::GetPointer(addr);
|
u16* dst = (u16*)Memory::GetPointer(addr);
|
||||||
|
@ -107,10 +102,10 @@ inline bool WritePB(u32 addr, const PBType& pb)
|
||||||
// Simulated accelerator state.
|
// Simulated accelerator state.
|
||||||
static u32 acc_loop_addr, acc_end_addr;
|
static u32 acc_loop_addr, acc_end_addr;
|
||||||
static u32* acc_cur_addr;
|
static u32* acc_cur_addr;
|
||||||
static AXPB* acc_pb;
|
static PB_TYPE* acc_pb;
|
||||||
|
|
||||||
// Sets up the simulated accelerator.
|
// 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_pb = pb;
|
||||||
acc_loop_addr = HILO_TO_32(pb->audio_addr.loop_addr);
|
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.
|
// 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);
|
u32 cur_addr = HILO_TO_32(pb.audio_addr.cur_addr);
|
||||||
AcceleratorSetup(&pb, &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.
|
// 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 the voice is not running, nothing to do.
|
||||||
if (!pb.running)
|
if (!pb.running)
|
||||||
|
@ -370,6 +365,15 @@ inline void Process1ms(AXPB& pb, const AXBuffers& buffers, AXMixControl mctrl)
|
||||||
if (mctrl & MIX_AUXB_S)
|
if (mctrl & MIX_AUXB_S)
|
||||||
MixAdd(buffers.auxB_surround, samples, &pb.mixer.auxB_surround, mctrl & MIX_AUXB_S_RAMP);
|
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.
|
// Optionally, phase shift left or right channel to simulate 3D sound.
|
||||||
if (pb.initial_time_delay.on)
|
if (pb.initial_time_delay.on)
|
||||||
{
|
{
|
||||||
|
|
Loading…
Reference in New Issue