Esempio n. 1
0
            public Z64File ToFile(Z64Game game)
            {
                if (!Valid())
                {
                    return(new Z64File(null, -1, -1, -1, false));
                }

                if (!Exist())
                {
                    return(Z64File.DeletedFile(VRomStart, RomStart, VRomEnd - VRomStart));
                }

                int len = GetSize();

                byte[] data = new byte[len];
                Buffer.BlockCopy(game.Rom.RawRom, RomStart, data, 0, len);

                int romEnd = RomStart + data.Length;

                if (Compressed())
                {
                    data = Yaz0.Decompress(data);
                }

                return(new Z64File(data, VRomStart, RomStart, romEnd, Compressed()));
            }
Esempio n. 2
0
        /// <summary>
        /// Returns a reference to a decompressed file
        /// </summary>
        /// <param name="record">The DMA address used to reference the file</param>
        /// <returns></returns>
        protected RomFile GetFile(FileRecord record)
        {
            MemoryStream ms;

            byte[] data;
            byte[] decompressedData;

            if (record.VirtualAddress == CachedFileAddress)
            {
                ms = new MemoryStream(CachedFile);
                return(new RomFile(record, ms, Version));
            }

            using (FileStream fs = new FileStream(RomLocation, FileMode.Open, FileAccess.Read))
            {
                data        = new byte[record.DataAddress.Size];
                fs.Position = record.DataAddress.Start;
                fs.Read(data, 0, (int)record.DataAddress.Size);

                if (record.IsCompressed)
                {
                    ms = new MemoryStream(data);
                    decompressedData = Yaz0.Decode(ms, (int)(record.DataAddress.Size));
                }
                else
                {
                    decompressedData = data;
                }
            }
            CachedFile        = decompressedData;
            ms                = new MemoryStream(decompressedData);
            CachedFileAddress = record.VirtualAddress;
            return(new RomFile(record, ms, Version));
        }
Esempio n. 3
0
        public void Load(string filename)
        {
            FileInfo = new FileInfo(filename);

            using (var br = new BinaryReaderX(FileInfo.OpenRead()))
            {
                _sarc = new SARC(new MemoryStream(Yaz0.Decompress(new MemoryStream(br.ReadBytes((int)FileInfo.Length)), ByteOrder.BigEndian)));
            }
        }
Esempio n. 4
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));
            }
        }
Esempio n. 5
0
        private static Tuple <Stream, string> CompressFileFormat(ICompressionFormat compressionFormat, Stream data, bool FileIsCompressed, int Alignment,
                                                                 string FileName, bool EnableDialog = true)
        {
            string extension = Path.GetExtension(FileName);

            if (extension == ".szs" || extension == ".sbfres")
            {
                FileIsCompressed  = true;
                compressionFormat = new Yaz0();
            }

            if (compressionFormat == null)
            {
                return(Tuple.Create(data, ""));
            }

            bool CompressFile = false;

            if (EnableDialog && FileIsCompressed)
            {
                if (Runtime.AlwaysCompressOnSave)
                {
                    CompressFile = true;
                }
                else
                {
                    DialogResult save = MessageBox.Show($"Compress file with {compressionFormat}?", "File Save", MessageBoxButtons.YesNo);
                    CompressFile = (save == DialogResult.Yes);
                }
            }
            else if (FileIsCompressed)
            {
                CompressFile = true;
            }

            Console.WriteLine($"FileIsCompressed {FileIsCompressed} CompressFile {CompressFile} CompressionType {compressionFormat}");

            if (CompressFile)
            {
                if (compressionFormat is Yaz0)
                {
                    ((Yaz0)compressionFormat).Alignment = Alignment;
                }

                System.Diagnostics.Stopwatch sw = new System.Diagnostics.Stopwatch();
                sw.Start();

                var comp = compressionFormat.Compress(data);
                sw.Stop();
                TimeSpan ts      = sw.Elapsed;
                string   message = string.Format("{0:D2}:{1:D2}:{2:D2}", ts.Minutes, ts.Seconds, ts.Milliseconds);
                Console.WriteLine($"Compression Time : {message}");
                return(Tuple.Create(comp, message));
            }

            return(Tuple.Create(data, ""));
        }
Esempio n. 6
0
        static void Main(string[] args)
        {
            String file = args[0];

            byte[] uncompressed = Yaz0.Decompress(file);
            String output       = Path.GetDirectoryName(file) + "test.notyaz0";

            File.WriteAllBytes(output, uncompressed);
        }
