diff options
Diffstat (limited to 'engines/adl/adl_v4.cpp')
-rw-r--r-- | engines/adl/adl_v4.cpp | 219 |
1 files changed, 208 insertions, 11 deletions
diff --git a/engines/adl/adl_v4.cpp b/engines/adl/adl_v4.cpp index 456ee10dca..dcf0f997c9 100644 --- a/engines/adl/adl_v4.cpp +++ b/engines/adl/adl_v4.cpp @@ -21,6 +21,7 @@ */ #include "adl/adl_v4.h" +#include "adl/display.h" #include "adl/detection.h" namespace Adl { @@ -36,6 +37,143 @@ AdlEngine_v4::~AdlEngine_v4() { delete _itemPicIndex; } +void AdlEngine_v4::gameLoop() { + uint verb = 0, noun = 0; + _isRestarting = false; + + if (_isRestoring) { + // Game restored from launcher. As this version of ADL long jumps to + // the game loop after restoring, no special action is required. + _isRestoring = false; + } + + showRoom(); + + if (_isRestarting || shouldQuit()) + return; + + _canSaveNow = _canRestoreNow = true; + getInput(verb, noun); + _canSaveNow = _canRestoreNow = false; + + if (_isRestoring) { + // Game restored from GMM. Move cursor to next line and jump to + // start of game loop. + _display->printAsciiString("\r"); + _isRestoring = false; + return; + } + + if (_isRestarting || shouldQuit()) + return; + + _linesPrinted = 0; + + checkInput(verb, noun); + + if (_isRestarting || shouldQuit()) + return; + + doAllCommands(_globalCommands, verb, noun); + + if (_isRestarting || shouldQuit()) + return; + + _state.moves++; +} + +void AdlEngine_v4::loadState(Common::ReadStream &stream) { + _state.room = stream.readByte(); + _state.region = stream.readByte(); + _state.prevRegion = stream.readByte(); + + uint32 size = stream.readUint32BE(); + if (size != _state.regions.size()) + error("Region count mismatch (expected %i; found %i)", _state.regions.size(), size); + + Common::Array<Region>::iterator region; + for (region = _state.regions.begin(); region != _state.regions.end(); ++region) { + size = stream.readUint32BE(); + if (size != region->rooms.size()) + error("Room count mismatch (expected %i; found %i)", region->rooms.size(), size); + + Common::Array<RoomState>::iterator room; + for (room = region->rooms.begin(); room != region->rooms.end(); ++room) { + room->picture = stream.readByte(); + room->isFirstTime = stream.readByte(); + } + + size = stream.readUint32BE(); + if (size != region->vars.size()) + error("Variable count mismatch (expected %i; found %i)", region->vars.size(), size); + + for (uint i = 0; i < region->vars.size(); ++i) + region->vars[i] = stream.readByte(); + } + + size = stream.readUint32BE(); + if (size != _state.items.size()) + error("Item count mismatch (expected %i; found %i)", _state.items.size(), size); + + Common::List<Item>::iterator item; + for (item = _state.items.begin(); item != _state.items.end(); ++item) { + item->room = stream.readByte(); + item->region = stream.readByte(); + item->state = stream.readByte(); + } + + size = stream.readUint32BE(); + const uint expectedSize = _state.vars.size() - getRegion(1).vars.size(); + if (size != expectedSize) + error("Variable count mismatch (expected %i; found %i)", expectedSize, size); + + for (uint i = getRegion(1).vars.size(); i < size; ++i) + _state.vars[i] = stream.readByte(); + + if (stream.err() || stream.eos()) + return; + + loadRegion(_state.region); + restoreRoomState(_state.room); + _roomOnScreen = _picOnScreen = 0; +} + +void AdlEngine_v4::saveState(Common::WriteStream &stream) { + backupVars(); + backupRoomState(_state.room); + + stream.writeByte(_state.room); + stream.writeByte(_state.region); + stream.writeByte(_state.prevRegion); + + stream.writeUint32BE(_state.regions.size()); + Common::Array<Region>::const_iterator region; + for (region = _state.regions.begin(); region != _state.regions.end(); ++region) { + stream.writeUint32BE(region->rooms.size()); + Common::Array<RoomState>::const_iterator room; + for (room = region->rooms.begin(); room != region->rooms.end(); ++room) { + stream.writeByte(room->picture); + stream.writeByte(room->isFirstTime); + } + + stream.writeUint32BE(region->vars.size()); + for (uint i = 0; i < region->vars.size(); ++i) + stream.writeByte(region->vars[i]); + } + + stream.writeUint32BE(_state.items.size()); + Common::List<Item>::const_iterator item; + for (item = _state.items.begin(); item != _state.items.end(); ++item) { + stream.writeByte(item->room); + stream.writeByte(item->region); + stream.writeByte(item->state); + } + + stream.writeUint32BE(_state.vars.size() - getRegion(1).vars.size()); + for (uint i = getRegion(1).vars.size(); i < _state.vars.size(); ++i) + stream.writeByte(_state.vars[i]); +} + Common::String AdlEngine_v4::loadMessage(uint idx) const { Common::String str = AdlEngine_v3::loadMessage(idx); @@ -268,6 +406,14 @@ void AdlEngine_v4::switchRegion(byte region) { _picOnScreen = _roomOnScreen = 0; } +void AdlEngine_v4::switchRoom(byte roomNr) { + getCurRoom().curPicture = getCurRoom().picture; + getCurRoom().isFirstTime = false; + backupRoomState(_state.room); + _state.room = roomNr; + restoreRoomState(_state.room); +} + int AdlEngine_v4::o4_isItemInRoom(ScriptEnv &e) { OP_DEBUG_2("\t&& GET_ITEM_ROOM(%s) == %s", itemStr(e.arg(1)).c_str(), itemRoomStr(e.arg(2)).c_str()); @@ -297,17 +443,6 @@ int AdlEngine_v4::o4_moveItem(ScriptEnv &e) { return 2; } -int AdlEngine_v4::o4_setRoom(ScriptEnv &e) { - OP_DEBUG_1("\tROOM = %d", e.arg(1)); - - getCurRoom().curPicture = getCurRoom().picture; - getCurRoom().isFirstTime = false; - backupRoomState(_state.room); - _state.room = e.arg(1); - restoreRoomState(_state.room); - return 1; -} - int AdlEngine_v4::o4_setRegionToPrev(ScriptEnv &e) { OP_DEBUG_0("\tREGION = PREV_REGION"); @@ -363,6 +498,68 @@ int AdlEngine_v4::o4_setRegion(ScriptEnv &e) { return -1; } +int AdlEngine_v4::o4_save(ScriptEnv &e) { + OP_DEBUG_0("\tSAVE_GAME()"); + + _display->printString(_strings_v2.saveReplace); + const char key = inputKey(); + + if (shouldQuit()) + return -1; + + if (key != APPLECHAR('Y')) + return 0; + + const int slot = askForSlot(_strings_v2.saveInsert); + + if (slot < 0) + return -1; + + saveGameState(slot, ""); + return 0; +} + +int AdlEngine_v4::o4_restore(ScriptEnv &e) { + OP_DEBUG_0("\tRESTORE_GAME()"); + + const int slot = askForSlot(_strings_v2.restoreInsert); + + if (slot < 0) + return -1; + + loadGameState(slot); + _isRestoring = false; + + _picOnScreen = 0; + _roomOnScreen = 0; + + // Long jump + _isRestarting = true; + return -1; +} + +int AdlEngine_v4::o4_restart(ScriptEnv &e) { + OP_DEBUG_0("\tRESTART_GAME()"); + + while (true) { + _display->printString(_strings.playAgain); + const Common::String input(inputString()); + + if (shouldQuit()) + return -1; + + if (input.firstChar() == APPLECHAR('N')) { + return o1_quit(e); + } else if (input.firstChar() == APPLECHAR('Y')) { + // The original game loads a special save game from volume 3 + initState(); + // Long jump + _isRestarting = true; + return -1; + } + } +} + int AdlEngine_v4::o4_setRegionRoom(ScriptEnv &e) { OP_DEBUG_2("\tSET_REGION_ROOM(%d, %d)", e.arg(1), e.arg(2)); |