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 if (!gba->biosVf) {
338 gba->memory.io[REG_VCOUNT >> 1] = 0x7E;
339 gba->memory.io[REG_POSTFLG >> 1] = 1;
340 }
341}
342
343void GBAIOWrite(struct GBA* gba, uint32_t address, uint16_t value) {
344 if (address < REG_SOUND1CNT_LO && (address > REG_VCOUNT || address == REG_DISPCNT)) {
345 value = gba->video.renderer->writeVideoRegister(gba->video.renderer, address, value);
346 } else {
347 switch (address) {
348 // Video
349 case REG_DISPSTAT:
350 value &= 0xFFF8;
351 GBAVideoWriteDISPSTAT(&gba->video, value);
352 return;
353
354 case REG_VCOUNT:
355 mLOG(GBA_IO, GAME_ERROR, "Write to read-only I/O register: %03X", address);
356 return;
357
358 // Audio
359 case REG_SOUND1CNT_LO:
360 GBAAudioWriteSOUND1CNT_LO(&gba->audio, value);
361 value &= 0x007F;
362 break;
363 case REG_SOUND1CNT_HI:
364 GBAAudioWriteSOUND1CNT_HI(&gba->audio, value);
365 break;
366 case REG_SOUND1CNT_X:
367 GBAAudioWriteSOUND1CNT_X(&gba->audio, value);
368 value &= 0x47FF;
369 break;
370 case REG_SOUND2CNT_LO:
371 GBAAudioWriteSOUND2CNT_LO(&gba->audio, value);
372 break;
373 case REG_SOUND2CNT_HI:
374 GBAAudioWriteSOUND2CNT_HI(&gba->audio, value);
375 value &= 0x47FF;
376 break;
377 case REG_SOUND3CNT_LO:
378 GBAAudioWriteSOUND3CNT_LO(&gba->audio, value);
379 value &= 0x00E0;
380 break;
381 case REG_SOUND3CNT_HI:
382 GBAAudioWriteSOUND3CNT_HI(&gba->audio, value);
383 value &= 0xE03F;
384 break;
385 case REG_SOUND3CNT_X:
386 GBAAudioWriteSOUND3CNT_X(&gba->audio, value);
387 // TODO: The low bits need to not be readable, but still 8-bit writable
388 value &= 0x47FF;
389 break;
390 case REG_SOUND4CNT_LO:
391 GBAAudioWriteSOUND4CNT_LO(&gba->audio, value);
392 value &= 0xFF3F;
393 break;
394 case REG_SOUND4CNT_HI:
395 GBAAudioWriteSOUND4CNT_HI(&gba->audio, value);
396 value &= 0x40FF;
397 break;
398 case REG_SOUNDCNT_LO:
399 GBAAudioWriteSOUNDCNT_LO(&gba->audio, value);
400 value &= 0xFF77;
401 break;
402 case REG_SOUNDCNT_HI:
403 GBAAudioWriteSOUNDCNT_HI(&gba->audio, value);
404 value &= 0x770F;
405 break;
406 case REG_SOUNDCNT_X:
407 GBAAudioWriteSOUNDCNT_X(&gba->audio, value);
408 value &= 0x0080;
409 value |= gba->memory.io[REG_SOUNDCNT_X >> 1] & 0xF;
410 break;
411 case REG_SOUNDBIAS:
412 GBAAudioWriteSOUNDBIAS(&gba->audio, value);
413 break;
414
415 case REG_WAVE_RAM0_LO:
416 case REG_WAVE_RAM1_LO:
417 case REG_WAVE_RAM2_LO:
418 case REG_WAVE_RAM3_LO:
419 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
420 break;
421
422 case REG_WAVE_RAM0_HI:
423 case REG_WAVE_RAM1_HI:
424 case REG_WAVE_RAM2_HI:
425 case REG_WAVE_RAM3_HI:
426 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
427 break;
428
429 case REG_FIFO_A_LO:
430 case REG_FIFO_B_LO:
431 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
432 break;
433
434 case REG_FIFO_A_HI:
435 case REG_FIFO_B_HI:
436 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
437 break;
438
439 // DMA
440 case REG_DMA0SAD_LO:
441 case REG_DMA0DAD_LO:
442 case REG_DMA1SAD_LO:
443 case REG_DMA1DAD_LO:
444 case REG_DMA2SAD_LO:
445 case REG_DMA2DAD_LO:
446 case REG_DMA3SAD_LO:
447 case REG_DMA3DAD_LO:
448 GBAIOWrite32(gba, address, (gba->memory.io[(address >> 1) + 1] << 16) | value);
449 break;
450
451 case REG_DMA0SAD_HI:
452 case REG_DMA0DAD_HI:
453 case REG_DMA1SAD_HI:
454 case REG_DMA1DAD_HI:
455 case REG_DMA2SAD_HI:
456 case REG_DMA2DAD_HI:
457 case REG_DMA3SAD_HI:
458 case REG_DMA3DAD_HI:
459 GBAIOWrite32(gba, address - 2, gba->memory.io[(address >> 1) - 1] | (value << 16));
460 break;
461
462 case REG_DMA0CNT_LO:
463 GBAMemoryWriteDMACNT_LO(gba, 0, value);
464 break;
465 case REG_DMA0CNT_HI:
466 value = GBAMemoryWriteDMACNT_HI(gba, 0, value);
467 break;
468 case REG_DMA1CNT_LO:
469 GBAMemoryWriteDMACNT_LO(gba, 1, value);
470 break;
471 case REG_DMA1CNT_HI:
472 value = GBAMemoryWriteDMACNT_HI(gba, 1, value);
473 break;
474 case REG_DMA2CNT_LO:
475 GBAMemoryWriteDMACNT_LO(gba, 2, value);
476 break;
477 case REG_DMA2CNT_HI:
478 value = GBAMemoryWriteDMACNT_HI(gba, 2, value);
479 break;
480 case REG_DMA3CNT_LO:
481 GBAMemoryWriteDMACNT_LO(gba, 3, value);
482 break;
483 case REG_DMA3CNT_HI:
484 value = GBAMemoryWriteDMACNT_HI(gba, 3, value);
485 break;
486
487 // Timers
488 case REG_TM0CNT_LO:
489 GBATimerWriteTMCNT_LO(gba, 0, value);
490 return;
491 case REG_TM1CNT_LO:
492 GBATimerWriteTMCNT_LO(gba, 1, value);
493 return;
494 case REG_TM2CNT_LO:
495 GBATimerWriteTMCNT_LO(gba, 2, value);
496 return;
497 case REG_TM3CNT_LO:
498 GBATimerWriteTMCNT_LO(gba, 3, value);
499 return;
500
501 case REG_TM0CNT_HI:
502 value &= 0x00C7;
503 GBATimerWriteTMCNT_HI(gba, 0, value);
504 break;
505 case REG_TM1CNT_HI:
506 value &= 0x00C7;
507 GBATimerWriteTMCNT_HI(gba, 1, value);
508 break;
509 case REG_TM2CNT_HI:
510 value &= 0x00C7;
511 GBATimerWriteTMCNT_HI(gba, 2, value);
512 break;
513 case REG_TM3CNT_HI:
514 value &= 0x00C7;
515 GBATimerWriteTMCNT_HI(gba, 3, value);
516 break;
517
518 // SIO
519 case REG_SIOCNT:
520 GBASIOWriteSIOCNT(&gba->sio, value);
521 break;
522 case REG_RCNT:
523 value &= 0xC1FF;
524 GBASIOWriteRCNT(&gba->sio, value);
525 break;
526 case REG_SIOMLT_SEND:
527 case REG_JOYCNT:
528 case REG_JOYSTAT:
529 case REG_JOY_RECV_LO:
530 case REG_JOY_RECV_HI:
531 case REG_JOY_TRANS_LO:
532 case REG_JOY_TRANS_HI:
533 value = GBASIOWriteRegister(&gba->sio, address, value);
534 break;
535
536 // Interrupts and misc
537 case REG_WAITCNT:
538 GBAAdjustWaitstates(gba, value);
539 break;
540 case REG_IE:
541 GBAWriteIE(gba, value);
542 break;
543 case REG_IF:
544 gba->springIRQ &= ~value;
545 value = gba->memory.io[REG_IF >> 1] & ~value;
546 break;
547 case REG_IME:
548 GBAWriteIME(gba, value);
549 break;
550 case REG_MAX:
551 // Some bad interrupt libraries will write to this
552 break;
553 case REG_DEBUG_ENABLE:
554 gba->debug = value == 0xC0DE;
555 return;
556 case REG_DEBUG_FLAGS:
557 if (gba->debug) {
558 GBADebug(gba, value);
559 return;
560 }
561 // Fall through
562 default:
563 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
564 STORE_16LE(value, address - REG_DEBUG_STRING, gba->debugString);
565 return;
566 }
567 mLOG(GBA_IO, STUB, "Stub I/O register write: %03X", address);
568 if (address >= REG_MAX) {
569 mLOG(GBA_IO, GAME_ERROR, "Write to unused I/O register: %03X", address);
570 return;
571 }
572 break;
573 }
574 }
575 gba->memory.io[address >> 1] = value;
576}
577
578void GBAIOWrite8(struct GBA* gba, uint32_t address, uint8_t value) {
579 if (address == REG_HALTCNT) {
580 value &= 0x80;
581 if (!value) {
582 GBAHalt(gba);
583 } else {
584 GBAStop(gba);
585 }
586 return;
587 }
588 if (address == REG_POSTFLG) {
589 gba->memory.io[(address & (SIZE_IO - 1)) >> 1] = value;
590 return;
591 }
592 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
593 gba->debugString[address - REG_DEBUG_STRING] = value;
594 return;
595 }
596 if (address > SIZE_IO) {
597 return;
598 }
599 uint16_t value16 = value << (8 * (address & 1));
600 value16 |= (gba->memory.io[(address & (SIZE_IO - 1)) >> 1]) & ~(0xFF << (8 * (address & 1)));
601 GBAIOWrite(gba, address & 0xFFFFFFFE, value16);
602}
603
604void GBAIOWrite32(struct GBA* gba, uint32_t address, uint32_t value) {
605 switch (address) {
606 case REG_WAVE_RAM0_LO:
607 GBAAudioWriteWaveRAM(&gba->audio, 0, value);
608 break;
609 case REG_WAVE_RAM1_LO:
610 GBAAudioWriteWaveRAM(&gba->audio, 1, value);
611 break;
612 case REG_WAVE_RAM2_LO:
613 GBAAudioWriteWaveRAM(&gba->audio, 2, value);
614 break;
615 case REG_WAVE_RAM3_LO:
616 GBAAudioWriteWaveRAM(&gba->audio, 3, value);
617 break;
618 case REG_FIFO_A_LO:
619 case REG_FIFO_B_LO:
620 GBAAudioWriteFIFO(&gba->audio, address, value);
621 break;
622 case REG_DMA0SAD_LO:
623 value = GBAMemoryWriteDMASAD(gba, 0, value);
624 break;
625 case REG_DMA0DAD_LO:
626 value = GBAMemoryWriteDMADAD(gba, 0, value);
627 break;
628 case REG_DMA1SAD_LO:
629 value = GBAMemoryWriteDMASAD(gba, 1, value);
630 break;
631 case REG_DMA1DAD_LO:
632 value = GBAMemoryWriteDMADAD(gba, 1, value);
633 break;
634 case REG_DMA2SAD_LO:
635 value = GBAMemoryWriteDMASAD(gba, 2, value);
636 break;
637 case REG_DMA2DAD_LO:
638 value = GBAMemoryWriteDMADAD(gba, 2, value);
639 break;
640 case REG_DMA3SAD_LO:
641 value = GBAMemoryWriteDMASAD(gba, 3, value);
642 break;
643 case REG_DMA3DAD_LO:
644 value = GBAMemoryWriteDMADAD(gba, 3, value);
645 break;
646 default:
647 if (address >= REG_DEBUG_STRING && address - REG_DEBUG_STRING < sizeof(gba->debugString)) {
648 STORE_32LE(value, address - REG_DEBUG_STRING, gba->debugString);
649 return;
650 }
651 GBAIOWrite(gba, address, value & 0xFFFF);
652 GBAIOWrite(gba, address | 2, value >> 16);
653 return;
654 }
655 gba->memory.io[address >> 1] = value;
656 gba->memory.io[(address >> 1) + 1] = value >> 16;
657}
658
659bool GBAIOIsReadConstant(uint32_t address) {
660 switch (address) {
661 default:
662 return false;
663 case REG_BG0CNT:
664 case REG_BG1CNT:
665 case REG_BG2CNT:
666 case REG_BG3CNT:
667 case REG_WININ:
668 case REG_WINOUT:
669 case REG_BLDCNT:
670 case REG_BLDALPHA:
671 case REG_SOUND1CNT_LO:
672 case REG_SOUND1CNT_HI:
673 case REG_SOUND1CNT_X:
674 case REG_SOUND2CNT_LO:
675 case REG_SOUND2CNT_HI:
676 case REG_SOUND3CNT_LO:
677 case REG_SOUND3CNT_HI:
678 case REG_SOUND3CNT_X:
679 case REG_SOUND4CNT_LO:
680 case REG_SOUND4CNT_HI:
681 case REG_SOUNDCNT_LO:
682 case REG_SOUNDCNT_HI:
683 case REG_TM0CNT_HI:
684 case REG_TM1CNT_HI:
685 case REG_TM2CNT_HI:
686 case REG_TM3CNT_HI:
687 case REG_KEYINPUT:
688 case REG_IE:
689 return true;
690 }
691}
692
693uint16_t GBAIORead(struct GBA* gba, uint32_t address) {
694 if (!GBAIOIsReadConstant(address)) {
695 // Most IO reads need to disable idle removal
696 gba->haltPending = false;
697 }
698
699 switch (address) {
700 case REG_TM0CNT_LO:
701 GBATimerUpdateRegister(gba, 0);
702 break;
703 case REG_TM1CNT_LO:
704 GBATimerUpdateRegister(gba, 1);
705 break;
706 case REG_TM2CNT_LO:
707 GBATimerUpdateRegister(gba, 2);
708 break;
709 case REG_TM3CNT_LO:
710 GBATimerUpdateRegister(gba, 3);
711 break;
712
713 case REG_KEYINPUT:
714 if (gba->rr && gba->rr->isPlaying(gba->rr)) {
715 return 0x3FF ^ gba->rr->queryInput(gba->rr);
716 } else {
717 uint16_t input = 0x3FF;
718 if (gba->keyCallback) {
719 input = gba->keyCallback->readKeys(gba->keyCallback);
720 } else if (gba->keySource) {
721 input = *gba->keySource;
722 }
723 if (!gba->allowOpposingDirections) {
724 unsigned rl = input & 0x030;
725 unsigned ud = input & 0x0C0;
726 input &= 0x30F;
727 if (rl != 0x030) {
728 input |= rl;
729 }
730 if (ud != 0x0C0) {
731 input |= ud;
732 }
733 }
734 if (gba->rr && gba->rr->isRecording(gba->rr)) {
735 gba->rr->logInput(gba->rr, input);
736 }
737 return 0x3FF ^ input;
738 }
739
740 case REG_SIOCNT:
741 return gba->sio.siocnt;
742 case REG_RCNT:
743 return gba->sio.rcnt;
744
745 case REG_BG0HOFS:
746 case REG_BG0VOFS:
747 case REG_BG1HOFS:
748 case REG_BG1VOFS:
749 case REG_BG2HOFS:
750 case REG_BG2VOFS:
751 case REG_BG3HOFS:
752 case REG_BG3VOFS:
753 case REG_BG2PA:
754 case REG_BG2PB:
755 case REG_BG2PC:
756 case REG_BG2PD:
757 case REG_BG2X_LO:
758 case REG_BG2X_HI:
759 case REG_BG2Y_LO:
760 case REG_BG2Y_HI:
761 case REG_BG3PA:
762 case REG_BG3PB:
763 case REG_BG3PC:
764 case REG_BG3PD:
765 case REG_BG3X_LO:
766 case REG_BG3X_HI:
767 case REG_BG3Y_LO:
768 case REG_BG3Y_HI:
769 case REG_WIN0H:
770 case REG_WIN1H:
771 case REG_WIN0V:
772 case REG_WIN1V:
773 case REG_MOSAIC:
774 case REG_BLDY:
775 case REG_FIFO_A_LO:
776 case REG_FIFO_A_HI:
777 case REG_FIFO_B_LO:
778 case REG_FIFO_B_HI:
779 case REG_DMA0SAD_LO:
780 case REG_DMA0SAD_HI:
781 case REG_DMA0DAD_LO:
782 case REG_DMA0DAD_HI:
783 case REG_DMA1SAD_LO:
784 case REG_DMA1SAD_HI:
785 case REG_DMA1DAD_LO:
786 case REG_DMA1DAD_HI:
787 case REG_DMA2SAD_LO:
788 case REG_DMA2SAD_HI:
789 case REG_DMA2DAD_LO:
790 case REG_DMA2DAD_HI:
791 case REG_DMA3SAD_LO:
792 case REG_DMA3SAD_HI:
793 case REG_DMA3DAD_LO:
794 case REG_DMA3DAD_HI:
795 // Write-only register
796 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
797 return GBALoadBad(gba->cpu);
798
799 case REG_DMA0CNT_LO:
800 case REG_DMA1CNT_LO:
801 case REG_DMA2CNT_LO:
802 case REG_DMA3CNT_LO:
803 // Write-only register
804 mLOG(GBA_IO, GAME_ERROR, "Read from write-only I/O register: %03X", address);
805 return 0;
806
807 case REG_SOUNDBIAS:
808 case REG_KEYCNT:
809 case REG_POSTFLG:
810 mLOG(GBA_IO, STUB, "Stub I/O register read: %03x", address);
811 break;
812 case REG_SOUND1CNT_LO:
813 case REG_SOUND1CNT_HI:
814 case REG_SOUND1CNT_X:
815 case REG_SOUND2CNT_LO:
816 case REG_SOUND2CNT_HI:
817 case REG_SOUND3CNT_LO:
818 case REG_SOUND3CNT_HI:
819 case REG_SOUND3CNT_X:
820 case REG_SOUND4CNT_LO:
821 case REG_SOUND4CNT_HI:
822 case REG_SOUNDCNT_LO:
823 case REG_SOUNDCNT_HI:
824 if (!GBAudioEnableIsEnable(gba->memory.io[REG_SOUNDCNT_X >> 1])) {
825 // TODO: Is writing allowed when the circuit is disabled?
826 return 0;
827 }
828 // Fall through
829 case REG_DISPCNT:
830 case REG_DISPSTAT:
831 case REG_VCOUNT:
832 case REG_BG0CNT:
833 case REG_BG1CNT:
834 case REG_BG2CNT:
835 case REG_BG3CNT:
836 case REG_WININ:
837 case REG_WINOUT:
838 case REG_BLDCNT:
839 case REG_BLDALPHA:
840 case REG_SOUNDCNT_X:
841 case REG_WAVE_RAM0_LO:
842 case REG_WAVE_RAM0_HI:
843 case REG_WAVE_RAM1_LO:
844 case REG_WAVE_RAM1_HI:
845 case REG_WAVE_RAM2_LO:
846 case REG_WAVE_RAM2_HI:
847 case REG_WAVE_RAM3_LO:
848 case REG_WAVE_RAM3_HI:
849 case REG_DMA0CNT_HI:
850 case REG_DMA1CNT_HI:
851 case REG_DMA2CNT_HI:
852 case REG_DMA3CNT_HI:
853 case REG_TM0CNT_HI:
854 case REG_TM1CNT_HI:
855 case REG_TM2CNT_HI:
856 case REG_TM3CNT_HI:
857 case REG_SIOMULTI0:
858 case REG_SIOMULTI1:
859 case REG_SIOMULTI2:
860 case REG_SIOMULTI3:
861 case REG_SIOMLT_SEND:
862 case REG_JOYCNT:
863 case REG_JOY_RECV_LO:
864 case REG_JOY_RECV_HI:
865 case REG_JOY_TRANS_LO:
866 case REG_JOY_TRANS_HI:
867 case REG_JOYSTAT:
868 case REG_IE:
869 case REG_IF:
870 case REG_WAITCNT:
871 case REG_IME:
872 // Handled transparently by registers
873 break;
874 case REG_MAX:
875 // Some bad interrupt libraries will read from this
876 break;
877 case 0x66:
878 case 0x6E:
879 case 0x76:
880 case 0x7A:
881 case 0x7E:
882 case 0x86:
883 case 0x8A:
884 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
885 return 0;
886 case REG_DEBUG_ENABLE:
887 if (gba->debug) {
888 return 0x1DEA;
889 }
890 // Fall through
891 default:
892 mLOG(GBA_IO, GAME_ERROR, "Read from unused I/O register: %03X", address);
893 return GBALoadBad(gba->cpu);
894 }
895 return gba->memory.io[address >> 1];
896}
897
898void GBAIOSerialize(struct GBA* gba, struct GBASerializedState* state) {
899 int i;
900 for (i = 0; i < REG_MAX; i += 2) {
901 if (_isRSpecialRegister[i >> 1]) {
902 STORE_16(gba->memory.io[i >> 1], i, state->io);
903 } else if (_isValidRegister[i >> 1]) {
904 uint16_t reg = GBAIORead(gba, i);
905 STORE_16(reg, i, state->io);
906 }
907 }
908
909 for (i = 0; i < 4; ++i) {
910 STORE_16(gba->memory.io[(REG_DMA0CNT_LO + i * 12) >> 1], (REG_DMA0CNT_LO + i * 12), state->io);
911 STORE_16(gba->timers[i].reload, 0, &state->timers[i].reload);
912 STORE_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
913 STORE_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
914 STORE_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
915 STORE_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
916 STORE_32(gba->timers[i].flags, 0, &state->timers[i].flags);
917 STORE_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
918 STORE_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
919 STORE_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
920 STORE_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
921 }
922
923 GBAHardwareSerialize(&gba->memory.hw, state);
924}
925
926void GBAIODeserialize(struct GBA* gba, const struct GBASerializedState* state) {
927 int i;
928 for (i = 0; i < REG_MAX; i += 2) {
929 if (_isWSpecialRegister[i >> 1]) {
930 LOAD_16(gba->memory.io[i >> 1], i, state->io);
931 } else if (_isValidRegister[i >> 1]) {
932 uint16_t reg;
933 LOAD_16(reg, i, state->io);
934 GBAIOWrite(gba, i, reg);
935 }
936 }
937
938 gba->timersEnabled = 0;
939 for (i = 0; i < 4; ++i) {
940 LOAD_16(gba->timers[i].reload, 0, &state->timers[i].reload);
941 LOAD_16(gba->timers[i].oldReload, 0, &state->timers[i].oldReload);
942 LOAD_32(gba->timers[i].overflowInterval, 0, &state->timers[i].overflowInterval);
943 LOAD_32(gba->timers[i].flags, 0, &state->timers[i].flags);
944 if (i > 0 && GBATimerFlagsIsCountUp(gba->timers[i].flags)) {
945 // Overwrite invalid values in savestate
946 gba->timers[i].lastEvent = 0;
947 gba->timers[i].nextEvent = INT_MAX;
948 } else {
949 LOAD_32(gba->timers[i].lastEvent, 0, &state->timers[i].lastEvent);
950 LOAD_32(gba->timers[i].nextEvent, 0, &state->timers[i].nextEvent);
951 }
952 LOAD_16(gba->memory.dma[i].reg, (REG_DMA0CNT_HI + i * 12), state->io);
953 LOAD_32(gba->memory.dma[i].nextSource, 0, &state->dma[i].nextSource);
954 LOAD_32(gba->memory.dma[i].nextDest, 0, &state->dma[i].nextDest);
955 LOAD_32(gba->memory.dma[i].nextCount, 0, &state->dma[i].nextCount);
956 LOAD_32(gba->memory.dma[i].nextEvent, 0, &state->dma[i].nextEvent);
957 if (GBADMARegisterGetTiming(gba->memory.dma[i].reg) != DMA_TIMING_NOW) {
958 GBAMemoryScheduleDMA(gba, i, &gba->memory.dma[i]);
959 }
960
961 if (GBATimerFlagsIsEnable(gba->timers[i].flags)) {
962 gba->timersEnabled |= 1 << i;
963 }
964 }
965 GBAAudioWriteSOUNDCNT_X(&gba->audio, gba->memory.io[REG_SOUNDCNT_X >> 1]);
966 GBAMemoryUpdateDMAs(gba, 0);
967 GBAHardwareDeserialize(&gba->memory.hw, state);
968}