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

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: #include "SDL.h"
                     19: 
                     20: #include "generator.h"
                     21: #include "snprintf.h"
                     22: 
                     23: #include "glade/interface.h"
                     24: #include "glade/support.h"
                     25: 
                     26: #include "ui.h"
                     27: #include "ui-gtk.h"
                     28: #include "uiplot.h"
                     29: #include "gtkopts.h"
                     30: 
                     31: #include "vdp.h"
                     32: #include "gensound.h"
                     33: #include "cpu68k.h"
                     34: #include "mem68k.h"
                     35: #include "cpuz80.h"
                     36: #include "event.h"
                     37: #include "state.h"
                     38: #include "initcart.h"
1.1.1.2 ! root       39: #include "patch.h"
        !            40: #include "dib.h"
        !            41: #include "avi.h"
1.1       root       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: 
1.1.1.2 ! root       55: #define DISSWIN_MAX 64
        !            56: 
1.1       root       57: typedef struct {
                     58:   unsigned int a;
                     59:   unsigned int b;
                     60:   unsigned int c;
                     61:   unsigned int up;
                     62:   unsigned int down;
                     63:   unsigned int left;
                     64:   unsigned int right;
                     65:   unsigned int start;
                     66: } t_gtkkeys;
                     67: 
                     68: const char *ui_gtk_keys[] = {
                     69:   "a", "b", "c", "start", "left", "right", "up", "down"
                     70: };
                     71: 
                     72: /*** static variables ***/
                     73: 
                     74: static SDL_Surface *screen = NULL;      /* SDL screen */
                     75: 
                     76: static char *ui_initload = NULL;        /* filename to load on init */
                     77: static char *ui_configfile = NULL;      /* configuration file */
                     78: static uint8 ui_plotfield = 0;  /* flag indicating plotting this field */
                     79: static uint8 ui_vdpsimple = 0;  /* 0=raster, 1=cell based plotter */
                     80: static int ui_running = 0;      /* running a game */
                     81: static GtkWidget *ui_win_main;  /* main window */
                     82: static GtkWidget *ui_win_about; /* about window */
                     83: static GtkWidget *ui_win_console;       /* console window */
                     84: static GtkWidget *ui_win_opts;  /* options window */
1.1.1.2 ! root       85: static GtkWidget *ui_win_codes; /* game genie codes window */
1.1       root       86: static GtkWidget *ui_win_filesel;       /* file selection window */
                     87: static int ui_filesel_type;     /* selection type: 0=rom, 1=state */
                     88: static int ui_filesel_save;     /* 0=load, 1=save */
                     89: static GtkWidget *ui_gtk_dialog(const char *msg);
                     90: static uint8 ui_frameskip = 0;  /* 0 for dynamic */
                     91: static uint8 ui_actualskip = 0; /* the last skip we did (1..) */
                     92: static uint8 ui_statusbar = 1;  /* status-bar? */
                     93: static uint8 ui_screen[3][4 * HMAXSIZE * VMAXSIZE];     /* screen buffers */
                     94: static uint8 *ui_screen0;       /* pointer to screen block for bank 0 */
                     95: static uint8 *ui_screen1;       /* pointer to screen block for bank 1 */
                     96: static uint8 *ui_newscreen;     /* pointer to new screen block */
                     97: static int ui_whichbank;        /* current viewed screen */
                     98: static int ui_locksurface;      /* lock SDL surface? */
                     99: static unsigned int ui_hborder = HBORDER_DEFAULT;       /* horizontal border */
                    100: static unsigned int ui_vborder = VBORDER_DEFAULT;       /* vertical border */
                    101: static int ui_query_response = -1; /* query response */
1.1.1.2 ! root      102: static t_gtkkeys ui_cont[2];    /* keyboard key codes */
1.1       root      103: static int ui_musicfile = -1;   /* fd of output file for GYM/GNM logging */
1.1.1.2 ! root      104: static int ui_joysticks = 0;    /* number of joysticks */
        !           105: static SDL_Joystick *js_handle[2] = { NULL, NULL };     /* SDL handles */
        !           106: static t_aviinfo ui_aviinfo;    /* AVI information */
        !           107: static t_avi *ui_avi = NULL;    /* Current AVI writer if applicable */
        !           108: static uint8 *ui_avivideo;      /* video buffer */
        !           109: static uint8 *ui_aviaudio;      /* audio buffer */
        !           110: static GtkWidget *ui_disswins[DISSWIN_MAX];     /* disassembly windows */
        !           111: static GdkFont *ui_dissfont;    /* disassembly window font */
1.1       root      112: 
                    113: static enum {
                    114:   SCREEN_100, SCREEN_200, SCREEN_FULL
                    115: } ui_screenmode = SCREEN_100;
                    116: 
                    117: t_interlace ui_interlace = DEINTERLACE_WEAVEFILTER;
                    118: 
                    119: /*** Forward references ***/
                    120: 
                    121: static void ui_usage(void);
                    122: static void ui_gtk_filesel_ok(GtkFileSelection * obj, gpointer user_data);
                    123: static void ui_gtk_sizechange(void);
                    124: static void ui_newframe(void);
                    125: static void ui_rendertoscreen(void);
                    126: static gint ui_gtk_configuremain(GtkWidget * widget,
                    127:                                  GdkEventConfigure * event);
                    128: static int ui_topbit(unsigned long int bits);
                    129: static void ui_gtk_opts_to_window(void);
                    130: static void ui_gtk_opts_from_window(void);
                    131: static int ui_gtk_query(const char *msg, int style);
                    132: static void ui_gtk_opts_to_menu(void);
                    133: static void ui_simpleplot(void);
1.1.1.2 ! root      134: static void ui_sdl_events(void);
1.1       root      135: 
                    136: /*** Program entry point ***/
                    137: 
                    138: int ui_init(int argc, char *argv[])
                    139: {
1.1.1.2 ! root      140:   int ch;
1.1       root      141:   GtkWidget *button, *draw, *obj;
                    142:   struct passwd *passwd;
                    143:   struct stat statbuf;
1.1.1.2 ! root      144:   int i;
        !           145:   const char *name;
1.1       root      146: 
                    147:   gtk_set_locale();
                    148:   gtk_init(&argc, &argv);
                    149: 
1.1.1.2 ! root      150:   fprintf(stderr, "Generator is (c) James Ponder 1997-2003, all rights "
        !           151:           "reserved. v" VERSION "\n\n");
        !           152: 
1.1       root      153:   while ((ch = getopt(argc, argv, "?dc:w:")) != -1) {
                    154:     switch (ch) {
                    155:     case 'd':                  /* turn on debug mode */
                    156:       gen_debugmode = 1;
                    157:       break;
                    158:     case 'c':                  /* configuration file */
                    159:       ui_configfile = optarg;
                    160:       break;
                    161:     case 'w':                  /* saved game work dir */
                    162:       chdir(optarg);            /* for the moment this will do */
                    163:       break;
                    164:     case '?':
                    165:     default:
                    166:       ui_usage();
                    167:     }
                    168:   }
                    169:   argc -= optind;
                    170:   argv += optind;
                    171: 
                    172:   if (argc > 0) {
                    173:     ui_initload = argv[0];
                    174:     argc--;
                    175:     argv++;
                    176:   }
                    177: 
                    178:   if (argc != 0)
                    179:     ui_usage();
                    180: 
                    181:   if (ui_configfile == NULL) {
                    182:     if ((passwd = getpwuid(getuid())) == NULL) {
                    183:       fprintf(stderr, "Who are you? (getpwent failed)\n");
                    184:       exit(1);
                    185:     }
                    186:     ui_configfile = malloc(strlen(passwd->pw_dir) + sizeof("/.genrc"));
                    187:     sprintf(ui_configfile, "%s/.genrc", passwd->pw_dir);
                    188:   }
                    189:   if (stat(ui_configfile, &statbuf) != 0) {
                    190:     fprintf(stderr, "No configuration file found, using defaults.\n");
                    191:   } else {
                    192:     if (gtkopts_load(ui_configfile) != 0)
                    193:       fprintf(stderr, "Error loading configuration file, using defaults.\n");
                    194:   }
                    195: 
                    196:   /* create gtk windows */
                    197: 
                    198:   ui_win_main = create_mainwin();
                    199:   ui_win_about = create_about();
                    200:   ui_win_console = create_console();
                    201:   ui_win_opts = create_opts();
1.1.1.2 ! root      202:   ui_win_codes = create_codes();
1.1       root      203:   ui_win_filesel = gtk_file_selection_new("Select file...");
                    204:   button = GTK_FILE_SELECTION(ui_win_filesel)->ok_button;
                    205:   gtk_signal_connect(GTK_OBJECT(button), "clicked",
                    206:                      GTK_SIGNAL_FUNC(ui_gtk_filesel_ok), NULL);
                    207:   button = GTK_FILE_SELECTION(ui_win_filesel)->cancel_button;
                    208:   gtk_signal_connect_object(GTK_OBJECT(button), "clicked",
                    209:                             GTK_SIGNAL_FUNC(gtk_widget_hide),
                    210:                             GTK_OBJECT(ui_win_filesel));
                    211: 
1.1.1.2 ! root      212:   /* load our font */
        !           213:   ui_dissfont = gdk_font_load
        !           214:       ("-*-fixed-medium-r-normal-*-*-*-*-*-*-80-iso8859-1");
        !           215:   gdk_font_ref(ui_dissfont);
        !           216:  
        !           217:   /* set codes window so that code list is reorderable */
        !           218: 
        !           219:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !           220:                                        "clist_codes"));
        !           221:   gtk_clist_set_reorderable(GTK_CLIST(obj), 1);
        !           222: 
1.1       root      223:   /* open main window */
                    224: 
                    225:   gtk_widget_add_events(ui_win_main, GDK_KEY_RELEASE_MASK);
                    226:   gtk_window_set_title(GTK_WINDOW(ui_win_main), "Generator/gtk " VERSION);
                    227:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "debug"));
                    228:   if (!gen_debugmode)
                    229:     gtk_widget_hide(obj);
                    230:   gtk_widget_show(ui_win_main);
                    231:   draw = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
                    232:                                         "drawingarea_main"));
                    233:   gtk_signal_connect(GTK_OBJECT(ui_win_main), "configure_event",
                    234:                      GTK_SIGNAL_FUNC(ui_gtk_configuremain), 0);
                    235:   {
                    236:     char SDL_windowhack[32];
                    237:     snprintf(SDL_windowhack, sizeof(SDL_windowhack), "SDL_WINDOWID=%ld",
                    238:              GDK_WINDOW_XWINDOW(draw->window));
                    239:     putenv(SDL_windowhack);
                    240:   }
1.1.1.2 ! root      241:   if (SDL_Init(SDL_INIT_VIDEO|SDL_INIT_JOYSTICK) < 0) {
1.1       root      242:     fprintf(stderr, "Couldn't initialise SDL: %s\n", SDL_GetError());
                    243:     return -1;
                    244:   }
1.1.1.2 ! root      245:   ui_joysticks = SDL_NumJoysticks();
        !           246:   /* Print information about the joysticks */
        !           247:   fprintf(stderr, "%d joysticks detected\n", ui_joysticks);
        !           248:   for (i = 0; i < ui_joysticks; i++) {
        !           249:     name = SDL_JoystickName(i);
        !           250:     fprintf(stderr, "Joystick %d: %s\n", i,
        !           251:                     name ? name : "Unknown Joystick");
        !           252:   }
        !           253:   js_handle[0] = SDL_JoystickOpen(0);
        !           254:   js_handle[1] = SDL_JoystickOpen(1);
        !           255:   SDL_JoystickEventState(SDL_ENABLE);
        !           256: 
