src/gb/mbc.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 "mbc.h"
7
8#include "gb/gb.h"
9#include "gb/memory.h"
10#include "util/vfs.h"
11
12mLOG_DEFINE_CATEGORY(GB_MBC, "GB MBC");
13
14static void _GBMBCNone(struct GB* gb, uint16_t address, uint8_t value) {
15 UNUSED(gb);
16 UNUSED(address);
17 UNUSED(value);
18
19 mLOG(GB_MBC, GAME_ERROR, "Wrote to invalid MBC");
20}
21
22static void _GBMBC1(struct GB*, uint16_t address, uint8_t value);
23static void _GBMBC2(struct GB*, uint16_t address, uint8_t value);
24static void _GBMBC3(struct GB*, uint16_t address, uint8_t value);
25static void _GBMBC5(struct GB*, uint16_t address, uint8_t value);
26static void _GBMBC6(struct GB*, uint16_t address, uint8_t value);
27static void _GBMBC7(struct GB*, uint16_t address, uint8_t value);
28static void _GBHuC3(struct GB*, uint16_t address, uint8_t value);
29
30void GBMBCSwitchBank(struct GBMemory* memory, int bank) {
31 size_t bankStart = bank * GB_SIZE_CART_BANK0;
32 if (bankStart + GB_SIZE_CART_BANK0 > memory->romSize) {
33 mLOG(GB_MBC, GAME_ERROR, "Attempting to switch to an invalid ROM bank: %0X", bank);
34 bankStart &= (memory->romSize - 1);
35 bank = bankStart / GB_SIZE_CART_BANK0;
36 }
37 memory->romBank = &memory->rom[bankStart];
38 memory->currentBank = bank;
39}
40
41void GBMBCSwitchSramBank(struct GB* gb, int bank) {
42 size_t bankStart = bank * GB_SIZE_EXTERNAL_RAM;
43 GBResizeSram(gb, (bank + 1) * GB_SIZE_EXTERNAL_RAM);
44 gb->memory.sramBank = &gb->memory.sram[bankStart];
45 gb->memory.sramCurrentBank = bank;
46}
47
48void GBMBCInit(struct GB* gb) {
49 const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
50 switch (cart->ramSize) {
51 case 0:
52 gb->sramSize = 0;
53 break;
54 case 1:
55 gb->sramSize = 0x800;
56 break;
57 default:
58 case 2:
59 gb->sramSize = 0x2000;
60 break;
61 case 3:
62 gb->sramSize = 0x8000;
63 break;
64 }
65
66 if (gb->memory.mbcType == GB_MBC_AUTODETECT) {
67 const struct GBCartridge* cart = (const struct GBCartridge*) &gb->memory.rom[0x100];
68 switch (cart->type) {
69 case 0:
70 case 8:
71 case 9:
72 gb->memory.mbcType = GB_MBC_NONE;
73 break;
74 case 1:
75 case 2:
76 case 3:
77 gb->memory.mbcType = GB_MBC1;
78 break;
79 case 5:
80 case 6:
81 gb->memory.mbcType = GB_MBC2;
82 break;
83 case 0x0F:
84 case 0x10:
85 gb->memory.mbcType = GB_MBC3_RTC;
86 break;
87 case 0x11:
88 case 0x12:
89 case 0x13:
90 gb->memory.mbcType = GB_MBC3;
91 break;
92 default:
93 mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
94 // Fall through
95 case 0x19:
96 case 0x1A:
97 case 0x1B:
98 gb->memory.mbcType = GB_MBC5;
99 break;
100 case 0x1C:
101 case 0x1D:
102 case 0x1E:
103 gb->memory.mbcType = GB_MBC5_RUMBLE;
104 break;
105 case 0x20:
106 gb->memory.mbcType = GB_MBC6;
107 break;
108 case 0x22:
109 gb->memory.mbcType = GB_MBC7;
110 break;
111 case 0xFE:
112 gb->memory.mbcType = GB_HuC3;
113 break;
114 }
115 }
116 switch (gb->memory.mbcType) {
117 case GB_MBC_NONE:
118 gb->memory.mbc = _GBMBCNone;
119 break;
120 case GB_MBC1:
121 gb->memory.mbc = _GBMBC1;
122 break;
123 case GB_MBC2:
124 gb->memory.mbc = _GBMBC2;
125 gb->sramSize = 0x200;
126 break;
127 case GB_MBC3:
128 gb->memory.mbc = _GBMBC3;
129 break;
130 default:
131 mLOG(GB_MBC, WARN, "Unknown MBC type: %02X", cart->type);
132 // Fall through
133 case GB_MBC5:
134 gb->memory.mbc = _GBMBC5;
135 break;
136 case GB_MBC6:
137 mLOG(GB_MBC, WARN, "unimplemented MBC: MBC6");
138 gb->memory.mbc = _GBMBC6;
139 break;
140 case GB_MBC7:
141 gb->memory.mbc = _GBMBC7;
142 break;
143 case GB_MMM01:
144 mLOG(GB_MBC, WARN, "unimplemented MBC: MMM01");
145 gb->memory.mbc = _GBMBC1;
146 break;
147 case GB_HuC1:
148 mLOG(GB_MBC, WARN, "unimplemented MBC: HuC-1");
149 gb->memory.mbc = _GBMBC1;
150 break;
151 case GB_HuC3:
152 gb->memory.mbc = _GBHuC3;
153 break;
154 case GB_MBC3_RTC:
155 memset(gb->memory.rtcRegs, 0, sizeof(gb->memory.rtcRegs));
156 gb->memory.mbc = _GBMBC3;
157 break;
158 case GB_MBC5_RUMBLE:
159 gb->memory.mbc = _GBMBC5;
160 break;
161 }
162
163 GBResizeSram(gb, gb->sramSize);
164
165 if (gb->memory.mbcType == GB_MBC3_RTC) {
166 GBMBCRTCRead(gb);
167 }
168}
169
170static void _latchRtc(struct mRTCSource* rtc, uint8_t* rtcRegs, time_t* rtcLastLatch) {
171 time_t t;
172 if (rtc) {
173 if (rtc->sample) {
174 rtc->sample(rtc);
175 }
176 t = rtc->unixTime(rtc);
177 } else {
178 t = time(0);
179 }
180 time_t currentLatch = t;
181 t -= *rtcLastLatch;
182 *rtcLastLatch = currentLatch;
183
184 int64_t diff;
185 diff = rtcRegs[0] + t % 60;
186 if (diff < 0) {
187 diff += 60;
188 t -= 60;
189 }
190 rtcRegs[0] = diff % 60;
191 t /= 60;
192 t += diff / 60;
193
194 diff = rtcRegs[1] + t % 60;
195 if (diff < 0) {
196 diff += 60;
197 t -= 60;
198 }
199 rtcRegs[1] = diff % 60;
200 t /= 60;
201 t += diff / 60;
202
203 diff = rtcRegs[2] + t % 24;
204 if (diff < 0) {
205 diff += 24;
206 t -= 24;
207 }
208 rtcRegs[2] = diff % 24;
209 t /= 24;
210 t += diff / 24;
211
212 diff = rtcRegs[3] + ((rtcRegs[4] & 1) << 8) + (t & 0x1FF);
213 rtcRegs[3] = diff;
214 rtcRegs[4] &= 0xFE;
215 rtcRegs[4] |= (diff >> 8) & 1;
216 if (diff & 0x200) {
217 rtcRegs[4] |= 0x80;
218 }
219}
220
221void _GBMBC1(struct GB* gb, uint16_t address, uint8_t value) {
222 struct GBMemory* memory = &gb->memory;
223 int bank = value & 0x1F;
224 switch (address >> 13) {
225 case 0x0:
226 switch (value) {
227 case 0:
228 memory->sramAccess = false;
229 break;
230 case 0xA:
231 memory->sramAccess = true;
232 GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
233 break;
234 default:
235 // TODO
236 mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
237 break;
238 }
239 break;
240 case 0x1:
241 if (!bank) {
242 ++bank;
243 }
244 GBMBCSwitchBank(memory, bank | (memory->currentBank & 0x60));
245 break;
246 case 0x2:
247 bank &= 3;
248 if (!memory->mbcState.mbc1.mode) {
249 GBMBCSwitchBank(memory, (bank << 5) | (memory->currentBank & 0x1F));
250 } else {
251 GBMBCSwitchSramBank(gb, bank);
252 }
253 break;
254 case 0x3:
255 memory->mbcState.mbc1.mode = value & 1;
256 if (memory->mbcState.mbc1.mode) {
257 GBMBCSwitchBank(memory, memory->currentBank & 0x1F);
258 } else {
259 GBMBCSwitchSramBank(gb, 0);
260 }
261 break;
262 default:
263 // TODO
264 mLOG(GB_MBC, STUB, "MBC1 unknown address: %04X:%02X", address, value);
265 break;
266 }
267}
268
269void _GBMBC2(struct GB* gb, uint16_t address, uint8_t value) {
270 struct GBMemory* memory = &gb->memory;
271 int bank = value & 0xF;
272 switch (address >> 13) {
273 case 0x0:
274 switch (value) {
275 case 0:
276 memory->sramAccess = false;
277 break;
278 case 0xA:
279 memory->sramAccess = true;
280 GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
281 break;
282 default:
283 // TODO
284 mLOG(GB_MBC, STUB, "MBC1 unknown value %02X", value);
285 break;
286 }
287 break;
288 case 0x1:
289 if (!bank) {
290 ++bank;
291 }
292 GBMBCSwitchBank(memory, bank);
293 break;
294 default:
295 // TODO
296 mLOG(GB_MBC, STUB, "MBC2 unknown address: %04X:%02X", address, value);
297 break;
298 }}
299
300void _GBMBC3(struct GB* gb, uint16_t address, uint8_t value) {
301 struct GBMemory* memory = &gb->memory;
302 int bank = value & 0x7F;
303 switch (address >> 13) {
304 case 0x0:
305 switch (value) {
306 case 0:
307 memory->sramAccess = false;
308 break;
309 case 0xA:
310 memory->sramAccess = true;
311 GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
312 break;
313 default:
314 // TODO
315 mLOG(GB_MBC, STUB, "MBC3 unknown value %02X", value);
316 break;
317 }
318 break;
319 case 0x1:
320 if (!bank) {
321 ++bank;
322 }
323 GBMBCSwitchBank(memory, bank);
324 break;
325 case 0x2:
326 if (value < 4) {
327 GBMBCSwitchSramBank(gb, value);
328 memory->rtcAccess = false;
329 } else if (value >= 8 && value <= 0xC) {
330 memory->activeRtcReg = value - 8;
331 memory->rtcAccess = true;
332 }
333 break;
334 case 0x3:
335 if (memory->rtcLatched && value == 0) {
336 memory->rtcLatched = false;
337 } else if (!memory->rtcLatched && value == 1) {
338 _latchRtc(gb->memory.rtc, gb->memory.rtcRegs, &gb->memory.rtcLastLatch);
339 memory->rtcLatched = true;
340 }
341 break;
342 }
343}
344
345void _GBMBC5(struct GB* gb, uint16_t address, uint8_t value) {
346 struct GBMemory* memory = &gb->memory;
347 int bank;
348 switch (address >> 12) {
349 case 0x0:
350 case 0x1:
351 switch (value) {
352 case 0:
353 memory->sramAccess = false;
354 break;
355 case 0xA:
356 memory->sramAccess = true;
357 GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
358 break;
359 default:
360 // TODO
361 mLOG(GB_MBC, STUB, "MBC5 unknown value %02X", value);
362 break;
363 }
364 break;
365 case 0x2:
366 bank = (memory->currentBank & 0x100) | value;
367 GBMBCSwitchBank(memory, bank);
368 break;
369 case 0x3:
370 bank = (memory->currentBank & 0xFF) | ((value & 1) << 8);
371 GBMBCSwitchBank(memory, bank);
372 break;
373 case 0x4:
374 case 0x5:
375 if (memory->mbcType == GB_MBC5_RUMBLE && memory->rumble) {
376 memory->rumble->setRumble(memory->rumble, (value >> 3) & 1);
377 value &= ~8;
378 }
379 GBMBCSwitchSramBank(gb, value & 0xF);
380 break;
381 default:
382 // TODO
383 mLOG(GB_MBC, STUB, "MBC5 unknown address: %04X:%02X", address, value);
384 break;
385 }
386}
387
388void _GBMBC6(struct GB* gb, uint16_t address, uint8_t value) {
389 // TODO
390 mLOG(GB_MBC, STUB, "MBC6 unimplemented");
391 UNUSED(gb);
392 UNUSED(address);
393 UNUSED(value);
394}
395
396void _GBMBC7(struct GB* gb, uint16_t address, uint8_t value) {
397 struct GBMemory* memory = &gb->memory;
398 int bank = value & 0x7F;
399 switch (address >> 13) {
400 case 0x1:
401 GBMBCSwitchBank(memory, bank);
402 break;
403 case 0x2:
404 if (value < 0x10) {
405 GBMBCSwitchSramBank(gb, value);
406 }
407 break;
408 default:
409 // TODO
410 mLOG(GB_MBC, STUB, "MBC7 unknown address: %04X:%02X", address, value);
411 break;
412 }
413}
414
415uint8_t GBMBC7Read(struct GBMemory* memory, uint16_t address) {
416 struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
417 switch (address & 0xF0) {
418 case 0x00:
419 case 0x10:
420 case 0x60:
421 case 0x70:
422 return 0;
423 case 0x20:
424 if (memory->rotation && memory->rotation->readTiltX) {
425 int32_t x = -memory->rotation->readTiltX(memory->rotation);
426 x >>= 21;
427 x += 2047;
428 return x;
429 }
430 return 0xFF;
431 case 0x30:
432 if (memory->rotation && memory->rotation->readTiltX) {
433 int32_t x = -memory->rotation->readTiltX(memory->rotation);
434 x >>= 21;
435 x += 2047;
436 return x >> 8;
437 }
438 return 7;
439 case 0x40:
440 if (memory->rotation && memory->rotation->readTiltY) {
441 int32_t y = -memory->rotation->readTiltY(memory->rotation);
442 y >>= 21;
443 y += 2047;
444 return y;
445 }
446 return 0xFF;
447 case 0x50:
448 if (memory->rotation && memory->rotation->readTiltY) {
449 int32_t y = -memory->rotation->readTiltY(memory->rotation);
450 y >>= 21;
451 y += 2047;
452 return y >> 8;
453 }
454 return 7;
455 case 0x80:
456 return (mbc7->sr >> 16) & 1;
457 default:
458 return 0xFF;
459 }
460}
461
462void GBMBC7Write(struct GBMemory* memory, uint16_t address, uint8_t value) {
463 if ((address & 0xF0) != 0x80) {
464 return;
465 }
466 struct GBMBC7State* mbc7 = &memory->mbcState.mbc7;
467 GBMBC7Field old = memory->mbcState.mbc7.field;
468 mbc7->field = GBMBC7FieldClearIO(value);
469 if (!GBMBC7FieldIsCS(old) && GBMBC7FieldIsCS(value)) {
470 if (mbc7->state == GBMBC7_STATE_WRITE) {
471 if (mbc7->writable) {
472 memory->sramBank[mbc7->address * 2] = mbc7->sr >> 8;
473 memory->sramBank[mbc7->address * 2 + 1] = mbc7->sr;
474 }
475 mbc7->sr = 0x1FFFF;
476 mbc7->state = GBMBC7_STATE_NULL;
477 } else {
478 mbc7->state = GBMBC7_STATE_IDLE;
479 }
480 }
481 if (!GBMBC7FieldIsSK(old) && GBMBC7FieldIsSK(value)) {
482 if (mbc7->state > GBMBC7_STATE_IDLE && mbc7->state != GBMBC7_STATE_READ) {
483 mbc7->sr <<= 1;
484 mbc7->sr |= GBMBC7FieldGetIO(value);
485 ++mbc7->srBits;
486 }
487 switch (mbc7->state) {
488 case GBMBC7_STATE_IDLE:
489 if (GBMBC7FieldIsIO(value)) {
490 mbc7->state = GBMBC7_STATE_READ_COMMAND;
491 mbc7->srBits = 0;
492 mbc7->sr = 0;
493 }
494 break;
495 case GBMBC7_STATE_READ_COMMAND:
496 if (mbc7->srBits == 2) {
497 mbc7->state = GBMBC7_STATE_READ_ADDRESS;
498 mbc7->srBits = 0;
499 mbc7->command = mbc7->sr;
500 }
501 break;
502 case GBMBC7_STATE_READ_ADDRESS:
503 if (mbc7->srBits == 8) {
504 mbc7->state = GBMBC7_STATE_COMMAND_0 + mbc7->command;
505 mbc7->srBits = 0;
506 mbc7->address = mbc7->sr;
507 if (mbc7->state == GBMBC7_STATE_COMMAND_0) {
508 switch (mbc7->address >> 6) {
509 case 0:
510 mbc7->writable = false;
511 mbc7->state = GBMBC7_STATE_NULL;
512 break;
513 case 3:
514 mbc7->writable = true;
515 mbc7->state = GBMBC7_STATE_NULL;
516 break;
517 }
518 }
519 }
520 break;
521 case GBMBC7_STATE_COMMAND_0:
522 if (mbc7->srBits == 16) {
523 switch (mbc7->address >> 6) {
524 case 0:
525 mbc7->writable = false;
526 mbc7->state = GBMBC7_STATE_NULL;
527 break;
528 case 1:
529 mbc7->state = GBMBC7_STATE_WRITE;
530 if (mbc7->writable) {
531 int i;
532 for (i = 0; i < 256; ++i) {
533 memory->sramBank[i * 2] = mbc7->sr >> 8;
534 memory->sramBank[i * 2 + 1] = mbc7->sr;
535 }
536 }
537 break;
538 case 2:
539 mbc7->state = GBMBC7_STATE_WRITE;
540 if (mbc7->writable) {
541 int i;
542 for (i = 0; i < 256; ++i) {
543 memory->sramBank[i * 2] = 0xFF;
544 memory->sramBank[i * 2 + 1] = 0xFF;
545 }
546 }
547 break;
548 case 3:
549 mbc7->writable = true;
550 mbc7->state = GBMBC7_STATE_NULL;
551 break;
552 }
553 }
554 break;
555 case GBMBC7_STATE_COMMAND_SR_WRITE:
556 if (mbc7->srBits == 16) {
557 mbc7->srBits = 0;
558 mbc7->state = GBMBC7_STATE_WRITE;
559 }
560 break;
561 case GBMBC7_STATE_COMMAND_SR_READ:
562 if (mbc7->srBits == 1) {
563 mbc7->sr = memory->sramBank[mbc7->address * 2] << 8;
564 mbc7->sr |= memory->sramBank[mbc7->address * 2 + 1];
565 mbc7->srBits = 0;
566 mbc7->state = GBMBC7_STATE_READ;
567 }
568 break;
569 case GBMBC7_STATE_COMMAND_SR_FILL:
570 if (mbc7->srBits == 16) {
571 mbc7->sr = 0xFFFF;
572 mbc7->srBits = 0;
573 mbc7->state = GBMBC7_STATE_WRITE;
574 }
575 break;
576 default:
577 break;
578 }
579 } else if (GBMBC7FieldIsSK(old) && !GBMBC7FieldIsSK(value)) {
580 if (mbc7->state == GBMBC7_STATE_READ) {
581 mbc7->sr <<= 1;
582 ++mbc7->srBits;
583 if (mbc7->srBits == 16) {
584 mbc7->srBits = 0;
585 mbc7->state = GBMBC7_STATE_NULL;
586 }
587 }
588 }
589}
590
591void _GBHuC3(struct GB* gb, uint16_t address, uint8_t value) {
592 struct GBMemory* memory = &gb->memory;
593 int bank = value & 0x3F;
594 if (address & 0x1FFF) {
595 mLOG(GB_MBC, STUB, "HuC-3 unknown value %04X:%02X", address, value);
596 }
597
598 switch (address >> 13) {
599 case 0x0:
600 switch (value) {
601 case 0xA:
602 memory->sramAccess = true;
603 GBMBCSwitchSramBank(gb, memory->sramCurrentBank);
604 break;
605 default:
606 memory->sramAccess = false;
607 break;
608 }
609 break;
610 case 0x1:
611 GBMBCSwitchBank(memory, bank);
612 break;
613 case 0x2:
614 GBMBCSwitchSramBank(gb, bank);
615 break;
616 default:
617 // TODO
618 mLOG(GB_MBC, STUB, "HuC-3 unknown address: %04X:%02X", address, value);
619 break;
620 }
621}
622
623void GBMBCRTCRead(struct GB* gb) {
624 struct GBMBCRTCSaveBuffer rtcBuffer;
625 struct VFile* vf = gb->sramVf;
626 ssize_t end = vf->seek(vf, -sizeof(rtcBuffer), SEEK_END);
627 switch (end & 0x1FFF) {
628 case 0:
629 break;
630 case 0x1FFC:
631 vf->seek(vf, -sizeof(rtcBuffer) - 4, SEEK_END);
632 break;
633 default:
634 return;
635 }
636 vf->read(vf, &rtcBuffer, sizeof(rtcBuffer));
637
638 LOAD_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
639 LOAD_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
640 LOAD_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
641 LOAD_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
642 LOAD_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
643 LOAD_64LE(gb->memory.rtcLastLatch, 0, &rtcBuffer.unixTime);
644}
645
646void GBMBCRTCWrite(struct GB* gb) {
647 uint8_t rtcRegs[5];
648 memcpy(rtcRegs, gb->memory.rtcRegs, sizeof(rtcRegs));
649 time_t rtcLastLatch = gb->memory.rtcLastLatch;
650 _latchRtc(gb->memory.rtc, rtcRegs, &rtcLastLatch);
651
652 struct GBMBCRTCSaveBuffer rtcBuffer;
653 STORE_32LE(rtcRegs[0], 0, &rtcBuffer.sec);
654 STORE_32LE(rtcRegs[1], 0, &rtcBuffer.min);
655 STORE_32LE(rtcRegs[2], 0, &rtcBuffer.hour);
656 STORE_32LE(rtcRegs[3], 0, &rtcBuffer.days);
657 STORE_32LE(rtcRegs[4], 0, &rtcBuffer.daysHi);
658 STORE_32LE(gb->memory.rtcRegs[0], 0, &rtcBuffer.latchedSec);
659 STORE_32LE(gb->memory.rtcRegs[1], 0, &rtcBuffer.latchedMin);
660 STORE_32LE(gb->memory.rtcRegs[2], 0, &rtcBuffer.latchedHour);
661 STORE_32LE(gb->memory.rtcRegs[3], 0, &rtcBuffer.latchedDays);
662 STORE_32LE(gb->memory.rtcRegs[4], 0, &rtcBuffer.latchedDaysHi);
663 STORE_64LE(rtcLastLatch, 0, &rtcBuffer.unixTime);
664
665 struct VFile* vf = gb->sramVf;
666 vf->seek(vf, gb->sramSize, SEEK_SET);
667 vf->write(vf, &rtcBuffer, sizeof(rtcBuffer));
668}