Annotation of uae/src/gtkui.c, revision 1.1.1.8

1.1       root        1: /*
                      2:  * UAE - the Un*x Amiga Emulator
                      3:  *
                      4:  * Yet Another User Interface for the X11 version
                      5:  *
                      6:  * Copyright 1997, 1998 Bernd Schmidt
1.1.1.2   root        7:  * Copyright 1998 Michael Krause
1.1       root        8:  * 
                      9:  * The Tk GUI doesn't work.
                     10:  * The X Forms Library isn't available as source, and there aren't any
                     11:  * binaries compiled against glibc
                     12:  *
                     13:  * So let's try this...
                     14:  */
                     15: 
                     16: #include "sysconfig.h"
                     17: #include "sysdeps.h"
                     18: 
                     19: #include "config.h"
                     20: #include "options.h"
                     21: #include "uae.h"
                     22: #include "memory.h"
                     23: #include "custom.h"
                     24: #include "gui.h"
                     25: #include "newcpu.h"
                     26: #include "threaddep/penguin.h"
1.1.1.2   root       27: #include "sounddep/sound.h"
1.1       root       28: 
                     29: #include <gtk/gtk.h>
                     30: 
1.1.1.4   root       31: /* One of the 1.1.6 "features" is a gratuitous name change */
                     32: #ifndef HAVE_GTK_FEATURES_1_1_6
                     33: #define gtk_container_set_border_width gtk_container_border_width
                     34: #endif
                     35: /* Likewise for 1.1.8.  */
                     36: #ifndef HAVE_GTK_FEATURES_1_1_8
                     37: #define gtk_label_set_text gtk_label_set
                     38: #endif
1.1.1.5   root       39: /* This is beginning to suck... */
                     40: #ifndef HAVE_GTK_FEATURES_1_1_13
                     41: #define gtk_toggle_button_set_active gtk_toggle_button_set_state
                     42: #endif
1.1.1.4   root       43: 
1.1       root       44: static int gui_active;
                     45: 
1.1.1.6   root       46: static GtkWidget *pause_uae_widget;
                     47: 
1.1       root       48: static GtkWidget *disk_insert_widget[4], *disk_eject_widget[4], *disk_text_widget[4];
                     49: static char *new_disk_string[4];
                     50: 
                     51: static GtkAdjustment *cpuspeed_adj;
1.1.1.3   root       52: static GtkWidget *cpuspeed_widgets[4], *cpuspeed_scale;
1.1.1.8 ! root       53: static GtkWidget *cpu_widget[5], *a24m_widget, *ccpu_widget;
1.1.1.2   root       54: static GtkWidget *sound_widget[4], *sound_bits_widget[2], *sound_freq_widget[3], *sound_ch_widget[2];
1.1       root       55: 
                     56: static GtkAdjustment *framerate_adj;
1.1.1.7   root       57: static GtkWidget *bimm_widget, *b32_widget, *afscr_widget, *pfscr_widget;
1.1       root       58: 
                     59: static GtkWidget *joy_widget[2][6];
                     60: 
                     61: static GtkWidget *led_widgets[5];
                     62: static GdkColor led_on[5], led_off[5];
                     63: static unsigned int prevledstate;
                     64: 
1.1.1.2   root       65: static smp_comm_pipe to_gui_pipe, from_gui_pipe;
                     66: static uae_sem_t gui_sem, gui_quit_sem; /* gui_sem protects the DFx fields */
                     67: 
                     68: static volatile int quit_gui = 0, quitted_gui = 0;
                     69: 
1.1       root       70: static void save_config (void)
                     71: {
                     72:     FILE *f;
                     73:     char tmp[257];
                     74: 
                     75:     /* Backup the options file.  */
                     76:     strcpy (tmp, optionsfile);
                     77:     strcat (tmp, "~");
                     78:     rename (optionsfile, tmp);
                     79: 
                     80:     f = fopen (optionsfile, "w");
                     81:     if (f == NULL) {
1.1.1.2   root       82:        fprintf (stderr, "Error saving options file!\n");
1.1       root       83:        return;
                     84:     }
1.1.1.4   root       85:     save_options (f, &currprefs);
1.1       root       86:     fclose (f);
                     87: }
                     88: 
                     89: static int nr_for_led (GtkWidget *led)
                     90: {
                     91:     int i;
                     92:     i = 0;
                     93:     while (led_widgets[i] != led)
                     94:        i++;
                     95:     return i;
                     96: }
                     97: 
                     98: static void enable_disk_buttons (int enable)
                     99: {
                    100:     int i;
                    101:     for (i = 0; i < 4; i++) {
                    102:        gtk_widget_set_sensitive (disk_insert_widget[i], enable);
                    103:        gtk_widget_set_sensitive (disk_eject_widget[i], enable);
                    104:     }
                    105: }
                    106: 
                    107: static void set_cpu_state (void)
                    108: {
1.1.1.5   root      109:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (a24m_widget), changed_prefs.address_space_24 != 0);
1.1.1.8 ! root      110:     gtk_widget_set_sensitive (a24m_widget, changed_prefs.cpu_level > 1 && changed_prefs.cpu_level < 4);
1.1.1.5   root      111:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (ccpu_widget), changed_prefs.cpu_compatible != 0);
1.1       root      112:     gtk_widget_set_sensitive (ccpu_widget, changed_prefs.cpu_level == 0);
1.1.1.3   root      113:     gtk_widget_set_sensitive (cpuspeed_scale, changed_prefs.m68k_speed > 0);
1.1       root      114: }
                    115: 
                    116: static void set_cpu_widget (void)
                    117: {
                    118:     int nr = changed_prefs.cpu_level;
1.1.1.5   root      119:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpu_widget[nr]), TRUE);
1.1.1.3   root      120:     nr = currprefs.m68k_speed + 1 < 3 ? currprefs.m68k_speed + 1 : 2;
1.1.1.5   root      121:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (cpuspeed_widgets[nr]), TRUE);
1.1       root      122: }
                    123: 
                    124: static void set_gfx_state (void)
                    125: {
1.1.1.5   root      126:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (bimm_widget), currprefs.immediate_blits != 0);
                    127:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (b32_widget), currprefs.blits_32bit_enabled != 0);
