|
|
1.1 root 1: /* Generator is (c) James Ponder, 1997-2001 http://www.squish.net/generator/ */
2:
3: /* gtk user interface */
4:
5: #include <sys/types.h>
6: #include <sys/stat.h>
7: #include <unistd.h>
8: #include <fcntl.h>
9: #include <errno.h>
10: #include <stdio.h>
11: #include <stdlib.h>
12: #include <string.h>
13: #include <pwd.h>
14:
15: #include <gtk/gtk.h>
16: #include <gdk/gdkx.h>
17:
18: /* need Xlib.h for XAutoRepeatOff - how poo is X */
19: #include "X11/Xlib.h"
20:
21: #include "SDL.h"
22:
23: #include "generator.h"
24: #include "snprintf.h"
25:
26: #include "glade/interface.h"
27: #include "glade/support.h"
28:
29: #include "ui.h"
30: #include "ui-gtk.h"
31: #include "uiplot.h"
32: #include "gtkopts.h"
33:
34: #include "vdp.h"
35: #include "gensound.h"
36: #include "cpu68k.h"
37: #include "mem68k.h"
38: #include "cpuz80.h"
39: #include "event.h"
40: #include "state.h"
41: #include "initcart.h"
42:
43: #define HBORDER_MAX 32
44: #define HBORDER_DEFAULT 8
45:
46: #define VBORDER_MAX 32
47: #define VBORDER_DEFAULT 8
48:
49: #define HMAXSIZE (320 + 2 * HBORDER_MAX)
50: #define VMAXSIZE (240 + 2 * VBORDER_MAX)
51:
52: #define HSIZE (320 + 2 * ui_hborder)
53: #define VSIZE ((vdp_vislines ? vdp_vislines : 224) + 2 * ui_vborder)
54:
55: typedef struct {
56: unsigned int a;
57: unsigned int b;
58: unsigned int c;
59: unsigned int up;
60: unsigned int down;
61: unsigned int left;
62: unsigned int right;
63: unsigned int start;
64: } t_gtkkeys;
65:
66: const char *ui_gtk_keys[] = {
67: "a", "b", "c", "start", "left", "right", "up", "down"
68: };
69:
70: /*** static variables ***/
71:
72: static SDL_Surface *screen = NULL; /* SDL screen */
73:
74: static char *ui_initload = NULL; /* filename to load on init */
75: static char *ui_configfile = NULL; /* configuration file */
76: static uint8 ui_plotfield = 0; /* flag indicating plotting this field */
77: static uint8 ui_vdpsimple = 0; /* 0=raster, 1=cell based plotter */
78: static int ui_running = 0; /* running a game */
79: static GtkWidget *ui_win_main; /* main window */
80: static GtkWidget *ui_win_about; /* about window */
81: static GtkWidget *ui_win_console; /* console window */
82: static GtkWidget *ui_win_opts; /* options window */
83: static GtkWidget *ui_win_filesel; /* file selection window */
84: static int ui_filesel_type; /* selection type: 0=rom, 1=state */
85: static int ui_filesel_save; /* 0=load, 1=save */
86: static GtkWidget *ui_gtk_dialog(const char *msg);
87: static uint8 ui_frameskip = 0; /* 0 for dynamic */
88: static uint8 ui_actualskip = 0; /* the last skip we did (1..) */
89: static uint8 ui_statusbar = 1; /* status-bar? */
90: static uint8 ui_screen[3][4 * HMAXSIZE * VMAXSIZE]; /* screen buffers */
91: static uint8 *ui_screen0; /* pointer to screen block for bank 0 */
92: static uint8 *ui_screen1; /* pointer to screen block for bank 1 */
93: static uint8 *ui_newscreen; /* pointer to new screen block */
94: static int ui_whichbank; /* current viewed screen */
95: static int ui_locksurface; /* lock SDL surface? */
96: static unsigned int ui_hborder = HBORDER_DEFAULT; /* horizontal border */
97: static unsigned int ui_vborder = VBORDER_DEFAULT; /* vertical border */
98: static int ui_query_response = -1; /* query response */
99: t_gtkkeys ui_cont[2]; /* keyboard key codes */
100: static int ui_musicfile = -1; /* fd of output file for GYM/GNM logging */
101:
102: static enum {
103: SCREEN_100, SCREEN_200, SCREEN_FULL
104: } ui_screenmode = SCREEN_100;
105:
106: t_interlace ui_interlace = DEINTERLACE_WEAVEFILTER;
107:
108: /*** Forward references ***/
109:
110: static void ui_usage(void);
111: static void ui_gtk_filesel_ok(GtkFileSelection * obj, gpointer user_data);
112: static void ui_gtk_sizechange(void);
113: static void ui_newframe(void);
114: static void ui_rendertoscreen(void);
115: static gint ui_gtk_configuremain(GtkWidget * widget,
116: GdkEventConfigure * event);
117: static int ui_topbit(unsigned long int bits);
118: static void ui_gtk_opts_to_window(void);
119: static void ui_gtk_opts_from_window(void);
120: static int ui_gtk_query(const char *msg, int style);
121: static void ui_gtk_opts_to_menu(void);
122: static void ui_simpleplot(void);
123:
124: /*** Program entry point ***/
125:
126: int ui_init(int argc, char *argv[])
127: {
128: char ch;
129: GtkWidget *button, *draw, *obj;
130: struct passwd *passwd;
131: struct stat statbuf;
132:
133: gtk_set_locale();
134: gtk_init(&argc, &argv);
135:
136: while ((ch = getopt(argc, argv, "?dc:w:")) != -1) {
137: switch (ch) {
138: case 'd': /* turn on debug mode */
139: gen_debugmode = 1;
140: break;
141: case 'c': /* configuration file */
142: ui_configfile = optarg;
143: break;
144: case 'w': /* saved game work dir */
145: chdir(optarg); /* for the moment this will do */
146: break;
147: case '?':
148: default:
149: ui_usage();
150: }
151: }
152: argc -= optind;
153: argv += optind;
154:
155: if (argc > 0) {
156: ui_initload = argv[0];
157: argc--;
158: argv++;
159: }
160:
161: if (argc != 0)
162: ui_usage();
163:
164: if (ui_configfile == NULL) {
165: if ((passwd = getpwuid(getuid())) == NULL) {
166: fprintf(stderr, "Who are you? (getpwent failed)\n");
167: exit(1);
168: }
169: ui_configfile = malloc(strlen(passwd->pw_dir) + sizeof("/.genrc"));
170: sprintf(ui_configfile, "%s/.genrc", passwd->pw_dir);
171: }
172: if (stat(ui_configfile, &statbuf) != 0) {
173: fprintf(stderr, "No configuration file found, using defaults.\n");
174: } else {
175: if (gtkopts_load(ui_configfile) != 0)
176: fprintf(stderr, "Error loading configuration file, using defaults.\n");
177: }
178:
179: /* create gtk windows */
180:
181: ui_win_main = create_mainwin();
182: ui_win_about = create_about();
183: ui_win_console = create_console();
184: ui_win_opts = create_opts();
185: ui_win_filesel = gtk_file_selection_new("Select file...");
186: button = GTK_FILE_SELECTION(ui_win_filesel)->ok_button;
187: gtk_signal_connect(GTK_OBJECT(button), "clicked",
188: GTK_SIGNAL_FUNC(ui_gtk_filesel_ok), NULL);
189: button = GTK_FILE_SELECTION(ui_win_filesel)->cancel_button;
190: gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
191: GTK_SIGNAL_FUNC(gtk_widget_hide),
192: GTK_OBJECT(ui_win_filesel));
193:
194: /* open main window */
195:
196: gtk_widget_add_events(ui_win_main, GDK_KEY_RELEASE_MASK);
197: gtk_window_set_title(GTK_WINDOW(ui_win_main), "Generator/gtk " VERSION);
198: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "debug"));
199: if (!gen_debugmode)
200: gtk_widget_hide(obj);
201: gtk_widget_show(ui_win_main);
202: draw = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
203: "drawingarea_main"));
204: gtk_signal_connect(GTK_OBJECT(ui_win_main), "configure_event",
205: GTK_SIGNAL_FUNC(ui_gtk_configuremain), 0);
206: {
207: char SDL_windowhack[32];
208: snprintf(SDL_windowhack, sizeof(SDL_windowhack), "SDL_WINDOWID=%ld",
209: GDK_WINDOW_XWINDOW(draw->window));
210: putenv(SDL_windowhack);
211: }
212: if (SDL_Init(SDL_INIT_VIDEO) < 0) {
213: fprintf(stderr, "Couldn't initialise SDL: %s\n", SDL_GetError());
214: return -1;
215: }
216: ui_gtk_sizechange();
217: ui_gtk_newoptions();
218: ui_gtk_opts_to_menu();
219:
220: /* ui_newscreen is where the emulation data is rendered to - it is
221: then compared with ui_screen0 or ui_screen1 depending on which
222: screen bank it is being written to, and the delta changes are sent
223: to screen memory. The ui_screenX and ui_newscreen pointers are then
224: switched, and the next frame/field begins... */
225: memset(ui_screen[0], 0, sizeof(ui_screen[0]));
226: memset(ui_screen[1], 0, sizeof(ui_screen[1]));
227: ui_screen0 = ui_screen[0];
228: ui_screen1 = ui_screen[1];
229: ui_newscreen = ui_screen[2];
230: ui_whichbank = 0; /* viewing 0 */
231: return 0;
232: }
233:
234: static void ui_usage(void)
235: {
236: fprintf(stderr, "Generator is (c) James Ponder 1997-2001, all rights "
237: "reserved. v" VERSION "\n\n");
238: fprintf(stderr, "generator [options] [<rom>]\n\n");
239: fprintf(stderr, " -d debug mode\n");
240: fprintf(stderr, " -w <work dir> set work directory\n");
241: fprintf(stderr, " -c <config file> use alternative config file\n\n");
242: fprintf(stderr, " ROM types supported: .rom or .smd interleaved "
243: "(autodetected)\n");
244: exit(1);
245: }
246:
247: void ui_final(void)
248: {
249: SDL_Quit();
250: }
251:
252: int ui_loop(void)
253: {
254: char *p;
255:
256: if (ui_initload) {
257: p = gen_loadimage(ui_initload);
258: if (p)
259: ui_gtk_dialog(p);
260: } else {
261: gen_loadmemrom(initcart, initcart_len);
262: }
263: while (!gen_quit) {
264: if (ui_running) {
265: while (gtk_events_pending())
266: gtk_main_iteration_do(0);
267: ui_newframe();
268: event_doframe();
269: } else {
270: gtk_main();
271: }
272: }
273: return 0;
274: }
275:
276: void ui_newframe(void)
277: {
278: static int vmode = -1;
279: static int pal = -1;
280: static int skipcount = 0;
281: static char frameplots[60]; /* 60 for NTSC, 50 for PAL */
282: static unsigned int frameplots_i = 0;
283: unsigned int i;
284: int fps;
285: char fps_string[8];
286: GtkWidget *entry_fps;
287: static int lasttype = -1;
288:
289: if (frameplots_i > vdp_framerate)
290: frameplots_i = 0;
291: if (((vdp_reg[12] >> 1) & 3) && vdp_oddframe) {
292: /* interlace mode, and we're about to do an odd field - we always leave
293: ui_plotfield alone so we do fields in pairs, this stablises the
294: display, reduces blurring */
295: } else {
296: ui_plotfield = 0;
297: if (ui_frameskip == 0) {
298: if (sound_feedback != -1)
299: ui_plotfield = 1;
300: } else {
301: if (cpu68k_frames % ui_frameskip == 0)
302: ui_plotfield = 1;
303: }
304: }
305: if (!ui_plotfield) {
306: skipcount++;
307: frameplots[frameplots_i++] = 0;
308: return;
309: }
310: lasttype = vdp_oddframe;
311: /* check for ROM or user changing the vertical size */
312: if (vmode == (int)(vdp_reg[1] & (1 << 3)) || pal != (int)vdp_pal) {
313: vdp_setupvideo();
314: vmode = vdp_reg[1] & (1 << 3);
315: pal = vdp_pal;
316: }
317: /* count the frames we've plotted in the last vdp_framerate real frames */
318: fps = 0;
319: for (i = 0; i < vdp_framerate; i++) {
320: if (frameplots[i])
321: fps++;
322: }
323: frameplots[frameplots_i++] = 1;
324: if (!ui_statusbar)
325: return;
326: snprintf(fps_string, sizeof(fps_string), "%d", fps);
327: entry_fps = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
328: "entry_fps"));
329: gtk_entry_set_text(GTK_ENTRY(entry_fps), fps_string);
330: skipcount = 0;
331: }
332:
333: /* ui_line is called for all vdp_totlines but is offset so that line=0
334: is the first line, line=(vdp_totlines-vdp_visstartline)-1 is the
335: last */
336:
337: void ui_line(int line)
338: {
339: static uint8 gfx[320];
340: unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
341: unsigned int offset = ui_hborder + ((vdp_reg[12] & 1) ? 0 : 32);
342: uint8 bg;
343: uint32 bgpix;
344: uint8 *location;
345: unsigned int i;
346:
347: if (!ui_plotfield)
348: return;
349: if (ui_vdpsimple) {
350: if (line == (int)(vdp_vislines >> 1))
351: /* if we're in simple cell-based mode, plot when half way down screen */
352: ui_simpleplot();
353: return;
354: }
355: if (line < -(int)ui_vborder || line >= (int)(vdp_vislines + ui_vborder))
356: return;
357:
358: bg = (vdp_reg[7] & 63);
359: uiplot_checkpalcache(0);
360: bgpix = uiplot_palcache[bg];
361: location = ui_newscreen +
362: (line + ui_vborder) * HMAXSIZE * screen->format->BytesPerPixel;
363: if (line < 0 || line >= (int)vdp_vislines) {
364: /* in border */
365: switch (screen->format->BytesPerPixel) {
366: case 2:
367: for (i = 0; i < HSIZE; i++) {
368: ((uint16 *)location)[i] = bgpix;
369: }
370: break;
371: case 4:
372: for (i = 0; i < HSIZE; i++) {
373: ((uint32 *)location)[i] = bgpix;
374: }
375: break;
376: }
377: return;
378: }
379: /* normal line */
380: switch ((vdp_reg[12] >> 1) & 3) {
381: case 0: /* normal */
382: case 1: /* interlace simply doubled up */
383: case 2: /* invalid */
384: vdp_renderline(line, gfx, 0);
385: break;
386: case 3: /* interlace with double resolution */
387: vdp_renderline(line, gfx, vdp_oddframe);
388: break;
389: }
390: switch (screen->format->BytesPerPixel) {
391: case 2:
392: uiplot_convertdata16(gfx, ((uint16 *)location) + offset, width);
393: for (i = 0; i < offset; i++) {
394: ((uint16 *)location)[i] = bgpix;
395: ((uint16 *)location)[i + offset + width] = bgpix;
396: }
397: break;
398: case 4:
399: uiplot_convertdata32(gfx, ((uint32 *)location) + offset, width);
400: for (i = 0; i < offset; i++) {
401: ((uint32 *)location)[i] = bgpix;
402: ((uint32 *)location)[i + offset + width] = bgpix;
403: }
404: break;
405: }
406: }
407:
408: static void ui_simpleplot(void)
409: {
410: static uint8 gfx[(320 + 16) * (240 + 16)];
411: unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
412: unsigned int offset = ui_hborder + ((vdp_reg[12] & 1) ? 0 : 32);
413: unsigned int line, i;
414: uint8 *location, *location2;
415: uint8 bg;
416: uint32 bgpix;
417: /* cell mode - entire frame done here */
418: bg = (vdp_reg[7] & 63);
419: uiplot_checkpalcache(0);
420: bgpix = uiplot_palcache[bg];
421: vdp_renderframe(gfx + (8 * (320 + 16)) + 8, 320 + 16); /* plot frame */
422: location = ui_newscreen +
423: ui_vborder * HMAXSIZE * screen->format->BytesPerPixel;
424: switch (screen->format->BytesPerPixel) {
425: case 2:
426: for (line = 0; line < vdp_vislines; line++) {
427: for (i = 0; i < offset; i++) {
428: ((uint16 *)location)[i] = bgpix;
429: ((uint16 *)location)[width + offset + i] = bgpix;
430: }
431: uiplot_convertdata16(gfx + 8 + (line + 8) * (320 + 16),
432: ((uint16 *)location) + offset, width);
433: location += HMAXSIZE * 2;
434: }
435: break;
436: case 4:
437: for (line = 0; line < vdp_vislines; line++) {
438: for (i = 0; i < offset; i++) {
439: ((uint32 *)location)[i] = bgpix;
440: ((uint32 *)location)[width + offset + i] = bgpix;
441: }
442: uiplot_convertdata32(gfx + 8 + (line + 8) * (320 + 16),
443: ((uint32 *)location) + offset, width);
444: location += HMAXSIZE * 4;
445: }
446: break;
447: }
448: location = ui_newscreen;
449: location2 = ui_newscreen + (ui_vborder + vdp_vislines) *
450: HMAXSIZE * screen->format->BytesPerPixel;
451: switch (screen->format->BytesPerPixel) {
452: case 2:
453: for (line = 0; line < ui_vborder; line++) {
454: for (i = 0; i < HSIZE; i++) {
455: ((uint16 *)location)[i] = bgpix;
456: ((uint16 *)location2)[i] = bgpix;
457: }
458: location += HMAXSIZE * 2;
459: location2 += HMAXSIZE * 2;
460: }
461: break;
462: case 4:
463: for (line = 0; line < ui_vborder; line++) {
464: for (i = 0; i < HSIZE; i++) {
465: ((uint32 *)location)[i] = bgpix;
466: ((uint32 *)location2)[i] = bgpix;
467: }
468: location += HMAXSIZE * 4;
469: location2 += HMAXSIZE * 4;
470: }
471: break;
472: }
473: }
474:
475: /*** ui_endfield - end of field reached ***/
476:
477: void ui_endfield(void)
478: {
479: static int counter = 0;
480:
481: if (ui_plotfield) {
482: ui_rendertoscreen(); /* plot ui_newscreen to screen */
483: }
484: if (ui_frameskip == 0) {
485: /* dynamic frame skipping */
486: counter++;
487: if (sound_feedback >= 0) {
488: ui_actualskip = counter;
489: counter = 0;
490: }
491: } else {
492: ui_actualskip = ui_frameskip;
493: }
494: }
495:
496: void ui_rendertoscreen(void)
497: {
498: uint8 **oldscreenpp = ui_whichbank ? &ui_screen1 : &ui_screen0;
499: uint8 *scrtmp;
500: uint8 *newlinedata, *oldlinedata;
501: unsigned int line;
502: uint8 *location;
503: uint8 *evenscreen; /* interlace: lines 0,2,etc. */
504: uint8 *oddscreen; /* lines 1,3,etc. */
505:
506: if (ui_locksurface && SDL_LockSurface(screen) != 0)
507: ui_err("Failed to lock SDL surface");
508: for (line = 0; line < VSIZE; line++) {
509: newlinedata = ui_newscreen +
510: line * HMAXSIZE * screen->format->BytesPerPixel;
511: oldlinedata = *oldscreenpp +
512: line * HMAXSIZE * screen->format->BytesPerPixel;
513: switch (ui_screenmode) {
514: case SCREEN_100:
515: location = screen->pixels + line * screen->pitch;
516: /* we could use uiplot_renderXX_x1 routines here, but SDL wouldn't
517: pick up our delta changes so we don't */
518: memcpy(location, newlinedata, HSIZE * screen->format->BytesPerPixel);
519: break;
520: case SCREEN_200:
521: location = screen->pixels + 2 * line * screen->pitch;
522: if (screen->format->BytesPerPixel != 2 &&
523: screen->format->BytesPerPixel != 4)
524: ui_err("unsupported mode for 200%% scaling\n");
525: switch ((vdp_reg[12] >> 1) & 3) { /* interlace mode */
526: case 0:
527: case 1:
528: case 2:
529: switch (screen->format->BytesPerPixel) {
530: case 2:
531: uiplot_render16_x2((uint16 *)newlinedata, NULL, location,
532: screen->pitch, HSIZE);
533: break;
534: case 4:
535: uiplot_render32_x2((uint32 *)newlinedata, NULL, location,
536: screen->pitch, HSIZE);
537: break;
538: }
539: break;
540: case 3:
541: /* work out which buffer contains the odd and even fields */
542: if (vdp_oddframe) {
543: oddscreen = ui_newscreen;
544: evenscreen = ui_whichbank ? ui_screen0 : ui_screen1;
545: } else {
546: evenscreen = ui_newscreen;
547: oddscreen = ui_whichbank ? ui_screen0 : ui_screen1;
548: }
549: switch (ui_interlace) {
550: case DEINTERLACE_BOB:
551: switch (screen->format->BytesPerPixel) {
552: case 2:
553: uiplot_render16_x2((uint16 *)newlinedata, NULL, location,
554: screen->pitch, HSIZE);
555: break;
556: case 4:
557: uiplot_render32_x2((uint32 *)newlinedata, NULL, location,
558: screen->pitch, HSIZE);
559: break;
560: }
561: break;
562: case DEINTERLACE_WEAVE:
563: evenscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
564: oddscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
565: switch (screen->format->BytesPerPixel) {
566: case 2:
567: uiplot_render16_x2h((uint16 *)evenscreen, NULL, location, HSIZE);
568: uiplot_render16_x2h((uint16 *)oddscreen, NULL,
569: location + screen->pitch, HSIZE);
570: break;
571: case 4:
572: uiplot_render32_x2h((uint32 *)evenscreen, NULL, location, HSIZE);
573: uiplot_render32_x2h((uint32 *)oddscreen, NULL,
574: location + screen->pitch, HSIZE);
575: break;
576: }
577: break;
578: case DEINTERLACE_WEAVEFILTER:
579: evenscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
580: oddscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
581: switch (screen->format->BytesPerPixel) {
582: case 2:
583: /* lines line+0 and line+1 */
584: uiplot_irender16_weavefilter((uint16 *)evenscreen,
585: (uint16 *)oddscreen,
586: location, HSIZE);
587: /* lines line+1 and line+2 */
588: uiplot_irender16_weavefilter((uint16 *)oddscreen,
589: ((uint16 *)evenscreen) + HMAXSIZE,
590: location + screen->pitch, HSIZE);
591: break;
592: case 4:
593: /* lines line+0 and line+1 */
594: uiplot_irender32_weavefilter((uint32 *)evenscreen,
595: (uint32 *)oddscreen,
596: location, HSIZE);
597: /* lines line+1 and line+2 */
598: uiplot_irender32_weavefilter((uint32 *)oddscreen,
599: ((uint32 *)evenscreen) + HMAXSIZE,
600: location + screen->pitch, HSIZE);
601: break;
602: }
603: }
604: break;
605: }
606: break;
607: case SCREEN_FULL:
608: default:
609: ui_err("invalid screen mode\n");
610: }
611: }
612: if (ui_locksurface)
613: SDL_UnlockSurface(screen);
614: SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
615: ui_whichbank ^= 1;
616: // if (ui_vsync)
617: // uip_vsync();
618: /* swap ui_screenX and ui_newscreen pointers */
619: scrtmp = *oldscreenpp;
620: *oldscreenpp = ui_newscreen;
621: ui_newscreen = scrtmp;
622: }
623:
624: /*** logging functions ***/
625:
626: /* logging is done this way because this was the best I could come up with
627: whilst battling with macros that can only take fixed numbers of arguments */
628:
629: #define LOG_FUNC(name,level,txt) void ui_log_ ## name ## (const char *text, ...) \
630: { \
631: va_list ap; \
632: if (gen_loglevel >= level) { \
633: printf("[%s] ", txt); \
634: va_start(ap, text); \
635: vprintf(text, ap); \
636: va_end(ap); \
637: putchar(10); \
638: } \
639: }
640:
641: /* *INDENT-OFF* */
642:
643: LOG_FUNC(debug3, 7, "DEBG ");
644: LOG_FUNC(debug2, 6, "DEBG ");
645: LOG_FUNC(debug1, 5, "DEBG ");
646: LOG_FUNC(user, 4, "USER ");
647: LOG_FUNC(verbose, 3, "---- ");
648: LOG_FUNC(normal, 2, "---- ");
649: LOG_FUNC(critical, 1, "CRIT ");
650: LOG_FUNC(request, 0, "---- "); /* this generates a warning, such is life */
651:
652: /* *INDENT-ON* */
653:
654: /*** ui_err - log error message and quit ***/
655:
656: void ui_err(const char *text, ...)
657: {
658: va_list ap;
659:
660: printf("ERROR: ");
661:
662: va_start(ap, text);
663: vfprintf(stderr, text, ap);
664: va_end(ap);
665: putc(10, stderr);
666: exit(0);
667: }
668:
669: /*** ui_topbit - given an integer return the top most bit set ***/
670:
671: int ui_topbit(unsigned long int bits)
672: {
673: long int bit = 31;
674: unsigned long int mask = 1 << 31;
675:
676: for (; bit >= 0; bit--, mask >>= 1) {
677: if (bits & mask)
678: return bit;
679: }
680: return -1;
681: }
682:
683: /*** ui_setinfo - there is new cart information ***/
684:
685: char *ui_setinfo(t_cartinfo *cartinfo)
686: {
687: (void)cartinfo;
688: return NULL;
689: }
690:
691: /*** gtk functions ***/
692:
693: gint ui_gtk_configuremain(GtkWidget * widget, GdkEventConfigure * event)
694: {
695: (void)widget;
696: (void)event;
697: /* if we were allowing resizing this is where we'd do it, but note
698: to check whether it's just the location or the size being changed
699: as a call to SDL to set the video mode will erase the screen and
700: then everything would go black */
701: return TRUE;
702: }
703:
704: void ui_gtk_filesel_ok(GtkFileSelection * obj, gpointer user_data)
705: {
706: char msg[512];
707: char buf[8];
708: char *file, *p;
709: int fd;
710: struct stat s;
711:
712: (void)obj;
713: (void)user_data;
714: file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ui_win_filesel));
715: gtk_widget_hide(ui_win_filesel);
716:
717: if (ui_filesel_save) {
718: if (stat(file, &s) == 0) {
719: snprintf(msg, sizeof(msg), "The file '%s' already exists - overwrite?",
720: file);
721: if (ui_gtk_query(msg, 0) != 0)
722: return;
723: }
724: }
725: *msg = '\0';
726:
727: switch ((ui_filesel_type << 1) | ui_filesel_save) {
728: case 0:
729: p = gen_loadimage(file);
730: if (p)
731: snprintf(msg, sizeof(msg), "An error occured whilst tring to load "
732: "the ROM '%s': %s", file, p);
733: break;
734: case 1:
735: if (cpu68k_rom == NULL || cpu68k_romlen == 0) {
736: snprintf(msg, sizeof(msg), "There is no ROM currently in memory to "
737: "save!");
738: break;
739: }
740: if ((fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1
741: || write(fd, cpu68k_rom, cpu68k_romlen) == -1 || close(fd) == -1) {
742: snprintf(msg, sizeof(msg), "An error occured whilst trying to save the "
743: "ROM as '%s': %s", file, strerror(errno));
744: }
745: break;
746: case 2:
747: if (stat(file, &s) != 0) {
748: snprintf(msg, sizeof(msg), "%s: %s", file, strerror(errno));
749: break;
750: }
751: if (state_loadfile(file) != 0)
752: snprintf(msg, sizeof(msg), "An error occured whilst trying to load "
753: "state from '%s': %s", file, strerror(errno));
754: break;
755: case 3:
756: if (state_savefile(file) != 0)
757: snprintf(msg, sizeof(msg), "An error occured whilst trying to save "
758: "state to '%s': %s", file, strerror(errno));
759: break;
760: case 5:
761: if (ui_musicfile != -1) {
762: snprintf(msg, sizeof(msg), "There is already a music log in progress");
763: break;
764: }
765: if ((ui_musicfile = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1) {
766: snprintf(msg, sizeof(msg), "An error occured whilst trying to start "
767: "a GYM log to '%s': %s", file, strerror(errno));
768: }
769: gen_musiclog = 1;
770: break;
771: case 7:
772: if (ui_musicfile != -1) {
773: snprintf(msg, sizeof(msg), "There is already a music log in progress");
774: break;
775: }
776: if ((ui_musicfile = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1) {
777: snprintf(msg, sizeof(msg), "An error occured whilst trying to start "
778: "a GNM log to '%s': %s", file, strerror(errno));
779: }
780: buf[0] = 'G'; buf[1] = 'N'; buf[2] = 'M';
781: buf[3] = vdp_framerate;
782: write(ui_musicfile, buf, 4);
783: gen_musiclog = 2;
784: break;
785: default:
786: strcpy(msg, "Not implemented.");
787: break;
788: }
789: if (msg[0])
790: ui_gtk_dialog(msg);
791: }
792:
793: GtkWidget *ui_gtk_dialog(const char *msg)
794: {
795: GtkWidget *dialog, *label, *button_ok;
796:
797: dialog = gtk_dialog_new();
798: label = gtk_label_new(msg);
799: gtk_label_set_line_wrap(GTK_LABEL(label), 1);
800: button_ok = gtk_button_new_with_label("OK");
801: gtk_signal_connect_object(GTK_OBJECT(button_ok), "clicked",
802: GTK_SIGNAL_FUNC(gtk_widget_destroy),
803: GTK_OBJECT(dialog));
804: gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
805: button_ok);
806: gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
807: gtk_window_set_modal(GTK_WINDOW(dialog), 1);
808: gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 150);
809: gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
810: gtk_widget_show_all(dialog);
811: return dialog;
812: }
813:
814: /* supporting function for ui_gtk_query */
815:
816: static void ui_gtk_response(GtkButton *button, gpointer func_data)
817: {
818: (void)button;
819: ui_query_response = GPOINTER_TO_INT(func_data);
820: gtk_main_quit();
821: }
822:
823: /* ask a question and return 0 for OK/Yes, -1 for Cancel/No */
824:
825: static int ui_gtk_query(const char *msg, int style)
826: {
827: GtkWidget *dialog, *label, *button_a, *button_b, *hbox;
828:
829: dialog = gtk_dialog_new();
830: label = gtk_label_new(msg);
831: hbox = gtk_hbox_new(1, 8);
832: gtk_label_set_line_wrap(GTK_LABEL(label), 1);
833: switch (style) {
834: default:
835: case 0:
836: button_a = gtk_button_new_with_label("OK");
837: button_b = gtk_button_new_with_label("Cancel");
838: break;
839: case 1:
840: button_a = gtk_button_new_with_label("Yes");
841: button_b = gtk_button_new_with_label("No");
842: break;
843: }
844: gtk_box_pack_end(GTK_BOX(hbox), button_b, 0, 1, 0);
845: gtk_box_pack_end(GTK_BOX(hbox), button_a, 0, 1, 0);
846: gtk_signal_connect(GTK_OBJECT(button_a), "clicked",
847: GTK_SIGNAL_FUNC(ui_gtk_response),
848: GINT_TO_POINTER(0));
849: gtk_signal_connect(GTK_OBJECT(button_b), "clicked",
850: GTK_SIGNAL_FUNC(ui_gtk_response),
851: GINT_TO_POINTER(-1));
852: gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
853: hbox);
854: gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
855: gtk_window_set_modal(GTK_WINDOW(dialog), 1);
856: gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 150);
857: gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
858: gtk_widget_show_all(dialog);
859: ui_query_response = -1;
860: gtk_main();
861: gtk_widget_destroy(dialog);
862: return ui_query_response;
863: }
864:
865: void ui_gtk_filesel(int type, int save)
866: {
867: ui_filesel_type = type;
868: ui_filesel_save = save;
869:
870: switch ((type << 1) | save) {
871: case 0:
872: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
873: "Choose ROM file (BIN or SMD format) to load");
874: break;
875: case 1:
876: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
877: "Choose filename to save ROM file (BIN format) to");
878: break;
879: case 2:
880: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
881: "Choose state file to load");
882: break;
883: case 3:
884: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
885: "Choose filename to save state to");
886: break;
887: case 5:
888: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
889: "Choose where to start GYM logging");
890: break;
891: case 7:
892: gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
893: "Choose where to start GNM logging");
894: break;
895: }
896: gtk_widget_show(ui_win_filesel);
897: }
898:
899: void ui_gtk_about(void)
900: {
901: gtk_widget_show(ui_win_about);
902: }
903:
904: void ui_gtk_options(void)
905: {
906: ui_gtk_opts_to_window();
907: gtk_widget_show(ui_win_opts);
908: }
909:
910: void ui_gtk_console(void)
911: {
912: gtk_widget_show(ui_win_console);
913: }
914:
915: void ui_gtk_quit(void)
916: {
917: gen_quit = 1;
918: gtk_main_quit();
919: }
920:
921: void ui_gtk_closeconsole(void)
922: {
923: gtk_widget_hide(ui_win_console);
924: }
925:
926: void ui_gtk_play(void)
927: {
928: if (ui_running) {
929: ui_gtk_dialog("Generator is already playing a ROM");
930: return;
931: }
932: if (cpu68k_rom == NULL || cpu68k_romlen == 0) {
933: ui_gtk_dialog("You must load a ROM into Generator");
934: return;
935: }
936: /* start running the game */
937: ui_running = 1;
938: ui_gtk_sizechange();
939: gtk_main_quit();
940: }
941:
942: void ui_gtk_pause(void)
943: {
944: if (!ui_running) {
945: ui_gtk_dialog("Generator is not playing a ROM");
946: return;
947: }
948: ui_running = 0;
949: }
950:
951: void ui_gtk_softreset(void)
952: {
953: gen_softreset();
954: }
955:
956: void ui_gtk_hardreset(void)
957: {
958: gen_reset();
959: }
960:
961: /* set main window size from current parameters */
962:
963: void ui_gtk_sizechange(void)
964: {
965: GtkWidget *w;
966:
967: w = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
968: "drawingarea_main"));
969: switch (ui_screenmode) {
970: case SCREEN_100:
971: gtk_widget_set_usize(w, HSIZE, VSIZE);
972: screen = SDL_SetVideoMode(HSIZE, VSIZE, 0, 0);
973: break;
974: case SCREEN_200:
975: gtk_widget_set_usize(w, HSIZE * 2, VSIZE * 2);
976: screen = SDL_SetVideoMode(HSIZE * 2, VSIZE * 2, 0, 0);
977: break;
978: default:
979: ui_err("invalid screen mode\n");
980: }
981: w = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "hbox_bottom"));
982: if (ui_statusbar)
983: gtk_widget_show(w);
984: else
985: gtk_widget_hide(w);
986: ui_locksurface = SDL_MUSTLOCK(screen);
987: uiplot_setshifts(ui_topbit(screen->format->Rmask) - 4,
988: ui_topbit(screen->format->Gmask) - 4,
989: ui_topbit(screen->format->Bmask) - 4);
990: }
991:
992: void ui_gtk_newoptions(void)
993: {
994: char buf[32];
995: const char *v;
996: int i, c;
997: unsigned int old_ui_screenmode = ui_screenmode;
998: unsigned int old_sound_minfields = sound_minfields;
999: unsigned int old_sound_maxfields = sound_maxfields;
1000: unsigned int old_ui_hborder = ui_hborder;
1001: unsigned int old_ui_vborder = ui_vborder;
1002: unsigned int old_ui_statusbar = ui_statusbar;
1003:
1004: i = atoi(gtkopts_getvalue("view"));
1005: ui_screenmode = (i == 200) ? SCREEN_200 : SCREEN_100;
1006:
1007: v = gtkopts_getvalue("region");
1008: vdp_overseas = !strcasecmp(v, "overseas");
1009:
1010: v = gtkopts_getvalue("videostd");
1011: vdp_pal = !strcasecmp(v, "pal");
1012:
1013: v = gtkopts_getvalue("autodetect");
1014: gen_autodetect = !strcasecmp(v, "on");
1015:
1016: v = gtkopts_getvalue("plotter");
1017: ui_vdpsimple = !strcasecmp(v, "cell");
1018:
1019: v = gtkopts_getvalue("interlace");
1020: if (!strcasecmp(v, "weave"))
1021: ui_interlace = DEINTERLACE_WEAVE;
1022: else if (!strcasecmp(v, "weave-filter"))
1023: ui_interlace = DEINTERLACE_WEAVEFILTER;
1024: else
1025: ui_interlace = DEINTERLACE_BOB;
1026:
1027: v = gtkopts_getvalue("frameskip");
1028: if (!strcasecmp(v, "auto")) {
1029: ui_frameskip = 0;
1030: } else {
1031: ui_frameskip = atoi(v);
1032: }
1033:
1034: v = gtkopts_getvalue("hborder");
1035: ui_hborder = atoi(v);
1036: if (ui_hborder > HBORDER_MAX)
1037: ui_hborder = HBORDER_MAX;
1038:
1039: v = gtkopts_getvalue("vborder");
1040: ui_vborder = atoi(v);
1041: if (ui_vborder > VBORDER_MAX)
1042: ui_vborder = VBORDER_MAX;
1043:
1044: v = gtkopts_getvalue("z80");
1045: cpuz80_on = !strcasecmp(v, "on");
1046:
1047: v = gtkopts_getvalue("sound");
1048: sound_on = !strcasecmp(v, "on");
1049:
1050: v = gtkopts_getvalue("fm");
1051: sound_fm = !strcasecmp(v, "on");
1052:
1053: v = gtkopts_getvalue("psg");
1054: sound_psg = !strcasecmp(v, "on");
1055:
1056: v = gtkopts_getvalue("sound_minfields");
1057: sound_minfields = atoi(v);
1058:
1059: v = gtkopts_getvalue("sound_maxfields");
1060: sound_maxfields = atoi(v);
1061:
1062: v = gtkopts_getvalue("loglevel");
1063: gen_loglevel = atoi(v);
1064:
1065: v = gtkopts_getvalue("statusbar");
1066: ui_statusbar = !strcasecmp(v, "on");
1067:
1068: for (c = 0; c < 2; c++) {
1069: snprintf(buf, sizeof(buf), "key%d_a", c + 1);
1070: v = gtkopts_getvalue(buf);
1071: ui_cont[c].a = gdk_keyval_from_name(v);
1072: snprintf(buf, sizeof(buf), "key%d_b", c + 1);
1073: v = gtkopts_getvalue(buf);
1074: ui_cont[c].b = gdk_keyval_from_name(v);
1075: snprintf(buf, sizeof(buf), "key%d_c", c + 1);
1076: v = gtkopts_getvalue(buf);
1077: ui_cont[c].c = gdk_keyval_from_name(v);
1078: snprintf(buf, sizeof(buf), "key%d_up", c + 1);
1079: v = gtkopts_getvalue(buf);
1080: ui_cont[c].up = gdk_keyval_from_name(v);
1081: snprintf(buf, sizeof(buf), "key%d_down", c + 1);
1082: v = gtkopts_getvalue(buf);
1083: ui_cont[c].down = gdk_keyval_from_name(v);
1084: snprintf(buf, sizeof(buf), "key%d_left", c + 1);
1085: v = gtkopts_getvalue(buf);
1086: ui_cont[c].left = gdk_keyval_from_name(v);
1087: snprintf(buf, sizeof(buf), "key%d_right", c + 1);
1088: v = gtkopts_getvalue(buf);
1089: ui_cont[c].right = gdk_keyval_from_name(v);
1090: snprintf(buf, sizeof(buf), "key%d_start", c + 1);
1091: v = gtkopts_getvalue(buf);
1092: ui_cont[c].start = gdk_keyval_from_name(v);
1093: }
1094: if (ui_screenmode != old_ui_screenmode ||
1095: ui_hborder != old_ui_hborder ||
1096: ui_vborder != old_ui_vborder || ui_statusbar != old_ui_statusbar)
1097: ui_gtk_sizechange();
1098:
1099: if (sound_minfields != old_sound_minfields ||
1100: sound_maxfields != old_sound_maxfields) {
1101: sound_reset();
1102: }
1103: }
1104:
1105: static void ui_gtk_opts_from_window(void)
1106: {
1107: GtkWidget *obj, *active;
1108: char buf[64];
1109: int c;
1110: const char *v;
1111: const char **key;
1112:
1113: /* hardware - region */
1114:
1115: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1116: "radiobutton_domestic"));
1117: if (GTK_TOGGLE_BUTTON(obj)->active)
1118: gtkopts_setvalue("region", "domestic");
1119: else
1120: gtkopts_setvalue("region", "overseas");
1121:
1122: /* hardware - video standard */
1123:
1124: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1125: "radiobutton_pal"));
1126: if (GTK_TOGGLE_BUTTON(obj)->active)
1127: gtkopts_setvalue("videostd", "pal");
1128: else
1129: gtkopts_setvalue("videostd", "ntsc");
1130:
1131: /* hardware - auto detect */
1132:
1133: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1134: "checkbutton_autodetect"));
1135: if (GTK_TOGGLE_BUTTON(obj)->active)
1136: gtkopts_setvalue("autodetect", "on");
1137: else
1138: gtkopts_setvalue("autodetect", "off");
1139:
1140: /* video - plotter */
1141:
1142: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1143: "radiobutton_line"));
1144: if (GTK_TOGGLE_BUTTON(obj)->active)
1145: gtkopts_setvalue("plotter", "line");
1146: else
1147: gtkopts_setvalue("plotter", "cell");
1148:
1149: /* video - interlace mode */
1150:
1151: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1152: "optionmenu_interlace"));
1153: /* now get active widget on menu */
1154: obj = GTK_BIN(GTK_OPTION_MENU(obj))->child;
1155: gtkopts_setvalue("interlace", GTK_LABEL(obj)->label);
1156:
1157: /* video - frame skip */
1158:
1159: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1160: "checkbutton_auto"));
1161: if (GTK_TOGGLE_BUTTON(obj)->active) {
1162: gtkopts_setvalue("frameskip", "auto");
1163: } else {
1164: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1165: "hscale_skip"));
1166: snprintf(buf, sizeof(buf), "%d",
1167: (int)(gtk_range_get_adjustment(GTK_RANGE(obj))->value));
1168: gtkopts_setvalue("frameskip", buf);
1169: }
1170:
1171: /* video - hborder */
1172:
1173: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1174: "spinbutton_hborder"));
1175: snprintf(buf, sizeof(buf), "%d",
1176: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
1177: gtkopts_setvalue("hborder", buf);
1178:
1179: /* video - vborder */
1180:
1181: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1182: "spinbutton_vborder"));
1183: snprintf(buf, sizeof(buf), "%d",
1184: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
1185: gtkopts_setvalue("vborder", buf);
1186:
1187: /* sound - z80 */
1188:
1189: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1190: "checkbutton_z80"));
1191: if (GTK_TOGGLE_BUTTON(obj)->active)
1192: gtkopts_setvalue("z80", "on");
1193: else
1194: gtkopts_setvalue("z80", "off");
1195:
1196: /* sound - on/off */
1197:
1198: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1199: "checkbutton_sound"));
1200: if (GTK_TOGGLE_BUTTON(obj)->active)
1201: gtkopts_setvalue("sound", "on");
1202: else
1203: gtkopts_setvalue("sound", "off");
1204:
1205: /* sound - psg */
1206:
1207: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1208: "checkbutton_psg"));
1209: if (GTK_TOGGLE_BUTTON(obj)->active)
1210: gtkopts_setvalue("psg", "on");
1211: else
1212: gtkopts_setvalue("psg", "off");
1213:
1214: /* sound - fm */
1215:
1216: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1217: "checkbutton_fm"));
1218: if (GTK_TOGGLE_BUTTON(obj)->active)
1219: gtkopts_setvalue("fm", "on");
1220: else
1221: gtkopts_setvalue("fm", "off");
1222:
1223: /* sound - min fields */
1224:
1225: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1226: "spinbutton_minfields"));
1227: snprintf(buf, sizeof(buf), "%d",
1228: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
1229: gtkopts_setvalue("sound_minfields", buf);
1230:
1231: /* sound - min fields */
1232:
1233: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1234: "spinbutton_maxfields"));
1235: snprintf(buf, sizeof(buf), "%d",
1236: gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
1237: gtkopts_setvalue("sound_maxfields", buf);
1238:
1239: /* info - verbosity */
1240:
1241: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1242: "optionmenu_level"));
1243: obj = GTK_OPTION_MENU(obj)->menu;
1244: /* now get active widget on menu */
1245: active = gtk_menu_get_active(GTK_MENU(obj));
1246: snprintf(buf, sizeof(buf), "%d",
1247: g_list_index(GTK_MENU_SHELL(obj)->children, active));
1248: gtkopts_setvalue("loglevel", buf);
1249:
1250: /* info - sound */
1251:
1252: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1253: "checkbutton_debugsound"));
1254: if (GTK_TOGGLE_BUTTON(obj)->active)
1255: gtkopts_setvalue("debugsound", "on");
1256: else
1257: gtkopts_setvalue("debugsound", "off");
1258:
1259: /* info - status bar */
1260: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1261: "checkbutton_statusbar"));
1262: if (GTK_TOGGLE_BUTTON(obj)->active)
1263: gtkopts_setvalue("statusbar", "on");
1264: else
1265: gtkopts_setvalue("statusbar", "off");
1266:
1267: /* controls */
1268:
1269: for (c = 1; c <= 2; c++) {
1270: for (key = ui_gtk_keys;
1271: (char *)key < ((char *)ui_gtk_keys + sizeof(ui_gtk_keys));
1272: key++) {
1273: snprintf(buf, sizeof(buf), "entry_player%d_%s", c, *key);
1274: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts), buf));
1275: v = gtk_entry_get_text(GTK_ENTRY(obj));
1276: snprintf(buf, sizeof(buf), "key%d_%s", c, *key);
1277: gtkopts_setvalue(buf, v);
1278: }
1279: }
1280: }
1281:
1282: static void ui_gtk_opts_to_window(void)
1283: {
1284: GtkWidget *obj;
1285: const char *v;
1286: const char **key;
1287: int i, c;
1288: char buf[32];
1289:
1290: /* hardware - region */
1291:
1292: v = gtkopts_getvalue("region");
1293: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1294: "radiobutton_domestic"));
1295: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1296: !strcasecmp(v, "domestic"));
1297: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1298: "radiobutton_overseas"));
1299: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1300: !strcasecmp(v, "overseas"));
1301:
1302: /* hardware - video standard */
1303:
1304: v = gtkopts_getvalue("videostd");
1305: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1306: "radiobutton_pal"));
1307: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "pal"));
1308: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1309: "radiobutton_ntsc"));
1310: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1311: !strcasecmp(v, "ntsc"));
1312:
1313: /* hardware - auto detect */
1314:
1315: v = gtkopts_getvalue("autodetect");
1316: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1317: "checkbutton_autodetect"));
1318: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1319:
1320: /* video - plotter */
1321:
1322: v = gtkopts_getvalue("plotter");
1323: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1324: "radiobutton_line"));
1325: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1326: !strcasecmp(v, "line"));
1327: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1328: "radiobutton_cell"));
1329: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1330: !strcasecmp(v, "cell"));
1331:
1332: /* video - interlace mode */
1333:
1334: v = gtkopts_getvalue("interlace");
1335: if (!strcasecmp(v, "bob")) {
1336: i = 0;
1337: } else if (!strcasecmp(v, "weave")) {
1338: i = 1;
1339: } else {
1340: i = 2;
1341: }
1342: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1343: "optionmenu_interlace"));
1344: gtk_option_menu_set_history(GTK_OPTION_MENU(obj), i);
1345:
1346: /* video - frame skip */
1347:
1348: v = gtkopts_getvalue("frameskip");
1349: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1350: "checkbutton_auto"));
1351: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
1352: !strcasecmp(v, "auto"));
1353: i = atoi(v);
1354: if (i < 1)
1355: i = 1;
1356: if (i > 10)
1357: i = 10;
1358: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1359: "hscale_skip"));
1360: gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(obj)), i);
1361:
1362: /* video - hborder */
1363:
1364: v = gtkopts_getvalue("hborder");
1365: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1366: "spinbutton_hborder"));
1367: i = atoi(v);
1368: if (i < 0)
1369: i = 0;
1370: if (i > HBORDER_MAX)
1371: i = HBORDER_MAX;
1372: gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
1373:
1374: /* video - vborder */
1375:
1376: v = gtkopts_getvalue("vborder");
1377: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1378: "spinbutton_vborder"));
1379: i = atoi(v);
1380: if (i < 0)
1381: i = 0;
1382: if (i > VBORDER_MAX)
1383: i = VBORDER_MAX;
1384: gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
1385:
1386: /* sound - z80 */
1387:
1388: v = gtkopts_getvalue("z80");
1389: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1390: "checkbutton_z80"));
1391: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1392:
1393: /* sound - on/off */
1394:
1395: v = gtkopts_getvalue("sound");
1396: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1397: "checkbutton_sound"));
1398: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1399:
1400: /* sound - psg */
1401:
1402: v = gtkopts_getvalue("psg");
1403: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1404: "checkbutton_psg"));
1405: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1406:
1407: /* sound - fm */
1408:
1409: v = gtkopts_getvalue("fm");
1410: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1411: "checkbutton_fm"));
1412: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1413:
1414: /* sound - min fields */
1415:
1416: v = gtkopts_getvalue("sound_minfields");
1417: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1418: "spinbutton_minfields"));
1419: i = atoi(v);
1420: if (i < 1)
1421: i = 1;
1422: gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
1423:
1424: /* sound - max fields */
1425:
1426: v = gtkopts_getvalue("sound_maxfields");
1427: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1428: "spinbutton_maxfields"));
1429: i = atoi(v);
1430: if (i < 1)
1431: i = 1;
1432: gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
1433:
1434: /* info - verbosity */
1435:
1436: v = gtkopts_getvalue("loglevel");
1437: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1438: "optionmenu_level"));
1439: i = atoi(v);
1440: gtk_option_menu_set_history(GTK_OPTION_MENU(obj), i);
1441:
1442: /* info - sound */
1443:
1444: v = gtkopts_getvalue("debugsound");
1445: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1446: "checkbutton_debugsound"));
1447: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1448:
1449: /* info - status bar */
1450:
1451: v = gtkopts_getvalue("statusbar");
1452: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
1453: "checkbutton_statusbar"));
1454: gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
1455:
1456: /* controls */
1457:
1458: for (c = 1; c <= 2; c++) {
1459: for (key = ui_gtk_keys;
1460: (char *)key < ((char *)ui_gtk_keys + sizeof(ui_gtk_keys));
1461: key++) {
1462: snprintf(buf, sizeof(buf), "key%d_%s", c, *key);
1463: v = gtkopts_getvalue(buf);
1464: i = gdk_keyval_from_name(v);
1465: if (i) {
1466: v = gdk_keyval_name(i); /* just incase case is different etc. */
1467: } else {
1468: v = "";
1469: }
1470: snprintf(buf, sizeof(buf), "entry_player%d_%s", c, *key);
1471: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts), buf));
1472: gtk_entry_set_text(GTK_ENTRY(obj), v);
1473: }
1474: }
1475: }
1476:
1477: void ui_gtk_applyoptions(void)
1478: {
1479: ui_gtk_opts_from_window();
1480: gtk_widget_hide(ui_win_opts);
1481: ui_gtk_newoptions();
1482: ui_gtk_opts_to_menu();
1483: }
1484:
1485: void ui_gtk_saveoptions(void)
1486: {
1487: char buf[256];
1488:
1489: ui_gtk_opts_from_window();
1490: if (gtkopts_save(ui_configfile) != 0) {
1491: snprintf(buf, sizeof(buf), "Failed to save configuration to '%s': %s",
1492: ui_configfile, strerror(errno));
1493: ui_gtk_dialog(buf);
1494: return;
1495: }
1496: gtk_widget_hide(ui_win_opts);
1497: ui_gtk_newoptions();
1498: ui_gtk_opts_to_menu();
1499: }
1500:
1501: void ui_gtk_redraw(void)
1502: {
1503: SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
1504: }
1505:
1506: void ui_gtk_key(unsigned long key, int press)
1507: {
1508: t_gtkkeys *cont;
1509: int c;
1510:
1511: for (c = 0; c < 2; c++) {
1512: cont = &ui_cont[c];
1513: if (key == cont->a) {
1514: mem68k_cont[c].a = press;
1515: } else if (key == cont->b) {
1516: mem68k_cont[c].b = press;
1517: } else if (key == cont->c) {
1518: mem68k_cont[c].c = press;
1519: } else if (key == cont->left) {
1520: mem68k_cont[c].left = press;
1521: } else if (key == cont->right) {
1522: mem68k_cont[c].right = press;
1523: } else if (key == cont->up) {
1524: mem68k_cont[c].up = press;
1525: } else if (key == cont->down) {
1526: mem68k_cont[c].down = press;
1527: } else if (key == cont->start) {
1528: mem68k_cont[c].start = press;
1529: }
1530: }
1531: }
1532:
1533: void ui_gtk_mainenter(void)
1534: {
1535: /* clear out current state */
1536: memset(mem68k_cont, 0, sizeof(mem68k_cont));
1537: XAutoRepeatOff(GDK_DISPLAY());
1538: }
1539:
1540: void ui_gtk_mainleave(void)
1541: {
1542: XAutoRepeatOn(GDK_DISPLAY());
1543: }
1544:
1545: static void ui_gtk_opts_to_menu(void)
1546: {
1547: GtkWidget *obj;
1548: const char *v;
1549:
1550: /* view */
1551:
1552: v = gtkopts_getvalue("view");
1553: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "_100"));
1554: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(obj),
1555: !strcasecmp(v, "100"));
1556: obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "_200"));
1557: gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(obj),
1558: !strcasecmp(v, "200"));
1559: }
1560:
1561: void ui_musiclog(uint8 *data, unsigned int length)
1562: {
1563: if (ui_musicfile != -1)
1564: write(ui_musicfile, data, length);
1565: }
1566:
1567: void ui_gtk_closemusiclog(void)
1568: {
1569: if (ui_musicfile == -1) {
1570: ui_gtk_dialog("There is no log to close");
1571: return;
1572: }
1573: close(ui_musicfile);
1574: ui_musicfile = -1;
1575: gen_musiclog = 0;
1576: }
This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.