// TODO: Remove this ASAP. Rewrite the decompression routines to allow easy decompression of multiple patch file versions. To future me: Consider using a C++ class for decompression. bool ZPatcher::FileDecompress_Version_1(CLzma2Dec* decoder, FILE* sourceFile, FILE* destFile) { ELzmaStatus status; const SizeT buffer_size = 1 << 16; Byte sourceBuffer[buffer_size]; Byte destBuffer[buffer_size]; SizeT sourceLen = 0; SizeT destLen = buffer_size; int64_t sourceFilePos = ftell64(sourceFile); // We must reinitialize every time we want a decode a new file. Lzma2Dec_Init(decoder); while (true) { sourceLen = fread(sourceBuffer, 1, buffer_size, sourceFile); SRes res = Lzma2Dec_DecodeToBuf(decoder, destBuffer, &destLen, sourceBuffer, &sourceLen, LZMA_FINISH_ANY, &status); assert(res == SZ_OK); fwrite(destBuffer, 1, destLen, destFile); sourceFilePos += sourceLen; res = fseek64(sourceFile, sourceFilePos, SEEK_SET); assert(res == 0); if (res == SZ_OK && status == LZMA_STATUS_FINISHED_WITH_MARK) break; } return true; }
void UnCompressWithLZMA2(std::vector<unsigned char> &outBuf, const std::vector<unsigned char> &inBuf) { CLzma2Dec dec; Lzma2Dec_Construct(&dec); UInt64 unpackSize = 0; SRes res = Lzma2Dec_Allocate(&dec, inBuf[0], &g_Alloc); assert(res == SZ_OK); Lzma2Dec_Init(&dec); for (int i = 0; i < 8; i++) unpackSize += (UInt64)inBuf[1+i] << (i * 8); outBuf.resize(unpackSize); unsigned outPos = 0, inPos = 9; ELzmaStatus status; const unsigned BUF_SIZE = 10240; while (outPos < outBuf.size()) { SizeT destLen = min(BUF_SIZE, outBuf.size() - outPos); SizeT srcLen = min(BUF_SIZE, inBuf.size() - inPos); res = Lzma2Dec_DecodeToBuf(&dec, &outBuf[outPos], &destLen, &inBuf[inPos], &srcLen, (outPos + destLen == outBuf.size()) ? LZMA_FINISH_END : LZMA_FINISH_ANY, &status); unsigned int outbufsize = outBuf.size(); assert(res == SZ_OK); inPos += srcLen; outPos += destLen; if (status == LZMA_STATUS_FINISHED_WITH_MARK) { break; } } Lzma2Dec_Free(&dec, &g_Alloc); outBuf.resize(outPos); FILE *fout = fopen("data22.dc", "wb+"); fwrite(&outBuf[0], 1, outBuf.size(), fout); fclose(fout); }
STDMETHODIMP CDecoder::Read(void *data, UInt32 size, UInt32 *processedSize) { if (processedSize) *processedSize = 0; do { if (_inPos == _inSize) { _inPos = _inSize = 0; RINOK(_inStream->Read(_inBuf, kInBufSize, &_inSize)); } { SizeT inProcessed = _inSize - _inPos; if (_outSizeDefined) { const UInt64 rem = _outSize - _outSizeProcessed; if (rem < size) size = (UInt32)rem; } SizeT outProcessed = size; ELzmaStatus status; SRes res = Lzma2Dec_DecodeToBuf(&_state, (Byte *)data, &outProcessed, _inBuf + _inPos, &inProcessed, LZMA_FINISH_ANY, &status); _inPos += (UInt32)inProcessed; _inSizeProcessed += inProcessed; _outSizeProcessed += outProcessed; size -= (UInt32)outProcessed; data = (Byte *)data + outProcessed; if (processedSize) *processedSize += (UInt32)outProcessed; RINOK(SResToHRESULT(res)); if (inProcessed == 0 && outProcessed == 0) return S_OK; } } while (size != 0); return S_OK; }