convert SPU to OOP

This commit is contained in:
Arisotura 2023-11-04 14:20:58 +01:00
parent ac38faef14
commit 76976fef30
8 changed files with 216 additions and 202 deletions

View File

@ -1320,7 +1320,7 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
switch (addr & 0xFF800000) switch (addr & 0xFF800000)
{ {
case 0x04000000: case 0x04000000:
if (addr >= 0x04000400 && addr < 0x04000520) /*if (addr >= 0x04000400 && addr < 0x04000520)
{ {
switch (size | store) switch (size | store)
{ {
@ -1331,7 +1331,7 @@ void* GetFuncForAddr(ARM* cpu, u32 addr, bool store, int size)
case 32: return (void*)SPU::Read32; case 32: return (void*)SPU::Read32;
case 33: return (void*)SPU::Write32; case 33: return (void*)SPU::Write32;
} }
} }*/
if (NDS::ConsoleType == 0) if (NDS::ConsoleType == 0)
{ {

View File

@ -178,7 +178,8 @@ u32 KeyInput;
u16 KeyCnt[2]; u16 KeyCnt[2];
u16 RCnt; u16 RCnt;
SPIHost* SPI; class SPU* SPU;
class SPIHost* SPI;
class RTC* RTC; class RTC* RTC;
bool Running; bool Running;
@ -218,13 +219,13 @@ bool Init()
DMAs[6] = new DMA(1, 2); DMAs[6] = new DMA(1, 2);
DMAs[7] = new DMA(1, 3); DMAs[7] = new DMA(1, 3);
SPI = new SPIHost(); SPU = new class SPU;
SPI = new class SPIHost();
RTC = new class RTC(); RTC = new class RTC();
if (!NDSCart::Init()) return false; if (!NDSCart::Init()) return false;
if (!GBACart::Init()) return false; if (!GBACart::Init()) return false;
if (!GPU::Init()) return false; if (!GPU::Init()) return false;
if (!SPU::Init()) return false;
if (!Wifi::Init()) return false; if (!Wifi::Init()) return false;
if (!DSi::Init()) return false; if (!DSi::Init()) return false;
@ -240,11 +241,8 @@ void DeInit()
ARMJIT::DeInit(); ARMJIT::DeInit();
#endif #endif
delete ARM9; delete ARM9; ARM9 = nullptr;
ARM9 = nullptr; delete ARM7; ARM7 = nullptr;
delete ARM7;
ARM7 = nullptr;
for (int i = 0; i < 8; i++) for (int i = 0; i < 8; i++)
{ {
@ -252,16 +250,13 @@ void DeInit()
DMAs[i] = nullptr; DMAs[i] = nullptr;
} }
delete SPI; delete SPU; SPU = nullptr;
SPI = nullptr; delete SPI; SPI = nullptr;
delete RTC; RTC = nullptr;
delete RTC;
RTC = nullptr;
NDSCart::DeInit(); NDSCart::DeInit();
GBACart::DeInit(); GBACart::DeInit();
GPU::DeInit(); GPU::DeInit();
SPU::DeInit();
Wifi::DeInit(); Wifi::DeInit();
DSi::DeInit(); DSi::DeInit();
@ -529,7 +524,7 @@ void SetupDirectBoot(const std::string& romname)
NDSCart::SPICnt = 0x8000; NDSCart::SPICnt = 0x8000;
SPU::SetBias(0x200); SPU->SetBias(0x200);
SetWifiWaitCnt(0x0030); SetWifiWaitCnt(0x0030);
} }
@ -648,7 +643,7 @@ void Reset()
NDSCart::Reset(); NDSCart::Reset();
GBACart::Reset(); GBACart::Reset();
GPU::Reset(); GPU::Reset();
SPU::Reset(); SPU->Reset();
SPI->Reset(); SPI->Reset();
RTC->Reset(); RTC->Reset();
Wifi::Reset(); Wifi::Reset();
@ -656,7 +651,7 @@ void Reset()
// TODO: move the SOUNDBIAS/degrade logic to SPU? // TODO: move the SOUNDBIAS/degrade logic to SPU?
// The SOUNDBIAS register does nothing on DSi // The SOUNDBIAS register does nothing on DSi
SPU::SetApplyBias(ConsoleType == 0); SPU->SetApplyBias(ConsoleType == 0);
bool degradeAudio = true; bool degradeAudio = true;
@ -673,7 +668,7 @@ void Reset()
else if (bitDepth == 2) // Always 16-bit else if (bitDepth == 2) // Always 16-bit
degradeAudio = false; degradeAudio = false;
SPU::SetDegrade10Bit(degradeAudio); SPU->SetDegrade10Bit(degradeAudio);
AREngine::Reset(); AREngine::Reset();
} }
@ -722,7 +717,7 @@ void Stop(Platform::StopReason reason)
Running = false; Running = false;
Platform::SignalStop(reason); Platform::SignalStop(reason);
GPU::Stop(); GPU::Stop();
SPU::Stop(); SPU->Stop();
if (ConsoleType == 1) if (ConsoleType == 1)
DSi::Stop(); DSi::Stop();
@ -850,7 +845,7 @@ bool DoSavestate(Savestate* file)
if (ConsoleType == 0) if (ConsoleType == 0)
GBACart::DoSavestate(file); GBACart::DoSavestate(file);
GPU::DoSavestate(file); GPU::DoSavestate(file);
SPU::DoSavestate(file); SPU->DoSavestate(file);
SPI->DoSavestate(file); SPI->DoSavestate(file);
RTC->DoSavestate(file); RTC->DoSavestate(file);
Wifi::DoSavestate(file); Wifi::DoSavestate(file);
@ -862,7 +857,7 @@ bool DoSavestate(Savestate* file)
{ {
GPU::SetPowerCnt(PowerControl9); GPU::SetPowerCnt(PowerControl9);
SPU::SetPowerCnt(PowerControl7 & 0x0001); SPU->SetPowerCnt(PowerControl7 & 0x0001);
Wifi::SetPowerCnt(PowerControl7 & 0x0002); Wifi::SetPowerCnt(PowerControl7 & 0x0002);
} }
@ -1193,7 +1188,7 @@ u32 RunFrame()
ARM7Timestamp-SysTimestamp, ARM7Timestamp-SysTimestamp,
GPU3D::Timestamp-SysTimestamp); GPU3D::Timestamp-SysTimestamp);
#endif #endif
SPU::TransferOutput(); SPU->TransferOutput();
break; break;
} }
@ -3922,7 +3917,7 @@ u8 ARM7IORead8(u32 addr)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
return SPU::Read8(addr); return SPU->Read8(addr);
} }
if ((addr & 0xFFFFF000) != 0x04004000) if ((addr & 0xFFFFF000) != 0x04004000)
@ -4016,7 +4011,7 @@ u16 ARM7IORead16(u32 addr)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
return SPU::Read16(addr); return SPU->Read16(addr);
} }
if ((addr & 0xFFFFF000) != 0x04004000) if ((addr & 0xFFFFF000) != 0x04004000)
@ -4117,7 +4112,7 @@ u32 ARM7IORead32(u32 addr)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
return SPU::Read32(addr); return SPU->Read32(addr);
} }
if ((addr & 0xFFFFF000) != 0x04004000) if ((addr & 0xFFFFF000) != 0x04004000)
@ -4195,7 +4190,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
SPU::Write8(addr, val); SPU->Write8(addr, val);
return; return;
} }
@ -4336,7 +4331,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
{ {
u16 change = PowerControl7 ^ val; u16 change = PowerControl7 ^ val;
PowerControl7 = val & 0x0003; PowerControl7 = val & 0x0003;
SPU::SetPowerCnt(val & 0x0001); SPU->SetPowerCnt(val & 0x0001);
Wifi::SetPowerCnt(val & 0x0002); Wifi::SetPowerCnt(val & 0x0002);
if (change & 0x0002) UpdateWifiTimings(); if (change & 0x0002) UpdateWifiTimings();
} }
@ -4350,7 +4345,7 @@ void ARM7IOWrite16(u32 addr, u16 val)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
SPU::Write16(addr, val); SPU->Write16(addr, val);
return; return;
} }
@ -4466,7 +4461,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
{ {
u16 change = PowerControl7 ^ val; u16 change = PowerControl7 ^ val;
PowerControl7 = val & 0x0003; PowerControl7 = val & 0x0003;
SPU::SetPowerCnt(val & 0x0001); SPU->SetPowerCnt(val & 0x0001);
Wifi::SetPowerCnt(val & 0x0002); Wifi::SetPowerCnt(val & 0x0002);
if (change & 0x0002) UpdateWifiTimings(); if (change & 0x0002) UpdateWifiTimings();
} }
@ -4484,7 +4479,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
SPU::Write32(addr, val); SPU->Write32(addr, val);
return; return;
} }

