X-Git-Url: https://git.stderr.nl/gitweb?a=blobdiff_plain;f=interpreters%2Fglulxe%2Fglulxe.h;fp=interpreters%2Fglulxe%2Fglulxe.h;h=093ac6a600c75b4e5dd98f4b973fce05ca274124;hb=147a8cbf17f2b3379277bf7d37cda9866510f16c;hp=0000000000000000000000000000000000000000;hpb=7de488aa6a1709a4d5c59b5ff59862105c1748c5;p=rodin%2Fchimara.git diff --git a/interpreters/glulxe/glulxe.h b/interpreters/glulxe/glulxe.h new file mode 100644 index 0000000..093ac6a --- /dev/null +++ b/interpreters/glulxe/glulxe.h @@ -0,0 +1,271 @@ +/* glulxe.h: Glulxe header file. + Designed by Andrew Plotkin + 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 */