📄 resfile.cpp
字号:
/*
* ============================================================================
* Name : CResFile from ResFile.cpp
* Part of : Game
* Created : 2003-06-16 by Qiu Wei Min
* Implementation notes:
* Modified : 2003-09-03 by Zheng Jie Sheng
* To decompress from zlib compressed package. Using old packing tool.
Modified : 2004-10-04 by Wang Zhendong
* To decompress from lzma compressed package. Using new packing tool.
* Version :
* Copyright: Gameloft S.A.
*
* ============================================================================
*/
// INCLUDE FILES
#include <AEE.h>
#include <AEEfile.h>
#include <AEEStdLib.h>
#include "simplememory.h"
#include "resfile.h"
#include "gfx.h"
//#include "game.h"
// ================= MEMBER FUNCTIONS =======================
// Base
//const int Sign8_cos[] = {0, 1, 1, 1, 0, -1, -1, -1};
//const int Sign8_sin[] = {-1, -1, 0, 1, 1, 1, 0, -1};
CResFile::CResFile(CEngine *pEngine)
{
m_pEngine = pEngine;
m_nEntry = 0;
m_handle = NULL;
CSimpleMemory::Fill((void*)&m_f, 0, sizeof(FileIO));
/*
m_pZlib = NULL;
m_pZlib = new CZLibBrew();
SYS_ASSERT(NULL != m_pZlib);
if(m_pZlib)
{
}
*/
}
CResFile::~CResFile()
{
if(m_handle)
{
IFILE_Release((IFile*)m_handle);
m_handle = NULL;
}
/*
if(m_pZlib)
{
delete m_pZlib;
m_pZlib = NULL;
}
*/
}
bool CResFile::Open(const char *fn)
{
int iRet = 0;
long nPak; //number of pakage entry
m_handle = IFILEMGR_OpenFile ((IFileMgr*) m_pEngine->pFileMgr ,fn, _OFM_READ);
SYS_ASSERT(NULL != m_handle);
if(NULL ==m_handle)
return false;
m_f.isPaked = (char)(m_handle !=NULL);
int size;
iRet = IFILE_Read(m_handle, &nPak, sizeof(nPak));
if(iRet != sizeof(nPak))
{
return false;
}
m_nEntry = (int)nPak;
SYS_ASSERT(nPak >= 0 && nPak <=64000); //max file number on brew.
size = sizeof(struct Pak ) + nPak *sizeof(struct PakEntry);
m_f.pak = (struct Pak*)m_pEngine->GetMem()->GlobalMalloc(size);
SYS_ASSERT(NULL != m_f.pak);
if(NULL == m_f.pak)
return false;
IFILE_Seek(m_handle,_SEEK_START,0);
IFILE_Read(m_handle, m_f.pak, size);
return true;
}
void* CResFile::FindRecord(const char *name)
{
unsigned long h = ComputeHash(name);
int i;
struct PakEntry *p;
for(i=0, p=m_f.pak->aPak; i<m_f.pak->nPak; i++, p++){
if(p->nameHash == h)
return p;//(void*)i;
}
SYS_ASSERT(0);//open failed
return NULL;
}
unsigned long CResFile::ComputeHash(const char *s)
{
unsigned long h=0;
const char *p;
for(p = s; *p ; p ++)
h = ( h << 5 ) - h + *p;
return h;
}
void* CResFile::ReadToStack(void *hRecord)
{
int len = GetDecompressedSize(hRecord);
if(len>=0)
{
void* p = m_pEngine->GetMem()->StackMalloc(len);
if(NULL != p)
{
if(Read(hRecord, p, len))
return p;
m_pEngine->GetMem()->StackFree(p);
}
}
return NULL;
}
int CResFile::LoadFileToStack(const char *fName, void **pData)
{
*pData = NULL;
void *h = FindRecord(fName);
SYS_ASSERT(NULL != h);
if(NULL == h)
return -1;
void *p = ReadToStack(h);
if(p)
{
int size = GetDecompressedSize(h);
if(size >= 0)
{
*pData = p;
return size;// read to stack ok
}
m_pEngine->GetMem()->StackFree(NULL);
}
return -1;
}
// Size after compression
int CResFile::GetRecordSize(void *hRecord)
{
PakEntry *p = (PakEntry*)hRecord;
SYS_ASSERT(p != NULL);
if(NULL == p)
return -1;
return p->len;
}
// Size before compression
int CResFile::GetDecompressedSize(void *hRecord)
{
int iRet = -1;
PakEntry *p = (PakEntry*)hRecord;
if(SUCCESS != IFILE_Seek((IFile*)m_handle, _SEEK_START, (p->start<<2)))
{
return -1;
}
unsigned char properties[5] ;
int ii,outSize;
IFILE_Read((IFile*)m_handle,properties,5);
outSize = 0;
for (ii = 0; ii < 4; ii++)
{
unsigned char b;
IFILE_Read((IFile*)m_handle,&b,1);
outSize += (unsigned int)(b) << (ii * 8);
}
if (outSize == 0xFFFFFFFF)
{
//DBGPRINTF("outSize:%d",outSize);
return NULL;
}
for (ii = 0; ii < 4; ii++)
{
unsigned char b;
IFILE_Read((IFile*)m_handle,&b,1);
if (b != 0)
{
//DBGPRINTF("\n too long file");
return -1;
}
}
return outSize;
}
bool CResFile::Read(void *hRecord, void *pBuf, int len, int ofs)
{
struct PakEntry *p = (struct PakEntry*)hRecord;
if(len == -1)
return false;
int iCompressedSize = GetRecordSize(hRecord);
SYS_ASSERT( iCompressedSize >= 0);
if(iCompressedSize < 0)
return false;
if(SUCCESS != IFILE_Seek((IFile*)m_handle, _SEEK_START, (p->start<<2)+ ofs))
{
return false;
}
unsigned int length;
unsigned int compressedSize, outSize, outSizeProcessed, lzmaInternalSize;
void *inStream, *lzmaInternalData;
unsigned char properties[5];
unsigned char prop0;
int ii;
int lc, lp, pb;
int res;
long crc = 0;
length = iCompressedSize;
IFILE_Read((IFile*)m_handle,properties,5);
outSize = 0;
for (ii = 0; ii < 4; ii++)
{
unsigned char b;
IFILE_Read((IFile*)m_handle,&b,1);
outSize += (unsigned int)(b) << (ii * 8);
}
if (outSize == 0xFFFFFFFF)
{
//DBGPRINTF("outSize:%d",outSize);
return NULL;
}
for (ii = 0; ii < 4; ii++)
{
unsigned char b;
IFILE_Read((IFile*)m_handle,&b,1);
if (b != 0)
{
//DBGPRINTF("\n too long file");
return false;
}
}
compressedSize = length - 13;
inStream = m_pEngine->GetMem()->StackMalloc(compressedSize);
if (inStream == NULL)
{
//DBGPRINTF("can't allocate1");
return false;
}
IFILE_Read((IFile*)m_handle,inStream,compressedSize);
prop0 = properties[0];
if (prop0 >= (9*5*5))
{
//DBGPRINTF("Properties error");
return NULL;
}
for (pb = 0; prop0 >= (9 * 5);
pb++, prop0 -= (9 * 5));
for (lp = 0; prop0 >= 9;
lp++, prop0 -= 9);
lc = prop0;
lzmaInternalSize = (LZMA_BASE_SIZE + (LZMA_LIT_SIZE << (lc + lp)))* sizeof(unsigned short);
lzmaInternalData = m_pEngine->GetMem()->StackMalloc(lzmaInternalSize);
if ( lzmaInternalData == 0)
{
//DBGPRINTF("can't allocate2");
return NULL;
}
res = LzmaDecode((unsigned char *)lzmaInternalData, lzmaInternalSize,
lc, lp, pb,
#ifdef _LZMA_IN_CB
&bo.InCallback,
#else
(unsigned char *)inStream, compressedSize,
#endif
(unsigned char *)pBuf, len, &outSizeProcessed,NULL);
m_pEngine->GetMem()->StackFree(lzmaInternalData);
m_pEngine->GetMem()->StackFree(inStream);
if(res == 0)
return true;
else
return false;
}
#define kNumTopBits 24
#define kTopValue ((UInt32)1 << kNumTopBits)
#define kNumBitModelTotalBits 11
#define kBitModelTotal (1 << kNumBitModelTotalBits)
#define kNumMoveBits 5
Byte CResFile::RangeDecoderReadByte(CRangeDecoder *rd)
{
if (rd->Buffer == rd->BufferLim)
{
#ifdef _LZMA_IN_CB
UInt32 size;
rd->Result = rd->InCallback->Read(rd->InCallback, &rd->Buffer, &size);
rd->BufferLim = rd->Buffer + size;
if (size == 0)
#endif
{
rd->ExtraBytes = 1;
return 0xFF;
}
}
return (*rd->Buffer++);
}
/* #define ReadByte (*rd->Buffer++) */
#define ReadByte (RangeDecoderReadByte(rd))
void CResFile::RangeDecoderInit(CRangeDecoder *rd,
#ifdef _LZMA_IN_CB
ILzmaInCallback *inCallback
#else
Byte *stream, UInt32 bufferSize
#endif
)
{
int i;
#ifdef _LZMA_IN_CB
rd->InCallback = inCallback;
rd->Buffer = rd->BufferLim = 0;
#else
rd->Buffer = stream;
rd->BufferLim = stream + bufferSize;
#endif
rd->ExtraBytes = 0;
rd->Code = 0;
rd->Range = (0xFFFFFFFF);
for(i = 0; i < 5; i++)
rd->Code = (rd->Code << 8) | ReadByte;
}
#define RC_INIT_VAR UInt32 range = rd->Range; UInt32 code = rd->Code;
#define RC_FLUSH_VAR rd->Range = range; rd->Code = code;
#define RC_NORMALIZE if (range < kTopValue) { range <<= 8; code = (code << 8) | ReadByte; }
UInt32 CResFile::RangeDecoderDecodeDirectBits(CRangeDecoder *rd, int numTotalBits)
{
RC_INIT_VAR
UInt32 result = 0;
int i;
for (i = numTotalBits; i > 0; i--)
{
/* UInt32 t; */
range >>= 1;
result <<= 1;
if (code >= range)
{
code -= range;
result |= 1;
}
/*
t = (code - range) >> 31;
t &= 1;
code -= range & (t - 1);
result = (result + result) | (1 - t);
*/
RC_NORMALIZE
}
RC_FLUSH_VAR
return result;
}
int CResFile::RangeDecoderBitDecode(CProb *prob, CRangeDecoder *rd)
{
UInt32 bound = (rd->Range >> kNumBitModelTotalBits) * *prob;
if (rd->Code < bound)
{
rd->Range = bound;
*prob += (kBitModelTotal - *prob) >> kNumMoveBits;
if (rd->Range < kTopValue)
{
rd->Code = (rd->Code << 8) | ReadByte;
rd->Range <<= 8;
}
return 0;
}
else
{
rd->Range -= bound;
rd->Code -= bound;
*prob -= (*prob) >> kNumMoveBits;
if (rd->Range < kTopValue)
{
rd->Code = (rd->Code << 8) | ReadByte;
rd->Range <<= 8;
}
return 1;
}
}
#define RC_GET_BIT2(prob, mi, A0, A1) \
UInt32 bound = (range >> kNumBitModelTotalBits) * *prob; \
if (code < bound) \
{ A0; range = bound; *prob += (kBitModelTotal - *prob) >> kNumMoveBits; mi <<= 1; } \
else \
{ A1; range -= bound; code -= bound; *prob -= (*prob) >> kNumMoveBits; mi = (mi + mi) + 1; } \
RC_NORMALIZE
#define RC_GET_BIT(prob, mi) RC_GET_BIT2(prob, mi, ; , ;)
int CResFile::RangeDecoderBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
{
int mi = 1;
int i;
#ifdef _LZMA_LOC_OPT
RC_INIT_VAR
#endif
for(i = numLevels; i > 0; i--)
{
#ifdef _LZMA_LOC_OPT
CProb *prob = probs + mi;
RC_GET_BIT(prob, mi)
#else
mi = (mi + mi) + RangeDecoderBitDecode(probs + mi, rd);
#endif
}
#ifdef _LZMA_LOC_OPT
RC_FLUSH_VAR
#endif
return mi - (1 << numLevels);
}
int CResFile::RangeDecoderReverseBitTreeDecode(CProb *probs, int numLevels, CRangeDecoder *rd)
{
int mi = 1;
int i;
int symbol = 0;
#ifdef _LZMA_LOC_OPT
RC_INIT_VAR
#endif
for(i = 0; i < numLevels; i++)
{
#ifdef _LZMA_LOC_OPT
CProb *prob = probs + mi;
RC_GET_BIT2(prob, mi, ; , symbol |= (1 << i))
#else
int bit = RangeDecoderBitDecode(probs + mi, rd);
mi = mi + mi + bit;
symbol |= (bit << i);
#endif
}
#ifdef _LZMA_LOC_OPT
RC_FLUSH_VAR
#endif
return symbol;
}
Byte CResFile::LzmaLiteralDecode(CProb *probs, CRangeDecoder *rd)
{
int symbol = 1;
#ifdef _LZMA_LOC_OPT
RC_INIT_VAR
#endif
do
{
#ifdef _LZMA_LOC_OPT
CProb *prob = probs + symbol;
RC_GET_BIT(prob, symbol)
#else
symbol = (symbol + symbol) | RangeDecoderBitDecode(probs + symbol, rd);
#endif
}
while (symbol < 0x100);
#ifdef _LZMA_LOC_OPT
RC_FLUSH_VAR
#endif
return symbol;
}
Byte CResFile::LzmaLiteralDecodeMatch(CProb *probs, CRangeDecoder *rd, Byte matchByte)
{
int symbol = 1;
#ifdef _LZMA_LOC_OPT
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -