diff options
author | Filippos Karapetis | 2011-02-08 19:50:45 +0000 |
---|---|---|
committer | Filippos Karapetis | 2011-02-08 19:50:45 +0000 |
commit | 72a9706950675cc3fd04e39d0f842193d66a5f9e (patch) | |
tree | 39ad5b83dfc81c0836f1dc3473f73f4cd19990db /engines/sci/video | |
parent | 656afd6daa2b468fdf2731f082d1fd5897e43110 (diff) | |
download | scummvm-rg350-72a9706950675cc3fd04e39d0f842193d66a5f9e.tar.gz scummvm-rg350-72a9706950675cc3fd04e39d0f842193d66a5f9e.tar.bz2 scummvm-rg350-72a9706950675cc3fd04e39d0f842193d66a5f9e.zip |
SCI: Some work on robot videos
- The size of the videos is now calculated when they are loaded (this helps remove some
nasty hacks and constant memory reallocations and simplifies the code)
- Some work on frame placement (e.g. in robot 1305, Phantasmagoria)
svn-id: r55830
Diffstat (limited to 'engines/sci/video')
-rw-r--r-- | engines/sci/video/robot_decoder.cpp | 64 | ||||
-rw-r--r-- | engines/sci/video/robot_decoder.h | 8 |
2 files changed, 61 insertions, 11 deletions
diff --git a/engines/sci/video/robot_decoder.cpp b/engines/sci/video/robot_decoder.cpp index d243816ff7..8dd60cd9a6 100644 --- a/engines/sci/video/robot_decoder.cpp +++ b/engines/sci/video/robot_decoder.cpp @@ -76,6 +76,8 @@ enum robotPalTypes { RobotDecoder::RobotDecoder(Audio::Mixer *mixer, bool isBigEndian) { _surface = 0; + _width = 0; + _height = 0; _fileStream = 0; _audioStream = 0; _dirtyPalette = false; @@ -123,6 +125,9 @@ bool RobotDecoder::loadStream(Common::SeekableReadStream *stream) { readPaletteChunk(_header.paletteDataSize); readFrameSizesChunk(); + calculateVideoDimensions(); + _surface->create(_width, _height, 1); + return true; } @@ -218,31 +223,56 @@ void RobotDecoder::readFrameSizesChunk() { _fileStream->seek((curPos & ~0x7ff) + 2048); } +void RobotDecoder::calculateVideoDimensions() { + // This is an O(n) operation, as each frame has a different size. + // We need to know the actual frame size to have a constant video size. + uint32 pos = _fileStream->pos(); + + for (uint32 curFrame = 0; curFrame < _header.frameCount; curFrame++) { + _fileStream->skip(4); + uint16 frameWidth = _fileStream->readUint16(); + uint16 frameHeight = _fileStream->readUint16(); + if (frameWidth > _width) + _width = frameWidth; + if (frameHeight > _height) + _height = frameHeight; + _fileStream->skip(_frameTotalSize[curFrame] - 8); + } + + _fileStream->seek(pos); +} + const Graphics::Surface *RobotDecoder::decodeNextFrame() { // Read frame image header (24 bytes) _fileStream->skip(3); byte frameScale = _fileStream->readByte(); uint16 frameWidth = _fileStream->readUint16(); uint16 frameHeight = _fileStream->readUint16(); - _fileStream->skip(8); // x, y, width and height of the frame + _fileStream->skip(4); // unknown, almost always 0 + uint16 frameX = _fileStream->readUint16(); + uint16 frameY = _fileStream->readUint16(); uint16 compressedSize = _fileStream->readUint16(); uint16 frameFragments = _fileStream->readUint16(); _fileStream->skip(4); // unknown - uint32 decompressedSize = frameWidth * frameHeight * frameScale / 100; - _surface->free(); - _surface->create(frameWidth, frameHeight, 1); - _surface->w = frameWidth * frameScale / 100; + // FIXME: A frame's height + position can go off limits... why? With the + // following, we cut the contents to fit the frame + uint16 scaledHeight = CLIP<uint16>(decompressedSize / frameWidth, 0, _height - frameY); + // FIXME: Same goes for the frame's width + position. In this case, we + // modify the position to fit the contents on screen. + if (frameWidth + frameX > _width) + frameX = _width - frameWidth; + assert (frameWidth + frameX <= _width && scaledHeight + frameY <= _height); DecompressorLZS lzs; + byte *decompressedFrame = new byte[decompressedSize]; + byte *outPtr = decompressedFrame; if (_header.version == 4) { // v4 has just the one fragment, it seems, and ignores the fragment count Common::SeekableSubReadStream fragmentStream(_fileStream, _fileStream->pos(), _fileStream->pos() + compressedSize); - lzs.unpack(&fragmentStream, (byte *)_surface->pixels, compressedSize, decompressedSize); + lzs.unpack(&fragmentStream, outPtr, compressedSize, decompressedSize); } else { - byte *outPtr = (byte *)_surface->pixels; - for (uint16 i = 0; i < frameFragments; ++i) { uint32 compressedFragmentSize = _fileStream->readUint32(); uint32 decompressedFragmentSize = _fileStream->readUint32(); @@ -261,6 +291,24 @@ const Graphics::Surface *RobotDecoder::decodeNextFrame() { } } + // Copy over the decompressed frame + byte *inFrame = decompressedFrame; + byte *outFrame = (byte *)_surface->pixels; + + // Black out the surface + memset(outFrame, 0, _width * _height); + + // Move to the correct y coordinate + outFrame += _width * frameY; + + for (uint16 y = 0; y < scaledHeight; y++) { + memcpy(outFrame + frameX, inFrame, frameWidth); + inFrame += frameWidth; + outFrame += _width; + } + + delete[] decompressedFrame; + // +1 because we start with frame number -1 uint32 audioChunkSize = _frameTotalSize[_curFrame + 1] - (24 + compressedSize); diff --git a/engines/sci/video/robot_decoder.h b/engines/sci/video/robot_decoder.h index eb0a150c9d..b8ca0ee857 100644 --- a/engines/sci/video/robot_decoder.h +++ b/engines/sci/video/robot_decoder.h @@ -62,9 +62,8 @@ public: void close(); bool isVideoLoaded() const { return _fileStream != 0; } - uint16 getWidth() const { assert(_surface); return _surface->w; } - uint16 getHeight() const { assert(_surface); return _surface->h; } - uint16 getPitch() const { assert(_surface); return _surface->pitch; } + uint16 getWidth() const { return _width; } + uint16 getHeight() const { return _height; } uint32 getFrameCount() const { return _header.frameCount; } const Graphics::Surface *decodeNextFrame(); Graphics::PixelFormat getPixelFormat() const { return Graphics::PixelFormat::createFormatCLUT8(); } @@ -80,6 +79,7 @@ private: void readHeaderChunk(); void readPaletteChunk(uint16 chunkSize); void readFrameSizesChunk(); + void calculateVideoDimensions(); void freeData(); @@ -89,6 +89,8 @@ private: Common::SeekableSubReadStreamEndian *_fileStream; + uint16 _width; + uint16 _height; uint32 *_frameTotalSize; byte _palette[256 * 3]; bool _dirtyPalette; |