[Scummvm-git-logs] scummvm master -> ce551c1f1c5c8dae51b4d64181ee9717df03c7d8

elasota noreply at scummvm.org
Wed Mar 8 02:40:56 UTC 2023


This automated email contains information about 1 new commit which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .

Summary:
ce551c1f1c VCRUISE: Add initial save game support and enough script ops to enter second area.


Commit: ce551c1f1c5c8dae51b4d64181ee9717df03c7d8
    https://github.com/scummvm/scummvm/commit/ce551c1f1c5c8dae51b4d64181ee9717df03c7d8
Author: elasota (ejlasota at gmail.com)
Date: 2023-03-07T21:38:56-05:00

Commit Message:
VCRUISE: Add initial save game support and enough script ops to enter second area.

Changed paths:
    engines/vcruise/POTFILES
    engines/vcruise/metaengine.cpp
    engines/vcruise/runtime.cpp
    engines/vcruise/runtime.h
    engines/vcruise/script.cpp
    engines/vcruise/script.h
    engines/vcruise/vcruise.cpp
    engines/vcruise/vcruise.h


diff --git a/engines/vcruise/POTFILES b/engines/vcruise/POTFILES
index e62f9068bc3..a64c348f1b5 100644
--- a/engines/vcruise/POTFILES
+++ b/engines/vcruise/POTFILES
@@ -1,2 +1,3 @@
 engines/vcruise/metaengine.cpp
+engines/vcruise/runtime.cpp
 engines/vcruise/vcruise.cpp
diff --git a/engines/vcruise/metaengine.cpp b/engines/vcruise/metaengine.cpp
index 56c5535e8fb..f19018985b0 100644
--- a/engines/vcruise/metaengine.cpp
+++ b/engines/vcruise/metaengine.cpp
@@ -64,6 +64,13 @@ public:
 };
 
 bool VCruiseMetaEngine::hasFeature(MetaEngineFeature f) const {
+	switch (f) {
+	case kSupportsLoadingDuringStartup:
+		return true;
+	default:
+		break;
+	}
+
 	return checkExtendedSaves(f);
 }
 
diff --git a/engines/vcruise/runtime.cpp b/engines/vcruise/runtime.cpp
index e955d426bfb..5f7101dbbba 100644
--- a/engines/vcruise/runtime.cpp
+++ b/engines/vcruise/runtime.cpp
@@ -25,6 +25,7 @@
 #include "common/random.h"
 #include "common/system.h"
 #include "common/stream.h"
+#include "common/translation.h"
 
 #include "graphics/cursorman.h"
 #include "graphics/font.h"
@@ -37,6 +38,8 @@
 
 #include "video/avi_decoder.h"
 
+#include "gui/message.h"
+
 #include "vcruise/audio_player.h"
 #include "vcruise/runtime.h"
 #include "vcruise/script.h"
