all repos — mgba @ 7735c08fd5075862c57e353063ad59e84d8b9d60

mGBA Game Boy Advance Emulator

src/gba/io.c (view raw)

  1/* Copyright (c) 2013-2015 Jeffrey Pfau
  2 *
  3 * This Source Code Form is subject to the terms of the Mozilla Public
  4 * License, v. 2.0. If a copy of the MPL was not distributed with this
  5 * file, You can obtain one at http://mozilla.org/MPL/2.0/. */
  6#include "io.h"
  7
  8#include "gba/rr/rr.h"
  9#include "gba/serialize.h"
 10#include "gba/sio.h"
 11#include "gba/video.h"
 12
 13const char* GBAIORegisterNames[] = {
 14	// Video
 15	"DISPCNT",
 16	0,
 17	"DISPSTAT",
 18	"VCOUNT",
 19	"BG0CNT",
 20	"BG1CNT",
 21	"BG2CNT",
 22	"BG3CNT",
 23	"BG0HOFS",
 24	"BG0VOFS",
 25	"BG1HOFS",
 26	"BG1VOFS",
 27	"BG2HOFS",
 28	"BG2VOFS",
 29	"BG3HOFS",
 30	"BG3VOFS",
 31	"BG2PA",
 32	"BG2PB",
 33	"BG2PC",
 34	"BG2PD",
 35	"BG2X_LO",
 36	"BG2X_HI",
 37	"BG2Y_LO",
 38	"BG2Y_HI",
 39	"BG3PA",
 40	"BG3PB",
 41	"BG3PC",
 42	"BG3PD",
 43	"BG3X_LO",
 44	"BG3X_HI",
 45	"BG3Y_LO",
 46	"BG3Y_HI",
 47	"WIN0H",
 48	"WIN1H",
 49	"WIN0V",
 50	"WIN1V",
 51	"WININ",
 52	"WINOUT",
 53	"MOSAIC",
 54	0,
 55	"BLDCNT",
 56	"BLDALPHA",
 57	"BLDY",
 58	0,
 59	0,
 60	0,
 61	0,
 62	0,
 63
 64	// Sound
 65	"SOUND1CNT_LO",
 66	"SOUND1CNT_HI",
 67	"SOUND1CNT_X",
 68	0,
 69	"SOUND2CNT_LO",
 70	0,
 71	"SOUND2CNT_HI",
 72	0,
 73	"SOUND3CNT_LO",
 74	"SOUND3CNT_HI",
 75	"SOUND3CNT_X",
 76	0,
 77	"SOUND4CNT_LO",
 78	0,
 79	"SOUND4CNT_HI",
 80	0,
 81	"SOUNDCNT_LO",
 82	"SOUNDCNT_HI",
 83	"SOUNDCNT_X",
 84	0,
 85	"SOUNDBIAS",
 86	0,
 87	0,
 88	0,
 89	"WAVE_RAM0_LO",
 90	"WAVE_RAM0_HI",
 91	"WAVE_RAM1_LO",
 92	"WAVE_RAM1_HI",
 93	"WAVE_RAM2_LO",
 94	"WAVE_RAM2_HI",
 95	"WAVE_RAM3_LO",
 96	"WAVE_RAM3_HI",
 97	"FIFO_A_LO",
 98	"FIFO_A_HI",
 99	"FIFO_B_LO",
100	"FIFO_B_HI",
101	0,
102	0,
103	0,
104	0,
105
106	// DMA
107	"DMA0SAD_LO",
108	"DMA0SAD_HI",
109	"DMA0DAD_LO",
110	"DMA0DAD_HI",
111	"DMA0CNT_LO",
112	"DMA0CNT_HI",
113	"DMA1SAD_LO",
114	"DMA1SAD_HI",
115	"DMA1DAD_LO",
116	"DMA1DAD_HI",
117	"DMA1CNT_LO",
118	"DMA1CNT_HI",
119	"DMA2SAD_LO",
120	"DMA2SAD_HI",
121	"DMA2DAD_LO",
122	"DMA2DAD_HI",
123	"DMA2CNT_LO",
124	"DMA2CNT_HI",
125	"DMA3SAD_LO",
126	"DMA3SAD_HI",
127	"DMA3DAD_LO",
128	"DMA3DAD_HI",
129	"DMA3CNT_LO",
130	"DMA3CNT_HI",
131
132	0, 0, 0, 0, 0, 0, 0, 0,
133	0, 0, 0, 0, 0, 0, 0, 0,
134
135	// Timers
136	"TM0CNT_LO",
137	"TM0CNT_HI",
138	"TM1CNT_LO",
139	"TM1CNT_HI",
140	"TM2CNT_LO",
141	"TM2CNT_HI",
142	"TM3CNT_LO",
143	"TM3CNT_HI",
144
145	0, 0, 0, 0, 0, 0, 0, 0,
146
147	// SIO
148	"SIOMULTI0",
149	"SIOMULTI1",
150	"SIOMULTI2",
151	"SIOMULTI3",
152	"SIOCNT",
153	"SIOMLT_SEND",
154	0,
155	0,
156	"KEYINPUT",
157	"KEYCNT",
158	"RCNT",
159	0,
160	0,
161	0,
162	0,
163	0,
164	"JOYCNT",
165	0,
166	0,
167	0,
168	0,
169	0,
170	0,
171	0,
172	"JOY_RECV_LO",
173	"JOY_RECV_HI",
174	"JOY_TRANS_LO",
175	"JOY_TRANS_HI",
176	"JOYSTAT",
177	0,
178	0,
179	0,
180
181	0, 0, 0, 0, 0, 0, 0, 0,
182	0, 0, 0, 0, 0, 0, 0, 0,
183	0, 0, 0, 0, 0, 0, 0, 0,
184	0, 0, 0, 0, 0, 0, 0, 0,
185	0, 0, 0, 0, 0, 0, 0, 0,
186	0, 0, 0, 0, 0, 0, 0, 0,
187	0, 0, 0, 0, 0, 0, 0, 0,
188	0, 0, 0, 0, 0, 0, 0, 0,
189	0, 0, 0, 0, 0, 0, 0, 0,
190	0, 0, 0, 0, 0, 0, 0, 0,
191
192	// Interrupts, etc
193	"IE",
194	"IF",
195	"WAITCNT",
196	0,
197	"IME"
198};
199
200static const int _isValidRegister[REG_MAX >> 1] = {
201	// Video
202	1, 0, 1, 1, 1, 1, 1, 1,
203	1, 1, 1, 1, 1, 1, 1, 1,
204	1, 1, 1, 1, 1, 1, 1, 1,
205	1, 1, 1, 1, 1, 1, 1, 1,
206	1, 1, 1, 1, 1, 1, 1, 0,
207	1, 1, 1, 0, 0, 0, 0, 0,
208	// Audio
209	1, 1, 1, 0, 1, 0, 1, 0,
210	1, 1, 1, 0, 1, 0, 1, 0,
211	1, 1, 1, 0, 1, 0, 0, 0,
212	1, 1, 1, 1, 1, 1, 1, 1,
213	1, 1, 1, 1, 1, 0, 0, 0,
214	// DMA
215	1, 1, 1, 1, 1, 1, 1, 1,
216	1, 1, 1, 1, 1, 1, 1, 1,
217	1, 1, 1, 1, 1, 1, 1, 1,
218	0, 0, 0, 0, 0, 0, 0, 0,
219	0, 0, 0, 0, 0, 0, 0, 0,
220	// Timers
221	1, 1, 1, 1, 1, 1, 1, 1,
222	0, 0, 0, 0, 0, 0, 0, 0,
223	// SIO
224	1, 1, 1, 1, 1, 0, 0, 0,
225	1, 1, 1, 0, 0, 0, 0, 0,
226	1, 0, 0, 0, 0, 0, 0, 0,
227	1, 0, 1, 0, 1, 0, 0, 0,
228	0, 0, 0, 0, 0, 0, 0, 0,
229	0, 0, 0, 0, 0, 0, 0, 0,
230	0, 0, 0, 0, 0, 0, 0, 0,
231	0, 0, 0, 0, 0, 0, 0, 0,
232	0, 0, 0, 0, 0, 0, 0, 0,
233	0, 0, 0, 0, 0, 0, 0, 0,
234	0, 0, 0, 0, 0, 0, 0, 0,
235	0, 0, 0, 0, 0, 0, 0, 0,
236	0, 0, 0, 0, 0, 0, 0, 0,
237	0, 0, 0, 0, 0, 0, 0, 0,
238	// Interrupts
239	1, 1, 1, 0, 1
240};
241
242static const int _isSpecialRegister[REG_MAX >> 1] = {
243	// Video
244	0, 0, 1, 1, 0, 0, 0, 0,
245	0, 0, 0, 0, 0, 0, 0, 0,
246	0, 0, 0, 0, 0, 0, 0, 0,
247	0, 0, 0, 0, 0, 0, 0, 0,
248	0, 0, 0, 0, 0, 0, 0, 0,
249	0, 0, 0, 0, 0, 0, 0, 0,
250	// Audio
251	0, 0, 0, 0, 0, 0, 0, 0,
252	0, 0, 0, 0, 0, 0, 0, 0,
253	0, 0, 0, 0, 0, 0, 0, 0,
254	1, 1, 1, 1, 1, 1, 1, 1,
255	1, 1, 1, 1, 0, 0, 0, 0,
256	// DMA
257	0, 0, 0, 0, 0, 1, 0, 0,
258	0, 0, 0, 1, 0, 0, 0, 0,
259	0, 1, 0, 0, 0, 0, 0, 1,
260	0, 0, 0, 0, 0, 0, 0, 0,
261	0, 0, 0, 0, 0, 0, 0, 0,
262	// Timers
263	1, 1, 1, 1, 1, 1, 1, 1,
264	0, 0, 0, 0, 0, 0, 0, 0,
265	// SIO
266	1, 1, 1, 1, 1, 0, 0, 0,
267	1, 1, 1, 0, 0, 0, 0, 0,
268	1, 0, 0, 0, 0, 0, 0, 0,
269	1, 0, 1, 0, 1, 0, 0, 0,
270	0, 0, 0, 0, 0, 0, 0, 0,
271	0, 0, 0, 0, 0, 0, 0, 0,
272	0, 0, 0, 0, 0, 0, 0, 0,
273	0, 0, 0, 0, 0, 0, 0, 0,
274	0, 0, 0, 0, 0, 0, 0, 0,
275	0, 0, 0, 0, 0, 0, 0, 0,
276	0, 0, 0, 0, 0, 0, 0, 0,
277	0, 0, 0, 0, 0, 0, 0, 0,
278	0, 0, 0, 0, 0, 0, 0, 0,
279	0, 0, 0, 0, 0, 0, 0, 0,
280	// Interrupts
281	1, 1, 0, 0, 1
282};
283
284void GBAIOInit(struct GBA* gba) {
285	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
286	gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
287	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
288	gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
289	gba->memory.io[REG_BG2PA >> 1] = 0x100;
290	gba->memory.io[REG_BG2PD >> 1] = 0x100;
291	gba->memory.io[REG_BG3PA >> 1] = 0x100;
292	gba->memory.io[REG_BG3PD >> 1] = 0x100;
293}
294
295void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
296	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
297		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
298	} else {
299		switch (address) {
300		// Video
301		case REG_DISPSTAT:
302			value &= 0xFFF8;
303			GBAVideoWriteDISPSTAT(&gba->video, value);
304			return;
305
306		// Audio
307		case REG_SOUND1CNT_LO:
308			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
309			value &= 0x00FF;
310			break;
311		case REG_SOUND1CNT_HI:
312			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
313			break;
314		case REG_SOUND1CNT_X:
315			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
316			value &= 0x47FF;
317			break;
318		case REG_SOUND2CNT_LO:
319			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
320			break;
321		case REG_SOUND2CNT_HI:
322			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
323			value &= 0x47FF;
324			break;
325		case REG_SOUND3CNT_LO:
326			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
327			value &= 0x00E0;
328			break;
329		case REG_SOUND3CNT_HI:
330			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
331			value &= 0xE03F;
332			break;
333		case REG_SOUND3CNT_X:
334			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
335			// TODO: The low bits need to not be readable, but still 8-bit writable
336			value &= 0x47FF;
337			break;
338		case REG_SOUND4CNT_LO:
339			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
340			value &= 0xFF3F;
341			break;
342		case REG_SOUND4CNT_HI:
343			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
344			value &= 0x40FF;
345			break;
346		case REG_SOUNDCNT_LO:
347			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
348			break;
349		case REG_SOUNDCNT_HI:
350			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
351			break;
352		case REG_SOUNDCNT_X:
353			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
354			value &= 0xFFFF;
355			value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF;
356			break;
357		case REG_SOUNDBIAS:
358			GBAAudioWriteSOUNDBIAS(&gba->audio, value);
359			break;
360
361		case REG_WAVE_RAM0_LO:
362		case REG_WAVE_RAM1_LO:
363		case REG_WAVE_RAM2_LO:
364		case REG_WAVE_RAM3_LO:
365			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
366			break;
367
368		case REG_WAVE_RAM0_HI:
369		case REG_WAVE_RAM1_HI:
370		case REG_WAVE_RAM2_HI:
371		case REG_WAVE_RAM3_HI:
372			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
373			break;
374
375		case REG_FIFO_A_LO:
376		case REG_FIFO_B_LO:
377			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
378			break;
379
380		case REG_FIFO_A_HI:
381		case REG_FIFO_B_HI:
382			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
383			break;
384
385		// DMA
386		case REG_DMA0SAD_LO:
387		case REG_DMA0DAD_LO:
388		case REG_DMA1SAD_LO:
389		case REG_DMA1DAD_LO:
390		case REG_DMA2SAD_LO:
391		case REG_DMA2DAD_LO:
392		case REG_DMA3SAD_LO:
393		case REG_DMA3DAD_LO:
394			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
395			break;
396
397		case REG_DMA0SAD_HI:
398		case REG_DMA0DAD_HI:
399		case REG_DMA1SAD_HI:
400		case REG_DMA1DAD_HI:
401		case REG_DMA2SAD_HI:
402		case REG_DMA2DAD_HI:
403		case REG_DMA3SAD_HI:
404		case REG_DMA3DAD_HI:
405			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
406			break;
407
408		case REG_DMA0CNT_LO:
409			GBAMemoryWriteDMACNT_LO(gba, 0, value);
410			break;
411		case REG_DMA0CNT_HI:
412			value = GBAMemoryWriteDMACNT_HI(gba, 0, value);
413			break;
414		case REG_DMA1CNT_LO:
415			GBAMemoryWriteDMACNT_LO(gba, 1, value);
416			break;
417		case REG_DMA1CNT_HI:
418			value = GBAMemoryWriteDMACNT_HI(gba, 1, value);
419			break;
420		case REG_DMA2CNT_LO:
421			GBAMemoryWriteDMACNT_LO(gba, 2, value);
422			break;
423		case REG_DMA2CNT_HI:
424			value = GBAMemoryWriteDMACNT_HI(gba, 2, value);
425			break;
426		case REG_DMA3CNT_LO:
427			GBAMemoryWriteDMACNT_LO(gba, 3, value);
428			break;
429		case REG_DMA3CNT_HI:
430			value = GBAMemoryWriteDMACNT_HI(gba, 3, value);
431			break;
432
433		// Timers
434		case REG_TM0CNT_LO:
435			GBATimerWriteTMCNT_LO(gba, 0, value);
436			return;
437		case REG_TM1CNT_LO:
438			GBATimerWriteTMCNT_LO(gba, 1, value);
439			return;
440		case REG_TM2CNT_LO:
441			GBATimerWriteTMCNT_LO(gba, 2, value);
442			return;
443		case REG_TM3CNT_LO:
444			GBATimerWriteTMCNT_LO(gba, 3, value);
445			return;
446
447		case REG_TM0CNT_HI:
448			value &= 0x00C7;
449			GBATimerWriteTMCNT_HI(gba, 0, value);
450			break;
451		case REG_TM1CNT_HI:
452			value &= 0x00C7;
453			GBATimerWriteTMCNT_HI(gba, 1, value);
454			break;
455		case REG_TM2CNT_HI:
456			value &= 0x00C7;
457			GBATimerWriteTMCNT_HI(gba, 2, value);
458			break;
459		case REG_TM3CNT_HI:
460			value &= 0x00C7;
461			GBATimerWriteTMCNT_HI(gba, 3, value);
462			break;
463
464		// SIO
465		case REG_SIOCNT:
466			GBASIOWriteSIOCNT(&gba->sio, value);
467			break;
468		case REG_RCNT:
469			value &= 0xC1FF;
470			GBASIOWriteRCNT(&gba->sio, value);
471			break;
472		case REG_SIOMLT_SEND:
473			GBASIOWriteSIOMLT_SEND(&gba->sio, value);
474			break;
475
476		// Interrupts and misc
477		case REG_WAITCNT:
478			GBAAdjustWaitstates(gba, value);
479			break;
480		case REG_IE:
481			GBAWriteIE(gba, value);
482			break;
483		case REG_IF:
484			value = gba->memory.io[REG_IF >> 1] & ~value;
485			break;
486		case REG_IME:
487			GBAWriteIME(gba, value);
488			break;
489		case REG_MAX:
490			// Some bad interrupt libraries will write to this
491			break;
492		default:
493			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03x", address);
494			if (address >= REG_MAX) {
495				GBALog(gba, GBA_LOG_GAME_ERROR, "Write to unused I/O register: %03X", address);
496				return;
497			}
498			break;
499		}
500	}
501	gba->memory.io[address >> 1] = value;
502}
503
504void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
505	if (address == REG_HALTCNT) {
506		value &= 0x80;
507		if (!value) {
508			GBAHalt(gba);
509		} else {
510			GBAStop(gba);
511		}
512		return;
513	}
514	uint16_t value16 = value << (8 * (address & 1));
515	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
516	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
517}
518
519void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
520	switch (address) {
521	case REG_WAVE_RAM0_LO:
522		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
523		break;
524	case REG_WAVE_RAM1_LO:
525		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
526		break;
527	case REG_WAVE_RAM2_LO:
528		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
529		break;
530	case REG_WAVE_RAM3_LO:
531		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
532		break;
533	case REG_FIFO_A_LO:
534	case REG_FIFO_B_LO:
535		GBAAudioWriteFIFO(&gba->audio, address, value);
536		break;
537	case REG_DMA0SAD_LO:
538		value = GBAMemoryWriteDMASAD(gba, 0, value);
539		break;
540	case REG_DMA0DAD_LO:
541		value = GBAMemoryWriteDMADAD(gba, 0, value);
542		break;
543	case REG_DMA1SAD_LO:
544		value = GBAMemoryWriteDMASAD(gba, 1, value);
545		break;
546	case REG_DMA1DAD_LO:
547		value = GBAMemoryWriteDMADAD(gba, 1, value);
548		break;
549	case REG_DMA2SAD_LO:
550		value = GBAMemoryWriteDMASAD(gba, 2, value);
551		break;
552	case REG_DMA2DAD_LO:
553		value = GBAMemoryWriteDMADAD(gba, 2, value);
554		break;
555	case REG_DMA3SAD_LO:
556		value = GBAMemoryWriteDMASAD(gba, 3, value);
557		break;
558	case REG_DMA3DAD_LO:
559		value = GBAMemoryWriteDMADAD(gba, 3, value);
560		break;
561	default:
562		GBAIOWrite(gba, address, value & 0xFFFF);
563		GBAIOWrite(gba, address | 2, value >> 16);
564		return;
565	}
566	gba->memory.io[address >> 1] = value;
567	gba->memory.io[(address >> 1) + 1] = value >> 16;
568}
569
570bool GBAIOIsReadConstant(uint32_t address) {
571	switch (address) {
572	default:
573		return false;
574	case REG_BG0CNT:
575	case REG_BG1CNT:
576	case REG_BG2CNT:
577	case REG_BG3CNT:
578	case REG_WININ:
579	case REG_WINOUT:
580	case REG_BLDCNT:
581	case REG_BLDALPHA:
582	case REG_DMA0CNT_LO:
583	case REG_DMA1CNT_LO:
584	case REG_DMA2CNT_LO:
585	case REG_DMA3CNT_LO:
586	case REG_KEYINPUT:
587	case REG_IE:
588		return true;
589	}
590}
591
592uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
593	if (!GBAIOIsReadConstant(address)) {
594		// Most IO reads need to disable idle removal
595		gba->haltPending = false;
596	}
597
598	switch (address) {
599	case REG_TM0CNT_LO:
600		GBATimerUpdateRegister(gba, 0);
601		break;
602	case REG_TM1CNT_LO:
603		GBATimerUpdateRegister(gba, 1);
604		break;
605	case REG_TM2CNT_LO:
606		GBATimerUpdateRegister(gba, 2);
607		break;
608	case REG_TM3CNT_LO:
609		GBATimerUpdateRegister(gba, 3);
610		break;
611
612	case REG_KEYINPUT:
613		if (gba->rr && gba->rr->isPlaying(gba->rr)) {
614			return 0x3FF ^ gba->rr->queryInput(gba->rr);
615		} else {
616			uint16_t input = 0x3FF;
617			if (gba->keyCallback) {
618				input = gba->keyCallback->readKeys(gba->keyCallback);
619			} else if (gba->keySource) {
620				input = *gba->keySource;
621			}
622			if (gba->rr && gba->rr->isRecording(gba->rr)) {
623				gba->rr->logInput(gba->rr, input);
624			}
625			return 0x3FF ^ input;
626		}
627
628	case REG_SIOCNT:
629		return gba->sio.siocnt;
630	case REG_RCNT:
631		return gba->sio.rcnt;
632
633	case REG_DMA0CNT_LO:
634	case REG_DMA1CNT_LO:
635	case REG_DMA2CNT_LO:
636	case REG_DMA3CNT_LO:
637		// Write-only register
638		return 0;
639	case REG_BG0HOFS:
640	case REG_BG0VOFS:
641	case REG_BG1HOFS:
642	case REG_BG1VOFS:
643	case REG_BG2HOFS:
644	case REG_BG2VOFS:
645	case REG_BG3HOFS:
646	case REG_BG3VOFS:
647	case REG_BG2PA:
648	case REG_BG2PB:
649	case REG_BG2PC:
650	case REG_BG2PD:
651	case REG_BG2X_LO:
652	case REG_BG2X_HI:
653	case REG_BG2Y_LO:
654	case REG_BG2Y_HI:
655	case REG_BG3PA:
656	case REG_BG3PB:
657	case REG_BG3PC:
658	case REG_BG3PD:
659	case REG_BG3X_LO:
660	case REG_BG3X_HI:
661	case REG_BG3Y_LO:
662	case REG_BG3Y_HI:
663	case REG_WIN0H:
664	case REG_WIN1H:
665	case REG_WIN0V:
666	case REG_WIN1V:
667	case REG_MOSAIC:
668	case REG_BLDY:
669		// Write-only register
670		return GBALoad16(gba->cpu, 0x01000000, 0); // Simulate a bad load
671	case REG_DISPCNT:
672	case REG_DISPSTAT:
673	case REG_VCOUNT:
674	case REG_BG0CNT:
675	case REG_BG1CNT:
676	case REG_BG2CNT:
677	case REG_BG3CNT:
678	case REG_WININ:
679	case REG_WINOUT:
680	case REG_BLDCNT:
681	case REG_BLDALPHA:
682	case REG_SOUND1CNT_LO:
683	case REG_SOUND1CNT_HI:
684	case REG_SOUND1CNT_X:
685	case REG_SOUND2CNT_LO:
686	case REG_SOUND2CNT_HI:
687	case REG_SOUND3CNT_LO:
688	case REG_SOUND3CNT_HI:
689	case REG_SOUND3CNT_X:
690	case REG_SOUND4CNT_LO:
691	case REG_SOUND4CNT_HI:
692	case REG_SOUNDCNT_LO:
693	case REG_SOUNDCNT_HI:
694	case REG_DMA0CNT_HI:
695	case REG_DMA1CNT_HI:
696	case REG_DMA2CNT_HI:
697	case REG_DMA3CNT_HI:
698	case REG_SIOMULTI0:
699	case REG_SIOMULTI1:
700	case REG_SIOMULTI2:
701	case REG_SIOMULTI3:
702	case REG_SIOMLT_SEND:
703	case REG_IE:
704	case REG_IF:
705	case REG_WAITCNT:
706	case REG_IME:
707		// Handled transparently by registers
708		break;
709	case REG_MAX:
710		// Some bad interrupt libraries will read from this
711		break;
712	default:
713		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
714		if (address >= REG_MAX) {
715			GBALog(gba, GBA_LOG_GAME_ERROR, "Read from unused I/O register: %03X", address);
716			return 0; // TODO: Reuse LOAD_BAD
717		}
718		break;
719	}
720	return gba->memory.io[address >> 1];
721}
722
723void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
724	int i;
725	for (i = 0; i < REG_MAX; i += 2) {
726		if (_isSpecialRegister[i >> 1]) {
727			STORE_16(gba->memory.io[i >> 1], i, state->io);
728		} else if (_isValidRegister[i >> 1]) {
729			uint16_t reg = GBAIORead(gba, i);
730			STORE_16(reg, i, state->io);
731		}
732	}
733
734	for (i = 0; i < 4; ++i) {
735		STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
736		STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
737		STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
738		STORE_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
739		STORE_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
740		STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
741		STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
742		STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
743		STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
744		STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
745		STORE_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
746	}
747
748	GBAHardwareSerialize(&gba->memory.hw, state);
749}
750
751void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
752	int i;
753	for (i = 0; i < REG_MAX; i += 2) {
754		if (_isSpecialRegister[i >> 1]) {
755			LOAD_16(gba->memory.io[i >> 1], i, state->io);
756		} else if (_isValidRegister[i >> 1]) {
757			uint16_t reg;
758			LOAD_16(reg, i, state->io);
759			GBAIOWrite(gba, i, reg);
760		}
761	}
762
763	gba->timersEnabled = 0;
764	for (i = 0; i < 4; ++i) {
765		LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
766		LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
767		LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
768		LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
769		LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
770		LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
771		LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
772		LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
773		LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
774		LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
775		LOAD_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
776		if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
777			GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
778		}
779
780		if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
781			gba->timersEnabled |= 1 << i;
782		}
783	}
784	GBAMemoryUpdateDMAs(gba, 0);
785	GBAHardwareDeserialize(&gba->memory.hw, state);
786}