Jak and Daxter relies on implementation details of memcpy (scary!), fix our replacement. Fixes #7502

This commit is contained in:
Henrik Rydgard 2015-02-19 11:14:23 +01:00
parent e89c881e4a
commit 23492d8d90
4 changed files with 52 additions and 3 deletions

View File

@ -144,6 +144,51 @@ static int Replace_memcpy() {
return 10 + bytes / 4; // approximation
}
static int Replace_memcpy_jak() {
u32 destPtr = PARAM(0);
u32 srcPtr = PARAM(1);
u32 bytes = PARAM(2);
bool skip = false;
if (!bytes) {
RETURN(destPtr);
return 10;
}
currentMIPS->InvalidateICache(srcPtr, bytes);
if (Memory::IsVRAMAddress(destPtr) || Memory::IsVRAMAddress(srcPtr)) {
skip = gpu->PerformMemoryCopy(destPtr, srcPtr, bytes);
}
if (!skip && bytes != 0) {
u8 *dst = Memory::GetPointer(destPtr);
const u8 *src = Memory::GetPointer(srcPtr);
if (!dst || !src) {
// Already logged.
} else if (std::min(destPtr, srcPtr) + bytes > std::max(destPtr, srcPtr)) {
// Jak style overlap.
for (int i = 0; i < (int)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_A3] = destPtr + bytes;
#ifndef MOBILE_DEVICE
CBreakPoints::ExecMemCheck(srcPtr, false, bytes, currentMIPS->pc);
CBreakPoints::ExecMemCheck(destPtr, true, bytes, currentMIPS->pc);
#endif
return 10 + bytes / 4; // approximation
}
static int Replace_memcpy16() {
u32 destPtr = PARAM(0);
u32 srcPtr = PARAM(1);
@ -953,17 +998,19 @@ static const ReplacementTableEntry entries[] = {
{ "sinf", &Replace_sinf, 0, REPFLAG_DISABLED },
{ "cosf", &Replace_cosf, 0, REPFLAG_DISABLED },
{ "tanf", &Replace_tanf, 0, REPFLAG_DISABLED },
{ "atanf", &Replace_atanf, 0, REPFLAG_DISABLED },
{ "sqrtf", &Replace_sqrtf, 0, REPFLAG_DISABLED },
{ "atan2f", &Replace_atan2f, 0, REPFLAG_DISABLED },
{ "floorf", &Replace_floorf, 0, REPFLAG_DISABLED },
{ "ceilf", &Replace_ceilf, 0, REPFLAG_DISABLED },
{ "memcpy", &Replace_memcpy, 0, 0 },
{ "memcpy_jak", &Replace_memcpy_jak, 0, 0 },
{ "memcpy16", &Replace_memcpy16, 0, 0 },
{ "memcpy_swizzled", &Replace_memcpy_swizzled, 0, 0 },
{ "memmove", &Replace_memmove, 0, 0 },
{ "memset", &Replace_memset, 0, 0 },
{ "strlen", &Replace_strlen, 0, REPFLAG_DISABLED },
{ "strcpy", &Replace_strcpy, 0, REPFLAG_DISABLED },
{ "strncpy", &Replace_strncpy, 0, REPFLAG_DISABLED },

View File

@ -59,6 +59,8 @@ enum MIPSGPReg {
MIPS_REG_A4=8,
MIPS_REG_A5=9,
MIPS_REG_T0=8, //alternate names for A4/A5
MIPS_REG_T1=9,
MIPS_REG_T2=10,
MIPS_REG_T3=11,
MIPS_REG_T4=12,

View File

@ -105,7 +105,7 @@ static const HardHashTableEntry hardcodedHashes[] = {
//{ 0x0eb5f2e95f59276a, 40, "dl_write_lightmode", },
{ 0x0f1e7533a546f6a1, 228, "dl_write_bone_matrix_4", },
{ 0x0f2a1106ad84fb74, 52, "strcmp", },
{ 0x0ffa5db8396d4274, 64, "memcpy", }, // CRUSH
{ 0x0ffa5db8396d4274, 64, "memcpy_jak", }, // CRUSH
{ 0x1252e902d0b49bfb, 44, "vector_sub_q_2", },
{ 0x12df3d33a58d0298, 52, "vmidt_t", },
{ 0x12feef7b017d3431, 700, "memmove", },

View File

@ -19,7 +19,7 @@
0eb5f2e95f59276a:40 = dl_write_lightmode
0f1e7533a546f6a1:228 = dl_write_bone_matrix_4
0f2a1106ad84fb74:52 = strcmp
0ffa5db8396d4274:64 = memcpy
0ffa5db8396d4274:64 = memcpy_jak
1252e902d0b49bfb:44 = vector_sub_q_2
12df3d33a58d0298:52 = vmidt_t
12feef7b017d3431:700 = memmove