all repos — mgba @ 92c6b90b03f8c04b53312bf2273d86a9783ee073

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);
 11
 12void GBIOInit(struct GB* gb) {
 13	memset(gb->memory.io, 0, sizeof(gb->memory.io));
 14}
 15
 16void GBIOReset(struct GB* gb) {
 17	memset(gb->memory.io, 0, sizeof(gb->memory.io));
 18
 19	GBIOWrite(gb, 0x05, 0);
 20	GBIOWrite(gb, 0x06, 0);
 21	GBIOWrite(gb, 0x07, 0);
 22	GBIOWrite(gb, 0x10, 0x80);
 23	GBIOWrite(gb, 0x11, 0xBF);
 24	GBIOWrite(gb, 0x12, 0xF3);
 25	GBIOWrite(gb, 0x12, 0xF3);
 26	GBIOWrite(gb, 0x14, 0xBF);
 27	GBIOWrite(gb, 0x16, 0x3F);
 28	GBIOWrite(gb, 0x17, 0x00);
 29	GBIOWrite(gb, 0x19, 0xBF);
 30	GBIOWrite(gb, 0x1A, 0x7F);
 31	GBIOWrite(gb, 0x1B, 0xFF);
 32	GBIOWrite(gb, 0x1C, 0x9F);
 33	GBIOWrite(gb, 0x1E, 0xBF);
 34	GBIOWrite(gb, 0x20, 0xFF);
 35	GBIOWrite(gb, 0x21, 0x00);
 36	GBIOWrite(gb, 0x22, 0x00);
 37	GBIOWrite(gb, 0x23, 0xBF);
 38	GBIOWrite(gb, 0x24, 0x77);
 39	GBIOWrite(gb, 0x25, 0xF3);
 40	GBIOWrite(gb, 0x26, 0xF1);
 41	GBIOWrite(gb, 0x40, 0x91);
 42	GBIOWrite(gb, 0x42, 0x00);
 43	GBIOWrite(gb, 0x43, 0x00);
 44	GBIOWrite(gb, 0x45, 0x00);
 45	GBIOWrite(gb, 0x47, 0xFC);
 46	GBIOWrite(gb, 0x48, 0xFF);
 47	GBIOWrite(gb, 0x49, 0xFF);
 48	GBIOWrite(gb, 0x4A, 0x00);
 49	GBIOWrite(gb, 0x4B, 0x00);
 50	GBIOWrite(gb, 0xFF, 0x00);
 51}
 52
 53void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
 54	switch (address) {
 55	case REG_DIV:
 56		GBTimerDivReset(&gb->timer);
 57		return;
 58	case REG_NR10:
 59		GBAudioWriteNR10(&gb->audio, value);
 60		break;
 61	case REG_NR11:
 62		GBAudioWriteNR11(&gb->audio, value);
 63		break;
 64	case REG_NR12:
 65		GBAudioWriteNR12(&gb->audio, value);
 66		break;
 67	case REG_NR13:
 68		GBAudioWriteNR13(&gb->audio, value);
 69		break;
 70	case REG_NR14:
 71		GBAudioWriteNR14(&gb->audio, value);
 72		break;
 73	case REG_NR21:
 74		GBAudioWriteNR21(&gb->audio, value);
 75		break;
 76	case REG_NR22:
 77		GBAudioWriteNR22(&gb->audio, value);
 78		break;
 79	case REG_NR23:
 80		GBAudioWriteNR23(&gb->audio, value);
 81		break;
 82	case REG_NR24:
 83		GBAudioWriteNR24(&gb->audio, value);
 84		break;
 85	case REG_NR30:
 86		GBAudioWriteNR30(&gb->audio, value);
 87		break;
 88	case REG_NR31:
 89		GBAudioWriteNR31(&gb->audio, value);
 90		break;
 91	case REG_NR32:
 92		GBAudioWriteNR32(&gb->audio, value);
 93		break;
 94	case REG_NR33:
 95		GBAudioWriteNR33(&gb->audio, value);
 96		break;
 97	case REG_NR34:
 98		GBAudioWriteNR34(&gb->audio, value);
 99		break;
100	case REG_NR41:
101		GBAudioWriteNR41(&gb->audio, value);
102		break;
103	case REG_NR42:
104		GBAudioWriteNR42(&gb->audio, value);
105		break;
106	case REG_NR43:
107		GBAudioWriteNR43(&gb->audio, value);
108		break;
109	case REG_NR44:
110		GBAudioWriteNR44(&gb->audio, value);
111		break;
112	case REG_NR50:
113		GBAudioWriteNR50(&gb->audio, value);
114		break;
115	case REG_NR51:
116		GBAudioWriteNR51(&gb->audio, value);
117		break;
118	case REG_NR52:
119		GBAudioWriteNR52(&gb->audio, value);
120		break;
121	case REG_WAVE_0:
122	case REG_WAVE_1:
123	case REG_WAVE_2:
124	case REG_WAVE_3:
125	case REG_WAVE_4:
126	case REG_WAVE_5:
127	case REG_WAVE_6:
128	case REG_WAVE_7:
129	case REG_WAVE_8:
130	case REG_WAVE_9:
131	case REG_WAVE_A:
132	case REG_WAVE_B:
133	case REG_WAVE_C:
134	case REG_WAVE_D:
135	case REG_WAVE_E:
136	case REG_WAVE_F:
137		((uint8_t*) gb->audio.ch3.wavedata)[address - REG_WAVE_0] = value; // TODO: Big endian
138		break;
139	case REG_JOYP:
140	case REG_TIMA:
141	case REG_TMA:
142	case REG_LYC:
143		// Handled transparently by the registers
144		break;
145	case REG_TAC:
146		value = GBTimerUpdateTAC(&gb->timer, value);
147		break;
148	case REG_IF:
149		gb->memory.io[REG_IF] = value | 0xE0;
150		GBUpdateIRQs(gb);
151		return;
152	case REG_LCDC:
153		// TODO: handle GBC differences
154		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
155		GBVideoWriteLCDC(&gb->video, value);
156		break;
157	case REG_DMA:
158		GBMemoryDMA(gb, value << 8);
159		break;
160	case REG_SCY:
161	case REG_SCX:
162	case REG_WY:
163	case REG_WX:
164	case REG_BGP:
165	case REG_OBP0:
166	case REG_OBP1:
167		value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
168		break;
169	case REG_STAT:
170		GBVideoWriteSTAT(&gb->video, value);
171		break;
172	case REG_IE:
173		gb->memory.ie = value;
174		GBUpdateIRQs(gb);
175		return;
176	default:
177		mLOG(GB_MBC, STUB, "Writing to unknown register FF%02X:%02X", address, value);
178		if (address >= GB_SIZE_IO) {
179			return;
180		}
181		break;
182	}
183	gb->memory.io[address] = value;
184}
185
186static uint8_t _readKeys(struct GB* gb) {
187	uint8_t keys = *gb->keySource;
188	switch (gb->memory.io[REG_JOYP] & 0x30) {
189	case 0x20:
190		keys >>= 4;
191		break;
192	case 0x10:
193		break;
194	default:
195		// ???
196		keys = 0;
197		break;
198	}
199	return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
200}
201
202uint8_t GBIORead(struct GB* gb, unsigned address) {
203	switch (address) {
204	case REG_JOYP:
205		return _readKeys(gb);
206	case REG_IF:
207		break;
208	case REG_IE:
209		return gb->memory.ie;
210	case REG_DIV:
211	case REG_TIMA:
212	case REG_TMA:
213	case REG_TAC:
214	case REG_STAT:
215	case REG_LCDC:
216	case REG_SCY:
217	case REG_SCX:
218	case REG_LY:
219	case REG_LYC:
220		// Handled transparently by the registers
221		break;
222	default:
223		mLOG(GB_MBC, STUB, "Reading from unknown register FF%02X", address);
224		if (address >= GB_SIZE_IO) {
225			return 0;
226		}
227		break;
228	}
229	return gb->memory.io[address];
230}