mirror of https://github.com/mgba-emu/mgba.git
GBA Memory: Improve Thumb open bus behavior (fixes issue #10)
This commit is contained in:
parent
592f6614aa
commit
02ecfa6843
1
CHANGES
1
CHANGES
|
@ -25,6 +25,7 @@ Bugfixes:
|
||||||
- Qt: Fix potential crash if a gamepad causes focus to change
|
- Qt: Fix potential crash if a gamepad causes focus to change
|
||||||
- GBA Memory: Allow SRAM to be 64kB
|
- GBA Memory: Allow SRAM to be 64kB
|
||||||
- Qt: Fix controller axis querying
|
- Qt: Fix controller axis querying
|
||||||
|
- GBA Memory: Improve Thumb open bus behavior
|
||||||
Misc:
|
Misc:
|
||||||
- Qt: Show multiplayer numbers in window title
|
- Qt: Show multiplayer numbers in window title
|
||||||
|
|
||||||
|
|
|
@ -279,13 +279,30 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
}
|
}
|
||||||
|
|
||||||
#define LOAD_BAD \
|
#define LOAD_BAD \
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
|
|
||||||
if (gba->performingDMA) { \
|
if (gba->performingDMA) { \
|
||||||
value = gba->bus; \
|
value = gba->bus; \
|
||||||
} else { \
|
} else { \
|
||||||
value = cpu->prefetch[1]; \
|
value = cpu->prefetch[1]; \
|
||||||
if (cpu->executionMode == MODE_THUMB) { \
|
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 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
|
||||||
value = memory->biosPrefetch; \
|
value = memory->biosPrefetch; \
|
||||||
} \
|
} \
|
||||||
} else { \
|
} else { \
|
||||||
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address); \
|
||||||
LOAD_BAD; \
|
LOAD_BAD; \
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -380,6 +398,7 @@ uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
LOAD_SRAM;
|
LOAD_SRAM;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load32: 0x%08X", address);
|
||||||
LOAD_BAD;
|
LOAD_BAD;
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
@ -409,15 +428,9 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||||
if (gba->performingDMA) {
|
LOAD_BAD;
|
||||||
LOAD_16(value, address & 2, &gba->bus);
|
uint32_t v2 = value;
|
||||||
} else {
|
LOAD_16(v2, address & 2, &value);
|
||||||
uint32_t prefetch = cpu->prefetch[1];
|
|
||||||
if (cpu->executionMode == MODE_THUMB) {
|
|
||||||
prefetch |= prefetch << 16;
|
|
||||||
}
|
|
||||||
LOAD_16(value, address & 2, &prefetch);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REGION_WORKING_RAM:
|
case REGION_WORKING_RAM:
|
||||||
|
@ -475,15 +488,9 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load16: 0x%08X", address);
|
||||||
if (gba->performingDMA) {
|
LOAD_BAD;
|
||||||
LOAD_16(value, address & 2, &gba->bus);
|
uint32_t v2 = value;
|
||||||
} else {
|
LOAD_16(v2, address & 2, &value);
|
||||||
uint32_t prefetch = cpu->prefetch[1];
|
|
||||||
if (cpu->executionMode == MODE_THUMB) {
|
|
||||||
prefetch |= prefetch << 16;
|
|
||||||
}
|
|
||||||
LOAD_16(value, address & 2, &prefetch);
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -498,49 +505,42 @@ uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
struct GBA* gba = (struct GBA*) cpu->master;
|
struct GBA* gba = (struct GBA*) cpu->master;
|
||||||
struct GBAMemory* memory = &gba->memory;
|
struct GBAMemory* memory = &gba->memory;
|
||||||
uint8_t value = 0;
|
uint32_t value = 0;
|
||||||
int wait = 0;
|
int wait = 0;
|
||||||
|
|
||||||
switch (address >> BASE_OFFSET) {
|
switch (address >> BASE_OFFSET) {
|
||||||
case REGION_BIOS:
|
case REGION_BIOS:
|
||||||
if (address < SIZE_BIOS) {
|
if (address < SIZE_BIOS) {
|
||||||
if (memory->activeRegion == REGION_BIOS) {
|
if (memory->activeRegion == REGION_BIOS) {
|
||||||
value = ((int8_t*) memory->bios)[address];
|
value = ((uint8_t*) memory->bios)[address];
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad BIOS Load8: 0x%08X", address);
|
||||||
value = ((uint8_t*) &memory->biosPrefetch)[address & 3];
|
value = ((uint8_t*) &memory->biosPrefetch)[address & 3];
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||||
if (gba->performingDMA) {
|
LOAD_BAD;
|
||||||
value = ((uint8_t*) &gba->bus)[address & 3];
|
value = ((uint8_t*) &value)[address & 3];
|
||||||
} else {
|
|
||||||
uint32_t prefetch = cpu->prefetch[1];
|
|
||||||
if (cpu->executionMode == MODE_THUMB) {
|
|
||||||
prefetch |= prefetch << 16;
|
|
||||||
}
|
|
||||||
value = ((uint8_t*) &prefetch)[address & 3];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REGION_WORKING_RAM:
|
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];
|
wait = memory->waitstatesNonseq16[REGION_WORKING_RAM];
|
||||||
break;
|
break;
|
||||||
case REGION_WORKING_IRAM:
|
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;
|
break;
|
||||||
case REGION_IO:
|
case REGION_IO:
|
||||||
value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
|
value = (GBAIORead(gba, address & 0xFFFE) >> ((address & 0x0001) << 3)) & 0xFF;
|
||||||
break;
|
break;
|
||||||
case REGION_PALETTE_RAM:
|
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;
|
break;
|
||||||
case REGION_VRAM:
|
case REGION_VRAM:
|
||||||
if ((address & 0x0001FFFF) < SIZE_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 {
|
} else {
|
||||||
value = ((int8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
|
value = ((uint8_t*) gba->video.renderer->vram)[address & 0x00017FFF];
|
||||||
}
|
}
|
||||||
break;
|
break;
|
||||||
case REGION_OAM:
|
case REGION_OAM:
|
||||||
|
@ -554,7 +554,7 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
case REGION_CART2_EX:
|
case REGION_CART2_EX:
|
||||||
wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
|
wait = memory->waitstatesNonseq16[address >> BASE_OFFSET];
|
||||||
if ((address & (SIZE_CART0 - 1)) < memory->romSize) {
|
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 {
|
} else {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Out of bounds ROM Load8: 0x%08X", address);
|
||||||
value = (address >> 1) & 0xFF; \
|
value = (address >> 1) & 0xFF; \
|
||||||
|
@ -577,18 +577,12 @@ uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter) {
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Reading from non-existent SRAM: 0x%08X", address);
|
||||||
value = 0xFF;
|
value = 0xFF;
|
||||||
}
|
}
|
||||||
|
value &= 0xFF;
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
GBALog(gba, GBA_LOG_GAME_ERROR, "Bad memory Load8: 0x%08x", address);
|
||||||
if (gba->performingDMA) {
|
LOAD_BAD;
|
||||||
value = ((uint8_t*) &gba->bus)[address & 3];
|
value = ((uint8_t*) &value)[address & 3];
|
||||||
} else {
|
|
||||||
uint32_t prefetch = cpu->prefetch[1];
|
|
||||||
if (cpu->executionMode == MODE_THUMB) {
|
|
||||||
prefetch |= prefetch << 16;
|
|
||||||
}
|
|
||||||
value = ((uint8_t*) &prefetch)[address & 3];
|
|
||||||
}
|
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in New Issue