From 7a3dd94de1e5343f00316d69674e46d129f56914 Mon Sep 17 00:00:00 2001 From: Paul Gilbert Date: Sun, 11 Nov 2018 21:57:30 -0800 Subject: GLK: FROTZ: Add undo data initialization --- engines/gargoyle/frotz/frotz.cpp | 3 +++ engines/gargoyle/frotz/glk_interface.cpp | 2 +- engines/gargoyle/frotz/glk_interface.h | 2 +- engines/gargoyle/frotz/mem.cpp | 29 ++++++++++++++++++++++++++++- engines/gargoyle/frotz/mem.h | 27 ++++++++++++++++++++++++++- engines/gargoyle/frotz/processor.cpp | 2 +- engines/gargoyle/frotz/processor.h | 2 +- 7 files changed, 61 insertions(+), 6 deletions(-) diff --git a/engines/gargoyle/frotz/frotz.cpp b/engines/gargoyle/frotz/frotz.cpp index df6d7364ac..5c861890bf 100644 --- a/engines/gargoyle/frotz/frotz.cpp +++ b/engines/gargoyle/frotz/frotz.cpp @@ -74,6 +74,9 @@ void Frotz::initialize() { // Call process initialization Processor::initialize(); + + // Restart the game + z_restart(); } Common::Error Frotz::loadGameState(int slot) { diff --git a/engines/gargoyle/frotz/glk_interface.cpp b/engines/gargoyle/frotz/glk_interface.cpp index f60ecc5009..13d0a562b5 100644 --- a/engines/gargoyle/frotz/glk_interface.cpp +++ b/engines/gargoyle/frotz/glk_interface.cpp @@ -26,7 +26,7 @@ namespace Gargoyle { namespace Frotz { GlkInterface::GlkInterface(OSystem *syst, const GargoyleGameDescription *gameDesc) : - Glk(syst, gameDesc), UserOptions(), + Glk(syst, gameDesc), oldstyle(0), curstyle(0), cury(1), curx(1), fixforced(0), curr_fg(-2), curr_bg(-2), curr_font(1), prev_font(1), temp_font(0), curr_status_ht(0), mach_status_ht(0), gos_status(nullptr), gos_upper(nullptr), diff --git a/engines/gargoyle/frotz/glk_interface.h b/engines/gargoyle/frotz/glk_interface.h index 1d30364683..f02fa0dd8c 100644 --- a/engines/gargoyle/frotz/glk_interface.h +++ b/engines/gargoyle/frotz/glk_interface.h @@ -40,7 +40,7 @@ enum SoundEffect { * Implements an intermediate interface on top of the GLK layer, providing screen * and sound effect handling */ -class GlkInterface : public Glk, public UserOptions, public virtual Mem { +class GlkInterface : public Glk, public virtual UserOptions, public virtual Mem { public: zchar statusline[256]; int oldstyle; diff --git a/engines/gargoyle/frotz/mem.cpp b/engines/gargoyle/frotz/mem.cpp index cb5a73b8d1..d9ff53d449 100644 --- a/engines/gargoyle/frotz/mem.cpp +++ b/engines/gargoyle/frotz/mem.cpp @@ -112,11 +112,15 @@ void Header::loadHeader(Common::SeekableReadStream &f) { /*--------------------------------------------------------------------------*/ -Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0) { +Mem::Mem() : story_fp(nullptr), blorb_ofs(0), blorb_len(0), story_size(0), + first_undo(nullptr), last_undo(nullptr), curr_undo(nullptr), + undo_mem(nullptr), prev_zmp(nullptr), undo_diff(nullptr), + undo_count(0), reserve_mem(0) { } void Mem::initialize() { initializeStoryFile(); + initializeUndo(); loadGameHeader(); // Allocate memory for story data @@ -173,6 +177,29 @@ void Mem::initializeStoryFile() { error("This file is too small to be a Z-code file."); } +void Mem::initializeUndo() { + void *reserved = nullptr; + + if (reserve_mem != 0) { + if ((reserved = malloc(reserve_mem)) == NULL) + return; + } + + // Allocate h_dynamic_size bytes for previous dynamic zmp state + // + 1.5 h_dynamic_size for Quetzal diff + 2. + undo_mem = new zbyte[(h_dynamic_size * 5) / 2 + 2]; + if (undo_mem != nullptr) { + prev_zmp = undo_mem; + undo_diff = undo_mem + h_dynamic_size; + memcpy(prev_zmp, zmp, h_dynamic_size); + } else { + _undo_slots = 0; + } + + if (reserve_mem != 0) + delete reserved; +} + void Mem::loadGameHeader() { // Load header zmp = new byte[64]; diff --git a/engines/gargoyle/frotz/mem.h b/engines/gargoyle/frotz/mem.h index 55cc4dc6fe..e12c062ff8 100644 --- a/engines/gargoyle/frotz/mem.h +++ b/engines/gargoyle/frotz/mem.h @@ -81,6 +81,21 @@ enum { HX_BACK_COLOUR = 6 }; +/** + * Stores undo information + */ +struct undo_struct { + undo_struct *next; + undo_struct *prev; + long pc; + long diff_size; + zword frame_count; + zword stack_size; + zword frame_offset; + // undo diff and stack data follow +}; +typedef undo_struct undo_t; + /** * Story file header data */ @@ -160,19 +175,29 @@ public: void loadHeader(Common::SeekableReadStream &f); }; -class Mem : public Header { +class Mem : public Header, public virtual UserOptions { protected: Common::SeekableReadStream *story_fp; uint blorb_ofs, blorb_len; uint story_size; byte *pcp; byte *zmp; + + undo_t *first_undo, *last_undo, *curr_undo; + zbyte *undo_mem, *prev_zmp, *undo_diff; + int undo_count; + int reserve_mem; private: /** * Handles setting the story file, parsing it if it's a Blorb file */ void initializeStoryFile(); + /** + * Setup undo data + */ + void initializeUndo(); + /** * Handles loading the game header */ diff --git a/engines/gargoyle/frotz/processor.cpp b/engines/gargoyle/frotz/processor.cpp index 20fb387b74..721f64b4bf 100644 --- a/engines/gargoyle/frotz/processor.cpp +++ b/engines/gargoyle/frotz/processor.cpp @@ -132,7 +132,7 @@ Opcode Processor::ext_opcodes[64] = { }; Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) : - GlkInterface(syst, gameDesc), Mem(), Errors(), + GlkInterface(syst, gameDesc), Errors(), _finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0), zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0), _randomInterval(0), _randomCtr(0), first_restart(true) { diff --git a/engines/gargoyle/frotz/processor.h b/engines/gargoyle/frotz/processor.h index a11fa1b966..77192b4f6a 100644 --- a/engines/gargoyle/frotz/processor.h +++ b/engines/gargoyle/frotz/processor.h @@ -412,7 +412,7 @@ private: zchar unicode_tolower(zchar c); /**@}*/ -private: +protected: /** * \defgroup General Opcode methods * @{ -- cgit v1.2.3