=========
In this tutorial we're going to add Compressed PK3 support to SharpQuake.
Impetus
=========
PAK files are pretty horrible, you need special tools to add to them and they don't provide any form of compression. This will allow us to easily add files in an industry standard format.
Drawbacks
=========
This tutorial removes PAK support from the engine, but with appropriate checking it would be possible to add both if you so desired.
File compression always adds overhead to the engine, however any computer sufficiently modern to cope with the .NET framework shouldn't experience any real problems with PK3 support.
Pre-requisites
==========
SharpQuake - http://sourceforge.net/projects/sharpquake/
DotNetZipLibrary - http://dotnetzip.codeplex.com/
Visual Studio -or- Visual C# Express
Method
==========
First add a reference to the DotNetZip-Reduced library to our project. (Project Menu -> Add Reference -> Browse)
Open Common.cs
Find:
Code: Select all
using System.IO;
Code: Select all
using Ionic.Zip;
and completly remove the method.
Paste in the following method instead -
Code: Select all
//EGL PK3 Support
public static ZipFile LoadCompressedContainer(string filename)
{
ZipFile output=null;
try
{
output = ZipFile.Read(filename);
}
catch(Exception)
{}
return output;
}
Code: Select all
class searchpath_t
Code: Select all
class searchpath_t
{
public string filename; // char[MAX_OSPATH];
public ZipFile pack; // only one of filename / pack will be used
public searchpath_t(string path)
{
if (path.EndsWith(".pk3"))
{
this.pack = Common.LoadCompressedContainer(path);
if (this.pack == null)
Sys.Error("Couldn't load packfile: {0}", path);
}
else
this.filename = path;
}
public searchpath_t(ZipFile pak)
{
this.pack = pak;
}
} // searchpath_t;
Next find the Path_f method and locate the line -
Code: Select all
Con.Print("{0} ({1} files)\n", sp.pack.filename, sp.pack.files.Length);
Code: Select all
Con.Print("{0} ({1} files))\n", sp.pack.Name, sp.pack.Count); //EGL: PK3
And change the line that reads -
Code: Select all
string pakfile = String.Format("{0}/pak{1}.pak", dir, i);
Code: Select all
string pakfile = String.Format("{0}/pak{1}.pk3", dir, i);
in there find the line that reads
Code: Select all
if(sp.pack != null)
Code: Select all
{
// look through all the pak file elements
ZipFile pak = sp.pack;
if (pak.ContainsEntry(filename))
{
Stream entryStream = new MemoryStream();
pak[filename].Extract(entryStream);
file = new DisposableWrapper<BinaryReader>(new BinaryReader(entryStream, Encoding.ASCII), true);
file.Object.BaseStream.Seek(0, SeekOrigin.Begin);
return (int)entryStream.Length;
}
}
And we're done. Your next step is to extract the orignal PAK files and repackage them as ZIP files. The DotNetZipLibrary does all the donkey work for us here (which is always nice). It's worth noting that although .NET does support both ZIP compression and the ZIP file container, it doesn't support the ZIP container format in a standard way. The .NET framework version requires that all ZIP file has an XML manifest within them which lists the contents and thier MIME types, without this it simply see the ZIP files as empty... which is pretty damn irritating.