private void Setup_Mapper() { // setup up mapper based on header entry string mppr; switch (header[0x47]) { case 0x0: mapper = new MapperDefault(); mppr = "NROM"; break; case 0x1: mapper = new MapperMBC1(); mppr = "MBC1"; break; case 0x2: mapper = new MapperMBC1(); mppr = "MBC1"; break; case 0x3: mapper = new MapperMBC1(); mppr = "MBC1"; break; case 0x5: mapper = new MapperMBC2(); mppr = "MBC2"; break; case 0x6: mapper = new MapperMBC2(); mppr = "MBC2"; break; case 0x8: mapper = new MapperDefault(); mppr = "NROM"; break; case 0x9: mapper = new MapperDefault(); mppr = "NROM"; break; case 0xB: mapper = new MapperMMM01(); mppr = "MMM01"; break; case 0xC: mapper = new MapperMMM01(); mppr = "MMM01"; break; case 0xD: mapper = new MapperMMM01(); mppr = "MMM01"; break; case 0xF: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x10: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x11: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x12: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x13: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x19: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1A: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1B: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1C: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1D: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1E: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x20: mapper = new MapperMBC6(); mppr = "MBC6"; break; case 0x22: mapper = new MapperMBC7(); mppr = "MBC7"; break; case 0xFC: mapper = new MapperCamera(); mppr = "CAM"; break; case 0xFD: mapper = new MapperTAMA5(); mppr = "TAMA5"; break; case 0xFE: mapper = new MapperHuC3(); mppr = "HuC3"; break; case 0xFF: mapper = new MapperHuC1(); mppr = "HuC1"; break; // Bootleg mappers // NOTE: Sachen mapper selection does not account for scrambling, so if another bootleg mapper // identifies itself as 0x31, this will need to be modified case 0x31: mapper = new MapperSachen2(); mppr = "Schn2"; break; case 0x4: case 0x7: case 0xA: case 0xE: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x1F: case 0x21: default: // mapper not implemented Console.WriteLine(header[0x47]); throw new Exception("Mapper not implemented"); break; } // special case for multi cart mappers if ((_rom.HashMD5(0, _rom.Length) == "97122B9B183AAB4079C8D36A4CE6E9C1") || (_rom.HashMD5(0, _rom.Length) == "9FB9C42CF52DCFDCFBAD5E61AE1B5777") || (_rom.HashMD5(0, _rom.Length) == "CF1F58AB72112716D3C615A553B2F481") ) { Console.WriteLine("Using Multi-Cart Mapper"); mapper = new MapperMBC1Multi(); } Console.Write("Mapper: "); Console.WriteLine(mppr); cart_RAM = null; switch (header[0x49]) { case 1: cart_RAM = new byte[0x800]; break; case 2: cart_RAM = new byte[0x2000]; break; case 3: cart_RAM = new byte[0x8000]; break; case 4: cart_RAM = new byte[0x20000]; break; case 5: cart_RAM = new byte[0x10000]; break; } // Sachen maper not known to have RAM if ((mppr == "Schn1") || (mppr == "Schn2")) { cart_RAM = null; } // mbc2 carts have built in RAM if (mppr == "MBC2") { cart_RAM = new byte[0x200]; } mapper.Core = this; mapper.Initialize(); if (cart_RAM != null) { Console.Write("RAM: "); Console.WriteLine(cart_RAM.Length); if (_syncSettings.Use_SRAM) { // load cartRAM here } else { for (int i = 0; i < cart_RAM.Length; i++) { cart_RAM[i] = 0xFF; } } } // Extra RTC initialization for mbc3 if (mppr == "MBC3") { Use_RTC = true; int days = (int)Math.Floor(_syncSettings.RTCInitialTime / 86400.0); int days_upper = ((days & 0x100) >> 8) | ((days & 0x200) >> 2); mapper.RTC_Get((byte)days_upper, 4); mapper.RTC_Get((byte)(days & 0xFF), 3); int remaining = _syncSettings.RTCInitialTime - (days * 86400); int hours = (int)Math.Floor(remaining / 3600.0); mapper.RTC_Get((byte)(hours & 0xFF), 2); remaining = remaining - (hours * 3600); int minutes = (int)Math.Floor(remaining / 60.0); mapper.RTC_Get((byte)(minutes & 0xFF), 1); remaining = remaining - (minutes * 60); mapper.RTC_Get((byte)(remaining & 0xFF), 0); } }
private void Setup_Mapper() { // setup up mapper based on header entry string mppr; switch (header[0x47]) { case 0x0: mapper = new MapperDefault(); mppr = "NROM"; break; case 0x1: mapper = new MapperMBC1(); mppr = "MBC1"; break; case 0x2: mapper = new MapperMBC1(); mppr = "MBC1"; break; case 0x3: mapper = new MapperMBC1(); mppr = "MBC1"; has_bat = true; break; case 0x5: mapper = new MapperMBC2(); mppr = "MBC2"; break; case 0x6: mapper = new MapperMBC2(); mppr = "MBC2"; has_bat = true; break; case 0x8: mapper = new MapperDefault(); mppr = "NROM"; break; case 0x9: mapper = new MapperDefault(); mppr = "NROM"; has_bat = true; break; case 0xB: mapper = new MapperMMM01(); mppr = "MMM01"; break; case 0xC: mapper = new MapperMMM01(); mppr = "MMM01"; break; case 0xD: mapper = new MapperMMM01(); mppr = "MMM01"; has_bat = true; break; case 0xF: mapper = new MapperMBC3(); mppr = "MBC3"; has_bat = true; break; case 0x10: mapper = new MapperMBC3(); mppr = "MBC3"; has_bat = true; break; case 0x11: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x12: mapper = new MapperMBC3(); mppr = "MBC3"; break; case 0x13: mapper = new MapperMBC3(); mppr = "MBC3"; has_bat = true; break; case 0x19: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1A: mapper = new MapperMBC5(); mppr = "MBC5"; has_bat = true; break; case 0x1B: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1C: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1D: mapper = new MapperMBC5(); mppr = "MBC5"; break; case 0x1E: mapper = new MapperMBC5(); mppr = "MBC5"; has_bat = true; break; case 0x20: mapper = new MapperMBC6(); mppr = "MBC6"; break; case 0x22: mapper = new MapperMBC7(); mppr = "MBC7"; has_bat = true; break; case 0xFC: mapper = new MapperCamera(); mppr = "CAM"; break; case 0xFD: mapper = new MapperTAMA5(); mppr = "TAMA5"; break; case 0xFE: mapper = new MapperHuC3(); mppr = "HuC3"; break; case 0xFF: mapper = new MapperHuC1(); mppr = "HuC1"; break; // Bootleg mappers // NOTE: Sachen mapper selection does not account for scrambling, so if another bootleg mapper // identifies itself as 0x31, this will need to be modified case 0x31: mapper = new MapperSachen2(); mppr = "Schn2"; break; case 0x4: case 0x7: case 0xA: case 0xE: case 0x14: case 0x15: case 0x16: case 0x17: case 0x18: case 0x1F: case 0x21: default: // mapper not implemented Console.WriteLine(header[0x47]); throw new Exception("Mapper not implemented"); } // special case for multi cart mappers if ((_rom.HashMD5(0, _rom.Length) == "97122B9B183AAB4079C8D36A4CE6E9C1") || (_rom.HashMD5(0, _rom.Length) == "9FB9C42CF52DCFDCFBAD5E61AE1B5777") || (_rom.HashMD5(0, _rom.Length) == "CF1F58AB72112716D3C615A553B2F481") ) { Console.WriteLine("Using Multi-Cart Mapper"); mapper = new MapperMBC1Multi(); } // Wisdom Tree does not identify their mapper, so use hash instead if ((_rom.HashMD5(0, _rom.Length) == "2C07CAEE51A1F0C91C72C7C6F380B0F6") || // Joshua (_rom.HashMD5(0, _rom.Length) == "37E017C8D1A45BAB609FB5B43FB64337") || // Spiritual Warfare (_rom.HashMD5(0, _rom.Length) == "AB1FA0ED0207B1D0D5F401F0CD17BEBF") || // Exodus (_rom.HashMD5(0, _rom.Length) == "BA2AC3587B3E1B36DE52E740274071B0") || // Bible - KJV (_rom.HashMD5(0, _rom.Length) == "8CDDB8B2DCD3EC1A3FDD770DF8BDA07C") // Bible - NIV ) { Console.WriteLine("Using Wisdom Tree Mapper"); mapper = new MapperWT(); mppr = "Wtree"; } // special case for bootlegs if ((_rom.HashMD5(0, _rom.Length) == "CAE0998A899DF2EE6ABA8E7695C2A096")) { Console.WriteLine("Using RockMan 8 (Unlicensed) Mapper"); mapper = new MapperRM8(); } if ((_rom.HashMD5(0, _rom.Length) == "D3C1924D847BC5D125BF54C2076BE27A")) { Console.WriteLine("Using Sachen 1 (Unlicensed) Mapper"); mapper = new MapperSachen1(); mppr = "Schn1"; } Console.Write("Mapper: "); Console.WriteLine(mppr); cart_RAM = null; switch (header[0x49]) { case 1: cart_RAM = new byte[0x800]; break; case 2: cart_RAM = new byte[0x2000]; break; case 3: cart_RAM = new byte[0x8000]; break; case 4: cart_RAM = new byte[0x20000]; break; case 5: cart_RAM = new byte[0x10000]; break; case 0: Console.WriteLine("Mapper Number indicates Battery Backed RAM but none present."); Console.WriteLine("Disabling Battery Setting."); has_bat = false; break; } // Sachen maper not known to have RAM if ((mppr == "Schn1") || (mppr == "Schn2")) { cart_RAM = null; Use_MT = true; } // mbc2 carts have built in RAM if (mppr == "MBC2") { cart_RAM = new byte[0x200]; } // mbc7 has 256 bytes of RAM, regardless of any header info if (mppr == "MBC7") { cart_RAM = new byte[0x100]; has_bat = true; } mapper.Core = this; mapper.Initialize(); if (cart_RAM != null && (mppr != "MBC7")) { Console.Write("RAM: "); Console.WriteLine(cart_RAM.Length); for (int i = 0; i < cart_RAM.Length; i++) { cart_RAM[i] = 0xFF; } } // Extra RTC initialization for mbc3 if (mppr == "MBC3") { Use_MT = true; int days = (int)Math.Floor(_syncSettings.RTCInitialTime / 86400.0); int days_upper = ((days & 0x100) >> 8) | ((days & 0x200) >> 2); mapper.RTC_Get((byte)days_upper, 4); mapper.RTC_Get((byte)(days & 0xFF), 3); int remaining = _syncSettings.RTCInitialTime - (days * 86400); int hours = (int)Math.Floor(remaining / 3600.0); mapper.RTC_Get((byte)(hours & 0xFF), 2); remaining = remaining - (hours * 3600); int minutes = (int)Math.Floor(remaining / 60.0); mapper.RTC_Get((byte)(minutes & 0xFF), 1); remaining = remaining - (minutes * 60); mapper.RTC_Get((byte)(remaining & 0xFF), 0); } if (mppr == "HuC3") { Use_MT = true; int years = (int)Math.Floor(_syncSettings.RTCInitialTime / 31536000.0); mapper.RTC_Get((byte)years, 24); int remaining = _syncSettings.RTCInitialTime - (years * 31536000); int days = (int)Math.Floor(remaining / 86400.0); int days_upper = (days >> 8) & 0xF; mapper.RTC_Get((byte)days_upper, 20); mapper.RTC_Get((byte)(days & 0xFF), 12); remaining = remaining - (days * 86400); int minutes = (int)Math.Floor(remaining / 60.0); int minutes_upper = (minutes >> 8) & 0xF; mapper.RTC_Get((byte)(minutes_upper), 8); mapper.RTC_Get((byte)(remaining & 0xFF), 0); } }