mirror of
https://github.com/alliedmodders/hl2sdk.git
synced 2024-12-23 01:59:43 +08:00
272 lines
10 KiB
C++
272 lines
10 KiB
C++
//===== Copyright © 1996-2005, Valve Corporation, All rights reserved. ======
|
|
//
|
|
// .xzp creation and manipulation.
|
|
//
|
|
// XZip file format:
|
|
// [xZipHeader]
|
|
//
|
|
//
|
|
// Regular directory:
|
|
// [xZipDirectoryEntry 1]
|
|
// [xZipDirectoryEntry 2]
|
|
// [xZipDirectoryEntry 3]
|
|
// [...]
|
|
//
|
|
// Preload offset points here:
|
|
// Preload directory:
|
|
// [xZipDirectoryEntry 1]
|
|
// [xZipDirectoryEntry 2]
|
|
// [xZipDirectoryEntry 3]
|
|
// [...]
|
|
// [unsigned short directory to preload mapping 1]
|
|
// [unsigned short directory to preload mapping 2]
|
|
// [unsigned short directory to preload mapping 3]
|
|
// [...]
|
|
// [regular preload data]
|
|
//
|
|
// [consolidated file data]
|
|
//
|
|
// (v2+ only):
|
|
// The filename string table. This is stored at the end of the file because in most cases it will rarely ever be read:
|
|
// [xZipFilenameEntry 1]
|
|
// [xZipFilenameEntry 2]
|
|
// [xZipFilenameEntry 3]
|
|
// [...]
|
|
// [filename string data]
|
|
//
|
|
// The filename strings are currently only used for debugging purposes, though
|
|
// code could be written to use them for findfirst / findnext functionality.
|
|
//
|
|
//===========================================================================
|
|
//
|
|
// .xzp format version history:
|
|
//
|
|
// 1: Initial version
|
|
// 2: Filename strings added, still reads version 1.
|
|
// 3: File dates added to the filename strings structure.
|
|
// 4: No more filename length - filenames are now offsets
|
|
//
|
|
//===========================================================================
|
|
|
|
#ifndef __XZIP_H__
|
|
#define __XZIP_H__
|
|
|
|
#pragma pack(1)
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipHeader
|
|
//
|
|
// Found at logical offset 0 in an .xzip file.
|
|
//-----------------------------------------------------------------------------
|
|
struct xZipHeader_t
|
|
{
|
|
enum
|
|
{
|
|
MAGIC = 'xZip',
|
|
FREE = 'Free',
|
|
VERSION = 6
|
|
};
|
|
|
|
unsigned Magic; // MAGIC
|
|
unsigned Version; // VERSION
|
|
unsigned PreloadDirectoryEntries; // Number of preloaded directory entries.
|
|
unsigned DirectoryEntries; // Total # of directory entries (may not correspond to # of files as one file may have any number of directory entries)
|
|
unsigned PreloadBytes; // Number of bytes following the directory to preload.
|
|
unsigned HeaderLength; // Length of this header.
|
|
unsigned FilenameEntries; // The count of filename entries.
|
|
unsigned FilenameStringsOffset; // Offset to the filename strings offset table (array of dwords) (v2 only)
|
|
unsigned FilenameStringsLength; // Length of the filename string data. ( including the offsets table )
|
|
};
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipDirectoryEntry
|
|
//
|
|
// Multiple entries may be stored for a single file, representing pieces of the
|
|
// same file at different locations in the archive (for optimizing seek times)
|
|
// in the preload section, or to facilitate streaming.
|
|
//
|
|
// Note that a preloaded directory entry is the exact same structure, only
|
|
// stored in a different directory table.
|
|
//-----------------------------------------------------------------------------
|
|
struct xZipDirectoryEntry_t
|
|
{
|
|
unsigned FilenameCRC; // CRC of the filename
|
|
unsigned Length; // Length of this chunk of the file. In bytes. TODO: use sectors instead:
|
|
int StoredOffset; // Offset the file data in the .xzip. When building the zip, a negative means standard data, positive means preloaded data.
|
|
|
|
static int __cdecl xZipDirectoryEntrySortCompare( const void* left, const void* right );
|
|
static int __cdecl xZipDirectoryEntryFindCompare( const void* left, const void* right );
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipFilenameEntry
|
|
//
|
|
// An entry describing where to find an individual filename
|
|
//-----------------------------------------------------------------------------
|
|
struct xZipFilenameEntry_t
|
|
{
|
|
unsigned FilenameCRC; // CRC of the filename associated with this filename.
|
|
unsigned FilenameOffset; // Absolute offset to the filename on disk.
|
|
unsigned TimeStamp; // Time stamp of the file at the time it was added.
|
|
|
|
static int __cdecl xZipFilenameEntryCompare( const void* left, const void* right );
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipFooter
|
|
//
|
|
// This footer is tacked onto the end of every xzip. It allows you to find the
|
|
// beginning of an .xzip file when it is appended to something else.
|
|
//-----------------------------------------------------------------------------
|
|
struct xZipFooter_t
|
|
{
|
|
enum
|
|
{
|
|
MAGIC = 'XzFt'
|
|
};
|
|
|
|
unsigned Size; // Total size of this .xzip including this footer.
|
|
unsigned Magic; // MAGIC (last dword in the file)
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZip
|
|
//
|
|
// Class for manipulating xZips.
|
|
//-----------------------------------------------------------------------------
|
|
class CXZip
|
|
{
|
|
public:
|
|
// Construction and destruction:
|
|
CXZip( char* filename ); // xZip filename to register
|
|
CXZip( FILE* handle, int offset, int size ); // file handle and offset of the zip file - used for constructing files inside of files.
|
|
CXZip();
|
|
|
|
|
|
virtual ~CXZip();
|
|
|
|
// Loading and unloading xZips:
|
|
bool Load( char* filename, bool bPreload = true ); // Load a pack file into this instance. Returns true on success.
|
|
bool Load( FILE* handle, int nOffset, int nSize, bool bPreload = true ); // Load a pack file into this instance. Returns true on success.
|
|
void Unload(); // Unload this packfile
|
|
|
|
void PreloadData(); // Loads the preloaded data if it isn't already.
|
|
void DiscardPreloadedData(); // Free the preloaded data from memory.
|
|
|
|
// Header Accessors:
|
|
int GetVersion() { return m_Header.Version; }
|
|
int EntryCount() { return m_Header.DirectoryEntries; }
|
|
int GetPreloadSize() { return m_Header.PreloadBytes; }
|
|
|
|
// Hack, interfaces to main thing:
|
|
bool GetSimpleFileOffsetLength( const char* FileName, int& nBaseIndex, int &nFileOffset, int &nLength );
|
|
bool ExtractFile( const char* FileName );
|
|
|
|
// If installed, these routines will be called instead of fread, etc
|
|
bool InstallAlternateIO( int (*read)( void* buffer, int offset, int destLength, int length, int hUser), int hUser );
|
|
|
|
|
|
// Retrieves the file name of a given entry, returns true on success. NOTE: Slow and memory consuming
|
|
char* GetEntryFileName( unsigned CRC, char* pDefault = NULL );
|
|
|
|
xZipDirectoryEntry_t* GetEntry( int nEntryIndex ) { return &m_pDirectory[nEntryIndex]; }
|
|
xZipDirectoryEntry_t* GetPreloadEntry( int nEntryIndex )
|
|
{
|
|
// If the preload chunk isn't loaded, fail.
|
|
if( !m_pPreloadedData )
|
|
return NULL;
|
|
|
|
// If this entry doesn't have a corresponding preload entry, fail.
|
|
if( m_nRegular2PreloadEntryMapping[nEntryIndex] == 0xFFFF )
|
|
return NULL;
|
|
|
|
// Return the entry:
|
|
return &m_pPreloadDirectory[m_nRegular2PreloadEntryMapping[nEntryIndex]];
|
|
}
|
|
// Reads a certain amount of data from a certain file.
|
|
// Determines and reads from the optimal entry index. (Precached, closest seek, etc)
|
|
// If -1 based from the beginning of the pack file, if -1, from the beginning of the entry
|
|
int ReadIndex( int nEntryIndex, int nFileOffset, int nDestBytes, int nLength, void* pBuffer );
|
|
|
|
// Sanity checks that the zip file is ready and readable:
|
|
bool IsValid();
|
|
|
|
void WarningDir();
|
|
void SetMonitorLevel( int nLevel ) { m_nMonitorLevel = nLevel; }
|
|
|
|
|
|
protected:
|
|
// Returns the size of the given entry: Returns -1 on error.
|
|
int GetEntrySize( int nEntryIndex );
|
|
|
|
xZipHeader_t m_Header; // The xZip header structure.
|
|
xZipDirectoryEntry_t* m_pPreloadDirectory;// Pointer to the preload directory entries.
|
|
xZipDirectoryEntry_t* m_pDirectory; // Pointer to the directory entries
|
|
xZipFilenameEntry_t* m_pFilenames; // Pointer to the filename table, or NULL
|
|
void* m_pPreloadedData; // Pointer to the preloaded data, or NULL
|
|
unsigned m_nPreloadStart;
|
|
unsigned short* m_nRegular2PreloadEntryMapping;
|
|
|
|
FILE* m_hZip; // Handle to the zip file.
|
|
int m_nSize; // Size of the zip file.
|
|
int m_nOffset; // Offset of the start of the zip within the above file
|
|
int m_hUser;
|
|
int m_nMonitorLevel; // Default monitoring level
|
|
|
|
// Alternate IO functions
|
|
int (*m_pRead)( void* buffer, int offset, int destLength, int length, int hUser);
|
|
static int defaultRead( void* buffer, int offset, int destLength, int length, int hUser);
|
|
};
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipCRCFilename
|
|
//
|
|
// CRC's and returns the string for the given filename.
|
|
//-----------------------------------------------------------------------------
|
|
unsigned xZipCRCFilename( char* filename );
|
|
|
|
#ifdef MAKE_XZIP_TOOL
|
|
//-----------------------------------------------------------------------------
|
|
// xZipBegin
|
|
// xZipAddFile
|
|
// xZipEnd
|
|
//
|
|
// Functions for constructing an xZip.
|
|
//-----------------------------------------------------------------------------
|
|
int xZipBegin( char* fileNameXzip );
|
|
bool xZipAddFile( char* filename, bool bPrecacheEntireFile = false, bool bProcessPrecacheHeader = false, bool bProcessPrecacheHeaderOnly = false );
|
|
bool xZipEnd();
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipAttachPreloadFooter
|
|
//
|
|
// Attaches a preload footer to the given binary file. Returns true on success.
|
|
//-----------------------------------------------------------------------------
|
|
bool xZipAttachPreloadFooter( char* filename, unsigned nLength, unsigned nOffset = 0 );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipReadPreloadFooter
|
|
//
|
|
// Reads the preload footer off a file, or returns false if none exists:
|
|
//-----------------------------------------------------------------------------
|
|
bool xZipReadPreloadFooter( char* filename, unsigned &nLength, unsigned &nOffset );
|
|
|
|
//-----------------------------------------------------------------------------
|
|
// xZipComputeCustomPreloads
|
|
//
|
|
// Computes custom preload lengths for propriatary formats.
|
|
// ex, computes the offset of everything up until the data chunk in a .wav file.
|
|
//-----------------------------------------------------------------------------
|
|
unsigned xZipComputeCustomPreloads( char* filename );
|
|
|
|
|
|
// Hacky non encapsulated functions:
|
|
char* CleanFilename( char* filename );
|
|
#endif // MAKE_XZIP_TOOL
|
|
|
|
#endif // __XZIP_H__
|