all repos — mgba @ 02ecfa684360a458de8477665162fcd394ef2c09

mGBA Game Boy Advance Emulator

GBA Memory: Improve Thumb open bus behavior (fixes issue #10)
Jeffrey Pfau jeffrey@endrift.com
Fri, 17 Apr 2015 03:20:09 -0700
commit

02ecfa684360a458de8477665162fcd394ef2c09

parent

592f6614aaa513e94905cafd74695397146bfaa9

2 files changed, 41 insertions(+), 46 deletions(-)

jump to
M CHANGESCHANGES

@@ -25,6 +25,7 @@ - GBA: Add initial I/O register settings for background matrix registers

- Qt: Fix potential crash if a gamepad causes focus to change - GBA Memory: Allow SRAM to be 64kB - Qt: Fix controller axis querying + - GBA Memory: Improve Thumb open bus behavior Misc: - Qt: Show multiplayer numbers in window title
M src/gba/memory.csrc/gba/memory.c

@@ -279,13 +279,30 @@ cpu->memory.activeUncachedCycles16 = memory->waitstatesNonseq16[memory->activeRegion];

} #define LOAD_BAD \ - GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \ if (gba->performingDMA) { \ value = gba->bus; \ } else { \ value = cpu->prefetch[1]; \ if (cpu->executionMode == MODE_THUMB) { \ - value |= value << 16; \ + /* http://ngemu.com/threads/gba-open-bus.170809/ */ \ + switch (cpu->gprs[ARM_PC] >> BASE_OFFSET) { \ + case REGION_BIOS: \ + case REGION_OAM: \ + /* This isn't right half the time, but we don't have $+6 handy */ \ + value <<= 16; \ + value |= cpu->prefetch[0]; \ + break; \ + case REGION_WORKING_IRAM: \ + /* This doesn't handle prefetch clobbering */ \ + if (cpu->gprs[ARM_PC] & 2) { \ + value |= cpu->prefetch[0] << 16; \ + } else { \ + value <<= 16; \ + value |= cpu->prefetch[0]; \ + } \ + default: \ + value |= value << 16; \ + } \ } \ }

@@ -298,6 +315,7 @@ GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load32: 0x%08X", address); \

value = memory->biosPrefetch; \ } \ } else { \ + GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \ LOAD_BAD; \ }

@@ -380,6 +398,7 @@ case REGION_CART_SRAM_MIRROR:

LOAD_SRAM; break; default: + GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); LOAD_BAD; break; }

@@ -409,15 +428,9 @@ LOAD_16(value, address & 2, &memory->biosPrefetch);

} } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); - if (gba->performingDMA) { - LOAD_16(value, address & 2, &gba->bus); - } else { - uint32_t prefetch = cpu->prefetch[1]; - if (cpu->executionMode == MODE_THUMB) { - prefetch |= prefetch << 16; - } - LOAD_16(value, address & 2, &prefetch); - } + LOAD_BAD; + uint32_t v2 = value; + LOAD_16(v2, address & 2, &value); } break; case REGION_WORKING_RAM:

@@ -475,15 +488,9 @@ value |= value << 8;

break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address); - if (gba->performingDMA) { - LOAD_16(value, address & 2, &gba->bus); - } else { - uint32_t prefetch = cpu->prefetch[1]; - if (cpu->executionMode == MODE_THUMB) { - prefetch |= prefetch << 16; - } - LOAD_16(value, address & 2, &prefetch); - } + LOAD_BAD; + uint32_t v2 = value; + LOAD_16(v2, address & 2, &value); break; }

@@ -498,49 +505,42 @@

uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory; - uint8_t value = 0; + uint32_t value = 0; int wait = 0; switch (address >> BASE_OFFSET) { case REGION_BIOS: if (address < SIZE_BIOS) { if (memory->activeRegion == REGION_BIOS) { - value = ((int8_t*) memory->bios)[address]; + value = ((uint8_t*) memory->bios)[address]; } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address); value = ((uint8_t*) &memory->biosPrefetch)[address & 3]; } } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address); - if (gba->performingDMA) { - value = ((uint8_t*) &gba->bus)[address & 3]; - } else { - uint32_t prefetch = cpu->prefetch[1]; - if (cpu->executionMode == MODE_THUMB) { - prefetch |= prefetch << 16; - } - value = ((uint8_t*) &prefetch)[address & 3]; - } + LOAD_BAD; + value = ((uint8_t*) &value)[address & 3]; } break; case REGION_WORKING_RAM: - value = ((int8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)]; + value = ((uint8_t*) memory->wram)[address & (SIZE_WORKING_RAM - 1)]; wait = memory->waitstatesNonseq16[REGION_WORKING_RAM]; break; case REGION_WORKING_IRAM: - value = ((int8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; + value = ((uint8_t*) memory->iwram)[address & (SIZE_WORKING_IRAM - 1)]; break; case REGION_IO: value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF; break; case REGION_PALETTE_RAM: - value = ((int8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)]; + value = ((uint8_t*) gba->video.palette)[address & (SIZE_PALETTE_RAM - 1)]; break; case REGION_VRAM: if ((address & 0x0001FFFF) < SIZE_VRAM) { - value = ((int8_t*) gba->video.renderer->vram)[address & 0x0001FFFF]; + value = ((uint8_t*) gba->video.renderer->vram)[address & 0x0001FFFF]; } else { - value = ((int8_t*) gba->video.renderer->vram)[address & 0x00017FFF]; + value = ((uint8_t*) gba->video.renderer->vram)[address & 0x00017FFF]; } break; case REGION_OAM:

@@ -554,7 +554,7 @@ case REGION_CART2:

case REGION_CART2_EX: wait = memory->waitstatesNonseq16[address >> BASE_OFFSET]; if ((address & (SIZE_CART0 - 1)) < memory->romSize) { - value = ((int8_t*) memory->rom)[address & (SIZE_CART0 - 1)]; + value = ((uint8_t*) memory->rom)[address & (SIZE_CART0 - 1)]; } else { GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address); value = (address >> 1) & 0xFF; \

@@ -577,18 +577,12 @@ } else {

GBALog(gba, GBA_LOG_GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address); value = 0xFF; } + value &= 0xFF; break; default: GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address); - if (gba->performingDMA) { - value = ((uint8_t*) &gba->bus)[address & 3]; - } else { - uint32_t prefetch = cpu->prefetch[1]; - if (cpu->executionMode == MODE_THUMB) { - prefetch |= prefetch << 16; - } - value = ((uint8_t*) &prefetch)[address & 3]; - } + LOAD_BAD; + value = ((uint8_t*) &value)[address & 3]; break; }