From 19e1ea6a02f6593ed47180e6591ae91eede20c18 Mon Sep 17 00:00:00 2001
From: Kelebek1 <eeeedddccc@hotmail.co.uk>
Date: Fri, 10 Feb 2023 21:06:34 +0000
Subject: [PATCH 1/2] Fix depop prepare receiving bad mix infos and writing out
 of bounds, and update aux a bit, may help

---
 .../renderer/command/command_generator.cpp    |  2 +-
 .../renderer/command/effect/aux_.cpp          | 78 +++++++++----------
 2 files changed, 40 insertions(+), 40 deletions(-)

diff --git a/src/audio_core/renderer/command/command_generator.cpp b/src/audio_core/renderer/command/command_generator.cpp
index 2ea50d128..fba84c7bd 100644
--- a/src/audio_core/renderer/command/command_generator.cpp
+++ b/src/audio_core/renderer/command/command_generator.cpp
@@ -46,7 +46,7 @@ void CommandGenerator::GenerateDataSourceCommand(VoiceInfo& voice_info,
             while (destination != nullptr) {
                 if (destination->IsConfigured()) {
                     auto mix_id{destination->GetMixId()};
-                    if (mix_id < mix_context.GetCount()) {
+                    if (mix_id < mix_context.GetCount() && mix_id != UnusedSplitterId) {
                         auto mix_info{mix_context.GetInfo(mix_id)};
                         command_buffer.GenerateDepopPrepareCommand(
                             voice_info.node_id, voice_state, render_context.depop_buffer,
diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp
index e76db893f..0c69dcc28 100644
--- a/src/audio_core/renderer/command/effect/aux_.cpp
+++ b/src/audio_core/renderer/command/effect/aux_.cpp
@@ -4,6 +4,7 @@
 #include "audio_core/renderer/adsp/command_list_processor.h"
 #include "audio_core/renderer/command/effect/aux_.h"
 #include "audio_core/renderer/effect/aux_.h"
+#include "core/core.h"
 #include "core/memory.h"
 
 namespace AudioCore::AudioRenderer {
@@ -40,11 +41,10 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
  * @param update_count - If non-zero, send_info_ will be updated.
  * @return Number of samples written.
  */
-static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_info_,
-                             [[maybe_unused]] u32 sample_count, const CpuAddr send_buffer,
-                             const u32 count_max, std::span<const s32> input,
-                             const u32 write_count_, const u32 write_offset,
-                             const u32 update_count) {
+static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
+                             [[maybe_unused]] u32 sample_count, CpuAddr send_buffer, u32 count_max,
+                             std::span<const s32> input, u32 write_count_, u32 write_offset,
+                             u32 update_count) {
     if (write_count_ > count_max) {
         LOG_ERROR(Service_Audio,
                   "write_count must be smaller than count_max! write_count {}, count_max {}",
@@ -52,6 +52,11 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
         return 0;
     }
 
+    if (send_info_ == 0) {
+        LOG_ERROR(Service_Audio, "send_info_ is 0!");
+        return 0;
+    }
+
     if (input.empty()) {
         LOG_ERROR(Service_Audio, "input buffer is empty!");
         return 0;
@@ -66,35 +71,30 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
         return 0;
     }
 
-    AuxInfo::AuxInfoDsp send_info{};
-    memory.ReadBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
+    auto send_info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(send_info_))};
 
-    u32 target_write_offset{send_info.write_offset + write_offset};
-    if (target_write_offset > count_max || write_count_ == 0) {
+    u32 target_write_offset{send_info->write_offset + write_offset};
+    if (target_write_offset > count_max) {
         return 0;
     }
 
     u32 write_count{write_count_};
-    u32 write_pos{0};
+    u32 read_pos{0};
     while (write_count > 0) {
         u32 to_write{std::min(count_max - target_write_offset, write_count)};
-
-        if (to_write > 0) {
+        if (to_write) {
             memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
-                                    &input[write_pos], to_write * sizeof(s32));
+                                    &input[read_pos], to_write * sizeof(s32));
         }
-
         target_write_offset = (target_write_offset + to_write) % count_max;
         write_count -= to_write;
-        write_pos += to_write;
+        read_pos += to_write;
     }
 
     if (update_count) {
-        send_info.write_offset = (send_info.write_offset + update_count) % count_max;
+        send_info->write_offset = (send_info->write_offset + update_count) % count_max;
     }
 
-    memory.WriteBlockUnsafe(send_info_, &send_info, sizeof(AuxInfo::AuxInfoDsp));
-
     return write_count_;
 }
 
@@ -102,7 +102,7 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
  * Read the given memory at return_buffer into the output mix buffer, and update return_info_ if
  * update_count is set, to notify the game that an update happened.
  *
- * @param memory        - Core memory for writing.
+ * @param memory        - Core memory for reading.
  * @param return_info_  - Meta information for where to read the mix buffer.
  * @param return_buffer - Memory address to read the samples from.
  * @param count_max     - Maximum number of samples in the receiving buffer.
@@ -112,16 +112,21 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr send_in
  * @param update_count  - If non-zero, send_info_ will be updated.
  * @return Number of samples read.
  */
-static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_info_,
-                            const CpuAddr return_buffer, const u32 count_max, std::span<s32> output,
-                            const u32 count_, const u32 read_offset, const u32 update_count) {
+static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
+                            CpuAddr return_buffer, u32 count_max, std::span<s32> output,
+                            u32 read_count_, u32 read_offset, u32 update_count) {
     if (count_max == 0) {
         return 0;
     }
 
-    if (count_ > count_max) {
+    if (read_count_ > count_max) {
         LOG_ERROR(Service_Audio, "count must be smaller than count_max! count {}, count_max {}",
-                  count_, count_max);
+                  read_count_, count_max);
+        return 0;
+    }
+
+    if (return_info_ == 0) {
+        LOG_ERROR(Service_Audio, "return_info_ is 0!");
         return 0;
     }
 
@@ -135,36 +140,31 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr return_i
         return 0;
     }
 
-    AuxInfo::AuxInfoDsp return_info{};
-    memory.ReadBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
+    auto return_info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(return_info_))};
 
-    u32 target_read_offset{return_info.read_offset + read_offset};
+    u32 target_read_offset{return_info->read_offset + read_offset};
     if (target_read_offset > count_max) {
         return 0;
     }
 
-    u32 read_count{count_};
-    u32 read_pos{0};
+    u32 read_count{read_count_};
+    u32 write_pos{0};
     while (read_count > 0) {
         u32 to_read{std::min(count_max - target_read_offset, read_count)};
-
-        if (to_read > 0) {
+        if (to_read) {
             memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
-                                   &output[read_pos], to_read * sizeof(s32));
+                                   &output[write_pos], to_read * sizeof(s32));
         }
-
         target_read_offset = (target_read_offset + to_read) % count_max;
         read_count -= to_read;
-        read_pos += to_read;
+        write_pos += to_read;
     }
 
     if (update_count) {
-        return_info.read_offset = (return_info.read_offset + update_count) % count_max;
+        return_info->read_offset = (return_info->read_offset + update_count) % count_max;
     }
 
-    memory.WriteBlockUnsafe(return_info_, &return_info, sizeof(AuxInfo::AuxInfoDsp));
-
-    return count_;
+    return read_count_;
 }
 
 void AuxCommand::Dump([[maybe_unused]] const ADSP::CommandListProcessor& processor,
@@ -189,7 +189,7 @@ void AuxCommand::Process(const ADSP::CommandListProcessor& processor) {
                                    update_count)};
 
         if (read != processor.sample_count) {
-            std::memset(&output_buffer[read], 0, processor.sample_count - read);
+            std::memset(&output_buffer[read], 0, (processor.sample_count - read) * sizeof(s32));
         }
     } else {
         ResetAuxBufferDsp(*processor.memory, send_buffer_info);

From 2e02ed8bb574255383667969a46280d435964c2c Mon Sep 17 00:00:00 2001
From: Kelebek1 <eeeedddccc@hotmail.co.uk>
Date: Sat, 11 Feb 2023 16:27:43 +0000
Subject: [PATCH 2/2] Add fallback for memory read/write in case the address
 goes over a 4K page

---
 .../renderer/command/effect/aux_.cpp          | 76 ++++++++++++++++---
 1 file changed, 64 insertions(+), 12 deletions(-)

diff --git a/src/audio_core/renderer/command/effect/aux_.cpp b/src/audio_core/renderer/command/effect/aux_.cpp
index 0c69dcc28..c5650effa 100644
--- a/src/audio_core/renderer/command/effect/aux_.cpp
+++ b/src/audio_core/renderer/command/effect/aux_.cpp
@@ -20,10 +20,24 @@ static void ResetAuxBufferDsp(Core::Memory::Memory& memory, const CpuAddr aux_in
         return;
     }
 
-    auto info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(aux_info))};
-    info->read_offset = 0;
-    info->write_offset = 0;
-    info->total_sample_count = 0;
+    AuxInfo::AuxInfoDsp info{};
+    auto info_ptr{&info};
+    bool host_safe{(aux_info & Core::Memory::YUZU_PAGEMASK) <=
+                   (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp))};
+
+    if (host_safe) [[likely]] {
+        info_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(aux_info);
+    } else {
+        memory.ReadBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
+    }
+
+    info_ptr->read_offset = 0;
+    info_ptr->write_offset = 0;
+    info_ptr->total_sample_count = 0;
+
+    if (!host_safe) [[unlikely]] {
+        memory.WriteBlockUnsafe(aux_info, info_ptr, sizeof(AuxInfo::AuxInfoDsp));
+    }
 }
 
 /**
@@ -71,9 +85,18 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
         return 0;
     }
 
-    auto send_info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(send_info_))};
+    AuxInfo::AuxInfoDsp send_info{};
+    auto send_ptr = &send_info;
+    bool host_safe = (send_info_ & Core::Memory::YUZU_PAGEMASK) <=
+                     (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
 
-    u32 target_write_offset{send_info->write_offset + write_offset};
+    if (host_safe) [[likely]] {
+        send_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(send_info_);
+    } else {
+        memory.ReadBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
+    }
+
+    u32 target_write_offset{send_ptr->write_offset + write_offset};
     if (target_write_offset > count_max) {
         return 0;
     }
@@ -82,7 +105,13 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
     u32 read_pos{0};
     while (write_count > 0) {
         u32 to_write{std::min(count_max - target_write_offset, write_count)};
-        if (to_write) {
+        const auto write_addr = send_buffer + target_write_offset * sizeof(s32);
+        bool write_safe{(write_addr & Core::Memory::YUZU_PAGEMASK) <=
+                        (Core::Memory::YUZU_PAGESIZE - (write_addr + to_write * sizeof(s32)))};
+        if (write_safe) [[likely]] {
+            auto ptr = memory.GetPointer(write_addr);
+            std::memcpy(ptr, &input[read_pos], to_write * sizeof(s32));
+        } else {
             memory.WriteBlockUnsafe(send_buffer + target_write_offset * sizeof(s32),
                                     &input[read_pos], to_write * sizeof(s32));
         }
@@ -92,7 +121,11 @@ static u32 WriteAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr send_info_,
     }
 
     if (update_count) {
-        send_info->write_offset = (send_info->write_offset + update_count) % count_max;
+        send_ptr->write_offset = (send_ptr->write_offset + update_count) % count_max;
+    }
+
+    if (!host_safe) [[unlikely]] {
+        memory.WriteBlockUnsafe(send_info_, send_ptr, sizeof(AuxInfo::AuxInfoDsp));
     }
 
     return write_count_;
@@ -140,9 +173,18 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
         return 0;
     }
 
-    auto return_info{reinterpret_cast<AuxInfo::AuxInfoDsp*>(memory.GetPointer(return_info_))};
+    AuxInfo::AuxInfoDsp return_info{};
+    auto return_ptr = &return_info;
+    bool host_safe = (return_info_ & Core::Memory::YUZU_PAGEMASK) <=
+                     (Core::Memory::YUZU_PAGESIZE - sizeof(AuxInfo::AuxInfoDsp));
 
-    u32 target_read_offset{return_info->read_offset + read_offset};
+    if (host_safe) [[likely]] {
+        return_ptr = memory.GetPointer<AuxInfo::AuxInfoDsp>(return_info_);
+    } else {
+        memory.ReadBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
+    }
+
+    u32 target_read_offset{return_ptr->read_offset + read_offset};
     if (target_read_offset > count_max) {
         return 0;
     }
@@ -151,7 +193,13 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
     u32 write_pos{0};
     while (read_count > 0) {
         u32 to_read{std::min(count_max - target_read_offset, read_count)};
-        if (to_read) {
+        const auto read_addr = return_buffer + target_read_offset * sizeof(s32);
+        bool read_safe{(read_addr & Core::Memory::YUZU_PAGEMASK) <=
+                       (Core::Memory::YUZU_PAGESIZE - (read_addr + to_read * sizeof(s32)))};
+        if (read_safe) [[likely]] {
+            auto ptr = memory.GetPointer(read_addr);
+            std::memcpy(&output[write_pos], ptr, to_read * sizeof(s32));
+        } else {
             memory.ReadBlockUnsafe(return_buffer + target_read_offset * sizeof(s32),
                                    &output[write_pos], to_read * sizeof(s32));
         }
@@ -161,7 +209,11 @@ static u32 ReadAuxBufferDsp(Core::Memory::Memory& memory, CpuAddr return_info_,
     }
 
     if (update_count) {
-        return_info->read_offset = (return_info->read_offset + update_count) % count_max;
+        return_ptr->read_offset = (return_ptr->read_offset + update_count) % count_max;
+    }
+
+    if (!host_safe) [[unlikely]] {
+        memory.WriteBlockUnsafe(return_info_, return_ptr, sizeof(AuxInfo::AuxInfoDsp));
     }
 
     return read_count_;