1 /* glulxe.h: Glulxe header file.
2 Designed by Andrew Plotkin <erkyrath@eblong.com>
3 http://eblong.com/zarf/glulx/index.html
9 /* We define our own TRUE and FALSE and NULL, because ANSI
10 is a strange world. */
21 /* You may have to edit the definition of glui16 to make sure it's really a
22 16-bit unsigned integer type, and glsi16 to make sure it's really a
23 16-bit signed integer type. If they're not, horrible things will happen. */
24 typedef unsigned short glui16;
25 typedef signed short glsi16;
27 /* Uncomment this definition to turn on memory-address checking. In
28 this mode, all reads and writes to main memory will be checked to
29 ensure they're in range. This is slower, but prevents malformed
30 game files from crashing the interpreter. */
31 /* #define VERIFY_MEMORY_ACCESS (1) */
33 /* Uncomment this definition to turn on Glulx VM profiling. In this
34 mode, all function calls are timed, and the timing information is
35 written to a data file called "profile-raw". */
36 /* #define VM_PROFILING (1) */
38 /* Comment this definition to turn off floating-point support. You
39 might need to do this if you are building on a very limited platform
40 with no math library. */
41 #define FLOAT_SUPPORT (1)
43 /* Some macros to read and write integers to memory, always in big-endian
46 ( (glui32)(((unsigned char *)(ptr))[0] << 24) \
47 | (glui32)(((unsigned char *)(ptr))[1] << 16) \
48 | (glui32)(((unsigned char *)(ptr))[2] << 8) \
49 | (glui32)(((unsigned char *)(ptr))[3]))
51 ( (glui16)(((unsigned char *)(ptr))[0] << 8) \
52 | (glui16)(((unsigned char *)(ptr))[1]))
54 ((unsigned char)(((unsigned char *)(ptr))[0]))
56 #define Write4(ptr, vl) \
57 (((ptr)[0] = (unsigned char)(((glui32)(vl)) >> 24)), \
58 ((ptr)[1] = (unsigned char)(((glui32)(vl)) >> 16)), \
59 ((ptr)[2] = (unsigned char)(((glui32)(vl)) >> 8)), \
60 ((ptr)[3] = (unsigned char)(((glui32)(vl)))))
61 #define Write2(ptr, vl) \
62 (((ptr)[0] = (unsigned char)(((glui32)(vl)) >> 8)), \
63 ((ptr)[1] = (unsigned char)(((glui32)(vl)))))
64 #define Write1(ptr, vl) \
65 (((unsigned char *)(ptr))[0] = (vl))
67 #if VERIFY_MEMORY_ACCESS
68 #define Verify(adr, ln) verify_address(adr, ln)
69 #define VerifyW(adr, ln) verify_address_write(adr, ln)
71 #define Verify(adr, ln) (0)
72 #define VerifyW(adr, ln) (0)
73 #endif /* VERIFY_MEMORY_ACCESS */
75 #define Mem1(adr) (Verify(adr, 1), Read1(memmap+(adr)))
76 #define Mem2(adr) (Verify(adr, 2), Read2(memmap+(adr)))
77 #define Mem4(adr) (Verify(adr, 4), Read4(memmap+(adr)))
78 #define MemW1(adr, vl) (VerifyW(adr, 1), Write1(memmap+(adr), (vl)))
79 #define MemW2(adr, vl) (VerifyW(adr, 2), Write2(memmap+(adr), (vl)))
80 #define MemW4(adr, vl) (VerifyW(adr, 4), Write4(memmap+(adr), (vl)))
82 /* Macros to access values on the stack. These *must* be used
83 with proper alignment! (That is, Stk4 and StkW4 must take
84 addresses which are multiples of four, etc.) If the alignment
85 rules are not followed, the program will see performance
86 degradation or even crashes, depending on the machine CPU. */
89 (*((unsigned char *)(stack+(adr))))
91 (*((glui16 *)(stack+(adr))))
93 (*((glui32 *)(stack+(adr))))
95 #define StkW1(adr, vl) \
96 (*((unsigned char *)(stack+(adr))) = (unsigned char)(vl))
97 #define StkW2(adr, vl) \
98 (*((glui16 *)(stack+(adr))) = (glui16)(vl))
99 #define StkW4(adr, vl) \
100 (*((glui32 *)(stack+(adr))) = (glui32)(vl))
102 /* Some useful structures. */
105 Represents one operand value to an instruction being executed. The
106 code in exec.c assumes that no instruction has more than MAX_OPERANDS
109 typedef struct oparg_struct {
114 #define MAX_OPERANDS (8)
117 Represents the operand structure of an opcode.
119 typedef struct operandlist_struct {
120 int num_ops; /* Number of operands for this opcode */
121 int arg_size; /* Usually 4, but can be 1 or 2 */
122 int *formlist; /* Array of values, either modeform_Load or modeform_Store */
124 #define modeform_Load (1)
125 #define modeform_Store (2)
127 /* Some useful globals */
129 extern strid_t gamefile;
130 extern glui32 gamefile_start, gamefile_len;
131 extern char *init_err, *init_err2;
133 extern unsigned char *memmap;
134 extern unsigned char *stack;
136 extern glui32 ramstart;
137 extern glui32 endgamefile;
138 extern glui32 origendmem;
139 extern glui32 stacksize;
140 extern glui32 startfuncaddr;
141 extern glui32 checksum;
142 extern glui32 stackptr;
143 extern glui32 frameptr;
145 extern glui32 origstringtable;
146 extern glui32 stringtable;
147 extern glui32 valstackbase;
148 extern glui32 localsbase;
149 extern glui32 endmem;
150 extern glui32 protectstart, protectend;
152 extern void (*stream_char_handler)(unsigned char ch);
153 extern void (*stream_unichar_handler)(glui32 ch);
156 extern void fatal_error_handler(char *str, char *arg, int useval, glsi32 val);
157 extern void nonfatal_warning_handler(char *str, char *arg, int useval, glsi32 val);
158 #define fatal_error(s) (fatal_error_handler((s), NULL, FALSE, 0))
159 #define fatal_error_2(s1, s2) (fatal_error_handler((s1), (s2), FALSE, 0))
160 #define fatal_error_i(s, v) (fatal_error_handler((s), NULL, TRUE, (v)))
161 #define nonfatal_warning(s) (nonfatal_warning_handler((s), NULL, FALSE, 0))
162 #define nonfatal_warning_2(s1, s2) (nonfatal_warning_handler((s1), (s2), FALSE, 0))
163 #define nonfatal_warning_i(s, v) (nonfatal_warning_handler((s), NULL, TRUE, (v)))
166 extern int is_gamefile_valid(void);
167 extern int locate_gamefile(int isblorb);
170 extern void setup_vm(void);
171 extern void finalize_vm(void);
172 extern void vm_restart(void);
173 extern glui32 change_memsize(glui32 newlen, int internal);
174 extern glui32 *pop_arguments(glui32 count, glui32 addr);
175 extern void verify_address(glui32 addr, glui32 count);
176 extern void verify_address_write(glui32 addr, glui32 count);
177 extern void verify_array_addresses(glui32 addr, glui32 count, glui32 size);
180 extern void execute_loop(void);
183 extern operandlist_t *fast_operandlist[0x80];
184 extern void init_operands(void);
185 extern operandlist_t *lookup_operandlist(glui32 opcode);
186 extern void parse_operands(oparg_t *opargs, operandlist_t *oplist);
187 extern void store_operand(glui32 desttype, glui32 destaddr, glui32 storeval);
188 extern void store_operand_s(glui32 desttype, glui32 destaddr, glui32 storeval);
189 extern void store_operand_b(glui32 desttype, glui32 destaddr, glui32 storeval);
192 extern void enter_function(glui32 addr, glui32 argc, glui32 *argv);
193 extern void leave_function(void);
194 extern void push_callstub(glui32 desttype, glui32 destaddr);
195 extern void pop_callstub(glui32 returnvalue);
196 extern glui32 pop_callstub_string(int *bitnum);
199 extern void stream_num(glsi32 val, int inmiddle, int charnum);
200 extern void stream_string(glui32 addr, int inmiddle, int bitnum);
201 extern glui32 stream_get_table(void);
202 extern void stream_set_table(glui32 addr);
203 extern void stream_get_iosys(glui32 *mode, glui32 *rock);
204 extern void stream_set_iosys(glui32 mode, glui32 rock);
205 extern char *make_temp_string(glui32 addr);
206 extern glui32 *make_temp_ustring(glui32 addr);
207 extern void free_temp_string(char *str);
208 extern void free_temp_ustring(glui32 *str);
211 extern void heap_clear(void);
212 extern int heap_is_active(void);
213 extern glui32 heap_get_start(void);
214 extern glui32 heap_alloc(glui32 len);
215 extern void heap_free(glui32 addr);
216 extern int heap_get_summary(glui32 *valcount, glui32 **summary);
217 extern int heap_apply_summary(glui32 valcount, glui32 *summary);
218 extern void heap_sanity_check(void);
221 extern int init_serial(void);
222 extern glui32 perform_save(strid_t str);
223 extern glui32 perform_restore(strid_t str);
224 extern glui32 perform_saveundo(void);
225 extern glui32 perform_restoreundo(void);
226 extern glui32 perform_verify(void);
229 extern glui32 linear_search(glui32 key, glui32 keysize,
230 glui32 start, glui32 structsize, glui32 numstructs,
231 glui32 keyoffset, glui32 options);
232 extern glui32 binary_search(glui32 key, glui32 keysize,
233 glui32 start, glui32 structsize, glui32 numstructs,
234 glui32 keyoffset, glui32 options);
235 extern glui32 linked_search(glui32 key, glui32 keysize,
236 glui32 start, glui32 keyoffset, glui32 nextoffset,
240 extern void *glulx_malloc(glui32 len);
241 extern void *glulx_realloc(void *ptr, glui32 len);
242 extern void glulx_free(void *ptr);
243 extern void glulx_setrandom(glui32 seed);
244 extern glui32 glulx_random(void);
245 extern void glulx_sort(void *addr, int count, int size,
246 int (*comparefunc)(void *p1, void *p2));
249 extern glui32 do_gestalt(glui32 val, glui32 val2);
252 extern int init_dispatch(void);
253 extern glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist);
254 extern strid_t find_stream_by_id(glui32 objid);
257 extern void setup_profile(strid_t stream, char *filename);
258 extern int init_profile(void);
260 extern glui32 profile_opcount;
261 #define profile_tick() (profile_opcount++)
262 extern void profile_in(glui32 addr, glui32 stackuse, int accel);
263 extern void profile_out(glui32 stackuse);
264 extern void profile_fail(char *reason);
265 extern void profile_quit(void);
266 #else /* VM_PROFILING */
267 #define profile_tick() (0)
268 #define profile_in(addr, stackuse, accel) (0)
269 #define profile_out(stackuse) (0)
270 #define profile_fail(reason) (0)
271 #define profile_quit() (0)
272 #endif /* VM_PROFILING */
275 typedef glui32 (*acceleration_func)(glui32 argc, glui32 *argv);
276 extern void init_accel(void);
277 extern acceleration_func accel_find_func(glui32 index);
278 extern acceleration_func accel_get_func(glui32 addr);
279 extern void accel_set_func(glui32 index, glui32 addr);
280 extern void accel_set_param(glui32 index, glui32 val);
284 /* You may have to edit the definition of gfloat32 to make sure it's really
285 a 32-bit floating-point type. */
286 typedef float gfloat32;
288 /* Uncomment this definition if your gfloat32 type is not a standard
289 IEEE-754 single-precision (32-bit) format. Normally, Glulxe assumes
290 that it can reinterpret-cast IEEE-754 int values into gfloat32
291 values. If you uncomment this, Glulxe switches to lengthier
292 (but safer) encoding and decoding functions. */
293 /* #define FLOAT_NOT_NATIVE (1) */
296 extern int init_float(void);
297 extern glui32 encode_float(gfloat32 val);
298 extern gfloat32 decode_float(glui32 val);
300 /* Uncomment this definition if your powf() function does not support
301 all the corner cases specified by C99. If you uncomment this,
302 osdepend.c will provide a safer implementation of glulx_powf(). */
303 /* #define FLOAT_COMPILE_SAFER_POWF (1) */
305 extern gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2);
307 #endif /* FLOAT_SUPPORT */
309 #endif /* _GLULXE_H */