1.1.1.7   root      128:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (afscr_widget), currprefs.gfx_afullscreen != 0);
                    129:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pfscr_widget), currprefs.gfx_pfullscreen != 0);
1.1       root      130: }
                    131: 
1.1.1.2   root      132: static void set_sound_state (void)
                    133: {
1.1.1.5   root      134:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_widget[currprefs.produce_sound]), 1);
                    135:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_ch_widget[currprefs.stereo]), 1);
                    136:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (sound_bits_widget[currprefs.sound_bits == 16]), 1);
1.1.1.2   root      137: }
                    138: 
1.1       root      139: static void set_joy_state (void)
                    140: {
1.1.1.4   root      141:     int j0t = changed_prefs.jport0;
                    142:     int j1t = changed_prefs.jport1;
1.1       root      143:     int i;
                    144: 
                    145:     if (j0t == j1t) {
                    146:        /* Can't happen */
                    147:        j0t++;
                    148:        j0t %= 6;
                    149:     }
                    150:     for (i = 0; i < 6; i++) {
1.1.1.5   root      151:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[0][i]), j0t == i);
                    152:        gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (joy_widget[1][i]), j1t == i);
1.1       root      153:        gtk_widget_set_sensitive (joy_widget[0][i], j1t != i);
                    154:        gtk_widget_set_sensitive (joy_widget[1][i], j0t != i);
                    155:     }
                    156: }
                    157: 
                    158: static void draw_led (int nr)
                    159: {
                    160:     GtkWidget *thing = led_widgets[nr];
                    161:     GdkWindow *window = thing->window;
                    162:     GdkGC *gc = gdk_gc_new (window);
                    163:     GdkColor *col;
                    164: 
                    165:     if (gui_ledstate & (1 << nr))
                    166:        col = led_on + nr;
                    167:     else
                    168:        col = led_off + nr;
                    169:     gdk_gc_set_foreground (gc, col);
                    170:     gdk_draw_rectangle (window, gc, 1, 0, 0, -1, -1);
                    171:     gdk_gc_destroy (gc);
                    172: }
                    173: 
                    174: static int my_idle (void)
                    175: {
                    176:     unsigned int leds = gui_ledstate;
                    177:     int i;
                    178: 
                    179:     if (quit_gui) {
                    180:        /*printf("Foo...\n");*/
                    181:        gtk_main_quit ();
                    182:        goto out;
                    183:     }
                    184:     while (comm_pipe_has_data (&to_gui_pipe)) {
                    185:        int cmd = read_comm_pipe_int_blocking (&to_gui_pipe);
                    186:        int n;
                    187:        /*printf ("cmd %d\n", cmd);*/
                    188:        switch (cmd) {
                    189:         case 0:
                    190:            n = read_comm_pipe_int_blocking (&to_gui_pipe);
1.1.1.4   root      191:            gtk_label_set_text (GTK_LABEL (disk_text_widget[n]), currprefs.df[n]);
1.1       root      192:            break;
                    193:         case 1:
                    194:            /* Initialization.  */
                    195:            set_cpu_widget ();
                    196:            set_cpu_state ();
                    197:            set_gfx_state ();
                    198:            set_joy_state ();
1.1.1.2   root      199:            set_sound_state ();
1.1.1.3   root      200: 
1.1       root      201:            gui_active = 1;
                    202:            break;
                    203:        }
                    204:     }
                    205:     
                    206:     for (i = 0; i < 5; i++) {
                    207:        unsigned int mask = 1 << i;
1.1.1.2   root      208:        unsigned int on = leds & mask;
1.1       root      209: 
                    210:        if (on == (prevledstate & mask))
                    211:            continue;
                    212: 
                    213: /*     printf(": %d %d\n", i, on);*/
                    214:        draw_led (i);
                    215:     }
                    216:     prevledstate = leds;
                    217: out:
                    218:     return 1;
                    219: }
                    220: 
1.1.1.2   root      221: static int find_current_toggle (GtkWidget **widgets, int count)
                    222: {
                    223:     int i;
                    224:     for (i = 0; i < count; i++)
                    225:        if (GTK_TOGGLE_BUTTON (*widgets++)->active)
                    226:            return i;
                    227:     fprintf (stderr, "GTKUI: Can't happen!\n");
                    228:     return -1;
                    229: }
                    230: 
1.1       root      231: static void joy_changed (void)
                    232: {
                    233:     if (! gui_active)
                    234:        return;
                    235: 
1.1.1.4   root      236:     changed_prefs.jport0 = find_current_toggle (joy_widget[0], 6);
                    237:     changed_prefs.jport1 = find_current_toggle (joy_widget[1], 6);
1.1       root      238:     set_joy_state ();
                    239: }
                    240: 
1.1.1.2   root      241: static void custom_changed (void)
1.1       root      242: {
1.1.1.6   root      243:     changed_prefs.gfx_framerate = framerate_adj->value;
1.1       root      244:     changed_prefs.blits_32bit_enabled = GTK_TOGGLE_BUTTON (b32_widget)->active;
                    245:     changed_prefs.immediate_blits = GTK_TOGGLE_BUTTON (bimm_widget)->active;
1.1.1.7   root      246:     changed_prefs.gfx_afullscreen = GTK_TOGGLE_BUTTON (afscr_widget)->active;
                    247:     changed_prefs.gfx_pfullscreen = GTK_TOGGLE_BUTTON (pfscr_widget)->active;
1.1       root      248: }
                    249: 
                    250: static void cpuspeed_changed (void)
                    251: {
1.1.1.3   root      252:     int which = find_current_toggle (cpuspeed_widgets, 3);
                    253:     changed_prefs.m68k_speed = (which == 0 ? -1
                    254:                                : which == 1 ? 0
                    255:                                : cpuspeed_adj->value);
                    256:     set_cpu_state ();
1.1       root      257: }
                    258: 
                    259: static void cputype_changed (void)
                    260: {
                    261:     int i, oldcl;
                    262:     if (! gui_active)
                    263:        return;
                    264: 
                    265:     oldcl = changed_prefs.cpu_level;
                    266: 
1.1.1.8 ! root      267:     changed_prefs.cpu_level = find_current_toggle (cpu_widget, 5);
1.1       root      268:     changed_prefs.cpu_compatible = GTK_TOGGLE_BUTTON (ccpu_widget)->active;
                    269:     changed_prefs.address_space_24 = GTK_TOGGLE_BUTTON (a24m_widget)->active;
                    270: 
                    271:     if (changed_prefs.cpu_level != 0)
                    272:        changed_prefs.cpu_compatible = 0;
                    273:     /* 68000/68010 always have a 24 bit address space.  */
                    274:     if (changed_prefs.cpu_level < 2)
                    275:        changed_prefs.address_space_24 = 1;
                    276:     /* Changing from 68000/68010 to 68020 should set a sane default.  */
                    277:     else if (oldcl < 2)
                    278:        changed_prefs.address_space_24 = 0;
1.1.1.8 ! root      279: 
1.1       root      280:     set_cpu_state ();
                    281: }
                    282: 
