using System; using System.IO; using System.Linq; using System.Text; using BizHawk.Common; using BizHawk.Common.NumberExtensions; namespace BizHawk.Emulation.Cores.Nintendo.NES { partial class NES { private static int iNES2Wram(int i) { if (i == 0) return 0; if (i == 15) throw new InvalidDataException(); return 1 << (i + 6); } public static bool DetectFromINES(byte[] data, out CartInfo Cart, out CartInfo CartV2) { byte[] ID = new byte[4]; Buffer.BlockCopy(data, 0, ID, 0, 4); if (!ID.SequenceEqual(Encoding.ASCII.GetBytes("NES\x1A"))) { Cart = null; CartV2 = null; return false; } if ((data[7] & 0x0c) == 0x08) { // process as iNES v2 CartV2 = new CartInfo(); CartV2.prg_size = data[4] | data[9] << 8 & 0xf00; CartV2.chr_size = data[5] | data[9] << 4 & 0xf00; CartV2.prg_size *= 16; CartV2.chr_size *= 8; CartV2.wram_battery = (data[6] & 2) != 0; // should this be respected in v2 mode?? int wrambat = iNES2Wram(data[10] >> 4); int wramnon = iNES2Wram(data[10] & 15); CartV2.wram_battery |= wrambat > 0; // fixme - doesn't handle sizes not divisible by 1024 CartV2.wram_size = (short)((wrambat + wramnon) / 1024); int mapper = data[6] >> 4 | data[7] & 0xf0 | data[8] << 8 & 0xf00; int submapper = data[8] >> 4; CartV2.board_type = string.Format("MAPPER{0:d4}-{1:d2}", mapper, submapper); int vrambat = iNES2Wram(data[11] >> 4); int vramnon = iNES2Wram(data[11] & 15); // hopefully a game with battery backed vram understands what to do internally CartV2.wram_battery |= vrambat > 0; CartV2.vram_size = (vrambat + vramnon) / 1024; CartV2.inesmirroring = data[6] & 1 | data[6] >> 2 & 2; switch (CartV2.inesmirroring) { case 0: CartV2.pad_v = 1; break; case 1: CartV2.pad_h = 1; break; } switch (data[12] & 1) { case 0: CartV2.system = "NES-NTSC"; break; case 1: CartV2.system = "NES-PAL"; break; } if ((data[6] & 4) != 0) CartV2.trainer_size = 512; } else { CartV2 = null; } // process as iNES v1 // the DiskDude cleaning is no longer; get better roms Cart = new CartInfo(); Cart.prg_size = data[4]; Cart.chr_size = data[5]; if (Cart.prg_size == 0) Cart.prg_size = 256; Cart.prg_size *= 16; Cart.chr_size *= 8; Cart.wram_battery = (data[6] & 2) != 0; Cart.wram_size = 8; // should be data[8], but that never worked { int mapper = data[6] >> 4 | data[7] & 0xf0; Cart.board_type = string.Format("MAPPER{0:d3}", mapper); } Cart.vram_size = Cart.chr_size > 0 ? 0 : 8; Cart.inesmirroring = data[6] & 1 | data[6] >> 2 & 2; switch (Cart.inesmirroring) { case 0: Cart.pad_v = 1; break; case 1: Cart.pad_h = 1; break; } if (data[6].Bit(2)) Cart.trainer_size = 512; return true; } } }