127 lines
2.9 KiB
C
127 lines
2.9 KiB
C
#include "gba-io.h"
|
|
|
|
#include "gba-video.h"
|
|
|
|
void GBAIOInit(struct GBA* gba) {
|
|
gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
|
|
}
|
|
|
|
void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
|
|
switch (address) {
|
|
case REG_DISPSTAT:
|
|
GBAVideoWriteDISPSTAT(&gba->video, value);
|
|
break;
|
|
case REG_DMA0CNT_LO:
|
|
GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
|
|
break;
|
|
case REG_DMA0CNT_HI:
|
|
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
|
|
break;
|
|
case REG_DMA1CNT_LO:
|
|
GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
|
|
break;
|
|
case REG_DMA1CNT_HI:
|
|
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
|
|
break;
|
|
case REG_DMA2CNT_LO:
|
|
GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
|
|
break;
|
|
case REG_DMA2CNT_HI:
|
|
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
|
|
break;
|
|
case REG_DMA3CNT_LO:
|
|
GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
|
|
break;
|
|
case REG_DMA3CNT_HI:
|
|
value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
|
|
break;
|
|
|
|
case REG_WAITCNT:
|
|
GBAAdjustWaitstates(&gba->memory, value);
|
|
break;
|
|
case REG_IE:
|
|
GBAWriteIE(gba, value);
|
|
break;
|
|
case REG_IF:
|
|
value = gba->memory.io[REG_IF >> 1] & ~value;
|
|
break;
|
|
case REG_IME:
|
|
GBAWriteIME(gba, value);
|
|
break;
|
|
case REG_HALTCNT:
|
|
value &= 0x80;
|
|
if (!value) {
|
|
GBAHalt(gba);
|
|
} else {
|
|
GBALog(GBA_LOG_STUB, "Stop unimplemented");
|
|
}
|
|
return;
|
|
default:
|
|
GBALog(GBA_LOG_STUB, "Stub I/O register write: %03x", address);
|
|
break;
|
|
}
|
|
gba->memory.io[address >> 1] = value;
|
|
}
|
|
|
|
void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
|
|
switch (address) {
|
|
case REG_DMA0SAD_LO:
|
|
GBAMemoryWriteDMASAD(&gba->memory, 0, value);
|
|
break;
|
|
case REG_DMA0DAD_LO:
|
|
GBAMemoryWriteDMADAD(&gba->memory, 0, value);
|
|
break;
|
|
case REG_DMA1SAD_LO:
|
|
GBAMemoryWriteDMASAD(&gba->memory, 1, value);
|
|
break;
|
|
case REG_DMA1DAD_LO:
|
|
GBAMemoryWriteDMADAD(&gba->memory, 1, value);
|
|
break;
|
|
case REG_DMA2SAD_LO:
|
|
GBAMemoryWriteDMASAD(&gba->memory, 2, value);
|
|
break;
|
|
case REG_DMA2DAD_LO:
|
|
GBAMemoryWriteDMADAD(&gba->memory, 2, value);
|
|
break;
|
|
case REG_DMA3SAD_LO:
|
|
GBAMemoryWriteDMASAD(&gba->memory, 3, value);
|
|
break;
|
|
case REG_DMA3DAD_LO:
|
|
GBAMemoryWriteDMADAD(&gba->memory, 3, value);
|
|
break;
|
|
default:
|
|
GBAIOWrite(gba, address, value & 0xFFFF);
|
|
GBAIOWrite(gba, address | 2, value >> 16);
|
|
break;
|
|
}
|
|
}
|
|
|
|
uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
|
|
switch (address) {
|
|
case REG_DISPSTAT:
|
|
return GBAVideoReadDISPSTAT(&gba->video);
|
|
break;
|
|
case REG_DMA0CNT_LO:
|
|
case REG_DMA1CNT_LO:
|
|
case REG_DMA2CNT_LO:
|
|
case REG_DMA3CNT_LO:
|
|
// Write-only register
|
|
return 0;
|
|
case REG_VCOUNT:
|
|
case REG_DMA0CNT_HI:
|
|
case REG_DMA1CNT_HI:
|
|
case REG_DMA2CNT_HI:
|
|
case REG_DMA3CNT_HI:
|
|
case REG_IE:
|
|
case REG_IF:
|
|
case REG_WAITCNT:
|
|
case REG_IME:
|
|
// Handled transparently by registers
|
|
break;
|
|
default:
|
|
GBALog(GBA_LOG_STUB, "Stub I/O register read: %03x", address);
|
|
break;
|
|
}
|
|
return gba->memory.io[address >> 1];
|
|
}
|