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