all repos — mgba @ 534d4fe5baffae9dca0dfe915c7c379752374ba4

mGBA Game Boy Advance Emulator

GBA: Clean up I/O register read/write
Jeffrey Pfau jeffrey@endrift.com
Wed, 11 Nov 2015 19:46:16 -0800
commit

534d4fe5baffae9dca0dfe915c7c379752374ba4

parent

a2bc814d9c93572f6d0da014a138495995afff4e

3 files changed, 77 insertions(+), 22 deletions(-)

jump to
M src/gba/io.csrc/gba/io.c

@@ -254,9 +254,9 @@ 0, 0, 0, 0, 1, 0, 0, 0,

1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, // DMA - 0, 0, 0, 0, 0, 1, 0, 0, - 0, 0, 0, 1, 0, 0, 0, 0, - 0, 1, 0, 0, 0, 0, 0, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, + 1, 1, 1, 1, 1, 1, 1, 1, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, // Timers

@@ -389,10 +389,11 @@ GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);

break; case REG_SOUNDCNT_HI: GBAAudioWriteSOUNDCNT_HI(&gba->audio, value); + value &= 0x770F; break; case REG_SOUNDCNT_X: GBAAudioWriteSOUNDCNT_X(&gba->audio, value); - value &= 0xFFFF; + value &= 0x00F0; value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF; break; case REG_SOUNDBIAS:

@@ -531,7 +532,7 @@ case REG_MAX:

// Some bad interrupt libraries will write to this break; default: - GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address); + GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03X", address); if (address >= REG_MAX) { GBALog(gba, GBA_LOG_GAME_ERROR, "Write to unused I/O register: %03X", address); return;

@@ -620,10 +621,22 @@ case REG_WININ:

case REG_WINOUT: case REG_BLDCNT: case REG_BLDALPHA: - case REG_DMA0CNT_LO: - case REG_DMA1CNT_LO: - case REG_DMA2CNT_LO: - case REG_DMA3CNT_LO: + case REG_SOUND1CNT_LO: + case REG_SOUND1CNT_HI: + case REG_SOUND1CNT_X: + case REG_SOUND2CNT_LO: + case REG_SOUND2CNT_HI: + case REG_SOUND3CNT_LO: + case REG_SOUND3CNT_HI: + case REG_SOUND3CNT_X: + case REG_SOUND4CNT_LO: + case REG_SOUND4CNT_HI: + case REG_SOUNDCNT_LO: + case REG_SOUNDCNT_HI: + case REG_TM0CNT_HI: + case REG_TM1CNT_HI: + case REG_TM2CNT_HI: + case REG_TM3CNT_HI: case REG_KEYINPUT: case REG_IE: return true;

@@ -671,12 +684,6 @@ return gba->sio.siocnt;

case REG_RCNT: return gba->sio.rcnt; - case REG_DMA0CNT_LO: - case REG_DMA1CNT_LO: - case REG_DMA2CNT_LO: - case REG_DMA3CNT_LO: - // Write-only register - return 0; case REG_BG0HOFS: case REG_BG0VOFS: case REG_BG1HOFS:

@@ -707,9 +714,42 @@ case REG_WIN0V:

