eabb5edd6067735ac4007094a3f579816c9897c7
[fceu.git] / general.c
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 <stdlib.h>
23 #include <string.h>
24 #include <stdarg.h>
25
26 #include <sys/types.h>
27 #include <sys/stat.h>
28 #include <unistd.h>
29
30 #include "types.h"
31 #include "fce.h"
32
33 #include "general.h"
34 #include "state.h"
35 #include "movie.h"
36
37 #include "driver.h"
38
39 #include "md5.h"
40 #include "svga.h"
41
42 static char BaseDirectory[2048];
43 char FileBase[2048];
44 static char FileExt[2048];      /* Includes the . character, as in ".nes" */
45
46 static char FileBaseDirectory[2048];
47
48 void FCEUI_SetBaseDirectory(char *dir)
49 {
50  strncpy(BaseDirectory,dir,2047);
51  BaseDirectory[2047]=0;
52 }
53
54 static char *odirs[FCEUIOD__COUNT]={0,0,0,0,0};     // odirs, odors. ^_^
55
56 void FCEUI_SetDirOverride(int which, char *n)
57 {
58 //      FCEU_PrintError("odirs[%d]=%s->%s", which, odirs[which], n);
59 if(which < FCEUIOD__COUNT)
60  odirs[which]=n;
61
62 #if 0
63  if(FCEUGameInfo)  /* Rebuild cache of present states/movies. */
64  {
65   if(which==FCEUIOD_STATE)
66    FCEUSS_CheckStates();
67   else if(which == FCEUIOD_MISC)
68    FCEUMOV_CheckMovies();
69  }
70 #endif
71 }
72
73 #ifndef HAVE_ASPRINTF
74 static int asprintf(char **strp, const char *fmt, ...)
75 {
76  va_list ap;
77  int ret;
78
79  va_start(ap,fmt);
80  if(!(*strp=malloc(2048)))
81   return(0);
82  ret=vsnprintf(*strp,2048,fmt,ap);
83  va_end(ap);
84  return(ret);
85 }
86 #endif
87
88 char* FCEU_GetPath(int type)
89 {
90  char *ret=0;
91  switch(type)
92  {
93   case FCEUMKF_STATE:if(odirs[FCEUIOD_STATE])
94                       ret=strdup(odirs[FCEUIOD_STATE]);
95                      else
96                       asprintf(&ret,"%s"PSS"movie",BaseDirectory);
97                      break;
98   case FCEUMKF_MOVIE:if(odirs[FCEUIOD_MISC])
99                       ret=strdup(odirs[FCEUIOD_MISC]);
100                      else
101                       asprintf(&ret,"%s"PSS"movie",BaseDirectory);
102                      break;
103  }
104  return(ret);
105 }
106
107 char *FCEU_MakePath(int type, const char* filebase)
108 {
109  char *ret=0;
110
111  switch(type)
112  {
113   case FCEUMKF_MOVIE:if(odirs[FCEUIOD_MISC])
114                       asprintf(&ret,"%s"PSS"%s",odirs[FCEUIOD_MISC],filebase);
115                      else
116                       asprintf(&ret,"%s"PSS"movie"PSS"%s",BaseDirectory,filebase);
117                      break;
118  }
119  return(ret);
120 }
121
122 char *FCEU_MakeFName(int type, int id1, char *cd1)
123 {
124  char *ret=0;
125  struct stat tmpstat;
126
127  switch(type)
128  {
129   case FCEUMKF_NPTEMP: asprintf(&ret,"%s"PSS"m590plqd94fo.tmp",BaseDirectory);break;
130   case FCEUMKF_MOVIE:if(id1>=0)
131                                          {
132                           if(odirs[FCEUIOD_MISC])
133                        asprintf(&ret,"%s"PSS"%s.%d.fcm",odirs[FCEUIOD_MISC],FileBase,id1);
134                       else
135                        asprintf(&ret,"%s"PSS"movie"PSS"%s.%d.fcm",BaseDirectory,FileBase,id1);
136                       if(stat(ret,&tmpstat)==-1)
137                       {
138                        if(odirs[FCEUIOD_MISC])
139                         asprintf(&ret,"%s"PSS"%s.%d.fcm",odirs[FCEUIOD_MISC],FileBase,id1);
140                        else
141                         asprintf(&ret,"%s"PSS"movie"PSS"%s.%d.fcm",BaseDirectory,FileBase,id1);
142                       }
143                                          }
144                                          else
145                                          {
146                                           if(odirs[FCEUIOD_MISC])
147                                            asprintf(&ret,"%s"PSS"%s.fcm",odirs[FCEUIOD_MISC],FileBase);
148                                           else
149                                            asprintf(&ret,"%s"PSS"movie"PSS"%s.fcm",BaseDirectory,FileBase);
150                                          }
151                      break;
152   case FCEUMKF_STATE:if(odirs[FCEUIOD_STATE])
153                                          {
154                       asprintf(&ret,"%s"PSS"%s.fc%d",odirs[FCEUIOD_STATE],FileBase,id1);
155 //                                        FCEU_PrintError("A");
156                                          }
157                      else
158                                          {
159                       asprintf(&ret,"%s"PSS"fcs"PSS"%s.fc%d",BaseDirectory,FileBase,id1);
160 //                                        FCEU_PrintError("B");
161                                          }
162                      if(stat(ret,&tmpstat)==-1)
163                      {
164                       if(odirs[FCEUIOD_STATE])
165                           {
166                        asprintf(&ret,"%s"PSS"%s.fc%d",odirs[FCEUIOD_STATE],FileBase,id1);
167 //                                        FCEU_PrintError("C");
168                           }
169                       else
170                                           {
171                        asprintf(&ret,"%s"PSS"fcs"PSS"%s.fc%d",BaseDirectory,FileBase,id1);
172 //                                        FCEU_PrintError("D");
173                                           }
174                      }
175                      break;
176   case FCEUMKF_SNAP:
177                     if(FSettings.SnapName)
178                     {
179                      if(odirs[FCEUIOD_SNAPS])
180                       asprintf(&ret,"%s"PSS"%s-%d.%s",odirs[FCEUIOD_SNAPS],FileBase,id1,cd1);
181                      else
182                       asprintf(&ret,"%s"PSS"snaps"PSS"%s-%d.%s",BaseDirectory,FileBase,id1,cd1);
183                     }
184                     else
185                     {
186                      if(odirs[FCEUIOD_SNAPS])
187                       asprintf(&ret,"%s"PSS"%d.%s",odirs[FCEUIOD_SNAPS],id1,cd1);
188                      else
189                       asprintf(&ret,"%s"PSS"snaps"PSS"%d.%s",BaseDirectory,id1,cd1);
190                     }
191                     break;
192   case FCEUMKF_FDS:if(odirs[FCEUIOD_NV])
193                     asprintf(&ret,"%s"PSS"%s.fds",odirs[FCEUIOD_NV],FileBase);
194                    else
195                     asprintf(&ret,"%s"PSS"sav"PSS"%s.fds",BaseDirectory,FileBase);
196                    break;
197   case FCEUMKF_SAV:if(odirs[FCEUIOD_NV])
198                     asprintf(&ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
199                    else
200                     asprintf(&ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory,FileBase,cd1);
201                    if(stat(ret,&tmpstat)==-1)
202                    {
203                     if(odirs[FCEUIOD_NV])
204                      asprintf(&ret,"%s"PSS"%s.%s",odirs[FCEUIOD_NV],FileBase,cd1);
205                     else
206                      asprintf(&ret,"%s"PSS"sav"PSS"%s.%s",BaseDirectory,FileBase,cd1);
207                    }
208                    break;
209   case FCEUMKF_CHEAT:
210                      if(odirs[FCEUIOD_CHEATS])
211                       asprintf(&ret,"%s"PSS"%s.cht",odirs[FCEUIOD_CHEATS],FileBase);
212                      else
213                       asprintf(&ret,"%s"PSS"cheats"PSS"%s.cht",BaseDirectory,FileBase);
214                      break;
215   case FCEUMKF_IPS:  asprintf(&ret,"%s"PSS"%s%s.ips",FileBaseDirectory,FileBase,FileExt);
216                      break;
217   case FCEUMKF_GGROM:asprintf(&ret,"%s"PSS"gg.rom",BaseDirectory);break;
218   case FCEUMKF_FDSROM:asprintf(&ret,"%s"PSS"disksys.rom",BaseDirectory);break;
219   case FCEUMKF_PALETTE:
220                        if(odirs[FCEUIOD_MISC])
221                         asprintf(&ret,"%s"PSS"%s.pal",odirs[FCEUIOD_MISC],FileBase);
222                        else
223                         asprintf(&ret,"%s"PSS"%s.pal",BaseDirectory,FileBase);
224                        break;
225   case FCEUMKF_MOVIEGLOB:
226                      if(odirs[FCEUIOD_MISC])
227 //                      asprintf(&ret,"%s"PSS"%s*.fcm",odirs[FCEUIOD_MISC],FileBase);
228                       asprintf(&ret,"%s"PSS"*.???",odirs[FCEUIOD_MISC]);
229                      else
230 //                      asprintf(&ret,"%s"PSS"fcs"PSS"%s*.fcm",BaseDirectory,FileBase);
231                       asprintf(&ret,"%s"PSS"movie"PSS"*.???",BaseDirectory);
232                      break;
233   case FCEUMKF_MOVIEGLOB2:
234                       asprintf(&ret,"%s"PSS"*.???",BaseDirectory);
235                      break;
236   case FCEUMKF_STATEGLOB:
237                      if(odirs[FCEUIOD_STATE])
238                       asprintf(&ret,"%s"PSS"%s*.fc?",odirs[FCEUIOD_STATE],FileBase);
239                      else
240                       asprintf(&ret,"%s"PSS"fcs"PSS"%s*.fc?",BaseDirectory,FileBase);
241                      break;
242  }
243  return(ret);
244 }
245
246 void GetFileBase(const char *f)
247 {
248         const char *tp1,*tp3;
249
250  #if PSS_STYLE==4
251      tp1=((char *)strrchr(f,':'));
252  #elif PSS_STYLE==1
253      tp1=((char *)strrchr(f,'/'));
254  #else
255      tp1=((char *)strrchr(f,'\\'));
256   #if PSS_STYLE!=3
257      tp3=((char *)strrchr(f,'/'));
258      if(tp1<tp3) tp1=tp3;
259   #endif
260  #endif
261      if(!tp1)
262      {
263       tp1=f;
264       strcpy(FileBaseDirectory,".");
265      }
266      else
267      {
268       memcpy(FileBaseDirectory,f,tp1-f);
269       FileBaseDirectory[tp1-f]=0;
270       tp1++;
271      }
272
273      if(((tp3=strrchr(f,'.'))!=NULL) && (tp3>tp1))
274      {
275       memcpy(FileBase,tp1,tp3-tp1);
276       FileBase[tp3-tp1]=0;
277       strcpy(FileExt,tp3);
278      }
279      else
280      {
281       strcpy(FileBase,tp1);
282       FileExt[0]=0;
283      }
284 }
285
286 uint32 uppow2(uint32 n)
287 {
288  int x;
289
290  for(x=31;x>=0;x--)
291   if(n&(1<<x))
292   {
293    if((1<<x)!=n)
294     return(1<<(x+1));
295    break;
296   }
297  return n;
298 }
299