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.cpp365
1 files changed, 125 insertions, 240 deletions
diff --git a/engines/sci/engine/kfile.cpp b/engines/sci/engine/kfile.cpp
index 2b22f6d87a..041784ee27 100644
--- a/engines/sci/engine/kfile.cpp
+++ b/engines/sci/engine/kfile.cpp
@@ -30,8 +30,10 @@
#endif
#include "common/str.h"
+#include "common/savefile.h"
#include "sci/include/engine.h"
+#include "sci/sci.h"
#include <errno.h>
@@ -43,7 +45,8 @@ static int _savegame_indices_nr = -1; // means 'uninitialized'
static struct _savegame_index_struct {
int id;
- long timestamp;
+ int date;
+ int time;
} _savegame_indices[MAX_SAVEGAME_NR];
// This assumes modern stream implementations. It may break on DOS.
@@ -264,29 +267,6 @@ static void fseek_wrapper(state_t *s, int handle, int offset, int whence) {
s->r_acc = make_reg(0, fseek(f, offset, whence));
}
-static char *_chdir_savedir(state_t *s) {
- char *cwd = sci_getcwd();
- char *save_dir = kernel_dereference_char_pointer(s, make_reg(s->sys_strings_segment, SYS_STRING_SAVEDIR), 0);
-
- if (chdir(save_dir) && sci_mkpath(save_dir)) {
- sciprintf(__FILE__": Can't chdir to savegame dir '%s' or create it\n", save_dir);
- free(cwd);
- return NULL;
- }
-
- if (!cwd)
- cwd = strdup(s->work_dir);
-
- return cwd; // Potentially try again
-}
-
-static void _chdir_restoredir(char *dir) {
- if (chdir(dir)) {
- sciprintf(__FILE__": Can't seem to return to previous homedir '%s'\n", dir);
- }
- free(dir);
-}
-
#define TEST_DIR_OR_QUIT(dir) if (!dir) { return NULL_REG; }
reg_t kFGets(state_t *s, int funct_nr, int argc, reg_t *argv) {
@@ -314,36 +294,13 @@ reg_t kGetCWD(state_t *s, int funct_nr, int argc, reg_t *argv) {
return argv[0];
}
-// Returns a dynamically allocated pointer to the name of the requested save dir
-char *_k_get_savedir_name(int nr) {
- char suffices[] = "0123456789abcdefghijklmnopqrstuvwxyz";
- char *savedir_name = (char*)sci_malloc(strlen(FREESCI_SAVEDIR_PREFIX) + 2);
- assert(nr >= 0);
- assert(nr < MAX_SAVEGAME_NR);
- strcpy(savedir_name, FREESCI_SAVEDIR_PREFIX);
- savedir_name[strlen(FREESCI_SAVEDIR_PREFIX)] = suffices[nr];
- savedir_name[strlen(FREESCI_SAVEDIR_PREFIX) + 1] = 0;
-
- return savedir_name;
-}
-
void delete_savegame(state_t *s, int savedir_nr) {
- char *workdir = _chdir_savedir(s);
- char *savedir = _k_get_savedir_name(savedir_nr);
- char buffer[256];
-
- sciprintf("Deleting savegame '%s'\n", savedir);
-
- sprintf(buffer, "%s/%s.id", savedir, s->game_name);
- sci_unlink(buffer);
-
- sprintf(buffer, "%s/state", savedir);
- sci_unlink(buffer);
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_nr);
- sci_rmdir(savedir);
+ sciprintf("Deleting savegame '%s'\n", filename.c_str());
- free(savedir);
- _chdir_restoredir(workdir);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ saveFileMan->removeSavefile(filename.c_str());
}
#define K_DEVICE_INFO_GET_DEVICE 0
@@ -553,216 +510,145 @@ int _k_check_file(char *filename, int minfilesize) {
return (sci_file_size(filename) < minfilesize);
}
-int _k_find_savegame_by_name(char *game_id_file, char *name) {
- int savedir_nr = -1;
- int i;
- char *buf = NULL;
-
- for (i = 0; i < MAX_SAVEGAME_NR; i++) {
- if (!chdir((buf = _k_get_savedir_name(i)))) {
- char namebuf[32]; // Save game name buffer
- FILE *idfile = sci_fopen(game_id_file, "r");
-
- if (idfile) {
- fgets(namebuf, 31, idfile);
- if (strlen(namebuf) > 0)
- if (namebuf[strlen(namebuf) - 1] == '\n')
- namebuf[strlen(namebuf) - 1] = 0; // Remove trailing newlines
-
- if (strcmp(name, namebuf) == 0) {
- sciprintf("Save game name matched entry %d\n", i);
- savedir_nr = i;
- }
- fclose(idfile);
- }
- chdir("..");
- }
- free(buf);
- }
- return 0;
-}
-
-#ifdef __DC__
-static long get_file_mtime(int fd) {
- /* FIXME (Dreamcast): Not yet implemented */
- return 0;
-}
-
-#else
-
-#define get_file_mtime(fd) get_file_mtime_Unix(fd)
-/* Returns the time of the specified file's last modification
-** Parameters: (int) fd: The file descriptor of the file in question
-** Returns : (long) An integer value describing the time of the
-** file's last modification.
-** The only thing that must be ensured is that
-** get_file_mtime(f1) > get_file_mtime(f2)
-** <=>
-** if f1 was modified at a later point in time than the last time
-** f2 was modified.
-*/
-
-static long get_file_mtime_Unix(int fd) {
- struct stat fd_stat;
- fstat(fd, &fd_stat);
-
- return fd_stat.st_ctime;
-}
-#endif
-
static int _savegame_index_struct_compare(const void *a, const void *b) {
- return ((struct _savegame_index_struct *)b)->timestamp - ((struct _savegame_index_struct *)a)->timestamp;
+ struct _savegame_index_struct *A = (struct _savegame_index_struct *)a;
+ struct _savegame_index_struct *B = (struct _savegame_index_struct *)b;
+
+ if (B->date != A->date)
+ return B->date - A->date;
+ return B->time - A->time;
}
-static void update_savegame_indices(const char *gfname) {
+static void update_savegame_indices() {
int i;
_savegame_indices_nr = 0;
- for (i = 0; i < MAX_SAVEGAME_NR; i++) {
- char *dirname = _k_get_savedir_name(i);
- int fd;
-
- if (!chdir(dirname)) {
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
- if (IS_VALID_FD(fd = sci_open(gfname, O_RDONLY))) {
- _savegame_indices[_savegame_indices_nr].id = i;
- _savegame_indices[_savegame_indices_nr++].timestamp = get_file_mtime(fd);
- close(fd);
+ for (i = 0; i < MAX_SAVEGAME_NR; i++) {
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(i);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename.c_str()))) {
+ SavegameMetadata meta;
+ if (!get_savegame_metadata(in, &meta)) {
+ // invalid
+ delete in;
+ continue;
}
- chdir("..");
- }
-
- free(dirname);
- }
-
- qsort(_savegame_indices, _savegame_indices_nr, sizeof(struct _savegame_index_struct), _savegame_index_struct_compare);
-}
+ delete in;
-int test_savegame(state_t *s, char *savegame_id, char *savegame_name, int savegame_name_length) {
- FILE *f;
- char buffer[80];
- int version = -1;
-
- chdir(savegame_id);
- f = fopen("state", "r");
-
- if (!f) return 0;
- while (!feof(f)) {
- char *seeker;
- fgets(buffer, sizeof(buffer), f);
- if ((seeker = strstr(buffer, "savegame_version = ")) != NULL) {
- seeker += strlen("savegame_version = ");
- version = strtol(seeker, NULL, 10);
- break;
+ fprintf(stderr, "Savegame in %s file ok\n", filename.c_str());
+ _savegame_indices[_savegame_indices_nr].id = i;
+ _savegame_indices[_savegame_indices_nr].date = meta.savegame_date;
+ _savegame_indices[_savegame_indices_nr].time = meta.savegame_time;
+ _savegame_indices_nr++;
}
}
- fclose(f);
- return version >= FREESCI_MINIMUM_SAVEGAME_VERSION && version <= FREESCI_CURRENT_SAVEGAME_VERSION;
+ qsort(_savegame_indices, _savegame_indices_nr, sizeof(struct _savegame_index_struct), _savegame_index_struct_compare);
}
reg_t kCheckSaveGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
- char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
+ //char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
int savedir_nr = UKPV(1);
- char *buf = NULL;
- char *workdir = _chdir_savedir(s);
- TEST_DIR_OR_QUIT(workdir);
if (_savegame_indices_nr < 0) {
- char *game_id_file_name = (char*)sci_malloc(strlen(game_id) + strlen(FREESCI_ID_SUFFIX) + 1);
-
- strcpy(game_id_file_name, game_id);
- strcat(game_id_file_name, FREESCI_ID_SUFFIX);
warning("Savegame index list not initialized");
- update_savegame_indices(game_id_file_name);
+ update_savegame_indices();
}
savedir_nr = _savegame_indices[savedir_nr].id;
if (savedir_nr > MAX_SAVEGAME_NR - 1) {
- _chdir_restoredir(workdir);
return NULL_REG;
}
- s->r_acc = make_reg(0, test_savegame(s, (buf = _k_get_savedir_name(savedir_nr)), NULL, 0));
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_nr);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename.c_str()))) {
+ // found a savegame file
- _chdir_restoredir(workdir);
- free(buf);
+ 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(state_t *s, int funct_nr, int argc, reg_t *argv) {
- char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
+ //char *game_id = kernel_dereference_char_pointer(s, argv[0], 0);
char *nametarget = kernel_dereference_char_pointer(s, argv[1], 0);
reg_t nametarget_base = argv[1];
reg_t *nameoffsets = kernel_dereference_reg_pointer(s, argv[2], 0);
- int gfname_len = strlen(game_id) + strlen(FREESCI_ID_SUFFIX) + 1;
- char *gfname = (char*)sci_malloc(gfname_len);
int i;
- char *workdir = _chdir_savedir(s);
- TEST_DIR_OR_QUIT(workdir);
-
- strcpy(gfname, game_id);
- strcat(gfname, FREESCI_ID_SUFFIX); // This file is used to identify in-game savegames
- update_savegame_indices(gfname);
+ update_savegame_indices();
s->r_acc = NULL_REG;
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
for (i = 0; i < _savegame_indices_nr; i++) {
- char *savedir_name = _k_get_savedir_name(_savegame_indices[i].id);
- FILE *idfile;
-
- if (!chdir(savedir_name)) {
- if ((idfile = sci_fopen(gfname, "r"))) { // Valid game ID file: Assume valid game
- char namebuf[SCI_MAX_SAVENAME_LENGTH]; // Save game name buffer
- fgets(namebuf, SCI_MAX_SAVENAME_LENGTH - 1, idfile);
- if (strlen(namebuf) > 0) {
- if (namebuf[strlen(namebuf) - 1] == '\n')
- namebuf[strlen(namebuf) - 1] = 0; // Remove trailing newline
-
- *nameoffsets = s->r_acc; // Store savegame ID
- ++s->r_acc.offset; // Increase number of files found
-
- nameoffsets++; // Make sure the next ID string address is written to the next pointer
- strncpy(nametarget, namebuf, SCI_MAX_SAVENAME_LENGTH); // Copy identifier string
- *(nametarget + SCI_MAX_SAVENAME_LENGTH - 1) = 0; // Make sure it's terminated
- nametarget += SCI_MAX_SAVENAME_LENGTH; // Increase name offset pointer accordingly
- nametarget_base.offset += SCI_MAX_SAVENAME_LENGTH;
- fclose(idfile);
- }
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(_savegame_indices[i].id);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename.c_str()))) {
+ // found a savegame file
+
+ SavegameMetadata meta;
+ if (!get_savegame_metadata(in, &meta)) {
+ // invalid
+ delete in;
+ continue;
+ }
+
+ char namebuf[SCI_MAX_SAVENAME_LENGTH]; // Save game name buffer
+ strncpy(namebuf, meta.savegame_name, SCI_MAX_SAVENAME_LENGTH);
+ namebuf[SCI_MAX_SAVENAME_LENGTH-1] = 0;
+
+ if (strlen(namebuf) > 0) {
+ if (namebuf[strlen(namebuf) - 1] == '\n')
+ namebuf[strlen(namebuf) - 1] = 0; // Remove trailing newline
+
+ *nameoffsets = s->r_acc; // Store savegame ID
+ ++s->r_acc.offset; // Increase number of files found
+
+ nameoffsets++; // Make sure the next ID string address is written to the next pointer
+ strncpy(nametarget, namebuf, SCI_MAX_SAVENAME_LENGTH); // Copy identifier string
+ *(nametarget + SCI_MAX_SAVENAME_LENGTH - 1) = 0; // Make sure it's terminated
+ nametarget += SCI_MAX_SAVENAME_LENGTH; // Increase name offset pointer accordingly
+ nametarget_base.offset += SCI_MAX_SAVENAME_LENGTH;
}
- chdir("..");
+ delete in;
}
- free(savedir_name);
}
- free(gfname);
+ //free(gfname);
*nametarget = 0; // Terminate list
- _chdir_restoredir(workdir);
return s->r_acc;
}
reg_t kSaveGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
- char *game_id = (char*)kernel_dereference_bulk_pointer(s, argv[0], 0);
- char *savegame_dir;
+ //char *game_id = (char*)kernel_dereference_bulk_pointer(s, argv[0], 0);
int savedir_nr = UKPV(1);
int savedir_id; // Savegame ID, derived from savedir_nr and the savegame ID list
- char *game_id_file_name = (char*)sci_malloc(strlen(game_id) + strlen(FREESCI_ID_SUFFIX) + 1);
char *game_description = (char*)kernel_dereference_bulk_pointer(s, argv[2], 0);
- char *workdir = _chdir_savedir(s);
char *version = argc > 3 ? strdup((char*)kernel_dereference_bulk_pointer(s, argv[3], 0)) : NULL;
- TEST_DIR_OR_QUIT(workdir);
s->game_version = version;
- strcpy(game_id_file_name, game_id);
- strcat(game_id_file_name, FREESCI_ID_SUFFIX);
+ update_savegame_indices();
- update_savegame_indices(game_id_file_name);
+ fprintf(stderr, "savedir_nr = %d\n", savedir_nr);
if (savedir_nr >= 0 && savedir_nr < _savegame_indices_nr)
// Overwrite
@@ -770,6 +656,8 @@ reg_t kSaveGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
else if (savedir_nr >= 0 && savedir_nr < MAX_SAVEGAME_NR) {
int i = 0;
+ fprintf(stderr, "searching for hole\n");
+
savedir_id = 0;
// First, look for holes
@@ -790,31 +678,29 @@ reg_t kSaveGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
return NULL_REG;
}
- savegame_dir = _k_get_savedir_name(savedir_id);
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_id);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ Common::OutSaveFile *out;
+ if (!(out = saveFileMan->openForSaving(filename.c_str()))) {
+ sciprintf("Error opening savegame \"%s\" for writing\n", filename.c_str());
+ s->r_acc = NULL_REG;
+ return NULL_REG;
+ }
- if (gamestate_save(s, savegame_dir)) {
+ if (gamestate_save(s, out, game_description)) {
sciprintf("Saving the game failed.\n");
s->r_acc = NULL_REG;
} else {
- FILE *idfile;
-
- chdir(savegame_dir);
-
- if ((idfile = sci_fopen(game_id_file_name, "w"))) {
- fprintf(idfile, "%s", game_description);
- fclose(idfile);
- } else {
- sciprintf("Creating the game ID file failed.\n");
- sciprintf("You can still restore from inside the debugger with \"restore_game %s\"\n", savegame_dir);
+ out->finalize();
+ if (out->err()) {
+ delete out;
+ sciprintf("Writing the savegame failed.\n");
s->r_acc = NULL_REG;
+ } else {
+ delete out;
+ s->r_acc = make_reg(0, 1);
}
-
- chdir("..");
- s->r_acc = make_reg(0, 1);
}
- free(game_id_file_name);
- _chdir_restoredir(workdir);
-
free(s->game_version);
s->game_version = NULL;
@@ -824,39 +710,38 @@ reg_t kSaveGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
reg_t kRestoreGame(state_t *s, int funct_nr, int argc, reg_t *argv) {
char *game_id = (char*)kernel_dereference_bulk_pointer(s, argv[0], 0);
int savedir_nr = UKPV(1);
- char *workdir = _chdir_savedir(s);
- TEST_DIR_OR_QUIT(workdir);
if (_savegame_indices_nr < 0) {
- char *game_id_file_name = (char*)sci_malloc(strlen(game_id) + strlen(FREESCI_ID_SUFFIX) + 1);
-
- strcpy(game_id_file_name, game_id);
- strcat(game_id_file_name, FREESCI_ID_SUFFIX);
warning("Savegame index list not initialized");
- update_savegame_indices(game_id_file_name);
+ update_savegame_indices();
}
savedir_nr = _savegame_indices[savedir_nr].id;
if (savedir_nr > -1) {
- char *savedir_name = _k_get_savedir_name(savedir_nr);
- state_t *newstate = gamestate_restore(s, savedir_name);
-
- free(savedir_name);
- if (newstate) {
- s->successor = newstate;
- script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
- s->execution_stack_pos = s->execution_stack_base;
- } else {
- s->r_acc = make_reg(0, 1);
- sciprintf("Restoring failed (game_id = '%s').\n", game_id);
+ Common::SaveFileManager *saveFileMan = g_engine->getSaveFileManager();
+ Common::String filename = ((Sci::SciEngine*)g_engine)->getSavegameName(savedir_nr);
+ Common::SeekableReadStream *in;
+ if ((in = saveFileMan->openForLoading(filename.c_str()))) {
+ // found a savegame file
+
+ state_t *newstate = gamestate_restore(s, in);
+ delete in;
+
+ if (newstate) {
+ s->successor = newstate;
+ script_abort_flag = SCRIPT_ABORT_WITH_REPLAY; // Abort current game
+ s->execution_stack_pos = s->execution_stack_base;
+ } else {
+ s->r_acc = make_reg(0, 1);
+ sciprintf("Restoring failed (game_id = '%s').\n", game_id);
+ }
+ return s->r_acc;
}
- } else {
- s->r_acc = make_reg(0, 1);
- sciprintf("Savegame #%d not found", savedir_nr);
}
- _chdir_restoredir(workdir);
+ s->r_acc = make_reg(0, 1);
+ sciprintf("Savegame #%d not found!\n", savedir_nr);
return s->r_acc;
}