start SPU work

This commit is contained in:
StapleButter 2017-04-06 19:44:34 +02:00
parent 28cddadfbc
commit 8d66beba6b
6 changed files with 335 additions and 85 deletions

View File

@ -25,6 +25,7 @@
#include "DMA.h" #include "DMA.h"
#include "FIFO.h" #include "FIFO.h"
#include "GPU.h" #include "GPU.h"
#include "SPU.h"
#include "SPI.h" #include "SPI.h"
#include "RTC.h" #include "RTC.h"
#include "Wifi.h" #include "Wifi.h"
@ -37,11 +38,6 @@ namespace NDS
// * stick all the variables in a big structure? // * stick all the variables in a big structure?
// would make it easier to deal with savestates // would make it easier to deal with savestates
/*SchedEvent SchedBuffer[SCHED_BUF_LEN];
SchedEvent* SchedQueue;
bool NeedReschedule;*/
ARM* ARM9; ARM* ARM9;
ARM* ARM7; ARM* ARM7;
@ -108,8 +104,6 @@ u32 SqrtRes;
u32 KeyInput; u32 KeyInput;
u16 _soundbias; // temp
bool Running; bool Running;
@ -132,6 +126,7 @@ bool Init()
if (!NDSCart::Init()) return false; if (!NDSCart::Init()) return false;
if (!GPU::Init()) return false; if (!GPU::Init()) return false;
if (!SPU::Init()) return false;
if (!SPI::Init()) return false; if (!SPI::Init()) return false;
if (!RTC::Init()) return false; if (!RTC::Init()) return false;
@ -151,6 +146,7 @@ void DeInit()
NDSCart::DeInit(); NDSCart::DeInit();
GPU::DeInit(); GPU::DeInit();
SPU::DeInit();
SPI::DeInit(); SPI::DeInit();
RTC::DeInit(); RTC::DeInit();
} }
@ -300,14 +296,6 @@ void Reset()
for (i = 0; i < 8; i++) DMAs[i]->Reset(); for (i = 0; i < 8; i++) DMAs[i]->Reset();
memset(DMA9Fill, 0, 4*4); memset(DMA9Fill, 0, 4*4);
NDSCart::Reset();
GPU::Reset();
SPI::Reset();
RTC::Reset();
Wifi::Reset();
// memset(SchedBuffer, 0, sizeof(SchedEvent)*SCHED_BUF_LEN);
// SchedQueue = NULL;
memset(SchedList, 0, sizeof(SchedList)); memset(SchedList, 0, sizeof(SchedList));
SchedListMask = 0; SchedListMask = 0;
@ -319,7 +307,12 @@ void Reset()
KeyInput = 0x007F03FF; KeyInput = 0x007F03FF;
_soundbias = 0; NDSCart::Reset();
GPU::Reset();
SPU::Reset();
SPI::Reset();
RTC::Reset();
Wifi::Reset();
} }
void LoadROM(const char* path, bool direct) void LoadROM(const char* path, bool direct)
@ -1629,7 +1622,6 @@ void ARM9IOWrite16(u32 addr, u16 val)
{ {
SetIRQ(1, IRQ_IPCSync); SetIRQ(1, IRQ_IPCSync);
} }
//CompensateARM7();
return; return;
case 0x04000184: case 0x04000184:
@ -1901,8 +1893,7 @@ u8 ARM7IORead8(u32 addr)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O return SPU::Read8(addr);
return 0;
} }
printf("unknown ARM7 IO read8 %08X\n", addr); printf("unknown ARM7 IO read8 %08X\n", addr);
@ -1972,14 +1963,11 @@ u16 ARM7IORead16(u32 addr)
case 0x04000300: return PostFlag7; case 0x04000300: return PostFlag7;
case 0x04000304: return PowerControl7; case 0x04000304: return PowerControl7;
case 0x04000308: return ARM7BIOSProt; case 0x04000308: return ARM7BIOSProt;
case 0x04000504: return _soundbias;
} }
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O return SPU::Read16(addr);
return 0;
} }
printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM9->R[15]); printf("unknown ARM7 IO read16 %08X %08X\n", addr, ARM9->R[15]);
@ -2057,8 +2045,7 @@ u32 ARM7IORead32(u32 addr)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O return SPU::Read32(addr);
return 0;
} }
printf("unknown ARM7 IO read32 %08X\n", addr); printf("unknown ARM7 IO read32 %08X\n", addr);
@ -2116,7 +2103,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O SPU::Write8(addr, val);
return; return;
} }
@ -2228,15 +2215,11 @@ void ARM7IOWrite16(u32 addr, u16 val)
if (ARM7BIOSProt == 0) if (ARM7BIOSProt == 0)
ARM7BIOSProt = val; ARM7BIOSProt = val;
return; return;
case 0x04000504: // removeme
_soundbias = val & 0x3FF;
return;
} }
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O SPU::Write16(addr, val);
return; return;
} }
@ -2326,7 +2309,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
if (addr >= 0x04000400 && addr < 0x04000520) if (addr >= 0x04000400 && addr < 0x04000520)
{ {
// sound I/O SPU::Write32(addr, val);
return; return;
} }

