From 1cc3bbf68da370b52396e60842235041a87b8e8b Mon Sep 17 00:00:00 2001 From: wheremyfoodat <44909372+wheremyfoodat@users.noreply.github.com> Date: Sat, 6 Apr 2024 19:12:58 +0300 Subject: [PATCH] HLE DSP: Fix format and source type for audio buffers --- include/audio/hle_core.hpp | 27 +++++++++++++++++++++++++++ include/memory.hpp | 5 ++++- src/core/audio/hle_core.cpp | 28 ++++++++++++++++++++++++---- 3 files changed, 55 insertions(+), 5 deletions(-) diff --git a/include/audio/hle_core.hpp b/include/audio/hle_core.hpp index 46caf2f5..6d7b3ad1 100644 --- a/include/audio/hle_core.hpp +++ b/include/audio/hle_core.hpp @@ -8,6 +8,9 @@ #include "memory.hpp" namespace Audio { + using SampleFormat = HLE::SourceConfiguration::Configuration::Format; + using SourceType = HLE::SourceConfiguration::Configuration::MonoOrStereo; + struct DSPSource { // Audio buffer information // https://www.3dbrew.org/wiki/DSP_Memory_Region @@ -24,6 +27,9 @@ namespace Audio { u8 pad2; u32 playPosition = 0; // Current position in the buffer + SampleFormat format; + SourceType sourceType; + bool fromQueue = false; // Is this buffer from the buffer queue or an embedded buffer? bool hasPlayedOnce = false; // Has the buffer been played at least once before? @@ -81,6 +87,9 @@ namespace Audio { std::array sources; // DSP voices Audio::HLE::DspMemory dspRam; + SampleFormat sampleFormat = SampleFormat::ADPCM; + SourceType sourceType = SourceType::Stereo; + void resetAudioPipe(); bool loaded = false; // Have we loaded a component? @@ -104,9 +113,27 @@ namespace Audio { Audio::HLE::SharedMemory& readRegion() { return readRegionIndex() == 0 ? dspRam.region0 : dspRam.region1; } Audio::HLE::SharedMemory& writeRegion() { return readRegionIndex() == 0 ? dspRam.region1 : dspRam.region0; } + // Get a pointer of type T* to the data starting from physical address paddr + template + T* getPointerPhys(u32 paddr, u32 size = 0) { + if (paddr >= PhysicalAddrs::FCRAM && paddr + size <= PhysicalAddrs::FCRAMEnd) { + u8* fcram = mem.getFCRAM(); + u32 index = paddr - PhysicalAddrs::FCRAM; + + return (T*)&fcram[index]; + } else if (paddr >= PhysicalAddrs::DSP_RAM && paddr + size <= PhysicalAddrs::DSP_RAM_End) { + u32 index = paddr - PhysicalAddrs::DSP_RAM; + return (T*)&dspRam.rawMemory[index]; + } else [[unlikely]] { + Helpers::warn("[DSP] Tried to access unknown physical address: %08X", paddr); + return nullptr; + } + } + void updateSourceConfig(Source& source, HLE::SourceConfiguration::Configuration& config); void generateFrame(StereoFrame& frame); void outputFrame(); + void dumpBuffer(const Source::Buffer& buffer); public: HLE_DSP(Memory& mem, Scheduler& scheduler, DSPService& dspService); ~HLE_DSP() override {} diff --git a/include/memory.hpp b/include/memory.hpp index 1b6e622c..33ccbae5 100644 --- a/include/memory.hpp +++ b/include/memory.hpp @@ -19,7 +19,10 @@ namespace PhysicalAddrs { VRAM = 0x18000000, VRAMEnd = VRAM + 0x005FFFFF, FCRAM = 0x20000000, - FCRAMEnd = FCRAM + 0x07FFFFFF + FCRAMEnd = FCRAM + 0x07FFFFFF, + + DSP_RAM = 0x1FF00000, + DSP_RAM_End = DSP_RAM + 0x0007FFFF }; } diff --git a/src/core/audio/hle_core.cpp b/src/core/audio/hle_core.cpp index 06d15945..f9f1248c 100644 --- a/src/core/audio/hle_core.cpp +++ b/src/core/audio/hle_core.cpp @@ -59,7 +59,13 @@ namespace Audio { } void HLE_DSP::reset() { + dspState = DSPState::Off; loaded = false; + + // Initialize these to some sane defaults + sampleFormat = SampleFormat::ADPCM; + sourceType = SourceType::Stereo; + for (auto& e : pipeData) { e.clear(); } @@ -207,16 +213,19 @@ namespace Audio { updateSourceConfig(source, config); // Generate audio - if (source.enabled) { - + if (source.enabled && !source.buffers.empty()) { + const auto& buffer = source.buffers.top(); + const u8* data = getPointerPhys(buffer.paddr); + + if (data != nullptr) { + // TODO + } } // Update write region of shared memory auto& status = write.sourceStatuses.status[i]; status.isEnabled = source.enabled; status.syncCount = source.syncCount; - //status.lastBufferID=0,status.currentBufferID = 1; status.currentBufferIDDirty = 1; - //status.bufferPosition = } } @@ -245,6 +254,15 @@ namespace Audio { config.partialResetFlag = 0; source.buffers = {}; } + + // TODO: Should we check bufferQueueDirty here too? + if (config.formatDirty || config.embeddedBufferDirty) { + sampleFormat = config.format; + } + + if (config.monoOrStereoDirty || config.embeddedBufferDirty) { + sourceType = config.monoOrStereo; + } if (config.embeddedBufferDirty) { config.embeddedBufferDirty = 0; @@ -259,6 +277,8 @@ namespace Audio { .looping = config.isLooping != 0, .bufferID = config.bufferID, .playPosition = config.playPosition, + .format = sampleFormat, + .sourceType = sourceType, .fromQueue = false, .hasPlayedOnce = false, };