278 lines
9.0 KiB
C++
278 lines
9.0 KiB
C++
/*
|
|
* HLLib
|
|
* Copyright (C) 2006-2010 Ryan Gregg
|
|
|
|
* This library is free software; you can redistribute it and/or
|
|
* modify it under the terms of the GNU Lesser General Public
|
|
* License as published by the Free Software Foundation; either
|
|
* version 2.1 of the License, or (at your option) any later
|
|
* version.
|
|
*/
|
|
|
|
#ifndef GCFFILE_H
|
|
#define GCFFILE_H
|
|
|
|
#include "stdafx.h"
|
|
#include "Package.h"
|
|
|
|
namespace HLLib
|
|
{
|
|
namespace Streams
|
|
{
|
|
class CGCFStream;
|
|
}
|
|
|
|
class HLLIB_API CGCFFile : public CPackage
|
|
{
|
|
friend class Streams::CGCFStream;
|
|
|
|
private:
|
|
#pragma pack(1)
|
|
|
|
struct GCFHeader
|
|
{
|
|
hlUInt uiDummy0; // Always 0x00000001
|
|
hlUInt uiMajorVersion; // Always 0x00000001
|
|
hlUInt uiMinorVersion; // GCF version number.
|
|
hlUInt uiCacheID;
|
|
hlUInt uiLastVersionPlayed;
|
|
hlUInt uiDummy1;
|
|
hlUInt uiDummy2;
|
|
hlUInt uiFileSize; // Total size of GCF file in bytes.
|
|
hlUInt uiBlockSize; // Size of each data block in bytes.
|
|
hlUInt uiBlockCount; // Number of data blocks.
|
|
hlUInt uiDummy3;
|
|
};
|
|
|
|
struct GCFBlockEntryHeader
|
|
{
|
|
hlUInt uiBlockCount; // Number of data blocks.
|
|
hlUInt uiBlocksUsed; // Number of data blocks that point to data.
|
|
hlUInt uiDummy0;
|
|
hlUInt uiDummy1;
|
|
hlUInt uiDummy2;
|
|
hlUInt uiDummy3;
|
|
hlUInt uiDummy4;
|
|
hlUInt uiChecksum; // Header checksum.
|
|
};
|
|
|
|
struct GCFBlockEntry
|
|
{
|
|
hlUInt uiEntryFlags; // Flags for the block entry. 0x200F0000 == Not used.
|
|
hlUInt uiFileDataOffset; // The offset for the data contained in this block entry in the file.
|
|
hlUInt uiFileDataSize; // The length of the data in this block entry.
|
|
hlUInt uiFirstDataBlockIndex; // The index to the first data block of this block entry's data.
|
|
hlUInt uiNextBlockEntryIndex; // The next block entry in the series. (N/A if == BlockCount.)
|
|
hlUInt uiPreviousBlockEntryIndex; // The previous block entry in the series. (N/A if == BlockCount.)
|
|
hlUInt uiDirectoryIndex; // The index of the block entry in the directory.
|
|
};
|
|
|
|
struct GCFFragmentationMapHeader
|
|
{
|
|
hlUInt uiBlockCount; // Number of data blocks.
|
|
hlUInt uiFirstUnusedEntry; // The index of the first unused fragmentation map entry.
|
|
hlUInt uiTerminator; // The block entry terminator; 0 = 0x0000ffff or 1 = 0xffffffff.
|
|
hlUInt uiChecksum; // Header checksum.
|
|
};
|
|
|
|
struct GCFFragmentationMap
|
|
{
|
|
hlUInt uiNextDataBlockIndex; // The index of the next data block.
|
|
};
|
|
|
|
// The below section is part of version 5 but not version 6.
|
|
|
|
struct GCFBlockEntryMapHeader
|
|
{
|
|
hlUInt uiBlockCount; // Number of data blocks.
|
|
hlUInt uiFirstBlockEntryIndex; // Index of the first block entry.
|
|
hlUInt uiLastBlockEntryIndex; // Index of the last block entry.
|
|
hlUInt uiDummy0;
|
|
hlUInt uiChecksum; // Header checksum.
|
|
};
|
|
|
|
struct GCFBlockEntryMap
|
|
{
|
|
hlUInt uiPreviousBlockEntryIndex; // The previous block entry. (N/A if == BlockCount.)
|
|
hlUInt uiNextBlockEntryIndex; // The next block entry. (N/A if == BlockCount.)
|
|
};
|
|
|
|
// End section.
|
|
|
|
struct GCFDirectoryHeader
|
|
{
|
|
hlUInt uiDummy0; // Always 0x00000004
|
|
hlUInt uiCacheID; // Cache ID.
|
|
hlUInt uiLastVersionPlayed; // GCF file version.
|
|
hlUInt uiItemCount; // Number of items in the directory.
|
|
hlUInt uiFileCount; // Number of files in the directory.
|
|
hlUInt uiDummy1; // Always 0x00008000. Data per checksum?
|
|
hlUInt uiDirectorySize; // Size of lpGCFDirectoryEntries & lpGCFDirectoryNames & lpGCFDirectoryInfo1Entries & lpGCFDirectoryInfo2Entries & lpGCFDirectoryCopyEntries & lpGCFDirectoryLocalEntries in bytes.
|
|
hlUInt uiNameSize; // Size of the directory names in bytes.
|
|
hlUInt uiInfo1Count; // Number of Info1 entires.
|
|
hlUInt uiCopyCount; // Number of files to copy.
|
|
hlUInt uiLocalCount; // Number of files to keep local.
|
|
hlUInt uiDummy2;
|
|
hlUInt uiDummy3;
|
|
hlUInt uiChecksum; // Header checksum.
|
|
};
|
|
|
|
struct GCFDirectoryEntry
|
|
{
|
|
hlUInt uiNameOffset; // Offset to the directory item name from the end of the directory items.
|
|
hlUInt uiItemSize; // Size of the item. (If file, file size. If folder, num items.)
|
|
hlUInt uiChecksumIndex; // Checksome index. (0xFFFFFFFF == None).
|
|
hlUInt uiDirectoryFlags; // Flags for the directory item. (0x00000000 == Folder).
|
|
hlUInt uiParentIndex; // Index of the parent directory item. (0xFFFFFFFF == None).
|
|
hlUInt uiNextIndex; // Index of the next directory item. (0x00000000 == None).
|
|
hlUInt uiFirstIndex; // Index of the first directory item. (0x00000000 == None).
|
|
};
|
|
|
|
struct GCFDirectoryInfo1Entry
|
|
{
|
|
hlUInt uiDummy0;
|
|
};
|
|
|
|
struct GCFDirectoryInfo2Entry
|
|
{
|
|
hlUInt uiDummy0;
|
|
};
|
|
|
|
struct GCFDirectoryCopyEntry
|
|
{
|
|
hlUInt uiDirectoryIndex; // Index of the directory item.
|
|
};
|
|
|
|
struct GCFDirectoryLocalEntry
|
|
{
|
|
hlUInt uiDirectoryIndex; // Index of the directory item.
|
|
};
|
|
|
|
// The below header was added in version 4 or version 5.
|
|
|
|
struct GCFDirectoryMapHeader
|
|
{
|
|
hlUInt uiDummy0; // Always 0x00000001
|
|
hlUInt uiDummy1; // Always 0x00000000
|
|
};
|
|
|
|
struct GCFDirectoryMapEntry
|
|
{
|
|
hlUInt uiFirstBlockIndex; // Index of the first data block. (N/A if == BlockCount.)
|
|
};
|
|
|
|
struct GCFChecksumHeader
|
|
{
|
|
hlUInt uiDummy0; // Always 0x00000001
|
|
hlUInt uiChecksumSize; // Size of LPGCFCHECKSUMHEADER & LPGCFCHECKSUMMAPHEADER & in bytes.
|
|
};
|
|
|
|
struct GCFChecksumMapHeader
|
|
{
|
|
hlUInt uiDummy0; // Always 0x14893721
|
|
hlUInt uiDummy1; // Always 0x00000001
|
|
hlUInt uiItemCount; // Number of items.
|
|
hlUInt uiChecksumCount; // Number of checksums.
|
|
};
|
|
|
|
struct GCFChecksumMapEntry
|
|
{
|
|
hlUInt uiChecksumCount; // Number of checksums.
|
|
hlUInt uiFirstChecksumIndex; // Index of first checksum.
|
|
};
|
|
|
|
struct GCFChecksumEntry
|
|
{
|
|
hlULong uiChecksum; // Checksum.
|
|
};
|
|
|
|
struct GCFDataBlockHeader
|
|
{
|
|
hlUInt uiLastVersionPlayed; // GCF file version. This field is not part of all file versions.
|
|
hlUInt uiBlockCount; // Number of data blocks.
|
|
hlUInt uiBlockSize; // Size of each data block in bytes.
|
|
hlUInt uiFirstBlockOffset; // Offset to first data block.
|
|
hlUInt uiBlocksUsed; // Number of data blocks that contain data.
|
|
hlUInt uiChecksum; // Header checksum.
|
|
};
|
|
|
|
#pragma pack()
|
|
|
|
private:
|
|
static const char *lpAttributeNames[];
|
|
static const char *lpItemAttributeNames[];
|
|
|
|
Mapping::CView *pHeaderView;
|
|
|
|
GCFHeader *pHeader;
|
|
|
|
GCFBlockEntryHeader *pBlockEntryHeader;
|
|
GCFBlockEntry *lpBlockEntries;
|
|
|
|
GCFFragmentationMapHeader *pFragmentationMapHeader;
|
|
GCFFragmentationMap *lpFragmentationMap;
|
|
|
|
// The below section is part of version 5 but not version 6.
|
|
GCFBlockEntryMapHeader *pBlockEntryMapHeader;
|
|
GCFBlockEntryMap *lpBlockEntryMap;
|
|
|
|
GCFDirectoryHeader *pDirectoryHeader;
|
|
GCFDirectoryEntry *lpDirectoryEntries;
|
|
hlChar *lpDirectoryNames;
|
|
GCFDirectoryInfo1Entry *lpDirectoryInfo1Entries;
|
|
GCFDirectoryInfo2Entry *lpDirectoryInfo2Entries;
|
|
GCFDirectoryCopyEntry *lpDirectoryCopyEntries;
|
|
GCFDirectoryLocalEntry *lpDirectoryLocalEntries;
|
|
|
|
GCFDirectoryMapHeader *pDirectoryMapHeader;
|
|
GCFDirectoryMapEntry *lpDirectoryMapEntries;
|
|
|
|
GCFChecksumHeader *pChecksumHeader;
|
|
GCFChecksumMapHeader *pChecksumMapHeader;
|
|
GCFChecksumMapEntry *lpChecksumMapEntries;
|
|
GCFChecksumEntry *lpChecksumEntries;
|
|
|
|
GCFDataBlockHeader *pDataBlockHeader;
|
|
|
|
CDirectoryItem **lpDirectoryItems;
|
|
|
|
public:
|
|
CGCFFile();
|
|
virtual ~CGCFFile();
|
|
|
|
virtual HLPackageType GetType() const;
|
|
virtual const hlChar *GetExtension() const;
|
|
virtual const hlChar *GetDescription() const;
|
|
|
|
protected:
|
|
virtual hlBool MapDataStructures();
|
|
virtual hlVoid UnmapDataStructures();
|
|
|
|
virtual hlBool DefragmentInternal();
|
|
|
|
virtual CDirectoryFolder *CreateRoot();
|
|
|
|
virtual hlUInt GetAttributeCountInternal() const;
|
|
virtual const hlChar *GetAttributeNameInternal(HLPackageAttribute eAttribute) const;
|
|
virtual hlBool GetAttributeInternal(HLPackageAttribute eAttribute, HLAttribute &Attribute) const;
|
|
|
|
virtual hlUInt GetItemAttributeCountInternal() const;
|
|
virtual const hlChar *GetItemAttributeNameInternal(HLPackageAttribute eAttribute) const;
|
|
virtual hlBool GetItemAttributeInternal(const CDirectoryItem *pItem, HLPackageAttribute eAttribute, HLAttribute &Attribute) const;
|
|
|
|
virtual hlBool GetFileExtractableInternal(const CDirectoryFile *pFile, hlBool &bExtractable) const;
|
|
virtual hlBool GetFileValidationInternal(const CDirectoryFile *pFile, HLValidation &eValidation) const;
|
|
virtual hlBool GetFileSizeInternal(const CDirectoryFile *pFile, hlUInt &uiSize) const;
|
|
virtual hlBool GetFileSizeOnDiskInternal(const CDirectoryFile *pFile, hlUInt &uiSize) const;
|
|
|
|
virtual hlBool CreateStreamInternal(const CDirectoryFile *pFile, Streams::IStream *&pStream) const;
|
|
|
|
private:
|
|
hlVoid CreateRoot(CDirectoryFolder *pFolder);
|
|
|
|
hlVoid GetItemFragmentation(hlUInt uiDirectoryItemIndex, hlUInt &uiBlocksFragmented, hlUInt &uiBlocksUsed) const;
|
|
};
|
|
}
|
|
|
|
#endif
|