all repos — mgba @ ed94288902a67d9dd0fd86211e07cb27000ec826

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 static uint8_t _registerMask[] = {
 13	[REG_SC]   = 0x7E, // TODO: GBC differences
 14	[REG_IF]   = 0xE0,
 15	[REG_TAC]  = 0xF8,
 16	[REG_NR10] = 0x80,
 17	[REG_NR11] = 0x3F,
 18	[REG_NR12] = 0x00,
 19	[REG_NR13] = 0xFF,
 20	[REG_NR14] = 0xBF,
 21	[REG_NR21] = 0x3F,
 22	[REG_NR22] = 0x00,
 23	[REG_NR23] = 0xFF,
 24	[REG_NR24] = 0xBF,
 25	[REG_NR30] = 0x7F,
 26	[REG_NR31] = 0xFF,
 27	[REG_NR32] = 0x9F,
 28	[REG_NR33] = 0xFF,
 29	[REG_NR34] = 0xBF,
 30	[REG_NR41] = 0xFF,
 31	[REG_NR42] = 0x00,
 32	[REG_NR43] = 0x00,
 33	[REG_NR44] = 0xBF,
 34	[REG_NR50] = 0x00,
 35	[REG_NR51] = 0x00,
 36	[REG_NR52] = 0x70,
 37	[REG_STAT] = 0x80,
 38	[REG_IE]   = 0xE0,
 39};
 40
 41void GBIOInit(struct GB* gb) {
 42	memset(gb->memory.io, 0, sizeof(gb->memory.io));
 43}
 44
 45void GBIOReset(struct GB* gb) {
 46	memset(gb->memory.io, 0, sizeof(gb->memory.io));
 47
 48	GBIOWrite(gb, REG_TIMA, 0);
 49	GBIOWrite(gb, REG_TMA, 0);
 50	GBIOWrite(gb, REG_TAC, 0);
 51	GBIOWrite(gb, REG_IF, 1);
 52	GBIOWrite(gb, REG_NR52, 0xF1);
 53	GBIOWrite(gb, REG_NR10, 0x80);
 54	GBIOWrite(gb, REG_NR11, 0xBF);
 55	GBIOWrite(gb, REG_NR12, 0xF3);
 56	GBIOWrite(gb, REG_NR13, 0xF3);
 57	GBIOWrite(gb, REG_NR14, 0xBF);
 58	GBIOWrite(gb, REG_NR21, 0x3F);
 59	GBIOWrite(gb, REG_NR22, 0x00);
 60	GBIOWrite(gb, REG_NR24, 0xBF);
 61	GBIOWrite(gb, REG_NR30, 0x7F);
 62	GBIOWrite(gb, REG_NR31, 0xFF);
 63	GBIOWrite(gb, REG_NR32, 0x9F);
 64	GBIOWrite(gb, REG_NR34, 0xBF);
 65	GBIOWrite(gb, REG_NR41, 0xFF);
 66	GBIOWrite(gb, REG_NR42, 0x00);
 67	GBIOWrite(gb, REG_NR43, 0x00);
 68	GBIOWrite(gb, REG_NR44, 0xBF);
 69	GBIOWrite(gb, REG_NR50, 0x77);
 70	GBIOWrite(gb, REG_NR51, 0xF3);
 71	GBIOWrite(gb, REG_LCDC, 0x91);
 72	GBIOWrite(gb, REG_SCY, 0x00);
 73	GBIOWrite(gb, REG_SCX, 0x00);
 74	GBIOWrite(gb, REG_LYC, 0x00);
 75	GBIOWrite(gb, REG_BGP, 0xFC);
 76	GBIOWrite(gb, REG_OBP0, 0xFF);
 77	GBIOWrite(gb, REG_OBP1, 0xFF);
 78	GBIOWrite(gb, REG_WY, 0x00);
 79	GBIOWrite(gb, REG_WX, 0x00);
 80	GBIOWrite(gb, REG_IE, 0x00);
 81}
 82
 83void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
 84	switch (address) {
 85	case REG_DIV:
 86		GBTimerDivReset(&gb->timer);
 87		return;
 88	case REG_NR10:
 89		if (gb->audio.enable) {
 90			GBAudioWriteNR10(&gb->audio, value);
 91		} else {
 92			value = 0;
 93		}
 94		break;
 95	case REG_NR11:
 96		if (gb->audio.enable) {
 97			GBAudioWriteNR11(&gb->audio, value);
 98		} else {
 99			value = 0;
100		}
101		break;
102	case REG_NR12:
103		if (gb->audio.enable) {
104			GBAudioWriteNR12(&gb->audio, value);
105		} else {
106			value = 0;
107		}
108		break;
109	case REG_NR13:
110		if (gb->audio.enable) {
111			GBAudioWriteNR13(&gb->audio, value);
112		} else {
113			value = 0;
114		}
115		break;
116	case REG_NR14:
117		if (gb->audio.enable) {
118			GBAudioWriteNR14(&gb->audio, value);
119		} else {
120			value = 0;
121		}
122		break;
123	case REG_NR21:
124		if (gb->audio.enable) {
125			GBAudioWriteNR21(&gb->audio, value);
126		} else {
127			value = 0;
128		}
129		break;
130	case REG_NR22:
131		if (gb->audio.enable) {
132			GBAudioWriteNR22(&gb->audio, value);
133		} else {
134			value = 0;
135		}
136		break;
137	case REG_NR23:
138		if (gb->audio.enable) {
139			GBAudioWriteNR23(&gb->audio, value);
140		} else {
141			value = 0;
142		}
143		break;
144	case REG_NR24:
145		if (gb->audio.enable) {
146			GBAudioWriteNR24(&gb->audio, value);
147		} else {
148			value = 0;
149		}
150		break;
151	case REG_NR30:
152		if (gb->audio.enable) {
153			GBAudioWriteNR30(&gb->audio, value);
154		} else {
155			value = 0;
156		}
157		break;
158	case REG_NR31:
159		if (gb->audio.enable) {
160			GBAudioWriteNR31(&gb->audio, value);
161		} else {
162			value = 0;
163		}
164		break;
165	case REG_NR32:
166		if (gb->audio.enable) {
167			GBAudioWriteNR32(&gb->audio, value);
168		} else {
169			value = 0;
170		}
171		break;
172	case REG_NR33:
173		if (gb->audio.enable) {
174			GBAudioWriteNR33(&gb->audio, value);
175		} else {
176			value = 0;
177		}
178		break;
179	case REG_NR34:
180		if (gb->audio.enable) {
181			GBAudioWriteNR34(&gb->audio, value);
182		} else {
183			value = 0;
184		}
185		break;
186	case REG_NR41:
187		// NR41 is exempt, for some reason
188		GBAudioWriteNR41(&gb->audio, value);
189		break;
190	case REG_NR42:
191		if (gb->audio.enable) {
192			GBAudioWriteNR42(&gb->audio, value);
193		} else {
194			value = 0;
195		}
196		break;
197	case REG_NR43:
198		if (gb->audio.enable) {
199			GBAudioWriteNR43(&gb->audio, value);
200		} else {
201			value = 0;
202		}
203		break;
204	case REG_NR44:
205		if (gb->audio.enable) {
206			GBAudioWriteNR44(&gb->audio, value);
207		} else {
208			value = 0;
209		}
210		break;
211	case REG_NR50:
212		if (gb->audio.enable) {
213			GBAudioWriteNR50(&gb->audio, value);
214		} else {
215			value = 0;
216		}
217		break;
218	case REG_NR51:
219		if (gb->audio.enable) {
220			GBAudioWriteNR51(&gb->audio, value);
221		} else {
222			value = 0;
223		}
224		break;
225	case REG_NR52:
226		GBAudioWriteNR52(&gb->audio, value);
227		value &= 0x80;
228		value |= gb->memory.io[REG_NR52] & 0x0F;
229		break;
230	case REG_WAVE_0:
231	case REG_WAVE_1:
232	case REG_WAVE_2:
233	case REG_WAVE_3:
234	case REG_WAVE_4:
235	case REG_WAVE_5:
236	case REG_WAVE_6:
237	case REG_WAVE_7:
238	case REG_WAVE_8:
239	case REG_WAVE_9:
240	case REG_WAVE_A:
241	case REG_WAVE_B:
242	case REG_WAVE_C:
243	case REG_WAVE_D:
244	case REG_WAVE_E:
245	case REG_WAVE_F:
246		if (!gb->audio.playingCh3) {
247			gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
248		} else if(gb->audio.ch3.readable) {
249			gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
250		}
251		break;
252	case REG_JOYP:
253	case REG_TIMA:
254	case REG_TMA:
255	case REG_LYC:
256		// Handled transparently by the registers
257		break;
258	case REG_TAC:
259		value = GBTimerUpdateTAC(&gb->timer, value);
260		break;
261	case REG_IF:
262		gb->memory.io[REG_IF] = value | 0xE0;
263		GBUpdateIRQs(gb);
264		return;
265	case REG_LCDC:
266		// TODO: handle GBC differences
267		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
268		GBVideoWriteLCDC(&gb->video, value);
269		break;
270	case REG_DMA:
271		GBMemoryDMA(gb, value << 8);
272		break;
273	case REG_SCY:
274	case REG_SCX:
275	case REG_WY:
276	case REG_WX:
277	case REG_BGP:
278	case REG_OBP0:
279	case REG_OBP1:
280		GBVideoProcessDots(&gb->video);
281		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
282		break;
283	case REG_STAT:
284		GBVideoWriteSTAT(&gb->video, value);
285		break;
286	case REG_IE:
287		gb->memory.ie = value;
288		GBUpdateIRQs(gb);
289		return;
290	default:
291		mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
292		if (address >= GB_SIZE_IO) {
293			return;
294		}
295		break;
296	}
297	gb->memory.io[address] = value;
298}
299
300static uint8_t _readKeys(struct GB* gb) {
301	uint8_t keys = *gb->keySource;
302	switch (gb->memory.io[REG_JOYP] & 0x30) {
303	case 0x20:
304		keys >>= 4;
305		break;
306	case 0x10:
307		break;
308	default:
309		// ???
310		keys = 0;
311		break;
312	}
313	return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
314}
315
316uint8_t GBIORead(struct GB* gb, unsigned address) {
317	switch (address) {
318	case REG_JOYP:
319		return _readKeys(gb);
320	case REG_SB:
321	case REG_SC:
322		// TODO
323		break;
324	case REG_IE:
325		return gb->memory.ie;
326	case REG_WAVE_0:
327	case REG_WAVE_1:
328	case REG_WAVE_2:
329	case REG_WAVE_3:
330	case REG_WAVE_4:
331	case REG_WAVE_5:
332	case REG_WAVE_6:
333	case REG_WAVE_7:
334	case REG_WAVE_8:
335	case REG_WAVE_9:
336	case REG_WAVE_A:
337	case REG_WAVE_B:
338	case REG_WAVE_C:
339	case REG_WAVE_D:
340	case REG_WAVE_E:
341	case REG_WAVE_F:
342		if (gb->audio.playingCh3) {
343			if (gb->audio.ch3.readable) {
344				return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
345			} else {
346				return 0xFF;
347			}
348		} else {
349			return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
350		}
351		break;
352	case REG_IF:
353	case REG_NR10:
354	case REG_NR11:
355	case REG_NR12:
356	case REG_NR14:
357	case REG_NR21:
358	case REG_NR22:
359	case REG_NR24:
360	case REG_NR30:
361	case REG_NR32:
362	case REG_NR34:
363	case REG_NR41:
364	case REG_NR42:
365	case REG_NR43:
366	case REG_NR44:
367	case REG_NR50:
368	case REG_NR51:
369	case REG_NR52:
370	case REG_DIV:
371	case REG_TIMA:
372	case REG_TMA:
373	case REG_TAC:
374	case REG_STAT:
375	case REG_LCDC:
376	case REG_SCY:
377	case REG_SCX:
378	case REG_LY:
379	case REG_LYC:
380	case REG_BGP:
381	case REG_OBP0:
382	case REG_OBP1:
383	case REG_WY:
384	case REG_WX:
385		// Handled transparently by the registers
386		break;
387	default:
388		mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
389		return 0xFF;
390	}
391	return gb->memory.io[address] | _registerMask[address];
392}