aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mads/animation.cpp255
-rw-r--r--engines/mads/animation.h54
-rw-r--r--engines/mads/msurface.cpp67
-rw-r--r--engines/mads/msurface.h12
-rw-r--r--engines/mads/palette.cpp9
-rw-r--r--engines/mads/palette.h5
-rw-r--r--engines/mads/sprites.cpp14
-rw-r--r--engines/mads/sprites.h2
8 files changed, 382 insertions, 36 deletions
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
index c97d707f39..d0c7d3079b 100644
--- a/engines/mads/animation.cpp
+++ b/engines/mads/animation.cpp
@@ -27,7 +27,7 @@
namespace MADS {
-AAHeader::AAHeader(Common::SeekableReadStream *f) {
+void AAHeader::load(Common::SeekableReadStream *f) {
_spriteSetsCount = f->readUint16LE();
_miscEntriesCount = f->readUint16LE();
_frameEntriesCount = f->readUint16LE();
@@ -40,7 +40,7 @@ AAHeader::AAHeader(Common::SeekableReadStream *f) {
_roomNumber = f->readUint16LE();
f->skip(2);
_manualFlag = f->readUint16LE() != 0;
- _spriteListIndex = f->readUint16LE();
+ _spritesIndex = f->readUint16LE();
_scrollPosition.x = f->readSint16LE();
_scrollPosition.y = f->readSint16LE();
_scrollTicks = f->readUint32LE();
@@ -184,33 +184,33 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
MadsPack madsPack(&f);
Common::SeekableReadStream *stream = madsPack.getItemStream(0);
- AAHeader aaHeader(stream);
+ _header.load(stream);
delete stream;
- if (aaHeader._animMode == 4)
+ if (_header._animMode == 4)
flags |= 0x4000;
if (flags & 0x100) {
- loadInterface(interfaceSurface, depthSurface, aaHeader, flags, palAnimData, sceneInfo);
+ loadInterface(interfaceSurface, depthSurface, _header, flags, palAnimData, sceneInfo);
}
if (flags & 0x200) {
// No data
- aaHeader._messagesCount = 0;
- aaHeader._frameEntriesCount = 0;
- aaHeader._miscEntriesCount = 0;
+ _header._messagesCount = 0;
+ _header._frameEntriesCount = 0;
+ _header._miscEntriesCount = 0;
}
// Initialize the reference list
_spriteListIndexes.clear();
- for (int i = 0; i < aaHeader._spriteSetsCount; ++i)
+ for (int i = 0; i < _header._spriteSetsCount; ++i)
_spriteListIndexes.push_back(-1);
_messages.clear();
- if (aaHeader._messagesCount > 0) {
+ if (_header._messagesCount > 0) {
// Chunk 2: Following is a list of any messages for the animation
Common::SeekableReadStream *msgStream = madsPack.getItemStream(1);
- for (int i = 0; i < aaHeader._messagesCount; ++i) {
+ for (int i = 0; i < _header._messagesCount; ++i) {
AnimMessage rec;
rec.load(msgStream);
_messages.push_back(rec);
@@ -220,11 +220,11 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
}
_frameEntries.clear();
- if (aaHeader._frameEntriesCount > 0) {
+ if (_header._frameEntriesCount > 0) {
// Chunk 3: animation frame info
Common::SeekableReadStream *frameStream = madsPack.getItemStream(2);
- for (int i = 0; i < aaHeader._frameEntriesCount; i++) {
+ for (int i = 0; i < _header._frameEntriesCount; i++) {
AnimFrameEntry rec;
rec.load(frameStream);
_frameEntries.push_back(rec);
@@ -234,11 +234,11 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
}
_miscEntries.clear();
- if (aaHeader._miscEntriesCount > 0) {
+ if (_header._miscEntriesCount > 0) {
// Chunk 4: Misc Data
Common::SeekableReadStream *miscStream = madsPack.getItemStream(3);
- for (int i = 0; i < aaHeader._miscEntriesCount; ++i) {
+ for (int i = 0; i < _header._miscEntriesCount; ++i) {
AnimMiscEntry rec;
rec.load(miscStream);
_miscEntries.push_back(rec);
@@ -249,8 +249,8 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
// If the animation specifies a font, then load it for access
delete _font;
- if (aaHeader._flags & ANIM_CUSTOM_FONT) {
- Common::String fontName = "*" + aaHeader._fontResource;
+ if (_header._flags & ANIM_CUSTOM_FONT) {
+ Common::String fontName = "*" + _header._fontResource;
_font = _vm->_font->getFont(fontName.c_str());
} else {
_font = nullptr;
@@ -260,28 +260,28 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
for (uint i = 0; i < _spriteSets.size(); ++i)
delete _spriteSets[i];
_spriteSets.clear();
- _spriteSets.resize(aaHeader._spriteSetsCount);
+ _spriteSets.resize(_header._spriteSetsCount);
- for (int i = 0; i < aaHeader._spriteSetsCount; ++i) {
- if (aaHeader._manualFlag && (i == aaHeader._spriteListIndex)) {
+ for (int i = 0; i < _header._spriteSetsCount; ++i) {
+ if (_header._manualFlag && (i == _header._spritesIndex)) {
// Skip over field, since it's manually loaded
_spriteSets[i] = nullptr;
} else {
- _spriteSets[i] = new SpriteAsset(_vm, aaHeader._spriteSetNames[i], flags);
+ _spriteSets[i] = new SpriteAsset(_vm, _header._spriteSetNames[i], flags);
}
}
- if (aaHeader._manualFlag) {
- Common::String resName = "*" + aaHeader._spriteSetNames[aaHeader._spriteListIndex];
+ if (_header._manualFlag) {
+ Common::String resName = "*" + _header._spriteSetNames[_header._spritesIndex];
SpriteAsset *sprites = new SpriteAsset(_vm, resName, flags);
- _spriteSets[aaHeader._spriteListIndex] = sprites;
+ _spriteSets[_header._spritesIndex] = sprites;
- _spriteListIndexes[aaHeader._spriteListIndex] = _scene->_sprites.add(sprites);
+ _spriteListIndexes[_header._spritesIndex] = _scene->_sprites.add(sprites);
}
// TODO: List var_420/var_422 population that seems to overwrite other structures?
- if (aaHeader._animMode == 4) {
+ if (_header._animMode == 4) {
// Remaps the sprite list indexes for frames to the loaded sprite list indexes
for (uint i = 0; i < _frameEntries.size(); ++i) {
int spriteListIndex = _frameEntries[i]._spriteSlot._spritesIndex;
@@ -298,6 +298,33 @@ void Animation::load(MSurface &depthSurface, InterfaceSurface &interfaceSurface,
f.close();
}
+void Animation::loadFrame(int frameNumber) {
+ Scene &scene = _vm->_game->_scene;
+ if (_skipLoad)
+ return;
+
+ Common::Point pt;
+ int listIndex = _spriteListIndexes[_header._spritesIndex];
+ SpriteAsset &spriteSet = scene._spriteSlots.getSprite(listIndex);
+
+ if (_unkIndex < 0) {
+ MSurface *frame = spriteSet.getFrame(0);
+ pt.x = frame->getBounds().left;
+ pt.y = frame->getBounds().top;
+ } else {
+ pt.x = _unkList[_unkIndex].x;
+ pt.y = _unkList[_unkIndex].y;
+ _unkIndex = 1 - _unkIndex;
+ }
+
+ if (drawFrame(spriteSet, pt, frameNumber))
+ error("proc1 failure");
+}
+
+bool Animation::drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber) {
+ return 0;
+}
+
void Animation::loadInterface(InterfaceSurface &interfaceSurface, MSurface &depthSurface,
AAHeader &header, int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo) {
_scene->_depthStyle = 0;
@@ -323,8 +350,182 @@ void Animation::loadInterface(InterfaceSurface &interfaceSurface, MSurface &dept
}
}
+bool Animation::hasScroll() const {
+ return (_header._scrollPosition.x != 0) || (_header._scrollPosition.x != 0);
+}
+
void Animation::update() {
- warning("TODO: Animation::update");
+ Scene &scene = _vm->_game->_scene;
+
+ if (_header._manualFlag) {
+ int spriteListIndex = _spriteListIndexes[_header._spritesIndex];
+ int newIndex = -1;
+
+ for (uint idx = _oldFrameEntry; idx < _frameEntries.size(); ++idx) {
+ if (_frameEntries[idx]._frameNumber > _currentFrame)
+ break;
+ if (_frameEntries[idx]._spriteSlot._spritesIndex == spriteListIndex)
+ newIndex = _frameEntries[idx]._spriteSlot._frameNumber;
+ }
+
+ if (newIndex >= 0)
+ loadFrame(newIndex);
+ }
+
+ // If it's not time for the next frame, then exit
+ if (_vm->_events->_currentTimer < _nextFrameTimer)
+ return;
+
+ for (uint idx = 0; idx < scene._spriteSlots.size(); ++idx) {
+ if (scene._spriteSlots[idx]._seqIndex >= 0x80)
+ scene._spriteSlots[idx]._spriteType = ST_EXPIRED;
+ }
+
+ // Validate the current frame
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Is the animation allowed to be repeated?
+ if (_resetFlag) {
+ _currentFrame = 0;
+ _oldFrameEntry = 0;
+ } else {
+ _freeFlag = true;
+ return;
+ }
+ }
+
+ // Handle executing any sound command for this frame
+ AnimMiscEntry &misc = _miscEntries[_currentFrame];
+ if (misc._soundId)
+ _vm->_sound->command(misc._soundId);
+
+ // Handle any screen scrolling
+ if (hasScroll()) {
+ scene._backgroundSurface.scrollX(_header._scrollPosition.x);
+ scene._backgroundSurface.scrollY(_header._scrollPosition.y);
+ scene._spriteSlots.fullRefresh();
+ }
+
+ // Handle any offset adjustment for sprites as of this frame
+ bool paChanged = false;
+ if (scene._posAdjust.x != misc._posAdjust.x) {
+ scene._posAdjust.x = misc._posAdjust.x;
+ paChanged = true;
+ }
+ if (scene._posAdjust.y != misc._posAdjust.y) {
+ scene._posAdjust.y = misc._posAdjust.y;
+ paChanged = true;
+ }
+
+ int newIndex = -1;
+ if (paChanged) {
+ newIndex = scene._spriteSlots.getIndex();
+ scene._spriteSlots[newIndex]._seqIndex = -1;
+ scene._spriteSlots[newIndex]._spriteType = ST_FULL_SCREEN_REFRESH;
+ }
+
+ // Main frame animation loop - frames get animated by being placed, as necessary, into the
+ // main sprite slot array
+ while ((uint)_oldFrameEntry < _frameEntries.size()) {
+ if (_frameEntries[_oldFrameEntry]._frameNumber > _currentFrame)
+ break;
+ else if (_frameEntries[_oldFrameEntry]._frameNumber == _currentFrame) {
+ // Found the correct frame
+ int spriteSlotIndex = 0;
+ int index = 0;
+
+ for (;;) {
+ if ((spriteSlotIndex == 0) && (index < (int)scene._spriteSlots.size())) {
+ int seqIndex = _frameEntries[_oldFrameEntry]._seqIndex - scene._spriteSlots[index]._seqIndex;
+ if (seqIndex == 0x80) {
+ if (scene._spriteSlots[index] == _frameEntries[_oldFrameEntry]._spriteSlot) {
+ scene._spriteSlots[index]._spriteType = ST_NONE;
+ spriteSlotIndex = -1;
+ }
+ }
+ ++index;
+ continue;
+ }
+
+ if (spriteSlotIndex == 0) {
+ int slotIndex = scene._spriteSlots.getIndex();
+ SpriteSlot &slot = scene._spriteSlots[slotIndex];
+ slot.copy(_frameEntries[_oldFrameEntry]._spriteSlot);
+ slot._seqIndex = _frameEntries[_oldFrameEntry]._seqIndex + 0x80;
+
+ SpriteAsset &spriteSet = scene._spriteSlots.getSprite(
+ scene._spriteSlots[slotIndex]._spritesIndex);
+ slot._spriteType = spriteSet.isBackground() ? ST_BACKGROUND : ST_FOREGROUND;
+ }
+ break;
+ }
+ }
+
+ ++_oldFrameEntry;
+ }
+
+ // Handle the display of any messages
+ for (uint idx = 0; idx < _messages.size(); ++idx) {
+ if (_messages[idx]._kernelMsgIndex >= 0) {
+ // Handle currently active message
+ if ((_currentFrame < _messages[idx]._startFrame) || (_currentFrame > _messages[idx]._endFrame)) {
+ scene._kernelMessages.remove(_messages[idx]._kernelMsgIndex);
+ _messages[idx]._kernelMsgIndex = -1;
+ --_messageCtr;
+ }
+ } else if ((_currentFrame >= _messages[idx]._startFrame) && (_currentFrame <= _messages[idx]._endFrame)) {
+ // Start displaying the message
+ AnimMessage &me = _messages[idx];
+
+ // The color index to use is dependant on how many messages are currently on-screen
+ uint8 colIndex;
+ switch (_messageCtr) {
+ case 1:
+ colIndex = 252;
+ break;
+ case 2:
+ colIndex = 16;
+ break;
+ default:
+ colIndex = 250;
+ break;
+ }
+
+ _vm->_palette->setEntry(colIndex, me._rgb1[0], me._rgb1[1], me._rgb1[2]);
+ _vm->_palette->setEntry(colIndex + 1, me._rgb2[0], me._rgb2[1], me._rgb2[2]);
+
+ // Add a kernel message to display the given text
+ me._kernelMsgIndex = scene._kernelMessages.add(me._pos, colIndex * 0x101 + 0x100,
+ 0, 0, INDEFINITE_TIMEOUT, me._msg);
+ assert(me._kernelMsgIndex >= 0);
+ ++_messageCtr;
+ }
+ }
+
+ // Move to the next frame
+ _currentFrame++;
+ if (_currentFrame >= (int)_miscEntries.size()) {
+ // Animation is complete
+ if (_abortTimers != 0) {
+ _vm->_game->_abortTimers = _abortTimers;
+ _vm->_game->_abortTimersMode = _abortMode;
+
+ if (_abortMode != ABORTMODE_1) {
+ // Copy the noun list
+ scene._action._action = _actionNouns;
+ }
+ }
+ }
+
+ int frameNum = MIN(_currentFrame, (int)_miscEntries.size() - 1);
+ _nextFrameTimer = _vm->_events->_currentTimer + _miscEntries[frameNum]._numTicks;
+}
+
+void Animation::setCurrentFrame(int frameNumber) {
+ _currentFrame = frameNumber;
+ _oldFrameEntry = 0;
+ _freeFlag = false;
+
+ _nextScrollTimer = _nextFrameTimer = _vm->_events->_currentTimer;
}
} // End of namespace MADS
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
index 9498483fb6..8df7b37439 100644
--- a/engines/mads/animation.h
+++ b/engines/mads/animation.h
@@ -90,7 +90,7 @@ public:
int _animMode;
int _roomNumber;
bool _manualFlag;
- int _spriteListIndex;
+ int _spritesIndex;
Common::Point _scrollPosition;
uint32 _scrollTicks;
Common::String _interfaceFile;
@@ -104,28 +104,57 @@ public:
/**
* Loads the data for a animation file header
*/
- AAHeader(Common::SeekableReadStream *f);
+ void load(Common::SeekableReadStream *f);
};
class Animation {
private:
MADSEngine *_vm;
Scene *_scene;
+ AAHeader _header;
- void loadInterface(InterfaceSurface &interfaceSurface, MSurface &depthSurface,
- AAHeader &header, int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo);
-protected:
- Animation(MADSEngine *vm, Scene *scene);
-public:
- static Animation *init(MADSEngine *vm, Scene *scene);
-public:
Common::Array<int> _spriteListIndexes;
Common::Array<AnimMessage> _messages;
Common::Array<AnimFrameEntry> _frameEntries;
Common::Array<AnimMiscEntry> _miscEntries;
Common::Array<SpriteAsset *> _spriteSets;
Font *_font;
+
+ int _currentFrame, _oldFrameEntry;
bool _resetFlag;
+ bool _freeFlag;
+ bool _skipLoad;
+ int _unkIndex;
+ Common::Point _unkList[2];
+ uint32 _nextFrameTimer;
+ uint32 _nextScrollTimer;
+ int _messageCtr;
+ int _abortTimers;
+ AbortTimerMode _abortMode;
+ ActionDetails _actionNouns;
+
+ /**
+ * Load data for a given frame
+ * @param frameNumber Frame number
+ */
+ void loadFrame(int frameNumber);
+
+ bool drawFrame(SpriteAsset &spriteSet, const Common::Point &pt, int frameNumber);
+
+ /**
+ * Load the user interface display for an animation
+ */
+ void loadInterface(InterfaceSurface &interfaceSurface, MSurface &depthSurface,
+ AAHeader &header, int flags, Common::Array<RGB4> *palAnimData, SceneInfo *sceneInfo);
+
+ /**
+ * Returns true if there is a scroll required
+ */
+ bool hasScroll() const;
+protected:
+ Animation(MADSEngine *vm, Scene *scene);
+public:
+ static Animation *init(MADSEngine *vm, Scene *scene);
public:
/*
* Destructor
@@ -147,6 +176,13 @@ public:
* Update the animation
*/
void update();
+
+ virtual void setCurrentFrame(int frameNumber);
+ virtual int getCurrentFrame() const { return _currentFrame; }
+
+ bool freeFlag() const { return _freeFlag; }
+ bool getAnimMode() const { return _header._animMode; }
+ int roomNumber() const { return _header._roomNumber; }
};
} // End of namespace MADS
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index aed00f5553..754fea851d 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -406,6 +406,73 @@ void MSurface::copyFrom(MSurface *src, const Common::Point &destPos, int depth,
}
}
+void MSurface::scrollX(int xAmount) {
+ if (xAmount == 0)
+ return;
+
+ byte buffer[80];
+ int direction = (xAmount > 0) ? -1 : 1;
+ int xSize = ABS(xAmount);
+ assert(xSize <= 80);
+
+ byte *srcP = getBasePtr(0, 0);
+
+ for (int y = 0; y < this->h; ++y, srcP += pitch) {
+ if (direction < 0) {
+ // Copy area to be overwritten
+ Common::copy(srcP, srcP + xSize, &buffer[0]);
+ // Shift the remainder of the line over the given area
+ Common::copy(srcP + xSize, srcP + this->w, srcP);
+ // Move buffered area to the end of the line
+ Common::copy(&buffer[0], &buffer[xSize], srcP + this->w - xSize);
+ }
+ else {
+ // Copy area to be overwritten
+ Common::copy_backward(srcP + this->w - xSize, srcP + this->w, &buffer[80]);
+ // Shift the remainder of the line over the given area
+ Common::copy_backward(srcP, srcP + this->w - xSize, srcP + this->w);
+ // Move buffered area to the start of the line
+ Common::copy_backward(&buffer[80 - xSize], &buffer[80], srcP + xSize);
+ }
+ }
+}
+
+void MSurface::scrollY(int yAmount) {
+ if (yAmount == 0)
+ return;
+
+ int direction = (yAmount > 0) ? 1 : -1;
+ int ySize = ABS(yAmount);
+ assert(ySize < (this->h / 2));
+ assert(this->w == pitch);
+
+ int blockSize = ySize * this->w;
+ byte *tempData = new byte[blockSize];
+ byte *pixelsP = getBasePtr(0, 0);
+
+ if (direction > 0) {
+ // Buffer the lines to be overwritten
+ byte *srcP = (byte *)getBasePtr(0, this->h - ySize);
+ Common::copy(srcP, srcP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy_backward(pixelsP, pixelsP + (pitch * (this->h - ySize)),
+ pixelsP + (pitch * this->h));
+ // Transfer the buffered lines top the top of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP);
+ }
+ else {
+ // Buffer the lines to be overwritten
+ Common::copy(pixelsP, pixelsP + (pitch * ySize), tempData);
+ // Vertically shift all the lines
+ Common::copy(pixelsP + (pitch * ySize), pixelsP + (pitch * this->h), pixelsP);
+ // Transfer the buffered lines to the bottom of the screen
+ Common::copy(tempData, tempData + blockSize, pixelsP + (pitch * (this->h - ySize)));
+ }
+
+ delete[] tempData;
+}
+
+
void MSurface::translate(Common::Array<RGB6> &palette) {
for (int y = 0; y < this->h; ++y) {
byte *pDest = getBasePtr(0, y);
diff --git a/engines/mads/msurface.h b/engines/mads/msurface.h
index c797033859..bd8142fd1a 100644
--- a/engines/mads/msurface.h
+++ b/engines/mads/msurface.h
@@ -180,6 +180,18 @@ public:
}
/**
+ * Scroll the screen horizontally by a given amount
+ * @param xAmount Horizontal amount
+ */
+ void scrollX(int xAmount);
+
+ /**
+ * Scroll the screen vertically by a given amount
+ * @param yAmount Vertical amount
+ */
+ void scrollY(int yAmount);
+
+ /**
* Translates the pixels of an image used the passed palette with RGB mapping
*/
void translate(Common::Array<RGB6> &palette);
diff --git a/engines/mads/palette.cpp b/engines/mads/palette.cpp
index aca1298a23..4568f7d39a 100644
--- a/engines/mads/palette.cpp
+++ b/engines/mads/palette.cpp
@@ -180,6 +180,15 @@ void Palette::setPalette(const byte *colors, uint start, uint num) {
reset();
}
+void Palette::setEntry(byte palIndex, byte r, byte g, byte b) {
+ _mainPalette[palIndex * 3] = r;
+ _mainPalette[palIndex * 3 + 1] = g;
+ _mainPalette[palIndex * 3 + 2] = b;
+
+ setPalette((const byte *)&_mainPalette[palIndex * 3], palIndex, 1);
+}
+
+
void Palette::grabPalette(byte *colors, uint start, uint num) {
g_system->getPaletteManager()->grabPalette(colors, start, num);
reset();
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
index 18b058cccc..a00e1789f4 100644
--- a/engines/mads/palette.h
+++ b/engines/mads/palette.h
@@ -165,6 +165,11 @@ public:
void setPalette(const byte *colors, uint start, uint num);
/**
+ * Set a palette entry
+ */
+ void setEntry(byte palIndex, byte r, byte g, byte b);
+
+ /**
* Returns a subset of the currently loaded palette
*/
void grabPalette(byte *colors, uint start, uint num);
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
index aa15f665f4..23360b0a00 100644
--- a/engines/mads/sprites.cpp
+++ b/engines/mads/sprites.cpp
@@ -149,6 +149,20 @@ SpriteSlot::SpriteSlot(SpriteType type, int seqIndex) {
_scale = 0;
}
+bool SpriteSlot::operator==(const SpriteSlotSubset &other) const {
+ return (_spritesIndex == other._spritesIndex) && (_frameNumber == other._frameNumber) &&
+ (_position == other._position) && (_depth == other._depth) &&
+ (_scale == other._scale);
+}
+
+void SpriteSlot::copy(const SpriteSlotSubset &other) {
+ _spritesIndex = other._spritesIndex;
+ _frameNumber = other._frameNumber;
+ _position = other._position;
+ _depth = other._depth;
+ _scale = other._scale;
+}
+
/*------------------------------------------------------------------------*/
SpriteSlots::SpriteSlots(MADSEngine *vm) : _vm(vm) {
diff --git a/engines/mads/sprites.h b/engines/mads/sprites.h
index f9ae46ad9b..49f13add21 100644
--- a/engines/mads/sprites.h
+++ b/engines/mads/sprites.h
@@ -139,6 +139,8 @@ public:
SpriteSlot(SpriteType type, int seqIndex);
void setup(int dirtyAreaIndex);
+ bool operator==(const SpriteSlotSubset &other) const;
+ void copy(const SpriteSlotSubset &other);
};
class SpriteSlots : public Common::Array<SpriteSlot> {