Mercurial > vba-clojure
view src/gb/gbMemory.cpp @ 396:c7a43f4ffd9d
fixed bug where A was always 0 when the self-modigying code was executed.
author | Robert McIntyre <rlm@mit.edu> |
---|---|
date | Fri, 13 Apr 2012 04:50:58 -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 enable8 1, // ROM bank9 0, // RAM bank10 0, // memory model11 0, // ROM high address12 0 // RAM address13 };15 // MBC1 ROM write registers16 void mapperMBC1ROM(u16 address, u8 value)17 {18 int tmpAddress = 0;20 switch (address & 0x6000)21 {22 case 0x0000: // RAM enable register23 gbDataMBC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);24 break;25 case 0x2000: // ROM bank select26 // value = value & 0x1f;27 if (value == 0)28 value = 1;29 if (value == gbDataMBC1.mapperROMBank)30 break;32 tmpAddress = value << 14;34 // check current model35 if (gbDataMBC1.mapperMemoryModel == 0)36 {37 // model is 16/8, so we have a high address in use38 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 select49 if (gbDataMBC1.mapperMemoryModel == 1)50 {51 // 4/32 model, RAM bank switching provided52 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 else63 {64 // 16/8, set the high address65 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 select76 gbDataMBC1.mapperMemoryModel = value & 1;77 break;78 }79 }81 // MBC1 RAM write82 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 model99 if (gbDataMBC1.mapperMemoryModel == 1)100 {101 // model is 16/8, so we have a high address in use102 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 enable120 1 // ROM bank121 };123 // MBC2 ROM write registers124 void mapperMBC2ROM(u16 address, u8 value)125 {126 switch (address & 0x6000)127 {128 case 0x0000: // RAM enable129 if (!(address & 0x0100))130 {131 gbDataMBC2.mapperRAMEnable = (value & 0x0f) == 0x0a;132 }133 break;134 case 0x2000: // ROM bank select135 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 write160 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 enable186 1, // ROM bank187 0, // RAM bank188 0, // RAM address189 0, // timer clock latch190 0, // timer clock register191 0, // timer seconds192 0, // timer minutes193 0, // timer hours194 0, // timer days195 0, // timer control196 0, // timer latched seconds197 0, // timer latched minutes198 0, // timer latched hours199 0, // timer latched days200 0, // timer latched control201 (time_t)-1 // last time202 };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 else211 now = time(NULL);213 time_t diff = now - gbDataMBC3.mapperLastTime;214 if (diff > 0)215 {216 // update the clock according to the last update time217 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 registers259 void mapperMBC3ROM(u16 address, u8 value)260 {261 int tmpAddress = 0;263 switch (address & 0x6000)264 {265 case 0x0000: // RAM enable register266 gbDataMBC3.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);267 break;268 case 0x2000: // ROM bank select269 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 select286 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 else298 {299 if (gbDataMBC3.mapperRAMEnable)300 {301 gbDataMBC3.mapperRAMBank = -1;303 gbDataMBC3.mapperClockRegister = value;304 }305 }306 break;307 case 0x6000: // clock latch308 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 write324 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 else337 {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 else366 gbDataMBC3.mapperControl = value;367 break;368 }369 }370 }371 }373 // MBC3 read RAM374 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 enable426 1, // ROM bank427 0, // RAM bank428 0, // ROM high address429 0, // RAM address430 0 // is rumble cartridge?431 };433 // MBC5 ROM write registers434 void mapperMBC5ROM(u16 address, u8 value)435 {436 int tmpAddress = 0;438 switch (address & 0x6000)439 {440 case 0x0000: // RAM enable register441 gbDataMBC5.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);442 break;443 case 0x2000: // ROM bank select444 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 else460 {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 select476 if (gbDataMBC5.isRumbleCartridge)477 value &= 0x07;478 else479 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 write497 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 enable531 1, // ROM bank532 0, // RAM bank533 0, // RAM address534 0, // chip select535 0, // ??536 0, // mapper state537 0, // buffer for receiving serial data538 0, // idle state539 0, // count of bits received540 0, // command received541 0, // address received542 0, // write enable543 0, // value to return on ram544 };546 // MBC7 ROM write registers547 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 select556 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/enable573 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 else585 {586 gbDataMBC7.mapperRAMEnable = 0;587 }588 break;589 }590 }592 // MBC7 read RAM593 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 byte604 return systemGetSensorX() & 255;605 case 0xa030:606 // sensor X high byte607 return systemGetSensorX() >> 8;608 case 0xa040:609 // sensor Y low byte610 return systemGetSensorY() & 255;611 case 0xa050:612 // sensor Y high byte613 return systemGetSensorY() >> 8;614 case 0xa080:615 return gbDataMBC7.value;616 }617 return 0xff;618 }620 // MBC7 RAM write621 void mapperMBC7RAM(u16 address, u8 value)622 {623 if (address == 0xa080)624 {625 // special processing needed626 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 else645 {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 else663 {664 switch (gbDataMBC7.state)665 {666 case 1:667 // receiving command668 gbDataMBC7.buffer <<= 1;669 gbDataMBC7.buffer |= (value & 0x02) ? 1 : 0;670 gbDataMBC7.count++;671 if (gbDataMBC7.count == 2)672 {673 // finished receiving command674 gbDataMBC7.state = 2;675 gbDataMBC7.count = 0;676 gbDataMBC7.code = gbDataMBC7.buffer & 3;677 }678 break;679 case 2:680 // receive address681 gbDataMBC7.buffer <<= 1;682 gbDataMBC7.buffer |= (value&0x02) ? 1 : 0;683 gbDataMBC7.count++;684 if (gbDataMBC7.count == 8)685 {686 // finish receiving687 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 enable813 1, // ROM bank814 0, // RAM bank815 0, // memory model816 0, // ROM high address817 0 // RAM address818 };820 // HuC1 ROM write registers821 void mapperHuC1ROM(u16 address, u8 value)822 {823 int tmpAddress = 0;825 switch (address & 0x6000)826 {827 case 0x0000: // RAM enable register828 gbDataHuC1.mapperRAMEnable = ((value & 0x0a) == 0x0a ? 1 : 0);829 break;830 case 0x2000: // ROM bank select831 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 select847 if (gbDataHuC1.mapperMemoryModel == 1)848 {849 // 4/32 model, RAM bank switching provided850 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 else861 {862 // 16/8, set the high address863 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 select874 gbDataHuC1.mapperMemoryModel = value & 1;875 break;876 }877 }879 // HuC1 RAM write880 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 enable914 1, // ROM bank915 0, // RAM bank916 0, // RAM address917 0, // RAM flag918 0 // RAM read value919 };921 // HuC3 ROM write registers922 void mapperHuC3ROM(u16 address, u8 value)923 {924 int tmpAddress = 0;926 switch (address & 0x6000)927 {928 case 0x0000: // RAM enable register929 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 select935 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 select951 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 RAM967 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 else977 return gbReadMemoryQuick(address);978 }980 // HuC3 RAM write981 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 else998 {999 if (gbDataHuC3.mapperRAMFlag == 0x0b)1000 {1001 if (value == 0x62)1002 {1003 gbDataHuC3.mapperRAMValue = 1;1004 }1005 else1006 {1007 switch (value & 0xf0)1008 {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;1046 }1047 }1048 }1049 }1050 }1052 void memoryUpdateMapHuC3()1053 {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)1063 {1064 tmpAddress = gbDataHuC3.mapperRAMBank << 13;1065 tmpAddress &= gbRamSizeMask;1066 gbMemoryMap[0x0a] = &gbRam[tmpAddress];1067 gbMemoryMap[0x0b] = &gbRam[tmpAddress + 0x1000];1068 }1069 }