all repos — mgba @ 683e90fa06abf5168d65c049e51216cf325ef3fc

mGBA Game Boy Advance Emulator

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

  1#include "gba-io.h"
  2
  3#include "gba-serialize.h"
  4#include "gba-sio.h"
  5#include "gba-video.h"
  6
  7static const int _isValidRegister[REG_MAX >> 1] = {
  8	// Video
  9	1, 0, 1, 1, 1, 1, 1, 1,
 10	1, 1, 1, 1, 1, 1, 1, 1,
 11	1, 1, 1, 1, 1, 1, 1, 1,
 12	1, 1, 1, 1, 1, 1, 1, 1,
 13	1, 1, 1, 1, 1, 1, 1, 0,
 14	1, 1, 1, 0, 0, 0, 0, 0,
 15	// Audio
 16	1, 1, 1, 0, 1, 0, 1, 0,
 17	1, 1, 1, 0, 1, 0, 1, 0,
 18	1, 1, 1, 0, 1, 0, 0, 0,
 19	1, 1, 1, 1, 1, 1, 1, 1,
 20	1, 1, 1, 1, 0, 0, 0, 0,
 21	// DMA
 22	1, 1, 1, 1, 1, 1, 1, 1,
 23	1, 1, 1, 1, 1, 1, 1, 1,
 24	1, 1, 1, 1, 1, 1, 1, 1,
 25	0, 0, 0, 0, 0, 0, 0, 0,
 26	0, 0, 0, 0, 0, 0, 0, 0,
 27	// Timers
 28	1, 1, 1, 1, 1, 1, 1, 1,
 29	0, 0, 0, 0, 0, 0, 0, 0,
 30	// SIO
 31	1, 1, 1, 1, 1, 0, 0, 0,
 32	1, 1, 1, 0, 0, 0, 0, 0,
 33	1, 0, 0, 0, 0, 0, 0, 0,
 34	1, 0, 1, 0, 1, 0, 0, 0,
 35	0, 0, 0, 0, 0, 0, 0, 0,
 36	0, 0, 0, 0, 0, 0, 0, 0,
 37	0, 0, 0, 0, 0, 0, 0, 0,
 38	0, 0, 0, 0, 0, 0, 0, 0,
 39	0, 0, 0, 0, 0, 0, 0, 0,
 40	0, 0, 0, 0, 0, 0, 0, 0,
 41	0, 0, 0, 0, 0, 0, 0, 0,
 42	0, 0, 0, 0, 0, 0, 0, 0,
 43	0, 0, 0, 0, 0, 0, 0, 0,
 44	0, 0, 0, 0, 0, 0, 0, 0,
 45	// Interrupts
 46	1, 1, 1, 0, 1
 47};
 48
 49static const int _isSpecialRegister[REG_MAX >> 1] = {
 50	// Video
 51	0, 0, 0, 1, 0, 0, 0, 0,
 52	0, 0, 0, 0, 0, 0, 0, 0,
 53	0, 0, 0, 0, 0, 0, 0, 0,
 54	0, 0, 0, 0, 0, 0, 0, 0,
 55	0, 0, 0, 0, 0, 0, 0, 0,
 56	0, 0, 0, 0, 0, 0, 0, 0,
 57	// Audio
 58	0, 0, 0, 0, 0, 0, 0, 0,
 59	0, 0, 0, 0, 0, 0, 0, 0,
 60	0, 0, 0, 0, 0, 0, 0, 0,
 61	1, 1, 1, 1, 1, 1, 1, 1,
 62	1, 1, 1, 1, 0, 0, 0, 0,
 63	// DMA
 64	1, 1, 1, 1, 1, 1, 1, 1,
 65	1, 1, 1, 1, 1, 1, 1, 1,
 66	1, 1, 1, 1, 1, 1, 1, 1,
 67	0, 0, 0, 0, 0, 0, 0, 0,
 68	0, 0, 0, 0, 0, 0, 0, 0,
 69	// Timers
 70	1, 1, 1, 1, 1, 1, 1, 1,
 71	0, 0, 0, 0, 0, 0, 0, 0,
 72	// SIO
 73	1, 1, 1, 1, 1, 0, 0, 0,
 74	1, 1, 1, 0, 0, 0, 0, 0,
 75	1, 0, 0, 0, 0, 0, 0, 0,
 76	1, 0, 1, 0, 1, 0, 0, 0,
 77	0, 0, 0, 0, 0, 0, 0, 0,
 78	0, 0, 0, 0, 0, 0, 0, 0,
 79	0, 0, 0, 0, 0, 0, 0, 0,
 80	0, 0, 0, 0, 0, 0, 0, 0,
 81	0, 0, 0, 0, 0, 0, 0, 0,
 82	0, 0, 0, 0, 0, 0, 0, 0,
 83	0, 0, 0, 0, 0, 0, 0, 0,
 84	0, 0, 0, 0, 0, 0, 0, 0,
 85	0, 0, 0, 0, 0, 0, 0, 0,
 86	0, 0, 0, 0, 0, 0, 0, 0,
 87	// Interrupts
 88	1, 1, 1, 0, 1
 89};
 90
 91void GBAIOInit(struct GBA* gba) {
 92	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
 93	gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
 94	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
 95}
 96
 97void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
 98	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
 99		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
