aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/frotz/processor_mem.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/frotz/processor_mem.cpp')
-rw-r--r--engines/glk/frotz/processor_mem.cpp218
1 files changed, 218 insertions, 0 deletions
diff --git a/engines/glk/frotz/processor_mem.cpp b/engines/glk/frotz/processor_mem.cpp
new file mode 100644
index 0000000000..7c7af0d2f5
--- /dev/null
+++ b/engines/glk/frotz/processor_mem.cpp
@@ -0,0 +1,218 @@
+/* ScummVM - Graphic Adventure Engine
+ *
+ * ScummVM is the legal property of its developers, whose names
+ * are too numerous to list here. Please refer to the COPYRIGHT
+ * file distributed with this source distribution.
+ *
+ * This program is free software; you can redistribute it and/or
+ * modify it under the terms of the GNU General Public License
+ * as published by the Free Software Foundation; either version 2
+ * of the License, or (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
+ *
+ */
+
+#include "glk/frotz/processor.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+void Processor::flagsChanged(zbyte value) {
+ if (value & SCRIPTING_FLAG) {
+ if (!ostream_script)
+ script_open();
+ } else {
+ if (ostream_script)
+ script_close();
+ }
+}
+
+int Processor::save_undo() {
+ long diff_size;
+ zword stack_size;
+ undo_t *p;
+
+ if (_undo_slots == 0)
+ // undo feature unavailable
+ return -1;
+
+ // save undo possible
+ while (last_undo != curr_undo) {
+ p = last_undo;
+ last_undo = last_undo->prev;
+ delete p;
+ undo_count--;
+ }
+ if (last_undo)
+ last_undo->next = nullptr;
+ else
+ first_undo = nullptr;
+
+ if (undo_count == _undo_slots)
+ free_undo(1);
+
+ diff_size = mem_diff(zmp, prev_zmp, h_dynamic_size, undo_diff);
+ stack_size = _stack + STACK_SIZE - _sp;
+ do {
+ p = (undo_t *) malloc(sizeof(undo_t) + diff_size + stack_size * sizeof(*_sp));
+ if (p == nullptr)
+ free_undo(1);
+ } while (!p && undo_count);
+ if (p == nullptr)
+ return -1;
+
+ GET_PC(p->pc);
+ p->frame_count = _frameCount;
+ p->diff_size = diff_size;
+ p->stack_size = stack_size;
+ p->frame_offset = _fp - _stack;
+ memcpy(p + 1, undo_diff, diff_size);
+ memcpy((zbyte *)(p + 1) + diff_size, _sp, stack_size * sizeof(*_sp));
+
+ if (!first_undo) {
+ p->prev = nullptr;
+ first_undo = p;
+ } else {
+ last_undo->next = p;
+ p->prev = last_undo;
+ }
+
+ p->next = nullptr;
+ curr_undo = last_undo = p;
+ undo_count++;
+
+ return 1;
+}
+
+int Processor::restore_undo(void) {
+ if (_undo_slots == 0)
+ // undo feature unavailable
+ return -1;
+
+ if (curr_undo == nullptr)
+ // no saved game state
+ return 0;
+
+ // undo possible
+ memcpy(zmp, prev_zmp, h_dynamic_size);
+ SET_PC(curr_undo->pc);
+ _sp = _stack + STACK_SIZE - curr_undo->stack_size;
+ _fp = _stack + curr_undo->frame_offset;
+ _frameCount = curr_undo->frame_count;
+ mem_undiff((zbyte *)(curr_undo + 1), curr_undo->diff_size, prev_zmp);
+ memcpy(_sp, (zbyte *)(curr_undo + 1) + curr_undo->diff_size,
+ curr_undo->stack_size * sizeof(*_sp));
+
+ curr_undo = curr_undo->prev;
+
+ restart_header();
+
+ return 2;
+}
+
+/**
+ * TOR: glkify -- this is for V6 only
+ */
+static zword get_max_width(zword win) { return 80; }
+
+void Processor::memory_open(zword table, zword xsize, bool buffering) {
+ if (_redirect.size() < MAX_NESTING) {
+ if (!buffering)
+ xsize = 0xffff;
+ if (buffering && (short)xsize <= 0)
+ xsize = get_max_width((zword)(-(short)xsize));
+
+ storew(table, 0);
+
+ _redirect.push(Redirect(xsize, table));
+ ostream_memory = true;
+ } else {
+ runtimeError(ERR_STR3_NESTING);
+ }
+}
+
+void Processor::memory_new_line() {
+ zword size;
+ zword addr;
+
+ Redirect &r = _redirect.top();
+ r._total += r._width;
+ r._width = 0;
+
+ addr = r._table;
+
+ LOW_WORD(addr, size);
+ addr += 2;
+
+ if (r._xSize != 0xffff) {
+ r._table = addr + size;
+ size = 0;
+ } else {
+ storeb((zword)(addr + (size++)), 13);
+ }
+
+ storew(r._table, size);
+}
+
+void Processor::memory_word(const zchar *s) {
+ zword size;
+ zword addr;
+ zchar c;
+
+ Redirect &r = _redirect.top();
+ if (h_version == V6) {
+ int width = os_string_width(s);
+
+ if (r._xSize != 0xffff) {
+ if (r._width + width > r._xSize) {
+
+ if (*s == ' ' || *s == ZC_INDENT || *s == ZC_GAP)
+ width = os_string_width(++s);
+
+ memory_new_line();
+ }
+ }
+
+ r._width += width;
+ }
+
+ addr = r._table;
+
+ LOW_WORD(addr, size);
+ addr += 2;
+
+ while ((c = *s++) != 0)
+ storeb((zword)(addr + (size++)), translate_to_zscii(c));
+
+ storew(r._table, size);
+}
+
+void Processor::memory_close(void) {
+ if (!_redirect.empty()) {
+ Redirect &r = _redirect.top();
+
+ if (r._xSize != 0xffff)
+ memory_new_line();
+
+ if (h_version == V6) {
+ h_line_width = (r._xSize != 0xffff) ? r._total : r._width;
+
+ SET_WORD(H_LINE_WIDTH, h_line_width);
+ }
+
+ _redirect.pop();
+ if (_redirect.empty())
+ ostream_memory = false;
+ }
+}
+
+} // End of namespace Scott
+} // End of namespace Gargoyle