case REG_WIN1V: case REG_MOSAIC: case REG_BLDY: + case REG_FIFO_A_LO: + case REG_FIFO_A_HI: + case REG_FIFO_B_LO: + case REG_FIFO_B_HI: + case REG_DMA0SAD_LO: + case REG_DMA0SAD_HI: + case REG_DMA0DAD_LO: + case REG_DMA0DAD_HI: + case REG_DMA0CNT_LO: + case REG_DMA1SAD_LO: + case REG_DMA1SAD_HI: + case REG_DMA1DAD_LO: + case REG_DMA1DAD_HI: + case REG_DMA1CNT_LO: + case REG_DMA2SAD_LO: + case REG_DMA2SAD_HI: + case REG_DMA2DAD_LO: + case REG_DMA2DAD_HI: + case REG_DMA2CNT_LO: + case REG_DMA3SAD_LO: + case REG_DMA3SAD_HI: + case REG_DMA3DAD_LO: + case REG_DMA3DAD_HI: + case REG_DMA3CNT_LO: // Write-only register GBALog(gba, GBA_LOG_GAME_ERROR, "Read from write-only I/O register: %03X", address); - return GBALoad16(gba->cpu, 0x01000000, 0); // Simulate a bad load + return GBALoadBad(gba->cpu); + + case REG_SOUNDBIAS: + case REG_JOYCNT: + case REG_JOY_RECV: + case REG_JOY_TRANS: + case REG_KEYCNT: + case REG_POSTFLG: + GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address); + break; case REG_DISPCNT: case REG_DISPSTAT: case REG_VCOUNT:

@@ -733,6 +773,15 @@ case REG_SOUND4CNT_LO:

case REG_SOUND4CNT_HI: case REG_SOUNDCNT_LO: case REG_SOUNDCNT_HI: + case REG_SOUNDCNT_X: + case REG_WAVE_RAM0_LO: + case REG_WAVE_RAM0_HI: + case REG_WAVE_RAM1_LO: + case REG_WAVE_RAM1_HI: + case REG_WAVE_RAM2_LO: + case REG_WAVE_RAM2_HI: + case REG_WAVE_RAM3_LO: + case REG_WAVE_RAM3_HI: case REG_DMA0CNT_HI: case REG_DMA1CNT_HI: case REG_DMA2CNT_HI:

@@ -752,12 +801,8 @@ case REG_MAX:

// Some bad interrupt libraries will read from this break; default: - GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address); - if (address >= REG_MAX) { - GBALog(gba, GBA_LOG_GAME_ERROR, "Read from unused I/O register: %03X", address); - return GBALoad16(gba->cpu, 0x01000000, 0); - } - break; + GBALog(gba, GBA_LOG_GAME_ERROR, "Read from unused I/O register: %03X", address); + return GBALoadBad(gba->cpu); } return gba->memory.io[address >> 1]; }
M src/gba/memory.csrc/gba/memory.c

@@ -374,6 +374,13 @@ value = GBALoad8(cpu, address, 0); \

value |= value << 8; \ value |= value << 16; +uint32_t GBALoadBad(struct ARMCore* cpu) { + struct GBA* gba = (struct GBA*) cpu->master; + uint32_t value = 0; + LOAD_BAD; + return value; +} + uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter) { struct GBA* gba = (struct GBA*) cpu->master; struct GBAMemory* memory = &gba->memory;

@@ -1364,6 +1371,7 @@ uint16_t GBAMemoryWriteDMACNT_HI(struct GBA* gba, int dma, uint16_t control) {

struct GBAMemory* memory = &gba->memory; struct GBADMA* currentDma = &memory->dma[dma]; int wasEnabled = GBADMARegisterIsEnable(currentDma->reg); + control &= 0xFFE0; currentDma->reg = control; if (GBADMARegisterIsDRQ(currentDma->reg)) {
M src/gba/memory.hsrc/gba/memory.h

@@ -151,6 +151,8 @@ uint32_t GBALoad32(struct ARMCore* cpu, uint32_t address, int* cycleCounter);

uint32_t GBALoad16(struct ARMCore* cpu, uint32_t address, int* cycleCounter); uint32_t GBALoad8(struct ARMCore* cpu, uint32_t address, int* cycleCounter); +uint32_t GBALoadBad(struct ARMCore* cpu); + void GBAStore32(struct ARMCore* cpu, uint32_t address, int32_t value, int* cycleCounter); void GBAStore16(struct ARMCore* cpu, uint32_t address, int16_t value, int* cycleCounter); void GBAStore8(struct ARMCore* cpu, uint32_t address, int8_t value, int* cycleCounter);