public bool ReadMoviesCameras(Location location) { ArchiveFileEntry mskEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".msk"); if (mskEntry == null) { return(true); } using (MskFileReader mskReader = new MskFileReader(mskEntry.OpenReadableContentStream())) { MovieCameras cameras = new MovieCameras(mskReader.Rects.Length); foreach (MskRect rect in mskReader.Rects) { MovieCamera camera = new MovieCamera { TopLeft = rect.Top, TopRight = rect.Bottom, BottomRight = rect.Right, BottomLeft = rect.Left }; cameras.Add(camera); } location.MovieCameras = cameras; } location.SaveRequest &= ~LocationProperty.MoviesCameras; location.Importable &= ~LocationProperty.MoviesCameras; return(true); }
/// <summary> /// Add <see cref="ZipArchiveEntry"/> into tree structure. /// </summary> /// <param name="root"></param> /// <param name="zipArchiveEntries"></param> /// <param name="streamProvider">stream provider for files</param> /// <returns>this</returns> static ArchiveDirectoryEntry AddArchiveEntries(ArchiveDirectoryEntry root, IEnumerable <ZipArchiveEntry> zipArchiveEntries, IStreamProvider streamProvider) { foreach (ZipArchiveEntry ze in zipArchiveEntries) { // Is entry a file if (!ze.FullName.EndsWith("/") || ze.Length > 0L) { // Split to filename and path int slashIx = ze.FullName.LastIndexOf('/'); string filename = ze.FullName.Substring(slashIx + 1); string dirPath = slashIx < 0 ? "" : ze.FullName.Substring(0, slashIx); // Create file entry ArchiveFileEntry fileEntry = new ArchiveFileEntry(streamProvider, ze.FullName, filename, ze.Length, ze.LastWriteTime); // Create dir ArchiveDirectoryEntry dir = root.GetOrCreateDirectory(dirPath); // Add to dir dir.files[filename] = fileEntry; } else { // Create dir root.GetOrCreateDirectory(ze.FullName); } } // Return the whole tree return(root); }
public bool ReadCamera(Location location) { ArchiveFileEntry caEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".ca"); if (caEntry == null) { return(true); } using (CaFileReader caReader = new CaFileReader(caEntry.OpenReadableContentStream())) { FieldCameras cameras = new FieldCameras(caReader.Rects.Length); foreach (CaCamera rect in caReader.Rects) { FieldCamera camera = new FieldCamera { XAxis = rect.XAxis, YAxis = rect.YAxis, ZAxis = rect.ZAxis, Position = rect.Position, Zoom = rect.Zoom }; cameras.Add(camera); } location.FieldCameras = cameras; } location.SaveRequest &= ~LocationProperty.FieldCamera; location.Importable &= ~LocationProperty.FieldCamera; return(true); }
public bool ReadMonologues(Location location) { ArchiveFileEntry msdEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".msd"); if (msdEntry == null) { return(true); } using (MsdFileReader msdReader = new MsdFileReader(msdEntry.OpenReadableContentStream())) { string[] strings = msdReader.ReadAllMonologues(); LocalizableStrings monologues = new LocalizableStrings(strings.Length); foreach (string str in strings) { LocalizableString localizableString = new LocalizableString(str, str); monologues.Add(localizableString); } location.Monologues = monologues; } location.SaveRequest &= ~LocationProperty.Monologues; location.Importable &= ~LocationProperty.Monologues; return(true); }
public static GameFont HiResFromGameData() { using (DisposableStack disposables = new DisposableStack(2)) { GameImage firstImage, secondImage; ArchiveDirectoryEntry mainDirectory = Archives.GetEntry <ArchiveDirectoryEntry>(MainPath); ArchiveDirectoryEntry menuDirectory = Archives.GetEntry <ArchiveDirectoryEntry>(MenuPath); ArchiveDirectoryEntry hiresDirectory = menuDirectory.GetChildEntry <ArchiveDirectoryEntry>(HiResDirectoryName); ArchiveFileEntry tdwEntry = mainDirectory.GetChildEntry <ArchiveFileEntry>(HiResCharactersWidthsFileName); ArchiveFileEntry image01 = hiresDirectory.GetChildEntry <ArchiveFileEntry>(HiResFontImage1FileName); ArchiveFileEntry image02 = hiresDirectory.GetChildEntry <ArchiveFileEntry>(HiResFontImage2FileName); byte[] widths; using (TdwFileReader tdwReader = new TdwFileReader(tdwEntry.OpenReadableContentStream())) widths = tdwReader.Table; using (TexFileReader texReader = new TexFileReader(image01.OpenReadableContentStream())) { firstImage = GameImageReader.FromTex(texReader); disposables.Add(firstImage.Layer); } using (TexFileReader texReader = new TexFileReader(image02.OpenReadableContentStream())) secondImage = disposables.Add(GameImageReader.FromTex(texReader)); int x = firstImage.X; int y = firstImage.Y; GLTexture palettes = firstImage.Palettes; GLTexture layer = GLTextureFactory.HorizontalJoin(firstImage.Layer, secondImage.Layer); GameImage image = new GameImage(x, y, layer, palettes); return(new GameFont(image, widths)); } }
public bool ReadInformation(Location location) { ArchiveFileEntry infEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".inf"); if (infEntry == null) { return(true); } using (InfFileReader infReader = new InfFileReader(infEntry.OpenReadableContentStream())) { InfEntry entry = infReader.Entry; FieldInfo result = new FieldInfo( entry.Name, entry.Direction, entry.HeightCameraFocus, entry.CameraRanges, entry.ScreenRanges, entry.Gateways.Select(g => new FieldGateway(g.SourceLine, g.TargetFieldID, g.TargetPoint, g.Unknown1, g.Unknown2, g.Unknown3)).ToArray(), entry.Triggers.Select(t => new FieldTrigger(t.DoorID, t.SourceLine)).ToArray(), entry.PvP, entry.Unknown); location.Info = result; } location.SaveRequest &= ~LocationProperty.Information; location.Importable &= ~LocationProperty.Information; return(true); }
public override void ExtractArchiveFile(ArchiveFileEntry afe) { var entry = afe as Img1DirectoryEntry; FolderBrowserDialog fbd = new FolderBrowserDialog(); if (fbd.ShowDialog() == DialogResult.OK) { File.WriteAllBytes(fbd.SelectedPath + "\\" + entry.Name, entry.Data); } }
public void WriteScripts(AsmCollection asmCollection) { ArchiveFileEntry jsmEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".jsm"); if (jsmEntry == null) { return; } JsmHeader header = new JsmHeader(); List <JsmGroup> groups = new List <JsmGroup>(8); List <JsmScript> scripts = new List <JsmScript>(32); List <JsmOperation> operations = new List <JsmOperation>(512); foreach (AsmModule module in asmCollection.GetOrderedModules()) { JsmGroup group = new JsmGroup(module.ExecutionOrder, module.Label, (byte)module.Count, (JsmModuleType)module.Type); header.IncrementCount(group.Type); groups.Add(group); } foreach (AsmModule module in asmCollection.GetOrderedModulesByIndex()) { foreach (AsmEvent evt in module.GetOrderedEvents()) { JsmScript script = new JsmScript((ushort)operations.Count, evt.Flag); scripts.Add(script); foreach (JsmOperation command in evt) { operations.Add(command); } } } scripts.Add(new JsmScript((ushort)operations.Count, false)); header.ScriptsOffset = (ushort)(8 + groups.Count * 2); header.OperationsOffset = (ushort)(header.ScriptsOffset + scripts.Count * 2); using (JsmFileWriter jsmWriter = new JsmFileWriter(jsmEntry.OpenWritableCapacityStream())) jsmWriter.WriteScripts(header, groups, scripts, operations); //ArchiveFileEntry symEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".sym"); //if (symEntry == null) // return; //using (SymFileWriter symWriter = new SymFileWriter(symEntry.OpenWritableCapacityStream())) //{ //} }
public bool ReadParticles(Location location) { ArchiveFileEntry pmdEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".pmd"); ArchiveFileEntry pmpEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".pmp"); if (pmdEntry == null || pmpEntry == null) { return(true); } SafeHGlobalHandle pmdContent, pmpContent; using (Stream input = pmdEntry.OpenReadableContentStream()) { pmdContent = new SafeHGlobalHandle((int)input.Length); try { using (Stream output = pmdContent.OpenStream(FileAccess.Write)) input.CopyTo(output); } catch { pmdContent.SafeDispose(); throw; } } using (Stream input = pmpEntry.OpenReadableContentStream()) { pmpContent = new SafeHGlobalHandle((int)input.Length); try { using (Stream output = pmpContent.OpenStream(FileAccess.Write)) input.CopyTo(output); } catch { pmpContent.SafeDispose(); throw; } } Particles result = new Particles(pmdContent, pmpContent); location.Particles = result; location.SaveRequest &= ~LocationProperty.Particles; location.Importable &= ~LocationProperty.Particles; return(true); }
public override void ViewFile(ArchiveFileEntry afe, bool hex = false) { var entry = afe as Img1DirectoryEntry; var filepath = entry.Name; var data = entry.Data; if (hex) { ViewHexFile(filepath, data); return; } switch (entry.Extension.Replace(".", string.Empty).ToLower()) { case "dff": ViewDffFile(filepath, data); break; case "txd": ViewTxdFile(filepath, data); break; case "dat": ViewTextFile(filepath, data); break; case "ini": ViewTextFile(filepath, data); break; case "txt": ViewTextFile(filepath, data); break; case "cfg": ViewTextFile(filepath, data); break; case "xml": ViewXmlFile(filepath, data); break; default: ViewHexFile(filepath, data); break; } }
public bool ReadPvP(Location location) { ArchiveFileEntry pvpEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".pvp"); if (pvpEntry == null) { return(true); } using (PvpFileReader pvpReader = new PvpFileReader(pvpEntry.OpenReadableContentStream())) location.PVP = pvpReader.Value; location.SaveRequest &= ~LocationProperty.PvP; location.Importable &= ~LocationProperty.PvP; return(true); }
public static Location[] GetLocationList(Action <long> totalCallback, Action <long> progressCallback) { List <Location> result = new List <Location>(850); try { string mapFilePath = Path.Combine(SourcePath, MaplistFileName); ArchiveFileEntry mapFile = Archives.GetEntry <ArchiveFileEntry>(mapFilePath); totalCallback.Invoke(result.Capacity); using (FileSegment stream = mapFile.OpenReadableContentStream()) using (StreamReader sr = stream.GetStreamReader()) while (!sr.EndOfStream) { string name = sr.ReadLine(); if (name == "testno") { progressCallback.Invoke(1); continue; } Location location = FindLocation(name); if (location == null) { progressCallback.Invoke(1); continue; } result.Add(location); location.LoadBaseInformation(); progressCallback.Invoke(1); } totalCallback.Invoke(result.Count); } catch { result.SafeDispose(); throw; } return(result.ToArray()); }
public bool GetBackgroundReader(Location location) { ArchiveFileEntry mapEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".map"); ArchiveFileEntry mimEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".mim"); if (mapEntry == null || mimEntry == null) { return(true); } MimFileReader mimReader = new MimFileReader(mimEntry.OpenReadableContentStream()); MapFileReader mapReader = new MapFileReader(mapEntry.OpenReadableContentStream()); location.BackgroundReader = new MimGLTextureReader(mimReader, mapReader, true); location.SaveRequest &= ~LocationProperty.Background; location.Importable &= ~LocationProperty.Background; return(true); }
public ArchiveFile(Archive archive, ArchiveFileInfo fileInfo, ArchiveFileEntry fileHeader) { this.ar = archive; this.info = fileInfo; this.fileHeader = fileHeader; this.stream = this.ar.File.OpenRead(); this.chunkEntries = this.ar.Table.ReadChunkTableRange(this.stream, this.fileHeader.firstChunkIdx, this.fileHeader.lastChunkIdx); this.chunkFileOffsets = new long[this.chunkEntries.Length]; this.position = 0; this.length = 0; for (int i = 0; i < this.chunkEntries.Length; i++) { this.chunkFileOffsets[i] = this.length; this.length += this.chunkEntries[i].originalSize; } }
public bool ReadAmbient(Location location) { ArchiveFileEntry sfxEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".sfx"); if (sfxEntry == null) { return(true); } using (SfxFileReader sfxReader = new SfxFileReader(sfxEntry.OpenReadableContentStream())) { Ambient result = new Ambient(sfxReader.SoundIds); location.Ambient = result; } location.SaveRequest &= ~LocationProperty.Ambient; location.Importable &= ~LocationProperty.Ambient; return(true); }
public bool ReadModels(Location location) { ArchiveFileEntry oneEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue("chara.one"); if (oneEntry == null) { return(true); } using (OneFileReader oneReader = new OneFileReader(oneEntry.OpenReadableContentStream())) { SafeHGlobalHandle result = oneReader.ReadData(); location.Models = result; } location.SaveRequest &= ~LocationProperty.Models; location.Importable &= ~LocationProperty.Models; return(true); }
public static void HiResToGameData(GameFont gameFont) { using (DisposableStack disposables = new DisposableStack(2)) { GLTexture leftTexture; GLTexture rightTexture; GLTextureFactory.HorizontalSplit(gameFont.CharactersImage.Layer, out leftTexture, out rightTexture); disposables.Add(leftTexture); disposables.Add(rightTexture); ArchiveDirectoryEntry mainDirectory = Archives.GetEntry <ArchiveDirectoryEntry>(GameFontReader.MainPath); ArchiveDirectoryEntry menuDirectory = Archives.GetEntry <ArchiveDirectoryEntry>(GameFontReader.MenuPath); ArchiveDirectoryEntry hiresDirectory = menuDirectory.GetChildEntry <ArchiveDirectoryEntry>(GameFontReader.HiResDirectoryName); ArchiveFileEntry tdwEntry = mainDirectory.GetChildEntry <ArchiveFileEntry>(GameFontReader.HiResCharactersWidthsFileName); ArchiveFileEntry image01 = hiresDirectory.GetChildEntry <ArchiveFileEntry>(GameFontReader.HiResFontImage1FileName); ArchiveFileEntry image02 = hiresDirectory.GetChildEntry <ArchiveFileEntry>(GameFontReader.HiResFontImage2FileName); using (Stream output = tdwEntry.OpenWritableCapacityStream()) using (TdwFileWriter tdwWriter = new TdwFileWriter(output)) { tdwWriter.WriteFontCharactersWidths(gameFont.CharactersWidths); tdwEntry.UpdateMetrics((int)output.Position, tdwEntry.ContentOffset, Compression.None); } using (Stream output = image01.OpenWritableCapacityStream()) using (TexFileWriter texWriter = new TexFileWriter(output)) { texWriter.WriteImage(leftTexture, gameFont.CharactersImage.Palettes); image01.UpdateMetrics((int)output.Position, image01.ContentOffset, Compression.None); } using (Stream output = image02.OpenWritableCapacityStream()) using (TexFileWriter texWriter = new TexFileWriter(output)) { texWriter.WriteImage(rightTexture, gameFont.CharactersImage.Palettes); image02.UpdateMetrics((int)output.Position, image02.ContentOffset, Compression.None); } Archives.GetInfo(ArchiveName.Main).Update(); Archives.GetInfo(ArchiveName.Menu).Update(); } }
public bool ReadWalkmesh(Location location) { ArchiveFileEntry idEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".id"); if (idEntry == null) { return(true); } using (IdFileReader idReader = new IdFileReader(idEntry.OpenReadableContentStream())) { WalkmeshTriangle[] triangles = idReader.Triangles.Select(t => new WalkmeshTriangle(t.Vertices.Select(v => v.Point).ToArray())).ToArray(); WalkmeshPassability[] passability = idReader.Accesses.Select(a => new WalkmeshPassability(a.Accesses)).ToArray(); Walkmesh result = new Walkmesh(triangles, passability); location.Walkmesh = result; } location.SaveRequest &= ~LocationProperty.Walkmesh; location.Importable &= ~LocationProperty.Walkmesh; return(true); }
public bool ReadEncounters(Location location) { ArchiveFileEntry mrtEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".mrt"); ArchiveFileEntry ratEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".rat"); if (mrtEntry == null || ratEntry == null) { return(true); } using (MrtFileReader mrtReader = new MrtFileReader(mrtEntry.OpenReadableContentStream())) using (RatFileReader ratReader = new RatFileReader(ratEntry.OpenReadableContentStream())) { Encounters result = new Encounters(mrtReader.Troops, (byte)(ratReader.Rates & 0xFF)); location.Encounters = result; } location.SaveRequest &= ~LocationProperty.Encounters; location.Importable &= ~LocationProperty.Encounters; return(true); }
public static GameFont FromGameData(ArchiveDirectoryEntry directory, string name) { ArchiveFileEntry tdwEntry = (ArchiveFileEntry)directory.Childs.TryGetValue(name + ".tdw"); if (tdwEntry == null) { return(null); } using (TdwFileReader tdwReader = new TdwFileReader(tdwEntry.OpenReadableContentStream())) using (TimFileReader timReader = tdwReader.TimReader) { if (timReader == null) { return(null); } GameImage image = GameImageReader.FromTim(timReader); return(new GameFont(image, tdwReader.Table)); } }
public void WriteMonologues(LocalizableStrings monologues) { ArchiveFileEntry msdEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".msd"); if (msdEntry == null) { if (!monologues.IsNullOrEmpty()) { throw new NotImplementedException(); } return; } using (Stream output = msdEntry.OpenWritableCapacityStream()) using (MsdFileWriter msdWriter = new MsdFileWriter(output)) { msdWriter.WriteAllMonologues(monologues.Select(m => m.Current)); msdEntry.UpdateMetrics((int)output.Position, msdEntry.ContentOffset, Compression.None); } }
public bool ReadPlaceables(Location location) { ArchiveFileEntry pcbEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".pcb"); if (pcbEntry == null) { return(true); } using (PcbFileReader pcbReader = new PcbFileReader(pcbEntry.OpenReadableContentStream())) { Placeables placeables = new Placeables(pcbReader.Entries.Length); for (int i = 0; i < placeables.Capacity; i++) { placeables.Add(new Placeable(pcbReader.Entries[i].Unknown)); } location.Placeables = placeables; } location.SaveRequest &= ~LocationProperty.Placeables; location.Importable &= ~LocationProperty.Placeables; return(true); }
public async Task Read(Stream stream) { byte[] buffer = new byte[Marshal.SizeOf <ArchiveFileEntry>()]; stream.Read(buffer, 0, buffer.Length); BinaryReader reader = new BinaryReader(new MemoryStream(buffer)); ArchiveFileEntry fileHeader = new ArchiveFileEntry(); fileHeader.NameHash = reader.ReadUInt64(); fileHeader.Filetime = reader.ReadInt64(); fileHeader.Flags = reader.ReadUInt32(); fileHeader.firstChunkIdx = reader.ReadUInt32(); fileHeader.lastChunkIdx = reader.ReadUInt32(); fileHeader.firstDependencyIdx = reader.ReadUInt32(); fileHeader.lastDependencyIdx = reader.ReadUInt32(); this.fileHeader = fileHeader; try { this.resolvedName = ArchiveManager.ResolveFileHash(this.fileHeader.NameHash); } catch (Exception) {} }
private static LocalizableStrings LoadAreaNames() { lock (_glossaryNode) { if (_glossaryNode.Value != null) { XmlElement node = _glossaryNode.Value.GetChildElement("AreaNames"); return(LocalizableString.FromXml(node)); } ArchiveDirectoryEntry dir = Archives.GetEntry <ArchiveDirectoryEntry>(SourcePath); ArchiveFileEntry entry1 = dir.GetChildEntry <ArchiveFileEntry>(AreaNamesFileName); LocalizableStrings result = new LocalizableStrings(256); using (DictionaryFileReader dicReader = new DictionaryFileReader(entry1.OpenReadableContentStream())) foreach (string title in dicReader.Titles) { result.Add(new LocalizableString(title, title)); } return(result); } }
public static void Main(string[] args) { bool verbose = false; bool showHelp = false; uint baseRevision = 0; uint revision = 0; string deletionsPath = null; bool noCrypto = false; const Endian endian = Endian.Little; var options = new OptionSet() { { "R|baseRevision=", "specify archive base revision", v => baseRevision = v == null ? 0 : uint.Parse(v) }, { "r|revision=", "specify archive revision", v => revision = v == null ? 0 : uint.Parse(v) }, { "d|deletions=", "path of deletions file", v => deletionsPath = v }, { "no-crypto", "don't use any encryption", v => noCrypto = v != null }, { "v|verbose", "show verbose messages", 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_ipf input_directory+", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Pack files from input directories into a archive."); 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], ".ipf"); } else { outputPath = Path.ChangeExtension(extras[0], ".ipf"); inputPaths.AddRange(extras.Skip(1)); } var pendingEntries = new SortedDictionary <string, 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)) { string fullPath = Path.GetFullPath(path); string partPath = fullPath.Substring(inputPath.Length + 1) .Replace(Path.DirectorySeparatorChar, '/') .Replace(Path.AltDirectorySeparatorChar, '/'); var key = partPath.ToLowerInvariant(); if (pendingEntries.ContainsKey(key) == true) { Console.WriteLine("Ignoring duplicate of {0}: {1}", partPath, fullPath); if (verbose == true) { Console.WriteLine(" Previously added from: {0}", pendingEntries[key]); } continue; } var archiveSeparatorIndex = partPath.IndexOf('/'); if (archiveSeparatorIndex < 0) { continue; } var archiveName = partPath.Substring(0, archiveSeparatorIndex); var fileName = partPath.Substring(archiveSeparatorIndex + 1); pendingEntries[key] = new PendingEntry(fullPath, archiveName, fileName); } } using (var output = File.Create(outputPath)) { var fileEntries = new List <ArchiveFileEntry>(); var deletionEntries = new List <ArchiveDeletionEntry>(); if (string.IsNullOrEmpty(deletionsPath) == false) { if (verbose == true) { Console.WriteLine("Reading deletions..."); } var serializer = JsonSerializer.Create(); using (var input = File.OpenRead(deletionsPath)) using (var streamReader = new StreamReader(input)) using (var jsonReader = new JsonTextReader(streamReader)) { var jsonDeletionEntries = serializer.Deserialize <JsonArchiveDeletionEntry[]>(jsonReader); deletionEntries.AddRange(jsonDeletionEntries.Select(jde => new ArchiveDeletionEntry() { Name = jde.Name, Archive = jde.Archive, })); } } if (verbose == true) { Console.WriteLine("Writing file data..."); } long current = 0; long total = pendingEntries.Count; var padding = total.ToString(CultureInfo.InvariantCulture).Length; foreach (var pendingEntry in pendingEntries.Select(kv => kv.Value)) { var fullPath = pendingEntry.FullPath; var archiveName = pendingEntry.ArchiveName; var fileName = pendingEntry.FileName; current++; if (verbose == true) { Console.WriteLine("[{0}/{1}] {2} => {3}", current.ToString(CultureInfo.InvariantCulture).PadLeft(padding), total, archiveName, fileName); } var bytes = File.ReadAllBytes(fullPath); var fileEntry = new ArchiveFileEntry(); fileEntry.Name = fileName; fileEntry.Archive = archiveName; fileEntry.Hash = CRC32.Compute(bytes, 0, bytes.Length); fileEntry.UncompressedSize = (uint)bytes.Length; fileEntry.Offset = (uint)output.Position; if (fileEntry.ShouldCompress == true) { int compressionLevel = Deflater.BEST_COMPRESSION; byte[] compressedBytes; using (var temp = new MemoryStream()) { var zlib = new DeflaterOutputStream(temp, new Deflater(compressionLevel, true)); zlib.WriteBytes(bytes); zlib.Finish(); temp.Flush(); temp.Position = 0; compressedBytes = temp.ToArray(); } if (noCrypto == false) { var crypto = new ArchiveCrypto(); crypto.Encrypt(compressedBytes, 0, compressedBytes.Length); } output.WriteBytes(compressedBytes); fileEntry.CompressedSize = (uint)compressedBytes.Length; } else { fileEntry.CompressedSize = fileEntry.UncompressedSize; output.WriteBytes(bytes); } fileEntries.Add(fileEntry); } if (verbose == true) { Console.WriteLine("Writing file table..."); } long fileTableOffset = output.Position; for (int i = 0; i < fileEntries.Count; i++) { fileEntries[i].Write(output, endian); } if (verbose == true) { Console.WriteLine("Writing deletion table..."); } long deletionTableOffset = output.Position; for (int i = 0; i < deletionEntries.Count; i++) { deletionEntries[i].Write(output, endian); } if (verbose == true) { Console.WriteLine("Writing header..."); } ArchiveHeader header; header.FileTableCount = (ushort)fileEntries.Count; header.FileTableOffset = (uint)fileTableOffset; header.DeletionTableCount = (ushort)deletionEntries.Count; header.DeletionTableOffset = (uint)deletionTableOffset; header.Magic = ArchiveHeader.Signature; header.BaseRevision = baseRevision; header.Revision = revision; header.Write(output, endian); if (verbose == true) { Console.WriteLine("Done!"); } } }
public static void Main(string[] args) { bool showHelp = false; bool overwriteFiles = false; bool noCrypto = false; bool verbose = false; var options = new OptionSet() { { "no-crypto", "don't use any encryption", v => noCrypto = v != null }, { "o|overwrite", "overwrite existing files", v => overwriteFiles = 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_ipf [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } var inputPath = Path.GetFullPath(extras[0]); var outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_unpack"; const Endian endian = Endian.Little; using (var input = File.OpenRead(inputPath)) { if (input.Length < ArchiveHeader.Size) { throw new FormatException(); } input.Seek(-ArchiveHeader.Size, SeekOrigin.End); var header = ArchiveHeader.Read(input, endian); if (header.Magic != ArchiveHeader.Signature) { throw new FormatException(); } var fileEntries = new ArchiveFileEntry[header.FileTableCount]; if (header.FileTableCount > 0) { input.Position = header.FileTableOffset; for (int i = 0; i < header.FileTableCount; i++) { fileEntries[i] = ArchiveFileEntry.Read(input, endian); } } var deletionEntries = new ArchiveDeletionEntry[header.DeletionTableCount]; if (header.DeletionTableCount > 0) { input.Position = header.DeletionTableOffset; for (int i = 0; i < header.DeletionTableCount; i++) { deletionEntries[i] = ArchiveDeletionEntry.Read(input, endian); } } long current = 0; long total = fileEntries.Length; var padding = total.ToString(CultureInfo.InvariantCulture).Length; if (header.DeletionTableCount > 0) { Directory.CreateDirectory(outputPath); using (var output = File.Create(Path.Combine(outputPath, "deletions.json"))) using (var streamWriter = new StreamWriter(output)) using (var writer = new JsonTextWriter(streamWriter)) { writer.Indentation = 2; writer.IndentChar = ' '; writer.Formatting = Formatting.Indented; writer.WriteStartArray(); foreach (var deletionEntry in deletionEntries) { writer.WriteStartObject(); writer.WritePropertyName("archive"); writer.WriteValue(deletionEntry.Archive); writer.WritePropertyName("name"); writer.WriteValue(deletionEntry.Name); writer.WriteEndObject(); } writer.WriteEndArray(); } } foreach (var entry in fileEntries) { current++; var entryPath = Path.Combine(outputPath, entry.Archive.Replace('/', Path.DirectorySeparatorChar), entry.Name.Replace('/', Path.DirectorySeparatorChar)); if (overwriteFiles == false && File.Exists(entryPath) == true) { continue; } if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}", current.ToString(CultureInfo.InvariantCulture).PadLeft(padding), total, entry.Name); } input.Seek(entry.Offset, SeekOrigin.Begin); var entryDirectory = Path.GetDirectoryName(entryPath); if (entryDirectory != null) { Directory.CreateDirectory(entryDirectory); } using (var output = File.Create(entryPath)) { input.Seek(entry.Offset, SeekOrigin.Begin); if (entry.ShouldCompress == false) { output.WriteFromStream(input, entry.CompressedSize); } else { var bytes = input.ReadBytes(entry.CompressedSize); if (noCrypto == false) { var crypto = new ArchiveCrypto(); crypto.Decrypt(bytes, 0, bytes.Length); } using (var temp = new MemoryStream(bytes, false)) { var zlib = new InflaterInputStream(temp, new Inflater(true)); output.WriteFromStream(zlib, entry.UncompressedSize); } } } } } }
/// <summary> /// Gets the full file name with file extension for the specified <see cref="ArchiveFileEntry"/> /// </summary> /// <param name="fileEntry"></param> /// <returns></returns> public static string GetFullResourceName(ArchiveFileEntry fileEntry) { return(GetFullResourceName(fileEntry.FileName, fileEntry.FileType)); }
public bool ReadScripts(Location location) { ArchiveFileEntry jsmEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".jsm"); if (jsmEntry == null) { return(true); } AsmCollection result; using (JsmFileReader jsmReader = new JsmFileReader(jsmEntry.OpenReadableContentStream())) { AsmModule previousModule = null; result = new AsmCollection(jsmReader.Groups.Length); for (ushort g = 0, s = 0, o = 0; g < jsmReader.Groups.Length; g++) { JsmGroup jsmGroup = jsmReader.Groups[g]; AsmModule asmGroup = AsmModuleFactory.Create(jsmGroup.Type); asmGroup.Index = g; asmGroup.ExecutionOrder = jsmGroup.ExecutionOrder; asmGroup.Label = jsmGroup.Label; asmGroup.Title = jsmGroup.Label.ToString("D3"); asmGroup.PreviousModule = previousModule; if (previousModule != null) { previousModule.NextModule = asmGroup; } previousModule = asmGroup; result.Add(asmGroup.Label, asmGroup); for (int i = 0; i < jsmGroup.ScriptsCount; i++) { JsmScript jsmScript = jsmReader.Scripts[s++]; AsmEvent asmScript = new AsmEvent(asmGroup, jsmScript.OperationsCount) { Flag = jsmScript.Flag, Label = (ushort)(asmGroup.Label + i) }; asmGroup.SetEventByIndex(i, asmScript); for (int k = 0; k < jsmScript.OperationsCount; k++) { JsmOperation jsmOperation = jsmReader.Opertations[o++]; asmScript.Add(jsmOperation); } } } } ArchiveFileEntry symEntry = (ArchiveFileEntry)_locationDirectory.Childs.TryGetValue(_name + ".sym"); if (symEntry == null) { location.Scripts = result; return(true); } using (SymFileReader symReader = new SymFileReader(symEntry.OpenReadableContentStream())) { foreach (AsmModule module in result.GetOrderedModules()) { module.Title = symReader.Labels[module.Label]; foreach (AsmEvent evt in module.GetOrderedEvents()) { evt.Title = symReader.Labels[evt.Label]; } } } location.Scripts = result; location.SaveRequest &= ~LocationProperty.Scripts; location.Importable &= ~LocationProperty.Scripts; return(true); }
public static void Main(string[] args) { bool showHelp = false; bool verbose = false; bool noCrypto = false; var options = new OptionSet() { { "no-crypto", "don't use any encryption", v => noCrypto = 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_dir [output_dir]", GetExecutableName()); Console.WriteLine(); Console.WriteLine("Options:"); options.WriteOptionDescriptions(Console.Out); return; } const Endian endian = Endian.Little; var inputPath = Path.GetFullPath(extras[0]); var outputPath = extras.Count > 1 ? extras[1] : Path.ChangeExtension(inputPath, null) + "_unpack"; var archiveInfosUnsorted = new List <ArchiveInfo>(); var basePathInfo = new List <KeyValuePair <string, string> >(); basePathInfo.Add(new KeyValuePair <string, string>(Path.Combine(inputPath, "data"), "*.ipf")); basePathInfo.Add(new KeyValuePair <string, string>(Path.Combine(inputPath, "patch"), "*_001001.ipf")); foreach (var kv in basePathInfo) { var basePath = kv.Key; var filter = kv.Value; if (Directory.Exists(basePath) == false) { continue; } foreach (var archivePath in Directory.GetFiles(basePath, filter)) { using (var input = File.OpenRead(archivePath)) { if (input.Length < ArchiveHeader.Size) { throw new FormatException(); } input.Seek(-ArchiveHeader.Size, SeekOrigin.End); var header = ArchiveHeader.Read(input, endian); if (header.Magic != ArchiveHeader.Signature) { throw new FormatException(); } archiveInfosUnsorted.Add( new ArchiveInfo(archivePath, header.BaseRevision, header.Revision, header.FileTableCount + header.DeletionTableCount)); } } } var archiveInfos = archiveInfosUnsorted.OrderBy(ai => ai.BaseRevision) .ThenBy(ai => ai.Revision) .ThenBy(ai => ai.Path) .ToList(); long current = 0; long total = archiveInfos.Sum(ai => ai.TotalCount); var padding = total.ToString(CultureInfo.InvariantCulture).Length; var dataPaths = new Dictionary <string, List <string> >(); foreach (var archiveInfo in archiveInfos) { using (var input = File.OpenRead(archiveInfo.Path)) { if (input.Length < ArchiveHeader.Size) { throw new FormatException(); } input.Seek(-ArchiveHeader.Size, SeekOrigin.End); var header = ArchiveHeader.Read(input, endian); if (header.Magic != ArchiveHeader.Signature) { throw new FormatException(); } var fileEntries = new ArchiveFileEntry[header.FileTableCount]; if (header.FileTableCount > 0) { input.Position = header.FileTableOffset; for (int i = 0; i < header.FileTableCount; i++) { fileEntries[i] = ArchiveFileEntry.Read(input, endian); } } var deletionEntries = new ArchiveDeletionEntry[header.DeletionTableCount]; if (header.DeletionTableCount > 0) { input.Position = header.DeletionTableOffset; for (int i = 0; i < header.DeletionTableCount; i++) { deletionEntries[i] = ArchiveDeletionEntry.Read(input, endian); } } foreach (var entry in deletionEntries) { current++; if (entry.Archive == "data") { var dataPath = entry.Name.ToLowerInvariant(); if (dataPaths.ContainsKey(dataPath) == false) { // probably an incorrect entry pointing to a directory continue; } foreach (var entryPath in dataPaths[dataPath]) { if (File.Exists(entryPath) == true) { File.Delete(entryPath); } } dataPaths.Remove(entry.Name); } else { throw new NotImplementedException(); var entryPath = Path.Combine(outputPath, entry.Archive, entry.Name); if (File.Exists(entryPath) == true) { File.Delete(entryPath); } } } foreach (var entry in fileEntries) { current++; var entryPath = Path.Combine(outputPath, entry.Archive.Replace('/', Path.DirectorySeparatorChar), entry.Name.Replace('/', Path.DirectorySeparatorChar)); var dataPath = entry.Name.ToLowerInvariant(); if (dataPaths.ContainsKey(dataPath) == false) { dataPaths[dataPath] = new List <string>(); } if (dataPaths[dataPath].Contains(entryPath) == false) { dataPaths[dataPath].Add(entryPath); } if (verbose == true) { Console.WriteLine("[{0}/{1}] {2}/{3}", current.ToString(CultureInfo.InvariantCulture).PadLeft(padding), total, entry.Archive, entry.Name); } input.Seek(entry.Offset, SeekOrigin.Begin); var entryDirectory = Path.GetDirectoryName(entryPath); if (entryDirectory != null) { Directory.CreateDirectory(entryDirectory); } using (var output = File.Create(entryPath)) { input.Seek(entry.Offset, SeekOrigin.Begin); if (entry.ShouldCompress == false) { output.WriteFromStream(input, entry.CompressedSize); } else { var bytes = input.ReadBytes(entry.CompressedSize); if (noCrypto == false) { var crypto = new ArchiveCrypto(); crypto.Decrypt(bytes, 0, bytes.Length); } using (var temp = new MemoryStream(bytes, false)) { var zlib = new InflaterInputStream(temp, new Inflater(true)); output.WriteFromStream(zlib, entry.UncompressedSize); } } } } } } }
public virtual void ExtractArchiveFile(ArchiveFileEntry afe) { }