1.1.1.2   root      283: static void sound_changed (void)
                    284: {
                    285:     changed_prefs.produce_sound = find_current_toggle (sound_widget, 4);
                    286:     changed_prefs.stereo = find_current_toggle (sound_ch_widget, 2);
                    287:     changed_prefs.sound_bits = (find_current_toggle (sound_bits_widget, 2) + 1) * 8;
                    288: }
                    289: 
1.1       root      290: static void did_reset (void)
                    291: {
                    292:     if (quit_gui)
                    293:        return;
                    294:     
                    295:     write_comm_pipe_int (&from_gui_pipe, 2, 1);
                    296: }
                    297: 
                    298: static void did_debug (void)
                    299: {
                    300:     if (quit_gui)
                    301:        return;
                    302:     
                    303:     write_comm_pipe_int (&from_gui_pipe, 3, 1);
                    304: }
                    305: 
                    306: static void did_quit (void)
                    307: {
                    308:     if (quit_gui)
                    309:        return;
                    310:     
                    311:     write_comm_pipe_int (&from_gui_pipe, 4, 1);
                    312: }
                    313: 
1.1.1.2   root      314: static void did_eject (GtkWidget *w, gpointer data)
                    315: {
1.1       root      316:     if (quit_gui)
                    317:        return;
                    318:     
                    319:     write_comm_pipe_int (&from_gui_pipe, 0, 0);
1.1.1.2   root      320:     write_comm_pipe_int (&from_gui_pipe, (int)data, 1);
1.1       root      321: }
                    322: 
1.1.1.6   root      323: static void pause_uae (GtkWidget *widget, gpointer data)
                    324: {
                    325:     if (quit_gui)
                    326:        return;
                    327: 
                    328:     write_comm_pipe_int (&from_gui_pipe, GTK_TOGGLE_BUTTON (widget)->active ? 5 : 6, 1);  
                    329: }
                    330: 
                    331: static void end_pause_uae (void)
                    332: {
                    333:     gtk_toggle_button_set_active (GTK_TOGGLE_BUTTON (pause_uae_widget), FALSE);
                    334: }
                    335:     
1.1       root      336: static int filesel_active = -1;
                    337: static GtkWidget *selector;
                    338: 
                    339: static void did_close_insert (GtkObject *o, GtkWidget *w)
                    340: {
                    341:     filesel_active = -1;
                    342:     enable_disk_buttons (1);
                    343:     gtk_widget_hide (selector);
                    344: }
                    345: 
                    346: static void did_cancel_insert (GtkObject *o)
                    347: {
                    348:     filesel_active = -1;
                    349:     enable_disk_buttons (1);
                    350:     gtk_widget_hide (selector);
                    351: }
                    352: 
                    353: static void did_insert_select (GtkObject *o)
                    354: {
                    355:     char *s = gtk_file_selection_get_filename (GTK_FILE_SELECTION (selector));
                    356:     printf ("%s\n", s);
                    357:     if (quit_gui)
                    358:        return;
                    359: 
                    360:     uae_sem_wait (&gui_sem);
                    361:     if (new_disk_string[filesel_active] != 0)
                    362:        free (new_disk_string[filesel_active]);
                    363:     new_disk_string[filesel_active] = strdup (s);
                    364:     uae_sem_post (&gui_sem);
                    365:     write_comm_pipe_int (&from_gui_pipe, 1, 0);
                    366:     write_comm_pipe_int (&from_gui_pipe, filesel_active, 1);
                    367:     filesel_active = -1;
                    368:     enable_disk_buttons (1);
                    369:     gtk_widget_hide (selector);
                    370: }
                    371: 
                    372: static char fsbuffer[100];
                    373: 
1.1.1.2   root      374: static void did_insert (GtkWidget *w, gpointer data)
1.1       root      375: {
1.1.1.2   root      376:     int n = (int)data;
1.1       root      377:     if (filesel_active != -1)
                    378:        return;
                    379:     filesel_active = n;
                    380:     enable_disk_buttons (0);
                    381: 
                    382:     sprintf (fsbuffer, "Select a disk image file for DF%d", n);
                    383:     gtk_window_set_title (GTK_WINDOW (selector), fsbuffer);
                    384: 
                    385:     /*printf("%p\n", selector);*/
                    386:     gtk_widget_show (selector);
                    387: }
                    388: 
                    389: static gint driveled_event (GtkWidget *thing, GdkEvent *event)
                    390: {
                    391:     int lednr = nr_for_led (thing);
                    392: 
                    393:     switch (event->type) {
                    394:      case GDK_MAP:
                    395:        draw_led (lednr);
                    396:        break;
                    397:      case GDK_EXPOSE:
                    398:        draw_led (lednr);
                    399:        break;
                    400:      default:
                    401:        break;
                    402:     }
                    403: 
                    404:   return 0;
                    405: }
                    406: 
1.1.1.2   root      407: static void add_empty_vbox (GtkWidget *tobox)
                    408: {
                    409:     GtkWidget *thing = gtk_vbox_new (FALSE, 0);
                    410:     gtk_widget_show (thing);
                    411:     gtk_box_pack_start (GTK_BOX (tobox), thing, TRUE, TRUE, 0);
                    412: }
                    413: 
