all repos — mgba @ f03b7b11415e541a6f7230db73b4bb752bbe5eeb

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, 0, 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 _isRSpecialRegister[REG_MAX >> 1] = {
243	// Video
244	0, 0, 1, 1, 0, 0, 0, 0,
245	1, 1, 1, 1, 1, 1, 1, 1,
246	1, 1, 1, 1, 1, 1, 1, 1,
247	1, 1, 1, 1, 1, 1, 1, 1,
248	1, 1, 1, 1, 1, 1, 1, 1,
249	1, 1, 1, 1, 1, 1, 1, 1,
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, 1, 0, 0, 0,
254	1, 1, 1, 1, 1, 1, 1, 1,
255	1, 1, 1, 1, 0, 0, 0, 0,
256	// DMA
257	1, 1, 1, 1, 1, 1, 1, 1,
258	1, 1, 1, 1, 1, 1, 1, 1,
259	1, 1, 1, 1, 1, 1, 1, 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};
282
283static const int _isWSpecialRegister[REG_MAX >> 1] = {
284	// Video
285	0, 0, 1, 1, 0, 0, 0, 0,
286	0, 0, 0, 0, 0, 0, 0, 0,
287	0, 0, 0, 0, 0, 0, 0, 0,
288	0, 0, 0, 0, 0, 0, 0, 0,
289	0, 0, 0, 0, 0, 0, 0, 0,
290	0, 0, 0, 0, 0, 0, 0, 0,
291	// Audio
292	0, 0, 0, 0, 0, 0, 0, 0,
293	0, 0, 0, 0, 0, 0, 0, 0,
294	0, 0, 1, 0, 0, 0, 0, 0,
295	1, 1, 1, 1, 1, 1, 1, 1,
296	1, 1, 1, 1, 0, 0, 0, 0,
297	// DMA
298	0, 0, 0, 0, 0, 1, 0, 0,
299	0, 0, 0, 1, 0, 0, 0, 0,
300	0, 1, 0, 0, 0, 0, 0, 1,
301	0, 0, 0, 0, 0, 0, 0, 0,
302	0, 0, 0, 0, 0, 0, 0, 0,
303	// Timers
304	1, 1, 1, 1, 1, 1, 1, 1,
305	0, 0, 0, 0, 0, 0, 0, 0,
306	// SIO
307	1, 1, 1, 1, 1, 0, 0, 0,
308	1, 1, 1, 0, 0, 0, 0, 0,
309	1, 0, 0, 0, 0, 0, 0, 0,
310	1, 0, 1, 0, 1, 0, 0, 0,
311	0, 0, 0, 0, 0, 0, 0, 0,
312	0, 0, 0, 0, 0, 0, 0, 0,
313	0, 0, 0, 0, 0, 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	// Interrupts
322	1, 1, 0, 0, 1
323};
324
325void GBAIOInit(struct GBA* gba) {
326	gba->memory.io[REG_DISPCNT >> 1] = 0x0080;
327	gba->memory.io[REG_RCNT >> 1] = RCNT_INITIAL;
328	gba->memory.io[REG_KEYINPUT >> 1] = 0x3FF;
329	gba->memory.io[REG_SOUNDBIAS >> 1] = 0x200;
330	gba->memory.io[REG_BG2PA >> 1] = 0x100;
331	gba->memory.io[REG_BG2PD >> 1] = 0x100;
332	gba->memory.io[REG_BG3PA >> 1] = 0x100;
333	gba->memory.io[REG_BG3PD >> 1] = 0x100;
334}
335
336void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
337	if (address < REG_SOUND1CNT_LO && address != REG_DISPSTAT) {
338		value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
339	} else {
340		switch (address) {
341		// Video
342		case REG_DISPSTAT:
343			value &= 0xFFF8;
344			GBAVideoWriteDISPSTAT(&gba->video, value);
345			return;
346
347		// Audio
348		case REG_SOUND1CNT_LO:
349			GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
350			value &= 0x007F;
351			break;
352		case REG_SOUND1CNT_HI:
353			GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
354			break;
355		case REG_SOUND1CNT_X:
356			GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
357			value &= 0x47FF;
358			break;
359		case REG_SOUND2CNT_LO:
360			GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
361			break;
362		case REG_SOUND2CNT_HI:
363			GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
364			value &= 0x47FF;
365			break;
366		case REG_SOUND3CNT_LO:
367			GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
368			value &= 0x00E0;
369			break;
370		case REG_SOUND3CNT_HI:
371			GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
372			value &= 0xE03F;
373			break;
374		case REG_SOUND3CNT_X:
375			GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
376			// TODO: The low bits need to not be readable, but still 8-bit writable
377			value &= 0x47FF;
378			break;
379		case REG_SOUND4CNT_LO:
380			GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
381			value &= 0xFF3F;
382			break;
383		case REG_SOUND4CNT_HI:
384			GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
385			value &= 0x40FF;
386			break;
387		case REG_SOUNDCNT_LO:
388			GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
389			value &= 0xFF77;
390			break;
391		case REG_SOUNDCNT_HI:
392			GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
393			value &= 0x770F;
394			break;
395		case REG_SOUNDCNT_X:
396			GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
397			value &= 0x0080;
398			value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF;
399			break;
400		case REG_SOUNDBIAS:
401			GBAAudioWriteSOUNDBIAS(&gba->audio, value);
402			break;
403
404		case REG_WAVE_RAM0_LO:
405		case REG_WAVE_RAM1_LO:
406		case REG_WAVE_RAM2_LO:
407		case REG_WAVE_RAM3_LO:
408			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
409			break;
410
411		case REG_WAVE_RAM0_HI:
412		case REG_WAVE_RAM1_HI:
413		case REG_WAVE_RAM2_HI:
414		case REG_WAVE_RAM3_HI:
415			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
416			break;
417
418		case REG_FIFO_A_LO:
419		case REG_FIFO_B_LO:
420			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
421			break;
422
423		case REG_FIFO_A_HI:
424		case REG_FIFO_B_HI:
425			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
426			break;
427
428		// DMA
429		case REG_DMA0SAD_LO:
430		case REG_DMA0DAD_LO:
431		case REG_DMA1SAD_LO:
432		case REG_DMA1DAD_LO:
433		case REG_DMA2SAD_LO:
434		case REG_DMA2DAD_LO:
435		case REG_DMA3SAD_LO:
436		case REG_DMA3DAD_LO:
437			GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
438			break;
439
440		case REG_DMA0SAD_HI:
441		case REG_DMA0DAD_HI:
442		case REG_DMA1SAD_HI:
443		case REG_DMA1DAD_HI:
444		case REG_DMA2SAD_HI:
445		case REG_DMA2DAD_HI:
446		case REG_DMA3SAD_HI:
447		case REG_DMA3DAD_HI:
448			GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
449			break;
450
451		case REG_DMA0CNT_LO:
452			GBAMemoryWriteDMACNT_LO(gba, 0, value);
453			break;
454		case REG_DMA0CNT_HI:
455			value = GBAMemoryWriteDMACNT_HI(gba, 0, value);
456			break;
457		case REG_DMA1CNT_LO:
458			GBAMemoryWriteDMACNT_LO(gba, 1, value);
459			break;
460		case REG_DMA1CNT_HI:
461			value = GBAMemoryWriteDMACNT_HI(gba, 1, value);
462			break;
463		case REG_DMA2CNT_LO:
464			GBAMemoryWriteDMACNT_LO(gba, 2, value);
465			break;
466		case REG_DMA2CNT_HI:
467			value = GBAMemoryWriteDMACNT_HI(gba, 2, value);
468			break;
469		case REG_DMA3CNT_LO:
470			GBAMemoryWriteDMACNT_LO(gba, 3, value);
471			break;
472		case REG_DMA3CNT_HI:
473			value = GBAMemoryWriteDMACNT_HI(gba, 3, value);
474			break;
475
476		// Timers
477		case REG_TM0CNT_LO:
478			GBATimerWriteTMCNT_LO(gba, 0, value);
479			return;
480		case REG_TM1CNT_LO:
481			GBATimerWriteTMCNT_LO(gba, 1, value);
482			return;
483		case REG_TM2CNT_LO:
484			GBATimerWriteTMCNT_LO(gba, 2, value);
485			return;
486		case REG_TM3CNT_LO:
487			GBATimerWriteTMCNT_LO(gba, 3, value);
488			return;
489
490		case REG_TM0CNT_HI:
491			value &= 0x00C7;
492			GBATimerWriteTMCNT_HI(gba, 0, value);
493			break;
494		case REG_TM1CNT_HI:
495			value &= 0x00C7;
496			GBATimerWriteTMCNT_HI(gba, 1, value);
497			break;
498		case REG_TM2CNT_HI:
499			value &= 0x00C7;
500			GBATimerWriteTMCNT_HI(gba, 2, value);
501			break;
502		case REG_TM3CNT_HI:
503			value &= 0x00C7;
504			GBATimerWriteTMCNT_HI(gba, 3, value);
505			break;
506
507		// SIO
508		case REG_SIOCNT:
509			GBASIOWriteSIOCNT(&gba->sio, value);
510			break;
511		case REG_RCNT:
512			value &= 0xC1FF;
513			GBASIOWriteRCNT(&gba->sio, value);
514			break;
515		case REG_SIOMLT_SEND:
516			GBASIOWriteSIOMLT_SEND(&gba->sio, value);
517			break;
518
519		// Interrupts and misc
520		case REG_WAITCNT:
521			GBAAdjustWaitstates(gba, value);
522			break;
523		case REG_IE:
524			GBAWriteIE(gba, value);
525			break;
526		case REG_IF:
527			value = gba->memory.io[REG_IF >> 1] & ~value;
528			break;
529		case REG_IME:
530			GBAWriteIME(gba, value);
531			break;
532		case REG_MAX:
533			// Some bad interrupt libraries will write to this
534			break;
535		default:
536			GBALog(gba, GBA_LOG_STUB, "Stub I/O register write: %03X", address);
537			if (address >= REG_MAX) {
538				GBALog(gba, GBA_LOG_GAME_ERROR, "Write to unused I/O register: %03X", address);
539				return;
540			}
541			break;
542		}
543	}
544	gba->memory.io[address >> 1] = value;
545}
546
547void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
548	if (address == REG_HALTCNT) {
549		value &= 0x80;
550		if (!value) {
551			GBAHalt(gba);
552		} else {
553			GBAStop(gba);
554		}
555		return;
556	}
557	uint16_t value16 = value << (8 * (address & 1));
558	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
559	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
560}
561
562void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
563	switch (address) {
564	case REG_WAVE_RAM0_LO:
565		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
566		break;
567	case REG_WAVE_RAM1_LO:
568		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
569		break;
570	case REG_WAVE_RAM2_LO:
571		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
572		break;
573	case REG_WAVE_RAM3_LO:
574		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
575		break;
576	case REG_FIFO_A_LO:
577	case REG_FIFO_B_LO:
578		GBAAudioWriteFIFO(&gba->audio, address, value);
579		break;
580	case REG_DMA0SAD_LO:
581		value = GBAMemoryWriteDMASAD(gba, 0, value);
582		break;
583	case REG_DMA0DAD_LO:
584		value = GBAMemoryWriteDMADAD(gba, 0, value);
585		break;
586	case REG_DMA1SAD_LO:
587		value = GBAMemoryWriteDMASAD(gba, 1, value);
588		break;
589	case REG_DMA1DAD_LO:
590		value = GBAMemoryWriteDMADAD(gba, 1, value);
591		break;
592	case REG_DMA2SAD_LO:
593		value = GBAMemoryWriteDMASAD(gba, 2, value);
594		break;
595	case REG_DMA2DAD_LO:
596		value = GBAMemoryWriteDMADAD(gba, 2, value);
597		break;
598	case REG_DMA3SAD_LO:
599		value = GBAMemoryWriteDMASAD(gba, 3, value);
600		break;
601	case REG_DMA3DAD_LO:
602		value = GBAMemoryWriteDMADAD(gba, 3, value);
603		break;
604	default:
605		GBAIOWrite(gba, address, value & 0xFFFF);
606		GBAIOWrite(gba, address | 2, value >> 16);
607		return;
608	}
609	gba->memory.io[address >> 1] = value;
610	gba->memory.io[(address >> 1) + 1] = value >> 16;
611}
612
613bool GBAIOIsReadConstant(uint32_t address) {
614	switch (address) {
615	default:
616		return false;
617	case REG_BG0CNT:
618	case REG_BG1CNT:
619	case REG_BG2CNT:
620	case REG_BG3CNT:
621	case REG_WININ:
622	case REG_WINOUT:
623	case REG_BLDCNT:
624	case REG_BLDALPHA:
625	case REG_SOUND1CNT_LO:
626	case REG_SOUND1CNT_HI:
627	case REG_SOUND1CNT_X:
628	case REG_SOUND2CNT_LO:
629	case REG_SOUND2CNT_HI:
630	case REG_SOUND3CNT_LO:
631	case REG_SOUND3CNT_HI:
632	case REG_SOUND3CNT_X:
633	case REG_SOUND4CNT_LO:
634	case REG_SOUND4CNT_HI:
635	case REG_SOUNDCNT_LO:
636	case REG_SOUNDCNT_HI:
637	case REG_TM0CNT_HI:
638	case REG_TM1CNT_HI:
639	case REG_TM2CNT_HI:
640	case REG_TM3CNT_HI:
641	case REG_KEYINPUT:
642	case REG_IE:
643		return true;
644	}
645}
646
647uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
648	if (!GBAIOIsReadConstant(address)) {
649		// Most IO reads need to disable idle removal
650		gba->haltPending = false;
651	}
652
653	switch (address) {
654	case REG_TM0CNT_LO:
655		GBATimerUpdateRegister(gba, 0);
656		break;
657	case REG_TM1CNT_LO:
658		GBATimerUpdateRegister(gba, 1);
659		break;
660	case REG_TM2CNT_LO:
661		GBATimerUpdateRegister(gba, 2);
662		break;
663	case REG_TM3CNT_LO:
664		GBATimerUpdateRegister(gba, 3);
665		break;
666
667	case REG_KEYINPUT:
668		if (gba->rr && gba->rr->isPlaying(gba->rr)) {
669			return 0x3FF ^ gba->rr->queryInput(gba->rr);
670		} else {
671			uint16_t input = 0x3FF;
672			if (gba->keyCallback) {
673				input = gba->keyCallback->readKeys(gba->keyCallback);
674			} else if (gba->keySource) {
675				input = *gba->keySource;
676			}
677			if (gba->rr && gba->rr->isRecording(gba->rr)) {
678				gba->rr->logInput(gba->rr, input);
679			}
680			return 0x3FF ^ input;
681		}
682
683	case REG_SIOCNT:
684		return gba->sio.siocnt;
685	case REG_RCNT:
686		return gba->sio.rcnt;
687
688	case REG_BG0HOFS:
689	case REG_BG0VOFS:
690	case REG_BG1HOFS:
691	case REG_BG1VOFS:
692	case REG_BG2HOFS:
693	case REG_BG2VOFS:
694	case REG_BG3HOFS:
695	case REG_BG3VOFS:
696	case REG_BG2PA:
697	case REG_BG2PB:
698	case REG_BG2PC:
699	case REG_BG2PD:
700	case REG_BG2X_LO:
701	case REG_BG2X_HI:
702	case REG_BG2Y_LO:
703	case REG_BG2Y_HI:
704	case REG_BG3PA:
705	case REG_BG3PB:
706	case REG_BG3PC:
707	case REG_BG3PD:
708	case REG_BG3X_LO:
709	case REG_BG3X_HI:
710	case REG_BG3Y_LO:
711	case REG_BG3Y_HI:
712	case REG_WIN0H:
713	case REG_WIN1H:
714	case REG_WIN0V:
715	case REG_WIN1V:
716	case REG_MOSAIC:
717	case REG_BLDY:
718	case REG_FIFO_A_LO:
719	case REG_FIFO_A_HI:
720	case REG_FIFO_B_LO:
721	case REG_FIFO_B_HI:
722	case REG_DMA0SAD_LO:
723	case REG_DMA0SAD_HI:
724	case REG_DMA0DAD_LO:
725	case REG_DMA0DAD_HI:
726	case REG_DMA0CNT_LO:
727	case REG_DMA1SAD_LO:
728	case REG_DMA1SAD_HI:
729	case REG_DMA1DAD_LO:
730	case REG_DMA1DAD_HI:
731	case REG_DMA1CNT_LO:
732	case REG_DMA2SAD_LO:
733	case REG_DMA2SAD_HI:
734	case REG_DMA2DAD_LO:
735	case REG_DMA2DAD_HI:
736	case REG_DMA2CNT_LO:
737	case REG_DMA3SAD_LO:
738	case REG_DMA3SAD_HI:
739	case REG_DMA3DAD_LO:
740	case REG_DMA3DAD_HI:
741	case REG_DMA3CNT_LO:
742		// Write-only register
743		GBALog(gba, GBA_LOG_GAME_ERROR, "Read from write-only I/O register: %03X", address);
744		return GBALoadBad(gba->cpu);
745
746	case REG_SOUNDBIAS:
747	case REG_JOYCNT:
748	case REG_JOY_RECV:
749	case REG_JOY_TRANS:
750	case REG_KEYCNT:
751	case REG_POSTFLG:
752		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
753		break;
754	case REG_SOUND1CNT_LO:
755	case REG_SOUND1CNT_HI:
756	case REG_SOUND1CNT_X:
757	case REG_SOUND2CNT_LO:
758	case REG_SOUND2CNT_HI:
759	case REG_SOUND3CNT_LO:
760	case REG_SOUND3CNT_HI:
761	case REG_SOUND3CNT_X:
762	case REG_SOUND4CNT_LO:
763	case REG_SOUND4CNT_HI:
764	case REG_SOUNDCNT_LO:
765	case REG_SOUNDCNT_HI:
766		if (!GBARegisterSOUNDCNT_XIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
767			// TODO: Is writing allowed when the circuit is disabled?
768			return 0;
769		}
770		// Fall through
771	case REG_DISPCNT:
772	case REG_DISPSTAT:
773	case REG_VCOUNT:
774	case REG_BG0CNT:
775	case REG_BG1CNT:
776	case REG_BG2CNT:
777	case REG_BG3CNT:
778	case REG_WININ:
779	case REG_WINOUT:
780	case REG_BLDCNT:
781	case REG_BLDALPHA:
782	case REG_SOUNDCNT_X:
783	case REG_WAVE_RAM0_LO:
784	case REG_WAVE_RAM0_HI:
785	case REG_WAVE_RAM1_LO:
786	case REG_WAVE_RAM1_HI:
787	case REG_WAVE_RAM2_LO:
788	case REG_WAVE_RAM2_HI:
789	case REG_WAVE_RAM3_LO:
790	case REG_WAVE_RAM3_HI:
791	case REG_DMA0CNT_HI:
792	case REG_DMA1CNT_HI:
793	case REG_DMA2CNT_HI:
794	case REG_DMA3CNT_HI:
795	case REG_SIOMULTI0:
796	case REG_SIOMULTI1:
797	case REG_SIOMULTI2:
798	case REG_SIOMULTI3:
799	case REG_SIOMLT_SEND:
800	case REG_IE:
801	case REG_IF:
802	case REG_WAITCNT:
803	case REG_IME:
804		// Handled transparently by registers
805		break;
806	case REG_MAX:
807		// Some bad interrupt libraries will read from this
808		break;
809	default:
810		GBALog(gba, GBA_LOG_GAME_ERROR, "Read from unused I/O register: %03X", address);
811		return GBALoadBad(gba->cpu);
812	}
813	return gba->memory.io[address >> 1];
814}
815
816void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
817	int i;
818	for (i = 0; i < REG_MAX; i += 2) {
819		if (_isRSpecialRegister[i >> 1]) {
820			STORE_16(gba->memory.io[i >> 1], i, state->io);
821		} else if (_isValidRegister[i >> 1]) {
822			uint16_t reg = GBAIORead(gba, i);
823			STORE_16(reg, i, state->io);
824		}
825	}
826
827	for (i = 0; i < 4; ++i) {
828		STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
829		STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
830		STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
831		STORE_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
832		STORE_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
833		STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
834		STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
835		STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
836		STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
837		STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
838		STORE_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
839	}
840
841	GBAHardwareSerialize(&gba->memory.hw, state);
842}
843
844void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
845	int i;
846	for (i = 0; i < REG_MAX; i += 2) {
847		if (_isWSpecialRegister[i >> 1]) {
848			LOAD_16(gba->memory.io[i >> 1], i, state->io);
849		} else if (_isValidRegister[i >> 1]) {
850			uint16_t reg;
851			LOAD_16(reg, i, state->io);
852			GBAIOWrite(gba, i, reg);
853		}
854	}
855
856	gba->timersEnabled = 0;
857	for (i = 0; i < 4; ++i) {
858		LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
859		LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
860		LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
861		LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
862		LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
863		LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
864		LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
865		LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
866		LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
867		LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
868		LOAD_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
869		if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
870			GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
871		}
872
873		if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
874			gba->timersEnabled |= 1 << i;
875		}
876	}
877	GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
878	GBAMemoryUpdateDMAs(gba, 0);
879	GBAHardwareDeserialize(&gba->memory.hw, state);
880}