From aed38527010e7b155af469d0521aa07e7fd7d12e Mon Sep 17 00:00:00 2001 From: johndoe123 Date: Fri, 4 Dec 2015 23:20:22 +0100 Subject: ILLUSIONS: Implement save/load functionality - Only works in Duckman at the moment - Only via the ScummVM main menu for now, save/load via the game's menu to be implemented --- engines/illusions/duckman/gamestate_duckman.cpp | 50 +++++++++++++ engines/illusions/duckman/gamestate_duckman.h | 44 +++++++++++ engines/illusions/duckman/illusions_duckman.cpp | 86 ++++++++++++---------- engines/illusions/duckman/illusions_duckman.h | 5 +- .../illusions/duckman/scriptopcodes_duckman.cpp | 12 +-- 5 files changed, 152 insertions(+), 45 deletions(-) create mode 100644 engines/illusions/duckman/gamestate_duckman.cpp create mode 100644 engines/illusions/duckman/gamestate_duckman.h (limited to 'engines/illusions/duckman') diff --git a/engines/illusions/duckman/gamestate_duckman.cpp b/engines/illusions/duckman/gamestate_duckman.cpp new file mode 100644 index 0000000000..8f4939f9dc --- /dev/null +++ b/engines/illusions/duckman/gamestate_duckman.cpp @@ -0,0 +1,50 @@ +/* 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 "illusions/duckman/gamestate_duckman.h" +#include "illusions/duckman/illusions_duckman.h" +#include "illusions/resources/scriptresource.h" + +namespace Illusions { + +Duckman_GameState::Duckman_GameState(IllusionsEngine_Duckman *vm) + : _vm(vm) { +} + +uint32 Duckman_GameState::calcWriteBufferSizeInternal() { + return + _vm->_scriptResource->_properties.getSize() + + _vm->_scriptResource->_blockCounters.getSize(); +} + +bool Duckman_GameState::readStateInternal(Common::ReadStream *in) { + return + _vm->_scriptResource->_properties.readFromStream(in) && + _vm->_scriptResource->_blockCounters.readFromStream(in); +} + +void Duckman_GameState::writeStateInternal(Common::WriteStream *out) { + _vm->_scriptResource->_properties.writeToStream(out); + _vm->_scriptResource->_blockCounters.writeToStream(out); +} + +} // End of namespace Illusions diff --git a/engines/illusions/duckman/gamestate_duckman.h b/engines/illusions/duckman/gamestate_duckman.h new file mode 100644 index 0000000000..36024c8d8e --- /dev/null +++ b/engines/illusions/duckman/gamestate_duckman.h @@ -0,0 +1,44 @@ +/* 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 ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H +#define ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H + +#include "illusions/gamestate.h" + +namespace Illusions { + +class IllusionsEngine_Duckman; + +class Duckman_GameState : public GameState { +public: + Duckman_GameState(IllusionsEngine_Duckman *vm); +protected: + IllusionsEngine_Duckman *_vm; + uint32 calcWriteBufferSizeInternal(); + bool readStateInternal(Common::ReadStream *in); + void writeStateInternal(Common::WriteStream *out); +}; + +} // End of namespace Illusions + +#endif // ILLUSIONS_DUCKMAN_GAMESTATE_DUCKMAN_H diff --git a/engines/illusions/duckman/illusions_duckman.cpp b/engines/illusions/duckman/illusions_duckman.cpp index ebfcdca4bd..c9233ae6d1 100644 --- a/engines/illusions/duckman/illusions_duckman.cpp +++ b/engines/illusions/duckman/illusions_duckman.cpp @@ -23,6 +23,7 @@ #include "illusions/duckman/illusions_duckman.h" #include "illusions/duckman/duckman_dialog.h" #include "illusions/duckman/duckman_specialcode.h" +#include "illusions/duckman/gamestate_duckman.h" #include "illusions/duckman/menusystem_duckman.h" #include "illusions/duckman/scriptopcodes_duckman.h" #include "illusions/actor.h" @@ -114,6 +115,7 @@ Common::Error IllusionsEngine_Duckman::run() { _updateFunctions = new UpdateFunctions(); _soundMan = new SoundMan(this); _menuSystem = new DuckmanMenuSystem(this); + _gameState = new Duckman_GameState(this); _fader = new Fader(); @@ -153,10 +155,7 @@ Common::Error IllusionsEngine_Duckman::run() { _resSys->loadResource(0x120001, 0x00010001, 0); _resSys->loadResource(0x120002, 0x00010001, 0); _resSys->loadResource(0x120003, 0x00010001, 0); - _resSys->loadResource(0x000D0001, 0x00010001, 0); - startScriptThread(0x00020004, 0); - _doScriptThreadInit = true; #if 0 //DEBUG @@ -174,13 +173,28 @@ Common::Error IllusionsEngine_Duckman::run() { _scriptResource->_blockCounters.set(238, 1); #endif -#if 1 +#if 0 // DEBUG Map / special code 0016001A _scriptResource->_properties.set(0x000E0017, true); _scriptResource->_properties.set(0x000E0022, false); #endif + if (ConfMan.hasKey("save_slot")) { + _doScriptThreadInit = true; + // Load global resources manually, usually done by the game script + enterScene(0x00010003, 0); + loadGameState(ConfMan.getInt("save_slot")); + } else { + startScriptThread(0x00020004, 0); + _doScriptThreadInit = true; + } + while (!shouldQuit()) { + if (_resumeFromSavegameRequested) { + activateSavegame(0); + resumeFromSavegame(0); + _resumeFromSavegameRequested = false; + } runUpdateFunctions(); _system->updateScreen(); updateEvents(); @@ -195,6 +209,7 @@ Common::Error IllusionsEngine_Duckman::run() { delete _fader; + delete _gameState; delete _menuSystem; delete _soundMan; delete _updateFunctions; @@ -218,12 +233,9 @@ Common::Error IllusionsEngine_Duckman::run() { bool IllusionsEngine_Duckman::hasFeature(EngineFeature f) const { return - false; - /* (f == kSupportsRTL) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime); - */ } void IllusionsEngine_Duckman::initInput() { @@ -793,7 +805,7 @@ bool IllusionsEngine_Duckman::changeScene(uint32 sceneId, uint32 threadId, uint3 _controls->destroyControls(); _resSys->unloadSceneResources(0x10003, 0x10001); if (enterScene(sceneId, threadId)) { - // TODO GameStates_writeStates(sceneId, threadId); + _gameState->writeState(sceneId, threadId); return true; } return false; @@ -1075,23 +1087,24 @@ uint32 IllusionsEngine_Duckman::runTriggerCause(uint32 verbId, uint32 objectId2, if (!getTriggerCause(verbId, objectId2, objectId, triggerThreadId)) return 0; - bool flag = false; + // TODO Extract sound effect playing to method + bool soundWasPlayed = false; if (_scriptResource->_properties.get(0x000E003C)) { if (verbId == 7 && objectId == 0x40003) { playSoundEffect(7); - flag = true; + soundWasPlayed = true; } else if (objectId == 0x40003) { playSoundEffect(14); - flag = true; + soundWasPlayed = true; } else if (verbId == 3) { playSoundEffect(16); - flag = true; + soundWasPlayed = true; } else if (verbId == 2) { - flag = true; + soundWasPlayed = true; } } - if (!flag) { + if (!soundWasPlayed) { if (objectId == 0x40003) { playSoundEffect(14); } else if ((verbId == 1 || verbId == 2) && _scriptResource->getMainActorObjectId() == objectId) { @@ -1120,34 +1133,33 @@ uint32 IllusionsEngine_Duckman::runTriggerCause(uint32 verbId, uint32 objectId2, return tempThreadId; } -bool IllusionsEngine_Duckman::loadSavegame(int16 slotNum, uint32 callingThreadId) { -#if 0 - // TODO - bool success = _gameStates->load(slotNum); - if (success) { - _vm->_screen->setDisplayOn(false); - uint32 currSceneId = getCurrentScene(); - if (currSceneId != 0x10003) - dumpCurrSceneFiles(currSceneId, callerThreadId); - reset(); - stopMidi(); - clearMidiPlayList(); - _gameStates->readStates(); - pushActiveScene(0x10000); - } - _gameStates->freeGameStateReadBuffer(); +bool IllusionsEngine_Duckman::loadSavegameFromScript(int16 slotNum, uint32 callingThreadId) { + const char *fileName = getSavegameFilename(slotNum); + bool success = loadgame(fileName); + if (success) + activateSavegame(callingThreadId); + _gameState->deleteReadStream(); return success; -#endif - return true; } -bool IllusionsEngine_Duckman::saveSavegame(int16 slotNum, uint32 callingThreadId) { -#if 0 +bool IllusionsEngine_Duckman::saveSavegameFromScript(int16 slotNum, uint32 callingThreadId) { // TODO - bool success = _gameStates->save(slotNum); + const char *fileName = getSavegameFilename(slotNum); + bool success = false;//savegame(fileName, _savegameDescription.c_str()); return success; -#endif - return true; +} + +void IllusionsEngine_Duckman::activateSavegame(uint32 callingThreadId) { + // TODO _screen->setDisplayOn(false); + uint32 currSceneId = getCurrentScene(); + if (currSceneId != 0x10003) + dumpCurrSceneFiles(currSceneId, callingThreadId); + reset(); + // TODO stopMidi(); + // TODO clearMidiPlayList(); + _gameState->readState(_savegameSceneId, _savegameThreadId); + pushActiveScene(0x10000); + _gameState->deleteReadStream(); } } // End of namespace Illusions diff --git a/engines/illusions/duckman/illusions_duckman.h b/engines/illusions/duckman/illusions_duckman.h index 87520d3a6a..1825123e5c 100644 --- a/engines/illusions/duckman/illusions_duckman.h +++ b/engines/illusions/duckman/illusions_duckman.h @@ -187,8 +187,9 @@ public: bool getTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId, uint32 &outThreadId); uint32 runTriggerCause(uint32 verbId, uint32 objectId2, uint32 objectId); - bool loadSavegame(int16 slotNum, uint32 callingThreadId); - bool saveSavegame(int16 slotNum, uint32 callingThreadId); + bool loadSavegameFromScript(int16 slotNum, uint32 callingThreadId); + bool saveSavegameFromScript(int16 slotNum, uint32 callingThreadId); + void activateSavegame(uint32 callingThreadId); }; diff --git a/engines/illusions/duckman/scriptopcodes_duckman.cpp b/engines/illusions/duckman/scriptopcodes_duckman.cpp index a62a78b46b..1456cfc0ee 100644 --- a/engines/illusions/duckman/scriptopcodes_duckman.cpp +++ b/engines/illusions/duckman/scriptopcodes_duckman.cpp @@ -259,7 +259,7 @@ void ScriptOpcodes_Duckman::opUnloadResourcesBySceneId(ScriptThread *scriptThrea //static uint dsceneId = 0, dthreadId = 0; //static uint dsceneId = 0x00010008, dthreadId = 0x00020029;//Beginning in Jac -//static uint dsceneId = 0x0001000A, dthreadId = 0x00020043;//Home front +static uint dsceneId = 0x0001000A, dthreadId = 0x00020043;//Home front //static uint dsceneId = 0x0001000E, dthreadId = 0x0002007C; //static uint dsceneId = 0x00010012, dthreadId = 0x0002009D;//Paramount //static uint dsceneId = 0x00010020, dthreadId = 0x00020112;//Xmas @@ -276,7 +276,7 @@ void ScriptOpcodes_Duckman::opUnloadResourcesBySceneId(ScriptThread *scriptThrea //static uint dsceneId = 0x10002, dthreadId = 0x20001;//Debug menu, not supported //static uint dsceneId = 0x10044, dthreadId = 0x000202B8; // Starship Enterprise //static uint dsceneId = 0x00010039, dthreadId = 0x00020089; // Map -static uint dsceneId = 0x00010052, dthreadId = 0x00020347; // Credits +//static uint dsceneId = 0x00010052, dthreadId = 0x00020347; // Credits void ScriptOpcodes_Duckman::opChangeScene(ScriptThread *scriptThread, OpCall &opCall) { ARG_SKIP(2); @@ -348,12 +348,12 @@ void ScriptOpcodes_Duckman::opLeaveScene24(ScriptThread *scriptThread, OpCall &o void ScriptOpcodes_Duckman::opEnterDebugger(ScriptThread *scriptThread, OpCall &opCall) { // Used for debugging purposes in the original engine // This is not supported and only reachable by code not implemented here! - error("ScriptOpcodes_Duckman::opEnterDebugger() Debugger function called"); + //error("ScriptOpcodes_Duckman::opEnterDebugger() Debugger function called"); } void ScriptOpcodes_Duckman::opLeaveDebugger(ScriptThread *scriptThread, OpCall &opCall) { // See opEnterDebugger - error("ScriptOpcodes_Duckman::opLeaveDebugger() Debugger function called"); + //error("ScriptOpcodes_Duckman::opLeaveDebugger() Debugger function called"); } void ScriptOpcodes_Duckman::opDumpCurrentSceneFiles(ScriptThread *scriptThread, OpCall &opCall) { @@ -690,7 +690,7 @@ void ScriptOpcodes_Duckman::opLoadGame(ScriptThread *scriptThread, OpCall &opCal ARG_SKIP(2); ARG_INT16(bankNum) ARG_INT16(slotNum) - bool success = _vm->loadSavegame(slotNum, opCall._callerThreadId); + bool success = _vm->loadSavegameFromScript(slotNum, opCall._callerThreadId); _vm->_stack->push(success ? 1 : 0); } @@ -698,7 +698,7 @@ void ScriptOpcodes_Duckman::opSaveGame(ScriptThread *scriptThread, OpCall &opCal ARG_SKIP(2); ARG_INT16(bankNum) ARG_INT16(slotNum) - bool success = _vm->saveSavegame(slotNum, opCall._callerThreadId); + bool success = _vm->saveSavegameFromScript(slotNum, opCall._callerThreadId); _vm->_stack->push(success ? 1 : 0); } -- cgit v1.2.3