1.1.1.3   root      414: static void add_empty_hbox (GtkWidget *tobox)
                    415: {
                    416:     GtkWidget *thing = gtk_hbox_new (FALSE, 0);
                    417:     gtk_widget_show (thing);
                    418:     gtk_box_pack_start (GTK_BOX (tobox), thing, TRUE, TRUE, 0);
                    419: }
                    420: 
1.1.1.2   root      421: static void add_centered_to_vbox (GtkWidget *vbox, GtkWidget *w)
                    422: {
                    423:     GtkWidget *hbox = gtk_hbox_new (TRUE, 0);
                    424:     gtk_widget_show (hbox);
                    425:     gtk_box_pack_start (GTK_BOX (hbox), w, TRUE, FALSE, 0);
                    426:     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
                    427: }
                    428: 
                    429: static GtkWidget *make_labelled_widget (const char *str, GtkWidget *thing)
                    430: {
                    431:     GtkWidget *label = gtk_label_new (str);
                    432:     GtkWidget *hbox2 = gtk_hbox_new (FALSE, 4);
                    433: 
                    434:     gtk_widget_show (label);
                    435:     gtk_widget_show (thing);
                    436: 
                    437:     gtk_box_pack_start (GTK_BOX (hbox2), label, FALSE, TRUE, 0);
                    438:     gtk_box_pack_start (GTK_BOX (hbox2), thing, FALSE, TRUE, 0);
                    439: 
                    440:     return hbox2;
                    441: }
                    442: 
1.1.1.3   root      443: static GtkWidget *add_labelled_widget_centered (const char *str, GtkWidget *thing, GtkWidget *vbox)
1.1.1.2   root      444: {
                    445:     GtkWidget *w = make_labelled_widget (str, thing);
                    446:     gtk_widget_show (w);
                    447:     add_centered_to_vbox (vbox, w);
1.1.1.3   root      448:     return w;
1.1.1.2   root      449: }
                    450: 
                    451: static void make_radio_group (const char **labels, GtkWidget *tobox,
                    452:                              GtkWidget **saveptr, gint t1, gint t2,
                    453:                              void (*sigfunc) (void))
                    454: {
                    455:     GtkWidget *thing = NULL;
                    456: 
                    457:     while (*labels) {
                    458:        thing = gtk_radio_button_new_with_label ((thing
                    459:                                                  ? gtk_radio_button_group (GTK_RADIO_BUTTON (thing))
                    460:                                                  : 0),
                    461:                                                 *labels++);
                    462:        *saveptr++ = thing;
                    463:        gtk_widget_show (thing);
                    464:        gtk_box_pack_start (GTK_BOX (tobox), thing, t1, t2, 0);
                    465:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
                    466:     }
                    467: }
                    468: 
                    469: static GtkWidget *make_radio_group_box (const char *title, const char **labels,
                    470:                                        GtkWidget **saveptr, int horiz,
                    471:                                        void (*sigfunc) (void))
                    472: {
                    473:     GtkWidget *frame, *newbox;
                    474: 
                    475:     frame = gtk_frame_new (title);
                    476:     newbox = (horiz ? gtk_hbox_new : gtk_vbox_new) (FALSE, 4);
                    477:     gtk_widget_show (newbox);
1.1.1.4   root      478:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1.1.1.2   root      479:     gtk_container_add (GTK_CONTAINER (frame), newbox);
                    480:     make_radio_group (labels, newbox, saveptr, horiz, !horiz, sigfunc);
                    481:     return frame;
                    482: }
                    483: 
