all repos — mgba @ e6b4144ba21fc63a774f17fc2804948fd8bd1f36

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