/* 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_GLULXE_TYPES #define GLK_GLULXE_TYPES #include "common/scummsys.h" namespace Glk { namespace Glulxe { class Glulxe; /** * Comment this definition to turn off memory-address checking. With verification on, * all reads and writes to main memory will be checked to ensure they're in range. * This is slower, but prevents malformed game files from crashing the interpreter. */ #define VERIFY_MEMORY_ACCESS (1) /** * Uncomment this definition to permit an exception for memory-address checking for @glk and @copy * opcodes that try to write to memory address 0. This was a bug in old Superglus-built game files. */ /* #define TOLERATE_SUPERGLUS_BUG (1) */ /** * Uncomment this definition to turn on Glulx VM profiling. In this mode, all function calls are timed, * and the timing information is written to a data file called "profile-raw". * (Build note: on Linux, glibc may require you to also define _BSD_SOURCE or _DEFAULT_SOURCE or both * for the timeradd() macro.) */ /* #define VM_PROFILING (1) */ /** * Uncomment this definition to turn on the Glulx debugger. You should only do this when debugging * facilities are desired; it slows down the interpreter. If you do, you will need to build with libxml2; * see the Makefile. */ /* #define VM_DEBUGGER (1) */ /** * Comment this definition to turn off floating-point support. You might need to do this if you are building * on a very limited platform with no math library. */ #define FLOAT_SUPPORT (1) /** * Comment this definition to not cache the original state of RAM in (real) memory. This saves some memory, * but slows down save/restore/undo operations, which will have to read the original state off disk * every time. */ #define SERIALIZE_CACHE_RAM (1) /** * Some macros to read and write integers to memory, always in big-endian format. */ #define Read4(ptr) READ_BE_UINT32(ptr) #define Read2(ptr) READ_BE_UINT16(ptr) #define Read1(ptr) ((byte)(((byte *)(ptr))[0])) #define Write4(ptr, vl) WRITE_BE_UINT32(ptr, vl) #define Write2(ptr, vl) WRITE_BE_UINT16(ptr, vl) #define Write1(ptr, vl) (((byte *)(ptr))[0] = (vl)) #if VERIFY_MEMORY_ACCESS #define Verify(adr, ln) verify_address(adr, ln) #define VerifyW(adr, ln) verify_address_write(adr, ln) #else #define Verify(adr, ln) (0) #define VerifyW(adr, ln) (0) #endif /* VERIFY_MEMORY_ACCESS */ #define Mem1(adr) (Read1(memmap+(adr))) #define Mem2(adr) (Read2(memmap+(adr))) #define Mem4(adr) (Read4(memmap+(adr))) #define MemW1(adr, vl) (VerifyW(adr, 1), Write1(memmap+(adr), (vl))) #define MemW2(adr, vl) (VerifyW(adr, 2), Write2(memmap+(adr), (vl))) #define MemW4(adr, vl) (VerifyW(adr, 4), Write4(memmap+(adr), (vl))) #ifndef _HUGE_ENUF #define _HUGE_ENUF 1e+300 // _HUGE_ENUF*_HUGE_ENUF must overflow #endif #ifndef INFINITY #define INFINITY ((float)(_HUGE_ENUF * _HUGE_ENUF)) #endif #ifndef NAN #define NAN ((float)(INFINITY * 0.0F)) #endif /** * Macros to access values on the stack. These *must* be used with proper alignment! * (That is, Stk4 and StkW4 must take addresses which are multiples of four, etc.) * If the alignment rules are not followed, the program will see performance * degradation or even crashes, depending on the machine CPU. */ #define Stk1(adr) \ (*((unsigned char *)(stack+(adr)))) #define Stk2(adr) \ (*((uint16 *)(stack+(adr)))) #define Stk4(adr) \ (*((uint32 *)(stack+(adr)))) #define StkW1(adr, vl) \ (*((byte *)(stack+(adr))) = (byte)(vl)) #define StkW2(adr, vl) \ (*((uint16 *)(stack+(adr))) = (uint16)(vl)) #define StkW4(adr, vl) \ (*((uint32 *)(stack+(adr))) = (uint32)(vl)) enum Opcode { op_nop = 0x00, op_add = 0x10, op_sub = 0x11, op_mul = 0x12, op_div = 0x13, op_mod = 0x14, op_neg = 0x15, op_bitand = 0x18, op_bitor = 0x19, op_bitxor = 0x1A, op_bitnot = 0x1B, op_shiftl = 0x1C, op_sshiftr = 0x1D, op_ushiftr = 0x1E, op_jump = 0x20, op_jz = 0x22, op_jnz = 0x23, op_jeq = 0x24, op_jne = 0x25, op_jlt = 0x26, op_jge = 0x27, op_jgt = 0x28, op_jle = 0x29, op_jltu = 0x2A, op_jgeu = 0x2B, op_jgtu = 0x2C, op_jleu = 0x2D, op_call = 0x30, op_return = 0x31, op_catch = 0x32, op_throw = 0x33, op_tailcall = 0x34, op_copy = 0x40, op_copys = 0x41, op_copyb = 0x42, op_sexs = 0x44, op_sexb = 0x45, op_aload = 0x48, op_aloads = 0x49, op_aloadb = 0x4A, op_aloadbit = 0x4B, op_astore = 0x4C, op_astores = 0x4D, op_astoreb = 0x4E, op_astorebit = 0x4F, op_stkcount = 0x50, op_stkpeek = 0x51, op_stkswap = 0x52, op_stkroll = 0x53, op_stkcopy = 0x54, op_streamchar = 0x70, op_streamnum = 0x71, op_streamstr = 0x72, op_streamunichar = 0x73, op_gestalt = 0x100, op_debugtrap = 0x101, op_getmemsize = 0x102, op_setmemsize = 0x103, op_jumpabs = 0x104, op_random = 0x110, op_setrandom = 0x111, op_quit = 0x120, op_verify = 0x121, op_restart = 0x122, op_save = 0x123, op_restore = 0x124, op_saveundo = 0x125, op_restoreundo = 0x126, op_protect = 0x127, op_glk = 0x130, op_getstringtbl = 0x140, op_setstringtbl = 0x141, op_getiosys = 0x148, op_setiosys = 0x149, op_linearsearch = 0x150, op_binarysearch = 0x151, op_linkedsearch = 0x152, op_callf = 0x160, op_callfi = 0x161, op_callfii = 0x162, op_callfiii = 0x163, op_mzero = 0x170, op_mcopy = 0x171, op_malloc = 0x178, op_mfree = 0x179, op_accelfunc = 0x180, op_accelparam = 0x181, op_numtof = 0x190, op_ftonumz = 0x191, op_ftonumn = 0x192, op_ceil = 0x198, op_floor = 0x199, op_fadd = 0x1A0, op_fsub = 0x1A1, op_fmul = 0x1A2, op_fdiv = 0x1A3, op_fmod = 0x1A4, op_sqrt = 0x1A8, op_exp = 0x1A9, op_log = 0x1AA, op_pow = 0x1AB, op_sin = 0x1B0, op_cos = 0x1B1, op_tan = 0x1B2, op_asin = 0x1B3, op_acos = 0x1B4, op_atan = 0x1B5, op_atan2 = 0x1B6, op_jfeq = 0x1C0, op_jfne = 0x1C1, op_jflt = 0x1C2, op_jfle = 0x1C3, op_jfgt = 0x1C4, op_jfge = 0x1C5, op_jisnan = 0x1C8, op_jisinf = 0x1C9 }; enum gestulx { gestulx_GlulxVersion = 0, gestulx_TerpVersion = 1, gestulx_ResizeMem = 2, gestulx_Undo = 3, gestulx_IOSystem = 4, gestulx_Unicode = 5, gestulx_MemCopy = 6, gestulx_MAlloc = 7, gestulx_MAllocHeap = 8, gestulx_Acceleration = 9, gestulx_AccelFunc = 10, gestulx_Float = 11 }; /** * You may have to edit the definition of gfloat32 to make sure it's really a 32-bit floating-point type. */ typedef float gfloat32; struct dispatch_splot_struct { int numwanted; int maxargs; gluniversal_t *garglist; uint *varglist; int numvargs; uint *retval; }; typedef dispatch_splot_struct dispatch_splot_t; /** * We maintain a linked list of arrays being used for Glk calls. It is only used for integer * (uint) arrays -- char arrays are handled in place. It's not worth bothering with a hash table, * since most arrays appear here only momentarily. */ struct arrayref_struct { void *array; uint addr; uint elemsize; uint len; /* elements */ int retained; arrayref_struct *next; }; typedef arrayref_struct arrayref_t; /** * We maintain a hash table for each opaque Glk class. classref_t are the nodes of the table, * and classtable_t are the tables themselves. */ struct classref_struct { void *obj; uint id; int bucknum; classref_struct *next; }; typedef classref_struct classref_t; #define CLASSHASH_SIZE (31) struct classtable_struct { uint lastid; classref_t *bucket[CLASSHASH_SIZE]; }; typedef classtable_struct classtable_t; /** * Represents the operand structure of an opcode. */ struct operandlist_struct { int num_ops; ///< Number of operands for this opcode int arg_size; ///< Usually 4, but can be 1 or 2 const int *formlist; ///< Array of values, either modeform_Load or modeform_Store }; typedef operandlist_struct operandlist_t; enum modeform { modeform_Load = 1, modeform_Store = 2 }; /** * Represents one operand value to an instruction being executed. The * code in exec.c assumes that no instruction has more than MAX_OPERANDS of these. */ struct oparg_struct { uint desttype; uint value; }; typedef oparg_struct oparg_t; #define MAX_OPERANDS (8) typedef uint(Glulxe::*acceleration_func)(uint argc, uint *argv); struct accelentry_struct { uint addr; uint index; acceleration_func func; accelentry_struct *next; }; typedef accelentry_struct accelentry_t; #define ACCEL_HASH_SIZE (511) struct heapblock_struct { uint addr; uint len; int isfree; struct heapblock_struct *next; struct heapblock_struct *prev; }; typedef heapblock_struct heapblock_t; /** * This structure allows us to write either to a Glk stream or to a dynamically-allocated memory chunk. */ struct dest_struct { int ismem; /* If it's a Glk stream: */ strid_t str; /* If it's a block of memory: */ byte *ptr; uint pos; uint size; }; typedef dest_struct dest_t; /** * These constants are defined in the Glulx spec. */ enum iosys { iosys_None = 0, iosys_Filter = 1, iosys_Glk = 2 }; #define CACHEBITS (4) #define CACHESIZE (1 << CACHEBITS) #define CACHEMASK (15) struct cacheblock_struct { int depth; /* 1 to 4 */ int type; union { struct cacheblock_struct *branches; unsigned char ch; uint uch; uint addr; } u; }; typedef cacheblock_struct cacheblock_t; } // End of namespace Glulxe } // End of namespace Glk #endif