1.1       root      257:   ui_gtk_sizechange();
                    258:   ui_gtk_newoptions();
                    259:   ui_gtk_opts_to_menu();
                    260: 
                    261:   /* ui_newscreen is where the emulation data is rendered to - it is
                    262:      then compared with ui_screen0 or ui_screen1 depending on which
                    263:      screen bank it is being written to, and the delta changes are sent
                    264:      to screen memory.  The ui_screenX and ui_newscreen pointers are then
                    265:      switched, and the next frame/field begins... */
                    266:   memset(ui_screen[0], 0, sizeof(ui_screen[0]));
                    267:   memset(ui_screen[1], 0, sizeof(ui_screen[1]));
                    268:   ui_screen0 = ui_screen[0];
                    269:   ui_screen1 = ui_screen[1];
                    270:   ui_newscreen = ui_screen[2];
                    271:   ui_whichbank = 0;             /* viewing 0 */
1.1.1.2 ! root      272:   fprintf(stderr, "Please use the GTK menu to quit this program properly.\n");
1.1       root      273:   return 0;
                    274: }
                    275: 
                    276: static void ui_usage(void)
                    277: {
                    278:   fprintf(stderr, "generator [options] [<rom>]\n\n");
                    279:   fprintf(stderr, "  -d                     debug mode\n");
                    280:   fprintf(stderr, "  -w <work dir>          set work directory\n");
                    281:   fprintf(stderr, "  -c <config file>       use alternative config file\n\n");
                    282:   fprintf(stderr, "  ROM types supported: .rom or .smd interleaved "
                    283:           "(autodetected)\n");
                    284:   exit(1);
                    285: }
                    286: 
                    287: void ui_final(void)
                    288: {
1.1.1.2 ! root      289:   gdk_font_unref(ui_dissfont);
        !           290:   gdk_key_repeat_restore();
1.1       root      291:   SDL_Quit();
1.1.1.2 ! root      292:   gtk_exit(0);
1.1       root      293: }
                    294: 
                    295: int ui_loop(void)
                    296: {
                    297:   char *p;
                    298: 
                    299:   if (ui_initload) {
                    300:     p = gen_loadimage(ui_initload);
                    301:     if (p)
                    302:       ui_gtk_dialog(p);
                    303:   } else {
                    304:     gen_loadmemrom(initcart, initcart_len);
                    305:   }
                    306:   while (!gen_quit) {
                    307:     if (ui_running) {
                    308:       while (gtk_events_pending())
                    309:         gtk_main_iteration_do(0);
1.1.1.2 ! root      310:       ui_sdl_events();
1.1       root      311:       ui_newframe();
                    312:       event_doframe();
                    313:     } else {
                    314:       gtk_main();
                    315:     }
                    316:   }
                    317:   return 0;
                    318: }
                    319: 
                    320: void ui_newframe(void)
                    321: {
                    322:   static int vmode = -1;
                    323:   static int pal = -1;
                    324:   static int skipcount = 0;
                    325:   static char frameplots[60];   /* 60 for NTSC, 50 for PAL */
                    326:   static unsigned int frameplots_i = 0;
                    327:   unsigned int i;
                    328:   int fps;
                    329:   char fps_string[8];
                    330:   GtkWidget *entry_fps;
                    331:   static int lasttype = -1;
                    332: 
                    333:   if (frameplots_i > vdp_framerate)
                    334:     frameplots_i = 0;
                    335:   if (((vdp_reg[12] >> 1) & 3) && vdp_oddframe) {
                    336:     /* interlace mode, and we're about to do an odd field - we always leave
                    337:        ui_plotfield alone so we do fields in pairs, this stablises the
                    338:        display, reduces blurring */
                    339:   } else {
                    340:     ui_plotfield = 0;
                    341:     if (ui_frameskip == 0) {
                    342:       if (sound_feedback != -1)
                    343:         ui_plotfield = 1;
                    344:     } else {
                    345:       if (cpu68k_frames % ui_frameskip == 0)
                    346:         ui_plotfield = 1;
                    347:     }
                    348:   }
                    349:   if (!ui_plotfield) {
                    350:     skipcount++;
                    351:     frameplots[frameplots_i++] = 0;
                    352:     return;
                    353:   }
                    354:   lasttype = vdp_oddframe;
                    355:   /* check for ROM or user changing the vertical size */
                    356:   if (vmode == (int)(vdp_reg[1] & (1 << 3)) || pal != (int)vdp_pal) {
                    357:     vdp_setupvideo();
                    358:     vmode = vdp_reg[1] & (1 << 3);
                    359:     pal = vdp_pal;
                    360:   }
                    361:   /* count the frames we've plotted in the last vdp_framerate real frames */
                    362:   fps = 0;
                    363:   for (i = 0; i < vdp_framerate; i++) {
                    364:     if (frameplots[i])
                    365:       fps++;
                    366:   }
                    367:   frameplots[frameplots_i++] = 1;
                    368:   if (!ui_statusbar)
                    369:     return;
                    370:   snprintf(fps_string, sizeof(fps_string), "%d", fps);
                    371:   entry_fps = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
                    372:                                              "entry_fps"));
                    373:   gtk_entry_set_text(GTK_ENTRY(entry_fps), fps_string);
                    374:   skipcount = 0;
                    375: }
                    376: 
                    377: /* ui_line is called for all vdp_totlines but is offset so that line=0
                    378:    is the first line, line=(vdp_totlines-vdp_visstartline)-1 is the
                    379:    last */
                    380: 
                    381: void ui_line(int line)
                    382: {
                    383:   static uint8 gfx[320];
                    384:   unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
                    385:   unsigned int offset = ui_hborder + ((vdp_reg[12] & 1) ? 0 : 32);
                    386:   uint8 bg;
                    387:   uint32 bgpix;
                    388:   uint8 *location;
                    389:   unsigned int i;
                    390: 
                    391:   if (!ui_plotfield)
                    392:     return;
                    393:   if (ui_vdpsimple) {
                    394:     if (line == (int)(vdp_vislines >> 1))
                    395:       /* if we're in simple cell-based mode, plot when half way down screen */
                    396:       ui_simpleplot();
                    397:     return;
                    398:   }
                    399:   if (line < -(int)ui_vborder || line >= (int)(vdp_vislines + ui_vborder))
                    400:     return;
                    401: 
                    402:   bg = (vdp_reg[7] & 63);
                    403:   uiplot_checkpalcache(0);
                    404:   bgpix = uiplot_palcache[bg];
                    405:   location = ui_newscreen +
                    406:     (line + ui_vborder) * HMAXSIZE * screen->format->BytesPerPixel;
                    407:   if (line < 0 || line >= (int)vdp_vislines) {
                    408:     /* in border */
                    409:     switch (screen->format->BytesPerPixel) {
                    410:     case 2:
                    411:       for (i = 0; i < HSIZE; i++) {
                    412:         ((uint16 *)location)[i] = bgpix;
                    413:       }
                    414:       break;
                    415:     case 4:
                    416:       for (i = 0; i < HSIZE; i++) {
                    417:         ((uint32 *)location)[i] = bgpix;
                    418:       }
                    419:       break;
                    420:     }
                    421:     return;
                    422:   }
                    423:   /* normal line */
                    424:   switch ((vdp_reg[12] >> 1) & 3) {
                    425:   case 0:                      /* normal */
                    426:   case 1:                      /* interlace simply doubled up */
                    427:   case 2:                      /* invalid */
                    428:     vdp_renderline(line, gfx, 0);
                    429:     break;
                    430:   case 3:                      /* interlace with double resolution */
                    431:     vdp_renderline(line, gfx, vdp_oddframe);
                    432:     break;
                    433:   }
                    434:   switch (screen->format->BytesPerPixel) {
                    435:   case 2:
                    436:     uiplot_convertdata16(gfx, ((uint16 *)location) + offset, width);
                    437:     for (i = 0; i < offset; i++) {
                    438:       ((uint16 *)location)[i] = bgpix;
                    439:       ((uint16 *)location)[i + offset + width] = bgpix;
                    440:     }
                    441:     break;
                    442:   case 4:
                    443:     uiplot_convertdata32(gfx, ((uint32 *)location) + offset, width);
                    444:     for (i = 0; i < offset; i++) {
                    445:       ((uint32 *)location)[i] = bgpix;
                    446:       ((uint32 *)location)[i + offset + width] = bgpix;
                    447:     }
                    448:     break;
                    449:   }
                    450: }
                    451: 
                    452: static void ui_simpleplot(void)
                    453: {
                    454:   static uint8 gfx[(320 + 16) * (240 + 16)];
                    455:   unsigned int width = (vdp_reg[12] & 1) ? 320 : 256;
                    456:   unsigned int offset = ui_hborder + ((vdp_reg[12] & 1) ? 0 : 32);
                    457:   unsigned int line, i;
                    458:   uint8 *location, *location2;
                    459:   uint8 bg;
                    460:   uint32 bgpix;
                    461:   /* cell mode - entire frame done here */
                    462:   bg = (vdp_reg[7] & 63);
                    463:   uiplot_checkpalcache(0);
                    464:   bgpix = uiplot_palcache[bg];
                    465:   vdp_renderframe(gfx + (8 * (320 + 16)) + 8, 320 + 16);    /* plot frame */
                    466:   location = ui_newscreen +
                    467:       ui_vborder * HMAXSIZE * screen->format->BytesPerPixel;
                    468:   switch (screen->format->BytesPerPixel) {
                    469:   case 2:
                    470:     for (line = 0; line < vdp_vislines; line++) {
                    471:       for (i = 0; i < offset; i++) {
                    472:         ((uint16 *)location)[i] = bgpix;
                    473:         ((uint16 *)location)[width + offset + i] = bgpix;
                    474:       }
                    475:       uiplot_convertdata16(gfx + 8 + (line + 8) * (320 + 16),
                    476:                            ((uint16 *)location) + offset, width);
                    477:       location += HMAXSIZE * 2;
                    478:     }
                    479:     break;
                    480:   case 4:
                    481:     for (line = 0; line < vdp_vislines; line++) {
                    482:       for (i = 0; i < offset; i++) {
                    483:         ((uint32 *)location)[i] = bgpix;
                    484:         ((uint32 *)location)[width + offset + i] = bgpix;
                    485:       }
                    486:       uiplot_convertdata32(gfx + 8 + (line + 8) * (320 + 16),
                    487:                            ((uint32 *)location) + offset, width);
                    488:       location += HMAXSIZE * 4;
                    489:     }
                    490:     break;
                    491:   }
                    492:   location = ui_newscreen;
                    493:   location2 = ui_newscreen + (ui_vborder + vdp_vislines) *
                    494:       HMAXSIZE * screen->format->BytesPerPixel;
                    495:   switch (screen->format->BytesPerPixel) {
                    496:   case 2:
                    497:     for (line = 0; line < ui_vborder; line++) {
                    498:       for (i = 0; i < HSIZE; i++) {
                    499:         ((uint16 *)location)[i] = bgpix;
                    500:         ((uint16 *)location2)[i] = bgpix;
                    501:       }
                    502:       location += HMAXSIZE * 2;
                    503:       location2 += HMAXSIZE * 2;
                    504:     }
                    505:     break;
                    506:   case 4:
                    507:     for (line = 0; line < ui_vborder; line++) {
                    508:       for (i = 0; i < HSIZE; i++) {
                    509:         ((uint32 *)location)[i] = bgpix;
                    510:         ((uint32 *)location2)[i] = bgpix;
                    511:       }
                    512:       location += HMAXSIZE * 4;
                    513:       location2 += HMAXSIZE * 4;
                    514:     }
                    515:     break;
                    516:   }
                    517: }
                    518: 
