1 /* 2 * A Z-Machine 3 * Copyright (C) 2000 Andrew Hunter 4 * 5 * This library is free software; you can redistribute it and/or 6 * modify it under the terms of the GNU Lesser General Public 7 * License as published by the Free Software Foundation; either 8 * version 2.1 of the License, or (at your option) any later version. 9 * 10 * This library is distributed in the hope that it will be useful, 11 * but WITHOUT ANY WARRANTY; without even the implied warranty of 12 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU 13 * Lesser General Public License for more details. 14 * 15 * You should have received a copy of the GNU Lesser General Public 16 * License along with this library; if not, write to the Free Software 17 * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA 18 */ 19 20 /* 21 * Data types that describe the Z-Machine 22 */ 23 24 #ifndef __ZMACHINE_H 25 #define __ZMACHINE_H 26 27 #include <stdio.h> 28 29 #include "ztypes.h" 30 #include "hash.h" 31 #include "file.h" 32 #include "display.h" 33 #include "blorb.h" 34 35 /* 36 * You can #define the following definitions to alter how your version 37 * of Zoom is compiled. 38 * 39 * DEBUG does produce rather a lot of debugging information (~15Mb 40 * from advent.z5, just to open the grate...). However, if you know 41 * what you're doing, you may find this useful to fix problems in your 42 * games (or locate problems in Zoom) 43 * 44 * Undefining SAFE will turn off bounds checking in any operations 45 * that use it. 46 * 47 * GLOBAL_PC will make the program counter be stored in a global 48 * variable - this creates a very slight slowdown, but means warnings 49 * and errors can give the PC that they occured at 50 * 51 * CAN_UNDO means that the undo commands are supported 52 * 53 * SQUEEZEUNDO will cause the undo buffer to be compressed (which is slow) 54 * 55 * SPEC_10 will cause the interpreter to indicate that it is 56 * conformant to the v1.0 specification. 57 * 58 * GRAPHICAL causes the interpreter to run version 5 games in 59 * 'graphical' mode. Beyond Zork supports this, Inform games do 60 * not. The v1.0 specification indicates that you shouldn't do this, 61 * but games that do not support this mode do not have the 'pictures' 62 * bit set, Beyond Zork being the only v5 game that I know of that has 63 * this bit set. This doesn't actually do a lot any more. 64 */ 65 66 #undef DEBUG /* Lots of debugging crap */ 67 #define SAFE /* Perform more bounds checking */ 68 #undef PAGED_MEMORY /* Not implemented, anyway ;-) */ 69 #define GLOBAL_PC /* Set to make the program counter global */ 70 #define CAN_UNDO /* Support the undo commands */ 71 #define UNDO_LEVEL 5 /* Number of levels of undo that we support */ 72 #undef SQUEEZEUNDO /* Store undo information in a compressed format (slow) */ 73 #undef TRACKING /* Enable object tracking options */ 74 #define SPEC_10 /* 75 * Unset if you don`t believe me when I say this 76 * interpreter is conformant to the ZMachine 77 * specification v1.0 78 */ 79 #define SPEC_11 /* Define to implement spec 1.1 (draft 6) */ 80 #undef GRAPHICAL /* 81 * Define to set the default behaviour to mimic 82 * that of the Beyond Zork interpreter 83 */ 84 #define V6ASSERT /* 85 * Performs sanity checks to ensure that non-v6 86 * display functions are not called from a v6 game 87 */ 88 #undef CUTE_STARTUP /* 'Adventure-style' warranty message */ 89 90 #ifndef REMOTE_BREAKPOINT 91 #undef REMOTE_BREAKPOINT /* Send SIGUSR1 to force a breakpoint at the next execution point */ 92 #endif 93 94 /* 95 * Versions to support (note that support for version 5 includes 96 * support for versions 7 and 8 as well 97 */ 98 #define SUPPORT_VERSION_3 99 #define SUPPORT_VERSION_4 100 #define SUPPORT_VERSION_5 101 #define SUPPORT_VERSION_6 102 103 /* File format */ 104 105 enum ZHeader_bytes 106 { 107 ZH_version = 0x00, 108 ZH_flags, 109 ZH_release = 0x02, 110 ZH_base_high = 0x04, 111 ZH_initpc = 0x06, 112 ZH_dict = 0x08, 113 ZH_objs = 0x0a, 114 ZH_globals = 0x0c, 115 ZH_static = 0x0e, 116 ZH_flags2 = 0x10, 117 ZH_serial = 0x12, 118 ZH_abbrevs = 0x18, 119 ZH_filelen = 0x1a, 120 ZH_checksum = 0x1c, 121 ZH_intnumber = 0x1e, 122 ZH_intvers, 123 ZH_lines, 124 ZH_columns, 125 ZH_width = 0x22, 126 ZH_height = 0x24, 127 ZH_fontwidth = 0x26, /* height in v6 */ 128 ZH_fontheight, /* width in v6 */ 129 ZH_routines, 130 ZH_staticstrings = 0x2a, 131 ZH_defback = 0x2c, 132 ZH_deffore, 133 ZH_termtable, 134 ZH_widthos3 = 0x30, 135 ZH_revnumber = 0x32, 136 ZH_alphatable = 0x34, 137 ZH_extntable = 0x36 138 }; 139 140 enum ZHEB_bytes 141 { 142 ZHEB_len = 0, 143 ZHEB_xmouse = 2, 144 ZHEB_ymouse = 4, 145 ZHEB_unitable = 6, 146 ZHEB_flags3 = 8, 147 ZHEB_truefore = 10, 148 ZHEB_trueback = 12 149 }; 150 151 /* Internal data structures */ 152 153 typedef struct ZMap 154 { 155 ZDWord actual_size; 156 ZByte* mapped_pages; 157 ZByte** pages; 158 } ZMap; 159 160 struct ZStack; 161 162 typedef struct ZArgblock 163 { 164 int n_args; 165 ZWord arg[8]; 166 } ZArgblock; 167 168 typedef struct ZFrame 169 { 170 /* Return address */ 171 ZDWord ret; 172 173 ZByte nlocals; /* Number of locals */ 174 ZByte flags; /* Arguments supplied */ 175 ZByte storevar; /* Variable to store result in on return */ 176 ZByte discard; /* Nonzero if result should be discarded */ 177 178 ZWord frame_size; /* Evaluation size */ 179 180 ZWord local[16]; 181 ZUWord frame_num; 182 183 int break_on_return; /* Used by the debugger */ 184 185 void (*v4read)(ZDWord*, struct ZStack*, ZArgblock*); 186 void (*v5read)(ZDWord*, struct ZStack*, ZArgblock*, int); 187 int end_func; 188 ZArgblock readblock; 189 int readstore; 190 191 struct ZFrame* last_frame; 192 } ZFrame; 193 194 typedef struct ZStack 195 { 196 ZDWord stack_total; 197 ZDWord stack_size; 198 ZWord* stack; 199 ZWord* stack_top; 200 ZFrame* current_frame; 201 } ZStack; 202 203 typedef struct ZMachine 204 { 205 ZUWord static_ceiling; 206 ZUWord dynamic_ceiling; 207 ZDWord high_start; 208 ZDWord story_offset; 209 ZDWord story_length; 210 211 ZByte* header; 212 ZByte* dynamic_memory; 213 214 ZFile* file; 215 char* story_file; 216 217 ZByte* undo [UNDO_LEVEL]; 218 ZDWord undo_len[UNDO_LEVEL]; 219 220 ZByte version; 221 222 #ifdef PAGED_MEMORY 223 ZMap memory; /* Still not implemented */ 224 #else 225 ZByte* memory; 226 #endif 227 228 ZByte* globals; 229 230 ZStack stack; 231 232 int* abbrev [96]; 233 int abbrev_addr[96]; 234 235 ZByte* dict; 236 237 hash cached_dictionaries; 238 239 enum { 240 packed_v3, 241 packed_v4, 242 packed_v6, 243 packed_v8 244 } packtype; 245 246 ZDWord routine_offset; 247 ZDWord string_offset; 248 249 int display_active; 250 ZDisplay* dinfo; 251 252 int graphical; 253 254 /* Header extension block */ 255 ZByte* heb; 256 ZUWord heblen; 257 258 /* Output streams */ 259 int mouse_on; 260 int screen_on; 261 int transcript_on; 262 int transcript_commands; 263 ZFile* transcript_file; 264 265 int memory_on; 266 ZUWord memory_pos [16]; 267 int memory_width[16]; 268 269 int buffering; 270 271 /* Input streams */ 272 int script_on; 273 ZFile* script_file; 274 275 #ifdef GLOBAL_PC 276 ZDWord zpc; 277 #endif 278 279 /* Autosaving */ 280 ZDWord autosave_pc; 281 282 /* Commandline options */ 283 int warning_level; 284 285 #ifdef TRACKING 286 int track_objects; 287 int track_properties; 288 int track_attributes; 289 #endif 290 291 ZFile* blorb_file; 292 IffFile* blorb_tokens; 293 BlorbFile* blorb; 294 295 int force_breakpoint; 296 } ZMachine; 297 298 typedef struct ZDictionary 299 { 300 char sep[256]; 301 hash words; 302 } ZDictionary; 303 304 extern void zmachine_load_story (char* filename, ZMachine* machine); 305 extern void zmachine_load_file (ZFile* file, ZMachine* machine); 306 extern void zmachine_setup_header (void); 307 extern void zmachine_resize_display(ZDisplay* dis); 308 extern void zmachine_fatal (char* format, ...); 309 extern void zmachine_warning (char* format, ...); 310 extern void zmachine_info (char* format, ...); 311 extern void zmachine_mark_statusbar(void); 312 extern char* zmachine_get_serial (void); 313 extern void zmachine_dump_stack (ZStack* stack); 314 315 extern ZWord pop (ZStack*); 316 extern ZWord top (ZStack*); 317 extern ZFrame* call_routine(ZDWord* pc, ZStack* stack, ZDWord start); 318 319 /* Utility macros */ 320 321 #ifdef DEBUG 322 extern ZWord debug_print_var(ZWord val, int var); 323 #define DebugVar(x, y) debug_print_var(x, y) 324 #else 325 #define DebugVar(x, y) x 326 #endif 327 328 #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) 329 #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) 330 #define GetCode(x) machine.memory[(x)] 331 #define Word(x) ((machine.memory[(x)]<<8)|machine.memory[(x)+1]) 332 #define ReadByte(x) (machine.memory[(x)]) 333 #define GetWord(m, x) ((m[x]<<8)|(m[x+1])) 334 #define Address(x) (machine.memory + (x)) 335 336 extern ZMachine machine; 337 338 #endif 339