📄 diffbin.cpp
字号:
{
if (pcCurMatched[cCurMatched] + k > pcMatched[j - k])
{
pcMatched[j - k] = pcCurMatched[cCurMatched] + k;
piPlace[j - k] = iOffset - k;
}
++k;
}
}
if (pcCurMatched[cCurMatched] > pcMatched[j])
{
pcMatched[j] = pcCurMatched[cCurMatched];
piPlace[j] = piCurMatched[cCurMatched];
}
++cCurMatched;
}
}
// switch prev and cur lines
pcTemp = pcCurMatched;
pcCurMatched = pcPrevMatched;
pcPrevMatched = pcTemp;
piTemp = piPrevMatched;
piPrevMatched = piCurMatched;
piCurMatched = piTemp;
cPrevMatched = cCurMatched;
iPrevMatched = 0;
cCurMatched = 0;
if ((pbSection - pbNewImage + cSecLen - j) % 10000 < HASH_BYTES / 2) {
RETAILMSG(ZONE_PROGRESS, (TEXT("\b\b\b\b\b\b\b\b%8u"), (pbSection - pbNewImage + cSecLen - j) / 10000 * 10000));
}
}
CHR(ComputeRuns(&SectionRunList, pcMatched, piPlace, pbSection, cSecLen));
}
CHR(SectionRunList.GetTotalLength(&dwSectionTokenLen));
RETAILMSG(ZONE_VERBOSE, (TEXT("ComputeSubstrings: Addr=0x%08lx Len=0x%08lx RunLen=0x%08lx\n"),
pSection->GetSectionHeader()->Address, pSection->GetSectionHeader()->Size, dwSectionTokenLen));
// Now that we've got a compressed version of this section, let's see
// if it actually bought us anything at all.
if ((cSecLen < HASH_BYTES) || (dwSectionTokenLen >= pSection->GetSectionHeader()->Size)) {
// Either this section was too small to compress, or the compressed
// size of the image was worse than the original. Let's leave the
// original data section here.
// Note that since we are using GetDataPtr, we are getting the original
// version of the section that does not have fixups applied, so we do
// not need to write the fixup sections
CHR(pSection->SetUncompressedSize(ALL_DATA));
pRunList->Insert(RUNTYPE_RAWDATA, pSection->GetSectionHeader()->Size, (DWORD)pSection->GetDataPtr());
} else {
// The compression saved us something. Use it!
// Copy the runs that make up the compressedversion of this section
pRunList->CopyRuns(&SectionRunList);
// Insert the fixup commands
CHR(pRunList->Insert(RUNTYPE_FIXUPCOMMANDS, 0, (DWORD)pSection));
// Insert the compression commands
CHR(pRunList->Insert(RUNTYPE_COMPRESSIONCOMMANDS, 0, (DWORD)pSection));
}
}
RETAILMSG(ZONE_PROGRESS, (TEXT("\b\b\b\b\b\b\b\b%8u\n\n"), cbNewImage));
// Insert zero'd section header to mark the end of the file
CHR(pRunList->Insert(RUNTYPE_ZEROBLOCK, sizeof(ROMIMAGE_SECTION), 0));
Error:
LocalFree(pcCurMatched);
LocalFree(pcPrevMatched);
LocalFree(piCurMatched);
LocalFree(piPrevMatched);
LocalFree(pcMatched);
LocalFree(piPlace);
return hr;
} /* ComputeSubstrings()
*/
////////////////////////////////////////////////////////////
// BuildFile
// Output the compressed data to the file "name"
////////////////////////////////////////////////////////////
HRESULT
BuildFile(CRunList *pRunList, CImageData *pImgOld, CImageData *pImgNew,
LPCSTR szOutputFilename, DWORD *pdwOutputLength)
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
HRESULT hr = NOERROR;
HANDLE hfOutput = INVALID_HANDLE_VALUE;
DWORD dwWritten = 0;
DWORD cComprRgns;
DWORD dwPhysicalStartAddr;
UINT32 i, j;
ROMIMAGE_HEADER rh;
DWORD cbRelocCmds = 0;
LPBYTE pbRelocCmds = NULL;
DWORD cbSectionHeaders = 0;
DWORD cbCompressedRgnTable = 0;
DWORD cbCompressionCommands = 0;
DWORD cbHdr = 0;
DWORD cbVerification = 0;
DWORD cbMisc = 0;
DWORD cbData = 0;
DWORD cbCopy = 0;
DWORD cbFixups = 0;
DWORD dwTemp;
dwPhysicalStartAddr = pImgOld->GetHeader()->PhysicalStartAddress;
//
// Open Output file
//
CBR((hfOutput = CreateFile(szOutputFilename, GENERIC_READ | GENERIC_WRITE,
0, NULL, CREATE_ALWAYS, 0, NULL)) != INVALID_HANDLE_VALUE);
//
// Write DIFF Header
//
memcpy(&rh, pImgNew->GetHeader(), sizeof(ROMIMAGE_HEADER));
rh.Signature[0] = COMPRESSED_INDICATOR;
CHR(IWriteFile(hfOutput, (LPBYTE)&rh, sizeof(ROMIMAGE_HEADER), &dwWritten));
CHR(WriteInt(hfOutput, pImgNew->GetUncompressedImageLength(), 3, &dwWritten));
cbHdr = dwWritten;
//
// Write Old BIN verification data
//
for(i = 0; i < pImgOld->GetSectionCount(); i++) {
CSectionData *pSection = pImgOld->GetSection(i);
CHR(IWriteFile(hfOutput, (LPBYTE)pSection->GetSectionHeader(), sizeof(ROMIMAGE_SECTION), &dwWritten));
}
{
// Write a section full of 0's to mark the end.
ROMIMAGE_SECTION section;
memset(§ion, 0, sizeof(section));
CHR(IWriteFile(hfOutput, (LPBYTE)§ion, sizeof(section), &dwWritten));
}
cbVerification = dwWritten - cbHdr;
//
// Write Compressed Region Table
//
cComprRgns = pImgOld->GetCompressedRegionCount();
CHR(WriteInt(hfOutput, cComprRgns, 3, &dwWritten));
for (i = 0; i < cComprRgns; ++i) {
COMPR_RGN *pcr = pImgOld->GetCompressedRegion(i);
CBRA(pcr);
// pcr.iAddress holds the complete 32 bit address
DWORD dwAddr = pcr->iAddress;
dwAddr -= dwPhysicalStartAddr;
// Make sure that the address we're trying to write is within 16MB of the start...
// ASSERT((dwAddr & 0x00FFFFFF) == dwAddr);
CHR(WriteInt(hfOutput, dwAddr, 3, &dwWritten));
CHR(WriteInt(hfOutput, pcr->cBytesCompressed, 3, &dwWritten));
CHR(WriteInt(hfOutput, pcr->cBytesUncompressed, 3, &dwWritten));
}
cbCompressedRgnTable = dwWritten - cbVerification - cbHdr;
//
// Write Token stream
//
for(i = 0; i < pRunList->GetRunCount(); i++) {
Run *pRun = pRunList->GetRun(i);
switch (pRun->eType)
{
case RUNTYPE_SECTIONHEADER:
{
dwTemp = dwWritten;
ROMIMAGE_SECTION *pSection = ((CSectionData*)pRun->dwOffset)->GetSectionHeader();
CHR(WriteAddrVarInt(hfOutput, pSection->Address, &dwWritten));
CHR(WriteVarInt(hfOutput, pSection->Size, &dwWritten));
CHR(WriteVarInt(hfOutput, pSection->CheckSum, &dwWritten));
CHR(WriteVarInt(hfOutput, ((CSectionData*)pRun->dwOffset)->GetUncompressedSize(), &dwWritten));
cbSectionHeaders += dwWritten - dwTemp;
}
break;
case RUNTYPE_DATATOKEN:
dwTemp = dwWritten;
CHR(WriteDataToken(hfOutput, pRun->dwRunLength, &dwWritten));
cbData += dwWritten - dwTemp;
// Intentional Fallthrough
case RUNTYPE_RAWDATA:
dwTemp = dwWritten;
CHR(IWriteFile(hfOutput, (LPBYTE)pRun->dwOffset, pRun->dwRunLength, &dwWritten));
cbData += dwWritten - dwTemp;
break;
case RUNTYPE_COPYTOKEN:
dwTemp = dwWritten;
{
ADDRESS addr = pImgOld->GetTranslationTable()->Lookup(pRun->dwOffset);
if(addr.iOffset == NO_COMPRESS) {
addr.iAddr -= dwPhysicalStartAddr;
// Make sure that the address we're trying to write is within 16MB of the start...
ASSERT((addr.iAddr & 0x00FFFFFF) == addr.iAddr);
}
CHR(WriteCopyToken(hfOutput, pRun->dwRunLength, addr, cComprRgns, &dwWritten));
}
cbCopy += dwWritten - dwTemp;
break;
case RUNTYPE_FIXUPCOMMANDS:
{
CSectionData *pSection = (CSectionData*)pRun->dwOffset;
dwTemp = dwWritten;
CHR(pSection->GetRelocCmdBuffer(&pbRelocCmds, &cbRelocCmds));
CHR(WriteVarInt(hfOutput, cbRelocCmds, &dwWritten));
CHR(IWriteFile(hfOutput, pbRelocCmds, cbRelocCmds, &dwWritten));
cbFixups += dwWritten - dwTemp;
}
break;
case RUNTYPE_COMPRESSIONCOMMANDS:
{
CSectionData *pSection = (CSectionData*)pRun->dwOffset;
dwTemp = dwWritten;
CHR(WriteVarInt(hfOutput, pSection->GetCountCompressionCommands(), &dwWritten));
for(j = 0; j < pSection->GetCountCompressionCommands(); j++) {
COMPR_CMD *pCmd = pSection->GetCompressionCommand(j);
CBRA(pCmd);
CHR(WriteVarInt(hfOutput, pCmd->cBytesCompressed, &dwWritten));
CHR(WriteVarInt(hfOutput, pCmd->cBytesUncompressed, &dwWritten));
}
cbCompressionCommands += dwWritten - dwTemp;
}
break;
case RUNTYPE_ZEROBLOCK:
dwTemp = dwWritten;
for(j = 0; j < pRun->dwRunLength; j++) {
DWORD dwZero = 0;
CHR(IWriteFile(hfOutput, (LPBYTE)&dwZero, 1, &dwWritten));
}
cbMisc += dwWritten - dwTemp;;
break;
}
}
RETAILMSG(ZONE_VERBOSE, (TEXT("\nImage size breakdown:\n")));
RETAILMSG(ZONE_VERBOSE, (TEXT("Header %8d\n"), cbHdr));
RETAILMSG(ZONE_VERBOSE, (TEXT("Verification Data %8d\n"), cbVerification));
RETAILMSG(ZONE_VERBOSE, (TEXT("Compressed Region Table %8d\n"), cbCompressedRgnTable));
RETAILMSG(ZONE_VERBOSE, (TEXT("Section Headers %8d\n"), cbSectionHeaders));
RETAILMSG(ZONE_VERBOSE, (TEXT("Compression Commands %8d\n"), cbCompressionCommands));
RETAILMSG(ZONE_VERBOSE, (TEXT("Fixup Commands %8d\n"), cbFixups));
RETAILMSG(ZONE_VERBOSE, (TEXT("Miscellaneous %8d\n"), cbMisc));
RETAILMSG(ZONE_VERBOSE, (TEXT("Data Commands %8d\n"), cbData));
RETAILMSG(ZONE_VERBOSE, (TEXT("Copy Commands %8d\n"), cbCopy));
RETAILMSG(ZONE_VERBOSE, (TEXT("\n")));
if(pdwOutputLength) {
*pdwOutputLength = GetFileSize(hfOutput, NULL);
}
RETAILMSG(ZONE_VERBOSE, (TEXT("Total Size %8d\n"), dwWritten));
Error:
if(hfOutput != INVALID_HANDLE_VALUE) {
CloseHandle(hfOutput);
hfOutput = NULL;
}
return hr;
} /* BuildFile()
*/
HRESULT
BuildUncompressedFile(LPCSTR szInFileName, LPCSTR szOutFileName)
/*---------------------------------------------------------------------------*\
* This is the fallback. If we don't like the results of the compression,
* i.e. the savings were small, then we can create an uncompressed file.
* This file is identical to the NK image.
\*---------------------------------------------------------------------------*/
{
CopyFile(szInFileName, szOutFileName, FALSE);
return NOERROR;
} /* BuildUncompressedFile()
*/
void
DiffBin(LPSTR szFile1, LPSTR szFile2, LPSTR szOutputFile)
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
HRESULT hr = NOERROR;
DWORD dwOutputLength = 0;
CRunList RunList;
CSecDiv SecDiv;
CMappedFile mfOld(szFile1);
CMappedFile mfNew(szFile2);
CImageData imgOld;
CImageData imgNew;
hr = mfOld.Open(GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ);
if(FAILED(hr)) {
RETAILMSG(1, (TEXT("\nError opening file '%s'\n\n"), szFile1));
goto Error;
}
hr = mfNew.Open(GENERIC_READ, OPEN_EXISTING, FILE_SHARE_READ);
if(FAILED(hr)) {
RETAILMSG(1, (TEXT("\nError opening file '%s'\n\n"), szFile2));
goto Error;
}
CHR(imgOld.Initialize((LPBYTE)mfOld.GetDataPtr(), mfOld.GetDataSize()));
CHR(imgNew.Initialize((LPBYTE)mfNew.GetDataPtr(), mfNew.GetDataSize()));
CHR(imgOld.GenerateDecompressedImage(&SecDiv));
CHR(imgNew.GenerateDecompressedImage(NULL));
CHR(ApplyReverseFixups(&imgOld, &imgNew));
CHR(RunList.Initialize(&imgOld));
CHR(ComputeSubstrings(&imgOld, &imgNew, &SecDiv, &RunList));
CHR(BuildFile(&RunList, &imgOld, &imgNew, szOutputFile, &dwOutputLength));
Error:
return;
} /* DiffBin()
*/
void
usage()
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
printf("Usage:\n");
printf(" diffbin <infile1> <infile2> <outfile> /z:<zonemask>\n");
printf(" infile1: Original image file\n");
printf(" infile2: New image file\n");
printf(" outfile: Compressed version of new image file\n");
printf(" zonemask: Hex value of zones to enable:\n");
printf(" ZONE_VERBOSE 00000001\n");
printf(" ZONE_PARSE_VERBOSE 00000002\n");
printf(" ZONE_FIXUP 00000004\n");
printf(" ZONE_FIXUP_VERBOSE 00000008\n");
printf(" ZONE_PROGRESS 00000010\n");
printf(" ZONE_DECOMPRESS 00000020\n");
exit(-1);
} /* usage()
*/
////////////////////////////////////////////////////////////
// main
// The entry point to the program
////////////////////////////////////////////////////////////
int
main(int argc, char* argv[])
/*---------------------------------------------------------------------------*\
*
\*---------------------------------------------------------------------------*/
{
if(getenv("d_break"))
DebugBreak();
if (argc < 4) {
usage();
}
for(int i=4; i < argc; i++) {
if(argv[i][0] != '-' && argv[i][0] != '/') {
usage();
}
switch(argv[i][1]) {
case 'z':
case 'Z':
if(argv[i][2] != ':') {
usage();
}
g_dwZoneMask = strtoul(&argv[i][3], NULL, 16);
break;
default:
usage();
break;
}
}
DiffBin(argv[1], argv[2], argv[3]);
return 0;
} /* main()
*/
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -