all repos — mgba @ 6c1476403ef5b90bedef9840d7ef08244eaac37b

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