public override void Reset() { this.romBank = 1; this.ramBank = 0; this.enableExternalRam = false; Array.Clear(this.externalRam, 0, this.externalRam.Length); this.bankingMode = BankingMode.ROM; }
public void WriteByte(byte data, int address) { if (address < MemorySchema.ROM_END) { //TODO determine how to get rid of magic numbers if (address < 0x2000) { switch (_header.BankingMode) { case CartridgeSchema.MBCMode.MBC1: case CartridgeSchema.MBCMode.MBC2: case CartridgeSchema.MBCMode.MBC3: case CartridgeSchema.MBCMode.MBC5: if (_header.BankingMode == CartridgeSchema.MBCMode.MBC2 && Helpers.TestBit((ushort)address, 4)) { return; } _externalRAM.Enabled = Helpers.GetBits(data, 4) == 0x0A; break; } } else if (address < 0x4000) { int newBank; switch (_header.BankingMode) { case CartridgeSchema.MBCMode.NoMBC: break; case CartridgeSchema.MBCMode.MBC1: //Override the lower 5 bits of the ROM Bank newBank = _romBank; Helpers.ResetLowBits(ref newBank, 5); newBank |= Helpers.GetBits(data, 5); SetROMBank(newBank); break; case CartridgeSchema.MBCMode.MBC2: SetROMBank(Helpers.GetBits(data, 4)); break; case CartridgeSchema.MBCMode.MBC3: SetROMBank(Helpers.GetBits(data, 7)); break; case CartridgeSchema.MBCMode.MBC5: if (address < 0x3000) { //Override the lower 5 bits of the ROM Bank newBank = _romBank; Helpers.ResetLowBits(ref newBank, 8); newBank |= Helpers.GetBits(data, 8); SetROMBank(newBank); } else { newBank = _romBank; Helpers.SetBit(ref newBank, 9, Helpers.TestBit(data, 1)); SetROMBank(newBank); } break; default: throw new ArgumentOutOfRangeException(); } } else if (address < 0x6000) { switch (_header.BankingMode) { case CartridgeSchema.MBCMode.MBC1: if (_bankMode == BankingMode.ROMBank) { //Override the bits 5-6 of the romBank int newBank = _romBank; Helpers.ResetHighBits(ref newBank, 3); newBank |= (byte)(data << 5); SetROMBank(newBank); } else { _ramBank = _header.RAMBanks == 0 ? 0 : Helpers.GetBits(data, 2) % _header.RAMBanks; } break; case CartridgeSchema.MBCMode.MBC3: //TODO RTC register select _ramBank = Helpers.GetBits(data, 2) % _header.RAMBanks; break; case CartridgeSchema.MBCMode.MBC5: _ramBank = Helpers.GetBits(data, 4) % _header.RAMBanks; break; } } else if (address < 0x8000) { if (_header.BankingMode == CartridgeSchema.MBCMode.MBC1) { _bankMode = (BankingMode)Helpers.GetBits(data, 1); } } } else if (address >= MemorySchema.EXTERNAL_RAM_START && address < MemorySchema.EXTERNAL_RAM_END && _externalRAM.Enabled) { address = (address - MemorySchema.EXTERNAL_RAM_START) + ((_bankMode == BankingMode.RAMBank ? _ramBank : 0) * CartridgeSchema.RAM_BANK_SIZE); if (address < _externalRAM.Length) { _externalRAM.WriteByte(data, address); } } }
public override void Write(ushort addr, byte value) { // RAM Enable if (addr >= 0x0000 && addr <= 0x1FFF) { if ((value & 0xF) == 0x0A) { this.enableExternalRam = true; } else { this.enableExternalRam = false; } return; } // ROM Bank Number Lower 5 Bits if (addr >= 0x2000 && addr <= 0x3FFF) { this.romBank &= 0b11100000; // Erase 5 bits this.romBank |= (byte)(value & 0b00011111); // Whole 5 bits if (this.romBank == 0) { this.romBank = 1; } return; } // RAM Bank Number / Upper Bits of ROM Bank Number if (addr >= 0x4000 && addr <= 0x5FFF) { value &= 0b11; if (this.bankingMode == BankingMode.RAM) { Console.WriteLine("Set RAM Bank to: " + value); this.ramBank = value; } else { this.romBank &= 0b00011111; // Erase high bits this.romBank |= (byte)(value << 5); } return; } // RAM Bank 00-03 if (addr >= 0xA000 && addr <= 0xBFFF && this.enableExternalRam) { this.externalRam[this.calcBankAddrRam(addr, this.ramBank)] = value; return; } if (addr >= 0x6000 && addr <= 0x7FFF) { if ((value & 1) != 0) { this.bankingMode = BankingMode.RAM; } else { this.bankingMode = BankingMode.ROM; } return; } }