uae-wii/src/main.c

1167 lines
27 KiB
C

/*
* 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 <assert.h>
#if defined(GEKKO)
#include <gccore.h>
#include <ogc/usbstorage.h>
#include <fat.h>
#include <network.h>
#include <smb.h>
#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;
bool usbismount = false;
bool networkisinit = false;
bool smbismount = false;
bool sdismount = false;
int log_quiet = 0;
#if defined(GEKKO)
/****************************************************************************
* Mount SMB Share
****************************************************************************/
bool ConnectShare ()
{
if(smbismount)
return true;
//printf("user: %s\n", network_prefs.SmbUser);
//printf("pass: %s\n", network_prefs.SmbPwd);
//printf("share: %s\n", network_prefs.SmbShare);
//printf("ip: %s\n\n", network_prefs.SmbIp);
int a;
for (a=0;a<3;a++)
if(smbInit(currprefs.SmbUser, currprefs.SmbPwd,currprefs.SmbShare, currprefs.SmbIp))
{smbismount = true; break;}
if(!smbismount) printf("Failed to connect to SMB share\n\n");
else {
printf("Established connection to SMB share\n\n");
}
return smbismount;
}
void CloseShare()
{
if(smbismount) {
printf("Disconnected from SMB share\n");
smbClose("smb");
}
smbismount = false;
}
/****************************************************************************
* init and deinit USB device functions
****************************************************************************/
bool InitUSB()
{
printf("Initializing USB FAT subsytem ...\n\n");
fatUnmount("usb:");
// This should wake up the drive
bool isMounted = fatMountSimple("usb", &__io_usbstorage);
bool isInserted = __io_usbstorage.isInserted();
if (!isInserted)
{
printf("USB device not found\n\n");
return false;
}
// USB Drive may be "sleeeeping"
// We need to try Mounting a few times to wake it up
int retry = 10;
while (retry && !isMounted)
{
sleep(1);
isMounted = fatMountSimple("usb", &__io_usbstorage);
retry--;
}
if (isMounted)
printf("USB FAT subsytem initialized\n\n");
else
printf("Impossible to initialize USB FAT subsytem\n\n");
return isMounted;
}
void DeInitUSB()
{
fatUnmount("usb:");
__io_usbstorage.shutdown();
}
bool InitNetwork()
{
char myIP[16];
memset(myIP, 0, sizeof(myIP));
printf("Getting IP address via DHCP...\n\n");
if (if_config(myIP, NULL, NULL, true) < 0) {
printf("No DHCP reply\n\n");
return false;
}
printf("Got an address: %s\n\n",myIP);
return true;
}
#endif
/*
* 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;
}
}
void fix_options (void)
{
int err = 0;
if ((currprefs.cpu_level < 2)&&(currprefs.address_space_24==0))
{
currprefs.address_space_24 = 1;
write_log ("With 68000/68010 address space is always 24 bit\n");
err = 1;
}
if ((currprefs.cpu_level >= 4)&&(currprefs.address_space_24==1))
{
currprefs.address_space_24 = 0;
write_log("With 68040/060 address space is always 32 bit\n");
err = 1;
}
if ((currprefs.cpu_level != 0)&&(currprefs.cpu_compatible == 1))
{
currprefs.cpu_compatible = 0;
write_log ("Compatible emulation is available only for 68000\n");
err = 1;
}
if ((currprefs.cpu_level != 0)&&(currprefs.cpu_cycle_exact == 1))
{
currprefs.cpu_cycle_exact = 0;
write_log ("Cycle-exact emulation is available only for 68000\n");
err = 1;
}
if ((currprefs.bogomem_size > 0x100000) && ((currprefs.chipset_mask & CSMASK_AGA)))
{
currprefs.bogomem_size = 0x100000;
write_log ("No more than 1MB slowmem with AGA\n");
err = 1;
}
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", (long unsigned int) 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)
{
write_log (UAE_VERSION_STRING "\n");
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++;
}
else strncpy (currprefs.df[0], argv[1], 255); currprefs.df[0][255] = 0; //Load the argument without - in df0
}
}
}
#endif
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
}
cfgfile_load (&currprefs, SAVEDFILENAME, 0);
cfgfile_load (&currprefs, USERFILENAME, 0);
parse_cmdline (argc, argv);
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
#ifdef FILESYS
rtarea_init ();
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 (&regs); /* compatibility with old state saves */
}
savestate_restore_finish ();
#endif
fill_prefetch_slow (&regs);
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 ();
hardfile_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 ();
#ifdef 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)
{
#ifdef GEKKO
printf("\x1b[2;0H");
//initialize libfat library
if (fatInitDefault())
printf("FAT subsytem initialized\n\n");
else
{
printf("Couldn't initialize FAT subsytem\n\n");
sleep(3);
exit(0);
}
DIR *dp;
dp = opendir ("sd:/");
if (dp) sdismount = 1; else sdismount = 0;
if (sdismount)
printf("SD FAT subsytem initialized\n\n");
else
printf("Couldn't initialize SD fat subsytem\n\n");
if (sdismount) closedir (dp);
usbismount = InitUSB();
default_prefs (&currprefs, 0);
cfgfile_load (&currprefs, SMBFILENAME, 0);
printf("\n");
if (currprefs.smb_enable) networkisinit = InitNetwork();
if (networkisinit && currprefs.smb_enable) ConnectShare();
sleep(3);
// clear the screen
printf("\x1b[2J");
printf("\x1b[2;0H");
if (!(log_quiet = !currprefs.write_logfile)) set_logfile("/uae/uae.log");
#endif
write_log("main started\n");
init_sdl ();
write_log("sdl inited\n");
gui_init (argc, argv);
write_log("Starting real main\n");
real_main (argc, argv);
#ifdef GEKKO
if (smbismount) CloseShare ();
DeInitUSB();
fatUnmount(0);
#endif
return 0;
}
#endif
#ifdef SINGLEFILE
uae_u8 singlefile_config[50000] = { "_CONFIG_STARTS_HERE" };
uae_u8 singlefile_data[1500000] = { "_DATA_STARTS_HERE" };
#endif