mirror of
https://github.com/libretro/scummvm.git
synced 2025-03-04 01:07:22 +00:00
MOHAWK: Cleanup Myst script handling
Scripts are now loaded from a central place and are properly freed at the correct time. This fixes a regression from r54152. svn-id: r54309
This commit is contained in:
parent
8ebee136b6
commit
d971396572
@ -29,7 +29,6 @@
|
||||
|
||||
#include "mohawk/graphics.h"
|
||||
#include "mohawk/myst.h"
|
||||
#include "mohawk/myst_scripts.h"
|
||||
#include "mohawk/myst_saveload.h"
|
||||
#include "mohawk/dialogs.h"
|
||||
#include "mohawk/resource.h"
|
||||
@ -703,44 +702,10 @@ void MohawkEngine_Myst::runInitScript() {
|
||||
debugC(kDebugINIT, "Running INIT script");
|
||||
|
||||
Common::SeekableReadStream *initStream = getRawData(ID_INIT, _view.init);
|
||||
|
||||
uint16 scriptCount = initStream->readUint16LE();
|
||||
|
||||
debugC(kDebugINIT, "\tOpcode Count: %d", scriptCount);
|
||||
|
||||
MystScriptEntry *scripts = new MystScriptEntry[scriptCount];
|
||||
|
||||
for (uint16 i = 0; i < scriptCount; i++) {
|
||||
// TODO: u0 is likely variable reference for boolean to
|
||||
// determine whether or not to execute opcode
|
||||
uint16 u0 = initStream->readUint16LE();
|
||||
scripts[i].opcode = initStream->readUint16LE();
|
||||
// If variable indicates not to execute opcode, rewrite to NOP
|
||||
//if (!_varStore->getVar(u0))
|
||||
// scripts[i].opcode = 0xFFFF;
|
||||
scripts[i].var = initStream->readUint16LE();
|
||||
scripts[i].numValues = initStream->readUint16LE();
|
||||
scripts[i].values = new uint16[scripts[i].numValues];
|
||||
|
||||
debugC(kDebugINIT, "\tu0: %d", u0);
|
||||
debugC(kDebugINIT, "\tOpcode %d: %s", i, _scriptParser->getOpcodeDesc(scripts[i].opcode));
|
||||
debugC(kDebugINIT, "\t\tUses Variable %d", scripts[i].var);
|
||||
debugC(kDebugINIT, "\t\tHas %d Arguments:", scripts[i].numValues);
|
||||
|
||||
for (uint16 j = 0; j < scripts[i].numValues; j++) {
|
||||
scripts[i].values[j] = initStream->readUint16LE();
|
||||
debugC(kDebugINIT, "\t\tArgument %d: %d", j, scripts[i].values[j]);
|
||||
}
|
||||
}
|
||||
|
||||
MystScript script = _scriptParser->readScript(initStream, kMystScriptInit);
|
||||
delete initStream;
|
||||
|
||||
_scriptParser->runScript(scriptCount, scripts);
|
||||
|
||||
for (uint16 i = 0; i < scriptCount; i++)
|
||||
delete[] scripts[i].values;
|
||||
delete[] scripts;
|
||||
|
||||
_scriptParser->runScript(script);
|
||||
_gfx->updateScreen();
|
||||
}
|
||||
|
||||
@ -753,49 +718,10 @@ void MohawkEngine_Myst::runExitScript() {
|
||||
debugC(kDebugEXIT, "Running EXIT script");
|
||||
|
||||
Common::SeekableReadStream *exitStream = getRawData(ID_EXIT, _view.exit);
|
||||
|
||||
uint16 scriptCount = exitStream->readUint16LE();
|
||||
|
||||
debugC(kDebugEXIT, "\tOpcode Count: %d", scriptCount);
|
||||
|
||||
MystScriptEntry *scripts = new MystScriptEntry[scriptCount];
|
||||
|
||||
for (uint16 i = 0; i < scriptCount; i++) {
|
||||
// TODO: u0 is likely variable reference for boolean to
|
||||
// to determine whether or not to execute opcode (i.e. door
|
||||
// close noises only when door is open).
|
||||
uint16 u0 = exitStream->readUint16LE();
|
||||
scripts[i].opcode = exitStream->readUint16LE();
|
||||
// If variable indicates not to execute opcode, rewrite to NOP
|
||||
//if (!_varStore->getVar(u0))
|
||||
// scripts[i].opcode = 0xFFFF;
|
||||
scripts[i].var = exitStream->readUint16LE();
|
||||
scripts[i].numValues = exitStream->readUint16LE();
|
||||
scripts[i].values = new uint16[scripts[i].numValues];
|
||||
|
||||
debugC(kDebugEXIT, "\tu0: %d", u0);
|
||||
debugC(kDebugEXIT, "\tOpcode %d: %s", i, _scriptParser->getOpcodeDesc(scripts[i].opcode));
|
||||
debugC(kDebugEXIT, "\t\tUses Variable %d", scripts[i].var);
|
||||
debugC(kDebugEXIT, "\t\tHas %d Arguments:", scripts[i].numValues);
|
||||
|
||||
for (uint16 j = 0; j < scripts[i].numValues; j++) {
|
||||
scripts[i].values[j] = exitStream->readUint16LE();
|
||||
debugC(kDebugEXIT, "\t\tArgument %d: %d", j, scripts[i].values[j]);
|
||||
}
|
||||
|
||||
uint16 u1 = exitStream->readUint16LE();
|
||||
if (u1 != 1)
|
||||
warning("Myst EXIT u1 not 1");
|
||||
}
|
||||
|
||||
MystScript script = _scriptParser->readScript(exitStream, kMystScriptExit);
|
||||
delete exitStream;
|
||||
|
||||
_scriptParser->runScript(scriptCount, scripts);
|
||||
|
||||
for (uint16 i = 0; i < scriptCount; i++)
|
||||
delete[] scripts[i].values;
|
||||
delete[] scripts;
|
||||
|
||||
_scriptParser->runScript(script);
|
||||
_gfx->updateScreen();
|
||||
}
|
||||
|
||||
@ -1059,40 +985,11 @@ void MystResource::handleMouseUp() {
|
||||
MystResourceType5::MystResourceType5(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent) : MystResource(vm, rlstStream, parent) {
|
||||
debugC(kDebugResource, "\tResource Type 5 Script:");
|
||||
|
||||
_scripts = NULL;
|
||||
_scriptCount = rlstStream->readUint16LE();
|
||||
|
||||
debugC(kDebugResource, "\tOpcode Count: %d", _scriptCount);
|
||||
|
||||
if (_scriptCount == 0)
|
||||
return;
|
||||
|
||||
_scripts = new MystScriptEntry[_scriptCount];
|
||||
for (uint16 i = 0; i < _scriptCount; i++) {
|
||||
_scripts[i].opcode = rlstStream->readUint16LE();
|
||||
_scripts[i].var = rlstStream->readUint16LE();
|
||||
_scripts[i].numValues = rlstStream->readUint16LE();
|
||||
_scripts[i].values = new uint16[_scripts[i].numValues];
|
||||
|
||||
debugC(kDebugResource, "\tOpcode %d: %s", i, _vm->_scriptParser->getOpcodeDesc(_scripts[i].opcode));
|
||||
debugC(kDebugResource, "\t\tUses Variable %d", _scripts[i].var);
|
||||
debugC(kDebugResource, "\t\tHas %d Arguments:", _scripts[i].numValues);
|
||||
|
||||
for (uint16 j = 0; j < _scripts[i].numValues; j++) {
|
||||
_scripts[i].values[j] = rlstStream->readUint16LE();
|
||||
debugC(kDebugResource, "\t\tArgument %d: %d", j, _scripts[i].values[j]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
MystResourceType5::~MystResourceType5() {
|
||||
for (uint16 i = 0; i < _scriptCount; i++)
|
||||
delete[] _scripts[i].values;
|
||||
delete[] _scripts;
|
||||
_script = vm->_scriptParser->readScript(rlstStream, kMystScriptNormal);
|
||||
}
|
||||
|
||||
void MystResourceType5::handleMouseUp() {
|
||||
_vm->_scriptParser->runScript(_scriptCount, _scripts, this);
|
||||
_vm->_scriptParser->runScript(_script, this);
|
||||
}
|
||||
|
||||
// In Myst/Making of Myst, the paths are hardcoded ala Windows style without extension. Convert them.
|
||||
|
@ -30,6 +30,7 @@
|
||||
#include "mohawk/mohawk.h"
|
||||
#include "mohawk/resource_cache.h"
|
||||
#include "mohawk/myst_vars.h"
|
||||
#include "mohawk/myst_scripts.h"
|
||||
|
||||
#include "gui/saveload.h"
|
||||
|
||||
@ -147,13 +148,6 @@ struct MystView {
|
||||
uint16 exit;
|
||||
};
|
||||
|
||||
struct MystScriptEntry {
|
||||
uint16 opcode;
|
||||
uint16 var;
|
||||
uint16 numValues;
|
||||
uint16 *values;
|
||||
};
|
||||
|
||||
class MystResource {
|
||||
public:
|
||||
MystResource(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
|
||||
@ -188,12 +182,10 @@ protected:
|
||||
class MystResourceType5 : public MystResource {
|
||||
public:
|
||||
MystResourceType5(MohawkEngine_Myst *vm, Common::SeekableReadStream *rlstStream, MystResource *parent);
|
||||
virtual ~MystResourceType5();
|
||||
void handleMouseUp();
|
||||
|
||||
protected:
|
||||
uint16 _scriptCount;
|
||||
MystScriptEntry *_scripts;
|
||||
MystScript _script;
|
||||
};
|
||||
|
||||
class MystResourceType6 : public MystResourceType5 {
|
||||
|
@ -33,6 +33,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 +91,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 +110,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 +130,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 +169,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 +210,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 +225,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 +264,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 +298,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,
|
||||
|
@ -26,6 +26,7 @@
|
||||
#ifndef MYST_SCRIPTS_H
|
||||
#define MYST_SCRIPTS_H
|
||||
|
||||
#include "common/ptr.h"
|
||||
#include "common/scummsys.h"
|
||||
#include "common/util.h"
|
||||
|
||||
@ -34,16 +35,39 @@ namespace Mohawk {
|
||||
#define DECLARE_OPCODE(x) void x(uint16 op, uint16 var, uint16 argc, uint16 *argv)
|
||||
|
||||
class MohawkEngine_Myst;
|
||||
struct MystScriptEntry;
|
||||
class MystResource;
|
||||
|
||||
enum MystScriptType {
|
||||
kMystScriptNone,
|
||||
kMystScriptNormal,
|
||||
kMystScriptInit,
|
||||
kMystScriptExit
|
||||
};
|
||||
|
||||
struct MystScriptEntry {
|
||||
MystScriptEntry();
|
||||
~MystScriptEntry();
|
||||
|
||||
MystScriptType type;
|
||||
uint16 u0;
|
||||
uint16 opcode;
|
||||
uint16 var;
|
||||
uint16 argc;
|
||||
uint16 *argv;
|
||||
uint16 u1;
|
||||
};
|
||||
|
||||
typedef Common::SharedPtr<Common::Array<MystScriptEntry> > MystScript;
|
||||
|
||||
class MystScriptParser {
|
||||
public:
|
||||
MystScriptParser(MohawkEngine_Myst *vm);
|
||||
~MystScriptParser();
|
||||
|
||||
void runScript(uint16 scriptCount, MystScriptEntry *scripts, MystResource* invokingResource = NULL);
|
||||
void runScript(MystScript script, MystResource *invokingResource = NULL);
|
||||
void runOpcode(uint16 op, uint16 var = 0, uint16 argc = 0, uint16 *argv = NULL);
|
||||
const char *getOpcodeDesc(uint16 op);
|
||||
MystScript readScript(Common::SeekableReadStream *stream, MystScriptType type);
|
||||
|
||||
void disableInitOpcodes();
|
||||
void runPersistentOpcodes();
|
||||
|
Loading…
x
Reference in New Issue
Block a user