--- BasiliskII/src/Windows/prefs_editor_gtk.cpp 2005/06/20 08:40:34 1.1 +++ BasiliskII/src/Windows/prefs_editor_gtk.cpp 2005/11/29 22:59:44 1.10 @@ -20,8 +20,11 @@ #include "sysdeps.h" -#include #include +#include +#include +#include +#include #include "user_strings.h" #include "version.h" @@ -29,6 +32,7 @@ #include "xpram.h" #include "prefs.h" #include "prefs_editor.h" +#include "b2ether/inc/b2ether_hl.h" // Global variables @@ -49,6 +53,24 @@ static void read_settings(void); /* + * SheepShaver glue + */ + +#ifdef SHEEPSHAVER +#define DISABLE_SCSI 1 +#define PROGRAM_NAME "SheepShaver" +enum { + STR_WINDOW_LAB = STR_WINDOW_CTRL, + STR_FULLSCREEN_LAB = STR_FULLSCREEN_CTRL, + STR_SERIALA_CTRL = STR_SERPORTA_CTRL, + STR_SERIALB_CTRL = STR_SERPORTB_CTRL, +}; +#else +#define PROGRAM_NAME "BasiliskII" +#endif + + +/* * Utility functions */ @@ -157,6 +179,86 @@ static GtkWidget *make_table(GtkWidget * return table; } +static GtkWidget *table_make_option_menu(GtkWidget *table, int row, int label_id, const opt_desc *options, int active) +{ + GtkWidget *label, *opt, *menu; + + label = gtk_label_new(GetString(label_id)); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + opt = gtk_option_menu_new(); + gtk_widget_show(opt); + menu = gtk_menu_new(); + + while (options->label_id) { + add_menu_item(menu, options->label_id, options->func); + options++; + } + gtk_menu_set_active(GTK_MENU(menu), active); + + gtk_option_menu_set_menu(GTK_OPTION_MENU(opt), menu); + gtk_table_attach(GTK_TABLE(table), opt, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + return menu; +} + +static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, GList *glist) +{ + GtkWidget *label, *combo; + char str[32]; + + label = gtk_label_new(GetString(label_id)); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + combo = gtk_combo_new(); + gtk_widget_show(combo); + gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); + + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); + gtk_table_attach(GTK_TABLE(table), combo, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + + return combo; +} + +static GtkWidget *table_make_combobox(GtkWidget *table, int row, int label_id, const char *default_value, const combo_desc *options) +{ + GList *glist = NULL; + while (options->label_id) { + glist = g_list_append(glist, (void *)GetString(options->label_id)); + options++; + } + + return table_make_combobox(table, row, label_id, default_value, glist); +} + +static GtkWidget *table_make_file_entry(GtkWidget *table, int row, int label_id, const char *prefs_item, bool only_dirs = false) +{ + GtkWidget *box, *label, *entry, *button; + + label = gtk_label_new(GetString(label_id)); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, row, row + 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + const char *str = PrefsFindString(prefs_item); + if (str == NULL) + str = ""; + + box = gtk_hbox_new(FALSE, 4); + gtk_widget_show(box); + gtk_table_attach(GTK_TABLE(table), box, 1, 2, row, row + 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + + entry = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(entry), str); + gtk_widget_show(entry); + gtk_box_pack_start(GTK_BOX(box), entry, TRUE, TRUE, 0); + + button = make_browse_button(entry); + gtk_box_pack_start(GTK_BOX(box), button, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(entry), "chooser_button", button); + return entry; +} + static GtkWidget *make_option_menu(GtkWidget *top, int label_id, const opt_desc *options, int active) { GtkWidget *box, *label, *opt, *menu; @@ -222,10 +324,9 @@ static GtkWidget *make_checkbox(GtkWidge return button; } -static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *prefs_item, const combo_desc *options) +static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, GList *glist) { GtkWidget *box, *label, *combo; - char str[32]; box = gtk_hbox_new(FALSE, 4); gtk_widget_show(box); @@ -234,24 +335,28 @@ static GtkWidget *make_combobox(GtkWidge label = gtk_label_new(GetString(label_id)); gtk_widget_show(label); gtk_box_pack_start(GTK_BOX(box), label, FALSE, FALSE, 0); - - GList *glist = NULL; - while (options->label_id) { - glist = g_list_append(glist, (void *)GetString(options->label_id)); - options++; - } combo = gtk_combo_new(); gtk_widget_show(combo); gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); - sprintf(str, "%d", PrefsFindInt32(prefs_item)); - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); + gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), default_value); gtk_box_pack_start(GTK_BOX(box), combo, TRUE, TRUE, 0); return combo; } +static GtkWidget *make_combobox(GtkWidget *top, int label_id, const char *default_value, const combo_desc *options) +{ + GList *glist = NULL; + while (options->label_id) { + glist = g_list_append(glist, (void *)GetString(options->label_id)); + options++; + } + + return make_combobox(top, label_id, default_value, glist); +} + /* * Show preferences editor @@ -307,11 +412,15 @@ static void cb_about(...) char str[512]; sprintf(str, - "Basilisk II\nVersion %d.%d\n\n" + PROGRAM_NAME "\nVersion %d.%d\n\n" "Copyright (C) 1997-2005 Christian Bauer et al.\n" - "E-mail: Christian.Bauer@uni-mainz.de\n" - "http://www.uni-mainz.de/~bauec002/B2Main.html\n\n" - "Basilisk II comes with ABSOLUTELY NO\n" + "E-mail: cb@cebix.net\n" +#ifdef SHEEPSHAVER + "http://sheepshaver.cebix.net/\n\n" +#else + "http://basilisk.cebix.net/\n\n" +#endif + PROGRAM_NAME " comes with ABSOLUTELY NO\n" "WARRANTY. This is free software, and\n" "you are welcome to redistribute it\n" "under the terms of the GNU General\n" @@ -341,12 +450,12 @@ static void cb_about(...) // Menu item descriptions static GtkItemFactoryEntry menu_items[] = { {(gchar *)GetString(STR_PREFS_MENU_FILE_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), NULL, GTK_SIGNAL_FUNC(cb_start), 0, NULL}, + {(gchar *)GetString(STR_PREFS_ITEM_START_GTK), "S", GTK_SIGNAL_FUNC(cb_start), 0, NULL}, {(gchar *)GetString(STR_PREFS_ITEM_ZAP_PRAM_GTK), NULL, GTK_SIGNAL_FUNC(cb_zap_pram), 0, NULL}, {(gchar *)GetString(STR_PREFS_ITEM_SEPL_GTK), NULL, NULL, 0, ""}, {(gchar *)GetString(STR_PREFS_ITEM_QUIT_GTK), "Q", GTK_SIGNAL_FUNC(cb_quit), 0, NULL}, {(gchar *)GetString(STR_HELP_MENU_GTK), NULL, NULL, 0, ""}, - {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), NULL, GTK_SIGNAL_FUNC(cb_about), 0, NULL} + {(gchar *)GetString(STR_HELP_ITEM_ABOUT_GTK), "H", GTK_SIGNAL_FUNC(cb_about), 0, NULL} }; bool PrefsEditor(void) @@ -381,7 +490,7 @@ bool PrefsEditor(void) gtk_box_pack_start(GTK_BOX(box), notebook, TRUE, TRUE, 0); create_volumes_pane(notebook); - create_scsi_pane(notebook); +// create_scsi_pane(notebook); XXX not ready yet (merge scsi_windows.cpp from original B2/Win) create_graphics_pane(notebook); create_input_pane(notebook); create_serial_pane(notebook); @@ -391,8 +500,6 @@ bool PrefsEditor(void) static const opt_desc buttons[] = { {STR_START_BUTTON, GTK_SIGNAL_FUNC(cb_start)}, - {STR_PREFS_ITEM_ZAP_PRAM, GTK_SIGNAL_FUNC(cb_zap_pram)}, - {STR_ABOUT_BUTTON, GTK_SIGNAL_FUNC(cb_about)}, {STR_QUIT_BUTTON, GTK_SIGNAL_FUNC(cb_quit)}, {0, NULL} }; @@ -409,9 +516,19 @@ bool PrefsEditor(void) * "Volumes" pane */ +static GtkWidget *w_enableextfs, *w_extdrives, *w_cdrom_drive; static GtkWidget *volume_list; static int selected_volume; +// Set sensitivity of widgets +static void set_volumes_sensitive(void) +{ + const bool enable_extfs = PrefsFindBool("enableextfs"); + gtk_widget_set_sensitive(w_extdrives, enable_extfs); + const bool no_cdrom = PrefsFindBool("nocdrom"); + gtk_widget_set_sensitive(w_cdrom_drive, !no_cdrom); +} + // Volume in list selected static void cl_selected(GtkWidget *list, int row, int column) { @@ -433,13 +550,14 @@ static void create_volume_ok(GtkWidget * gchar *file = (gchar *)gtk_file_selection_get_filename(GTK_FILE_SELECTION(assoc->req)); const gchar *str = gtk_entry_get_text(GTK_ENTRY(assoc->entry)); - int size = atoi(str); + size_t size = atoi(str) << 20; - char cmd[1024]; - sprintf(cmd, "dd if=/dev/zero \"of=%s\" bs=1024k count=%d", file, size); - int ret = system(cmd); - if (ret == 0) + int fd = _open(file, _O_WRONLY | _O_CREAT | _O_BINARY | _O_TRUNC, _S_IREAD | _S_IWRITE); + if (fd >= 0) { + if (_chsize(fd, size) == 0) gtk_clist_append(GTK_CLIST(volume_list), &file); + _close(fd); + } gtk_widget_destroy(GTK_WIDGET(assoc->req)); delete assoc; } @@ -488,10 +606,39 @@ static void cb_remove_volume(...) static void mn_boot_any(...) {PrefsReplaceInt32("bootdriver", 0);} static void mn_boot_cdrom(...) {PrefsReplaceInt32("bootdriver", CDROMRefNum);} +// "Enable external file system" button toggled +static void tb_enableextfs(GtkWidget *widget) +{ + PrefsReplaceBool("enableextfs", GTK_TOGGLE_BUTTON(widget)->active); + set_volumes_sensitive(); +} + // "No CD-ROM Driver" button toggled static void tb_nocdrom(GtkWidget *widget) { PrefsReplaceBool("nocdrom", GTK_TOGGLE_BUTTON(widget)->active); + set_volumes_sensitive(); +} + +// Add names of CD-ROM devices +static GList *add_cdrom_names(void) +{ + GList *glist = NULL; + + char rootdir[4] = "X:\\"; + for (char letter = 'C'; letter <= 'Z'; letter++) { + rootdir[0] = letter; + if (GetDriveType(rootdir) == DRIVE_CDROM) + glist = g_list_append(glist, strdup(rootdir)); + } + + return glist; +} + +// "Enable polling" button toggled +static void tb_pollmedia(GtkWidget *widget) +{ + PrefsReplaceBool("pollmedia", GTK_TOGGLE_BUTTON(widget)->active); } // Read settings from widgets and set preferences @@ -505,6 +652,14 @@ static void read_volumes_settings(void) gtk_clist_get_text(GTK_CLIST(volume_list), i, 0, &str); PrefsAddString("disk", str); } + + const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_cdrom_drive)->entry)); + if (str && strlen(str)) + PrefsReplaceString("cdrom", str); + else + PrefsRemoveItem("cdrom"); + + PrefsReplaceString("extdrives", get_file_entry_path(w_extdrives)); } // Create "Volumes" pane @@ -553,6 +708,20 @@ static void create_volumes_pane(GtkWidge menu = make_option_menu(box, STR_BOOTDRIVER_CTRL, options, active); make_checkbox(box, STR_NOCDROM_CTRL, "nocdrom", GTK_SIGNAL_FUNC(tb_nocdrom)); + + GList *glist = add_cdrom_names(); + str = const_cast(PrefsFindString("cdrom")); + if (str == NULL) + str = ""; + w_cdrom_drive = make_combobox(box, STR_CDROM_DRIVE_CTRL, str, glist); + + make_checkbox(box, STR_POLLMEDIA_CTRL, "pollmedia", GTK_SIGNAL_FUNC(tb_pollmedia)); + + make_separator(box); + w_enableextfs = make_checkbox(box, STR_EXTFS_ENABLE_CTRL, "enableextfs", GTK_SIGNAL_FUNC(tb_enableextfs)); + w_extdrives = make_file_entry(box, STR_EXTFS_DRIVES_CTRL, "extdrives", true); + + set_volumes_sensitive(); } @@ -560,20 +729,24 @@ static void create_volumes_pane(GtkWidge * "JIT Compiler" pane */ +#ifndef SHEEPSHAVER static GtkWidget *w_jit_fpu; static GtkWidget *w_jit_atraps; static GtkWidget *w_jit_cache_size; static GtkWidget *w_jit_lazy_flush; static GtkWidget *w_jit_follow_const_jumps; +#endif // Set sensitivity of widgets static void set_jit_sensitive(void) { +#ifndef SHEEPSHAVER const bool jit_enabled = PrefsFindBool("jit"); gtk_widget_set_sensitive(w_jit_fpu, jit_enabled); gtk_widget_set_sensitive(w_jit_cache_size, jit_enabled); gtk_widget_set_sensitive(w_jit_lazy_flush, jit_enabled); gtk_widget_set_sensitive(w_jit_follow_const_jumps, jit_enabled); +#endif } // "Use JIT Compiler" button toggled @@ -584,22 +757,28 @@ static void tb_jit(GtkWidget *widget) } // "Compile FPU Instructions" button toggled +#ifndef SHEEPSHAVER static void tb_jit_fpu(GtkWidget *widget) { PrefsReplaceBool("jitfpu", GTK_TOGGLE_BUTTON(widget)->active); } +#endif // "Lazy translation cache invalidation" button toggled +#ifndef SHEEPSHAVER static void tb_jit_lazy_flush(GtkWidget *widget) { PrefsReplaceBool("jitlazyflush", GTK_TOGGLE_BUTTON(widget)->active); } +#endif // "Translate through constant jumps (inline blocks)" button toggled +#ifndef SHEEPSHAVER static void tb_jit_follow_const_jumps(GtkWidget *widget) { PrefsReplaceBool("jitinline", GTK_TOGGLE_BUTTON(widget)->active); } +#endif // Read settings from widgets and set preferences static void read_jit_settings(void) @@ -607,12 +786,22 @@ static void read_jit_settings(void) #if USE_JIT bool jit_enabled = PrefsFindBool("jit"); if (jit_enabled) { +#ifndef SHEEPSHAVER const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_jit_cache_size)->entry)); PrefsReplaceInt32("jitcachesize", atoi(str)); +#endif } #endif } +// "Use built-in 68k DR emulator" button toggled +#ifdef SHEEPSHAVER +static void tb_jit_68k(GtkWidget *widget) +{ + PrefsReplaceBool("jit68k", GTK_TOGGLE_BUTTON(widget)->active); +} +#endif + // Create "JIT Compiler" pane static void create_jit_pane(GtkWidget *top) { @@ -623,6 +812,7 @@ static void create_jit_pane(GtkWidget *t box = make_pane(top, STR_JIT_PANE_TITLE); make_checkbox(box, STR_JIT_CTRL, "jit", GTK_SIGNAL_FUNC(tb_jit)); +#ifndef SHEEPSHAVER w_jit_fpu = make_checkbox(box, STR_JIT_FPU_CTRL, "jitfpu", GTK_SIGNAL_FUNC(tb_jit_fpu)); // Translation cache size @@ -633,16 +823,22 @@ static void create_jit_pane(GtkWidget *t STR_JIT_CACHE_SIZE_16MB_LAB, 0 }; - w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, "jitcachesize", options); + sprintf(str, "%d", PrefsFindInt32("jitcachesize")); + w_jit_cache_size = make_combobox(box, STR_JIT_CACHE_SIZE_CTRL, str, options); // Lazy translation cache invalidation w_jit_lazy_flush = make_checkbox(box, STR_JIT_LAZY_CINV_CTRL, "jitlazyflush", GTK_SIGNAL_FUNC(tb_jit_lazy_flush)); // Follow constant jumps (inline basic blocks) w_jit_follow_const_jumps = make_checkbox(box, STR_JIT_FOLLOW_CONST_JUMPS, "jitinline", GTK_SIGNAL_FUNC(tb_jit_follow_const_jumps)); +#endif set_jit_sensitive(); #endif + +#ifdef SHEEPSHAVER + make_checkbox(box, STR_JIT_68K_CTRL, "jit68k", GTK_SIGNAL_FUNC(tb_jit_68k)); +#endif } /* @@ -654,6 +850,7 @@ static GtkWidget *w_scsi[7]; // Read settings from widgets and set preferences static void read_scsi_settings(void) { +#ifndef DISABLE_SCSI for (int id=0; id<7; id++) { char prefs_name[32]; sprintf(prefs_name, "scsi%d", id); @@ -663,11 +860,13 @@ static void read_scsi_settings(void) else PrefsRemoveItem(prefs_name); } +#endif } // Create "SCSI" pane static void create_scsi_pane(GtkWidget *top) { +#ifndef DISABLE_SCSI GtkWidget *box; box = make_pane(top, STR_SCSI_PANE_TITLE); @@ -677,6 +876,7 @@ static void create_scsi_pane(GtkWidget * sprintf(prefs_name, "scsi%d", id); w_scsi[id] = make_file_entry(box, STR_SCSI_ID_0 + id, prefs_name); } +#endif } @@ -720,6 +920,7 @@ static void mn_fullscreen(...) { display_type = DISPLAY_SCREEN; hide_show_graphics_widgets(); + PrefsReplaceInt32("frameskip", 1); } // "5 Hz".."60Hz" selected @@ -731,6 +932,14 @@ static void mn_30hz(...) {PrefsReplaceIn static void mn_60hz(...) {PrefsReplaceInt32("frameskip", 1);} static void mn_dynamic(...) {PrefsReplaceInt32("frameskip", 0);} +// QuickDraw acceleration +#ifdef SHEEPSHAVER +static void tb_gfxaccel(GtkWidget *widget) +{ + PrefsReplaceBool("gfxaccel", GTK_TOGGLE_BUTTON(widget)->active); +} +#endif + // Set sensitivity of widgets static void set_graphics_sensitive(void) { @@ -748,8 +957,13 @@ static void tb_nosound(GtkWidget *widget static void parse_graphics_prefs(void) { display_type = DISPLAY_WINDOW; +#ifdef SHEEPSHAVER + dis_width = 640; + dis_height = 480; +#else dis_width = 512; dis_height = 384; +#endif const char *str = PrefsFindString("screen"); if (str) { @@ -889,6 +1103,10 @@ static void create_graphics_pane(GtkWidg gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)GTK_FILL, (GtkAttachOptions)0, 4, 4); w_display_y = GTK_COMBO(combo)->entry; +#ifdef SHEEPSHAVER + make_checkbox(box, STR_GFXACCEL_CTRL, "gfxaccel", GTK_SIGNAL_FUNC(tb_gfxaccel)); +#endif + make_separator(box); make_checkbox(box, STR_NOSOUND_CTRL, "nosound", GTK_SIGNAL_FUNC(tb_nosound)); @@ -908,7 +1126,9 @@ static GtkWidget *w_mouse_wheel_lines; // Set sensitivity of widgets static void set_input_sensitive(void) { - gtk_widget_set_sensitive(w_keycode_file, PrefsFindBool("keycodes")); + const bool use_keycodes = PrefsFindBool("keycodes"); + gtk_widget_set_sensitive(w_keycode_file, use_keycodes); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_keycode_file), "chooser_button")), use_keycodes); gtk_widget_set_sensitive(w_mouse_wheel_lines, PrefsFindInt32("mousewheelmode") == 1); } @@ -938,13 +1158,33 @@ static void read_input_settings(void) // Create "Input" pane static void create_input_pane(GtkWidget *top) { - GtkWidget *box, *hbox, *menu, *label; + GtkWidget *box, *hbox, *menu, *label, *button; GtkObject *adj; box = make_pane(top, STR_INPUT_PANE_TITLE); make_checkbox(box, STR_KEYCODES_CTRL, "keycodes", GTK_SIGNAL_FUNC(tb_keycodes)); - w_keycode_file = make_file_entry(box, STR_KEYCODE_FILE_CTRL, "keycodefile"); + + hbox = gtk_hbox_new(FALSE, 4); + gtk_widget_show(hbox); + gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); + + label = gtk_label_new(GetString(STR_KEYCODES_CTRL)); + gtk_widget_show(label); + gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); + + const char *str = PrefsFindString("keycodefile"); + if (str == NULL) + str = ""; + + w_keycode_file = gtk_entry_new(); + gtk_entry_set_text(GTK_ENTRY(w_keycode_file), str); + gtk_widget_show(w_keycode_file); + gtk_box_pack_start(GTK_BOX(hbox), w_keycode_file, TRUE, TRUE, 0); + + button = make_browse_button(w_keycode_file); + gtk_box_pack_start(GTK_BOX(hbox), button, FALSE, FALSE, 0); + g_object_set_data(G_OBJECT(w_keycode_file), "chooser_button", button); make_separator(box); @@ -978,11 +1218,11 @@ static void create_input_pane(GtkWidget /* - * "Ports" pane + * "Serial" pane */ -static GtkWidget *w_seriala, *w_portfile0, *w_portfile0_browse; -static GtkWidget *w_serialb, *w_portfile1, *w_portfile1_browse; +static GtkWidget *w_seriala, *w_portfile0; +static GtkWidget *w_serialb, *w_portfile1; // Set sensitivity of widgets static void set_serial_sensitive(void) @@ -993,12 +1233,12 @@ static void set_serial_sensitive(void) str = gtk_entry_get_text(GTK_ENTRY(w_seriala)); is_file = strcmp(str, "FILE") == 0; gtk_widget_set_sensitive(w_portfile0, is_file); - gtk_widget_set_sensitive(w_portfile0_browse, is_file); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile0), "chooser_button")), is_file); str = gtk_entry_get_text(GTK_ENTRY(w_serialb)); is_file = strcmp(str, "FILE") == 0; gtk_widget_set_sensitive(w_portfile1, is_file); - gtk_widget_set_sensitive(w_portfile1_browse, is_file); + gtk_widget_set_sensitive(GTK_WIDGET(g_object_get_data(G_OBJECT(w_portfile1), "chooser_button")), is_file); } // Read settings from widgets and set preferences @@ -1022,7 +1262,6 @@ static void read_serial_settings(void) // Port changed in combo static void cb_serial_port_changed(...) { - printf("serial port changed\n"); set_serial_sensitive(); } @@ -1044,7 +1283,7 @@ static GList *add_serial_names(void) return glist; } -// Create "Ports" pane +// Create "Serial" pane static void create_serial_pane(GtkWidget *top) { GtkWidget *box, *hbox, *table, *label, *combo, *sep, *entry; @@ -1053,78 +1292,24 @@ static void create_serial_pane(GtkWidget box = make_pane(top, STR_SERIAL_PANE_TITLE); table = make_table(box, 2, 5); - label = gtk_label_new(GetString(STR_SERIALA_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 0, 1, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - GList *glist = add_serial_names(); - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); const char *str = PrefsFindString("seriala"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + combo = table_make_combobox(table, 0, STR_SERIALA_CTRL, str, glist); w_seriala = GTK_COMBO(combo)->entry; gtk_signal_connect(GTK_OBJECT(w_seriala), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL); - label = gtk_label_new(GetString(STR_FILE_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 1, 2, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - w_portfile0 = gtk_entry_new(); - str = PrefsFindString("portfile0"); - if (str == NULL) - str = "C:\\B2TEMP0.OUT"; - gtk_entry_set_text(GTK_ENTRY(w_portfile0), str); - gtk_widget_show(w_portfile0); - gtk_box_pack_start(GTK_BOX(hbox), w_portfile0, TRUE, TRUE, 0); - - w_portfile0_browse = make_browse_button(w_portfile0); - gtk_box_pack_start(GTK_BOX(hbox), w_portfile0_browse, FALSE, FALSE, 0); + w_portfile0 = table_make_file_entry(table, 1, STR_FILE_CTRL, "portfile0"); sep = gtk_hseparator_new(); gtk_widget_show(sep); gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - label = gtk_label_new(GetString(STR_SERIALB_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - combo = gtk_combo_new(); - gtk_widget_show(combo); - gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); str = PrefsFindString("serialb"); - if (str == NULL) - str = ""; - gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); - gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + combo = table_make_combobox(table, 3, STR_SERIALB_CTRL, str, glist); w_serialb = GTK_COMBO(combo)->entry; gtk_signal_connect(GTK_OBJECT(w_serialb), "changed", GTK_SIGNAL_FUNC(cb_serial_port_changed), NULL); - label = gtk_label_new(GetString(STR_FILE_CTRL)); - gtk_widget_show(label); - gtk_table_attach(GTK_TABLE(table), label, 0, 1, 4, 5, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); - - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - gtk_table_attach(GTK_TABLE(table), hbox, 1, 2, 4, 5, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); - - w_portfile1 = gtk_entry_new(); - str = PrefsFindString("portfile1"); - if (str == NULL) - str = "C:\\B2TEMP1.OUT"; - gtk_entry_set_text(GTK_ENTRY(w_portfile1), str); - gtk_widget_show(w_portfile1); - gtk_box_pack_start(GTK_BOX(hbox), w_portfile1, TRUE, TRUE, 0); - - w_portfile1_browse = make_browse_button(w_portfile1); - gtk_box_pack_start(GTK_BOX(hbox), w_portfile1_browse, FALSE, FALSE, 0); + w_portfile1 = table_make_file_entry(table, 4, STR_FILE_CTRL, "portfile1"); set_serial_sensitive(); } @@ -1134,39 +1319,80 @@ static void create_serial_pane(GtkWidget * "Ethernet" pane */ -static GtkWidget *w_ether, *w_udp_port; +static GtkWidget *w_ether; +static GtkWidget *w_ftp_port_list, *w_tcp_port_list; +static const char s_nat_router[] = "NAT/Router module"; +static const char s_ndis_tag[] = "NDIS "; // Set sensitivity of widgets static void set_ethernet_sensitive(void) { + const char *str = gtk_entry_get_text(GTK_ENTRY(w_ether)); + + bool is_nat_router = strcmp(str, s_nat_router) == 0; + gtk_widget_set_sensitive(w_ftp_port_list, is_nat_router); + gtk_widget_set_sensitive(w_tcp_port_list, is_nat_router); } // Read settings from widgets and set preferences static void read_ethernet_settings(void) { const char *str = gtk_entry_get_text(GTK_ENTRY(w_ether)); - if (str && strlen(str)) - PrefsReplaceString("ether", str); + if (str && strlen(str) > sizeof(s_ndis_tag) && strncmp(str, s_ndis_tag, sizeof(s_ndis_tag) - 1) == 0) + PrefsReplaceString("ether", &str[sizeof(s_ndis_tag) - 1]); else PrefsRemoveItem("ether"); + + const bool router_enabled = str && strcmp(str, s_nat_router) == 0; + PrefsReplaceBool("routerenabled", router_enabled); + if (router_enabled) { + str = gtk_entry_get_text(GTK_ENTRY(w_ftp_port_list)); + PrefsReplaceString("ftp_port_list", str); + str = gtk_entry_get_text(GTK_ENTRY(w_tcp_port_list)); + PrefsReplaceString("tcp_port", str); + } +} + +// Ethernet emulation type changed in menulist +static void cb_ether_changed(...) +{ + set_ethernet_sensitive(); } // Add names of ethernet interfaces +// XXX use radio buttons instead (None/NDIS/NAT) static GList *add_ether_names(void) { GList *glist = NULL; - // TODO: Get list of all Ethernet interfaces -#ifdef HAVE_SLIRP - static char s_slirp[] = "slirp"; - glist = g_list_append(glist, s_slirp); -#endif -#if 0 - if (glist) - g_list_sort(glist, gl_str_cmp); - else -#endif - glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB)); + glist = g_list_append(glist, (void *)GetString(STR_NONE_LAB)); + glist = g_list_append(glist, (void *)s_nat_router); + + { // Get NDIS ethernet adapters (XXX handle "ethermulticastmode") + PacketOpenAdapter("", 0); + { + ULONG sz; + char names[1024]; + sz = sizeof(names); + if (PacketGetAdapterNames(NULL, names, &sz) == ERROR_SUCCESS) { + char *p = names; + while (*p) { + const char DEVICE_HEADER[] = "\\Device\\B2ether_"; + if (strnicmp(p, DEVICE_HEADER, sizeof(DEVICE_HEADER) - 1) == 0) { + LPADAPTER fd = PacketOpenAdapter(p + sizeof(DEVICE_HEADER) - 1, 0); + if (fd) { + char str[256]; + sprintf(str, "%s%s", s_ndis_tag, p + sizeof(DEVICE_HEADER) - 1); + glist = g_list_append(glist, strdup(str)); + PacketCloseAdapter(fd); + } + } + p += strlen(p) + 1; + } + } + } + PacketCloseAdapter(NULL); + } return glist; } @@ -1188,11 +1414,51 @@ static void create_ethernet_pane(GtkWidg gtk_widget_show(combo); gtk_combo_set_popdown_strings(GTK_COMBO(combo), glist); const char *str = PrefsFindString("ether"); - if (str == NULL) - str = ""; + if (str == NULL || str[0] == '\0') { + if (PrefsFindBool("routerenabled")) + str = s_nat_router; + else + str = GetString(STR_NONE_LAB); + } + else if (str[0] == '{') { + static char s_device[256]; + sprintf(s_device, "%s%s", s_ndis_tag, str); + str = s_device; + } gtk_entry_set_text(GTK_ENTRY(GTK_COMBO(combo)->entry), str); gtk_table_attach(GTK_TABLE(table), combo, 1, 2, 0, 1, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); w_ether = GTK_COMBO(combo)->entry; + gtk_signal_connect(GTK_OBJECT(w_ether), "changed", GTK_SIGNAL_FUNC(cb_ether_changed), NULL); + + sep = gtk_hseparator_new(); + gtk_widget_show(sep); + gtk_table_attach(GTK_TABLE(table), sep, 0, 2, 1, 2, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + label = gtk_label_new(GetString(STR_ETHER_FTP_PORT_LIST_CTRL)); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 2, 3, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + entry = gtk_entry_new(); + str = PrefsFindString("ftp_port_list"); + if (str == NULL) + str = ""; + gtk_entry_set_text(GTK_ENTRY(entry), str); + gtk_widget_show(entry); + gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 2, 3, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + w_ftp_port_list = entry; + + label = gtk_label_new(GetString(STR_ETHER_TCP_PORT_LIST_CTRL)); + gtk_widget_show(label); + gtk_table_attach(GTK_TABLE(table), label, 0, 1, 3, 4, (GtkAttachOptions)0, (GtkAttachOptions)0, 4, 4); + + entry = gtk_entry_new(); + str = PrefsFindString("tcp_port"); + if (str == NULL) + str = ""; + gtk_entry_set_text(GTK_ENTRY(entry), str); + gtk_widget_show(entry); + gtk_table_attach(GTK_TABLE(table), entry, 1, 2, 3, 4, (GtkAttachOptions)(GTK_FILL | GTK_EXPAND), (GtkAttachOptions)0, 4, 4); + w_tcp_port_list = entry; set_ethernet_sensitive(); } @@ -1202,9 +1468,17 @@ static void create_ethernet_pane(GtkWidg * "Memory/Misc" pane */ -static GtkObject *w_ramsize_adj; +static GtkWidget *w_ramsize; static GtkWidget *w_rom_file; +// Don't use CPU when idle? +#ifdef SHEEPSHAVER +static void tb_idlewait(GtkWidget *widget) +{ + PrefsReplaceBool("idlewait", GTK_TOGGLE_BUTTON(widget)->active); +} +#endif + // "Ignore SEGV" button toggled #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION static void tb_ignoresegv(GtkWidget *widget) @@ -1227,9 +1501,10 @@ static void mn_cpu_68040(...) {PrefsRepl // Read settings from widgets and set preferences static void read_memory_settings(void) { - PrefsReplaceInt32("ramsize", int(GTK_ADJUSTMENT(w_ramsize_adj)->value) << 20); + const char *str = gtk_entry_get_text(GTK_ENTRY(GTK_COMBO(w_ramsize)->entry)); + PrefsReplaceInt32("ramsize", atoi(str) << 20); - const char *str = get_file_entry_path(w_rom_file); + str = get_file_entry_path(w_rom_file); if (str && strlen(str)) PrefsReplaceString("rom", str); else @@ -1240,48 +1515,33 @@ static void read_memory_settings(void) // Create "Memory/Misc" pane static void create_memory_pane(GtkWidget *top) { - GtkWidget *box, *hbox, *vbox, *hbox2, *label, *scale; + GtkWidget *box, *hbox, *table, *label, *scale, *menu; box = make_pane(top, STR_MEMORY_MISC_PANE_TITLE); + table = make_table(box, 2, 5); - hbox = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox); - - label = gtk_label_new(GetString(STR_RAMSIZE_SLIDER)); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox), label, FALSE, FALSE, 0); - - vbox = gtk_vbox_new(FALSE, 4); - gtk_widget_show(vbox); - - gfloat min, max; - min = 1; - max = 1024; - w_ramsize_adj = gtk_adjustment_new(min, min, max, 1, 16, 0); - gtk_adjustment_set_value(GTK_ADJUSTMENT(w_ramsize_adj), PrefsFindInt32("ramsize") >> 20); - - scale = gtk_hscale_new(GTK_ADJUSTMENT(w_ramsize_adj)); - gtk_widget_show(scale); - gtk_scale_set_digits(GTK_SCALE(scale), 0); - gtk_box_pack_start(GTK_BOX(vbox), scale, TRUE, TRUE, 0); - - hbox2 = gtk_hbox_new(FALSE, 4); - gtk_widget_show(hbox2); - - char val[32]; - sprintf(val, GetString(STR_RAMSIZE_FMT), int(min)); - label = gtk_label_new(val); - gtk_widget_show(label); - gtk_box_pack_start(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - - sprintf(val, GetString(STR_RAMSIZE_FMT), int(max)); - label = gtk_label_new(val); - gtk_widget_show(label); - gtk_box_pack_end(GTK_BOX(hbox2), label, FALSE, FALSE, 0); - gtk_box_pack_start(GTK_BOX(vbox), hbox2, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(hbox), vbox, TRUE, TRUE, 0); - gtk_box_pack_start(GTK_BOX(box), hbox, FALSE, FALSE, 0); + static const combo_desc options[] = { +#ifndef SHEEPSHAVER + STR_RAMSIZE_2MB_LAB, +#endif + STR_RAMSIZE_4MB_LAB, + STR_RAMSIZE_8MB_LAB, + STR_RAMSIZE_16MB_LAB, + STR_RAMSIZE_32MB_LAB, + STR_RAMSIZE_64MB_LAB, + STR_RAMSIZE_128MB_LAB, + STR_RAMSIZE_256MB_LAB, + STR_RAMSIZE_512MB_LAB, +#ifndef SHEEPSHAVER + STR_RAMSIZE_1024MB_LAB, +#endif + 0 + }; + char default_ramsize[10]; + sprintf(default_ramsize, "%d", PrefsFindInt32("ramsize") >> 20); + w_ramsize = table_make_combobox(table, 0, STR_RAMSIZE_CTRL, default_ramsize, options); +#ifndef SHEEPSHAVER static const opt_desc model_options[] = { {STR_MODELID_5_LAB, GTK_SIGNAL_FUNC(mn_modelid_5)}, {STR_MODELID_14_LAB, GTK_SIGNAL_FUNC(mn_modelid_14)}, @@ -1292,7 +1552,8 @@ static void create_memory_pane(GtkWidget case 5: active = 0; break; case 14: active = 1; break; } - make_option_menu(box, STR_MODELID_CTRL, model_options, active); + table_make_option_menu(table, 2, STR_MODELID_CTRL, model_options, active); +#endif #if EMULATED_68K static const opt_desc cpu_options[] = { @@ -1311,14 +1572,18 @@ static void create_memory_pane(GtkWidget case 3: active = fpu ? 3 : 2; break; case 4: active = 4; } - make_option_menu(box, STR_CPU_CTRL, cpu_options, active); + table_make_option_menu(table, 3, STR_CPU_CTRL, cpu_options, active); #endif - w_rom_file = make_file_entry(box, STR_ROM_FILE_CTRL, "rom"); + w_rom_file = table_make_file_entry(table, 4, STR_ROM_FILE_CTRL, "rom"); #ifdef HAVE_SIGSEGV_SKIP_INSTRUCTION make_checkbox(box, STR_IGNORESEGV_CTRL, "ignoresegv", GTK_SIGNAL_FUNC(tb_ignoresegv)); #endif + +#ifdef SHEEPSHAVER + make_checkbox(box, STR_IDLEWAIT_CTRL, "idlewait", GTK_SIGNAL_FUNC(tb_idlewait)); +#endif } @@ -1347,6 +1612,8 @@ uint8 XPRAM[XPRAM_SIZE]; void MountVolume(void *fh) { } void FileDiskLayout(loff_t size, uint8 *data, loff_t &start_byte, loff_t &real_size) { } void WarningAlert(const char *text) { } +void recycle_write_packet(LPPACKET) { } +VOID CALLBACK packet_read_completion(DWORD, DWORD, LPOVERLAPPED) { } /* @@ -1361,6 +1628,21 @@ void SysAddSerialPrefs(void) /* + * Display alerts + */ + +static void display_alert(int title_id, const char *text, int flags) +{ + MessageBox(NULL, text, GetString(title_id), MB_OK | flags); +} + +static void ErrorAlert(const char *text) +{ + display_alert(STR_ERROR_ALERT_TITLE, text, MB_ICONSTOP); +} + + +/* * Start standalone GUI */ @@ -1379,9 +1661,27 @@ int main(int argc, char *argv[]) // Exit preferences PrefsExit(); - // Transfer control to the Basilisk II executable + // Transfer control to the executable if (start) { - printf("Start Basilisk II\n"); + char path[_MAX_PATH]; + bool ok = GetModuleFileName(NULL, path, sizeof(path)) != 0; + if (ok) { + char b2_path[_MAX_PATH]; + char *p = strrchr(path, '\\'); + *++p = '\0'; + SetCurrentDirectory(path); + strcpy(b2_path, path); + strcat(b2_path, PROGRAM_NAME); + strcat(b2_path, ".exe"); + HINSTANCE h = ShellExecute(GetDesktopWindow(), "open", + b2_path, "", path, SW_SHOWNORMAL); + if ((int)h <= 32) + ok = false; + } + if (!ok) { + ErrorAlert("Coult not start " PROGRAM_NAME " executable"); + return 1; + } } return 0;