diff --git a/DOOMExtract/DOOMExtract.csproj b/DOOMExtract/DOOMExtract.csproj
index 0c72fc9..8f31546 100644
--- a/DOOMExtract/DOOMExtract.csproj
+++ b/DOOMExtract/DOOMExtract.csproj
@@ -45,10 +45,12 @@
+
-
+
+
diff --git a/DOOMExtract/DOOMResourceEntry.cs b/DOOMExtract/DOOMResourceEntry.cs
new file mode 100644
index 0000000..64b1135
--- /dev/null
+++ b/DOOMExtract/DOOMResourceEntry.cs
@@ -0,0 +1,115 @@
+using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
+using System;
+using System.IO;
+
+namespace DOOMExtract
+{
+ public class DOOMResourceEntry
+ {
+ private DOOMResourceIndex _index;
+
+ public int ID;
+ public string FileType; // type?
+ public string FileName2; // ??
+ public string FileName3; // full path
+
+ public long Offset;
+ public int Size;
+ public int CompressedSize;
+ public long Zero;
+ public byte PatchFileNumber;
+
+ public bool IsCompressed { get { return Size != CompressedSize; } }
+ public DOOMResourceEntry(DOOMResourceIndex index)
+ {
+ _index = index;
+ }
+
+ public override string ToString()
+ {
+ return GetFullName();
+ }
+
+ public string GetFullName()
+ {
+ if (!String.IsNullOrEmpty(FileName3))
+ return FileName3.Replace("/", "\\"); // convert to windows path
+
+ if (!String.IsNullOrEmpty(FileName2))
+ return FileName2.Replace("/", "\\"); // convert to windows path
+
+ return FileType.Replace("/", "\\"); // convert to windows path
+
+ }
+ public void Read(EndianIO io)
+ {
+ io.BigEndian = true;
+ ID = io.Reader.ReadInt32();
+
+ io.BigEndian = false;
+ // fname1
+ int size = io.Reader.ReadInt32();
+ FileType = io.Reader.ReadAsciiString(size);
+ // fname2
+ size = io.Reader.ReadInt32();
+ FileName2 = io.Reader.ReadAsciiString(size);
+ // fname3
+ size = io.Reader.ReadInt32();
+ FileName3 = io.Reader.ReadAsciiString(size);
+
+ io.BigEndian = true;
+
+ Offset = io.Reader.ReadInt64();
+ Size = io.Reader.ReadInt32();
+ CompressedSize = io.Reader.ReadInt32();
+ if (_index.Header_Version <= 4)
+ Zero = io.Reader.ReadInt64();
+ else
+ Zero = io.Reader.ReadInt32(); // Zero field is 4 bytes instead of 8 in version 5+
+
+ PatchFileNumber = io.Reader.ReadByte();
+ }
+
+ public void Write(EndianIO io)
+ {
+ io.BigEndian = true;
+ io.Writer.Write(ID);
+
+ io.BigEndian = false;
+ io.Writer.Write(FileType.Length);
+ io.Writer.WriteAsciiString(FileType, FileType.Length);
+ io.Writer.Write(FileName2.Length);
+ io.Writer.WriteAsciiString(FileName2, FileName2.Length);
+ io.Writer.Write(FileName3.Length);
+ io.Writer.WriteAsciiString(FileName3, FileName3.Length);
+
+ io.BigEndian = true;
+
+ io.Writer.Write(Offset);
+ io.Writer.Write(Size);
+ io.Writer.Write(CompressedSize);
+ if (_index.Header_Version <= 4)
+ io.Writer.Write(Zero);
+ else
+ io.Writer.Write((int)Zero); // Zero field is 4 bytes instead of 8 in version 5+
+ io.Writer.Write(PatchFileNumber);
+ }
+
+ public Stream GetDataStream(bool decompress)
+ {
+ if (Size == 0 && CompressedSize == 0)
+ return null;
+
+ var io = _index.GetResourceIO(PatchFileNumber);
+ if (io == null)
+ return null;
+
+ io.Stream.Position = Offset;
+ Stream dataStream = io.Stream;
+ if (IsCompressed && decompress)
+ dataStream = new InflaterInputStream(io.Stream, new ICSharpCode.SharpZipLib.Zip.Compression.Inflater(true), 4096);
+
+ return dataStream;
+ }
+ }
+}
diff --git a/DOOMExtract/ResourceIndex.cs b/DOOMExtract/DOOMResourceIndex.cs
similarity index 62%
rename from DOOMExtract/ResourceIndex.cs
rename to DOOMExtract/DOOMResourceIndex.cs
index f41428a..bb3eaef 100644
--- a/DOOMExtract/ResourceIndex.cs
+++ b/DOOMExtract/DOOMResourceIndex.cs
@@ -1,155 +1,90 @@
using System;
using System.Collections.Generic;
-using System.Linq;
-using System.Text;
-using System.Threading.Tasks;
using System.IO;
-using ICSharpCode.SharpZipLib.Core;
+using System.Linq;
using ICSharpCode.SharpZipLib.Zip.Compression.Streams;
namespace DOOMExtract
{
- public class DOOMResourceEntry
+ public class DOOMResourceIndex
{
- private DOOMResourceIndex _index;
-
- public int ID;
- public string FileType; // type?
- public string FileName2; // ??
- public string FileName3; // full path
-
- public long Offset;
- public int Size;
- public int CompressedSize;
- public long Zero;
- public byte PatchFileIndex;
+ EndianIO indexIO;
+ Dictionary resourceIOs;
- public DOOMResourceEntry(DOOMResourceIndex index)
- {
- _index = index;
- }
+ public byte PatchFileNumber = 0; // highest PatchFileNumber found in the entries of this index
- public override string ToString()
+ public string IndexFilePath;
+ public string BaseIndexFilePath
{
- return GetFullName();
+ get
+ {
+ var sepString = "resources_";
+ var indexPath = IndexFilePath;
+ var numSepIdx = indexPath.IndexOf(sepString);
+ if (numSepIdx < 0)
+ return indexPath; // IndexFilePath is the base index?
+
+ var basePath = indexPath.Substring(0, numSepIdx + sepString.Length - 1);
+ return basePath + ".index";
+ }
}
- public string GetFullName()
- {
- if (!String.IsNullOrEmpty(FileName3))
- return FileName3.Replace("/", "\\"); // convert to windows path
-
- if (!String.IsNullOrEmpty(FileName2))
- return FileName2.Replace("/", "\\"); // convert to windows path
+ public byte Header_Version;
+ public int Header_IndexSize;
+ public int Header_NumEntries;
- return FileType.Replace("/", "\\"); // convert to windows path
+ public List Entries;
- }
- public void Read(EndianIO io)
+ public DOOMResourceIndex(string indexFilePath)
{
- io.BigEndian = true;
- ID = io.Reader.ReadInt32();
-
- io.BigEndian = false;
- // fname1
- int size = io.Reader.ReadInt32();
- FileType = io.Reader.ReadAsciiString(size);
- // fname2
- size = io.Reader.ReadInt32();
- FileName2 = io.Reader.ReadAsciiString(size);
- // fname3
- size = io.Reader.ReadInt32();
- FileName3 = io.Reader.ReadAsciiString(size);
-
- io.BigEndian = true;
-
- Offset = io.Reader.ReadInt64();
- Size = io.Reader.ReadInt32();
- CompressedSize = io.Reader.ReadInt32();
- if (_index.Header_Version <= 4)
- Zero = io.Reader.ReadInt64();
- else
- Zero = io.Reader.ReadInt32(); // Zero field is 4 bytes instead of 8 in version 5+
-
- PatchFileIndex = io.Reader.ReadByte();
+ IndexFilePath = indexFilePath;
}
- public void Write(EndianIO io)
+ public string ResourceFilePath(int patchFileNumber)
{
- io.BigEndian = true;
- io.Writer.Write(ID);
-
- io.BigEndian = false;
- io.Writer.Write(FileType.Length);
- io.Writer.WriteAsciiString(FileType, FileType.Length);
- io.Writer.Write(FileName2.Length);
- io.Writer.WriteAsciiString(FileName2, FileName2.Length);
- io.Writer.Write(FileName3.Length);
- io.Writer.WriteAsciiString(FileName3, FileName3.Length);
-
- io.BigEndian = true;
-
- io.Writer.Write(Offset);
- io.Writer.Write(Size);
- io.Writer.Write(CompressedSize);
- if (_index.Header_Version <= 4)
- io.Writer.Write(Zero);
- else
- io.Writer.Write((int)Zero); // Zero field is 4 bytes instead of 8 in version 5+
- io.Writer.Write(PatchFileIndex);
- }
- }
- public class DOOMResourceIndex
- {
- EndianIO indexIO;
- EndianIO resourceIO;
-
- public string IndexFilePath;
- public string ResourceFilePath;
+ var path = Path.Combine(Path.GetDirectoryName(BaseIndexFilePath), Path.GetFileNameWithoutExtension(BaseIndexFilePath));
+ if (patchFileNumber == 0)
+ return path + ".resources";
+ if (patchFileNumber == 1)
+ return path + ".patch";
- public byte Header_Version;
- public int Header_IndexSize;
- public int Header_NumEntries;
+ return $"{path}_{patchFileNumber:D3}.patch";
+ }
- public List Entries;
- public static long StreamCopy(Stream destStream, Stream sourceStream, int bufferSize, long length)
+ public EndianIO GetResourceIO(int patchFileNumber)
{
- long read = 0;
- while (read < length)
+ var resPath = ResourceFilePath(patchFileNumber);
+ if (!resourceIOs.ContainsKey(resPath))
{
- int toRead = bufferSize;
- if (toRead > length - read)
- toRead = (int)(length - read);
-
- var buf = new byte[toRead];
- int buf_read = sourceStream.Read(buf, 0, toRead);
- destStream.Write(buf, 0, buf_read);
- read += buf_read;
+ if (!File.Exists(resPath))
+ return null;
+
+ var io = new EndianIO(resPath, FileMode.Open);
+ io.Stream.Position = 0;
+ var magic = io.Reader.ReadUInt32();
+ if ((magic & 0xFFFFFF00) != 0x52455300)
+ {
+ io.Close();
+ return null;
+ }
+
+ resourceIOs.Add(resPath, io);
}
- return read;
- }
- public DOOMResourceIndex(string indexFilePath)
- {
- IndexFilePath = indexFilePath;
+ return resourceIOs[resPath];
}
public long CopyEntryDataToStream(DOOMResourceEntry entry, Stream destStream, bool decompress = true)
{
- if (entry.Size == 0 && entry.CompressedSize == 0)
+ var srcStream = entry.GetDataStream(decompress);
+ if (srcStream == null)
return 0;
-
- resourceIO.Stream.Position = entry.Offset;
-
- Stream sourceStream = resourceIO.Stream;
+
long copyLen = entry.CompressedSize;
- if (entry.Size != entry.CompressedSize && decompress)
- {
- sourceStream = new InflaterInputStream(resourceIO.Stream, new ICSharpCode.SharpZipLib.Zip.Compression.Inflater(true), 4096);
+ if (entry.IsCompressed && decompress)
copyLen = entry.Size;
- }
- return StreamCopy(destStream, sourceStream, 40960, copyLen);
+ return Utility.StreamCopy(destStream, srcStream, 40960, copyLen);
}
/*public static byte[] CompressData(byte[] data, ZLibNet.CompressionLevel level = ZLibNet.CompressionLevel.Level9)
@@ -198,6 +133,7 @@ private void addFilesFromFolder(string folder, string baseFolder, EndianIO destR
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
{
@@ -208,15 +144,21 @@ private void addFilesFromFolder(string folder, string baseFolder, EndianIO destR
fileEntry.FileName2 = filePath;
fileEntry.FileName3 = filePath;
- if (destResources.Stream.Length % 0x10 != 0)
+ 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)
{
int extra = 0x10 - ((int)destResources.Stream.Length % 0x10);
destResources.Stream.SetLength(destResources.Stream.Length + extra);
}
+
+ fileEntry.Offset = destResources.Stream.Length;
+
byte[] fileData = File.ReadAllBytes(file);
fileEntry.Size = fileEntry.CompressedSize = fileData.Length;
- fileEntry.Offset = destResources.Stream.Length;
fileEntry.ID = Entries.Count; // TODO: find out wtf the ID is needed for?
destResources.Stream.Position = fileEntry.Offset;
destResources.Writer.Write(fileData);
@@ -245,12 +187,31 @@ public void Rebuild(string destResourceFile, string replaceFromFolder = "", bool
var destResources = new EndianIO(destResourceFile, FileMode.CreateNew);
byte[] header = { Header_Version, 0x53, 0x45, 0x52, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
+ if(PatchFileNumber > 0)
+ header = new byte[]{ Header_Version, 0x53, 0x45, 0x52 }; // patch files start at 0x4 instead
+
destResources.Writer.Write(header);
var addedFiles = new List();
foreach (var file in Entries)
{
- if (destResources.Stream.Length % 0x10 != 0)
+ var replacePath = (String.IsNullOrEmpty(replaceFromFolder) ? String.Empty : Path.Combine(replaceFromFolder, file.GetFullName()));
+ if (File.Exists(replacePath + ";" + file.FileType))
+ replacePath += ";" + file.FileType;
+
+ bool isReplacing = !string.IsNullOrEmpty(replaceFromFolder) && File.Exists(replacePath);
+
+ if (file.PatchFileNumber != PatchFileNumber && !isReplacing)
+ continue; // file is located in a different patch resource and we aren't replacing it, so skip it
+
+ 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 (file.IsCompressed && PatchFileNumber > 0 && !isReplacing) // compressed files not padded in patch files?
+ needToPad = false;
+
+ if (needToPad)
{
int extra = 0x10 - ((int)destResources.Stream.Length % 0x10);
destResources.Stream.SetLength(destResources.Stream.Length + extra);
@@ -262,21 +223,21 @@ public void Rebuild(string destResourceFile, string replaceFromFolder = "", bool
continue;
}
- var replacePath = (String.IsNullOrEmpty(replaceFromFolder) ? String.Empty : Path.Combine(replaceFromFolder, file.GetFullName()));
- if (File.Exists(replacePath + ";" + file.FileType))
- replacePath += ";" + file.FileType;
+ var offset = destResources.Stream.Length;
+ destResources.Stream.Position = offset;
- file.Offset = destResources.Stream.Length;
- destResources.Stream.Position = file.Offset;
-
- if (!string.IsNullOrEmpty(replaceFromFolder) && File.Exists(replacePath))
+ if (isReplacing)
{
+ file.PatchFileNumber = PatchFileNumber;
+
addedFiles.Add(replacePath);
using (var fs = File.OpenRead(replacePath))
- file.CompressedSize = file.Size = (int)StreamCopy(destResources.Stream, fs, 40960, fs.Length);
+ file.CompressedSize = file.Size = (int)Utility.StreamCopy(destResources.Stream, fs, 40960, fs.Length);
}
else
file.CompressedSize = (int)CopyEntryDataToStream(file, destResources.Stream, !keepCompressed);
+
+ file.Offset = offset;
}
// now add any files that weren't replaced
@@ -294,10 +255,13 @@ public void Close()
indexIO.Close();
indexIO = null;
}
- if(resourceIO != null)
+ if(resourceIOs != null)
{
- resourceIO.Close();
- resourceIO = null;
+ foreach (var kvp in resourceIOs)
+ kvp.Value.Close();
+
+ resourceIOs.Clear();
+ resourceIOs = null;
}
}
@@ -323,33 +287,31 @@ public void Save()
public bool Load()
{
- if (!File.Exists(IndexFilePath) || Path.GetExtension(IndexFilePath) != ".index")
+ var indexExt = Path.GetExtension(IndexFilePath);
+ if (!File.Exists(IndexFilePath) || (indexExt != ".index" && indexExt != ".pindex"))
return false; // not an index file
- ResourceFilePath = Path.Combine(Path.GetDirectoryName(IndexFilePath), Path.GetFileNameWithoutExtension(IndexFilePath)) + ".resources";
- if (!File.Exists(ResourceFilePath))
- return false;
+ if (!File.Exists(ResourceFilePath(0)))
+ return false; // base resource data file not found!
+
+ resourceIOs = new Dictionary();
indexIO = new EndianIO(IndexFilePath, FileMode.Open);
- resourceIO = new EndianIO(ResourceFilePath, FileMode.Open);
indexIO.Stream.Position = 0;
var magic = indexIO.Reader.ReadInt32();
if ((magic & 0xFFFFFF00) != 0x52455300)
{
- indexIO.Close();
- resourceIO.Close();
+ Close();
return false; // not a RES file.
}
Header_Version = (byte)(magic & 0xFF);
Header_IndexSize = indexIO.Reader.ReadInt32();
- resourceIO.Stream.Position = 0;
- magic = resourceIO.Reader.ReadInt32();
- if((magic & 0xFFFFFF00) != 0x52455300)
+ // init the base resource data file
+ if(GetResourceIO(0) == null)
{
- indexIO.Close();
- resourceIO.Close();
+ Close();
return false;
}
@@ -363,6 +325,8 @@ public bool Load()
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;
diff --git a/DOOMExtract/Program.cs b/DOOMExtract/Program.cs
index 6f8fac3..5ecfc84 100644
--- a/DOOMExtract/Program.cs
+++ b/DOOMExtract/Program.cs
@@ -13,23 +13,31 @@ static void PrintUsage()
{
Console.WriteLine("Usage:");
Console.WriteLine("Extraction: DOOMExtract.exe [pathToIndexFile] ");
- Console.WriteLine("If destFolder isn't specified a folder will be created next to the index file.");
- Console.WriteLine("Files with fileType != \"file\" will have the fileType appended to the filename.");
- Console.WriteLine("eg. allowoverlays.decl;renderParm for fileType \"renderParm\"");
+ Console.WriteLine(" If destFolder isn't specified a folder will be created next to the index/pindex file.");
+ Console.WriteLine(" Files with fileType != \"file\" will have the fileType appended to the filename.");
+ Console.WriteLine(" eg. allowoverlays.decl;renderParm for fileType \"renderParm\"");
Console.WriteLine();
Console.WriteLine("Repacking: DOOMExtract.exe [pathToIndexFile] --repack [repackFolder]");
- Console.WriteLine("Will repack the resources with the files in the repack folder.");
- Console.WriteLine("Note that files that don't already exist in the resources will be added.");
- Console.WriteLine("To set a new files fileType append the fileType to its filename.");
- Console.WriteLine("eg. allowoverlays.decl;renderParm for fileType \"renderParm\"");
+ Console.WriteLine(" Will repack the resources with the files in the repack folder.");
+ Console.WriteLine(" Files that don't already exist in the resources will be added.");
+ Console.WriteLine(" To set a new files fileType append the fileType to its filename.");
+ Console.WriteLine(" eg. allowoverlays.decl;renderParm for fileType \"renderParm\"");
+ Console.WriteLine(" Note that you should only rebuild the latest patch index file, as patches rely on the data in earlier files!");
+ Console.WriteLine();
+ Console.WriteLine("Patch creation: DOOMExtract.exe [pathToLatestPatchIndex] --createPatch [patchContentsFolder]");
+ Console.WriteLine(" Allows you to create your own patch files.");
+ Console.WriteLine(" Works like repacking above, but the resulting patch files will only contain the files you've added/changed.");
+ Console.WriteLine(" Make sure to point it to the highest-numbered .pindex file!");
+ Console.WriteLine(" Once completed a new .patch/.pindex file pair should be created.");
Console.WriteLine();
Console.WriteLine("Deleting files: DOOMExtract.exe [pathToIndexFile] --delete [file1] ...");
- Console.WriteLine("Will delete files from the resources package. Full filepaths should be specified.");
- Console.WriteLine("If a file isn't found in the package a warning will be given.");
+ Console.WriteLine(" Will delete files from the resources package. Full filepaths should be specified.");
+ Console.WriteLine(" If a file isn't found in the package a warning will be given.");
+ Console.WriteLine(" This should only be used on the latest patch file, as modifying earlier patch files may break later ones.");
}
static void Main(string[] args)
{
- Console.WriteLine("DOOMExtract 1.5.1 - by infogram");
+ Console.WriteLine("DOOMExtract 1.6 - by infogram");
Console.WriteLine();
if (args.Length <= 0)
{
@@ -43,6 +51,12 @@ static void Main(string[] args)
bool isRepacking = false;
bool isDeleting = false;
+ bool isCreatingPatch = false;
+ bool quietMode = false;
+
+ foreach (var arg in args)
+ if (arg == "--quiet")
+ quietMode = true;
if (args.Length >= 2)
{
@@ -50,9 +64,11 @@ static void Main(string[] args)
{
isDeleting = true;
}
- else if(args[1] == "--repack") // repacking
+ else if(args[1] == "--repack" || args[1] == "--createPatch") // repacking
{
isRepacking = true;
+ isCreatingPatch = args[1] == "--createPatch";
+
if (args.Length <= 2) // missing the repack folder arg
{
PrintUsage();
@@ -62,7 +78,7 @@ static void Main(string[] args)
destFolder = Path.GetFullPath(args[2]); // use destFolder as the folder where repack files are
if(!Directory.Exists(destFolder))
{
- Console.WriteLine("Repack folder \"" + destFolder + "\" doesn't exist!");
+ Console.WriteLine((isCreatingPatch ? "Patch" : "Repack") + $" folder \"{destFolder}\" doesn't exist!");
return;
}
}
@@ -70,7 +86,7 @@ static void Main(string[] args)
destFolder = Path.GetFullPath(args[1]);
}
- Console.WriteLine("Loading " + indexFilePath + "...");
+ Console.WriteLine($"Loading {indexFilePath}...");
var index = new DOOMResourceIndex(indexFilePath);
if(!index.Load())
{
@@ -78,18 +94,72 @@ static void Main(string[] args)
return;
}
- Console.WriteLine("Index loaded, Header_NumEntries = " + index.Header_NumEntries.ToString());
+ Console.WriteLine($"Index loaded ({index.Entries.Count} files)" + (!quietMode ? ", data file contents:" : ""));
+
+ if (!quietMode)
+ {
+ var pfis = new Dictionary();
+
+ foreach (var entry in index.Entries)
+ {
+ if (!pfis.ContainsKey(entry.PatchFileNumber))
+ pfis.Add(entry.PatchFileNumber, 0);
+ pfis[entry.PatchFileNumber]++;
+ }
+
+ var pfiKeys = pfis.Keys.ToList();
+ pfiKeys.Sort();
+
+ int total = 0;
+ foreach (var key in pfiKeys)
+ {
+ var resName = Path.GetFileName(index.ResourceFilePath(key));
+ Console.WriteLine($" {resName}: {pfis[key]} files");
+ total += pfis[key];
+ }
+
+ Console.WriteLine();
+ }
+
+ if (isCreatingPatch)
+ {
+ // clone old index and increment the patch file number
+
+ byte pfi = (byte)(index.PatchFileNumber + 1);
+ var destPath = Path.ChangeExtension(index.ResourceFilePath(pfi), ".pindex");
+ index.Close();
+
+ if (File.Exists(destPath))
+ File.Delete(destPath); // !!!!
+
+ File.Copy(indexFilePath, destPath);
+ indexFilePath = destPath;
+
+ index = new DOOMResourceIndex(destPath);
+ if(!index.Load())
+ {
+ Console.WriteLine("Copied patch file failed to load? (this should never happen!)");
+ return;
+ }
+ index.PatchFileNumber = pfi;
+ }
if(isRepacking)
{
- // REPACK MODE!!!
+ // REPACK (and patch creation) MODE!!!
- Console.WriteLine("Repacking/rebuilding resources file from folder " + destFolder + "...");
- index.Rebuild(index.ResourceFilePath + "_tmp", destFolder, true);
+ var resFile = index.ResourceFilePath(index.PatchFileNumber);
+
+ Console.WriteLine((isCreatingPatch ? "Creating" : "Repacking") + $" {Path.GetFileName(indexFilePath)} from folder {destFolder}...");
+
+ index.Rebuild(resFile + "_tmp", destFolder, true);
index.Close();
- File.Delete(index.ResourceFilePath);
- File.Move(index.ResourceFilePath + "_tmp", index.ResourceFilePath);
- Console.WriteLine("Repack complete!");
+
+ if(File.Exists(resFile))
+ File.Delete(resFile);
+
+ File.Move(resFile + "_tmp", resFile);
+ Console.WriteLine(isCreatingPatch ? "Patch file created!" : "Repack complete!");
return;
}
@@ -118,12 +188,12 @@ static void Main(string[] args)
}
if (delIdx == -1)
- Console.WriteLine("Failed to find file " + args[i] + " in package.");
+ Console.WriteLine($"Failed to find file {args[i]} in package.");
else
{
index.Entries.RemoveAt(delIdx);
deleted++;
- Console.WriteLine("Deleted " + args[i] + "!");
+ Console.WriteLine($"Deleted {args[i]}!");
}
}
@@ -131,12 +201,12 @@ static void Main(string[] args)
if (deleted > 0)
{
Console.WriteLine("Repacking/rebuilding resources file...");
- index.Rebuild(index.ResourceFilePath + "_tmp", String.Empty, true);
+ index.Rebuild(index.ResourceFilePath(index.PatchFileNumber) + "_tmp", String.Empty, true);
index.Close();
- File.Delete(index.ResourceFilePath);
- File.Move(index.ResourceFilePath + "_tmp", index.ResourceFilePath);
+ File.Delete(index.ResourceFilePath(index.PatchFileNumber));
+ File.Move(index.ResourceFilePath(index.PatchFileNumber) + "_tmp", index.ResourceFilePath(index.PatchFileNumber));
}
- Console.WriteLine("Deleted " + deleted.ToString() + " files from resources.");
+ Console.WriteLine($"Deleted {deleted} files from resources.");
return;
}
@@ -145,14 +215,17 @@ static void Main(string[] args)
if (!Directory.Exists(destFolder))
Directory.CreateDirectory(destFolder);
+ Console.WriteLine("Extracting contents to:");
+ Console.WriteLine("\t" + destFolder);
+
int numExtracted = 0;
- var warned = new List();
foreach(var entry in index.Entries)
{
if(entry.Size == 0 && entry.CompressedSize == 0) // blank entry?
continue;
-
- Console.WriteLine("Extracting " + entry.GetFullName() + " (type: " + entry.FileType + " size: " + entry.Size.ToString() + " compressed: " + entry.CompressedSize.ToString());
+
+ Console.WriteLine($"Extracting {entry.GetFullName()}...");
+ Console.WriteLine($"\ttype: {entry.FileType}, size: {entry.Size} ({entry.CompressedSize} bytes compressed), source file: {Path.GetFileName(index.ResourceFilePath(entry.PatchFileNumber))}");
var destFilePath = Path.Combine(destFolder, entry.GetFullName());
if (entry.FileType != "file")
@@ -160,37 +233,18 @@ static void Main(string[] args)
var destFileFolder = Path.GetDirectoryName(destFilePath);
- /*var data = index.GetEntryData(entry);
- if(data.Length <= 0)
- {
- Console.WriteLine("Decompression failed!");
- continue;
- }
-
- if (data.Length != entry.Size)
- {
- Console.WriteLine("WARNING: Decompression resulted in " + data.Length + " bytes, but we expected " + entry.Size + " bytes!");
- warned.Add(entry);
- }
-
- if (!Directory.Exists(destFileFolder))
- Directory.CreateDirectory(destFileFolder);
-
- File.WriteAllBytes(destFilePath, data);*/
-
if (!Directory.Exists(destFileFolder))
Directory.CreateDirectory(destFileFolder);
using (FileStream fs = File.OpenWrite(destFilePath))
index.CopyEntryDataToStream(entry, fs);
-
+
Console.WriteLine("----------------------------------------------------");
+
numExtracted++;
}
Console.WriteLine("Extraction complete! Extracted " + numExtracted.ToString() + " files.");
- if (warned.Count > 0)
- Console.WriteLine("... with " + warned.Count + " warnings!");
}
}
}
diff --git a/DOOMExtract/Properties/AssemblyInfo.cs b/DOOMExtract/Properties/AssemblyInfo.cs
index be086d9..23a5e5c 100644
--- a/DOOMExtract/Properties/AssemblyInfo.cs
+++ b/DOOMExtract/Properties/AssemblyInfo.cs
@@ -32,5 +32,5 @@
// You can specify all the values or you can default the Build and Revision Numbers
// by using the '*' as shown below:
// [assembly: AssemblyVersion("1.0.*")]
-[assembly: AssemblyVersion("1.5.1.0")]
-[assembly: AssemblyFileVersion("1.5.1.0")]
+[assembly: AssemblyVersion("1.6.0.0")]
+[assembly: AssemblyFileVersion("1.6.0.0")]
diff --git a/DOOMExtract/Utility.cs b/DOOMExtract/Utility.cs
new file mode 100644
index 0000000..3e8315e
--- /dev/null
+++ b/DOOMExtract/Utility.cs
@@ -0,0 +1,27 @@
+using System;
+using System.IO;
+
+namespace DOOMExtract
+{
+ public static class Utility
+ {
+ public static long StreamCopy(Stream destStream, Stream sourceStream, int bufferSize, long length)
+ {
+ long read = 0;
+ while (read < length)
+ {
+ int toRead = bufferSize;
+ if (toRead > length - read)
+ toRead = (int)(length - read);
+
+ var buf = new byte[toRead];
+ int buf_read = sourceStream.Read(buf, 0, toRead);
+ destStream.Write(buf, 0, buf_read);
+ read += buf_read;
+ if (buf_read == 0)
+ break; // no more to be read..
+ }
+ return read;
+ }
+ }
+}