Ejemplo n.º 1
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));
        }
Ejemplo n.º 2
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.º 3
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);
                }
            }
        }
Ejemplo 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 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));
            }
        }
Ejemplo n.º 5
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.º 6
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);
        }
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;
            }
        }