summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/machine.cpp
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/machine.cpp')
-rw-r--r--src/emu/machine.cpp451
1 files changed, 203 insertions, 248 deletions
diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
index 68bf7dc74d9..a77140dba16 100644
--- a/src/emu/machine.cpp
+++ b/src/emu/machine.cpp
@@ -2,93 +2,44 @@
// copyright-holders:Aaron Giles
/***************************************************************************
- machine.c
+ machine.cpp
Controls execution of the core MAME system.
-****************************************************************************
-
- Since there has been confusion in the past over the order of
- initialization and other such things, here it is, all spelled out
- as of January, 2008:
-
- main()
- - does platform-specific init
- - calls mame_execute() [mame.c]
-
- mame_execute() [mame.c]
- - calls mame_validitychecks() [validity.c] to perform validity checks on all compiled drivers
- - begins resource tracking (level 1)
- - calls create_machine [mame.c] to initialize the running_machine structure
- - calls init_machine() [mame.c]
-
- init_machine() [mame.c]
- - calls fileio_init() [fileio.c] to initialize file I/O info
- - calls config_init() [config.c] to initialize configuration system
- - calls input_init() [input.c] to initialize the input system
- - calls output_init() [output.c] to initialize the output system
- - calls state_init() [state.c] to initialize save state system
- - calls state_save_allow_registration() [state.c] to allow registrations
- - calls palette_init() [palette.c] to initialize palette system
- - calls render_init() [render.c] to initialize the rendering system
- - calls ui_init() [ui.c] to initialize the user interface
- - calls generic_machine_init() [machine/generic.c] to initialize generic machine structures
- - calls timer_init() [timer.c] to reset the timer system
- - calls osd_init() [osdepend.h] to do platform-specific initialization
- - calls input_port_init() [inptport.c] to set up the input ports
- - calls rom_init() [romload.c] to load the game's ROMs
- - calls memory_init() [memory.c] to process the game's memory maps
- - calls the driver's DRIVER_INIT callback
- - calls device_list_start() [devintrf.c] to start any devices
- - calls video_init() [video.c] to start the video system
- - calls tilemap_init() [tilemap.c] to start the tilemap system
- - calls crosshair_init() [crsshair.c] to configure the crosshairs
- - calls sound_init() [sound.c] to start the audio system
- - calls debugger_init() [debugger.c] to set up the debugger
- - calls the driver's MACHINE_START, SOUND_START, and VIDEO_START callbacks
- - calls cheat_init() [cheat.c] to initialize the cheat system
- - calls image_init() [image.c] to initialize the image system
-
- - calls config_load_settings() [config.c] to load the configuration file
- - calls nvram_load [machine/generic.c] to load NVRAM
- - calls ui_display_startup_screens() [ui.c] to display the startup screens
- - begins resource tracking (level 2)
- - calls soft_reset() [mame.c] to reset all systems
-
- -------------------( at this point, we're up and running )----------------------
-
- - calls scheduler->timeslice() [schedule.c] over and over until we exit
- - ends resource tracking (level 2), freeing all auto_mallocs and timers
- - calls the nvram_save() [machine/generic.c] to save NVRAM
- - calls config_save_settings() [config.c] to save the game's configuration
- - calls all registered exit routines [mame.c]
- - ends resource tracking (level 1), freeing all auto_mallocs and timers
-
- - exits the program
-
***************************************************************************/
#include "emu.h"
-#include "emuopts.h"
-#include "osdepend.h"
+
#include "config.h"
-#include "debugger.h"
-#include "render.h"
-#include "uiinput.h"
#include "crsshair.h"
-#include "unzip.h"
-#include "debug/debugvw.h"
#include "debug/debugcpu.h"
+#include "debug/debugvw.h"
+#include "debugger.h"
#include "dirtc.h"
+#include "emuopts.h"
+#include "fileio.h"
+#include "http.h"
#include "image.h"
+#include "main.h"
+#include "natkeyboard.h"
#include "network.h"
+#include "render.h"
#include "romload.h"
#include "tilemap.h"
+#include "uiinput.h"
+
#include "ui/uimain.h"
-#include <time.h>
+
+#include "corestr.h"
+#include "unzip.h"
+
+#include "osdepend.h"
+
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
+#include <ctime>
+
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#endif
@@ -109,38 +60,33 @@ osd_interface &running_machine::osd() const
//-------------------------------------------------
running_machine::running_machine(const machine_config &_config, machine_manager &manager)
- : m_side_effects_disabled(0),
- debug_flags(0),
- m_config(_config),
- m_system(_config.gamedrv()),
- m_manager(manager),
- m_current_phase(machine_phase::PREINIT),
- m_paused(false),
- m_hard_reset_pending(false),
- m_exit_pending(false),
- m_soft_reset_timer(nullptr),
- m_rand_seed(0x9d14abd7),
- m_ui_active(_config.options().ui_active()),
- m_basename(_config.gamedrv().name),
- m_sample_rate(_config.options().sample_rate()),
- m_saveload_schedule(saveload_schedule::NONE),
- m_saveload_schedule_time(attotime::zero),
- m_saveload_searchpath(nullptr),
-
- m_save(*this),
- m_memory(*this),
- m_ioport(*this),
- m_parameters(*this),
- m_scheduler(*this),
- m_dummy_space(_config, "dummy_space", &root_device(), 0)
+ : m_side_effects_disabled(0)
+ , debug_flags(0)
+ , m_config(_config)
+ , m_system(_config.gamedrv())
+ , m_manager(manager)
+ , m_current_phase(machine_phase::PREINIT)
+ , m_paused(false)
+ , m_hard_reset_pending(false)
+ , m_exit_pending(false)
+ , m_soft_reset_timer(nullptr)
+ , m_rand_seed(0x9d14abd7)
+ , m_basename(_config.gamedrv().name)
+ , m_sample_rate(_config.options().sample_rate())
+ , m_saveload_schedule(saveload_schedule::NONE)
+ , m_saveload_schedule_time(attotime::zero)
+ , m_saveload_searchpath(nullptr)
+
+ , m_save(*this)
+ , m_memory(*this)
+ , m_ioport(*this)
+ , m_parameters(*this)
+ , m_scheduler(*this)
{
memset(&m_base_time, 0, sizeof(m_base_time));
- m_dummy_space.set_machine(*this);
- m_dummy_space.config_complete();
-
// set the machine on all devices
- device_iterator iter(root_device());
+ device_enumerator iter(root_device());
for (device_t &device : iter)
device.set_machine(*this);
@@ -178,7 +124,10 @@ std::string running_machine::describe_context() const
}
}
- return std::string("(no context)");
+ if (m_current_phase == machine_phase::RESET)
+ return std::string("(reset phase)");
+ else
+ return std::string("(no context)");
}
@@ -199,14 +148,15 @@ void running_machine::start()
m_soft_reset_timer = m_scheduler.timer_alloc(timer_expired_delegate(FUNC(running_machine::soft_reset), this));
// initialize UI input
- m_ui_input = make_unique_clear<ui_input_manager>(*this);
+ m_ui_input = std::make_unique<ui_input_manager>(*this);
- // init the osd layer
+ // init the OSD layer
m_manager.osd().init(*this);
- // create the video manager
+ // create the video manager and UI manager
m_video = std::make_unique<video_manager>(*this);
m_ui = manager().create_ui(*this);
+ m_ui->set_startup_text("Initializing...", true);
// initialize the base time (needed for doing record/playback)
::time(&m_base_time);
@@ -218,11 +168,14 @@ void running_machine::start()
if (newbase != 0)
m_base_time = newbase;
+ // initialize natural keyboard support after ports have been initialized
+ m_natkeyboard = std::make_unique<natural_keyboard>(*this);
+
// initialize the streams engine before the sound devices start
m_sound = std::make_unique<sound_manager>(*this);
// resolve objects that can be used by memory maps
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
device.resolve_pre_map();
// configure the address spaces, load ROMs (which needs
@@ -230,7 +183,7 @@ void running_machine::start()
// needs rom bases), and finally initialize CPUs (which needs
// complete address spaces). These operations must proceed in this
// order
- m_rom_load = make_unique_clear<rom_load_manager>(*this);
+ m_rom_load = std::make_unique<rom_load_manager>(*this);
m_memory.initialize();
// save the random seed or save states might be broken in drivers that use the rand() method
@@ -239,7 +192,7 @@ void running_machine::start()
// initialize image devices
m_image = std::make_unique<image_manager>(*this);
m_tilemap = std::make_unique<tilemap_manager>(*this);
- m_crosshair = make_unique_clear<crosshair_manager>(*this);
+ m_crosshair = std::make_unique<crosshair_manager>(*this);
m_network = std::make_unique<network_manager>(*this);
// initialize the debugger
@@ -249,30 +202,60 @@ void running_machine::start()
m_debugger = std::make_unique<debugger_manager>(*this);
}
- m_render->resolve_tags();
-
manager().create_custom(*this);
// resolve objects that are created by memory maps
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
device.resolve_post_map();
// register callbacks for the devices, then start them
add_notifier(MACHINE_NOTIFY_RESET, machine_notify_delegate(&running_machine::reset_all_devices, this));
add_notifier(MACHINE_NOTIFY_EXIT, machine_notify_delegate(&running_machine::stop_all_devices, this));
save().register_presave(save_prepost_delegate(FUNC(running_machine::presave_all_devices), this));
+ m_sound->before_devices_init();
start_all_devices();
+ m_sound->after_devices_init();
save().register_postload(save_prepost_delegate(FUNC(running_machine::postload_all_devices), this));
+
+ // save outputs created before start time
+ output().register_save();
+
+ m_render->resolve_tags();
+
+ // load cheat files
manager().load_cheatfiles(*this);
- // if we're coming in with a savegame request, process it now
+ // start recording movie if specified
+ const char *filename = options().mng_write();
+ if (filename[0] != 0)
+ m_video->begin_recording(filename, movie_recording::format::MNG);
+
+ filename = options().avi_write();
+ if (filename[0] != 0 && !m_video->is_recording())
+ m_video->begin_recording(filename, movie_recording::format::AVI);
+
const char *savegame = options().state();
if (savegame[0] != 0)
+ {
+ // if we're coming in with a savegame request, process it now
schedule_load(savegame);
-
- // if we're in autosave mode, schedule a load
- else if (options().autosave() && (m_system.flags & MACHINE_SUPPORTS_SAVE) != 0)
- schedule_load("auto");
+ }
+ else if (options().autosave())
+ {
+ // if we're in autosave mode, schedule a load
+ // m_save.supported() won't be set until save state registrations are finalised
+ bool supported = true;
+ for (device_t &device : device_enumerator(root_device()))
+ {
+ if (device.type().emulation_flags() & device_t::flags::SAVE_UNSUPPORTED)
+ {
+ supported = false;
+ break;
+ }
+ }
+ if (supported)
+ schedule_load("auto");
+ }
manager().update_machine();
}
@@ -298,26 +281,32 @@ int running_machine::run(bool quiet)
if (options().log() && !quiet)
{
m_logfile = std::make_unique<emu_file>(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr = m_logfile->open("error.log");
- if (filerr != osd_file::error::NONE)
- throw emu_fatalerror("running_machine::run: unable to open log file");
+ std::error_condition const filerr = m_logfile->open("error.log");
+ if (filerr)
+ throw emu_fatalerror("running_machine::run: unable to open error.log file");
using namespace std::placeholders;
add_logerror_callback(std::bind(&running_machine::logfile_callback, this, _1));
}
+ if (options().debug() && options().debuglog())
+ {
+ m_debuglogfile = std::make_unique<emu_file>(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ std::error_condition const filerr = m_debuglogfile->open("debug.log");
+ if (filerr)
+ throw emu_fatalerror("running_machine::run: unable to open debug.log file");
+ }
+
// then finish setting up our local machine
start();
+ // disallow save state registrations starting here
+ m_save.allow_registration(false);
+
// load the configuration settings
manager().before_load_settings(*this);
m_configuration->load_settings();
- // disallow save state registrations starting here.
- // Don't do it earlier, config load can create network
- // devices with timers.
- m_save.allow_registration(false);
-
// load the NVRAM
nvram_load();
@@ -328,6 +317,8 @@ int running_machine::run(bool quiet)
if (!quiet)
sound().start_recording();
+ m_hard_reset_pending = false;
+
// initialize ui lists
// display the startup screens
manager().ui_initialize(*this);
@@ -341,8 +332,6 @@ int running_machine::run(bool quiet)
export_http_api();
- m_hard_reset_pending = false;
-
#if defined(__EMSCRIPTEN__)
// break out to our async javascript loop and halt
emscripten_set_running_machine(this);
@@ -351,20 +340,21 @@ int running_machine::run(bool quiet)
// run the CPUs until a reset or exit
while ((!m_hard_reset_pending && !m_exit_pending) || m_saveload_schedule != saveload_schedule::NONE)
{
- g_profiler.start(PROFILER_EXTRA);
+ auto profile = g_profiler.start(PROFILER_EXTRA);
// execute CPUs if not paused
if (!m_paused)
m_scheduler.timeslice();
- // otherwise, just pump video updates through
+ // otherwise, just pump video updates and sound mapping updates through
else
+ {
m_video->frame_update();
+ sound().mapping_update();
+ }
// handle save/load
if (m_saveload_schedule != saveload_schedule::NONE)
handle_saveload();
-
- g_profiler.stop();
}
m_manager.http()->clear();
@@ -377,29 +367,29 @@ int running_machine::run(bool quiet)
nvram_save();
m_configuration->save_settings();
}
- catch (emu_fatalerror &fatal)
+ catch (emu_fatalerror const &fatal)
{
- osd_printf_error("Fatal error: %s\n", fatal.string());
+ osd_printf_error("Fatal error: %s\n", fatal.what());
error = EMU_ERR_FATALERROR;
if (fatal.exitcode() != 0)
error = fatal.exitcode();
}
- catch (emu_exception &)
+ catch (emu_exception const &)
{
osd_printf_error("Caught unhandled emulator exception\n");
error = EMU_ERR_FATALERROR;
}
- catch (binding_type_exception &btex)
+ catch (binding_type_exception const &btex)
{
- osd_printf_error("Error performing a late bind of type %s to %s\n", btex.m_actual_type.name(), btex.m_target_type.name());
+ osd_printf_error("Error performing a late bind of function expecting type %s to instance of type %s\n", btex.target_type().name(), btex.actual_type().name());
error = EMU_ERR_FATALERROR;
}
- catch (tag_add_exception &aex)
+ catch (tag_add_exception const &aex)
{
osd_printf_error("Tag '%s' already exists in tagged map\n", aex.tag());
error = EMU_ERR_FATALERROR;
}
- catch (std::exception &ex)
+ catch (std::exception const &ex)
{
osd_printf_error("Caught unhandled %s exception: %s\n", typeid(ex).name(), ex.what());
error = EMU_ERR_FATALERROR;
@@ -435,7 +425,7 @@ void running_machine::schedule_exit()
m_scheduler.eat_all_cycles();
// if we're autosaving on exit, schedule a save as well
- if (options().autosave() && (m_system.flags & MACHINE_SUPPORTS_SAVE) && this->time() > attotime::zero)
+ if (options().autosave() && m_save.supported() && (this->time() > attotime::zero))
schedule_save("auto");
}
@@ -474,7 +464,7 @@ void running_machine::schedule_soft_reset()
//-------------------------------------------------
// get_statename - allow to specify a subfolder of
// the state directory for state loading/saving,
-// very useful for MESS and consoles or computers
+// very useful for consoles or computers
// where you can have separate folders for diff
// software
//-------------------------------------------------
@@ -499,7 +489,7 @@ std::string running_machine::get_statename(const char *option) const
if (pos != -1)
{
// if more %d are found, revert to default and ignore them all
- if (statename_str.find(statename_dev.c_str(), pos + 3) != -1)
+ if (statename_str.find(statename_dev, pos + 3) != -1)
statename_str.assign("%g");
// else if there is a single %d, try to create the correct snapname
else
@@ -507,21 +497,10 @@ std::string running_machine::get_statename(const char *option) const
int name_found = 0;
// find length of the device name
- int end1 = statename_str.find("/", pos + 3);
- int end2 = statename_str.find("%", pos + 3);
- int end;
-
- if ((end1 != -1) && (end2 != -1))
- end = std::min(end1, end2);
- else if (end1 != -1)
- end = end1;
- else if (end2 != -1)
- end = end2;
- else
+ int end = statename_str.find_first_not_of("abcdefghijklmnopqrstuvwxyz1234567890", pos + 3);
+ if (end == -1)
end = statename_str.length();
- if (end - pos < 3)
- fatalerror("Something very wrong is going on!!!\n");
// copy the device name to an std::string
std::string devname_str;
@@ -529,7 +508,7 @@ std::string running_machine::get_statename(const char *option) const
//printf("check template: %s\n", devname_str.c_str());
// verify that there is such a device for this system
- for (device_image_interface &image : image_interface_iterator(root_device()))
+ for (device_image_interface &image : image_interface_enumerator(root_device()))
{
// get the device name
std::string tempdevname(image.brief_instance_name());
@@ -543,7 +522,7 @@ std::string running_machine::get_statename(const char *option) const
std::string filename(image.basename_noext());
// setup snapname and remove the %d_
- strreplace(statename_str, devname_str.c_str(), filename.c_str());
+ strreplace(statename_str, devname_str, filename);
statename_str.erase(pos, 3);
//printf("check image: %s\n", filename.c_str());
@@ -633,10 +612,10 @@ void running_machine::schedule_save(std::string &&filename)
// immediate_save - save state.
//-------------------------------------------------
-void running_machine::immediate_save(const char *filename)
+void running_machine::immediate_save(std::string_view filename)
{
// specify the filename to save or load
- set_saveload_filename(filename);
+ set_saveload_filename(std::string(filename));
// set up some parameters for handle_saveload()
m_saveload_schedule = saveload_schedule::SAVE;
@@ -670,10 +649,10 @@ void running_machine::schedule_load(std::string &&filename)
// immediate_load - load state.
//-------------------------------------------------
-void running_machine::immediate_load(const char *filename)
+void running_machine::immediate_load(std::string_view filename)
{
// specify the filename to save or load
- set_saveload_filename(filename);
+ set_saveload_filename(std::string(filename));
// set up some parameters for handle_saveload()
m_saveload_schedule = saveload_schedule::LOAD;
@@ -856,7 +835,7 @@ void running_machine::current_datetime(system_time &systime)
void running_machine::set_rtc_datetime(const system_time &systime)
{
- for (device_rtc_interface &rtc : rtc_interface_iterator(root_device()))
+ for (device_rtc_interface &rtc : rtc_interface_enumerator(root_device()))
if (rtc.has_battery())
rtc.set_current_time(systime);
}
@@ -901,6 +880,7 @@ void running_machine::handle_saveload()
if (!m_saveload_pending_file.empty())
{
const char *const opname = (m_saveload_schedule == saveload_schedule::LOAD) ? "load" : "save";
+ const char *const preposname = (m_saveload_schedule == saveload_schedule::LOAD) ? "from" : "to";
// if there are anonymous timers, we can't save just yet, and we can't load yet either
// because the timers might overwrite data we have loaded
@@ -908,7 +888,7 @@ void running_machine::handle_saveload()
{
// if more than a second has passed, we're probably screwed
if ((this->time() - m_saveload_schedule_time) > attotime::from_seconds(1))
- popmessage("Unable to %s due to pending anonymous timers. See error.log for details.", opname);
+ popmessage("Error: Unable to %s state %s %s due to pending anonymous timers. See error.log for details.", opname, preposname, m_saveload_pending_file);
else
return; // return without cancelling the operation
}
@@ -919,41 +899,38 @@ void running_machine::handle_saveload()
// open the file
emu_file file(m_saveload_searchpath ? m_saveload_searchpath : "", openflags);
auto const filerr = file.open(m_saveload_pending_file);
- if (filerr == osd_file::error::NONE)
+ if (!filerr)
{
- const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "loaded" : "saved";
-
// read/write the save state
save_error saverr = (m_saveload_schedule == saveload_schedule::LOAD) ? m_save.read_file(file) : m_save.write_file(file);
// handle the result
switch (saverr)
{
- case STATERR_ILLEGAL_REGISTRATIONS:
- popmessage("Error: Unable to %s state due to illegal registrations. See error.log for details.", opname);
- break;
-
case STATERR_INVALID_HEADER:
- popmessage("Error: Unable to %s state due to an invalid header. Make sure the save state is correct for this machine.", opname);
+ popmessage("Error: Unable to %s state %s %s due to an invalid header. Make sure the save state is correct for this system.", opname, preposname, m_saveload_pending_file);
break;
case STATERR_READ_ERROR:
- popmessage("Error: Unable to %s state due to a read error (file is likely corrupt).", opname);
+ popmessage("Error: Unable to %s state %s %s due to a read error (file is likely corrupt).", opname, preposname, m_saveload_pending_file);
break;
case STATERR_WRITE_ERROR:
- popmessage("Error: Unable to %s state due to a write error. Verify there is enough disk space.", opname);
+ popmessage("Error: Unable to %s state %s %s due to a write error. Verify there is enough disk space.", opname, preposname, m_saveload_pending_file);
break;
case STATERR_NONE:
- if (!(m_system.flags & MACHINE_SUPPORTS_SAVE))
- popmessage("State successfully %s.\nWarning: Save states are not officially supported for this machine.", opnamed);
+ {
+ const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "Loaded" : "Saved";
+ if (!m_save.supported())
+ popmessage("%s state %s %s.\nWarning: Save states are not officially supported for this system.", opnamed, preposname, m_saveload_pending_file);
else
- popmessage("State successfully %s.", opnamed);
+ popmessage("%s state %s %s.", opnamed, preposname, m_saveload_pending_file);
break;
+ }
default:
- popmessage("Error: Unknown error during state %s.", opnamed);
+ popmessage("Error: Unknown error during %s state %s %s.", opname, preposname, m_saveload_pending_file);
break;
}
@@ -961,11 +938,15 @@ void running_machine::handle_saveload()
if (saverr != STATERR_NONE && m_saveload_schedule == saveload_schedule::SAVE)
file.remove_on_close();
}
- else if (openflags == OPEN_FLAG_READ && filerr == osd_file::error::NOT_FOUND)
+ else if ((openflags == OPEN_FLAG_READ) && (std::errc::no_such_file_or_directory == filerr))
+ {
// attempt to load a non-existent savestate, report empty slot
- popmessage("Error: No savestate file to load.", opname);
+ popmessage("Error: Load state file %s not found.", m_saveload_pending_file);
+ }
else
- popmessage("Error: Failed to open file for %s operation.", opname);
+ {
+ popmessage("Error: Failed to open %s for %s state operation.", m_saveload_pending_file, opname);
+ }
}
}
@@ -981,7 +962,7 @@ void running_machine::handle_saveload()
// of the system
//-------------------------------------------------
-void running_machine::soft_reset(void *ptr, s32 param)
+void running_machine::soft_reset(s32 param)
{
logerror("Soft reset\n");
@@ -1012,49 +993,56 @@ void running_machine::logfile_callback(const char *buffer)
//-------------------------------------------------
+// steal_debuglogfile - relinquish ownership of
+// the debug.log file
+//-------------------------------------------------
+
+std::unique_ptr<emu_file> running_machine::steal_debuglogfile()
+{
+ return std::move(m_debuglogfile);
+}
+
+
+//-------------------------------------------------
// start_all_devices - start any unstarted devices
//-------------------------------------------------
void running_machine::start_all_devices()
{
- m_dummy_space.start();
-
// iterate through the devices
int last_failed_starts = -1;
- while (last_failed_starts != 0)
+ do
{
// iterate over all devices
int failed_starts = 0;
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
if (!device.started())
{
// attempt to start the device, catching any expected exceptions
try
{
// if the device doesn't have a machine yet, set it first
- if (device.m_machine == nullptr)
+ if (!device.m_machine)
device.set_machine(*this);
// now start the device
osd_printf_verbose("Starting %s '%s'\n", device.name(), device.tag());
device.start();
}
-
- // handle missing dependencies by moving the device to the end
- catch (device_missing_dependencies &)
+ catch (device_missing_dependencies const &)
{
- // if we're the end, fail
+ // handle missing dependencies by moving the device to the end
osd_printf_verbose(" (missing dependencies; rescheduling)\n");
failed_starts++;
}
}
- // each iteration should reduce the number of failed starts; error if
- // this doesn't happen
+ // each iteration should reduce the number of failed starts; error if this doesn't happen
if (failed_starts == last_failed_starts)
throw emu_fatalerror("Circular dependency in device startup!");
last_failed_starts = failed_starts;
}
+ while (last_failed_starts);
}
@@ -1082,7 +1070,7 @@ void running_machine::stop_all_devices()
debugger().cpu().comment_save();
// iterate over devices and stop them
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
device.stop();
}
@@ -1094,7 +1082,7 @@ void running_machine::stop_all_devices()
void running_machine::presave_all_devices()
{
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
device.pre_save();
}
@@ -1106,7 +1094,7 @@ void running_machine::presave_all_devices()
void running_machine::postload_all_devices()
{
- for (device_t &device : device_iterator(root_device()))
+ for (device_t &device : device_enumerator(root_device()))
device.post_load();
}
@@ -1159,12 +1147,13 @@ std::string running_machine::nvram_filename(device_t &device) const
void running_machine::nvram_load()
{
- for (device_nvram_interface &nvram : nvram_interface_iterator(root_device()))
+ for (device_nvram_interface &nvram : nvram_interface_enumerator(root_device()))
{
emu_file file(options().nvram_directory(), OPEN_FLAG_READ);
- if (file.open(nvram_filename(nvram.device())) == osd_file::error::NONE)
+ if (nvram.nvram_backup_enabled() && !file.open(nvram_filename(nvram.device())))
{
- nvram.nvram_load(file);
+ if (!nvram.nvram_load(file))
+ osd_printf_error("Error reading NVRAM file %s\n", file.filename());
file.close();
}
else
@@ -1179,13 +1168,26 @@ void running_machine::nvram_load()
void running_machine::nvram_save()
{
- for (device_nvram_interface &nvram : nvram_interface_iterator(root_device()))
+ for (device_nvram_interface &nvram : nvram_interface_enumerator(root_device()))
{
- emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- if (file.open(nvram_filename(nvram.device())) == osd_file::error::NONE)
+ if (nvram.nvram_can_save())
{
- nvram.nvram_save(file);
- file.close();
+ emu_file file(options().nvram_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
+ if (!file.open(nvram_filename(nvram.device())))
+ {
+ bool error = false;
+
+ if (!nvram.nvram_save(file))
+ {
+ error = true;
+ osd_printf_error("Error writing NVRAM file %s\n", file.filename());
+ }
+
+ // close and perhaps delete the file
+ if (error || file.size() == 0)
+ file.remove_on_close();
+ file.close();
+ }
}
}
}
@@ -1200,7 +1202,7 @@ void running_machine::popup_clear() const
ui().popup_time(0, " ");
}
-void running_machine::popup_message(util::format_argument_pack<std::ostream> const &args) const
+void running_machine::popup_message(util::format_argument_pack<char> const &args) const
{
std::string const temp(string_format(args));
ui().popup_time(temp.length() / 40 + 2, "%s", temp);
@@ -1226,7 +1228,7 @@ running_machine::notifier_callback_item::notifier_callback_item(machine_notify_d
//-------------------------------------------------
running_machine::logerror_callback_item::logerror_callback_item(logerror_callback func)
- : m_func(func)
+ : m_func(std::move(func))
{
}
@@ -1244,7 +1246,7 @@ void running_machine::export_http_api()
writer.Key("devices");
writer.StartArray();
- device_iterator iter(this->root_device());
+ device_enumerator iter(this->root_device());
for (device_t &device : iter)
writer.String(device.tag());
@@ -1311,51 +1313,6 @@ void system_time::full_time::set(struct tm &t)
//**************************************************************************
-// DUMMY ADDRESS SPACE
-//**************************************************************************
-
-READ8_MEMBER(dummy_space_device::read)
-{
- throw emu_fatalerror("Attempted to read from generic address space (offs %X)\n", offset);
-}
-
-WRITE8_MEMBER(dummy_space_device::write)
-{
- throw emu_fatalerror("Attempted to write to generic address space (offs %X = %02X)\n", offset, data);
-}
-
-void dummy_space_device::dummy(address_map &map)
-{
- map(0x00000000, 0xffffffff).rw(FUNC(dummy_space_device::read), FUNC(dummy_space_device::write));
-}
-
-DEFINE_DEVICE_TYPE(DUMMY_SPACE, dummy_space_device, "dummy_space", "Dummy Space")
-
-dummy_space_device::dummy_space_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) :
- device_t(mconfig, DUMMY_SPACE, tag, owner, clock),
- device_memory_interface(mconfig, *this),
- m_space_config("dummy", ENDIANNESS_LITTLE, 8, 32, 0, address_map_constructor(FUNC(dummy_space_device::dummy), this))
-{
-}
-
-void dummy_space_device::device_start()
-{
-}
-
-//-------------------------------------------------
-// memory_space_config - return a description of
-// any address spaces owned by this device
-//-------------------------------------------------
-
-device_memory_interface::space_config_vector dummy_space_device::memory_space_config() const
-{
- return space_config_vector {
- std::make_pair(0, &m_space_config)
- };
-}
-
-
-//**************************************************************************
// JAVASCRIPT PORT-SPECIFIC
//**************************************************************************
@@ -1367,7 +1324,7 @@ void running_machine::emscripten_main_loop()
{
running_machine *machine = emscripten_running_machine;
- g_profiler.start(PROFILER_EXTRA);
+ auto profile = g_profiler.start(PROFILER_EXTRA);
// execute CPUs if not paused
if (!machine->m_paused)
@@ -1400,8 +1357,6 @@ void running_machine::emscripten_main_loop()
{
emscripten_cancel_main_loop();
}
-
- g_profiler.stop();
}
void running_machine::emscripten_set_running_machine(running_machine *machine)