Permalink
Browse files

GBA: Clean up I/O register read/write

  • Loading branch information...
endrift committed Nov 12, 2015
1 parent a2bc814 commit 534d4fe5baffae9dca0dfe915c7c379752374ba4
Showing with 77 additions and 22 deletions.
  1. +67 −22 src/gba/io.c
  2. +8 −0 src/gba/memory.c
  3. +2 −0 src/gba/memory.h
View
@@ -254,9 +254,9 @@ static const int _isRSpecialRegister[REG_MAX >> 1] = {
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 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t 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 @@ void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
// 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 @@ bool GBAIOIsReadConstant(uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
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 @@ uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
// 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];
}
View
@@ -374,6 +374,13 @@ static void GBASetActiveRegion(struct ARMCore* cpu, uint32_t address) {
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)) {
View
@@ -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);

0 comments on commit 534d4fe

Please sign in to comment.