From 3b95fdf32864f7d4574e985a85e7299a3e3f3e72 Mon Sep 17 00:00:00 2001 From: ekeeke Date: Sun, 1 Sep 2024 11:36:32 +0200 Subject: [PATCH] [Core/CD] improved GFX processing robustness in case of word-RAM address overflow (fixes potential emulator crash in Flink level 20) --- core/cd_hw/gfx.c | 16 ++++++++++++---- 1 file changed, 12 insertions(+), 4 deletions(-) diff --git a/core/cd_hw/gfx.c b/core/cd_hw/gfx.c index 85600e3..81b8087 100644 --- a/core/cd_hw/gfx.c +++ b/core/cd_hw/gfx.c @@ -455,9 +455,11 @@ int gfx_context_load(uint8 *state) load_param(&gfx.bufferStart, sizeof(gfx.bufferStart)); load_param(&tmp32, 4); + tmp32 &= 0x3fff8; gfx.tracePtr = (uint16 *)(scd.word_ram_2M + tmp32); load_param(&tmp32, 4); + tmp32 &= ~((1 << ((2*gfx.mapShift) + 1)) - 1) & 0x3ffff; gfx.mapPtr = (uint16 *)(scd.word_ram_2M + tmp32); return bufferptr; @@ -480,6 +482,12 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) uint32 xoffset = (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 */ while (width--) { @@ -557,7 +565,7 @@ INLINE void gfx_render(uint32 bufferIndex, uint32 width) } /* 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 */ 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]; /* 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 */ 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 */ /* 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 */ - 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 */ scd.regs[0x58>>1].byte.h = 0x80; @@ -731,7 +739,7 @@ void gfx_update(int cycles) while (lines--) { /* 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) */ gfx.bufferStart += 8;