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