all repos — mgba @ 1f6126d1247a2b0c4d0ea97fd73b4d91c8d353d7

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 <mgba/internal/gba/io.h>
  7
  8#include <mgba/internal/arm/macros.h>
  9#include <mgba/internal/gba/dma.h>
 10#include <mgba/internal/gba/gba.h>
 11#include <mgba/internal/gba/rr/rr.h>
 12#include <mgba/internal/gba/serialize.h>
 13
 14mLOG_DEFINE_CATEGORY(GBA_IO, "GBA I/O", "gba.io");
 15
 16const char* const GBAIORegisterNames[] = {
 17	// Video
 18	"DISPCNT",
 19	0,
 20	"DISPSTAT",
 21	"VCOUNT",
 22	"BG0CNT",
 23	"BG1CNT",
 24	"BG2CNT",
 25	"BG3CNT",
 26	"BG0HOFS",
 27	"BG0VOFS",
 28	"BG1HOFS",
 29	"BG1VOFS",
 30	"BG2HOFS",
 31	"BG2VOFS",
 32	"BG3HOFS",
 33	"BG3VOFS",
 34	"BG2PA",
 35	"BG2PB",
 36	"BG2PC",
 37	"BG2PD",
 38	"BG2X_LO",
 39	"BG2X_HI",
 40	"BG2Y_LO",
 41	"BG2Y_HI",
 42	"BG3PA",
 43	"BG3PB",
 44	"BG3PC",
 45	"BG3PD",
 46	"BG3X_LO",
 47	"BG3X_HI",
 48	"BG3Y_LO",
 49	"BG3Y_HI",
 50	"WIN0H",
 51	"WIN1H",
 52	"WIN0V",
 53	"WIN1V",
 54	"WININ",
 55	"WINOUT",
 56	"MOSAIC",
 57	0,
 58	"BLDCNT",
 59	"BLDALPHA",
 60	"BLDY",
 61	0,
 62	0,
 63	0,
 64	0,
 65	0,
 66
 67	// Sound
 68	"SOUND1CNT_LO",
 69	"SOUND1CNT_HI",
 70	"SOUND1CNT_X",
 71	0,
 72	"SOUND2CNT_LO",
 73	0,
 74	"SOUND2CNT_HI",
 75	0,
 76	"SOUND3CNT_LO",
 77	"SOUND3CNT_HI",
 78	"SOUND3CNT_X",
 79	0,
 80	"SOUND4CNT_LO",
 81	0,
 82	"SOUND4CNT_HI",
 83	0,
 84	"SOUNDCNT_LO",
 85	"SOUNDCNT_HI",
 86	"SOUNDCNT_X",
 87	0,
 88	"SOUNDBIAS",
 89	0,
 90	0,
 91	0,
 92	"WAVE_RAM0_LO",
 93	"WAVE_RAM0_HI",
 94	"WAVE_RAM1_LO",
 95	"WAVE_RAM1_HI",
 96	"WAVE_RAM2_LO",
 97	"WAVE_RAM2_HI",
 98	"WAVE_RAM3_LO",
 99	"WAVE_RAM3_HI",
100	"FIFO_A_LO",
101	"FIFO_A_HI",
102	"FIFO_B_LO",
103	"FIFO_B_HI",
104	0,
105	0,
106	0,
107	0,
108
109	// DMA
110	"DMA0SAD_LO",
111	"DMA0SAD_HI",
112	"DMA0DAD_LO",
113	"DMA0DAD_HI",
114	"DMA0CNT_LO",
115	"DMA0CNT_HI",
116	"DMA1SAD_LO",
117	"DMA1SAD_HI",
118	"DMA1DAD_LO",
119	"DMA1DAD_HI",
120	"DMA1CNT_LO",
121	"DMA1CNT_HI",
122	"DMA2SAD_LO",
123	"DMA2SAD_HI",
124	"DMA2DAD_LO",
125	"DMA2DAD_HI",
126	"DMA2CNT_LO",
127	"DMA2CNT_HI",
128	"DMA3SAD_LO",
129	"DMA3SAD_HI",
130	"DMA3DAD_LO",
131	"DMA3DAD_HI",
132	"DMA3CNT_LO",
133	"DMA3CNT_HI",
134
135	0, 0, 0, 0, 0, 0, 0, 0,
136	0, 0, 0, 0, 0, 0, 0, 0,
137
138	// Timers
139	"TM0CNT_LO",
140	"TM0CNT_HI",
141	"TM1CNT_LO",
142	"TM1CNT_HI",
143	"TM2CNT_LO",
144	"TM2CNT_HI",
145	"TM3CNT_LO",
146	"TM3CNT_HI",
147
148	0, 0, 0, 0, 0, 0, 0, 0,
149
150	// SIO
151	"SIOMULTI0",
152	"SIOMULTI1",
153	"SIOMULTI2",
154	"SIOMULTI3",
155	"SIOCNT",
156	"SIOMLT_SEND",
157	0,
158	0,
159	"KEYINPUT",
160	"KEYCNT",
161	"RCNT",
162	0,
163	0,
164	0,
165	0,
166	0,
167	"JOYCNT",
168	0,
169	0,
170	0,
171	0,
172	0,
173	0,
174	0,
175	"JOY_RECV_LO",
176	"JOY_RECV_HI",
177	"JOY_TRANS_LO",
178	"JOY_TRANS_HI",
179	"JOYSTAT",
180	0,
181	0,
182	0,
183
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	0, 0, 0, 0, 0, 0, 0, 0,
192	0, 0, 0, 0, 0, 0, 0, 0,
193	0, 0, 0, 0, 0, 0, 0, 0,
194
195	// Interrupts, etc
196	"IE",
197	"IF",
198	"WAITCNT",
199	0,
200	"IME"
201};
202
203static const int _isValidRegister[REG_MAX >> 1] = {
204	// Video
205	1, 0, 1, 1, 1, 1, 1, 1,
206	1, 1, 1, 1, 1, 1, 1, 1,
207	1, 1, 1, 1, 1, 1, 1, 1,
208	1, 1, 1, 1, 1, 1, 1, 1,
209	1, 1, 1, 1, 1, 1, 1, 0,
210	1, 1, 1, 0, 0, 0, 0, 0,
211	// Audio
212	1, 1, 1, 0, 1, 0, 1, 0,
213	1, 1, 1, 0, 1, 0, 1, 0,
214	1, 1, 1, 0, 1, 0, 0, 0,
215	1, 1, 1, 1, 1, 1, 1, 1,
216	1, 1, 1, 1, 0, 0, 0, 0,
217	// DMA
218	1, 1, 1, 1, 1, 1, 1, 1,
219	1, 1, 1, 1, 1, 1, 1, 1,
220	1, 1, 1, 1, 1, 1, 1, 1,
221	0, 0, 0, 0, 0, 0, 0, 0,
222	0, 0, 0, 0, 0, 0, 0, 0,
223	// Timers
224	1, 1, 1, 1, 1, 1, 1, 1,
225	0, 0, 0, 0, 0, 0, 0, 0,
226	// SIO
227	1, 1, 1, 1, 1, 0, 0, 0,
228	1, 1, 1, 0, 0, 0, 0, 0,
229	1, 0, 0, 0, 0, 0, 0, 0,
230	1, 0, 1, 0, 1, 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	0, 0, 0, 0, 0, 0, 0, 0,
239	0, 0, 0, 0, 0, 0, 0, 0,
240	0, 0, 0, 0, 0, 0, 0, 0,
241	// Interrupts
242	1, 1, 1, 0, 1
243};
244
245static const int _isRSpecialRegister[REG_MAX >> 1] = {
246	// Video
247	0, 0, 1, 1, 0, 0, 0, 0,
248	1, 1, 1, 1, 1, 1, 1, 1,
249	1, 1, 1, 1, 1, 1, 1, 1,
250	1, 1, 1, 1, 1, 1, 1, 1,
251	1, 1, 1, 1, 1, 1, 1, 1,
252	1, 1, 1, 1, 1, 1, 1, 1,
253	// Audio
254	0, 0, 1, 0, 0, 0, 1, 0,
255	0, 0, 1, 0, 0, 0, 1, 0,
256	0, 0, 0, 0, 1, 0, 0, 0,
257	1, 1, 1, 1, 1, 1, 1, 1,
258	1, 1, 1, 1, 0, 0, 0, 0,
259	// DMA
260	1, 1, 1, 1, 1, 1, 1, 1,
261	1, 1, 1, 1, 1, 1, 1, 1,
262	1, 1, 1, 1, 1, 1, 1, 1,
263	0, 0, 0, 0, 0, 0, 0, 0,
264	0, 0, 0, 0, 0, 0, 0, 0,
265	// Timers
266	1, 1, 1, 1, 1, 1, 1, 1,
267	0, 0, 0, 0, 0, 0, 0, 0,
268	// SIO
269	1, 1, 1, 1, 1, 0, 0, 0,
270	1, 1, 1, 0, 0, 0, 0, 0,
271	1, 0, 0, 0, 0, 0, 0, 0,
272	1, 0, 1, 0, 1, 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	0, 0, 0, 0, 0, 0, 0, 0,
281	0, 0, 0, 0, 0, 0, 0, 0,
282	0, 0, 0, 0, 0, 0, 0, 0,
283	// Interrupts
284};
285
286static const int _isWSpecialRegister[REG_MAX >> 1] = {
287	// Video
288	0, 0, 1, 1, 0, 0, 0, 0,
289	0, 0, 0, 0, 0, 0, 0, 0,
290	0, 0, 0, 0, 0, 0, 0, 0,
291	0, 0, 0, 0, 0, 0, 0, 0,
292	0, 0, 0, 0, 0, 0, 0, 0,
293	0, 0, 0, 0, 0, 0, 0, 0,
294	// Audio
295	1, 1, 1, 0, 1, 0, 1, 0,
296	1, 0, 1, 0, 1, 0, 1, 0,
297	1, 0, 1, 0, 0, 0, 0, 0,
298	1, 1, 1, 1, 1, 1, 1, 1,
299	1, 1, 1, 1, 0, 0, 0, 0,
300	// DMA
301	0, 0, 0, 0, 0, 1, 0, 0,
302	0, 0, 0, 1, 0, 0, 0, 0,
303	0, 1, 0, 0, 0, 0, 0, 1,
304	0, 0, 0, 0, 0, 0, 0, 0,
305	0, 0, 0, 0, 0, 0, 0, 0,
306	// Timers
307	1, 1, 1, 1, 1, 1, 1, 1,
308	0, 0, 0, 0, 0, 0, 0, 0,
309	// SIO
310	1, 1, 1, 1, 1, 0, 0, 0,
311	1, 1, 1, 0, 0, 0, 0, 0,
312	1, 0, 0, 0, 0, 0, 0, 0,
313	1, 0, 1, 0, 1, 0, 0, 0,
314	0, 0, 0, 0, 0, 0, 0, 0,
315	0, 0, 0, 0, 0, 0, 0, 0,
316	0, 0, 0, 0, 0, 0, 0, 0,
317	0, 0, 0, 0, 0, 0, 0, 0,
318	0, 0, 0, 0, 0, 0, 0, 0,
319	0, 0, 0, 0, 0, 0, 0, 0,
320	0, 0, 0, 0, 0, 0, 0, 0,
321	0, 0, 0, 0, 0, 0, 0, 0,
322	0, 0, 0, 0, 0, 0, 0, 0,
323	0, 0, 0, 0, 0, 0, 0, 0,
324	// Interrupts
325	1, 1, 0, 0, 1
326};
327
328void GBAIOInit(struct GBA* gba) {
329	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
330	gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
331	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
332	gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
333	gba->memory.io[REG_BG2PA >> 1] = 0x100;
334	gba->memory.io[REG_BG2PD >> 1] = 0x100;
335	gba->memory.io[REG_BG3PA >> 1] = 0x100;
336	gba->memory.io[REG_BG3PD >> 1] = 0x100;
337
338	if (!gba->biosVf) {
339		gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
340		gba->memory.io[REG_POSTFLG >> 1] = 1;
341	}
342}
343
344void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
345	if (address < REG_SOUND1CNT_LO && (address > REG_VCOUNT || address == REG_DISPCNT)) {
346		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
347	} else {
348		switch (address) {
349		// Video
350		case REG_DISPSTAT:
351			value &= 0xFFF8;
352			GBAVideoWriteDISPSTAT(&gba->video, value);
353			return;
354
355		case REG_VCOUNT:
356			mLOG(GBA_IO, GAME_ERROR, "Write to read-only I/O register: %03X", address);
357			return;
358
359		// Audio
360		case REG_SOUND1CNT_LO:
361			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
362			value &= 0x007F;
363			break;
364		case REG_SOUND1CNT_HI:
365			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
366			break;
367		case REG_SOUND1CNT_X:
368			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
369			value &= 0x47FF;
370			break;
371		case REG_SOUND2CNT_LO:
372			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
373			break;
374		case REG_SOUND2CNT_HI:
375			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
376			value &= 0x47FF;
377			break;
378		case REG_SOUND3CNT_LO:
379			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
380			value &= 0x00E0;
381			break;
382		case REG_SOUND3CNT_HI:
383			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
384			value &= 0xE03F;
385			break;
386		case REG_SOUND3CNT_X:
387			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
388			// TODO: The low bits need to not be readable, but still 8-bit writable
389			value &= 0x47FF;
390			break;
391		case REG_SOUND4CNT_LO:
392			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
393			value &= 0xFF3F;
394			break;
395		case REG_SOUND4CNT_HI:
396			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
397			value &= 0x40FF;
398			break;
399		case REG_SOUNDCNT_LO:
400			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
401			value &= 0xFF77;
402			break;
403		case REG_SOUNDCNT_HI:
404			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
405			value &= 0x770F;
406			break;
407		case REG_SOUNDCNT_X:
408			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
409			value &= 0x0080;
410			value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF;
411			break;
412		case REG_SOUNDBIAS:
413			GBAAudioWriteSOUNDBIAS(&gba->audio, value);
414			break;
415
416		case REG_WAVE_RAM0_LO:
417		case REG_WAVE_RAM1_LO:
418		case REG_WAVE_RAM2_LO:
419		case REG_WAVE_RAM3_LO:
420			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
421			break;
422
423		case REG_WAVE_RAM0_HI:
424		case REG_WAVE_RAM1_HI:
425		case REG_WAVE_RAM2_HI:
426		case REG_WAVE_RAM3_HI:
427			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
428			break;
429
430		case REG_FIFO_A_LO:
431		case REG_FIFO_B_LO:
432			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
433			break;
434
435		case REG_FIFO_A_HI:
436		case REG_FIFO_B_HI:
437			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
438			break;
439
440		// DMA
441		case REG_DMA0SAD_LO:
442		case REG_DMA0DAD_LO:
443		case REG_DMA1SAD_LO:
444		case REG_DMA1DAD_LO:
445		case REG_DMA2SAD_LO:
446		case REG_DMA2DAD_LO:
447		case REG_DMA3SAD_LO:
448		case REG_DMA3DAD_LO:
449			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
450			break;
451
452		case REG_DMA0SAD_HI:
453		case REG_DMA0DAD_HI:
454		case REG_DMA1SAD_HI:
455		case REG_DMA1DAD_HI:
456		case REG_DMA2SAD_HI:
457		case REG_DMA2DAD_HI:
458		case REG_DMA3SAD_HI:
459		case REG_DMA3DAD_HI:
460			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
461			break;
462
463		case REG_DMA0CNT_LO:
464			GBADMAWriteCNT_LO(gba, 0, value & 0x3FFF);
465			break;
466		case REG_DMA0CNT_HI:
467			value = GBADMAWriteCNT_HI(gba, 0, value);
468			break;
469		case REG_DMA1CNT_LO:
470			GBADMAWriteCNT_LO(gba, 1, value & 0x3FFF);
471			break;
472		case REG_DMA1CNT_HI:
473			value = GBADMAWriteCNT_HI(gba, 1, value);
474			break;
475		case REG_DMA2CNT_LO:
476			GBADMAWriteCNT_LO(gba, 2, value & 0x3FFF);
477			break;
478		case REG_DMA2CNT_HI:
479			value = GBADMAWriteCNT_HI(gba, 2, value);
480			break;
481		case REG_DMA3CNT_LO:
482			GBADMAWriteCNT_LO(gba, 3, value);
483			break;
484		case REG_DMA3CNT_HI:
485			value = GBADMAWriteCNT_HI(gba, 3, value);
486			break;
487
488		// Timers
489		case REG_TM0CNT_LO:
490			GBATimerWriteTMCNT_LO(gba, 0, value);
491			return;
492		case REG_TM1CNT_LO:
493			GBATimerWriteTMCNT_LO(gba, 1, value);
494			return;
495		case REG_TM2CNT_LO:
496			GBATimerWriteTMCNT_LO(gba, 2, value);
497			return;
498		case REG_TM3CNT_LO:
499			GBATimerWriteTMCNT_LO(gba, 3, value);
500			return;
501
502		case REG_TM0CNT_HI:
503			value &= 0x00C7;
504			GBATimerWriteTMCNT_HI(gba, 0, value);
505			break;
506		case REG_TM1CNT_HI:
507			value &= 0x00C7;
508			GBATimerWriteTMCNT_HI(gba, 1, value);
509			break;
510		case REG_TM2CNT_HI:
511			value &= 0x00C7;
512			GBATimerWriteTMCNT_HI(gba, 2, value);
513			break;
514		case REG_TM3CNT_HI:
515			value &= 0x00C7;
516			GBATimerWriteTMCNT_HI(gba, 3, value);
517			break;
518
519		// SIO
520		case REG_SIOCNT:
521			GBASIOWriteSIOCNT(&gba->sio, value);
522			break;
523		case REG_RCNT:
524			value &= 0xC1FF;
525			GBASIOWriteRCNT(&gba->sio, value);
526			break;
527		case REG_JOY_TRANS_LO:
528		case REG_JOY_TRANS_HI:
529			gba->memory.io[REG_JOYSTAT >> 1] |= JOYSTAT_TRANS_BIT;
530			// Fall through
531		case REG_SIOMLT_SEND:
532		case REG_JOYCNT:
533		case REG_JOYSTAT:
534		case REG_JOY_RECV_LO:
535		case REG_JOY_RECV_HI:
536			value = GBASIOWriteRegister(&gba->sio, address, value);
537			break;
538
539		// Interrupts and misc
540		case REG_KEYCNT:
541			value &= 0xC3FF;
542			gba->memory.io[address >> 1] = value;
543			GBATestKeypadIRQ(gba);
544			return;
545		case REG_WAITCNT:
546			value &= 0x5FFF;
547			GBAAdjustWaitstates(gba, value);
548			break;
549		case REG_IE:
550			gba->memory.io[REG_IE >> 1] = value;
551			GBATestIRQ(gba, 1);
552			return;
553		case REG_IF:
554			value = gba->memory.io[REG_IF >> 1] & ~value;
555			gba->memory.io[REG_IF >> 1] = value;
556			GBATestIRQ(gba, 1);
557			return;
558		case REG_IME:
559			gba->memory.io[REG_IME >> 1] = value;
560			GBATestIRQ(gba, 1);
561			return;
562		case REG_MAX:
563			// Some bad interrupt libraries will write to this
564			break;
565		case REG_DEBUG_ENABLE:
566			gba->debug = value == 0xC0DE;
567			return;
568		case REG_DEBUG_FLAGS:
569			if (gba->debug) {
570				GBADebug(gba, value);
571				return;
572			}
573			// Fall through
574		default:
575			if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
576				STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
577				return;
578			}
579			mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
580			if (address >= REG_MAX) {
581				mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
582				return;
583			}
584			break;
585		}
586	}
587	gba->memory.io[address >> 1] = value;
588}
589
590void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
591	if (address == REG_HALTCNT) {
592		value &= 0x80;
593		if (!value) {
594			GBAHalt(gba);
595		} else {
596			GBAStop(gba);
597		}
598		return;
599	}
600	if (address == REG_POSTFLG) {
601		gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
602		return;
603	}
604	if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
605		gba->debugString[address - REG_DEBUG_STRING] = value;
606		return;
607	}
608	if (address > SIZE_IO) {
609		return;
610	}
611	uint16_t value16 = value << (8 * (address & 1));
612	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
613	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
614}
615
616void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
617	switch (address) {
618	case REG_WAVE_RAM0_LO:
619		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
620		break;
621	case REG_WAVE_RAM1_LO:
622		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
623		break;
624	case REG_WAVE_RAM2_LO:
625		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
626		break;
627	case REG_WAVE_RAM3_LO:
628		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
629		break;
630	case REG_FIFO_A_LO:
631	case REG_FIFO_B_LO:
632		GBAAudioWriteFIFO(&gba->audio, address, value);
633		break;
634	case REG_DMA0SAD_LO:
635		value = GBADMAWriteSAD(gba, 0, value);
636		break;
637	case REG_DMA0DAD_LO:
638		value = GBADMAWriteDAD(gba, 0, value);
639		break;
640	case REG_DMA1SAD_LO:
641		value = GBADMAWriteSAD(gba, 1, value);
642		break;
643	case REG_DMA1DAD_LO:
644		value = GBADMAWriteDAD(gba, 1, value);
645		break;
646	case REG_DMA2SAD_LO:
647		value = GBADMAWriteSAD(gba, 2, value);
648		break;
649	case REG_DMA2DAD_LO:
650		value = GBADMAWriteDAD(gba, 2, value);
651		break;
652	case REG_DMA3SAD_LO:
653		value = GBADMAWriteSAD(gba, 3, value);
654		break;
655	case REG_DMA3DAD_LO:
656		value = GBADMAWriteDAD(gba, 3, value);
657		break;
658	default:
659		if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
660			STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
661			return;
662		}
663		GBAIOWrite(gba, address, value & 0xFFFF);
664		GBAIOWrite(gba, address | 2, value >> 16);
665		return;
666	}
667	gba->memory.io[address >> 1] = value;
668	gba->memory.io[(address >> 1) + 1] = value >> 16;
669}
670
671bool GBAIOIsReadConstant(uint32_t address) {
672	switch (address) {
673	default:
674		return false;
675	case REG_BG0CNT:
676	case REG_BG1CNT:
677	case REG_BG2CNT:
678	case REG_BG3CNT:
679	case REG_WININ:
680	case REG_WINOUT:
681	case REG_BLDCNT:
682	case REG_BLDALPHA:
683	case REG_SOUND1CNT_LO:
684	case REG_SOUND1CNT_HI:
685	case REG_SOUND1CNT_X:
686	case REG_SOUND2CNT_LO:
687	case REG_SOUND2CNT_HI:
688	case REG_SOUND3CNT_LO:
689	case REG_SOUND3CNT_HI:
690	case REG_SOUND3CNT_X:
691	case REG_SOUND4CNT_LO:
692	case REG_SOUND4CNT_HI:
693	case REG_SOUNDCNT_LO:
694	case REG_SOUNDCNT_HI:
695	case REG_TM0CNT_HI:
696	case REG_TM1CNT_HI:
697	case REG_TM2CNT_HI:
698	case REG_TM3CNT_HI:
699	case REG_KEYINPUT:
700	case REG_KEYCNT:
701	case REG_IE:
702		return true;
703	}
704}
705
706uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
707	if (!GBAIOIsReadConstant(address)) {
708		// Most IO reads need to disable idle removal
709		gba->haltPending = false;
710	}
711
712	switch (address) {
713	// Reading this takes two cycles (1N+1I), so let's remove them preemptively
714	case REG_TM0CNT_LO:
715		GBATimerUpdateRegister(gba, 0, 4);
716		break;
717	case REG_TM1CNT_LO:
718		GBATimerUpdateRegister(gba, 1, 4);
719		break;
720	case REG_TM2CNT_LO:
721		GBATimerUpdateRegister(gba, 2, 4);
722		break;
723	case REG_TM3CNT_LO:
724		GBATimerUpdateRegister(gba, 3, 4);
725		break;
726
727	case REG_KEYINPUT:
728		{
729			size_t c;
730			for (c = 0; c < mCoreCallbacksListSize(&gba->coreCallbacks); ++c) {
731				struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gba->coreCallbacks, c);
732				if (callbacks->keysRead) {
733					callbacks->keysRead(callbacks->context);
734				}
735			}
736		}
737		if (gba->rr && gba->rr->isPlaying(gba->rr)) {
738			return 0x3FF ^ gba->rr->queryInput(gba->rr);
739		} else {
740			uint16_t input = 0;
741			if (gba->keyCallback) {
742				input = gba->keyCallback->readKeys(gba->keyCallback);
743				if (gba->keySource) {
744					*gba->keySource = input;
745				}
746			} else if (gba->keySource) {
747				input = *gba->keySource;
748				if (!gba->allowOpposingDirections) {
749					unsigned rl = input & 0x030;
750					unsigned ud = input & 0x0C0;
751					input &= 0x30F;
752					if (rl != 0x030) {
753						input |= rl;
754					}
755					if (ud != 0x0C0) {
756						input |= ud;
757					}
758				}
759			}
760			if (gba->rr && gba->rr->isRecording(gba->rr)) {
761				gba->rr->logInput(gba->rr, input);
762			}
763			return 0x3FF ^ input;
764		}
765
766	case REG_SIOCNT:
767		return gba->sio.siocnt;
768	case REG_RCNT:
769		return gba->sio.rcnt;
770
771	case REG_BG0HOFS:
772	case REG_BG0VOFS:
773	case REG_BG1HOFS:
774	case REG_BG1VOFS:
775	case REG_BG2HOFS:
776	case REG_BG2VOFS:
777	case REG_BG3HOFS:
778	case REG_BG3VOFS:
779	case REG_BG2PA:
780	case REG_BG2PB:
781	case REG_BG2PC:
782	case REG_BG2PD:
783	case REG_BG2X_LO:
784	case REG_BG2X_HI:
785	case REG_BG2Y_LO:
786	case REG_BG2Y_HI:
787	case REG_BG3PA:
788	case REG_BG3PB:
789	case REG_BG3PC:
790	case REG_BG3PD:
791	case REG_BG3X_LO:
792	case REG_BG3X_HI:
793	case REG_BG3Y_LO:
794	case REG_BG3Y_HI:
795	case REG_WIN0H:
796	case REG_WIN1H:
797	case REG_WIN0V:
798	case REG_WIN1V:
799	case REG_MOSAIC:
800	case REG_BLDY:
801	case REG_FIFO_A_LO:
802	case REG_FIFO_A_HI:
803	case REG_FIFO_B_LO:
804	case REG_FIFO_B_HI:
805	case REG_DMA0SAD_LO:
806	case REG_DMA0SAD_HI:
807	case REG_DMA0DAD_LO:
808	case REG_DMA0DAD_HI:
809	case REG_DMA1SAD_LO:
810	case REG_DMA1SAD_HI:
811	case REG_DMA1DAD_LO:
812	case REG_DMA1DAD_HI:
813	case REG_DMA2SAD_LO:
814	case REG_DMA2SAD_HI:
815	case REG_DMA2DAD_LO:
816	case REG_DMA2DAD_HI:
817	case REG_DMA3SAD_LO:
818	case REG_DMA3SAD_HI:
819	case REG_DMA3DAD_LO:
820	case REG_DMA3DAD_HI:
821		// Write-only register
822		mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
823		return GBALoadBad(gba->cpu);
824
825	case REG_DMA0CNT_LO:
826	case REG_DMA1CNT_LO:
827	case REG_DMA2CNT_LO:
828	case REG_DMA3CNT_LO:
829		// Write-only register
830		mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
831		return 0;
832
833	case REG_JOY_RECV_LO:
834	case REG_JOY_RECV_HI:
835		gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV_BIT;
836		break;
837
838	case REG_SOUNDBIAS:
839	case REG_POSTFLG:
840		mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
841		break;
842	case REG_SOUND1CNT_LO:
843	case REG_SOUND1CNT_HI:
844	case REG_SOUND1CNT_X:
845	case REG_SOUND2CNT_LO:
846	case REG_SOUND2CNT_HI:
847	case REG_SOUND3CNT_LO:
848	case REG_SOUND3CNT_HI:
849	case REG_SOUND3CNT_X:
850	case REG_SOUND4CNT_LO:
851	case REG_SOUND4CNT_HI:
852	case REG_SOUNDCNT_LO:
853		if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
854			// TODO: Is writing allowed when the circuit is disabled?
855			return 0;
856		}
857		// Fall through
858	case REG_DISPCNT:
859	case REG_DISPSTAT:
860	case REG_VCOUNT:
861	case REG_BG0CNT:
862	case REG_BG1CNT:
863	case REG_BG2CNT:
864	case REG_BG3CNT:
865	case REG_WININ:
866	case REG_WINOUT:
867	case REG_BLDCNT:
868	case REG_BLDALPHA:
869	case REG_SOUNDCNT_HI:
870	case REG_SOUNDCNT_X:
871	case REG_WAVE_RAM0_LO:
872	case REG_WAVE_RAM0_HI:
873	case REG_WAVE_RAM1_LO:
874	case REG_WAVE_RAM1_HI:
875	case REG_WAVE_RAM2_LO:
876	case REG_WAVE_RAM2_HI:
877	case REG_WAVE_RAM3_LO:
878	case REG_WAVE_RAM3_HI:
879	case REG_DMA0CNT_HI:
880	case REG_DMA1CNT_HI:
881	case REG_DMA2CNT_HI:
882	case REG_DMA3CNT_HI:
883	case REG_TM0CNT_HI:
884	case REG_TM1CNT_HI:
885	case REG_TM2CNT_HI:
886	case REG_TM3CNT_HI:
887	case REG_KEYCNT:
888	case REG_SIOMULTI0:
889	case REG_SIOMULTI1:
890	case REG_SIOMULTI2:
891	case REG_SIOMULTI3:
892	case REG_SIOMLT_SEND:
893	case REG_JOYCNT:
894	case REG_JOY_TRANS_LO:
895	case REG_JOY_TRANS_HI:
896	case REG_JOYSTAT:
897	case REG_IE:
898	case REG_IF:
899	case REG_WAITCNT:
900	case REG_IME:
901		// Handled transparently by registers
902		break;
903	case REG_MAX:
904		// Some bad interrupt libraries will read from this
905	case 0x066:
906	case 0x06E:
907	case 0x076:
908	case 0x07A:
909	case 0x07E:
910	case 0x086:
911	case 0x08A:
912	case 0x136:
913	case 0x142:
914	case 0x15A:
915	case 0x206:
916		mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
917		return 0;
918	case REG_DEBUG_ENABLE:
919		if (gba->debug) {
920			return 0x1DEA;
921		}
922		// Fall through
923	default:
924		mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
925		return GBALoadBad(gba->cpu);
926	}
927	return gba->memory.io[address >> 1];
928}
929
930void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
931	int i;
932	for (i = 0; i < REG_MAX; i += 2) {
933		if (_isRSpecialRegister[i >> 1]) {
934			STORE_16(gba->memory.io[i >> 1], i, state->io);
935		} else if (_isValidRegister[i >> 1]) {
936			uint16_t reg = GBAIORead(gba, i);
937			STORE_16(reg, i, state->io);
938		}
939	}
940
941	for (i = 0; i < 4; ++i) {
942		STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
943		STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
944		STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent);
945		STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent);
946		STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
947		STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
948		STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
949		STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
950		STORE_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
951	}
952
953	state->dmaTransferRegister = gba->memory.dmaTransferRegister;
954
955	GBAHardwareSerialize(&gba->memory.hw, state);
956}
957
958void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
959	int i;
960	for (i = 0; i < REG_MAX; i += 2) {
961		if (_isWSpecialRegister[i >> 1]) {
962			LOAD_16(gba->memory.io[i >> 1], i, state->io);
963		} else if (_isValidRegister[i >> 1]) {
964			uint16_t reg;
965			LOAD_16(reg, i, state->io);
966			GBAIOWrite(gba, i, reg);
967		}
968	}
969
970	uint32_t when;
971	for (i = 0; i < 4; ++i) {
972		LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
973		LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
974		if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
975			// Overwrite invalid values in savestate
976			gba->timers[i].lastEvent = 0;
977		} else {
978			LOAD_32(when, 0, &state->timers[i].lastEvent);
979			gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
980		}
981		LOAD_32(when, 0, &state->timers[i].nextEvent);
982		if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
983			mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
984		}
985
986		LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
987		LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
988		LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
989		LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
990		LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
991		if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != GBA_DMA_TIMING_NOW) {
992			GBADMASchedule(gba, i, &gba->memory.dma[i]);
993		}
994	}
995	GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
996	gba->memory.dmaTransferRegister = state->dmaTransferRegister;
997	GBADMAUpdate(gba);
998	GBAHardwareDeserialize(&gba->memory.hw, state);
999}