diff options
author | whitertandrek | 2018-03-23 22:52:16 +0200 |
---|---|---|
committer | Eugene Sandulenko | 2018-06-28 23:51:32 +0200 |
commit | c6df869fec46858d25d294854c1e446ca47fd85d (patch) | |
tree | 21711e773e5b7e0d0e92821c1439f2cc981fb2cf | |
parent | bba35c5f2c71aa8c83c7ba9180f08ce7f609c911 (diff) | |
download | scummvm-rg350-c6df869fec46858d25d294854c1e446ca47fd85d.tar.gz scummvm-rg350-c6df869fec46858d25d294854c1e446ca47fd85d.tar.bz2 scummvm-rg350-c6df869fec46858d25d294854c1e446ca47fd85d.zip |
PINK: Basic implementation of CEL decoder. Fixed sprite positioning
-rw-r--r-- | engines/pink/cel_decoder.cpp | 103 | ||||
-rw-r--r-- | engines/pink/cel_decoder.h | 17 | ||||
-rw-r--r-- | engines/pink/director.cpp | 7 | ||||
-rw-r--r-- | engines/pink/module.mk | 1 | ||||
-rw-r--r-- | engines/pink/objects/actions/action_cel.cpp | 21 | ||||
-rw-r--r-- | engines/pink/objects/actions/action_cel.h | 6 | ||||
-rw-r--r-- | engines/pink/objects/actions/action_play.cpp | 7 | ||||
-rw-r--r-- | engines/pink/objects/actions/action_still.cpp | 3 | ||||
-rw-r--r-- | engines/pink/objects/pages/page.cpp | 2 | ||||
-rw-r--r-- | engines/pink/objects/pages/page.h | 2 | ||||
-rw-r--r-- | engines/pink/resource_mgr.cpp | 5 | ||||
-rw-r--r-- | engines/pink/resource_mgr.h | 3 |
12 files changed, 153 insertions, 24 deletions
diff --git a/engines/pink/cel_decoder.cpp b/engines/pink/cel_decoder.cpp index 5d20e415d3..bff0e4a5bc 100644 --- a/engines/pink/cel_decoder.cpp +++ b/engines/pink/cel_decoder.cpp @@ -20,6 +20,107 @@ * */ +#include <common/stream.h> +#include "cel_decoder.h" + namespace Pink { -}
\ No newline at end of file +bool CelDecoder::loadStream(Common::SeekableReadStream *stream) { + close(); + + /* uint32 frameSize = */ stream->readUint32LE(); + uint16 frameType = stream->readUint16LE(); + + // Check FLC magic number + if (frameType != 0xAF12) { + warning("FlicDecoder::loadStream(): attempted to load non-FLC data (type = 0x%04X)", frameType); + return false; + } + + uint16 frameCount = stream->readUint16LE(); + uint16 width = stream->readUint16LE(); + uint16 height = stream->readUint16LE(); + uint16 colorDepth = stream->readUint16LE(); + if (colorDepth != 8) { + warning("FlicDecoder::loadStream(): attempted to load an FLC with a palette of color depth %d. Only 8-bit color palettes are supported", colorDepth); + return false; + } + + addTrack(new CelVideoTrack(stream, frameCount, width, height)); + return true; +} + +uint32 CelDecoder::getX(){ + CelVideoTrack *track = (CelVideoTrack*) getTrack(0); + if (!track) + return -1; + return track->getX(); +} + +uint32 CelDecoder::getY() { + CelVideoTrack *track = (CelVideoTrack*) getTrack(0); + if (!track) + return -1; + return track->getY(); +} + +CelDecoder::CelVideoTrack::CelVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, bool skipHeader) + : FlicVideoTrack(stream, frameCount, width, height, 1) { + readHeader(); +} + +#define PREFIX_TYPE 0xF100 +#define CEL_DATA 3 + +void CelDecoder::CelVideoTrack::readPrefixChunk() { + _fileStream->seek(0x80); + uint32 chunkSize = _fileStream->readUint32LE(); + uint16 chunkType = _fileStream->readUint16LE(); + if (chunkType != PREFIX_TYPE) + return; + uint32 offset = 6; + while (offset < chunkSize) { + uint32 subchunkSize = _fileStream->readUint32LE(); + uint16 subchunkType = _fileStream->readUint16LE(); + switch (subchunkType) { + case CEL_DATA: + _fileStream->skip(2); // Unknown field + _center.x = _fileStream->readUint16LE(); + _center.y = _fileStream->readUint16LE(); + _fileStream->skip(subchunkSize - 6 - 6); + break; + default: + _fileStream->skip(subchunkSize - 6); + break; + } + offset += subchunkSize; + } +} + +void CelDecoder::CelVideoTrack::readHeader() { + _fileStream->readUint16LE(); // flags + // Note: The normal delay is a 32-bit integer (dword), whereas the overridden delay is a 16-bit integer (word) + // the frame delay is the FLIC "speed", in milliseconds. + _frameDelay = _startFrameDelay = _fileStream->readUint32LE(); + + _fileStream->seek(80); + _offsetFrame1 = _fileStream->readUint32LE(); + _offsetFrame2 = _fileStream->readUint32LE(); + + if (_offsetFrame1 > 0x80) { + readPrefixChunk(); + } + + // Seek to the first frame + _fileStream->seek(_offsetFrame1); +} + +uint32 CelDecoder::CelVideoTrack::getX() const { + return _center.x - getWidth() / 2; +} + +uint32 CelDecoder::CelVideoTrack::getY() const { + return _center.y - getHeight() / 2; +} + +} // End of namepsace Pink
\ No newline at end of file diff --git a/engines/pink/cel_decoder.h b/engines/pink/cel_decoder.h index 0e8d6120e6..c096793f1c 100644 --- a/engines/pink/cel_decoder.h +++ b/engines/pink/cel_decoder.h @@ -29,8 +29,25 @@ namespace Pink { class CelDecoder : public Video::FlicDecoder { +public: + uint32 getX(); + uint32 getY(); + virtual bool loadStream(Common::SeekableReadStream *stream); +protected: + class CelVideoTrack : public FlicVideoTrack { + public: + CelVideoTrack(Common::SeekableReadStream *stream, uint16 frameCount, uint16 width, uint16 height, bool skipHeader = false); + virtual void readHeader(); + + uint32 getX() const; + uint32 getY() const; + + private: + void readPrefixChunk(); + Common::Point _center; + }; }; } diff --git a/engines/pink/director.cpp b/engines/pink/director.cpp index cdc60c8aa4..f45948b9e7 100644 --- a/engines/pink/director.cpp +++ b/engines/pink/director.cpp @@ -24,6 +24,7 @@ #include <engines/pink/objects/actions/action_cel.h> #include "graphics/surface.h" #include "graphics/palette.h" +#include "cel_decoder.h" namespace Pink { Director::Director(OSystem *system) @@ -32,10 +33,12 @@ Director::Director(OSystem *system) void Director::draw() { bool needUpdate = 0; for (int i = 0; i < _sprites.size(); ++i) { - Video::FlicDecoder *decoder = _sprites[i]->getDecoder(); + CelDecoder *decoder = _sprites[i]->getDecoder(); if (decoder->needsUpdate()) { const Graphics::Surface *surface = decoder->decodeNextFrame(); - _system->copyRectToScreen(surface->getPixels(), surface->pitch, 0, 0, surface->w, surface->h); + _system->copyRectToScreen(surface->getPixels(), surface->pitch, + decoder->getX(), decoder->getY(), + surface->w, surface->h); needUpdate = 1; } } diff --git a/engines/pink/module.mk b/engines/pink/module.mk index 1b833738b3..4bff006ed0 100644 --- a/engines/pink/module.mk +++ b/engines/pink/module.mk @@ -2,6 +2,7 @@ MODULE := engines/pink MODULE_OBJS = \ archive.o \ + cel_decoder.o \ console.o \ cursor_mgr.o \ detection.o \ diff --git a/engines/pink/objects/actions/action_cel.cpp b/engines/pink/objects/actions/action_cel.cpp index 5385386b39..abfc59373e 100644 --- a/engines/pink/objects/actions/action_cel.cpp +++ b/engines/pink/objects/actions/action_cel.cpp @@ -26,11 +26,12 @@ #include "engines/pink/archive.h" #include "engines/pink/objects/pages/game_page.h" #include "pink/pink.h" +#include "pink/cel_decoder.h" namespace Pink { ActionCEL::ActionCEL() - : _flicDecoder(nullptr) { + : _decoder(nullptr) { } @@ -40,30 +41,30 @@ void ActionCEL::deserialize(Archive &archive) { } void ActionCEL::start(bool unk) { - if (!_flicDecoder) - _flicDecoder = _actor->getPage()->loadCel(_fileName); + if (!_decoder) + _decoder = _actor->getPage()->loadCel(_fileName); _actor->getPage()->getGame()->getDirector()->addSprite(this); this->onStart(); } void ActionCEL::end() { _actor->getPage()->getGame()->getDirector()->removeSprite(this); - delete _flicDecoder; - _flicDecoder = nullptr; + delete _decoder; + _decoder = nullptr; } uint32 ActionCEL::getZ() { return _z; } -Video::FlicDecoder *ActionCEL::getDecoder() { - return _flicDecoder; +CelDecoder *ActionCEL::getDecoder() { + return _decoder; } bool ActionCEL::initPallete(Director *director) { - _flicDecoder = _actor->getPage()->loadCel(_fileName); - _flicDecoder->decodeNextFrame(); - director->setPallette(_flicDecoder->getPalette()); + _decoder = _actor->getPage()->loadCel(_fileName); + _decoder->decodeNextFrame(); + director->setPallette(_decoder->getPalette()); return 1; } diff --git a/engines/pink/objects/actions/action_cel.h b/engines/pink/objects/actions/action_cel.h index 92986fb1bc..4dc37724df 100644 --- a/engines/pink/objects/actions/action_cel.h +++ b/engines/pink/objects/actions/action_cel.h @@ -28,6 +28,8 @@ namespace Pink { +class CelDecoder; + class ActionCEL : public Action { public: ActionCEL(); @@ -36,13 +38,13 @@ public: virtual void end(); uint32 getZ(); - Video::FlicDecoder *getDecoder(); + CelDecoder *getDecoder(); virtual bool initPallete(Director *director); protected: virtual void onStart() {} ; - Video::FlicDecoder *_flicDecoder; + CelDecoder *_decoder; Common::String _fileName; uint32 _z; }; diff --git a/engines/pink/objects/actions/action_play.cpp b/engines/pink/objects/actions/action_play.cpp index 3945fe62a2..969eacf035 100644 --- a/engines/pink/objects/actions/action_play.cpp +++ b/engines/pink/objects/actions/action_play.cpp @@ -24,6 +24,7 @@ #include "action_play.h" #include "../actors/actor.h" #include "engines/pink/archive.h" +#include "pink/cel_decoder.h" namespace Pink { @@ -44,10 +45,10 @@ void ActionPlay::end() { void ActionPlay::onStart() { debug("Actor %s has now ActionPlay %s", _actor->getName().c_str(), _name.c_str()); - _flicDecoder->seekToFrame(_startFrame); + _decoder->seekToFrame(_startFrame); if (_stopFrame != -1) - _flicDecoder->setEndFrame(_stopFrame); - _flicDecoder->start(); + _decoder->setEndFrame(_stopFrame); + _decoder->start(); } } // End of namespace Pink diff --git a/engines/pink/objects/actions/action_still.cpp b/engines/pink/objects/actions/action_still.cpp index 8e90c836bb..563af93c28 100644 --- a/engines/pink/objects/actions/action_still.cpp +++ b/engines/pink/objects/actions/action_still.cpp @@ -24,6 +24,7 @@ #include "action_still.h" #include "engines/pink/archive.h" #include <engines/pink/objects/actors/actor.h> +#include "pink/cel_decoder.h" namespace Pink { @@ -44,7 +45,7 @@ void ActionStill::end() { void ActionStill::onStart() { debug("Actor %s has now ActionStill %s", _actor->getName().c_str(), _name.c_str()); - _flicDecoder->seekToFrame(_startFrame); + _decoder->seekToFrame(_startFrame); } } // End of namespace Pink
\ No newline at end of file diff --git a/engines/pink/objects/pages/page.cpp b/engines/pink/objects/pages/page.cpp index dc2bb43c51..a57860e11d 100644 --- a/engines/pink/objects/pages/page.cpp +++ b/engines/pink/objects/pages/page.cpp @@ -45,7 +45,7 @@ Sound *Page::loadSound(Common::String &fileName) { } -Video::FlicDecoder *Page::loadCel(Common::String &fileName) { +CelDecoder *Page::loadCel(Common::String &fileName) { return _resMgr.loadCEL(fileName); } diff --git a/engines/pink/objects/pages/page.h b/engines/pink/objects/pages/page.h index 5244ed9ae9..282d061f1e 100644 --- a/engines/pink/objects/pages/page.h +++ b/engines/pink/objects/pages/page.h @@ -40,7 +40,7 @@ public: void load(Archive &archive); Actor *findActor(Common::String &name); Sound* loadSound(Common::String &fileName); - Video::FlicDecoder *loadCel(Common::String &fileName); + CelDecoder *loadCel(Common::String &fileName); virtual void toConsole(); diff --git a/engines/pink/resource_mgr.cpp b/engines/pink/resource_mgr.cpp index b367a52e36..c91101ec67 100644 --- a/engines/pink/resource_mgr.cpp +++ b/engines/pink/resource_mgr.cpp @@ -28,6 +28,7 @@ #include "pink.h" #include "sound.h" #include "engines/pink/objects/pages/game_page.h" +#include "cel_decoder.h" namespace Pink { @@ -77,8 +78,8 @@ PinkEngine *ResourceMgr::getGame() const { return _game; } -Video::FlicDecoder *ResourceMgr::loadCEL(Common::String &name) { - Video::FlicDecoder *decoder = new Video::FlicDecoder(); +CelDecoder *ResourceMgr::loadCEL(Common::String &name) { + CelDecoder *decoder = new CelDecoder(); decoder->loadStream(getResourceStream(name)); return decoder; } diff --git a/engines/pink/resource_mgr.h b/engines/pink/resource_mgr.h index 8d04ec7df7..cc52ee8bd0 100644 --- a/engines/pink/resource_mgr.h +++ b/engines/pink/resource_mgr.h @@ -37,6 +37,7 @@ class PinkEngine; class OrbFile; class BroFile; class Sound; +class CelDecoder; struct ResourceDescription; @@ -49,7 +50,7 @@ public: //Common::String loadText(Common::String &name); Sound *loadSound(Common::String &name); - Video::FlicDecoder *loadCEL(Common::String &name); + CelDecoder *loadCEL(Common::String &name); PinkEngine *getGame() const; private: |