1.1       root      484: static GtkWidget *make_led (int nr)
                    485: {
                    486:     GtkWidget *subframe, *the_led, *thing;
                    487:     GdkColormap *colormap;
                    488: 
                    489:     the_led = gtk_vbox_new (FALSE, 0);
                    490:     gtk_widget_show (the_led);
                    491: 
                    492:     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
                    493:     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
                    494:     gtk_widget_show (thing);
                    495: 
                    496:     subframe = gtk_frame_new (NULL);
                    497:     gtk_box_pack_start (GTK_BOX (the_led), subframe, TRUE, TRUE, 0);
                    498:     gtk_widget_show (subframe);
                    499: 
                    500:     thing = gtk_drawing_area_new ();
                    501:     gtk_drawing_area_size (GTK_DRAWING_AREA (thing), 20, 5);
                    502:     gtk_widget_set_events (thing, GDK_EXPOSURE_MASK);
                    503:     gtk_container_add (GTK_CONTAINER (subframe), thing);
                    504:     colormap = gtk_widget_get_colormap (thing);
                    505:     led_on[nr].red = nr == 0 ? 0xEEEE : 0xCCCC;
                    506:     led_on[nr].green = nr == 0 ? 0: 0xFFFF;
                    507:     led_on[nr].blue = 0;
                    508:     led_on[nr].pixel = 0;
                    509:     led_off[nr].red = 0;
                    510:     led_off[nr].green = 0;
                    511:     led_off[nr].blue = 0;
                    512:     led_off[nr].pixel = 0;
                    513:     gdk_color_alloc (colormap, led_on + nr);
                    514:     gdk_color_alloc (colormap, led_off + nr);
                    515:     led_widgets[nr] = thing;
                    516:     gtk_signal_connect (GTK_OBJECT (thing), "event",
                    517:                        (GtkSignalFunc) driveled_event, (gpointer) thing);
                    518:     gtk_widget_show (thing);
                    519: 
                    520:     thing = gtk_preview_new (GTK_PREVIEW_COLOR);
                    521:     gtk_box_pack_start (GTK_BOX (the_led), thing, TRUE, TRUE, 0);
                    522:     gtk_widget_show (thing);
                    523:     
                    524:     return the_led;
                    525: }
                    526: 
                    527: static void make_floppy_disks (GtkWidget *vbox)
                    528: {
1.1.1.2   root      529:     GtkWidget *thing, *subthing, *subframe, *buttonbox;
                    530:     char buf[5];
1.1       root      531:     int i;
1.1.1.2   root      532: 
                    533:     add_empty_vbox (vbox);
                    534: 
1.1       root      535:     for (i = 0; i < 4; i++) {
1.1.1.2   root      536:        /* Frame with an hbox and the "DFx:" title */
1.1       root      537:        sprintf (buf, "DF%d:", i);
1.1.1.2   root      538:        thing = gtk_frame_new (buf);
                    539:        buttonbox = gtk_hbox_new (FALSE, 4);
1.1.1.4   root      540:        gtk_container_set_border_width (GTK_CONTAINER (buttonbox), 4);
1.1.1.2   root      541:        gtk_container_add (GTK_CONTAINER (thing), buttonbox);
                    542:         gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
1.1       root      543:        gtk_widget_show (buttonbox);
                    544:        gtk_widget_show (thing);
                    545: 
1.1.1.2   root      546:        /* LED */
1.1       root      547:        subthing = make_led (i + 1);
                    548:        gtk_box_pack_start (GTK_BOX (buttonbox), subthing, FALSE, TRUE, 0);
                    549: 
1.1.1.2   root      550:        /* Current file display */
1.1       root      551:        subframe = gtk_frame_new (NULL);
                    552:        gtk_frame_set_shadow_type (GTK_FRAME (subframe), GTK_SHADOW_ETCHED_OUT);
1.1.1.2   root      553:        gtk_box_pack_start (GTK_BOX (buttonbox), subframe, TRUE, TRUE, 0);
1.1       root      554:        gtk_widget_show (subframe);
                    555:        subthing = gtk_vbox_new (FALSE, 0);
                    556:        gtk_widget_show (subthing);
                    557:        gtk_container_add (GTK_CONTAINER (subframe), subthing);
                    558:        thing = gtk_label_new ("");
                    559:        disk_text_widget[i] = thing;
                    560:        gtk_widget_show (thing);
1.1.1.2   root      561:        gtk_box_pack_start (GTK_BOX (subthing), thing, TRUE, TRUE, 0);
1.1       root      562: 
                    563:        /* Now, the buttons.  */
                    564:        thing = gtk_button_new_with_label ("Eject");
                    565:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
                    566:        gtk_widget_show (thing);
                    567:        disk_eject_widget[i] = thing;
1.1.1.2   root      568:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_eject, (gpointer) i);
1.1       root      569: 
                    570:        thing = gtk_button_new_with_label ("Insert");
                    571:        gtk_box_pack_start (GTK_BOX (buttonbox), thing, FALSE, TRUE, 0);
                    572:        gtk_widget_show (thing);
                    573:        disk_insert_widget[i] = thing;
1.1.1.2   root      574:        gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) did_insert, (gpointer) i);
1.1       root      575:     }
1.1.1.2   root      576: 
                    577:     add_empty_vbox (vbox);
1.1       root      578: }
                    579: 
1.1.1.3   root      580: static GtkWidget *make_cpu_speed_sel (void)
                    581: {
                    582:     static const char *labels[] = {
                    583:        "Optimize for host CPU speed","Approximate 68000/7MHz speed", "Adjustable",
                    584:        NULL
                    585:     };
                    586:     GtkWidget *frame, *newbox;
                    587: 
                    588:     frame = gtk_frame_new ("CPU speed");
                    589:     newbox = gtk_vbox_new (FALSE, 4);
                    590:     gtk_widget_show (newbox);
1.1.1.4   root      591:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1.1.1.3   root      592:     gtk_container_add (GTK_CONTAINER (frame), newbox);
                    593:     make_radio_group (labels, newbox, cpuspeed_widgets, 0, 1, cpuspeed_changed);
                    594: 
                    595:     cpuspeed_adj = GTK_ADJUSTMENT (gtk_adjustment_new (currprefs.m68k_speed, 1.0, 10.0, 1.0, 1.0, 1.0));
                    596:     gtk_signal_connect (GTK_OBJECT (cpuspeed_adj), "value_changed",
                    597:                        GTK_SIGNAL_FUNC (cpuspeed_changed), NULL);
                    598: 
                    599:     cpuspeed_scale = gtk_hscale_new (cpuspeed_adj);
                    600:     gtk_range_set_update_policy (GTK_RANGE (cpuspeed_scale), GTK_UPDATE_DELAYED);
                    601:     gtk_scale_set_digits (GTK_SCALE (cpuspeed_scale), 0);
                    602:     gtk_scale_set_value_pos (GTK_SCALE (cpuspeed_scale), GTK_POS_RIGHT);
                    603:     cpuspeed_scale = add_labelled_widget_centered ("Cycles per instruction:", cpuspeed_scale, newbox);
                    604: 
                    605:     return frame;
                    606: }
                    607: 
1.1.1.2   root      608: static void make_cpu_widgets (GtkWidget *vbox)
1.1       root      609: {
                    610:     int i;
1.1.1.3   root      611:     GtkWidget *newbox, *hbox, *frame;
1.1       root      612:     GtkWidget *thing;
1.1.1.2   root      613:     static const char *radiolabels[] = {
1.1.1.8 ! root      614:        "68000", "68010", "68020", "68020+68881", "68040",
1.1.1.2   root      615:        NULL
                    616:     };
                    617: 
                    618:     add_empty_vbox (vbox);
                    619: 
1.1.1.3   root      620:     hbox = gtk_hbox_new (FALSE, 0);
                    621:     add_empty_vbox (hbox);
                    622: 
                    623:     newbox = make_radio_group_box ("CPU type", radiolabels, cpu_widget, 0, cputype_changed);
1.1.1.2   root      624:     gtk_widget_show (newbox);
1.1.1.3   root      625:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
                    626: 
                    627:     newbox = make_cpu_speed_sel ();
                    628:     gtk_widget_show (newbox);
                    629:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, FALSE, 0);
                    630: 
                    631:     add_empty_vbox (hbox);
                    632:     gtk_widget_show (hbox); 
                    633:     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, FALSE, 0);
1.1       root      634: 
                    635:     frame = gtk_frame_new ("CPU flags");
