diff options
Diffstat (limited to 'engines/mutationofjb/animationdecoder.cpp')
-rw-r--r-- | engines/mutationofjb/animationdecoder.cpp | 113 |
1 files changed, 79 insertions, 34 deletions
diff --git a/engines/mutationofjb/animationdecoder.cpp b/engines/mutationofjb/animationdecoder.cpp index 43590a92c3..84325a95ef 100644 --- a/engines/mutationofjb/animationdecoder.cpp +++ b/engines/mutationofjb/animationdecoder.cpp @@ -27,10 +27,13 @@ namespace MutationOfJB { -AnimationDecoder::AnimationDecoder(const Common::String &fileName) : _fileName(fileName) { +AnimationDecoder::AnimationDecoder(const Common::String &fileName) : _fileName(fileName), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) { _surface.create(IMAGE_WIDTH, IMAGE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8()); + _owningSurface = true; } +AnimationDecoder::AnimationDecoder(const Common::String &fileName, const Graphics::Surface &outSurface) : _fileName(fileName), _surface(outSurface), _owningSurface(false), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {} + bool AnimationDecoder::decode(AnimationDecoderCallback *callback) { EncryptedFile file; file.open(_fileName); @@ -60,39 +63,43 @@ bool AnimationDecoder::decode(AnimationDecoderCallback *callback) { // Subrecords. if (recordId == 0xF1FA) { - if (subrecords == 0) { - if (callback) { - callback->onFrame(frameNo, _surface); // Empty record, frame identical to the previous one. - } + if ((_fromFrame != -1 && frameNo < _fromFrame) || (_toFrame != -1 && frameNo > _toFrame)) { + file.seek(length - 16, SEEK_CUR); } else { - for (int i = 0; i < subrecords; ++i) { - int32 filePos = file.pos(); - - const uint32 subLength = file.readUint32LE(); - const uint16 type = file.readUint16LE(); - - if (type == 0x0B) { - loadPalette(file); - if (callback) { - callback->onPaletteUpdated(_palette); - } - } else if (type == 0x0F) { - loadFullFrame(file, subLength - 6); - if (callback) { - callback->onFrame(frameNo, _surface); - } - } else if (type == 0x0C) { - loadDiffFrame(file, subLength - 6); - if (callback) { - callback->onFrame(frameNo, _surface); - } - } else { - debug("Unsupported record type %02X.", type); - file.seek(subLength - 6, SEEK_CUR); + if (subrecords == 0) { + if (callback) { + callback->onFrame(frameNo, _surface); // Empty record, frame identical to the previous one. } + } else { + for (int i = 0; i < subrecords; ++i) { + int32 filePos = file.pos(); + + const uint32 subLength = file.readUint32LE(); + const uint16 type = file.readUint16LE(); + + if (type == 0x0B) { + loadPalette(file); + if (callback) { + callback->onPaletteUpdated(_palette); + } + } else if (type == 0x0F) { + loadFullFrame(file, subLength - 6); + if (callback) { + callback->onFrame(frameNo, _surface); + } + } else if (type == 0x0C) { + loadDiffFrame(file, subLength - 6); + if (callback) { + callback->onFrame(frameNo, _surface); + } + } else { + debug("Unsupported record type %02X.", type); + file.seek(subLength - 6, SEEK_CUR); + } - // Makes decoding more robust, because for some reason records might have extra data at the end. - file.seek(filePos + subLength, SEEK_SET); + // Makes decoding more robust, because for some reason records might have extra data at the end. + file.seek(filePos + subLength, SEEK_SET); + } } } frameNo++; @@ -105,6 +112,13 @@ bool AnimationDecoder::decode(AnimationDecoderCallback *callback) { return true; } +void AnimationDecoder::setPartialMode(int fromFrame, int toFrame, const Common::Rect area, uint8 threshold) { + _fromFrame = fromFrame; + _toFrame = toFrame; + _area = area; + _threshold = threshold; +} + void AnimationDecoder::loadPalette(Common::SeekableReadStream &file) { uint16 packets = file.readUint16LE(); const uint8 skipCount = file.readByte(); @@ -165,6 +179,11 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) { for (uint16 line = firstLine; line < firstLine + numLines; ++line) { uint8 *imageData = reinterpret_cast<uint8 *>(_surface.getBasePtr(0, line)); + uint16 lineOffset = 0; + + // Optimization for skipping the whole line if outside of confined area. + const bool skipLineOutput = !_area.isEmpty() && (line < _area.top || line >= _area.bottom); + uint8 buf[0x80]; uint8 runs = file.readByte(); while (runs--) { @@ -172,17 +191,42 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) { uint8 num = file.readByte(); imageData += localOffset; + lineOffset += localOffset; if (num == 0) { // Ignore? debug("Zero RLE number found."); } else if (num < 0x80) { - file.read(imageData, num); + if (!skipLineOutput) { + if (_area.isEmpty() && _threshold == 0xFF) { + file.read(imageData, num); + } else { + file.read(buf, num); + for (uint16 i = 0; i < num; i++) { + if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold) + imageData[i] = buf[i]; + } + } + } else { + file.skip(num); + } + imageData += num; + lineOffset += num; } else { const uint8 color = file.readByte(); const int no = 0x100 - num; - memset(imageData, color, no); + if (!skipLineOutput) { + if (_area.isEmpty() && _threshold == 0xFF) { + memset(imageData, color, no); + } else { + for (int i = 0; i < no; i++) { + if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold) + imageData[i] = color; + } + } + } imageData += no; + lineOffset += no; } } @@ -190,7 +234,8 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) { } AnimationDecoder::~AnimationDecoder() { - _surface.free(); + if (_owningSurface) + _surface.free(); } } |