diff --git a/include/services/dsp.hpp b/include/services/dsp.hpp index 82c0ed40..f3e15a0c 100644 --- a/include/services/dsp.hpp +++ b/include/services/dsp.hpp @@ -3,11 +3,60 @@ #include "logger.hpp" #include "memory.hpp" +// Stub for DSP audio pipe +class DSPPipe { + // Hardcoded responses for now + static constexpr std::array pipeData = { + 0x000F, //Number of responses + 0xBFFF, + 0x9E8E, + 0x8680, + 0xA78E, + 0x9430, + 0x8400, + 0x8540, + 0x948E, + 0x8710, + 0x8410, + 0xA90E, + 0xAA0E, + 0xAACE, + 0xAC4E, + 0xAC58 + }; + uint index = 0; + +public: + void reset() { + index = 0; + } + + // Read without checking if the pipe has overflowed + u16 readUnchecked() { + return pipeData[index++]; + } + + bool empty() { + return index >= pipeData.size(); + } +}; + class DSPService { Handle handle = KernelHandles::DSP; Memory& mem; MAKE_LOG_FUNCTION(log, dspServiceLogger) + DSPPipe audioPipe; + + // Service functions + void getSemaphoreHandle(u32 messagePointer); + void loadComponent(u32 messagePointer); + void readPipeIfPossible(u32 messagePointer); + void registerInterruptEvents(u32 messagePointer); + void setSemaphore(u32 messagePointer); + void setSemaphoreMask(u32 messagePointer); + void writeProcessPipe(u32 messagePointer); + public: DSPService(Memory& mem) : mem(mem) {} void reset(); diff --git a/src/core/services/dsp.cpp b/src/core/services/dsp.cpp index 751f3dea..8652bccf 100644 --- a/src/core/services/dsp.cpp +++ b/src/core/services/dsp.cpp @@ -2,6 +2,13 @@ namespace DSPCommands { enum : u32 { + ReadPipeIfPossible = 0x001000C0, + LoadComponent = 0x001100C2, + RegisterInterruptEvents = 0x00150082, + GetSemaphoreHandle = 0x00160000, + SetSemaphoreMask = 0x00170040, + SetSemaphore = 0x00070040, + WriteProcessPipe = 0x000D0082 }; } @@ -11,11 +18,97 @@ namespace Result { }; } -void DSPService::reset() {} +void DSPService::reset() { + audioPipe.reset(); +} void DSPService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { + case DSPCommands::GetSemaphoreHandle: getSemaphoreHandle(messagePointer); break; + case DSPCommands::LoadComponent: loadComponent(messagePointer); break; + case DSPCommands::ReadPipeIfPossible: readPipeIfPossible(messagePointer); break; + case DSPCommands::RegisterInterruptEvents: registerInterruptEvents(messagePointer); break; + case DSPCommands::SetSemaphore: setSemaphore(messagePointer); break; + case DSPCommands::SetSemaphoreMask: setSemaphoreMask(messagePointer); break; + case DSPCommands::WriteProcessPipe: [[likely]] writeProcessPipe(messagePointer); break; default: Helpers::panic("DSP service requested. Command: %08X\n", command); } +} + +void DSPService::loadComponent(u32 messagePointer) { + u32 size = mem.read32(messagePointer + 4); + u32 programMask = mem.read32(messagePointer + 8); + u32 dataMask = mem.read32(messagePointer + 12); + + log("DSP::LoadComponent (size = %08X, program mask = %X, data mask = %X\n", size, programMask, dataMask); + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 8, 1); // Component loaded + mem.write32(messagePointer + 12, (size << 4) | 0xA); + mem.write32(messagePointer + 16, mem.read32(messagePointer + 20)); // Component buffer +} + +void DSPService::readPipeIfPossible(u32 messagePointer) { + u32 channel = mem.read32(messagePointer + 4); + u32 peer = mem.read32(messagePointer + 8); + u16 size = mem.read16(messagePointer + 12); + u32 buffer = mem.read32(messagePointer + 0x100 + 4); + log("DSP::ReadPipeIfPossible (channel = %d, peer = %d, size = %04X, buffer = %08X)\n", channel, peer, size, buffer); + + if (size & 1) Helpers::panic("Tried to read odd amount of bytes from DSP pipe"); + if (channel != 2) Helpers::panic("Read from non-audio pipe"); + + DSPPipe& pipe = audioPipe; + + uint i; // Number of bytes transferred + for (i = 0; i < size; i += 2) { + if (pipe.empty()) { + printf("Tried to read from empty pipe\n"); + break; + } + + mem.write16(buffer + i, pipe.readUnchecked()); + } + + mem.write32(messagePointer + 4, Result::Success); + mem.write16(messagePointer + 8, i); // Number of bytes read +} + +void DSPService::registerInterruptEvents(u32 messagePointer) { + u32 interrupt = mem.read32(messagePointer + 4); + u32 channel = mem.read32(messagePointer + 8); + u32 event = mem.read32(messagePointer + 16); + + log("DSP::RegisterInterruptEvents (interrupt = %d, channel = %d, event = %d)\n", interrupt, channel, event); + mem.write32(messagePointer + 4, Result::Success); +} + +void DSPService::getSemaphoreHandle(u32 messagePointer) { + log("DSP::GetSemaphoreHandle\n"); + + mem.write32(messagePointer + 4, Result::Success); + mem.write32(messagePointer + 12, 0xF9991234); // Semaphore handle (stubbed with random, obvious number) +} + +void DSPService::setSemaphore(u32 messagePointer) { + const u16 value = mem.read16(messagePointer + 4); + log("DSP::SetSemaphore(value = %04X)\n", value); + + mem.write32(messagePointer + 4, Result::Success); +} + +void DSPService::setSemaphoreMask(u32 messagePointer) { + const u16 mask = mem.read16(messagePointer + 4); + log("DSP::SetSemaphoreMask(mask = %04X)\n", mask); + + mem.write32(messagePointer + 4, Result::Success); +} + +void DSPService::writeProcessPipe(u32 messagePointer) { + u32 channel = mem.read32(messagePointer + 4); + u32 size = mem.read32(messagePointer + 8); + u32 buffer = mem.read32(messagePointer + 16); + + log("DSP::writeProcessPipe (channel = %d, size = %X, buffer = %08X)\n", channel, size, buffer); + mem.write32(messagePointer + 4, Result::Success); } \ No newline at end of file