cli added for debug
[fceu.git] / drivers / cli / 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
41 #include "../common/config.h"
42 #include "../common/args.h"
43 #include "../common/unixdsp.h"
44 #include "../common/cheat.h"
45
46 #include "dface.h"
47
48 static int ntsccol=0,ntschue=-1,ntsctint=-1;
49 /*static*/ int soundvol=100;
50 static int inited=0;
51
52 int srendlinev[2]={8,0};
53 int erendlinev[2]={239,239};
54 int srendline,erendline;
55
56
57 static char BaseDirectory[2048];
58
59 int eoptions=0;
60
61 static void DriverKill(void);
62 static int DriverInitialize(void);
63
64 static int gametype;
65 #include "input.c"
66
67 static void ParseGI(FCEUGI *gi)
68 {
69  gametype=gi->type;
70
71  InputType[0]=UsrInputType[0];
72  InputType[1]=UsrInputType[1];
73  InputTypeFC=UsrInputTypeFC;
74
75  if(gi->input[0]>=0)
76   InputType[0]=gi->input[0];
77  if(gi->input[1]>=0)
78   InputType[1]=gi->input[1];
79  if(gi->inputfc>=0)
80   InputTypeFC=gi->inputfc;
81  FCEUI_GetCurrentVidSystem(&srendline,&erendline);
82 }
83
84 void FCEUD_PrintError(char *s)
85 {
86  puts(s);
87 }
88
89 static char *cpalette=0;
90 static void LoadCPalette(void)
91 {
92  uint8 tmpp[192];
93  FILE *fp;
94
95  if(!(fp=fopen(cpalette,"rb")))
96  {
97   printf(" Error loading custom palette from file: %s\n",cpalette);
98   return;
99  }
100  fread(tmpp,1,192,fp);
101  FCEUI_SetPaletteArray(tmpp);
102  fclose(fp);
103 }
104
105 static CFGSTRUCT fceuconfig[]={
106         AC(soundvol),
107         ACS(cpalette),
108         AC(ntsctint),
109         AC(ntschue),
110         AC(ntsccol),
111         AC(UsrInputTypeFC),
112         ACA(UsrInputType),
113         AC(powerpadside),
114         AC(powerpadsc),
115         AC(eoptions),
116         ACA(srendlinev),
117         ACA(erendlinev),
118         ADDCFGSTRUCT(DriverConfig),
119         ENDCFGSTRUCT
120 };
121
122 static void SaveConfig(void)
123 {
124         char tdir[2048];
125         sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
126         DriverInterface(DES_GETNTSCTINT,&ntsctint);
127         DriverInterface(DES_GETNTSCHUE,&ntschue);
128         SaveFCEUConfig(tdir,fceuconfig);
129 }
130
131 static void LoadConfig(void)
132 {
133         char tdir[2048];
134         sprintf(tdir,"%s"PSS"fceu.cfg",BaseDirectory);
135         LoadFCEUConfig(tdir,fceuconfig);
136         if(ntsctint>=0) DriverInterface(DES_SETNTSCTINT,&ntsctint);
137         if(ntschue>=0) DriverInterface(DES_SETNTSCHUE,&ntschue);
138 }
139
140 static void CreateDirs(void)
141 {
142  char *subs[5]={"fcs","snaps","gameinfo","sav","cheats"};
143  char tdir[2048];
144  int x;
145
146  mkdir(BaseDirectory,S_IRWXU);
147  for(x=0;x<5;x++)
148  {
149   sprintf(tdir,"%s"PSS"%s",BaseDirectory,subs[x]);
150   mkdir(tdir,S_IRWXU);
151  }
152 }
153
154 static void SetSignals(void (*t)(int))
155 {
156   int sigs[11]={SIGINT,SIGTERM,SIGHUP,SIGPIPE,SIGSEGV,SIGFPE,SIGKILL,SIGALRM,SIGABRT,SIGUSR1,SIGUSR2};
157   int x;
158   for(x=0;x<11;x++)
159    signal(sigs[x],t);
160 }
161
162 static void CloseStuff(int signum)
163 {
164         DriverKill();
165         printf("\nSignal %d has been caught and dealt with...\n",signum);
166         switch(signum)
167         {
168          case SIGINT:printf("How DARE you interrupt me!\n");break;
169          case SIGTERM:printf("MUST TERMINATE ALL HUMANS\n");break;
170          case SIGHUP:printf("Reach out and hang-up on someone.\n");break;
171          case SIGPIPE:printf("The pipe has broken!  Better watch out for floods...\n");break;
172          case SIGSEGV:printf("Iyeeeeeeeee!!!  A segmentation fault has occurred.  Have a fluffy day.\n");break;
173          /* So much SIGBUS evil. */
174          #ifdef SIGBUS
175          #if(SIGBUS!=SIGSEGV)
176          case SIGBUS:printf("I told you to be nice to the driver.\n");break;
177          #endif
178          #endif
179          case SIGFPE:printf("Those darn floating points.  Ne'er know when they'll bite!\n");break;
180          case SIGALRM:printf("Don't throw your clock at the meowing cats!\n");break;
181          case SIGABRT:printf("Abort, Retry, Ignore, Fail?\n");break;
182          case SIGUSR1:
183          case SIGUSR2:printf("Killing your processes is not nice.\n");break;
184         }
185         exit(1);
186 }
187
188 static void DoArgs(int argc, char *argv[])
189 {
190         static char *cortab[5]={"none","gamepad","zapper","powerpad","arkanoid"};
191         static int cortabi[5]={SI_NONE,SI_GAMEPAD,
192                                SI_ZAPPER,SI_POWERPADA,SI_ARKANOID};
193         static char *fccortab[5]={"none","arkanoid","shadow","4player","fkb"};
194         static int fccortabi[5]={SIFC_NONE,SIFC_ARKANOID,SIFC_SHADOW,
195                                  SIFC_4PLAYER,SIFC_FKB};
196
197         int x;
198         static char *inputa[2]={0,0};
199         static char *fcexp=0;
200         static int docheckie[4];
201
202         static ARGPSTRUCT FCEUArgs[]={
203          {"-soundvol",0,&soundvol,0},
204          {"-cpalette",0,&cpalette,0x4001},
205
206          {"-ntsccol",0,&ntsccol,0},
207          {"-pal",&docheckie[0],0,0},
208          {"-input1",0,&inputa[0],0x4001},{"-input2",0,&inputa[1],0x4001},
209          {"-fcexp",0,&fcexp,0x4001},
210
211          {"-gg",&docheckie[1],0,0},
212          {"-no8lim",0,&eoptions,0x8001},
213          {"-subase",0,&eoptions,0x8002},
214          {"-snapname",0,&eoptions,0x8000|EO_SNAPNAME},
215          {"-nofs",0,&eoptions,0x8000|EO_NOFOURSCORE},
216          {"-clipsides",0,&eoptions,0x8000|EO_CLIPSIDES},
217          {"-nothrottle",0,&eoptions,0x8000|EO_NOTHROTTLE},
218          {"-slstart",0,&srendlinev[0],0},{"-slend",0,&erendlinev[0],0},
219          {"-slstartp",0,&srendlinev[1],0},{"-slendp",0,&erendlinev[1],0},
220          {0,(void *)DriverArgs,0,0},
221          {0,0,0,0}
222         };
223
224         memset(docheckie,0,sizeof(docheckie));
225         ParseArguments(argc, argv, FCEUArgs);
226         if(cpalette)
227         {
228          if(cpalette[0]=='0')
229           if(cpalette[1]==0)
230           {
231            free(cpalette);
232            cpalette=0;
233           }
234         }
235         if(docheckie[0])
236          FCEUI_SetVidSystem(1);
237         if(docheckie[1])
238          FCEUI_SetGameGenie(1);
239
240         FCEUI_DisableSpriteLimitation(eoptions&1);
241         FCEUI_SaveExtraDataUnderBase(eoptions&2);
242         FCEUI_SetSnapName(eoptions&EO_SNAPNAME);
243
244         for(x=0;x<2;x++)
245         {
246          if(srendlinev[x]<0 || srendlinev[x]>239) srendlinev[x]=0;
247          if(erendlinev[x]<srendlinev[x] || erendlinev[x]>239) erendlinev[x]=239;
248         }
249
250         FCEUI_SetRenderedLines(srendlinev[0],erendlinev[0],srendlinev[1],erendlinev[1]);
251         FCEUI_SetSoundVolume(soundvol);
252         //DriverInterface(DES_NTSCCOL,&ntsccol);
253         DoDriverArgs();
254
255         if(fcexp)
256         {
257          int y;
258          for(y=0;y<5;y++)
259          {
260           if(!strncmp(fccortab[y],fcexp,8))
261           {
262            UsrInputTypeFC=fccortabi[y];
263            break;
264           }
265          }
266          free(fcexp);
267         }
268         for(x=0;x<2;x++)
269         {
270          int y;
271
272          if(!inputa[x])
273           continue;
274
275          for(y=0;y<5;y++)
276          {
277           if(!strncmp(cortab[y],inputa[x],8))
278           {
279            UsrInputType[x]=cortabi[y];
280            if(y==3)
281            {
282             powerpadside&=~(1<<x);
283             powerpadside|=((((inputa[x][8])-'a')&1)^1)<<x;
284            }
285            free(inputa[x]);
286           }
287          }
288         }
289 }
290
291 #include "usage.h"
292
293 int CLImain(int argc, char *argv[])
294 {
295         FCEUGI *tmp;
296         int ret;
297
298         if(!(ret=FCEUI_Initialize()))
299          return(1);
300         GetBaseDirectory(BaseDirectory);
301         FCEUI_SetBaseDirectory(BaseDirectory);
302
303         CreateDirs();
304         if(argc<=1)
305         {
306          ShowUsage(argv[0]);
307          return 1;
308         }
309         LoadConfig();
310         DoArgs(argc-2,&argv[1]);
311         FCEUI_SetNTSCTH(ntsccol, ntsctint, ntschue);
312         if(cpalette)
313          LoadCPalette();
314         if(InitSound())
315          inited|=1;
316
317         if(!(tmp=FCEUI_LoadGame(argv[argc-1])))
318         {
319          ret=0;
320          goto dk;
321         }
322         ParseGI(tmp);
323         RefreshThrottleFPS();
324         if(!DriverInitialize())
325         {
326          ret=0;
327          goto dk;
328         }
329         InitOtherInput();
330         FCEUI_Emulate();
331
332         dk:
333         DriverKill();
334         return(ret?0:1);
335 }
336
337 static int DriverInitialize(void)
338 {
339    SetSignals((void *)CloseStuff);
340
341    if(InitJoysticks())
342     inited|=2;
343    if(!InitVideo()) return 0;
344    inited|=4;
345    if(!InitKeyboard()) return 0;
346    inited|=8;
347    return 1;
348 }
349
350 static void DriverKill(void)
351 {
352  SaveConfig();
353  SetSignals(SIG_IGN);
354
355  if(inited&2)
356   KillJoysticks();
357  if(inited&8)
358   KillKeyboard();
359  if(inited&4)
360   KillVideo();
361  if(inited&1)
362   KillSound();
363  if(inited&16)
364   KillMouse();
365  inited=0;
366 }
367
368 void FCEUD_Update(uint8 *XBuf, int16 *Buffer, int Count)
369 {
370  if(!Count && !NoWaiting && !(eoptions&EO_NOTHROTTLE))
371   SpeedThrottle();
372  BlitScreen(XBuf);
373  if(Count)
374   WriteSound(Buffer,Count,NoWaiting);
375  FCEUD_UpdateInput();
376 }
377