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_DMA1SAD_LO:
746 case REG_DMA1SAD_HI:
747 case REG_DMA1DAD_LO:
748 case REG_DMA1DAD_HI:
749 case REG_DMA2SAD_LO:
750 case REG_DMA2SAD_HI:
751 case REG_DMA2DAD_LO:
752 case REG_DMA2DAD_HI:
753 case REG_DMA3SAD_LO:
754 case REG_DMA3SAD_HI:
755 case REG_DMA3DAD_LO:
756 case REG_DMA3DAD_HI:
757 // Write-only register
758 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
759 return GBALoadBad(gba->cpu);
760
761 case REG_DMA0CNT_LO:
762 case REG_DMA1CNT_LO:
763 case REG_DMA2CNT_LO:
764 case REG_DMA3CNT_LO:
765 // Write-only register
766 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
767 return 0;
768
769 case REG_SOUNDBIAS:
770 case REG_KEYCNT:
771 case REG_POSTFLG:
772 mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
773 break;
774 case REG_SOUND1CNT_LO:
775 case REG_SOUND1CNT_HI:
776 case REG_SOUND1CNT_X:
777 case REG_SOUND2CNT_LO:
778 case REG_SOUND2CNT_HI:
779 case REG_SOUND3CNT_LO:
780 case REG_SOUND3CNT_HI:
781 case REG_SOUND3CNT_X:
782 case REG_SOUND4CNT_LO:
783 case REG_SOUND4CNT_HI:
784 case REG_SOUNDCNT_LO:
785 case REG_SOUNDCNT_HI:
786 if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
787 // TODO: Is writing allowed when the circuit is disabled?
788 return 0;
789 }
790 // Fall through
791 case REG_DISPCNT:
792 case REG_DISPSTAT:
793 case REG_VCOUNT:
794 case REG_BG0CNT:
795 case REG_BG1CNT:
796 case REG_BG2CNT:
797 case REG_BG3CNT:
798 case REG_WININ:
799 case REG_WINOUT:
800 case REG_BLDCNT:
801 case REG_BLDALPHA:
802 case REG_SOUNDCNT_X:
803 case REG_WAVE_RAM0_LO:
804 case REG_WAVE_RAM0_HI:
805 case REG_WAVE_RAM1_LO:
806 case REG_WAVE_RAM1_HI:
807 case REG_WAVE_RAM2_LO:
808 case REG_WAVE_RAM2_HI:
809 case REG_WAVE_RAM3_LO:
810 case REG_WAVE_RAM3_HI:
811 case REG_DMA0CNT_HI:
812 case REG_DMA1CNT_HI:
813 case REG_DMA2CNT_HI:
814 case REG_DMA3CNT_HI:
815 case REG_TM0CNT_HI:
816 case REG_TM1CNT_HI:
817 case REG_TM2CNT_HI:
818 case REG_TM3CNT_HI:
819 case REG_SIOMULTI0:
820 case REG_SIOMULTI1:
821 case REG_SIOMULTI2:
822 case REG_SIOMULTI3:
823 case REG_SIOMLT_SEND:
824 case REG_JOYCNT:
825 case REG_JOY_RECV_LO:
826 case REG_JOY_RECV_HI:
827 case REG_JOY_TRANS_LO:
828 case REG_JOY_TRANS_HI:
829 case REG_JOYSTAT:
830 case REG_IE:
831 case REG_IF:
832 case REG_WAITCNT:
833 case REG_IME:
834 // Handled transparently by registers
835 break;
836 case REG_MAX:
837 // Some bad interrupt libraries will read from this
838 break;
839 case 0x66:
840 case 0x6E:
841 case 0x76:
842 case 0x7A:
843 case 0x7E:
844 case 0x86:
845 case 0x8A:
846 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
847 return 0;
848 default:
849 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
850 return GBALoadBad(gba->cpu);
851 }
852 return gba->memory.io[address >> 1];
853}
854
855void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
856 int i;
857 for (i = 0; i < REG_MAX; i += 2) {
858 if (_isRSpecialRegister[i >> 1]) {
859 STORE_16(gba->memory.io[i >> 1], i, state->io);
860 } else if (_isValidRegister[i >> 1]) {
861 uint16_t reg = GBAIORead(gba, i);
862 STORE_16(reg, i, state->io);
863 }
864 }
865
866 for (i = 0; i < 4; ++i) {
867 STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
868 STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
869 STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
870 STORE_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
871 STORE_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
872 STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
873 STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
874 STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
875 STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
876 STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
877 STORE_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
878 }
879
880 GBAHardwareSerialize(&gba->memory.hw, state);
881}
882
883void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
884 int i;
885 for (i = 0; i < REG_MAX; i += 2) {
886 if (_isWSpecialRegister[i >> 1]) {
887 LOAD_16(gba->memory.io[i >> 1], i, state->io);
888 } else if (_isValidRegister[i >> 1]) {
889 uint16_t reg;
890 LOAD_16(reg, i, state->io);
891 GBAIOWrite(gba, i, reg);
892 }
893 }
894
895 gba->timersEnabled = 0;
896 for (i = 0; i < 4; ++i) {
897 LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
898 LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
899 LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
900 LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
901 if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
902 // Overwrite invalid values in savestate
903 gba->timers[i].lastEvent = 0;
904 gba->timers[i].nextEvent = INT_MAX;
905 } else {
906 LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
907 LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
908 }
909 LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
910 LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
911 LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
912 LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
913 LOAD_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
914 if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
915 GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
916 }
917
918 if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
919 gba->timersEnabled |= 1 << i;
920 }
921 }
922 GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
923 GBAMemoryUpdateDMAs(gba, 0);
924 GBAHardwareDeserialize(&gba->memory.hw, state);
925}