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