all repos — mgba @ a44a8f668f6a54a4b4ee3e5853d504b2708f8458

mGBA Game Boy Advance Emulator

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