view src/gb/gbMemory.cpp @ 92:1ff2c546f5ad

added tick(), which allows one to step through each opcode of gameboy
author Robert McIntyre <rlm@mit.edu>
date Sun, 11 Mar 2012 19:07:31 -0500
parents f9f4f1b99eed
children
line wrap: on
line source
1 #include "gbGlobals.h"
2 #include "gbMemory.h"
3 #include "../common/System.h"
4 #include "../common/movie.h"
6 mapperMBC1 gbDataMBC1 = {
7 0, // RAM enable
8 1, // ROM bank
9 0, // RAM bank
10 0, // memory model
11 0, // ROM high address
12 0 // RAM address
13 };
15 // MBC1 ROM write registers
16 void mapperMBC1ROM(u16 address, u8 value)
17 {
18 int tmpAddress = 0;
20 switch (address & 0x6000)
21 {
22 case 0x0000: // RAM enable register
23 gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
24 break;
25 case 0x2000: // ROM bank select
26 // value = value & 0x1f;
27 if (value == 0)
28 value = 1;
29 if (value == gbDataMBC1.mapperROMBank)
30 break;
32 tmpAddress = value << 14;
34 // check current model
35 if (gbDataMBC1.mapperMemoryModel == 0)
36 {
37 // model is 16/8, so we have a high address in use
38 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
39 }
41 tmpAddress &= gbRomSizeMask;
42 gbDataMBC1.mapperROMBank = value;
43 gbMemoryMap[0x04] = &gbRom[tmpAddress];
44 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
45 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
46 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
47 break;
48 case 0x4000: // RAM bank select
49 if (gbDataMBC1.mapperMemoryModel == 1)
50 {
51 // 4/32 model, RAM bank switching provided
52 value = value & 0x03;
53 if (value == gbDataMBC1.mapperRAMBank)
54 break;
55 tmpAddress = value << 13;
56 tmpAddress &= gbRamSizeMask;
57 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
58 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
59 gbDataMBC1.mapperRAMBank = value;
60 gbDataMBC1.mapperRAMAddress = tmpAddress;
61 }
62 else
63 {
64 // 16/8, set the high address
65 gbDataMBC1.mapperROMHighAddress = value & 0x03;
66 tmpAddress = gbDataMBC1.mapperROMBank << 14;
67 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
68 tmpAddress &= gbRomSizeMask;
69 gbMemoryMap[0x04] = &gbRom[tmpAddress];
70 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
71 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
72 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
73 }
74 break;
75 case 0x6000: // memory model select
76 gbDataMBC1.mapperMemoryModel = value & 1;
77 break;
78 }
79 }
81 // MBC1 RAM write
82 void mapperMBC1RAM(u16 address, u8 value)
83 {
84 if (gbDataMBC1.mapperRAMEnable)
85 {
86 if (gbRamSize)
87 {
88 gbWriteMemoryQuick(address, value);
89 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
90 }
91 }
92 }
94 void memoryUpdateMapMBC1()
95 {
96 int tmpAddress = gbDataMBC1.mapperROMBank << 14;
98 // check current model
99 if (gbDataMBC1.mapperMemoryModel == 1)
100 {
101 // model is 16/8, so we have a high address in use
102 tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
103 }
105 tmpAddress &= gbRomSizeMask;
106 gbMemoryMap[0x04] = &gbRom[tmpAddress];
107 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
108 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
109 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
111 if (gbRamSize)
112 {
113 gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
114 gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
115 }
116 }
118 mapperMBC2 gbDataMBC2 = {
119 0, // RAM enable
120 1 // ROM bank
121 };
123 // MBC2 ROM write registers
124 void mapperMBC2ROM(u16 address, u8 value)
125 {
126 switch (address & 0x6000)
127 {
128 case 0x0000: // RAM enable
129 if (!(address & 0x0100))
130 {
131 gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a;
132 }
133 break;
134 case 0x2000: // ROM bank select
135 if (address & 0x0100)
136 {
137 value &= 0x0f;
139 if (value == 0)
140 value = 1;
141 if (gbDataMBC2.mapperROMBank != value)
142 {
143 gbDataMBC2.mapperROMBank = value;
145 int tmpAddress = value << 14;
147 tmpAddress &= gbRomSizeMask;
149 gbMemoryMap[0x04] = &gbRom[tmpAddress];
150 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
151 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
152 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
153 }
154 }
155 break;
156 }
157 }
159 // MBC2 RAM write
160 void mapperMBC2RAM(u16 address, u8 value)
161 {
162 if (gbDataMBC2.mapperRAMEnable)
163 {
164 if (gbRamSize && address < 0xa200)
165 {
166 gbWriteMemoryQuick(address, value);
167 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
168 }
169 }
170 }
172 void memoryUpdateMapMBC2()
173 {
174 int tmpAddress = gbDataMBC2.mapperROMBank << 14;
176 tmpAddress &= gbRomSizeMask;
178 gbMemoryMap[0x04] = &gbRom[tmpAddress];
179 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
180 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
181 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
182 }
184 mapperMBC3 gbDataMBC3 = {
185 0, // RAM enable
186 1, // ROM bank
187 0, // RAM bank
188 0, // RAM address
189 0, // timer clock latch
190 0, // timer clock register
191 0, // timer seconds
192 0, // timer minutes
193 0, // timer hours
194 0, // timer days
195 0, // timer control
196 0, // timer latched seconds
197 0, // timer latched minutes
198 0, // timer latched hours
199 0, // timer latched days
200 0, // timer latched control
201 (time_t)-1 // last time
202 };
204 void memoryUpdateMBC3Clock()
205 {
206 time_t now;
208 if (VBAMovieActive() || VBAMovieLoading())
209 now = (time_t)(VBAMovieGetId() + VBAMovieGetFrameCounter()/60); /// FIXME: is /60 the right factor?
210 else
211 now = time(NULL);
213 time_t diff = now - gbDataMBC3.mapperLastTime;
214 if (diff > 0)
215 {
216 // update the clock according to the last update time
217 gbDataMBC3.mapperSeconds += (int)(diff % 60);
218 if (gbDataMBC3.mapperSeconds > 59)
219 {
220 gbDataMBC3.mapperSeconds -= 60;
221 gbDataMBC3.mapperMinutes++;
222 }
224 diff /= 60;
226 gbDataMBC3.mapperMinutes += (int)(diff % 60);
227 if (gbDataMBC3.mapperMinutes > 60)
228 {
229 gbDataMBC3.mapperMinutes -= 60;
230 gbDataMBC3.mapperHours++;
231 }
233 diff /= 60;
235 gbDataMBC3.mapperHours += (int)(diff % 24);
236 if (gbDataMBC3.mapperHours > 24)
237 {
238 gbDataMBC3.mapperHours -= 24;
239 gbDataMBC3.mapperDays++;
240 }
241 diff /= 24;
243 gbDataMBC3.mapperDays += (int)diff;
244 if (gbDataMBC3.mapperDays > 255)
245 {
246 if (gbDataMBC3.mapperDays > 511)
247 {
248 gbDataMBC3.mapperDays %= 512;
249 gbDataMBC3.mapperControl |= 0x80;
250 }
251 gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
252 (gbDataMBC3.mapperDays > 255 ? 1 : 0);
253 }
254 }
255 gbDataMBC3.mapperLastTime = now;
256 }
258 // MBC3 ROM write registers
259 void mapperMBC3ROM(u16 address, u8 value)
260 {
261 int tmpAddress = 0;
263 switch (address & 0x6000)
264 {
265 case 0x0000: // RAM enable register
266 gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
267 break;
268 case 0x2000: // ROM bank select
269 value = value & 0x7f;
270 if (value == 0)
271 value = 1;
272 if (value == gbDataMBC3.mapperROMBank)
273 break;
275 tmpAddress = value << 14;
277 tmpAddress &= gbRomSizeMask;
278 gbDataMBC3.mapperROMBank = value;
279 gbMemoryMap[0x04] = &gbRom[tmpAddress];
280 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
281 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
282 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
284 break;
285 case 0x4000: // RAM bank select
286 if (value < 8)
287 {
288 if (value == gbDataMBC3.mapperRAMBank)
289 break;
290 tmpAddress = value << 13;
291 tmpAddress &= gbRamSizeMask;
292 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
293 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
294 gbDataMBC3.mapperRAMBank = value;
295 gbDataMBC3.mapperRAMAddress = tmpAddress;
296 }
297 else
298 {
299 if (gbDataMBC3.mapperRAMEnable)
300 {
301 gbDataMBC3.mapperRAMBank = -1;
303 gbDataMBC3.mapperClockRegister = value;
304 }
305 }
306 break;
307 case 0x6000: // clock latch
308 if (gbDataMBC3.mapperClockLatch == 0 && value == 1)
309 {
310 memoryUpdateMBC3Clock();
311 gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds;
312 gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes;
313 gbDataMBC3.mapperLHours = gbDataMBC3.mapperHours;
314 gbDataMBC3.mapperLDays = gbDataMBC3.mapperDays;
315 gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl;
316 }
317 if (value == 0x00 || value == 0x01)
318 gbDataMBC3.mapperClockLatch = value;
319 break;
320 }
321 }
323 // MBC3 RAM write
324 void mapperMBC3RAM(u16 address, u8 value)
325 {
326 if (gbDataMBC3.mapperRAMEnable)
327 {
328 if (gbDataMBC3.mapperRAMBank != -1)
329 {
330 if (gbRamSize)
331 {
332 gbWriteMemoryQuick(address, value);
333 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
334 }
335 }
336 else
337 {
338 time_t tmp; //Small kludge to get it working on some 64 bit systems.
339 if (VBAMovieActive() || VBAMovieLoading())
340 gbDataMBC3.mapperLastTime = VBAMovieGetId() + VBAMovieGetFrameCounter()/60;
341 else {
342 time(&tmp);
343 gbDataMBC3.mapperLastTime=(u32)tmp;
344 }
345 systemScreenMessage(ctime(&tmp), 4);
346 gbDataMBC3.mapperLastTime=(u32)tmp;
348 switch (gbDataMBC3.mapperClockRegister)
349 {
350 case 0x08:
351 gbDataMBC3.mapperSeconds = value;
352 break;
353 case 0x09:
354 gbDataMBC3.mapperMinutes = value;
355 break;
356 case 0x0a:
357 gbDataMBC3.mapperHours = value;
358 break;
359 case 0x0b:
360 gbDataMBC3.mapperDays = value;
361 break;
362 case 0x0c:
363 if (gbDataMBC3.mapperControl & 0x80)
364 gbDataMBC3.mapperControl = 0x80 | value;
365 else
366 gbDataMBC3.mapperControl = value;
367 break;
368 }
369 }
370 }
371 }
373 // MBC3 read RAM
374 u8 mapperMBC3ReadRAM(u16 address)
375 {
376 if (gbDataMBC3.mapperRAMEnable)
377 {
378 if (gbDataMBC3.mapperRAMBank != -1)
379 {
380 return gbReadMemoryQuick(address);
381 }
383 switch (gbDataMBC3.mapperClockRegister)
384 {
385 case 0x08:
386 return gbDataMBC3.mapperLSeconds;
387 break;
388 case 0x09:
389 return gbDataMBC3.mapperLMinutes;
390 break;
391 case 0x0a:
392 return gbDataMBC3.mapperLHours;
393 break;
394 case 0x0b:
395 return gbDataMBC3.mapperLDays;
396 break;
397 case 0x0c:
398 return gbDataMBC3.mapperLControl;
399 }
400 }
401 return 0;
402 }
404 void memoryUpdateMapMBC3()
405 {
406 int tmpAddress = gbDataMBC3.mapperROMBank << 14;
408 tmpAddress &= gbRomSizeMask;
410 gbMemoryMap[0x04] = &gbRom[tmpAddress];
411 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
412 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
413 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
415 if (gbDataMBC3.mapperRAMBank >= 0 && gbRamSize)
416 {
417 tmpAddress = gbDataMBC3.mapperRAMBank << 13;
418 tmpAddress &= gbRamSizeMask;
419 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
420 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
421 }
422 }
424 mapperMBC5 gbDataMBC5 = {
425 0, // RAM enable
426 1, // ROM bank
427 0, // RAM bank
428 0, // ROM high address
429 0, // RAM address
430 0 // is rumble cartridge?
431 };
433 // MBC5 ROM write registers
434 void mapperMBC5ROM(u16 address, u8 value)
435 {
436 int tmpAddress = 0;
438 switch (address & 0x6000)
439 {
440 case 0x0000: // RAM enable register
441 gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
442 break;
443 case 0x2000: // ROM bank select
444 if (address < 0x3000)
445 {
446 value = value & 0xff;
447 if (value == gbDataMBC5.mapperROMBank)
448 break;
450 tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ;
452 tmpAddress &= gbRomSizeMask;
453 gbDataMBC5.mapperROMBank = value;
454 gbMemoryMap[0x04] = &gbRom[tmpAddress];
455 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
456 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
457 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
458 }
459 else
460 {
461 value = value & 1;
462 if (value == gbDataMBC5.mapperROMHighAddress)
463 break;
465 tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22);
467 tmpAddress &= gbRomSizeMask;
468 gbDataMBC5.mapperROMHighAddress = value;
469 gbMemoryMap[0x04] = &gbRom[tmpAddress];
470 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
471 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
472 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
473 }
474 break;
475 case 0x4000: // RAM bank select
476 if (gbDataMBC5.isRumbleCartridge)
477 value &= 0x07;
478 else
479 value &= 0x0f;
480 if (value == gbDataMBC5.mapperRAMBank)
481 break;
482 tmpAddress = value << 13;
483 tmpAddress &= gbRamSizeMask;
484 if (gbRamSize)
485 {
486 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
487 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
489 gbDataMBC5.mapperRAMBank = value;
490 gbDataMBC5.mapperRAMAddress = tmpAddress;
491 }
492 break;
493 }
494 }
496 // MBC5 RAM write
497 void mapperMBC5RAM(u16 address, u8 value)
498 {
499 if (gbDataMBC5.mapperRAMEnable)
500 {
501 if (gbRamSize)
502 {
503 gbWriteMemoryQuick(address, value);
504 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
505 }
506 }
507 }
509 void memoryUpdateMapMBC5()
510 {
511 int tmpAddress = (gbDataMBC5.mapperROMBank << 14) |
512 (gbDataMBC5.mapperROMHighAddress << 22) ;
514 tmpAddress &= gbRomSizeMask;
515 gbMemoryMap[0x04] = &gbRom[tmpAddress];
516 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
517 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
518 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
520 if (gbRamSize)
521 {
522 tmpAddress = gbDataMBC5.mapperRAMBank << 13;
523 tmpAddress &= gbRamSizeMask;
524 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
525 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
526 }
527 }
529 mapperMBC7 gbDataMBC7 = {
530 0, // RAM enable
531 1, // ROM bank
532 0, // RAM bank
533 0, // RAM address
534 0, // chip select
535 0, // ??
536 0, // mapper state
537 0, // buffer for receiving serial data
538 0, // idle state
539 0, // count of bits received
540 0, // command received
541 0, // address received
542 0, // write enable
543 0, // value to return on ram
544 };
546 // MBC7 ROM write registers
547 void mapperMBC7ROM(u16 address, u8 value)
548 {
549 int tmpAddress = 0;
551 switch (address & 0x6000)
552 {
553 case 0x0000:
554 break;
555 case 0x2000: // ROM bank select
556 value = value & 0x7f;
557 if (value == 0)
558 value = 1;
560 if (value == gbDataMBC7.mapperROMBank)
561 break;
563 tmpAddress = (value << 14);
565 tmpAddress &= gbRomSizeMask;
566 gbDataMBC7.mapperROMBank = value;
567 gbMemoryMap[0x04] = &gbRom[tmpAddress];
568 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
569 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
570 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
571 break;
572 case 0x4000: // RAM bank select/enable
573 if (value < 8)
574 {
575 tmpAddress = (value&3) << 13;
576 tmpAddress &= gbRamSizeMask;
577 gbMemoryMap[0x0a] = &gbMemory[0xa000];
578 gbMemoryMap[0x0b] = &gbMemory[0xb000];
580 gbDataMBC7.mapperRAMBank = value;
581 gbDataMBC7.mapperRAMAddress = tmpAddress;
582 gbDataMBC7.mapperRAMEnable = 0;
583 }
584 else
585 {
586 gbDataMBC7.mapperRAMEnable = 0;
587 }
588 break;
589 }
590 }
592 // MBC7 read RAM
593 u8 mapperMBC7ReadRAM(u16 address)
594 {
595 switch (address & 0xa0f0)
596 {
597 case 0xa000:
598 case 0xa010:
599 case 0xa060:
600 case 0xa070:
601 return 0;
602 case 0xa020:
603 // sensor X low byte
604 return systemGetSensorX() & 255;
605 case 0xa030:
606 // sensor X high byte
607 return systemGetSensorX() >> 8;
608 case 0xa040:
609 // sensor Y low byte
610 return systemGetSensorY() & 255;
611 case 0xa050:
612 // sensor Y high byte
613 return systemGetSensorY() >> 8;
614 case 0xa080:
615 return gbDataMBC7.value;
616 }
617 return 0xff;
618 }
620 // MBC7 RAM write
621 void mapperMBC7RAM(u16 address, u8 value)
622 {
623 if (address == 0xa080)
624 {
625 // special processing needed
626 int oldCs = gbDataMBC7.cs, oldSk = gbDataMBC7.sk;
628 gbDataMBC7.cs = value>>7;
629 gbDataMBC7.sk = (value>>6)&1;
631 if (!oldCs && gbDataMBC7.cs)
632 {
633 if (gbDataMBC7.state == 5)
634 {
635 if (gbDataMBC7.writeEnable)
636 {
637 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2, gbDataMBC7.buffer>>8);
638 gbWriteMemoryQuick(0xa000+gbDataMBC7.address*2+1, gbDataMBC7.buffer&0xff);
639 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
640 }
641 gbDataMBC7.state = 0;
642 gbDataMBC7.value = 1;
643 }
644 else
645 {
646 gbDataMBC7.idle = true;
647 gbDataMBC7.state = 0;
648 }
649 }
651 if (!oldSk && gbDataMBC7.sk)
652 {
653 if (gbDataMBC7.idle)
654 {
655 if (value & 0x02)
656 {
657 gbDataMBC7.idle = false;
658 gbDataMBC7.count = 0;
659 gbDataMBC7.state = 1;
660 }
661 }
662 else
663 {
664 switch (gbDataMBC7.state)
665 {
666 case 1:
667 // receiving command
668 gbDataMBC7.buffer <<= 1;
669 gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0;
670 gbDataMBC7.count++;
671 if (gbDataMBC7.count == 2)
672 {
673 // finished receiving command
674 gbDataMBC7.state = 2;
675 gbDataMBC7.count = 0;
676 gbDataMBC7.code = gbDataMBC7.buffer & 3;
677 }
678 break;
679 case 2:
680 // receive address
681 gbDataMBC7.buffer <<= 1;
682 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
683 gbDataMBC7.count++;
684 if (gbDataMBC7.count == 8)
685 {
686 // finish receiving
687 gbDataMBC7.state = 3;
688 gbDataMBC7.count = 0;
689 gbDataMBC7.address = gbDataMBC7.buffer&0xff;
690 if (gbDataMBC7.code == 0)
691 {
692 if ((gbDataMBC7.address>>6) == 0)
693 {
694 gbDataMBC7.writeEnable = 0;
695 gbDataMBC7.state = 0;
696 }
697 else if ((gbDataMBC7.address>>6) == 3)
698 {
699 gbDataMBC7.writeEnable = 1;
700 gbDataMBC7.state = 0;
701 }
702 }
703 }
704 break;
705 case 3:
706 gbDataMBC7.buffer <<= 1;
707 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;
708 gbDataMBC7.count++;
710 switch (gbDataMBC7.code)
711 {
712 case 0:
713 if (gbDataMBC7.count == 16)
714 {
715 if ((gbDataMBC7.address>>6) == 0)
716 {
717 gbDataMBC7.writeEnable = 0;
718 gbDataMBC7.state = 0;
719 }
720 else if ((gbDataMBC7.address>>6) == 1)
721 {
722 if (gbDataMBC7.writeEnable)
723 {
724 for (int i = 0; i < 256; i++)
725 {
726 gbWriteMemoryQuick(0xa000+i*2, gbDataMBC7.buffer >> 8);
727 gbWriteMemoryQuick(0xa000+i*2+1, gbDataMBC7.buffer & 0xff);
728 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
729 }
730 }
731 gbDataMBC7.state = 5;
732 }
733 else if ((gbDataMBC7.address>>6) == 2)
734 {
735 if (gbDataMBC7.writeEnable)
736 {
737 for (int i = 0; i < 256; i++)
738 WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff);
739 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
740 }
741 gbDataMBC7.state = 5;
742 }
743 else if ((gbDataMBC7.address>>6) == 3)
744 {
745 gbDataMBC7.writeEnable = 1;
746 gbDataMBC7.state = 0;
747 }
748 gbDataMBC7.count = 0;
749 }
750 break;
751 case 1:
752 if (gbDataMBC7.count == 16)
753 {
754 gbDataMBC7.count = 0;
755 gbDataMBC7.state = 5;
756 gbDataMBC7.value = 0;
757 }
758 break;
759 case 2:
760 if (gbDataMBC7.count == 1)
761 {
762 gbDataMBC7.state = 4;
763 gbDataMBC7.count = 0;
764 gbDataMBC7.buffer = (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2)<<8)|
765 (gbReadMemoryQuick(0xa000+gbDataMBC7.address*2+1));
766 }
767 break;
768 case 3:
769 if (gbDataMBC7.count == 16)
770 {
771 gbDataMBC7.count = 0;
772 gbDataMBC7.state = 5;
773 gbDataMBC7.value = 0;
774 gbDataMBC7.buffer = 0xffff;
775 }
776 break;
777 }
778 break;
779 }
780 }
781 }
783 if (oldSk && !gbDataMBC7.sk)
784 {
785 if (gbDataMBC7.state == 4)
786 {
787 gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000) ? 1 : 0;
788 gbDataMBC7.buffer <<= 1;
789 gbDataMBC7.count++;
790 if (gbDataMBC7.count == 16)
791 {
792 gbDataMBC7.count = 0;
793 gbDataMBC7.state = 0;
794 }
795 }
796 }
797 }
798 }
800 void memoryUpdateMapMBC7()
801 {
802 int tmpAddress = (gbDataMBC5.mapperROMBank << 14);
804 tmpAddress &= gbRomSizeMask;
805 gbMemoryMap[0x04] = &gbRom[tmpAddress];
806 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
807 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
808 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
809 }
811 mapperHuC1 gbDataHuC1 = {
812 0, // RAM enable
813 1, // ROM bank
814 0, // RAM bank
815 0, // memory model
816 0, // ROM high address
817 0 // RAM address
818 };
820 // HuC1 ROM write registers
821 void mapperHuC1ROM(u16 address, u8 value)
822 {
823 int tmpAddress = 0;
825 switch (address & 0x6000)
826 {
827 case 0x0000: // RAM enable register
828 gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);
829 break;
830 case 0x2000: // ROM bank select
831 value = value & 0x3f;
832 if (value == 0)
833 value = 1;
834 if (value == gbDataHuC1.mapperROMBank)
835 break;
837 tmpAddress = value << 14;
839 tmpAddress &= gbRomSizeMask;
840 gbDataHuC1.mapperROMBank = value;
841 gbMemoryMap[0x04] = &gbRom[tmpAddress];
842 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
843 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
844 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
845 break;
846 case 0x4000: // RAM bank select
847 if (gbDataHuC1.mapperMemoryModel == 1)
848 {
849 // 4/32 model, RAM bank switching provided
850 value = value & 0x03;
851 if (value == gbDataHuC1.mapperRAMBank)
852 break;
853 tmpAddress = value << 13;
854 tmpAddress &= gbRamSizeMask;
855 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
856 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
857 gbDataHuC1.mapperRAMBank = value;
858 gbDataHuC1.mapperRAMAddress = tmpAddress;
859 }
860 else
861 {
862 // 16/8, set the high address
863 gbDataHuC1.mapperROMHighAddress = value & 0x03;
864 tmpAddress = gbDataHuC1.mapperROMBank << 14;
865 tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19;
866 tmpAddress &= gbRomSizeMask;
867 gbMemoryMap[0x04] = &gbRom[tmpAddress];
868 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
869 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
870 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
871 }
872 break;
873 case 0x6000: // memory model select
874 gbDataHuC1.mapperMemoryModel = value & 1;
875 break;
876 }
877 }
879 // HuC1 RAM write
880 void mapperHuC1RAM(u16 address, u8 value)
881 {
882 if (gbDataHuC1.mapperRAMEnable)
883 {
884 if (gbRamSize)
885 {
886 gbWriteMemoryQuick(address, value);
887 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
888 }
889 }
890 }
892 void memoryUpdateMapHuC1()
893 {
894 int tmpAddress = gbDataHuC1.mapperROMBank << 14;
896 tmpAddress &= gbRomSizeMask;
898 gbMemoryMap[0x04] = &gbRom[tmpAddress];
899 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
900 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
901 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
903 if (gbRamSize)
904 {
905 tmpAddress = gbDataHuC1.mapperRAMBank << 13;
906 tmpAddress &= gbRamSizeMask;
907 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
908 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
909 }
910 }
912 mapperHuC3 gbDataHuC3 = {
913 0, // RAM enable
914 1, // ROM bank
915 0, // RAM bank
916 0, // RAM address
917 0, // RAM flag
918 0 // RAM read value
919 };
921 // HuC3 ROM write registers
922 void mapperHuC3ROM(u16 address, u8 value)
923 {
924 int tmpAddress = 0;
926 switch (address & 0x6000)
927 {
928 case 0x0000: // RAM enable register
929 gbDataHuC3.mapperRAMEnable = (value == 0x0a ? 1 : 0);
930 gbDataHuC3.mapperRAMFlag = value;
931 if (gbDataHuC3.mapperRAMFlag != 0x0a)
932 gbDataHuC3.mapperRAMBank = -1;
933 break;
934 case 0x2000: // ROM bank select
935 value = value & 0x7f;
936 if (value == 0)
937 value = 1;
938 if (value == gbDataHuC3.mapperROMBank)
939 break;
941 tmpAddress = value << 14;
943 tmpAddress &= gbRomSizeMask;
944 gbDataHuC3.mapperROMBank = value;
945 gbMemoryMap[0x04] = &gbRom[tmpAddress];
946 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
947 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
948 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
949 break;
950 case 0x4000: // RAM bank select
951 value = value & 0x03;
952 if (value == gbDataHuC3.mapperRAMBank)
953 break;
954 tmpAddress = value << 13;
955 tmpAddress &= gbRamSizeMask;
956 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
957 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
958 gbDataHuC3.mapperRAMBank = value;
959 gbDataHuC3.mapperRAMAddress = tmpAddress;
960 break;
961 case 0x6000: // nothing to do!
962 break;
963 }
964 }
966 // HuC3 read RAM
967 u8 mapperHuC3ReadRAM(u16 address)
968 {
969 if (gbDataHuC3.mapperRAMFlag > 0x0b &&
970 gbDataHuC3.mapperRAMFlag < 0x0e)
971 {
972 if (gbDataHuC3.mapperRAMFlag != 0x0c)
973 return 1;
974 return gbDataHuC3.mapperRAMValue;
975 }
976 else
977 return gbReadMemoryQuick(address);
978 }
980 // HuC3 RAM write
981 void mapperHuC3RAM(u16 address, u8 value)
982 {
983 int32 *p;
985 if (gbDataHuC3.mapperRAMFlag < 0x0b ||
986 gbDataHuC3.mapperRAMFlag > 0x0e)
987 {
988 if (gbDataHuC3.mapperRAMEnable)
989 {
990 if (gbRamSize)
991 {
992 gbWriteMemoryQuick(address, value);
993 systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
994 }
995 }
996 }
997 else
998 {
999 if (gbDataHuC3.mapperRAMFlag == 0x0b)
1001 if (value == 0x62)
1003 gbDataHuC3.mapperRAMValue = 1;
1005 else
1007 switch (value & 0xf0)
1009 case 0x10:
1010 p = &gbDataHuC3.mapperRegister2;
1011 gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++);
1012 if (gbDataHuC3.mapperRegister1 > 6)
1013 gbDataHuC3.mapperRegister1 = 0;
1014 break;
1015 case 0x30:
1016 p = &gbDataHuC3.mapperRegister2;
1017 *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f;
1018 if (gbDataHuC3.mapperRegister1 > 6)
1019 gbDataHuC3.mapperRegister1 = 0;
1020 gbDataHuC3.mapperAddress =
1021 (gbDataHuC3.mapperRegister6 << 24) |
1022 (gbDataHuC3.mapperRegister5 << 16) |
1023 (gbDataHuC3.mapperRegister4 << 8) |
1024 (gbDataHuC3.mapperRegister3 << 4) |
1025 (gbDataHuC3.mapperRegister2);
1026 break;
1027 case 0x40:
1028 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) |
1029 (value & 0x0f);
1030 gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f);
1031 gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f);
1032 gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f);
1033 gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f);
1034 gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f);
1035 gbDataHuC3.mapperRegister7 = 0;
1036 gbDataHuC3.mapperRegister8 = 0;
1037 gbDataHuC3.mapperRAMValue = 0;
1038 break;
1039 case 0x50:
1040 gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) |
1041 ((value << 4)&0x0f);
1042 break;
1043 default:
1044 gbDataHuC3.mapperRAMValue = 1;
1045 break;
1052 void memoryUpdateMapHuC3()
1054 int tmpAddress = gbDataHuC3.mapperROMBank << 14;
1056 tmpAddress &= gbRomSizeMask;
1057 gbMemoryMap[0x04] = &gbRom[tmpAddress];
1058 gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
1059 gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
1060 gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
1062 if (gbRamSize)
1064 tmpAddress = gbDataHuC3.mapperRAMBank << 13;
1065 tmpAddress &= gbRamSizeMask;
1066 gbMemoryMap[0x0a] = &gbRam[tmpAddress];
1067 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];