Annotation of generator/main/ui-gtk.c, revision 1.1

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: }

unix.superglobalmegacorp.com

This archive runs on limited infrastructure. Preserving old code on modern bandwidth. Automated agents are requested to crawl responsibly.