/*public static byte[] CompressData(byte[] data, ZLibNet.CompressionLevel level = ZLibNet.CompressionLevel.Level9) * { * using (var dest = new MemoryStream()) * { * using (var source = new MemoryStream(data)) * { * using (var deflateStream = new ZLibNet.DeflateStream(dest, ZLibNet.CompressionMode.Compress, level, true)) * { * source.CopyTo(deflateStream); * * // DOOM's compressed resources all end with 00 00 FF FF * dest.SetLength(dest.Length + 4); * dest.Position = dest.Length - 2; * dest.WriteByte(0xFF); * dest.WriteByte(0xFF); * * /* DOOM's compressed resources all seem to have the first bit unset * tested by decompressing data and then recompressing using this Compress method, data is 1:1 except for the first bit (eg. our compressed data started with 0x7D, the games data would be 0x7C) * in one test, keeping the bit set made the games graphics screw up and trying to open multiplayer would crash * but unsetting this bit let the game work normally (using a slightly modified decl file also) * another test like this using data that was heavily modded still resulted in a glitched game, even with this bit unset * results inconclusive :( * /*dest.Position = 0; * byte b = (byte)ms.ReadByte(); * b &= byte.MaxValue ^ (1 << 0); * ms.Position = 0; * ms.WriteByte((byte)b); * * return dest.ToArray(); * } * } * } * }*/ private void addFilesFromFolder(string folder, string baseFolder, EndianIO destResources, ref List <string> addedFiles) { var dirs = Directory.GetDirectories(folder); var files = Directory.GetFiles(folder); foreach (var file in files) { if (addedFiles.Contains(Path.GetFullPath(file))) { continue; } if (folder == baseFolder && Path.GetFileName(file).ToLower() == "fileids.txt") { continue; // don't want to add fileIds.txt from base } var filePath = Path.GetFullPath(file).Substring(Path.GetFullPath(baseFolder).Length).Replace("\\", "/"); var fileEntry = new DOOMResourceEntry(this); fileEntry.PatchFileNumber = PatchFileNumber; fileEntry.FileType = "file"; if (filePath.Contains(";")) // fileType is specified { var idx = filePath.IndexOf(";"); fileEntry.FileType = filePath.Substring(idx + 1); filePath = filePath.Substring(0, idx); } fileEntry.FileName2 = filePath; fileEntry.FileName3 = filePath; bool needToPad = destResources.Stream.Length % 0x10 != 0; if (PatchFileNumber > 0 && destResources.Stream.Length == 4) { needToPad = false; // for some reason patch files start at 0x4 instead of 0x10 } if (needToPad) { long numPadding = 0x10 - (destResources.Stream.Length % 0x10); destResources.Stream.SetLength(destResources.Stream.Length + numPadding); } fileEntry.Offset = destResources.Stream.Length; byte[] fileData = File.ReadAllBytes(file); fileEntry.Size = fileEntry.CompressedSize = fileData.Length; fileEntry.ID = Entries.Count; // TODO: find out wtf the ID is needed for? destResources.Stream.Position = fileEntry.Offset; destResources.Writer.Write(fileData); Entries.Add(fileEntry); addedFiles.Add(Path.GetFullPath(file)); } foreach (var dir in dirs) { addFilesFromFolder(dir, baseFolder, destResources, ref addedFiles); } }
public bool Load() { var indexExt = Path.GetExtension(IndexFilePath); if (!File.Exists(IndexFilePath) || (indexExt != ".index" && indexExt != ".pindex")) { return(false); // not an index file } if (!File.Exists(ResourceFilePath(0))) { return(false); // base resource data file not found! } resourceIOs = new Dictionary <string, EndianIO>(); indexIO = new EndianIO(IndexFilePath, FileMode.Open); indexIO.Stream.Position = 0; var magic = indexIO.Reader.ReadInt32(); if ((magic & 0xFFFFFF00) != 0x52455300) { Close(); return(false); // not a RES file. } Header_Version = (byte)(magic & 0xFF); Header_IndexSize = indexIO.Reader.ReadInt32(); // init the base resource data file if (GetResourceIO(0) == null) { Close(); return(false); } indexIO.Stream.Position = 0x20; indexIO.BigEndian = true; Header_NumEntries = indexIO.Reader.ReadInt32(); Entries = new List <DOOMResourceEntry>(); for (var i = 0; i < Header_NumEntries; i++) { var entry = new DOOMResourceEntry(this); entry.Read(indexIO); Entries.Add(entry); if (entry.PatchFileNumber > PatchFileNumber) { PatchFileNumber = entry.PatchFileNumber; // highest PatchFileNumber must be our patch file index } } return(true); }
public long CopyEntryDataToStream(DOOMResourceEntry entry, Stream destStream, bool decompress = true) { var srcStream = entry.GetDataStream(decompress); if (srcStream == null) { return(0); } long copyLen = entry.CompressedSize; if (entry.IsCompressed && decompress) { copyLen = entry.Size; } return(Utility.StreamCopy(destStream, srcStream, 40960, copyLen)); }