Esempio n. 7
0
        private void ImportDlcVillager()
        {
            if (_villager.Data.VillagerId < 0xE0EC || _villager.Data.VillagerId > 0xE0FF)
            {
                MessageBox.Show("You must set your villager to one of the DLC villagers before importing!", "DLC Villager Import Info");
                return;
            }

            using (var openFileDialog = new OpenFileDialog {
                Filter = "Yaz0 compressed file|*.yaz0"
            })
            {
                if (openFileDialog.ShowDialog() != DialogResult.OK)
                {
                    return;
                }

                byte[] villagerData = null;
                try
                {
                    villagerData = System.IO.File.ReadAllBytes(openFileDialog.FileName);
                }
                catch
                {
                    MessageBox.Show("An error occurred while importing the DLC villager info.\nPlease try again!",
                                    "DLC Villager Import Error",
                                    MessageBoxButtons.OK, MessageBoxIcon.Error);
                }
                finally
                {
                    if (villagerData != null)
                    {
                        _villager.ImportDlcVillager(villagerData, (_villager.Data.VillagerId - 0xEC) & 0xFF);

                        // Decompress Yaz0 data and set accordingly
                        var decompressedData = Yaz0.Decompress(villagerData);
                        _villager.Name             = new AcString(decompressedData.Skip(1).Take(6).ToArray(), _saveFile.SaveType).Trim();
                        _villager.Data.Catchphrase = new AcString(decompressedData.Skip(7).Take(4).ToArray(), _saveFile.SaveType).Trim();
                        _shirtEditor.Item          = new Item((ushort)(0x2400 | decompressedData[0xE]));
                        _villager.Data.Personality = decompressedData[0xD];

                        // Update controls to reflect changes
                        _nameBox.Text                 = _villager.Name;
                        _catchphraseBox.Text          = _villager.Data.Catchphrase;
                        _personalityBox.SelectedIndex = _villager.Data.Personality;

                        MessageBox.Show("DLC Villager import was succsessful!", "DLC Villager Import Info",
                                        MessageBoxButtons.OK, MessageBoxIcon.Information);
                    }
                }
            }
        }
Esempio n. 8
0
        /// <summary>
        /// Creates an archive out of the specified <see cref="VirtualFilesystemDirectory"/>, optionally compressing the resulting file.
        /// </summary>
        /// <param name="outputPath">Filepath to which to write the file to.</param>
        /// <param name="root"><see cref="VirtualFilesystemDirectory"/> to create an archive out of.</param>
        /// <param name="compression">Optionally compress with Yaz0 or Yay0 compression.</param>
        public static void WriteArchive(string outputPath, VirtualFilesystemDirectory root, ArchiveCompression compression = ArchiveCompression.Uncompressed)
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                throw new ArgumentNullException("filePath", "Cannot write archive to empty file path!");
            }

            if (root == null)
            {
                throw new ArgumentNullException("root", "Cannot write null VirtualFilesystemDirectory to archive.");
            }

            Archive      rarc       = new Archive();
            MemoryStream outputData = new MemoryStream();

            // Create an archive structure from the given root and write it to file. Compression will be applied if specified.
            MemoryStream uncompressedStream = new MemoryStream();

            using (EndianBinaryWriter fileWriter = new EndianBinaryWriter(uncompressedStream, Endian.Big))
            {
                byte[] rawData = rarc.WriteFile(root);

                fileWriter.Write(rawData);
                fileWriter.Seek(0, SeekOrigin.Begin);
                fileWriter.BaseStream.CopyTo(outputData);
            }

            MemoryStream compressedStream = new MemoryStream();

            switch (compression)
            {
            case ArchiveCompression.Yay0:
                throw new NotImplementedException("Yay0 Compression not implemented.");
            //compressedStream = Yay0.Encode(uncompressedStream);
            //break;

            case ArchiveCompression.Yaz0:
                EndianBinaryWriter encoded = Yaz0.Encode(uncompressedStream);
                encoded.Seek(0, SeekOrigin.Begin);
                encoded.BaseStream.CopyTo(compressedStream);
                break;

            case ArchiveCompression.Uncompressed:

                // Well, that was easy.
                compressedStream = uncompressedStream;
                break;
            }

            compressedStream.Seek(0, SeekOrigin.Begin);
            compressedStream.WriteTo(File.Create(outputPath));
        }
