From 69ecc15c028208f6b0f28d6df4d86d1a8ba7e26a Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 10 Aug 2014 22:25:30 -0400 Subject: ACCESS: Add decoding of animation resources --- engines/access/animation.cpp | 129 +++++++++++++++++++++++++++++++++++++++---- engines/access/animation.h | 53 ++++++++++++++++-- engines/access/room.cpp | 8 ++- engines/access/scripts.cpp | 91 +++++++++++++++--------------- engines/access/scripts.h | 2 +- 5 files changed, 219 insertions(+), 64 deletions(-) diff --git a/engines/access/animation.cpp b/engines/access/animation.cpp index 4d73801e5d..0d8589d4f1 100644 --- a/engines/access/animation.cpp +++ b/engines/access/animation.cpp @@ -21,24 +21,123 @@ */ #include "common/endian.h" +#include "common/memstream.h" #include "access/animation.h" namespace Access { +AnimationResource::AnimationResource(const byte *data, int size) { + Common::MemoryReadStream stream(data, size); + int count = stream.readUint16LE(); + + Common::Array offsets; + for (int i = 0; i < count; ++i) + offsets.push_back(stream.readUint32LE()); + + _animations.reserve(count); + for (int i = 0; i < count; ++i) { + stream.seek(offsets[i]); + Animation *anim = new Animation(stream); + _animations.push_back(anim); + } +} + +AnimationResource::~AnimationResource() { + for (int i = 0; i < (int)_animations.size(); ++i) + delete _animations[i]; +} + +/*------------------------------------------------------------------------*/ + +Animation::Animation(Common::MemoryReadStream &stream) { + uint32 startOfs = stream.pos(); + + _type = stream.readByte(); + _scaling = stream.readByte(); + stream.readByte(); // unk + _frameNumber = stream.readByte(); + _initialTicks = stream.readUint16LE(); + stream.readUint16LE(); // unk + stream.readUint16LE(); // unk + _loopCount = stream.readUint16LE(); + _countdownTicks = stream.readUint16LE(); + _currentLoopCount = stream.readUint16LE(); + stream.readUint16LE(); // unk + + Common::Array frameOffsets; + uint16 ofs; + while ((ofs = stream.readUint16LE()) != 0) + frameOffsets.push_back(ofs); + + for (int i = 0; i < (int)frameOffsets.size(); i++) { + stream.seek(startOfs + frameOffsets[i]); + + AnimationFrame *frame = new AnimationFrame(stream, startOfs); + _frames.push_back(frame); + } +} + +Animation::~Animation() { + for (int i = 0; i < (int)_frames.size(); ++i) + delete _frames[i]; +} + +void Animation::animate() { + error("TODO"); +} + +/*------------------------------------------------------------------------*/ + +AnimationFrame::AnimationFrame(Common::MemoryReadStream &stream, int startOffset) { + uint16 nextOffset; + + stream.readByte(); // unk + _baseX = stream.readUint16LE(); + _baseY = stream.readUint16LE(); + _frameDelay = stream.readUint16LE(); + nextOffset = stream.readUint16LE(); + + while (nextOffset != 0) { + stream.seek(startOffset + nextOffset); + + AnimationFramePart *framePart = new AnimationFramePart(stream); + _parts.push_back(framePart); + + nextOffset = stream.readUint16LE(); + } +} + +AnimationFrame::~AnimationFrame() { + for (int i = 0; i < (int)_parts.size(); ++i) + delete _parts[i]; +} + +/*------------------------------------------------------------------------*/ + +AnimationFramePart::AnimationFramePart(Common::MemoryReadStream &stream) { + _flags = stream.readByte(); + _slotIndex = stream.readByte(); + _spriteIndex = stream.readByte(); + _position.x = stream.readUint16LE(); + _position.y = stream.readUint16LE(); + _priority = stream.readUint16LE(); +} + +/*------------------------------------------------------------------------*/ + AnimationManager::AnimationManager(AccessEngine *vm) : Manager(vm) { - _anim = nullptr; _animation = nullptr; + _animStart = nullptr; } AnimationManager::~AnimationManager() { - delete[] _anim; delete _animation; } void AnimationManager::freeAnimationData() { - delete[] _anim; - _anim = nullptr; + delete _animation; _animation = nullptr; + _animStart = nullptr; } void AnimationManager::clearTimers() { @@ -48,10 +147,17 @@ void AnimationManager::clearTimers() { _animationTimers.clear(); } +void AnimationManager::loadAnimations(const byte *data, int size) { + _animationTimers.clear(); + delete _animation; + _animation = new AnimationResource(data, size); +} + + Animation *AnimationManager::setAnimation(int animId) { Animation *anim = findAnimation(animId); - anim->_countdownTicks = anim->_ticks; + anim->_countdownTicks = anim->_initialTicks; anim->_frameNumber = 0; anim->_currentLoopCount = (anim->_type != 3 && anim->_type != 4) ? 0 : @@ -62,18 +168,17 @@ Animation *AnimationManager::setAnimation(int animId) { } void AnimationManager::setAnimTimer(Animation *anim) { - + _animationTimers.push_back(anim); } Animation *AnimationManager::findAnimation(int animId) { - _animation = new Animation(_anim + READ_LE_UINT16(_anim + animId * 4 + 2)); - return _animation; + _animStart = _animation->getAnimation(animId); + return _animStart; } -/*------------------------------------------------------------------------*/ - -Animation::Animation(const byte *data) { - +void AnimationManager::animate(int animId) { + Animation *anim = findAnimation(animId); + anim->animate(); } } // End of namespace Access diff --git a/engines/access/animation.h b/engines/access/animation.h index 879d1e9318..45a59efb68 100644 --- a/engines/access/animation.h +++ b/engines/access/animation.h @@ -25,41 +25,86 @@ #include "common/scummsys.h" #include "common/array.h" +#include "common/memstream.h" #include "access/data.h" namespace Access { +class AnimationResource; class Animation; +class AnimationFrame; +class AnimationFramePart; class AnimationManager : public Manager { public: - const byte *_anim; - Animation *_animation; Common::Array _animationTimers; + AnimationResource *_animation; + Animation *_animStart; public: AnimationManager(AccessEngine *vm); ~AnimationManager(); void freeAnimationData(); + void loadAnimations(const byte *data, int size); + void clearTimers(); Animation *findAnimation(int animId); Animation *setAnimation(int animId); void setAnimTimer(Animation *anim); + + void animate(int animId); +}; + +class AnimationResource { +private: + Common::Array _animations; +public: + AnimationResource(const byte *data, int size); + ~AnimationResource(); + + int getCount() { return _animations.size(); } + Animation *getAnimation(int idx) { return _animations[idx]; } }; class Animation { +private: + Common::Array _frames; public: int _type; int _scaling; int _frameNumber; - int _ticks; + int _initialTicks; int _loopCount; int _countdownTicks; int _currentLoopCount; int _field10; public: - Animation(const byte *data); + Animation(Common::MemoryReadStream &stream); + ~Animation(); + + void animate(); +}; + +class AnimationFrame { +public: + int _baseX, _baseY; + int _frameDelay; + Common::Array _parts; +public: + AnimationFrame(Common::MemoryReadStream &stream, int startOffset); + ~AnimationFrame(); +}; + +class AnimationFramePart { +public: + byte _flags; + int _slotIndex; + int _spriteIndex; + Common::Point _position; + int _priority; +public: + AnimationFramePart(Common::MemoryReadStream &stream); }; } // End of namespace Access diff --git a/engines/access/room.cpp b/engines/access/room.cpp index 371b714467..98e9d5ed6f 100644 --- a/engines/access/room.cpp +++ b/engines/access/room.cpp @@ -207,9 +207,11 @@ void Room::loadRoomData(const byte *roomData) { // Load animation data _vm->_animation->freeAnimationData(); - if (roomInfo._animFile._fileNum != -1) - _vm->_animation->_anim = _vm->_files->loadFile(roomInfo._animFile._fileNum, - roomInfo._animFile._subfile); + if (roomInfo._animFile._fileNum != -1) { + byte *data = _vm->_files->loadFile(roomInfo._animFile._fileNum, + roomInfo._animFile._subfile); + _vm->_animation->loadAnimations(data, _vm->_files->_filesize); + } _vm->_scaleI = roomInfo._scaleI; _vm->_screen->_scrollThreshold = roomInfo._scrollThreshold; diff --git a/engines/access/scripts.cpp b/engines/access/scripts.cpp index a6ecfa3eff..fd42530eb9 100644 --- a/engines/access/scripts.cpp +++ b/engines/access/scripts.cpp @@ -85,7 +85,7 @@ void Scripts::executeCommand(int commandIndex) { &Scripts::CMDOBJECT, &Scripts::CMDENDOBJECT, &Scripts::cmdJumpLook, &Scripts::cmdJumpHelp, &Scripts::cmdJumpGet, &Scripts::cmdJumpMove, &Scripts::cmdJumpUse, &Scripts::cmdJumpTalk, &Scripts::cmdNull, - &Scripts::CMDPRINT, &Scripts::cmdRetPos, &Scripts::CMDANIM, + &Scripts::CMDPRINT, &Scripts::cmdRetPos, &Scripts::cmdAnim, &Scripts::cmdSetFlag, &Scripts::cmdCheckFlag, &Scripts::cmdGoto, &Scripts::cmdSetInventory, &Scripts::cmdSetInventory, &Scripts::cmdCheckInventory, &Scripts::CMDSETTEX, &Scripts::CMDNEWROOM, &Scripts::CMDCONVERSE, @@ -114,9 +114,9 @@ void Scripts::executeCommand(int commandIndex) { (this->*COMMAND_LIST[commandIndex])(); } -void Scripts::CMDOBJECT() { } +void Scripts::CMDOBJECT() { error("TODO"); } -void Scripts::CMDENDOBJECT() { } +void Scripts::CMDENDOBJECT() { error("TODO"); } void Scripts::cmdJumpLook() { if (_vm->_selectCommand == 0) @@ -163,14 +163,17 @@ void Scripts::cmdJumpTalk() { void Scripts::cmdNull() { } -void Scripts::CMDPRINT() { } +void Scripts::CMDPRINT() { error("TODO"); } void Scripts::cmdRetPos() { _endFlag = true; _returnCode = 0; } -void Scripts::CMDANIM() { } +void Scripts::cmdAnim() { + int animId = _data->readUint16LE(); + _vm->_animation->animate(animId); +} void Scripts::cmdSetFlag() { int flagNum = _data->readByte(); @@ -216,10 +219,10 @@ void Scripts::cmdCheckInventory() { _data->skip(2); } -void Scripts::CMDSETTEX() { } -void Scripts::CMDNEWROOM() { } -void Scripts::CMDCONVERSE() { } -void Scripts::CMDCHECKFRAME() { } +void Scripts::CMDSETTEX() { error("TODO"); } +void Scripts::CMDNEWROOM() { error("TODO"); } +void Scripts::CMDCONVERSE() { error("TODO"); } +void Scripts::CMDCHECKFRAME() { error("TODO"); } void Scripts::cmdCheckAnim() { int id = _data->readUint16LE(); @@ -232,7 +235,7 @@ void Scripts::cmdCheckAnim() { _data->skip(4); } -void Scripts::CMDSND() { } +void Scripts::CMDSND() { error("TODO"); } void Scripts::cmdRetNeg() { _endFlag = true; @@ -260,9 +263,9 @@ void Scripts::cmdSetAnim() { _vm->_animation->setAnimTimer(anim); } -void Scripts::CMDDISPINV() { } -void Scripts::CMDSETTIMER() { } -void Scripts::CMDCHECKTIMER() { } +void Scripts::CMDDISPINV() { error("TODO"); } +void Scripts::CMDSETTIMER() { error("TODO"); } +void Scripts::CMDCHECKTIMER() { error("TODO"); } void Scripts::cmdSetTravel() { if (_vm->_selectCommand == 5) @@ -271,8 +274,8 @@ void Scripts::cmdSetTravel() { _data->skip(2); } -void Scripts::CMDSETVID() { } -void Scripts::CMDPLAYVID() { } +void Scripts::CMDSETVID() { error("TODO"); } +void Scripts::CMDPLAYVID() { error("TODO"); } void Scripts::cmdPlotImage() { _vm->_destIn = _vm->_current; @@ -290,7 +293,7 @@ void Scripts::cmdSetDisplay() { _vm->_current = _vm->_screen; } -void Scripts::CMDSETBUFFER() { } +void Scripts::CMDSETBUFFER() { error("TODO"); } void Scripts::cmdSetScroll() { _vm->_screen->_scrollCol = _data->readUint16LE(); @@ -299,31 +302,31 @@ void Scripts::cmdSetScroll() { _vm->_screen->_scrollY = 0; } -void Scripts::CMDSAVERECT() { } -void Scripts::CMDSETBUFVID() { } -void Scripts::CMDPLAYBUFVID() { } +void Scripts::CMDSAVERECT() { error("TODO"); } +void Scripts::CMDSETBUFVID() { error("TODO"); } +void Scripts::CMDPLAYBUFVID() { error("TODO"); } void Scripts::cmeRemoveLast() { --_vm->_numAnimTimers; } -void Scripts::CMDSPECIAL() { } -void Scripts::CMDSETCYCLE() { } -void Scripts::CMDCYCLE() { } -void Scripts::CMDCHARSPEAK() { } -void Scripts::CMDTEXSPEAK() { } -void Scripts::CMDTEXCHOICE() { } -void Scripts::CMDWAIT() { } -void Scripts::CMDSETCONPOS() { } -void Scripts::CMDCHECKVFRAME() { } -void Scripts::CMDJUMPCHOICE() { } -void Scripts::CMDRETURNCHOICE() { } -void Scripts::CMDCLEARBLOCK() { } -void Scripts::CMDLOADSOUND() { } -void Scripts::CMDFREESOUND() { } -void Scripts::CMDSETVIDSND() { } -void Scripts::CMDPLAYVIDSND() { } -void Scripts::CMDPUSHLOCATION() { } +void Scripts::CMDSPECIAL() { error("TODO"); } +void Scripts::CMDSETCYCLE() { error("TODO"); } +void Scripts::CMDCYCLE() { error("TODO"); } +void Scripts::CMDCHARSPEAK() { error("TODO"); } +void Scripts::CMDTEXSPEAK() { error("TODO"); } +void Scripts::CMDTEXCHOICE() { error("TODO"); } +void Scripts::CMDWAIT() { error("TODO"); } +void Scripts::CMDSETCONPOS() { error("TODO"); } +void Scripts::CMDCHECKVFRAME() { error("TODO"); } +void Scripts::CMDJUMPCHOICE() { error("TODO"); } +void Scripts::CMDRETURNCHOICE() { error("TODO"); } +void Scripts::CMDCLEARBLOCK() { error("TODO"); } +void Scripts::CMDLOADSOUND() { error("TODO"); } +void Scripts::CMDFREESOUND() { error("TODO"); } +void Scripts::CMDSETVIDSND() { error("TODO"); } +void Scripts::CMDPLAYVIDSND() { error("TODO"); } +void Scripts::CMDPUSHLOCATION() { error("TODO"); } void Scripts::cmdPlayerOff() { _vm->_player->_playerOff = true; @@ -333,18 +336,18 @@ void Scripts::cmdPlayerOn() { _vm->_player->_playerOff = false; } -void Scripts::CMDDEAD() { } +void Scripts::CMDDEAD() { error("TODO"); } void Scripts::cmdFadeOut() { _vm->_screen->forceFadeOut(); } -void Scripts::CMDENDVID() { } -void Scripts::CMDHELP() { } -void Scripts::CMDCYCLEBACK() { } -void Scripts::CMDCHAPTER() { } -void Scripts::CMDSETHELP() { } -void Scripts::CMDCENTERPANEL() { } +void Scripts::CMDENDVID() { error("TODO"); } +void Scripts::CMDHELP() { error("TODO"); } +void Scripts::CMDCYCLEBACK() { error("TODO"); } +void Scripts::CMDCHAPTER() { error("TODO"); } +void Scripts::CMDSETHELP() { error("TODO"); } +void Scripts::CMDCENTERPANEL() { error("TODO"); } void Scripts::cmdMainPanel() { if (_vm->_screen->_vesaMode) { @@ -353,7 +356,7 @@ void Scripts::cmdMainPanel() { } } -void Scripts::CMDRETFLASH() { } +void Scripts::CMDRETFLASH() { error("TODO"); } } // End of namespace Access diff --git a/engines/access/scripts.h b/engines/access/scripts.h index 3173c8a587..c8f951deae 100644 --- a/engines/access/scripts.h +++ b/engines/access/scripts.h @@ -52,7 +52,7 @@ protected: void cmdNull(); void CMDPRINT(); void cmdRetPos(); - void CMDANIM(); + void cmdAnim(); void cmdSetFlag(); void cmdCheckFlag(); -- cgit v1.2.3