private static void Main(string[] args) { bool showHelp = 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_fc3map [output_fc3map]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } string inputPath = extras[0]; string outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(Path.ChangeExtension(inputPath, null) + "_stripped", Path.GetExtension(inputPath)); var map = new CustomMapGameFile(); using (var input = File.OpenRead(inputPath)) { map.Deserialize(input); } var wantedFileNamesToStrip = new[] { @"ige\collection.mask", @"ige\heightmap.raw", @"ige\holemap.raw", @"ige\map.xml", @"ige\texture.mask", }; var wantedFileHashesToStrip = wantedFileNamesToStrip .Select(fn => Dunia2.FileFormats.CRC64.Hash(fn)) .ToArray(); var strippedMap = (CustomMapGameFile)map.Clone(); var fat = new Dunia2.FileFormats.BigFile(); using (var input = map.Archive.Header.Unpack()) { fat.Deserialize(input); } var fileHashesToStrip = fat.Entries .Select(e => e.NameHash) .Intersect(wantedFileHashesToStrip) .ToArray(); if (verbose == true) { Console.WriteLine("Stripping {0} files...", fileHashesToStrip.Length); } if (fileHashesToStrip.Length > 0) { var strippedFat = new Dunia2.FileFormats.BigFile { Version = fat.Version, Platform = fat.Platform, Unknown74 = fat.Unknown74 }; using (var input = map.Archive.Data.Unpack()) using (var output = new MemoryStream()) { var strippedEntries = new List <Dunia2.FileFormats.Big.Entry>(); foreach (var entry in fat.Entries.Where(e => fileHashesToStrip.Contains(e.NameHash) == false)) { var rebuiltEntry = new Dunia2.FileFormats.Big.Entry { NameHash = entry.NameHash, UncompressedSize = entry.UncompressedSize, CompressedSize = entry.CompressedSize, Offset = output.Position, CompressionScheme = entry.CompressionScheme }; input.Seek(entry.Offset, SeekOrigin.Begin); output.WriteFromStream(input, entry.CompressedSize); output.Seek(output.Position.Align(16), SeekOrigin.Begin); strippedEntries.Add(rebuiltEntry); } strippedFat.Entries.AddRange(strippedEntries.OrderBy(e => e.NameHash)); output.Position = 0; strippedMap.Archive.Data = CustomMap.CompressedData.Pack(output); } using (var output = new MemoryStream()) { strippedFat.Serialize(output); output.Position = 0; strippedMap.Archive.Header = CustomMap.CompressedData.Pack(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 fat.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("CrcHex", entry.NameHash.ToString("x16", CultureInfo.InvariantCulture)); writer.WriteAttributeString("FileTime", "0"); writer.WriteAttributeString("SeekPos", entry.Offset.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndDocument(); } output.Position = 0; strippedMap.Archive.Descriptor = CustomMap.CompressedData.Pack(output); } } using (var output = File.Create(outputPath)) { strippedMap.Serialize(output); } }
public static void Main(string[] args) { bool showHelp = false; bool useDescriptorFromFile = false; bool verbose = false; var options = new OptionSet() { { "v|verbose", "be verbose", v => verbose = v != null }, { "fd|use-descriptor-from-file", v => useDescriptorFromFile = 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_dir [output_fc3map]", 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) + ".fc3map"; MapConfiguration config; using (var input = File.OpenRead(Path.Combine(inputPath, "config.json"))) using (var streamReader = new StreamReader(input)) using (var jsonReader = new JsonTextReader(streamReader)) { var serializer = new JsonSerializer(); config = serializer.Deserialize <MapConfiguration>(jsonReader); } var map = new CustomMapGameFile() { Endian = config.Endian, }; map.Header = new CustomMapGameFileHeader() { Unknown2 = config.Header.Unknown2, Unknown3 = config.Header.Unknown3, Unknown4 = config.Header.Unknown4, Unknown5 = config.Header.Unknown5, Creator = config.Header.Creator, Unknown7 = config.Header.Unknown7, Author = config.Header.Author, Name = config.Header.Name, MapId = new CustomMap.MapId() { Guid = config.Header.MapId.Guid, Unknown2 = config.Header.MapId.Unknown2, Unknown3 = config.Header.MapId.Unknown3, }, VersionId = config.Header.VersionId, TimeModified = config.Header.TimeModified, TimeCreated = config.Header.TimeCreated, MapSize = config.Header.MapSize, PlayerRange = config.Header.PlayerRange, Unknown16 = config.Header.Unknown16, Unknown17 = config.Header.Unknown17, }; if (string.IsNullOrEmpty(config.SnapshotPath) == true) { map.Snapshot = new Snapshot(); } else { using (var input = File.OpenRead(Path.Combine(inputPath, config.SnapshotPath))) { map.Snapshot = ImportSnapshot(input, map.Endian); } } if (string.IsNullOrEmpty(config.ExtraSnapshotPath) == true) { map.ExtraSnapshot = new Snapshot(); } else { using (var input = File.OpenRead(Path.Combine(inputPath, config.ExtraSnapshotPath))) { map.ExtraSnapshot = ImportSnapshot(input, map.Endian); } } if (config.Data != null) { map.Data.Unknown1 = config.Data.Unknown1; if (string.IsNullOrEmpty(config.Data.Unknown2Path) == true) { map.Data.Unknown2 = new byte[0]; } else { map.Data.Unknown2 = File.ReadAllBytes(Path.Combine(inputPath, config.Data.Unknown2Path)); } } if (string.IsNullOrEmpty(config.FilesystemHeaderPath) == false) { using (var input = File.OpenRead(Path.Combine(inputPath, config.FilesystemHeaderPath))) { map.Archive.Header = CustomMap.CompressedData.Pack(input); } } if (string.IsNullOrEmpty(config.FilesystemDataPath) == false) { using (var input = File.OpenRead(Path.Combine(inputPath, config.FilesystemDataPath))) { map.Archive.Data = CustomMap.CompressedData.Pack(input); } } if (useDescriptorFromFile == true) { if (string.IsNullOrEmpty(config.FilesystemDescriptorPath) == false) { using (var input = File.OpenRead(Path.Combine(inputPath, config.FilesystemDescriptorPath))) { map.Archive.Descriptor = CustomMap.CompressedData.Pack(input); } } } else { using (var input = File.OpenRead(Path.Combine(inputPath, config.FilesystemHeaderPath))) { var fat = new Dunia2.FileFormats.BigFile(); fat.Deserialize(input); 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 fat.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("CrcHex", entry.NameHash.ToString("x16", CultureInfo.InvariantCulture)); writer.WriteAttributeString("FileTime", "0"); writer.WriteAttributeString("SeekPos", entry.Offset.ToString(CultureInfo.InvariantCulture)); writer.WriteEndElement(); } writer.WriteEndElement(); writer.WriteEndDocument(); } output.Position = 0; map.Archive.Descriptor = CustomMap.CompressedData.Pack(output); } } } using (var output = File.Create(outputPath)) { map.Serialize(output); } }