diff options
Diffstat (limited to 'engines')
77 files changed, 753 insertions, 978 deletions
diff --git a/engines/agi/preagi.cpp b/engines/agi/preagi.cpp index 1aa6ef5cc4..7457a317c2 100644 --- a/engines/agi/preagi.cpp +++ b/engines/agi/preagi.cpp @@ -42,8 +42,7 @@ namespace Agi { PreAgiEngine::PreAgiEngine(OSystem *syst, const AGIGameDescription *gameDesc) : AgiBase(syst, gameDesc) { // Setup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + syncSoundSettings(); _rnd = new Common::RandomSource(); diff --git a/engines/agos/agos.cpp b/engines/agos/agos.cpp index ae95bb0d2b..574031d047 100644 --- a/engines/agos/agos.cpp +++ b/engines/agos/agos.cpp @@ -1045,18 +1045,15 @@ uint32 AGOSEngine::getTime() const { } void AGOSEngine::syncSoundSettings() { - // Sync the engine with the config manager - int soundVolumeMusic = ConfMan.getInt("music_volume"); - int soundVolumeSFX = ConfMan.getInt("sfx_volume"); - int soundVolumeSpeech = ConfMan.getInt("speech_volume"); + Engine::syncSoundSettings(); bool mute = false; if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : (_musicPaused ? 0 : soundVolumeMusic))); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX)); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech)); + // Sync the engine with the config manager + int soundVolumeMusic = ConfMan.getInt("music_volume"); + int soundVolumeSFX = ConfMan.getInt("sfx_volume"); if (_midiEnabled) _midi.setVolume((mute ? 0 : soundVolumeMusic), (mute ? 0 : soundVolumeSFX)); diff --git a/engines/cine/cine.cpp b/engines/cine/cine.cpp index d80ab70660..54d113d69c 100644 --- a/engines/cine/cine.cpp +++ b/engines/cine/cine.cpp @@ -50,20 +50,15 @@ Sound *g_sound = 0; CineEngine *g_cine = 0; CineEngine::CineEngine(OSystem *syst, const CINEGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + // Setup mixer + syncSoundSettings(); + DebugMan.addDebugChannel(kCineDebugScript, "Script", "Script debug level"); DebugMan.addDebugChannel(kCineDebugPart, "Part", "Part debug level"); DebugMan.addDebugChannel(kCineDebugSound, "Sound", "Sound debug level"); DebugMan.addDebugChannel(kCineDebugCollision, "Collision", "Collision debug level"); _console = new CineConsole(this); - // Setup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - // Use music volume for plain sound types (At least the AdLib player uses a plain sound type - // so previously the music and sfx volume controls didn't affect it at all). - // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this. - _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("music_volume")); - g_cine = this; g_eventRec.registerRandomSource(_rnd, "cine"); @@ -78,6 +73,20 @@ CineEngine::~CineEngine() { delete _console; } +void CineEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + // Use music volume for plain sound types (At least the AdLib player uses a plain sound type + // so previously the music and sfx volume controls didn't affect it at all). + // FIXME: Make AdLib player differentiate between playing sound effects and music and remove this. + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, + mute ? 0 : ConfMan.getInt("music_volume")); +} + Common::Error CineEngine::run() { // Initialize backend initGraphics(320, 200, false); diff --git a/engines/cine/cine.h b/engines/cine/cine.h index 5f49a2907f..7de0bdc86f 100644 --- a/engines/cine/cine.h +++ b/engines/cine/cine.h @@ -117,6 +117,8 @@ public: CineEngine(OSystem *syst, const CINEGameDescription *gameDesc); virtual ~CineEngine(); + virtual void syncSoundSettings(); + int getGameType() const; uint32 getFeatures() const; Common::Language getLanguage() const; diff --git a/engines/cruise/cruise.cpp b/engines/cruise/cruise.cpp index c1ea711228..2c5659c4d9 100644 --- a/engines/cruise/cruise.cpp +++ b/engines/cruise/cruise.cpp @@ -52,16 +52,13 @@ CruiseEngine::CruiseEngine(OSystem * syst, const CRUISEGameDescription *gameDesc DebugMan.addDebugChannel(kCruiseDebugScript, "scripts", "Scripts debug level"); DebugMan.addDebugChannel(kCruiseDebugSound, "sound", "Sound debug level"); - // Setup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, - ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, - ConfMan.getInt("music_volume")); - _vm = this; _debugger = new Debugger(); _sound = new PCSound(_mixer, this); + // Setup mixer + syncSoundSettings(); + g_eventRec.registerRandomSource(_rnd, "cruise"); } @@ -235,6 +232,8 @@ const char *CruiseEngine::getSavegameFile(int saveGameIdx) { } void CruiseEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + _sound->syncSounds(); } diff --git a/engines/cruise/sound.cpp b/engines/cruise/sound.cpp index 8a4b1d0d2b..2826a34351 100644 --- a/engines/cruise/sound.cpp +++ b/engines/cruise/sound.cpp @@ -283,9 +283,21 @@ void PCSoundDriver::resetChannel(int channel) { } void PCSoundDriver::syncSounds() { + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + bool music_mute = mute; + bool sfx_mute = mute; + + if (!mute) { + music_mute = ConfMan.getBool("music_mute"); + sfx_mute = ConfMan.getBool("sfx_mute"); + } + // Get the new music and sfx volumes - _musicVolume = ConfMan.getBool("music_mute") ? 0 : MIN(255, ConfMan.getInt("music_volume")); - _sfxVolume = ConfMan.getBool("sfx_mute") ? 0 : MIN(255, ConfMan.getInt("sfx_volume")); + _musicVolume = music_mute ? 0 : MIN(255, ConfMan.getInt("music_volume")); + _sfxVolume = sfx_mute ? 0 : MIN(255, ConfMan.getInt("sfx_volume")); } AdLibSoundDriver::AdLibSoundDriver(Audio::Mixer *mixer) diff --git a/engines/draci/draci.cpp b/engines/draci/draci.cpp index d0eb511cbd..0bf2d5d34a 100644 --- a/engines/draci/draci.cpp +++ b/engines/draci/draci.cpp @@ -175,6 +175,9 @@ int DraciEngine::init() { _music->open(); //_music->setAdLib(adlib); + // Setup mixer + syncSoundSettings(); + // Load the game's fonts _smallFont = new Font(kFontSmall); _bigFont = new Font(kFontBig); diff --git a/engines/draci/sound.cpp b/engines/draci/sound.cpp index dc8f548d6b..c8646fff67 100644 --- a/engines/draci/sound.cpp +++ b/engines/draci/sound.cpp @@ -408,6 +408,9 @@ void Sound::stopVoice() { } void Sound::setVolume() { + _showSubtitles = ConfMan.getBool("subtitles"); + _talkSpeed = ConfMan.getInt("talkspeed"); + if (_mixer->isReady()) { _muteSound = ConfMan.getBool("sfx_mute"); _muteVoice = ConfMan.getBool("speech_mute"); @@ -417,10 +420,10 @@ void Sound::setVolume() { if (ConfMan.getBool("mute")) { _muteSound = _muteVoice = true; } - _showSubtitles = ConfMan.getBool("subtitles"); - _talkSpeed = ConfMan.getInt("talkspeed"); - const int soundVolume = ConfMan.getInt("sfx_volume"); - const int speechVolume = ConfMan.getInt("speech_volume"); + + const int soundVolume = _muteSound ? 0: ConfMan.getInt("sfx_volume"); + const int speechVolume = _muteVoice ? 0 : ConfMan.getInt("speech_volume"); + _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolume); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, speechVolume); } diff --git a/engines/drascula/drascula.cpp b/engines/drascula/drascula.cpp index b59ab6f566..19395dcd3f 100644 --- a/engines/drascula/drascula.cpp +++ b/engines/drascula/drascula.cpp @@ -195,8 +195,7 @@ Common::Error DrasculaEngine::run() { loadArchives(); // Setup mixer - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + syncSoundSettings(); currentChapter = 1; // values from 1 to 6 will start each part of game loadedDifferentChapter = 0; diff --git a/engines/engine.cpp b/engines/engine.cpp index 5ce0f99921..0e5e58bc72 100644 --- a/engines/engine.cpp +++ b/engines/engine.cpp @@ -430,7 +430,6 @@ int Engine::runDialog(GUI::Dialog &dialog) { } void Engine::syncSoundSettings() { - // Sync the engine with the config manager int soundVolumeMusic = ConfMan.getInt("music_volume"); int soundVolumeSFX = ConfMan.getInt("sfx_volume"); @@ -440,6 +439,7 @@ void Engine::syncSoundSettings() { if (ConfMan.hasKey("mute")) mute = ConfMan.getBool("mute"); + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (mute ? 0 : Audio::Mixer::kMaxMixerVolume)); _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, (mute ? 0 : soundVolumeMusic)); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, (mute ? 0 : soundVolumeSFX)); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, (mute ? 0 : soundVolumeSpeech)); diff --git a/engines/engine.h b/engines/engine.h index 508e9887ef..168a1dc2a0 100644 --- a/engines/engine.h +++ b/engines/engine.h @@ -163,6 +163,15 @@ public: * Notify the engine that the sound settings in the config manager may have * changed and that it hence should adjust any internal volume etc. values * accordingly. + * The default implementation sets the volume levels of all mixer sound + * types according to the config entries of the active domain. + * When overwriting, call the default implementation first, then adjust the + * volumes further (if required). + * + * @note When setting volume levels, respect the "mute" config entry. + * @note The volume for the plain sound type is reset to the maximum + * volume. If the engine can associate its own value for this + * type, it needs to overwrite this member and set it accordingly. * @todo find a better name for this */ virtual void syncSoundSettings(); diff --git a/engines/gob/detection_tables.h b/engines/gob/detection_tables.h index c779d5d764..b12fb81be1 100644 --- a/engines/gob/detection_tables.h +++ b/engines/gob/detection_tables.h @@ -3723,6 +3723,20 @@ static const GOBGameDescription gameDescriptions[] = { kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, + { // Supplied by Collector9 in bug report #3228040 + { + "urban", + "", + AD_ENTRY1s("intro.stk", "6ce3d878178932053267237ec4843ce1", 1252518), + EN_USA, + kPlatformPC, + ADGF_NO_FLAGS, + GUIO_NOSUBTITLES | GUIO_NOSPEECH + }, + kGameTypeUrban, + kFeatures640x480 | kFeaturesTrueColor, + 0, 0, 0 + }, { // Supplied by gamin in the forums { "urban", @@ -4935,7 +4949,7 @@ static const GOBGameDescription fallbackDescs[] = { GUIO_NOSUBTITLES | GUIO_NOSPEECH }, kGameTypeUrban, - kFeaturesCD | kFeaturesTrueColor, + kFeatures640x480 | kFeaturesTrueColor, 0, 0, 0 }, { //13 diff --git a/engines/gob/gob.cpp b/engines/gob/gob.cpp index b65bbe0d0f..12914163c2 100644 --- a/engines/gob/gob.cpp +++ b/engines/gob/gob.cpp @@ -575,6 +575,9 @@ bool GobEngine::initGameParts() { return false; } + // Setup mixer + syncSoundSettings(); + _inter->setupOpcodes(); return true; diff --git a/engines/groovie/groovie.cpp b/engines/groovie/groovie.cpp index 4a4f5e0de5..67c8f3dbc7 100644 --- a/engines/groovie/groovie.cpp +++ b/engines/groovie/groovie.cpp @@ -322,6 +322,8 @@ void GroovieEngine::errorString(const char *buf_input, char *buf_output, int buf } void GroovieEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + bool mute = ConfMan.getBool("mute"); // Set the music volume diff --git a/engines/hugo/display.cpp b/engines/hugo/display.cpp index aa4d4384c1..333eb59707 100644 --- a/engines/hugo/display.cpp +++ b/engines/hugo/display.cpp @@ -479,7 +479,7 @@ void Screen::shadowStr(int16 sx, const int16 sy, const char *s, const byte color * present in the DOS versions */ void Screen::userHelp() const { - Utils::Box(kBoxAny , "%s", + Utils::notifyBox( "F1 - Press F1 again\n" " for instructions\n" "F2 - Sound on/off\n" diff --git a/engines/hugo/file.cpp b/engines/hugo/file.cpp index 94e1756a0d..f4eada456d 100644 --- a/engines/hugo/file.cpp +++ b/engines/hugo/file.cpp @@ -550,7 +550,7 @@ void FileManager::printBootText() { buf[i] ^= cypher[i % strlen(cypher)]; buf[i] = '\0'; - Utils::Box(kBoxOk, "%s", buf); + Utils::notifyBox(buf); } free(buf); diff --git a/engines/hugo/file_v1d.cpp b/engines/hugo/file_v1d.cpp index d8b3fa494f..48f274e88a 100644 --- a/engines/hugo/file_v1d.cpp +++ b/engines/hugo/file_v1d.cpp @@ -121,7 +121,7 @@ void FileManager_v1d::instructions() const { f.read(wrkLine, 1); } while (*wrkLine++ != '#'); // '#' is EOP wrkLine[-2] = '\0'; // Remove EOP and previous CR - Utils::Box(kBoxAny, "%s", line); + Utils::notifyBox(line); wrkLine = line; f.read(readBuf, 2); // Remove CRLF after EOP } diff --git a/engines/hugo/file_v2w.cpp b/engines/hugo/file_v2w.cpp index b917d81bd5..245d4d017e 100644 --- a/engines/hugo/file_v2w.cpp +++ b/engines/hugo/file_v2w.cpp @@ -48,7 +48,7 @@ FileManager_v2w::~FileManager_v2w() { * Same comment than in SCI: maybe in the future we can implement this, but for now this message should suffice */ void FileManager_v2w::instructions() const { - Utils::Box(kBoxAny, "Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1); + Utils::notifyBox(Common::String::format("Please use an external viewer to open the game's help file: HUGOWIN%d.HLP", _vm->_gameVariant + 1)); } } // End of namespace Hugo diff --git a/engines/hugo/hugo.cpp b/engines/hugo/hugo.cpp index 231b2a5d51..6ba9e8eaa8 100644 --- a/engines/hugo/hugo.cpp +++ b/engines/hugo/hugo.cpp @@ -165,7 +165,7 @@ bool HugoEngine::isPacked() const { * Print options for user when dead */ void HugoEngine::gameOverMsg() { - Utils::Box(kBoxOk, "%s", _text->getTextUtil(kGameOver)); + Utils::notifyBox(_text->getTextUtil(kGameOver)); } Common::Error HugoEngine::run() { @@ -176,6 +176,10 @@ Common::Error HugoEngine::run() { _inventory = new InventoryHandler(this); _route = new Route(this); _sound = new SoundHandler(this); + + // Setup mixer + syncSoundSettings(); + _text = new TextHandler(this); _topMenu = new TopMenu(this); @@ -674,8 +678,8 @@ void HugoEngine::endGame() { debugC(1, kDebugEngine, "endGame"); if (_boot.registered != kRegRegistered) - Utils::Box(kBoxAny, "%s", _text->getTextEngine(kEsAdvertise)); - Utils::Box(kBoxAny, "%s\n%s", _episode, getCopyrightString()); + Utils::notifyBox(_text->getTextEngine(kEsAdvertise)); + Utils::notifyBox(Common::String::format("%s\n%s", _episode, getCopyrightString())); _status.viewState = kViewExit; } diff --git a/engines/hugo/hugo.h b/engines/hugo/hugo.h index a137df786f..ed021f5cd6 100644 --- a/engines/hugo/hugo.h +++ b/engines/hugo/hugo.h @@ -132,11 +132,6 @@ enum HugoRegistered { }; /** - * Ways to dismiss a text/prompt box - */ -enum box_t {kBoxAny, kBoxOk, kBoxPrompt, kBoxYesNo}; - -/** * Inventory icon bar states */ enum istate_t {kInventoryOff, kInventoryUp, kInventoryDown, kInventoryActive}; diff --git a/engines/hugo/intro.cpp b/engines/hugo/intro.cpp index 7551476300..7cd5a0fd17 100644 --- a/engines/hugo/intro.cpp +++ b/engines/hugo/intro.cpp @@ -337,13 +337,13 @@ bool intro_v3d::introPlay() { // Text boxes at various times switch (introTicks) { case 4: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro1)); break; case 9: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro2)); break; case 35: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro3)); break; } } @@ -429,13 +429,13 @@ bool intro_v3w::introPlay() { // Text boxes at various times switch (introTicks) { case 4: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro1)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro1)); break; case 9: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro2)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro2)); break; case 35: - Utils::Box(kBoxOk, "%s", _vm->_text->getTextIntro(kIntro3)); + Utils::notifyBox(_vm->_text->getTextIntro(kIntro3)); break; } } diff --git a/engines/hugo/mouse.cpp b/engines/hugo/mouse.cpp index 73805dcfba..1b2dd588b8 100644 --- a/engines/hugo/mouse.cpp +++ b/engines/hugo/mouse.cpp @@ -187,7 +187,7 @@ void MouseHandler::processRightClick(const int16 objId, const int16 cx, const in if (_vm->_hero->cycling == kCycleInvisible) // If invisible do _vm->_object->useObject(objId); // immediate use else - Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there + Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there } break; } @@ -241,7 +241,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int else if (_hotspots[i].direction == Common::KEYCODE_LEFT) x += kHeroMaxWidth; if (!_vm->_route->startRoute(kRouteExit, i, x, y)) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there + Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there } // Get rid of any attached icon @@ -271,7 +271,7 @@ void MouseHandler::processLeftClick(const int16 objId, const int16 cx, const int if (_vm->_hero->cycling == kCycleInvisible) // If invisible do _vm->_object->lookObject(obj); // immediate decription else - Utils::Box(kBoxAny, "%s", _vm->_text->getTextMouse(kMsNoWayText)); // Can't get there + Utils::notifyBox(_vm->_text->getTextMouse(kMsNoWayText)); // Can't get there } break; } diff --git a/engines/hugo/object.cpp b/engines/hugo/object.cpp index f82a6a53c6..0a52a0f62d 100644 --- a/engines/hugo/object.cpp +++ b/engines/hugo/object.cpp @@ -175,7 +175,7 @@ void ObjectHandler::useObject(int16 objId) { // Deselect dragged icon if inventory not active if (_vm->_inventory->getInventoryState() != kInventoryActive) _vm->_screen->resetInventoryObjId(); - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(use->dataIndex)); + Utils::notifyBox(_vm->_text->getTextData(use->dataIndex)); return; } } @@ -353,7 +353,7 @@ void ObjectHandler::showTakeables() { if ((obj->cycling != kCycleInvisible) && (obj->screenIndex == *_vm->_screen_p) && (((TAKE & obj->genericCmd) == TAKE) || obj->objValue)) { - Utils::Box(kBoxAny, "You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME)); + Utils::notifyBox(Common::String::format("You can also see:\n%s.", _vm->_text->getNoun(obj->nounIndex, LOOK_NAME))); } } } diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp index a0a3ee3350..feee4cbadd 100644 --- a/engines/hugo/parser.cpp +++ b/engines/hugo/parser.cpp @@ -288,7 +288,7 @@ void Parser::keyHandler(Common::Event event) { _vm->_file->restoreGame(-1); break; case Common::KEYCODE_n: - if (Utils::Box(kBoxYesNo, "%s", "Are you sure you want to start a new game?") != 0) + if (Utils::yesNoBox("Are you sure you want to start a new game?")) _vm->_file->restoreGame(0); break; case Common::KEYCODE_s: @@ -485,7 +485,7 @@ void Parser::showDosInventory() const { if (index & 1) buffer += "\n"; buffer += Common::String(_vm->_text->getTextParser(kTBOutro)); - Utils::Box(kBoxAny, "%s", buffer.c_str()); + Utils::notifyBox(buffer.c_str()); } } // End of namespace Hugo diff --git a/engines/hugo/parser_v1d.cpp b/engines/hugo/parser_v1d.cpp index df3a73feb8..de18427d93 100644 --- a/engines/hugo/parser_v1d.cpp +++ b/engines/hugo/parser_v1d.cpp @@ -151,25 +151,25 @@ bool Parser_v1d::isGenericVerb_v1(const char *word, object_t *obj) { // Following is equivalent to switch, but couldn't do one if (word == _vm->_text->getVerb(_vm->_look, 0)) { if ((LOOK & obj->genericCmd) == LOOK) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex)); + Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex)); else - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual_1d)); + Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual_1d)); } else if (word == _vm->_text->getVerb(_vm->_take, 0)) { if (obj->carriedFl) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave)); + Utils::notifyBox(_vm->_text->getTextParser(kTBHave)); else if ((TAKE & obj->genericCmd) == TAKE) takeObject(obj); else if (!obj->verbOnlyFl) // Make sure not taking object in context! - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse)); else return false; } else if (word == _vm->_text->getVerb(_vm->_drop, 0)) { if (!obj->carriedFl) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave)); + Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave)); else if ((DROP & obj->genericCmd) == DROP) dropObject(obj); else - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNeed)); } else { // It was not a generic cmd return false; } @@ -206,7 +206,7 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) { uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) { // for each obj if (!_vm->_object->isCarrying(reqs[i])) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex)); return true; } } @@ -214,14 +214,14 @@ bool Parser_v1d::isObjectVerb_v1(const char *word, object_t *obj) { // Required objects are present, now check state is correct if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)){ - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex)); return true; } // Everything checked. Change the state and carry out any actions if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care obj->state = cmnd->newState; - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex)); _vm->_scheduler->insertActionList(cmnd->actIndex); // Special case if verb is Take or Drop. Assume additional generic actions if ((word == _vm->_text->getVerb(_vm->_take, 0)) || (word == _vm->_text->getVerb(_vm->_drop, 0))) @@ -241,7 +241,7 @@ bool Parser_v1d::isBackgroundWord_v1(const char *noun, const char *verb, objectL for (int i = 0; obj[i].verbIndex; i++) { if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && (noun == _vm->_text->getNoun(obj[i].nounIndex, 0))) { - Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex)); return true; } } @@ -260,7 +260,7 @@ void Parser_v1d::takeObject(object_t *obj) { _vm->adjustScore(obj->objValue); - Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)); + Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME))); } /** @@ -276,7 +276,7 @@ void Parser_v1d::dropObject(object_t *obj) { obj->x = _vm->_hero->x - 1; obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; _vm->adjustScore(-obj->objValue); - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk)); + Utils::notifyBox(_vm->_text->getTextParser(kTBOk)); } /** @@ -294,7 +294,7 @@ bool Parser_v1d::isCatchallVerb_v1(bool testNounFl, const char *noun, const char for (int i = 0; obj[i].verbIndex; i++) { if ((verb == _vm->_text->getVerb(obj[i].verbIndex, 0)) && ((noun == _vm->_text->getNoun(obj[i].nounIndex, 0)) || (obj[i].nounIndex == 0))) { - Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex)); return true; } } @@ -364,7 +364,7 @@ void Parser_v1d::lineHandler() { } if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) { - if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0) + if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d))) _vm->endGame(); return; } @@ -418,11 +418,11 @@ void Parser_v1d::lineHandler() { } noun = findNextNoun(noun); if (*farComment != '\0') // An object matched but not near enough - Utils::Box(kBoxAny, "%s", farComment); + Utils::notifyBox(farComment); else if (!isCatchallVerb_v1(true, noun, verb, _catchallList) && !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) && !isCatchallVerb_v1(false, noun, verb, _catchallList)) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_1d)); + Utils::notifyBox(_vm->_text->getTextParser(kTBEh_1d)); } void Parser_v1d::showInventory() const { diff --git a/engines/hugo/parser_v1w.cpp b/engines/hugo/parser_v1w.cpp index d3424274f8..305fb995e1 100644 --- a/engines/hugo/parser_v1w.cpp +++ b/engines/hugo/parser_v1w.cpp @@ -119,7 +119,7 @@ void Parser_v1w::lineHandler() { // Special meta commands // EXIT/QUIT if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) { - if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0) + if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d))) _vm->endGame(); return; } @@ -182,7 +182,7 @@ void Parser_v1w::lineHandler() { // If a not-near comment was generated, print it if (*farComment != '\0') { - Utils::Box(kBoxAny, "%s", farComment); + Utils::notifyBox(farComment); return; } @@ -190,16 +190,16 @@ void Parser_v1w::lineHandler() { const char *verb = findVerb(); const char *noun = findNoun(); if (verb == _vm->_text->getVerb(_vm->_look, 0) && _vm->_maze.enabledFl) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze)); + Utils::notifyBox(_vm->_text->getTextParser(kTBMaze)); _vm->_object->showTakeables(); } else if (verb && noun) { // A combination I didn't think of - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint)); } else if (noun) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoun)); } else if (verb) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb)); + Utils::notifyBox(_vm->_text->getTextParser(kTBVerb)); } else { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh)); + Utils::notifyBox(_vm->_text->getTextParser(kTBEh)); } } diff --git a/engines/hugo/parser_v2d.cpp b/engines/hugo/parser_v2d.cpp index d19b8b1091..d6f2adfedc 100644 --- a/engines/hugo/parser_v2d.cpp +++ b/engines/hugo/parser_v2d.cpp @@ -114,7 +114,7 @@ void Parser_v2d::lineHandler() { } if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) { - if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0) + if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d))) _vm->endGame(); return; } @@ -175,16 +175,16 @@ void Parser_v2d::lineHandler() { && !isCatchallVerb_v1(false, noun, verb, _backgroundObjects[*_vm->_screen_p]) && !isCatchallVerb_v1(false, noun, verb, _catchallList)) { if (*farComment != '\0') { // An object matched but not near enough - Utils::Box(kBoxAny, "%s", farComment); + Utils::notifyBox(farComment); } else if (_vm->_maze.enabledFl && (verb == _vm->_text->getVerb(_vm->_look, 0))) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBMaze)); + Utils::notifyBox(_vm->_text->getTextParser(kTBMaze)); _vm->_object->showTakeables(); } else if (verb && noun) { // A combination I didn't think of - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse_2d)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse_2d)); } else if (verb || noun) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoun)); } else { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh_2d)); + Utils::notifyBox(_vm->_text->getTextParser(kTBEh_2d)); } } } diff --git a/engines/hugo/parser_v3d.cpp b/engines/hugo/parser_v3d.cpp index fcd937808b..f08d472240 100644 --- a/engines/hugo/parser_v3d.cpp +++ b/engines/hugo/parser_v3d.cpp @@ -116,7 +116,7 @@ void Parser_v3d::lineHandler() { // Special meta commands // EXIT/QUIT if (!strcmp("exit", _vm->_line) || strstr(_vm->_line, "quit")) { - if (Utils::Box(kBoxYesNo, "%s", _vm->_text->getTextParser(kTBExit_1d)) != 0) + if (Utils::yesNoBox(_vm->_text->getTextParser(kTBExit_1d))) _vm->endGame(); return; } @@ -184,7 +184,7 @@ void Parser_v3d::lineHandler() { // If a not-near comment was generated, print it if (*farComment != '\0') { - Utils::Box(kBoxAny, "%s", farComment); + Utils::notifyBox(farComment); return; } @@ -193,13 +193,13 @@ void Parser_v3d::lineHandler() { const char *noun = findNoun(); if (verb && noun) { // A combination I didn't think of - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoPoint)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoPoint)); } else if (noun) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoun)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoun)); } else if (verb) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBVerb)); + Utils::notifyBox(_vm->_text->getTextParser(kTBVerb)); } else { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBEh)); + Utils::notifyBox(_vm->_text->getTextParser(kTBEh)); } } @@ -236,7 +236,7 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) { uint16 *reqs = _arrayReqs[cmnd->reqIndex]; // ptr to list of required objects for (i = 0; reqs[i]; i++) { // for each obj if (!_vm->_object->isCarrying(reqs[i])) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataNoCarryIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataNoCarryIndex)); return true; } } @@ -244,14 +244,14 @@ bool Parser_v3d::isObjectVerb_v3(object_t *obj, char *comment) { // Required objects are present, now check state is correct if ((obj->state != cmnd->reqState) && (cmnd->reqState != kStateDontCare)) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataWrongIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataWrongIndex)); return true; } // Everything checked. Change the state and carry out any actions if (cmnd->reqState != kStateDontCare) // Don't change new state if required state didn't care obj->state = cmnd->newState; - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(cmnd->textDataDoneIndex)); + Utils::notifyBox(_vm->_text->getTextData(cmnd->textDataDoneIndex)); _vm->_scheduler->insertActionList(cmnd->actIndex); // See if any additional generic actions @@ -273,35 +273,35 @@ bool Parser_v3d::isGenericVerb_v3(object_t *obj, char *comment) { if (isWordPresent(_vm->_text->getVerbArray(_vm->_look)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_look, 0), comment)) { // Test state-dependent look before general look if ((obj->genericCmd & LOOK_S) == LOOK_S) { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->stateDataIndex[obj->state])); + Utils::notifyBox(_vm->_text->getTextData(obj->stateDataIndex[obj->state])); } else { if ((LOOK & obj->genericCmd) == LOOK) { if (obj->dataIndex != 0) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextData(obj->dataIndex)); + Utils::notifyBox(_vm->_text->getTextData(obj->dataIndex)); else return false; } else { - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBUnusual)); + Utils::notifyBox(_vm->_text->getTextParser(kTBUnusual)); } } } else if (isWordPresent(_vm->_text->getVerbArray(_vm->_take)) && isNear_v3(obj, _vm->_text->getVerb(_vm->_take, 0), comment)) { if (obj->carriedFl) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBHave)); + Utils::notifyBox(_vm->_text->getTextParser(kTBHave)); else if ((TAKE & obj->genericCmd) == TAKE) takeObject(obj); else if (obj->cmdIndex) // No comment if possible commands return false; else if (!obj->verbOnlyFl && (TAKE & obj->genericCmd) == TAKE) // Make sure not taking object in context! - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNoUse)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNoUse)); else return false; } else if (isWordPresent(_vm->_text->getVerbArray(_vm->_drop))) { if (!obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBDontHave)); + Utils::notifyBox(_vm->_text->getTextParser(kTBDontHave)); else if (obj->carriedFl && ((DROP & obj->genericCmd) == DROP)) dropObject(obj); else if (obj->cmdIndex == 0) - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBNeed)); + Utils::notifyBox(_vm->_text->getTextParser(kTBNeed)); else return false; } else { // It was not a generic cmd @@ -383,7 +383,7 @@ void Parser_v3d::takeObject(object_t *obj) { if (obj->seqNumb > 0) // If object has an image, force walk to dropped obj->viewx = -1; // (possibly moved) object next time taken! - Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME)); + Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(obj->nounIndex, TAKE_NAME))); } /** @@ -402,7 +402,7 @@ void Parser_v3d::dropObject(object_t *obj) { obj->y = _vm->_hero->y + _vm->_hero->currImagePtr->y2 - 1; obj->y = (obj->y + obj->currImagePtr->y2 < kYPix) ? obj->y : kYPix - obj->currImagePtr->y2 - 10; _vm->adjustScore(-obj->objValue); - Utils::Box(kBoxAny, "%s", _vm->_text->getTextParser(kTBOk)); + Utils::notifyBox(_vm->_text->getTextParser(kTBOk)); } /** @@ -422,7 +422,7 @@ bool Parser_v3d::isCatchallVerb_v3(objectList_t obj) const { (!obj[i].matchFl || !findNoun()) && ((obj[i].roomState == kStateDontCare) || (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { - Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex)); _vm->_scheduler->processBonus(obj[i].bonusIndex); // If this is LOOK (without a noun), show any takeable objects @@ -450,7 +450,7 @@ bool Parser_v3d::isBackgroundWord_v3(objectList_t obj) const { isWordPresent(_vm->_text->getNounArray(obj[i].nounIndex)) && ((obj[i].roomState == kStateDontCare) || (obj[i].roomState == _vm->_screenStates[*_vm->_screen_p]))) { - Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(obj[i].commentIndex)); + Utils::notifyBox(_vm->_file->fetchString(obj[i].commentIndex)); _vm->_scheduler->processBonus(obj[i].bonusIndex); return true; } diff --git a/engines/hugo/schedule.cpp b/engines/hugo/schedule.cpp index 1556f3a154..45a2b77826 100644 --- a/engines/hugo/schedule.cpp +++ b/engines/hugo/schedule.cpp @@ -1242,7 +1242,7 @@ event_t *Scheduler::doAction(event_t *curEvent) { insertActionList(action->a11.actFailIndex); break; case TEXT: // act12: Text box (CF WARN) - Utils::Box(kBoxAny, "%s", _vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file + Utils::notifyBox(_vm->_file->fetchString(action->a12.stringIndex)); // Fetch string from file break; case SWAP_IMAGES: // act13: Swap 2 object images _vm->_object->swapImages(action->a13.objIndex1, action->a13.objIndex2); @@ -1367,7 +1367,7 @@ event_t *Scheduler::doAction(event_t *curEvent) { gameStatus.storyModeFl = action->a39.storyModeFl; break; case WARN: // act40: Text box (CF TEXT) - Utils::Box(kBoxOk, "%s", _vm->_file->fetchString(action->a40.stringIndex)); + Utils::notifyBox(_vm->_file->fetchString(action->a40.stringIndex)); break; case COND_BONUS: // act41: Perform action if got bonus if (_points[action->a41.BonusIndex].scoredFl) @@ -1376,10 +1376,10 @@ event_t *Scheduler::doAction(event_t *curEvent) { insertActionList(action->a41.actFailIndex); break; case TEXT_TAKE: // act42: Text box with "take" message - Utils::Box(kBoxAny, TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME)); + Utils::notifyBox(Common::String::format(TAKE_TEXT, _vm->_text->getNoun(_vm->_object->_objects[action->a42.objIndex].nounIndex, TAKE_NAME))); break; case YESNO: // act43: Prompt user for Yes or No - if (Utils::Box(kBoxYesNo, "%s", _vm->_file->fetchString(action->a43.promptIndex)) != 0) + if (Utils::yesNoBox(_vm->_file->fetchString(action->a43.promptIndex))) insertActionList(action->a43.actYesIndex); else insertActionList(action->a43.actNoIndex); @@ -1529,7 +1529,7 @@ void Scheduler_v1d::runScheduler() { } void Scheduler_v1d::promptAction(act *action) { - Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex)); warning("STUB: doAction(act3)"); // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block @@ -1578,7 +1578,7 @@ const char *Scheduler_v2d::getCypher() const { } void Scheduler_v2d::promptAction(act *action) { - Utils::Box(kBoxPrompt, "%s", _vm->_file->fetchString(action->a3.promptIndex)); + Utils::promptBox(_vm->_file->fetchString(action->a3.promptIndex)); warning("STUB: doAction(act3), expecting answer %s", _vm->_file->fetchString(action->a3.responsePtr[0])); // TODO: The answer of the player is not handled currently! Once it'll be read in the messageBox, uncomment this block diff --git a/engines/hugo/util.cpp b/engines/hugo/util.cpp index f36c431867..044b58e986 100644 --- a/engines/hugo/util.cpp +++ b/engines/hugo/util.cpp @@ -41,10 +41,12 @@ namespace Hugo { +namespace Utils { + /** * Returns index (0 to 7) of first 1 in supplied byte, or 8 if not found */ -int Utils::firstBit(byte data) { +int firstBit(byte data) { if (!data) return 8; @@ -60,7 +62,7 @@ int Utils::firstBit(byte data) { /** * Returns index (0 to 7) of last 1 in supplied byte, or 8 if not found */ -int Utils::lastBit(byte data) { +int lastBit(byte data) { if (!data) return 8; @@ -76,7 +78,7 @@ int Utils::lastBit(byte data) { /** * Reverse the bit order in supplied byte */ -void Utils::reverseByte(byte *data) { +void reverseByte(byte *data) { byte maskIn = 0x80; byte maskOut = 0x01; byte result = 0; @@ -89,58 +91,31 @@ void Utils::reverseByte(byte *data) { *data = result; } -const char *Utils::Box(box_t dismiss, const char *s, ...) { - static char buffer[kMaxStrLength + 1]; // Format text into this - - if (!s) - return 0; // NULL strings catered for - - if (s[0] == '\0') - return 0; +void notifyBox(const Common::String &msg) { + if (msg.empty()) + return; - if (strlen(s) > kMaxStrLength - 100) { // Test length - warning("String too long: '%s'", s); - return 0; - } + GUI::MessageDialog dialog(msg, "OK"); + dialog.runModal(); +} - va_list marker; - va_start(marker, s); - vsprintf(buffer, s, marker); // Format string into buffer - va_end(marker); +Common::String promptBox(const Common::String &msg) { + if (msg.empty()) + return Common::String(); - if (buffer[0] == '\0') - return 0; + EntryDialog dialog(msg, "OK", ""); + return dialog.getEditString(); +} - switch(dismiss) { - case kBoxAny: - case kBoxOk: { - GUI::MessageDialog dialog(buffer, "OK"); - dialog.runModal(); - break; - } - case kBoxYesNo: { - GUI::MessageDialog dialog(buffer, "YES", "NO"); - if (dialog.runModal() == GUI::kMessageOK) - return buffer; +bool yesNoBox(const Common::String &msg) { + if (msg.empty()) return 0; - break; - } - case kBoxPrompt: { - EntryDialog dialog(buffer, "OK", ""); - Common::String result = dialog.getEditString(); - - return result.c_str(); - - break; - } - default: - error("Unknown BOX Type %d", dismiss); - } - return 0; + GUI::MessageDialog dialog(msg, "YES", "NO"); + return (dialog.runModal() == GUI::kMessageOK); } -char *Utils::strlwr(char *buffer) { +char *strlwr(char *buffer) { char *result = buffer; while (*buffer != '\0') { @@ -152,4 +127,6 @@ char *Utils::strlwr(char *buffer) { return result; } +} // End of namespace Utils + } // End of namespace Hugo diff --git a/engines/hugo/util.h b/engines/hugo/util.h index acead5a0c4..85fef01a6e 100644 --- a/engines/hugo/util.h +++ b/engines/hugo/util.h @@ -40,16 +40,36 @@ enum seqTextUtil { }; namespace Utils { -static const int kMaxStrLength = 1024; int firstBit(byte data); int lastBit(byte data); void reverseByte(byte *data); -const char *Box(box_t, const char *, ...) GCC_PRINTF(2, 3); +/** + * Show a dialog notifying the user about something, with + * only a simple "OK" button to dismiss it. + */ +void notifyBox(const Common::String &msg); + +/** + * Show a dialog prompting the player to input some text. + */ +Common::String promptBox(const Common::String &msg); + +/** + * Show a dialog prompting the player for a "yes"/"no" choice. + */ +bool yesNoBox(const Common::String &msg); + +/** + * Convert a string to lower case, in place. + * @param buffer string to convert to lower case + * @return the string which was passed in + */ char *strlwr(char *buffer); -} + +} // End of namespace Utils } // End of namespace Hugo diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp index ad6e5f2a24..9074225e94 100644 --- a/engines/lastexpress/lastexpress.cpp +++ b/engines/lastexpress/lastexpress.cpp @@ -56,6 +56,8 @@ LastExpressEngine::LastExpressEngine(OSystem *syst, const ADGameDescription *gd) _font(NULL), _logic(NULL), _menu(NULL), _frameCounter(0), _lastFrameCount(0), _graphicsMan(NULL), _resMan(NULL), _sceneMan(NULL), _soundMan(NULL), _eventMouse(NULL), _eventTick(NULL), _eventMouseBackup(NULL), _eventTickBackup(NULL) { + // Setup mixer + syncSoundSettings(); // Adding the default directories const Common::FSNode gameDataDir(ConfMan.get("path")); diff --git a/engines/lure/lure.cpp b/engines/lure/lure.cpp index ca102e237c..b0968c1956 100644 --- a/engines/lure/lure.cpp +++ b/engines/lure/lure.cpp @@ -95,6 +95,10 @@ Common::Error LureEngine::init() { _gameToLoad = -1; _initialised = true; + + // Setup mixer + syncSoundSettings(); + return Common::kNoError; } @@ -264,6 +268,8 @@ GUI::Debugger *LureEngine::getDebugger() { } void LureEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + Sound.syncSounds(); } diff --git a/engines/m4/m4.cpp b/engines/m4/m4.cpp index 2bdd53040a..d8d25f6895 100644 --- a/engines/m4/m4.cpp +++ b/engines/m4/m4.cpp @@ -107,6 +107,8 @@ void gameMenuHotkeyHandler(MadsM4Engine *vm, View *view, uint32 key) { MadsM4Engine::MadsM4Engine(OSystem *syst, const M4GameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc) { + // Setup mixer + syncSoundSettings(); // FIXME _vm = this; diff --git a/engines/made/made.cpp b/engines/made/made.cpp index 11f7734495..1c8d54aada 100644 --- a/engines/made/made.cpp +++ b/engines/made/made.cpp @@ -146,11 +146,15 @@ MadeEngine::~MadeEngine() { } void MadeEngine::syncSoundSettings() { - _music->setVolume(ConfMan.getInt("music_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + Engine::syncSoundSettings(); + + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + _music->setVolume(mute ? 0 : ConfMan.getInt("music_volume")); + _mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, + mute ? 0 : ConfMan.getInt("sfx_volume")); } int16 MadeEngine::getTicks() { diff --git a/engines/mohawk/mohawk.cpp b/engines/mohawk/mohawk.cpp index a3db630c6a..015cbffb26 100644 --- a/engines/mohawk/mohawk.cpp +++ b/engines/mohawk/mohawk.cpp @@ -46,8 +46,8 @@ MohawkEngine::MohawkEngine(OSystem *syst, const MohawkGameDescription *gamedesc) if (!_mixer->isReady()) error ("Sound initialization failed"); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + // Setup mixer + syncSoundSettings(); _sound = 0; _video = 0; diff --git a/engines/mohawk/myst_vars.cpp b/engines/mohawk/myst_vars.cpp deleted file mode 100644 index f8ea11a1e2..0000000000 --- a/engines/mohawk/myst_vars.cpp +++ /dev/null @@ -1,578 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - * - */ - -#include "mohawk/myst.h" -#include "mohawk/myst_vars.h" - -namespace Mohawk { - -// The Myst variable system is complex, and the structure is fairly -// unknown. The idea of this class is to abstract the variable references -// from the storage structure until the structure is clear enough that -// the complexity of this abstraction can be removed. - -// The exact organization of local/global, persistent/non-persistent -// age-specific mapping etc. is currently unknown. - -MystVarEntry introVars[] = { - { 0, 7, "Age To Link To" } // 0 to 7 - // 0 = Selenitic - // 1 = Stoneship - // 2 = Myst (Library Ceiling) - // 3 = Mechanical - // 4 = Channelwood - // 5 = Myst (Start of Movie - Over Sea) - // 6 = D'ni - // 7 = Myst (End of Movie - On Dock) -}; - -MystVarEntry seleniticVars[] = { - { 0, 0, "Sound Pickup At Windy Tunnel" }, // 0 to 1 // TODO: Multiple Uses of Var 0? - { 1, 0, "Sound Pickup At Volcanic Crack" }, // 0 to 1 - { 2, 0, "Sound Pickup At Clock" }, // 0 to 1 - { 3, 0, "Sound Pickup At Water Pool" }, // 0 to 1 - { 4, 0, "Sound Pickup At Crystal Rocks" }, // 0 to 1 - { 5, 0, "Sound Receiver Doors" }, // 0 to 1 - { 6, 0, "Windy Tunnel Lights" }, // 0 to 1 - { 7, 0, "Maze Runner Porthole View" }, // 0 to 3 - { 8, 0, "Sound Receiver Screen (Control Variable?)" }, - { 9, 0, "Sound Receiver Water Pool Button Selected" }, - { 10, 0, "Sound Receiver Volcanic Crack Button Selected" }, - { 11, 0, "Sound Receiver Clock Button Selected" }, - { 12, 0, "Sound Receiver Crystal Rocks Button Selected" }, - { 13, 0, "Sound Receiver Windy Tunnel Button Selected" }, - { 14, 0, "Sound Receiver LED Digit #0 (Left)" }, - { 15, 0, "Sound Receiver LED Digit #1" }, - { 16, 0, "Sound Receiver LED Digit #2" }, - { 17, 0, "Sound Receiver LED Digit #3 (Right)" }, - { 18, 0, "Sound Receiver Green Arrow - Right" }, - { 19, 0, "Sound Receiver Green Arrow - Left" }, - { 20, 0, "Sound Lock Slider #1 (Left) (Position?)" }, - { 21, 0, "Sound Lock Slider #2 (Position?)" }, - { 22, 0, "Sound Lock Slider #3 (Position?)" }, - { 23, 0, "Sound Lock Slider #4 (Position?)" }, - { 24, 0, "Sound Lock Slider #5 (Right) (Position?)" }, - { 25, 0, "Maze Runner Compass Heading" }, // 0 to 8 - { 26, 0, "Sound Receiver Sum Button Selected" }, - { 27, 0, "Maze Runner Red Warning Light" }, - { 28, 0, "Sound Lock Button State" }, - { 29, 0, "Maze Runner Door Button State" }, - { 30, 0, "Maze Runner Door State" }, - { 31, 0, "Maze Runner Forward Button Lit" }, // 0 to 2 - { 32, 0, "Maze Runner Left & Right Button Lit" }, // 0 to 2 - { 33, 0, "Maze Runner Backtrack Button Lit" }, // 0 to 2 - { 102, 1, "Red Page in Age" }, // 0 to 1 - { 103, 1, "Blue Page in Age" } // 0 to 1 -}; - -MystVarEntry stoneshipVars[] = { - { 0, 0, "Water Pump Button #3 (Right) / Lighthouse Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit - { 1, 0, "Water Pump Button #2 / Tunnels To Brothers Rooms Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit - { 2, 0, "Water Pump Button #1 (Left) / Ship Cabin Water Drained" }, // 0 to 2 = Button Up & Unlit, Button Down & Lit, Button Up & Lit - { 3, 0, "Lighthouse (Water or Chest Floating?)" }, // 0 to 1, Used by Far View - { 4, 0, "Lighthouse Water/Chest State" }, // 0 to 2 = Water, No Water, Water & Chest Floating - { 5, 2, "Lighthouse Trapdoor State" }, // 0 to 2 = Closed & Unlocked, Open, Closed & Locked - { 6, 0, "Lighthouse Chest Valve Position" }, // 0 to 1 - { 7, 0, "Lighthouse Chest Unlocked" }, // 0 to 1 - { 8, 0, "Lighthouse Chest Key Position?" }, // 0 to 2, 2 = Bottom of Lighthouse -// Var 9 Unused - { 10, 1, "Lighthouse Chest Full Of Water" }, // 0 to 1 - { 11, 3, "Lighthouse Key State" }, // 0 to 3 = Closed?, Open & No Key, Open & No Key, Open & Key - { 12, 0, "Lighthouse Trapdoor - Holding Key" }, // 0 to 1 - { 13, 0, "State of Water in Tunnels to Brothers' Rooms" }, // 0 to 2 = Dark & Water, Dark & Drained, Lit & Water - { 14, 0, "Tunnels to Brothers' Rooms Lit" }, // 0 to 1 - { 15, 0, "Side Door in Tunnels To Brother's Rooms Open" }, // 0 to 1 - { 16, 0, "Underwater Light Lit" }, // 0 to 1 - { 17, 0, "Sirrus' Room Drawer with Drugs Open" }, // 0 to 1 - { 18, 0, "Brother Room Door Open" }, // 0 to 1, Used for Door Slam - { 19, 0, "Brother Room Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit - { 20, 0, "Ship Cabin Myst Book Present" }, // 0 to 1 - { 21, 0, "Brothers Rooms' Chest Of Drawers Drawer State" }, // 0 to 6 (Card 2197) or 0 to 7 (Card 2004) - { 22, 0, "Sirrus' Chest of Drawers Drawer #1 (Top) Open" }, // 0 to 1 - { 23, 0, "Sirrus' Chest of Drawers Drawer #2 Open" }, // 0 to 1 - { 24, 0, "Sirrus' Chest of Drawers Drawer #3 Open" }, // 0 to 1 -// Var 25 Unused - Replaced by Var 35. - { 26, 0, "Sirrus' Chest of Drawers Left Small Drawer Open" }, // 0 to 1 - { 27, 0, "Sirrus' Chest of Drawers Right Small Drawer Open" }, // 0 to 1 - { 28, 0, "Telescope View Position" }, // Range Unknown.. 0 to 360? - { 29, 0, "Achenar's Room Rose/Skull Hologram Button Lit" }, // 0 to 1 - { 30, 2, "Light State in Tunnel to Compass Rose Room" }, // 0 to 2 = Lit & Underwater Light Lit, Lit, Dark - { 31, 0, "Lighthouse Lamp Room Battery Pack Indicator Light" }, // 0 to 1 - { 32, 0, "Lighthouse Lamp Room Battery Pack Meter Level" }, // Range Unknown.. // Must be 1 to vertical size of image... - { 33, 0, "State of Side Door in Tunnels to Compass Rose Room (Power?)" }, // 0 to 2 = Closed (No Power), Closed (Power), Open - { 34, 1, "Achenar's Room Drawer with Torn Note Closed" }, // 0 to 1 - { 35, 2, "Sirrus' Room Drawer #4 (Bottom) Open and Red Page State" }, // 0 to 2 = Open, Open with Page, Closed - { 36, 0, "Ship Cabin Door State" }, // 0 to 2 = Closed, Open & Dark, Open & Lit - { 102, 1, "Red Page in Age" }, // 0 to 1 - { 103, 1, "Blue Page in Age" }, // 0 to 1 - { 105, 0, "Ship Cabin Door State" } -}; - -MystVarEntry mystVars[] = { - { 0, 1, "Myst Library Bookcase Closed / Library Exit Open" }, // 0 to 1 // TODO: Multiple Uses of Var 0? - { 1, 0, "Myst Library Bookcase Open / Library Exit Blocked" }, // 0 to 1 - { 2, 0, "Marker Switch Near Cabin" }, // 0 to 1 - { 3, 0, "Marker Switch Near Clock Tower" }, // 0 to 1 - { 4, 0, "Marker Switch on Dock" }, // 0 to 1 - { 5, 0, "Marker Switch Near Ship Pool" }, // 0 to 1 - { 6, 0, "Marker Switch Near Cogs" }, // 0 to 1 - { 7, 0, "Marker Switch Near Generator Room" }, // 0 to 1 - { 8, 0, "Marker Switch Near Stellar Observatory" }, // 0 to 1 - { 9, 0, "Marker Switch Near Rocket Ship" }, // 0 to 1 - { 10, 0, "Ship Floating State" }, // 0 to 1 - { 11, 0, "Cabin Door Open State" }, - { 12, 0, "Clock Tower Gear Bridge" }, // 0 to 1 - { 13, 0, "Tower Elevator Sound Control" }, // 0 to 1 - { 14, 0, "Tower Solution (Key) Plaque" }, // 0 to 4 - // 0 = None - // 1 = 59 V - // 2 = 2:40 2-2-1 - // 3 = October 11, 1984 10:04 AM - // January 17, 1207 5:46 AM - // November 23, 9791 6:57 PM - // 4 = 7, 2, 4 - { 15, 0, "Tower Window (Book) View" }, // 0 to 6 - // 0 = Wall - // 1 = Rocketship - // 2 = Cogs Closed - // 3 = Ship Sunk - // 4 = Channelwood Tree - // 5 = Ship Floating - // 6 = Cogs Open - { 16, 0, "Tower Window (Book) View From Ladder Top" }, // 0 to 2 - // 0 = Wall - // 1 = Sky - // 2 = Sky with Channelwood Tree - { 17, 0, "Fireplace Grid Row #1 (Top)" }, // Bitfield 0x00 to 0xFF - { 18, 0, "Fireplace Grid Row #2" }, // Bitfield 0x00 to 0xFF - { 19, 0, "Fireplace Grid Row #3" }, // Bitfield 0x00 to 0xFF - { 20, 0, "Fireplace Grid Row #4" }, // Bitfield 0x00 to 0xFF - { 21, 0, "Fireplace Grid Row #5" }, // Bitfield 0x00 to 0xFF - { 22, 0, "Fireplace Grid Row #6 (Bottom)" }, // Bitfield 0x00 to 0xFF - { 23, 0, "Fireplace Pattern Correct" }, // 0 to 1 - { 24, 1, "Fireplace Blue Page Present" }, // 0 to 1 - { 25, 1, "Fireplace Red Page Present" }, // 0 to 1 - { 26, 0, "Ship Puzzle Box Image (Cross)" }, // 0 to 2 - { 27, 0, "Ship Puzzle Box Image (Leaf)" }, // 0 to 2 - { 28, 0, "Ship Puzzle Box Image (Arrow)" }, // 0 to 2 - { 29, 0, "Ship Puzzle Box Image (Eye)" }, // 0 to 2 - { 30, 0, "Ship Puzzle Box Image (Snake)" }, // 0 to 2 - { 31, 0, "Ship Puzzle Box Image (Spider)" }, // 0 to 2 - { 32, 0, "Ship Puzzle Box Image (Anchor)" }, // 0 to 2 - { 33, 0, "Ship Puzzle Box Image (Ostrich)" }, // 0 to 2 - { 34, 2, "Dock Forechamber Imager State" }, // 0 to 2 = Off, Mountain, Water - { 35, 5, "Dock Forechamber Imager Control Left Digit" }, // 0 to 9 - { 36, 6, "Dock Forechamber Imager Control Right Digit" }, // 0 to 9 - { 37, 0, "Clock Tower Control Wheels Position" }, // 0 to 8 -// Var 38 Unused -// 39 = TODO: ? - { 40, 0, "Cog Close/Open State" }, - { 41, 0, "Dock Marker Switch Vault State" }, // 0 to 2 = Closed, Open & Page Taken, Open & Page Present -// Var 42 Unused - { 43, 0, "Clock Tower Time" }, // 0 to 143 - { 44, 0, "Rocket Ship Power State" }, // 0 to 2 = None, Insufficient, Correct - { 45, 1, "Dock Forechamber Imager Water Effect Enabled" }, // 0 to 1 - { 46, 0, "Number Of Pages in Red Book" }, // 0 to 6 = 0-5, Extra - { 47, 0, "Number Of Pages in Blue Book" }, // 0 to 6 = 0-5, Extra - { 48, 0, "Marker Switch on Dock - Duplicate of Var #4?" }, // 0 to 2 - { 49, 0, "Generator Running" }, // Boolean used for Sound.. -// 50 = TODO: ? - { 51, 2, "Forechamber Imager Movie Control Variable" }, // 0 to 4 = Blank, Mountain, Water, Atrus, Marker Switch - { 52, 0, "Generator Switch #1" }, - { 53, 0, "Generator Switch #2" }, - { 54, 0, "Generator Switch #3" }, - { 55, 0, "Generator Switch #4" }, - { 56, 0, "Generator Switch #5" }, - { 57, 0, "Generator Switch #6" }, - { 58, 0, "Generator Switch #7" }, - { 59, 0, "Generator Switch #8" }, - { 60, 0, "Generator Switch #9" }, - { 61, 0, "Generator Switch #10" }, - { 62, 0, "Generator Power Dial Left LED Digit" }, // 0 to 9 - { 63, 0, "Generator Power Dial Right LED Digit" }, // 0 to 9 - { 64, 0, "Generator Power To Spaceship Dial Left LED Digit" }, // 0 to 9 - { 65, 0, "Generator Power To Spaceship Dial Right LED Digit" }, // 0 to 9 - { 66, 0, "Generator Room Lights On" }, // Boolean - { 67, 9, "Cabin Safe Lock Number #1 - Left" }, - { 68, 9, "Cabin Safe Lock Number #2" }, - { 69, 9, "Cabin Safe Lock Number #3 - Right" }, - { 70, 0, "Cabin Safe Matchbox State" }, // 0 to 2 - { 71, 1, "Stellar Observatory Lights" }, - { 72, 0, "Channelwood Tree Position" }, // 0 to 12, 4 for Alcove - { 73, 9, "Stellar Observatory Telescope Control - Month" }, // 0 to 11, Not in order... - // 0 = OCT, 1 = NOV, 2 = DEC, 3 = JUL, 4 = AUG, 5 = SEP - // 6 = APR, 7 = MAY, 8 = JUN, 9 = JAN, 10 = FEB, 11 = MAR - { 74, 10, "Stellar Observatory Telescope Control - Day Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank - { 75, 1, "Stellar Observatory Telescope Control - Day Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank - { 76, 10, "Stellar Observatory Telescope Control - Year Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank - { 77, 10, "Stellar Observatory Telescope Control - Year Digit #2" }, // 0 to 10 = 0 to 9, Blank - { 78, 10, "Stellar Observatory Telescope Control - Year Digit #3" }, // 0 to 10 = 0 to 9, Blank - { 79, 0, "Stellar Observatory Telescope Control - Year Digit #4 (Right)" }, // 0 to 10 = 0 to 9, Blank - { 80, 1, "Stellar Observatory Telescope Control - Hour Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank - { 81, 2, "Stellar Observatory Telescope Control - Hour Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank - { 82, 0, "Stellar Observatory Telescope Control - Minute Digit #1 (Left)" }, // 0 to 10 = 0 to 9, Blank - { 83, 0, "Stellar Observatory Telescope Control - Minute Digit #2 (Right)" }, // 0 to 10 = 0 to 9, Blank -// 84 to 87 = TODO: ? - { 88, 0, "Stellar Observatory Telescope Control - AM/PM Indicator" }, // 0 = AM, 1 = PM - { 89, 0, "Stellar Observatory Telescope Control - Slider #1 (Left)" }, // 0 to 2 = Not Present, Dark, Lit - { 90, 0, "Stellar Observatory Telescope Control - Slider #2" }, // 0 to 2 = Not Present, Dark, Lit - { 91, 0, "Stellar Observatory Telescope Control - Slider #3" }, // 0 to 2 = Not Present, Dark, Lit - { 92, 0, "Stellar Observatory Telescope Control - Slider #4 (Right)" }, // 0 to 2 = Not Present, Dark, Lit - { 93, 0, "Breaker nearest Generator Room Blown" }, - { 94, 0, "Breaker nearest Rocket Ship Blown" }, -// 95 = TODO: ? - { 96, 0, "Generator Power Dial Needle Position" }, // 0 to 24 - { 97, 0, "Generator Power To Spaceship Dial Needle Position" }, // 0 to 24 - { 98, 0, "Cabin Boiler Pilot Light Lit" }, - { 99, 0, "Cabin Boiler Gas Valve Position" }, // 0 to 5 - { 100, 0, "Red Book Page State" }, // Bitfield - { 101, 0, "Blue Book Page State" }, // Bitfield - { 102, 1, "Red Page in Age" }, // 0 to 1 - { 103, 1, "Blue Page in Age" }, // 0 to 1 -// 104 = TODO: ? - { 105, 0, "Clock Tower Door / Ship Box Temp Value" }, - { 106, 0, "Red / Blue Book State" }, // 0 to 4, 0-3 = Books Present 4 = Books Burnt - { 300, 0, "Rocket Ship Music Puzzle Slider State" }, // 0 to 2 = Not Present, Dark, Lit - { 301, 0, "Rocket Ship Piano Key Depressed" }, // 0 to 1 - { 302, 0, "Green Book Opened Before Flag" }, // 0 to 1 - { 303, 1, "Myst Library Bookcase Closed / Library Exit Open" }, - { 304, 0, "Myst Library Image Present on Tower Rotation Map" }, // 0 to 1 - { 305, 0, "Cabin Boiler Lit" }, - { 306, 0, "Cabin Boiler Steam Sound Control" }, // 0 to 27 - { 307, 0, "Cabin Boiler Needle Position i.e. Fully Pressurised" }, // 0 to 1 - { 308, 0, "Cabin Safe Handle Position / Matchbox Temp Value" }, - { 309, 0, "Red/Blue/Green Book Open" }, // 0 to 1 - { 310, 0, "Dock Forechamber Imager Control Temp Value?" } -}; - -MystVarEntry mechVars[] = { - { 0, 0, "Achenar's Room Secret Panel State" }, // TODO: Multiple Uses of Var 0? - { 1, 0, "Sirrus's Room Secret Panel State" }, - { 2, 0, "Achenar's Secret Room Crate Lid Open and Blue Page Present" }, // 0 to 4 - // 0 = Lid Closed, Blue Page Present - // 1 = Lid Closed, Blue Page Not Present - // 2 = Lid Open, Blue Page Not Present - // 3 = Lid Open, Blue Page Present - { 3, 0, "Achenar's Secret Room Crate Lid Open" }, // 0 to 1 - { 4, 0, "Myst Book Staircase State" }, - { 5, 0, "Fortress Telescope View" }, - { 6, 0, "Large Cog Visible Through Distant Fortress Doorway" }, // 0 to 1 - { 7, 0, "Fortress Elevator Door Rotated to Open" }, // 0 to 1 -// Var 8 Not Used -// Var 9 Not Used - { 10, 0, "Fortress Staircase State" }, // 0 to 1 - { 11, 0, "Fortress Elevator Rotation Control - Position Indicator" }, // 0 to 9, 4 = Red Open Position - { 12, 0, "Fortress Elevator Rotation Control - Top Cog Position" }, // 0 to 5 - { 13, 0, "Fortress Elevator Vertical Position - View" }, // 0 to 2, Used for View Logic on change from Card 6150 - { 14, 0, "Fortress Elevator Vertical Position - Button" }, // 0 to 2, Used for Button Logic on Card 6120 - { 15, 0, "Code Lock State" }, // 0 to 2 - { 16, 0, "Code Lock Shape #1 (Left)" }, - { 17, 0, "Code Lock Shape #2" }, - { 18, 0, "Code Lock Shape #3" }, - { 19, 0, "Code Lock Shape #4 (Right)" }, - { 20, 0, "Red Dodecahedron Lit" }, - { 21, 0, "Green Dodecahedron Lit" }, - { 22, 0, "Yellow Tetrahedron Lit" }, - { 23, 0, "In Elevator" }, // 0 to 1 - { 102, 1, "Red Page in Age" }, // 0 to 1 - { 103, 1, "Blue Page in Age" } // 0 to 1 -}; - -MystVarEntry channelwoodVars[] = { - { 0, 0, "Multiple Uses..." }, // TODO: Multiple Uses of Var 0? - { 1, 0, "Water Pump Bridge State" }, // 0 to 1 - { 2, 0, "Lower Walkway to Upper Walkway Elevator State" }, // 0 to 1 - { 3, 0, "Water Flowing (R) to Pump for Upper Walkway to Temple Elevator" }, // 0 to 1 - { 4, 0, "Water Flowing (L, R, R, L, Pipe Extended) to Pump for Book Room Elevator" }, // 0 to 1 - { 5, 0, "Lower Walkway to Upper Walkway Spiral Stair Lower Door Open" }, // 0 to 1 - { 6, 0, "Pipe Bridge Extended" }, // 0 to 1 - { 7, 0, "Bridge Pump Running" }, // 0 to 1 - { 8, 0, "Water Tank Valve State" }, // 0 to 1 - { 9, 0, "First Water Valve State" }, // 0 to 1 - { 10, 0, "Second (L) Water Valve State" }, // 0 to 1 - { 11, 0, "Third (L, R) Water Valve State" }, // 0 to 1 - { 12, 0, "Fourth (L, R, R) Water Valve State" }, // 0 to 1 - { 13, 0, "Fourth (L, R, L) Water Valve State" }, // 0 to 1 - { 14, 0, "Third (L, L) Water Valve State" }, // 0 to 1 - { 15, 0, "Water Flowing (L, R, R, R) to Pump for Lower Walkway to Upper Walkway Elevator" }, // 0 to 1 - { 16, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door Open" }, // 0 to 1 - { 17, 0, "Achenar's Holoprojector Selection" }, // 0 to 3 - { 18, 0, "Drawer in Sirrus' Room with Wine Bottles and Torn Note Open" }, // 0 to 1 - { 19, 0, "Water Flowing to First Water Valve" }, // 0 to 1 - { 20, 0, "Water Flowing to Second (L) Water Valve" }, // 0 to 1 - { 21, 0, "Water Flowing to Third (L, R) Water Valve" }, // 0 to 1 - { 22, 0, "Water Flowing to Fourth (L, R, R) Water Valve" }, // 0 to 1 - { 23, 0, "Water Flowing to Fourth (L, R, L) Water Valve" }, // 0 to 1 - { 24, 0, "Water Flowing to Third (L, L) Water Valve" }, // 0 to 1 - { 25, 0, "Water Flowing to Pipe Bridge (L, R, R, L)" }, // 0 to 1 - { 26, 0, "Water Flowing to Pipe At Entry Point (L, R, L, R)" }, // 0 to 1 - { 27, 0, "Water Flowing to Join and Pump Bridge (L, R, L, L)" }, // 0 to 1 - { 28, 0, "Water Flowing to Join and Pump Bridge (L, L, R)" }, // 0 to 1 - { 29, 0, "Water Flowing to Pipe In Water (L, L, L)" }, // 0 to 1 - { 30, 0, "Lower Walkway to Upper Walkway Elevator Door Open" }, // 0 to 1 - { 31, 0, "Water Flowing to Join (L, L, R)" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow - { 32, 0, "Water Flowing (L, R, R, L, Pipe) State" }, // 0 to 2 = Stop Sound, Background, Background with Water Flow - { 33, 0, "Lower Walkway to Upper Walkway Spiral Stair Upper Door State" }, // 0 to 2 = Closed, Open, Open but slams behind you. - { 102, 1, "Red Page in Age" }, // 0 to 1 - { 103, 1, "Blue Page in Age" }, // 0 to 1 - { 105, 0, "Upper Walkway to Temple Elevator Door Open / Temple Iron Door Open" } // 0 to 1, used for slam sound -}; - -MystVarEntry dniVars[] = { - { 0, 0, "Atrus Gone" }, // 0 to 1 // TODO: Multiple Uses of Var 0? - { 1, 0, "Myst Book State" }, // 0 to 2 = Book Inactive, Book Unlinkable, Book Linkable - { 2, 0, "Sound Control" }, // 0 to 2 = Win Tune, Lose Tune, Stop Sound - { 106, 0, "Atrus State Control" } // 0 to 4 = Atrus Writing, Atrus Holding Out Hand, Atrus Gone, Atrus #2, Atrus #2 -}; - -MystVarEntry creditsVars[] = { - { 0, 0, "Image Control" }, // 0 to 6 - { 1, 1, "Sound Control" } // 0 to 1 = Win Tune, Lose Tune -}; - -MystVar::MystVar(MohawkEngine_Myst *vm) { - _vm = vm; -} - -MystVar::~MystVar() { -} - -// Only for use by Save/Load, all other code should use getVar() -uint16 MystVar::saveGetVar(uint16 stack, uint16 v) { - uint16 value = 0; - MystVarEntry unknownVar = { v, 0, "Unknown" }; - const char *desc = NULL; - uint16 i; - - switch (stack) { - case kIntroStack: - for (i = 0; i < ARRAYSIZE(introVars); i++) { - if (introVars[i].refNum == v) { - value = introVars[i].storage; - desc = introVars[i].description; - break; - } - } - break; - case kSeleniticStack: - for (i = 0; i < ARRAYSIZE(seleniticVars); i++) { - if (seleniticVars[i].refNum == v) { - value = seleniticVars[i].storage; - desc = seleniticVars[i].description; - break; - } - } - break; - case kStoneshipStack: - for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) { - if (stoneshipVars[i].refNum == v) { - value = stoneshipVars[i].storage; - desc = stoneshipVars[i].description; - break; - } - } - break; - case kDemoPreviewStack: - case kMystStack: - for (i = 0; i < ARRAYSIZE(mystVars); i++) { - if (mystVars[i].refNum == v) { - value = mystVars[i].storage; - desc = mystVars[i].description; - break; - } - } - break; - case kMechanicalStack: - for (i = 0; i < ARRAYSIZE(mechVars); i++) { - if (mechVars[i].refNum == v) { - value = mechVars[i].storage; - desc = mechVars[i].description; - break; - } - } - break; - case kChannelwoodStack: - for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) { - if (channelwoodVars[i].refNum == v) { - value = channelwoodVars[i].storage; - desc = channelwoodVars[i].description; - break; - } - } - break; - case kDniStack: - for (i = 0; i < ARRAYSIZE(dniVars); i++) { - if (dniVars[i].refNum == v) { - value = dniVars[i].storage; - desc = dniVars[i].description; - break; - } - } - break; - case kCreditsStack: - for (i = 0; i < ARRAYSIZE(creditsVars); i++) { - if (creditsVars[i].refNum == v) { - value = creditsVars[i].storage; - desc = creditsVars[i].description; - break; - } - } - break; - default: - break; - } - - if (desc == NULL) { - for (i = 0; i < _unknown.size(); i++) { - if (_unknown[i].refNum == v) { - value = _unknown[i].storage; - desc = _unknown[i].description; - break; - } - } - - if (desc == NULL) { - warning("MystVar::getVar(%d): Unknown variable reference", v); - _unknown.push_back(unknownVar); - desc = _unknown.back().description; - } - } - - debugC(kDebugVariable, "MystVar::getVar(%d = %s): %d", v, desc, value); - return value; -} - -// Only for use by Save/Load, all other code should use setVar() -void MystVar::loadSetVar(uint16 stack, uint16 v, uint16 value) { - const char *desc = NULL; - MystVarEntry unknownVar = { v, value, "Unknown" }; - uint16 i; - - switch (stack) { - case kIntroStack: - for (i = 0; i < ARRAYSIZE(introVars); i++) { - if (introVars[i].refNum == v) { - introVars[i].storage = value; - desc = introVars[i].description; - break; - } - } - break; - case kSeleniticStack: - for (i = 0; i < ARRAYSIZE(seleniticVars); i++) { - if (seleniticVars[i].refNum == v) { - seleniticVars[i].storage = value; - desc = seleniticVars[i].description; - break; - } - } - break; - case kStoneshipStack: - for (i = 0; i < ARRAYSIZE(stoneshipVars); i++) { - if (stoneshipVars[i].refNum == v) { - stoneshipVars[i].storage = value; - desc = stoneshipVars[i].description; - break; - } - } - break; - case kDemoPreviewStack: - case kMystStack: - for (i = 0; i < ARRAYSIZE(mystVars); i++) { - if (mystVars[i].refNum == v) { - mystVars[i].storage = value; - desc = mystVars[i].description; - break; - } - } - break; - case kMechanicalStack: - for (i = 0; i < ARRAYSIZE(mechVars); i++) { - if (mechVars[i].refNum == v) { - mechVars[i].storage = value; - desc = mechVars[i].description; - break; - } - } - break; - case kChannelwoodStack: - for (i = 0; i < ARRAYSIZE(channelwoodVars); i++) { - if (channelwoodVars[i].refNum == v) { - channelwoodVars[i].storage = value; - desc = channelwoodVars[i].description; - break; - } - } - break; - case kDniStack: - for (i = 0; i < ARRAYSIZE(dniVars); i++) { - if (dniVars[i].refNum == v) { - dniVars[i].storage = value; - desc = dniVars[i].description; - break; - } - } - break; - case kCreditsStack: - for (i = 0; i < ARRAYSIZE(creditsVars); i++) { - if (creditsVars[i].refNum == v) { - creditsVars[i].storage = value; - desc = creditsVars[i].description; - break; - } - } - break; - default: - break; - } - - if (desc == NULL) { - for (i = 0; i < _unknown.size(); i++) { - if (_unknown[i].refNum == v) { - _unknown[i].storage = value; - desc = _unknown[i].description; - break; - } - } - - if (desc == NULL) { - warning("MystVar::setVar(%d): Unknown variable reference", v); - _unknown.push_back(unknownVar); - desc = _unknown.back().description; - } - } - - debugC(kDebugVariable, "MystVar::setVar(%d = %s): %d", v, desc, value); -} - -uint16 MystVar::getVar(uint16 v) { - return this->saveGetVar(_vm->getCurStack(), v); -} - -void MystVar::setVar(uint16 v, uint16 value) { - this->loadSetVar(_vm->getCurStack(), v, value); -} - -} // End of namespace Mohawk diff --git a/engines/mohawk/myst_vars.h b/engines/mohawk/myst_vars.h deleted file mode 100644 index 065d8df2cb..0000000000 --- a/engines/mohawk/myst_vars.h +++ /dev/null @@ -1,60 +0,0 @@ -/* 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. - * - * $URL$ - * $Id$ - * - */ - -#include "mohawk/myst.h" - -#ifndef MYST_VARS_H -#define MYST_VARS_H - -namespace Mohawk { - -struct MystVarEntry { - uint16 refNum; - uint16 storage; // Used for Initial Value setting - const char *description; -}; - -class MystVar { -public: - MystVar(MohawkEngine_Myst *vm); - ~MystVar(); - - // Only for use by Save/Load - // All other code should use getVar() / setVar() - void loadSetVar(uint16 stack, uint16 v, uint16 value); - uint16 saveGetVar(uint16 stack, uint16 v); - - uint16 getVar(uint16 v); - void setVar(uint16 v, uint16 value); - -private: - MohawkEngine_Myst *_vm; - - Common::Array<MystVarEntry> _unknown; -}; - -} // End of namespace Mohawk - -#endif diff --git a/engines/mohawk/riven.cpp b/engines/mohawk/riven.cpp index e9742e0bc2..1d47d453a0 100644 --- a/engines/mohawk/riven.cpp +++ b/engines/mohawk/riven.cpp @@ -57,9 +57,10 @@ MohawkEngine_Riven::MohawkEngine_Riven(OSystem *syst, const MohawkGameDescriptio _gameOver = false; _activatedSLST = false; _ignoreNextMouseUp = false; - _extrasFile = NULL; + _extrasFile = 0; _curStack = aspit; - _hotspots = NULL; + _hotspots = 0; + removeTimer(); // NOTE: We can never really support CD swapping. All of the music files // (*_Sounds.mhk) are stored on disc 1. They are copied to the hard drive @@ -185,12 +186,13 @@ Common::Error MohawkEngine_Riven::run() { } void MohawkEngine_Riven::handleEvents() { - Common::Event event; - - // Update background videos and the water effect + // Update background running things + checkTimer(); bool needsUpdate = _gfx->runScheduledWaterEffects(); needsUpdate |= _video->updateMovies(); + Common::Event event; + while (_eventMan->pollEvent(event)) { switch (event.type) { case Common::EVENT_MOUSEMOVE: @@ -376,6 +378,9 @@ void MohawkEngine_Riven::changeToCard(uint16 dest) { } void MohawkEngine_Riven::refreshCard() { + // Clear any timer still floating around + removeTimer(); + loadHotspots(_curCard); _gfx->_updatesEnabled = true; @@ -393,13 +398,15 @@ void MohawkEngine_Riven::refreshCard() { if (!_activatedSLST) _sound->playSLST(1, _curCard); - if (_showHotspots) { + if (_showHotspots) for (uint16 i = 0; i < _hotspotCount; i++) _gfx->drawRect(_hotspots[i].rect, _hotspots[i].enabled); - } // Now we need to redraw the cursor if necessary and handle mouse over scripts updateCurrentHotspot(); + + // Finally, install any hardcoded timer + installCardTimer(); } void MohawkEngine_Riven::loadCard(uint16 id) { @@ -744,6 +751,88 @@ Common::String MohawkEngine_Riven::getStackName(uint16 stack) const { return rivenStackNames[stack]; } +void MohawkEngine_Riven::installTimer(TimerProc proc, uint32 time) { + removeTimer(); + _timerProc = proc; + _timerTime = time + getTotalPlayTime(); +} + +void MohawkEngine_Riven::checkTimer() { + if (!_timerProc) + return; + + // NOTE: If the specified timer function is called, it is its job to remove the timer! + if (getTotalPlayTime() >= _timerTime) { + TimerProc proc = _timerProc; + proc(this); + } +} + +void MohawkEngine_Riven::removeTimer() { + _timerProc = 0; + _timerTime = 0; +} + +static void catherineIdleTimer(MohawkEngine_Riven *vm) { + uint32 *cathCheck = vm->getVar("pcathcheck"); + uint32 *cathState = vm->getVar("acathstate"); + uint16 movie; + + // Choose a random movie based on where Catherine is + if (*cathCheck == 0) { + static const int movieList[] = { 5, 6, 7, 8 }; + *cathCheck = 1; + movie = movieList[vm->_rnd->getRandomNumber(3)]; + } else if (*cathState == 1) { + static const int movieList[] = { 11, 14 }; + movie = movieList[vm->_rnd->getRandomBit()]; + } else { + static const int movieList[] = { 9, 10, 12, 13 }; + movie = movieList[vm->_rnd->getRandomNumber(3)]; + } + + // Update her state if she moves from left/right or right/left, resp. + if (movie == 5 || movie == 7 || movie == 11 || movie == 14) + *cathState = 2; + else + *cathState = 1; + + // Play the movie, blocking + vm->_video->activateMLST(movie, vm->getCurCard()); + vm->_cursor->hideCursor(); + vm->_video->playMovieBlockingRiven(movie); + vm->_cursor->showCursor(); + vm->_system->updateScreen(); + + // Install the next timer for the next video + uint32 timeUntilNextMovie = vm->_rnd->getRandomNumber(120) * 1000; + + *vm->getVar("pcathtime") = timeUntilNextMovie + vm->getTotalPlayTime(); + + vm->installTimer(&catherineIdleTimer, timeUntilNextMovie); +} + +void MohawkEngine_Riven::installCardTimer() { + switch (getCurCardRMAP()) { + case 0x3a85: // Top of elevator on prison island + // Handle Catherine hardcoded videos + installTimer(&catherineIdleTimer, _rnd->getRandomNumberRng(1, 33) * 1000); + break; + case 0x77d6: // Sunners, top of stairs + // TODO: Background Sunner videos + break; + case 0x79bd: // Sunners, middle of stairs + // TODO: Background Sunner videos + break; + case 0x7beb: // Sunners, bottom of stairs + // TODO: Background Sunner videos + break; + case 0xb6ca: // Sunners, shoreline + // TODO: Background Sunner videos + break; + } +} + bool ZipMode::operator== (const ZipMode &z) const { return z.name == name && z.id == id; } diff --git a/engines/mohawk/riven.h b/engines/mohawk/riven.h index 60a31736d7..6eb02901bb 100644 --- a/engines/mohawk/riven.h +++ b/engines/mohawk/riven.h @@ -127,6 +127,8 @@ public: Common::Error saveGameState(int slot, const char *desc); bool hasFeature(EngineFeature f) const; + typedef void (*TimerProc)(MohawkEngine_Riven *vm); + private: MohawkArchive *_extrasFile; // We need a separate handle for the extra data RivenConsole *_console; @@ -152,6 +154,10 @@ private: uint32 *_vars; uint32 _varCount; + // Timer + TimerProc _timerProc; + uint32 _timerTime; + // Miscellaneous bool _gameOver; bool _ignoreNextMouseUp; @@ -195,6 +201,12 @@ public: bool _activatedSLST; void runLoadDialog(); void delayAndUpdate(uint32 ms); + + // Timer + void installTimer(TimerProc proc, uint32 time); + void installCardTimer(); + void checkTimer(); + void removeTimer(); }; } // End of namespace Mohawk diff --git a/engines/mohawk/riven_external.cpp b/engines/mohawk/riven_external.cpp index 5424a07a3c..2fc0c4e17b 100644 --- a/engines/mohawk/riven_external.cpp +++ b/engines/mohawk/riven_external.cpp @@ -870,12 +870,57 @@ void RivenExternal::xbupdateboiler(uint16 argc, uint16 *argv) { } } +static void ytramTrapTimer(MohawkEngine_Riven *vm) { + // Remove this timer + vm->removeTimer(); + + // Check if we've caught a Ytram + vm->_externalScriptHandler->checkYtramCatch(true); +} + void RivenExternal::xbsettrap(uint16 argc, uint16 *argv) { - // TODO: Set the Ytram trap + // Set the Ytram trap + + // We can catch the Ytram between 10 seconds and 3 minutes from now + uint32 timeUntilCatch = _vm->_rnd->getRandomNumberRng(10, 60 * 3) * 1000; + *_vm->getVar("bytramtime") = timeUntilCatch + _vm->getTotalPlayTime(); + + // And set the timer too + _vm->installTimer(&ytramTrapTimer, timeUntilCatch); +} + +void RivenExternal::checkYtramCatch(bool playSound) { + // Check if we've caught a Ytram + + uint32 *ytramTime = _vm->getVar("bytramtime"); + + // If the trap still has not gone off, reinstall our timer + // This is in case you set the trap, walked away, and returned + if (_vm->getTotalPlayTime() < *ytramTime) { + _vm->installTimer(&ytramTrapTimer, *ytramTime - _vm->getTotalPlayTime()); + return; + } + + // Increment the movie per catch (max = 3) + uint32 *ytramMovie = _vm->getVar("bytram"); + *ytramMovie += 1; + if (*ytramMovie > 3) + *ytramMovie = 3; + + // Reset variables + *_vm->getVar("bytrapped") = 1; + *_vm->getVar("bbait") = 0; + *_vm->getVar("bytrap") = 0; + *ytramTime = 0; + + // Play the capture sound, if requested + if (playSound) + _vm->_sound->playSound(33); } void RivenExternal::xbcheckcatch(uint16 argc, uint16 *argv) { - // TODO: Check if we've caught a Ytram + // Just pass our parameter along... + checkYtramCatch(argv[0] != 0); } void RivenExternal::xbait(uint16 argc, uint16 *argv) { @@ -914,7 +959,28 @@ void RivenExternal::xbait(uint16 argc, uint16 *argv) { } void RivenExternal::xbfreeytram(uint16 argc, uint16 *argv) { - // TODO: Play a random Ytram movie + // Play a random Ytram movie after freeing it + uint16 mlstId; + + switch (*_vm->getVar("bytram")) { + case 1: + mlstId = 11; + break; + case 2: + mlstId = 12; + break; + default: + mlstId = _vm->_rnd->getRandomNumberRng(13, 15); + break; + } + + // Activate the MLST and play the video + _vm->_video->activateMLST(mlstId, _vm->getCurCard()); + _vm->_video->playMovieBlockingRiven(11); + + // Now play the second movie + _vm->_video->activateMLST(mlstId + 5, _vm->getCurCard()); + _vm->_video->playMovieBlockingRiven(12); } void RivenExternal::xbaitplate(uint16 argc, uint16 *argv) { @@ -1380,12 +1446,105 @@ void RivenExternal::xglview_villageoff(uint16 argc, uint16 *argv) { _vm->_gfx->updateScreen(); } +static void catherineViewerIdleTimer(MohawkEngine_Riven *vm) { + uint32 *cathState = vm->getVar("gcathstate"); + uint16 movie; + + // Choose a new movie + if (*cathState == 1) { + static const int movieList[] = { 9, 10, 19, 19, 21, 21 }; + movie = movieList[vm->_rnd->getRandomNumber(5)]; + } else if (*cathState == 2) { + static const int movieList[] = { 18, 20, 22 }; + movie = movieList[vm->_rnd->getRandomNumber(2)]; + } else { + static const int movieList[] = { 11, 11, 12, 17, 17, 17, 17, 23 }; + movie = movieList[vm->_rnd->getRandomNumber(7)]; + } + + // Update Catherine's state + if (movie == 10 || movie == 17 || movie == 18 || movie == 20) + *cathState = 1; + else if (movie == 19 || movie == 21 || movie == 23) + *cathState = 2; + else + *cathState = 3; + + // Begin playing the new movie + vm->_video->activateMLST(movie, vm->getCurCard()); + VideoHandle videoHandle = vm->_video->playMovieRiven(30); + + // Reset the timer + vm->installTimer(&catherineViewerIdleTimer, vm->_video->getDuration(videoHandle) + vm->_rnd->getRandomNumber(60) * 1000); +} + void RivenExternal::xglview_prisonon(uint16 argc, uint16 *argv) { - // TODO: Activate random background Catherine videos + // Activate random background Catherine videos + + // Turn on the left viewer to 'prison mode' + *_vm->getVar("glview") = 1; + + // Get basic starting states + uint16 cathMovie = _vm->_rnd->getRandomNumberRng(8, 23); + uint16 turnOnMovie = 4; + uint32 *cathState = _vm->getVar("gcathstate"); + + // Adjust the turn on movie + if (cathMovie == 14) + turnOnMovie = 6; + else if (cathMovie == 15) + turnOnMovie = 7; + + // Adjust Catherine's state + if (cathMovie == 9 || cathMovie == 11 || cathMovie == 12 || cathMovie == 22) + *cathState = 3; + else if (cathMovie == 19 || cathMovie == 21 || cathMovie == 23 || cathMovie == 14) + *cathState = 2; + else + *cathState = 1; + + // Turn on the viewer + _vm->_cursor->hideCursor(); + _vm->_video->playMovieBlockingRiven(turnOnMovie); + _vm->_cursor->showCursor(); + + uint32 timeUntilNextMovie; + + // Begin playing a movie immediately if Catherine is already in the viewer + if (cathMovie == 8 || (cathMovie >= 13 && cathMovie <= 16)) { + _vm->_video->activateMLST(cathMovie, _vm->getCurCard()); + VideoHandle videoHandle = _vm->_video->playMovieRiven(30); + + timeUntilNextMovie = _vm->_video->getDuration(videoHandle) + _vm->_rnd->getRandomNumber(60) * 1000; + } else { + // Otherwise, just redraw the imager + timeUntilNextMovie = _vm->_rnd->getRandomNumberRng(10, 20) * 1000; + _vm->_gfx->drawPLST(8); + _vm->_gfx->updateScreen(); + } + + // Create the timer for the next video + _vm->installTimer(&catherineViewerIdleTimer, timeUntilNextMovie); } void RivenExternal::xglview_prisonoff(uint16 argc, uint16 *argv) { - // TODO: Deactivate random background Catherine videos + // Deactivate random background Catherine videos + + // Update the viewer state (now off) + *_vm->getVar("glview") = 0; + + // Remove the timer we set in xglview_prisonon() + _vm->removeTimer(); + + // Play the 'turn off' movie after stopping any videos still playing + _vm->_video->stopVideos(); + _vm->_cursor->hideCursor(); + _vm->_video->playMovieBlockingRiven(5); + _vm->_cursor->showCursor(); + + // Redraw the viewer + _vm->_gfx->drawPLST(1); + _vm->_gfx->updateScreen(); } // ------------------------------------------------------------------------------------ diff --git a/engines/mohawk/riven_external.h b/engines/mohawk/riven_external.h index 90fdc664c1..034cd662f6 100644 --- a/engines/mohawk/riven_external.h +++ b/engines/mohawk/riven_external.h @@ -41,6 +41,7 @@ public: uint16 getComboDigit(uint32 correctCombo, uint32 digit); uint32 getDomeSliderState() { return _sliderState; } void setDomeSliderState(uint32 state) { _sliderState = state; } + void checkYtramCatch(bool playSound); private: MohawkEngine_Riven *_vm; diff --git a/engines/mohawk/riven_saveload.cpp b/engines/mohawk/riven_saveload.cpp index c7b5cd01fd..d70c3c69b1 100644 --- a/engines/mohawk/riven_saveload.cpp +++ b/engines/mohawk/riven_saveload.cpp @@ -167,14 +167,22 @@ bool RivenSaveLoad::loadGame(Common::String filename) { uint32 *var = _vm->getVar(name); - *var = rawVariables[i]; - - if (name.equalsIgnoreCase("CurrentStackID")) + // Handle any special variables here + // WORKAROUND: bytramtime is reset here for one main reason: + // The save does not store any start point for the time, so we don't know the real time. + // Because of this, in many cases, the original would just give a 'free' Ytram upon saving + // since the time would be used in a new (improper) time frame. + // TODO: Check of the other 'time' variables require this too + if (name.equalsIgnoreCase("CurrentStackID")) // Remap to our definitions, store for later stackID = mapOldStackIDToNew(rawVariables[i]); - else if (name.equalsIgnoreCase("CurrentCardID")) + else if (name.equalsIgnoreCase("CurrentCardID")) // Store for later cardID = rawVariables[i]; - else if (name.equalsIgnoreCase("ReturnStackID")) + else if (name.equalsIgnoreCase("ReturnStackID") && *var != 0) // if 0, the game did not use the variable yet *var = mapOldStackIDToNew(rawVariables[i]); + else if (name.equalsIgnoreCase("bytramtime")) // WORKAROUND: See above + *var = 0; + else // Otherwise, just store it + *var = rawVariables[i]; } _vm->changeToStack(stackID); diff --git a/engines/mohawk/video.cpp b/engines/mohawk/video.cpp index 9bf202083a..f481b5ceb2 100644 --- a/engines/mohawk/video.cpp +++ b/engines/mohawk/video.cpp @@ -490,6 +490,11 @@ uint32 VideoManager::getElapsedTime(VideoHandle handle) { return _videoStreams[handle]->getElapsedTime(); } +uint32 VideoManager::getDuration(VideoHandle handle) { + assert(handle != NULL_VID_HANDLE); + return _videoStreams[handle]->getDuration(); +} + bool VideoManager::endOfVideo(VideoHandle handle) { assert(handle != NULL_VID_HANDLE); return _videoStreams[handle].endOfVideo(); diff --git a/engines/mohawk/video.h b/engines/mohawk/video.h index 6b9cfa25d2..e65629a1ec 100644 --- a/engines/mohawk/video.h +++ b/engines/mohawk/video.h @@ -104,6 +104,7 @@ public: int32 getCurFrame(VideoHandle handle); uint32 getFrameCount(VideoHandle handle); uint32 getElapsedTime(VideoHandle handle); + uint32 getDuration(VideoHandle videoHandle); bool endOfVideo(VideoHandle handle); void setVideoBounds(VideoHandle handle, Audio::Timestamp start, Audio::Timestamp end); void seekToTime(VideoHandle handle, Audio::Timestamp time); diff --git a/engines/parallaction/parallaction.cpp b/engines/parallaction/parallaction.cpp index 1113eb5dca..3055439e47 100644 --- a/engines/parallaction/parallaction.cpp +++ b/engines/parallaction/parallaction.cpp @@ -52,6 +52,8 @@ uint32 _globalFlags = 0; Parallaction::Parallaction(OSystem *syst, const PARALLACTIONGameDescription *gameDesc) : Engine(syst), _gameDescription(gameDesc), _location(getGameType()), _dialogueMan(0) { + // Setup mixer + syncSoundSettings(); _vm = this; DebugMan.addDebugChannel(kDebugDialogue, "dialogue", "Dialogues debug level"); diff --git a/engines/queen/queen.cpp b/engines/queen/queen.cpp index 74bb52f574..692e38179a 100644 --- a/engines/queen/queen.cpp +++ b/engines/queen/queen.cpp @@ -240,14 +240,20 @@ void QueenEngine::checkOptionSettings() { } void QueenEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + readOptionSettings(); } void QueenEngine::readOptionSettings() { + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + _sound->setVolume(ConfMan.getInt("music_volume")); - _sound->musicToggle(!ConfMan.getBool("music_mute")); - _sound->sfxToggle(!ConfMan.getBool("sfx_mute")); - _sound->speechToggle(!ConfMan.getBool("speech_mute")); + _sound->musicToggle(!(mute || ConfMan.getBool("music_mute"))); + _sound->sfxToggle(!(mute || ConfMan.getBool("sfx_mute"))); + _sound->speechToggle(!(mute || ConfMan.getBool("speech_mute"))); _talkSpeed = (ConfMan.getInt("talkspeed") * (MAX_TEXT_SPEED - MIN_TEXT_SPEED) + 255 / 2) / 255 + MIN_TEXT_SPEED; _subtitles = ConfMan.getBool("subtitles"); checkOptionSettings(); @@ -470,11 +476,14 @@ Common::Error QueenEngine::run() { } _sound = Sound::makeSoundInstance(_mixer, this, _resource->getCompression()); + _walk = new Walk(this); //_talkspeedScale = (MAX_TEXT_SPEED - MIN_TEXT_SPEED) / 255.0; registerDefaultSettings(); - readOptionSettings(); + + // Setup mixer + syncSoundSettings(); _logic->start(); if (ConfMan.hasKey("save_slot") && canLoadOrSave()) { diff --git a/engines/queen/sound.cpp b/engines/queen/sound.cpp index 6eb7362338..a34af99ec3 100644 --- a/engines/queen/sound.cpp +++ b/engines/queen/sound.cpp @@ -192,10 +192,12 @@ Sound *Sound::makeSoundInstance(Audio::Mixer *mixer, QueenEngine *vm, uint8 comp } void Sound::setVolume(int vol) { - _musicVolume = vol; + if (ConfMan.hasKey("mute") && ConfMan.getBool("mute")) + _musicVolume = 0; + else + _musicVolume = vol; + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, _musicVolume); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); } void Sound::saveState(byte *&ptr) { diff --git a/engines/saga/music.cpp b/engines/saga/music.cpp index dd3034cdb9..f801001d88 100644 --- a/engines/saga/music.cpp +++ b/engines/saga/music.cpp @@ -239,6 +239,9 @@ void Music::setVolume(int volume, int time) { volume = 255; if (time == 1) { + if (ConfMan.hasKey("mute") && ConfMan.getBool("mute")) + volume = 0; + _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, volume); _driver->setVolume(volume); _vm->getTimerManager()->removeTimerProc(&musicVolumeGaugeCallback); diff --git a/engines/saga/saga.cpp b/engines/saga/saga.cpp index 2e34b49dc5..62493f5eac 100644 --- a/engines/saga/saga.cpp +++ b/engines/saga/saga.cpp @@ -625,6 +625,8 @@ GUI::Debugger *SagaEngine::getDebugger() { } void SagaEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + _subtitlesEnabled = ConfMan.getBool("subtitles"); _readingSpeed = getTalkspeed(); diff --git a/engines/saga/sound.cpp b/engines/saga/sound.cpp index 07e8487ee4..8ffce4e6cd 100644 --- a/engines/saga/sound.cpp +++ b/engines/saga/sound.cpp @@ -175,8 +175,12 @@ void Sound::stopAll() { } void Sound::setVolume() { - _vm->_soundVolume = ConfMan.getInt("sfx_volume"); - _vm->_speechVolume = ConfMan.getInt("speech_volume"); + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + _vm->_soundVolume = mute ? 0 : ConfMan.getInt("sfx_volume"); + _vm->_speechVolume = mute ? 0 : ConfMan.getInt("speech_volume"); _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, _vm->_soundVolume); _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, _vm->_speechVolume); } diff --git a/engines/sci/console.cpp b/engines/sci/console.cpp index fddae530e0..93d21c32e0 100644 --- a/engines/sci/console.cpp +++ b/engines/sci/console.cpp @@ -40,6 +40,7 @@ #include "sci/sound/music.h" #include "sci/sound/drivers/mididriver.h" #include "sci/sound/drivers/map-mt32-to-gm.h" +#include "sci/graphics/animate.h" #include "sci/graphics/cache.h" #include "sci/graphics/cursor.h" #include "sci/graphics/screen.h" @@ -47,6 +48,7 @@ #include "sci/graphics/paint16.h" #include "sci/graphics/paint32.h" #include "sci/graphics/palette.h" +#include "sci/graphics/ports.h" #include "sci/graphics/view.h" #include "sci/parser/vocabulary.h" @@ -125,6 +127,10 @@ Console::Console(SciEngine *engine) : GUI::Debugger(), DCmd_Register("undither", WRAP_METHOD(Console, cmdUndither)); DCmd_Register("pic_visualize", WRAP_METHOD(Console, cmdPicVisualize)); DCmd_Register("play_video", WRAP_METHOD(Console, cmdPlayVideo)); + DCmd_Register("animate_list", WRAP_METHOD(Console, cmdAnimateList)); + DCmd_Register("al", WRAP_METHOD(Console, cmdAnimateList)); // alias + DCmd_Register("window_list", WRAP_METHOD(Console, cmdWindowList)); + DCmd_Register("wl", WRAP_METHOD(Console, cmdWindowList)); // alias // Segments DCmd_Register("segment_table", WRAP_METHOD(Console, cmdPrintSegmentTable)); DCmd_Register("segtable", WRAP_METHOD(Console, cmdPrintSegmentTable)); // alias @@ -356,6 +362,8 @@ bool Console::cmdHelp(int argc, const char **argv) { DebugPrintf(" draw_cel - Draws a cel from a view resource\n"); DebugPrintf(" pic_visualize - Enables visualization of the drawing process of EGA pictures\n"); DebugPrintf(" undither - Enable/disable undithering\n"); + DebugPrintf(" play_video - Plays a SEQ, AVI, VMD, RBT or DUK video\n"); + DebugPrintf(" animate_object_list / al - Shows the current list of objects in kAnimate's draw list\n"); DebugPrintf("\n"); DebugPrintf("Segments:\n"); DebugPrintf(" segment_table / segtable - Lists all segments\n"); @@ -1576,6 +1584,22 @@ bool Console::cmdPlayVideo(int argc, const char **argv) { } } +bool Console::cmdAnimateList(int argc, const char **argv) { + if (_engine->_gfxAnimate) { + DebugPrintf("Animate list:\n"); + _engine->_gfxAnimate->printAnimateList(this); + } + return true; +} + +bool Console::cmdWindowList(int argc, const char **argv) { + if (_engine->_gfxPorts) { + DebugPrintf("Window list:\n"); + _engine->_gfxPorts->printWindowList(this); + } + return true; + +} bool Console::cmdParseGrammar(int argc, const char **argv) { DebugPrintf("Parse grammar, in strict GNF:\n"); @@ -1710,9 +1734,7 @@ bool Console::segmentInfo(int nr) { for (uint i = 0; i < ct->_table.size(); i++) if (ct->isValidEntry(i)) { - reg_t objpos; - objpos.offset = i; - objpos.segment = nr; + reg_t objpos = make_reg(nr, i); DebugPrintf(" [%04x] %s; copy of ", i, _engine->_gamestate->_segMan->getObjectName(objpos)); // Object header const Object *obj = _engine->_gamestate->_segMan->getObject(ct->_table[i].getPos()); diff --git a/engines/sci/console.h b/engines/sci/console.h index d45454376a..93ccc45503 100644 --- a/engines/sci/console.h +++ b/engines/sci/console.h @@ -95,6 +95,8 @@ private: bool cmdUndither(int argc, const char **argv); bool cmdPicVisualize(int argc, const char **argv); bool cmdPlayVideo(int argc, const char **argv); + bool cmdAnimateList(int argc, const char **argv); + bool cmdWindowList(int argc, const char **argv); // Segments bool cmdPrintSegmentTable(int argc, const char **argv); bool cmdSegmentInfo(int argc, const char **argv); diff --git a/engines/sci/detection_tables.h b/engines/sci/detection_tables.h index 923d35fe16..23d76cc0f6 100644 --- a/engines/sci/detection_tables.h +++ b/engines/sci/detection_tables.h @@ -1608,7 +1608,13 @@ static const struct ADGameDescription SciGameDescriptions[] = { AD_LISTEND}, Common::EN_ANY, Common::kPlatformPC, 0, GUIO_NOSPEECH }, - // Larry 1 VGA Remake - English Amiga (from www.back2roots.org) +#if 0 + // The resource.002 file, contained in disk 3, is broken in this version + // (it contains a large chunk of zeroes and several broken resources, + // e.g. pic 250 and views 250 and 251). + // Thus this detection entry isn't accurate. + + // Larry 1 Remake - English Amiga (from www.back2roots.org) // Executable scanning reports "1.004.024" // SCI interpreter version 1.000.784 {"lsl1sci", "SCI", { @@ -1619,6 +1625,7 @@ static const struct ADGameDescription SciGameDescriptions[] = { {"resource.003", 0, "4a34c3367c2fe7eb380d741374da1989", 572251}, AD_LISTEND}, Common::EN_ANY, Common::kPlatformAmiga, 0, GUIO_NOSPEECH }, +#endif // Larry 1 VGA Remake - English DOS (from spookypeanut) // Executable scanning reports "1.000.577", VERSION file reports "2.1" diff --git a/engines/sci/engine/gc.cpp b/engines/sci/engine/gc.cpp index d205763051..e395eeab94 100644 --- a/engines/sci/engine/gc.cpp +++ b/engines/sci/engine/gc.cpp @@ -49,28 +49,23 @@ const char *segmentTypeNames[] = { }; #endif -struct WorklistManager { - Common::Array<reg_t> _worklist; - AddrSet _map; // used for 2 contains() calls, inside push() and run_gc() +void WorklistManager::push(reg_t reg) { + if (!reg.segment) // No numbers + return; - void push(reg_t reg) { - if (!reg.segment) // No numbers - return; + debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg)); - debugC(kDebugLevelGC, "[GC] Adding %04x:%04x", PRINT_REG(reg)); + if (_map.contains(reg)) + return; // already dealt with it - if (_map.contains(reg)) - return; // already dealt with it - - _map.setVal(reg, true); - _worklist.push_back(reg); - } + _map.setVal(reg, true); + _worklist.push_back(reg); +} - void pushArray(const Common::Array<reg_t> &tmp) { - for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) - push(*it); - } -}; +void WorklistManager::pushArray(const Common::Array<reg_t> &tmp) { + for (Common::Array<reg_t>::const_iterator it = tmp.begin(); it != tmp.end(); ++it) + push(*it); +} static AddrSet *normalizeAddresses(SegManager *segMan, const AddrSet &nonnormal_map) { AddrSet *normal_map = new AddrSet(); @@ -103,18 +98,6 @@ static void processWorkList(SegManager *segMan, WorklistManager &wm, const Commo } } -static void processEngineHunkList(WorklistManager &wm) { - PortList windowList = g_sci->_gfxPorts->_windowList; - - for (PortList::const_iterator it = windowList.begin(); it != windowList.end(); ++it) { - if ((*it)->isWindow()) { - Window *wnd = ((Window *)*it); - wm.push(wnd->hSaved1); - wm.push(wnd->hSaved2); - } - } -} - AddrSet *findAllActiveReferences(EngineState *s) { assert(!s->_executionStack.empty()); @@ -174,8 +157,8 @@ AddrSet *findAllActiveReferences(EngineState *s) { processWorkList(s->_segMan, wm, heap); - if (getSciVersion() <= SCI_VERSION_1_1) - processEngineHunkList(wm); + if (g_sci->_gfxPorts) + g_sci->_gfxPorts->processEngineHunkList(wm); return normalizeAddresses(s->_segMan, wm._map); } diff --git a/engines/sci/engine/gc.h b/engines/sci/engine/gc.h index f4318a1453..48e1c6b482 100644 --- a/engines/sci/engine/gc.h +++ b/engines/sci/engine/gc.h @@ -58,6 +58,15 @@ AddrSet *findAllActiveReferences(EngineState *s); */ void run_gc(EngineState *s); +struct WorklistManager { + Common::Array<reg_t> _worklist; + AddrSet _map; // used for 2 contains() calls, inside push() and run_gc() + + void push(reg_t reg); + void pushArray(const Common::Array<reg_t> &tmp); +}; + + } // End of namespace Sci #endif // SCI_ENGINE_GC_H diff --git a/engines/sci/graphics/animate.cpp b/engines/sci/graphics/animate.cpp index e02b27c788..d8f3fa09b0 100644 --- a/engines/sci/graphics/animate.cpp +++ b/engines/sci/graphics/animate.cpp @@ -27,6 +27,7 @@ #include "common/stack.h" #include "graphics/primitives.h" +#include "sci/console.h" #include "sci/sci.h" #include "sci/event.h" #include "sci/engine/kernel.h" @@ -728,4 +729,21 @@ void GfxAnimate::kernelAddToPicView(GuiResourceId viewId, int16 loopNo, int16 ce addToPicSetPicNotValid(); } +void GfxAnimate::printAnimateList(Console *con) { + AnimateList::iterator it; + const AnimateList::iterator end = _list.end(); + + for (it = _list.begin(); it != end; ++it) { + Script *scr = _s->_segMan->getScriptIfLoaded(it->object.segment); + int16 scriptNo = scr ? scr->getScriptNumber() : -1; + + con->DebugPrintf("%04x:%04x (%s), script %d, view %d (%d, %d), pal %d, " + "at %d, %d, scale %d, %d / %d (z: %d, prio: %d, shown: %d, signal: %d)\n", + PRINT_REG(it->object), _s->_segMan->getObjectName(it->object), + scriptNo, it->viewId, it->loopNo, it->celNo, it->paletteNo, + it->x, it->y, it->scaleX, it->scaleY, it->scaleSignal, + it->z, it->priority, it->showBitsFlag, it->signal); + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/animate.h b/engines/sci/graphics/animate.h index 87072b7a8d..b2aadcbead 100644 --- a/engines/sci/graphics/animate.h +++ b/engines/sci/graphics/animate.h @@ -77,6 +77,7 @@ struct AnimateEntry { typedef Common::List<AnimateEntry> AnimateList; typedef Common::Array<AnimateEntry> AnimateArray; +class Console; class GfxCache; class GfxCursor; class GfxPorts; @@ -105,6 +106,7 @@ public: void reAnimate(Common::Rect rect); void addToPicDrawCels(); void addToPicDrawView(GuiResourceId viewId, int16 loopNo, int16 celNo, int16 leftPos, int16 topPos, int16 priority, int16 control); + void printAnimateList(Console *con); virtual void kernelAnimate(reg_t listReference, bool cycle, int argc, reg_t *argv); virtual void kernelAddToPicList(reg_t listReference, int argc, reg_t *argv); diff --git a/engines/sci/graphics/paint16.h b/engines/sci/graphics/paint16.h index 4f709fd7c6..69ddf09ea6 100644 --- a/engines/sci/graphics/paint16.h +++ b/engines/sci/graphics/paint16.h @@ -36,7 +36,6 @@ class GfxPorts; class GfxScreen; class GfxPalette; class Font; -class SciGuiPicture; class GfxView; /** diff --git a/engines/sci/graphics/ports.cpp b/engines/sci/graphics/ports.cpp index 9ac8d103fc..cc206bd5b9 100644 --- a/engines/sci/graphics/ports.cpp +++ b/engines/sci/graphics/ports.cpp @@ -25,8 +25,10 @@ #include "common/util.h" +#include "sci/console.h" #include "sci/sci.h" #include "sci/engine/features.h" +#include "sci/engine/gc.h" #include "sci/engine/kernel.h" #include "sci/engine/state.h" #include "sci/engine/selector.h" @@ -707,4 +709,26 @@ int16 GfxPorts::kernelPriorityToCoordinate(byte priority) { return _priorityBottom; } +void GfxPorts::processEngineHunkList(WorklistManager &wm) { + for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) { + if ((*it)->isWindow()) { + Window *wnd = ((Window *)*it); + wm.push(wnd->hSaved1); + wm.push(wnd->hSaved2); + } + } +} + +void GfxPorts::printWindowList(Console *con) { + for (PortList::const_iterator it = _windowList.begin(); it != _windowList.end(); ++it) { + if ((*it)->isWindow()) { + Window *wnd = ((Window *)*it); + con->DebugPrintf("%d: '%s' at %d, %d, (%d, %d, %d, %d), drawn: %d, style: %d\n", + wnd->id, wnd->title.c_str(), wnd->left, wnd->top, + wnd->rect.left, wnd->rect.top, wnd->rect.right, wnd->rect.bottom, + wnd->bDrawn, wnd->wndStyle); + } + } +} + } // End of namespace Sci diff --git a/engines/sci/graphics/ports.h b/engines/sci/graphics/ports.h index 9faee2be8d..31ed671daf 100644 --- a/engines/sci/graphics/ports.h +++ b/engines/sci/graphics/ports.h @@ -32,10 +32,10 @@ namespace Sci { -class SciGui; class GfxPaint16; class GfxScreen; class GfxText16; +struct WorklistManager; // window styles enum { @@ -103,6 +103,8 @@ public: void kernelGraphAdjustPriority(int top, int bottom); byte kernelCoordinateToPriority(int16 y); int16 kernelPriorityToCoordinate(byte priority); + void processEngineHunkList(WorklistManager &wm); + void printWindowList(Console *con); Port *_wmgrPort; Window *_picWind; @@ -115,10 +117,10 @@ public: virtual void saveLoadWithSerializer(Common::Serializer &ser); +private: /** The list of open 'windows' (and ports), in visual order. */ PortList _windowList; -private: /** The list of all open 'windows' (and ports), ordered by their id. */ PortArray _windowsById; diff --git a/engines/sci/sci.h b/engines/sci/sci.h index 26ddb00a01..cd50b2402c 100644 --- a/engines/sci/sci.h +++ b/engines/sci/sci.h @@ -77,7 +77,6 @@ class GfxText16; class GfxTransitions; #ifdef ENABLE_SCI32 -class SciGui32; class RobotDecoder; class GfxFrameout; #endif diff --git a/engines/scumm/scumm.cpp b/engines/scumm/scumm.cpp index c2556d6467..564f3a7e9c 100644 --- a/engines/scumm/scumm.cpp +++ b/engines/scumm/scumm.cpp @@ -1874,11 +1874,11 @@ void ScummEngine::setupMusic(int midi) { } void ScummEngine::syncSoundSettings() { + Engine::syncSoundSettings(); // Sync the engine with the config manager int soundVolumeMusic = ConfMan.getInt("music_volume"); int soundVolumeSfx = ConfMan.getInt("sfx_volume"); - int soundVolumeSpeech = ConfMan.getInt("speech_volume"); bool mute = false; @@ -1886,7 +1886,7 @@ void ScummEngine::syncSoundSettings() { mute = ConfMan.getBool("mute"); if (mute) - soundVolumeMusic = soundVolumeSfx = soundVolumeSpeech = 0; + soundVolumeMusic = soundVolumeSfx = 0; } if (_musicEngine) { @@ -1897,10 +1897,6 @@ void ScummEngine::syncSoundSettings() { _townsPlayer->setSfxVolume(soundVolumeSfx); } - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, soundVolumeSfx); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, soundVolumeMusic); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, soundVolumeSpeech); - if (ConfMan.getBool("speech_mute")) _voiceMode = 2; else diff --git a/engines/sky/sky.cpp b/engines/sky/sky.cpp index c42bb6301e..f3556c84b3 100644 --- a/engines/sky/sky.cpp +++ b/engines/sky/sky.cpp @@ -100,6 +100,22 @@ SkyEngine::~SkyEngine() { free(_itemList[i]); } +void SkyEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + + bool mute = false; + if (ConfMan.hasKey("mute")) + mute = ConfMan.getBool("mute"); + + if (ConfMan.getBool("sfx_mute")) + SkyEngine::_systemVars.systemFlags |= SF_FX_OFF; + + if (ConfMan.getBool("music_mute")) + SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF; + + _skyMusic->setVolume(mute ? 0: ConfMan.getInt("music_volume") >> 1); +} + GUI::Debugger *SkyEngine::getDebugger() { return _debugger; } @@ -242,16 +258,6 @@ Common::Error SkyEngine::go() { Common::Error SkyEngine::init() { initGraphics(320, 200, false); - if (ConfMan.getBool("sfx_mute")) { - SkyEngine::_systemVars.systemFlags |= SF_FX_OFF; - } - if (ConfMan.getBool("music_mute")) { - SkyEngine::_systemVars.systemFlags |= SF_MUS_OFF; - } - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); - _skyDisk = new Disk(); _skySound = new Sound(_mixer, _skyDisk, Audio::Mixer::kMaxChannelVolume); @@ -346,7 +352,8 @@ Common::Error SkyEngine::init() { } } - _skyMusic->setVolume(ConfMan.getInt("music_volume") >> 1); + // Setup mixer + syncSoundSettings(); _debugger = new Debugger(_skyLogic, _skyMouse, _skyScreen, _skyCompact); return Common::kNoError; diff --git a/engines/sky/sky.h b/engines/sky/sky.h index 29e7c9ab42..d8ced1e569 100644 --- a/engines/sky/sky.h +++ b/engines/sky/sky.h @@ -84,6 +84,8 @@ public: SkyEngine(OSystem *syst); virtual ~SkyEngine(); + virtual void syncSoundSettings(); + static bool isDemo(); static bool isCDVersion(); diff --git a/engines/sword1/sword1.cpp b/engines/sword1/sword1.cpp index 537720401d..8768e62457 100644 --- a/engines/sword1/sword1.cpp +++ b/engines/sword1/sword1.cpp @@ -170,6 +170,8 @@ void SwordEngine::reinitialize() { } void SwordEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + uint musicVol = ConfMan.getInt("music_volume"); uint sfxVol = ConfMan.getInt("sfx_volume"); uint speechVol = ConfMan.getInt("speech_volume"); @@ -228,9 +230,6 @@ void SwordEngine::syncSoundSettings() { _sound->setSpeechVol(speechVolL, speechVolR); _sound->setSfxVol(sfxVolL, sfxVolR); } - - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume")); } void SwordEngine::flagsToBool(bool *dest, uint8 flags) { diff --git a/engines/sword2/sword2.cpp b/engines/sword2/sword2.cpp index 9c67fcdf25..7ad021b3a5 100644 --- a/engines/sword2/sword2.cpp +++ b/engines/sword2/sword2.cpp @@ -319,11 +319,10 @@ void Sword2Engine::registerDefaultSettings() { } void Sword2Engine::syncSoundSettings() { + Engine::syncSoundSettings(); + bool mute = ConfMan.getBool("mute"); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, mute ? 0 : ConfMan.getInt("music_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, mute ? 0 : ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, mute ? 0 : ConfMan.getInt("sfx_volume")); setSubtitles(ConfMan.getBool("subtitles")); // Our own settings dialog can mute the music, speech and sound effects diff --git a/engines/sword25/gfx/graphicengine_script.cpp b/engines/sword25/gfx/graphicengine_script.cpp index d67d0038c3..d8daaab32c 100644 --- a/engines/sword25/gfx/graphicengine_script.cpp +++ b/engines/sword25/gfx/graphicengine_script.cpp @@ -81,26 +81,6 @@ static ActionCallback *actionCallbackPtr = 0; // FIXME: should be turned into Gr #define ANIMATION_TEMPLATE_CLASS_NAME "Gfx.AnimationTemplate" static const char *GFX_LIBRARY_NAME = "Gfx"; -// Wie luaL_checkudata, nur ohne dass kein Fehler erzeugt wird. -static void *my_checkudata(lua_State *L, int ud, const char *tname) { - int top = lua_gettop(L); - - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ - LuaBindhelper::getMetatable(L, tname); - if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ - lua_settop(L, top); - return p; - } - } - } - - lua_settop(L, top); - return NULL; -} - static void newUintUserData(lua_State *L, uint value) { void *userData = lua_newuserdata(L, sizeof(value)); memcpy(userData, &value, sizeof(value)); @@ -108,8 +88,8 @@ static void newUintUserData(lua_State *L, uint value) { static AnimationTemplate *checkAnimationTemplate(lua_State *L, int idx = 1) { // Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.AnimationTemplate - uint animationTemplateHandle; - if ((animationTemplateHandle = *reinterpret_cast<uint *>(my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME))) != 0) { + uint animationTemplateHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, idx, ANIMATION_TEMPLATE_CLASS_NAME)); + if (animationTemplateHandle != 0) { AnimationTemplate *animationTemplatePtr = AnimationTemplateRegistry::instance().resolveHandle(animationTemplateHandle); if (!animationTemplatePtr) luaL_error(L, "The animation template with the handle %d does no longer exist.", animationTemplateHandle); @@ -370,10 +350,10 @@ static const luaL_reg GFX_FUNCTIONS[] = { static RenderObjectPtr<RenderObject> checkRenderObject(lua_State *L, bool errorIfRemoved = true) { // Der erste Parameter muss vom Typ userdata sein und die Metatable einer Klasse haben, die von Gfx.RenderObject "erbt". uint *userDataPtr; - if ((userDataPtr = (uint *) my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 || - (userDataPtr = (uint *) my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 || - (userDataPtr = (uint *) my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 || - (userDataPtr = (uint *) my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) { + if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0 || + (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0 || + (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0 || + (userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) { RenderObjectPtr<RenderObject> roPtr(*userDataPtr); if (roPtr.isValid()) return roPtr; @@ -600,11 +580,11 @@ static const luaL_reg RENDEROBJECT_METHODS[] = { static RenderObjectPtr<Panel> checkPanel(lua_State *L) { // Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Panel uint *userDataPtr; - if ((userDataPtr = (uint *)my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) { + if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, PANEL_CLASS_NAME)) != 0) { RenderObjectPtr<RenderObject> roPtr(*userDataPtr); - if (roPtr.isValid()) { + if (roPtr.isValid()) return roPtr->toPanel(); - } else + else luaL_error(L, "The panel with the handle %d does no longer exist.", *userDataPtr); } else { luaL_argcheck(L, 0, 1, "'" PANEL_CLASS_NAME "' expected"); @@ -645,11 +625,11 @@ static const luaL_reg PANEL_METHODS[] = { static RenderObjectPtr<Bitmap> checkBitmap(lua_State *L) { // Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Bitmap uint *userDataPtr; - if ((userDataPtr = (uint *)my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) { + if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, BITMAP_CLASS_NAME)) != 0) { RenderObjectPtr<RenderObject> roPtr(*userDataPtr); - if (roPtr.isValid()) { + if (roPtr.isValid()) return roPtr->toBitmap(); - } else + else luaL_error(L, "The bitmap with the handle %d does no longer exist.", *userDataPtr); } else { luaL_argcheck(L, 0, 1, "'" BITMAP_CLASS_NAME "' expected"); @@ -790,13 +770,12 @@ static const luaL_reg BITMAP_METHODS[] = { static RenderObjectPtr<Animation> checkAnimation(lua_State *L) { // Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Animation uint *userDataPtr; - if ((userDataPtr = (uint *)my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) { + if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, ANIMATION_CLASS_NAME)) != 0) { RenderObjectPtr<RenderObject> roPtr(*userDataPtr); if (roPtr.isValid()) return roPtr->toAnimation(); - else { + else luaL_error(L, "The animation with the handle %d does no longer exist.", *userDataPtr); - } } else { luaL_argcheck(L, 0, 1, "'" ANIMATION_CLASS_NAME "' expected"); } @@ -1064,7 +1043,7 @@ static const luaL_reg ANIMATION_METHODS[] = { static RenderObjectPtr<Text> checkText(lua_State *L) { // Der erste Parameter muss vom Typ userdata sein und die Metatable der Klasse Gfx.Text uint *userDataPtr; - if ((userDataPtr = (uint *)my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) { + if ((userDataPtr = (uint *)LuaBindhelper::my_checkudata(L, 1, TEXT_CLASS_NAME)) != 0) { RenderObjectPtr<RenderObject> roPtr(*userDataPtr); if (roPtr.isValid()) return roPtr->toText(); diff --git a/engines/sword25/math/geometry_script.cpp b/engines/sword25/math/geometry_script.cpp index 6562a0f0a5..4b5e0550fe 100644 --- a/engines/sword25/math/geometry_script.cpp +++ b/engines/sword25/math/geometry_script.cpp @@ -51,27 +51,6 @@ namespace Sword25 { #define REGION_CLASS_NAME "Geo.Region" #define WALKREGION_CLASS_NAME "Geo.WalkRegion" -// How luaL_checkudata, only without that no error is generated. -static void *my_checkudata(lua_State *L, int ud, const char *tname) { - int top = lua_gettop(L); - - void *p = lua_touserdata(L, ud); - if (p != NULL) { /* value is a userdata? */ - if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ - // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ - LuaBindhelper::getMetatable(L, tname); - /* does it have the correct mt? */ - if (lua_rawequal(L, -1, -2)) { - lua_settop(L, top); - return p; - } - } - } - - lua_settop(L, top); - return NULL; -} - static void newUintUserData(lua_State *L, uint value) { void *userData = lua_newuserdata(L, sizeof(value)); memcpy(userData, &value, sizeof(value)); @@ -276,9 +255,9 @@ static const luaL_reg GEO_FUNCTIONS[] = { static Region *checkRegion(lua_State *L) { // The first parameter must be of type 'userdata', and the Metatable class Geo.Region or Geo.WalkRegion - uint *regionHandlePtr; - if ((regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, REGION_CLASS_NAME))) != 0 || - (regionHandlePtr = reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) { + uint *regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, REGION_CLASS_NAME)); + if (regionHandlePtr != 0 || + (regionHandlePtr = reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) { return RegionRegistry::instance().resolveHandle(*regionHandlePtr); } else { luaL_argcheck(L, 0, 1, "'" REGION_CLASS_NAME "' expected"); @@ -398,7 +377,7 @@ static const luaL_reg REGION_METHODS[] = { static WalkRegion *checkWalkRegion(lua_State *L) { // The first parameter must be of type 'userdate', and the Metatable class Geo.WalkRegion uint regionHandle; - if ((regionHandle = *reinterpret_cast<uint *>(my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) { + if ((regionHandle = *reinterpret_cast<uint *>(LuaBindhelper::my_checkudata(L, 1, WALKREGION_CLASS_NAME))) != 0) { return reinterpret_cast<WalkRegion *>(RegionRegistry::instance().resolveHandle(regionHandle)); } else { luaL_argcheck(L, 0, 1, "'" WALKREGION_CLASS_NAME "' expected"); diff --git a/engines/sword25/script/luabindhelper.cpp b/engines/sword25/script/luabindhelper.cpp index 5ff9708b95..03a1802a04 100644 --- a/engines/sword25/script/luabindhelper.cpp +++ b/engines/sword25/script/luabindhelper.cpp @@ -303,6 +303,27 @@ bool LuaBindhelper::getMetatable(lua_State *L, const Common::String &tableName) return true; } +// Like luaL_checkudata, only without that no error is generated. +void *LuaBindhelper::my_checkudata(lua_State *L, int ud, const char *tname) { + int top = lua_gettop(L); + + void *p = lua_touserdata(L, ud); + if (p != NULL) { /* value is a userdata? */ + if (lua_getmetatable(L, ud)) { /* does it have a metatable? */ + // lua_getfield(L, LUA_REGISTRYINDEX, tname); /* get correct metatable */ + LuaBindhelper::getMetatable(L, tname); + if (lua_rawequal(L, -1, -2)) { /* does it have the correct mt? */ + lua_settop(L, top); + return p; + } + } + } + + lua_settop(L, top); + return NULL; +} + + bool LuaBindhelper::createTable(lua_State *L, const Common::String &tableName) { const char *partBegin = tableName.c_str(); diff --git a/engines/sword25/script/luabindhelper.h b/engines/sword25/script/luabindhelper.h index dc45104d53..94f52743f3 100644 --- a/engines/sword25/script/luabindhelper.h +++ b/engines/sword25/script/luabindhelper.h @@ -110,6 +110,8 @@ public: static bool getMetatable(lua_State *L, const Common::String &tableName); + static void *my_checkudata(lua_State *L, int ud, const char *tname); + private: static bool createTable(lua_State *L, const Common::String &tableName); }; diff --git a/engines/sword25/sword25.cpp b/engines/sword25/sword25.cpp index 55b9aa340d..aac21f4b55 100644 --- a/engines/sword25/sword25.cpp +++ b/engines/sword25/sword25.cpp @@ -56,6 +56,8 @@ const char *const DEFAULT_SCRIPT_FILE = "/system/boot.lua"; Sword25Engine::Sword25Engine(OSystem *syst, const ADGameDescription *gameDesc): Engine(syst), _gameDescription(gameDesc) { + // Setup mixer + syncSoundSettings(); DebugMan.addDebugChannel(kDebugScript, "Script", "Script debug level"); DebugMan.addDebugChannel(kDebugScript, "Scripts", "Script debug level"); diff --git a/engines/sword25/util/lua/lmathlib.cpp b/engines/sword25/util/lua/lmathlib.cpp index bb9c6ed442..7e64d75789 100644 --- a/engines/sword25/util/lua/lmathlib.cpp +++ b/engines/sword25/util/lua/lmathlib.cpp @@ -6,6 +6,11 @@ #include <stdlib.h> +// MSVC does not define M_PI, M_SQRT2 and other math defines by default. +// _USE_MATH_DEFINES must be defined in order to have these defined, thus +// we enable it here. For more information, check: +// http://msdn.microsoft.com/en-us/library/4hwaceh6(v=VS.100).aspx +#define _USE_MATH_DEFINES #include <math.h> #define lmathlib_c diff --git a/engines/touche/touche.cpp b/engines/touche/touche.cpp index 97d533f29f..6b47a7fc4d 100644 --- a/engines/touche/touche.cpp +++ b/engines/touche/touche.cpp @@ -44,7 +44,6 @@ namespace Touche { ToucheEngine::ToucheEngine(OSystem *system, Common::Language language) : Engine(system), _midiPlayer(0), _language(language) { - _saveLoadCurrentPage = 0; _saveLoadCurrentSlot = 0; _hideInventoryTexts = false; @@ -103,9 +102,8 @@ Common::Error ToucheEngine::run() { _midiPlayer = new MidiPlayer; - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); + // Setup mixer + syncSoundSettings(); res_openDataFile(); res_allocateTables(); @@ -245,10 +243,9 @@ Common::Point ToucheEngine::getMousePos() const { } void ToucheEngine::syncSoundSettings() { + Engine::syncSoundSettings(); + readConfigurationSettings(); - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); } void ToucheEngine::mainLoop() { diff --git a/engines/tucker/detection.cpp b/engines/tucker/detection.cpp index f0437d2f87..7404abc2e7 100644 --- a/engines/tucker/detection.cpp +++ b/engines/tucker/detection.cpp @@ -122,8 +122,8 @@ static const ADParams detectionParams = { 0, // Flags 0, - // Additional GUI options (for every game} - Common::GUIO_NOLAUNCHLOAD, + // Additional GUI options (for every game) + Common::GUIO_NONE, // Maximum directory depth 1, // List of directory globs @@ -156,6 +156,7 @@ public: virtual bool hasFeature(MetaEngineFeature f) const { switch (f) { case kSupportsListSaves: + case kSupportsLoadingDuringStartup: case kSupportsDeleteSave: return true; default: diff --git a/engines/tucker/tucker.cpp b/engines/tucker/tucker.cpp index 6e44eadc47..e41cbfbeef 100644 --- a/engines/tucker/tucker.cpp +++ b/engines/tucker/tucker.cpp @@ -68,12 +68,6 @@ Common::Error TuckerEngine::run() { return Common::kNoError; } -void TuckerEngine::syncSoundSettings() { - _mixer->setVolumeForSoundType(Audio::Mixer::kSFXSoundType, ConfMan.getInt("sfx_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kSpeechSoundType, ConfMan.getInt("speech_volume")); - _mixer->setVolumeForSoundType(Audio::Mixer::kMusicSoundType, ConfMan.getInt("music_volume")); -} - int TuckerEngine::getRandomNumber() { return _rnd.getRandomNumber(0x7FFF); } @@ -130,10 +124,7 @@ void TuckerEngine::restart() { _timerCounter2 = 0; _partNum = _currentPartNum = 0; _locationNum = 0; - _nextLocationNum = ConfMan.getInt("boot_param"); - if (_nextLocationNum == 0) { - _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo; - } + _nextLocationNum = (_gameFlags & kGameFlagDemo) == 0 ? kStartupLocationGame : kStartupLocationDemo; _gamePaused = false; _gameDebug = false; _displayGameHints = false; @@ -359,6 +350,15 @@ void TuckerEngine::mainLoop() { _spriteAnimationFrameIndex = _spriteAnimationsTable[14].firstFrameIndex; + if (ConfMan.hasKey("save_slot")) { + const int slot = ConfMan.getInt("save_slot"); + if (slot >= 0 && slot <= kLastSaveSlot) { + loadGameState(slot); + } + } else if (ConfMan.hasKey("boot_param")) { + _nextLocationNum = ConfMan.getInt("boot_param"); + } + do { ++_syncCounter; if (_flagsTable[137] != _flagsTable[138]) { diff --git a/engines/tucker/tucker.h b/engines/tucker/tucker.h index fd931998e4..532892fd48 100644 --- a/engines/tucker/tucker.h +++ b/engines/tucker/tucker.h @@ -280,7 +280,6 @@ public: virtual Common::Error run(); virtual bool hasFeature(EngineFeature f) const; - virtual void syncSoundSettings(); GUI::Debugger *getDebugger() { return _console; } protected: |