From ba00cdfc024e495dc377f07d9ed6e5c57958de9c Mon Sep 17 00:00:00 2001 From: Vicki Pfau Date: Thu, 30 May 2019 12:26:49 -0700 Subject: [PATCH] GBA Memory: Fix STM to VRAM (fixes #1430) --- CHANGES | 1 + src/gba/memory.c | 52 ++++++++++++++++++++++++++++++------------------ 2 files changed, 34 insertions(+), 19 deletions(-) diff --git a/CHANGES b/CHANGES index 84dbb27fa..3366a9ea9 100644 --- a/CHANGES +++ b/CHANGES @@ -19,6 +19,7 @@ Emulation fixes: - GB Video: Fix window being enabled mid-scanline (fixes mgba.io/i/1328) - GB I/O: Filter IE top bits properly (fixes mgba.io/i/1329) - GBA Video: Fix wrapped sprite mosaic clamping (fixes mgba.io/i/1432) + - GBA Memory: Fix STM to VRAM (fixes mgba.io/i/1430) Other fixes: - Qt: Fix some Qt display driver race conditions - Core: Improved lockstep driver reliability (Le Hoang Quyen) diff --git a/src/gba/memory.c b/src/gba/memory.c index 3f037567c..62fa6fda9 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -396,9 +396,10 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { value = 0; \ break; \ } \ - address &= 0x00017FFC; \ + LOAD_32(value, address & 0x00017FFC, gba->video.vram); \ + } else { \ + LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \ } \ - LOAD_32(value, address & 0x0001FFFC, gba->video.vram); \ wait += waitstatesRegion[REGION_VRAM]; #define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); @@ -530,9 +531,10 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { value = 0; break; } - address &= 0x00017FFE; + LOAD_16(value, address & 0x00017FFE, gba->video.vram); + } else { + LOAD_16(value, address & 0x0001FFFE, gba->video.vram); } - LOAD_16(value, address & 0x0001FFFE, gba->video.vram); break; case REGION_OAM: LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw); @@ -645,9 +647,10 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { value = 0; break; } - address &= 0x00017FFF; + value = ((uint8_t*) gba->video.vram)[address & 0x00017FFF]; + } else { + value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF]; } - value = ((uint8_t*) gba->video.vram)[address & 0x0001FFFF]; break; case REGION_OAM: value = ((uint8_t*) gba->video.oam.raw)[address & (SIZE_OAM - 1)]; @@ -734,13 +737,19 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { mLOG(GBA_MEM, GAME_ERROR, "Bad VRAM Store32: 0x%08X", address); \ break; \ } \ - address &= 0x00017FFC; \ - } \ - LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); \ - if (oldValue != value) { \ - STORE_32(value, address & 0x0001FFFC, gba->video.vram); \ - gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \ - gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \ + LOAD_32(oldValue, address & 0x00017FFC, gba->video.vram); \ + if (oldValue != value) { \ + STORE_32(value, address & 0x00017FFC, gba->video.vram); \ + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC) + 2); \ + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x00017FFC)); \ + } \ + } else { \ + LOAD_32(oldValue, address & 0x0001FFFC, gba->video.vram); \ + if (oldValue != value) { \ + STORE_32(value, address & 0x0001FFFC, gba->video.vram); \ + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC) + 2); \ + gba->video.renderer->writeVRAM(gba->video.renderer, (address & 0x0001FFFC)); \ + } \ } \ wait += waitstatesRegion[REGION_VRAM]; @@ -855,12 +864,17 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle mLOG(GBA_MEM, GAME_ERROR, "Bad VRAM Store16: 0x%08X", address); break; } - address &= 0x00017FFE; - } - LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram); - if (value != oldValue) { - STORE_16(value, address & 0x0001FFFE, gba->video.vram); - gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); + LOAD_16(oldValue, address & 0x00017FFE, gba->video.vram); + if (value != oldValue) { + STORE_16(value, address & 0x00017FFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x00017FFE); + } + } else { + LOAD_16(oldValue, address & 0x0001FFFE, gba->video.vram); + if (value != oldValue) { + STORE_16(value, address & 0x0001FFFE, gba->video.vram); + gba->video.renderer->writeVRAM(gba->video.renderer, address & 0x0001FFFE); + } } break; case REGION_OAM: