Add Glulxe and Git. They compile but don't work yet.
[rodin/chimara.git] / interpreters / glulxe / glulxe.h
diff --git a/interpreters/glulxe/glulxe.h b/interpreters/glulxe/glulxe.h
new file mode 100644 (file)
index 0000000..093ac6a
--- /dev/null
@@ -0,0 +1,271 @@
+/* glulxe.h: Glulxe header file.
+    Designed by Andrew Plotkin <erkyrath@eblong.com>
+    http://eblong.com/zarf/glulx/index.html
+*/
+
+#ifndef _GLULXE_H
+#define _GLULXE_H
+
+/* We define our own TRUE and FALSE and NULL, because ANSI
+   is a strange world. */
+#ifndef TRUE
+#define TRUE 1
+#endif
+#ifndef FALSE
+#define FALSE 0
+#endif
+#ifndef NULL
+#define NULL 0
+#endif
+
+/* You may have to edit the definition of glui16 to make sure it's really a
+   16-bit unsigned integer type, and glsi16 to make sure it's really a
+   16-bit signed integer type. If they're not, horrible things will happen. */
+typedef unsigned short glui16; 
+typedef signed short glsi16; 
+
+/* Uncomment this definition to turn on memory-address checking. In
+   this mode, 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 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". */
+/* #define VM_PROFILING (1) */
+
+/* Some macros to read and write integers to memory, always in big-endian
+   format. */
+#define Read4(ptr)    \
+  ( (glui32)(((unsigned char *)(ptr))[0] << 24)  \
+  | (glui32)(((unsigned char *)(ptr))[1] << 16)  \
+  | (glui32)(((unsigned char *)(ptr))[2] << 8)   \
+  | (glui32)(((unsigned char *)(ptr))[3]))
+#define Read2(ptr)    \
+  ( (glui16)(((unsigned char *)(ptr))[0] << 8)  \
+  | (glui16)(((unsigned char *)(ptr))[1]))
+#define Read1(ptr)    \
+  ((unsigned char)(((unsigned char *)(ptr))[0]))
+
+#define Write4(ptr, vl)   \
+  (((ptr)[0] = (unsigned char)(((glui32)(vl)) >> 24)),   \
+   ((ptr)[1] = (unsigned char)(((glui32)(vl)) >> 16)),   \
+   ((ptr)[2] = (unsigned char)(((glui32)(vl)) >> 8)),    \
+   ((ptr)[3] = (unsigned char)(((glui32)(vl)))))
+#define Write2(ptr, vl)   \
+  (((ptr)[0] = (unsigned char)(((glui32)(vl)) >> 8)),   \
+   ((ptr)[1] = (unsigned char)(((glui32)(vl)))))
+#define Write1(ptr, vl)   \
+  (((unsigned char *)(ptr))[0] = (vl))
+
+#if VERIFY_MEMORY_ACCESS
+#define Verify(adr, ln) verify_address(adr, ln)
+#else
+#define Verify(adr, ln) (0)
+#endif /* VERIFY_MEMORY_ACCESS */
+
+#define Mem1(adr)  (Verify(adr, 1), Read1(memmap+(adr)))
+#define Mem2(adr)  (Verify(adr, 2), Read2(memmap+(adr)))
+#define Mem4(adr)  (Verify(adr, 4), Read4(memmap+(adr)))
+#define MemW1(adr, vl)  (Verify(adr, 1), Write1(memmap+(adr), (vl)))
+#define MemW2(adr, vl)  (Verify(adr, 2), Write2(memmap+(adr), (vl)))
+#define MemW4(adr, vl)  (Verify(adr, 4), Write4(memmap+(adr), (vl)))
+
+/* 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)   \
+  (*((glui16 *)(stack+(adr))))
+#define Stk4(adr)   \
+  (*((glui32 *)(stack+(adr))))
+
+#define StkW1(adr, vl)   \
+  (*((unsigned char *)(stack+(adr))) = (unsigned char)(vl))
+#define StkW2(adr, vl)   \
+  (*((glui16 *)(stack+(adr))) = (glui16)(vl))
+#define StkW4(adr, vl)   \
+  (*((glui32 *)(stack+(adr))) = (glui32)(vl))
+
+/* Some useful structures. */
+
+/* instruction_t:
+   Represents the list of operands to an instruction being executed.
+   (Yes, it's somewhat misnamed. Sorry.) We assume, for the indefinite
+   moment, that no opcode has more than 8 operands, and no opcode
+   has two "store" operands.
+*/
+typedef struct instruction_struct {
+  glui32 desttype;
+  glui32 value[8];
+} instruction_t;
+
+/* operandlist_t:
+   Represents the operand structure of an opcode.
+*/
+typedef struct operandlist_struct {
+  int num_ops; /* Number of operands for this opcode */
+  int arg_size; /* Usually 4, but can be 1 or 2 */
+  int *formlist; /* Array of values, either modeform_Load or modeform_Store */
+} operandlist_t;
+#define modeform_Load (1)
+#define modeform_Store (2)
+
+/* Some useful globals */
+
+extern strid_t gamefile;
+extern glui32 gamefile_start, gamefile_len;
+extern char *init_err, *init_err2;
+
+extern unsigned char *memmap;
+extern unsigned char *stack;
+
+extern glui32 ramstart;
+extern glui32 endgamefile;
+extern glui32 origendmem;
+extern glui32 stacksize;
+extern glui32 startfuncaddr;
+extern glui32 checksum;
+extern glui32 stackptr;
+extern glui32 frameptr;
+extern glui32 pc;
+extern glui32 origstringtable;
+extern glui32 stringtable;
+extern glui32 valstackbase;
+extern glui32 localsbase;
+extern glui32 endmem;
+extern glui32 protectstart, protectend;
+
+extern void (*stream_char_handler)(unsigned char ch);
+extern void (*stream_unichar_handler)(glui32 ch);
+
+/* main.c */
+extern void fatal_error_handler(char *str, char *arg, int useval, glsi32 val);
+extern void nonfatal_warning_handler(char *str, char *arg, int useval, glsi32 val);
+#define fatal_error(s)  (fatal_error_handler((s), NULL, FALSE, 0))
+#define fatal_error_2(s1, s2)  (fatal_error_handler((s1), (s2), FALSE, 0))
+#define fatal_error_i(s, v)  (fatal_error_handler((s), NULL, TRUE, (v)))
+#define nonfatal_warning(s) (nonfatal_warning_handler((s), NULL, FALSE, 0))
+#define nonfatal_warning_2(s1, s2) (nonfatal_warning_handler((s1), (s2), FALSE, 0))
+#define nonfatal_warning_i(s, v) (nonfatal_warning_handler((s), NULL, TRUE, (v)))
+
+/* files.c */
+extern int is_gamefile_valid(void);
+extern int locate_gamefile(int isblorb);
+
+/* vm.c */
+extern void setup_vm(void);
+extern void finalize_vm(void);
+extern void vm_restart(void);
+extern glui32 change_memsize(glui32 newlen, int internal);
+extern glui32 *pop_arguments(glui32 count, glui32 addr);
+extern void verify_address(glui32 addr, glui32 count);
+
+/* exec.c */
+extern void execute_loop(void);
+
+/* operand.c */
+extern operandlist_t *fast_operandlist[0x80];
+extern void init_operands(void);
+extern operandlist_t *lookup_operandlist(glui32 opcode);
+extern void parse_operands(instruction_t *inst, operandlist_t *oplist);
+extern void store_operand(glui32 desttype, glui32 destaddr, glui32 storeval);
+extern void store_operand_s(glui32 desttype, glui32 destaddr, glui32 storeval);
+extern void store_operand_b(glui32 desttype, glui32 destaddr, glui32 storeval);
+
+/* funcs.c */
+extern void enter_function(glui32 addr, glui32 argc, glui32 *argv);
+extern void leave_function(void);
+extern void push_callstub(glui32 desttype, glui32 destaddr);
+extern void pop_callstub(glui32 returnvalue);
+extern glui32 pop_callstub_string(int *bitnum);
+
+/* string.c */
+extern void stream_num(glsi32 val, int inmiddle, int charnum);
+extern void stream_string(glui32 addr, int inmiddle, int bitnum);
+extern glui32 stream_get_table(void);
+extern void stream_set_table(glui32 addr);
+extern void stream_get_iosys(glui32 *mode, glui32 *rock);
+extern void stream_set_iosys(glui32 mode, glui32 rock);
+extern char *make_temp_string(glui32 addr);
+extern glui32 *make_temp_ustring(glui32 addr);
+extern void free_temp_string(char *str);
+extern void free_temp_ustring(glui32 *str);
+
+/* heap.c */
+extern void heap_clear(void);
+extern int heap_is_active(void);
+extern glui32 heap_get_start(void);
+extern glui32 heap_alloc(glui32 len);
+extern void heap_free(glui32 addr);
+extern int heap_get_summary(glui32 *valcount, glui32 **summary);
+extern int heap_apply_summary(glui32 valcount, glui32 *summary);
+extern void heap_sanity_check(void);
+
+/* serial.c */
+extern int init_serial(void);
+extern glui32 perform_save(strid_t str);
+extern glui32 perform_restore(strid_t str);
+extern glui32 perform_saveundo(void);
+extern glui32 perform_restoreundo(void);
+extern glui32 perform_verify(void);
+
+/* search.c */
+extern glui32 linear_search(glui32 key, glui32 keysize, 
+  glui32 start, glui32 structsize, glui32 numstructs, 
+  glui32 keyoffset, glui32 options);
+extern glui32 binary_search(glui32 key, glui32 keysize, 
+  glui32 start, glui32 structsize, glui32 numstructs, 
+  glui32 keyoffset, glui32 options);
+extern glui32 linked_search(glui32 key, glui32 keysize, 
+  glui32 start, glui32 keyoffset, glui32 nextoffset,
+  glui32 options);
+
+/* osdepend.c */
+extern void *glulx_malloc(glui32 len);
+extern void *glulx_realloc(void *ptr, glui32 len);
+extern void glulx_free(void *ptr);
+extern void glulx_setrandom(glui32 seed);
+extern glui32 glulx_random(void);
+extern void glulx_sort(void *addr, int count, int size, 
+  int (*comparefunc)(void *p1, void *p2));
+
+/* gestalt.c */
+extern glui32 do_gestalt(glui32 val, glui32 val2);
+
+/* glkop.c */
+extern int init_dispatch(void);
+extern glui32 perform_glk(glui32 funcnum, glui32 numargs, glui32 *arglist);
+extern strid_t find_stream_by_id(glui32 objid);
+
+/* profile.c */
+extern int init_profile(void);
+#if VM_PROFILING
+extern glui32 profile_opcount;
+#define profile_tick() (profile_opcount++)
+extern void profile_in(glui32 addr, int accel);
+extern void profile_out(void);
+extern void profile_fail(char *reason);
+extern void profile_quit(void);
+#else /* VM_PROFILING */
+#define profile_tick()       (0)
+#define profile_in(addr, accel)  (0)
+#define profile_out()        (0)
+#define profile_fail(reason) (0)
+#define profile_quit()       (0)
+#endif /* VM_PROFILING */
+
+/* accel.c */
+typedef glui32 (*acceleration_func)(glui32 argc, glui32 *argv);
+extern void init_accel(void);
+extern acceleration_func accel_find_func(glui32 index);
+extern acceleration_func accel_get_func(glui32 addr);
+extern void accel_set_func(glui32 index, glui32 addr);
+extern void accel_set_param(glui32 index, glui32 val);
+
+#endif /* _GLULXE_H */