1.1.1.2 ! root      519: static void ui_makeavivideo(void)
        !           520: {
        !           521:   unsigned int line;
        !           522:   SDL_PixelFormat *f = screen->format;
        !           523:   uint8 *linep = ui_newscreen;
        !           524:   uint8 *video;
        !           525:   uint32 c;
        !           526:   unsigned int x;
        !           527: 
        !           528:   video = ui_avivideo;
        !           529:   switch (screen->format->BytesPerPixel) {
        !           530:   case 2:
        !           531:     for (line = 0; line < ui_avi->info.height; line++) {
        !           532:       for (x = 0; x < ui_avi->info.width; x++) {
        !           533:         c = ((uint16 *)linep)[x];
        !           534:         *video++ = ((c & f->Rmask) >> f->Rshift) << f->Rloss;
        !           535:         *video++ = ((c & f->Gmask) >> f->Gshift) << f->Gloss;
        !           536:         *video++ = ((c & f->Bmask) >> f->Bshift) << f->Bloss;
        !           537:       }
        !           538:       linep+= (HMAXSIZE * 2);
        !           539:     }
        !           540:     break;
        !           541:   case 4:
        !           542:     for (line = 0; line < ui_avi->info.height; line++) {
        !           543:       for (x = 0; x < ui_avi->info.width; x++) {
        !           544:         c = ((uint32 *)linep)[x];
        !           545:         *video++ = ((c & f->Rmask) >> f->Rshift) << f->Rloss;
        !           546:         *video++ = ((c & f->Gmask) >> f->Gshift) << f->Gloss;
        !           547:         *video++ = ((c & f->Bmask) >> f->Bshift) << f->Bloss;
        !           548:       }
        !           549:       linep+= (HMAXSIZE * 4);
        !           550:     }
        !           551:     break;
        !           552:   }
        !           553:   avi_video(ui_avi, ui_avivideo);
        !           554: }
        !           555: 
        !           556: static void ui_makeaviaudio(void)
        !           557: {
        !           558:   unsigned int i;
        !           559: 
        !           560:   /* 22050 doesn't divide nicely into 60 fields - that means 367.50 samples
        !           561:      per field.  So we need to compensate by adding in a byte every now and
        !           562:      again */
        !           563: 
        !           564:   /* audio buffer gensound_soundbuf is in local endian - avi is little */
        !           565:   for (i = 0; i < sound_sampsperfield; i++) {
        !           566:     ((uint16 *)ui_aviaudio)[i * 2] = LOCENDIAN16L(sound_soundbuf[0][i]);
        !           567:     ((uint16 *)ui_aviaudio)[i * 2 + 1] = LOCENDIAN16L(sound_soundbuf[1][i]);
        !           568:   }
        !           569:   /* duplicate last byte */
        !           570:   ((uint16 *)ui_aviaudio)[i * 2] = LOCENDIAN16L(sound_soundbuf[0][i - 1]);
        !           571:   ((uint16 *)ui_aviaudio)[i * 2 + 1] = LOCENDIAN16L(sound_soundbuf[1][i - 1]);
        !           572: 
        !           573:   /* get partial bytes per second we should be outputting in 1000ths */
        !           574:   ui_avi->error+= (ui_avi->info.sampspersec * 1000 / vdp_framerate) % 1000;
        !           575:   if (ui_avi->error > 1000) {
        !           576:     ui_avi->error-= 1000;
        !           577:     avi_audio(ui_avi, ui_aviaudio, sound_sampsperfield + 1);
        !           578:   } else {
        !           579:     avi_audio(ui_avi, ui_aviaudio, sound_sampsperfield);
        !           580:   }
        !           581: }
        !           582: 
1.1       root      583: /*** ui_endfield - end of field reached ***/
                    584: 
                    585: void ui_endfield(void)
                    586: {
                    587:   static int counter = 0;
                    588: 
1.1.1.2 ! root      589:   if (ui_avi)
        !           590:     ui_makeaviaudio();
        !           591: 
        !           592:   if (ui_plotfield)
1.1       root      593:     ui_rendertoscreen();        /* plot ui_newscreen to screen */
1.1.1.2 ! root      594: 
1.1       root      595:   if (ui_frameskip == 0) {
                    596:     /* dynamic frame skipping */
                    597:     counter++;
                    598:     if (sound_feedback >= 0) {
                    599:       ui_actualskip = counter;
                    600:       counter = 0;
                    601:     }
                    602:   } else {
                    603:     ui_actualskip = ui_frameskip;
                    604:   }
                    605: }
                    606: 
                    607: void ui_rendertoscreen(void)
                    608: {
                    609:   uint8 **oldscreenpp = ui_whichbank ? &ui_screen1 : &ui_screen0;
                    610:   uint8 *scrtmp;
                    611:   uint8 *newlinedata, *oldlinedata;
                    612:   unsigned int line;
                    613:   uint8 *location;
                    614:   uint8 *evenscreen;            /* interlace: lines 0,2,etc. */
                    615:   uint8 *oddscreen;             /*            lines 1,3,etc. */
                    616: 
                    617:   if (ui_locksurface && SDL_LockSurface(screen) != 0)
                    618:     ui_err("Failed to lock SDL surface");
                    619:   for (line = 0; line < VSIZE; line++) {
                    620:     newlinedata = ui_newscreen +
                    621:         line * HMAXSIZE * screen->format->BytesPerPixel;
                    622:     oldlinedata = *oldscreenpp +
                    623:         line * HMAXSIZE * screen->format->BytesPerPixel;
                    624:     switch (ui_screenmode) {
                    625:     case SCREEN_100:
                    626:       location = screen->pixels + line * screen->pitch;
                    627:       /* we could use uiplot_renderXX_x1 routines here, but SDL wouldn't
                    628:          pick up our delta changes so we don't */
                    629:       memcpy(location, newlinedata, HSIZE * screen->format->BytesPerPixel);
                    630:       break;
                    631:     case SCREEN_200:
                    632:       location = screen->pixels + 2 * line * screen->pitch;
                    633:       if (screen->format->BytesPerPixel != 2 &&
                    634:           screen->format->BytesPerPixel != 4)
                    635:         ui_err("unsupported mode for 200%% scaling\n");
                    636:       switch ((vdp_reg[12] >> 1) & 3) { /* interlace mode */
                    637:       case 0:
                    638:       case 1:
                    639:       case 2:
                    640:         switch (screen->format->BytesPerPixel) {
                    641:         case 2:
                    642:           uiplot_render16_x2((uint16 *)newlinedata, NULL, location,
                    643:                              screen->pitch, HSIZE);
                    644:           break;
                    645:         case 4:
                    646:           uiplot_render32_x2((uint32 *)newlinedata, NULL, location,
                    647:                              screen->pitch, HSIZE);
                    648:           break;
                    649:         }
                    650:         break;
                    651:       case 3:
                    652:         /* work out which buffer contains the odd and even fields */
                    653:         if (vdp_oddframe) {
                    654:           oddscreen = ui_newscreen;
                    655:           evenscreen = ui_whichbank ? ui_screen0 : ui_screen1;
                    656:         } else {
                    657:           evenscreen = ui_newscreen;
                    658:           oddscreen = ui_whichbank ? ui_screen0 : ui_screen1;
                    659:         }
                    660:         switch (ui_interlace) {
                    661:         case DEINTERLACE_BOB:
                    662:           switch (screen->format->BytesPerPixel) {
                    663:           case 2:
                    664:             uiplot_render16_x2((uint16 *)newlinedata, NULL, location,
                    665:                                screen->pitch, HSIZE);
                    666:             break;
                    667:           case 4:
                    668:             uiplot_render32_x2((uint32 *)newlinedata, NULL, location,
                    669:                                screen->pitch, HSIZE);
                    670:             break;
                    671:           }
                    672:           break;
                    673:         case DEINTERLACE_WEAVE:
                    674:           evenscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
                    675:           oddscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
                    676:           switch (screen->format->BytesPerPixel) {
                    677:           case 2:
                    678:             uiplot_render16_x2h((uint16 *)evenscreen, NULL, location, HSIZE);
                    679:             uiplot_render16_x2h((uint16 *)oddscreen, NULL,
                    680:                                 location + screen->pitch, HSIZE);
                    681:             break;
                    682:           case 4:
                    683:             uiplot_render32_x2h((uint32 *)evenscreen, NULL, location, HSIZE);
                    684:             uiplot_render32_x2h((uint32 *)oddscreen, NULL,
                    685:                                 location + screen->pitch, HSIZE);
                    686:             break;
                    687:           }
                    688:           break;
                    689:         case DEINTERLACE_WEAVEFILTER:
                    690:           evenscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
                    691:           oddscreen += line * HMAXSIZE * screen->format->BytesPerPixel;
                    692:           switch (screen->format->BytesPerPixel) {
                    693:           case 2:
                    694:             /* lines line+0 and line+1 */
                    695:             uiplot_irender16_weavefilter((uint16 *)evenscreen,
                    696:                                          (uint16 *)oddscreen,
                    697:                                          location, HSIZE);
                    698:             /* lines line+1 and line+2 */
                    699:             uiplot_irender16_weavefilter((uint16 *)oddscreen,
                    700:                                          ((uint16 *)evenscreen) + HMAXSIZE,
                    701:                                          location + screen->pitch, HSIZE);
                    702:             break;
                    703:           case 4:
                    704:             /* lines line+0 and line+1 */
                    705:             uiplot_irender32_weavefilter((uint32 *)evenscreen,
                    706:                                          (uint32 *)oddscreen,
                    707:                                          location, HSIZE);
                    708:             /* lines line+1 and line+2 */
                    709:             uiplot_irender32_weavefilter((uint32 *)oddscreen,
                    710:                                          ((uint32 *)evenscreen) + HMAXSIZE,
                    711:                                          location + screen->pitch, HSIZE);
                    712:             break;
                    713:           }
                    714:         }
                    715:         break;
                    716:       }
                    717:       break;
                    718:     case SCREEN_FULL:
                    719:     default:
                    720:       ui_err("invalid screen mode\n");
                    721:     }
                    722:   }
                    723:   if (ui_locksurface)
                    724:     SDL_UnlockSurface(screen);
                    725:   SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
1.1.1.2 ! root      726:   if (ui_avi)
        !           727:     ui_makeavivideo();
1.1       root      728:   ui_whichbank ^= 1;
                    729: //  if (ui_vsync)
                    730: //    uip_vsync();
                    731:   /* swap ui_screenX and ui_newscreen pointers */
                    732:   scrtmp = *oldscreenpp;
                    733:   *oldscreenpp = ui_newscreen;
                    734:   ui_newscreen = scrtmp;
                    735: }
                    736: 
                    737: /*** logging functions ***/
                    738: 
                    739: /* logging is done this way because this was the best I could come up with
                    740:    whilst battling with macros that can only take fixed numbers of arguments */
                    741: 
                    742: #define LOG_FUNC(name,level,txt) void ui_log_ ## name ## (const char *text, ...) \
                    743: { \
                    744:   va_list ap; \
                    745:   if (gen_loglevel >= level) { \
                    746:     printf("[%s] ", txt); \
                    747:     va_start(ap, text); \
                    748:     vprintf(text, ap); \
                    749:     va_end(ap); \
                    750:     putchar(10); \
                    751:   } \
                    752: }
                    753: 
                    754: /* *INDENT-OFF* */
                    755: 
                    756: LOG_FUNC(debug3,   7, "DEBG ");
                    757: LOG_FUNC(debug2,   6, "DEBG ");
                    758: LOG_FUNC(debug1,   5, "DEBG ");
                    759: LOG_FUNC(user,     4, "USER ");
                    760: LOG_FUNC(verbose,  3, "---- ");
                    761: LOG_FUNC(normal,   2, "---- ");
                    762: LOG_FUNC(critical, 1, "CRIT ");
                    763: LOG_FUNC(request,  0, "---- ");  /* this generates a warning, such is life */
                    764: 
                    765: /* *INDENT-ON* */
                    766: 
                    767: /*** ui_err - log error message and quit ***/
                    768: 
                    769: void ui_err(const char *text, ...)
                    770: {
                    771:   va_list ap;
                    772: 
                    773:   printf("ERROR: ");
                    774: 
                    775:   va_start(ap, text);
                    776:   vfprintf(stderr, text, ap);
                    777:   va_end(ap);
                    778:   putc(10, stderr);
                    779:   exit(0);
                    780: }
                    781: 
                    782: /*** ui_topbit - given an integer return the top most bit set ***/
                    783: 
                    784: int ui_topbit(unsigned long int bits)
                    785: {
                    786:   long int bit = 31;
                    787:   unsigned long int mask = 1 << 31;
                    788: 
                    789:   for (; bit >= 0; bit--, mask >>= 1) {
                    790:     if (bits & mask)
                    791:       return bit;
                    792:   }
                    793:   return -1;
                    794: }
                    795: 
                    796: /*** ui_setinfo - there is new cart information ***/
                    797: 
                    798: char *ui_setinfo(t_cartinfo *cartinfo)
                    799: {
                    800:   (void)cartinfo;
                    801:   return NULL;
                    802: }
                    803: 
                    804: /*** gtk functions ***/
                    805: 
