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 <gdk/gdkkeysyms.h> | |
24 | #include <gtk/gtk.h> | |
25 | #include <glade/glade.h> | |
26 | #include <signal.h> | |
27 | #include <sys/time.h> | |
28 | ||
29 | #include "Linux.h" | |
30 | #include "../libpcsxcore/sio.h" | |
31 | ||
32 | #define MAX_MEMCARD_BLOCKS 15 | |
33 | ||
34 | static gboolean quit; | |
35 | static unsigned int currentIcon; | |
36 | ||
37 | McdBlock Blocks[2][MAX_MEMCARD_BLOCKS]; // Assuming 2 cards, 15 blocks? | |
38 | int IconC[2][MAX_MEMCARD_BLOCKS]; | |
39 | enum { | |
40 | CL_ICON, | |
41 | CL_TITLE, | |
42 | CL_STAT, | |
43 | CL_ID, | |
44 | CL_NAME, | |
45 | NUM_CL | |
46 | }; | |
47 | ||
48 | GtkWidget *GtkCList_McdList1, *GtkCList_McdList2; | |
49 | ||
50 | static void AddColumns(GtkTreeView *treeview) { | |
51 | GtkCellRenderer *renderer; | |
52 | GtkTreeViewColumn *column; | |
53 | ||
54 | // column for icon | |
55 | renderer = gtk_cell_renderer_pixbuf_new (); | |
56 | column = gtk_tree_view_column_new_with_attributes(_("Icon"), | |
57 | renderer, "pixbuf", CL_ICON, NULL); | |
58 | gtk_tree_view_append_column(treeview, column); | |
59 | ||
60 | // column for title | |
61 | renderer = gtk_cell_renderer_text_new(); | |
62 | column = gtk_tree_view_column_new_with_attributes(_("Title"), | |
63 | renderer, "text", CL_TITLE, NULL); | |
64 | gtk_tree_view_append_column(treeview, column); | |
65 | ||
66 | // column for status | |
67 | renderer = gtk_cell_renderer_text_new(); | |
68 | column = gtk_tree_view_column_new_with_attributes(_("Status"), | |
69 | renderer, "text", CL_STAT, NULL); | |
70 | gtk_tree_view_append_column(treeview, column); | |
71 | ||
72 | // column for id | |
73 | renderer = gtk_cell_renderer_text_new(); | |
74 | column = gtk_tree_view_column_new_with_attributes(_("ID"), | |
75 | renderer, "text", CL_ID, NULL); | |
76 | gtk_tree_view_append_column(treeview, column); | |
77 | ||
78 | // column for Name | |
79 | renderer = gtk_cell_renderer_text_new(); | |
80 | column = gtk_tree_view_column_new_with_attributes(_("Name"), | |
81 | renderer, "text", CL_NAME, NULL); | |
82 | gtk_tree_view_append_column(treeview, column); | |
83 | } | |
84 | ||
85 | static GdkPixbuf *SetIcon(GtkWidget *dialog, short *icon, int i) { | |
86 | GdkPixmap *pixmap; | |
87 | GdkImage *image; | |
88 | GdkVisual *visual; | |
89 | GdkPixbuf *pixbuf; | |
90 | GdkGC *gc; | |
91 | int x, y, c; | |
92 | ||
93 | visual = gdk_window_get_visual(dialog->window); | |
94 | ||
95 | if (visual->depth == 8) return NULL; | |
96 | ||
97 | image = gdk_image_new(GDK_IMAGE_NORMAL, visual, 32, 32); | |
98 | ||
99 | for (y = 0; y < 32; y++) { | |
100 | for (x = 0; x < 32; x++) { | |
101 | c = icon[(y>>1) * 16 + (x>>1)]; | |
102 | c = ((c & 0x001f) << 10) | ((c & 0x7c00) >> 10) | (c & 0x03e0); | |
103 | if (visual->depth == 16) | |
104 | c = (c & 0x001f) | ((c & 0x7c00) << 1) | ((c & 0x03e0) << 1); | |
105 | else if (visual->depth == 24 || visual->depth == 32) | |
106 | c = ((c & 0x001f) << 3) | ((c & 0x03e0) << 6) | ((c & 0x7c00) << 9); | |
107 | ||
108 | gdk_image_put_pixel(image, x, y, c); | |
109 | } | |
110 | } | |
111 | ||
112 | pixmap = gdk_pixmap_new(dialog->window, 32, 32, visual->depth); | |
113 | ||
114 | gc = gdk_gc_new(pixmap); | |
115 | gdk_draw_image(pixmap, gc, image, 0, 0, 0, 0, 32, 32); | |
116 | gdk_gc_destroy(gc); | |
117 | gdk_image_destroy(image); | |
118 | ||
119 | pixbuf = gdk_pixbuf_get_from_drawable(NULL, GDK_PIXMAP (pixmap), NULL, | |
120 | 0, 0, 0, 0, -1, -1); | |
121 | g_object_unref(pixmap); | |
122 | ||
123 | return pixbuf; | |
124 | } | |
125 | ||
126 | static void LoadListItems(int mcd, GtkWidget *widget) { | |
127 | int i; | |
128 | GladeXML *xml; | |
129 | GtkWidget *List; | |
130 | GtkWidget *dialog; | |
131 | GtkListStore *store; | |
132 | GtkTreeIter iter; | |
133 | GdkPixbuf *pixbuf; | |
134 | gchar *title; | |
135 | ||
136 | store = gtk_list_store_new(NUM_CL, GDK_TYPE_PIXBUF, G_TYPE_STRING, | |
137 | G_TYPE_STRING, G_TYPE_STRING, G_TYPE_STRING); | |
138 | ||
139 | xml = glade_get_widget_tree(widget); | |
140 | dialog = glade_xml_get_widget(xml, "McdsDlg"); | |
141 | ||
142 | if (mcd == 1) List = glade_xml_get_widget(xml, "GtkCList_McdList1"); | |
143 | else List = glade_xml_get_widget(xml, "GtkCList_McdList2"); | |
144 | ||
145 | for (i = 0; i < MAX_MEMCARD_BLOCKS; i++) { | |
146 | McdBlock *Info; | |
147 | gchar *state; | |
148 | ||
149 | Info = &Blocks[mcd - 1][i]; | |
150 | IconC[mcd - 1][i] = 0; | |
151 | ||
152 | if ((Info->Flags & 0xF0) == 0xA0) { | |
153 | if ((Info->Flags & 0xF) >= 1 && | |
154 | (Info->Flags & 0xF) <= 3) { | |
155 | state = _("Deleted"); | |
156 | } else | |
157 | state = _("Free"); | |
158 | } else if ((Info->Flags & 0xF0) == 0x50) | |
159 | state = _("Used"); | |
160 | else | |
161 | state = _("Free"); | |
162 | ||
163 | pixbuf = SetIcon(dialog, Info->Icon, i + 1); | |
164 | ||
165 | gtk_list_store_append(store, &iter); | |
166 | ||
167 | title = g_convert(Info->sTitle, strlen(Info->sTitle), "UTF-8", | |
168 | "Shift-JIS", NULL, NULL, NULL); | |
169 | ||
170 | gtk_list_store_set(store, &iter, | |
171 | CL_ICON, pixbuf, | |
172 | CL_TITLE, title, | |
173 | CL_STAT, state, | |
174 | CL_NAME, Info->Name, | |
175 | CL_ID, Info->ID, | |
176 | -1); | |
177 | ||
178 | g_free(title); | |
179 | ||
180 | g_object_unref(pixbuf); | |
181 | } | |
182 | ||
183 | gtk_tree_view_set_model(GTK_TREE_VIEW(List), GTK_TREE_MODEL(store)); | |
184 | g_object_unref(G_OBJECT(store)); | |
185 | gtk_tree_view_set_rules_hint(GTK_TREE_VIEW(List), TRUE); | |
186 | gtk_widget_show(List); | |
187 | } | |
188 | ||
189 | static void UpdateFilenameButtons(GtkWidget *widget) { | |
190 | int i; | |
191 | GladeXML *xml; | |
192 | GtkWidget *dialog; | |
193 | const char *filename; | |
194 | gchar *p; | |
195 | ||
196 | xml = glade_get_widget_tree(widget); | |
197 | dialog = glade_xml_get_widget(xml, "McdsDlg"); | |
198 | ||
199 | for (i = 0; i < 2; i++) { | |
200 | if (i == 0) { | |
201 | widget = glade_xml_get_widget(xml, "Mcd1Label"); | |
202 | filename = Config.Mcd1; | |
203 | } else { | |
204 | widget = glade_xml_get_widget(xml, "Mcd2Label"); | |
205 | filename = Config.Mcd2; | |
206 | } | |
207 | ||
208 | p = g_path_get_basename(filename); | |
209 | gtk_label_set_text(GTK_LABEL(widget), p); | |
210 | g_free(p); | |
211 | } | |
212 | } | |
213 | ||
214 | static void LoadMcdDlg(GtkWidget *widget) { | |
215 | int i; | |
216 | ||
217 | for (i = 0; i < MAX_MEMCARD_BLOCKS; i++) { | |
218 | GetMcdBlockInfo(1, i + 1, &Blocks[0][i]); | |
219 | GetMcdBlockInfo(2, i + 1, &Blocks[1][i]); | |
220 | } | |
221 | ||
222 | LoadListItems(1, widget); | |
223 | LoadListItems(2, widget); | |
224 | ||
225 | UpdateFilenameButtons(widget); | |
226 | } | |
227 | ||
228 | static void OnTreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data); | |
229 | ||
230 | static void UpdateListItems(int mcd, GtkWidget *widget) { | |
231 | GladeXML *xml; | |
232 | GtkWidget *List; | |
233 | GtkWidget *dialog; | |
234 | GtkListStore *store; | |
235 | GtkTreeIter iter; | |
236 | GdkPixbuf *pixbuf; | |
237 | short *pIcon; | |
238 | int i; | |
239 | gchar *title; | |
240 | ||
241 | xml = glade_get_widget_tree(widget); | |
242 | dialog = glade_xml_get_widget(xml, "McdsDlg"); | |
243 | ||
244 | if (mcd == 1) List = glade_xml_get_widget(xml, "GtkCList_McdList1"); | |
245 | else List = glade_xml_get_widget(xml, "GtkCList_McdList2"); | |
246 | ||
247 | store = GTK_LIST_STORE(gtk_tree_view_get_model(GTK_TREE_VIEW(List))); | |
248 | gtk_tree_model_get_iter_first(GTK_TREE_MODEL(store), &iter); | |
249 | ||
250 | for (i = 0; i < MAX_MEMCARD_BLOCKS; i++) { | |
251 | McdBlock *Info; | |
252 | gchar *state; | |
253 | ||
254 | Info = &Blocks[mcd - 1][i]; | |
255 | IconC[mcd - 1][i] = 0; | |
256 | ||
257 | if ((Info->Flags & 0xF0) == 0xA0) { | |
258 | if ((Info->Flags & 0xF) >= 1 && | |
259 | (Info->Flags & 0xF) <= 3) { | |
260 | state = _("Deleted"); | |
261 | } else | |
262 | state = _("Free"); | |
263 | } else if ((Info->Flags & 0xF0) == 0x50) | |
264 | state = _("Used"); | |
265 | else | |
266 | state = _("Free"); | |
267 | ||
268 | if (Info->IconCount > 0) { | |
269 | pIcon = &Info->Icon[(currentIcon % Info->IconCount) * 16 * 16]; | |
270 | } else { | |
271 | pIcon = Info->Icon; | |
272 | } | |
273 | ||
274 | pixbuf = SetIcon(dialog, pIcon, i + 1); | |
275 | title = g_convert(Info->sTitle, strlen(Info->sTitle), "UTF-8", | |
276 | "Shift-JIS", NULL, NULL, NULL); | |
277 | ||
278 | gtk_list_store_set(store, &iter, | |
279 | CL_ICON, pixbuf, | |
280 | CL_TITLE, title, | |
281 | CL_STAT, state, | |
282 | CL_NAME, Info->Name, | |
283 | CL_ID, Info->ID, | |
284 | -1); | |
285 | ||
286 | g_free(title); | |
287 | ||
288 | g_object_unref(pixbuf); | |
289 | gtk_tree_model_iter_next(GTK_TREE_MODEL(store), &iter); | |
290 | } | |
291 | ||
292 | gtk_widget_show(List); | |
293 | ||
294 | OnTreeSelectionChanged(gtk_tree_view_get_selection(GTK_TREE_VIEW(List)), (gpointer)mcd); | |
295 | } | |
296 | ||
297 | static void UpdateMcdDlg(GtkWidget *widget) { | |
298 | int i; | |
299 | ||
300 | for (i = 0; i < MAX_MEMCARD_BLOCKS; i++) { | |
301 | GetMcdBlockInfo(1, i + 1, &Blocks[0][i]); | |
302 | GetMcdBlockInfo(2, i + 1, &Blocks[1][i]); | |
303 | } | |
304 | ||
305 | UpdateListItems(1, widget); | |
306 | UpdateListItems(2, widget); | |
307 | ||
308 | UpdateFilenameButtons(widget); | |
309 | } | |
310 | ||
311 | static void OnMcd_Close(GtkDialog *dialog, gint arg1, gpointer user_data) { | |
312 | quit = TRUE; | |
313 | SaveConfig(); | |
314 | gtk_widget_destroy(GTK_WIDGET(dialog)); | |
315 | } | |
316 | ||
317 | static void OnMcd_FileChange(GtkWidget *widget, gpointer user_data) { | |
318 | gint memcard = (int)user_data; | |
319 | gchar *filename; | |
320 | GtkWidget *chooser; | |
321 | ||
322 | // Ask for name of memory card | |
323 | chooser = gtk_file_chooser_dialog_new(_("Select A File"), | |
324 | NULL, GTK_FILE_CHOOSER_ACTION_OPEN, | |
325 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
326 | GTK_STOCK_OPEN, GTK_RESPONSE_OK, | |
327 | NULL); | |
328 | ||
329 | if (memcard == 1) | |
330 | gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(chooser), Config.Mcd1); | |
331 | else | |
332 | gtk_file_chooser_set_filename(GTK_FILE_CHOOSER(chooser), Config.Mcd2); | |
333 | ||
334 | if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { | |
335 | gtk_widget_hide(chooser); | |
336 | ||
337 | filename = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); | |
338 | ||
339 | if (filename != NULL) { | |
340 | if (memcard == 1) strncpy(Config.Mcd1, filename, MAXPATHLEN); | |
341 | else strncpy(Config.Mcd2, filename, MAXPATHLEN); | |
342 | ||
343 | LoadMcd(memcard, filename); | |
344 | LoadMcdDlg(widget); | |
345 | ||
346 | g_free(filename); | |
347 | } | |
348 | } | |
349 | ||
350 | gtk_widget_destroy(chooser); | |
351 | } | |
352 | ||
353 | // format a memory card | |
354 | static void OnMcd_Format(GtkWidget *widget, gpointer user_data) { | |
355 | GladeXML *xml; | |
356 | GtkWidget *message_dialog; | |
357 | gint result; | |
358 | char *str; | |
359 | ||
360 | gint memcard = (int)user_data; | |
361 | ||
362 | message_dialog = gtk_message_dialog_new(NULL, GTK_DIALOG_MODAL, | |
363 | GTK_MESSAGE_QUESTION, GTK_BUTTONS_NONE, | |
364 | _("Format this Memory Card?")); | |
365 | gtk_message_dialog_format_secondary_text(GTK_MESSAGE_DIALOG(message_dialog), | |
366 | _("If you format the memory card, the card will be empty, and any existing data overwritten.")); | |
367 | gtk_dialog_add_buttons(GTK_DIALOG(message_dialog), | |
368 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
369 | _("Format card"), GTK_RESPONSE_YES, NULL); | |
370 | ||
371 | result = gtk_dialog_run(GTK_DIALOG(message_dialog)); | |
372 | gtk_widget_destroy(message_dialog); | |
373 | ||
374 | if (result == GTK_RESPONSE_YES) { | |
375 | xml = glade_get_widget_tree(widget); | |
376 | ||
377 | if (memcard == 1) str = Config.Mcd1; | |
378 | else str = Config.Mcd2; | |
379 | ||
380 | CreateMcd(str); | |
381 | LoadMcd(memcard, str); | |
382 | ||
383 | UpdateMcdDlg(widget); | |
384 | } | |
385 | } | |
386 | ||
387 | // create a new, formatted memory card | |
388 | static void OnMcd_New(GtkWidget *widget, gpointer user_data) { | |
389 | GtkWidget *chooser; | |
390 | gchar *path; | |
391 | ||
392 | // Ask for name of new memory card | |
393 | chooser = gtk_file_chooser_dialog_new(_("Create a new Memory Card"), | |
394 | NULL, GTK_FILE_CHOOSER_ACTION_SAVE, | |
395 | GTK_STOCK_CANCEL, GTK_RESPONSE_CANCEL, | |
396 | GTK_STOCK_SAVE, GTK_RESPONSE_OK, | |
397 | NULL); | |
398 | ||
399 | // Card should be put into $HOME/.pcsx/memcards | |
400 | path = g_build_filename(g_get_home_dir(), ".pcsx", "memcards", NULL); | |
401 | gtk_file_chooser_set_current_folder(GTK_FILE_CHOOSER(chooser), path); | |
402 | gtk_file_chooser_set_current_name(GTK_FILE_CHOOSER(chooser), _("New Memory Card.mcd")); | |
403 | gtk_file_chooser_set_do_overwrite_confirmation(GTK_FILE_CHOOSER(chooser), TRUE); | |
404 | ||
405 | if (gtk_dialog_run(GTK_DIALOG(chooser)) == GTK_RESPONSE_OK) { | |
406 | gchar *name; | |
407 | ||
408 | gtk_widget_hide(chooser); | |
409 | name = gtk_file_chooser_get_filename(GTK_FILE_CHOOSER(chooser)); | |
410 | ||
411 | CreateMcd(name); | |
412 | ||
413 | if ((int)user_data == 1) strncpy(Config.Mcd1, name, MAXPATHLEN); | |
414 | else strncpy(Config.Mcd2, name, MAXPATHLEN); | |
415 | ||
416 | LoadMcd((int)user_data, name); | |
417 | LoadMcdDlg(widget); | |
418 | ||
419 | g_free(name); | |
420 | } | |
421 | ||
422 | gtk_widget_destroy(chooser); | |
423 | g_free(path); | |
424 | } | |
425 | ||
426 | static int copy = 0, copymcd = 0; | |
427 | ||
428 | static int GetFreeMemcardSlot(int target_card) { | |
429 | McdBlock *Info; | |
430 | gboolean found = FALSE; | |
431 | ||
432 | int i = 0; | |
433 | while (i < 15 && found == FALSE) { | |
434 | Info = &Blocks[target_card][i]; | |
435 | if (g_ascii_strcasecmp(Info->Title, "") == 0) { | |
436 | found = TRUE; | |
437 | } else { | |
438 | i++; | |
439 | } | |
440 | } | |
441 | ||
442 | if (found == TRUE) | |
443 | return i; | |
444 | ||
445 | // no free slots, try to find a deleted one | |
446 | i = 0; | |
447 | while (i < 15 && found == FALSE) { | |
448 | Info = &Blocks[target_card][i]; | |
449 | if ((Info->Flags & 0xF0) != 0x50) { | |
450 | found = TRUE; | |
451 | } else { | |
452 | i++; | |
453 | } | |
454 | } | |
455 | ||
456 | if (found == TRUE) | |
457 | return i; | |
458 | ||
459 | return -1; | |
460 | } | |
461 | ||
462 | static void CopyMemcardData(char *from, char *to, gint *i, gchar *str) { | |
463 | memcpy(to + (*i + 1) * 128, from + (copy + 1) * 128, 128); | |
464 | SaveMcd((char *)str, to, (*i + 1) * 128, 128); | |
465 | memcpy(to + (*i + 1) * 1024 * 8, from + (copy+1) * 1024 * 8, 1024 * 8); | |
466 | SaveMcd((char *)str, to, (*i + 1) * 1024 * 8, 1024 * 8); | |
467 | } | |
468 | ||
469 | static void OnMcd_CopyTo(GtkWidget *widget, gpointer user_data) { | |
470 | gint mcd = (gint)user_data; | |
471 | ||
472 | GtkTreeIter iter; | |
473 | GtkTreeModel *model; | |
474 | GtkTreePath *path; | |
475 | gint *i; | |
476 | GladeXML *xml; | |
477 | GtkTreeSelection *treesel; | |
478 | gchar *str; | |
479 | char *source, *destination; | |
480 | ||
481 | int first_free_slot; | |
482 | ||
483 | xml = glade_get_widget_tree(widget); | |
484 | ||
485 | if (mcd == 1) | |
486 | treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(GtkCList_McdList2)); | |
487 | else | |
488 | treesel = gtk_tree_view_get_selection(GTK_TREE_VIEW(GtkCList_McdList1)); | |
489 | ||
490 | // If the item selected is not reported as a 'Free' slot | |
491 | if (gtk_tree_selection_get_selected(treesel, &model, &iter)) { | |
492 | path = gtk_tree_model_get_path(model, &iter); | |
493 | i = gtk_tree_path_get_indices(path); | |
494 | copy = *i; | |
495 | copymcd = mcd; | |
496 | gtk_tree_path_free(path); | |
497 | } | |
498 | ||
499 | // Determine the first free slot in the target memory card | |
500 | first_free_slot = GetFreeMemcardSlot(mcd - 1); | |
501 | if (first_free_slot == -1) { | |
502 | // No free slots available on the destination card | |
503 | SysErrorMessage(_("No free space on memory card"), | |
504 | _("There are no free slots available on the target memory card. Please delete a slot first.")); | |
505 | return; | |
506 | } | |
507 | ||
508 | xml = glade_get_widget_tree(GtkCList_McdList1); | |
509 | ||
510 | if (mcd == 1) { | |
511 | str = Config.Mcd1; | |
512 | source = Mcd2Data; | |
513 | destination = Mcd1Data; | |
514 | } else { | |
515 | str = Config.Mcd2; | |
516 | source = Mcd1Data; | |
517 | destination = Mcd2Data; | |
518 | } | |
519 | ||
520 | CopyMemcardData(source, destination, &first_free_slot, str); | |
521 | UpdateMcdDlg(widget); | |
522 | } | |
523 | ||
524 | static void OnMemcardDelete(GtkWidget *widget, gpointer user_data) { | |
525 | McdBlock *Info; | |
526 | int i, xor = 0, j; | |
527 | char *data, *ptr; | |
528 | GtkTreeIter iter; | |
529 | GtkTreeModel *model; | |
530 | GtkTreePath *path; | |
531 | gchar *filename; | |
532 | GladeXML *xml; | |
533 | gboolean selected; | |
534 | GtkWidget *tree; | |
535 | GtkTreeSelection *sel; | |
536 | ||
537 | gint memcard = (int)user_data; | |
538 | ||
539 | xml = glade_get_widget_tree(widget); | |
540 | ||
541 | if (memcard == 1) { | |
542 | tree = glade_xml_get_widget(xml, "GtkCList_McdList1"); | |
543 | sel = gtk_tree_view_get_selection(GTK_TREE_VIEW (tree)); | |
544 | selected = gtk_tree_selection_get_selected (sel, &model, &iter); | |
545 | data = Mcd1Data; | |
546 | filename = Config.Mcd1; | |
547 | } else { | |
548 | tree = glade_xml_get_widget(xml, "GtkCList_McdList2"); | |
549 | sel = gtk_tree_view_get_selection(GTK_TREE_VIEW (tree)); | |
550 | selected = gtk_tree_selection_get_selected(sel, &model, &iter); | |
551 | data = Mcd2Data; | |
552 | filename = Config.Mcd2; | |
553 | } | |
554 | ||
555 | if (selected) { | |
556 | path = gtk_tree_model_get_path(model, &iter); | |
557 | i = *gtk_tree_path_get_indices(path); | |
558 | ||
559 | i++; | |
560 | ptr = data + i * 128; | |
561 | Info = &Blocks[memcard - 1][i - 1]; | |
562 | ||
563 | if ((Info->Flags & 0xF0) == 0xA0) { | |
564 | if ((Info->Flags & 0xF) >= 1 && | |
565 | (Info->Flags & 0xF) <= 3) { // deleted | |
566 | *ptr = 0x50 | (Info->Flags & 0xF); | |
567 | } else return; | |
568 | } else if ((Info->Flags & 0xF0) == 0x50) { // used | |
569 | *ptr = 0xA0 | (Info->Flags & 0xF); | |
570 | } else { return; } | |
571 | ||
572 | for (j = 0; j < 127; j++) xor ^= *ptr++; | |
573 | *ptr = xor; | |
574 | ||
575 | SaveMcd((char *)filename, data, i * 128, 128); | |
576 | UpdateMcdDlg(widget); | |
577 | } | |
578 | } | |
579 | ||
580 | static void OnTreeSelectionChanged(GtkTreeSelection *selection, gpointer user_data) { | |
581 | GladeXML *xml; | |
582 | GtkTreeIter iter; | |
583 | GtkTreeModel *model; | |
584 | GtkTreePath *path; | |
585 | ||
586 | gboolean selected; | |
587 | int i; | |
588 | McdBlock b; | |
589 | ||
590 | gint memcard = (int)user_data; | |
591 | ||
592 | xml = glade_get_widget_tree(GtkCList_McdList1); | |
593 | selected = gtk_tree_selection_get_selected(selection, &model, &iter); | |
594 | ||
595 | if (selected) { | |
596 | path = gtk_tree_model_get_path(model, &iter); | |
597 | i = *gtk_tree_path_get_indices(path); | |
598 | gtk_tree_path_free(path); | |
599 | ||
600 | // If a row was selected, and the row is not blank, we can now enable | |
601 | // some of the disabled widgets | |
602 | if (memcard == 1) { | |
603 | GetMcdBlockInfo(1, i + 1, &b); | |
604 | ||
605 | if ((b.Flags >= 0xA1 && b.Flags <= 0xA3) || ((b.Flags & 0xF0) == 0x50)) { | |
606 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete1"), TRUE); | |
607 | } else { | |
608 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete1"), FALSE); | |
609 | } | |
610 | ||
611 | if ((b.Flags & 0xF0) == 0x50) { | |
612 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo2"), TRUE); | |
613 | } else { | |
614 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo2"), FALSE); | |
615 | } | |
616 | } else { | |
617 | GetMcdBlockInfo(2, i + 1, &b); | |
618 | ||
619 | if ((b.Flags >= 0xA1 && b.Flags <= 0xA3) || ((b.Flags & 0xF0) == 0x50)) { | |
620 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete2"), TRUE); | |
621 | } else { | |
622 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete2"), FALSE); | |
623 | } | |
624 | ||
625 | if ((b.Flags & 0xF0) == 0x50) { | |
626 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo1"), TRUE); | |
627 | } else { | |
628 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo1"), FALSE); | |
629 | } | |
630 | } | |
631 | } else { | |
632 | if (memcard == 1) { | |
633 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo2"), FALSE); | |
634 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete1"), FALSE); | |
635 | } else { | |
636 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_CopyTo1"), FALSE); | |
637 | gtk_widget_set_sensitive(glade_xml_get_widget(xml, "GtkButton_Delete2"), FALSE); | |
638 | } | |
639 | } | |
640 | } | |
641 | ||
642 | gboolean updateFunc(gpointer data) { | |
643 | if (quit) return FALSE; | |
644 | currentIcon++; | |
645 | UpdateListItems(1, GtkCList_McdList1); | |
646 | UpdateListItems(2, GtkCList_McdList2); | |
647 | g_timeout_add(333, updateFunc, 0); | |
648 | return FALSE; | |
649 | } | |
650 | ||
651 | void OnConf_Mcds() { | |
652 | GladeXML *xml; | |
653 | GtkWidget *dialog; | |
654 | GtkWidget *widget; | |
655 | GtkTreeSelection *treesel1, *treesel2; | |
656 | gchar *str; | |
657 | ||
658 | xml = glade_xml_new(PACKAGE_DATA_DIR "pcsx.glade2", "McdsDlg", NULL); | |
659 | ||
660 | if (!xml) { | |
661 | g_warning("We could not load the interface!"); | |
662 | return; | |
663 | } | |
664 | ||
665 | dialog = glade_xml_get_widget(xml, "McdsDlg"); | |
666 | ||
667 | gtk_window_set_title(GTK_WINDOW(dialog), _("Memory Card Manager")); | |
668 | ||
669 | // Assign default memory cards | |
670 | if (!strlen(Config.Mcd1)) { | |
671 | str = g_strconcat(getenv("HOME"), DEFAULT_MEM_CARD_1, NULL); | |
672 | strcpy(Config.Mcd1, str); | |
673 | g_free(str); | |
674 | } | |
675 | ||
676 | if (!strlen(Config.Mcd2)) { | |
677 | str = g_strconcat(getenv("HOME"), DEFAULT_MEM_CARD_2, NULL); | |
678 | strcpy(Config.Mcd2, str); | |
679 | g_free(str); | |
680 | } | |
681 | ||
682 | GtkCList_McdList1 = glade_xml_get_widget(xml, "GtkCList_McdList1"); | |
683 | AddColumns(GTK_TREE_VIEW(GtkCList_McdList1)); | |
684 | GtkCList_McdList2 = glade_xml_get_widget(xml, "GtkCList_McdList2"); | |
685 | AddColumns(GTK_TREE_VIEW(GtkCList_McdList2)); | |
686 | ||
687 | treesel1 = gtk_tree_view_get_selection(GTK_TREE_VIEW (GtkCList_McdList1)); | |
688 | gtk_tree_selection_set_mode(treesel1, GTK_SELECTION_SINGLE); | |
689 | g_signal_connect_data(G_OBJECT(treesel1), "changed", | |
690 | G_CALLBACK(OnTreeSelectionChanged), | |
691 | (gpointer)1, NULL, G_CONNECT_AFTER); | |
692 | ||
693 | treesel2 = gtk_tree_view_get_selection(GTK_TREE_VIEW (GtkCList_McdList2)); | |
694 | gtk_tree_selection_set_mode(treesel2, GTK_SELECTION_SINGLE); | |
695 | g_signal_connect_data(G_OBJECT(treesel2), "changed", | |
696 | G_CALLBACK(OnTreeSelectionChanged), | |
697 | (gpointer)2, NULL, G_CONNECT_AFTER); | |
698 | ||
699 | LoadMcdDlg(dialog); | |
700 | ||
701 | // Setup a handler for when Close or Cancel is clicked | |
702 | g_signal_connect_data(GTK_OBJECT(dialog), "response", | |
703 | GTK_SIGNAL_FUNC(OnMcd_Close), xml, (GClosureNotify)g_object_unref, G_CONNECT_AFTER); | |
704 | ||
705 | widget = glade_xml_get_widget(xml, "GtkButton_Format1"); | |
706 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
707 | GTK_SIGNAL_FUNC(OnMcd_Format), (gpointer)1, NULL, G_CONNECT_AFTER); | |
708 | ||
709 | widget = glade_xml_get_widget(xml, "GtkButton_Format2"); | |
710 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
711 | GTK_SIGNAL_FUNC(OnMcd_Format), (gpointer)2, NULL, G_CONNECT_AFTER); | |
712 | ||
713 | widget = glade_xml_get_widget(xml, "Mcd1Button"); | |
714 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
715 | GTK_SIGNAL_FUNC(OnMcd_FileChange), (gpointer)1, NULL, G_CONNECT_AFTER); | |
716 | ||
717 | widget = glade_xml_get_widget(xml, "Mcd2Button"); | |
718 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
719 | GTK_SIGNAL_FUNC(OnMcd_FileChange), (gpointer)2, NULL, G_CONNECT_AFTER); | |
720 | ||
721 | widget = glade_xml_get_widget(xml, "GtkButton_New1"); | |
722 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
723 | GTK_SIGNAL_FUNC(OnMcd_New), (gpointer)1, NULL, G_CONNECT_AFTER); | |
724 | ||
725 | widget = glade_xml_get_widget(xml, "GtkButton_New2"); | |
726 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
727 | GTK_SIGNAL_FUNC(OnMcd_New), (gpointer)2, NULL, G_CONNECT_AFTER); | |
728 | ||
729 | widget = glade_xml_get_widget(xml, "GtkButton_CopyTo1"); | |
730 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
731 | GTK_SIGNAL_FUNC(OnMcd_CopyTo), (gpointer)1, NULL, G_CONNECT_AFTER); | |
732 | gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE); | |
733 | ||
734 | widget = glade_xml_get_widget(xml, "GtkButton_CopyTo2"); | |
735 | g_signal_connect_data(GTK_OBJECT(widget), "clicked", | |
736 | GTK_SIGNAL_FUNC(OnMcd_CopyTo), (gpointer)2, NULL, G_CONNECT_AFTER); | |
737 | gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE); | |
738 | ||
739 | widget = glade_xml_get_widget(xml, "GtkButton_Delete1"); | |
740 | g_signal_connect_data (GTK_OBJECT (widget), "clicked", | |
741 | GTK_SIGNAL_FUNC(OnMemcardDelete), (gpointer)1, NULL, G_CONNECT_AFTER); | |
742 | gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE); | |
743 | ||
744 | widget = glade_xml_get_widget(xml, "GtkButton_Delete2"); | |
745 | g_signal_connect_data (GTK_OBJECT (widget), "clicked", | |
746 | GTK_SIGNAL_FUNC(OnMemcardDelete), (gpointer)2, NULL, G_CONNECT_AFTER); | |
747 | gtk_widget_set_sensitive(GTK_WIDGET(widget), FALSE); | |
748 | ||
749 | quit = FALSE; | |
750 | currentIcon = 0; | |
751 | ||
752 | g_timeout_add(1, updateFunc, 0); | |
753 | ||
754 | while (gtk_events_pending()) { gtk_main_iteration(); } | |
755 | } |