View File

@ -24,30 +24,11 @@
namespace NDS namespace NDS
{ {
/*#define SCHED_BUF_LEN 64
typedef struct _SchedEvent
{
u32 Delay;
void (*Func)(u32);
u32 Param;
struct _SchedEvent* PrevEvent;
struct _SchedEvent* NextEvent;
} SchedEvent;*/
enum enum
{ {
Event_LCD = 0, Event_LCD = 0,
/*Event_Timer9_0, Event_SPU,
Event_Timer9_1,
Event_Timer9_2,
Event_Timer9_3,
Event_Timer7_0,
Event_Timer7_1,
Event_Timer7_2,
Event_Timer7_3,*/
Event_MAX Event_MAX
}; };
@ -95,7 +76,6 @@ typedef struct
u16 Cnt; u16 Cnt;
u32 Counter; u32 Counter;
u32 CycleShift; u32 CycleShift;
//SchedEvent* Event;
} Timer; } Timer;
@ -127,15 +107,9 @@ void ReleaseKey(u32 key);
void TouchScreen(u16 x, u16 y); void TouchScreen(u16 x, u16 y);
void ReleaseScreen(); void ReleaseScreen();
/*SchedEvent* ScheduleEvent(s32 Delay, void (*Func)(u32), u32 Param);
void CancelEvent(SchedEvent* event);
void RunEvents(s32 cycles);*/
void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param); void ScheduleEvent(u32 id, bool periodic, s32 delay, void (*func)(u32), u32 param);
void CancelEvent(u32 id); void CancelEvent(u32 id);
// DO NOT CALL FROM ARM7!!
void CompensateARM7();
void debug(u32 p); void debug(u32 p);
void Halt(); void Halt();

View File