1.1.1.2 ! root      806: gint ui_gtk_configuremain(GtkWidget *widget, GdkEventConfigure *event)
1.1       root      807: {
                    808:   (void)widget;
                    809:   (void)event;
                    810:   /* if we were allowing resizing this is where we'd do it, but note
                    811:      to check whether it's just the location or the size being changed
                    812:      as a call to SDL to set the video mode will erase the screen and
                    813:      then everything would go black */
                    814:   return TRUE;
                    815: }
                    816: 
1.1.1.2 ! root      817: void ui_gtk_filesel_ok(GtkFileSelection *obj, gpointer user_data)
1.1       root      818: {
                    819:   char msg[512];
                    820:   char buf[8];
                    821:   char *file, *p;
                    822:   int fd;
                    823:   struct stat s;
1.1.1.2 ! root      824:   int avi_skip, avi_jpeg;
1.1       root      825: 
                    826:   (void)obj;
                    827:   (void)user_data;
                    828:   file = gtk_file_selection_get_filename(GTK_FILE_SELECTION(ui_win_filesel));
                    829:   gtk_widget_hide(ui_win_filesel);
                    830: 
                    831:   if (ui_filesel_save) {
                    832:     if (stat(file, &s) == 0) {
                    833:       snprintf(msg, sizeof(msg), "The file '%s' already exists - overwrite?",
                    834:                file);
                    835:       if (ui_gtk_query(msg, 0) != 0)
                    836:         return;
                    837:     }
                    838:   }
                    839:   *msg = '\0';
                    840: 
                    841:   switch ((ui_filesel_type << 1) | ui_filesel_save) {
                    842:   case 0:
                    843:     p = gen_loadimage(file);
                    844:     if (p)
                    845:       snprintf(msg, sizeof(msg), "An error occured whilst tring to load "
                    846:                "the ROM '%s': %s", file, p);
                    847:     break;
                    848:   case 1:
                    849:     if (cpu68k_rom == NULL || cpu68k_romlen == 0) {
                    850:       snprintf(msg, sizeof(msg), "There is no ROM currently in memory to "
                    851:                "save!");
                    852:       break;
                    853:     }
1.1.1.2 ! root      854:     if (gen_modifiedrom) {
        !           855:       if (ui_gtk_query("The ROM in memory has been modified by cheat "
        !           856:                        "codes - are you really sure you want to save"
        !           857:                       "this ROM?", 0) != 0)
        !           858:         break;
        !           859:     }
1.1       root      860:     if ((fd = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1
                    861:         || write(fd, cpu68k_rom, cpu68k_romlen) == -1 || close(fd) == -1) {
                    862:       snprintf(msg, sizeof(msg), "An error occured whilst trying to save the "
                    863:                "ROM as '%s': %s", file, strerror(errno));
                    864:     }
                    865:     break;
                    866:   case 2:
                    867:     if (stat(file, &s) != 0) {
                    868:       snprintf(msg, sizeof(msg), "%s: %s", file, strerror(errno));
                    869:       break;
                    870:     }
                    871:     if (state_loadfile(file) != 0)
                    872:       snprintf(msg, sizeof(msg), "An error occured whilst trying to load "
                    873:                "state from '%s': %s", file, strerror(errno));
                    874:     break;
                    875:   case 3:
                    876:     if (state_savefile(file) != 0)
                    877:       snprintf(msg, sizeof(msg), "An error occured whilst trying to save "
                    878:                "state to '%s': %s", file, strerror(errno));
                    879:     break;
                    880:   case 5:
                    881:     if (ui_musicfile != -1) {
                    882:       snprintf(msg, sizeof(msg), "There is already a music log in progress");
                    883:       break;
                    884:     }
                    885:     if ((ui_musicfile = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1) {
                    886:       snprintf(msg, sizeof(msg), "An error occured whilst trying to start "
                    887:                "a GYM log to '%s': %s", file, strerror(errno));
                    888:     }
                    889:     gen_musiclog = 1;
                    890:     break;
                    891:   case 7:
                    892:     if (ui_musicfile != -1) {
                    893:       snprintf(msg, sizeof(msg), "There is already a music log in progress");
                    894:       break;
                    895:     }
                    896:     if ((ui_musicfile = open(file, O_CREAT | O_WRONLY | O_TRUNC, 0777)) == -1) {
                    897:       snprintf(msg, sizeof(msg), "An error occured whilst trying to start "
                    898:                "a GNM log to '%s': %s", file, strerror(errno));
                    899:     }
                    900:     buf[0] = 'G'; buf[1] = 'N'; buf[2] = 'M';
                    901:     buf[3] = vdp_framerate;
                    902:     write(ui_musicfile, buf, 4);
                    903:     gen_musiclog = 2;
                    904:     break;
1.1.1.2 ! root      905:   case 8:
        !           906:     if (stat(file, &s) != 0) {
        !           907:       snprintf(msg, sizeof(msg), "%s: %s", file, strerror(errno));
        !           908:       break;
        !           909:     }
        !           910:     if (patch_loadfile(file) != 0)
        !           911:       snprintf(msg, sizeof(msg), "An error occured whilst trying to load "
        !           912:                "state from '%s': %s", file, strerror(errno));
        !           913:     break;
        !           914:   case 9:
        !           915:     if (patch_savefile(file) != 0)
        !           916:       snprintf(msg, sizeof(msg), "An error occured whilst trying to save "
        !           917:                "state to '%s': %s", file, strerror(errno));
        !           918:     break;
        !           919:   case 11:
        !           920:     if (ui_avi) {
        !           921:       snprintf(msg, sizeof(msg), "There is already an avi in progress");
        !           922:       break;
        !           923:     }
        !           924:     avi_skip = atoi(gtkopts_getvalue("aviframeskip"));
        !           925:     avi_jpeg = !strcasecmp(gtkopts_getvalue("aviformat"), "jpeg");
        !           926:     ui_aviinfo.width = HSIZE;
        !           927:     ui_aviinfo.height = VSIZE;
        !           928:     ui_aviinfo.sampspersec = sound_speed;
        !           929:     ui_aviinfo.fps = (vdp_framerate * 1000) / avi_skip;
        !           930:     ui_aviinfo.jpegquality = atoi(gtkopts_getvalue("jpegquality"));
        !           931:     if ((ui_avi = avi_open(file, &ui_aviinfo, avi_jpeg)) == NULL) {
        !           932:       snprintf(msg, sizeof(msg), "An error occured whilst trying to start "
        !           933:                "the AVI: %s", strerror(errno));
        !           934:       break;
        !           935:     }
        !           936:     if ((ui_aviaudio = malloc((sound_sampsperfield + 1) * 4)) == NULL ||
        !           937:         (ui_avivideo = malloc(ui_avi->linebytes * VSIZE)) == NULL)
        !           938:       ui_err("out of memory");
        !           939:     ui_frameskip = avi_skip;
        !           940:     break;
1.1       root      941:   default:
                    942:     strcpy(msg, "Not implemented.");
                    943:     break;
                    944:   }
                    945:   if (msg[0])
                    946:     ui_gtk_dialog(msg);
                    947: }
                    948: 
                    949: GtkWidget *ui_gtk_dialog(const char *msg)
                    950: {
                    951:   GtkWidget *dialog, *label, *button_ok;
                    952: 
                    953:   dialog = gtk_dialog_new();
                    954:   label = gtk_label_new(msg);
                    955:   gtk_label_set_line_wrap(GTK_LABEL(label), 1);
                    956:   button_ok = gtk_button_new_with_label("OK");
                    957:   gtk_signal_connect_object(GTK_OBJECT(button_ok), "clicked",
                    958:                             GTK_SIGNAL_FUNC(gtk_widget_destroy),
                    959:                             GTK_OBJECT(dialog));
                    960:   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
                    961:                     button_ok);
                    962:   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
                    963:   gtk_window_set_modal(GTK_WINDOW(dialog), 1);
                    964:   gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 150);
                    965:   gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
                    966:   gtk_widget_show_all(dialog);
                    967:   return dialog;
                    968: }
                    969: 
                    970: /* supporting function for ui_gtk_query */
                    971: 
                    972: static void ui_gtk_response(GtkButton *button, gpointer func_data)
                    973: {
                    974:   (void)button;
                    975:   ui_query_response = GPOINTER_TO_INT(func_data);
1.1.1.2 ! root      976:   if (gtk_main_level() > 0)
        !           977:     gtk_main_quit();
1.1       root      978: }
                    979: 
                    980: /* ask a question and return 0 for OK/Yes, -1 for Cancel/No */
                    981: 
                    982: static int ui_gtk_query(const char *msg, int style)
                    983: {
                    984:   GtkWidget *dialog, *label, *button_a, *button_b, *hbox;
                    985: 
                    986:   dialog = gtk_dialog_new();
                    987:   label = gtk_label_new(msg);
                    988:   hbox = gtk_hbox_new(1, 8);
                    989:   gtk_label_set_line_wrap(GTK_LABEL(label), 1);
                    990:   switch (style) {
                    991:   default:
                    992:   case 0:
                    993:     button_a = gtk_button_new_with_label("OK");
                    994:     button_b = gtk_button_new_with_label("Cancel");
                    995:     break;
                    996:   case 1:
                    997:     button_a = gtk_button_new_with_label("Yes");
                    998:     button_b = gtk_button_new_with_label("No");
                    999:     break;
                   1000:   }
                   1001:   gtk_box_pack_end(GTK_BOX(hbox), button_b, 0, 1, 0);
                   1002:   gtk_box_pack_end(GTK_BOX(hbox), button_a, 0, 1, 0);
                   1003:   gtk_signal_connect(GTK_OBJECT(button_a), "clicked",
                   1004:                      GTK_SIGNAL_FUNC(ui_gtk_response),
                   1005:                      GINT_TO_POINTER(0));
                   1006:   gtk_signal_connect(GTK_OBJECT(button_b), "clicked",
                   1007:                      GTK_SIGNAL_FUNC(ui_gtk_response),
                   1008:                      GINT_TO_POINTER(-1));
                   1009:   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->action_area),
                   1010:                     hbox);
                   1011:   gtk_container_add(GTK_CONTAINER(GTK_DIALOG(dialog)->vbox), label);
                   1012:   gtk_window_set_modal(GTK_WINDOW(dialog), 1);
                   1013:   gtk_window_set_default_size(GTK_WINDOW(dialog), 350, 150);
                   1014:   gtk_window_set_position(GTK_WINDOW(dialog), GTK_WIN_POS_CENTER);
                   1015:   gtk_widget_show_all(dialog);
                   1016:   ui_query_response = -1;
                   1017:   gtk_main();
                   1018:   gtk_widget_destroy(dialog);
                   1019:   return ui_query_response;
                   1020: }
                   1021: 
                   1022: void ui_gtk_filesel(int type, int save)
                   1023: {
                   1024:   ui_filesel_type = type;
                   1025:   ui_filesel_save = save;
                   1026: 
                   1027:   switch ((type << 1) | save) {
                   1028:   case 0:
                   1029:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1030:                          "Choose ROM file (BIN or SMD format) to load");
                   1031:     break;
                   1032:   case 1:
                   1033:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1034:                          "Choose filename to save ROM file (BIN format) to");
                   1035:     break;
                   1036:   case 2:
                   1037:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1038:                          "Choose state file to load");
                   1039:     break;
                   1040:   case 3:
                   1041:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1042:                          "Choose filename to save state to");
                   1043:     break;
                   1044:   case 5:
                   1045:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1046:                          "Choose where to start GYM logging");
                   1047:     break;
                   1048:   case 7:
                   1049:     gtk_window_set_title(GTK_WINDOW(ui_win_filesel),
                   1050:                          "Choose where to start GNM logging");
                   1051:     break;
                   1052:   }
                   1053:   gtk_widget_show(ui_win_filesel);
                   1054: }
                   1055: 
                   1056: void ui_gtk_about(void)
                   1057: {
                   1058:   gtk_widget_show(ui_win_about);
                   1059: }
                   1060: 
                   1061: void ui_gtk_options(void)
                   1062: {
                   1063:   ui_gtk_opts_to_window();
                   1064:   gtk_widget_show(ui_win_opts);
                   1065: }
                   1066: 
                   1067: void ui_gtk_console(void)
                   1068: {
                   1069:   gtk_widget_show(ui_win_console);
                   1070: }
                   1071: 
                   1072: void ui_gtk_quit(void)
                   1073: {
                   1074:   gen_quit = 1;
1.1.1.2 ! root     1075:   if (gtk_main_level() > 0)
        !          1076:     gtk_main_quit();
1.1       root     1077: }
                   1078: 
                   1079: void ui_gtk_closeconsole(void)
                   1080: {
                   1081:   gtk_widget_hide(ui_win_console);
                   1082: }
                   1083: 
                   1084: void ui_gtk_play(void)
                   1085: {
                   1086:   if (ui_running) {
                   1087:     ui_gtk_dialog("Generator is already playing a ROM");
                   1088:     return;
                   1089:   }
                   1090:   if (cpu68k_rom == NULL || cpu68k_romlen == 0) {
                   1091:     ui_gtk_dialog("You must load a ROM into Generator");
                   1092:     return;
                   1093:   }
                   1094:   /* start running the game */
                   1095:   ui_running = 1;
                   1096:   ui_gtk_sizechange();
1.1.1.2 ! root     1097:   if (gtk_main_level() > 0)
        !          1098:     gtk_main_quit();
1.1       root     1099: }
                   1100: 
                   1101: void ui_gtk_pause(void)
                   1102: {
                   1103:   if (!ui_running) {
                   1104:     ui_gtk_dialog("Generator is not playing a ROM");
                   1105:     return;
                   1106:   }
                   1107:   ui_running = 0;
                   1108: }
                   1109: 
                   1110: void ui_gtk_softreset(void)
                   1111: {
                   1112:   gen_softreset();
                   1113: }
                   1114: 
                   1115: void ui_gtk_hardreset(void)
                   1116: {
                   1117:   gen_reset();
                   1118: }
                   1119: 
                   1120: /* set main window size from current parameters */
                   1121: 
                   1122: void ui_gtk_sizechange(void)
                   1123: {
                   1124:   GtkWidget *w;
                   1125: 
                   1126:   w = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main),
                   1127:                                      "drawingarea_main"));
                   1128:   switch (ui_screenmode) {
                   1129:   case SCREEN_100:
                   1130:     gtk_widget_set_usize(w, HSIZE, VSIZE);
                   1131:     screen = SDL_SetVideoMode(HSIZE, VSIZE, 0, 0);
                   1132:     break;
                   1133:   case SCREEN_200:
                   1134:     gtk_widget_set_usize(w, HSIZE * 2, VSIZE * 2);
                   1135:     screen = SDL_SetVideoMode(HSIZE * 2, VSIZE * 2, 0, 0);
                   1136:     break;
                   1137:   default:
                   1138:     ui_err("invalid screen mode\n");
                   1139:   }
                   1140:   w = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "hbox_bottom"));
                   1141:   if (ui_statusbar)
                   1142:     gtk_widget_show(w);
                   1143:   else
                   1144:     gtk_widget_hide(w);
                   1145:   ui_locksurface = SDL_MUSTLOCK(screen);
                   1146:   uiplot_setshifts(ui_topbit(screen->format->Rmask) - 4,
                   1147:                    ui_topbit(screen->format->Gmask) - 4,
                   1148:                    ui_topbit(screen->format->Bmask) - 4);
                   1149: }
                   1150: 
                   1151: void ui_gtk_newoptions(void)
                   1152: {
                   1153:   char buf[32];
                   1154:   const char *v;
                   1155:   int i, c;
                   1156:   unsigned int old_ui_screenmode = ui_screenmode;
                   1157:   unsigned int old_sound_minfields = sound_minfields;
                   1158:   unsigned int old_sound_maxfields = sound_maxfields;
                   1159:   unsigned int old_ui_hborder = ui_hborder;
                   1160:   unsigned int old_ui_vborder = ui_vborder;
                   1161:   unsigned int old_ui_statusbar = ui_statusbar;
                   1162: 
                   1163:   i = atoi(gtkopts_getvalue("view"));
                   1164:   ui_screenmode = (i == 200) ? SCREEN_200 : SCREEN_100;
                   1165: 
                   1166:   v = gtkopts_getvalue("region");
                   1167:   vdp_overseas = !strcasecmp(v, "overseas");
                   1168: 
                   1169:   v = gtkopts_getvalue("videostd");
                   1170:   vdp_pal = !strcasecmp(v, "pal");
                   1171: 
                   1172:   v = gtkopts_getvalue("autodetect");
                   1173:   gen_autodetect = !strcasecmp(v, "on");
                   1174: 
                   1175:   v = gtkopts_getvalue("plotter");
                   1176:   ui_vdpsimple = !strcasecmp(v, "cell");
                   1177: 
                   1178:   v = gtkopts_getvalue("interlace");
                   1179:   if (!strcasecmp(v, "weave"))
                   1180:     ui_interlace = DEINTERLACE_WEAVE;
                   1181:   else if (!strcasecmp(v, "weave-filter"))
                   1182:     ui_interlace = DEINTERLACE_WEAVEFILTER;
                   1183:   else
                   1184:     ui_interlace = DEINTERLACE_BOB;
                   1185: 
                   1186:   v = gtkopts_getvalue("frameskip");
                   1187:   if (!strcasecmp(v, "auto")) {
                   1188:     ui_frameskip = 0;
                   1189:   } else {
                   1190:     ui_frameskip = atoi(v);
                   1191:   }
                   1192: 
                   1193:   v = gtkopts_getvalue("hborder");
                   1194:   ui_hborder = atoi(v);
                   1195:   if (ui_hborder > HBORDER_MAX)
                   1196:     ui_hborder = HBORDER_MAX;
                   1197: 
                   1198:   v = gtkopts_getvalue("vborder");
                   1199:   ui_vborder = atoi(v);
                   1200:   if (ui_vborder > VBORDER_MAX)
                   1201:     ui_vborder = VBORDER_MAX;
                   1202: 
                   1203:   v = gtkopts_getvalue("z80");
                   1204:   cpuz80_on = !strcasecmp(v, "on");
                   1205: 
                   1206:   v = gtkopts_getvalue("sound");
                   1207:   sound_on = !strcasecmp(v, "on");
                   1208: 
                   1209:   v = gtkopts_getvalue("fm");
                   1210:   sound_fm = !strcasecmp(v, "on");
                   1211: 
                   1212:   v = gtkopts_getvalue("psg");
                   1213:   sound_psg = !strcasecmp(v, "on");
                   1214: 
                   1215:   v = gtkopts_getvalue("sound_minfields");
                   1216:   sound_minfields = atoi(v);
                   1217: 
                   1218:   v = gtkopts_getvalue("sound_maxfields");
                   1219:   sound_maxfields = atoi(v);
                   1220: 
1.1.1.2 ! root     1221:   v = gtkopts_getvalue("lowpassfilter");
        !          1222:   sound_filter = atoi(v);
        !          1223: 
1.1       root     1224:   v = gtkopts_getvalue("loglevel");
                   1225:   gen_loglevel = atoi(v);
                   1226: 
                   1227:   v = gtkopts_getvalue("statusbar");
                   1228:   ui_statusbar = !strcasecmp(v, "on");
                   1229: 
                   1230:   for (c = 0; c < 2; c++) {
                   1231:     snprintf(buf, sizeof(buf), "key%d_a", c + 1);
                   1232:     v = gtkopts_getvalue(buf);
                   1233:     ui_cont[c].a = gdk_keyval_from_name(v);
                   1234:     snprintf(buf, sizeof(buf), "key%d_b", c + 1);
                   1235:     v = gtkopts_getvalue(buf);
                   1236:     ui_cont[c].b = gdk_keyval_from_name(v);
                   1237:     snprintf(buf, sizeof(buf), "key%d_c", c + 1);
                   1238:     v = gtkopts_getvalue(buf);
                   1239:     ui_cont[c].c = gdk_keyval_from_name(v);
                   1240:     snprintf(buf, sizeof(buf), "key%d_up", c + 1);
                   1241:     v = gtkopts_getvalue(buf);
                   1242:     ui_cont[c].up = gdk_keyval_from_name(v);
                   1243:     snprintf(buf, sizeof(buf), "key%d_down", c + 1);
                   1244:     v = gtkopts_getvalue(buf);
                   1245:     ui_cont[c].down = gdk_keyval_from_name(v);
                   1246:     snprintf(buf, sizeof(buf), "key%d_left", c + 1);
                   1247:     v = gtkopts_getvalue(buf);
                   1248:     ui_cont[c].left = gdk_keyval_from_name(v);
                   1249:     snprintf(buf, sizeof(buf), "key%d_right", c + 1);
                   1250:     v = gtkopts_getvalue(buf);
                   1251:     ui_cont[c].right = gdk_keyval_from_name(v);
                   1252:     snprintf(buf, sizeof(buf), "key%d_start", c + 1);
                   1253:     v = gtkopts_getvalue(buf);
                   1254:     ui_cont[c].start = gdk_keyval_from_name(v);
                   1255:   }
                   1256:   if (ui_screenmode != old_ui_screenmode ||
                   1257:       ui_hborder != old_ui_hborder ||
                   1258:       ui_vborder != old_ui_vborder || ui_statusbar != old_ui_statusbar)
                   1259:     ui_gtk_sizechange();
                   1260: 
                   1261:   if (sound_minfields != old_sound_minfields ||
                   1262:       sound_maxfields != old_sound_maxfields) {
                   1263:     sound_reset();
                   1264:   }
                   1265: }
                   1266: 
                   1267: static void ui_gtk_opts_from_window(void)
                   1268: {
                   1269:   GtkWidget *obj, *active;
                   1270:   char buf[64];
                   1271:   int c;
                   1272:   const char *v;
                   1273:   const char **key;
                   1274: 
                   1275:   /* hardware - region */
                   1276: 
                   1277:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1278:                                        "radiobutton_domestic"));
                   1279:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1280:     gtkopts_setvalue("region", "domestic");
                   1281:   else
                   1282:     gtkopts_setvalue("region", "overseas");
                   1283: 
                   1284:   /* hardware - video standard */
                   1285: 
                   1286:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1287:                                        "radiobutton_pal"));
                   1288:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1289:     gtkopts_setvalue("videostd", "pal");
                   1290:   else
                   1291:     gtkopts_setvalue("videostd", "ntsc");
                   1292: 
                   1293:   /* hardware - auto detect */
                   1294: 
                   1295:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1296:                                        "checkbutton_autodetect"));
                   1297:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1298:     gtkopts_setvalue("autodetect", "on");
                   1299:   else
                   1300:     gtkopts_setvalue("autodetect", "off");
                   1301: 
                   1302:   /* video - plotter */
                   1303: 
                   1304:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1305:                                        "radiobutton_line"));
                   1306:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1307:     gtkopts_setvalue("plotter", "line");
                   1308:   else
                   1309:     gtkopts_setvalue("plotter", "cell");
                   1310: 
                   1311:   /* video - interlace mode */
                   1312: 
                   1313:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1314:                                        "optionmenu_interlace"));
                   1315:   /* now get active widget on menu */
                   1316:   obj = GTK_BIN(GTK_OPTION_MENU(obj))->child;
                   1317:   gtkopts_setvalue("interlace", GTK_LABEL(obj)->label);
                   1318: 
                   1319:   /* video - frame skip */
                   1320: 
                   1321:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1322:                                        "checkbutton_auto"));
                   1323:   if (GTK_TOGGLE_BUTTON(obj)->active) {
                   1324:     gtkopts_setvalue("frameskip", "auto");
                   1325:   } else {
                   1326:     obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1327:                                          "hscale_skip"));
                   1328:     snprintf(buf, sizeof(buf), "%d",
                   1329:              (int)(gtk_range_get_adjustment(GTK_RANGE(obj))->value));
                   1330:     gtkopts_setvalue("frameskip", buf);
                   1331:   }
                   1332: 
                   1333:   /* video - hborder */
                   1334: 
                   1335:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1336:                                        "spinbutton_hborder"));
                   1337:   snprintf(buf, sizeof(buf), "%d",
                   1338:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
                   1339:   gtkopts_setvalue("hborder", buf);
                   1340: 
                   1341:   /* video - vborder */
                   1342: 
                   1343:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1344:                                        "spinbutton_vborder"));
                   1345:   snprintf(buf, sizeof(buf), "%d",
                   1346:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
                   1347:   gtkopts_setvalue("vborder", buf);
                   1348: 
                   1349:   /* sound - z80 */
                   1350: 
                   1351:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1352:                                        "checkbutton_z80"));
                   1353:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1354:     gtkopts_setvalue("z80", "on");
                   1355:   else
                   1356:     gtkopts_setvalue("z80", "off");
                   1357: 
                   1358:   /* sound - on/off */
                   1359: 
                   1360:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1361:                                        "checkbutton_sound"));
                   1362:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1363:     gtkopts_setvalue("sound", "on");
                   1364:   else
                   1365:     gtkopts_setvalue("sound", "off");
                   1366: 
                   1367:   /* sound - psg */
                   1368: 
                   1369:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1370:                                        "checkbutton_psg"));
                   1371:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1372:     gtkopts_setvalue("psg", "on");
                   1373:   else
                   1374:     gtkopts_setvalue("psg", "off");
                   1375: 
                   1376:   /* sound - fm */
                   1377: 
                   1378:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1379:                                        "checkbutton_fm"));
                   1380:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1381:     gtkopts_setvalue("fm", "on");
                   1382:   else
                   1383:     gtkopts_setvalue("fm", "off");
                   1384: 
                   1385:   /* sound - min fields */
                   1386: 
                   1387:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1388:                                        "spinbutton_minfields"));
                   1389:   snprintf(buf, sizeof(buf), "%d",
                   1390:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
                   1391:   gtkopts_setvalue("sound_minfields", buf);
                   1392: 
1.1.1.2 ! root     1393:   /* sound - max fields */
1.1       root     1394: 
                   1395:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1396:                                        "spinbutton_maxfields"));
                   1397:   snprintf(buf, sizeof(buf), "%d",
                   1398:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
                   1399:   gtkopts_setvalue("sound_maxfields", buf);
                   1400: 
1.1.1.2 ! root     1401:   /* sound - filter */
        !          1402: 
        !          1403:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1404:                                        "spinbutton_filter"));
        !          1405:   snprintf(buf, sizeof(buf), "%d",
        !          1406:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
        !          1407:   gtkopts_setvalue("lowpassfilter", buf);
        !          1408: 
        !          1409:   /* logging - verbosity */
1.1       root     1410: 
                   1411:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1412:                                        "optionmenu_level"));
                   1413:   obj = GTK_OPTION_MENU(obj)->menu;
                   1414:   /* now get active widget on menu */
                   1415:   active = gtk_menu_get_active(GTK_MENU(obj));
                   1416:   snprintf(buf, sizeof(buf), "%d",
                   1417:            g_list_index(GTK_MENU_SHELL(obj)->children, active));
                   1418:   gtkopts_setvalue("loglevel", buf);
                   1419: 