View File

@ -30,6 +30,7 @@
// with this enabled, to make sure it doesn't desync // with this enabled, to make sure it doesn't desync
//#define DEBUG_CHECK_DESYNC //#define DEBUG_CHECK_DESYNC
class SPU;
class SPIHost; class SPIHost;
class RTC; class RTC;
@ -249,7 +250,8 @@ extern MemRegion SWRAM_ARM7;
extern u32 KeyInput; extern u32 KeyInput;
extern u16 RCnt; extern u16 RCnt;
extern SPIHost* SPI; extern class SPU* SPU;
extern class SPIHost* SPI;
extern class RTC* RTC; extern class RTC* RTC;
const u32 ARM7WRAMSize = 0x10000; const u32 ARM7WRAMSize = 0x10000;

View File

@ -533,7 +533,11 @@ SPIHost::SPIHost()
Devices[SPIDevice_FirmwareMem] = new FirmwareMem(this); Devices[SPIDevice_FirmwareMem] = new FirmwareMem(this);
Devices[SPIDevice_PowerMan] = new PowerMan(this); Devices[SPIDevice_PowerMan] = new PowerMan(this);
Devices[SPIDevice_TSC] = nullptr;
if (NDS::ConsoleType == 1)
Devices[SPIDevice_TSC] = new DSi_TSC(this);
else
Devices[SPIDevice_TSC] = new TSC(this);
} }
SPIHost::~SPIHost() SPIHost::~SPIHost()
@ -553,14 +557,6 @@ void SPIHost::Reset()
{ {
Cnt = 0; Cnt = 0;
if (Devices[SPIDevice_TSC])
delete Devices[SPIDevice_TSC];
if (NDS::ConsoleType == 1)
Devices[SPIDevice_TSC] = new DSi_TSC(this);
else
Devices[SPIDevice_TSC] = new TSC(this);
for (int i = 0; i < SPIDevice_MAX; i++) for (int i = 0; i < SPIDevice_MAX; i++)
{ {
Devices[i]->Reset(); Devices[i]->Reset();

View File

@ -32,12 +32,10 @@ using Platform::LogLevel;
// * capture addition modes, overflow bugs // * capture addition modes, overflow bugs
// * channel hold // * channel hold
namespace SPU
{
const s8 ADPCMIndexTable[8] = {-1, -1, -1, -1, 2, 4, 6, 8}; const s8 SPUChannel::ADPCMIndexTable[8] = {-1, -1, -1, -1, 2, 4, 6, 8};
const u16 ADPCMTable[89] = const u16 SPUChannel::ADPCMTable[89] =
{ {
0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E, 0x0007, 0x0008, 0x0009, 0x000A, 0x000B, 0x000C, 0x000D, 0x000E,
0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F, 0x0010, 0x0011, 0x0013, 0x0015, 0x0017, 0x0019, 0x001C, 0x001F,
@ -53,7 +51,7 @@ const u16 ADPCMTable[89] =
0x7FFF 0x7FFF
}; };
const s16 PSGTable[8][8] = const s16 SPUChannel::PSGTable[8][8] =
{ {
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF}, {-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF},
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF}, {-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, 0x7FFF, 0x7FFF},
@ -65,76 +63,63 @@ const s16 PSGTable[8][8] =
{-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF} {-0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF, -0x7FFF}
}; };
// audio interpolation is an improvement upon the original hardware s16 SPUChannel::InterpCos[0x100];
// (which performs no interpolation) s16 SPUChannel::InterpCubic[0x100][4];
int InterpType; bool SPUChannel::InterpInited = false;
s16 InterpCos[0x100];
s16 InterpCubic[0x100][4];
const u32 OutputBufferSize = 2*2048;
s16 OutputBackbuffer[2 * OutputBufferSize];
u32 OutputBackbufferWritePosition;
s16 OutputFrontBuffer[2 * OutputBufferSize];
u32 OutputFrontBufferWritePosition;
u32 OutputFrontBufferReadPosition;
Platform::Mutex* AudioLock;
u16 Cnt;
u8 MasterVolume;
u16 Bias;
bool ApplyBias;
bool Degrade10Bit;
Channel* Channels[16];
CaptureUnit* Capture[2];
bool Init() SPU::SPU()
{ {
NDS::RegisterEventFunc(NDS::Event_SPU, 0, Mix); NDS::RegisterEventFunc(NDS::Event_SPU, 0, MemberEventFunc(SPU, Mix));
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
Channels[i] = new Channel(i); Channels[i] = new SPUChannel(i);
Capture[0] = new CaptureUnit(0); Capture[0] = new SPUCaptureUnit(0);
Capture[1] = new CaptureUnit(1); Capture[1] = new SPUCaptureUnit(1);
AudioLock = Platform::Mutex_Create(); AudioLock = Platform::Mutex_Create();
InterpType = 0;
ApplyBias = true; ApplyBias = true;
Degrade10Bit = false; Degrade10Bit = false;
// generate interpolation tables memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2);
// values are 1:1:14 fixed-point
float m_pi = std::acos(-1.0f); OutputBackbufferWritePosition = 0;
for (int i = 0; i < 0x100; i++) OutputFrontBufferReadPosition = 0;
OutputFrontBufferWritePosition = 0;
if (!SPUChannel::InterpInited)
{ {
float ratio = (i * m_pi) / 255.0f; // generate interpolation tables
ratio = 1.0f - std::cos(ratio); // values are 1:1:14 fixed-point
InterpCos[i] = (s16)(ratio * 0x2000); float m_pi = std::acos(-1.0f);
for (int i = 0; i < 0x100; i++)
{
float ratio = (i * m_pi) / 255.0f;
ratio = 1.0f - std::cos(ratio);
SPUChannel::InterpCos[i] = (s16)(ratio * 0x2000);
}
for (int i = 0; i < 0x100; i++)
{
s32 i1 = i << 6;
s32 i2 = (i * i) >> 2;
s32 i3 = (i * i * i) >> 10;
SPUChannel::InterpCubic[i][0] = -i3 + 2*i2 - i1;
SPUChannel::InterpCubic[i][1] = i3 - 2*i2 + 0x4000;
SPUChannel::InterpCubic[i][2] = -i3 + i2 + i1;
SPUChannel::InterpCubic[i][3] = i3 - i2;
}
SPUChannel::InterpInited = true;
} }
for (int i = 0; i < 0x100; i++)
{
s32 i1 = i << 6;
s32 i2 = (i * i) >> 2;
s32 i3 = (i * i * i) >> 10;
InterpCubic[i][0] = -i3 + 2*i2 - i1;
InterpCubic[i][1] = i3 - 2*i2 + 0x4000;
InterpCubic[i][2] = -i3 + i2 + i1;
InterpCubic[i][3] = i3 - i2;
}
return true;
} }
void DeInit() SPU::~SPU()
{ {
for (int i = 0; i < 16; i++) for (int i = 0; i < 16; i++)
{ {
@ -153,7 +138,7 @@ void DeInit()
NDS::UnregisterEventFunc(NDS::Event_SPU, 0); NDS::UnregisterEventFunc(NDS::Event_SPU, 0);
} }
void Reset() void SPU::Reset()
{ {
InitOutput(); InitOutput();
@ -170,7 +155,7 @@ void Reset()
NDS::ScheduleEvent(NDS::Event_SPU, false, 1024, 0, 0); NDS::ScheduleEvent(NDS::Event_SPU, false, 1024, 0, 0);
} }
void Stop() void SPU::Stop()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2); memset(OutputFrontBuffer, 0, 2*OutputBufferSize*2);
@ -181,7 +166,7 @@ void Stop()
Platform::Mutex_Unlock(AudioLock); Platform::Mutex_Unlock(AudioLock);
} }
void DoSavestate(Savestate* file) void SPU::DoSavestate(Savestate* file)
{ {
file->Section("SPU."); file->Section("SPU.");
@ -197,43 +182,46 @@ void DoSavestate(Savestate* file)
} }
void SetPowerCnt(u32 val) void SPU::SetPowerCnt(u32 val)
{ {
// TODO // TODO
} }
void SetInterpolation(int type) void SPU::SetInterpolation(int type)
{ {
InterpType = type; for (int i = 0; i < 16; i++)
Channels[i]->InterpType = type;
} }
void SetBias(u16 bias) void SPU::SetBias(u16 bias)
{ {
Bias = bias; Bias = bias;
} }
void SetApplyBias(bool enable) void SPU::SetApplyBias(bool enable)
{ {
ApplyBias = enable; ApplyBias = enable;
} }
void SetDegrade10Bit(bool enable) void SPU::SetDegrade10Bit(bool enable)
{ {
Degrade10Bit = enable; Degrade10Bit = enable;
} }
Channel::Channel(u32 num) SPUChannel::SPUChannel(u32 num)
{ {
Num = num; Num = num;
InterpType = 0;
} }
Channel::~Channel() SPUChannel::~SPUChannel()
{ {
} }
void Channel::Reset() void SPUChannel::Reset()
{ {
if (NDS::ConsoleType == 1) if (NDS::ConsoleType == 1)
BusRead32 = DSi::ARM7Read32; BusRead32 = DSi::ARM7Read32;
@ -257,7 +245,7 @@ void Channel::Reset()
FIFOLevel = 0; FIFOLevel = 0;
} }
void Channel::DoSavestate(Savestate* file) void SPUChannel::DoSavestate(Savestate* file)
{ {
file->Var32(&Cnt); file->Var32(&Cnt);
file->Var32(&SrcAddr); file->Var32(&SrcAddr);
@ -289,7 +277,7 @@ void Channel::DoSavestate(Savestate* file)
file->VarArray(FIFO, sizeof(FIFO)); file->VarArray(FIFO, sizeof(FIFO));
} }
void Channel::FIFO_BufferData() void SPUChannel::FIFO_BufferData()
{ {
u32 totallen = LoopPos + Length; u32 totallen = LoopPos + Length;
@ -330,7 +318,7 @@ void Channel::FIFO_BufferData()
} }
template<typename T> template<typename T>
T Channel::FIFO_ReadData() T SPUChannel::FIFO_ReadData()
{ {
T ret = *(T*)&((u8*)FIFO)[FIFOReadPos]; T ret = *(T*)&((u8*)FIFO)[FIFOReadPos];
@ -344,7 +332,7 @@ T Channel::FIFO_ReadData()
return ret; return ret;
} }
void Channel::Start() void SPUChannel::Start()
{ {
Timer = TimerReload; Timer = TimerReload;
@ -372,7 +360,7 @@ void Channel::Start()
} }
} }
void Channel::NextSample_PCM8() void SPUChannel::NextSample_PCM8()
{ {
Pos++; Pos++;
if (Pos < 0) return; if (Pos < 0) return;
@ -395,7 +383,7 @@ void Channel::NextSample_PCM8()
CurSample = val << 8; CurSample = val << 8;
} }
void Channel::NextSample_PCM16() void SPUChannel::NextSample_PCM16()
{ {
Pos++; Pos++;
if (Pos < 0) return; if (Pos < 0) return;
@ -418,7 +406,7 @@ void Channel::NextSample_PCM16()
CurSample = val; CurSample = val;
} }
void Channel::NextSample_ADPCM() void SPUChannel::NextSample_ADPCM()
{ {
Pos++; Pos++;
if (Pos < 8) if (Pos < 8)
@ -493,13 +481,13 @@ void Channel::NextSample_ADPCM()
CurSample = ADPCMVal; CurSample = ADPCMVal;
} }
void Channel::NextSample_PSG() void SPUChannel::NextSample_PSG()
{ {
Pos++; Pos++;
CurSample = PSGTable[(Cnt >> 24) & 0x7][Pos & 0x7]; CurSample = PSGTable[(Cnt >> 24) & 0x7][Pos & 0x7];
} }
void Channel::NextSample_Noise() void SPUChannel::NextSample_Noise()
{ {
if (NoiseVal & 0x1) if (NoiseVal & 0x1)
{ {
@ -514,7 +502,7 @@ void Channel::NextSample_Noise()
} }
template<u32 type> template<u32 type>
s32 Channel::Run() s32 SPUChannel::Run()
{ {
if (!(Cnt & (1<<31))) return 0; if (!(Cnt & (1<<31))) return 0;
@ -586,23 +574,23 @@ s32 Channel::Run()
return val; return val;
} }
void Channel::PanOutput(s32 in, s32& left, s32& right) void SPUChannel::PanOutput(s32 in, s32& left, s32& right)
{ {
left += ((s64)in * (128-Pan)) >> 10; left += ((s64)in * (128-Pan)) >> 10;
right += ((s64)in * Pan) >> 10; right += ((s64)in * Pan) >> 10;
} }
CaptureUnit::CaptureUnit(u32 num) SPUCaptureUnit::SPUCaptureUnit(u32 num)
{ {
Num = num; Num = num;
} }
CaptureUnit::~CaptureUnit() SPUCaptureUnit::~SPUCaptureUnit()
{ {
} }
void CaptureUnit::Reset() void SPUCaptureUnit::Reset()
{ {
if (NDS::ConsoleType == 1) if (NDS::ConsoleType == 1)
BusWrite32 = DSi::ARM7Write32; BusWrite32 = DSi::ARM7Write32;
@ -623,7 +611,7 @@ void CaptureUnit::Reset()
FIFOLevel = 0; FIFOLevel = 0;
} }
void CaptureUnit::DoSavestate(Savestate* file) void SPUCaptureUnit::DoSavestate(Savestate* file)
{ {
file->Var8(&Cnt); file->Var8(&Cnt);
file->Var32(&DstAddr); file->Var32(&DstAddr);
@ -640,7 +628,7 @@ void CaptureUnit::DoSavestate(Savestate* file)
file->VarArray(FIFO, 4*4); file->VarArray(FIFO, 4*4);
} }
void CaptureUnit::FIFO_FlushData() void SPUCaptureUnit::FIFO_FlushData()
{ {
for (u32 i = 0; i < 4; i++) for (u32 i = 0; i < 4; i++)
{ {
@ -660,7 +648,7 @@ void CaptureUnit::FIFO_FlushData()
} }
template<typename T> template<typename T>
void CaptureUnit::FIFO_WriteData(T val) void SPUCaptureUnit::FIFO_WriteData(T val)
{ {
*(T*)&((u8*)FIFO)[FIFOWritePos] = val; *(T*)&((u8*)FIFO)[FIFOWritePos] = val;
@ -672,7 +660,7 @@ void CaptureUnit::FIFO_WriteData(T val)
FIFO_FlushData(); FIFO_FlushData();
} }
void CaptureUnit::Run(s32 sample) void SPUCaptureUnit::Run(s32 sample)
{ {
Timer += 512; Timer += 512;
@ -725,7 +713,7 @@ void CaptureUnit::Run(s32 sample)
} }
void Mix(u32 dummy) void SPU::Mix(u32 dummy)
{ {
s32 left = 0, right = 0; s32 left = 0, right = 0;
s32 leftoutput = 0, rightoutput = 0; s32 leftoutput = 0, rightoutput = 0;
@ -746,7 +734,7 @@ void Mix(u32 dummy)
for (int i = 4; i < 16; i++) for (int i = 4; i < 16; i++)
{ {
Channel* chan = Channels[i]; SPUChannel* chan = Channels[i];
s32 channel = chan->DoRun(); s32 channel = chan->DoRun();
chan->PanOutput(channel, left, right); chan->PanOutput(channel, left, right);
@ -871,7 +859,7 @@ void Mix(u32 dummy)
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024, 0, 0); NDS::ScheduleEvent(NDS::Event_SPU, true, 1024, 0, 0);
} }
void TransferOutput() void SPU::TransferOutput()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
for (u32 i = 0; i < OutputBackbufferWritePosition; i += 2) for (u32 i = 0; i < OutputBackbufferWritePosition; i += 2)
@ -889,10 +877,10 @@ void TransferOutput()
} }
} }
OutputBackbufferWritePosition = 0; OutputBackbufferWritePosition = 0;
Platform::Mutex_Unlock(AudioLock); Platform::Mutex_Unlock(AudioLock);;
} }
void TrimOutput() void SPU::TrimOutput()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
const int halflimit = (OutputBufferSize / 2); const int halflimit = (OutputBufferSize / 2);
@ -904,7 +892,7 @@ void TrimOutput()
Platform::Mutex_Unlock(AudioLock); Platform::Mutex_Unlock(AudioLock);
} }
void DrainOutput() void SPU::DrainOutput()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
OutputFrontBufferWritePosition = 0; OutputFrontBufferWritePosition = 0;
@ -912,7 +900,7 @@ void DrainOutput()
Platform::Mutex_Unlock(AudioLock); Platform::Mutex_Unlock(AudioLock);
} }
void InitOutput() void SPU::InitOutput()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
memset(OutputBackbuffer, 0, 2*OutputBufferSize*2); memset(OutputBackbuffer, 0, 2*OutputBufferSize*2);
@ -922,7 +910,7 @@ void InitOutput()
Platform::Mutex_Unlock(AudioLock); Platform::Mutex_Unlock(AudioLock);
} }
int GetOutputSize() int SPU::GetOutputSize()
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
@ -938,7 +926,7 @@ int GetOutputSize()
return ret; return ret;
} }
void Sync(bool wait) void SPU::Sync(bool wait)
{ {
// this function is currently not used anywhere // this function is currently not used anywhere
// depending on the usage context the thread safety measures could be made // depending on the usage context the thread safety measures could be made
@ -968,7 +956,7 @@ void Sync(bool wait)
} }
} }
int ReadOutput(s16* data, int samples) int SPU::ReadOutput(s16* data, int samples)
{ {
Platform::Mutex_Lock(AudioLock); Platform::Mutex_Lock(AudioLock);
if (OutputFrontBufferReadPosition == OutputFrontBufferWritePosition) if (OutputFrontBufferReadPosition == OutputFrontBufferWritePosition)
@ -997,11 +985,11 @@ int ReadOutput(s16* data, int samples)
} }
u8 Read8(u32 addr) u8 SPU::Read8(u32 addr)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1027,11 +1015,11 @@ u8 Read8(u32 addr)
return 0; return 0;
} }
u16 Read16(u32 addr) u16 SPU::Read16(u32 addr)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1054,11 +1042,11 @@ u16 Read16(u32 addr)
return 0; return 0;
} }
u32 Read32(u32 addr) u32 SPU::Read32(u32 addr)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1083,11 +1071,11 @@ u32 Read32(u32 addr)
return 0; return 0;
} }
void Write8(u32 addr, u8 val) void SPU::Write8(u32 addr, u8 val)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1124,11 +1112,11 @@ void Write8(u32 addr, u8 val)
Log(LogLevel::Warn, "unknown SPU write8 %08X %02X\n", addr, val); Log(LogLevel::Warn, "unknown SPU write8 %08X %02X\n", addr, val);
} }
void Write16(u32 addr, u16 val) void SPU::Write16(u32 addr, u16 val)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1173,11 +1161,11 @@ void Write16(u32 addr, u16 val)
Log(LogLevel::Warn, "unknown SPU write16 %08X %04X\n", addr, val); Log(LogLevel::Warn, "unknown SPU write16 %08X %04X\n", addr, val);
} }
void Write32(u32 addr, u32 val) void SPU::Write32(u32 addr, u32 val)
{ {
if (addr < 0x04000500) if (addr < 0x04000500)
{ {
Channel* chan = Channels[(addr >> 4) & 0xF]; SPUChannel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF) switch (addr & 0xF)
{ {
@ -1220,5 +1208,3 @@ void Write32(u32 addr, u32 val)
} }
} }
} }
}

