all repos — mgba @ 3ec0afa8fc5785f45f0c7a24a24ac5a684ab769f

mGBA Game Boy Advance Emulator

src/gba/gba-io.c (view raw)

  1#include "gba-io.h"
  2
  3#include "gba-video.h"
  4
  5void GBAIOInit(struct GBA* gba) {
  6	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
  7	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
  8}
  9
 10void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
 11	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
 12		gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
 13	} else {
 14		switch (address) {
 15		// Video
 16		case REG_DISPSTAT:
 17			GBAVideoWriteDISPSTAT(&gba->video, value);
 18			break;
 19
 20		// DMA
 21		case REG_DMA0CNT_LO:
 22			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
 23			break;
 24		case REG_DMA0CNT_HI:
 25			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
 26			break;
 27		case REG_DMA1CNT_LO:
 28			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
 29			break;
 30		case REG_DMA1CNT_HI:
 31			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
 32			break;
 33		case REG_DMA2CNT_LO:
 34			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
 35			break;
 36		case REG_DMA2CNT_HI:
 37			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
 38			break;
 39		case REG_DMA3CNT_LO:
 40			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
 41			break;
 42		case REG_DMA3CNT_HI:
 43			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
 44			break;
 45
 46		// Timers
 47		case REG_TM0CNT_LO:
 48			GBATimerWriteTMCNT_LO(gba, 0, value);
 49			return;
 50		case REG_TM1CNT_LO:
 51			GBATimerWriteTMCNT_LO(gba, 1, value);
 52			return;
 53		case REG_TM2CNT_LO:
 54			GBATimerWriteTMCNT_LO(gba, 2, value);
 55			return;
 56		case REG_TM3CNT_LO:
 57			GBATimerWriteTMCNT_LO(gba, 3, value);
 58			return;
 59
 60		case REG_TM0CNT_HI:
 61			value &= 0x00C7;
 62			GBATimerWriteTMCNT_HI(gba, 0, value);
 63			break;
 64		case REG_TM1CNT_HI:
 65			value &= 0x00C7;
 66			GBATimerWriteTMCNT_HI(gba, 1, value);
 67			break;
 68		case REG_TM2CNT_HI:
 69			value &= 0x00C7;
 70			GBATimerWriteTMCNT_HI(gba, 2, value);
 71			break;
 72		case REG_TM3CNT_HI:
 73			value &= 0x00C7;
 74			GBATimerWriteTMCNT_HI(gba, 3, value);
 75			break;
 76
 77		// Interrupts and misc
 78		case REG_WAITCNT:
 79			GBAAdjustWaitstates(&gba->memory, value);
 80			break;
 81		case REG_IE:
 82			GBAWriteIE(gba, value);
 83			break;
 84		case REG_IF:
 85			value = gba->memory.io[REG_IF >> 1] & ~value;
 86			break;
 87		case REG_IME:
 88			GBAWriteIME(gba, value);
 89			break;
 90		case REG_HALTCNT:
 91			value &= 0x80;
 92			if (!value) {
 93				GBAHalt(gba);
 94			} else {
 95				GBALog(GBA_LOG_STUB, "Stop unimplemented");
 96			}
 97			return;
 98		default:
 99			GBALog(GBA_LOG_STUB, "Stub I/O register write: %03x", address);
100			break;
101		}
102	}
103	gba->memory.io[address >> 1] = value;
104}
105
106void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
107	switch (address) {
108	case REG_DMA0SAD_LO:
109		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
110		break;
111	case REG_DMA0DAD_LO:
112		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
113		break;
114	case REG_DMA1SAD_LO:
115		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
116		break;
117	case REG_DMA1DAD_LO:
118		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
119		break;
120	case REG_DMA2SAD_LO:
121		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
122		break;
123	case REG_DMA2DAD_LO:
124		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
125		break;
126	case REG_DMA3SAD_LO:
127		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
128		break;
129	case REG_DMA3DAD_LO:
130		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
131		break;
132	default:
133		GBAIOWrite(gba, address, value & 0xFFFF);
134		GBAIOWrite(gba, address | 2, value >> 16);
135		break;
136	}
137}
138
139uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
140	switch (address) {
141	case REG_DISPSTAT:
142		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
143		break;
144
145	case REG_TM0CNT_LO:
146		GBATimerUpdateRegister(gba, 0);
147		break;
148	case REG_TM1CNT_LO:
149		GBATimerUpdateRegister(gba, 1);
150		break;
151	case REG_TM2CNT_LO:
152		GBATimerUpdateRegister(gba, 2);
153		break;
154	case REG_TM3CNT_LO:
155		GBATimerUpdateRegister(gba, 3);
156		break;
157
158	case REG_KEYINPUT:
159		if (gba->keySource) {
160			return 0x3FF ^ *gba->keySource;
161		}
162		break;
163
164	case REG_DMA0CNT_LO:
165	case REG_DMA1CNT_LO:
166	case REG_DMA2CNT_LO:
167	case REG_DMA3CNT_LO:
168		// Write-only register
169		return 0;
170	case REG_VCOUNT:
171	case REG_DMA0CNT_HI:
172	case REG_DMA1CNT_HI:
173	case REG_DMA2CNT_HI:
174	case REG_DMA3CNT_HI:
175	case REG_IE:
176	case REG_IF:
177	case REG_WAITCNT:
178	case REG_IME:
179		// Handled transparently by registers
180		break;
181	default:
182		GBALog(GBA_LOG_STUB, "Stub I/O register read: %03x", address);
183		break;
184	}
185	return gba->memory.io[address >> 1];
186}