From ccd7ef3a23f184b3a97391aff9f119c8987b33cd Mon Sep 17 00:00:00 2001 From: wheremyfoodat Date: Sun, 11 Jun 2023 14:11:50 +0300 Subject: [PATCH] [DSP] Add other pipes for Picross 3D --- include/services/dsp.hpp | 45 ++------------------ src/core/PICA/gpu.cpp | 2 +- src/core/services/dsp.cpp | 88 +++++++++++++++++++++++++++++++-------- 3 files changed, 75 insertions(+), 60 deletions(-) diff --git a/include/services/dsp.hpp b/include/services/dsp.hpp index a63c4e3f..d6f98bd4 100644 --- a/include/services/dsp.hpp +++ b/include/services/dsp.hpp @@ -5,46 +5,6 @@ #include "logger.hpp" #include "memory.hpp" -// Stub for DSP audio pipe -class DSPPipe { - // Hardcoded responses for now - // These are DSP DRAM offsets for various variables - // https://www.3dbrew.org/wiki/DSP_Memory_Region - static constexpr std::array pipeData = { - 0x000F, // Number of responses - 0xBFFF, // Frame counter - 0x9E92, // Source configs - 0x8680, // Source statuses - 0xA792, // ADPCM coefficients - 0x9430, // DSP configs - 0x8400, // DSP status - 0x8540, // Final samples - 0x9492, // Intermediate mix samples - 0x8710, // Compressor - 0x8410, // Debug - 0xA912, // ?? - 0xAA12, // ?? - 0xAAD2, // ?? - 0xAC52, // Surround sound biquad filter 1 - 0xAC5C // Surround sound biquad filter 2 - }; - 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(); - } -}; - namespace DSPPipeType { enum : u32 { Debug = 0, DMA = 1, Audio = 2, Binary = 3 @@ -66,7 +26,6 @@ class DSPService { // Number of DSP pipes static constexpr size_t pipeCount = 8; - DSPPipe audioPipe; DSPState dspState; // DSP service event handles @@ -76,6 +35,10 @@ class DSPService { DSPEvent interrupt0; DSPEvent interrupt1; std::array pipeEvents; + std::array, pipeCount> pipeData; // The data of each pipe + + void resetAudioPipe(); + std::vector readPipe(u32 pipe, u32 size); DSPEvent& getEventRef(u32 type, u32 pipe); static constexpr size_t maxEventCount = 6; diff --git a/src/core/PICA/gpu.cpp b/src/core/PICA/gpu.cpp index 599f79fd..9cbd17a8 100644 --- a/src/core/PICA/gpu.cpp +++ b/src/core/PICA/gpu.cpp @@ -256,7 +256,7 @@ void GPU::fireDMA(u32 dest, u32 source, u32 size) { u8* fcram = mem.getFCRAM(); std::memcpy(&vram[dest - vramStart], &fcram[source - fcramStart], size); } else { - printf("Non-trivially optimizable GPU DMA. Falling back to byte-by-byte transfer"); + printf("Non-trivially optimizable GPU DMA. Falling back to byte-by-byte transfer\n"); for (u32 i = 0; i < size; i++) { mem.write8(dest + i, mem.read8(source + i)); diff --git a/src/core/services/dsp.cpp b/src/core/services/dsp.cpp index 3ba962ad..3331d4b2 100644 --- a/src/core/services/dsp.cpp +++ b/src/core/services/dsp.cpp @@ -2,6 +2,8 @@ #include "ipc.hpp" #include "kernel.hpp" +#include + namespace DSPCommands { enum : u32 { RecvData = 0x00010040, @@ -30,7 +32,11 @@ namespace Result { } void DSPService::reset() { - audioPipe.reset(); + for (auto& e : pipeData) + e.clear(); + + // Note: Reset audio pipe AFTER resetting all pipes, otherwise the new data will be yeeted + resetAudioPipe(); totalEventCount = 0; dspState = DSPState::Off; @@ -43,6 +49,40 @@ void DSPService::reset() { } } +void DSPService::resetAudioPipe() { + // Hardcoded responses for now + // These are DSP DRAM offsets for various variables + // https://www.3dbrew.org/wiki/DSP_Memory_Region + static constexpr std::array responses = { + 0x000F, // Number of responses + 0xBFFF, // Frame counter + 0x9E92, // Source configs + 0x8680, // Source statuses + 0xA792, // ADPCM coefficients + 0x9430, // DSP configs + 0x8400, // DSP status + 0x8540, // Final samples + 0x9492, // Intermediate mix samples + 0x8710, // Compressor + 0x8410, // Debug + 0xA912, // ?? + 0xAA12, // ?? + 0xAAD2, // ?? + 0xAC52, // Surround sound biquad filter 1 + 0xAC5C // Surround sound biquad filter 2 + }; + + std::vector& audioPipe = pipeData[DSPPipeType::Audio]; + audioPipe.resize(responses.size() * sizeof(u16)); + + // Push back every response to the audio pipe + size_t index = 0; + for (auto e : responses) { + audioPipe[index++] = e & 0xff; + audioPipe[index++] = e >> 8; + } +} + void DSPService::handleSyncRequest(u32 messagePointer) { const u32 command = mem.read32(messagePointer); switch (command) { @@ -93,31 +133,43 @@ void DSPService::unloadComponent(u32 messagePointer) { mem.write32(messagePointer + 4, Result::Success); } +std::vector DSPService::readPipe(u32 pipe, u32 size) { + if (size & 1) Helpers::panic("Tried to read odd amount of bytes from DSP pipe"); + if (pipe >= pipeCount || size > 0xffff) { + return {}; + } + + if (pipe != DSPPipeType::Audio) { + Helpers::warn("Reading from non-audio pipe! This might be broken, might need to check what pipe is being read from and implement writing to it\n"); + } + + std::vector& data = pipeData[pipe]; + size = std::min(size, data.size()); // Clamp size to the maximum available data size + + if (size == 0) + return {}; + + // Return "size" bytes from the audio pipe and erase them + std::vector out(data.begin(), data.begin() + size); + data.erase(data.begin(), data.begin() + size); + return out; +} + 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); + mem.write32(messagePointer, IPC::responseHeader(0x10, 2, 2)); - 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()); + std::vector data = readPipe(channel, size); + for (uint i = 0; i < data.size(); i++) { + mem.write8(buffer + i, data[i]); } - mem.write32(messagePointer, IPC::responseHeader(0x10, 2, 2)); mem.write32(messagePointer + 4, Result::Success); - mem.write16(messagePointer + 8, i); // Number of bytes read + mem.write16(messagePointer + 8, data.size()); // Number of bytes read } void DSPService::recvData(u32 messagePointer) { @@ -130,7 +182,7 @@ void DSPService::recvData(u32 messagePointer) { 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 + mem.write16(messagePointer + 8, ret); } void DSPService::recvDataIsReady(u32 messagePointer) { @@ -257,7 +309,7 @@ void DSPService::writeProcessPipe(u32 messagePointer) { case StateChange::Initialize: // TODO: Other initialization stuff here dspState = DSPState::On; - audioPipe.reset(); + resetAudioPipe(); break; case StateChange::Shutdown: