--- uae/src/main.c 2018/04/24 16:48:39 1.1.1.9 +++ uae/src/main.c 2018/04/24 17:21:48 1.1.1.24 @@ -6,48 +6,52 @@ * Copyright 1995 Ed Hanway * Copyright 1995, 1996, 1997 Bernd Schmidt */ - #include "sysconfig.h" #include "sysdeps.h" #include -#include "config.h" #include "options.h" -#include "threaddep/penguin.h" +#include "threaddep/thread.h" #include "uae.h" #include "gensound.h" +#include "audio.h" #include "sounddep/sound.h" #include "events.h" #include "memory.h" #include "custom.h" #include "serial.h" -#include "readcpu.h" #include "newcpu.h" #include "disk.h" #include "debug.h" #include "xwin.h" -#include "joystick.h" +#include "inputdevice.h" #include "keybuf.h" #include "gui.h" #include "zfile.h" #include "autoconf.h" +#include "filesys.h" #include "osemu.h" -#include "osdep/exectasks.h" -#include "compiler.h" #include "picasso96.h" +#include "traps.h" #include "bsdsocket.h" #include "uaeexe.h" #include "native2amiga.h" #include "scsidev.h" +#include "romlist.h" -long int version = 256*65536L*UAEMAJOR + 65536L*UAEMINOR + UAESUBREV; +#ifdef USE_SDL +#include "SDL.h" +#endif struct uae_prefs currprefs, changed_prefs; +struct gfx_params *curr_gfx; int no_gui = 0; int joystickpresent = 0; int cloanto_rom = 0; +struct gui_info gui_data; + char warning_buffer[256]; char optionsfile[256]; @@ -61,9 +65,6 @@ char optionsfile[256]; * PostScript printer or ghostscript -=SR=- */ -/* People must provide their own name for this */ -char sername[256] = ""; - /* Slightly stupid place for this... */ /* ncurses.c might use quite a few of those. */ char *colormodes[] = { "256 colors", "32768 colors", "65536 colors", @@ -75,6 +76,99 @@ char *colormodes[] = { "256 colors", "32 "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "", "" }; +struct uae_rect *gfx_fullscreen_modes, *gfx_windowed_modes; +int n_fullscreen_modes, n_windowed_modes; + +static struct uae_rect default_windowed_modes[] = +{ + { 320, 256 }, + { 400, 300 }, + { 640, 512 }, + { 800, 600 } +}; + +struct config_list *predef_configs; +int n_predef_configs; +int predef_configs_space; + +static int sortfn (const void *a, const void *b) +{ + struct config_list *pa = (struct config_list *)a; + struct config_list *pb = (struct config_list *)b; + return strcmp (pa->sortstr, pb->sortstr); +} + +static void scan_configs (const char *path) +{ + DIR *dir; + int pathlen = strlen (path); + int bufsz = pathlen + 256; + char *buffer; + uae_u8 *data; + + predef_configs_space = 20; + predef_configs = malloc (sizeof (struct config_list) * 20); + n_predef_configs = 0; + + dir = opendir (path); + if (!dir) + return; + + buffer = malloc (bufsz); + if (!buffer) + goto out; + data = malloc (1024 * 1024); + if (!data) + goto out1; + + strcpy (buffer, path); + buffer[pathlen++] = '/'; + buffer[pathlen] = '\0'; + for (;;) { + struct uae_prefs p; + struct zfile *f; + struct dirent *ent = readdir (dir); + int len; + struct romdata *rd; + long size; + + if (!ent) + break; + + len = strlen (ent->d_name); + if (len + pathlen + 1 >= bufsz) { + bufsz = len + pathlen + 200; + buffer = realloc (buffer, bufsz); + if (!buffer) { + free (data); + goto out; + } + } + strcpy (buffer + pathlen, ent->d_name); + + if (n_predef_configs >= predef_configs_space) { + predef_configs_space += 20; + predef_configs = realloc (predef_configs, + sizeof (struct config_list) * predef_configs_space); + } + default_prefs (&p); + strcpy (p.description, ""); + strcpy (p.sortstr, ""); + cfgfile_load (&p, buffer); + if (strlen (p.description) > 0) { + predef_configs[n_predef_configs].filename = strdup (buffer); + predef_configs[n_predef_configs].description = strdup (p.description); + predef_configs[n_predef_configs++].sortstr = strdup (p.sortstr); + } + } + qsort (predef_configs, n_predef_configs, sizeof *predef_configs, sortfn); + free (data); + out1: + free (buffer); + out: + closedir (dir); +} + void discard_prefs (struct uae_prefs *p) { struct strlist **ps = &p->unknown_lines; @@ -98,36 +192,40 @@ void default_prefs (struct uae_prefs *p) /* Note to porters: please don't change any of these options! UAE is supposed * to behave identically on all platforms if possible. */ p->illegal_mem = 0; - p->no_xhair = 0; p->use_serial = 0; p->serial_demand = 0; p->parallel_demand = 0; - p->automount_uaedev = 1; - p->jport0 = 2; - p->jport1 = 0; + p->jport0 = JSEM_MICE; + p->jport1 = JSEM_JOYS; + p->keyboard_lang = KBD_LANG_US; p->emul_accuracy = 2; p->test_drawing_speed = 0; - p->produce_sound = 0; - p->stereo = 0; - p->sound_bits = DEFAULT_SOUND_BITS; + p->produce_sound = 3; + p->sound_stereo = 0; + p->sound_stereo_separation = 7; + p->sound_mixed_stereo_delay = 0; p->sound_freq = DEFAULT_SOUND_FREQ; - p->sound_minbsiz = DEFAULT_SOUND_MINB; p->sound_maxbsiz = DEFAULT_SOUND_MAXB; - p->sound_interpol = 0; + p->sound_interpol = 2; + p->sound_filter = FILTER_SOUND_OFF; + p->sound_filter_type = FILTER_SOUND_TYPE_A500; p->gfx_framerate = 1; - p->gfx_width = 800; - p->gfx_height = 600; - p->gfx_lores = 0; - p->gfx_linedbl = 0; + p->gfx_w.width = 800; + p->gfx_w.height = 600; + p->gfx_w.lores = 0; + p->gfx_w.linedbl = 2; + p->gfx_w.correct_aspect = 0; + p->gfx_w.xcenter = 0; + p->gfx_w.ycenter = 0; + p->gfx_f = p->gfx_w; + p->gfx_w.leds_on_screen = 0; + p->gfx_f.leds_on_screen = 1; p->gfx_afullscreen = 0; p->gfx_pfullscreen = 0; - p->gfx_correct_aspect = 0; - p->gfx_xcenter = 0; - p->gfx_ycenter = 0; p->color_mode = 0; p->x11_use_low_bandwidth = 0; @@ -136,15 +234,23 @@ void default_prefs (struct uae_prefs *p) p->svga_no_linear = 0; + p->curses_reverse_video = 0; + p->win32_middle_mouse = 0; - p->win32_sound_style = 0; - p->win32_sound_tweak = 0; p->win32_logfile = 0; p->win32_iconified_nospeed = 0; p->win32_iconified_nosound = 0; + p->win32_no_overlay = 0; p->immediate_blits = 0; - p->blits_32bit_enabled = 0; + p->collision_level = 1; + + p->chipset_mask = CSMASK_ECS_AGNUS; + p->cs_rtc = 2; + p->cs_a1000ram = 0; + p->cs_fatgaryrev = -1; + p->cs_ramseyrev = -1; + p->cs_ide = 0; strcpy (p->df[0], "df0.adf"); strcpy (p->df[1], "df1.adf"); @@ -154,132 +260,179 @@ void default_prefs (struct uae_prefs *p) strcpy (p->romfile, "kick.rom"); strcpy (p->keyfile, ""); strcpy (p->prtname, DEFPRTNAME); + p->rom_crc32 = 0; strcpy (p->path_rom, "./"); strcpy (p->path_floppy, "./"); strcpy (p->path_hardfile, "./"); - p->m68k_speed = 4; - p->cpu_level = 2; - p->cpu_compatible = 0; + strcpy (p->prtname, ""); + strcpy (p->sername, ""); + + p->nr_floppies = 2; + p->dfxtype[0] = DRV_35_DD; + p->dfxtype[1] = DRV_35_DD; + p->dfxtype[2] = DRV_NONE; + p->dfxtype[3] = DRV_NONE; + + p->m68k_speed = 0; + p->cpu_model = 68020; + p->fpu_model = 0; p->address_space_24 = 0; p->fastmem_size = 0x00000000; - p->a3000mem_size = 0x00000000; + p->mbresmem_low_size = 0x00000000; + p->mbresmem_high_size = 0x00000000; p->z3fastmem_size = 0x00000000; p->chipmem_size = 0x00200000; p->bogomem_size = 0x00000000; p->gfxmem_size = 0x00000000; p->mountinfo = alloc_mountinfo (); + inputdevice_default_prefs (p); + p->bootrom = 1; } -void fixup_prefs_dimensions (struct uae_prefs *prefs) +int fixup_prefs_dimensions (struct gfx_params *p, struct uae_rect *modes, int n_modes) { - if (prefs->gfx_width < 320) - prefs->gfx_width = 320; - if (prefs->gfx_height < 200) - prefs->gfx_height = 200; - if (prefs->gfx_height > 300 && ! prefs->gfx_linedbl) - prefs->gfx_height = 300; - if (prefs->gfx_height > 600) - prefs->gfx_height = 600; + int i; + if (p->width < 320) + p->width = 320; + if (p->height < 200) + p->height = 200; + for (i = 0; i < n_modes; i++) { + if ((modes[i].w >= p->width && modes[i].h >= p->height) + || i == n_modes - 1) + { + p->width = modes[i].w; + p->height = modes[i].h; + p->lores = p->width <= 512; + if (p->height > 300 && !p->linedbl) + p->linedbl = 1; + return i; + } + } + return n_modes - 1; +} - prefs->gfx_width += 7; /* X86.S wants multiples of 4 bytes, might be 8 in the future. */ - prefs->gfx_width &= ~7; +static void fixup_sound (struct uae_prefs *p) +{ + if (p->sound_stereo_separation < 0) + p->sound_stereo_separation = 0; + if (p->sound_stereo_separation > MIXED_STEREO_MAX) + p->sound_stereo_separation = MIXED_STEREO_MAX; } -static void fix_options (void) +static void fixup_prefs (struct uae_prefs *p) { int err = 0; - if ((currprefs.chipmem_size & (currprefs.chipmem_size - 1)) != 0 - || currprefs.chipmem_size < 0x80000 - || currprefs.chipmem_size > 0x800000) + if ((p->chipmem_size & (p->chipmem_size - 1)) != 0 + || p->chipmem_size < 0x80000 + || p->chipmem_size > 0x800000) { - currprefs.chipmem_size = 0x200000; - fprintf (stderr, "Unsupported chipmem size!\n"); + p->chipmem_size = 0x200000; + write_log ("Unsupported chipmem size!\n"); err = 1; } - if ((currprefs.fastmem_size & (currprefs.fastmem_size - 1)) != 0 - || (currprefs.fastmem_size != 0 && (currprefs.fastmem_size < 0x100000 || currprefs.fastmem_size > 0x800000))) + if ((p->fastmem_size & (p->fastmem_size - 1)) != 0 + || (p->fastmem_size != 0 && (p->fastmem_size < 0x100000 || p->fastmem_size > 0x800000))) { - currprefs.fastmem_size = 0; - fprintf (stderr, "Unsupported fastmem size!\n"); + p->fastmem_size = 0; + write_log ("Unsupported fastmem size!\n"); err = 1; } - if ((currprefs.gfxmem_size & (currprefs.gfxmem_size - 1)) != 0 - || (currprefs.gfxmem_size != 0 && (currprefs.gfxmem_size < 0x100000 || currprefs.gfxmem_size > 0x800000))) + if ((p->gfxmem_size & (p->gfxmem_size - 1)) != 0 + || (p->gfxmem_size != 0 && (p->gfxmem_size < 0x100000 || p->gfxmem_size > 0x2000000))) { - currprefs.gfxmem_size = 0; - fprintf (stderr, "Unsupported graphics card memory size!\n"); + write_log ("Unsupported graphics card memory size %lx!\n", p->gfxmem_size); + p->gfxmem_size = 0; err = 1; } - if ((currprefs.z3fastmem_size & (currprefs.z3fastmem_size - 1)) != 0 - || (currprefs.z3fastmem_size != 0 && (currprefs.z3fastmem_size < 0x100000 || currprefs.z3fastmem_size > 0x4000000))) + if ((p->z3fastmem_size & (p->z3fastmem_size - 1)) != 0 + || (p->z3fastmem_size != 0 && (p->z3fastmem_size < 0x100000 || p->z3fastmem_size > 0x10000000))) { - currprefs.z3fastmem_size = 0; - fprintf (stderr, "Unsupported Zorro III fastmem size!\n"); + p->z3fastmem_size = 0; + write_log ("Unsupported Zorro III fastmem size!\n"); err = 1; } - if (currprefs.address_space_24 && (currprefs.gfxmem_size != 0 || currprefs.z3fastmem_size != 0)) { - currprefs.z3fastmem_size = currprefs.gfxmem_size = 0; - fprintf (stderr, "Can't use a graphics card or Zorro III fastmem when using a 24 bit\n" + if (p->address_space_24 && (p->gfxmem_size != 0 || p->z3fastmem_size != 0)) { + p->z3fastmem_size = p->gfxmem_size = 0; + write_log ("Can't use a graphics card or Zorro III fastmem when using a 24 bit\n" "address space - sorry.\n"); } - if ((currprefs.bogomem_size & (currprefs.bogomem_size - 1)) != 0 - || (currprefs.bogomem_size != 0 && (currprefs.bogomem_size < 0x80000 || currprefs.bogomem_size > 0x100000))) + if ((p->bogomem_size & (p->bogomem_size - 1)) != 0 + || (p->bogomem_size != 0 && (p->bogomem_size < 0x80000 || p->bogomem_size > 0x100000))) { - currprefs.bogomem_size = 0; - fprintf (stderr, "Unsupported bogomem size!\n"); + p->bogomem_size = 0; + write_log ("Unsupported bogomem size!\n"); err = 1; } - if (currprefs.chipmem_size > 0x200000 && currprefs.fastmem_size != 0) { - fprintf (stderr, "You can't use fastmem and more than 2MB chip at the same time!\n"); - currprefs.fastmem_size = 0; + if (p->chipmem_size > 0x200000 && p->fastmem_size != 0) { + write_log ("You can't use fastmem and more than 2MB chip at the same time!\n"); + p->fastmem_size = 0; err = 1; } - if (currprefs.m68k_speed < -1 || currprefs.m68k_speed > 20) { - fprintf (stderr, "Bad value for -w parameter: must be -1, 0, or within 1..20.\n"); - currprefs.m68k_speed = 4; +#if 0 + if (p->m68k_speed < -1 || p->m68k_speed > 20) { + write_log ("Bad value for -w parameter: must be -1, 0, or within 1..20.\n"); + p->m68k_speed = 4; err = 1; } - if (currprefs.produce_sound < 0 || currprefs.produce_sound > 3) { - fprintf (stderr, "Bad value for -S parameter: enable value must be within 0..3\n"); - currprefs.produce_sound = 0; +#endif + + if (p->produce_sound < 0 || p->produce_sound > 3) { + write_log ("Bad value for -S parameter: enable value must be within 0..3\n"); + p->produce_sound = 0; err = 1; } - if (currprefs.cpu_level < 2 && currprefs.z3fastmem_size > 0) { - fprintf (stderr, "Z3 fast memory can't be used with a 68000/68010 emulation. It\n" + if (p->cpu_model < 68020 && p->z3fastmem_size > 0) { + write_log ("Z3 fast memory can't be used with a 68000/68010 emulation. It\n" "requires a 68020 emulation. Turning off Z3 fast memory.\n"); - currprefs.z3fastmem_size = 0; + p->z3fastmem_size = 0; err = 1; } - if (currprefs.gfxmem_size > 0 && (currprefs.cpu_level < 2 || currprefs.address_space_24)) { - fprintf (stderr, "Picasso96 can't be used with a 68000/68010 or 68EC020 emulation. It\n" + if (p->gfxmem_size > 0 && (p->cpu_model < 68020 || p->address_space_24)) { + write_log ("Picasso96 can't be used with a 68000/68010 or 68EC020 emulation. It\n" "requires a 68020 emulation. Turning off Picasso96.\n"); - currprefs.gfxmem_size = 0; + p->gfxmem_size = 0; err = 1; } -#ifndef BSDSOCKET_SUPPORTED - if (currprefs.socket_emu) { - fprintf (stderr, "Compile-time option of BSDSOCKET_SUPPORTED was not enabled. You can't use bsd-socket emulation.\n"); - currprefs.socket_emu = 0; +#ifndef BSDSOCKET + if (p->socket_emu) { + write_log ("Compile-time option of BSDSOCKET_SUPPORTED was not enabled. You can't use bsd-socket emulation.\n"); + p->socket_emu = 0; err = 1; } #endif + if (p->nr_floppies < 1 || p->nr_floppies > 4) { + write_log ("Invalid number of floppies. Using 4.\n"); + p->nr_floppies = 4; + err = 1; + } + if (p->collision_level < 0 || p->collision_level > 3) { + write_log ("Invalid collision support level. Using 1.\n"); + p->collision_level = 1; + err = 1; + } + + fixup_sound (p); + if (err) - fprintf (stderr, "Please use \"uae -h\" to get usage information.\n"); + write_log ("Please use \"uae -h\" to get usage information.\n"); } int quit_program = 0; -void uae_reset (void) +void uae_reset (int hardreset) { - if (quit_program == 0) + if (quit_program == 0) { quit_program = -2; + if (hardreset) + quit_program = -3; + } } void uae_quit (void) @@ -288,24 +441,6 @@ void uae_quit (void) quit_program = -1; } -const char *gameport_state (int nr) -{ - if (JSEM_ISJOY0 (nr, &currprefs) && nr_joysticks > 0) - return "using joystick #0"; - else if (JSEM_ISJOY1 (nr, &currprefs) && nr_joysticks > 1) - return "using joystick #1"; - else if (JSEM_ISMOUSE (nr, &currprefs)) - return "using mouse"; - else if (JSEM_ISNUMPAD (nr, &currprefs)) - return "using numeric pad as joystick"; - else if (JSEM_ISCURSOR (nr, &currprefs)) - return "using cursor keys as joystick"; - else if (JSEM_ISSOMEWHEREELSE (nr, &currprefs)) - return "using T/F/H/B/Alt as joystick"; - - return "not connected"; -} - #ifndef DONT_PARSE_CMDLINE void usage (void) @@ -321,12 +456,12 @@ void parse_cmdline (int argc, char **arg /* Check for new-style "-f xxx" argument, where xxx is config-file */ else if (strcmp (argv[i], "-f") == 0) { if (i + 1 == argc) - fprintf (stderr, "Missing argument for '-f' option.\n"); + write_log ("Missing argument for '-f' option.\n"); else cfgfile_load (&currprefs, argv[++i]); } else if (strcmp (argv[i], "-s") == 0) { if (i + 1 == argc) - fprintf (stderr, "Missing argument for '-s' option.\n"); + write_log ("Missing argument for '-s' option.\n"); else cfgfile_parse_line (&currprefs, argv[++i]); } else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "-help") == 0) { @@ -335,9 +470,11 @@ void parse_cmdline (int argc, char **arg } else { if (argv[i][0] == '-' && argv[i][1] != '\0') { const char *arg = argv[i] + 2; - if (*arg == '\0') + int extra_arg = *arg == '\0'; + if (extra_arg) arg = i + 1 < argc ? argv[i + 1] : 0; - i += parse_cmdline_option (argv[i][1], arg); + if (parse_cmdline_option (&currprefs, argv[i][1], arg) && extra_arg) + i++; } } } @@ -363,40 +500,23 @@ static void parse_cmdline_and_init_file if (! cfgfile_load (&currprefs, optionsfile)) { #ifdef OPTIONS_IN_HOME - /* sam: if not found in $HOME then look in current directory */ + /* If not found in $HOME then look in current directory. However, + * don't use the optionsfile variable, so that we will save changes + * to the home directory. */ + char pwd_optionsfile[256]; strcpy (optionsfile, OPTIONSFILENAME); cfgfile_load (&currprefs, optionsfile); - } #endif + } parse_cmdline (argc, argv); } -void write_log_standard (const char *fmt, ...) -{ - va_list ap; - va_start (ap, fmt); -#ifdef HAVE_VFPRINTF - vfprintf (stderr, fmt, ap); -#else - /* Technique stolen from GCC. */ - { - int x1, x2, x3, x4, x5, x6, x7, x8; - x1 = va_arg (ap, int); - x2 = va_arg (ap, int); - x3 = va_arg (ap, int); - x4 = va_arg (ap, int); - x5 = va_arg (ap, int); - x6 = va_arg (ap, int); - x7 = va_arg (ap, int); - x8 = va_arg (ap, int); - fprintf (stderr, fmt, x1, x2, x3, x4, x5, x6, x7, x8); - } -#endif -} - void reset_all_systems (void) { + init_eventtab (); + + memory_reset (); bsdlib_reset (); filesys_reset (); filesys_start_threads (); @@ -416,21 +536,31 @@ void reset_all_systems (void) void do_start_program (void) { + if (quit_program == -1) + return; + inputdevice_updateconfig (&currprefs); + /* Do a reset on startup. Whether this is elegant is debatable. */ - quit_program = 2; + if (quit_program >= 0) + quit_program = 2; m68k_go (1); } void do_leave_program (void) { graphics_leave (); - close_joystick (); + inputdevice_close (); close_sound (); dump_counts (); serial_exit (); zfile_exit (); if (! no_gui) gui_exit (); +#ifdef USE_SDL + SDL_Quit (); +#endif + expansion_cleanup (); + memory_cleanup (); } void start_program (void) @@ -447,8 +577,21 @@ void real_main (int argc, char **argv) { FILE *hf; +#ifdef USE_SDL + SDL_Init (SDL_INIT_EVERYTHING | SDL_INIT_NOPARACHUTE); +#endif + default_prefs (&currprefs); - + +#ifdef SYSTEM_CFGDIR + scan_configs (SYSTEM_CFGDIR); +#endif + + /* Can be overriden in graphics_setup, although there's not much of a + point. Fullscreen modes are filled in by graphics_setup. */ + gfx_windowed_modes = default_windowed_modes; + n_windowed_modes = sizeof default_windowed_modes / sizeof *default_windowed_modes; + if (! graphics_setup ()) { exit (1); } @@ -460,30 +603,37 @@ void real_main (int argc, char **argv) parse_cmdline_and_init_file (argc, argv); machdep_init (); + init_gtod (); if (! setup_sound ()) { - fprintf (stderr, "Sound driver unavailable: Sound output disabled\n"); + write_log ("Sound driver unavailable: Sound output disabled\n"); currprefs.produce_sound = 0; } - init_joystick (); + inputdevice_init (); + changed_prefs = currprefs; no_gui = ! currprefs.start_gui; if (! no_gui) { - int err = gui_init (); + int err = gui_init (1); + currprefs = changed_prefs; if (err == -1) { - fprintf (stderr, "Failed to initialize the GUI\n"); + write_log ("Failed to initialize the GUI\n"); } else if (err == -2) { exit (0); } } - if (sound_available && currprefs.produce_sound > 1 && ! init_sound ()) { - fprintf (stderr, "Sound driver unavailable: Sound output disabled\n"); + if (sound_available && currprefs.produce_sound > 1 && ! init_audio ()) { + write_log ("Sound driver unavailable: Sound output disabled\n"); currprefs.produce_sound = 0; } - fix_options (); + fixup_prefs (&currprefs); changed_prefs = currprefs; +#ifdef SYSTEM_ROMDIR + scan_roms (SYSTEM_ROMDIR, ROMLOC_SYSTEM); +#endif + scan_roms (currprefs.path_rom, ROMLOC_USER); /* Install resident module to get 8MB chipmem, if requested */ rtarea_setup (); @@ -493,7 +643,7 @@ void real_main (int argc, char **argv) memory_init (); filesys_install (); - gfxlib_install (); + bsdlib_install (); emulib_install (); uaeexe_install (); native2amiga_install (); @@ -505,10 +655,10 @@ void real_main (int argc, char **argv) reset_frame_rate_hack (); init_m68k(); /* must come after reset_frame_rate_hack (); */ - compiler_init (); gui_update (); if (graphics_init ()) { + reset_drawing (); setup_brkhandler (); if (currprefs.start_debugger && debuggable ()) activate_debugger (); @@ -518,6 +668,12 @@ void real_main (int argc, char **argv) leave_program (); } +void uae_abort (const char *msg) +{ + write_log ("%s", msg); + abort (); +} + #ifndef NO_MAIN_IN_MAIN_C int main (int argc, char **argv) {