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

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

unix.superglobalmegacorp.com

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