Once I get that upgrade to 36-hour days, I will tackle that. – Mychaeel

UZ2 file

From Unreal Wiki, The Unreal Engine Documentation Site
Revision as of 13:12, 23 March 2014 by Wormbo (Talk | contribs)

Jump to: navigation, search

The file extension .uz2 identifies a file, usually an Unreal package, that was compressed by an Unreal Engine 2 game. It is the equivalent to Unreal Engine 1's UZ file and Unreal Engine 3's UZ3 file. UZ2 files are usually stored on "redirect servers", i.e. HTTP servers the game client can fetch packages from that a game server requires.

Usage

The .uz2 format is a general-purpose compression format, i.e. it is not limited to Unreal packages. To compress a file into UZ2, run the command

UCC Compress path\to\file.ext

from a Windows command prompt. This will create a compressed file in the same directory that has the .uz2 extension appended.

To decompress a UZ2 file, use the command

UCC Decompress path\to\file.ext.uz2

and the decompressed file with be created in the same directory but with the .uz2 extension removed.

Note that UCC Compress and UCC Decompress will override any existing file without warning!

There are also 3rd-party tools for compressing or decompressing UZ2 files, like elmuerte's TinyUZ2 or various "cache manager" tools for UT2003 and UT2004.

File format

The format of UZ2 files is relatively simple. It doesn't have any kind of header and consists of a series of chunks, each of which looks as follows:

Field Type Length Value range
Compressed chunk size int 4 Bytes 0-33096
Uncompressed chunk size int 4 Bytes 0-32768
Compressed data bytes 0-33096 Bytes

In other words, every chunk starts with the length of the compressed data and the length of the data when it is decompressed, followed by the actual compressed data. The last chunk's compressed data must end exactly at the end of the file. The compression format is defined by the Zlib library's compress() and uncompress() functions. Each chunk is compressed independently from the others.

UZ2 files created by the Unreal Engine 2 will consist almost only of chunks that decompress into 32768 Bytes of data, except for the very last chunk, which may be smaller. (The chunks aren't 32768 Bytes themselves, but decompress into 32768 Bytes.)

UZ2 files in .NET

As mentioned above, the compressed chunk data is usually created by the Zlib library, which is written in C. However, if you are using the .NET framework, you probably don't want to link to unmanaged code. Fortunately the Zlib functionality was ported to managed code as part of the DotNetZip library. Unfortunately it doesn't really include a lightweight implementation of Zlib's plain compress() and uncompress() functions.

Fortunately, it is quite easy to build the same functionality with DotNetZip's public interface and the following C# code:

using Ionic.Zlib;
 
public static int Compress(byte[] dest, int destStart, byte[] source, int sourceStart, int sourceLen)
{
	var codec = new ZlibCodec(CompressionMode.Compress)
	{
		InputBuffer = source,
		NextIn = sourceStart,
		AvailableBytesIn = sourceLen,
		OutputBuffer = dest,
		NextOut = destStart,
		AvailableBytesOut = dest.Length - destStart,
	};
 
	codec.InitializeDeflate(); // if you want, you can even set a compression level here
	int err = codec.Deflate(FlushType.Finish);
	if (err != ZlibConstants.Z_STREAM_END)
	{
		codec.EndDeflate();
		throw new ZlibException();
	}
	var numBytes = (int) codec.TotalBytesOut;
	codec.EndDeflate();
	return numBytes;
}
 
public static int Uncompress(byte[] dest, int destStart, byte[] source, int sourceStart, int sourceLen)
{
	var codec = new ZlibCodec(CompressionMode.Decompress)
	{
		InputBuffer = source,
		NextIn = sourceStart,
		AvailableBytesIn = sourceLen,
		OutputBuffer = dest,
		NextOut = destStart,
		AvailableBytesOut = dest.Length - destStart
	};
 
	codec.InitializeInflate();
	int err = codec.Inflate(FlushType.Finish);
	if (err != ZlibConstants.Z_STREAM_END)
	{
		codec.EndInflate();
		throw new ZlibException();
	}
	var numBytes = (int) codec.TotalBytesOut;
	codec.EndInflate();
	return numBytes;
}