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

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

unix.superglobalmegacorp.com

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