1.1.1.2   root      636:     add_centered_to_vbox (vbox, frame);
1.1       root      637:     gtk_widget_show (frame);
1.1.1.2   root      638:     newbox = gtk_vbox_new (FALSE, 4);
                    639:     gtk_widget_show (newbox);
1.1.1.4   root      640:     gtk_container_set_border_width (GTK_CONTAINER (newbox), 4);
1.1.1.2   root      641:     gtk_container_add (GTK_CONTAINER (frame), newbox);
1.1       root      642: 
                    643:     a24m_widget = gtk_check_button_new_with_label ("24 bit address space");
1.1.1.2   root      644:     add_centered_to_vbox (newbox, a24m_widget);
1.1       root      645:     gtk_widget_show (a24m_widget);
                    646:     ccpu_widget = gtk_check_button_new_with_label ("Slow but compatible");
1.1.1.2   root      647:     add_centered_to_vbox (newbox, ccpu_widget);
1.1       root      648:     gtk_widget_show (ccpu_widget);
1.1.1.8 ! root      649: 
1.1.1.2   root      650:     add_empty_vbox (vbox);
                    651: 
1.1       root      652:     gtk_signal_connect (GTK_OBJECT (ccpu_widget), "clicked",
                    653:                        (GtkSignalFunc) cputype_changed, NULL);
                    654:     gtk_signal_connect (GTK_OBJECT (a24m_widget), "clicked",
                    655:                        (GtkSignalFunc) cputype_changed, NULL);    
                    656: }
                    657: 
1.1.1.2   root      658: static void make_gfx_widgets (GtkWidget *vbox)
1.1       root      659: {
                    660:     GtkWidget *thing;
                    661: 
1.1.1.2   root      662:     add_empty_vbox (vbox);
1.1       root      663: 
1.1.1.6   root      664:     framerate_adj = GTK_ADJUSTMENT (gtk_adjustment_new (currprefs.gfx_framerate, 1.0, 21.0, 1.0, 1.0, 1.0));
1.1       root      665:     gtk_signal_connect (GTK_OBJECT (framerate_adj), "value_changed",
1.1.1.2   root      666:                        GTK_SIGNAL_FUNC (custom_changed), NULL);
1.1       root      667: 
                    668:     thing = gtk_hscale_new (framerate_adj);
                    669:     gtk_range_set_update_policy (GTK_RANGE (thing), GTK_UPDATE_DELAYED);
                    670:     gtk_scale_set_digits (GTK_SCALE (thing), 0);
                    671:     gtk_scale_set_value_pos (GTK_SCALE (thing), GTK_POS_RIGHT);
1.1.1.2   root      672:     add_labelled_widget_centered ("Framerate:", thing, vbox);
1.1       root      673: 
                    674:     b32_widget = gtk_check_button_new_with_label ("32 bit blitter");
1.1.1.2   root      675:     add_centered_to_vbox (vbox, b32_widget);
1.1.1.7   root      676: #if 0
1.1       root      677:     gtk_widget_show (b32_widget);
1.1.1.7   root      678: #endif
1.1       root      679:     bimm_widget = gtk_check_button_new_with_label ("Immediate blits");
1.1.1.2   root      680:     add_centered_to_vbox (vbox, bimm_widget);
1.1       root      681:     gtk_widget_show (bimm_widget);
                    682: 
1.1.1.7   root      683:     afscr_widget = gtk_check_button_new_with_label ("Amiga modes fullscreen");
                    684:     add_centered_to_vbox (vbox, afscr_widget);
                    685: #if 0
                    686:     gtk_widget_show (afscr_widget);
                    687: #endif
                    688:     pfscr_widget = gtk_check_button_new_with_label ("Picasso modes fullscreen");
                    689:     add_centered_to_vbox (vbox, pfscr_widget);
                    690: #if 0
                    691:     gtk_widget_show (pfscr_widget);
                    692: #endif
1.1.1.2   root      693:     add_empty_vbox (vbox);
                    694: 
1.1       root      695:     gtk_signal_connect (GTK_OBJECT (bimm_widget), "clicked",
1.1.1.2   root      696:                        (GtkSignalFunc) custom_changed, NULL);
1.1       root      697:     gtk_signal_connect (GTK_OBJECT (b32_widget), "clicked",
1.1.1.2   root      698:                        (GtkSignalFunc) custom_changed, NULL);
1.1.1.7   root      699:     gtk_signal_connect (GTK_OBJECT (afscr_widget), "clicked",
                    700:                        (GtkSignalFunc) custom_changed, NULL);
                    701:     gtk_signal_connect (GTK_OBJECT (pfscr_widget), "clicked",
                    702:                        (GtkSignalFunc) custom_changed, NULL);
1.1.1.2   root      703: }
                    704: 
                    705: static void make_sound_widgets (GtkWidget *vbox)
                    706: {
                    707:     GtkWidget *frame, *newbox;
                    708:     int i;
                    709:     GtkWidget *hbox;
                    710:     static const char *soundlabels1[] = {
                    711:        "None", "No output", "Normal", "Accurate",
                    712:        NULL
                    713:     }, *soundlabels2[] = {
                    714:        "8 bit", "16 bit",
                    715:        NULL
                    716:     }, *soundlabels3[] = {
                    717:        "Mono", "Stereo",
                    718:        NULL
                    719:     };
                    720: 
                    721:     add_empty_vbox (vbox);
                    722: 
                    723:     newbox = make_radio_group_box ("Mode", soundlabels1, sound_widget, 1, sound_changed);
                    724:     gtk_widget_show (newbox);
                    725:     add_centered_to_vbox (vbox, newbox);
                    726: 
                    727:     hbox = gtk_hbox_new (FALSE, 10);
                    728:     gtk_widget_show (hbox);
                    729:     add_centered_to_vbox (vbox, hbox);
                    730:     newbox = make_radio_group_box ("Channels", soundlabels3, sound_ch_widget, 1, sound_changed);
                    731:     gtk_widget_show (newbox);
                    732:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
                    733:     newbox = make_radio_group_box ("Resolution", soundlabels2, sound_bits_widget, 1, sound_changed);
                    734:     gtk_widget_show (newbox);
                    735:     gtk_box_pack_start (GTK_BOX (hbox), newbox, FALSE, TRUE, 0);
1.1.1.3   root      736: 
1.1.1.2   root      737:     add_empty_vbox (vbox);
1.1       root      738: }
                    739: 
