diff options
Diffstat (limited to 'engines/sci/engine/kfile.cpp')
-rw-r--r-- | engines/sci/engine/kfile.cpp | 118 |
1 files changed, 84 insertions, 34 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp index c48fb4035f..e6b9a5388c 100644 --- a/engines/sci/engine/kfile.cpp +++ b/engines/sci/engine/kfile.cpp @@ -44,8 +44,6 @@ struct SavegameDesc { int id; int date; int time; - int version; - char name[SCI_MAX_SAVENAME_LENGTH]; }; /* @@ -247,10 +245,13 @@ static void fgets_wrapper(EngineState *s, char *dest, int maxsize, int handle) { debugC(2, kDebugLevelFile, "FGets'ed \"%s\"", dest); } -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); +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; } void listSavegames(Common::Array<SavegameDesc> &saves) { @@ -264,7 +265,7 @@ void listSavegames(Common::Array<SavegameDesc> &saves) { Common::SeekableReadStream *in; if ((in = saveFileMan->openForLoading(filename))) { SavegameMetadata meta; - if (!get_savegame_metadata(in, &meta) || meta.savegame_name.empty()) { + if (!get_savegame_metadata(in, &meta)) { // invalid delete in; continue; @@ -277,13 +278,6 @@ 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); @@ -291,18 +285,35 @@ void listSavegames(Common::Array<SavegameDesc> &saves) { } // Sort the list by creation date of the saves - Common::sort(saves.begin(), saves.end(), _savegame_index_struct_compare); + qsort(saves.begin(), saves.size(), sizeof(SavegameDesc), _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); - DebugPrintf("%s: '%s'\n", filename.c_str(), saves[i].name); - } + 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; + } + } return true; } @@ -417,7 +428,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->_segMan->getSysStringsSegment(), SYS_STRING_SAVEDIR); + return make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR); } reg_t kCheckFreeSpace(EngineState *s, int argc, reg_t *argv) { @@ -438,30 +449,44 @@ 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]); - uint16 savedir_nr = argv[1].toUint16(); + int savedir_nr = argv[1].toUint16(); debug(3, "kCheckSaveGame(%s, %d)", game_id.c_str(), savedir_nr); Common::Array<SavegameDesc> saves; listSavegames(saves); - // Check for savegame slot being out of range - if (savedir_nr >= saves.size()) - return NULL_REG; + savedir_nr = saves[savedir_nr].id; - // Check for compatible savegame version - int ver = saves[savedir_nr].version; - if (ver < MINIMUM_SAVEGAME_VERSION || ver > CURRENT_SAVEGAME_VERSION) + if (savedir_nr > MAX_SAVEGAME_NR - 1) { return NULL_REG; + } - // Otherwise we assume the savegame is OK - return make_reg(0, 1); + 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); + } + + return s->r_acc; } 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 *slot = s->_segMan->derefRegPtr(argv[2], 0); + reg_t *nameoffsets = s->_segMan->derefRegPtr(argv[2], 0); debug(3, "kGetSaveFiles(%s)", game_id.c_str()); @@ -469,17 +494,42 @@ reg_t kGetSaveFiles(EngineState *s, int argc, reg_t *argv) { listSavegames(saves); s->r_acc = NULL_REG; + 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))) { + // found a savegame file + + 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(); - for (uint i = 0; i < MIN<uint>(saves.size(), MAX_SAVEGAME_NR); i++) { - *slot++ = s->r_acc; // Store savegame ID - ++s->r_acc.offset; // Increase number of files found + *nameoffsets = s->r_acc; // Store savegame ID + ++s->r_acc.offset; // Increase number of files found - s->_segMan->strcpy(nametarget, saves[i].name); + 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()); - // Increase name offset pointer accordingly - nametarget.offset += SCI_MAX_SAVENAME_LENGTH; + // Increase name offset pointer accordingly + nametarget.offset += SCI_MAX_SAVENAME_LENGTH; + } + delete in; + } } + //free(gfname); s->_segMan->strcpy(nametarget, ""); // Terminate list return s->r_acc; |