/* * UAE - The Un*x Amiga Emulator * * Main program * * Copyright 1995 Ed Hanway * Copyright 1995, 1996, 1997 Bernd Schmidt * Copyright 2006-2007 Richard Drummond */ #include "sysconfig.h" #include "sysdeps.h" #include #if defined(GEKKO) # include #endif #include "options.h" #include "threaddep/thread.h" #include "uae.h" #include "audio.h" #include "events.h" #include "memory.h" #include "custom.h" #include "serial.h" #include "newcpu.h" #include "disk.h" #include "debug.h" #include "xwin.h" #include "drawing.h" #include "inputdevice.h" #include "keybuf.h" #include "gui.h" #include "zfile.h" #include "autoconf.h" #include "traps.h" #include "osemu.h" #include "filesys.h" #include "picasso96.h" #include "bsdsocket.h" #include "uaeexe.h" #include "native2amiga.h" #include "scsidev.h" #include "akiko.h" #include "savestate.h" #include "hrtimer.h" #include "sleep.h" #include "version.h" #ifdef USE_SDL #include "SDL.h" #endif #ifdef WIN32 //FIXME: This shouldn't be necessary #include "windows.h" #endif struct uae_prefs currprefs, changed_prefs; static int restart_program; static char restart_config[256]; static char optionsfile[256]; int cloanto_rom = 0; int log_scsi; struct gui_info gui_data; /* * Random prefs-related junk that needs to go elsewhere. */ void fixup_prefs_dimensions (struct uae_prefs *prefs) { if (prefs->gfx_width_fs < 320) prefs->gfx_width_fs = 320; if (prefs->gfx_height_fs < 200) prefs->gfx_height_fs = 200; if (prefs->gfx_height_fs > 1280) prefs->gfx_height_fs = 1280; prefs->gfx_width_fs += 7; prefs->gfx_width_fs &= ~7; if (prefs->gfx_width_win < 320) prefs->gfx_width_win = 320; if (prefs->gfx_height_win < 200) prefs->gfx_height_win = 200; if (prefs->gfx_height_win > 1280) prefs->gfx_height_win = 1280; prefs->gfx_width_win += 7; prefs->gfx_width_win &= ~7; } static void fixup_prefs_joysticks (struct uae_prefs *prefs) { int joy_count = inputdevice_get_device_total (IDTYPE_JOYSTICK); /* If either port is configured to use a non-existent joystick, try * to use a sensible alternative. */ if (prefs->jport0 >= JSEM_JOYS && prefs->jport0 < JSEM_MICE) { if (prefs->jport0 - JSEM_JOYS >= joy_count) prefs->jport0 = (prefs->jport1 != JSEM_MICE) ? JSEM_MICE : JSEM_NONE; } if (prefs->jport1 >= JSEM_JOYS && prefs->jport1 < JSEM_MICE) { if (prefs->jport1 - JSEM_JOYS >= joy_count) prefs->jport1 = (prefs->jport0 != JSEM_KBDLAYOUT) ? JSEM_KBDLAYOUT : JSEM_NONE; } } static void fix_options (void) { int err = 0; if ((currprefs.chipmem_size & (currprefs.chipmem_size - 1)) != 0 || currprefs.chipmem_size < 0x40000 || currprefs.chipmem_size > 0x800000) { currprefs.chipmem_size = 0x200000; write_log ("Unsupported chipmem size!\n"); err = 1; } if (currprefs.chipmem_size > 0x80000) currprefs.chipset_mask |= CSMASK_ECS_AGNUS; if ((currprefs.fastmem_size & (currprefs.fastmem_size - 1)) != 0 || (currprefs.fastmem_size != 0 && (currprefs.fastmem_size < 0x100000 || currprefs.fastmem_size > 0x800000))) { currprefs.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 > 0x2000000))) { write_log ("Unsupported graphics card memory size %lx!\n", currprefs.gfxmem_size); currprefs.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 > 0x20000000))) { currprefs.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; 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 != 0 && currprefs.bogomem_size != 0x80000 && currprefs.bogomem_size != 0x100000 && currprefs.bogomem_size != 0x1C0000) { currprefs.bogomem_size = 0; write_log ("Unsupported bogomem size!\n"); err = 1; } if (currprefs.chipmem_size > 0x200000 && currprefs.fastmem_size != 0) { write_log ("You can't use fastmem and more than 2MB chip at the same time!\n"); currprefs.fastmem_size = 0; err = 1; } #if 0 if (currprefs.m68k_speed < -1 || currprefs.m68k_speed > 20) { write_log ("Bad value for -w parameter: must be -1, 0, or within 1..20.\n"); currprefs.m68k_speed = 4; err = 1; } #endif if (currprefs.produce_sound < 0 || currprefs.produce_sound > 3) { write_log ("Bad value for -S parameter: enable value must be within 0..3\n"); currprefs.produce_sound = 0; err = 1; } #ifdef JIT if (currprefs.comptrustbyte < 0 || currprefs.comptrustbyte > 3) { write_log ("Bad value for comptrustbyte parameter: value must be within 0..2\n"); currprefs.comptrustbyte = 1; err = 1; } if (currprefs.comptrustword < 0 || currprefs.comptrustword > 3) { write_log ("Bad value for comptrustword parameter: value must be within 0..2\n"); currprefs.comptrustword = 1; err = 1; } if (currprefs.comptrustlong < 0 || currprefs.comptrustlong > 3) { write_log ("Bad value for comptrustlong parameter: value must be within 0..2\n"); currprefs.comptrustlong = 1; err = 1; } if (currprefs.comptrustnaddr < 0 || currprefs.comptrustnaddr > 3) { write_log ("Bad value for comptrustnaddr parameter: value must be within 0..2\n"); currprefs.comptrustnaddr = 1; err = 1; } if (currprefs.compnf < 0 || currprefs.compnf > 1) { write_log ("Bad value for compnf parameter: value must be within 0..1\n"); currprefs.compnf = 1; err = 1; } if (currprefs.comp_hardflush < 0 || currprefs.comp_hardflush > 1) { write_log ("Bad value for comp_hardflush parameter: value must be within 0..1\n"); currprefs.comp_hardflush = 1; err = 1; } if (currprefs.comp_constjump < 0 || currprefs.comp_constjump > 1) { write_log ("Bad value for comp_constjump parameter: value must be within 0..1\n"); currprefs.comp_constjump = 1; err = 1; } if (currprefs.comp_oldsegv < 0 || currprefs.comp_oldsegv > 1) { write_log ("Bad value for comp_oldsegv parameter: value must be within 0..1\n"); currprefs.comp_oldsegv = 1; err = 1; } if (currprefs.cachesize < 0 || currprefs.cachesize > 16384) { write_log ("Bad value for cachesize parameter: value must be within 0..16384\n"); currprefs.cachesize = 0; err = 1; } #endif if (currprefs.cpu_level < 2 && currprefs.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; err = 1; } if (currprefs.gfxmem_size > 0 && (currprefs.cpu_level < 2 || currprefs.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; err = 1; } #ifndef BSDSOCKET if (currprefs.socket_emu) { write_log ("Compile-time option of BSDSOCKET was not enabled. You can't use bsd-socket emulation.\n"); currprefs.socket_emu = 0; err = 1; } #endif if (currprefs.nr_floppies < 0 || currprefs.nr_floppies > 4) { write_log ("Invalid number of floppies. Using 4.\n"); currprefs.nr_floppies = 4; currprefs.dfxtype[0] = 0; currprefs.dfxtype[1] = 0; currprefs.dfxtype[2] = 0; currprefs.dfxtype[3] = 0; err = 1; } if (currprefs.floppy_speed > 0 && currprefs.floppy_speed < 10) { currprefs.floppy_speed = 100; } if (currprefs.input_mouse_speed < 1 || currprefs.input_mouse_speed > 1000) { currprefs.input_mouse_speed = 100; } if (currprefs.collision_level < 0 || currprefs.collision_level > 3) { write_log ("Invalid collision support level. Using 1.\n"); currprefs.collision_level = 1; err = 1; } fixup_prefs_dimensions (&currprefs); #ifdef CPU_68000_ONLY currprefs.cpu_level = 0; #endif #ifndef CPUEMU_0 currprefs.cpu_compatible = 1; currprefs.address_space_24 = 1; #endif #if !defined(CPUEMU_5) && !defined (CPUEMU_6) currprefs.cpu_compatible = 0; currprefs.address_space_24 = 0; #endif #if !defined (CPUEMU_6) currprefs.cpu_cycle_exact = currprefs.blitter_cycle_exact = 0; #endif #ifndef AGA currprefs.chipset_mask &= ~CSMASK_AGA; #endif #ifndef AUTOCONFIG currprefs.z3fastmem_size = 0; currprefs.fastmem_size = 0; currprefs.gfxmem_size = 0; #endif #if !defined (BSDSOCKET) currprefs.socket_emu = 0; #endif #if !defined (SCSIEMU) currprefs.scsi = 0; #ifdef _WIN32 currprefs.win32_aspi = 0; #endif #endif fixup_prefs_joysticks (&currprefs); if (err) write_log ("Please use \"uae -h\" to get usage information.\n"); } #ifndef DONT_PARSE_CMDLINE void usage (void) { cfgfile_show_usage (); } static void show_version (void) { #ifdef PACKAGE_VERSION write_log (PACKAGE_NAME " " PACKAGE_VERSION "\n"); #else write_log ("UAE %d.%d.%d\n", UAEMAJOR, UAEMINOR, UAESUBREV); #endif write_log ("Build date: " __DATE__ " " __TIME__ "\n"); } static void show_version_full (void) { write_log ("\n"); show_version (); write_log ("\nCopyright 2003-2007 Richard Drummond and contributors.\n"); write_log ("Based on source code from:\n"); write_log ("UAE - copyright 1995-2002 Bernd Schmidt;\n"); write_log ("WinUAE - copyright 1999-2007 Toni Wilen.\n"); write_log ("See the source code for a full list of contributors.\n"); write_log ("This is free software; see the file COPYING for copying conditions. There is NO\n"); write_log ("warranty; not even for MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.\n"); } static void parse_cmdline (int argc, char **argv) { int i; for (i = 1; i < argc; i++) { if (strcmp (argv[i], "-cfgparam") == 0) { if (i + 1 < argc) i++; } else if (strncmp (argv[i], "-config=", 8) == 0) { #ifdef FILESYS free_mountinfo (currprefs.mountinfo); #endif if (cfgfile_load (&currprefs, argv[i] + 8, 0)) strcpy (optionsfile, argv[i] + 8); } /* Check for new-style "-f xxx" argument, where xxx is config-file */ else if (strcmp (argv[i], "-f") == 0) { if (i + 1 == argc) { write_log ("Missing argument for '-f' option.\n"); } else { #ifdef FILESYS free_mountinfo (currprefs.mountinfo); #endif if (cfgfile_load (&currprefs, argv[++i], 0)) strcpy (optionsfile, argv[i]); } } else if (strcmp (argv[i], "-s") == 0) { if (i + 1 == argc) write_log ("Missing argument for '-s' option.\n"); else cfgfile_parse_line (&currprefs, argv[++i], 0); } else if (strcmp (argv[i], "-h") == 0 || strcmp (argv[i], "-help") == 0) { usage (); exit (0); } else if (strcmp (argv[i], "-version") == 0) { show_version_full (); exit (0); } else if (strcmp (argv[i], "-scsilog") == 0) { log_scsi = 1; } else { if (argv[i][0] == '-' && argv[i][1] != '\0') { const char *arg = argv[i] + 2; int extra_arg = *arg == '\0'; if (extra_arg) arg = i + 1 < argc ? argv[i + 1] : 0; if (parse_cmdline_option (&currprefs, argv[i][1], (char*)arg) && extra_arg) i++; } } } } #endif static void parse_user_conf_file(const char *extension) { /* FIXME! ska: This is temporary, and will be removed when you can * pass command line options in meta.xml for the homebrew channel */ char user_options[255] = ""; char *user_argv[] = {"program", "-f", user_options}; #ifdef OPTIONS_IN_HOME char *home = getenv ("HOME"); if (home != NULL && strlen (home) < 240) { strcpy (user_options, home); strcat (user_options, "/"); } #endif strcat(user_options, OPTIONSFILENAME); strcat(user_options, extension); /* Allow the user uaerc to override the default one */ parse_cmdline (3, user_argv); /* Until here */ } static void parse_cmdline_and_init_file (int argc, char **argv) { char *home; #ifdef _WIN32 extern char *start_path; #endif strcpy (optionsfile, ""); #ifdef OPTIONS_IN_HOME home = getenv ("HOME"); if (home != NULL && strlen (home) < 240) { strcpy (optionsfile, home); strcat (optionsfile, "/"); } #endif #ifdef _WIN32 sprintf( optionsfile, "%s\\Configurations\\", start_path ); #endif strcat (optionsfile, OPTIONSFILENAME); if (! cfgfile_load (&currprefs, optionsfile, 0)) { // write_log ("failed to load config '%s'\n", optionsfile); #ifdef OPTIONS_IN_HOME /* sam: if not found in $HOME then look in current directory */ char *saved_path = strdup (optionsfile); strcpy (optionsfile, OPTIONSFILENAME); if (! cfgfile_load (&currprefs, optionsfile, 0) ) { /* If not in current dir either, change path back to home * directory - so that a GUI can save a new config file there */ strcpy (optionsfile, saved_path); } free (saved_path); #endif } fix_options (); parse_cmdline (argc, argv); parse_user_conf_file(".saved"); parse_user_conf_file(".user"); fix_options (); } /* * Save the currently loaded configuration. */ void uae_save_config (void) { FILE *f; char tmp[257]; /* Back up the old file. */ strcpy (tmp, optionsfile); strcat (tmp, "~"); write_log ("Backing-up config file '%s' to '%s'\n", optionsfile, tmp); rename (optionsfile, tmp); write_log ("Writing new config file '%s'\n", optionsfile); f = fopen (optionsfile, "w"); if (f == NULL) { gui_message ("Error saving configuration file.!\n"); // FIXME - better error msg. return; } // FIXME - either fix this nonsense, or only allow config to be saved when emulator is stopped. if (uae_get_state () == UAE_STATE_STOPPED) save_options (f, &changed_prefs, 0); else save_options (f, &currprefs, 0); fclose (f); } /* * A first cut at better state management... */ static int uae_state; static int uae_target_state; int uae_get_state (void) { return uae_state; } static void set_state (int state) { uae_state = state; gui_notify_state (state); graphics_notify_state (state); } int uae_state_change_pending (void) { return uae_state != uae_target_state; } void uae_start (void) { uae_target_state = UAE_STATE_COLD_START; } void uae_pause (void) { if (uae_target_state == UAE_STATE_RUNNING) uae_target_state = UAE_STATE_PAUSED; } void uae_resume (void) { if (uae_target_state == UAE_STATE_PAUSED) uae_target_state = UAE_STATE_RUNNING; } void uae_quit (void) { if (uae_target_state != UAE_STATE_QUITTING) { uae_target_state = UAE_STATE_QUITTING; } } void uae_stop (void) { if (uae_target_state != UAE_STATE_QUITTING && uae_target_state != UAE_STATE_STOPPED) { uae_target_state = UAE_STATE_STOPPED; restart_config[0] = 0; } } void uae_reset (int hard_reset) { switch (uae_target_state) { case UAE_STATE_QUITTING: case UAE_STATE_STOPPED: case UAE_STATE_COLD_START: case UAE_STATE_WARM_START: /* Do nothing */ break; default: uae_target_state = hard_reset ? UAE_STATE_COLD_START : UAE_STATE_WARM_START; } } /* This needs to be rethought */ void uae_restart (int opengui, char *cfgfile) { uae_stop (); restart_program = opengui > 0 ? 1 : (opengui == 0 ? 2 : 3); restart_config[0] = 0; if (cfgfile) strcpy (restart_config, cfgfile); } /* * Early initialization of emulator, parsing of command-line options, * and loading of config files, etc. * * TODO: Need better cohesion! Break this sucker up! */ static int do_preinit_machine (int argc, char **argv) { if (! graphics_setup ()) { exit (1); } if (restart_config[0]) { #ifdef FILESYS free_mountinfo (currprefs.mountinfo); #endif default_prefs (&currprefs, 0); fix_options (); } #ifdef NATMEM_OFFSET init_shm (); #endif rtarea_init (); #ifdef FILESYS hardfile_install (); #endif if (restart_config[0]) parse_cmdline_and_init_file (argc, argv); else currprefs = changed_prefs; uae_inithrtimer (); machdep_init (); if (! audio_setup ()) { write_log ("Sound driver unavailable: Sound output disabled\n"); currprefs.produce_sound = 0; } inputdevice_init (); return 1; } /* * Initialization of emulator proper */ static int do_init_machine (void) { #ifdef JIT if (!(( currprefs.cpu_level >= 2 ) && ( currprefs.address_space_24 == 0 ) && ( currprefs.cachesize ))) canbang = 0; #endif #ifdef _WIN32 logging_init(); /* Yes, we call this twice - the first case handles when the user has loaded a config using the cmd-line. This case handles loads through the GUI. */ #endif #ifdef SAVESTATE savestate_init (); #endif #ifdef SCSIEMU scsidev_install (); #endif #ifdef AUTOCONFIG /* Install resident module to get 8MB chipmem, if requested */ rtarea_setup (); #endif keybuf_init (); /* Must come after init_joystick */ #ifdef AUTOCONFIG expansion_init (); #endif memory_init (); memory_reset (); #ifdef FILESYS filesys_install (); #endif #ifdef AUTOCONFIG bsdlib_install (); emulib_install (); uaeexe_install (); native2amiga_install (); #endif if (custom_init ()) { /* Must come after memory_init */ #ifdef SERIAL_PORT serial_init (); #endif DISK_init (); reset_frame_rate_hack (); init_m68k(); /* must come after reset_frame_rate_hack (); */ gui_update (); if (graphics_init ()) { #ifdef DEBUGGER setup_brkhandler (); if (currprefs.start_debugger && debuggable ()) activate_debugger (); #endif #ifdef WIN32 #ifdef FILESYS filesys_init (); /* New function, to do 'add_filesys_unit()' calls at start-up */ #endif #endif if (sound_available && currprefs.produce_sound > 1 && ! audio_init ()) { write_log ("Sound driver unavailable: Sound output disabled\n"); currprefs.produce_sound = 0; } return 1; } } return 0; } /* * Helper for reset method */ static void reset_all_systems (void) { init_eventtab (); memory_reset (); #ifdef BSDSOCKET bsdlib_reset (); #endif #ifdef FILESYS filesys_reset (); filesys_start_threads (); hardfile_reset (); #endif #ifdef SCSIEMU scsidev_reset (); scsidev_start_threads (); #endif } /* * Reset emulator */ static void do_reset_machine (int hardreset) { #ifdef SAVESTATE if (savestate_state == STATE_RESTORE) restore_state (savestate_fname); else if (savestate_state == STATE_REWIND) savestate_rewind (); #endif /* following three lines must not be reordered or * fastram state restore breaks */ reset_all_systems (); customreset (); m68k_reset (); if (hardreset) { memset (chipmemory, 0, allocated_chipmem); write_log ("chipmem cleared\n"); } #ifdef SAVESTATE /* We may have been restoring state, but we're done now. */ if (savestate_state == STATE_RESTORE || savestate_state == STATE_REWIND) { map_overlay (1); fill_prefetch_slow (®s); /* compatibility with old state saves */ } savestate_restore_finish (); #endif fill_prefetch_slow (®s); if (currprefs.produce_sound == 0) eventtab[ev_audio].active = 0; handle_active_events (); inputdevice_updateconfig (&currprefs); } /* * Run emulator */ static void do_run_machine (void) { #if defined (NATMEM_OFFSET) && defined( _WIN32 ) && !defined( NO_WIN32_EXCEPTION_HANDLER ) extern int EvalException ( LPEXCEPTION_POINTERS blah, int n_except ); __try #endif { m68k_go (1); } #if defined (NATMEM_OFFSET) && defined( _WIN32 ) && !defined( NO_WIN32_EXCEPTION_HANDLER ) __except( EvalException( GetExceptionInformation(), GetExceptionCode() ) ) { // EvalException does the good stuff... } #endif } /* * Exit emulator */ static void do_exit_machine (void) { graphics_leave (); inputdevice_close (); #ifdef SCSIEMU scsidev_exit (); #endif DISK_free (); audio_close (); dump_counts (); #ifdef SERIAL_PORT serial_exit (); #endif #ifdef CD32 akiko_free (); #endif gui_exit (); #ifdef AUTOCONFIG expansion_cleanup (); #endif #ifdef FILESYS filesys_cleanup (); #endif #ifdef SAVESTATE savestate_free (); #endif memory_cleanup (); cfgfile_addcfgparam (0); } /* * Here's where all the action takes place! */ void real_main (int argc, char **argv) { show_version (); #if defined(FILESYS) currprefs.mountinfo = changed_prefs.mountinfo = &options_mountinfo; #endif restart_program = 1; #ifdef _WIN32 sprintf (restart_config, "%sConfigurations\\", start_path); #endif strcat (restart_config, OPTIONSFILENAME); /* Initial state is stopped */ uae_target_state = UAE_STATE_STOPPED; while (uae_target_state != UAE_STATE_QUITTING) { int want_gui; set_state (uae_target_state); do_preinit_machine (argc, argv); /* Should we open the GUI? TODO: This mess needs to go away */ want_gui = currprefs.start_gui; if (restart_program == 2) want_gui = 0; else if (restart_program == 3) want_gui = 1; changed_prefs = currprefs; if (want_gui) { /* Handle GUI at start-up */ int err = gui_open (); if (err >= 0) { do { gui_handle_events (); uae_msleep (10); } while (!uae_state_change_pending ()); } else if (err == - 1) { if (restart_program == 3) { restart_program = 0; uae_quit (); } } else uae_quit (); currprefs = changed_prefs; fix_options (); inputdevice_init (); } restart_program = 0; if (uae_target_state == UAE_STATE_QUITTING) break; uae_target_state = UAE_STATE_COLD_START; /* Start emulator proper. */ if (!do_init_machine ()) break; while (uae_target_state != UAE_STATE_QUITTING && uae_target_state != UAE_STATE_STOPPED) { /* Reset */ set_state (uae_target_state); do_reset_machine (uae_state == UAE_STATE_COLD_START); /* Running */ uae_target_state = UAE_STATE_RUNNING; /* * Main Loop */ do { set_state (uae_target_state); /* Run emulator. */ do_run_machine (); if (uae_target_state == UAE_STATE_PAUSED) { /* Paused */ set_state (uae_target_state); audio_pause (); /* While UAE is paused we have to handle * input events, etc. ourselves. */ do { gui_handle_events (); handle_events (); /* Manually pump input device */ inputdevicefunc_keyboard.read (); inputdevicefunc_mouse.read (); inputdevicefunc_joystick.read (); inputdevice_handle_inputcode (); /* Don't busy wait. */ uae_msleep (10); } while (!uae_state_change_pending ()); audio_resume (); } } while (uae_target_state == UAE_STATE_RUNNING); /* * End of Main Loop * * We're no longer running or paused. */ set_inhibit_frame (IHF_QUIT_PROGRAM); #ifdef FILESYS /* Ensure any cached changes to virtual filesystem are flushed before * resetting or exitting. */ filesys_prepare_reset (); #endif } /* while (!QUITTING && !STOPPED) */ do_exit_machine (); /* TODO: This stuff is a hack. What we need to do is * check whether a config GUI is available. If not, * then quit. */ restart_program = 3; } zfile_exit (); } #ifdef USE_SDL int init_sdl (void) { int result = (SDL_Init (SDL_INIT_VIDEO | SDL_INIT_TIMER /*| SDL_INIT_AUDIO*/) == 0); if (result) atexit (SDL_Quit); return result; } #else #define init_sdl() #endif #ifndef NO_MAIN_IN_MAIN_C int main (int argc, char **argv) { fprintf(stderr, "main started\n"); #if defined(GEKKO) fatInitDefault(); #endif init_sdl (); fprintf(stderr, "sdl inited\n"); gui_init (argc, argv); fprintf(stderr, "Starting real main\n"); real_main (argc, argv); return 0; } #endif #ifdef SINGLEFILE uae_u8 singlefile_config[50000] = { "_CONFIG_STARTS_HERE" }; uae_u8 singlefile_data[1500000] = { "_DATA_STARTS_HERE" }; #endif