~ubuntu-branches/ubuntu/lucid/fceux/lucid

« back to all changes in this revision

Viewing changes to fceu/src/file.cpp

  • Committer: Bazaar Package Importer
  • Author(s): Fabrice Coutadeur
  • Date: 2009-12-14 08:05:17 UTC
  • Revision ID: james.westby@ubuntu.com-20091214080517-abi5tj8avthfan7c
Tags: upstream-2.1.2+repack
ImportĀ upstreamĀ versionĀ 2.1.2+repack

Show diffs side-by-side

added added

removed removed

Lines of Context:
 
1
/* FCE Ultra - NES/Famicom Emulator
 
2
 *
 
3
 * Copyright notice for this file:
 
4
 *  Copyright (C) 2002 Xodnizel
 
5
 *
 
6
 * This program is free software; you can redistribute it and/or modify
 
7
 * it under the terms of the GNU General Public License as published by
 
8
 * the Free Software Foundation; either version 2 of the License, or
 
9
 * (at your option) any later version.
 
10
 *
 
11
 * This program is distributed in the hope that it will be useful,
 
12
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 
13
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
14
 * GNU General Public License for more details.
 
15
 *
 
16
 * You should have received a copy of the GNU General Public License
 
17
 * along with this program; if not, write to the Free Software
 
18
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 
19
 */
 
20
 
 
21
#include <stdio.h>
 
22
#include <limits.h>
 
23
#include <stdlib.h>
 
24
#include <string.h>
 
25
#include <stdarg.h>
 
26
#include <sys/types.h>
 
27
#include <sys/stat.h>
 
28
#include <fstream>
 
29
 
 
30
#ifndef WIN32
 
31
#include <zlib.h>
 
32
#endif
 
33
 
 
34
#include "types.h"
 
35
#include "file.h"
 
36
#include "utils/endian.h"
 
37
#include "utils/memory.h"
 
38
#include "utils/md5.h"
 
39
#include "utils/unzip.h"
 
40
#include "driver.h"
 
41
#include "types.h"
 
42
#include "fceu.h"
 
43
#include "state.h"
 
44
#include "movie.h"
 
45
#include "driver.h"
 
46
#include "utils/xstring.h"
 
47
#include "utils/memorystream.h"
 
48
 
 
49
using namespace std;
 
50
 
 
51
bool bindSavestate = true;      //Toggle that determines if a savestate filename will include the movie filename
 
52
static std::string BaseDirectory;
 
53
static char FileExt[2048];      //Includes the . character, as in ".nes"
 
54
char FileBase[2048];
 
55
static char FileBaseDirectory[2048];
 
56
 
 
57
 
 
58
void ApplyIPS(FILE *ips, FCEUFILE* fp)
 
