mame/src/emu/machine.h

441 lines
16 KiB
C++

// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************
machine.h
Controls execution of the core MAME system.
***************************************************************************/
#pragma once
#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif
#ifndef MAME_EMU_MACHINE_H
#define MAME_EMU_MACHINE_H
#include <functional>
#include <time.h>
// forward declaration instead of osdepend.h
class osd_interface;
//**************************************************************************
// CONSTANTS
//**************************************************************************
// machine phases
enum machine_phase
{
MACHINE_PHASE_PREINIT,
MACHINE_PHASE_INIT,
MACHINE_PHASE_RESET,
MACHINE_PHASE_RUNNING,
MACHINE_PHASE_EXIT
};
// notification callback types
enum machine_notification
{
MACHINE_NOTIFY_FRAME,
MACHINE_NOTIFY_RESET,
MACHINE_NOTIFY_PAUSE,
MACHINE_NOTIFY_RESUME,
MACHINE_NOTIFY_EXIT,
MACHINE_NOTIFY_COUNT
};
// debug flags
const int DEBUG_FLAG_ENABLED = 0x00000001; // debugging is enabled
const int DEBUG_FLAG_CALL_HOOK = 0x00000002; // CPU cores must call instruction hook
const int DEBUG_FLAG_WPR_PROGRAM = 0x00000010; // watchpoints are enabled for PROGRAM memory reads
const int DEBUG_FLAG_WPR_DATA = 0x00000020; // watchpoints are enabled for DATA memory reads
const int DEBUG_FLAG_WPR_IO = 0x00000040; // watchpoints are enabled for IO memory reads
const int DEBUG_FLAG_WPW_PROGRAM = 0x00000100; // watchpoints are enabled for PROGRAM memory writes
const int DEBUG_FLAG_WPW_DATA = 0x00000200; // watchpoints are enabled for DATA memory writes
const int DEBUG_FLAG_WPW_IO = 0x00000400; // watchpoints are enabled for IO memory writes
const int DEBUG_FLAG_OSD_ENABLED = 0x00001000; // The OSD debugger is enabled
//**************************************************************************
// MACROS
//**************************************************************************
// global allocation helpers
#define auto_alloc(m, t) pool_alloc(static_cast<running_machine &>(m).respool(), t)
#define auto_alloc_clear(m, t) pool_alloc_clear(static_cast<running_machine &>(m).respool(), t)
#define auto_alloc_array(m, t, c) pool_alloc_array(static_cast<running_machine &>(m).respool(), t, c)
#define auto_alloc_array_clear(m, t, c) pool_alloc_array_clear(static_cast<running_machine &>(m).respool(), t, c)
#define auto_free(m, v) pool_free(static_cast<running_machine &>(m).respool(), v)
//**************************************************************************
// TYPE DEFINITIONS
//**************************************************************************
// forward declarations
class render_manager;
class sound_manager;
class video_manager;
class ui_manager;
class tilemap_manager;
class debug_view_manager;
class network_manager;
class bookkeeping_manager;
class configuration_manager;
class output_manager;
class ui_input_manager;
class crosshair_manager;
class image_manager;
class rom_load_manager;
class debugger_manager;
class osd_interface;
enum class config_type;
// ======================> system_time
// system time description, both local and UTC
class system_time
{
public:
system_time();
explicit system_time(time_t t);
void set(time_t t);
struct full_time
{
void set(struct tm &t);
u8 second; // seconds (0-59)
u8 minute; // minutes (0-59)
u8 hour; // hours (0-23)
u8 mday; // day of month (1-31)
u8 month; // month (0-11)
s32 year; // year (1=1 AD)
u8 weekday; // day of week (0-6)
u16 day; // day of year (0-365)
u8 is_dst; // is this daylight savings?
};
s64 time; // number of seconds elapsed since midnight, January 1 1970 UTC
full_time local_time; // local time
full_time utc_time; // UTC coordinated time
};
// ======================> dummy_space_device
// a dummy address space for passing to handlers outside of the memory system
class dummy_space_device : public device_t,
public device_memory_interface
{
public:
dummy_space_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock);
DECLARE_READ8_MEMBER(read);
DECLARE_WRITE8_MEMBER(write);
protected:
// device-level overrides
virtual void device_start() override;
// device_memory_interface overrides
virtual const address_space_config *memory_space_config(address_spacenum spacenum = AS_0) const override;
private:
const address_space_config m_space_config;
};
// ======================> running_machine
typedef delegate<void ()> machine_notify_delegate;
// description of the currently-running machine
class running_machine
{
DISABLE_COPYING(running_machine);
friend class sound_manager;
friend class memory_manager;
typedef std::function<void(const char*)> logerror_callback;
// must be at top of member variables
resource_pool m_respool; // pool of resources for this machine
public:
// construction/destruction
running_machine(const machine_config &config, machine_manager &manager);
~running_machine();
// getters
const machine_config &config() const { return m_config; }
device_t &root_device() const { return m_config.root_device(); }
const game_driver &system() const { return m_system; }
osd_interface &osd() const;
machine_manager &manager() const { return m_manager; }
resource_pool &respool() { return m_respool; }
device_scheduler &scheduler() { return m_scheduler; }
save_manager &save() { return m_save; }
memory_manager &memory() { return m_memory; }
ioport_manager &ioport() { return m_ioport; }
parameters_manager &parameters() { return m_parameters; }
render_manager &render() const { assert(m_render != nullptr); return *m_render; }
input_manager &input() const { assert(m_input != nullptr); return *m_input; }
sound_manager &sound() const { assert(m_sound != nullptr); return *m_sound; }
video_manager &video() const { assert(m_video != nullptr); return *m_video; }
network_manager &network() const { assert(m_network != nullptr); return *m_network; }
bookkeeping_manager &bookkeeping() const { assert(m_network != nullptr); return *m_bookkeeping; }
configuration_manager &configuration() const { assert(m_configuration != nullptr); return *m_configuration; }
output_manager &output() const { assert(m_output != nullptr); return *m_output; }
ui_manager &ui() const { assert(m_ui != nullptr); return *m_ui; }
ui_input_manager &ui_input() const { assert(m_ui_input != nullptr); return *m_ui_input; }
crosshair_manager &crosshair() const { assert(m_crosshair != nullptr); return *m_crosshair; }
image_manager &image() const { assert(m_image != nullptr); return *m_image; }
rom_load_manager &rom_load() const { assert(m_rom_load != nullptr); return *m_rom_load; }
tilemap_manager &tilemap() const { assert(m_tilemap != nullptr); return *m_tilemap; }
debug_view_manager &debug_view() const { assert(m_debug_view != nullptr); return *m_debug_view; }
debugger_manager &debugger() const { assert(m_debugger != nullptr); return *m_debugger; }
driver_device *driver_data() const { return &downcast<driver_device &>(root_device()); }
template<class _DriverClass> _DriverClass *driver_data() const { return &downcast<_DriverClass &>(root_device()); }
machine_phase phase() const { return m_current_phase; }
bool paused() const { return m_paused || (m_current_phase != MACHINE_PHASE_RUNNING); }
bool exit_pending() const { return m_exit_pending; }
bool ui_active() const { return m_ui_active; }
const char *basename() const { return m_basename.c_str(); }
int sample_rate() const { return m_sample_rate; }
bool save_or_load_pending() const { return !m_saveload_pending_file.empty(); }
screen_device *first_screen() const { return primary_screen; }
// additional helpers
emu_options &options() const { return m_config.options(); }
attotime time() const { return m_scheduler.time(); }
bool scheduled_event_pending() const { return m_exit_pending || m_hard_reset_pending; }
bool allow_logging() const { return !m_logerror_list.empty(); }
// fetch items by name
inline device_t *device(const char *tag) const { return root_device().subdevice(tag); }
template<class _DeviceClass> inline _DeviceClass *device(const char *tag) { return downcast<_DeviceClass *>(device(tag)); }
// immediate operations
int run(bool quiet);
void pause();
void resume();
void toggle_pause();
void add_notifier(machine_notification event, machine_notify_delegate callback, bool first = false);
void call_notifiers(machine_notification which);
void add_logerror_callback(logerror_callback callback);
void set_ui_active(bool active) { m_ui_active = active; }
void debug_break();
void export_http_api();
// TODO: Do saves and loads still require scheduling?
void immediate_save(const char *filename);
void immediate_load(const char *filename);
// scheduled operations
void schedule_exit();
void schedule_hard_reset();
void schedule_soft_reset();
void schedule_save(const char *filename);
void schedule_load(const char *filename);
// date & time
void base_datetime(system_time &systime);
void current_datetime(system_time &systime);
void set_rtc_datetime(const system_time &systime);
// misc
address_space &dummy_space() const { return m_dummy_space.space(AS_PROGRAM); }
void popmessage() const { popmessage(static_cast<char const *>(nullptr)); }
template <typename Format, typename... Params> void popmessage(Format &&fmt, Params &&... args) const;
template <typename Format, typename... Params> void logerror(Format &&fmt, Params &&... args) const;
void strlog(const char *str) const;
u32 rand();
const char *describe_context();
std::string compose_saveload_filename(const char *base_filename, const char **searchpath = nullptr);
// CPU information
cpu_device * firstcpu; // first CPU
private:
// video-related information
screen_device * primary_screen; // the primary screen device, or nullptr if screenless
public:
// debugger-related information
u32 debug_flags; // the current debug flags
private:
// internal helpers
template <typename T> struct is_null { template <typename U> static bool value(U &&x) { return false; } };
template <typename T> struct is_null<T *> { template <typename U> static bool value(U &&x) { return !x; } };
void start();
void set_saveload_filename(const char *filename);
std::string get_statename(const char *statename_opt) const;
void handle_saveload();
void soft_reset(void *ptr = nullptr, s32 param = 0);
std::string nvram_filename(device_t &device) const;
void nvram_load();
void nvram_save();
void popup_clear() const;
void popup_message(util::format_argument_pack<std::ostream> const &args) const;
// internal callbacks
void logfile_callback(const char *buffer);
// internal device helpers
void start_all_devices();
void reset_all_devices();
void stop_all_devices();
void presave_all_devices();
void postload_all_devices();
// internal state
const machine_config & m_config; // reference to the constructed machine_config
const game_driver & m_system; // reference to the definition of the game machine
machine_manager & m_manager; // reference to machine manager system
// managers
std::unique_ptr<render_manager> m_render; // internal data from render.cpp
std::unique_ptr<input_manager> m_input; // internal data from input.cpp
std::unique_ptr<sound_manager> m_sound; // internal data from sound.cpp
std::unique_ptr<video_manager> m_video; // internal data from video.cpp
ui_manager *m_ui; // internal data from ui.cpp
std::unique_ptr<ui_input_manager> m_ui_input; // internal data from uiinput.cpp
std::unique_ptr<tilemap_manager> m_tilemap; // internal data from tilemap.cpp
std::unique_ptr<debug_view_manager> m_debug_view; // internal data from debugvw.cpp
std::unique_ptr<network_manager> m_network; // internal data from network.cpp
std::unique_ptr<bookkeeping_manager> m_bookkeeping;// internal data from bookkeeping.cpp
std::unique_ptr<configuration_manager> m_configuration; // internal data from config.cpp
std::unique_ptr<output_manager> m_output; // internal data from output.cpp
std::unique_ptr<crosshair_manager> m_crosshair; // internal data from crsshair.cpp
std::unique_ptr<image_manager> m_image; // internal data from image.cpp
std::unique_ptr<rom_load_manager> m_rom_load; // internal data from romload.cpp
std::unique_ptr<debugger_manager> m_debugger; // internal data from debugger.cpp
// system state
machine_phase m_current_phase; // current execution phase
bool m_paused; // paused?
bool m_hard_reset_pending; // is a hard reset pending?
bool m_exit_pending; // is an exit pending?
emu_timer * m_soft_reset_timer; // timer used to schedule a soft reset
// misc state
u32 m_rand_seed; // current random number seed
bool m_ui_active; // ui active or not (useful for games / systems with keyboard inputs)
time_t m_base_time; // real time at initial emulation time
std::string m_basename; // basename used for game-related paths
std::string m_context; // context string buffer
int m_sample_rate; // the digital audio sample rate
std::unique_ptr<emu_file> m_logfile; // pointer to the active log file
// load/save management
enum saveload_schedule
{
SLS_NONE,
SLS_SAVE,
SLS_LOAD
};
saveload_schedule m_saveload_schedule;
attotime m_saveload_schedule_time;
std::string m_saveload_pending_file;
const char * m_saveload_searchpath;
// notifier callbacks
struct notifier_callback_item
{
// construction/destruction
notifier_callback_item(machine_notify_delegate func);
// state
machine_notify_delegate m_func;
};
std::list<std::unique_ptr<notifier_callback_item>> m_notifier_list[MACHINE_NOTIFY_COUNT];
// logerror callbacks
class logerror_callback_item
{
public:
// construction/destruction
logerror_callback_item(logerror_callback func);
// state
logerror_callback m_func;
};
std::list<std::unique_ptr<logerror_callback_item>> m_logerror_list;
// embedded managers and objects
save_manager m_save; // save manager
memory_manager m_memory; // memory manager
ioport_manager m_ioport; // I/O port manager
parameters_manager m_parameters; // parameters manager
device_scheduler m_scheduler; // scheduler object
// string formatting buffer
mutable util::ovectorstream m_string_buffer;
// configuration state
dummy_space_device m_dummy_space;
};
//**************************************************************************
// MEMBER TEMPLATES
//**************************************************************************
/*-------------------------------------------------
popmessage - pop up a user-visible message
-------------------------------------------------*/
template <typename Format, typename... Params>
inline void running_machine::popmessage(Format &&fmt, Params &&... args) const
{
// if the format is nullptr, it is a signal to clear the popmessage
// otherwise, generate the buffer and call the UI to display the message
if (is_null<Format>::value(fmt))
popup_clear();
else
popup_message(util::make_format_argument_pack(std::forward<Format>(fmt), std::forward<Params>(args)...));
}
/*-------------------------------------------------
logerror - log to the debugger and any other
OSD-defined output streams
-------------------------------------------------*/
template <typename Format, typename... Params>
inline void running_machine::logerror(Format &&fmt, Params &&... args) const
{
// process only if there is a target
if (allow_logging())
{
g_profiler.start(PROFILER_LOGERROR);
// dump to the buffer
m_string_buffer.clear();
m_string_buffer.seekp(0);
util::stream_format(m_string_buffer, std::forward<Format>(fmt), std::forward<Params>(args)...);
m_string_buffer.put('\0');
strlog(&m_string_buffer.vec()[0]);
g_profiler.stop();
}
}
#endif /* MAME_EMU_MACHINE_H */