1.1.1.2 ! root     1420:   /* logging - sound */
1.1       root     1421: 
                   1422:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1423:                                        "checkbutton_debugsound"));
                   1424:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1425:     gtkopts_setvalue("debugsound", "on");
                   1426:   else
                   1427:     gtkopts_setvalue("debugsound", "off");
                   1428: 
1.1.1.2 ! root     1429:   /* logging - status bar */
        !          1430: 
1.1       root     1431:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1432:                                        "checkbutton_statusbar"));
                   1433:   if (GTK_TOGGLE_BUTTON(obj)->active)
                   1434:     gtkopts_setvalue("statusbar", "on");
                   1435:   else
                   1436:     gtkopts_setvalue("statusbar", "off");
                   1437: 
1.1.1.2 ! root     1438:   /* logging - avi format */
        !          1439: 
        !          1440:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1441:                                        "optionmenu_aviformat"));
        !          1442:   /* now get active widget on menu */
        !          1443:   obj = GTK_BIN(GTK_OPTION_MENU(obj))->child;
        !          1444:   gtkopts_setvalue("aviformat", GTK_LABEL(obj)->label);
        !          1445: 
        !          1446:   /* logging - avi frame skip */
        !          1447: 
        !          1448:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1449:                                        "hscale_avi"));
        !          1450:   snprintf(buf, sizeof(buf), "%d",
        !          1451:            (int)(gtk_range_get_adjustment(GTK_RANGE(obj))->value));
        !          1452:   gtkopts_setvalue("aviframeskip", buf);
        !          1453: 
        !          1454:   /* logging - jpeg quality */
        !          1455: 
        !          1456:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1457:                                        "spinbutton_jpegquality"));
        !          1458:   snprintf(buf, sizeof(buf), "%d",
        !          1459:            gtk_spin_button_get_value_as_int(GTK_SPIN_BUTTON(obj)));
        !          1460:   gtkopts_setvalue("jpegquality", buf);
        !          1461: 