59
{
 
60
        uint8 header[5];
 
61
        uint32 count=0;
 
62
 
 
63
        if(!ips) return;
 
64
 
 
65
        char* buf = (char*)malloc(fp->size);
 
66
        memcpy(buf,fp->EnsureMemorystream()->buf(),fp->size);
 
67
 
 
68
 
 
69
        FCEU_printf(" Applying IPS...\n");
 
70
        if(fread(header,1,5,ips)!=5)
 
71
        {
 
72
                goto end;
 
73
        }
 
74
        if(memcmp(header,"PATCH",5))
 
75
        {
 
76
                goto end;
 
77
        }
 
78
 
 
79
        while(fread(header,1,3,ips)==3)
 
80
        {
 
81
                uint32 offset=(header[0]<<16)|(header[1]<<8)|header[2];
 
82
                uint16 size;
 
83
 
 
84
                if(!memcmp(header,"EOF",3))
 
85
                {
 
86
                        FCEU_printf(" IPS EOF:  Did %d patches\n\n",count);
 
87
                        goto end;
 
88
                }
 
89
 
 
90
                size=fgetc(ips)<<8;
 
91
                size|=fgetc(ips);
 
92
                if(!size)       /* RLE */
 
93
                {
 
94
                        char *start;
 
95
                        char b;
 
96
                        size=fgetc(ips)<<8;
 
97
                        size|=fgetc(ips);
 
98
 
 
99
                        //FCEU_printf("  Offset: %8d  Size: %5d RLE\n",offset,size);
 
100
 
 
101
                        if((offset+size)>(uint32)fp->size)
 
102
                        {
 
103
                                // Probably a little slow.
 
104
                                buf=(char *)realloc(buf,offset+size);
 
105
                                if(!buf)
 
106
                                {
 
107
                                        FCEU_printf("  Oops.  IPS patch %d(type RLE) goes beyond end of file.  Could not allocate memory.\n",count);
 
108
                                        goto end;
 
109
                                }
 
110
                                memset(buf+fp->size,0,offset+size-fp->size);
 
111
                                fp->size=offset+size;
 
112
                        }
 
113
                        b=fgetc(ips);
 
114
                        start=buf+offset;
 
115
                        do
 
116
                        {
 
117
                                *start=b;
 
118
                                start++;
 
119
                        } while(--size);
 
120
                }
 
121
                else            /* Normal patch */
 
122
                {
 
123
                        //FCEU_printf("  Offset: %8d  Size: %5d\n",offset,size);
 
124
                        if((offset+size)>(uint32)fp->size)
 
125
                        {
 
126
                                // Probably a little slow.
 
127
                                buf=(char *)realloc(buf,offset+size);
 
128
                                if(!buf)
 
129
                                {
 
130
                                        FCEU_printf("  Oops.  IPS patch %d(type normal) goes beyond end of file.  Could not allocate memory.\n",count);
 
131
                                        goto end;
 
132
                                }
 
133
                                memset(buf+fp->size,0,offset+size-fp->size);
 
134
                        }
 
135
                        fread(buf+offset,1,size,ips);
 
136
                }
 
137
                count++;
 
138
        }
 
139
        FCEU_printf(" Hard IPS end!\n");
 
140
end:
 
141
        fclose(ips);
 
142
        memorystream* ms = new memorystream(buf,fp->size);
 
143
        ms->giveBuf();
 
144
        fp->SetStream(ms);
 
145
}
 
146
 
 
147
std::string FCEU_MakeIpsFilename(FileBaseInfo fbi) {
 
148
        char ret[FILENAME_MAX] = "";
 
149
        sprintf(ret,"%s"PSS"%s%s.ips",fbi.filebasedirectory.c_str(),fbi.filebase.c_str(),fbi.ext.c_str());
 
150
        return ret;
 
151
}
 
152
 
 
153
void FCEU_SplitArchiveFilename(std::string src, std::string& archive, std::string& file, std::string& fileToOpen)
 
154
{
 
155
        size_t pipe = src.find_first_of('|');
 
156
        if(pipe == std::string::npos)
 
157
        {
 
158
                archive = "";
 
159
                file = src;
 
160
                fileToOpen = src;
 
161
        }
 
162
        else
 
163
        {
 
164
                archive = src.substr(0,pipe);
 
165
                file = src.substr(pipe+1);
 
166
                fileToOpen = archive;
 
167
        }
 
168
}
 
169
 
 
170
FileBaseInfo CurrentFileBase() {
 
171
        return FileBaseInfo(FileBaseDirectory,FileBase,FileExt);
 
172
}
 
173
 
 
174
FileBaseInfo DetermineFileBase(const char *f) {
 
175
 
 
176
        char drv[PATH_MAX], dir[PATH_MAX], name[PATH_MAX], ext[PATH_MAX];
 
177
        splitpath(f,drv,dir,name,ext);
 
178
 
 
179
        if(dir[0] == 0) strcpy(dir,".");
 
180
 
 
181
        return FileBaseInfo((std::string)drv + dir,name,ext);   
 
182
        
 
183
}
 
184
 
 
185
inline FileBaseInfo DetermineFileBase(const std::string& str) { return DetermineFileBase(str.c_str()); }
 
