[Core/CD] improved GFX processing robustness in case of word-RAM address overflow (fixes potential emulator crash in Flink level 20)

This commit is contained in:
ekeeke 2024-09-01 11:36:32 +02:00
parent f9f16d7a55
commit 3b95fdf328

View File

@ -455,9 +455,11 @@ int gfx_context_load(uint8 *state)
load_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); load_param(&gfx.bufferStart, sizeof(gfx.bufferStart));
load_param(&tmp32, 4); load_param(&tmp32, 4);
tmp32 &= 0x3fff8;
gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32); gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32);
load_param(&tmp32, 4); load_param(&tmp32, 4);
tmp32 &= ~((1 << ((2*gfx.mapShift) + 1)) - 1) & 0x3ffff;
gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32); gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32);
return bufferptr; return bufferptr;
@ -480,6 +482,12 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
uint32 xoffset = (int16) *gfx.tracePtr++; uint32 xoffset = (int16) *gfx.tracePtr++;
uint32 yoffset = (int16) *gfx.tracePtr++; uint32 yoffset = (int16) *gfx.tracePtr++;
/* handle trace vector address overflow */
if (gfx.tracePtr == (uint16 *)(scd.word_ram_2M + 0x40000)
{
gfx.tracePtr = (uint16 *)(scd.word_ram_2M);
}
/* process all dots */ /* process all dots */
while (width--) while (width--)
{ {
@ -557,7 +565,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
} }
/* read out paired pixel data */ /* read out paired pixel data */
pixel_in = READ_BYTE(scd.word_ram_2M, bufferIndex >> 1); pixel_in = READ_BYTE(scd.word_ram_2M, (bufferIndex >> 1) & 0x3ffff);
/* update left or rigth pixel */ /* update left or rigth pixel */
if (bufferIndex & 1) if (bufferIndex & 1)
@ -573,7 +581,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width)
pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out]; pixel_out = gfx.lut_prio[(scd.regs[0x02>>1].w >> 3) & 0x03][pixel_in][pixel_out];
/* write data to image buffer */ /* write data to image buffer */
WRITE_BYTE(scd.word_ram_2M, bufferIndex >> 1, pixel_out); WRITE_BYTE(scd.word_ram_2M, (bufferIndex >> 1) & 0x3ffff, pixel_out);
/* check current pixel position */ /* check current pixel position */
if ((bufferIndex & 7) != 7) if ((bufferIndex & 7) != 7)
@ -657,7 +665,7 @@ void gfx_start(unsigned int base, int cycles)
/* reference: https://github.com/MiSTer-devel/MegaCD_MiSTer/blob/master/docs/mcd%20logs/graphics_operations_and_68k_wordram_access.jpg */ /* reference: https://github.com/MiSTer-devel/MegaCD_MiSTer/blob/master/docs/mcd%20logs/graphics_operations_and_68k_wordram_access.jpg */
/* TODO: figure what happen exactly when pixel offset is different from 0 */ /* TODO: figure what happen exactly when pixel offset is different from 0 */
/* for the moment, one additional read-modify-write access is assumed at the start if pixel offset is not aligned to 4 pixels */ /* for the moment, one additional read-modify-write access is assumed at the start if pixel offset is not aligned to 4 pixels */
gfx.cyclesPerLine = 4 * 3 * (4 + 2 * scd.regs[0x62>>1].w + ((scd.regs[0x62>>1].w + (scd.regs[0x60>>1].byte.l & 0x03) + 3) >> 2)); gfx.cyclesPerLine = 4 * 3 * (4 + 2 * (scd.regs[0x62>>1].w & 0x1ff) + (((scd.regs[0x62>>1].w & 0x1ff) + (scd.regs[0x60>>1].byte.l & 0x03) + 3) >> 2));
/* start graphics operation */ /* start graphics operation */
scd.regs[0x58>>1].byte.h = 0x80; scd.regs[0x58>>1].byte.h = 0x80;
@ -731,7 +739,7 @@ void gfx_update(int cycles)
while (lines--) while (lines--)
{ {
/* process dots to image buffer */ /* process dots to image buffer */
gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w); gfx_render(gfx.bufferStart, scd.regs[0x62>>1].w & 0x1ff);
/* increment image buffer start index for next line (8 pixels/line) */ /* increment image buffer start index for next line (8 pixels/line) */
gfx.bufferStart += 8; gfx.bufferStart += 8;