all repos — mgba @ 3cb5cdee9416de28f6f76f4a2e57b8fb4cf408cb

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			GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
100			value = 0;
101		}
102		break;
103	case REG_NR12:
104		if (gb->audio.enable) {
105			GBAudioWriteNR12(&gb->audio, value);
106		} else {
107			value = 0;
108		}
109		break;
110	case REG_NR13:
111		if (gb->audio.enable) {
112			GBAudioWriteNR13(&gb->audio, value);
113		} else {
114			value = 0;
115		}
116		break;
117	case REG_NR14:
118		if (gb->audio.enable) {
119			GBAudioWriteNR14(&gb->audio, value);
120		} else {
121			value = 0;
122		}
123		break;
124	case REG_NR21:
125		if (gb->audio.enable) {
126			GBAudioWriteNR21(&gb->audio, value);
127		} else {
128			GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
129			value = 0;
130		}
131		break;
132	case REG_NR22:
133		if (gb->audio.enable) {
134			GBAudioWriteNR22(&gb->audio, value);
135		} else {
136			value = 0;
137		}
138		break;
139	case REG_NR23:
140		if (gb->audio.enable) {
141			GBAudioWriteNR23(&gb->audio, value);
142		} else {
143			value = 0;
144		}
145		break;
146	case REG_NR24:
147		if (gb->audio.enable) {
148			GBAudioWriteNR24(&gb->audio, value);
149		} else {
150			value = 0;
151		}
152		break;
153	case REG_NR30:
154		if (gb->audio.enable) {
155			GBAudioWriteNR30(&gb->audio, value);
156		} else {
157			value = 0;
158		}
159		break;
160	case REG_NR31:
161		if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
162			GBAudioWriteNR31(&gb->audio, value);
163		} else {
164			value = 0;
165		}
166		break;
167	case REG_NR32:
168		if (gb->audio.enable) {
169			GBAudioWriteNR32(&gb->audio, value);
170		} else {
171			value = 0;
172		}
173		break;
174	case REG_NR33:
175		if (gb->audio.enable) {
176			GBAudioWriteNR33(&gb->audio, value);
177		} else {
178			value = 0;
179		}
180		break;
181	case REG_NR34:
182		if (gb->audio.enable) {
183			GBAudioWriteNR34(&gb->audio, value);
184		} else {
185			value = 0;
186		}
187		break;
188	case REG_NR41:
189		if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
190			GBAudioWriteNR41(&gb->audio, value);
191		} else {
192			value = 0;
193		}
194		break;
195	case REG_NR42:
196		if (gb->audio.enable) {
197			GBAudioWriteNR42(&gb->audio, value);
198		} else {
199			value = 0;
200		}
201		break;
202	case REG_NR43:
203		if (gb->audio.enable) {
204			GBAudioWriteNR43(&gb->audio, value);
205		} else {
206			value = 0;
207		}
208		break;
209	case REG_NR44:
210		if (gb->audio.enable) {
211			GBAudioWriteNR44(&gb->audio, value);
212		} else {
213			value = 0;
214		}
215		break;
216	case REG_NR50:
217		if (gb->audio.enable) {
218			GBAudioWriteNR50(&gb->audio, value);
219		} else {
220			value = 0;
221		}
222		break;
223	case REG_NR51:
224		if (gb->audio.enable) {
225			GBAudioWriteNR51(&gb->audio, value);
226		} else {
227			value = 0;
228		}
229		break;
230	case REG_NR52:
231		GBAudioWriteNR52(&gb->audio, value);
232		value &= 0x80;
233		value |= gb->memory.io[REG_NR52] & 0x0F;
234		break;
235	case REG_WAVE_0:
236	case REG_WAVE_1:
237	case REG_WAVE_2:
238	case REG_WAVE_3:
239	case REG_WAVE_4:
240	case REG_WAVE_5:
241	case REG_WAVE_6:
242	case REG_WAVE_7:
243	case REG_WAVE_8:
244	case REG_WAVE_9:
245	case REG_WAVE_A:
246	case REG_WAVE_B:
247	case REG_WAVE_C:
248	case REG_WAVE_D:
249	case REG_WAVE_E:
250	case REG_WAVE_F:
251		if (!gb->audio.playingCh3) {
252			gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
253		} else if(gb->audio.ch3.readable) {
254			gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
255		}
256		break;
257	case REG_JOYP:
258	case REG_TIMA:
259	case REG_TMA:
260	case REG_LYC:
261		// Handled transparently by the registers
262		break;
263	case REG_TAC:
264		value = GBTimerUpdateTAC(&gb->timer, value);
265		break;
266	case REG_IF:
267		gb->memory.io[REG_IF] = value | 0xE0;
268		GBUpdateIRQs(gb);
269		return;
270	case REG_LCDC:
271		// TODO: handle GBC differences
272		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
273		GBVideoWriteLCDC(&gb->video, value);
274		break;
275	case REG_DMA:
276		GBMemoryDMA(gb, value << 8);
277		break;
278	case REG_SCY:
279	case REG_SCX:
280	case REG_WY:
281	case REG_WX:
282	case REG_BGP:
283	case REG_OBP0:
284	case REG_OBP1:
285		GBVideoProcessDots(&gb->video);
286		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
287		break;
288	case REG_STAT:
289		GBVideoWriteSTAT(&gb->video, value);
290		break;
291	case REG_IE:
292		gb->memory.ie = value;
293		GBUpdateIRQs(gb);
294		return;
295	default:
296		mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
297		if (address >= GB_SIZE_IO) {
298			return;
299		}
300		break;
301	}
302	gb->memory.io[address] = value;
303}
304
305static uint8_t _readKeys(struct GB* gb) {
306	uint8_t keys = *gb->keySource;
307	switch (gb->memory.io[REG_JOYP] & 0x30) {
308	case 0x20:
309		keys >>= 4;
310		break;
311	case 0x10:
312		break;
313	default:
314		// ???
315		keys = 0;
316		break;
317	}
318	return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
319}
320
321uint8_t GBIORead(struct GB* gb, unsigned address) {
322	switch (address) {
323	case REG_JOYP:
324		return _readKeys(gb);
325	case REG_SB:
326	case REG_SC:
327		// TODO
328		break;
329	case REG_IE:
330		return gb->memory.ie;
331	case REG_WAVE_0:
332	case REG_WAVE_1:
333	case REG_WAVE_2:
334	case REG_WAVE_3:
335	case REG_WAVE_4:
336	case REG_WAVE_5:
337	case REG_WAVE_6:
338	case REG_WAVE_7:
339	case REG_WAVE_8:
340	case REG_WAVE_9:
341	case REG_WAVE_A:
342	case REG_WAVE_B:
343	case REG_WAVE_C:
344	case REG_WAVE_D:
345	case REG_WAVE_E:
346	case REG_WAVE_F:
347		if (gb->audio.playingCh3) {
348			if (gb->audio.ch3.readable) {
349				return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
350			} else {
351				return 0xFF;
352			}
353		} else {
354			return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
355		}
356		break;
357	case REG_IF:
358	case REG_NR10:
359	case REG_NR11:
360	case REG_NR12:
361	case REG_NR14:
362	case REG_NR21:
363	case REG_NR22:
364	case REG_NR24:
365	case REG_NR30:
366	case REG_NR32:
367	case REG_NR34:
368	case REG_NR41:
369	case REG_NR42:
370	case REG_NR43:
371	case REG_NR44:
372	case REG_NR50:
373	case REG_NR51:
374	case REG_NR52:
375	case REG_DIV:
376	case REG_TIMA:
377	case REG_TMA:
378	case REG_TAC:
379	case REG_STAT:
380	case REG_LCDC:
381	case REG_SCY:
382	case REG_SCX:
383	case REG_LY:
384	case REG_LYC:
385	case REG_BGP:
386	case REG_OBP0:
387	case REG_OBP1:
388	case REG_WY:
389	case REG_WX:
390		// Handled transparently by the registers
391		break;
392	default:
393		mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
394		return 0xFF;
395	}
396	return gb->memory.io[address] | _registerMask[address];
397}