186
 
 
187
static FCEUFILE * TryUnzip(const std::string& path) {
 
188
        unzFile tz;
 
189
        if((tz=unzOpen(path.c_str())))  // If it's not a zip file, use regular file handlers.
 
190
                // Assuming file type by extension usually works,
 
191
                // but I don't like it. :)
 
192
        {
 
193
                if(unzGoToFirstFile(tz)==UNZ_OK)
 
194
                {
 
195
                        for(;;)
 
196
                        {
 
197
                                char tempu[512];        // Longer filenames might be possible, but I don't
 
198
                                // think people would name files that long in zip files...
 
199
                                unzGetCurrentFileInfo(tz,0,tempu,512,0,0,0,0);
 
200
                                tempu[511]=0;
 
201
                                if(strlen(tempu)>=4)
 
202
                                {
 
203
                                        char *za=tempu+strlen(tempu)-4;
 
204
 
 
205
                                        //if(!ext)
 
206
                                        {
 
207
                                                if(!strcasecmp(za,".nes") || !strcasecmp(za,".fds") ||
 
208
                                                        !strcasecmp(za,".nsf") || !strcasecmp(za,".unf") ||
 
209
                                                        !strcasecmp(za,".nez"))
 
210
                                                        break;
 
211
                                        }
 
212
                                        //else if(!strcasecmp(za,ext))
 
213
                                        //      break;
 
214
                                }
 
215
                                if(strlen(tempu)>=5)
 
216
                                {
 
217
                                        if(!strcasecmp(tempu+strlen(tempu)-5,".unif"))
 
218
                                                break;
 
219
                                }
 
220
                                if(unzGoToNextFile(tz)!=UNZ_OK)
 
221
                                {
 
222
                                        if(unzGoToFirstFile(tz)!=UNZ_OK) goto zpfail;
 
223
                                        break;
 
224
                                }
 
225
                        }
 
226
                        if(unzOpenCurrentFile(tz)!=UNZ_OK)
 
227
                                goto zpfail;
 
228
                }
 
229
                else
 
230
                {
 
231
zpfail:
 
232
                        unzClose(tz);
 
233
                        return 0;
 
234
                }
 
235
 
 
236
                unz_file_info ufo;
 
237
                unzGetCurrentFileInfo(tz,&ufo,0,0,0,0,0,0);
 
238
                
 
239
                int size = ufo.uncompressed_size;
 
240
                memorystream* ms = new memorystream(size);
 
241
                unzReadCurrentFile(tz,ms->buf(),ufo.uncompressed_size);
 
242
                unzCloseCurrentFile(tz);
 
243
                unzClose(tz);
 
244
 
 
245
                FCEUFILE *fceufp = new FCEUFILE();
 
246
                fceufp->stream = ms;
 
247
                fceufp->size = size;
 
248
                return fceufp;
 
249
                
 
250
        }
 
251
 
 
252
        return 0;
 
253
}
 
254
 
 
255
FCEUFILE * FCEU_fopen(const char *path, const char *ipsfn, char *mode, char *ext, int index, const char** extensions)
 
