SHERLOCK: Merged decompression code into Resources class

This commit is contained in:
Paul Gilbert 2015-05-16 08:56:50 -04:00
parent 8c7f5bf92f
commit 052e04c005
7 changed files with 77 additions and 132 deletions

View file

@ -1,80 +0,0 @@
/* 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 "sherlock/decompress.h"
namespace Sherlock {
/**
* Decompresses an LZW compressed resource. If no outSize is specified, it will
* decompress the entire resource. If, however, an explicit size is specified,
* then it means we're already within a resource, and only want to decompress
* part of it.
*/
Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize) {
if (outSize == -1) {
source.seek(4);
outSize = source.readSint32LE();
}
byte lzWindow[4096];
uint16 lzWindowPos;
uint16 cmd;
byte *outBuffer = (byte *)malloc(outSize);
byte *outBufferEnd = outBuffer + outSize;
Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
cmd = 0;
do {
cmd >>= 1;
if (!(cmd & 0x100))
cmd = source.readByte() | 0xFF00;
if (cmd & 1) {
byte literal = source.readByte();
*outBuffer++ = literal;
lzWindow[lzWindowPos] = literal;
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
} else {
int copyPos, copyLen;
copyPos = source.readByte();
copyLen = source.readByte();
copyPos = copyPos | ((copyLen & 0xF0) << 4);
copyLen = (copyLen & 0x0F) + 3;
while (copyLen--) {
byte literal = lzWindow[copyPos];
copyPos = (copyPos + 1) & 0x0FFF;
*outBuffer++ = literal;
lzWindow[lzWindowPos] = literal;
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
} while (outBuffer < outBufferEnd);
return outS;
}
} // namespace Sherlock

View file

@ -1,36 +0,0 @@
/* 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 SHERLOCK_DECOMPRESS_H
#define SHERLOCK_DECOMPRESS_H
#include "common/memstream.h"
namespace Sherlock {
#include "common/stream.h"
Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, int32 outSize = -1);
} // namespace Sherlock
#endif

View file

@ -5,7 +5,6 @@ MODULE_OBJS = \
scalpel/scalpel.o \ scalpel/scalpel.o \
tattoo/tattoo.o \ tattoo/tattoo.o \
animation.o \ animation.o \
decompress.o \
debugger.o \ debugger.o \
detection.o \ detection.o \
events.o \ events.o \

View file

@ -21,14 +21,14 @@
*/ */
#include "sherlock/resources.h" #include "sherlock/resources.h"
#include "sherlock/decompress.h"
#include "sherlock/screen.h" #include "sherlock/screen.h"
#include "sherlock/sherlock.h" #include "sherlock/sherlock.h"
#include "common/debug.h" #include "common/debug.h"
#include "common/memstream.h"
namespace Sherlock { namespace Sherlock {
Cache::Cache() { Cache::Cache(SherlockEngine *vm): _vm(vm) {
} }
/** /**
@ -76,7 +76,7 @@ void Cache::load(const Common::String &name, Common::SeekableReadStream &stream)
// Check whether the file is compressed // Check whether the file is compressed
if (signature == MKTAG('L', 'Z', 'V', 26)) { if (signature == MKTAG('L', 'Z', 'V', 26)) {
// It's compressed, so decompress the file and store it's data in the cache entry // It's compressed, so decompress the file and store it's data in the cache entry
Common::SeekableReadStream *decompressed = decompressLZ(stream); Common::SeekableReadStream *decompressed = _vm->_res->decompressLZ(stream);
cacheEntry.resize(decompressed->size()); cacheEntry.resize(decompressed->size());
decompressed->read(&cacheEntry[0], decompressed->size()); decompressed->read(&cacheEntry[0], decompressed->size());
@ -99,7 +99,7 @@ Common::SeekableReadStream *Cache::get(const Common::String &filename) const {
/*----------------------------------------------------------------*/ /*----------------------------------------------------------------*/
Resources::Resources() { Resources::Resources(SherlockEngine *vm): _vm(vm), _cache(vm) {
_resourceIndex = -1; _resourceIndex = -1;
addToCache("vgs.lib"); addToCache("vgs.lib");
@ -404,4 +404,62 @@ void ImageFile::decompressFrame(ImageFrame &frame, const byte *src) {
} }
} }
/**
* Decompress an LZW compressed resource
*/
Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source) {
if (_vm->getGameID() == GType_SerratedScalpel) {
uint32 id = source.readUint32BE();
assert(id == MKTAG('L', 'Z', 'V', 0x1A));
}
uint32 size = source.readUint32LE();
return decompressLZ(source, size);
}
/**
* Decompresses an LZW block of data with a specified output size
*/
Common::SeekableReadStream *Resources::decompressLZ(Common::SeekableReadStream &source, uint32 outSize) {
byte lzWindow[4096];
uint16 lzWindowPos;
uint16 cmd;
byte *outBuffer = (byte *)malloc(outSize);
byte *outBufferEnd = outBuffer + outSize;
Common::MemoryReadStream *outS = new Common::MemoryReadStream(outBuffer, outSize, DisposeAfterUse::YES);
memset(lzWindow, 0xFF, 0xFEE);
lzWindowPos = 0xFEE;
cmd = 0;
do {
cmd >>= 1;
if (!(cmd & 0x100))
cmd = source.readByte() | 0xFF00;
if (cmd & 1) {
byte literal = source.readByte();
*outBuffer++ = literal;
lzWindow[lzWindowPos] = literal;
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
} else {
int copyPos, copyLen;
copyPos = source.readByte();
copyLen = source.readByte();
copyPos = copyPos | ((copyLen & 0xF0) << 4);
copyLen = (copyLen & 0x0F) + 3;
while (copyLen--) {
byte literal = lzWindow[copyPos];
copyPos = (copyPos + 1) & 0x0FFF;
*outBuffer++ = literal;
lzWindow[lzWindowPos] = literal;
lzWindowPos = (lzWindowPos + 1) & 0x0FFF;
}
}
} while (outBuffer < outBufferEnd);
return outS;
}
} // End of namespace Sherlock } // End of namespace Sherlock

