1 /* ScummVM - Graphic Adventure Engine 2 * 3 * ScummVM is the legal property of its developers, whose names 4 * are too numerous to list here. Please refer to the COPYRIGHT 5 * file distributed with this source distribution. 6 * 7 * This program is free software; you can redistribute it and/or 8 * modify it under the terms of the GNU General Public License 9 * as published by the Free Software Foundation; either version 2 10 * of the License, or (at your option) any later version. 11 * 12 * This program is distributed in the hope that it will be useful, 13 * but WITHOUT ANY WARRANTY; without even the implied warranty of 14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 15 * GNU General Public License for more details. 16 * 17 * You should have received a copy of the GNU General Public License 18 * along with this program; if not, write to the Free Software 19 * Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA. 20 * 21 */ 22 23 #ifndef GLK_GLULXE_TYPES 24 #define GLK_GLULXE_TYPES 25 26 #include "common/scummsys.h" 27 28 namespace Glk { 29 namespace Glulx { 30 31 class Glulx; 32 33 /** 34 * Comment this definition to turn off memory-address checking. With verification on, 35 * all reads and writes to main memory will be checked to ensure they're in range. 36 * This is slower, but prevents malformed game files from crashing the interpreter. 37 */ 38 #define VERIFY_MEMORY_ACCESS (1) 39 40 /** 41 * Uncomment this definition to permit an exception for memory-address checking for @glk and @copy 42 * opcodes that try to write to memory address 0. This was a bug in old Superglus-built game files. 43 */ 44 /* #define TOLERATE_SUPERGLUS_BUG (1) */ 45 46 /** 47 * Uncomment this definition to turn on Glulx VM profiling. In this mode, all function calls are timed, 48 * and the timing information is written to a data file called "profile-raw". 49 * (Build note: on Linux, glibc may require you to also define _BSD_SOURCE or _DEFAULT_SOURCE or both 50 * for the timeradd() macro.) 51 */ 52 /* #define VM_PROFILING (1) */ 53 54 /** 55 * Uncomment this definition to turn on the Glulx debugger. You should only do this when debugging 56 * facilities are desired; it slows down the interpreter. If you do, you will need to build with libxml2; 57 * see the Makefile. 58 */ 59 /* #define VM_DEBUGGER (1) */ 60 61 /** 62 * Comment this definition to turn off floating-point support. You might need to do this if you are building 63 * on a very limited platform with no math library. 64 */ 65 #define FLOAT_SUPPORT (1) 66 67 /** 68 * Comment this definition to not cache the original state of RAM in (real) memory. This saves some memory, 69 * but slows down save/restore/undo operations, which will have to read the original state off disk 70 * every time. 71 */ 72 #define SERIALIZE_CACHE_RAM (1) 73 74 /** 75 * Some macros to read and write integers to memory, always in big-endian format. 76 */ 77 #define Read4(ptr) READ_BE_UINT32(ptr) 78 #define Read2(ptr) READ_BE_UINT16(ptr) 79 #define Read1(ptr) ((byte)(((byte *)(ptr))[0])) 80 #define Write4(ptr, vl) WRITE_BE_UINT32(ptr, vl) 81 #define Write2(ptr, vl) WRITE_BE_UINT16(ptr, vl) 82 #define Write1(ptr, vl) (((byte *)(ptr))[0] = (vl)) 83 84 #if VERIFY_MEMORY_ACCESS 85 #define Verify(adr, ln) verify_address(adr, ln) 86 #define VerifyW(adr, ln) verify_address_write(adr, ln) 87 #else 88 #define Verify(adr, ln) (0) 89 #define VerifyW(adr, ln) (0) 90 #endif /* VERIFY_MEMORY_ACCESS */ 91 92 #define Mem1(adr) (Read1(memmap+(adr))) 93 #define Mem2(adr) (Read2(memmap+(adr))) 94 #define Mem4(adr) (Read4(memmap+(adr))) 95 #define MemW1(adr, vl) (VerifyW(adr, 1), Write1(memmap+(adr), (vl))) 96 #define MemW2(adr, vl) (VerifyW(adr, 2), Write2(memmap+(adr), (vl))) 97 #define MemW4(adr, vl) (VerifyW(adr, 4), Write4(memmap+(adr), (vl))) 98 99 #ifndef _HUGE_ENUF 100 #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow 101 #endif 102 #ifndef INFINITY 103 #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) 104 #endif 105 #ifndef NAN 106 #define NAN ((float)(INFINITY * 0.0F)) 107 #endif 108 109 /** 110 * Macros to access values on the stack. These *must* be used with proper alignment! 111 * (That is, Stk4 and StkW4 must take addresses which are multiples of four, etc.) 112 * If the alignment rules are not followed, the program will see performance 113 * degradation or even crashes, depending on the machine CPU. 114 */ 115 #define Stk1(adr) \ 116 (*((unsigned char *)(stack+(adr)))) 117 #define Stk2(adr) \ 118 (*((uint16 *)(stack+(adr)))) 119 #define Stk4(adr) \ 120 (*((uint32 *)(stack+(adr)))) 121 122 #define StkW1(adr, vl) \ 123 (*((byte *)(stack+(adr))) = (byte)(vl)) 124 #define StkW2(adr, vl) \ 125 (*((uint16 *)(stack+(adr))) = (uint16)(vl)) 126 #define StkW4(adr, vl) \ 127 (*((uint32 *)(stack+(adr))) = (uint32)(vl)) 128 129 enum Opcode { 130 op_nop = 0x00, 131 132 op_add = 0x10, 133 op_sub = 0x11, 134 op_mul = 0x12, 135 op_div = 0x13, 136 op_mod = 0x14, 137 op_neg = 0x15, 138 op_bitand = 0x18, 139 op_bitor = 0x19, 140 op_bitxor = 0x1A, 141 op_bitnot = 0x1B, 142 op_shiftl = 0x1C, 143 op_sshiftr = 0x1D, 144 op_ushiftr = 0x1E, 145 146 op_jump = 0x20, 147 op_jz = 0x22, 148 op_jnz = 0x23, 149 op_jeq = 0x24, 150 op_jne = 0x25, 151 op_jlt = 0x26, 152 op_jge = 0x27, 153 op_jgt = 0x28, 154 op_jle = 0x29, 155 op_jltu = 0x2A, 156 op_jgeu = 0x2B, 157 op_jgtu = 0x2C, 158 op_jleu = 0x2D, 159 160 op_call = 0x30, 161 op_return = 0x31, 162 op_catch = 0x32, 163 op_throw = 0x33, 164 op_tailcall = 0x34, 165 166 op_copy = 0x40, 167 op_copys = 0x41, 168 op_copyb = 0x42, 169 op_sexs = 0x44, 170 op_sexb = 0x45, 171 op_aload = 0x48, 172 op_aloads = 0x49, 173 op_aloadb = 0x4A, 174 op_aloadbit = 0x4B, 175 op_astore = 0x4C, 176 op_astores = 0x4D, 177 op_astoreb = 0x4E, 178 op_astorebit = 0x4F, 179 180 op_stkcount = 0x50, 181 op_stkpeek = 0x51, 182 op_stkswap = 0x52, 183 op_stkroll = 0x53, 184 op_stkcopy = 0x54, 185 186 op_streamchar = 0x70, 187 op_streamnum = 0x71, 188 op_streamstr = 0x72, 189 op_streamunichar = 0x73, 190 191 op_gestalt = 0x100, 192 op_debugtrap = 0x101, 193 op_getmemsize = 0x102, 194 op_setmemsize = 0x103, 195 op_jumpabs = 0x104, 196 197 op_random = 0x110, 198 op_setrandom = 0x111, 199 200 op_quit = 0x120, 201 op_verify = 0x121, 202 op_restart = 0x122, 203 op_save = 0x123, 204 op_restore = 0x124, 205 op_saveundo = 0x125, 206 op_restoreundo = 0x126, 207 op_protect = 0x127, 208 209 op_glk = 0x130, 210 211 op_getstringtbl = 0x140, 212 op_setstringtbl = 0x141, 213 op_getiosys = 0x148, 214 op_setiosys = 0x149, 215 216 op_linearsearch = 0x150, 217 op_binarysearch = 0x151, 218 op_linkedsearch = 0x152, 219 220 op_callf = 0x160, 221 op_callfi = 0x161, 222 op_callfii = 0x162, 223 op_callfiii = 0x163, 224 225 op_mzero = 0x170, 226 op_mcopy = 0x171, 227 op_malloc = 0x178, 228 op_mfree = 0x179, 229 230 op_accelfunc = 0x180, 231 op_accelparam = 0x181, 232 233 op_numtof = 0x190, 234 op_ftonumz = 0x191, 235 op_ftonumn = 0x192, 236 op_ceil = 0x198, 237 op_floor = 0x199, 238 op_fadd = 0x1A0, 239 op_fsub = 0x1A1, 240 op_fmul = 0x1A2, 241 op_fdiv = 0x1A3, 242 op_fmod = 0x1A4, 243 op_sqrt = 0x1A8, 244 op_exp = 0x1A9, 245 op_log = 0x1AA, 246 op_pow = 0x1AB, 247 op_sin = 0x1B0, 248 op_cos = 0x1B1, 249 op_tan = 0x1B2, 250 op_asin = 0x1B3, 251 op_acos = 0x1B4, 252 op_atan = 0x1B5, 253 op_atan2 = 0x1B6, 254 op_jfeq = 0x1C0, 255 op_jfne = 0x1C1, 256 op_jflt = 0x1C2, 257 op_jfle = 0x1C3, 258 op_jfgt = 0x1C4, 259 op_jfge = 0x1C5, 260 op_jisnan = 0x1C8, 261 op_jisinf = 0x1C9 262 }; 263 264 enum gestulx { 265 gestulx_GlulxVersion = 0, 266 gestulx_TerpVersion = 1, 267 gestulx_ResizeMem = 2, 268 gestulx_Undo = 3, 269 gestulx_IOSystem = 4, 270 gestulx_Unicode = 5, 271 gestulx_MemCopy = 6, 272 gestulx_MAlloc = 7, 273 gestulx_MAllocHeap = 8, 274 gestulx_Acceleration = 9, 275 gestulx_AccelFunc = 10, 276 gestulx_Float = 11 277 }; 278 279 /** 280 * You may have to edit the definition of gfloat32 to make sure it's really a 32-bit floating-point type. 281 */ 282 typedef float gfloat32; 283 284 struct dispatch_splot_struct { 285 int numwanted; 286 int maxargs; 287 gluniversal_t *garglist; 288 uint *varglist; 289 int numvargs; 290 uint *retval; 291 }; 292 typedef dispatch_splot_struct dispatch_splot_t; 293 294 /** 295 * We maintain a linked list of arrays being used for Glk calls. It is only used for integer 296 * (uint) arrays -- char arrays are handled in place. It's not worth bothering with a hash table, 297 * since most arrays appear here only momentarily. 298 */ 299 struct arrayref_struct { 300 void *array; 301 uint addr; 302 uint elemsize; 303 uint len; /* elements */ 304 int retained; 305 arrayref_struct *next; 306 }; 307 typedef arrayref_struct arrayref_t; 308 309 /** 310 * We maintain a hash table for each opaque Glk class. classref_t are the nodes of the table, 311 * and classtable_t are the tables themselves. 312 */ 313 struct classref_struct { 314 void *obj; 315 uint id; 316 int bucknum; 317 classref_struct *next; 318 }; 319 typedef classref_struct classref_t; 320 321 #define CLASSHASH_SIZE (31) 322 struct classtable_struct { 323 uint lastid; 324 classref_t *bucket[CLASSHASH_SIZE]; 325 }; 326 typedef classtable_struct classtable_t; 327 328 /** 329 * Represents the operand structure of an opcode. 330 */ 331 struct operandlist_struct { 332 int num_ops; ///< Number of operands for this opcode 333 int arg_size; ///< Usually 4, but can be 1 or 2 334 const int *formlist; ///< Array of values, either modeform_Load or modeform_Store 335 }; 336 typedef operandlist_struct operandlist_t; 337 338 enum modeform { 339 modeform_Load = 1, 340 modeform_Store = 2 341 }; 342 343 /** 344 * Represents one operand value to an instruction being executed. The 345 * code in exec.c assumes that no instruction has more than MAX_OPERANDS of these. 346 */ 347 struct oparg_struct { 348 uint desttype; 349 uint value; 350 }; 351 typedef oparg_struct oparg_t; 352 353 #define MAX_OPERANDS (8) 354 355 typedef uint(Glulx::*acceleration_func)(uint argc, uint *argv); 356 357 struct accelentry_struct { 358 uint addr; 359 uint index; 360 acceleration_func func; 361 accelentry_struct *next; 362 }; 363 typedef accelentry_struct accelentry_t; 364 365 #define ACCEL_HASH_SIZE (511) 366 367 struct heapblock_struct { 368 uint addr; 369 uint len; 370 int isfree; 371 struct heapblock_struct *next; 372 struct heapblock_struct *prev; 373 }; 374 typedef heapblock_struct heapblock_t; 375 376 /** 377 * This structure allows us to write either to a Glk stream or to a dynamically-allocated memory chunk. 378 */ 379 struct dest_struct { 380 bool _isMem; 381 382 /* If it's a raw stream */ 383 Common::SeekableReadStream *_src; 384 Common::WriteStream *_dest; 385 386 /* If it's a block of memory: */ 387 byte *_ptr; 388 uint _pos; 389 uint _size; 390 dest_structdest_struct391 dest_struct() : _isMem(false), _src(nullptr), _dest(nullptr), 392 _ptr(nullptr), _pos(0), _size(0) {} 393 }; 394 typedef dest_struct dest_t; 395 396 /** 397 * These constants are defined in the Glulx spec. 398 */ 399 enum iosys { 400 iosys_None = 0, 401 iosys_Filter = 1, 402 iosys_Glk = 2 403 }; 404 405 #define CACHEBITS (4) 406 #define CACHESIZE (1 << CACHEBITS) 407 #define CACHEMASK (15) 408 409 struct cacheblock_struct { 410 int depth; /* 1 to 4 */ 411 int type; 412 union { 413 struct cacheblock_struct *branches; 414 unsigned char ch; 415 uint uch; 416 uint addr; 417 } u; 418 }; 419 typedef cacheblock_struct cacheblock_t; 420 421 } // End of namespace Glulx 422 } // End of namespace Glk 423 424 #endif 425