aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--engines/mads/animation.cpp72
-rw-r--r--engines/mads/animation.h32
-rw-r--r--engines/mads/game.cpp1
-rw-r--r--engines/mads/game.h1
-rw-r--r--engines/mads/mads.cpp1
-rw-r--r--engines/mads/mads.h1
-rw-r--r--engines/mads/palette.h13
-rw-r--r--engines/mads/scene.cpp22
-rw-r--r--engines/mads/scene.h2
-rw-r--r--engines/mads/scene_data.h5
-rw-r--r--engines/mads/screen.cpp6
-rw-r--r--engines/mads/user_interface.cpp76
-rw-r--r--engines/mads/user_interface.h14
13 files changed, 206 insertions, 40 deletions
diff --git a/engines/mads/animation.cpp b/engines/mads/animation.cpp
index b557a598ed..40abdbe26b 100644
--- a/engines/mads/animation.cpp
+++ b/engines/mads/animation.cpp
@@ -108,15 +108,24 @@ void AnimMessage::load(Common::SeekableReadStream *f) {
f->skip(2);
}
-void AnimFrameEntry::load(Common::SeekableReadStream *f) {
- _frameNumber = f->readUint16LE();
- _seqIndex = f->readByte();
- _spriteSlot._spritesIndex = f->readByte();
- _spriteSlot._frameNumber = f->readUint16LE();
- _spriteSlot._position.x = f->readSint16LE();
- _spriteSlot._position.y = f->readSint16LE();
- _spriteSlot._depth = f->readSByte();
- _spriteSlot._scale = (int8)f->readByte();
+void AnimFrameEntry::load(Common::SeekableReadStream *f, bool uiFlag) {
+ if (uiFlag) {
+ f->skip(2);
+ _seqIndex = f->readByte();
+ _spriteSlot._spritesIndex = f->readByte();
+ _spriteSlot._frameNumber = f->readUint16LE();
+ _spriteSlot._position.x = f->readSint16LE();
+ _spriteSlot._position.y = f->readSint16LE();
+ } else {
+ _frameNumber = f->readUint16LE();
+ _seqIndex = f->readByte();
+ _spriteSlot._spritesIndex = f->readByte();
+ _spriteSlot._frameNumber = f->readUint16LE();
+ _spriteSlot._position.x = f->readSint16LE();
+ _spriteSlot._position.y = f->readSint16LE();
+ _spriteSlot._depth = f->readSByte();
+ _spriteSlot._scale = (int8)f->readByte();
+ }
}
/*------------------------------------------------------------------------*/
@@ -132,6 +141,22 @@ void AnimMiscEntry::load(Common::SeekableReadStream *f) {
/*------------------------------------------------------------------------*/
+void AnimUIEntry::load(Common::SeekableReadStream *f) {
+ _probability = f->readUint16LE();
+ _imageCount = f->readUint16LE();
+ _firstImage = f->readUint16LE();
+ _lastImage = f->readUint16LE();
+ _counter = f->readSint16LE();
+ for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
+ _spawn[i] = f->readByte();
+ for (int i = 0; i < ANIM_SPAWN_COUNT; ++i)
+ _spawnFrame[i] = f->readUint16LE();
+ _sound = f->readUint16LE() & 0xFF;
+ _soundFrame = f->readUint16LE();
+}
+
+/*------------------------------------------------------------------------*/
+
Animation *Animation::init(MADSEngine *vm, Scene *scene) {
return new Animation(vm, scene);
}
@@ -149,7 +174,7 @@ Animation::~Animation() {
if (_header._manualFlag)
scene._sprites.remove(_spriteListIndexes[_header._spritesIndex]);
- for (uint idx = 0; idx < _header._spriteSetsCount; ++idx) {
+ for (int idx = 0; idx < _header._spriteSetsCount; ++idx) {
if (!_header._manualFlag || _header._spritesIndex != idx)
scene._sprites.remove(_spriteListIndexes[idx]);
}
@@ -195,12 +220,12 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
delete stream;
if (_header._animMode == 4)
- flags |= 0x4000;
+ flags |= PALFLAG_RESERVED;
- if (flags & 0x100) {
+ if (flags & ANIMFLAG_LOAD_BACKGROUND) {
loadInterface(interfaceSurface, depthSurface, _header, flags, palAnimData, sceneInfo);
}
- if (flags & 0x200) {
+ if (flags & ANIMFLAG_LOAD_BACKGROUND_ONLY) {
// No data
_header._messagesCount = 0;
_header._frameEntriesCount = 0;
@@ -234,7 +259,7 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
for (int i = 0; i < _header._frameEntriesCount; i++) {
AnimFrameEntry rec;
- rec.load(frameStream);
+ rec.load(frameStream, flags & ANIMFLAG_LOAD_BACKGROUND);
_frameEntries.push_back(rec);
}
@@ -242,14 +267,23 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
}
_miscEntries.clear();
+ _uiEntries.clear();
if (_header._miscEntriesCount > 0) {
// Chunk 4: Misc Data
Common::SeekableReadStream *miscStream = madsPack.getItemStream(streamIndex++);
- for (int i = 0; i < _header._miscEntriesCount; ++i) {
- AnimMiscEntry rec;
- rec.load(miscStream);
- _miscEntries.push_back(rec);
+ if (flags & ANIMFLAG_LOAD_BACKGROUND) {
+ for (int i = 0; i < _header._miscEntriesCount; ++i) {
+ AnimUIEntry rec;
+ rec.load(miscStream);
+ _uiEntries.push_back(rec);
+ }
+ } else {
+ for (int i = 0; i < _header._miscEntriesCount; ++i) {
+ AnimMiscEntry rec;
+ rec.load(miscStream);
+ _miscEntries.push_back(rec);
+ }
}
delete miscStream;
@@ -257,7 +291,7 @@ void Animation::load(UserInterface &interfaceSurface, MSurface &depthSurface,
// If the animation specifies a font, then load it for access
delete _font;
- if (_header._flags & ANIM_CUSTOM_FONT) {
+ if (_header._flags & ANIMFLAG_CUSTOM_FONT) {
Common::String fontName = "*" + _header._fontResource;
_font = _vm->_font->getFont(fontName.c_str());
} else {
diff --git a/engines/mads/animation.h b/engines/mads/animation.h
index 8095bec5e0..75f14a52b3 100644
--- a/engines/mads/animation.h
+++ b/engines/mads/animation.h
@@ -33,7 +33,12 @@
namespace MADS {
-enum AnimFlag { ANIM_CUSTOM_FONT = 0x20 };
+enum AnimFlag {
+ ANIMFLAG_DITHER = 0x0001, // Dither to 16 colors
+ ANIMFLAG_CUSTOM_FONT = 0x0020, // Load ccustom font
+ ANIMFLAG_LOAD_BACKGROUND = 0x0100, // Load background
+ ANIMFLAG_LOAD_BACKGROUND_ONLY = 0x0200 // Load background only
+};
class MADSEngine;
class Scene;
@@ -63,7 +68,7 @@ public:
/**
* Loads data for the record
*/
- void load(Common::SeekableReadStream *f);
+ void load(Common::SeekableReadStream *f, bool uiFlag);
};
class AnimMiscEntry {
@@ -80,6 +85,26 @@ public:
void load(Common::SeekableReadStream *f);
};
+#define ANIM_SPAWN_COUNT 2
+
+class AnimUIEntry {
+public:
+ int _probability;
+ int _imageCount;
+ int _firstImage;
+ int _lastImage;
+ int _counter;
+ int _spawn[ANIM_SPAWN_COUNT];
+ int _spawnFrame[ANIM_SPAWN_COUNT];
+ int _sound;
+ int _soundFrame;
+
+ /**
+ * Loads the data for the record
+ */
+ void load(Common::SeekableReadStream *f);
+};
+
class AAHeader {
public:
int _spriteSetsCount;
@@ -115,7 +140,6 @@ private:
Common::Array<int> _spriteListIndexes;
Common::Array<AnimMessage> _messages;
- Common::Array<AnimFrameEntry> _frameEntries;
Common::Array<AnimMiscEntry> _miscEntries;
Common::Array<SpriteAsset *> _spriteSets;
Font *_font;
@@ -153,6 +177,8 @@ private:
protected:
Animation(MADSEngine *vm, Scene *scene);
public:
+ Common::Array<AnimFrameEntry> _frameEntries;
+ Common::Array<AnimUIEntry> _uiEntries;
bool _resetFlag;
static Animation *init(MADSEngine *vm, Scene *scene);
diff --git a/engines/mads/game.cpp b/engines/mads/game.cpp
index 90ea105bd1..fd0294161d 100644
--- a/engines/mads/game.cpp
+++ b/engines/mads/game.cpp
@@ -52,7 +52,6 @@ Game::Game(MADSEngine *vm): _vm(vm), _surface(nullptr), _objects(vm),
_priorSectionNumber = 0;
_currentSectionNumber = -1;
_kernelMode = KERNEL_GAME_LOAD;
- _v2 = 0;
_quoteEmergency = false;
_vocabEmergency = false;
_aaName = "*I0.AA";
diff --git a/engines/mads/game.h b/engines/mads/game.h
index f41e7d248c..e4880091cc 100644
--- a/engines/mads/game.h
+++ b/engines/mads/game.h
@@ -131,7 +131,6 @@ public:
VisitedScenes _visitedScenes;
Scene _scene;
KernelMode _kernelMode;
- int _v2;
int _trigger;
ScreenTransition _fx;
TriggerMode _triggerMode;
diff --git a/engines/mads/mads.cpp b/engines/mads/mads.cpp
index 68d8579dc4..229d3fcef8 100644
--- a/engines/mads/mads.cpp
+++ b/engines/mads/mads.cpp
@@ -43,6 +43,7 @@ MADSEngine::MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc) :
_textWindowStill = false;
_screenFade = SCREEN_FADE_SMOOTH;
_musicFlag = false;
+ _dithering = false;
_debugger = nullptr;
_dialogs = nullptr;
diff --git a/engines/mads/mads.h b/engines/mads/mads.h
index cf8046f8f6..4ea0758f88 100644
--- a/engines/mads/mads.h
+++ b/engines/mads/mads.h
@@ -104,6 +104,7 @@ public:
bool _textWindowStill;
ScreenFade _screenFade;
bool _musicFlag;
+ bool _dithering;
public:
MADSEngine(OSystem *syst, const MADSGameDescription *gameDesc);
virtual ~MADSEngine();
diff --git a/engines/mads/palette.h b/engines/mads/palette.h
index dd5eaf6c2b..cceef09417 100644
--- a/engines/mads/palette.h
+++ b/engines/mads/palette.h
@@ -32,6 +32,19 @@ class MADSEngine;
#define PALETTE_USAGE_COUNT 4
+/**
+ * Palette mapping options
+ */
+enum {
+ PALFLAG_BACKGROUND = 0x8000, // Loading initial background
+ PALFLAG_RESERVED = 0x4000, // Enable mapping reserved colors
+ PALFLAG_ANY_TO_CLOSEST = 0x2000, // Any color can map to closest
+ PALFLAG_ALL_TO_CLOSEST = 0x1000, // Any colors that can map must map
+ PALFLAG_TOP_COLORS = 0x0800, // Allow mapping to high four colors
+ PALFLAG_DEFINE_RESERVED = 0x0400, // Define initial reserved color
+ PALFLAG_MASK = 0xfc00 // Mask for all the palette flags
+};
+
struct RGB4 {
byte r;
byte g;
diff --git a/engines/mads/scene.cpp b/engines/mads/scene.cpp
index b178de5839..ac57e0bcbf 100644
--- a/engines/mads/scene.cpp
+++ b/engines/mads/scene.cpp
@@ -123,8 +123,12 @@ void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
_kernelMessages.clear();
// TODO: palletteUsage reset? setPalette(_nullPalette);
+ int flags = SCENEFLAG_LOAD_SHADOW;
+ if (_vm->_dithering)
+ flags |= SCENEFLAG_DITHER;
+
_sceneInfo = SceneInfo::init(_vm);
- _sceneInfo->load(_currentSceneId, _variant, Common::String(), _vm->_game->_v2 ? 17 : 16,
+ _sceneInfo->load(_currentSceneId, _variant, Common::String(), flags,
_depthSurface, _backgroundSurface);
// Initialise palette animation for the scene
@@ -143,10 +147,12 @@ void Scene::loadScene(int sceneId, const Common::String &prefix, bool palFlag) {
_vm->_palette->_paletteUsage.load(1, 0xF);
// Load interface
- int flags = _vm->_game->_v2 ? 0x4101 : 0x4100;
- if (!_vm->_textWindowStill)
- flags |= 0x200;
-
+ flags = PALFLAG_RESERVED | ANIMFLAG_LOAD_BACKGROUND;
+ if (_vm->_dithering)
+ flags |= ANIMFLAG_DITHER;
+ if (_vm->_textWindowStill)
+ flags |= ANIMFLAG_LOAD_BACKGROUND_ONLY;
+
_animationData = Animation::init(_vm, this);
MSurface depthSurface;
_animationData->load(_userInterface, depthSurface, prefix, flags, nullptr, nullptr);
@@ -513,7 +519,7 @@ void Scene::loadAnimation(const Common::String &resName, int abortTimers) {
_activeAnimation = Animation::init(_vm, this);
_activeAnimation->load(interfaceSurface, depthSurface, resName,
- _vm->_game->_v2 ? 1 : 0, nullptr, nullptr);
+ _vm->_dithering ? ANIMFLAG_DITHER : 0, nullptr, nullptr);
_activeAnimation->startAnimation(abortTimers);
}
@@ -585,8 +591,4 @@ void Scene::resetScene() {
_sequences.clear();
}
-void Scene::backgroundAnimation() {
- warning("TODO: Scene::backgroundAnimation");
-}
-
} // End of namespace MADS
diff --git a/engines/mads/scene.h b/engines/mads/scene.h
index b0ecf111e6..f449ededfc 100644
--- a/engines/mads/scene.h
+++ b/engines/mads/scene.h
@@ -213,8 +213,6 @@ public:
void resetScene();
- void backgroundAnimation();
-
/**
* Removes all the scene specific sprites fromt the sprites list,
* leaving any player sprites list in place at the start of the list.
diff --git a/engines/mads/scene_data.h b/engines/mads/scene_data.h
index 2a6032a507..73ca21d092 100644
--- a/engines/mads/scene_data.h
+++ b/engines/mads/scene_data.h
@@ -52,6 +52,11 @@ class SpriteSlot;
#define TEXT_DISPLAY_MAX_SIZE 40
#define DIRTY_AREAS_SIZE (SPRITE_SLOTS_MAX_SIZE + TEXT_DISPLAY_MAX_SIZE)
+enum {
+ SCENEFLAG_DITHER = 0x01, // Dither to 16 colors
+ SCENEFLAG_LOAD_SHADOW = 0x10 // Load hard shadows
+};
+
class VerbInit {
public:
int _id;
diff --git a/engines/mads/screen.cpp b/engines/mads/screen.cpp
index 25623bc215..683a56705a 100644
--- a/engines/mads/screen.cpp
+++ b/engines/mads/screen.cpp
@@ -354,10 +354,10 @@ void ScreenObjects::check(bool scanFlag) {
slot._flags = IMG_ERASE;
}
- // Any background animation
- scene.backgroundAnimation();
+ // Any background animation in the user interface
+ userInterface.doBackgroundAnimation();
- // Handle animating the selected inventory animation
+ // Handle animating the selected inventory item
userInterface.inventoryAnim();
// Set the base time
diff --git a/engines/mads/user_interface.cpp b/engines/mads/user_interface.cpp
index c371f3d837..d7f198f3ce 100644
--- a/engines/mads/user_interface.cpp
+++ b/engines/mads/user_interface.cpp
@@ -48,7 +48,7 @@ void UISlots::add(const Common::Point &pt, int frameNumber, int spritesIndex) {
assert(size() < 50);
UISlot ie;
- ie._flags = -3;
+ ie._flags = IMG_OVERPRINT;
ie._segmentId = IMG_TEXT_UPDATE;
ie._position = pt;
ie._frameNumber = frameNumber;
@@ -57,6 +57,20 @@ void UISlots::add(const Common::Point &pt, int frameNumber, int spritesIndex) {
push_back(ie);
}
+void UISlots::add(const AnimFrameEntry &frameEntry) {
+ assert(size() < 50);
+
+ UISlot ie;
+ ie._flags = IMG_UPDATE;
+ ie._segmentId = frameEntry._seqIndex;
+ ie._spritesIndex = frameEntry._spriteSlot._spritesIndex;
+ ie._frameNumber = frameEntry._frameNumber;
+ ie._position = frameEntry._spriteSlot._position;
+
+ push_back(ie);
+}
+
+
void UISlots::draw(bool updateFlag, bool delFlag) {
Scene &scene = _vm->_game->_scene;
UserInterface &userInterface = scene._userInterface;
@@ -633,6 +647,66 @@ void UserInterface::inventoryAnim() {
_uiSlots.push_back(slot);
}
+void UserInterface::doBackgroundAnimation() {
+ Scene &scene = _vm->_game->_scene;
+ Common::Array<AnimUIEntry> &uiEntries = scene._animationData->_uiEntries;
+ Common::Array<AnimFrameEntry> &frameEntries = scene._animationData->_frameEntries;
+
+ _noSegmentsActive = !_someSegmentsActive;
+ _someSegmentsActive = false;
+
+ for (int idx = 0; idx < uiEntries.size(); ++idx) {
+ AnimUIEntry &uiEntry = uiEntries[idx];
+
+ if (uiEntry._counter < 0) {
+ if (uiEntry._counter == -1) {
+ int probabilityRandom = _vm->getRandomNumber(1, 30000);
+ int probability = uiEntry._probability;
+ if (uiEntry._probability > 30000) {
+ if (_noSegmentsActive) {
+ probability -= 30000;
+ } else {
+ probability = -1;
+ }
+ }
+ if (probabilityRandom <= probability) {
+ uiEntry._counter = uiEntry._firstImage;
+ _someSegmentsActive = true;
+ }
+ } else {
+ uiEntry._counter = uiEntry._firstImage;
+ _someSegmentsActive = true;
+ }
+ } else {
+ for (int idx2 = 0; idx2 < ANIM_SPAWN_COUNT; idx2++) {
+ if (uiEntry._spawnFrame[idx2] == (uiEntry._counter - uiEntry._firstImage)) {
+ int tempIndex = uiEntry._spawn[idx2];
+ if (idx >= tempIndex) {
+ uiEntries[tempIndex]._counter = uiEntries[tempIndex]._firstImage;
+ } else {
+ uiEntries[tempIndex]._counter = -2;
+ }
+ _someSegmentsActive = true;
+ }
+ }
+
+ ++uiEntry._counter;
+ if (uiEntry._counter > uiEntry._lastImage) {
+ uiEntry._counter = -1;
+ } else {
+ _someSegmentsActive = true;
+ }
+ }
+ }
+
+ for (int idx = 0; idx < uiEntries.size(); ++idx) {
+ int imgScan = uiEntries[idx]._counter;
+ if (imgScan >= 0) {
+ _uiSlots.add(frameEntries[imgScan]);
+ }
+ }
+}
+
void UserInterface::categoryChanged() {
_highlightedItemIndex = -1;
_vm->_events->initVars();
diff --git a/engines/mads/user_interface.h b/engines/mads/user_interface.h
index 445cd1e487..86b5622a03 100644
--- a/engines/mads/user_interface.h
+++ b/engines/mads/user_interface.h
@@ -33,6 +33,8 @@ namespace MADS {
enum { IMG_SPINNING_OBJECT = 200, IMG_TEXT_UPDATE = 201 };
+class AnimFrameEntry;
+
class UISlot {
public:
int _flags;
@@ -62,6 +64,11 @@ public:
void add(const Common::Point &pt, int frameNumber, int spritesIndex);
/**
+ * Loads the data from an aimation frame entry
+ */
+ void add(const AnimFrameEntry &frameEntry);
+
+ /**
* Adds a special entry for full refresh of the user interface
*/
void fullRefresh();
@@ -83,6 +90,8 @@ private:
int _invFrameNumber;
uint32 _scrollMilli;
bool _scrollFlag;
+ int _noSegmentsActive;
+ int _someSegmentsActive;
/**
* Loads the elements of the user interface
@@ -183,6 +192,11 @@ public:
void noInventoryAnim();
/**
+ * Handles any animation that occurs in the background of the user interface
+ */
+ void doBackgroundAnimation();
+
+ /**
* Handles queuing a new frame of an inventory animation for drawing
*/
void inventoryAnim();