From 78551827c93d827eb0a6212faad1232147c403a8 Mon Sep 17 00:00:00 2001 From: SimoneN64 Date: Tue, 18 Jun 2024 23:20:36 +0200 Subject: [PATCH] Slightly better PI DMA behaviour --- src/backend/core/mmio/PI.cpp | 64 +++++++++++++++++++----------------- src/backend/core/mmio/PI.hpp | 2 +- 2 files changed, 35 insertions(+), 31 deletions(-) diff --git a/src/backend/core/mmio/PI.cpp b/src/backend/core/mmio/PI.cpp index 083f1669..354a5ed5 100644 --- a/src/backend/core/mmio/PI.cpp +++ b/src/backend/core/mmio/PI.cpp @@ -14,8 +14,6 @@ void PI::Reset() { latch = 0; dramAddr = 0; cartAddr = 0; - dramAddrInternal = 0; - cartAddrInternal = 0; rdLen = 0; wrLen = 0; piBsdDom1Lat = 0; @@ -271,7 +269,7 @@ template <> void PI::BusWrite(u32 addr, u32 val) { if (val < CART_ISVIEWER_SIZE) { std::string message(val + 1, 0); std::copy(mem.isviewer.begin(), mem.isviewer.begin() + val, message.begin()); - Util::always("{}", message); + Util::print("{}", message); } else { Util::panic("ISViewer buffer size is emulated at {} bytes, but received a flush command for {} bytes!", CART_ISVIEWER_SIZE, val); } @@ -353,10 +351,10 @@ template <> void PI::BusWrite(u32 addr, u64 val) { auto PI::Read(u32 addr) const -> u32 { switch(addr) { - case 0x04600000: return dramAddr; - case 0x04600004: return cartAddr; - case 0x04600008: return rdLen; - case 0x0460000C: return wrLen; + case 0x04600000: return dramAddr & 0x00FFFFFE; + case 0x04600004: return cartAddr & 0xFFFFFFFE; + case 0x04600008: return 0x7F; + case 0x0460000C: return 0x7F; case 0x04600010: { u32 value = 0; value |= (dmaBusy << 0); // Is PI DMA active? No, because it's instant @@ -428,50 +426,56 @@ u32 PI::AccessTiming(u8 domain, u32 length) const { void PI::Write(u32 addr, u32 val) { MI& mi = mem.mmio.mi; switch(addr) { - case 0x04600000: dramAddr = val & 0xFFFFFF; break; - case 0x04600004: cartAddr = val; break; + case 0x04600000: dramAddr = val & 0x00FFFFFE; break; + case 0x04600004: cartAddr = val & 0xFFFFFFFE; break; case 0x04600008: { - u32 len = (val & 0x00FFFFFF) + 1; - cartAddrInternal = cartAddr & 0xFFFFFFFE; - dramAddrInternal = dramAddr & 0x007FFFFE; - if (dramAddrInternal & 0x7) { - len -= dramAddrInternal & 0x7; - } - rdLen = len; + rdLen = val & 0x00FFFFFF; + s32 len = val + 1; + + s32 misalign = dramAddr & 7; + s32 distEndOfRow = 0x800-(dramAddr&0x7ff); + s32 blockLen = std::min(128-misalign, distEndOfRow); + s32 curLen = std::min(len, blockLen); for (int i = 0; i < len; i++) { - u32 addr = BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE; + u32 addr = BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE; if (addr < RDRAM_SIZE) { - BusWrite(cartAddrInternal + i, mem.mmio.rdp.rdram[addr]); + BusWrite(cartAddr + i, mem.mmio.rdp.rdram[addr]); } else { - BusWrite(cartAddrInternal + i, 0); + BusWrite(cartAddr + i, 0); } } + dramAddr += len; + dramAddr = (dramAddr + 7) & ~7; + for(s32 i = 0; i < curLen; i+=2) cartAddr += 2; Util::trace("PI DMA from RDRAM to CARTRIDGE (size: {} B, {:08X} to {:08X})", len, dramAddr, cartAddr); dmaBusy = true; toCart = true; scheduler.EnqueueRelative(AccessTiming(GetDomain(cartAddr), len), PI_DMA_COMPLETE); } break; case 0x0460000C: { - u32 len = (val & 0x00FFFFFF) + 1; - cartAddrInternal = cartAddr & 0xFFFFFFFE; - dramAddrInternal = dramAddr & 0x007FFFFE; - if (dramAddrInternal & 0x7) { - len -= (dramAddrInternal & 0x7); - } - wrLen = len; + wrLen = val & 0x00FFFFFF; + s32 len = wrLen + 1; - if(mem.saveType == SAVE_FLASH_1m && cartAddrInternal >= SREGION_PI_SRAM && cartAddrInternal < 0x08010000) { - cartAddrInternal = SREGION_PI_SRAM | ((cartAddrInternal & 0xFFFFF) << 1); + s32 misalign = dramAddr & 7; + s32 distEndOfRow = 0x800-(dramAddr&0x7ff); + s32 blockLen = std::min(128-misalign, distEndOfRow); + s32 curLen = std::min(len, blockLen); + + if(mem.saveType == SAVE_FLASH_1m && cartAddr >= SREGION_PI_SRAM && cartAddr < 0x08010000) { + cartAddr = SREGION_PI_SRAM | ((cartAddr & 0xFFFFF) << 1); } for(u32 i = 0; i < len; i++) { - u32 addr = BYTE_ADDRESS(dramAddrInternal + i) & RDRAM_DSIZE; + u32 addr = BYTE_ADDRESS(dramAddr + i) & RDRAM_DSIZE; if (addr < RDRAM_SIZE) { - mem.mmio.rdp.rdram[addr] = BusRead(cartAddrInternal + i); + mem.mmio.rdp.rdram[addr] = BusRead(cartAddr + i); } } + dramAddr += len; + dramAddr = (dramAddr + 7) & ~7; + for(s32 i = 0; i < curLen; i+=2) cartAddr += 2; dmaBusy = true; Util::trace("PI DMA from CARTRIDGE to RDRAM (size: {} B, {:08X} to {:08X})", len, cartAddr, dramAddr); toCart = false; diff --git a/src/backend/core/mmio/PI.hpp b/src/backend/core/mmio/PI.hpp index d1132cb0..04f4f4ce 100644 --- a/src/backend/core/mmio/PI.hpp +++ b/src/backend/core/mmio/PI.hpp @@ -28,7 +28,7 @@ struct PI { [[nodiscard]] u32 AccessTiming(u8 domain, u32 length) const; bool dmaBusy{}, ioBusy{}, toCart{}; u32 latch{}; - u32 dramAddr{}, cartAddr{}, dramAddrInternal{}, cartAddrInternal{}; + u32 dramAddr{}, cartAddr{}; u32 rdLen{}, wrLen{}; u32 piBsdDom1Lat{}, piBsdDom2Lat{}; u32 piBsdDom1Pwd{}, piBsdDom2Pwd{};