GLK: FROTZ: Merge Err class into Processor

This commit is contained in:
Paul Gilbert 2018-11-12 18:27:04 -08:00 committed by Paul Gilbert
parent c19d40fa78
commit 6b23a72e51
9 changed files with 180 additions and 300 deletions

View File

@ -1,134 +0,0 @@
/* 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 "gargoyle/frotz/err.h"
#include "gargoyle/frotz/frotz.h"
#include "common/textconsole.h"
namespace Gargoyle {
namespace Frotz {
const char *const Errors::ERR_MESSAGES[ERR_NUM_ERRORS] = {
"Text buffer overflow",
"Store out of dynamic memory",
"Division by zero",
"Illegal object",
"Illegal attribute",
"No such property",
"Stack overflow",
"Call to illegal address",
"Call to non-routine",
"Stack underflow",
"Illegal opcode",
"Bad stack frame",
"Jump to illegal address",
"Can't save while in interrupt",
"Nesting stream #3 too deep",
"Illegal window",
"Illegal window property",
"Print at illegal address",
"Illegal dictionary word length",
"@jin called with object 0",
"@get_child called with object 0",
"@get_parent called with object 0",
"@get_sibling called with object 0",
"@get_prop_addr called with object 0",
"@get_prop called with object 0",
"@put_prop called with object 0",
"@clear_attr called with object 0",
"@set_attr called with object 0",
"@test_attr called with object 0",
"@move_object called moving object 0",
"@move_object called moving into object 0",
"@remove_object called with object 0",
"@get_next_prop called with object 0"
};
Errors::Errors() {
Common::fill(&_count[0], &_count[ERR_NUM_ERRORS], 0);
}
void Errors::runtimeError(ErrorCode errNum) {
#ifdef TODO
int wasfirst;
if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
return;
if (g_vm->_err_report_mode == ERR_REPORT_FATAL
|| (!g_vm->_ignore_errors && errNum <= ERR_MAX_FATAL)) {
g_vm->_buffer.flush();
error(ERR_MESSAGES[errNum - 1]);
return;
}
wasfirst = (_count[errNum - 1] == 0);
_count[errNum - 1]++;
if ((g_vm->_err_report_mode == ERR_REPORT_ALWAYS)
|| (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
long pc = g_vm->_processor
GET_PC(pc);
printString("Warning: ");
printString(ERR_MESSAGES[errNum - 1]);
printString(" (PC = ");
printLong(pc, 16);
printChar(')');
if (_err_report_mode == ERR_REPORT_ONCE) {
printString(" (will ignore further occurrences)");
} else {
printString(" (occurence ");
printLong(_count[errNum - 1], 10);
printChar(')');
}
newLine();
}
#endif
}
void Errors::printLong(uint value, int base) {
unsigned long i;
char c;
for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base)
if (value >= i || i == 1) {
c = (value / i) % base;
printChar(c + (c <= 9 ? '0' : 'a' - 10));
}
}
void Errors::printChar(const char c) {
// TODO
}
void Errors::printString(const char *str) {
// TODO
}
void Errors::newLine() {
// TODO
}
} // End of namespace Scott
} // End of namespace Gargoyle

View File

@ -1,117 +0,0 @@
/* 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.
*
*/
#ifndef GARGOYLE_FROTZ_ERR
#define GARGOYLE_FROTZ_ERR
#include "gargoyle/frotz/frotz_types.h"
namespace Gargoyle {
namespace Frotz {
enum ErrorCode {
ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
ERR_DIV_ZERO = 3, ///< Division by zero
ERR_ILL_OBJ = 4, ///< Illegal object
ERR_ILL_ATTR = 5, ///< Illegal attribute
ERR_NO_PROP = 6, ///< No such property
ERR_STK_OVF = 7, ///< Stack overflow
ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
ERR_CALL_NON_RTN = 9, ///< Call to non-routine
ERR_STK_UNDF = 10, ///< Stack underflow
ERR_ILL_OPCODE = 11, ///< Illegal opcode
ERR_BAD_FRAME = 12, ///< Bad stack frame
ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
ERR_ILL_WIN = 16, ///< Illegal window
ERR_ILL_WIN_PROP = 17, ///< Illegal window property
ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
ERR_DICT_LEN = 19, ///< Illegal dictionary word length
ERR_MAX_FATAL = 19,
// Less serious errors
ERR_JIN_0 = 20, ///< @jin called with object 0
ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
ERR_NUM_ERRORS = 33
};
class Errors {
private:
static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
int _count[ERR_NUM_ERRORS];
private:
/**
* Print an unsigned 32bit number in decimal or hex.
*/
void printLong(uint value, int base);
/**
* Print a character
*/
void printChar(const char c);
/**
* Print a string
*/
void printString(const char *str);
/**
* Add a newline
*/
void newLine();
protected:
/**
* Get the PC. Is implemented by the Processor class, which derives from Errors
*/
virtual uint getPC() const = 0;
public:
/**
* Constructor
*/
Errors();
/**
* An error has occurred. Ignore it, pass it to os_fatal or report
* it according to err_report_mode.
* @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
*/
void runtimeError(ErrorCode errNum);
};
} // End of namespace Frotz
} // End of namespace Gargoyle
#endif

