start SPU work
This commit is contained in:
parent
28cddadfbc
commit
8d66beba6b
47
src/NDS.cpp
47
src/NDS.cpp
|
@ -25,6 +25,7 @@
|
|||
#include "DMA.h"
|
||||
#include "FIFO.h"
|
||||
#include "GPU.h"
|
||||
#include "SPU.h"
|
||||
#include "SPI.h"
|
||||
#include "RTC.h"
|
||||
#include "Wifi.h"
|
||||
|
@ -37,11 +38,6 @@ namespace NDS
|
|||
// * stick all the variables in a big structure?
|
||||
// would make it easier to deal with savestates
|
||||
|
||||
/*SchedEvent SchedBuffer[SCHED_BUF_LEN];
|
||||
SchedEvent* SchedQueue;
|
||||
|
||||
bool NeedReschedule;*/
|
||||
|
||||
ARM* ARM9;
|
||||
ARM* ARM7;
|
||||
|
||||
|
@ -108,8 +104,6 @@ u32 SqrtRes;
|
|||
|
||||
u32 KeyInput;
|
||||
|
||||
u16 _soundbias; // temp
|
||||
|
||||
bool Running;
|
||||
|
||||
|
||||
|
@ -132,6 +126,7 @@ bool Init()
|
|||
|
||||
if (!NDSCart::Init()) return false;
|
||||
if (!GPU::Init()) return false;
|
||||
if (!SPU::Init()) return false;
|
||||
if (!SPI::Init()) return false;
|
||||
if (!RTC::Init()) return false;
|
||||
|
||||
|
@ -151,6 +146,7 @@ void DeInit()
|
|||
|
||||
NDSCart::DeInit();
|
||||
GPU::DeInit();
|
||||
SPU::DeInit();
|
||||
SPI::DeInit();
|
||||
RTC::DeInit();
|
||||
}
|
||||
|
@ -300,14 +296,6 @@ void Reset()
|
|||
for (i = 0; i < 8; i++) DMAs[i]->Reset();
|
||||
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));
|
||||
SchedListMask = 0;
|
||||
|
||||
|
@ -319,7 +307,12 @@ void Reset()
|
|||
|
||||
KeyInput = 0x007F03FF;
|
||||
|
||||
_soundbias = 0;
|
||||
NDSCart::Reset();
|
||||
GPU::Reset();
|
||||
SPU::Reset();
|
||||
SPI::Reset();
|
||||
RTC::Reset();
|
||||
Wifi::Reset();
|
||||
}
|
||||
|
||||
void LoadROM(const char* path, bool direct)
|
||||
|
@ -1629,7 +1622,6 @@ void ARM9IOWrite16(u32 addr, u16 val)
|
|||
{
|
||||
SetIRQ(1, IRQ_IPCSync);
|
||||
}
|
||||
//CompensateARM7();
|
||||
return;
|
||||
|
||||
case 0x04000184:
|
||||
|
@ -1901,8 +1893,7 @@ u8 ARM7IORead8(u32 addr)
|
|||
|
||||
if (addr >= 0x04000400 && addr < 0x04000520)
|
||||
{
|
||||
// sound I/O
|
||||
return 0;
|
||||
return SPU::Read8(addr);
|
||||
}
|
||||
|
||||
printf("unknown ARM7 IO read8 %08X\n", addr);
|
||||
|
@ -1972,14 +1963,11 @@ u16 ARM7IORead16(u32 addr)
|
|||
case 0x04000300: return PostFlag7;
|
||||
case 0x04000304: return PowerControl7;
|
||||
case 0x04000308: return ARM7BIOSProt;
|
||||
|
||||
case 0x04000504: return _soundbias;
|
||||
}
|
||||
|
||||
if (addr >= 0x04000400 && addr < 0x04000520)
|
||||
{
|
||||
// sound I/O
|
||||
return 0;
|
||||
return SPU::Read16(addr);
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
// sound I/O
|
||||
return 0;
|
||||
return SPU::Read32(addr);
|
||||
}
|
||||
|
||||
printf("unknown ARM7 IO read32 %08X\n", addr);
|
||||
|
@ -2116,7 +2103,7 @@ void ARM7IOWrite8(u32 addr, u8 val)
|
|||
|
||||
if (addr >= 0x04000400 && addr < 0x04000520)
|
||||
{
|
||||
// sound I/O
|
||||
SPU::Write8(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2228,15 +2215,11 @@ void ARM7IOWrite16(u32 addr, u16 val)
|
|||
if (ARM7BIOSProt == 0)
|
||||
ARM7BIOSProt = val;
|
||||
return;
|
||||
|
||||
case 0x04000504: // removeme
|
||||
_soundbias = val & 0x3FF;
|
||||
return;
|
||||
}
|
||||
|
||||
if (addr >= 0x04000400 && addr < 0x04000520)
|
||||
{
|
||||
// sound I/O
|
||||
SPU::Write16(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
@ -2326,7 +2309,7 @@ void ARM7IOWrite32(u32 addr, u32 val)
|
|||
|
||||
if (addr >= 0x04000400 && addr < 0x04000520)
|
||||
{
|
||||
// sound I/O
|
||||
SPU::Write32(addr, val);
|
||||
return;
|
||||
}
|
||||
|
||||
|
|
28
src/NDS.h
28
src/NDS.h
|
@ -24,30 +24,11 @@
|
|||
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
|
||||
{
|
||||
Event_LCD = 0,
|
||||
|
||||
/*Event_Timer9_0,
|
||||
Event_Timer9_1,
|
||||
Event_Timer9_2,
|
||||
Event_Timer9_3,
|
||||
Event_Timer7_0,
|
||||
Event_Timer7_1,
|
||||
Event_Timer7_2,
|
||||
Event_Timer7_3,*/
|
||||
Event_SPU,
|
||||
|
||||
Event_MAX
|
||||
};
|
||||
|
@ -95,7 +76,6 @@ typedef struct
|
|||
u16 Cnt;
|
||||
u32 Counter;
|
||||
u32 CycleShift;
|
||||
//SchedEvent* Event;
|
||||
|
||||
} Timer;
|
||||
|
||||
|
@ -127,15 +107,9 @@ void ReleaseKey(u32 key);
|
|||
void TouchScreen(u16 x, u16 y);
|
||||
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 CancelEvent(u32 id);
|
||||
|
||||
// DO NOT CALL FROM ARM7!!
|
||||
void CompensateARM7();
|
||||
|
||||
void debug(u32 p);
|
||||
|
||||
void Halt();
|
||||
|
|
265
src/SPU.cpp
265
src/SPU.cpp
|
@ -25,38 +25,269 @@
|
|||
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()
|
||||
{
|
||||
/*SDL_AudioSpec whatIwant, whatIget;
|
||||
|
||||
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;
|
||||
}*/
|
||||
for (int i = 0; i < 16; i++)
|
||||
Channels[i] = new Channel(i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void DeInit()
|
||||
{
|
||||
//if (device) SDL_CloseAudioDevice(device);
|
||||
for (int i = 0; i < 16; i++)
|
||||
delete Channels[i];
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
}
|
||||
|
|
35
src/SPU.h
35
src/SPU.h
|
@ -26,6 +26,41 @@ bool Init();
|
|||
void DeInit();
|
||||
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
|
||||
|
|
|
@ -22,6 +22,7 @@
|
|||
#include "../Config.h"
|
||||
#include "../NDS.h"
|
||||
#include "../GPU.h"
|
||||
#include "../SPU.h"
|
||||
|
||||
#include "InputConfig.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()
|
||||
{
|
||||
emustatus = 3;
|
||||
|
@ -344,6 +350,23 @@ wxThread::ExitCode EmuThread::Entry()
|
|||
botdst.x = 0; botdst.y = 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;
|
||||
axismask = 0;
|
||||
|
||||
|
@ -433,6 +456,8 @@ wxThread::ExitCode EmuThread::Entry()
|
|||
|
||||
emupaused = true;
|
||||
|
||||
if (audio) SDL_CloseAudioDevice(audio);
|
||||
|
||||
SDL_DestroyTexture(sdltex);
|
||||
SDL_DestroyRenderer(sdlrend);
|
||||
SDL_DestroyWindow(sdlwin);
|
||||
|
|
|
@ -105,6 +105,8 @@ protected:
|
|||
SDL_Rect topsrc, topdst;
|
||||
SDL_Rect botsrc, botdst;
|
||||
|
||||
SDL_AudioDeviceID audio;
|
||||
|
||||
bool Touching;
|
||||
int txoffset, tyoffset;
|
||||
|
||||
|
|
Loading…
Reference in New Issue