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