all repos — mgba @ a3a380d9f551bbc5ad726ef07c11d20c0263d1e5

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 "io.h"
  7
  8#include "gb/gb.h"
  9
 10mLOG_DEFINE_CATEGORY(GB_IO, "GB I/O");
 11
 12const char* const GBIORegisterNames[] = {
 13	[REG_JOYP] = "JOYP",
 14	[REG_SB] = "SB",
 15	[REG_SC] = "SC",
 16	[REG_DIV] = "DIV",
 17	[REG_TIMA] = "TIMA",
 18	[REG_TMA] = "TMA",
 19	[REG_TAC] = "TAC",
 20	[REG_IF] = "IF",
 21	[REG_NR10] = "NR10",
 22	[REG_NR11] = "NR11",
 23	[REG_NR12] = "NR12",
 24	[REG_NR13] = "NR13",
 25	[REG_NR14] = "NR14",
 26	[REG_NR21] = "NR21",
 27	[REG_NR22] = "NR22",
 28	[REG_NR23] = "NR23",
 29	[REG_NR24] = "NR24",
 30	[REG_NR30] = "NR30",
 31	[REG_NR31] = "NR31",
 32	[REG_NR32] = "NR32",
 33	[REG_NR33] = "NR33",
 34	[REG_NR34] = "NR34",
 35	[REG_NR41] = "NR41",
 36	[REG_NR42] = "NR42",
 37	[REG_NR43] = "NR43",
 38	[REG_NR44] = "NR44",
 39	[REG_NR50] = "NR50",
 40	[REG_NR51] = "NR51",
 41	[REG_NR52] = "NR52",
 42	[REG_LCDC] = "LCDC",
 43	[REG_STAT] = "STAT",
 44	[REG_SCY] = "SCY",
 45	[REG_SCX] = "SCX",
 46	[REG_LY] = "LY",
 47	[REG_LYC] = "LYC",
 48	[REG_DMA] = "DMA",
 49	[REG_BGP] = "BGP",
 50	[REG_OBP0] = "OBP0",
 51	[REG_OBP1] = "OBP1",
 52	[REG_WY] = "WY",
 53	[REG_WX] = "WX",
 54	[REG_KEY1] = "KEY1",
 55	[REG_VBK] = "VBK",
 56	[REG_HDMA1] = "HDMA1",
 57	[REG_HDMA2] = "HDMA2",
 58	[REG_HDMA3] = "HDMA3",
 59	[REG_HDMA4] = "HDMA4",
 60	[REG_HDMA5] = "HDMA5",
 61	[REG_RP] = "RP",
 62	[REG_BCPS] = "BCPS",
 63	[REG_BCPD] = "BCPD",
 64	[REG_OCPS] = "OCPS",
 65	[REG_OCPD] = "OCPD",
 66	[REG_SVBK] = "SVBK",
 67	[REG_IE] = "IE",
 68};
 69
 70static const uint8_t _registerMask[] = {
 71	[REG_SC]   = 0x7E, // TODO: GBC differences
 72	[REG_IF]   = 0xE0,
 73	[REG_TAC]  = 0xF8,
 74	[REG_NR10] = 0x80,
 75	[REG_NR11] = 0x3F,
 76	[REG_NR12] = 0x00,
 77	[REG_NR13] = 0xFF,
 78	[REG_NR14] = 0xBF,
 79	[REG_NR21] = 0x3F,
 80	[REG_NR22] = 0x00,
 81	[REG_NR23] = 0xFF,
 82	[REG_NR24] = 0xBF,
 83	[REG_NR30] = 0x7F,
 84	[REG_NR31] = 0xFF,
 85	[REG_NR32] = 0x9F,
 86	[REG_NR33] = 0xFF,
 87	[REG_NR34] = 0xBF,
 88	[REG_NR41] = 0xFF,
 89	[REG_NR42] = 0x00,
 90	[REG_NR43] = 0x00,
 91	[REG_NR44] = 0xBF,
 92	[REG_NR50] = 0x00,
 93	[REG_NR51] = 0x00,
 94	[REG_NR52] = 0x70,
 95	[REG_STAT] = 0x80,
 96	[REG_KEY1] = 0x7E,
 97	[REG_VBK] = 0xFE,
 98	[REG_OCPS] = 0x40,
 99	[REG_BCPS] = 0x40,
100	[REG_UNK6C] = 0xFE,
101	[REG_SVBK] = 0xF8,
102	[REG_UNK75] = 0x8F,
103	[REG_IE]   = 0xE0,
104};
105
106void GBIOInit(struct GB* gb) {
107	memset(gb->memory.io, 0, sizeof(gb->memory.io));
108}
109
110void GBIOReset(struct GB* gb) {
111	memset(gb->memory.io, 0, sizeof(gb->memory.io));
112
113	GBIOWrite(gb, REG_TIMA, 0);
114	GBIOWrite(gb, REG_TMA, 0);
115	GBIOWrite(gb, REG_TAC, 0);
116	GBIOWrite(gb, REG_IF, 1);
117	GBIOWrite(gb, REG_NR52, 0xF1);
118	GBIOWrite(gb, REG_NR10, 0x80);
119	GBIOWrite(gb, REG_NR11, 0xBF);
120	GBIOWrite(gb, REG_NR12, 0xF3);
121	GBIOWrite(gb, REG_NR13, 0xF3);
122	GBIOWrite(gb, REG_NR14, 0xBF);
123	GBIOWrite(gb, REG_NR21, 0x3F);
124	GBIOWrite(gb, REG_NR22, 0x00);
125	GBIOWrite(gb, REG_NR24, 0xBF);
126	GBIOWrite(gb, REG_NR30, 0x7F);
127	GBIOWrite(gb, REG_NR31, 0xFF);
128	GBIOWrite(gb, REG_NR32, 0x9F);
129	GBIOWrite(gb, REG_NR34, 0xBF);
130	GBIOWrite(gb, REG_NR41, 0xFF);
131	GBIOWrite(gb, REG_NR42, 0x00);
132	GBIOWrite(gb, REG_NR43, 0x00);
133	GBIOWrite(gb, REG_NR44, 0xBF);
134	GBIOWrite(gb, REG_NR50, 0x77);
135	GBIOWrite(gb, REG_NR51, 0xF3);
136	GBIOWrite(gb, REG_LCDC, 0x91);
137	GBIOWrite(gb, REG_SCY, 0x00);
138	GBIOWrite(gb, REG_SCX, 0x00);
139	GBIOWrite(gb, REG_LYC, 0x00);
140	GBIOWrite(gb, REG_BGP, 0xFC);
141	GBIOWrite(gb, REG_OBP0, 0xFF);
142	GBIOWrite(gb, REG_OBP1, 0xFF);
143	GBIOWrite(gb, REG_WY, 0x00);
144	GBIOWrite(gb, REG_WX, 0x00);
145	GBIOWrite(gb, REG_VBK, 0);
146	GBIOWrite(gb, REG_BCPS, 0);
147	GBIOWrite(gb, REG_OCPS, 0);
148	GBIOWrite(gb, REG_SVBK, 1);
149	GBIOWrite(gb, REG_HDMA1, 0xFF);
150	GBIOWrite(gb, REG_HDMA2, 0xFF);
151	GBIOWrite(gb, REG_HDMA3, 0xFF);
152	GBIOWrite(gb, REG_HDMA4, 0xFF);
153	gb->memory.io[REG_HDMA5] = 0xFF;
154	GBIOWrite(gb, REG_IE, 0x00);
155}
156
157void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
158	switch (address) {
159	case REG_DIV:
160		GBTimerDivReset(&gb->timer);
161		return;
162	case REG_NR10:
163		if (gb->audio.enable) {
164			GBAudioWriteNR10(&gb->audio, value);
165		} else {
166			value = 0;
167		}
168		break;
169	case REG_NR11:
170		if (gb->audio.enable) {
171			GBAudioWriteNR11(&gb->audio, value);
172		} else {
173			if (gb->audio.style == GB_AUDIO_DMG) {
174				GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
175			}
176			value = 0;
177		}
178		break;
179	case REG_NR12:
180		if (gb->audio.enable) {
181			GBAudioWriteNR12(&gb->audio, value);
182		} else {
183			value = 0;
184		}
185		break;
186	case REG_NR13:
187		if (gb->audio.enable) {
188			GBAudioWriteNR13(&gb->audio, value);
189		} else {
190			value = 0;
191		}
192		break;
193	case REG_NR14:
194		if (gb->audio.enable) {
195			GBAudioWriteNR14(&gb->audio, value);
196		} else {
197			value = 0;
198		}
199		break;
200	case REG_NR21:
201		if (gb->audio.enable) {
202			GBAudioWriteNR21(&gb->audio, value);
203		} else {
204			if (gb->audio.style == GB_AUDIO_DMG) {
205				GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
206			}
207			value = 0;
208		}
209		break;
210	case REG_NR22:
211		if (gb->audio.enable) {
212			GBAudioWriteNR22(&gb->audio, value);
213		} else {
214			value = 0;
215		}
216		break;
217	case REG_NR23:
218		if (gb->audio.enable) {
219			GBAudioWriteNR23(&gb->audio, value);
220		} else {
221			value = 0;
222		}
223		break;
224	case REG_NR24:
225		if (gb->audio.enable) {
226			GBAudioWriteNR24(&gb->audio, value);
227		} else {
228			value = 0;
229		}
230		break;
231	case REG_NR30:
232		if (gb->audio.enable) {
233			GBAudioWriteNR30(&gb->audio, value);
234		} else {
235			value = 0;
236		}
237		break;
238	case REG_NR31:
239		if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
240			GBAudioWriteNR31(&gb->audio, value);
241		} else {
242			value = 0;
243		}
244		break;
245	case REG_NR32:
246		if (gb->audio.enable) {
247			GBAudioWriteNR32(&gb->audio, value);
248		} else {
249			value = 0;
250		}
251		break;
252	case REG_NR33:
253		if (gb->audio.enable) {
254			GBAudioWriteNR33(&gb->audio, value);
255		} else {
256			value = 0;
257		}
258		break;
259	case REG_NR34:
260		if (gb->audio.enable) {
261			GBAudioWriteNR34(&gb->audio, value);
262		} else {
263			value = 0;
264		}
265		break;
266	case REG_NR41:
267		if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
268			GBAudioWriteNR41(&gb->audio, value);
269		} else {
270			value = 0;
271		}
272		break;
273	case REG_NR42:
274		if (gb->audio.enable) {
275			GBAudioWriteNR42(&gb->audio, value);
276		} else {
277			value = 0;
278		}
279		break;
280	case REG_NR43:
281		if (gb->audio.enable) {
282			GBAudioWriteNR43(&gb->audio, value);
283		} else {
284			value = 0;
285		}
286		break;
287	case REG_NR44:
288		if (gb->audio.enable) {
289			GBAudioWriteNR44(&gb->audio, value);
290		} else {
291			value = 0;
292		}
293		break;
294	case REG_NR50:
295		if (gb->audio.enable) {
296			GBAudioWriteNR50(&gb->audio, value);
297		} else {
298			value = 0;
299		}
300		break;
301	case REG_NR51:
302		if (gb->audio.enable) {
303			GBAudioWriteNR51(&gb->audio, value);
304		} else {
305			value = 0;
306		}
307		break;
308	case REG_NR52:
309		GBAudioWriteNR52(&gb->audio, value);
310		value &= 0x80;
311		value |= gb->memory.io[REG_NR52] & 0x0F;
312		break;
313	case REG_WAVE_0:
314	case REG_WAVE_1:
315	case REG_WAVE_2:
316	case REG_WAVE_3:
317	case REG_WAVE_4:
318	case REG_WAVE_5:
319	case REG_WAVE_6:
320	case REG_WAVE_7:
321	case REG_WAVE_8:
322	case REG_WAVE_9:
323	case REG_WAVE_A:
324	case REG_WAVE_B:
325	case REG_WAVE_C:
326	case REG_WAVE_D:
327	case REG_WAVE_E:
328	case REG_WAVE_F:
329		if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
330			gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
331		} else if(gb->audio.ch3.readable) {
332			gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
333		}
334		break;
335	case REG_JOYP:
336	case REG_TIMA:
337	case REG_TMA:
338	case REG_LYC:
339		// Handled transparently by the registers
340		break;
341	case REG_TAC:
342		value = GBTimerUpdateTAC(&gb->timer, value);
343		break;
344	case REG_IF:
345		gb->memory.io[REG_IF] = value | 0xE0;
346		GBUpdateIRQs(gb);
347		return;
348	case REG_LCDC:
349		// TODO: handle GBC differences
350		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
351		GBVideoWriteLCDC(&gb->video, value);
352		break;
353	case REG_DMA:
354		GBMemoryDMA(gb, value << 8);
355		break;
356	case REG_SCY:
357	case REG_SCX:
358	case REG_WY:
359	case REG_WX:
360		GBVideoProcessDots(&gb->video);
361		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
362		break;
363	case REG_BGP:
364	case REG_OBP0:
365	case REG_OBP1:
366		GBVideoProcessDots(&gb->video);
367		GBVideoWritePalette(&gb->video, address, value);
368		break;
369	case REG_STAT:
370		GBVideoWriteSTAT(&gb->video, value);
371		break;
372	case 0x50:
373		if (gb->memory.romBase != gb->memory.rom) {
374			free(gb->memory.romBase);
375			gb->memory.romBase = gb->memory.rom;
376		}
377		break;
378	case REG_IE:
379		gb->memory.ie = value;
380		GBUpdateIRQs(gb);
381		return;
382	default:
383		if (gb->model >= GB_MODEL_CGB) {
384			switch (address) {
385			case REG_KEY1:
386				value &= 0x1;
387				value |= gb->memory.io[address] & 0x80;
388				break;
389			case REG_VBK:
390				GBVideoSwitchBank(&gb->video, value);
391				break;
392			case REG_HDMA1:
393			case REG_HDMA2:
394			case REG_HDMA3:
395			case REG_HDMA4:
396				// Handled transparently by the registers
397				break;
398			case REG_HDMA5:
399				GBMemoryWriteHDMA5(gb, value);
400				value &= 0x7F;
401				break;
402			case REG_BCPS:
403				gb->video.bcpIndex = value & 0x3F;
404				gb->video.bcpIncrement = value & 0x80;
405				gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1] >> (8 * (gb->video.bcpIndex & 1));
406				break;
407			case REG_BCPD:
408				GBVideoProcessDots(&gb->video);
409				GBVideoWritePalette(&gb->video, address, value);
410				break;
411			case REG_OCPS:
412				gb->video.ocpIndex = value & 0x3F;
413				gb->video.ocpIncrement = value & 0x80;
414				gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)] >> (8 * (gb->video.ocpIndex & 1));
415				break;
416			case REG_OCPD:
417				GBVideoProcessDots(&gb->video);
418				GBVideoWritePalette(&gb->video, address, value);
419				break;
420			case REG_SVBK:
421				GBMemorySwitchWramBank(&gb->memory, value);
422				value = gb->memory.wramCurrentBank;
423				break;
424			default:
425				goto failed;
426			}
427			goto success;
428		}
429		failed:
430		mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
431		if (address >= GB_SIZE_IO) {
432			return;
433		}
434		break;
435	}
436	success:
437	gb->memory.io[address] = value;
438}
439
440static uint8_t _readKeys(struct GB* gb) {
441	uint8_t keys = *gb->keySource;
442	switch (gb->memory.io[REG_JOYP] & 0x30) {
443	case 0x30:
444		keys = 0;
445		break;
446	case 0x20:
447		keys >>= 4;
448		break;
449	case 0x10:
450		break;
451	case 0x00:
452		keys |= keys >> 4;
453		break;
454	}
455	return (0xC0 | (gb->memory.io[REG_JOYP] | 0xF)) ^ (keys & 0xF);
456}
457
458uint8_t GBIORead(struct GB* gb, unsigned address) {
459	switch (address) {
460	case REG_JOYP:
461		return _readKeys(gb);
462	case REG_SB:
463	case REG_SC:
464		// TODO
465		break;
466	case REG_IE:
467		return gb->memory.ie;
468	case REG_WAVE_0:
469	case REG_WAVE_1:
470	case REG_WAVE_2:
471	case REG_WAVE_3:
472	case REG_WAVE_4:
473	case REG_WAVE_5:
474	case REG_WAVE_6:
475	case REG_WAVE_7:
476	case REG_WAVE_8:
477	case REG_WAVE_9:
478	case REG_WAVE_A:
479	case REG_WAVE_B:
480	case REG_WAVE_C:
481	case REG_WAVE_D:
482	case REG_WAVE_E:
483	case REG_WAVE_F:
484		if (gb->audio.playingCh3) {
485			if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
486				return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
487			} else {
488				return 0xFF;
489			}
490		} else {
491			return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
492		}
493		break;
494	case REG_IF:
495	case REG_NR10:
496	case REG_NR11:
497	case REG_NR12:
498	case REG_NR14:
499	case REG_NR21:
500	case REG_NR22:
501	case REG_NR24:
502	case REG_NR30:
503	case REG_NR32:
504	case REG_NR34:
505	case REG_NR41:
506	case REG_NR42:
507	case REG_NR43:
508	case REG_NR44:
509	case REG_NR50:
510	case REG_NR51:
511	case REG_NR52:
512	case REG_DIV:
513	case REG_TIMA:
514	case REG_TMA:
515	case REG_TAC:
516	case REG_STAT:
517	case REG_LCDC:
518	case REG_SCY:
519	case REG_SCX:
520	case REG_LY:
521	case REG_LYC:
522	case REG_BGP:
523	case REG_OBP0:
524	case REG_OBP1:
525	case REG_WY:
526	case REG_WX:
527		// Handled transparently by the registers
528		break;
529	default:
530		if (gb->model >= GB_MODEL_CGB) {
531			switch (address) {
532			case REG_KEY1:
533			case REG_VBK:
534			case REG_HDMA1:
535			case REG_HDMA2:
536			case REG_HDMA3:
537			case REG_HDMA4:
538			case REG_HDMA5:
539			case REG_BCPD:
540			case REG_OCPD:
541			case REG_SVBK:
542				// Handled transparently by the registers
543				goto success;
544			default:
545				break;
546			}
547		}
548		mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
549		return 0xFF;
550	}
551	success:
552	return gb->memory.io[address] | _registerMask[address];
553}