diff --git a/src/DSi.cpp b/src/DSi.cpp index 1aba7d99..8ea26c5f 100644 --- a/src/DSi.cpp +++ b/src/DSi.cpp @@ -82,6 +82,7 @@ DSi_SDHost* SDIO; DSi_I2CHost* I2C; DSi_CamModule* CamModule; DSi_AES* AES; +DSi_DSP* DSP; // FIXME: these currently have no effect (and aren't stored in a savestate) // ... not that they matter all that much @@ -104,8 +105,6 @@ bool Init() NWRAM_C = new u8[NWRAMSize]; #endif - if (!DSi_DSP::Init()) return false; - NDMAs[0] = new DSi_NDMA(0, 0); NDMAs[1] = new DSi_NDMA(0, 1); NDMAs[2] = new DSi_NDMA(0, 2); @@ -121,6 +120,7 @@ bool Init() I2C = new DSi_I2CHost(); CamModule = new DSi_CamModule(); AES = new DSi_AES(); + DSP = new DSi_DSP(); return true; } @@ -137,8 +137,6 @@ void DeInit() NWRAM_C = nullptr; #endif - DSi_DSP::DeInit(); - for (int i = 0; i < 8; i++) { delete NDMAs[i]; @@ -151,6 +149,7 @@ void DeInit() delete I2C; I2C = nullptr; delete CamModule; CamModule = nullptr; delete AES; AES = nullptr; + delete DSP; DSP = nullptr; NANDImage = nullptr; // The NANDImage is cleaned up (and its underlying file closed) @@ -170,7 +169,7 @@ void Reset() I2C->Reset(); CamModule->Reset(); - DSi_DSP::Reset(); + DSP->Reset(); SDMMC->CloseHandles(); SDIO->CloseHandles(); @@ -197,7 +196,7 @@ void Reset() SCFG_MC = 0x0010 | (~((u32)(NDSCart::Cart != nullptr))&1);//0x0011; SCFG_RST = 0; - DSi_DSP::SetRstLine(false); + DSP->SetRstLine(false); GPIO_Data = 0xff; // these actually initialize to high after reset GPIO_Dir = 0x80; // enable sound out, all others input @@ -239,7 +238,7 @@ void DoSavestate(Savestate* file) { Set_SCFG_Clock9(SCFG_Clock9); Set_SCFG_MC(SCFG_MC); - DSi_DSP::SetRstLine(SCFG_RST & 0x0001); + DSP->SetRstLine(SCFG_RST & 0x0001); MBK[0][8] = 0; MBK[1][8] = 0; @@ -288,7 +287,7 @@ void DoSavestate(Savestate* file) AES->DoSavestate(file); CamModule->DoSavestate(file); - DSi_DSP::DoSavestate(file); + DSP->DoSavestate(file); I2C->DoSavestate(file); SDMMC->DoSavestate(file); SDIO->DoSavestate(file); @@ -700,7 +699,7 @@ void SoftReset() // TODO: does the DSP get reset? NWRAM doesn't, so I'm assuming no // *HOWEVER*, the bootrom (which does get rerun) does remap NWRAM, and thus // the DSP most likely gets reset - DSi_DSP::Reset(); + DSP->Reset(); SDMMC->CloseHandles(); SDIO->CloseHandles(); @@ -727,7 +726,7 @@ void SoftReset() SCFG_MC = 0x0010;//0x0011; // TODO: is this actually reset? SCFG_RST = 0; - DSi_DSP::SetRstLine(false); + DSP->SetRstLine(false); // LCD init flag @@ -2310,7 +2309,7 @@ u8 ARM9IORead8(u32 addr) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return 0; - return DSi_DSP::Read8(addr); + return DSP->Read8(addr); } return NDS::ARM9IORead8(addr); @@ -2345,7 +2344,7 @@ u16 ARM9IORead16(u32 addr) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return 0; - return DSi_DSP::Read16(addr); + return DSP->Read16(addr); } return NDS::ARM9IORead16(addr); @@ -2410,7 +2409,7 @@ u32 ARM9IORead32(u32 addr) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return 0; - return DSi_DSP::Read32(addr); + return DSP->Read32(addr); } return NDS::ARM9IORead32(addr); @@ -2434,7 +2433,7 @@ void ARM9IOWrite8(u32 addr, u8 val) if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ return; SCFG_RST = (SCFG_RST & 0xFF00) | val; - DSi_DSP::SetRstLine(val & 1); + DSP->SetRstLine(val & 1); return; case 0x04004040: @@ -2480,7 +2479,7 @@ void ARM9IOWrite8(u32 addr, u8 val) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return; - return DSi_DSP::Write8(addr, val); + return DSP->Write8(addr, val); } return NDS::ARM9IOWrite8(addr, val); @@ -2500,7 +2499,7 @@ void ARM9IOWrite16(u32 addr, u16 val) if (!(SCFG_EXT[0] & (1 << 31))) /* no access to SCFG Registers if disabled*/ return; SCFG_RST = val; - DSi_DSP::SetRstLine(val & 1); + DSP->SetRstLine(val & 1); return; case 0x04004040: @@ -2540,7 +2539,7 @@ void ARM9IOWrite16(u32 addr, u16 val) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return; - return DSi_DSP::Write16(addr, val); + return DSP->Write16(addr, val); } return NDS::ARM9IOWrite16(addr, val); @@ -2555,7 +2554,7 @@ void ARM9IOWrite32(u32 addr, u32 val) return; Set_SCFG_Clock9(val & 0xFFFF); SCFG_RST = val >> 16; - DSi_DSP::SetRstLine((val >> 16) & 1); + DSP->SetRstLine((val >> 16) & 1); break; case 0x04004008: @@ -2690,7 +2689,7 @@ void ARM9IOWrite32(u32 addr, u32 val) if ((addr & 0xFFFFFF00) == 0x04004300) { if (!(SCFG_EXT[0] & (1<<18))) return; - return DSi_DSP::Write32(addr, val); + return DSP->Write32(addr, val); } return NDS::ARM9IOWrite32(addr, val); @@ -2730,8 +2729,8 @@ u8 ARM7IORead8(u32 addr) case 0x04004D07: if (SCFG_BIOS & (1<<10)) return 0; return NANDImage->GetConsoleID() >> 56; case 0x04004D08: return 0; - case 0x4004700: return DSi_DSP::SNDExCnt; - case 0x4004701: return DSi_DSP::SNDExCnt >> 8; + case 0x4004700: return DSP->ReadSNDExCnt() & 0xFF; + case 0x4004701: return DSP->ReadSNDExCnt() >> 8; case 0x04004C00: return GPIO_Data; case 0x04004C01: return GPIO_Dir; @@ -2773,7 +2772,7 @@ u16 ARM7IORead16(u32 addr) case 0x04004D06: if (SCFG_BIOS & (1<<10)) return 0; return NANDImage->GetConsoleID() >> 48; case 0x04004D08: return 0; - case 0x4004700: return DSi_DSP::SNDExCnt; + case 0x4004700: return DSP->ReadSNDExCnt(); case 0x04004C00: return GPIO_Data | ((u16)GPIO_Dir << 8); case 0x04004C02: return GPIO_IEdgeSel | ((u16)GPIO_IE << 8); @@ -2852,7 +2851,7 @@ u32 ARM7IORead32(u32 addr) case 0x4004700: Log(LogLevel::Debug, "32-Bit SNDExCnt read? %08X\n", NDS::ARM7->R[15]); - return DSi_DSP::SNDExCnt; + return DSP->ReadSNDExCnt(); } if (addr >= 0x04004800 && addr < 0x04004A00) @@ -2905,10 +2904,10 @@ void ARM7IOWrite8(u32 addr, u8 val) case 0x04004501: I2C->WriteCnt(val); return; case 0x4004700: - DSi_DSP::WriteSNDExCnt((u16)val | (DSi_DSP::SNDExCnt & 0xFF00)); + DSP->WriteSNDExCnt((u16)val, 0xFF); return; case 0x4004701: - DSi_DSP::WriteSNDExCnt(((u16)val << 8) | (DSi_DSP::SNDExCnt & 0x00FF)); + DSP->WriteSNDExCnt(((u16)val << 8), 0xFF00); return; case 0x04004C00: @@ -3007,7 +3006,7 @@ void ARM7IOWrite16(u32 addr, u16 val) return; case 0x4004700: - DSi_DSP::WriteSNDExCnt(val); + DSP->WriteSNDExCnt(val, 0xFFFF); return; case 0x04004C00: @@ -3156,7 +3155,7 @@ void ARM7IOWrite32(u32 addr, u32 val) case 0x4004700: Log(LogLevel::Debug, "32-Bit SNDExCnt write? %08X %08X\n", val, NDS::ARM7->R[15]); - DSi_DSP::WriteSNDExCnt(val); + DSP->WriteSNDExCnt(val, 0xFFFF); return; } @@ -3204,7 +3203,7 @@ void ARM7IOWrite32(u32 addr, u32 val) if (addr >= 0x04004300 && addr <= 0x04004400) { - DSi_DSP::Write32(addr, val); + DSP->Write32(addr, val); return; } diff --git a/src/DSi.h b/src/DSi.h index 0e772f63..66a4e808 100644 --- a/src/DSi.h +++ b/src/DSi.h @@ -25,6 +25,7 @@ class DSi_I2CHost; class DSi_CamModule; class DSi_AES; +class DSi_DSP; namespace DSi_NAND { @@ -63,6 +64,7 @@ extern u32 NWRAMMask[2][3]; extern DSi_I2CHost* I2C; extern DSi_CamModule* CamModule; extern DSi_AES* AES; +extern DSi_DSP* DSP; bool Init(); void DeInit(); diff --git a/src/DSi_DSP.cpp b/src/DSi_DSP.cpp index d4747635..82a52aeb 100644 --- a/src/DSi_DSP.cpp +++ b/src/DSi_DSP.cpp @@ -27,34 +27,12 @@ using Platform::Log; using Platform::LogLevel; -namespace DSi_DSP -{ -// not sure whether to not rather put it somewhere else -u16 SNDExCnt; - -Teakra::Teakra* TeakraCore; - -bool SCFG_RST; - -u16 DSP_PADR; -u16 DSP_PCFG; -u16 DSP_PSTS; -u16 DSP_PSEM; -u16 DSP_PMASK; -u16 DSP_PCLEAR; -u16 DSP_CMD[3]; -u16 DSP_REP[3]; - -u64 DSPTimestamp; - -FIFO PDATAReadFifo/*, *PDATAWriteFifo*/; -int PDataDMALen = 0; - -constexpr u32 DataMemoryOffset = 0x20000; // from Teakra memory_interface.h +const u32 DSi_DSP::DataMemoryOffset = 0x20000; // from Teakra memory_interface.h // NOTE: ^ IS IN DSP WORDS, NOT IN BYTES! -u16 GetPSTS() + +u16 DSi_DSP::GetPSTS() { u16 r = DSP_PSTS & (1<<9); // this is the only sticky bit //r &= ~((1<<2)|(1<<7)); // we support instant resets and wrfifo xfers @@ -73,26 +51,26 @@ u16 GetPSTS() return r; } -void IrqRep0() +void DSi_DSP::IrqRep0() { if (DSP_PCFG & (1<< 9)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); } -void IrqRep1() +void DSi_DSP::IrqRep1() { if (DSP_PCFG & (1<<10)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); } -void IrqRep2() +void DSi_DSP::IrqRep2() { if (DSP_PCFG & (1<<11)) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); } -void IrqSem() +void DSi_DSP::IrqSem() { DSP_PSTS |= 1<<9; // apparently these are always fired? NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); } -u16 DSPRead16(u32 addr) +u16 DSi_DSP::DSPRead16(u32 addr) { if (!(addr & 0x40000)) { @@ -106,7 +84,7 @@ u16 DSPRead16(u32 addr) } } -void DSPWrite16(u32 addr, u16 val) +void DSi_DSP::DSPWrite16(u32 addr, u16 val) { // TODO: does the rule for overlapping NWRAM slots also apply to the DSP side? @@ -122,29 +100,32 @@ void DSPWrite16(u32 addr, u16 val) } } -void AudioCb(std::array frame) +void DSi_DSP::AudioCb(std::array frame) { // TODO } -bool Init() +DSi_DSP::DSi_DSP() { - NDS::RegisterEventFunc(NDS::Event_DSi_DSP, 0, DSPCatchUpU32); + NDS::RegisterEventFunc(NDS::Event_DSi_DSP, 0, MemberEventFunc(DSi_DSP, DSPCatchUpU32)); TeakraCore = new Teakra::Teakra(); SCFG_RST = false; - if (!TeakraCore) return false; + // ???? + //if (!TeakraCore) return false; - TeakraCore->SetRecvDataHandler(0, IrqRep0); - TeakraCore->SetRecvDataHandler(1, IrqRep1); - TeakraCore->SetRecvDataHandler(2, IrqRep2); + using namespace std::placeholders; - TeakraCore->SetSemaphoreHandler(IrqSem); + TeakraCore->SetRecvDataHandler(0, std::bind(&DSi_DSP::IrqRep0, this)); + TeakraCore->SetRecvDataHandler(1, std::bind(&DSi_DSP::IrqRep1, this)); + TeakraCore->SetRecvDataHandler(2, std::bind(&DSi_DSP::IrqRep2, this)); + + TeakraCore->SetSemaphoreHandler(std::bind(&DSi_DSP::IrqSem, this)); Teakra::SharedMemoryCallback smcb; - smcb.read16 = DSPRead16; - smcb.write16 = DSPWrite16; + smcb.read16 = std::bind(&DSi_DSP::DSPRead16, this, _1); + smcb.write16 = std::bind(&DSi_DSP::DSPWrite16, this, _1, _2); TeakraCore->SetSharedMemoryCallback(smcb); // these happen instantaneously and without too much regard for bus aribtration @@ -158,14 +139,13 @@ bool Init() cb.write32 = DSi::ARM9Write32; TeakraCore->SetAHBMCallback(cb); - TeakraCore->SetAudioCallback(AudioCb); + TeakraCore->SetAudioCallback(std::bind(&DSi_DSP::AudioCb, this, _1)); //PDATAReadFifo = new FIFO(16); //PDATAWriteFifo = new FIFO(16); - - return true; } -void DeInit() + +DSi_DSP::~DSi_DSP() { //if (PDATAWriteFifo) delete PDATAWriteFifo; if (TeakraCore) delete TeakraCore; @@ -177,7 +157,7 @@ void DeInit() NDS::UnregisterEventFunc(NDS::Event_DSi_DSP, 0); } -void Reset() +void DSi_DSP::Reset() { DSPTimestamp = 0; @@ -200,28 +180,28 @@ void Reset() SNDExCnt = 0; } -bool IsRstReleased() +bool DSi_DSP::IsRstReleased() { return SCFG_RST; } -void SetRstLine(bool release) +void DSi_DSP::SetRstLine(bool release) { SCFG_RST = release; Reset(); DSPTimestamp = NDS::ARM9Timestamp; // only start now! } -inline bool IsDSPCoreEnabled() +inline bool DSi_DSP::IsDSPCoreEnabled() { return (DSi::SCFG_Clock9 & (1<<1)) && SCFG_RST && (!(DSP_PCFG & (1<<0))); } -inline bool IsDSPIOEnabled() +inline bool DSi_DSP::IsDSPIOEnabled() { return (DSi::SCFG_Clock9 & (1<<1)) && SCFG_RST; } -bool DSPCatchUp() +bool DSi_DSP::DSPCatchUp() { //asm volatile("int3"); if (!IsDSPCoreEnabled()) @@ -249,9 +229,9 @@ bool DSPCatchUp() return true; } -void DSPCatchUpU32(u32 _) { DSPCatchUp(); } +void DSi_DSP::DSPCatchUpU32(u32 _) { DSPCatchUp(); } -void PDataDMAWrite(u16 wrval) +void DSi_DSP::PDataDMAWrite(u16 wrval) { u32 addr = DSP_PADR; @@ -293,7 +273,7 @@ void PDataDMAWrite(u16 wrval) NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); // wrfifo empty } // TODO: FIFO interrupts! (rd full, nonempty) -u16 PDataDMARead() +u16 DSi_DSP::PDataDMARead() { u16 r = 0; u32 addr = DSP_PADR; @@ -331,7 +311,7 @@ u16 PDataDMARead() return r; } -void PDataDMAFetch() +void DSi_DSP::PDataDMAFetch() { if (!PDataDMALen) return; @@ -339,7 +319,7 @@ void PDataDMAFetch() if (PDataDMALen > 0) --PDataDMALen; } -void PDataDMAStart() +void DSi_DSP::PDataDMAStart() { switch ((DSP_PSTS & (3<<2)) >> 2) { @@ -358,13 +338,13 @@ void PDataDMAStart() NDS::SetIRQ(0, NDS::IRQ_DSi_DSP); } -void PDataDMACancel() +void DSi_DSP::PDataDMACancel() { PDataDMALen = 0; PDATAReadFifo.Clear(); } -u16 PDataDMAReadMMIO() +u16 DSi_DSP::PDataDMAReadMMIO() { u16 ret; @@ -395,7 +375,7 @@ u16 PDataDMAReadMMIO() return ret; } -u8 Read8(u32 addr) +u8 DSi_DSP::Read8(u32 addr) { //if (!IsDSPIOEnabled()) return 0; DSPCatchUp(); @@ -422,7 +402,7 @@ u8 Read8(u32 addr) return 0; } -u16 Read16(u32 addr) +u16 DSi_DSP::Read16(u32 addr) { //printf("DSP READ16 %d %08X %08X\n", IsDSPCoreEnabled(), addr, NDS::GetPC(0)); //if (!IsDSPIOEnabled()) return 0; @@ -465,14 +445,14 @@ u16 Read16(u32 addr) return 0; } -u32 Read32(u32 addr) +u32 DSi_DSP::Read32(u32 addr) { addr &= 0x3C; return Read16(addr); // *shrug* (doesn't do anything unintended due to the // 4byte spacing between regs while they're all 16bit) } -void Write8(u32 addr, u8 val) +void DSi_DSP::Write8(u32 addr, u8 val) { //if (!IsDSPIOEnabled()) return; DSPCatchUp(); @@ -493,7 +473,7 @@ void Write8(u32 addr, u8 val) // no REPx writes } } -void Write16(u32 addr, u16 val) +void DSi_DSP::Write16(u32 addr, u16 val) { Log(LogLevel::Debug,"DSP WRITE16 %d %08X %08X %08X\n", IsDSPCoreEnabled(), addr, val, NDS::GetPC(0)); //if (!IsDSPIOEnabled()) return; @@ -548,14 +528,16 @@ void Write16(u32 addr, u16 val) } } -void Write32(u32 addr, u32 val) +void DSi_DSP::Write32(u32 addr, u32 val) { addr &= 0x3C; Write16(addr, val & 0xFFFF); } -void WriteSNDExCnt(u16 val) +void DSi_DSP::WriteSNDExCnt(u16 val, u16 mask) { + val = (val & mask) | (SNDExCnt & ~mask); + // it can be written even in NDS mode // mic frequency can only be changed if it was disabled @@ -569,7 +551,7 @@ void WriteSNDExCnt(u16 val) SNDExCnt = val & 0xE00F; } -void Run(u32 cycles) +void DSi_DSP::Run(u32 cycles) { if (!IsDSPCoreEnabled()) { @@ -586,7 +568,7 @@ void Run(u32 cycles) 16384/*from citra (TeakraSlice)*/, 0, 0); } -void DoSavestate(Savestate* file) +void DSi_DSP::DoSavestate(Savestate* file) { file->Section("DSPi"); @@ -611,6 +593,3 @@ void DoSavestate(Savestate* file) // TODO: save the Teakra state!!! } - -} - diff --git a/src/DSi_DSP.h b/src/DSi_DSP.h index e88b5b56..56850c0e 100644 --- a/src/DSi_DSP.h +++ b/src/DSi_DSP.h @@ -25,50 +25,84 @@ // TODO: for actual sound output // * audio callbacks -namespace DSi_DSP +namespace Teakra { class Teakra; } + +class DSi_DSP { +public: + DSi_DSP(); + ~DSi_DSP(); + void Reset(); + void DoSavestate(Savestate* file); -extern u16 SNDExCnt; + void DSPCatchUpU32(u32 _); -extern u16 DSP_PDATA; -extern u16 DSP_PADR; -extern u16 DSP_PCFG; -extern u16 DSP_PSTS; -extern u16 DSP_PSEM; -extern u16 DSP_PMASK; -extern u16 DSP_PCLEAR; -extern u16 DSP_SEM; -extern u16 DSP_CMD[3]; -extern u16 DSP_REP[3]; + // SCFG_RST bit0 + bool IsRstReleased(); + void SetRstLine(bool release); -bool Init(); -void DeInit(); -void Reset(); + // DSP_* regs (0x040043xx) (NOTE: checks SCFG_EXT) + u8 Read8(u32 addr); + void Write8(u32 addr, u8 val); -void DoSavestate(Savestate* file); + u16 Read16(u32 addr); + void Write16(u32 addr, u16 val); -void DSPCatchUpU32(u32 _); + u32 Read32(u32 addr); + void Write32(u32 addr, u32 val); -// SCFG_RST bit0 -bool IsRstReleased(); -void SetRstLine(bool release); + u16 ReadSNDExCnt() { return SNDExCnt; } + void WriteSNDExCnt(u16 val, u16 mask); -// DSP_* regs (0x040043xx) (NOTE: checks SCFG_EXT) -u8 Read8(u32 addr); -void Write8(u32 addr, u8 val); + // NOTE: checks SCFG_CLK9 + void Run(u32 cycles); -u16 Read16(u32 addr); -void Write16(u32 addr, u16 val); + void IrqRep0(); + void IrqRep1(); + void IrqRep2(); + void IrqSem(); + u16 DSPRead16(u32 addr); + void DSPWrite16(u32 addr, u16 val); + void AudioCb(std::array frame); -u32 Read32(u32 addr); -void Write32(u32 addr, u32 val); +private: + // not sure whether to not rather put it somewhere else + u16 SNDExCnt; -void WriteSNDExCnt(u16 val); + Teakra::Teakra* TeakraCore; -// NOTE: checks SCFG_CLK9 -void Run(u32 cycles); + bool SCFG_RST; -} + u16 DSP_PADR; + u16 DSP_PCFG; + u16 DSP_PSTS; + u16 DSP_PSEM; + u16 DSP_PMASK; + u16 DSP_PCLEAR; + u16 DSP_CMD[3]; + u16 DSP_REP[3]; + + u64 DSPTimestamp; + + FIFO PDATAReadFifo/*, *PDATAWriteFifo*/; + int PDataDMALen; + + static const u32 DataMemoryOffset; + + u16 GetPSTS(); + + inline bool IsDSPCoreEnabled(); + inline bool IsDSPIOEnabled(); + + bool DSPCatchUp(); + + void PDataDMAWrite(u16 wrval); + u16 PDataDMARead(); + void PDataDMAFetch(); + void PDataDMAStart(); + void PDataDMACancel(); + u16 PDataDMAReadMMIO(); +}; #endif // DSI_DSP_H