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}