/* * A Z-Machine * Copyright (C) 2000 Andrew Hunter * * This library is free software; you can redistribute it and/or * modify it under the terms of the GNU Lesser General Public * License as published by the Free Software Foundation; either * version 2.1 of the License, or (at your option) any later version. * * This library 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 * Lesser General Public License for more details. * * You should have received a copy of the GNU Lesser General Public * License along with this library; if not, write to the Free Software * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA */ /* * Data types that describe the Z-Machine */ #ifndef __ZMACHINE_H #define __ZMACHINE_H #include #include "ztypes.h" #include "hash.h" #include "file.h" #include "display.h" #include "blorb.h" /* * You can #define the following definitions to alter how your version * of Zoom is compiled. * * DEBUG does produce rather a lot of debugging information (~15Mb * from advent.z5, just to open the grate...). However, if you know * what you're doing, you may find this useful to fix problems in your * games (or locate problems in Zoom) * * Undefining SAFE will turn off bounds checking in any operations * that use it. * * GLOBAL_PC will make the program counter be stored in a global * variable - this creates a very slight slowdown, but means warnings * and errors can give the PC that they occured at * * CAN_UNDO means that the undo commands are supported * * SQUEEZEUNDO will cause the undo buffer to be compressed (which is slow) * * SPEC_10 will cause the interpreter to indicate that it is * conformant to the v1.0 specification. * * GRAPHICAL causes the interpreter to run version 5 games in * 'graphical' mode. Beyond Zork supports this, Inform games do * not. The v1.0 specification indicates that you shouldn't do this, * but games that do not support this mode do not have the 'pictures' * bit set, Beyond Zork being the only v5 game that I know of that has * this bit set. This doesn't actually do a lot any more. */ #undef DEBUG /* Lots of debugging crap */ #define SAFE /* Perform more bounds checking */ #undef PAGED_MEMORY /* Not implemented, anyway ;-) */ #define GLOBAL_PC /* Set to make the program counter global */ #define CAN_UNDO /* Support the undo commands */ #define UNDO_LEVEL 5 /* Number of levels of undo that we support */ #undef SQUEEZEUNDO /* Store undo information in a compressed format (slow) */ #undef TRACKING /* Enable object tracking options */ #define SPEC_10 /* * Unset if you don`t believe me when I say this * interpreter is conformant to the ZMachine * specification v1.0 */ #define SPEC_11 /* Define to implement spec 1.1 (draft 6) */ #undef GRAPHICAL /* * Define to set the default behaviour to mimic * that of the Beyond Zork interpreter */ #define V6ASSERT /* * Performs sanity checks to ensure that non-v6 * display functions are not called from a v6 game */ #undef CUTE_STARTUP /* 'Adventure-style' warranty message */ #ifndef REMOTE_BREAKPOINT #undef REMOTE_BREAKPOINT /* Send SIGUSR1 to force a breakpoint at the next execution point */ #endif /* * Versions to support (note that support for version 5 includes * support for versions 7 and 8 as well */ #define SUPPORT_VERSION_3 #define SUPPORT_VERSION_4 #define SUPPORT_VERSION_5 #define SUPPORT_VERSION_6 /* File format */ enum ZHeader_bytes { ZH_version = 0x00, ZH_flags, ZH_release = 0x02, ZH_base_high = 0x04, ZH_initpc = 0x06, ZH_dict = 0x08, ZH_objs = 0x0a, ZH_globals = 0x0c, ZH_static = 0x0e, ZH_flags2 = 0x10, ZH_serial = 0x12, ZH_abbrevs = 0x18, ZH_filelen = 0x1a, ZH_checksum = 0x1c, ZH_intnumber = 0x1e, ZH_intvers, ZH_lines, ZH_columns, ZH_width = 0x22, ZH_height = 0x24, ZH_fontwidth = 0x26, /* height in v6 */ ZH_fontheight, /* width in v6 */ ZH_routines, ZH_staticstrings = 0x2a, ZH_defback = 0x2c, ZH_deffore, ZH_termtable, ZH_widthos3 = 0x30, ZH_revnumber = 0x32, ZH_alphatable = 0x34, ZH_extntable = 0x36 }; enum ZHEB_bytes { ZHEB_len = 0, ZHEB_xmouse = 2, ZHEB_ymouse = 4, ZHEB_unitable = 6, ZHEB_flags3 = 8, ZHEB_truefore = 10, ZHEB_trueback = 12 }; /* Internal data structures */ typedef struct ZMap { ZDWord actual_size; ZByte* mapped_pages; ZByte** pages; } ZMap; struct ZStack; typedef struct ZArgblock { int n_args; ZWord arg[8]; } ZArgblock; typedef struct ZFrame { /* Return address */ ZDWord ret; ZByte nlocals; /* Number of locals */ ZByte flags; /* Arguments supplied */ ZByte storevar; /* Variable to store result in on return */ ZByte discard; /* Nonzero if result should be discarded */ ZWord frame_size; /* Evaluation size */ ZWord local[16]; ZUWord frame_num; int break_on_return; /* Used by the debugger */ void (*v4read)(ZDWord*, struct ZStack*, ZArgblock*); void (*v5read)(ZDWord*, struct ZStack*, ZArgblock*, int); int end_func; ZArgblock readblock; int readstore; struct ZFrame* last_frame; } ZFrame; typedef struct ZStack { ZDWord stack_total; ZDWord stack_size; ZWord* stack; ZWord* stack_top; ZFrame* current_frame; } ZStack; typedef struct ZMachine { ZUWord static_ceiling; ZUWord dynamic_ceiling; ZDWord high_start; ZDWord story_offset; ZDWord story_length; ZByte* header; ZByte* dynamic_memory; ZFile* file; char* story_file; ZByte* undo [UNDO_LEVEL]; ZDWord undo_len[UNDO_LEVEL]; ZByte version; #ifdef PAGED_MEMORY ZMap memory; /* Still not implemented */ #else ZByte* memory; #endif ZByte* globals; ZStack stack; int* abbrev [96]; int abbrev_addr[96]; ZByte* dict; hash cached_dictionaries; enum { packed_v3, packed_v4, packed_v6, packed_v8 } packtype; ZDWord routine_offset; ZDWord string_offset; int display_active; ZDisplay* dinfo; int graphical; /* Header extension block */ ZByte* heb; ZUWord heblen; /* Output streams */ int mouse_on; int screen_on; int transcript_on; int transcript_commands; ZFile* transcript_file; int memory_on; ZUWord memory_pos [16]; int memory_width[16]; int buffering; /* Input streams */ int script_on; ZFile* script_file; #ifdef GLOBAL_PC ZDWord zpc; #endif /* Autosaving */ ZDWord autosave_pc; /* Commandline options */ int warning_level; #ifdef TRACKING int track_objects; int track_properties; int track_attributes; #endif ZFile* blorb_file; IffFile* blorb_tokens; BlorbFile* blorb; int force_breakpoint; } ZMachine; typedef struct ZDictionary { char sep[256]; hash words; } ZDictionary; extern void zmachine_load_story (char* filename, ZMachine* machine); extern void zmachine_load_file (ZFile* file, ZMachine* machine); extern void zmachine_setup_header (void); extern void zmachine_resize_display(ZDisplay* dis); extern void zmachine_fatal (char* format, ...); extern void zmachine_warning (char* format, ...); extern void zmachine_info (char* format, ...); extern void zmachine_mark_statusbar(void); extern char* zmachine_get_serial (void); extern void zmachine_dump_stack (ZStack* stack); extern ZWord pop (ZStack*); extern ZWord top (ZStack*); extern ZFrame* call_routine(ZDWord* pc, ZStack* stack, ZDWord start); /* Utility macros */ #ifdef DEBUG extern ZWord debug_print_var(ZWord val, int var); #define DebugVar(x, y) debug_print_var(x, y) #else #define DebugVar(x, y) x #endif #define GetVar(y) DebugVar(((y)==0?pop(stack):(((unsigned char) (y))<16?stack->current_frame->local[(y)]:(machine.globals[((y)<<1)-32]<<8)|machine.globals[((y)<<1)-31])), y) #define GetVarNoPop(y) DebugVar(((y)==0?top(stack):(((unsigned char) (y))<16?stack->current_frame->local[(y)]:(machine.globals[((y)<<1)-32]<<8)|machine.globals[((y)<<1)-31])), y) #define GetCode(x) machine.memory[(x)] #define Word(x) ((machine.memory[(x)]<<8)|machine.memory[(x)+1]) #define ReadByte(x) (machine.memory[(x)]) #define GetWord(m, x) ((m[x]<<8)|(m[x+1])) #define Address(x) (machine.memory + (x)) extern ZMachine machine; #endif