aboutsummaryrefslogtreecommitdiff
path: root/engines/glk
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk')
-rw-r--r--engines/glk/frotz/frotz.cpp169
-rw-r--r--engines/glk/frotz/frotz.h8
-rw-r--r--engines/glk/frotz/processor_streams.cpp211
-rw-r--r--engines/glk/glk.cpp52
-rw-r--r--engines/glk/glk.h35
-rw-r--r--engines/glk/scott/scott.cpp45
-rw-r--r--engines/glk/scott/scott.h10
-rw-r--r--engines/glk/streams.h2
8 files changed, 281 insertions, 251 deletions
diff --git a/engines/glk/frotz/frotz.cpp b/engines/glk/frotz/frotz.cpp
index a6371b6ef3..344aa92b12 100644
--- a/engines/glk/frotz/frotz.cpp
+++ b/engines/glk/frotz/frotz.cpp
@@ -84,13 +84,174 @@ void Frotz::initialize() {
z_restart();
}
-Common::Error Frotz::loadGameState(int slot) {
- // TODO
+Common::Error Frotz::saveGameData(strid_t file) {
+#ifdef TODO
+ long pc;
+ zword addr;
+ zword nsp, nfp;
+ int skip;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt(FILE_SAVE)) == nullptr)
+ goto finished;
+
+ if (_save_quetzal) {
+ success = save_quetzal(gfp, story_fp, blorb_ofs);
+ }
+ else {
+ /* Write game file */
+
+ fputc((int)hi(h_release), gfp);
+ fputc((int)lo(h_release), gfp);
+ fputc((int)hi(h_checksum), gfp);
+ fputc((int)lo(h_checksum), gfp);
+
+ GET_PC(pc)
+
+ fputc((int)(pc >> 16) & 0xff, gfp);
+ fputc((int)(pc >> 8) & 0xff, gfp);
+ fputc((int)(pc)& 0xff, gfp);
+
+ nsp = (int)(_sp - _stack);
+ nfp = (int)(_fp - _stack);
+
+ fputc((int)hi(nsp), gfp);
+ fputc((int)lo(nsp), gfp);
+ fputc((int)hi(nfp), gfp);
+ fputc((int)lo(nfp), gfp);
+
+ for (i = nsp; i < STACK_SIZE; i++) {
+ fputc((int)hi(_stack[i]), gfp);
+ fputc((int)lo(_stack[i]), gfp);
+ }
+
+ fseek(story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
+ if (zmp[addr] != fgetc(story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
+ fputc(skip, gfp);
+ fputc(zmp[addr], gfp);
+ skip = 0;
+ }
+ else skip++;
+ }
+
+ /* Close game file and check for errors */
+
+ if (fclose(gfp) == EOF || ferror(story_fp)) {
+ print_string("Error writing save file\n");
+ goto finished;
+ }
+
+ /* Success */
+
+ success = 1;
+#endif
return Common::kNoError;
}
-Common::Error Frotz::saveGameState(int slot, const Common::String &desc) {
- // TODO
+Common::Error Frotz::loadGameData(strid_t file) {
+#ifdef TODO
+ long pc;
+ zword release;
+ zword addr;
+ int i;
+
+ /* Open game file */
+
+ if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
+ goto finished;
+
+ if (_save_quetzal) {
+ success = restore_quetzal (gfp, story_fp, blorb_ofs);
+
+ } else {
+ /* Load game file */
+
+ release = (unsigned) fgetc (gfp) << 8;
+ release |= fgetc (gfp);
+
+ () fgetc (gfp);
+ () fgetc (gfp);
+
+ /* Check the release number */
+
+ if (release == h_release) {
+
+ pc = (long) fgetc (gfp) << 16;
+ pc |= (unsigned) fgetc (gfp) << 8;
+ pc |= fgetc (gfp);
+
+ SET_PC (pc);
+
+ _sp = _stack + (fgetc (gfp) << 8);
+ _sp += fgetc (gfp);
+ _fp = _stack + (fgetc (gfp) << 8);
+ _fp += fgetc (gfp);
+
+ for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
+ _stack[i] = (unsigned) fgetc (gfp) << 8;
+ _stack[i] |= fgetc (gfp);
+ }
+
+ fseek (story_fp, blorb_ofs, SEEK_SET);
+
+ for (addr = 0; addr < h_dynamic_size; addr++) {
+ int skip = fgetc (gfp);
+ for (i = 0; i < skip; i++)
+ zmp[addr++] = fgetc (story_fp);
+ zmp[addr] = fgetc (gfp);
+ () fgetc (story_fp);
+ }
+
+ /* Check for errors */
+
+ if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
+ success = -1;
+ else
+
+ /* Success */
+
+ success = 2;
+
+ } else print_string ("Invalid save file\n");
+ }
+
+ if ((short) success >= 0) {
+
+ /* Close game file */
+
+ fclose (gfp);
+
+ if ((short) success > 0) {
+ zbyte old_screen_rows;
+ zbyte old_screen_cols;
+
+ /* In V3, reset the upper window. */
+ if (h_version == V3)
+ split_window (0);
+
+ LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
+ LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
+
+ /* Reload cached header fields. */
+ restart_header ();
+
+ /*
+ * Since QUETZAL files may be saved on many different machines,
+ * the screen sizes may vary a lot. Erasing the status window
+ * seems to cover up most of the resulting badness.
+ */
+ if (h_version > V3 && h_version != V6
+ && (h_screen_rows != old_screen_rows
+ || h_screen_cols != old_screen_cols))
+ erase_window (1);
+ }
+ } else
+ os_fatal ("Error reading save file");
+#endif
return Common::kNoError;
}
diff --git a/engines/glk/frotz/frotz.h b/engines/glk/frotz/frotz.h
index e45abc07a8..00aeb599fb 100644
--- a/engines/glk/frotz/frotz.h
+++ b/engines/glk/frotz/frotz.h
@@ -54,14 +54,14 @@ public:
virtual void runGame(Common::SeekableReadStream *gameFile) override;
/**
- * Load a savegame
+ * Load a savegame from the passed stream
*/
- virtual Common::Error loadGameState(int slot) override;
+ virtual Common::Error loadGameData(strid_t file) override;
/**
- * Save the game
+ * Save the game to the passed stream
*/
- virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+ virtual Common::Error saveGameData(strid_t file) override;
};
extern Frotz *g_vm;
diff --git a/engines/glk/frotz/processor_streams.cpp b/engines/glk/frotz/processor_streams.cpp
index 091165ed7c..cbef38aaa6 100644
--- a/engines/glk/frotz/processor_streams.cpp
+++ b/engines/glk/frotz/processor_streams.cpp
@@ -545,227 +545,54 @@ void Processor::z_restart() {
}
void Processor::z_save() {
-#ifdef TODO
bool success = false;
if (zargc != 0) {
// Open auxilary file
frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
filemode_Write, 0);
- if (ref == nullptr)
- goto finished;
+ if (ref != nullptr) {
+ // Write data
+ strid_t f = glk_stream_open_file(ref, filemode_Write);
- // Write data
- strid_t f = glk_stream_open_file(ref, filemode_Write);
+ glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
- glk_put_buffer_stream(f, (const char *)zmp + zargs[0], zargs[1]);
-
- glk_stream_close(f);
-
- } else {
- long pc;
- zword addr;
- zword nsp, nfp;
- int skip;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt (FILE_SAVE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = save_quetzal (gfp, story_fp, blorb_ofs);
- } else {
- /* Write game file */
-
- fputc ((int) hi (h_release), gfp);
- fputc ((int) lo (h_release), gfp);
- fputc ((int) hi (h_checksum), gfp);
- fputc ((int) lo (h_checksum), gfp);
-
- GET_PC (pc)
-
- fputc ((int) (pc >> 16) & 0xff, gfp);
- fputc ((int) (pc >> 8) & 0xff, gfp);
- fputc ((int) (pc) & 0xff, gfp);
-
- nsp = (int) (_sp - _stack);
- nfp = (int) (_fp - _stack);
-
- fputc ((int) hi (nsp), gfp);
- fputc ((int) lo (nsp), gfp);
- fputc ((int) hi (nfp), gfp);
- fputc ((int) lo (nfp), gfp);
-
- for (i = nsp; i < STACK_SIZE; i++) {
- fputc ((int) hi (_stack[i]), gfp);
- fputc ((int) lo (_stack[i]), gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0, skip = 0; addr < h_dynamic_size; addr++)
- if (zmp[addr] != fgetc (story_fp) || skip == 255 || addr + 1 == h_dynamic_size) {
- fputc (skip, gfp);
- fputc (zmp[addr], gfp);
- skip = 0;
- } else skip++;
+ glk_stream_close(f);
+ success = true;
}
-
- /* Close game file and check for errors */
-
- if (fclose (gfp) == EOF || ferror (story_fp)) {
- print_string ("Error writing save file\n");
- goto finished;
- }
-
- /* Success */
-
- success = 1;
-
+ } else {
+ success = saveGame().getCode() == Common::kNoError;
}
-finished:
-
if (h_version <= V3)
branch (success);
else
store (success);
-#endif
}
void Processor::z_restore() {
-#ifdef TODO
- FILE *gfp;
-
- zword success = 0;
+ bool success = false;
if (zargc != 0) {
+ frefid_t ref = glk_fileref_create_by_prompt(fileusage_Data | fileusage_BinaryMode,
+ filemode_Read, 0);
+ if (ref != nullptr) {
+ // Write data
+ strid_t f = glk_stream_open_file(ref, filemode_Read);
- /* Get the file name */
-
- /* Open auxilary file */
-
- if ((gfp = frotzopenprompt(FILE_LOAD_AUX)) == nullptr)
- goto finished;
-
- /* Load auxilary file */
-
- success = fread (zmp + zargs[0], 1, zargs[1], gfp);
-
- /* Close auxilary file */
-
- fclose (gfp);
-
- } else {
-
- long pc;
- zword release;
- zword addr;
- int i;
-
- /* Open game file */
-
- if ((gfp = frotzopenprompt(FILE_RESTORE)) == nullptr)
- goto finished;
-
- if (_save_quetzal) {
- success = restore_quetzal (gfp, story_fp, blorb_ofs);
-
- } else {
- /* Load game file */
-
- release = (unsigned) fgetc (gfp) << 8;
- release |= fgetc (gfp);
-
- () fgetc (gfp);
- () fgetc (gfp);
-
- /* Check the release number */
-
- if (release == h_release) {
-
- pc = (long) fgetc (gfp) << 16;
- pc |= (unsigned) fgetc (gfp) << 8;
- pc |= fgetc (gfp);
-
- SET_PC (pc);
-
- _sp = _stack + (fgetc (gfp) << 8);
- _sp += fgetc (gfp);
- _fp = _stack + (fgetc (gfp) << 8);
- _fp += fgetc (gfp);
-
- for (i = (int) (_sp - _stack); i < STACK_SIZE; i++) {
- _stack[i] = (unsigned) fgetc (gfp) << 8;
- _stack[i] |= fgetc (gfp);
- }
-
- fseek (story_fp, blorb_ofs, SEEK_SET);
-
- for (addr = 0; addr < h_dynamic_size; addr++) {
- int skip = fgetc (gfp);
- for (i = 0; i < skip; i++)
- zmp[addr++] = fgetc (story_fp);
- zmp[addr] = fgetc (gfp);
- () fgetc (story_fp);
- }
-
- /* Check for errors */
-
- if (ferror (gfp) || ferror (story_fp) || addr != h_dynamic_size)
- success = -1;
- else
-
- /* Success */
-
- success = 2;
+ glk_get_buffer_stream(f, (char *)zmp + zargs[0], zargs[1]);
- } else print_string ("Invalid save file\n");
+ glk_stream_close(f);
+ success = true;
}
-
- if ((short) success >= 0) {
-
- /* Close game file */
-
- fclose (gfp);
-
- if ((short) success > 0) {
- zbyte old_screen_rows;
- zbyte old_screen_cols;
-
- /* In V3, reset the upper window. */
- if (h_version == V3)
- split_window (0);
-
- LOW_BYTE (H_SCREEN_ROWS, old_screen_rows);
- LOW_BYTE (H_SCREEN_COLS, old_screen_cols);
-
- /* Reload cached header fields. */
- restart_header ();
-
- /*
- * Since QUETZAL files may be saved on many different machines,
- * the screen sizes may vary a lot. Erasing the status window
- * seems to cover up most of the resulting badness.
- */
- if (h_version > V3 && h_version != V6
- && (h_screen_rows != old_screen_rows
- || h_screen_cols != old_screen_cols))
- erase_window (1);
- }
- } else
- os_fatal ("Error reading save file");
+ } else {
+ success = loadGame().getCode() == Common::kNoError;
}
-finished:
-
if (h_version <= V3)
branch (success);
else
store (success);
-#endif
}
void Processor::z_verify() {
diff --git a/engines/glk/glk.cpp b/engines/glk/glk.cpp
index 987fbc894a..a3cd167ae7 100644
--- a/engines/glk/glk.cpp
+++ b/engines/glk/glk.cpp
@@ -117,4 +117,56 @@ void GlkEngine::GUIError(const char *msg, ...) {
GUIErrorMessage(buffer);
}
+Common::Error GlkEngine::loadGame() {
+ frefid_t ref = _streams->createByPrompt(fileusage_BinaryMode | fileusage_SavedGame,
+ filemode_Read, 0);
+ if (ref == nullptr)
+ return Common::kReadingFailed;
+
+ int slotNumber = ref->_slotNumber;
+ _streams->deleteRef(ref);
+
+ return loadGameState(slotNumber);
+}
+
+Common::Error GlkEngine::saveGame() {
+ frefid_t ref = _streams->createByPrompt(fileusage_BinaryMode | fileusage_SavedGame,
+ filemode_Write, 0);
+ if (ref == nullptr)
+ return Common::kWritingFailed;
+
+ int slot = ref->_slotNumber;
+ Common::String desc = ref->_description;
+ _streams->deleteRef(ref);
+
+ return saveGameState(slot, desc);
+}
+
+Common::Error GlkEngine::loadGameState(int slot) {
+ FileReference ref(slot, "", fileusage_SavedGame | fileusage_TextMode);
+
+ strid_t file = _streams->openFileStream(&ref, filemode_Read);
+ if (file == nullptr)
+ return Common::kReadingFailed;
+
+ Common::Error result = saveGameData(file);
+
+ file->close();
+ return result;
+}
+
+Common::Error GlkEngine::saveGameState(int slot, const Common::String &desc) {
+ Common::String msg;
+ FileReference ref(slot, desc, fileusage_BinaryMode | fileusage_SavedGame);
+
+ strid_t file = _streams->openFileStream(&ref, filemode_Write);
+ if (file == nullptr)
+ return Common::kWritingFailed;
+
+ Common::Error result = loadGameData(file);
+
+ file->close();
+ return result;
+}
+
} // End of namespace Glk
diff --git a/engines/glk/glk.h b/engines/glk/glk.h
index 8dce78f085..f925fd0cc3 100644
--- a/engines/glk/glk.h
+++ b/engines/glk/glk.h
@@ -30,6 +30,7 @@
#include "engines/advancedDetector.h"
#include "engines/engine.h"
#include "glk/glk_types.h"
+#include "glk/streams.h"
namespace Glk {
@@ -181,6 +182,11 @@ public:
}
/**
+ * Display a message in a GUI dialog
+ */
+ void GUIError(const char *msg, ...);
+
+ /**
* Return the filename for a given save slot
*/
Common::String getSaveName(uint slot) const {
@@ -188,9 +194,34 @@ public:
}
/**
- * Display a message in a GUI dialog
+ * Prompt the user for a savegame to load, and then load it
*/
- void GUIError(const char *msg, ...);
+ Common::Error loadGame();
+
+ /**
+ * Prompt the user to save their game, and then save it
+ */
+ Common::Error saveGame();
+
+ /**
+ * Load a savegame from a given slot
+ */
+ virtual Common::Error loadGameState(int slot) override;
+
+ /**
+ * Save the game to a given slot
+ */
+ virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+
+ /**
+ * Load a savegame from the passed file
+ */
+ virtual Common::Error loadGameData(strid_t file) = 0;
+
+ /**
+ * Save the game to the passed file
+ */
+ virtual Common::Error saveGameData(strid_t file) = 0;
};
extern GlkEngine *g_vm;
diff --git a/engines/glk/scott/scott.cpp b/engines/glk/scott/scott.cpp
index fed31f014e..cbc5886130 100644
--- a/engines/glk/scott/scott.cpp
+++ b/engines/glk/scott/scott.cpp
@@ -309,7 +309,7 @@ void Scott::loadDatabase(Common::SeekableReadStream *f, bool loud) {
if (loud)
debug("Reading %d actions.", na);
- for (uint idx = 0; idx < na + 1; ++idx) {
+ for (int idx = 0; idx < na + 1; ++idx) {
Action &a = _actions[idx];
readInts(f, 8,
&a._vocab, &a._condition[0], &a._condition[1], &a._condition[2],
@@ -503,26 +503,8 @@ void Scott::lineInput(char *buf, size_t n) {
buf[ev.val1] = 0;
}
-void Scott::saveGame(void) {
- frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Write, 0);
- if (ref == nullptr)
- return;
-
- int slot = ref->_slotNumber;
- Common::String desc = ref->_description;
- glk_fileref_destroy(ref);
-
- saveGameState(slot, desc);
-}
-
-Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
+Common::Error Scott::saveGameData(strid_t file) {
Common::String msg;
- FileReference ref(slot, desc, fileusage_TextMode | fileusage_SavedGame);
-
- strid_t file = glk_stream_open_file(&ref, filemode_Write, 0);
- if (file == nullptr)
- return Common::kWritingFailed;
for (int ct = 0; ct < 16; ct++) {
msg = Common::String::format("%d %d\n", _counters[ct], _roomSaved[ct]);
@@ -539,37 +521,16 @@ Common::Error Scott::saveGameState(int slot, const Common::String &desc) {
glk_put_string_stream(file, msg.c_str());
}
- glk_stream_close(file, nullptr);
output("Saved.\n");
-
return Common::kNoError;
}
-void Scott::loadGame(void) {
- frefid_t ref = glk_fileref_create_by_prompt(fileusage_TextMode | fileusage_SavedGame,
- filemode_Read, 0);
- if (ref == nullptr)
- return;
-
- int slotNumber = ref->_slotNumber;
- glk_fileref_destroy(ref);
-
- loadGameState(slotNumber);
-}
-
-Common::Error Scott::loadGameState(int slot) {
- strid_t file;
+Common::Error Scott::loadGameData(strid_t file) {
char buf[128];
int ct = 0;
short lo;
short darkFlag;
- FileReference ref(slot, "", fileusage_SavedGame | fileusage_TextMode);
-
- file = glk_stream_open_file(&ref, filemode_Read, 0);
- if (file == nullptr)
- return Common::kReadingFailed;
-
for (ct = 0; ct < 16; ct++) {
glk_get_line_stream(file, buf, sizeof buf);
sscanf(buf, "%d %d", &_counters[ct], &_roomSaved[ct]);
diff --git a/engines/glk/scott/scott.h b/engines/glk/scott/scott.h
index 4741892687..a22f88bf94 100644
--- a/engines/glk/scott/scott.h
+++ b/engines/glk/scott/scott.h
@@ -153,8 +153,6 @@ private:
void look(void);
int whichWord(const char *word, const Common::StringArray &list);
void lineInput(char *buf, size_t n);
- void saveGame(void);
- void loadGame(void);
int getInput(int *vb, int *no);
int performLine(int ct);
int performActions(int vb, int no);
@@ -174,14 +172,14 @@ public:
virtual void runGame(Common::SeekableReadStream *gameFile) override;
/**
- * Load a savegame
+ * Load a savegame from the passed stream
*/
- virtual Common::Error loadGameState(int slot) override;
+ virtual Common::Error loadGameData(strid_t file) override;
/**
- * Save the game
+ * Save the game to the passed stream
*/
- virtual Common::Error saveGameState(int slot, const Common::String &desc) override;
+ virtual Common::Error saveGameData(strid_t file) override;
};
} // End of namespace Scott
diff --git a/engines/glk/streams.h b/engines/glk/streams.h
index 22a0a59602..3150ce9c38 100644
--- a/engines/glk/streams.h
+++ b/engines/glk/streams.h
@@ -563,7 +563,7 @@ public:
/**
* Open a file stream
*/
- FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock, bool unicode);
+ FileStream *openFileStream(frefid_t fref, glui32 fmode, glui32 rock = 0, bool unicode = false);
/**
* Open a window stream