Updated interpreters
[projects/chimara/chimara.git] / interpreters / glulxe / glulxe.h
1 /* glulxe.h: Glulxe header file.
2     Designed by Andrew Plotkin <erkyrath@eblong.com>
3     http://eblong.com/zarf/glulx/index.html
4 */
5
6 #ifndef _GLULXE_H
7 #define _GLULXE_H
8
9 /* We define our own TRUE and FALSE and NULL, because ANSI
10    is a strange world. */
11 #ifndef TRUE
12 #define TRUE 1
13 #endif
14 #ifndef FALSE
15 #define FALSE 0
16 #endif
17 #ifndef NULL
18 #define NULL 0
19 #endif
20
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; 
26
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) */
32
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) */
37
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)
42
43 /* Some macros to read and write integers to memory, always in big-endian
44    format. */
45 #define Read4(ptr)    \
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]))
50 #define Read2(ptr)    \
51   ( (glui16)(((unsigned char *)(ptr))[0] << 8)  \
52   | (glui16)(((unsigned char *)(ptr))[1]))
53 #define Read1(ptr)    \
54   ((unsigned char)(((unsigned char *)(ptr))[0]))
55
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))
66
67 #if VERIFY_MEMORY_ACCESS
68 #define Verify(adr, ln) verify_address(adr, ln)
69 #define VerifyW(adr, ln) verify_address_write(adr, ln)
70 #else
71 #define Verify(adr, ln) (0)
72 #define VerifyW(adr, ln) (0)
73 #endif /* VERIFY_MEMORY_ACCESS */
74
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)))
81
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. */
87
88 #define Stk1(adr)   \
89   (*((unsigned char *)(stack+(adr))))
90 #define Stk2(adr)   \
91   (*((glui16 *)(stack+(adr))))
92 #define Stk4(adr)   \
93   (*((glui32 *)(stack+(adr))))
94
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))
101
102 /* Some useful structures. */
103
104 /* oparg_t:
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
107    of these.
108 */
109 typedef struct oparg_struct {
110   glui32 desttype;
111   glui32 value;
112 } oparg_t;
113
114 #define MAX_OPERANDS (8)
115
116 /* operandlist_t:
117    Represents the operand structure of an opcode.
118 */
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 */
123 } operandlist_t;
124 #define modeform_Load (1)
125 #define modeform_Store (2)
126
127 /* Some useful globals */
128
129 extern strid_t gamefile;
130 extern glui32 gamefile_start, gamefile_len;
131 extern char *init_err, *init_err2;
132
133 extern unsigned char *memmap;
134 extern unsigned char *stack;
135
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;
144 extern glui32 pc;
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;
151
152 extern void (*stream_char_handler)(unsigned char ch);
153 extern void (*stream_unichar_handler)(glui32 ch);
154
155 /* main.c */
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)))
164
165 /* files.c */
166 extern int is_gamefile_valid(void);
167 extern int locate_gamefile(int isblorb);
168
169 /* vm.c */
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);
178
179 /* exec.c */
180 extern void execute_loop(void);
181
182 /* operand.c */
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);
190
191 /* funcs.c */
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);
197
198 /* string.c */
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);
209
210 /* heap.c */
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);
219
220 /* serial.c */
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);
227
228 /* search.c */
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,
237   glui32 options);
238
239 /* osdepend.c */
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));
247
248 /* gestalt.c */
249 extern glui32 do_gestalt(glui32 val, glui32 val2);
250
251 /* glkop.c */
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);
255
256 /* profile.c */
257 extern int init_profile(void);
258 #if VM_PROFILING
259 extern glui32 profile_opcount;
260 #define profile_tick() (profile_opcount++)
261 extern void profile_in(glui32 addr, int accel);
262 extern void profile_out(void);
263 extern void profile_fail(char *reason);
264 extern void profile_quit(void);
265 #else /* VM_PROFILING */
266 #define profile_tick()       (0)
267 #define profile_in(addr, accel)  (0)
268 #define profile_out()        (0)
269 #define profile_fail(reason) (0)
270 #define profile_quit()       (0)
271 #endif /* VM_PROFILING */
272
273 /* accel.c */
274 typedef glui32 (*acceleration_func)(glui32 argc, glui32 *argv);
275 extern void init_accel(void);
276 extern acceleration_func accel_find_func(glui32 index);
277 extern acceleration_func accel_get_func(glui32 addr);
278 extern void accel_set_func(glui32 index, glui32 addr);
279 extern void accel_set_param(glui32 index, glui32 val);
280
281 #ifdef FLOAT_SUPPORT
282
283 /* You may have to edit the definition of gfloat32 to make sure it's really
284    a 32-bit floating-point type. */
285 typedef float gfloat32;
286
287 /* Uncomment this definition if your gfloat32 type is not a standard
288    IEEE-754 single-precision (32-bit) format. Normally, Glulxe assumes
289    that it can reinterpret-cast IEEE-754 int values into gfloat32
290    values. If you uncomment this, Glulxe switches to lengthier
291    (but safer) encoding and decoding functions. */
292 /* #define FLOAT_NOT_NATIVE (1) */
293
294 /* float.c */
295 extern int init_float(void);
296 extern glui32 encode_float(gfloat32 val);
297 extern gfloat32 decode_float(glui32 val);
298
299 /* Uncomment this definition if your powf() function does not support
300    all the corner cases specified by C99. If you uncomment this,
301    osdepend.c will provide a safer implementation of glulx_powf(). */
302 /* #define FLOAT_COMPILE_SAFER_POWF (1) */
303
304 extern gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2);
305
306 #endif /* FLOAT_SUPPORT */
307
308 #endif /* _GLULXE_H */