int DecompressorLZW::unpackLZW(Common::ReadStream *src, byte *dest, uint32 nPacked, uint32 nUnpacked) { init(src, dest, nPacked, nUnpacked); uint16 token; // The last received value uint16 tokenlist[4096]; // pointers to dest[] uint16 tokenlengthlist[4096]; // char length of each token uint16 tokenlastlength = 0; while (!isFinished()) { token = getBitsLSB(_numbits); if (token == 0x101) return 0; // terminator if (token == 0x100) { // reset command _numbits = 9; _endtoken = 0x1FF; _curtoken = 0x0102; } else { if (token > 0xff) { if (token >= _curtoken) { warning("unpackLZW: Bad token %x", token); return SCI_ERROR_DECOMPRESSION_ERROR; } tokenlastlength = tokenlengthlist[token] + 1; if (_dwWrote + tokenlastlength > _szUnpacked) { // For me this seems a normal situation, It's necessary to handle it warning("unpackLZW: Trying to write beyond the end of array(len=%d, destctr=%d, tok_len=%d)", _szUnpacked, _dwWrote, tokenlastlength); for (int i = 0; _dwWrote < _szUnpacked; i++) putByte(dest[tokenlist[token] + i]); } else for (int i = 0; i < tokenlastlength; i++) putByte(dest[tokenlist[token] + i]); } else { tokenlastlength = 1; if (_dwWrote >= _szUnpacked) warning("unpackLZW: Try to write single byte beyond end of array"); else putByte(token); } if (_curtoken > _endtoken && _numbits < 12) { _numbits++; _endtoken = (_endtoken << 1) + 1; } if (_curtoken <= _endtoken) { tokenlist[_curtoken] = _dwWrote - tokenlastlength; tokenlengthlist[_curtoken] = tokenlastlength; _curtoken++; } } } return _dwWrote == _szUnpacked ? 0 : SCI_ERROR_DECOMPRESSION_ERROR; }
byte Decompressor::getByteLSB() { return getBitsLSB(8); }