Ejemplo n.º 1
0
        /// <summary>
        /// Loads an archive into a <see cref="VirtualFilesystemDirectory"/>, automatically de-compressing the archive if required.
        ///
        /// </summary>
        /// <param name="filePath">Filepath of file to (optionally) decompress and load.</param>
        /// <returns><see cref="VirtualFilesystemDirectory"/> containing the contents, or null if filepath is not a valid archive.</returns>
        public static VirtualFilesystemDirectory LoadArchive(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath", "Cannot load archive from empty file path!");
            }

            if (!File.Exists(filePath))
            {
                throw new ArgumentException("Cannot load archive from non-existant file!", "filePath");
            }

            MemoryStream decompressedFile = null;

            using (EndianBinaryReader fileReader = new EndianBinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Endian.Big))
            {
                // Read the first 4 bytes to see if it's a compressed file (Yaz0) or a plain RARC file.
                uint fileMagic = fileReader.ReadUInt32();
                fileReader.BaseStream.Position = 0L; // Reset to the start so that the next thing to read it is at the start like it expects.

                switch (fileMagic)
                {
                case 0x59617A30:     // Yaz0 Compression
                    decompressedFile = Yaz0.Decode(fileReader);
                    break;

                case 0x59617930:     // Yay0 Compression
                    decompressedFile = Yay0.Decode(fileReader);
                    break;

                case 0x52415243:     // RARC - Uncompressed
                    decompressedFile = new MemoryStream((int)fileReader.BaseStream.Length);
                    fileReader.BaseStream.CopyTo(decompressedFile);

                    // Copying modifies the decompressedFile's read head (places it at new location) so we rewind.
                    decompressedFile.Position = 0L;
                    break;

                default:
                    throw new NotImplementedException(string.Format("Unknown magic: {0}. If this is a Nintendo archive, open an Issue on GitHub!", fileMagic.ToString("X8")));
                }
            }

            // Not an archive we know how to handle.
            if (decompressedFile == null)
            {
                return(null);
            }

            // Decompress the archive into the folder. It'll generate a sub-folder with the Archive's ROOT name.
            Archive rarc = new Archive();

            using (EndianBinaryReader reader = new EndianBinaryReader(decompressedFile, Endian.Big))
            {
                return(rarc.ReadFile(reader));
            }
        }
Ejemplo n.º 2
0
        /// <summary>
        /// Loads a file into a <see cref="EndianBinaryReader"/>, automatically de-compressing the file if required.
        /// Throws an exception if the filepath to the file is not valid.
        /// </summary>
        /// <param name="filePath">Filepath of file to (optionally) decompress and load.</param>
        /// <returns><see cref="EndianBinaryReader"/> containing the contents.</returns>
        public static EndianBinaryReader LoadFile(string filePath)
        {
            if (string.IsNullOrEmpty(filePath))
            {
                throw new ArgumentNullException("filePath", "Cannot load archive from empty file path!");
            }

            if (!File.Exists(filePath))
            {
                throw new ArgumentException("Cannot load archive from non-existant file!", "filePath");
            }

            MemoryStream decompressedFile = null;

            using (EndianBinaryReader fileReader = new EndianBinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Endian.Big))
            {
                // Read the first 4 bytes to see if it's a compressed file (Yaz0, Yay0, etc.)
                uint fileMagic = fileReader.ReadUInt32();
                fileReader.BaseStream.Position = 0L; // Reset to the start so that the next thing to read it is at the start like it expects.

                switch (fileMagic)
                {
                case 0x59617A30:     // Yaz0 Compression
                    decompressedFile = Yaz0.Decode(fileReader);
                    break;

                case 0x59617930:     // Yay0 Compression
                    decompressedFile = Yay0.Decode(fileReader);
                    break;

                default:     // Uncompressed
                    decompressedFile = new MemoryStream((int)fileReader.BaseStream.Length);
                    fileReader.BaseStream.CopyTo(decompressedFile);

                    // CopyTo modifies the decompressedFile's read head (places it at new location) so we rewind.
                    decompressedFile.Position = 0L;
                    break;
                }
            }

            // Return the decompressed file
            return(new EndianBinaryReader(decompressedFile, Endian.Big));
        }
