1 /** \file   settings_io.c
2  * \brief   I/O extension settings that don't go/fit into subwidgets
3  *
4  * \author  Bas Wassink <b.wassink@ziggo.nl>
5  */
6 
7 /*
8  * $VICERES IOCollisionHandling -vsid
9  * $VICERES CartridgeReset      -vsid
10  * $VICERES HummerADC           x64dtv
11  */
12 
13 /*
14  * This file is part of VICE, the Versatile Commodore Emulator.
15  * See README for copyright notice.
16  *
17  *  This program is free software; you can redistribute it and/or modify
18  *  it under the terms of the GNU General Public License as published by
19  *  the Free Software Foundation; either version 2 of the License, or
20  *  (at your option) any later version.
21  *
22  *  This program is distributed in the hope that it will be useful,
23  *  but WITHOUT ANY WARRANTY; without even the implied warranty of
24  *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
25  *  GNU General Public License for more details.
26  *
27  *  You should have received a copy of the GNU General Public License
28  *  along with this program; if not, write to the Free Software
29  *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA
30  *  02111-1307  USA.
31  *
32  */
33 
34 #include "vice.h"
35 #include <gtk/gtk.h>
36 
37 #include "machine.h"
38 #include "resources.h"
39 #include "debug_gtk3.h"
40 #include "basewidgets.h"
41 #include "widgethelpers.h"
42 #include "basedialogs.h"
43 #include "cartio.h"
44 #include "cartridge.h"
45 #include "resourcewidgetmanager.h"
46 #include "uisettings.h"
47 
48 #include "settings_io.h"
49 
50 
51 /** \brief  Methods of handling I/O collisions
52  */
53 static const vice_gtk3_radiogroup_entry_t io_collision_methods[] = {
54     { "Detach all",     IO_COLLISION_METHOD_DETACH_ALL },
55     { "Detach last",    IO_COLLISION_METHOD_DETACH_LAST },
56     { "AND values",     IO_COLLISION_METHOD_AND_WIRES },
57     { NULL, -1 }
58 };
59 
60 
61 /** \brief  Resource widget manager instance
62  */
63 static resource_widget_manager_t manager;
64 
65 
66 /** \brief  Handler for the "destroy" event of the main widget
67  *
68  * \param[in]   widget  main widget (unused)
69  * \param[in]   data    extra even data (unused)
70  */
on_settings_io_destroy(GtkWidget * widget,gpointer data)71 static void on_settings_io_destroy(GtkWidget *widget, gpointer data)
72 {
73     debug_gtk3("calling vice_resource_widget_manager_exit()");
74     vice_resource_widget_manager_exit(&manager);
75 }
76 
77 
78 /** \brief  Create widget to specify I/O collision handling method
79  *
80  * The \a desc is added as a label under the "I/O collision handling" label,
81  * in italics and surrounded with parenthesis.
82  *
83  * \param[in]   desc    description of the I/O areas involved
84  *
85  * \return  GtkGrid
86  */
create_collision_widget(const char * desc)87 static GtkWidget *create_collision_widget(const char *desc)
88 {
89     GtkWidget *grid;
90     GtkWidget *label;
91     GtkWidget *group;
92     char buffer[256];
93 
94     grid = gtk_grid_new();
95     gtk_grid_set_column_spacing(GTK_GRID(grid), 16);
96     gtk_grid_set_row_spacing(GTK_GRID(grid), 0);
97 
98     label = gtk_label_new("I/O collision handling");
99     gtk_widget_set_halign(label, GTK_ALIGN_START);
100     g_object_set(label, "margin-left", 16, NULL);
101     gtk_grid_attach(GTK_GRID(grid), label, 0, 0, 1, 1);
102 
103     group = vice_gtk3_resource_radiogroup_new("IOCollisionHandling",
104             io_collision_methods, GTK_ORIENTATION_HORIZONTAL);
105     gtk_grid_set_column_spacing(GTK_GRID(group), 16);
106     gtk_grid_attach(GTK_GRID(grid), group, 1, 0, 1, 1);
107     vice_resource_widget_manager_add_widget(&manager, group, NULL,
108             NULL, NULL, NULL);
109 
110     label = gtk_label_new(NULL);
111     g_snprintf(buffer, 256, "<i>(%s)</i>", desc);
112     gtk_label_set_markup(GTK_LABEL(label), buffer);
113 
114     gtk_widget_set_halign(label, GTK_ALIGN_START);
115     g_object_set(label, "margin-left", 16, NULL);
116     gtk_grid_attach(GTK_GRID(grid), label, 0, 1, 1, 1);
117 
118 
119     gtk_widget_show_all(grid);
120     return grid;
121 }
122 
123 
124 /** \brief  Create check button for "reset-on-cart-change"
125  *
126  * \return  GtkCheckButton
127  */
create_cart_reset_widget(void)128 static GtkWidget *create_cart_reset_widget(void)
129 {
130     GtkWidget *check;
131 
132     check = vice_gtk3_resource_check_button_new("CartridgeReset",
133             "Reset machine on cartridge change");
134     g_object_set(check, "margin-left", 16, NULL);
135     vice_resource_widget_manager_add_widget(&manager, check, NULL,
136             NULL, NULL, NULL);
137     return check;
138 }
139 
140 
141 /** \brief  Create layout for x64/x64sc
142  *
143  * \param[in,out]   grid    grid to add widgets to
144  */
create_c64_layout(GtkWidget * grid)145 static void create_c64_layout(GtkWidget *grid)
146 {
147     GtkWidget *collision_widget;
148 
149     collision_widget = create_collision_widget("$D000-$DFFF");
150     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
151     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
152 }
153 
154 
155 /** \brief  Create layout for xscpu64
156  *
157  * \param[in,out]   grid    grid to add widgets to
158  */
create_scpu64_layout(GtkWidget * grid)159 static void create_scpu64_layout(GtkWidget *grid)
160 {
161     GtkWidget *collision_widget;
162 
163     collision_widget = create_collision_widget("$D000-$DFFF");
164     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
165     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
166 }
167 
168 
169 /** \brief  Create layout for x128
170  *
171  * \param[in,out]   grid    grid to add widgets to
172  */
create_c128_layout(GtkWidget * grid)173 static void create_c128_layout(GtkWidget *grid)
174 {
175     GtkWidget *collision_widget;
176 
177     collision_widget = create_collision_widget("$D000-$DFFF");
178     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
179     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
180 }
181 
182 
183 
184 /** \brief  Create layout for x64dtv
185  *
186  * \param[in,out]   grid    grid to add widgets to
187  */
create_c64dtv_layout(GtkWidget * grid)188 static void create_c64dtv_layout(GtkWidget *grid)
189 {
190     GtkWidget *hummer;
191 
192     hummer = vice_gtk3_resource_check_button_new("HummerADC",
193             "Enable Hummer ADC");
194     g_object_set(hummer, "margin-left", 16, NULL);
195     gtk_grid_attach(GTK_GRID(grid), hummer, 0, 1, 3, 1);
196     vice_resource_widget_manager_add_widget(&manager, hummer, NULL,
197             NULL, NULL, NULL);
198 }
199 
200 
201 /** \brief  Create layout for xvic
202  *
203  * \param[in,out]   grid    grid to add widgets to
204  */
create_vic20_layout(GtkWidget * grid)205 static void create_vic20_layout(GtkWidget *grid)
206 {
207     GtkWidget *collision_widget;
208 
209     collision_widget = create_collision_widget("$9000-$93FF, $9800-$9FFF");
210     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
211     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
212 }
213 
214 
215 /** \brief  Create layout for xplus4
216  *
217  * \param[in,out]   grid    grid to add widgets to
218  */
create_plus4_layout(GtkWidget * grid)219 static void create_plus4_layout(GtkWidget *grid)
220 {
221     GtkWidget *collision_widget;
222 
223     collision_widget = create_collision_widget("$FD00-$FEFF");
224     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
225     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
226 }
227 
228 
229 
230 /** \brief  Create layout for xpet
231  *
232  * \param[in,out]   grid    grid to add widgets to
233  */
create_pet_layout(GtkWidget * grid)234 static void create_pet_layout(GtkWidget *grid)
235 {
236     GtkWidget *collision_widget;
237 
238     collision_widget = create_collision_widget("$8800-$8FFF, $E900-$EEFF");
239     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
240 }
241 
242 
243 /** \brief  Create layout for xcbm5x0/xcbm2
244  *
245  * \param[in,out]   grid    grid to add widgets to
246  */
create_cbm5x0_layout(GtkWidget * grid)247 static void create_cbm5x0_layout(GtkWidget *grid)
248 {
249     GtkWidget *collision_widget;
250 
251     collision_widget = create_collision_widget("$D800-$DFFF");
252     gtk_grid_attach(GTK_GRID(grid), collision_widget, 0, 1, 3, 1);
253     gtk_grid_attach(GTK_GRID(grid), create_cart_reset_widget(), 0, 2, 3, 1);
254 }
255 
256 
257 
258 /** \brief  Create widget for generic I/O extension settings
259  *
260  * Creates a widget for generic I/O extension settings and settings that don't
261  * make sense to create a separate widget for (ie stuff that has a single
262  * bool resource or a single "open file" dialog").
263  *
264  * \param[in]   parent  parent widget
265  *
266  * \return GtkGrid
267  */
settings_io_widget_create(GtkWidget * parent)268 GtkWidget *settings_io_widget_create(GtkWidget *parent)
269 {
270     GtkWidget *grid;
271 
272     /*
273      * Initialize and register resource widget manager. The various widgets
274      * register themselves in the create_bla() calls.
275      */
276     vice_resource_widget_manager_init(&manager);
277     ui_settings_set_resource_widget_manager(&manager);
278 
279     grid = uihelpers_create_grid_with_label(
280             "Generic I/O extension settings", 3);
281     gtk_grid_set_row_spacing(GTK_GRID(grid), 16);
282 
283     switch (machine_class) {
284 
285         case VICE_MACHINE_C64:      /* fall through */
286         case VICE_MACHINE_C64SC:
287             create_c64_layout(grid);
288             break;
289 
290         case VICE_MACHINE_SCPU64:
291             create_scpu64_layout(grid);
292             break;
293 
294         case VICE_MACHINE_C128:
295             create_c128_layout(grid);
296             break;
297 
298         case VICE_MACHINE_C64DTV:
299             create_c64dtv_layout(grid);
300             break;
301 
302         case VICE_MACHINE_VIC20:
303             create_vic20_layout(grid);
304             break;
305 
306         case VICE_MACHINE_PLUS4:
307             create_plus4_layout(grid);
308             break;
309 
310         case VICE_MACHINE_PET:
311             create_pet_layout(grid);
312             break;
313 
314         case VICE_MACHINE_CBM5x0:       /* fall through */
315         case VICE_MACHINE_CBM6x0:
316             create_cbm5x0_layout(grid);
317             break;
318 
319         default:
320             /* NOP */
321             break;
322     }
323 
324     g_signal_connect(grid, "destroy", G_CALLBACK(on_settings_io_destroy),
325             NULL);
326 
327     vice_resource_widget_manager_dump(&manager);
328 
329     gtk_widget_show_all(grid);
330     return grid;
331 }
332