private IEnumerable <XElement> GetSnapElements(XElement snap, CICKeyType cic, RegionType region) { var condition = snap.Attribute("Condition"); var value = snap.Attribute("Value"); Boolean valid = false; if (condition != null) { switch (condition.Value) { case "CIC": valid = CompareCic(value.Value, cic); break; case "Region": valid = CompareRegion(value.Value, region); break; default: break; } if (!valid) { return(Enumerable.Empty <XElement>()); } } List <XElement> writes = new List <XElement>(); writes.AddRange(snap.Elements("GPRRegSet")); writes.AddRange(snap.Elements("Mem32")); writes.AddRange(snap.Elements("BootSnap").SelectMany(s => GetSnapElements(s, cic, region))); return(writes); }
public void LoadBootSnap(CICKeyType cic, RegionType region) { List<GprRegWrite> regs = new List<GprRegWrite>(); List<Mem32Write> mem32 = new List<Mem32Write>(); BinaryWriter bw = new BinaryWriter(Machine.Current.N64MemorySafe); StreamReader reader = new StreamReader(m_BootSnapStream); XDocument doc = XDocument.Load(reader, LoadOptions.None); XElement root = doc.Root; var results = GetSnapElements(root, cic, region); foreach (var result in results) { if (result.Name == "GPRRegSet") { regs.Add( new GprRegWrite { index = Int32.Parse(result.Attribute("Index").Value), value = UInt64.Parse(HexFix(result.Value), NumberStyles.AllowHexSpecifier) }); } if (result.Name == "Mem32") { mem32.Add( new Mem32Write { index = Int32.Parse(result.Attribute("Index").Value), position = Int64.Parse(HexFix(result.Attribute("Offset").Value), NumberStyles.AllowHexSpecifier), value = UInt32.Parse(HexFix(result.Value), NumberStyles.AllowHexSpecifier), }); } } /* Now we do the actual writes to the emulator */ foreach (var reg in regs) { Machine.Current.DeviceCPU.State.WriteGPRUnsigned(reg.index, reg.value); } foreach (var m in mem32) { bw.BaseStream.Position = m.position + (4 * m.index); bw.Write(m.value); } }
public void LoadBootSnap(CICKeyType cic, RegionType region) { List <GprRegWrite> regs = new List <GprRegWrite>(); List <Mem32Write> mem32 = new List <Mem32Write>(); BinaryWriter bw = new BinaryWriter(Machine.Current.Memory); StreamReader reader = new StreamReader(m_BootSnapStream); XDocument doc = XDocument.Load(reader, LoadOptions.None); XElement root = doc.Root; var results = GetSnapElements(root, cic, region); foreach (var result in results) { if (result.Name == "GPRRegSet") { regs.Add( new GprRegWrite { index = Int32.Parse(result.Attribute("Index").Value), value = UInt64.Parse(HexFix(result.Value), NumberStyles.AllowHexSpecifier) }); } if (result.Name == "Mem32") { mem32.Add( new Mem32Write { index = Int32.Parse(result.Attribute("Index").Value), position = Int64.Parse(HexFix(result.Attribute("Offset").Value), NumberStyles.AllowHexSpecifier), value = UInt32.Parse(HexFix(result.Value), NumberStyles.AllowHexSpecifier), }); } } /* Now we do the actual writes to the emulator */ foreach (var reg in regs) { Machine.Current.DeviceCPU.State.WriteGPRUnsigned(reg.index, reg.value); } foreach (var m in mem32) { bw.BaseStream.Position = m.position + (4 * m.index); bw.Write(m.value); } }
public static Int32 Seed(this CICKeyType cic) { switch (cic) { default: return(0); case CICKeyType.CIC_X101: case CICKeyType.CIC_X102: return(0x3F); case CICKeyType.CIC_X103: return(0x78); case CICKeyType.CIC_X105: return(0x91); case CICKeyType.CIC_X106: return(0x85); } }
private void ComputeCICType() { Byte[] bootcodeBuffer = new Byte[Size]; using (MemoryStream ms = new MemoryStream(bootcodeBuffer)) { CopyCode(ms); } Crc32HashAlgorithm alg = new Crc32HashAlgorithm(); alg.Initialize(); alg.ComputeHash(bootcodeBuffer); switch (alg.CrcValue) { case 0x6170A4A1: m_CICType = CICKeyType.CIC_X101; break; case 0x90BB6CB5: m_CICType = CICKeyType.CIC_X102; break; case 0x0B050EE0: m_CICType = CICKeyType.CIC_X103; break; case 0x98BC2C86: m_CICType = CICKeyType.CIC_X105; break; case 0xACC8580A: m_CICType = CICKeyType.CIC_X106; break; default: m_CICType = CICKeyType.Unknown; break; } m_BootChecksum = alg.CrcValue; #if DEBUG /* For future of converting the bootcode hashcodes to MD5 */ MD5 md5 = MD5.Create(); md5.Initialize(); md5.ComputeHash(bootcodeBuffer); StringBuilder sb = new StringBuilder(); foreach (Byte b in md5.Hash) { sb.AppendFormat("{0:X2}", b); } Debug.WriteLine(String.Format("MD5 Checksum for CIC Type ({0}): {1}", m_CICType, sb.ToString())); #endif }
public static String GetGoodName(this CICKeyType type) { switch (type) { case CICKeyType.CIC_HLE: return("HLE CIC"); case CICKeyType.CIC_X101: return("CIC-X101"); case CICKeyType.CIC_X102: return("CIC-X102"); case CICKeyType.CIC_X103: return("CIC-X103"); case CICKeyType.CIC_X105: return("CIC-X105"); case CICKeyType.CIC_X106: return("CIC-X106"); default: return(type.ToString()); } }
public RomChecksum(CICKeyType type) { m_CicType = type; }
private Boolean CompareCic(String cicName, CICKeyType cic) { return cic.ToString().Contains(cicName); }
private IEnumerable<XElement> GetSnapElements(XElement snap, CICKeyType cic, RegionType region) { var condition = snap.Attribute("Condition"); var value = snap.Attribute("Value"); Boolean valid = false; if (condition != null) { switch (condition.Value) { case "CIC": valid = CompareCic(value.Value, cic); break; case "Region": valid = CompareRegion(value.Value, region); break; default: break; } if (!valid) return Enumerable.Empty<XElement>(); } List<XElement> writes = new List<XElement>(); writes.AddRange(snap.Elements("GPRRegSet")); writes.AddRange(snap.Elements("Mem32")); writes.AddRange(snap.Elements("BootSnap").SelectMany(s => GetSnapElements(s, cic, region))); return writes; }
private void AssertPIFCodes(RegionType region, CICKeyType cic, ExecutionState state) { Assert.Equal(0x00000000A4000040L, state.PC); Assert.Equal(0x0000000000000000UL, state.GPRRegs[0]); Assert.Equal(0xFFFFFFFFA4001F0CUL, state.GPRRegs[6]); Assert.Equal(0xFFFFFFFFA4001F08UL, state.GPRRegs[7]); Assert.Equal(0x00000000000000C0UL, state.GPRRegs[8]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[9]); Assert.Equal(0x0000000000000040UL, state.GPRRegs[10]); Assert.Equal(0xFFFFFFFFA4000040UL, state.GPRRegs[11]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[16]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[17]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[18]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[19]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[21]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[26]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[27]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[28]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[28]); Assert.Equal(0xFFFFFFFFA4001FF0UL, state.GPRRegs[29]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[30]); switch (Cartridge.Current.RomImage.Region) { case RegionType.MPAL: case RegionType.PAL: { switch (Cartridge.Current.RomImage.BootRomInformation.CIC) { default: case CICKeyType.Unknown: case CICKeyType.CIC_X102: { Assert.Equal(0xFFFFFFFFC0F1D859UL, state.GPRRegs[5]); Assert.Equal(0x000000002DE108EAUL, state.GPRRegs[14]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[24]); break; } case CICKeyType.CIC_X101: { break; } case CICKeyType.CIC_X103: { Assert.Equal(0xFFFFFFFFD4646273UL, state.GPRRegs[5]); Assert.Equal(0x000000001AF99984UL, state.GPRRegs[14]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[24]); break; } case CICKeyType.CIC_X105: { Assert.Equal(0xFFFFFFFFDECAAAD1UL, state.GPRRegs[5]); Assert.Equal(0x000000000CF85C13UL, state.GPRRegs[14]); Assert.Equal(0x0000000000000002UL, state.GPRRegs[24]); AssertEqualMemoryReadU32(0xA4001004, 0xBDA807FC); break; } case CICKeyType.CIC_X106: { Assert.Equal(0xFFFFFFFFB04DC903UL, state.GPRRegs[5]); Assert.Equal(0x000000001AF99984UL, state.GPRRegs[14]); Assert.Equal(0x0000000000000002UL, state.GPRRegs[24]); break; } } Assert.Equal(0x0000000000000000UL, state.GPRRegs[20]); Assert.Equal(0x0000000000000006UL, state.GPRRegs[23]); Assert.Equal(0xFFFFFFFFA4001554UL, state.GPRRegs[31]); break; } default: case RegionType.Unknown: case RegionType.NTSC: { switch (Cartridge.Current.RomImage.BootRomInformation.CIC) { default: case CICKeyType.Unknown: case CICKeyType.CIC_X102: { Assert.Equal(0xFFFFFFFFC95973D5UL, state.GPRRegs[5]); Assert.Equal(0x000000002449A366UL, state.GPRRegs[14]); break; } case CICKeyType.CIC_X101: { Assert.Equal(0x000000000000003FUL, state.GPRRegs[22]); break; } case CICKeyType.CIC_X103: { Assert.Equal(0xFFFFFFFF95315A28UL, state.GPRRegs[5]); Assert.Equal(0x000000005BACA1DFUL, state.GPRRegs[14]); break; } case CICKeyType.CIC_X105: { AssertEqualMemoryReadU32(0xA4001004, 0x8DA807FC); Assert.Equal(0x000000005493FB9AUL, state.GPRRegs[5]); Assert.Equal(0xFFFFFFFFC2C20384UL, state.GPRRegs[14]); break; } case CICKeyType.CIC_X106: { Assert.Equal(0xFFFFFFFFE067221FUL, state.GPRRegs[5]); Assert.Equal(0x000000005CD2B70FUL, state.GPRRegs[14]); break; } } Assert.Equal(0x0000000000000001UL, state.GPRRegs[20]); Assert.Equal(0x0000000000000000UL, state.GPRRegs[23]); Assert.Equal(0x0000000000000003UL, state.GPRRegs[24]); Assert.Equal(0xFFFFFFFFA4001550UL, state.GPRRegs[31]); break; } } switch (cic) { case CICKeyType.CIC_X101: { Assert.Equal(0x000000000000003FUL, state.GPRRegs[22]); break; } case CICKeyType.Unknown: default: case CICKeyType.CIC_X102: { Assert.Equal(0x0000000000000001UL, state.GPRRegs[1]); Assert.Equal(0x000000000EBDA536UL, state.GPRRegs[2]); Assert.Equal(0x000000000EBDA536UL, state.GPRRegs[3]); Assert.Equal(0x000000000000A536UL, state.GPRRegs[4]); Assert.Equal(0xFFFFFFFFED10D0B3UL, state.GPRRegs[12]); Assert.Equal(0x000000001402A4CCUL, state.GPRRegs[13]); Assert.Equal(0x000000003103E121UL, state.GPRRegs[15]); Assert.Equal(0x000000000000003FUL, state.GPRRegs[22]); Assert.Equal(0xFFFFFFFF9DEBB54FUL, state.GPRRegs[25]); break; } case CICKeyType.CIC_X103: { Assert.Equal(0x0000000000000001UL, state.GPRRegs[1]); Assert.Equal(0x0000000049A5EE96UL, state.GPRRegs[2]); Assert.Equal(0x0000000049A5EE96UL, state.GPRRegs[3]); Assert.Equal(0x000000000000EE96UL, state.GPRRegs[4]); Assert.Equal(0xFFFFFFFFCE9DFBF7UL, state.GPRRegs[12]); Assert.Equal(0xFFFFFFFFCE9DFBF7UL, state.GPRRegs[13]); Assert.Equal(0x0000000018B63D28UL, state.GPRRegs[15]); Assert.Equal(0x0000000000000078UL, state.GPRRegs[22]); Assert.Equal(0xFFFFFFFF825B21C9UL, state.GPRRegs[25]); break; } case CICKeyType.CIC_X105: { AssertEqualMemoryReadU32(0xA4001000, 0x3C0DBFC0); AssertEqualMemoryReadU32(0xA4001008, 0x25AD07C0); AssertEqualMemoryReadU32(0xA400100C, 0x31080080); AssertEqualMemoryReadU32(0xA4001010, 0x5500FFFC); AssertEqualMemoryReadU32(0xA4001014, 0x3C0DBFC0); AssertEqualMemoryReadU32(0xA4001018, 0x8DA80024); AssertEqualMemoryReadU32(0xA400101C, 0x3C0BB000); Assert.Equal(0x0000000000000000UL, state.GPRRegs[1]); Assert.Equal(0xFFFFFFFFF58B0FBFUL, state.GPRRegs[2]); Assert.Equal(0xFFFFFFFFF58B0FBFUL, state.GPRRegs[3]); Assert.Equal(0x0000000000000FBFUL, state.GPRRegs[4]); Assert.Equal(0xFFFFFFFF9651F81EUL, state.GPRRegs[12]); Assert.Equal(0x000000002D42AAC5UL, state.GPRRegs[13]); Assert.Equal(0x0000000056584D60UL, state.GPRRegs[15]); Assert.Equal(0x0000000000000091UL, state.GPRRegs[22]); Assert.Equal(0xFFFFFFFFCDCE565FUL, state.GPRRegs[25]); break; } case CICKeyType.CIC_X106: { Assert.Equal(0x0000000000000000UL, state.GPRRegs[1]); Assert.Equal(0xFFFFFFFFA95930A4UL, state.GPRRegs[2]); Assert.Equal(0xFFFFFFFFA95930A4UL, state.GPRRegs[3]); Assert.Equal(0x00000000000030A4UL, state.GPRRegs[4]); Assert.Equal(0xFFFFFFFFBCB59510UL, state.GPRRegs[12]); Assert.Equal(0xFFFFFFFFBCB59510UL, state.GPRRegs[13]); Assert.Equal(0x000000007A3C07F4UL, state.GPRRegs[15]); Assert.Equal(0x0000000000000085UL, state.GPRRegs[22]); Assert.Equal(0x00000000465E3F72UL, state.GPRRegs[25]); break; } } }
private Cartridge MockUpCartridge(RegionType region, CICKeyType cic) { var mockedCart = new Mock<Cartridge>(); var mockedCartRom = new Mock<ICartRom>(); var mockedBootRom = new Mock<IBootRom>(); GameSerial serial = new GameSerial(new Byte[] { 0x00, 00, 00, 00, 00, 00, 00, 00 }); MemoryStream stream = new MemoryStream(); for (Int32 i = 0; i < (1024 ^ 2); i++) stream.WriteByte(0); mockedBootRom.Setup<CICKeyType>(x => x.CIC).Returns(cic); mockedBootRom.Setup<Int32>(x => x.BootChecksum).Returns(0x00); mockedCartRom.Setup<PiBusSpeedConfig>(x => x.BusConfig).Returns(new PiBusSpeedConfig(0x80, 0x37, 0x12, 0x40)); mockedCartRom.Setup<String>(x => x.Name).Returns("MockedCartridge"); mockedCartRom.Setup<Int32>(x => x.Clockrate).Returns(60); mockedCartRom.Setup<Int64>(x => x.EntryPoint).Returns(0x80000000); mockedCartRom.Setup<GameSerial>(x => x.Serial).Returns(serial); mockedCartRom.Setup<Int32>(x => x.CRC1).Returns(0x00); mockedCartRom.Setup<Int32>(x => x.CRC2).Returns(0x00); mockedCartRom.Setup<Boolean>(x => x.IsHeaderOnly).Returns(false); mockedCartRom.Setup<IBootRom>(x => x.BootRomInformation).Returns(mockedBootRom.Object); mockedCartRom.Setup<RegionType>(x => x.Region).Returns(region); mockedCartRom.Setup<Stream>(x => x.RomStream).Returns(stream); mockedCart.SetupProperty<Boolean>(c => c.IsOpened, true); mockedCart.Setup<Stream>(c => c.PiCartridgeStream).Returns(stream); mockedCart.Setup<ICartRom>(c => c.RomImage).Returns(mockedCartRom.Object); return mockedCart.Object; }
public static void SetupExecutionState(BootMode bootMode) { if (bootMode == BootMode.IPL_ROM) { throw new InvalidOperationException("Low-level IPL booting not supported yet"); //Machine.Current.RCP.State.PC = 0x1FC00000; /* TODO: * Schedule CPU and RCP threads to execute MIPS Interpreter * Have CPU sit idle, and RCP execute the PIF Rom * */ } else if (bootMode == BootMode.HLE_IPL) { if (Machine.Current.DeviceRCP.Interface_Parallel.InsertedCartridge != null) { /* Code taken from mupen64plus-core on github */ ExecutionState state = Machine.Current.DeviceCPU.State; state.PC = 0xA4000040; /* PI Setup */ var pi = Machine.Current.Memory.PI; PiBusSpeedConfig config = Cartridge.Current.RomImage.BusConfig; pi.Domain1Latency = config.DeviceLatency; pi.Domain1PageSize = config.PageSize; pi.Domain1PulseWidth = config.PulseWidth; pi.Domain1Release = config.ReleaseTime; pi.Status.DataShared = 0; /* TODO: sp_register.sp_status_reg = 1; * rsp_register.rsp_pc = 0; * * ai_register.ai_dram_addr = 0; * ai_register.ai_len = 0; * * vi_register.vi_v_intr = 1023; * vi_register.vi_current = 0; * vi_register.vi_h_start = 0; * * /* MI Setup */ var mi = Machine.Current.Memory.MI; mi.VersionReg.DataToMaster = 0x02020102; mi.VersionReg.DataToSlave &= ~(0x10U | 0x8U | 0x4U | 0x1U); PifHleCopyBootRom(); state.GPRRegs[19] = 0; /* 0: Cart, 1: DiskDrive */ state.GPRRegs[20] = (UInt64)((Int32)Cartridge.Current.RomImage.Region) - 1; state.GPRRegs[21] = 0; /* 0: ColdReset, 1: NMI */ state.GPRRegs[22] = (UInt64)Cartridge.Current.RomImage.BootRomInformation.CIC.Seed(); state.GPRRegs[23] = 0; /* S7: Unknown */ /* Required by CIC X105 */ BinaryWriter bw = new BinaryWriter(Machine.Current.Memory); bw.BaseStream.Position = 0x04001000; bw.Write(0x3c0dbfc0U); bw.Write(0x8da807fcU); bw.Write(0x25ad07c0U); bw.Write(0x31080080U); bw.Write(0x5500fffcU); bw.Write(0x3c0dbfc0U); bw.Write(0x8da80024U); bw.Write(0x3c0bb000U); /* Required by CIC X105 */ state.GPRRegs[11] = 0xffffffffa4000040UL; /* T3 */ state.GPRRegs[29] = 0xffffffffa4001ff0UL; /* SP */ state.GPRRegs[31] = 0xffffffffa4001550UL; /* RA */ } else { logger.Warn("No cartridge inserted, skipping IPL boot"); Machine.Current.DeviceCPU.State.PC = 0xBFC00000; } logger.Debug("ROM Entry Point: " + Machine.Current.DeviceCPU.State.PC.ToString("X8")); } else if (bootMode == BootMode.HLE_IPL_OLD) { if (Machine.Current.DeviceRCP.Interface_Parallel.InsertedCartridge != null) { /* This is the older method of booting the emulator */ Machine.Current.DeviceCPU.State.PC = 0xA4000040; /* This simulates the effects of the PIF Bootloader */ /* 1. Copy the game cartrdige boot rom into SP Memory * 2. Load a snapshot of the CPU / Memory state generated by the real PIF boot sequence */ PifHleCopyBootRom(); using (Stream stream = typeof(SoftBootManager).Assembly.GetManifestResourceStream("Soft64.BootStateSnapshots.xml")) { CartridgeInfo info = Cartridge.Current.GetCartridgeInfo(); CICKeyType cic = Cartridge.Current.RomImage.BootRomInformation.CIC; BootSnapReader bootsnap = new BootSnapReader(stream); bootsnap.LoadBootSnap(cic, info.RegionCode); } } else { logger.Warn("No cartridge inserted, skipping IPL boot"); Machine.Current.DeviceCPU.State.PC = 0xBFC00000; } logger.Debug("ROM Entry Point: " + Machine.Current.DeviceCPU.State.PC.ToString("X8")); } else { throw new ArgumentException("Unknown bootmode"); } }
private Boolean CompareCic(String cicName, CICKeyType cic) { return(cic.ToString().Contains(cicName)); }