View file

@ -52,9 +52,10 @@ class SherlockEngine;
class Cache { class Cache {
private: private:
SherlockEngine *_vm;
CacheHash _resources; CacheHash _resources;
public: public:
Cache(); Cache(SherlockEngine *_vm);
bool isCached(const Common::String &filename) const; bool isCached(const Common::String &filename) const;
@ -66,13 +67,14 @@ public:
class Resources { class Resources {
private: private:
SherlockEngine *_vm;
Cache _cache; Cache _cache;
LibraryIndexes _indexes; LibraryIndexes _indexes;
int _resourceIndex; int _resourceIndex;
void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream); void loadLibraryIndex(const Common::String &libFilename, Common::SeekableReadStream *stream);
public: public:
Resources(); Resources(SherlockEngine *vm);
void addToCache(const Common::String &filename); void addToCache(const Common::String &filename);
void addToCache(const Common::String &filename, const Common::String &libFilename); void addToCache(const Common::String &filename, const Common::String &libFilename);
@ -86,6 +88,9 @@ public:
bool exists(const Common::String &filename) const; bool exists(const Common::String &filename) const;
int resourceIndex() const; int resourceIndex() const;
static Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source, uint32 outSize);
Common::SeekableReadStream *decompressLZ(Common::SeekableReadStream &source);
}; };
struct ImageFrame { struct ImageFrame {

View file

@ -23,7 +23,6 @@
#include "sherlock/scene.h" #include "sherlock/scene.h"
#include "sherlock/sherlock.h" #include "sherlock/sherlock.h"
#include "sherlock/scalpel/scalpel.h" #include "sherlock/scalpel/scalpel.h"
#include "sherlock/decompress.h"
namespace Sherlock { namespace Sherlock {
@ -274,7 +273,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read information // Read information
Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream : Common::SeekableReadStream *infoStream = !_lzwMode ? rrmStream :
decompressLZ(*rrmStream, bgHeader._numImages * 569 + Resources::decompressLZ(*rrmStream, bgHeader._numImages * 569 +
bgHeader._descSize + bgHeader._seqSize); bgHeader._descSize + bgHeader._seqSize);
_bgShapes.resize(bgHeader._numStructs); _bgShapes.resize(bgHeader._numStructs);
@ -302,7 +301,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the image data // Read in the image data
Common::SeekableReadStream *imageStream = _lzwMode ? Common::SeekableReadStream *imageStream = _lzwMode ?
decompressLZ(*rrmStream, bgInfo[idx]._filesize) : Resources::decompressLZ(*rrmStream, bgInfo[idx]._filesize) :
rrmStream->readStream(bgInfo[idx]._filesize); rrmStream->readStream(bgInfo[idx]._filesize);
_images[idx + 1]._images = new ImageFile(*imageStream); _images[idx + 1]._images = new ImageFile(*imageStream);
@ -331,7 +330,7 @@ bool Scene::loadScene(const Common::String &filename) {
_cAnim.clear(); _cAnim.clear();
if (bgHeader._numcAnimations) { if (bgHeader._numcAnimations) {
Common::SeekableReadStream *canimStream = _lzwMode ? Common::SeekableReadStream *canimStream = _lzwMode ?
decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) : Resources::decompressLZ(*rrmStream, 65 * bgHeader._numcAnimations) :
rrmStream->readStream(65 * bgHeader._numcAnimations); rrmStream->readStream(65 * bgHeader._numcAnimations);
_cAnim.resize(bgHeader._numcAnimations); _cAnim.resize(bgHeader._numcAnimations);
@ -344,7 +343,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the room bounding areas // Read in the room bounding areas
int size = rrmStream->readUint16LE(); int size = rrmStream->readUint16LE();
Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream : Common::SeekableReadStream *boundsStream = !_lzwMode ? rrmStream :
decompressLZ(*rrmStream, size); Resources::decompressLZ(*rrmStream, size);
_zones.resize(size / 10); _zones.resize(size / 10);
for (uint idx = 0; idx < _zones.size(); ++idx) { for (uint idx = 0; idx < _zones.size(); ++idx) {
@ -371,7 +370,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the walk data // Read in the walk data
size = rrmStream->readUint16LE(); size = rrmStream->readUint16LE();
Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream : Common::SeekableReadStream *walkStream = !_lzwMode ? rrmStream :
decompressLZ(*rrmStream, size); Resources::decompressLZ(*rrmStream, size);
_walkData.resize(size); _walkData.resize(size);
walkStream->read(&_walkData[0], size); walkStream->read(&_walkData[0], size);
@ -408,7 +407,7 @@ bool Scene::loadScene(const Common::String &filename) {
// Read in the background // Read in the background
Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream : Common::SeekableReadStream *bgStream = !_lzwMode ? rrmStream :
decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); Resources::decompressLZ(*rrmStream, SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT); bgStream->read(screen._backBuffer1.getPixels(), SHERLOCK_SCREEN_WIDTH * SHERLOCK_SCENE_HEIGHT);
@ -982,7 +981,7 @@ int Scene::startCAnim(int cAnimNum, int playRate) {
// Load the canimation into the cache // Load the canimation into the cache
Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) : Common::SeekableReadStream *imgStream = !_lzwMode ? rrmStream->readStream(cAnim._size) :
decompressLZ(*rrmStream, cAnim._size); Resources::decompressLZ(*rrmStream, cAnim._size);
res.addToCache(fname, *imgStream); res.addToCache(fname, *imgStream);
delete imgStream; delete imgStream;

View file

@ -79,7 +79,7 @@ void SherlockEngine::initialize() {
ImageFile::setVm(this); ImageFile::setVm(this);
Object::setVm(this); Object::setVm(this);
Sprite::setVm(this); Sprite::setVm(this);
_res = new Resources(); _res = new Resources(this);
_animation = new Animation(this); _animation = new Animation(this);
_debugger = new Debugger(this); _debugger = new Debugger(this);
_events = new Events(this); _events = new Events(this);