diff --git a/src/map/IMG/huffmantext.cpp b/src/map/IMG/huffmantext.cpp index 6ecce73f..e026b420 100644 --- a/src/map/IMG/huffmantext.cpp +++ b/src/map/IMG/huffmantext.cpp @@ -1,65 +1,33 @@ #include "subfile.h" +#include "huffmanstream.h" #include "huffmantext.h" using namespace IMG; -bool HuffmanText::fetch(const SubFile *file, SubFile::Handle &hdl, - quint32 &data, quint32 &bits, quint32 &usedBits, quint32 &usedData) const +bool HuffmanText::load(const RGNFile *rgn, SubFile::Handle &rgnHdl) { - quint32 rs, ls, old; + if (!_table.load(rgn, rgnHdl)) + return false; - bits = _table.symBits() - bits; - - if (usedBits < bits) { - old = usedBits ? usedData >> (32 - usedBits) : 0; - if (!file->readVUInt32SW(hdl, 4, usedData)) - return false; - ls = bits - usedBits; - rs = 32 - (bits - usedBits); - old = usedData >> rs | old << ls; - } else { - ls = bits; - rs = usedBits - bits; - old = usedData >> (32 - bits); - } - - usedData = usedData << ls; - data = data | old << (32 - _table.symBits()); - usedBits = rs; - - return true; + Q_ASSERT(!(_table.symbolBits() & 7)); + return !(_table.symbolBits() & 7); } bool HuffmanText::decode(const SubFile *file, SubFile::Handle &hdl, - QVector &str) const + quint32 size, QVector &str) const { - quint32 bits = 0; - quint32 data = 0; - quint32 usedBits = 0; - quint32 usedData = 0; + BitStream4F bs(*file, hdl, size); + HuffmanStream hs(bs, _table); + quint32 sym; - while (true) { - if (!fetch(file, hdl, data, bits, usedBits, usedData)) - return false; - - quint8 size; - quint32 sym = _table.symbol(data, size); - - if (_table.symBits() < size) - return false; - data = data << size; - bits = _table.symBits() - size; - - if (!(_table.symbolBits() & 7)) { - for (quint32 i = 0; i < (_table.symbolBits() >> 3); i++) { - str.append((quint8)sym); - if (((quint8)sym == '\0')) - return true; - sym = sym >> 8; - } - } else { - Q_ASSERT(false); - return false; + while (hs.readSymbol(sym)) { + for (quint32 i = 0; i < (_table.symbolBits() >> 3); i++) { + str.append((quint8)sym); + if (((quint8)sym == '\0')) + return true; + sym = sym >> 8; } } + + return false; } diff --git a/src/map/IMG/huffmantext.h b/src/map/IMG/huffmantext.h index 7d32abdf..227ef43e 100644 --- a/src/map/IMG/huffmantext.h +++ b/src/map/IMG/huffmantext.h @@ -10,15 +10,11 @@ class HuffmanText public: HuffmanText() : _table(0) {} - bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl) - {return _table.load(rgn, rgnHdl);} - bool decode(const SubFile *file, SubFile::Handle &hdl, + bool load(const RGNFile *rgn, SubFile::Handle &rgnHdl); + bool decode(const SubFile *file, SubFile::Handle &hdl, quint32 size, QVector &str) const; private: - bool fetch(const SubFile *file, SubFile::Handle &hdl, quint32 &data, - quint32 &bits, quint32 &usedBits, quint32 &usedData) const; - HuffmanTable _table; }; diff --git a/src/map/IMG/lblfile.cpp b/src/map/IMG/lblfile.cpp index 59df9318..9fc15fc7 100644 --- a/src/map/IMG/lblfile.cpp +++ b/src/map/IMG/lblfile.cpp @@ -268,10 +268,11 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize, bool convert) const { QVector str; + quint32 end = _offset + _size; if (!seek(hdl, offset)) return Label(); - if (!_huffmanText->decode(this, hdl, str)) + if (!_huffmanText->decode(this, hdl, end - offset, str)) return Label(); if (!_table) return str2label(str, capitalize, convert); @@ -281,14 +282,16 @@ Label LBLFile::labelHuffman(Handle &hdl, quint32 offset, bool capitalize, for (int i = 0; i < str.size(); i++) { quint32 val = _table[str.at(i)]; if (val) { - if (!seek(hdl, _offset + ((val & 0x7fffff) << _multiplier))) + quint32 off = _offset + ((val & 0x7fffff) << _multiplier); + if (!seek(hdl, off)) return Label(); if (str2.size() && str2.back() == '\0') str2[str2.size() - 1] = ' '; else if (str2.size()) str2.append(' '); - if (!_huffmanText->decode(this, hdl, str2)) + + if (!_huffmanText->decode(this, hdl, end - off, str2)) return Label(); } else { if (str.at(i) == 7) {