all repos — mgba @ cb0f95b07053e63e817bd05df0a36bf917667d09

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, 1, 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);
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);
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);
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->timers[0], value);
491			return;
492		case REG_TM1CNT_LO:
493			GBATimerWriteTMCNT_LO(&gba->timers[1], value);
494			return;
495		case REG_TM2CNT_LO:
496			GBATimerWriteTMCNT_LO(&gba->timers[2], value);
497			return;
498		case REG_TM3CNT_LO:
499			GBATimerWriteTMCNT_LO(&gba->timers[3], value);
500			return;
501
502		case REG_TM0CNT_HI:
503			value &= 0x00C7;
504			GBATimerUpdateRegister(gba, 0);
505			GBATimerWriteTMCNT_HI(&gba->timers[0], &gba->timing, gba->cpu, &gba->memory.io[REG_TM0CNT_LO >> 1], value);
506			break;
507		case REG_TM1CNT_HI:
508			value &= 0x00C7;
509			GBATimerUpdateRegister(gba, 1);
510			GBATimerWriteTMCNT_HI(&gba->timers[1], &gba->timing, gba->cpu, &gba->memory.io[REG_TM1CNT_LO >> 1], value);
511			break;
512		case REG_TM2CNT_HI:
513			value &= 0x00C7;
514			GBATimerUpdateRegister(gba, 2);
515			GBATimerWriteTMCNT_HI(&gba->timers[2], &gba->timing, gba->cpu, &gba->memory.io[REG_TM2CNT_LO >> 1], value);
516			break;
517		case REG_TM3CNT_HI:
518			value &= 0x00C7;
519			GBATimerUpdateRegister(gba, 3);
520			GBATimerWriteTMCNT_HI(&gba->timers[3], &gba->timing, gba->cpu, &gba->memory.io[REG_TM3CNT_LO >> 1], value);
521			break;
522
523		// SIO
524		case REG_SIOCNT:
525			GBASIOWriteSIOCNT(&gba->sio, value);
526			break;
527		case REG_RCNT:
528			value &= 0xC1FF;
529			GBASIOWriteRCNT(&gba->sio, value);
530			break;
531		case REG_JOY_TRANS_LO:
532		case REG_JOY_TRANS_HI:
533			gba->memory.io[REG_JOYSTAT >> 1] |= JOYSTAT_TRANS_BIT;
534			// Fall through
535		case REG_SIOMLT_SEND:
536		case REG_JOYCNT:
537		case REG_JOYSTAT:
538		case REG_JOY_RECV_LO:
539		case REG_JOY_RECV_HI:
540			value = GBASIOWriteRegister(&gba->sio, address, value);
541			break;
542
543		// Interrupts and misc
544		case REG_WAITCNT:
545			value &= 0x5FFF;
546			GBAAdjustWaitstates(gba, value);
547			break;
548		case REG_IE:
549			GBAWriteIE(gba, value);
550			break;
551		case REG_IF:
552			gba->springIRQ &= ~value;
553			value = gba->memory.io[REG_IF >> 1] & ~value;
554			break;
555		case REG_IME:
556			GBAWriteIME(gba, value);
557			break;
558		case REG_MAX:
559			// Some bad interrupt libraries will write to this
560			break;
561		case REG_DEBUG_ENABLE:
562			gba->debug = value == 0xC0DE;
563			return;
564		case REG_DEBUG_FLAGS:
565			if (gba->debug) {
566				GBADebug(gba, value);
567				return;
568			}
569			// Fall through
570		default:
571			if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
572				STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
573				return;
574			}
575			mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
576			if (address >= REG_MAX) {
577				mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
578				return;
579			}
580			break;
581		}
582	}
583	gba->memory.io[address >> 1] = value;
584}
585
586void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
587	if (address == REG_HALTCNT) {
588		value &= 0x80;
589		if (!value) {
590			GBAHalt(gba);
591		} else {
592			GBAStop(gba);
593		}
594		return;
595	}
596	if (address == REG_POSTFLG) {
597		gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
598		return;
599	}
600	if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
601		gba->debugString[address - REG_DEBUG_STRING] = value;
602		return;
603	}
604	if (address > SIZE_IO) {
605		return;
606	}
607	uint16_t value16 = value << (8 * (address & 1));
608	value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
609	GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
610}
611
612void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
613	switch (address) {
614	case REG_WAVE_RAM0_LO:
615		GBAAudioWriteWaveRAM(&gba->audio, 0, value);
616		break;
617	case REG_WAVE_RAM1_LO:
618		GBAAudioWriteWaveRAM(&gba->audio, 1, value);
619		break;
620	case REG_WAVE_RAM2_LO:
621		GBAAudioWriteWaveRAM(&gba->audio, 2, value);
622		break;
623	case REG_WAVE_RAM3_LO:
624		GBAAudioWriteWaveRAM(&gba->audio, 3, value);
625		break;
626	case REG_FIFO_A_LO:
627	case REG_FIFO_B_LO:
628		GBAAudioWriteFIFO(&gba->audio, address, value);
629		break;
630	case REG_DMA0SAD_LO:
631		value = GBADMAWriteSAD(gba, 0, value);
632		break;
633	case REG_DMA0DAD_LO:
634		value = GBADMAWriteDAD(gba, 0, value);
635		break;
636	case REG_DMA1SAD_LO:
637		value = GBADMAWriteSAD(gba, 1, value);
638		break;
639	case REG_DMA1DAD_LO:
640		value = GBADMAWriteDAD(gba, 1, value);
641		break;
642	case REG_DMA2SAD_LO:
643		value = GBADMAWriteSAD(gba, 2, value);
644		break;
645	case REG_DMA2DAD_LO:
646		value = GBADMAWriteDAD(gba, 2, value);
647		break;
648	case REG_DMA3SAD_LO:
649		value = GBADMAWriteSAD(gba, 3, value);
650		break;
651	case REG_DMA3DAD_LO:
652		value = GBADMAWriteDAD(gba, 3, value);
653		break;
654	default:
655		if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
656			STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
657			return;
658		}
659		GBAIOWrite(gba, address, value & 0xFFFF);
660		GBAIOWrite(gba, address | 2, value >> 16);
661		return;
662	}
663	gba->memory.io[address >> 1] = value;
664	gba->memory.io[(address >> 1) + 1] = value >> 16;
665}
666
667bool GBAIOIsReadConstant(uint32_t address) {
668	switch (address) {
669	default:
670		return false;
671	case REG_BG0CNT:
672	case REG_BG1CNT:
673	case REG_BG2CNT:
674	case REG_BG3CNT:
675	case REG_WININ:
676	case REG_WINOUT:
677	case REG_BLDCNT:
678	case REG_BLDALPHA:
679	case REG_SOUND1CNT_LO:
680	case REG_SOUND1CNT_HI:
681	case REG_SOUND1CNT_X:
682	case REG_SOUND2CNT_LO:
683	case REG_SOUND2CNT_HI:
684	case REG_SOUND3CNT_LO:
685	case REG_SOUND3CNT_HI:
686	case REG_SOUND3CNT_X:
687	case REG_SOUND4CNT_LO:
688	case REG_SOUND4CNT_HI:
689	case REG_SOUNDCNT_LO:
690	case REG_SOUNDCNT_HI:
691	case REG_TM0CNT_HI:
692	case REG_TM1CNT_HI:
693	case REG_TM2CNT_HI:
694	case REG_TM3CNT_HI:
695	case REG_KEYINPUT:
696	case REG_IE:
697		return true;
698	}
699}
700
701uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
702	if (!GBAIOIsReadConstant(address)) {
703		// Most IO reads need to disable idle removal
704		gba->haltPending = false;
705	}
706
707	switch (address) {
708	case REG_TM0CNT_LO:
709		GBATimerUpdateRegister(gba, 0);
710		break;
711	case REG_TM1CNT_LO:
712		GBATimerUpdateRegister(gba, 1);
713		break;
714	case REG_TM2CNT_LO:
715		GBATimerUpdateRegister(gba, 2);
716		break;
717	case REG_TM3CNT_LO:
718		GBATimerUpdateRegister(gba, 3);
719		break;
720
721	case REG_KEYINPUT:
722		if (gba->rr && gba->rr->isPlaying(gba->rr)) {
723			return 0x3FF ^ gba->rr->queryInput(gba->rr);
724		} else {
725			uint16_t input = 0x3FF;
726			if (gba->keyCallback) {
727				input = gba->keyCallback->readKeys(gba->keyCallback);
728			} else if (gba->keySource) {
729				input = *gba->keySource;
730			}
731			if (!gba->allowOpposingDirections) {
732				unsigned rl = input & 0x030;
733				unsigned ud = input & 0x0C0;
734				input &= 0x30F;
735				if (rl != 0x030) {
736					input |= rl;
737				}
738				if (ud != 0x0C0) {
739					input |= ud;
740				}
741			}
742			if (gba->rr && gba->rr->isRecording(gba->rr)) {
743				gba->rr->logInput(gba->rr, input);
744			}
745			return 0x3FF ^ input;
746		}
747
748	case REG_SIOCNT:
749		return gba->sio.siocnt;
750	case REG_RCNT:
751		return gba->sio.rcnt;
752
753	case REG_BG0HOFS:
754	case REG_BG0VOFS:
755	case REG_BG1HOFS:
756	case REG_BG1VOFS:
757	case REG_BG2HOFS:
758	case REG_BG2VOFS:
759	case REG_BG3HOFS:
760	case REG_BG3VOFS:
761	case REG_BG2PA:
762	case REG_BG2PB:
763	case REG_BG2PC:
764	case REG_BG2PD:
765	case REG_BG2X_LO:
766	case REG_BG2X_HI:
767	case REG_BG2Y_LO:
768	case REG_BG2Y_HI:
769	case REG_BG3PA:
770	case REG_BG3PB:
771	case REG_BG3PC:
772	case REG_BG3PD:
773	case REG_BG3X_LO:
774	case REG_BG3X_HI:
775	case REG_BG3Y_LO:
776	case REG_BG3Y_HI:
777	case REG_WIN0H:
778	case REG_WIN1H:
779	case REG_WIN0V:
780	case REG_WIN1V:
781	case REG_MOSAIC:
782	case REG_BLDY:
783	case REG_FIFO_A_LO:
784	case REG_FIFO_A_HI:
785	case REG_FIFO_B_LO:
786	case REG_FIFO_B_HI:
787	case REG_DMA0SAD_LO:
788	case REG_DMA0SAD_HI:
789	case REG_DMA0DAD_LO:
790	case REG_DMA0DAD_HI:
791	case REG_DMA1SAD_LO:
792	case REG_DMA1SAD_HI:
793	case REG_DMA1DAD_LO:
794	case REG_DMA1DAD_HI:
795	case REG_DMA2SAD_LO:
796	case REG_DMA2SAD_HI:
797	case REG_DMA2DAD_LO:
798	case REG_DMA2DAD_HI:
799	case REG_DMA3SAD_LO:
800	case REG_DMA3SAD_HI:
801	case REG_DMA3DAD_LO:
802	case REG_DMA3DAD_HI:
803		// Write-only register
804		mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
805		return GBALoadBad(gba->cpu);
806
807	case REG_DMA0CNT_LO:
808	case REG_DMA1CNT_LO:
809	case REG_DMA2CNT_LO:
810	case REG_DMA3CNT_LO:
811		// Write-only register
812		mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
813		return 0;
814
815	case REG_JOY_RECV_LO:
816	case REG_JOY_RECV_HI:
817		gba->memory.io[REG_JOYSTAT >> 1] &= ~JOYSTAT_RECV_BIT;
818		break;
819
820	case REG_SOUNDBIAS:
821	case REG_KEYCNT:
822	case REG_POSTFLG:
823		mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
824		break;
825	case REG_SOUND1CNT_LO:
826	case REG_SOUND1CNT_HI:
827	case REG_SOUND1CNT_X:
828	case REG_SOUND2CNT_LO:
829	case REG_SOUND2CNT_HI:
830	case REG_SOUND3CNT_LO:
831	case REG_SOUND3CNT_HI:
832	case REG_SOUND3CNT_X:
833	case REG_SOUND4CNT_LO:
834	case REG_SOUND4CNT_HI:
835	case REG_SOUNDCNT_LO:
836	case REG_SOUNDCNT_HI:
837		if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
838			// TODO: Is writing allowed when the circuit is disabled?
839			return 0;
840		}
841		// Fall through
842	case REG_DISPCNT:
843	case REG_DISPSTAT:
844	case REG_VCOUNT:
845	case REG_BG0CNT:
846	case REG_BG1CNT:
847	case REG_BG2CNT:
848	case REG_BG3CNT:
849	case REG_WININ:
850	case REG_WINOUT:
851	case REG_BLDCNT:
852	case REG_BLDALPHA:
853	case REG_SOUNDCNT_X:
854	case REG_WAVE_RAM0_LO:
855	case REG_WAVE_RAM0_HI:
856	case REG_WAVE_RAM1_LO:
857	case REG_WAVE_RAM1_HI:
858	case REG_WAVE_RAM2_LO:
859	case REG_WAVE_RAM2_HI:
860	case REG_WAVE_RAM3_LO:
861	case REG_WAVE_RAM3_HI:
862	case REG_DMA0CNT_HI:
863	case REG_DMA1CNT_HI:
864	case REG_DMA2CNT_HI:
865	case REG_DMA3CNT_HI:
866	case REG_TM0CNT_HI:
867	case REG_TM1CNT_HI:
868	case REG_TM2CNT_HI:
869	case REG_TM3CNT_HI:
870	case REG_SIOMULTI0:
871	case REG_SIOMULTI1:
872	case REG_SIOMULTI2:
873	case REG_SIOMULTI3:
874	case REG_SIOMLT_SEND:
875	case REG_JOYCNT:
876	case REG_JOY_TRANS_LO:
877	case REG_JOY_TRANS_HI:
878	case REG_JOYSTAT:
879	case REG_IE:
880	case REG_IF:
881	case REG_WAITCNT:
882	case REG_IME:
883		// Handled transparently by registers
884		break;
885	case REG_MAX:
886		// Some bad interrupt libraries will read from this
887		break;
888	case 0x66:
889	case 0x6E:
890	case 0x76:
891	case 0x7A:
892	case 0x7E:
893	case 0x86:
894	case 0x8A:
895		mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
896		return 0;
897	case REG_DEBUG_ENABLE:
898		if (gba->debug) {
899			return 0x1DEA;
900		}
901		// Fall through
902	default:
903		mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
904		return GBALoadBad(gba->cpu);
905	}
906	return gba->memory.io[address >> 1];
907}
908
909void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
910	int i;
911	for (i = 0; i < REG_MAX; i += 2) {
912		if (_isRSpecialRegister[i >> 1]) {
913			STORE_16(gba->memory.io[i >> 1], i, state->io);
914		} else if (_isValidRegister[i >> 1]) {
915			uint16_t reg = GBAIORead(gba, i);
916			STORE_16(reg, i, state->io);
917		}
918	}
919
920	for (i = 0; i < 4; ++i) {
921		STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
922		STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
923		STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
924		STORE_32(gba->timers[i].lastEvent - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].lastEvent);
925		STORE_32(gba->timers[i].event.when - mTimingCurrentTime(&gba->timing), 0, &state->timers[i].nextEvent);
926		STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
927		STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
928		STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
929		STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
930		STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
931		STORE_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
932	}
933
934	GBAHardwareSerialize(&gba->memory.hw, state);
935}
936
937void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
938	int i;
939	for (i = 0; i < REG_MAX; i += 2) {
940		if (_isWSpecialRegister[i >> 1]) {
941			LOAD_16(gba->memory.io[i >> 1], i, state->io);
942		} else if (_isValidRegister[i >> 1]) {
943			uint16_t reg;
944			LOAD_16(reg, i, state->io);
945			GBAIOWrite(gba, i, reg);
946		}
947	}
948
949	uint32_t when;
950	for (i = 0; i < 4; ++i) {
951		LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
952		LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
953		LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
954		LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
955		if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
956			// Overwrite invalid values in savestate
957			gba->timers[i].lastEvent = 0;
958		} else {
959			LOAD_32(when, 0, &state->timers[i].lastEvent);
960			gba->timers[i].lastEvent = when + mTimingCurrentTime(&gba->timing);
961		}
962		LOAD_32(when, 0, &state->timers[i].nextEvent);
963		if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
964			mTimingSchedule(&gba->timing, &gba->timers[i].event, when);
965		}
966
967		LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
968		LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
969		LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
970		LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
971		LOAD_32(gba->memory.dma[i].when, 0, &state->dma[i].when);
972		if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
973			GBADMASchedule(gba, i, &gba->memory.dma[i]);
974		}
975	}
976	GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
977	GBADMAUpdate(gba);
978	GBAHardwareDeserialize(&gba->memory.hw, state);
979}