aboutsummaryrefslogtreecommitdiff
path: root/engines/scumm
diff options
context:
space:
mode:
Diffstat (limited to 'engines/scumm')
-rw-r--r--engines/scumm/detection.cpp5
-rw-r--r--engines/scumm/detection_tables.h2
-rw-r--r--engines/scumm/he/intern_he.h9
-rw-r--r--engines/scumm/he/logic/moonbase.cpp52
-rw-r--r--engines/scumm/he/logic/moonbase_logic.cpp253
-rw-r--r--engines/scumm/he/moonbase/moonbase.cpp179
-rw-r--r--engines/scumm/he/moonbase/moonbase.h99
-rw-r--r--engines/scumm/he/moonbase/moonbase_fow.cpp417
-rw-r--r--engines/scumm/he/script_v100he.cpp144
-rw-r--r--engines/scumm/he/script_v90he.cpp34
-rw-r--r--engines/scumm/he/sound_he.cpp4
-rw-r--r--engines/scumm/he/sprite_he.cpp30
-rw-r--r--engines/scumm/he/sprite_he.h8
-rw-r--r--engines/scumm/he/wiz_he.cpp323
-rw-r--r--engines/scumm/he/wiz_he.h90
-rw-r--r--engines/scumm/module.mk6
-rw-r--r--engines/scumm/scumm-md5.h4
-rw-r--r--engines/scumm/scumm.cpp12
18 files changed, 1433 insertions, 238 deletions
diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp
index 0867b20fc3..4c9d1221aa 100644
--- a/engines/scumm/detection.cpp
+++ b/engines/scumm/detection.cpp
@@ -186,6 +186,11 @@ Common::String ScummEngine_v70he::generateFilename(const int room) const {
}
if (_filenamePattern.genMethod == kGenHEPC || _filenamePattern.genMethod == kGenHEIOS) {
+ if (id == '3' && _game.id == GID_MOONBASE) {
+ result = Common::String::format("%s.u32", _filenamePattern.pattern);
+ break;
+ }
+
// For HE >= 98, we already called snprintf above.
if (_game.heversion < 98 || room < 0)
result = Common::String::format("%s.he%c", _filenamePattern.pattern, id);
diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h
index 5a994cb699..bb3e7f6ec3 100644
--- a/engines/scumm/detection_tables.h
+++ b/engines/scumm/detection_tables.h
@@ -245,9 +245,11 @@ static const GameSettings gameVariantsTable[] = {
{"monkey", "CD", 0, GID_MONKEY, 5, 0, MDT_ADLIB, GF_AUDIOTRACKS, UNK, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
{"monkey", "FM-TOWNS", 0, GID_MONKEY, 5, 0, MDT_TOWNS, GF_AUDIOTRACKS, Common::kPlatformFMTowns, GUIO4(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_MIDITOWNS, GUIO_NOASPECT)},
{"monkey", "SEGA", 0, GID_MONKEY, 5, 0, MDT_NONE, GF_AUDIOTRACKS, Common::kPlatformSegaCD, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)},
+ {"monkey", "SE Talkie", 0, GID_MONKEY, 5, 0, MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, GF_AUDIOTRACKS, UNK, GUIO0()},
{"monkey2", "", 0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO1(GUIO_NOSPEECH)},
{"monkey2", "FM-TOWNS", 0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_TOWNS | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, Common::kPlatformFMTowns, GUIO5(GUIO_NOSPEECH, GUIO_MIDITOWNS, GUIO_MIDIADLIB, GUIO_MIDIMT32, GUIO_NOASPECT)},
+ {"monkey2", "SE Talkie",0, GID_MONKEY2, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},
{"atlantis", "", 0, GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},
{"atlantis", "Steam", "steam", GID_INDY4, 5, 0, MDT_PCSPK | MDT_ADLIB | MDT_MIDI | MDT_PREFER_MT32, 0, UNK, GUIO0()},
diff --git a/engines/scumm/he/intern_he.h b/engines/scumm/he/intern_he.h
index 370f54c1d8..06e6b249f6 100644
--- a/engines/scumm/he/intern_he.h
+++ b/engines/scumm/he/intern_he.h
@@ -184,8 +184,11 @@ protected:
};
#ifdef ENABLE_HE
+class Moonbase;
+
class ScummEngine_v71he : public ScummEngine_v70he {
friend class Wiz;
+ friend class Moonbase;
protected:
bool _skipProcessActors;
@@ -244,6 +247,10 @@ public:
void queueAuxEntry(int actorNum, int subIndex);
void remapHEPalette(const uint8 *src, uint8 *dst);
+
+public:
+ /* Moonbase stuff */
+ Moonbase *_moonbase;
};
class ScummEngine_v72he : public ScummEngine_v71he {
@@ -433,7 +440,7 @@ protected:
byte filename[260];
int32 status;
int32 flags;
- int32 unk2;
+ int32 number;
int32 wizResNum;
};
diff --git a/engines/scumm/he/logic/moonbase.cpp b/engines/scumm/he/logic/moonbase.cpp
deleted file mode 100644
index 29a0dde7a2..0000000000
--- a/engines/scumm/he/logic/moonbase.cpp
+++ /dev/null
@@ -1,52 +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 "scumm/he/intern_he.h"
-#include "scumm/he/logic_he.h"
-
-namespace Scumm {
-
-/**
- * Logic code for:
- * Moonbase Commander
- */
-class LogicHEmoonbase : public LogicHE {
-public:
- LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {}
-
- int versionID();
-};
-
-int LogicHEmoonbase::versionID() {
- if (_vm->_game.features & GF_DEMO)
- return -100;
- else if (strcmp(_vm->_game.variant, "1.1") == 0)
- return 110;
- else
- return 100;
-}
-
-LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) {
- return new LogicHEmoonbase(vm);
-}
-
-} // End of namespace Scumm
diff --git a/engines/scumm/he/logic/moonbase_logic.cpp b/engines/scumm/he/logic/moonbase_logic.cpp
new file mode 100644
index 0000000000..a32356614f
--- /dev/null
+++ b/engines/scumm/he/logic/moonbase_logic.cpp
@@ -0,0 +1,253 @@
+/* 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 "scumm/he/intern_he.h"
+#include "scumm/he/logic_he.h"
+#include "scumm/he/moonbase/moonbase.h"
+
+namespace Scumm {
+
+/**
+ * Logic code for:
+ * Moonbase Commander
+ */
+class LogicHEmoonbase : public LogicHE {
+public:
+ LogicHEmoonbase(ScummEngine_v90he *vm) : LogicHE(vm) {}
+
+ int versionID();
+
+ int32 dispatch(int op, int numArgs, int32 *args);
+
+private:
+ void op_create_multi_state_wiz(int op, int numArgs, int32 *args);
+ void op_load_multi_channel_wiz(int op, int numArgs, int32 *args);
+ void op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args);
+ void op_dos_command(int op, int numArgs, int32 *args);
+ void op_set_fow_sentinel(int32 *args);
+ void op_set_fow_information(int op, int numArgs, int32 *args);
+ int op_set_fow_image(int op, int numArgs, int32 *args);
+
+ void op_ai_test_kludge(int op, int numArgs, int32 *args);
+ void op_ai_master_control_program(int op, int numArgs, int32 *args);
+ void op_ai_reset(int op, int numArgs, int32 *args);
+ void op_ai_set_type(int op, int numArgs, int32 *args);
+ void op_ai_clean_up(int op, int numArgs, int32 *args);
+};
+
+int LogicHEmoonbase::versionID() {
+ if (_vm->_game.features & GF_DEMO)
+ return -100;
+ else if (strcmp(_vm->_game.variant, "1.1") == 0)
+ return 110;
+ else
+ return 100;
+}
+
+#define OP_CREATE_MULTI_STATE_WIZ 100
+#define OP_LOAD_MULTI_CHANNEL_WIZ 101
+#define OP_WIZ_FROM_MULTI_CHANNEL_WIZ 102
+#define OP_DOS_COMMAND 103
+#define OP_SET_FOW_SENTINEL 104
+#define OP_SET_FOW_INFORMATION 105
+#define OP_SET_FOW_IMAGE 106
+
+#define OP_AI_TEST_KLUDGE 10000
+#define OP_AI_MASTER_CONTROL_PROGRAM 10001
+#define OP_AI_RESET 10002
+#define OP_AI_SET_TYPE 10003
+#define OP_AI_CLEAN_UP 10004
+
+#define OP_NET_REMOTE_START_SCRIPT 1492
+#define OP_NET_DO_INIT_ALL 1493
+#define OP_NET_DO_INIT_PROVIDER 1494
+#define OP_NET_DO_INIT_SESSION 1495
+#define OP_NET_DO_INIT_USER 1496
+#define OP_NET_QUERY_PROVIDERS 1497
+#define OP_NET_GET_PROVIDER_NAME 1498
+#define OP_NET_SET_PROVIDER 1499
+#define OP_NET_CLOSE_PROVIDER 1500
+#define OP_NET_QUERY_SESSIONS 1501
+#define OP_NET_GET_SESSION_NAME 1502
+#define OP_NET_CREATE_SESSION 1503
+#define OP_NET_JOIN_SESSION 1504
+#define OP_NET_END_SESSION 1505
+#define OP_NET_ADD_USER 1506
+#define OP_NET_REMOVE_USER 1507
+#define OP_NET_WHO_SENT_THIS 1508
+#define OP_NET_REMOTE_SEND_ARRAY 1509
+#define OP_NET_WHO_AM_I 1510
+#define OP_NET_REMOTE_START_FUNCTION 1511
+#define OP_NET_GET_PLAYER_LONG_NAME 1512
+#define OP_NET_GET_PLAYER_SHORT_NAME 1513
+#define OP_NET_SET_PROVIDER_BY_NAME 1516
+#define OP_NET_HOST_TCPIP_GAME 1517
+#define OP_NET_JOIN_TCPIP_GAME 1518
+#define OP_NET_SET_FAKE_LAG 1555
+#define OP_NET_GET_HOST_NAME 1556
+#define OP_NET_GET_IP_FROM_NAME 1557
+#define OP_NET_GET_SESSION_PLAYER_COUNT 1558
+#define OP_NET_DISABLE_SESSION_PLAYER_JOIN 1559
+#define OP_NET_START_QUERY_SESSIONS 1560
+#define OP_NET_UPDATE_QUERY_SESSIONS 1561
+#define OP_NET_STOP_QUERY_SESSIONS 1562
+#define OP_NET_DESTROY_PLAYER 1563
+#define OP_NET_ENABLE_SESSION_PLAYER_JOIN 1564
+#define OP_NET_SET_AI_PLAYER_COUNT 1565
+
+
+int32 LogicHEmoonbase::dispatch(int op, int numArgs, int32 *args) {
+ switch (op) {
+ case OP_CREATE_MULTI_STATE_WIZ:
+ op_create_multi_state_wiz(op, numArgs, args);
+ break;
+ case OP_LOAD_MULTI_CHANNEL_WIZ:
+ op_load_multi_channel_wiz(op, numArgs, args);
+ break;
+ case OP_WIZ_FROM_MULTI_CHANNEL_WIZ:
+ op_wiz_from_multi_channel_wiz(op, numArgs, args);
+ break;
+ case OP_DOS_COMMAND:
+ op_dos_command(op, numArgs, args);
+ break;
+ case OP_SET_FOW_SENTINEL:
+ op_set_fow_sentinel(args);
+ break;
+ case OP_SET_FOW_INFORMATION:
+ op_set_fow_information(op, numArgs, args);
+ break;
+ case OP_SET_FOW_IMAGE:
+ return op_set_fow_image(op, numArgs, args);
+ break;
+
+ case OP_AI_TEST_KLUDGE:
+ op_ai_test_kludge(op, numArgs, args);
+ break;
+ case OP_AI_MASTER_CONTROL_PROGRAM:
+ op_ai_master_control_program(op, numArgs, args);
+ break;
+ case OP_AI_RESET:
+ op_ai_reset(op, numArgs, args);
+ break;
+ case OP_AI_SET_TYPE:
+ op_ai_set_type(op, numArgs, args);
+ break;
+ case OP_AI_CLEAN_UP:
+ op_ai_clean_up(op, numArgs, args);
+ break;
+
+ default:
+ LogicHE::dispatch(op, numArgs, args);
+ }
+
+ return 0;
+}
+
+void LogicHEmoonbase::op_create_multi_state_wiz(int op, int numArgs, int32 *args) {
+ warning("STUB: op_create_multi_state_wiz()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_load_multi_channel_wiz(int op, int numArgs, int32 *args) {
+ warning("STUB: op_load_multi_channel_wiz()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_wiz_from_multi_channel_wiz(int op, int numArgs, int32 *args) {
+ warning("STUB: op_wiz_from_multi_channel_wiz()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_dos_command(int op, int numArgs, int32 *args) {
+ warning("STUB: op_dos_command()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_set_fow_sentinel(int32 *args) {
+ debug(2, "op_set_fow_sentinel(%d, %d, %d)", args[0], args[1], args[2]);
+
+ _vm->_moonbase->_fowSentinelImage = args[0];
+ _vm->_moonbase->_fowSentinelState = args[1];
+ _vm->_moonbase->_fowSentinelConditionBits = args[2];
+}
+
+void LogicHEmoonbase::op_set_fow_information(int op, int numArgs, int32 *args) {
+ Common::String str;
+
+ str = Common::String::format("op_set_fow_information(%d", args[0]);
+ for (int i = 1; i < numArgs; i++) {
+ str += Common::String::format(", %d", args[i]);
+ }
+ str += ")";
+
+ debug(2, "%s", str.c_str());
+
+ _vm->_moonbase->setFOWInfo(
+ args[0], // array
+ args[1], // array down dimension
+ args[2], // array across dimension
+ args[3], // logical view X coordinate
+ args[4], // logical view Y coordinate
+ args[5], // screen draw clip rect x1
+ args[6], // screen draw clip rect y1
+ args[7], // screen draw clip rect x2
+ args[8], // screen draw clip rect y2
+ args[9], // techinque
+ args[10] // frame
+ );
+}
+
+int LogicHEmoonbase::op_set_fow_image(int op, int numArgs, int32 *args) {
+ debug(2, "op_set_fow_image(%d)", args[0]);
+ return _vm->_moonbase->setFOWImage(args[0]) ? 1 : 0;
+}
+
+void LogicHEmoonbase::op_ai_test_kludge(int op, int numArgs, int32 *args) {
+ warning("STUB: op_ai_test_kludge()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_ai_master_control_program(int op, int numArgs, int32 *args) {
+ warning("STUB: op_ai_master_control_program()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_ai_reset(int op, int numArgs, int32 *args) {
+ warning("STUB: op_ai_reset)");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_ai_set_type(int op, int numArgs, int32 *args) {
+ warning("STUB: op_ai_set_type()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+void LogicHEmoonbase::op_ai_clean_up(int op, int numArgs, int32 *args) {
+ warning("STUB: op_ai_clean_up()");
+ LogicHE::dispatch(op, numArgs, args);
+}
+
+LogicHE *makeLogicHEmoonbase(ScummEngine_v90he *vm) {
+ return new LogicHEmoonbase(vm);
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/moonbase/moonbase.cpp b/engines/scumm/he/moonbase/moonbase.cpp
new file mode 100644
index 0000000000..34d4368725
--- /dev/null
+++ b/engines/scumm/he/moonbase/moonbase.cpp
@@ -0,0 +1,179 @@
+/* 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 "scumm/he/intern_he.h"
+#include "scumm/he/moonbase/moonbase.h"
+
+namespace Scumm {
+
+Moonbase::Moonbase(ScummEngine_v71he *vm) : _vm(vm) {
+ initFOW();
+}
+
+Moonbase::~Moonbase() {
+}
+
+void Moonbase::blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox,
+ uint8 *wizd, int x, int y, int rawROP, int paramROP) {
+ bool premulAlpa = false;
+
+ if (rawROP == 1)
+ premulAlpa = true;
+
+ Common::Rect clippedDstRect(dstw, dsth);
+ if (clipBox) {
+ Common::Rect clip(clipBox->left, clipBox->top, clipBox->right, clipBox->bottom);
+ if (clippedDstRect.intersects(clip)) {
+ clippedDstRect.clip(clip);
+ } else {
+ return;
+ }
+ }
+
+ int width = READ_LE_UINT16(wizd + 0x8 + 0);
+ int height = READ_LE_UINT16(wizd + 0x8 + 2);
+
+ Common::Rect srcLimitsRect(width, height);
+ Common::Rect dstOperation(x, y, x + width, y + height);
+ if (!clippedDstRect.intersects(dstOperation))
+ return;
+ Common::Rect clippedRect = clippedDstRect.findIntersectingRect(dstOperation);
+
+ int cx = clippedRect.right - clippedRect.left;
+ int cy = clippedRect.bottom - clippedRect.top;
+
+ int sx = ((clippedRect.left - x) + srcLimitsRect.left);
+ int sy = ((clippedRect.top - y) + srcLimitsRect.top);
+
+ dst += clippedRect.top * dstPitch + clippedRect.left * 2;
+
+ int headerSize = READ_LE_UINT32(wizd + 0x4);
+ uint8 *dataPointer = wizd + 0x8 + headerSize;
+
+ for (int i = 0; i < sy; i++) {
+ uint16 lineSize = READ_LE_UINT16(dataPointer + 0);
+
+ dataPointer += lineSize;
+ }
+
+ for (int i = 0; i < cy; i++) {
+ uint16 lineSize = READ_LE_UINT16(dataPointer + 0);
+ uint8 *singlesOffset = READ_LE_UINT16(dataPointer + 2) + dataPointer;
+ uint8 *quadsOffset = READ_LE_UINT16(dataPointer + 4) + dataPointer;
+
+ int pixels = 0;
+ byte *dst1 = dst;
+ byte *codes = dataPointer + 6;
+
+ while (1) {
+ int code = *codes - 2;
+ codes++;
+
+ if (code <= 0) { // quad or single
+ uint8 *src;
+ int cnt;
+ if (code == 0) { // quad
+ src = quadsOffset;
+ quadsOffset += 8;
+ cnt = 4; // 4 pixels
+ } else { // single
+ src = singlesOffset;
+ singlesOffset += 2;
+ cnt = 1;
+ }
+
+ for (int c = 0; c < cnt; c++) {
+ if (pixels >= sx) {
+ if (rawROP == 1) { // MMX_PREMUL_ALPHA_COPY
+ WRITE_LE_UINT16(dst1, READ_LE_UINT16(src));
+ } else if (rawROP == 2) { // MMX_ADDITIVE
+ uint16 color = READ_LE_UINT16(src);
+ uint16 orig = READ_LE_UINT16(dst1);
+
+ uint32 r = MIN<uint32>(0x7c00, (orig & 0x7c00) + (color & 0x7c00));
+ uint32 g = MIN<uint32>(0x03e0, (orig & 0x03e0) + (color & 0x03e0));
+ uint32 b = MIN<uint32>(0x001f, (orig & 0x001f) + (color & 0x001f));
+ WRITE_LE_UINT16(dst1, (r | g | b));
+ } else if (rawROP == 5) { // MMX_CHEAP_50_50
+ uint16 color = (READ_LE_UINT16(src) >> 1) & 0x3DEF;
+ uint16 orig = (READ_LE_UINT16(dst1) >> 1) & 0x3DEF;
+ WRITE_LE_UINT16(dst1, (color + orig));
+ }
+ dst1 += 2;
+ }
+ src += 2;
+ pixels++;
+ }
+ } else { // skip
+ if ((code & 1) == 0) {
+ code >>= 1;
+
+ for (int j = 0; j < code; j++) {
+ if (pixels >= sx)
+ dst1 += 2;
+ pixels++;
+ }
+ } else { // special case
+ if (pixels >= sx) {
+ int alpha = code >> 1;
+ uint16 color = READ_LE_UINT16(singlesOffset);
+ uint32 orig = READ_LE_UINT16(dst1);
+
+ if (!premulAlpa) {
+ WRITE_LE_UINT16(dst1, color); // ENABLE_PREMUL_ALPHA = 0
+ } else {
+ if (alpha > 32) {
+ alpha -= 32;
+
+ uint32 oR = orig & 0x7c00;
+ uint32 oG = orig & 0x03e0;
+ uint32 oB = orig & 0x1f;
+ uint32 dR = ((((color & 0x7c00) - oR) * alpha) >> 5) + oR;
+ uint32 dG = ((((color & 0x3e0) - oG) * alpha) >> 5) + oG;
+ uint32 dB = ((((color & 0x1f) - oB) * alpha) >> 5) + oB;
+
+ WRITE_LE_UINT16(dst1, (dR & 0x7c00) | (dG & 0x3e0) | (dB & 0x1f));
+ } else {
+ uint32 pix = ((orig << 16) | orig) & 0x3e07c1f;
+ pix = (((pix * alpha) & 0xffffffff) >> 5) & 0x3e07c1f;
+ pix = ((pix >> 16) + pix + color) & 0xffff;
+ WRITE_LE_UINT16(dst1, pix);
+ }
+ }
+
+ dst1 += 2;
+ }
+ singlesOffset += 2;
+ pixels++;
+ }
+ }
+
+ if (pixels >= cx + sx)
+ break;
+ }
+
+ dataPointer += lineSize;
+ dst += dstPitch;
+ }
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/moonbase/moonbase.h b/engines/scumm/he/moonbase/moonbase.h
new file mode 100644
index 0000000000..e82ae0164f
--- /dev/null
+++ b/engines/scumm/he/moonbase/moonbase.h
@@ -0,0 +1,99 @@
+/* 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 SCUMM_HE_MOONBASE_H
+#define SCUMM_HE_MOONBASE_H
+
+#ifdef ENABLE_HE
+
+#include "common/winexe_pe.h"
+
+namespace Scumm {
+
+class Moonbase {
+public:
+ Moonbase(ScummEngine_v71he *vm);
+ ~Moonbase();
+
+ void blitT14WizImage(uint8 *dst, int dstw, int dsth, int dstPitch, const Common::Rect *clipBox,
+ uint8 *wizd, int srcx, int srcy, int rawROP, int paramROP);
+
+ // FOW Stuff
+ void initFOW();
+ void releaseFOWResources();
+
+ bool setFOWImage(int id);
+
+ void setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1,
+ int clipY1, int clipX2, int clipY2, int technique, int nFrame);
+
+
+ void renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags);
+
+private:
+ int readFOWVisibilityArray(int array, int y, int x);
+ void renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags);
+
+public:
+ int _fowSentinelImage;
+ int _fowSentinelState;
+ uint32 _fowSentinelConditionBits;
+
+private:
+ ScummEngine_v71he *_vm;
+
+ int _fowFrameBaseNumber;
+ int _fowAnimationFrames;
+ int _fowCurrentFOWFrame;
+
+ int32 _fowTileW;
+ int32 _fowTileH;
+
+ uint8 *_fowImage;
+ int _fowClipX1;
+ int _fowClipY1;
+ int _fowClipX2;
+ int _fowClipY2;
+
+ int _fowDrawX;
+ int _fowDrawY;
+
+ int _fowVtx1;
+ int _fowVty1;
+ int _fowMvx;
+ int _fowMvy;
+ int _fowVw;
+ int _fowVh;
+
+ bool _fowBlackMode;
+
+ int _fowRenderTable[32768];
+
+ Common::PEResources _exe;
+ Common::String _fileName;
+};
+
+} // End of namespace Scumm
+
+#endif // ENABLE_HE
+
+#endif // SCUMM_HE_MOONBASE_H
diff --git a/engines/scumm/he/moonbase/moonbase_fow.cpp b/engines/scumm/he/moonbase/moonbase_fow.cpp
new file mode 100644
index 0000000000..3f3730b6f1
--- /dev/null
+++ b/engines/scumm/he/moonbase/moonbase_fow.cpp
@@ -0,0 +1,417 @@
+/* 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/config-manager.h"
+
+#include "scumm/he/intern_he.h"
+#include "scumm/he/moonbase/moonbase.h"
+
+namespace Scumm {
+
+#define FOW_ANIM_FRAME_COUNT 38
+
+void Moonbase::initFOW() {
+ _fowSentinelImage = -1;
+ _fowSentinelState = -1;
+ _fowSentinelConditionBits = 0;
+
+ _fowFrameBaseNumber = 0;
+ _fowAnimationFrames = 1;
+ _fowCurrentFOWFrame = 0;
+
+ _fowTileW = 0;
+ _fowTileH = 0;
+
+ _fowImage = nullptr;
+ _fowClipX1 = 0;
+ _fowClipY1 = 0;
+ _fowClipX2 = 0;
+ _fowClipY2 = 0;
+
+ _fowDrawX = 0;
+ _fowDrawY = 0;
+
+ _fowVtx1 = 0;
+ _fowVty1 = 0;
+ _fowMvx = 0;
+ _fowMvy = 0;
+ _fowVw = 0;
+ _fowVh = 0;
+
+ _fowBlackMode = true;
+
+ memset(_fowRenderTable, 0, 32768);
+}
+
+void Moonbase::releaseFOWResources() {
+ if (_fowImage) {
+ free(_fowImage);
+ _fowImage = 0;
+ }
+}
+
+bool Moonbase::setFOWImage(int image) {
+ releaseFOWResources();
+
+ if (!_fowImage) {
+ Common::String fowImageFilename(ConfMan.get("MOONX_FOWImageFilename").c_str());
+
+#if 0 // TODO
+ if (!fowImageFilename.empty()) {
+ void *wiz = loadWizFromFilename(fowImageFilename);
+
+ if (wiz) {
+ captureFOWImageFromLocation(wiz, file.size());
+ free(wiz);
+ }
+ }
+#endif
+
+ if (!_fowImage && image < 0) {
+ int resId;
+
+ // PIECES BUBBLES CIRCLES SIMPLE* WEDGEY BUBBLE2
+ // WEDGE2 SPIKEY ANGLES SMOOTHED WUZZY SYS7-BEVELED
+ if (image >= -12 && image <= -1)
+ resId = 210 - image; // 211-222 range
+ else
+ resId = 214; // default, SIMPLE
+
+ if (_fileName.empty()) { // We are running for the first time
+ _fileName = _vm->generateFilename(-3);
+
+ if (!_exe.loadFromEXE(_fileName))
+ error("Cannot open file %s", _fileName.c_str());
+ }
+
+ Common::SeekableReadStream *stream = _exe.getResource(Common::kPERCData, resId);
+
+ if (stream->size()) {
+ _fowImage = (uint8 *)malloc(stream->size());
+
+ stream->read(_fowImage, stream->size());
+ }
+
+ delete stream;
+ }
+
+ if (!_fowImage && image > 0)
+ _fowImage = _vm->getResourceAddress(rtImage, image);
+
+ if (!_fowImage)
+ return false;
+ }
+
+ int nStates = _vm->_wiz->getWizImageStates(_fowImage);
+
+ if (nStates > FOW_ANIM_FRAME_COUNT) {
+ releaseFOWResources();
+ return false;
+ }
+
+ _fowAnimationFrames = (nStates + FOW_ANIM_FRAME_COUNT - 1) / FOW_ANIM_FRAME_COUNT;
+
+ _vm->_wiz->getWizImageDim(_fowImage, (nStates - 1), _fowTileW, _fowTileH);
+ _fowBlackMode = !_vm->_wiz->isWizPixelNonTransparent(_fowImage, nStates - 1, 0, 0, 0);
+
+ if (ConfMan.hasKey("EnableFOWRects"))
+ _fowBlackMode = (ConfMan.getInt("EnableFOWRects") == 1);
+
+ return true;
+}
+
+enum FOWElement {
+ FOW_EMPTY = 0,
+ FOW_SOLID = 1,
+
+ FF_L = 0x01,
+ FF_R = 0x02,
+ FF_T = 0x04,
+ FF_B = 0x08,
+ FF_T_L = 0x10,
+ FF_T_R = 0x20,
+ FF_B_L = 0x40,
+ FF_B_R = 0x80,
+ FF_Q_A = (FF_L | FF_T | FF_T_L),
+ FF_Q_B = (FF_R | FF_T | FF_T_R),
+ FF_Q_C = (FF_L | FF_B | FF_B_L),
+ FF_Q_D = (FF_R | FF_B | FF_B_R)
+};
+
+int Moonbase::readFOWVisibilityArray(int array, int y, int x) {
+ _vm->VAR(116) = array;
+
+ if (_vm->readArray(116, y, x) > 0)
+ return FOW_EMPTY;
+
+ return FOW_SOLID;
+}
+
+void Moonbase::setFOWInfo(int fowInfoArray, int downDim, int acrossDim, int viewX, int viewY, int clipX1,
+ int clipY1, int clipX2, int clipY2, int technique, int nFrame) {
+ if (!_fowImage)
+ return;
+
+ _fowDrawX = clipX1;
+ _fowDrawY = clipY1;
+
+ _fowClipX1 = clipX1;
+ _fowClipY1 = clipY1;
+ _fowClipX2 = clipX2;
+ _fowClipY2 = clipY2;
+
+ // Figure out the number of tiles are involved
+ int view_W = (clipX2 - clipX1) + 1;
+ int view_H = (clipY2 - clipY1) + 1;
+
+ int tw = _fowTileW;
+ int th = _fowTileH;
+
+ int dw = acrossDim;
+ int dh = downDim;
+
+ int dlw = dw * tw;
+ int dlh = dh * th;
+
+ _fowMvx = (0 <= viewX) ? (viewX % dlw) : (dlw - (-viewX % dlw));
+ _fowMvy = (0 <= viewY) ? (viewY % dlh) : (dlh - (-viewY % dlh));
+
+ _fowVtx1 = _fowMvx / tw;
+ _fowVty1 = _fowMvy / th;
+
+ _fowVw = (((_fowMvx + view_W + tw - 1) / tw) - _fowVtx1) + 1;
+ _fowVh = (((_fowMvy + view_H + th - 1) / th) - _fowVty1) + 1;
+
+ // Build the connectivity table
+ int t = (_fowVty1 - 1); if (t >= dh) { t = 0; } else if (t < 0) { t = (dh - 1); }
+ int m = (_fowVty1 + 0); if (m >= dh) { m = 0; } else if (m < 0) { m = (dh - 1); }
+ int b = (_fowVty1 + 1); if (b >= dh) { b = 0; } else if (b < 0) { b = (dh - 1); }
+
+ int il = (_fowVtx1 - 1); if (il >= dh) { il = 0; } else if (il < 0) { il = (dw - 1); }
+ int ic = (_fowVtx1 + 0); if (ic >= dh) { ic = 0; } else if (ic < 0) { ic = (dw - 1); }
+ int ir = (_fowVtx1 + 1); if (ir >= dh) { ir = 0; } else if (ir < 0) { ir = (dw - 1); }
+
+ int dataOffset = (_fowVw * 3);
+ int dataOffset2 = (dataOffset * 2);
+ int *pOutterRenderTableA = _fowRenderTable;
+ int *pOutterRenderTableB = pOutterRenderTableA + dataOffset;
+
+ for (int ay = 0; ay < _fowVh; ay++) {
+ int l = il;
+ int c = ic;
+ int r = ir;
+
+ int *pRenderTableA = pOutterRenderTableA;
+ int *pRenderTableB = pOutterRenderTableB;
+
+ pOutterRenderTableA += dataOffset2;
+ pOutterRenderTableB += dataOffset2;
+
+ for (int ax = 0; ax < _fowVw; ax++) {
+ int visibility = readFOWVisibilityArray(fowInfoArray, m, c);
+
+ if (visibility == FOW_EMPTY) {
+ int bits = 0;
+
+ if (readFOWVisibilityArray(fowInfoArray, t, l) != 0) bits |= FF_T_L;
+ if (readFOWVisibilityArray(fowInfoArray, t, c) != 0) bits |= FF_T;
+ if (readFOWVisibilityArray(fowInfoArray, t, r) != 0) bits |= FF_T_R;
+ if (readFOWVisibilityArray(fowInfoArray, m, l) != 0) bits |= FF_L;
+ if (readFOWVisibilityArray(fowInfoArray, m, r) != 0) bits |= FF_R;
+ if (readFOWVisibilityArray(fowInfoArray, b, l) != 0) bits |= FF_B_L;
+ if (readFOWVisibilityArray(fowInfoArray, b, c) != 0) bits |= FF_B;
+ if (readFOWVisibilityArray(fowInfoArray, b, r) != 0) bits |= FF_B_R;
+
+ if (bits) {
+ *pRenderTableA++ = 1;
+ *pRenderTableB++ = 1;
+
+ // Quadrant (A)
+ if (bits & FF_Q_A) {
+ *pRenderTableA++ = (
+ ((FF_L & bits) ? 1 : 0) |
+ ((FF_T & bits) ? 2 : 0) |
+ ((FF_T_L & bits) ? 4 : 0)
+ ) + 0;
+ } else {
+ *pRenderTableA++ = 0;
+ }
+
+ // Quadrant (B)
+ if (bits & FF_Q_B) {
+ *pRenderTableA++ = (
+ ((FF_R & bits) ? 1 : 0) |
+ ((FF_T & bits) ? 2 : 0) |
+ ((FF_T_R & bits) ? 4 : 0)
+ ) + 8;
+ } else {
+ *pRenderTableA++ = 0;
+ }
+
+ // Quadrant (C)
+ if (bits & FF_Q_C) {
+ *pRenderTableB++ = (
+ ((FF_L & bits) ? 1 : 0) |
+ ((FF_B & bits) ? 2 : 0) |
+ ((FF_B_L & bits) ? 4 : 0)
+ ) + 16;
+ } else {
+ *pRenderTableB++ = 0;
+ }
+
+ // Quadrant (D)
+ if (bits & FF_Q_D) {
+ *pRenderTableB++ = (
+ ((FF_R & bits) ? 1 : 0) |
+ ((FF_B & bits) ? 2 : 0) |
+ ((FF_B_R & bits) ? 4 : 0)
+ ) + 24;
+ } else {
+ *pRenderTableB++ = 0;
+ }
+ } else {
+ *pRenderTableA++ = 0;
+ *pRenderTableB++ = 0;
+ }
+ } else {
+ if (_fowBlackMode) {
+ *pRenderTableA++ = 2;
+ *pRenderTableB++ = 2;
+ } else {
+ *pRenderTableA++ = 1;
+ *pRenderTableA++ = 33;
+ *pRenderTableA++ = 34;
+
+ *pRenderTableB++ = 1;
+ *pRenderTableB++ = 35;
+ *pRenderTableB++ = 36;
+ }
+ }
+
+ if (++l >= dw) { l = 0; }
+ if (++c >= dw) { c = 0; }
+ if (++r >= dw) { r = 0; }
+ }
+
+ if (++t >= dh) { t = 0; }
+ if (++m >= dh) { m = 0; }
+ if (++b >= dh) { b = 0; }
+ }
+
+ _fowCurrentFOWFrame = (nFrame >= 0) ? (nFrame % _fowAnimationFrames) : ((-nFrame) % _fowAnimationFrames);
+ _fowFrameBaseNumber = (_fowCurrentFOWFrame * FOW_ANIM_FRAME_COUNT);
+}
+
+void Moonbase::renderFOWState(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int x, int y, int srcw, int srch, int state, int flags) {
+ int32 spotx, spoty;
+
+ _vm->_wiz->getWizImageSpot(_fowImage, state, spotx, spoty);
+ Common::Rect r(_fowClipX1, _fowClipY1, _fowClipX2, _fowClipY2);
+
+ _vm->_wiz->drawWizImageEx(destSurface, _fowImage, 0, dstPitch, dstType, dstw, dsth, x - spotx, y - spoty, srcw, srch, state, &r, flags, 0, 0, 16, 0, 0);
+}
+
+static void blackRect_16bpp(uint8 *destSurface, int dstPitch, int dstw, int dsth, int x1, int y1, int x2, int y2) {
+ byte *dst = destSurface + dstPitch * y1 + x1 * 2;
+ int h = y2 - y1;
+ int w = ((x2 - x1) + 1) * 2;
+
+ while ( --h >= 0 ) {
+ memset(dst, 0, w);
+ dst += dstPitch;
+ }
+}
+
+void Moonbase::renderFOW(uint8 *destSurface, int dstPitch, int dstType, int dstw, int dsth, int flags) {
+ if (!_fowImage)
+ return;
+
+ const int *pOutterRenderTable = _fowRenderTable;
+ int ixPos = ((_fowVtx1 * _fowTileW) - _fowMvx) + _fowDrawX;
+ int yPos = ((_fowVty1 * _fowTileH) - _fowMvy) + _fowDrawY;
+ int dataOffset = _fowVw * 3;
+ int halfTileHeight = _fowTileH / 2;
+ int cx2 = MIN(_fowClipX2, (dstw - 1));
+ int cy2 = MIN(_fowClipY2, (dsth - 1));
+
+ for (int ry = 0; ry < _fowVh; ry++) {
+ int real_yPos = yPos;
+
+ for (int i = 0; i < 2; i++) {
+ const int *pRenderTable = pOutterRenderTable;
+ pOutterRenderTable += dataOffset;
+
+ int xPos = ixPos;
+
+ for (int rx = 0; rx < _fowVw; rx++) {
+ int nState = *pRenderTable++;
+
+ if (nState != 0) {
+ if (nState == 2) {
+ int countLeft = (_fowVw - rx);
+ int count = 0;
+
+ for (; count < countLeft; count++) {
+ if (*(pRenderTable + count) != 2)
+ break;
+
+ pRenderTable++;
+ rx++;
+ }
+ count++;
+
+ int x1 = xPos;
+ int y1 = real_yPos;
+
+ xPos += _fowTileW * count;
+ int x2 = (xPos - 1);
+ int y2 = ((y1 + halfTileHeight) - 1);
+
+ x1 = MAX(0, x1);
+ y1 = MAX(0, y1);
+ x2 = MIN(x2, cx2);
+ y2 = MIN(y2, cy2);
+
+ if ((x2 >= x1) && (y2 >= y1) && (x1 <= _fowClipX2) && (y1 <= _fowClipY2))
+ blackRect_16bpp(destSurface, dstPitch, dstw, dsth, x1, y1, x2, y2);
+ } else {
+ int subState;
+
+ if ((subState = *pRenderTable++) != 0)
+ renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags);
+
+ if ((subState = *pRenderTable++) != 0)
+ renderFOWState(destSurface, dstPitch, dstType, dstw, dsth, xPos, yPos, _fowTileW, _fowTileH, (subState + _fowFrameBaseNumber), flags);
+
+ xPos += _fowTileW;
+ }
+ } else {
+ xPos += _fowTileW;
+ }
+ }
+ real_yPos += halfTileHeight;
+ }
+ yPos += _fowTileH;
+ }
+}
+
+} // End of namespace Scumm
diff --git a/engines/scumm/he/script_v100he.cpp b/engines/scumm/he/script_v100he.cpp
index afc6633ef6..4388433c7e 100644
--- a/engines/scumm/he/script_v100he.cpp
+++ b/engines/scumm/he/script_v100he.cpp
@@ -549,20 +549,20 @@ void ScummEngine_v100he::o100_arrayOps() {
debug(9,"o100_arrayOps: array %d case %d", array, subOp);
switch (subOp) {
- case 35:
+ case 35: // SO_FORMATTED_STRING
decodeScriptString(string);
len = resStrLen(string);
data = defineArray(array, kStringArray, 0, 0, 0, len);
memcpy(data, string, len);
break;
- case 77: // SO_ASSIGN_STRING
+ case 77: // SO_STRING
copyScriptString(string, sizeof(string));
len = resStrLen(string);
data = defineArray(array, kStringArray, 0, 0, 0, len);
memcpy(data, string, len);
break;
- case 128: // SO_ASSIGN_2DIM_LIST
+ case 128: // SO_ASSIGN_2DIM_LIST
len = getStackList(list, ARRAYSIZE(list));
id = readVar(array);
if (id == 0)
@@ -572,7 +572,7 @@ void ScummEngine_v100he::o100_arrayOps() {
writeArray(array, c, len, list[len]);
}
break;
- case 129: // SO_ASSIGN_INT_LIST
+ case 129: // SO_ASSIGN_INT_LIST
b = pop();
c = pop();
id = readVar(array);
@@ -583,7 +583,7 @@ void ScummEngine_v100he::o100_arrayOps() {
writeArray(array, 0, b + c, pop());
}
break;
- case 130:
+ case 130: //
len = getStackList(list, ARRAYSIZE(list));
dim1end = pop();
dim1start = pop();
@@ -607,7 +607,7 @@ void ScummEngine_v100he::o100_arrayOps() {
dim2start++;
}
break;
- case 131:
+ case 131: // SO_COMPLEX_ARRAY_COPY_OPERATION
{
int a2_dim1end = pop();
int a2_dim1start = pop();
@@ -624,7 +624,7 @@ void ScummEngine_v100he::o100_arrayOps() {
copyArray(array, a1_dim2start, a1_dim2end, a1_dim1start, a1_dim1end, array2, a2_dim2start, a2_dim2end, a2_dim1start, a2_dim1end);
}
break;
- case 132:
+ case 132: // SO_COMPLEX_ARRAY_MATH_OPERATION
// TODO: Used by room 2 script 2180 in Moonbase Commander
fetchScriptWord();
fetchScriptWord();
@@ -659,9 +659,9 @@ void ScummEngine_v100he::o100_arrayOps() {
default:
error("o100_arrayOps: case 132 unknown type %d)", type);
}
- debug(0, "o100_arrayOps: case 132 type %d", type);
+ warning("STUB: o100_arrayOps: case 132 type %d", type);
break;
- case 133:
+ case 133: // SO_RANGE_ARRAY_ASSIGNMENT
b = pop();
c = pop();
dim1end = pop();
@@ -1110,6 +1110,7 @@ void ScummEngine_v100he::o100_resourceRoutines() {
break;
case 128:
// TODO: Clear Heap
+ warning("STUB: o100_resourceRoutines: clear Heap");
break;
case 129:
// Dummy case
@@ -1310,36 +1311,36 @@ void ScummEngine_v100he::o100_wizImageOps() {
if (_wizParams.img.resNum)
_wiz->processWizImage(&_wizParams);
break;
- case 128:
- _wizParams.field_239D = pop();
- _wizParams.field_2399 = pop();
- _wizParams.field_23A5 = pop();
- _wizParams.field_23A1 = pop();
- copyScriptString(_wizParams.string2, sizeof(_wizParams.string2));
+ case 128: // Font create
_wizParams.processMode = 15;
+ _wizParams.fontProperties.bgColor = pop();
+ _wizParams.fontProperties.fgColor = pop();
+ _wizParams.fontProperties.size = pop();
+ _wizParams.fontProperties.style = pop();
+ copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName));
break;
case 129:
_wizParams.processMode = 14;
break;
- case 130:
+ case 130: // Font render
_wizParams.processMode = 16;
- _wizParams.field_23AD = pop();
- _wizParams.field_23A9 = pop();
- copyScriptString(_wizParams.string1, sizeof(_wizParams.string1));
+ _wizParams.fontProperties.yPos = pop();
+ _wizParams.fontProperties.xPos = pop();
+ copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string));
break;
case 131:
_wizParams.processMode = 13;
break;
- case 133:
+ case 133: // Render ellipse
_wizParams.processMode = 17;
- _wizParams.field_23CD = pop();
- _wizParams.field_23C9 = pop();
- _wizParams.field_23C5 = pop();
- _wizParams.field_23C1 = pop();
- _wizParams.field_23BD = pop();
- _wizParams.field_23B9 = pop();
- _wizParams.field_23B5 = pop();
- _wizParams.field_23B1 = pop();
+ _wizParams.ellipseProperties.color = pop();
+ _wizParams.ellipseProperties.lod = pop();
+ _wizParams.ellipseProperties.ky = pop();
+ _wizParams.ellipseProperties.kx = pop();
+ _wizParams.ellipseProperties.qy = pop();
+ _wizParams.ellipseProperties.qx = pop();
+ _wizParams.ellipseProperties.py = pop();
+ _wizParams.ellipseProperties.px = pop();
break;
case 134:
_wizParams.processFlags |= kWPFFillColor | kWPFClipBox2;
@@ -1781,14 +1782,14 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
byte subOp = fetchScriptByte();
switch (subOp) {
- case 0:
+ case 0: // SO_INIT
_curMaxSpriteId = pop();
_curSpriteId = pop();
if (_curSpriteId > _curMaxSpriteId)
SWAP(_curSpriteId, _curMaxSpriteId);
break;
- case 2:
+ case 2: // SO_ANGLE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1799,7 +1800,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteAngle(spriteId, args[0]);
break;
- case 3:
+ case 3: // SO_ANIMATION
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1810,7 +1811,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagAutoAnim(spriteId, args[0]);
break;
- case 4:
+ case 4: // SO_ANIMATION_SPEED
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1821,7 +1822,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteAnimSpeed(spriteId, args[0]);
break;
- case 6:
+ case 6: // SO_AT
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1833,7 +1834,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePosition(spriteId, args[0], args[1]);
break;
- case 7:
+ case 7: // SO_AT_IMAGE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1844,7 +1845,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteSourceImage(spriteId, args[0]);
break;
- case 16:
+ case 16: // SO_CLASS
n = getStackList(args, ARRAYSIZE(args));
if (_curSpriteId != 0 && _curMaxSpriteId != 0 && n != 0) {
int *p = &args[n - 1];
@@ -1867,7 +1868,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
} while (--n);
}
break;
- case 32:
+ case 32: // SO_ERASE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1878,7 +1879,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagEraseType(spriteId, args[0]);
break;
- case 38:
+ case 38: // SO_GROUP
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1889,7 +1890,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteGroup(spriteId, args[0]);
break;
- case 40:
+ case 40: // SO_IMAGE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1900,7 +1901,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteImage(spriteId, args[0]);
break;
- case 48:
+ case 48: // SO_MASK
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1911,7 +1912,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteMaskImage(spriteId, args[0]);
break;
- case 49:
+ case 49: // SO_MOVE
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1923,10 +1924,10 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->moveSprite(spriteId, args[0], args[1]);
break;
- case 52:
+ case 52: // SO_NAME
copyScriptString(string, sizeof(string));
break;
- case 53:
+ case 53: // SO_NEW
if (_curSpriteId > _curMaxSpriteId)
break;
spriteId = _curSpriteId;
@@ -1936,7 +1937,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->resetSprite(spriteId);
break;
- case 54:
+ case 54: // SO_NEW_GENERAL_PROPERTY
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1948,7 +1949,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteGeneralProperty(spriteId, args[0], args[1]);
break;
- case 57:
+ case 57: // SO_PALETTE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1959,7 +1960,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePalette(spriteId, args[0]);
break;
- case 59:
+ case 59: // SO_PRIORITY
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -1970,7 +1971,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpritePriority(spriteId, args[0]);
break;
- case 60:
+ case 60: // SO_PROPERTY
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -1997,13 +1998,14 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
_sprite->setSpriteFlagRemapPalette(spriteId, args[0]);
break;
default:
+ warning("Unknown sprite property %d for sprite %d", args[0], spriteId);
break;
}
break;
- case 61:
+ case 61: // SO_RESTART
_sprite->resetTables(true);
break;
- case 65:
+ case 65: // SO_SCALE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2014,7 +2016,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteScale(spriteId, args[0]);
break;
- case 70:
+ case 70: // SO_SHADOW
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2025,7 +2027,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteShadow(spriteId, args[0]);
break;
- case 73:
+ case 73: // SO_STATE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2036,7 +2038,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteImageState(spriteId, args[0]);
break;
- case 74:
+ case 74: // SO_STEP_DIST
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -2048,7 +2050,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteDist(spriteId, args[0], args[1]);
break;
- case 75:
+ case 75: // SO_STEP_DIST_X
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2061,7 +2063,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
_sprite->setSpriteDist(spriteId, args[0], tmp[1]);
}
break;
- case 76:
+ case 76: // SO_STEP_DIST_Y
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2074,7 +2076,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
_sprite->setSpriteDist(spriteId, tmp[0], args[0]);
}
break;
- case 82:
+ case 82: // SO_UPDATE
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2085,7 +2087,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteFlagUpdateType(spriteId, args[0]);
break;
- case 83:
+ case 83: // SO_VARIABLE
args[1] = pop();
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
@@ -2097,7 +2099,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
for (; spriteId <= _curMaxSpriteId; spriteId++)
_sprite->setSpriteUserValue(spriteId, args[0], args[1]);
break;
- case 88:
+ case 88: // SO_IMAGE_ZCLIP
args[0] = pop();
if (_curSpriteId > _curMaxSpriteId)
break;
@@ -2106,9 +2108,9 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
spriteId++;
for (; spriteId <= _curMaxSpriteId; spriteId++)
- _sprite->setSpriteField84(spriteId, args[0]);
+ _sprite->setSpriteZBuffer(spriteId, args[0]);
break;
- case 89:
+ case 89: // SO_NEVER_ZCLIP
if (_curSpriteId > _curMaxSpriteId)
break;
spriteId = _curSpriteId;
@@ -2116,7 +2118,7 @@ void ScummEngine_v100he::o100_setSpriteInfo() {
spriteId++;
for (; spriteId <= _curMaxSpriteId; spriteId++)
- _sprite->setSpriteField84(spriteId, 0);
+ _sprite->setSpriteZBuffer(spriteId, 0);
break;
default:
error("o100_setSpriteInfo: Unknown case %d", subOp);
@@ -2235,40 +2237,43 @@ void ScummEngine_v100he::o100_videoOps() {
byte subOp = fetchScriptByte();
switch (subOp) {
- case 0:
+ case 0: // SO_INIT
memset(_videoParams.filename, 0, sizeof(_videoParams.filename));
_videoParams.status = 0;
_videoParams.flags = 0;
- _videoParams.unk2 = pop();
+ _videoParams.number = pop();
_videoParams.wizResNum = 0;
+
+ if (_videoParams.number != 1 && _videoParams.number != -1)
+ warning("o100_videoOps: number: %d", _videoParams.number);
break;
- case 19:
+ case 19: // SO_CLOSE
_videoParams.status = 19;
break;
- case 40:
+ case 40: // SO_IMAGE
_videoParams.wizResNum = pop();
if (_videoParams.wizResNum)
_videoParams.flags |= 2;
break;
- case 47:
+ case 47: // SO_LOAD
copyScriptString(_videoParams.filename, sizeof(_videoParams.filename));
_videoParams.status = 47;
break;
- case 67:
+ case 67: // SO_SET_FLAGS
_videoParams.flags |= pop();
break;
- case 92:
- if (_videoParams.status == 47) {
+ case 92: // SO_END
+ if (_videoParams.status == 47) { // SO_LOAD
// Start video
if (_videoParams.flags == 0)
_videoParams.flags = 4;
- if (_videoParams.flags == 2) {
+ if (_videoParams.flags & 2) {
VAR(119) = _moviePlay->load(convertFilePath(_videoParams.filename), _videoParams.flags, _videoParams.wizResNum);
} else {
VAR(119) = _moviePlay->load(convertFilePath(_videoParams.filename), _videoParams.flags);
}
- } else if (_videoParams.status == 19) {
+ } else if (_videoParams.status == 19) { // SO_CLOSE
// Stop video
_moviePlay->close();
}
@@ -2468,6 +2473,7 @@ void ScummEngine_v100he::o100_getSpriteGroupInfo() {
pop();
pop();
push(0);
+ warning("STUB: o100_getSpriteGroupInfo, subop 54");
break;
case 59:
spriteGroupId = pop();
diff --git a/engines/scumm/he/script_v90he.cpp b/engines/scumm/he/script_v90he.cpp
index f65d2f6077..f63973e3f1 100644
--- a/engines/scumm/he/script_v90he.cpp
+++ b/engines/scumm/he/script_v90he.cpp
@@ -285,29 +285,29 @@ void ScummEngine_v90he::o90_wizImageOps() {
_wizParams.processMode = 13;
break;
case 142: // HE99+
- _wizParams.field_239D = pop();
- _wizParams.field_2399 = pop();
- _wizParams.field_23A5 = pop();
- _wizParams.field_23A1 = pop();
- copyScriptString(_wizParams.string2, sizeof(_wizParams.string2));
_wizParams.processMode = 15;
+ _wizParams.fontProperties.bgColor = pop();
+ _wizParams.fontProperties.fgColor = pop();
+ _wizParams.fontProperties.size = pop();
+ _wizParams.fontProperties.style = pop();
+ copyScriptString(_wizParams.fontProperties.fontName, sizeof(_wizParams.fontProperties.fontName));
break;
case 143: // HE99+
_wizParams.processMode = 16;
- _wizParams.field_23AD = pop();
- _wizParams.field_23A9 = pop();
- copyScriptString(_wizParams.string1, sizeof(_wizParams.string1));
+ _wizParams.fontProperties.yPos = pop();
+ _wizParams.fontProperties.xPos = pop();
+ copyScriptString(_wizParams.fontProperties.string, sizeof(_wizParams.fontProperties.string));
break;
case 189: // HE99+
_wizParams.processMode = 17;
- _wizParams.field_23CD = pop();
- _wizParams.field_23C9 = pop();
- _wizParams.field_23C5 = pop();
- _wizParams.field_23C1 = pop();
- _wizParams.field_23BD = pop();
- _wizParams.field_23B9 = pop();
- _wizParams.field_23B5 = pop();
- _wizParams.field_23B1 = pop();
+ _wizParams.ellipseProperties.color = pop();
+ _wizParams.ellipseProperties.lod = pop();
+ _wizParams.ellipseProperties.ky = pop();
+ _wizParams.ellipseProperties.kx = pop();
+ _wizParams.ellipseProperties.qy = pop();
+ _wizParams.ellipseProperties.qx = pop();
+ _wizParams.ellipseProperties.py = pop();
+ _wizParams.ellipseProperties.px = pop();
break;
case 196: // HE99+
_wizParams.processMode = 14;
@@ -1412,7 +1412,7 @@ void ScummEngine_v90he::o90_videoOps() {
memset(_videoParams.filename, 0, sizeof(_videoParams.filename));
_videoParams.status = 0;
_videoParams.flags = 0;
- _videoParams.unk2 = pop();
+ _videoParams.number = pop();
_videoParams.wizResNum = 0;
break;
case 14:
diff --git a/engines/scumm/he/sound_he.cpp b/engines/scumm/he/sound_he.cpp
index 9a456b86c0..2e0a03af7f 100644
--- a/engines/scumm/he/sound_he.cpp
+++ b/engines/scumm/he/sound_he.cpp
@@ -470,6 +470,10 @@ void SoundHE::processSoundOpcodes(int sound, byte *codePtr, int *soundVars) {
if (arg == 2) {
val = getSoundVar(sound, val);
}
+ if (!val) {
+ val = 1; // Safeguard for division by zero
+ warning("Incorrect value 0 for processSoundOpcodes() kludge DIV");
+ }
val = getSoundVar(sound, var) / val;
setSoundVar(sound, var, val);
break;
diff --git a/engines/scumm/he/sprite_he.cpp b/engines/scumm/he/sprite_he.cpp
index 245a986531..e3f04dfcf0 100644
--- a/engines/scumm/he/sprite_he.cpp
+++ b/engines/scumm/he/sprite_he.cpp
@@ -386,7 +386,7 @@ int Sprite::getSpriteGeneralProperty(int spriteId, int type) {
case 0x7B:
return _spriteTable[spriteId].imgFlags;
case 0x7D:
- return _spriteTable[spriteId].field_90;
+ return _spriteTable[spriteId].conditionBits;
case 0x7E:
return _spriteTable[spriteId].animProgress;
default:
@@ -739,26 +739,24 @@ void Sprite::setSpriteResetClass(int spriteId) {
_spriteTable[spriteId].classFlags = 0;
}
-void Sprite::setSpriteField84(int spriteId, int value) {
+void Sprite::setSpriteZBuffer(int spriteId, int value) {
assertRange(1, spriteId, _varNumSprites, "sprite");
- _spriteTable[spriteId].field_84 = value;
+ _spriteTable[spriteId].zbufferImage = value;
}
void Sprite::setSpriteGeneralProperty(int spriteId, int type, int value) {
- debug(0, "setSpriteGeneralProperty: spriteId %d type 0x%x", spriteId, type);
+ debug(6, "setSpriteGeneralProperty: spriteId %d type 0x%x value 0x%x", spriteId, type, value);
assertRange(1, spriteId, _varNumSprites, "sprite");
int32 delay;
- // XXX U32 related check
-
switch (type) {
case 0x7B:
_spriteTable[spriteId].imgFlags = value;
_spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
break;
case 0x7D:
- _spriteTable[spriteId].field_90 = value;
+ _spriteTable[spriteId].conditionBits = value;
_spriteTable[spriteId].flags |= kSFChanged | kSFNeedRedraw;
break;
case 0x7E:
@@ -797,9 +795,9 @@ void Sprite::resetSprite(int spriteId) {
_spriteTable[spriteId].sourceImage = 0;
_spriteTable[spriteId].maskImage = 0;
_spriteTable[spriteId].priority = 0;
- _spriteTable[spriteId].field_84 = 0;
+ _spriteTable[spriteId].zbufferImage = 0;
_spriteTable[spriteId].imgFlags = 0;
- _spriteTable[spriteId].field_90 = 0;
+ _spriteTable[spriteId].conditionBits = 0;
if (_vm->_game.heversion >= 100) {
_spriteTable[spriteId].flags &= ~kSFMarkDirty;
@@ -816,7 +814,7 @@ void Sprite::setSpriteImage(int spriteId, int imageNum) {
origResWizStates = _spriteTable[spriteId].imageStateCount;
_spriteTable[spriteId].image = imageNum;
- _spriteTable[spriteId].field_74 = 0;
+ _spriteTable[spriteId].animIndex = 0;
_spriteTable[spriteId].imageState = 0;
if (_spriteTable[spriteId].image) {
@@ -1292,7 +1290,7 @@ void Sprite::processImages(bool arg) {
wiz.spriteId = spi->id;
wiz.spriteGroup = spi->group;
- wiz.field_23EA = spi->field_90;
+ wiz.conditionBits = spi->conditionBits;
spi->curImageState = wiz.img.state = imageState;
spi->curImage = wiz.img.resNum = image;
wiz.processFlags = kWPFNewState | kWPFSetPos;
@@ -1339,9 +1337,9 @@ void Sprite::processImages(bool arg) {
}
if (spr_flags & kSFRemapPalette)
wiz.img.flags |= kWIFRemapPalette;
- if (spi->field_84) {
+ if (spi->zbufferImage) {
wiz.processFlags |= 0x200000;
- wiz.img.field_390 = spi->field_84;
+ wiz.img.zbuffer = spi->zbufferImage;
wiz.img.zorder = spi->priority;
}
if (spi->sourceImage) {
@@ -1419,14 +1417,14 @@ void Sprite::saveOrLoadSpriteData(Serializer *s) {
MKLINE(SpriteInfo, curAngle, sleInt32, VER(48)),
MKLINE(SpriteInfo, curScale, sleInt32, VER(48)),
MKLINE(SpriteInfo, curImgFlags, sleInt32, VER(48)),
- MKLINE(SpriteInfo, field_74, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, animIndex, sleInt32, VER(48)),
MKLINE(SpriteInfo, animSpeed, sleInt32, VER(48)),
MKLINE(SpriteInfo, sourceImage, sleInt32, VER(48)),
MKLINE(SpriteInfo, maskImage, sleInt32, VER(48)),
- MKLINE(SpriteInfo, field_84, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, zbufferImage, sleInt32, VER(48)),
MKLINE(SpriteInfo, classFlags, sleInt32, VER(48)),
MKLINE(SpriteInfo, imgFlags, sleInt32, VER(48)),
- MKLINE(SpriteInfo, field_90, sleInt32, VER(48)),
+ MKLINE(SpriteInfo, conditionBits, sleInt32, VER(48)),
MKEND()
};
diff --git a/engines/scumm/he/sprite_he.h b/engines/scumm/he/sprite_he.h
index e31ccbf790..3ea6bb9f84 100644
--- a/engines/scumm/he/sprite_he.h
+++ b/engines/scumm/he/sprite_he.h
@@ -72,14 +72,14 @@ struct SpriteInfo {
int32 curAngle;
int32 curScale;
int32 curImgFlags;
- int32 field_74;
+ int32 animIndex;
int32 animSpeed;
int32 sourceImage;
int32 maskImage;
- int32 field_84;
+ int32 zbufferImage;
int32 classFlags;
int32 imgFlags;
- int32 field_90;
+ int32 conditionBits;
};
struct SpriteGroup {
@@ -182,7 +182,7 @@ public:
void setSpriteAnimSpeed(int spriteId, int value);
void setSpriteSetClass(int spriteId, int classId, int toggle);
void setSpriteResetClass(int spriteId);
- void setSpriteField84(int spriteId, int value);
+ void setSpriteZBuffer(int spriteId, int value);
void setSpriteGeneralProperty(int spriteId, int type, int value);
void moveGroupMembers(int spriteGroupId, int value1, int value2);
diff --git a/engines/scumm/he/wiz_he.cpp b/engines/scumm/he/wiz_he.cpp
index 9a59609651..0976a532de 100644
--- a/engines/scumm/he/wiz_he.cpp
+++ b/engines/scumm/he/wiz_he.cpp
@@ -31,6 +31,7 @@
#include "scumm/scumm.h"
#include "scumm/util.h"
#include "scumm/he/wiz_he.h"
+#include "scumm/he/moonbase/moonbase.h"
namespace Scumm {
@@ -976,7 +977,7 @@ void Wiz::decompressRawWizImage(uint8 *dst, int dstPitch, int dstType, const uin
}
}
-int Wiz::isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) {
+int Wiz::isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth) {
if (x < 0 || x >= w || y < 0 || y >= h) {
return 0;
}
@@ -1422,19 +1423,19 @@ void Wiz::displayWizImage(WizImage *pwi) {
wi->state = pwi->state;
wi->flags = pwi->flags;
wi->shadow = 0;
- wi->field_390 = 0;
+ wi->zbuffer = 0;
wi->palette = 0;
++_imagesNum;
} else if (pwi->flags & kWIFIsPolygon) {
drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, 0, 0, 0);
} else {
const Common::Rect *r = NULL;
- drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0));
+ drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, 0, 0, 0, r, pwi->flags, 0, _vm->getHEPaletteSlot(0), 0);
}
}
-uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr) {
- debug(3, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d field_390 %d dstResNum %d)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, field_390, dstResNum);
+uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits) {
+ debug(7, "drawWizImage(resNum %d, state %d maskNum %d maskState %d x1 %d y1 %d flags 0x%X zorder %d shadow %d zbuffer %d dstResNum %d conditionBits: 0x%x)", resNum, state, maskNum, maskState, x1, y1, flags, zorder, shadow, zbuffer, dstResNum, conditionBits);
uint8 *dataPtr;
uint8 *dst = NULL;
@@ -1454,10 +1455,7 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
uint32 comp = READ_LE_UINT32(wizh + 0x0);
uint32 width = READ_LE_UINT32(wizh + 0x4);
uint32 height = READ_LE_UINT32(wizh + 0x8);
- debug(3, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height);
-
- uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
- assert(wizd);
+ debug(7, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height);
uint8 *mask = NULL;
if (maskNum) {
@@ -1574,58 +1572,261 @@ uint8 *Wiz::drawWizImage(int resNum, int state, int maskNum, int maskState, int
transColor = (trns == NULL) ? _vm->VAR(_vm->VAR_WIZ_TCOLOR) : -1;
}
+ if (_vm->_game.id == GID_MOONBASE &&
+ resNum == _vm->_moonbase->_fowSentinelImage &&
+ state == _vm->_moonbase->_fowSentinelState &&
+ conditionBits == _vm->_moonbase->_fowSentinelConditionBits) {
+ _vm->_moonbase->renderFOW(dst, dstPitch, dstType, cw, ch, flags);
+ x1 = 0;
+ y1 = 0;
+ width = rScreen.width();
+ height = rScreen.height();
+ } else {
+ drawWizImageEx(dst, dataPtr, mask, dstPitch, dstType, cw, ch, x1, y1, width, height,
+ state, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel, xmapPtr, conditionBits);
+ }
+
+ if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) {
+ Common::Rect rImage(x1, y1, x1 + width, y1 + height);
+ if (rImage.intersects(rScreen)) {
+ rImage.clip(rScreen);
+ if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) {
+ ++rImage.bottom;
+ _vm->markRectAsDirty(kMainVirtScreen, rImage);
+ } else {
+ _vm->restoreBackgroundHE(rImage);
+ }
+ }
+ }
+
+ return dst;
+}
+
+void Wiz::drawWizImageEx(uint8 *dst, uint8 *dataPtr, uint8 *maskPtr, int dstPitch, int dstType,
+ int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect,
+ int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) {
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
+ assert(wizh);
+ uint32 comp = READ_LE_UINT32(wizh + 0x0);
+ uint32 width = READ_LE_UINT32(wizh + 0x4);
+ uint32 height = READ_LE_UINT32(wizh + 0x8);
+ debug(7, "wiz_header.comp = %d wiz_header.w = %d wiz_header.h = %d", comp, width, height);
+
+ uint8 *wizd = _vm->findWrappedBlock(MKTAG('W','I','Z','D'), dataPtr, state, 0);
+ assert(wizd);
+
switch (comp) {
case 0:
- copyRawWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, transColor, _vm->_bytesPerPixel);
+ copyRawWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, transColor, bitDepth);
break;
case 1:
- if (flags & 0x80) {
+ if (flags & kWIFZPlaneOn) {
dst = _vm->getMaskBuffer(0, 0, 1);
dstPitch /= _vm->_bytesPerPixel;
- copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 2);
- } else if (flags & 0x100) {
+ copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 2);
+ } else if (flags & kWIFZPlaneOff) {
dst = _vm->getMaskBuffer(0, 0, 1);
dstPitch /= _vm->_bytesPerPixel;
- copyWizImageWithMask(dst, wizd, dstPitch, cw, ch, x1, y1, width, height, &rScreen, 0, 1);
+ copyWizImageWithMask(dst, wizd, dstPitch, dstw, dsth, srcx, srcy, srcw, srch, rect, 0, 1);
} else {
- copyWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr, xmapPtr, _vm->_bytesPerPixel);
+ copyWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr, xmapPtr, bitDepth);
}
break;
#ifdef USE_RGB_COLOR
case 2:
- if (maskNum) {
- copyMaskWizImage(dst, wizd, mask, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, palPtr);
+ if (maskPtr) {
+ copyMaskWizImage(dst, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, palPtr);
} else {
- copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, transColor);
+ copyRaw16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, transColor);
}
break;
case 4:
- // TODO: Unknown image type
+ copyCompositeWizImage(dst, dataPtr, wizd, maskPtr, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, state, rect, flags, palPtr, transColor, bitDepth, xmapPtr, conditionBits);
break;
case 5:
- copy16BitWizImage(dst, wizd, dstPitch, dstType, cw, ch, x1, y1, width, height, &rScreen, flags, xmapPtr);
+ copy16BitWizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, srcw, srch, rect, flags, xmapPtr);
+ break;
+ case 9:
+ copy555WizImage(dst, wizd, dstPitch, dstType, dstw, dsth, srcx, srcy, rect, conditionBits);
break;
#endif
default:
- error("drawWizImage: Unhandled wiz compression type %d", comp);
+ error("drawWizImageEx: Unhandled wiz compression type %d", comp);
}
+}
- if (!(flags & kWIFBlitToMemBuffer) && dstResNum == 0) {
- Common::Rect rImage(x1, y1, x1 + width, y1 + height);
- if (rImage.intersects(rScreen)) {
- rImage.clip(rScreen);
- if (!(flags & kWIFBlitToFrontVideoBuffer) && (flags & (kWIFBlitToFrontVideoBuffer | kWIFMarkBufferDirty))) {
- ++rImage.bottom;
- _vm->markRectAsDirty(kMainVirtScreen, rImage);
- } else {
- _vm->restoreBackgroundHE(rImage);
+#ifdef USE_RGB_COLOR
+
+void Wiz::copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *compositeInfoBlockPtr, uint8 *maskPtr, int dstPitch, int dstType,
+ int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox,
+ int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits) {
+
+ uint8 *nestedBlockHeader = _vm->heFindResource(MKTAG('N','E','S','T'), wizPtr);
+ assert(nestedBlockHeader);
+
+ uint8 *nestedWizHeader = _vm->heFindResource(MKTAG('M','U','L','T'), nestedBlockHeader);
+ assert(nestedWizHeader);
+
+ uint16 layerCount = READ_LE_UINT16(compositeInfoBlockPtr);
+ compositeInfoBlockPtr += 2;
+
+ uint16 defaultSubConditionBits = (conditionBits & kWMSBReservedBits);
+
+ conditionBits &= ~kWMSBReservedBits;
+
+ for (uint layerCounter = 0; layerCounter < layerCount; layerCounter++) {
+ int cmdSize = READ_LE_UINT16(compositeInfoBlockPtr);
+ uint8 *cmdPtr = compositeInfoBlockPtr + 2;
+
+ compositeInfoBlockPtr += (cmdSize + 2);
+ uint32 layerCmdDataBits = READ_LE_UINT32(cmdPtr);
+ cmdPtr += 4;
+
+ uint32 subConditionBits;
+
+ if (layerCmdDataBits & kWCFConditionBits) {
+ uint32 layerConditionBits = READ_LE_UINT32(cmdPtr);
+ cmdPtr += 4;
+
+ subConditionBits = (layerConditionBits & kWMSBReservedBits);
+ layerConditionBits &= ~kWMSBReservedBits;
+
+ if (subConditionBits == 0)
+ subConditionBits = defaultSubConditionBits;
+
+ uint32 conditionType = (layerConditionBits & kWSPCCTBits);
+ layerConditionBits &= ~kWSPCCTBits;
+
+ switch (conditionType) {
+ case kWSPCCTAnd:
+ if (layerConditionBits != (layerConditionBits & conditionBits))
+ continue;
+ break;
+
+ case kWSPCCTNot:
+ if (layerConditionBits & conditionBits)
+ continue;
+ break;
+
+ case kWSPCCTOr:
+ default:
+ if (!(layerConditionBits & conditionBits))
+ continue;
+ break;
}
+ } else {
+ subConditionBits = defaultSubConditionBits;
}
+
+ uint16 subState;
+ if (layerCmdDataBits & kWCFSubState) {
+ subState = READ_LE_UINT16(cmdPtr);
+ cmdPtr += 2;
+ } else {
+ subState = 0;
+ }
+
+ int16 xPos;
+ if (layerCmdDataBits & kWCFXDelta) {
+ xPos = (int16)READ_LE_UINT16(cmdPtr);
+ cmdPtr += 2;
+ } else {
+ xPos = 0;
+ }
+
+ int16 yPos;
+ if (layerCmdDataBits & kWCFYDelta) {
+ yPos = (int16)READ_LE_UINT16(cmdPtr);
+ cmdPtr += 2;
+ } else {
+ yPos = 0;
+ }
+
+ uint32 drawFlags;
+ if (layerCmdDataBits & kWCFDrawFlags) {
+ drawFlags = READ_LE_UINT32(cmdPtr);
+ cmdPtr += 4;
+ } else {
+ drawFlags = flags;
+ }
+
+ uint srcw1, srch1;
+ if (drawFlags & (kWIFFlipX | kWIFFlipY)) {
+ uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), wizPtr, subState, 0);
+ assert(wizh);
+ srcw1 = READ_LE_UINT32(wizh + 0x4);
+ srch1 = READ_LE_UINT32(wizh + 0x8);
+ }
+
+ if (drawFlags & kWIFFlipX)
+ xPos = (srcw - (xPos + srcw1));
+
+ if (drawFlags & kWIFFlipY)
+ yPos = (srch - (yPos + srch1));
+
+ if (layerCmdDataBits & kWCFSubConditionBits) {
+ subConditionBits = READ_LE_UINT32(cmdPtr);
+ cmdPtr += 4;
+ }
+
+ drawWizImageEx(dst, nestedWizHeader, maskPtr, dstPitch, dstType, dstw, dsth, srcx + xPos, srcy + yPos, srcw, srch,
+ subState, clipBox, drawFlags, palPtr, transColor, bitDepth, xmapPtr, subConditionBits);
+ }
+}
+
+void Wiz::copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType,
+ int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits) {
+
+ int rawROP = conditionBits & kWMSBRopMask;
+ int paramROP = (conditionBits & kWMSBReservedBits) >> kWMSBRopParamRShift;
+
+ switch (rawROP) {
+ default:
+ case 1:
+ rawROP = 1;
+ // MMX_PREMUL_ALPHA_COPY
+ break;
+
+ case 2:
+ //warning("T14: MMX_ADDITIVE");
+ break;
+
+ case 3:
+ warning("T14: MMX_SUBTRACTIVE");
+ break;
+
+ case 4:
+ warning("T14: MMX_CONSTANT_ALPHA");
+ break;
+
+ case 5:
+ //warning("T14: MMX_CHEAP_50_50");
+ break;
+
+ case 6:
+ warning("T14: COPY");
+ break;
+
+ case 7:
+ warning("T14: CHEAP_50_50");
+ break;
+ }
+
+
+ uint32 compID = READ_LE_UINT32(wizd);
+
+ if (compID == 0x12340102) {
+ _vm->_moonbase->blitT14WizImage(dst, dstw, dsth, dstPitch, clipBox, wizd, srcx, srcy, rawROP, paramROP);
+ } else if (compID == 0x12340802) {
+ warning("Distorion codec");
+ } else if (compID == 0x12340902) {
+ error("Unsupported Distortion");
}
- return dst;
}
+#endif
+
struct PolygonDrawData {
struct PolygonArea {
int32 xmin;
@@ -1747,7 +1948,7 @@ void Wiz::captureWizPolygon(int resNum, int maskNum, int maskState, int id1, int
assert(maskNum);
const Common::Rect *r = NULL;
- const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0);
+ const uint8 *src = drawWizImage(maskNum, maskState, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, 0, 0);
getWizImageDim(maskNum, maskState, srcw, srch);
dstw = wp->bound.width();
@@ -1815,7 +2016,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
debug(0, "drawWizPolygonTransform() unhandled flag 0x800000");
}
- srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette));
+ srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, flags, 0, _vm->getHEPaletteSlot(palette), 0);
} else {
assert(_vm->_bytesPerPixel == 1);
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
@@ -1826,7 +2027,7 @@ void Wiz::drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int
}
} else {
if (getWizImageData(resNum, state, 0) != 0) {
- srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette));
+ srcWizBuf = drawWizImage(resNum, state, 0, 0, 0, 0, 0, shadow, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0);
} else {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
@@ -2001,7 +2202,7 @@ void Wiz::flushWizBuffer() {
drawWizPolygon(pwi->resNum, pwi->state, pwi->x1, pwi->flags, pwi->shadow, 0, pwi->palette);
} else {
const Common::Rect *r = NULL;
- drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->field_390, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette));
+ drawWizImage(pwi->resNum, pwi->state, 0, 0, pwi->x1, pwi->y1, pwi->zorder, pwi->shadow, pwi->zbuffer, r, pwi->flags, 0, _vm->getHEPaletteSlot(pwi->palette), 0);
}
}
_imagesNum = 0;
@@ -2023,7 +2224,7 @@ void Wiz::loadWizCursor(int resId, int palette) {
const Common::Rect *r = NULL;
_cursorImage = true;
- uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette));
+ uint8 *cursor = drawWizImage(resId, 0, 0, 0, 0, 0, 0, 0, 0, r, kWIFBlitToMemBuffer, 0, _vm->getHEPaletteSlot(palette), 0);
_cursorImage = false;
int32 cw, ch;
@@ -2073,10 +2274,10 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {
if (params->processFlags & kWPFShadow) {
shadow = params->img.shadow;
}
- int field_390 = 0;
- if (params->processFlags & 0x200000) {
- field_390 = params->img.field_390;
- debug(0, "displayWizComplexImage() unhandled flag 0x200000");
+ int zbuffer = 0;
+ if (params->processFlags & kWPFZBuffer) {
+ zbuffer = params->img.zbuffer;
+ debug(0, "displayWizComplexImage() unhandled flag kWPFZBuffer");
}
const Common::Rect *r = NULL;
if (params->processFlags & kWPFClipBox) {
@@ -2104,19 +2305,19 @@ void Wiz::displayWizComplexImage(const WizParameters *params) {
pwi->state = state;
pwi->flags = flags;
pwi->shadow = shadow;
- pwi->field_390 = field_390;
+ pwi->zbuffer = zbuffer;
pwi->palette = palette;
++_imagesNum;
} else {
if (sourceImage != 0) {
- drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));
+ drawWizImage(params->sourceImage, 0, params->img.resNum, state, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), 0);
} else if (params->processFlags & (kWPFScaled | kWPFRotate)) {
drawWizComplexPolygon(params->img.resNum, state, po_x, po_y, shadow, rotationAngle, scale, r, flags, dstResNum, palette);
} else {
if (flags & kWIFIsPolygon) {
drawWizPolygon(params->img.resNum, state, po_x, flags, shadow, dstResNum, palette);
} else {
- drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, field_390, r, flags, dstResNum, _vm->getHEPaletteSlot(palette));
+ drawWizImage(params->img.resNum, state, 0, 0, po_x, po_y, params->img.zorder, shadow, zbuffer, r, flags, dstResNum, _vm->getHEPaletteSlot(palette), params->conditionBits);
}
}
}
@@ -2501,6 +2702,10 @@ void Wiz::processWizImage(const WizParameters *params) {
void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
+ getWizImageDim(dataPtr, state, w, h);
+}
+
+void Wiz::getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h) {
uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), dataPtr, state, 0);
assert(wizh);
w = READ_LE_UINT32(wizh + 0x4);
@@ -2510,6 +2715,10 @@ void Wiz::getWizImageDim(int resNum, int state, int32 &w, int32 &h) {
void Wiz::getWizImageSpot(int resId, int state, int32 &x, int32 &y) {
uint8 *dataPtr = _vm->getResourceAddress(rtImage, resId);
assert(dataPtr);
+ getWizImageSpot(dataPtr, state, x, y);
+}
+
+void Wiz::getWizImageSpot(uint8 *dataPtr, int state, int32 &x, int32 &y) {
uint8 *spotPtr = _vm->findWrappedBlock(MKTAG('S','P','O','T'), dataPtr, state, 0);
if (spotPtr) {
x = READ_LE_UINT32(spotPtr + 0);
@@ -2547,6 +2756,11 @@ int Wiz::getWizImageData(int resNum, int state, int type) {
int Wiz::getWizImageStates(int resNum) {
const uint8 *dataPtr = _vm->getResourceAddress(rtImage, resNum);
assert(dataPtr);
+
+ return getWizImageStates(dataPtr);
+}
+
+int Wiz::getWizImageStates(const uint8 *dataPtr) {
if (READ_BE_UINT32(dataPtr) == MKTAG('M','U','L','T')) {
const byte *offs, *wrap;
@@ -2565,9 +2779,14 @@ int Wiz::getWizImageStates(int resNum) {
}
int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags) {
- int ret = 0;
uint8 *data = _vm->getResourceAddress(rtImage, resNum);
assert(data);
+
+ return isWizPixelNonTransparent(data, state, x, y, flags);
+}
+
+int Wiz::isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags) {
+ int ret = 0;
uint8 *wizh = _vm->findWrappedBlock(MKTAG('W','I','Z','H'), data, state, 0);
assert(wizh);
int c = READ_LE_UINT32(wizh + 0x0);
@@ -2591,19 +2810,20 @@ int Wiz::isWizPixelNonTransparent(int resNum, int state, int x, int y, int flags
}
break;
case 1:
- ret = isWizPixelNonTransparent(wizd, x, y, w, h, 1);
+ ret = isPixelNonTransparent(wizd, x, y, w, h, 1);
break;
#ifdef USE_RGB_COLOR
case 2:
ret = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR)) != _vm->VAR(_vm->VAR_WIZ_TCOLOR) ? 1 : 0;
break;
- case 4:
- // TODO: Unknown image type
- ret = 1;
- debug(0, "isWizPixelNonTransparent: Unhandled wiz compression type %d", c);
+ case 4: {
+ uint16 color = 0xffff;
+ copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0);
+ ret = color != 0xffff;
break;
+ }
case 5:
- ret = isWizPixelNonTransparent(wizd, x, y, w, h, 2);
+ ret = isPixelNonTransparent(wizd, x, y, w, h, 2);
break;
#endif
default:
@@ -2641,8 +2861,7 @@ uint16 Wiz::getWizPixelColor(int resNum, int state, int x, int y) {
color = getRawWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR));
break;
case 4:
- // TODO: Unknown image type
- debug(0, "getWizPixelColor: Unhandled wiz compression type %d", c);
+ copyCompositeWizImage((byte *)&color, data, wizd, 0, 2, kDstMemory, 1, 1, -x, -y, w, h, state, 0, 0, 0, 0, 2, 0, 0);
break;
case 5:
color = getWizPixelColor(wizd, x, y, w, h, 2, _vm->VAR(_vm->VAR_WIZ_TCOLOR));
diff --git a/engines/scumm/he/wiz_he.h b/engines/scumm/he/wiz_he.h
index 8db438a074..692ad76db5 100644
--- a/engines/scumm/he/wiz_he.h
+++ b/engines/scumm/he/wiz_he.h
@@ -43,10 +43,32 @@ struct WizImage {
int state;
int flags;
int shadow;
- int field_390;
+ int zbuffer;
int palette;
};
+struct FontProperties {
+ byte string[4096];
+ byte fontName[4096];
+ int fgColor;
+ int bgColor;
+ int style;
+ int size;
+ int xPos;
+ int yPos;
+};
+
+struct EllipseProperties {
+ int px;
+ int py;
+ int qx;
+ int qy;
+ int kx;
+ int ky;
+ int lod;
+ int color;
+};
+
struct WizParameters {
int field_0;
byte filename[260];
@@ -77,27 +99,13 @@ struct WizParameters {
int remapNum;
int dstResNum;
uint16 fillColor;
- byte string1[4096];
- byte string2[4096];
- int field_2399;
- int field_239D;
- int field_23A1;
- int field_23A5;
- int field_23A9;
- int field_23AD;
- int field_23B1;
- int field_23B5;
- int field_23B9;
- int field_23BD;
- int field_23C1;
- int field_23C5;
- int field_23C9;
- int field_23CD;
+ FontProperties fontProperties;
+ EllipseProperties ellipseProperties;
Common::Rect box2;
- int field_23DE;
+ int blendFlags;
int spriteId;
int spriteGroup;
- int field_23EA;
+ int conditionBits;
WizImage img;
};
@@ -109,6 +117,9 @@ enum WizImageFlags {
kWIFMarkBufferDirty = 0x10,
kWIFBlitToMemBuffer = 0x20,
kWIFIsPolygon = 0x40,
+ kWIFZPlaneOn = 0x80,
+ kWIFZPlaneOff = 0x100,
+ kWIFUseShadow = 0x200,
kWIFFlipX = 0x400,
kWIFFlipY = 0x800
};
@@ -130,7 +141,31 @@ enum WizProcessFlags {
kWPFFillColor = 0x20000,
kWPFClipBox2 = 0x40000,
kWPFMaskImg = 0x80000,
- kWPFParams = 0x100000
+ kWPFParams = 0x100000,
+ kWPFZBuffer = 0x200000
+};
+
+enum WizCompositeFlags {
+ kWCFConditionBits = 0x01,
+ kWCFSubState = 0x02,
+ kWCFXDelta = 0x04,
+ kWCFYDelta = 0x08,
+ kWCFDrawFlags = 0x10,
+ kWCFSubConditionBits = 0x20
+};
+
+enum WizSpcConditionTypes {
+ kWSPCCTBits = 0xc0000000,
+ kWSPCCTOr = 0x00000000,
+ kWSPCCTAnd = 0x40000000,
+ kWSPCCTNot = 0x80000000
+};
+
+enum WizMoonSystemBits {
+ kWMSBRopMask = 0xff,
+ kWMSBRopParamMask = 0xff00,
+ kWMSBReservedBits = (kWMSBRopMask | kWMSBRopParamMask),
+ kWMSBRopParamRShift = 8
};
enum {
@@ -185,14 +220,19 @@ public:
void remapWizImagePal(const WizParameters *params);
void getWizImageDim(int resNum, int state, int32 &w, int32 &h);
+ void getWizImageDim(uint8 *dataPtr, int state, int32 &w, int32 &h);
int getWizImageStates(int resnum);
+ int getWizImageStates(const uint8 *ptr);
int isWizPixelNonTransparent(int resnum, int state, int x, int y, int flags);
+ int isWizPixelNonTransparent(uint8 *data, int state, int x, int y, int flags);
+ int isPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth);
uint16 getWizPixelColor(int resnum, int state, int x, int y);
int getWizImageData(int resNum, int state, int type);
void flushWizBuffer();
void getWizImageSpot(int resId, int state, int32 &x, int32 &y);
+ void getWizImageSpot(uint8 *data, int state, int32 &x, int32 &y);
void loadWizCursor(int resId, int palette);
void captureWizImage(int resNum, const Common::Rect& r, bool frontBuffer, int compType);
@@ -202,7 +242,8 @@ public:
void displayWizImage(WizImage *pwi);
void processWizImage(const WizParameters *params);
- uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int field_390, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr);
+ uint8 *drawWizImage(int resNum, int state, int maskNum, int maskState, int x1, int y1, int zorder, int shadow, int zbuffer, const Common::Rect *clipBox, int flags, int dstResNum, const uint8 *palPtr, uint32 conditionBits);
+ void drawWizImageEx(uint8 *dst, uint8 *src, uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *rect, int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits);
void drawWizPolygon(int resNum, int state, int id, int flags, int shadow, int dstResNum, int palette);
void drawWizComplexPolygon(int resNum, int state, int po_x, int po_y, int shadow, int angle, int zoom, const Common::Rect *r, int flags, int dstResNum, int palette);
void drawWizPolygonTransform(int resNum, int state, Common::Point *wp, int flags, int shadow, int dstResNum, int palette);
@@ -210,6 +251,12 @@ public:
#ifdef USE_RGB_COLOR
static void copyMaskWizImage(uint8 *dst, const uint8 *src, const uint8 *mask, int dstPitch, int dstType, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, const Common::Rect *rect, int flags, const uint8 *palPtr);
+
+ void copyCompositeWizImage(uint8 *dst, uint8 *wizPtr, uint8 *wizd, uint8 *maskPtr, int dstPitch, int dstType,
+ int dstw, int dsth, int srcx, int srcy, int srcw, int srch, int state, const Common::Rect *clipBox,
+ int flags, const uint8 *palPtr, int transColor, uint8 bitDepth, const uint8 *xmapPtr, uint32 conditionBits);
+ void copy555WizImage(uint8 *dst, uint8 *wizd, int dstPitch, int dstType,
+ int dstw, int dsth, int srcx, int srcy, const Common::Rect *clipBox, uint32 conditionBits);
#endif
static void copyAuxImage(uint8 *dst1, uint8 *dst2, const uint8 *src, int dstw, int dsth, int srcx, int srcy, int srcw, int srch, uint8 bitdepth);
@@ -230,7 +277,6 @@ public:
template<int type> static void write8BitColor(uint8 *dst, const uint8 *src, int dstType, const uint8 *palPtr, const uint8 *xmapPtr, uint8 bitDepth);
static void writeColor(uint8 *dstPtr, int dstType, uint16 color);
- int isWizPixelNonTransparent(const uint8 *data, int x, int y, int w, int h, uint8 bitdepth);
uint16 getWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color);
uint16 getRawWizPixelColor(const uint8 *data, int x, int y, int w, int h, uint8 bitDepth, uint16 color);
void computeWizHistogram(uint32 *histogram, const uint8 *data, const Common::Rect& rCapt);
diff --git a/engines/scumm/module.mk b/engines/scumm/module.mk
index 416a8f7ef9..c56ef7e5f4 100644
--- a/engines/scumm/module.mk
+++ b/engines/scumm/module.mk
@@ -136,9 +136,11 @@ MODULE_OBJS += \
he/logic/basketball.o \
he/logic/football.o \
he/logic/funshop.o \
- he/logic/moonbase.o \
+ he/logic/moonbase_logic.o \
he/logic/puttrace.o \
- he/logic/soccer.o
+ he/logic/soccer.o \
+ he/moonbase/moonbase.o \
+ he/moonbase/moonbase_fow.o
endif
# This module can be built as a plugin
diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h
index e986ae4b47..68e4887b00 100644
--- a/engines/scumm/scumm-md5.h
+++ b/engines/scumm/scumm-md5.h
@@ -1,5 +1,5 @@
/*
- This file was generated by the md5table tool on Mon Mar 28 09:52:54 2016
+ This file was generated by the md5table tool on Sat Apr 30 14:24:41 2016
DO NOT EDIT MANUALLY!
*/
@@ -532,6 +532,7 @@ static const MD5Table md5table[] = {
{ "bf8b52fdd9a69c67f34e8e9fec72661c", "farm", "HE 71", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "bfdf584b01503f0762baded581f6a0a2", "SoccerMLS", "", "", -1, Common::EN_ANY, Common::kPlatformWindows },
{ "c0039ad982999c92d0de81910d640fa0", "freddi", "HE 71", "", 26159, Common::NL_NLD, Common::kPlatformWindows },
+ { "c0c9de81fb965e6cbe77f6e5631ca705", "monkey", "SE Talkie", "Unofficial SE Talkie v1.02", 9135, Common::EN_ANY, Common::kPlatformDOS },
{ "c13225cb1bbd3bc9fe578301696d8021", "monkey", "SEGA", "", -1, Common::EN_ANY, Common::kPlatformSegaCD },
{ "c20848f53c2d48bfacdc840993843765", "freddi2", "HE 80", "Demo", -1, Common::NL_NLD, Common::kPlatformUnknown },
{ "c225bec1b6c0798a2b8c89ac226dc793", "pajama", "HE 101", "", -1, Common::EN_ANY, Common::kPlatformWii },
@@ -672,6 +673,7 @@ static const MD5Table md5table[] = {
{ "f3c5d9bf3f091bd1f18dc1013fba5396", "atlantis", "Steam", "Steam", 638976, Common::EN_ANY, Common::kPlatformWindows },
{ "f3d55aea441e260e9e9c7d2a187097e0", "puttzoo", "", "Demo", 14337, Common::EN_ANY, Common::kPlatformWindows },
{ "f40a7f495f59188ca57a9d1d50301bb6", "puttputt", "HE 60", "Demo", -1, Common::EN_ANY, Common::kPlatformMacintosh },
+ { "f4d20ab4ce19743a646cb48bd93aee72", "monkey2", "SE Talkie", "Unofficial SE Talkie v0.2", 10835, Common::EN_ANY, Common::kPlatformDOS },
{ "f5228b0cc1c19e6ea8268ba2eeb61f60", "freddi", "HE 73", "Demo", -1, Common::FR_FRA, Common::kPlatformWindows },
{ "f73883f13b5a302749a5bad31d909780", "tentacle", "", "CD", -1, Common::DE_DEU, Common::kPlatformMacintosh },
{ "f7635a0e2ab82c9a0f9ace5f232a488f", "catalog", "HE 72", "Demo", -1, Common::EN_ANY, Common::kPlatformWindows },
diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp
index e7118616ba..1f8a85b8c3 100644
--- a/engines/scumm/scumm.cpp
+++ b/engines/scumm/scumm.cpp
@@ -66,6 +66,7 @@
#include "scumm/players/player_v5m.h"
#include "scumm/resource.h"
#include "scumm/he/resource_he.h"
+#include "scumm/he/moonbase/moonbase.h"
#include "scumm/scumm_v0.h"
#include "scumm/scumm_v8.h"
#include "scumm/sound.h"
@@ -733,7 +734,7 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr)
VAR_ACTIVE_VERB = 0xFF;
if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 )
- _game.features |= GF_DEMO;
+ _game.features |= GF_DEMO;
}
ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr)
@@ -832,9 +833,16 @@ ScummEngine_v71he::ScummEngine_v71he(OSystem *syst, const DetectorResult &dr)
_skipProcessActors = 0;
VAR_WIZ_TCOLOR = 0xFF;
+
+ /* Moonbase stuff */
+ _moonbase = 0;
+
+ if (_game.id == GID_MOONBASE)
+ _moonbase = new Moonbase(this);
}
ScummEngine_v71he::~ScummEngine_v71he() {
+ delete _moonbase;
delete _wiz;
}
@@ -874,7 +882,7 @@ ScummEngine_v90he::ScummEngine_v90he(OSystem *syst, const DetectorResult &dr)
memset(_videoParams.filename, 0, sizeof(_videoParams.filename));
_videoParams.status = 0;
_videoParams.flags = 0;
- _videoParams.unk2 = 0;
+ _videoParams.number = 0;
_videoParams.wizResNum = 0;
VAR_NUM_SPRITE_GROUPS = 0xFF;