all repos — mgba @ 385059c63ab64ada69f328d744342f6a86f497e4

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		if (gb->audio.enable) {
188			GBAudioWriteNR41(&gb->audio, value);
189		} else {
190			value = 0;
191		}
192		break;
193	case REG_NR42:
194		if (gb->audio.enable) {
195			GBAudioWriteNR42(&gb->audio, value);
196		} else {
197			value = 0;
198		}
199		break;
200	case REG_NR43:
201		if (gb->audio.enable) {
202			GBAudioWriteNR43(&gb->audio, value);
203		} else {
204			value = 0;
205		}
206		break;
207	case REG_NR44:
208		if (gb->audio.enable) {
209			GBAudioWriteNR44(&gb->audio, value);
210		} else {
211			value = 0;
212		}
213		break;
214	case REG_NR50:
215		if (gb->audio.enable) {
216			GBAudioWriteNR50(&gb->audio, value);
217		} else {
218			value = 0;
219		}
220		break;
221	case REG_NR51:
222		if (gb->audio.enable) {
223			GBAudioWriteNR51(&gb->audio, value);
224		} else {
225			value = 0;
226		}
227		break;
228	case REG_NR52:
229		GBAudioWriteNR52(&gb->audio, value);
230		value &= 0x80;
231		value |= gb->memory.io[REG_NR52] & 0x0F;
232		break;
233	case REG_WAVE_0:
234	case REG_WAVE_1:
235	case REG_WAVE_2:
236	case REG_WAVE_3:
237	case REG_WAVE_4:
238	case REG_WAVE_5:
239	case REG_WAVE_6:
240	case REG_WAVE_7:
241	case REG_WAVE_8:
242	case REG_WAVE_9:
243	case REG_WAVE_A:
244	case REG_WAVE_B:
245	case REG_WAVE_C:
246	case REG_WAVE_D:
247	case REG_WAVE_E:
248	case REG_WAVE_F:
249		((uint8_t*) gb->audio.ch3.wavedata)[address - REG_WAVE_0] = value; // TODO: Big endian
250		break;
251	case REG_JOYP:
252	case REG_TIMA:
253	case REG_TMA:
254	case REG_LYC:
255		// Handled transparently by the registers
256		break;
257	case REG_TAC:
258		value = GBTimerUpdateTAC(&gb->timer, value);
259		break;
260	case REG_IF:
261		gb->memory.io[REG_IF] = value | 0xE0;
262		GBUpdateIRQs(gb);
263		return;
264	case REG_LCDC:
265		// TODO: handle GBC differences
266		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
267		GBVideoWriteLCDC(&gb->video, value);
268		break;
269	case REG_DMA:
270		GBMemoryDMA(gb, value << 8);
271		break;
272	case REG_SCY:
273	case REG_SCX:
274	case REG_WY:
275	case REG_WX:
276	case REG_BGP:
277	case REG_OBP0:
278	case REG_OBP1:
279		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
280		break;
281	case REG_STAT:
282		GBVideoWriteSTAT(&gb->video, value);
283		break;
284	case REG_IE:
285		gb->memory.ie = value;
286		GBUpdateIRQs(gb);
287		return;
288	default:
289		mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
290		if (address >= GB_SIZE_IO) {
291			return;
292		}
293		break;
294	}
295	gb->memory.io[address] = value;
296}
297
298static uint8_t _readKeys(struct GB* gb) {
299	uint8_t keys = *gb->keySource;
300	switch (gb->memory.io[REG_JOYP] & 0x30) {
301	case 0x20:
302		keys >>= 4;
303		break;
304	case 0x10:
305		break;
306	default:
307		// ???
308		keys = 0;
309		break;
310	}
311	return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
312}
313
314uint8_t GBIORead(struct GB* gb, unsigned address) {
315	switch (address) {
316	case REG_JOYP:
317		return _readKeys(gb);
318	case REG_SB:
319	case REG_SC:
320		// TODO
321		break;
322	case REG_IE:
323		return gb->memory.ie;
324	case REG_IF:
325	case REG_NR10:
326	case REG_NR11:
327	case REG_NR12:
328	case REG_NR14:
329	case REG_NR21:
330	case REG_NR22:
331	case REG_NR24:
332	case REG_NR30:
333	case REG_NR32:
334	case REG_NR34:
335	case REG_NR41:
336	case REG_NR42:
337	case REG_NR43:
338	case REG_NR44:
339	case REG_NR50:
340	case REG_NR51:
341	case REG_NR52:
342	case REG_WAVE_0:
343	case REG_WAVE_1:
344	case REG_WAVE_2:
345	case REG_WAVE_3:
346	case REG_WAVE_4:
347	case REG_WAVE_5:
348	case REG_WAVE_6:
349	case REG_WAVE_7:
350	case REG_WAVE_8:
351	case REG_WAVE_9:
352	case REG_WAVE_A:
353	case REG_WAVE_B:
354	case REG_WAVE_C:
355	case REG_WAVE_D:
356	case REG_WAVE_E:
357	case REG_WAVE_F:
358	case REG_DIV:
359	case REG_TIMA:
360	case REG_TMA:
361	case REG_TAC:
362	case REG_STAT:
363	case REG_LCDC:
364	case REG_SCY:
365	case REG_SCX:
366	case REG_LY:
367	case REG_LYC:
368	case REG_BGP:
369	case REG_OBP0:
370	case REG_OBP1:
371	case REG_WY:
372	case REG_WX:
373		// Handled transparently by the registers
374		break;
375	default:
376		mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
377		return 0xFF;
378	}
379	return gb->memory.io[address] | _registerMask[address];
380}