basic profiling
[pcsx_rearmed.git] / frontend / main.c
CommitLineData
e906c010 1/*
2 * (C) notaz, 2010
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
80c2304e 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
e906c010 16#include "plugin.h"
14dffdb7 17#include "pcnt.h"
80c2304e 18#include "../gui/Linux.h"
19#include "../libpcsxcore/misc.h"
20
21int UseGui;
b60f2812 22static char *(*real_getenv)(const char *name);
80c2304e 23
24static void make_path(char *buf, size_t size, const char *dir, const char *fname)
25{
26 if (fname)
27 snprintf(buf, size, ".%s%s", dir, fname);
28 else
29 snprintf(buf, size, ".%s", dir);
30}
31#define MAKE_PATH(buf, dir, fname) \
32 make_path(buf, sizeof(buf), dir, fname)
33
34static void create_profile_dir(const char *directory) {
35 char path[MAXPATHLEN];
36
37 MAKE_PATH(path, directory, NULL);
38 mkdir(path, S_IRWXU | S_IRWXG);
39}
40
41static void CheckSubDir() {
42 // make sure that ~/.pcsx exists
43 create_profile_dir(PCSX_DOT_DIR);
44
45 create_profile_dir(BIOS_DIR);
46 create_profile_dir(MEMCARD_DIR);
47 create_profile_dir(STATES_DIR);
48 create_profile_dir(PLUGINS_DIR);
49 create_profile_dir(PLUGINS_CFG_DIR);
50 create_profile_dir(CHEATS_DIR);
51 create_profile_dir(PATCHES_DIR);
52}
53
54static void CreateMemcard(char *filename, char *conf_mcd) {
55 struct stat buf;
56
57 make_path(conf_mcd, MAXPATHLEN, MEMCARD_DIR, filename);
58
59 /* Only create a memory card if an existing one does not exist */
60 if (stat(conf_mcd, &buf) == -1) {
61 SysPrintf(_("Creating memory card: %s\n"), conf_mcd);
62 CreateMcd(conf_mcd);
63 }
64}
65
66int main(int argc, char *argv[])
67{
68 char file[MAXPATHLEN] = "";
69 char path[MAXPATHLEN];
70 int runcd = 0;
71 int loadst = 0;
b60f2812 72 void *tmp;
80c2304e 73 int i;
74
b60f2812 75 tmp = dlopen("/lib/libdl.so.2", RTLD_LAZY);
76 if (tmp != NULL)
77 real_getenv = dlsym(tmp, "getenv");
78 if (real_getenv == NULL) {
79 fprintf(stderr, "%s\n", dlerror());
80 return 1;
81 }
82 dlclose(tmp);
83
80c2304e 84 // what is the name of the config file?
85 // it may be redefined by -cfg on the command line
86 strcpy(cfgfile_basename, "pcsx.cfg");
87
e906c010 88 emuLog = stdout;
80c2304e 89 SetIsoFile(NULL);
90 Config.PsxOut = 1;
91
92 // read command line options
93 for (i = 1; i < argc; i++) {
e906c010 94 if (!strcmp(argv[i], "-psxout")) Config.PsxOut = 1;
80c2304e 95 else if (!strcmp(argv[i], "-load")) loadst = atol(argv[++i]);
96 else if (!strcmp(argv[i], "-cfg")) {
97 if (i+1 >= argc) break;
98 strncpy(cfgfile_basename, argv[++i], MAXPATHLEN-100); /* TODO buffer overruns */
99 printf("Using config file %s.\n", cfgfile_basename);
100 }
101 else if (!strcmp(argv[i], "-cdfile")) {
102 char isofilename[MAXPATHLEN];
103
104 if (i+1 >= argc) break;
105 strncpy(isofilename, argv[++i], MAXPATHLEN);
106 if (isofilename[0] != '/') {
107 getcwd(path, MAXPATHLEN);
108 if (strlen(path) + strlen(isofilename) + 1 < MAXPATHLEN) {
109 strcat(path, "/");
110 strcat(path, isofilename);
111 strcpy(isofilename, path);
112 } else
113 isofilename[0] = 0;
114 }
115
116 SetIsoFile(isofilename);
117 runcd = 1;
118 }
119 else if (!strcmp(argv[i], "-h") ||
120 !strcmp(argv[i], "-help") ||
121 !strcmp(argv[i], "--help")) {
122 printf(PACKAGE_NAME " " PACKAGE_VERSION "\n");
123 printf("%s\n", _(
124 " pcsx [options] [file]\n"
125 "\toptions:\n"
126 "\t-cdfile FILE\tRuns a CD image file\n"
127 "\t-nogui\t\tDon't open the GTK GUI\n"
128 "\t-cfg FILE\tLoads desired configuration file (default: ~/.pcsx/pcsx.cfg)\n"
129 "\t-psxout\t\tEnable PSX output\n"
130 "\t-load STATENUM\tLoads savestate STATENUM (1-5)\n"
131 "\t-h -help\tDisplay this message\n"
132 "\tfile\t\tLoads file\n"));
133 return 0;
134 } else {
135 strncpy(file, argv[i], MAXPATHLEN);
136 if (file[0] != '/') {
137 getcwd(path, MAXPATHLEN);
138 if (strlen(path) + strlen(file) + 1 < MAXPATHLEN) {
139 strcat(path, "/");
140 strcat(path, file);
141 strcpy(file, path);
142 } else
143 file[0] = 0;
144 }
145 }
146 }
147
148 memset(&Config, 0, sizeof(PcsxConfig));
149 strcpy(Config.Net, "Disabled");
150
151 CheckSubDir();
152// ScanAllPlugins();
153
e906c010 154 strcpy(Config.Bios, "HLE");
155 strcpy(Config.BiosDir, "./");
156
157 strcpy(Config.PluginsDir, "plugins");
158 strcpy(Config.Gpu, "builtin_gpu");
159 strcpy(Config.Spu, "builtin_spu");
160 strcpy(Config.Cdr, "builtin_cdr");
161 strcpy(Config.Pad1, "builtin_pad");
162 strcpy(Config.Pad2, "builtin_pad");
163
80c2304e 164 // try to load config
165 // if the config file doesn't exist
166 if (LoadConfig() == -1) {
167 // Uh oh, no config file found, use some defaults
168 Config.PsxAuto = 1;
169
80c2304e 170 // create & load default memcards if they don't exist
171 CreateMemcard("card1.mcd", Config.Mcd1);
172 CreateMemcard("card2.mcd", Config.Mcd2);
173
174 LoadMcds(Config.Mcd1, Config.Mcd2);
175
176 SaveConfig();
177 }
178
179 snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "." PATCHES_DIR);
180/*
181 // switch to plugin dotdir
182 // this lets plugins work without modification!
183 gchar *plugin_default_dir = g_build_filename(getenv("HOME"), PLUGINS_DIR, NULL);
184 chdir(plugin_default_dir);
185 g_free(plugin_default_dir);
186*/
187 if (SysInit() == -1) return 1;
188
189 // if !gui
190 {
191 // the following only occurs if the gui isn't started
192 if (LoadPlugins() == -1) {
193 SysMessage("Failed loading plugins!");
194 return 1;
195 }
14dffdb7 196 pcnt_hook_plugins();
80c2304e 197
198 if (OpenPlugins() == -1) {
199 return 1;
200 }
201
202 SysReset();
203 CheckCdrom();
204
205 if (file[0] != '\0') {
206 Load(file);
207 } else {
208 if (runcd) {
209 if (LoadCdrom() == -1) {
210 ClosePlugins();
211 printf(_("Could not load CD-ROM!\n"));
212 return -1;
213 }
214 }
215 }
216
217 // If a state has been specified, then load that
218 if (loadst) {
219 StatesC = loadst - 1;
220 char *state_filename = get_state_filename(StatesC);
221 LoadState(state_filename);
222 free(state_filename);
223 }
224
225 psxCpu->Execute();
226 }
227
228 return 0;
229}
230
231int SysInit() {
80c2304e 232 if (EmuInit() == -1) {
233 printf("PSX emulator couldn't be initialized.\n");
234 return -1;
235 }
236
237 LoadMcds(Config.Mcd1, Config.Mcd2); /* TODO Do we need to have this here, or in the calling main() function?? */
238
239 if (Config.Debug) {
240 StartDebugger();
241 }
242
243 return 0;
244}
245
246void SysRunGui() {
247 printf("SysRunGui\n");
248}
249
250void StartGui() {
251 printf("StartGui\n");
252}
253
254void SysReset() {
255 EmuReset();
256}
257
258void SysClose() {
259 EmuShutdown();
260 ReleasePlugins();
261
262 StopDebugger();
263
264 if (emuLog != NULL) fclose(emuLog);
265}
266
267void SysUpdate() {
268 PADhandleKey(PAD1_keypressed());
269 PADhandleKey(PAD2_keypressed());
270}
271
272void UpdateMenuSlots() {
273}
274
275void OnFile_Exit() {
276 printf("OnFile_Exit\n");
277 exit(0);
278}
279
280void state_save(gchar *state_filename) {
281 char Text[MAXPATHLEN + 20];
282
283 GPU_updateLace();
284
285 if (SaveState(state_filename) == 0)
286 sprintf(Text, _("Saved state %s."), state_filename);
287 else
288 sprintf(Text, _("Error saving state %s!"), state_filename);
289
290 GPU_displayText(Text);
291}
292
293void state_load(gchar *state_filename) {
294 int ret;
295 char Text[MAXPATHLEN + 20];
296 FILE *fp;
297
298 // check if the state file actually exists
299 fp = fopen(state_filename, "rb");
300 if (fp == NULL) {
301 // file does not exist
302 return;
303 }
304
305 fclose(fp);
306
307 ret = CheckState(state_filename);
308
309 if (ret == 0) {
310 SysReset();
311 ret = LoadState(state_filename);
312 }
313
314 if (ret == 0) {
315 // Check the CD-ROM is valid
316 if (CheckCdrom() == -1) {
317 ClosePlugins();
318 SysRunGui();
319 return;
320 }
321
322 sprintf(Text, _("Loaded state %s."), state_filename);
323 } else {
324 sprintf(Text, _("Error loading state %s!"), state_filename);
325 }
326 GPU_displayText(Text);
327}
328
329char *get_state_filename(int i) {
330 char SStateFile[256];
331 char trimlabel[33];
332 int j;
333
334 strncpy(trimlabel, CdromLabel, 32);
335 trimlabel[32] = 0;
336 for (j = 31; j >= 0; j--)
337 if (trimlabel[j] == ' ')
338 trimlabel[j] = 0;
339 else
340 continue;
341
342 snprintf(SStateFile, sizeof(SStateFile), "." STATES_DIR "%.32s-%.9s.%3.3d",
343 trimlabel, CdromId, i);
344
345 return strdup(SStateFile);
346}
347
348void SysPrintf(const char *fmt, ...) {
349 va_list list;
350 char msg[512];
351
352 va_start(list, fmt);
353 vsprintf(msg, fmt, list);
354 va_end(list);
355
356 if (Config.PsxOut) {
357 static char linestart = 1;
358 int l = strlen(msg);
359
360 printf(linestart ? " * %s" : "%s", msg);
361
362 if (l > 0 && msg[l - 1] == '\n') {
363 linestart = 1;
364 } else {
365 linestart = 0;
366 }
367 }
368
369 fprintf(emuLog, "%s", msg);
370}
371
372void SysMessage(const char *fmt, ...) {
373 va_list list;
374 char msg[512];
375
376 va_start(list, fmt);
377 vsprintf(msg, fmt, list);
378 va_end(list);
379
380 if (msg[strlen(msg) - 1] == '\n')
381 msg[strlen(msg) - 1] = 0;
382
383 fprintf(stderr, "%s\n", msg);
384}
385
e906c010 386#if 1
387/* this is to avoid having to hack every plugin to stop using $HOME */
388char *getenv(const char *name)
389{
390 static char ret[8] = ".";
391
b60f2812 392 if (name && strcmp(name, "HOME") == 0)
393 return ret;
e906c010 394
b60f2812 395 return real_getenv(name);
e906c010 396}
397#endif
398
399/* we hook statically linked plugins here */
400static const char *builtin_plugins[] = {
401 "builtin_gpu", "builtin_spu", "builtin_cdr", "builtin_pad"
402};
403
404static const int builtin_plugin_ids[] = {
405 PLUGIN_GPU, PLUGIN_SPU, PLUGIN_CDR, PLUGIN_PAD,
406};
407
80c2304e 408void *SysLoadLibrary(const char *lib) {
e906c010 409 const char *tmp = strrchr(lib, '/');
410 int i;
411
412 printf("dlopen %s\n", lib);
413 if (tmp != NULL) {
414 tmp++;
415 for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++)
416 if (strcmp(tmp, builtin_plugins[i]) == 0)
417 return (void *)(long)(PLUGIN_DL_BASE + builtin_plugin_ids[i]);
418 }
419
80c2304e 420 return dlopen(lib, RTLD_NOW);
421}
422
423void *SysLoadSym(void *lib, const char *sym) {
e906c010 424 unsigned int plugid = (unsigned int)(long)lib;
425
426 if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
427 return plugin_link(plugid - PLUGIN_DL_BASE, sym);
428
80c2304e 429 return dlsym(lib, sym);
430}
431
432const char *SysLibError() {
433 return dlerror();
434}
435
436void SysCloseLibrary(void *lib) {
e906c010 437 unsigned int plugid = (unsigned int)(long)lib;
438
439 if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
440 return;
441
80c2304e 442 dlclose(lib);
443}
444
445