all repos — mgba @ c0eb7c81f70d94b21b931b6a1ed44e7b9c9f5dd3

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