256
{
 
257
        FILE *ipsfile=0;
 
258
        FCEUFILE *fceufp=0;
 
259
 
 
260
        bool read = (std::string)mode == "rb";
 
261
        bool write = (std::string)mode == "wb";
 
262
        if((read&&write) || (!read&&!write))
 
263
        {
 
264
                FCEU_PrintError("invalid file open mode specified (only wb and rb are supported)");
 
265
                return 0;
 
266
        }
 
267
 
 
268
        std::string archive,fname,fileToOpen;
 
269
        FCEU_SplitArchiveFilename(path,archive,fname,fileToOpen);
 
270
        
 
271
 
 
272
        //try to setup the ips file
 
273
        if(ipsfn && read)
 
274
                ipsfile=FCEUD_UTF8fopen(ipsfn,"rb");
 
275
        if(read)
 
276
        {
 
277
                ArchiveScanRecord asr = FCEUD_ScanArchive(fileToOpen);
 
278
                asr.files.FilterByExtension(extensions);
 
279
                if(!asr.isArchive())
 
280
                {
 
281
                        //if the archive contained no files, try to open it the old fashioned way
 
282
                        std::fstream* fp = FCEUD_UTF8_fstream(fileToOpen,mode);
 
283
                        if(!fp)
 
284
                        {
 
285
                                return 0;
 
286
                        }
 
287
 
 
288
                        //try to read a zip file
 
289
                        {
 
290
                                fceufp = TryUnzip(fileToOpen);
 
291
                                if(fceufp) {
 
292
                                        delete fp;
 
293
                                        fceufp->filename = fileToOpen;
 
294
                                        fceufp->logicalPath = fileToOpen;
 
295
                                        fceufp->fullFilename = fileToOpen;
 
296
                                        fceufp->archiveIndex = -1;
 
297
                                        goto applyips;
 
298
                                }
 
299
                        }
 
300
 
 
301
                        //try to read a gzipped file
 
302
                        {
 
303
                                uint32 magic;
 
304
                                
 
305
                                magic = fp->get();
 
306
                                magic|=fp->get()<<8;
 
307
                                magic|=fp->get()<<16;
 
308
                                fp->seekg(0,std::ios::beg);
 
309
 
 
310
                                if(magic==0x088b1f) {
 
311
                                         // maybe gzip... 
 
312
 
 
313
                                        void* gzfile = gzopen(fileToOpen.c_str(),"rb");
 
314
                                        if(gzfile) {
 
315
                                                delete fp;
 
316
 
 
317
                                                int size;
 
318
                                                for(size=0; gzgetc(gzfile) != EOF; size++) {}
 
319
                                                memorystream* ms = new memorystream(size);
 
320
                                                gzseek(gzfile,0,SEEK_SET);
 
321
                                                gzread(gzfile,ms->buf(),size);
 
322
                                                gzclose(gzfile);
 
323
 
 
324
                                                fceufp = new FCEUFILE();
 
325
                                                fceufp->filename = fileToOpen;
 
326
                                                fceufp->logicalPath = fileToOpen;
 
327
                                                fceufp->fullFilename = fileToOpen;
 
328
                                                fceufp->archiveIndex = -1;
 
329
                                                fceufp->stream = ms;
 
330
                                                fceufp->size = size;
 
331
                                                goto applyips;
 
332
                                        }
 
333
                                }
 
334
                        }
 
335
 
 
336
                
 
337
                        //open a plain old file
 
338
                        fceufp = new FCEUFILE();
 
339
                        fceufp->filename = fileToOpen;
 
340
                        fceufp->logicalPath = fileToOpen;
 
341
                        fceufp->fullFilename = fileToOpen;
 
342
                        fceufp->archiveIndex = -1;
 
343
                        fceufp->stream = (std::iostream*)fp;
 
344
                        FCEU_fseek(fceufp,0,SEEK_END);
 
345
                        fceufp->size = FCEU_ftell(fceufp);
 
346
                        FCEU_fseek(fceufp,0,SEEK_SET);
 
347
                        goto applyips;
 
348
                }
 
349
                else
 
350
                {
 
351
                        //open an archive file
 
352
                        if(archive == "")
 
353
                                if(index != -1)
 
354
                                        fceufp = FCEUD_OpenArchiveIndex(asr, fileToOpen, index);
 
355
                                else 
 
356
                                        fceufp = FCEUD_OpenArchive(asr, fileToOpen, 0);
 
357
                        else
 
358
                                fceufp = FCEUD_OpenArchive(asr, archive, &fname);
 
359
 
 
360
                        if(!fceufp) return 0;
 
361
 
 
362
                        FileBaseInfo fbi = DetermineFileBase(fileToOpen);
 
363
                        fceufp->logicalPath = fbi.filebasedirectory + fceufp->filename;
 
364
                        goto applyips;
 
365
                }
 
366
 
 
367
        applyips:
 
368
                //try to open the ips file
 
369
                if(!ipsfile && !ipsfn)
 
370
                        ipsfile=FCEUD_UTF8fopen(FCEU_MakeIpsFilename(DetermineFileBase(fceufp->logicalPath.c_str())),"rb");
 
371
                ApplyIPS(ipsfile,fceufp);
 
372
                return fceufp;
 
373
        }
 
374
        return 0;
 
375
}
 
376
 
 
377
int FCEU_fclose(FCEUFILE *fp)
 
378
{
 
379
        delete fp;
 
380
        return 1;
 
381
}
 
