aboutsummaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorColin Snover2016-09-15 21:08:44 -0500
committerColin Snover2016-09-29 19:39:16 -0500
commit2629269212b9a5946e11cadf6abead7856b5fe58 (patch)
tree10a0bb275442ed9cc20b0c0adcbbc76220cd13cc
parent25c874b9cd370cab26ebef6e8e30786e39823c21 (diff)
downloadscummvm-rg350-2629269212b9a5946e11cadf6abead7856b5fe58.tar.gz
scummvm-rg350-2629269212b9a5946e11cadf6abead7856b5fe58.tar.bz2
scummvm-rg350-2629269212b9a5946e11cadf6abead7856b5fe58.zip
SCI32: Emulate Shivers 1 game score metadata
-rw-r--r--engines/sci/engine/file.cpp1
-rw-r--r--engines/sci/engine/file.h4
-rw-r--r--engines/sci/engine/kfile.cpp60
-rw-r--r--engines/sci/engine/savegame.cpp11
-rw-r--r--engines/sci/engine/savegame.h6
-rw-r--r--engines/sci/engine/vm.h4
6 files changed, 50 insertions, 36 deletions
diff --git a/engines/sci/engine/file.cpp b/engines/sci/engine/file.cpp
index 74cd812f89..efeae63a09 100644
--- a/engines/sci/engine/file.cpp
+++ b/engines/sci/engine/file.cpp
@@ -335,6 +335,7 @@ bool fillSavegameDesc(const Common::String &filename, SavegameDesc *desc) {
desc->time = meta.saveTime;
desc->version = meta.version;
desc->gameVersion = meta.gameVersion;
+ desc->score = meta.score;
if (meta.name.lastChar() == '\n')
meta.name.deleteLastChar();
diff --git a/engines/sci/engine/file.h b/engines/sci/engine/file.h
index 88d483bab7..27250d3da9 100644
--- a/engines/sci/engine/file.h
+++ b/engines/sci/engine/file.h
@@ -59,6 +59,10 @@ struct SavegameDesc {
int version;
char name[SCI_MAX_SAVENAME_LENGTH];
Common::String gameVersion;
+#ifdef ENABLE_SCI32
+ // Used by Shivers 1
+ uint32 score;
+#endif
};
class FileHandle {
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index b6fbd45562..33ddd1f6f8 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -328,50 +328,42 @@ reg_t kFileIOOpen(EngineState *s, int argc, reg_t *argv) {
}
#ifdef ENABLE_SCI32
- // Shivers is trying to store savegame descriptions and current spots in
- // separate .SG files, which are hardcoded in the scripts.
- // Essentially, there is a normal save file, created by the executable
- // and an extra hardcoded save file, created by the game scripts, probably
- // because they didn't want to modify the save/load code to add the extra
- // information.
- // Each slot in the book then has two strings, the save description and a
- // description of the current spot that the player is at.
- // For now, we don't allow the creation of these files, which means that
- // all the spot descriptions next to each slot description will be empty.
- // Until a viable solution is found to handle these
- // extra files and until the spot description strings are initialized
- // correctly, we resort to virtual files in order to make the load screen
- // useable. Without this code it is unusable, as the extra information is
- // always saved to 0.SG for some reason, but on restore the correct file is
- // used. Perhaps the virtual ID is not taken into account when saving.
- //
- // Future TODO: maintain spot descriptions and show them too, ideally without
- // having to return to this logic of extra hardcoded files.
+ // Shivers stores the name and score of save games in separate %d.SG files,
+ // which are used by the save/load screen
if (g_sci->getGameId() == GID_SHIVERS && name.hasSuffix(".SG")) {
if (mode == _K_FILE_MODE_OPEN_OR_CREATE || mode == _K_FILE_MODE_CREATE) {
- // Game scripts are trying to create a file with the save
- // description, stop them here
+ // Suppress creation of the SG file, since it is not necessary
debugC(kDebugLevelFile, "Not creating unused file %s", name.c_str());
return SIGNAL_REG;
} else if (mode == _K_FILE_MODE_OPEN_OR_FAIL) {
// Create a virtual file containing the save game description
// and slot number, as the game scripts expect.
- int slotNumber;
- sscanf(name.c_str(), "%d.SG", &slotNumber);
-
- Common::Array<SavegameDesc> saves;
- listSavegames(saves);
- int savegameNr = findSavegame(saves, slotNumber);
- assert(savegameNr >= 0);
+ int saveNo;
+ sscanf(name.c_str(), "%d.SG", &saveNo);
+
+ SavegameDesc save;
+ fillSavegameDesc(g_sci->getSavegameName(saveNo), &save);
+ Common::String score;
+ const uint16 lowScore = save.score & 0xFFFF;
+ const uint16 highScore = save.score >> 16;
+
+ if (!highScore) {
+ score = Common::String::format("%u", lowScore);
+ } else {
+ score = Common::String::format("%u%03u", highScore, lowScore);
+ }
- int size = strlen(saves[savegameNr].name) + 2;
- char *buf = (char *)malloc(size);
- strcpy(buf, saves[savegameNr].name);
- buf[size - 1] = 0; // Spot description (empty)
+ const uint nameLength = strlen(save.name);
+ const uint size = nameLength + /* \r\n */ 2 + score.size();
+ char *buffer = (char *)malloc(size);
+ memcpy(buffer, save.name, nameLength);
+ buffer[nameLength] = '\r';
+ buffer[nameLength + 1] = '\n';
+ memcpy(buffer + nameLength + 2, score.c_str(), score.size());
- uint handle = findFreeFileHandle(s);
+ const uint handle = findFreeFileHandle(s);
- s->_fileHandles[handle]._in = new Common::MemoryReadStream((byte *)buf, size, DisposeAfterUse::YES);
+ s->_fileHandles[handle]._in = new Common::MemoryReadStream((byte *)buffer, size, DisposeAfterUse::YES);
s->_fileHandles[handle]._out = nullptr;
s->_fileHandles[handle]._name = "";
diff --git a/engines/sci/engine/savegame.cpp b/engines/sci/engine/savegame.cpp
index 5a73526fb7..74493fcfde 100644
--- a/engines/sci/engine/savegame.cpp
+++ b/engines/sci/engine/savegame.cpp
@@ -330,6 +330,17 @@ static void sync_SavegameMetadata(Common::Serializer &s, SavegameMetadata &obj)
}
s.syncAsUint32LE(obj.playTime);
}
+
+ if (s.getVersion() >= 38) {
+ if (s.isSaving()) {
+ obj.score = g_sci->getEngineState()->variables[VAR_GLOBAL][kScore].toUint16();
+ if (g_sci->getGameId() == GID_SHIVERS) {
+ obj.score |= g_sci->getEngineState()->variables[VAR_GLOBAL][kShivers1Score].toUint16() << 16;
+ }
+ }
+
+ s.syncAsUint32LE(obj.score);
+ }
}
void EngineState::saveLoadWithSerializer(Common::Serializer &s) {
diff --git a/engines/sci/engine/savegame.h b/engines/sci/engine/savegame.h
index 5995de7818..01f92ed342 100644
--- a/engines/sci/engine/savegame.h
+++ b/engines/sci/engine/savegame.h
@@ -37,7 +37,7 @@ struct EngineState;
*
* Version - new/changed feature
* =============================
- * 38 - SCI32 cursor, accurate SCI32 arrays/strings
+ * 38 - SCI32 cursor, accurate SCI32 arrays/strings, score metadata
* 37 - Segment entry data changed to pointers
* 36 - SCI32 bitmap segment
* 35 - SCI32 remap
@@ -77,6 +77,10 @@ struct SavegameMetadata {
uint32 playTime;
uint16 gameObjectOffset;
uint16 script0Size;
+#ifdef ENABLE_SCI32
+ // Used by Shivers 1
+ uint32 score;
+#endif
};
/**
diff --git a/engines/sci/engine/vm.h b/engines/sci/engine/vm.h
index e127706d58..31433555e4 100644
--- a/engines/sci/engine/vm.h
+++ b/engines/sci/engine/vm.h
@@ -147,8 +147,10 @@ enum GlobalVar {
kCurrentRoomNo = 11,
kPreviousRoomNo = 12,
kNewRoomNo = 13,
+ kScore = 15,
kFastCast = 84, // SCI16
- kMessageType = 90
+ kMessageType = 90,
+ kShivers1Score = 349
};
/** Number of kernel calls in between gcs; should be < 50000 */