Esempio n. 9
0
        private void UpdateModel()
        {
            // Loads the necessary information about which figurine model to load dynamically from the REL and the DOL.

            m_actorMeshes = WResourceManager.LoadActorResource("Figurine Stand");

            int modelFileID;
            int modelArcIndex;

            int figurineIndex = (int)WhichFigurine;

            string       figurine_rel_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "rels/d_a_obj_figure.rel");
            MemoryStream figurine_rel_data = null;

            using (EndianBinaryReader reader = new EndianBinaryReader(File.ReadAllBytes(figurine_rel_path), Endian.Big))
            {
                figurine_rel_data = Yaz0.Decode(reader);
            }
            using (EndianBinaryReader reader = new EndianBinaryReader(figurine_rel_data, Endian.Big))
            {
                int l_figure_dat_entry_offset = l_figure_dat_tbl_offset + figurineIndex * 0xC;
                modelFileID   = reader.ReadInt32At(l_figure_dat_entry_offset + 0x00);
                modelArcIndex = reader.ReadInt32At(l_figure_dat_entry_offset + 0x08);
            }

            if (modelArcIndex == -1)
            {
                string main_dol_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "sys", "main.dol");
                using (FileStream strm = new FileStream(main_dol_path, FileMode.Open, FileAccess.Read))
                {
                    EndianBinaryReader reader      = new EndianBinaryReader(strm, Endian.Big);
                    long l_CharaData_entry_address = l_CharaData_address + figurineIndex * 0x12;
                    long l_CharaData_entry_offset  = DOL.AddressToOffset(l_CharaData_entry_address, reader);
                    modelArcIndex = reader.ReadByteAt(l_CharaData_entry_offset + 0x10);
                }
            }

            var    arc_name = l_arcname_tbl[modelArcIndex];
            string arc_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", arc_name + ".arc");

            if (File.Exists(arc_path))
            {
                VirtualFilesystemDirectory model_arc = ArchiveUtilities.LoadArchive(arc_path);
                if (model_arc.FindByID((ushort)modelFileID) != null)
                {
                    var figurine_model = WResourceManager.LoadModelFromVFS(model_arc, fileID: (ushort)modelFileID);
                    figurine_model.SetOffsetTranslation(new Vector3(0, 100, 0));
                    m_actorMeshes.Add(figurine_model);
                }
            }
        }
Esempio n. 10
0
        private static Stream CompressFileFormat(ICompressionFormat compressionFormat, Stream data, bool FileIsCompressed, int Alignment,
                                                 string FileName, bool EnableDialog = true)
        {
            string extension = Path.GetExtension(FileName);

            if (extension == ".szs" || extension == ".sbfres")
            {
                FileIsCompressed  = true;
                compressionFormat = new Yaz0();
            }

            if (compressionFormat == null)
            {
                return(data);
            }

            bool CompressFile = false;

            if (EnableDialog && FileIsCompressed)
            {
                if (Runtime.AlwaysCompressOnSave)
                {
                    CompressFile = true;
                }
                else
                {
                    DialogResult save = MessageBox.Show($"Compress file with {compressionFormat}?", "File Save", MessageBoxButtons.YesNo);
                    CompressFile = (save == DialogResult.Yes);
                }
            }
            else if (FileIsCompressed)
            {
                CompressFile = true;
            }

            Console.WriteLine($"FileIsCompressed {FileIsCompressed} CompressFile {CompressFile} CompressionType {compressionFormat}");

            if (CompressFile)
            {
                if (compressionFormat is Yaz0)
                {
                    ((Yaz0)compressionFormat).Alignment = Alignment;
                }

                return(compressionFormat.Compress(data));
            }

            return(data);
        }
Esempio n. 11
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 decompress and load.</param>
        /// <returns><see cref="VirtualFilesystemDirectory"/> containing the contents, or null if not an 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.

                if (fileMagic == 0x59617A30)         // Yaz0
                {
                    Yaz0 yaz0 = new Yaz0();
                    decompressedFile = yaz0.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;
                }
            }

            // 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.
            RARC rarc = new RARC();

            using (EndianBinaryReader reader = new EndianBinaryReader(decompressedFile, Endian.Big))
            {
                return(rarc.ReadFile(reader));
            }
        }
        /// <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));
        }
Esempio n. 13
0
        private void Yaz0CompressLittleEndianToolStripMenuItem_Click(object sender, EventArgs e)
        {
            if (openxmlFileDialog.ShowDialog() == DialogResult.OK)
            {
                FileInfo file = new FileInfo(openyamlFileDialog.FileName);

                saveyaz0FileDialog.ShowDialog();
                if (saveyaz0FileDialog.FileName != "")
                {
                    FileInfo selected = new FileInfo(saveFileDialog.FileName);

                    //TODO: Change to using.
                    FileStream byml = file.OpenRead();
                    File.WriteAllBytes(selected.FullName, Yaz0.Encode(byml));
                    byml.Close();
                    saveyaz0FileDialog.FileName = "";
                }
            }
        }
Esempio n. 14
0
        private void decompressYaz0ToolStripMenuItem_Click(object sender, EventArgs e)
        {
            try
            {
                using (var ofd = new OpenFileDialog())
                {
                    if (ofd.ShowDialog(this) != DialogResult.OK)
                    {
                        return;
                    }

                    using (var stream = ofd.OpenFile())
                        using (var outputStream = new MemoryStream())
                        {
                            Yaz0.Decompress(stream, outputStream);

                            using (var sfd = new SaveFileDialog())
                            {
                                sfd.FileName = ofd.FileName;

                                if (sfd.ShowDialog(this) != DialogResult.OK)
                                {
                                    return;
                                }

                                using (var outputFile = sfd.OpenFile())
                                {
                                    outputStream.Seek(0, SeekOrigin.Begin);
                                    outputStream.CopyTo(outputFile);
                                }
                            }
                        }
                }
            }
            catch (Exception ex)
            {
                MessageBox.Show(ex.Message);
            }
        }