118
src/SPU.h
View File

@ -20,51 +20,30 @@
#define SPU_H #define SPU_H
#include "Savestate.h" #include "Savestate.h"
#include "Platform.h"
namespace SPU class SPU;
{
bool Init(); class SPUChannel
void DeInit();
void Reset();
void Stop();
void DoSavestate(Savestate* file);
void SetPowerCnt(u32 val);
// 0=none 1=linear 2=cosine 3=cubic
void SetInterpolation(int type);
void SetBias(u16 bias);
void SetDegrade10Bit(bool enable);
void SetApplyBias(bool enable);
void Mix(u32 dummy);
void TrimOutput();
void DrainOutput();
void InitOutput();
int GetOutputSize();
void Sync(bool wait);
int ReadOutput(s16* data, int samples);
void TransferOutput();
u8 Read8(u32 addr);
u16 Read16(u32 addr);
u32 Read32(u32 addr);
void Write8(u32 addr, u8 val);
void Write16(u32 addr, u16 val);
void Write32(u32 addr, u32 val);
class Channel
{ {
public: public:
Channel(u32 num); SPUChannel(u32 num);
~Channel(); ~SPUChannel();
void Reset(); void Reset();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
static const s8 ADPCMIndexTable[8];
static const u16 ADPCMTable[89];
static const s16 PSGTable[8][8];
static s16 InterpCos[0x100];
static s16 InterpCubic[0x100][4];
static bool InterpInited;
// audio interpolation is an improvement upon the original hardware
// (which performs no interpolation)
int InterpType;
u32 Num; u32 Num;
u32 Cnt; u32 Cnt;
@ -164,11 +143,11 @@ private:
u32 (*BusRead32)(u32 addr); u32 (*BusRead32)(u32 addr);
}; };
class CaptureUnit class SPUCaptureUnit
{ {
public: public:
CaptureUnit(u32 num); SPUCaptureUnit(u32 num);
~CaptureUnit(); ~SPUCaptureUnit();
void Reset(); void Reset();
void DoSavestate(Savestate* file); void DoSavestate(Savestate* file);
@ -221,6 +200,61 @@ private:
void (*BusWrite32)(u32 addr, u32 val); void (*BusWrite32)(u32 addr, u32 val);
}; };
} class SPU
{
public:
SPU();
~SPU();
void Reset();
void DoSavestate(Savestate* file);
void Stop();
void SetPowerCnt(u32 val);
// 0=none 1=linear 2=cosine 3=cubic
void SetInterpolation(int type);
void SetBias(u16 bias);
void SetDegrade10Bit(bool enable);
void SetApplyBias(bool enable);
void Mix(u32 dummy);
void TrimOutput();
void DrainOutput();
void InitOutput();
int GetOutputSize();
void Sync(bool wait);
int ReadOutput(s16* data, int samples);
void TransferOutput();
u8 Read8(u32 addr);
u16 Read16(u32 addr);
u32 Read32(u32 addr);
void Write8(u32 addr, u8 val);
void Write16(u32 addr, u16 val);
void Write32(u32 addr, u32 val);
private:
static const u32 OutputBufferSize = 2*2048;
s16 OutputBackbuffer[2 * OutputBufferSize];
u32 OutputBackbufferWritePosition;
s16 OutputFrontBuffer[2 * OutputBufferSize];
u32 OutputFrontBufferWritePosition;
u32 OutputFrontBufferReadPosition;
Platform::Mutex* AudioLock;
u16 Cnt;
u8 MasterVolume;
u16 Bias;
bool ApplyBias;
bool Degrade10Bit;
SPUChannel* Channels[16];
SPUCaptureUnit* Capture[2];
};
#endif // SPU_H #endif // SPU_H