Ejemplo n.º 3
0
        static void Test(byte[] bytes, Method method)
        {
            var bytes2 = new byte[bytes.Length];

            switch (method)
            {
            case Method.RLE:
                bytes2 = RLE.Decompress(new MemoryStream(RLE.Compress(new MemoryStream(bytes))), bytes.Length);
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.Yaz0:
                bytes2 = Yaz0.Decompress(new MemoryStream(Yaz0.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;

            case Method.Yay0:
                bytes2 = Yay0.Decompress(new MemoryStream(Yay0.Compress(new MemoryStream(bytes))));
                Assert.IsTrue(bytes.SequenceEqual(bytes2));
                break;
            }
        }
Ejemplo n.º 4
0
        public static void Compress(object sender, EventArgs e)
        {
            var tsi = sender as ToolStripMenuItem;

            if (!Shared.PrepareFiles("Open a decompressed " + tsi?.Tag + "file...", "Save your compressed file...", ".decomp", out var openFile, out var saveFile, true))
            {
                return;
            }

            try
            {
                using (openFile)
                    using (var outFs = new BinaryWriterX(saveFile))
                        switch (tsi?.Tag)
                        {
                        case Compression.L5LZ10:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.LZ10));
                            break;

                        case Compression.L5Huff4:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.Huffman4Bit));
                            break;

                        case Compression.L5Huff8:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.Huffman8Bit));
                            break;

                        case Compression.L5RLE:
                            outFs.Write(Level5.Compress(openFile, Level5.Method.RLE));
                            break;

                        case Compression.NLZ10:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ10));
                            break;

                        case Compression.NLZ11:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ11));
                            break;

                        case Compression.NLZ60:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.LZ60));
                            break;

                        case Compression.NHuff4:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.Huff4));
                            break;

                        case Compression.NHuff8:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.Huff8));
                            break;

                        case Compression.NRLE:
                            outFs.Write(Nintendo.Compress(openFile, Nintendo.Method.RLE));
                            break;

                        case Compression.LZ77:
                            outFs.Write(LZ77.Compress(openFile));
                            break;

                        case Compression.RevLZ77:
                            outFs.Write(RevLZ77.Compress(openFile));
                            break;

                        case Compression.LZOvl:
                            outFs.Write(LZOvl.Compress(openFile));
                            break;

                        case Compression.LZ4:
                            outFs.Write(Kontract.Compression.LZ4.Compress(openFile));
                            break;

                        case Compression.MIO0LE:
                            outFs.Write(MIO0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.MIO0BE:
                            outFs.Write(MIO0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yay0LE:
                            outFs.Write(Yay0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yay0BE:
                            outFs.Write(Yay0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yaz0LE:
                            outFs.Write(Yaz0.Compress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yaz0BE:
                            outFs.Write(Yaz0.Compress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.GZip:
                            outFs.Write(GZip.Compress(openFile));
                            break;

                        case Compression.ZLib:
                            outFs.Write(ZLib.Compress(openFile));
                            break;

                        case Compression.PSVSpikeChun:
                            outFs.Write(PSVSpikeChun.Compress(openFile));
                            break;
                        }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show($"Successfully compressed {Path.GetFileName(openFile.Name)}.", tsi.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
Ejemplo n.º 5
0
        public static void Decompress(object sender, EventArgs e)
        {
            var tsi = sender as ToolStripMenuItem;

            if (!Shared.PrepareFiles("Open a " + tsi?.Tag + " compressed file...", "Save your decompressed file...", ".decomp", out var openFile, out var saveFile))
            {
                return;
            }

            try
            {
                using (openFile)
                    using (var outFs = new BinaryWriterX(saveFile))
                        switch (tsi?.Tag)
                        {
                        case Compression.Level5:
                            outFs.Write(Level5.Decompress(openFile));
                            break;

                        case Compression.Nintendo:
                            outFs.Write(Nintendo.Decompress(openFile));
                            break;

                        case Compression.LZ77:
                            outFs.Write(LZ77.Decompress(openFile));
                            break;

                        case Compression.RevLZ77:
                            outFs.Write(RevLZ77.Decompress(openFile));
                            break;

                        case Compression.LZOvl:
                            outFs.Write(LZOvl.Decompress(openFile));
                            break;

                        case Compression.LZ4:
                            outFs.Write(Kontract.Compression.LZ4.Decompress(openFile));
                            break;

                        case Compression.MIO0LE:
                            outFs.Write(MIO0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.MIO0BE:
                            outFs.Write(MIO0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yay0LE:
                            outFs.Write(Yay0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yay0BE:
                            outFs.Write(Yay0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.Yaz0LE:
                            outFs.Write(Yaz0.Decompress(openFile, ByteOrder.LittleEndian));
                            break;

                        case Compression.Yaz0BE:
                            outFs.Write(Yaz0.Decompress(openFile, ByteOrder.BigEndian));
                            break;

                        case Compression.LZECD:
                            outFs.Write(LZECD.Decompress(openFile));
                            break;

                        case Compression.LZ10VLE:
                            outFs.Write(LZSSVLE.Decompress(openFile));
                            break;

                        case Compression.GZip:
                            outFs.Write(GZip.Decompress(openFile));
                            break;

                        case Compression.ZLib:
                            outFs.Write(ZLib.Decompress(openFile));
                            break;

                        case Compression.PSVSpikeChun:
                            outFs.Write(PSVSpikeChun.Decompress(openFile));
                            break;
                        }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.ToString(), tsi?.Text, MessageBoxButtons.OK, MessageBoxIcon.Error);
                return;
            }

            MessageBox.Show($"Successfully decompressed {Path.GetFileName(openFile.Name)}.", tsi.Text, MessageBoxButtons.OK, MessageBoxIcon.Information);
        }
Ejemplo n.º 6
0
        public static VirtDirectory LoadRarc(byte[] data)
        {
            if (Yay0.IsCompressed(data))
            {
                data = Yay0.Decompress(data);
            }

            DhBinaryReader br = new DhBinaryReader(data, DhEndian.Big);

            if (br.ReadStr(4) != "RARC")
            {
                throw new InvalidDataException("No valid RARC signature was found!");
            }

            List <RarcNode>  nodes   = new List <RarcNode>();
            List <RarcEntry> entries = new List <RarcEntry>();

            // read header
            // RARC here
            br.Skip(4);
            br.Skip(4);
            var dataOffset = br.ReadU32() + 0x20;

            br.Skip(4);
            br.Skip(4);
            br.Skip(4);
            br.Skip(4);

            // read infoblock
            var NodeCount   = br.ReadU32();
            var NodeOffset  = br.ReadU32() + 0x20;
            var EntryCount  = br.ReadU32();
            var EntryOffset = br.ReadU32() + 0x20;

            br.Skip(4);
            var StringTableOffset = br.ReadU32() + 0x20;

            br.Skip(2);
            br.Skip(2);
            br.Skip(4);

            br.Goto(EntryOffset);

            // read entries
            for (int i = 0; i < EntryCount; i++)
            {
                RarcEntry entry = new RarcEntry()
                {
                    Id         = br.ReadU16(),
                    NameHash   = br.ReadU16(),
                    Type       = br.ReadU16(),
                    NameOffset = br.ReadU16(),
                    DataOffset = br.ReadU32(),
                    DataLength = br.ReadU32()
                };

                if (entry.Type == 0x1100)
                {
                    entry.Data = br.ReadAt(dataOffset + entry.DataOffset, (int)entry.DataLength);
                }
                entry.MemoryPointer = br.ReadU32();
                entry.Name          = br.ReadStrAt(StringTableOffset + entry.NameOffset);

                entries.Add(entry);
            }

            br.Goto(NodeOffset);

            // read nodes
            for (int i = 0; i < NodeCount; i++)
            {
                RarcNode rarcNode = new RarcNode()
                {
                    Id              = br.ReadStr(4),
                    NameOffset      = br.ReadU32(),
                    NameHash        = br.ReadU16(),
                    EntryCount      = br.ReadU16(),
                    FirstEntryIndex = br.ReadU32()
                };

                rarcNode.Name    = br.ReadStrAt(StringTableOffset + rarcNode.NameOffset);
                rarcNode.Entries = entries.GetRange((int)rarcNode.FirstEntryIndex, (int)rarcNode.EntryCount);

                nodes.Add(rarcNode);
            }

            List <VirtDirectory> virtDirectories = new List <VirtDirectory>(nodes.Count);

            foreach (RarcNode rarcNode in nodes)
            {
                virtDirectories.Add(new VirtDirectory(rarcNode.Name, Guid.Empty));
            }

            for (int i = 0; i < nodes.Count; i++)
            {
                RarcNode rarcNode = nodes[i];

                for (int y = 0; y < nodes[i].Entries.Count; y++)
                {
                    if (rarcNode.Entries[y].Name == "." || rarcNode.Entries[y].Name == "..")
                    {
                        continue;
                    }

                    if (rarcNode.Entries[y].Type == (ushort)NodeType.Directory)
                    {
                        var virtDirectory = virtDirectories[(int)rarcNode.Entries[y].DataOffset];
                        virtDirectory.ParentGuid = virtDirectories[i].Guid;
                        virtDirectory.Name       = rarcNode.Entries[y].Name;

                        virtDirectories[i].Children.Add(virtDirectory);
                    }
                    else
                    {
                        VirtFile virtFile = new VirtFile(rarcNode.Entries[y].Name, virtDirectories[i].Guid, rarcNode.Entries[y].Data);
                        virtDirectories[i].Children.Add(virtFile);
                    }
                }
            }

            return(virtDirectories.Count > 0 ? virtDirectories[0] : null);
        }
Ejemplo n.º 7
0
        private static void ExtractArchive(string outputFolder, string filePath)
        {
            if (!File.Exists(filePath))
            {
                Console.WriteLine("Warning: Tried to extract archive from filePath \"{0}\" but not a file!", filePath);
                return;
            }

            if (m_verboseOutput)
            {
                Console.Write("Extracting archive {0}... ", Path.GetFileName(filePath));
            }

            try
            {
                MemoryStream decompressedFile = null;
                using (EndianBinaryReader fileReader = new EndianBinaryReader(File.Open(filePath, FileMode.Open, FileAccess.Read, FileShare.ReadWrite), Endian.Big))
                {
                    // Read the first 4 bytes to see if it's a compressed file (Yaz0) or a plain RARC file.
                    uint fileMagic = fileReader.ReadUInt32();
                    fileReader.BaseStream.Position = 0L; // Reset to the start so that the next thing to read it is at the start like it expects.

                    if (fileMagic == 0x59617A30)         // Yaz0
                    {
                        if (m_verboseOutput)
                        {
                            Console.Write("Archive compressed with Yaz0, decompressing... ");
                        }

                        decompressedFile = Yaz0.Decode(fileReader);
                    }
                    if (fileMagic == 0x59617930) // Yay0
                    {
                        if (m_verboseOutput)
                        {
                            Console.Write("Archive compressed with Yay0, decompressing... ");
                        }

                        decompressedFile = Yay0.Decode(fileReader);
                    }
                    else if (fileMagic == 0x52415243) // RARC
                    {
                        // Copy the fileReader stream to a new memorystream.
                        decompressedFile = new MemoryStream((int)fileReader.BaseStream.Length);
                        fileReader.BaseStream.CopyTo(decompressedFile);
                        decompressedFile.Position = 0L;
                    }
                }

                if (decompressedFile == null)
                {
                    if (m_verboseOutput)
                    {
                        Console.WriteLine("Skipping archive, not a Yaz0 or RARC file.");
                    }
                    return;
                }

                // Decompress the archive into the folder. It'll generate a sub-folder with the Archive's ROOT name.
                Archive rarc = new Archive();
                using (EndianBinaryReader reader = new EndianBinaryReader(decompressedFile, Endian.Big))
                {
                    VirtualFilesystemDirectory root = rarc.ReadFile(reader);
                    if (m_printFS)
                    {
                        PrintFileSystem(root);
                    }

                    // Many archives use the same internal root name, which causes a conflict when they export.
                    // To solve this, we use the file name of the file as the root name, instead of the internal
                    // name.
                    if (!m_useInternalNames)
                    {
                        root.Name = Path.GetFileNameWithoutExtension(filePath);
                    }

                    // Write it to disk.
                    root.ExportToDisk(outputFolder);
                }

                if (m_verboseOutput)
                {
                    Console.WriteLine("Completed.");
                }
            }
            catch (Exception ex)
            {
                Console.WriteLine("Caught Exception: " + ex.ToString());
                m_wasError = true;
            }
        }