[Scummvm-cvs-logs] scummvm master -> 712af61f76148095cd3b8762eeb2b2b10502df1f
Littleboy
littleboy22 at gmail.com
Thu Jun 23 15:00:01 CEST 2011
This automated email contains information about 4 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
f0cf72f431 LASTEXPRESS: Move Menu class to a separate folder
7a96e0bfb6 LASTEXPRESS: Extract Clock and TrainLine classes to separate files
b694a78f62 ANALYSIS: Add static casts to is* functions
712af61f76 BACKENDS: Silence warnings when compiling Win32TaskbarManager with mingw and add CLSID_ShellLink definition
Commit: f0cf72f4313c146dcec25fa004312a4319b89b91
https://github.com/scummvm/scummvm/commit/f0cf72f4313c146dcec25fa004312a4319b89b91
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-23T03:58:21-07:00
Commit Message:
LASTEXPRESS: Move Menu class to a separate folder
Changed paths:
A engines/lastexpress/menu/menu.cpp
A engines/lastexpress/menu/menu.h
R engines/lastexpress/game/menu.cpp
R engines/lastexpress/game/menu.h
engines/lastexpress/entities/chapters.cpp
engines/lastexpress/game/inventory.cpp
engines/lastexpress/game/logic.cpp
engines/lastexpress/game/savegame.cpp
engines/lastexpress/lastexpress.cpp
engines/lastexpress/module.mk
diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp
index 1252a62..6a41590 100644
--- a/engines/lastexpress/entities/chapters.cpp
+++ b/engines/lastexpress/entities/chapters.cpp
@@ -57,13 +57,14 @@
#include "lastexpress/game/entities.h"
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/scenes.h"
#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/resource.h"
diff --git a/engines/lastexpress/game/inventory.cpp b/engines/lastexpress/game/inventory.cpp
index adf6ff7..07ad8d9 100644
--- a/engines/lastexpress/game/inventory.cpp
+++ b/engines/lastexpress/game/inventory.cpp
@@ -27,11 +27,12 @@
#include "lastexpress/data/snd.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/scenes.h"
#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
diff --git a/engines/lastexpress/game/logic.cpp b/engines/lastexpress/game/logic.cpp
index a8a2ce8..3bd7d6d 100644
--- a/engines/lastexpress/game/logic.cpp
+++ b/engines/lastexpress/game/logic.cpp
@@ -38,7 +38,6 @@
#include "lastexpress/game/beetle.h"
#include "lastexpress/game/entities.h"
#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savegame.h"
#include "lastexpress/game/savepoint.h"
@@ -46,6 +45,8 @@
#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
diff --git a/engines/lastexpress/game/menu.cpp b/engines/lastexpress/game/menu.cpp
deleted file mode 100644
index 27a43d8..0000000
--- a/engines/lastexpress/game/menu.cpp
+++ /dev/null
@@ -1,1542 +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.
- *
- */
-
-#include "lastexpress/game/menu.h"
-
-// Data
-#include "lastexpress/data/animation.h"
-#include "lastexpress/data/cursor.h"
-#include "lastexpress/data/snd.h"
-#include "lastexpress/data/scene.h"
-
-#include "lastexpress/fight/fight.h"
-
-#include "lastexpress/game/inventory.h"
-#include "lastexpress/game/logic.h"
-#include "lastexpress/game/savegame.h"
-#include "lastexpress/game/savepoint.h"
-#include "lastexpress/game/scenes.h"
-#include "lastexpress/game/sound.h"
-#include "lastexpress/game/state.h"
-
-#include "lastexpress/graphics.h"
-#include "lastexpress/helpers.h"
-#include "lastexpress/lastexpress.h"
-#include "lastexpress/resource.h"
-
-#include "common/rational.h"
-
-#define getNextGameId() (GameId)((_gameId + 1) % 6)
-
-namespace LastExpress {
-
-// Bottom-left buttons (quit.seq)
-enum StartMenuButtons {
- kButtonVolumeDownPushed,
- kButtonVolumeDown,
- kButtonVolume,
- kButtonVolumeUp,
- kButtonVolumeUpPushed,
- kButtonBrightnessDownPushed, // 5
- kButtonBrightnessDown,
- kButtonBrightness,
- kButtonBrightnessUp,
- kButtonBrightnessUpPushed,
- kButtonQuit, // 10
- kButtonQuitPushed
-};
-
-// Egg buttons (buttns.seq)
-enum StartMenuEggButtons {
- kButtonShield,
- kButtonRewind,
- kButtonRewindPushed,
- kButtonForward,
- kButtonForwardPushed,
- kButtonCredits, // 5
- kButtonCreditsPushed,
- kButtonContinue
-};
-
-// Tooltips sequence (helpnewr.seq)
-enum StartMenuTooltips {
- kTooltipInsertCd1,
- kTooltipInsertCd2,
- kTooltipInsertCd3,
- kTooltipContinueGame,
- kTooltipReplayGame,
- kTooltipContinueRewoundGame, // 5
- kTooltipViewGameEnding,
- kTooltipStartAnotherGame,
- kTooltipVolumeUp,
- kTooltipVolumeDown,
- kTooltipBrightnessUp, // 10
- kTooltipBrightnessDown,
- kTooltipQuit,
- kTooltipRewindParis,
- kTooltipForwardStrasbourg,
- kTooltipRewindStrasbourg, // 15
- kTooltipRewindMunich,
- kTooltipForwardMunich,
- kTooltipForwardVienna,
- kTooltipRewindVienna,
- kTooltipRewindBudapest, // 20
- kTooltipForwardBudapest,
- kTooltipForwardBelgrade,
- kTooltipRewindBelgrade,
- kTooltipForwardConstantinople,
- kTooltipSwitchBlueGame, // 25
- kTooltipSwitchRedGame,
- kTooltipSwitchGoldGame,
- kTooltipSwitchGreenGame,
- kTooltipSwitchTealGame,
- kTooltipSwitchPurpleGame, // 30
- kTooltipPlayNewGame,
- kTooltipCredits,
- kTooltipFastForward,
- kTooltipRewind
-};
-
-//////////////////////////////////////////////////////////////////////////
-// DATA
-//////////////////////////////////////////////////////////////////////////
-
-// Information about the cities on the train line
-static const struct {
- uint8 frame;
- TimeValue time;
-} _trainCities[31] = {
- {0, kTimeCityParis},
- {9, kTimeCityEpernay},
- {11, kTimeCityChalons},
- {16, kTimeCityBarLeDuc},
- {21, kTimeCityNancy},
- {25, kTimeCityLuneville},
- {35, kTimeCityAvricourt},
- {37, kTimeCityDeutschAvricourt},
- {40, kTimeCityStrasbourg},
- {53, kTimeCityBadenOos},
- {56, kTimeCityKarlsruhe},
- {60, kTimeCityStuttgart},
- {63, kTimeCityGeislingen},
- {66, kTimeCityUlm},
- {68, kTimeCityAugsburg},
- {73, kTimeCityMunich},
- {84, kTimeCitySalzbourg},
- {89, kTimeCityAttnangPuchheim},
- {97, kTimeCityWels},
- {100, kTimeCityLinz},
- {104, kTimeCityAmstetten},
- {111, kTimeCityVienna},
- {120, kTimeCityPoszony},
- {124, kTimeCityGalanta},
- {132, kTimeCityBudapest},
- {148, kTimeCityBelgrade},
- /* Line 1 ends at 150 - line 2 begins at 0 */
- {157, kTimeCityNish},
- {165, kTimeCityTzaribrod},
- {174, kTimeCitySofia},
- {198, kTimeCityAdrianople},
- {210, kTimeCityConstantinople}};
-
-static const struct {
- TimeValue time;
- uint index;
- StartMenuTooltips rewind;
- StartMenuTooltips forward;
-} _cityButtonsInfo[7] = {
- {kTimeCityParis, 64, kTooltipRewindParis, kTooltipRewindParis},
- {kTimeCityStrasbourg, 128, kTooltipRewindStrasbourg, kTooltipForwardStrasbourg},
- {kTimeCityMunich, 129, kTooltipRewindMunich, kTooltipForwardMunich},
- {kTimeCityVienna, 130, kTooltipRewindVienna, kTooltipForwardVienna},
- {kTimeCityBudapest, 131, kTooltipRewindBudapest, kTooltipForwardBudapest},
- {kTimeCityBelgrade, 132, kTooltipRewindBelgrade, kTooltipForwardBelgrade},
- {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople}
-};
-
-//////////////////////////////////////////////////////////////////////////
-// Clock
-//////////////////////////////////////////////////////////////////////////
-class Clock {
-public:
- explicit Clock(LastExpressEngine *engine);
- ~Clock();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameMinutes;
- SequenceFrame *_frameHour;
- SequenceFrame *_frameSun;
- SequenceFrame *_frameDate;
-};
-
-Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) {
- _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
- _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
- _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
- _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
-}
-
-Clock::~Clock() {
- SAFE_DELETE(_frameMinutes);
- SAFE_DELETE(_frameHour);
- SAFE_DELETE(_frameSun);
- SAFE_DELETE(_frameDate);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void Clock::clear() {
- getScenes()->removeFromQueue(_frameMinutes);
- getScenes()->removeFromQueue(_frameHour);
- getScenes()->removeFromQueue(_frameSun);
- getScenes()->removeFromQueue(_frameDate);
-}
-
-void Clock::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
- error("Clock::process: clock sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914
- // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914
- // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins
-
- // 15 = 1 second
- // 15 * 60 = 900 = 1 minute
- // 900 * 60 = 54000 = 1 hour
- // 54000 * 24 = 1296000 = 1 day
-
- // Calculate each sequence index from the current time
-
- uint8 hour = 0;
- uint8 minute = 0;
- State::getHourMinutes(time, &hour, &minute);
- uint32 index_date = 18 * time / 1296000;
- if (hour == 23)
- index_date += 18 * minute / 60;
-
- // Set sequences frames
- _frameMinutes->setFrame(minute);
- _frameHour->setFrame((5 * hour + minute / 12) % 60);
- _frameSun->setFrame((5 * hour + minute / 12) % 120);
- _frameDate->setFrame((uint16)index_date);
-
- // Adjust z-order and queue
- _frameMinutes->getInfo()->location = 1;
- _frameHour->getInfo()->location = 1;
- _frameSun->getInfo()->location = 1;
- _frameDate->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameMinutes);
- getScenes()->addToQueue(_frameHour);
- getScenes()->addToQueue(_frameSun);
- getScenes()->addToQueue(_frameDate);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// TrainLine
-//////////////////////////////////////////////////////////////////////////
-class TrainLine {
-public:
- explicit TrainLine(LastExpressEngine *engine);
- ~TrainLine();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameLine1;
- SequenceFrame *_frameLine2;
-};
-
-TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) {
- _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true);
- _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true);
-}
-
-TrainLine::~TrainLine() {
- SAFE_DELETE(_frameLine1);
- SAFE_DELETE(_frameLine2);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void TrainLine::clear() {
- getScenes()->removeFromQueue(_frameLine1);
- getScenes()->removeFromQueue(_frameLine2);
-}
-
-// Draw the train line at the time
-// line1: 150 frames (=> Belgrade)
-// line2: 61 frames (=> Constantinople)
-void TrainLine::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameLine1 || !_frameLine2)
- error("TrainLine::process: Line sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Get the index of the last city the train has visited
- uint index = 0;
- for (uint i = 0; i < ARRAYSIZE(_trainCities); i++)
- if ((uint32)_trainCities[i].time <= time)
- index = i;
-
- uint16 frame;
- if (time > (uint32)_trainCities[index].time) {
- // Interpolate linearly to use a frame between the cities
- uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame;
- uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time);
- uint traveledTime = (time - (uint)_trainCities[index].time);
- frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities);
- } else {
- // Exactly on the city
- frame = _trainCities[index].frame;
- }
-
- // Set frame, z-order and queue
- if (frame < 150) {
- _frameLine1->setFrame(frame);
-
- _frameLine1->getInfo()->location = 1;
- getScenes()->addToQueue(_frameLine1);
- } else {
- // We passed Belgrade
- _frameLine1->setFrame(149);
- _frameLine2->setFrame(frame - 150);
-
- _frameLine1->getInfo()->location = 1;
- _frameLine2->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameLine1);
- getScenes()->addToQueue(_frameLine2);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
-// Menu
-//////////////////////////////////////////////////////////////////////////
-Menu::Menu(LastExpressEngine *engine) : _engine(engine),
- _seqTooltips(NULL), _seqEggButtons(NULL), _seqButtons(NULL), _seqAcorn(NULL), _seqCity1(NULL), _seqCity2(NULL), _seqCity3(NULL), _seqCredits(NULL),
- _gameId(kGameBlue), _hasShownStartScreen(false), _hasShownIntro(false),
- _isShowingCredits(false), _isGameStarted(false), _isShowingMenu(false),
- _creditsSequenceIndex(0), _checkHotspotsTicks(15), _mouseFlags(Common::EVENT_INVALID), _lastHotspot(NULL),
- _currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) {
-
- _clock = new Clock(_engine);
- _trainLine = new TrainLine(_engine);
-}
-
-Menu::~Menu() {
- SAFE_DELETE(_clock);
- SAFE_DELETE(_trainLine);
-
- SAFE_DELETE(_seqTooltips);
- SAFE_DELETE(_seqEggButtons);
- SAFE_DELETE(_seqButtons);
- SAFE_DELETE(_seqAcorn);
- SAFE_DELETE(_seqCity1);
- SAFE_DELETE(_seqCity2);
- SAFE_DELETE(_seqCity3);
- SAFE_DELETE(_seqCredits);
-
- _lastHotspot = NULL;
-
- // Cleanup frames
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- SAFE_DELETE(it->_value);
-
- _frames.clear();
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Setup
-void Menu::setup() {
-
- // Clear drawing queue
- getScenes()->removeAndRedraw(&_frames[kOverlayAcorn], false);
- SAFE_DELETE(_seqAcorn);
-
- // Load Menu scene
- // + 1 = normal menu with open egg / clock
- // + 2 = shield menu, when no savegame exists (no game has been started)
- _isGameStarted = _lowerTime >= kTimeStartGame;
- getScenes()->loadScene((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2));
- getFlags()->shouldRedraw = true;
- getLogic()->updateCursor();
-
- //////////////////////////////////////////////////////////////////////////
- // Load Acorn sequence
- _seqAcorn = loadSequence(getAcornSequenceName(_isGameStarted ? getNextGameId() : kGameBlue));
-
- //////////////////////////////////////////////////////////////////////////
- // Check if we loaded sequences before
- if (_seqTooltips && _seqTooltips->count() > 0)
- return;
-
- // Load all static data
- _seqTooltips = loadSequence("helpnewr.seq");
- _seqEggButtons = loadSequence("buttns.seq");
- _seqButtons = loadSequence("quit.seq");
- _seqCity1 = loadSequence("jlinetl.seq");
- _seqCity2 = loadSequence("jlinecen.seq");
- _seqCity3 = loadSequence("jlinebr.seq");
- _seqCredits = loadSequence("credits.seq");
-
- _frames[kOverlayTooltip] = new SequenceFrame(_seqTooltips);
- _frames[kOverlayEggButtons] = new SequenceFrame(_seqEggButtons);
- _frames[kOverlayButtons] = new SequenceFrame(_seqButtons);
- _frames[kOverlayAcorn] = new SequenceFrame(_seqAcorn);
- _frames[kOverlayCity1] = new SequenceFrame(_seqCity1);
- _frames[kOverlayCity2] = new SequenceFrame(_seqCity2);
- _frames[kOverlayCity3] = new SequenceFrame(_seqCity3);
- _frames[kOverlayCredits] = new SequenceFrame(_seqCredits);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Handle events
-void Menu::eventMouse(const Common::Event &ev) {
- if (!getFlags()->shouldRedraw)
- return;
-
- bool redraw = true;
- getFlags()->shouldRedraw = false;
-
- // Update coordinates
- setCoords(ev.mouse);
- //_mouseFlags = (Common::EventType)(ev.type & Common::EVENT_LBUTTONUP);
-
- if (_isShowingCredits) {
- if (ev.type == Common::EVENT_RBUTTONUP) {
- showFrame(kOverlayCredits, -1, true);
- _isShowingCredits = false;
- }
-
- if (ev.type == Common::EVENT_LBUTTONUP) {
- // Last frame of the credits
- if (_seqCredits && _creditsSequenceIndex == _seqCredits->count() - 1) {
- showFrame(kOverlayCredits, -1, true);
- _isShowingCredits = false;
- } else {
- ++_creditsSequenceIndex;
- showFrame(kOverlayCredits, _creditsSequenceIndex, true);
- }
- }
- } else {
- // Check for hotspots
- SceneHotspot *hotspot = NULL;
- getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot);
-
- if (_lastHotspot != hotspot || ev.type == Common::EVENT_LBUTTONUP) {
- _lastHotspot = hotspot;
-
- if (ev.type == Common::EVENT_MOUSEMOVE) { /* todo check event type */
- if (!_handleTimeDelta && hasTimeDelta())
- setTime();
- }
-
- if (hotspot) {
- redraw = handleEvent((StartMenuAction)hotspot->action, ev.type);
- getFlags()->mouseRightClick = false;
- getFlags()->mouseLeftClick = false;
- } else {
- hideOverlays();
- }
- }
- }
-
- if (redraw) {
- getFlags()->shouldRedraw = true;
- askForRedraw();
- }
-}
-
-void Menu::eventTick(const Common::Event&) {
- if (hasTimeDelta())
- adjustTime();
- else if (_handleTimeDelta)
- _handleTimeDelta = false;
-
- // Check hotspots
- if (!--_checkHotspotsTicks) {
- checkHotspots();
- _checkHotspotsTicks = 15;
- }
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Show the intro and load the main menu scene
-void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
-
- if (_isShowingMenu)
- return;
-
- _isShowingMenu = true;
- getEntities()->reset();
-
- // If no blue savegame exists, this might be the first time we start the game, so we show the full intro
- if (!getFlags()->mouseRightClick) {
- if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
-
- if (!_hasShownIntro) {
- // Show Broderbrund logo
- Animation animation;
- if (animation.load(getArchive("1930.nis")))
- animation.play();
-
- getFlags()->mouseRightClick = false;
-
- // Play intro music
- getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer);
-
- // Show The Smoking Car logo
- if (animation.load(getArchive("1931.nis")))
- animation.play();
-
- _hasShownIntro = true;
- }
- } else {
- // Only show the quick intro
- if (!_hasShownStartScreen) {
- getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer);
- getScenes()->loadScene(kSceneStartScreen);
-
- // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed
- uint32 nextFrameCount = getFrameCount() + 60;
- while (getFrameCount() < nextFrameCount) {
- _engine->pollEvents();
-
- if (getFlags()->mouseRightClick)
- break;
-
- getSound()->updateQueue();
- }
- }
- }
- }
-
- _hasShownStartScreen = true;
-
- // Init Menu
- init(doSavegame, type, value);
-
- // Setup sound
- getSound()->unknownFunction4();
- getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13);
- if (getSound()->isBuffered("TIMER"))
- getSound()->removeFromQueue("TIMER");
-
- // Init flags & misc
- _isShowingCredits = false;
- _handleTimeDelta = hasTimeDelta();
- getInventory()->unselectItem();
-
- // Set Cursor type
- _engine->getCursor()->setStyle(kCursorNormal);
- _engine->getCursor()->show(true);
-
- setup();
- checkHotspots();
-
- // Set event handlers
- SET_EVENT_HANDLERS(Menu, this);
-}
-
-bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
- bool clicked = (type == Common::EVENT_LBUTTONUP);
-
- switch(action) {
- default:
- hideOverlays();
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuCredits:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- showFrame(kOverlayEggButtons, kButtonCreditsPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- hideOverlays();
-
- _isShowingCredits = true;
- _creditsSequenceIndex = 0;
-
- showFrame(kOverlayCredits, 0, true);
- } else {
- // TODO check flags ?
-
- showFrame(kOverlayEggButtons, kButtonCredits, true);
- showFrame(kOverlayTooltip, kTooltipCredits, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuQuitGame:
- showFrame(kOverlayTooltip, kTooltipQuit, true);
-
- if (clicked) {
- showFrame(kOverlayButtons, kButtonQuitPushed, true);
-
- getSound()->clearStatus();
- getSound()->updateQueue();
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- // FIXME uncomment when sound queue is properly implemented
- /*while (getSound()->isBuffered("LIB046"))
- getSound()->updateQueue();*/
-
- getFlags()->shouldRedraw = false;
-
- Engine::quitGame();
-
- return false;
- } else {
- showFrame(kOverlayButtons, kButtonQuit, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuCase4:
- if (clicked)
- _index = 0;
- // fall down to kMenuContinue
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuContinue: {
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Determine the proper CD archive
- ArchiveIndex cd = kArchiveCd1;
- if (getProgress().chapter > kChapter1)
- cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2;
-
- // Show tooltips & buttons to start a game, continue a game or load the proper cd
- if (ResourceManager::isArchivePresent(cd)) {
- if (_isGameStarted) {
- showFrame(kOverlayEggButtons, kButtonContinue, true);
-
- if (_lastIndex == _index) {
- showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true);
- } else {
- showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true);
- }
-
- } else {
- showFrame(kOverlayEggButtons, kButtonShield, true);
- showFrame(kOverlayTooltip, kTooltipPlayNewGame, true);
- }
- } else {
- showFrame(kOverlayEggButtons, -1, true);
- showFrame(kOverlayTooltip, cd - 1, true);
- }
-
- if (!clicked)
- break;
-
- // Try loading the archive file
- if (!_engine->getResourceManager()->loadArchive(cd))
- break;
-
- // Load the train data file and setup game
- getScenes()->loadSceneDataFile(cd);
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- // Setup new game
- getSavePoints()->reset();
- setLogicEventHandlers();
-
- if (_index) {
- getSound()->processEntry(SoundManager::kSoundType11);
- } else {
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 3));
-
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 4));
-
- if (!getFlags()->mouseRightClick) {
- getScenes()->loadScene((SceneIndex)(5 * _gameId + 5));
-
- if (!getFlags()->mouseRightClick) {
- getSound()->processEntry(SoundManager::kSoundType11);
-
- // Show intro
- Animation animation;
- if (animation.load(getArchive("1601.nis")))
- animation.play();
-
- getEvent(kEventIntro) = 1;
- }
- }
- }
- }
-
- if (!getEvent(kEventIntro)) {
- getEvent(kEventIntro) = 1;
-
- getSound()->processEntry(SoundManager::kSoundType11);
- }
- }
-
- // Setup game
- getFlags()->isGameRunning = true;
- startGame();
-
- if (!_isShowingMenu)
- getInventory()->show();
-
- return false;
- }
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuSwitchSaveGame:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- showFrame(kOverlayAcorn, 1, true);
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB047");
-
- // Setup new menu screen
- switchGame();
- setup();
-
- // Set fight state to 0
- getFight()->resetState();
-
- return true;
- }
-
- // TODO Check for flag
-
- showFrame(kOverlayAcorn, 0, true);
-
- if (_isGameStarted) {
- showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
- break;
- }
-
- if (_gameId == kGameGold) {
- showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
- break;
- }
-
- if (!SaveLoad::isSavegameValid(getNextGameId())) {
- showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
- break;
- }
-
- // Stupid tooltips ids are not in order, so we can't just increment them...
- switch(_gameId) {
- default:
- break;
-
- case kGameBlue:
- showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true);
- break;
-
- case kGameRed:
- showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true);
- break;
-
- case kGameGreen:
- showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true);
- break;
-
- case kGamePurple:
- showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true);
- break;
-
- case kGameTeal:
- showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true);
- break;
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuRewindGame:
- if (!_index || _currentTime < _time) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- if (hasTimeDelta())
- _handleTimeDelta = false;
-
- showFrame(kOverlayEggButtons, kButtonRewindPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- rewindTime();
-
- _handleTimeDelta = false;
- } else {
- showFrame(kOverlayEggButtons, kButtonRewind, true);
- showFrame(kOverlayTooltip, kTooltipRewind, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuForwardGame:
- if (_lastIndex <= _index || _currentTime > _time) {
- hideOverlays();
- break;
- }
-
- if (clicked) {
- if (hasTimeDelta())
- _handleTimeDelta = false;
-
- showFrame(kOverlayEggButtons, kButtonForwardPushed, true);
- showFrame(kOverlayTooltip, -1, true);
-
- getSound()->playSound(kEntityPlayer, "LIB046");
-
- forwardTime();
-
- _handleTimeDelta = false;
- } else {
- showFrame(kOverlayEggButtons, kButtonForward, true);
- showFrame(kOverlayTooltip, kTooltipFastForward, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuParis:
- moveToCity(kParis, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuStrasBourg:
- moveToCity(kStrasbourg, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuMunich:
- moveToCity(kMunich, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuVienna:
- moveToCity(kVienna, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuBudapest:
- moveToCity(kBudapest, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuBelgrade:
- moveToCity(kBelgrade, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuConstantinople:
- moveToCity(kConstantinople, clicked);
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuDecreaseVolume:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot decrease volume further
- if (getVolume() == 0) {
- showFrame(kOverlayButtons, kButtonVolume, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipVolumeDown, true);
-
- // Show highlight on button & adjust volume if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonVolumeDownPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setVolume(getVolume() - 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- uint32 nextFrameCount = getFrameCount() + 15;
- while (nextFrameCount > getFrameCount()) {
- _engine->pollEvents();
-
- getSound()->updateQueue();
- }
- } else {
- showFrame(kOverlayButtons, kButtonVolumeDown, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuIncreaseVolume:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase volume further
- if (getVolume() >= 7) {
- showFrame(kOverlayButtons, kButtonVolume, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipVolumeUp, true);
-
- // Show highlight on button & adjust volume if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonVolumeUpPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setVolume(getVolume() + 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- uint32 nextFrameCount = getFrameCount() + 15;
- while (nextFrameCount > getFrameCount()) {
- _engine->pollEvents();
-
- getSound()->updateQueue();
- }
- } else {
- showFrame(kOverlayButtons, kButtonVolumeUp, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuDecreaseBrightness:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase brightness further
- if (getBrightness() == 0) {
- showFrame(kOverlayButtons, kButtonBrightness, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipBrightnessDown, true);
-
- // Show highlight on button & adjust brightness if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setBrightness(getBrightness() - 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
- _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
- showFrame(kOverlayTooltip, kTooltipBrightnessDown, false);
- showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false);
- } else {
- showFrame(kOverlayButtons, kButtonBrightnessDown, true);
- }
- break;
-
- //////////////////////////////////////////////////////////////////////////
- case kMenuIncreaseBrightness:
- if (hasTimeDelta()) {
- hideOverlays();
- break;
- }
-
- // Cannot increase brightness further
- if (getBrightness() >= 6) {
- showFrame(kOverlayButtons, kButtonBrightness, true);
- showFrame(kOverlayTooltip, -1, true);
- break;
- }
-
- showFrame(kOverlayTooltip, kTooltipBrightnessUp, true);
-
- // Show highlight on button & adjust brightness if needed
- if (clicked) {
- showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- setBrightness(getBrightness() + 1);
-
- getSaveLoad()->saveVolumeBrightness();
-
- // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
- _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
- showFrame(kOverlayTooltip, kTooltipBrightnessUp, false);
- showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false);
- } else {
- showFrame(kOverlayButtons, kButtonBrightnessUp, true);
- }
- break;
- }
-
- return true;
-}
-
-void Menu::setLogicEventHandlers() {
- SET_EVENT_HANDLERS(Logic, getLogic());
- clear();
- _isShowingMenu = false;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Game-related
-//////////////////////////////////////////////////////////////////////////
-void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
-
- bool useSameIndex = true;
-
- if (getGlobalTimer()) {
- value = 0;
-
- // Check if the CD file is present
- ArchiveIndex index = kArchiveCd1;
- switch (getProgress().chapter) {
- default:
- case kChapter1:
- break;
-
- case kChapter2:
- case kChapter3:
- index = kArchiveCd2;
- break;
-
- case kChapter4:
- case kChapter5:
- index = kArchiveCd3;
- break;
- }
-
- if (ResourceManager::isArchivePresent(index)) {
- setGlobalTimer(0);
- useSameIndex = false;
-
- // TODO remove existing savegame and reset index & savegame name
- warning("Menu::initGame: not implemented!");
- }
-
- doSavegame = false;
- } else {
- // TODO rename saves?
- }
-
- // Create a new savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
-
- if (doSavegame)
- getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone);
-
- if (!getGlobalTimer()) {
- // TODO: remove existing savegame temp file
- }
-
- // Init savegame & menu values
- _lastIndex = getSaveLoad()->init(_gameId, true);
- _lowerTime = getSaveLoad()->getTime(_lastIndex);
-
- if (useSameIndex)
- _index = _lastIndex;
-
- //if (!getGlobalTimer())
- // _index3 = 0;
-
- if (!getProgress().chapter)
- getProgress().chapter = kChapter1;
-
- getState()->time = (TimeValue)getSaveLoad()->getTime(_index);
- getProgress().chapter = getSaveLoad()->getChapter(_index);
-
- if (_lowerTime >= kTimeStartGame) {
- _currentTime = (uint32)getState()->time;
- _time = (uint32)getState()->time;
- _clock->draw(_time);
- _trainLine->draw(_time);
-
- initTime(type, value);
- }
-}
-
-// Start a game (or load an existing savegame)
-void Menu::startGame() {
- // Clear savegame headers
- getSaveLoad()->clear();
-
- // Hide menu elements
- _clock->clear();
- _trainLine->clear();
-
- if (_lastIndex == _index) {
- setGlobalTimer(0);
- if (_index) {
- getSaveLoad()->loadGame(_gameId);
- } else {
- getLogic()->resetState();
- getEntities()->setup(true, kEntityPlayer);
- }
- } else {
- getSaveLoad()->loadGame(_gameId, _index);
- }
-}
-
-// Switch to the next savegame
-void Menu::switchGame() {
-
- // Switch back to blue game is the current game is not started
- _gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue;
-
- // Initialize savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
-
- getState()->time = kTimeNone;
-
- // Clear menu elements
- _clock->clear();
- _trainLine->clear();
-
- // Clear loaded savegame data
- getSaveLoad()->clear(true);
-
- init(false, kSavegameTypeIndex, 0);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Overlays & elements
-//////////////////////////////////////////////////////////////////////////
-void Menu::checkHotspots() {
- if (!_isShowingMenu)
- return;
-
- if (!getFlags()->shouldRedraw)
- return;
-
- if (_isShowingCredits)
- return;
-
- SceneHotspot *hotspot = NULL;
- getScenes()->get(getState()->scene)->checkHotSpot(getCoords(), &hotspot);
-
- if (hotspot)
- handleEvent((StartMenuAction)hotspot->action, _mouseFlags);
- else
- hideOverlays();
-}
-
-void Menu::hideOverlays() {
- _lastHotspot = NULL;
-
- // Hide all menu overlays
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- showFrame(it->_key, -1, false);
-
- getScenes()->drawFrames(true);
-}
-
-void Menu::showFrame(StartMenuOverlay overlayType, int index, bool redraw) {
- if (index == -1) {
- getScenes()->removeFromQueue(_frames[overlayType]);
- } else {
- // Check that the overlay is valid
- if (!_frames[overlayType])
- return;
-
- // Remove the frame and add a new one with the proper index
- getScenes()->removeFromQueue(_frames[overlayType]);
- _frames[overlayType]->setFrame((uint16)index);
- getScenes()->addToQueue(_frames[overlayType]);
- }
-
- if (redraw)
- getScenes()->drawFrames(true);
-}
-
-// Remove all frames from the queue
-void Menu::clear() {
- for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
- getScenes()->removeAndRedraw(&it->_value, false);
-
- clearBg(GraphicsManager::kBackgroundOverlay);
-}
-
-// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame
-Common::String Menu::getAcornSequenceName(GameId id) const {
- Common::String name = "";
- switch (id) {
- default:
- case kGameBlue:
- name = "aconblu3.seq";
- break;
-
- case kGameRed:
- name = "aconred.seq";
- break;
-
- case kGameGreen:
- name = "acongren.seq";
- break;
-
- case kGamePurple:
- name = "aconpurp.seq";
- break;
-
- case kGameTeal:
- name = "aconteal.seq";
- break;
-
- case kGameGold:
- name = "acongold.seq";
- break;
- }
-
- return name;
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Time
-//////////////////////////////////////////////////////////////////////////
-void Menu::initTime(SavegameType type, uint32 value) {
- if (!value)
- return;
-
- // The savegame entry index
- uint32 entryIndex = 0;
-
- switch (type) {
- default:
- break;
-
- case kSavegameTypeIndex:
- entryIndex = (_index <= value) ? 1 : _index - value;
- break;
-
- case kSavegameTypeTime:
- if (value < kTimeStartGame)
- break;
-
- entryIndex = _index;
- if (!entryIndex)
- break;
-
- // Iterate through existing entries
- do {
- if (getSaveLoad()->getTime(entryIndex) <= value)
- break;
-
- entryIndex--;
- } while (entryIndex);
- break;
-
- case kSavegameTypeEvent:
- entryIndex = _index;
- if (!entryIndex)
- break;
-
- do {
- if (getSaveLoad()->getValue(entryIndex) == value)
- break;
-
- entryIndex--;
- } while (entryIndex);
- break;
-
- case kSavegameTypeEvent2:
- // TODO rewrite in a more legible way
- if (_index > 1) {
- uint32 index = _index;
- do {
- if (getSaveLoad()->getValue(index) == value)
- break;
-
- index--;
- } while (index > 1);
-
- entryIndex = index - 1;
- } else {
- entryIndex = _index - 1;
- }
- break;
- }
-
- if (entryIndex) {
- _currentIndex = entryIndex;
- updateTime(getSaveLoad()->getTime(entryIndex));
- }
-}
-
-void Menu::updateTime(uint32 time) {
- if (_currentTime == _time)
- _delta = 0;
-
- _currentTime = time;
-
- if (_time != time) {
- if (getSound()->isBuffered(kEntityChapters))
- getSound()->removeFromQueue(kEntityChapters);
-
- getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters);
- adjustIndex(_currentTime, _time, false);
- }
-}
-
-void Menu::adjustIndex(uint32 time1, uint32 time2, bool searchEntry) {
- uint32 index = 0;
- int32 timeDelta = -1;
-
- if (time1 != time2) {
-
- index = _index;
-
- if (time2 >= time1) {
- if (searchEntry) {
- uint32 currentIndex = _index;
-
- if ((int32)_index >= 0) {
- do {
- // Calculate new delta
- int32 newDelta = time1 - (uint32)getSaveLoad()->getTime(currentIndex);
-
- if (newDelta >= 0 && timeDelta >= newDelta) {
- timeDelta = newDelta;
- index = currentIndex;
- }
-
- --currentIndex;
- } while ((int32)currentIndex >= 0);
- }
- } else {
- index = _index - 1;
- }
- } else {
- if (searchEntry) {
- uint32 currentIndex = _index;
-
- if (_lastIndex >= _index) {
- do {
- // Calculate new delta
- int32 newDelta = (uint32)getSaveLoad()->getTime(currentIndex) - time1;
-
- if (newDelta >= 0 && timeDelta > newDelta) {
- timeDelta = newDelta;
- index = currentIndex;
- }
-
- ++currentIndex;
- } while (currentIndex <= _lastIndex);
- }
- } else {
- index = _index + 1;
- }
- }
-
- _index = index;
- checkHotspots();
- }
-
- if (_index == _currentIndex) {
- if (getProgress().chapter != getSaveLoad()->getChapter(index))
- getProgress().chapter = getSaveLoad()->getChapter(_index);
- }
-}
-
-void Menu::goToTime(uint32 time) {
-
- uint32 entryIndex = 0;
- uint32 deltaTime = (uint32)ABS((int32)(getSaveLoad()->getTime(0) - time));
- uint32 index = 0;
-
- do {
- uint32 deltaTime2 = (uint32)ABS((int32)(getSaveLoad()->getTime(index) - time));
- if (deltaTime2 < deltaTime) {
- deltaTime = deltaTime2;
- entryIndex = index;
- }
-
- ++index;
- } while (_lastIndex >= index);
-
- _currentIndex = entryIndex;
- updateTime(getSaveLoad()->getTime(entryIndex));
-}
-
-void Menu::setTime() {
- _currentIndex = _index;
- _currentTime = getSaveLoad()->getTime(_currentIndex);
-
- if (_time == _currentTime)
- adjustTime();
-}
-
-void Menu::forwardTime() {
- if (_lastIndex <= _index)
- return;
-
- _currentIndex = _lastIndex;
- updateTime(getSaveLoad()->getTime(_currentIndex));
-}
-
-void Menu::rewindTime() {
- if (!_index)
- return;
-
- _currentIndex = 0;
- updateTime(getSaveLoad()->getTime(_currentIndex));
-}
-
-void Menu::adjustTime() {
- uint32 originalTime = _time;
-
- // Adjust time delta
- Common::Rational timeDelta(_delta >= 90 ? 9 : (9 * _delta + 89), _delta >= 90 ? 1 : 90);
-
- if (_currentTime < _time) {
- timeDelta *= 900;
- _time -= (uint)timeDelta.toInt();
-
- if (_currentTime > _time)
- _time = _currentTime;
- } else {
- timeDelta *= 900;
- _time += (uint)timeDelta.toInt();
-
- if (_currentTime < _time)
- _time = _currentTime;
- }
-
- if (_currentTime == _time && getSound()->isBuffered(kEntityChapters))
- getSound()->removeFromQueue(kEntityChapters);
-
- _clock->draw(_time);
- _trainLine->draw(_time);
- getScenes()->drawFrames(true);
-
- adjustIndex(_time, originalTime, true);
-
- ++_delta;
-}
-
-void Menu::moveToCity(CityButton city, bool clicked) {
- uint32 time = (uint32)_cityButtonsInfo[city].time;
-
- // TODO Check if we have access (there seems to be more checks on some internal times) - probably : current_time (menu only) / game time / some other?
- if (_lowerTime < time || _time == time || _currentTime == time) {
- hideOverlays();
- return;
- }
-
- // Show city overlay
- showFrame((StartMenuOverlay)((_cityButtonsInfo[city].index >> 6) + 3), _cityButtonsInfo[city].index & 63, true);
-
- if (clicked) {
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB046");
- goToTime(time);
-
- _handleTimeDelta = true;
-
- return;
- }
-
- // Special case of first and last cities
- if (city == kParis || city == kConstantinople) {
- showFrame(kOverlayTooltip, (city == kParis) ? kTooltipRewindParis : kTooltipForwardConstantinople, true);
- return;
- }
-
- showFrame(kOverlayTooltip, (_time <= time) ? _cityButtonsInfo[city].forward : _cityButtonsInfo[city].rewind, true);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// Sound / Brightness
-//////////////////////////////////////////////////////////////////////////
-
-// Get current volume (converted internal ScummVM value)
-uint32 Menu::getVolume() const {
- return getState()->volume;
-}
-
-// Set the volume (converts to ScummVM values)
-void Menu::setVolume(uint32 volume) const {
- getState()->volume = volume;
-
- // Clamp volume
- uint32 value = volume * Audio::Mixer::kMaxMixerVolume / 7;
-
- if (value > Audio::Mixer::kMaxMixerVolume)
- value = Audio::Mixer::kMaxMixerVolume;
-
- _engine->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (int32)value);
-}
-
-uint32 Menu::getBrightness() const {
- return getState()->brightness;
-}
-
-void Menu::setBrightness(uint32 brightness) const {
- getState()->brightness = brightness;
-
- // TODO reload cursor & font with adjusted brightness
-}
-
-} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/menu.h b/engines/lastexpress/game/menu.h
deleted file mode 100644
index 4b84c06..0000000
--- a/engines/lastexpress/game/menu.h
+++ /dev/null
@@ -1,207 +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.
- *
- */
-
-#ifndef LASTEXPRESS_MENU_H
-#define LASTEXPRESS_MENU_H
-
-#include "lastexpress/data/sequence.h"
-
-#include "lastexpress/eventhandler.h"
-
-#include "lastexpress/shared.h"
-
-#include "common/hashmap.h"
-
-namespace LastExpress {
-
-class LastExpressEngine;
-class Scene;
-class SceneHotspot;
-
-class Clock;
-class TrainLine;
-
-class Menu : public EventHandler {
-public:
- Menu(LastExpressEngine *engine);
- ~Menu();
-
- void show(bool doSavegame, SavegameType type, uint32 value);
-
- // Event handling
- void eventMouse(const Common::Event &ev);
- void eventTick(const Common::Event &ev);
-
- bool isShown() const { return _isShowingMenu; }
-
- GameId getGameId() const { return _gameId; }
-
-private:
- // Start menu events
- enum StartMenuAction {
- kMenuContinue = 1,
- kMenuCredits = 2,
- kMenuQuitGame = 3,
- kMenuCase4 = 4,
- kMenuSwitchSaveGame = 6,
- kMenuRewindGame = 7,
- kMenuForwardGame = 8,
- kMenuParis = 10,
- kMenuStrasBourg = 11,
- kMenuMunich = 12,
- kMenuVienna = 13,
- kMenuBudapest = 14,
- kMenuBelgrade = 15,
- kMenuConstantinople = 16,
- kMenuDecreaseVolume = 17,
- kMenuIncreaseVolume = 18,
- kMenuDecreaseBrightness = 19,
- kMenuIncreaseBrightness = 20
- };
-
- // City buttons
- enum CityButton {
- kParis = 0,
- kStrasbourg = 1,
- kMunich = 2,
- kVienna = 3,
- kBudapest = 4,
- kBelgrade = 5,
- kConstantinople = 6
- };
-
- // Start menu overlay elements
- enum StartMenuOverlay {
- kOverlayTooltip, // 0
- kOverlayEggButtons,
- kOverlayButtons,
- kOverlayAcorn,
- kOverlayCity1,
- kOverlayCity2, // 5
- kOverlayCity3,
- kOverlayCredits
- };
-
- LastExpressEngine *_engine;
-
- // Sequences
- Sequence *_seqTooltips;
- Sequence *_seqEggButtons;
- Sequence *_seqButtons;
- Sequence *_seqAcorn;
- Sequence *_seqCity1;
- Sequence *_seqCity2;
- Sequence *_seqCity3;
- Sequence *_seqCredits;
-
- GameId _gameId;
-
- // Indicator to know if we need to show the start animation when showMenu is called
- bool _hasShownStartScreen;
- bool _hasShownIntro;
-
- bool _isShowingCredits;
- bool _isGameStarted;
- bool _isShowingMenu;
-
-
- uint16 _creditsSequenceIndex;
-
- //////////////////////////////////////////////////////////////////////////
- // Event handling
- uint32 _checkHotspotsTicks;
- Common::EventType _mouseFlags;
- SceneHotspot *_lastHotspot;
-
- void init(bool doSavegame, SavegameType type, uint32 value);
- void setup();
- bool handleEvent(StartMenuAction action, Common::EventType type);
- void checkHotspots();
- void setLogicEventHandlers();
-
- //////////////////////////////////////////////////////////////////////////
- // Game-related
- void startGame();
- void switchGame();
-
- //////////////////////////////////////////////////////////////////////////
- // Overlays & elements
- Clock *_clock;
- TrainLine *_trainLine;
-
- struct MenuOverlays_EqualTo {
- bool operator()(const StartMenuOverlay &x, const StartMenuOverlay &y) const { return x == y; }
- };
-
- struct MenuOverlays_Hash {
- uint operator()(const StartMenuOverlay &x) const { return x; }
- };
-
- typedef Common::HashMap<StartMenuOverlay, SequenceFrame *, MenuOverlays_Hash, MenuOverlays_EqualTo> MenuFrames;
-
- MenuFrames _frames;
-
- void hideOverlays();
- void showFrame(StartMenuOverlay overlay, int index, bool redraw);
-
- void clear();
-
- // TODO: remove?
- void moveToCity(CityButton city, bool clicked);
-
- //////////////////////////////////////////////////////////////////////////
- // Misc
- Common::String getAcornSequenceName(GameId id) const;
-
- //////////////////////////////////////////////////////////////////////////
- // Time
- uint32 _currentTime; // current game time
- uint32 _lowerTime; // lower time value
- uint32 _time;
-
- uint32 _currentIndex; // current savegame entry
- uint32 _index;
- uint32 _lastIndex;
- uint32 _delta;
- bool _handleTimeDelta;
-
- void initTime(SavegameType type, uint32 val);
- void updateTime(uint32 time);
- void adjustTime();
- void adjustIndex(uint32 time1, uint32 time2, bool searchEntry);
- void goToTime(uint32 time);
- void setTime();
- void forwardTime();
- void rewindTime();
- bool hasTimeDelta() { return (_currentTime - _time) >= 1; }
-
- //////////////////////////////////////////////////////////////////////////
- // Sound/Brightness related
- uint32 getVolume() const;
- void setVolume(uint32 volume) const;
- uint32 getBrightness() const;
- void setBrightness(uint32 brightness) const;
-};
-
-} // End of namespace LastExpress
-
-#endif // LASTEXPRESS_MENU_H
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 5d06eca..594cd12 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -24,11 +24,12 @@
#include "lastexpress/game/inventory.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/object.h"
#include "lastexpress/game/savepoint.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/menu.h"
+
#include "lastexpress/debug.h"
#include "lastexpress/lastexpress.h"
#include "lastexpress/helpers.h"
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 120e6eb..73893c9 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -26,11 +26,12 @@
#include "lastexpress/data/font.h"
#include "lastexpress/game/logic.h"
-#include "lastexpress/game/menu.h"
#include "lastexpress/game/scenes.h"
#include "lastexpress/game/state.h"
#include "lastexpress/game/sound.h"
+#include "lastexpress/menu/menu.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/resource.h"
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
new file mode 100644
index 0000000..b7e6a14
--- /dev/null
+++ b/engines/lastexpress/menu/menu.cpp
@@ -0,0 +1,1542 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/menu/menu.h"
+
+// Data
+#include "lastexpress/data/animation.h"
+#include "lastexpress/data/cursor.h"
+#include "lastexpress/data/snd.h"
+#include "lastexpress/data/scene.h"
+
+#include "lastexpress/fight/fight.h"
+
+#include "lastexpress/game/inventory.h"
+#include "lastexpress/game/logic.h"
+#include "lastexpress/game/savegame.h"
+#include "lastexpress/game/savepoint.h"
+#include "lastexpress/game/scenes.h"
+#include "lastexpress/game/sound.h"
+#include "lastexpress/game/state.h"
+
+#include "lastexpress/graphics.h"
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+#include "common/rational.h"
+
+#define getNextGameId() (GameId)((_gameId + 1) % 6)
+
+namespace LastExpress {
+
+// Bottom-left buttons (quit.seq)
+enum StartMenuButtons {
+ kButtonVolumeDownPushed,
+ kButtonVolumeDown,
+ kButtonVolume,
+ kButtonVolumeUp,
+ kButtonVolumeUpPushed,
+ kButtonBrightnessDownPushed, // 5
+ kButtonBrightnessDown,
+ kButtonBrightness,
+ kButtonBrightnessUp,
+ kButtonBrightnessUpPushed,
+ kButtonQuit, // 10
+ kButtonQuitPushed
+};
+
+// Egg buttons (buttns.seq)
+enum StartMenuEggButtons {
+ kButtonShield,
+ kButtonRewind,
+ kButtonRewindPushed,
+ kButtonForward,
+ kButtonForwardPushed,
+ kButtonCredits, // 5
+ kButtonCreditsPushed,
+ kButtonContinue
+};
+
+// Tooltips sequence (helpnewr.seq)
+enum StartMenuTooltips {
+ kTooltipInsertCd1,
+ kTooltipInsertCd2,
+ kTooltipInsertCd3,
+ kTooltipContinueGame,
+ kTooltipReplayGame,
+ kTooltipContinueRewoundGame, // 5
+ kTooltipViewGameEnding,
+ kTooltipStartAnotherGame,
+ kTooltipVolumeUp,
+ kTooltipVolumeDown,
+ kTooltipBrightnessUp, // 10
+ kTooltipBrightnessDown,
+ kTooltipQuit,
+ kTooltipRewindParis,
+ kTooltipForwardStrasbourg,
+ kTooltipRewindStrasbourg, // 15
+ kTooltipRewindMunich,
+ kTooltipForwardMunich,
+ kTooltipForwardVienna,
+ kTooltipRewindVienna,
+ kTooltipRewindBudapest, // 20
+ kTooltipForwardBudapest,
+ kTooltipForwardBelgrade,
+ kTooltipRewindBelgrade,
+ kTooltipForwardConstantinople,
+ kTooltipSwitchBlueGame, // 25
+ kTooltipSwitchRedGame,
+ kTooltipSwitchGoldGame,
+ kTooltipSwitchGreenGame,
+ kTooltipSwitchTealGame,
+ kTooltipSwitchPurpleGame, // 30
+ kTooltipPlayNewGame,
+ kTooltipCredits,
+ kTooltipFastForward,
+ kTooltipRewind
+};
+
+//////////////////////////////////////////////////////////////////////////
+// DATA
+//////////////////////////////////////////////////////////////////////////
+
+// Information about the cities on the train line
+static const struct {
+ uint8 frame;
+ TimeValue time;
+} _trainCities[31] = {
+ {0, kTimeCityParis},
+ {9, kTimeCityEpernay},
+ {11, kTimeCityChalons},
+ {16, kTimeCityBarLeDuc},
+ {21, kTimeCityNancy},
+ {25, kTimeCityLuneville},
+ {35, kTimeCityAvricourt},
+ {37, kTimeCityDeutschAvricourt},
+ {40, kTimeCityStrasbourg},
+ {53, kTimeCityBadenOos},
+ {56, kTimeCityKarlsruhe},
+ {60, kTimeCityStuttgart},
+ {63, kTimeCityGeislingen},
+ {66, kTimeCityUlm},
+ {68, kTimeCityAugsburg},
+ {73, kTimeCityMunich},
+ {84, kTimeCitySalzbourg},
+ {89, kTimeCityAttnangPuchheim},
+ {97, kTimeCityWels},
+ {100, kTimeCityLinz},
+ {104, kTimeCityAmstetten},
+ {111, kTimeCityVienna},
+ {120, kTimeCityPoszony},
+ {124, kTimeCityGalanta},
+ {132, kTimeCityBudapest},
+ {148, kTimeCityBelgrade},
+ /* Line 1 ends at 150 - line 2 begins at 0 */
+ {157, kTimeCityNish},
+ {165, kTimeCityTzaribrod},
+ {174, kTimeCitySofia},
+ {198, kTimeCityAdrianople},
+ {210, kTimeCityConstantinople}};
+
+static const struct {
+ TimeValue time;
+ uint index;
+ StartMenuTooltips rewind;
+ StartMenuTooltips forward;
+} _cityButtonsInfo[7] = {
+ {kTimeCityParis, 64, kTooltipRewindParis, kTooltipRewindParis},
+ {kTimeCityStrasbourg, 128, kTooltipRewindStrasbourg, kTooltipForwardStrasbourg},
+ {kTimeCityMunich, 129, kTooltipRewindMunich, kTooltipForwardMunich},
+ {kTimeCityVienna, 130, kTooltipRewindVienna, kTooltipForwardVienna},
+ {kTimeCityBudapest, 131, kTooltipRewindBudapest, kTooltipForwardBudapest},
+ {kTimeCityBelgrade, 132, kTooltipRewindBelgrade, kTooltipForwardBelgrade},
+ {kTimeCityConstantinople, 192, kTooltipForwardConstantinople, kTooltipForwardConstantinople}
+};
+
+//////////////////////////////////////////////////////////////////////////
+// Clock
+//////////////////////////////////////////////////////////////////////////
+class Clock {
+public:
+ explicit Clock(LastExpressEngine *engine);
+ ~Clock();
+
+ void draw(uint32 time);
+ void clear();
+
+private:
+ LastExpressEngine *_engine;
+
+ // Frames
+ SequenceFrame *_frameMinutes;
+ SequenceFrame *_frameHour;
+ SequenceFrame *_frameSun;
+ SequenceFrame *_frameDate;
+};
+
+Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) {
+ _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
+ _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
+ _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
+ _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
+}
+
+Clock::~Clock() {
+ SAFE_DELETE(_frameMinutes);
+ SAFE_DELETE(_frameHour);
+ SAFE_DELETE(_frameSun);
+ SAFE_DELETE(_frameDate);
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+void Clock::clear() {
+ getScenes()->removeFromQueue(_frameMinutes);
+ getScenes()->removeFromQueue(_frameHour);
+ getScenes()->removeFromQueue(_frameSun);
+ getScenes()->removeFromQueue(_frameDate);
+}
+
+void Clock::draw(uint32 time) {
+ assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
+
+ // Check that sequences have been loaded
+ if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
+ error("Clock::process: clock sequences have not been loaded correctly!");
+
+ // Clear existing frames
+ clear();
+
+ // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914
+ // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914
+ // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins
+
+ // 15 = 1 second
+ // 15 * 60 = 900 = 1 minute
+ // 900 * 60 = 54000 = 1 hour
+ // 54000 * 24 = 1296000 = 1 day
+
+ // Calculate each sequence index from the current time
+
+ uint8 hour = 0;
+ uint8 minute = 0;
+ State::getHourMinutes(time, &hour, &minute);
+ uint32 index_date = 18 * time / 1296000;
+ if (hour == 23)
+ index_date += 18 * minute / 60;
+
+ // Set sequences frames
+ _frameMinutes->setFrame(minute);
+ _frameHour->setFrame((5 * hour + minute / 12) % 60);
+ _frameSun->setFrame((5 * hour + minute / 12) % 120);
+ _frameDate->setFrame((uint16)index_date);
+
+ // Adjust z-order and queue
+ _frameMinutes->getInfo()->location = 1;
+ _frameHour->getInfo()->location = 1;
+ _frameSun->getInfo()->location = 1;
+ _frameDate->getInfo()->location = 1;
+
+ getScenes()->addToQueue(_frameMinutes);
+ getScenes()->addToQueue(_frameHour);
+ getScenes()->addToQueue(_frameSun);
+ getScenes()->addToQueue(_frameDate);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// TrainLine
+//////////////////////////////////////////////////////////////////////////
+class TrainLine {
+public:
+ explicit TrainLine(LastExpressEngine *engine);
+ ~TrainLine();
+
+ void draw(uint32 time);
+ void clear();
+
+private:
+ LastExpressEngine *_engine;
+
+ // Frames
+ SequenceFrame *_frameLine1;
+ SequenceFrame *_frameLine2;
+};
+
+TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) {
+ _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true);
+ _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true);
+}
+
+TrainLine::~TrainLine() {
+ SAFE_DELETE(_frameLine1);
+ SAFE_DELETE(_frameLine2);
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+void TrainLine::clear() {
+ getScenes()->removeFromQueue(_frameLine1);
+ getScenes()->removeFromQueue(_frameLine2);
+}
+
+// Draw the train line at the time
+// line1: 150 frames (=> Belgrade)
+// line2: 61 frames (=> Constantinople)
+void TrainLine::draw(uint32 time) {
+ assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
+
+ // Check that sequences have been loaded
+ if (!_frameLine1 || !_frameLine2)
+ error("TrainLine::process: Line sequences have not been loaded correctly!");
+
+ // Clear existing frames
+ clear();
+
+ // Get the index of the last city the train has visited
+ uint index = 0;
+ for (uint i = 0; i < ARRAYSIZE(_trainCities); i++)
+ if ((uint32)_trainCities[i].time <= time)
+ index = i;
+
+ uint16 frame;
+ if (time > (uint32)_trainCities[index].time) {
+ // Interpolate linearly to use a frame between the cities
+ uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame;
+ uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time);
+ uint traveledTime = (time - (uint)_trainCities[index].time);
+ frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities);
+ } else {
+ // Exactly on the city
+ frame = _trainCities[index].frame;
+ }
+
+ // Set frame, z-order and queue
+ if (frame < 150) {
+ _frameLine1->setFrame(frame);
+
+ _frameLine1->getInfo()->location = 1;
+ getScenes()->addToQueue(_frameLine1);
+ } else {
+ // We passed Belgrade
+ _frameLine1->setFrame(149);
+ _frameLine2->setFrame(frame - 150);
+
+ _frameLine1->getInfo()->location = 1;
+ _frameLine2->getInfo()->location = 1;
+
+ getScenes()->addToQueue(_frameLine1);
+ getScenes()->addToQueue(_frameLine2);
+ }
+}
+
+
+//////////////////////////////////////////////////////////////////////////
+// Menu
+//////////////////////////////////////////////////////////////////////////
+Menu::Menu(LastExpressEngine *engine) : _engine(engine),
+ _seqTooltips(NULL), _seqEggButtons(NULL), _seqButtons(NULL), _seqAcorn(NULL), _seqCity1(NULL), _seqCity2(NULL), _seqCity3(NULL), _seqCredits(NULL),
+ _gameId(kGameBlue), _hasShownStartScreen(false), _hasShownIntro(false),
+ _isShowingCredits(false), _isGameStarted(false), _isShowingMenu(false),
+ _creditsSequenceIndex(0), _checkHotspotsTicks(15), _mouseFlags(Common::EVENT_INVALID), _lastHotspot(NULL),
+ _currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) {
+
+ _clock = new Clock(_engine);
+ _trainLine = new TrainLine(_engine);
+}
+
+Menu::~Menu() {
+ SAFE_DELETE(_clock);
+ SAFE_DELETE(_trainLine);
+
+ SAFE_DELETE(_seqTooltips);
+ SAFE_DELETE(_seqEggButtons);
+ SAFE_DELETE(_seqButtons);
+ SAFE_DELETE(_seqAcorn);
+ SAFE_DELETE(_seqCity1);
+ SAFE_DELETE(_seqCity2);
+ SAFE_DELETE(_seqCity3);
+ SAFE_DELETE(_seqCredits);
+
+ _lastHotspot = NULL;
+
+ // Cleanup frames
+ for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
+ SAFE_DELETE(it->_value);
+
+ _frames.clear();
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Setup
+void Menu::setup() {
+
+ // Clear drawing queue
+ getScenes()->removeAndRedraw(&_frames[kOverlayAcorn], false);
+ SAFE_DELETE(_seqAcorn);
+
+ // Load Menu scene
+ // + 1 = normal menu with open egg / clock
+ // + 2 = shield menu, when no savegame exists (no game has been started)
+ _isGameStarted = _lowerTime >= kTimeStartGame;
+ getScenes()->loadScene((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2));
+ getFlags()->shouldRedraw = true;
+ getLogic()->updateCursor();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Load Acorn sequence
+ _seqAcorn = loadSequence(getAcornSequenceName(_isGameStarted ? getNextGameId() : kGameBlue));
+
+ //////////////////////////////////////////////////////////////////////////
+ // Check if we loaded sequences before
+ if (_seqTooltips && _seqTooltips->count() > 0)
+ return;
+
+ // Load all static data
+ _seqTooltips = loadSequence("helpnewr.seq");
+ _seqEggButtons = loadSequence("buttns.seq");
+ _seqButtons = loadSequence("quit.seq");
+ _seqCity1 = loadSequence("jlinetl.seq");
+ _seqCity2 = loadSequence("jlinecen.seq");
+ _seqCity3 = loadSequence("jlinebr.seq");
+ _seqCredits = loadSequence("credits.seq");
+
+ _frames[kOverlayTooltip] = new SequenceFrame(_seqTooltips);
+ _frames[kOverlayEggButtons] = new SequenceFrame(_seqEggButtons);
+ _frames[kOverlayButtons] = new SequenceFrame(_seqButtons);
+ _frames[kOverlayAcorn] = new SequenceFrame(_seqAcorn);
+ _frames[kOverlayCity1] = new SequenceFrame(_seqCity1);
+ _frames[kOverlayCity2] = new SequenceFrame(_seqCity2);
+ _frames[kOverlayCity3] = new SequenceFrame(_seqCity3);
+ _frames[kOverlayCredits] = new SequenceFrame(_seqCredits);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Handle events
+void Menu::eventMouse(const Common::Event &ev) {
+ if (!getFlags()->shouldRedraw)
+ return;
+
+ bool redraw = true;
+ getFlags()->shouldRedraw = false;
+
+ // Update coordinates
+ setCoords(ev.mouse);
+ //_mouseFlags = (Common::EventType)(ev.type & Common::EVENT_LBUTTONUP);
+
+ if (_isShowingCredits) {
+ if (ev.type == Common::EVENT_RBUTTONUP) {
+ showFrame(kOverlayCredits, -1, true);
+ _isShowingCredits = false;
+ }
+
+ if (ev.type == Common::EVENT_LBUTTONUP) {
+ // Last frame of the credits
+ if (_seqCredits && _creditsSequenceIndex == _seqCredits->count() - 1) {
+ showFrame(kOverlayCredits, -1, true);
+ _isShowingCredits = false;
+ } else {
+ ++_creditsSequenceIndex;
+ showFrame(kOverlayCredits, _creditsSequenceIndex, true);
+ }
+ }
+ } else {
+ // Check for hotspots
+ SceneHotspot *hotspot = NULL;
+ getScenes()->get(getState()->scene)->checkHotSpot(ev.mouse, &hotspot);
+
+ if (_lastHotspot != hotspot || ev.type == Common::EVENT_LBUTTONUP) {
+ _lastHotspot = hotspot;
+
+ if (ev.type == Common::EVENT_MOUSEMOVE) { /* todo check event type */
+ if (!_handleTimeDelta && hasTimeDelta())
+ setTime();
+ }
+
+ if (hotspot) {
+ redraw = handleEvent((StartMenuAction)hotspot->action, ev.type);
+ getFlags()->mouseRightClick = false;
+ getFlags()->mouseLeftClick = false;
+ } else {
+ hideOverlays();
+ }
+ }
+ }
+
+ if (redraw) {
+ getFlags()->shouldRedraw = true;
+ askForRedraw();
+ }
+}
+
+void Menu::eventTick(const Common::Event&) {
+ if (hasTimeDelta())
+ adjustTime();
+ else if (_handleTimeDelta)
+ _handleTimeDelta = false;
+
+ // Check hotspots
+ if (!--_checkHotspotsTicks) {
+ checkHotspots();
+ _checkHotspotsTicks = 15;
+ }
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Show the intro and load the main menu scene
+void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
+
+ if (_isShowingMenu)
+ return;
+
+ _isShowingMenu = true;
+ getEntities()->reset();
+
+ // If no blue savegame exists, this might be the first time we start the game, so we show the full intro
+ if (!getFlags()->mouseRightClick) {
+ if (!SaveLoad::isSavegameValid(kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
+
+ if (!_hasShownIntro) {
+ // Show Broderbrund logo
+ Animation animation;
+ if (animation.load(getArchive("1930.nis")))
+ animation.play();
+
+ getFlags()->mouseRightClick = false;
+
+ // Play intro music
+ getSound()->playSoundWithSubtitles("MUS001.SND", SoundManager::kFlagMusic, kEntityPlayer);
+
+ // Show The Smoking Car logo
+ if (animation.load(getArchive("1931.nis")))
+ animation.play();
+
+ _hasShownIntro = true;
+ }
+ } else {
+ // Only show the quick intro
+ if (!_hasShownStartScreen) {
+ getSound()->playSoundWithSubtitles("MUS018.SND", SoundManager::kFlagMusic, kEntityPlayer);
+ getScenes()->loadScene(kSceneStartScreen);
+
+ // Original game waits 60 frames and loops Sound::unknownFunction1 unless the right button is pressed
+ uint32 nextFrameCount = getFrameCount() + 60;
+ while (getFrameCount() < nextFrameCount) {
+ _engine->pollEvents();
+
+ if (getFlags()->mouseRightClick)
+ break;
+
+ getSound()->updateQueue();
+ }
+ }
+ }
+ }
+
+ _hasShownStartScreen = true;
+
+ // Init Menu
+ init(doSavegame, type, value);
+
+ // Setup sound
+ getSound()->unknownFunction4();
+ getSound()->resetQueue(SoundManager::kSoundType11, SoundManager::kSoundType13);
+ if (getSound()->isBuffered("TIMER"))
+ getSound()->removeFromQueue("TIMER");
+
+ // Init flags & misc
+ _isShowingCredits = false;
+ _handleTimeDelta = hasTimeDelta();
+ getInventory()->unselectItem();
+
+ // Set Cursor type
+ _engine->getCursor()->setStyle(kCursorNormal);
+ _engine->getCursor()->show(true);
+
+ setup();
+ checkHotspots();
+
+ // Set event handlers
+ SET_EVENT_HANDLERS(Menu, this);
+}
+
+bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
+ bool clicked = (type == Common::EVENT_LBUTTONUP);
+
+ switch(action) {
+ default:
+ hideOverlays();
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuCredits:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ if (clicked) {
+ showFrame(kOverlayEggButtons, kButtonCreditsPushed, true);
+ showFrame(kOverlayTooltip, -1, true);
+
+ getSound()->playSound(kEntityPlayer, "LIB046");
+
+ hideOverlays();
+
+ _isShowingCredits = true;
+ _creditsSequenceIndex = 0;
+
+ showFrame(kOverlayCredits, 0, true);
+ } else {
+ // TODO check flags ?
+
+ showFrame(kOverlayEggButtons, kButtonCredits, true);
+ showFrame(kOverlayTooltip, kTooltipCredits, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuQuitGame:
+ showFrame(kOverlayTooltip, kTooltipQuit, true);
+
+ if (clicked) {
+ showFrame(kOverlayButtons, kButtonQuitPushed, true);
+
+ getSound()->clearStatus();
+ getSound()->updateQueue();
+ getSound()->playSound(kEntityPlayer, "LIB046");
+
+ // FIXME uncomment when sound queue is properly implemented
+ /*while (getSound()->isBuffered("LIB046"))
+ getSound()->updateQueue();*/
+
+ getFlags()->shouldRedraw = false;
+
+ Engine::quitGame();
+
+ return false;
+ } else {
+ showFrame(kOverlayButtons, kButtonQuit, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuCase4:
+ if (clicked)
+ _index = 0;
+ // fall down to kMenuContinue
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuContinue: {
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ // Determine the proper CD archive
+ ArchiveIndex cd = kArchiveCd1;
+ if (getProgress().chapter > kChapter1)
+ cd = (getProgress().chapter > kChapter3) ? kArchiveCd3 : kArchiveCd2;
+
+ // Show tooltips & buttons to start a game, continue a game or load the proper cd
+ if (ResourceManager::isArchivePresent(cd)) {
+ if (_isGameStarted) {
+ showFrame(kOverlayEggButtons, kButtonContinue, true);
+
+ if (_lastIndex == _index) {
+ showFrame(kOverlayTooltip, getSaveLoad()->isGameFinished(_index, _lastIndex) ? kTooltipViewGameEnding : kTooltipContinueGame, true);
+ } else {
+ showFrame(kOverlayTooltip, kTooltipContinueRewoundGame, true);
+ }
+
+ } else {
+ showFrame(kOverlayEggButtons, kButtonShield, true);
+ showFrame(kOverlayTooltip, kTooltipPlayNewGame, true);
+ }
+ } else {
+ showFrame(kOverlayEggButtons, -1, true);
+ showFrame(kOverlayTooltip, cd - 1, true);
+ }
+
+ if (!clicked)
+ break;
+
+ // Try loading the archive file
+ if (!_engine->getResourceManager()->loadArchive(cd))
+ break;
+
+ // Load the train data file and setup game
+ getScenes()->loadSceneDataFile(cd);
+ showFrame(kOverlayTooltip, -1, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+
+ // Setup new game
+ getSavePoints()->reset();
+ setLogicEventHandlers();
+
+ if (_index) {
+ getSound()->processEntry(SoundManager::kSoundType11);
+ } else {
+ if (!getFlags()->mouseRightClick) {
+ getScenes()->loadScene((SceneIndex)(5 * _gameId + 3));
+
+ if (!getFlags()->mouseRightClick) {
+ getScenes()->loadScene((SceneIndex)(5 * _gameId + 4));
+
+ if (!getFlags()->mouseRightClick) {
+ getScenes()->loadScene((SceneIndex)(5 * _gameId + 5));
+
+ if (!getFlags()->mouseRightClick) {
+ getSound()->processEntry(SoundManager::kSoundType11);
+
+ // Show intro
+ Animation animation;
+ if (animation.load(getArchive("1601.nis")))
+ animation.play();
+
+ getEvent(kEventIntro) = 1;
+ }
+ }
+ }
+ }
+
+ if (!getEvent(kEventIntro)) {
+ getEvent(kEventIntro) = 1;
+
+ getSound()->processEntry(SoundManager::kSoundType11);
+ }
+ }
+
+ // Setup game
+ getFlags()->isGameRunning = true;
+ startGame();
+
+ if (!_isShowingMenu)
+ getInventory()->show();
+
+ return false;
+ }
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuSwitchSaveGame:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ if (clicked) {
+ showFrame(kOverlayAcorn, 1, true);
+ showFrame(kOverlayTooltip, -1, true);
+ getSound()->playSound(kEntityPlayer, "LIB047");
+
+ // Setup new menu screen
+ switchGame();
+ setup();
+
+ // Set fight state to 0
+ getFight()->resetState();
+
+ return true;
+ }
+
+ // TODO Check for flag
+
+ showFrame(kOverlayAcorn, 0, true);
+
+ if (_isGameStarted) {
+ showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
+ break;
+ }
+
+ if (_gameId == kGameGold) {
+ showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
+ break;
+ }
+
+ if (!SaveLoad::isSavegameValid(getNextGameId())) {
+ showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
+ break;
+ }
+
+ // Stupid tooltips ids are not in order, so we can't just increment them...
+ switch(_gameId) {
+ default:
+ break;
+
+ case kGameBlue:
+ showFrame(kOverlayTooltip, kTooltipSwitchRedGame, true);
+ break;
+
+ case kGameRed:
+ showFrame(kOverlayTooltip, kTooltipSwitchGreenGame, true);
+ break;
+
+ case kGameGreen:
+ showFrame(kOverlayTooltip, kTooltipSwitchPurpleGame, true);
+ break;
+
+ case kGamePurple:
+ showFrame(kOverlayTooltip, kTooltipSwitchTealGame, true);
+ break;
+
+ case kGameTeal:
+ showFrame(kOverlayTooltip, kTooltipSwitchGoldGame, true);
+ break;
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuRewindGame:
+ if (!_index || _currentTime < _time) {
+ hideOverlays();
+ break;
+ }
+
+ if (clicked) {
+ if (hasTimeDelta())
+ _handleTimeDelta = false;
+
+ showFrame(kOverlayEggButtons, kButtonRewindPushed, true);
+ showFrame(kOverlayTooltip, -1, true);
+
+ getSound()->playSound(kEntityPlayer, "LIB046");
+
+ rewindTime();
+
+ _handleTimeDelta = false;
+ } else {
+ showFrame(kOverlayEggButtons, kButtonRewind, true);
+ showFrame(kOverlayTooltip, kTooltipRewind, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuForwardGame:
+ if (_lastIndex <= _index || _currentTime > _time) {
+ hideOverlays();
+ break;
+ }
+
+ if (clicked) {
+ if (hasTimeDelta())
+ _handleTimeDelta = false;
+
+ showFrame(kOverlayEggButtons, kButtonForwardPushed, true);
+ showFrame(kOverlayTooltip, -1, true);
+
+ getSound()->playSound(kEntityPlayer, "LIB046");
+
+ forwardTime();
+
+ _handleTimeDelta = false;
+ } else {
+ showFrame(kOverlayEggButtons, kButtonForward, true);
+ showFrame(kOverlayTooltip, kTooltipFastForward, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuParis:
+ moveToCity(kParis, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuStrasBourg:
+ moveToCity(kStrasbourg, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuMunich:
+ moveToCity(kMunich, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuVienna:
+ moveToCity(kVienna, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuBudapest:
+ moveToCity(kBudapest, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuBelgrade:
+ moveToCity(kBelgrade, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuConstantinople:
+ moveToCity(kConstantinople, clicked);
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuDecreaseVolume:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ // Cannot decrease volume further
+ if (getVolume() == 0) {
+ showFrame(kOverlayButtons, kButtonVolume, true);
+ showFrame(kOverlayTooltip, -1, true);
+ break;
+ }
+
+ showFrame(kOverlayTooltip, kTooltipVolumeDown, true);
+
+ // Show highlight on button & adjust volume if needed
+ if (clicked) {
+ showFrame(kOverlayButtons, kButtonVolumeDownPushed, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+ setVolume(getVolume() - 1);
+
+ getSaveLoad()->saveVolumeBrightness();
+
+ uint32 nextFrameCount = getFrameCount() + 15;
+ while (nextFrameCount > getFrameCount()) {
+ _engine->pollEvents();
+
+ getSound()->updateQueue();
+ }
+ } else {
+ showFrame(kOverlayButtons, kButtonVolumeDown, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuIncreaseVolume:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ // Cannot increase volume further
+ if (getVolume() >= 7) {
+ showFrame(kOverlayButtons, kButtonVolume, true);
+ showFrame(kOverlayTooltip, -1, true);
+ break;
+ }
+
+ showFrame(kOverlayTooltip, kTooltipVolumeUp, true);
+
+ // Show highlight on button & adjust volume if needed
+ if (clicked) {
+ showFrame(kOverlayButtons, kButtonVolumeUpPushed, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+ setVolume(getVolume() + 1);
+
+ getSaveLoad()->saveVolumeBrightness();
+
+ uint32 nextFrameCount = getFrameCount() + 15;
+ while (nextFrameCount > getFrameCount()) {
+ _engine->pollEvents();
+
+ getSound()->updateQueue();
+ }
+ } else {
+ showFrame(kOverlayButtons, kButtonVolumeUp, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuDecreaseBrightness:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ // Cannot increase brightness further
+ if (getBrightness() == 0) {
+ showFrame(kOverlayButtons, kButtonBrightness, true);
+ showFrame(kOverlayTooltip, -1, true);
+ break;
+ }
+
+ showFrame(kOverlayTooltip, kTooltipBrightnessDown, true);
+
+ // Show highlight on button & adjust brightness if needed
+ if (clicked) {
+ showFrame(kOverlayButtons, kButtonBrightnessDownPushed, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+ setBrightness(getBrightness() - 1);
+
+ getSaveLoad()->saveVolumeBrightness();
+
+ // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
+ _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
+ showFrame(kOverlayTooltip, kTooltipBrightnessDown, false);
+ showFrame(kOverlayButtons, kButtonBrightnessDownPushed, false);
+ } else {
+ showFrame(kOverlayButtons, kButtonBrightnessDown, true);
+ }
+ break;
+
+ //////////////////////////////////////////////////////////////////////////
+ case kMenuIncreaseBrightness:
+ if (hasTimeDelta()) {
+ hideOverlays();
+ break;
+ }
+
+ // Cannot increase brightness further
+ if (getBrightness() >= 6) {
+ showFrame(kOverlayButtons, kButtonBrightness, true);
+ showFrame(kOverlayTooltip, -1, true);
+ break;
+ }
+
+ showFrame(kOverlayTooltip, kTooltipBrightnessUp, true);
+
+ // Show highlight on button & adjust brightness if needed
+ if (clicked) {
+ showFrame(kOverlayButtons, kButtonBrightnessUpPushed, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+ setBrightness(getBrightness() + 1);
+
+ getSaveLoad()->saveVolumeBrightness();
+
+ // Reshow the background and frames (they will pick up the new brightness through the GraphicsManager)
+ _engine->getGraphicsManager()->draw(getScenes()->get((SceneIndex)(_isGameStarted ? _gameId * 5 + 1 : _gameId * 5 + 2)), GraphicsManager::kBackgroundC, true);
+ showFrame(kOverlayTooltip, kTooltipBrightnessUp, false);
+ showFrame(kOverlayButtons, kButtonBrightnessUpPushed, false);
+ } else {
+ showFrame(kOverlayButtons, kButtonBrightnessUp, true);
+ }
+ break;
+ }
+
+ return true;
+}
+
+void Menu::setLogicEventHandlers() {
+ SET_EVENT_HANDLERS(Logic, getLogic());
+ clear();
+ _isShowingMenu = false;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Game-related
+//////////////////////////////////////////////////////////////////////////
+void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
+
+ bool useSameIndex = true;
+
+ if (getGlobalTimer()) {
+ value = 0;
+
+ // Check if the CD file is present
+ ArchiveIndex index = kArchiveCd1;
+ switch (getProgress().chapter) {
+ default:
+ case kChapter1:
+ break;
+
+ case kChapter2:
+ case kChapter3:
+ index = kArchiveCd2;
+ break;
+
+ case kChapter4:
+ case kChapter5:
+ index = kArchiveCd3;
+ break;
+ }
+
+ if (ResourceManager::isArchivePresent(index)) {
+ setGlobalTimer(0);
+ useSameIndex = false;
+
+ // TODO remove existing savegame and reset index & savegame name
+ warning("Menu::initGame: not implemented!");
+ }
+
+ doSavegame = false;
+ } else {
+ // TODO rename saves?
+ }
+
+ // Create a new savegame if needed
+ if (!SaveLoad::isSavegamePresent(_gameId))
+ getSaveLoad()->create(_gameId);
+
+ if (doSavegame)
+ getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone);
+
+ if (!getGlobalTimer()) {
+ // TODO: remove existing savegame temp file
+ }
+
+ // Init savegame & menu values
+ _lastIndex = getSaveLoad()->init(_gameId, true);
+ _lowerTime = getSaveLoad()->getTime(_lastIndex);
+
+ if (useSameIndex)
+ _index = _lastIndex;
+
+ //if (!getGlobalTimer())
+ // _index3 = 0;
+
+ if (!getProgress().chapter)
+ getProgress().chapter = kChapter1;
+
+ getState()->time = (TimeValue)getSaveLoad()->getTime(_index);
+ getProgress().chapter = getSaveLoad()->getChapter(_index);
+
+ if (_lowerTime >= kTimeStartGame) {
+ _currentTime = (uint32)getState()->time;
+ _time = (uint32)getState()->time;
+ _clock->draw(_time);
+ _trainLine->draw(_time);
+
+ initTime(type, value);
+ }
+}
+
+// Start a game (or load an existing savegame)
+void Menu::startGame() {
+ // Clear savegame headers
+ getSaveLoad()->clear();
+
+ // Hide menu elements
+ _clock->clear();
+ _trainLine->clear();
+
+ if (_lastIndex == _index) {
+ setGlobalTimer(0);
+ if (_index) {
+ getSaveLoad()->loadGame(_gameId);
+ } else {
+ getLogic()->resetState();
+ getEntities()->setup(true, kEntityPlayer);
+ }
+ } else {
+ getSaveLoad()->loadGame(_gameId, _index);
+ }
+}
+
+// Switch to the next savegame
+void Menu::switchGame() {
+
+ // Switch back to blue game is the current game is not started
+ _gameId = SaveLoad::isSavegameValid(_gameId) ? getNextGameId() : kGameBlue;
+
+ // Initialize savegame if needed
+ if (!SaveLoad::isSavegamePresent(_gameId))
+ getSaveLoad()->create(_gameId);
+
+ getState()->time = kTimeNone;
+
+ // Clear menu elements
+ _clock->clear();
+ _trainLine->clear();
+
+ // Clear loaded savegame data
+ getSaveLoad()->clear(true);
+
+ init(false, kSavegameTypeIndex, 0);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Overlays & elements
+//////////////////////////////////////////////////////////////////////////
+void Menu::checkHotspots() {
+ if (!_isShowingMenu)
+ return;
+
+ if (!getFlags()->shouldRedraw)
+ return;
+
+ if (_isShowingCredits)
+ return;
+
+ SceneHotspot *hotspot = NULL;
+ getScenes()->get(getState()->scene)->checkHotSpot(getCoords(), &hotspot);
+
+ if (hotspot)
+ handleEvent((StartMenuAction)hotspot->action, _mouseFlags);
+ else
+ hideOverlays();
+}
+
+void Menu::hideOverlays() {
+ _lastHotspot = NULL;
+
+ // Hide all menu overlays
+ for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
+ showFrame(it->_key, -1, false);
+
+ getScenes()->drawFrames(true);
+}
+
+void Menu::showFrame(StartMenuOverlay overlayType, int index, bool redraw) {
+ if (index == -1) {
+ getScenes()->removeFromQueue(_frames[overlayType]);
+ } else {
+ // Check that the overlay is valid
+ if (!_frames[overlayType])
+ return;
+
+ // Remove the frame and add a new one with the proper index
+ getScenes()->removeFromQueue(_frames[overlayType]);
+ _frames[overlayType]->setFrame((uint16)index);
+ getScenes()->addToQueue(_frames[overlayType]);
+ }
+
+ if (redraw)
+ getScenes()->drawFrames(true);
+}
+
+// Remove all frames from the queue
+void Menu::clear() {
+ for (MenuFrames::iterator it = _frames.begin(); it != _frames.end(); it++)
+ getScenes()->removeAndRedraw(&it->_value, false);
+
+ clearBg(GraphicsManager::kBackgroundOverlay);
+}
+
+// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame
+Common::String Menu::getAcornSequenceName(GameId id) const {
+ Common::String name = "";
+ switch (id) {
+ default:
+ case kGameBlue:
+ name = "aconblu3.seq";
+ break;
+
+ case kGameRed:
+ name = "aconred.seq";
+ break;
+
+ case kGameGreen:
+ name = "acongren.seq";
+ break;
+
+ case kGamePurple:
+ name = "aconpurp.seq";
+ break;
+
+ case kGameTeal:
+ name = "aconteal.seq";
+ break;
+
+ case kGameGold:
+ name = "acongold.seq";
+ break;
+ }
+
+ return name;
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Time
+//////////////////////////////////////////////////////////////////////////
+void Menu::initTime(SavegameType type, uint32 value) {
+ if (!value)
+ return;
+
+ // The savegame entry index
+ uint32 entryIndex = 0;
+
+ switch (type) {
+ default:
+ break;
+
+ case kSavegameTypeIndex:
+ entryIndex = (_index <= value) ? 1 : _index - value;
+ break;
+
+ case kSavegameTypeTime:
+ if (value < kTimeStartGame)
+ break;
+
+ entryIndex = _index;
+ if (!entryIndex)
+ break;
+
+ // Iterate through existing entries
+ do {
+ if (getSaveLoad()->getTime(entryIndex) <= value)
+ break;
+
+ entryIndex--;
+ } while (entryIndex);
+ break;
+
+ case kSavegameTypeEvent:
+ entryIndex = _index;
+ if (!entryIndex)
+ break;
+
+ do {
+ if (getSaveLoad()->getValue(entryIndex) == value)
+ break;
+
+ entryIndex--;
+ } while (entryIndex);
+ break;
+
+ case kSavegameTypeEvent2:
+ // TODO rewrite in a more legible way
+ if (_index > 1) {
+ uint32 index = _index;
+ do {
+ if (getSaveLoad()->getValue(index) == value)
+ break;
+
+ index--;
+ } while (index > 1);
+
+ entryIndex = index - 1;
+ } else {
+ entryIndex = _index - 1;
+ }
+ break;
+ }
+
+ if (entryIndex) {
+ _currentIndex = entryIndex;
+ updateTime(getSaveLoad()->getTime(entryIndex));
+ }
+}
+
+void Menu::updateTime(uint32 time) {
+ if (_currentTime == _time)
+ _delta = 0;
+
+ _currentTime = time;
+
+ if (_time != time) {
+ if (getSound()->isBuffered(kEntityChapters))
+ getSound()->removeFromQueue(kEntityChapters);
+
+ getSound()->playSoundWithSubtitles((_currentTime >= _time) ? "LIB042" : "LIB041", SoundManager::kFlagMenuClock, kEntityChapters);
+ adjustIndex(_currentTime, _time, false);
+ }
+}
+
+void Menu::adjustIndex(uint32 time1, uint32 time2, bool searchEntry) {
+ uint32 index = 0;
+ int32 timeDelta = -1;
+
+ if (time1 != time2) {
+
+ index = _index;
+
+ if (time2 >= time1) {
+ if (searchEntry) {
+ uint32 currentIndex = _index;
+
+ if ((int32)_index >= 0) {
+ do {
+ // Calculate new delta
+ int32 newDelta = time1 - (uint32)getSaveLoad()->getTime(currentIndex);
+
+ if (newDelta >= 0 && timeDelta >= newDelta) {
+ timeDelta = newDelta;
+ index = currentIndex;
+ }
+
+ --currentIndex;
+ } while ((int32)currentIndex >= 0);
+ }
+ } else {
+ index = _index - 1;
+ }
+ } else {
+ if (searchEntry) {
+ uint32 currentIndex = _index;
+
+ if (_lastIndex >= _index) {
+ do {
+ // Calculate new delta
+ int32 newDelta = (uint32)getSaveLoad()->getTime(currentIndex) - time1;
+
+ if (newDelta >= 0 && timeDelta > newDelta) {
+ timeDelta = newDelta;
+ index = currentIndex;
+ }
+
+ ++currentIndex;
+ } while (currentIndex <= _lastIndex);
+ }
+ } else {
+ index = _index + 1;
+ }
+ }
+
+ _index = index;
+ checkHotspots();
+ }
+
+ if (_index == _currentIndex) {
+ if (getProgress().chapter != getSaveLoad()->getChapter(index))
+ getProgress().chapter = getSaveLoad()->getChapter(_index);
+ }
+}
+
+void Menu::goToTime(uint32 time) {
+
+ uint32 entryIndex = 0;
+ uint32 deltaTime = (uint32)ABS((int32)(getSaveLoad()->getTime(0) - time));
+ uint32 index = 0;
+
+ do {
+ uint32 deltaTime2 = (uint32)ABS((int32)(getSaveLoad()->getTime(index) - time));
+ if (deltaTime2 < deltaTime) {
+ deltaTime = deltaTime2;
+ entryIndex = index;
+ }
+
+ ++index;
+ } while (_lastIndex >= index);
+
+ _currentIndex = entryIndex;
+ updateTime(getSaveLoad()->getTime(entryIndex));
+}
+
+void Menu::setTime() {
+ _currentIndex = _index;
+ _currentTime = getSaveLoad()->getTime(_currentIndex);
+
+ if (_time == _currentTime)
+ adjustTime();
+}
+
+void Menu::forwardTime() {
+ if (_lastIndex <= _index)
+ return;
+
+ _currentIndex = _lastIndex;
+ updateTime(getSaveLoad()->getTime(_currentIndex));
+}
+
+void Menu::rewindTime() {
+ if (!_index)
+ return;
+
+ _currentIndex = 0;
+ updateTime(getSaveLoad()->getTime(_currentIndex));
+}
+
+void Menu::adjustTime() {
+ uint32 originalTime = _time;
+
+ // Adjust time delta
+ Common::Rational timeDelta(_delta >= 90 ? 9 : (9 * _delta + 89), _delta >= 90 ? 1 : 90);
+
+ if (_currentTime < _time) {
+ timeDelta *= 900;
+ _time -= (uint)timeDelta.toInt();
+
+ if (_currentTime > _time)
+ _time = _currentTime;
+ } else {
+ timeDelta *= 900;
+ _time += (uint)timeDelta.toInt();
+
+ if (_currentTime < _time)
+ _time = _currentTime;
+ }
+
+ if (_currentTime == _time && getSound()->isBuffered(kEntityChapters))
+ getSound()->removeFromQueue(kEntityChapters);
+
+ _clock->draw(_time);
+ _trainLine->draw(_time);
+ getScenes()->drawFrames(true);
+
+ adjustIndex(_time, originalTime, true);
+
+ ++_delta;
+}
+
+void Menu::moveToCity(CityButton city, bool clicked) {
+ uint32 time = (uint32)_cityButtonsInfo[city].time;
+
+ // TODO Check if we have access (there seems to be more checks on some internal times) - probably : current_time (menu only) / game time / some other?
+ if (_lowerTime < time || _time == time || _currentTime == time) {
+ hideOverlays();
+ return;
+ }
+
+ // Show city overlay
+ showFrame((StartMenuOverlay)((_cityButtonsInfo[city].index >> 6) + 3), _cityButtonsInfo[city].index & 63, true);
+
+ if (clicked) {
+ showFrame(kOverlayTooltip, -1, true);
+ getSound()->playSound(kEntityPlayer, "LIB046");
+ goToTime(time);
+
+ _handleTimeDelta = true;
+
+ return;
+ }
+
+ // Special case of first and last cities
+ if (city == kParis || city == kConstantinople) {
+ showFrame(kOverlayTooltip, (city == kParis) ? kTooltipRewindParis : kTooltipForwardConstantinople, true);
+ return;
+ }
+
+ showFrame(kOverlayTooltip, (_time <= time) ? _cityButtonsInfo[city].forward : _cityButtonsInfo[city].rewind, true);
+}
+
+//////////////////////////////////////////////////////////////////////////
+// Sound / Brightness
+//////////////////////////////////////////////////////////////////////////
+
+// Get current volume (converted internal ScummVM value)
+uint32 Menu::getVolume() const {
+ return getState()->volume;
+}
+
+// Set the volume (converts to ScummVM values)
+void Menu::setVolume(uint32 volume) const {
+ getState()->volume = volume;
+
+ // Clamp volume
+ uint32 value = volume * Audio::Mixer::kMaxMixerVolume / 7;
+
+ if (value > Audio::Mixer::kMaxMixerVolume)
+ value = Audio::Mixer::kMaxMixerVolume;
+
+ _engine->_mixer->setVolumeForSoundType(Audio::Mixer::kPlainSoundType, (int32)value);
+}
+
+uint32 Menu::getBrightness() const {
+ return getState()->brightness;
+}
+
+void Menu::setBrightness(uint32 brightness) const {
+ getState()->brightness = brightness;
+
+ // TODO reload cursor & font with adjusted brightness
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/menu/menu.h b/engines/lastexpress/menu/menu.h
new file mode 100644
index 0000000..4b84c06
--- /dev/null
+++ b/engines/lastexpress/menu/menu.h
@@ -0,0 +1,207 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_MENU_H
+#define LASTEXPRESS_MENU_H
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/eventhandler.h"
+
+#include "lastexpress/shared.h"
+
+#include "common/hashmap.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+class Scene;
+class SceneHotspot;
+
+class Clock;
+class TrainLine;
+
+class Menu : public EventHandler {
+public:
+ Menu(LastExpressEngine *engine);
+ ~Menu();
+
+ void show(bool doSavegame, SavegameType type, uint32 value);
+
+ // Event handling
+ void eventMouse(const Common::Event &ev);
+ void eventTick(const Common::Event &ev);
+
+ bool isShown() const { return _isShowingMenu; }
+
+ GameId getGameId() const { return _gameId; }
+
+private:
+ // Start menu events
+ enum StartMenuAction {
+ kMenuContinue = 1,
+ kMenuCredits = 2,
+ kMenuQuitGame = 3,
+ kMenuCase4 = 4,
+ kMenuSwitchSaveGame = 6,
+ kMenuRewindGame = 7,
+ kMenuForwardGame = 8,
+ kMenuParis = 10,
+ kMenuStrasBourg = 11,
+ kMenuMunich = 12,
+ kMenuVienna = 13,
+ kMenuBudapest = 14,
+ kMenuBelgrade = 15,
+ kMenuConstantinople = 16,
+ kMenuDecreaseVolume = 17,
+ kMenuIncreaseVolume = 18,
+ kMenuDecreaseBrightness = 19,
+ kMenuIncreaseBrightness = 20
+ };
+
+ // City buttons
+ enum CityButton {
+ kParis = 0,
+ kStrasbourg = 1,
+ kMunich = 2,
+ kVienna = 3,
+ kBudapest = 4,
+ kBelgrade = 5,
+ kConstantinople = 6
+ };
+
+ // Start menu overlay elements
+ enum StartMenuOverlay {
+ kOverlayTooltip, // 0
+ kOverlayEggButtons,
+ kOverlayButtons,
+ kOverlayAcorn,
+ kOverlayCity1,
+ kOverlayCity2, // 5
+ kOverlayCity3,
+ kOverlayCredits
+ };
+
+ LastExpressEngine *_engine;
+
+ // Sequences
+ Sequence *_seqTooltips;
+ Sequence *_seqEggButtons;
+ Sequence *_seqButtons;
+ Sequence *_seqAcorn;
+ Sequence *_seqCity1;
+ Sequence *_seqCity2;
+ Sequence *_seqCity3;
+ Sequence *_seqCredits;
+
+ GameId _gameId;
+
+ // Indicator to know if we need to show the start animation when showMenu is called
+ bool _hasShownStartScreen;
+ bool _hasShownIntro;
+
+ bool _isShowingCredits;
+ bool _isGameStarted;
+ bool _isShowingMenu;
+
+
+ uint16 _creditsSequenceIndex;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Event handling
+ uint32 _checkHotspotsTicks;
+ Common::EventType _mouseFlags;
+ SceneHotspot *_lastHotspot;
+
+ void init(bool doSavegame, SavegameType type, uint32 value);
+ void setup();
+ bool handleEvent(StartMenuAction action, Common::EventType type);
+ void checkHotspots();
+ void setLogicEventHandlers();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Game-related
+ void startGame();
+ void switchGame();
+
+ //////////////////////////////////////////////////////////////////////////
+ // Overlays & elements
+ Clock *_clock;
+ TrainLine *_trainLine;
+
+ struct MenuOverlays_EqualTo {
+ bool operator()(const StartMenuOverlay &x, const StartMenuOverlay &y) const { return x == y; }
+ };
+
+ struct MenuOverlays_Hash {
+ uint operator()(const StartMenuOverlay &x) const { return x; }
+ };
+
+ typedef Common::HashMap<StartMenuOverlay, SequenceFrame *, MenuOverlays_Hash, MenuOverlays_EqualTo> MenuFrames;
+
+ MenuFrames _frames;
+
+ void hideOverlays();
+ void showFrame(StartMenuOverlay overlay, int index, bool redraw);
+
+ void clear();
+
+ // TODO: remove?
+ void moveToCity(CityButton city, bool clicked);
+
+ //////////////////////////////////////////////////////////////////////////
+ // Misc
+ Common::String getAcornSequenceName(GameId id) const;
+
+ //////////////////////////////////////////////////////////////////////////
+ // Time
+ uint32 _currentTime; // current game time
+ uint32 _lowerTime; // lower time value
+ uint32 _time;
+
+ uint32 _currentIndex; // current savegame entry
+ uint32 _index;
+ uint32 _lastIndex;
+ uint32 _delta;
+ bool _handleTimeDelta;
+
+ void initTime(SavegameType type, uint32 val);
+ void updateTime(uint32 time);
+ void adjustTime();
+ void adjustIndex(uint32 time1, uint32 time2, bool searchEntry);
+ void goToTime(uint32 time);
+ void setTime();
+ void forwardTime();
+ void rewindTime();
+ bool hasTimeDelta() { return (_currentTime - _time) >= 1; }
+
+ //////////////////////////////////////////////////////////////////////////
+ // Sound/Brightness related
+ uint32 getVolume() const;
+ void setVolume(uint32 volume) const;
+ uint32 getBrightness() const;
+ void setBrightness(uint32 brightness) const;
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_MENU_H
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index e811519..e38772a 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -57,13 +57,13 @@ MODULE_OBJS := \
game/entities.o \
game/inventory.o \
game/logic.o \
- game/menu.o \
game/object.o \
game/savegame.o \
game/savepoint.o \
game/scenes.o \
game/sound.o \
game/state.o \
+ menu/menu.o \
debug.o \
detection.o \
graphics.o \
Commit: 7a96e0bfb67e9b5b8c0aa9bdae8415fb98214c3f
https://github.com/scummvm/scummvm/commit/7a96e0bfb67e9b5b8c0aa9bdae8415fb98214c3f
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-23T05:52:45-07:00
Commit Message:
LASTEXPRESS: Extract Clock and TrainLine classes to separate files
Changed paths:
A engines/lastexpress/menu/clock.cpp
A engines/lastexpress/menu/clock.h
A engines/lastexpress/menu/trainline.cpp
A engines/lastexpress/menu/trainline.h
engines/lastexpress/menu/menu.cpp
engines/lastexpress/module.mk
diff --git a/engines/lastexpress/menu/clock.cpp b/engines/lastexpress/menu/clock.cpp
new file mode 100644
index 0000000..b0e6a26
--- /dev/null
+++ b/engines/lastexpress/menu/clock.cpp
@@ -0,0 +1,106 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/menu/clock.h"
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/scenes.h"
+#include "lastexpress/game/state.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) {
+ _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
+ _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
+ _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
+ _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
+}
+
+Clock::~Clock() {
+ SAFE_DELETE(_frameMinutes);
+ SAFE_DELETE(_frameHour);
+ SAFE_DELETE(_frameSun);
+ SAFE_DELETE(_frameDate);
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+void Clock::clear() {
+ getScenes()->removeFromQueue(_frameMinutes);
+ getScenes()->removeFromQueue(_frameHour);
+ getScenes()->removeFromQueue(_frameSun);
+ getScenes()->removeFromQueue(_frameDate);
+}
+
+void Clock::draw(uint32 time) {
+ assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
+
+ // Check that sequences have been loaded
+ if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
+ error("Clock::process: clock sequences have not been loaded correctly!");
+
+ // Clear existing frames
+ clear();
+
+ // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914
+ // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914
+ // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins
+
+ // 15 = 1 second
+ // 15 * 60 = 900 = 1 minute
+ // 900 * 60 = 54000 = 1 hour
+ // 54000 * 24 = 1296000 = 1 day
+
+ // Calculate each sequence index from the current time
+
+ uint8 hour = 0;
+ uint8 minute = 0;
+ State::getHourMinutes(time, &hour, &minute);
+ uint32 index_date = 18 * time / 1296000;
+ if (hour == 23)
+ index_date += 18 * minute / 60;
+
+ // Set sequences frames
+ _frameMinutes->setFrame(minute);
+ _frameHour->setFrame((5 * hour + minute / 12) % 60);
+ _frameSun->setFrame((5 * hour + minute / 12) % 120);
+ _frameDate->setFrame((uint16)index_date);
+
+ // Adjust z-order and queue
+ _frameMinutes->getInfo()->location = 1;
+ _frameHour->getInfo()->location = 1;
+ _frameSun->getInfo()->location = 1;
+ _frameDate->getInfo()->location = 1;
+
+ getScenes()->addToQueue(_frameMinutes);
+ getScenes()->addToQueue(_frameHour);
+ getScenes()->addToQueue(_frameSun);
+ getScenes()->addToQueue(_frameDate);
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/menu/clock.h b/engines/lastexpress/menu/clock.h
new file mode 100644
index 0000000..339a186
--- /dev/null
+++ b/engines/lastexpress/menu/clock.h
@@ -0,0 +1,53 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_CLOCK_H
+#define LASTEXPRESS_CLOCK_H
+
+#include "common/scummsys.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+class SequenceFrame;
+
+class Clock {
+public:
+ explicit Clock(LastExpressEngine *engine);
+ ~Clock();
+
+ void draw(uint32 time);
+ void clear();
+
+private:
+ LastExpressEngine *_engine;
+
+ // Frames
+ SequenceFrame *_frameMinutes;
+ SequenceFrame *_frameHour;
+ SequenceFrame *_frameSun;
+ SequenceFrame *_frameDate;
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_CLOCK_H
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index b7e6a14..e55a6d5 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -38,6 +38,9 @@
#include "lastexpress/game/sound.h"
#include "lastexpress/game/state.h"
+#include "lastexpress/menu/clock.h"
+#include "lastexpress/menu/trainline.h"
+
#include "lastexpress/graphics.h"
#include "lastexpress/helpers.h"
#include "lastexpress/lastexpress.h"
@@ -119,45 +122,6 @@ enum StartMenuTooltips {
//////////////////////////////////////////////////////////////////////////
// DATA
//////////////////////////////////////////////////////////////////////////
-
-// Information about the cities on the train line
-static const struct {
- uint8 frame;
- TimeValue time;
-} _trainCities[31] = {
- {0, kTimeCityParis},
- {9, kTimeCityEpernay},
- {11, kTimeCityChalons},
- {16, kTimeCityBarLeDuc},
- {21, kTimeCityNancy},
- {25, kTimeCityLuneville},
- {35, kTimeCityAvricourt},
- {37, kTimeCityDeutschAvricourt},
- {40, kTimeCityStrasbourg},
- {53, kTimeCityBadenOos},
- {56, kTimeCityKarlsruhe},
- {60, kTimeCityStuttgart},
- {63, kTimeCityGeislingen},
- {66, kTimeCityUlm},
- {68, kTimeCityAugsburg},
- {73, kTimeCityMunich},
- {84, kTimeCitySalzbourg},
- {89, kTimeCityAttnangPuchheim},
- {97, kTimeCityWels},
- {100, kTimeCityLinz},
- {104, kTimeCityAmstetten},
- {111, kTimeCityVienna},
- {120, kTimeCityPoszony},
- {124, kTimeCityGalanta},
- {132, kTimeCityBudapest},
- {148, kTimeCityBelgrade},
- /* Line 1 ends at 150 - line 2 begins at 0 */
- {157, kTimeCityNish},
- {165, kTimeCityTzaribrod},
- {174, kTimeCitySofia},
- {198, kTimeCityAdrianople},
- {210, kTimeCityConstantinople}};
-
static const struct {
TimeValue time;
uint index;
@@ -174,185 +138,6 @@ static const struct {
};
//////////////////////////////////////////////////////////////////////////
-// Clock
-//////////////////////////////////////////////////////////////////////////
-class Clock {
-public:
- explicit Clock(LastExpressEngine *engine);
- ~Clock();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameMinutes;
- SequenceFrame *_frameHour;
- SequenceFrame *_frameSun;
- SequenceFrame *_frameDate;
-};
-
-Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(NULL), _frameHour(NULL), _frameSun(NULL), _frameDate(NULL) {
- _frameMinutes = new SequenceFrame(loadSequence("eggmin.seq"), 0, true);
- _frameHour = new SequenceFrame(loadSequence("egghour.seq"), 0, true);
- _frameSun = new SequenceFrame(loadSequence("sun.seq"), 0, true);
- _frameDate = new SequenceFrame(loadSequence("datenew.seq"), 0, true);
-}
-
-Clock::~Clock() {
- SAFE_DELETE(_frameMinutes);
- SAFE_DELETE(_frameHour);
- SAFE_DELETE(_frameSun);
- SAFE_DELETE(_frameDate);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void Clock::clear() {
- getScenes()->removeFromQueue(_frameMinutes);
- getScenes()->removeFromQueue(_frameHour);
- getScenes()->removeFromQueue(_frameSun);
- getScenes()->removeFromQueue(_frameDate);
-}
-
-void Clock::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameMinutes || !_frameHour || !_frameSun || !_frameDate)
- error("Clock::process: clock sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Game starts at: 1037700 = 7:13 p.m. on July 24, 1914
- // Game ends at: 4941000 = 7:30 p.m. on July 26, 1914
- // Game lasts for: 3903300 = 2 days + 17 mins = 2897 mins
-
- // 15 = 1 second
- // 15 * 60 = 900 = 1 minute
- // 900 * 60 = 54000 = 1 hour
- // 54000 * 24 = 1296000 = 1 day
-
- // Calculate each sequence index from the current time
-
- uint8 hour = 0;
- uint8 minute = 0;
- State::getHourMinutes(time, &hour, &minute);
- uint32 index_date = 18 * time / 1296000;
- if (hour == 23)
- index_date += 18 * minute / 60;
-
- // Set sequences frames
- _frameMinutes->setFrame(minute);
- _frameHour->setFrame((5 * hour + minute / 12) % 60);
- _frameSun->setFrame((5 * hour + minute / 12) % 120);
- _frameDate->setFrame((uint16)index_date);
-
- // Adjust z-order and queue
- _frameMinutes->getInfo()->location = 1;
- _frameHour->getInfo()->location = 1;
- _frameSun->getInfo()->location = 1;
- _frameDate->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameMinutes);
- getScenes()->addToQueue(_frameHour);
- getScenes()->addToQueue(_frameSun);
- getScenes()->addToQueue(_frameDate);
-}
-
-//////////////////////////////////////////////////////////////////////////
-// TrainLine
-//////////////////////////////////////////////////////////////////////////
-class TrainLine {
-public:
- explicit TrainLine(LastExpressEngine *engine);
- ~TrainLine();
-
- void draw(uint32 time);
- void clear();
-
-private:
- LastExpressEngine *_engine;
-
- // Frames
- SequenceFrame *_frameLine1;
- SequenceFrame *_frameLine2;
-};
-
-TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) {
- _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true);
- _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true);
-}
-
-TrainLine::~TrainLine() {
- SAFE_DELETE(_frameLine1);
- SAFE_DELETE(_frameLine2);
-
- // Zero passed pointers
- _engine = NULL;
-}
-
-void TrainLine::clear() {
- getScenes()->removeFromQueue(_frameLine1);
- getScenes()->removeFromQueue(_frameLine2);
-}
-
-// Draw the train line at the time
-// line1: 150 frames (=> Belgrade)
-// line2: 61 frames (=> Constantinople)
-void TrainLine::draw(uint32 time) {
- assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
-
- // Check that sequences have been loaded
- if (!_frameLine1 || !_frameLine2)
- error("TrainLine::process: Line sequences have not been loaded correctly!");
-
- // Clear existing frames
- clear();
-
- // Get the index of the last city the train has visited
- uint index = 0;
- for (uint i = 0; i < ARRAYSIZE(_trainCities); i++)
- if ((uint32)_trainCities[i].time <= time)
- index = i;
-
- uint16 frame;
- if (time > (uint32)_trainCities[index].time) {
- // Interpolate linearly to use a frame between the cities
- uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame;
- uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time);
- uint traveledTime = (time - (uint)_trainCities[index].time);
- frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities);
- } else {
- // Exactly on the city
- frame = _trainCities[index].frame;
- }
-
- // Set frame, z-order and queue
- if (frame < 150) {
- _frameLine1->setFrame(frame);
-
- _frameLine1->getInfo()->location = 1;
- getScenes()->addToQueue(_frameLine1);
- } else {
- // We passed Belgrade
- _frameLine1->setFrame(149);
- _frameLine2->setFrame(frame - 150);
-
- _frameLine1->getInfo()->location = 1;
- _frameLine2->getInfo()->location = 1;
-
- getScenes()->addToQueue(_frameLine1);
- getScenes()->addToQueue(_frameLine2);
- }
-}
-
-
-//////////////////////////////////////////////////////////////////////////
// Menu
//////////////////////////////////////////////////////////////////////////
Menu::Menu(LastExpressEngine *engine) : _engine(engine),
diff --git a/engines/lastexpress/menu/trainline.cpp b/engines/lastexpress/menu/trainline.cpp
new file mode 100644
index 0000000..df08abf
--- /dev/null
+++ b/engines/lastexpress/menu/trainline.cpp
@@ -0,0 +1,142 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "lastexpress/menu/trainline.h"
+
+#include "lastexpress/data/sequence.h"
+
+#include "lastexpress/game/scenes.h"
+
+#include "lastexpress/helpers.h"
+#include "lastexpress/lastexpress.h"
+#include "lastexpress/resource.h"
+
+namespace LastExpress {
+
+// Information about the cities on the train line
+static const struct {
+ uint8 frame;
+ TimeValue time;
+} _trainCities[31] = {
+ {0, kTimeCityParis},
+ {9, kTimeCityEpernay},
+ {11, kTimeCityChalons},
+ {16, kTimeCityBarLeDuc},
+ {21, kTimeCityNancy},
+ {25, kTimeCityLuneville},
+ {35, kTimeCityAvricourt},
+ {37, kTimeCityDeutschAvricourt},
+ {40, kTimeCityStrasbourg},
+ {53, kTimeCityBadenOos},
+ {56, kTimeCityKarlsruhe},
+ {60, kTimeCityStuttgart},
+ {63, kTimeCityGeislingen},
+ {66, kTimeCityUlm},
+ {68, kTimeCityAugsburg},
+ {73, kTimeCityMunich},
+ {84, kTimeCitySalzbourg},
+ {89, kTimeCityAttnangPuchheim},
+ {97, kTimeCityWels},
+ {100, kTimeCityLinz},
+ {104, kTimeCityAmstetten},
+ {111, kTimeCityVienna},
+ {120, kTimeCityPoszony},
+ {124, kTimeCityGalanta},
+ {132, kTimeCityBudapest},
+ {148, kTimeCityBelgrade},
+ /* Line 1 ends at 150 - line 2 begins at 0 */
+ {157, kTimeCityNish},
+ {165, kTimeCityTzaribrod},
+ {174, kTimeCitySofia},
+ {198, kTimeCityAdrianople},
+ {210, kTimeCityConstantinople}
+};
+
+TrainLine::TrainLine(LastExpressEngine *engine) : _engine(engine), _frameLine1(NULL), _frameLine2(NULL) {
+ _frameLine1 = new SequenceFrame(loadSequence("line1.seq"), 0, true);
+ _frameLine2 = new SequenceFrame(loadSequence("line2.seq"), 0, true);
+}
+
+TrainLine::~TrainLine() {
+ SAFE_DELETE(_frameLine1);
+ SAFE_DELETE(_frameLine2);
+
+ // Zero passed pointers
+ _engine = NULL;
+}
+
+void TrainLine::clear() {
+ getScenes()->removeFromQueue(_frameLine1);
+ getScenes()->removeFromQueue(_frameLine2);
+}
+
+// Draw the train line at the time
+// line1: 150 frames (=> Belgrade)
+// line2: 61 frames (=> Constantinople)
+void TrainLine::draw(uint32 time) {
+ assert(time >= kTimeCityParis && time <= kTimeCityConstantinople);
+
+ // Check that sequences have been loaded
+ if (!_frameLine1 || !_frameLine2)
+ error("TrainLine::process: Line sequences have not been loaded correctly!");
+
+ // Clear existing frames
+ clear();
+
+ // Get the index of the last city the train has visited
+ uint index = 0;
+ for (uint i = 0; i < ARRAYSIZE(_trainCities); i++)
+ if ((uint32)_trainCities[i].time <= time)
+ index = i;
+
+ uint16 frame;
+ if (time > (uint32)_trainCities[index].time) {
+ // Interpolate linearly to use a frame between the cities
+ uint8 diffFrames = _trainCities[index + 1].frame - _trainCities[index].frame;
+ uint diffTimeCities = (uint)(_trainCities[index + 1].time - _trainCities[index].time);
+ uint traveledTime = (time - (uint)_trainCities[index].time);
+ frame = (uint16)(_trainCities[index].frame + (traveledTime * diffFrames) / diffTimeCities);
+ } else {
+ // Exactly on the city
+ frame = _trainCities[index].frame;
+ }
+
+ // Set frame, z-order and queue
+ if (frame < 150) {
+ _frameLine1->setFrame(frame);
+
+ _frameLine1->getInfo()->location = 1;
+ getScenes()->addToQueue(_frameLine1);
+ } else {
+ // We passed Belgrade
+ _frameLine1->setFrame(149);
+ _frameLine2->setFrame(frame - 150);
+
+ _frameLine1->getInfo()->location = 1;
+ _frameLine2->getInfo()->location = 1;
+
+ getScenes()->addToQueue(_frameLine1);
+ getScenes()->addToQueue(_frameLine2);
+ }
+}
+
+} // End of namespace LastExpress
diff --git a/engines/lastexpress/menu/trainline.h b/engines/lastexpress/menu/trainline.h
new file mode 100644
index 0000000..af6a121
--- /dev/null
+++ b/engines/lastexpress/menu/trainline.h
@@ -0,0 +1,51 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#ifndef LASTEXPRESS_TRAINLINE_H
+#define LASTEXPRESS_TRAINLINE_H
+
+#include "common/scummsys.h"
+
+namespace LastExpress {
+
+class LastExpressEngine;
+class SequenceFrame;
+
+class TrainLine {
+public:
+ explicit TrainLine(LastExpressEngine *engine);
+ ~TrainLine();
+
+ void draw(uint32 time);
+ void clear();
+
+private:
+ LastExpressEngine *_engine;
+
+ // Frames
+ SequenceFrame *_frameLine1;
+ SequenceFrame *_frameLine2;
+};
+
+} // End of namespace LastExpress
+
+#endif // LASTEXPRESS_TRAINLINE_H
diff --git a/engines/lastexpress/module.mk b/engines/lastexpress/module.mk
index e38772a..71d81da 100644
--- a/engines/lastexpress/module.mk
+++ b/engines/lastexpress/module.mk
@@ -63,7 +63,9 @@ MODULE_OBJS := \
game/scenes.o \
game/sound.o \
game/state.o \
+ menu/clock.o \
menu/menu.o \
+ menu/trainline.o \
debug.o \
detection.o \
graphics.o \
Commit: b694a78f62a02253bca2a5611314599ae7fce725
https://github.com/scummvm/scummvm/commit/b694a78f62a02253bca2a5611314599ae7fce725
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-23T05:52:52-07:00
Commit Message:
ANALYSIS: Add static casts to is* functions
This fixes a potential problem with passing char values that would be sign-extended and yield unexpected results.
See http://msdn.microsoft.com/en-us/library/ms245348.aspx
Changed paths:
base/commandLine.cpp
common/config-file.cpp
common/config-manager.cpp
common/str.cpp
common/xmlparser.cpp
common/xmlparser.h
engines/agi/wagparser.cpp
engines/agos/script_pn.cpp
engines/cine/detection.cpp
engines/drascula/interface.cpp
engines/hugo/parser.cpp
engines/hugo/util.cpp
engines/kyra/gui.cpp
engines/m4/dialogs.cpp
engines/parallaction/parser_br.cpp
engines/parallaction/parser_ns.cpp
engines/queen/talk.cpp
engines/sci/engine/kstring.cpp
engines/sci/graphics/text16.cpp
engines/sci/resource.cpp
engines/sci/resource_audio.cpp
engines/scumm/smush/smush_player.cpp
engines/scumm/string.cpp
engines/sky/detection.cpp
engines/sword1/animation.cpp
engines/sword25/util/lua/llex.cpp
engines/touche/menu.cpp
graphics/font.cpp
diff --git a/base/commandLine.cpp b/base/commandLine.cpp
index 6cb8585..2620d69 100644
--- a/base/commandLine.cpp
+++ b/base/commandLine.cpp
@@ -279,7 +279,7 @@ void registerDefaults() {
// resp. between "--some-option" and "--no-some-option".
#define DO_OPTION_BOOL(shortCmd, longCmd) \
if (isLongCmd ? (!strcmp(s+2, longCmd) || !strcmp(s+2, "no-"longCmd)) : (tolower(s[1]) == shortCmd)) { \
- bool boolValue = (islower(s[1]) != 0); \
+ bool boolValue = (islower(static_cast<unsigned char>(s[1])) != 0); \
s += 2; \
if (isLongCmd) { \
boolValue = !strcmp(s, longCmd); \
diff --git a/common/config-file.cpp b/common/config-file.cpp
index 5594113..ea3feff 100644
--- a/common/config-file.cpp
+++ b/common/config-file.cpp
@@ -38,7 +38,7 @@ namespace Common {
*/
bool ConfigFile::isValidName(const Common::String &name) {
const char *p = name.c_str();
- while (*p && (isalnum(*p) || *p == '-' || *p == '_' || *p == '.'))
+ while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_' || *p == '.'))
p++;
return *p == 0;
}
@@ -116,7 +116,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
// is, verify that it only consists of alphanumerics,
// periods, dashes and underscores). Mohawk Living Books games
// can have periods in their section names.
- while (*p && (isalnum(*p) || *p == '-' || *p == '_' || *p == '.'))
+ while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_' || *p == '.'))
p++;
if (*p == '\0')
@@ -139,7 +139,7 @@ bool ConfigFile::loadFromStream(SeekableReadStream &stream) {
// Skip leading whitespaces
const char *t = line.c_str();
- while (isspace(*t))
+ while (isspace(static_cast<unsigned char>(*t)))
t++;
// Skip empty lines / lines with only whitespace
diff --git a/common/config-manager.cpp b/common/config-manager.cpp
index 3941e27..a9d8c89 100644
--- a/common/config-manager.cpp
+++ b/common/config-manager.cpp
@@ -31,7 +31,7 @@ DECLARE_SINGLETON(Common::ConfigManager);
static bool isValidDomainName(const Common::String &domName) {
const char *p = domName.c_str();
- while (*p && (isalnum(*p) || *p == '-' || *p == '_'))
+ while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_'))
p++;
return *p == 0;
}
@@ -187,7 +187,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
// Get the domain name, and check whether it's valid (that
// is, verify that it only consists of alphanumerics,
// dashes and underscores).
- while (*p && (isalnum(*p) || *p == '-' || *p == '_'))
+ while (*p && (isalnum(static_cast<unsigned char>(*p)) || *p == '-' || *p == '_'))
p++;
if (*p == '\0')
@@ -205,7 +205,7 @@ void ConfigManager::loadFromStream(SeekableReadStream &stream) {
// Skip leading whitespaces
const char *t = line.c_str();
- while (isspace(*t))
+ while (isspace(static_cast<unsigned char>(*t)))
t++;
// Skip empty lines / lines with only whitespace
diff --git a/common/str.cpp b/common/str.cpp
index a2cd4a01..32f4b44 100644
--- a/common/str.cpp
+++ b/common/str.cpp
@@ -405,7 +405,7 @@ void String::trim() {
makeUnique();
// Trim trailing whitespace
- while (_size >= 1 && isspace(_str[_size - 1]))
+ while (_size >= 1 && isspace(static_cast<unsigned char>(_str[_size - 1])))
--_size;
_str[_size] = 0;
@@ -606,14 +606,14 @@ String operator+(const String &x, char y) {
}
char *ltrim(char *t) {
- while (isspace(*t))
+ while (isspace(static_cast<unsigned char>(*t)))
t++;
return t;
}
char *rtrim(char *t) {
int l = strlen(t) - 1;
- while (l >= 0 && isspace(t[l]))
+ while (l >= 0 && isspace(static_cast<unsigned char>(t[l])))
t[l--] = 0;
return t;
}
diff --git a/common/xmlparser.cpp b/common/xmlparser.cpp
index 5217c4e..6236199 100644
--- a/common/xmlparser.cpp
+++ b/common/xmlparser.cpp
@@ -263,7 +263,7 @@ bool XMLParser::vparseIntegerKey(const char *key, int count, va_list args) {
int *num_ptr;
while (count--) {
- while (isspace(*key))
+ while (isspace(static_cast<unsigned char>(*key)))
key++;
num_ptr = va_arg(args, int*);
@@ -271,7 +271,7 @@ bool XMLParser::vparseIntegerKey(const char *key, int count, va_list args) {
key = parseEnd;
- while (isspace(*key))
+ while (isspace(static_cast<unsigned char>(*key)))
key++;
if (count && *key++ != ',')
@@ -463,10 +463,10 @@ bool XMLParser::parse() {
}
bool XMLParser::skipSpaces() {
- if (!isspace(_char))
+ if (!isspace(static_cast<unsigned char>(_char)))
return false;
- while (_char && isspace(_char))
+ while (_char && isspace(static_cast<unsigned char>(_char)))
_char = _stream->readByte();
return true;
@@ -516,7 +516,7 @@ bool XMLParser::parseToken() {
_char = _stream->readByte();
}
- return isspace(_char) != 0 || _char == '>' || _char == '=' || _char == '/';
+ return isspace(static_cast<unsigned char>(_char)) != 0 || _char == '>' || _char == '=' || _char == '/';
}
} // End of namespace Common
diff --git a/common/xmlparser.h b/common/xmlparser.h
index 7923e43..40c779b 100644
--- a/common/xmlparser.h
+++ b/common/xmlparser.h
@@ -294,7 +294,7 @@ protected:
* in their name.
*/
virtual inline bool isValidNameChar(char c) {
- return isalnum(c) || c == '_';
+ return isalnum(static_cast<unsigned char>(c)) || c == '_';
}
/**
diff --git a/engines/agi/wagparser.cpp b/engines/agi/wagparser.cpp
index 14159c0..39f9e0d 100644
--- a/engines/agi/wagparser.cpp
+++ b/engines/agi/wagparser.cpp
@@ -112,11 +112,11 @@ WagFileParser::~WagFileParser() {
bool WagFileParser::checkAgiVersionProperty(const WagProperty &version) const {
if (version.getCode() == WagProperty::PC_INTVERSION && // Must be AGI interpreter version property
version.getSize() >= 3 && // Need at least three characters for a version number like "X.Y"
- isdigit(version.getData()[0]) && // And the first character must be a digit
+ isdigit(static_cast<unsigned char>(version.getData()[0])) && // And the first character must be a digit
(version.getData()[1] == ',' || version.getData()[1] == '.')) { // And the second a comma or a period
for (int i = 2; i < version.getSize(); i++) // And the rest must all be digits
- if (!isdigit(version.getData()[i]))
+ if (!isdigit(static_cast<unsigned char>(version.getData()[i])))
return false; // Bail out if found a non-digit after the decimal point
return true;
diff --git a/engines/agos/script_pn.cpp b/engines/agos/script_pn.cpp
index bde59b7..3bd8ce1 100644
--- a/engines/agos/script_pn.cpp
+++ b/engines/agos/script_pn.cpp
@@ -465,8 +465,8 @@ void AGOSEngine_PN::opn_opcode35() {
void AGOSEngine_PN::opn_opcode36() {
for (int i = 0; i < _dataBase[57] + 1; ++i)
_wordcp[i] = 0;
- if (isspace(*_inpp))
- while ((*_inpp) && (isspace(*_inpp)))
+ if (isspace(static_cast<unsigned char>(*_inpp)))
+ while ((*_inpp) && (isspace(static_cast<unsigned char>(*_inpp))))
_inpp++;
if (*_inpp == 0) {
setScriptReturn(false);
@@ -480,7 +480,7 @@ void AGOSEngine_PN::opn_opcode36() {
}
int ct = 1;
- while ((*_inpp != '.') && (*_inpp != ',') && (!isspace(*_inpp)) && (*_inpp != '\0') &&
+ while ((*_inpp != '.') && (*_inpp != ',') && (!isspace(static_cast<unsigned char>(*_inpp))) && (*_inpp != '\0') &&
(*_inpp!='"')) {
if (ct < _dataBase[57])
_wordcp[ct++] = *_inpp;
@@ -580,7 +580,7 @@ void AGOSEngine_PN::opn_opcode46() {
return;
}
x++;
- while ((*x != '.') && (*x != ',') && (*x != '"') && (!isspace(*x)) && (*x != '\0'))
+ while ((*x != '.') && (*x != ',') && (*x != '"') && (!isspace(static_cast<unsigned char>(*x))) && (*x != '\0'))
pcf(*x++);
setScriptReturn(true);
}
diff --git a/engines/cine/detection.cpp b/engines/cine/detection.cpp
index cffeb29..ba02515 100644
--- a/engines/cine/detection.cpp
+++ b/engines/cine/detection.cpp
@@ -141,7 +141,7 @@ SaveStateList CineMetaEngine::listSaves(const char *target) const {
for (file = filenames.begin(); file != filenames.end(); ++file) {
// Jump over savegame files that don't end with a digit (e.g. "fw.3" is ok, "fw.a" is not).
- if (!isdigit(file->lastChar()))
+ if (!isdigit(static_cast<unsigned char>(file->lastChar())))
continue;
// Obtain the last digit of the filename, since they correspond to the save slot
diff --git a/engines/drascula/interface.cpp b/engines/drascula/interface.cpp
index eb36bae..e3a9708 100644
--- a/engines/drascula/interface.cpp
+++ b/engines/drascula/interface.cpp
@@ -159,7 +159,7 @@ void DrasculaEngine::enterName() {
key = getScan();
if (key != 0) {
- if (key >= 0 && key <= 0xFF && isalpha(key))
+ if (key >= 0 && key <= 0xFF && isalpha(static_cast<unsigned char>(key)))
select2[v] = tolower(key);
else if ((key >= Common::KEYCODE_0 && key <= Common::KEYCODE_9) || key == Common::KEYCODE_SPACE)
select2[v] = key;
diff --git a/engines/hugo/parser.cpp b/engines/hugo/parser.cpp
index 5cb97f2..38a8e4e 100644
--- a/engines/hugo/parser.cpp
+++ b/engines/hugo/parser.cpp
@@ -235,7 +235,7 @@ void Parser::charHandler() {
if (_cmdLineIndex >= kMaxLineSize) {
//MessageBeep(MB_ICONASTERISK);
warning("STUB: MessageBeep() - Command line too long");
- } else if (isprint(c)) {
+ } else if (isprint(static_cast<unsigned char>(c))) {
_cmdLine[_cmdLineIndex++] = c;
_cmdLine[_cmdLineIndex] = '\0';
}
diff --git a/engines/hugo/util.cpp b/engines/hugo/util.cpp
index a936a23..6dc9890 100644
--- a/engines/hugo/util.cpp
+++ b/engines/hugo/util.cpp
@@ -119,7 +119,7 @@ char *strlwr(char *buffer) {
char *result = buffer;
while (*buffer != '\0') {
- if (isupper(*buffer))
+ if (isupper(static_cast<unsigned char>(*buffer)))
*buffer = tolower(*buffer);
buffer++;
}
diff --git a/engines/kyra/gui.cpp b/engines/kyra/gui.cpp
index f58ca01..29cbe20 100644
--- a/engines/kyra/gui.cpp
+++ b/engines/kyra/gui.cpp
@@ -375,7 +375,7 @@ void GUI::updateSaveList(bool excludeQuickSaves) {
s1 = (*i)[i->size()-3];
s2 = (*i)[i->size()-2];
s3 = (*i)[i->size()-1];
- if (!isdigit(s1) || !isdigit(s2) || !isdigit(s3))
+ if (!isdigit(static_cast<unsigned char>(s1)) || !isdigit(static_cast<unsigned char>(s2)) || !isdigit(static_cast<unsigned char>(s3)))
continue;
s1 -= '0';
s2 -= '0';
diff --git a/engines/m4/dialogs.cpp b/engines/m4/dialogs.cpp
index 390ca71..2b2c479 100644
--- a/engines/m4/dialogs.cpp
+++ b/engines/m4/dialogs.cpp
@@ -265,7 +265,7 @@ void Dialog::setupInputArea() {
*/
bool Dialog::matchCommand(const char *s1, const char *s2) {
bool result = scumm_strnicmp(s1, s2, strlen(s2)) == 0;
- _commandCase = isupper(*s1);
+ _commandCase = isupper(static_cast<unsigned char>(*s1));
return result;
}
diff --git a/engines/parallaction/parser_br.cpp b/engines/parallaction/parser_br.cpp
index f53d71c..df53ecc 100644
--- a/engines/parallaction/parser_br.cpp
+++ b/engines/parallaction/parser_br.cpp
@@ -524,14 +524,14 @@ DECLARE_COMMAND_PARSER(location) {
ctxt.cmd->_startPos.x = -1000;
ctxt.cmd->_startPos2.x = -1000;
if (_tokens[ctxt.nextToken][0] != '\0') {
- if (isdigit(_tokens[ctxt.nextToken][0]) || _tokens[ctxt.nextToken][0] == '-') {
+ if (isdigit(static_cast<unsigned char>(_tokens[ctxt.nextToken][0])) || _tokens[ctxt.nextToken][0] == '-') {
ctxt.cmd->_startPos.x = atoi(_tokens[ctxt.nextToken]);
ctxt.nextToken++;
ctxt.cmd->_startPos.y = atoi(_tokens[ctxt.nextToken]);
ctxt.nextToken++;
}
- if (isdigit(_tokens[ctxt.nextToken][0]) || _tokens[ctxt.nextToken][0] == '-') {
+ if (isdigit(static_cast<unsigned char>(_tokens[ctxt.nextToken][0])) || _tokens[ctxt.nextToken][0] == '-') {
ctxt.cmd->_startPos2.x = atoi(_tokens[ctxt.nextToken]);
ctxt.nextToken++;
ctxt.cmd->_startPos2.y = atoi(_tokens[ctxt.nextToken]);
@@ -677,7 +677,7 @@ DECLARE_COMMAND_PARSER(text) {
createCommand(_parser->_lookup);
- if (isdigit(_tokens[1][1])) {
+ if (isdigit(static_cast<unsigned char>(_tokens[1][1]))) {
ctxt.cmd->_zeta0 = atoi(_tokens[1]);
ctxt.nextToken++;
} else {
@@ -714,7 +714,7 @@ DECLARE_COMMAND_PARSER(unary) {
DECLARE_ZONE_PARSER(limits) {
debugC(7, kDebugParser, "ZONE_PARSER(limits) ");
- if (isalpha(_tokens[1][1])) {
+ if (isalpha(static_cast<unsigned char>(_tokens[1][1]))) {
ctxt.z->_flags |= kFlagsAnimLinked;
ctxt.z->_linkedName = _tokens[1];
} else {
@@ -1003,7 +1003,7 @@ DECLARE_INSTRUCTION_PARSER(text) {
int _si = 1;
- if (isdigit(_tokens[1][1])) {
+ if (isdigit(static_cast<unsigned char>(_tokens[1][1]))) {
ctxt.inst->_y = atoi(_tokens[1]);
_si = 2;
} else {
@@ -1066,7 +1066,7 @@ DECLARE_INSTRUCTION_PARSER(endif) {
void ProgramParser_br::parseRValue(ScriptVar &v, const char *str) {
- if (isdigit(str[0]) || str[0] == '-') {
+ if (isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-') {
v.setImmediate(atoi(str));
return;
}
diff --git a/engines/parallaction/parser_ns.cpp b/engines/parallaction/parser_ns.cpp
index 213f0ae..100b608 100644
--- a/engines/parallaction/parser_ns.cpp
+++ b/engines/parallaction/parser_ns.cpp
@@ -534,7 +534,7 @@ DECLARE_INSTRUCTION_PARSER(endscript) {
void ProgramParser_ns::parseRValue(ScriptVar &v, const char *str) {
- if (isdigit(str[0]) || str[0] == '-') {
+ if (isdigit(static_cast<unsigned char>(str[0])) || str[0] == '-') {
v.setImmediate(atoi(str));
return;
}
diff --git a/engines/queen/talk.cpp b/engines/queen/talk.cpp
index b83bf60..1f8d9b2 100644
--- a/engines/queen/talk.cpp
+++ b/engines/queen/talk.cpp
@@ -658,7 +658,7 @@ void Talk::stringAnimation(const SpeechParameters *parameters, int startFrame, i
} else if (parameters->animation[0] == 'E') {
// Talking head animation
return;
- } else if (!isdigit(parameters->animation[0])) {
+ } else if (!isdigit(static_cast<unsigned char>(parameters->animation[0]))) {
debug(6, "Error in speak string animation: '%s'", parameters->animation);
return;
} else
diff --git a/engines/sci/engine/kstring.cpp b/engines/sci/engine/kstring.cpp
index 07b87a7..9f10691 100644
--- a/engines/sci/engine/kstring.cpp
+++ b/engines/sci/engine/kstring.cpp
@@ -238,14 +238,14 @@ reg_t kFormat(EngineState *s, int argc, reg_t *argv) {
/* int writelength; -- unused atm */
- if (xfer && (isdigit(xfer) || xfer == '-' || xfer == '=')) {
+ if (xfer && (isdigit(static_cast<unsigned char>(xfer)) || xfer == '-' || xfer == '=')) {
char *destp;
if (xfer == '0')
fillchar = '0';
else if (xfer == '=')
align = ALIGN_CENTER;
- else if (isdigit(xfer) || (xfer == '-'))
+ else if (isdigit(static_cast<unsigned char>(xfer)) || (xfer == '-'))
source--; // Go to start of length argument
str_leng = strtol(source, &destp, 10);
diff --git a/engines/sci/graphics/text16.cpp b/engines/sci/graphics/text16.cpp
index c2f71a0..84547d9 100644
--- a/engines/sci/graphics/text16.cpp
+++ b/engines/sci/graphics/text16.cpp
@@ -100,7 +100,7 @@ int16 GfxText16::CodeProcessing(const char *&text, GuiResourceId orgFontId, int1
// cX -> sets textColor to _textColors[X-1]
curCode = textCode[0];
curCodeParm = textCode[1];
- if (isdigit(curCodeParm)) {
+ if (isdigit(static_cast<unsigned char>(curCodeParm))) {
curCodeParm -= '0';
} else {
curCodeParm = -1;
diff --git a/engines/sci/resource.cpp b/engines/sci/resource.cpp
index fa70481..f18b6c9 100644
--- a/engines/sci/resource.cpp
+++ b/engines/sci/resource.cpp
@@ -1555,7 +1555,7 @@ void ResourceManager::readResourcePatches() {
name = (*x)->getName();
// SCI1 scheme
- if (isdigit(name[0])) {
+ if (isdigit(static_cast<unsigned char>(name[0]))) {
char *end = 0;
resourceNr = strtol(name.c_str(), &end, 10);
bAdd = (*end == '.'); // Ensure the next character is the period
@@ -1563,7 +1563,7 @@ void ResourceManager::readResourcePatches() {
// SCI0 scheme
int resname_len = strlen(szResType);
if (scumm_strnicmp(name.c_str(), szResType, resname_len) == 0
- && !isalpha(name[resname_len + 1])) {
+ && !isalpha(static_cast<unsigned char>(name[resname_len + 1]))) {
resourceNr = atoi(name.c_str() + resname_len + 1);
bAdd = true;
}
diff --git a/engines/sci/resource_audio.cpp b/engines/sci/resource_audio.cpp
index 032040f..f3a3c8d 100644
--- a/engines/sci/resource_audio.cpp
+++ b/engines/sci/resource_audio.cpp
@@ -197,7 +197,7 @@ void ResourceManager::readWaveAudioPatches() {
for (Common::ArchiveMemberList::const_iterator x = files.begin(); x != files.end(); ++x) {
Common::String name = (*x)->getName();
- if (isdigit(name[0]))
+ if (isdigit(static_cast<unsigned char>(name[0])))
processWavePatch(ResourceId(kResourceTypeAudio, atoi(name.c_str())), name);
}
}
diff --git a/engines/scumm/smush/smush_player.cpp b/engines/scumm/smush/smush_player.cpp
index 6650257..2f4e86b 100644
--- a/engines/scumm/smush/smush_player.cpp
+++ b/engines/scumm/smush/smush_player.cpp
@@ -90,13 +90,13 @@ public:
assert(def_end != NULL);
char *id_end = def_end;
- while (id_end >= def_start && !isdigit(*(id_end-1))) {
+ while (id_end >= def_start && !isdigit(static_cast<unsigned char>(*(id_end-1)))) {
id_end--;
}
assert(id_end > def_start);
char *id_start = id_end;
- while (isdigit(*(id_start - 1))) {
+ while (isdigit(static_cast<unsigned char>(*(id_start - 1)))) {
id_start--;
}
diff --git a/engines/scumm/string.cpp b/engines/scumm/string.cpp
index 4b3207c..2d2209c 100644
--- a/engines/scumm/string.cpp
+++ b/engines/scumm/string.cpp
@@ -1383,10 +1383,10 @@ void ScummEngine_v7::loadLanguageBundle() {
} else if (*ptr == '#') {
// Number of subtags following a given basetag. We don't need that
// information so we just skip it
- } else if (isdigit(*ptr)) {
+ } else if (isdigit(static_cast<unsigned char>(*ptr))) {
int idx = 0;
// A number (up to three digits)...
- while (isdigit(*ptr)) {
+ while (isdigit(static_cast<unsigned char>(*ptr))) {
idx = idx * 10 + (*ptr - '0');
ptr++;
}
@@ -1424,12 +1424,12 @@ void ScummEngine_v7::loadLanguageBundle() {
for (i = 0; i < _languageIndexSize; i++) {
// First 8 chars in the line give the string ID / 'tag'
int j;
- for (j = 0; j < 8 && !isspace(*ptr); j++, ptr++)
+ for (j = 0; j < 8 && !isspace(static_cast<unsigned char>(*ptr)); j++, ptr++)
_languageIndex[i].tag[j] = toupper(*ptr);
_languageIndex[i].tag[j] = 0;
// After that follows a single space which we skip
- assert(isspace(*ptr));
+ assert(isspace(static_cast<unsigned char>(*ptr)));
ptr++;
// Then comes the translated string: we record an offset to that.
diff --git a/engines/sky/detection.cpp b/engines/sky/detection.cpp
index f3cce06..a106749 100644
--- a/engines/sky/detection.cpp
+++ b/engines/sky/detection.cpp
@@ -206,7 +206,7 @@ SaveStateList SkyMetaEngine::listSaves(const char *target) const {
// Extract the extension
Common::String ext = file->c_str() + file->size() - 3;
ext.toUppercase();
- if (isdigit(ext[0]) && isdigit(ext[1]) && isdigit(ext[2])){
+ if (isdigit(static_cast<unsigned char>(ext[0])) && isdigit(static_cast<unsigned char>(ext[1])) && isdigit(static_cast<unsigned char>(ext[2]))){
int slotNum = atoi(ext.c_str());
Common::InSaveFile *in = saveFileMan->openForLoading(*file);
if (in) {
diff --git a/engines/sword1/animation.cpp b/engines/sword1/animation.cpp
index 4ce3e2e..f19efd2 100644
--- a/engines/sword1/animation.cpp
+++ b/engines/sword1/animation.cpp
@@ -114,7 +114,7 @@ bool MoviePlayer::load(uint32 id) {
int startFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);
int endFrame = strtoul(ptr, const_cast<char **>(&ptr), 10);
- while (*ptr && isspace(*ptr))
+ while (*ptr && isspace(static_cast<unsigned char>(*ptr)))
ptr++;
if (startFrame > endFrame) {
diff --git a/engines/sword25/util/lua/llex.cpp b/engines/sword25/util/lua/llex.cpp
index 4d73a6a..b456ee2 100644
--- a/engines/sword25/util/lua/llex.cpp
+++ b/engines/sword25/util/lua/llex.cpp
@@ -188,7 +188,7 @@ static void trydecpoint (LexState *ls, SemInfo *seminfo) {
sprintf(buf, "%.1f", 1.0);
ls->decpoint = '.';
for (i = 0; buf[i]; i++) {
- if (!isspace(buf[i]) && !isdigit(buf[i])) {
+ if (!isspace(static_cast<unsigned char>(buf[i])) && !isdigit(static_cast<unsigned char>(buf[i]))) {
ls->decpoint = buf[i];
break;
}
diff --git a/engines/touche/menu.cpp b/engines/touche/menu.cpp
index f469a95..c58e2f1 100644
--- a/engines/touche/menu.cpp
+++ b/engines/touche/menu.cpp
@@ -103,7 +103,7 @@ struct MenuData {
void addCharToDescription(int slot, char chr) {
char *description = saveLoadDescriptionsTable[slot];
int descriptionLen = strlen(description);
- if (descriptionLen < 32 && isprint(chr)) {
+ if (descriptionLen < 32 && isprint(static_cast<unsigned char>(chr))) {
description[descriptionLen] = chr;
description[descriptionLen + 1] = 0;
}
diff --git a/graphics/font.cpp b/graphics/font.cpp
index d254c64..0c180ee 100644
--- a/graphics/font.cpp
+++ b/graphics/font.cpp
@@ -948,7 +948,7 @@ int Font::wordWrapText(const Common::String &str, int maxWidth, Common::Array<Co
if (lineWidth > 0) {
wrapper.add(line, lineWidth);
// Trim left side
- while (tmpStr.size() && isspace(tmpStr[0])) {
+ while (tmpStr.size() && isspace(static_cast<unsigned char>(tmpStr[0]))) {
tmpWidth -= getCharWidth(tmpStr[0]);
tmpStr.deleteChar(0);
}
Commit: 712af61f76148095cd3b8762eeb2b2b10502df1f
https://github.com/scummvm/scummvm/commit/712af61f76148095cd3b8762eeb2b2b10502df1f
Author: Littleboy (littleboy at users.sourceforge.net)
Date: 2011-06-23T05:52:54-07:00
Commit Message:
BACKENDS: Silence warnings when compiling Win32TaskbarManager with mingw and add CLSID_ShellLink definition
Changed paths:
backends/taskbar/win32/mingw-compat.h
diff --git a/backends/taskbar/win32/mingw-compat.h b/backends/taskbar/win32/mingw-compat.h
index bf03db9..30ce818 100644
--- a/backends/taskbar/win32/mingw-compat.h
+++ b/backends/taskbar/win32/mingw-compat.h
@@ -45,10 +45,10 @@
#include <shlguid.h>
#define CMIC_MASK_ASYNCOK SEE_MASK_ASYNCOK
-// Misc enumeration values
-#ifndef SHARD_LINK
+extern const GUID CLSID_ShellLink;
+
+// Shard enumeration value
#define SHARD_LINK 0x00000006
-#endif
// Taskbar GUID definitions
DEFINE_GUID(CLSID_TaskbarList,0x56fdf344,0xfd6d,0x11d0,0x95,0x8a,0x0,0x60,0x97,0xc9,0xa0,0x90);
@@ -73,6 +73,9 @@ DECLARE_INTERFACE_(IPropertyStore, IUnknown) {
STDMETHOD (GetValue) (REFPROPERTYKEY key, PROPVARIANT *pv) PURE;
STDMETHOD (SetValue) (REFPROPERTYKEY key, REFPROPVARIANT propvar) PURE;
STDMETHOD (Commit) (void) PURE;
+
+private:
+ ~IPropertyStore();
};
typedef IPropertyStore *LPIPropertyStore;
@@ -137,6 +140,9 @@ DECLARE_INTERFACE_(ITaskbarList3, IUnknown) {
STDMETHOD (SetOverlayIcon) (THIS_ HWND hwnd, HICON hIcon, LPCWSTR pszDescription) PURE;
STDMETHOD (SetThumbnailTooltip) (THIS_ HWND hwnd, LPCWSTR pszTip) PURE;
STDMETHOD (SetThumbnailClip) (THIS_ HWND hwnd, RECT *prcClip) PURE;
+
+private:
+ ~ITaskbarList3();
};
typedef ITaskbarList3 *LPITaskbarList3;
More information about the Scummvm-git-logs
mailing list