1.1.1.2   root      740: static void make_joy_widgets (GtkWidget *dvbox)
1.1       root      741: {
                    742:     int i;
1.1.1.2   root      743:     GtkWidget *hbox = gtk_hbox_new (FALSE, 10);
                    744:     static const char *joylabels[] = {
                    745:        "Joystick 0", "Joystick 1", "Mouse", "Numeric pad",
                    746:        "Cursor keys/Right Ctrl", "T/F/H/B/Left Alt",
                    747:        NULL
                    748:     };
                    749: 
                    750:     add_empty_vbox (dvbox);
                    751:     gtk_widget_show (hbox);
                    752:     add_centered_to_vbox (dvbox, hbox);
1.1       root      753: 
                    754:     for (i = 0; i < 2; i++) {
                    755:        GtkWidget *vbox, *frame;
                    756:        GtkWidget *thing;
                    757:        char buffer[20];
                    758:        int j;
                    759: 
                    760:        sprintf (buffer, "Port %d", i);
1.1.1.2   root      761:        frame = make_radio_group_box (buffer, joylabels, joy_widget[i], 0, joy_changed);
1.1       root      762:        gtk_widget_show (frame);
1.1.1.2   root      763:        gtk_box_pack_start (GTK_BOX (hbox), frame, FALSE, TRUE, 0);
1.1       root      764:     }
1.1.1.2   root      765: 
                    766:     add_empty_vbox (dvbox);
                    767: }
                    768: 
1.1.1.6   root      769: static GtkWidget *make_buttons (const char *label, GtkWidget *box, void (*sigfunc) (void), GtkWidget *(*create)(const char *label))
1.1.1.2   root      770: {
1.1.1.6   root      771:     GtkWidget *thing = create (label);
1.1.1.2   root      772:     gtk_widget_show (thing);
                    773:     gtk_signal_connect (GTK_OBJECT (thing), "clicked", (GtkSignalFunc) sigfunc, NULL);
                    774:     gtk_box_pack_start (GTK_BOX (box), thing, TRUE, TRUE, 0);
1.1.1.6   root      775: 
                    776:     return thing;
1.1       root      777: }
1.1.1.6   root      778: #define make_button(label, box, sigfunc) make_buttons(label, box, sigfunc, gtk_button_new_with_label)
1.1       root      779: 
                    780: static void *gtk_penguin (void *dummy)
                    781: {
                    782:     GtkWidget *window, *notebook;
1.1.1.2   root      783:     GtkWidget *buttonbox, *vbox, *hbox;
1.1       root      784:     GtkWidget *thing;
                    785:     int i;
                    786:     int argc = 1;
                    787:     char *a[] = {"UAE"};
                    788:     char **argv = a;
1.1.1.2   root      789:     static const struct _pages {
                    790:        const char *title;
                    791:        void (*createfunc)(GtkWidget *);
                    792:     } pages[] = {
                    793:        { "Floppy disks", make_floppy_disks },
                    794:        { "CPU emulation", make_cpu_widgets },
                    795:        { "Graphics", make_gfx_widgets },
                    796:        { "Sound", make_sound_widgets },
                    797:        { "Game ports", make_joy_widgets }
                    798:     };
1.1       root      799: 
                    800:     gtk_init (&argc, &argv);
                    801:     gtk_rc_parse ("uaegtkrc");
                    802: 
                    803:     window = gtk_window_new (GTK_WINDOW_TOPLEVEL);
1.1.1.2   root      804:     gtk_window_set_title (GTK_WINDOW (window), "UAE control");
1.1       root      805: 
                    806:     vbox = gtk_vbox_new (FALSE, 4);
                    807:     gtk_container_add (GTK_CONTAINER (window), vbox);
1.1.1.4   root      808:     gtk_container_set_border_width (GTK_CONTAINER (window), 10);
1.1       root      809: 
1.1.1.2   root      810:     /* First line - buttons and power LED */
                    811:     hbox = gtk_hbox_new (FALSE, 10);
                    812:     gtk_widget_show (hbox);
                    813:     gtk_box_pack_start (GTK_BOX (vbox), hbox, FALSE, TRUE, 0);
1.1       root      814: 
1.1.1.2   root      815:     /* The buttons */
                    816:     buttonbox = gtk_hbox_new (TRUE, 4);
1.1       root      817:     gtk_widget_show (buttonbox);
1.1.1.2   root      818:     gtk_box_pack_start (GTK_BOX (hbox), buttonbox, TRUE, TRUE, 0);
                    819:     make_button ("Reset", buttonbox, did_reset);
                    820:     make_button ("Debug", buttonbox, did_debug);
                    821:     make_button ("Quit", buttonbox, did_quit);
                    822:     make_button ("Save config", buttonbox, save_config);
1.1.1.6   root      823:     pause_uae_widget = make_buttons ("Pause", buttonbox, pause_uae, gtk_toggle_button_new_with_label);
1.1       root      824: 
1.1.1.2   root      825:     /* The LED */
                    826:     thing = make_led (0);
                    827:     thing = make_labelled_widget ("Power:", thing);
1.1       root      828:     gtk_widget_show (thing);
1.1.1.2   root      829:     gtk_box_pack_start (GTK_BOX (hbox), thing, FALSE, TRUE, 0);
1.1       root      830: 
1.1.1.2   root      831:     /* Place a separator below those buttons.  */
1.1       root      832:     thing = gtk_hseparator_new ();
                    833:     gtk_box_pack_start (GTK_BOX (vbox), thing, FALSE, TRUE, 0);
                    834:     gtk_widget_show (thing);
                    835: 
1.1.1.2   root      836:     /* Now the notebook */
1.1       root      837:     notebook = gtk_notebook_new ();
1.1.1.2   root      838:     gtk_box_pack_start (GTK_BOX (vbox), notebook, TRUE, TRUE, 0);
1.1       root      839:     gtk_widget_show (notebook);
                    840: 
1.1.1.2   root      841:     for (i = 0; i < sizeof pages / sizeof (struct _pages); i++) {
                    842:        thing = gtk_vbox_new (FALSE, 4);
                    843:        gtk_widget_show (thing);
1.1.1.4   root      844:        gtk_container_set_border_width (GTK_CONTAINER (thing), 10);
1.1.1.2   root      845:        pages[i].createfunc (thing);
                    846:        gtk_notebook_append_page (GTK_NOTEBOOK (notebook), thing, gtk_label_new (pages[i].title));
                    847:     }
1.1       root      848: 
                    849:     enable_disk_buttons (1);
                    850: 
                    851:     gtk_widget_show (vbox);
                    852:     gtk_widget_show (window);
                    853: 
                    854:     /* We're going to need that later.  */
                    855:     selector = gtk_file_selection_new ("");
                    856:     gtk_signal_connect (GTK_OBJECT (selector), "destroy",
                    857:                        (GtkSignalFunc) did_close_insert, selector);
                    858: 
                    859:     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->ok_button),
                    860:                               "clicked", (GtkSignalFunc) did_insert_select,
                    861:                               GTK_OBJECT (selector));
                    862:     gtk_signal_connect_object (GTK_OBJECT (GTK_FILE_SELECTION (selector)->cancel_button),
                    863:                               "clicked", (GtkSignalFunc) did_cancel_insert,
                    864:                               GTK_OBJECT (selector));
                    865:     filesel_active = -1;
                    866: 
                    867:     gtk_timeout_add (1000, (GtkFunction)my_idle, 0);
                    868:     gtk_main ();
                    869:     
                    870:     quitted_gui = 1;
                    871:     uae_sem_post (&gui_quit_sem);
                    872:     return 0;
                    873: }
                    874: 
                    875: void gui_changesettings(void)
                    876: {
                    877:     
                    878: }
                    879: 
                    880: int gui_init (void)
                    881: {
                    882:     penguin_id tid;
                    883: 
                    884:     gui_active = 0;
                    885:     
                    886:     init_comm_pipe (&to_gui_pipe, 20, 1);
                    887:     init_comm_pipe (&from_gui_pipe, 20, 1);
                    888:     uae_sem_init (&gui_sem, 0, 1);
                    889:     uae_sem_init (&gui_quit_sem, 0, 0);
                    890:     start_penguin (gtk_penguin, NULL, &tid);
                    891:     return 1;
                    892: }
                    893: 
                    894: int gui_update (void)
                    895: {
                    896:     if (no_gui)
                    897:        return 0;
                    898: 
                    899:     write_comm_pipe_int (&to_gui_pipe, 1, 1);    
                    900:     return 0;
                    901: }
                    902: 
                    903: void gui_exit (void)
                    904: {
                    905:     if (no_gui)
                    906:        return;
                    907: 
                    908:     quit_gui = 1;
                    909:     uae_sem_wait (&gui_quit_sem);
                    910: }
                    911: 
