all repos — mgba @ c4b38790f211b65cb15af26cebe9fc25e3c19914

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