src/gb/io.c (view raw)
1/* Copyright (c) 2013-2016 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 <mgba/internal/gb/io.h>
7
8#include <mgba/internal/gb/gb.h>
9#include <mgba/internal/gb/sio.h>
10#include <mgba/internal/gb/serialize.h>
11
12mLOG_DEFINE_CATEGORY(GB_IO, "GB I/O", "gb.io");
13
14MGBA_EXPORT const char* const GBIORegisterNames[] = {
15 [REG_JOYP] = "JOYP",
16 [REG_SB] = "SB",
17 [REG_SC] = "SC",
18 [REG_DIV] = "DIV",
19 [REG_TIMA] = "TIMA",
20 [REG_TMA] = "TMA",
21 [REG_TAC] = "TAC",
22 [REG_IF] = "IF",
23 [REG_NR10] = "NR10",
24 [REG_NR11] = "NR11",
25 [REG_NR12] = "NR12",
26 [REG_NR13] = "NR13",
27 [REG_NR14] = "NR14",
28 [REG_NR21] = "NR21",
29 [REG_NR22] = "NR22",
30 [REG_NR23] = "NR23",
31 [REG_NR24] = "NR24",
32 [REG_NR30] = "NR30",
33 [REG_NR31] = "NR31",
34 [REG_NR32] = "NR32",
35 [REG_NR33] = "NR33",
36 [REG_NR34] = "NR34",
37 [REG_NR41] = "NR41",
38 [REG_NR42] = "NR42",
39 [REG_NR43] = "NR43",
40 [REG_NR44] = "NR44",
41 [REG_NR50] = "NR50",
42 [REG_NR51] = "NR51",
43 [REG_NR52] = "NR52",
44 [REG_LCDC] = "LCDC",
45 [REG_STAT] = "STAT",
46 [REG_SCY] = "SCY",
47 [REG_SCX] = "SCX",
48 [REG_LY] = "LY",
49 [REG_LYC] = "LYC",
50 [REG_DMA] = "DMA",
51 [REG_BGP] = "BGP",
52 [REG_OBP0] = "OBP0",
53 [REG_OBP1] = "OBP1",
54 [REG_WY] = "WY",
55 [REG_WX] = "WX",
56 [REG_KEY0] = "KEY0",
57 [REG_KEY1] = "KEY1",
58 [REG_VBK] = "VBK",
59 [REG_HDMA1] = "HDMA1",
60 [REG_HDMA2] = "HDMA2",
61 [REG_HDMA3] = "HDMA3",
62 [REG_HDMA4] = "HDMA4",
63 [REG_HDMA5] = "HDMA5",
64 [REG_RP] = "RP",
65 [REG_BCPS] = "BCPS",
66 [REG_BCPD] = "BCPD",
67 [REG_OCPS] = "OCPS",
68 [REG_OCPD] = "OCPD",
69 [REG_OPRI] = "OPRI",
70 [REG_SVBK] = "SVBK",
71 [REG_IE] = "IE",
72};
73
74static const uint8_t _registerMask[] = {
75 [REG_SC] = 0x7E, // TODO: GBC differences
76 [REG_IF] = 0xE0,
77 [REG_TAC] = 0xF8,
78 [REG_NR10] = 0x80,
79 [REG_NR11] = 0x3F,
80 [REG_NR12] = 0x00,
81 [REG_NR13] = 0xFF,
82 [REG_NR14] = 0xBF,
83 [REG_NR21] = 0x3F,
84 [REG_NR22] = 0x00,
85 [REG_NR23] = 0xFF,
86 [REG_NR24] = 0xBF,
87 [REG_NR30] = 0x7F,
88 [REG_NR31] = 0xFF,
89 [REG_NR32] = 0x9F,
90 [REG_NR33] = 0xFF,
91 [REG_NR34] = 0xBF,
92 [REG_NR41] = 0xFF,
93 [REG_NR42] = 0x00,
94 [REG_NR43] = 0x00,
95 [REG_NR44] = 0xBF,
96 [REG_NR50] = 0x00,
97 [REG_NR51] = 0x00,
98 [REG_NR52] = 0x70,
99 [REG_STAT] = 0x80,
100 [REG_KEY1] = 0x7E,
101 [REG_VBK] = 0xFE,
102 [REG_OCPS] = 0x40,
103 [REG_BCPS] = 0x40,
104 [REG_OPRI] = 0xFE,
105 [REG_SVBK] = 0xF8,
106 [REG_IE] = 0xE0,
107};
108
109static uint8_t _readKeys(struct GB* gb);
110static uint8_t _readKeysFiltered(struct GB* gb);
111
112static void _writeSGBBits(struct GB* gb, int bits) {
113 if (!bits) {
114 gb->sgbBit = -1;
115 memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
116 }
117 if (bits == gb->currentSgbBits) {
118 return;
119 }
120 switch (bits) {
121 case 0:
122 case 1:
123 if (gb->currentSgbBits & 2) {
124 gb->sgbIncrement = !gb->sgbIncrement;
125 }
126 break;
127 case 3:
128 if (gb->sgbIncrement) {
129 gb->sgbIncrement = false;
130 gb->sgbCurrentController = (gb->sgbCurrentController + 1) & gb->sgbControllers;
131 }
132 break;
133 }
134 gb->currentSgbBits = bits;
135 if (gb->sgbBit == 128 && bits == 2) {
136 GBVideoWriteSGBPacket(&gb->video, gb->sgbPacket);
137 ++gb->sgbBit;
138 }
139 if (gb->sgbBit >= 128) {
140 return;
141 }
142 switch (bits) {
143 case 1:
144 if (gb->sgbBit < 0) {
145 return;
146 }
147 gb->sgbPacket[gb->sgbBit >> 3] |= 1 << (gb->sgbBit & 7);
148 break;
149 case 3:
150 ++gb->sgbBit;
151 default:
152 break;
153 }
154}
155
156void GBIOInit(struct GB* gb) {
157 memset(gb->memory.io, 0, sizeof(gb->memory.io));
158}
159
160void GBIOReset(struct GB* gb) {
161 memset(gb->memory.io, 0, sizeof(gb->memory.io));
162
163 GBIOWrite(gb, REG_TIMA, 0);
164 GBIOWrite(gb, REG_TMA, 0);
165 GBIOWrite(gb, REG_TAC, 0);
166 GBIOWrite(gb, REG_IF, 1);
167 GBIOWrite(gb, REG_NR52, 0xF1);
168 GBIOWrite(gb, REG_NR14, 0x3F);
169 GBIOWrite(gb, REG_NR10, 0x80);
170 GBIOWrite(gb, REG_NR11, 0xBF);
171 GBIOWrite(gb, REG_NR12, 0xF3);
172 GBIOWrite(gb, REG_NR13, 0xF3);
173 GBIOWrite(gb, REG_NR24, 0x3F);
174 GBIOWrite(gb, REG_NR21, 0x3F);
175 GBIOWrite(gb, REG_NR22, 0x00);
176 GBIOWrite(gb, REG_NR34, 0x3F);
177 GBIOWrite(gb, REG_NR30, 0x7F);
178 GBIOWrite(gb, REG_NR31, 0xFF);
179 GBIOWrite(gb, REG_NR32, 0x9F);
180 GBIOWrite(gb, REG_NR44, 0x3F);
181 GBIOWrite(gb, REG_NR41, 0xFF);
182 GBIOWrite(gb, REG_NR42, 0x00);
183 GBIOWrite(gb, REG_NR43, 0x00);
184 GBIOWrite(gb, REG_NR50, 0x77);
185 GBIOWrite(gb, REG_NR51, 0xF3);
186 if (!gb->biosVf) {
187 GBIOWrite(gb, REG_LCDC, 0x91);
188 gb->memory.io[0x50] = 1;
189 } else {
190 GBIOWrite(gb, REG_LCDC, 0x00);
191 gb->memory.io[0x50] = 0xFF;
192 }
193 GBIOWrite(gb, REG_SCY, 0x00);
194 GBIOWrite(gb, REG_SCX, 0x00);
195 GBIOWrite(gb, REG_LYC, 0x00);
196 GBIOWrite(gb, REG_DMA, 0xFF);
197 GBIOWrite(gb, REG_BGP, 0xFC);
198 if (gb->model < GB_MODEL_CGB) {
199 GBIOWrite(gb, REG_OBP0, 0xFF);
200 GBIOWrite(gb, REG_OBP1, 0xFF);
201 }
202 GBIOWrite(gb, REG_WY, 0x00);
203 GBIOWrite(gb, REG_WX, 0x00);
204 if (gb->model & GB_MODEL_CGB) {
205 GBIOWrite(gb, REG_KEY0, 0);
206 GBIOWrite(gb, REG_JOYP, 0xFF);
207 GBIOWrite(gb, REG_VBK, 0);
208 GBIOWrite(gb, REG_BCPS, 0x80);
209 GBIOWrite(gb, REG_OCPS, 0);
210 GBIOWrite(gb, REG_SVBK, 1);
211 GBIOWrite(gb, REG_HDMA1, 0xFF);
212 GBIOWrite(gb, REG_HDMA2, 0xFF);
213 GBIOWrite(gb, REG_HDMA3, 0xFF);
214 GBIOWrite(gb, REG_HDMA4, 0xFF);
215 gb->memory.io[REG_HDMA5] = 0xFF;
216 } else if (gb->model & GB_MODEL_SGB) {
217 GBIOWrite(gb, REG_JOYP, 0xFF);
218 }
219 GBIOWrite(gb, REG_IE, 0x00);
220}
221
222void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
223 switch (address) {
224 case REG_SB:
225 GBSIOWriteSB(&gb->sio, value);
226 break;
227 case REG_SC:
228 GBSIOWriteSC(&gb->sio, value);
229 break;
230 case REG_DIV:
231 GBTimerDivReset(&gb->timer);
232 return;
233 case REG_NR10:
234 if (gb->audio.enable) {
235 GBAudioWriteNR10(&gb->audio, value);
236 } else {
237 value = 0;
238 }
239 break;
240 case REG_NR11:
241 if (gb->audio.enable) {
242 GBAudioWriteNR11(&gb->audio, value);
243 } else {
244 if (gb->audio.style == GB_AUDIO_DMG) {
245 GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
246 }
247 value = 0;
248 }
249 break;
250 case REG_NR12:
251 if (gb->audio.enable) {
252 GBAudioWriteNR12(&gb->audio, value);
253 } else {
254 value = 0;
255 }
256 break;
257 case REG_NR13:
258 if (gb->audio.enable) {
259 GBAudioWriteNR13(&gb->audio, value);
260 } else {
261 value = 0;
262 }
263 break;
264 case REG_NR14:
265 if (gb->audio.enable) {
266 GBAudioWriteNR14(&gb->audio, value);
267 } else {
268 value = 0;
269 }
270 break;
271 case REG_NR21:
272 if (gb->audio.enable) {
273 GBAudioWriteNR21(&gb->audio, value);
274 } else {
275 if (gb->audio.style == GB_AUDIO_DMG) {
276 GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
277 }
278 value = 0;
279 }
280 break;
281 case REG_NR22:
282 if (gb->audio.enable) {
283 GBAudioWriteNR22(&gb->audio, value);
284 } else {
285 value = 0;
286 }
287 break;
288 case REG_NR23:
289 if (gb->audio.enable) {
290 GBAudioWriteNR23(&gb->audio, value);
291 } else {
292 value = 0;
293 }
294 break;
295 case REG_NR24:
296 if (gb->audio.enable) {
297 GBAudioWriteNR24(&gb->audio, value);
298 } else {
299 value = 0;
300 }
301 break;
302 case REG_NR30:
303 if (gb->audio.enable) {
304 GBAudioWriteNR30(&gb->audio, value);
305 } else {
306 value = 0;
307 }
308 break;
309 case REG_NR31:
310 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
311 GBAudioWriteNR31(&gb->audio, value);
312 } else {
313 value = 0;
314 }
315 break;
316 case REG_NR32:
317 if (gb->audio.enable) {
318 GBAudioWriteNR32(&gb->audio, value);
319 } else {
320 value = 0;
321 }
322 break;
323 case REG_NR33:
324 if (gb->audio.enable) {
325 GBAudioWriteNR33(&gb->audio, value);
326 } else {
327 value = 0;
328 }
329 break;
330 case REG_NR34:
331 if (gb->audio.enable) {
332 GBAudioWriteNR34(&gb->audio, value);
333 } else {
334 value = 0;
335 }
336 break;
337 case REG_NR41:
338 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
339 GBAudioWriteNR41(&gb->audio, value);
340 } else {
341 value = 0;
342 }
343 break;
344 case REG_NR42:
345 if (gb->audio.enable) {
346 GBAudioWriteNR42(&gb->audio, value);
347 } else {
348 value = 0;
349 }
350 break;
351 case REG_NR43:
352 if (gb->audio.enable) {
353 GBAudioWriteNR43(&gb->audio, value);
354 } else {
355 value = 0;
356 }
357 break;
358 case REG_NR44:
359 if (gb->audio.enable) {
360 GBAudioWriteNR44(&gb->audio, value);
361 } else {
362 value = 0;
363 }
364 break;
365 case REG_NR50:
366 if (gb->audio.enable) {
367 GBAudioWriteNR50(&gb->audio, value);
368 } else {
369 value = 0;
370 }
371 break;
372 case REG_NR51:
373 if (gb->audio.enable) {
374 GBAudioWriteNR51(&gb->audio, value);
375 } else {
376 value = 0;
377 }
378 break;
379 case REG_NR52:
380 GBAudioWriteNR52(&gb->audio, value);
381 value &= 0x80;
382 value |= gb->memory.io[REG_NR52] & 0x0F;
383 break;
384 case REG_WAVE_0:
385 case REG_WAVE_1:
386 case REG_WAVE_2:
387 case REG_WAVE_3:
388 case REG_WAVE_4:
389 case REG_WAVE_5:
390 case REG_WAVE_6:
391 case REG_WAVE_7:
392 case REG_WAVE_8:
393 case REG_WAVE_9:
394 case REG_WAVE_A:
395 case REG_WAVE_B:
396 case REG_WAVE_C:
397 case REG_WAVE_D:
398 case REG_WAVE_E:
399 case REG_WAVE_F:
400 if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
401 gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
402 } else if(gb->audio.ch3.readable) {
403 gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
404 }
405 break;
406 case REG_JOYP:
407 gb->memory.io[REG_JOYP] = value | 0x0F;
408 _readKeys(gb);
409 if (gb->model & GB_MODEL_SGB) {
410 _writeSGBBits(gb, (value >> 4) & 3);
411 }
412 return;
413 case REG_TIMA:
414 if (value && mTimingUntil(&gb->timing, &gb->timer.irq) > 1) {
415 mTimingDeschedule(&gb->timing, &gb->timer.irq);
416 }
417 if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
418 return;
419 }
420 break;
421 case REG_TMA:
422 if (mTimingUntil(&gb->timing, &gb->timer.irq) == -1) {
423 gb->memory.io[REG_TIMA] = value;
424 }
425 break;
426 case REG_TAC:
427 value = GBTimerUpdateTAC(&gb->timer, value);
428 break;
429 case REG_IF:
430 gb->memory.io[REG_IF] = value | 0xE0;
431 GBUpdateIRQs(gb);
432 return;
433 case REG_LCDC:
434 // TODO: handle GBC differences
435 GBVideoProcessDots(&gb->video, 0);
436 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
437 GBVideoWriteLCDC(&gb->video, value);
438 break;
439 case REG_LYC:
440 GBVideoWriteLYC(&gb->video, value);
441 break;
442 case REG_DMA:
443 GBMemoryDMA(gb, value << 8);
444 break;
445 case REG_SCY:
446 case REG_SCX:
447 case REG_WY:
448 case REG_WX:
449 GBVideoProcessDots(&gb->video, 0);
450 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
451 break;
452 case REG_BGP:
453 case REG_OBP0:
454 case REG_OBP1:
455 GBVideoProcessDots(&gb->video, 0);
456 GBVideoWritePalette(&gb->video, address, value);
457 break;
458 case REG_STAT:
459 GBVideoWriteSTAT(&gb->video, value);
460 value = gb->video.stat;
461 break;
462 case 0x50:
463 if (gb->memory.io[0x50] != 0xFF) {
464 break;
465 }
466 GBUnmapBIOS(gb);
467 if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_KEY0] < 0x80) {
468 gb->model = GB_MODEL_DMG;
469 GBVideoDisableCGB(&gb->video);
470 }
471 break;
472 case REG_IE:
473 gb->memory.ie = value;
474 GBUpdateIRQs(gb);
475 return;
476 default:
477 if (gb->model >= GB_MODEL_CGB) {
478 switch (address) {
479 case REG_KEY0:
480 break;
481 case REG_KEY1:
482 value &= 0x1;
483 value |= gb->memory.io[address] & 0x80;
484 break;
485 case REG_VBK:
486 GBVideoSwitchBank(&gb->video, value);
487 break;
488 case REG_HDMA1:
489 case REG_HDMA2:
490 case REG_HDMA3:
491 case REG_HDMA4:
492 // Handled transparently by the registers
493 break;
494 case REG_HDMA5:
495 value = GBMemoryWriteHDMA5(gb, value);
496 break;
497 case REG_BCPS:
498 gb->video.bcpIndex = value & 0x3F;
499 gb->video.bcpIncrement = value & 0x80;
500 gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1));
501 break;
502 case REG_BCPD:
503 if (gb->video.mode != 3) {
504 GBVideoProcessDots(&gb->video, 0);
505 }
506 GBVideoWritePalette(&gb->video, address, value);
507 return;
508 case REG_OCPS:
509 gb->video.ocpIndex = value & 0x3F;
510 gb->video.ocpIncrement = value & 0x80;
511 gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1));
512 break;
513 case REG_OCPD:
514 if (gb->video.mode != 3) {
515 GBVideoProcessDots(&gb->video, 0);
516 }
517 GBVideoWritePalette(&gb->video, address, value);
518 return;
519 case REG_SVBK:
520 GBMemorySwitchWramBank(&gb->memory, value);
521 value = gb->memory.wramCurrentBank;
522 break;
523 default:
524 goto failed;
525 }
526 goto success;
527 }
528 failed:
529 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
530 if (address >= GB_SIZE_IO) {
531 return;
532 }
533 break;
534 }
535 success:
536 gb->memory.io[address] = value;
537}
538
539static uint8_t _readKeys(struct GB* gb) {
540 uint8_t keys = *gb->keySource;
541 if (gb->sgbCurrentController != 0) {
542 keys = 0;
543 }
544 uint8_t joyp = gb->memory.io[REG_JOYP];
545 switch (joyp & 0x30) {
546 case 0x30:
547 keys = gb->sgbCurrentController;
548 break;
549 case 0x20:
550 keys >>= 4;
551 break;
552 case 0x10:
553 break;
554 case 0x00:
555 keys |= keys >> 4;
556 break;
557 }
558 gb->memory.io[REG_JOYP] = (0xCF | joyp) ^ (keys & 0xF);
559 if (joyp & ~gb->memory.io[REG_JOYP] & 0xF) {
560 gb->memory.io[REG_IF] |= (1 << GB_IRQ_KEYPAD);
561 GBUpdateIRQs(gb);
562 }
563 return gb->memory.io[REG_JOYP];
564}
565
566static uint8_t _readKeysFiltered(struct GB* gb) {
567 uint8_t keys = _readKeys(gb);
568 if (!gb->allowOpposingDirections && (keys & 0x30) == 0x20) {
569 unsigned rl = keys & 0x03;
570 unsigned ud = keys & 0x0C;
571 if (!rl) {
572 keys |= 0x03;
573 }
574 if (!ud) {
575 keys |= 0x0C;
576 }
577 }
578 return keys;
579}
580
581uint8_t GBIORead(struct GB* gb, unsigned address) {
582 switch (address) {
583 case REG_JOYP:
584 {
585 size_t c;
586 for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) {
587 struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c);
588 if (callbacks->keysRead) {
589 callbacks->keysRead(callbacks->context);
590 }
591 }
592 }
593 return _readKeysFiltered(gb);
594 case REG_IE:
595 return gb->memory.ie;
596 case REG_WAVE_0:
597 case REG_WAVE_1:
598 case REG_WAVE_2:
599 case REG_WAVE_3:
600 case REG_WAVE_4:
601 case REG_WAVE_5:
602 case REG_WAVE_6:
603 case REG_WAVE_7:
604 case REG_WAVE_8:
605 case REG_WAVE_9:
606 case REG_WAVE_A:
607 case REG_WAVE_B:
608 case REG_WAVE_C:
609 case REG_WAVE_D:
610 case REG_WAVE_E:
611 case REG_WAVE_F:
612 if (gb->audio.playingCh3) {
613 if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
614 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
615 } else {
616 return 0xFF;
617 }
618 } else {
619 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
620 }
621 break;
622 case REG_SB:
623 case REG_SC:
624 case REG_IF:
625 case REG_NR10:
626 case REG_NR11:
627 case REG_NR12:
628 case REG_NR14:
629 case REG_NR21:
630 case REG_NR22:
631 case REG_NR24:
632 case REG_NR30:
633 case REG_NR32:
634 case REG_NR34:
635 case REG_NR41:
636 case REG_NR42:
637 case REG_NR43:
638 case REG_NR44:
639 case REG_NR50:
640 case REG_NR51:
641 case REG_NR52:
642 case REG_DIV:
643 case REG_TIMA:
644 case REG_TMA:
645 case REG_TAC:
646 case REG_STAT:
647 case REG_LCDC:
648 case REG_SCY:
649 case REG_SCX:
650 case REG_LY:
651 case REG_LYC:
652 case REG_DMA:
653 case REG_BGP:
654 case REG_OBP0:
655 case REG_OBP1:
656 case REG_WY:
657 case REG_WX:
658 // Handled transparently by the registers
659 break;
660 default:
661 if (gb->model >= GB_MODEL_CGB) {
662 switch (address) {
663 case REG_KEY1:
664 case REG_VBK:
665 case REG_HDMA1:
666 case REG_HDMA2:
667 case REG_HDMA3:
668 case REG_HDMA4:
669 case REG_HDMA5:
670 case REG_BCPS:
671 case REG_BCPD:
672 case REG_OCPS:
673 case REG_OCPD:
674 case REG_SVBK:
675 // Handled transparently by the registers
676 goto success;
677 default:
678 break;
679 }
680 }
681 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
682 return 0xFF;
683 }
684 success:
685 return gb->memory.io[address] | _registerMask[address];
686}
687
688void GBTestKeypadIRQ(struct GB* gb) {
689 _readKeys(gb);
690}
691
692struct GBSerializedState;
693void GBIOSerialize(const struct GB* gb, struct GBSerializedState* state) {
694 memcpy(state->io, gb->memory.io, GB_SIZE_IO);
695 state->ie = gb->memory.ie;
696}
697
698void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
699 memcpy(gb->memory.io, state->io, GB_SIZE_IO);
700 gb->memory.ie = state->ie;
701
702 if (GBAudioEnableGetEnable(*gb->audio.nr52)) {
703 GBIOWrite(gb, REG_NR10, gb->memory.io[REG_NR10]);
704 GBIOWrite(gb, REG_NR11, gb->memory.io[REG_NR11]);
705 GBIOWrite(gb, REG_NR12, gb->memory.io[REG_NR12]);
706 GBIOWrite(gb, REG_NR13, gb->memory.io[REG_NR13]);
707 gb->audio.ch1.control.frequency &= 0xFF;
708 gb->audio.ch1.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR14] << 8);
709 gb->audio.ch1.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR14] << 8);
710 GBIOWrite(gb, REG_NR21, gb->memory.io[REG_NR21]);
711 GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR22]);
712 GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR23]);
713 gb->audio.ch2.control.frequency &= 0xFF;
714 gb->audio.ch2.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR24] << 8);
715 gb->audio.ch2.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR24] << 8);
716 GBIOWrite(gb, REG_NR30, gb->memory.io[REG_NR30]);
717 GBIOWrite(gb, REG_NR31, gb->memory.io[REG_NR31]);
718 GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR32]);
719 GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR33]);
720 gb->audio.ch3.rate &= 0xFF;
721 gb->audio.ch3.rate |= GBAudioRegisterControlGetRate(gb->memory.io[REG_NR34] << 8);
722 gb->audio.ch3.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR34] << 8);
723 GBIOWrite(gb, REG_NR41, gb->memory.io[REG_NR41]);
724 GBIOWrite(gb, REG_NR42, gb->memory.io[REG_NR42]);
725 GBIOWrite(gb, REG_NR43, gb->memory.io[REG_NR43]);
726 gb->audio.ch4.stop = GBAudioRegisterNoiseControlGetStop(gb->memory.io[REG_NR44]);
727 GBIOWrite(gb, REG_NR50, gb->memory.io[REG_NR50]);
728 GBIOWrite(gb, REG_NR51, gb->memory.io[REG_NR51]);
729 }
730
731 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_LCDC, state->io[REG_LCDC]);
732 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCY, state->io[REG_SCY]);
733 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCX, state->io[REG_SCX]);
734 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WY, state->io[REG_WY]);
735 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WX, state->io[REG_WX]);
736 if (gb->model & GB_MODEL_SGB) {
737 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_BGP, state->io[REG_BGP]);
738 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP0, state->io[REG_OBP0]);
739 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP1, state->io[REG_OBP1]);
740 }
741 gb->video.stat = state->io[REG_STAT];
742}