aboutsummaryrefslogtreecommitdiff
path: root/engines/mohawk/myst_scripts.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/mohawk/myst_scripts.cpp')
-rw-r--r--engines/mohawk/myst_scripts.cpp137
1 files changed, 98 insertions, 39 deletions
diff --git a/engines/mohawk/myst_scripts.cpp b/engines/mohawk/myst_scripts.cpp
index a8cd643e2c..b67c109acc 100644
--- a/engines/mohawk/myst_scripts.cpp
+++ b/engines/mohawk/myst_scripts.cpp
@@ -23,6 +23,7 @@
*
*/
+#include "mohawk/cursors.h"
#include "mohawk/myst.h"
#include "mohawk/graphics.h"
#include "mohawk/myst_scripts.h"
@@ -33,6 +34,19 @@
namespace Mohawk {
+MystScriptEntry::MystScriptEntry() {
+ type = kMystScriptNone;
+ var = 0;
+ argc = 0;
+ argv = 0;
+ u0 = 0;
+ u1 = 0;
+}
+
+MystScriptEntry::~MystScriptEntry() {
+ delete[] argv;
+}
+
const uint8 stack_map[8] = {
kSeleniticStack,
kStoneshipStack,
@@ -78,12 +92,12 @@ void MystScriptParser::setupOpcodes() {
OPCODE(2, altDest),
OPCODE(3, takePage),
OPCODE(4, opcode_4),
- // TODO: Opcode 5 Not Present
+ // Opcode 5 Not Present
OPCODE(6, opcode_6),
OPCODE(7, opcode_7),
OPCODE(8, opcode_8),
OPCODE(9, opcode_9),
- // TODO: Opcode 10 to 11 Not Present
+ // Opcode 10 to 11 Not Present
OPCODE(12, altDest),
OPCODE(13, altDest),
OPCODE(14, opcode_14),
@@ -97,7 +111,7 @@ void MystScriptParser::setupOpcodes() {
OPCODE(22, opcode_22),
OPCODE(23, opcode_23),
OPCODE(24, playSound),
- // TODO: Opcode 25 Not Present
+ // Opcode 25 Not Present
OPCODE(26, opcode_26),
OPCODE(27, playSoundBlocking),
OPCODE(28, opcode_28),
@@ -117,9 +131,9 @@ void MystScriptParser::setupOpcodes() {
OPCODE(42, opcode_42),
OPCODE(43, opcode_43),
OPCODE(44, opcode_44),
- // TODO: Opcode 45 Not Present
+ // Opcode 45 Not Present
OPCODE(46, opcode_46),
- // TODO: Opcodes 47 to 99 Not Present
+ // Opcodes 47 to 99 Not Present
// "Stack-Specific" Opcodes
OPCODE(100, opcode_100),
@@ -156,18 +170,18 @@ void MystScriptParser::setupOpcodes() {
OPCODE(131, opcode_131),
OPCODE(132, opcode_132),
OPCODE(133, opcode_133),
- // TODO: Opcodes 134 to 146 Not Present
+ // Opcodes 134 to 146 Not Present
OPCODE(147, opcode_147),
- // TODO: Opcodes 148 to 163 Not Present
+ // Opcodes 148 to 163 Not Present
OPCODE(164, opcode_164),
- // TODO: Opcodes 165 to 168 Not Present
+ // Opcodes 165 to 168 Not Present
OPCODE(169, opcode_169),
- // TODO: Opcodes 170 to 181 Not Present
+ // Opcodes 170 to 181 Not Present
OPCODE(182, opcode_182),
OPCODE(183, opcode_183),
OPCODE(184, opcode_184),
OPCODE(185, opcode_185),
- // TODO: Opcodes 186 to 195 Not Present
+ // Opcodes 186 to 195 Not Present
OPCODE(196, opcode_196), // Demo only
OPCODE(197, opcode_197), // Demo only
OPCODE(198, opcode_198),
@@ -197,7 +211,7 @@ void MystScriptParser::setupOpcodes() {
OPCODE(220, opcode_220),
OPCODE(221, opcode_221),
OPCODE(222, opcode_222),
- // TODO: Opcodes 223 to 297 Not Present
+ // Opcodes 223 to 297 Not Present
OPCODE(298, opcode_298), // Demo only
OPCODE(299, opcode_299), // Demo only
@@ -212,9 +226,9 @@ void MystScriptParser::setupOpcodes() {
OPCODE(307, opcode_307),
OPCODE(308, opcode_308),
OPCODE(309, opcode_309),
- // TODO: Opcodes 310 to 311 Not Present
+ // Opcodes 310 to 311 Not Present
OPCODE(312, opcode_312),
- // TODO: Opcodes 313 and greater Not Present
+ // Opcodes 313 and greater Not Present
OPCODE(0xFFFF, NOP)
};
@@ -251,13 +265,14 @@ void MystScriptParser::runPersistentOpcodes() {
opcode_212_run();
}
-void MystScriptParser::runScript(uint16 scriptCount, MystScriptEntry *scripts, MystResource *invokingResource) {
+void MystScriptParser::runScript(MystScript script, MystResource *invokingResource) {
_invokingResource = invokingResource;
- debugC(kDebugScript, "Script Count: %d", scriptCount);
- for (uint16 i = 0; i < scriptCount; i++) {
- debugC(kDebugScript, "\tOpcode %d: %d", i, scripts[i].opcode);
- runOpcode(scripts[i].opcode, scripts[i].var, scripts[i].numValues, scripts[i].values);
+ debugC(kDebugScript, "Script Size: %d", script->size());
+ for (uint16 i = 0; i < script->size(); i++) {
+ MystScriptEntry &entry = script->operator[](i);
+ debugC(kDebugScript, "\tOpcode %d: %d", i, entry.opcode);
+ runOpcode(entry.opcode, entry.var, entry.argc, entry.argv);
}
}
@@ -284,6 +299,41 @@ const char *MystScriptParser::getOpcodeDesc(uint16 op) {
return "";
}
+MystScript MystScriptParser::readScript(Common::SeekableReadStream *stream, MystScriptType type) {
+ assert(stream);
+ assert(type != kMystScriptNone);
+
+ MystScript script = MystScript(new Common::Array<MystScriptEntry>());
+
+ uint16 opcodeCount = stream->readUint16LE();
+ script->resize(opcodeCount);
+
+ for (uint16 i = 0; i < opcodeCount; i++) {
+ MystScriptEntry &entry = script->operator[](i);
+ entry.type = type;
+
+ // u0 only exists in INIT and EXIT scripts
+ if (type != kMystScriptNormal)
+ entry.u0 = stream->readUint16LE();
+
+ entry.opcode = stream->readUint16LE();
+ entry.var = stream->readUint16LE();
+ entry.argc = stream->readUint16LE();
+
+ if (entry.argc > 0) {
+ entry.argv = new uint16[entry.argc];
+ for (uint16 j = 0; j < entry.argc; j++)
+ entry.argv[j] = stream->readUint16LE();
+ }
+
+ // u1 exists only in EXIT scripts
+ if (type == kMystScriptExit)
+ entry.u1 = stream->readUint16LE();
+ }
+
+ return script;
+}
+
// NOTE: Check to be used on Opcodes where var is thought
// not to be used. This emits a warning if var is nonzero.
// It is possible that the opcode does use var 0 in this case,
@@ -294,17 +344,16 @@ void MystScriptParser::varUnusedCheck(uint16 op, uint16 var) {
}
void MystScriptParser::unknown(uint16 op, uint16 var, uint16 argc, uint16 *argv) {
- // NOTE: printf used here instead of debug, so unknown opcodes are always reported...
- printf("Unimplemented opcode 0x%02x (%d)\n", op, op);
- printf("\tUses var %d\n", var);
- printf("\tArg count = %d\n", argc);
- if (argc)
- printf("\tArgs: ");
- for (uint16 i = 0; i < argc; i++) {
- if (i == argc - 1)
- printf("%d\n", argv[i]);
- else
- printf("%d, ", argv[i]);
+ warning("Unimplemented opcode 0x%02x (%d)", op, op);
+ warning("\tUses var %d", var);
+ warning("\tArg count = %d", argc);
+ if (argc) {
+ Common::String str;
+ str += Common::String::format("%d", argv[0]);
+ for (uint16 i = 1; i < argc; i++) {
+ str += Common::String::format(", %d", argv[i]);
+ }
+ warning("\tArgs: %s\n", str.c_str());
}
}
@@ -382,9 +431,10 @@ void MystScriptParser::opcode_4(uint16 op, uint16 var, uint16 argc, uint16 *argv
// the general case, rather than this image blit...
uint16 var_value = _vm->_varStore->getVar(var);
if (var_value < _vm->_view.scriptResCount) {
- if (_vm->_view.scriptResources[var_value].type == 1) // TODO: Add Symbols for Types
+ if (_vm->_view.scriptResources[var_value].type == 1) { // TODO: Add Symbols for Types
_vm->_gfx->copyImageToScreen(_vm->_view.scriptResources[var_value].id, Common::Rect(0, 0, 544, 333));
- else
+ _vm->_gfx->updateScreen();
+ } else
warning("Opcode %d: Script Resource %d Type Not Image", op, var_value);
} else
warning("Opcode %d: var %d value %d outside Script Resource Range %d", op, var, var_value, _vm->_view.scriptResCount);
@@ -953,7 +1003,7 @@ void MystScriptParser::opcode_35(uint16 op, uint16 var, uint16 argc, uint16 *arg
debugC(kDebugScript, "\tdelay: %d", delay);
_vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333));
- _vm->_system->updateScreen();
+ _vm->_gfx->updateScreen();
_vm->_system->delayMillis(delay * 100);
_vm->changeToCard(cardId);
} else
@@ -968,7 +1018,7 @@ void MystScriptParser::changeCursor(uint16 op, uint16 var, uint16 argc, uint16 *
debugC(kDebugScript, "Cursor: %d", argv[0]);
// TODO: Not sure if this needs to change mainCursor or similar...
- _vm->_gfx->changeCursor(argv[0]);
+ _vm->_cursor->setCursor(argv[0]);
} else
unknown(op, var, argc, argv);
}
@@ -978,7 +1028,7 @@ void MystScriptParser::hideCursor(uint16 op, uint16 var, uint16 argc, uint16 *ar
if (argc == 0) {
debugC(kDebugScript, "Opcode %d: Hide Cursor", op);
- _vm->_gfx->hideCursor();
+ _vm->_cursor->hideCursor();
} else
unknown(op, var, argc, argv);
}
@@ -988,7 +1038,7 @@ void MystScriptParser::showCursor(uint16 op, uint16 var, uint16 argc, uint16 *ar
if (argc == 0) {
debugC(kDebugScript, "Opcode %d: Show Cursor", op);
- _vm->_gfx->showCursor();
+ _vm->_cursor->showCursor();
} else
unknown(op, var, argc, argv);
}
@@ -1529,7 +1579,7 @@ void MystScriptParser::opcode_102(uint16 op, uint16 var, uint16 argc, uint16 *ar
debugC(kDebugScript, "\tstartTime: %d", startTime);
debugC(kDebugScript, "\tendTime: %d", endTime);
- printf("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
+ warning("TODO: Opcode %d Movie Time Index %d to %d", op, startTime, endTime);
// TODO: Need version of playMovie blocking which allows selection
// of start and finish points.
_vm->_video->playMovie(_vm->wrapMovieFilename("bkroom", kStoneshipStack), 159, 99);
@@ -1686,6 +1736,7 @@ void MystScriptParser::opcode_104(uint16 op, uint16 var, uint16 argc, uint16 *ar
// TODO: Need to load the image ids from Script Resources structure of VIEW
for (uint16 imageId = 3595; imageId <= 3601; imageId++) {
_vm->_gfx->copyImageToScreen(imageId, rect);
+ _vm->_gfx->updateScreen();
_vm->_system->delayMillis(50);
}
@@ -2488,7 +2539,7 @@ void MystScriptParser::opcode_121(uint16 op, uint16 var, uint16 argc, uint16 *ar
uint16 startTime = argv[0];
uint16 endTime = argv[1];
- printf("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
+ warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, startTime, endTime);
// TODO: Need version of playMovie blocking which allows selection
// of start and finish points.
_vm->_video->playMovie(_vm->wrapMovieFilename("ewindow", kMechanicalStack), 253, 0);
@@ -2516,6 +2567,7 @@ void MystScriptParser::opcode_122(uint16 op, uint16 var, uint16 argc, uint16 *ar
// TODO: Need to load the image ids from Script Resources structure of VIEW
for (uint16 imageId = 3601; imageId >= 3595; imageId--) {
_vm->_gfx->copyImageToScreen(imageId, rect);
+ _vm->_gfx->updateScreen();
_vm->_system->delayMillis(50);
}
@@ -2550,7 +2602,7 @@ void MystScriptParser::opcode_123(uint16 op, uint16 var, uint16 argc, uint16 *ar
uint16 start_time = argv[0];
uint16 end_time = argv[1];
- printf("TODO: Opcode %d Movie Time Index %d to %d\n", op, start_time, end_time);
+ warning("TODO: Opcode %d Movie Time Index %d to %d\n", op, start_time, end_time);
// TODO: Need version of playMovie blocking which allows selection
// of start and finish points.
// TODO: Not 100% sure about movie position
@@ -3143,8 +3195,10 @@ void MystScriptParser::opcode_200_run() {
else
rect = Common::Rect(0, 0, 544, 333);
- if (curImageIndex != lastImageIndex)
+ if (curImageIndex != lastImageIndex) {
_vm->_gfx->copyImageToScreen(g_opcode200Parameters.imageBaseId + curImageIndex, rect);
+ _vm->_gfx->updateScreen();
+ }
// TODO: Comparison with original engine shows that this simple solution
// may not be the correct one and the choice of which sound
@@ -3166,6 +3220,7 @@ void MystScriptParser::opcode_200_run() {
// Note: The modulus by 6 is because the 6th image is the one at imageBaseId
_vm->_gfx->copyImageToScreen(g_opcode200Parameters.imageBaseId + curImageIndex % 6, Common::Rect(0, 0, 544, 333));
+ _vm->_gfx->updateScreen();
_vm->_varStore->setVar(g_opcode200Parameters.var, curImageIndex + 1);
g_opcode200Parameters.lastCardTime = _vm->_system->getMillis();
@@ -3380,6 +3435,7 @@ void MystScriptParser::opcode_201(uint16 op, uint16 var, uint16 argc, uint16 *ar
case kIntroStack:
_vm->_system->delayMillis(4 * 1000);
_vm->_gfx->copyImageToScreen(4, Common::Rect(0, 0, 544, 333));
+ _vm->_gfx->updateScreen();
// TODO : Wait until video ends, then change to card 5
break;
case kSeleniticStack:
@@ -4328,6 +4384,8 @@ void MystScriptParser::opcode_211_run(void) {
lastGridState[i] = gridState[i];
}
+ _vm->_gfx->updateScreen();
+
// Var 23 contains boolean for whether pattern matches correct book pattern i.e. Pattern 158
if (gridState[0] == 0xc3 && gridState[1] == 0x6b && gridState[2] == 0xa3 &&
gridState[3] == 0x93 && gridState[4] == 0xcc && gridState[5] == 0xfa)
@@ -4657,6 +4715,7 @@ void MystScriptParser::opcode_298(uint16 op, uint16 var, uint16 argc, uint16 *ar
_vm->_system->delayMillis(20 * 1000);
for (uint16 imageId = 3001; imageId <= 3012; imageId++) {
_vm->_gfx->copyImageToScreen(imageId, Common::Rect(0, 0, 544, 333));
+ _vm->_gfx->updateScreen();
_vm->_system->delayMillis(5 * 1000);
}
break;