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