CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
CoCalc provides the best real-time collaborative environment for Jupyter Notebooks, LaTeX documents, and SageMath, scalable from individual users to large groups and classes!
Path: blob/master/Core/HLE/sceDmac.cpp
Views: 1401
// Copyright (c) 2012- PPSSPP Project.12// This program is free software: you can redistribute it and/or modify3// it under the terms of the GNU General Public License as published by4// the Free Software Foundation, version 2.0 or later versions.56// This program is distributed in the hope that it will be useful,7// but WITHOUT ANY WARRANTY; without even the implied warranty of8// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the9// GNU General Public License 2.0 for more details.1011// A copy of the GPL 2.0 should have been included with the program.12// If not, see http://www.gnu.org/licenses/1314// Official git repository and contact information can be found at15// https://github.com/hrydgard/ppsspp and http://www.ppsspp.org/.1617#include "Common/Serialize/Serializer.h"18#include "Common/Serialize/SerializeFuncs.h"19#include "Core/CoreTiming.h"20#include "Core/MemMapHelpers.h"21#include "Core/Reporting.h"22#include "Core/HLE/HLE.h"23#include "Core/HLE/sceDmac.h"24#include "Core/HLE/sceKernel.h"25#include "Core/HLE/FunctionWrappers.h"26#include "Core/Debugger/Breakpoints.h"27#include "GPU/GPUInterface.h"28#include "GPU/GPUState.h"2930u64 dmacMemcpyDeadline;3132void __DmacInit() {33dmacMemcpyDeadline = 0;34}3536void __DmacDoState(PointerWrap &p) {37auto s = p.Section("sceDmac", 0, 1);38if (s == 0) {39dmacMemcpyDeadline = 0;40return;41}4243Do(p, dmacMemcpyDeadline);44}4546static int __DmacMemcpy(u32 dst, u32 src, u32 size) {47bool skip = false;48if (Memory::IsVRAMAddress(src) || Memory::IsVRAMAddress(dst)) {49skip = gpu->PerformMemoryCopy(dst, src, size);50}51if (!skip && size != 0) {52currentMIPS->InvalidateICache(src, size);53if (Memory::IsValidRange(dst, size) && Memory::IsValidRange(src, size)) {54memcpy(Memory::GetPointerWriteUnchecked(dst), Memory::GetPointerUnchecked(src), size);55}56if (MemBlockInfoDetailed(size)) {57NotifyMemInfoCopy(dst, src, size, "DmacMemcpy/");58}59currentMIPS->InvalidateICache(dst, size);60}6162// This number seems strangely reproducible.63if (size >= 272) {64// Approx. 225 MiB/s or 235929600 B/s, so let's go with 236 B/us.65int delayUs = size / 236;66dmacMemcpyDeadline = CoreTiming::GetTicks() + usToCycles(delayUs);67return hleDelayResult(0, "dmac copy", delayUs);68}69return 0;70}7172static u32 sceDmacMemcpy(u32 dst, u32 src, u32 size) {73if (size == 0) {74// Some games seem to do this frequently.75DEBUG_LOG(Log::HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size);76return SCE_KERNEL_ERROR_INVALID_SIZE;77}78if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) {79ERROR_LOG(Log::HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);80return SCE_KERNEL_ERROR_INVALID_POINTER;81}82if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {83ERROR_LOG(Log::HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);84return SCE_KERNEL_ERROR_PRIV_REQUIRED;85}8687if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {88WARN_LOG_REPORT_ONCE(overlapDmacMemcpy, Log::HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%d): overlapping read", dst, src, size);89// TODO: Should block, seems like copy doesn't start until previous finishes.90// Might matter for overlapping copies.91} else {92DEBUG_LOG(Log::HLE, "sceDmacMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);93}9495return __DmacMemcpy(dst, src, size);96}9798static u32 sceDmacTryMemcpy(u32 dst, u32 src, u32 size) {99if (size == 0) {100ERROR_LOG(Log::HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid size", dst, src, size);101return SCE_KERNEL_ERROR_INVALID_SIZE;102}103if (!Memory::IsValidAddress(dst) || !Memory::IsValidAddress(src)) {104ERROR_LOG(Log::HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): invalid address", dst, src, size);105return SCE_KERNEL_ERROR_INVALID_POINTER;106}107if (dst + size >= 0x80000000 || src + size >= 0x80000000 || size >= 0x80000000) {108ERROR_LOG(Log::HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): illegal size", dst, src, size);109return SCE_KERNEL_ERROR_PRIV_REQUIRED;110}111112if (dmacMemcpyDeadline > CoreTiming::GetTicks()) {113DEBUG_LOG(Log::HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i): busy", dst, src, size);114return SCE_KERNEL_ERROR_BUSY;115} else {116DEBUG_LOG(Log::HLE, "sceDmacTryMemcpy(dest=%08x, src=%08x, size=%i)", dst, src, size);117}118119return __DmacMemcpy(dst, src, size);120}121122const HLEFunction sceDmac[] = {123{0X617F3FE6, &WrapU_UUU<sceDmacMemcpy>, "sceDmacMemcpy", 'x', "xxx"},124{0XD97F94D8, &WrapU_UUU<sceDmacTryMemcpy>, "sceDmacTryMemcpy", 'x', "xxx"},125};126127void Register_sceDmac() {128RegisterModule("sceDmac", ARRAY_SIZE(sceDmac), sceDmac);129}130131132