1.1.1.4   root      912: void gui_fps (int x)
                    913: {
                    914: }
                    915: 
                    916: void gui_led (int num, int on)
1.1       root      917: {
                    918:     if (no_gui)
                    919:        return;
                    920: 
                    921: /*    if (num == 0)
                    922:        return;
                    923:     printf("LED %d %d\n", num, on);
                    924:     write_comm_pipe_int (&to_gui_pipe, 1, 0);
                    925:     write_comm_pipe_int (&to_gui_pipe, num == 0 ? 4 : num - 1, 0);
                    926:     write_comm_pipe_int (&to_gui_pipe, on, 1);
                    927:     printf("#LED %d %d\n", num, on);*/
                    928: }
                    929: 
                    930: void gui_filename(int num, const char *name)
                    931: {
                    932:     if (no_gui)
                    933:        return;
                    934: 
                    935:     write_comm_pipe_int (&to_gui_pipe, 0, 0);
                    936:     write_comm_pipe_int (&to_gui_pipe, num, 1);
                    937: 
                    938: /*    gui_update ();*/
                    939: }
                    940: 
                    941: void gui_handle_events(void)
                    942: {
1.1.1.6   root      943:     int pause_uae = FALSE;
                    944:     
1.1       root      945:     if (no_gui)
                    946:        return;
                    947: 
1.1.1.6   root      948:     do {
                    949:         while (pause_uae || comm_pipe_has_data (&from_gui_pipe)) {
                    950:             int cmd = read_comm_pipe_int_blocking (&from_gui_pipe);
                    951:             int n;
                    952:             switch (cmd) {
                    953:              case 0:
                    954:                 n = read_comm_pipe_int_blocking (&from_gui_pipe);
                    955:                 changed_prefs.df[n][0] = '\0';
                    956:                 break;
                    957:              case 1:
                    958:                 n = read_comm_pipe_int_blocking (&from_gui_pipe);
                    959:                 uae_sem_wait (&gui_sem);
                    960:                 strncpy (changed_prefs.df[n], new_disk_string[n], 255);
                    961:                 changed_prefs.df[n][255] = '\0';
                    962:                 uae_sem_post (&gui_sem);
                    963:                 break;
                    964:              case 2:
                    965:                 uae_reset ();
                    966:                 end_pause_uae ();
                    967:                 break;
                    968:              case 3:
                    969:                 activate_debugger ();
                    970:                 end_pause_uae ();
                    971:                 break;
                    972:              case 4:
                    973:                 uae_quit ();
                    974:                 end_pause_uae ();
                    975:                 break;
                    976:              case 5:
                    977:                 pause_uae = TRUE;
                    978:                 break;
                    979:              case 6:
                    980:                 pause_uae = FALSE;
                    981:                 break;
                    982:             }
                    983:         }
                    984:     } while (pause_uae);
1.1       root      985: }
1.1.1.7   root      986: 
                    987: void gui_update_gfx (void)
                    988: {
                    989: #if 0 /* This doesn't work... */
                    990:     set_gfx_state ();
                    991: #endif
                    992: }

unix.superglobalmegacorp.com

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