100	} else {
101		switch (address) {
102		// Video
103		case REG_DISPSTAT:
104			value &= 0xFFF8;
105			GBAVideoWriteDISPSTAT(&gba->video, value);
106			break;
107
108		// Audio
109		case REG_SOUND1CNT_LO:
110			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
111			value &= 0x00FF;
112			break;
113		case REG_SOUND1CNT_HI:
114			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
115			break;
116		case REG_SOUND1CNT_X:
117			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
118			value &= 0x47FF;
119			break;
120		case REG_SOUND2CNT_LO:
121			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
122			break;
123		case REG_SOUND2CNT_HI:
124			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
125			value &= 0x47FF;
126			break;
127		case REG_SOUND3CNT_LO:
128			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
129			value &= 0x00E0;
130			break;
131		case REG_SOUND3CNT_HI:
132			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
133			value &= 0xE000;
134			break;
135		case REG_SOUND3CNT_X:
136			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
137			value &= 0x4000;
138			break;
139		case REG_SOUND4CNT_LO:
140			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
141			value &= 0xFF00;
142			break;
143		case REG_SOUND4CNT_HI:
144			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
145			value &= 0x40FF;
146			break;
147		case REG_SOUNDCNT_LO:
148			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
149			break;
150		case REG_SOUNDCNT_HI:
151			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
152			break;
153		case REG_SOUNDCNT_X:
154			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
155			break;
156
157		case REG_WAVE_RAM0_LO:
158		case REG_WAVE_RAM1_LO:
159		case REG_WAVE_RAM2_LO:
160		case REG_WAVE_RAM3_LO:
161		case REG_FIFO_A_LO:
162		case REG_FIFO_B_LO:
163			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
164			break;
165
166		case REG_WAVE_RAM0_HI:
167		case REG_WAVE_RAM1_HI:
168		case REG_WAVE_RAM2_HI:
169		case REG_WAVE_RAM3_HI:
170		case REG_FIFO_A_HI:
171		case REG_FIFO_B_HI:
172			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
173			break;
174
175		// DMA
176		case REG_DMA0SAD_LO:
177		case REG_DMA0DAD_LO:
178		case REG_DMA1SAD_LO:
179		case REG_DMA1DAD_LO:
180		case REG_DMA2SAD_LO:
181		case REG_DMA2DAD_LO:
182		case REG_DMA3SAD_LO:
183		case REG_DMA3DAD_LO:
184			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
185			break;
186
187		case REG_DMA0SAD_HI:
188		case REG_DMA0DAD_HI:
189		case REG_DMA1SAD_HI:
190		case REG_DMA1DAD_HI:
191		case REG_DMA2SAD_HI:
192		case REG_DMA2DAD_HI:
193		case REG_DMA3SAD_HI:
194		case REG_DMA3DAD_HI:
195			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
196			break;
197
198		case REG_DMA0CNT_LO:
199			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
200			break;
201		case REG_DMA0CNT_HI:
202			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
203			break;
204		case REG_DMA1CNT_LO:
205			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
206			break;
207		case REG_DMA1CNT_HI:
208			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
209			break;
210		case REG_DMA2CNT_LO:
211			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
212			break;
213		case REG_DMA2CNT_HI:
214			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
215			break;
216		case REG_DMA3CNT_LO:
217			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
218			break;
219		case REG_DMA3CNT_HI:
220			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
221			break;
222
223		// Timers
224		case REG_TM0CNT_LO:
225			GBATimerWriteTMCNT_LO(gba, 0, value);
226			return;
227		case REG_TM1CNT_LO:
228			GBATimerWriteTMCNT_LO(gba, 1, value);
229			return;
230		case REG_TM2CNT_LO:
231			GBATimerWriteTMCNT_LO(gba, 2, value);
232			return;
233		case REG_TM3CNT_LO:
234			GBATimerWriteTMCNT_LO(gba, 3, value);
235			return;
236
237		case REG_TM0CNT_HI:
238			value &= 0x00C7;
239			GBATimerWriteTMCNT_HI(gba, 0, value);
240			break;
241		case REG_TM1CNT_HI:
242			value &= 0x00C7;
243			GBATimerWriteTMCNT_HI(gba, 1, value);
244			break;
245		case REG_TM2CNT_HI:
246			value &= 0x00C7;
247			GBATimerWriteTMCNT_HI(gba, 2, value);
248			break;
249		case REG_TM3CNT_HI:
250			value &= 0x00C7;
251			GBATimerWriteTMCNT_HI(gba, 3, value);
252			break;
253
254		// SIO
255		case REG_SIOCNT:
256			GBASIOWriteSIOCNT(&gba->sio, value);
257			break;
258		case REG_RCNT:
259			value &= 0xC1FF;
260			GBASIOWriteRCNT(&gba->sio, value);
261			break;
262		case REG_SIOMLT_SEND:
263			GBASIOWriteSIOMLT_SEND(&gba->sio, value);
264			break;
265
266		// Interrupts and misc
267		case REG_WAITCNT:
268			GBAAdjustWaitstates(&gba->memory, value);
269			break;
270		case REG_IE:
271			GBAWriteIE(gba, value);
272			break;
273		case REG_IF:
274			value = gba->memory.io[REG_IF >> 1] & ~value;
275			break;
276		case REG_IME:
277			GBAWriteIME(gba, value);
278			break;
279		case REG_MAX:
280			// Some bad interrupt libraries will write to this
281			break;
282		default:
283			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
284			break;
285		}
286	}
287	gba->memory.io[address >> 1] = value;
288}
289
290void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
291	if (address == REG_HALTCNT) {
292		value &= 0x80;
293		if (!value) {
294			GBAHalt(gba);
295		} else {
296			GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
297		}
298		return;
299	}
300	uint16_t value16 = value << (8 * (address & 1));
301	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
302	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
303}
304
305void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
306	switch (address) {
307	case REG_WAVE_RAM0_LO:
308		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
309		break;
310	case REG_WAVE_RAM1_LO:
311		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
312		break;
313	case REG_WAVE_RAM2_LO:
314		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
315		break;
316	case REG_WAVE_RAM3_LO:
317		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
318		break;
319	case REG_FIFO_A_LO:
320	case REG_FIFO_B_LO:
321		GBAAudioWriteFIFO(&gba->audio, address, value);
322		break;
323	case REG_DMA0SAD_LO:
324		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
325		break;
326	case REG_DMA0DAD_LO:
327		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
328		break;
329	case REG_DMA1SAD_LO:
330		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
331		break;
332	case REG_DMA1DAD_LO:
333		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
334		break;
335	case REG_DMA2SAD_LO:
336		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
337		break;
338	case REG_DMA2DAD_LO:
339		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
340		break;
341	case REG_DMA3SAD_LO:
342		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
343		break;
344	case REG_DMA3DAD_LO:
345		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
346		break;
347	default:
348		GBAIOWrite(gba, address, value & 0xFFFF);
349		GBAIOWrite(gba, address | 2, value >> 16);
350		return;
351	}
352	gba->memory.io[address >> 1] = value;
353	gba->memory.io[(address >> 1) + 1] = value >> 16;
354}
355
356uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
357	switch (address) {
358	case REG_TM0CNT_LO:
359		GBATimerUpdateRegister(gba, 0);
360		break;
361	case REG_TM1CNT_LO:
362		GBATimerUpdateRegister(gba, 1);
363		break;
364	case REG_TM2CNT_LO:
365		GBATimerUpdateRegister(gba, 2);
366		break;
367	case REG_TM3CNT_LO:
368		GBATimerUpdateRegister(gba, 3);
369		break;
370
371	case REG_KEYINPUT:
372		if (gba->keySource) {
373			return 0x3FF ^ *gba->keySource;
374		}
375		break;
376
377	case REG_SIOCNT:
378		return gba->sio.siocnt;
379	case REG_RCNT:
380		return gba->sio.rcnt;
381
382	case REG_DMA0CNT_LO:
383	case REG_DMA1CNT_LO:
384	case REG_DMA2CNT_LO:
385	case REG_DMA3CNT_LO:
386		// Write-only register
387		return 0;
388	case REG_DISPCNT:
389	case REG_DISPSTAT:
390	case REG_VCOUNT:
391	case REG_BG0CNT:
392	case REG_BG1CNT:
393	case REG_BG2CNT:
394	case REG_BG3CNT:
395	case REG_WININ:
396	case REG_WINOUT:
397	case REG_BLDCNT:
398	case REG_SOUND1CNT_LO:
399	case REG_SOUND1CNT_HI:
400	case REG_SOUND1CNT_X:
401	case REG_SOUND2CNT_LO:
402	case REG_SOUND2CNT_HI:
403	case REG_SOUND3CNT_LO:
404	case REG_SOUND3CNT_HI:
405	case REG_SOUND3CNT_X:
406	case REG_SOUND4CNT_LO:
407	case REG_SOUND4CNT_HI:
408	case REG_SOUNDCNT_LO:
409	case REG_SOUNDCNT_HI:
410	case REG_DMA0CNT_HI:
411	case REG_DMA1CNT_HI:
412	case REG_DMA2CNT_HI:
413	case REG_DMA3CNT_HI:
414	case REG_SIOMULTI0:
415	case REG_SIOMULTI1:
416	case REG_SIOMULTI2:
417	case REG_SIOMULTI3:
418	case REG_SIOMLT_SEND:
419	case REG_IE:
420	case REG_IF:
421	case REG_WAITCNT:
422	case REG_IME:
423		// Handled transparently by registers
424		break;
425	case REG_MAX:
426		// Some bad interrupt libraries will read from this
427		break;
428	default:
429		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
430		break;
431	}
432	return gba->memory.io[address >> 1];
433}
434
435void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
436	int i;
437	for (i = 0; i < REG_MAX; i += 2) {
438		if (_isSpecialRegister[i >> 1]) {
439			state->io[i >> 1] = gba->memory.io[i >> 1];
440		} else if (_isValidRegister[i >> 1]) {
441			state->io[i >> 1] = GBAIORead(gba, i);
442		}
443	}
444
445	for (i = 0; i < 4; ++i) {
446		state->dma[i].nextSource = gba->memory.dma[i].nextSource;
447		state->dma[i].nextDest = gba->memory.dma[i].nextDest;
448		state->dma[i].nextCount = gba->memory.dma[i].nextCount;
449		state->dma[i].nextEvent = gba->memory.dma[i].nextEvent;
450	}
451
452	memcpy(state->timers, gba->timers, sizeof(state->timers));
453}
454
455void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {
456	int i;
457	for (i = 0; i < REG_MAX; i += 2) {
458		if (_isSpecialRegister[i >> 1]) {
459			gba->memory.io[i >> 1] = state->io[i >> 1];
460		} else if (_isValidRegister[i >> 1]) {
461			GBAIOWrite(gba, i, state->io[i >> 1]);
462		}
463	}
464
465	for (i = 0; i < 4; ++i) {
466		gba->memory.dma[i].nextSource = state->dma[i].nextSource;
467		gba->memory.dma[i].nextDest = state->dma[i].nextDest;
468		gba->memory.dma[i].nextCount = state->dma[i].nextCount;
469		gba->memory.dma[i].nextEvent = state->dma[i].nextEvent;
470	}
471
472	memcpy(state->timers, gba->timers, sizeof(gba->timers));
473}