From 3cddb332880dff06bc9259965acbad589c5d7fef Mon Sep 17 00:00:00 2001 From: Jeffrey Pfau Date: Tue, 16 Jun 2015 05:15:17 -0700 Subject: [PATCH] GBA: Fix calls to endian-independent loadstores --- CHANGES | 1 + src/gba/memory.c | 148 ++++++++++++++--------------- src/gba/renderers/video-software.c | 8 +- 3 files changed, 79 insertions(+), 78 deletions(-) diff --git a/CHANGES b/CHANGES index f2585d80b..b522ce84d 100644 --- a/CHANGES +++ b/CHANGES @@ -43,6 +43,7 @@ Bugfixes: - GBA Audio: Fix audio pitch changing when adjusting buffer size - SDL: Fix SDL build when OpenGL is missing - ARM7: Fix timing of multiplies to use N cycles + - GBA: Fix calls to endian-independent loadstores Misc: - Qt: Handle saving input settings better - Debugger: Free watchpoints in addition to breakpoints diff --git a/src/gba/memory.c b/src/gba/memory.c index 63f0a54ed..19155f9d5 100644 --- a/src/gba/memory.c +++ b/src/gba/memory.c @@ -326,30 +326,30 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) { } #define LOAD_WORKING_RAM \ - LOAD_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \ + LOAD_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \ wait += waitstatesRegion[REGION_WORKING_RAM]; -#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); +#define LOAD_WORKING_IRAM LOAD_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram); #define LOAD_IO value = GBAIORead(gba, (address & (SIZE_IO - 1)) & ~2) | (GBAIORead(gba, (address & (SIZE_IO - 1)) | 2) << 16); #define LOAD_PALETTE_RAM \ - LOAD_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \ + LOAD_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \ ++wait; #define LOAD_VRAM \ if ((address & 0x0001FFFF) < SIZE_VRAM) { \ - LOAD_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \ + LOAD_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \ } else { \ - LOAD_32(value, address & 0x00017FFF, gba->video.renderer->vram); \ + LOAD_32(value, address & 0x00017FFC, gba->video.renderer->vram); \ } \ ++wait; -#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); +#define LOAD_OAM LOAD_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); #define LOAD_CART \ wait += waitstatesRegion[address >> BASE_OFFSET]; \ if ((address & (SIZE_CART0 - 1)) < memory->romSize) { \ - LOAD_32(value, address & (SIZE_CART0 - 1), memory->rom); \ + LOAD_32(value, address & (SIZE_CART0 - 4), memory->rom); \ } else { \ GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load32: 0x%08X", address); \ value = (address >> 1) & 0xFFFF; \ @@ -440,27 +440,27 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } break; case REGION_WORKING_RAM: - LOAD_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram); + LOAD_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram); wait = memory->waitstatesNonseq16[REGION_WORKING_RAM]; break; case REGION_WORKING_IRAM: - LOAD_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); + LOAD_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram); break; case REGION_IO: - value = GBAIORead(gba, address & (SIZE_IO - 1)); + value = GBAIORead(gba, address & (SIZE_IO - 2)); break; case REGION_PALETTE_RAM: - LOAD_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); + LOAD_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette); break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_16(value, address & 0x0001FFFF, gba->video.renderer->vram); + LOAD_16(value, address & 0x0001FFFE, gba->video.renderer->vram); } else { - LOAD_16(value, address & 0x00017FFF, gba->video.renderer->vram); + LOAD_16(value, address & 0x00017FFE, gba->video.renderer->vram); } break; case REGION_OAM: - LOAD_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw); + LOAD_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw); break; case REGION_CART0: case REGION_CART0_EX: @@ -469,7 +469,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { case REGION_CART2: wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < memory->romSize) { - LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom); + LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address); value = (address >> 1) & 0xFFFF; \ @@ -480,7 +480,7 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { if (memory->savedata.type == SAVEDATA_EEPROM) { value = GBASavedataReadEEPROM(&memory->savedata); } else if ((address & (SIZE_CART0 - 1)) < memory->romSize) { - LOAD_16(value, address & (SIZE_CART0 - 1), memory->rom); + LOAD_16(value, address & (SIZE_CART0 - 2), memory->rom); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load16: 0x%08X", address); value = (address >> 1) & 0xFFFF; \ @@ -599,31 +599,31 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { } #define STORE_WORKING_RAM \ - STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); \ + STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); \ wait += waitstatesRegion[REGION_WORKING_RAM]; #define STORE_WORKING_IRAM \ - STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); + STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram); #define STORE_IO \ - GBAIOWrite32(gba, address & (SIZE_IO - 1), value); + GBAIOWrite32(gba, address & (SIZE_IO - 4), value); #define STORE_PALETTE_RAM \ - STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); \ - gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16); \ + STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); \ + gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); \ ++wait; \ - gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value); + gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value); #define STORE_VRAM \ if ((address & 0x0001FFFF) < SIZE_VRAM) { \ - STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); \ + STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); \ } else { \ - STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); \ + STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); \ } \ ++wait; #define STORE_OAM \ - STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); \ + STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); \ gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); \ gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) >> 1) + 1); @@ -691,33 +691,33 @@ void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycle switch (address >> BASE_OFFSET) { case REGION_WORKING_RAM: - STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram); + STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram); wait = memory->waitstatesNonseq16[REGION_WORKING_RAM]; break; case REGION_WORKING_IRAM: - STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); + STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram); break; case REGION_IO: - GBAIOWrite(gba, address & (SIZE_IO - 1), value); + GBAIOWrite(gba, address & (SIZE_IO - 2), value); break; case REGION_PALETTE_RAM: - STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); - gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value); + STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette); + gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value); break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram); + STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram); } else { - STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram); + STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram); } break; case REGION_OAM: - STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw); - gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1); + STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw); + gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1); break; case REGION_CART0: - if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFF)) { - uint32_t reg = address & 0xFFFFFF; + if (memory->hw.devices != HW_NONE && IS_GPIO_REGISTER(address & 0xFFFFFE)) { + uint32_t reg = address & 0xFFFFFE; GBAHardwareGPIOWrite(&memory->hw, reg, value); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad cartridge Store16: 0x%08X", address); @@ -817,36 +817,36 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o switch (address >> BASE_OFFSET) { case REGION_WORKING_RAM: - LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 1), memory->wram); - STORE_32(value, address & (SIZE_WORKING_RAM - 1), memory->wram); + LOAD_32(oldValue, address & (SIZE_WORKING_RAM - 4), memory->wram); + STORE_32(value, address & (SIZE_WORKING_RAM - 4), memory->wram); break; case REGION_WORKING_IRAM: - LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 1), memory->iwram); - STORE_32(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); + LOAD_32(oldValue, address & (SIZE_WORKING_IRAM - 4), memory->iwram); + STORE_32(value, address & (SIZE_WORKING_IRAM - 4), memory->iwram); break; case REGION_IO: GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch32: 0x%08X", address); break; case REGION_PALETTE_RAM: LOAD_32(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); - STORE_32(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); - gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value); - gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 1)) + 2, value >> 16); + STORE_32(value, address & (SIZE_PALETTE_RAM - 4), gba->video.palette); + gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 4), value); + gba->video.renderer->writePalette(gba->video.renderer, (address & (SIZE_PALETTE_RAM - 4)) + 2, value >> 16); break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_32(oldValue, address & 0x0001FFFF, gba->video.renderer->vram); - STORE_32(value, address & 0x0001FFFF, gba->video.renderer->vram); + LOAD_32(oldValue, address & 0x0001FFFC, gba->video.renderer->vram); + STORE_32(value, address & 0x0001FFFC, gba->video.renderer->vram); } else { - LOAD_32(oldValue, address & 0x00017FFF, gba->video.renderer->vram); - STORE_32(value, address & 0x00017FFF, gba->video.renderer->vram); + LOAD_32(oldValue, address & 0x00017FFC, gba->video.renderer->vram); + STORE_32(value, address & 0x00017FFC, gba->video.renderer->vram); } break; case REGION_OAM: - LOAD_32(oldValue, address & (SIZE_OAM - 1), gba->video.oam.raw); - STORE_32(value, address & (SIZE_OAM - 1), gba->video.oam.raw); - gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1); - gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 1)) + 2) >> 1); + LOAD_32(oldValue, address & (SIZE_OAM - 4), gba->video.oam.raw); + STORE_32(value, address & (SIZE_OAM - 4), gba->video.oam.raw); + gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 4)) >> 1); + gba->video.renderer->writeOAM(gba->video.renderer, ((address & (SIZE_OAM - 4)) + 2) >> 1); break; case REGION_CART0: case REGION_CART0_EX: @@ -855,17 +855,17 @@ void GBAPatch32(struct ARMCore* cpu, uint32_t address, int32_t value, int32_t* o case REGION_CART2: case REGION_CART2_EX: _pristineCow(gba); - if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) { + if ((address & (SIZE_CART0 - 4)) >= gba->memory.romSize) { gba->memory.romSize = (address & (SIZE_CART0 - 4)) + 4; } - LOAD_32(oldValue, address & (SIZE_CART0 - 1), gba->memory.rom); - STORE_32(value, address & (SIZE_CART0 - 1), gba->memory.rom); + LOAD_32(oldValue, address & (SIZE_CART0 - 4), gba->memory.rom); + STORE_32(value, address & (SIZE_CART0 - 4), gba->memory.rom); break; case REGION_CART_SRAM: case REGION_CART_SRAM_MIRROR: if (memory->savedata.type == SAVEDATA_SRAM) { - LOAD_32(oldValue, address & (SIZE_CART_SRAM - 1), memory->savedata.data); - STORE_32(value, address & (SIZE_CART_SRAM - 1), memory->savedata.data); + LOAD_32(oldValue, address & (SIZE_CART_SRAM - 4), memory->savedata.data); + STORE_32(value, address & (SIZE_CART_SRAM - 4), memory->savedata.data); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address); } @@ -886,34 +886,34 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o switch (address >> BASE_OFFSET) { case REGION_WORKING_RAM: - LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 1), memory->wram); - STORE_16(value, address & (SIZE_WORKING_RAM - 1), memory->wram); + LOAD_16(oldValue, address & (SIZE_WORKING_RAM - 2), memory->wram); + STORE_16(value, address & (SIZE_WORKING_RAM - 2), memory->wram); break; case REGION_WORKING_IRAM: - LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 1), memory->iwram); - STORE_16(value, address & (SIZE_WORKING_IRAM - 1), memory->iwram); + LOAD_16(oldValue, address & (SIZE_WORKING_IRAM - 2), memory->iwram); + STORE_16(value, address & (SIZE_WORKING_IRAM - 2), memory->iwram); break; case REGION_IO: GBALog(gba, GBA_LOG_STUB, "Unimplemented memory Patch16: 0x%08X", address); break; case REGION_PALETTE_RAM: - LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); - STORE_16(value, address & (SIZE_PALETTE_RAM - 1), gba->video.palette); - gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 1), value); + LOAD_16(oldValue, address & (SIZE_PALETTE_RAM - 2), gba->video.palette); + STORE_16(value, address & (SIZE_PALETTE_RAM - 2), gba->video.palette); + gba->video.renderer->writePalette(gba->video.renderer, address & (SIZE_PALETTE_RAM - 2), value); break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - LOAD_16(oldValue, address & 0x0001FFFF, gba->video.renderer->vram); - STORE_16(value, address & 0x0001FFFF, gba->video.renderer->vram); + LOAD_16(oldValue, address & 0x0001FFFE, gba->video.renderer->vram); + STORE_16(value, address & 0x0001FFFE, gba->video.renderer->vram); } else { - LOAD_16(oldValue, address & 0x00017FFF, gba->video.renderer->vram); - STORE_16(value, address & 0x00017FFF, gba->video.renderer->vram); + LOAD_16(oldValue, address & 0x00017FFE, gba->video.renderer->vram); + STORE_16(value, address & 0x00017FFE, gba->video.renderer->vram); } break; case REGION_OAM: - LOAD_16(oldValue, address & (SIZE_OAM - 1), gba->video.oam.raw); - STORE_16(value, address & (SIZE_OAM - 1), gba->video.oam.raw); - gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 1)) >> 1); + LOAD_16(oldValue, address & (SIZE_OAM - 2), gba->video.oam.raw); + STORE_16(value, address & (SIZE_OAM - 2), gba->video.oam.raw); + gba->video.renderer->writeOAM(gba->video.renderer, (address & (SIZE_OAM - 2)) >> 1); break; case REGION_CART0: case REGION_CART0_EX: @@ -925,14 +925,14 @@ void GBAPatch16(struct ARMCore* cpu, uint32_t address, int16_t value, int16_t* o if ((address & (SIZE_CART0 - 1)) >= gba->memory.romSize) { gba->memory.romSize = (address & (SIZE_CART0 - 2)) + 2; } - LOAD_16(oldValue, address & (SIZE_CART0 - 1), gba->memory.rom); - STORE_16(value, address & (SIZE_CART0 - 1), gba->memory.rom); + LOAD_16(oldValue, address & (SIZE_CART0 - 2), gba->memory.rom); + STORE_16(value, address & (SIZE_CART0 - 2), gba->memory.rom); break; case REGION_CART_SRAM: case REGION_CART_SRAM_MIRROR: if (memory->savedata.type == SAVEDATA_SRAM) { - LOAD_16(oldValue, address & (SIZE_CART_SRAM - 1), memory->savedata.data); - STORE_16(value, address & (SIZE_CART_SRAM - 1), memory->savedata.data); + LOAD_16(oldValue, address & (SIZE_CART_SRAM - 2), memory->savedata.data); + STORE_16(value, address & (SIZE_CART_SRAM - 2), memory->savedata.data); } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Writing to non-existent SRAM: 0x%08X", address); } diff --git a/src/gba/renderers/video-software.c b/src/gba/renderers/video-software.c index 22217c4ef..06fe436c0 100644 --- a/src/gba/renderers/video-software.c +++ b/src/gba/renderers/video-software.c @@ -1723,7 +1723,7 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru #define SPRITE_YBASE_16(localY) unsigned yBase = (localY & ~0x7) * (GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? width >> 1 : 0x80) + (localY & 0x7) * 4; #define SPRITE_DRAW_PIXEL_16_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ + LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -1735,7 +1735,7 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru } #define SPRITE_DRAW_PIXEL_16_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ + LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ tileData = (tileData >> ((localX & 3) << 2)) & 0xF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \ @@ -1745,7 +1745,7 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru #define SPRITE_YBASE_256(localY) unsigned yBase = (localY & ~0x7) * (GBARegisterDISPCNTIsObjCharacterMapping(renderer->dispcnt) ? width : 0x80) + (localY & 0x7) * 8; #define SPRITE_DRAW_PIXEL_256_NORMAL(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ + LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ current = renderer->spriteLayer[outX]; \ if ((current & FLAG_ORDER_MASK) > flags) { \ @@ -1757,7 +1757,7 @@ static void _drawBackgroundMode5(struct GBAVideoSoftwareRenderer* renderer, stru } #define SPRITE_DRAW_PIXEL_256_OBJWIN(localX) \ - LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFF), vramBase); \ + LOAD_16(tileData, ((yBase + charBase + xBase) & 0x7FFE), vramBase); \ tileData = (tileData >> ((localX & 1) << 3)) & 0xFF; \ if (tileData) { \ renderer->row[outX] |= FLAG_OBJWIN; \