fix maemo build
[pcsx_rearmed.git] / frontend / main.c
CommitLineData
e906c010 1/*
201c21e2 2 * (C) notaz, 2010-2011
e906c010 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>
c5061935 15#include <signal.h>
29a8c4f3 16#include <time.h>
80c2304e 17
c5061935 18#include "main.h"
e906c010 19#include "plugin.h"
7c0f51de 20#include "plugin_lib.h"
14dffdb7 21#include "pcnt.h"
3c70c47b 22#include "menu.h"
47821672 23#include "plat.h"
80c2304e 24#include "../libpcsxcore/misc.h"
799b0b87 25#include "../libpcsxcore/new_dynarec/new_dynarec.h"
47bf65ab 26#include "../plugins/cdrcimg/cdrcimg.h"
69af03a2 27#include "common/plat.h"
29a8c4f3 28#include "common/readpng.h"
f2de172b 29#include "common/input.h"
30#include "linux/in_evdev.h"
80c2304e 31
fc8145b7 32// don't include debug.h - it breaks ARM build (R1 redefined)
33void StartDebugger();
34void StopDebugger();
35
69af03a2 36int ready_to_go;
c5061935 37unsigned long gpuDisp;
38char cfgfile_basename[MAXPATHLEN];
8f892648 39int state_slot;
40enum sched_action emu_action, emu_action_old;
41char hud_msg[64];
42int hud_new_msg;
43
80c2304e 44static void make_path(char *buf, size_t size, const char *dir, const char *fname)
45{
46 if (fname)
47 snprintf(buf, size, ".%s%s", dir, fname);
48 else
49 snprintf(buf, size, ".%s", dir);
50}
51#define MAKE_PATH(buf, dir, fname) \
52 make_path(buf, sizeof(buf), dir, fname)
53
54static void create_profile_dir(const char *directory) {
55 char path[MAXPATHLEN];
56
57 MAKE_PATH(path, directory, NULL);
58 mkdir(path, S_IRWXU | S_IRWXG);
59}
60
61static void CheckSubDir() {
62 // make sure that ~/.pcsx exists
63 create_profile_dir(PCSX_DOT_DIR);
64
65 create_profile_dir(BIOS_DIR);
66 create_profile_dir(MEMCARD_DIR);
67 create_profile_dir(STATES_DIR);
68 create_profile_dir(PLUGINS_DIR);
69 create_profile_dir(PLUGINS_CFG_DIR);
70 create_profile_dir(CHEATS_DIR);
71 create_profile_dir(PATCHES_DIR);
cd6e8d0f 72 create_profile_dir(PCSX_DOT_DIR "cfg");
29a8c4f3 73 create_profile_dir("/screenshots/");
74}
75
76static int get_gameid_filename(char *buf, int size, const char *fmt, int i) {
77 char trimlabel[33];
78 int j;
79
80 strncpy(trimlabel, CdromLabel, 32);
81 trimlabel[32] = 0;
82 for (j = 31; j >= 0; j--)
83 if (trimlabel[j] == ' ')
84 trimlabel[j] = 0;
85 else
86 continue;
87
88 snprintf(buf, size, fmt, trimlabel, CdromId, i);
89
90 return 0;
80c2304e 91}
92
47bf65ab 93void set_cd_image(const char *fname)
94{
e16a7e51 95 const char *ext = NULL;
47bf65ab 96
33716956 97 if (fname != NULL)
98 ext = strrchr(fname, '.');
47bf65ab 99
33716956 100 if (ext && (
101 strcasecmp(ext, ".z") == 0 || strcasecmp(ext, ".bz") == 0 ||
9a92bffb 102 strcasecmp(ext, ".znx") == 0 /*|| strcasecmp(ext, ".pbp") == 0*/)) {
47bf65ab 103 SetIsoFile(NULL);
104 cdrcimg_set_fname(fname);
105 strcpy(Config.Cdr, "builtin_cdrcimg");
106 } else {
107 SetIsoFile(fname);
108 strcpy(Config.Cdr, "builtin_cdr");
109 }
110}
111
6fe1f056 112static void set_default_paths(void)
113{
114 MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd");
115 MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd");
116 strcpy(Config.BiosDir, "bios");
117
118 strcpy(Config.PluginsDir, "plugins");
119 strcpy(Config.Gpu, "builtin_gpu");
120 strcpy(Config.Spu, "builtin_spu");
121 strcpy(Config.Cdr, "builtin_cdr");
122 strcpy(Config.Pad1, "builtin_pad");
123 strcpy(Config.Pad2, "builtin_pad");
124 strcpy(Config.Net, "Disabled");
d3f3bf09 125#if defined(__arm__) && !defined(__ARM_ARCH_7A__) /* XXX */
126 strcpy(Config.Gpu, "gpuPCSX4ALL.so");
127#endif
6fe1f056 128 Config.PsxAuto = 1;
129
130 snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "." PATCHES_DIR);
131}
132
51f77282 133static void check_memcards(void)
134{
135 char buf[MAXPATHLEN];
136 FILE *f;
137 int i;
138
139 for (i = 1; i <= 9; i++) {
140 snprintf(buf, sizeof(buf), ".%scard%d.mcd", MEMCARD_DIR, i);
141
142 f = fopen(buf, "rb");
143 if (f == NULL) {
144 printf("Creating memcard: %s\n", buf);
145 CreateMcd(buf);
146 }
147 else
148 fclose(f);
149 }
150}
151
8f892648 152void do_emu_action(void)
153{
29a8c4f3 154 char buf[MAXPATHLEN];
8f892648 155 int ret;
156
157 emu_action_old = emu_action;
158
159 switch (emu_action) {
8f892648 160 case SACTION_ENTER_MENU:
161 menu_loop();
162 return;
163 case SACTION_LOAD_STATE:
164 ret = emu_load_state(state_slot);
165 snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "LOADED" : "FAIL!");
166 break;
167 case SACTION_SAVE_STATE:
168 ret = emu_save_state(state_slot);
169 snprintf(hud_msg, sizeof(hud_msg), ret == 0 ? "SAVED" : "FAIL!");
170 break;
171 case SACTION_NEXT_SSLOT:
172 state_slot++;
173 if (state_slot > 9)
174 state_slot = 0;
175 goto do_state_slot;
176 case SACTION_PREV_SSLOT:
177 state_slot--;
178 if (state_slot < 0)
179 state_slot = 9;
180 goto do_state_slot;
181 case SACTION_TOGGLE_FSKIP:
ea4a16e7 182 pl_rearmed_cbs.fskip_advice = 0;
183 pl_rearmed_cbs.frameskip++;
184 if (pl_rearmed_cbs.frameskip > 1)
185 pl_rearmed_cbs.frameskip = -1;
186 snprintf(hud_msg, sizeof(hud_msg), "FRAMESKIP: %s",
187 pl_rearmed_cbs.frameskip == -1 ? "AUTO" :
188 pl_rearmed_cbs.frameskip == 0 ? "OFF" : "1" );
189 plugin_call_rearmed_cbs();
8f892648 190 break;
29a8c4f3 191 case SACTION_SCREENSHOT:
192 {
193 void *scrbuf;
194 int w, h, bpp;
195 time_t t = time(NULL);
196 struct tm *tb = localtime(&t);
197 int ti = tb->tm_yday * 1000000 + tb->tm_hour * 10000 +
198 tb->tm_min * 100 + tb->tm_sec;
199
200 scrbuf = pl_prepare_screenshot(&w, &h, &bpp);
201 get_gameid_filename(buf, sizeof(buf),
202 "screenshots/%.32s-%.9s.%d.png", ti);
203 ret = -1;
204 if (scrbuf != 0 && bpp == 16)
205 ret = writepng(buf, scrbuf, w, h);
206 if (ret == 0)
207 snprintf(hud_msg, sizeof(hud_msg), "SCREENSHOT TAKEN");
208 break;
209 }
4c08b9e7 210 default:
211 return;
8f892648 212 }
213 hud_new_msg = 3;
214 return;
215
216do_state_slot:
217 snprintf(hud_msg, sizeof(hud_msg), "STATE SLOT %d [%s]", state_slot,
218 emu_check_state(state_slot) == 0 ? "USED" : "FREE");
219 hud_new_msg = 3;
4c08b9e7 220 printf("* %s\n", hud_msg);
8f892648 221}
222
80c2304e 223int main(int argc, char *argv[])
224{
80c2304e 225 // what is the name of the config file?
226 // it may be redefined by -cfg on the command line
227 strcpy(cfgfile_basename, "pcsx.cfg");
228
e906c010 229 emuLog = stdout;
80c2304e 230 SetIsoFile(NULL);
80c2304e 231
e0c692d9 232 memset(&Config, 0, sizeof(Config));
233
234 CheckSubDir();
235 set_default_paths();
51f77282 236 check_memcards();
e0c692d9 237 strcpy(Config.Bios, "HLE");
238
239#ifdef MAEMO
240 extern int maemo_main(int argc, char **argv);
241 return maemo_main(argc, argv);
242#else
243 char file[MAXPATHLEN] = "";
244 char path[MAXPATHLEN];
245 const char *cdfile = NULL;
de910c6b 246 const char *loadst_f = NULL;
0a151868 247 int psxout = 0;
e0c692d9 248 int loadst = 0;
249 int i;
250
80c2304e 251 // read command line options
252 for (i = 1; i < argc; i++) {
0a151868 253 if (!strcmp(argv[i], "-psxout")) psxout = 1;
80c2304e 254 else if (!strcmp(argv[i], "-load")) loadst = atol(argv[++i]);
255 else if (!strcmp(argv[i], "-cfg")) {
256 if (i+1 >= argc) break;
257 strncpy(cfgfile_basename, argv[++i], MAXPATHLEN-100); /* TODO buffer overruns */
258 printf("Using config file %s.\n", cfgfile_basename);
259 }
260 else if (!strcmp(argv[i], "-cdfile")) {
261 char isofilename[MAXPATHLEN];
262
263 if (i+1 >= argc) break;
264 strncpy(isofilename, argv[++i], MAXPATHLEN);
265 if (isofilename[0] != '/') {
266 getcwd(path, MAXPATHLEN);
267 if (strlen(path) + strlen(isofilename) + 1 < MAXPATHLEN) {
268 strcat(path, "/");
269 strcat(path, isofilename);
270 strcpy(isofilename, path);
271 } else
272 isofilename[0] = 0;
273 }
274
47bf65ab 275 cdfile = isofilename;
80c2304e 276 }
de910c6b 277 else if (!strcmp(argv[i], "-loadf")) {
278 if (i+1 >= argc) break;
279 loadst_f = argv[++i];
280 }
80c2304e 281 else if (!strcmp(argv[i], "-h") ||
282 !strcmp(argv[i], "-help") ||
283 !strcmp(argv[i], "--help")) {
284 printf(PACKAGE_NAME " " PACKAGE_VERSION "\n");
285 printf("%s\n", _(
286 " pcsx [options] [file]\n"
287 "\toptions:\n"
288 "\t-cdfile FILE\tRuns a CD image file\n"
289 "\t-nogui\t\tDon't open the GTK GUI\n"
290 "\t-cfg FILE\tLoads desired configuration file (default: ~/.pcsx/pcsx.cfg)\n"
291 "\t-psxout\t\tEnable PSX output\n"
292 "\t-load STATENUM\tLoads savestate STATENUM (1-5)\n"
293 "\t-h -help\tDisplay this message\n"
294 "\tfile\t\tLoads file\n"));
295 return 0;
296 } else {
297 strncpy(file, argv[i], MAXPATHLEN);
298 if (file[0] != '/') {
299 getcwd(path, MAXPATHLEN);
300 if (strlen(path) + strlen(file) + 1 < MAXPATHLEN) {
301 strcat(path, "/");
302 strcat(path, file);
303 strcpy(file, path);
304 } else
305 file[0] = 0;
306 }
307 }
308 }
309
47bf65ab 310 if (cdfile)
311 set_cd_image(cdfile);
312
69af03a2 313 if (SysInit() == -1)
314 return 1;
80c2304e 315
69af03a2 316 // frontend stuff
317 in_init();
f2de172b 318 in_evdev_init();
ef94866c 319 //in_probe();
69af03a2 320 plat_init();
0a151868 321 menu_init(); // loads config
4c08b9e7 322 pl_init();
faf2b2aa 323 plat_rescan_inputs();
0a151868 324
325 if (psxout)
326 Config.PsxOut = 1;
80c2304e 327
69af03a2 328 if (LoadPlugins() == -1) {
6fe1f056 329 // FIXME: this recovery doesn't work, just delete bad config and bail out
330 // SysMessage("could not load plugins, retrying with defaults\n");
331 set_default_paths();
332 snprintf(path, sizeof(path), "." PCSX_DOT_DIR "%s", cfgfile_basename);
333 remove(path);
69af03a2 334 SysMessage("Failed loading plugins!");
335 return 1;
336 }
337 pcnt_hook_plugins();
80c2304e 338
69af03a2 339 if (OpenPlugins() == -1) {
340 return 1;
341 }
201c21e2 342 plugin_call_rearmed_cbs();
80c2304e 343
69af03a2 344 CheckCdrom();
bbd837c6 345 SysReset();
69af03a2 346
347 if (file[0] != '\0') {
348 if (Load(file) != -1)
349 ready_to_go = 1;
350 } else {
47bf65ab 351 if (cdfile) {
69af03a2 352 if (LoadCdrom() == -1) {
353 ClosePlugins();
354 printf(_("Could not load CD-ROM!\n"));
355 return -1;
80c2304e 356 }
69af03a2 357 ready_to_go = 1;
80c2304e 358 }
69af03a2 359 }
80c2304e 360
45d45c1e 361 if (ready_to_go) {
3c70c47b 362 menu_prepare_emu();
45d45c1e 363
364 // If a state has been specified, then load that
365 if (loadst) {
366 int ret = emu_load_state(loadst - 1);
367 printf("%s state %d\n", ret ? "failed to load" : "loaded", loadst);
368 }
de910c6b 369 if (loadst_f) {
370 int ret = LoadState(loadst_f);
371 printf("%s state file: %s\n", ret ? "failed to load" : "loaded", loadst_f);
372 }
45d45c1e 373 }
3c70c47b 374 else
69af03a2 375 menu_loop();
376
7c0f51de 377 pl_start_watchdog();
378
69af03a2 379 while (1)
380 {
799b0b87 381 stop = 0;
8f892648 382 emu_action = SACTION_NONE;
383
80c2304e 384 psxCpu->Execute();
8f892648 385 if (emu_action != SACTION_NONE)
386 do_emu_action();
80c2304e 387 }
388
389 return 0;
e0c692d9 390#endif
80c2304e 391}
392
393int SysInit() {
80c2304e 394 if (EmuInit() == -1) {
395 printf("PSX emulator couldn't be initialized.\n");
396 return -1;
397 }
398
51f77282 399 LoadMcds(Config.Mcd1, Config.Mcd2);
80c2304e 400
401 if (Config.Debug) {
402 StartDebugger();
403 }
404
405 return 0;
406}
407
408void SysRunGui() {
409 printf("SysRunGui\n");
410}
411
412void StartGui() {
413 printf("StartGui\n");
414}
415
e6eb2066 416static void dummy_lace()
417{
418}
419
80c2304e 420void SysReset() {
e6eb2066 421 // rearmed hack: EmuReset() runs some code when real BIOS is used,
422 // but we usually do reset from menu while GPU is not open yet,
423 // so we need to prevent updateLace() call..
424 void *real_lace = GPU_updateLace;
425 GPU_updateLace = dummy_lace;
426
80c2304e 427 EmuReset();
bd6267e6 428
429 // hmh core forgets this
430 CDR_stop();
e6eb2066 431
432 GPU_updateLace = real_lace;
80c2304e 433}
434
435void SysClose() {
436 EmuShutdown();
437 ReleasePlugins();
438
439 StopDebugger();
440
441 if (emuLog != NULL) fclose(emuLog);
442}
443
444void SysUpdate() {
80c2304e 445}
446
447void OnFile_Exit() {
bd6267e6 448 printf("OnFile_Exit\n");
e0c692d9 449#ifndef MAEMO
201c21e2 450 menu_finish();
e0c692d9 451#endif
bd6267e6 452 SysClose();
2c886904 453 plat_finish();
80c2304e 454 exit(0);
455}
456
c5061935 457int get_state_filename(char *buf, int size, int i) {
29a8c4f3 458 return get_gameid_filename(buf, size,
459 "." STATES_DIR "%.32s-%.9s.%3.3d", i);
80c2304e 460}
461
8f892648 462int emu_check_state(int slot)
463{
464 char fname[MAXPATHLEN];
465 int ret;
466
467 ret = get_state_filename(fname, sizeof(fname), slot);
468 if (ret != 0)
469 return ret;
470
471 return CheckState(fname);
472}
473
474int emu_save_state(int slot)
475{
476 char fname[MAXPATHLEN];
477 int ret;
478
479 ret = get_state_filename(fname, sizeof(fname), slot);
480 if (ret != 0)
481 return ret;
482
90f1d26c 483 ret = SaveState(fname);
484 printf("* %s \"%s\" [%d]\n", ret == 0 ? "saved" : "failed to save", fname, slot);
485 return ret;
8f892648 486}
487
488int emu_load_state(int slot)
489{
490 char fname[MAXPATHLEN];
491 int ret;
492
493 ret = get_state_filename(fname, sizeof(fname), slot);
494 if (ret != 0)
495 return ret;
496
497 return LoadState(fname);
498}
499
80c2304e 500void SysPrintf(const char *fmt, ...) {
501 va_list list;
502 char msg[512];
503
504 va_start(list, fmt);
505 vsprintf(msg, fmt, list);
506 va_end(list);
507
80c2304e 508 fprintf(emuLog, "%s", msg);
509}
510
511void SysMessage(const char *fmt, ...) {
512 va_list list;
513 char msg[512];
514
515 va_start(list, fmt);
516 vsprintf(msg, fmt, list);
517 va_end(list);
518
519 if (msg[strlen(msg) - 1] == '\n')
520 msg[strlen(msg) - 1] = 0;
521
522 fprintf(stderr, "%s\n", msg);
523}
524
c5061935 525static void SignalExit(int sig) {
526 ClosePlugins();
527 OnFile_Exit();
528}
529
530#define PARSEPATH(dst, src) \
531 ptr = src + strlen(src); \
532 while (*ptr != '\\' && ptr != src) ptr--; \
533 if (ptr != src) { \
534 strcpy(dst, ptr+1); \
535 }
536
537static int _OpenPlugins(void) {
538 int ret;
539
540 signal(SIGINT, SignalExit);
541 signal(SIGPIPE, SignalExit);
542
543 GPU_clearDynarec(clearDynarec);
544
545 ret = CDR_open();
546 if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
547 ret = SPU_open();
548 if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
549 SPU_registerCallback(SPUirq);
550 // pcsx-rearmed: we handle gpu elsewhere
551 //ret = GPU_open(&gpuDisp, "PCSX", NULL);
552 //if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; }
553 ret = PAD1_open(&gpuDisp);
554 if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; }
555 ret = PAD2_open(&gpuDisp);
556 if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
557
558 if (Config.UseNet && !NetOpened) {
559 netInfo info;
560 char path[MAXPATHLEN];
561 char dotdir[MAXPATHLEN];
562
563 MAKE_PATH(dotdir, "/.pcsx/plugins/", NULL);
564
565 strcpy(info.EmuName, "PCSX " PACKAGE_VERSION);
566 strncpy(info.CdromID, CdromId, 9);
567 strncpy(info.CdromLabel, CdromLabel, 9);
568 info.psxMem = psxM;
569 info.GPU_showScreenPic = GPU_showScreenPic;
570 info.GPU_displayText = GPU_displayText;
571 info.GPU_showScreenPic = GPU_showScreenPic;
572 info.PAD_setSensitive = PAD1_setSensitive;
573 sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
574 strcpy(info.BIOSpath, path);
575 strcpy(info.MCD1path, Config.Mcd1);
576 strcpy(info.MCD2path, Config.Mcd2);
577 sprintf(path, "%s%s", dotdir, Config.Gpu);
578 strcpy(info.GPUpath, path);
579 sprintf(path, "%s%s", dotdir, Config.Spu);
580 strcpy(info.SPUpath, path);
581 sprintf(path, "%s%s", dotdir, Config.Cdr);
582 strcpy(info.CDRpath, path);
583 NET_setInfo(&info);
584
585 ret = NET_open(&gpuDisp);
586 if (ret < 0) {
587 if (ret == -2) {
588 // -2 is returned when something in the info
589 // changed and needs to be synced
590 char *ptr;
591
592 PARSEPATH(Config.Bios, info.BIOSpath);
593 PARSEPATH(Config.Gpu, info.GPUpath);
594 PARSEPATH(Config.Spu, info.SPUpath);
595 PARSEPATH(Config.Cdr, info.CDRpath);
596
597 strcpy(Config.Mcd1, info.MCD1path);
598 strcpy(Config.Mcd2, info.MCD2path);
599 return -2;
600 } else {
601 Config.UseNet = FALSE;
602 }
603 } else {
604 if (NET_queryPlayer() == 1) {
605 if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
606 } else {
607 if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
608 }
609 }
610 NetOpened = TRUE;
611 } else if (Config.UseNet) {
612 NET_resume();
613 }
614
615 return 0;
616}
617
618int OpenPlugins() {
619 int ret;
620
621 while ((ret = _OpenPlugins()) == -2) {
622 ReleasePlugins();
623 LoadMcds(Config.Mcd1, Config.Mcd2);
624 if (LoadPlugins() == -1) return -1;
625 }
626 return ret;
627}
628
629void ClosePlugins() {
630 int ret;
631
632 signal(SIGINT, SIG_DFL);
633 signal(SIGPIPE, SIG_DFL);
634 ret = CDR_close();
635 if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
636 ret = SPU_close();
637 if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
638 ret = PAD1_close();
639 if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
640 ret = PAD2_close();
641 if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
642 // pcsx-rearmed: we handle gpu elsewhere
643 //ret = GPU_close();
644 //if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
645
646 if (Config.UseNet) {
647 NET_pause();
648 }
649}
650
e906c010 651/* we hook statically linked plugins here */
652static const char *builtin_plugins[] = {
47bf65ab 653 "builtin_gpu", "builtin_spu", "builtin_cdr", "builtin_pad",
654 "builtin_cdrcimg",
e906c010 655};
656
657static const int builtin_plugin_ids[] = {
658 PLUGIN_GPU, PLUGIN_SPU, PLUGIN_CDR, PLUGIN_PAD,
47bf65ab 659 PLUGIN_CDRCIMG,
e906c010 660};
661
80c2304e 662void *SysLoadLibrary(const char *lib) {
e906c010 663 const char *tmp = strrchr(lib, '/');
bbd837c6 664 void *ret;
e906c010 665 int i;
666
bbd837c6 667 printf("plugin: %s\n", lib);
668
e906c010 669 if (tmp != NULL) {
670 tmp++;
671 for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++)
672 if (strcmp(tmp, builtin_plugins[i]) == 0)
673 return (void *)(long)(PLUGIN_DL_BASE + builtin_plugin_ids[i]);
674 }
675
2185e39b 676#if defined(__x86_64__) || defined(__i386__)
677 // convenience hack
678 char name[MAXPATHLEN];
679 snprintf(name, sizeof(name), "%s.x86", lib);
680 lib = name;
681#endif
682
bbd837c6 683 ret = dlopen(lib, RTLD_NOW);
684 if (ret == NULL)
685 fprintf(stderr, "dlopen: %s\n", dlerror());
686 return ret;
80c2304e 687}
688
689void *SysLoadSym(void *lib, const char *sym) {
e906c010 690 unsigned int plugid = (unsigned int)(long)lib;
691
692 if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
693 return plugin_link(plugid - PLUGIN_DL_BASE, sym);
694
80c2304e 695 return dlsym(lib, sym);
696}
697
698const char *SysLibError() {
699 return dlerror();
700}
701
702void SysCloseLibrary(void *lib) {
e906c010 703 unsigned int plugid = (unsigned int)(long)lib;
704
705 if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
706 return;
707
80c2304e 708 dlclose(lib);
709}
710