From e140516130f18b118f5b258d366379af72cefc70 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 23 Jan 2023 15:06:57 -0800 Subject: [PATCH 1/2] DSPLLE: Add assertion for bad DMA alignment I haven't tested this extensively on real hardware, but I do know that bad things happen if the address isn't properly aligned, and libogc says it should be 32-byte aligned. --- Source/Core/Core/HW/DSPLLE/DSPHost.cpp | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/Source/Core/Core/HW/DSPLLE/DSPHost.cpp b/Source/Core/Core/HW/DSPLLE/DSPHost.cpp index 6c359929fe..51fedc190f 100644 --- a/Source/Core/Core/HW/DSPLLE/DSPHost.cpp +++ b/Source/Core/Core/HW/DSPLLE/DSPHost.cpp @@ -5,6 +5,7 @@ #include +#include "Common/Assert.h" #include "Common/CommonTypes.h" #include "Common/Hash.h" #include "Common/Logging/Log.h" @@ -40,6 +41,11 @@ void WriteHostMemory(u8 value, u32 addr) void DMAToDSP(u16* dst, u32 addr, u32 size) { + // Hardware testing indicates that a misaligned DMA address does not work properly (it's unclear + // exactly what goes wrong currently). A size that's not a multiple of 32 is allowed, though + // (and occurs with modern libogc homebrew uCode, including the oggpalyer (asnd uCode) and + // modplay (aesnd uCode) examples). It's untested whether extra bytes are copied in that case. + ASSERT_MSG(DSPLLE, (addr & 0x1f) == 0, "DSP DMA addr must be 32-byte aligned (was {:08x})", addr); auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); memory.CopyFromEmuSwapped(dst, addr, size); @@ -47,6 +53,8 @@ void DMAToDSP(u16* dst, u32 addr, u32 size) void DMAFromDSP(const u16* src, u32 addr, u32 size) { + // See comment in DMAToDSP + ASSERT_MSG(DSPLLE, (addr & 0x1f) == 0, "DSP DMA addr must be 32-byte aligned (was {:08x})", addr); auto& system = Core::System::GetInstance(); auto& memory = system.GetMemory(); memory.CopyToEmuSwapped(addr, src, size); From e391a281024a8f8283160b03aa3703405e037ed7 Mon Sep 17 00:00:00 2001 From: Pokechu22 Date: Mon, 23 Jan 2023 15:30:49 -0800 Subject: [PATCH 2/2] DSPTool: Generate an alignment specifier alignas is a C++ keyword since C++11, and can be used in C with a header too (although I don't know the details). --- Source/DSPTool/DSPTool.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/DSPTool/DSPTool.cpp b/Source/DSPTool/DSPTool.cpp index 46d71b4bf9..2f99d56522 100644 --- a/Source/DSPTool/DSPTool.cpp +++ b/Source/DSPTool/DSPTool.cpp @@ -68,7 +68,7 @@ static std::string CodeToHeader(const std::vector& code, const std::string& SplitPath(filename, nullptr, &filename_without_extension, nullptr); header.append(fmt::format("const char* UCODE_NAMES[NUM_UCODES] = {{\"{}\"}};\n\n", filename_without_extension)); - header.append("const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n"); + header.append("alignas(0x20) const unsigned short dsp_code[NUM_UCODES][0x1000] = {\n"); header.append("\t{\n\t\t"); for (u32 j = 0; j < code_padded.size(); j++)