diff options
Diffstat (limited to 'src/KINDLE/i_system.c')
-rw-r--r-- | src/KINDLE/i_system.c | 460 |
1 files changed, 460 insertions, 0 deletions
diff --git a/src/KINDLE/i_system.c b/src/KINDLE/i_system.c new file mode 100644 index 0000000..077e708 --- /dev/null +++ b/src/KINDLE/i_system.c | |||
@@ -0,0 +1,460 @@ | |||
1 | |||
2 | |||
3 | #include <stdio.h> | ||
4 | |||
5 | #include <stdarg.h> | ||
6 | #include <stdlib.h> | ||
7 | #include <ctype.h> | ||
8 | #include <signal.h> | ||
9 | #ifdef _MSC_VER | ||
10 | #define F_OK 0 /* Check for file existence */ | ||
11 | #define W_OK 2 /* Check for write permission */ | ||
12 | #define R_OK 4 /* Check for read permission */ | ||
13 | #include <io.h> | ||
14 | #include <direct.h> | ||
15 | #else | ||
16 | #include <unistd.h> | ||
17 | #include <time.h> | ||
18 | #include <sys/types.h> | ||
19 | #include <sys/stat.h> | ||
20 | #include <fcntl.h> | ||
21 | #include <sys/time.h> | ||
22 | #endif | ||
23 | #include <sys/stat.h> | ||
24 | |||
25 | #ifdef _WIN32 | ||
26 | #define WIN32_LEAN_AND_MEAN | ||
27 | #include <windows.h> | ||
28 | #endif | ||
29 | |||
30 | #ifdef HAVE_CONFIG_H | ||
31 | #include "config.h" | ||
32 | #endif | ||
33 | #ifdef HAVE_UNISTD_H | ||
34 | #include <unistd.h> | ||
35 | #endif | ||
36 | #ifdef HAVE_SCHED_H | ||
37 | #include <sched.h> | ||
38 | #endif | ||
39 | #ifdef _MSC_VER | ||
40 | #include <io.h> | ||
41 | #endif | ||
42 | #include <fcntl.h> | ||
43 | #include <sys/stat.h> | ||
44 | #include <errno.h> | ||
45 | |||
46 | #ifndef PRBOOM_SERVER | ||
47 | #include "m_argv.h" | ||
48 | #endif | ||
49 | #include "lprintf.h" | ||
50 | #include "doomtype.h" | ||
51 | #include "doomdef.h" | ||
52 | #include "lprintf.h" | ||
53 | #ifndef PRBOOM_SERVER | ||
54 | #include "m_fixed.h" | ||
55 | #include "r_fps.h" | ||
56 | #endif | ||
57 | #include "i_system.h" | ||
58 | |||
59 | #ifdef __GNUG__ | ||
60 | #pragma implementation "i_system.h" | ||
61 | #endif | ||
62 | #include "i_system.h" | ||
63 | |||
64 | #ifdef HAVE_CONFIG_H | ||
65 | #include "config.h" | ||
66 | #endif | ||
67 | |||
68 | static unsigned int start_displaytime; | ||
69 | static unsigned int displaytime; | ||
70 | static boolean InDisplay = false; | ||
71 | |||
72 | unsigned int SDL_GetTicks() { | ||
73 | struct timespec ts; | ||
74 | clock_gettime(CLOCK_REALTIME, &ts); | ||
75 | |||
76 | return ((unsigned int)ts.tv_sec*1000) + (ts.tv_nsec/1000); | ||
77 | } | ||
78 | |||
79 | boolean I_StartDisplay(void) | ||
80 | { | ||
81 | if (InDisplay) | ||
82 | return false; | ||
83 | |||
84 | start_displaytime = SDL_GetTicks(); | ||
85 | InDisplay = true; | ||
86 | return true; | ||
87 | } | ||
88 | |||
89 | void I_EndDisplay(void) | ||
90 | { | ||
91 | displaytime = SDL_GetTicks() - start_displaytime; | ||
92 | InDisplay = false; | ||
93 | } | ||
94 | |||
95 | void I_uSleep(unsigned long usecs) | ||
96 | { | ||
97 | sleep(usecs/1000); | ||
98 | } | ||
99 | |||
100 | int ms_to_next_tick; | ||
101 | |||
102 | int I_GetTime_RealTime (void) | ||
103 | { | ||
104 | /* int t = SDL_GetTicks(); | ||
105 | int i = t*(TICRATE/5)/200; | ||
106 | ms_to_next_tick = (i+1)*200/(TICRATE/5) - t; | ||
107 | if (ms_to_next_tick > 1000/TICRATE || ms_to_next_tick<1) ms_to_next_tick = 1; | ||
108 | return i;*/ | ||
109 | struct timeval tv; | ||
110 | struct timezone tz; | ||
111 | unsigned long thistimereply; | ||
112 | |||
113 | gettimeofday(&tv, &tz); | ||
114 | |||
115 | //tv_sec is seconds tv_usec is microseconds | ||
116 | thistimereply = (tv.tv_sec * TICRATE + (tv.tv_usec * TICRATE) / | ||
117 | 1000000); | ||
118 | return thistimereply; | ||
119 | } | ||
120 | |||
121 | #ifndef PRBOOM_SERVER | ||
122 | fixed_t I_GetTimeFrac (void) | ||
123 | { | ||
124 | unsigned long now; | ||
125 | fixed_t frac; | ||
126 | |||
127 | now = SDL_GetTicks(); | ||
128 | |||
129 | if (tic_vars.step == 0) | ||
130 | return FRACUNIT; | ||
131 | else | ||
132 | { | ||
133 | frac = (fixed_t)((now - tic_vars.start + displaytime) * FRACUNIT / tic_vars.step); | ||
134 | if (frac < 0) | ||
135 | frac = 0; | ||
136 | if (frac > FRACUNIT) | ||
137 | frac = FRACUNIT; | ||
138 | return frac; | ||
139 | } | ||
140 | } | ||
141 | |||
142 | void I_GetTime_SaveMS(void) | ||
143 | { | ||
144 | if (!movement_smooth) | ||
145 | return; | ||
146 | |||
147 | tic_vars.start = SDL_GetTicks(); | ||
148 | tic_vars.next = (unsigned int) ((tic_vars.start * tic_vars.msec + 1.0f) / tic_vars.msec); | ||
149 | tic_vars.step = tic_vars.next - tic_vars.start; | ||
150 | } | ||
151 | #endif | ||
152 | |||
153 | /* | ||
154 | * I_GetRandomTimeSeed | ||
155 | * | ||
156 | * CPhipps - extracted from G_ReloadDefaults because it is O/S based | ||
157 | */ | ||
158 | unsigned long I_GetRandomTimeSeed(void) | ||
159 | { | ||
160 | /* This isnt very random */ | ||
161 | return(SDL_GetTicks()); | ||
162 | } | ||
163 | |||
164 | /* cphipps - I_GetVersionString | ||
165 | * Returns a version string in the given buffer | ||
166 | */ | ||
167 | const char* I_GetVersionString(char* buf, size_t sz) | ||
168 | { | ||
169 | #ifdef HAVE_SNPRINTF | ||
170 | snprintf(buf,sz,"%s v%s (http://prboom.sourceforge.net/)",PACKAGE,VERSION); | ||
171 | #else | ||
172 | sprintf(buf,"%s v%s (http://prboom.sourceforge.net/)",PACKAGE,VERSION); | ||
173 | #endif | ||
174 | return buf; | ||
175 | } | ||
176 | |||
177 | /* cphipps - I_SigString | ||
178 | * Returns a string describing a signal number | ||
179 | */ | ||
180 | const char* I_SigString(char* buf, size_t sz, int signum) | ||
181 | { | ||
182 | #ifdef SYS_SIGLIST_DECLARED | ||
183 | if (strlen(sys_siglist[signum]) < sz) | ||
184 | strcpy(buf,sys_siglist[signum]); | ||
185 | else | ||
186 | #endif | ||
187 | #ifdef HAVE_SNPRINTF | ||
188 | snprintf(buf,sz,"signal %d",signum); | ||
189 | #else | ||
190 | sprintf(buf,"signal %d",signum); | ||
191 | #endif | ||
192 | return buf; | ||
193 | } | ||
194 | |||
195 | |||
196 | /* | ||
197 | * I_Read | ||
198 | * | ||
199 | * cph 2001/11/18 - wrapper for read(2) which handles partial reads and aborts | ||
200 | * on error. | ||
201 | */ | ||
202 | void I_Read(int fd, void* vbuf, size_t sz) | ||
203 | { | ||
204 | unsigned char* buf = vbuf; | ||
205 | |||
206 | while (sz) { | ||
207 | int rc = read(fd,buf,sz); | ||
208 | if (rc <= 0) { | ||
209 | I_Error("I_Read: read failed: %s", rc ? strerror(errno) : "EOF"); | ||
210 | } | ||
211 | sz -= rc; buf += rc; | ||
212 | } | ||
213 | } | ||
214 | |||
215 | /* | ||
216 | * I_Filelength | ||
217 | * | ||
218 | * Return length of an open file. | ||
219 | */ | ||
220 | |||
221 | int I_Filelength(int handle) | ||
222 | { | ||
223 | struct stat fileinfo; | ||
224 | if (fstat(handle,&fileinfo) == -1) | ||
225 | I_Error("I_Filelength: %s",strerror(errno)); | ||
226 | return fileinfo.st_size; | ||
227 | } | ||
228 | |||
229 | #ifndef PRBOOM_SERVER | ||
230 | |||
231 | // Return the path where the executable lies -- Lee Killough | ||
232 | // proff_fs 2002-07-04 - moved to i_system | ||
233 | #ifdef _WIN32 | ||
234 | const char *I_DoomExeDir(void) | ||
235 | { | ||
236 | static const char current_dir_dummy[] = {"."}; // proff - rem extra slash 8/21/03 | ||
237 | static char *base; | ||
238 | if (!base) // cache multiple requests | ||
239 | { | ||
240 | size_t len = strlen(*myargv); | ||
241 | char *p = (base = malloc(len+1)) + len - 1; | ||
242 | strcpy(base,*myargv); | ||
243 | while (p > base && *p!='/' && *p!='\\') | ||
244 | *p--=0; | ||
245 | if (*p=='/' || *p=='\\') | ||
246 | *p--=0; | ||
247 | if (strlen(base)<2) | ||
248 | { | ||
249 | free(base); | ||
250 | base = malloc(1024); | ||
251 | if (!getcwd(base,1024)) | ||
252 | strcpy(base, current_dir_dummy); | ||
253 | } | ||
254 | } | ||
255 | return base; | ||
256 | } | ||
257 | |||
258 | #elif defined(AMIGA) | ||
259 | |||
260 | const char *I_DoomExeDir(void) | ||
261 | { | ||
262 | return "PROGDIR:"; | ||
263 | } | ||
264 | |||
265 | #elif defined(MACOSX) | ||
266 | |||
267 | /* Defined elsewhere */ | ||
268 | |||
269 | #else | ||
270 | // cph - V.Aguilar (5/30/99) suggested return ~/.lxdoom/, creating | ||
271 | // if non-existant | ||
272 | static const char prboom_dir[] = {"/.prboom"}; // Mead rem extra slash 8/21/03 | ||
273 | |||
274 | const char *I_DoomExeDir(void) | ||
275 | { | ||
276 | static char *base; | ||
277 | if (!base) // cache multiple requests | ||
278 | { | ||
279 | char *home = getenv("HOME"); | ||
280 | size_t len = strlen(home); | ||
281 | |||
282 | base = malloc(len + strlen(prboom_dir) + 1); | ||
283 | strcpy(base, home); | ||
284 | // I've had trouble with trailing slashes before... | ||
285 | if (base[len-1] == '/') base[len-1] = 0; | ||
286 | strcat(base, prboom_dir); | ||
287 | mkdir(base, S_IRUSR | S_IWUSR | S_IXUSR); // Make sure it exists | ||
288 | } | ||
289 | return base; | ||
290 | } | ||
291 | #endif | ||
292 | |||
293 | /* | ||
294 | * HasTrailingSlash | ||
295 | * | ||
296 | * cphipps - simple test for trailing slash on dir names | ||
297 | */ | ||
298 | |||
299 | boolean HasTrailingSlash(const char* dn) | ||
300 | { | ||
301 | return ( (dn[strlen(dn)-1] == '/') | ||
302 | #if defined(AMIGA) | ||
303 | || (dn[strlen(dn)-1] == ':') | ||
304 | #endif | ||
305 | ); | ||
306 | } | ||
307 | |||
308 | /* | ||
309 | * I_FindFile | ||
310 | * | ||
311 | * proff_fs 2002-07-04 - moved to i_system | ||
312 | * | ||
313 | * cphipps 19/1999 - writen to unify the logic in FindIWADFile and the WAD | ||
314 | * autoloading code. | ||
315 | * Searches the standard dirs for a named WAD file | ||
316 | * The dirs are listed at the start of the function | ||
317 | */ | ||
318 | |||
319 | #ifndef MACOSX /* OSX defines its search paths elsewhere. */ | ||
320 | char* I_FindFile(const char* wfname, const char* ext) | ||
321 | { | ||
322 | // lookup table of directories to search | ||
323 | static const struct { | ||
324 | const char *dir; // directory | ||
325 | const char *sub; // subdirectory | ||
326 | const char *env; // environment variable | ||
327 | const char *(*func)(void); // for I_DoomExeDir | ||
328 | } search[] = { | ||
329 | {NULL}, // current working directory | ||
330 | {NULL, NULL, "DOOMWADDIR"}, // run-time $DOOMWADDIR | ||
331 | {DOOMWADDIR}, // build-time configured DOOMWADDIR | ||
332 | {NULL, "doom", "HOME"}, // ~/doom | ||
333 | {NULL, NULL, "HOME"}, // ~ | ||
334 | {NULL, NULL, NULL, I_DoomExeDir}, // config directory | ||
335 | {"/usr/local/share/games/doom"}, | ||
336 | {"/usr/share/games/doom"}, | ||
337 | {"/usr/local/share/doom"}, | ||
338 | {"/usr/share/doom"}, | ||
339 | }; | ||
340 | |||
341 | int i; | ||
342 | /* Precalculate a length we will need in the loop */ | ||
343 | size_t pl = strlen(wfname) + strlen(ext) + 4; | ||
344 | |||
345 | for (i = 0; i < sizeof(search)/sizeof(*search); i++) { | ||
346 | char * p; | ||
347 | const char * d = NULL; | ||
348 | const char * s = NULL; | ||
349 | /* Each entry in the switch sets d to the directory to look in, | ||
350 | * and optionally s to a subdirectory of d */ | ||
351 | // switch replaced with lookup table | ||
352 | if (search[i].env) { | ||
353 | if (!(d = getenv(search[i].env))) | ||
354 | continue; | ||
355 | } else if (search[i].func) | ||
356 | d = search[i].func(); | ||
357 | else | ||
358 | d = search[i].dir; | ||
359 | s = search[i].sub; | ||
360 | |||
361 | p = malloc((d ? strlen(d) : 0) + (s ? strlen(s) : 0) + pl); | ||
362 | sprintf(p, "%s%s%s%s%s", d ? d : "", (d && !HasTrailingSlash(d)) ? "/" : "", | ||
363 | s ? s : "", (s && !HasTrailingSlash(s)) ? "/" : "", | ||
364 | wfname); | ||
365 | |||
366 | if (access(p,F_OK)) | ||
367 | strcat(p, ext); | ||
368 | if (!access(p,F_OK)) { | ||
369 | lprintf(LO_INFO, " found %s\n", p); | ||
370 | return p; | ||
371 | } | ||
372 | free(p); | ||
373 | } | ||
374 | return NULL; | ||
375 | } | ||
376 | #endif | ||
377 | |||
378 | #ifdef _WIN32 | ||
379 | static char* WINError(void) | ||
380 | { | ||
381 | static char *WinEBuff = NULL; | ||
382 | DWORD err = GetLastError(); | ||
383 | char *ch; | ||
384 | |||
385 | if (WinEBuff) | ||
386 | { | ||
387 | LocalFree(WinEBuff); | ||
388 | } | ||
389 | |||
390 | if (FormatMessage(FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM, | ||
391 | NULL, err, MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), | ||
392 | (LPTSTR) &WinEBuff, 0, NULL) == 0) | ||
393 | { | ||
394 | return "Unknown error"; | ||
395 | } | ||
396 | |||
397 | if ((ch = strchr(WinEBuff, '\n')) != 0) | ||
398 | *ch = 0; | ||
399 | if ((ch = strchr(WinEBuff, '\r')) != 0) | ||
400 | *ch = 0; | ||
401 | |||
402 | return WinEBuff; | ||
403 | } | ||
404 | #endif | ||
405 | |||
406 | #define DEFAULT_AFFINITY_MASK 1 | ||
407 | |||
408 | void I_SetAffinityMask(void) | ||
409 | { | ||
410 | unsigned int process_affinity_mask = DEFAULT_AFFINITY_MASK; | ||
411 | int p = M_CheckParm("-affinity"); | ||
412 | |||
413 | if (p && p < myargc-1) | ||
414 | process_affinity_mask = atoi(myargv[p+1]); | ||
415 | |||
416 | // Set the process affinity mask so that all threads | ||
417 | // run on the same processor. This is a workaround for a bug in | ||
418 | // SDL_mixer that causes occasional crashes. | ||
419 | if (process_affinity_mask) | ||
420 | { | ||
421 | const char *errbuf = NULL; | ||
422 | #ifdef _WIN32 | ||
423 | if (!SetProcessAffinityMask(GetCurrentProcess(), process_affinity_mask)) | ||
424 | { | ||
425 | errbuf = WINError(); | ||
426 | } | ||
427 | #elif defined(HAVE_SCHED_SETAFFINITY) | ||
428 | // POSIX version: | ||
429 | int i; | ||
430 | { | ||
431 | cpu_set_t set; | ||
432 | |||
433 | CPU_ZERO(&set); | ||
434 | |||
435 | for(i = 0; i < 16; i++) | ||
436 | { | ||
437 | CPU_SET((process_affinity_mask>>i)&1, &set); | ||
438 | } | ||
439 | |||
440 | if (sched_setaffinity(getpid(), sizeof(set), &set) == -1) | ||
441 | { | ||
442 | errbuf = strerror(errno); | ||
443 | } | ||
444 | } | ||
445 | #else | ||
446 | return; | ||
447 | #endif | ||
448 | |||
449 | if (errbuf == NULL) | ||
450 | { | ||
451 | lprintf(LO_INFO, "I_SetAffinityMask: manual affinity mask is %d\n", process_affinity_mask); | ||
452 | } | ||
453 | else | ||
454 | { | ||
455 | lprintf(LO_ERROR, "I_SetAffinityMask: failed to set process affinity mask (%s)\n", errbuf); | ||
456 | } | ||
457 | } | ||
458 | } | ||
459 | |||
460 | #endif // PRBOOM_SERVER | ||