aboutsummaryrefslogtreecommitdiff
path: root/engines/glk/frotz/processor.h
diff options
context:
space:
mode:
Diffstat (limited to 'engines/glk/frotz/processor.h')
-rw-r--r--engines/glk/frotz/processor.h1584
1 files changed, 1584 insertions, 0 deletions
diff --git a/engines/glk/frotz/processor.h b/engines/glk/frotz/processor.h
new file mode 100644
index 0000000000..b5c113def0
--- /dev/null
+++ b/engines/glk/frotz/processor.h
@@ -0,0 +1,1584 @@
+/* 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 GLK_FROTZ_PROCESSOR
+#define GLK_FROTZ_PROCESSOR
+
+#include "glk/frotz/mem.h"
+#include "glk/frotz/glk_interface.h"
+#include "glk/frotz/frotz_types.h"
+#include "common/stack.h"
+
+namespace Gargoyle {
+namespace Frotz {
+
+#define TEXT_BUFFER_SIZE 200
+
+#define CODE_BYTE(v) v = codeByte()
+#define CODE_WORD(v) v = codeWord()
+#define CODE_IDX_WORD(v,i) v = codeWordIdx(i)
+#define GET_PC(v) v = getPC()
+#define SET_PC(v) setPC(v)
+
+enum string_type {
+ LOW_STRING, ABBREVIATION, HIGH_STRING, EMBEDDED_STRING, VOCABULARY
+};
+
+class Processor;
+class Quetzal;
+typedef void (Processor::*Opcode)();
+
+/**
+ * Zcode processor
+ */
+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;
+ uint _randomInterval;
+ uint _randomCtr;
+ bool first_restart;
+ bool script_valid;
+
+ // Stack data
+ zword _stack[STACK_SIZE];
+ zword *_sp;
+ zword *_fp;
+ zword _frameCount;
+
+ // Text related fields
+ static zchar ZSCII_TO_LATIN1[];
+ zchar *_decoded, *_encoded;
+ int _resolution;
+ int _errorCount[ERR_NUM_ERRORS];
+
+ // Buffer related fields
+ bool _locked;
+ zchar _prevC;
+ zchar _buffer[TEXT_BUFFER_SIZE];
+ size_t _bufPos;
+
+ // Stream related fields
+ int script_width;
+ strid_t sfp, rfp, pfp;
+ Common::FixedStack<Redirect, MAX_NESTING> _redirect;
+private:
+ /**
+ * \defgroup General support methods
+ * @{
+ */
+
+ /**
+ * Load an operand, either a variable or a constant.
+ */
+ void load_operand(zbyte type);
+
+ /**
+ * Given the operand specifier byte, load all (up to four) operands
+ * for a VAR or EXT opcode.
+ */
+ void load_all_operands(zbyte specifier);
+
+ /**
+ * Call a subroutine. Save PC and FP then load new PC and initialise
+ * new stack frame. Note that the caller may legally provide less or
+ * more arguments than the function actually has. The call type "ct"
+ * can be 0 (z_call_s), 1 (z_call_n) or 2 (direct call).
+ */
+ void call(zword routine, int argc, zword *args, int ct);
+
+ /**
+ * Return from the current subroutine and restore the previous _stack
+ * frame. The result may be stored (0), thrown away (1) or pushed on
+ * the stack (2). In the latter case a direct call has been finished
+ * and we must exit the interpreter loop.
+ */
+ void ret(zword value);
+
+ /**
+ * Take a jump after an instruction based on the flag, either true or
+ * false. The branch can be short or long; it is encoded in one or two
+ * bytes respectively. When bit 7 of the first byte is set, the jump
+ * takes place if the flag is true; otherwise it is taken if the flag
+ * is false. When bit 6 of the first byte is set, the branch is short;
+ * otherwise it is long. The offset occupies the bottom 6 bits of the
+ * first byte plus all the bits in the second byte for long branches.
+ * Uniquely, an offset of 0 means return false, and an offset of 1 is
+ * return true.
+ */
+ void branch(bool flag);
+
+ /**
+ * Store an operand, either as a variable or pushed on the stack.
+ */
+ void store(zword value);
+
+ /*
+ * Call the interpreter loop directly. This is necessary when
+ *
+ * - a sound effect has been finished
+ * - a read instruction has timed out
+ * - a newline countdown has hit zero
+ *
+ * The interpreter returns the result value on the stack.
+ */
+ int direct_call(zword addr);
+
+ /**
+ * Set the seed value for the random number generator.
+ */
+ void seed_random(int value);
+
+ /**@}*/
+
+ /**
+ * \defgroup Input support methods
+ * @{
+ */
+
+ /**
+ * Copy the contents of the text buffer to the output streams.
+ */
+ void flush_buffer();
+
+ /**
+ * High level output function.
+ */
+ 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.
+ */
+ void new_line();
+
+ /**
+ * Returns true if the buffer is empty
+ */
+ 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);
+
+ /**@}*/
+
+ /**
+ * \defgroup Input support methods
+ * @{
+ */
+
+ /**
+ * Check if the given key is an input terminator.
+ */
+ bool is_terminator(zchar key);
+
+ /**
+ * Ask the user a question; return true if the answer is yes.
+ */
+ bool read_yes_or_no(const char *s);
+
+ /**
+ * Read a string from the current input stream.
+ */
+ void read_string(int max, zchar *buffer);
+
+ /**
+ * Ask the user to type in a number and return it.
+ */
+ int read_number();
+
+ /**@}*/
+
+ /**
+ * \defgroup Memory support methods
+ * @{
+ */
+
+ /**
+ * Called when the H_FLAGS field of the header has changed
+ */
+ virtual void flagsChanged(zbyte value) override;
+
+ /**
+ * This function does the dirty work for z_save_undo.
+ */
+ int save_undo();
+
+ /**
+ * This function does the dirty work for z_restore_undo.
+ */
+ int restore_undo();
+
+ /**
+ * Begin output redirection to the memory of the Z-machine.
+ */
+ void memory_open(zword table, zword xsize, bool buffering);
+
+ /**
+ * End of output redirection.
+ */
+ void memory_close();
+
+ /**
+ * Redirect a newline to the memory of the Z-machine.
+ */
+ void memory_new_line();
+
+ /**
+ * Redirect a string of characters to the memory of the Z-machine.
+ */
+ void memory_word(const zchar *s);
+
+ /**@}*/
+
+ /**
+ * \defgroup Object support methods
+ * @{
+ */
+
+ /**
+ * Calculate the address of an object.
+ */
+ zword object_address(zword obj);
+
+ /**
+ * Return the address of the given object's name.
+ */
+ zword object_name(zword object);
+
+ /**
+ * Calculate the start address of the property list associated with an object.
+ */
+ zword first_property(zword obj);
+
+ /**
+ * Calculate the address of the next property in a property list.
+ */
+ zword next_property(zword prop_addr);
+
+ /**
+ * Unlink an object from its parent and siblings.
+ */
+ void unlink_object(zword object);
+
+ /**@}*/
+
+ /**
+ * \defgroup Screen support methods
+ * @{
+ */
+
+ void screen_char(zchar c);
+ void screen_new_line();
+ void screen_word(const zchar *s);
+ void screen_mssg_on();
+ void screen_mssg_off();
+
+ /**@}*/
+
+ /**
+ * \defgroup Stream support methods
+ * @{
+ */
+
+ /**
+ * Waits for the user to type an input line
+ */
+ zchar console_read_input(int max, zchar *buf, zword timeout, bool continued);
+
+ /**
+ * Waits for a keypress
+ */
+ zchar console_read_key(zword timeout);
+
+ /**
+ * Write a single character to the scrollback buffer.
+ *
+ */
+ void scrollback_char(zchar c);
+
+ /**
+ * Write a string to the scrollback buffer.
+ */
+ void scrollback_word(const zchar *s);
+
+ /**
+ * Send an input line to the scrollback buffer.
+ */
+ void scrollback_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Remove an input line from the scrollback buffer.
+ */
+ void scrollback_erase_input(const zchar *buf);
+
+ /**
+ * Start printing a "debugging" message.
+ */
+ void stream_mssg_on();
+
+ /**
+ * Stop printing a "debugging" message.
+ */
+ void stream_mssg_off();
+
+ /**
+ * Send a single character to the output stream.
+ */
+ void stream_char(zchar c);
+
+ /**
+ * Send a string of characters to the output streams.
+ */
+ void stream_word(const zchar *s);
+
+ /**
+ * Send a newline to the output streams.
+ */
+ void stream_new_line();
+
+ /**
+ * Read a single keystroke from the current input stream.
+ */
+ zchar stream_read_key(zword timeout, zword routine, bool hot_keys);
+
+ /**
+ * Read a line of input from the current input stream.
+ */
+ zchar stream_read_input(int max, zchar *buf, zword timeout, zword routine,
+ bool hot_keys, bool no_scripting);
+
+ /*
+ * script_open
+ *
+ * Open the transscript file. 'AMFV' makes this more complicated as it
+ * turns transscription on/off several times to exclude some text from
+ * the transscription file. This wasn't a problem for the original V4
+ * interpreters which always sent transscription to the printer, but it
+ * means a problem to modern interpreters that offer to open a new file
+ * every time transscription is turned on. Our solution is to append to
+ * the old transscription file in V1 to V4, and to ask for a new file
+ * name in V5+.
+ *
+ */
+ void script_open();
+
+ /*
+ * Stop transscription.
+ */
+ void script_close();
+
+ /**
+ * Write a newline to the transscript file.
+ */
+ void script_new_line();
+
+ /**
+ * Write a single character to the transscript file.
+ */
+ void script_char(zchar c);
+
+ /**
+ * Write a string to the transscript file.
+ */
+ void script_word(const zchar *s);
+
+ /**
+ * Send an input line to the transscript file.
+ */
+ void script_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Remove an input line from the transscript file.
+ */
+ void script_erase_input(const zchar *buf);
+
+ /**
+ * Start sending a "debugging" message to the transscript file.
+ */
+ void script_mssg_on();
+
+ /**
+ * Stop writing a "debugging" message.
+ */
+ void script_mssg_off();
+
+ /**
+ * Open a file to record the player's input.
+ */
+ void record_open();
+
+ /**
+ * Stop recording the player's input.
+ */
+ void record_close();
+
+ /**
+ * Helper function for record_char.
+ */
+ void record_code(int c, bool force_encoding);
+
+ /**
+ * Write a character to the command file.
+ */
+ void record_char(zchar c);
+
+ /**
+ * Copy a keystroke to the command file.
+ */
+ void record_write_key(zchar key);
+
+ /**
+ * Copy a line of input to a command file.
+ */
+ void record_write_input(const zchar *buf, zchar key);
+
+ /**
+ * Open a file of commands for playback.
+ */
+ void replay_open();
+
+ /**
+ * Stop playback of commands.
+ */
+ void replay_close();
+
+ /*
+ * Helper function for replay_key and replay_line.
+ */
+ int replay_code();
+
+ /**
+ * Read a character from the command file.
+ */
+ zchar replay_char();
+
+ /**
+ * Read a keystroke from a command file.
+ */
+ zchar replay_read_key();
+
+ /*
+ * Read a line of input from a command file.
+ */
+ zchar replay_read_input(zchar *buf);
+
+ /**@}*/
+
+ /**
+ * \defgroup Text support methods
+ * @{
+ */
+
+ /**
+ * Map a ZSCII character into Unicode.
+ */
+ zchar translate_from_zscii(zbyte c);
+
+ /**
+ * Convert a Unicode character to ZSCII, returning 0 on failure.
+ */
+ zbyte unicode_to_zscii(zchar c);
+
+ /**
+ * Map a Unicode character onto the ZSCII alphabet.
+ *
+ */
+ zbyte translate_to_zscii(zchar c);
+
+ /**
+ * Return a character from one of the three character sets.
+ */
+ zchar alphabet(int set, int index);
+
+ /**
+ * Find the number of bytes used for dictionary resolution.
+ */
+ void find_resolution();
+
+ /**
+ * Copy a ZSCII string from the memory to the global "decoded" string.
+ */
+ void load_string(zword addr, zword length);
+
+ /**
+ * Encode the Unicode text in the global "decoded" string then write
+ * the result to the global "encoded" array. (This is used to look up
+ * words in the dictionary.) Up to V3 the vocabulary resolution is
+ * two, from V4 it is three, and from V9 it is any number of words.
+ * Because each word contains three Z-characters, that makes six or
+ * nine Z-characters respectively. Longer words are chopped to the
+ * proper size, shorter words are are padded out with 5's. For word
+ * completion we pad with 0s and 31s, the minimum and maximum
+ * Z-characters.
+ */
+ void encode_text(int padding);
+
+ /**
+ * Convert _encoded text to Unicode. The _encoded text consists of 16bit
+ * words. Every word holds 3 Z-characters (5 bits each) plus a spare
+ * bit to mark the last word. The Z-characters translate to ZSCII by
+ * looking at the current current character set. Some select another
+ * character set, others refer to abbreviations.
+ *
+ * There are several different string types:
+ *
+ * LOW_STRING - from the lower 64KB (byte address)
+ * ABBREVIATION - from the abbreviations table (word address)
+ * HIGH_STRING - from the end of the memory map (packed address)
+ * EMBEDDED_STRING - from the instruction stream (at PC)
+ * VOCABULARY - from the dictionary (byte address)
+ *
+ * The last type is only used for word completion.
+ */
+ void decode_text(string_type st, zword addr);
+
+ /**
+ * Print a signed 16bit number.
+ */
+ void print_num(zword value);
+
+ /**
+ * print_object
+ *
+ * Print an object description.
+ *
+ */
+ void print_object(zword object);
+
+ /**
+ * Scan a dictionary searching for the given word. The first argument
+ * can be
+ *
+ * 0x00 - find the first word which is >= the given one
+ * 0x05 - find the word which exactly matches the given one
+ * 0x1f - find the last word which is <= the given one
+ *
+ * The return value is 0 if the search fails.
+ */
+ zword lookup_text(int padding, zword dct);
+
+ /**
+ * tokenise_text
+ *
+ * Translate a single word to a token and append it to the token
+ * buffer. Every token consists of the address of the dictionary
+ * entry, the length of the word and the offset of the word from
+ * the start of the text buffer. Unknown words cause empty slots
+ * if the flag is set (such that the text can be scanned several
+ * times with different dictionaries); otherwise they are zero.
+ *
+ */
+ void tokenise_text(zword text, zword length, zword from, zword parse, zword dct, bool flag);
+
+ /**
+ * Split an input line into words and translate the words to tokens.
+ */
+ void tokenise_line(zword text, zword token, zword dct, bool flag);
+
+ /**
+ * Scan the vocabulary to complete the last word on the input line
+ * (similar to "tcsh" under Unix). The return value is
+ *
+ * 2 ==> completion is impossible
+ * 1 ==> completion is ambiguous
+ * 0 ==> completion is successful
+ *
+ * The function also returns a string in its second argument. In case
+ * of 2, the string is empty; in case of 1, the string is the longest
+ * extension of the last word on the input line that is common to all
+ * possible completions (for instance, if the last word on the input
+ * is "fo" and its only possible completions are "follow" and "folly"
+ * then the string is "ll"); in case of 0, the string is an extension
+ * to the last word that results in the only possible completion.
+ */
+ int completion(const zchar *buffer, zchar *result);
+
+ /**
+ * Convert a Unicode character to lowercase.
+ * Taken from Zip2000 by Kevin Bracey.
+ */
+ zchar unicode_tolower(zchar c);
+
+ /**@}*/
+protected:
+ /**
+ * \defgroup General Opcode methods
+ * @{
+ */
+
+ /*
+ * Load and execute an extended opcode.
+ */
+ void __extended__();
+
+ /*
+ * Exit game because an unknown opcode has been hit.
+ */
+ void __illegal__();
+
+ /*
+ * Store the current _stack frame for later use with z_throw.
+ *
+ * no zargs used
+ */
+ void z_catch();
+
+ /**
+ * Go back to the given _stack frame and return the given value.
+ *
+ * zargs[0] = value to return
+ * zargs[1] = _stack frame
+ */
+ void z_throw();
+
+ /*
+ * Call a subroutine and discard its result.
+ *
+ * zargs[0] = packed address of subroutine
+ * zargs[1] = first argument (optional)
+ * ...
+ * zargs[7] = seventh argument (optional)
+ */
+ void z_call_n();
+
+ /**
+ * Call a subroutine and store its result.
+ *
+ * zargs[0] = packed address of subroutine
+ * zargs[1] = first argument (optional)
+ * ...
+ * zargs[7] = seventh argument (optional)
+ */
+ void z_call_s();
+
+ /**
+ * Branch if subroutine was called with >= n arg's.
+ *
+ * zargs[0] = number of arguments
+ */
+ void z_check_arg_count();
+
+ /**
+ * Jump unconditionally to the given address.
+ *
+ * zargs[0] = PC relative address
+ */
+ void z_jump();
+
+ /*
+ * No operation.
+ *
+ * no zargs used
+ */
+ void z_nop();
+
+ /*
+ * Stop game and exit interpreter.
+ *
+ * no zargs used
+ */
+ void z_quit();
+
+ /*
+ * Return from a subroutine with the given value.
+ *
+ * zargs[0] = value to return
+ */
+ void z_ret();
+
+ /*
+ * Return from a subroutine with a value popped off the stack.
+ *
+ * no zargs used
+ */
+ void z_ret_popped();
+
+ /*
+ * Return from a subroutine with false (0).
+ *
+ * no zargs used
+ */
+ void z_rfalse();
+
+ /*
+ * Return from a subroutine with true (1).
+ *
+ * no zargs used
+ */
+ void z_rtrue();
+
+ /**
+ * Store a random number or set the random number seed.
+ *
+ * zargs[0] = range (positive) or seed value (negative)
+ */
+ void z_random();
+
+ /**
+ * Load / play / stop / discard a sound effect.
+ *
+ * zargs[0] = number of bleep (1 or 2) or sample
+ * zargs[1] = operation to perform (samples only)
+ * zargs[2] = repeats and volume (play sample only)
+ * zargs[3] = end-of-sound routine (play sample only, optional)
+ *
+ * Note: Volumes range from 1 to 8, volume 255 is the default volume.
+ * Repeats are stored in the high byte, 255 is infinite loop.
+ *
+ */
+ void z_sound_effect();
+
+ /**
+ * Branch if the story file is a legal copy
+ */
+ void z_piracy();
+
+ /**
+ * Save the current Z-machine state for a future undo.
+ *
+ * no zargs used
+ */
+ void z_save_undo();
+
+ /**
+ * Restore a Z-machine state from memory.
+ *
+ * no zargs used
+ */
+ void z_restore_undo();
+
+ /**@}*/
+
+ /**
+ * \defgroup Input Opcode methods
+ * @{
+ */
+
+ /**
+ * Add or remove a menu and branch if successful.
+ *
+ * zargs[0] = number of menu
+ * zargs[1] = table of menu entries or 0 to remove menu
+ */
+ void z_make_menu();
+
+ /**
+ * Read a line of input and (in V5+) store the terminating key.
+ *
+ * zargs[0] = address of text buffer
+ * zargs[1] = address of token buffer
+ * zargs[2] = timeout in tenths of a second (optional)
+ * zargs[3] = packed address of routine to be called on timeout
+ */
+ void z_read();
+
+ /**
+ * Read and store a key.
+ *
+ * zargs[0] = input device (must be 1)
+ * zargs[1] = timeout in tenths of a second (optional)
+ * zargs[2] = packed address of routine to be called on timeout
+ */
+ void z_read_char();
+
+ /**
+ * z_read_mouse, write the current mouse status into a table.
+ *
+ * zargs[0] = address of table
+ */
+ void z_read_mouse();
+
+ /**@}*/
+
+ /**
+ * \defgroup Math Opcode methods
+ * @{
+ */
+
+ /**
+ * 16 bit addition.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_add();
+
+ /**
+ * Bitwise AND operation.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_and();
+
+ /**
+ * Arithmetic SHIFT operation.
+ *
+ * zargs[0] = value
+ * zargs[1] = #positions to shift left (positive) or right
+ */
+ void z_art_shift();
+
+ /**
+ * Signed 16bit division.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_div();
+
+ /**
+ * B ranch if the first value equals any of the following.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value (optional)
+ * ...
+ * zargs[3] = fourth value (optional)
+ */
+ void z_je();
+
+ /**
+ * Branch if the first value is greater than the second.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_jg();
+
+ /**
+ * Branch if the first value is less than the second.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_jl();
+
+ /**
+ * Branch if value is zero.
+ *
+ * zargs[0] = value
+ */
+ void z_jz();
+
+ /**
+ * Logical SHIFT operation.
+ *
+ * zargs[0] = value
+ * zargs[1] = #positions to shift left (positive) or right (negative)
+ */
+ void z_log_shift();
+
+ /*
+ * Remainder after signed 16bit division.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_mod();
+
+ /**
+ * 16 bit multiplication.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_mul();
+
+ /**
+ * Bitwise NOT operation.
+ *
+ * zargs[0] = value
+ */
+ void z_not();
+
+ /**
+ * Bitwise OR operation.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_or();
+
+ /**
+ * 16 bit substraction.
+ *
+ * zargs[0] = first value
+ * zargs[1] = second value
+ */
+ void z_sub();
+
+ /**
+ * Branch if all the flags of a bit mask are set in a value.
+ *
+ * zargs[0] = value to be examined
+ * zargs[1] = bit mask
+ */
+ void z_test();
+
+ /**@}*/
+
+ /**
+ * \defgroup Object Opcode methods
+ * @{
+ */
+
+ /**
+ * Branch if the first object is inside the second.
+ *
+ * zargs[0] = first object
+ * zargs[1] = second object
+ */
+ void z_jin();
+
+ /**
+ * Store the child of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_child();
+
+ /**
+ * Store the number of the first or next property.
+ *
+ * zargs[0] = object
+ * zargs[1] = address of current property (0 gets the first property)
+ */
+ void z_get_next_prop();
+
+ /**
+ * Store the parent of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_parent();
+
+ /**
+ * Store the value of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to be examined
+ */
+ void z_get_prop();
+
+ /**
+ * Store the address of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to be examined
+ */
+ void z_get_prop_addr();
+
+ /**
+ * Store the length of an object property.
+ *
+ * zargs[0] = address of property to be examined
+ */
+ void z_get_prop_len();
+
+ /**
+ * Store the sibling of an object.
+ *
+ * zargs[0] = object
+ */
+ void z_get_sibling();
+
+ /**
+ * Make an object the first child of another object.
+ *
+ * zargs[0] = object to be moved
+ * zargs[1] = destination object
+ */
+ void z_insert_obj();
+
+ /**
+ * Set the value of an object property.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of property to set
+ * zargs[2] = value to set property to
+ */
+ void z_put_prop();
+
+ /**
+ * Unlink an object from its parent and siblings.
+ *
+ * zargs[0] = object
+ */
+ void z_remove_obj();
+
+ /**
+ * Set an object attribute.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to set
+ */
+ void z_set_attr();
+
+ /**
+ * Branch if an object attribute is set.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to test
+ */
+ void z_test_attr();
+
+ /**
+ * Clear an object attribute.
+ *
+ * zargs[0] = object
+ * zargs[1] = number of attribute to be cleared
+ */
+ void z_clear_attr();
+
+ /**@}*/
+
+ /**
+ * \defgroup Screen Opcode methods
+ * @{
+ */
+
+ /**
+ * Turn text buffering on/off.
+ *
+ * zargs[0] = new text buffering flag (0 or 1)
+ */
+ void z_buffer_mode();
+
+ /**
+ * Set the screen buffering mode.
+ *
+ * zargs[0] = mode
+ */
+ void z_buffer_screen();
+
+ /**
+ * Erase the line starting at the cursor position.
+ *
+ * zargs[0] = 1 + #units to erase (1 clears to the end of the line)
+ */
+ void z_erase_line();
+
+ /**
+ * Erase a window or the screen to background colour.
+ *
+ * zargs[0] = window (-3 current, -2 screen, -1 screen & unsplit)
+ */
+ void z_erase_window();
+
+ /**
+ * Write the cursor coordinates into a table.
+ *
+ * zargs[0] = address to write information to
+ */
+ void z_get_cursor();
+
+ /**
+ * Print ASCII text in a rectangular area.
+ *
+ * zargs[0] = address of text to be printed
+ * zargs[1] = width of rectangular area
+ * zargs[2] = height of rectangular area (optional)
+ * zargs[3] = number of char's to skip between lines (optional)
+ */
+ void z_print_table();
+
+ /**
+ * Set the foreground and background colours
+ * to specific RGB colour values.
+ *
+ * zargs[0] = foreground colour
+ * zargs[1] = background colour
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_true_colour();
+
+ /**
+ * Set the foreground and background colours.
+ *
+ * zargs[0] = foreground colour
+ * zargs[1] = background colour
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_colour();
+
+ /**
+ * Set the font for text output and store the previous font.
+ *
+ * zargs[0] = number of font or 0 to keep current font
+ */
+ void z_set_font();
+
+ /**
+ * Set the cursor position or turn the cursor on/off.
+ *
+ * zargs[0] = y-coordinate or -2/-1 for cursor on/off
+ * zargs[1] = x-coordinate
+ * zargs[2] = window (-3 is the current one, optional)
+ */
+ void z_set_cursor();
+
+ /**
+ * z_set_text_style, set the style for text output.
+ *
+ * zargs[0] = style flags to set or 0 to reset text style
+ */
+ void z_set_text_style();
+
+ /**
+ * Select the current window.
+ *
+ * zargs[0] = window to be selected (-3 is the current one)
+ */
+ void z_set_window();
+
+ /**
+ * Display the status line for V1 to V3 games.
+ *
+ * no zargs used
+ */
+ void pad_status_line(int column);
+
+ /**
+ * Display the status line for V1 to V3 games.
+ *
+ * no zargs used
+ */
+ void z_show_status();
+
+ /**
+ * Split the screen into an upper (1) and lower (0) window.
+ *
+ * zargs[0] = height of upper window in screen units (V6) or #lines
+ */
+ void z_split_window();
+
+ /**@}*/
+
+ /**
+ * \defgroup Stream Opcode methods
+ * @{
+ */
+
+ /**
+ * Select an input stream.
+ *
+ * zargs[0] = input stream to be selected
+ */
+ void z_input_stream();
+
+ /**
+ * Open or close an output stream.
+ *
+ * zargs[0] = stream to open (positive) or close (negative)
+ * zargs[1] = address to redirect output to (stream 3 only)
+ * zargs[2] = width of redirected output (stream 3 only, optional)
+ */
+ void z_output_stream();
+
+ /**
+ * Re-load dynamic area, clear the stack and set the PC.
+ *
+ * no zargs used
+ */
+ void z_restart();
+
+ /**
+ * Save [a part of] the Z-machine state to disk.
+ *
+ * zargs[0] = address of memory area to save (optional)
+ * zargs[1] = number of bytes to save
+ * zargs[2] = address of suggested file name
+ */
+ void z_save();
+
+ /**
+ * Restore [a part of] a Z-machine state from disk
+ *
+ * zargs[0] = address of area to restore (optional)
+ * zargs[1] = number of bytes to restore
+ * zargs[2] = address of suggested file name
+ */
+ void z_restore();
+
+ /**
+ * Check the story file integrity.
+ *
+ * no zargs used
+ */
+ void z_verify();
+
+ /**@}*/
+
+ /**
+ * \defgroup Table Opcode methods
+ * @{
+ */
+
+ /**
+ * Copy a table or fill it with zeroes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = destination address or 0 for fill
+ * zargs[2] = size of table
+ *
+ * Note: Copying is safe even when source and destination overlap; but
+ * if zargs[1] is negative the table _must_ be copied forwards.
+ */
+ void z_copy_table();
+
+ /**
+ * Store a value from a table of bytes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry to store
+ */
+ void z_loadb();
+
+ /**
+ * Store a value from a table of words.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry to store
+ */
+ void z_loadw();
+
+ /**
+ * Find and store the address of a target within a table.
+ *
+ * zargs[0] = target value to be searched for
+ * zargs[1] = address of table
+ * zargs[2] = number of table entries to check value against
+ * zargs[3] = type of table (optional, defaults to 0x82)
+ *
+ * Note: The table is a word array if bit 7 of zargs[3] is set; otherwise
+ * it's a byte array. The lower bits hold the address step.
+ */
+ void z_scan_table();
+
+ /**
+ * Write a byte into a table of bytes.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry
+ * zargs[2] = value to be written
+ */
+ void z_storeb();
+
+ /**
+ * Write a word into a table of words.
+ *
+ * zargs[0] = address of table
+ * zargs[1] = index of table entry
+ * zargs[2] = value to be written
+ */
+ void z_storew();
+
+ /**@}*/
+
+ /**
+ * \defgroup Text Opcode methods
+ * @{
+ */
+
+ /**
+ * Test if a unicode character can be printed (bit 0) and read (bit 1).
+ *
+ * zargs[0] = Unicode
+ */
+ void z_check_unicode();
+
+ /**
+ * Encode a ZSCII string for use in a dictionary.
+ *
+ * zargs[0] = address of text buffer
+ * zargs[1] = length of ASCII string
+ * zargs[2] = offset of ASCII string within the text buffer
+ * zargs[3] = address to store encoded text in
+ *
+ * This is a V5+ opcode and therefore the dictionary resolution must be
+ * three 16bit words.
+ */
+ void z_encode_text();
+
+ /**
+ * Print a new line.
+ *
+ * no zargs used
+ *
+ */
+ void z_new_line();
+
+ /**
+ * Print a string embedded in the instruction stream.
+ *
+ * no zargs used
+ */
+ void z_print();
+
+ /**
+ * Print a string from the lower 64KB.
+ *
+ * zargs[0] = address of string to print
+ */
+ void z_print_addr();
+
+ /**
+ * Print a single ZSCII character.
+ *
+ * zargs[0] = ZSCII character to be printed
+ */
+ void z_print_char();
+
+ /**
+ * Print a formatted table.
+ *
+ * zargs[0] = address of formatted table to be printed
+ */
+ void z_print_form();
+
+ /**
+ * Print a signed number.
+ *
+ * zargs[0] = number to print
+ */
+ void z_print_num();
+
+ /**
+ * Print an object description.
+ *
+ * zargs[0] = number of object to be printed
+ */
+ void z_print_obj();
+
+ /**
+ * Print the string at the given packed address.
+ *
+ * zargs[0] = packed address of string to be printed
+ */
+ void z_print_paddr();
+
+ /*
+ * Print the string at PC, print newline then return true.
+ *
+ * no zargs used
+ */
+ void z_print_ret();
+
+ /**
+ * Print unicode character
+ *
+ * zargs[0] = Unicode
+ */
+ void z_print_unicode();
+
+ /**
+ * Make a lexical analysis of a ZSCII string.
+ *
+ * zargs[0] = address of string to analyze
+ * zargs[1] = address of token buffer
+ * zargs[2] = address of dictionary (optional)
+ * zargs[3] = set when unknown words cause empty slots (optional)
+ */
+ void z_tokenise();
+
+ /**@}*/
+
+ /**
+ * \defgroup Variable Opcode methods
+ * @{
+ */
+
+ /**
+ * Decrement a variable.
+ *
+ * zargs[0] = variable to decrement
+ */
+ void z_dec();
+
+ /**
+ * Decrement a variable and branch if now less than value.
+ *
+ * zargs[0] = variable to decrement
+ * zargs[1] = value to check variable against
+ */
+ void z_dec_chk();
+
+ /**
+ * Increment a variable.
+ *
+ * zargs[0] = variable to increment
+ */
+ void z_inc();
+
+ /**
+ * Increment a variable and branch if now greater than value.
+ *
+ * zargs[0] = variable to increment
+ * zargs[1] = value to check variable against
+ */
+ void z_inc_chk();
+
+ /**
+ * Store the value of a variable.
+ *
+ * zargs[0] = variable to store
+ */
+ void z_load();
+
+ /**
+ * Pop a value off the game stack and discard it.
+ *
+ * no zargs used
+ */
+ void z_pop();
+
+ /**
+ * Pop n values off the game or user stack and discard them.
+ *
+ * zargs[0] = number of values to discard
+ * zargs[1] = address of user stack (optional)
+ */
+ void z_pop_stack();
+
+ /**
+ * Pop a value off...
+ *
+ * a) ...the game or a user stack and store it (V6)
+ *
+ * zargs[0] = address of user stack (optional)
+ *
+ * b) ...the game stack and write it to a variable (other than V6)
+ *
+ * zargs[0] = variable to write value to
+ */
+ void z_pull();
+
+ /**
+ * Push a value onto the game stack.
+ *
+ * zargs[0] = value to push onto the stack
+ */
+ void z_push();
+
+ /**
+ * Push a value onto a user stack then branch if successful.
+ *
+ * zargs[0] = value to push onto the stack
+ * zargs[1] = address of user stack
+ */
+ void z_push_stack();
+
+ /**
+ * Write a value to a variable.
+ *
+ * zargs[0] = variable to be written to
+ * zargs[1] = value to write
+ */
+ void z_store();
+
+ /**@}*/
+public:
+ /**
+ * Constructor
+ */
+ Processor(OSystem *syst, const GargoyleGameDescription *gameDesc);
+
+ /**
+ * Initialization
+ */
+ void initialize();
+
+ /**
+ * Z-code interpreter main loop
+ */
+ void interpret();
+
+ /**
+ * \defgroup Memory access methods
+ * @{
+ */
+
+ /**
+ * Square brackets operator
+ */
+ zbyte &operator[](uint addr) { return zmp[addr]; }
+
+ /**
+ * Read a code byte
+ */
+ zbyte codeByte() { return *pcp++; }
+
+ /**
+ * Read a code word
+ */
+ zword codeWord() {
+ zword v = READ_BE_UINT16(pcp);
+ pcp += 2;
+ return v;
+ }
+
+ /**
+ * Return a code word at a given address
+ */
+ zword codeWordIdx(uint addr) const {
+ return READ_BE_UINT16(pcp + addr);
+ }
+
+ /**
+ * Return the current program execution offset
+ */
+ uint getPC() const { return pcp - zmp; }
+
+ /**
+ * Set the program execution offset
+ */
+ void setPC(uint addr) { pcp = zmp + addr; }
+
+ /**@}*/
+};
+
+} // End of namespace Frotz
+} // End of namespace Gargoyle
+
+#endif