90a55a90b7cf805cf65da19d07a0aee0d0abd731
[pcsx_rearmed.git] / maemo / main.c
1 /*
2  * (C) notaz, 2010-2011
3  *
4  * This work is licensed under the terms of the GNU GPLv2 or later.
5  * See the COPYING file in the top-level directory.
6  */
7
8 #include <stdio.h>
9 #include <string.h>
10 #include <stdarg.h>
11 #include <dlfcn.h>
12 #include <sys/stat.h>
13 #include <sys/types.h>
14 #include <unistd.h>
15 #include <signal.h>
16
17 #include "main.h"
18 #include "plugin.h"
19 #include "pcnt.h"
20 #include "menu.h"
21 #include "../libpcsxcore/misc.h"
22 #include "../plugins/cdrcimg/cdrcimg.h"
23 #include "common/plat.h"
24 #include "common/input.h"
25
26 int ready_to_go;
27 unsigned long gpuDisp;
28 char cfgfile_basename[MAXPATHLEN];
29 static char *(*real_getenv)(const char *name);
30
31 static void make_path(char *buf, size_t size, const char *dir, const char *fname)
32 {
33         if (fname)
34                 snprintf(buf, size, ".%s%s", dir, fname);
35         else
36                 snprintf(buf, size, ".%s", dir);
37 }
38 #define MAKE_PATH(buf, dir, fname) \
39         make_path(buf, sizeof(buf), dir, fname)
40
41 static void create_profile_dir(const char *directory) {
42         char path[MAXPATHLEN];
43
44         MAKE_PATH(path, directory, NULL);
45         mkdir(path, S_IRWXU | S_IRWXG);
46 }
47
48 static void CheckSubDir() {
49         // make sure that ~/.pcsx exists
50         create_profile_dir(PCSX_DOT_DIR);
51
52         create_profile_dir(BIOS_DIR);
53         create_profile_dir(MEMCARD_DIR);
54         create_profile_dir(STATES_DIR);
55         create_profile_dir(PLUGINS_DIR);
56         create_profile_dir(PLUGINS_CFG_DIR);
57         create_profile_dir(CHEATS_DIR);
58         create_profile_dir(PATCHES_DIR);
59         create_profile_dir(PCSX_DOT_DIR "cfg");
60 }
61
62 void set_cd_image(const char *fname)
63 {
64         const char *ext;
65         int len;
66         
67         len = strlen(fname);
68         ext = fname;
69         if (len > 2)
70                 ext = fname + len - 2;
71
72         if (strcasecmp(ext, ".z") == 0) {
73                 SetIsoFile(NULL);
74                 cdrcimg_set_fname(fname);
75                 strcpy(Config.Cdr, "builtin_cdrcimg");
76         } else {
77                 SetIsoFile(fname);
78                 strcpy(Config.Cdr, "builtin_cdr");
79         }
80 }
81
82 // from softgpu plugin
83 extern int iUseDither;
84 extern int UseFrameSkip;
85 extern int UseFrameLimit;
86 extern uint32_t dwActFixes;
87 extern float fFrameRateHz;
88 extern int dwFrameRateTicks;
89
90 // sound plugin
91 extern int iUseReverb;
92 extern int iUseInterpolation;
93 extern int iXAPitch;
94 extern int iSPUIRQWait;
95 extern int iUseTimer;
96
97 static void ChangeWorkingDirectory(char *exe)
98 {
99   s8 exepath[1024];
100   s8* s;
101   sprintf(exepath, "%s", exe);
102         s = strrchr(exepath, '/');
103         if (s != NULL) {
104                 *s = '\0';
105                 chdir(exepath);
106         }
107 }
108
109 int main(int argc, char *argv[])
110 {
111         ChangeWorkingDirectory("c");
112         char file[MAXPATHLEN] = "";
113         char path[MAXPATHLEN];
114         const char *cdfile = NULL;
115         int loadst = 0;
116         void *tmp;
117         int i;
118
119         tmp = dlopen("/lib/libdl.so.2", RTLD_LAZY);
120         if (tmp == NULL)
121                 tmp = dlopen("/lib32/libdl.so.2", RTLD_LAZY);
122         if (tmp != NULL)
123                 real_getenv = dlsym(tmp, "getenv");
124         if (real_getenv == NULL) {
125                 fprintf(stderr, "%s\n", dlerror());
126                 return 1;
127         }
128         dlclose(tmp);
129
130         // what is the name of the config file?
131         // it may be redefined by -cfg on the command line
132         strcpy(cfgfile_basename, "pcsx.cfg");
133
134         emuLog = stdout;
135         SetIsoFile(NULL);
136
137         memset(&Config, 0, sizeof(PcsxConfig));
138         strcpy(Config.Net, "Disabled");
139
140         CheckSubDir();
141
142         MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd");
143         MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd");
144         strcpy(Config.Bios, "HLE");
145         strcpy(Config.BiosDir, "/home/user/MyDocs");
146
147
148         Config.PsxAuto = 1;
149         
150         strcpy(Config.PluginsDir, "/opt/maemo/usr/games/plugins");
151         strcpy(Config.Gpu, "builtin_gpu");
152         strcpy(Config.Spu, "builtin_spu");
153         strcpy(Config.Cdr, "builtin_cdr");
154         strcpy(Config.Pad1, "builtin_pad");
155         strcpy(Config.Pad2, "builtin_pad");
156         
157         
158         // read command line options
159         for (i = 1; i < argc; i++) {
160                      if (!strcmp(argv[i], "-psxout")) Config.PsxOut = 1;
161                 else if (!strcmp(argv[i], "-load")) loadst = atol(argv[++i]);
162                 else if (!strcmp(argv[i], "-cdfile")) {
163                         char isofilename[MAXPATHLEN];
164
165                         if (i+1 >= argc) break;
166                         strncpy(isofilename, argv[++i], MAXPATHLEN);
167                         if (isofilename[0] != '/') {
168                                 getcwd(path, MAXPATHLEN);
169                                 if (strlen(path) + strlen(isofilename) + 1 < MAXPATHLEN) {
170                                         strcat(path, "/");
171                                         strcat(path, isofilename);
172                                         strcpy(isofilename, path);
173                                 } else
174                                         isofilename[0] = 0;
175                         }
176
177                         cdfile = isofilename;
178                 }
179                 else if (!strcmp(argv[i],"-frameskip")){
180                 
181                 int tv_reg=atol(argv[++i]);
182                 if (tv_reg>0){
183                 UseFrameSkip=1;
184                 fFrameRateHz = (tv_reg==1)?50.0f:  59.94f;
185                 dwFrameRateTicks = (100000*100 / (unsigned long)(fFrameRateHz*100));
186                 }
187                 }
188                 else if (!strcmp(argv[i],"-sputhreaded")){
189                         iUseTimer=1;
190                 }
191                 else if (!strcmp(argv[i],"-nosound")){
192                                 strcpy(Config.Spu, "spunull.so");
193                 }
194                 else if(!strcmp(argv[i], "-bdir"))      sprintf(Config.BiosDir, "%s", argv[++i]);
195                 else if(!strcmp(argv[i], "-bios"))      sprintf(Config.Bios, "%s", argv[++i]);
196                 else if (!strcmp(argv[i],"-gles")){
197                 strcpy(Config.Gpu, "gpuGLES.so");
198                 }
199                 else if (!strcmp(argv[i], "-cdda"))             Config.Cdda = 1;
200                 else if (!strcmp(argv[i], "-xa"))               Config.Xa = 1;
201                 else if (!strcmp(argv[i], "-rcnt"))             Config.RCntFix = 1 ;
202                 else if (!strcmp(argv[i], "-sio"))              Config.Sio = 1;
203                 else if (!strcmp(argv[i], "-spuirq"))   Config.SpuIrq = 1;
204                 else if (!strcmp(argv[i], "-vsync"))    Config.VSyncWA = 1;
205                 else if (!strcmp(argv[i], "-h") ||
206                          !strcmp(argv[i], "-help") ||
207                          !strcmp(argv[i], "--help")) {
208                          printf(PACKAGE_NAME " " PACKAGE_VERSION "\n");
209                          printf("%s\n", _(
210                                                         " pcsx [options] [file]\n"
211                                                         "\toptions:\n"
212                                                         "\t-cdfile FILE\tRuns a CD image file\n"
213                                                         "\t-psxout\t\tEnable PSX output\n"
214                                                         "\t-nosound\t\tDisable sound using spunull plugin\n"
215                                                         "\t-sputhreaded\t\tMove sound to separate thread\n"
216                                                         "\t-frameskip\t\tEnable frameskip\n"
217                                                         "\t-load STATENUM\tLoads savestate STATENUM (1-5)\n"
218                                                         "\t-h -help\tDisplay this message\n"
219                                                         "\tfile\t\tLoads file\n"));
220                          return 0;
221                 } else {
222                         strncpy(file, argv[i], MAXPATHLEN);
223                         if (file[0] != '/') {
224                                 getcwd(path, MAXPATHLEN);
225                                 if (strlen(path) + strlen(file) + 1 < MAXPATHLEN) {
226                                         strcat(path, "/");
227                                         strcat(path, file);
228                                         strcpy(file, path);
229                                 } else
230                                         file[0] = 0;
231                         }
232                 }
233         }
234
235
236         
237         
238         snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "/opt/maemo/usr/games" PATCHES_DIR);
239 /*
240         // switch to plugin dotdir
241         // this lets plugins work without modification!
242         gchar *plugin_default_dir = g_build_filename(getenv("HOME"), PLUGINS_DIR, NULL);
243         chdir(plugin_default_dir);
244         g_free(plugin_default_dir);
245 */
246
247         hildon_init(&argc, &argv);
248         
249         if (cdfile)
250                 set_cd_image(cdfile);
251
252         if (SysInit() == -1)
253                 return 1;
254
255         // frontend stuff
256         
257
258         if (LoadPlugins() == -1) {
259                 SysMessage("Failed loading plugins!");
260                 return 1;
261         }
262         pcnt_hook_plugins();
263
264         if (OpenPlugins() == -1) {
265                 return 1;
266         }
267         plugin_call_rearmed_cbs();
268
269         CheckCdrom();
270         SysReset();
271
272         if (file[0] != '\0') {
273                 if (Load(file) != -1)
274                         ready_to_go = 1;
275         } else {
276                 if (cdfile) {
277                         if (LoadCdrom() == -1) {
278                                 ClosePlugins();
279                                 printf(_("Could not load CD-ROM!\n"));
280                                 return -1;
281                         }
282                         ready_to_go = 1;
283                 }
284         }
285
286         // If a state has been specified, then load that
287         if (loadst) {
288                 char state_filename[MAXPATHLEN];
289                 int ret = get_state_filename(state_filename, sizeof(state_filename), loadst - 1);
290                 if (ret == 0)
291                         ret = LoadState(state_filename);
292                 printf("%s state %s\n", ret ? "failed to load" : "loaded", state_filename);
293         }
294
295
296         if (ready_to_go)
297                 maemo_init();
298         else
299         {
300         printf ("somethings goes wrong, maybe you forgot -cdfile ? \n");
301         exit(0);
302         }
303
304
305
306                 psxCpu->Execute();
307
308
309         return 0;
310 }
311
312 int SysInit() {
313         if (EmuInit() == -1) {
314                 printf("PSX emulator couldn't be initialized.\n");
315                 return -1;
316         }
317
318         LoadMcds(Config.Mcd1, Config.Mcd2);     /* TODO Do we need to have this here, or in the calling main() function?? */
319
320         if (Config.Debug) {
321                 StartDebugger();
322         }
323
324         return 0;
325 }
326
327 void SysRunGui() {
328         printf("SysRunGui\n");
329 }
330
331 void StartGui() {
332         printf("StartGui\n");
333 }
334
335 void SysReset() {
336         EmuReset();
337
338         // hmh core forgets this
339         CDR_stop();
340 }
341
342 void SysClose() {
343         EmuShutdown();
344         ReleasePlugins();
345
346         StopDebugger();
347
348         if (emuLog != NULL) fclose(emuLog);
349 }
350
351 void SysUpdate() {
352 }
353
354 void OnFile_Exit() {
355         printf("OnFile_Exit\n");
356         plat_finish();
357         SysClose();
358         exit(0);
359 }
360
361 int get_state_filename(char *buf, int size, int i) {
362         char trimlabel[33];
363         int j;
364
365         strncpy(trimlabel, CdromLabel, 32);
366         trimlabel[32] = 0;
367         for (j = 31; j >= 0; j--)
368                 if (trimlabel[j] == ' ')
369                         trimlabel[j] = 0;
370                 else
371                         continue;
372
373         snprintf(buf, size, "." STATES_DIR "%.32s-%.9s.%3.3d",
374                 trimlabel, CdromId, i);
375
376         return 0;
377 }
378
379 void SysPrintf(const char *fmt, ...) {
380         va_list list;
381         char msg[512];
382
383         va_start(list, fmt);
384         vsprintf(msg, fmt, list);
385         va_end(list);
386
387         fprintf(emuLog, "%s", msg);
388 }
389
390 void SysMessage(const char *fmt, ...) {
391         va_list list;
392         char msg[512];
393
394         va_start(list, fmt);
395         vsprintf(msg, fmt, list);
396         va_end(list);
397
398         if (msg[strlen(msg) - 1] == '\n')
399                 msg[strlen(msg) - 1] = 0;
400
401         fprintf(stderr, "%s\n", msg);
402 }
403
404 static void SignalExit(int sig) {
405         ClosePlugins();
406         OnFile_Exit();
407 }
408
409 #define PARSEPATH(dst, src) \
410         ptr = src + strlen(src); \
411         while (*ptr != '\' && ptr != src) ptr--; \
412         if (ptr != src) { \
413                 strcpy(dst, ptr+1); \
414         }
415
416 static int _OpenPlugins(void) {
417         int ret;
418
419         signal(SIGINT, SignalExit);
420         signal(SIGPIPE, SignalExit);
421
422         GPU_clearDynarec(clearDynarec);
423
424         ret = CDR_open();
425         if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
426         ret = SPU_open();
427         if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
428         SPU_registerCallback(SPUirq);
429         // pcsx-rearmed: we handle gpu elsewhere
430         //ret = GPU_open(&gpuDisp, "PCSX", NULL);
431         //if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; }
432         ret = PAD1_open(&gpuDisp);
433         if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; }
434         ret = PAD2_open(&gpuDisp);
435         if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
436
437         if (Config.UseNet && !NetOpened) {
438                 netInfo info;
439                 char path[MAXPATHLEN];
440                 char dotdir[MAXPATHLEN];
441
442                 MAKE_PATH(dotdir, "/.pcsx/plugins/", NULL);
443
444                 strcpy(info.EmuName, "PCSX " PACKAGE_VERSION);
445                 strncpy(info.CdromID, CdromId, 9);
446                 strncpy(info.CdromLabel, CdromLabel, 9);
447                 info.psxMem = psxM;
448                 info.GPU_showScreenPic = GPU_showScreenPic;
449                 info.GPU_displayText = GPU_displayText;
450                 info.GPU_showScreenPic = GPU_showScreenPic;
451                 info.PAD_setSensitive = PAD1_setSensitive;
452                 sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
453                 strcpy(info.BIOSpath, path);
454                 strcpy(info.MCD1path, Config.Mcd1);
455                 strcpy(info.MCD2path, Config.Mcd2);
456                 sprintf(path, "%s%s", dotdir, Config.Gpu);
457                 strcpy(info.GPUpath, path);
458                 sprintf(path, "%s%s", dotdir, Config.Spu);
459                 strcpy(info.SPUpath, path);
460                 sprintf(path, "%s%s", dotdir, Config.Cdr);
461                 strcpy(info.CDRpath, path);
462                 NET_setInfo(&info);
463
464                 ret = NET_open(&gpuDisp);
465                 if (ret < 0) {
466                         if (ret == -2) {
467                                 // -2 is returned when something in the info
468                                 // changed and needs to be synced
469                                 char *ptr;
470
471                                 PARSEPATH(Config.Bios, info.BIOSpath);
472                                 PARSEPATH(Config.Gpu,  info.GPUpath);
473                                 PARSEPATH(Config.Spu,  info.SPUpath);
474                                 PARSEPATH(Config.Cdr,  info.CDRpath);
475
476                                 strcpy(Config.Mcd1, info.MCD1path);
477                                 strcpy(Config.Mcd2, info.MCD2path);
478                                 return -2;
479                         } else {
480                                 Config.UseNet = FALSE;
481                         }
482                 } else {
483                         if (NET_queryPlayer() == 1) {
484                                 if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
485                         } else {
486                                 if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
487                         }
488                 }
489                 NetOpened = TRUE;
490         } else if (Config.UseNet) {
491                 NET_resume();
492         }
493
494         return 0;
495 }
496
497 int OpenPlugins() {
498         int ret;
499
500         while ((ret = _OpenPlugins()) == -2) {
501                 ReleasePlugins();
502                 LoadMcds(Config.Mcd1, Config.Mcd2);
503                 if (LoadPlugins() == -1) return -1;
504         }
505         return ret;
506 }
507
508 void ClosePlugins() {
509         int ret;
510
511         signal(SIGINT, SIG_DFL);
512         signal(SIGPIPE, SIG_DFL);
513         ret = CDR_close();
514         if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
515         ret = SPU_close();
516         if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
517         ret = PAD1_close();
518         if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
519         ret = PAD2_close();
520         if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
521         // pcsx-rearmed: we handle gpu elsewhere
522         //ret = GPU_close();
523         //if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
524
525         if (Config.UseNet) {
526                 NET_pause();
527         }
528 }
529
530 #if 1
531 /* this is to avoid having to hack every plugin to stop using $HOME */
532 char *getenv(const char *name)
533 {
534         static char ret[8] = ".";
535
536         if (name && strcmp(name, "HOME") == 0 &&
537                         ((int)name >> 28) == 0) // HACK: let libs find home
538                 return ret;
539
540         return real_getenv(name);
541 }
542 #endif
543
544 /* we hook statically linked plugins here */
545 static const char *builtin_plugins[] = {
546         "builtin_gpu", "builtin_spu", "builtin_cdr", "builtin_pad",
547         "builtin_cdrcimg",
548 };
549
550 static const int builtin_plugin_ids[] = {
551         PLUGIN_GPU, PLUGIN_SPU, PLUGIN_CDR, PLUGIN_PAD,
552         PLUGIN_CDRCIMG,
553 };
554
555 void *SysLoadLibrary(const char *lib) {
556         const char *tmp = strrchr(lib, '/');
557         void *ret;
558         int i;
559
560         printf("plugin: %s\n", lib);
561
562         if (tmp != NULL) {
563                 tmp++;
564                 for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++)
565                         if (strcmp(tmp, builtin_plugins[i]) == 0)
566                                 return (void *)(long)(PLUGIN_DL_BASE + builtin_plugin_ids[i]);
567         }
568
569 #if defined(__x86_64__) || defined(__i386__)
570         // convenience hack
571         char name[MAXPATHLEN];
572         snprintf(name, sizeof(name), "%s.x86", lib);
573         lib = name;
574 #endif
575
576         ret = dlopen(lib, RTLD_NOW);
577         if (ret == NULL)
578                 fprintf(stderr, "dlopen: %s\n", dlerror());
579         return ret;
580 }
581
582 void *SysLoadSym(void *lib, const char *sym) {
583         unsigned int plugid = (unsigned int)(long)lib;
584
585         if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
586                 return plugin_link(plugid - PLUGIN_DL_BASE, sym);
587
588         return dlsym(lib, sym);
589 }
590
591 const char *SysLibError() {
592         return dlerror();
593 }
594
595 void SysCloseLibrary(void *lib) {
596         unsigned int plugid = (unsigned int)(long)lib;
597
598         if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
599                 return;
600
601         dlclose(lib);
602 }
603