diff options
-rw-r--r-- | devtools/scumm-md5.txt | 1 | ||||
-rw-r--r-- | engines/scumm/actor.cpp | 102 | ||||
-rw-r--r-- | engines/scumm/detection.cpp | 2 | ||||
-rw-r--r-- | engines/scumm/detection_tables.h | 2 | ||||
-rw-r--r-- | engines/scumm/file.cpp | 26 | ||||
-rw-r--r-- | engines/scumm/input.cpp | 12 | ||||
-rw-r--r-- | engines/scumm/resource_v2.cpp | 10 | ||||
-rw-r--r-- | engines/scumm/script_v0.cpp | 21 | ||||
-rw-r--r-- | engines/scumm/scumm-md5.h | 3 | ||||
-rw-r--r-- | engines/scumm/scumm.cpp | 16 | ||||
-rw-r--r-- | engines/scumm/scumm_v0.h | 4 | ||||
-rw-r--r-- | engines/scumm/verbs.cpp | 55 | ||||
-rw-r--r-- | engines/zvision/core/save_manager.cpp | 40 | ||||
-rw-r--r-- | engines/zvision/core/save_manager.h | 1 | ||||
-rw-r--r-- | engines/zvision/detection.cpp | 83 | ||||
-rw-r--r-- | engines/zvision/scripting/controls/save_control.cpp | 2 | ||||
-rw-r--r-- | engines/zvision/scripting/script_manager.cpp | 23 | ||||
-rw-r--r-- | engines/zvision/utility/clock.h | 3 | ||||
-rw-r--r-- | engines/zvision/utility/utility.cpp | 15 | ||||
-rw-r--r-- | engines/zvision/video/video.cpp | 2 | ||||
-rw-r--r-- | engines/zvision/zvision.cpp | 9 | ||||
-rw-r--r-- | engines/zvision/zvision.h | 8 |
22 files changed, 340 insertions, 100 deletions
diff --git a/devtools/scumm-md5.txt b/devtools/scumm-md5.txt index 37d7e7a5e1..62925e98fa 100644 --- a/devtools/scumm-md5.txt +++ b/devtools/scumm-md5.txt @@ -52,6 +52,7 @@ maniac Maniac Mansion 2d624d1b214f7faf0094daea65c6d1a6 -1 en 2gs Apple II - - + 2cb46375dd5cdfd023e2f07e0a21b530 -1 en C64 C64 Demo - Robert Crossfield eea4d9ac2fb6f145945a308e8866915b -1 en C64 C64 - - 439a7f4adf510489981ac52308e7d7a2 -1 de C64 C64 - - diff --git a/engines/scumm/actor.cpp b/engines/scumm/actor.cpp index 07c8f84be7..6cbb2a4e45 100644 --- a/engines/scumm/actor.cpp +++ b/engines/scumm/actor.cpp @@ -43,12 +43,60 @@ namespace Scumm { byte Actor::kInvalidBox = 0; -static const byte v0ActorTalkArray[0x19] = { - 0x00, 0x06, 0x06, 0x06, 0x06, - 0x06, 0x06, 0x00, 0x46, 0x06, - 0x06, 0x06, 0x06, 0xFF, 0xFF, - 0x06, 0xC0, 0x06, 0x06, 0x00, - 0xC0, 0xC0, 0x00, 0x06, 0x06 +static const byte v0ActorDemoTalk[25] = { + 0x00, + 0x06, // Syd + 0x06, // Razor + 0x06, // Dave + 0x06, // Michael + 0x06, // Bernard + 0x06, // Wendy + 0x00, // Jeff + 0x46, // Radiation Suit + 0x06, // Dr Fred + 0x06, // Nurse Edna + 0x06, // Weird Ed + 0x06, // Dead Cousin Ted + 0xE2, // Purple Tentacle + 0xE2, // Green Tentacle + 0x06, // Meteor police + 0xC0, // Meteor + 0x06, // Mark Eteer + 0x06, // Talkshow Host + 0x00, // Plant + 0xC0, // Meteor Radiation + 0xC0, // Edsel (small, outro) + 0x00, // Meteor (small, intro) + 0x06, // Sandy (Lab) + 0x06, // Sandy (Cut-Scene) +}; + +static const byte v0ActorTalk[25] = { + 0x00, + 0x06, // Syd + 0x06, // Razor + 0x06, // Dave + 0x06, // Michael + 0x06, // Bernard + 0x06, // Wendy + 0x00, // Jeff + 0x46, // Radiation Suit + 0x06, // Dr Fred + 0x06, // Nurse Edna + 0x06, // Weird Ed + 0x06, // Dead Cousin Ted + 0xFF, // Purple Tentacle + 0xFF, // Green Tentacle + 0x06, // Meteor police + 0xC0, // Meteor + 0x06, // Mark Eteer + 0x06, // Talkshow Host + 0x00, // Plant + 0xC0, // Meteor Radiation + 0xC0, // Edsel (small, outro) + 0x00, // Meteor (small, intro) + 0x06, // Sandy (Lab) + 0x06, // Sandy (Cut-Scene) }; static const byte v0WalkboxSlantedModifier[0x16] = { @@ -210,6 +258,12 @@ void Actor_v0::initActor(int mode) { _limbFrameRepeat[i] = 0; _limb_flipped[i] = false; } + + if (_vm->_game.features & GF_DEMO) { + _sound[0] = v0ActorDemoTalk[_number]; + } else { + _sound[0] = v0ActorTalk[_number]; + } } void Actor::setBox(int box) { @@ -1771,34 +1825,6 @@ void ScummEngine::showActors() { } } -// bits 0..5: sound, bit 6: ??? -static const byte v0ActorSounds[24] = { - 0x06, // Syd - 0x06, // Razor - 0x06, // Dave - 0x06, // Michael - 0x06, // Bernard - 0x06, // Wendy - 0x00, // Jeff - 0x46, // Radiation Suit - 0x06, // Dr Fred - 0x06, // Nurse Edna - 0x06, // Weird Ed - 0x06, // Dead Cousin Ted - 0xFF, // Purple Tentacle - 0xFF, // Green Tentacle - 0x06, // Meteor police - 0xC0, // Meteor - 0x06, // Mark Eteer - 0x06, // Talkshow Host - 0x00, // Plant - 0xC0, // Meteor Radiation - 0xC0, // Edsel (small, outro) - 0x00, // Meteor (small, intro) - 0x06, // Sandy (Lab) - 0x06, // Sandy (Cut-Scene) -}; - /* Used in Scumm v5 only. Play sounds associated with actors */ void ScummEngine::playActorSounds() { int i, j; @@ -1808,7 +1834,7 @@ void ScummEngine::playActorSounds() { if (_actors[i]->_cost.soundCounter && _actors[i]->isInCurrentRoom()) { _currentScript = 0xFF; if (_game.version == 0) { - sound = v0ActorSounds[i - 1] & 0x3F; + sound = _actors[i]->_sound[0] & 0x3F; } else { sound = _actors[i]->_sound[0]; } @@ -1968,7 +1994,7 @@ void ScummEngine::processActors() { // Is this the correct location? // 0x073C - if (v0ActorTalkArray[a0->_number] & 0x3F) + if (a0->_sound[0] & 0x3F) a0->_cost.soundPos = (a0->_cost.soundPos + 1) % 3; } } @@ -2277,7 +2303,7 @@ void Actor::startAnimActor(int f) { void Actor_v0::startAnimActor(int f) { if (f == _talkStartFrame) { - if (v0ActorTalkArray[_number] & 0x40) + if (_sound[0] & 0x40) return; _speaking = 1; @@ -2383,7 +2409,7 @@ void Actor_v0::animateCostume() { } void Actor_v0::speakCheck() { - if (v0ActorTalkArray[_number] & 0x80) + if (_sound[0] & 0x80) return; int cmd = newDirToOldDir(_facing); diff --git a/engines/scumm/detection.cpp b/engines/scumm/detection.cpp index c0db0d6d37..45647c9bed 100644 --- a/engines/scumm/detection.cpp +++ b/engines/scumm/detection.cpp @@ -323,6 +323,8 @@ static BaseScummFile *openDiskImage(const Common::FSNode &node, const GameFilena gs.gameid = gfp->gameid; gs.id = (Common::String(gfp->gameid) == "maniac" ? GID_MANIAC : GID_ZAK); gs.platform = gfp->platform; + if (strcmp(gfp->pattern, "maniacdemo.d64") == 0) + gs.features |= GF_DEMO; // determine second disk file name Common::String disk2(disk1); diff --git a/engines/scumm/detection_tables.h b/engines/scumm/detection_tables.h index f72e552fa6..82a8b4452b 100644 --- a/engines/scumm/detection_tables.h +++ b/engines/scumm/detection_tables.h @@ -207,6 +207,7 @@ static const Engines::ObsoleteGameID obsoleteGameIDsTable[] = { static const GameSettings gameVariantsTable[] = { {"maniac", "Apple II", 0, GID_MANIAC, 0, 0, MDT_APPLEIIGS, 0, Common::kPlatformApple2GS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"maniac", "C64", 0, GID_MANIAC, 0, 0, MDT_C64, 0, Common::kPlatformC64, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI) }, + {"maniac", "C64 Demo", 0, GID_MANIAC, 0, 0, MDT_C64, GF_DEMO, Common::kPlatformC64, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI) }, {"maniac", "V1", "v1", GID_MANIAC, 1, 0, MDT_PCSPK | MDT_PCJR, 0, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"maniac", "V1 Demo", "v1", GID_MANIAC, 1, 0, MDT_PCSPK | MDT_PCJR, GF_DEMO, Common::kPlatformDOS, GUIO2(GUIO_NOSPEECH, GUIO_NOMIDI)}, {"maniac", "NES", 0, GID_MANIAC, 1, 0, MDT_NONE, 0, Common::kPlatformNES, GUIO3(GUIO_NOSPEECH, GUIO_NOMIDI, GUIO_NOASPECT)}, @@ -448,6 +449,7 @@ static const GameFilenamePattern gameFilenamesTable[] = { { "maniac", "%02d.MAN", kGenRoomNum, UNK_LANG, UNK, "V1 Demo" }, { "maniac", "maniac1.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "C64" }, // ... and maniac2.d64 { "maniac", "maniac1.dsk", kGenUnchanged, UNK_LANG, Common::kPlatformApple2GS, "Apple II" }, // ... and maniac2.dsk + { "maniac", "maniacdemo.d64", kGenUnchanged, UNK_LANG, Common::kPlatformC64, "C64 Demo" }, { "maniac", "Maniac Mansion (E).prg", kGenUnchanged, Common::EN_GRB, Common::kPlatformNES, "NES" }, { "maniac", "Maniac Mansion (F).prg", kGenUnchanged, Common::FR_FRA, Common::kPlatformNES, "NES" }, { "maniac", "Maniac Mansion (SW).prg", kGenUnchanged, Common::SE_SWE, Common::kPlatformNES, "NES" }, diff --git a/engines/scumm/file.cpp b/engines/scumm/file.cpp index 475ffa3238..96b46aa21a 100644 --- a/engines/scumm/file.cpp +++ b/engines/scumm/file.cpp @@ -221,6 +221,15 @@ static const int maniacResourcesPerFile[55] = { 3, 10, 1, 0, 0 }; +static const int maniacDemoResourcesPerFile[55] = { + 0, 12, 0, 2, 1, 12, 1, 13, 6, 0, + 31, 0, 1, 0, 0, 0, 0, 1, 1, 1, + 0, 1, 0, 0, 2, 0, 0, 1, 0, 0, + 2, 7, 1, 11, 0, 0, 5, 1, 0, 0, + 1, 0, 1, 3, 4, 3, 1, 0, 0, 1, + 2, 2, 0, 0, 0 +}; + static const int zakResourcesPerFile[59] = { 0, 29, 12, 14, 13, 4, 4, 10, 7, 4, 14, 19, 5, 4, 7, 6, 11, 9, 4, 4, @@ -253,9 +262,17 @@ ScummDiskImage::ScummDiskImage(const char *disk1, const char *disk2, GameSetting _numGlobalObjects = 256; _numRooms = 55; _numCostumes = 25; - _numScripts = 160; - _numSounds = 70; - _resourcesPerFile = maniacResourcesPerFile; + + if (_game.features & GF_DEMO) { + _numScripts = 55; + _numSounds = 40; + _resourcesPerFile = maniacDemoResourcesPerFile; + } else { + _numScripts = 160; + _numSounds = 70; + _resourcesPerFile = maniacResourcesPerFile; + } + } else { _numGlobalObjects = 775; _numRooms = 59; @@ -327,6 +344,9 @@ bool ScummDiskImage::open(const Common::String &filename) { extractIndex(0); // Fill in resource arrays + if (_game.features & GF_DEMO) + return true; + openDisk(2); if (_game.platform == Common::kPlatformApple2GS) { diff --git a/engines/scumm/input.cpp b/engines/scumm/input.cpp index 824dfec144..86048af57c 100644 --- a/engines/scumm/input.cpp +++ b/engines/scumm/input.cpp @@ -452,8 +452,16 @@ void ScummEngine_v2::processKeyboard(Common::KeyState lastKeyHit) { lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE); // F7 is used to skip cutscenes in the Commodote 64 version of Maniac Mansion } else if (_game.id == GID_MANIAC &&_game.platform == Common::kPlatformC64) { - if (lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0)) - lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE); + // Demo always F7 to be pressed to restart + if (_game.features & GF_DEMO) { + if (_roomResource != 0x2D && lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0)) { + restart(); + return; + } + } else { + if (lastKeyHit.keycode == Common::KEYCODE_F7 && lastKeyHit.hasFlags(0)) + lastKeyHit = Common::KeyState(Common::KEYCODE_ESCAPE); + } // 'B' is used to skip cutscenes in the NES version of Maniac Mansion } else if (_game.id == GID_MANIAC &&_game.platform == Common::kPlatformNES) { if (lastKeyHit.keycode == Common::KEYCODE_b && lastKeyHit.hasFlags(Common::KBD_SHIFT)) diff --git a/engines/scumm/resource_v2.cpp b/engines/scumm/resource_v2.cpp index 7ccdfa4780..87dc132ff0 100644 --- a/engines/scumm/resource_v2.cpp +++ b/engines/scumm/resource_v2.cpp @@ -34,8 +34,14 @@ void ScummEngine_v2::readClassicIndexFile() { _numGlobalObjects = 256; _numRooms = 55; _numCostumes = 25; - _numScripts = 160; - _numSounds = 70; + if (_game.features & GF_DEMO) { + _numScripts = 55; + _numSounds = 40; + } else { + _numScripts = 160; + _numSounds = 70; + } + } else if (_game.platform == Common::kPlatformNES) { _numGlobalObjects = 775; _numRooms = 55; diff --git a/engines/scumm/script_v0.cpp b/engines/scumm/script_v0.cpp index 90291535fd..609cbd1e89 100644 --- a/engines/scumm/script_v0.cpp +++ b/engines/scumm/script_v0.cpp @@ -172,7 +172,7 @@ void ScummEngine_v0::setupOpcodes() { /* 6C */ OPCODE(0x6c, o_stopCurrentScript); OPCODE(0x6d, o2_putActorInRoom); - OPCODE(0x6e, o2_dummy); + OPCODE(0x6e, o_screenPrepare); OPCODE(0x6f, o2_ifState08); /* 70 */ OPCODE(0x70, o_lights); @@ -633,12 +633,21 @@ void ScummEngine_v0::setMode(byte mode) { switch (_currentMode) { case kModeCutscene: + if (_game.features & GF_DEMO) { + if (VAR(11) != 0) + _drawDemo = true; + } _redrawSentenceLine = false; // Note: do not change freeze state here state = USERSTATE_SET_IFACE | USERSTATE_SET_CURSOR; + break; case kModeKeypad: + if (_game.features & GF_DEMO) { + if (VAR(11) != 0) + _drawDemo = true; + } _redrawSentenceLine = false; state = USERSTATE_SET_IFACE | USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | @@ -646,6 +655,12 @@ void ScummEngine_v0::setMode(byte mode) { break; case kModeNormal: case kModeNoNewKid: + if (_game.features & GF_DEMO) { + resetVerbs(); + _activeVerb = kVerbWalkTo; + _redrawSentenceLine = true; + _drawDemo = false; + } state = USERSTATE_SET_IFACE | USERSTATE_IFACE_ALL | USERSTATE_SET_CURSOR | USERSTATE_CURSOR_ON | USERSTATE_SET_FREEZE; @@ -967,6 +982,10 @@ void ScummEngine_v0::o_setOwnerOf() { setOwnerOf(obj, owner); } +void ScummEngine_v0::o_screenPrepare() { + +} + void ScummEngine_v0::resetSentence() { _activeVerb = kVerbWalkTo; _activeObject = 0; diff --git a/engines/scumm/scumm-md5.h b/engines/scumm/scumm-md5.h index 4a34894506..5be18fb990 100644 --- a/engines/scumm/scumm-md5.h +++ b/engines/scumm/scumm-md5.h @@ -1,5 +1,5 @@ /* - This file was generated by the md5table tool on Sat Nov 29 19:54:41 2014 + This file was generated by the md5table tool on Sun Dec 7 23:09:10 2014 DO NOT EDIT MANUALLY! */ @@ -135,6 +135,7 @@ static const MD5Table md5table[] = { { "2a446817ffcabfef8716e0c456ecaf81", "puttzoo", "", "Demo", -1, Common::DE_DEU, Common::kPlatformWindows }, { "2a8658dbd13d84d1bce64a71a35995eb", "pajama2", "HE 99", "Demo", -1, Common::HE_ISR, Common::kPlatformWindows }, { "2c04aacffb8428f30ccf4f734fbe3adc", "activity", "", "", -1, Common::EN_ANY, Common::kPlatformDOS }, + { "2cb46375dd5cdfd023e2f07e0a21b530", "maniac", "C64", "Demo", -1, Common::EN_ANY, Common::kPlatformC64 }, { "2ccd8891ce4d3f1a334d21bff6a88ca2", "monkey", "CD", "", 9455, Common::EN_ANY, Common::kPlatformMacintosh }, { "2d1e891fe52df707c30185e52c50cd92", "monkey", "CD", "CD", 8955, Common::EN_ANY, Common::kPlatformDOS }, { "2d388339d6050d8ccaa757b64633954e", "indyloom", "FM-TOWNS", "Demo", 7520, Common::EN_ANY, Common::kPlatformFMTowns }, diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index 475b146a7b..6040344c2c 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -716,7 +716,7 @@ ScummEngine_v2::ScummEngine_v2(OSystem *syst, const DetectorResult &dr) ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr) : ScummEngine_v2(syst, dr) { - + _drawDemo = false; _currentMode = 0; _currentLights = 0; @@ -731,6 +731,9 @@ ScummEngine_v0::ScummEngine_v0(OSystem *syst, const DetectorResult &dr) VAR_ACTIVE_OBJECT2 = 0xFF; VAR_IS_SOUND_RUNNING = 0xFF; VAR_ACTIVE_VERB = 0xFF; + + if (strcmp(dr.fp.pattern, "maniacdemo.d64") == 0 ) + _game.features |= GF_DEMO; } ScummEngine_v6::ScummEngine_v6(OSystem *syst, const DetectorResult &dr) @@ -1091,8 +1094,13 @@ Common::Error ScummEngine::init() { const char *tmpBuf1, *tmpBuf2; assert(_game.id == GID_MANIAC || _game.id == GID_ZAK); if (_game.id == GID_MANIAC) { - tmpBuf1 = "maniac1.d64"; - tmpBuf2 = "maniac2.d64"; + if (_game.features & GF_DEMO) { + tmpBuf1 = "maniacdemo.d64"; + tmpBuf2 = "maniacdemo.d64"; + } else { + tmpBuf1 = "maniac1.d64"; + tmpBuf2 = "maniac2.d64"; + } } else { tmpBuf1 = "zak1.d64"; tmpBuf2 = "zak2.d64"; @@ -2572,7 +2580,7 @@ void ScummEngine::runBootscript() { int args[NUM_SCRIPT_LOCAL]; memset(args, 0, sizeof(args)); args[0] = _bootParam; - if (_game.id == GID_MANIAC && (_game.features & GF_DEMO)) + if (_game.id == GID_MANIAC && (_game.features & GF_DEMO) && (_game.platform != Common::kPlatformC64)) runScript(9, 0, 0, args); else runScript(1, 0, 0, args); diff --git a/engines/scumm/scumm_v0.h b/engines/scumm/scumm_v0.h index 83e0e32e15..4098d639c4 100644 --- a/engines/scumm/scumm_v0.h +++ b/engines/scumm/scumm_v0.h @@ -46,6 +46,7 @@ protected: }; protected: + bool _drawDemo; byte _currentMode; byte _currentLights; @@ -101,6 +102,8 @@ protected: virtual void handleMouseOver(bool updateInventory); int verbPrepIdType(int verbid); void resetVerbs(); + void verbDemoMode(); + void verbDrawDemoString(int VerbDemoNumber); void clearSentenceLine(); void flushSentenceLine(); @@ -163,6 +166,7 @@ protected: void o_cutscene(); void o_endCutscene(); void o_setOwnerOf(); + void o_screenPrepare(); byte VAR_ACTIVE_OBJECT2; byte VAR_IS_SOUND_RUNNING; diff --git a/engines/scumm/verbs.cpp b/engines/scumm/verbs.cpp index bf0a693467..fe936b550c 100644 --- a/engines/scumm/verbs.cpp +++ b/engines/scumm/verbs.cpp @@ -80,6 +80,19 @@ static const VerbSettings v0VerbTable_German[] = { {kVerbWhatIs, 13, 2, "Was ist"} }; +struct VerbDemo { + int color; + const char *str; +}; +static VerbDemo v0DemoStr[] = { + {7, " MANIAC MANSION DEMO DISK "}, + {5, " from Lucasfilm Games "}, + {5, " Copyright = 1987 by Lucasfilm Ltd. "}, + {5, " All Rights Reserved. "}, + {0, " "}, + {16, " Press F7 to return to menu. "} +}; + int ScummEngine_v0::verbPrepIdType(int verbid) { switch (verbid) { case kVerbUse: // depends on object1 @@ -93,6 +106,44 @@ int ScummEngine_v0::verbPrepIdType(int verbid) { } } +void ScummEngine_v0::verbDemoMode() { + int i; + + for (i = 1; i < 16; i++) + killVerb(i); + + for (i = 0; i < 6; i++) { + verbDrawDemoString(i); + } +} + +void ScummEngine_v0::verbDrawDemoString(int VerbDemoNumber) { + byte string[80]; + const char *ptr = v0DemoStr[VerbDemoNumber].str; + int i = 0, len = 0; + + // Maximum length of printable characters + int maxChars = 40; + while (*ptr) { + if (*ptr != '@') + len++; + if (len > maxChars) { + break; + } + + string[i++] = *ptr++; + + } + string[i] = 0; + + _string[2].charset = 1; + _string[2].ypos = _virtscr[kVerbVirtScreen].topline + (8 * VerbDemoNumber); + _string[2].xpos = 0; + _string[2].right = _virtscr[kVerbVirtScreen].w - 1; + _string[2].color = v0DemoStr[VerbDemoNumber].color; + drawString(2, (byte *)string); +} + void ScummEngine_v0::resetVerbs() { VirtScreen *virt = &_virtscr[kVerbVirtScreen]; VerbSlot *vs; @@ -854,6 +905,10 @@ void ScummEngine_v0::checkExecVerbs() { } } } + + if (_drawDemo && _game.features & GF_DEMO) { + verbDemoMode(); + } if (_redrawSentenceLine) drawSentenceLine(); diff --git a/engines/zvision/core/save_manager.cpp b/engines/zvision/core/save_manager.cpp index 11d3dd391a..20bd39fde5 100644 --- a/engines/zvision/core/save_manager.cpp +++ b/engines/zvision/core/save_manager.cpp @@ -23,22 +23,60 @@ #include "common/scummsys.h" #include "zvision/core/save_manager.h" - #include "zvision/zvision.h" #include "zvision/scripting/script_manager.h" #include "zvision/graphics/render_manager.h" #include "common/system.h" +#include "common/translation.h" #include "graphics/surface.h" #include "graphics/thumbnail.h" #include "gui/message.h" +#include "gui/saveload.h" namespace ZVision { const uint32 SaveManager::SAVEGAME_ID = MKTAG('Z', 'E', 'N', 'G'); +bool SaveManager::scummVMSaveLoadDialog(bool isSave) { + GUI::SaveLoadChooser *dialog; + Common::String desc; + int slot; + + if (isSave) { + dialog = new GUI::SaveLoadChooser(_("Save game:"), _("Save"), true); + + slot = dialog->runModalWithCurrentTarget(); + desc = dialog->getResultString(); + + if (desc.empty()) { + // create our own description for the saved game, the user didnt enter it + desc = dialog->createDefaultSaveDescription(slot); + } + + if (desc.size() > 28) + desc = Common::String(desc.c_str(), 28); + } else { + dialog = new GUI::SaveLoadChooser(_("Restore game:"), _("Restore"), false); + slot = dialog->runModalWithCurrentTarget(); + } + + delete dialog; + + if (slot < 0) + return false; + + if (isSave) { + saveGame(slot, desc); + return true; + } else { + Common::ErrorCode result = loadGame(slot).getCode(); + return (result == Common::kNoError); + } +} + void SaveManager::saveGame(uint slot, const Common::String &saveName) { // The games only support 20 slots //assert(slot <= 1 && slot <= 20); diff --git a/engines/zvision/core/save_manager.h b/engines/zvision/core/save_manager.h index 5cd61c7aa9..75841331e7 100644 --- a/engines/zvision/core/save_manager.h +++ b/engines/zvision/core/save_manager.h @@ -96,6 +96,7 @@ public: void prepareSaveBuffer(); void flushSaveBuffer(); + bool scummVMSaveLoadDialog(bool isSave); private: void writeSaveGameHeader(Common::OutSaveFile *file, const Common::String &saveName); }; diff --git a/engines/zvision/detection.cpp b/engines/zvision/detection.cpp index 4d210abe86..ebf5bdcfdd 100644 --- a/engines/zvision/detection.cpp +++ b/engines/zvision/detection.cpp @@ -26,6 +26,8 @@ #include "zvision/zvision.h" #include "zvision/detection.h" +#include "zvision/core/save_manager.h" +#include "zvision/scripting/script_manager.h" #include "common/translation.h" #include "common/savefile.h" @@ -178,24 +180,40 @@ public: }; bool ZVisionMetaEngine::hasFeature(MetaEngineFeature f) const { - return false; - /* + return (f == kSupportsListSaves) || (f == kSupportsLoadingDuringStartup) || (f == kSupportsDeleteSave) || (f == kSavesSupportMetaInfo) || (f == kSavesSupportThumbnail) || - (f == kSavesSupportCreationDate) || - (f == kSavesSupportPlayTime); - */ + (f == kSavesSupportCreationDate); + //(f == kSavesSupportPlayTime); } -/*bool ZVision::ZVision::hasFeature(EngineFeature f) const { +bool ZVision::ZVision::hasFeature(EngineFeature f) const { return (f == kSupportsRTL) || (f == kSupportsLoadingDuringRuntime) || (f == kSupportsSavingDuringRuntime); -}*/ +} + +Common::Error ZVision::ZVision::loadGameState(int slot) { + return _saveManager->loadGame(slot); +} + +Common::Error ZVision::ZVision::saveGameState(int slot, const Common::String &desc) { + _saveManager->saveGame(slot, desc); + return Common::kNoError; +} + +bool ZVision::ZVision::canLoadGameStateCurrently() { + return !_videoIsPlaying; +} + +bool ZVision::ZVision::canSaveGameStateCurrently() { + Location currentLocation = _scriptManager->getCurrentLocation(); + return !_videoIsPlaying && currentLocation.world != 'g' && !(currentLocation.room == 'j' || currentLocation.room == 'a'); +} bool ZVisionMetaEngine::createInstance(OSystem *syst, Engine **engine, const ADGameDescription *desc) const { const ZVision::ZVisionGameDescription *gd = (const ZVision::ZVisionGameDescription *)desc; @@ -213,8 +231,8 @@ const ExtraGuiOptions ZVisionMetaEngine::getExtraGuiOptions(const Common::String } SaveStateList ZVisionMetaEngine::listSaves(const char *target) const { - //Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - /*ZVision::ZVision::SaveHeader header; + Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); + ZVision::SaveGameHeader header; Common::String pattern = target; pattern += ".???"; @@ -223,20 +241,25 @@ SaveStateList ZVisionMetaEngine::listSaves(const char *target) const { Common::sort(filenames.begin(), filenames.end()); // Sort (hopefully ensuring we are sorted numerically..)*/ SaveStateList saveList; - /* for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) { + // We only use readSaveGameHeader() here, which doesn't need an engine callback + ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL); + + for (Common::StringArray::const_iterator file = filenames.begin(); file != filenames.end(); file++) { // Obtain the last 3 digits of the filename, since they correspond to the save slot int slotNum = atoi(file->c_str() + file->size() - 3); if (slotNum >= 0 && slotNum <= 999) { Common::InSaveFile *in = saveFileMan->openForLoading(file->c_str()); if (in) { - if (ZVision::ZVision::readSaveHeader(in, false, header) == ZVision::ZVision::kRSHENoError) { - saveList.push_back(SaveStateDescriptor(slotNum, header.description)); + if (zvisionSaveMan->readSaveGameHeader(in, header)) { + saveList.push_back(SaveStateDescriptor(slotNum, header.saveName)); } delete in; } } - }*/ + } + + delete zvisionSaveMan; return saveList; } @@ -246,9 +269,8 @@ int ZVisionMetaEngine::getMaximumSaveSlot() const { } void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const { - /* Common::SaveFileManager *saveFileMan = g_system->getSavefileManager(); - Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot); + Common::String filename = Common::String::format("%s.%03u", target, slot); saveFileMan->removeSavefile(filename.c_str()); @@ -265,48 +287,47 @@ void ZVisionMetaEngine::removeSaveState(const char *target, int slot) const { // Rename every slot greater than the deleted slot, if (slotNum > slot) { saveFileMan->renameSavefile(file->c_str(), filename.c_str()); - filename = ZVision::ZVision::getSavegameFilename(target, ++slot); + filename = Common::String::format("%s.%03u", target, ++slot); } } - */ } SaveStateDescriptor ZVisionMetaEngine::querySaveMetaInfos(const char *target, int slot) const { - /* - Common::String filename = ZVision::ZVision::getSavegameFilename(target, slot); + Common::String filename = Common::String::format("%s.%03u", target, slot); Common::InSaveFile *in = g_system->getSavefileManager()->openForLoading(filename.c_str()); if (in) { - ZVision::ZVision::SaveHeader header; - ZVision::ZVision::kReadSaveHeaderError error; + ZVision::SaveGameHeader header; - error = ZVision::ZVision::readSaveHeader(in, true, header); + // We only use readSaveGameHeader() here, which doesn't need an engine callback + ZVision::SaveManager *zvisionSaveMan = new ZVision::SaveManager(NULL); + bool successfulRead = zvisionSaveMan->readSaveGameHeader(in, header); + delete zvisionSaveMan; delete in; - if (error == ZVision::ZVision::kRSHENoError) { - SaveStateDescriptor desc(slot, header.description); + if (successfulRead) { + SaveStateDescriptor desc(slot, header.saveName); desc.setThumbnail(header.thumbnail); if (header.version > 0) { - int day = (header.saveDate >> 24) & 0xFF; - int month = (header.saveDate >> 16) & 0xFF; - int year = header.saveDate & 0xFFFF; + int day = header.saveDay; + int month = header.saveMonth; + int year = header.saveYear; desc.setSaveDate(year, month, day); - int hour = (header.saveTime >> 16) & 0xFF; - int minutes = (header.saveTime >> 8) & 0xFF; + int hour = header.saveHour; + int minutes = header.saveMinutes; desc.setSaveTime(hour, minutes); - desc.setPlayTime(header.playTime * 1000); + //desc.setPlayTime(header.playTime * 1000); } return desc; } } - */ return SaveStateDescriptor(); } diff --git a/engines/zvision/scripting/controls/save_control.cpp b/engines/zvision/scripting/controls/save_control.cpp index ad01257e6b..d773b5fc6f 100644 --- a/engines/zvision/scripting/controls/save_control.cpp +++ b/engines/zvision/scripting/controls/save_control.cpp @@ -101,6 +101,8 @@ bool SaveControl::process(uint32 deltaTimeInMillis) { toSave = false; if (toSave) { + // FIXME: At this point, the screen shows the save control, so the save game thumbnails will always + // show the save control _engine->getSaveManager()->saveGameBuffered(iter->saveId, inp->getText()); _engine->delayedMessage(_engine->getStringManager()->getTextLine(StringManager::ZVISION_STR_SAVED), 2000); _engine->getScriptManager()->changeLocation(_engine->getScriptManager()->getLastMenuLocation()); diff --git a/engines/zvision/scripting/script_manager.cpp b/engines/zvision/scripting/script_manager.cpp index 7904817156..c532a2b15d 100644 --- a/engines/zvision/scripting/script_manager.cpp +++ b/engines/zvision/scripting/script_manager.cpp @@ -36,6 +36,7 @@ #include "common/hashmap.h" #include "common/debug.h" #include "common/stream.h" +#include "common/config-manager.h" namespace ZVision { @@ -521,6 +522,28 @@ void ScriptManager::ChangeLocationReal() { assert(_nextLocation.world != 0); debug(1, "Changing location to: %c %c %c %c %u", _nextLocation.world, _nextLocation.room, _nextLocation.node, _nextLocation.view, _nextLocation.offset); + if (_nextLocation.world == 'g' && _nextLocation.room == 'j' && !ConfMan.getBool("originalsaveload")) { + if ((_nextLocation.node == 's' || _nextLocation.node == 'r') && _nextLocation.view == 'e') { + // Hook up the ScummVM save/restore dialog + bool isSave = (_nextLocation.node == 's'); + bool gameSavedOrLoaded = _engine->getSaveManager()->scummVMSaveLoadDialog(isSave); + if (!gameSavedOrLoaded || isSave) { + // Reload the current room + _nextLocation.world = _currentLocation.world; + _nextLocation.room = _currentLocation.room; + _nextLocation.node = _currentLocation.node; + _nextLocation.view = _currentLocation.view; + _nextLocation.offset = _currentLocation.offset; + _currentLocation.world = '0'; + _currentLocation.room = '0'; + _currentLocation.node = '0'; + _currentLocation.view = '0'; + _currentLocation.offset = 0; + } else + return; + } + } + _engine->setRenderDelay(2); if (getStateValue(StateKey_World) != 'g' || getStateValue(StateKey_Room) != 'j') { diff --git a/engines/zvision/utility/clock.h b/engines/zvision/utility/clock.h index 9a50116a8c..cbf52be560 100644 --- a/engines/zvision/utility/clock.h +++ b/engines/zvision/utility/clock.h @@ -47,6 +47,7 @@ public: * when the last update() was called. */ void update(); + /** * Get the delta time since the last frame. (The time between update() calls) * @@ -55,6 +56,7 @@ public: uint32 getDeltaTime() const { return _deltaTime; } + /** * Get the time from the program starting to the last update() call * @@ -69,6 +71,7 @@ public: * Has no effect if the clock is already paused. */ void start(); + /** * Un-pause the clock. * Has no effect if the clock is already un-paused. diff --git a/engines/zvision/utility/utility.cpp b/engines/zvision/utility/utility.cpp index 2388fe826e..e09545a90d 100644 --- a/engines/zvision/utility/utility.cpp +++ b/engines/zvision/utility/utility.cpp @@ -42,19 +42,4 @@ void trimCommentsAndWhiteSpace(Common::String *string) { string->trim(); } -void tryToDumpLine(const Common::String &key, - Common::String &line, - Common::HashMap<Common::String, byte> *count, - Common::HashMap<Common::String, bool> *fileAlreadyUsed, - Common::DumpFile &output) { - const byte numberOfExamplesPerType = 8; - - if ((*count)[key] < numberOfExamplesPerType && !(*fileAlreadyUsed)[key]) { - output.writeString(line); - output.writeByte('\n'); - (*count)[key]++; - (*fileAlreadyUsed)[key] = true; - } -} - } // End of namespace ZVision diff --git a/engines/zvision/video/video.cpp b/engines/zvision/video/video.cpp index 36b5f9b921..db6161bf0c 100644 --- a/engines/zvision/video/video.cpp +++ b/engines/zvision/video/video.cpp @@ -53,6 +53,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, _clock.stop(); vid.start(); + _videoIsPlaying = true; // Only continue while the video is still playing while (!shouldQuit() && !vid.endOfVideo() && vid.isPlaying()) { @@ -99,6 +100,7 @@ void ZVision::playVideo(Video::VideoDecoder &vid, const Common::Rect &destRect, _system->delayMillis(vid.getTimeToNextFrame() / 2); } + _videoIsPlaying = false; _clock.start(); if (scaled) { diff --git a/engines/zvision/zvision.cpp b/engines/zvision/zvision.cpp index af9d26a350..8a44ccebea 100644 --- a/engines/zvision/zvision.cpp +++ b/engines/zvision/zvision.cpp @@ -96,7 +96,8 @@ ZVision::ZVision(OSystem *syst, const ZVisionGameDescription *gameDesc) _audioId(0), _rendDelay(2), _kbdVelocity(0), - _mouseVelocity(0) { + _mouseVelocity(0), + _videoIsPlaying(false) { debug(1, "ZVision::ZVision"); @@ -205,6 +206,10 @@ void ZVision::initialize() { Common::Error ZVision::run() { initialize(); + // Check if a saved game is to be loaded from the launcher + if (ConfMan.hasKey("save_slot")) + _saveManager->loadGame(ConfMan.getInt("save_slot")); + // Main loop while (!shouldQuit()) { _clock.update(); @@ -327,7 +332,7 @@ void ZVision::pauseEngineIntern(bool pause) { } Common::String ZVision::generateSaveFileName(uint slot) { - return Common::String::format("%s.%02u", _targetName.c_str(), slot); + return Common::String::format("%s.%03u", _targetName.c_str(), slot); } Common::String ZVision::generateAutoSaveFileName() { diff --git a/engines/zvision/zvision.h b/engines/zvision/zvision.h index ca6c8e10e4..5850bf66cd 100644 --- a/engines/zvision/zvision.h +++ b/engines/zvision/zvision.h @@ -124,6 +124,7 @@ private: int16 _mouseVelocity; int16 _kbdVelocity; bool _halveDelay; + bool _videoIsPlaying; uint8 _cheatBuff[KEYBUF_SIZE]; public: @@ -198,6 +199,13 @@ public: void checkBorders(); void showDebugMsg(const Common::String &msg, int16 delay = 3000); + + // Engine features + bool hasFeature(EngineFeature f) const; + bool canLoadGameStateCurrently(); + bool canSaveGameStateCurrently(); + Common::Error loadGameState(int slot); + Common::Error saveGameState(int slot, const Common::String &desc); private: void initialize(); void initFonts(); |