diff options
author | Paul Gilbert | 2013-05-22 12:07:17 +1000 |
---|---|---|
committer | Paul Gilbert | 2013-05-22 12:07:17 +1000 |
commit | a52dffb3156220ed8ae7497b0273da0386bb335e (patch) | |
tree | 8b898dad35b21332a8e47d40f9c456e9de858bb9 | |
parent | bff4076093554700e94c4db74a47adabb5f7c74e (diff) | |
download | scummvm-rg350-a52dffb3156220ed8ae7497b0273da0386bb335e.tar.gz scummvm-rg350-a52dffb3156220ed8ae7497b0273da0386bb335e.tar.bz2 scummvm-rg350-a52dffb3156220ed8ae7497b0273da0386bb335e.zip |
VOYEUR: Implemented code for default decompression
-rw-r--r-- | engines/voyeur/files.cpp | 163 | ||||
-rw-r--r-- | engines/voyeur/files.h | 29 |
2 files changed, 179 insertions, 13 deletions
diff --git a/engines/voyeur/files.cpp b/engines/voyeur/files.cpp index d6df3aa1ea..6c4e824f75 100644 --- a/engines/voyeur/files.cpp +++ b/engines/voyeur/files.cpp @@ -51,6 +51,22 @@ byte *BoltFile::_curMemInfoPtr = NULL; int BoltFile::_fromGroupFlag = 0; byte BoltFile::_xorMask = 0; bool BoltFile::_encrypt = false; +int BoltFile::_curFilePosition = 0; +int BoltFile::_bufferEnd = 0; +int BoltFile::_bufferBegin = 0; +int BoltFile::_bytesLeft = 0; +int BoltFile::_bufSize = 0; +byte *BoltFile::_bufP = NULL; +byte *BoltFile::_bufStart = NULL; +byte *BoltFile::_bufPos = NULL; +byte BoltFile::_decompressBuf[512]; +int BoltFile::_historyIndex; +byte BoltFile::_historyBuffer[0x200]; +int BoltFile::_runLength; +int BoltFile::_decompState; +int BoltFile::_runType; +int BoltFile::_runValue; +int BoltFile::_runOffset; BoltFile::BoltFile() { if (!_curFd.open("bvoy.blt")) @@ -79,11 +95,8 @@ bool BoltFile::getBoltGroup(uint32 id) { _curGroupPtr = &_groups[(id >> 8) & 0xff]; int count = _curGroupPtr->_count ? _curGroupPtr->_count : 256; - if (_curGroupPtr->_groupPtr) { - // Group already loaded - _curMemInfoPtr = _curGroupPtr->_groupPtr; - } else { - // Load the group + if (!_curGroupPtr->_loaded) { + // Load the group index _curGroupPtr->load(); } @@ -96,7 +109,8 @@ bool BoltFile::getBoltGroup(uint32 id) { byte *member = getBoltMember(id); assert(member); } - } else if (!_curGroupPtr->_loaded) { + } else if (!_curGroupPtr->_processed) { + _curGroupPtr->_processed = true; _curGroupPtr->load(); } @@ -133,23 +147,154 @@ byte *BoltFile::getBoltMember(uint32 id) { _xorMask = _curMemberPtr->_xorMask; _encrypt = (_curMemberPtr->_mode & 0x10) != 0; - if (_curGroupPtr->_loaded) { + if (_curGroupPtr->_processed) { + // TODO: Figure out weird access type. Uncompressed read perhaps? + //int fileDiff = _curGroupPtr->_fileOffset - _curMemberPtr->_fileOffset; + + } else { + _bufStart = _decompressBuf; + _bufSize = DECOMPRESS_SIZE; + + if (_curMemberPtr->_fileOffset < _bufferBegin || _curMemberPtr->_fileOffset >= _bufferEnd) { + _bytesLeft = 0; + _bufPos = _bufStart; + _bufferBegin = -1; + _bufferEnd = _curMemberPtr->_fileOffset; + } else { + _bufPos = _curMemberPtr->_fileOffset + _bufferBegin + _bufStart; + _bufSize = ((_bufPos - _bufStart) << 16) >> 16; // TODO: Validate this + _bytesLeft = _bufSize; + } + _decompState = 0; + _historyIndex = 0; + initType(); } //TODO return NULL; } +void BoltFile::initType() { + _curMemberPtr->_data = decompress(0, _curMemberPtr->_size, _curMemberPtr->_mode); +} + +#define NEXT_BYTE if (--_bytesLeft <= 0) nextBlock() + +byte *BoltFile::decompress(byte *buf, int size, int mode) { + if (buf) + buf = new byte[size]; + byte *bufP = buf; + + if (mode & 8) { + _decompState = 1; + _runType = 0; + _runLength = size; + } + + while (size > 0) { + if (!_decompState) { + NEXT_BYTE; + byte nextByte = *_bufPos++; + + switch (nextByte & 0xC0) { + case 0: + _runType = 0; + _runLength = 30 - (nextByte & 0x1f) + 1; + break; + case 0x40: + _runType = 1; + _runLength = 35 - (nextByte & 0x1f); + NEXT_BYTE; + _runOffset = *_bufPos++ + ((nextByte & 0x20) << 3); + break; + case 0x80: + _runType = 1; + _runLength = (nextByte & 0x20) ? ((32 - (nextByte & 0x1f)) << 2) + 2 : + (32 - (nextByte & 0x1f)) << 2; + NEXT_BYTE; + _runOffset = *_bufPos++ << 1; + break; + default: + _runType = 2; + + if (nextByte & 0x20) { + _runLength = 0; + } else { + NEXT_BYTE; + _runLength = ((32 - (nextByte & 0x1f)) + (*_bufPos++ << 5)) << 2; + NEXT_BYTE; + _bufPos++; + NEXT_BYTE; + _runValue = *_bufPos++; + } + break; + } + + _runOffset = _historyIndex - _runOffset; + } + + int runOffset = _runOffset & 0x1ff; + int len; + if (_runLength <= size) { + len = _runLength; + _decompState = 0; + } else { + _decompState = 1; + _runLength = len = size; + if (_runType == 1) + _runOffset += len; + } + + // Handle the run lengths + switch (_runType) { + case 0: + while (len-- > 0) { + NEXT_BYTE; + _historyBuffer[_historyIndex] = *_bufPos++; + _historyIndex = (_historyIndex + 1) & 0x1ff; + } + break; + case 1: + while (len-- > 0) { + _historyBuffer[_historyIndex] = _historyBuffer[runOffset]; + *bufP++ = _historyBuffer[runOffset]; + _historyIndex = (_historyIndex + 1) & 0x1ff; + } + break; + default: + while (len-- > 0) { + _historyBuffer[_historyIndex] = _runValue; + _historyIndex = (_historyIndex + 1) & 0x1ff; + } + break; + } + } + + return buf; +} + +void BoltFile::nextBlock() { + if (_curFilePosition != _bufferEnd) + _curFd.seek(_bufferEnd); + + _bufferBegin = _curFilePosition; + int bytesRead = _curFd.read(_bufStart, _bufSize); + + _bufferEnd = _curFilePosition = _bufferBegin + bytesRead; + _bytesLeft -= bytesRead; + _bufPos = _bufStart; +} + /*------------------------------------------------------------------------*/ BoltGroup::BoltGroup(Common::SeekableReadStream *f): _file(f) { byte buffer[BOLT_GROUP_SIZE]; - _groupPtr = NULL; + _loaded = false; _file->read(&buffer[0], BOLT_GROUP_SIZE); - _loaded = false; + _processed = buffer[0] != 0; _callInitGro = buffer[1] != 0; _count = buffer[3] ? buffer[3] : 256; // TODO: Added this in. Check it's okay _fileOffset = READ_LE_UINT32(&buffer[8]); diff --git a/engines/voyeur/files.h b/engines/voyeur/files.h index 381ba20255..3b38dcceb3 100644 --- a/engines/voyeur/files.h +++ b/engines/voyeur/files.h @@ -32,6 +32,7 @@ namespace Voyeur { class VoyeurEngine; class BoltGroup; class BoltEntry; +#define DECOMPRESS_SIZE 512 class BoltFile { private: @@ -42,16 +43,36 @@ private: static int _fromGroupFlag; static byte _xorMask; static bool _encrypt; + // TODO: Move decompression statics and methods into BoltEntry + static int _curFilePosition; + static int _bufferEnd; + static int _bufferBegin; + static int _bytesLeft; + static int _bufSize; + static byte *_bufP; + static byte *_bufStart; + static byte *_bufPos; + static byte _decompressBuf[DECOMPRESS_SIZE]; + static int _historyIndex; + static byte _historyBuffer[0x200]; + static int _runLength; + static int _decompState; + static int _runType; + static int _runValue; + static int _runOffset; private: Common::File _curFd; - int _curFilePosition; Common::Array<BoltGroup> _groups; + + // Decompression + byte *decompress(byte *buf, int size, int mode); + void nextBlock(); private: void resolveAll() {} byte *getBoltMember(uint32 id); // Methods copied into bolt virtual table - void initType() {} + void initType(); void termType() {} void initMem(int id) {} void termMem() {} @@ -69,11 +90,11 @@ class BoltGroup { private: Common::SeekableReadStream *_file; public: - bool _loaded; + byte _loaded; + bool _processed; bool _callInitGro; int _count; int _fileOffset; - byte *_groupPtr; Common::Array<BoltEntry> _entries; public: BoltGroup(Common::SeekableReadStream *f); |