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