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