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