1 /*
2 * ui_x.c
3 *
4 * user interface for the X Window System.
5 */
6
7 /* $Id: ui_x.c,v 1.31 2000/08/22 01:28:59 nyef Exp $ */
8
9 #include <X11/Intrinsic.h>
10 #include <X11/Shell.h>
11 #include <X11/StringDefs.h>
12 #include <X11/Xaw/Box.h>
13 #include <X11/Xaw/MenuButton.h>
14 #include <X11/Xaw/SimpleMenu.h>
15 #include <X11/Xaw/SmeBSB.h>
16
17 #include <stdio.h>
18 #include <stdarg.h>
19 #include "ui.h"
20 #include "system.h"
21 #include "video.h"
22 #include "tool.h"
23 #include "menu.h"
24
25 #define APPLICATION_NAME "darcnes"
26 #define APPLICATION_CLASS "DarcNES"
27
28 /* Overhead for Xt and main window */
29 XtAppContext context;
30 Widget toplevel;
31 Widget manager;
32
33 /* Menus */
34 Widget menubar;
35 Widget menubutton_file;
36 Widget menu_file;
37 Widget menu_file_exit;
38
39 /* the drawing area */
40 Widget drawbox;
41
42 /* the shutdown callback */
43 shutdown_t dn_shutdown;
44
45 /* miscellany */
46 void do_file_exit(Widget, XtPointer, XtPointer);
47 Boolean emulation_timeslice(XtPointer);
48
menu_callback(Widget widget,XtPointer menu,XtPointer call_data)49 void menu_callback(Widget widget, XtPointer menu, XtPointer call_data)
50 {
51 struct ui_menu *item;
52
53 item = (struct ui_menu *) menu;
54 item->callback(item->callback_data);
55 }
56
menu_init(struct ui_menu * menu)57 void menu_init(struct ui_menu *menu)
58 {
59 Widget menubutton;
60 Widget themenu;
61 Widget menuitem;
62 int i;
63
64 menubutton = XtCreateManagedWidget(menu[0].name, menuButtonWidgetClass, menubar, NULL, 0);
65 themenu = XtCreatePopupShell("drivermenu", simpleMenuWidgetClass, menubutton, NULL, 0);
66 XtVaSetValues(menubutton, XtNmenuName, "drivermenu", NULL);
67
68 for (i = 1; menu[i].name; i++) {
69 if (menu[i].flags & MF_CHILD) {
70 /* don't create child menus */
71 continue;
72 }
73 menuitem = XtCreateManagedWidget(menu[i].name, smeBSBObjectClass, themenu, NULL, 0);
74 XtAddCallback(menuitem, XtNcallback, menu_callback, &menu[i]);
75 menu[i].ui_data = menuitem;
76 }
77 }
78
menu_rename_item(struct ui_menu * item)79 void menu_rename_item(struct ui_menu *item)
80 {
81 Widget item_widget;
82
83 item_widget = item->ui_data;
84 XtVaSetValues(item_widget, XtNlabel, item->name, NULL);
85 }
86
menu_disable_item(struct ui_menu * item)87 void menu_disable_item(struct ui_menu *item)
88 {
89 /* dummy implementation */
90 }
91
menu_enable_item(struct ui_menu * item)92 void menu_enable_item(struct ui_menu *item)
93 {
94 /* dummy implementation */
95 }
96
init_menus(void)97 void init_menus(void)
98 {
99 /* the menubar */
100 menubar = XtVaCreateManagedWidget("menubar", boxWidgetClass, manager, XtNorientation, XtorientHorizontal, XtNborderWidth, 0, NULL);
101
102 /* the file menu */
103 menubutton_file = XtCreateManagedWidget("File", menuButtonWidgetClass, menubar, NULL, 0);
104 menu_file = XtCreatePopupShell("fileMenu", simpleMenuWidgetClass, menubutton_file, NULL, 0);
105 XtVaSetValues(menubutton_file, XtNmenuName, "fileMenu", NULL);
106 menu_file_exit = XtCreateManagedWidget("Exit", smeBSBObjectClass, menu_file, NULL, 0);
107 XtAddCallback(menu_file_exit, XtNcallback, do_file_exit, NULL);
108 }
109
menu_file_open_box(ui_open_callback callback,void * data,char * filter)110 void menu_file_open_box(ui_open_callback callback, void *data, char *filter)
111 {
112 /* dummy implementation */
113 }
114
initialize_window(Display * display)115 void initialize_window(Display *display)
116 {
117 toplevel = XtVaAppCreateShell(APPLICATION_NAME, APPLICATION_CLASS, applicationShellWidgetClass, display, XtNallowShellResize, TRUE, NULL);
118
119 manager = XtVaCreateManagedWidget("manager", boxWidgetClass, toplevel, XtNhSpace, 0, XtNvSpace, 0, NULL);
120
121 init_menus();
122
123 drawbox = XtVaCreateManagedWidget("drawbox", boxWidgetClass, manager, XtNwidth, 512, XtNheight, 256, NULL);
124
125 XtRealizeWidget(toplevel);
126
127 video_init();
128 }
129
usage(char * progname)130 void usage(char *progname)
131 {
132 printf("usage: %s [--system=<system>] [--nosound] [filename]\n", progname);
133 }
134
main(int argc,char * argv[])135 int main(int argc, char *argv[])
136 {
137 extern int nes_psg_quality; /* FIXME: cheap hack, copied from nes_psg.h */
138 rom_file romfile;
139 int system_type;
140 int i;
141 Display *display; /* so as not to conflict with the one in video_x.c */
142
143 XtToolkitInitialize();
144
145 context = XtCreateApplicationContext();
146
147 display = XtOpenDisplay(context, NULL, APPLICATION_NAME, APPLICATION_CLASS, NULL, 0, &argc, argv);
148
149 if (argc == 1) {
150 usage(argv[0]);
151 return 1;
152 }
153
154 system_type = ST_NONE;
155 romfile = NULL;
156
157 nes_psg_quality = 2;
158
159 for (i = 1; i < argc; i++) {
160 if (!strncasecmp(argv[i], "--system=", 9)) {
161 system_type = parse_system_name(argv[i] + 9);
162 } else if (!strcasecmp(argv[i], "--nosound")) {
163 nes_psg_quality = 0;
164 } else if (romfile) {
165 printf("rom file \"%s\" already loaded, ignoring \"%s\"\n", romfile->filename, argv[i]);
166 } else if ((romfile = read_romimage(argv[i]))) {
167 if (system_type == ST_NONE) {
168 system_type = guess_system(romfile);
169 }
170 } else {
171 printf("error loading rom file \"%s\"\n", argv[i]);
172 }
173 }
174
175 if (system_type == ST_NONE) {
176 printf("no system specified or unable to guess system.\n");
177 return 1;
178 }
179
180 if (romfile == NULL) {
181 printf("rom not specified.\n");
182 usage(argv[0]);
183 return 1;
184 }
185
186 initialize_window(display);
187
188 activate_system(system_type, romfile);
189
190 XtAppMainLoop(context);
191
192 return 0;
193 }
194
195
196 /* debug console handling */
197
deb_printf(const char * fmt,...)198 void deb_printf(const char *fmt, ...)
199 {
200 va_list args;
201
202 va_start(args, fmt);
203 vprintf(fmt, args);
204 va_end(args);
205 }
206
207
208 /* emulation timeslicing */
209
210 void (*timeslice)(void *) = NULL;
211 void *timeslice_data;
212
set_timeslice(void (* proc)(void *),void * data)213 void set_timeslice(void (*proc)(void *), void *data)
214 {
215 if (!timeslice) {
216 XtAppAddWorkProc(context, emulation_timeslice, NULL);
217 }
218
219 timeslice = proc;
220 timeslice_data = data;
221 }
222
unset_timeslice(void)223 void unset_timeslice(void)
224 {
225 timeslice = NULL;
226 timeslice_data = NULL;
227 }
228
emulation_timeslice(XtPointer client_data)229 Boolean emulation_timeslice(XtPointer client_data)
230 {
231 if (timeslice) {
232 timeslice(timeslice_data);
233 }
234
235 if ((system_flags == F_NONE) && timeslice) {
236 return False;
237 } else {
238 return True;
239 }
240 }
241
242
243 /* menu callbacks */
244
do_file_exit(Widget w,XtPointer client_data,XtPointer call_data)245 void do_file_exit(Widget w, XtPointer client_data, XtPointer call_data)
246 {
247 if (dn_shutdown) {
248 dn_shutdown();
249 }
250 exit(0);
251 }
252
253
254 /* video interface */
255
ui_set_drawbox_size(int width,int height)256 void ui_set_drawbox_size(int width, int height)
257 {
258 XtVaSetValues(drawbox, XtNwidth, width, XtNheight, height, NULL);
259 }
260
261 /*
262 * $Log: ui_x.c,v $
263 * Revision 1.31 2000/08/22 01:28:59 nyef
264 * added dummy implementation of menu_file_open_box()
265 *
266 * Revision 1.30 2000/07/01 15:43:14 nyef
267 * fixed to not dump core when encountering a child menu
268 *
269 * Revision 1.29 2000/06/29 01:24:56 nyef
270 * renamed the menu functions more appropriately
271 *
272 * Revision 1.28 2000/06/29 01:05:39 nyef
273 * moved menu interface out from ui.h to menu.h
274 *
275 * Revision 1.27 2000/06/25 19:22:11 nyef
276 * added dummy implementations of ui_{en,dis}able_item()
277 *
278 * Revision 1.26 2000/06/25 18:57:09 nyef
279 * added support for parameters with menu callbacks
280 * added support for changing the label on a menu
281 *
282 * Revision 1.25 2000/06/25 17:20:09 nyef
283 * added per-driver menu interface
284 *
285 * Revision 1.24 2000/06/10 02:20:49 nyef
286 * fixed --nosound option (silly bug in args parser)
287 *
288 * Revision 1.23 2000/06/09 00:11:31 nyef
289 * added --nosound option
290 *
291 * Revision 1.22 2000/03/25 18:23:02 nyef
292 * broke up toolkit initialization
293 * moved toplevel window creation to initialize_window()
294 *
295 * Revision 1.21 2000/03/06 01:29:59 nyef
296 * extracted most of the X initialization code from main()
297 * rebuilt the command argument parser (added "--system=" option)
298 *
299 * Revision 1.20 2000/02/21 23:16:09 nyef
300 * fixed toplevel window to resize when the drawbox is resized
301 *
302 * Revision 1.19 2000/01/01 04:15:14 nyef
303 * added disabled code to activate apple2 emulation
304 *
305 * Revision 1.18 1999/12/04 06:43:22 nyef
306 * stripped out a lot of dead code
307 *
308 * Revision 1.17 1999/11/26 20:08:24 nyef
309 * moved sound quality control in from the game system layer
310 *
311 * Revision 1.16 1999/11/20 05:27:19 nyef
312 * fixed to work with new rom loading interface
313 *
314 * Revision 1.15 1999/04/17 20:12:46 nyef
315 * changed shutdown() to dn_shutdown().
316 *
317 * Revision 1.14 1999/03/03 02:53:05 nyef
318 * changed the initial size of the drawbox to "really big"
319 * as a workaround for the resize problem
320 *
321 * Revision 1.13 1999/02/13 17:25:34 nyef
322 * disabled file->nes.
323 * added code to accept a filename on the command line.
324 * changed to start running game immediately after starting.
325 *
326 * Revision 1.12 1999/01/08 02:45:25 nyef
327 * disabled file->zarzon.
328 *
329 * Revision 1.11 1998/12/24 04:56:51 nyef
330 * moved for loop from emulation_timeslice() to nes.c.
331 *
332 * Revision 1.10 1998/12/24 01:23:18 nyef
333 * removed debug menu (it was at best useless, and at worst dangerous).
334 * added two file menu items ("Nes", and "Zarzon") to start the system.
335 * fixed file->quit to call exit(3).
336 * fixed background task to only run when we need an emulation timeslice.
337 *
338 * Revision 1.9 1998/12/21 02:58:03 nyef
339 * added a shutdown callback.
340 *
341 * Revision 1.8 1998/12/18 04:22:25 nyef
342 * changed application class to "DarcNES".
343 *
344 * Revision 1.7 1998/10/28 01:50:00 nyef
345 * changed emulation_timeslice() to return aproximately once per screen
346 * refresh. this sped up the emulation appreciably but does not appear
347 * to have degraded the key response.
348 *
349 * Revision 1.6 1998/10/02 01:22:07 nyef
350 * changed timeslice function to remove itself when emulation halts.
351 *
352 * Revision 1.5 1998/08/24 01:25:41 nyef
353 * started working on new interface.
354 *
355 * Revision 1.4 1998/08/02 04:01:56 nyef
356 * added function deb_printf() for debug console support.
357 * added ui.h to the list of includes.
358 *
359 * Revision 1.3 1998/08/02 03:56:28 nyef
360 * added comments grouping functions into related sections.
361 *
362 * Revision 1.2 1998/08/02 02:31:47 nyef
363 * added a separate menubar widget.
364 * added a "Debug" menu with one item. ("Show console", which calls a stub.)
365 *
366 * Revision 1.1 1998/08/02 02:04:26 nyef
367 * Initial revision
368 *
369 */
370