涉及两个结构体:
struct st_NpkHeader { int _magic;// [_offset + 0] int _count;// [_offset + 4] size(count * 28) int _unknonw2; int _unknonw3; int _bUseTrunkCompressType; int _offset; };
struct st_NpkTrunk { int _trunkHash; int _dataOffset; int _compressSize; int _realSize; int _unknown1; int _unknonw2; int _compressType; };
完整代码:
// UnNpk.cpp : 定义控制台应用程序的入口点。 // #include "./liblz4/lz4.h" #include "./zlib/zlib.h" #include "stdafx.h" #include #include #include struct st_NpkHeader { int _magic;// [_offset + 0] int _count;// [_offset + 4] size(count * 28) int _unknonw2; int _unknonw3; int _bUseTrunkCompressType; int _offset; }; struct st_NpkTrunk { int _trunkHash; int _dataOffset; int _compressSize; int _realSize; int _unknown1; int _unknonw2; int _compressType; }; std::string GetNpkFileName(char *pData, unsigned int maxLen) { std::string name; for (int i = 0; i < maxLen; ++i) { if ((pData[i] >= 'a' && pData[i] <= 'z') || (pData[i] >= 'A' && pData[i] <= 'Z') ) { name += pData[i]; } } return name; } int _tmain(int argc, _TCHAR* argv[]) { if (argc < 2) { printf("%s npkFile\n", argv[0]); return 0; } FILE *fp = fopen(argv[1], "rb"); if (!fp) { return 0; } unsigned int nFileLen = 0; fseek(fp,0,SEEK_END); //定位到文件末 nFileLen = ftell(fp); //文件长度 fseek(fp,0,SEEK_SET); st_NpkHeader npkHeader; fread(&npkHeader, sizeof(npkHeader), 1, fp); if (npkHeader._magic != 0x4b50584e) { printf("not npk file\n"); return 0; } fseek(fp,0,SEEK_SET); st_NpkTrunk* pNpkTrunkList = new st_NpkTrunk[npkHeader._count]; std::string strDir = "./Dump"; if (_access(strDir.c_str(), 0) != 0) { _mkdir(strDir.c_str()); } fseek(fp, npkHeader._offset,SEEK_SET); int nRSize = fread(pNpkTrunkList, sizeof(st_NpkTrunk), npkHeader._count, fp); for (int i = 0; i < nRSize; ++i) { fseek(fp, pNpkTrunkList[i]._dataOffset, SEEK_SET); char *pSrc = new char[pNpkTrunkList[i]._compressSize]; fread(pSrc, pNpkTrunkList[i]._compressSize, 1, fp); char *pDst = new char[pNpkTrunkList[i]._realSize]; if (pNpkTrunkList[i]._compressType == 2) { LZ4_decompress_safe(pSrc, pDst, pNpkTrunkList[i]._compressSize, pNpkTrunkList[i]._realSize); } else if (pNpkTrunkList[i]._compressType == 1) { int realSize = pNpkTrunkList[i]._realSize; int nRet = uncompress((Bytef *)pDst, (uLongf*)&realSize, (Bytef *)pSrc, pNpkTrunkList[i]._compressSize); } else { memcpy(pDst, pSrc, pNpkTrunkList[i]._realSize); } char fileName[126]; std::string format = GetNpkFileName(pDst, 5); sprintf_s<126>(fileName, "%s/%x.%s", strDir.c_str(), pNpkTrunkList[i]._trunkHash, format.c_str()); FILE *fp2 = fopen(fileName, "wb"); fwrite(pDst, pNpkTrunkList[i]._realSize, 1, fp2); fclose(fp2); delete[] pSrc; delete[] pDst; } return 0; }