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