From 74908f6b38cd3f1dd12c93bd76f6b5109a022c11 Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 29 Sep 2013 16:51:49 -0700 Subject: [PATCH 1/2] Add errors and rescheduling to sceDmac*. The functionality seems pretty straight-forward. --- Core/HLE/sceDmac.cpp | 40 ++++++++++++++++++++++++++++++++++++---- GPU/GPUCommon.cpp | 2 +- 2 files changed, 37 insertions(+), 5 deletions(-) diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 9222ff356f..882a086fdd 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -23,9 +23,13 @@ #include "GPU/GPUState.h" u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) { + if (size == 0) { + ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size); + return SCE_KERNEL_ERROR_INVALID_SIZE; + } if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) { ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size); - return 0; + return SCE_KERNEL_ERROR_INVALID_POINTER; } DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); @@ -37,12 +41,40 @@ u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) { if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) { gpu->UpdateMemory(dst, src, size); } + + // This number seems strangely reproducible. + if (size >= 272) { + // Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us. + return hleDelayResult(0, "dmac copy", size / 236); + } return 0; } -u32 sceDmacTryMemcpy(u32 x, u32 y , u32 z) -{ - ERROR_LOG_REPORT(HLE,"UNIMPL sceDmacTryMemcpy(%08x, %08x, %i)", x ,y ,z); +u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) { + if (size == 0) { + ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size); + return SCE_KERNEL_ERROR_INVALID_SIZE; + } + if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) { + ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size); + return SCE_KERNEL_ERROR_INVALID_POINTER; + } + + DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); + + Memory::Memcpy(dst, Memory::GetPointer(src), size); + + src &= ~0x40000000; + dst &= ~0x40000000; + if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) { + gpu->UpdateMemory(dst, src, size); + } + + // This number seems strangely reproducible. + if (size >= 272) { + // Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us. + return hleDelayResult(0, "dmac copy", size / 236); + } return 0; } diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index dc5d06fa86..9816bf4f66 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -203,7 +203,7 @@ u32 GPUCommon::EnqueueList(u32 listpc, u32 stall, int subIntrBase, PSPPointer Date: Sun, 29 Sep 2013 16:56:11 -0700 Subject: [PATCH 2/2] Mostly implement sceDmacTryMemcpy(). --- Core/HLE/sceDmac.cpp | 69 +++++++++++++++++++++++++++++--------------- Core/HLE/sceDmac.h | 5 ++++ 2 files changed, 50 insertions(+), 24 deletions(-) diff --git a/Core/HLE/sceDmac.cpp b/Core/HLE/sceDmac.cpp index 882a086fdd..1706bdf609 100644 --- a/Core/HLE/sceDmac.cpp +++ b/Core/HLE/sceDmac.cpp @@ -16,24 +16,30 @@ // https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/. #include "Globals.h" +#include "Core/CoreTiming.h" #include "Core/MemMap.h" #include "Core/Reporting.h" #include "Core/HLE/HLE.h" #include "GPU/GPUInterface.h" #include "GPU/GPUState.h" -u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) { - if (size == 0) { - ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size); - return SCE_KERNEL_ERROR_INVALID_SIZE; - } - if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) { - ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size); - return SCE_KERNEL_ERROR_INVALID_POINTER; +u64 dmacMemcpyDeadline; + +void __DmacInit() { + dmacMemcpyDeadline = 0; +} + +void __DmacDoState(PointerWrap &p) { + auto s = p.Section("sceDmac", 0, 1); + if (s == 0) { + dmacMemcpyDeadline = 0; + return; } - DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); + p.Do(dmacMemcpyDeadline); +} +int __DmacMemcpy(u32 dst, u32 src, u32 size) { Memory::Memcpy(dst, Memory::GetPointer(src), size); src &= ~0x40000000; @@ -45,11 +51,34 @@ u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) { // This number seems strangely reproducible. if (size >= 272) { // Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us. - return hleDelayResult(0, "dmac copy", size / 236); + int delayUs = size / 236; + dmacMemcpyDeadline = CoreTiming::GetTicks() + usToCycles(delayUs); + return hleDelayResult(0, "dmac copy", delayUs); } return 0; } +u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) { + if (size == 0) { + ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size); + return SCE_KERNEL_ERROR_INVALID_SIZE; + } + if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) { + ERROR_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size); + return SCE_KERNEL_ERROR_INVALID_POINTER; + } + + if (dmacMemcpyDeadline > CoreTiming::GetTicks()) { + WARN_LOG_REPORT(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): overlapping read", dst, src, size); + // TODO: Should block, seems like copy doesn't start until previous finishes. + // Might matter for overlapping copies. + } else { + DEBUG_LOG(HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); + } + + return __DmacMemcpy(dst, src, size); +} + u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) { if (size == 0) { ERROR_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size); @@ -60,22 +89,14 @@ u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) { return SCE_KERNEL_ERROR_INVALID_POINTER; } - DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); - - Memory::Memcpy(dst, Memory::GetPointer(src), size); - - src &= ~0x40000000; - dst &= ~0x40000000; - if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) { - gpu->UpdateMemory(dst, src, size); + if (dmacMemcpyDeadline > CoreTiming::GetTicks()) { + DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): busy", dst, src, size); + return SCE_KERNEL_ERROR_BUSY; + } else { + DEBUG_LOG(HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size); } - // This number seems strangely reproducible. - if (size >= 272) { - // Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us. - return hleDelayResult(0, "dmac copy", size / 236); - } - return 0; + return __DmacMemcpy(dst, src, size); } const HLEFunction sceDmac[] = { diff --git a/Core/HLE/sceDmac.h b/Core/HLE/sceDmac.h index 0f40d75120..c2f9f498fd 100644 --- a/Core/HLE/sceDmac.h +++ b/Core/HLE/sceDmac.h @@ -17,4 +17,9 @@ #pragma once +class PointerWrap; + +void __DmacInit(); +void __DmacDoState(PointerWrap &p); + void Register_sceDmac();