private static async ValueTask <EInputBlockResult> VerifyRomCRCAsync(IRomData romData) { Console.WriteLine("Disassembling ROM."); Console.WriteLine(); var data = await romData.GetDataAsync(); switch (Crc.HasCorrectCrc(data.Span, out var crc)) { case false: Console.WriteLine("ROM has invalid CRC values."); Console.WriteLine($"Expected CRC1: 0x{crc.Crc1:X8}, Actual CRC1: 0x{romData.Header.Crc1:X8}"); Console.WriteLine($"Expected CRC2: 0x{crc.Crc1:X8}, Actual CRC2: 0x{romData.Header.Crc2:X8}"); break; case true: Console.WriteLine("CRC OK."); break; case null: default: Console.WriteLine("Unable to calculate CRC - unknown boot code."); break; } return(EInputBlockResult.Success); }
private static async ValueTask <EInputBlockResult> ChangeFormatAsync(IRomData romData) { return(await RequestInputBlockAsync("Enter the number of the format to convert to.", (".z64 (Big Endian)", () => ConvertAsync(romData, ERomFormat.BigEndian)), (".v64 (Byte Swapped)", () => ConvertAsync(romData, ERomFormat.ByteSwapped)), (".n64 (Little Endian)", () => ConvertAsync(romData, ERomFormat.LittleEndian)), ("Back", BackTask) ));
private static ValueTask <EInputBlockResult> DisassembleRomAsync(IRomData romData) { Console.WriteLine("Disassembling ROM."); Console.WriteLine(); Console.WriteLine("HEADER"); var romBuild = romData.GetRomBuild(); Console.WriteLine($"{romData.Header.Title}"); Console.WriteLine($"Build: {romBuild.Version} ({romBuild.BuildNumber})"); Console.WriteLine($"Size: {romData.Size.Size.Mebibits}Mib (0x{romData.Length:X})"); Console.WriteLine($"Destination Code: {romData.Header.DestinationCode}"); Console.WriteLine($"Game Code: {romData.Header.GameCode}"); Console.WriteLine($"Format: {romData.Header.Format}"); Console.WriteLine($"Mask Rom Version: {romData.Header.Version}"); Console.WriteLine($"Entry Address: 0x{romData.Header.EntryAddress:X}"); Console.WriteLine($"Return Address: 0x{romData.Header.ReturnAddress:X}"); Console.WriteLine(); using var decompressedRomData = romData.Decompress(); var disassembler = new Disassembler(); var options = new DisassemblerOptions { OutputDir = new DirectoryInfo(@"C:\Users\shira\Desktop\OoTDecomp"), SplitFiles = false, KnownFiles = { new FileEntry("INTERNAL_HEADER", 0xA4000000, romData.GetHeaderData()), new FileEntry("IPL3", 0xA4000040, romData.GetIPL3Data()), // We don't know what this is, but we can figure this out // when we start disassembling correctly and getting a bunch of opcode errors. // For reference, we know that Mario ends at 0x0B6A40. We'll go a bit higher then // work our way down. new FileEntry("CODE", romData.Header.EntryAddress, decompressedRomData.GetCodeData(0x0C3500)) }, Regions = { new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F) }, KnownFunctions = { { 0x80000400, "Main" } } }; //disassembler.AddRegion(new DataRegion("INTERNAL_HEADER", 0xA4000000, 0xA400003F)); Console.WriteLine(); if (!PerformChecklistOperation("Disassembling ROM to MIPS.", () => disassembler.Disassemble(options), r => r.Exception)) { return(new ValueTask <EInputBlockResult>(EInputBlockResult.Failed)); } return(new ValueTask <EInputBlockResult>(EInputBlockResult.Success)); }
/// <summary> /// Converts the content in <paramref name="data"/> to the format /// specified in <paramref name="format"/>. /// </summary> /// <remarks> /// This method will make a copy of the data even if the format is not /// changed. /// </remarks> /// <param name="data">The data to convert to.</param> /// <param name="format">The format to convert.</param> public static IRomData ConvertTo(this IRomData data, ERomFormat format) { Guard.IsNotNull(data, nameof(data)); byte[] copy = new byte[data.Length]; data.GetData().CopyTo(copy); ConvertTo(format, copy); return(RomData.LoadRom(copy)); }
/// <summary> /// Converts the content in <paramref name="data"/> to the format /// specified in <paramref name="format"/>. /// </summary> /// <remarks> /// This method will make a copy of the data even if the format is not /// changed. /// </remarks> /// <param name="data">The data to convert to.</param> /// <param name="format">The format to convert.</param> /// <param name="cancellationToken">The cancellation token.</param> public static async ValueTask <IRomData> ConvertToAsync(this IRomData data, ERomFormat format, CancellationToken cancellationToken = default) { Guard.IsNotNull(data, nameof(data)); byte[] copy = new byte[data.Length]; var src = await data.GetDataAsync(); src.CopyTo(copy); ConvertTo(format, copy); return(await RomData.LoadRomAsync(copy, cancellationToken)); }
/// <summary> /// Saves <paramref name="romData"/> to disk. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="file">The output file.</param> public static void Save(this IRomData romData, FileInfo file) { Guard.IsNotNull(romData, nameof(romData)); Guard.IsNotNull(file, nameof(file)); if (file.Directory?.Exists == false) { file.Directory.Create(); } using var fs = file.Open(FileMode.Create, FileAccess.Write, FileShare.None); fs.Write(romData.GetData().Span); fs.Flush(); }
/// <summary> /// Saves <paramref name="romData"/> to disk, using the metadata of the ROM /// to generate the output file name. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="outputDirectory">The output directory.</param> public static void Save(this IRomData romData, DirectoryInfo outputDirectory) { Guard.IsNotNull(romData, nameof(romData)); Guard.IsNotNull(outputDirectory, nameof(outputDirectory)); if (!outputDirectory.Exists) { outputDirectory.Create(); } string fileName = romData.GetFilename(); var file = new FileInfo(Path.Combine(outputDirectory.FullName, fileName)); using var fs = file.Open(FileMode.Create, FileAccess.Write, FileShare.None); fs.Write(romData.GetData().Span); fs.Flush(); }
/// <summary> /// Saves <paramref name="romData"/> to disk. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="file">The output file.</param> /// <param name="cancellationToken">The cancellation token.</param> public static async Task SaveAsync(this IRomData romData, FileInfo file, CancellationToken cancellationToken = default) { Guard.IsNotNull(romData, nameof(romData)); Guard.IsNotNull(file, nameof(file)); cancellationToken.ThrowIfCancellationRequested(); if (file.Directory?.Exists == false) { file.Directory.Create(); } using var fs = file.Open(FileMode.Create, FileAccess.Write, FileShare.None); await fs.WriteAsync(await romData.GetDataAsync(), cancellationToken); await fs.FlushAsync(); }
/// <summary> /// Saves <paramref name="romData"/> to disk, using the metadata of the ROM /// to generate the output file name. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="outputDirectory">The output directory.</param> /// <param name="cancellationToken">The cancellation token.</param> public static async Task SaveAsync(this IRomData romData, DirectoryInfo outputDirectory, CancellationToken cancellationToken) { Guard.IsNotNull(romData, nameof(romData)); Guard.IsNotNull(outputDirectory, nameof(outputDirectory)); cancellationToken.ThrowIfCancellationRequested(); if (!outputDirectory.Exists) { outputDirectory.Create(); } string fileName = romData.GetFilename(); var file = new FileInfo(Path.Combine(outputDirectory.FullName, fileName)); using var fs = file.Open(FileMode.Create, FileAccess.Write, FileShare.None); await fs.WriteAsync(await romData.GetDataAsync(), cancellationToken); await fs.FlushAsync(); }
static async ValueTask <EInputBlockResult> ConvertAsync(IRomData data, ERomFormat format) { FileInfo output; EraseLine(); if (data.Header.Format == format) { Console.WriteLine(); Console.WriteLine("The ROM data is already in the correct format."); if (data is not RomFile) { output = new FileInfo(data.GetFilename()); await data.SaveAsync(output); Console.WriteLine($"File saved to {output.FullName}"); } // If it is a RomFile, the file already exists. Do nothing. return(EInputBlockResult.Success); } output = data is RomFile rf ? rf.File.WithExtension(RomHeader.GetFormatExtension(format)) : new FileInfo(data.GetFilename()); var converted = await data.ConvertToAsync(format); if (await PromptOverwriteIfExistsAsync(output) != EInputBlockResult.Success) { return(EInputBlockResult.Failed); } await converted.SaveAsync(output); Console.WriteLine($"File saved to {output.FullName}"); return(EInputBlockResult.Success);
/// <summary> /// Makes a copy of <paramref name="data"/>. /// </summary> /// <param name="data">The data to copy.</param> public static IRomData Copy(this IRomData data) => ConvertTo(data, data.Header !.Format);
/// <summary> /// Saves <paramref name="romData"/> to disk. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="path">The output file path.</param> /// <param name="cancellationToken">The cancellation token.</param> public static Task SaveAsync(this IRomData romData, string path, CancellationToken cancellationToken = default) => SaveAsync(romData, new FileInfo(path), cancellationToken);
/// <summary> /// Saves <paramref name="romData"/> to disk. /// </summary> /// <param name="romData">The data to save.</param> /// <param name="path">The output file path.</param> public static void Save(this IRomData romData, string path) => Save(romData, new FileInfo(path));