1.1       root     1462:   /* controls */
                   1463: 
                   1464:   for (c = 1; c <= 2; c++) {
                   1465:     for (key = ui_gtk_keys;
                   1466:          (char *)key < ((char *)ui_gtk_keys + sizeof(ui_gtk_keys));
                   1467:          key++) {
                   1468:       snprintf(buf, sizeof(buf), "entry_player%d_%s", c, *key);
                   1469:       obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts), buf));
                   1470:       v = gtk_entry_get_text(GTK_ENTRY(obj));
                   1471:       snprintf(buf, sizeof(buf), "key%d_%s", c, *key);
                   1472:       gtkopts_setvalue(buf, v);
                   1473:     }
                   1474:   }
                   1475: }
                   1476: 
                   1477: static void ui_gtk_opts_to_window(void)
                   1478: {
                   1479:   GtkWidget *obj;
                   1480:   const char *v;
                   1481:   const char **key;
                   1482:   int i, c;
                   1483:   char buf[32];
                   1484: 
                   1485:   /* hardware - region */
                   1486: 
                   1487:   v = gtkopts_getvalue("region");
                   1488:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1489:                                        "radiobutton_domestic"));
                   1490:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1491:                                !strcasecmp(v, "domestic"));
                   1492:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1493:                                        "radiobutton_overseas"));
                   1494:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1495:                                !strcasecmp(v, "overseas"));
                   1496: 
                   1497:   /* hardware - video standard */
                   1498: 
                   1499:   v = gtkopts_getvalue("videostd");
                   1500:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1501:                                        "radiobutton_pal"));
                   1502:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "pal"));
                   1503:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1504:                                        "radiobutton_ntsc"));
                   1505:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1506:                                !strcasecmp(v, "ntsc"));
                   1507: 
                   1508:   /* hardware - auto detect */
                   1509: 
                   1510:   v = gtkopts_getvalue("autodetect");
                   1511:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1512:                                        "checkbutton_autodetect"));
                   1513:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1514: 
                   1515:   /* video - plotter */
                   1516: 
                   1517:   v = gtkopts_getvalue("plotter");
                   1518:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1519:                                        "radiobutton_line"));
                   1520:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1521:                                !strcasecmp(v, "line"));
                   1522:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1523:                                        "radiobutton_cell"));
                   1524:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1525:                                !strcasecmp(v, "cell"));
                   1526: 
                   1527:   /* video - interlace mode */
                   1528: 
                   1529:   v = gtkopts_getvalue("interlace");
                   1530:   if (!strcasecmp(v, "bob")) {
                   1531:     i = 0;
                   1532:   } else if (!strcasecmp(v, "weave")) {
                   1533:     i = 1;
                   1534:   } else {
                   1535:     i = 2;
                   1536:   }
                   1537:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1538:                                        "optionmenu_interlace"));
                   1539:   gtk_option_menu_set_history(GTK_OPTION_MENU(obj), i);
                   1540: 
                   1541:   /* video - frame skip */
                   1542: 
                   1543:   v = gtkopts_getvalue("frameskip");
                   1544:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1545:                                        "checkbutton_auto"));
                   1546:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj),
                   1547:                                !strcasecmp(v, "auto"));
                   1548:   i = atoi(v);
                   1549:   if (i < 1)
                   1550:     i = 1;
                   1551:   if (i > 10)
                   1552:     i = 10;
                   1553:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1554:                                        "hscale_skip"));
                   1555:   gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(obj)), i);
                   1556: 
                   1557:   /* video - hborder */
                   1558: 
                   1559:   v = gtkopts_getvalue("hborder");
                   1560:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1561:                                        "spinbutton_hborder"));
                   1562:   i = atoi(v);
                   1563:   if (i < 0)
                   1564:     i = 0;
                   1565:   if (i > HBORDER_MAX)
                   1566:     i = HBORDER_MAX;
                   1567:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
                   1568: 
                   1569:   /* video - vborder */
                   1570: 
                   1571:   v = gtkopts_getvalue("vborder");
                   1572:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1573:                                        "spinbutton_vborder"));
                   1574:   i = atoi(v);
                   1575:   if (i < 0)
                   1576:     i = 0;
                   1577:   if (i > VBORDER_MAX)
                   1578:     i = VBORDER_MAX;
                   1579:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
                   1580: 
                   1581:   /* sound - z80 */
                   1582: 
                   1583:   v = gtkopts_getvalue("z80");
                   1584:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1585:                                        "checkbutton_z80"));
                   1586:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1587: 
                   1588:   /* sound - on/off */
                   1589: 
                   1590:   v = gtkopts_getvalue("sound");
                   1591:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1592:                                        "checkbutton_sound"));
                   1593:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1594: 
                   1595:   /* sound - psg */
                   1596: 
                   1597:   v = gtkopts_getvalue("psg");
                   1598:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1599:                                        "checkbutton_psg"));
                   1600:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1601: 
                   1602:   /* sound - fm */
                   1603: 
                   1604:   v = gtkopts_getvalue("fm");
                   1605:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1606:                                        "checkbutton_fm"));
                   1607:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1608: 
                   1609:   /* sound - min fields */
                   1610: 
                   1611:   v = gtkopts_getvalue("sound_minfields");
                   1612:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1613:                                        "spinbutton_minfields"));
                   1614:   i = atoi(v);
                   1615:   if (i < 1)
                   1616:     i = 1;
                   1617:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
                   1618: 
                   1619:   /* sound - max fields */
                   1620: 
                   1621:   v = gtkopts_getvalue("sound_maxfields");
                   1622:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1623:                                        "spinbutton_maxfields"));
                   1624:   i = atoi(v);
                   1625:   if (i < 1)
                   1626:     i = 1;
                   1627:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
                   1628: 
1.1.1.2 ! root     1629:   /* sound - filter */
        !          1630: 
        !          1631:   v = gtkopts_getvalue("lowpassfilter");
        !          1632:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1633:                                        "spinbutton_filter"));
        !          1634:   i = atoi(v);
        !          1635:   if (i < 1)
        !          1636:     i = 1;
        !          1637:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
        !          1638: 
        !          1639:   /* logging - verbosity */
1.1       root     1640: 
                   1641:   v = gtkopts_getvalue("loglevel");
                   1642:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1643:                                        "optionmenu_level"));
                   1644:   i = atoi(v);
                   1645:   gtk_option_menu_set_history(GTK_OPTION_MENU(obj), i);
                   1646: 
1.1.1.2 ! root     1647:   /* logging - sound */
1.1       root     1648: 
                   1649:   v = gtkopts_getvalue("debugsound");
                   1650:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1651:                                        "checkbutton_debugsound"));
                   1652:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1653: 
