#include <stdlib.h>
#include <unistd.h>
#include <hildon/hildon.h>
-#include "minimal.h"
-
-GdkImage *image;
-HildonAnimationActor *actor;
-GtkWidget *window, *drawing;
+#include "plugin_lib.h"
#define X_RES 800
#define Y_RES 480
#define D_WIDTH 640
#define D_HEIGHT 480
-int screen_size;
+static GdkImage *image;
+static HildonAnimationActor *actor;
+static GtkWidget *window, *drawing;
+
+void *pl_fbdev_buf;
+int keystate;
+
+static int keymap[65536];
+
+// map psx4m compatible keymap to PSX keys
+static const unsigned char keymap2[14] = {
+ DKEY_LEFT, // 0
+ DKEY_RIGHT,
+ DKEY_UP,
+ DKEY_DOWN,
+ DKEY_CIRCLE,
+ DKEY_CROSS, // 5
+ DKEY_TRIANGLE,
+ DKEY_SQUARE,
+ DKEY_SELECT,
+ DKEY_START,
+ DKEY_L2, // 10
+ DKEY_R2,
+ DKEY_L1,
+ DKEY_R1,
+};
-void *pl_fbdev_buf=NULL;
-int keymap[65536];
-void hildon_quit();
-unsigned long keys = 0;
+void hildon_quit()
+{
+ gtk_main_quit();
+ exit(0);
+}
static void
-window_key_proxy (GtkWidget *widget,
+window_key_proxy(GtkWidget *widget,
GdkEventKey *event,
gpointer user_data)
{
- unsigned long key = 0;
-switch(keymap[event->hardware_keycode]){
- case -1:
- return; break;
- case 0:
- key = GP2X_LEFT;break;
- case 1:
- key = GP2X_RIGHT;break;
- case 2:
- key = GP2X_UP;break;
- case 3:
- key = GP2X_DOWN;break;
- case 4:
- key = GP2X_B;break;
- case 5:
- key = GP2X_X;break;
- case 6:
- key = GP2X_Y;break;
- case 7:
- key = GP2X_A;break;
- case 8:
- key = GP2X_SELECT;break;
- case 9:
- key = GP2X_START;break;
- case 10:
- key = GP2X_VOL_DOWN;break;
- case 11:
- key = GP2X_VOL_UP;break;
- case 12:
- key = GP2X_L;break;
- case 13:
- key = GP2X_R;break;
- case 14:
- hildon_quit();break;
- case 15:
- if (event->type == GDK_KEY_PRESS){
- keys |= GP2X_LEFT;
- keys |= GP2X_UP;
- }else if (event->type == GDK_KEY_RELEASE){
- keys &= ~GP2X_LEFT;
- keys &= ~GP2X_UP;
- }
- key = -1; return ; break;
- case 16:
- if (event->type == GDK_KEY_PRESS){
- keys |= GP2X_RIGHT;
- keys |= GP2X_UP;
- }else if (event->type == GDK_KEY_RELEASE){
- keys &= ~GP2X_RIGHT;
- keys &= ~GP2X_UP;
- }
- key = -1; return ; break;
- case 17:
- if (event->type == GDK_KEY_PRESS){
- keys |= GP2X_LEFT;
- keys |= GP2X_DOWN;
- }else if (event->type == GDK_KEY_RELEASE){
- keys &= ~GP2X_LEFT;
- keys &= ~GP2X_DOWN;
- }
- key = -1; return ; break;
- case 18:
- if (event->type == GDK_KEY_PRESS){
- keys |= GP2X_RIGHT;
- keys |= GP2X_DOWN;
- }else if (event->type == GDK_KEY_RELEASE){
- keys &= ~GP2X_RIGHT;
- keys &= ~GP2X_DOWN;
- }
- key = -1; return ; break;
-/* case 19:
- SaveState(cfile);
- key = -1; return ; break;
- break;
- case 20:
- LoadState(cfile);
- key = -1; return ; break;*/
- break;
-}
-
+ int key, psxkey1 = -1, psxkey2 = -1;
+
+ key = keymap[event->hardware_keycode];
+ if (key < 0)
+ return;
+
+ if (key < ARRAY_SIZE(keymap2))
+ psxkey1 = keymap2[key];
+ else switch (key) {
+ case 14:
+ hildon_quit();
+ break;
+ case 15:
+ psxkey1 = DKEY_UP;
+ psxkey2 = DKEY_LEFT;
+ break;
+ case 16:
+ psxkey1 = DKEY_UP;
+ psxkey2 = DKEY_RIGHT;
+ break;
+ case 17:
+ psxkey1 = DKEY_DOWN;
+ psxkey2 = DKEY_LEFT;
+ break;
+ case 18:
+ psxkey1 = DKEY_DOWN;
+ psxkey2 = DKEY_RIGHT;
+ break;
+ case 19:
+ //SaveState(cfile);
+ return;
+ case 20:
+ //LoadState(cfile);
+ return;
+ }
+
if (event->type == GDK_KEY_PRESS) {
- keys |= key;
+ if (psxkey1 >= 0)
+ keystate |= 1 << psxkey1;
+ if (psxkey2 >= 0)
+ keystate |= 1 << psxkey2;
}
else if (event->type == GDK_KEY_RELEASE) {
- keys &= ~key;
+ if (psxkey1 >= 0)
+ keystate &= ~(1 << psxkey1);
+ if (psxkey2 >= 0)
+ keystate &= ~(1 << psxkey2);
}
}
-unsigned long int gp2x_joystick_read();
-unsigned int ReadZodKeys()
-{
- unsigned int pad_status = 0xffff;
- unsigned long int keys = gp2x_joystick_read();
-
-
- if( keys & GP2X_VOL_DOWN ) // L2
- {
- pad_status &= ~(1<<8);
- }
- if (keys & GP2X_L)
- {
- pad_status &= ~(1<<10); // L ?
- }
-
-
-
- if( keys & GP2X_VOL_UP ) // R2
- {
- pad_status &= ~(1<<9);
- }
- if (keys & GP2X_R)
- {
- pad_status &= ~(1<<11); // R ?
- }
-
- if (keys & GP2X_UP)
- {
- pad_status &= ~(1<<4);
- }
- if (keys & GP2X_DOWN)
- {
- pad_status &= ~(1<<6);
- }
- if (keys & GP2X_LEFT)
- {
- pad_status &= ~(1<<7);
- }
- if (keys & GP2X_RIGHT)
- {
- pad_status &= ~(1<<5);
- }
- if (keys & GP2X_START)
- {
- pad_status &= ~(1<<3);
- }
- if (keys & GP2X_SELECT)
- {
- pad_status &= ~(1);
- }
-
- if (keys & GP2X_X)
- {
- pad_status &= ~(1<<14);
- }
- if (keys & GP2X_B)
- {
- pad_status &= ~(1<<13);
- }
- if (keys & GP2X_A)
- {
- pad_status &= ~(1<<15);
- }
- if (keys & GP2X_Y)
- {
- pad_status &= ~(1<<12);
- }
-
- return pad_status;
-}
-void hildon_quit()
+void plat_finish()
{
- gtk_main_quit();
- exit(0);
+ hildon_quit();
}
-void plat_finish(){hildon_quit();}
void maemo_init(int *argc, char ***argv)
{
}
fclose(pFile);
}
-
gtk_init (argc, argv);
gtk_widget_show_all (GTK_WIDGET (window));
}
-
-void pl_fbdev_set_mode(int w, int h,int bpp)
+void *pl_fbdev_set_mode(int w, int h, int bpp)
{
-//if (bpp==24){w=800;h=480;}
if (w <= 0 || h <= 0)
return;
if (image) gdk_image_destroy(image);
image = gdk_image_new( GDK_IMAGE_FASTEST, gdk_visual_get_system(), w, h );
- pl_fbdev_buf = (void*) image->mem;
- screen_size = image->bpl * h * image->bpp;
+ pl_fbdev_buf = (void *) image->mem;
gtk_image_set_from_image (GTK_IMAGE(drawing), image, NULL);
(gdouble)D_WIDTH / (gdouble)w,
(gdouble)D_HEIGHT / (gdouble)h
);
+
+ return pl_fbdev_buf;
}
-unsigned long gp2x_joystick_read(void)
+void *pl_fbdev_flip(void)
{
- //printf("gp2x_joystick_read\n");
+ gtk_widget_queue_draw (drawing);
+}
+
+void pl_frame_limit(void)
+{
+ extern void CheckFrameRate(void);
+ //CheckFrameRate();
+
/* process GTK+ events */
while (gtk_events_pending())
gtk_main_iteration();
-
- return keys;
}
-void gp2x_video_RGB_clearscreen16(void)
+void pl_fbdev_close(void)
{
- //if (screenbuffer && screen_size)
- // memset(pl_fbdev_buf, 0, screen_size);
}
-void pl_fbdev_flip()
+int pl_fbdev_open(void)
{
- gtk_widget_queue_draw (drawing);
}
-void gp2x_printfchar15(gp2x_font *f, unsigned char c)
+static void pl_get_layer_pos(int *x, int *y, int *w, int *h)
{
- unsigned short *dst=&((unsigned short*)pl_fbdev_buf)[f->x+f->y*(image->bpl>>1)],w,h=f->h;
-//unsigned char *src=f->data[ (c%16)*f->w + (c/16)*f->h ];
- unsigned char *src=&f->data[c*10];
-
- if(f->solid)
- while(h--)
- {
- w=f->wmask;
- while(w)
- {
- if( *src & w ) *dst++=f->fg; else *dst++=f->bg;
- w>>=1;
- }
- src++;
-
- dst+=(image->bpl>>1)-(f->w);
- }
- else
- while(h--)
- {
- w=f->wmask;
- while(w)
- {
- if( *src & w ) *dst=f->fg;
- dst++;
- w>>=1;
- }
- src++;
-
- dst+=(image->bpl>>1)-(f->w);
- }
+ *x = 0;
+ *y = 0;
+ *w = 800;
+ *h = 640;
}
-void pl_frame_limit(void){
-}
-
-void pl_fbdev_close(void){
-}
-
-void pl_fbdev_open(void){
-
-}
+extern int UseFrameSkip; // hmh
+const struct rearmed_cbs pl_rearmed_cbs = {
+ pl_get_layer_pos,
+ pl_fbdev_open,
+ pl_fbdev_set_mode,
+ pl_fbdev_flip,
+ pl_fbdev_close,
+ &UseFrameSkip,
+};
#include "main.h"
#include "plugin.h"
-#include "pcnt.h"
-#include "menu.h"
#include "../libpcsxcore/misc.h"
#include "../plugins/cdrcimg/cdrcimg.h"
-#include "common/plat.h"
-#include "common/input.h"
-
-int ready_to_go;
-unsigned long gpuDisp;
-char cfgfile_basename[MAXPATHLEN];
-static char *(*real_getenv)(const char *name);
-
-static void make_path(char *buf, size_t size, const char *dir, const char *fname)
-{
- if (fname)
- snprintf(buf, size, ".%s%s", dir, fname);
- else
- snprintf(buf, size, ".%s", dir);
-}
-#define MAKE_PATH(buf, dir, fname) \
- make_path(buf, sizeof(buf), dir, fname)
-
-static void create_profile_dir(const char *directory) {
- char path[MAXPATHLEN];
-
- MAKE_PATH(path, directory, NULL);
- mkdir(path, S_IRWXU | S_IRWXG);
-}
-
-static void CheckSubDir() {
- // make sure that ~/.pcsx exists
- create_profile_dir(PCSX_DOT_DIR);
-
- create_profile_dir(BIOS_DIR);
- create_profile_dir(MEMCARD_DIR);
- create_profile_dir(STATES_DIR);
- create_profile_dir(PLUGINS_DIR);
- create_profile_dir(PLUGINS_CFG_DIR);
- create_profile_dir(CHEATS_DIR);
- create_profile_dir(PATCHES_DIR);
- create_profile_dir(PCSX_DOT_DIR "cfg");
-}
-
-void set_cd_image(const char *fname)
-{
- const char *ext;
- int len;
-
- len = strlen(fname);
- ext = fname;
- if (len > 2)
- ext = fname + len - 2;
-
- if (strcasecmp(ext, ".z") == 0) {
- SetIsoFile(NULL);
- cdrcimg_set_fname(fname);
- strcpy(Config.Cdr, "builtin_cdrcimg");
- } else {
- SetIsoFile(fname);
- strcpy(Config.Cdr, "builtin_cdr");
- }
-}
// from softgpu plugin
extern int iUseDither;
static void ChangeWorkingDirectory(char *exe)
{
- s8 exepath[1024];
- s8* s;
- sprintf(exepath, "%s", exe);
+ s8 exepath[1024];
+ s8* s;
+ sprintf(exepath, "%s", exe);
s = strrchr(exepath, '/');
if (s != NULL) {
*s = '\0';
}
}
-int main(int argc, char *argv[])
+int maemo_main(int argc, char **argv)
{
ChangeWorkingDirectory("c");
char file[MAXPATHLEN] = "";
void *tmp;
int i;
- tmp = dlopen("/lib/libdl.so.2", RTLD_LAZY);
- if (tmp == NULL)
- tmp = dlopen("/lib32/libdl.so.2", RTLD_LAZY);
- if (tmp != NULL)
- real_getenv = dlsym(tmp, "getenv");
- if (real_getenv == NULL) {
- fprintf(stderr, "%s\n", dlerror());
- return 1;
- }
- dlclose(tmp);
-
- // what is the name of the config file?
- // it may be redefined by -cfg on the command line
- strcpy(cfgfile_basename, "pcsx.cfg");
-
- emuLog = stdout;
- SetIsoFile(NULL);
-
- memset(&Config, 0, sizeof(PcsxConfig));
- strcpy(Config.Net, "Disabled");
-
- CheckSubDir();
-
- MAKE_PATH(Config.Mcd1, MEMCARD_DIR, "card1.mcd");
- MAKE_PATH(Config.Mcd2, MEMCARD_DIR, "card2.mcd");
- strcpy(Config.Bios, "HLE");
strcpy(Config.BiosDir, "/home/user/MyDocs");
-
-
- Config.PsxAuto = 1;
-
strcpy(Config.PluginsDir, "/opt/maemo/usr/games/plugins");
- strcpy(Config.Gpu, "builtin_gpu");
- strcpy(Config.Spu, "builtin_spu");
- strcpy(Config.Cdr, "builtin_cdr");
- strcpy(Config.Pad1, "builtin_pad");
- strcpy(Config.Pad2, "builtin_pad");
-
+ snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "/opt/maemo/usr/games" PATCHES_DIR);
+ Config.PsxAuto = 1;
// read command line options
for (i = 1; i < argc; i++) {
}
}
-
-
-
- snprintf(Config.PatchesDir, sizeof(Config.PatchesDir), "/opt/maemo/usr/games" PATCHES_DIR);
-/*
- // switch to plugin dotdir
- // this lets plugins work without modification!
- gchar *plugin_default_dir = g_build_filename(getenv("HOME"), PLUGINS_DIR, NULL);
- chdir(plugin_default_dir);
- g_free(plugin_default_dir);
-*/
-
hildon_init(&argc, &argv);
if (cdfile)
if (SysInit() == -1)
return 1;
- // frontend stuff
-
-
if (LoadPlugins() == -1) {
SysMessage("Failed loading plugins!");
return 1;
}
- pcnt_hook_plugins();
if (OpenPlugins() == -1) {
return 1;
printf("%s state %s\n", ret ? "failed to load" : "loaded", state_filename);
}
-
if (ready_to_go)
maemo_init();
else
{
- printf ("somethings goes wrong, maybe you forgot -cdfile ? \n");
- exit(0);
- }
-
-
-
- psxCpu->Execute();
-
-
- return 0;
-}
-
-int SysInit() {
- if (EmuInit() == -1) {
- printf("PSX emulator couldn't be initialized.\n");
- return -1;
+ printf ("somethings goes wrong, maybe you forgot -cdfile ? \n");
+ return 0;
}
- LoadMcds(Config.Mcd1, Config.Mcd2); /* TODO Do we need to have this here, or in the calling main() function?? */
-
- if (Config.Debug) {
- StartDebugger();
- }
+ psxCpu->Execute();
return 0;
}
-void SysRunGui() {
- printf("SysRunGui\n");
-}
-
-void StartGui() {
- printf("StartGui\n");
-}
-
-void SysReset() {
- EmuReset();
-
- // hmh core forgets this
- CDR_stop();
-}
-
-void SysClose() {
- EmuShutdown();
- ReleasePlugins();
-
- StopDebugger();
-
- if (emuLog != NULL) fclose(emuLog);
-}
-
-void SysUpdate() {
-}
-
-void OnFile_Exit() {
- printf("OnFile_Exit\n");
- plat_finish();
- SysClose();
- exit(0);
-}
-
-int get_state_filename(char *buf, int size, int i) {
- char trimlabel[33];
- int j;
-
- strncpy(trimlabel, CdromLabel, 32);
- trimlabel[32] = 0;
- for (j = 31; j >= 0; j--)
- if (trimlabel[j] == ' ')
- trimlabel[j] = 0;
- else
- continue;
-
- snprintf(buf, size, "." STATES_DIR "%.32s-%.9s.%3.3d",
- trimlabel, CdromId, i);
-
- return 0;
-}
-
-void SysPrintf(const char *fmt, ...) {
- va_list list;
- char msg[512];
-
- va_start(list, fmt);
- vsprintf(msg, fmt, list);
- va_end(list);
-
- fprintf(emuLog, "%s", msg);
-}
-
-void SysMessage(const char *fmt, ...) {
- va_list list;
- char msg[512];
-
- va_start(list, fmt);
- vsprintf(msg, fmt, list);
- va_end(list);
-
- if (msg[strlen(msg) - 1] == '\n')
- msg[strlen(msg) - 1] = 0;
-
- fprintf(stderr, "%s\n", msg);
-}
-
-static void SignalExit(int sig) {
- ClosePlugins();
- OnFile_Exit();
-}
-
-#define PARSEPATH(dst, src) \
- ptr = src + strlen(src); \
- while (*ptr != '\' && ptr != src) ptr--; \
- if (ptr != src) { \
- strcpy(dst, ptr+1); \
- }
-
-static int _OpenPlugins(void) {
- int ret;
-
- signal(SIGINT, SignalExit);
- signal(SIGPIPE, SignalExit);
-
- GPU_clearDynarec(clearDynarec);
-
- ret = CDR_open();
- if (ret < 0) { SysMessage(_("Error opening CD-ROM plugin!")); return -1; }
- ret = SPU_open();
- if (ret < 0) { SysMessage(_("Error opening SPU plugin!")); return -1; }
- SPU_registerCallback(SPUirq);
- // pcsx-rearmed: we handle gpu elsewhere
- //ret = GPU_open(&gpuDisp, "PCSX", NULL);
- //if (ret < 0) { SysMessage(_("Error opening GPU plugin!")); return -1; }
- ret = PAD1_open(&gpuDisp);
- if (ret < 0) { SysMessage(_("Error opening Controller 1 plugin!")); return -1; }
- ret = PAD2_open(&gpuDisp);
- if (ret < 0) { SysMessage(_("Error opening Controller 2 plugin!")); return -1; }
-
- if (Config.UseNet && !NetOpened) {
- netInfo info;
- char path[MAXPATHLEN];
- char dotdir[MAXPATHLEN];
-
- MAKE_PATH(dotdir, "/.pcsx/plugins/", NULL);
-
- strcpy(info.EmuName, "PCSX " PACKAGE_VERSION);
- strncpy(info.CdromID, CdromId, 9);
- strncpy(info.CdromLabel, CdromLabel, 9);
- info.psxMem = psxM;
- info.GPU_showScreenPic = GPU_showScreenPic;
- info.GPU_displayText = GPU_displayText;
- info.GPU_showScreenPic = GPU_showScreenPic;
- info.PAD_setSensitive = PAD1_setSensitive;
- sprintf(path, "%s%s", Config.BiosDir, Config.Bios);
- strcpy(info.BIOSpath, path);
- strcpy(info.MCD1path, Config.Mcd1);
- strcpy(info.MCD2path, Config.Mcd2);
- sprintf(path, "%s%s", dotdir, Config.Gpu);
- strcpy(info.GPUpath, path);
- sprintf(path, "%s%s", dotdir, Config.Spu);
- strcpy(info.SPUpath, path);
- sprintf(path, "%s%s", dotdir, Config.Cdr);
- strcpy(info.CDRpath, path);
- NET_setInfo(&info);
-
- ret = NET_open(&gpuDisp);
- if (ret < 0) {
- if (ret == -2) {
- // -2 is returned when something in the info
- // changed and needs to be synced
- char *ptr;
-
- PARSEPATH(Config.Bios, info.BIOSpath);
- PARSEPATH(Config.Gpu, info.GPUpath);
- PARSEPATH(Config.Spu, info.SPUpath);
- PARSEPATH(Config.Cdr, info.CDRpath);
-
- strcpy(Config.Mcd1, info.MCD1path);
- strcpy(Config.Mcd2, info.MCD2path);
- return -2;
- } else {
- Config.UseNet = FALSE;
- }
- } else {
- if (NET_queryPlayer() == 1) {
- if (SendPcsxInfo() == -1) Config.UseNet = FALSE;
- } else {
- if (RecvPcsxInfo() == -1) Config.UseNet = FALSE;
- }
- }
- NetOpened = TRUE;
- } else if (Config.UseNet) {
- NET_resume();
- }
-
- return 0;
-}
-
-int OpenPlugins() {
- int ret;
-
- while ((ret = _OpenPlugins()) == -2) {
- ReleasePlugins();
- LoadMcds(Config.Mcd1, Config.Mcd2);
- if (LoadPlugins() == -1) return -1;
- }
- return ret;
-}
-
-void ClosePlugins() {
- int ret;
-
- signal(SIGINT, SIG_DFL);
- signal(SIGPIPE, SIG_DFL);
- ret = CDR_close();
- if (ret < 0) { SysMessage(_("Error closing CD-ROM plugin!")); return; }
- ret = SPU_close();
- if (ret < 0) { SysMessage(_("Error closing SPU plugin!")); return; }
- ret = PAD1_close();
- if (ret < 0) { SysMessage(_("Error closing Controller 1 Plugin!")); return; }
- ret = PAD2_close();
- if (ret < 0) { SysMessage(_("Error closing Controller 2 plugin!")); return; }
- // pcsx-rearmed: we handle gpu elsewhere
- //ret = GPU_close();
- //if (ret < 0) { SysMessage(_("Error closing GPU plugin!")); return; }
-
- if (Config.UseNet) {
- NET_pause();
- }
-}
-
-#if 1
-/* this is to avoid having to hack every plugin to stop using $HOME */
-char *getenv(const char *name)
-{
- static char ret[8] = ".";
-
- if (name && strcmp(name, "HOME") == 0 &&
- ((int)name >> 28) == 0) // HACK: let libs find home
- return ret;
-
- return real_getenv(name);
-}
-#endif
-
-/* we hook statically linked plugins here */
-static const char *builtin_plugins[] = {
- "builtin_gpu", "builtin_spu", "builtin_cdr", "builtin_pad",
- "builtin_cdrcimg",
-};
-
-static const int builtin_plugin_ids[] = {
- PLUGIN_GPU, PLUGIN_SPU, PLUGIN_CDR, PLUGIN_PAD,
- PLUGIN_CDRCIMG,
-};
-
-void *SysLoadLibrary(const char *lib) {
- const char *tmp = strrchr(lib, '/');
- void *ret;
- int i;
-
- printf("plugin: %s\n", lib);
-
- if (tmp != NULL) {
- tmp++;
- for (i = 0; i < ARRAY_SIZE(builtin_plugins); i++)
- if (strcmp(tmp, builtin_plugins[i]) == 0)
- return (void *)(long)(PLUGIN_DL_BASE + builtin_plugin_ids[i]);
- }
-
-#if defined(__x86_64__) || defined(__i386__)
- // convenience hack
- char name[MAXPATHLEN];
- snprintf(name, sizeof(name), "%s.x86", lib);
- lib = name;
-#endif
-
- ret = dlopen(lib, RTLD_NOW);
- if (ret == NULL)
- fprintf(stderr, "dlopen: %s\n", dlerror());
- return ret;
-}
-
-void *SysLoadSym(void *lib, const char *sym) {
- unsigned int plugid = (unsigned int)(long)lib;
-
- if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
- return plugin_link(plugid - PLUGIN_DL_BASE, sym);
-
- return dlsym(lib, sym);
-}
-
-const char *SysLibError() {
- return dlerror();
-}
-
-void SysCloseLibrary(void *lib) {
- unsigned int plugid = (unsigned int)(long)lib;
-
- if (PLUGIN_DL_BASE <= plugid && plugid < PLUGIN_DL_BASE + ARRAY_SIZE(builtin_plugins))
- return;
-
- dlclose(lib);
-}
-