all repos — mgba @ 4edd7286f39fe940a890394626567211e072badb

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->allowOpposingDirections) {
678				unsigned rl = input & 0x030;
679				unsigned ud = input & 0x0C0;
680				input &= 0x30F;
681				if (rl != 0x030) {
682					input |= rl;
683				}
684				if (ud != 0x0C0) {
685					input |= ud;
686				}
687			}
688			if (gba->rr && gba->rr->isRecording(gba->rr)) {
689				gba->rr->logInput(gba->rr, input);
690			}
691			return 0x3FF ^ input;
692		}
693
694	case REG_SIOCNT:
695		return gba->sio.siocnt;
696	case REG_RCNT:
697		return gba->sio.rcnt;
698
699	case REG_BG0HOFS:
700	case REG_BG0VOFS:
701	case REG_BG1HOFS:
702	case REG_BG1VOFS:
703	case REG_BG2HOFS:
704	case REG_BG2VOFS:
705	case REG_BG3HOFS:
706	case REG_BG3VOFS:
707	case REG_BG2PA:
708	case REG_BG2PB:
709	case REG_BG2PC:
710	case REG_BG2PD:
711	case REG_BG2X_LO:
712	case REG_BG2X_HI:
713	case REG_BG2Y_LO:
714	case REG_BG2Y_HI:
715	case REG_BG3PA:
716	case REG_BG3PB:
717	case REG_BG3PC:
718	case REG_BG3PD:
719	case REG_BG3X_LO:
720	case REG_BG3X_HI:
721	case REG_BG3Y_LO:
722	case REG_BG3Y_HI:
723	case REG_WIN0H:
724	case REG_WIN1H:
725	case REG_WIN0V:
726	case REG_WIN1V:
727	case REG_MOSAIC:
728	case REG_BLDY:
729	case REG_FIFO_A_LO:
730	case REG_FIFO_A_HI:
731	case REG_FIFO_B_LO:
732	case REG_FIFO_B_HI:
733	case REG_DMA0SAD_LO:
734	case REG_DMA0SAD_HI:
735	case REG_DMA0DAD_LO:
736	case REG_DMA0DAD_HI:
737	case REG_DMA0CNT_LO:
738	case REG_DMA1SAD_LO:
739	case REG_DMA1SAD_HI:
740	case REG_DMA1DAD_LO:
741	case REG_DMA1DAD_HI:
742	case REG_DMA1CNT_LO:
743	case REG_DMA2SAD_LO:
744	case REG_DMA2SAD_HI:
745	case REG_DMA2DAD_LO:
746	case REG_DMA2DAD_HI:
747	case REG_DMA2CNT_LO:
748	case REG_DMA3SAD_LO:
749	case REG_DMA3SAD_HI:
750	case REG_DMA3DAD_LO:
751	case REG_DMA3DAD_HI:
752	case REG_DMA3CNT_LO:
753		// Write-only register
754		GBALog(gba, GBA_LOG_GAME_ERROR, "Read from write-only I/O register: %03X", address);
755		return GBALoadBad(gba->cpu);
756
757	case REG_SOUNDBIAS:
758	case REG_JOYCNT:
759	case REG_JOY_RECV:
760	case REG_JOY_TRANS:
761	case REG_KEYCNT:
762	case REG_POSTFLG:
763		GBALog(gba, GBA_LOG_STUB, "Stub I/O register read: %03x", address);
764		break;
765	case REG_SOUND1CNT_LO:
766	case REG_SOUND1CNT_HI:
767	case REG_SOUND1CNT_X:
768	case REG_SOUND2CNT_LO:
769	case REG_SOUND2CNT_HI:
770	case REG_SOUND3CNT_LO:
771	case REG_SOUND3CNT_HI:
772	case REG_SOUND3CNT_X:
773	case REG_SOUND4CNT_LO:
774	case REG_SOUND4CNT_HI:
775	case REG_SOUNDCNT_LO:
776	case REG_SOUNDCNT_HI:
777		if (!GBARegisterSOUNDCNT_XIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
778			// TODO: Is writing allowed when the circuit is disabled?
779			return 0;
780		}
781		// Fall through
782	case REG_DISPCNT:
783	case REG_DISPSTAT:
784	case REG_VCOUNT:
785	case REG_BG0CNT:
786	case REG_BG1CNT:
787	case REG_BG2CNT:
788	case REG_BG3CNT:
789	case REG_WININ:
790	case REG_WINOUT:
791	case REG_BLDCNT:
792	case REG_BLDALPHA:
793	case REG_SOUNDCNT_X:
794	case REG_WAVE_RAM0_LO:
795	case REG_WAVE_RAM0_HI:
796	case REG_WAVE_RAM1_LO:
797	case REG_WAVE_RAM1_HI:
798	case REG_WAVE_RAM2_LO:
799	case REG_WAVE_RAM2_HI:
800	case REG_WAVE_RAM3_LO:
801	case REG_WAVE_RAM3_HI:
802	case REG_DMA0CNT_HI:
803	case REG_DMA1CNT_HI:
804	case REG_DMA2CNT_HI:
805	case REG_DMA3CNT_HI:
806	case REG_TM0CNT_HI:
807	case REG_TM1CNT_HI:
808	case REG_TM2CNT_HI:
809	case REG_TM3CNT_HI:
810	case REG_SIOMULTI0:
811	case REG_SIOMULTI1:
812	case REG_SIOMULTI2:
813	case REG_SIOMULTI3:
814	case REG_SIOMLT_SEND:
815	case REG_IE:
816	case REG_IF:
817	case REG_WAITCNT:
818	case REG_IME:
819		// Handled transparently by registers
820		break;
821	case REG_MAX:
822		// Some bad interrupt libraries will read from this
823		break;
824	default:
825		GBALog(gba, GBA_LOG_GAME_ERROR, "Read from unused I/O register: %03X", address);
826		return GBALoadBad(gba->cpu);
827	}
828	return gba->memory.io[address >> 1];
829}
830
831void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
832	int i;
833	for (i = 0; i < REG_MAX; i += 2) {
834		if (_isRSpecialRegister[i >> 1]) {
835			STORE_16(gba->memory.io[i >> 1], i, state->io);
836		} else if (_isValidRegister[i >> 1]) {
837			uint16_t reg = GBAIORead(gba, i);
838			STORE_16(reg, i, state->io);
839		}
840	}
841
842	for (i = 0; i < 4; ++i) {
843		STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
844		STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
845		STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
846		STORE_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
847		STORE_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
848		STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
849		STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
850		STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
851		STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
852		STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
853		STORE_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
854	}
855
856	GBAHardwareSerialize(&gba->memory.hw, state);
857}
858
859void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
860	int i;
861	for (i = 0; i < REG_MAX; i += 2) {
862		if (_isWSpecialRegister[i >> 1]) {
863			LOAD_16(gba->memory.io[i >> 1], i, state->io);
864		} else if (_isValidRegister[i >> 1]) {
865			uint16_t reg;
866			LOAD_16(reg, i, state->io);
867			GBAIOWrite(gba, i, reg);
868		}
869	}
870
871	gba->timersEnabled = 0;
872	for (i = 0; i < 4; ++i) {
873		LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
874		LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
875		LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
876		LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
877		LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
878		LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
879		LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
880		LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
881		LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
882		LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
883		LOAD_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
884		if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
885			GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
886		}
887
888		if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
889			gba->timersEnabled |= 1 << i;
890		}
891	}
892	GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
893	GBAMemoryUpdateDMAs(gba, 0);
894	GBAHardwareDeserialize(&gba->memory.hw, state);
895}