menu and controls wip..
[fceu.git] / drivers / gp2x / main.c
1 /* FCE Ultra - NES/Famicom Emulator
2  *
3  * This program is free software; you can redistribute it and/or modify
4  * it under the terms of the GNU General Public License as published by
5  * the Free Software Foundation; either version 2 of the License, or
6  * (at your option) any later version.
7  *
8  * This program is distributed in the hope that it will be useful,
9  * but WITHOUT ANY WARRANTY; without even the implied warranty of
10  * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
11  * GNU General Public License for more details.
12  *
13  * You should have received a copy of the GNU General Public License
14  * along with this program; if not, write to the Free Software
15  * Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
16  */
17
18
19 #include <unistd.h>
20 #include <sys/types.h>
21 #include <signal.h>
22 #include <sys/time.h>
23 #include <sys/stat.h>
24 #include <string.h>
25 #include <strings.h>
26 #include <errno.h>
27 #include <stdio.h>
28 #include <stdlib.h>
29
30 #include "main.h"
31 #include "throttle.h"
32 #include "menu.h"
33 #include "gp2x.h"
34
35 #include "../common/config.h"
36 #include "../common/args.h"
37 #include "../common/unixdsp.h"
38 #include "../common/cheat.h"
39
40 #include "dface.h"
41
42 // just for printing some iNES info for user..
43 #include "../../fce.h"
44 #include "../../ines.h"
45
46 // internals
47 extern char lastLoadedGameName[2048];
48 extern uint8 Exit; // exit emu loop flag
49 void CloseGame(void);
50
51 FCEUGI *fceugi = NULL;
52 static int ntsccol=0,ntschue=-1,ntsctint=-1;
53 int soundvol=70;
54 int inited=0;
55
56 int srendlinev[2]={0,0};
57 int erendlinev[2]={239,239};
58 int srendline,erendline;
59
60
61 static char BaseDirectory[2048];
62
63 int eoptions=0;
64
65 static void DriverKill(void);
66 static int DriverInitialize(void);
67
68 static int gametype;
69 #include "input.c"
70
71 static void ParseGI(FCEUGI *gi)
72 {
73  gametype=gi->type;
74
75  InputType[0]=UsrInputType[0];
76  InputType[1]=UsrInputType[1];
77  InputTypeFC=UsrInputTypeFC;
78
79  if(gi->input[0]>=0)
80   InputType[0]=gi->input[0];
81  if(gi->input[1]>=0)
82   InputType[1]=gi->input[1];
83  if(gi->inputfc>=0)
84   InputTypeFC=gi->inputfc;
85  FCEUI_GetCurrentVidSystem(&srendline,&erendline);
86 }
87
88 void FCEUD_PrintError(char *s)
89 {
90  puts(s);
91 }
92
93 static char *cpalette=0;
94 static void LoadCPalette(void)
95 {
96  char tmpp[192];
97  FILE *fp;
98
99  if(!(fp=fopen(cpalette,"rb")))
100  {
101   printf(" Error loading custom palette from file: %s\n",cpalette);
102   return;
103  }
104  fread(tmpp,1,192,fp);
105  FCEUI_SetPaletteArray((uint8 *)tmpp);
106  fclose(fp);
107 }
108
109 static CFGSTRUCT fceuconfig[]={
110         AC(soundvol),
111         ACS(cpalette),
112         AC(ntsctint),
113         AC(ntschue),
114         AC(ntsccol),
115         AC(UsrInputTypeFC),
116         ACA(UsrInputType),
117         AC(powerpadside),
118         AC(powerpadsc),
119         AC(eoptions),
120         ACA(srendlinev),
121         ACA(erendlinev),
122         ACA(lastLoadedGameName),
123         ADDCFGSTRUCT(DriverConfig),
124         ENDCFGSTRUCT
125 };
126
127 void SaveConfig(const char *name)
128 {
129         char tdir[2048];
130         if (name)
131              sprintf(tdir,"%s"PSS"cfg"PSS"%s.cfg",BaseDirectory,name);
132         else sprintf(tdir,"%s"PSS"fceu2.cfg",BaseDirectory);
133         DriverInterface(DES_GETNTSCTINT,&ntsctint);
134         DriverInterface(DES_GETNTSCHUE,&ntschue);
135         SaveFCEUConfig(tdir,fceuconfig);
136 }
137
138 static void LoadConfig(const char *name)
139 {
140         char tdir[2048];
141         if (name)
142              sprintf(tdir,"%s"PSS"cfg"PSS"%s.cfg",BaseDirectory,name);
143         else sprintf(tdir,"%s"PSS"fceu2.cfg",BaseDirectory);
144         LoadFCEUConfig(tdir,fceuconfig);
145         if(ntsctint>=0) DriverInterface(DES_SETNTSCTINT,&ntsctint);
146         if(ntschue>=0) DriverInterface(DES_SETNTSCHUE,&ntschue);
147 }
148
149 static void CreateDirs(void)
150 {
151  char *subs[]={"fcs","snaps","gameinfo","sav","cheats","cfg"};
152  char tdir[2048];
153  int x;
154
155  mkdir(BaseDirectory,S_IRWXU);
156  for(x=0;x<sizeof(subs)/sizeof(subs[0]);x++)
157  {
158   sprintf(tdir,"%s"PSS"%s",BaseDirectory,subs[x]);
159   mkdir(tdir,S_IRWXU);
160  }
161 }
162
163 static void SetSignals(void (*t)(int))
164 {
165   int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
166   int x;
167   for(x=0;x<11;x++)
168    signal(sigs[x],t);
169 }
170
171 static void CloseStuff(int signum)
172 {
173         DriverKill();
174         printf("\nSignal %d has been caught and dealt with...\n",signum);
175         switch(signum)
176         {
177          case SIGINT:printf("How DARE you interrupt me!\n");break;
178          case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
179          case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
180          case SIGPIPE:printf("The pipe has broken!  Better watch out for floods...\n");break;
181          case SIGSEGV:printf("Iyeeeeeeeee!!!  A segmentation fault has occurred.  Have a fluffy day.\n");break;
182          /* So much SIGBUS evil. */
183          #ifdef SIGBUS
184          #if(SIGBUS!=SIGSEGV)
185          case SIGBUS:printf("I told you to be nice to the driver.\n");break;
186          #endif
187          #endif
188          case SIGFPE:printf("Those darn floating points.  Ne'er know when they'll bite!\n");break;
189          case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
190          case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
191          case SIGUSR1:
192          case SIGUSR2:printf("Killing your processes is not nice.\n");break;
193         }
194         exit(1);
195 }
196
197 static int DoArgs(int argc, char *argv[])
198 {
199         static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"};
200         static int cortabi[5]={SI_NONE,SI_GAMEPAD,
201                                SI_ZAPPER,SI_POWERPADA,SI_ARKANOID};
202         static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"};
203         static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
204                                  SIFC_4PLAYER,SIFC_FKB};
205
206         int x, ret;
207         static char *inputa[2]={0,0};
208         static char *fcexp=0;
209         static int docheckie[4];
210
211         static ARGPSTRUCT FCEUArgs[]={
212          {"-soundvol",0,&soundvol,0},
213          {"-cpalette",0,&cpalette,0x4001},
214
215          {"-ntsccol",0,&ntsccol,0},
216          {"-pal",&docheckie[0],0,0},
217          {"-input1",0,&inputa[0],0x4001},{"-input2",0,&inputa[1],0x4001},
218          {"-fcexp",0,&fcexp,0x4001},
219
220          {"-gg",&docheckie[1],0,0},
221          {"-no8lim",0,&eoptions,0x8001},
222          {"-subase",0,&eoptions,0x8002},
223          {"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
224          {"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
225          {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
226          {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
227          {"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
228          {"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
229          {0,(void *)DriverArgs,0,0},
230          {0,0,0,0}
231         };
232
233         memset(docheckie,0,sizeof(docheckie));
234         ret=ParseArguments(argc, argv, FCEUArgs);
235         if(cpalette)
236         {
237          if(cpalette[0]=='0')
238           if(cpalette[1]==0)
239           {
240            free(cpalette);
241            cpalette=0;
242           }
243         }
244         if(docheckie[0])
245          FCEUI_SetVidSystem(1);
246         if(docheckie[1])
247          FCEUI_SetGameGenie(1);
248         FCEUI_DisableSpriteLimitation(1);
249         FCEUI_SaveExtraDataUnderBase(eoptions&2);
250         FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
251
252         for(x=0;x<2;x++)
253         {
254          if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
255          if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
256         }
257
258         printf("main() setrendered lines: %d, %d, %d, %d\n",srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
259         printf("main() clip sides %d\n", eoptions&EO_CLIPSIDES);
260         srendlinev[0]=0;
261         FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
262         FCEUI_SetRenderedLines(0,erendlinev[0],srendlinev[1],erendlinev[1]);
263         FCEUI_SetSoundVolume(soundvol);
264         DriverInterface(DES_NTSCCOL,&ntsccol);
265         DoDriverArgs();
266
267         if(fcexp)
268         {
269          int y;
270          for(y=0;y<5;y++)
271          {
272           if(!strncmp(fccortab[y],fcexp,8))
273           {
274            UsrInputTypeFC=fccortabi[y];
275            break;
276           }
277          }
278          free(fcexp);
279         }
280         for(x=0;x<2;x++)
281         {
282          int y;
283
284          if(!inputa[x])
285           continue;
286
287          for(y=0;y<5;y++)
288          {
289           if(!strncmp(cortab[y],inputa[x],8))
290           {
291            UsrInputType[x]=cortabi[y];
292            if(y==3)
293            {
294             powerpadside&=~(1<<x);
295             powerpadside|=((((inputa[x][8])-'a')&1)^1)<<x;
296            }
297            free(inputa[x]);
298           }
299          }
300         }
301         return ret;
302 }
303
304
305 #include "usage.h"
306
307 int CLImain(int argc, char *argv[])
308 {
309         int last_arg_parsed;
310         /* TODO if(argc<=1)
311         {
312          ShowUsage(argv[0]);
313          return 1;
314         }*/
315
316         if(!DriverInitialize())
317         {
318          return 1;
319         }
320
321         if(!FCEUI_Initialize())
322          return(1);
323         GetBaseDirectory(BaseDirectory);
324         FCEUI_SetBaseDirectory(BaseDirectory);
325         lastLoadedGameName[0] = 0;
326
327         CreateDirs();
328         LoadConfig(NULL);
329         last_arg_parsed=DoArgs(argc-1,&argv[1]);
330         gp2x_opt_setup();
331         gp2x_cpuclock_update();
332         if(cpalette)
333          LoadCPalette();
334         if(InitSound())
335          inited|=1;
336
337         if (argc > 1 && !last_arg_parsed)
338         {
339          strncpy(lastLoadedGameName, argv[argc-1], sizeof(lastLoadedGameName));
340          lastLoadedGameName[sizeof(lastLoadedGameName)-1] = 0;
341          Exit = 0;
342         }
343         else
344         {
345          Exit = 1;
346         }
347
348         while (1)
349         {
350          if(!Exit)
351          {
352           if (fceugi)
353            CloseGame();
354           fceugi=FCEUI_LoadGame(lastLoadedGameName);
355           if (fceugi)
356           {
357            LoadConfig(lastLoadedGameName);
358            ParseGI(fceugi);
359            //RefreshThrottleFPS();
360            InitOtherInput();
361
362            // additional print for gpfce
363            // TODO: handlers for other formats then iNES
364            {
365           int MapperNo;
366           iNES_HEADER *head = iNESGetHead();
367           MapperNo = (head->ROM_type>>4);
368           MapperNo|=(head->ROM_type2&0xF0);
369           FCEU_DispMessage("%s, Mapper: %d%s%s", PAL?"PAL":"NTSC", MapperNo, (head->ROM_type&2)?", BB":"", (head->ROM_type&4)?", T":"");
370            }
371           }
372           else
373            strcpy(menuErrorMsg, "failed to load ROM");
374          }
375          if(Exit || !fceugi)
376          {
377           int ret;
378           ret = gp2x_menu_do();
379           if (ret == 1) break;          // exit emu
380           if (ret == 2) {               // reload ROM
381            Exit = 0;
382            continue;
383           }
384          }
385
386          gp2x_video_changemode(Settings.scaling == 3 ? 15 : 8);
387          gp2x_video_RGB_setscaling(0, 320, 240);
388          gp2x_start_sound(22050, 16, 0);
389          FCEUI_Emulate();
390         }
391
392         if (fceugi)
393          CloseGame();
394
395         DriverKill();
396         return 0;
397 }
398
399 static int DriverInitialize(void)
400 {
401    SetSignals((void *)CloseStuff);
402
403    if(InitJoysticks())
404     inited|=2;
405    if(!InitVideo()) return 0;
406    inited|=4;
407    if(!InitKeyboard()) return 0;
408    inited|=8;
409    return 1;
410 }
411
412 static void DriverKill(void)
413 {
414  SaveConfig(NULL);
415  SetSignals(SIG_IGN);
416
417  if(inited&2)
418   KillJoysticks();
419  if(inited&8)
420   KillKeyboard();
421  if(inited&4)
422   KillVideo();
423  if(inited&1)
424   KillSound();
425  if(inited&16)
426   KillMouse();
427  inited=0;
428 }
429
430 void FCEUD_Update(uint8 *xbuf, int16 *Buffer, int Count)
431 {
432  if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
433   SpeedThrottle();
434  BlitScreen(xbuf);
435  if(Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
436   WriteSound(Buffer,Count);
437  FCEUD_UpdateInput();
438 }
439