Misc Garglk extensions documenting
[projects/chimara/chimara.git] / interpreters / glulxe / osdepend.c
1 /* osdepend.c: Glulxe platform-dependent code.
2     Designed by Andrew Plotkin <erkyrath@eblong.com>
3     http://eblong.com/zarf/glulx/index.html
4 */
5
6 #include "glk.h"
7 #include "glulxe.h"
8
9 /* This file contains definitions for platform-dependent code. Since
10    Glk takes care of I/O, this is a short list -- memory allocation
11    and random numbers.
12
13    The Makefile (or whatever) should define OS_UNIX, or some other
14    symbol. Code contributions welcome. 
15 */
16
17 #ifdef OS_UNIX
18
19 #include <time.h>
20 #include <stdlib.h>
21
22 /* Allocate a chunk of memory. */
23 void *glulx_malloc(glui32 len)
24 {
25   return malloc(len);
26 }
27
28 /* Resize a chunk of memory. This must follow ANSI rules: if the
29    size-change fails, this must return NULL, but the original chunk 
30    must remain unchanged. */
31 void *glulx_realloc(void *ptr, glui32 len)
32 {
33   return realloc(ptr, len);
34 }
35
36 /* Deallocate a chunk of memory. */
37 void glulx_free(void *ptr)
38 {
39   free(ptr);
40 }
41
42 /* Set the random-number seed; zero means use as random a source as
43    possible. */
44 void glulx_setrandom(glui32 seed)
45 {
46   if (seed == 0)
47     seed = time(NULL);
48   srandom(seed);
49 }
50
51 /* Return a random number in the range 0 to 2^32-1. */
52 glui32 glulx_random()
53 {
54   return (random() << 16) ^ random();
55 }
56
57 #endif /* OS_UNIX */
58
59 #ifdef OS_MAC
60
61 /* The Glk library uses malloc/free liberally, so we might as well also. */
62 #include <stdlib.h>
63
64 /* Allocate a chunk of memory. */
65 void *glulx_malloc(glui32 len)
66 {
67   return malloc(len);
68 }
69
70 /* Resize a chunk of memory. This must follow ANSI rules: if the
71    size-change fails, this must return NULL, but the original chunk 
72    must remain unchanged. */
73 void *glulx_realloc(void *ptr, glui32 len)
74 {
75   return realloc(ptr, len);
76 }
77
78 /* Deallocate a chunk of memory. */
79 void glulx_free(void *ptr)
80 {
81   free(ptr);
82 }
83
84 #define COMPILE_RANDOM_CODE
85 static glui32 lo_random(void);
86 static void lo_seed_random(glui32 seed);
87
88 /* Return a random number in the range 0 to 2^32-1. */
89 glui32 glulx_random()
90 {
91   return (lo_random() << 16) ^ lo_random();
92 }
93
94 /* Set the random-number seed; zero means use as random a source as
95    possible. */
96 void glulx_setrandom(glui32 seed)
97 {
98   if (seed == 0)
99     seed = TickCount() ^ Random();
100   lo_seed_random(seed);
101 }
102
103 #endif /* OS_MAC */
104
105 #ifdef WIN32
106
107 #include <time.h>
108 #include <stdlib.h>
109
110 /* Allocate a chunk of memory. */
111 void *glulx_malloc(glui32 len)
112 {
113   return malloc(len);
114 }
115
116 /* Resize a chunk of memory. This must follow ANSI rules: if the
117    size-change fails, this must return NULL, but the original chunk 
118    must remain unchanged. */
119 void *glulx_realloc(void *ptr, glui32 len)
120 {
121   return realloc(ptr, len);
122 }
123
124 /* Deallocate a chunk of memory. */
125 void glulx_free(void *ptr)
126 {
127   free(ptr);
128 }
129
130 /* Set the random-number seed; zero means use as random a source as
131    possible. */
132 void glulx_setrandom(glui32 seed)
133 {
134   if (seed == 0)
135     seed = time(NULL);
136   srand(seed);
137 }
138
139 /* Return a random number in the range 0 to 2^32-1. */
140 glui32 glulx_random()
141 {
142   return (rand() << 24) ^ (rand() << 12) ^ rand();
143 }
144
145 #endif /* WIN32 */
146
147 #ifdef COMPILE_RANDOM_CODE
148
149 /* Here is a pretty standard random-number generator and seed function. */
150 static glui32 lo_random(void);
151 static void lo_seed_random(glui32 seed);
152 static glui32 rand_table[55]; /* State for the RNG. */
153 static int rand_index1, rand_index2;
154
155 static glui32 lo_random()
156 {
157   rand_index1 = (rand_index1 + 1) % 55;
158   rand_index2 = (rand_index2 + 1) % 55;
159   rand_table[rand_index1] = rand_table[rand_index1] - rand_table[rand_index2];
160   return rand_table[rand_index1];
161 }
162
163 static void lo_seed_random(glui32 seed)
164 {
165   glui32 k = 1;
166   int i, loop;
167
168   rand_table[54] = seed;
169   rand_index1 = 0;
170   rand_index2 = 31;
171   
172   for (i = 0; i < 55; i++) {
173     int ii = (21 * i) % 55;
174     rand_table[ii] = k;
175     k = seed - k;
176     seed = rand_table[ii];
177   }
178   for (loop = 0; loop < 4; loop++) {
179     for (i = 0; i < 55; i++)
180       rand_table[i] = rand_table[i] - rand_table[ (1 + i + 30) % 55];
181   }
182 }
183
184 #endif /* COMPILE_RANDOM_CODE */
185
186 #include <stdlib.h>
187
188 /* I'm putting a wrapper for qsort() here, in case I ever have to
189    worry about a platform without it. But I am not worrying at
190    present. */
191 void glulx_sort(void *addr, int count, int size, 
192   int (*comparefunc)(void *p1, void *p2))
193 {
194   qsort(addr, count, size, (int (*)(const void *, const void *))comparefunc);
195 }
196
197 #ifdef FLOAT_SUPPORT
198 #include <math.h>
199
200 #ifdef FLOAT_COMPILE_SAFER_POWF
201
202 /* This wrapper handles all special cases, even if the underlying
203    powf() function doesn't. */
204 gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2)
205 {
206   if (val1 == 1.0f)
207     return 1.0f;
208   else if ((val2 == 0.0f) || (val2 == -0.0f))
209     return 1.0f;
210   else if ((val1 == -1.0f) && isinf(val2))
211     return 1.0f;
212   return powf(val1, val2);
213 }
214
215 #else /* FLOAT_COMPILE_SAFER_POWF */
216
217 /* This is the standard powf() function, unaltered. */
218 gfloat32 glulx_powf(gfloat32 val1, gfloat32 val2)
219 {
220   return powf(val1, val2);
221 }
222
223 #endif /* FLOAT_COMPILE_SAFER_POWF */
224
225 #endif /* FLOAT_SUPPORT */