[Scummvm-git-logs] scummvm master -> 7c2d841d3d99478de0641ed6c39c21823fde3a64
sev-
noreply at scummvm.org
Sat Apr 29 11:08:32 UTC 2023
This automated email contains information about 3 new commits which have been
pushed to the 'scummvm' repo located at https://github.com/scummvm/scummvm .
Summary:
9ddd5b5f74 LASTEXPRESS: Differentiate saved games per target
62d619e55e LASTEXPRESS: Fix compiler warnings and a bad index for entities array
7c2d841d3d LASTEXPRESS: Early support for demo
Commit: 9ddd5b5f7431aa31a62ca0bef9d83627eacbd7ee
https://github.com/scummvm/scummvm/commit/9ddd5b5f7431aa31a62ca0bef9d83627eacbd7ee
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-04-29T13:08:27+02:00
Commit Message:
LASTEXPRESS: Differentiate saved games per target
Saved games still maintain the suffix blue.egg, red.egg, etc but the prefix depends on the current game target
Also support listing of saves, loading from launcher and removal
Changed paths:
engines/lastexpress/game/savegame.cpp
engines/lastexpress/game/savegame.h
engines/lastexpress/lastexpress.cpp
engines/lastexpress/lastexpress.h
engines/lastexpress/menu/menu.cpp
engines/lastexpress/metaengine.cpp
engines/lastexpress/shared.h
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 6e4a3a3e2e7..41e843bba6f 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -36,19 +36,20 @@
#include "lastexpress/lastexpress.h"
#include "common/file.h"
+#include "common/savefile.h"
namespace LastExpress {
-// Names of savegames
+// Labels of savegames
static const struct {
- const char *saveFile;
-} gameInfo[6] = {
- {"lastexpress-blue.egg"},
- {"lastexpress-red.egg"},
- {"lastexpress-green.egg"},
- {"lastexpress-purple.egg"},
- {"lastexpress-teal.egg"},
- {"lastexpress-gold.egg"}
+ const char *label;
+} gameLabel[SaveLoad::kMaximumSaveSlots] = {
+ {"blue"},
+ {"red"},
+ {"green"},
+ {"purple"},
+ {"teal"},
+ {"gold"}
};
//////////////////////////////////////////////////////////////////////////
@@ -361,10 +362,10 @@ void SaveLoad::initStream() {
_savegame = new SavegameStream();
}
-void SaveLoad::flushStream(GameId id) {
- Common::OutSaveFile *save = openForSaving(id);
+void SaveLoad::flushStream(const Common::String &target, GameId id) {
+ Common::OutSaveFile *save = openForSaving(target, id);
if (!save)
- error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(id).c_str());
+ error("[SaveLoad::flushStream] Cannot open savegame (%s)", getFilename(target, id).c_str());
if (!_savegame)
error("[SaveLoad::flushStream] Savegame stream is invalid");
@@ -378,21 +379,20 @@ void SaveLoad::flushStream(GameId id) {
//////////////////////////////////////////////////////////////////////////
// Init
//////////////////////////////////////////////////////////////////////////
-void SaveLoad::create(GameId id) {
+void SaveLoad::create(const Common::String &target, GameId id) {
initStream();
Common::Serializer ser(nullptr, _savegame);
SavegameMainHeader header;
header.saveLoadWithSerializer(ser);
-
- flushStream(id);
+ flushStream(target, id);
}
-uint32 SaveLoad::init(GameId id, bool resetHeaders) {
+uint32 SaveLoad::init(const Common::String &target, GameId id, bool resetHeaders) {
initStream();
// Load game data
- loadStream(id);
+ loadStream(target, id);
// Get the main header
Common::Serializer ser(_savegame, nullptr);
@@ -435,8 +435,8 @@ uint32 SaveLoad::init(GameId id, bool resetHeaders) {
return mainHeader.count;
}
-void SaveLoad::loadStream(GameId id) {
- Common::InSaveFile *save = openForLoading(id);
+void SaveLoad::loadStream(const Common::String &target, GameId id) {
+ Common::InSaveFile *save = openForLoading(target, id);
if (save->size() < 32)
error("[SaveLoad::loadStream] Savegame seems to be corrupted (not enough data: %i bytes)", (int)save->size());
@@ -490,7 +490,7 @@ void SaveLoad::loadLastGame() {
// Validate main header
SavegameMainHeader header;
if (!loadMainHeader(_savegame, &header)) {
- debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(_engine->getTargetName(), getMenu()->getGameId()).c_str());
return;
}
@@ -510,7 +510,6 @@ void SaveLoad::loadLastGame() {
readEntry(&type, &entity, &val, false);
}
-
getEntities()->reset();
getEntities()->setup(false, entity);
}
@@ -550,7 +549,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
// Validate main header
SavegameMainHeader header;
if (!loadMainHeader(_savegame, &header)) {
- debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(getMenu()->getGameId()).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot load main header: %s", getFilename(_engine->getTargetName(), getMenu()->getGameId()).c_str());
return;
}
@@ -612,7 +611,7 @@ void SaveLoad::saveGame(SavegameType type, EntityIndex entity, uint32 value) {
Common::Serializer ser(nullptr, _savegame);
header.saveLoadWithSerializer(ser);
- flushStream(getMenu()->getGameId());
+ flushStream(_engine->getTargetName(), getMenu()->getGameId());
}
void SaveLoad::saveVolumeBrightness() {
@@ -799,7 +798,12 @@ void SaveLoad::readEntry(SavegameType *type, EntityIndex *entity, uint32 *val, b
// Skip padding
uint32 offset = (uint32)_savegame->pos() - originalPosition;
if (offset & 0xF) {
- _savegame->seek((~offset & 0xF) + 1, SEEK_CUR);
+ // (offset & 0xF) is a value in [0, 15]; the remainder of division of offset with 16.
+ // Entering here, that remainder is not zero so, with the following code, we skip the padding
+ // by seeking ahead (forward) from SEEK_CUR for the amount of the bytes required to complete
+ // a full 16 bytes final segment for the entity entry that we are reading.
+ // That is: 16 - (offset & 0xF) or equivalently: (~offset & 0xF) + 1) bytes skipped ahead.
+ _savegame->seek(16 - (offset & 0xF), SEEK_CUR);
}
}
@@ -810,28 +814,53 @@ SaveLoad::SavegameEntryHeader *SaveLoad::getEntry(uint32 index) {
return _gameHeaders[index];
}
+SaveStateList SaveLoad::list(const MetaEngine *metaEngine, const Common::String &target) {
+ Common::SaveFileManager *saveFileMan = g_system->getSavefileManager();
+ Common::StringArray files = saveFileMan->listSavefiles(target + "*.egg");
+
+ SaveStateList saveList;
+ for (Common::StringArray::const_iterator fileName = files.begin(); fileName != files.end(); ++fileName) {
+ for (int i = 0; i < kMaximumSaveSlots; ++i) {
+ // Do another more accurate filtering (than the more generic pattern used with listSavefiles() above)
+ // of save file names here
+ if (*fileName == getFilename(target, (GameId)i)) {
+ Common::InSaveFile *saveFile = saveFileMan->openForLoading(*fileName);
+ if (saveFile != nullptr && !saveFile->err()) {
+ saveList.push_back(SaveStateDescriptor(metaEngine, i, gameLabel[i].label));
+ }
+ delete saveFile;
+ break;
+ }
+ }
+ }
+
+ Common::sort(saveList.begin(), saveList.end(), SaveStateDescriptorSlotComparator());
+
+ return saveList;
+}
+
//////////////////////////////////////////////////////////////////////////
// Checks
//////////////////////////////////////////////////////////////////////////
// Check if a specific savegame exists
-bool SaveLoad::isSavegamePresent(GameId id) {
- if (g_system->getSavefileManager()->listSavefiles(getFilename(id)).size() == 0)
+bool SaveLoad::isSavegamePresent(const Common::String &target, GameId id) {
+ if (g_system->getSavefileManager()->listSavefiles(getFilename(target, id)).size() == 0)
return false;
return true;
}
// Check if the game has been started in the specific savegame
-bool SaveLoad::isSavegameValid(GameId id) {
- if (!isSavegamePresent(id)) {
- debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(id).c_str());
+bool SaveLoad::isSavegameValid(const Common::String &target, GameId id) {
+ if (!isSavegamePresent(target, id)) {
+ debugC(2, kLastExpressDebugSavegame, "Savegame does not exist: %s", getFilename(target, id).c_str());
return false;
}
SavegameMainHeader header;
- Common::InSaveFile *save = openForLoading(id);
+ Common::InSaveFile *save = openForLoading(target, id);
bool isHeaderValid = loadMainHeader(save, &header);
delete save;
@@ -886,29 +915,34 @@ bool SaveLoad::isGameFinished(uint32 menuIndex, uint32 savegameIndex) {
//////////////////////////////////////////////////////////////////////////
// Get the file name from the savegame ID
-Common::String SaveLoad::getFilename(GameId id) {
- if (id >= 6)
- error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - 5, was %d", id);
+Common::String SaveLoad::getFilename(const Common::String &target, GameId id) {
+ if (id < 0 || id >= kMaximumSaveSlots)
+ error("[SaveLoad::getFilename] Attempting to use an invalid game id. Valid values: 0 - %d, was %d", kMaximumSaveSlots - 1, id);
- return gameInfo[id].saveFile;
+ return target + "-" + gameLabel[id].label + ".egg";
}
-Common::InSaveFile *SaveLoad::openForLoading(GameId id) {
- Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(id));
+Common::InSaveFile *SaveLoad::openForLoading(const Common::String &target, GameId id) {
+ Common::InSaveFile *load = g_system->getSavefileManager()->openForLoading(getFilename(target, id));
if (!load)
- debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(id).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for loading: %s", getFilename(target, id).c_str());
return load;
}
-Common::OutSaveFile *SaveLoad::openForSaving(GameId id) {
- Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(id), false); // TODO Enable compression again
+Common::OutSaveFile *SaveLoad::openForSaving(const Common::String &target, GameId id) {
+ Common::OutSaveFile *save = g_system->getSavefileManager()->openForSaving(getFilename(target, id), false); // TODO Enable compression again
if (!save)
- debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(id).c_str());
+ debugC(2, kLastExpressDebugSavegame, "Cannot open savegame for writing: %s", getFilename(target, id).c_str());
return save;
}
+void SaveLoad::remove(const Common::String &target, GameId id) {
+ Common::String filename = getFilename(target, id);
+ g_system->getSavefileManager()->removeSavefile(filename);
+}
+
} // End of namespace LastExpress
diff --git a/engines/lastexpress/game/savegame.h b/engines/lastexpress/game/savegame.h
index 3afe284d4e4..2f7152ccc34 100644
--- a/engines/lastexpress/game/savegame.h
+++ b/engines/lastexpress/game/savegame.h
@@ -76,6 +76,8 @@
#include "common/serializer.h"
#include "common/memstream.h"
+#include "engines/savestate.h"
+
namespace LastExpress {
// our own hack until compression code will be confirmed stable
@@ -146,13 +148,15 @@ private:
class SaveLoad {
public:
+ static const int kMaximumSaveSlots = 6; // blue, red, green, purple, teal, gold
+
SaveLoad(LastExpressEngine *engine);
~SaveLoad();
// Init
- void create(GameId id);
+ void create(const Common::String &target, GameId id);
void clear(bool clearStream = false);
- uint32 init(GameId id, bool resetHeaders);
+ uint32 init(const Common::String &target, GameId id, bool resetHeaders);
// Save & Load
void loadLastGame();
@@ -162,9 +166,17 @@ public:
void loadVolumeBrightness();
void saveVolumeBrightness();
+ static SaveStateList list(const MetaEngine *metaEngine, const Common::String &target);
+ static void remove(const Common::String &target, GameId slot);
+
+ // Opening save files
+ static Common::String getFilename(const Common::String &target, GameId slot);
+ static Common::InSaveFile *openForLoading(const Common::String &target, GameId slot);
+ static Common::OutSaveFile *openForSaving(const Common::String &target, GameId slot);
+
// Getting information
- static bool isSavegamePresent(GameId id);
- static bool isSavegameValid(GameId id);
+ static bool isSavegamePresent(const Common::String &target, GameId id);
+ static bool isSavegameValid(const Common::String &target, GameId id);
bool isGameFinished(uint32 menuIndex, uint32 savegameIndex);
@@ -195,7 +207,7 @@ private:
keepIndex = 0;
brightness = 3;
volume = 7;
- field_1C = 9;
+ field_1C = 9; // Note: In demo's original save "BLUE.EGG" this value is 0x19
}
void saveLoadWithSerializer(Common::Serializer &s) override {
@@ -281,7 +293,7 @@ private:
if (time < kTimeStartGame || time > kTimeCityConstantinople)
return false;
- if (offset <= 0 || offset & 15)
+ if (offset <= 0 || offset & 0xF)
return false;
/* No check for < 0, as it cannot happen normaly */
@@ -308,15 +320,10 @@ private:
SavegameEntryHeader *getEntry(uint32 index);
- // Opening save files
- static Common::String getFilename(GameId id);
- static Common::InSaveFile *openForLoading(GameId id);
- static Common::OutSaveFile *openForSaving(GameId id);
-
// Savegame stream
void initStream();
- void loadStream(GameId id);
- void flushStream(GameId id);
+ void loadStream(const Common::String &target, GameId id);
+ void flushStream(const Common::String &target, GameId id);
// Misc
EntityIndex _entity;
diff --git a/engines/lastexpress/lastexpress.cpp b/engines/lastexpress/lastexpress.cpp
index 14137dbee5e..b86d7f75398 100644
--- a/engines/lastexpress/lastexpress.cpp
+++ b/engines/lastexpress/lastexpress.cpp
@@ -91,6 +91,10 @@ LastExpressEngine::~LastExpressEngine() {
_gameDescription = nullptr;
}
+Common::String LastExpressEngine::getTargetName() const {
+ return _targetName;
+}
+
// TODO: which error should we return when some game files are missing/corrupted?
Common::Error LastExpressEngine::run() {
// Initialize the graphics
diff --git a/engines/lastexpress/lastexpress.h b/engines/lastexpress/lastexpress.h
index 4938066ba23..86e7ef15635 100644
--- a/engines/lastexpress/lastexpress.h
+++ b/engines/lastexpress/lastexpress.h
@@ -101,6 +101,8 @@ public:
bool isDemo() const;
+ Common::String getTargetName() const;
+
// Frame Counter
// TODO: all callers could use _system->getMillis() directly without extra conversions
uint32 getFrameCounter() const;
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index ffd2b4aeb77..715f81490be 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -48,7 +48,7 @@
#include "common/rational.h"
-#define getNextGameId() (GameId)((_gameId + 1) % 6)
+#define getNextGameId() (GameId)((_gameId + 1) % SaveLoad::kMaximumSaveSlots)
namespace LastExpress {
@@ -303,7 +303,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
// 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 (!SaveLoad::isSavegameValid(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
if (!_hasShownIntro) {
// Show Broderbrund logo
@@ -448,7 +448,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
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 (_engine->getResourceManager()->isArchivePresent(cd)) {
if (_isGameStarted) {
showFrame(kOverlayEggButtons, kButtonContinue, true);
@@ -562,7 +562,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
break;
}
- if (!SaveLoad::isSavegameValid(getNextGameId())) {
+ if (!SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
break;
}
@@ -829,7 +829,6 @@ void Menu::setLogicEventHandlers() {
// Game-related
//////////////////////////////////////////////////////////////////////////
void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
-
bool useSameIndex = true;
if (getGlobalTimer()) {
@@ -853,7 +852,7 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
break;
}
- if (ResourceManager::isArchivePresent(index)) {
+ if (_engine->getResourceManager()->isArchivePresent(index)) {
setGlobalTimer(0);
useSameIndex = false;
@@ -867,8 +866,8 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
}
// Create a new savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
+ if (!SaveLoad::isSavegamePresent(_engine->getTargetName(), _gameId))
+ getSaveLoad()->create(_engine->getTargetName(), _gameId);
if (doSavegame)
getSaveLoad()->saveGame(kSavegameTypeEvent2, kEntityPlayer, kEventNone);
@@ -878,7 +877,7 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
}
// Init savegame & menu values
- _lastIndex = getSaveLoad()->init(_gameId, true);
+ _lastIndex = getSaveLoad()->init(_engine->getTargetName(), _gameId, true);
_lowerTime = getSaveLoad()->getTime(_lastIndex);
if (useSameIndex)
@@ -928,12 +927,12 @@ void Menu::startGame() {
// 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;
+ // Switch back to blue game if the current game is not started
+ _gameId = SaveLoad::isSavegameValid(_engine->getTargetName(), _gameId) ? getNextGameId() : kGameBlue;
// Initialize savegame if needed
- if (!SaveLoad::isSavegamePresent(_gameId))
- getSaveLoad()->create(_gameId);
+ if (!SaveLoad::isSavegamePresent(_engine->getTargetName(), _gameId))
+ getSaveLoad()->create(_engine->getTargetName(), _gameId);
getState()->time = kTimeNone;
diff --git a/engines/lastexpress/metaengine.cpp b/engines/lastexpress/metaengine.cpp
index 95a36b74093..63f546eb4aa 100644
--- a/engines/lastexpress/metaengine.cpp
+++ b/engines/lastexpress/metaengine.cpp
@@ -20,6 +20,7 @@
*/
#include "lastexpress/lastexpress.h"
+#include "lastexpress/game/savegame.h"
#include "engines/advancedDetector.h"
namespace LastExpress {
@@ -30,6 +31,12 @@ public:
return "lastexpress";
}
+ bool hasFeature(MetaEngineFeature f) const override;
+
+ SaveStateList listSaves(const char *target) const override;
+ int getMaximumSaveSlot() const override;
+ void removeSaveState(const char *target, int slot) const override;
+
protected:
Common::Error createInstance(OSystem *syst, Engine **engine, const ADGameDescription *gd) const override;
};
@@ -43,6 +50,24 @@ bool LastExpressEngine::isDemo() const {
return (bool)(_gameDescription->flags & ADGF_DEMO);
}
+bool LastExpressMetaEngine::hasFeature(MetaEngineFeature f) const {
+ return f == kSupportsListSaves
+ || f == kSupportsLoadingDuringStartup
+ || f == kSupportsDeleteSave;
+}
+
+SaveStateList LastExpressMetaEngine::listSaves(const char *target) const {
+ return LastExpress::SaveLoad::list(this, target);
+}
+
+int LastExpressMetaEngine::getMaximumSaveSlot() const {
+ return LastExpress::SaveLoad::kMaximumSaveSlots - 1;
+}
+
+void LastExpressMetaEngine::removeSaveState(const char *target, int slot) const {
+ LastExpress::SaveLoad::remove(target, (LastExpress::GameId)slot);
+}
+
} // End of namespace LastExpress
#if PLUGIN_ENABLED_DYNAMIC(LASTEXPRESS)
diff --git a/engines/lastexpress/shared.h b/engines/lastexpress/shared.h
index 9c852e2498b..850f660b936 100644
--- a/engines/lastexpress/shared.h
+++ b/engines/lastexpress/shared.h
@@ -573,7 +573,7 @@ enum CityIndex {
// Savegame ID
//////////////////////////////////////////////////////////////////////////
enum GameId {
- kGameBlue,
+ kGameBlue = 0,
kGameRed,
kGameGreen,
kGamePurple,
Commit: 62d619e55ed32db9104160bcc226f850d4004d27
https://github.com/scummvm/scummvm/commit/62d619e55ed32db9104160bcc226f850d4004d27
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-04-29T13:08:27+02:00
Commit Message:
LASTEXPRESS: Fix compiler warnings and a bad index for entities array
Compiler warnings were about uninitialized variables
Changed paths:
engines/lastexpress/entities/entity.cpp
engines/lastexpress/game/scenes.cpp
engines/lastexpress/game/state.h
engines/lastexpress/sound/entry.cpp
diff --git a/engines/lastexpress/entities/entity.cpp b/engines/lastexpress/entities/entity.cpp
index 3b56d00d124..7ecfd123fd2 100644
--- a/engines/lastexpress/entities/entity.cpp
+++ b/engines/lastexpress/entities/entity.cpp
@@ -159,7 +159,7 @@ void EntityData::saveLoadWithSerializer(Common::Serializer &s, const Common::Arr
// (the original game has same-size-PODs and just memcpy-s them.
// *sigh* Why does this implementation even need the extra byte in strings?
// Well, big-endian vs little-endian is also a thing...)
- byte buf[ARRAYSIZE(_parameters) * 32 * 4];
+ byte buf[ARRAYSIZE(_parameters) * 32 * 4] = {0};
s.syncBytes(buf, sizeof(buf));
_data.saveLoadWithSerializer(s);
diff --git a/engines/lastexpress/game/scenes.cpp b/engines/lastexpress/game/scenes.cpp
index 782c6ec16e8..a353802d47b 100644
--- a/engines/lastexpress/game/scenes.cpp
+++ b/engines/lastexpress/game/scenes.cpp
@@ -1115,14 +1115,14 @@ void SceneManager::postProcessScene() {
// If several entities are there, choose one to sound "Excuse me"
EntityPosition entityPosition = getEntityData(kEntityPlayer)->entityPosition;
if (getEntityData(kEntityPlayer)->car == kCar9 && (entityPosition == kPosition_4 || entityPosition == kPosition_3)) {
- EntityIndex entities[39];
+ EntityIndex entities[40] = {(EntityIndex)0};
// Init entities
entities[0] = kEntityPlayer;
uint progress = 0;
- for (uint i = 1; i < 40 /* number of entities */; i++) {
+ for (uint i = 1; i < 40 /* number of entities */; ++i) {
CarIndex car = getEntityData((EntityIndex)i)->car;
EntityPosition position = getEntityData((EntityIndex)i)->entityPosition;
diff --git a/engines/lastexpress/game/state.h b/engines/lastexpress/game/state.h
index 61fba00ed98..83eccab9c25 100644
--- a/engines/lastexpress/game/state.h
+++ b/engines/lastexpress/game/state.h
@@ -474,7 +474,7 @@ public:
void saveLoadWithSerializer(Common::Serializer &s) override {
if (s.isLoading()) {
for (uint i = 0; i < 128; i++) {
- uint32 val;
+ uint32 val = 0;
s.syncAsUint32LE(val);
getOrSetValueName(i, NULL, &val);
}
diff --git a/engines/lastexpress/sound/entry.cpp b/engines/lastexpress/sound/entry.cpp
index a7970829f88..22f50e04dd6 100644
--- a/engines/lastexpress/sound/entry.cpp
+++ b/engines/lastexpress/sound/entry.cpp
@@ -346,18 +346,18 @@ void SoundEntry::setSubtitles(Common::String filename) {
void SoundEntry::saveLoadWithSerializer(Common::Serializer &s) {
if (s.isLoading()) {
// load the fields
- uint32 blocksLeft;
+ uint32 blocksLeft = 0;
s.syncAsUint32LE(_status);
s.syncAsUint32LE(_tag);
s.syncAsUint32LE(blocksLeft);
s.syncAsUint32LE(_startTime);
- uint32 unused;
+ uint32 unused = 0;
s.syncAsUint32LE(unused);
s.syncAsUint32LE(unused);
s.syncAsUint32LE(_entity);
- uint32 activateDelay;
+ uint32 activateDelay = 0;
s.syncAsUint32LE(activateDelay);
s.syncAsUint32LE(_priority);
Commit: 7c2d841d3d99478de0641ed6c39c21823fde3a64
https://github.com/scummvm/scummvm/commit/7c2d841d3d99478de0641ed6c39c21823fde3a64
Author: antoniou79 (a.antoniou79 at gmail.com)
Date: 2023-04-29T13:08:27+02:00
Commit Message:
LASTEXPRESS: Early support for demo
Demo launches but the init state needs more work
Changed paths:
engines/lastexpress/entities/chapters.cpp
engines/lastexpress/game/entities.cpp
engines/lastexpress/game/savegame.cpp
engines/lastexpress/menu/clock.cpp
engines/lastexpress/menu/menu.cpp
engines/lastexpress/resource.cpp
engines/lastexpress/resource.h
diff --git a/engines/lastexpress/entities/chapters.cpp b/engines/lastexpress/entities/chapters.cpp
index a5424063ba7..01ac87db266 100644
--- a/engines/lastexpress/entities/chapters.cpp
+++ b/engines/lastexpress/entities/chapters.cpp
@@ -867,7 +867,12 @@ IMPLEMENT_FUNCTION(13, Chapters, chapter3)
}
// Set game time & delta
- getState()->time = kTimeChapter3;
+ // TODO This check and code (for demo case) may be removed in the future
+ if (_engine->isDemo()){
+ getState()->time = kTime2241000;
+ } else {
+ getState()->time = kTimeChapter3;
+ }
getState()->timeDelta = 5;
setup_chapter3Init();
diff --git a/engines/lastexpress/game/entities.cpp b/engines/lastexpress/game/entities.cpp
index ca35efec2d4..3f82e012d24 100644
--- a/engines/lastexpress/game/entities.cpp
+++ b/engines/lastexpress/game/entities.cpp
@@ -262,7 +262,14 @@ void Entities::saveCompartments(Common::Serializer &s) {
// Setup
//////////////////////////////////////////////////////////////////////////
void Entities::setup(bool isFirstChapter, EntityIndex entityIndex) {
- setupChapter(isFirstChapter ? kChapter1 : kChapterAll);
+ // TODO This check and code (for demo case) may be removed in the future
+ if (_engine->isDemo()) {
+ setupChapter(kChapter3);
+ // TODO Should this be set for the demo?
+ //isFirstChapter = false;
+ } else {
+ setupChapter(isFirstChapter ? kChapter1 : kChapterAll);
+ }
bool flag_4 = false;
@@ -300,8 +307,7 @@ void Entities::setupChapter(ChapterIndex chapter) {
// we skip the header when doing entity setup
for (uint i = 1; i < _entities.size(); i++) {
- // Special case of chapters (prevents infinite loop as we will be called from Chapters functions when changing chapters)
- if (i == kEntityChapters && chapter >= 2)
+ if (i == kEntityChapters && chapter >= 2 && !_engine->isDemo())
continue;
_entities[i]->setup(chapter);
diff --git a/engines/lastexpress/game/savegame.cpp b/engines/lastexpress/game/savegame.cpp
index 41e843bba6f..3ed1edfac1b 100644
--- a/engines/lastexpress/game/savegame.cpp
+++ b/engines/lastexpress/game/savegame.cpp
@@ -406,9 +406,14 @@ uint32 SaveLoad::init(const Common::String &target, GameId id, bool resetHeaders
clear();
SavegameEntryHeader *entryHeader = new SavegameEntryHeader();
- entryHeader->time = kTimeCityParis;
- entryHeader->chapter = kChapter1;
-
+ // TODO This check and code (for demo case) may be removed in the future
+ if (_engine->isDemo()) {
+ entryHeader->time = kTime2241000;
+ entryHeader->chapter = kChapter3;
+ } else {
+ entryHeader->time = kTimeCityParis;
+ entryHeader->chapter = kChapter1;
+ }
_gameHeaders.push_back(entryHeader);
}
diff --git a/engines/lastexpress/menu/clock.cpp b/engines/lastexpress/menu/clock.cpp
index 7aee60be6e2..0651bead4bc 100644
--- a/engines/lastexpress/menu/clock.cpp
+++ b/engines/lastexpress/menu/clock.cpp
@@ -35,15 +35,19 @@ namespace LastExpress {
Clock::Clock(LastExpressEngine *engine) : _engine(engine), _frameMinutes(nullptr), _frameHour(nullptr), _frameSun(nullptr), _frameDate(nullptr) {
_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);
+ if (!_engine->isDemo()) {
+ _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);
+ if (!_engine->isDemo()) {
+ SAFE_DELETE(_frameSun);
+ SAFE_DELETE(_frameDate);
+ }
// Zero passed pointers
_engine = nullptr;
@@ -52,15 +56,17 @@ Clock::~Clock() {
void Clock::clear() {
getScenes()->removeFromQueue(_frameMinutes);
getScenes()->removeFromQueue(_frameHour);
- getScenes()->removeFromQueue(_frameSun);
- getScenes()->removeFromQueue(_frameDate);
+ if (!_engine->isDemo()) {
+ 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)
+ if (!_frameMinutes || !_frameHour || (!_engine->isDemo() && !_frameSun) || (!_engine->isDemo() && !_frameDate))
error("[Clock::draw] Clock sequences have not been loaded correctly");
// Clear existing frames
@@ -87,19 +93,25 @@ void Clock::draw(uint32 time) {
// 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);
+ if (!_engine->isDemo()) {
+ _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;
+ if (!_engine->isDemo()) {
+ _frameSun->getInfo()->location = 1;
+ _frameDate->getInfo()->location = 1;
+ }
getScenes()->addToQueue(_frameMinutes);
getScenes()->addToQueue(_frameHour);
- getScenes()->addToQueue(_frameSun);
- getScenes()->addToQueue(_frameDate);
+ if (!_engine->isDemo()) {
+ getScenes()->addToQueue(_frameSun);
+ getScenes()->addToQueue(_frameDate);
+ }
}
} // End of namespace LastExpress
diff --git a/engines/lastexpress/menu/menu.cpp b/engines/lastexpress/menu/menu.cpp
index 715f81490be..72f9103ada8 100644
--- a/engines/lastexpress/menu/menu.cpp
+++ b/engines/lastexpress/menu/menu.cpp
@@ -148,12 +148,16 @@ Menu::Menu(LastExpressEngine *engine) : _engine(engine),
_currentTime(kTimeNone), _lowerTime(kTimeNone), _time(kTimeNone), _currentIndex(0), _index(0), _lastIndex(0), _delta(0), _handleTimeDelta(false) {
_clock = new Clock(_engine);
- _trainLine = new TrainLine(_engine);
+ if (!_engine->isDemo()) {
+ _trainLine = new TrainLine(_engine);
+ }
}
Menu::~Menu() {
SAFE_DELETE(_clock);
- SAFE_DELETE(_trainLine);
+ if (!_engine->isDemo()) {
+ SAFE_DELETE(_trainLine);
+ }
SAFE_DELETE(_seqTooltips);
SAFE_DELETE(_seqEggButtons);
@@ -303,7 +307,7 @@ void Menu::show(bool doSavegame, SavegameType type, uint32 value) {
// 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(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1)) {
+ if (!SaveLoad::isSavegameValid(_engine->getTargetName(), kGameBlue) && _engine->getResourceManager()->loadArchive(kArchiveCd1) && !_engine->isDemo()) {
if (!_hasShownIntro) {
// Show Broderbrund logo
@@ -534,17 +538,18 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
}
if (clicked) {
- showFrame(kOverlayAcorn, 1, true);
- showFrame(kOverlayTooltip, -1, true);
- getSound()->playSound(kEntityPlayer, "LIB047");
+ if (!_engine->isDemo()) {
+ 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();
+ // Setup new menu screen
+ switchGame();
+ setup();
+ // Set fight state to 0
+ getFight()->resetState();
+ }
return true;
}
@@ -552,7 +557,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
showFrame(kOverlayAcorn, 0, true);
- if (_isGameStarted) {
+ if (_isGameStarted && !_engine->isDemo()) {
showFrame(kOverlayTooltip, kTooltipSwitchBlueGame, true);
break;
}
@@ -562,7 +567,7 @@ bool Menu::handleEvent(StartMenuAction action, Common::EventType type) {
break;
}
- if (!SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
+ if (_engine->isDemo() || !SaveLoad::isSavegameValid(_engine->getTargetName(), getNextGameId())) {
showFrame(kOverlayTooltip, kTooltipStartAnotherGame, true);
break;
}
@@ -886,8 +891,13 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
//if (!getGlobalTimer())
// _index3 = 0;
- if (!getProgress().chapter)
- getProgress().chapter = kChapter1;
+ if (!getProgress().chapter) {
+ if (_engine->isDemo()) {
+ getProgress().chapter = kChapter3;
+ } else {
+ getProgress().chapter = kChapter1;
+ }
+ }
getState()->time = (TimeValue)getSaveLoad()->getTime(_index);
getProgress().chapter = getSaveLoad()->getChapter(_index);
@@ -896,7 +906,9 @@ void Menu::init(bool doSavegame, SavegameType type, uint32 value) {
_currentTime = (uint32)getState()->time;
_time = (uint32)getState()->time;
_clock->draw(_time);
- _trainLine->draw(_time);
+ if (!_engine->isDemo()) {
+ _trainLine->draw(_time);
+ }
initTime(type, value);
}
@@ -909,7 +921,9 @@ void Menu::startGame() {
// Hide menu elements
_clock->clear();
- _trainLine->clear();
+ if (!_engine->isDemo()) {
+ _trainLine->clear();
+ }
if (_lastIndex == _index) {
setGlobalTimer(0);
@@ -917,6 +931,11 @@ void Menu::startGame() {
getSaveLoad()->loadLastGame();
} else {
getLogic()->resetState();
+ // TODO This check and code (for demo case) may be removed in the future
+ if (_engine->isDemo()) {
+ getState()->time = kTime2241000;
+ getProgress().chapter = kChapter3;
+ }
getEntities()->setup(true, kEntityPlayer);
}
} else {
@@ -938,7 +957,9 @@ void Menu::switchGame() {
// Clear menu elements
_clock->clear();
- _trainLine->clear();
+ if (!_engine->isDemo()) {
+ _trainLine->clear();
+ }
// Clear loaded savegame data
getSaveLoad()->clear(true);
@@ -1006,6 +1027,10 @@ void Menu::clear() {
// Get the sequence name to use for the acorn highlight, depending of the currently loaded savegame
Common::String Menu::getAcornSequenceName(GameId id) const {
+ if (_engine->isDemo()) {
+ return "aconred.seq";
+ }
+
Common::String name = "";
switch (id) {
default:
@@ -1252,7 +1277,9 @@ void Menu::adjustTime() {
getSoundQueue()->stop(kEntityChapters);
_clock->draw(_time);
- _trainLine->draw(_time);
+ if (!_engine->isDemo()) {
+ _trainLine->draw(_time);
+ }
getScenes()->drawFrames(true);
adjustIndex(_time, originalTime, true);
diff --git a/engines/lastexpress/resource.cpp b/engines/lastexpress/resource.cpp
index 6db05257e4d..a835daffa47 100644
--- a/engines/lastexpress/resource.cpp
+++ b/engines/lastexpress/resource.cpp
@@ -47,6 +47,10 @@ ResourceManager::~ResourceManager() {
}
bool ResourceManager::isArchivePresent(ArchiveIndex type) {
+ // Demo version
+ if (_isDemo)
+ return Common::File::exists(archiveDemoPath);
+
switch (type) {
default:
case kArchiveAll:
diff --git a/engines/lastexpress/resource.h b/engines/lastexpress/resource.h
index 676492179b7..1df32e9afdf 100644
--- a/engines/lastexpress/resource.h
+++ b/engines/lastexpress/resource.h
@@ -40,7 +40,7 @@ public:
// Loading
bool loadArchive(ArchiveIndex type);
- static bool isArchivePresent(ArchiveIndex type);
+ bool isArchivePresent(ArchiveIndex type);
Common::SeekableReadStream *getFileStream(const Common::String &name) const;
// Archive functions
More information about the Scummvm-git-logs
mailing list