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 02110-1301 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 <signal.h>
29 #include <sys/time.h>
30 #include <regex.h>
31 #include <libintl.h>
32 
33 #include "Linux.h"
34 
35 #include "../libpcsxcore/plugins.h"
36 #include "../libpcsxcore/cheat.h"
37 #include "../libpcsxcore/cdrom.h"
38 
39 #include "MemcardDlg.h"
40 #include "ConfDlg.h"
41 #include "DebugMemory.h"
42 #include "AboutDlg.h"
43 
44 // Functions Callbacks
45 void OnFile_RunCd();
46 void OnFile_RunBios();
47 void OnFile_RunExe();
48 void OnFile_RunImage();
49 void OnEmu_Run();
50 void OnEmu_Reset();
51 void OnEmu_Shutdown();
52 void OnEmu_SwitchImage();
53 void OnHelp_Help();
54 void OnHelp_About();
55 void OnDestroy();
56 void OnFile_Exit();
57 
58 // EXE name is stored here
59 gchar* reset_load_info = NULL;
60 
61 void on_states_load(GtkWidget *widget, gpointer user_data);
62 void on_states_load_other();
63 void on_states_save(GtkWidget *widget, gpointer user_data);
64 void on_states_save_other();
65 void on_states_load_recent();
66 
67 static GtkBuilder *builder;
68 GtkWidget *Window = NULL;
69 
70 int destroy = 0;
71 
72 extern void LidInterrupt();
73 
74 #define MAX_SLOTS 9
75 
76 /* TODO - If MAX_SLOTS changes, need to find a way to automatically set all positions */
77 int Slots[MAX_SLOTS] = { -1, -1, -1, -1, -1, -1, -1, -1, -1 };
78 int recent_load_slot = -1;
79 
ResetMenuSlots()80 void ResetMenuSlots() {
81 	GtkWidget *widget;
82 	gchar *str;
83 	int i;
84 
85 	if (CdromId[0] == '\0') {
86 		// disable state saving/loading if no CD is loaded
87 		for (i = 0; i < MAX_SLOTS; i++) {
88 			// Save slots
89 			str = g_strdup_printf("GtkMenuItem_SaveSlot%d", i+1);
90 			widget = GTK_WIDGET(gtk_builder_get_object(builder, str));
91 			g_free(str);
92 
93 			gtk_widget_set_sensitive(widget, FALSE);
94 
95 			// Load slots
96 			str = g_strdup_printf("GtkMenuItem_LoadSlot%d", i+1);
97 			widget = GTK_WIDGET(gtk_builder_get_object(builder, str));
98 			g_free(str);
99 
100 			gtk_widget_set_sensitive(widget, FALSE);
101 		}
102 		// Recent
103 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlotRecent"));
104 		gtk_widget_set_sensitive(widget, FALSE);
105 		// Other save/load
106 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "other1"));
107 		gtk_widget_set_sensitive(widget, FALSE);
108 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "other2"));
109 		gtk_widget_set_sensitive(widget, FALSE);
110 
111 		// also disable certain menu/toolbar items
112 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "run1"));
113 		gtk_widget_set_sensitive(widget, FALSE);
114 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "reset1"));
115 		gtk_widget_set_sensitive(widget, FALSE);
116 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "shutdown1"));
117 		gtk_widget_set_sensitive(widget, FALSE);
118 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "search1"));
119 		gtk_widget_set_sensitive(widget, FALSE);
120 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "SwitchImage"));
121 		gtk_widget_set_sensitive(widget, FALSE);
122 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "memorydump1"));
123 		gtk_widget_set_sensitive(widget, FALSE);
124 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_run"));
125 		gtk_widget_set_sensitive(widget, FALSE);
126 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_switchimage"));
127 		gtk_widget_set_sensitive(widget, FALSE);
128 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "plugins_bios"));
129 		gtk_widget_set_sensitive(widget, TRUE);
130 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "graphics1"));
131 		gtk_widget_set_sensitive(widget, TRUE);
132 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "sound1"));
133 		gtk_widget_set_sensitive(widget, TRUE);
134 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "cdrom1"));
135 		gtk_widget_set_sensitive(widget, TRUE);
136 #ifdef ENABLE_SIO1API
137 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "sio1"));
138 		gtk_widget_set_sensitive(widget, TRUE);
139 #else
140 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "sio1"));
141 		gtk_widget_set_sensitive(widget, FALSE);
142 #endif
143 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "net1"));
144 		gtk_widget_set_sensitive(widget, TRUE);
145 
146 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_switchimage"));
147 		gtk_widget_set_sensitive(widget, UsingIso());
148 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_graphics"));
149 		gtk_widget_set_sensitive(widget, TRUE);
150 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_sound"));
151 		gtk_widget_set_sensitive(widget, TRUE);
152 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_cdrom"));
153 		gtk_widget_set_sensitive(widget, TRUE);
154 
155 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "statusbar"));
156 		gtk_statusbar_pop(GTK_STATUSBAR(widget), 1);
157 		gtk_statusbar_push(GTK_STATUSBAR(widget), 1, _("Ready"));
158 	}
159 	else {
160 		for (i = 0; i < MAX_SLOTS; i++) {
161 			str = g_strdup_printf("GtkMenuItem_LoadSlot%d", i+1);
162 			widget = GTK_WIDGET(gtk_builder_get_object (builder, str));
163 			g_free (str);
164 
165 			if (Slots[i] == -1)
166 				gtk_widget_set_sensitive(widget, FALSE);
167 			else
168 				gtk_widget_set_sensitive(widget, TRUE);
169 		}
170 		// Recent
171 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlotRecent"));
172 		gtk_widget_set_sensitive(widget, recent_load_slot>-1);
173 
174 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "plugins_bios"));
175 		gtk_widget_set_sensitive(widget, FALSE);
176 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "graphics1"));
177 		gtk_widget_set_sensitive(widget, FALSE);
178 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "sound1"));
179 		gtk_widget_set_sensitive(widget, FALSE);
180 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "cdrom1"));
181 		gtk_widget_set_sensitive(widget, FALSE);
182 #ifdef ENABLE_SIO1API
183 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "sio1"));
184 		gtk_widget_set_sensitive(widget, FALSE);
185 #endif
186 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "net1"));
187 		gtk_widget_set_sensitive(widget, FALSE);
188 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "SwitchImage"));
189 		gtk_widget_set_sensitive(widget, UsingIso());
190 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_switchimage"));
191 		gtk_widget_set_sensitive(widget, UsingIso());
192 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_graphics"));
193 		gtk_widget_set_sensitive(widget, FALSE);
194 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_sound"));
195 		gtk_widget_set_sensitive(widget, FALSE);
196 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_cdrom"));
197 		gtk_widget_set_sensitive(widget, FALSE);
198 
199 		widget = GTK_WIDGET(gtk_builder_get_object(builder, "statusbar"));
200 		gtk_statusbar_pop(GTK_STATUSBAR(widget), 1);
201 		gtk_statusbar_push(GTK_STATUSBAR(widget), 1, _("Emulation Paused."));
202 	}
203 }
204 
clear_change_image()205 static void clear_change_image() {
206 	g_free(reset_load_info);
207 	reset_load_info = NULL;
208 	autoloadCheats();
209 	g_free(cheat_last_filename);
210 	cheat_last_filename = NULL;
211 }
212 
match(const char * string,char * pattern)213 int match(const char *string, char *pattern) {
214 	int    status;
215 	regex_t    re;
216 
217 	if (regcomp(&re, pattern, REG_EXTENDED | REG_NOSUB) != 0) {
218 		return 0;
219 	}
220 	status = regexec(&re, string, (size_t) 0, NULL, 0);
221 	regfree(&re);
222 	if (status != 0) {
223 		return 0;
224 	}
225 
226 	return 1;
227 }
228 
get_state_filename(int i)229 gchar* get_state_filename(int i) {
230 	gchar *state_filename, *trimlabel;
231 	char SStateFile[64];
232 	int j;
233 
234 	trimlabel = get_cdrom_label_trim();
235 
236 	if (i >= OLD_SLOT && i <= LAST_OLD_SLOT) {
237 		sprintf(SStateFile, "%.32s-%.9s.old_%d", trimlabel, CdromId, i - OLD_SLOT);
238 	} else {
239 		sprintf(SStateFile, "%.32s-%.9s.%3.3d", trimlabel, CdromId, i);
240 	}
241 	state_filename = g_build_filename (getenv("HOME"), STATES_DIR, SStateFile, NULL);
242 
243 	g_free(trimlabel);
244 
245 	return state_filename;
246 }
247 
get_cdrom_label_trim()248 gchar* get_cdrom_label_trim() {
249 	char trimlabel[33];
250 	int j;
251 
252 	strncpy(trimlabel, CdromLabel, 32);
253 	trimlabel[32] = 0;
254 	for (j = 31; j >= 0; j--) {
255 		if (trimlabel[j] == ' ')
256 			trimlabel[j] = 0;
257 		else
258 			continue;
259 	}
260 
261 	return g_strdup(trimlabel);
262 }
263 
get_cdrom_label_id(const gchar * suffix)264 gchar* get_cdrom_label_id(const gchar* suffix) {
265 	const u8 lblmax = sizeof(CdromId) + sizeof(CdromLabel) + 20u;
266 	//printf("MAx %u\n", lblmax);
267 	char buf[lblmax];
268 	gchar *trimlabel = get_cdrom_label_trim();
269 
270 	snprintf(buf, lblmax, "%.32s-%.9s%s", trimlabel, CdromId, suffix);
271 
272 	g_free(trimlabel);
273 
274 	if (strlen(buf) <= (2+strlen(dot_extension_cht)))
275 		return g_strconcat("psx-default", dot_extension_cht, NULL);
276 	else
277 		return g_strdup(buf);
278 }
279 
get_state_time(const char * fn)280 static time_t get_state_time(const char* fn) {
281 	struct stat st;
282 	int ierr = stat (fn, &st);
283 	if (!ierr)
284 		return st.st_ctime;
285 	else
286 		return -1;
287 }
288 
UpdateMenuSlots()289 int UpdateMenuSlots() {
290 	gchar *str;
291 	int i, imax=-1;
292 	time_t tsmax = -1;
293 
294 	for (i = 0; i < MAX_SLOTS; i++) {
295 		str = get_state_filename (i);
296 		if ((Slots[i] = CheckState(str)) >= 0) {
297 			time_t ts = get_state_time(str);
298 			if (ts > tsmax) {
299 				tsmax=ts;
300 				imax=i;
301 			}
302 			//printf("File %s time %i\n", str, ts);
303 		}
304 		g_free (str);
305 	}
306 	return (recent_load_slot=imax);
307 }
308 
autoloadCheats()309 void autoloadCheats() {
310 	ClearAllCheats();
311 	gchar *chtfile = get_cdrom_label_id(dot_extension_cht);
312 	gchar *defaultChtFilePath = g_build_filename (getenv("HOME"), CHEATS_DIR, chtfile, NULL);
313 	LoadCheats(defaultChtFilePath); // file existence/access check in LoadCheats()
314 	g_free(defaultChtFilePath);
315 	g_free(chtfile);
316 }
317 
StartGui()318 void StartGui() {
319 	GtkWidget *widget;
320 
321 	/* If a plugin fails, the Window is not NULL, but is not initialised,
322 	   so the following causes a segfault
323 	if (Window != NULL) {
324 		gtk_window_present (GTK_WINDOW (Window));
325 		return;
326 	}*/
327 	GtkIconTheme *itheme = gtk_icon_theme_get_default();
328 	gtk_icon_theme_add_resource_path(itheme,"/org/pcsxr/gui");
329 	gtk_icon_theme_add_resource_path(itheme,"/org/pcsxr/gui/pixmaps/");
330 
331 	builder = gtk_builder_new();
332 
333 	if (!gtk_builder_add_from_resource(builder, "/org/pcsxr/gui/pcsxr.ui", NULL)) {
334 		g_warning("Error: interface could not be loaded!");
335 		return;
336 	}
337 
338 	Window = GTK_WIDGET(gtk_builder_get_object(builder, "MainWindow"));
339 	gtk_widget_show(GTK_WIDGET(Window));
340 
341 	gtk_window_set_title(GTK_WINDOW(Window), "PCSXR");
342 	gtk_window_set_icon(GTK_WINDOW(Window), gdk_pixbuf_new_from_resource("/org/pcsxr/gui/pixmaps/pcsxr-icon.png", NULL));
343 	gtk_window_set_default_icon(gdk_pixbuf_new_from_resource("/org/pcsxr/gui/pixmaps/pcsxr-icon.png", NULL));
344 	ResetMenuSlots();
345 
346 	// Set up callbacks
347 	g_signal_connect_data(G_OBJECT(Window), "delete-event",
348 			G_CALLBACK(OnDestroy), builder, (GClosureNotify)g_object_unref, G_CONNECT_AFTER);
349 
350 	// File menu
351 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "RunCd"));
352 	g_signal_connect_data(G_OBJECT(widget), "activate",
353 			G_CALLBACK(OnFile_RunCd), NULL, NULL, G_CONNECT_AFTER);
354 
355 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "RunBios"));
356 	g_signal_connect_data(G_OBJECT(widget), "activate",
357 			G_CALLBACK(OnFile_RunBios), NULL, NULL, G_CONNECT_AFTER);
358 
359 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "RunExe"));
360 	g_signal_connect_data(G_OBJECT(widget), "activate",
361 			G_CALLBACK(OnFile_RunExe), NULL, NULL, G_CONNECT_AFTER);
362 
363 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "RunImage"));
364 	g_signal_connect_data(G_OBJECT(widget), "activate",
365 			G_CALLBACK(OnFile_RunImage), NULL, NULL, G_CONNECT_AFTER);
366 
367 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "exit2"));
368 	g_signal_connect_data(G_OBJECT(widget), "activate",
369 			G_CALLBACK(OnFile_Exit), NULL, NULL, G_CONNECT_AFTER);
370 
371 	// States
372 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot1"));
373 	g_signal_connect_data(G_OBJECT(widget), "activate",
374 			G_CALLBACK(on_states_load), GINT_TO_POINTER(0), NULL, G_CONNECT_AFTER);
375 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot2"));
376 	g_signal_connect_data(G_OBJECT(widget), "activate",
377 			G_CALLBACK(on_states_load), GINT_TO_POINTER(1), NULL, G_CONNECT_AFTER);
378 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot3"));
379 	g_signal_connect_data(G_OBJECT(widget), "activate",
380 			G_CALLBACK(on_states_load), GINT_TO_POINTER(2), NULL, G_CONNECT_AFTER);
381 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot4"));
382 	g_signal_connect_data(G_OBJECT(widget), "activate",
383 			G_CALLBACK(on_states_load), GINT_TO_POINTER(3), NULL, G_CONNECT_AFTER);
384 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot5"));
385 	g_signal_connect_data(G_OBJECT(widget), "activate",
386 			G_CALLBACK(on_states_load), GINT_TO_POINTER(4), NULL, G_CONNECT_AFTER);
387 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot6"));
388 	g_signal_connect_data(G_OBJECT(widget), "activate",
389 			G_CALLBACK(on_states_load), GINT_TO_POINTER(5), NULL, G_CONNECT_AFTER);
390 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot7"));
391 	g_signal_connect_data(G_OBJECT(widget), "activate",
392 			G_CALLBACK(on_states_load), GINT_TO_POINTER(6), NULL, G_CONNECT_AFTER);
393 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot8"));
394 	g_signal_connect_data(G_OBJECT(widget), "activate",
395 			G_CALLBACK(on_states_load), GINT_TO_POINTER(7), NULL, G_CONNECT_AFTER);
396 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlot9"));
397 	g_signal_connect_data(G_OBJECT(widget), "activate",
398 			G_CALLBACK(on_states_load), GINT_TO_POINTER(8), NULL, G_CONNECT_AFTER);
399 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_LoadSlotRecent"));
400 	g_signal_connect_data(G_OBJECT(widget), "activate",
401 			G_CALLBACK(on_states_load_recent), NULL, NULL, G_CONNECT_AFTER);
402 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "other1"));
403 	g_signal_connect_data(G_OBJECT(widget), "activate",
404 			G_CALLBACK(on_states_load_other), NULL, NULL, G_CONNECT_AFTER);
405 
406 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot1"));
407 	g_signal_connect_data(G_OBJECT(widget), "activate",
408 			G_CALLBACK(on_states_save), GINT_TO_POINTER(0), NULL, G_CONNECT_AFTER);
409 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot2"));
410 	g_signal_connect_data(G_OBJECT(widget), "activate",
411 			G_CALLBACK(on_states_save), GINT_TO_POINTER(1), NULL, G_CONNECT_AFTER);
412 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot3"));
413 	g_signal_connect_data(G_OBJECT(widget), "activate",
414 			G_CALLBACK(on_states_save), GINT_TO_POINTER(2), NULL, G_CONNECT_AFTER);
415 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot4"));
416 	g_signal_connect_data(G_OBJECT(widget), "activate",
417 			G_CALLBACK(on_states_save), GINT_TO_POINTER(3), NULL, G_CONNECT_AFTER);
418 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot5"));
419 	g_signal_connect_data(G_OBJECT(widget), "activate",
420 			G_CALLBACK(on_states_save), GINT_TO_POINTER(4), NULL, G_CONNECT_AFTER);
421 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot6"));
422 	g_signal_connect_data(G_OBJECT(widget), "activate",
423 			G_CALLBACK(on_states_save), GINT_TO_POINTER(5), NULL, G_CONNECT_AFTER);
424 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot7"));
425 	g_signal_connect_data(G_OBJECT(widget), "activate",
426 			G_CALLBACK(on_states_save), GINT_TO_POINTER(6), NULL, G_CONNECT_AFTER);
427 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot8"));
428 	g_signal_connect_data(G_OBJECT(widget), "activate",
429 			G_CALLBACK(on_states_save), GINT_TO_POINTER(7), NULL, G_CONNECT_AFTER);
430 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "GtkMenuItem_SaveSlot9"));
431 	g_signal_connect_data(G_OBJECT(widget), "activate",
432 			G_CALLBACK(on_states_save), GINT_TO_POINTER(8), NULL, G_CONNECT_AFTER);
433 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "other2"));
434 	g_signal_connect_data(G_OBJECT(widget), "activate",
435 			G_CALLBACK(on_states_save_other), NULL, NULL, G_CONNECT_AFTER);
436 
437 	// Emulation menu
438 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "run1"));
439 	g_signal_connect_data(G_OBJECT(widget), "activate",
440 			G_CALLBACK(OnEmu_Run), NULL, NULL, G_CONNECT_AFTER);
441 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "reset1"));
442 	g_signal_connect_data(G_OBJECT(widget), "activate",
443 			G_CALLBACK(OnEmu_Reset), NULL, NULL, G_CONNECT_AFTER);
444 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "shutdown1"));
445 	g_signal_connect_data(G_OBJECT(widget), "activate",
446 			G_CALLBACK(OnEmu_Shutdown), NULL, NULL, G_CONNECT_AFTER);
447 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "SwitchImage"));
448 	g_signal_connect_data(G_OBJECT(widget), "activate",
449 			G_CALLBACK(OnEmu_SwitchImage), NULL, NULL, G_CONNECT_AFTER);
450 
451 	// Configuration menu
452 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "plugins_bios"));
453 	g_signal_connect_data(G_OBJECT(widget), "activate",
454 			G_CALLBACK(ConfigurePlugins), NULL, NULL, G_CONNECT_AFTER);
455 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "graphics1"));
456 	g_signal_connect_data(G_OBJECT(widget), "activate",
457 			G_CALLBACK(OnConf_Graphics), NULL, NULL, G_CONNECT_AFTER);
458 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "sound1"));
459 	g_signal_connect_data(G_OBJECT(widget), "activate",
460 			G_CALLBACK(OnConf_Sound), NULL, NULL, G_CONNECT_AFTER);
461 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "cdrom1"));
462 	g_signal_connect_data(G_OBJECT(widget), "activate",
463 			G_CALLBACK(OnConf_CdRom), NULL, NULL, G_CONNECT_AFTER);
464 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "pad1"));
465 	g_signal_connect_data(G_OBJECT(widget), "activate",
466 			G_CALLBACK(OnConf_Pad), NULL, NULL, G_CONNECT_AFTER);
467 #ifdef ENABLE_SIO1API
468 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "sio1"));
469 	g_signal_connect_data(G_OBJECT(widget), "activate",
470 			G_CALLBACK(OnConf_Sio1), NULL, NULL, G_CONNECT_AFTER);
471 #endif
472 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "cpu1"));
473 	g_signal_connect_data(G_OBJECT(widget), "activate",
474 			G_CALLBACK(OnConf_Cpu), NULL, NULL, G_CONNECT_AFTER);
475 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "memory_cards1"));
476 	g_signal_connect_data(G_OBJECT(widget), "activate",
477 			G_CALLBACK(OnConf_Mcds), NULL, NULL, G_CONNECT_AFTER);
478 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "net1"));
479 	g_signal_connect_data(G_OBJECT(widget), "activate",
480 			G_CALLBACK(OnConf_Net), NULL, NULL, G_CONNECT_AFTER);
481 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "memorydump1"));
482 	g_signal_connect_data(G_OBJECT(widget), "activate",
483 			G_CALLBACK(RunDebugMemoryDialog), NULL, NULL, G_CONNECT_AFTER);
484 
485 	// Cheat menu
486 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "browse1"));
487 	g_signal_connect_data(G_OBJECT(widget), "activate",
488 			G_CALLBACK(RunCheatListDialog), NULL, NULL, G_CONNECT_AFTER);
489 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "search1"));
490 	g_signal_connect_data(G_OBJECT(widget), "activate",
491 			G_CALLBACK(RunCheatSearchDialog), NULL, NULL, G_CONNECT_AFTER);
492 
493 	// Help menu
494 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "about_pcsxr1"));
495 	g_signal_connect_data(G_OBJECT(widget), "activate",
496 			G_CALLBACK(OnHelp_About), NULL, NULL, G_CONNECT_AFTER);
497 
498 	// Toolbar
499 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_runcd"));
500 	g_signal_connect_data(G_OBJECT(widget), "clicked",
501 			G_CALLBACK(OnFile_RunCd), NULL, NULL, G_CONNECT_AFTER);
502 
503 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_runimage"));
504 	g_signal_connect_data(G_OBJECT(widget), "clicked",
505 			G_CALLBACK(OnFile_RunImage), NULL, NULL, G_CONNECT_AFTER);
506 
507 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_run"));
508 	g_signal_connect_data(G_OBJECT(widget), "clicked",
509 			G_CALLBACK(OnEmu_Run), NULL, NULL, G_CONNECT_AFTER);
510 
511 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_switchimage"));
512 	g_signal_connect_data(G_OBJECT(widget), "clicked",
513 			G_CALLBACK(OnEmu_SwitchImage), NULL, NULL, G_CONNECT_AFTER);
514 
515 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_memcards"));
516 	g_signal_connect_data(G_OBJECT(widget), "clicked",
517 			G_CALLBACK(OnConf_Mcds), NULL, NULL, G_CONNECT_AFTER);
518 
519 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_graphics"));
520 	g_signal_connect_data(G_OBJECT(widget), "clicked",
521 			G_CALLBACK(OnConf_Graphics), NULL, NULL, G_CONNECT_AFTER);
522 
523 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_sound"));
524 	g_signal_connect_data(G_OBJECT(widget), "clicked",
525 			G_CALLBACK(OnConf_Sound), NULL, NULL, G_CONNECT_AFTER);
526 
527 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_cdrom"));
528 	g_signal_connect_data(G_OBJECT(widget), "clicked",
529 			G_CALLBACK(OnConf_CdRom), NULL, NULL, G_CONNECT_AFTER);
530 
531 	widget = GTK_WIDGET(gtk_builder_get_object(builder, "toolbutton_controllers"));
532 	g_signal_connect_data(G_OBJECT(widget), "clicked",
533 			G_CALLBACK(OnConf_Pad), NULL, NULL, G_CONNECT_AFTER);
534 
535 	gtk_main();
536 }
537 
OnDestroy()538 void OnDestroy() {
539 	if (!destroy) OnFile_Exit();
540 }
541 
destroy_main_window()542 void destroy_main_window () {
543 #ifdef DISABLE_GNOME_SCREENSAVER
544 	// Disable GNOME screensaver
545 	int response_token = 0;
546 	GError *error;
547 	GDBusProxy *proxy = g_dbus_proxy_new_for_bus_sync (G_BUS_TYPE_SYSTEM,
548 					G_DBUS_PROXY_FLAGS_NONE, NULL,
549 					"org.gnome.ScreenSaver",
550 					"org/gnome/ScreenSaver",
551 					"org.gnome.ScreenSaver",
552 					NULL, &error);
553 
554 	GVariant *retval = g_dbus_proxy_call_sync (proxy,
555 					 "Inhibit",
556 					 g_variant_new ("(ssu)", "PCSXR",
557 							"Emulating",
558 							response_token),
559 					 G_DBUS_CALL_FLAGS_NONE,
560 					 2, /* timeout */
561 					 NULL, /* cancellable */
562 					 &error);
563 	printf("Response %i\n", response_token);
564 #endif
565 
566 	destroy = 1;
567 	gtk_widget_destroy(Window);
568 	Window = NULL;
569 	destroy = 0;
570 	gtk_main_quit();
571 	while (gtk_events_pending()) gtk_main_iteration();
572 }
573 
OnFile_RunExe()574 void OnFile_RunExe() {
575 	GtkWidget *file_chooser;
576 
577 	if (plugins_configured() == FALSE) {
578 		ConfigurePlugins();
579 	} else {
580 		file_chooser = gtk_file_chooser_dialog_new(_("Select PSX EXE File"),
581 			NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
582 			"_Cancel", GTK_RESPONSE_CANCEL,
583 			"_Open", GTK_RESPONSE_ACCEPT, NULL);
584 
585 		// Add file filters
586 		GtkFileFilter *exefilter = gtk_file_filter_new ();
587 		gtk_file_filter_add_pattern (exefilter, "*.exe");
588 		gtk_file_filter_add_pattern (exefilter, "*.psx");
589 		gtk_file_filter_add_pattern (exefilter, "*.cpe");
590 		gtk_file_filter_add_pattern (exefilter, "*.EXE");
591 		gtk_file_filter_add_pattern (exefilter, "*.PSX");
592 		gtk_file_filter_add_pattern (exefilter, "*.CPE");
593 		gtk_file_filter_set_name (exefilter, _("PlayStation Executable Files"));
594 		gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), exefilter);
595 		GtkFileFilter *allfilter = gtk_file_filter_new ();
596 		gtk_file_filter_add_pattern (allfilter, "*");
597 		gtk_file_filter_set_name (allfilter, _("All Files"));
598 		gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (file_chooser), allfilter);
599 
600 		// Set this to the config object and retain it - maybe LastUsedDir
601 		gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), getenv("HOME"));
602 
603 		if (gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT) {
604 			gchar *file;
605 
606 			/* TODO Need to validate the file */
607 
608 			file = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
609 
610 			gtk_widget_destroy (file_chooser);
611 			destroy_main_window();
612 
613 			SetIsoFile(NULL);
614 			LoadPlugins();
615 			NetOpened = FALSE;
616 
617 			if (OpenPlugins() == -1) {
618 				g_free(file);
619 				SysRunGui();
620 			} else {
621 				// Auto-detect: get region first, then rcnt-bios reset
622 				SysReset();
623 
624 				if (Load(file) == 0) {
625 					g_free(reset_load_info);
626 					reset_load_info = g_strdup(file);
627 					g_free(file);
628 					psxCpu->Execute();
629 				} else {
630 					g_free(file);
631 					ClosePlugins();
632 					SysErrorMessage(_("Not a valid PSX file"), _("The file does not appear to be a valid Playstation executable"));
633 					SysRunGui();
634 				}
635 			}
636 		} else
637 			gtk_widget_destroy(file_chooser);
638 	}
639 }
640 
OnFile_RunCd()641 void OnFile_RunCd() {
642 	if (plugins_configured() == FALSE) {
643 		ConfigurePlugins();
644 		return;
645 	}
646 
647 	destroy_main_window();
648 
649 	SetIsoFile(NULL);
650 	LoadPlugins();
651 	NetOpened = FALSE;
652 
653 	if (OpenPlugins() == -1) {
654 		SysRunGui();
655 		return;
656 	}
657 
658 	if (CheckCdrom() == -1) {
659 		/* Only check the CD if we are starting the console with a CD */
660 		ClosePlugins();
661 		SysErrorMessage (_("CD ROM failed"), _("The CD does not appear to be a valid Playstation CD"));
662 		SysRunGui();
663 		return;
664 	}
665 
666 	// Auto-detect: get region first, then rcnt-bios reset
667 	SysReset();
668 
669 	// Read main executable directly from CDRom and start it
670 	if (LoadCdrom() == -1) {
671 		ClosePlugins();
672 		SysErrorMessage(_("Could not load CD-ROM!"), _("The CD-ROM could not be loaded"));
673 		SysRunGui();
674 	}
675 
676 	clear_change_image();
677 	psxCpu->Execute();
678 }
679 
OnFile_RunBios()680 void OnFile_RunBios() {
681 	if (plugins_configured() == FALSE) {
682 		ConfigurePlugins();
683 		return;
684 	}
685 
686 	if (strcmp(Config.Bios, "HLE") == 0) {
687 		SysErrorMessage (_("Could not run BIOS"), _("Running BIOS is not supported with Internal HLE BIOS."));
688 		return;
689 	}
690 
691 	destroy_main_window();
692 
693 	SetIsoFile(NULL);
694 	LoadPlugins();
695 	NetOpened = FALSE;
696 
697 	if (OpenPlugins() == -1) {
698 		SysRunGui();
699 		return;
700 	}
701 
702 	SysReset();
703 
704 	CdromId[0] = '\0';
705 	CdromLabel[0] = '\0';
706 
707 	clear_change_image();
708 	psxCpu->Execute();
709 }
710 
Open_Iso_Proc()711 static gchar *Open_Iso_Proc() {
712 	struct stat sb;
713 	GtkWidget *chooser;
714 	gchar *filename;
715 	GtkFileFilter *psxfilter, *allfilter;
716 	static char current_folder[MAXPATHLEN] = "";
717 
718 	chooser = gtk_file_chooser_dialog_new (_("Open PSX Disc Image File"),
719 		NULL, GTK_FILE_CHOOSER_ACTION_OPEN, "_Cancel", GTK_RESPONSE_CANCEL,
720 		"_Open", GTK_RESPONSE_ACCEPT,
721 		NULL);
722 
723 	if (stat(Config.IsoImgDir, &sb) == 0 && S_ISDIR(sb.st_mode)) {
724 		strcpy(current_folder, Config.IsoImgDir);
725 	} else if (strlen(Config.IsoImgDir) <= 0) {
726 		strcpy(current_folder, getenv("HOME"));
727 	} else {
728 		/* Using static (recent) PATH */
729 	}
730 
731 	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (chooser), current_folder);
732 
733 	psxfilter = gtk_file_filter_new();
734 	gtk_file_filter_add_pattern(psxfilter, "*.bin");
735 	gtk_file_filter_add_pattern(psxfilter, "*.img");
736 	gtk_file_filter_add_pattern(psxfilter, "*.mdf");
737 	gtk_file_filter_add_pattern(psxfilter, "*.iso");
738 	gtk_file_filter_add_pattern(psxfilter, "*.cue");
739 	gtk_file_filter_add_pattern(psxfilter, "*.pbp");
740 	gtk_file_filter_add_pattern(psxfilter, "*.cbn");
741 	gtk_file_filter_add_pattern(psxfilter, "*.BIN");
742 	gtk_file_filter_add_pattern(psxfilter, "*.IMG");
743 	gtk_file_filter_add_pattern(psxfilter, "*.MDF");
744 	gtk_file_filter_add_pattern(psxfilter, "*.ISO");
745 	gtk_file_filter_add_pattern(psxfilter, "*.CUE");
746 	gtk_file_filter_add_pattern(psxfilter, "*.PBP");
747 	gtk_file_filter_add_pattern(psxfilter, "*.CBN");
748 	gtk_file_filter_add_pattern(psxfilter, "*.ecm");
749 	gtk_file_filter_set_name(psxfilter, _("PSX Image Files (*.bin, *.img, *.mdf, *.iso, *.ecm, *.cue, *.pbp, *.cbn)"));
750 	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (chooser), psxfilter);
751 
752 	allfilter = gtk_file_filter_new();
753 	gtk_file_filter_add_pattern(allfilter, "*");
754 	gtk_file_filter_set_name(allfilter, _("All Files"));
755 	gtk_file_chooser_add_filter(GTK_FILE_CHOOSER (chooser), allfilter);
756 
757 	if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_ACCEPT) {
758 		gchar *path = gtk_file_chooser_get_current_folder(GTK_FILE_CHOOSER(chooser));
759 
760 		/* Workaround:
761 		for some reasons gtk_file_chooser_get_current_folder return NULL
762 		if a file is selected from "Recently Used" or "Searsh"*/
763 		if(path != NULL) {
764 		  strcpy(current_folder, path);
765 		  g_free(path);
766 		}
767 
768 		GSList * l = gtk_file_chooser_get_filenames(GTK_FILE_CHOOSER (chooser));
769 		if(l) {
770 		filename = l->data;
771 
772 		/* if the file was selected from "Recently Used" or "Searsh"
773 		we need to extract the path from the filename to set it to current_folder*/
774 		if(path == NULL) {
775 		  strncpy(current_folder, filename, strrchr(filename, '/') - filename);
776 		}
777 
778 		/* Save current path. */
779 		strcpy(Config.IsoImgDir, current_folder);
780 		SaveConfig();
781 
782 		/* free useless data */
783 		GSList * ll = l;
784 		while(l->next) {
785 			l = l->next;
786 			g_free(l->data);
787 		}
788 		g_slist_free(ll);
789 
790 		gtk_widget_destroy(GTK_WIDGET(chooser));
791 		while (gtk_events_pending()) gtk_main_iteration();
792 		return filename;
793 		} else {
794 			gtk_widget_destroy (GTK_WIDGET(chooser));
795 			while (gtk_events_pending()) gtk_main_iteration();
796 			return NULL;
797 		}
798 	} else {
799 		gtk_widget_destroy (GTK_WIDGET(chooser));
800 		while (gtk_events_pending()) gtk_main_iteration();
801 		return NULL;
802 	}
803 }
804 
OnFile_RunImage()805 void OnFile_RunImage() {
806 	gchar *filename;
807 
808 	if (plugins_configured() == FALSE) {
809 		ConfigurePlugins();
810 		return;
811 	}
812 
813 	filename = Open_Iso_Proc();
814 	if (filename == NULL) {
815 		return;
816 	}
817 
818 	destroy_main_window();
819 
820 	SetIsoFile(filename);
821 	g_free(filename);
822 
823 	LoadPlugins();
824 	NetOpened = FALSE;
825 
826 	if (OpenPlugins() == -1) {
827 		SysRunGui();
828 		return;
829 	}
830 
831 	if (CheckCdrom() == -1) {
832 		// Only check the CD if we are starting the console with a CD
833 		ClosePlugins();
834 		SysErrorMessage (_("CD ROM failed"), _("The CD does not appear to be a valid Playstation CD"));
835 		SysRunGui();
836 		return;
837 	}
838 
839 	// Auto-detect: get region first, then rcnt-bios reset
840 	SysReset();
841 
842 	// Read main executable directly from CDRom and start it
843 	if (LoadCdrom() == -1) {
844 		ClosePlugins();
845 		SysErrorMessage(_("Could not load CD-ROM!"), _("The CD-ROM could not be loaded"));
846 		SysRunGui();
847 	}
848 
849 	clear_change_image();
850 	psxCpu->Execute();
851 }
852 
OnEmu_Run()853 void OnEmu_Run() {
854 	if (plugins_configured() == FALSE) {
855 		ConfigurePlugins();
856 		return;
857 	}
858 
859 	destroy_main_window();
860 
861 	if (OpenPlugins() == -1) {
862 		SysRunGui();
863 		return;
864 	}
865 
866 	CheatSearchBackupMemory();
867 	psxCpu->Execute();
868 }
869 
OnEmu_Reset()870 void OnEmu_Reset() {
871 	if (plugins_configured() == FALSE) {
872 		ConfigurePlugins();
873 		return;
874 	}
875 
876 	destroy_main_window();
877 
878 	if (OpenPlugins() == -1) {
879 		SysRunGui();
880 		return;
881 	}
882 
883 	// No extra checks here since this is reset and target has been verified already once
884 	if (reset_load_info) {
885 		SysPrintf("RESET/reloading %s\n", reset_load_info);
886 		SysReset();
887 		Load(reset_load_info);
888 	} else {
889 		SysPrintf("RESET/reloading %s %s\n", CdromId, CdromLabel);
890 		CheckCdrom();
891 		SysReset();
892 		LoadCdrom();
893 	}
894 
895 	psxCpu->Execute();
896 }
897 
OnEmu_Shutdown()898 void OnEmu_Shutdown() {
899 	ReleasePlugins();
900 	SetIsoFile(NULL);
901 	CdromId[0] = '\0';
902 	CdromLabel[0] = '\0';
903 	ResetMenuSlots();
904 	g_free(reset_load_info);
905 	reset_load_info = NULL;
906 }
907 
OnEmu_SwitchImage()908 void OnEmu_SwitchImage() {
909 	gchar *filename;
910 
911 	if (plugins_configured() == FALSE) {
912 		ConfigurePlugins();
913 		return;
914 	}
915 
916 	filename = Open_Iso_Proc();
917 	if (filename == NULL) {
918 		return;
919 	}
920 
921 	destroy_main_window();
922 
923 	SetIsoFile(filename);
924 	g_free(filename);
925 
926 	if (OpenPlugins() == -1) {
927 		SysRunGui();
928 		return;
929 	}
930 
931 	SetCdOpenCaseTime(time(NULL) + 2);
932 	LidInterrupt(); // causes CD lid open event
933 
934 	CheatSearchBackupMemory();
935 	psxCpu->Execute();
936 }
937 
OnFile_Exit()938 void OnFile_Exit() {
939 	DIR *dir;
940 	struct dirent *ent;
941 	void *Handle;
942 	gchar *plugin = NULL;
943 	gchar *dotdir;
944 
945 	dotdir = g_build_filename(getenv("HOME"), PLUGINS_DIR, NULL);
946 
947 	// with this the problem with plugins that are linked with the pthread
948 	// library is solved
949 
950 	dir = opendir(dotdir);
951 	if (dir != NULL) {
952 		while ((ent = readdir(dir)) != NULL) {
953 			plugin = g_build_filename(dotdir, ent->d_name, NULL);
954 
955 			if (strstr(plugin, ".so") == NULL && strstr(plugin, ".dylib") == NULL)
956 				continue;
957 			Handle = dlopen(plugin, RTLD_NOW);
958 			if (Handle == NULL)
959 				continue;
960 
961 			g_free(plugin);
962 		}
963 	}
964 	g_free(dotdir);
965 
966 	bind_textdomain_codeset(PACKAGE_NAME, "");
967 	if (UseGui)
968 		gtk_main_quit();
969 	SysClose();
970 	exit(0);
971 }
972 
state_load(gchar * state_filename)973 void state_load(gchar *state_filename) {
974 	int ret;
975 	char Text[MAXPATHLEN + 20];
976 	FILE *fp;
977 
978 	// check if the state file actually exists
979 	fp = fopen(state_filename, "rb");
980 	if (fp == NULL) {
981 		// file does not exist
982 		return;
983 	}
984 
985 	fclose(fp);
986 
987 	// If the window exists, then we are loading the state from within
988 	// the PCSXR GUI. We need to initialise the plugins first.
989 	if (Window) {
990 		destroy_main_window();
991 
992 		if (OpenPlugins() == -1) {
993 			SysRunGui();
994 			return;
995 		}
996 	}
997 
998 	ret = CheckState(state_filename);
999 
1000 	if (ret == 0) {
1001 		// Check the CD-ROM is valid
1002 		if (CheckCdrom() == -1) {
1003 			ClosePlugins();
1004 			SysRunGui();
1005 			return;
1006 		}
1007 
1008 		// Auto-detect: region first, then rcnt reset
1009 		SysReset();
1010 		ret = LoadState(state_filename);
1011 
1012 		sprintf(Text, _("Loaded state %s."), state_filename);
1013 		GPU_displayText(Text);
1014 	} else {
1015 		sprintf(Text, _("Error loading state %s!"), state_filename);
1016 		GPU_displayText(Text);
1017 	}
1018 }
1019 
state_save(gchar * state_filename)1020 void state_save(gchar *state_filename) {
1021 	char Text[MAXPATHLEN + 20];
1022 
1023 	// If the window exists, then we are saving the state from within
1024 	// the PCSXR GUI. We need to initialise the plugins first.
1025 	if (Window) {
1026 		destroy_main_window();
1027 
1028 		if (OpenPlugins() == -1) {
1029 			SysRunGui();
1030 			return;
1031 		}
1032 	}
1033 
1034 	GPU_updateLace();
1035 
1036 	if (SaveState(state_filename) == 0)
1037 		sprintf(Text, _("Saved state %s."), state_filename);
1038 	else
1039 		sprintf(Text, _("Error saving state %s!"), state_filename);
1040 
1041 	GPU_displayText(Text);
1042 }
1043 
on_states_load(GtkWidget * widget,gpointer user_data)1044 void on_states_load (GtkWidget *widget, gpointer user_data) {
1045 	(void)widget; // unused
1046 
1047 	gchar *state_filename;
1048 	gint state = GPOINTER_TO_INT(user_data);
1049 
1050 	state_filename = get_state_filename(state);
1051 
1052 	state_load(state_filename);
1053 
1054 	g_free(state_filename);
1055 
1056 	psxCpu->Execute();
1057 }
1058 
on_states_save(GtkWidget * widget,gpointer user_data)1059 void on_states_save (GtkWidget *widget, gpointer user_data) {
1060 	(void)widget; // unused
1061 
1062 	gchar *state_filename;
1063 	gint state = GPOINTER_TO_INT(user_data);
1064 
1065 	state_filename = get_state_filename(state);
1066 
1067 	state_save(state_filename);
1068 
1069 	g_free(state_filename);
1070 }
1071 
on_states_load_recent()1072 void on_states_load_recent() {
1073 	gchar *state_filename;
1074 	gint state = StatesC = recent_load_slot;
1075 
1076 	state_filename = get_state_filename(state);
1077 
1078 	state_load(state_filename);
1079 
1080 	g_free(state_filename);
1081 
1082 	psxCpu->Execute();
1083 }
1084 
on_states_load_other()1085 void on_states_load_other() {
1086 	GtkWidget *file_chooser;
1087 	gchar *SStateFile;
1088 
1089 	SStateFile = g_strconcat(getenv("HOME"), STATES_DIR, NULL);
1090 
1091 	file_chooser = gtk_file_chooser_dialog_new(_("Select State File"), NULL, GTK_FILE_CHOOSER_ACTION_OPEN,
1092 		"_Cancel", GTK_RESPONSE_CANCEL,
1093 		"_Open", GTK_RESPONSE_ACCEPT,
1094 		NULL);
1095 	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER (file_chooser), SStateFile);
1096 	g_free(SStateFile);
1097 
1098 	if (gtk_dialog_run(GTK_DIALOG(file_chooser)) == GTK_RESPONSE_ACCEPT) {
1099 		gchar *filename;
1100 
1101 		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(file_chooser));
1102 		gtk_widget_destroy(file_chooser);
1103 
1104 		state_load(filename);
1105 
1106 		g_free(filename);
1107 
1108 		psxCpu->Execute();
1109 	} else
1110 		gtk_widget_destroy(file_chooser);
1111 }
1112 
on_states_save_other()1113 void on_states_save_other() {
1114 	GtkWidget *file_chooser;
1115 	gchar *SStateFile;
1116 
1117 	SStateFile = g_strconcat (getenv("HOME"), STATES_DIR, NULL);
1118 
1119 	file_chooser = gtk_file_chooser_dialog_new(_("Select State File"),
1120 			NULL, GTK_FILE_CHOOSER_ACTION_SAVE,
1121 			"_Cancel", GTK_RESPONSE_CANCEL,
1122 			"_Save", GTK_RESPONSE_OK,
1123 			NULL);
1124 	gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(file_chooser), SStateFile);
1125 	g_free(SStateFile);
1126 
1127 	if (gtk_dialog_run (GTK_DIALOG(file_chooser)) == GTK_RESPONSE_OK) {
1128 		gchar *filename;
1129 
1130 		filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER (file_chooser));
1131 		gtk_widget_destroy(file_chooser);
1132 
1133 		state_save(filename);
1134 
1135 		g_free(filename);
1136 	}
1137 	else
1138 		gtk_widget_destroy(file_chooser);
1139 }
1140 
OnHelp_About(GtkWidget * widget,gpointer user_data)1141 void OnHelp_About(GtkWidget *widget, gpointer user_data) {
1142 	RunAboutDialog();
1143 }
1144 
SysMessage(const char * fmt,...)1145 void SysMessage(const char *fmt, ...) {
1146 	GtkWidget *Txt, *MsgDlg;
1147 	va_list list;
1148 	char msg[512];
1149 
1150 	va_start(list, fmt);
1151 	vsprintf(msg, fmt, list);
1152 	va_end(list);
1153 
1154 	if (msg[strlen(msg) - 1] == '\n')
1155 		msg[strlen(msg) - 1] = 0;
1156 
1157 	if (!UseGui) {
1158 		fprintf(stderr, "%s\n", msg);
1159 		return;
1160 	}
1161 
1162 	MsgDlg = gtk_dialog_new_with_buttons(_("Notice"), NULL,
1163 		GTK_DIALOG_DESTROY_WITH_PARENT, "_OK", GTK_RESPONSE_NONE, NULL);
1164 
1165 	gtk_window_set_position (GTK_WINDOW(MsgDlg), GTK_WIN_POS_CENTER);
1166 
1167 	Txt = gtk_label_new (msg);
1168 	gtk_label_set_line_wrap(GTK_LABEL(Txt), TRUE);
1169 	gtk_container_add (GTK_CONTAINER (gtk_dialog_get_content_area(GTK_DIALOG(MsgDlg))), Txt);
1170 
1171 	gtk_widget_show (Txt);
1172 	gtk_widget_show_all (MsgDlg);
1173 
1174 	g_signal_connect_swapped(G_OBJECT(MsgDlg), "destroy", G_CALLBACK(gtk_main_quit), NULL);
1175 	g_signal_connect_swapped (MsgDlg,
1176 					"response",
1177 					G_CALLBACK (gtk_widget_destroy),
1178 					MsgDlg);
1179 
1180 	gtk_main();
1181 }
1182 
SysErrorMessage(gchar * primary,gchar * secondary)1183 void SysErrorMessage(gchar *primary, gchar *secondary) {
1184 	GtkWidget *message_dialog;
1185 	if (!UseGui)
1186 		printf ("%s - %s\n", primary, secondary);
1187 	else {
1188 		message_dialog = gtk_message_dialog_new(NULL,
1189 				GTK_DIALOG_MODAL,
1190 				GTK_MESSAGE_ERROR,
1191 				GTK_BUTTONS_CLOSE,
1192 				primary,
1193 				NULL);
1194 		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog),
1195 				"%s", secondary);
1196 
1197 		gtk_dialog_run(GTK_DIALOG(message_dialog));
1198 		gtk_widget_destroy(message_dialog);
1199 	}
1200 }
1201 
SysInfoMessage(gchar * primary,gchar * secondary)1202 void SysInfoMessage(gchar *primary, gchar *secondary) {
1203 	GtkWidget *message_dialog;
1204 	if (!UseGui)
1205 		printf ("%s - %s\n", primary, secondary);
1206 	else {
1207 		message_dialog = gtk_message_dialog_new(NULL,
1208 				GTK_DIALOG_MODAL,
1209 				GTK_MESSAGE_INFO,
1210 				GTK_BUTTONS_CLOSE,
1211 				primary,
1212 				NULL);
1213 		gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog),
1214 				"%s", secondary);
1215 
1216 		gtk_dialog_run(GTK_DIALOG(message_dialog));
1217 		gtk_widget_destroy(message_dialog);
1218 	}
1219 }
1220