1.1.1.2 ! root     1654:   /* logging - status bar */
1.1       root     1655: 
                   1656:   v = gtkopts_getvalue("statusbar");
                   1657:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
                   1658:                                        "checkbutton_statusbar"));
                   1659:   gtk_toggle_button_set_active(GTK_TOGGLE_BUTTON(obj), !strcasecmp(v, "on"));
                   1660: 
1.1.1.2 ! root     1661:   /* logging - avi format */
        !          1662: 
        !          1663:   v = gtkopts_getvalue("aviformat");
        !          1664:   if (!strcasecmp(v, "rgb")) {
        !          1665:     i = 0;
        !          1666:   } else {
        !          1667:     i = 1;
        !          1668:   }
        !          1669:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1670:                                        "optionmenu_aviformat"));
        !          1671:   gtk_option_menu_set_history(GTK_OPTION_MENU(obj), i);
        !          1672: 
        !          1673:   /* logging - avi frame skip */
        !          1674: 
        !          1675:   i = atoi(gtkopts_getvalue("aviframeskip"));
        !          1676:   if (i < 1)
        !          1677:     i = 1;
        !          1678:   if (i > 10)
        !          1679:     i = 10;
        !          1680:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1681:                                        "hscale_avi"));
        !          1682:   gtk_adjustment_set_value(gtk_range_get_adjustment(GTK_RANGE(obj)), i);
        !          1683:   
        !          1684:   /* logging - jpeg quality */
        !          1685: 
        !          1686:   v = gtkopts_getvalue("jpegquality");
        !          1687:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts),
        !          1688:                                        "spinbutton_jpegquality"));
        !          1689:   i = atoi(v);
        !          1690:   if (i < 1)
        !          1691:     i = 1;
        !          1692:   gtk_spin_button_set_value(GTK_SPIN_BUTTON(obj), i);
        !          1693: 
1.1       root     1694:   /* controls */
                   1695: 
                   1696:   for (c = 1; c <= 2; c++) {
                   1697:     for (key = ui_gtk_keys;
                   1698:          (char *)key < ((char *)ui_gtk_keys + sizeof(ui_gtk_keys));
                   1699:          key++) {
                   1700:       snprintf(buf, sizeof(buf), "key%d_%s", c, *key);
                   1701:       v = gtkopts_getvalue(buf);
                   1702:       i = gdk_keyval_from_name(v);
                   1703:       if (i) {
                   1704:         v = gdk_keyval_name(i); /* just incase case is different etc. */
                   1705:       } else {
                   1706:         v = "";
                   1707:       }
                   1708:       snprintf(buf, sizeof(buf), "entry_player%d_%s", c, *key);
                   1709:       obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_opts), buf));
                   1710:       gtk_entry_set_text(GTK_ENTRY(obj), v);
                   1711:     }
                   1712:   }
                   1713: }
                   1714: 
                   1715: void ui_gtk_applyoptions(void)
                   1716: {
                   1717:   ui_gtk_opts_from_window();
                   1718:   gtk_widget_hide(ui_win_opts);
                   1719:   ui_gtk_newoptions();
                   1720:   ui_gtk_opts_to_menu();
                   1721: }
                   1722: 
                   1723: void ui_gtk_saveoptions(void)
                   1724: {
                   1725:   char buf[256];
                   1726: 
                   1727:   ui_gtk_opts_from_window();
                   1728:   if (gtkopts_save(ui_configfile) != 0) {
                   1729:     snprintf(buf, sizeof(buf), "Failed to save configuration to '%s': %s",
                   1730:              ui_configfile, strerror(errno));
                   1731:     ui_gtk_dialog(buf);
                   1732:     return;
                   1733:   }
                   1734:   gtk_widget_hide(ui_win_opts);
                   1735:   ui_gtk_newoptions();
                   1736:   ui_gtk_opts_to_menu();
                   1737: }
                   1738: 
                   1739: void ui_gtk_redraw(void)
                   1740: {
                   1741:   SDL_UpdateRect(screen, 0, 0, screen->w, screen->h);
                   1742: }
                   1743: 
                   1744: void ui_gtk_key(unsigned long key, int press)
                   1745: {
                   1746:   t_gtkkeys *cont;
                   1747:   int c;
                   1748: 
                   1749:   for (c = 0; c < 2; c++) {
                   1750:     cont = &ui_cont[c];
                   1751:     if (key == cont->a) {
                   1752:       mem68k_cont[c].a = press;
                   1753:     } else if (key == cont->b) {
                   1754:       mem68k_cont[c].b = press;
                   1755:     } else if (key == cont->c) {
                   1756:       mem68k_cont[c].c = press;
                   1757:     } else if (key == cont->left) {
                   1758:       mem68k_cont[c].left = press;
                   1759:     } else if (key == cont->right) {
                   1760:       mem68k_cont[c].right = press;
                   1761:     } else if (key == cont->up) {
                   1762:       mem68k_cont[c].up = press;
                   1763:     } else if (key == cont->down) {
                   1764:       mem68k_cont[c].down = press;
                   1765:     } else if (key == cont->start) {
                   1766:       mem68k_cont[c].start = press;
                   1767:     }
                   1768:   }
                   1769: }
                   1770: 
1.1.1.2 ! root     1771: static void ui_sdl_events (void)
        !          1772: {
        !          1773:        SDL_Event event;
        !          1774:   #define      LEFT(event)     ((event.jaxis.value < -16384) ? 1 : 0)
        !          1775:   #define      RIGHT(event)    ((event.jaxis.value > 16384) ? 1 : 0)
        !          1776:   #define      UP(event)       ((event.jaxis.value < -16384) ? 1 : 0)
        !          1777:   #define      DOWN(event)     ((event.jaxis.value > 16384) ? 1 : 0)
        !          1778:   #define      PRESS(event)    ((event.type == SDL_JOYBUTTONDOWN) ? 1 : 0)
        !          1779: 
        !          1780:        while (SDL_PollEvent(&event)) {
        !          1781:                switch (event.type) {
        !          1782:                case SDL_JOYAXISMOTION:
        !          1783:                        if (event.jaxis.which > 1)
        !          1784:                                break;
        !          1785:                        switch (event.jaxis.axis) {
        !          1786:                        case 0: /* left & right */
        !          1787:                                mem68k_cont[event.jaxis.which].left = LEFT(event);
        !          1788:                                mem68k_cont[event.jaxis.which].right = RIGHT(event);
        !          1789:                                break;
        !          1790:                        case 1: /* up & down */
        !          1791:                                mem68k_cont[event.jaxis.which].up = UP(event);
        !          1792:                                mem68k_cont[event.jaxis.which].down = DOWN(event);
        !          1793:                                break;
        !          1794:                        default:
        !          1795:                                break;
        !          1796:                        }
        !          1797:                        break;
        !          1798:                case SDL_JOYBUTTONDOWN:
        !          1799:                case SDL_JOYBUTTONUP:
        !          1800:                        if (event.jbutton.which > 1)
        !          1801:                                break;
        !          1802:                        switch (event.jbutton.button) {
        !          1803:                        case 0:
        !          1804:                                mem68k_cont[event.jbutton.which].a = PRESS(event);
        !          1805:                                break;
        !          1806:                        case 1:
        !          1807:                                mem68k_cont[event.jbutton.which].b = PRESS(event);
        !          1808:                                break;
        !          1809:                        case 2:
        !          1810:                                mem68k_cont[event.jbutton.which].c = PRESS(event);
        !          1811:                                break;
        !          1812:                        case 3:
        !          1813:                                mem68k_cont[event.jbutton.which].start = PRESS(event);
        !          1814:                                break;
        !          1815:                        default:
        !          1816:                                break;
        !          1817:                        }
        !          1818:                        break;
        !          1819:                default:
        !          1820:                        break;
        !          1821:                }
        !          1822:        }
        !          1823: }      
        !          1824: 
1.1       root     1825: void ui_gtk_mainenter(void)
                   1826: {
                   1827:   /* clear out current state */
                   1828:   memset(mem68k_cont, 0, sizeof(mem68k_cont));
1.1.1.2 ! root     1829:   gdk_key_repeat_disable();
1.1       root     1830: }
                   1831: 
                   1832: void ui_gtk_mainleave(void)
                   1833: {
1.1.1.2 ! root     1834:   gdk_key_repeat_restore();
1.1       root     1835: }
                   1836: 
                   1837: static void ui_gtk_opts_to_menu(void)
                   1838: {
                   1839:   GtkWidget *obj;
                   1840:   const char *v;
                   1841: 
                   1842:   /* view */
                   1843: 
                   1844:   v = gtkopts_getvalue("view");
                   1845:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "_100"));
                   1846:   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(obj),
                   1847:                                  !strcasecmp(v, "100"));
                   1848:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_main), "_200"));
                   1849:   gtk_check_menu_item_set_active(GTK_CHECK_MENU_ITEM(obj),
                   1850:                                  !strcasecmp(v, "200"));
                   1851: }
                   1852: 
                   1853: void ui_musiclog(uint8 *data, unsigned int length)
                   1854: {
                   1855:   if (ui_musicfile != -1)
                   1856:     write(ui_musicfile, data, length);
                   1857: }
                   1858: 
                   1859: void ui_gtk_closemusiclog(void)
                   1860: {
                   1861:   if (ui_musicfile == -1) {
                   1862:     ui_gtk_dialog("There is no log to close");
                   1863:     return;
                   1864:   }
                   1865:   close(ui_musicfile);
                   1866:   ui_musicfile = -1;
                   1867:   gen_musiclog = 0;
                   1868: }
