all repos — mgba @ c60251de732a63ce3fa4c8723fbb429fb4a35fac

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