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