@ -25,38 +25,269 @@
namespace SPU namespace SPU
{ {
//SDL_AudioDeviceID device; const u32 OutputBufferSize = 2*1024;
// s16 OutputBuffer[2 * OutputBufferSize];
u32 OutputReadOffset;
u32 OutputWriteOffset;
u16 Cnt;
u8 MasterVolume;
u16 Bias;
Channel* Channels[16];
bool Init() bool Init()
{ {
/*SDL_AudioSpec whatIwant, whatIget; for (int i = 0; i < 16; i++)
Channels[i] = new Channel(i);
memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
whatIwant.freq = 32824; // 32823.6328125
whatIwant.format = AUDIO_S16LSB;
whatIwant.channels = 2;
whatIwant.samples = 2048;
whatIwant.callback = zorp;
device = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0);
if (!device)
{
printf("Audio init failed: %s\n", SDL_GetError());
return false;
}*/
return true; return true;
} }
void DeInit() void DeInit()
{ {
//if (device) SDL_CloseAudioDevice(device); for (int i = 0; i < 16; i++)
delete Channels[i];
} }
void Reset() void Reset()
{
memset(OutputBuffer, 0, 2*OutputBufferSize*2);
OutputReadOffset = 0;
OutputWriteOffset = 0;
Cnt = 0;
MasterVolume = 0;
Bias = 0;
for (int i = 0; i < 16; i++)
Channels[i]->Reset();
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*16, Mix, 16);
}
Channel::Channel(u32 num)
{ {
// //
} }
Channel::~Channel()
{
//
}
void Channel::Reset()
{
SetCnt(0);
SrcAddr = 0;
TimerReload = 0;
LoopPos = 0;
Length = 0;
}
void Mix(u32 samples)
{
//
NDS::ScheduleEvent(NDS::Event_SPU, true, 1024*16, Mix, 16);
}
void ReadOutput(s16* data, int samples)
{
for (int i = 0; i < samples; i++)
{
*data++ = OutputBuffer[OutputReadOffset];
*data++ = OutputBuffer[OutputReadOffset + 1];
if (OutputReadOffset != OutputWriteOffset)
{
OutputReadOffset += 2;
OutputReadOffset &= ((2*OutputBufferSize)-1);
}
}
}
u8 Read8(u32 addr)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: return chan->Cnt & 0xFF;
case 0x1: return (chan->Cnt >> 8) & 0xFF;
case 0x2: return (chan->Cnt >> 16) & 0xFF;
case 0x3: return chan->Cnt >> 24;
}
}
else
{
switch (addr)
{
case 0x04000500: return Cnt & 0x7F;
case 0x04000501: return Cnt >> 8;
}
}
printf("unknown SPU read8 %08X\n", addr);
return 0;
}
u16 Read16(u32 addr)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: return chan->Cnt & 0xFFFF;
case 0x2: return chan->Cnt >> 16;
}
}
else
{
switch (addr)
{
case 0x04000500: return Cnt;
case 0x04000504: return Bias;
}
}
printf("unknown SPU read16 %08X\n", addr);
return 0;
}
u32 Read32(u32 addr)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: return chan->Cnt;
}
}
else
{
switch (addr)
{
case 0x04000500: return Cnt;
case 0x04000504: return Bias;
}
}
printf("unknown SPU read32 %08X\n", addr);
return 0;
}
void Write8(u32 addr, u8 val)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: chan->SetCnt((chan->Cnt & 0xFFFFFF00) | val); return;
case 0x1: chan->SetCnt((chan->Cnt & 0xFFFF00FF) | (val << 8)); return;
case 0x2: chan->SetCnt((chan->Cnt & 0xFF00FFFF) | (val << 16)); return;
case 0x3: chan->SetCnt((chan->Cnt & 0x00FFFFFF) | (val << 24)); return;
}
}
else
{
switch (addr)
{
case 0x04000500:
Cnt = (Cnt & 0xBF00) | (val & 0x7F);
MasterVolume = Cnt & 0x7F;
if (MasterVolume == 127) MasterVolume++;
return;
case 0x04000501:
Cnt = (Cnt & 0x007F) | ((val & 0xBF) << 8);
return;
}
}
printf("unknown SPU write8 %08X %02X\n", addr, val);
}
void Write16(u32 addr, u16 val)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: chan->SetCnt((chan->Cnt & 0xFFFF0000) | val); return;
case 0x2: chan->SetCnt((chan->Cnt & 0x0000FFFF) | (val << 16)); return;
case 0x8: chan->SetTimerReload(val); return;
case 0xA: chan->SetLoopPos(val); return;
}
}
else
{
switch (addr)
{
case 0x04000500:
Cnt = val & 0xBF7F;
MasterVolume = Cnt & 0x7F;
if (MasterVolume == 127) MasterVolume++;
return;
case 0x04000504:
Bias = val & 0x3FF;
return;
}
}
printf("unknown SPU write16 %08X %04X\n", addr, val);
}
void Write32(u32 addr, u32 val)
{
if (addr < 0x04000500)
{
Channel* chan = Channels[(addr >> 4) & 0xF];
switch (addr & 0xF)
{
case 0x0: chan->SetCnt(val); return;
case 0x4: chan->SetSrcAddr(val); return;
case 0x8:
chan->SetTimerReload(val & 0xFFFF);
chan->SetLoopPos(val >> 16);
return;
case 0xC: chan->SetLength(val); return;
}
}
else
{
switch (addr)
{
case 0x04000500:
Cnt = val & 0xBF7F;
MasterVolume = Cnt & 0x7F;
if (MasterVolume == 127) MasterVolume++;
return;
case 0x04000504:
Bias = val & 0x3FF;
return;
}
}
printf("unknown SPU write32 %08X %08X\n", addr, val);
}
} }

