From 9ab4e3c686f343acd7680cf60165aee5f8b14cd2 Mon Sep 17 00:00:00 2001 From: Weiyi Wang Date: Thu, 6 Dec 2018 08:10:00 -0500 Subject: [PATCH] audio_core/lle: implement GetDspMemory and SetServiceToInterrupt --- src/audio_core/lle/lle.cpp | 55 ++++++++++++++++++++++++++++++++++++++ src/audio_core/lle/lle.h | 4 +++ 2 files changed, 59 insertions(+) diff --git a/src/audio_core/lle/lle.cpp b/src/audio_core/lle/lle.cpp index 7ead44e823..4dbcf2f29c 100644 --- a/src/audio_core/lle/lle.cpp +++ b/src/audio_core/lle/lle.cpp @@ -5,6 +5,7 @@ #include "audio_core/lle/lle.h" #include "common/assert.h" #include "common/swap.h" +#include "core/hle/service/dsp/dsp_dsp.h" #include "teakra/teakra.h" namespace AudioCore { @@ -33,6 +34,9 @@ struct DspLle::Impl final { Teakra::Teakra teakra; u16 pipe_base_waddr = 0; + bool semaphore_signaled = false; + bool data_signaled = false; + static constexpr unsigned TeakraSlice = 20000; void RunTeakraSlice() { teakra.Run(TeakraSlice); @@ -178,6 +182,57 @@ void DspLle::PipeWrite(DspPipe pipe_number, const std::vector& buffer) { impl->WritePipe(static_cast(pipe_number), buffer); } +std::array& DspLle::GetDspMemory() { + return impl->teakra.GetDspMemory(); +} + +void DspLle::SetServiceToInterrupt(std::weak_ptr dsp) { + impl->teakra.SetRecvDataHandler(0, [dsp]() { + if (auto locked = dsp.lock()) { + locked->SignalInterrupt(Service::DSP::DSP_DSP::InterruptType::Zero, + static_cast(0)); + } + }); + impl->teakra.SetRecvDataHandler(1, [dsp]() { + if (auto locked = dsp.lock()) { + locked->SignalInterrupt(Service::DSP::DSP_DSP::InterruptType::One, + static_cast(0)); + } + }); + + auto ProcessPipeEvent = [this, dsp](bool event_from_data) { + auto& teakra = impl->teakra; + if (event_from_data) { + impl->data_signaled = true; + } else { + if ((teakra.GetSemaphore() & 0x8000) == 0) + return; + impl->semaphore_signaled = true; + } + if (impl->semaphore_signaled && impl->data_signaled) { + impl->semaphore_signaled = impl->data_signaled = false; + u16 slot = teakra.RecvData(2); + u16 side = slot % 2; + u16 pipe = slot / 2; + ASSERT(pipe < 16); + if (side != static_cast(PipeDirection::DSPtoCPU)) + return; + if (pipe == 0) { + // pipe 0 is for debug. 3DS automatically drains this pipe and discards the data + impl->ReadPipe(pipe, impl->GetPipeReadableSize(pipe)); + } else { + if (auto locked = dsp.lock()) { + locked->SignalInterrupt(Service::DSP::DSP_DSP::InterruptType::Pipe, + static_cast(pipe)); + } + } + } + }; + + impl->teakra.SetRecvDataHandler(2, [ProcessPipeEvent]() { ProcessPipeEvent(true); }); + impl->teakra.SetSemaphoreHandler([ProcessPipeEvent]() { ProcessPipeEvent(false); }); +} + DspLle::DspLle() : impl(std::make_unique()) {} DspLle::~DspLle() = default; diff --git a/src/audio_core/lle/lle.h b/src/audio_core/lle/lle.h index 5a343d4963..7e418f4f26 100644 --- a/src/audio_core/lle/lle.h +++ b/src/audio_core/lle/lle.h @@ -20,6 +20,10 @@ public: std::size_t GetPipeReadableSize(DspPipe pipe_number) const override; void PipeWrite(DspPipe pipe_number, const std::vector& buffer) override; + std::array& GetDspMemory() override; + + void SetServiceToInterrupt(std::weak_ptr dsp) override; + private: struct Impl; friend struct Impl;