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