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