View File

@ -26,6 +26,41 @@ bool Init();
void DeInit(); void DeInit();
void Reset(); void Reset();
void Mix(u32 samples);
void ReadOutput(s16* data, int samples);
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:
Channel(u32 num);
~Channel();
void Reset();
u32 Cnt;
u32 SrcAddr;
u16 TimerReload;
u32 LoopPos;
u32 Length;
void SetCnt(u32 val)
{
Cnt = val & 0xFF7F837F;
}
void SetSrcAddr(u32 val) { SrcAddr = val & 0x07FFFFFF; }
void SetTimerReload(u32 val) { TimerReload = val & 0xFFFF; }
void SetLoopPos(u32 val) { LoopPos = (val & 0xFFFF) << 2; }
void SetLength(u32 val) { Length = (val & 0x001FFFFF) << 2; }
};
} }
#endif // SPU_H #endif // SPU_H

View File

@ -22,6 +22,7 @@
#include "../Config.h" #include "../Config.h"
#include "../NDS.h" #include "../NDS.h"
#include "../GPU.h" #include "../GPU.h"
#include "../SPU.h"
#include "InputConfig.h" #include "InputConfig.h"
#include "EmuConfig.h" #include "EmuConfig.h"
@ -313,6 +314,11 @@ EmuThread::~EmuThread()
{ {
} }
static void AudioCallback(void* data, Uint8* stream, int len)
{
SPU::ReadOutput((s16*)stream, len>>2);
}
wxThread::ExitCode EmuThread::Entry() wxThread::ExitCode EmuThread::Entry()
{ {
emustatus = 3; emustatus = 3;
@ -344,6 +350,23 @@ wxThread::ExitCode EmuThread::Entry()
botdst.x = 0; botdst.y = 192; botdst.x = 0; botdst.y = 192;
botdst.w = 256; botdst.h = 192; botdst.w = 256; botdst.h = 192;
SDL_AudioSpec whatIwant, whatIget;
memset(&whatIwant, 0, sizeof(SDL_AudioSpec));
whatIwant.freq = 32824; // 32823.6328125
whatIwant.format = AUDIO_S16LSB;
whatIwant.channels = 2;
whatIwant.samples = 1024;
whatIwant.callback = AudioCallback;
audio = SDL_OpenAudioDevice(NULL, 0, &whatIwant, &whatIget, 0);
if (!audio)
{
printf("Audio init failed: %s\n", SDL_GetError());
}
else
{
SDL_PauseAudioDevice(audio, 0);
}
Touching = false; Touching = false;
axismask = 0; axismask = 0;
@ -433,6 +456,8 @@ wxThread::ExitCode EmuThread::Entry()
emupaused = true; emupaused = true;
if (audio) SDL_CloseAudioDevice(audio);
SDL_DestroyTexture(sdltex); SDL_DestroyTexture(sdltex);
SDL_DestroyRenderer(sdlrend); SDL_DestroyRenderer(sdlrend);
SDL_DestroyWindow(sdlwin); SDL_DestroyWindow(sdlwin);

View File

@ -105,6 +105,8 @@ protected:
SDL_Rect topsrc, topdst; SDL_Rect topsrc, topdst;
SDL_Rect botsrc, botdst; SDL_Rect botsrc, botdst;
SDL_AudioDeviceID audio;
bool Touching; bool Touching;
int txoffset, tyoffset; int txoffset, tyoffset;