Example #1
0
// if user wants result to buffer?
void QXpkLib::getToBuffer(QByteArray &Array)
{
	CIOBuffer *pOut = m_pMaster->getResult();
	
	// reserve out-buffer and copy what we have
	Array.resize(pOut->GetCurrentPos());
	::memcpy(Array.data(), pOut->GetBegin(), pOut->GetCurrentPos());
}
Example #2
0
//////////////////
//
// XPK fileformat:
// chunk-based, crunched data in chunks
//
// Chunk format:
// * chunk header
// - 1 byte for chunk type
// - 1 byte for chunk header checksum ?
// - 2 bytes for chunk checksum
// - 2/4 bytes for chunk (compressed) length
// - 2/4 bytes for uncompressed length?
// * chunk data
// - amount of packed data given in chunk header..
//
// Note: chunk header may have different size in different file
// according to flags (if "long" sizes are used for chunks).
//
//
void XpkTags::ReadChunks(CIOBuffer &Buffer)
{
	m_pFirst = new XpkChunk();
	m_pFirst->m_nDataOffset = Buffer.GetCurrentPos();

	XpkChunk *pCurrent = m_pFirst;
	while (Buffer.IsEnd() == false)
	{
		bool isValidHeader = false;
		if (m_streamHeader.xsh_Flags & XPKSTREAMF_LONGHEADERS)
		{
			XpkChunkHdrLong *pHdr = (XpkChunkHdrLong*)Buffer.GetAtCurrent();
			
			pCurrent->m_Type = pHdr->xchl_Type;
			pCurrent->m_HChecksum = pHdr->xchl_HChk;
			pCurrent->m_ChunkChecksum = Swap2(pHdr->xchl_CChk);
			pCurrent->m_ChunkLength = Swap4(pHdr->xchl_CLen);
			pCurrent->m_UnLen = Swap4(pHdr->xchl_ULen);
			
			pCurrent->m_nDataOffset += sizeof(XpkChunkHdrLong);
			isValidHeader = verifyHeaderLong(pHdr);
		}
		else
		{
			XpkChunkHdrWord *pHdr = (XpkChunkHdrWord*)Buffer.GetAtCurrent();
			
			pCurrent->m_Type = pHdr->xchw_Type;
			pCurrent->m_HChecksum = pHdr->xchw_HChk;
			pCurrent->m_ChunkChecksum = Swap2(pHdr->xchw_CChk);
			pCurrent->m_ChunkLength = Swap2(pHdr->xchw_CLen);
			pCurrent->m_UnLen = Swap2(pHdr->xchw_ULen);

			pCurrent->m_nDataOffset += sizeof(XpkChunkHdrWord);
			isValidHeader = verifyHeaderWord(pHdr);
		}
		
		// TODO: need header checksum verification somewhere around here..
		if (isValidHeader == false)
		{
			// TODO: exception or skip ?
		}
		
		if (pCurrent->m_Type != XPKCHUNK_RAW
			&& pCurrent->m_Type != XPKCHUNK_PACKED
			&& pCurrent->m_Type != XPKCHUNK_END)
		{
			// TODO: exception or skip ?
		}
		
		// move to actual data of chunk (according to chunk header size)
		Buffer.SetCurrentPos(pCurrent->m_nDataOffset);

		// "end-of-file" chunk? (empty)
		if (pCurrent->m_Type == XPKCHUNK_END)
		{
			return;
		}
		
		// TODO:
		// .. process chunk
		// -> walkthrough in XPK-master now..
		
		// offset to start of next chunk:
		// start of data in current + size of data in current
		size_t nNextChunkOffset = pCurrent->m_nDataOffset + pCurrent->m_ChunkLength;
		Buffer.SetCurrentPos(nNextChunkOffset);
		
		pCurrent->m_pNext = new XpkChunk(pCurrent);
		pCurrent->m_pNext->m_nDataOffset = nNextChunkOffset;
		pCurrent = pCurrent->m_pNext;
	}
}
Example #3
0
//////////////////
//
// XPK fileformat:
// chunk-based, crunched data in chunks
// 
// File header:
// starts as common IFF-style header:
// - 4-byte ID, 'XPKF'
// - 4-byte int for filesize minus header (8)
// - 4-byte sub-type (cruncher-ID) e.g. 'SQSH'
// - 4-byte int for total uncompressed length ?
// - first 16-bytes of original file
// - 1 byte for flags
// - 1 byte for header checksum ?
// - 1 byte for minor version of cruncher/library ?
//  - actually version required of sub-library..
// - 1 byte for major version of cruncher/library ?
//
bool XpkTags::ReadStreamHeader(CIOBuffer &Buffer)
{
	// should have enough data to actually parse file header
	if (Buffer.GetSize() < sizeof(XpkStreamHeader))
	{
		return false;
	}
	
	if (isXpkFile(Buffer.GetBegin()) == false)
	{
		return false;
	}
	Buffer.SetCurrentPos(0); // start at beginning if not already..
	
	// set default
	m_formatType = XPKMODE_UPSTD;
	
	// "XPKF", 0x58504b46 (XPK_COOKIE, magic number)
	// note: support also XFD-packed files? ("XFDD")
	m_streamHeader.xsh_PackID = GetULong(Buffer.GetNext(4));
	
	if (m_streamHeader.xsh_PackID != MakeTag("XPKF"))
	// this too ? && m_streamHeader.xsh_PackID != MakeTag("XFDD"))
	{
		return false;
	}
	
	// file length without IFF header (type+length = 8) ?
	m_streamHeader.xsh_CompressedLen = GetULong(Buffer.GetNext(4));
	
	// keep packer type as type name/ID,
	// just access as-is
	m_typeName.assign((char*)Buffer.GetAtCurrent(), 4);
	
	// packer type, e.g. "SQSH", "NUKE", "RLEN"..
	m_streamHeader.xsh_PackerType = GetULong(Buffer.GetNext(4));
	
	// TODO: check supported types..? if != MakeTag()..
	// -> caller/parent should do (knows libraries..)
	
	// uncompressed length?
	m_streamHeader.xsh_UnpackedLen = GetULong(Buffer.GetNext(4));

	// first 16 bytes of original file
	::memcpy(m_streamHeader.xsh_Initial, Buffer.GetNext(16), 16);
	
	// flags
	m_streamHeader.xsh_Flags = Buffer.GetNextByte();
	
	/*
	// also check "XFDD", 0x58464444 in file ID?
	if (m_streamHeader.xsh_Flags & XMF_XFD && m_streamHeader.xsh_PackID == MakeTag("XFDD"))
	{
		m_formatType = XPKMODE_UPXFD;
	}
	
	if (m_streamHeader.xsh_Flags & XMF_PASSTHRU)
	{
		// unpacked?
		m_formatType = XPKMODE_UPUP;
	}
	
	if (m_streamHeader.xsh_Flags & XPKSTREAMF_PASSWORD)
	{
		// password-protected file?
	}
	*/
	
	// ..no idea.. header checksum?
	m_streamHeader.xsh_HeaderChk = Buffer.GetNextByte();
	
	// minor&major version of XPK master/cruncher?
	m_streamHeader.xsh_SubVrs = Buffer.GetNextByte(); // sub-library version required?
	m_streamHeader.xsh_MasVrs = Buffer.GetNextByte();
	
	// TODO: remove later, debug-test..
	if (Buffer.GetCurrentPos() != sizeof(XpkStreamHeader))
	{
		throw IOException("Read size does not match stream-header size");
	}
	
	// non-zero header checksum? (note where doing checksumming..)
    if (hchecksum(Buffer.GetBegin(), sizeof(XpkStreamHeader)) != 0)
    {
		throw ArcException("Header checksum error", m_streamHeader.xsh_HeaderChk);
    }
    
    // has extended header?
    if (m_streamHeader.xsh_Flags & XPKSTREAMF_EXTHEADER)
    {
		// size of extended header if present?
		m_extHeaderLen = GetUWord(Buffer.GetNext(2));
		
		/*
		// this done above..		
	    if(!hookread(xbuf, XIO_READ, &exthlen, sizeof(UWORD)))
			goto Abort; -> exception
			
		// no read, just skip it??
        if(!hookread(xbuf, XIO_READ, NULL, exthlen))
			goto Abort; -> exception
			
		// later it is read anyway, why not just directly when detected?
			
		*/
		
		// increment by length-field size anyway..
        m_extHeaderLen += sizeof(uint16_t);	/* for unwinding while XpkExamine */
        
        // note: increase buffer position by size of extended header?
	}

	// header parsed, should be valid file?	
	return true;
}