1 // VisualBoyAdvance - Nintendo Gameboy/GameboyAdvance (TM) emulator.
2 // Copyright (C) 1999-2003 Forgotten
3 // Copyright (C) 2004 Forgotten and the VBA development team
4 
5 // This program is free software; you can redistribute it and/or modify
6 // it under the terms of the GNU General Public License as published by
7 // the Free Software Foundation; either version 2, or(at your option)
8 // any later version.
9 //
10 // This program is distributed in the hope that it will be useful,
11 // but WITHOUT ANY WARRANTY; without even the implied warranty of
12 // MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
13 // GNU General Public License for more details.
14 //
15 // You should have received a copy of the GNU General Public License
16 // along with this program; if not, write to the Free Software Foundation,
17 // Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
18 
19 #include "../GBA.h"
20 #include "../Port.h"
21 #include "gbGlobals.h"
22 #include "gbMemory.h"
23 
24 mapperMBC1 gbDataMBC1 = {
25   0, // RAM enable
26   1, // ROM bank
27   0, // RAM bank
28   0, // memory model
29   0, // ROM high address
30   0  // RAM address
31 };
32 
33 // MBC1 ROM write registers
mapperMBC1ROM(u16 address,u8 value)34 void mapperMBC1ROM(u16 address, u8 value)
35 {
36   int tmpAddress = 0;
37 
38   switch(address & 0x6000) {
39   case 0x0000: // RAM enable register
40     gbDataMBC1.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
41     break;
42   case 0x2000: // ROM bank select
43     //    value = value & 0x1f;
44     if(value == 0)
45       value = 1;
46     if(value == gbDataMBC1.mapperROMBank)
47       break;
48 
49     tmpAddress = value << 14;
50 
51     // check current model
52     if(gbDataMBC1.mapperMemoryModel == 0) {
53       // model is 16/8, so we have a high address in use
54       tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
55     }
56 
57     tmpAddress &= gbRomSizeMask;
58     gbDataMBC1.mapperROMBank = value;
59     gbMemoryMap[0x04] = &gbRom[tmpAddress];
60     gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
61     gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
62     gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
63     break;
64   case 0x4000: // RAM bank select
65     if(gbDataMBC1.mapperMemoryModel == 1) {
66       // 4/32 model, RAM bank switching provided
67       value = value & 0x03;
68       if(value == gbDataMBC1.mapperRAMBank)
69         break;
70       tmpAddress = value << 13;
71       tmpAddress &= gbRamSizeMask;
72       gbMemoryMap[0x0a] = &gbRam[tmpAddress];
73       gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
74       gbDataMBC1.mapperRAMBank = value;
75       gbDataMBC1.mapperRAMAddress = tmpAddress;
76     } else {
77       // 16/8, set the high address
78       gbDataMBC1.mapperROMHighAddress = value & 0x03;
79       tmpAddress = gbDataMBC1.mapperROMBank << 14;
80       tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
81       tmpAddress &= gbRomSizeMask;
82       gbMemoryMap[0x04] = &gbRom[tmpAddress];
83       gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
84       gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
85       gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
86     }
87     break;
88   case 0x6000: // memory model select
89     gbDataMBC1.mapperMemoryModel = value & 1;
90     break;
91   }
92 }
93 
94 // MBC1 RAM write
mapperMBC1RAM(u16 address,u8 value)95 void mapperMBC1RAM(u16 address, u8 value)
96 {
97   if(gbDataMBC1.mapperRAMEnable) {
98     if(gbRamSize) {
99       gbMemoryMap[address >> 12][address & 0x0fff] = value;
100       systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
101     }
102   }
103 }
104 
memoryUpdateMapMBC1()105 void memoryUpdateMapMBC1()
106 {
107   int tmpAddress = gbDataMBC1.mapperROMBank << 14;
108 
109   // check current model
110   if(gbDataMBC1.mapperMemoryModel == 1) {
111     // model is 16/8, so we have a high address in use
112     tmpAddress |= (gbDataMBC1.mapperROMHighAddress) << 19;
113   }
114 
115   tmpAddress &= gbRomSizeMask;
116   gbMemoryMap[0x04] = &gbRom[tmpAddress];
117   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
118   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
119   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
120 
121   if(gbRamSize) {
122     gbMemoryMap[0x0a] = &gbRam[gbDataMBC1.mapperRAMAddress];
123     gbMemoryMap[0x0b] = &gbRam[gbDataMBC1.mapperRAMAddress + 0x1000];
124   }
125 }
126 
127 mapperMBC2 gbDataMBC2 = {
128   0, // RAM enable
129   1  // ROM bank
130 };
131 
132 // MBC2 ROM write registers
mapperMBC2ROM(u16 address,u8 value)133 void mapperMBC2ROM(u16 address, u8 value)
134 {
135   switch(address & 0x6000) {
136   case 0x0000: // RAM enable
137     if(!(address & 0x0100)) {
138       gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a;
139     }
140     break;
141   case 0x2000: // ROM bank select
142     if(address & 0x0100) {
143       value &= 0x0f;
144 
145       if(value == 0)
146         value = 1;
147       if(gbDataMBC2.mapperROMBank != value) {
148         gbDataMBC2.mapperROMBank = value;
149 
150         int tmpAddress = value << 14;
151 
152         tmpAddress &= gbRomSizeMask;
153 
154         gbMemoryMap[0x04] = &gbRom[tmpAddress];
155         gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
156         gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
157         gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
158       }
159     }
160     break;
161   }
162 }
163 
164 // MBC2 RAM write
mapperMBC2RAM(u16 address,u8 value)165 void mapperMBC2RAM(u16 address, u8 value)
166 {
167   if(gbDataMBC2.mapperRAMEnable) {
168     if(gbRamSize && address < 0xa200) {
169       gbMemoryMap[address >> 12][address & 0x0fff] = value;
170       systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
171     }
172   }
173 }
174 
memoryUpdateMapMBC2()175 void memoryUpdateMapMBC2()
176 {
177   int tmpAddress = gbDataMBC2.mapperROMBank << 14;
178 
179   tmpAddress &= gbRomSizeMask;
180 
181   gbMemoryMap[0x04] = &gbRom[tmpAddress];
182   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
183   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
184   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
185 }
186 
187 mapperMBC3 gbDataMBC3 = {
188   0, // RAM enable
189   1, // ROM bank
190   0, // RAM bank
191   0, // RAM address
192   0, // timer clock latch
193   0, // timer clock register
194   0, // timer seconds
195   0, // timer minutes
196   0, // timer hours
197   0, // timer days
198   0, // timer control
199   0, // timer latched seconds
200   0, // timer latched minutes
201   0, // timer latched hours
202   0, // timer latched days
203   0, // timer latched control
204   (time_t)-1 // last time
205 };
206 
memoryUpdateMBC3Clock()207 void memoryUpdateMBC3Clock()
208 {
209   time_t now = time(NULL);
210   time_t diff = now - gbDataMBC3.mapperLastTime;
211   if(diff > 0) {
212     // update the clock according to the last update time
213     gbDataMBC3.mapperSeconds += diff % 60;
214     if(gbDataMBC3.mapperSeconds > 59) {
215       gbDataMBC3.mapperSeconds -= 60;
216       gbDataMBC3.mapperMinutes++;
217     }
218 
219     diff /= 60;
220 
221     gbDataMBC3.mapperMinutes += diff % 60;
222     if(gbDataMBC3.mapperMinutes > 60) {
223       gbDataMBC3.mapperMinutes -= 60;
224       gbDataMBC3.mapperHours++;
225     }
226 
227     diff /= 60;
228 
229     gbDataMBC3.mapperHours += diff % 24;
230     if(gbDataMBC3.mapperHours > 24) {
231       gbDataMBC3.mapperHours -= 24;
232       gbDataMBC3.mapperDays++;
233     }
234     diff /= 24;
235 
236     gbDataMBC3.mapperDays += diff;
237     if(gbDataMBC3.mapperDays > 255) {
238       if(gbDataMBC3.mapperDays > 511) {
239         gbDataMBC3.mapperDays %= 512;
240         gbDataMBC3.mapperControl |= 0x80;
241       }
242       gbDataMBC3.mapperControl = (gbDataMBC3.mapperControl & 0xfe) |
243         (gbDataMBC3.mapperDays>255 ? 1 : 0);
244     }
245   }
246   gbDataMBC3.mapperLastTime = now;
247 }
248 
249 // MBC3 ROM write registers
mapperMBC3ROM(u16 address,u8 value)250 void mapperMBC3ROM(u16 address, u8 value)
251 {
252   int tmpAddress = 0;
253 
254   switch(address & 0x6000) {
255   case 0x0000: // RAM enable register
256     gbDataMBC3.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
257     break;
258   case 0x2000: // ROM bank select
259     value = value & 0x7f;
260     if(value == 0)
261       value = 1;
262     if(value == gbDataMBC3.mapperROMBank)
263       break;
264 
265     tmpAddress = value << 14;
266 
267     tmpAddress &= gbRomSizeMask;
268     gbDataMBC3.mapperROMBank = value;
269     gbMemoryMap[0x04] = &gbRom[tmpAddress];
270     gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
271     gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
272     gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
273 
274     break;
275   case 0x4000: // RAM bank select
276     if(value < 8) {
277       if(value == gbDataMBC3.mapperRAMBank)
278         break;
279       tmpAddress = value << 13;
280       tmpAddress &= gbRamSizeMask;
281       gbMemoryMap[0x0a] = &gbRam[tmpAddress];
282       gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
283       gbDataMBC3.mapperRAMBank = value;
284       gbDataMBC3.mapperRAMAddress = tmpAddress;
285     } else {
286       if(gbDataMBC3.mapperRAMEnable) {
287         gbDataMBC3.mapperRAMBank = -1;
288 
289         gbDataMBC3.mapperClockRegister = value;
290       }
291     }
292     break;
293   case 0x6000: // clock latch
294     if(gbDataMBC3.mapperClockLatch == 0 && value == 1) {
295       memoryUpdateMBC3Clock();
296       gbDataMBC3.mapperLSeconds = gbDataMBC3.mapperSeconds;
297       gbDataMBC3.mapperLMinutes = gbDataMBC3.mapperMinutes;
298       gbDataMBC3.mapperLHours   = gbDataMBC3.mapperHours;
299       gbDataMBC3.mapperLDays    = gbDataMBC3.mapperDays;
300       gbDataMBC3.mapperLControl = gbDataMBC3.mapperControl;
301     }
302     if(value == 0x00 || value == 0x01)
303       gbDataMBC3.mapperClockLatch = value;
304     break;
305   }
306 }
307 
308 // MBC3 RAM write
mapperMBC3RAM(u16 address,u8 value)309 void mapperMBC3RAM(u16 address, u8 value)
310 {
311   if(gbDataMBC3.mapperRAMEnable) {
312     if(gbDataMBC3.mapperRAMBank != -1) {
313       if(gbRamSize) {
314         gbMemoryMap[address>>12][address & 0x0fff] = value;
315         systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
316       }
317     } else {
318       time(&gbDataMBC3.mapperLastTime);
319       switch(gbDataMBC3.mapperClockRegister) {
320       case 0x08:
321         gbDataMBC3.mapperSeconds = value;
322         break;
323       case 0x09:
324         gbDataMBC3.mapperMinutes = value;
325         break;
326       case 0x0a:
327         gbDataMBC3.mapperHours = value;
328         break;
329       case 0x0b:
330         gbDataMBC3.mapperDays = value;
331         break;
332       case 0x0c:
333         if(gbDataMBC3.mapperControl & 0x80)
334           gbDataMBC3.mapperControl = 0x80 | value;
335         else
336           gbDataMBC3.mapperControl = value;
337         break;
338       }
339     }
340   }
341 }
342 
343 // MBC3 read RAM
mapperMBC3ReadRAM(u16 address)344 u8 mapperMBC3ReadRAM(u16 address)
345 {
346   if(gbDataMBC3.mapperRAMEnable) {
347     if(gbDataMBC3.mapperRAMBank != -1) {
348       return gbMemoryMap[address>>12][address & 0x0fff];
349     }
350 
351     switch(gbDataMBC3.mapperClockRegister) {
352       case 0x08:
353         return gbDataMBC3.mapperLSeconds;
354         break;
355       case 0x09:
356         return gbDataMBC3.mapperLMinutes;
357         break;
358       case 0x0a:
359         return gbDataMBC3.mapperLHours;
360         break;
361       case 0x0b:
362         return gbDataMBC3.mapperLDays;
363         break;
364       case 0x0c:
365         return gbDataMBC3.mapperLControl;
366     }
367   }
368   return 0;
369 }
370 
memoryUpdateMapMBC3()371 void memoryUpdateMapMBC3()
372 {
373   int tmpAddress = gbDataMBC3.mapperROMBank << 14;
374 
375   tmpAddress &= gbRomSizeMask;
376 
377   gbMemoryMap[0x04] = &gbRom[tmpAddress];
378   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
379   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
380   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
381 
382   if(gbDataMBC3.mapperRAMBank >= 0 && gbRamSize) {
383     tmpAddress = gbDataMBC3.mapperRAMBank << 13;
384     tmpAddress &= gbRamSizeMask;
385     gbMemoryMap[0x0a] = &gbRam[tmpAddress];
386     gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
387   }
388 }
389 
390 mapperMBC5 gbDataMBC5 = {
391   0, // RAM enable
392   1, // ROM bank
393   0, // RAM bank
394   0, // ROM high address
395   0, // RAM address
396   0  // is rumble cartridge?
397 };
398 
399 // MBC5 ROM write registers
mapperMBC5ROM(u16 address,u8 value)400 void mapperMBC5ROM(u16 address, u8 value)
401 {
402   int tmpAddress = 0;
403 
404   switch(address & 0x6000) {
405   case 0x0000: // RAM enable register
406     gbDataMBC5.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
407     break;
408   case 0x2000: // ROM bank select
409     if(address < 0x3000) {
410       value = value & 0xff;
411       if(value == gbDataMBC5.mapperROMBank)
412         break;
413 
414       tmpAddress = (value << 14) | (gbDataMBC5.mapperROMHighAddress << 22) ;
415 
416       tmpAddress &= gbRomSizeMask;
417       gbDataMBC5.mapperROMBank = value;
418       gbMemoryMap[0x04] = &gbRom[tmpAddress];
419       gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
420       gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
421       gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
422 
423     } else {
424       value = value & 1;
425       if(value == gbDataMBC5.mapperROMHighAddress)
426         break;
427 
428       tmpAddress = (gbDataMBC5.mapperROMBank << 14) | (value << 22);
429 
430       tmpAddress &= gbRomSizeMask;
431       gbDataMBC5.mapperROMHighAddress = value;
432       gbMemoryMap[0x04] = &gbRom[tmpAddress];
433       gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
434       gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
435       gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
436     }
437     break;
438   case 0x4000: // RAM bank select
439     if(gbDataMBC5.isRumbleCartridge)
440       value &= 0x07;
441     else
442       value &= 0x0f;
443     if(value == gbDataMBC5.mapperRAMBank)
444       break;
445     tmpAddress = value << 13;
446     tmpAddress &= gbRamSizeMask;
447     if(gbRamSize) {
448       gbMemoryMap[0x0a] = &gbRam[tmpAddress];
449       gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
450 
451       gbDataMBC5.mapperRAMBank = value;
452       gbDataMBC5.mapperRAMAddress = tmpAddress;
453     }
454     break;
455   }
456 }
457 
458 // MBC5 RAM write
mapperMBC5RAM(u16 address,u8 value)459 void mapperMBC5RAM(u16 address, u8 value)
460 {
461   if(gbDataMBC5.mapperRAMEnable) {
462     if(gbRamSize) {
463       gbMemoryMap[address >> 12][address & 0x0fff] = value;
464       systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
465     }
466   }
467 }
468 
memoryUpdateMapMBC5()469 void memoryUpdateMapMBC5()
470 {
471   int tmpAddress = (gbDataMBC5.mapperROMBank << 14) |
472     (gbDataMBC5.mapperROMHighAddress << 22) ;
473 
474   tmpAddress &= gbRomSizeMask;
475   gbMemoryMap[0x04] = &gbRom[tmpAddress];
476   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
477   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
478   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
479 
480   if(gbRamSize) {
481     tmpAddress = gbDataMBC5.mapperRAMBank << 13;
482     tmpAddress &= gbRamSizeMask;
483     gbMemoryMap[0x0a] = &gbRam[tmpAddress];
484     gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
485   }
486 }
487 
488 mapperMBC7 gbDataMBC7 = {
489   0, // RAM enable
490   1, // ROM bank
491   0, // RAM bank
492   0, // RAM address
493   0, // chip select
494   0, // ??
495   0, // mapper state
496   0, // buffer for receiving serial data
497   0, // idle state
498   0, // count of bits received
499   0, // command received
500   0, // address received
501   0, // write enable
502   0, // value to return on ram
503 };
504 
505 // MBC7 ROM write registers
mapperMBC7ROM(u16 address,u8 value)506 void mapperMBC7ROM(u16 address, u8 value)
507 {
508   int tmpAddress = 0;
509 
510   switch(address & 0x6000) {
511   case 0x0000:
512     break;
513   case 0x2000: // ROM bank select
514     value = value & 0x7f;
515     if(value == 0)
516       value = 1;
517 
518     if(value == gbDataMBC7.mapperROMBank)
519       break;
520 
521     tmpAddress = (value << 14);
522 
523     tmpAddress &= gbRomSizeMask;
524     gbDataMBC7.mapperROMBank = value;
525     gbMemoryMap[0x04] = &gbRom[tmpAddress];
526     gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
527     gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
528     gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
529     break;
530   case 0x4000: // RAM bank select/enable
531     if(value < 8) {
532       tmpAddress = (value&3) << 13;
533       tmpAddress &= gbRamSizeMask;
534       gbMemoryMap[0x0a] = &gbMemory[0xa000];
535       gbMemoryMap[0x0b] = &gbMemory[0xb000];
536 
537       gbDataMBC7.mapperRAMBank = value;
538       gbDataMBC7.mapperRAMAddress = tmpAddress;
539       gbDataMBC7.mapperRAMEnable = 0;
540     } else {
541       gbDataMBC7.mapperRAMEnable = 0;
542     }
543     break;
544   }
545 }
546 
547 // MBC7 read RAM
mapperMBC7ReadRAM(u16 address)548 u8 mapperMBC7ReadRAM(u16 address)
549 {
550   switch(address & 0xa0f0) {
551   case 0xa000:
552   case 0xa010:
553   case 0xa060:
554   case 0xa070:
555     return 0;
556   case 0xa020:
557     // sensor X low byte
558     return systemGetSensorX() & 255;
559   case 0xa030:
560     // sensor X high byte
561     return systemGetSensorX() >> 8;
562   case 0xa040:
563     // sensor Y low byte
564     return systemGetSensorY() & 255;
565   case 0xa050:
566     // sensor Y high byte
567     return systemGetSensorY() >> 8;
568   case 0xa080:
569     return gbDataMBC7.value;
570   }
571   return 0xff;
572 }
573 
574 // MBC7 RAM write
mapperMBC7RAM(u16 address,u8 value)575 void mapperMBC7RAM(u16 address, u8 value)
576 {
577   if(address == 0xa080) {
578     // special processing needed
579     int oldCs = gbDataMBC7.cs,oldSk=gbDataMBC7.sk;
580 
581     gbDataMBC7.cs=value>>7;
582     gbDataMBC7.sk=(value>>6)&1;
583 
584     if(!oldCs && gbDataMBC7.cs) {
585       if(gbDataMBC7.state==5) {
586         if(gbDataMBC7.writeEnable) {
587           gbMemory[0xa000+gbDataMBC7.address*2]=gbDataMBC7.buffer>>8;
588           gbMemory[0xa000+gbDataMBC7.address*2+1]=gbDataMBC7.buffer&0xff;
589           systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
590         }
591         gbDataMBC7.state=0;
592         gbDataMBC7.value=1;
593       } else {
594         gbDataMBC7.idle=true;
595         gbDataMBC7.state=0;
596       }
597     }
598 
599     if(!oldSk && gbDataMBC7.sk) {
600       if(gbDataMBC7.idle) {
601         if(value & 0x02) {
602           gbDataMBC7.idle=false;
603           gbDataMBC7.count=0;
604           gbDataMBC7.state=1;
605         }
606       } else {
607         switch(gbDataMBC7.state) {
608         case 1:
609           // receiving command
610           gbDataMBC7.buffer <<= 1;
611           gbDataMBC7.buffer |= (value & 0x02)?1:0;
612           gbDataMBC7.count++;
613           if(gbDataMBC7.count==2) {
614             // finished receiving command
615             gbDataMBC7.state=2;
616             gbDataMBC7.count=0;
617             gbDataMBC7.code=gbDataMBC7.buffer & 3;
618           }
619           break;
620         case 2:
621           // receive address
622           gbDataMBC7.buffer <<= 1;
623           gbDataMBC7.buffer |= (value&0x02)?1:0;
624           gbDataMBC7.count++;
625           if(gbDataMBC7.count==8) {
626           // finish receiving
627             gbDataMBC7.state=3;
628             gbDataMBC7.count=0;
629             gbDataMBC7.address=gbDataMBC7.buffer&0xff;
630             if(gbDataMBC7.code==0) {
631               if((gbDataMBC7.address>>6)==0) {
632                 gbDataMBC7.writeEnable=0;
633                 gbDataMBC7.state=0;
634               } else if((gbDataMBC7.address>>6) == 3) {
635                 gbDataMBC7.writeEnable=1;
636                 gbDataMBC7.state=0;
637               }
638             }
639           }
640           break;
641         case 3:
642           gbDataMBC7.buffer <<= 1;
643           gbDataMBC7.buffer |= (value&0x02)?1:0;
644           gbDataMBC7.count++;
645 
646           switch(gbDataMBC7.code) {
647           case 0:
648             if(gbDataMBC7.count==16) {
649               if((gbDataMBC7.address>>6)==0) {
650                 gbDataMBC7.writeEnable = 0;
651                 gbDataMBC7.state=0;
652               } else if((gbDataMBC7.address>>6)==1) {
653                 if (gbDataMBC7.writeEnable) {
654                   for(int i=0;i<256;i++) {
655                     gbMemory[0xa000+i*2] = gbDataMBC7.buffer >> 8;
656                     gbMemory[0xa000+i*2+1] = gbDataMBC7.buffer & 0xff;
657                     systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
658                   }
659                 }
660                 gbDataMBC7.state=5;
661               } else if((gbDataMBC7.address>>6) == 2) {
662                 if (gbDataMBC7.writeEnable) {
663                   for(int i=0;i<256;i++)
664                     WRITE16LE((u16 *)&gbMemory[0xa000+i*2], 0xffff);
665                   systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
666                 }
667                 gbDataMBC7.state=5;
668               } else if((gbDataMBC7.address>>6)==3) {
669                 gbDataMBC7.writeEnable = 1;
670                 gbDataMBC7.state=0;
671               }
672               gbDataMBC7.count=0;
673             }
674             break;
675           case 1:
676             if(gbDataMBC7.count==16) {
677               gbDataMBC7.count=0;
678               gbDataMBC7.state=5;
679               gbDataMBC7.value=0;
680             }
681             break;
682           case 2:
683             if(gbDataMBC7.count==1) {
684               gbDataMBC7.state=4;
685               gbDataMBC7.count=0;
686               gbDataMBC7.buffer = (gbMemory[0xa000+gbDataMBC7.address*2]<<8)|
687                 (gbMemory[0xa000+gbDataMBC7.address*2+1]);
688             }
689             break;
690           case 3:
691             if(gbDataMBC7.count==16) {
692               gbDataMBC7.count=0;
693               gbDataMBC7.state=5;
694               gbDataMBC7.value=0;
695               gbDataMBC7.buffer=0xffff;
696             }
697             break;
698           }
699           break;
700         }
701       }
702     }
703 
704     if (oldSk && !gbDataMBC7.sk) {
705       if (gbDataMBC7.state==4) {
706         gbDataMBC7.value = (gbDataMBC7.buffer & 0x8000)?1:0;
707         gbDataMBC7.buffer <<= 1;
708         gbDataMBC7.count++;
709         if (gbDataMBC7.count==16) {
710           gbDataMBC7.count=0;
711           gbDataMBC7.state=0;
712         }
713       }
714     }
715   }
716 }
717 
memoryUpdateMapMBC7()718 void memoryUpdateMapMBC7()
719 {
720   int tmpAddress = (gbDataMBC5.mapperROMBank << 14);
721 
722   tmpAddress &= gbRomSizeMask;
723   gbMemoryMap[0x04] = &gbRom[tmpAddress];
724   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
725   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
726   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
727 }
728 
729 mapperHuC1 gbDataHuC1 = {
730   0, // RAM enable
731   1, // ROM bank
732   0, // RAM bank
733   0, // memory model
734   0, // ROM high address
735   0  // RAM address
736 };
737 
738 // HuC1 ROM write registers
mapperHuC1ROM(u16 address,u8 value)739 void mapperHuC1ROM(u16 address, u8 value)
740 {
741   int tmpAddress = 0;
742 
743   switch(address & 0x6000) {
744   case 0x0000: // RAM enable register
745     gbDataHuC1.mapperRAMEnable = ( ( value & 0x0a) == 0x0a ? 1 : 0);
746     break;
747   case 0x2000: // ROM bank select
748     value = value & 0x3f;
749     if(value == 0)
750       value = 1;
751     if(value == gbDataHuC1.mapperROMBank)
752       break;
753 
754     tmpAddress = value << 14;
755 
756     tmpAddress &= gbRomSizeMask;
757     gbDataHuC1.mapperROMBank = value;
758     gbMemoryMap[0x04] = &gbRom[tmpAddress];
759     gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
760     gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
761     gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
762     break;
763   case 0x4000: // RAM bank select
764     if(gbDataHuC1.mapperMemoryModel == 1) {
765       // 4/32 model, RAM bank switching provided
766       value = value & 0x03;
767       if(value == gbDataHuC1.mapperRAMBank)
768         break;
769       tmpAddress = value << 13;
770       tmpAddress &= gbRamSizeMask;
771       gbMemoryMap[0x0a] = &gbRam[tmpAddress];
772       gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
773       gbDataHuC1.mapperRAMBank = value;
774       gbDataHuC1.mapperRAMAddress = tmpAddress;
775     } else {
776       // 16/8, set the high address
777       gbDataHuC1.mapperROMHighAddress = value & 0x03;
778       tmpAddress = gbDataHuC1.mapperROMBank << 14;
779       tmpAddress |= (gbDataHuC1.mapperROMHighAddress) << 19;
780       tmpAddress &= gbRomSizeMask;
781       gbMemoryMap[0x04] = &gbRom[tmpAddress];
782       gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
783       gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
784       gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
785     }
786     break;
787   case 0x6000: // memory model select
788     gbDataHuC1.mapperMemoryModel = value & 1;
789     break;
790   }
791 }
792 
793 // HuC1 RAM write
mapperHuC1RAM(u16 address,u8 value)794 void mapperHuC1RAM(u16 address, u8 value)
795 {
796   if(gbDataHuC1.mapperRAMEnable) {
797     if(gbRamSize) {
798       gbMemoryMap[address >> 12][address & 0x0fff] = value;
799       systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
800     }
801   }
802 }
803 
memoryUpdateMapHuC1()804 void memoryUpdateMapHuC1()
805 {
806   int tmpAddress = gbDataHuC1.mapperROMBank << 14;
807 
808   tmpAddress &= gbRomSizeMask;
809 
810   gbMemoryMap[0x04] = &gbRom[tmpAddress];
811   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
812   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
813   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
814 
815   if(gbRamSize) {
816     tmpAddress = gbDataHuC1.mapperRAMBank << 13;
817     tmpAddress &= gbRamSizeMask;
818     gbMemoryMap[0x0a] = &gbRam[tmpAddress];
819     gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
820   }
821 }
822 
823 mapperHuC3 gbDataHuC3 = {
824   0, // RAM enable
825   1, // ROM bank
826   0, // RAM bank
827   0, // RAM address
828   0, // RAM flag
829   0  // RAM read value
830 };
831 
832 
833 // HuC3 ROM write registers
mapperHuC3ROM(u16 address,u8 value)834 void mapperHuC3ROM(u16 address, u8 value)
835 {
836   int tmpAddress = 0;
837 
838   switch(address & 0x6000) {
839   case 0x0000: // RAM enable register
840     gbDataHuC3.mapperRAMEnable = ( value == 0x0a ? 1 : 0);
841     gbDataHuC3.mapperRAMFlag = value;
842     if(gbDataHuC3.mapperRAMFlag != 0x0a)
843       gbDataHuC3.mapperRAMBank = -1;
844     break;
845   case 0x2000: // ROM bank select
846     value = value & 0x7f;
847     if(value == 0)
848       value = 1;
849     if(value == gbDataHuC3.mapperROMBank)
850       break;
851 
852     tmpAddress = value << 14;
853 
854     tmpAddress &= gbRomSizeMask;
855     gbDataHuC3.mapperROMBank = value;
856     gbMemoryMap[0x04] = &gbRom[tmpAddress];
857     gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
858     gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
859     gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
860     break;
861   case 0x4000: // RAM bank select
862     value = value & 0x03;
863     if(value == gbDataHuC3.mapperRAMBank)
864       break;
865     tmpAddress = value << 13;
866     tmpAddress &= gbRamSizeMask;
867     gbMemoryMap[0x0a] = &gbRam[tmpAddress];
868     gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
869     gbDataHuC3.mapperRAMBank = value;
870     gbDataHuC3.mapperRAMAddress = tmpAddress;
871     break;
872   case 0x6000: // nothing to do!
873     break;
874   }
875 }
876 
877 // HuC3 read RAM
mapperHuC3ReadRAM(u16 address)878 u8 mapperHuC3ReadRAM(u16 address)
879 {
880   if(gbDataHuC3.mapperRAMFlag > 0x0b &&
881      gbDataHuC3.mapperRAMFlag < 0x0e) {
882     if(gbDataHuC3.mapperRAMFlag != 0x0c)
883       return 1;
884     return gbDataHuC3.mapperRAMValue;
885   } else
886     return gbMemoryMap[address >> 12][address & 0x0fff];
887 }
888 
889 // HuC3 RAM write
mapperHuC3RAM(u16 address,u8 value)890 void mapperHuC3RAM(u16 address, u8 value)
891 {
892   int *p;
893 
894   if(gbDataHuC3.mapperRAMFlag < 0x0b ||
895      gbDataHuC3.mapperRAMFlag > 0x0e) {
896     if(gbDataHuC3.mapperRAMEnable) {
897       if(gbRamSize) {
898         gbMemoryMap[address >> 12][address & 0x0fff] = value;
899         systemSaveUpdateCounter = SYSTEM_SAVE_UPDATED;
900       }
901     }
902   } else {
903     if(gbDataHuC3.mapperRAMFlag == 0x0b) {
904       if(value == 0x62) {
905         gbDataHuC3.mapperRAMValue = 1;
906       } else {
907         switch(value & 0xf0) {
908         case 0x10:
909           p = &gbDataHuC3.mapperRegister2;
910           gbDataHuC3.mapperRAMValue = *(p+gbDataHuC3.mapperRegister1++);
911           if(gbDataHuC3.mapperRegister1 > 6)
912             gbDataHuC3.mapperRegister1 = 0;
913           break;
914         case 0x30:
915           p = &gbDataHuC3.mapperRegister2;
916           *(p+gbDataHuC3.mapperRegister1++) = value & 0x0f;
917           if(gbDataHuC3.mapperRegister1 > 6)
918             gbDataHuC3.mapperRegister1 = 0;
919           gbDataHuC3.mapperAddress =
920             (gbDataHuC3.mapperRegister6 << 24) |
921             (gbDataHuC3.mapperRegister5 << 16) |
922             (gbDataHuC3.mapperRegister4 <<  8) |
923             (gbDataHuC3.mapperRegister3 <<  4) |
924             (gbDataHuC3.mapperRegister2);
925           break;
926         case 0x40:
927           gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0xf0) |
928             (value & 0x0f);
929           gbDataHuC3.mapperRegister2 = (gbDataHuC3.mapperAddress & 0x0f);
930           gbDataHuC3.mapperRegister3 = ((gbDataHuC3.mapperAddress>>4)&0x0f);
931           gbDataHuC3.mapperRegister4 = ((gbDataHuC3.mapperAddress>>8)&0x0f);
932           gbDataHuC3.mapperRegister5 = ((gbDataHuC3.mapperAddress>>16)&0x0f);
933           gbDataHuC3.mapperRegister6 = ((gbDataHuC3.mapperAddress>>24)&0x0f);
934           gbDataHuC3.mapperRegister7 = 0;
935           gbDataHuC3.mapperRegister8 = 0;
936           gbDataHuC3.mapperRAMValue = 0;
937           break;
938         case 0x50:
939           gbDataHuC3.mapperRegister1 = (gbDataHuC3.mapperRegister1 & 0x0f) |
940             ((value << 4)&0x0f);
941           break;
942         default:
943           gbDataHuC3.mapperRAMValue = 1;
944           break;
945         }
946       }
947     }
948   }
949 }
950 
memoryUpdateMapHuC3()951 void memoryUpdateMapHuC3()
952 {
953   int tmpAddress = gbDataHuC3.mapperROMBank << 14;
954 
955   tmpAddress &= gbRomSizeMask;
956   gbMemoryMap[0x04] = &gbRom[tmpAddress];
957   gbMemoryMap[0x05] = &gbRom[tmpAddress + 0x1000];
958   gbMemoryMap[0x06] = &gbRom[tmpAddress + 0x2000];
959   gbMemoryMap[0x07] = &gbRom[tmpAddress + 0x3000];
960 
961   if(gbRamSize) {
962     tmpAddress = gbDataHuC3.mapperRAMBank << 13;
963     tmpAddress &= gbRamSizeMask;
964     gbMemoryMap[0x0a] = &gbRam[tmpAddress];
965     gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];
966   }
967 }
968