@@ -185,7 +188,7 @@ void Runtime::loadCursors(const char *exeName) {
 
 		_namedCursors["CUR_TYL"] = 22;		// Tyl = back
 		//_namedCursors["CUR_NIC"] = ?		// Nic = nothing
-		//_namedCursors["CUR_WEZ"] = 50		// Wez = call? FIXME
+		_namedCursors["CUR_WEZ"] = 90;		// Wez = call?  This is the pick-up hand.
 		_namedCursors["CUR_LUPA"] = 21;		// Lupa = magnifier, could be 36 too?
 		_namedCursors["CUR_NAC"] = 13;		// Nac = top?  Not sure.  But this is the finger pointer.
 		_namedCursors["CUR_PRZOD"] = 1;		// Przod = forward
@@ -219,7 +222,7 @@ bool Runtime::runFrame() {
 		moreActions = false;
 		switch (_gameState) {
 		case kGameStateBoot:
-			moreActions = bootGame();
+			moreActions = bootGame(true);
 			break;
 		case kGameStateQuit:
 			return false;
@@ -262,18 +265,22 @@ bool Runtime::runFrame() {
 	return true;
 }
 
-bool Runtime::bootGame() {
+bool Runtime::bootGame(bool newGame) {
+	assert(_gameState == kGameStateBoot);
+
 	debug(1, "Booting V-Cruise game...");
 	loadIndex();
 	debug(1, "Index loaded OK");
 
 	_gameState = kGameStateIdle;
 
-	if (_gameID == GID_REAH) {
-		// TODO: Change to the logo instead (0xb1) instead when menus are implemented
-		changeToScreen(1, 0xb0);
-	} else
-		error("Couldn't figure out what screen to start on");
+	if (newGame) {
+		if (_gameID == GID_REAH) {
+			// TODO: Change to the logo instead (0xb1) instead when menus are implemented
+			changeToScreen(1, 0xb0);
+		} else
+			error("Couldn't figure out what screen to start on");
+	}
 
 	return true;
 }
@@ -708,20 +715,37 @@ bool Runtime::runScript() {
 			DISPATCH_OP(Static);
 			DISPATCH_OP(VarLoad);
 			DISPATCH_OP(VarStore);
+			DISPATCH_OP(ItemCheck);
+			DISPATCH_OP(ItemCRSet);
+			DISPATCH_OP(ItemSRSet);
+			DISPATCH_OP(ItemRSet);
 			DISPATCH_OP(SetCursor);
 			DISPATCH_OP(SetRoom);
 			DISPATCH_OP(LMB);
 			DISPATCH_OP(LMB1);
 			DISPATCH_OP(SoundS1);
+			DISPATCH_OP(SoundS2);
+			DISPATCH_OP(SoundS3);
+			DISPATCH_OP(SoundL1);
 			DISPATCH_OP(SoundL2);
+			DISPATCH_OP(SoundL3);
+			DISPATCH_OP(3DSoundL2);
+			DISPATCH_OP(Range);
+			DISPATCH_OP(AddXSound);
+			DISPATCH_OP(ClrXSound);
+			DISPATCH_OP(StopSndLA);
+			DISPATCH_OP(StopSndLO);
 
 			DISPATCH_OP(Music);
 			DISPATCH_OP(MusicUp);
 			DISPATCH_OP(MusicDn);
+			DISPATCH_OP(Parm0);
 			DISPATCH_OP(Parm1);
 			DISPATCH_OP(Parm2);
 			DISPATCH_OP(Parm3);
 			DISPATCH_OP(ParmG);
+			DISPATCH_OP(SParmX);
+			DISPATCH_OP(SAnimX);
 
 			DISPATCH_OP(VolumeDn4);
 			DISPATCH_OP(VolumeUp3);
@@ -729,8 +753,10 @@ bool Runtime::runScript() {
 			DISPATCH_OP(Drop);
 			DISPATCH_OP(Dup);
 			DISPATCH_OP(Say3);
+			DISPATCH_OP(Say3Get);
 			DISPATCH_OP(SetTimer);
 			DISPATCH_OP(GetTimer);
+			DISPATCH_OP(Delay);
 			DISPATCH_OP(LoSet);
 			DISPATCH_OP(LoGet);
 			DISPATCH_OP(HiSet);
@@ -739,7 +765,11 @@ bool Runtime::runScript() {
 			DISPATCH_OP(Not);
 			DISPATCH_OP(And);
 			DISPATCH_OP(Or);
+			DISPATCH_OP(Add);
+			DISPATCH_OP(Sub);
 			DISPATCH_OP(CmpEq);
+			DISPATCH_OP(CmpGt);
+			DISPATCH_OP(CmpLt);
 
 			DISPATCH_OP(BitLoad);
 			DISPATCH_OP(BitSet0);
@@ -975,6 +1005,8 @@ void Runtime::changeToScreen(uint roomNumber, uint screenNumber) {
 }
 
 void Runtime::returnToIdleState() {
+	debug(1, "Returned to idle state in room %u screen 0%x facing direction %u", _roomNumber, _screenNumber, _direction);
+
 	_animPlayWhileIdle = false;
 
 	if (_haveIdleAnimations[_direction]) {
@@ -1518,6 +1550,108 @@ void Runtime::onKeyDown(Common::KeyCode keyCode) {
 	queueOSEvent(evt);
 }
 
+bool Runtime::canSave() const {
+	return _gameState == kGameStateIdle;
+}
+
+bool Runtime::canLoad() const {
+	return _gameState == kGameStateIdle;
+}
+
+void Runtime::saveGame(Common::WriteStream *stream) const {
+	stream->writeUint32BE(kSaveGameIdentifier);
+	stream->writeUint32BE(kSaveGameCurrentVersion);
+
+	stream->writeUint32BE(_roomNumber);
+	stream->writeUint32BE(_screenNumber);
+	stream->writeUint32BE(_direction);
+
+	Common::Array<uint32> variableIDs;
+
+	for (const Common::HashMap<uint32, int32>::Node &varNode : _variables)
+		variableIDs.push_back(varNode._key);
+
+	Common::sort(variableIDs.begin(), variableIDs.end());
+
+	stream->writeUint32BE(variableIDs.size());
+
+	for (uint32 variableKey : variableIDs) {
+		Common::HashMap<uint32, int32>::const_iterator it = _variables.find(variableKey);
+		assert(it != _variables.end());
+
+		stream->writeUint32BE(variableKey);
+		stream->writeSint32BE(it->_value);
+	}
+}
+
+bool Runtime::loadGame(Common::ReadStream *stream) {
+	assert(canLoad());
+
+	uint32 saveGameID = stream->readUint32BE();
+	uint32 saveVersion = stream->readUint32BE();
+
+	if (stream->err() || stream->eos()) {
+		GUI::MessageDialog dialog(_("Failed to read version information from save file"));
+		dialog.runModal();
+
+		return false;
+	}
+
+	if (saveGameID != kSaveGameIdentifier) {
+		GUI::MessageDialog dialog(_("Failed to load save, the save file doesn't contain valid version information."));
+		dialog.runModal();
+
+		return false;
+	}
+
+	if (saveVersion > kSaveGameCurrentVersion) {
+		GUI::MessageDialog dialog(_("Saved game was created with a newer version of ScummVM. Unable to load."));
+		dialog.runModal();
+
+		return false;
+	}
+
+	if (saveVersion < kSaveGameEarliestSupportedVersion) {
+		GUI::MessageDialog dialog(_("Saved game was created with an earlier, incompatible version of ScummVM. Unable to load."));
+		dialog.runModal();
+
+		return false;
+	}
+
+	uint32 roomNumber = stream->readUint32BE();
+	uint32 screenNumber = stream->readUint32BE();
+	uint32 direction = stream->readUint32BE();
+
+	uint32 numVars = stream->readUint32BE();
+
+	if (stream->err() || stream->eos())
+		return false;
+
+	Common::HashMap<uint32, int32> vars;
+
+	for (uint32 i = 0; i < numVars; i++) {
+		uint32 varID = stream->readUint32BE();
+		int32 varValue = stream->readSint32BE();
+
+		vars[varID] = varValue;
+	}
+
+	if (stream->err() || stream->eos())
+		return false;
+
+	if (direction >= kNumDirections)
+		return false;
+
+	// Load succeeded
+	_variables = Common::move(vars);
+
+	_direction = direction;
+	changeToScreen(roomNumber, screenNumber);
+	_havePendingReturnToIdleState = true;
+
+	return true;
+}
+
 #ifdef PEEK_STACK
 #error "PEEK_STACK is already defined"
 #endif
@@ -1782,6 +1916,11 @@ void Runtime::scriptOpVarStore(ScriptArg_t arg) {
 	_variables[varID] = stackArgs[0];
 }
 
+OPCODE_STUB(ItemCheck)
+OPCODE_STUB(ItemCRSet)
+OPCODE_STUB(ItemSRSet)
+OPCODE_STUB(ItemRSet)
+
 void Runtime::scriptOpSetCursor(ScriptArg_t arg) {
 	TAKE_STACK(1);
 
@@ -1820,14 +1959,78 @@ void Runtime::scriptOpLMB1(ScriptArg_t arg) {
 void Runtime::scriptOpSoundS1(ScriptArg_t arg) {
 	TAKE_STACK(1);
 
-	warning("Sound play not implemented yet");
+	warning("Sound play 1 not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpSoundS2(ScriptArg_t arg) {
+	TAKE_STACK(2);
+
+	warning("Sound play 2 not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpSoundS3(ScriptArg_t arg) {
+	TAKE_STACK(3);
+
+	warning("Sound play 3 not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpSoundL1(ScriptArg_t arg) {
+	TAKE_STACK(1);
+
+	warning("Sound loop 1 not implemented yet");
 	(void)stackArgs;
 }
 
 void Runtime::scriptOpSoundL2(ScriptArg_t arg) {
 	TAKE_STACK(2);
 
-	warning("Sound loop not implemented yet");
+	warning("Sound loop 2 not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpSoundL3(ScriptArg_t arg) {
+	TAKE_STACK(3);
+
+	warning("Sound loop 3 not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOp3DSoundL2(ScriptArg_t arg) {
+	TAKE_STACK(4);
+
+	warning("3D sound loop not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpAddXSound(ScriptArg_t arg) {
+	TAKE_STACK(4);
+
+	warning("AddXSound not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpClrXSound(ScriptArg_t arg) {
+	warning("ClrXSound not implemented yet");
+}
+
+void Runtime::scriptOpStopSndLA(ScriptArg_t arg) {
+	warning("StopSndLA not implemented yet");
+}
+
+void Runtime::scriptOpStopSndLO(ScriptArg_t arg) {
+	TAKE_STACK(1);
+
+	warning("StopSndLO not implemented yet");
+	(void)stackArgs;
+}
+
+void Runtime::scriptOpRange(ScriptArg_t arg) {
+	TAKE_STACK(3);
+
+	warning("Range not implemented yet");
 	(void)stackArgs;
 }
 
@@ -1851,6 +2054,13 @@ void Runtime::scriptOpMusicDn(ScriptArg_t arg) {
 	(void)stackArgs;
 }
 
+void Runtime::scriptOpParm0(ScriptArg_t arg) {
+	TAKE_STACK(4);
+
+	warning("Parm0 is not implemented");
+	(void)stackArgs;
+}
+
 void Runtime::scriptOpParm1(ScriptArg_t arg) {
 	TAKE_STACK(3);
 
@@ -1892,6 +2102,9 @@ void Runtime::scriptOpParmG(ScriptArg_t arg) {
 	_gyros.maxValue = maxValue;
 }
 
+OPCODE_STUB(SParmX)
+OPCODE_STUB(SAnimX)
+
 void Runtime::scriptOpVolumeUp3(ScriptArg_t arg) {
 	TAKE_STACK(3);
 
@@ -1943,6 +2156,8 @@ void Runtime::scriptOpSay3(ScriptArg_t arg) {
 	(void)stackArgs;
 }
 
+OPCODE_STUB(Say3Get)
+
 void Runtime::scriptOpSetTimer(ScriptArg_t arg) {
 	TAKE_STACK(2);
 
@@ -1952,7 +2167,7 @@ void Runtime::scriptOpSetTimer(ScriptArg_t arg) {
 void Runtime::scriptOpGetTimer(ScriptArg_t arg) {
 	TAKE_STACK(1);
 
-	bool isCompleted = false;
+	bool isCompleted = true;
 
 	Common::HashMap<uint, uint32>::const_iterator timerIt = _timers.find(stackArgs[0]);
 	if (timerIt != _timers.end())
@@ -1961,6 +2176,13 @@ void Runtime::scriptOpGetTimer(ScriptArg_t arg) {
 	_scriptStack.push_back(isCompleted ? 1 : 0);
 }
 
+void Runtime::scriptOpDelay(ScriptArg_t arg) {
+	TAKE_STACK(1);
+
+	warning("Delay opcode is not implemented yet");
+	(void)stackArgs;
+}
+
 void Runtime::scriptOpLoSet(ScriptArg_t arg) {
 	scriptOpVerticalPanSet(_havePanDownFromDirection);
 }
@@ -2035,12 +2257,36 @@ void Runtime::scriptOpOr(ScriptArg_t arg) {
 	_scriptStack.push_back((stackArgs[0] != 0 || stackArgs[1] != 0) ? 1 : 0);
 }
 
+void Runtime::scriptOpAdd(ScriptArg_t arg) {
+	TAKE_STACK(2);
+
+	_scriptStack.push_back(stackArgs[0] + stackArgs[1]);
+}
+
+void Runtime::scriptOpSub(ScriptArg_t arg) {
+	TAKE_STACK(2);
+
+	_scriptStack.push_back(stackArgs[0] - stackArgs[1]);
+}
+
 void Runtime::scriptOpCmpEq(ScriptArg_t arg) {
 	TAKE_STACK(2);
 
 	_scriptStack.push_back((stackArgs[0] == stackArgs[1]) ? 1 : 0);
 }
 
+void Runtime::scriptOpCmpLt(ScriptArg_t arg) {
+	TAKE_STACK(2);
+
+	_scriptStack.push_back((stackArgs[0] < stackArgs[1]) ? 1 : 0);
+}
+
+void Runtime::scriptOpCmpGt(ScriptArg_t arg) {
+	TAKE_STACK(2);
+
+	_scriptStack.push_back((stackArgs[0] > stackArgs[1]) ? 1 : 0);
+}
+
 void Runtime::scriptOpBitLoad(ScriptArg_t arg) {
 	TAKE_STACK(2);
 
diff --git a/engines/vcruise/runtime.h b/engines/vcruise/runtime.h
index 8cdc64d9a47..fe01947f0c9 100644
--- a/engines/vcruise/runtime.h
+++ b/engines/vcruise/runtime.h
@@ -32,6 +32,8 @@ class OSystem;
 namespace Common {
 
 class RandomSource;
+class ReadStream;
+class WriteStream;
 
 } // End of namespace Commom
 
@@ -142,6 +144,14 @@ public:
 	void onMouseMove(int16 x, int16 y);
 	void onKeyDown(Common::KeyCode keyCode);
 
+	bool canSave() const;
+	bool canLoad() const;
+
+	void saveGame(Common::WriteStream *stream) const;
+	bool loadGame(Common::ReadStream *stream);
+
+	bool bootGame(bool newGame);
+
 private:
 	enum IndexParseType {
 		kIndexParseTypeNone,
@@ -254,7 +264,6 @@ private:
 	typedef int32 ScriptArg_t;
 	typedef int32 StackValue_t;
 
-	bool bootGame();
 	bool runIdle();
 	bool runHorizontalPan(bool isRight);
 	bool runScript();
@@ -323,20 +332,39 @@ private:
 	void scriptOpStatic(ScriptArg_t arg);
 	void scriptOpVarLoad(ScriptArg_t arg);
 	void scriptOpVarStore(ScriptArg_t arg);
+
+	void scriptOpItemCheck(ScriptArg_t arg);
+	void scriptOpItemCRSet(ScriptArg_t arg);
+	void scriptOpItemSRSet(ScriptArg_t arg);
+	void scriptOpItemRSet(ScriptArg_t arg);
+
 	void scriptOpSetCursor(ScriptArg_t arg);
 	void scriptOpSetRoom(ScriptArg_t arg);
 	void scriptOpLMB(ScriptArg_t arg);
 	void scriptOpLMB1(ScriptArg_t arg);
 	void scriptOpSoundS1(ScriptArg_t arg);
+	void scriptOpSoundS2(ScriptArg_t arg);
+	void scriptOpSoundS3(ScriptArg_t arg);
+	void scriptOpSoundL1(ScriptArg_t arg);
 	void scriptOpSoundL2(ScriptArg_t arg);
+	void scriptOpSoundL3(ScriptArg_t arg);
+	void scriptOp3DSoundL2(ScriptArg_t arg);
+	void scriptOpRange(ScriptArg_t arg);
+	void scriptOpAddXSound(ScriptArg_t arg);
+	void scriptOpClrXSound(ScriptArg_t arg);
+	void scriptOpStopSndLA(ScriptArg_t arg);
+	void scriptOpStopSndLO(ScriptArg_t arg);
 
 	void scriptOpMusic(ScriptArg_t arg);
 	void scriptOpMusicUp(ScriptArg_t arg);
 	void scriptOpMusicDn(ScriptArg_t arg);
+	void scriptOpParm0(ScriptArg_t arg);
 	void scriptOpParm1(ScriptArg_t arg);
 	void scriptOpParm2(ScriptArg_t arg);
 	void scriptOpParm3(ScriptArg_t arg);
 	void scriptOpParmG(ScriptArg_t arg);
+	void scriptOpSParmX(ScriptArg_t arg);
+	void scriptOpSAnimX(ScriptArg_t arg);
 
 	void scriptOpVolumeDn4(ScriptArg_t arg);
 	void scriptOpVolumeUp3(ScriptArg_t arg);
@@ -344,8 +372,10 @@ private:
 	void scriptOpDrop(ScriptArg_t arg);
 	void scriptOpDup(ScriptArg_t arg);
 	void scriptOpSay3(ScriptArg_t arg);
+	void scriptOpSay3Get(ScriptArg_t arg);
 	void scriptOpSetTimer(ScriptArg_t arg);
 	void scriptOpGetTimer(ScriptArg_t arg);
+	void scriptOpDelay(ScriptArg_t arg);
 	void scriptOpLoSet(ScriptArg_t arg);
 	void scriptOpLoGet(ScriptArg_t arg);
 	void scriptOpHiSet(ScriptArg_t arg);
@@ -354,7 +384,11 @@ private:
 	void scriptOpNot(ScriptArg_t arg);
 	void scriptOpAnd(ScriptArg_t arg);
 	void scriptOpOr(ScriptArg_t arg);
+	void scriptOpAdd(ScriptArg_t arg);
+	void scriptOpSub(ScriptArg_t arg);
 	void scriptOpCmpEq(ScriptArg_t arg);
+	void scriptOpCmpLt(ScriptArg_t arg);
+	void scriptOpCmpGt(ScriptArg_t arg);
 
 	void scriptOpBitLoad(ScriptArg_t arg);
 	void scriptOpBitSet0(ScriptArg_t arg);
@@ -496,6 +530,10 @@ private:
 
 	static const int kPanoramaPanningMarginX = 11;
 	static const int kPanoramaPanningMarginY = 11;
+
+	static const uint kSaveGameIdentifier = 0x53566372;
+	static const uint kSaveGameCurrentVersion = 1;
+	static const uint kSaveGameEarliestSupportedVersion = 1;
 };
 
 } // End of namespace VCruise
diff --git a/engines/vcruise/script.cpp b/engines/vcruise/script.cpp
index c32a56b8936..f3432f3de67 100644
--- a/engines/vcruise/script.cpp
+++ b/engines/vcruise/script.cpp
@@ -305,6 +305,10 @@ void ScriptCompiler::compileScreenScriptSet(ScreenScriptSet *sss) {
 			protoScript.reset();
 
 			sss->interactionScripts[interactionNumber] = currentScript;
+		} else if (token == "DEC") {
+			_numberParsingMode = kNumberParsingDec;
+		} else if (token == "HEX") {
+			_numberParsingMode = kNumberParsingHex;
 		} else if (compileInstructionToken(protoScript, token)) {
 			// Nothing
 		} else {
@@ -320,6 +324,7 @@ static ScriptNamedInstruction g_namedInstructions[] = {
 	{"speed", ProtoOp::kProtoOpScript, ScriptOps::kSpeed},
 	{"sanimL", ProtoOp::kProtoOpScript, ScriptOps::kSAnimL},
 	{"changeL", ProtoOp::kProtoOpScript, ScriptOps::kChangeL},
+	{"changeL1", ProtoOp::kProtoOpScript, ScriptOps::kChangeL},	// This seems wrong, but not sure what changeL1 does differently from changeL yet
 	{"animR", ProtoOp::kProtoOpScript, ScriptOps::kAnimR},
 	{"animF", ProtoOp::kProtoOpScript, ScriptOps::kAnimF},
 	{"animN", ProtoOp::kProtoOpScript, ScriptOps::kAnimN},
@@ -329,6 +334,10 @@ static ScriptNamedInstruction g_namedInstructions[] = {
 	{"static", ProtoOp::kProtoOpScript, ScriptOps::kStatic},
 	{"yes@", ProtoOp::kProtoOpScript, ScriptOps::kVarLoad},
 	{"yes!", ProtoOp::kProtoOpScript, ScriptOps::kVarStore},
+	{"cr?", ProtoOp::kProtoOpScript, ScriptOps::kItemCheck},
+	{"cr!", ProtoOp::kProtoOpScript, ScriptOps::kItemCRSet},
+	{"sr!", ProtoOp::kProtoOpScript, ScriptOps::kItemSRSet},
+	{"r!", ProtoOp::kProtoOpScript, ScriptOps::kItemRSet},
 	{"cursor!", ProtoOp::kProtoOpScript, ScriptOps::kSetCursor},
 	{"room!", ProtoOp::kProtoOpScript, ScriptOps::kSetRoom},
 	{"lmb", ProtoOp::kProtoOpScript, ScriptOps::kLMB},
@@ -339,8 +348,10 @@ static ScriptNamedInstruction g_namedInstructions[] = {
 	{"drop", ProtoOp::kProtoOpScript, ScriptOps::kDrop},
 	{"dup", ProtoOp::kProtoOpScript, ScriptOps::kDup},
 	{"say3", ProtoOp::kProtoOpScript, ScriptOps::kSay3},
+	{"say3@", ProtoOp::kProtoOpScript, ScriptOps::kSay3Get},
 	{"setTimer", ProtoOp::kProtoOpScript, ScriptOps::kSetTimer},
 	{"getTimer", ProtoOp::kProtoOpScript, ScriptOps::kGetTimer},
+	{"delay", ProtoOp::kProtoOpScript, ScriptOps::kDelay},
 	{"lo!", ProtoOp::kProtoOpScript, ScriptOps::kLoSet},
 	{"lo@", ProtoOp::kProtoOpScript, ScriptOps::kLoGet},
 	{"hi!", ProtoOp::kProtoOpScript, ScriptOps::kHiSet},
@@ -348,23 +359,41 @@ static ScriptNamedInstruction g_namedInstructions[] = {
 
 	{"and", ProtoOp::kProtoOpScript, ScriptOps::kAnd},
 	{"or", ProtoOp::kProtoOpScript, ScriptOps::kOr},
+	{"+", ProtoOp::kProtoOpScript, ScriptOps::kAdd},
+	{"-", ProtoOp::kProtoOpScript, ScriptOps::kSub},
 	{"not", ProtoOp::kProtoOpScript, ScriptOps::kNot},
 	{"=", ProtoOp::kProtoOpScript, ScriptOps::kCmpEq},
+	{">", ProtoOp::kProtoOpScript, ScriptOps::kCmpGt},
+	{"<", ProtoOp::kProtoOpScript, ScriptOps::kCmpLt},
 
 	{"bit@", ProtoOp::kProtoOpScript, ScriptOps::kBitLoad},
 	{"bit0!", ProtoOp::kProtoOpScript, ScriptOps::kBitSet0},
 	{"bit1!", ProtoOp::kProtoOpScript, ScriptOps::kBitSet1},
 
 	{"soundS1", ProtoOp::kProtoOpScript, ScriptOps::kSoundS1},
+	{"soundS2", ProtoOp::kProtoOpScript, ScriptOps::kSoundS2},
+	{"soundS3", ProtoOp::kProtoOpScript, ScriptOps::kSoundS3},
+	{"soundL1", ProtoOp::kProtoOpScript, ScriptOps::kSoundL1},
 	{"soundL2", ProtoOp::kProtoOpScript, ScriptOps::kSoundL2},
+	{"soundL3", ProtoOp::kProtoOpScript, ScriptOps::kSoundL3},
+	{"3DsoundL2", ProtoOp::kProtoOpScript, ScriptOps::k3DSoundL2},
+	{"range", ProtoOp::kProtoOpScript, ScriptOps::kRange},
+	{"addXsound", ProtoOp::kProtoOpScript, ScriptOps::kAddXSound},
+	{"clrXsound", ProtoOp::kProtoOpScript, ScriptOps::kClrXSound},
+	{"stopSndLA", ProtoOp::kProtoOpScript, ScriptOps::kStopSndLA},
+	{"stopSndLO", ProtoOp::kProtoOpScript, ScriptOps::kStopSndLO},
+
 	{"music", ProtoOp::kProtoOpScript, ScriptOps::kMusic},
 	{"musicUp", ProtoOp::kProtoOpScript, ScriptOps::kMusicUp},
 	{"musicDn", ProtoOp::kProtoOpScript, ScriptOps::kMusicDn},
 
+	{"parm0", ProtoOp::kProtoOpScript, ScriptOps::kParm0},
 	{"parm1", ProtoOp::kProtoOpScript, ScriptOps::kParm1},
 	{"parm2", ProtoOp::kProtoOpScript, ScriptOps::kParm2},
 	{"parm3", ProtoOp::kProtoOpScript, ScriptOps::kParm3},
 	{"parmG", ProtoOp::kProtoOpScript, ScriptOps::kParmG},
+	{"sparmX", ProtoOp::kProtoOpScript, ScriptOps::kSParmX},
+	{"sanimX", ProtoOp::kProtoOpScript, ScriptOps::kSAnimX},
 
 	{"disc1", ProtoOp::kProtoOpScript, ScriptOps::kDisc1},
 	{"disc2", ProtoOp::kProtoOpScript, ScriptOps::kDisc2},
diff --git a/engines/vcruise/script.h b/engines/vcruise/script.h
index 1976606a3ce..ccf8f2f1bd1 100644
--- a/engines/vcruise/script.h
+++ b/engines/vcruise/script.h
@@ -61,27 +61,46 @@ enum ScriptOp {
 	kStatic,
 	kVarLoad,
 	kVarStore,
+	kItemCheck,
+	kItemCRSet,
+	kItemSRSet,
+	kItemRSet,
 	kSetCursor,
 	kSetRoom,
 	kLMB,
 	kLMB1,
 	kSoundS1,
+	kSoundS2,
+	kSoundS3,
+	kSoundL1,
 	kSoundL2,
+	kSoundL3,
+	k3DSoundL2,
+	kRange,
+	kAddXSound,
+	kClrXSound,
+	kStopSndLA,
+	kStopSndLO,
 	kMusic,
 	kMusicUp,
 	kMusicDn,
+	kParm0,
 	kParm1,
 	kParm2,
 	kParm3,
 	kParmG,
+	kSParmX,
+	kSAnimX,
 	kVolumeDn4,
 	kVolumeUp3,
 	kRandom,
 	kDrop,
 	kDup,
 	kSay3,
+	kSay3Get,
 	kSetTimer,
 	kGetTimer,
+	kDelay,
 	kLoSet,
 	kLoGet,
 	kHiSet,
@@ -90,7 +109,11 @@ enum ScriptOp {
 	kNot,
 	kAnd,
 	kOr,
+	kSub,
+	kAdd,
 	kCmpEq,
+	kCmpLt,
+	kCmpGt,
 
 	kBitLoad,
 	kBitSet0,
diff --git a/engines/vcruise/vcruise.cpp b/engines/vcruise/vcruise.cpp
index c8bf0603390..b2bfb51d325 100644
--- a/engines/vcruise/vcruise.cpp
+++ b/engines/vcruise/vcruise.cpp
@@ -23,6 +23,7 @@
 
 #include "common/config-manager.h"
 #include "common/events.h"
+#include "common/stream.h"
 #include "common/system.h"
 #include "common/algorithm.h"
 #include "common/translation.h"
@@ -168,6 +169,17 @@ Common::Error VCruiseEngine::run() {
 		_runtime->setDebugMode(true);
 	}
 
+	if (ConfMan.hasKey("save_slot")) {
+		int saveSlot = ConfMan.getInt("save_slot");
+		if (saveSlot >= 0) {
+			(void)_runtime->bootGame(false);
+
+			Common::Error err = loadGameState(saveSlot);
+			if (err.getCode() != Common::kNoError)
+				return err;
+		}
+	}
+
 	// Run the game
 	while (!shouldQuit()) {
 		handleEvents();
@@ -191,7 +203,8 @@ void VCruiseEngine::pauseEngineIntern(bool pause) {
 bool VCruiseEngine::hasFeature(EngineFeature f) const {
 	switch (f) {
 	case kSupportsReturnToLauncher:
-	//case kSupportsSavingDuringRuntime:
+	case kSupportsSavingDuringRuntime:
+	case kSupportsLoadingDuringRuntime:
 		return true;
 	default:
 		return false;
@@ -199,15 +212,31 @@ bool VCruiseEngine::hasFeature(EngineFeature f) const {
 }
 
 Common::Error VCruiseEngine::saveGameStream(Common::WriteStream *stream, bool isAutosave) {
-	return Common::Error(Common::kUnknownError);
+	_runtime->saveGame(stream);
+
+	if (stream->err())
+		return Common::Error(Common::kWritingFailed);
+
+	return Common::Error(Common::kNoError);
+}
+
+Common::Error VCruiseEngine::loadGameStream(Common::SeekableReadStream *stream) {
+	if (!_runtime->loadGame(stream))
+		return Common::Error(Common::kReadingFailed);
+
+	return Common::Error(Common::kNoError);
 }
 
 bool VCruiseEngine::canSaveAutosaveCurrently() {
-	return false;
+	return _runtime->canSave();
 }
 
 bool VCruiseEngine::canSaveGameStateCurrently() {
-	return false;
+	return _runtime->canSave();
+}
+
+bool VCruiseEngine::canLoadGameStateCurrently() {
+	return _runtime->canLoad();
 }
 
 void VCruiseEngine::initializePath(const Common::FSNode &gamePath) {
diff --git a/engines/vcruise/vcruise.h b/engines/vcruise/vcruise.h
index eb16bc7adcf..44ccb05b9ad 100644
--- a/engines/vcruise/vcruise.h
+++ b/engines/vcruise/vcruise.h
@@ -54,8 +54,11 @@ public:
 	const VCruiseGameDescription *_gameDescription;
 
 	Common::Error saveGameStream(Common::WriteStream *stream, bool isAutosave) override;
+	Common::Error loadGameStream(Common::SeekableReadStream *stream) override;
+
 	bool canSaveAutosaveCurrently() override;
 	bool canSaveGameStateCurrently() override;
+	bool canLoadGameStateCurrently() override;
 
 	void initializePath(const Common::FSNode &gamePath) override;
 




More information about the Scummvm-git-logs mailing list