aboutsummaryrefslogtreecommitdiff
path: root/engines
diff options
context:
space:
mode:
authorĽubomír Remák2018-11-02 23:26:58 +0100
committerĽubomír Remák2018-11-02 23:26:58 +0100
commit0c340485e01e0c18634a496d145841afb2ac2536 (patch)
treeb657f2f0ea37709fb317aca02a64e345dbbb4ff2 /engines
parentfc0f83ef9bb992482ab5d43fcc6eeac42ec8424b (diff)
downloadscummvm-rg350-0c340485e01e0c18634a496d145841afb2ac2536.tar.gz
scummvm-rg350-0c340485e01e0c18634a496d145841afb2ac2536.tar.bz2
scummvm-rg350-0c340485e01e0c18634a496d145841afb2ac2536.zip
MUTATIONOFJB: Draw bitmaps.
Implement RB (bitmap visibility) command. Implement stub for FLX and FLB (play animation) commands.
Diffstat (limited to 'engines')
-rw-r--r--engines/mutationofjb/animationdecoder.cpp113
-rw-r--r--engines/mutationofjb/animationdecoder.h18
-rw-r--r--engines/mutationofjb/commands/bitmapvisibilitycommand.cpp58
-rw-r--r--engines/mutationofjb/commands/bitmapvisibilitycommand.h53
-rw-r--r--engines/mutationofjb/commands/camefromcommand.cpp1
-rw-r--r--engines/mutationofjb/commands/playanimationcommand.cpp61
-rw-r--r--engines/mutationofjb/commands/playanimationcommand.h52
-rw-r--r--engines/mutationofjb/debug.cpp29
-rw-r--r--engines/mutationofjb/debug.h1
-rw-r--r--engines/mutationofjb/gamedata.cpp13
-rw-r--r--engines/mutationofjb/gamedata.h2
-rw-r--r--engines/mutationofjb/module.mk2
-rw-r--r--engines/mutationofjb/room.cpp42
-rw-r--r--engines/mutationofjb/room.h2
-rw-r--r--engines/mutationofjb/script.cpp4
15 files changed, 417 insertions, 34 deletions
diff --git a/engines/mutationofjb/animationdecoder.cpp b/engines/mutationofjb/animationdecoder.cpp
index 43590a92c3..84325a95ef 100644
--- a/engines/mutationofjb/animationdecoder.cpp
+++ b/engines/mutationofjb/animationdecoder.cpp
@@ -27,10 +27,13 @@
namespace MutationOfJB {
-AnimationDecoder::AnimationDecoder(const Common::String &fileName) : _fileName(fileName) {
+AnimationDecoder::AnimationDecoder(const Common::String &fileName) : _fileName(fileName), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {
_surface.create(IMAGE_WIDTH, IMAGE_HEIGHT, Graphics::PixelFormat::createFormatCLUT8());
+ _owningSurface = true;
}
+AnimationDecoder::AnimationDecoder(const Common::String &fileName, const Graphics::Surface &outSurface) : _fileName(fileName), _surface(outSurface), _owningSurface(false), _fromFrame(-1), _toFrame(-1), _threshold(0xFF) {}
+
bool AnimationDecoder::decode(AnimationDecoderCallback *callback) {
EncryptedFile file;
file.open(_fileName);
@@ -60,39 +63,43 @@ bool AnimationDecoder::decode(AnimationDecoderCallback *callback) {
// Subrecords.
if (recordId == 0xF1FA) {
- if (subrecords == 0) {
- if (callback) {
- callback->onFrame(frameNo, _surface); // Empty record, frame identical to the previous one.
- }
+ if ((_fromFrame != -1 && frameNo < _fromFrame) || (_toFrame != -1 && frameNo > _toFrame)) {
+ file.seek(length - 16, SEEK_CUR);
} else {
- for (int i = 0; i < subrecords; ++i) {
- int32 filePos = file.pos();
-
- const uint32 subLength = file.readUint32LE();
- const uint16 type = file.readUint16LE();
-
- if (type == 0x0B) {
- loadPalette(file);
- if (callback) {
- callback->onPaletteUpdated(_palette);
- }
- } else if (type == 0x0F) {
- loadFullFrame(file, subLength - 6);
- if (callback) {
- callback->onFrame(frameNo, _surface);
- }
- } else if (type == 0x0C) {
- loadDiffFrame(file, subLength - 6);
- if (callback) {
- callback->onFrame(frameNo, _surface);
- }
- } else {
- debug("Unsupported record type %02X.", type);
- file.seek(subLength - 6, SEEK_CUR);
+ if (subrecords == 0) {
+ if (callback) {
+ callback->onFrame(frameNo, _surface); // Empty record, frame identical to the previous one.
}
+ } else {
+ for (int i = 0; i < subrecords; ++i) {
+ int32 filePos = file.pos();
+
+ const uint32 subLength = file.readUint32LE();
+ const uint16 type = file.readUint16LE();
+
+ if (type == 0x0B) {
+ loadPalette(file);
+ if (callback) {
+ callback->onPaletteUpdated(_palette);
+ }
+ } else if (type == 0x0F) {
+ loadFullFrame(file, subLength - 6);
+ if (callback) {
+ callback->onFrame(frameNo, _surface);
+ }
+ } else if (type == 0x0C) {
+ loadDiffFrame(file, subLength - 6);
+ if (callback) {
+ callback->onFrame(frameNo, _surface);
+ }
+ } else {
+ debug("Unsupported record type %02X.", type);
+ file.seek(subLength - 6, SEEK_CUR);
+ }
- // Makes decoding more robust, because for some reason records might have extra data at the end.
- file.seek(filePos + subLength, SEEK_SET);
+ // Makes decoding more robust, because for some reason records might have extra data at the end.
+ file.seek(filePos + subLength, SEEK_SET);
+ }
}
}
frameNo++;
@@ -105,6 +112,13 @@ bool AnimationDecoder::decode(AnimationDecoderCallback *callback) {
return true;
}
+void AnimationDecoder::setPartialMode(int fromFrame, int toFrame, const Common::Rect area, uint8 threshold) {
+ _fromFrame = fromFrame;
+ _toFrame = toFrame;
+ _area = area;
+ _threshold = threshold;
+}
+
void AnimationDecoder::loadPalette(Common::SeekableReadStream &file) {
uint16 packets = file.readUint16LE();
const uint8 skipCount = file.readByte();
@@ -165,6 +179,11 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) {
for (uint16 line = firstLine; line < firstLine + numLines; ++line) {
uint8 *imageData = reinterpret_cast<uint8 *>(_surface.getBasePtr(0, line));
+ uint16 lineOffset = 0;
+
+ // Optimization for skipping the whole line if outside of confined area.
+ const bool skipLineOutput = !_area.isEmpty() && (line < _area.top || line >= _area.bottom);
+ uint8 buf[0x80];
uint8 runs = file.readByte();
while (runs--) {
@@ -172,17 +191,42 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) {
uint8 num = file.readByte();
imageData += localOffset;
+ lineOffset += localOffset;
if (num == 0) {
// Ignore?
debug("Zero RLE number found.");
} else if (num < 0x80) {
- file.read(imageData, num);
+ if (!skipLineOutput) {
+ if (_area.isEmpty() && _threshold == 0xFF) {
+ file.read(imageData, num);
+ } else {
+ file.read(buf, num);
+ for (uint16 i = 0; i < num; i++) {
+ if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold)
+ imageData[i] = buf[i];
+ }
+ }
+ } else {
+ file.skip(num);
+ }
+
imageData += num;
+ lineOffset += num;
} else {
const uint8 color = file.readByte();
const int no = 0x100 - num;
- memset(imageData, color, no);
+ if (!skipLineOutput) {
+ if (_area.isEmpty() && _threshold == 0xFF) {
+ memset(imageData, color, no);
+ } else {
+ for (int i = 0; i < no; i++) {
+ if ((_area.isEmpty() || _area.contains(lineOffset + i, line)) && imageData[i] <= _threshold)
+ imageData[i] = color;
+ }
+ }
+ }
imageData += no;
+ lineOffset += no;
}
}
@@ -190,7 +234,8 @@ void AnimationDecoder::loadDiffFrame(EncryptedFile &file, uint32) {
}
AnimationDecoder::~AnimationDecoder() {
- _surface.free();
+ if (_owningSurface)
+ _surface.free();
}
}
diff --git a/engines/mutationofjb/animationdecoder.h b/engines/mutationofjb/animationdecoder.h
index 050aa3b9dd..f213440d9d 100644
--- a/engines/mutationofjb/animationdecoder.h
+++ b/engines/mutationofjb/animationdecoder.h
@@ -23,8 +23,10 @@
#ifndef MUTATIONOFJB_ANIMATIONDECODER_H
#define MUTATIONOFJB_ANIMATIONDECODER_H
+#include "common/rect.h"
#include "common/scummsys.h"
#include "common/str.h"
+
#include "graphics/surface.h"
#include "mutationofjb/encryptedfile.h"
@@ -51,9 +53,20 @@ public:
class AnimationDecoder {
public:
AnimationDecoder(const Common::String &fileName);
+ AnimationDecoder(const Common::String &fileName, const Graphics::Surface &outSurface);
~AnimationDecoder();
bool decode(AnimationDecoderCallback *callback);
+ /**
+ * Enables partial decoding mode.
+ *
+ * @param fromFrame Frame to start decoding on (inclusive).
+ * @param toFrame Frame to end decoding on (inclusive).
+ * @param area Output surface will be confined to this area.
+ * @param threshold Source pixels with color index above this threshold will not be replaced.
+ */
+ void setPartialMode(int fromFrame, int toFrame, const Common::Rect area = Common::Rect(), uint8 threshold = 0xFF);
+
private:
void loadPalette(Common::SeekableReadStream &stream);
void loadFullFrame(EncryptedFile &file, uint32 size);
@@ -61,7 +74,12 @@ private:
Common::String _fileName;
Graphics::Surface _surface;
+ bool _owningSurface;
byte _palette[PALETTE_SIZE];
+ int _fromFrame;
+ int _toFrame;
+ Common::Rect _area;
+ uint8 _threshold;
};
}
diff --git a/engines/mutationofjb/commands/bitmapvisibilitycommand.cpp b/engines/mutationofjb/commands/bitmapvisibilitycommand.cpp
new file mode 100644
index 0000000000..f1238907a7
--- /dev/null
+++ b/engines/mutationofjb/commands/bitmapvisibilitycommand.cpp
@@ -0,0 +1,58 @@
+/* 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 "mutationofjb/commands/bitmapvisibilitycommand.h"
+#include "mutationofjb/gamedata.h"
+#include "mutationofjb/script.h"
+
+/** @file
+ * "RB " <sceneId> " " <bitmapId> " " <visible>
+ *
+ * Changes visibility of a bitmap in the specified scene.
+ */
+
+namespace MutationOfJB {
+
+bool BitmapVisibilityCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
+ if (line.size() < 10 || !line.hasPrefix("RB "))
+ return false;
+
+ const uint8 sceneId = (uint8) atoi(line.c_str() + 3);
+ const uint8 bitmapId = (uint8) atoi(line.c_str() + 6);
+ const bool visible = (line[9] == '1');
+
+ command = new BitmapVisibilityCommand(sceneId, bitmapId, visible);
+ return true;
+}
+
+
+Command::ExecuteResult BitmapVisibilityCommand::execute(ScriptExecutionContext &scriptExecCtx) {
+ scriptExecCtx.getGameData().getScene(_sceneId)->getBitmap(_bitmapId)->_isVisible = _visible;
+
+ return Finished;
+}
+
+Common::String BitmapVisibilityCommand::debugString() const {
+ return Common::String::format("SETBITMAPVIS %u %u %s", (unsigned int) _sceneId, (unsigned int) _bitmapId, _visible ? "true" : "false");
+}
+
+}
diff --git a/engines/mutationofjb/commands/bitmapvisibilitycommand.h b/engines/mutationofjb/commands/bitmapvisibilitycommand.h
new file mode 100644
index 0000000000..366abd3148
--- /dev/null
+++ b/engines/mutationofjb/commands/bitmapvisibilitycommand.h
@@ -0,0 +1,53 @@
+/* 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.
+ *
+ */
+
+#ifndef MUTATIONOFJB_BITMAPVISIBILITYCOMMAND_H
+#define MUTATIONOFJB_BITMAPVISIBILITYCOMMAND_H
+
+#include "mutationofjb/commands/seqcommand.h"
+#include "common/str.h"
+
+namespace MutationOfJB {
+
+class BitmapVisibilityCommandParser : public SeqCommandParser {
+public:
+ BitmapVisibilityCommandParser() {}
+
+ virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command);
+};
+
+class BitmapVisibilityCommand : public SeqCommand {
+public:
+ BitmapVisibilityCommand(uint8 sceneId, uint8 bitmapId, bool visible) : _sceneId(sceneId), _bitmapId(bitmapId), _visible(visible) {}
+ const Common::String &getName() const;
+
+ virtual ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
+ virtual Common::String debugString() const override;
+private:
+ uint8 _sceneId;
+ uint8 _bitmapId;
+ bool _visible;
+};
+
+}
+
+#endif
diff --git a/engines/mutationofjb/commands/camefromcommand.cpp b/engines/mutationofjb/commands/camefromcommand.cpp
index 67033b8a53..b4bbcc75cb 100644
--- a/engines/mutationofjb/commands/camefromcommand.cpp
+++ b/engines/mutationofjb/commands/camefromcommand.cpp
@@ -41,6 +41,7 @@ bool CameFromCommandParser::parse(const Common::String &line, ScriptParseContext
}
const uint8 sceneId = atoi(line.c_str() + 9);
+ _tags.push(0);
command = new CameFromCommand(sceneId);
return true;
}
diff --git a/engines/mutationofjb/commands/playanimationcommand.cpp b/engines/mutationofjb/commands/playanimationcommand.cpp
new file mode 100644
index 0000000000..60c6f1c3cf
--- /dev/null
+++ b/engines/mutationofjb/commands/playanimationcommand.cpp
@@ -0,0 +1,61 @@
+/* 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 "mutationofjb/commands/playanimationcommand.h"
+#include "mutationofjb/game.h"
+#include "mutationofjb/room.h"
+#include "mutationofjb/script.h"
+
+/** @file
+ * ( "FLB " | "FLX" ) <fromFrame> " " <toFrame>
+ *
+ * Plays the specified frames from room animation.
+ *
+ * TODO: Parse all arguments of this command.
+ * TODO: Actually play the animation instead of just showing last frame.
+ */
+
+namespace MutationOfJB {
+
+bool PlayAnimationCommandParser::parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command) {
+ if (line.size() < 11 || (!line.hasPrefix("FLB ") && !line.hasPrefix("FLX ")))
+ return false;
+
+ const uint8 fromFrame = (uint8) atoi(line.c_str() + 4);
+ const uint8 toFrame = (uint8) atoi(line.c_str() + 8);
+
+ command = new PlayAnimationCommand(fromFrame, toFrame);
+ return true;
+}
+
+
+Command::ExecuteResult PlayAnimationCommand::execute(ScriptExecutionContext &scriptExecCtx) {
+ scriptExecCtx.getGame().getRoom().drawFrames(_fromFrame - 1, _toFrame - 1);
+
+ return Finished;
+}
+
+Common::String PlayAnimationCommand::debugString() const {
+ return Common::String::format("PLAYROOMANIM %u %u", (unsigned int) _fromFrame, (unsigned int) _toFrame);
+}
+
+}
diff --git a/engines/mutationofjb/commands/playanimationcommand.h b/engines/mutationofjb/commands/playanimationcommand.h
new file mode 100644
index 0000000000..da7ff25324
--- /dev/null
+++ b/engines/mutationofjb/commands/playanimationcommand.h
@@ -0,0 +1,52 @@
+/* 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.
+ *
+ */
+
+#ifndef MUTATIONOFJB_PLAYANIMATIONCOMMAND_H
+#define MUTATIONOFJB_PLAYANIMATIONCOMMAND_H
+
+#include "mutationofjb/commands/seqcommand.h"
+#include "common/str.h"
+
+namespace MutationOfJB {
+
+class PlayAnimationCommandParser : public SeqCommandParser {
+public:
+ PlayAnimationCommandParser() {}
+
+ virtual bool parse(const Common::String &line, ScriptParseContext &parseCtx, Command *&command);
+};
+
+class PlayAnimationCommand : public SeqCommand {
+public:
+ PlayAnimationCommand(uint8 fromFrame, uint8 toFrame) : _fromFrame(fromFrame), _toFrame(toFrame) {}
+ const Common::String &getName() const;
+
+ virtual ExecuteResult execute(ScriptExecutionContext &scriptExecCtx) override;
+ virtual Common::String debugString() const override;
+private:
+ uint8 _fromFrame;
+ uint8 _toFrame;
+};
+
+}
+
+#endif
diff --git a/engines/mutationofjb/debug.cpp b/engines/mutationofjb/debug.cpp
index 7068b6643f..112b810048 100644
--- a/engines/mutationofjb/debug.cpp
+++ b/engines/mutationofjb/debug.cpp
@@ -69,6 +69,7 @@ Console::Console(MutationOfJBEngine *vm) : _vm(vm) {
registerCmd("dumpdoorinfo", WRAP_METHOD(Console, cmd_dumpdoorinfo));
registerCmd("dumpobjectinfo", WRAP_METHOD(Console, cmd_dumpobjectinfo));
registerCmd("dumpstaticinfo", WRAP_METHOD(Console, cmd_dumpstaticinfo));
+ registerCmd("dumpbitmapinfo", WRAP_METHOD(Console, cmd_dumpbitmapinfo));
registerCmd("listinventory", WRAP_METHOD(Console, cmd_listinventory));
}
@@ -437,6 +438,34 @@ bool Console::cmd_dumpstaticinfo(int argc, const char **argv) {
return true;
}
+bool Console::cmd_dumpbitmapinfo(int argc, const char **argv) {
+ if (argc == 3) {
+ const uint8 sceneId = atoi(argv[1]);
+ const uint8 bitmapId = atoi(argv[2]);
+
+ Scene *const scene = _vm->getGame().getGameData().getScene(sceneId);
+ if (scene) {
+ Bitmap *const bitmap = scene->getBitmap(bitmapId);
+ if (bitmap) {
+ debugPrintf("Room Frame: %u\n", (unsigned int) bitmap->_roomFrame);
+ debugPrintf("Visible: %u\n", (unsigned int) bitmap->_isVisible);
+ debugPrintf("X1: %u\n", (unsigned int) bitmap->_x1);
+ debugPrintf("Y1: %u\n", (unsigned int) bitmap->_y1);
+ debugPrintf("X2: %u\n", (unsigned int) bitmap->_x2);
+ debugPrintf("Y2: %u\n", (unsigned int) bitmap->_y2);
+ } else {
+ debugPrintf("Bitmap %u not found.\n", (unsigned int) bitmapId);
+ }
+ } else {
+ debugPrintf("Scene %u not found.\n", (unsigned int) sceneId);
+ }
+ } else {
+ debugPrintf("dumpbitmapinfo <sceneid> <bitmapid>\n");
+ }
+
+ return true;
+}
+
Script *Console::getScriptFromArg(const char *arg) {
Script *script = nullptr;
if (strcmp(arg, "G") == 0) {
diff --git a/engines/mutationofjb/debug.h b/engines/mutationofjb/debug.h
index b5c40c032f..679cafc8ec 100644
--- a/engines/mutationofjb/debug.h
+++ b/engines/mutationofjb/debug.h
@@ -48,6 +48,7 @@ private:
bool cmd_dumpdoorinfo(int argc, const char **argv);
bool cmd_dumpobjectinfo(int argc, const char **argv);
bool cmd_dumpstaticinfo(int argc, const char **argv);
+ bool cmd_dumpbitmapinfo(int argc, const char **argv);
bool cmd_listinventory(int argc, const char **argv);
void showIndent(int indentLevel);
diff --git a/engines/mutationofjb/gamedata.cpp b/engines/mutationofjb/gamedata.cpp
index 4905bbb3e2..33f9ba2411 100644
--- a/engines/mutationofjb/gamedata.cpp
+++ b/engines/mutationofjb/gamedata.cpp
@@ -298,6 +298,15 @@ Static *Scene::getStatic(uint8 staticId, bool ignoreNo) {
return &_statics[staticId - 1];
}
+Bitmap *Scene::getBitmap(uint8 bitmapId) {
+ if (bitmapId == 0 || bitmapId > ARRAYSIZE(_bitmaps)) {
+ warning("Bitmap %d does not exist", bitmapId);
+ return nullptr;
+ }
+
+ return &_bitmaps[bitmapId - 1];
+}
+
uint8 Scene::getNoDoors(bool ignoreNo) const {
return (!ignoreNo ? MIN(_noDoors, static_cast<uint8>(ARRAYSIZE(_doors))) : ARRAYSIZE(_doors));
}
@@ -310,6 +319,10 @@ uint8 Scene::getNoStatics(bool ignoreNo) const {
return (!ignoreNo ? MIN(_noStatics, static_cast<uint8>(ARRAYSIZE(_statics))) : ARRAYSIZE(_statics));
}
+uint8 Scene::getNoBitmaps() const {
+ return ARRAYSIZE(_bitmaps);
+}
+
Door *Scene::findDoor(int16 x, int16 y, bool activeOnly, int *index) {
for (int i = 0; i < getNoDoors(); ++i) {
Door &door = _doors[i];
diff --git a/engines/mutationofjb/gamedata.h b/engines/mutationofjb/gamedata.h
index fb81518890..c2ddfd644a 100644
--- a/engines/mutationofjb/gamedata.h
+++ b/engines/mutationofjb/gamedata.h
@@ -338,10 +338,12 @@ struct Scene : Common::Serializable {
Door *getDoor(uint8 objectId);
Object *getObject(uint8 objectId, bool ignoreNo = false);
Static *getStatic(uint8 staticId, bool ignoreNo = false);
+ Bitmap *getBitmap(uint8 bitmapId);
uint8 getNoDoors(bool ignoreNo = false) const;
uint8 getNoObjects(bool ignoreNo = false) const;
uint8 getNoStatics(bool ignoreNo = false) const;
+ uint8 getNoBitmaps() const;
/**
* Finds the door at the given position. By default, only active doors are considered.
diff --git a/engines/mutationofjb/module.mk b/engines/mutationofjb/module.mk
index 20272d05dc..736e9429eb 100644
--- a/engines/mutationofjb/module.mk
+++ b/engines/mutationofjb/module.mk
@@ -2,6 +2,7 @@ MODULE := engines/mutationofjb
MODULE_OBJS := \
commands/additemcommand.o \
+ commands/bitmapvisibilitycommand.o \
commands/callmacrocommand.o \
commands/camefromcommand.o \
commands/changecommand.o \
@@ -16,6 +17,7 @@ MODULE_OBJS := \
commands/labelcommand.o \
commands/loadplayercommand.o \
commands/newroomcommand.o \
+ commands/playanimationcommand.o \
commands/removeallitemscommand.o \
commands/removeitemcommand.o \
commands/renamecommand.o \
diff --git a/engines/mutationofjb/room.cpp b/engines/mutationofjb/room.cpp
index 783edae268..6b868e75c7 100644
--- a/engines/mutationofjb/room.cpp
+++ b/engines/mutationofjb/room.cpp
@@ -146,6 +146,41 @@ void Room::drawObjectAnimation(uint8 objectId, int animOffset) {
blit_if(_surfaces[animFrame], *_screen, Common::Point(object->_x, object->_y), ThresholdBlitOperation());
}
+void Room::drawBitmap(uint8 bitmapId) {
+ GameData &gameData = _game->getGameData();
+
+ Scene *const scene = gameData.getCurrentScene();
+ if (!scene) {
+ return;
+ }
+ Bitmap *const bitmap = scene->getBitmap(bitmapId);
+ if (!bitmap) {
+ return;
+ }
+
+ Common::Rect bitmapArea(bitmap->_x1, bitmap->_y1, bitmap->_x2 + 1, bitmap->_y2 + 1);
+ drawFrames(bitmap->_roomFrame - 1, bitmap->_roomFrame - 1, bitmapArea, 0xC0);
+}
+
+void Room::drawFrames(uint8 fromFrame, uint8 toFrame, const Common::Rect &area, uint8 threshold) {
+ GameData &gameData = _game->getGameData();
+
+ Scene *const scene = gameData.getCurrentScene();
+ if (!scene) {
+ return;
+ }
+
+ const Common::String fileName = Common::String::format("room%d%s.dat", gameData._currentScene, gameData._partB ? "b" : "");
+
+ AnimationDecoder decoder(fileName, *_screen);
+ decoder.setPartialMode(fromFrame, toFrame, area, threshold);
+ decoder.decode(nullptr);
+ if (!area.isEmpty())
+ _screen->getSubArea(area); // Add dirty rect.
+ else
+ _screen->makeAllDirty();
+}
+
void Room::redraw() {
if (!_game->isCurrentSceneMap()) {
Common::Rect rect(0, 0, GAME_AREA_WIDTH, GAME_AREA_HEIGHT);
@@ -159,6 +194,13 @@ void Room::redraw() {
drawObjectAnimation(i + 1, obj->_currentFrame - _objectsStart[i] - 1);
}
}
+
+ for (uint8 i = 0; i < currentScene->getNoBitmaps(); ++i) {
+ Bitmap *const bitmap = currentScene->getBitmap(i + 1);
+ if (bitmap->_isVisible && bitmap->_roomFrame > 0) {
+ drawBitmap(i + 1);
+ }
+ }
}
}
diff --git a/engines/mutationofjb/room.h b/engines/mutationofjb/room.h
index 083fba6335..0c29510a8d 100644
--- a/engines/mutationofjb/room.h
+++ b/engines/mutationofjb/room.h
@@ -45,6 +45,8 @@ public:
Room(Game *game, Graphics::Screen *screen);
bool load(uint8 roomNumber, bool roomB);
void drawObjectAnimation(uint8 objectId, int animOffset);
+ void drawBitmap(uint8 bitmapId);
+ void drawFrames(uint8 fromFrame, uint8 toFrame, const Common::Rect &area = Common::Rect(), uint8 threshold = 0xFF);
void redraw();
private:
Game *_game;
diff --git a/engines/mutationofjb/script.cpp b/engines/mutationofjb/script.cpp
index a4bbb8f1ef..a931785404 100644
--- a/engines/mutationofjb/script.cpp
+++ b/engines/mutationofjb/script.cpp
@@ -49,6 +49,8 @@
#include "mutationofjb/commands/specialshowcommand.h"
#include "mutationofjb/commands/switchpartcommand.h"
#include "mutationofjb/commands/loadplayercommand.h"
+#include "mutationofjb/commands/bitmapvisibilitycommand.h"
+#include "mutationofjb/commands/playanimationcommand.h"
#include "mutationofjb/game.h"
namespace MutationOfJB {
@@ -81,6 +83,8 @@ static CommandParser **getParsers() {
new SpecialShowCommandParser,
new SwitchPartCommandParser,
new LoadPlayerCommandParser,
+ new BitmapVisibilityCommandParser,
+ new PlayAnimationCommandParser,
nullptr
};