forked from erkyrath/glulxe
-
Notifications
You must be signed in to change notification settings - Fork 0
/
osdepend.c
231 lines (185 loc) · 5.01 KB
/
osdepend.c
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
/* osdepend.c: Glulxe platform-dependent code.
Designed by Andrew Plotkin <[email protected]>
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 <time.h>
#include <stdlib.h>
/* 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 <stdlib.h>
/* 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 <time.h>
#include <stdlib.h>
/* 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();
}
__declspec(dllimport) unsigned long __stdcall GetTickCount(void);
/* Set the random-number seed; zero means use as random a source as
possible. */
void glulx_setrandom(glui32 seed)
{
if (seed == 0)
seed = GetTickCount() ^ time(NULL);
lo_seed_random(seed);
}
#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 <stdlib.h>
/* 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 <math.h>
#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 */