all repos — mgba @ 3edb2da58dbb4a4f08be5657b40384d87a2f7018

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_RCNT >> 1] = 0x8000;
  8	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
  9}
 10
 11void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
 12	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
 13		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
 14	} else {
 15		switch (address) {
 16		// Video
 17		case REG_DISPSTAT:
 18			GBAVideoWriteDISPSTAT(&gba->video, value);
 19			break;
 20
 21		// Audio
 22		case REG_SOUND1CNT_LO:
 23			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
 24			break;
 25		case REG_SOUND1CNT_HI:
 26			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
 27			break;
 28		case REG_SOUND1CNT_X:
 29			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
 30			break;
 31		case REG_SOUND2CNT_LO:
 32			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
 33			break;
 34		case REG_SOUND2CNT_HI:
 35			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
 36			break;
 37		case REG_SOUND3CNT_LO:
 38			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
 39			break;
 40		case REG_SOUND3CNT_HI:
 41			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
 42			break;
 43		case REG_SOUND3CNT_X:
 44			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
 45			break;
 46		case REG_SOUND4CNT_LO:
 47			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
 48			break;
 49		case REG_SOUND4CNT_HI:
 50			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
 51			break;
 52		case REG_SOUNDCNT_LO:
 53			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
 54			break;
 55		case REG_SOUNDCNT_HI:
 56			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
 57			break;
 58		case REG_SOUNDCNT_X:
 59			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
 60			break;
 61
 62		case REG_WAVE_RAM0_LO:
 63		case REG_WAVE_RAM1_LO:
 64		case REG_WAVE_RAM2_LO:
 65		case REG_WAVE_RAM3_LO:
 66		case REG_FIFO_A_LO:
 67		case REG_FIFO_B_LO:
 68			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 69			break;
 70
 71		case REG_WAVE_RAM0_HI:
 72		case REG_WAVE_RAM1_HI:
 73		case REG_WAVE_RAM2_HI:
 74		case REG_WAVE_RAM3_HI:
 75		case REG_FIFO_A_HI:
 76		case REG_FIFO_B_HI:
 77			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
 78			break;
 79
 80		// DMA
 81		case REG_DMA0SAD_LO:
 82		case REG_DMA0DAD_LO:
 83		case REG_DMA1SAD_LO:
 84		case REG_DMA1DAD_LO:
 85		case REG_DMA2SAD_LO:
 86		case REG_DMA2DAD_LO:
 87		case REG_DMA3SAD_LO:
 88		case REG_DMA3DAD_LO:
 89			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
 90			break;
 91
 92		case REG_DMA0SAD_HI:
 93		case REG_DMA0DAD_HI:
 94		case REG_DMA1SAD_HI:
 95		case REG_DMA1DAD_HI:
 96		case REG_DMA2SAD_HI:
 97		case REG_DMA2DAD_HI:
 98		case REG_DMA3SAD_HI:
 99		case REG_DMA3DAD_HI:
100			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
101			break;
102
103		case REG_DMA0CNT_LO:
104			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
105			break;
106		case REG_DMA0CNT_HI:
107			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
108			break;
109		case REG_DMA1CNT_LO:
110			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
111			break;
112		case REG_DMA1CNT_HI:
113			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
114			break;
115		case REG_DMA2CNT_LO:
116			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
117			break;
118		case REG_DMA2CNT_HI:
119			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
120			break;
121		case REG_DMA3CNT_LO:
122			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
123			break;
124		case REG_DMA3CNT_HI:
125			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
126			break;
127
128		// Timers
129		case REG_TM0CNT_LO:
130			GBATimerWriteTMCNT_LO(gba, 0, value);
131			return;
132		case REG_TM1CNT_LO:
133			GBATimerWriteTMCNT_LO(gba, 1, value);
134			return;
135		case REG_TM2CNT_LO:
136			GBATimerWriteTMCNT_LO(gba, 2, value);
137			return;
138		case REG_TM3CNT_LO:
139			GBATimerWriteTMCNT_LO(gba, 3, value);
140			return;
141
142		case REG_TM0CNT_HI:
143			value &= 0x00C7;
144			GBATimerWriteTMCNT_HI(gba, 0, value);
145			break;
146		case REG_TM1CNT_HI:
147			value &= 0x00C7;
148			GBATimerWriteTMCNT_HI(gba, 1, value);
149			break;
150		case REG_TM2CNT_HI:
151			value &= 0x00C7;
152			GBATimerWriteTMCNT_HI(gba, 2, value);
153			break;
154		case REG_TM3CNT_HI:
155			value &= 0x00C7;
156			GBATimerWriteTMCNT_HI(gba, 3, value);
157			break;
158
159		// Interrupts and misc
160		case REG_WAITCNT:
161			GBAAdjustWaitstates(&gba->memory, value);
162			break;
163		case REG_IE:
164			GBAWriteIE(gba, value);
165			break;
166		case REG_IF:
167			value = gba->memory.io[REG_IF >> 1] & ~value;
168			break;
169		case REG_IME:
170			GBAWriteIME(gba, value);
171			break;
172		case 0x20A:
173			// Some bad interrupt libraries will write to this
174			break;
175		default:
176			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
177			break;
178		}
179	}
180	gba->memory.io[address >> 1] = value;
181}
182
183void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
184	if (address == REG_HALTCNT) {
185		value &= 0x80;
186		if (!value) {
187			GBAHalt(gba);
188		} else {
189			GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
190		}
191		return;
192	}
193	uint16_t value16 = value << (8 * (address & 1));
194	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
195	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
196}
197
198void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
199	switch (address) {
200	case REG_WAVE_RAM0_LO:
201		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
202		break;
203	case REG_WAVE_RAM1_LO:
204		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
205		break;
206	case REG_WAVE_RAM2_LO:
207		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
208		break;
209	case REG_WAVE_RAM3_LO:
210		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
211		break;
212	case REG_FIFO_A_LO:
213	case REG_FIFO_B_LO:
214		GBAAudioWriteFIFO(&gba->audio, address, value);
215		break;
216	case REG_DMA0SAD_LO:
217		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
218		break;
219	case REG_DMA0DAD_LO:
220		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
221		break;
222	case REG_DMA1SAD_LO:
223		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
224		break;
225	case REG_DMA1DAD_LO:
226		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
227		break;
228	case REG_DMA2SAD_LO:
229		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
230		break;
231	case REG_DMA2DAD_LO:
232		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
233		break;
234	case REG_DMA3SAD_LO:
235		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
236		break;
237	case REG_DMA3DAD_LO:
238		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
239		break;
240	default:
241		GBAIOWrite(gba, address, value & 0xFFFF);
242		GBAIOWrite(gba, address | 2, value >> 16);
243		return;
244	}
245	gba->memory.io[address >> 1] = value;
246	gba->memory.io[(address >> 1) + 1] = value >> 16;
247}
248
249uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
250	switch (address) {
251	case REG_DISPSTAT:
252		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
253		break;
254
255	case REG_TM0CNT_LO:
256		GBATimerUpdateRegister(gba, 0);
257		break;
258	case REG_TM1CNT_LO:
259		GBATimerUpdateRegister(gba, 1);
260		break;
261	case REG_TM2CNT_LO:
262		GBATimerUpdateRegister(gba, 2);
263		break;
264	case REG_TM3CNT_LO:
265		GBATimerUpdateRegister(gba, 3);
266		break;
267
268	case REG_KEYINPUT:
269		if (gba->keySource) {
270			return 0x3FF ^ *gba->keySource;
271		}
272		break;
273
274	case REG_DMA0CNT_LO:
275	case REG_DMA1CNT_LO:
276	case REG_DMA2CNT_LO:
277	case REG_DMA3CNT_LO:
278		// Write-only register
279		return 0;
280	case REG_DISPCNT:
281	case REG_VCOUNT:
282	case REG_BG0CNT:
283	case REG_BG1CNT:
284	case REG_BG2CNT:
285	case REG_BG3CNT:
286	case REG_DMA0CNT_HI:
287	case REG_DMA1CNT_HI:
288	case REG_DMA2CNT_HI:
289	case REG_DMA3CNT_HI:
290	case REG_IE:
291	case REG_IF:
292	case REG_WAITCNT:
293	case REG_IME:
294		// Handled transparently by registers
295		break;
296	case 0x20A:
297		// Some bad interrupt libraries will read from this
298		break;
299	default:
300		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
301		break;
302	}
303	return gba->memory.io[address >> 1];
304}