+ menu_prepare_emu();
+}
+
+static void scan_plugins(void)
+{
+ char fname[MAXPATHLEN];
+ struct dirent *ent;
+ int gpu_i, spu_i;
+ char *p;
+ DIR *dir;
+
+ gpu_plugins[0] = "builtin_gpu";
+ spu_plugins[0] = "builtin_spu";
+ gpu_i = spu_i = 1;
+
+ snprintf(fname, sizeof(fname), "%s/", Config.PluginsDir);
+ dir = opendir(fname);
+ if (dir == NULL) {
+ perror("scan_plugins opendir");
+ return;
+ }
+
+ while (1) {
+ void *h, *tmp;
+
+ errno = 0;
+ ent = readdir(dir);
+ if (ent == NULL) {
+ if (errno != 0)
+ perror("readdir");
+ break;
+ }
+ p = strstr(ent->d_name, ".so");
+ if (p == NULL)
+ continue;
+
+ snprintf(fname, sizeof(fname), "%s/%s", Config.PluginsDir, ent->d_name);
+ h = dlopen(fname, RTLD_LAZY | RTLD_LOCAL);
+ if (h == NULL) {
+ fprintf(stderr, "%s\n", dlerror());
+ continue;
+ }
+
+ // now what do we have here?
+ tmp = dlsym(h, "GPUinit");
+ if (tmp) {
+ dlclose(h);
+ if (gpu_i < ARRAY_SIZE(gpu_plugins) - 1)
+ gpu_plugins[gpu_i++] = strdup(ent->d_name);
+ continue;
+ }
+
+ tmp = dlsym(h, "SPUinit");
+ if (tmp) {
+ dlclose(h);
+ if (spu_i < ARRAY_SIZE(spu_plugins) - 1)
+ spu_plugins[spu_i++] = strdup(ent->d_name);
+ continue;
+ }
+
+ fprintf(stderr, "ignoring unidentified plugin: %s\n", fname);
+ dlclose(h);
+ }
+
+ closedir(dir);
+}
+
+void menu_init(void)
+{
+ char buff[MAXPATHLEN];
+
+ strcpy(last_selected_fname, "/media");
+
+ scan_plugins();
+ pnd_menu_init();
+ menu_init_common();
+
+ menu_set_defconfig();
+ menu_load_config(0);
+ last_psx_w = 320;
+ last_psx_h = 240;
+ last_psx_bpp = 16;
+
+ g_menubg_src_ptr = calloc(g_menuscreen_w * g_menuscreen_h * 2, 1);
+ if (g_menubg_src_ptr == NULL)
+ exit(1);
+ emu_make_path(buff, "skin/background.png", sizeof(buff));
+ readpng(g_menubg_src_ptr, buff, READPNG_BG, g_menuscreen_w, g_menuscreen_h);
+}
+
+void menu_notify_mode_change(int w, int h, int bpp)
+{
+ last_psx_w = w;
+ last_psx_h = h;
+ last_psx_bpp = bpp;
+
+ if (scaling == SCALE_1_1) {
+ g_layer_x = 800/2 - w/2; g_layer_y = 480/2 - h/2;
+ g_layer_w = w; g_layer_h = h;
+ }
+}
+
+static void menu_leave_emu(void)
+{
+ if (GPU_close != NULL) {
+ int ret = GPU_close();
+ if (ret)
+ fprintf(stderr, "Warning: GPU_close returned %d\n", ret);
+ }
+
+ memcpy(g_menubg_ptr, g_menubg_src_ptr, g_menuscreen_w * g_menuscreen_h * 2);
+ if (ready_to_go && last_psx_bpp == 16) {
+ int x = max(0, g_menuscreen_w - last_psx_w);
+ int y = max(0, g_menuscreen_h / 2 - last_psx_h / 2);
+ int w = min(g_menuscreen_w, last_psx_w);
+ int h = min(g_menuscreen_h, last_psx_h);
+ u16 *d = (u16 *)g_menubg_ptr + g_menuscreen_w * y + x;
+ u16 *s = pl_fbdev_buf;
+
+ for (; h > 0; h--, d += g_menuscreen_w, s += last_psx_w)
+ menu_darken_bg(d, s, w, 0);
+ }
+}
+
+void menu_prepare_emu(void)
+{
+ switch (scaling) {
+ case SCALE_1_1:
+ menu_notify_mode_change(last_psx_w, last_psx_h, last_psx_bpp);
+ break;
+ case SCALE_4_3:
+ g_layer_x = 80; g_layer_y = 0;
+ g_layer_w = 640; g_layer_h = 480;
+ break;
+ case SCALE_FULLSCREEN:
+ g_layer_x = 0; g_layer_y = 0;
+ g_layer_w = 800; g_layer_h = 480;
+ break;
+ case SCALE_CUSTOM:
+ break;
+ }
+ apply_filter(filter);
+ apply_cpu_clock();