Esempio n. 15
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;
            }
        }
        /// <summary>
        /// Creates an new file out of the specified <see cref="EndianBinaryWriter"/>, optionally compressing the resulting file.
        /// </summary>
        /// <param name="outputPath">Filepath to which to write the file to.</param>
        /// <param name="stream"><see cref="MemoryStream"/> to create an archive out of.</param>
        /// <param name="compression">Optionally compress with Yaz0 or Yay0 compression.</param>
        public static void SaveFile(string outputPath, MemoryStream stream, ArchiveCompression compression = ArchiveCompression.Uncompressed)
        {
            if (string.IsNullOrEmpty(outputPath))
            {
                throw new ArgumentNullException("filePath", "Cannot write archive to empty file path!");
            }

            if (stream == null)
            {
                throw new ArgumentNullException("root", "Cannot write null EndianBinaryWriter to archive.");
            }

            MemoryStream compressedStream = new MemoryStream();

            switch (compression)
            {
            case ArchiveCompression.Yay0:
                throw new NotImplementedException("Yay0 Compression not implemented.");
            //compressedStream = Yay0.Encode(uncompressedStream);
            //break;

            case ArchiveCompression.Yaz0:
                EndianBinaryWriter encoded = Yaz0.Encode(stream);
                encoded.Seek(0, SeekOrigin.Begin);
                encoded.BaseStream.CopyTo(compressedStream);
                break;

            case ArchiveCompression.Uncompressed:

                // Well, that was easy.
                compressedStream = stream;
                break;
            }

            compressedStream.Seek(0, SeekOrigin.Begin);
            using (var fileStream = File.Create(outputPath))
                compressedStream.WriteTo(fileStream);
        }
Esempio n. 17
0
        public void Save(string filename = "")
        {
            if (!string.IsNullOrEmpty(filename))
            {
                FileInfo = new FileInfo(filename);
            }

            // Save As...
            if (!string.IsNullOrEmpty(filename))
            {
                var ms = new MemoryStream();
                _sarc.Save(ms, true);
                _sarc.Close();
                using (var bw = new BinaryWriterX(FileInfo.Create()))
                {
                    bw.Write(Yaz0.Compress(ms, ByteOrder.BigEndian));
                }
            }
            else
            {
                // Create the temp file
                var ms = new MemoryStream();
                _sarc.Save(ms, true);
                _sarc.Close();
                using (var bw = new BinaryWriterX(File.Create(FileInfo.FullName + ".tmp")))
                {
                    bw.Write(Yaz0.Compress(ms, ByteOrder.BigEndian));
                }
                // Delete the original
                FileInfo.Delete();
                // Rename the temporary file
                File.Move(FileInfo.FullName + ".tmp", FileInfo.FullName);
            }

            // Reload the new file to make sure everything is in order
            Load(FileInfo.FullName);
        }
Esempio n. 18
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);
        }
Esempio n. 19
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);
        }
