Example #1
0
        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);
        }
Example #2
0
 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)
                                         ));
Example #3
0
        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));
        }
Example #4
0
        /// <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));
        }
Example #5
0
        /// <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));
        }
Example #6
0
        /// <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();
        }
Example #7
0
        /// <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();
        }
Example #8
0
        /// <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();
        }
Example #9
0
        /// <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();
        }
Example #10
0
            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);
Example #11
0
 /// <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);
Example #12
0
 /// <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);
Example #13
0
 /// <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));