all repos — mgba @ 381fc94d7397a324207a4a48195a6a29b9e5825e

mGBA Game Boy Advance Emulator

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

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