aboutsummaryrefslogtreecommitdiff
path: root/engines/sci/engine/kfile.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/sci/engine/kfile.cpp')
-rw-r--r--engines/sci/engine/kfile.cpp132
1 files changed, 45 insertions, 87 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index e6b9a5388c..3e0ecd1a28 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -44,6 +44,8 @@ struct SavegameDesc {
int id;
int date;
int time;
+ int version;
+ char name[SCI_MAX_SAVENAME_LENGTH];
};
/*
@@ -245,13 +247,10 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) {
debugC(2, kDebugLevelFile, "FGets'ed \"%s\"", dest);
}
-static int _savegame_index_struct_compare(const void *a, const void *b) {
- const SavegameDesc *A = (const SavegameDesc *)a;
- const SavegameDesc *B = (const SavegameDesc *)b;
-
- if (B->date != A->date)
- return B->date - A->date;
- return B->time - A->time;
+static bool _savegame_index_struct_compare(const SavegameDesc &l, const SavegameDesc &r) {
+ if (l.date != r.date)
+ return (l.date > r.date);
+ return (l.time > r.time);
}
void listSavegames(Common::Array<SavegameDesc> &saves) {
@@ -265,7 +264,7 @@ void listSavegames(Common::Array<SavegameDesc> &saves) {
Common::SeekableReadStream *in;
if ((in = saveFileMan->openForLoading(filename))) {
SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
+ if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) {
// invalid
delete in;
continue;
@@ -278,6 +277,13 @@ void listSavegames(Common::Array<SavegameDesc> &saves) {
// We need to fix date in here, because we save DDMMYYYY instead of YYYYMMDD, so sorting wouldnt work
desc.date = ((desc.date & 0xFFFF) << 16) | ((desc.date & 0xFF0000) >> 8) | ((desc.date & 0xFF000000) >> 24);
desc.time = meta.savegame_time;
+ desc.version = meta.savegame_version;
+
+ if (meta.savegame_name.lastChar() == '\n')
+ meta.savegame_name.deleteLastChar();
+
+ Common::strlcpy(desc.name, meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH);
+
debug(3, "Savegame in file %s ok, id %d", filename.c_str(), desc.id);
saves.push_back(desc);
@@ -285,35 +291,18 @@ void listSavegames(Common::Array<SavegameDesc> &saves) {
}
// Sort the list by creation date of the saves
- qsort(saves.begin(), saves.size(), sizeof(SavegameDesc), _savegame_index_struct_compare);
+ Common::sort(saves.begin(), saves.end(), _savegame_index_struct_compare);
}
bool Console::cmdListSaves(int argc, const char **argv) {
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
-
for (uint i = 0; i < saves.size(); i++) {
Common::String filename = g_sci->getSavegameName(saves[i].id);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- delete in;
- continue;
- }
-
- if (!meta.savegame_name.empty()) {
- if (meta.savegame_name.lastChar() == '\n')
- meta.savegame_name.deleteLastChar();
-
- DebugPrintf("%s: '%s'\n", filename.c_str(), meta.savegame_name.c_str());
- }
- delete in;
- }
+ DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name);
}
+
return true;
}
@@ -428,7 +417,7 @@ reg_t kGetSaveDir(EngineState *s, int argc, reg_t *argv) {
warning("kGetSaveDir called with %d parameter(s): %04x:%04x", argc, PRINT_REG(argv[0]));
#endif
- return make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR);
+ return make_reg(s->_segMan->getSysStringsSegment(), SYS_STRING_SAVEDIR);
}
reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) {
@@ -449,90 +438,59 @@ reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) {
reg_t kCheckSaveGame(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = s->_segMan->getString(argv[0]);
- int savedir_nr = argv[1].toUint16();
+ uint16 savedir_nr = argv[1].toUint16();
debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr);
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- savedir_nr = saves[savedir_nr].id;
-
- if (savedir_nr > MAX_SAVEGAME_NR - 1) {
+ // Check for savegame slot being out of range
+ if (savedir_nr >= saves.size())
return NULL_REG;
- }
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- Common::String filename = g_sci->getSavegameName(savedir_nr);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- // found a savegame file
-
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- s->r_acc = make_reg(0, 0);
- } else {
- s->r_acc = make_reg(0, 1);
- }
- delete in;
- } else {
- s->r_acc = make_reg(0, 1);
- }
+ // Check for compatible savegame version
+ int ver = saves[savedir_nr].version;
+ if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION)
+ return NULL_REG;
- return s->r_acc;
+ // Otherwise we assume the savegame is OK
+ return make_reg(0, 1);
}
reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) {
Common::String game_id = s->_segMan->getString(argv[0]);
- reg_t nametarget = argv[1];
- reg_t *nameoffsets = s->_segMan->derefRegPtr(argv[2], 0);
debug(3, "kGetSaveFiles(%s)", game_id.c_str());
Common::Array<SavegameDesc> saves;
listSavegames(saves);
- s->r_acc = NULL_REG;
- Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ uint totalSaves = MIN<uint>(saves.size(), MAX_SAVEGAME_NR);
- for (uint i = 0; i < saves.size(); i++) {
- Common::String filename = g_sci->getSavegameName(saves[i].id);
- Common::SeekableReadStream *in;
- if ((in = saveFileMan->openForLoading(filename))) {
- // found a savegame file
+ reg_t *slot = s->_segMan->derefRegPtr(argv[2], totalSaves);
- SavegameMetadata meta;
- if (!get_savegame_metadata(in, &meta)) {
- // invalid
- delete in;
- continue;
- }
-
- if (!meta.savegame_name.empty()) {
- if (meta.savegame_name.lastChar() == '\n')
- meta.savegame_name.deleteLastChar();
-
- *nameoffsets = s->r_acc; // Store savegame ID
- ++s->r_acc.offset; // Increase number of files found
+ if (!slot) {
+ warning("kGetSaveFiles: %04X:%04X invalid or too small to hold slot data", PRINT_REG(argv[2]));
+ totalSaves = 0;
+ }
- nameoffsets++; // Make sure the next ID string address is written to the next pointer
- Common::String name = meta.savegame_name;
- if (name.size() > SCI_MAX_SAVENAME_LENGTH-1)
- name = Common::String(meta.savegame_name.c_str(), SCI_MAX_SAVENAME_LENGTH-1);
- s->_segMan->strcpy(nametarget, name.c_str());
+ const uint bufSize = (totalSaves * SCI_MAX_SAVENAME_LENGTH) + 1;
+ char *saveNames = new char[bufSize];
+ char *saveNamePtr = saveNames;
- // Increase name offset pointer accordingly
- nametarget.offset += SCI_MAX_SAVENAME_LENGTH;
- }
- delete in;
- }
+ for (uint i = 0; i < totalSaves; i++) {
+ *slot++ = make_reg(0, i); // Store slot
+ strcpy(saveNamePtr, saves[i].name);
+ saveNamePtr += SCI_MAX_SAVENAME_LENGTH;
}
- //free(gfname);
- s->_segMan->strcpy(nametarget, ""); // Terminate list
+ *saveNamePtr = 0; // Terminate list
- return s->r_acc;
+ s->_segMan->memcpy(argv[1], (byte *)saveNames, bufSize);
+ delete[] saveNames;
+
+ return make_reg(0, totalSaves);
}
reg_t kSaveGame(EngineState *s, int argc, reg_t *argv) {