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