Commit | Line | Data |
---|---|---|
ef79bbde P |
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 | ||
33 | #include "Linux.h" | |
34 | ||
35 | #include "../libpcsxcore/plugins.h" | |
36 | #include "../libpcsxcore/cheat.h" | |
37 | ||
38 | #include "MemcardDlg.h" | |
39 | #include "ConfDlg.h" | |
40 | #include "DebugMemory.h" | |
41 | #include "AboutDlg.h" | |
42 | ||
43 | // Functions Callbacks | |
44 | void OnFile_RunCd(); | |
45 | void OnFile_RunBios(); | |
46 | void OnFile_RunExe(); | |
47 | void OnFile_RunImage(); | |
48 | void OnEmu_Run(); | |
49 | void OnEmu_Reset(); | |
50 | void OnEmu_SwitchImage(); | |
51 | void OnHelp_Help(); | |
52 | void OnHelp_About(); | |
53 | void OnDestroy(); | |
54 | void OnFile_Exit(); | |
55 | ||
56 | void on_states_load(GtkWidget *widget, gpointer user_data); | |
57 | void on_states_load_other(); | |
58 | void on_states_save(GtkWidget *widget, gpointer user_data); | |
59 | void on_states_save_other(); | |
60 | ||
61 | GtkWidget *Window = NULL; | |
62 | ||
63 | int destroy = 0; | |
64 | ||
65 | #define MAX_SLOTS 5 | |
66 | ||
67 | /* TODO - If MAX_SLOTS changes, need to find a way to automatically set all positions */ | |
68 | int Slots[MAX_SLOTS] = { -1, -1, -1, -1, -1 }; | |
69 | ||
70 | void ResetMenuSlots(GladeXML *xml) { | |
71 | GtkWidget *widget; | |
72 | gchar *str; | |
73 | int i; | |
74 | ||
75 | if (CdromId[0] == '\0') { | |
76 | // disable state saving/loading if no CD is loaded | |
77 | for (i = 0; i < MAX_SLOTS; i++) { | |
78 | str = g_strdup_printf("GtkMenuItem_SaveSlot%d", i+1); | |
79 | widget = glade_xml_get_widget(xml, str); | |
80 | g_free(str); | |
81 | ||
82 | gtk_widget_set_sensitive(widget, FALSE); | |
83 | ||
84 | str = g_strdup_printf("GtkMenuItem_LoadSlot%d", i+1); | |
85 | widget = glade_xml_get_widget(xml, str); | |
86 | g_free(str); | |
87 | ||
88 | gtk_widget_set_sensitive(widget, FALSE); | |
89 | } | |
90 | ||
91 | // also disable certain menu/toolbar items | |
92 | widget = glade_xml_get_widget(xml, "other1"); | |
93 | gtk_widget_set_sensitive(widget, FALSE); | |
94 | widget = glade_xml_get_widget(xml, "other2"); | |
95 | gtk_widget_set_sensitive(widget, FALSE); | |
96 | widget = glade_xml_get_widget(xml, "run1"); | |
97 | gtk_widget_set_sensitive(widget, FALSE); | |
98 | widget = glade_xml_get_widget(xml, "reset1"); | |
99 | gtk_widget_set_sensitive(widget, FALSE); | |
100 | widget = glade_xml_get_widget(xml, "search1"); | |
101 | gtk_widget_set_sensitive(widget, FALSE); | |
102 | widget = glade_xml_get_widget(xml, "SwitchImage"); | |
103 | gtk_widget_set_sensitive(widget, FALSE); | |
104 | widget = glade_xml_get_widget(xml, "memorydump1"); | |
105 | gtk_widget_set_sensitive(widget, FALSE); | |
106 | widget = glade_xml_get_widget(xml, "toolbutton_run"); | |
107 | gtk_widget_set_sensitive(widget, FALSE); | |
108 | widget = glade_xml_get_widget(xml, "toolbutton_switchimage"); | |
109 | gtk_widget_set_sensitive(widget, FALSE); | |
110 | ||
111 | widget = glade_xml_get_widget(xml, "statusbar"); | |
112 | gtk_statusbar_pop(GTK_STATUSBAR(widget), 1); | |
113 | gtk_statusbar_push(GTK_STATUSBAR(widget), 1, _("Ready")); | |
114 | } | |
115 | else { | |
116 | for (i = 0; i < MAX_SLOTS; i++) { | |
117 | str = g_strdup_printf("GtkMenuItem_LoadSlot%d", i+1); | |
118 | widget = glade_xml_get_widget (xml, str); | |
119 | g_free (str); | |
120 | ||
121 | if (Slots[i] == -1) | |
122 | gtk_widget_set_sensitive(widget, FALSE); | |
123 | else | |
124 | gtk_widget_set_sensitive(widget, TRUE); | |
125 | } | |
126 | ||
127 | widget = glade_xml_get_widget(xml, "plugins_bios"); | |
128 | gtk_widget_set_sensitive(widget, FALSE); | |
129 | widget = glade_xml_get_widget(xml, "graphics1"); | |
130 | gtk_widget_set_sensitive(widget, FALSE); | |
131 | widget = glade_xml_get_widget(xml, "sound1"); | |
132 | gtk_widget_set_sensitive(widget, FALSE); | |
133 | widget = glade_xml_get_widget(xml, "cdrom1"); | |
134 | gtk_widget_set_sensitive(widget, FALSE); | |
135 | widget = glade_xml_get_widget(xml, "pad1"); | |
136 | gtk_widget_set_sensitive(widget, FALSE); | |
137 | widget = glade_xml_get_widget(xml, "net1"); | |
138 | gtk_widget_set_sensitive(widget, FALSE); | |
139 | widget = glade_xml_get_widget(xml, "SwitchImage"); | |
140 | gtk_widget_set_sensitive(widget, UsingIso()); | |
141 | widget = glade_xml_get_widget(xml, "toolbutton_switchimage"); | |
142 | gtk_widget_set_sensitive(widget, UsingIso()); | |
143 | widget = glade_xml_get_widget(xml, "toolbutton_graphics"); | |
144 | gtk_widget_set_sensitive(widget, FALSE); | |
145 | widget = glade_xml_get_widget(xml, "toolbutton_sound"); | |
146 | gtk_widget_set_sensitive(widget, FALSE); | |
147 | widget = glade_xml_get_widget(xml, "toolbutton_cdrom"); | |
148 | gtk_widget_set_sensitive(widget, FALSE); | |
149 | widget = glade_xml_get_widget(xml, "toolbutton_controllers"); | |
150 | gtk_widget_set_sensitive(widget, FALSE); | |
151 | ||
152 | widget = glade_xml_get_widget(xml, "statusbar"); | |
153 | gtk_statusbar_pop(GTK_STATUSBAR(widget), 1); | |
154 | gtk_statusbar_push(GTK_STATUSBAR(widget), 1, _("Emulation Paused.")); | |
155 | } | |
156 | } | |
157 | ||
158 | int match(const char *string, char *pattern) { | |
159 | int status; | |
160 | regex_t re; | |
161 | ||
162 | if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) { | |
163 | return 0; | |
164 | } | |
165 | status = regexec(&re, string, (size_t) 0, NULL, 0); | |
166 | regfree(&re); | |
167 | if (status != 0) { | |
168 | return 0; | |
169 | } | |
170 | ||
171 | return 1; | |
172 | } | |
173 | ||
174 | gchar* get_state_filename(int i) { | |
175 | gchar *state_filename; | |
176 | char SStateFile[64]; | |
177 | char trimlabel[33]; | |
178 | int j; | |
179 | ||
180 | strncpy(trimlabel, CdromLabel, 32); | |
181 | trimlabel[32] = 0; | |
182 | for (j = 31; j >= 0; j--) | |
183 | if (trimlabel[j] == ' ') | |
184 | trimlabel[j] = 0; | |
185 | else | |
186 | continue; | |
187 | ||
188 | sprintf(SStateFile, "%.32s-%.9s.%3.3d", trimlabel, CdromId, i); | |
189 | state_filename = g_build_filename (getenv("HOME"), STATES_DIR, SStateFile, NULL); | |
190 | ||
191 | return state_filename; | |
192 | } | |
193 | ||
194 | void UpdateMenuSlots() { | |
195 | gchar *str; | |
196 | int i; | |
197 | ||
198 | for (i = 0; i < MAX_SLOTS; i++) { | |
199 | str = get_state_filename (i); | |
200 | Slots[i] = CheckState(str); | |
201 | g_free (str); | |
202 | } | |
203 | } | |
204 | ||
205 | void StartGui() { | |
206 | GladeXML *xml; | |
207 | GtkWidget *widget; | |
208 | ||
209 | /* If a plugin fails, the Window is not NULL, but is not initialised, | |
210 | so the following causes a segfault | |
211 | if (Window != NULL) { | |
212 | gtk_window_present (GTK_WINDOW (Window)); | |
213 | return; | |
214 | }*/ | |
215 | ||
216 | xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "MainWindow", NULL); | |
217 | ||
218 | if (!xml) { | |
219 | g_warning("We could not load the interface!"); | |
220 | return; | |
221 | } | |
222 | ||
223 | Window = glade_xml_get_widget(xml, "MainWindow"); | |
224 | gtk_window_set_title(GTK_WINDOW(Window), "PCSX"); | |
225 | gtk_window_set_icon_from_file(GTK_WINDOW(Window), PIXMAPDIR "pcsx-icon.png", NULL); | |
226 | gtk_window_set_default_icon_from_file(PIXMAPDIR "pcsx-icon.png", NULL); | |
227 | ResetMenuSlots(xml); | |
228 | ||
229 | // Set up callbacks | |
230 | g_signal_connect_data(GTK_OBJECT(Window), "delete-event", | |
231 | GTK_SIGNAL_FUNC(OnDestroy), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); | |
232 | ||
233 | // File menu | |
234 | widget = glade_xml_get_widget(xml, "RunCd"); | |
235 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
236 | GTK_SIGNAL_FUNC(OnFile_RunCd), NULL, NULL, G_CONNECT_AFTER); | |
237 | ||
238 | widget = glade_xml_get_widget(xml, "RunBios"); | |
239 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
240 | GTK_SIGNAL_FUNC(OnFile_RunBios), NULL, NULL, G_CONNECT_AFTER); | |
241 | ||
242 | widget = glade_xml_get_widget(xml, "RunExe"); | |
243 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
244 | GTK_SIGNAL_FUNC(OnFile_RunExe), NULL, NULL, G_CONNECT_AFTER); | |
245 | ||
246 | widget = glade_xml_get_widget(xml, "RunImage"); | |
247 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
248 | GTK_SIGNAL_FUNC(OnFile_RunImage), NULL, NULL, G_CONNECT_AFTER); | |
249 | ||
250 | widget = glade_xml_get_widget(xml, "exit2"); | |
251 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
252 | GTK_SIGNAL_FUNC(OnFile_Exit), NULL, NULL, G_CONNECT_AFTER); | |
253 | ||
254 | // States | |
255 | widget = glade_xml_get_widget(xml, "GtkMenuItem_LoadSlot1"); | |
256 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
257 | GTK_SIGNAL_FUNC(on_states_load), (gpointer) 0, NULL, G_CONNECT_AFTER); | |
258 | widget = glade_xml_get_widget(xml, "GtkMenuItem_LoadSlot2"); | |
259 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
260 | GTK_SIGNAL_FUNC(on_states_load), (gpointer) 1, NULL, G_CONNECT_AFTER); | |
261 | widget = glade_xml_get_widget(xml, "GtkMenuItem_LoadSlot3"); | |
262 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
263 | GTK_SIGNAL_FUNC(on_states_load), (gpointer) 2, NULL, G_CONNECT_AFTER); | |
264 | widget = glade_xml_get_widget(xml, "GtkMenuItem_LoadSlot4"); | |
265 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
266 | GTK_SIGNAL_FUNC(on_states_load), (gpointer) 3, NULL, G_CONNECT_AFTER); | |
267 | widget = glade_xml_get_widget(xml, "GtkMenuItem_LoadSlot5"); | |
268 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
269 | GTK_SIGNAL_FUNC(on_states_load), (gpointer) 4, NULL, G_CONNECT_AFTER); | |
270 | widget = glade_xml_get_widget(xml, "other1"); | |
271 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
272 | GTK_SIGNAL_FUNC(on_states_load_other), NULL, NULL, G_CONNECT_AFTER); | |
273 | ||
274 | widget = glade_xml_get_widget(xml, "GtkMenuItem_SaveSlot1"); | |
275 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
276 | GTK_SIGNAL_FUNC(on_states_save), (gpointer) 0, NULL, G_CONNECT_AFTER); | |
277 | widget = glade_xml_get_widget(xml, "GtkMenuItem_SaveSlot2"); | |
278 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
279 | GTK_SIGNAL_FUNC(on_states_save), (gpointer) 1, NULL, G_CONNECT_AFTER); | |
280 | widget = glade_xml_get_widget(xml, "GtkMenuItem_SaveSlot3"); | |
281 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
282 | GTK_SIGNAL_FUNC(on_states_save), (gpointer) 2, NULL, G_CONNECT_AFTER); | |
283 | widget = glade_xml_get_widget(xml, "GtkMenuItem_SaveSlot4"); | |
284 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
285 | GTK_SIGNAL_FUNC(on_states_save), (gpointer) 3, NULL, G_CONNECT_AFTER); | |
286 | widget = glade_xml_get_widget(xml, "GtkMenuItem_SaveSlot5"); | |
287 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
288 | GTK_SIGNAL_FUNC(on_states_save), (gpointer) 4, NULL, G_CONNECT_AFTER); | |
289 | widget = glade_xml_get_widget(xml, "other2"); | |
290 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
291 | GTK_SIGNAL_FUNC(on_states_save_other), NULL, NULL, G_CONNECT_AFTER); | |
292 | ||
293 | // Emulation menu | |
294 | widget = glade_xml_get_widget(xml, "run1"); | |
295 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
296 | GTK_SIGNAL_FUNC(OnEmu_Run), NULL, NULL, G_CONNECT_AFTER); | |
297 | widget = glade_xml_get_widget(xml, "reset1"); | |
298 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
299 | GTK_SIGNAL_FUNC(OnEmu_Reset), NULL, NULL, G_CONNECT_AFTER); | |
300 | widget = glade_xml_get_widget(xml, "SwitchImage"); | |
301 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
302 | GTK_SIGNAL_FUNC(OnEmu_SwitchImage), NULL, NULL, G_CONNECT_AFTER); | |
303 | ||
304 | // Configuration menu | |
305 | widget = glade_xml_get_widget(xml, "plugins_bios"); | |
306 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
307 | GTK_SIGNAL_FUNC(ConfigurePlugins), NULL, NULL, G_CONNECT_AFTER); | |
308 | widget = glade_xml_get_widget(xml, "graphics1"); | |
309 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
310 | GTK_SIGNAL_FUNC(OnConf_Graphics), NULL, NULL, G_CONNECT_AFTER); | |
311 | widget = glade_xml_get_widget(xml, "sound1"); | |
312 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
313 | GTK_SIGNAL_FUNC(OnConf_Sound), NULL, NULL, G_CONNECT_AFTER); | |
314 | widget = glade_xml_get_widget(xml, "cdrom1"); | |
315 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
316 | GTK_SIGNAL_FUNC(OnConf_CdRom), NULL, NULL, G_CONNECT_AFTER); | |
317 | widget = glade_xml_get_widget(xml, "pad1"); | |
318 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
319 | GTK_SIGNAL_FUNC(OnConf_Pad), NULL, NULL, G_CONNECT_AFTER); | |
320 | widget = glade_xml_get_widget(xml, "cpu1"); | |
321 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
322 | GTK_SIGNAL_FUNC(OnConf_Cpu), NULL, NULL, G_CONNECT_AFTER); | |
323 | widget = glade_xml_get_widget(xml, "memory_cards1"); | |
324 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
325 | GTK_SIGNAL_FUNC(OnConf_Mcds), NULL, NULL, G_CONNECT_AFTER); | |
326 | widget = glade_xml_get_widget(xml, "net1"); | |
327 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
328 | GTK_SIGNAL_FUNC(OnConf_Net), NULL, NULL, G_CONNECT_AFTER); | |
329 | widget = glade_xml_get_widget(xml, "memorydump1"); | |
330 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
331 | GTK_SIGNAL_FUNC(RunDebugMemoryDialog), NULL, NULL, G_CONNECT_AFTER); | |
332 | ||
333 | // Cheat menu | |
334 | widget = glade_xml_get_widget(xml, "browse1"); | |
335 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
336 | GTK_SIGNAL_FUNC(RunCheatListDialog), NULL, NULL, G_CONNECT_AFTER); | |
337 | widget = glade_xml_get_widget(xml, "search1"); | |
338 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
339 | GTK_SIGNAL_FUNC(RunCheatSearchDialog), NULL, NULL, G_CONNECT_AFTER); | |
340 | ||
341 | // Help menu | |
342 | widget = glade_xml_get_widget(xml, "about_pcsx1"); | |
343 | g_signal_connect_data(GTK_OBJECT(widget), "activate", | |
344 | GTK_SIGNAL_FUNC(OnHelp_About), NULL, NULL, G_CONNECT_AFTER); | |
345 | ||
346 | // Toolbar | |
347 | widget = glade_xml_get_widget(xml, "toolbutton_runcd"); | |
348 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
349 | GTK_SIGNAL_FUNC(OnFile_RunCd), NULL, NULL, G_CONNECT_AFTER); | |
350 | ||
351 | widget = glade_xml_get_widget(xml, "toolbutton_runimage"); | |
352 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
353 | GTK_SIGNAL_FUNC(OnFile_RunImage), NULL, NULL, G_CONNECT_AFTER); | |
354 | ||
355 | widget = glade_xml_get_widget(xml, "toolbutton_run"); | |
356 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
357 | GTK_SIGNAL_FUNC(OnEmu_Run), NULL, NULL, G_CONNECT_AFTER); | |
358 | ||
359 | widget = glade_xml_get_widget(xml, "toolbutton_switchimage"); | |
360 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
361 | GTK_SIGNAL_FUNC(OnEmu_SwitchImage), NULL, NULL, G_CONNECT_AFTER); | |
362 | ||
363 | widget = glade_xml_get_widget(xml, "toolbutton_memcards"); | |
364 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
365 | GTK_SIGNAL_FUNC(OnConf_Mcds), NULL, NULL, G_CONNECT_AFTER); | |
366 | ||
367 | widget = glade_xml_get_widget(xml, "toolbutton_graphics"); | |
368 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
369 | GTK_SIGNAL_FUNC(OnConf_Graphics), NULL, NULL, G_CONNECT_AFTER); | |
370 | ||
371 | widget = glade_xml_get_widget(xml, "toolbutton_sound"); | |
372 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
373 | GTK_SIGNAL_FUNC(OnConf_Sound), NULL, NULL, G_CONNECT_AFTER); | |
374 | ||
375 | widget = glade_xml_get_widget(xml, "toolbutton_cdrom"); | |
376 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
377 | GTK_SIGNAL_FUNC(OnConf_CdRom), NULL, NULL, G_CONNECT_AFTER); | |
378 | ||
379 | widget = glade_xml_get_widget(xml, "toolbutton_controllers"); | |
380 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
381 | GTK_SIGNAL_FUNC(OnConf_Pad), NULL, NULL, G_CONNECT_AFTER); | |
382 | ||
383 | gtk_main(); | |
384 | } | |
385 | ||
386 | void OnDestroy() { | |
387 | if (!destroy) OnFile_Exit(); | |
388 | } | |
389 | ||
390 | void destroy_main_window () { | |
391 | destroy = 1; | |
392 | gtk_widget_destroy(Window); | |
393 | Window = NULL; | |
394 | destroy = 0; | |
395 | gtk_main_quit(); | |
396 | while (gtk_events_pending()) gtk_main_iteration(); | |
397 | } | |
398 | ||
399 | void OnFile_RunExe() { | |
400 | GtkWidget *file_chooser; | |
401 | ||
402 | if (plugins_configured() == FALSE) { | |
403 | ConfigurePlugins(); | |
404 | } else { | |
405 | file_chooser = gtk_file_chooser_dialog_new(_("Select PSX EXE File"), | |
406 | NULL, GTK_FILE_CHOOSER_ACTION_OPEN, | |
407 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
408 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, NULL); | |
409 | ||
410 | // Add file filters | |
411 | GtkFileFilter *exefilter = gtk_file_filter_new (); | |
412 | gtk_file_filter_add_pattern (exefilter, "*.exe"); | |
413 | gtk_file_filter_add_pattern (exefilter, "*.psx"); | |
414 | gtk_file_filter_add_pattern (exefilter, "*.cpe"); | |
415 | gtk_file_filter_add_pattern (exefilter, "*.EXE"); | |
416 | gtk_file_filter_add_pattern (exefilter, "*.PSX"); | |
417 | gtk_file_filter_add_pattern (exefilter, "*.CPE"); | |
418 | gtk_file_filter_set_name (exefilter, _("PlayStation Executable Files")); | |
419 | gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), exefilter); | |
420 | GtkFileFilter *allfilter = gtk_file_filter_new (); | |
421 | gtk_file_filter_add_pattern (allfilter, "*"); | |
422 | gtk_file_filter_set_name (allfilter, _("All Files")); | |
423 | gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), allfilter); | |
424 | ||
425 | // Set this to the config object and retain it - maybe LastUsedDir | |
426 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), getenv("HOME")); | |
427 | ||
428 | if (gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT) { | |
429 | gchar *file; | |
430 | ||
431 | /* TODO Need to validate the file */ | |
432 | ||
433 | file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser)); | |
434 | ||
435 | gtk_widget_destroy (file_chooser); | |
436 | destroy_main_window(); | |
437 | ||
438 | SetIsoFile(NULL); | |
439 | LoadPlugins(); | |
440 | NetOpened = FALSE; | |
441 | ||
442 | if (OpenPlugins() == -1) { | |
443 | g_free(file); | |
444 | SysRunGui(); | |
445 | } else { | |
446 | SysReset(); | |
447 | ||
448 | if (Load(file) == 0) { | |
449 | g_free(file); | |
450 | psxCpu->Execute(); | |
451 | } else { | |
452 | g_free(file); | |
453 | ClosePlugins(); | |
454 | SysErrorMessage(_("Not a valid PSX file"), _("The file does not appear to be a valid Playstation executable")); | |
455 | SysRunGui(); | |
456 | } | |
457 | } | |
458 | } else | |
459 | gtk_widget_destroy(file_chooser); | |
460 | } | |
461 | } | |
462 | ||
463 | void OnFile_RunCd() { | |
464 | if (plugins_configured() == FALSE) { | |
465 | ConfigurePlugins(); | |
466 | return; | |
467 | } | |
468 | ||
469 | destroy_main_window(); | |
470 | ||
471 | SetIsoFile(NULL); | |
472 | LoadPlugins(); | |
473 | NetOpened = FALSE; | |
474 | ||
475 | if (OpenPlugins() == -1) { | |
476 | SysRunGui(); | |
477 | return; | |
478 | } | |
479 | ||
480 | SysReset(); | |
481 | ||
482 | if (CheckCdrom() == -1) { | |
483 | /* Only check the CD if we are starting the console with a CD */ | |
484 | ClosePlugins(); | |
485 | SysErrorMessage (_("CD ROM failed"), _("The CD does not appear to be a valid Playstation CD")); | |
486 | SysRunGui(); | |
487 | return; | |
488 | } | |
489 | ||
490 | // Read main executable directly from CDRom and start it | |
491 | if (LoadCdrom() == -1) { | |
492 | ClosePlugins(); | |
493 | SysErrorMessage(_("Could not load CD-ROM!"), _("The CD-ROM could not be loaded")); | |
494 | SysRunGui(); | |
495 | } | |
496 | ||
497 | psxCpu->Execute(); | |
498 | } | |
499 | ||
500 | void OnFile_RunBios() { | |
501 | if (plugins_configured() == FALSE) { | |
502 | ConfigurePlugins(); | |
503 | return; | |
504 | } | |
505 | ||
506 | if (strcmp(Config.Bios, "HLE") == 0) { | |
507 | SysErrorMessage (_("Could not run BIOS"), _("Running BIOS is not supported with Internal HLE BIOS.")); | |
508 | return; | |
509 | } | |
510 | ||
511 | destroy_main_window(); | |
512 | ||
513 | SetIsoFile(NULL); | |
514 | LoadPlugins(); | |
515 | NetOpened = FALSE; | |
516 | ||
517 | if (OpenPlugins() == -1) { | |
518 | SysRunGui(); | |
519 | return; | |
520 | } | |
521 | ||
522 | SysReset(); | |
523 | ||
524 | CdromId[0] = '\0'; | |
525 | CdromLabel[0] = '\0'; | |
526 | ||
527 | psxCpu->Execute(); | |
528 | } | |
529 | ||
530 | static gchar *Open_Iso_Proc() { | |
531 | GtkWidget *chooser; | |
532 | gchar *filename; | |
533 | GtkFileFilter *psxfilter, *allfilter; | |
534 | static char current_folder[MAXPATHLEN] = ""; | |
535 | ||
536 | chooser = gtk_file_chooser_dialog_new (_("Open PSX Disc Image File"), | |
537 | NULL, GTK_FILE_CHOOSER_ACTION_OPEN, GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
538 | GTK_STOCK_OK, GTK_RESPONSE_OK, | |
539 | NULL); | |
540 | ||
541 | if (current_folder[0] == '\0') { | |
542 | strcpy(current_folder, getenv("HOME")); | |
543 | } | |
544 | ||
545 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (chooser), current_folder); | |
546 | ||
547 | psxfilter = gtk_file_filter_new(); | |
548 | gtk_file_filter_add_pattern(psxfilter, "*.bin"); | |
549 | gtk_file_filter_add_pattern(psxfilter, "*.img"); | |
550 | gtk_file_filter_add_pattern(psxfilter, "*.mdf"); | |
551 | gtk_file_filter_add_pattern(psxfilter, "*.iso"); | |
552 | gtk_file_filter_add_pattern(psxfilter, "*.BIN"); | |
553 | gtk_file_filter_add_pattern(psxfilter, "*.IMG"); | |
554 | gtk_file_filter_add_pattern(psxfilter, "*.MDF"); | |
555 | gtk_file_filter_add_pattern(psxfilter, "*.ISO"); | |
556 | gtk_file_filter_set_name(psxfilter, _("PSX Image Files (*.bin, *.img, *.mdf, *.iso)")); | |
557 | gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (chooser), psxfilter); | |
558 | ||
559 | allfilter = gtk_file_filter_new(); | |
560 | gtk_file_filter_add_pattern(allfilter, "*"); | |
561 | gtk_file_filter_set_name(allfilter, _("All Files")); | |
562 | gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (chooser), allfilter); | |
563 | ||
564 | if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { | |
565 | gchar *path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(chooser)); | |
566 | strcpy(current_folder, path); | |
567 | g_free(path); | |
568 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (chooser)); | |
569 | gtk_widget_destroy(GTK_WIDGET(chooser)); | |
570 | while (gtk_events_pending()) gtk_main_iteration(); | |
571 | return filename; | |
572 | } else { | |
573 | gtk_widget_destroy (GTK_WIDGET(chooser)); | |
574 | while (gtk_events_pending()) gtk_main_iteration(); | |
575 | return NULL; | |
576 | } | |
577 | } | |
578 | ||
579 | void OnFile_RunImage() { | |
580 | gchar *filename; | |
581 | ||
582 | if (plugins_configured() == FALSE) { | |
583 | ConfigurePlugins(); | |
584 | return; | |
585 | } | |
586 | ||
587 | filename = Open_Iso_Proc(); | |
588 | if (filename == NULL) { | |
589 | return; | |
590 | } | |
591 | ||
592 | destroy_main_window(); | |
593 | ||
594 | SetIsoFile(filename); | |
595 | g_free(filename); | |
596 | ||
597 | LoadPlugins(); | |
598 | NetOpened = FALSE; | |
599 | ||
600 | if (OpenPlugins() == -1) { | |
601 | SysRunGui(); | |
602 | return; | |
603 | } | |
604 | ||
605 | SysReset(); | |
606 | ||
607 | if (CheckCdrom() == -1) { | |
608 | // Only check the CD if we are starting the console with a CD | |
609 | ClosePlugins(); | |
610 | SysErrorMessage (_("CD ROM failed"), _("The CD does not appear to be a valid Playstation CD")); | |
611 | SysRunGui(); | |
612 | return; | |
613 | } | |
614 | ||
615 | // Read main executable directly from CDRom and start it | |
616 | if (LoadCdrom() == -1) { | |
617 | ClosePlugins(); | |
618 | SysErrorMessage(_("Could not load CD-ROM!"), _("The CD-ROM could not be loaded")); | |
619 | SysRunGui(); | |
620 | } | |
621 | ||
622 | psxCpu->Execute(); | |
623 | } | |
624 | ||
625 | void OnEmu_Run() { | |
626 | if (plugins_configured() == FALSE) { | |
627 | ConfigurePlugins(); | |
628 | return; | |
629 | } | |
630 | ||
631 | destroy_main_window(); | |
632 | ||
633 | if (OpenPlugins() == -1) { | |
634 | SysRunGui(); | |
635 | return; | |
636 | } | |
637 | ||
638 | CheatSearchBackupMemory(); | |
639 | psxCpu->Execute(); | |
640 | } | |
641 | ||
642 | void OnEmu_Reset() { | |
643 | if (plugins_configured() == FALSE) { | |
644 | ConfigurePlugins(); | |
645 | return; | |
646 | } | |
647 | ||
648 | destroy_main_window(); | |
649 | ||
650 | if (OpenPlugins() == -1) { | |
651 | SysRunGui(); | |
652 | return; | |
653 | } | |
654 | ||
655 | SysReset(); | |
656 | ||
657 | if (CheckCdrom() != -1) { | |
658 | LoadCdrom(); | |
659 | } | |
660 | ||
661 | psxCpu->Execute(); | |
662 | } | |
663 | ||
664 | void OnEmu_SwitchImage() { | |
665 | gchar *filename; | |
666 | ||
667 | if (plugins_configured() == FALSE) { | |
668 | ConfigurePlugins(); | |
669 | return; | |
670 | } | |
671 | ||
672 | filename = Open_Iso_Proc(); | |
673 | if (filename == NULL) { | |
674 | return; | |
675 | } | |
676 | ||
677 | destroy_main_window(); | |
678 | ||
679 | SetIsoFile(filename); | |
680 | g_free(filename); | |
681 | ||
682 | if (OpenPlugins() == -1) { | |
683 | SysRunGui(); | |
684 | return; | |
685 | } | |
686 | ||
687 | SetCdOpenCaseTime(time(NULL) + 2); | |
688 | ||
689 | CheatSearchBackupMemory(); | |
690 | psxCpu->Execute(); | |
691 | } | |
692 | ||
693 | void OnFile_Exit() { | |
694 | DIR *dir; | |
695 | struct dirent *ent; | |
696 | void *Handle; | |
697 | gchar *plugin = NULL; | |
698 | gchar *dotdir; | |
699 | ||
700 | dotdir = g_build_filename(getenv("HOME"), PLUGINS_DIR, NULL); | |
701 | ||
702 | // with this the problem with plugins that are linked with the pthread | |
703 | // library is solved | |
704 | ||
705 | dir = opendir(dotdir); | |
706 | if (dir != NULL) { | |
707 | while ((ent = readdir(dir)) != NULL) { | |
708 | plugin = g_build_filename(dotdir, ent->d_name, NULL); | |
709 | ||
710 | if (strstr(plugin, ".so") == NULL && strstr(plugin, ".dylib") == NULL) | |
711 | continue; | |
712 | Handle = dlopen(plugin, RTLD_NOW); | |
713 | if (Handle == NULL) | |
714 | continue; | |
715 | ||
716 | g_free(plugin); | |
717 | } | |
718 | } | |
719 | g_free(dotdir); | |
720 | ||
721 | bind_textdomain_codeset(PACKAGE_NAME, ""); | |
722 | if (UseGui) | |
723 | gtk_main_quit(); | |
724 | SysClose(); | |
725 | if (UseGui) | |
726 | gtk_exit (0); | |
727 | else | |
728 | exit(0); | |
729 | } | |
730 | ||
731 | void state_load(gchar *state_filename) { | |
732 | int ret; | |
733 | char Text[MAXPATHLEN + 20]; | |
734 | FILE *fp; | |
735 | ||
736 | // check if the state file actually exists | |
737 | fp = fopen(state_filename, "rb"); | |
738 | if (fp == NULL) { | |
739 | // file does not exist | |
740 | return; | |
741 | } | |
742 | ||
743 | fclose(fp); | |
744 | ||
745 | // If the window exists, then we are loading the state from within | |
746 | // within the PCSX GUI. We need to initialise the plugins first | |
747 | if (Window) { | |
748 | destroy_main_window(); | |
749 | ||
750 | if (OpenPlugins() == -1) { | |
751 | SysRunGui(); | |
752 | return; | |
753 | } | |
754 | } | |
755 | ||
756 | ret = CheckState(state_filename); | |
757 | ||
758 | if (ret == 0) { | |
759 | SysReset(); | |
760 | ret = LoadState(state_filename); | |
761 | } | |
762 | ||
763 | if (ret == 0) { | |
764 | // Check the CD-ROM is valid | |
765 | if (CheckCdrom() == -1) { | |
766 | ClosePlugins(); | |
767 | SysRunGui(); | |
768 | return; | |
769 | } | |
770 | ||
771 | sprintf(Text, _("Loaded state %s."), state_filename); | |
772 | GPU_displayText(Text); | |
773 | } else { | |
774 | sprintf(Text, _("Error loading state %s!"), state_filename); | |
775 | GPU_displayText(Text); | |
776 | } | |
777 | } | |
778 | ||
779 | void state_save(gchar *state_filename) { | |
780 | char Text[MAXPATHLEN + 20]; | |
781 | ||
782 | GPU_updateLace(); | |
783 | ||
784 | if (SaveState(state_filename) == 0) | |
785 | sprintf(Text, _("Saved state %s."), state_filename); | |
786 | else | |
787 | sprintf(Text, _("Error saving state %s!"), state_filename); | |
788 | ||
789 | GPU_displayText(Text); | |
790 | } | |
791 | ||
792 | void on_states_load (GtkWidget *widget, gpointer user_data) { | |
793 | gchar *state_filename; | |
794 | gint state = (int)user_data; | |
795 | ||
796 | state_filename = get_state_filename(state); | |
797 | ||
798 | state_load(state_filename); | |
799 | ||
800 | g_free(state_filename); | |
801 | ||
802 | psxCpu->Execute(); | |
803 | } | |
804 | ||
805 | void on_states_save (GtkWidget *widget, gpointer user_data) { | |
806 | gchar *state_filename; | |
807 | gint state = (int)user_data; | |
808 | ||
809 | state_filename = get_state_filename(state); | |
810 | ||
811 | state_save(state_filename); | |
812 | ||
813 | g_free(state_filename); | |
814 | } | |
815 | ||
816 | void on_states_load_other() { | |
817 | GtkWidget *file_chooser; | |
818 | gchar *SStateFile; | |
819 | ||
820 | SStateFile = g_strconcat(getenv("HOME"), STATES_DIR, NULL); | |
821 | ||
822 | file_chooser = gtk_file_chooser_dialog_new(_("Select State File"), NULL, GTK_FILE_CHOOSER_ACTION_OPEN, | |
823 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
824 | GTK_STOCK_OPEN, GTK_RESPONSE_ACCEPT, | |
825 | NULL); | |
826 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_chooser), SStateFile); | |
827 | g_free(SStateFile); | |
828 | ||
829 | if (gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT) { | |
830 | gchar *filename; | |
831 | ||
832 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser)); | |
833 | gtk_widget_destroy(file_chooser); | |
834 | ||
835 | state_load(filename); | |
836 | ||
837 | g_free(filename); | |
838 | ||
839 | psxCpu->Execute(); | |
840 | } else | |
841 | gtk_widget_destroy(file_chooser); | |
842 | } | |
843 | ||
844 | void on_states_save_other() { | |
845 | GtkWidget *file_chooser; | |
846 | gchar *SStateFile; | |
847 | ||
848 | SStateFile = g_strconcat (getenv("HOME"), STATES_DIR, NULL); | |
849 | ||
850 | file_chooser = gtk_file_chooser_dialog_new(_("Select State File"), | |
851 | NULL, GTK_FILE_CHOOSER_ACTION_SAVE, | |
852 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
853 | GTK_STOCK_SAVE, GTK_RESPONSE_OK, | |
854 | NULL); | |
855 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), SStateFile); | |
856 | g_free(SStateFile); | |
857 | ||
858 | if (gtk_dialog_run (GTK_DIALOG(file_chooser)) == GTK_RESPONSE_OK) { | |
859 | gchar *filename; | |
860 | ||
861 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_chooser)); | |
862 | gtk_widget_destroy(file_chooser); | |
863 | ||
864 | state_save(filename); | |
865 | ||
866 | g_free(filename); | |
867 | } | |
868 | else | |
869 | gtk_widget_destroy(file_chooser); | |
870 | } | |
871 | ||
872 | void OnHelp_About(GtkWidget *widget, gpointer user_data) { | |
873 | RunAboutDialog(); | |
874 | } | |
875 | ||
876 | void SysMessage(const char *fmt, ...) { | |
877 | GtkWidget *Txt, *MsgDlg; | |
878 | va_list list; | |
879 | char msg[512]; | |
880 | ||
881 | va_start(list, fmt); | |
882 | vsprintf(msg, fmt, list); | |
883 | va_end(list); | |
884 | ||
885 | if (msg[strlen(msg) - 1] == '\n') | |
886 | msg[strlen(msg) - 1] = 0; | |
887 | ||
888 | if (!UseGui) { | |
889 | fprintf(stderr, "%s\n", msg); | |
890 | return; | |
891 | } | |
892 | ||
893 | MsgDlg = gtk_dialog_new_with_buttons(_("Notice"), NULL, | |
894 | GTK_DIALOG_DESTROY_WITH_PARENT, GTK_STOCK_OK, GTK_RESPONSE_NONE, NULL); | |
895 | ||
896 | gtk_window_set_position (GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER); | |
897 | ||
898 | Txt = gtk_label_new (msg); | |
899 | gtk_label_set_line_wrap(GTK_LABEL(Txt), TRUE); | |
900 | gtk_container_add (GTK_CONTAINER (GTK_DIALOG(MsgDlg)->vbox), Txt); | |
901 | ||
902 | gtk_widget_show (Txt); | |
903 | gtk_widget_show_all (MsgDlg); | |
904 | gtk_dialog_run (GTK_DIALOG(MsgDlg)); | |
905 | gtk_widget_destroy (MsgDlg); | |
906 | } | |
907 | ||
908 | void SysErrorMessage(gchar *primary, gchar *secondary) { | |
909 | GtkWidget *message_dialog; | |
910 | if (!UseGui) | |
911 | printf ("%s - %s\n", primary, secondary); | |
912 | else { | |
913 | message_dialog = gtk_message_dialog_new(NULL, | |
914 | GTK_DIALOG_MODAL, | |
915 | GTK_MESSAGE_ERROR, | |
916 | GTK_BUTTONS_CLOSE, | |
917 | primary, | |
918 | NULL); | |
919 | gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog), | |
920 | secondary); | |
921 | ||
922 | gtk_dialog_run(GTK_DIALOG(message_dialog)); | |
923 | gtk_widget_destroy(message_dialog); | |
924 | } | |
925 | } | |
926 | ||
927 | void SysInfoMessage(gchar *primary, gchar *secondary) { | |
928 | GtkWidget *message_dialog; | |
929 | if (!UseGui) | |
930 | printf ("%s - %s\n", primary, secondary); | |
931 | else { | |
932 | message_dialog = gtk_message_dialog_new(NULL, | |
933 | GTK_DIALOG_MODAL, | |
934 | GTK_MESSAGE_INFO, | |
935 | GTK_BUTTONS_CLOSE, | |
936 | primary, | |
937 | NULL); | |
938 | gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog), | |
939 | secondary); | |
940 | ||
941 | gtk_dialog_run(GTK_DIALOG(message_dialog)); | |
942 | gtk_widget_destroy(message_dialog); | |
943 | } | |
944 | } |