📄 imgdata.cpp
字号:
case RUNTYPE_DATATOKEN:
// A data run takes up the amount of data in the run itself, plus
// the length of the type and length. Type and length are bit
// backed together, and will take between 1 and 4 bytes to encode,
// depending on the length.
if (pRun->dwRunLength < (1 << 5)) {
dwLen += 1;
} else if (pRun->dwRunLength < (1 << 13)) {
dwLen += 2;
} else if (pRun->dwRunLength < (1 << 21)) {
dwLen += 3;
} else {
dwLen += 4;
}
// Intentional Fallthrough
case RUNTYPE_RAWDATA:
case RUNTYPE_ZEROBLOCK:
dwLen += pRun->dwRunLength;
break;
case RUNTYPE_COPYTOKEN:
if (pRun->dwRunLength < (1 << 4)) {
dwLen += 4;
} else if (pRun->dwRunLength < (1 << 12)) {
dwLen += 5;
} else if (pRun->dwRunLength < (1 << 20)) {
dwLen += 6;
} else {
dwLen += 7;
}
if (m_tt.Lookup(pRun->dwOffset).iOffset != NO_COMPRESS) {
if (m_cCompressedRegions < (1 << 8)) {
dwLen += 1;
} else if (m_cCompressedRegions < (1 << 16)) {
dwLen += 2;
} else {
dwLen += 3;
}
}
break;
case RUNTYPE_COMPRESSIONCOMMANDS:
{
CSectionData *pSection = (CSectionData*)pRun->dwOffset;
dwLen += pSection->GetCountCompressionCommands() * 6 + 3;
}
break;
default:
ASSERT(0);
break;
}
return dwLen;
} /* CImageData::TokenLen()
*/
////////////////////////////////////////////////////////////
// FindCompressedRegions
// Find the regions that were compressed before
// being packed into the image.
////////////////////////////////////////////////////////////
HRESULT
CImageData::FindCompressedRegions()
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
HRESULT hr = NOERROR;
UINT32 i;
UINT32 j;
m_cCompressedRegions = 0;
//
// Find compressed files
//
for (i = 0; i < m_cFiles; i++)
{
FILESentry *pEntry = GetFile(i);
CBR(pEntry);
if ((pEntry->dwFileAttributes & FILE_ATTRIBUTE_COMPRESSED) && (pEntry->nRealFileSize > pEntry->nCompFileSize))
{
if (m_cCompressedRegions % NUM_COMPRESSED == 0) {
CHR(SafeRealloc((LPVOID*)&m_pCompressedRegions, (m_cCompressedRegions + NUM_COMPRESSED) * sizeof(COMPR_RGN)));
}
m_pCompressedRegions[m_cCompressedRegions].iAddress = pEntry->ulLoadOffset;
m_pCompressedRegions[m_cCompressedRegions].cBytesCompressed = pEntry->nCompFileSize;
m_pCompressedRegions[m_cCompressedRegions].cBytesUncompressed = pEntry->nRealFileSize;
m_cCompressedRegions++;
}
}
//
// Find compressed sections within Modules
//
for(i = 0; i < m_cModules; i++) {
o32_rom *rgO32 = GetO32List(i);
if(rgO32) {
e32_rom *pE32 = GetE32(i);
CBRA(pE32);
for(j = 0; j < pE32->e32_objcnt; j++) {
if ((rgO32[j].o32_flags & IMAGE_SCN_COMPRESSED) &&
(rgO32[j].o32_vsize > rgO32[j].o32_psize))
{
if (m_cCompressedRegions % NUM_COMPRESSED == 0) {
CHR(SafeRealloc((LPVOID*)&m_pCompressedRegions, (m_cCompressedRegions + NUM_COMPRESSED) * sizeof(COMPR_RGN)));
}
m_pCompressedRegions[m_cCompressedRegions].iAddress = rgO32[j].o32_dataptr;
m_pCompressedRegions[m_cCompressedRegions].cBytesCompressed = rgO32[j].o32_psize;
m_pCompressedRegions[m_cCompressedRegions].cBytesUncompressed = rgO32[j].o32_vsize;
m_cCompressedRegions++;
}
}
}
}
SortCompressedRgns(m_pCompressedRegions, m_cCompressedRegions);
RETAILMSG(ZONE_PARSE_VERBOSE, (TEXT("\nCompressed regions\n")));
for (i = 0; i < m_cCompressedRegions; ++i) {
RETAILMSG(ZONE_PARSE_VERBOSE, (TEXT("Addr: 0x%08X, Comp: 0x%08X, Uncomp: 0x%08X\n"),
m_pCompressedRegions[i].iAddress, m_pCompressedRegions[i].cBytesCompressed, m_pCompressedRegions[i].cBytesUncompressed));
}
Error:
return hr;
} /* CImageData::FindCompressedRegions()
*/
HRESULT
CImageData::GenerateDecompressedImage(CSecDiv *pSecDiv)
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
HRESULT hr = NOERROR;
UCHAR* pbBuf = m_pbImage;
UINT32 cLen = m_dwImageLen;
COMPR_CMD* pcc = NULL;
UINT32 cbBufNew = m_dwImageLen * 4;
LPBYTE pbBufNew = NULL;
LPBYTE pbBufNewOrig;
LPBYTE pbBufNewEnd;
PROMIMAGE_SECTION pSectionHeader;
DWORD dwSectionCount;
typedef DWORD (*CECOMPRESS)(LPBYTE lpbSrc, DWORD cbSrc, LPBYTE lpbDest, DWORD cbDest, WORD wStep, DWORD dwPagesize);
typedef DWORD (*CEDECOMPRESS)(LPBYTE lpbSrc, DWORD cbSrc, LPBYTE lpbDest, DWORD cbDest, DWORD dwSkip, WORD wStep, DWORD dwPagesize);
#define COMPRESS "compress.dll"
#define CECOMPRESSOR "CECompress"
#define CEDECOMPRESSOR "CEDecompress"
HMODULE hcomp = LoadLibrary(COMPRESS);
if(!hcomp){
fprintf(stderr, "Error: LoadLibrary() failed to load '%s': %d\n", COMPRESS, GetLastError());
CHR( hr = E_FAIL );
}
CEDECOMPRESS cedecompress = (CEDECOMPRESS)GetProcAddress(hcomp, CEDECOMPRESSOR);
if(!cedecompress){
fprintf(stderr, "Error: GetProcAddress() failed to find 'CEDecompress' in '%s': %d\n", CEDECOMPRESSOR, GetLastError());
CHR( hr = E_FAIL );
}
CPR(pbBufNew = (LPBYTE)LocalAlloc(LMEM_FIXED, cbBufNew));
pbBufNewOrig = pbBufNew;
pbBufNewEnd = pbBufNewOrig + cbBufNew;
CHR(FindCompressedRegions());
pSectionHeader = m_pFirstSection;
dwSectionCount = 0;
while (pSectionHeader->Address || (!pSectionHeader->Address && pSectionHeader->CheckSum))
{
UINT32 cBytesUncompressedTotal = 0;
UINT32 cComprRgnsSec = 0;
UINT32 cComprRgnsSecMax = 0;
UINT32 cBytesUncompressed;
UINT32 cBytesCompressed;
UINT32 iRgn = 0;
UINT32 iOffset = 0;
ADDRESS addr;
ASSERT(pcc == NULL);
pbBuf = DataFromSection(pSectionHeader);
CHR(m_pSectionDataList[dwSectionCount].SetUncompressedDataPtr(pbBufNew));
if(m_cCompressedRegions > 0)
{
while ((iRgn < m_cCompressedRegions - 1) && (m_pCompressedRegions[iRgn].iAddress < pSectionHeader->Address)) {
++iRgn;
}
}
while (iOffset < pSectionHeader->Size)
{
UINT32 uAddr = pSectionHeader->Address + iOffset;
if ((m_cCompressedRegions > 0) && uAddr == m_pCompressedRegions[iRgn].iAddress)
{
addr.iAddr = iRgn;
addr.iOffset = 0;
CHR(m_tt.Insert(pbBufNew - pbBufNewOrig, addr));
cBytesCompressed = m_pCompressedRegions[iRgn].cBytesCompressed;
cBytesUncompressed = cedecompress(pbBuf + iOffset, cBytesCompressed, pbBufNew, pbBufNewEnd - pbBufNew, 0, 1, 0x1000);
CBRA(cBytesUncompressed != CEDECOMPRESS_FAILED);
RETAILMSG(ZONE_DECOMPRESS, (TEXT(" %u bytes decompressed to %u\n"), cBytesCompressed, cBytesUncompressed));
pbBufNew += cBytesUncompressed;
++iRgn;
}
else
{
addr.iAddr = uAddr;
addr.iOffset = NO_COMPRESS;
CHR(m_tt.Insert(pbBufNew - pbBufNewOrig, addr));
if(m_cCompressedRegions > 0)
{
cBytesUncompressed = cBytesCompressed = min(pSectionHeader->Size, m_pCompressedRegions[iRgn].iAddress - pSectionHeader->Address) - iOffset;
} else
{
cBytesUncompressed = cBytesCompressed = pSectionHeader->Size - iOffset;
}
// Check to make sure we won't go off the end of the buffer
CBRA((pbBufNew + cBytesCompressed)<pbBufNewEnd);
memcpy(pbBufNew, pbBuf + iOffset, cBytesCompressed);
pbBufNew += cBytesCompressed;
}
if (cComprRgnsSec == cComprRgnsSecMax) {
cComprRgnsSecMax += NUM_COMPRESSED_SCN;
CHR(SafeRealloc((LPVOID*)&pcc, cComprRgnsSecMax * sizeof(COMPR_CMD)));
}
pcc[cComprRgnsSec].cBytesCompressed = cBytesCompressed;
pcc[cComprRgnsSec].cBytesUncompressed = cBytesUncompressed;
++cComprRgnsSec;
iOffset += cBytesCompressed;
cBytesUncompressedTotal += cBytesUncompressed;
if(pSecDiv) {
CHR(pSecDiv->Add(pbBufNew));
*pbBufNew++ = SEC_DIV_CHAR;
}
}
CHR(m_pSectionDataList[dwSectionCount].SetUncompressedSize(cBytesUncompressedTotal));
CHR(m_pSectionDataList[dwSectionCount].SetCompressionCommands(pcc, cComprRgnsSec));
// Handed off to the SectionData List...
pcc = NULL;
m_cbLargestUncompressedSection = max(m_cbLargestUncompressedSection, cBytesUncompressedTotal);
pSectionHeader = NextSection(pSectionHeader);
dwSectionCount++;
}
ASSERT(dwSectionCount == m_cSections);
m_cbUncompressedImage = pbBufNew - pbBufNewOrig;
RETAILMSG(ZONE_VERBOSE, (TEXT("Size of uncompressed image: %u\n"), m_cbUncompressedImage));
m_pbUncompressedImage = pbBufNewOrig;
pbBufNewOrig = NULL;
CHR(SafeRealloc((LPVOID*)&m_pbUncompressedImage, m_cbUncompressedImage));
Error:
LocalFree(pcc);
LocalFree(pbBufNewOrig);
if (FAILED(hr))
{
fprintf(stderr, "Error: GenerateDecompressedImage failed : 0x%x\n", hr);
}
return hr;
} /* CImageData::GenerateDecompressedImage()
*/
HRESULT
CImageData::FindDataPtr(DWORD dwVirtualAddr, DWORD dwLen,
CSectionData **ppSection, LPBYTE *ppbData)
/*---------------------------------------------------------------------------*\
* Find some data within the image...
* dwVirtualAddr - Virtual address that we're looking for. This is
* a real address in flash, which means that it's
* a "compressed" address. This is an address that
* you could actually go read from flash.
* If you need the address of some uncompressed data
* You have to call this function with the base
* address of the compression block and offset into
* it the appropriate amount.
* dwLen - Length of the data section. Note that the entire
* data section must be either compressed or
* uncompressed and can not cross a section boundary.
* If the data is compressed, this is the COMPRESSED
* length of the data.
* ppbData - return pointer for the address in memory.
\*---------------------------------------------------------------------------*/
{
HRESULT hr = NOERROR;
int i, j;
DWORD dwAddr;
LPBYTE pb;
ASSERT(ppSection);
ASSERT(ppbData);
for(i = 0; i < m_cSections; i++) {
CSectionData *pSection = GetSection(i);
ROMIMAGE_SECTION *pSectionHdr = pSection->GetSectionHeader();
if( dwVirtualAddr >= pSectionHdr->Address &&
dwVirtualAddr + dwLen <= pSectionHdr->Address + pSectionHdr->Size)
{
// It's in here somewhere... Now we have to see if it was compressed...
dwAddr = pSectionHdr->Address;
pb = pSection->GetUncompressedDataPtr();
if(pSection->GetCountCompressionCommands()) {
for(j = 0; j < pSection->GetCountCompressionCommands(); j++) {
COMPR_CMD *pCmd = pSection->GetCompressionCommand(j);
if(dwVirtualAddr >= dwAddr && dwVirtualAddr + dwLen <= dwAddr + pCmd->cBytesCompressed) {
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -