all repos — mgba @ 37b1cbe29cd0814242168426dec17cf611414f2c

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