View File

@ -149,19 +149,59 @@ enum {
TRANSPARENT_FLAG = 0x0001 ///< Game wants to use transparency - V6
};
enum ErrorCode {
ERR_TEXT_BUF_OVF = 1, ///< Text buffer overflow
ERR_STORE_RANGE = 2, ///< Store out of dynamic memory
ERR_DIV_ZERO = 3, ///< Division by zero
ERR_ILL_OBJ = 4, ///< Illegal object
ERR_ILL_ATTR = 5, ///< Illegal attribute
ERR_NO_PROP = 6, ///< No such property
ERR_STK_OVF = 7, ///< Stack overflow
ERR_ILL_CALL_ADDR = 8, ///< Call to illegal address
ERR_CALL_NON_RTN = 9, ///< Call to non-routine
ERR_STK_UNDF = 10, ///< Stack underflow
ERR_ILL_OPCODE = 11, ///< Illegal opcode
ERR_BAD_FRAME = 12, ///< Bad stack frame
ERR_ILL_JUMP_ADDR = 13, ///< Jump to illegal address
ERR_SAVE_IN_INTER = 14, ///< Can't save while in interrupt
ERR_STR3_NESTING = 15, ///< Nesting stream #3 too deep
ERR_ILL_WIN = 16, ///< Illegal window
ERR_ILL_WIN_PROP = 17, ///< Illegal window property
ERR_ILL_PRINT_ADDR = 18, ///< Print at illegal address
ERR_DICT_LEN = 19, ///< Illegal dictionary word length
ERR_MAX_FATAL = 19,
// Less serious errors
ERR_JIN_0 = 20, ///< @jin called with object 0
ERR_GET_CHILD_0 = 21, ///< @get_child called with object 0
ERR_GET_PARENT_0 = 22, ///< @get_parent called with object 0
ERR_GET_SIBLING_0 = 23, ///< @get_sibling called with object 0
ERR_GET_PROP_ADDR_0 = 24, ///< @get_prop_addr called with object 0
ERR_GET_PROP_0 = 25, ///< @get_prop called with object 0
ERR_PUT_PROP_0 = 26, ///< @put_prop called with object 0
ERR_CLEAR_ATTR_0 = 27, ///< @clear_attr called with object 0
ERR_SET_ATTR_0 = 28, ///< @set_attr called with object 0
ERR_TEST_ATTR_0 = 29, ///< @test_attr called with object 0
ERR_MOVE_OBJECT_0 = 30, ///< @move_object called moving object 0
ERR_MOVE_OBJECT_TO_0 = 31, ///< @move_object called moving into object 0
ERR_REMOVE_OBJECT_0 = 32, ///< @remove_object called with object 0
ERR_GET_NEXT_PROP_0 = 33, ///< @get_next_prop called with object 0
ERR_NUM_ERRORS = 33
};
enum FrotzInterp {
#define INTERP_DEFAULT 0
#define INTERP_DEC_20 1
#define INTERP_APPLE_IIE 2
#define INTERP_MACINTOSH 3
#define INTERP_AMIGA 4
#define INTERP_ATARI_ST 5
#define INTERP_MSDOS 6
#define INTERP_CBM_128 7
#define INTERP_CBM_64 8
#define INTERP_APPLE_IIC 9
#define INTERP_APPLE_IIGS 10
#define INTERP_TANDY 11
INTERP_DEFAULT = 0,
INTERP_DEC_20 = 1,
INTERP_APPLE_IIE = 2,
INTERP_MACINTOSH = 3,
INTERP_AMIGA = 4,
INTERP_ATARI_ST = 5,
INTERP_MSDOS = 6,
INTERP_CBM_128 = 7,
INTERP_CBM_64 = 8,
INTERP_APPLE_IIC = 9,
INTERP_APPLE_IIGS = 10,
INTERP_TANDY = 11
};
enum Colour {

View File

@ -24,7 +24,6 @@
#define GARGOYLE_FROTZ_MEM
#include "gargoyle/frotz/frotz_types.h"
#include "gargoyle/frotz/err.h"
namespace Gargoyle {
namespace Frotz {

View File

@ -132,7 +132,7 @@ Opcode Processor::ext_opcodes[64] = {
};
Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
GlkInterface(syst, gameDesc), Errors(),
GlkInterface(syst, gameDesc),
_finished(0), _sp(nullptr), _fp(nullptr), _frameCount(0),
zargc(0), _decoded(nullptr), _encoded(nullptr), _resolution(0),
_randomInterval(0), _randomCtr(0), first_restart(true), script_valid(false),
@ -180,6 +180,7 @@ Processor::Processor(OSystem *syst, const GargoyleGameDescription *gameDesc) :
Common::fill(&_stack[0], &_stack[STACK_SIZE], 0);
Common::fill(&zargs[0], &zargs[8], 0);
Common::fill(&_buffer[0], &_buffer[TEXT_BUFFER_SIZE], '\0');
Common::fill(&_errorCount[0], &_errorCount[ERR_NUM_ERRORS], 0);
}
void Processor::initialize() {

View File

@ -23,7 +23,6 @@
#ifndef GARGOYLE_FROTZ_PROCESSOR
#define GARGOYLE_FROTZ_PROCESSOR
#include "gargoyle/frotz/err.h"
#include "gargoyle/frotz/mem.h"
#include "gargoyle/frotz/glk_interface.h"
#include "gargoyle/frotz/frotz_types.h"
@ -51,9 +50,15 @@ typedef void (Processor::*Opcode)();
/**
* Zcode processor
*/
class Processor : public Errors, public GlkInterface, public virtual Mem {
class Processor : public GlkInterface, public virtual Mem {
friend class Quetzal;
private:
Opcode op0_opcodes[16];
Opcode op1_opcodes[16];
static const char *const ERR_MESSAGES[ERR_NUM_ERRORS];
static Opcode var_opcodes[64];
static Opcode ext_opcodes[64];
int _finished;
zword zargs[8];
int zargc;
@ -72,17 +77,13 @@ private:
static zchar ZSCII_TO_LATIN1[];
zchar *_decoded, *_encoded;
int _resolution;
int _errorCount[ERR_NUM_ERRORS];
// Buffer related fields
zchar _buffer[TEXT_BUFFER_SIZE];
size_t _bufPos;
bool _locked;
zchar _prevC;
Opcode op0_opcodes[16];
Opcode op1_opcodes[16];
static Opcode var_opcodes[64];
static Opcode ext_opcodes[64];
zchar _buffer[TEXT_BUFFER_SIZE];
size_t _bufPos;
// Stream related fields
int script_width;
@ -172,6 +173,16 @@ private:
*/
void print_char(zchar c);
/**
* Print a string of ASCII characters.
*/
void print_string(const char *s);
/**
* Print an unsigned 32bit number in decimal or hex.
*/
void print_long(uint value, int base);
/**
* High level newline function.
*/
@ -182,6 +193,13 @@ private:
*/
bool bufferEmpty() const { return !_bufPos; }
/**
* An error has occurred. Ignore it, pass it to os_fatal or report
* it according to err_report_mode.
* @param errNum Numeric code for error (1 to ERR_NUM_ERRORS)
*/
void runtimeError(ErrorCode errNum);
/**@}*/
/**
@ -216,13 +234,6 @@ private:
* @{
*/
/**
* Generates a runtime error
*/
virtual void runtimeError(ErrorCode errNum) override {
Errors::runtimeError(errNum);
}
/**
* Called when the H_FLAGS field of the header has changed
*/
@ -1394,11 +1405,6 @@ protected:
*/
void z_print_ret();
/**
* Print a string of ASCII characters.
*/
void print_string(const char *s);
/**
* Print unicode character
*
@ -1561,9 +1567,8 @@ public:
/**
* Return the current program execution offset
* @remarks This virtual as a convenient way for the ancestor Err class to access
*/
virtual uint getPC() const override { return pcp - zmp; }
uint getPC() const { return pcp - zmp; }
/**
* Set the program execution offset

View File

@ -27,6 +27,42 @@
namespace Gargoyle {
namespace Frotz {
const char *const Processor::ERR_MESSAGES[ERR_NUM_ERRORS] = {
"Text buffer overflow",
"Store out of dynamic memory",
"Division by zero",
"Illegal object",
"Illegal attribute",
"No such property",
"Stack overflow",
"Call to illegal address",
"Call to non-routine",
"Stack underflow",
"Illegal opcode",
"Bad stack frame",
"Jump to illegal address",
"Can't save while in interrupt",
"Nesting stream #3 too deep",
"Illegal window",
"Illegal window property",
"Print at illegal address",
"Illegal dictionary word length",
"@jin called with object 0",
"@get_child called with object 0",
"@get_parent called with object 0",
"@get_sibling called with object 0",
"@get_prop_addr called with object 0",
"@get_prop called with object 0",
"@put_prop called with object 0",
"@clear_attr called with object 0",
"@set_attr called with object 0",
"@test_attr called with object 0",
"@move_object called moving object 0",
"@move_object called moving into object 0",
"@remove_object called with object 0",
"@get_next_prop called with object 0"
};
void Processor::flush_buffer() {
/* Make sure we stop when flush_buffer is called from flush_buffer.
* Note that this is difficult to avoid as we might print a newline
@ -85,10 +121,72 @@ void Processor::print_char(zchar c) {
}
}
void Processor::print_string(const char *s) {
char c;
while ((c = *s++) != 0) {
if (c == '\n')
new_line();
else
print_char(c);
}
}
void Processor::print_long(uint value, int base) {
unsigned long i;
char c;
for (i = (base == 10 ? 1000000000 : 0x10000000); i != 0; i /= base) {
if (value >= i || i == 1) {
c = (value / i) % base;
print_char(c + (c <= 9 ? '0' : 'a' - 10));
}
}
}
void Processor::new_line() {
flush_buffer();
stream_new_line();
}
void Processor::runtimeError(ErrorCode errNum) {
int wasfirst;
if (errNum <= 0 || errNum > ERR_NUM_ERRORS)
return;
if (_err_report_mode == ERR_REPORT_FATAL
|| (!_ignore_errors && errNum <= ERR_MAX_FATAL)) {
flush_buffer();
error(ERR_MESSAGES[errNum - 1]);
return;
}
wasfirst = (_errorCount[errNum - 1] == 0);
_errorCount[errNum - 1]++;
if ((_err_report_mode == ERR_REPORT_ALWAYS)
|| (_err_report_mode == ERR_REPORT_ONCE && wasfirst)) {
long pc;
GET_PC(pc);
print_string("Warning: ");
print_string(ERR_MESSAGES[errNum - 1]);
print_string(" (PC = ");
print_long(pc, 16);
print_char(')');
if (_err_report_mode == ERR_REPORT_ONCE) {
print_string(" (will ignore further occurrences)");
}
else {
print_string(" (occurence ");
print_long(_errorCount[errNum - 1], 10);
print_char(')');
}
new_line();
}
}
} // End of namespace Scott
} // End of namespace Gargoyle

View File

@ -479,17 +479,6 @@ void Processor::print_object(zword object) {
}
}
void Processor::print_string(const char *s) {
char c;
while ((c = *s++) != 0) {
if (c == '\n')
new_line();
else
print_char(c);
}
}
zword Processor::lookup_text(int padding, zword dct) {
zword entry_addr;
zword entry_count;

View File

@ -23,7 +23,6 @@ MODULE_OBJS := \
window_text_grid.o \
frotz/detection.o \
frotz/detection_tables.o \
frotz/err.o \
frotz/frotz.o \
frotz/glk_interface.o \
frotz/mem.o \