View File

@ -22,6 +22,7 @@
#include "FrontendUtil.h" #include "FrontendUtil.h"
#include "Config.h" #include "Config.h"
#include "NDS.h"
#include "SPU.h" #include "SPU.h"
#include "Platform.h" #include "Platform.h"
#include "Input.h" #include "Input.h"
@ -54,7 +55,7 @@ void AudioCallback(void* data, Uint8* stream, int len)
int num_in; int num_in;
SDL_LockMutex(audioSyncLock); SDL_LockMutex(audioSyncLock);
num_in = SPU::ReadOutput(buf_in, len_in); num_in = NDS::SPU->ReadOutput(buf_in, len_in);
SDL_CondSignal(audioSync); SDL_CondSignal(audioSync);
SDL_UnlockMutex(audioSyncLock); SDL_UnlockMutex(audioSyncLock);
@ -352,7 +353,7 @@ void AudioSync()
if (audioDevice) if (audioDevice)
{ {
SDL_LockMutex(audioSyncLock); SDL_LockMutex(audioSyncLock);
while (SPU::GetOutputSize() > 1024) while (NDS::SPU->GetOutputSize() > 1024)
{ {
int ret = SDL_CondWaitTimeout(audioSync, audioSyncLock, 500); int ret = SDL_CondWaitTimeout(audioSync, audioSyncLock, 500);
if (ret == SDL_MUTEX_TIMEDOUT) break; if (ret == SDL_MUTEX_TIMEDOUT) break;
@ -365,7 +366,7 @@ void UpdateSettings()
{ {
MicClose(); MicClose();
SPU::SetInterpolation(Config::AudioInterp); NDS::SPU->SetInterpolation(Config::AudioInterp);
SetupMicInputData(); SetupMicInputData();
MicOpen(); MicOpen();

View File

@ -342,7 +342,7 @@ void EmuThread::run()
GPU::InitRenderer(videoRenderer); GPU::InitRenderer(videoRenderer);
GPU::SetRenderSettings(videoRenderer, videoSettings); GPU::SetRenderSettings(videoRenderer, videoSettings);
SPU::SetInterpolation(Config::AudioInterp); NDS::SPU->SetInterpolation(Config::AudioInterp);
Input::Init(); Input::Init();
@ -2942,12 +2942,12 @@ void MainWindow::onPathSettingsFinished(int res)
void MainWindow::onUpdateAudioSettings() void MainWindow::onUpdateAudioSettings()
{ {
SPU::SetInterpolation(Config::AudioInterp); NDS::SPU->SetInterpolation(Config::AudioInterp);
if (Config::AudioBitDepth == 0) if (Config::AudioBitDepth == 0)
SPU::SetDegrade10Bit(NDS::ConsoleType == 0); NDS::SPU->SetDegrade10Bit(NDS::ConsoleType == 0);
else else
SPU::SetDegrade10Bit(Config::AudioBitDepth == 1); NDS::SPU->SetDegrade10Bit(Config::AudioBitDepth == 1);
} }
void MainWindow::onAudioSettingsFinished(int res) void MainWindow::onAudioSettingsFinished(int res)