all repos — mgba @ 94ff4f7c4e25c717f3dc0b049e0e54c1818688ce

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 || gb->audio.ch3.readable) {
247			gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
248		}
249		break;
250	case REG_JOYP:
251	case REG_TIMA:
252	case REG_TMA:
253	case REG_LYC:
254		// Handled transparently by the registers
255		break;
256	case REG_TAC:
257		value = GBTimerUpdateTAC(&gb->timer, value);
258		break;
259	case REG_IF:
260		gb->memory.io[REG_IF] = value | 0xE0;
261		GBUpdateIRQs(gb);
262		return;
263	case REG_LCDC:
264		// TODO: handle GBC differences
265		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
266		GBVideoWriteLCDC(&gb->video, value);
267		break;
268	case REG_DMA:
269		GBMemoryDMA(gb, value << 8);
270		break;
271	case REG_SCY:
272	case REG_SCX:
273	case REG_WY:
274	case REG_WX:
275	case REG_BGP:
276	case REG_OBP0:
277	case REG_OBP1:
278		GBVideoProcessDots(&gb->video);
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_WAVE_0:
325	case REG_WAVE_1:
326	case REG_WAVE_2:
327	case REG_WAVE_3:
328	case REG_WAVE_4:
329	case REG_WAVE_5:
330	case REG_WAVE_6:
331	case REG_WAVE_7:
332	case REG_WAVE_8:
333	case REG_WAVE_9:
334	case REG_WAVE_A:
335	case REG_WAVE_B:
336	case REG_WAVE_C:
337	case REG_WAVE_D:
338	case REG_WAVE_E:
339	case REG_WAVE_F:
340		if (gb->audio.playingCh3) {
341			if (gb->audio.ch3.readable) {
342				return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
343			} else {
344				return 0xFF;
345			}
346		} else {
347			return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
348		}
349		break;
350	case REG_IF:
351	case REG_NR10:
352	case REG_NR11:
353	case REG_NR12:
354	case REG_NR14:
355	case REG_NR21:
356	case REG_NR22:
357	case REG_NR24:
358	case REG_NR30:
359	case REG_NR32:
360	case REG_NR34:
361	case REG_NR41:
362	case REG_NR42:
363	case REG_NR43:
364	case REG_NR44:
365	case REG_NR50:
366	case REG_NR51:
367	case REG_NR52:
368	case REG_DIV:
369	case REG_TIMA:
370	case REG_TMA:
371	case REG_TAC:
372	case REG_STAT:
373	case REG_LCDC:
374	case REG_SCY:
375	case REG_SCX:
376	case REG_LY:
377	case REG_LYC:
378	case REG_BGP:
379	case REG_OBP0:
380	case REG_OBP1:
381	case REG_WY:
382	case REG_WX:
383		// Handled transparently by the registers
384		break;
385	default:
386		mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
387		return 0xFF;
388	}
389	return gb->memory.io[address] | _registerMask[address];
390}