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_KEY1] = 0x7E,
39 [REG_VBK] = 0xFE,
40 [REG_OCPS] = 0x40,
41 [REG_BCPS] = 0x40,
42 [REG_UNK6C] = 0xFE,
43 [REG_SVBK] = 0xF8,
44 [REG_UNK75] = 0x8F,
45 [REG_IE] = 0xE0,
46};
47
48void GBIOInit(struct GB* gb) {
49 memset(gb->memory.io, 0, sizeof(gb->memory.io));
50}
51
52void GBIOReset(struct GB* gb) {
53 memset(gb->memory.io, 0, sizeof(gb->memory.io));
54
55 GBIOWrite(gb, REG_TIMA, 0);
56 GBIOWrite(gb, REG_TMA, 0);
57 GBIOWrite(gb, REG_TAC, 0);
58 GBIOWrite(gb, REG_IF, 1);
59 GBIOWrite(gb, REG_NR52, 0xF1);
60 GBIOWrite(gb, REG_NR10, 0x80);
61 GBIOWrite(gb, REG_NR11, 0xBF);
62 GBIOWrite(gb, REG_NR12, 0xF3);
63 GBIOWrite(gb, REG_NR13, 0xF3);
64 GBIOWrite(gb, REG_NR14, 0xBF);
65 GBIOWrite(gb, REG_NR21, 0x3F);
66 GBIOWrite(gb, REG_NR22, 0x00);
67 GBIOWrite(gb, REG_NR24, 0xBF);
68 GBIOWrite(gb, REG_NR30, 0x7F);
69 GBIOWrite(gb, REG_NR31, 0xFF);
70 GBIOWrite(gb, REG_NR32, 0x9F);
71 GBIOWrite(gb, REG_NR34, 0xBF);
72 GBIOWrite(gb, REG_NR41, 0xFF);
73 GBIOWrite(gb, REG_NR42, 0x00);
74 GBIOWrite(gb, REG_NR43, 0x00);
75 GBIOWrite(gb, REG_NR44, 0xBF);
76 GBIOWrite(gb, REG_NR50, 0x77);
77 GBIOWrite(gb, REG_NR51, 0xF3);
78 GBIOWrite(gb, REG_LCDC, 0x91);
79 GBIOWrite(gb, REG_SCY, 0x00);
80 GBIOWrite(gb, REG_SCX, 0x00);
81 GBIOWrite(gb, REG_LYC, 0x00);
82 GBIOWrite(gb, REG_BGP, 0xFC);
83 GBIOWrite(gb, REG_OBP0, 0xFF);
84 GBIOWrite(gb, REG_OBP1, 0xFF);
85 GBIOWrite(gb, REG_WY, 0x00);
86 GBIOWrite(gb, REG_WX, 0x00);
87 GBIOWrite(gb, REG_IE, 0x00);
88}
89
90void GBIOWrite(struct GB* gb, unsigned address, uint8_t value) {
91 switch (address) {
92 case REG_DIV:
93 GBTimerDivReset(&gb->timer);
94 return;
95 case REG_NR10:
96 if (gb->audio.enable) {
97 GBAudioWriteNR10(&gb->audio, value);
98 } else {
99 value = 0;
100 }
101 break;
102 case REG_NR11:
103 if (gb->audio.enable) {
104 GBAudioWriteNR11(&gb->audio, value);
105 } else {
106 if (gb->audio.style == GB_AUDIO_DMG) {
107 GBAudioWriteNR11(&gb->audio, value & _registerMask[REG_NR11]);
108 }
109 value = 0;
110 }
111 break;
112 case REG_NR12:
113 if (gb->audio.enable) {
114 GBAudioWriteNR12(&gb->audio, value);
115 } else {
116 value = 0;
117 }
118 break;
119 case REG_NR13:
120 if (gb->audio.enable) {
121 GBAudioWriteNR13(&gb->audio, value);
122 } else {
123 value = 0;
124 }
125 break;
126 case REG_NR14:
127 if (gb->audio.enable) {
128 GBAudioWriteNR14(&gb->audio, value);
129 } else {
130 value = 0;
131 }
132 break;
133 case REG_NR21:
134 if (gb->audio.enable) {
135 GBAudioWriteNR21(&gb->audio, value);
136 } else {
137 if (gb->audio.style == GB_AUDIO_DMG) {
138 GBAudioWriteNR21(&gb->audio, value & _registerMask[REG_NR21]);
139 }
140 value = 0;
141 }
142 break;
143 case REG_NR22:
144 if (gb->audio.enable) {
145 GBAudioWriteNR22(&gb->audio, value);
146 } else {
147 value = 0;
148 }
149 break;
150 case REG_NR23:
151 if (gb->audio.enable) {
152 GBAudioWriteNR23(&gb->audio, value);
153 } else {
154 value = 0;
155 }
156 break;
157 case REG_NR24:
158 if (gb->audio.enable) {
159 GBAudioWriteNR24(&gb->audio, value);
160 } else {
161 value = 0;
162 }
163 break;
164 case REG_NR30:
165 if (gb->audio.enable) {
166 GBAudioWriteNR30(&gb->audio, value);
167 } else {
168 value = 0;
169 }
170 break;
171 case REG_NR31:
172 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
173 GBAudioWriteNR31(&gb->audio, value);
174 } else {
175 value = 0;
176 }
177 break;
178 case REG_NR32:
179 if (gb->audio.enable) {
180 GBAudioWriteNR32(&gb->audio, value);
181 } else {
182 value = 0;
183 }
184 break;
185 case REG_NR33:
186 if (gb->audio.enable) {
187 GBAudioWriteNR33(&gb->audio, value);
188 } else {
189 value = 0;
190 }
191 break;
192 case REG_NR34:
193 if (gb->audio.enable) {
194 GBAudioWriteNR34(&gb->audio, value);
195 } else {
196 value = 0;
197 }
198 break;
199 case REG_NR41:
200 if (gb->audio.enable || gb->audio.style == GB_AUDIO_DMG) {
201 GBAudioWriteNR41(&gb->audio, value);
202 } else {
203 value = 0;
204 }
205 break;
206 case REG_NR42:
207 if (gb->audio.enable) {
208 GBAudioWriteNR42(&gb->audio, value);
209 } else {
210 value = 0;
211 }
212 break;
213 case REG_NR43:
214 if (gb->audio.enable) {
215 GBAudioWriteNR43(&gb->audio, value);
216 } else {
217 value = 0;
218 }
219 break;
220 case REG_NR44:
221 if (gb->audio.enable) {
222 GBAudioWriteNR44(&gb->audio, value);
223 } else {
224 value = 0;
225 }
226 break;
227 case REG_NR50:
228 if (gb->audio.enable) {
229 GBAudioWriteNR50(&gb->audio, value);
230 } else {
231 value = 0;
232 }
233 break;
234 case REG_NR51:
235 if (gb->audio.enable) {
236 GBAudioWriteNR51(&gb->audio, value);
237 } else {
238 value = 0;
239 }
240 break;
241 case REG_NR52:
242 GBAudioWriteNR52(&gb->audio, value);
243 value &= 0x80;
244 value |= gb->memory.io[REG_NR52] & 0x0F;
245 break;
246 case REG_WAVE_0:
247 case REG_WAVE_1:
248 case REG_WAVE_2:
249 case REG_WAVE_3:
250 case REG_WAVE_4:
251 case REG_WAVE_5:
252 case REG_WAVE_6:
253 case REG_WAVE_7:
254 case REG_WAVE_8:
255 case REG_WAVE_9:
256 case REG_WAVE_A:
257 case REG_WAVE_B:
258 case REG_WAVE_C:
259 case REG_WAVE_D:
260 case REG_WAVE_E:
261 case REG_WAVE_F:
262 if (!gb->audio.playingCh3 || gb->audio.style != GB_AUDIO_DMG) {
263 gb->audio.ch3.wavedata8[address - REG_WAVE_0] = value;
264 } else if(gb->audio.ch3.readable) {
265 gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1] = value;
266 }
267 break;
268 case REG_JOYP:
269 case REG_TIMA:
270 case REG_TMA:
271 case REG_LYC:
272 // Handled transparently by the registers
273 break;
274 case REG_TAC:
275 value = GBTimerUpdateTAC(&gb->timer, value);
276 break;
277 case REG_IF:
278 gb->memory.io[REG_IF] = value | 0xE0;
279 GBUpdateIRQs(gb);
280 return;
281 case REG_LCDC:
282 // TODO: handle GBC differences
283 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
284 GBVideoWriteLCDC(&gb->video, value);
285 break;
286 case REG_DMA:
287 GBMemoryDMA(gb, value << 8);
288 break;
289 case REG_SCY:
290 case REG_SCX:
291 case REG_WY:
292 case REG_WX:
293 GBVideoProcessDots(&gb->video);
294 value = gb->video.renderer->writeVideoRegister(gb->video.renderer, address, value);
295 break;
296 case REG_BGP:
297 case REG_OBP0:
298 case REG_OBP1:
299 GBVideoProcessDots(&gb->video);
300 GBVideoWritePalette(&gb->video, address, value);
301 break;
302 case REG_STAT:
303 GBVideoWriteSTAT(&gb->video, value);
304 break;
305 case REG_IE:
306 gb->memory.ie = value;
307 GBUpdateIRQs(gb);
308 return;
309 default:
310 if (gb->model >= GB_MODEL_CGB) {
311 switch (address) {
312 case REG_KEY1:
313 value &= 0x1;
314 value |= gb->memory.io[address] & 0x80;
315 break;
316 case REG_VBK:
317 GBVideoSwitchBank(&gb->video, value);
318 break;
319 case REG_HDMA1:
320 case REG_HDMA2:
321 case REG_HDMA3:
322 case REG_HDMA4:
323 // Handled transparently by the registers
324 break;
325 case REG_HDMA5:
326 GBMemoryWriteHDMA5(gb, value);
327 value &= 0x7F;
328 break;
329 case REG_BCPS:
330 gb->video.bcpIndex = value & 0x3F;
331 gb->video.bcpIncrement = value & 0x80;
332 break;
333 case REG_BCPD:
334 GBVideoProcessDots(&gb->video);
335 GBVideoWritePalette(&gb->video, address, value);
336 break;
337 case REG_OCPS:
338 gb->video.ocpIndex = value & 0x3F;
339 gb->video.ocpIncrement = value & 0x80;
340 break;
341 case REG_OCPD:
342 GBVideoProcessDots(&gb->video);
343 GBVideoWritePalette(&gb->video, address, value);
344 break;
345 case REG_SVBK:
346 GBMemorySwitchWramBank(&gb->memory, value);
347 break;
348 default:
349 goto failed;
350 }
351 goto success;
352 }
353 failed:
354 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
355 if (address >= GB_SIZE_IO) {
356 return;
357 }
358 break;
359 }
360 success:
361 gb->memory.io[address] = value;
362}
363
364static uint8_t _readKeys(struct GB* gb) {
365 uint8_t keys = *gb->keySource;
366 switch (gb->memory.io[REG_JOYP] & 0x30) {
367 case 0x30:
368 keys = 0;
369 break;
370 case 0x20:
371 keys >>= 4;
372 break;
373 case 0x10:
374 break;
375 case 0x00:
376 keys |= keys >> 4;
377 break;
378 }
379 return 0xC0 | (gb->memory.io[REG_JOYP] | 0xF) ^ (keys & 0xF);
380}
381
382uint8_t GBIORead(struct GB* gb, unsigned address) {
383 switch (address) {
384 case REG_JOYP:
385 return _readKeys(gb);
386 case REG_SB:
387 case REG_SC:
388 // TODO
389 break;
390 case REG_IE:
391 return gb->memory.ie;
392 case REG_WAVE_0:
393 case REG_WAVE_1:
394 case REG_WAVE_2:
395 case REG_WAVE_3:
396 case REG_WAVE_4:
397 case REG_WAVE_5:
398 case REG_WAVE_6:
399 case REG_WAVE_7:
400 case REG_WAVE_8:
401 case REG_WAVE_9:
402 case REG_WAVE_A:
403 case REG_WAVE_B:
404 case REG_WAVE_C:
405 case REG_WAVE_D:
406 case REG_WAVE_E:
407 case REG_WAVE_F:
408 if (gb->audio.playingCh3) {
409 if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
410 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
411 } else {
412 return 0xFF;
413 }
414 } else {
415 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
416 }
417 break;
418 case REG_IF:
419 case REG_NR10:
420 case REG_NR11:
421 case REG_NR12:
422 case REG_NR14:
423 case REG_NR21:
424 case REG_NR22:
425 case REG_NR24:
426 case REG_NR30:
427 case REG_NR32:
428 case REG_NR34:
429 case REG_NR41:
430 case REG_NR42:
431 case REG_NR43:
432 case REG_NR44:
433 case REG_NR50:
434 case REG_NR51:
435 case REG_NR52:
436 case REG_DIV:
437 case REG_TIMA:
438 case REG_TMA:
439 case REG_TAC:
440 case REG_STAT:
441 case REG_LCDC:
442 case REG_SCY:
443 case REG_SCX:
444 case REG_LY:
445 case REG_LYC:
446 case REG_BGP:
447 case REG_OBP0:
448 case REG_OBP1:
449 case REG_WY:
450 case REG_WX:
451 // Handled transparently by the registers
452 break;
453 default:
454 if (gb->model >= GB_MODEL_CGB) {
455 switch (address) {
456 case REG_VBK:
457 case REG_HDMA1:
458 case REG_HDMA2:
459 case REG_HDMA3:
460 case REG_HDMA4:
461 case REG_HDMA5:
462 case REG_SVBK:
463 case REG_KEY1:
464 // Handled transparently by the registers
465 goto success;
466 default:
467 break;
468 }
469 }
470 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
471 return 0xFF;
472 }
473 success:
474 return gb->memory.io[address] | _registerMask[address];
475}