diff --git a/engines/sherlock/image_file.cpp b/engines/sherlock/image_file.cpp index 29d4cdfd4f..1ee7ee9a73 100644 --- a/engines/sherlock/image_file.cpp +++ b/engines/sherlock/image_file.cpp @@ -38,6 +38,7 @@ ImageFile::ImageFile() { } ImageFile::ImageFile(const Common::String &name, bool skipPal, bool animImages) { + _name = name; Common::SeekableReadStream *stream = _vm->_res->load(name); Common::fill(&_palette[0], &_palette[PALETTE_SIZE], 0); @@ -52,8 +53,39 @@ ImageFile::ImageFile(Common::SeekableReadStream &stream, bool skipPal) { } ImageFile::~ImageFile() { - for (uint idx = 0; idx < size(); ++idx) - (*this)[idx]._frame.free(); + for (uint idx = 0; idx < size(); ++idx) { + if (_frames[idx]._decoded) + _frames[idx]._frame.free(); + } +} + +ImageFrame& ImageFile::operator[](uint index) { + if (!_frames[index]._decoded) { + decodeFrame(_frames[index]); + } + + return _frames[index]; +} + +uint ImageFile::size() { + return _frames.size(); +} + +void ImageFile::push_back(const ImageFrame &frame) { + _frames.push_back(frame); +} + +void ImageFile::decodeFrame(ImageFrame &frame) { + debug("%s: %dx%d", _name.c_str(), frame._width, frame._height); + + Common::SeekableReadStream *stream = _vm->_res->load(_name); + stream->seek(frame._pos); + byte *data = new byte[frame._size + 4]; + stream->read(data, frame._size); + Common::fill(data + frame._size, data + frame._size + 4, 0); + frame.decompressFrame(data, IS_ROSE_TATTOO); + delete[] data; + delete stream; } void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool animImages) { @@ -92,12 +124,22 @@ void ImageFile::load(Common::SeekableReadStream &stream, bool skipPalette, bool frame._size = frame._width * frame._height; } - // Load data for frame and decompress it - byte *data1 = new byte[frame._size + 4]; - stream.read(data1, frame._size); - Common::fill(data1 + frame._size, data1 + frame._size + 4, 0); - frame.decompressFrame(data1, IS_ROSE_TATTOO); - delete[] data1; + frame._pos = stream.pos(); + + if (_name.empty()) { + // Load data for frame and decompress it + frame._decoded = true; + byte *data1 = new byte[frame._size + 4]; + stream.read(data1, frame._size); + Common::fill(data1 + frame._size, data1 + frame._size + 4, 0); + frame.decompressFrame(data1, IS_ROSE_TATTOO); + delete[] data1; + } else { +debug("%s: %dx%d", _name.c_str(), frame._width, frame._height); + frame._decoded = false; + + stream.seek(MIN(stream.pos() + frame._size, stream.size())); + } push_back(frame); } @@ -302,6 +344,10 @@ ImageFile3DO::ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData) } } +void ImageFile3DO::decodeFrame(ImageFrame &frame) { + error("ImageFile3DO: Frame should already have been decoded"); +} + void ImageFile3DO::load(Common::SeekableReadStream &stream, bool isRoomData) { uint32 headerId = 0; @@ -354,6 +400,7 @@ void ImageFile3DO::loadAnimationFile(Common::SeekableReadStream &stream) { celDataSize = stream.readUint16BE(); + frame._decoded = true; frame._width = stream.readUint16BE() + 1; // 2 bytes BE width frame._height = stream.readByte() + 1; // 1 byte BE height frame._paletteBase = 0; @@ -586,6 +633,7 @@ void ImageFile3DO::load3DOCelFile(Common::SeekableReadStream &stream) { // Set up frame ImageFrame imageFrame; + imageFrame._decoded = true; imageFrame._width = ccbWidth; imageFrame._height = ccbHeight; imageFrame._paletteBase = 0; @@ -712,6 +760,7 @@ void ImageFile3DO::load3DOCelRoomData(Common::SeekableReadStream &stream) { { ImageFrame imageFrame; + imageFrame._decoded = true; imageFrame._width = ccbWidth; imageFrame._height = ccbHeight; imageFrame._paletteBase = 0; @@ -956,6 +1005,7 @@ void ImageFile3DO::loadFont(Common::SeekableReadStream &stream) { // create frame ImageFrame imageFrame; + imageFrame._decoded = true; imageFrame._width = widthTablePtr[curChar]; imageFrame._height = header_fontHeight; imageFrame._paletteBase = 0; diff --git a/engines/sherlock/image_file.h b/engines/sherlock/image_file.h index 0ae7cc1dcb..6cd7a2370d 100644 --- a/engines/sherlock/image_file.h +++ b/engines/sherlock/image_file.h @@ -37,6 +37,8 @@ namespace Sherlock { class SherlockEngine; struct ImageFrame { + uint32 _pos; + byte _decoded; uint32 _size; uint16 _width, _height; int _paletteBase; @@ -76,9 +78,11 @@ struct ImageFrame { int sDrawYOffset(int scaleVal) const; }; -class ImageFile : public Common::Array { +class ImageFile { private: static SherlockEngine *_vm; + Common::Array _frames; + Common::String _name; /** * Load the data of the sprite @@ -89,7 +93,13 @@ private: * Gets the palette at the start of the sprite file */ void loadPalette(Common::SeekableReadStream &stream); +protected: + virtual void decodeFrame(ImageFrame &frame); public: + ImageFrame& operator[](uint index); + uint size(); + void push_back(const ImageFrame &frame); + byte _palette[256 * 3]; public: ImageFile(); @@ -152,6 +162,9 @@ private: */ void loadFont(Common::SeekableReadStream &stream); +protected: + virtual void decodeFrame(ImageFrame &frame); + public: ImageFile3DO(const Common::String &name, ImageFile3DOType imageFile3DOType); ImageFile3DO(Common::SeekableReadStream &stream, bool isRoomData = false);