aboutsummaryrefslogtreecommitdiff
path: root/src/KINDLE/i_system.c
diff options
context:
space:
mode:
Diffstat (limited to 'src/KINDLE/i_system.c')
-rw-r--r--src/KINDLE/i_system.c460
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
68static unsigned int start_displaytime;
69static unsigned int displaytime;
70static boolean InDisplay = false;
71
72unsigned 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
79boolean I_StartDisplay(void)
80{
81 if (InDisplay)
82 return false;
83
84 start_displaytime = SDL_GetTicks();
85 InDisplay = true;
86 return true;
87}
88
89void I_EndDisplay(void)
90{
91 displaytime = SDL_GetTicks() - start_displaytime;
92 InDisplay = false;
93}
94
95void I_uSleep(unsigned long usecs)
96{
97 sleep(usecs/1000);
98}
99
100int ms_to_next_tick;
101
102int 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;
110struct timezone tz;
111unsigned long thistimereply;
112
113gettimeofday(&tv, &tz);
114
115//tv_sec is seconds tv_usec is microseconds
116thistimereply = (tv.tv_sec * TICRATE + (tv.tv_usec * TICRATE) /
1171000000);
118return thistimereply;
119}
120
121#ifndef PRBOOM_SERVER
122fixed_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
142void 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 */
158unsigned 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 */
167const 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 */
180const 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 */
202void 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
221int 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
234const 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
260const 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
272static const char prboom_dir[] = {"/.prboom"}; // Mead rem extra slash 8/21/03
273
274const 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
299boolean 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. */
320char* 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
379static 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
408void 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