SoftGPU: Range check block copies.

Needs testing to verify if we should copy zeroes instead if the src range is
partial, etc, quite a few possible edge cases.

Though on its own, this probably fixes the crash in #16427.

Still don't understand why that one has issues in hardware renderers
though since they do bounds-check the copies.
This commit is contained in:
Henrik Rydgård 2022-11-28 10:39:04 +01:00
parent 612d2181a1
commit 3246baec4b

View File

@ -807,15 +807,38 @@ void SoftGPU::Execute_BlockTransferStart(u32 op, u32 diff) {
u32 srcLineStartAddr = srcBasePtr + (srcY * srcStride + srcX) * bpp;
u32 dstLineStartAddr = dstBasePtr + (dstY * dstStride + dstX) * bpp;
u32 bytesToCopy = width * height * bpp;
if (!Memory::IsValidRange(srcLineStartAddr, bytesToCopy)) {
// What should we do here? Memset zeroes to the dest instead?
return;
}
if (!Memory::IsValidRange(dstLineStartAddr, bytesToCopy)) {
// What should we do here? Just not do the write, or partial write if
// some part is in-range?
return;
}
const u8 *srcp = Memory::GetPointer(srcLineStartAddr);
u8 *dstp = Memory::GetPointerWrite(dstLineStartAddr);
memcpy(dstp, srcp, width * height * bpp);
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, width * height * bpp);
memcpy(dstp, srcp, bytesToCopy);
GPURecord::NotifyMemcpy(dstLineStartAddr, srcLineStartAddr, bytesToCopy);
} else {
for (int y = 0; y < height; y++) {
u32 srcLineStartAddr = srcBasePtr + ((y + srcY) * srcStride + srcX) * bpp;
u32 dstLineStartAddr = dstBasePtr + ((y + dstY) * dstStride + dstX) * bpp;
u32 bytesToCopy = width * bpp;
if (!Memory::IsValidRange(srcLineStartAddr, bytesToCopy)) {
// What should we do here? Due to the y loop, in this case we might have
// performed a partial copy. Probably fine.
break;
}
if (!Memory::IsValidRange(dstLineStartAddr, bytesToCopy)) {
// What should we do here? Due to the y loop, in this case we might have
// performed a partial copy. Probably fine.
break;
}
const u8 *srcp = Memory::GetPointer(srcLineStartAddr);
u8 *dstp = Memory::GetPointerWrite(dstLineStartAddr);
memcpy(dstp, srcp, width * bpp);