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
12static const 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 gb->memory.io[REG_BCPD] = gb->video.palette[gb->video.bcpIndex >> 1];
333 break;
334 case REG_BCPD:
335 GBVideoProcessDots(&gb->video);
336 GBVideoWritePalette(&gb->video, address, value);
337 break;
338 case REG_OCPS:
339 gb->video.ocpIndex = value & 0x3F;
340 gb->video.ocpIncrement = value & 0x80;
341 gb->memory.io[REG_OCPD] = gb->video.palette[8 * 4 + (gb->video.ocpIndex >> 1)];
342 break;
343 case REG_OCPD:
344 GBVideoProcessDots(&gb->video);
345 GBVideoWritePalette(&gb->video, address, value);
346 break;
347 case REG_SVBK:
348 GBMemorySwitchWramBank(&gb->memory, value);
349 value = gb->memory.wramCurrentBank;
350 break;
351 default:
352 goto failed;
353 }
354 goto success;
355 }
356 failed:
357 mLOG(GB_IO, STUB, "Writing to unknown register FF%02X:%02X", address, value);
358 if (address >= GB_SIZE_IO) {
359 return;
360 }
361 break;
362 }
363 success:
364 gb->memory.io[address] = value;
365}
366
367static uint8_t _readKeys(struct GB* gb) {
368 uint8_t keys = *gb->keySource;
369 switch (gb->memory.io[REG_JOYP] & 0x30) {
370 case 0x30:
371 keys = 0;
372 break;
373 case 0x20:
374 keys >>= 4;
375 break;
376 case 0x10:
377 break;
378 case 0x00:
379 keys |= keys >> 4;
380 break;
381 }
382 return (0xC0 | (gb->memory.io[REG_JOYP] | 0xF)) ^ (keys & 0xF);
383}
384
385uint8_t GBIORead(struct GB* gb, unsigned address) {
386 switch (address) {
387 case REG_JOYP:
388 return _readKeys(gb);
389 case REG_SB:
390 case REG_SC:
391 // TODO
392 break;
393 case REG_IE:
394 return gb->memory.ie;
395 case REG_WAVE_0:
396 case REG_WAVE_1:
397 case REG_WAVE_2:
398 case REG_WAVE_3:
399 case REG_WAVE_4:
400 case REG_WAVE_5:
401 case REG_WAVE_6:
402 case REG_WAVE_7:
403 case REG_WAVE_8:
404 case REG_WAVE_9:
405 case REG_WAVE_A:
406 case REG_WAVE_B:
407 case REG_WAVE_C:
408 case REG_WAVE_D:
409 case REG_WAVE_E:
410 case REG_WAVE_F:
411 if (gb->audio.playingCh3) {
412 if (gb->audio.ch3.readable || gb->audio.style != GB_AUDIO_DMG) {
413 return gb->audio.ch3.wavedata8[gb->audio.ch3.window >> 1];
414 } else {
415 return 0xFF;
416 }
417 } else {
418 return gb->audio.ch3.wavedata8[address - REG_WAVE_0];
419 }
420 break;
421 case REG_IF:
422 case REG_NR10:
423 case REG_NR11:
424 case REG_NR12:
425 case REG_NR14:
426 case REG_NR21:
427 case REG_NR22:
428 case REG_NR24:
429 case REG_NR30:
430 case REG_NR32:
431 case REG_NR34:
432 case REG_NR41:
433 case REG_NR42:
434 case REG_NR43:
435 case REG_NR44:
436 case REG_NR50:
437 case REG_NR51:
438 case REG_NR52:
439 case REG_DIV:
440 case REG_TIMA:
441 case REG_TMA:
442 case REG_TAC:
443 case REG_STAT:
444 case REG_LCDC:
445 case REG_SCY:
446 case REG_SCX:
447 case REG_LY:
448 case REG_LYC:
449 case REG_BGP:
450 case REG_OBP0:
451 case REG_OBP1:
452 case REG_WY:
453 case REG_WX:
454 // Handled transparently by the registers
455 break;
456 default:
457 if (gb->model >= GB_MODEL_CGB) {
458 switch (address) {
459 case REG_KEY1:
460 case REG_VBK:
461 case REG_HDMA1:
462 case REG_HDMA2:
463 case REG_HDMA3:
464 case REG_HDMA4:
465 case REG_HDMA5:
466 case REG_BCPD:
467 case REG_OCPD:
468 case REG_SVBK:
469 // Handled transparently by the registers
470 goto success;
471 default:
472 break;
473 }
474 }
475 mLOG(GB_IO, STUB, "Reading from unknown register FF%02X", address);
476 return 0xFF;
477 }
478 success:
479 return gb->memory.io[address] | _registerMask[address];
480}