Esempio n. 20
0
        /// <summary>
        /// Process data in an input file that contains a layout.
        /// </summary>
        /// <param name="filename"></param>
        bool ProcessData(string filename, byte[] inData)
        {
            EndianBinaryReader reader = null;

            // now we need to decide what they just opened
            if (inData == null && filename != "")
            {
                reader = new EndianBinaryReader(File.Open(filename, FileMode.Open), Encoding.GetEncoding(932));
            }
            else
            {
                reader = new EndianBinaryReader(inData);
            }

            string magic = "";

            // we have a Yaz0 compressed file
            if (reader.ReadStringFrom(0, 4) == "Yaz0")
            {
                // we have to close our reader so we can properly read this file as a Yaz0 stream
                reader.Close();

                MemoryStream ms = null;

                if (inData == null)
                {
                    ms = new Yaz0(File.Open(filename, FileMode.Open));
                }
                else
                {
                    ms = new Yaz0(new MemoryStream(inData));
                }

                reader = new EndianBinaryReader(ms);
                magic  = reader.ReadStringFrom(0, 4);
            }
            // we have a LZ compressed file
            else if (reader.ReadByteFrom(0) == 0x11)
            {
                LZ77   lzFile = new LZ77(ref reader);
                byte[] lzData = lzFile.getData();
                // close our current reader to open a new one with our input data
                reader.Close();
                reader = new EndianBinaryReader(lzData);
                magic  = reader.ReadStringFrom(0, 4);
            }
            // no compression
            else
            {
                // it is not yaz0 compressed, so we see the magic
                magic = reader.ReadStringFrom(0, 4);
            }

            // now we have to check our magic to see what kind of file it is
            switch (magic)
            {
            case "darc":
                mArchive = new DARC(ref reader);
                break;

            case "NARC":
                mArchive = new NARC(ref reader);
                break;

            case "SARC":
                mArchive = new SARC(ref reader);
                break;

            case "RARC":
                reader.SetEndianess(Endianess.Big);
                mArchive = new RARC(ref reader);
                break;

            case "U?8-":
                reader.SetEndianess(Endianess.Big);
                mArchive = new U8(ref reader);
                break;

            default:
                MessageBox.Show("Error. Unsupported format with magic: " + magic);
                break;
            }

            string layoutType = "";

            // some files have their string table nullified, which makes the names obfuscated
            // I've only seen this in SARCs from MK7, but there's probably more
            if (mArchive != null)
            {
                if (mArchive.isStringTableObfuscated())
                {
                    MessageBox.Show("This file has obfuscated file names. The editor attempted to find layout files, but cannot supply names.");
                }
            }

            reader.Close();

            if (mArchive == null)
            {
                MessageBox.Show("Format not supported.");
                return(false);
            }

            // the only familiar format with archives in archives is SARC and RARC
            if (mArchive.getType() == ArchiveType.SARC || mArchive.getType() == ArchiveType.RARC)
            {
                List <string> names = mArchive.getArchiveFileNames();

                if (names.Count != 0)
                {
                    DialogResult res = MessageBox.Show("This archive has another archive inside of it.\nDo you wish to choose one of the found archives to select a layout?", "Internal Archive", MessageBoxButtons.YesNo);

                    if (res == DialogResult.Yes)
                    {
                        LayoutChooser archiveChooser = new LayoutChooser();
                        archiveChooser.insertEntries(names);
                        archiveChooser.ShowDialog();

                        // if this worked, we dont need to do anything
                        bool result = ProcessData(archiveChooser.getSelectedFile(), mArchive.getDataByName(archiveChooser.getSelectedFile()));

                        if (result)
                        {
                            return(true);
                        }
                        else
                        {
                            MessageBox.Show("Failed to get the internal file.");
                            return(false);
                        }
                    }
                }
            }

            // get all of our needed files
            mLayoutFiles     = mArchive.getLayoutFiles();
            mLayoutAnimFiles = mArchive.getLayoutAnimations();
            mLayoutImages    = mArchive.getLayoutImages();
            mLayoutControls  = mArchive.getLayoutControls();

            if (mLayoutFiles.Count == 0)
            {
                MessageBox.Show("This file contains no layouts.");
                return(false);
            }

            LayoutChooser layoutChooser = new LayoutChooser();

            layoutChooser.insertEntries(new List <string>(mLayoutFiles.Keys));
            layoutChooser.ShowDialog();

            string selectedFile = layoutChooser.getSelectedFile();

            if (selectedFile == null)
            {
                return(false);
            }

            string[] sections = selectedFile.Split('/');
            mMainRoot = "";

            // remove "lyt" part and the file name
            // this will be our main root of the entire opened file
            for (int i = 0; i < sections.Length - 2; i++)
            {
                mMainRoot += sections[i] + "/";
            }

            if (layoutType == "")
            {
                layoutType = Path.GetExtension(selectedFile);
            }

            // now we have to init a layout reader
            EndianBinaryReader layoutReader = null;

            byte[] data;

            switch (layoutType)
            {
            case ".brlyt":
                data         = mLayoutFiles[selectedFile];
                layoutReader = new EndianBinaryReader(data);
                mMainLayout  = new BRLYT(ref layoutReader);
                layoutReader.Close();
                break;

            case ".bclyt":
                data         = mLayoutFiles[selectedFile];
                layoutReader = new EndianBinaryReader(data);
                mMainLayout  = new BCLYT(ref layoutReader);
                break;

            case ".bflyt":
                data         = mLayoutFiles[selectedFile];
                layoutReader = new EndianBinaryReader(data);
                mMainLayout  = new BFLYT(ref layoutReader);
                break;

            case ".blo":
                data         = mLayoutFiles[selectedFile];
                layoutReader = new EndianBinaryReader(data);

                if (layoutReader.ReadStringFrom(4, 4) == "blo1")
                {
                    mMainLayout = new BLO1(ref layoutReader);
                }
                else
                {
                    mMainLayout = new BLO2(ref layoutReader);
                }
                break;

            default:
                MessageBox.Show("This format is not supported yet.");
                break;
            }

            layoutReader.Close();

            if (mMainLayout == null)
            {
                return(false);
            }

            // set our propertygrid with our LYT object
            mainPropertyGrid.SelectedObject = mMainLayout.getLayoutParams();

            if (mMainLayout.getRootPanel() == null)
            {
                MessageBox.Show("Error, the root pane in this layout is not specified.");
                return(false);
            }

            LayoutBase pane  = null;
            LayoutBase group = null;

            // now we have to grab our root panel, which is different on each console
            // so we have to specifically get the one we want
            // the same applies to our root group
            pane = mMainLayout.getRootPanel();

            // this should be RootPane
            TreeNode n1 = new TreeNode
            {
                Tag  = pane,
                Name = pane.mName,
                Text = pane.mName,
            };

            panelList.Nodes.Add(n1);
            fillNodes(pane.getChildren());

            // now for our groups
            group = mMainLayout.getRootGroup();

            if (group != null)
            {
                TreeNode n1_1 = new TreeNode
                {
                    Tag  = group,
                    Name = group.mName,
                    Text = group.mName,
                };

                panelList.Nodes.Add(n1_1);
                fillNodes(group.getChildren());
            }

            // now for textures and fonts
            // but it is possible for either one to not exist
            if (mMainLayout.containsTextures())
            {
                foreach (string str in mMainLayout.getTextureNames())
                {
                    texturesList.Items.Add(str);
                }
            }

            if (mMainLayout.containsFonts())
            {
                foreach (string str in mMainLayout.getFontNames())
                {
                    fontsList.Items.Add(str);
                }
            }

            // and our materials
            if (mMainLayout.containsMaterials())
            {
                foreach (string str in mMainLayout.getMaterialNames())
                {
                    materialList.Items.Add(str);
                }
            }

            // this draws the border of the layout
            mMainLayout.draw();

            layoutViewer.Refresh();

            return(true);
        }
