diff options
author | Paul Gilbert | 2014-08-03 16:59:22 -0400 |
---|---|---|
committer | Paul Gilbert | 2014-08-03 16:59:22 -0400 |
commit | d41c5cd7407a99fde350f2c9fbe9b4d6e73d1ba6 (patch) | |
tree | 71227d5f15db2afa89a36b921a00d1d5f82099aa /engines | |
parent | 7a63e12edb98f47d9a262601d9d26d9444975314 (diff) | |
download | scummvm-rg350-d41c5cd7407a99fde350f2c9fbe9b4d6e73d1ba6.tar.gz scummvm-rg350-d41c5cd7407a99fde350f2c9fbe9b4d6e73d1ba6.tar.bz2 scummvm-rg350-d41c5cd7407a99fde350f2c9fbe9b4d6e73d1ba6.zip |
ACCESS: Added decompression code
Diffstat (limited to 'engines')
-rw-r--r-- | engines/access/decompress.cpp | 127 | ||||
-rw-r--r-- | engines/access/decompress.h | 48 | ||||
-rw-r--r-- | engines/access/files.cpp | 33 | ||||
-rw-r--r-- | engines/access/files.h | 7 | ||||
-rw-r--r-- | engines/access/module.mk | 1 |
5 files changed, 196 insertions, 20 deletions
diff --git a/engines/access/decompress.cpp b/engines/access/decompress.cpp new file mode 100644 index 0000000000..45ae07d712 --- /dev/null +++ b/engines/access/decompress.cpp @@ -0,0 +1,127 @@ +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#include "common/debug.h" +#include "common/endian.h" +#include "common/util.h" + +#include "access/decompress.h" + +namespace Access { + +void LzwDecompressor::decompress(byte *source, byte *dest) { + + _source = source; + + byte litByte; + uint16 copyLength, maxCodeValue, code, nextCode, lastCode, oldCode; + + byte *copyBuf = new byte[8192]; + + struct { uint16 code; byte value; } codeTable[8192]; + memset(codeTable, 0, sizeof(codeTable)); + + _codeLength = 9; + nextCode = 258; + maxCodeValue = 512; + + copyLength = 0; + _bitPos = 0; + + while (1) { + + code = getCode(); + + if (code == 257) + break; + + if (code == 256) { + _codeLength = 9; + nextCode = 258; + maxCodeValue = 512; + lastCode = getCode(); + oldCode = lastCode; + litByte = lastCode; + *dest++ = litByte; + } else { + lastCode = code; + if (code >= nextCode) { + lastCode = oldCode; + copyBuf[copyLength++] = litByte; + } + while (lastCode > 255) { + copyBuf[copyLength++] = codeTable[lastCode].value; + lastCode = codeTable[lastCode].code; + } + litByte = lastCode; + copyBuf[copyLength++] = lastCode; + while (copyLength > 0) + *dest++ = copyBuf[--copyLength]; + codeTable[nextCode].value = lastCode; + codeTable[nextCode].code = oldCode; + nextCode++; + oldCode = code; + if (nextCode >= maxCodeValue && _codeLength <= 12) { + _codeLength++; + maxCodeValue <<= 1; + } + } + + } + + delete[] copyBuf; + +} + +uint16 LzwDecompressor::getCode() { + const byte bitMasks[9] = { + 0x00, 0x01, 0x03, 0x07, 0x0F, 0x1F, 0x3F, 0x7F, 0x0FF + }; + uint16 bits, loCode, hiCode; + loCode = (READ_LE_UINT16(_source) >> _bitPos) & 0xFF; + _source++; + bits = _codeLength - 8; + hiCode = (READ_LE_UINT16(_source) >> _bitPos) & bitMasks[bits]; + _bitPos += bits; + if (_bitPos > 8) { + _source++; + _bitPos -= 8; + } + return (hiCode << 8) | loCode; +} + +uint32 decompressDBE(byte *source, byte **dest) { + + uint32 destSize = READ_LE_UINT32(source + 4); + *dest = new byte[destSize]; + + debug(1, "decompressDBE() destSize = %d", destSize); + + LzwDecompressor dec; + dec.decompress(source + 16, *dest); + + debug(1, "decompressDBE() ok"); + + return destSize; +} + +} // End of namespace Access diff --git a/engines/access/decompress.h b/engines/access/decompress.h new file mode 100644 index 0000000000..522bfb2acf --- /dev/null +++ b/engines/access/decompress.h @@ -0,0 +1,48 @@ +/* ScummVM - Graphic Adventure Engine +* +* ScummVM is the legal property of its developers, whose names +* are too numerous to list here. Please refer to the COPYRIGHT +* file distributed with this source distribution. +/* ScummVM - Graphic Adventure Engine + * + * ScummVM is the legal property of its developers, whose names + * are too numerous to list here. Please refer to the COPYRIGHT + * file distributed with this source distribution. + * + * This program is free software; you can redistribute it and/or + * modify it under the terms of the GNU General Public License + * as published by the Free Software Foundation; either version 2 + * of the License, or (at your option) any later version. + + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + + * You should have received a copy of the GNU General Public License + * along with this program; if not, write to the Free Software + * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. + * + */ + +#ifndef ACCESS_DECOMPRESS_H +#define ACCESS_DECOMPRESS_H + +#include "common/scummsys.h" + +namespace Access { + +class LzwDecompressor { +public: + void decompress(byte *source, byte *dest); +private: + byte *_source; + byte _codeLength, _bitPos; + uint16 getCode(); +}; + +uint32 decompressDBE(byte *source, byte **dest); + +} // End of namespace Access + +#endif diff --git a/engines/access/files.cpp b/engines/access/files.cpp index 549429b154..7b4a23d0e8 100644 --- a/engines/access/files.cpp +++ b/engines/access/files.cpp @@ -68,6 +68,8 @@ void FileManager::openFile(const Common::String &filename) { _file.close(); if (_file.open(filename)) error("Could not open file - %s", filename.c_str()); + + _filesize = _file.size(); } byte *FileManager::loadScreen(int fileNum, int subfile) { @@ -83,11 +85,11 @@ byte *FileManager::loadScreen(const Common::String &filename) { openFile(filename); // Get the palette - _vm->_screen->loadPalette(_stream); + _vm->_screen->loadPalette(&_file); // Get a stream for the remainder of the file delete _stream; - _stream = _file.readStream(_file.size()); + _stream = _file.readStream(_file.size() - _file.pos()); return handleFile(); } @@ -95,21 +97,23 @@ byte *FileManager::loadScreen(const Common::String &filename) { byte *FileManager::handleFile() { char header[3]; _stream->read(&header[0], 3); + _stream->seek(-3, SEEK_CUR); - if (!strncmp(header, "DBE", 3)) - // Decompress the resource - return decompressFile(); - - // Not compressed, so pass out all of the file - _stream->seek(0); - byte *data = new byte[_stream->size()]; - _stream->read(data, _stream->size()); + bool isCompressed = !strncmp(header, "DBE", 3); - return data; -} + // Get the data from the file or resource + _filesize = _stream->size() - _stream->pos(); + byte *data = new byte[_filesize]; + _stream->read(data, _filesize); -byte *FileManager::decompressFile() { - error("TODO: decompression"); + // If the data is compressed, uncompress it + if (isCompressed) { + byte *src = data; + _filesize = decompressDBE(src, &data); + delete[] src; + } + + return data; } void FileManager::setAppended(int fileNum) { @@ -138,5 +142,4 @@ void FileManager::gotoAppended(int subfile) { _stream = _file.readStream(size); } - } // End of namespace Access diff --git a/engines/access/files.h b/engines/access/files.h index 42b439ce45..9224b29429 100644 --- a/engines/access/files.h +++ b/engines/access/files.h @@ -26,6 +26,7 @@ #include "common/scummsys.h" #include "common/array.h" #include "common/file.h" +#include "access/decompress.h" namespace Access { @@ -39,16 +40,12 @@ private: void openFile(const Common::String &filename); byte *handleFile(); - - byte *decompressFile(); - public: int _fileNumber; Common::File _file; Common::SeekableReadStream *_stream; Common::Array<uint32> _fileIndex; - uint32 _entryOffset; - uint32 _nextOffset; + uint32 _filesize; public: FileManager(AccessEngine *vm); ~FileManager(); diff --git a/engines/access/module.mk b/engines/access/module.mk index 7e23ede512..c9d593de22 100644 --- a/engines/access/module.mk +++ b/engines/access/module.mk @@ -3,6 +3,7 @@ MODULE := engines/access MODULE_OBJS := \ access.o \ debugger.o \ + decompress.o \ detection.o \ events.o \ files.o \ |