From 1ecfd6cebcd8bb97722be4dc6fbc48f3ea71fe56 Mon Sep 17 00:00:00 2001 From: Henrik Rydgard Date: Fri, 20 Feb 2015 00:17:47 +0100 Subject: [PATCH] More replacement function accuracy improvements. Makes J&D happy, "fixing" #7502. --- Core/HLE/ReplaceTables.cpp | 65 +++++++++++++++++++++++++-------- Core/HLE/sceKernelEventFlag.cpp | 2 +- Core/MIPS/MIPSAnalyst.cpp | 2 +- 3 files changed, 51 insertions(+), 18 deletions(-) diff --git a/Core/HLE/ReplaceTables.cpp b/Core/HLE/ReplaceTables.cpp index c1dcdc590b..0e7423eeff 100644 --- a/Core/HLE/ReplaceTables.cpp +++ b/Core/HLE/ReplaceTables.cpp @@ -20,6 +20,7 @@ #include "base/basictypes.h" #include "base/logging.h" +#include "Common/Log.h" #include "Core/Config.h" #include "Core/Debugger/Breakpoints.h" #include "Core/MemMap.h" @@ -149,11 +150,13 @@ static int Replace_memcpy_jak() { u32 srcPtr = PARAM(1); u32 bytes = PARAM(2); bool skip = false; - if (!bytes) { + if (bytes == 0) { RETURN(destPtr); - return 10; + currentMIPS->r[MIPS_REG_T0] = bytes; + currentMIPS->r[MIPS_REG_A0] = bytes - 1; + currentMIPS->r[MIPS_REG_A2] = bytes - 1; + return 5; } - currentMIPS->InvalidateICache(srcPtr, bytes); if (Memory::IsVRAMAddress(destPtr) || Memory::IsVRAMAddress(srcPtr)) { skip = gpu->PerformMemoryCopy(destPtr, srcPtr, bytes); @@ -163,30 +166,24 @@ static int Replace_memcpy_jak() { const u8 *src = Memory::GetPointer(srcPtr); if (!dst || !src) { - // Already logged. - } else if (std::min(destPtr, srcPtr) + bytes > std::max(destPtr, srcPtr)) { + } else { // Jak style overlap. - for (int i = 0; i < (int)bytes; i++) { + for (int i = 0; i < bytes; i++) { dst[i] = src[i]; } - } else { - memmove(dst, src, bytes); } } - RETURN(destPtr); // Jak relies on more registers coming out right than the ABI specifies. // See the disassembly of the function for the explanations for these... currentMIPS->r[MIPS_REG_T0] = 0; currentMIPS->r[MIPS_REG_A0] = -1; - currentMIPS->r[MIPS_REG_A2] = 0; + currentMIPS->r[MIPS_REG_A1] = srcPtr + bytes; + currentMIPS->r[MIPS_REG_A2] = -1; currentMIPS->r[MIPS_REG_A3] = destPtr + bytes; + RETURN(destPtr); -#ifndef MOBILE_DEVICE - CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc); - CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); -#endif - return 10 + bytes / 4; // approximation + return 5 + bytes * 8 + 2; // approximation. This is a slow memcpy - a byte copy loop.. } static int Replace_memcpy16() { @@ -298,6 +295,42 @@ static int Replace_memset() { return 10 + bytes / 4; // approximation } +static int Replace_memset_jak() { + u32 destPtr = PARAM(0); + u8 value = PARAM(1); + u32 bytes = PARAM(2); + + if (bytes == 0) { + currentMIPS->r[MIPS_REG_A2] = bytes - 1; + currentMIPS->r[MIPS_REG_A3] = bytes - 1; + currentMIPS->r[MIPS_REG_T0] = destPtr; + currentMIPS->r[MIPS_REG_T1] = 0; + RETURN(destPtr); + return 5; + } + + bool skip = false; + if (Memory::IsVRAMAddress(destPtr)) { + skip = gpu->PerformMemorySet(destPtr, value, bytes); + } + if (!skip && bytes != 0) { + u8 *dst = Memory::GetPointer(destPtr); + if (dst) { + memset(dst, value, bytes); + } + } + + currentMIPS->r[MIPS_REG_T0] = destPtr + bytes; + currentMIPS->r[MIPS_REG_A2] = -1; + currentMIPS->r[MIPS_REG_A3] = -1; + RETURN(destPtr); + +#ifndef MOBILE_DEVICE + CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc); +#endif + return 5 + bytes * 10 + 2; // approximation (hm, inspecting the disasm this should be 5 + 6 * bytes + 2, but this is what works..) +} + static int Replace_strlen() { u32 srcPtr = PARAM(0); const char *src = (const char *)Memory::GetPointer(srcPtr); @@ -1010,7 +1043,7 @@ static const ReplacementTableEntry entries[] = { { "memcpy_swizzled", &Replace_memcpy_swizzled, 0, 0 }, { "memmove", &Replace_memmove, 0, 0 }, { "memset", &Replace_memset, 0, 0 }, - + { "memset_jak", &Replace_memset_jak, 0, 0 }, { "strlen", &Replace_strlen, 0, REPFLAG_DISABLED }, { "strcpy", &Replace_strcpy, 0, REPFLAG_DISABLED }, { "strncpy", &Replace_strncpy, 0, REPFLAG_DISABLED }, diff --git a/Core/HLE/sceKernelEventFlag.cpp b/Core/HLE/sceKernelEventFlag.cpp index 24cc835fda..d4a985293c 100644 --- a/Core/HLE/sceKernelEventFlag.cpp +++ b/Core/HLE/sceKernelEventFlag.cpp @@ -633,7 +633,7 @@ u32 sceKernelReferEventFlagStatus(SceUID id, u32 statusPtr) } else { - ERROR_LOG(SCEKERNEL, "sceKernelReferEventFlagStatus(%i, %08x): invalid event flag", id, statusPtr); + ERROR_LOG(SCEKERNEL, "%08x=sceKernelReferEventFlagStatus(%i, %08x): invalid event flag", error, id, statusPtr); return error; } } diff --git a/Core/MIPS/MIPSAnalyst.cpp b/Core/MIPS/MIPSAnalyst.cpp index 78cf096d7f..ea7a6d3da8 100644 --- a/Core/MIPS/MIPSAnalyst.cpp +++ b/Core/MIPS/MIPSAnalyst.cpp @@ -439,7 +439,7 @@ static const HardHashTableEntry hardcodedHashes[] = { { 0xe83a7a9d80a21c11, 4448, "_strtod_r", }, { 0xe894bda909a8a8f9, 1064, "expensive_wipeout_pulse", }, { 0xe8ad7719be44e7c8, 276, "strchr", }, - { 0xeabb9c1b4f83d2b4, 52, "memset", }, // Crisis Core (US) + { 0xeabb9c1b4f83d2b4, 52, "memset_jak", }, // Crisis Core (US), Jak and Daxter (this is a slow memset and needs to have slow timing) { 0xeb0f7bf63d52ece9, 88, "strncat", }, { 0xeb8c0834d8bbc28c, 416, "fmodf", }, { 0xed8918f378e9a563, 628, "sd_gundam_g_generation_download_frame", }, // SD Gundam G Generation Overworld