uint32 BigHuffmanTree::getCode(Common::BitStream &bs) { byte peek = bs.peekBits(MIN<uint32>(bs.size() - bs.pos(), 8)); uint32 *p = &_tree[_prefixtree[peek]]; bs.skip(_prefixlength[peek]); while (*p & SMK_NODE) { if (bs.getBit()) p += (*p) & ~SMK_NODE; p++; } uint32 v = *p; if (v != _tree[_last[0]]) { _tree[_last[2]] = _tree[_last[1]]; _tree[_last[1]] = _tree[_last[0]]; _tree[_last[0]] = v; } return v; }
void CodebookLibrary::rebuild(Common::BitStream &bis, size_t size, Common::BitStreamWriter &bos) { const uint32 id = 0x564342; const uint16 dimensions = bis.getBits(4); const uint32 entries = bis.getBits(14); bos.putBits(id, 24); bos.putBits(dimensions, 16); bos.putBits(entries, 24); const bool ordered = bis.getBit(); bos.putBit(ordered); if (ordered) { const uint8 initialLength = bis.getBits(5); bos.putBits(initialLength, 5); uint32 currentEntry = 0; while (currentEntry < entries) { const size_t bitCount = Common::intLog2(entries - currentEntry) + 1; const uint32 number = bis.getBits(bitCount); bos.putBits(number, bitCount); currentEntry += number; } if (currentEntry > entries) throw Common::Exception("CodebookLibrary::rebuild(): Current entry out of range"); } else { const uint8 codewordLengthLength = bis.getBits(3); const bool sparse = bis.getBit(); if ((codewordLengthLength == 0) || (codewordLengthLength > 5)) throw Common::Exception("CodebookLibrary::rebuild(): Nonsense codeword length"); bos.putBit(sparse); for (size_t i = 0; i < entries; i++) { bool present = true; if (sparse) { present = bis.getBit(); bos.putBit(present); } if (present) bos.putBits(bis.getBits(codewordLengthLength), 5); } } const uint8 lookupType = bis.getBits(1); bos.putBits(lookupType, 4); if (lookupType == 0) { } else if (lookupType == 1) { const uint32 min = bis.getBits(32); const uint32 max = bis.getBits(32); const uint8 valueLength = bis.getBits(4) + 1; const bool sequenceFlag = bis.getBit(); bos.putBits(min, 32); bos.putBits(max, 32); bos.putBits(valueLength - 1, 4); bos.putBit(sequenceFlag); const size_t quantVals = bookMapType1QuantVals(entries, dimensions); for (size_t i = 0; i < quantVals; i++) bos.putBits(bis.getBits(valueLength), valueLength); } if ((size != 0) && (((bis.pos() / 8) + 1) != size )) throw Common::Exception("CodebookLibrary::rebuild(): Size mismatch: %s != %s", Common::composeString((bis.pos() / 8) + 1).c_str(), Common::composeString(size).c_str()); }