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