Esempio n. 21
0
        public static file load(Stream data)
        {
            //Too small
            if (data.Length < 0x10)
            {
                data.Close();
                return(new file {
                    type = formatType.unsupported
                });
            }

            BinaryReader input = new BinaryReader(data);
            uint         magic, length;

            switch (peek(input))
            {
            case 0x00010000: return(new file {
                    data = GfModel.load(data), type = formatType.model
                });

            case 0x00060000: return(new file {
                    data = GfMotion.loadAnim(input), type = formatType.anims
                });

            case 0x15041213: return(new file {
                    data = GfTexture.load(data), type = formatType.image
                });

            case 0x15122117:
                RenderBase.OModelGroup mdls = new RenderBase.OModelGroup();
                mdls.model.Add(GfModel.loadModel(data));
                return(new file {
                    data = mdls, type = formatType.model
                });
            }

            switch (getMagic(input, 5))
            {
            case "MODEL": return(new file {
                    data = DQVIIPack.load(data), type = formatType.container
                });
            }

            switch (getMagic(input, 4))
            {
            case "CGFX": return(new file {
                    data = CGFX.load(data), type = formatType.model
                });

            case "CRAG": return(new file {
                    data = GARC.load(data), type = formatType.container
                });

            case "darc": return(new file {
                    data = DARC.load(data), type = formatType.container
                });

            case "FPT0": return(new file {
                    data = FPT0.load(data), type = formatType.container
                });

            case "IECP":
                magic  = input.ReadUInt32();
                length = input.ReadUInt32();
                return(load(new MemoryStream(LZSS.decompress(data, length))));

            case "NLK2":
                data.Seek(0x80, SeekOrigin.Begin);
                return(new file
                {
                    data = CGFX.load(data),
                    type = formatType.model
                });

            case "SARC": return(new file {
                    data = SARC.load(data), type = formatType.container
                });

            case "SMES": return(new file {
                    data = NLP.loadMesh(data), type = formatType.model
                });

            case "Yaz0":
                magic  = input.ReadUInt32();
                length = IOUtils.endianSwap(input.ReadUInt32());
                data.Seek(8, SeekOrigin.Current);
                return(load(new MemoryStream(Yaz0.decompress(data, length))));

            case "zmdl": return(new file {
                    data = ZMDL.load(data), type = formatType.model
                });

            case "ztex": return(new file {
                    data = ZTEX.load(data), type = formatType.texture
                });
            }

            //Check if is a BCLIM or BFLIM file (header on the end)
            if (data.Length > 0x28)
            {
                data.Seek(-0x28, SeekOrigin.End);
                string clim = IOUtils.readStringWithLength(input, 4);
                if (clim == "CLIM" || clim == "FLIM")
                {
                    return new file {
                               data = BCLIM.load(data), type = formatType.image
                    }
                }
                ;
            }

            switch (getMagic(input, 3))
            {
            case "BCH":
                byte[] buffer = new byte[data.Length];
                input.Read(buffer, 0, buffer.Length);
                data.Close();
                return(new file
                {
                    data = BCH.load(new MemoryStream(buffer)),
                    type = formatType.model
                });

            case "DMP": return(new file {
                    data = DMP.load(data), type = formatType.image
                });
            }

            string magic2b = getMagic(input, 2);

            switch (magic2b)
            {
            case "AD": return(new file {
                    data = AD.load(data), type = formatType.model
                });

            case "BM": return(new file {
                    data = MM.load(data), type = formatType.model
                });

            case "BS": return(new file {
                    data = BS.load(data), type = formatType.anims
                });

            case "CM": return(new file {
                    data = CM.load(data), type = formatType.model
                });

            case "CP": return(new file {
                    data = CP.load(data), type = formatType.model
                });

            case "GR": return(new file {
                    data = GR.load(data), type = formatType.model
                });

            case "MM": return(new file {
                    data = MM.load(data), type = formatType.model
                });

            case "PC": return(new file {
                    data = PC.load(data), type = formatType.model
                });

            case "PT": return(new file {
                    data = PT.load(data), type = formatType.texture
                });
            }

            if (magic2b.Length == 2)
            {
                if ((magic2b[0] >= 'A' && magic2b[0] <= 'Z') &&
                    (magic2b[1] >= 'A' && magic2b[1] <= 'Z'))
                {
                    return(new file {
                        data = PkmnContainer.load(data), type = formatType.container
                    });
                }
            }

            //Compressions
            data.Seek(0, SeekOrigin.Begin);
            uint cmp = input.ReadUInt32();

            if ((cmp & 0xff) == 0x13)
            {
                cmp = input.ReadUInt32();
            }
            switch (cmp & 0xff)
            {
            case 0x11: return(load(new MemoryStream(LZSS_Ninty.decompress(data, cmp >> 8))));

            case 0x90:
                byte[] buffer  = BLZ.decompress(data);
                byte[] newData = new byte[buffer.Length - 1];
                Buffer.BlockCopy(buffer, 1, newData, 0, newData.Length);
                return(load(new MemoryStream(newData)));
            }

            data.Close();
            return(new file {
                type = formatType.unsupported
            });
        }
