Beispiel #1
0
static void reset_tempos(const char* sDefaultOS)
{
	framebuffer_setdisplaytext(FALSE);
	nvram_setvar("opib-temp-os",sDefaultOS);
	nvram_save();
	framebuffer_setdisplaytext(TRUE);
}
Beispiel #2
0
void cmd_install(int argc, char** argv) {
	bufferPrintf("Installing Images...\r\n");
	images_install(&_start, (uint32_t)&OpenIBootEnd - (uint32_t)&_start);
	bufferPrintf("Setting NVRAM version...\r\n");
	nvram_setvar("opib-version", "0.1.1");
	nvram_save(1);
	bufferPrintf("Images installed\r\n");
}
Beispiel #3
0
void cmd_install(int argc, char** argv) {
	bufferPrintf("Installing Images...\r\n");
	images_install(&_start, (uint32_t)&OpenIBootEnd - (uint32_t)&_start);
	bufferPrintf("Setting version and defaulting menu-timeout to 10s\r\n");
	nvram_setvar("opib-version", "0.1.1-zinnx");
	nvram_setvar("opib-menu-timeout", "10000");
	nvram_save();
	bufferPrintf("Images installed\r\n");
}
Beispiel #4
0
void running_machine::retro_machineexit(){

	// and out via the exit phase
	m_current_phase = MACHINE_PHASE_EXIT;

	// save the NVRAM and configuration
	sound().ui_mute(true);
	nvram_save();
	config_save_settings(*this);
	call_notifiers(MACHINE_NOTIFY_EXIT);
	printf("retro exit machine\n");
	zip_file_cache_clear();

	m_logfile.reset();
}
Beispiel #5
0
void running_machine::retro_machineexit()
{   
    retro_log(RETRO_LOG_INFO, "beginning retro_machineexit()\n");

   /* and out via the exit phase */
   m_current_phase = MACHINE_PHASE_EXIT;

   /* save the NVRAM and configuration */
   sound_mute(this, true);
   nvram_save(this);
   config_save_settings(this);
   
   /* call all exit callbacks registered */
   call_notifiers(MACHINE_NOTIFY_EXIT);

}
Beispiel #6
0
void running_machine::schedule_hard_reset()
{
    retro_log(RETRO_LOG_INFO, "[MAME 2010] schedule_hard_reset for current MAME machine.\n");
    
	m_hard_reset_pending = true;

	/* if we're executing, abort out immediately */
	m_scheduler.eat_all_cycles();

    /* and out via the exit phase */
    m_current_phase = MACHINE_PHASE_EXIT;

    /* save the NVRAM and configuration */
    sound_mute(this, true);
    nvram_save(this);
    config_save_settings(this);

    /* call all exit callbacks registered */
    call_notifiers(MACHINE_NOTIFY_EXIT);

    ENDEXEC=1;
}
Beispiel #7
0
void running_machine::retro_loop(){

	while (RLOOP==1)
   {
		// execute CPUs if not paused
		if (!m_paused)
			m_scheduler.timeslice();

		// otherwise, just pump video updates through
		else
			m_video->frame_update();

		// handle save/load
		if (m_saveload_schedule != SLS_NONE)
			handle_saveload();

	}

	if( (m_hard_reset_pending || m_exit_pending) && m_saveload_schedule == SLS_NONE){

	 	// and out via the exit phase
		m_current_phase = MACHINE_PHASE_EXIT;

		// save the NVRAM and configuration
		sound().ui_mute(true);
		nvram_save();
		config_save_settings(*this);

		// call all exit callbacks registered
		call_notifiers(MACHINE_NOTIFY_EXIT);
	
		zip_file_cache_clear();

		m_logfile.reset();		

		ENDEXEC=1;
	}

}
Beispiel #8
0
void cmd_saveenv(int argc, char** argv) {
	bufferPrintf("Saving environment, this may take awhile...\r\n");
	nvram_save();
	bufferPrintf("Environment saved\r\n");
}
Beispiel #9
0
int running_machine::run(bool firstrun)
{
	int error = MAMERR_NONE;

	// use try/catch for deep error recovery
	try
	{
		// move to the init phase
		m_current_phase = MACHINE_PHASE_INIT;

		// if we have a logfile, set up the callback
		if (options().log())
		{
			m_logfile = auto_alloc(*this, emu_file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
			file_error filerr = m_logfile->open("error.log");
			assert_always(filerr == FILERR_NONE, "unable to open log file");
			add_logerror_callback(logfile_callback);
		}

		// then finish setting up our local machine
		start();

		// load the configuration settings and NVRAM
		bool settingsloaded = config_load_settings(*this);
		nvram_load(*this);
		sound().ui_mute(false);

		// display the startup screens
		ui_display_startup_screens(*this, firstrun, !settingsloaded);

		// perform a soft reset -- this takes us to the running phase
		soft_reset();

		// run the CPUs until a reset or exit
		m_hard_reset_pending = false;
		while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
		{
			g_profiler.start(PROFILER_EXTRA);

			// execute CPUs if not paused
			if (!m_paused)
				m_scheduler.timeslice();

			// otherwise, just pump video updates through
			else
				m_video->frame_update();

			// handle save/load
			if (m_saveload_schedule != SLS_NONE)
				handle_saveload();

			g_profiler.stop();
		}

		// and out via the exit phase
		m_current_phase = MACHINE_PHASE_EXIT;

		// save the NVRAM and configuration
		sound().ui_mute(true);
		nvram_save(*this);
		config_save_settings(*this);
	}
	catch (emu_fatalerror &fatal)
	{
		mame_printf_error("%s\n", fatal.string());
		error = MAMERR_FATALERROR;
		if (fatal.exitcode() != 0)
			error = fatal.exitcode();
	}
	catch (emu_exception &)
	{
		mame_printf_error("Caught unhandled emulator exception\n");
		error = MAMERR_FATALERROR;
	}
	catch (std::bad_alloc &)
	{
		mame_printf_error("Out of memory!\n");
		error = MAMERR_FATALERROR;
	}

	// call all exit callbacks registered
	call_notifiers(MACHINE_NOTIFY_EXIT);
	zip_file_cache_clear();

	// close the logfile
	auto_free(*this, m_logfile);
	return error;
}
Beispiel #10
0
/* NVRAM utility */
int
main(int argc, char **argv)
{
	char *name, *value;
	int ret = 0;

	/* Skip program name */
	--argc;
	++argv;

	if (!*argv)
		usage();

	/* Process the remaining arguments. */
	for (; *argv; argv++) {
		if (!strcmp(*argv, "get")) {
			if (*++argv) {
				if ((value = nvram_get(*argv)))
					puts(value);
			}
		}
		else if (!strcmp(*argv, "settmp")) {
			if (*++argv) {
				char buf[1024];
				strncpy(value = buf, *argv, sizeof(buf)-1);
				name = strsep(&value, "=");
				nvram_set_temp(name, value);
			}
		}
		else if (!strcmp(*argv, "set")) {
			if (*++argv) {
				char buf[1024];
				strncpy(value = buf, *argv, sizeof(buf)-1);
				name = strsep(&value, "=");
				nvram_set(name, value);
			}
		}
		else if (!strcmp(*argv, "unset")) {
			if (*++argv)
				nvram_unset(*argv);
		}
		else if (!strcmp(*argv, "clear")) {
			nvram_clear();
		}
		else if (!strcmp(*argv, "commit")) {
			nvram_commit();
			break;
		}
		else if (!strcmp(*argv, "save")) {
			if (*++argv)
				ret |= nvram_save(*argv);
			break;
		}
		else if (!strcmp(*argv, "restore")) {
			if (*++argv)
				ret |= nvram_restore(*argv);
			break;
		}
		else if (!strcmp(*argv, "show")) {
			ret |= nvram_show(0);
			break;
		}
		else if (!strcmp(*argv, "showall")) {
			ret |= nvram_show(1);
			break;
		}
		if (!*argv)
			break;
	}

	return ret;
}
Beispiel #11
0
int run_game(int game)
{
	running_machine *machine;
	int error = MAMERR_NONE;
	mame_private *mame;
	callback_item *cb;

	/* create the machine structure and driver */
	machine = create_machine(game);
	mame = machine->mame_data;

	/* looooong term: remove this */
	Machine = machine;

	/* start in the "pre-init phase" */
	mame->current_phase = MAME_PHASE_PREINIT;

	/* perform validity checks before anything else */
	if (mame_validitychecks(game) != 0)
		return MAMERR_FAILED_VALIDITY;

	/* loop across multiple hard resets */
	mame->exit_pending = FALSE;
	while (error == 0 && !mame->exit_pending)
	{
		init_resource_tracking();
		add_free_resources_callback(timer_free);
		add_free_resources_callback(state_save_free);

		/* use setjmp/longjmp for deep error recovery */
		mame->fatal_error_jmpbuf_valid = TRUE;
		error = setjmp(mame->fatal_error_jmpbuf);
		if (error == 0)
		{
			int settingsloaded;

			/* move to the init phase */
			mame->current_phase = MAME_PHASE_INIT;

			/* start tracking resources for real */
			begin_resource_tracking();

			/* if we have a logfile, set up the callback */
			mame->logerror_callback_list = NULL;
			if (options.logfile)
				add_logerror_callback(machine, logfile_callback);

			/* then finish setting up our local machine */
			init_machine(machine);

			/* load the configuration settings and NVRAM */
			settingsloaded = config_load_settings();
			nvram_load();

			/* display the startup screens */
			ui_display_startup_screens(!settingsloaded && !options.skip_disclaimer, !options.skip_warnings, !options.skip_gameinfo);

			/* ensure we don't show the opening screens on a reset */
			options.skip_disclaimer = options.skip_warnings = options.skip_gameinfo = TRUE;

			/* start resource tracking; note that soft_reset assumes it can */
			/* call end_resource_tracking followed by begin_resource_tracking */
			/* to clear out resources allocated between resets */
			begin_resource_tracking();

			/* perform a soft reset -- this takes us to the running phase */
			soft_reset(0);

			/* run the CPUs until a reset or exit */
			mame->hard_reset_pending = FALSE;
			while ((!mame->hard_reset_pending && !mame->exit_pending) || mame->saveload_pending_file != NULL)
			{
				profiler_mark(PROFILER_EXTRA);

				/* execute CPUs if not paused */
				if (!mame->paused)
					cpuexec_timeslice();

				/* otherwise, just pump video updates through */
				else
					video_frame_update();

				/* handle save/load */
				if (mame->saveload_schedule_callback)
					(*mame->saveload_schedule_callback)(machine);

				profiler_mark(PROFILER_END);
			}

			/* and out via the exit phase */
			mame->current_phase = MAME_PHASE_EXIT;

			/* stop tracking resources at this level */
			end_resource_tracking();

			/* save the NVRAM and configuration */
			nvram_save();
			config_save_settings();
		}
		mame->fatal_error_jmpbuf_valid = FALSE;

		/* call all exit callbacks registered */
		for (cb = mame->exit_callback_list; cb; cb = cb->next)
			(*cb->func.exit)(machine);

		/* close all inner resource tracking */
		exit_resource_tracking();

		/* free our callback lists */
		free_callback_list(&mame->exit_callback_list);
		free_callback_list(&mame->reset_callback_list);
		free_callback_list(&mame->pause_callback_list);
	}

	/* destroy the machine */
	destroy_machine(machine);

	/* return an error */
	return error;
}
Beispiel #12
0
void images_install(void* newData, size_t newDataLen, uint32_t newFourcc, uint32_t replaceFourcc) {
	ImageDataList* list = NULL;
	ImageDataList* cur = NULL;
	ImageDataList* toReplace = NULL;
    ImageDataList* verify = NULL;
    
	int isReplace = (replaceFourcc != newFourcc) ? TRUE : FALSE;
	int isUpgrade = FALSE;

	Image* curImage = imageList;
    
	while(curImage != NULL) {
		if(cur == NULL) {
			list = cur = verify = malloc(sizeof(ImageDataList));
		} else {
			cur->next = malloc(sizeof(ImageDataList));
			cur = cur->next;
		}

		bufferPrintf("Reading: ");
		print_fourcc(curImage->type);
		bufferPrintf(" (%d bytes)\r\n", curImage->padded);

		cur->type = curImage->type;
		cur->next = NULL;
		cur->data = malloc(curImage->padded);
		nor_read(cur->data, curImage->offset, curImage->padded);

		if(isReplace && cur->type == replaceFourcc) {
			isUpgrade = TRUE;
		} else if(cur->type == newFourcc) {
			toReplace = cur;
		}

		curImage = curImage->next;
	}

	if(!isUpgrade) {
		bufferPrintf("Performing installation... (%d bytes)\r\n", newDataLen);

		ImageDataList* ibox = malloc(sizeof(ImageDataList));
		ibox->type = replaceFourcc;
		ibox->data = toReplace->data;
		ibox->next = toReplace->next;

		toReplace->next = ibox;
		toReplace->data = images_inject_img3(toReplace->data, newData, newDataLen);
		images_change_type(ibox->data, ibox->type);
	} else {
		bufferPrintf("Performing upgrade... (%d bytes)\r\n", newDataLen);
		void* newIBoot = images_inject_img3(toReplace->data, newData, newDataLen);
		free(toReplace->data);
		toReplace->data = newIBoot;
	}

    //check for size and availability
    size_t newPaddedDataLen=0;
    size_t totalBytes=0;
    //if somebody can find how to get padded length for new ibot maybe this loop not needed
    while(verify != NULL) {
        cur = verify;
        verify = verify->next;
        AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;
        totalBytes += header->base.size;
        
        if(cur->type == newFourcc) {
            newPaddedDataLen = header->base.size;
        }
    }
    
    bufferPrintf("Total size to be written %d\r\n",totalBytes);
    if((ImagesStart + totalBytes) >= 0xfc000) {
        bufferPrintf("**ABORTED** Writing total image size: 0x%x, new ibot size: 0x%x at 0x%x would overflow NOR!\r\n", totalBytes, newPaddedDataLen,ImagesStart);
        images_rewind();
        images_release();
        images_setup();
        return;
    }
    
	bufferPrintf("Flashing...\r\n");

	images_rewind();
	while(list != NULL) {
		cur = list;
		list = list->next;
		AppleImg3RootHeader* header = (AppleImg3RootHeader*) cur->data;

		bufferPrintf("Flashing: ");
		print_fourcc(cur->type);
		bufferPrintf(" (%x, %d bytes)\r\n", cur->data, header->base.size);

		images_append(cur->data, header->base.size);

		free(cur->data);
		free(cur);
	}
	bufferPrintf("Flashing Complete, Free space after flashing %d\r\n",0xfc000-MaxOffset);

	images_release();
	images_setup();

    bufferPrintf("Configuring openiBoot settings...\r\n");
    
    Volume* volume;
    io_func* io;

    io = bdev_open(0);
    volume = openVolume(io);

    char buffer [sizeof(XSTRINGIFY(OPENIBOOT_VERSION))];
    strcpy(buffer, XSTRINGIFY(OPENIBOOT_VERSION));
    add_hfs(volume, (uint8_t*)buffer, sizeof(buffer), "/openiboot");

    closeVolume(volume);
    CLOSE(io);

    ftl_sync();
    
    if(!nvram_getvar("opib-temp-os")) {
    	nvram_setvar("opib-temp-os", "0");
    }
    
    if(!nvram_getvar("opib-default-os")) {
		nvram_setvar("opib-default-os", "1");
    }

    if(!nvram_getvar("opib-menu-timeout")) {
		nvram_setvar("opib-menu-timeout", "10000");
    }

    nvram_save();
    bufferPrintf("openiBoot installation complete.\r\n");
}
Beispiel #13
0
int running_machine::run(bool firstrun)
{
	int error = MAMERR_NONE;

	// use try/catch for deep error recovery
	try
	{
		// move to the init phase
		m_current_phase = MACHINE_PHASE_INIT;

		// if we have a logfile, set up the callback
		if (options().log())
		{
			m_logfile = auto_alloc(*this, emu_file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
			file_error filerr = m_logfile->open("error.log");
			assert_always(filerr == FILERR_NONE, "unable to open log file");
			add_logerror_callback(logfile_callback);
		}

		// then finish setting up our local machine
		start();

		// load the configuration settings and NVRAM
		bool settingsloaded = config_load_settings(*this);
		nvram_load(*this);
		sound().ui_mute(false);

		// initialize ui lists
		ui_initialize(*this);

		// display the startup screens
		ui_display_startup_screens(*this, firstrun, !settingsloaded);

		// perform a soft reset -- this takes us to the running phase
		soft_reset();

		// run the CPUs until a reset or exit
		m_hard_reset_pending = false;
		while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
		{
			g_profiler.start(PROFILER_EXTRA);

			#ifdef SDLMAME_EMSCRIPTEN
			//break out to our async javascript loop and halt
			js_set_main_loop(m_scheduler);
			#endif

			// execute CPUs if not paused
			if (!m_paused)
				m_scheduler.timeslice();

			// otherwise, just pump video updates through
			else
				m_video->frame_update();

			// handle save/load
			if (m_saveload_schedule != SLS_NONE)
				handle_saveload();

			g_profiler.stop();
		}

		// and out via the exit phase
		m_current_phase = MACHINE_PHASE_EXIT;

		// save the NVRAM and configuration
		sound().ui_mute(true);
		nvram_save(*this);
		config_save_settings(*this);
	}
	catch (emu_fatalerror &fatal)
	{
		mame_printf_error("%s\n", fatal.string());
		error = MAMERR_FATALERROR;
		if (fatal.exitcode() != 0)
			error = fatal.exitcode();
	}
	catch (emu_exception &)
	{
		mame_printf_error("Caught unhandled emulator exception\n");
		error = MAMERR_FATALERROR;
	}
	catch (binding_type_exception &btex)
	{
		mame_printf_error("Error performing a late bind of type %s to %s\n", btex.m_actual_type.name(), btex.m_target_type.name());
		error = MAMERR_FATALERROR;
	}
	catch (std::exception &ex)
	{
		mame_printf_error("Caught unhandled %s exception: %s\n", typeid(ex).name(), ex.what());
		error = MAMERR_FATALERROR;
	}
	catch (...)
	{
		mame_printf_error("Caught unhandled exception\n");
		error = MAMERR_FATALERROR;
	}

	// make sure our phase is set properly before cleaning up,
	// in case we got here via exception
	m_current_phase = MACHINE_PHASE_EXIT;

	// call all exit callbacks registered
	call_notifiers(MACHINE_NOTIFY_EXIT);
	zip_file_cache_clear();

	// close the logfile
	auto_free(*this, m_logfile);
	return error;
}
Beispiel #14
0
int running_machine::run(bool firstrun, bool benchmarking)
{
	int error = MAMERR_NONE;

	// use try/catch for deep error recovery
	try
	{
		// move to the init phase
		m_current_phase = MACHINE_PHASE_INIT;

		// if we have a logfile, set up the callback
		if (options().log())
		{
			m_logfile = auto_alloc(*this, emu_file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS));
			file_error filerr = m_logfile->open("error.log");
			assert_always(filerr == FILERR_NONE, "unable to open log file");
			add_logerror_callback(logfile_callback);
		}

		// then finish setting up our local machine
		start();

		// load the configuration settings and NVRAM
		bool settingsloaded = config_load_settings(*this);
		nvram_load(*this);
		sound().ui_mute(false);

        // this point is chosen arbitrarily to be represented as 50% complete
        // with the "initializing state" init phase
        announce_init_phase(STARTUP_PHASE_INITIALIZING_STATE, 50);

		// display the startup screens, unless benchmarking, in which case
        // there is no user interaction expected and no need to show the
        // startup screens
        if (!benchmarking) {
            ui_display_startup_screens(*this, firstrun, !settingsloaded);
        }

		// perform a soft reset -- this takes us to the running phase
		soft_reset();

        // now initialization is 100% complete and the next thing that will
        // happen is the game will start running
        announce_init_phase(STARTUP_PHASE_INITIALIZING_STATE, 100);

		// run the CPUs until a reset or exit
		m_hard_reset_pending = false;
		while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
		{
			g_profiler.start(PROFILER_EXTRA);

			// execute CPUs if not paused
			if (!m_paused)
				m_scheduler.timeslice();

			// otherwise, just pump video updates through
			else
				m_video->frame_update();

			// handle save/load
			if (m_saveload_schedule != SLS_NONE)
				handle_saveload();

			g_profiler.stop();
		}

		// and out via the exit phase
		m_current_phase = MACHINE_PHASE_EXIT;

		// save the NVRAM and configuration
		sound().ui_mute(true);
		nvram_save(*this);
		config_save_settings(*this);
	}
	catch (emu_fatalerror &fatal)
	{
		mame_printf_error("%s\n", fatal.string());
		error = MAMERR_FATALERROR;
		if (fatal.exitcode() != 0)
			error = fatal.exitcode();
	}
	catch (emu_exception &)
	{
		mame_printf_error("Caught unhandled emulator exception\n");
		error = MAMERR_FATALERROR;
	}
	catch (std::bad_alloc &)
	{
		mame_printf_error("Out of memory!\n");
		error = MAMERR_FATALERROR;
	}

	// make sure our phase is set properly before cleaning up,
	// in case we got here via exception
	m_current_phase = MACHINE_PHASE_EXIT;

	// call all exit callbacks registered
	call_notifiers(MACHINE_NOTIFY_EXIT);
	zip_file_cache_clear();

	// close the logfile
	auto_free(*this, m_logfile);
	return error;
}
Beispiel #15
0
int running_machine::run(bool firstrun)
{
   int error = MAMERR_NONE;

   // move to the init phase
   m_current_phase = MACHINE_PHASE_INIT;

   // if we have a logfile, set up the callback
   if (options().log())
   {
      m_logfile.reset(global_alloc(emu_file(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS)));
      file_error filerr = m_logfile->open("error.log");
      assert_always(filerr == FILERR_NONE, "unable to open log file");
      add_logerror_callback(logfile_callback);
   }

   // then finish setting up our local machine
   start();

   // load the configuration settings and NVRAM
   bool settingsloaded = config_load_settings(*this);

   //MKCHAMP - INITIALIZING THE HISCORE ENGINE
   if (! options().disable_hiscore_patch())
      hiscore_init(*this);

   // disallow save state registrations starting here.
   // Don't do it earlier, config load can create network
   // devices with timers.
   m_save.allow_registration(false);

   nvram_load();
   sound().ui_mute(false);

   // initialize ui lists
   ui().initialize(*this);

   // display the startup screens
   ui().display_startup_screens(firstrun, !options().skip_nagscreen());

   // perform a soft reset -- this takes us to the running phase
   soft_reset();

   // handle initial load
   if (m_saveload_schedule != SLS_NONE)
      handle_saveload();

   // run the CPUs until a reset or exit
   m_hard_reset_pending = false;
   while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != SLS_NONE)
      return 0;

   // and out via the exit phase
   m_current_phase = MACHINE_PHASE_EXIT;

   // save the NVRAM and configuration
   sound().ui_mute(true);
   nvram_save();
   config_save_settings(*this);

   // make sure our phase is set properly before cleaning up,
   // in case we got here via exception
   m_current_phase = MACHINE_PHASE_EXIT;

   // call all exit callbacks registered
   call_notifiers(MACHINE_NOTIFY_EXIT);
   zip_file_cache_clear();

   // close the logfile
   m_logfile.reset();
   return error;
}
Beispiel #16
0
int run_game(int game)
{
	callback_item *cb;
	int error = 0;

	/* start in the "pre-init phase" */
	current_phase = MAME_PHASE_PREINIT;

/* AdvanceMAME: Disable validity checks */
#if 0
	/* perform validity checks before anything else */
	if (mame_validitychecks(game) != 0)
		return 1;
#endif

	/* loop across multiple hard resets */
	exit_pending = FALSE;
	while (error == 0 && !exit_pending)
	{
		/* use setjmp/longjmp for deep error recovery */
		fatal_error_jmpbuf_valid = TRUE;
		error = setjmp(fatal_error_jmpbuf);
		if (error == 0)
		{
			int settingsloaded;

			/* move to the init phase */
			current_phase = MAME_PHASE_INIT;

			/* start tracking resources for real */
			begin_resource_tracking();

			/* if we have a logfile, set up the callback */
			logerror_callback_list = NULL;
			if (options.logfile)
				add_logerror_callback(logfile_callback);

			/* create the Machine structure and driver */
			create_machine(game);

			/* then finish setting up our local machine */
			init_machine();

			/* load the configuration settings and NVRAM */
			settingsloaded = config_load_settings();
			nvram_load();

			/* initialize the UI and display the startup screens */
			if (ui_init(!settingsloaded && !options.skip_disclaimer, !options.skip_warnings, !options.skip_gameinfo) != 0)
				fatalerror("User cancelled");

			/* ensure we don't show the opening screens on a reset */
			options.skip_disclaimer = options.skip_warnings = options.skip_gameinfo = TRUE;

			/* start resource tracking; note that soft_reset assumes it can */
			/* call end_resource_tracking followed by begin_resource_tracking */
			/* to clear out resources allocated between resets */
			begin_resource_tracking();

			/* perform a soft reset -- this takes us to the running phase */
			soft_reset(0);

			/* run the CPUs until a reset or exit */
			hard_reset_pending = FALSE;
			while ((!hard_reset_pending && !exit_pending) || saveload_pending_file != NULL)
			{
				profiler_mark(PROFILER_EXTRA);

				/* execute CPUs if not paused */
				if (!mame_paused)
					cpuexec_timeslice();

				/* otherwise, just pump video updates through */
				else
				{
					updatescreen();
					reset_partial_updates();
				}

				/* handle save/load */
				if (saveload_schedule_callback)
					(*saveload_schedule_callback)();

				profiler_mark(PROFILER_END);
			}

			/* and out via the exit phase */
			current_phase = MAME_PHASE_EXIT;

			/* stop tracking resources at this level */
			end_resource_tracking();

			/* save the NVRAM and configuration */
			nvram_save();
			config_save_settings();
		}
		fatal_error_jmpbuf_valid = FALSE;

		/* call all exit callbacks registered */
		for (cb = exit_callback_list; cb; cb = cb->next)
			(*cb->func.exit)();

		/* close all inner resource tracking */
		while (resource_tracking_tag != 0)
			end_resource_tracking();

		/* free our callback lists */
		free_callback_list(&exit_callback_list);
		free_callback_list(&reset_callback_list);
		free_callback_list(&pause_callback_list);
	}

	/* return an error */
	return error;
}