public CartridgeHeader(byte[] romData) { // 0x134 - 0x13E - 11 ascii characters of the game title GameTitle = Encoding.ASCII.GetString(romData, 0x134, 11); // 0x13F - 0x142 - 4 ascii character game code GameCode = Encoding.ASCII.GetString(romData, 0x13F, 4); CgbSupportCode = (CgbSupportCode)romData[0x143]; // 0x144 - 0x145 - 2 ascii character licensee code MakerCode = Encoding.ASCII.GetString(romData, 0x144, 2); SgbSupportCode = romData[0x146]; CartridgeType = (CartridgeType)romData[0x147]; RomSize = romData[0x148]; ExternalRamSize = romData[0x149]; DestinationCode = romData[0x14A]; OldLicenseeCode = romData[0x14B]; MaskRomVersion = romData[0x14C]; ComplementCheck = romData[0x14D]; Checksum = (ushort)((romData[0x14E] << 8) | romData[0x14F]); }
public GBHeader(byte[] rom) { // Verify that there's at least enough here to try reading the header info if (rom.Length < 0x014f) { return; } couldParse = true; containsScrollingNintendoGraphic = CheckScrollingGraphics(rom); gameTitle = GetTitle(rom); gbcVal = GetGBCVal(rom); newLicenseeCode = GetNewLicenseeCode(rom); sgbFunctions = GetSGBFunctions(rom); cartridgeType = GetCartridgeType(rom); romSize = GetRomSize(rom); ramSize = GetRamSize(rom); destinationCode = GetDestinationCode(rom); oldLicenseeCode = GetOldLicenseeCode(rom); maskROMVersion = rom[0x14C]; complementCheckByte = rom[0x14D]; checksumHigh = rom[0x14E]; checksumLow = rom[0x14F]; passesComplementCheck = RunComplementCheck(rom); isValid = containsScrollingNintendoGraphic & passesComplementCheck; }
/// <summary> /// Initializes a new instance of the <see cref="CartridgeHeader"/> class. /// </summary> /// <param name="entryPoint">The entry point.</param> /// <param name="title">The title.</param> /// <param name="isGameBoyColour">if set to <c>true</c> [supports game boy colour].</param> /// <param name="licenseCode">The license code.</param> /// <param name="isSuperGameBoy">if set to <c>true</c> [supports super game boy].</param> /// <param name="cartridgeType">Type of the cartridge.</param> /// <param name="romSize">Size of the rom.</param> /// <param name="ramSize">Size of the ram.</param> /// <param name="destinationCode">The destination code.</param> /// <param name="romVersion">The rom version.</param> /// <param name="headerChecksum">The header checksum.</param> /// <param name="romChecksum">The rom checksum.</param> public CartridgeHeader(byte[] entryPoint, string title, bool isGameBoyColour, string licenseCode, bool isSuperGameBoy, CartridgeType cartridgeType, CartridgeRomSize romSize, CartridgeRamSize ramSize, DestinationCode destinationCode, byte romVersion, byte headerChecksum, ushort romChecksum) { EntryPoint = entryPoint; Title = title; IsGameBoyColour = isGameBoyColour; LicenseCode = licenseCode; IsSuperGameBoy = isSuperGameBoy; CartridgeType = cartridgeType; RomSize = romSize; RamSize = ramSize; DestinationCode = destinationCode; RomVersion = romVersion; HeaderChecksum = headerChecksum; RomChecksum = romChecksum; }
public EmulatedCartridge(byte[] romContents) { if (romContents == null) { throw new ArgumentNullException(nameof(romContents)); } _romContents = romContents; if (CartridgeType.IsRom()) { BankController = new RomOnlyBankController(this); } else if (CartridgeType.IsMbc1()) { BankController = new MemoryBankController1(this); } else if (CartridgeType.IsMbc2()) { BankController = new MemoryBankController2(this); } else { throw new NotSupportedException("Unsupported cartridge type " + CartridgeType + "."); } }
public static bool HasTimer(this CartridgeType type) { switch (type) { case CartridgeType.Mbc3TimerBattery: case CartridgeType.Mbc3TimerRamBattery: return(true); } return(false); }
public static bool IsMbc2(this CartridgeType type) { switch (type) { case CartridgeType.Mbc2: case CartridgeType.Mbc2Battery: return(true); } return(false); }
public static bool IsRom(this CartridgeType type) { switch (type) { case CartridgeType.RomOnly: case CartridgeType.RomRam: case CartridgeType.RomRamBattery: return(true); } return(false); }
public void OpenMemo(Stream memo) { _carsize = Math.Min(memo.Length, 0x10000); _car = new byte[_carsize]; memo.Read(_car, 0, (int)_carsize); _cartype = _carsize > 0x4000 ? CartridgeType.SwitchBank : CartridgeType.Simple; //cartouche > 16 Ko _carflags = 4; //cartridge enabled, write disabled, bank 0; Reset(); }
public static bool HasRumble(this CartridgeType type) { switch (type) { case CartridgeType.Mbc5Rumble: case CartridgeType.Mbc5RumbleRam: case CartridgeType.Mbc5RumbleRamBattery: return(true); } return(false); }
public Mbc2(int[] cartridge, CartridgeType type, IBattery battery, int romBanks) { _cartridge = cartridge; _ram = new int[0x0200]; for (var i = 0; i < _ram.Length; i++) { _ram[i] = 0xff; } _battery = battery; battery.LoadRam(_ram); }
/// <summary> /// Returns the proper Cart object, based on the file loaded. /// </summary> /// <param name="romFile">The binary file to load.</param> /// <returns>A Cart with the characteristics of the cartridge the file specifies.</returns> public static Cart LoadCart(byte[] romFile) { CartridgeType cs = (CartridgeType)romFile[0x147]; Cart returnedCart = null; #region MBC switch (cs) { case CartridgeType.ROM: case CartridgeType.ROM_R: case CartridgeType.ROM_RB: returnedCart = new PlainCart(romFile, FeatureList[cs]); break; case CartridgeType.MBC1: case CartridgeType.MBC1_R: case CartridgeType.MBC1_RB: returnedCart = new MBC1(romFile, FeatureList[cs]); break; case CartridgeType.MBC2: case CartridgeType.MBC2_B: returnedCart = new MBC2(romFile, FeatureList[cs]); break; case CartridgeType.MBC3: case CartridgeType.MBC3_TB: case CartridgeType.MBC3_TRB: case CartridgeType.MBC3_R: case CartridgeType.MBC3_RB: returnedCart = new MBC3(romFile, FeatureList[cs]); break; case CartridgeType.MBC5: case CartridgeType.MBC5_M: case CartridgeType.MBC5_MR: case CartridgeType.MBC5_MRB: case CartridgeType.MBC5_R: case CartridgeType.MBC5_RB: returnedCart = new MBC5(romFile, FeatureList[cs]); break; default: throw new System.Exception("Cart is not supported."); } #endregion MBC Logger.GetInstance().Log(new LogMessage(LogMessageSource.Cart, $"Cart type {cs} loaded.")); return(returnedCart); }
public Mbc5(int[] cartridge, CartridgeType type, IBattery battery, int romBanks, int ramBanks) { _cartridge = cartridge; _ramBanks = ramBanks; _ram = new int[0x2000 * Math.Max(_ramBanks, 1)]; for (var i = 0; i < _ram.Length; i++) { _ram[i] = 0xff; } _battery = battery; battery.LoadRam(_ram); }
private void ScrapeMetaData(byte[] rom) { ROM_TITLE = GetROMTitle(rom); gameType = GetGameType(rom); cartridgeType = GetCartridgeType(rom); romBanks = GetNumROMBanks(rom); ramBanks = GetNumRAMBanks(rom); destinationCode = GetDestinationCode(rom); memoryModel = MemoryModel.MM16x8; Debug.Log("ROM Title:{0}\nGame Type:{1}\nCartridge Type:{2}\nROM Banks:{3}\nRAM Banks:{4}\nDestination Code:{5}\n", ROM_TITLE, gameType, cartridgeType, romBanks, ramBanks, destinationCode); }
public Mbc1(int[] cartridge, CartridgeType type, IBattery battery, int romBanks, int ramBanks) { _multicart = romBanks == 64 && IsMulticart(cartridge); _cartridge = cartridge; _ramBanks = ramBanks; _romBanks = romBanks; _ram = new int[0x2000 * _ramBanks]; for (var i = 0; i < _ram.Length; i++) { _ram[i] = 0xff; } _battery = battery; battery.LoadRam(_ram); }
public Mbc3(int[] cartridge, CartridgeType type, IBattery battery, int romBanks, int ramBanks) { _cartridge = cartridge; _ram = new int[0x2000 * Math.Max(ramBanks, 1)]; for (var i = 0; i < _ram.Length; i++) { _ram[i] = 0xff; } _clock = new RealTimeClock(Clock.SystemClock); _battery = battery; var clockData = new long[12]; battery.LoadRamWithClock(_ram, clockData); _clock.Deserialize(clockData); }
public MBCBase(byte[] romData) { _romData = romData; //check if CGB-only game (not supported for now) if (_romData[0x0143] == 0xC0) { throw new NotSupportedException("CGB-only games are not supported"); } _cartridgeType = (CartridgeType)romData[0x0147]; _romSizeType = (RomSizeType)_romData[0x0148]; _ramSizeType = (RamSizeType)_romData[0x0149]; _ramData = new byte[RamSizeInBytes]; }
public static bool HasBattery(this CartridgeType type) { switch (type) { case CartridgeType.RomRamBattery: case CartridgeType.Mbc1RamBattery: case CartridgeType.Mbc2Battery: case CartridgeType.Mbc3RamBattery: case CartridgeType.Mbc3TimerBattery: case CartridgeType.Mbc3TimerRamBattery: case CartridgeType.Mbc4RamBattery: case CartridgeType.Mbc5RamBattery: case CartridgeType.Mmm01RamBattery: case CartridgeType.HuC1RamBattery: return(true); } return(false); }
public Memory(string romPath) { byte[] rom = File.ReadAllBytes(romPath); ROM_TITLE = GetROMTitle(rom); gameType = GetGameType(rom); cartridgeType = GetCartridgeType(rom); int romBanks = GetNumROMBanks(rom); int ramBanks = GetNumRAMBanks(rom); destinationCode = GetDestinationCode(rom); memoryModel = MemoryModel.MM16x8; cartridge = AssembleCartridge(ramBanks, romBanks, rom); Console.WriteLine(ROM_TITLE); Console.WriteLine(gameType); Console.WriteLine(cartridgeType); Console.WriteLine("ROM Banks: {0}", romBanks); Console.WriteLine("RAM Banks: {0}", ramBanks); Console.WriteLine(destinationCode); }
public static IEnumerable <CartridgeType> Values(this CartridgeType src) { return(Enum.GetValues(typeof(CartridgeType)).Cast <CartridgeType>()); }
private static bool NameContainsSegment(this CartridgeType src, string segment) { return(new Regex("(^|_)" + Regex.Escape(segment) + "($|_)").IsMatch(src.ToString())); }
public static bool IsRumble(this CartridgeType src) => src.NameContainsSegment("RUMBLE");
public static bool IsBattery(this CartridgeType src) => src.NameContainsSegment("BATTERY");
public static bool IsTimer(this CartridgeType src) => src.NameContainsSegment("TIMER");
public static bool IsSram(this CartridgeType src) => src.NameContainsSegment("SRAM");
public static bool IsMmm01(this CartridgeType src) => src.NameContainsSegment("MMM01");
public static bool IsMbc5(this CartridgeType src) => src.NameContainsSegment("MBC5");
public void Awake() { _rom = File.ReadAllBytes("./Contrib/ROMs/tetris.gb"); StringBuilder titleString = new StringBuilder(); for (int i = 0x0134; i <= 0x0142; i++) { if (_rom[i] == 0x00) { break; } titleString.Append((char)_rom[i]); } Title = titleString.ToString(); if ((_rom[0x0143] & 0xC0) == 0xC0) { ColorType = ColorType.ColorOnly; } else if ((_rom[0x0143] & 0x80) == 0x80) { ColorType = ColorType.MonochromeOrColor; } else { ColorType = ColorType.Monochrome; } NewLicenseeCode = (_rom[0x0144] << 4) | _rom[0x0145]; SupportsSuperGameBoyFucntionality = _rom[0x0146] == 0x03; CartridgeType = (CartridgeType)_rom[0x0147]; Size = (32 * 1024) << _rom[0x0148]; switch (_rom[0x0149]) { case 0x01: RAMSize = 2048; break; case 0x02: RAMSize = 8192; break; case 0x03: RAMSize = 32768; break; case 0x04: RAMSize = 131072; break; case 0x05: RAMSize = 65536; break; default: RAMSize = 0; break; } IsJapanese = _rom[0x014A] == 0x00; OldLicenseeCode = _rom[0x014B]; MaskROMVersion = _rom[0x014C]; HeaderChecksum = _rom[0x014D]; int calculatedHeaderChecksum = 0; for (int i = 0x0134; i <= 0x014C; i++) { calculatedHeaderChecksum = calculatedHeaderChecksum - _rom[i] - 1; } CalculatedHeaderChecksum = (byte)(calculatedHeaderChecksum & 0xFF); Checksum = (ushort)((_rom[0x014E] << 8) | _rom[0x014F]); int calculatedChecksum = 0; for (int i = 0; i < _rom.Length; i++) { if ((i != 0x014E) && (i != 0x014F)) { calculatedChecksum += _rom[i]; } } CalculatedChecksum = (ushort)(calculatedChecksum & 0xFFFF); }
public Rom(int[] rom, CartridgeType type, int romBanks, int ramBanks) { _rom = rom; }
public void setByte(ushort address, Byte Value) { CartridgeType type = (CartridgeType)this.headerInfoDict.Where(fi => fi.description == "Cartridge Type").First().value; switch (type) { case CartridgeType.ROM_ONLY: break; case CartridgeType.ROM_MBC1: case CartridgeType.ROM_MBC1_RAM: case CartridgeType.ROM_MBC1_RAM_BATT: if (address >= 0x0000 && address <= 0x1FFF) { // RAM Enable } else if (address >= 0x2000 && address <= 0x3FFF) { // ROM Select Byte romBankNum = Value; // ROM Address MBC1 Bug if ((romBankNum & 0x1F) == 0) { romBankNum += 1; } romBankNum = (Byte)(romBankNum & 0x1F); // Set ROM Bank Num if (memContMode == MBC1_Mode.ROM_MODE) { // Set only 5 lsb bits selectedRomBank = (ushort)((selectedRomBank & 0xC0) | (romBankNum & 0x1F)); } } else if (address >= 0x4000 && address <= 0x5FFF) { Byte tmp = (Byte)(Value & 0x03); if (memContMode == MBC1_Mode.ROM_MODE) { // Upper ROM Select (Set upper 2 bits 5-6) selectedRomBank = (ushort)((selectedRomBank & 0x1F) | (tmp << 5)); } else { // RAM Mode selectedRamBank = tmp; } } else if (address >= 0x6000 && address <= 0x7FFF) { // ROM/RAM mode select if (Value == 0) { memContMode = MBC1_Mode.ROM_MODE; } else if (Value == 1) { memContMode = MBC1_Mode.RAM_MODE; } else { throw new ArgumentException($"Invalid Write to ROM Address 0x{address.ToString("X4")} value 0x{Value.ToString("X2")}"); } } else { throw new ArgumentException($"Attempted Write to Address Which is in ROM Space"); } break; default: throw new NotImplementedException($"Cartridge Type {type.ToString()} MMC Operation write at {address.ToString("X4")} not Implemented"); } }