pcsxr-1.9.92
[pcsx_rearmed.git] / gui / ConfDlg.c
1 /*  Pcsx - Pc Psx Emulator
2  *  Copyright (C) 1999-2002  Pcsx Team
3  *
4  *  This program is free software; you can redistribute it and/or modify
5  *  it under the terms of the GNU General Public License as published by
6  *  the Free Software Foundation; either version 2 of the License, or
7  *  (at your option) any later version.
8  *
9  *  This program is distributed in the hope that it will be useful,
10  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
11  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
12  *  GNU General Public License for more details.
13  *
14  *  You should have received a copy of the GNU General Public License
15  *  along with this program; if not, write to the Free Software
16  *  Foundation, Inc., 51 Franklin Street, Fifth Floor, Boston, MA 02111-1307 USA
17  */
18
19 #include <stdio.h>
20 #include <stdlib.h>
21 #include <unistd.h>
22 #include <string.h>
23 #include <dirent.h>
24 #include <dlfcn.h>
25 #include <sys/stat.h>
26 #include <gdk/gdkkeysyms.h>
27 #include <gtk/gtk.h>
28 #include <glade/glade.h>
29 #include <signal.h>
30 #include <sys/time.h>
31 #include <regex.h>
32 #include "Linux.h"
33 #include "ConfDlg.h"
34
35 #include "../libpcsxcore/plugins.h"
36
37 static void OnBiosPath_Changed(GtkWidget *wdg, gpointer data);
38 static void OnConf_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data);
39 static void OnPluginPath_Changed(GtkWidget *wdg, gpointer data);
40 static void OnConfConf_Pad1About(GtkWidget *widget, gpointer user_data);
41 static void OnConfConf_Pad2About(GtkWidget *widget, gpointer user_data);
42 static void OnConfConf_Pad1Conf(GtkWidget *widget, gpointer user_data);
43 static void OnConfConf_Pad2Conf(GtkWidget *widget, gpointer user_data);
44 static void OnNet_Conf(GtkWidget *widget, gpointer user_data);
45 static void OnNet_About(GtkWidget *widget, gpointer user_data);
46 static void on_configure_plugin(GtkWidget *widget, gpointer user_data);
47 static void on_about_plugin(GtkWidget *widget, gpointer user_data);
48 static void UpdatePluginsBIOS_UpdateGUI(GladeXML *xml);
49 static void FindNetPlugin(GladeXML *xml);
50
51 PSEgetLibType           PSE_getLibType = NULL;
52 PSEgetLibVersion        PSE_getLibVersion = NULL;
53 PSEgetLibName           PSE_getLibName = NULL;
54
55 GtkWidget *ConfDlg = NULL;
56 GtkWidget *NetDlg = NULL;
57 GtkWidget *controlwidget = NULL;
58
59 PluginConf GpuConfS;
60 PluginConf SpuConfS;
61 PluginConf CdrConfS;
62 PluginConf Pad1ConfS;
63 PluginConf Pad2ConfS;
64 PluginConf NetConfS;
65 PluginConf BiosConfS;
66
67 #define FindComboText(combo, list, conf) \
68         if (strlen(conf) > 0) { \
69                 int i; \
70                 for (i = 2; i < 255; i += 2) { \
71                         if (!strcmp(conf, list[i - 2])) { \
72                                 gtk_combo_box_set_active(GTK_COMBO_BOX(combo), i / 2 - 1); \
73                                 break; \
74                         } \
75                 } \
76         }
77
78 #define GetComboText(combo, list, conf) \
79         { \
80                 int row; \
81                 row = gtk_combo_box_get_active(GTK_COMBO_BOX(combo)); \
82                 strcpy(conf, (char *)list[row * 2]); \
83         }
84
85 void ConfigurePlugins() {
86         if (!UseGui) {
87                 /* How do we get here if we're not running the GUI? */
88                 /* Ryan: we're going to imagine that someday, there will be a way
89                  * to configure plugins from the commandline */
90                 printf("ERROR: Plugins cannot be configured without the GUI.");
91                 return;
92         }
93
94         GladeXML *xml;
95         GtkWidget *widget;
96
97         gchar *path;
98
99         UpdatePluginsBIOS();
100
101         xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "ConfDlg", NULL);
102
103         if (!xml) {
104                 g_warning(_("Error: Glade interface could not be loaded!"));
105                 return;
106         }
107
108         UpdatePluginsBIOS_UpdateGUI(xml);
109
110         ConfDlg = glade_xml_get_widget(xml, "ConfDlg");
111
112         gtk_window_set_title(GTK_WINDOW(ConfDlg), _("Configure PCSX"));
113
114         /* Set the paths in the file choosers to be based on the saved configurations */
115         widget = glade_xml_get_widget(xml, "GtkFileChooser_Bios");
116         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), Config.BiosDir);
117
118         widget = glade_xml_get_widget(xml, "GtkFileChooser_Plugin");
119         gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (widget), Config.PluginsDir);
120
121         if (strlen(Config.PluginsDir) == 0) {
122                 if((path = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (widget))) != NULL) {
123                         strcpy(Config.PluginsDir, path);
124                         g_free(path);
125                 }
126         }
127
128         widget = glade_xml_get_widget(xml, "btn_ConfGpu");
129         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
130                         GTK_SIGNAL_FUNC(on_configure_plugin), (gpointer) PSE_LT_GPU, NULL, G_CONNECT_AFTER);
131
132         widget = glade_xml_get_widget(xml, "btn_ConfSpu");
133         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
134                         GTK_SIGNAL_FUNC(on_configure_plugin), (gpointer) PSE_LT_SPU, NULL, G_CONNECT_AFTER);
135
136         /* ADB TODO Does pad 1 and 2 need to be different? */
137         widget = glade_xml_get_widget(xml, "btn_ConfPad1");
138         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
139                                                   GTK_SIGNAL_FUNC(OnConfConf_Pad1Conf), xml, NULL, G_CONNECT_AFTER);
140
141         widget = glade_xml_get_widget(xml, "btn_ConfPad2");
142         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
143                         GTK_SIGNAL_FUNC(OnConfConf_Pad2Conf), xml, NULL, G_CONNECT_AFTER);
144
145         widget = glade_xml_get_widget(xml, "btn_ConfCdr");
146         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
147                         GTK_SIGNAL_FUNC(on_configure_plugin), (gpointer) PSE_LT_CDR, NULL, G_CONNECT_AFTER);
148
149         widget = glade_xml_get_widget(xml, "btn_AboutGpu");
150         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
151                         GTK_SIGNAL_FUNC(on_about_plugin), (gpointer) PSE_LT_GPU, NULL, G_CONNECT_AFTER);
152
153         widget = glade_xml_get_widget(xml, "btn_AboutSpu");
154         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
155                         GTK_SIGNAL_FUNC(on_about_plugin), (gpointer) PSE_LT_SPU, NULL, G_CONNECT_AFTER);
156
157         widget = glade_xml_get_widget(xml, "btn_AboutPad1");
158         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
159                         GTK_SIGNAL_FUNC(OnConfConf_Pad1About), xml, NULL, G_CONNECT_AFTER);
160
161         widget = glade_xml_get_widget(xml, "btn_AboutPad2");
162         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
163                         GTK_SIGNAL_FUNC(OnConfConf_Pad2About), xml, NULL, G_CONNECT_AFTER);
164
165         widget = glade_xml_get_widget(xml, "btn_AboutCdr");
166         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
167                         GTK_SIGNAL_FUNC(on_about_plugin), (gpointer) PSE_LT_CDR, NULL, G_CONNECT_AFTER);
168
169         widget = glade_xml_get_widget(xml, "GtkFileChooser_Bios");
170         g_signal_connect_data(GTK_OBJECT(widget), "current_folder_changed",
171                         GTK_SIGNAL_FUNC(OnBiosPath_Changed), xml, NULL, G_CONNECT_AFTER);
172
173         widget = glade_xml_get_widget(xml, "GtkFileChooser_Plugin");
174         g_signal_connect_data(GTK_OBJECT(widget), "current_folder_changed",
175                         GTK_SIGNAL_FUNC(OnPluginPath_Changed), xml, NULL, G_CONNECT_AFTER);
176
177         g_signal_connect_data(GTK_OBJECT(ConfDlg), "response",
178                         GTK_SIGNAL_FUNC(OnConf_Clicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
179 }
180
181 void OnNet_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) {
182         GetComboText(NetConfS.Combo, NetConfS.plist, Config.Net);
183         SaveConfig();
184         gtk_widget_destroy(GTK_WIDGET(dialog));
185         NetDlg = NULL;
186 }
187
188 void OnConf_Net() {
189         GladeXML *xml;
190         GtkWidget *widget;
191
192         if (NetDlg != NULL) {
193                 gtk_window_present (GTK_WINDOW (NetDlg));
194                 return;
195         }
196
197         xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "NetDlg", NULL);
198
199         if (!xml) {
200                 g_warning(_("Error: Glade interface could not be loaded!"));
201                 return;
202         }
203
204         NetDlg = glade_xml_get_widget(xml, "NetDlg");
205
206         FindNetPlugin(xml);
207
208         /* Setup a handler for when Close or Cancel is clicked */
209         g_signal_connect_data(GTK_OBJECT(NetDlg), "response",
210                         GTK_SIGNAL_FUNC(OnNet_Clicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
211
212         widget = glade_xml_get_widget(xml, "btn_ConfNet");
213         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
214                         GTK_SIGNAL_FUNC(OnNet_Conf), xml, NULL, G_CONNECT_AFTER);
215
216         widget = glade_xml_get_widget(xml, "btn_AboutNet");
217         g_signal_connect_data(GTK_OBJECT(widget), "clicked",
218                         GTK_SIGNAL_FUNC(OnNet_About), xml, NULL, G_CONNECT_AFTER);
219 }
220
221 void OnConf_Graphics() {
222         void *drv;
223         GPUconfigure conf;
224         char Plugin[MAXPATHLEN];
225
226         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Gpu);
227         drv = SysLoadLibrary(Plugin);
228         if (drv == NULL) { printf("Error with file %s\n", Plugin); return; }
229
230         while (gtk_events_pending()) gtk_main_iteration();
231
232         conf = (GPUconfigure)SysLoadSym(drv, "GPUconfigure");
233         if (conf != NULL) {
234                 conf();
235         }
236         else
237                 SysInfoMessage (_("No configuration required"), _("This plugin doesn't need to be configured."));
238
239         SysCloseLibrary(drv);
240 }
241
242 void OnConf_Sound() {
243         void *drv;
244         SPUconfigure conf;
245         char Plugin[MAXPATHLEN];
246
247         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Spu);
248         drv = SysLoadLibrary(Plugin);
249         if (drv == NULL) { printf("Error with file %s\n", Plugin); return; }
250
251         while (gtk_events_pending()) gtk_main_iteration();
252
253         conf = (GPUconfigure)SysLoadSym(drv, "SPUconfigure");
254         if (conf != NULL) {
255                 conf();
256         }
257         else
258                 SysInfoMessage (_("No configuration required"), _("This plugin doesn't need to be configured."));
259
260         SysCloseLibrary(drv);
261 }
262
263 void OnConf_CdRom() {
264         void *drv;
265         CDRconfigure conf;
266         char Plugin[MAXPATHLEN];
267
268         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Cdr);
269         drv = SysLoadLibrary(Plugin);
270         if (drv == NULL) { printf("Error with file %s\n", Plugin); return; }
271
272         while (gtk_events_pending()) gtk_main_iteration();
273
274         conf = (GPUconfigure)SysLoadSym(drv, "CDRconfigure");
275         if (conf != NULL) {
276                 conf();
277         }
278         else
279                 SysInfoMessage (_("No configuration required"), _("This plugin doesn't need to be configured."));
280
281         SysCloseLibrary(drv);
282 }
283
284 void OnConf_Pad() {
285         void *drv;
286         PADconfigure conf;
287         char Plugin[MAXPATHLEN];
288
289         sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad1);
290         drv = SysLoadLibrary(Plugin);
291         if (drv == NULL) { printf("Error with file %s\n", Plugin); return; }
292
293         while (gtk_events_pending()) gtk_main_iteration();
294
295         conf = (GPUconfigure)SysLoadSym(drv, "PADconfigure");
296         if (conf != NULL) {
297                 conf();
298         }
299         else
300                 SysInfoMessage (_("No configuration required"), _("This plugin doesn't need to be configured."));
301
302         SysCloseLibrary(drv);
303
304         if (strcmp(Config.Pad1, Config.Pad2) != 0) {
305                 sprintf(Plugin, "%s/%s", Config.PluginsDir, Config.Pad2);
306                 drv = SysLoadLibrary(Plugin);
307                 if (drv == NULL) { printf("Error with file %s\n", Plugin); return; }
308
309                 while (gtk_events_pending()) gtk_main_iteration();
310
311                 conf = (GPUconfigure)SysLoadSym(drv, "PADconfigure");
312                 if (conf != NULL) {
313                         conf();
314                 }
315
316                 SysCloseLibrary(drv);
317         }
318 }
319
320 static int all_config_set() {
321         int retval;
322
323         if ((strlen(Config.Gpu) != 0) &&
324             (strlen(Config.Spu) != 0) &&
325             (strlen(Config.Cdr) != 0) &&
326             (strlen(Config.Pad1) != 0) &&
327             (strlen(Config.Pad2) != 0))
328                 retval = TRUE;
329         else
330                 retval = FALSE;
331
332         return retval;
333 }
334
335 /* TODO Check whether configuration is required when we choose the plugin, and set the state of the
336     button appropriately. New gtk tooltip API should allow us to put a tooltip explanation for
337     disabled widgets */
338 /* TODO If combo screen hasn't been opened and the user chooses the menu config option, confs.Combo will be null and cause a segfault */
339 #define ConfPlugin(src, confs, plugin, name, parent)  { \
340         void *drv; \
341         src conf; \
342         gchar *filename; \
343  \
344         GetComboText(confs.Combo, confs.plist, plugin); \
345         filename = g_build_filename (getenv("HOME"), PLUGINS_DIR, plugin, NULL); \
346         /*printf("Configuring plugin %s\n", filename);*/ \
347         drv = SysLoadLibrary(filename); \
348         if (drv == NULL) {printf("Error with file %s\n", filename);return; } \
349 \
350         while (gtk_events_pending()) gtk_main_iteration(); \
351         conf = (src) SysLoadSym(drv, name); \
352         if (conf) { \
353                 conf(); \
354         } else \
355                 SysInfoMessage (_("No configuration required"), _("This plugin doesn't need to be configured.")); \
356         SysCloseLibrary(drv); \
357         g_free (filename); \
358 }
359
360 static void on_configure_plugin(GtkWidget *widget, gpointer user_data) {
361         gint plugin_type = (int) user_data;
362
363         while (gtk_events_pending())
364                 gtk_main_iteration();
365         if (all_config_set() == TRUE) {
366                 switch (plugin_type) {
367                         case PSE_LT_GPU:
368                                 ConfPlugin(GPUconfigure, GpuConfS, Config.Gpu, "GPUconfigure", ConfDlg);
369                                 break;
370                         case PSE_LT_SPU:
371                                 ConfPlugin(SPUconfigure, SpuConfS, Config.Spu, "SPUconfigure", ConfDlg);
372                                 break;
373                         case PSE_LT_CDR:
374                                 ConfPlugin(CDRconfigure, CdrConfS, Config.Cdr, "CDRconfigure", ConfDlg);
375                                 break;
376                 }
377         } else
378                 ConfigurePlugins();
379 }
380
381 static void on_about_plugin(GtkWidget *widget, gpointer user_data) {
382         gint plugin_type = (int) user_data;
383
384         while (gtk_events_pending())
385                 gtk_main_iteration();
386         if (all_config_set() == TRUE) {
387                 switch (plugin_type) {
388                         case PSE_LT_GPU:
389                                 ConfPlugin(GPUconfigure, GpuConfS, Config.Gpu, "GPUabout", ConfDlg);
390                                 break;
391                         case PSE_LT_SPU:
392                                 ConfPlugin(SPUconfigure, SpuConfS, Config.Spu, "SPUabout", ConfDlg);
393                                 break;
394                         case PSE_LT_CDR:
395                                 ConfPlugin(CDRconfigure, CdrConfS, Config.Cdr, "CDRabout", ConfDlg);
396                                 break;
397                 }
398         } else
399                 ConfigurePlugins();
400 }
401
402 static void OnConfConf_Pad1About(GtkWidget *widget, gpointer user_data) {
403         ConfPlugin(PADabout, Pad1ConfS, Config.Pad1, "PADabout", ConfDlg);
404 }
405
406 static void OnConfConf_Pad2About(GtkWidget *widget, gpointer user_data) {
407         ConfPlugin(PADabout, Pad2ConfS, Config.Pad2, "PADabout", ConfDlg);
408 }
409
410 static void OnConfConf_Pad1Conf(GtkWidget *widget, gpointer user_data) {
411         ConfPlugin(PADabout, Pad1ConfS, Config.Pad1, "PADconfigure", ConfDlg);
412 }
413
414 static void OnConfConf_Pad2Conf(GtkWidget *widget, gpointer user_data) {
415         ConfPlugin(PADabout, Pad2ConfS, Config.Pad2, "PADconfigure", ConfDlg);
416 }
417
418 static void OnNet_Conf(GtkWidget *widget, gpointer user_data) {
419         ConfPlugin(NETconfigure, NetConfS, Config.Net, "NETconfigure", NetDlg);
420 }
421
422 static void OnNet_About(GtkWidget *widget, gpointer user_data) {
423         ConfPlugin(NETabout, NetConfS, Config.Net, "NETabout", NetDlg);
424 }
425
426 static void OnPluginPath_Changed(GtkWidget *wdg, gpointer data) {
427         gchar *path;
428
429         path = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (wdg));
430         strcpy(Config.PluginsDir, path);
431         UpdatePluginsBIOS();
432         UpdatePluginsBIOS_UpdateGUI(data);
433
434         g_free(path);
435 }
436
437 static void OnBiosPath_Changed(GtkWidget *wdg, gpointer data) {
438         gchar *foldername;
439
440         foldername = gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (wdg));
441         strcpy(Config.BiosDir, foldername);
442
443         UpdatePluginsBIOS();
444         UpdatePluginsBIOS_UpdateGUI(data);
445
446         g_free(foldername);
447 }
448
449 void OnConf_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) {
450         GetComboText(GpuConfS.Combo, GpuConfS.plist, Config.Gpu);
451         GetComboText(SpuConfS.Combo, SpuConfS.plist, Config.Spu);
452         GetComboText(CdrConfS.Combo, CdrConfS.plist, Config.Cdr);
453         GetComboText(Pad1ConfS.Combo, Pad1ConfS.plist, Config.Pad1);
454         GetComboText(Pad2ConfS.Combo, Pad2ConfS.plist, Config.Pad2);
455         GetComboText(BiosConfS.Combo, BiosConfS.plist, Config.Bios);
456
457         SaveConfig();
458
459         gtk_widget_destroy(ConfDlg);
460         ConfDlg = NULL;
461 }
462
463 #define ComboAddPlugin(type) { \
464         type##ConfS.plugins += 2; \
465         strcpy(type##ConfS.plist[type##ConfS.plugins - 1], name); \
466         strcpy(type##ConfS.plist[type##ConfS.plugins - 2], ent->d_name); \
467         type##ConfS.glist = g_list_append(type##ConfS.glist, type##ConfS.plist[type##ConfS.plugins-1]); \
468 }
469
470 void populate_combo_box(GtkWidget *widget, GList *list) {
471         GtkListStore *store;
472         GtkCellRenderer *renderer;
473         store = gtk_list_store_new(1, G_TYPE_STRING);
474
475         // Clear existing data from combo box
476         gtk_cell_layout_clear(GTK_CELL_LAYOUT(widget));
477
478         renderer = gtk_cell_renderer_text_new();
479         gtk_cell_layout_pack_start(GTK_CELL_LAYOUT(widget), renderer, FALSE);
480         gtk_cell_layout_add_attribute(GTK_CELL_LAYOUT(widget), renderer, "text", 0);
481
482         while (list != NULL) {
483                 GtkTreeIter iter;
484                 gtk_list_store_append(store, &iter);
485                 gtk_list_store_set(store, &iter, 0, (char *)list->data, -1);
486                 list = list->next;
487         }
488
489         gtk_combo_box_set_model(GTK_COMBO_BOX(widget), GTK_TREE_MODEL(store));
490 }
491
492 #define ConfCreatePConf(name, type) \
493         /* Populate the relevant combo widget with the list of plugins. \
494            If no plugins available, disable the combo and its controls. \
495            Note that the Bios plugin has no About/Conf control. */ \
496         type##ConfS.Combo = glade_xml_get_widget(xml, "GtkCombo_" name); \
497         if (type##ConfS.glist != NULL) { \
498                 populate_combo_box (type##ConfS.Combo, type##ConfS.glist); \
499                 FindComboText(type##ConfS.Combo, type##ConfS.plist, Config.type); \
500                 gtk_widget_set_sensitive (type##ConfS.Combo, TRUE); \
501                 if (g_ascii_strcasecmp (name, "Bios") != 0) { \
502                         controlwidget = glade_xml_get_widget(xml, "btn_Conf" name); \
503                         gtk_widget_set_sensitive (controlwidget, TRUE); \
504                         controlwidget = glade_xml_get_widget(xml, "btn_About" name); \
505                         gtk_widget_set_sensitive (controlwidget, TRUE); \
506                 } \
507         } else { \
508                 if (g_ascii_strcasecmp (name, "Bios") != 0) { \
509                         gtk_cell_layout_clear (GTK_CELL_LAYOUT (type##ConfS.Combo)); \
510                         gtk_widget_set_sensitive (type##ConfS.Combo, FALSE); \
511                         controlwidget = glade_xml_get_widget(xml, "btn_Conf" name); \
512                         gtk_widget_set_sensitive (controlwidget, FALSE); \
513                         controlwidget = glade_xml_get_widget(xml, "btn_About" name); \
514                         gtk_widget_set_sensitive (controlwidget, FALSE); \
515                 } \
516         }
517
518 int plugin_is_available(gchar *plugin) {
519         int retval;
520         gchar *pluginfile;
521         struct stat stbuf;
522
523         pluginfile = g_strconcat(getenv("HOME"), PLUGINS_DIR, plugin, NULL);
524
525         if (stat(pluginfile, &stbuf) == -1)
526                 retval = FALSE;
527         else
528                 retval = TRUE;
529
530         g_free(pluginfile);
531
532         return retval;
533 }
534
535 int plugins_configured() {
536         // make sure there are choices for all of the plugins!!
537         if (all_config_set() == FALSE)
538                 return FALSE;
539
540         // and make sure they can all be accessed
541         // if they can't be, wipe the variable and return FALSE
542         if (plugin_is_available (Config.Gpu) == FALSE) { Config.Gpu[0] = '\0'; return FALSE; }
543         if (plugin_is_available (Config.Spu) == FALSE) { Config.Spu[0] = '\0'; return FALSE; }
544         if (plugin_is_available (Config.Cdr) == FALSE) { Config.Cdr[0] = '\0'; return FALSE; }
545         if (plugin_is_available (Config.Pad1) == FALSE) { Config.Pad1[0] = '\0'; return FALSE; }
546         if (plugin_is_available (Config.Pad2) == FALSE) { Config.Pad2[0] = '\0'; return FALSE; }
547
548         // if everything is happy, return TRUE
549         return TRUE;
550 }
551
552 int is_valid_bios_file(gchar *filename) {
553         int valid;
554         struct stat buf;
555
556         if ((stat(filename, &buf) == -1) || (buf.st_size != (1024*512)))
557                 valid = FALSE;
558         else {
559                 valid = TRUE;
560         }
561
562         return valid;
563 }
564
565 // Add the name of the BIOS file to the drop-down list. This will
566 // be the filename, not the full path to the file
567 void add_bios_to_list(gchar *bios_name, gchar *internal_name) {
568         BiosConfS.plugins += 2;
569         strcpy(BiosConfS.plist[BiosConfS.plugins - 1], bios_name);
570         strcpy(BiosConfS.plist[BiosConfS.plugins - 2], internal_name);
571         BiosConfS.glist = g_list_append(BiosConfS.glist, BiosConfS.plist[BiosConfS.plugins - 1]);
572 }
573
574 void scan_bios_dir(gchar *dirname) {
575         DIR *dir;
576         struct dirent *ent;
577         gchar *filename;
578
579         dir = opendir(dirname);
580         if (dir == NULL) {
581                 SysMessage(_("Could not open BIOS directory: '%s'\n"), dirname);
582                 return;
583         }
584
585         while ((ent = readdir(dir)) != NULL) {
586                 filename = g_build_filename(dirname, ent->d_name, NULL);
587                 if (is_valid_bios_file(filename))
588                         add_bios_to_list(g_path_get_basename(filename), g_path_get_basename (filename));
589                 g_free(filename);
590         }
591         closedir(dir);
592 }
593
594 void UpdatePluginsBIOS() {
595         DIR *dir;
596         struct dirent *ent;
597         void *Handle;
598         char name[256];
599         gchar *linkname;
600
601         GpuConfS.plugins  = 0; SpuConfS.plugins  = 0; CdrConfS.plugins  = 0;
602         Pad1ConfS.plugins = 0; Pad2ConfS.plugins = 0; BiosConfS.plugins = 0;
603         GpuConfS.glist  = NULL; SpuConfS.glist  = NULL; CdrConfS.glist  = NULL;
604         Pad1ConfS.glist = NULL; Pad2ConfS.glist = NULL; BiosConfS.glist = NULL;
605         GpuConfS.plist[0][0]  = '\0'; SpuConfS.plist[0][0]  = '\0'; CdrConfS.plist[0][0]  = '\0';
606         Pad1ConfS.plist[0][0] = '\0'; Pad2ConfS.plist[0][0] = '\0'; BiosConfS.plist[0][0] = '\0';
607
608         // Load and get plugin info
609         dir = opendir(Config.PluginsDir);
610         if (dir == NULL) {
611                 printf(_("Could not open directory: '%s'\n"), Config.PluginsDir);
612                 return;
613         }
614         while ((ent = readdir(dir)) != NULL) {
615                 long type, v;
616                 linkname = g_build_filename(Config.PluginsDir, ent->d_name, NULL);
617
618                 // only libraries past this point, not config tools
619                 if (strstr(linkname, ".so") == NULL && strstr(linkname, ".dylib") == NULL)
620                         continue;
621
622                 Handle = dlopen(linkname, RTLD_NOW);
623                 if (Handle == NULL) {
624                         printf("%s\n", dlerror());
625                         g_free(linkname);
626                         continue;
627                 }
628
629                 PSE_getLibType = (PSEgetLibType)dlsym(Handle, "PSEgetLibType");
630                 if (PSE_getLibType == NULL) {
631                         if (strstr(linkname, "gpu") != NULL) type = PSE_LT_GPU;
632                         else if (strstr(linkname, "cdr") != NULL) type = PSE_LT_CDR;
633                         else if (strstr(linkname, "spu") != NULL) type = PSE_LT_SPU;
634                         else if (strstr(linkname, "pad") != NULL) type = PSE_LT_PAD;
635                         else { g_free(linkname); continue; }
636                 }
637                 else type = PSE_getLibType();
638
639                 PSE_getLibName = (PSEgetLibName) dlsym(Handle, "PSEgetLibName");
640                 if (PSE_getLibName != NULL) {
641                         sprintf(name, "%s", PSE_getLibName());
642                         PSE_getLibVersion = (PSEgetLibVersion) dlsym(Handle, "PSEgetLibVersion");
643                         if (PSE_getLibVersion != NULL) {
644                                 char ver[32];
645
646                                 v = PSE_getLibVersion();
647                                 sprintf(ver, " %ld.%ld.%ld", v >> 16, (v >> 8) & 0xff, v & 0xff);
648                                 strcat(name, ver);
649                         }
650                 }
651                 else strcpy(name, ent->d_name);
652
653                 if (type & PSE_LT_CDR)
654                         ComboAddPlugin(Cdr);
655                 if (type & PSE_LT_GPU)
656                         ComboAddPlugin(Gpu);
657                 if (type & PSE_LT_SPU)
658                         ComboAddPlugin(Spu);
659                 if (type & PSE_LT_PAD) {
660                         PADquery query = (PADquery)dlsym(Handle, "PADquery");
661                         if (query() & 0x1) {
662                                 ComboAddPlugin(Pad1);
663                         }
664                         if (query() & 0x2) {
665                                 ComboAddPlugin(Pad2);
666                         }
667                 }
668                 g_free(linkname);
669         }
670         closedir(dir);
671
672         scan_bios_dir(Config.BiosDir);
673
674         // The BIOS list always contains the PCSX internal BIOS
675         add_bios_to_list(_("Simulate PSX BIOS"), "HLE");
676 }
677
678 static void UpdatePluginsBIOS_UpdateGUI(GladeXML *xml) {
679         // Populate the plugin combo boxes
680         ConfCreatePConf("Gpu", Gpu);
681         ConfCreatePConf("Spu", Spu);
682         ConfCreatePConf("Pad1", Pad1);
683         ConfCreatePConf("Pad2", Pad2);
684         ConfCreatePConf("Cdr", Cdr);
685         ConfCreatePConf("Bios", Bios);
686 }
687
688 static void FindNetPlugin(GladeXML *xml) {
689         DIR *dir;
690         struct dirent *ent;
691         void *Handle;
692         char plugin[MAXPATHLEN],name[MAXPATHLEN];
693
694         NetConfS.plugins  = 0;
695         NetConfS.glist = NULL; 
696
697         NetConfS.plugins += 2;
698         strcpy(NetConfS.plist[NetConfS.plugins - 1], "Disabled");
699         strcpy(NetConfS.plist[NetConfS.plugins - 2], "Disabled");
700         NetConfS.glist = g_list_append(NetConfS.glist, NetConfS.plist[NetConfS.plugins - 1]);
701
702         dir = opendir(Config.PluginsDir);
703         if (dir == NULL)
704                 SysMessage(_("Could not open directory: '%s'\n"), Config.PluginsDir);
705         else {
706                 /* ADB TODO Replace the following with a function */
707                 while ((ent = readdir(dir)) != NULL) {
708                         long type, v;
709
710                         sprintf(plugin, "%s/%s", Config.PluginsDir, ent->d_name);
711
712                         if (strstr(plugin, ".so") == NULL && strstr(plugin, ".dylib") == NULL)
713                                 continue;
714                         Handle = dlopen(plugin, RTLD_NOW);
715                         if (Handle == NULL) continue;
716
717                         PSE_getLibType = (PSEgetLibType) dlsym(Handle, "PSEgetLibType");
718                         if (PSE_getLibType == NULL) {
719                                 if (strstr(plugin, "net") != NULL) type = PSE_LT_NET;
720                                 else continue;
721                         }
722                         else type = PSE_getLibType();
723
724                         PSE_getLibName = (PSEgetLibName) dlsym(Handle, "PSEgetLibName");
725                         if (PSE_getLibName != NULL) {
726                                 sprintf(name, "%s", PSE_getLibName());
727                                 PSE_getLibVersion = (PSEgetLibVersion) dlsym(Handle, "PSEgetLibVersion");
728                                 if (PSE_getLibVersion != NULL) {
729                                         char ver[32];
730
731                                         v = PSE_getLibVersion();
732                                         sprintf(ver, " %ld.%ld.%ld",v>>16,(v>>8)&0xff,v&0xff);
733                                         strcat(name, ver);
734                                 }
735                         }
736                         else strcpy(name, ent->d_name);
737
738                         if (type & PSE_LT_NET) {
739                                 ComboAddPlugin(Net);
740                         }
741                 }
742                 closedir(dir);
743
744                 ConfCreatePConf("Net", Net);
745         }
746 }
747
748 GtkWidget *CpuDlg;
749 GtkWidget *PsxCombo;
750 GList *psxglist;
751 char *psxtypes[] = {
752         "NTSC",
753         "PAL"
754 };
755
756 // When the auto-detect CPU type is selected, disable the NTSC/PAL selection
757 static void OnCpu_PsxAutoClicked (GtkWidget *widget, gpointer user_data) {
758         GtkWidget *combo;
759         GladeXML *xml = user_data;
760         combo = glade_xml_get_widget(xml, "GtkCombo_PsxType");
761
762         gtk_widget_set_sensitive (combo,
763                         !(gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget))));
764 }
765
766 // When the interpreter core is deselected, disable the debugger checkbox
767 static void OnCpu_CpuClicked(GtkWidget *widget, gpointer user_data) {
768         GtkWidget *check;
769         GladeXML *xml = user_data;
770         check = glade_xml_get_widget(xml, "GtkCheckButton_Dbg");
771
772         // Debugger is only working with interpreter not recompiler, so let's set it
773         if (!gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)))
774                 gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (check), FALSE);
775
776         gtk_widget_set_sensitive (check,
777                         gtk_toggle_button_get_active (GTK_TOGGLE_BUTTON (widget)));
778 }
779
780 void OnCpu_Clicked(GtkDialog *dialog, gint arg1, gpointer user_data) {
781         GtkWidget *widget;
782         GladeXML *xml = user_data;
783         int tmp;
784         long t;
785
786         widget = glade_xml_get_widget(xml, "GtkCombo_PsxType");
787
788         // If nothing chosen, default to NTSC
789         tmp = gtk_combo_box_get_active (GTK_COMBO_BOX (widget));
790         if (tmp == -1)  
791                 tmp = PSX_TYPE_NTSC;
792
793         if (!strcmp("NTSC", psxtypes[tmp]))
794                 Config.PsxType = PSX_TYPE_NTSC;
795         else
796                 Config.PsxType = PSX_TYPE_PAL;
797
798         Config.Xa = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Xa")));
799         Config.Sio = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Sio")));
800         Config.Mdec = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Mdec")));
801         Config.Cdda = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_CDDA")));
802         Config.PsxAuto = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_PsxAuto")));
803
804         t = Config.Debug;
805         Config.Debug = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Dbg")));
806         if (t != Config.Debug) {
807                 if (Config.Debug) StartDebugger();
808                 else StopDebugger();
809         }
810
811         t = Config.Cpu;
812         Config.Cpu = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Cpu")));
813         if (t != Config.Cpu) {
814                 psxCpu->Shutdown();
815 #ifdef PSXREC
816                 if (Config.Cpu == CPU_INTERPRETER) {
817                         psxCpu = &psxInt;
818                 }
819                 else psxCpu = &psxRec;
820 #else
821                 psxCpu = &psxInt;
822 #endif
823                 if (psxCpu->Init() == -1) {
824                         SysClose();
825                         exit(1);
826                 }
827                 psxCpu->Reset();
828         }
829
830         Config.PsxOut = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_PsxOut")));
831         Config.SpuIrq = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_SpuIrq")));
832         Config.RCntFix = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_RCntFix")));
833         Config.VSyncWA = gtk_toggle_button_get_active(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_VSyncWA")));
834
835         SaveConfig();
836
837         gtk_widget_destroy(CpuDlg);
838         CpuDlg = NULL;
839 }
840
841 void OnConf_Cpu() {
842         GladeXML *xml;
843
844         xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "CpuDlg", NULL);
845
846         if (!xml) {
847                 g_warning("We could not load the interface!");
848                 return;
849         }
850
851         CpuDlg = glade_xml_get_widget(xml, "CpuDlg");
852
853         PsxCombo = glade_xml_get_widget(xml, "GtkCombo_PsxType");
854         gtk_combo_box_set_active(GTK_COMBO_BOX (PsxCombo), Config.PsxType);
855         gtk_widget_set_sensitive(GTK_WIDGET (PsxCombo), !Config.PsxAuto);
856
857         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Xa")), Config.Xa);
858         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Sio")), Config.Sio);
859         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_Mdec")), Config.Mdec);
860         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_CDDA")), Config.Cdda);
861         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_PsxAuto")), Config.PsxAuto);
862
863         g_signal_connect_data(GTK_OBJECT(glade_xml_get_widget(xml, "GtkCheckButton_PsxAuto")), "toggled",
864                         GTK_SIGNAL_FUNC(OnCpu_PsxAutoClicked), xml, NULL, G_CONNECT_AFTER);
865
866 #ifdef PSXREC
867         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "GtkCheckButton_Cpu")), Config.Cpu);
868
869         g_signal_connect_data(GTK_OBJECT(glade_xml_get_widget(xml, "GtkCheckButton_Cpu")), "toggled",
870                         GTK_SIGNAL_FUNC(OnCpu_CpuClicked), xml, NULL, G_CONNECT_AFTER);
871 #else
872         Config.Cpu = CPU_INTERPRETER;
873
874         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "GtkCheckButton_Cpu")), TRUE);
875         gtk_widget_set_sensitive(GTK_WIDGET (glade_xml_get_widget(xml, "GtkCheckButton_Cpu")), FALSE);
876 #endif
877
878         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON (glade_xml_get_widget(xml, "GtkCheckButton_Dbg")), Config.Cpu && Config.Debug);
879         gtk_widget_set_sensitive(GTK_WIDGET (glade_xml_get_widget(xml, "GtkCheckButton_Dbg")), Config.Cpu);
880
881         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_PsxOut")), Config.PsxOut);
882         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_SpuIrq")), Config.SpuIrq);
883         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_RCntFix")), Config.RCntFix);
884         gtk_toggle_button_set_state(GTK_TOGGLE_BUTTON(glade_xml_get_widget(xml, "GtkCheckButton_VSyncWA")), Config.VSyncWA);
885
886         // Setup a handler for when Close or Cancel is clicked
887         g_signal_connect_data(GTK_OBJECT(CpuDlg), "response",
888                         GTK_SIGNAL_FUNC(OnCpu_Clicked), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
889 }