WinUAE/main.cpp
2012-08-26 14:18:48 +03:00

1057 lines
24 KiB
C++

/*
* UAE - The Un*x Amiga Emulator
*
* Main program
*
* Copyright 1995 Ed Hanway
* Copyright 1995, 1996, 1997 Bernd Schmidt
*/
#include "sysconfig.h"
#include "sysdeps.h"
#include <assert.h>
#include "options.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 "newcpu.h"
#include "disk.h"
#include "debug.h"
#include "xwin.h"
#include "inputdevice.h"
#include "keybuf.h"
#include "gui.h"
#include "zfile.h"
#include "autoconf.h"
#include "traps.h"
#include "osemu.h"
#include "picasso96.h"
#include "bsdsocket.h"
#include "uaeexe.h"
#include "native2amiga.h"
#include "scsidev.h"
#include "uaeserial.h"
#include "akiko.h"
#include "cdtv.h"
#include "savestate.h"
#include "filesys.h"
#include "parallel.h"
#include "a2091.h"
#include "a2065.h"
#include "ncr_scsi.h"
#include "scsi.h"
#include "sana2.h"
#include "blkdev.h"
#include "gfxfilter.h"
#include "uaeresource.h"
#include "dongle.h"
#include "sampler.h"
#include "consolehook.h"
#ifdef RETROPLATFORM
#include "rp.h"
#endif
#ifdef USE_SDL
#include "SDL.h"
#endif
long int version = 256 * 65536L * UAEMAJOR + 65536L * UAEMINOR + UAESUBREV;
struct uae_prefs currprefs, changed_prefs;
int config_changed;
bool no_gui = 0, quit_to_gui = 0;
bool cloanto_rom = 0;
bool kickstart_rom = 1;
bool console_emulation = 0;
struct gui_info gui_data;
TCHAR warning_buffer[256];
TCHAR optionsfile[256];
static uae_u32 randseed;
static int oldhcounter;
uae_u32 uaesrand (uae_u32 seed)
{
oldhcounter = -1;
randseed = seed;
//randseed = 0x12345678;
//write_log (_T("seed=%08x\n"), randseed);
return randseed;
}
uae_u32 uaerand (void)
{
if (oldhcounter != hsync_counter) {
srand (hsync_counter ^ randseed);
oldhcounter = hsync_counter;
}
uae_u32 r = rand ();
//write_log (_T("rand=%08x\n"), r);
return r;
}
uae_u32 uaerandgetseed (void)
{
return randseed;
}
void my_trim (TCHAR *s)
{
int len;
while (_tcscspn (s, _T("\t \r\n")) == 0)
memmove (s, s + 1, (_tcslen (s + 1) + 1) * sizeof (TCHAR));
len = _tcslen (s);
while (len > 0 && _tcscspn (s + len - 1, _T("\t \r\n")) == 0)
s[--len] = '\0';
}
TCHAR *my_strdup_trim (const TCHAR *s)
{
TCHAR *out;
int len;
while (_tcscspn (s, _T("\t \r\n")) == 0)
s++;
len = _tcslen (s);
while (len > 0 && _tcscspn (s + len - 1, _T("\t \r\n")) == 0)
len--;
out = xmalloc (TCHAR, len + 1);
memcpy (out, s, len * sizeof (TCHAR));
out[len] = 0;
return out;
}
void discard_prefs (struct uae_prefs *p, int type)
{
struct strlist **ps = &p->all_lines;
while (*ps) {
struct strlist *s = *ps;
*ps = s->next;
xfree (s->value);
xfree (s->option);
xfree (s);
}
#ifdef FILESYS
filesys_cleanup ();
#endif
}
static void fixup_prefs_dim2 (struct wh *wh)
{
if (wh->width < 160)
wh->width = 160;
if (wh->height < 128)
wh->height = 128;
if (wh->width > 3072)
wh->width = 3072;
if (wh->height > 2048)
wh->height = 2048;
}
void fixup_prefs_dimensions (struct uae_prefs *prefs)
{
fixup_prefs_dim2 (&prefs->gfx_size_fs);
fixup_prefs_dim2 (&prefs->gfx_size_win);
if (prefs->gfx_apmode[1].gfx_vsync)
prefs->gfx_apmode[1].gfx_vsyncmode = 1;
for (int i = 0; i < 2; i++) {
struct apmode *ap = &prefs->gfx_apmode[i];
ap->gfx_vflip = 0;
if (ap->gfx_vsync) {
if (ap->gfx_vsyncmode) {
// low latency vsync: no flip only if no-buffer
if (ap->gfx_backbuffers >= 1)
ap->gfx_vflip = 1;
if (!i && ap->gfx_backbuffers == 2)
ap->gfx_vflip = 1;
} else {
// legacy vsync: always wait for flip
ap->gfx_vflip = -1;
if (prefs->gfx_api && ap->gfx_backbuffers < 1)
ap->gfx_backbuffers = 1;
}
} else {
// no vsync: wait if triple bufferirng
if (ap->gfx_backbuffers >= 2)
ap->gfx_vflip = -1;
}
}
if (prefs->gfx_filter == 0 && ((prefs->gfx_filter_autoscale && !prefs->gfx_api) || (prefs->gfx_apmode[0].gfx_vsyncmode)))
prefs->gfx_filter = 1;
if (prefs->gfx_filter == 0 && prefs->monitoremu)
prefs->gfx_filter = 1;
}
void fixup_cpu (struct uae_prefs *p)
{
if (p->cpu_frequency == 1000000)
p->cpu_frequency = 0;
switch (p->cpu_model)
{
case 68000:
p->address_space_24 = 1;
if (p->cpu_compatible || p->cpu_cycle_exact)
p->fpu_model = 0;
break;
case 68010:
p->address_space_24 = 1;
if (p->cpu_compatible || p->cpu_cycle_exact)
p->fpu_model = 0;
break;
case 68020:
break;
case 68030:
p->address_space_24 = 0;
break;
case 68040:
p->address_space_24 = 0;
if (p->fpu_model)
p->fpu_model = 68040;
break;
case 68060:
p->address_space_24 = 0;
if (p->fpu_model)
p->fpu_model = 68060;
break;
}
if (p->cpu_model != 68040)
p->mmu_model = 0;
if (p->cachesize && p->cpu_cycle_exact)
p->cachesize = 0;
if (p->cpu_cycle_exact && p->m68k_speed < 0)
p->m68k_speed = 0;
if (p->immediate_blits && p->blitter_cycle_exact)
p->immediate_blits = false;
if (p->immediate_blits && p->waiting_blits)
p->waiting_blits = 0;
}
void fixup_prefs (struct uae_prefs *p)
{
int err = 0;
built_in_chipset_prefs (p);
fixup_cpu (p);
if (((p->chipmem_size & (p->chipmem_size - 1)) != 0 && p->chipmem_size != 0x180000)
|| p->chipmem_size < 0x20000
|| p->chipmem_size > 0x800000)
{
write_log (_T("Unsupported chipmem size %x!\n"), p->chipmem_size);
p->chipmem_size = 0x200000;
err = 1;
}
if ((p->fastmem_size & (p->fastmem_size - 1)) != 0
|| (p->fastmem_size != 0 && (p->fastmem_size < 0x100000 || p->fastmem_size > 0x800000)))
{
write_log (_T("Unsupported fastmem size %x!\n"), p->fastmem_size);
err = 1;
}
if ((p->rtgmem_size & (p->rtgmem_size - 1)) != 0
|| (p->rtgmem_size != 0 && (p->rtgmem_size < 0x100000 || p->rtgmem_size > max_z3fastmem / 2)))
{
write_log (_T("Unsupported graphics card memory size %x (%x)!\n"), p->rtgmem_size, max_z3fastmem / 2);
if (p->rtgmem_size > max_z3fastmem / 2)
p->rtgmem_size = max_z3fastmem / 2;
else
p->rtgmem_size = 0;
err = 1;
}
if ((p->z3fastmem_size & (p->z3fastmem_size - 1)) != 0
|| (p->z3fastmem_size != 0 && (p->z3fastmem_size < 0x100000 || p->z3fastmem_size > max_z3fastmem)))
{
write_log (_T("Unsupported Zorro III fastmem size %x (%x)!\n"), p->z3fastmem_size, max_z3fastmem);
if (p->z3fastmem_size > max_z3fastmem)
p->z3fastmem_size = max_z3fastmem;
else
p->z3fastmem_size = 0;
err = 1;
}
if ((p->z3fastmem2_size & (p->z3fastmem2_size - 1)) != 0
|| (p->z3fastmem2_size != 0 && (p->z3fastmem2_size < 0x100000 || p->z3fastmem2_size > max_z3fastmem)))
{
write_log (_T("Unsupported Zorro III fastmem size %x (%x)!\n"), p->z3fastmem2_size, max_z3fastmem);
if (p->z3fastmem2_size > max_z3fastmem)
p->z3fastmem2_size = max_z3fastmem;
else
p->z3fastmem2_size = 0;
err = 1;
}
p->z3fastmem_start &= ~0xffff;
if (p->z3fastmem_start < 0x1000000)
p->z3fastmem_start = 0x1000000;
if ((p->z3chipmem_size & (p->z3chipmem_size - 1)) != 0
|| (p->z3chipmem_size != 0 && (p->z3chipmem_size < 0x100000 || p->z3chipmem_size > max_z3fastmem)))
{
write_log (_T("Unsupported Zorro III fake chipmem size %x (%x)!\n"), p->z3chipmem_size, max_z3fastmem);
if (p->z3chipmem_size > max_z3fastmem)
p->z3chipmem_size = max_z3fastmem;
else
p->z3chipmem_size = 0;
err = 1;
}
if (p->address_space_24 && (p->z3fastmem_size != 0 || p->z3fastmem2_size != 0 || p->z3chipmem_size != 0)) {
p->z3fastmem_size = p->z3fastmem2_size = p->z3chipmem_size = 0;
write_log (_T("Can't use a graphics card or 32-bit memory when using a 24 bit\naddress space.\n"));
}
if (p->bogomem_size != 0 && p->bogomem_size != 0x80000 && p->bogomem_size != 0x100000 && p->bogomem_size != 0x180000 && p->bogomem_size != 0x1c0000) {
p->bogomem_size = 0;
write_log (_T("Unsupported bogomem size!\n"));
err = 1;
}
if (p->bogomem_size > 0x180000 && (p->cs_fatgaryrev >= 0 || p->cs_ide || p->cs_ramseyrev >= 0)) {
p->bogomem_size = 0x180000;
write_log (_T("Possible Gayle bogomem conflict fixed\n"));
}
if (p->chipmem_size > 0x200000 && p->fastmem_size != 0) {
write_log (_T("You can't use fastmem and more than 2MB chip at the same time!\n"));
p->fastmem_size = 0;
err = 1;
}
if (p->mbresmem_low_size > 0x04000000 || (p->mbresmem_low_size & 0xfffff)) {
p->mbresmem_low_size = 0;
write_log (_T("Unsupported A3000 MB RAM size\n"));
}
if (p->mbresmem_high_size > 0x04000000 || (p->mbresmem_high_size & 0xfffff)) {
p->mbresmem_high_size = 0;
write_log (_T("Unsupported Motherboard RAM size\n"));
}
if (p->address_space_24 && p->rtgmem_size)
p->rtgmem_type = 0;
if (!p->rtgmem_type && (p->chipmem_size > 2 * 1024 * 1024 || getz2size (p) > 8 * 1024 * 1024 || getz2size (p) < 0)) {
p->rtgmem_size = 0;
write_log (_T("Too large Z2 RTG memory size\n"));
}
#if 0
if (p->m68k_speed < -1 || p->m68k_speed > 20) {
write_log (_T("Bad value for -w parameter: must be -1, 0, or within 1..20.\n"));
p->m68k_speed = 4;
err = 1;
}
#endif
if (p->produce_sound < 0 || p->produce_sound > 3) {
write_log (_T("Bad value for -S parameter: enable value must be within 0..3\n"));
p->produce_sound = 0;
err = 1;
}
if (p->comptrustbyte < 0 || p->comptrustbyte > 3) {
write_log (_T("Bad value for comptrustbyte parameter: value must be within 0..2\n"));
p->comptrustbyte = 1;
err = 1;
}
if (p->comptrustword < 0 || p->comptrustword > 3) {
write_log (_T("Bad value for comptrustword parameter: value must be within 0..2\n"));
p->comptrustword = 1;
err = 1;
}
if (p->comptrustlong < 0 || p->comptrustlong > 3) {
write_log (_T("Bad value for comptrustlong parameter: value must be within 0..2\n"));
p->comptrustlong = 1;
err = 1;
}
if (p->comptrustnaddr < 0 || p->comptrustnaddr > 3) {
write_log (_T("Bad value for comptrustnaddr parameter: value must be within 0..2\n"));
p->comptrustnaddr = 1;
err = 1;
}
if (p->cachesize < 0 || p->cachesize > 16384) {
write_log (_T("Bad value for cachesize parameter: value must be within 0..16384\n"));
p->cachesize = 0;
err = 1;
}
if (p->z3fastmem_size > 0 && (p->address_space_24 || p->cpu_model < 68020)) {
write_log (_T("Z3 fast memory can't be used with a 68000/68010 emulation. It\n")
_T("requires a 68020 emulation. Turning off Z3 fast memory.\n"));
p->z3fastmem_size = 0;
err = 1;
}
if (p->rtgmem_size > 0 && p->rtgmem_type && (p->cpu_model < 68020 || p->address_space_24)) {
write_log (_T("RTG can't be used with a 68000/68010 or 68EC020 emulation. It\n")
_T("requires a 68020 emulation. Turning off RTG.\n"));
p->rtgmem_size = 0;
err = 1;
}
#if !defined (BSDSOCKET)
if (p->socket_emu) {
write_log (_T("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 < 0 || p->nr_floppies > 4) {
write_log (_T("Invalid number of floppies. Using 4.\n"));
p->nr_floppies = 4;
p->floppyslots[0].dfxtype = 0;
p->floppyslots[1].dfxtype = 0;
p->floppyslots[2].dfxtype = 0;
p->floppyslots[3].dfxtype = 0;
err = 1;
}
if (p->floppy_speed > 0 && p->floppy_speed < 10) {
p->floppy_speed = 100;
}
if (p->input_mouse_speed < 1 || p->input_mouse_speed > 1000) {
p->input_mouse_speed = 100;
}
if (p->collision_level < 0 || p->collision_level > 3) {
write_log (_T("Invalid collision support level. Using 1.\n"));
p->collision_level = 1;
err = 1;
}
if (p->parallel_postscript_emulation)
p->parallel_postscript_detection = 1;
if (p->cs_compatible == 1) {
p->cs_fatgaryrev = p->cs_ramseyrev = p->cs_mbdmac = -1;
p->cs_ide = 0;
if (p->cpu_model >= 68020) {
p->cs_fatgaryrev = 0;
p->cs_ide = -1;
p->cs_ramseyrev = 0x0f;
p->cs_mbdmac = 0;
}
} else if (p->cs_compatible == 0) {
if (p->cs_ide == IDE_A4000) {
if (p->cs_fatgaryrev < 0)
p->cs_fatgaryrev = 0;
if (p->cs_ramseyrev < 0)
p->cs_ramseyrev = 0x0f;
}
}
/* Can't fit genlock and A2024 or Graffiti at the same time,
* also Graffiti uses genlock audio bit as an enable signal
*/
if (p->genlock && p->monitoremu)
p->genlock = false;
fixup_prefs_dimensions (p);
#if !defined (JIT)
p->cachesize = 0;
#endif
#ifdef CPU_68000_ONLY
p->cpu_model = 68000;
p->fpu_model = 0;
#endif
#ifndef CPUEMU_0
p->cpu_compatible = 1;
p->address_space_24 = 1;
#endif
#if !defined (CPUEMU_11) && !defined (CPUEMU_12)
p->cpu_compatible = 0;
p->address_space_24 = 0;
#endif
#if !defined (CPUEMU_12)
p->cpu_cycle_exact = p->blitter_cycle_exact = 0;
#endif
#ifndef AGA
p->chipset_mask &= ~CSMASK_AGA;
#endif
#ifndef AUTOCONFIG
p->z3fastmem_size = 0;
p->fastmem_size = 0;
p->rtgmem_size = 0;
#endif
#if !defined (BSDSOCKET)
p->socket_emu = 0;
#endif
#if !defined (SCSIEMU)
p->scsi = 0;
#ifdef _WIN32
p->win32_aspi = 0;
#endif
#endif
#if !defined (SANA2)
p->sana2 = 0;
#endif
#if !defined (UAESERIAL)
p->uaeserial = 0;
#endif
#if defined (CPUEMU_12)
if (p->cpu_cycle_exact) {
p->gfx_framerate = 1;
p->cachesize = 0;
p->m68k_speed = 0;
}
#endif
if (p->maprom && !p->address_space_24)
p->maprom = 0x0f000000;
if ((p->maprom & 0xff000000) && p->address_space_24)
p->maprom = 0x00e00000;
if (p->tod_hack && p->cs_ciaatod == 0)
p->cs_ciaatod = p->ntscmode ? 2 : 1;
blkdev_fix_prefs (p);
target_fixup_options (p);
}
int quit_program = 0;
static int restart_program;
static TCHAR restart_config[MAX_DPATH];
static int default_config;
void uae_reset (int hardreset)
{
if (debug_dma) {
record_dma_reset ();
record_dma_reset ();
}
currprefs.quitstatefile[0] = changed_prefs.quitstatefile[0] = 0;
if (quit_program == 0) {
quit_program = -2;
if (hardreset)
quit_program = -3;
}
}
void uae_quit (void)
{
deactivate_debugger ();
if (quit_program != -1)
quit_program = -1;
target_quit ();
}
/* 0 = normal, 1 = nogui, -1 = disable nogui */
void uae_restart (int opengui, TCHAR *cfgfile)
{
uae_quit ();
restart_program = opengui > 0 ? 1 : (opengui == 0 ? 2 : 3);
restart_config[0] = 0;
default_config = 0;
if (cfgfile)
_tcscpy (restart_config, cfgfile);
}
#ifndef DONT_PARSE_CMDLINE
void usage (void)
{
}
static void parse_cmdline_2 (int argc, TCHAR **argv)
{
int i;
cfgfile_addcfgparam (0);
for (i = 1; i < argc; i++) {
if (_tcsncmp (argv[i], _T("-cfgparam="), 10) == 0) {
cfgfile_addcfgparam (argv[i] + 10);
} else if (_tcscmp (argv[i], _T("-cfgparam")) == 0) {
if (i + 1 == argc)
write_log (_T("Missing argument for '-cfgparam' option.\n"));
else
cfgfile_addcfgparam (argv[++i]);
}
}
}
static void parse_diskswapper (TCHAR *s)
{
TCHAR *tmp = my_strdup (s);
TCHAR *delim = _T(",");
TCHAR *p1, *p2;
int num = 0;
p1 = tmp;
for (;;) {
p2 = _tcstok (p1, delim);
if (!p2)
break;
p1 = NULL;
if (num >= MAX_SPARE_DRIVES)
break;
_tcsncpy (currprefs.dfxlist[num], p2, 255);
num++;
}
free (tmp);
}
static TCHAR *parsetext (const TCHAR *s)
{
if (*s == '"' || *s == '\'') {
TCHAR *d;
TCHAR c = *s++;
int i;
d = my_strdup (s);
for (i = 0; i < _tcslen (d); i++) {
if (d[i] == c) {
d[i] = 0;
break;
}
}
return d;
} else {
return my_strdup (s);
}
}
static TCHAR *parsetextpath (const TCHAR *s)
{
TCHAR *s2 = parsetext (s);
TCHAR *s3 = target_expand_environment (s2);
xfree (s2);
return s3;
}
static void parse_cmdline (int argc, TCHAR **argv)
{
int i;
for (i = 1; i < argc; i++) {
if (!_tcsncmp (argv[i], _T("-diskswapper="), 13)) {
TCHAR *txt = parsetextpath (argv[i] + 13);
parse_diskswapper (txt);
xfree (txt);
} else if (_tcsncmp (argv[i], _T("-cfgparam="), 10) == 0) {
;
} else if (_tcscmp (argv[i], _T("-cfgparam")) == 0) {
if (i + 1 < argc)
i++;
} else if (_tcsncmp (argv[i], _T("-config="), 8) == 0) {
TCHAR *txt = parsetextpath (argv[i] + 8);
currprefs.mountitems = 0;
target_cfgfile_load (&currprefs, txt, -1, 0);
xfree (txt);
} else if (_tcsncmp (argv[i], _T("-statefile="), 11) == 0) {
TCHAR *txt = parsetextpath (argv[i] + 11);
savestate_state = STATE_DORESTORE;
_tcscpy (savestate_fname, txt);
xfree (txt);
} else if (_tcscmp (argv[i], _T("-f")) == 0) {
/* Check for new-style "-f xxx" argument, where xxx is config-file */
if (i + 1 == argc) {
write_log (_T("Missing argument for '-f' option.\n"));
} else {
TCHAR *txt = parsetextpath (argv[++i]);
currprefs.mountitems = 0;
target_cfgfile_load (&currprefs, txt, -1, 0);
xfree (txt);
}
} else if (_tcscmp (argv[i], _T("-s")) == 0) {
if (i + 1 == argc)
write_log (_T("Missing argument for '-s' option.\n"));
else
cfgfile_parse_line (&currprefs, argv[++i], 0);
} else if (_tcscmp (argv[i], _T("-h")) == 0 || _tcscmp (argv[i], _T("-help")) == 0) {
usage ();
exit (0);
} else if (_tcsncmp (argv[i], _T("-cdimage="), 9) == 0) {
TCHAR *txt = parsetextpath (argv[i] + 9);
TCHAR *txt2 = xmalloc(TCHAR, _tcslen(txt) + 2);
_tcscpy(txt2, txt);
if (_tcsrchr(txt2, ',') != NULL)
_tcscat(txt2, _T(","));
cfgfile_parse_option (&currprefs, _T("cdimage0"), txt2, 0);
xfree(txt2);
xfree (txt);
} else {
if (argv[i][0] == '-' && argv[i][1] != '\0') {
const TCHAR *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], arg) && extra_arg)
i++;
}
}
}
}
#endif
static void parse_cmdline_and_init_file (int argc, TCHAR **argv)
{
_tcscpy (optionsfile, _T(""));
#ifdef OPTIONS_IN_HOME
{
TCHAR *home = getenv ("HOME");
if (home != NULL && strlen (home) < 240)
{
_tcscpy (optionsfile, home);
_tcscat (optionsfile, _T("/"));
}
}
#endif
parse_cmdline_2 (argc, argv);
_tcscat (optionsfile, restart_config);
if (! target_cfgfile_load (&currprefs, optionsfile, 0, default_config)) {
write_log (_T("failed to load config '%s'\n"), optionsfile);
#ifdef OPTIONS_IN_HOME
/* sam: if not found in $HOME then look in current directory */
_tcscpy (optionsfile, restart_config);
target_cfgfile_load (&currprefs, optionsfile, 0, default_config);
#endif
}
fixup_prefs (&currprefs);
parse_cmdline (argc, argv);
}
void reset_all_systems (void)
{
init_eventtab ();
#ifdef PICASSO96
picasso_reset ();
#endif
#ifdef SCSIEMU
scsi_reset ();
scsidev_reset ();
scsidev_start_threads ();
#endif
#ifdef A2065
a2065_reset ();
#endif
#ifdef SANA2
netdev_reset ();
netdev_start_threads ();
#endif
#ifdef FILESYS
filesys_prepare_reset ();
filesys_reset ();
#endif
init_shm ();
memory_reset ();
#if defined (BSDSOCKET)
bsdlib_reset ();
#endif
#ifdef FILESYS
filesys_start_threads ();
hardfile_reset ();
#endif
#ifdef UAESERIAL
uaeserialdev_reset ();
uaeserialdev_start_threads ();
#endif
#if defined (PARALLEL_PORT)
initparallel ();
#endif
native2amiga_reset ();
dongle_reset ();
sampler_init ();
}
/* Okay, this stuff looks strange, but it is here to encourage people who
* port UAE to re-use as much of this code as possible. Functions that you
* should be using are do_start_program () and do_leave_program (), as well
* as real_main (). Some OSes don't call main () (which is braindamaged IMHO,
* but unfortunately very common), so you need to call real_main () from
* whatever entry point you have. You may want to write your own versions
* of start_program () and leave_program () if you need to do anything special.
* Add #ifdefs around these as appropriate.
*/
#ifdef _WIN32
#ifndef JIT
extern int DummyException (LPEXCEPTION_POINTERS blah, int n_except)
{
return EXCEPTION_CONTINUE_SEARCH;
}
#endif
#endif
void do_start_program (void)
{
if (quit_program == -1)
return;
if (!canbang && candirect < 0)
candirect = 0;
if (canbang && candirect < 0)
candirect = 1;
/* Do a reset on startup. Whether this is elegant is debatable. */
inputdevice_updateconfig (&currprefs);
if (quit_program >= 0)
quit_program = 2;
#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER)
extern int EvalException (LPEXCEPTION_POINTERS blah, int n_except);
__try
#endif
{
m68k_go (1);
}
#if (defined (_WIN32) || defined (_WIN64)) && !defined (NO_WIN32_EXCEPTION_HANDLER)
#ifdef JIT
__except (EvalException (GetExceptionInformation (), GetExceptionCode ()))
#else
__except (DummyException (GetExceptionInformation (), GetExceptionCode ()))
#endif
{
// EvalException does the good stuff...
}
#endif
}
void do_leave_program (void)
{
sampler_free ();
graphics_leave ();
inputdevice_close ();
DISK_free ();
close_sound ();
dump_counts ();
#ifdef SERIAL_PORT
serial_exit ();
#endif
#ifdef CDTV
cdtv_free ();
#endif
#ifdef A2091
a2091_free ();
#endif
#ifdef NCR
ncr_free ();
#endif
#ifdef CD32
akiko_free ();
#endif
if (! no_gui)
gui_exit ();
#ifdef USE_SDL
SDL_Quit ();
#endif
#ifdef AUTOCONFIG
expansion_cleanup ();
#endif
#ifdef FILESYS
filesys_cleanup ();
#endif
#ifdef BSDSOCKET
bsdlib_reset ();
#endif
device_func_reset ();
savestate_free ();
memory_cleanup ();
free_shm ();
cfgfile_addcfgparam (0);
machdep_free ();
}
void start_program (void)
{
do_start_program ();
}
void leave_program (void)
{
do_leave_program ();
}
void virtualdevice_init (void)
{
#ifdef AUTOCONFIG
rtarea_setup ();
#endif
#ifdef FILESYS
rtarea_init ();
uaeres_install ();
hardfile_install ();
#endif
#ifdef SCSIEMU
scsi_reset ();
scsidev_install ();
#endif
#ifdef SANA2
netdev_install ();
#endif
#ifdef UAESERIAL
uaeserialdev_install ();
#endif
#ifdef AUTOCONFIG
expansion_init ();
#endif
#ifdef FILESYS
filesys_install ();
#endif
}
static int real_main2 (int argc, TCHAR **argv)
{
#ifdef USE_SDL
SDL_Init (SDL_INIT_TIMER | SDL_INIT_AUDIO | SDL_INIT_JOYSTICK | SDL_INIT_NOPARACHUTE);
#endif
config_changed = 1;
if (restart_config[0]) {
default_prefs (&currprefs, 0);
fixup_prefs (&currprefs);
}
if (! graphics_setup ()) {
exit (1);
}
#ifdef NATMEM_OFFSET
//preinit_shm ();
#endif
if (restart_config[0])
parse_cmdline_and_init_file (argc, argv);
else
currprefs = changed_prefs;
if (!machdep_init ()) {
restart_program = 0;
return -1;
}
if (console_emulation) {
consolehook_config (&currprefs);
fixup_prefs (&currprefs);
}
if (! setup_sound ()) {
write_log (_T("Sound driver unavailable: Sound output disabled\n"));
currprefs.produce_sound = 0;
}
inputdevice_init ();
changed_prefs = currprefs;
no_gui = ! currprefs.start_gui;
if (restart_program == 2)
no_gui = 1;
else if (restart_program == 3)
no_gui = 0;
restart_program = 0;
if (! no_gui) {
int err = gui_init ();
currprefs = changed_prefs;
config_changed = 1;
if (err == -1) {
write_log (_T("Failed to initialize the GUI\n"));
return -1;
} else if (err == -2) {
return 1;
}
}
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. */
#ifdef NATMEM_OFFSET
init_shm ();
#endif
#ifdef PICASSO96
picasso_reset ();
#endif
#if 0
#ifdef JIT
if (!(currprefs.cpu_model >= 68020 && currprefs.address_space_24 == 0 && currprefs.cachesize))
canbang = 0;
#endif
#endif
fixup_prefs (&currprefs);
#ifdef RETROPLATFORM
rp_fixup_options (&currprefs);
#endif
changed_prefs = currprefs;
target_run ();
/* force sound settings change */
currprefs.produce_sound = 0;
savestate_init ();
keybuf_init (); /* Must come after init_joystick */
memory_hardreset (2);
memory_reset ();
#ifdef AUTOCONFIG
#if defined (BSDSOCKET)
bsdlib_install ();
#endif
emulib_install ();
uaeexe_install ();
native2amiga_install ();
#endif
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 ()) {
setup_brkhandler ();
if (currprefs.start_debugger && debuggable ())
activate_debugger ();
if (!init_audio ()) {
if (sound_available && currprefs.produce_sound > 1) {
write_log (_T("Sound driver unavailable: Sound output disabled\n"));
}
currprefs.produce_sound = 0;
}
start_program ();
}
return 0;
}
void real_main (int argc, TCHAR **argv)
{
restart_program = 1;
fetch_configurationpath (restart_config, sizeof (restart_config) / sizeof (TCHAR));
_tcscat (restart_config, OPTIONSFILENAME);
default_config = 1;
while (restart_program) {
int ret;
changed_prefs = currprefs;
ret = real_main2 (argc, argv);
if (ret == 0 && quit_to_gui)
restart_program = 1;
leave_program ();
quit_program = 0;
}
zfile_exit ();
}
#ifndef NO_MAIN_IN_MAIN_C
int main (int argc, TCHAR **argv)
{
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