2004-05-29 22:48:08 +02:00
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
//
|
|
|
|
// Name: FileUnpacker.cpp
|
|
|
|
// Author: Rich Cross
|
|
|
|
// Contact: rich@wildfiregames.com
|
|
|
|
//
|
|
|
|
///////////////////////////////////////////////////////////////////////////////
|
|
|
|
|
2004-06-03 20:38:14 +02:00
|
|
|
#include "precompiled.h"
|
|
|
|
|
2004-05-29 22:48:08 +02:00
|
|
|
#include "FileUnpacker.h"
|
2005-08-12 19:06:53 +02:00
|
|
|
#include "lib/res/res.h"
|
2004-05-29 22:48:08 +02:00
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// CFileUnpacker constructor
|
2004-09-19 20:51:19 +02:00
|
|
|
CFileUnpacker::CFileUnpacker()
|
2004-05-29 22:48:08 +02:00
|
|
|
{
|
2004-09-19 20:51:19 +02:00
|
|
|
m_Buf = 0;
|
|
|
|
m_Size = 0;
|
|
|
|
m_UnpackPos = 0;
|
|
|
|
m_Version = 0;
|
2004-05-29 22:48:08 +02:00
|
|
|
}
|
|
|
|
|
2004-12-28 17:17:17 +01:00
|
|
|
CFileUnpacker::~CFileUnpacker()
|
|
|
|
{
|
2006-01-24 09:16:29 +01:00
|
|
|
file_buf_free(m_Buf);
|
2004-12-28 17:17:17 +01:00
|
|
|
}
|
|
|
|
|
2004-05-29 22:48:08 +02:00
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// Read: open and read in given file, check magic bits against those given; throw
|
|
|
|
// variety of exceptions for missing files etc
|
|
|
|
void CFileUnpacker::Read(const char* filename,const char magicstr[4])
|
|
|
|
{
|
2004-12-15 15:24:12 +01:00
|
|
|
// avoid vfs_load complaining about missing data files (which happens
|
|
|
|
// too often). better to check here than squelch internal VFS error
|
|
|
|
// reporting. we disable this in release mode to avoid a speed hit.
|
2005-07-30 22:12:41 +02:00
|
|
|
// UPDATE: We don't disable this in release mode, because vfs_load now
|
|
|
|
// complains about missing files when running in release
|
|
|
|
//#ifndef NDEBUG
|
2004-12-15 15:24:12 +01:00
|
|
|
if(!vfs_exists(filename))
|
|
|
|
throw CFileOpenError();
|
2005-07-30 22:12:41 +02:00
|
|
|
//#endif
|
2004-12-15 15:24:12 +01:00
|
|
|
|
2004-08-11 22:18:49 +02:00
|
|
|
// load the whole thing into memory
|
2006-01-24 09:16:29 +01:00
|
|
|
if(vfs_load(filename, m_Buf, m_Size) < 0)
|
2004-08-11 22:18:49 +02:00
|
|
|
throw CFileOpenError();
|
|
|
|
|
|
|
|
// make sure we read enough for the header
|
2004-09-19 20:51:19 +02:00
|
|
|
if(m_Size < 12)
|
2004-08-11 22:18:49 +02:00
|
|
|
{
|
2006-01-24 09:16:29 +01:00
|
|
|
(void)file_buf_free(m_Buf);
|
2004-09-19 20:51:19 +02:00
|
|
|
m_Buf = 0;
|
|
|
|
m_Size = 0;
|
2004-08-11 22:18:49 +02:00
|
|
|
throw CFileReadError();
|
|
|
|
}
|
|
|
|
|
|
|
|
// extract data from header
|
2004-09-19 20:51:19 +02:00
|
|
|
u8* header = (u8*)m_Buf;
|
2004-08-11 22:18:49 +02:00
|
|
|
char* magic = (char*)(header+0);
|
2004-09-21 16:33:13 +02:00
|
|
|
// FIXME m_Version and datasize: Byte order? -- Simon
|
2004-08-11 22:18:49 +02:00
|
|
|
m_Version = *(u32*)(header+4);
|
|
|
|
u32 datasize = *(u32*)(header+8);
|
|
|
|
|
|
|
|
// check we've got the right kind of file
|
|
|
|
// .. and that we read exactly headersize+datasize
|
|
|
|
if(strncmp(magic, magicstr, 4) != 0 ||
|
2004-09-19 20:51:19 +02:00
|
|
|
m_Size != 12+datasize)
|
2004-08-11 22:18:49 +02:00
|
|
|
{
|
2006-01-24 09:16:29 +01:00
|
|
|
(void)file_buf_free(m_Buf);
|
2004-09-19 20:51:19 +02:00
|
|
|
m_Buf = 0;
|
|
|
|
m_Size = 0;
|
2004-08-11 22:18:49 +02:00
|
|
|
throw CFileTypeError();
|
|
|
|
}
|
2004-09-19 21:22:18 +02:00
|
|
|
|
|
|
|
m_UnpackPos = 12;
|
2004-05-29 22:48:08 +02:00
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// UnpackRaw: unpack given number of bytes from the input stream into the given array
|
|
|
|
// - throws CFileEOFError if the end of the data stream is reached before the given
|
|
|
|
// number of bytes have been read
|
|
|
|
void CFileUnpacker::UnpackRaw(void* rawdata,u32 rawdatalen)
|
|
|
|
{
|
|
|
|
// got enough data to unpack?
|
2004-09-19 20:51:19 +02:00
|
|
|
if (m_UnpackPos+rawdatalen<=m_Size)
|
|
|
|
{
|
2004-05-29 22:48:08 +02:00
|
|
|
// yes .. copy over
|
2004-09-19 20:51:19 +02:00
|
|
|
void* src = (char*)m_Buf + m_UnpackPos;
|
2005-10-30 17:19:20 +01:00
|
|
|
memcpy2(rawdata, src, rawdatalen);
|
2004-09-19 20:51:19 +02:00
|
|
|
m_UnpackPos += rawdatalen;
|
|
|
|
}
|
|
|
|
else
|
2004-05-29 22:48:08 +02:00
|
|
|
// nope - throw exception
|
|
|
|
throw CFileEOFError();
|
|
|
|
}
|
|
|
|
|
|
|
|
////////////////////////////////////////////////////////////////////////////////////////
|
|
|
|
// UnpackString: unpack a string from the raw data stream
|
2004-09-21 16:33:13 +02:00
|
|
|
// - throws CFileEOFError if eof is reached before the string length has been
|
|
|
|
// satisfied
|
2004-05-29 22:48:08 +02:00
|
|
|
void CFileUnpacker::UnpackString(CStr& result)
|
|
|
|
{
|
|
|
|
// get string length
|
|
|
|
u32 length;
|
2004-09-21 16:33:13 +02:00
|
|
|
UnpackRaw(&length,sizeof(length)); // FIXME Byte order? -- Simon
|
2004-05-29 22:48:08 +02:00
|
|
|
|
2004-09-21 16:33:13 +02:00
|
|
|
if (m_UnpackPos + length <= m_Size)
|
|
|
|
{
|
|
|
|
result=std::string((char *)m_Buf+m_UnpackPos, length);
|
|
|
|
m_UnpackPos += length;
|
|
|
|
}
|
|
|
|
else
|
|
|
|
throw CFileEOFError();
|
2004-05-29 22:48:08 +02:00
|
|
|
}
|
|
|
|
|