mirror of
https://github.com/libretro/scummvm.git
synced 2025-01-09 19:32:11 +00:00
219 lines
4.6 KiB
C++
219 lines
4.6 KiB
C++
/* 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 Glk {
|
|
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 Frotz
|
|
} // End of namespace Glk
|