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.cpp311
1 files changed, 113 insertions, 198 deletions
diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp
index aecaf26ed15..573c1b9e095 100644
--- a/src/emu/machine.cpp
+++ b/src/emu/machine.cpp
@@ -6,91 +6,40 @@
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 "natkeyboard.h"
+#include "uiinput.h"
+
#include "ui/uimain.h"
+
#include "corestr.h"
-#include <ctime>
+#include "unzip.h"
+
+#include "osdepend.h"
+
#include <rapidjson/writer.h>
#include <rapidjson/stringbuffer.h>
+#include <ctime>
+
#if defined(__EMSCRIPTEN__)
#include <emscripten.h>
#endif
@@ -111,36 +60,31 @@ 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_enumerator iter(root_device());
for (device_t &device : iter)
@@ -180,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)");
}
@@ -203,12 +150,13 @@ void running_machine::start()
// initialize UI input
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);
@@ -317,8 +265,8 @@ 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)
+ 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;
@@ -328,8 +276,8 @@ int running_machine::run(bool quiet)
if (options().debug() && options().debuglog())
{
m_debuglogfile = std::make_unique<emu_file>(OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
- osd_file::error filerr = m_debuglogfile->open("debug.log");
- if (filerr != osd_file::error::NONE)
+ std::error_condition const filerr = m_debuglogfile->open("debug.log");
+ if (filerr)
throw emu_fatalerror("running_machine::run: unable to open debug.log file");
}
@@ -378,7 +326,7 @@ 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)
@@ -390,8 +338,6 @@ int running_machine::run(bool quiet)
// handle save/load
if (m_saveload_schedule != saveload_schedule::NONE)
handle_saveload();
-
- g_profiler.stop();
}
m_manager.http()->clear();
@@ -404,29 +350,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.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;
@@ -501,7 +447,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
//-------------------------------------------------
@@ -649,10 +595,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;
@@ -686,10 +632,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;
@@ -917,6 +863,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
@@ -924,7 +871,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
}
@@ -935,41 +882,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:
+ {
+ const char *const opnamed = (m_saveload_schedule == saveload_schedule::LOAD) ? "Loaded" : "Saved";
if (!(m_system.flags & MACHINE_SUPPORTS_SAVE))
- popmessage("State successfully %s.\nWarning: Save states are not officially supported for this machine.", opnamed);
+ 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;
}
@@ -977,14 +921,14 @@ 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);
}
}
}
@@ -1001,7 +945,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");
@@ -1032,16 +976,25 @@ 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;
@@ -1052,29 +1005,27 @@ void running_machine::start_all_devices()
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);
}
@@ -1182,9 +1133,10 @@ void running_machine::nvram_load()
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
@@ -1204,9 +1156,19 @@ void running_machine::nvram_save()
if (nvram.nvram_can_save())
{
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 (!file.open(nvram_filename(nvram.device())))
{
- nvram.nvram_save(file);
+ 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();
}
}
@@ -1223,7 +1185,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);
@@ -1334,51 +1296,6 @@ void system_time::full_time::set(struct tm &t)
//**************************************************************************
-// DUMMY ADDRESS SPACE
-//**************************************************************************
-
-u8 dummy_space_device::read(offs_t offset)
-{
- throw emu_fatalerror("Attempted to read from generic address space (offs %X)\n", offset);
-}
-
-void dummy_space_device::write(offs_t offset, u8 data)
-{
- 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
//**************************************************************************
@@ -1390,7 +1307,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)
@@ -1423,8 +1340,6 @@ void running_machine::emscripten_main_loop()
{
emscripten_cancel_main_loop();
}
-
- g_profiler.stop();
}
void running_machine::emscripten_set_running_machine(running_machine *machine)