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}