Esempio n. 22
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;
            }
        }
Esempio n. 23
0
        public void InjectFile(int vrom, byte[] data)
        {
            var file = GetFile(vrom);

            if (file == null)
            {
                throw new Z64GameException("Invalid VROM");
            }

            int oldSize = file.Compressed ? file.RomEnd - file.RomStart : file.Data.Length;

            var restStart = file.RomEnd != 0
                ? file.RomEnd
                : file.RomStart + file.Data.Length;

            //find rom end
            Z64File last = null;

            for (int i = 0; i < GetFileCount(); i++)
            {
                var iter = GetFileFromIndex(i);

                if (iter.Valid() && !iter.Deleted && (last == null || iter.RomStart > last.RomStart))
                {
                    last = iter;
                }
            }
            if (last == null)
            {
                throw new Exception("?");
            }

            var restEnd = last.RomEnd;

            //save rest
            byte[] rest = new byte[restEnd - restStart];
            Buffer.BlockCopy(Rom.RawRom, restStart, rest, 0, rest.Length);

            var encData = file.Compressed ? Yaz0.Compress(data) : data;
            int off     = encData.Length - oldSize;

            //copy new file in rom
            Buffer.BlockCopy(encData, 0, Rom.RawRom, file.RomStart, encData.Length);

            file.Data    = data;
            file.VRomEnd = (file.VRomStart + data.Length) + 0xF & ~0xF;
            if (file.Compressed)
            {
                file.RomEnd = (file.RomStart + encData.Length) + 0xF & ~0xF;
            }

            //copy rest
            Buffer.BlockCopy(rest, 0, Rom.RawRom, file.RomEnd, rest.Length);

            //offset each file rom addresses
            for (int i = _files.IndexOf(file) + 1; i < _files.Count; i++)
            {
                _files[i].RomStart = (_files[i].RomStart + off) + 0xF & ~0xF;
                _files[i].RomEnd   = (_files[i].RomEnd + off) + 0xF & ~0xF;
            }

            file.Data    = data;
            file.Deleted = false;
        }
