mirror of
https://github.com/tribes2/engine.git
synced 2026-03-05 13:30:24 +00:00
t2 engine svn checkout
This commit is contained in:
commit
ff569bd2ae
988 changed files with 394180 additions and 0 deletions
212
core/zipAggregate.cc
Normal file
212
core/zipAggregate.cc
Normal file
|
|
@ -0,0 +1,212 @@
|
|||
//-----------------------------------------------------------------------------
|
||||
// V12 Engine
|
||||
//
|
||||
// Copyright (c) 2001 GarageGames.Com
|
||||
// Portions Copyright (c) 2001 by Sierra Online, Inc.
|
||||
//-----------------------------------------------------------------------------
|
||||
|
||||
#include "Platform/platform.h"
|
||||
#include "Core/stringTable.h"
|
||||
|
||||
#include "Core/fileStream.h" // Streams
|
||||
|
||||
#include "Core/zipAggregate.h" // Own header, and private includes
|
||||
#include "Core/zipHeaders.h"
|
||||
|
||||
ZipAggregate::ZipAggregate()
|
||||
: m_pZipFileName(NULL)
|
||||
{
|
||||
VECTOR_SET_ASSOCIATION(m_fileList);
|
||||
}
|
||||
|
||||
ZipAggregate::~ZipAggregate()
|
||||
{
|
||||
closeAggregate();
|
||||
}
|
||||
|
||||
bool
|
||||
ZipAggregate::refreshAggregate()
|
||||
{
|
||||
AssertFatal(m_pZipFileName != NULL, "No filename? Must not be open. Disallowed");
|
||||
|
||||
char tmpBuff[512];
|
||||
dStrcpy(tmpBuff, m_pZipFileName);
|
||||
|
||||
return openAggregate(tmpBuff);
|
||||
}
|
||||
|
||||
bool
|
||||
ZipAggregate::openAggregate(const char* in_pFileName)
|
||||
{
|
||||
closeAggregate();
|
||||
|
||||
AssertFatal(in_pFileName != NULL, "No filename to open!");
|
||||
|
||||
m_pZipFileName = new char[dStrlen(in_pFileName) + 1];
|
||||
dStrcpy(m_pZipFileName, in_pFileName);
|
||||
|
||||
FileStream* pStream = new FileStream;
|
||||
if (pStream->open(m_pZipFileName, FileStream::Read) == false ||
|
||||
createZipDirectory(pStream) == false) {
|
||||
// Failure, abort the open...
|
||||
//
|
||||
delete pStream;
|
||||
|
||||
delete [] m_pZipFileName;
|
||||
m_pZipFileName = NULL;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Finished! Open for business
|
||||
delete pStream;
|
||||
return true;
|
||||
}
|
||||
|
||||
void
|
||||
ZipAggregate::closeAggregate()
|
||||
{
|
||||
destroyZipDirectory();
|
||||
|
||||
delete [] m_pZipFileName;
|
||||
m_pZipFileName = NULL;
|
||||
}
|
||||
|
||||
void
|
||||
ZipAggregate::destroyZipDirectory()
|
||||
{
|
||||
m_fileList.clear();
|
||||
}
|
||||
|
||||
bool
|
||||
ZipAggregate::createZipDirectory(Stream* io_pStream)
|
||||
{
|
||||
AssertFatal(io_pStream != NULL, "Error, stream not open.");
|
||||
|
||||
U32 streamSize = io_pStream->getStreamSize();
|
||||
U32 initialPosition = io_pStream->getPosition();
|
||||
|
||||
// We assume that the CD is 22 bytes from the end. This will be invalid
|
||||
// in the case that the zip file has comments. Perhaps test the quick
|
||||
// way, then degrade to seaching the final 64k+22b (!) of the stream?
|
||||
//
|
||||
bool posSuccess = io_pStream->setPosition(streamSize - sizeof(ZipEOCDRecord::EOCDRecord));
|
||||
if (posSuccess == false) {
|
||||
AssertWarn(false, "Unable to position stream to start of EOCDRecord");
|
||||
return false;
|
||||
}
|
||||
|
||||
ZipEOCDRecord* pEOCDRecord = new ZipEOCDRecord;
|
||||
if (pEOCDRecord->readFromStream(*io_pStream) == false) {
|
||||
// This is where we would try to degrade to general case...
|
||||
//
|
||||
AssertWarn(false, "Unable to locate central directory. "
|
||||
"Zip File might have comments");
|
||||
delete pEOCDRecord;
|
||||
return false;
|
||||
}
|
||||
|
||||
// Check the consistency of the zipFile.
|
||||
//
|
||||
if ((pEOCDRecord->m_record.diskNumber != pEOCDRecord->m_record.eocdDiskNumber) ||
|
||||
(pEOCDRecord->m_record.numCDEntriesDisk != pEOCDRecord->m_record.numCDEntriesTotal)) {
|
||||
AssertWarn(false, "Zipfile appears to be part of a "
|
||||
"multi-zip disk span set, unsupported");
|
||||
delete pEOCDRecord;
|
||||
return false;
|
||||
}
|
||||
|
||||
// If we're here, we're good! Scan to the start of the CDirectory, and
|
||||
// start scanning the entries into our directory structure...
|
||||
//
|
||||
U32 startCDPosition = pEOCDRecord->m_record.cdOffset;
|
||||
U32 endCDPosition = pEOCDRecord->m_record.cdOffset +
|
||||
pEOCDRecord->m_record.cdSize;
|
||||
|
||||
posSuccess = io_pStream->setPosition(startCDPosition);
|
||||
if (posSuccess == false) {
|
||||
AssertWarn(false, "Unable to position to CD entries.");
|
||||
delete pEOCDRecord;
|
||||
return false;
|
||||
}
|
||||
|
||||
bool dirReadSuccess = true;
|
||||
for (U16 i = 0; i < pEOCDRecord->m_record.numCDEntriesTotal; i++) {
|
||||
ZipDirFileHeader zdfHeader;
|
||||
|
||||
bool hrSuccess = zdfHeader.readFromStream(*io_pStream);
|
||||
if (hrSuccess == false) {
|
||||
AssertWarn(false, "Error reading a CD Entry in zip aggregate");
|
||||
dirReadSuccess = false;
|
||||
break;
|
||||
}
|
||||
|
||||
enterZipDirRecord(zdfHeader);
|
||||
}
|
||||
|
||||
delete pEOCDRecord;
|
||||
if (dirReadSuccess == true) {
|
||||
// Every thing went well, we're done, position the stream to the end of the
|
||||
// CD...
|
||||
//
|
||||
io_pStream->setPosition(endCDPosition);
|
||||
return true;
|
||||
} else {
|
||||
// Oh, crap.
|
||||
io_pStream->setPosition(initialPosition);
|
||||
destroyZipDirectory();
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
void
|
||||
ZipAggregate::enterZipDirRecord(const ZipDirFileHeader& in_rHeader)
|
||||
{
|
||||
// Ok, the first thing to do is figure out whether this is
|
||||
// a directory or a file. Directories have a trailing /
|
||||
// in the file name, and a filelength (comp/uncomp) of 0
|
||||
// Note: this is not specified in
|
||||
// the file format spec I have, but seems fairly likely to
|
||||
// be correct.
|
||||
//
|
||||
if (in_rHeader.m_pFileName[dStrlen(in_rHeader.m_pFileName) - 1] == '/' &&
|
||||
(in_rHeader.m_header.compressedSize == 0 &&
|
||||
in_rHeader.m_header.uncompressedSize == 0))
|
||||
return;
|
||||
|
||||
// It's a file. Enter it into the directory...
|
||||
m_fileList.increment();
|
||||
FileEntry& rEntry = m_fileList.last();
|
||||
|
||||
char tempString[1024];
|
||||
dStrcpy(tempString, in_rHeader.m_pFileName);
|
||||
char* scan = tempString;
|
||||
while (*scan != '\0') {
|
||||
if (*scan == '\\')
|
||||
*scan = '/';
|
||||
scan++;
|
||||
}
|
||||
char* pPathEnd = dStrrchr(tempString, '/');
|
||||
if (pPathEnd != NULL) {
|
||||
pPathEnd[0] = '\0';
|
||||
rEntry.pPath = StringTable->insert(tempString);
|
||||
rEntry.pFileName = StringTable->insert(pPathEnd + 1);
|
||||
} else {
|
||||
rEntry.pPath = NULL;
|
||||
rEntry.pFileName = StringTable->insert(in_rHeader.m_pFileName);
|
||||
}
|
||||
|
||||
rEntry.fileSize = in_rHeader.m_header.uncompressedSize;
|
||||
rEntry.compressedFileSize = in_rHeader.m_header.compressedSize;
|
||||
rEntry.fileOffset = in_rHeader.m_header.relativeOffsetOfLocalHeader;
|
||||
|
||||
if (in_rHeader.m_header.compressionMethod == ZipDirFileHeader::Deflated) {
|
||||
rEntry.flags = FileEntry::Compressed;
|
||||
} else if (in_rHeader.m_header.compressionMethod == ZipDirFileHeader::Stored) {
|
||||
rEntry.flags = FileEntry::Uncompressed;
|
||||
} else {
|
||||
AssertWarn(0, avar("Warning, non-stored or deflated resource in %s",
|
||||
m_pZipFileName));
|
||||
m_fileList.decrement();
|
||||
}
|
||||
}
|
||||
|
||||
Loading…
Add table
Add a link
Reference in a new issue