1 /*
2 * This program is free software; you can redistribute it and/or modify
3 * it under the terms of the GNU General Public License as published by
4 * the Free Software Foundation; either version 2 of the License, or
5 * (at your option) any later version.
6 *
7 * This program is distributed in the hope that it will be useful,
8 * but WITHOUT ANY WARRANTY; without even the implied warranty of
9 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
10 * GNU Library General Public License for more details.
11 *
12 * You should have received a copy of the GNU General Public License
13 * along with this program; if not, write to the Free Software
14 * Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
15 */
16
17 #include <stdio.h>
18 #include <string.h>
19 #include <stdarg.h>
20 #include <ctype.h>
21
22 #if defined(HAVE_LIMITS_H)
23 #include <limits.h>
24 #else
25 #define PATH_MAX 255
26 #define MAX_INPUT 255
27 #endif
28
29 #if defined(LINUX) || defined(SOLARIS)
30
31 #include <sys/time.h>
32 #include <stdlib.h>
33
34 #elif defined(WIN32)
35
36 #include <windows.h>
37
38 #endif
39
40 #include "utils.h"
41 #include <sys/types.h>
42 #include <sys/stat.h>
43 #include <unistd.h>
44 #include <dirent.h>
45 #include <errno.h>
46
47 /******************************************************************************
48 * Log stuff
49 *****************************************************************************/
50
51 char log_filename[PATH_MAX];
52 // real filename of the logging file
53 // it thus also includes full path on advanced system
54
55 void
Log(char * format,...)56 Log (char *format, ...)
57 {
58 FILE *log_file;
59 char buf[256];
60
61 va_list ap;
62 va_start (ap, format);
63 vsprintf (buf, format, ap);
64 va_end (ap);
65
66 if (!(log_file = fopen (log_filename, "at")))
67 return;
68
69 fprintf (log_file, buf);
70 fflush (log_file);
71 fclose (log_file);
72 }
73
74
75 #ifdef GTK
gtk_menu_ensure_uline_accel_group()76 void gtk_menu_ensure_uline_accel_group ()
77 {
78 }
79 #endif
80
81
82 #ifndef BENCHMARK
osd_getTime(void)83 static double osd_getTime(void)
84 {
85 #ifdef WIN32
86 return (SDL_GetTicks() * 1e-3);
87 #elif defined(DJGPP)
88 return uclock() * (1.0 / UCLOCKS_PER_SEC);
89 #else
90 struct timeval tp;
91
92 gettimeofday(&tp, NULL);
93 // printf("current microsec = %f\n",tp.tv_sec + 1e-6 * tp.tv_usec);
94 return tp.tv_sec + 1e-6 * tp.tv_usec;
95 #endif
96 }
97 #endif /* !BENCHMARK */
98
99 #ifndef BENCHMARK
osd_sleep(double s)100 static void osd_sleep(double s)
101 {
102 // emu_too_fast = 0;
103 // printf("Sleeping %d micro seconds\n", s);
104 // Log("Sleeping %f seconds\n", s);
105 if (s > 0)
106 {
107 #ifdef linux
108 struct timeval tp;
109
110 tp.tv_sec = 0;
111 tp.tv_usec = 1e6 * s;
112 select(1,NULL,NULL,NULL,&tp);
113 #elif defined(WIN32)
114 SDL_Delay((unsigned int)(s * 1e3));
115 #elif defined(DJGPP)
116 double curtime = osd_time();
117 while ((curtime + s) > osd_time());
118 #else
119 usleep(s * 1e6);
120 #endif
121 // emu_too_fast = 1;
122 }
123 }
124 #endif /* !BENCHMARK */
125
126
127 void
wait_next_vsync()128 wait_next_vsync()
129 {
130 #ifndef BENCHMARK
131 static double lasttime = 0, lastcurtime = 0, frametime = 0.1;
132 double curtime;
133 const double deltatime = (1.0 / 60.0);
134
135 curtime = osd_getTime();
136
137 osd_sleep(lasttime + deltatime - curtime);
138 curtime = osd_getTime();
139
140 lastcurtime = curtime;
141
142 lasttime += deltatime;
143
144 if ((lasttime + deltatime) < curtime)
145 lasttime = curtime;
146 #endif
147 }
148
149 #if defined(WIN32)
150
151 static char memory_name[50];
152
shmget(key_t identifier,int size,int flags)153 int shmget (key_t identifier, int size, int flags)
154 {
155 int handle;
156
157 snprintf(memory_name, sizeof(memory_name), "%05d hugo shared mem", identifier);
158
159 handle=CreateFileMapping(
160 (HANDLE)0xFFFFFFFF, // Not mapped to any actual file
161 NULL,
162 PAGE_READWRITE, // Read write mode
163 0,
164 size, // Buffer size
165 memory_name // Shared memory name
166 );
167
168 if (handle == 0)
169 {
170 Log("Couldn't get shared memory\n");
171 return -1;
172 }
173
174 return handle;
175 }
176
shmat(int handle,int dummy1,int dummy2)177 char* shmat (int handle, int dummy1, int dummy2)
178 {
179 char* result;
180
181 result = (char*) MapViewOfFile((HANDLE)handle,FILE_MAP_WRITE,0,0,10);
182
183 if (result == NULL)
184 {
185 Log("Couldn't attach shared memory\n");
186 }
187
188 return result;
189 }
190
shmctl(int handle,int dummy,int flags)191 int shmctl(int handle, int dummy, int flags)
192 {
193 UnmapViewOfFile((HANDLE)handle);
194 return 0;
195 }
196
197
198 #endif /* WIN32 */
199
200 unsigned long TAB_CONST[256] = {
201 0X0,
202 0X77073096,
203 0XEE0E612C,
204 0X990951BA,
205 0X76DC419,
206 0X706AF48F,
207 0XE963A535,
208 0X9E6495A3,
209 0XEDB8832,
210 0X79DCB8A4,
211 0XE0D5E91E,
212 0X97D2D988,
213 0X9B64C2B,
214 0X7EB17CBD,
215 0XE7B82D07,
216 0X90BF1D91,
217 0X1DB71064,
218 0X6AB020F2,
219 0XF3B97148,
220 0X84BE41DE,
221 0X1ADAD47D,
222 0X6DDDE4EB,
223 0XF4D4B551,
224 0X83D385C7,
225 0X136C9856,
226 0X646BA8C0,
227 0XFD62F97A,
228 0X8A65C9EC,
229 0X14015C4F,
230 0X63066CD9,
231 0XFA0F3D63,
232 0X8D080DF5,
233 0X3B6E20C8,
234 0X4C69105E,
235 0XD56041E4,
236 0XA2677172,
237 0X3C03E4D1,
238 0X4B04D447,
239 0XD20D85FD,
240 0XA50AB56B,
241 0X35B5A8FA,
242 0X42B2986C,
243 0XDBBBC9D6,
244 0XACBCF940,
245 0X32D86CE3,
246 0X45DF5C75,
247 0XDCD60DCF,
248 0XABD13D59,
249 0X26D930AC,
250 0X51DE003A,
251 0XC8D75180,
252 0XBFD06116,
253 0X21B4F4B5,
254 0X56B3C423,
255 0XCFBA9599,
256 0XB8BDA50F,
257 0X2802B89E,
258 0X5F058808,
259 0XC60CD9B2,
260 0XB10BE924,
261 0X2F6F7C87,
262 0X58684C11,
263 0XC1611DAB,
264 0XB6662D3D,
265 0X76DC4190,
266 0X1DB7106,
267 0X98D220BC,
268 0XEFD5102A,
269 0X71B18589,
270 0X6B6B51F,
271 0X9FBFE4A5,
272 0XE8B8D433,
273 0X7807C9A2,
274 0XF00F934,
275 0X9609A88E,
276 0XE10E9818,
277 0X7F6A0DBB,
278 0X86D3D2D,
279 0X91646C97,
280 0XE6635C01,
281 0X6B6B51F4,
282 0X1C6C6162,
283 0X856530D8,
284 0XF262004E,
285 0X6C0695ED,
286 0X1B01A57B,
287 0X8208F4C1,
288 0XF50FC457,
289 0X65B0D9C6,
290 0X12B7E950,
291 0X8BBEB8EA,
292 0XFCB9887C,
293 0X62DD1DDF,
294 0X15DA2D49,
295 0X8CD37CF3,
296 0XFBD44C65,
297 0X4DB26158,
298 0X3AB551CE,
299 0XA3BC0074,
300 0XD4BB30E2,
301 0X4ADFA541,
302 0X3DD895D7,
303 0XA4D1C46D,
304 0XD3D6F4FB,
305 0X4369E96A,
306 0X346ED9FC,
307 0XAD678846,
308 0XDA60B8D0,
309 0X44042D73,
310 0X33031DE5,
311 0XAA0A4C5F,
312 0XDD0D7CC9,
313 0X5005713C,
314 0X270241AA,
315 0XBE0B1010,
316 0XC90C2086,
317 0X5768B525,
318 0X206F85B3,
319 0XB966D409,
320 0XCE61E49F,
321 0X5EDEF90E,
322 0X29D9C998,
323 0XB0D09822,
324 0XC7D7A8B4,
325 0X59B33D17,
326 0X2EB40D81,
327 0XB7BD5C3B,
328 0XC0BA6CAD,
329 0XEDB88320,
330 0X9ABFB3B6,
331 0X3B6E20C,
332 0X74B1D29A,
333 0XEAD54739,
334 0X9DD277AF,
335 0X4DB2615,
336 0X73DC1683,
337 0XE3630B12,
338 0X94643B84,
339 0XD6D6A3E,
340 0X7A6A5AA8,
341 0XE40ECF0B,
342 0X9309FF9D,
343 0XA00AE27,
344 0X7D079EB1,
345 0XF00F9344,
346 0X8708A3D2,
347 0X1E01F268,
348 0X6906C2FE,
349 0XF762575D,
350 0X806567CB,
351 0X196C3671,
352 0X6E6B06E7,
353 0XFED41B76,
354 0X89D32BE0,
355 0X10DA7A5A,
356 0X67DD4ACC,
357 0XF9B9DF6F,
358 0X8EBEEFF9,
359 0X17B7BE43,
360 0X60B08ED5,
361 0XD6D6A3E8,
362 0XA1D1937E,
363 0X38D8C2C4,
364 0X4FDFF252,
365 0XD1BB67F1,
366 0XA6BC5767,
367 0X3FB506DD,
368 0X48B2364B,
369 0XD80D2BDA,
370 0XAF0A1B4C,
371 0X36034AF6,
372 0X41047A60,
373 0XDF60EFC3,
374 0XA867DF55,
375 0X316E8EEF,
376 0X4669BE79,
377 0XCB61B38C,
378 0XBC66831A,
379 0X256FD2A0,
380 0X5268E236,
381 0XCC0C7795,
382 0XBB0B4703,
383 0X220216B9,
384 0X5505262F,
385 0XC5BA3BBE,
386 0XB2BD0B28,
387 0X2BB45A92,
388 0X5CB36A04,
389 0XC2D7FFA7,
390 0XB5D0CF31,
391 0X2CD99E8B,
392 0X5BDEAE1D,
393 0X9B64C2B0,
394 0XEC63F226,
395 0X756AA39C,
396 0X26D930A,
397 0X9C0906A9,
398 0XEB0E363F,
399 0X72076785,
400 0X5005713,
401 0X95BF4A82,
402 0XE2B87A14,
403 0X7BB12BAE,
404 0XCB61B38,
405 0X92D28E9B,
406 0XE5D5BE0D,
407 0X7CDCEFB7,
408 0XBDBDF21,
409 0X86D3D2D4,
410 0XF1D4E242,
411 0X68DDB3F8,
412 0X1FDA836E,
413 0X81BE16CD,
414 0XF6B9265B,
415 0X6FB077E1,
416 0X18B74777,
417 0X88085AE6,
418 0XFF0F6A70,
419 0X66063BCA,
420 0X11010B5C,
421 0X8F659EFF,
422 0XF862AE69,
423 0X616BFFD3,
424 0X166CCF45,
425 0XA00AE278,
426 0XD70DD2EE,
427 0X4E048354,
428 0X3903B3C2,
429 0XA7672661,
430 0XD06016F7,
431 0X4969474D,
432 0X3E6E77DB,
433 0XAED16A4A,
434 0XD9D65ADC,
435 0X40DF0B66,
436 0X37D83BF0,
437 0XA9BCAE53,
438 0XDEBB9EC5,
439 0X47B2CF7F,
440 0X30B5FFE9,
441 0XBDBDF21C,
442 0XCABAC28A,
443 0X53B39330,
444 0X24B4A3A6,
445 0XBAD03605,
446 0XCDD70693,
447 0X54DE5729,
448 0X23D967BF,
449 0XB3667A2E,
450 0XC4614AB8,
451 0X5D681B02,
452 0X2A6F2B94,
453 0XB40BBE37,
454 0XC30C8EA1,
455 0X5A05DF1B,
456 0X2D02EF8D
457 };
458
459 #if defined(SOLARIS)
htons(u_short arg)460 u_short htons(u_short arg)
461 {
462 return (arg >> 8) | ((arg & 0xFF) << 8);
463 }
464 #endif
465
patch_rom(char * filename,int offset,UChar value)466 void patch_rom(char* filename, int offset, UChar value)
467 {
468 FILE* f;
469
470 f = fopen(filename, "rb+");
471
472 if (f == NULL)
473 {
474 Log("Error patching %s (%d,%d)\n", filename, offset, value);
475 return;
476 }
477
478 fseek(f, offset, SEEK_SET);
479
480 fputc(value, f);
481
482 fclose(f);
483 }
484
485 char *
strupr(char * s)486 strupr(char *s)
487 {
488 char *t = s;
489 while (*s)
490 {
491 *s = toupper(*s);
492 s++;
493 }
494 return t;
495 }
496
497 #if !defined(FREEBSD)
498 char *
strcasestr(const char * s1,const char * s2)499 strcasestr (const char *s1, const char *s2)
500 {
501 char *tmps1 = (char *) strupr (strdup (s1));
502 char *tmps2 = (char *) strupr (strdup (s2));
503
504 char *result = strstr (tmps1, tmps2);
505
506 free (tmps1);
507 free (tmps2);
508
509 return result;
510 }
511 #endif
512
513 #if !defined(WIN32)
514
515 int
stricmp(char * s1,char * s2)516 stricmp (char *s1, char *s2)
517 {
518 char *tmps1 = (char *) strupr (strdup (s1));
519 char *tmps2 = (char *) strupr (strdup (s2));
520
521 int result = strcmp (tmps1, tmps2);
522
523 free (tmps1);
524 free (tmps2);
525
526 return result;
527 }
528 #endif
529
530 void
get_directory_from_filename(char * filename)531 get_directory_from_filename(char* filename)
532 {
533 struct stat file_stat;
534 #if defined(UNIX)
535 lstat(filename, &file_stat);
536 #else
537 stat(filename, &file_stat);
538 #endif
539
540 if (S_ISDIR(file_stat.st_mode))
541 {
542 if ('/' != filename[strlen(filename) - 1])
543 { // It is a directory but not finished by a slash
544 strcat(filename, "/");
545 }
546 return;
547 }
548
549 // It is a file, we'll remove the basename part from it
550 // It there's a slash, we put the end of string marker just after the last one
551 if (strrchr(filename, '/') != NULL)
552 {
553 strrchr(filename, '/')[1] = 0;
554 }
555
556 }
557
558 /*!
559 * wipe_directory : suppress a directory, eventually containing files (but not other directories)
560 * @param directory_name Name of the directory to suppress
561 */
562 void
wipe_directory(char * directory_name)563 wipe_directory(char* directory_name)
564 {
565 DIR* directory;
566 struct dirent* directory_entry;
567
568 directory = opendir(directory_name);
569
570 if (NULL == directory)
571 {
572 Log("wipe_directory failed : %s\n", strerror(errno));
573 return;
574 }
575
576 while (directory_entry = readdir(directory))
577 {
578 unlink(directory_entry->d_name);
579 }
580
581 closedir(directory);
582
583 }
584
585 /*!
586 * file_exists : Check whether a file exists. If doesn't involve much checking (like read/write access,
587 * whether it is a symbolic link or a directory, ...)
588 * @param name_to_check Name of the file to check for existence
589 * @return 0 if the file doesn't exist, else non null value
590 */
591 int
file_exists(char * name_to_check)592 file_exists(char* name_to_check)
593 {
594 struct stat stat_buffer;
595 return !stat(name_to_check, &stat_buffer);
596 }
597