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
14const 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_KEY1] = "KEY1",
57 [REG_VBK] = "VBK",
58 [REG_HDMA1] = "HDMA1",
59 [REG_HDMA2] = "HDMA2",
60 [REG_HDMA3] = "HDMA3",
61 [REG_HDMA4] = "HDMA4",
62 [REG_HDMA5] = "HDMA5",
63 [REG_RP] = "RP",
64 [REG_BCPS] = "BCPS",
65 [REG_BCPD] = "BCPD",
66 [REG_OCPS] = "OCPS",
67 [REG_OCPD] = "OCPD",
68 [REG_SVBK] = "SVBK",
69 [REG_IE] = "IE",
70};
71
72static const uint8_t _registerMask[] = {
73 [REG_SC] = 0x7E, // TODO: GBC differences
74 [REG_IF] = 0xE0,
75 [REG_TAC] = 0xF8,
76 [REG_NR10] = 0x80,
77 [REG_NR11] = 0x3F,
78 [REG_NR12] = 0x00,
79 [REG_NR13] = 0xFF,
80 [REG_NR14] = 0xBF,
81 [REG_NR21] = 0x3F,
82 [REG_NR22] = 0x00,
83 [REG_NR23] = 0xFF,
84 [REG_NR24] = 0xBF,
85 [REG_NR30] = 0x7F,
86 [REG_NR31] = 0xFF,
87 [REG_NR32] = 0x9F,
88 [REG_NR33] = 0xFF,
89 [REG_NR34] = 0xBF,
90 [REG_NR41] = 0xFF,
91 [REG_NR42] = 0x00,
92 [REG_NR43] = 0x00,
93 [REG_NR44] = 0xBF,
94 [REG_NR50] = 0x00,
95 [REG_NR51] = 0x00,
96 [REG_NR52] = 0x70,
97 [REG_STAT] = 0x80,
98 [REG_KEY1] = 0x7E,
99 [REG_VBK] = 0xFE,
100 [REG_OCPS] = 0x40,
101 [REG_BCPS] = 0x40,
102 [REG_UNK6C] = 0xFE,
103 [REG_SVBK] = 0xF8,
104 [REG_IE] = 0xE0,
105};
106
107static uint8_t _readKeys(struct GB* gb);
108static uint8_t _readKeysFiltered(struct GB* gb);
109
110static void _writeSGBBits(struct GB* gb, int bits) {
111 if (!bits) {
112 gb->sgbBit = -1;
113 memset(gb->sgbPacket, 0, sizeof(gb->sgbPacket));
114 }
115 if (bits == gb->currentSgbBits) {
116 return;
117 }
118 gb->currentSgbBits = bits;
119 if (gb->sgbBit > 128) {
120 switch (bits) {
121 case 1:
122 gb->sgbBit |= 2;
123 break;
124 case 2:
125 gb->sgbBit |= 4;
126 break;
127 case 3:
128 if (gb->sgbBit == 135) {
129 gb->sgbBit &= ~6;
130 gb->sgbCurrentController = (gb->sgbCurrentController + 1) & gb->sgbControllers;
131 }
132 break;
133 }
134 }
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_UNK4C, 0);
206 GBIOWrite(gb, REG_JOYP, 0xFF);
207 GBIOWrite(gb, REG_VBK, 0);
208 GBIOWrite(gb, REG_BCPS, 0);
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 GBUnmapBIOS(gb);
464 if (gb->model >= GB_MODEL_CGB && gb->memory.io[REG_UNK4C] < 0x80) {
465 gb->model = GB_MODEL_DMG;
466 GBVideoDisableCGB(&gb->video);
467 }
468 break;
469 case REG_IE:
470 gb->memory.ie = value;
471 GBUpdateIRQs(gb);
472 return;
473 default:
474 if (gb->model >= GB_MODEL_CGB) {
475 switch (address) {
476 case REG_UNK4C:
477 break;
478 case REG_KEY1:
479 value &= 0x1;
480 value |= gb->memory.io[address] & 0x80;
481 break;
482 case REG_VBK:
483 GBVideoSwitchBank(&gb->video, value);
484 break;
485 case REG_HDMA1:
486 case REG_HDMA2:
487 case REG_HDMA3:
488 case REG_HDMA4:
489 // Handled transparently by the registers
490 break;
491 case REG_HDMA5:
492 value = GBMemoryWriteHDMA5(gb, value);
493 break;
494 case REG_BCPS:
495 gb->video.bcpIndex = value & 0x3F;
496 gb->video.bcpIncrement = value & 0x80;
497 gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1));
498 break;
499 case REG_BCPD:
500 if (gb->video.mode != 3) {
501 GBVideoProcessDots(&gb->video, 0);
502 GBVideoWritePalette(&gb->video, address, value);
503 }
504 return;
505 case REG_OCPS:
506 gb->video.ocpIndex = value & 0x3F;
507 gb->video.ocpIncrement = value & 0x80;
508 gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1));
509 break;
510 case REG_OCPD:
511 if (gb->video.mode != 3) {
512 GBVideoProcessDots(&gb->video, 0);
513 GBVideoWritePalette(&gb->video, address, value);
514 }
515 return;
516 case REG_SVBK:
517 GBMemorySwitchWramBank(&gb->memory, value);
518 value = gb->memory.wramCurrentBank;
519 break;
520 default:
521 goto failed;
522 }
523 goto success;
524 }
525 failed:
526 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
527 if (address >= GB_SIZE_IO) {
528 return;
529 }
530 break;
531 }
532 success:
533 gb->memory.io[address] = value;
534}
535
536static uint8_t _readKeys(struct GB* gb) {
537 uint8_t keys = *gb->keySource;
538 if (gb->sgbCurrentController != 0) {
539 keys = 0;
540 }
541 uint8_t joyp = gb->memory.io[REG_JOYP];
542 switch (joyp & 0x30) {
543 case 0x30:
544 keys = gb->sgbCurrentController;
545 break;
546 case 0x20:
547 keys >>= 4;
548 break;
549 case 0x10:
550 break;
551 case 0x00:
552 keys |= keys >> 4;
553 break;
554 }
555 gb->memory.io[REG_JOYP] = (0xCF | joyp) ^ (keys & 0xF);
556 if (joyp & ~gb->memory.io[REG_JOYP] & 0xF) {
557 gb->memory.io[REG_IF] |= (1 << GB_IRQ_KEYPAD);
558 GBUpdateIRQs(gb);
559 }
560 return gb->memory.io[REG_JOYP];
561}
562
563static uint8_t _readKeysFiltered(struct GB* gb) {
564 uint8_t keys = _readKeys(gb);
565 if (!gb->allowOpposingDirections && (keys & 0x30) == 0x20) {
566 unsigned rl = keys & 0x03;
567 unsigned ud = keys & 0x0C;
568 if (!rl) {
569 keys |= 0x03;
570 }
571 if (!ud) {
572 keys |= 0x0C;
573 }
574 }
575 return keys;
576}
577
578uint8_t GBIORead(struct GB* gb, unsigned address) {
579 switch (address) {
580 case REG_JOYP:
581 {
582 size_t c;
583 for (c = 0; c < mCoreCallbacksListSize(&gb->coreCallbacks); ++c) {
584 struct mCoreCallbacks* callbacks = mCoreCallbacksListGetPointer(&gb->coreCallbacks, c);
585 if (callbacks->keysRead) {
586 callbacks->keysRead(callbacks->context);
587 }
588 }
589 }
590 return _readKeysFiltered(gb);
591 case REG_IE:
592 return gb->memory.ie;
593 case REG_WAVE_0:
594 case REG_WAVE_1:
595 case REG_WAVE_2:
596 case REG_WAVE_3:
597 case REG_WAVE_4:
598 case REG_WAVE_5:
599 case REG_WAVE_6:
600 case REG_WAVE_7:
601 case REG_WAVE_8:
602 case REG_WAVE_9:
603 case REG_WAVE_A:
604 case REG_WAVE_B:
605 case REG_WAVE_C:
606 case REG_WAVE_D:
607 case REG_WAVE_E:
608 case REG_WAVE_F:
609 if (gb->audio.playingCh3) {
610 if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
611 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
612 } else {
613 return 0xFF;
614 }
615 } else {
616 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
617 }
618 break;
619 case REG_SB:
620 case REG_SC:
621 case REG_IF:
622 case REG_NR10:
623 case REG_NR11:
624 case REG_NR12:
625 case REG_NR14:
626 case REG_NR21:
627 case REG_NR22:
628 case REG_NR24:
629 case REG_NR30:
630 case REG_NR32:
631 case REG_NR34:
632 case REG_NR41:
633 case REG_NR42:
634 case REG_NR43:
635 case REG_NR44:
636 case REG_NR50:
637 case REG_NR51:
638 case REG_NR52:
639 case REG_DIV:
640 case REG_TIMA:
641 case REG_TMA:
642 case REG_TAC:
643 case REG_STAT:
644 case REG_LCDC:
645 case REG_SCY:
646 case REG_SCX:
647 case REG_LY:
648 case REG_LYC:
649 case REG_DMA:
650 case REG_BGP:
651 case REG_OBP0:
652 case REG_OBP1:
653 case REG_WY:
654 case REG_WX:
655 // Handled transparently by the registers
656 break;
657 default:
658 if (gb->model >= GB_MODEL_CGB) {
659 switch (address) {
660 case REG_KEY1:
661 case REG_VBK:
662 case REG_HDMA1:
663 case REG_HDMA2:
664 case REG_HDMA3:
665 case REG_HDMA4:
666 case REG_HDMA5:
667 case REG_BCPS:
668 case REG_BCPD:
669 case REG_OCPS:
670 case REG_OCPD:
671 case REG_SVBK:
672 // Handled transparently by the registers
673 goto success;
674 default:
675 break;
676 }
677 }
678 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
679 return 0xFF;
680 }
681 success:
682 return gb->memory.io[address] | _registerMask[address];
683}
684
685void GBTestKeypadIRQ(struct GB* gb) {
686 _readKeys(gb);
687}
688
689struct GBSerializedState;
690void GBIOSerialize(const struct GB* gb, struct GBSerializedState* state) {
691 memcpy(state->io, gb->memory.io, GB_SIZE_IO);
692 state->ie = gb->memory.ie;
693}
694
695void GBIODeserialize(struct GB* gb, const struct GBSerializedState* state) {
696 memcpy(gb->memory.io, state->io, GB_SIZE_IO);
697 gb->memory.ie = state->ie;
698
699 if (GBAudioEnableGetEnable(*gb->audio.nr52)) {
700 GBIOWrite(gb, REG_NR10, gb->memory.io[REG_NR10]);
701 GBIOWrite(gb, REG_NR11, gb->memory.io[REG_NR11]);
702 GBIOWrite(gb, REG_NR12, gb->memory.io[REG_NR12]);
703 GBIOWrite(gb, REG_NR13, gb->memory.io[REG_NR13]);
704 gb->audio.ch1.control.frequency &= 0xFF;
705 gb->audio.ch1.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR14] << 8);
706 gb->audio.ch1.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR14] << 8);
707 GBIOWrite(gb, REG_NR21, gb->memory.io[REG_NR21]);
708 GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR22]);
709 GBIOWrite(gb, REG_NR22, gb->memory.io[REG_NR23]);
710 gb->audio.ch2.control.frequency &= 0xFF;
711 gb->audio.ch2.control.frequency |= GBAudioRegisterControlGetFrequency(gb->memory.io[REG_NR24] << 8);
712 gb->audio.ch2.control.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR24] << 8);
713 GBIOWrite(gb, REG_NR30, gb->memory.io[REG_NR30]);
714 GBIOWrite(gb, REG_NR31, gb->memory.io[REG_NR31]);
715 GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR32]);
716 GBIOWrite(gb, REG_NR32, gb->memory.io[REG_NR33]);
717 gb->audio.ch3.rate &= 0xFF;
718 gb->audio.ch3.rate |= GBAudioRegisterControlGetRate(gb->memory.io[REG_NR34] << 8);
719 gb->audio.ch3.stop = GBAudioRegisterControlGetStop(gb->memory.io[REG_NR34] << 8);
720 GBIOWrite(gb, REG_NR41, gb->memory.io[REG_NR41]);
721 GBIOWrite(gb, REG_NR42, gb->memory.io[REG_NR42]);
722 GBIOWrite(gb, REG_NR43, gb->memory.io[REG_NR43]);
723 gb->audio.ch4.stop = GBAudioRegisterNoiseControlGetStop(gb->memory.io[REG_NR44]);
724 GBIOWrite(gb, REG_NR50, gb->memory.io[REG_NR50]);
725 GBIOWrite(gb, REG_NR51, gb->memory.io[REG_NR51]);
726 }
727
728 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_LCDC, state->io[REG_LCDC]);
729 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCY, state->io[REG_SCY]);
730 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_SCX, state->io[REG_SCX]);
731 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WY, state->io[REG_WY]);
732 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_WX, state->io[REG_WX]);
733 if (gb->model & GB_MODEL_SGB) {
734 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_BGP, state->io[REG_BGP]);
735 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP0, state->io[REG_OBP0]);
736 gb->video.renderer->writeVideoRegister(gb->video.renderer, REG_OBP1, state->io[REG_OBP1]);
737 }
738 gb->video.stat = state->io[REG_STAT];
739}