From 7f5be6b35d8fd3d7d0fea95a1fa443edfb649d1a Mon Sep 17 00:00:00 2001 From: "Unknown W. Brackets" Date: Sun, 4 May 2014 17:58:44 -0700 Subject: [PATCH] CALLs and JUMPs to misaligned addresses round down. Fixes Pac-Man World 3. Matches tests on hardware. --- GPU/GPUCommon.cpp | 18 ++++++++---------- 1 file changed, 8 insertions(+), 10 deletions(-) diff --git a/GPU/GPUCommon.cpp b/GPU/GPUCommon.cpp index be0ceac43c..25313b46d6 100644 --- a/GPU/GPUCommon.cpp +++ b/GPU/GPUCommon.cpp @@ -698,13 +698,12 @@ void GPUCommon::Execute_Origin(u32 op, u32 diff) { void GPUCommon::Execute_Jump(u32 op, u32 diff) { easy_guard guard(listLock); - const u32 data = op & 0x00FFFFFF; - const u32 target = gstate_c.getRelativeAddress(data); + const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); if (Memory::IsValidAddress(target)) { UpdatePC(currentList->pc, target - 4); currentList->pc = target - 4; // pc will be increased after we return, counteract that } else { - ERROR_LOG_REPORT(G3D, "JUMP to illegal address %08x - ignoring! data=%06x", target, data); + ERROR_LOG_REPORT(G3D, "JUMP to illegal address %08x - ignoring! data=%06x", target, op & 0x00FFFFFF); } } @@ -712,13 +711,12 @@ void GPUCommon::Execute_BJump(u32 op, u32 diff) { if (!currentList->bboxResult) { // bounding box jump. easy_guard guard(listLock); - const u32 data = op & 0x00FFFFFF; - const u32 target = gstate_c.getRelativeAddress(data); + const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); if (Memory::IsValidAddress(target)) { UpdatePC(currentList->pc, target - 4); currentList->pc = target - 4; // pc will be increased after we return, counteract that } else { - ERROR_LOG_REPORT(G3D, "BJUMP to illegal address %08x - ignoring! data=%06x", target, data); + ERROR_LOG_REPORT(G3D, "BJUMP to illegal address %08x - ignoring! data=%06x", target, op & 0x00FFFFFF); } } } @@ -728,8 +726,7 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) { // Saint Seiya needs correct support for relative calls. const u32 retval = currentList->pc + 4; - const u32 data = op & 0x00FFFFFF; - const u32 target = gstate_c.getRelativeAddress(data); + const u32 target = gstate_c.getRelativeAddress(op & 0x00FFFFFC); // Bone matrix optimization - many games will CALL a bone matrix (!). if ((Memory::ReadUnchecked_U32(target) >> 24) == GE_CMD_BONEMATRIXDATA) { @@ -745,7 +742,7 @@ void GPUCommon::Execute_Call(u32 op, u32 diff) { if (currentList->stackptr == ARRAY_SIZE(currentList->stack)) { ERROR_LOG_REPORT(G3D, "CALL: Stack full!"); } else if (!Memory::IsValidAddress(target)) { - ERROR_LOG_REPORT(G3D, "CALL to illegal address %08x - ignoring! data=%06x", target, data); + ERROR_LOG_REPORT(G3D, "CALL to illegal address %08x - ignoring! data=%06x", target, op & 0x00FFFFFF); } else { auto &stackEntry = currentList->stack[currentList->stackptr++]; stackEntry.pc = retval; @@ -763,7 +760,8 @@ void GPUCommon::Execute_Ret(u32 op, u32 diff) { } else { auto &stackEntry = currentList->stack[--currentList->stackptr]; gstate_c.offsetAddr = stackEntry.offsetAddr; - u32 target = (currentList->pc & 0xF0000000) | (stackEntry.pc & 0x0FFFFFFF); + // We always clear the top (uncached/etc.) bits + const u32 target = stackEntry.pc & 0x0FFFFFFF; UpdatePC(currentList->pc, target - 4); currentList->pc = target - 4; if (!Memory::IsValidAddress(currentList->pc)) {