382
 
 
383
uint64 FCEU_fread(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
 
384
{
 
385
        fp->stream->read((char*)ptr,size*nmemb);
 
386
        uint32 read = fp->stream->gcount();
 
387
        return read/size;
 
388
}
 
389
 
 
390
uint64 FCEU_fwrite(void *ptr, size_t size, size_t nmemb, FCEUFILE *fp)
 
391
{
 
392
        fp->stream->write((char*)ptr,size*nmemb);
 
393
        //todo - how do we tell how many bytes we wrote?
 
394
        return nmemb;
 
395
}
 
396
 
 
397
int FCEU_fseek(FCEUFILE *fp, long offset, int whence)
 
398
{
 
399
        //if(fp->type==1)
 
400
        //{
 
401
        //      return( (gzseek(fp->fp,offset,whence)>0)?0:-1);
 
402
        //}
 
403
        //else if(fp->type>=2)
 
404
        //{
 
405
        //      MEMWRAP *wz;
 
406
        //      wz=(MEMWRAP*)fp->fp;
 
407
 
 
408
        //      switch(whence)
 
409
        //      {
 
410
        //      case SEEK_SET:if(offset>=(long)wz->size) //mbg merge 7/17/06 - added cast to long
 
411
        //                                        return(-1);
 
412
        //              wz->location=offset;break;
 
413
        //      case SEEK_CUR:if(offset+wz->location>wz->size)
 
414
        //                                        return (-1);
 
415
        //              wz->location+=offset;
 
416
        //              break;
 
417
        //      }
 
418
        //      return 0;
 
419
        //}
 
420
        //else
 
421
        //      return fseek((FILE *)fp->fp,offset,whence);
 
422
 
 
423
        fp->stream->seekg(offset,(std::ios_base::seekdir)whence);
 
424
        fp->stream->seekp(offset,(std::ios_base::seekdir)whence);
 
425
 
 
426
        return FCEU_ftell(fp);
 
427
}
 
428
 
 
429
uint64 FCEU_ftell(FCEUFILE *fp)
 
430
{
 
431
        if(fp->mode == FCEUFILE::READ)
 
432
                return fp->stream->tellg();
 
433
        else
 
434
                return fp->stream->tellp();
 
435
}
 
436
 
 
437
int FCEU_read16le(uint16 *val, FCEUFILE *fp)
 
438
{
 
439
        return read16le(val,fp->stream);
 
440
}
 
441
 
 
442
int FCEU_read32le(uint32 *Bufo, FCEUFILE *fp)
 
443
{
 
444
        return read32le(Bufo, fp->stream);
 
445
}
 
446
 
 
447
int FCEU_fgetc(FCEUFILE *fp)
 
448
{
 
449
        return fp->stream->get();
 
450
}
 
451
 
 
452
uint64 FCEU_fgetsize(FCEUFILE *fp)
 
453
{
 
454
        return fp->size;
 
455
}
 
456
 
 
457
int FCEU_fisarchive(FCEUFILE *fp)
 
458
{
 
459
        if(fp->archiveIndex==0) return 0;
 
460
        else return 1;
 
461
}
 
462
 
 
463
std::string GetMfn() //Retrieves the movie filename from curMovieFilename (for adding to savestate and auto-save files)
 
464
{
 
465
        std::string movieFilenamePart;
 
466
        extern char curMovieFilename[512];
 
467
        if(*curMovieFilename)
 
468
                {
 
469
                char drv[PATH_MAX], dir[PATH_MAX], name[PATH_MAX], ext[PATH_MAX];
 
470
                splitpath(curMovieFilename,drv,dir,name,ext);
 
471
                movieFilenamePart = std::string(".") + name;
 
472
                }
 
473
        return movieFilenamePart;
 
474
}
 
475
 
 
476
/// Updates the base directory
 
477
void FCEUI_SetBaseDirectory(std::string const & dir)
 
478
{
 
479
        BaseDirectory = dir;
 
480
}
 
481
 
 
482
static char *odirs[FCEUIOD__COUNT]={0,0,0,0,0,0,0,0,0,0,0,0,0};     // odirs, odors. ^_^
 
483
 
 
484
void FCEUI_SetDirOverride(int which, char *n)
 
485
{
 
486
        //      FCEU_PrintError("odirs[%d]=%s->%s", which, odirs[which], n);
 
487
        if (which < FCEUIOD__COUNT)
 
488
        {
 
489
                odirs[which] = n;
 
490
        }
 
491
}
 
492
 
 
493
        #ifndef HAVE_ASPRINTF
 
494
        static int asprintf(char **strp, const char *fmt, ...)
 
495
        {
 
496
                va_list ap;
 
497
                int ret;
 
498
 
 
499
                va_start(ap,fmt);
 
500
                if(!(*strp=(char*)malloc(2048))) //mbg merge 7/17/06 cast to char*
 
501
                        return(0);
 
502
                ret=vsnprintf(*strp,2048,fmt,ap);
 
503
                va_end(ap);
 
504
                return(ret);
 
505
        }
 
506
        #endif
 
507
 
 
508
std::string  FCEU_GetPath(int type)
 
509
{
 
510
        char ret[FILENAME_MAX];
 
511
        switch(type)
 
512
        {
 
513
                case FCEUMKF_STATE:
 
514
                        if(odirs[FCEUIOD_STATES])
 
515
                                return (odirs[FCEUIOD_STATES]);
 
516
                        else
 
517
                                return BaseDirectory + PSS + "fcs";
 
518
                        break;
 
519
                case FCEUMKF_MOVIE:
 
520
                        if(odirs[FCEUIOD_MOVIES])
 
521
                                return (odirs[FCEUIOD_MOVIES]);
 
522
                        else
 
523
                                return BaseDirectory + PSS + "movies";
 
524
                        break;
 
525
                case FCEUMKF_MEMW:
 
526
                        if(odirs[FCEUIOD_MEMW])
 
527
                                return (odirs[FCEUIOD_MEMW]);
 
528
                        else
 
529
                                return "";      //adelikat: 03/02/09 - return null so it defaults to last directory used
 
530
                                //return BaseDirectory + PSS + "tools";
 
531
                        break;
 
532
                //adelikat: TODO: this no longer exist and could be removed (but that would require changing a lot of other directory arrays
 
533
                case FCEUMKF_BBOT:
 
534
                        if(odirs[FCEUIOD_BBOT])
 
535
                                return (odirs[FCEUIOD_BBOT]);
 
536
                        else
 
537
                                return BaseDirectory + PSS + "tools";
 
538
                        break;
 
539
                case FCEUMKF_ROMS:
 
540
                        if(odirs[FCEUIOD_ROMS])
 
541
                                return (odirs[FCEUIOD_ROMS]);
 
542
                        else
 
543
                                return "";      //adelikat: removing base directory return, should return null it goes to last used directory
 
544
                        break;
 
545
                case FCEUMKF_INPUT:
 
546
                        if(odirs[FCEUIOD_INPUT])
 
547
                                return (odirs[FCEUIOD_INPUT]);
 
548
                        else
 
549
                                return BaseDirectory + PSS + "tools";
 
550
                        break;
 
551
                case FCEUMKF_LUA:
 
552
                        if(odirs[FCEUIOD_LUA])
 
553
                                return (odirs[FCEUIOD_LUA]);
 
554
                        else
 
555
                                return "";      //adelikat: 03/02/09 - return null so it defaults to last directory used //return BaseDirectory + PSS + "tools";
 
556
                        break;
 
557
                case FCEUMKF_AVI:
 
558
                        if(odirs[FCEUIOD_AVI])
 
559
                                return (odirs[FCEUIOD_AVI]);
 
560
                        else
 
561
                                return "";              //adelikat - 03/02/09 - if no override, should return null and allow the last directory to be used intead
 
562
                                //return BaseDirectory + PSS + "tools";
 
563
                        break;
 
564
        }
 
565
 
 
566
        return ret;
 
567
}
 
568
 
 
569
std::string FCEU_MakePath(int type, const char* filebase)
 
570
{
 
571
        char ret[FILENAME_MAX];
 
572
 
 
573
        switch(type)
 
574
        {
 
575
                case FCEUMKF_MOVIE:
 
576
                        if(odirs[FCEUIOD_MOVIES])
 
577
                                return (string)odirs[FCEUIOD_MOVIES] + PSS + filebase;
 
578
                        else
 
579
                                return BaseDirectory + PSS + "movies" + PSS + filebase;
 
580
                        break;
 
581
                case FCEUMKF_STATE:
 
582
                        if(odirs[FCEUIOD_STATES])
 
583
                                return (string)odirs[FCEUIOD_STATES] + PSS + filebase;
 
584
                        else
 
585
                                return BaseDirectory + PSS + "fcs" + PSS + filebase;
 
586
                        break;
 
587
        }
 
588
        return ret;
 
589
}
 
590
 
 
591
std::string FCEU_MakeFName(int type, int id1, const char *cd1)
 
592
{
 
593
        char ret[FILENAME_MAX] = "";
 
594
        struct stat tmpstat;
 
595
        std::string mfnString;
 
596
        const char* mfn;
 
597
 
 
598
        switch(type)
 
599
        {
 
600
                case FCEUMKF_MOVIE:
 
601
                        struct stat fileInfo; 
 
602
                        do {
 
603
                                if(odirs[FCEUIOD_MOVIES])
 
604
                                        sprintf(ret,"%s"PSS"%s-%d.fm2",odirs[FCEUIOD_MOVIES],FileBase, id1);
 
605
                                else
 
606
                                        sprintf(ret,"%s"PSS"movies"PSS"%s-%d.fm2",BaseDirectory.c_str(),FileBase, id1);
 
607
                                id1++;
 
608
                        } while (stat(ret, &fileInfo) == 0);
 
609
                        break;
 
610
                case FCEUMKF_STATE:
 
611
                        {
 
612
                                if (bindSavestate) mfnString = GetMfn();
 
613
                                else mfnString = "";
 
614
                                
 
615
                                if (mfnString.length() < 60)    //This caps the movie filename length before adding it to the savestate filename.  
 
616
                                        mfn = mfnString.c_str();        //This helps prevent possible crashes from savestate filenames of excessive length.
 
617
                                        
 
618
                                else 
 
619
                                        {
 
620
                                        std::string mfnStringTemp = mfnString.substr(0,60);
 
621
                                        mfn = mfnStringTemp.c_str();    //mfn is the movie filename
 
622
                                        }
 
623
                                
 
624
                                
 
625
                                
 
626
                                if(odirs[FCEUIOD_STATES])
 
627
                                {
 
628
                                        sprintf(ret,"%s"PSS"%s%s.fc%d",odirs[FCEUIOD_STATES],FileBase,mfn,id1);
 
629
                                }
 
630
                                else
 
631
                                {
 
632
                                        sprintf(ret,"%s"PSS"fcs"PSS"%s%s.fc%d",BaseDirectory.c_str(),FileBase,mfn,id1);
 
633
                                }
 
634
                                if(stat(ret,&tmpstat)==-1)
 
635
                                {
 
636
                                        if(odirs[FCEUIOD_STATES])
 
637
                                        {
 
638
                                                sprintf(ret,"%s"PSS"%s%s.fc%d",odirs[FCEUIOD_STATES],FileBase,mfn,id1);
 
639
                                        }
 
640
                                        else
 
641
                                        {
 
642
                                                sprintf(ret,"%s"PSS"fcs"PSS"%s%s.fc%d",BaseDirectory.c_str(),FileBase,mfn,id1);
 
643
                                        }
 
644
                                }
 
645
                        }
 
646
                        break;
 
647
                case FCEUMKF_SNAP:
 
648
                        if(odirs[FCEUIOD_SNAPS])
 
649
                                sprintf(ret,"%s"PSS"%s-%d.%s",odirs[FCEUIOD_SNAPS],FileBase,id1,cd1);
 
650
                        else
 
651
                                sprintf(ret,"%s"PSS"snaps"PSS"%s-%d.%s",BaseDirectory.c_str(),FileBase,id1,cd1);
 
652
                        break;
 
653
                case FCEUMKF_FDS:
 
654
                        if(odirs[FCEUIOD_NV])
 
655
                                sprintf(ret,"%s"PSS"%s.fds",odirs[FCEUIOD_NV],FileBase);
 
656
                        else
 
657
                                sprintf(ret,"%s"PSS"sav"PSS"%s.fds",BaseDirectory.c_str(),FileBase);
 
658
                        break;
 
659
                case FCEUMKF_SAV:
 
660
                        if(odirs[FCEUIOD_NV])
 
661
                                sprintf(ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
 
662
                        else
 
663
                                sprintf(ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory.c_str(),FileBase,cd1);
 
664
                        if(stat(ret,&tmpstat)==-1)
 
665
                        {
 
666
                                if(odirs[FCEUIOD_NV])
 
667
                                        sprintf(ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
 
668
                                else
 
669
                                        sprintf(ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory.c_str(),FileBase,cd1);
 
670
                        }
 
671
                        break;
 
672
                case FCEUMKF_AUTOSTATE:
 
673
                        mfnString = GetMfn();
 
674
                        mfn = mfnString.c_str();
 
675
                        if(odirs[FCEUIOD_STATES])
 
676
                        {
 
677
                                sprintf(ret,"%s"PSS"%s%s-autosave%d.fcs",odirs[FCEUIOD_STATES],FileBase,mfn,id1);
 
678
                        }
 
679
                        else
 
680
                        {
 
681
                                sprintf(ret,"%s"PSS"fcs"PSS"%s%s-autosave%d.fcs",BaseDirectory.c_str(),FileBase,mfn,id1);
 
682
                        }
 
683
                        if(stat(ret,&tmpstat)==-1)
 
684
                        {
 
685
                                if(odirs[FCEUIOD_STATES])
 
686
                                {
 
687
                                        sprintf(ret,"%s"PSS"%s%s-autosave%d.fcs",odirs[FCEUIOD_STATES],FileBase,mfn,id1);
 
688
                                }
 
689
                                else
 
690
                                {
 
691
                                        sprintf(ret,"%s"PSS"fcs"PSS"%s%s-autosave%d.fcs",BaseDirectory.c_str(),FileBase,mfn,id1);
 
692
                                }
 
693
                        }
 
694
                        break;
 
695
                case FCEUMKF_CHEAT:
 
696
                        if(odirs[FCEUIOD_CHEATS])
 
697
                                sprintf(ret,"%s"PSS"%s.cht",odirs[FCEUIOD_CHEATS],FileBase);
 
698
                        else
 
699
                                sprintf(ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory.c_str(),FileBase);
 
700
                        break;
 
701
                case FCEUMKF_IPS:
 
702
                        strcpy(ret,FCEU_MakeIpsFilename(CurrentFileBase()).c_str());
 
703
                        break;
 
704
                case FCEUMKF_GGROM:sprintf(ret,"%s"PSS"gg.rom",BaseDirectory.c_str());break;
 
705
                case FCEUMKF_FDSROM:
 
706
                        if(odirs[FCEUIOD_FDSROM])
 
707
                                sprintf(ret,"%s"PSS"disksys.rom",odirs[FCEUIOD_FDSROM]);
 
708
                        else
 
709
                                sprintf(ret,"%s"PSS"disksys.rom",BaseDirectory.c_str());
 
710
                        break;
 
711
                case FCEUMKF_PALETTE:sprintf(ret,"%s"PSS"%s.pal",BaseDirectory.c_str(),FileBase);break;
 
712
                case FCEUMKF_MOVIEGLOB:
 
713
                        //these globs use ??? because we can load multiple formats
 
714
                        if(odirs[FCEUIOD_MOVIES])
 
715
                                sprintf(ret,"%s"PSS"*.???",odirs[FCEUIOD_MOVIES]);
 
716
                        else
 
717
                                sprintf(ret,"%s"PSS"movies"PSS"*.???",BaseDirectory.c_str());
 
718
                        break;
 
719
                case FCEUMKF_MOVIEGLOB2:sprintf(ret,"%s"PSS"*.???",BaseDirectory.c_str());break;
 
720
                case FCEUMKF_STATEGLOB:
 
721
                        if(odirs[FCEUIOD_STATES])
 
722
                                sprintf(ret,"%s"PSS"%s*.fc?",odirs[FCEUIOD_STATES],FileBase);
 
723
                        else
 
724
                                sprintf(ret,"%s"PSS"fcs"PSS"%s*.fc?",BaseDirectory.c_str(),FileBase);
 
725
                        break;
 
726
        }
 
727
        
 
728
        //convert | to . for archive filenames.
 
729
        return mass_replace(ret,"|",".");
 
730
}
 
731
 
 
732
void GetFileBase(const char *f)
 
733
{
 
734
        FileBaseInfo fbi = DetermineFileBase(f);
 
735
        strcpy(FileBase,fbi.filebase.c_str());
 
736
        strcpy(FileBaseDirectory,fbi.filebasedirectory.c_str());
 
737
}
 
738
 
 
739
bool FCEU_isFileInArchive(const char *path)
 
740
{
 
741
        bool isarchive = false;
 
742
        FCEUFILE* fp = FCEU_fopen(path,0,"rb",0,0);
 
743
        if(fp) {
 
744
                isarchive = fp->isArchive();
 
745
                delete fp;
 
746
        }
 
747
        return isarchive;
 
748
}
 
749
 
 
750
 
 
751
 
 
752
void FCEUARCHIVEFILEINFO::FilterByExtension(const char** ext)
 
753
{
 
754
        if(!ext) return;
 
755
        int count = size();
 
756
        for(int i=count-1;i>=0;i--) {
 
757
                std::string fext = getExtension((*this)[i].name.c_str());
 
758
                const char** currext = ext;
 
759
                while(*currext) {
 
760
                        if(fext == *currext)
 
761
                                goto ok;
 
762
                        currext++;
 
763
                }
 
764
                this->erase(begin()+i);
 
765
        ok: ;
 
766
        }
 
767
}