all repos — mgba @ 2eb5a7a6390e053ca6a0b3356400724c04d5533c

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-video.h"
  5
  6static const int _isValidRegister[REG_MAX >> 1] = {
  7	// Video
  8	1, 0, 1, 1, 1, 1, 1, 1,
  9	1, 1, 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, 0,
 13	1, 1, 1, 0, 0, 0, 0, 0,
 14	// Audio
 15	1, 1, 1, 0, 1, 0, 1, 0,
 16	1, 1, 1, 0, 1, 0, 1, 0,
 17	1, 1, 1, 0, 1, 0, 0, 0,
 18	1, 1, 1, 1, 1, 1, 1, 1,
 19	1, 1, 1, 1, 1, 0, 0, 0,
 20	// DMA
 21	1, 1, 1, 1, 1, 1, 1, 1,
 22	1, 1, 1, 1, 1, 1, 1, 1,
 23	1, 1, 1, 1, 1, 1, 1, 1,
 24	0, 0, 0, 0, 0, 0, 0, 0,
 25	0, 0, 0, 0, 0, 0, 0, 0,
 26	// Timers
 27	1, 1, 1, 1, 1, 1, 1, 1,
 28	0, 0, 0, 0, 0, 0, 0, 0,
 29	// SIO
 30	1, 1, 1, 1, 1, 0, 0, 0,
 31	1, 1, 1, 0, 0, 0, 0, 0,
 32	1, 0, 0, 0, 0, 0, 0, 0,
 33	1, 0, 1, 0, 1, 0, 0, 0,
 34	0, 0, 0, 0, 0, 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	// Interrupts
 45	1, 1, 1, 0, 1
 46};
 47
 48static const int _isSpecialRegister[REG_MAX >> 1] = {
 49	// Video
 50	0, 0, 0, 1, 0, 0, 0, 0,
 51	0, 0, 0, 0, 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	// Audio
 57	0, 0, 0, 0, 0, 0, 0, 0,
 58	0, 0, 0, 0, 0, 0, 0, 0,
 59	0, 0, 0, 0, 0, 0, 0, 0,
 60	1, 1, 1, 1, 1, 1, 1, 1,
 61	1, 1, 1, 1, 0, 0, 0, 0,
 62	// DMA
 63	1, 1, 1, 1, 1, 1, 1, 1,
 64	1, 1, 1, 1, 1, 1, 1, 1,
 65	1, 1, 1, 1, 1, 1, 1, 1,
 66	0, 0, 0, 0, 0, 0, 0, 0,
 67	0, 0, 0, 0, 0, 0, 0, 0,
 68	// Timers
 69	1, 1, 1, 1, 1, 1, 1, 1,
 70	0, 0, 0, 0, 0, 0, 0, 0,
 71	// SIO
 72	1, 1, 1, 1, 1, 0, 0, 0,
 73	1, 1, 1, 0, 0, 0, 0, 0,
 74	1, 0, 0, 0, 0, 0, 0, 0,
 75	1, 0, 1, 0, 1, 0, 0, 0,
 76	0, 0, 0, 0, 0, 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	// Interrupts
 87	1, 1, 1, 0, 1
 88};
 89
 90void GBAIOInit(struct GBA* gba) {
 91	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
 92	gba->memory.io[REG_RCNT >> 1] = 0x8000;
 93	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
 94	gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
 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		case REG_SOUNDBIAS:
157			GBAAudioWriteSOUNDBIAS(&gba->audio, value);
158			break;
159
160		case REG_WAVE_RAM0_LO:
161		case REG_WAVE_RAM1_LO:
162		case REG_WAVE_RAM2_LO:
163		case REG_WAVE_RAM3_LO:
164		case REG_FIFO_A_LO:
165		case REG_FIFO_B_LO:
166			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
167			break;
168
169		case REG_WAVE_RAM0_HI:
170		case REG_WAVE_RAM1_HI:
171		case REG_WAVE_RAM2_HI:
172		case REG_WAVE_RAM3_HI:
173		case REG_FIFO_A_HI:
174		case REG_FIFO_B_HI:
175			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
176			break;
177
178		// DMA
179		case REG_DMA0SAD_LO:
180		case REG_DMA0DAD_LO:
181		case REG_DMA1SAD_LO:
182		case REG_DMA1DAD_LO:
183		case REG_DMA2SAD_LO:
184		case REG_DMA2DAD_LO:
185		case REG_DMA3SAD_LO:
186		case REG_DMA3DAD_LO:
187			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
188			break;
189
190		case REG_DMA0SAD_HI:
191		case REG_DMA0DAD_HI:
192		case REG_DMA1SAD_HI:
193		case REG_DMA1DAD_HI:
194		case REG_DMA2SAD_HI:
195		case REG_DMA2DAD_HI:
196		case REG_DMA3SAD_HI:
197		case REG_DMA3DAD_HI:
198			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
199			break;
200
201		case REG_DMA0CNT_LO:
202			GBAMemoryWriteDMACNT_LO(&gba->memory, 0, value);
203			break;
204		case REG_DMA0CNT_HI:
205			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 0, value);
206			break;
207		case REG_DMA1CNT_LO:
208			GBAMemoryWriteDMACNT_LO(&gba->memory, 1, value);
209			break;
210		case REG_DMA1CNT_HI:
211			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 1, value);
212			break;
213		case REG_DMA2CNT_LO:
214			GBAMemoryWriteDMACNT_LO(&gba->memory, 2, value);
215			break;
216		case REG_DMA2CNT_HI:
217			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 2, value);
218			break;
219		case REG_DMA3CNT_LO:
220			GBAMemoryWriteDMACNT_LO(&gba->memory, 3, value);
221			break;
222		case REG_DMA3CNT_HI:
223			value = GBAMemoryWriteDMACNT_HI(&gba->memory, 3, value);
224			break;
225
226		// Timers
227		case REG_TM0CNT_LO:
228			GBATimerWriteTMCNT_LO(gba, 0, value);
229			return;
230		case REG_TM1CNT_LO:
231			GBATimerWriteTMCNT_LO(gba, 1, value);
232			return;
233		case REG_TM2CNT_LO:
234			GBATimerWriteTMCNT_LO(gba, 2, value);
235			return;
236		case REG_TM3CNT_LO:
237			GBATimerWriteTMCNT_LO(gba, 3, value);
238			return;
239
240		case REG_TM0CNT_HI:
241			value &= 0x00C7;
242			GBATimerWriteTMCNT_HI(gba, 0, value);
243			break;
244		case REG_TM1CNT_HI:
245			value &= 0x00C7;
246			GBATimerWriteTMCNT_HI(gba, 1, value);
247			break;
248		case REG_TM2CNT_HI:
249			value &= 0x00C7;
250			GBATimerWriteTMCNT_HI(gba, 2, value);
251			break;
252		case REG_TM3CNT_HI:
253			value &= 0x00C7;
254			GBATimerWriteTMCNT_HI(gba, 3, value);
255			break;
256
257		// Interrupts and misc
258		case REG_WAITCNT:
259			GBAAdjustWaitstates(&gba->memory, value);
260			break;
261		case REG_IE:
262			GBAWriteIE(gba, value);
263			break;
264		case REG_IF:
265			value = gba->memory.io[REG_IF >> 1] & ~value;
266			break;
267		case REG_IME:
268			GBAWriteIME(gba, value);
269			break;
270		case REG_MAX:
271			// Some bad interrupt libraries will write to this
272			break;
273		default:
274			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
275			break;
276		}
277	}
278	gba->memory.io[address >> 1] = value;
279}
280
281void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
282	if (address == REG_HALTCNT) {
283		value &= 0x80;
284		if (!value) {
285			GBAHalt(gba);
286		} else {
287			GBALog(gba, GBA_LOG_STUB, "Stop unimplemented");
288		}
289		return;
290	}
291	uint16_t value16 = value << (8 * (address & 1));
292	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
293	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
294}
295
296void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
297	switch (address) {
298	case REG_WAVE_RAM0_LO:
299		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
300		break;
301	case REG_WAVE_RAM1_LO:
302		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
303		break;
304	case REG_WAVE_RAM2_LO:
305		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
306		break;
307	case REG_WAVE_RAM3_LO:
308		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
309		break;
310	case REG_FIFO_A_LO:
311	case REG_FIFO_B_LO:
312		GBAAudioWriteFIFO(&gba->audio, address, value);
313		break;
314	case REG_DMA0SAD_LO:
315		GBAMemoryWriteDMASAD(&gba->memory, 0, value);
316		break;
317	case REG_DMA0DAD_LO:
318		GBAMemoryWriteDMADAD(&gba->memory, 0, value);
319		break;
320	case REG_DMA1SAD_LO:
321		GBAMemoryWriteDMASAD(&gba->memory, 1, value);
322		break;
323	case REG_DMA1DAD_LO:
324		GBAMemoryWriteDMADAD(&gba->memory, 1, value);
325		break;
326	case REG_DMA2SAD_LO:
327		GBAMemoryWriteDMASAD(&gba->memory, 2, value);
328		break;
329	case REG_DMA2DAD_LO:
330		GBAMemoryWriteDMADAD(&gba->memory, 2, value);
331		break;
332	case REG_DMA3SAD_LO:
333		GBAMemoryWriteDMASAD(&gba->memory, 3, value);
334		break;
335	case REG_DMA3DAD_LO:
336		GBAMemoryWriteDMADAD(&gba->memory, 3, value);
337		break;
338	default:
339		GBAIOWrite(gba, address, value & 0xFFFF);
340		GBAIOWrite(gba, address | 2, value >> 16);
341		return;
342	}
343	gba->memory.io[address >> 1] = value;
344	gba->memory.io[(address >> 1) + 1] = value >> 16;
345}
346
347uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
348	switch (address) {
349	case REG_DISPSTAT:
350		return gba->memory.io[REG_DISPSTAT >> 1] | GBAVideoReadDISPSTAT(&gba->video);
351		break;
352
353	case REG_TM0CNT_LO:
354		GBATimerUpdateRegister(gba, 0);
355		break;
356	case REG_TM1CNT_LO:
357		GBATimerUpdateRegister(gba, 1);
358		break;
359	case REG_TM2CNT_LO:
360		GBATimerUpdateRegister(gba, 2);
361		break;
362	case REG_TM3CNT_LO:
363		GBATimerUpdateRegister(gba, 3);
364		break;
365
366	case REG_KEYINPUT:
367		if (gba->keySource) {
368			return 0x3FF ^ *gba->keySource;
369		}
370		break;
371
372	case REG_DMA0CNT_LO:
373	case REG_DMA1CNT_LO:
374	case REG_DMA2CNT_LO:
375	case REG_DMA3CNT_LO:
376		// Write-only register
377		return 0;
378	case REG_DISPCNT:
379	case REG_VCOUNT:
380	case REG_BG0CNT:
381	case REG_BG1CNT:
382	case REG_BG2CNT:
383	case REG_BG3CNT:
384	case REG_WININ:
385	case REG_WINOUT:
386	case REG_BLDCNT:
387	case REG_SOUND1CNT_LO:
388	case REG_SOUND1CNT_HI:
389	case REG_SOUND1CNT_X:
390	case REG_SOUND2CNT_LO:
391	case REG_SOUND2CNT_HI:
392	case REG_SOUND3CNT_LO:
393	case REG_SOUND3CNT_HI:
394	case REG_SOUND3CNT_X:
395	case REG_SOUND4CNT_LO:
396	case REG_SOUND4CNT_HI:
397	case REG_SOUNDCNT_LO:
398	case REG_SOUNDCNT_HI:
399	case REG_DMA0CNT_HI:
400	case REG_DMA1CNT_HI:
401	case REG_DMA2CNT_HI:
402	case REG_DMA3CNT_HI:
403	case REG_IE:
404	case REG_IF:
405	case REG_WAITCNT:
406	case REG_IME:
407		// Handled transparently by registers
408		break;
409	case REG_MAX:
410		// Some bad interrupt libraries will read from this
411		break;
412	default:
413		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
414		break;
415	}
416	return gba->memory.io[address >> 1];
417}
418
419void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
420	int i;
421	for (i = 0; i < REG_MAX; i += 2) {
422		if (_isSpecialRegister[i >> 1]) {
423			state->io[i >> 1] = gba->memory.io[i >> 1];
424		} else if (_isValidRegister[i >> 1]) {
425			state->io[i >> 1] = GBAIORead(gba, i);
426		}
427	}
428
429	for (i = 0; i < 4; ++i) {
430		state->dma[i].nextSource = gba->memory.dma[i].nextSource;
431		state->dma[i].nextDest = gba->memory.dma[i].nextDest;
432		state->dma[i].nextCount = gba->memory.dma[i].nextCount;
433		state->dma[i].nextEvent = gba->memory.dma[i].nextEvent;
434	}
435
436	memcpy(state->timers, gba->timers, sizeof(state->timers));
437}
438
439void GBAIODeserialize(struct GBA* gba, struct GBASerializedState* state) {
440	int i;
441	for (i = 0; i < REG_MAX; i += 2) {
442		if (_isSpecialRegister[i >> 1]) {
443			gba->memory.io[i >> 1] = state->io[i >> 1];
444		} else if (_isValidRegister[i >> 1]) {
445			GBAIOWrite(gba, i, state->io[i >> 1]);
446		}
447	}
448
449	for (i = 0; i < 4; ++i) {
450		gba->memory.dma[i].nextSource = state->dma[i].nextSource;
451		gba->memory.dma[i].nextDest = state->dma[i].nextDest;
452		gba->memory.dma[i].nextCount = state->dma[i].nextCount;
453		gba->memory.dma[i].nextEvent = state->dma[i].nextEvent;
454	}
455
456	memcpy(state->timers, gba->timers, sizeof(gba->timers));
457}