1.1.1.2 ! root     1869: 
        !          1870: static void ui_gtk_codes_to_window(void)
        !          1871: {
        !          1872:   GtkWidget *obj;
        !          1873:   t_patchlist *ent;
        !          1874:   char *data[2];
        !          1875: 
        !          1876:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1877:                                        "clist_codes"));
        !          1878:   gtk_clist_clear(GTK_CLIST(obj));
        !          1879:   for (ent = patch_patchlist; ent; ent = ent->next) {
        !          1880:     data[0] = ent->code;
        !          1881:     data[1] = ent->action;
        !          1882:     gtk_clist_append(GTK_CLIST(obj), data);
        !          1883:   }
        !          1884: }
        !          1885: 
        !          1886: void ui_gtk_codes(void)
        !          1887: {
        !          1888:   ui_gtk_codes_to_window();
        !          1889:   gtk_widget_show(ui_win_codes);
        !          1890: }
        !          1891: 
        !          1892: void ui_gtk_codes_add(void)
        !          1893: {
        !          1894:   GtkWidget *obj;
        !          1895:   char *data[2];
        !          1896:   char *code, *action;
        !          1897: 
        !          1898:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1899:                                        "entry_code"));
        !          1900:   code = gtk_entry_get_text(GTK_ENTRY(obj));
        !          1901:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1902:                                        "entry_action"));
        !          1903:   action = gtk_entry_get_text(GTK_ENTRY(obj));
        !          1904:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1905:                                        "clist_codes"));
        !          1906:   data[0] = (char *)code;
        !          1907:   data[1] = (char *)action;
        !          1908:   gtk_clist_append(GTK_CLIST(obj), data);
        !          1909: }
        !          1910: 
        !          1911: void ui_gtk_codes_delete(void)
        !          1912: {
        !          1913:   GtkWidget *obj;
        !          1914:   GList *slist;
        !          1915: 
        !          1916:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1917:                                        "clist_codes"));
        !          1918:   while ((slist = GTK_CLIST(obj)->selection) != NULL) {
        !          1919:     gtk_clist_remove(GTK_CLIST(obj), (int)slist->data);
        !          1920:   }
        !          1921: }
        !          1922: 
        !          1923: void ui_gtk_codes_deleteall(void)
        !          1924: {
        !          1925:   GtkWidget *obj;
        !          1926: 
        !          1927:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1928:                                        "clist_codes"));
        !          1929:   gtk_clist_clear(GTK_CLIST(obj));
        !          1930: }
        !          1931: 
        !          1932: void ui_gtk_codes_clearsel(void)
        !          1933: {
        !          1934:   GtkWidget *obj;
        !          1935: 
        !          1936:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1937:                                        "clist_codes"));
        !          1938:   gtk_clist_unselect_all(GTK_CLIST(obj));
        !          1939: }
        !          1940: 
        !          1941: void ui_gtk_codes_ok(void)
        !          1942: {
        !          1943:   GtkWidget *obj;
        !          1944:   int i;
        !          1945:   char *code, *action;
        !          1946: 
        !          1947:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1948:                                        "clist_codes"));
        !          1949:   patch_clearlist();
        !          1950:   for (i = 0;; i++) {
        !          1951:     if (gtk_clist_get_text(GTK_CLIST(obj), i, 0, &code) != 1 ||
        !          1952:         gtk_clist_get_text(GTK_CLIST(obj), i, 1, &action) != 1)
        !          1953:       break;
        !          1954:     patch_addcode(code, action);
        !          1955:   }
        !          1956:   gtk_widget_hide(ui_win_codes);
        !          1957: }
        !          1958: 
        !          1959: void ui_gtk_codes_apply(void)
        !          1960: {
        !          1961:   GtkWidget *obj;
        !          1962:   GList *slist;
        !          1963:   char *code, *action;
        !          1964:   int failed = 0;
        !          1965: 
        !          1966:   obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(ui_win_codes),
        !          1967:                                        "clist_codes"));
        !          1968:   slist = GTK_CLIST(obj)->selection;
        !          1969:   for (; slist; slist = slist->next) {
        !          1970:     if (gtk_clist_get_text(GTK_CLIST(obj), (int)slist->data, 0, &code) != 1 ||
        !          1971:         gtk_clist_get_text(GTK_CLIST(obj), (int)slist->data, 1, &action) != 1) {
        !          1972:       failed = 1;
        !          1973:       break;
        !          1974:     }
        !          1975:     if (patch_apply(code, action) != 0)
        !          1976:       failed = 1;
        !          1977:   }
        !          1978:   if (failed)
        !          1979:     ui_gtk_dialog("Unable to apply one or more cheats (either invalid cheat "
        !          1980:                   "code or out of bounds for currently loaded ROM)");
        !          1981:   cpu68k_clearcache();
        !          1982: }
        !          1983: 
        !          1984: void ui_gtk_closeavi(void)
        !          1985: {
        !          1986:   if (ui_avi == NULL) {
        !          1987:     ui_gtk_dialog("There is no avi to close");
        !          1988:     return;
        !          1989:   }
        !          1990:   if (avi_close(ui_avi) != 0) {
        !          1991:     ui_gtk_dialog(strerror(errno));
        !          1992:     return;
        !          1993:   }
        !          1994:   free(ui_avivideo);
        !          1995:   free(ui_aviaudio);
        !          1996:   ui_avi = NULL;
        !          1997:   ui_avivideo = NULL;
        !          1998:   ui_aviaudio = NULL;
        !          1999:   ui_gtk_newoptions(); /* restore ui_frameskip */
        !          2000: }
        !          2001: 
        !          2002: GtkWidget *ui_gtk_newdiss(unsigned int type)
        !          2003: {
        !          2004:   GtkWidget *disswin, *obj;
        !          2005:   GtkStyle *style;
        !          2006:   unsigned int i;
        !          2007:   GtkWidget **dw;
        !          2008: 
        !          2009:   disswin = create_diss();
        !          2010:   gtk_object_set_data(GTK_OBJECT(disswin), "generator_diss_type", 
        !          2011:                       GINT_TO_POINTER(type));
        !          2012:   gtk_object_set_data(GTK_OBJECT(disswin), "generator_diss_offset",
        !          2013:                       GINT_TO_POINTER(0));
        !          2014: 
        !          2015:   /* store in our list */
        !          2016:   dw = ui_disswins;
        !          2017:   for (i = 0; i < DISSWIN_MAX; i++, dw++) {
        !          2018:     if (*dw == NULL) {
        !          2019:       *dw = disswin;
        !          2020:       break;
        !          2021:     }
        !          2022:   }
        !          2023:   if (i == DISSWIN_MAX) {
        !          2024:     ui_gtk_dialog("Too many disassembly windows!");
        !          2025:     gtk_widget_destroy(disswin);
        !          2026:     return NULL;
        !          2027:   }
        !          2028:   return disswin;
        !          2029: }
        !          2030: 
        !          2031: int ui_gtk_destroydiss(GtkWidget *disswin)
        !          2032: {
        !          2033:   unsigned int i;
        !          2034:   GtkWidget **dw;
        !          2035: 
        !          2036:   dw = ui_disswins;
        !          2037:   for (i = 0; i < DISSWIN_MAX; i++, dw++) {
        !          2038:     if (*dw == disswin) {
        !          2039:       gtk_widget_destroy(disswin);
        !          2040:       *dw = NULL;
        !          2041:       return 0;
        !          2042:     }
        !          2043:   }
        !          2044:   return -1;
        !          2045: }
        !          2046: 
        !          2047: //{
        !          2048: //  GtkWidget *adj, *scrollbar;
        !          2049: //
        !          2050: //  scrollbar = lookup_widget(disswin, "vscrollbar_diss");
        !          2051: //  adj = gtk_range_get_adjustment(GTK_RANGE(scrollbar));
        !          2052: //}
        !          2053: //scrollbar = lookup_widget(disswin, "vscrollbar_diss");
        !          2054: //gtk_signal_connect(GTK_OBJECT(GTK_RANGE(scrollbar)->adjustment),
        !          2055: //                   "changed", GTK_SIGNAL_FUNC(on_adjustment_changed), NULL);
        !          2056: 
        !          2057: void ui_gtk_redrawdiss(GtkWidget *canvas, GdkEventExpose *event)
        !          2058: {
        !          2059:   GdkRectangle *rect = &event->area;
        !          2060:   GtkWidget *obj, *disswin;
        !          2061:   signed int yoff = -2;
        !          2062:   signed int y;
        !          2063:   unsigned int y_start, y_end, fontheight, i;
        !          2064:   uint8 *mem_where;
        !          2065:   uint32 mem_start;
        !          2066:   uint32 mem_len;
        !          2067:   uint32 type, offset;
        !          2068:   char dumpline[256];
        !          2069:   char *p;
        !          2070:   int words;
        !          2071: 
        !          2072:   disswin = gtk_widget_get_toplevel(canvas);
        !          2073:   offset = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(disswin),
        !          2074:                                                "generator_diss_offset"));
        !          2075:   type = GPOINTER_TO_INT(gtk_object_get_data(GTK_OBJECT(disswin),
        !          2076:                                              "generator_diss_type"));
        !          2077:   switch (type) {
        !          2078:   case 0:
        !          2079:     mem_where = cpu68k_rom;
        !          2080:     mem_start = 0;
        !          2081:     mem_len = cpu68k_romlen;
        !          2082:     break;
        !          2083:   case 1:
        !          2084:     mem_where = cpu68k_ram;
        !          2085:     mem_start = 0xFF0000;
        !          2086:     mem_len = 0x10000;
        !          2087:     break;
        !          2088:   case 2:
        !          2089:     mem_where = vdp_vram;
        !          2090:     mem_start = 0x0;
        !          2091:     mem_len = LEN_VRAM;
        !          2092:     break;
        !          2093:   case 3:
        !          2094:     mem_where = vdp_cram;
        !          2095:     mem_start = 0x0;
        !          2096:     mem_len = LEN_CRAM;
        !          2097:     break;
        !          2098:   case 4:
        !          2099:     mem_where = vdp_vsram;
        !          2100:     mem_start = 0x0;
        !          2101:     mem_len = LEN_VSRAM;
        !          2102:     break;
        !          2103:   case 5:
        !          2104:     mem_where = cpuz80_ram;
        !          2105:     mem_start = 0x0;
        !          2106:     mem_len = LEN_SRAM;
        !          2107:     break;
        !          2108:   default:
        !          2109:     return;
        !          2110:   }
        !          2111: 
        !          2112:   fontheight = ui_dissfont->ascent + ui_dissfont->descent;
        !          2113:   if ((y = rect->y - yoff) < 0)
        !          2114:     y = 0;
        !          2115:   y_start = y / fontheight;
        !          2116:   y_end = (y + rect->height) / fontheight;
        !          2117:   offset+= y_start * 2;
        !          2118:   for (i = y_start; i <= y_end; i++) {
        !          2119:     printf("offset=%X\n", offset);
        !          2120:     p = dumpline;
        !          2121:     *p++ = '>';
        !          2122:     *p++ = ' ';
        !          2123:     if (offset >= mem_len) {
        !          2124:     } else {
        !          2125:       words = diss68k_getdumpline(mem_start + offset, mem_where + offset, p);
        !          2126:       offset+= words * 2;
        !          2127:     }
        !          2128:     gdk_draw_rectangle(canvas->window,
        !          2129:                        canvas->style->bg_gc[GTK_WIDGET_STATE(canvas)],
        !          2130:                        TRUE, 0, i * fontheight + yoff,
        !          2131:                        4096, fontheight);
        !          2132:     gdk_draw_text(canvas->window, ui_dissfont,
        !          2133:                   canvas->style->fg_gc[GTK_WIDGET_STATE(canvas)],
        !          2134:                   2, i * fontheight + yoff + fontheight, dumpline,
        !          2135:                   strlen(dumpline));
        !          2136:   }
        !          2137:   /*
        !          2138:   printf("x = %d\ny = %d\nwidth = %d\nheight = %d\noff=%f\n\n", rect->x,
        !          2139:   rect->y, rect->width, rect->height, adj->value);
        !          2140:   */
        !          2141: 
        !          2142: 
        !          2143: }
        !          2144: 
        !          2145: //void ui_gtk_redrawdiss(GtkWidget *canvas, GdkEventExpose *event)
        !          2146: //{
        !          2147: //  GdkRectangle *rect = &event->area;
        !          2148: //  GtkWidget *obj, *disswin;
        !          2149: //  GtkAdjustment *adj;
        !          2150: //  signed int y, ypos;
        !          2151: //  unsigned int y_start, y_end, fontheight, i;
        !          2152: //
        !          2153: //  disswin = gtk_widget_get_toplevel(canvas);
        !          2154: //  obj = GTK_WIDGET(gtk_object_get_data(GTK_OBJECT(disswin), 
        !          2155: //                                       "scrolledwindow_diss"));
        !          2156: //  adj = gtk_scrolled_window_get_vadjustment(GTK_SCROLLED_WINDOW(obj));
        !          2157: //
        !          2158: //  fontheight = ui_dissfont->ascent + ui_dissfont->descent;
        !          2159: //  if ((y = rect->y - 2) < 0)
        !          2160: //    y = 0;
        !          2161: //  printf("y = %d\n", y);
        !          2162: //  y_start = (y + (int)adj->value) / fontheight;
        !          2163: //  y_end = (y + (int)adj->value + rect->height) / fontheight;
        !          2164: //  printf("val = %f start = %d height = %d\n", adj->value, y_start, fontheight);
        !          2165: //  ypos = -adj->value + y_start * fontheight;
        !          2166: //  printf("< %d %d >\n", y_start, y_end);
        !          2167: //  for (i = y_start; i < y_end; i++, ypos+= fontheight) {
        !          2168: //    gdk_draw_text(canvas->window, ui_dissfont,
        !          2169: //                  cavas->style->fg_gc[GTK_WIDGET_STATE(canvas)],
        !          2170: //                  0, ypos);
        !          2171: //
        !          2172: //    printf("[%d] %d\n", i, ypos);
        !          2173: //  }
        !          2174: //  /*
        !          2175: //  printf("x = %d\ny = %d\nwidth = %d\nheight = %d\noff=%f\n\n", rect->x,
        !          2176: //  rect->y, rect->width, rect->height, adj->value);
        !          2177: //  */
        !          2178: //
        !          2179: //
        !          2180: //}

unix.superglobalmegacorp.com

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