1 #include <stdint.h>
2 #include <sys/stat.h>
3 #include <unistd.h>
4
5 #include "driver.h"
6 #include "unzip.h"
7 #include "../zlib/zlib.h"
8 #include "shared.h"
9 #include <file/file_path.h>
10
11 /* Verbose outputs to error.log ? */
12 #define VERBOSE 0
13
14 /* Use the file cache ? */
15 #define FILE_CACHE 1
16
17 #if VERBOSE
18 #define LOG(x) logerror x
19 #else
20 #define LOG(x) /* x */
21 #endif
22
23 char *roms = NULL;
24 char **rompathv = NULL;
25 int rompathc = 0;
26
27 char *samples = NULL;
28 char **samplepathv = NULL;
29 int samplepathc = 0;
30
31 char *cfgdir, *nvdir, *hidir, *inpdir, *stadir;
32 char *memcarddir, *artworkdir, *screenshotdir;
33 char *cheatdir; /* Steph */
34
35 char *alternate_name; /* for "-romdir" */
36
37 typedef enum
38 {
39 kPlainFile,
40 kRAMFile,
41 kZippedFile
42 } eFileType;
43
44 typedef struct
45 {
46 FILE *file;
47 unsigned char *data;
48 unsigned int offset;
49 unsigned int length;
50 eFileType type;
51 unsigned int crc;
52 } FakeFileHandle;
53
54 //extern unsigned int crc32 (unsigned int crc, const unsigned char *buf, unsigned int len);
55 static int checksum_file (const char *file, unsigned char **p, unsigned int *size, unsigned int *crc);
56
57 /*
58 * File stat cache LRU (Last Recently Used)
59 */
60
61 #if FILE_CACHE
62 struct file_cache_entry
63 {
64 struct stat stat_buffer;
65 int result;
66 char *file;
67 };
68
69 /* File cache buffer */
70 static struct file_cache_entry **file_cache_map = 0;
71
72 /* File cache size */
73 static unsigned int file_cache_max = 0;
74
75 /* AM 980919 */
cache_stat(const char * path,struct stat * statbuf)76 static int cache_stat (const char *path, struct stat *statbuf)
77 {
78 if( file_cache_max )
79 {
80 unsigned i;
81 struct file_cache_entry *entry;
82
83 /* search in the cache */
84 for( i = 0; i < file_cache_max; ++i )
85 {
86 if( file_cache_map[i]->file && strcmp (file_cache_map[i]->file, path) == 0 )
87 {
88 unsigned j;
89
90 #if 0
91 /* found */
92 /* LOG(("File cache HIT for %s\n", path)); */
93 /* store */
94 #endif
95 entry = file_cache_map[i];
96
97 /* shift */
98 for( j = i; j > 0; --j )
99 file_cache_map[j] = file_cache_map[j - 1];
100
101 /* set the first entry */
102 file_cache_map[0] = entry;
103
104 if( entry->result == 0 )
105 memcpy (statbuf, &entry->stat_buffer, sizeof (struct stat));
106
107 return entry->result;
108 }
109 }
110
111 #if 0
112 LOG(("File cache FAIL for %s\n", path));
113 #endif
114
115 /* oldest entry */
116 entry = file_cache_map[file_cache_max - 1];
117 free(entry->file);
118
119 /* shift */
120 for( i = file_cache_max - 1; i > 0; --i )
121 file_cache_map[i] = file_cache_map[i - 1];
122
123 /* set the first entry */
124 file_cache_map[0] = entry;
125
126 /* file */
127 entry->file = (char *) malloc(strlen (path) + 1);
128 strcpy (entry->file, path);
129
130 /* result and stat */
131 entry->result = stat (path, &entry->stat_buffer);
132
133 if( entry->result == 0 )
134 memcpy (statbuf, &entry->stat_buffer, sizeof (struct stat));
135
136 return entry->result;
137 }
138
139 return stat (path, statbuf);
140 }
141
142 /* AM 980919 */
cache_allocate(unsigned entries)143 static void cache_allocate (unsigned entries)
144 {
145 if( entries )
146 {
147 unsigned i;
148
149 file_cache_max = entries;
150 file_cache_map = (struct file_cache_entry **) malloc(file_cache_max * sizeof (struct file_cache_entry *));
151
152 for( i = 0; i < file_cache_max; ++i )
153 {
154 file_cache_map[i] = (struct file_cache_entry *) malloc(sizeof (struct file_cache_entry));
155 memset (file_cache_map[i], 0, sizeof (struct file_cache_entry));
156 }
157 LOG(("File cache allocated for %d entries\n", file_cache_max));
158 }
159 }
160 #else
161
162 #define cache_stat(a,b) stat(a,b)
163
164 #endif
165
166 /* This function can be called several times with different parameters,
167 * for example by "mame -verifyroms *". */
decompose_rom_sample_path(char * rompath,char * samplepath)168 void decompose_rom_sample_path (char *rompath, char *samplepath)
169 {
170 char *token;
171
172 /* start with zero path components */
173 rompathc = samplepathc = 0;
174
175 if (!roms)
176 roms = (char*)malloc( strlen(rompath) + 1);
177 else
178 roms = (char*)realloc( roms, strlen(rompath) + 1);
179
180 if (!samples)
181 samples = (char*)malloc( strlen(samplepath) + 1);
182 else
183 samples = (char*)realloc( samples, strlen(samplepath) + 1);
184
185 if( !roms || !samples )
186 {
187 logerror("decompose_rom_sample_path: failed to malloc!\n");
188 #ifdef HAVE_SIGNALS
189 raise(SIGABRT);
190 #endif
191 }
192
193 strcpy (roms, rompath);
194 token = strtok (roms, ";");
195 while( token )
196 {
197 if( rompathc )
198 rompathv = (char**)realloc(rompathv, (rompathc + 1) * sizeof(char *));
199 else
200 rompathv = (char**)malloc(sizeof(char *));
201 if( !rompathv )
202 break;
203 rompathv[rompathc++] = token;
204 token = strtok (NULL, ";");
205 }
206
207 strcpy (samples, samplepath);
208 token = strtok (samples, ";");
209 while( token )
210 {
211 if( samplepathc )
212 samplepathv = (char**)realloc(samplepathv, (samplepathc + 1) * sizeof(char *));
213 else
214 samplepathv = (char**)malloc(sizeof(char *));
215 if( !samplepathv )
216 break;
217 samplepathv[samplepathc++] = token;
218 token = strtok (NULL, ";");
219 }
220
221 #if FILE_CACHE
222 /* AM 980919 */
223 if( file_cache_max == 0 )
224 {
225 /* (rom path directories + 1 buffer)==rompathc+1 */
226 /* (dir + .zip + .zif)==3 */
227 /* (clone+parent)==2 */
228 cache_allocate ((rompathc + 1) * 3 * 2);
229 }
230 #endif
231
232 }
233
234 /*
235 * file handling routines
236 *
237 * gamename holds the driver name, filename is only used for ROMs and samples.
238 * if 'write' is not 0, the file is opened for write. Otherwise it is opened
239 * for read.
240 */
241
242 /*
243 * check if roms/samples for a game exist at all
244 * return index+1 of the path vector component on success, otherwise 0
245 */
osd_faccess(const char * newfilename,int filetype)246 int osd_faccess (const char *newfilename, int filetype)
247 {
248 static int indx;
249 static const char *filename;
250 char name[256];
251 char **pathv;
252 int pathc;
253 char *dir_name;
254
255 /* if filename == NULL, continue the search */
256 if( newfilename != NULL )
257 {
258 indx = 0;
259 filename = newfilename;
260 }
261 else
262 indx++;
263
264 #ifdef MESS
265 if(
266 filetype == OSD_FILETYPE_ROM ||
267 filetype == OSD_FILETYPE_IMAGE_R ||
268 filetype == OSD_FILETYPE_IMAGE_RW )
269 #else
270 if( filetype == OSD_FILETYPE_ROM )
271 #endif
272 {
273 pathv = rompathv;
274 pathc = rompathc;
275 }
276 else
277 if( filetype == OSD_FILETYPE_SAMPLE )
278 {
279 pathv = samplepathv;
280 pathc = samplepathc;
281 }
282 else
283 if( filetype == OSD_FILETYPE_SCREENSHOT )
284 {
285 void *f = NULL;
286 sprintf (name, "%s/%s.png", screenshotdir, newfilename);
287 f = fopen (name, "rb");
288 if( f )
289 {
290 fclose ((FILE*)f);
291 return 1;
292 }
293
294 return 0;
295 }
296 else
297 return 0;
298
299 for( ; indx < pathc; indx++ )
300 {
301 struct stat stat_buffer;
302
303 dir_name = pathv[indx];
304
305 /* does such a directory (or file) exist? */
306 sprintf (name, "%s/%s", dir_name, filename);
307 if( cache_stat (name, &stat_buffer) == 0 )
308 return indx + 1;
309
310 /* try again with a .zip extension */
311 sprintf (name, "%s/%s.zip", dir_name, filename);
312 if( cache_stat (name, &stat_buffer) == 0 )
313 return indx + 1;
314
315 /* try again with a .zif extension */
316 sprintf (name, "%s/%s.zif", dir_name, filename);
317 if( cache_stat (name, &stat_buffer) == 0 )
318 return indx + 1;
319 }
320
321 /* no match */
322 return 0;
323 }
324
325
326 extern char slash;
327 #define PATHSEPCH slash
328 #define NO_ERROR (0)
329
create_path_recursive(char * path)330 UINT32 create_path_recursive(char *path)
331 {
332 char *sep = strrchr(path, PATHSEPCH);
333 UINT32 filerr;
334 struct stat st;
335
336 // if there's still a separator, and it's not the root, nuke it and recurse
337 if (sep != NULL && sep > path && sep[0] != ':' && sep[-1] != PATHSEPCH)
338 {
339 *sep = 0;
340 filerr = create_path_recursive(path);
341 *sep = PATHSEPCH;
342 if (filerr != NO_ERROR)
343 return filerr;
344 }
345
346 // if the path already exists, we're done
347 if (!stat(path, &st))
348 return NO_ERROR;
349
350 //printf("mkd(%s)\n",path);
351 // create the path
352 if (path_mkdir(path) != 1)
353 /*
354 #ifdef WIN32
355 if (mkdir(path) != 0)
356 #else
357 if (mkdir(path, 0777) != 0)
358 #endif
359 */
360 return -1;//errno;
361
362 return NO_ERROR;
363 }
364
365 /* JB 980920 update */
366 /* AM 980919 update */
osd_fopen(const char * game,const char * filename,int filetype,int _write)367 void *osd_fopen (const char *game, const char *filename, int filetype, int _write)
368 {
369 char name[256];
370 char *gamename;
371 int found = 0;
372 int indx;
373 struct stat stat_buffer;
374 int pathc;
375 char **pathv;
376 FakeFileHandle *f = (FakeFileHandle *) malloc(sizeof (FakeFileHandle));
377
378 if( !f )
379 {
380 logerror("osd_fopen: failed to mallocFakeFileHandle!\n");
381 return 0;
382 }
383 memset (f, 0, sizeof (FakeFileHandle));
384
385 gamename = (char *) game;
386
387 /* Support "-romdir" yuck. */
388 if( alternate_name )
389 {
390 LOG(("osd_fopen: -romdir overrides '%s' by '%s'\n", gamename, alternate_name));
391 gamename = alternate_name;
392 }
393
394 switch( filetype )
395 {
396 case OSD_FILETYPE_ROM:
397 case OSD_FILETYPE_SAMPLE:
398
399 /* only for reading */
400 if( _write )
401 {
402 logerror("osd_fopen: type %02x write not supported\n",filetype);
403 break;
404 }
405
406 if( filetype == OSD_FILETYPE_SAMPLE )
407 {
408 LOG(("osd_fopen: using samplepath\n"));
409 pathc = samplepathc;
410 pathv = samplepathv;
411 }
412 else
413 {
414 LOG(("osd_fopen: using rompath\n"));
415 pathc = rompathc;
416 pathv = rompathv;
417 }
418
419 for( indx = 0; indx < pathc && !found; ++indx )
420 {
421 const char *dir_name = pathv[indx];
422
423 if( !found )
424 {
425 sprintf (name, "%s/%s", dir_name, gamename);
426 LOG(("Trying %s\n", name));
427 if( cache_stat (name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
428 {
429 sprintf (name, "%s/%s/%s", dir_name, gamename, filename);
430 if( filetype == OSD_FILETYPE_ROM )
431 {
432 if( checksum_file (name, &f->data, &f->length, &f->crc) == 0 )
433 {
434 f->type = kRAMFile;
435 f->offset = 0;
436 found = 1;
437 }
438 }
439 else
440 {
441 f->type = kPlainFile;
442 f->file = fopen (name, "rb");
443 found = f->file != 0;
444 }
445 }
446 }
447
448 if( !found )
449 {
450 /* try with a .zip extension */
451 sprintf (name, "%s/%s.zip", dir_name, gamename);
452 LOG(("Trying %s file\n", name));
453 if( cache_stat (name, &stat_buffer) == 0 )
454 {
455 if( load_zipped_file (name, filename, &f->data, &f->length) == 0 )
456 {
457 LOG(("Using (osd_fopen) zip file for %s\n", filename));
458 f->type = kZippedFile;
459 f->offset = 0;
460 f->crc = crc32 (0L, f->data, f->length);
461 found = 1;
462 }
463 }
464 }
465
466 if( !found )
467 {
468 /* try with a .zip directory (if ZipMagic is installed) */
469 sprintf (name, "%s/%s.zip", dir_name, gamename);
470 LOG(("Trying %s directory\n", name));
471 if( cache_stat (name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
472 {
473 sprintf (name, "%s/%s.zip/%s", dir_name, gamename, filename);
474 if( filetype == OSD_FILETYPE_ROM )
475 {
476 if( checksum_file (name, &f->data, &f->length, &f->crc) == 0 )
477 {
478 f->type = kRAMFile;
479 f->offset = 0;
480 found = 1;
481 }
482 }
483 else
484 {
485 f->type = kPlainFile;
486 f->file = fopen (name, "rb");
487 found = f->file != 0;
488 }
489 }
490 }
491 }
492
493 break;
494
495 #ifdef MESS
496 case OSD_FILETYPE_IMAGE_R:
497
498 /* only for reading */
499 if( _write )
500 {
501 logerror("osd_fopen: type %02x write not supported\n",filetype);
502 break;
503 }
504 else
505 {
506 LOG(("osd_fopen: using rompath\n"));
507 pathc = rompathc;
508 pathv = rompathv;
509 }
510
511 LOG(("Open IMAGE_R '%s' for %s\n", filename, game));
512 for( indx = 0; indx < pathc && !found; ++indx )
513 {
514 const char *dir_name = pathv[indx];
515
516 /* this section allows exact path from .cfg */
517 if( !found )
518 {
519 sprintf(name,"%s",dir_name);
520 if( cache_stat(name,&stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
521 {
522 sprintf(name,"%s/%s",dir_name,filename);
523 if( filetype == OSD_FILETYPE_ROM )
524 {
525 if( checksum_file (name, &f->data, &f->length, &f->crc) == 0 )
526 {
527 f->type = kRAMFile;
528 f->offset = 0;
529 found = 1;
530 }
531 }
532 else
533 {
534 f->type = kPlainFile;
535 f->file = fopen(name,"rb");
536 found = f->file!=0;
537 }
538 }
539 }
540
541 if( !found )
542 {
543 sprintf (name, "%s/%s", dir_name, gamename);
544 LOG(("Trying %s directory\n", name));
545 if( cache_stat (name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
546 {
547 sprintf (name, "%s/%s/%s", dir_name, gamename, filename);
548 LOG(("Trying %s file\n", name));
549 if( filetype == OSD_FILETYPE_ROM )
550 {
551 if( checksum_file(name, &f->data, &f->length, &f->crc) == 0 )
552 {
553 f->type = kRAMFile;
554 f->offset = 0;
555 found = 1;
556 }
557 }
558 else
559 {
560 f->type = kPlainFile;
561 f->file = fopen (name, "rb");
562 found = f->file != 0;
563 }
564 }
565 }
566
567 /* Zip cart support for MESS */
568 if( !found && filetype == OSD_FILETYPE_IMAGE_R )
569 {
570 char *extension = strrchr (name, '.'); /* find extension */
571 if( extension )
572 strcpy (extension, ".zip");
573 else
574 strcat (name, ".zip");
575 LOG(("Trying %s file\n", name));
576 if( cache_stat(name, &stat_buffer) == 0 )
577 {
578 if( load_zipped_file(name, filename, &f->data, &f->length) == 0 )
579 {
580 LOG(("Using (osd_fopen) zip file for %s\n", filename));
581 f->type = kZippedFile;
582 f->offset = 0;
583 f->crc = crc32 (0L, f->data, f->length);
584 found = 1;
585 }
586 }
587 }
588
589 if( !found )
590 {
591 /* try with a .zip extension */
592 sprintf (name, "%s/%s.zip", dir_name, gamename);
593 LOG(("Trying %s file\n", name));
594 if( cache_stat(name, &stat_buffer) == 0 )
595 {
596 if( load_zipped_file(name, filename, &f->data, &f->length) == 0 )
597 {
598 LOG(("Using (osd_fopen) zip file for %s\n", filename));
599 f->type = kZippedFile;
600 f->offset = 0;
601 f->crc = crc32 (0L, f->data, f->length);
602 found = 1;
603 }
604 }
605 }
606 }
607 break; /* end of IMAGE_R */
608
609 case OSD_FILETYPE_IMAGE_RW:
610 {
611 static char *write_modes[] = {"rb","wb","r+b","r+b","w+b"};
612 char file[256];
613 char *extension;
614
615 LOG(("Open IMAGE_RW '%s' for %s mode '%s'\n", filename, game, write_modes[_write]));
616 strcpy (file, filename);
617
618 do
619 {
620 /* 29-05-00 Lee Ward: Reversed the search order. */
621 for (indx=rompathc-1; indx>=0; --indx)
622 {
623 const char *dir_name = rompathv[indx];
624
625 /* Exact path support */
626
627 /* 29-05-00 Lee Ward: Changed the search order to prevent new files
628 being created in the application root as default */
629
630 if( !found )
631 {
632 sprintf (name, "%s/%s", dir_name, gamename);
633 LOG(("Trying %s directory\n", name));
634 if( cache_stat(name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
635 {
636 sprintf (name, "%s/%s/%s", dir_name, gamename, file);
637 LOG(("Trying %s file\n", name));
638 f->file = fopen (name, write_modes[_write]);
639 found = f->file != 0;
640 if( !found && _write == 3 )
641 {
642 f->file = fopen(name, write_modes[4]);
643 found = f->file != 0;
644 }
645 }
646 }
647
648 /* Steph - Zip disk images support for MESS */
649 if( !found && !_write )
650 {
651 extension = strrchr (name, '.'); /* find extension */
652 /* add .zip for zipfile */
653 if( extension )
654 strcpy(extension, ".zip");
655 else
656 strcat(extension, ".zip");
657 LOG(("Trying %s file\n", name));
658 if( cache_stat(name, &stat_buffer) == 0 )
659 {
660 if( load_zipped_file(name, filename, &f->data, &f->length) == 0 )
661 {
662 LOG(("Using (osd_fopen) zip file for %s\n", filename));
663 f->type = kZippedFile;
664 f->offset = 0;
665 f->crc = crc32(0L, f->data, f->length);
666 found = 1;
667 }
668 }
669 }
670
671 if (!found)
672 {
673 sprintf(name, "%s", dir_name);
674 LOG(("Trying %s directory\n", name));
675 if( cache_stat(name,&stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
676 {
677 sprintf(name,"%s/%s", dir_name, file);
678 LOG(("Trying %s file\n", name));
679 f->file = fopen(name, write_modes[_write]);
680 found = f->file != 0;
681 if( !found && _write == 3 )
682 {
683 f->file = fopen(name, write_modes[4]);
684 found = f->file != 0;
685 }
686 }
687 }
688
689 if( !found && !_write )
690 {
691 extension = strrchr (name, '.'); /* find extension */
692 /* add .zip for zipfile */
693 if( extension )
694 strcpy(extension, ".zip");
695 else
696 strcat(extension, ".zip");
697 LOG(("Trying %s file\n", name));
698 if( cache_stat(name, &stat_buffer) == 0 )
699 {
700 if( load_zipped_file(name, filename, &f->data, &f->length) == 0 )
701 {
702 LOG(("Using (osd_fopen) zip file for %s\n", filename));
703 f->type = kZippedFile;
704 f->offset = 0;
705 f->crc = crc32(0L, f->data, f->length);
706 found = 1;
707 }
708 }
709 }
710
711 if( !found && !_write )
712 {
713 /* try with a .zip extension */
714 sprintf (name, "%s/%s.zip", dir_name, gamename);
715 LOG(("Trying %s file\n", name));
716 if( cache_stat (name, &stat_buffer) == 0 )
717 {
718 if( load_zipped_file (name, file, &f->data, &f->length) == 0 )
719 {
720 LOG(("Using (osd_fopen) zip file for %s\n", filename));
721 f->type = kZippedFile;
722 f->offset = 0;
723 f->crc = crc32 (0L, f->data, f->length);
724 found = 1;
725 }
726 }
727 }
728
729 if( !found )
730 {
731 /* try with a .zip directory (if ZipMagic is installed) */
732 sprintf (name, "%s/%s.zip", dir_name, gamename);
733 LOG(("Trying %s ZipMagic directory\n", name));
734 if( cache_stat (name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
735 {
736 sprintf (name, "%s/%s.zip/%s", dir_name, gamename, file);
737 LOG(("Trying %s\n", name));
738 f->file = fopen (name, write_modes[_write]);
739 found = f->file != 0;
740 if( !found && _write == 3 )
741 {
742 f->file = fopen(name, write_modes[4]);
743 found = f->file != 0;
744 }
745 }
746 }
747 if( found )
748 LOG(("IMAGE_RW %s FOUND in %s!\n", file, name));
749 }
750
751 extension = strrchr (file, '.');
752 if( extension )
753 *extension = '\0';
754 } while( !found && extension );
755 }
756 break;
757 #endif /* MESS */
758
759
760 case OSD_FILETYPE_NVRAM:
761 if( !found )
762 {
763 sprintf (name, "%s/%s.nv", nvdir, gamename);
764 f->type = kPlainFile;
765 f->file = fopen (name, _write ? "wb" : "rb");
766 found = f->file != 0;
767 }
768
769 if( !found )
770 {
771 /* try with a .zip directory (if ZipMagic is installed) */
772 sprintf (name, "%s.zip/%s.nv", nvdir, gamename);
773 f->type = kPlainFile;
774 f->file = fopen (name, _write ? "wb" : "rb");
775 found = f->file != 0;
776 }
777
778 if( !found )
779 {
780 /* try with a .zif directory (if ZipFolders is installed) */
781 sprintf (name, "%s.zif/%s.nv", nvdir, gamename);
782 f->type = kPlainFile;
783 f->file = fopen (name, _write ? "wb" : "rb");
784 found = f->file != 0;
785 }
786 break;
787
788 case OSD_FILETYPE_HIGHSCORE:
789 if( mame_highscore_enabled () )
790 {
791 if( !found )
792 {
793 sprintf (name, "%s/%s.hi", hidir, gamename);
794 f->type = kPlainFile;
795 f->file = fopen (name, _write ? "wb" : "rb");
796 found = f->file != 0;
797 }
798
799 if( !found )
800 {
801 /* try with a .zip directory (if ZipMagic is installed) */
802 sprintf (name, "%s.zip/%s.hi", hidir, gamename);
803 f->type = kPlainFile;
804 f->file = fopen (name, _write ? "wb" : "rb");
805 found = f->file != 0;
806 }
807
808 if( !found )
809 {
810 /* try with a .zif directory (if ZipFolders is installed) */
811 sprintf (name, "%s.zif/%s.hi", hidir, gamename);
812 f->type = kPlainFile;
813 f->file = fopen (name, _write ? "wb" : "rb");
814 found = f->file != 0;
815 }
816 }
817 break;
818
819 case OSD_FILETYPE_CONFIG:
820 sprintf (name, "%s/%s.cfg", cfgdir, gamename);
821 f->type = kPlainFile;
822 f->file = fopen (name, _write ? "wb" : "rb");
823 found = f->file != 0;
824
825 if( !found )
826 {
827 /* try with a .zip directory (if ZipMagic is installed) */
828 sprintf (name, "%s.zip/%s.cfg", cfgdir, gamename);
829 f->type = kPlainFile;
830 f->file = fopen (name, _write ? "wb" : "rb");
831 found = f->file != 0;
832 }
833
834 if( !found )
835 {
836 /* try with a .zif directory (if ZipFolders is installed) */
837 sprintf (name, "%s.zif/%s.cfg", cfgdir, gamename);
838 f->type = kPlainFile;
839 f->file = fopen (name, _write ? "wb" : "rb");
840 found = f->file != 0;
841 }
842 break;
843
844 case OSD_FILETYPE_INPUTLOG:
845 sprintf (name, "%s/%s.inp", inpdir, gamename);
846 f->type = kPlainFile;
847 f->file = fopen (name, _write ? "wb" : "rb");
848 found = f->file != 0;
849
850 if( !found )
851 {
852 /* try with a .zip directory (if ZipMagic is installed) */
853 sprintf (name, "%s.zip/%s.cfg", inpdir, gamename);
854 f->type = kPlainFile;
855 f->file = fopen (name, _write ? "wb" : "rb");
856 found = f->file != 0;
857 }
858
859 if( !found )
860 {
861 /* try with a .zif directory (if ZipFolders is installed) */
862 sprintf (name, "%s.zif/%s.cfg", inpdir, gamename);
863 f->type = kPlainFile;
864 f->file = fopen (name, _write ? "wb" : "rb");
865 found = f->file != 0;
866 }
867
868 if( !_write )
869 {
870 char file[256];
871 sprintf (file, "%s.inp", gamename);
872 sprintf (name, "%s/%s.zip", inpdir, gamename);
873 LOG(("Trying %s in %s\n", file, name));
874 if( cache_stat (name, &stat_buffer) == 0 )
875 {
876 if( load_zipped_file (name, file, &f->data, &f->length) == 0 )
877 {
878 LOG(("Using (osd_fopen) zip file %s for %s\n", name, file));
879 f->type = kZippedFile;
880 f->offset = 0;
881 found = 1;
882 }
883 }
884 }
885
886 break;
887
888 case OSD_FILETYPE_STATE:
889 sprintf (name, "%s/%s.sta", stadir, gamename);
890 f->file = fopen (name, _write ? "wb" : "rb");
891 found = !(f->file == 0);
892 if( !found )
893 {
894 /* try with a .zip directory (if ZipMagic is installed) */
895 sprintf (name, "%s.zip/%s.sta", stadir, gamename);
896 f->file = fopen (name, _write ? "wb" : "rb");
897 found = !(f->file == 0);
898 }
899 if( !found )
900 {
901 /* try with a .zif directory (if ZipFolders is installed) */
902 sprintf (name, "%s.zif/%s.sta", stadir, gamename);
903 f->file = fopen (name, _write ? "wb" : "rb");
904 found = !(f->file == 0);
905 }
906 break;
907
908 case OSD_FILETYPE_ARTWORK:
909 /* only for reading */
910 if( _write )
911 {
912 logerror("osd_fopen: type %02x write not supported\n",filetype);
913 break;
914 }
915 sprintf (name, "%s/%s", artworkdir, filename);
916 f->type = kPlainFile;
917 f->file = fopen (name, _write ? "wb" : "rb");
918 found = f->file != 0;
919 if( !found )
920 {
921 /* try with a .zip directory (if ZipMagic is installed) */
922 sprintf (name, "%s.zip/%s.png", artworkdir, filename);
923 f->type = kPlainFile;
924 f->file = fopen (name, _write ? "wb" : "rb");
925 found = f->file != 0;
926 }
927
928 if( !found )
929 {
930 /* try with a .zif directory (if ZipFolders is installed) */
931 sprintf (name, "%s.zif/%s.png", artworkdir, filename);
932 f->type = kPlainFile;
933 f->file = fopen (name, _write ? "wb" : "rb");
934 found = f->file != 0;
935 }
936
937 if( !found )
938 {
939 char file[256], *extension;
940 sprintf(file, "%s", filename);
941 sprintf(name, "%s/%s", artworkdir, filename);
942 extension = strrchr(name, '.');
943 if( extension )
944 strcpy (extension, ".zip");
945 else
946 strcat (name, ".zip");
947 LOG(("Trying %s in %s\n", file, name));
948 if( cache_stat (name, &stat_buffer) == 0 )
949 {
950 if( load_zipped_file (name, file, &f->data, &f->length) == 0 )
951 {
952 LOG(("Using (osd_fopen) zip file %s\n", name));
953 f->type = kZippedFile;
954 f->offset = 0;
955 found = 1;
956 }
957 }
958 if( !found )
959 {
960 sprintf(name, "%s/%s.zip", artworkdir, game);
961 LOG(("Trying %s in %s\n", file, name));
962 if( cache_stat (name, &stat_buffer) == 0 )
963 {
964 if( load_zipped_file (name, file, &f->data, &f->length) == 0 )
965 {
966 LOG(("Using (osd_fopen) zip file %s\n", name));
967 f->type = kZippedFile;
968 f->offset = 0;
969 found = 1;
970 }
971 }
972 }
973 }
974 break;
975
976 case OSD_FILETYPE_MEMCARD:
977 sprintf (name, "%s/%s", memcarddir, filename);
978 f->type = kPlainFile;
979 f->file = fopen (name, _write ? "wb" : "rb");
980 found = f->file != 0;
981 break;
982
983 case OSD_FILETYPE_SCREENSHOT:
984 /* only for writing */
985 if( !_write )
986 {
987 logerror("osd_fopen: type %02x read not supported\n",filetype);
988 break;
989 }
990
991 sprintf (name, "%s/%s.png", screenshotdir, filename);
992 f->type = kPlainFile;
993 f->file = fopen (name, _write ? "wb" : "rb");
994 found = f->file != 0;
995 break;
996
997 case OSD_FILETYPE_HIGHSCORE_DB:
998 case OSD_FILETYPE_HISTORY:
999 /* only for reading */
1000 sprintf (name, "%s/%s", IMAMEBASEPATH, filename);//FIX Seleuco
1001 if( _write )
1002 {
1003 logerror("osd_fopen: type %02x write not supported\n",filetype);
1004 break;
1005 }
1006 f->type = kPlainFile;
1007 /* open as ASCII files, not binary like the others */
1008 f->file = fopen (name/*filename*/, _write ? "w" : "r");//FIX Seleuco
1009 found = f->file != 0;
1010 break;
1011
1012 /* Steph */
1013 case OSD_FILETYPE_CHEAT:
1014 sprintf (name, "%s/%s", cheatdir, filename);
1015 f->type = kPlainFile;
1016 /* open as ASCII files, not binary like the others */
1017 f->file = fopen (/*filename*/name, _write ? "a" : "r");//FIX Seleuco
1018 found = f->file != 0;
1019 break;
1020
1021 case OSD_FILETYPE_LANGUAGE:
1022 /* only for reading */
1023 if( _write )
1024 {
1025 logerror("osd_fopen: type %02x write not supported\n",filetype);
1026 break;
1027 }
1028 sprintf (name, "%s.lng", filename);
1029 f->type = kPlainFile;
1030 /* open as ASCII files, not binary like the others */
1031 f->file = fopen (name, _write ? "w" : "r");
1032 found = f->file != 0;
1033 logerror("fopen %s = %08x\n",name,(intptr_t)f->file);
1034 break;
1035
1036 default:
1037 logerror("osd_fopen(): unknown filetype %02x\n",filetype);
1038 }
1039
1040 if( !found )
1041 {
1042 free(f);
1043 return 0;
1044 }
1045
1046 return f;
1047 }
1048
1049 /* JB 980920 update */
osd_fread(void * file,void * buffer,int length)1050 int osd_fread (void *file, void *buffer, int length)
1051 {
1052 FakeFileHandle *f = (FakeFileHandle *) file;
1053
1054 switch( f->type )
1055 {
1056 case kPlainFile:
1057 return fread (buffer, 1, length, f->file);
1058 case kZippedFile:
1059 case kRAMFile:
1060 /* reading from the RAM image of a file */
1061 if( f->data )
1062 {
1063 if( length + f->offset > f->length )
1064 length = f->length - f->offset;
1065 memcpy (buffer, f->offset + f->data, length);
1066 f->offset += length;
1067 return length;
1068 }
1069 break;
1070 }
1071
1072 return 0;
1073 }
1074
osd_fread_swap(void * file,void * buffer,int length)1075 int osd_fread_swap (void *file, void *buffer, int length)
1076 {
1077 int i;
1078 unsigned char temp;
1079 int res = osd_fread (file, buffer, length);
1080 unsigned char *buf = (unsigned char*)buffer;
1081
1082 for( i = 0; i < length; i += 2 )
1083 {
1084 temp = buf[i];
1085 buf[i] = buf[i + 1];
1086 buf[i + 1] = temp;
1087 }
1088
1089 return res;
1090 }
1091
1092
1093 /* AM 980919 update */
osd_fwrite(void * file,const void * buffer,int length)1094 int osd_fwrite (void *file, const void *buffer, int length)
1095 {
1096 FakeFileHandle *f = (FakeFileHandle *) file;
1097
1098 switch( f->type )
1099 {
1100 case kPlainFile:
1101 return fwrite (buffer, 1, length, ((FakeFileHandle *) file)->file);
1102 default:
1103 break;
1104 }
1105
1106 return 0;
1107 }
1108
osd_fwrite_swap(void * file,const void * buffer,int length)1109 int osd_fwrite_swap (void *file, const void *buffer, int length)
1110 {
1111 int i;
1112 int res;
1113 unsigned char temp;
1114 unsigned char *buf = (unsigned char *) buffer;
1115
1116 for( i = 0; i < length; i += 2 )
1117 {
1118 temp = buf[i];
1119 buf[i] = buf[i + 1];
1120 buf[i + 1] = temp;
1121 }
1122
1123 res = osd_fwrite (file, buffer, length);
1124
1125 for( i = 0; i < length; i += 2 )
1126 {
1127 temp = buf[i];
1128 buf[i] = buf[i + 1];
1129 buf[i + 1] = temp;
1130 }
1131
1132 return res;
1133 }
1134
osd_fread_scatter(void * file,void * buffer,int length,int increment)1135 int osd_fread_scatter (void *file, void *buffer, int length, int increment)
1136 {
1137 unsigned char *buf = (unsigned char*)buffer;
1138 FakeFileHandle *f = (FakeFileHandle *) file;
1139 unsigned char tempbuf[4096];
1140 int totread, r, i;
1141
1142 switch( f->type )
1143 {
1144 case kPlainFile:
1145 totread = 0;
1146 while (length)
1147 {
1148 r = length;
1149 if( r > 4096 )
1150 r = 4096;
1151 r = fread (tempbuf, 1, r, f->file);
1152 if( r == 0 )
1153 return totread; /* error */
1154 for( i = 0; i < r; i++ )
1155 {
1156 *buf = tempbuf[i];
1157 buf += increment;
1158 }
1159 totread += r;
1160 length -= r;
1161 }
1162 return totread;
1163 case kZippedFile:
1164 case kRAMFile:
1165 /* reading from the RAM image of a file */
1166 if( f->data )
1167 {
1168 if( length + f->offset > f->length )
1169 length = f->length - f->offset;
1170 for( i = 0; i < length; i++ )
1171 {
1172 *buf = f->data[f->offset + i];
1173 buf += increment;
1174 }
1175 f->offset += length;
1176 return length;
1177 }
1178 break;
1179 }
1180
1181 return 0;
1182 }
1183
1184
1185 /* JB 980920 update */
osd_fseek(void * file,int offset,int whence)1186 int osd_fseek (void *file, int offset, int whence)
1187 {
1188 FakeFileHandle *f = (FakeFileHandle *) file;
1189 int err = 0;
1190
1191 switch( f->type )
1192 {
1193 case kPlainFile:
1194 return fseek (f->file, offset, whence);
1195 case kZippedFile:
1196 case kRAMFile:
1197 /* seeking within the RAM image of a file */
1198 switch( whence )
1199 {
1200 case SEEK_SET:
1201 f->offset = offset;
1202 break;
1203 case SEEK_CUR:
1204 f->offset += offset;
1205 break;
1206 case SEEK_END:
1207 f->offset = f->length + offset;
1208 break;
1209 }
1210 break;
1211 }
1212
1213 return err;
1214 }
1215
1216 /* JB 980920 update */
osd_fclose(void * file)1217 void osd_fclose (void *file)
1218 {
1219 FakeFileHandle *f = (FakeFileHandle *) file;
1220
1221 switch( f->type )
1222 {
1223 case kPlainFile:
1224 fclose (f->file);
1225 break;
1226 case kZippedFile:
1227 case kRAMFile:
1228 if( f->data )
1229 free(f->data);
1230 break;
1231 }
1232 free(f);
1233 }
1234
1235 /* JB 980920 update */
1236 /* AM 980919 */
checksum_file(const char * file,unsigned char ** p,unsigned int * size,unsigned int * crc)1237 static int checksum_file (const char *file, unsigned char **p, unsigned int *size, unsigned int *crc)
1238 {
1239 int length;
1240 unsigned char *data;
1241 FILE *f = fopen (file, "rb");
1242
1243 if( !f )
1244 return -1;
1245
1246 /* determine length of file */
1247 if( fseek (f, 0L, SEEK_END) != 0 )
1248 {
1249 fclose (f);
1250 return -1;
1251 }
1252
1253 length = ftell (f);
1254 if( length == -1L )
1255 {
1256 fclose (f);
1257 return -1;
1258 }
1259
1260 /* allocate space for entire file */
1261 data = (unsigned char *) malloc(length);
1262 if( !data )
1263 {
1264 fclose (f);
1265 return -1;
1266 }
1267
1268 /* read entire file into memory */
1269 if( fseek (f, 0L, SEEK_SET) != 0 )
1270 {
1271 free(data);
1272 fclose (f);
1273 return -1;
1274 }
1275
1276 if( fread (data, sizeof (unsigned char), length, f) != length )
1277 {
1278 free(data);
1279 fclose (f);
1280 return -1;
1281 }
1282
1283 *size = length;
1284 *crc = crc32 (0L, data, length);
1285 if( p )
1286 *p = data;
1287 else
1288 free(data);
1289
1290 fclose (f);
1291
1292 return 0;
1293 }
1294
1295 /* JB 980920 updated */
1296 /* AM 980919 updated */
osd_fchecksum(const char * game,const char * filename,unsigned int * length,unsigned int * sum)1297 int osd_fchecksum (const char *game, const char *filename, unsigned int *length, unsigned int *sum)
1298 {
1299 char name[256];
1300 int indx;
1301 struct stat stat_buffer;
1302 int found = 0;
1303 const char *gamename = game;
1304
1305 /* Support "-romdir" yuck. */
1306 if( alternate_name )
1307 gamename = alternate_name;
1308
1309 for( indx = 0; indx < rompathc && !found; ++indx )
1310 {
1311 const char *dir_name = rompathv[indx];
1312
1313 if( !found )
1314 {
1315 sprintf (name, "%s/%s", dir_name, gamename);
1316 if( cache_stat (name, &stat_buffer) == 0 && (stat_buffer.st_mode & S_IFDIR) )
1317 {
1318 sprintf (name, "%s/%s/%s", dir_name, gamename, filename);
1319 if( checksum_file (name, 0, length, sum) == 0 )
1320 {
1321 found = 1;
1322 }
1323 }
1324 }
1325
1326 if( !found )
1327 {
1328 /* try with a .zip extension */
1329 sprintf (name, "%s/%s.zip", dir_name, gamename);
1330 if( cache_stat (name, &stat_buffer) == 0 )
1331 {
1332 if( checksum_zipped_file (name, filename, length, sum) == 0 )
1333 {
1334 LOG(("Using (osd_fchecksum) zip file for %s\n", filename));
1335 found = 1;
1336 }
1337 }
1338 }
1339
1340 if( !found )
1341 {
1342 /* try with a .zif directory (if ZipFolders is installed) */
1343 sprintf (name, "%s/%s.zif", dir_name, gamename);
1344 if( cache_stat (name, &stat_buffer) == 0 )
1345 {
1346 sprintf (name, "%s/%s.zif/%s", dir_name, gamename, filename);
1347 if( checksum_file (name, 0, length, sum) == 0 )
1348 {
1349 found = 1;
1350 }
1351 }
1352 }
1353 }
1354
1355 if( !found )
1356 return -1;
1357
1358 return 0;
1359 }
1360
1361 /* JB 980920 */
osd_fsize(void * file)1362 int osd_fsize (void *file)
1363 {
1364 FakeFileHandle *f = (FakeFileHandle *) file;
1365
1366 if( f->type == kRAMFile || f->type == kZippedFile )
1367 return f->length;
1368
1369 if( f->file )
1370 {
1371 int size;
1372 int offs = ftell( f->file );
1373
1374 fseek( f->file, 0, SEEK_END );
1375 size = ftell( f->file );
1376 fseek( f->file, offs, SEEK_SET );
1377 return size;
1378 }
1379
1380 return 0;
1381 }
1382
1383 /* JB 980920 */
osd_fcrc(void * file)1384 unsigned int osd_fcrc (void *file)
1385 {
1386 FakeFileHandle *f = (FakeFileHandle *) file;
1387
1388 return f->crc;
1389 }
1390
osd_fgetc(void * file)1391 int osd_fgetc(void *file)
1392 {
1393 FakeFileHandle *f = (FakeFileHandle *) file;
1394
1395 if (f->type == kPlainFile && f->file)
1396 return fgetc(f->file);
1397
1398 return EOF;
1399 }
1400
osd_ungetc(int c,void * file)1401 int osd_ungetc(int c, void *file)
1402 {
1403 FakeFileHandle *f = (FakeFileHandle *) file;
1404
1405 if (f->type == kPlainFile && f->file)
1406 return ungetc(c,f->file);
1407
1408 return EOF;
1409 }
1410
osd_fgets(char * s,int n,void * file)1411 char *osd_fgets(char *s, int n, void *file)
1412 {
1413 FakeFileHandle *f = (FakeFileHandle *) file;
1414
1415 if (f->type == kPlainFile && f->file)
1416 return fgets(s,n,f->file);
1417
1418 return NULL;
1419 }
1420
osd_feof(void * file)1421 int osd_feof(void *file)
1422 {
1423 FakeFileHandle *f = (FakeFileHandle *) file;
1424
1425 if (f->type == kPlainFile && f->file)
1426 return feof(f->file);
1427
1428 return 1;
1429 }
1430
osd_ftell(void * file)1431 int osd_ftell(void *file)
1432 {
1433 FakeFileHandle *f = (FakeFileHandle *) file;
1434
1435 if (f->type == kPlainFile && f->file)
1436 return ftell(f->file);
1437
1438 return -1L;
1439 }
1440
1441
1442 /* called while loading ROMs. It is called a last time with name == 0 to signal */
1443 /* that the ROM loading process is finished. */
1444 /* return non-zero to abort loading */
osd_display_loading_rom_message(const char * name,int current,int total)1445 int osd_display_loading_rom_message (const char *name, int current, int total)
1446 {
1447 if( name )
1448 printf ("loading %-12s\n", name);
1449 else
1450 printf (" \n");
1451 fflush (stdout);
1452
1453 if( keyboard_pressed (KEYCODE_LCONTROL) && keyboard_pressed (KEYCODE_C) )
1454 return 1;
1455
1456 return 0;
1457 }
1458