Esempio n. 24
0
        private static J3D LoadModelFromResource(WActorResource.ModelResource res, string archive)
        {
            J3D j3d = null;

            if (string.IsNullOrEmpty(res.Path) || string.IsNullOrEmpty(archive))
            {
                return(null);
            }

            string archivePath = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", archive + ".arc");

            if (!File.Exists(archivePath))
            {
                return(null);
            }

            VirtualFilesystemDirectory model_arc   = ArchiveUtilities.LoadArchive(archivePath);
            VirtualFilesystemFile      archiveFile = model_arc.GetFileAtPath(res.Path);

            if (archiveFile == null)
            {
                Console.WriteLine("LoadActorByName failed because the specified path \"{0}\" does not exist in archive \"{1}\"!", res.Path, archive);
                return(null);
            }

            byte[] j3dData = archiveFile.Data;

            j3d = new J3D(archiveFile.Name);
            using (EndianBinaryReader reader = new EndianBinaryReader(j3dData, Endian.Big))
                j3d.LoadFromStream(reader, WSettingsManager.GetSettings().DumpTextures, WSettingsManager.GetSettings().DumpShaders);

            if (res.Position != null)
            {
                j3d.SetOffsetTranslation((Vector3)res.Position);
            }
            if (res.Rotation != null)
            {
                j3d.SetOffsetRotation((Vector3)res.Rotation);
            }
            if (res.Scale != null)
            {
                j3d.SetOffsetScale((Vector3)res.Scale);
            }

            j3d.SetHardwareLight(0, m_mainLight);
            j3d.SetHardwareLight(1, m_secondaryLight);
            j3d.SetTextureOverride("ZBtoonEX", "resources/textures/ZBtoonEX.png");
            j3d.SetTextureOverride("ZAtoon", "resources/textures/ZAtoon.png");

            if (res.Animations == null)
            {
                res.Animations = new WActorResource.AnimationResource[0];
            }

            foreach (var anim in res.Animations)
            {
                VirtualFilesystemDirectory anim_arc = model_arc;

                if (!string.IsNullOrEmpty(anim.ArchiveName))
                {
                    string anim_arc_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res/Object/", anim.ArchiveName + ".arc");

                    if (!File.Exists(anim_arc_path))
                    {
                        return(null);
                    }

                    anim_arc = ArchiveUtilities.LoadArchive(anim_arc_path);
                }

                VirtualFilesystemFile anim_file = anim_arc.GetFileAtPath(anim.Path);

                if (anim_file == null)
                {
                    continue;
                }

                byte[] anim_data = anim_file.Data;

                // Decompress the file if necessary
                if (anim_data[0] == 'Y')
                {
                    MemoryStream decompressed_data = null;

                    using (EndianBinaryReader decompressor = new EndianBinaryReader(anim_data, Endian.Big))
                    {
                        decompressed_data = Yaz0.Decode(decompressor);
                    }

                    anim_data = decompressed_data.ToArray();
                }

                switch (anim.Type)
                {
                case "bck":
                    BCK loaded_bck = new BCK(anim_file.Name);
                    using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big))
                        loaded_bck.LoadFromStream(reader);

                    j3d.BoneAnimations.Add(loaded_bck);
                    j3d.SetBoneAnimation(anim_file.Name);

                    loaded_bck.Tick(anim.StartTime);

                    if (anim.PausedOnLoad)
                    {
                        loaded_bck.Pause();
                    }
                    break;

                case "btk":
                    BTK loaded_btk = new BTK(anim_file.Name);
                    using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big))
                        loaded_btk.LoadFromStream(reader);

                    j3d.MaterialAnimations.Add(loaded_btk);
                    j3d.SetMaterialAnimation(anim_file.Name);

                    loaded_btk.Tick(anim.StartTime);

                    if (anim.PausedOnLoad)
                    {
                        loaded_btk.Pause();
                    }
                    break;

                case "brk":
                    BRK loaded_brk = new BRK(anim_file.Name);
                    using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big))
                        loaded_brk.LoadFromStream(reader);

                    j3d.RegisterAnimations.Add(loaded_brk);
                    j3d.SetRegisterAnimation(anim_file.Name);

                    loaded_brk.Tick(anim.StartTime);

                    if (anim.PausedOnLoad)
                    {
                        loaded_brk.Pause();
                    }
                    break;

                case "bmt":
                    BMT loaded_bmt = new BMT(anim_file.Name);
                    using (EndianBinaryReader reader = new EndianBinaryReader(anim_data, Endian.Big))
                        loaded_bmt.LoadFromStream(reader);

                    j3d.ExternalMaterials.Add(loaded_bmt);
                    j3d.SetExternalMaterial(anim_file.Name);

                    if (loaded_bmt.MAT3 != null)
                    {
                        // a hack to get bmts working
                        Material dummyMat = null;
                        j3d.AssignVertexAttributesToMaterialsRecursive(j3d.INF1Tag.HierarchyRoot, ref dummyMat, loaded_bmt.MAT3);
                        j3d.GenerateShadersForMaterials(loaded_bmt.MAT3);
                    }

                    break;

                default:
                    break;
                }
            }

            j3d.Tick(1 / (float)60);

            if (res.ChildModels == null)
            {
                res.ChildModels = new WActorResource.ModelResource[0];
            }

            foreach (var childRes in res.ChildModels)
            {
                var childJ3d = LoadModelFromResource(childRes, archive);
                j3d.AddChildModel(childJ3d, childRes.ParentJointName);
            }

            return(j3d);
        }