public void ShowSaveProgress( IWin32Window owner, Stream stream, BigFile archive, IEnumerable <BigFile.Entry> saving, Dictionary <uint, string> fileNames, string basePath, SaveAllSettings settings) { SaveAllInformation info; info.BasePath = basePath; info.Stream = stream; info.Archive = archive; info.Saving = saving; info.FileNames = fileNames; info.Settings = settings; this.progressBar.Value = 0; this.progressBar.Maximum = 100; this.SaveThread = new Thread(new ParameterizedThreadStart(SaveAll)); this.SaveThread.Start(info); this.ShowDialog(owner); }
private void OnOpen(object sender, EventArgs e) { if (this.openDialog.ShowDialog() != DialogResult.OK) { return; } if (this.openDialog.InitialDirectory != null) { this.openDialog.InitialDirectory = null; } BigFile archive; using (var input = this.openDialog.OpenFile()) { archive = new BigFile(); archive.Deserialize(input); } this.Archive = archive; this.BuildFileTree(); var exists = File.Exists(Path.ChangeExtension(this.openDialog.FileName, ".dat")); this.saveAllButton.Enabled = exists; this.saveToolStripMenuItem.Enabled = exists; }
static void CheckFiles() { Console.Write("File path: "); string path = Console.ReadLine(); if (!File.Exists(path) && !Directory.Exists(path)) { Environment.Exit(69); } LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info; BigFile bigFile = BigFile.OpenBigFile(path); bigFile.LoadFromDisk(); for (int i = 0; i < bigFile.FileMap.FilesList.Length; i++) { BigFileFile file = bigFile.FileMap.FilesList[i]; if (file.FileInfo.Offset == -1) { LogManager.GlobalLogFlags = LogFlags.All; file.FileInfo.DebugLog(log); LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info; } } Console.ReadLine(); }
private void OnOpen(object sender, EventArgs e) { if (this.openDialog.ShowDialog() != DialogResult.OK) { return; } if (this.openDialog.InitialDirectory != null) { this.openDialog.InitialDirectory = null; } BigFile archive; using (var input = this.openDialog.OpenFile()) { archive = new BigFile(); archive.Deserialize(input); } this.Archive = archive; /* * TextWriter writer = new StreamWriter("all_file_hashes.txt"); * foreach (var hash in table.Keys.OrderBy(k => k)) * { * writer.WriteLine(hash.ToString("X8")); * } * writer.Close(); */ this.BuildFileTree(); }
private async void button24_Click(object sender, EventArgs e) { OpenFileDialog ofd = new OpenFileDialog(); ofd.Filter = "Crash Team Racing BIG file|*.big"; if (ofd.ShowDialog() == DialogResult.OK) { Task load = new Task(() => big = BigFile.FromFile(ofd.FileName)); load.Start(); await load; LoadBig(ofd.FileName); } }
bool IPackageLoader.TryParsePackage(Stream s, string filename, FS context, out IReadOnlyPackage package) { // Take a peek at the file signature var signature = s.ReadASCII(4); s.Position -= 4; if (signature != "BIGF") { package = null; return(false); } package = new BigFile(s, filename); return(true); }
/// <summary> /// Creates a thread and loads a bigfile on it, then calls the method provided. /// </summary> /// <param name="file"></param> /// <param name="next"></param> public static void LoadBigFileInBackground(string file, Action <BigFile> next) { BigFile bigFile = BigFile.OpenBigFile(file); ThreadStart ts = new ThreadStart (() => { bigFile.LoadFromDisk(); next?.Invoke(bigFile); }); Thread t = new Thread(ts); t.Start(); }
public void LoadBigFile() { if (isLoaded) { return; } isLoaded = true; IntegrationUtil.LoadBigFileInBackground (currentFilePath, (bigFile) => { textureMetadataFiles = bigFile.RootFolder.GetAllFilesOfArchetype <TextureMetadataFileArchetype>(); bigFile.FileLoader.LoadFiles(textureMetadataFiles); m_bigFile = bigFile; }); }
private async void LoadBigFull(string path) { if (!File.Exists(path)) { MessageBox.Show($"File doesn't exist!\r\n{path}"); return; } Task load = new Task(() => big = BigFile.FromFile(path)); load.Start(); await load; LoadBig(path); MessageBox.Show("Done."); }
static void Main(string[] args) { Console.WriteLine( "{0}\r\n{1}\r\n\r\n{2}\r\n", "CTR-tools: BigTool", "Builds and extracts Crash Team Racing BIG files", Meta.GetVersion()); if (args.Length > 0) { Console.WriteLine("Current path: " + Environment.CurrentDirectory); string ext = Path.GetExtension(args[0]).ToLower(); try { BigFile big = BigFile.FromFile(args[0]); if (big.Entries.Count > 0) { switch (ext) { case ".big": big.Export(".\\bigfile"); break; case ".txt": big.Build(".\\bigfile.big"); break; default: Console.WriteLine("{0}: {1}", "Unsupported file", ext); break; } } } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); } return; } Console.WriteLine( "{0}:\r\n\t{1}: {2}\r\n\t{3}: {4}", "Usage", "Extract example", "bigtool C:\\BIGFILE.BIG", "Build example", "bigtool C:\\BIGFILE.TXT" ); }
private static bool FileExistsInBig(string fatPath, string fileName) { if (File.Exists(fatPath) == false) { return(false); } var big = new BigFile(); using (var input = File.OpenRead(fatPath)) { big.Deserialize(input); } var entries = big.Entries.Where(e => e.NameHash == fileName.HashFileNameCRC32()); if (entries.Count() == 0) { return(false); } return(true); }
private void HandleNodeClick(object sender, EventArgs ea) { itemsList.Items.Clear(); if (filesTree.SelectedNodes.Count > 0) { var node = filesTree.SelectedNodes[0]; if (node.Tag != null) { var tag = (NodeTag)node.Tag; if (tag.FullPath.EndsWith(".big")) { BigFile bf = new BigFile(); if (bf.Read(tag.FullPath)) { //label2.Text = $"archive {Path.GetFileName(tag.FullPath)} has {bf.Entries.Count} files."; foreach (var e in bf.Entries) { DarkListItem item = new DarkListItem(e.Name); item.Tag = new ListTag() { NodeTag = tag, BigFile = bf, Entry = e }; itemsList.Items.Add(item); } } else { MessageBox.Show($"Failed reading {Path.GetFileName(tag.FullPath)} :("); } } } } }
static void Main(string[] args) { Console.WriteLine( "{0}\r\n{1}\r\n\r\n{2}\r\n", "CTR-tools: bigtool by DCxDemo*", "Builds and extracts Crash Team Racing BIG files", Meta.GetVersionInfo()); if (args.Length > 0) { Console.WriteLine("Current path: " + Environment.CurrentDirectory); string name = Path.GetFileNameWithoutExtension(args[0]).ToLower(); string ext = Path.GetExtension(args[0]).ToLower(); string bigpath = Path.GetDirectoryName(args[0]); if (!Path.IsPathRooted(args[0])) { bigpath = Environment.CurrentDirectory; if (!File.Exists(Path.Combine(bigpath, args[0]))) { bigpath = bigpath = Meta.BasePath; if (!File.Exists(Path.Combine(bigpath, args[0]))) { Console.WriteLine("Check filename."); return; } } } string path = Path.Combine(bigpath, name); try { BigFile big = BigFile.FromFile(Path.Combine(bigpath, $"{name}{ext}")); if (big.Entries.Count == 0) { Console.WriteLine("No files to process."); return; } switch (ext) { case ".big": big.Extract(path); break; case ".txt": big.Save(Path.Combine(bigpath, $"{name}.big")); break; default: Console.WriteLine($"Unsupported file type: {ext}"); break; } } catch (Exception ex) { Console.WriteLine("Error: " + ex.Message); } return; } Console.WriteLine( "{0}:\r\n\t{1}: {2}\r\n\t{3}: {4}", "Usage", "Extract example", "bigtool C:\\BIGFILE.BIG", "Build example", "bigtool C:\\BIGFILE.TXT" ); }
static void CompareAllFiles() { LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info; Console.Write("Bigfile 1: "); string path1 = Console.ReadLine(); Console.Write("Bigfile 2: "); string path2 = Console.ReadLine(); IOBuffers buffer1 = new IOBuffers(); IOBuffers buffer2 = new IOBuffers(); BigFile file1 = BigFile.OpenBigFile(path1); BigFile file2 = BigFile.OpenBigFile(path2); if (file1 == null) { Console.WriteLine("file 1 null"); Console.ReadLine(); Environment.Exit(911); } if (file2 == null) { Console.WriteLine("file 2 null"); Console.ReadLine(); Environment.Exit(911); } file1.LoadFromDisk(); Console.Write("Press enter..."); Console.ReadLine(); file2.LoadFromDisk(); Console.Write("Press enter..."); Console.ReadLine(); Console.Clear(); int missingFiles = 0; if (file1.FileMap.FilesList.Length != file2.FileMap.FilesList.Length) { Console.WriteLine("Files count don't match!"); foreach (BigFileFile file1file in file1.FileMap.FilesList) { if (file2.FileMap[file1file.FileInfo.Key] == null) { missingFiles++; Console.WriteLine("Found file {0} (key: {1:X8}) that appears in the first bigfile but not the second!", file1file.Name, file1file.FileInfo.Key); } } Console.ReadLine(); foreach (BigFileFile file2file in file2.FileMap.FilesList) { if (file1.FileMap[file2file.FileInfo.Key] == null) { missingFiles++; Console.WriteLine("Found file {0} (key: {1:X8}) that appears in the second bigfile but not the first!", file2file.Name, file2file.FileInfo.Key); } } Console.ReadLine(); } Console.WriteLine(""); Console.WriteLine("Found {0} file discrepancies between the two bigfiles", missingFiles); Console.Write("Would you like to continue? "); Console.ReadLine(); Console.Clear(); IEnumerator <int[]> headers1 = file1.FileReader.ReadAllHeaders(file1.FileMap.FilesList, buffer1, file1.FileReader.DefaultFlags).GetEnumerator(); IEnumerator <int[]> headers2 = file2.FileReader.ReadAllHeaders(file2.FileMap.FilesList, buffer1, file2.FileReader.DefaultFlags).GetEnumerator(); void CompareHeaders(BigFileFile file1file, BigFileFile file2file, int[] a, int[] b) { bool foundError = a.Length != b.Length; if (!foundError) { for (int i = 0; i < a.Length; i++) { if (a[i] != b[i]) { foundError = true; break; } } } if (foundError) { Console.WriteLine("File {0} has a header discrepancy!"); Console.WriteLine("File 1 header length: {0}", a.Length); Console.WriteLine("File 2 header length: {1}", b.Length); for (int i = 0; i < a.Length; i++) { Console.Write("{0:X8} ", a[i]); } for (int i = 0; i < b.Length; i++) { Console.Write("{0:X8} ", b[i]); } } } }
internal BigFileFileReader(BigFile _bigFile) { bigFile = _bigFile; }
static void CompareFiles() { LogManager.GlobalLogFlags = LogFlags.Error | LogFlags.Info; Console.Write("Bigfile 1: "); string path1 = Console.ReadLine(); Console.Write("Bigfile 2: "); string path2 = Console.ReadLine(); IOBuffers buffer1 = new IOBuffers(); IOBuffers buffer2 = new IOBuffers(); Console.Write("File key: "); int key = 0; key = Convert.ToInt32(Console.ReadLine(), 16); if (key == 0) { Environment.Exit(420); } BigFile file1 = BigFile.OpenBigFile(path1); BigFile file2 = BigFile.OpenBigFile(path2); if (file1 == null) { Console.WriteLine("file 1 null"); Console.ReadLine(); Environment.Exit(911); } if (file2 == null) { Console.WriteLine("file 2 null"); Console.ReadLine(); Environment.Exit(911); } file1.LoadFromDisk(); Console.Write("Press enter..."); Console.ReadLine(); file2.LoadFromDisk(); Console.Write("Press enter..."); Console.ReadLine(); BigFileFile bigFileFile1 = file1.FileMap[key]; BigFileFile bigFileFile2 = file2.FileMap[key]; int[] header1 = file1.FileReader.ReadFileHeader(bigFileFile1, buffer1, file1.FileReader.DefaultFlags); int[] header2 = file2.FileReader.ReadFileHeader(bigFileFile2, buffer2, file2.FileReader.DefaultFlags); int size1 = file1.FileReader.ReadFileRaw(bigFileFile1, buffer1, file1.FileReader.DefaultFlags); int size2 = file2.FileReader.ReadFileRaw(bigFileFile2, buffer2, file2.FileReader.DefaultFlags); int chksum1 = 0; int chksum2 = 0; for (int i = 0; i < size1; i++) { chksum1 += buffer1[size1][i]; } for (int i = 0; i < size2; i++) { chksum2 += buffer2[size2][i]; } Console.Clear(); Console.WriteLine("Size 1: " + size1); Console.WriteLine("Checksum 1: " + chksum1); Console.WriteLine("Size 2: " + size2); Console.WriteLine("Checksum 2: " + chksum2); Console.Write("Header 1, length: {0} : ", header1.Length); for (int i = 0; i < header1.Length; i++) { Console.Write("{0:X8} ", header1[i]); } Console.Write("\nHeader 2, length: {0} : ", header2.Length); for (int i = 0; i < header2.Length; i++) { Console.Write("{0:X8} ", header2[i]); } Console.WriteLine(""); LogManager.GlobalLogFlags = LogFlags.All; bigFileFile1.FileInfo.DebugLog(log); bigFileFile2.FileInfo.DebugLog(log); Console.ReadLine(); }
public static void Main(string[] args) { bool showHelp = false; bool verbose = false; bool compress = false; var options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "c|compress", "compress data with LZO1x", v => compress = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ output_fat input_directory+", GetExecutableName()); Console.WriteLine("Pack files from input directories into a Encapsulated Resource File."); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPaths = new List <string>(); string fatPath, datPath; if (extras.Count == 1) { inputPaths.Add(extras[0]); fatPath = Path.ChangeExtension(extras[0], ".fat"); datPath = Path.ChangeExtension(extras[0], ".dat"); } else { fatPath = extras[0]; if (Path.GetExtension(fatPath) != ".fat") { datPath = fatPath; fatPath = Path.ChangeExtension(datPath, ".fat"); } else { datPath = Path.ChangeExtension(fatPath, ".dat"); } inputPaths.AddRange(extras.Skip(1)); } var paths = new SortedDictionary <uint, string>(); if (verbose == true) { Console.WriteLine("Finding files..."); } foreach (var relPath in inputPaths) { string inputPath = Path.GetFullPath(relPath); if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true) { inputPath = inputPath.Substring(0, inputPath.Length - 1); } foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories)) { string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant(); uint hash = 0xFFFFFFFFu; if (partPath.ToUpper().StartsWith("__UNKNOWN") == true) { string partName; partName = Path.GetFileNameWithoutExtension(partPath); if (partName.Length > 8) { partName = partName.Substring(0, 8); } hash = uint.Parse( partName, System.Globalization.NumberStyles.AllowHexSpecifier); } else { hash = partPath.HashFileNameCRC32(); } if (paths.ContainsKey(hash) == true) { //if (verbose == true) { Console.WriteLine("Ignoring {0} duplicate.", partPath); } continue; } paths[hash] = fullPath; //Console.WriteLine(fullPath); } } var big = new BigFile(); using (var output = File.Create(datPath)) { foreach (var value in paths) { var hash = value.Key; var path = value.Value; if (verbose == true) { Console.WriteLine(path); } var entry = new Big.Entry(); entry.NameHash = hash; entry.Offset = output.Position; using (var input = File.OpenRead(path)) { if (compress == false) { entry.CompressionScheme = Big.CompressionScheme.None; entry.UncompressedSize = 0; entry.CompressedSize = (uint)input.Length; output.WriteFromStream(input, input.Length); } else { var uncompressedData = new byte[input.Length]; var uncompressedSize = (uint)uncompressedData.Length; input.Read(uncompressedData, 0, uncompressedData.Length); var compressedData = new byte[ uncompressedData.Length + (uncompressedData.Length / 16) + 64 + 3]; var compressedSize = (uint)compressedData.Length; var result = LZO1x.Compress( uncompressedData, uncompressedSize, compressedData, ref compressedSize); if (result != 0) { throw new InvalidOperationException("compression error " + result.ToString()); } if (compressedSize < uncompressedSize) { entry.CompressionScheme = Big.CompressionScheme.LZO1x; entry.UncompressedSize = uncompressedSize; entry.CompressedSize = compressedSize; output.Write(compressedData, 0, (int)compressedSize); } else { input.Seek(0, SeekOrigin.Begin); entry.CompressionScheme = Big.CompressionScheme.None; entry.UncompressedSize = 0; entry.CompressedSize = (uint)input.Length; output.WriteFromStream(input, input.Length); } } output.Seek(output.Position.Align(16), SeekOrigin.Begin); } big.Entries.Add(entry); } } using (var output = File.Create(fatPath)) { big.Serialize(output); } }
public static void Main(string[] args) { Logger = new LogConsole(null, new LogOptions() { LogTimestamp = false }); Logger.ClearPrependers(); var origVisible = Console.CursorVisible; var origWidth = Console.WindowWidth; var origHeight = Console.WindowHeight; Console.CursorVisible = false; Console.CancelKeyPress += (s, e) => { ms_isTerminating = true; e.Cancel = true; FinishWithError("User terminated execution.", true); }; if (origWidth < 160) { Console.WindowWidth = 160; } if (origHeight < 8 + 16) { Console.WindowHeight = 8 + 16; } Console.Clear(); void DrawCentered(string text, Color col) { Logger.Info(new string(' ', (Console.WindowWidth - text.Length) / 2), col); Console.WriteLine(text); } string filePath = ""; if (args.Length == 0) { TitleDraw.Welcome(Logger); DrawCentered("DR2 Format Tools - by avail (alpha)", Color.OrangeRed); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); Console.WriteLine(); DrawCentered("Drop a .big or .tex onto me to dump contents.", Color.Cyan); DrawCentered("(or drop to exe itself next time instead of launching it first)", Color.Green); Logger.Info("\t\t Input -> ", Color.Cyan); bool CheckExtension(char[] data, int len) { int readOffset = 0; if (data[0] == '"') { readOffset += 1; } if (data[len - (readOffset + 2)] == 't' && data[len - (readOffset + 1)] == 'e' && data[len - (readOffset + 0)] == 'x') { return(true); } if (data[len - (readOffset + 2)] == 'b' && data[len - (readOffset + 1)] == 'i' && data[len - (readOffset + 0)] == 'g') { return(true); } return(false); } var input = new char[256]; for (var i = 0; i < input.Length; i++) { input[i] = Console.ReadKey().KeyChar; if (i > 6 && CheckExtension(input, i)) { Console.WriteLine(); break; } } filePath = new string(input).Split('\0')[0].Replace("\"", ""); if (!File.Exists(filePath)) { FinishWithError("The file you specified isn't valid."); } } else { filePath = args[0]; var ext = Path.GetExtension(filePath); if (!File.Exists(filePath) || (ext != ".tex" && ext != ".big")) { FinishWithError("The file you specified isn't valid."); } } var bf = new BigFile(); var dumpDir = Path.Combine(AppDomain.CurrentDomain.BaseDirectory, "dump", Path.GetFileNameWithoutExtension(filePath)); bool success = bf.Read(filePath, true, dumpDir); Console.CursorVisible = origVisible; //Console.WindowWidth = origWidth; //Console.WindowHeight = origHeight; Console.Clear(); Console.SetCursorPosition(0, 0); if (success) { FinishWithSuccess(ProcessElapsed, MetadataElapsed, ExportElapsed, EntryCount); } }
public static void Main(string[] args) { bool showHelp = false; bool overwriteFiles = false; bool verbose = false; var options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_fat [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string inputPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + ".fc2map"; var map = new MapFile(); map.Info = new Map.Info(); map.Snapshot = new Map.Snapshot(); map.Data = new Map.Data(); map.Data.Unknown2 = new Map.Snapshot(); map.Archive = new Map.Archive(); using (var input = File.OpenRead(Path.Combine(inputPath, "map.xml"))) { var doc = new XPathDocument(input); var nav = doc.CreateNavigator(); var info = nav.SelectSingleNode("/map/info"); map.Info.Name = info.SelectSingleNode("name").Value; map.Info.Creator = info.SelectSingleNode("creator").Value; map.Info.Author = info.SelectSingleNode("author").Value; map.Info.Size = (Map.Size)Enum.Parse(typeof(Map.Size), info.SelectSingleNode("size").Value); map.Info.Players = (Map.Players)Enum.Parse(typeof(Map.Players), info.SelectSingleNode("players").Value); map.Info.Unknown2 = uint.Parse(info.SelectSingleNode("unknown2").Value, CultureInfo.InvariantCulture); map.Info.Unknown3 = uint.Parse(info.SelectSingleNode("unknown3").Value, CultureInfo.InvariantCulture); map.Info.Unknown4 = uint.Parse(info.SelectSingleNode("unknown4").Value, CultureInfo.InvariantCulture); map.Info.Unknown5 = ulong.Parse(info.SelectSingleNode("unknown5").Value, CultureInfo.InvariantCulture); map.Info.Unknown7 = ulong.Parse(info.SelectSingleNode("unknown7").Value, CultureInfo.InvariantCulture); map.Info.Unknown10 = ulong.Parse(info.SelectSingleNode("unknown10").Value, CultureInfo.InvariantCulture); using (var reader = new XmlTextReader(new StringReader(info.SelectSingleNode("unknown11").OuterXml))) { reader.MoveToContent(); map.Info.Unknown11 = new byte[0]; int read = 0; do { Array.Resize(ref map.Info.Unknown11, map.Info.Unknown11.Length + 4096); read += reader.ReadBinHex(map.Info.Unknown11, read, 4096); }while (reader.EOF == false); Array.Resize(ref map.Info.Unknown11, read); } using (var reader = new XmlTextReader(new StringReader(info.SelectSingleNode("unknown12").OuterXml))) { reader.MoveToContent(); map.Info.Unknown12 = new byte[0]; int read = 0; do { Array.Resize(ref map.Info.Unknown12, map.Info.Unknown12.Length + 4096); read += reader.ReadBinHex(map.Info.Unknown12, read, 4096); }while (reader.EOF == false); Array.Resize(ref map.Info.Unknown12, read); } map.Info.Unknown15 = uint.Parse(info.SelectSingleNode("unknown15").Value, CultureInfo.InvariantCulture); var snapshot = nav.SelectSingleNode("/map/snapshot"); map.Snapshot.Width = uint.Parse(snapshot.SelectSingleNode("width").Value, CultureInfo.InvariantCulture); map.Snapshot.Height = uint.Parse(snapshot.SelectSingleNode("height").Value, CultureInfo.InvariantCulture); map.Snapshot.BytesPerPixel = uint.Parse(snapshot.SelectSingleNode("bpp").Value, CultureInfo.InvariantCulture); map.Snapshot.Unknown4 = uint.Parse(snapshot.SelectSingleNode("unknown4").Value, CultureInfo.InvariantCulture); var data = nav.SelectSingleNode("/map/data"); map.Data.Unknown1 = data.SelectSingleNode("unknown1").Value; } using (var input = File.OpenRead(Path.Combine(inputPath, "snapshot.bin"))) { map.Snapshot.Data = new byte[input.Length]; input.Read(map.Snapshot.Data, 0, map.Snapshot.Data.Length); } var paths = new SortedDictionary <uint, string>(); if (verbose == true) { Console.WriteLine("Finding files..."); } var dataPath = Path.Combine(inputPath, "archive"); dataPath = Path.GetFullPath(dataPath); if (dataPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true) { dataPath = dataPath.Substring(0, dataPath.Length - 1); } foreach (string path in Directory.GetFiles(dataPath, "*", SearchOption.AllDirectories)) { string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(dataPath.Length + 1).ToLowerInvariant(); uint hash = 0xFFFFFFFFu; if (partPath.ToUpper().StartsWith("__UNKNOWN") == true) { string partName; partName = Path.GetFileNameWithoutExtension(partPath); if (partName.Length > 8) { partName = partName.Substring(0, 8); } hash = uint.Parse( partName, System.Globalization.NumberStyles.AllowHexSpecifier); } else { hash = partPath.HashFileNameCRC32(); } if (paths.ContainsKey(hash) == true) { continue; } paths[hash] = fullPath; } var big = new BigFile(); using (var output = new MemoryStream()) { foreach (var value in paths) { var hash = value.Key; var path = value.Value; if (verbose == true) { Console.WriteLine(path); } var entry = new Big.Entry(); entry.NameHash = hash; entry.Offset = output.Position; using (var input = File.OpenRead(path)) { entry.CompressionScheme = Big.CompressionScheme.None; entry.UncompressedSize = 0; entry.CompressedSize = (uint)input.Length; output.WriteFromStream(input, input.Length); } big.Entries.Add(entry); } map.Archive.DAT = MakeCompressedData(output); } using (var output = new MemoryStream()) { big.Serialize(output); map.Archive.FAT = MakeCompressedData(output); } using (var output = new MemoryStream()) { var settings = new XmlWriterSettings(); settings.Indent = true; settings.OmitXmlDeclaration = true; settings.IndentChars = "\t"; settings.Encoding = Encoding.ASCII; using (var writer = XmlWriter.Create(output, settings)) { writer.WriteStartDocument(); writer.WriteStartElement("FatInfo"); foreach (var entry in big.Entries.OrderBy(e => e.NameHash)) { writer.WriteStartElement("File"); writer.WriteAttributeString("Path", entry.NameHash.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("Crc", entry.NameHash.ToString(CultureInfo.InvariantCulture)); writer.WriteAttributeString("FileTime", "0"); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndDocument(); } output.Position = 0; map.Archive.XML = MakeCompressedData(output); } using (var output = File.Create(outputPath)) { map.Serialize(output); } }
private static bool GetEntryName(Stream input, BigFile fat, Big.Entry entry, ProjectData.HashList <uint> hashes, bool extractUnknowns, bool onlyUnknowns, out string entryName) { entryName = hashes[entry.NameHash]; if (entryName == null) { if (extractUnknowns == false) { return(false); } string type; string extension; { var guess = new byte[64]; int read = 0; if (entry.CompressionScheme == Big.CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); read = input.Read(guess, 0, (int)Math.Min(entry.CompressedSize, guess.Length)); } } else { using (var temp = new MemoryStream()) { EntryDecompression.Decompress(entry, input, temp); temp.Position = 0; read = temp.Read(guess, 0, (int)Math.Min(temp.Length, guess.Length)); } } var tuple = FileDetection.Detect(guess, Math.Min(guess.Length, read)); type = tuple != null ? tuple.Item1 : "unknown"; extension = tuple != null ? tuple.Item2 : null; } entryName = entry.NameHash.ToString("X8"); if (string.IsNullOrEmpty(extension) == false) { entryName = Path.ChangeExtension(entryName, "." + extension); } if (string.IsNullOrEmpty(type) == false) { entryName = Path.Combine(type, entryName); } entryName = Path.Combine("__UNKNOWN", entryName); } else { if (onlyUnknowns == true) { return(false); } entryName = FilterEntryName(entryName); } return(true); }
public static void Main(string[] args) { bool showHelp = false; string currentProject = null; var options = new OptionSet() { { "h|help", "show this message and exit", v => showHelp = v != null }, { "p|project=", "override current project", v => currentProject = v }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count != 0 || showHelp) { Console.WriteLine("Usage: {0} [OPTIONS]+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } Console.WriteLine("Loading project..."); var manager = Manager.Load(currentProject); if (manager.ActiveProject == null) { Console.WriteLine("Nothing to do: no active project loaded."); return; } var project = manager.ActiveProject; var version = -1; HashList <uint> knownHashes = null; var installPath = project.InstallPath; var listsPath = project.ListsPath; if (installPath == null) { Console.WriteLine("Could not detect install path."); return; } if (listsPath == null) { Console.WriteLine("Could not detect lists path."); return; } Console.WriteLine("Searching for .fat archives in game directory..."); var fatPaths = new List <string>(); fatPaths.AddRange(Directory.GetFiles(installPath, "*.fat", SearchOption.AllDirectories)); var outputPaths = new List <string>(); var breakdown = new Breakdown(); var tracking = new Tracking(); Console.WriteLine("Processing..."); for (int i = 0; i < fatPaths.Count; i++) { var fatPath = fatPaths[i]; var outputPath = GetListPath(installPath, fatPath); if (outputPath == null) { throw new InvalidOperationException(); } Console.WriteLine("Found file: " + outputPath); outputPath = Path.Combine(listsPath, outputPath); if (outputPaths.Contains(outputPath)) { throw new InvalidOperationException(); } outputPaths.Add(outputPath); if (File.Exists(fatPath + ".bak")) { fatPath += ".bak"; } var fat = new BigFile(); using (var input = File.OpenRead(fatPath)) { fat.Deserialize(input); } if (version == -1) { version = fat.Version; knownHashes = manager.LoadListsFileNames(fat.Version); } else if (version != fat.Version) { throw new InvalidOperationException(); } if (knownHashes == null) { throw new InvalidOperationException(); } HandleEntries(fat.Entries.Select(e => e.NameHash).Distinct(), knownHashes, tracking, breakdown, outputPath); } using (var output = new StreamWriter(Path.Combine(Path.Combine(listsPath, "files"), "status.txt"))) { output.WriteLine("{0}", new Breakdown() { Known = tracking.Names.Distinct().Count(), Total = tracking.Hashes.Distinct().Count(), }); } }
private static void Main(string[] args) { bool showHelp = false; bool verbose = false; bool compress = false; int packageVersion = 9; Big.Platform packagePlatform = Big.Platform.PC; var options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "c|compress", "compress data with LZO1x", v => compress = v != null }, { "pv|package-version", "package version (default 9)", v => packageVersion = ParsePackageVersion(v) }, { "pp|package-platform", "package platform (default PC)", v => packagePlatform = ParsePackagePlatform(v) }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ output_fat input_directory+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Pack files from input directories into a Big File (FAT/DAT pair)."); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPaths = new List <string>(); string fatPath, datPath; if (extras.Count == 1) { inputPaths.Add(extras[0]); fatPath = Path.ChangeExtension(extras[0], ".fat"); datPath = Path.ChangeExtension(extras[0], ".dat"); } else { fatPath = extras[0]; if (Path.GetExtension(fatPath) != ".fat") { datPath = fatPath; fatPath = Path.ChangeExtension(datPath, ".fat"); } else { datPath = Path.ChangeExtension(fatPath, ".dat"); } inputPaths.AddRange(extras.Skip(1)); } var pendingEntries = new SortedDictionary <ulong, PendingEntry>(); if (verbose == true) { Console.WriteLine("Finding files..."); } foreach (var relativePath in inputPaths) { string inputPath = Path.GetFullPath(relativePath); if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString(CultureInfo.InvariantCulture)) == true) { inputPath = inputPath.Substring(0, inputPath.Length - 1); } foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories)) { PendingEntry pendingEntry; string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant(); pendingEntry.FullPath = fullPath; pendingEntry.PartPath = partPath; var pieces = partPath.Split(Path.DirectorySeparatorChar, Path.AltDirectorySeparatorChar); int index = 0; if (index >= pieces.Length) { continue; } if (pieces[index].ToUpperInvariant() == "__SUBFAT") { Console.WriteLine("Sorry, packing of subfats is not currently implemented."); return; } if (index >= pieces.Length) { continue; } if (pieces[index].ToUpperInvariant() == "__UNKNOWN") { var partName = Path.GetFileNameWithoutExtension(partPath); if (string.IsNullOrEmpty(partName) == true) { continue; } if (partName.Length > 16) { partName = partName.Substring(0, 16); } pendingEntry.Name = null; pendingEntry.NameHash = ulong.Parse(partName, NumberStyles.AllowHexSpecifier); } else { pendingEntry.Name = string.Join("\\", pieces.Skip(index).ToArray()).ToLowerInvariant(); pendingEntry.NameHash = CRC64.Hash(pendingEntry.Name); } if (pendingEntries.ContainsKey(pendingEntry.NameHash) == true) { Console.WriteLine("Ignoring duplicate of {0:X}: {1}", pendingEntry.NameHash, partPath); if (verbose == true) { Console.WriteLine(" Previously added from: {0}", pendingEntries[pendingEntry.NameHash].PartPath); } continue; } pendingEntries[pendingEntry.NameHash] = pendingEntry; } } var fat = new BigFile { Version = packageVersion, Platform = packagePlatform }; // reasonable default? // need to figure out what this value actually does if (packagePlatform == Big.Platform.PC) { fat.Unknown74 = 3; } else if (packagePlatform == Big.Platform.PS3 || packagePlatform == Big.Platform.X360) { fat.Unknown74 = 4; } else { throw new InvalidOperationException(); } using (var output = File.Create(datPath)) { long current = 0; long total = pendingEntries.Count; var padding = total.ToString(CultureInfo.InvariantCulture).Length; foreach (var pendingEntry in pendingEntries.Select(kv => kv.Value)) { current++; if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current.ToString(CultureInfo.InvariantCulture).PadLeft(padding), total, pendingEntry.PartPath); } var entry = new Big.Entry(); entry.NameHash = pendingEntry.NameHash; entry.Offset = output.Position; using (var input = File.OpenRead(pendingEntry.FullPath)) { EntryCompression.Compress(fat.Platform, ref entry, input, compress, output); output.Seek(output.Position.Align(16), SeekOrigin.Begin); } fat.Entries.Add(entry); } } using (var output = File.Create(fatPath)) { fat.Serialize(output); } }
private static bool UnpackFileFromBig(string fatPath, string fileName, string outputPath) { var datPath = Path.ChangeExtension(fatPath, ".dat"); if (File.Exists(fatPath) == false || File.Exists(datPath) == false) { return(false); } var big = new BigFile(); using (var input = File.OpenRead(fatPath)) { big.Deserialize(input); } var entries = big.Entries.Where(e => e.NameHash == fileName.HashFileNameCRC32()); if (entries.Count() == 0) { return(false); } var entry = entries.First(); using (var input = File.OpenRead(datPath)) { using (var output = File.Create(outputPath)) { if (entry.CompressionScheme == Big.CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); output.WriteFromStream(input, entry.CompressedSize); } } else if (entry.CompressionScheme == Big.CompressionScheme.LZO1x) { if (entry.UncompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); var compressedData = new byte[entry.CompressedSize]; if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length) { throw new EndOfStreamException(); } var uncompressedData = new byte[entry.UncompressedSize]; int uncompressedSize = (int)entry.UncompressedSize; var result = MiniLZO.LZO.DecompressSafe( compressedData, 0, (int)entry.CompressedSize, uncompressedData, 0, ref uncompressedSize); if (result != MiniLZO.ErrorCode.Success) { throw new InvalidOperationException("decompression error: " + result.ToString()); } else if (uncompressedSize != entry.UncompressedSize) { throw new InvalidOperationException("did not decompress correct amount of data"); } output.Write(uncompressedData, 0, uncompressedData.Length); } } else { throw new NotSupportedException(); } } } return(true); }
public static void Main(string[] args) { bool showHelp = false; string currentProject = null; var options = new OptionSet() { { "h|help", "show this message and exit", v => showHelp = v != null }, { "p|project=", "override current project", v => currentProject = v }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count != 0 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } Console.WriteLine("Loading project..."); var manager = Manager.Load(currentProject); if (manager.ActiveProject == null) { Console.WriteLine("Nothing to do: no active project loaded."); return; } var project = manager.ActiveProject; var version = -1; HashList <ulong> knownHashes = null; HashList <ulong> subFatHashes = null; var installPath = project.InstallPath; var listsPath = project.ListsPath; if (installPath == null) { Console.WriteLine("Could not detect install path."); return; } if (listsPath == null) { Console.WriteLine("Could not detect lists path."); return; } Console.WriteLine("Searching for archives..."); var fatPaths = new List <string>(); fatPaths.AddRange(Directory.GetFiles(installPath, "*.fat", SearchOption.AllDirectories)); var outputPaths = new List <string>(); var breakdown = new Breakdown(); var tracking = new Tracking(); Console.WriteLine("Processing..."); for (int i = 0; i < fatPaths.Count; i++) { var fatPath = fatPaths[i]; var datPath = Path.ChangeExtension(fatPath, ".dat"); var outputPath = GetListPath(installPath, fatPath); if (outputPath == null) { throw new InvalidOperationException(); } Console.WriteLine(outputPath); outputPath = Path.Combine(listsPath, outputPath); if (outputPaths.Contains(outputPath) == true) { throw new InvalidOperationException(); } outputPaths.Add(outputPath); if (File.Exists(fatPath + ".bak") == true) { fatPath += ".bak"; datPath += ".bak"; } var fat = new BigFile(); using (var input = File.OpenRead(fatPath)) { fat.Deserialize(input); } if (version == -1) { version = fat.Version; knownHashes = manager.LoadListsFileNames(fat.Version); subFatHashes = manager.LoadListsSubFatNames(fat.Version); } else if (version != fat.Version) { throw new InvalidOperationException(); } if (knownHashes == null || subFatHashes == null) { throw new InvalidOperationException(); } HandleEntries(fat.Entries.Select(e => e.NameHash).Distinct(), knownHashes, tracking, breakdown, outputPath); using (var input = File.OpenRead(datPath)) { foreach (var headerEntry in fat.Entries.Where(e => subFatHashes.Contains(e.NameHash) == true)) { var subFat = new SubFatFile(); using (var temp = new MemoryStream()) { Big.EntryDecompression.Decompress(headerEntry, input, temp); temp.Position = 0; subFat.Deserialize(temp, fat); } var matchingSubFats = fat.SubFats .Where(sf => subFat.Entries.SequenceEqual(sf.Entries)) .ToArray(); if (matchingSubFats.Length == 0) { continue; } if (matchingSubFats.Length > 1) { throw new InvalidOperationException(); } var subfatPath = GetListPath(installPath, fatPath, FilterEntryName(subFatHashes[headerEntry.NameHash])); if (subfatPath == null) { throw new InvalidOperationException(); } Console.WriteLine(subfatPath); subfatPath = Path.Combine(listsPath, subfatPath); HandleEntries(subFat.Entries.Select(e => e.NameHash), knownHashes, tracking, breakdown, subfatPath); } } } using (var output = new StreamWriter(Path.Combine(Path.Combine(listsPath, "files"), "status.txt"))) { output.WriteLine("{0}", new Breakdown() { Known = tracking.Names.Distinct().Count(), Total = tracking.Hashes.Distinct().Count(), }); } }
public static void Main(string[] args) { bool showHelp = false; bool extractUnknowns = true; bool noArt = true; bool overwriteFiles = false; bool verbose = false; var options = new OptionSet() { { "o|overwrite", "overwrite existing files", v => overwriteFiles = v != null }, { "na|no-art", "don't extract art files (textures, models, etc)", v => noArt = v != null }, { "nu|no-unknowns", "don't extract unknown files", v => extractUnknowns = v == null }, { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_fat [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string fatPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(fatPath, null) + "_unpack"; string datPath; if (Path.GetExtension(fatPath) == ".dat") { datPath = fatPath; fatPath = Path.ChangeExtension(fatPath, ".fat"); } else { datPath = Path.ChangeExtension(fatPath, ".dat"); } var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Warning: no active project loaded."); } var hashes = manager.LoadLists( "*.filelist", s => s.HashFileNameCRC32(), s => s.ToLowerInvariant()); var big = new BigFile(); using (var input = File.OpenRead(fatPath)) { big.Deserialize(input); } using (var input = File.OpenRead(datPath)) { long current = 0; long total = big.Entries.Count; foreach (var entry in big.Entries) { current++; string name = hashes[entry.NameHash]; if (name == null) { if (extractUnknowns == false) { continue; } string extension; // detect type { var guess = new byte[64]; int read = 0; if (entry.CompressionScheme == CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); read = input.Read(guess, 0, (int)Math.Min( entry.CompressedSize, guess.Length)); } } else if (entry.CompressionScheme == CompressionScheme.LZO1x) { input.Seek(entry.Offset, SeekOrigin.Begin); var compressedData = new byte[entry.CompressedSize]; if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length) { throw new EndOfStreamException(); } var uncompressedData = new byte[entry.UncompressedSize]; uint uncompressedSize = entry.UncompressedSize; var result = LZO1x.Decompress( compressedData, entry.CompressedSize, uncompressedData, ref uncompressedSize); if (result != 0) { throw new InvalidOperationException("decompression error: " + result.ToString()); } else if (uncompressedSize != entry.UncompressedSize) { throw new InvalidOperationException("did not decompress correct amount of data"); } Array.Copy(uncompressedData, 0, guess, 0, Math.Min(guess.Length, uncompressedData.Length)); read = uncompressedData.Length; } else { throw new NotSupportedException(); } extension = FileExtensions.Detect(guess, Math.Min(guess.Length, read)); } name = entry.NameHash.ToString("X8"); name = Path.ChangeExtension(name, "." + extension); name = Path.Combine(extension, name); name = Path.Combine("__UNKNOWN", name); } else { name = name.Replace("/", "\\"); if (name.StartsWith("\\") == true) { name = name.Substring(1); } } if (noArt == true) { var ext = Path.GetExtension(name); if (ext == ".xbt" || ext == ".xbg" || ext == ".xbm" || ext == ".spk" || ext == ".mab" || ext == ".lfe" || ext == ".lfa" || ext == ".rtx" || ext == ".apm") { continue; } } var entryPath = Path.Combine(outputPath, name); Directory.CreateDirectory(Path.GetDirectoryName(entryPath)); if (overwriteFiles == false && File.Exists(entryPath) == true) { continue; } if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current, total, name); } using (var output = File.Create(entryPath)) { if (entry.CompressionScheme == CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); output.WriteFromStream(input, entry.CompressedSize); } } else if (entry.CompressionScheme == CompressionScheme.LZO1x) { if (entry.UncompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); var compressedData = new byte[entry.CompressedSize]; if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length) { throw new EndOfStreamException(); } var uncompressedData = new byte[entry.UncompressedSize]; uint uncompressedSize = entry.UncompressedSize; var result = LZO1x.Decompress( compressedData, entry.CompressedSize, uncompressedData, ref uncompressedSize); if (result != 0) { throw new InvalidOperationException("decompression error: " + result.ToString()); } else if (uncompressedSize != entry.UncompressedSize) { throw new InvalidOperationException("did not decompress correct amount of data"); } output.Write(uncompressedData, 0, uncompressedData.Length); } } else { throw new NotSupportedException(); } } } } }
public static void Main(string[] args) { bool showHelp = false; bool extractUnknowns = true; bool onlyUnknowns = false; bool extractFiles = true; string filterPattern = null; bool overwriteFiles = false; bool verbose = false; var options = new OptionSet() { { "o|overwrite", "overwrite existing files", v => overwriteFiles = v != null }, { "nf|no-files", "don't extract files", v => extractFiles = v == null }, { "nu|no-unknowns", "don't extract unknown files", v => extractUnknowns = v == null }, { "ou|only-unknowns", "only extract unknown files", v => onlyUnknowns = v != null }, { "f|filter=", "only extract files using pattern", v => filterPattern = v }, { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_fat [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Unpack files from a Big File (FAT/DAT pair)."); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string fatPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(fatPath, null) + "_unpack"; string datPath; Regex filter = null; if (string.IsNullOrEmpty(filterPattern) == false) { filter = new Regex(filterPattern, RegexOptions.Compiled | RegexOptions.IgnoreCase); } if (Path.GetExtension(fatPath) == ".dat") { datPath = fatPath; fatPath = Path.ChangeExtension(fatPath, ".fat"); } else { datPath = Path.ChangeExtension(fatPath, ".dat"); } if (verbose == true) { Console.WriteLine("Loading project..."); } var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Warning: no active project loaded."); } if (verbose == true) { Console.WriteLine("Reading FAT..."); } BigFile fat; using (var input = File.OpenRead(fatPath)) { fat = new BigFile(); fat.Deserialize(input); } var hashes = manager.LoadListsFileNames(fat.Version); using (var input = File.OpenRead(datPath)) { if (extractFiles == true) { Big.Entry[] entries = fat.Entries.OrderBy(e => e.Offset).ToArray(); if (entries.Length > 0) { if (verbose == true) { Console.WriteLine("Unpacking files..."); } long current = 0; long total = entries.Length; var padding = total.ToString(CultureInfo.InvariantCulture).Length; var duplicates = new Dictionary <ulong, int>(); foreach (var entry in entries) { current++; string entryName; if (GetEntryName(input, fat, entry, hashes, extractUnknowns, onlyUnknowns, out entryName) == false) { continue; } if (duplicates.ContainsKey(entry.NameHash) == true) { var number = duplicates[entry.NameHash]++; var e = Path.GetExtension(entryName); var nn = Path.ChangeExtension( Path.ChangeExtension(entryName, null) + "__DUPLICATE_" + number.ToString(CultureInfo.InvariantCulture), e); entryName = Path.Combine("__DUPLICATE", nn); } else { duplicates[entry.NameHash] = 0; } if (filter != null && filter.IsMatch(entryName) == false) { continue; } var entryPath = Path.Combine(outputPath, entryName); if (overwriteFiles == false && File.Exists(entryPath) == true) { continue; } if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current.ToString(CultureInfo.InvariantCulture).PadLeft(padding), total, entryName); } input.Seek(entry.Offset, SeekOrigin.Begin); var entryParent = Path.GetDirectoryName(entryPath); if (string.IsNullOrEmpty(entryParent) == false) { Directory.CreateDirectory(entryParent); } using (var output = File.Create(entryPath)) { EntryDecompression.Decompress(entry, input, output); } } } } } }
public BigFileFileLoader(BigFile _bigFile) { bigFile = _bigFile; }
public static void Main(string[] args) { bool showHelp = false; var options = new OptionSet() { { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count != 0 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } Console.WriteLine("Loading project..."); var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Nothing to do: no active project loaded."); return; } var project = manager.ActiveProject; var hashes = project.LoadLists( "*.filelist", s => s.HashFileNameCRC32(), s => s.ToLowerInvariant()); var installPath = project.InstallPath; var listsPath = project.ListsPath; if (installPath == null) { Console.WriteLine("Could not detect install path."); return; } else if (listsPath == null) { Console.WriteLine("Could not detect lists path."); return; } Console.WriteLine("Searching for archives..."); var inputPaths = new List <string>(); inputPaths.AddRange(Directory.GetFiles(installPath, "*.fat", SearchOption.AllDirectories)); var outputPaths = new List <string>(); Console.WriteLine("Processing..."); foreach (var inputPath in inputPaths) { // f**k you, colliding fat *g* if (Path.GetFileNameWithoutExtension(inputPath).ToLowerInvariant() == "shadersobj") { continue; } var outputPath = GetListPath(installPath, inputPath); if (outputPath == null) { throw new InvalidOperationException(); } Console.WriteLine(outputPath); outputPath = Path.Combine(listsPath, outputPath); if (outputPaths.Contains(outputPath) == true) { throw new InvalidOperationException(); } outputPaths.Add(outputPath); var big = new BigFile(); if (File.Exists(inputPath + ".bak") == true) { using (var input = File.OpenRead(inputPath + ".bak")) { big.Deserialize(input); } } else { using (var input = File.OpenRead(inputPath)) { big.Deserialize(input); } } var localBreakdown = new Breakdown(); var names = new List <string>(); foreach (var entry in big.Entries) { if (entry.UncompressedSize == 4680308) { } var name = hashes[entry.NameHash]; if (name != null) { if (names.Contains(name) == false) { names.Add(name); localBreakdown.Known++; } } localBreakdown.Total++; } names.Sort(); Directory.CreateDirectory(Path.GetDirectoryName(outputPath)); using (var output = new StreamWriter(outputPath)) { output.WriteLine("; {0}", localBreakdown); foreach (string name in names) { output.WriteLine(name); } } } }
public static void Main(string[] args) { bool showHelp = false; bool overwriteFiles = false; bool verbose = false; var options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || extras.Count > 2 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ input_fat [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string inputPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_unpack"; var manager = ProjectData.Manager.Load(); if (manager.ActiveProject == null) { Console.WriteLine("Warning: no active project loaded."); } var hashes = manager.LoadLists( "*.filelist", s => s.HashFileNameCRC32(), s => s.ToLowerInvariant()); var map = new MapFile(); using (var input = File.OpenRead(inputPath)) { map.Deserialize(input); } Directory.CreateDirectory(outputPath); using (var output = File.Create(Path.Combine(outputPath, "map.xml"))) { var settings = new XmlWriterSettings(); settings.Indent = true; using (var writer = XmlWriter.Create(output, settings)) { writer.WriteStartDocument(); writer.WriteStartElement("map"); writer.WriteStartElement("info"); writer.WriteElementString("name", map.Info.Name); writer.WriteElementString("creator", map.Info.Creator); writer.WriteElementString("author", map.Info.Author); writer.WriteElementString("size", map.Info.Size.ToString()); writer.WriteElementString("players", map.Info.Players.ToString()); writer.WriteElementString("unknown2", map.Info.Unknown2.ToString()); writer.WriteElementString("unknown3", map.Info.Unknown3.ToString()); writer.WriteElementString("unknown4", map.Info.Unknown4.ToString()); writer.WriteElementString("unknown5", map.Info.Unknown5.ToString()); writer.WriteElementString("unknown7", map.Info.Unknown7.ToString()); writer.WriteElementString("unknown10", map.Info.Unknown10.ToString()); writer.WriteStartElement("unknown11"); writer.WriteBinHex(map.Info.Unknown11, 0, map.Info.Unknown11.Length); writer.WriteEndElement(); writer.WriteStartElement("unknown12"); writer.WriteBinHex(map.Info.Unknown12, 0, map.Info.Unknown12.Length); writer.WriteEndElement(); writer.WriteElementString("unknown15", map.Info.Unknown15.ToString()); writer.WriteEndElement(); writer.WriteStartElement("snapshot"); writer.WriteElementString("width", map.Snapshot.Width.ToString()); writer.WriteElementString("height", map.Snapshot.Height.ToString()); writer.WriteElementString("bpp", map.Snapshot.BytesPerPixel.ToString()); writer.WriteElementString("unknown4", map.Snapshot.Unknown4.ToString()); writer.WriteEndElement(); writer.WriteStartElement("data"); writer.WriteElementString("unknown1", map.Data.Unknown1); writer.WriteEndElement(); writer.WriteEndElement(); writer.WriteEndDocument(); } } using (var input = map.Archive.XML.Unpack()) { using (var output = File.Create(Path.Combine(outputPath, "archive.xml"))) { output.WriteFromStream(input, input.Length); } } using (var output = File.Create(Path.Combine(outputPath, "snapshot.bin"))) { output.Write(map.Snapshot.Data, 0, map.Snapshot.Data.Length); } var big = new BigFile(); using (var input = map.Archive.FAT.Unpack()) { big.Deserialize(input); } var dataPath = Path.Combine(outputPath, "archive"); Directory.CreateDirectory(dataPath); using (var input = map.Archive.DAT.Unpack()) { long current = 0; long total = big.Entries.Count; foreach (var entry in big.Entries) { current++; string name = hashes[entry.NameHash]; if (name == null) { string extension; // detect type { var guess = new byte[64]; int read = 0; if (entry.CompressionScheme == CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); read = input.Read(guess, 0, (int)Math.Min( entry.CompressedSize, guess.Length)); } } else if (entry.CompressionScheme == CompressionScheme.LZO1x) { input.Seek(entry.Offset, SeekOrigin.Begin); var compressedData = new byte[entry.CompressedSize]; if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length) { throw new EndOfStreamException(); } var uncompressedData = new byte[entry.UncompressedSize]; uint uncompressedSize = entry.UncompressedSize; var result = LZO1x.Decompress( compressedData, entry.CompressedSize, uncompressedData, ref uncompressedSize); if (result != 0) { throw new InvalidOperationException("decompression error: " + result.ToString()); } else if (uncompressedSize != entry.UncompressedSize) { throw new InvalidOperationException("did not decompress correct amount of data"); } Array.Copy(uncompressedData, 0, guess, 0, Math.Min(guess.Length, uncompressedData.Length)); read = uncompressedData.Length; } else { throw new NotSupportedException(); } extension = FileExtensions.Detect(guess, Math.Min(guess.Length, read)); } name = entry.NameHash.ToString("X8"); name = Path.ChangeExtension(name, "." + extension); name = Path.Combine(extension, name); name = Path.Combine("__UNKNOWN", name); } else { name = name.Replace("/", "\\"); if (name.StartsWith("\\") == true) { name = name.Substring(1); } } var entryPath = Path.Combine(dataPath, name); Directory.CreateDirectory(Path.GetDirectoryName(entryPath)); if (overwriteFiles == false && File.Exists(entryPath) == true) { continue; } if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current, total, name); } using (var output = File.Create(entryPath)) { if (entry.CompressionScheme == CompressionScheme.None) { if (entry.CompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); output.WriteFromStream(input, entry.CompressedSize); } } else if (entry.CompressionScheme == CompressionScheme.LZO1x) { if (entry.UncompressedSize > 0) { input.Seek(entry.Offset, SeekOrigin.Begin); var compressedData = new byte[entry.CompressedSize]; if (input.Read(compressedData, 0, compressedData.Length) != compressedData.Length) { throw new EndOfStreamException(); } var uncompressedData = new byte[entry.UncompressedSize]; uint uncompressedSize = entry.UncompressedSize; var result = LZO1x.Decompress( compressedData, entry.CompressedSize, uncompressedData, ref uncompressedSize); if (result != 0) { throw new InvalidOperationException("decompression error: " + result.ToString()); } else if (uncompressedSize != entry.UncompressedSize) { throw new InvalidOperationException("did not decompress correct amount of data"); } output.Write(uncompressedData, 0, uncompressedData.Length); } } else { throw new NotSupportedException(); } } } } }
public static void Main(string[] args) { bool showHelp = false; bool verbose = false; OptionSet options = new OptionSet() { { "v|verbose", "be verbose (list files)", v => verbose = v != null }, { "h|help", "show this message and exit", v => showHelp = v != null }, }; List <string> extras; try { extras = options.Parse(args); } catch (OptionException e) { Console.Write("{0}: ", GetExecutableName()); Console.WriteLine(e.Message); Console.WriteLine("Try `{0} --help' for more information.", GetExecutableName()); return; } if (extras.Count < 1 || showHelp == true) { Console.WriteLine("Usage: {0} [OPTIONS]+ output_big input_directory+", GetExecutableName()); Console.WriteLine("Pack files from input directories into a Big File."); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPaths = new List <string>(); string outputPath; if (extras.Count == 1) { inputPaths.Add(extras[0]); outputPath = Path.ChangeExtension(extras[0], ".viv"); } else { outputPath = extras[0]; inputPaths.AddRange(extras.Skip(1)); } var paths = new SortedDictionary <uint, string>(); if (verbose == true) { Console.WriteLine("Finding files..."); } foreach (var relPath in inputPaths) { string inputPath = Path.GetFullPath(relPath); if (inputPath.EndsWith(Path.DirectorySeparatorChar.ToString()) == true) { inputPath = inputPath.Substring(0, inputPath.Length - 1); } foreach (string path in Directory.GetFiles(inputPath, "*", SearchOption.AllDirectories)) { string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1).ToLowerInvariant(); uint hash = 0xFFFFFFFF; if (partPath.ToUpper().StartsWith("__UNKNOWN") == true) { string partName; partName = Path.GetFileNameWithoutExtension(partPath); if (partName.Length > 8) { partName = partName.Substring(0, 8); } hash = uint.Parse( partName, System.Globalization.NumberStyles.AllowHexSpecifier); } else { hash = partPath.ToLowerInvariant().HashFileName(); } if (paths.ContainsKey(hash) == true) { Console.WriteLine("Ignoring {0} duplicate.", partPath); continue; } paths[hash] = fullPath; } } using (var output = File.Open(outputPath, FileMode.Create, FileAccess.ReadWrite, FileShare.ReadWrite)) { var big = new BigFile(); if (verbose == true) { Console.WriteLine("Adding files..."); } // write a dummy header output.Seek(0, SeekOrigin.Begin); big.Entries.Clear(); foreach (var kvp in paths) { big.Entries.Add(new BigFile.Entry() { Name = 0, Offset = 0, Size = 0, }); } big.Serialize(output); output.Seek(output.Position.Align(2048), SeekOrigin.Begin); long baseOffset = output.Position; // write file data big.Entries.Clear(); if (verbose == true) { Console.WriteLine("Writing to disk..."); } foreach (var kvp in paths) { if (verbose == true) { Console.WriteLine(kvp.Value); } using (var input = File.Open(kvp.Value, FileMode.Open, FileAccess.Read, FileShare.ReadWrite)) { output.Seek(baseOffset, SeekOrigin.Begin); uint size = (uint)input.Length.Align(2048); big.Entries.Add(new BigFile.Entry() { Name = kvp.Key, Offset = (uint)output.Position, Size = size, }); output.WriteFromStream(input, input.Length); baseOffset += size; } } // write filled header output.Seek(0, SeekOrigin.Begin); big.TotalFileSize = (uint)output.Length; big.Serialize(output); } }