private int GetDirStructureRecursive(int curIndex, List <FSTEntry> FST, FSTEntry parentFST, VirtualFilesystemDirectory parentDir, EndianBinaryReader image) { FSTEntry curEntry = FST[curIndex]; if (curEntry.Type == FSTNodeType.Directory) { VirtualFilesystemDirectory dir = new VirtualFilesystemDirectory(curEntry.RelativeFileName); Console.WriteLine("Created directory: " + dir.Name); while (curIndex < curEntry.FileSizeNextDirIndex - 1) { curIndex = GetDirStructureRecursive(curIndex + 1, FST, curEntry, dir, image); } parentDir.Children.Add(dir); Console.WriteLine("Leaving directory: " + dir.Name); return(curIndex); } else { VirtualFilesystemFile file = GetFileData(curEntry, image); parentDir.Children.Add(file); return(curIndex); } }
private void PathExport(string path) { VirtualFilesystemDirectory rootDir = new VirtualFilesystemDirectory("archive"); // Write text MemoryStream bmgFile = new MemoryStream(); EndianBinaryWriter bmgWriter = new EndianBinaryWriter(bmgFile, Endian.Big); LoadedTextFile.Export(bmgWriter); VirtualFilesystemFile bmg = new VirtualFilesystemFile("zel_00", ".bmg", new VirtualFileContents(bmgFile.ToArray())); rootDir.Children.Add(bmg); // Write color MemoryStream bmcFile = new MemoryStream(); EndianBinaryWriter bmcWriter = new EndianBinaryWriter(bmcFile, Endian.Big); LoadedColorFile.Export(bmcWriter); VirtualFilesystemFile bmc = new VirtualFilesystemFile("color", ".bmc", new VirtualFileContents(bmcFile.ToArray())); rootDir.Children.Add(bmc); if (m_isCompressed) { WArchiveTools.ArchiveUtilities.WriteArchive(path, rootDir, WArchiveTools.ArchiveCompression.Yaz0); } else { WArchiveTools.ArchiveUtilities.WriteArchive(path, rootDir); } }
private void PathExport(string path) { /* * VirtualFilesystemDirectory rootDir = new VirtualFilesystemDirectory("archive"); * * // Write text * MemoryStream bmgFile = new MemoryStream(); * EndianBinaryWriter bmgWriter = new EndianBinaryWriter(bmgFile, Endian.Big); * LoadedTextFile.Export(bmgWriter); * VirtualFilesystemFile bmg = new VirtualFilesystemFile("zel_00", ".bmg", new VirtualFileContents(bmgFile.ToArray())); * rootDir.Children.Add(bmg); * * // Write color * MemoryStream bmcFile = new MemoryStream(); * EndianBinaryWriter bmcWriter = new EndianBinaryWriter(bmcFile, Endian.Big); * LoadedColorFile.Export(bmcWriter); * VirtualFilesystemFile bmc = new VirtualFilesystemFile("color", ".bmc", new VirtualFileContents(bmcFile.ToArray())); * rootDir.Children.Add(bmc); */ VirtualFilesystemDirectory rootDir = new VirtualFilesystemDirectory("archive"); foreach (VirtualFilesystemNode node in m_loadedDirRoot.Children) { if (node is VirtualFilesystemFile) { VirtualFilesystemFile oldFile = node as VirtualFilesystemFile; MemoryStream newFileData = new MemoryStream(); EndianBinaryWriter newFileWriter = new EndianBinaryWriter(newFileData, Endian.Big); if (oldFile.Extension == ".bmg") { LoadedTextFile.Export(newFileWriter); } else if (oldFile.Extension == ".bmc") { LoadedColorFile.Export(newFileWriter); } else { rootDir.Children.Add(oldFile); continue; } VirtualFilesystemFile newFile = new VirtualFilesystemFile(oldFile.Name, oldFile.Extension, newFileData.ToArray()); rootDir.Children.Add(newFile); } } if (m_isCompressed) { WArchiveTools.ArchiveUtilities.WriteArchive(path, rootDir, WArchiveTools.ArchiveCompression.Yaz0); } else { WArchiveTools.ArchiveUtilities.WriteArchive(path, rootDir); } }
private void DoOutputPrep(VirtualFilesystemNode vfsNode, List <FSTEntry> outputFST, List <byte> fstNameBank, EndianBinaryWriter writer, int curParentDirIndex) { FSTEntry fstEnt = new FSTEntry(); if (vfsNode.Type == NodeType.Directory) { VirtualFilesystemDirectory dir = (VirtualFilesystemDirectory)vfsNode; fstEnt.Type = FSTNodeType.Directory; fstEnt.FileNameOffset = fstNameBank.Count(); fstNameBank.AddRange(Encoding.ASCII.GetBytes(dir.Name.ToCharArray())); fstNameBank.Add(0); fstEnt.FileOffsetParentDir = curParentDirIndex; curParentDirIndex = outputFST.Count(); int thisDirIndex = curParentDirIndex; outputFST.Add(fstEnt); //Placeholder for this dir foreach (VirtualFilesystemNode child in dir.Children) { DoOutputPrep(child, outputFST, fstNameBank, writer, curParentDirIndex); } int dirEndIndex = outputFST.Count(); fstEnt.FileSizeNextDirIndex = (dirEndIndex - thisDirIndex) + thisDirIndex; outputFST[thisDirIndex] = fstEnt; //Add the actual entry after giving it the rest of the info } else { VirtualFilesystemFile file = (VirtualFilesystemFile)vfsNode; fstEnt.Type = FSTNodeType.File; fstEnt.FileSizeNextDirIndex = file.Data.Length; fstEnt.FileNameOffset = fstNameBank.Count(); fstNameBank.AddRange(Encoding.ASCII.GetBytes(file.Name.ToCharArray())); fstNameBank.AddRange(Encoding.ASCII.GetBytes(file.Extension.ToCharArray())); fstNameBank.Add((byte)0); writer.BaseStream.Position = (int)writer.BaseStream.Position + (32 - ((int)writer.BaseStream.Position % 32)) % 32; fstEnt.FileOffsetParentDir = (int)writer.BaseStream.Position; writer.Write(file.Data); for (int i = 0; i < ((32 - (file.Data.Length - 32)) % 32); i++) { writer.Write((byte)0); } //Console.WriteLine("Wrote file: " + file.Name); outputFST.Add(fstEnt); } }
private void CreateFileFromArc(VirtualFilesystemFile file, string rootPath) { string filePath = $"{rootPath}\\{file.NameWithExtension}"; using (FileStream stream = new FileStream(filePath, FileMode.Create, FileAccess.Write)) { stream.Write(file.Data, 0, file.Data.Length); } }
private void Open() { OpenFileDialog m_openFile = new OpenFileDialog(); m_openFile.FileName = "bmgres"; m_openFile.DefaultExt = ".arc"; m_openFile.Filter = "arc files (*.arc)|*.arc"; if (m_openFile.ShowDialog() == true) { VirtualFilesystemDirectory sourceDir = WArchiveTools.ArchiveUtilities.LoadArchive(m_openFile.FileName); foreach (VirtualFilesystemNode node in sourceDir.Children) { EndianBinaryReader reader; if (node.Type == NodeType.File) { VirtualFilesystemFile file = node as VirtualFilesystemFile; if (file.Extension == ".bmg") { if (IsDataLoaded) { CloseCurrentFile(); } reader = new EndianBinaryReader(file.Data, Endian.Big); LoadedTextFile = new BMG(reader); m_listboxSelectedIndex = 0; m_loadedFileName = m_openFile.FileName; WindowTitle = m_loadedFileName; ColViewSource = new CollectionViewSource(); ColViewSource.Source = LoadedTextFile.MessageList; SelectedMessage = LoadedTextFile.MessageList[0]; IsDataLoaded = true; m_loadedDirRoot = sourceDir; } else if (file.Extension == ".bmc") { VirtualFilesystemFile bmcFile = node as VirtualFilesystemFile; reader = new EndianBinaryReader(bmcFile.Data, Endian.Big); LoadedColorFile = new BMC(reader); } } } } }
/// <summary> /// Returns the file at the given path, if it exists. If the file does not exist, it will return null. /// </summary> /// <param name="root">ISO to search</param> /// <param name="filePath">File path to search for</param> /// <returns></returns> public static VirtualFilesystemFile FindFile(VirtualFilesystemDirectory root, string filePath) { VirtualFilesystemFile result = null; VirtualFilesystemDirectory curDir = root; List <string> dividedPath = new List <string>(filePath.ToLower().Split('\\')); int pathIndex = 0; // For each element of the filepath, we'll look at the current directory's children, // starting with the root, and see if the name matches. // If we find a file, we'll check to see if its name and extension match the current // filepath element. If it does, we can break the loop and leave. // If not, we check if it's a directory instead, and if it is, we set curDir to it. while (pathIndex < dividedPath.Count) { for (int i = 0; i < curDir.Children.Count; i++) { if (curDir.Children[i].Type == NodeType.File) { VirtualFilesystemFile cand = curDir.Children[i] as VirtualFilesystemFile; string fileNameWithExtension = cand.Name.ToLower() + cand.Extension.ToLower(); if (fileNameWithExtension == dividedPath[pathIndex]) { result = cand; break; } } else if (curDir.Children[i].Name.ToLower() == dividedPath[pathIndex]) { if (curDir.Children[i].Type == NodeType.Directory) { curDir = curDir.Children[i] as VirtualFilesystemDirectory; } break; } } pathIndex++; } return(result); }
private void DumpDirsRecursive(VirtualFilesystemNode vfsObj, string root) { if (vfsObj.Type == NodeType.Directory) { VirtualFilesystemDirectory dir = (VirtualFilesystemDirectory)vfsObj; string testRoot = root + @"\" + dir.Name; Directory.CreateDirectory(testRoot); foreach (VirtualFilesystemNode child in dir.Children) { if (child.Type == NodeType.Directory) { Directory.CreateDirectory(testRoot + @"\" + child.Name); Console.WriteLine("Wrote directory: " + testRoot + @"\" + child.Name); DumpDirsRecursive(child, testRoot); } else { DumpDirsRecursive(child, testRoot); } } } else { VirtualFilesystemFile file = (VirtualFilesystemFile)vfsObj; using (FileStream stream = new FileStream(root + @"\" + file.Name + file.Extension, FileMode.Create)) { EndianBinaryWriter writer = new EndianBinaryWriter(stream, Endian.Big); writer.Write(file.Data); Console.WriteLine("Wrote file: " + root + @"\" + file.Name + file.Extension); } } }
public static J3D LoadModelFromVFS(VirtualFilesystemDirectory fs, string path) { TSharedRef <J3D> existRef = null;//m_j3dList.Find(x => string.Compare(x.FilePath, arc_and_file_path, StringComparison.InvariantCultureIgnoreCase) == 0); J3D model = new J3D(path); VirtualFilesystemFile file = fs.GetFileAtPath(path); using (EndianBinaryReader reader = new EndianBinaryReader(file.Data, Endian.Big)) model.LoadFromStream(reader); existRef = new TSharedRef <J3D>(); existRef.FilePath = fs.Name + '/' + path; existRef.Asset = model; existRef.ReferenceCount++; m_j3dList.Add(existRef); return(model); }
private int GetFSTSkipValue(int curValue, VirtualFilesystemNode node) { if (node.Type == NodeType.Directory) { VirtualFilesystemDirectory dir = (VirtualFilesystemDirectory)node; curValue += (12 + dir.Name.Length + 1); foreach (VirtualFilesystemNode child in dir.Children) { curValue = GetFSTSkipValue(curValue, child); } } else { VirtualFilesystemFile file = (VirtualFilesystemFile)node; curValue += (int)(12 + file.Name.Length + file.Extension.Length + 1); } return(curValue); }
private bool TryLoadMessageArchive() { string bmgres_path = Path.Combine(WSettingsManager.GetSettings().RootDirectoryPath, "files", "res", "Msg", "bmgres.arc"); if (!File.Exists(bmgres_path)) { return(false); } m_MessageArchive = ArchiveUtilities.LoadArchive(bmgres_path); VirtualFilesystemFile text_bank = m_MessageArchive.GetFileAtPath("zel_00.bmg"); using (MemoryStream strm = new MemoryStream(text_bank.Data)) { EndianBinaryReader reader = new EndianBinaryReader(strm, Endian.Big); LoadMessageData(reader); } return(true); }
private VirtualFilesystemFile GetFileData(FSTEntry fstData, EndianBinaryReader image) { string[] fileNameAndExtension = fstData.RelativeFileName.Split('.'); image.BaseStream.Position = fstData.FileOffsetParentDir; byte[] data = image.ReadBytes((int)fstData.FileSizeNextDirIndex); VirtualFilesystemFile file; if (fileNameAndExtension.Length != 2) { file = new VirtualFilesystemFile(fileNameAndExtension[0], "", data); } else { file = new VirtualFilesystemFile(fileNameAndExtension[0], "." + fileNameAndExtension[1], data); } Console.WriteLine("Created file: " + file.Name); return(file); }
public override VirtualFilesystemDirectory ExportToVFS() { VirtualFilesystemDirectory new_dir = SourceDirectory; new_dir.Name = Name; VirtualFilesystemFile dzr_file = SourceDirectory.GetFileAtPath("dzr/room.dzr"); using (MemoryStream mem = new MemoryStream()) { using (EndianBinaryWriter writer = new EndianBinaryWriter(mem, Endian.Big)) { SceneDataExporter exporter = new SceneDataExporter(); exporter.ExportToStream(writer, this); writer.Flush(); dzr_file.Data = mem.ToArray(); } } return(new_dir); }
public override VirtualFilesystemDirectory ExportToVFS() { VirtualFilesystemDirectory new_dir = SourceDirectory; new_dir.Name = Name; VirtualFilesystemFile dzs_file = SourceDirectory.GetFileAtPath("dzs/stage.dzs"); using (MemoryStream mem = new MemoryStream()) { using (EndianBinaryWriter writer = new EndianBinaryWriter(mem, Endian.Big)) { SceneDataExporter exporter = new SceneDataExporter(); exporter.ExportToStream(writer, this); writer.Flush(); dzs_file.Data = mem.ToArray(); } } List <J3DNode> meshes = GetChildrenOfType <J3DNode>(); for (int i = 0; i < meshes.Count; i++) { string modelExt = meshes[i].Model.StudioType == "bdl4" ? "bdl" : "bmd"; VirtualFilesystemFile modelFile = SourceDirectory.GetFileAtPath($"{ modelExt }/{ meshes[i].Name }.{ modelExt }"); byte[] data = File.ReadAllBytes(meshes[i].Filename); if (modelFile != null) { modelFile.Data = data; } else { VirtualFilesystemDirectory modelDir = null; foreach (VirtualFilesystemNode n in new_dir.Children) { if (n.Name == modelExt) { modelDir = n as VirtualFilesystemDirectory; break; } } if (modelDir == null) { modelDir = new VirtualFilesystemDirectory(modelExt); new_dir.Children.Add(modelDir); } modelDir.Children.Add(new VirtualFilesystemFile(meshes[i].Name, $".{ modelExt }", data)); } } VirtualFilesystemFile dat_file = SourceDirectory.GetFileAtPath("dat/event_list.dat"); WEventList eventlist = GetChildrenOfType <WEventList>()[0]; using (MemoryStream ev_strm = new MemoryStream()) { using (EndianBinaryWriter writer = new EndianBinaryWriter(ev_strm, Endian.Big)) { eventlist.ExportToStream(writer); writer.Flush(); dat_file.Data = ev_strm.ToArray(); } } return(new_dir); }
private void Open() { OpenFileDialog m_openFile = new OpenFileDialog(); m_openFile.FileName = "bmgres"; m_openFile.DefaultExt = ".arc"; m_openFile.Filter = "arc files (*.arc)|*.arc"; if (m_openFile.ShowDialog() == true) { VirtualFilesystemDirectory sourceDir = WArchiveTools.ArchiveUtilities.LoadArchive(m_openFile.FileName); foreach (VirtualFilesystemNode node in sourceDir.Children) { EndianBinaryReader reader; if (node.Name == "zel_00") { VirtualFilesystemFile bmgFile = node as VirtualFilesystemFile; reader = new EndianBinaryReader(bmgFile.File.GetData(), Endian.Big); LoadedTextFile = new BmgTextFile(reader); m_listboxSelectedIndex = 0; IsSearchByText = true; m_loadedFileName = m_openFile.FileName; WindowTitle = m_loadedFileName; ColViewSource = new CollectionViewSource(); ColViewSource.Source = LoadedTextFile.MessageList; SelectedMessage = LoadedTextFile.MessageList[0]; IsDataLoaded = true; } else if (node.Name == "color") { VirtualFilesystemFile bmcFile = node as VirtualFilesystemFile; reader = new EndianBinaryReader(bmcFile.File.GetData(), Endian.Big); LoadedColorFile = new BmcColorFile(reader); } } /* * RARC m_arc = new RARC(m_openFile.FileName); * * for (int i = 0; i < m_arc.Nodes.Count(); i++) * { * for (int j = 0; j < m_arc.Nodes[i].Entries.Count(); j++) * { * if (m_arc.Nodes[i].Entries[j].Name.Contains(".bmg")) * { * LoadedTextFile = new BmgTextFile(new EndianBinaryReader(m_arc.Nodes[i].Entries[j].Data, Endian.Big)); * * m_listboxSelectedIndex = 0; * * IsSearchByText = true; * * m_loadedFileName = m_openFile.FileName; * * ColViewSource = new CollectionViewSource(); * * ColViewSource.Source = LoadedTextFile.MessageList; * * SelectedMessage = LoadedTextFile.MessageList[0]; * * IsDataLoaded = true; * } * * if (m_arc.Nodes[i].Entries[j].Name.Contains(".bmc")) * { * LoadedColorFile = new BmcColorFile(new EndianBinaryReader(m_arc.Nodes[i].Entries[j].Data, Endian.Big)); * } * } * }*/ } }
public void WriteISO(VirtualFilesystemDirectory root, string path) { using (FileStream output = new FileStream(path, FileMode.Create, FileAccess.Write)) { EndianBinaryWriter writer = new EndianBinaryWriter(output, Endian.Big); List <byte> fstNameBank = new List <byte>(); List <FSTEntry> outputFST = new List <FSTEntry>(); List <VirtualFilesystemFile> fileList = new List <VirtualFilesystemFile>(); FSTEntry rootFST = new FSTEntry(); int fstListOffset = 0; VirtualFilesystemDirectory sysDir = (VirtualFilesystemDirectory)root.Children[0]; VirtualFilesystemFile header = (VirtualFilesystemFile)sysDir.Children[0]; writer.Write(header.Data); VirtualFilesystemFile apploader = (VirtualFilesystemFile)sysDir.Children[2]; writer.Write(apploader.Data); VirtualFilesystemFile dol = (VirtualFilesystemFile)sysDir.Children[1]; writer.Write(dol.Data); fstListOffset = (int)writer.BaseStream.Position; int fstSkipOffsetValue = 12; root.Children.RemoveAt(0); foreach (VirtualFilesystemNode node in root.Children) { fstSkipOffsetValue = GetFSTSkipValue(fstSkipOffsetValue, node); } byte[] dummyFST = new byte[fstSkipOffsetValue]; writer.Write(dummyFST); rootFST.Type = FSTNodeType.Directory; outputFST.Add(rootFST); //Placeholder FST entry for the root foreach (VirtualFilesystemNode node in root.Children) { DoOutputPrep(node, outputFST, fstNameBank, writer, 0); } rootFST.FileSizeNextDirIndex = outputFST.Count(); outputFST[0] = rootFST; //Add actual root FST entry writer.BaseStream.Position = fstListOffset; foreach (FSTEntry entry in outputFST) { writer.Write((byte)entry.Type); writer.Write((byte)0); writer.Write((ushort)entry.FileNameOffset); writer.Write(entry.FileOffsetParentDir); writer.Write(entry.FileSizeNextDirIndex); } writer.Write(fstNameBank.ToArray()); } }
public VirtualFilesystemDirectory LoadISO(EndianBinaryReader reader) { // This will hold the file system entries that we grab from the ISO. List <FSTEntry> FSTTest = new List <FSTEntry>(); int FSTOffset = reader.ReadInt32At(0x424); reader.BaseStream.Position = FSTOffset; int numEntries = reader.ReadInt32At(reader.BaseStream.Position + 8); int stringTableOffset = numEntries * 0xC; // Each FST entry is 12/0xC bytes long for (int i = 0; i < numEntries; i++) { FSTEntry fst = new FSTEntry(); fst.Type = (FSTNodeType)reader.ReadByte(); reader.SkipByte(); // Padding int curPos = (int)reader.BaseStream.Position; // Save the current stream position ushort stringOffset = (ushort)reader.ReadInt16(); // Get the offset to the entry's name reader.BaseStream.Position = stringOffset + stringTableOffset + FSTOffset; // Seek to entry's name string name = reader.ReadStringUntil('\0'); fst.RelativeFileName = name; reader.BaseStream.Position = curPos + 2; // Return to where we were so that we can read additional data for this entry fst.FileOffsetParentDir = reader.ReadInt32(); fst.FileSizeNextDirIndex = reader.ReadInt32(); FSTTest.Add(fst); } // Root of the ISO. The function will return this. VirtualFilesystemDirectory rootDir = new VirtualFilesystemDirectory("root"); // Holds system data. DOL, apploader, etc. Named to provide compatibility with GCRebuilder VirtualFilesystemDirectory sysData = new VirtualFilesystemDirectory("&&systemdata"); // Header data for the ISO byte[] headerData = reader.ReadBytesAt(0, 0x2440); sysData.Children.Add(new VirtualFilesystemFile("iso", ".hdr", headerData)); int headerOffset = reader.ReadInt32At(0x420); // Executable data byte[] dolData = reader.ReadBytesAt(headerOffset, FSTOffset - headerOffset); sysData.Children.Add(new VirtualFilesystemFile("Start", ".dol", dolData)); // Apploader byte[] appLoaderData = reader.ReadBytesAt(0x2440, headerOffset - 0x2440); sysData.Children.Add(new VirtualFilesystemFile("AppLoader", ".ldr", appLoaderData)); // Table of contents (FST) byte[] fstData = reader.ReadBytesAt(FSTOffset, reader.ReadInt32At(0x428)); sysData.Children.Add(new VirtualFilesystemFile("Game", ".toc", fstData)); rootDir.Children.Add(sysData); int count = 1; while (count < numEntries) { if (FSTTest[count].Type == FSTNodeType.Directory) { VirtualFilesystemDirectory dir = new VirtualFilesystemDirectory(FSTTest[count].RelativeFileName); FSTEntry curEnt = FSTTest[count]; while (count < curEnt.FileSizeNextDirIndex - 1) { count = GetDirStructureRecursive(count + 1, FSTTest, FSTTest[count + 1], dir, reader); } rootDir.Children.Add(dir); } else { VirtualFilesystemFile file = GetFileData(FSTTest[count], reader); rootDir.Children.Add(file); } count += 1; } return(rootDir); }
private FileEntry[] GetDirDataRecursive(VirtualFilesystemDirectory rootDir, VirtualFilesystemDirectory parentDir) { List <FileEntry> dirFileEntries = new List <FileEntry>(); FileEntry file; Node dirNode; // I'll admit this isn't ideal. If I'm looking at the native archives right, they tend // to follow the rule of "files first, directories second" when it comes to file entries. // Therefore, I'm going to set it up right now so that it will get files first, *then* directories. foreach (VirtualFilesystemNode node in rootDir.Children) { // We just need a file entry here if (node.Type == NodeType.File) { VirtualFilesystemFile virtFile = node as VirtualFilesystemFile; file = new FileEntry { ID = (ushort)exportFileEntries.Count, NameHashcode = HashName(virtFile.Name + virtFile.Extension), Flags = 0x11, Name = virtFile.Name + virtFile.Extension, Data = virtFile.Data }; dirFileEntries.Add(file); } } foreach (VirtualFilesystemNode node in rootDir.Children) { // We need a node and a file entry here if (node.Type == NodeType.Directory) { VirtualFilesystemDirectory virtDir = node as VirtualFilesystemDirectory; dirNode = new Node { Type = virtDir.Name.Substring(0, 3).ToUpper() + " ", Name = virtDir.Name, NameHashcode = HashName(virtDir.Name), FirstFileOffset = (uint)exportFileEntries.Count }; exportNodes.Add(dirNode); file = new FileEntry { ID = ushort.MaxValue, NameHashcode = HashName(virtDir.Name), Flags = 0x02, Name = virtDir.Name, Data = new byte[] { (byte)(exportNodes.IndexOf(exportNodes.Find(i => i.Name == virtDir.Name))) }, }; dirFileEntries.Add(file); } } exportFileEntries.AddRange(dirFileEntries.ToArray()); InsertDirOperatorEntries(rootDir, parentDir); // The recursive part. One more foreach! foreach (VirtualFilesystemNode node in rootDir.Children) { if (node.Type == NodeType.Directory) { VirtualFilesystemDirectory dir = node as VirtualFilesystemDirectory; Node tempNode = exportNodes.Find(i => i.Name == node.Name); tempNode.Entries = GetDirDataRecursive(dir, rootDir); } } return(dirFileEntries.ToArray()); }
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); }
public static J3D LoadActorByName(string actorName) { // Stop to check if we've already loaded this model. var existRef = m_j3dList.Find(x => string.Compare(x.FilePath, actorName, StringComparison.InvariantCultureIgnoreCase) == 0); if (existRef != null) { existRef.ReferenceCount++; return(existRef.Asset); } if (actorName == null) { return(null); } // Check to see if we have an Actor Descriptor for this actor. if (!m_actorDescriptors.ContainsKey(actorName)) { return(null); } WActorDescriptor descriptor = m_actorDescriptors[actorName]; // Check to see that this actor descriptor specifies a model path. if (string.IsNullOrEmpty(descriptor.ModelPath) || string.IsNullOrEmpty(descriptor.ArchiveName)) { return(null); } string archivePath = Path.Combine(Properties.Settings.Default.RootDirectory, "res/Object/", descriptor.ArchiveName + ".arc"); // Check to see that the archive exists if (!File.Exists(archivePath)) { return(null); } // Finally, open the archive so we can look insdie of it to see if it exists. VirtualFilesystemDirectory archive = ArchiveUtilities.LoadArchive(archivePath); VirtualFilesystemFile archiveFile = archive.GetFileAtPath(descriptor.ModelPath); if (archiveFile == null) { Console.WriteLine("LoadActorByName failed because the specified path \"{0}\" does not exist in archive \"{1}\"!", descriptor.ModelPath, descriptor.ArchiveName); return(null); } // Now that we finally have the file, we can try to load a J3D from it. byte[] j3dData = archiveFile.Data; J3D j3d = new J3D(archiveFile.Name); using (EndianBinaryReader reader = new EndianBinaryReader(j3dData, Endian.Big)) j3d.LoadFromStream(reader, Properties.Settings.Default.DumpTexturesToDisk, Properties.Settings.Default.DumpShadersToDisk); j3d.SetHardwareLight(0, m_mainLight); j3d.SetHardwareLight(1, m_secondaryLight); // Apply patches for Wind Waker by default, since they don't seem to break anything else. j3d.SetTextureOverride("ZBtoonEX", "resources/textures/ZBtoonEX.png"); j3d.SetTextureOverride("ZAtoon", "resources/textures/ZAtoon.png"); j3d.SetColorWriteOverride("eyeLdamA", false); j3d.SetColorWriteOverride("eyeLdamB", false); j3d.SetColorWriteOverride("mayuLdamA", false); j3d.SetColorWriteOverride("mayuLdamB", false); j3d.SetColorWriteOverride("eyeRdamA", false); j3d.SetColorWriteOverride("eyeRdamB", false); j3d.SetColorWriteOverride("mayuRdamA", false); j3d.SetColorWriteOverride("mayuRdamB", false); existRef = new TSharedRef <J3D>(); existRef.FilePath = actorName; existRef.Asset = j3d; existRef.ReferenceCount++; m_j3dList.Add(existRef); return(j3d); }
private void LoadEntities(Map newMap, EditorCore core, Dictionary <Scene, VirtualFilesystemDirectory> archiveMap, WWorld world) { MapEntityLoader entityLoader = new MapEntityLoader(core, newMap); // For each room/scene, find the associated dzr/dzs file and load its // contents into the entityLoader. foreach (var kvp in archiveMap) { // Check to see if this Archive has stage/room entity data. var roomEntData = kvp.Value.FindByExtension(".dzr"); var stageEntData = kvp.Value.FindByExtension(".dzs"); VirtualFilesystemFile vfsFile = null; if (roomEntData.Count > 0) { vfsFile = roomEntData[0]; } else if (stageEntData.Count > 0) { vfsFile = stageEntData[0]; } else { continue; } using (EndianBinaryReader reader = new EndianBinaryReader(new System.IO.MemoryStream(vfsFile.File.GetData()), Endian.Big)) { WLog.Info(LogCategory.EntityLoading, null, "Loading .dzr/.dzs (Room/Stage Entity Dat) for {0}{1}...", vfsFile.Name, vfsFile.Extension); entityLoader.LoadFromStream(kvp.Key, reader); WLog.Info(LogCategory.EntityLoading, null, "Finished loading .dzr/.dzs (Room/Stage Entity Dat) for {0}{1}.", vfsFile.Name, vfsFile.Extension); } } // Once we've loaded all of the entities from the stream, we're going to // post-process them to resolve object references. entityLoader.PostProcessEntities(); // Finally, we can actually convert these into map objects foreach (var roomOrStageData in entityLoader.GetData()) { Stage stage = roomOrStageData.Key as Stage; Room room = roomOrStageData.Key as Room; if (stage != null) { PostProcessStage(stage, roomOrStageData.Value); foreach (var entity in stage.Entities) { entity.World = world; } } if (room != null) { PostProcessRoom(room, roomOrStageData.Value); foreach (var entity in room.Entities) { entity.World = world; } } } }
private void SaveMessageData() { VirtualFilesystemFile text_bank = m_MessageArchive.GetFileAtPath("zel_00.bmg"); Encoding enc = Encoding.ASCII; switch (m_OriginalEncoding) { case TextEncoding.CP1252: enc = Encoding.GetEncoding(1252); break; case TextEncoding.Shift_JIS: enc = Encoding.GetEncoding(932); break; case TextEncoding.UTF_16: enc = Encoding.BigEndianUnicode; break; case TextEncoding.UTF_8: enc = Encoding.UTF8; break; } using (MemoryStream new_bmg_strm = new MemoryStream()) { EndianBinaryWriter bmg_writer = new EndianBinaryWriter(new_bmg_strm, Endian.Big); bmg_writer.Write("MESGbmg1".ToCharArray()); bmg_writer.Write(0); bmg_writer.Write(2); bmg_writer.Write((byte)m_OriginalEncoding); bmg_writer.Write(new byte[15]); using (MemoryStream text_data_strm = new MemoryStream()) { EndianBinaryWriter text_data_writer = new EndianBinaryWriter(text_data_strm, Endian.Big); text_data_writer.Write((byte)0); using (MemoryStream message_data_strm = new MemoryStream()) { EndianBinaryWriter message_data_writer = new EndianBinaryWriter(message_data_strm, Endian.Big); foreach (Message m in m_Messages) { m.Save(message_data_writer, text_data_writer, enc); } int delta = WMath.Pad16Delta(message_data_strm.Length); bmg_writer.Write("INF1".ToCharArray()); bmg_writer.Write((uint)(message_data_strm.Length + 16 + delta)); bmg_writer.Write((ushort)m_Messages.Count); bmg_writer.Write((ushort)0x18); bmg_writer.Write(0); bmg_writer.Write(message_data_strm.ToArray()); for (int i = 0; i < delta; i++) { bmg_writer.Write((byte)0); } } // Seek to the end of the stream, and then pad us to 32-byte alignment. text_data_strm.Seek(0, SeekOrigin.End); int pad32delta = WMath.Pad32Delta(text_data_strm.Position + 8); for (int i = 0; i < pad32delta; i++) { text_data_writer.Write((byte)0x00); } bmg_writer.Write("DAT1".ToCharArray()); bmg_writer.Write((uint)text_data_strm.Length + 8); bmg_writer.Write(text_data_strm.ToArray()); } text_bank.Data = new_bmg_strm.ToArray(); } m_IsDataDirty = false; OnPropertyChanged("WindowTitle"); }
static void GetDirectoriesRecursive(VirtualFilesystemDirectory root, string rootString) { List <string> files = new List <string>(Directory.GetFiles(rootString)); // The entries in this subdir need to be in a particular order. // We'll fill them in with null so that we can replace them later. if (Path.GetFileName(rootString).ToLowerInvariant() == "&&systemdata") { for (int i = 0; i < 4; i++) { root.Children.Add(null); } } foreach (string str in files) { string fileName = Path.GetFileNameWithoutExtension(str); string fileExt = Path.GetExtension(str); VirtualFileContents cont = new VirtualFileContents(File.ReadAllBytes(str)); VirtualFilesystemFile newFile = new VirtualFilesystemFile(fileName, fileExt, cont); string fileNameLower = fileName.ToLowerInvariant(); string fileExtLower = fileExt.ToLowerInvariant(); string fullFileName = fileNameLower + fileExtLower; // These will replace the nulls we put in &&systemdata's child list earlier. if ((fullFileName == "iso.hdr") || (fullFileName == "isoheader.hdr")) { root.Children[0] = newFile; } else if (fullFileName == "apploader.ldr") { root.Children[2] = newFile; } else if (fullFileName == "start.dol") { root.Children[1] = newFile; } else if (fullFileName == "game.toc") { root.Children[3] = newFile; } else { root.Children.Add(newFile); } } List <string> dirs = new List <string>(Directory.GetDirectories(rootString)); foreach (string str in dirs) { string dirName = Path.GetFileName(str); string dirNameLower = dirName.ToLowerInvariant(); VirtualFilesystemDirectory dir = new VirtualFilesystemDirectory(dirName); GetDirectoriesRecursive(dir, str); if (dirNameLower == "&&systemdata") { root.Children.Insert(0, dir); } else { root.Children.Add(dir); } } }
public void WriteISO(VirtualFilesystemDirectory root, string path) { using (FileStream output = new FileStream(path, FileMode.Create, FileAccess.Write)) { EndianBinaryWriter writer = new EndianBinaryWriter(output, Endian.Big); List <byte> fstNameBank = new List <byte>(); List <FSTEntry> outputFST = new List <FSTEntry>(); List <VirtualFilesystemFile> fileList = new List <VirtualFilesystemFile>(); FSTEntry rootFST = new FSTEntry(); VirtualFilesystemDirectory sysDir = (VirtualFilesystemDirectory)root.Children.SingleOrDefault(e => e.Name == "&&systemdata") ?? (VirtualFilesystemDirectory)root.Children.SingleOrDefault(e => e.Name == "sys"); VirtualFilesystemFile header = (VirtualFilesystemFile)sysDir.Children.Single(e => e is VirtualFilesystemFile && ((VirtualFilesystemFile)e).NameWithExtension == "iso.hdr"); writer.Write(header.Data); VirtualFilesystemFile apploader = (VirtualFilesystemFile)sysDir.Children.SingleOrDefault(e => e is VirtualFilesystemFile && ((VirtualFilesystemFile)e).NameWithExtension == "AppLoader.ldr") ?? (VirtualFilesystemFile)sysDir.Children.SingleOrDefault(e => e is VirtualFilesystemFile && ((VirtualFilesystemFile)e).NameWithExtension == "apploader.img"); writer.Write(apploader.Data); var dolOffsetWithoutPadding = writer.BaseStream.Position; var dolOffset = AlignTo(dolOffsetWithoutPadding, DolAlignment); for (long i = dolOffsetWithoutPadding; i < dolOffset; i++) { writer.Write((byte)0); } VirtualFilesystemFile dol = (VirtualFilesystemFile)sysDir.Children.Single(e => e is VirtualFilesystemFile && ((VirtualFilesystemFile)e).Extension == ".dol"); writer.Write(dol.Data); var fstListOffsetWithoutPadding = writer.BaseStream.Position; var fstListOffset = AlignTo(fstListOffsetWithoutPadding, FstAlignment); for (long i = fstListOffsetWithoutPadding; i < fstListOffset; i++) { writer.Write((byte)0); } int fstLength = 12; root.Children.RemoveAt(0); foreach (VirtualFilesystemNode node in root.Children) { fstLength = GetFSTSkipValue(fstLength, node); } byte[] dummyFST = new byte[fstLength]; writer.Write(dummyFST); rootFST.Type = FSTNodeType.Directory; outputFST.Add(rootFST); //Placeholder FST entry for the root foreach (VirtualFilesystemNode node in root.Children) { DoOutputPrep(node, outputFST, fstNameBank, writer, 0); } rootFST.FileSizeNextDirIndex = outputFST.Count(); outputFST[0] = rootFST; //Add actual root FST entry writer.BaseStream.Position = fstListOffset; foreach (FSTEntry entry in outputFST) { writer.Write((byte)entry.Type); writer.Write((byte)0); writer.Write((ushort)entry.FileNameOffset); writer.Write(entry.FileOffsetParentDir); writer.Write(entry.FileSizeNextDirIndex); } writer.Write(fstNameBank.ToArray()); writer.BaseStream.Position = OffsetOfDolOffset; writer.Write((uint)dolOffset); writer.Write((uint)fstListOffset); writer.Write((uint)fstLength); writer.Write((uint)fstLength); // Doesn't work for multi disks } }
public VirtualFilesystemDirectory ReadFile(EndianBinaryReader reader) { if (reader.ReadUInt32() != 0x52415243) // "RARC" { throw new InvalidDataException("Invalid Magic, not a RARC File"); } uint fileSize = reader.ReadUInt32(); reader.SkipUInt32(); // Unknown uint dataOffset = reader.ReadUInt32() + 0x20; reader.Skip(16); // Unknown - 4 unsigned ints uint numNodes = reader.ReadUInt32(); reader.Skip(8); // Unknown - 2 unsigned ints uint fileEntryOffset = reader.ReadUInt32() + 0x20; reader.SkipUInt32(); // Unknown uint stringTableOffset = reader.ReadUInt32() + 0x20; reader.Skip(8); // Unknown - 2 unsigned ints. // Read all of the node headers. Node[] nodes = new Node[numNodes]; for (int i = 0; i < numNodes; i++) { nodes[i] = new Node { Type = new string(reader.ReadChars(4)), Name = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt32()), NameHashcode = reader.ReadUInt16(), Entries = new FileEntry[reader.ReadUInt16()], FirstFileOffset = reader.ReadUInt32() }; } // Create a virtual directory for every folder within the ARC before we process any of them. List <VirtualFilesystemDirectory> allDirs = new List <VirtualFilesystemDirectory>(nodes.Length); foreach (Node node in nodes) { VirtualFilesystemDirectory vfDir = new VirtualFilesystemDirectory(node.Name); allDirs.Add(vfDir); } for (int k = 0; k < nodes.Length; k++) { Node node = nodes[k]; VirtualFilesystemDirectory curDir = allDirs[k]; for (int i = 0; i < node.Entries.Length; i++) { // Jump to the entry's offset in the file. reader.BaseStream.Position = fileEntryOffset + ((node.FirstFileOffset + i) * 0x14); // 0x14 is the size of a File Entry in bytes node.Entries[i] = new FileEntry(); node.Entries[i].ID = reader.ReadUInt16(); node.Entries[i].NameHashcode = reader.ReadUInt16(); node.Entries[i].Flags = reader.ReadByte(); reader.SkipByte(); // Padding node.Entries[i].Name = ReadStringAtOffset(reader, stringTableOffset, reader.ReadUInt16()); // Skip these ones cause I don't know how computers work. if (node.Entries[i].Name == "." || node.Entries[i].Name == "..") { continue; } uint entryDataOffset = reader.ReadUInt32(); uint dataSize = reader.ReadUInt32(); // If it's a directory, then entryDataOffset contains the index of the parent node if (node.Entries[i].IsDirectory) { node.Entries[i].SubDirIndex = entryDataOffset; var newSubDir = allDirs[(int)entryDataOffset]; newSubDir.NodeID = node.Entries[i].ID; curDir.Children.Add(newSubDir); } else { node.Entries[i].Data = reader.ReadBytesAt(dataOffset + entryDataOffset, (int)dataSize); string fileName = Path.GetFileNameWithoutExtension(node.Entries[i].Name); string extension = Path.GetExtension(node.Entries[i].Name); VirtualFilesystemFile vfFile = new VirtualFilesystemFile(fileName, extension, node.Entries[i].Data); vfFile.NodeID = node.Entries[i].ID; curDir.Children.Add(vfFile); } reader.SkipInt32(); // Padding } } // The ROOT directory should always be the first node. We don't have access to the node's TYPE anymore // so we're going to assume its always the first one listed. return(allDirs.Count > 0 ? allDirs[0] : null); }