diff --git a/src/DSP_HLE/Ucode_Base.cpp b/src/DSP_HLE/Ucode_Base.cpp index e5e3a218..954180bf 100644 --- a/src/DSP_HLE/Ucode_Base.cpp +++ b/src/DSP_HLE/Ucode_Base.cpp @@ -40,7 +40,11 @@ DSPHLE_UcodeBase::~DSPHLE_UcodeBase() void DSPHLE_UcodeBase::Reset() { - // + memset(CmdReg, 0, sizeof(CmdReg)); + memset(CmdWritten, 0, sizeof(CmdWritten)); + memset(ReplyReg, 0, sizeof(ReplyReg)); + memset(ReplyWritten, 0, sizeof(ReplyWritten)); + memset(ReplyReadCb, 0, sizeof(ReplyReadCb)); } void DSPHLE_UcodeBase::DoSavestate(Savestate *file) @@ -48,18 +52,67 @@ void DSPHLE_UcodeBase::DoSavestate(Savestate *file) // } -bool DSPHLE_UcodeBase::SendDataIsEmpty(u8 index) + +bool DSPHLE_UcodeBase::RecvDataIsReady(u8 index) { - // - return false; + return ReplyWritten[index]; } -bool DSPHLE_UcodeBase::RecvDataIsEmpty(u8 index) +bool DSPHLE_UcodeBase::SendDataIsEmpty(u8 index) { - // - return false; + return !CmdWritten[index]; } +u16 DSPHLE_UcodeBase::RecvData(u8 index) +{ + if (!ReplyWritten[index]) return 0; // CHECKME + + u16 ret = ReplyReg[index]; + ReplyWritten[index] = false; + + if (ReplyReadCb[index]) + { + ReplyReadCb[index](); + ReplyReadCb[index] = nullptr; + } + + return ret; +} + +void DSPHLE_UcodeBase::SendData(u8 index, u16 val) +{ + if (CmdWritten[index]) + { + printf("??? trying to write cmd but there's already one\n"); + return; // CHECKME + } + + CmdReg[index] = val; + CmdWritten[index] = true; + printf("DSP: send cmd%d %04X\n", index, val); +} + + +void DSPHLE_UcodeBase::SendReply(u8 index, u16 val) +{ + if (ReplyWritten[index]) + { + printf("??? trying to write reply but there's already one\n"); + return; + } + + ReplyReg[index] = val; + ReplyWritten[index] = true; + + // TODO add callback for when it is successfully written +} + +void DSPHLE_UcodeBase::SetReplyReadCallback(u8 index, fnReplyReadCb callback) +{ + ReplyReadCb[index] = callback; +} + + u16 DSPHLE_UcodeBase::DMAChan0GetDstHigh() { // @@ -160,16 +213,26 @@ void DSPHLE_UcodeBase::MaskSemaphore(u16 val) // } -u16 DSPHLE_UcodeBase::RecvData(u8 index) + +void DSPHLE_UcodeBase::Start() { - // - return 0; + printf("DSP HLE: start\n"); + // TODO later: detect which ucode it is and create the right class! + // (and fall back to Teakra if not a known ucode) + + SendReply(0, 1); + SendReply(1, 1); + SendReply(2, 1); + SetReplyReadCallback(2, [=]() + { + printf("reply 2 was read\n"); + + SendReply(2, 0x0800); + }); + + // TODO more shit } -void DSPHLE_UcodeBase::SendData(u8 index, u16 val) -{ - // -} void DSPHLE_UcodeBase::Run(u32 cycles) { diff --git a/src/DSP_HLE/Ucode_Base.h b/src/DSP_HLE/Ucode_Base.h index 7e33e938..acf5c180 100644 --- a/src/DSP_HLE/Ucode_Base.h +++ b/src/DSP_HLE/Ucode_Base.h @@ -35,11 +35,19 @@ public: void Reset(); void DoSavestate(Savestate* file); + typedef std::function fnReplyReadCb; + //void SetRecvDataHandler(u8 index, std::function func); //void SetSemaphoreHandler(std::function func); + bool RecvDataIsReady(u8 index); bool SendDataIsEmpty(u8 index); - bool RecvDataIsEmpty(u8 index); + u16 RecvData(u8 index); + void SendData(u8 index, u16 val); + + // TODO receive cmd + void SendReply(u8 index, u16 val); + void SetReplyReadCallback(u8 index, fnReplyReadCb callback); u16 DMAChan0GetDstHigh(); u16 AHBMGetDmaChannel(u16 index); @@ -62,10 +70,16 @@ public: void ClearSemaphore(u16 val); void MaskSemaphore(u16 val); - u16 RecvData(u8 index); - void SendData(u8 index, u16 val); + void Start(); void Run(u32 cycles); + +protected: + u16 CmdReg[3]; + bool CmdWritten[3]; + u16 ReplyReg[3]; + bool ReplyWritten[3]; + fnReplyReadCb ReplyReadCb[3]; }; } diff --git a/src/DSi_DSP.cpp b/src/DSi_DSP.cpp index 26399e3f..733c8687 100644 --- a/src/DSi_DSP.cpp +++ b/src/DSi_DSP.cpp @@ -17,6 +17,7 @@ */ #include "teakra/include/teakra/teakra.h" +#include "DSP_HLE/Ucode_Base.h" #include "DSi.h" #include "DSi_DSP.h" @@ -43,12 +44,18 @@ u16 DSi_DSP::GetPSTS() const if ( PDATAReadFifo.IsFull ()) r |= 1<<5; if (!PDATAReadFifo.IsEmpty()) r |=(1<<6)|(1<<0); - if (!TeakraCore->SendDataIsEmpty(0)) r |= 1<<13; + /*if (!TeakraCore->SendDataIsEmpty(0)) r |= 1<<13; if (!TeakraCore->SendDataIsEmpty(1)) r |= 1<<14; if (!TeakraCore->SendDataIsEmpty(2)) r |= 1<<15; if ( TeakraCore->RecvDataIsReady(0)) r |= 1<<10; if ( TeakraCore->RecvDataIsReady(1)) r |= 1<<11; - if ( TeakraCore->RecvDataIsReady(2)) r |= 1<<12; + if ( TeakraCore->RecvDataIsReady(2)) r |= 1<<12;*/ + if (!HleCore->SendDataIsEmpty(0)) r |= 1<<13; + if (!HleCore->SendDataIsEmpty(1)) r |= 1<<14; + if (!HleCore->SendDataIsEmpty(2)) r |= 1<<15; + if ( HleCore->RecvDataIsReady(0)) r |= 1<<10; + if ( HleCore->RecvDataIsReady(1)) r |= 1<<11; + if ( HleCore->RecvDataIsReady(2)) r |= 1<<12; return r; } @@ -111,7 +118,8 @@ DSi_DSP::DSi_DSP(melonDS::DSi& dsi) : DSi(dsi) { DSi.RegisterEventFuncs(Event_DSi_DSP, this, {MakeEventThunk(DSi_DSP, DSPCatchUpU32)}); - TeakraCore = new Teakra::Teakra(); + //TeakraCore = new Teakra::Teakra(); + HleCore = new DSPHLE_UcodeBase(); SCFG_RST = false; // ???? @@ -119,7 +127,7 @@ DSi_DSP::DSi_DSP(melonDS::DSi& dsi) : DSi(dsi) using namespace std::placeholders; - TeakraCore->SetRecvDataHandler(0, std::bind(&DSi_DSP::IrqRep0, this)); + /*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)); @@ -141,7 +149,7 @@ DSi_DSP::DSi_DSP(melonDS::DSi& dsi) : DSi(dsi) cb.write32 = [this](auto addr, auto val) { DSi.ARM9Write32(addr, val); }; TeakraCore->SetAHBMCallback(cb); - TeakraCore->SetAudioCallback(std::bind(&DSi_DSP::AudioCb, this, _1)); + TeakraCore->SetAudioCallback(std::bind(&DSi_DSP::AudioCb, this, _1));*/ //PDATAReadFifo = new FIFO(16); //PDATAWriteFifo = new FIFO(16); @@ -150,11 +158,13 @@ DSi_DSP::DSi_DSP(melonDS::DSi& dsi) : DSi(dsi) DSi_DSP::~DSi_DSP() { //if (PDATAWriteFifo) delete PDATAWriteFifo; - if (TeakraCore) delete TeakraCore; + //if (TeakraCore) delete TeakraCore; + if (HleCore) delete HleCore; //PDATAReadFifo = NULL; //PDATAWriteFifo = NULL; - TeakraCore = NULL; + //TeakraCore = NULL; + HleCore = nullptr; DSi.UnregisterEventFuncs(Event_DSi_DSP); } @@ -175,7 +185,8 @@ void DSi_DSP::Reset() PDATAReadFifo.Clear(); //PDATAWriteFifo->Clear(); - TeakraCore->Reset(); + //TeakraCore->Reset(); + HleCore->Reset(); DSi.CancelEvent(Event_DSi_DSP); @@ -240,17 +251,23 @@ void DSi_DSP::PDataDMAWrite(u16 wrval) switch (DSP_PCFG & (7<<12)) // memory region select { case 0<<12: // data - addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; - TeakraCore->DataWriteA32(addr, wrval); + //addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; + //TeakraCore->DataWriteA32(addr, wrval); + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + HleCore->DataWriteA32(addr, wrval); break; case 1<<12: // mmio - TeakraCore->MMIOWrite(addr & 0x7FF, wrval); + //TeakraCore->MMIOWrite(addr & 0x7FF, wrval); + HleCore->MMIOWrite(addr & 0x7FF, wrval); break; case 5<<12: // program - addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; - TeakraCore->ProgramWrite(addr, wrval); + //addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; + //TeakraCore->ProgramWrite(addr, wrval); + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + HleCore->ProgramWrite(addr, wrval); break; case 7<<12: +#if 0 addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; // only do stuff when AHBM is configured correctly if (TeakraCore->AHBMGetDmaChannel(0) == 0 && TeakraCore->AHBMGetDirection(0) == 1/*W*/) @@ -265,6 +282,21 @@ void DSi_DSP::PDataDMAWrite(u16 wrval) case 2: /* 32 b */ TeakraCore->AHBMWrite32(addr, wrval); break; } } +#endif + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + // only do stuff when AHBM is configured correctly + if (HleCore->AHBMGetDmaChannel(0) == 0 && HleCore->AHBMGetDirection(0) == 1/*W*/) + { + switch (HleCore->AHBMGetUnitSize(0)) + { + case 0: /* 8bit */ DSi.ARM9Write8 (addr, (u8)wrval); break; + case 1: /* 16 b */ HleCore->AHBMWrite16(addr, wrval); break; + // does it work like this, or should it first buffer two u16's + // until it has enough data to write to the actual destination? + // -> this seems to be correct behavior! + case 2: /* 32 b */ HleCore->AHBMWrite32(addr, wrval); break; + } + } break; default: return; }printf("DSP: PDATA write %08X -> %04X\n", addr, wrval); @@ -282,17 +314,23 @@ u16 DSi_DSP::PDataDMARead() switch (DSP_PCFG & (7<<12)) // memory region select { case 0<<12: // data - addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; - r = TeakraCore->DataReadA32(addr); + //addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; + //r = TeakraCore->DataReadA32(addr); + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + r = HleCore->DataReadA32(addr); break; case 1<<12: // mmio - r = TeakraCore->MMIORead(addr & 0x7FF); + //r = TeakraCore->MMIORead(addr & 0x7FF); + r = HleCore->MMIORead(addr & 0x7FF); break; case 5<<12: // program - addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; - r = TeakraCore->ProgramRead(addr); + //addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; + //r = TeakraCore->ProgramRead(addr); + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + r = HleCore->ProgramRead(addr); break; case 7<<12: +#if 0 addr |= (u32)TeakraCore->DMAChan0GetDstHigh() << 16; // only do stuff when AHBM is configured correctly if (TeakraCore->AHBMGetDmaChannel(0) == 0 && TeakraCore->AHBMGetDirection(0) == 0/*R*/) @@ -304,6 +342,18 @@ u16 DSi_DSP::PDataDMARead() case 2: /* 32 b */ r = (u16)TeakraCore->AHBMRead32(addr); break; } } +#endif + addr |= (u32)HleCore->DMAChan0GetDstHigh() << 16; + // only do stuff when AHBM is configured correctly + if (HleCore->AHBMGetDmaChannel(0) == 0 && HleCore->AHBMGetDirection(0) == 0/*R*/) + { + switch (HleCore->AHBMGetUnitSize(0)) + { + case 0: /* 8bit */ r = DSi.ARM9Read8 (addr); break; + case 1: /* 16 b */ r = HleCore->AHBMRead16(addr); break; + case 2: /* 32 b */ r = (u16)HleCore->AHBMRead32(addr); break; + } + } break; default: return r; }printf("DSP: PDATA read %08X -> %04X\n", addr, r); @@ -392,8 +442,10 @@ u8 DSi_DSP::Read8(u32 addr) case 0x14: return DSP_PMASK & 0xFF; case 0x15: return DSP_PMASK >> 8; // no DSP_PCLEAR read - case 0x1C: return TeakraCore->GetSemaphore() & 0xFF; // SEM - case 0x1D: return TeakraCore->GetSemaphore() >> 8; + //case 0x1C: return TeakraCore->GetSemaphore() & 0xFF; // SEM + //case 0x1D: return TeakraCore->GetSemaphore() >> 8; + case 0x1C: return HleCore->GetSemaphore() & 0xFF; // SEM + case 0x1D: return HleCore->GetSemaphore() >> 8; } return 0; @@ -416,7 +468,8 @@ u16 DSi_DSP::Read16(u32 addr) case 0x10: return DSP_PSEM; case 0x14: return DSP_PMASK; // no DSP_PCLEAR read - case 0x1C: return TeakraCore->GetSemaphore(); // SEM + //case 0x1C: return TeakraCore->GetSemaphore(); // SEM + case 0x1C: return HleCore->GetSemaphore(); // SEM case 0x20: return DSP_CMD[0]; case 0x28: return DSP_CMD[1]; @@ -424,17 +477,20 @@ u16 DSi_DSP::Read16(u32 addr) case 0x24: { - u16 r = TeakraCore->RecvData(0);printf("DSP: read CMD0, %04X\n", r); + //u16 r = TeakraCore->RecvData(0);printf("DSP: read CMD0, %04X\n", r); + u16 r = HleCore->RecvData(0);printf("DSP: read CMD0, %04X\n", r); return r; } case 0x2C: { - u16 r = TeakraCore->RecvData(1);printf("DSP: read CMD1, %04X\n", r); + //u16 r = TeakraCore->RecvData(1);printf("DSP: read CMD1, %04X\n", r); + u16 r = HleCore->RecvData(1);printf("DSP: read CMD1, %04X\n", r); return r; } case 0x34: { - u16 r = TeakraCore->RecvData(2);printf("DSP: read CMD2, %04X\n", r); + //u16 r = TeakraCore->RecvData(2);printf("DSP: read CMD2, %04X\n", r); + u16 r = HleCore->RecvData(2);printf("DSP: read CMD2, %04X\n", r); return r; } } @@ -483,9 +539,12 @@ void DSi_DSP::Write16(u32 addr, u16 val) case 0x04: DSP_PADR = val; break; case 0x08: + if ((DSP_PCFG & (1<<0)) && (!(val & (1<<0)))) + HleCore->Start(); DSP_PCFG = val; if (DSP_PCFG & (1<<0)) - TeakraCore->Reset(); + //TeakraCore->Reset(); + HleCore->Reset(); /*else if (!fazil) { fazil = true; @@ -499,15 +558,19 @@ void DSi_DSP::Write16(u32 addr, u16 val) // no PSTS writes case 0x10: DSP_PSEM = val; - TeakraCore->SetSemaphore(val); + //TeakraCore->SetSemaphore(val); + HleCore->SetSemaphore(val); break; case 0x14: DSP_PMASK = val; - TeakraCore->MaskSemaphore(val); + //TeakraCore->MaskSemaphore(val); + HleCore->MaskSemaphore(val); break; case 0x18: // PCLEAR - TeakraCore->ClearSemaphore(val); - if (TeakraCore->GetSemaphore() == 0) + //TeakraCore->ClearSemaphore(val); + HleCore->ClearSemaphore(val); + //if (TeakraCore->GetSemaphore() == 0) + if (HleCore->GetSemaphore() == 0) DSP_PSTS &= ~(1<<9); break; @@ -515,15 +578,18 @@ void DSi_DSP::Write16(u32 addr, u16 val) case 0x20: // CMD0 DSP_CMD[0] = val;printf("DSP: CMD0 = %04X\n", val); - TeakraCore->SendData(0, val); + //TeakraCore->SendData(0, val); + HleCore->SendData(0, val); break; case 0x28: // CMD1 DSP_CMD[1] = val;printf("DSP: CMD1 = %04X\n", val); - TeakraCore->SendData(1, val); + //TeakraCore->SendData(1, val); + HleCore->SendData(1, val); break; case 0x30: // CMD2 DSP_CMD[2] = val;printf("DSP: CMD2 = %04X\n", val); - TeakraCore->SendData(2, val); + //TeakraCore->SendData(2, val); + HleCore->SendData(2, val); break; // no REPx writes @@ -561,7 +627,8 @@ void DSi_DSP::Run(u32 cycles) return; } - TeakraCore->Run(cycles); + //TeakraCore->Run(cycles); + HleCore->Run(cycles); DSPTimestamp += cycles; diff --git a/src/DSi_DSP.h b/src/DSi_DSP.h index f76b4202..d7c8aa12 100644 --- a/src/DSi_DSP.h +++ b/src/DSi_DSP.h @@ -30,6 +30,7 @@ namespace Teakra { class Teakra; } namespace melonDS { class DSi; +class DSPHLE_UcodeBase; class DSi_DSP { public: @@ -74,6 +75,7 @@ private: u16 SNDExCnt; Teakra::Teakra* TeakraCore; + DSPHLE_UcodeBase* HleCore; bool SCFG_RST;