/* osdepend.c: Glulxe platform-dependent code. Designed by Andrew Plotkin http://eblong.com/zarf/glulx/index.html */ #include "glk.h" #include "glulxe.h" /* This file contains definitions for platform-dependent code. Since Glk takes care of I/O, this is a short list -- memory allocation and random numbers. The Makefile (or whatever) should define OS_UNIX, or some other symbol. Code contributions welcome. */ #ifdef OS_UNIX #include #include /* Allocate a chunk of memory. */ void *glulx_malloc(glui32 len) { return malloc(len); } /* Resize a chunk of memory. This must follow ANSI rules: if the size-change fails, this must return NULL, but the original chunk must remain unchanged. */ void *glulx_realloc(void *ptr, glui32 len) { return realloc(ptr, len); } /* Deallocate a chunk of memory. */ void glulx_free(void *ptr) { free(ptr); } /* Set the random-number seed; zero means use as random a source as possible. */ void glulx_setrandom(glui32 seed) { if (seed == 0) seed = time(NULL); srandom(seed); } /* Return a random number in the range 0 to 2^32-1. */ glui32 glulx_random() { return (random() << 16) ^ random(); } #endif /* OS_UNIX */ #ifdef OS_MAC /* The Glk library uses malloc/free liberally, so we might as well also. */ #include /* Allocate a chunk of memory. */ void *glulx_malloc(glui32 len) { return malloc(len); } /* Resize a chunk of memory. This must follow ANSI rules: if the size-change fails, this must return NULL, but the original chunk must remain unchanged. */ void *glulx_realloc(void *ptr, glui32 len) { return realloc(ptr, len); } /* Deallocate a chunk of memory. */ void glulx_free(void *ptr) { free(ptr); } #define COMPILE_RANDOM_CODE static glui32 lo_random(void); static void lo_seed_random(glui32 seed); /* Return a random number in the range 0 to 2^32-1. */ glui32 glulx_random() { return (lo_random() << 16) ^ lo_random(); } /* Set the random-number seed; zero means use as random a source as possible. */ void glulx_setrandom(glui32 seed) { if (seed == 0) seed = TickCount() ^ Random(); lo_seed_random(seed); } #endif /* OS_MAC */ #ifdef WIN32 #include #include /* Allocate a chunk of memory. */ void *glulx_malloc(glui32 len) { return malloc(len); } /* Resize a chunk of memory. This must follow ANSI rules: if the size-change fails, this must return NULL, but the original chunk must remain unchanged. */ void *glulx_realloc(void *ptr, glui32 len) { return realloc(ptr, len); } /* Deallocate a chunk of memory. */ void glulx_free(void *ptr) { free(ptr); } /* Set the random-number seed; zero means use as random a source as possible. */ void glulx_setrandom(glui32 seed) { if (seed == 0) seed = time(NULL); srand(seed); } /* Return a random number in the range 0 to 2^32-1. */ glui32 glulx_random() { return (rand() << 24) ^ (rand() << 12) ^ rand(); } #endif /* WIN32 */ #ifdef COMPILE_RANDOM_CODE /* Here is a pretty standard random-number generator and seed function. */ static glui32 lo_random(void); static void lo_seed_random(glui32 seed); static glui32 rand_table[55]; /* State for the RNG. */ static int rand_index1, rand_index2; static glui32 lo_random() { rand_index1 = (rand_index1 + 1) % 55; rand_index2 = (rand_index2 + 1) % 55; rand_table[rand_index1] = rand_table[rand_index1] - rand_table[rand_index2]; return rand_table[rand_index1]; } static void lo_seed_random(glui32 seed) { glui32 k = 1; int i, loop; rand_table[54] = seed; rand_index1 = 0; rand_index2 = 31; for (i = 0; i < 55; i++) { int ii = (21 * i) % 55; rand_table[ii] = k; k = seed - k; seed = rand_table[ii]; } for (loop = 0; loop < 4; loop++) { for (i = 0; i < 55; i++) rand_table[i] = rand_table[i] - rand_table[ (1 + i + 30) % 55]; } } #endif /* COMPILE_RANDOM_CODE */ #include /* I'm putting a wrapper for qsort() here, in case I ever have to worry about a platform without it. But I am not worrying at present. */ void glulx_sort(void *addr, int count, int size, int (*comparefunc)(void *p1, void *p2)) { qsort(addr, count, size, (int (*)(const void *, const void *))comparefunc); } #ifdef FLOAT_SUPPORT #include #ifdef FLOAT_COMPILE_SAFER_POWF /* This wrapper handles all special cases, even if the underlying powf() function doesn't. */ gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2) { if (val1 == 1.0f) return 1.0f; else if ((val2 == 0.0f) || (val2 == -0.0f)) return 1.0f; else if ((val1 == -1.0f) && isinf(val2)) return 1.0f; return powf(val1, val2); } #else /* FLOAT_COMPILE_SAFER_POWF */ /* This is the standard powf() function, unaltered. */ gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2) { return powf(val1, val2); } #endif /* FLOAT_COMPILE_SAFER_POWF */ #endif /* FLOAT_SUPPORT */