aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorPaul Gilbert2014-03-04 22:33:27 -0500
committerPaul Gilbert2014-03-04 22:33:27 -0500
commit568fc31b3090a70aa922479991540d4f5c2e918c (patch)
treef77e83b0b738479e369520513d8741ac05883ca2
parent1607a9104700e987cacfec41aaafd25d979aeb98 (diff)
downloadscummvm-rg350-568fc31b3090a70aa922479991540d4f5c2e918c.tar.gz
scummvm-rg350-568fc31b3090a70aa922479991540d4f5c2e918c.tar.bz2
scummvm-rg350-568fc31b3090a70aa922479991540d4f5c2e918c.zip
MADS: Beginnings of code support for Scene::drawElements
-rw-r--r--engines/mads/assets.cpp9
-rw-r--r--engines/mads/assets.h9
-rw-r--r--engines/mads/dialogs.cpp30
-rw-r--r--engines/mads/events.cpp2
-rw-r--r--engines/mads/events.h2
-rw-r--r--engines/mads/mads.cpp10
-rw-r--r--engines/mads/mads.h2
-rw-r--r--engines/mads/messages.cpp49
-rw-r--r--engines/mads/messages.h10
-rw-r--r--engines/mads/module.mk2
-rw-r--r--engines/mads/msprite.cpp107
-rw-r--r--engines/mads/msurface.cpp2
-rw-r--r--engines/mads/scene.cpp7
-rw-r--r--engines/mads/scene.h1
-rw-r--r--engines/mads/scene_data.cpp165
-rw-r--r--engines/mads/scene_data.h99
-rw-r--r--engines/mads/sprites.cpp239
-rw-r--r--engines/mads/sprites.h (renamed from engines/mads/msprite.h)89
18 files changed, 464 insertions, 370 deletions
diff --git a/engines/mads/assets.cpp b/engines/mads/assets.cpp
index c968afc311..ebedeb8141 100644
--- a/engines/mads/assets.cpp
+++ b/engines/mads/assets.cpp
@@ -163,6 +163,15 @@ void SpriteAsset::drawScaled(int frameNumber, MSurface &depthSurface, MSurface &
warning("TODO: SpriteAsset::drawScaled");
}
+void SpriteAsset::draw(MSurface *surface, int frameNumber, const Common::Point &pt) {
+ error("TODO: draw");
+}
+
+void SpriteAsset::depthDraw(MSurface *surface, MSurface *depthSurface, int frameNumber,
+ const Common::Point &pt, int depth) {
+ error("TODO: depthDraw");
+}
+
/*------------------------------------------------------------------------*/
SpriteSetCharInfo::SpriteSetCharInfo(Common::SeekableReadStream *s) {
diff --git a/engines/mads/assets.h b/engines/mads/assets.h
index 7a6939b222..30676a1d7e 100644
--- a/engines/mads/assets.h
+++ b/engines/mads/assets.h
@@ -25,14 +25,16 @@
#include "common/scummsys.h"
#include "common/array.h"
-#include "mads/msprite.h"
#include "mads/palette.h"
-#include "mads/msprite.h"
namespace MADS {
#define SPRITE_SET_CHAR_INFO 4
+class MADSEngine;
+class MSprite;
+class MSurface;
+
struct SpriteAssetFrame {
uint32 _stream;
Common::Rect _bounds;
@@ -100,6 +102,9 @@ public:
void drawScaled(int frameNumber, MSurface &depthSurface, MSurface &destSurface,
int scale, int depth, const Common::Point &pos);
+ void draw(MSurface *surface, int frameNumber, const Common::Point &pt);
+ void depthDraw(MSurface *surface, MSurface *depthSurface, int frameNumber,
+ const Common::Point &pt, int depth);
};
} // End of namespace MADS
diff --git a/engines/mads/dialogs.cpp b/engines/mads/dialogs.cpp
index e4c7682a38..d159d48ace 100644
--- a/engines/mads/dialogs.cpp
+++ b/engines/mads/dialogs.cpp
@@ -34,7 +34,7 @@ Dialog::Dialog(MADSEngine *vm): _vm(vm), _savedSurface(nullptr),
}
Dialog::~Dialog() {
- restore(_vm->_screen);
+ restore(&_vm->_screen);
}
@@ -55,21 +55,21 @@ void Dialog::restore(MSurface *s) {
void Dialog::draw() {
// Save the screen portion the dialog will overlap
- save(_vm->_screen);
+ save(&_vm->_screen);
// Draw the dialog
// Fill entire content of dialog
- _vm->_screen->fillRect(Common::Rect(_position.x, _position.y,
+ _vm->_screen.fillRect(Common::Rect(_position.x, _position.y,
_position.x + _width, _position.y + _height), TEXTDIALOG_BACKGROUND);
// Draw the outer edge lines
- _vm->_screen->hLine(_position.x + 1, _position.y + _height - 2,
+ _vm->_screen.hLine(_position.x + 1, _position.y + _height - 2,
_position.x + _width - 2, TEXTDIALOG_EDGE);
- _vm->_screen->hLine(_position.x, _position.y + _height - 1,
+ _vm->_screen.hLine(_position.x, _position.y + _height - 1,
_position.x + _width - 1, TEXTDIALOG_EDGE);
- _vm->_screen->vLine(_position.x + _width - 2, _position.y + 2,
+ _vm->_screen.vLine(_position.x + _width - 2, _position.y + 2,
_position.y + _height - 2, TEXTDIALOG_EDGE);
- _vm->_screen->vLine(_position.x + _width - 1, _position.y + 1,
+ _vm->_screen.vLine(_position.x + _width - 1, _position.y + 1,
_position.y + _height - 1, TEXTDIALOG_EDGE);
// Draw the gravelly dialog content
@@ -82,7 +82,7 @@ void Dialog::drawContent(const Common::Rect &r, int seed, byte color1, byte colo
uint16 currSeed = seed ? seed : 0xB78E;
for (int yp = 0; yp < r.height(); ++yp) {
- byte *destP = _vm->_screen->getBasePtr(r.left, r.top + yp);
+ byte *destP = _vm->_screen.getBasePtr(r.left, r.top + yp);
for (int xp = 0; xp < r.width(); ++xp) {
uint16 seedAdjust = currSeed;
@@ -246,10 +246,10 @@ void TextDialog::draw() {
if (_position.y == -1)
_position.y = 100 - (_height / 2);
- if ((_position.x + _width) > _vm->_screen->getWidth())
- _position.x = _vm->_screen->getWidth() - (_position.x + _width);
- if ((_position.y + _height) > _vm->_screen->getHeight())
- _position.y = _vm->_screen->getHeight() - (_position.y + _height);
+ if ((_position.x + _width) > _vm->_screen.getWidth())
+ _position.x = _vm->_screen.getWidth() - (_position.x + _width);
+ if ((_position.y + _height) > _vm->_screen.getHeight())
+ _position.y = _vm->_screen.getHeight() - (_position.y + _height);
// Draw the underlying dialog
Dialog::draw();
@@ -259,7 +259,7 @@ void TextDialog::draw() {
for (int lineNum = 0; lineNum < _numLines; ++lineNum) {
if (_lineXp[lineNum] == -1) {
// Draw a line across the entire dialog
- _vm->_screen->hLine(_position.x + 2,
+ _vm->_screen.hLine(_position.x + 2,
lineYp + (_vm->_font->getHeight() + 1) / 2,
_position.x + _width - 4, TEXTDIALOG_BLACK);
} else {
@@ -269,13 +269,13 @@ void TextDialog::draw() {
if (_lineXp[lineNum] & 0x40)
++yp;
- _vm->_font->writeString(_vm->_screen, _lines[lineNum],
+ _vm->_font->writeString(&_vm->_screen, _lines[lineNum],
Common::Point(xp, yp), 0, 1);
if (_lineXp[lineNum] & 0x80) {
// Draw an underline under the text
int lineWidth = _vm->_font->getWidth(_lines[lineNum], 1);
- _vm->_screen->hLine(xp, yp + _vm->_font->getHeight(), xp + lineWidth,
+ _vm->_screen.hLine(xp, yp + _vm->_font->getHeight(), xp + lineWidth,
TEXTDIALOG_BLACK);
}
}
diff --git a/engines/mads/events.cpp b/engines/mads/events.cpp
index 1acb081d8a..7fa31d7616 100644
--- a/engines/mads/events.cpp
+++ b/engines/mads/events.cpp
@@ -148,7 +148,7 @@ void EventsManager::checkForNextFrameCounter() {
_vm->_debugger->onFrame();
// Display the frame
- _vm->_screen->updateScreen();
+ _vm->_screen.updateScreen();
// Signal the ScummVM debugger
_vm->_debugger->onFrame();
diff --git a/engines/mads/events.h b/engines/mads/events.h
index add8fc34c0..f30e588bb4 100644
--- a/engines/mads/events.h
+++ b/engines/mads/events.h
@@ -24,8 +24,8 @@
#define MADS_EVENTS_H
#include "common/scummsys.h"
-#include "mads/msprite.h"
#include "mads/assets.h"
+#include "mads/sprites.h"
namespace MADS {
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index e9fbf918c4..fd2aebaecf 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -27,10 +27,10 @@
#include "engines/util.h"
#include "mads/mads.h"
#include "mads/graphics.h"
+#include "mads/msurface.h"
#include "mads/resources.h"
#include "mads/sound.h"
-#include "mads/msurface.h"
-#include "mads/msprite.h"
+#include "mads/sprites.h"
namespace MADS {
@@ -50,7 +50,6 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
_game = nullptr;
_palette = nullptr;
_resources = nullptr;
- _screen = nullptr;
_sound = nullptr;
_userInterface = nullptr;
}
@@ -63,7 +62,6 @@ MADSEngine::~MADSEngine() {
delete _game;
delete _palette;
delete _resources;
- delete _screen;
delete _sound;
delete _userInterface;
}
@@ -84,13 +82,13 @@ void MADSEngine::initialise() {
_events = new EventsManager(this);
_palette = new Palette(this);
_font = new Font(this);
- _screen = new MSurface(g_system->getWidth(), g_system->getHeight());
+ _screen.setSize(g_system->getWidth(), g_system->getHeight());
_sound = new SoundManager(this, _mixer);
_userInterface = UserInterface::init(this);
_game = Game::init(this);
_events->loadCursors("*CURSOR.SS");
- _screen->empty();
+ _screen.empty();
}
Common::Error MADSEngine::run() {
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index 2d85236d8d..0d5e16ac47 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -97,7 +97,7 @@ public:
Game *_game;
Palette *_palette;
Resources *_resources;
- MSurface *_screen;
+ MSurface _screen;
SoundManager *_sound;
UserInterface *_userInterface;
bool _easyMouse;
diff --git a/engines/mads/messages.cpp b/engines/mads/messages.cpp
index cc618c4b76..3b6663e71d 100644
--- a/engines/mads/messages.cpp
+++ b/engines/mads/messages.cpp
@@ -301,13 +301,13 @@ TextDisplayList::TextDisplayList(MADSEngine *vm) : _vm(vm) {
TextDisplay rec;
rec._active = false;
rec._expire = 0;
- _entries.push_back(rec);
+ push_back(rec);
}
}
void TextDisplayList::clear() {
for (int i = 0; i < TEXT_DISPLAY_SIZE; ++i)
- _entries[i]._active = false;
+ (*this)[i]._active = false;
}
int TextDisplayList::add(int xp, int yp, uint fontColor, int charSpacing,
@@ -315,20 +315,21 @@ int TextDisplayList::add(int xp, int yp, uint fontColor, int charSpacing,
int usedSlot = -1;
for (int idx = 0; idx < TEXT_DISPLAY_SIZE; ++idx) {
- if (!_entries[idx]._active) {
+ TextDisplay &td = (*this)[idx];
+ if (!td._active) {
usedSlot = idx;
- _entries[idx]._bounds.left = xp;
- _entries[idx]._bounds.top = yp;
- _entries[idx]._font = font;
- _entries[idx]._msg = msg;
- _entries[idx]._bounds.setWidth(font->getWidth(msg, charSpacing));
- _entries[idx]._bounds.setHeight(font->getHeight());
- _entries[idx]._color1 = fontColor & 0xff;
- _entries[idx]._color2 = fontColor >> 8;
- _entries[idx]._spacing = charSpacing;
- _entries[idx]._expire = 1;
- _entries[idx]._active = true;
+ td._bounds.left = xp;
+ td._bounds.top = yp;
+ td._font = font;
+ td._msg = msg;
+ td._bounds.setWidth(font->getWidth(msg, charSpacing));
+ td._bounds.setHeight(font->getHeight());
+ td._color1 = fontColor & 0xff;
+ td._color2 = fontColor >> 8;
+ td._spacing = charSpacing;
+ td._expire = 1;
+ td._active = true;
break;
}
}
@@ -340,11 +341,11 @@ void TextDisplayList::setDirtyAreas() {
Scene &scene = _vm->_game->_scene;
for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) {
- if ((_entries[idx]._expire >= 0) || !_entries[idx]._active)
+ if (((*this)[idx]._expire >= 0) || !(*this)[idx]._active)
scene._dirtyAreas[dirtyIdx]._active = false;
else {
scene._dirtyAreas[dirtyIdx]._textActive = true;
- scene._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]);
+ scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]);
}
}
}
@@ -353,9 +354,9 @@ void TextDisplayList::setDirtyAreas2() {
Scene &scene = _vm->_game->_scene;
for (uint idx = 0, dirtyIdx = DIRTY_AREAS_TEXT_DISPLAY_IDX; dirtyIdx < DIRTY_AREAS_SIZE; ++idx, ++dirtyIdx) {
- if (_entries[idx]._active && (_entries[idx]._expire >= 0)) {
- scene._dirtyAreas.setTextDisplay(dirtyIdx, _entries[idx]);
- scene._dirtyAreas[dirtyIdx]._textActive = (_entries[idx]._expire <= 0) ? 0 : 1;
+ if ((*this)[idx]._active && ((*this)[idx]._expire >= 0)) {
+ scene._dirtyAreas[dirtyIdx].setTextDisplay(&(*this)[idx]);
+ scene._dirtyAreas[dirtyIdx]._textActive = ((*this)[idx]._expire <= 0) ? 0 : 1;
}
}
}
@@ -375,16 +376,16 @@ void TextDisplayList::draw(MSurface *view) {
}
void TextDisplayList::cleanUp() {
- for (uint idx = 0; idx < _entries.size(); ++idx) {
- if (_entries[idx]._expire < 0) {
- _entries[idx]._active = false;
- _entries[idx]._expire = 0;
+ for (uint idx = 0; idx < size(); ++idx) {
+ if ((*this)[idx]._expire < 0) {
+ (*this)[idx]._active = false;
+ (*this)[idx]._expire = 0;
}
}
}
void TextDisplayList::expire(int idx) {
- _entries[idx]._expire = -1;
+ (*this)[idx]._expire = -1;
}
} // End of namespace MADS
diff --git a/engines/mads/messages.h b/engines/mads/messages.h
index 6967755cdd..1357b98d03 100644
--- a/engines/mads/messages.h
+++ b/engines/mads/messages.h
@@ -105,10 +105,9 @@ public:
#define TEXT_DISPLAY_SIZE 40
-class TextDisplayList {
+class TextDisplayList: public Common::Array<TextDisplay> {
private:
MADSEngine *_vm;
- Common::Array<TextDisplay> _entries;
/**
* Determine dirty areas for active text areas
@@ -118,13 +117,6 @@ public:
TextDisplayList(MADSEngine *vm);
/**
- * Item operator
- */
- TextDisplay &operator[](int idx) {
- return _entries[idx];
- }
-
- /**
* Expire a given text display entry
*/
void expire(int idx);
diff --git a/engines/mads/module.mk b/engines/mads/module.mk
index 36d0c49ff7..2bff5b782e 100644
--- a/engines/mads/module.mk
+++ b/engines/mads/module.mk
@@ -20,7 +20,6 @@ MODULE_OBJS := \
graphics.o \
mads.o \
messages.o \
- msprite.o \
msurface.o \
palette.o \
player.o \
@@ -29,6 +28,7 @@ MODULE_OBJS := \
scene_data.o \
sequence.o \
sound.o \
+ sprites.o \
user_interface.o
# This module can be built as a plugin
diff --git a/engines/mads/msprite.cpp b/engines/mads/msprite.cpp
deleted file mode 100644
index 279192fbdc..0000000000
--- a/engines/mads/msprite.cpp
+++ /dev/null
@@ -1,107 +0,0 @@
-/* ScummVM - Graphic Adventure Engine
- *
- * ScummVM is the legal property of its developers, whose names
- * are too numerous to list here. Please refer to the COPYRIGHT
- * file distributed with this source distribution.
- *
- * This program is free software; you can redistribute it and/or
- * modify it under the terms of the GNU General Public License
- * as published by the Free Software Foundation; either version 2
- * of the License, or (at your option) any later version.
-
- * This program is distributed in the hope that it will be useful,
- * but WITHOUT ANY WARRANTY; without even the implied warranty of
- * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
- * GNU General Public License for more details.
-
- * You should have received a copy of the GNU General Public License
- * along with this program; if not, write to the Free Software
- * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
- *
- */
-
-#include "common/scummsys.h"
-#include "engines/util.h"
-#include "graphics/palette.h"
-#include "mads/mads.h"
-#include "mads/msurface.h"
-#include "mads/msprite.h"
-
-namespace MADS {
-
-enum {
- kEndOfLine = 0,
- kEndOfSprite = 1,
- kMarker = 2
-};
-
-MSprite::MSprite(): MSurface() {
- _encoding = 0;
-}
-
-MSprite::MSprite(Common::SeekableReadStream *source, const Common::Point &offset,
- int widthVal, int heightVal, bool decodeRle, uint8 encodingVal)
- : MSurface(widthVal, heightVal),
- _encoding(encodingVal), _offset(offset) {
-
- // Load the sprite data
- loadSprite(source);
-}
-
-MSprite::~MSprite() {
-}
-
-
-// TODO: The sprite outlines (pixel value 0xFD) are not shown
-void MSprite::loadSprite(Common::SeekableReadStream *source) {
- byte *outp, *lineStart;
- bool newLine = false;
-
- outp = getData();
- lineStart = getData();
-
- while (1) {
- byte cmd1, cmd2, count, pixel;
-
- if (newLine) {
- outp = lineStart + getWidth();
- lineStart = outp;
- newLine = false;
- }
-
- cmd1 = source->readByte();
-
- if (cmd1 == 0xFC)
- break;
- else if (cmd1 == 0xFF)
- newLine = true;
- else if (cmd1 == 0xFD) {
- while (!newLine) {
- count = source->readByte();
- if (count == 0xFF) {
- newLine = true;
- } else {
- pixel = source->readByte();
- while (count--)
- *outp++ = (pixel == 0xFD) ? 0 : pixel;
- }
- }
- } else {
- while (!newLine) {
- cmd2 = source->readByte();
- if (cmd2 == 0xFF) {
- newLine = true;
- } else if (cmd2 == 0xFE) {
- count = source->readByte();
- pixel = source->readByte();
- while (count--)
- *outp++ = (pixel == 0xFD) ? 0 : pixel;
- } else {
- *outp++ = (cmd2 == 0xFD) ? 0 : cmd2;
- }
- }
- }
- }
-}
-
-} // End of namespace MADS
diff --git a/engines/mads/msurface.cpp b/engines/mads/msurface.cpp
index ca75a50bde..bb9b3089df 100644
--- a/engines/mads/msurface.cpp
+++ b/engines/mads/msurface.cpp
@@ -24,9 +24,9 @@
#include "mads/compression.h"
#include "mads/graphics.h"
#include "mads/mads.h"
-#include "mads/msprite.h"
#include "mads/msurface.h"
#include "mads/resources.h"
+#include "mads/sprites.h"
namespace MADS {
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index db252a95a4..994f58230e 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -424,7 +424,14 @@ void Scene::doFrame() {
}
void Scene::drawElements(bool transitionFlag, bool surfaceFlag) {
+ // Draw any background objects
+ _spriteSlots.drawBackground();
+ // Merge any identified dirty areas
+ _dirtyAreas.merge(1, _dirtyAreas.size());
+
+ // Copy dirty areas to the main display surface
+ _dirtyAreas.copy(&_vm->_screen, &_backgroundSurface, _posAdjust);
}
void Scene::leftClick() {
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
index 483ecae23c..c466f97c02 100644
--- a/engines/mads/scene.h
+++ b/engines/mads/scene.h
@@ -32,6 +32,7 @@
#include "mads/scene_data.h"
#include "mads/animation.h"
#include "mads/sequence.h"
+#include "mads/sprites.h"
namespace MADS {
diff --git a/engines/mads/scene_data.cpp b/engines/mads/scene_data.cpp
index 46ef2c3058..371fa43501 100644
--- a/engines/mads/scene_data.cpp
+++ b/engines/mads/scene_data.cpp
@@ -138,76 +138,7 @@ void ScreenObjects::proc1() {
/*------------------------------------------------------------------------*/
-SpriteSlot::SpriteSlot() {
- _spriteType = ST_NONE;
- _seqIndex = 0;
- _spritesIndex = 0;
- _frameNumber = 0;
- _depth = 0;
- _scale = 0;
-}
-
-SpriteSlot::SpriteSlot(SpriteType type, int seqIndex) {
- _spriteType = type;
- _seqIndex = seqIndex;
- _spritesIndex = 0;
- _frameNumber = 0;
- _depth = 0;
- _scale = 0;
-}
-
-/*------------------------------------------------------------------------*/
-
-void SpriteSlots::clear(bool flag) {
- _vm->_game->_scene._textDisplay.clear();
-
- if (flag)
- _vm->_game->_scene._sprites.clear();
-
- Common::Array<SpriteSlot>::clear();
- push_back(SpriteSlot(ST_FULL_SCREEN_REFRESH, -1));
-}
-
-/**
- * Releases any sprites used by the player
- */
-void SpriteSlots::releasePlayerSprites() {
- Player &player = _vm->_game->_player;
-
- if (player._spritesLoaded && player._numSprites > 0) {
- int spriteEnd = player._spritesStart + player._numSprites - 1;
- do {
- deleteEntry(spriteEnd);
- } while (--spriteEnd >= player._spritesStart);
- }
-}
-
-void SpriteSlots::deleteEntry(int index) {
- remove_at(index);
-}
-
-void SpriteSlots::fullRefresh(bool clearAll) {
- if (clearAll)
- Common::Array<SpriteSlot>::clear();
-
- push_back(SpriteSlot(ST_FULL_SCREEN_REFRESH, -1));
-}
-
-/*------------------------------------------------------------------------*/
-
-int SpriteSets::add(SpriteAsset *asset, int idx) {
- if (!idx)
- idx = size();
-
- if (idx >= (int)(size() + 1))
- resize(idx + 1);
- delete (*this)[idx];
- (*this)[idx] = asset;
-
- return idx;
-}
-
-/*------------------------------------------------------------------------*/
+MADSEngine *DirtyArea::_vm = nullptr;
void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
if (_bounds.left % 2) {
@@ -246,73 +177,75 @@ void DirtyArea::setArea(int width, int height, int maxWidth, int maxHeight) {
_active = true;
}
-/*------------------------------------------------------------------------*/
-
-DirtyAreas::DirtyAreas(MADSEngine *vm) : _vm(vm) {
- for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) {
- DirtyArea rec;
- rec._active = false;
- _entries.push_back(rec);
- }
-}
-void DirtyAreas::setSpriteSlot(int dirtyIdx, const SpriteSlot &spriteSlot) {
+void DirtyArea::setSpriteSlot(const SpriteSlot *spriteSlot) {
int width, height;
- DirtyArea &dirtyArea = _entries[dirtyIdx];
Scene &scene = _vm->_game->_scene;
- if (spriteSlot._spriteType == ST_FULL_SCREEN_REFRESH) {
+ if (spriteSlot->_spriteType == ST_FULL_SCREEN_REFRESH) {
// Special entry to refresh the entire screen
- dirtyArea._bounds.left = 0;
- dirtyArea._bounds.top = 0;
+ _bounds.left = 0;
+ _bounds.top = 0;
width = MADS_SCREEN_WIDTH;
height = MADS_SCENE_HEIGHT;
} else {
// Standard sprite slots
- dirtyArea._bounds.left = spriteSlot._position.x - scene._posAdjust.x;
- dirtyArea._bounds.top = spriteSlot._position.y - scene._posAdjust.y;
+ _bounds.left = spriteSlot->_position.x - scene._posAdjust.x;
+ _bounds.top = spriteSlot->_position.y - scene._posAdjust.y;
- SpriteAsset &spriteSet = scene._spriteSlots.getSprite(spriteSlot._spritesIndex);
- MSprite *frame = spriteSet.getFrame(((spriteSlot._frameNumber & 0x7fff) - 1) & 0x7f);
+ SpriteAsset &spriteSet = scene._spriteSlots.getSprite(spriteSlot->_spritesIndex);
+ MSprite *frame = spriteSet.getFrame(((spriteSlot->_frameNumber & 0x7fff) - 1) & 0x7f);
- if (spriteSlot._scale == -1) {
- width = frame->getWidth();
- height = frame->getHeight();
- } else {
- width = frame->getWidth() * spriteSlot._scale / 100;
- height = frame->getHeight() * spriteSlot._scale / 100;
+ if (spriteSlot->_scale == -1) {
+ width = frame->w;
+ height = frame->h;
+ }
+ else {
+ width = frame->w * spriteSlot->_scale / 100;
+ height = frame->h * spriteSlot->_scale / 100;
- dirtyArea._bounds.left -= width / 2;
- dirtyArea._bounds.top += -(height - 1);
+ _bounds.left -= width / 2;
+ _bounds.top += -(height - 1);
}
}
- dirtyArea.setArea(width, height, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
+ setArea(width, height, MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
}
-void DirtyAreas::setTextDisplay(int dirtyIdx, const TextDisplay &textDisplay) {
- DirtyArea &dirtyArea = _entries[dirtyIdx];
- dirtyArea._bounds.left = textDisplay._bounds.left;
- dirtyArea._bounds.top = textDisplay._bounds.top;
+void DirtyArea::setTextDisplay(const TextDisplay *textDisplay) {
+ _bounds.left = textDisplay->_bounds.left;
+ _bounds.top = textDisplay->_bounds.top;
- dirtyArea.setArea(textDisplay._bounds.width(), textDisplay._bounds.height(),
+ setArea(textDisplay->_bounds.width(), textDisplay->_bounds.height(),
MADS_SCREEN_WIDTH, MADS_SCENE_HEIGHT);
}
+/*------------------------------------------------------------------------*/
+
+DirtyAreas::DirtyAreas(MADSEngine *vm) : _vm(vm) {
+ DirtyArea::_vm = vm;
+
+ for (int i = 0; i < DIRTY_AREAS_SIZE; ++i) {
+ DirtyArea rec;
+ rec._active = false;
+ push_back(rec);
+ }
+}
+
void DirtyAreas::merge(int startIndex, int count) {
error("TODO: DirtyAreas::merge");
if (startIndex >= count)
return;
for (int outerCtr = startIndex - 1, idx = 0; idx < count; ++outerCtr, ++idx) {
- if (!_entries[outerCtr]._active)
+ if (!(*this)[outerCtr]._active)
continue;
for (int innerCtr = outerCtr + 1; innerCtr < count; ++innerCtr) {
- if (!_entries[innerCtr]._active || !intersects(outerCtr, innerCtr))
+ if (!(*this)[innerCtr]._active || !intersects(outerCtr, innerCtr))
continue;
- if (_entries[outerCtr]._textActive && _entries[innerCtr]._textActive)
+ if ((*this)[outerCtr]._textActive && (*this)[innerCtr]._textActive)
mergeAreas(outerCtr, innerCtr);
}
}
@@ -322,12 +255,12 @@ void DirtyAreas::merge(int startIndex, int count) {
* Returns true if two dirty areas intersect
*/
bool DirtyAreas::intersects(int idx1, int idx2) {
- return _entries[idx1]._bounds2.intersects(_entries[idx2]._bounds2);
+ return (*this)[idx1]._bounds2.intersects((*this)[idx2]._bounds2);
}
void DirtyAreas::mergeAreas(int idx1, int idx2) {
- DirtyArea &da1 = _entries[idx1];
- DirtyArea &da2 = _entries[idx2];
+ DirtyArea &da1 = (*this)[idx1];
+ DirtyArea &da2 = (*this)[idx2];
da1._bounds.extend(da2._bounds);
@@ -341,20 +274,22 @@ void DirtyAreas::mergeAreas(int idx1, int idx2) {
}
void DirtyAreas::copy(MSurface *dest, MSurface *src, const Common::Point &posAdjust) {
- for (uint i = 0; i < _entries.size(); ++i) {
- const Common::Rect &srcBounds = _entries[i]._bounds;
+ for (uint i = 0; i < size(); ++i) {
+ const Common::Rect &srcBounds = (*this)[i]._bounds;
Common::Rect bounds(srcBounds.left + posAdjust.x, srcBounds.top + posAdjust.y,
srcBounds.right + posAdjust.x, srcBounds.bottom + posAdjust.y);
- if (_entries[i]._active && _entries[i]._bounds.isValidRect())
- src->copyTo(dest, bounds, Common::Point(_entries[i]._bounds.left, _entries[i]._bounds.top));
+ if ((*this)[i]._active && (*this)[i]._bounds.isValidRect()) {
+ src->copyTo(dest, bounds, Common::Point((*this)[i]._bounds.left,
+ (*this)[i]._bounds.top));
+ }
}
}
-void DirtyAreas::clear() {
- for (uint i = 0; i < _entries.size(); ++i)
- _entries[i]._active = false;
+void DirtyAreas::reset() {
+ for (uint i = 0; i < size(); ++i)
+ (*this)[i]._active = false;
}
/*------------------------------------------------------------------------*/
diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h
index 522cd178d0..15371e405f 100644
--- a/engines/mads/scene_data.h
+++ b/engines/mads/scene_data.h
@@ -38,6 +38,7 @@ namespace MADS {
class MADSEngine;
class Scene;
+class SpriteSlot;
#define MADS_INTERFACE_HEIGHT 44
#define MADS_SCENE_HEIGHT 156
@@ -58,11 +59,6 @@ enum Layer {
LAYER_GUI = 19
};
-enum SpriteType {
- ST_NONE = 0, ST_FOREGROUND = 1, ST_BACKGROUND = -4,
- ST_FULL_SCREEN_REFRESH = -2, ST_EXPIRED = -1
-};
-
class VerbInit {
public:
int _id;
@@ -117,72 +113,6 @@ public:
void check(bool scanFlag);
};
-class SpriteSlotSubset {
-public:
- int _spritesIndex;
- int _frameNumber;
- Common::Point _position;
- int _depth;
- int _scale;
-};
-
-class SpriteSlot: public SpriteSlotSubset {
-public:
- SpriteType _spriteType;
- int _seqIndex;
-public:
- SpriteSlot();
- SpriteSlot(SpriteType type, int seqIndex);
-};
-
-class SpriteSlots: public Common::Array<SpriteSlot> {
-private:
- MADSEngine *_vm;
-public:
- SpriteSlots(MADSEngine *vm): _vm(vm) {}
-
- /**
- * Clears any pending slot data and schedules a full screen refresh.
- * @param flag Also reset sprite list
- */
- void clear(bool flag);
-
- /**
- * Delete any sprites used by the player
- */
- void releasePlayerSprites();
-
- /**
- * Delete a sprite entry
- * @param index Specifies the index in the array
- */
- void deleteEntry(int index);
-
- /**
- * Adds a full screen refresh to the sprite slots
- */
- void fullRefresh(bool clearAll = false);
-
- SpriteAsset &getSprite(int idx) {
- error("TODO");
- }
- void deleteTimer(int idx) {
- warning("TODO: SpriteSlots::deleteTimer");
- }
- int getIndex() {
- warning("TODO: SpriteSlots::indexOf");
- return -1;
- }
-};
-
-class SpriteSets: public Common::Array<SpriteAsset *> {
-public:
- /**
- * Add a sprite asset to the list
- */
- int add(SpriteAsset *asset, int idx = 0);
-};
-
class DynamicHotspot {
public:
bool _active;
@@ -235,6 +165,9 @@ public:
};
class DirtyArea {
+private:
+ static MADSEngine *_vm;
+ friend class DirtyAreas;
public:
Common::Rect _bounds;
Common::Rect _bounds2;
@@ -242,25 +175,23 @@ public:
bool _active;
DirtyArea() { _active = false; }
+
void setArea(int width, int height, int maxWidth, int maxHeight);
+
+ void setSpriteSlot(const SpriteSlot *spriteSlot);
+
+ /**
+ * Set up a dirty area for a text display
+ */
+ void setTextDisplay(const TextDisplay *textDisplay);
};
-class DirtyAreas {
+class DirtyAreas: public Common::Array<DirtyArea> {
private:
MADSEngine *_vm;
- Common::Array<DirtyArea> _entries;
public:
DirtyAreas(MADSEngine *vm);
-
- DirtyArea &operator[](uint idx) {
- assert(idx < _entries.size());
- return _entries[idx];
- }
-
- void setSpriteSlot(int dirtyIdx, const SpriteSlot &spriteSlot);
-
- void setTextDisplay(int dirtyIdx, const TextDisplay &textDisplay);
-
+
/**
* Merge together any designated dirty areas that overlap
* @param startIndex 1-based starting dirty area starting index
@@ -271,7 +202,7 @@ public:
bool intersects(int idx1, int idx2);
void mergeAreas(int idx1, int idx2);
void copy(MSurface *dest, MSurface *src, const Common::Point &posAdjust);
- void clear();
+ void reset();
};
class SceneLogic {
diff --git a/engines/mads/sprites.cpp b/engines/mads/sprites.cpp
new file mode 100644
index 0000000000..3cba6989b1
--- /dev/null
+++ b/engines/mads/sprites.cpp
@@ -0,0 +1,239 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "common/scummsys.h"
+#include "engines/util.h"
+#include "graphics/palette.h"
+#include "mads/mads.h"
+#include "mads/graphics.h"
+#include "mads/msurface.h"
+#include "mads/sprites.h"
+
+namespace MADS {
+
+enum {
+ kEndOfLine = 0,
+ kEndOfSprite = 1,
+ kMarker = 2
+};
+
+MSprite::MSprite(): MSurface() {
+ _encoding = 0;
+}
+
+MSprite::MSprite(Common::SeekableReadStream *source, const Common::Point &offset,
+ int widthVal, int heightVal, bool decodeRle, uint8 encodingVal)
+ : MSurface(widthVal, heightVal),
+ _encoding(encodingVal), _offset(offset) {
+
+ // Load the sprite data
+ loadSprite(source);
+}
+
+MSprite::~MSprite() {
+}
+
+
+// TODO: The sprite outlines (pixel value 0xFD) are not shown
+void MSprite::loadSprite(Common::SeekableReadStream *source) {
+ byte *outp, *lineStart;
+ bool newLine = false;
+
+ outp = getData();
+ lineStart = getData();
+
+ while (1) {
+ byte cmd1, cmd2, count, pixel;
+
+ if (newLine) {
+ outp = lineStart + getWidth();
+ lineStart = outp;
+ newLine = false;
+ }
+
+ cmd1 = source->readByte();
+
+ if (cmd1 == 0xFC)
+ break;
+ else if (cmd1 == 0xFF)
+ newLine = true;
+ else if (cmd1 == 0xFD) {
+ while (!newLine) {
+ count = source->readByte();
+ if (count == 0xFF) {
+ newLine = true;
+ } else {
+ pixel = source->readByte();
+ while (count--)
+ *outp++ = (pixel == 0xFD) ? 0 : pixel;
+ }
+ }
+ } else {
+ while (!newLine) {
+ cmd2 = source->readByte();
+ if (cmd2 == 0xFF) {
+ newLine = true;
+ } else if (cmd2 == 0xFE) {
+ count = source->readByte();
+ pixel = source->readByte();
+ while (count--)
+ *outp++ = (pixel == 0xFD) ? 0 : pixel;
+ } else {
+ *outp++ = (cmd2 == 0xFD) ? 0 : cmd2;
+ }
+ }
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+MADSEngine *SpriteSlot::_vm = nullptr;
+
+SpriteSlot::SpriteSlot() {
+ _spriteType = ST_NONE;
+ _seqIndex = 0;
+ _spritesIndex = 0;
+ _frameNumber = 0;
+ _depth = 0;
+ _scale = 0;
+}
+
+SpriteSlot::SpriteSlot(SpriteType type, int seqIndex) {
+ _spriteType = type;
+ _seqIndex = seqIndex;
+ _spritesIndex = 0;
+ _frameNumber = 0;
+ _depth = 0;
+ _scale = 0;
+}
+
+/*------------------------------------------------------------------------*/
+
+SpriteSlots::SpriteSlots(MADSEngine *vm) : _vm(vm) {
+ SpriteSlot::_vm = vm;
+}
+
+void SpriteSlots::clear(bool flag) {
+ _vm->_game->_scene._textDisplay.clear();
+
+ if (flag)
+ _vm->_game->_scene._sprites.clear();
+
+ Common::Array<SpriteSlot>::clear();
+ push_back(SpriteSlot(ST_FULL_SCREEN_REFRESH, -1));
+}
+
+/**
+* Releases any sprites used by the player
+*/
+void SpriteSlots::releasePlayerSprites() {
+ Player &player = _vm->_game->_player;
+
+ if (player._spritesLoaded && player._numSprites > 0) {
+ int spriteEnd = player._spritesStart + player._numSprites - 1;
+ do {
+ deleteEntry(spriteEnd);
+ } while (--spriteEnd >= player._spritesStart);
+ }
+}
+
+void SpriteSlots::deleteEntry(int index) {
+ remove_at(index);
+}
+
+void SpriteSlots::fullRefresh(bool clearAll) {
+ if (clearAll)
+ Common::Array<SpriteSlot>::clear();
+
+ push_back(SpriteSlot(ST_FULL_SCREEN_REFRESH, -1));
+}
+
+void SpriteSlots::drawBackground() {
+ Scene &scene = _vm->_game->_scene;
+
+ // Initial draw loop for any active sprites in the background
+ for (uint i = 0; i < scene._spriteSlots.size(); ++i) {
+ if (scene._spriteSlots[i]._spriteType >= ST_NONE) {
+ scene._dirtyAreas[i]._active = false;
+ }
+ else {
+ scene._dirtyAreas[i]._active = true;
+ scene._dirtyAreas[i].setSpriteSlot(&scene._spriteSlots[i]);
+
+ SpriteAsset *asset = scene._sprites[scene._spriteSlots[i]._spritesIndex];
+ MSprite *frame = asset->getFrame(scene._spriteSlots[i]._frameNumber);
+
+ if (scene._spriteSlots[i]._spriteType == ST_BACKGROUND) {
+ Common::Point pt = scene._spriteSlots[i]._position;
+ if (scene._spriteSlots[i]._scale != -1) {
+ // Adjust the drawing position
+ pt.x -= frame->w / 2;
+ pt.y -= frame->h / 2;
+ }
+
+ if (scene._spriteSlots[i]._depth <= 1) {
+ asset->draw(&scene._backgroundSurface, scene._spriteSlots[i]._frameNumber, pt);
+ }
+ else if (scene._depthStyle == 0) {
+ asset->depthDraw(&scene._backgroundSurface, &scene._depthSurface, scene._spriteSlots[i]._frameNumber,
+ pt, scene._spriteSlots[i]._depth);
+ } else {
+ error("Unsupported depth style");
+ }
+ }
+ }
+ }
+
+ // Mark any remaning dirty areas as inactive
+ for (uint i = scene._spriteSlots.size(); i < 50; ++i)
+ scene._dirtyAreas[i]._active = false;
+
+ // Flag any active text display
+ for (uint i = 50; i < scene._textDisplay.size(); ++i) {
+ TextDisplay &textDisplay = scene._textDisplay[i - 50];
+ if (scene._textDisplay[i]._expire >= 0 || !textDisplay._active) {
+ scene._dirtyAreas[i]._active = false;
+ } else {
+ scene._dirtyAreas[i]._active = true;
+ scene._dirtyAreas[i].setTextDisplay(&textDisplay);
+ }
+ }
+}
+
+/*------------------------------------------------------------------------*/
+
+int SpriteSets::add(SpriteAsset *asset, int idx) {
+ if (!idx)
+ idx = size();
+
+ if (idx >= (int)(size() + 1))
+ resize(idx + 1);
+ delete (*this)[idx];
+ (*this)[idx] = asset;
+
+ return idx;
+}
+
+/*------------------------------------------------------------------------*/
+
+} // End of namespace MADS
diff --git a/engines/mads/msprite.h b/engines/mads/sprites.h
index f2194dab08..6b131105dc 100644
--- a/engines/mads/msprite.h
+++ b/engines/mads/sprites.h
@@ -20,14 +20,21 @@
*
*/
-#ifndef MADS_MSPRITE_H
-#define MADS_MSPRITE_H
+#ifndef MADS_SPRITES_H
+#define MADS_SPRITES_H
#include "common/scummsys.h"
+#include "common/array.h"
+#include "mads/assets.h"
#include "mads/msurface.h"
namespace MADS {
+enum SpriteType {
+ ST_NONE = 0, ST_FOREGROUND = 1, ST_BACKGROUND = -4,
+ ST_FULL_SCREEN_REFRESH = -2, ST_EXPIRED = -1
+};
+
class MADSEngine;
struct BGR8 {
@@ -109,6 +116,82 @@ public:
uint8 _encoding;
};
+class SpriteSlotSubset {
+public:
+ int _spritesIndex;
+ int _frameNumber;
+ Common::Point _position;
+ int _depth;
+ int _scale;
+};
+
+class SpriteSlot : public SpriteSlotSubset {
+private:
+ static MADSEngine *_vm;
+ friend class SpriteSlots;
+public:
+ SpriteType _spriteType;
+ int _seqIndex;
+public:
+ SpriteSlot();
+ SpriteSlot(SpriteType type, int seqIndex);
+
+ void setup(int dirtyAreaIndex);
+};
+
+class SpriteSlots : public Common::Array<SpriteSlot> {
+private:
+ MADSEngine *_vm;
+public:
+ SpriteSlots(MADSEngine *vm);
+
+ /**
+ * Clears any pending slot data and schedules a full screen refresh.
+ * @param flag Also reset sprite list
+ */
+ void clear(bool flag);
+
+ /**
+ * Delete any sprites used by the player
+ */
+ void releasePlayerSprites();
+
+ /**
+ * Delete a sprite entry
+ * @param index Specifies the index in the array
+ */
+ void deleteEntry(int index);
+
+ /**
+ * Adds a full screen refresh to the sprite slots
+ */
+ void fullRefresh(bool clearAll = false);
+
+ SpriteAsset &getSprite(int idx) {
+ error("TODO");
+ }
+ void deleteTimer(int idx) {
+ warning("TODO: SpriteSlots::deleteTimer");
+ }
+ int getIndex() {
+ warning("TODO: SpriteSlots::indexOf");
+ return -1;
+ }
+
+ /**
+ * Draw any sprites into the background of the scene
+ */
+ void drawBackground();
+};
+
+class SpriteSets : public Common::Array<SpriteAsset *> {
+public:
+ /**
+ * Add a sprite asset to the list
+ */
+ int add(SpriteAsset *asset, int idx = 0);
+};
+
} // End of namespace MADS
-#endif /* MADS_MSPRITE_H */
+#endif /* MADS_SPRITES_H */