From 207fe1f5de36a4d0cffebef6559b770a15b571d5 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 30 Mar 2026 18:04:30 -0500 Subject: [PATCH 1/3] HW/HSP: Make IHSPDevice::GetDeviceType a virtual function to eliminate `m_device_type`. --- Source/Core/Core/HW/HSP/HSP_Device.cpp | 16 ++++------------ Source/Core/Core/HW/HSP/HSP_Device.h | 8 ++------ .../Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp | 2 +- .../Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h | 6 ++++-- Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp | 7 +++---- Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h | 6 ++++-- Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp | 5 ----- Source/Core/Core/HW/HSP/HSP_DeviceNull.h | 4 ++-- 8 files changed, 20 insertions(+), 34 deletions(-) diff --git a/Source/Core/Core/HW/HSP/HSP_Device.cpp b/Source/Core/Core/HW/HSP/HSP_Device.cpp index 7a75afc79c..6140eb17d5 100644 --- a/Source/Core/Core/HW/HSP/HSP_Device.cpp +++ b/Source/Core/Core/HW/HSP/HSP_Device.cpp @@ -12,20 +12,12 @@ namespace HSP { -IHSPDevice::IHSPDevice(HSPDeviceType device_type) : m_device_type(device_type) -{ -} - -HSPDeviceType IHSPDevice::GetDeviceType() const -{ - return m_device_type; -} +IHSPDevice::~IHSPDevice() = default; void IHSPDevice::DoState(PointerWrap& p) { } -// F A C T O R Y std::unique_ptr HSPDevice_Create(const HSPDeviceType device) { auto& system = Core::System::GetInstance(); @@ -33,12 +25,12 @@ std::unique_ptr HSPDevice_Create(const HSPDeviceType device) switch (device) { case HSPDeviceType::ARAMExpansion: - return std::make_unique(device); + return std::make_unique(); case HSPDeviceType::GBPlayer: - return std::make_unique(system, device); + return std::make_unique(system); case HSPDeviceType::None: default: - return std::make_unique(device); + return std::make_unique(); } } } // namespace HSP diff --git a/Source/Core/Core/HW/HSP/HSP_Device.h b/Source/Core/Core/HW/HSP/HSP_Device.h index baf8fc025e..faca30f2b9 100644 --- a/Source/Core/Core/HW/HSP/HSP_Device.h +++ b/Source/Core/Core/HW/HSP/HSP_Device.h @@ -21,19 +21,15 @@ enum class HSPDeviceType : int class IHSPDevice { public: - explicit IHSPDevice(HSPDeviceType device_type); - virtual ~IHSPDevice() = default; + virtual ~IHSPDevice(); - HSPDeviceType GetDeviceType() const; + virtual HSPDeviceType GetDeviceType() const = 0; virtual void Write(u32 address, u64 value) = 0; virtual u64 Read(u32 address) = 0; // Savestate support virtual void DoState(PointerWrap& p); - -protected: - HSPDeviceType m_device_type; }; std::unique_ptr HSPDevice_Create(HSPDeviceType device); diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp index 34fdc1b613..a182d6b932 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp @@ -14,7 +14,7 @@ namespace HSP { -CHSPDevice_ARAMExpansion::CHSPDevice_ARAMExpansion(HSPDeviceType device) : IHSPDevice(device) +CHSPDevice_ARAMExpansion::CHSPDevice_ARAMExpansion() { m_size = MathUtil::NextPowerOf2(Config::Get(Config::MAIN_ARAM_EXPANSION_SIZE)); m_mask = m_size - 1; diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h index 8efa766286..b584e4118b 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h @@ -7,12 +7,14 @@ namespace HSP { -class CHSPDevice_ARAMExpansion : public IHSPDevice +class CHSPDevice_ARAMExpansion final : public IHSPDevice { public: - explicit CHSPDevice_ARAMExpansion(HSPDeviceType device); + explicit CHSPDevice_ARAMExpansion(); ~CHSPDevice_ARAMExpansion() override; + HSPDeviceType GetDeviceType() const override { return HSPDeviceType::ARAMExpansion; } + void Write(u32 address, u64 value) override; u64 Read(u32 address) override; diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp index 470ba38a23..20a9998e15 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp @@ -53,7 +53,7 @@ constexpr u8 CONTROL_MASK_IRQ = 0x10; constexpr u32 COMMAND_ADDRESS_MASK = 0x1f; constexpr u32 AV_ADDRESS_MASK = 0xff8; -class CGBPlayer_Dummy : public HSP::IGBPlayer +class CGBPlayer_Dummy final : public HSP::IGBPlayer { public: using IGBPlayer::IGBPlayer; @@ -89,7 +89,7 @@ enum class CHSPDevice_GBPlayer::IRQ : int #if defined(HAS_LIBMGBA) -class CGBPlayer_mGBA : public IGBPlayer +class CGBPlayer_mGBA final : public IGBPlayer { public: CGBPlayer_mGBA(Core::System&, CHSPDevice_GBPlayer*); @@ -389,8 +389,7 @@ void CGBPlayer_mGBA::UpdateVideo(u32 scanline_index, s64 cycles_late) #endif -CHSPDevice_GBPlayer::CHSPDevice_GBPlayer(Core::System& system, HSPDeviceType device) - : IHSPDevice(device), m_system{system} +CHSPDevice_GBPlayer::CHSPDevice_GBPlayer(Core::System& system) : m_system{system} { #if defined(HAS_LIBMGBA) m_gbp = std::make_unique(m_system, this); diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h index ba93412de0..18f096e640 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h @@ -50,12 +50,14 @@ protected: CHSPDevice_GBPlayer* const m_player; }; -class CHSPDevice_GBPlayer : public IHSPDevice +class CHSPDevice_GBPlayer final : public IHSPDevice { public: enum class IRQ : int; - CHSPDevice_GBPlayer(Core::System& system, HSPDeviceType device); + explicit CHSPDevice_GBPlayer(Core::System& system); + + HSPDeviceType GetDeviceType() const override { return HSPDeviceType::GBPlayer; } void Write(u32 address, u64 value) override; u64 Read(u32 address) override; diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp index 3527ecc778..e11586f97f 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp @@ -3,13 +3,8 @@ #include "Core/HW/HSP/HSP_DeviceNull.h" -#include "Core/HW/HSP/HSP.h" - namespace HSP { -CHSPDevice_Null::CHSPDevice_Null(HSPDeviceType device) : IHSPDevice(device) -{ -} u64 CHSPDevice_Null::Read(u32 address) { diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceNull.h b/Source/Core/Core/HW/HSP/HSP_DeviceNull.h index afadddd475..62b500215b 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceNull.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceNull.h @@ -8,10 +8,10 @@ namespace HSP { -class CHSPDevice_Null : public IHSPDevice +class CHSPDevice_Null final : public IHSPDevice { public: - explicit CHSPDevice_Null(HSPDeviceType device); + HSPDeviceType GetDeviceType() const override { return HSPDeviceType::None; } void Write(u32 address, u64 value) override; u64 Read(u32 address) override; From 187fcfa7dc61215778f7de5c7688c8c1de003bb4 Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 30 Mar 2026 18:12:11 -0500 Subject: [PATCH 2/3] HW/HSP: Ensure an IHSPDevice object always exists to remove null checks as a micro optimization. --- Source/Core/Core/HW/HSP/HSP.cpp | 33 ++++++++++++++------------------- Source/Core/Core/HW/HSP/HSP.h | 5 ++--- 2 files changed, 16 insertions(+), 22 deletions(-) diff --git a/Source/Core/Core/HW/HSP/HSP.cpp b/Source/Core/Core/HW/HSP/HSP.cpp index 87fccd34f9..d53d0d2d26 100644 --- a/Source/Core/Core/HW/HSP/HSP.cpp +++ b/Source/Core/Core/HW/HSP/HSP.cpp @@ -16,54 +16,49 @@ HSPManager::~HSPManager() = default; void HSPManager::Init() { - AddDevice(Config::Get(Config::MAIN_HSP_DEVICE)); + SetDevice(Config::Get(Config::MAIN_HSP_DEVICE)); } void HSPManager::Shutdown() { - RemoveDevice(); + m_device.reset(); } u64 HSPManager::Read(u32 address) { DEBUG_LOG_FMT(HSP, "HSP read from 0x{:08x}", address); - if (m_device) - return m_device->Read(address); - return 0; + + return m_device->Read(address); } void HSPManager::Write(u32 address, u64 value) { DEBUG_LOG_FMT(HSP, "HSP write to 0x{:08x}: 0x{:016x}", address, value); - if (m_device) - m_device->Write(address, value); + + m_device->Write(address, value); } void HSPManager::DoState(PointerWrap& p) { - HSPDeviceType type = m_device->GetDeviceType(); - p.Do(type); + const HSPDeviceType current_type = m_device->GetDeviceType(); + auto state_type = current_type; + p.Do(state_type); // If the type doesn't match, switch to the right device type - if (type != m_device->GetDeviceType()) - AddDevice(type); + if (state_type != current_type) + SetDevice(state_type); m_device->DoState(p); } -void HSPManager::AddDevice(std::unique_ptr device) +void HSPManager::SetDevice(std::unique_ptr device) { - // Set the new one m_device = std::move(device); } -void HSPManager::AddDevice(const HSPDeviceType device) +void HSPManager::SetDevice(const HSPDeviceType device) { - AddDevice(HSPDevice_Create(device)); + SetDevice(HSPDevice_Create(device)); } -void HSPManager::RemoveDevice() -{ - m_device.reset(); -} } // namespace HSP diff --git a/Source/Core/Core/HW/HSP/HSP.h b/Source/Core/Core/HW/HSP/HSP.h index 5882e4b912..b588d26624 100644 --- a/Source/Core/Core/HW/HSP/HSP.h +++ b/Source/Core/Core/HW/HSP/HSP.h @@ -32,9 +32,8 @@ public: void DoState(PointerWrap& p); - void RemoveDevice(); - void AddDevice(std::unique_ptr device); - void AddDevice(HSPDeviceType device); + void SetDevice(std::unique_ptr device); + void SetDevice(HSPDeviceType device); private: std::unique_ptr m_device; From 9410094d9ff89a526ce353f5607245120321962c Mon Sep 17 00:00:00 2001 From: Jordan Woyak Date: Mon, 30 Mar 2026 19:20:11 -0500 Subject: [PATCH 3/3] HW/HSP: Change Read/Write interface to use `span` instead of four calls with swapped u64 values. --- Source/Core/Core/HW/DSP.cpp | 35 +++++++--- Source/Core/Core/HW/HSP/HSP.cpp | 12 ++-- Source/Core/Core/HW/HSP/HSP.h | 9 ++- Source/Core/Core/HW/HSP/HSP_Device.h | 10 ++- .../Core/HW/HSP/HSP_DeviceARAMExpansion.cpp | 18 ++--- .../Core/HW/HSP/HSP_DeviceARAMExpansion.h | 10 +-- .../Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp | 67 +++++++++---------- Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h | 4 +- Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp | 5 +- Source/Core/Core/HW/HSP/HSP_DeviceNull.h | 4 +- 10 files changed, 93 insertions(+), 81 deletions(-) diff --git a/Source/Core/Core/HW/DSP.cpp b/Source/Core/Core/HW/DSP.cpp index 3abea2bea8..ae46113e79 100644 --- a/Source/Core/Core/HW/DSP.cpp +++ b/Source/Core/Core/HW/DSP.cpp @@ -505,12 +505,20 @@ void DSPManager::Do_ARAM_DMA() } else if (!m_aram.wii_mode) { - while (m_aram_dma.Cnt.count) + auto* mm_ptr = memory.GetPointerForRange(m_aram_dma.MMAddr, m_aram_dma.Cnt.count); + if (mm_ptr != nullptr) { - memory.Write_U64(m_system.GetHSP().Read(m_aram_dma.ARAddr), m_aram_dma.MMAddr); - m_aram_dma.MMAddr += 8; - m_aram_dma.ARAddr += 8; - m_aram_dma.Cnt.count -= 8; + auto& hsp = m_system.GetHSP(); + while (m_aram_dma.Cnt.count) + { + hsp.Read(m_aram_dma.ARAddr, + std::span(mm_ptr, HSP::TRANSFER_SIZE)); + + m_aram_dma.MMAddr += HSP::TRANSFER_SIZE; + m_aram_dma.ARAddr += HSP::TRANSFER_SIZE; + m_aram_dma.Cnt.count -= HSP::TRANSFER_SIZE; + mm_ptr += HSP::TRANSFER_SIZE; + } } } } @@ -557,13 +565,20 @@ void DSPManager::Do_ARAM_DMA() } else if (!m_aram.wii_mode) { - while (m_aram_dma.Cnt.count) + auto* mm_ptr = memory.GetPointerForRange(m_aram_dma.MMAddr, m_aram_dma.Cnt.count); + if (mm_ptr != nullptr) { - m_system.GetHSP().Write(m_aram_dma.ARAddr, memory.Read_U64(m_aram_dma.MMAddr)); + auto& hsp = m_system.GetHSP(); + while (m_aram_dma.Cnt.count) + { + hsp.Write(m_aram_dma.ARAddr, + std::span(mm_ptr, HSP::TRANSFER_SIZE)); - m_aram_dma.MMAddr += 8; - m_aram_dma.ARAddr += 8; - m_aram_dma.Cnt.count -= 8; + m_aram_dma.MMAddr += HSP::TRANSFER_SIZE; + m_aram_dma.ARAddr += HSP::TRANSFER_SIZE; + m_aram_dma.Cnt.count -= HSP::TRANSFER_SIZE; + mm_ptr += HSP::TRANSFER_SIZE; + } } } } diff --git a/Source/Core/Core/HW/HSP/HSP.cpp b/Source/Core/Core/HW/HSP/HSP.cpp index d53d0d2d26..c4cc5af029 100644 --- a/Source/Core/Core/HW/HSP/HSP.cpp +++ b/Source/Core/Core/HW/HSP/HSP.cpp @@ -5,6 +5,8 @@ #include +#include + #include "Common/ChunkFile.h" #include "Core/Config/MainSettings.h" #include "Core/HW/HSP/HSP_Device.h" @@ -24,18 +26,18 @@ void HSPManager::Shutdown() m_device.reset(); } -u64 HSPManager::Read(u32 address) +void HSPManager::Read(u32 address, std::span data) { DEBUG_LOG_FMT(HSP, "HSP read from 0x{:08x}", address); - return m_device->Read(address); + m_device->Read(address, data); } -void HSPManager::Write(u32 address, u64 value) +void HSPManager::Write(u32 address, std::span data) { - DEBUG_LOG_FMT(HSP, "HSP write to 0x{:08x}: 0x{:016x}", address, value); + DEBUG_LOG_FMT(HSP, "HSP write to 0x{:08x}: {:02x}", address, fmt::join(data, " ")); - m_device->Write(address, value); + m_device->Write(address, data); } void HSPManager::DoState(PointerWrap& p) diff --git a/Source/Core/Core/HW/HSP/HSP.h b/Source/Core/Core/HW/HSP/HSP.h index b588d26624..f0ff14d5b9 100644 --- a/Source/Core/Core/HW/HSP/HSP.h +++ b/Source/Core/Core/HW/HSP/HSP.h @@ -4,16 +4,15 @@ #pragma once #include +#include #include "Common/CommonTypes.h" +#include "Core/HW/HSP/HSP_Device.h" class PointerWrap; namespace HSP { -class IHSPDevice; -enum class HSPDeviceType : int; - class HSPManager { public: @@ -27,8 +26,8 @@ public: void Init(); void Shutdown(); - u64 Read(u32 address); - void Write(u32 address, u64 value); + void Read(u32 address, std::span data); + void Write(u32 address, std::span data); void DoState(PointerWrap& p); diff --git a/Source/Core/Core/HW/HSP/HSP_Device.h b/Source/Core/Core/HW/HSP/HSP_Device.h index faca30f2b9..33cb69989b 100644 --- a/Source/Core/Core/HW/HSP/HSP_Device.h +++ b/Source/Core/Core/HW/HSP/HSP_Device.h @@ -4,6 +4,7 @@ #pragma once #include +#include #include "Common/CommonTypes.h" @@ -11,6 +12,9 @@ class PointerWrap; namespace HSP { + +static constexpr std::size_t TRANSFER_SIZE = 32; + enum class HSPDeviceType : int { None, @@ -25,8 +29,10 @@ public: virtual HSPDeviceType GetDeviceType() const = 0; - virtual void Write(u32 address, u64 value) = 0; - virtual u64 Read(u32 address) = 0; + // Note: DSPManager::RegisterMMIO ensures addresses are 32 byte aligned. + + virtual void Read(u32 address, std::span data) = 0; + virtual void Write(u32 address, std::span data) = 0; // Savestate support virtual void DoState(PointerWrap& p); diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp index a182d6b932..1ad66c9830 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.cpp @@ -8,36 +8,30 @@ #include "Common/ChunkFile.h" #include "Common/MathUtil.h" #include "Common/MemoryUtil.h" -#include "Common/Swap.h" #include "Core/Config/MainSettings.h" namespace HSP { CHSPDevice_ARAMExpansion::CHSPDevice_ARAMExpansion() + : m_size{MathUtil::NextPowerOf2(Config::Get(Config::MAIN_ARAM_EXPANSION_SIZE))}, + m_mask{m_size - 1}, m_ptr{static_cast(Common::AllocateMemoryPages(m_size))} { - m_size = MathUtil::NextPowerOf2(Config::Get(Config::MAIN_ARAM_EXPANSION_SIZE)); - m_mask = m_size - 1; - m_ptr = static_cast(Common::AllocateMemoryPages(m_size)); } CHSPDevice_ARAMExpansion::~CHSPDevice_ARAMExpansion() { Common::FreeMemoryPages(m_ptr, m_size); - m_ptr = nullptr; } -u64 CHSPDevice_ARAMExpansion::Read(u32 address) +void CHSPDevice_ARAMExpansion::Read(u32 address, std::span data) { - u64 value; - std::memcpy(&value, &m_ptr[address & m_mask], sizeof(value)); - return Common::swap64(value); + std::memcpy(data.data(), m_ptr + (address & m_mask), data.size()); } -void CHSPDevice_ARAMExpansion::Write(u32 address, u64 value) +void CHSPDevice_ARAMExpansion::Write(u32 address, std::span data) { - value = Common::swap64(value); - std::memcpy(&m_ptr[address & m_mask], &value, sizeof(value)); + std::memcpy(m_ptr + (address & m_mask), data.data(), data.size()); } void CHSPDevice_ARAMExpansion::DoState(PointerWrap& p) diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h index b584e4118b..e37a151201 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceARAMExpansion.h @@ -15,14 +15,14 @@ public: HSPDeviceType GetDeviceType() const override { return HSPDeviceType::ARAMExpansion; } - void Write(u32 address, u64 value) override; - u64 Read(u32 address) override; + void Read(u32 address, std::span data) override; + void Write(u32 address, std::span data) override; void DoState(PointerWrap&) override; private: - u32 m_size; - u32 m_mask; - u8* m_ptr = nullptr; + const u32 m_size; + const u32 m_mask; + u8* const m_ptr = nullptr; }; } // namespace HSP diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp index 20a9998e15..68af359028 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.cpp @@ -17,6 +17,7 @@ #include "Common/ChunkFile.h" #include "Common/Logging/Log.h" +#include "Common/Swap.h" #include "Core/Config/MainSettings.h" #include "Core/CoreTiming.h" @@ -50,8 +51,7 @@ constexpr u8 CONTROL_MASK_IRQ = 0x10; // constexpr u8 CONTROL_LINK_CABLE = 0x40; // constexpr u8 CONTROL_LINK_ENABLE = 0x80; -constexpr u32 COMMAND_ADDRESS_MASK = 0x1f; -constexpr u32 AV_ADDRESS_MASK = 0xff8; +constexpr u32 AV_ADDRESS_MASK = 0xfe0; class CGBPlayer_Dummy final : public HSP::IGBPlayer { @@ -232,13 +232,13 @@ void CGBPlayer_mGBA::ReadScanlines(std::span scanlines) { const u32 color = M_RGB8_TO_RGB5(video_buffer[(m_current_scanline_index * GBA_VIDEO_HORIZONTAL_PIXELS) + i]); - u32 c = color & 0xFF; - c |= (color & 0xFF00u) << 8; + u32 c = color >> 8u; + c |= (color & 0xffu) << 16u; scanlines[i] = c | (c << 8); // Parity } if (m_current_scanline_index == 0) - scanlines[0] |= 0x80800000; + scanlines[0] |= 0x00008080; m_current_scanline_index += 4; @@ -398,14 +398,13 @@ CHSPDevice_GBPlayer::CHSPDevice_GBPlayer(Core::System& system) : m_system{system #endif } -u64 CHSPDevice_GBPlayer::Read(u32 address) +void CHSPDevice_GBPlayer::Read(u32 address, std::span data) { - u64 value = 0; switch (GBPRegister(address >> 20)) { case GBPRegister::Test: { - std::memcpy(&value, &m_test[address & COMMAND_ADDRESS_MASK], sizeof(value)); + std::ranges::copy(m_test, data.data()); break; } case GBPRegister::Control: @@ -423,14 +422,19 @@ u64 CHSPDevice_GBPlayer::Read(u32 address) m_control &= ~(CONTROL_CART_DETECTED | CONTROL_CART_INSERTED); } - value = m_control * 0x0101010101010101ULL; + std::ranges::fill(data, m_control); break; } case GBPRegister::IRQ: { - value = m_irq * 0x0000000100000001ULL; - value |= (m_irq & 0xFF00) * 0x0001010000010100ULL; - value &= 0xFFFF7FFFFFFF7FFFULL; + u32 value = m_irq; + value |= (m_irq & 0xff00) * 0x0100'0001u; + value &= 0x7fff'ffffu; + + for (std::size_t i = 0; i != data.size(); i += sizeof(value)) + { + std::memcpy(data.data() + i, &value, sizeof(value)); + } break; } case GBPRegister::Video: @@ -441,8 +445,7 @@ u64 CHSPDevice_GBPlayer::Read(u32 address) const u32 scanlines_pos = offset / 4; - value = u64(m_scanlines[scanlines_pos]) << 32; - value |= m_scanlines[scanlines_pos + 1]; + std::memcpy(data.data(), m_scanlines.data() + scanlines_pos, data.size()); break; } case GBPRegister::Audio: @@ -451,10 +454,13 @@ u64 CHSPDevice_GBPlayer::Read(u32 address) if (offset == 0) m_gbp->ReadAudio(m_audio); - const u32 audio_pos = offset / 4; + u32 audio_pos = offset / 4; - value = 0x0101010100000000ULL * m_audio[audio_pos]; - value |= 0x01010101ULL * m_audio[audio_pos + 1]; + for (std::size_t i = 0; i != data.size(); i += sizeof(u32)) + { + std::memset(data.data() + i, m_audio[audio_pos], sizeof(u32)); + ++audio_pos; + } break; } default: @@ -463,27 +469,22 @@ u64 CHSPDevice_GBPlayer::Read(u32 address) break; } } - return value; } -void CHSPDevice_GBPlayer::Write(u32 address, u64 value) +void CHSPDevice_GBPlayer::Write(u32 address, std::span data) { - // This seems to compensate for DSP.cpp turning 32byte writes into 4 x 8byte writes. - // TODO: Rectify that and adjust this. - constexpr u32 last_chunk = 0x18; - switch (GBPRegister(address >> 20)) { case GBPRegister::Test: { - value = ~value; - std::memcpy(&m_test[address & COMMAND_ADDRESS_MASK], &value, sizeof(value)); + u8* dest = m_test.data(); + for (u8 value : data) + *(dest++) = value ^ 0xffu; break; } case GBPRegister::Control: { - if ((address & COMMAND_ADDRESS_MASK) != last_chunk) - break; + const u8 value = data[0x1f]; if (!(m_control & (CONTROL_3V | CONTROL_5V)) && (value & (CONTROL_3V | CONTROL_5V))) { @@ -506,24 +507,20 @@ void CHSPDevice_GBPlayer::Write(u32 address, u64 value) } case GBPRegister::IRQ: { - if ((address & COMMAND_ADDRESS_MASK) != last_chunk) - break; - - m_irq &= ~value; + const u16 value = Common::swap16(data.data() + 0x1e); + m_irq &= u16(~value); UpdateInterrupts(); break; } case GBPRegister::Keypad: { - if ((address & COMMAND_ADDRESS_MASK) != last_chunk) - break; - + const u16 value = Common::swap16(data.data() + 0x1e); m_gbp->SetKeys(value & 0x3FF); break; } default: { - WARN_LOG_FMT(HSP, "GBPlayer: Unknown write to 0x{:08x}: 0x{:016x}", address, value); + WARN_LOG_FMT(HSP, "GBPlayer: Unknown write to 0x{:08x}", address); break; } } diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h index 18f096e640..9d5fe079fd 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceGBPlayer.h @@ -59,8 +59,8 @@ public: HSPDeviceType GetDeviceType() const override { return HSPDeviceType::GBPlayer; } - void Write(u32 address, u64 value) override; - u64 Read(u32 address) override; + void Read(u32 address, std::span data) override; + void Write(u32 address, std::span data) override; void DoState(PointerWrap& p) override; diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp b/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp index e11586f97f..6a52697ed3 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp +++ b/Source/Core/Core/HW/HSP/HSP_DeviceNull.cpp @@ -6,12 +6,11 @@ namespace HSP { -u64 CHSPDevice_Null::Read(u32 address) +void CHSPDevice_Null::Read(u32 address, std::span data) { - return 0; } -void CHSPDevice_Null::Write(u32 address, u64 value) +void CHSPDevice_Null::Write(u32 address, std::span data) { } diff --git a/Source/Core/Core/HW/HSP/HSP_DeviceNull.h b/Source/Core/Core/HW/HSP/HSP_DeviceNull.h index 62b500215b..5fcc552779 100644 --- a/Source/Core/Core/HW/HSP/HSP_DeviceNull.h +++ b/Source/Core/Core/HW/HSP/HSP_DeviceNull.h @@ -13,7 +13,7 @@ class CHSPDevice_Null final : public IHSPDevice public: HSPDeviceType GetDeviceType() const override { return HSPDeviceType::None; } - void Write(u32 address, u64 value) override; - u64 Read(u32 address) override; + void Read(u32 address, std::span data) override; + void Write(u32 address, std::span data) override; }; } // namespace HSP