all repos — mgba @ 659b929f3e58d50762f3054ba634877e458cdb4c

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