From 913f7ee524f9691ae2dc22625b5af9be3dcfe49e Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Apr 2016 09:01:53 +0100 Subject: [PATCH 1/6] DSP_DSP: Remove unused variable --- src/core/hle/service/dsp_dsp.cpp | 2 -- 1 file changed, 2 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 08e437125f..751cb3d61b 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -17,7 +17,6 @@ namespace DSP_DSP { -static u32 read_pipe_count; static Kernel::SharedPtr semaphore_event; struct PairHash { @@ -458,7 +457,6 @@ const Interface::FunctionInfo FunctionTable[] = { Interface::Interface() { semaphore_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event"); - read_pipe_count = 0; Register(FunctionTable); } From 555907ce8dc842ef0859537a0c25443a5e9527bb Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Apr 2016 09:12:15 +0100 Subject: [PATCH 2/6] DSP/Pipe: There are 8 pipes --- src/audio_core/hle/pipe.cpp | 28 +++++++++++++++++----------- src/audio_core/hle/pipe.h | 4 ++-- 2 files changed, 19 insertions(+), 13 deletions(-) diff --git a/src/audio_core/hle/pipe.cpp b/src/audio_core/hle/pipe.cpp index 9381883b4f..7ec97dfda4 100644 --- a/src/audio_core/hle/pipe.cpp +++ b/src/audio_core/hle/pipe.cpp @@ -17,7 +17,7 @@ namespace HLE { static DspState dsp_state = DspState::Off; -static std::array, static_cast(DspPipe::DspPipe_MAX)> pipe_data; +static std::array, NUM_DSP_PIPE> pipe_data; void ResetPipes() { for (auto& data : pipe_data) { @@ -27,16 +27,18 @@ void ResetPipes() { } std::vector PipeRead(DspPipe pipe_number, u32 length) { - if (pipe_number >= DspPipe::DspPipe_MAX) { - LOG_ERROR(Audio_DSP, "pipe_number = %u invalid", pipe_number); + const size_t pipe_index = static_cast(pipe_number); + + if (pipe_index >= NUM_DSP_PIPE) { + LOG_ERROR(Audio_DSP, "pipe_number = %zu invalid", pipe_index); return {}; } - std::vector& data = pipe_data[static_cast(pipe_number)]; + std::vector& data = pipe_data[pipe_index]; if (length > data.size()) { - LOG_WARNING(Audio_DSP, "pipe_number = %u is out of data, application requested read of %u but %zu remain", - pipe_number, length, data.size()); + LOG_WARNING(Audio_DSP, "pipe_number = %zu is out of data, application requested read of %u but %zu remain", + pipe_index, length, data.size()); length = data.size(); } @@ -49,16 +51,20 @@ std::vector PipeRead(DspPipe pipe_number, u32 length) { } size_t GetPipeReadableSize(DspPipe pipe_number) { - if (pipe_number >= DspPipe::DspPipe_MAX) { - LOG_ERROR(Audio_DSP, "pipe_number = %u invalid", pipe_number); + const size_t pipe_index = static_cast(pipe_number); + + if (pipe_index >= NUM_DSP_PIPE) { + LOG_ERROR(Audio_DSP, "pipe_number = %zu invalid", pipe_index); return 0; } - return pipe_data[static_cast(pipe_number)].size(); + return pipe_data[pipe_index].size(); } static void WriteU16(DspPipe pipe_number, u16 value) { - std::vector& data = pipe_data[static_cast(pipe_number)]; + const size_t pipe_index = static_cast(pipe_number); + + std::vector& data = pipe_data.at(pipe_index); // Little endian data.emplace_back(value & 0xFF); data.emplace_back(value >> 8); @@ -145,7 +151,7 @@ void PipeWrite(DspPipe pipe_number, const std::vector& buffer) { return; } default: - LOG_CRITICAL(Audio_DSP, "pipe_number = %u unimplemented", pipe_number); + LOG_CRITICAL(Audio_DSP, "pipe_number = %zu unimplemented", static_cast(pipe_number)); UNIMPLEMENTED(); return; } diff --git a/src/audio_core/hle/pipe.h b/src/audio_core/hle/pipe.h index 382d35e873..64d97f8bab 100644 --- a/src/audio_core/hle/pipe.h +++ b/src/audio_core/hle/pipe.h @@ -19,9 +19,9 @@ enum class DspPipe { Debug = 0, Dma = 1, Audio = 2, - Binary = 3, - DspPipe_MAX + Binary = 3 }; +constexpr size_t NUM_DSP_PIPE = 8; /** * Read a DSP pipe. From ff6db69c6052f674265c453932a3dc7637c46412 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Apr 2016 10:21:10 +0100 Subject: [PATCH 3/6] DSP_DSP: Updated interrupt implementation --- src/audio_core/audio_core.cpp | 7 +- src/audio_core/hle/pipe.cpp | 4 + src/core/hle/service/dsp_dsp.cpp | 129 +++++++++++++++++++++++-------- src/core/hle/service/dsp_dsp.h | 19 ++--- 4 files changed, 113 insertions(+), 46 deletions(-) diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index 894f469901..0685eaf85b 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -4,6 +4,7 @@ #include "audio_core/audio_core.h" #include "audio_core/hle/dsp.h" +#include "audio_core/hle/pipe.h" #include "core/core_timing.h" #include "core/hle/kernel/vm_manager.h" @@ -17,10 +18,8 @@ static constexpr u64 audio_frame_ticks = 1310252ull; ///< Units: ARM11 cycles static void AudioTickCallback(u64 /*userdata*/, int cycles_late) { if (DSP::HLE::Tick()) { - // HACK: We're not signaling the interrups when they should be, but just firing them all off together. - // It should be only (interrupt_id = 2, channel_id = 2) that's signalled here. - // TODO(merry): Understand when the other interrupts are fired. - DSP_DSP::SignalAllInterrupts(); + // TODO(merry): Signal all the other interrupts as appropriate. + DSP_DSP::SignalPipeInterrupt(DSP::HLE::DspPipe::Audio); } // Reschedule recurrent event diff --git a/src/audio_core/hle/pipe.cpp b/src/audio_core/hle/pipe.cpp index 7ec97dfda4..03280780fe 100644 --- a/src/audio_core/hle/pipe.cpp +++ b/src/audio_core/hle/pipe.cpp @@ -12,6 +12,8 @@ #include "common/common_types.h" #include "common/logging/log.h" +#include "core/hle/service/dsp_dsp.h" + namespace DSP { namespace HLE { @@ -97,6 +99,8 @@ static void AudioPipeWriteStructAddresses() { for (u16 addr : struct_addresses) { WriteU16(DspPipe::Audio, addr); } + // Signal that we have data on this pipe. + DSP_DSP::SignalPipeInterrupt(DspPipe::Audio); } void PipeWrite(DspPipe pipe_number, const std::vector& buffer) { diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 751cb3d61b..e9ef50f863 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -2,6 +2,7 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. +#include #include #include "audio_core/hle/pipe.h" @@ -12,6 +13,8 @@ #include "core/hle/kernel/event.h" #include "core/hle/service/dsp_dsp.h" +using DspPipe = DSP::HLE::DspPipe; + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace DSP_DSP @@ -19,29 +22,71 @@ namespace DSP_DSP { static Kernel::SharedPtr semaphore_event; -struct PairHash { - template - std::size_t operator()(const std::pair &x) const { - // TODO(yuriks): Replace with better hash combining function. - return std::hash()(x.first) ^ std::hash()(x.second); +/// There are three types of interrupts +enum class InterruptType { + Zero, One, Pipe +}; +constexpr size_t NUM_INTERRUPT_TYPE = 3; + +class InterruptEvents final { +public: + void Signal(InterruptType type, DspPipe pipe) { + Kernel::SharedPtr& event = Get(type, pipe); + if (event) { + event->Signal(); + } } + + Kernel::SharedPtr& Get(InterruptType type, DspPipe dsp_pipe) { + switch (type) { + case InterruptType::Zero: + return zero; + case InterruptType::One: + return one; + case InterruptType::Pipe: { + const size_t pipe_index = static_cast(dsp_pipe); + ASSERT(pipe_index < DSP::HLE::NUM_DSP_PIPE); + return pipe[pipe_index]; + } + } + + UNREACHABLE_MSG("Invalid interrupt type = %zu", static_cast(type)); + } + + bool HasTooManyEventsRegistered() const { + // Actual service implementation only has 6 'slots' for interrupts. + constexpr size_t max_number_of_interrupt_events = 6; + + size_t number = std::count_if(pipe.begin(), pipe.end(), [](const auto& evt) { + return evt != nullptr; + }); + + if (zero != nullptr) + number++; + if (one != nullptr) + number++; + + return number >= max_number_of_interrupt_events; + } + +private: + /// Currently unknown purpose + Kernel::SharedPtr zero = nullptr; + /// Currently unknown purpose + Kernel::SharedPtr one = nullptr; + /// Each DSP pipe has an associated interrupt + std::array, DSP::HLE::NUM_DSP_PIPE> pipe = {{}}; }; -/// Map of (audio interrupt number, channel number) to Kernel::Events. See: RegisterInterruptEvents -static std::unordered_map, Kernel::SharedPtr, PairHash> interrupt_events; +static InterruptEvents interrupt_events; // DSP Interrupts: -// Interrupt #2 occurs every frame tick. Userland programs normally have a thread that's waiting -// for an interrupt event. Immediately after this interrupt event, userland normally updates the -// state in the next region and increments the relevant frame counter by two. -void SignalAllInterrupts() { - // HACK: The other interrupts have currently unknown purpose, we trigger them each tick in any case. - for (auto& interrupt_event : interrupt_events) - interrupt_event.second->Signal(); -} - -void SignalInterrupt(u32 interrupt, u32 channel) { - interrupt_events[std::make_pair(interrupt, channel)]->Signal(); +// The audio-pipe interrupt occurs every frame tick. Userland programs normally have a thread +// that's waiting for an interrupt event. Immediately after this interrupt event, userland +// normally updates the state in the next region and increments the relevant frame counter by +// two. +void SignalPipeInterrupt(DspPipe pipe) { + interrupt_events.Signal(InterruptType::Pipe, pipe); } /** @@ -147,8 +192,8 @@ static void FlushDataCache(Service::Interface* self) { /** * DSP_DSP::RegisterInterruptEvents service function * Inputs: - * 1 : Interrupt Number - * 2 : Channel Number + * 1 : Interrupt Type + * 2 : Pipe Number * 4 : Interrupt event handle * Outputs: * 1 : Result of function, 0 on success, otherwise error code @@ -156,23 +201,40 @@ static void FlushDataCache(Service::Interface* self) { static void RegisterInterruptEvents(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - u32 interrupt = cmd_buff[1]; - u32 channel = cmd_buff[2]; + u32 type_index = cmd_buff[1]; + u32 pipe_index = cmd_buff[2]; u32 event_handle = cmd_buff[4]; + ASSERT_MSG(type_index < NUM_INTERRUPT_TYPE && pipe_index < DSP::HLE::NUM_DSP_PIPE, + "Invalid type or pipe: type = %u, pipe = %u", type_index, pipe_index); + + InterruptType type = static_cast(cmd_buff[1]); + DspPipe pipe = static_cast(cmd_buff[2]); + + cmd_buff[0] = IPC::MakeHeader(0x15, 1, 0); + if (event_handle) { auto evt = Kernel::g_handle_table.Get(cmd_buff[4]); - if (evt) { - interrupt_events[std::make_pair(interrupt, channel)] = evt; - cmd_buff[1] = RESULT_SUCCESS.raw; - LOG_INFO(Service_DSP, "Registered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); - } else { - LOG_CRITICAL(Service_DSP, "Invalid event handle! interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); - ASSERT(false); // This should really be handled at a IPC translation layer. + + if (!evt) { + LOG_INFO(Service_DSP, "Invalid event handle! type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); + ASSERT(false); // TODO: This should really be handled at an IPC translation layer. } + + if (interrupt_events.HasTooManyEventsRegistered()) { + LOG_INFO(Service_DSP, "Ran out of space to register interrupts (Attempted to register type=%u, pipe=%u, event_handle=0x%08X)", + type_index, pipe_index, event_handle); + cmd_buff[1] = ResultCode(ErrorDescription::InvalidResultValue, ErrorModule::DSP, ErrorSummary::OutOfResource, ErrorLevel::Status).raw; + return; + } + + interrupt_events.Get(type, pipe) = evt; + LOG_INFO(Service_DSP, "Registered type=%u, pipe=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); + cmd_buff[1] = RESULT_SUCCESS.raw; } else { - interrupt_events.erase(std::make_pair(interrupt, channel)); - LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", interrupt, channel, event_handle); + interrupt_events.Get(type, pipe) = nullptr; + LOG_INFO(Service_DSP, "Unregistered interrupt=%u, channel=%u, event_handle=0x%08X", type_index, pipe_index, event_handle); + cmd_buff[1] = RESULT_SUCCESS.raw; } } @@ -194,7 +256,7 @@ static void SetSemaphore(Service::Interface* self) { /** * DSP_DSP::WriteProcessPipe service function * Inputs: - * 1 : Channel + * 1 : Pipe Number * 2 : Size * 3 : (size << 14) | 0x402 * 4 : Buffer @@ -457,13 +519,14 @@ const Interface::FunctionInfo FunctionTable[] = { Interface::Interface() { semaphore_event = Kernel::Event::Create(Kernel::ResetType::OneShot, "DSP_DSP::semaphore_event"); + interrupt_events = {}; Register(FunctionTable); } Interface::~Interface() { semaphore_event = nullptr; - interrupt_events.clear(); + interrupt_events = {}; } } // namespace diff --git a/src/core/hle/service/dsp_dsp.h b/src/core/hle/service/dsp_dsp.h index 32b89e9bb1..22f6687cce 100644 --- a/src/core/hle/service/dsp_dsp.h +++ b/src/core/hle/service/dsp_dsp.h @@ -8,6 +8,12 @@ #include "core/hle/service/service.h" +namespace DSP { +namespace HLE { +enum class DspPipe; +} +} + //////////////////////////////////////////////////////////////////////////////////////////////////// // Namespace DSP_DSP @@ -23,15 +29,10 @@ public: } }; -/// Signal all audio related interrupts. -void SignalAllInterrupts(); - /** - * Signal a specific audio related interrupt based on interrupt id and channel id. - * @param interrupt_id The interrupt id - * @param channel_id The channel id - * The significance of various values of interrupt_id and channel_id is not yet known. + * Signal a specific DSP related interrupt of type == InterruptType::Pipe, pipe == pipe. + * @param pipe The DSP pipe for which to signal an interrupt for. */ -void SignalInterrupt(u32 interrupt_id, u32 channel_id); +void SignalPipeInterrupt(DSP::HLE::DspPipe pipe); -} // namespace +} // namespace DSP_DSP From 2929b67c5f76a6bb7bc99e612fc582c5de28353f Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Apr 2016 11:39:59 +0100 Subject: [PATCH 4/6] DSP_DSP: Add return IPC headers --- src/core/hle/result.h | 1 + src/core/hle/service/dsp_dsp.cpp | 30 ++++++++++++++++++++++++++---- 2 files changed, 27 insertions(+), 4 deletions(-) diff --git a/src/core/hle/result.h b/src/core/hle/result.h index 2d22652d9b..53931a1064 100644 --- a/src/core/hle/result.h +++ b/src/core/hle/result.h @@ -18,6 +18,7 @@ /// Detailed description of the error. This listing is likely incomplete. enum class ErrorDescription : u32 { Success = 0, + OS_InvalidBufferDescriptor = 48, WrongAddress = 53, FS_NotFound = 120, FS_AlreadyExists = 190, diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index e9ef50f863..58ded7eb5a 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -102,7 +102,10 @@ static void ConvertProcessAddressFromDspDram(Service::Interface* self) { u32 addr = cmd_buff[1]; + cmd_buff[0] = IPC::MakeHeader(0xC, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error + + // TODO(merry): There is a per-region offset missing in this calculation (that seems to be always zero). cmd_buff[2] = (addr << 1) + (Memory::DSP_RAM_VADDR + 0x40000); LOG_DEBUG(Service_DSP, "addr=0x%08X", addr); @@ -157,7 +160,9 @@ static void LoadComponent(Service::Interface* self) { static void GetSemaphoreEventHandle(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); + cmd_buff[0] = IPC::MakeHeader(0x16, 1, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error + // cmd_buff[2] not set cmd_buff[3] = Kernel::g_handle_table.Create(semaphore_event).MoveFrom(); // Event handle LOG_WARNING(Service_DSP, "(STUBBED) called"); @@ -182,8 +187,7 @@ static void FlushDataCache(Service::Interface* self) { u32 size = cmd_buff[2]; u32 process = cmd_buff[4]; - // TODO(purpasmart96): Verify return header on HW - + cmd_buff[0] = IPC::MakeHeader(0x13, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_TRACE(Service_DSP, "called address=0x%08X, size=0x%X, process=0x%08X", address, size, process); @@ -248,6 +252,7 @@ static void RegisterInterruptEvents(Service::Interface* self) { static void SetSemaphore(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); + cmd_buff[0] = IPC::MakeHeader(0x7, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_DSP, "(STUBBED) called"); @@ -271,17 +276,23 @@ static void WriteProcessPipe(Service::Interface* self) { u32 size = cmd_buff[2]; u32 buffer = cmd_buff[4]; - ASSERT_MSG(IPC::StaticBufferDesc(size, 1) == cmd_buff[3], "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer); + if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { + LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer); + cmd_buff[0] = IPC::MakeHeader(0, 1, 0); + cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; + return; + } + ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); std::vector message(size); - for (size_t i = 0; i < size; i++) { message[i] = Memory::Read8(buffer + i); } DSP::HLE::PipeWrite(pipe, message); + cmd_buff[0] = IPC::MakeHeader(0xD, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); @@ -311,6 +322,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); + cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { std::vector response = DSP::HLE::PipeRead(pipe, size); @@ -321,6 +333,8 @@ static void ReadPipeIfPossible(Service::Interface* self) { } else { cmd_buff[2] = 0; // Return no data } + cmd_buff[3] = IPC::StaticBufferDesc(size, 0); + cmd_buff[4] = addr; LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]); } @@ -351,8 +365,11 @@ static void ReadPipe(Service::Interface* self) { Memory::WriteBlock(addr, response.data(), response.size()); + cmd_buff[0] = IPC::MakeHeader(0xE, 2, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = static_cast(response.size()); + cmd_buff[3] = IPC::StaticBufferDesc(size, 0); + cmd_buff[4] = addr; } else { // No more data is in pipe. Hardware hangs in this case; this should never happen. UNREACHABLE(); @@ -376,6 +393,7 @@ static void GetPipeReadableSize(Service::Interface* self) { DSP::HLE::DspPipe pipe = static_cast(cmd_buff[1]); u32 unknown = cmd_buff[2]; + cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = DSP::HLE::GetPipeReadableSize(pipe); @@ -394,6 +412,7 @@ static void SetSemaphoreMask(Service::Interface* self) { u32 mask = cmd_buff[1]; + cmd_buff[0] = IPC::MakeHeader(0x17, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error LOG_WARNING(Service_DSP, "(STUBBED) called mask=0x%08X", mask); @@ -411,6 +430,7 @@ static void SetSemaphoreMask(Service::Interface* self) { static void GetHeadphoneStatus(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); + cmd_buff[0] = IPC::MakeHeader(0x1F, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = 0; // Not using headphones? @@ -437,6 +457,7 @@ static void RecvData(Service::Interface* self) { // Application reads this after requesting DSP shutdown, to verify the DSP has indeed shutdown or slept. + cmd_buff[0] = IPC::MakeHeader(0x1, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; switch (DSP::HLE::GetDspState()) { case DSP::HLE::DspState::On: @@ -472,6 +493,7 @@ static void RecvDataIsReady(Service::Interface* self) { ASSERT_MSG(register_number == 0, "Unknown register_number %u", register_number); + cmd_buff[0] = IPC::MakeHeader(0x2, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; cmd_buff[2] = 1; // Ready to read From a47f149e0769127b137ec98dcd732aff6464c333 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Sun, 24 Apr 2016 13:36:44 +0100 Subject: [PATCH 5/6] AudioCore: Hack to prevent regressions: Trigger Binary pipe interrupt every audio frame --- src/audio_core/audio_core.cpp | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/audio_core/audio_core.cpp b/src/audio_core/audio_core.cpp index 0685eaf85b..b512b0f9b2 100644 --- a/src/audio_core/audio_core.cpp +++ b/src/audio_core/audio_core.cpp @@ -20,6 +20,8 @@ static void AudioTickCallback(u64 /*userdata*/, int cycles_late) { if (DSP::HLE::Tick()) { // TODO(merry): Signal all the other interrupts as appropriate. DSP_DSP::SignalPipeInterrupt(DSP::HLE::DspPipe::Audio); + // HACK(merry): Added to prevent regressions. Will remove soon. + DSP_DSP::SignalPipeInterrupt(DSP::HLE::DspPipe::Binary); } // Reschedule recurrent event From c379b22117f61bcbeda8f8edb3035d080a4dc223 Mon Sep 17 00:00:00 2001 From: MerryMage Date: Tue, 26 Apr 2016 19:28:53 +0100 Subject: [PATCH 6/6] DSP_DSP: Fix log format strings and arguments --- src/core/hle/service/dsp_dsp.cpp | 32 ++++++++++++++++++++------------ 1 file changed, 20 insertions(+), 12 deletions(-) diff --git a/src/core/hle/service/dsp_dsp.cpp b/src/core/hle/service/dsp_dsp.cpp index 58ded7eb5a..995bee3f96 100644 --- a/src/core/hle/service/dsp_dsp.cpp +++ b/src/core/hle/service/dsp_dsp.cpp @@ -272,18 +272,20 @@ static void SetSemaphore(Service::Interface* self) { static void WriteProcessPipe(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - DSP::HLE::DspPipe pipe = static_cast(cmd_buff[1]); + u32 pipe_index = cmd_buff[1]; u32 size = cmd_buff[2]; u32 buffer = cmd_buff[4]; + DSP::HLE::DspPipe pipe = static_cast(pipe_index); + if (IPC::StaticBufferDesc(size, 1) != cmd_buff[3]) { - LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe, size, buffer); + LOG_ERROR(Service_DSP, "IPC static buffer descriptor failed validation (0x%X). pipe=%u, size=0x%X, buffer=0x%08X", cmd_buff[3], pipe_index, size, buffer); cmd_buff[0] = IPC::MakeHeader(0, 1, 0); cmd_buff[1] = ResultCode(ErrorDescription::OS_InvalidBufferDescriptor, ErrorModule::OS, ErrorSummary::WrongArgument, ErrorLevel::Permanent).raw; return; } - ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); + ASSERT_MSG(Memory::GetPointer(buffer) != nullptr, "Invalid Buffer: pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); std::vector message(size); for (size_t i = 0; i < size; i++) { @@ -295,7 +297,7 @@ static void WriteProcessPipe(Service::Interface* self) { cmd_buff[0] = IPC::MakeHeader(0xD, 1, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error - LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe, size, buffer); + LOG_DEBUG(Service_DSP, "pipe=%u, size=0x%X, buffer=0x%08X", pipe_index, size, buffer); } /** @@ -315,12 +317,14 @@ static void WriteProcessPipe(Service::Interface* self) { static void ReadPipeIfPossible(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - DSP::HLE::DspPipe pipe = static_cast(cmd_buff[1]); + u32 pipe_index = cmd_buff[1]; u32 unknown = cmd_buff[2]; u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size VAddr addr = cmd_buff[0x41]; - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); + DSP::HLE::DspPipe pipe = static_cast(pipe_index); + + ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); cmd_buff[0] = IPC::MakeHeader(0x10, 1, 2); cmd_buff[1] = RESULT_SUCCESS.raw; // No error @@ -336,7 +340,7 @@ static void ReadPipeIfPossible(Service::Interface* self) { cmd_buff[3] = IPC::StaticBufferDesc(size, 0); cmd_buff[4] = addr; - LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]); + LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); } /** @@ -353,12 +357,14 @@ static void ReadPipeIfPossible(Service::Interface* self) { static void ReadPipe(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - DSP::HLE::DspPipe pipe = static_cast(cmd_buff[1]); + u32 pipe_index = cmd_buff[1]; u32 unknown = cmd_buff[2]; u32 size = cmd_buff[3] & 0xFFFF; // Lower 16 bits are size VAddr addr = cmd_buff[0x41]; - ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe, unknown, size, addr); + DSP::HLE::DspPipe pipe = static_cast(pipe_index); + + ASSERT_MSG(Memory::GetPointer(addr) != nullptr, "Invalid addr: pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X", pipe_index, unknown, size, addr); if (DSP::HLE::GetPipeReadableSize(pipe) >= size) { std::vector response = DSP::HLE::PipeRead(pipe, size); @@ -375,7 +381,7 @@ static void ReadPipe(Service::Interface* self) { UNREACHABLE(); } - LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, size, addr, cmd_buff[2]); + LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, size=0x%X, buffer=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, size, addr, cmd_buff[2]); } /** @@ -390,14 +396,16 @@ static void ReadPipe(Service::Interface* self) { static void GetPipeReadableSize(Service::Interface* self) { u32* cmd_buff = Kernel::GetCommandBuffer(); - DSP::HLE::DspPipe pipe = static_cast(cmd_buff[1]); + u32 pipe_index = cmd_buff[1]; u32 unknown = cmd_buff[2]; + DSP::HLE::DspPipe pipe = static_cast(pipe_index); + cmd_buff[0] = IPC::MakeHeader(0xF, 2, 0); cmd_buff[1] = RESULT_SUCCESS.raw; // No error cmd_buff[2] = DSP::HLE::GetPipeReadableSize(pipe); - LOG_DEBUG(Service_DSP, "pipe=0x%08X, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe, unknown, cmd_buff[2]); + LOG_DEBUG(Service_DSP, "pipe=%u, unknown=0x%08X, return cmd_buff[2]=0x%08X", pipe_index, unknown, cmd_buff[2]); } /**