From fdeb45d188c7c46118ec70ab8fe932cd11b43843 Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Wed, 17 May 2023 01:17:10 +0300 Subject: [PATCH] [DSP] HLE DSP state & some of the audio pipe --- include/services/dsp.hpp | 13 ++++++++ src/core/services/dsp.cpp | 69 ++++++++++++++++++++++++++++++++++++++- 2 files changed, 81 insertions(+), 1 deletion(-) diff --git a/include/services/dsp.hpp b/include/services/dsp.hpp index 5fe42a89..774c25de 100644 --- a/include/services/dsp.hpp +++ b/include/services/dsp.hpp @@ -43,6 +43,12 @@ public: } }; +namespace DSPPipeType { + enum : u32 { + Debug = 0, DMA = 1, Audio = 2, Binary = 3 + }; +} + // Circular dependencies! class Kernel; @@ -52,9 +58,14 @@ class DSPService { Kernel& kernel; MAKE_LOG_FUNCTION(log, dspServiceLogger) + enum class DSPState : u32 { + Off, On, Slep + }; + // Number of DSP pipes static constexpr size_t pipeCount = 8; DSPPipe audioPipe; + DSPState dspState; // DSP service event handles using DSPEvent = std::optional; @@ -78,6 +89,8 @@ class DSPService { void invalidateDCache(u32 messagePointer); void loadComponent(u32 messagePointer); void readPipeIfPossible(u32 messagePointer); + void recvData(u32 messagePointer); + void recvDataIsReady(u32 messagePointer); void registerInterruptEvents(u32 messagePointer); void setSemaphore(u32 messagePointer); void setSemaphoreMask(u32 messagePointer); diff --git a/src/core/services/dsp.cpp b/src/core/services/dsp.cpp index e94fc92d..a8485794 100644 --- a/src/core/services/dsp.cpp +++ b/src/core/services/dsp.cpp @@ -4,6 +4,8 @@ namespace DSPCommands { enum : u32 { + RecvData = 0x00010040, + RecvDataIsReady = 0x00020040, SetSemaphore = 0x00070040, ConvertProcessAddressFromDspDram = 0x000C0040, WriteProcessPipe = 0x000D0082, @@ -29,6 +31,7 @@ namespace Result { void DSPService::reset() { audioPipe.reset(); totalEventCount = 0; + dspState = DSPState::Off; semaphoreEvent = std::nullopt; interrupt0 = std::nullopt; @@ -49,6 +52,8 @@ void DSPService::handleSyncRequest(u32 messagePointer) { case DSPCommands::GetSemaphoreEventHandle: getSemaphoreEventHandle(messagePointer); break; case DSPCommands::LoadComponent: loadComponent(messagePointer); break; case DSPCommands::ReadPipeIfPossible: readPipeIfPossible(messagePointer); break; + case DSPCommands::RecvData: recvData(messagePointer); break; + case DSPCommands::RecvDataIsReady: recvDataIsReady(messagePointer); break; case DSPCommands::RegisterInterruptEvents: registerInterruptEvents(messagePointer); break; case DSPCommands::SetSemaphore: setSemaphore(messagePointer); break; case DSPCommands::SetSemaphoreMask: setSemaphoreMask(messagePointer); break; @@ -107,6 +112,29 @@ void DSPService::readPipeIfPossible(u32 messagePointer) { mem.write16(messagePointer + 8, i); // Number of bytes read } +void DSPService::recvData(u32 messagePointer) { + const u32 registerIndex = mem.read32(messagePointer + 4); + log("DSP::RecvData (register = %d)\n", registerIndex); + if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvData"); + + // Return 0 if the DSP is running, otherwise 1 + const u16 ret = dspState == DSPState::On ? 0 : 1; + + mem.write32(messagePointer, IPC::responseHeader(0x01, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write16(messagePointer + 8, ret); // Always return that the DSP is on +} + +void DSPService::recvDataIsReady(u32 messagePointer) { + const u32 registerIndex = mem.read32(messagePointer + 4); + log("DSP::RecvDataIsReady (register = %d)\n", registerIndex); + if (registerIndex != 0) Helpers::panic("Unknown register in DSP::RecvDataIsReady"); + + mem.write32(messagePointer, IPC::responseHeader(0x02, 2, 0)); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 1); // Always return that the register is ready for now +} + DSPService::DSPEvent& DSPService::getEventRef(u32 type, u32 pipe) { switch (type) { case 0: return interrupt0; @@ -192,8 +220,47 @@ void DSPService::writeProcessPipe(u32 messagePointer) { const u32 channel = mem.read32(messagePointer + 4); const u32 size = mem.read32(messagePointer + 8); const u32 buffer = mem.read32(messagePointer + 16); - log("DSP::writeProcessPipe (channel = %d, size = %X, buffer = %08X)\n", channel, size, buffer); + + enum class StateChange : u8 { + Initialize = 0, + Shutdown = 1, + Wakeup = 2, + Sleep = 3, + }; + + switch (channel) { + case DSPPipeType::Audio: { + if (size != 4) { + printf("Invalid size written to DSP Audio Pipe\n"); + break; + } + + // Get new state + const u8 state = mem.read8(buffer); + if (state > 3) { + log("WriteProcessPipe::Audio: Unknown state change type"); + } else { + switch (static_cast(state)) { + case StateChange::Initialize: + // TODO: Other initialization stuff here + dspState = DSPState::On; + break; + + case StateChange::Shutdown: + dspState = DSPState::Off; + break; + + default: Helpers::panic("Unimplemented DSP audio pipe state change %d", state); + } + } + } + + default: + log("DSP: Wrote to unimplemented pipe %d\n", channel); + break; + } + mem.write32(messagePointer, IPC::responseHeader(0xD, 1, 0)); mem.write32(messagePointer + 4, Result::Success); }