mirror of
https://github.com/libretro/ppsspp.git
synced 2024-11-24 00:29:57 +00:00
Support swizzled framebuffer downloads.
Used in God Eater 2 when showing the load save screen.
This commit is contained in:
parent
64f6012dba
commit
b73c575418
@ -142,6 +142,42 @@ static int Replace_memcpy16() {
|
||||
return 10 + bytes / 4; // approximation
|
||||
}
|
||||
|
||||
static int Replace_memcpy_swizzled() {
|
||||
u32 destPtr = PARAM(0);
|
||||
u32 srcPtr = PARAM(1);
|
||||
u32 pitch = PARAM(2);
|
||||
u32 h = PARAM(4);
|
||||
if (Memory::IsVRAMAddress(srcPtr)) {
|
||||
// Cheat a bit to force a download of the framebuffer.
|
||||
// VRAM + 0x00400000 is simply a VRAM mirror.
|
||||
gpu->UpdateMemory(srcPtr ^ 0x00400000, srcPtr, pitch * h);
|
||||
}
|
||||
u8 *dstp = Memory::GetPointerUnchecked(destPtr);
|
||||
const u8 *srcp = Memory::GetPointerUnchecked(srcPtr);
|
||||
|
||||
const u8 *ysrcp = srcp;
|
||||
for (u32 y = 0; y < h; y += 8) {
|
||||
const u8 *xsrcp = ysrcp;
|
||||
for (u32 x = 0; x < pitch; x += 16) {
|
||||
const u8 *src = xsrcp;
|
||||
for (int n = 0; n < 8; ++n) {
|
||||
memcpy(dstp, src, 16);
|
||||
src += pitch;
|
||||
dstp += 16;
|
||||
}
|
||||
xsrcp += 16;
|
||||
}
|
||||
ysrcp += 8 * pitch;
|
||||
}
|
||||
|
||||
RETURN(0);
|
||||
#ifndef MOBILE_DEVICE
|
||||
CBreakPoints::ExecMemCheck(srcPtr, false, pitch * h, currentMIPS->pc);
|
||||
CBreakPoints::ExecMemCheck(destPtr, true, pitch * h, currentMIPS->pc);
|
||||
#endif
|
||||
return 10 + (pitch * h) / 4; // approximation
|
||||
}
|
||||
|
||||
static int Replace_memmove() {
|
||||
u32 destPtr = PARAM(0);
|
||||
u32 srcPtr = PARAM(1);
|
||||
@ -420,6 +456,7 @@ static const ReplacementTableEntry entries[] = {
|
||||
{ "ceilf", &Replace_ceilf, 0, 0},
|
||||
{ "memcpy", &Replace_memcpy, 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, 0},
|
||||
|
@ -220,6 +220,7 @@ static const HardHashTableEntry hardcodedHashes[] = {
|
||||
{ 0x6301fa5149bd973a, 120, "wcscat", },
|
||||
{ 0x658b07240a690dbd, 36, "strlen", },
|
||||
{ 0x66122f0ab50b2ef9, 296, "dl_write_dither_matrix_5", },
|
||||
{ 0x66f7f1beccbc104a, 256, "memcpy_swizzled", }, // God Eater 2
|
||||
{ 0x679e647e34ecf7f1, 132, "roundf", },
|
||||
{ 0x67afe74d9ec72f52, 4380, "_strtod_r", },
|
||||
{ 0x68b22c2aa4b8b915, 400, "sqrt", },
|
||||
@ -738,6 +739,7 @@ skip:
|
||||
bool looking = false;
|
||||
bool end = false;
|
||||
bool isStraightLeaf = true;
|
||||
bool decreasedSp = false;
|
||||
|
||||
u32 addr;
|
||||
u32 addrNextSym = 0;
|
||||
@ -761,6 +763,8 @@ skip:
|
||||
furthestBranch = 0;
|
||||
looking = false;
|
||||
end = false;
|
||||
isStraightLeaf = false;
|
||||
decreasedSp = false;
|
||||
continue;
|
||||
}
|
||||
|
||||
@ -771,6 +775,7 @@ skip:
|
||||
if (target > furthestBranch) {
|
||||
furthestBranch = target;
|
||||
}
|
||||
// j X
|
||||
} else if ((op & 0xFC000000) == 0x08000000) {
|
||||
u32 sureTarget = GetJumpTarget(addr);
|
||||
// Check for a tail call. Might not even have a jr ra.
|
||||
@ -782,6 +787,18 @@ skip:
|
||||
end = true;
|
||||
}
|
||||
} else if (sureTarget != INVALIDTARGET && sureTarget > addr && sureTarget > furthestBranch) {
|
||||
static const u32 MAX_JUMP_FORWARD = 128;
|
||||
// If it's a nearby forward jump, and not a stackless leaf, assume not a tail call.
|
||||
if (sureTarget <= addr + MAX_JUMP_FORWARD && decreasedSp) {
|
||||
// But let's check the delay slot.
|
||||
MIPSOpcode op = Memory::Read_Instruction(addr + 4);
|
||||
// addiu sp, sp, +X
|
||||
if ((op & 0xFFFF8000) != 0x27BD0000) {
|
||||
furthestBranch = sureTarget;
|
||||
continue;
|
||||
}
|
||||
}
|
||||
|
||||
// A jump later. Probably tail, but let's check if it jumps back.
|
||||
u32 knownEnd = furthestBranch == 0 ? addr : furthestBranch;
|
||||
u32 jumpback = ScanAheadForJumpback(sureTarget, currentFunction.start, knownEnd);
|
||||
@ -806,6 +823,14 @@ skip:
|
||||
end = true;
|
||||
}
|
||||
}
|
||||
// addiu sp, sp, -X
|
||||
if ((op & 0xFFFF8000) == 0x27BD8000) {
|
||||
decreasedSp = true;
|
||||
}
|
||||
// addiu sp, sp, +X
|
||||
if ((op & 0xFFFF8000) == 0x27BD0000) {
|
||||
decreasedSp = false;
|
||||
}
|
||||
|
||||
if (looking) {
|
||||
if (addr >= furthestBranch) {
|
||||
@ -838,6 +863,7 @@ skip:
|
||||
looking = false;
|
||||
end = false;
|
||||
isStraightLeaf = true;
|
||||
decreasedSp = false;
|
||||
currentFunction.start = addr+4;
|
||||
}
|
||||
}
|
||||
|
@ -140,6 +140,7 @@
|
||||
6301fa5149bd973a:120 = wcscat
|
||||
658b07240a690dbd:36 = strlen
|
||||
66122f0ab50b2ef9:296 = dl_write_dither_matrix_5
|
||||
66f7f1beccbc104a:256 = memcpy_swizzled
|
||||
679e647e34ecf7f1:132 = roundf
|
||||
67afe74d9ec72f52:4380 = _strtod_r
|
||||
68b22c2aa4b8b915:400 = sqrt
|
||||
|
Loading…
Reference in New Issue
Block a user