// 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 __MACHINE_H__ #define __MACHINE_H__ #include #include // 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(m).respool(), t) #define auto_alloc_clear(m, t) pool_alloc_clear(static_cast(m).respool(), t) #define auto_alloc_array(m, t, c) pool_alloc_array(static_cast(m).respool(), t, c) #define auto_alloc_array_clear(m, t, c) pool_alloc_array_clear(static_cast(m).respool(), t, c) #define auto_free(m, v) pool_free(static_cast(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); uint8_t second; // seconds (0-59) uint8_t minute; // minutes (0-59) uint8_t hour; // hours (0-23) uint8_t mday; // day of month (1-31) uint8_t month; // month (0-11) int32_t year; // year (1=1 AD) uint8_t weekday; // day of week (0-6) uint16_t day; // day of year (0-365) uint8_t is_dst; // is this daylight savings? }; int64_t time; // number of seconds elapsed since midnight, January 1 1970 UTC full_time local_time; // local time full_time utc_time; // UTC coordinated time }; // ======================> running_machine typedef delegate machine_notify_delegate; // description of the currently-running machine class running_machine { DISABLE_COPYING(running_machine); friend class sound_manager; typedef std::function 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 ¶meters() { 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(root_device()); } template _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 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(); // 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 void popmessage() const { popmessage(static_cast(nullptr)); } template void popmessage(Format &&fmt, Params &&... args) const; template void logerror(Format &&fmt, Params &&... args) const; void strlog(const char *str) const; uint32_t 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 uint32_t debug_flags; // the current debug flags private: // internal helpers template struct is_null { template static bool value(U &&x) { return false; } }; template struct is_null { template 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, int32_t 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 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 m_render; // internal data from render.cpp std::unique_ptr m_input; // internal data from input.cpp std::unique_ptr m_sound; // internal data from sound.cpp std::unique_ptr m_video; // internal data from video.cpp ui_manager *m_ui; // internal data from ui.cpp std::unique_ptr m_ui_input; // internal data from uiinput.cpp std::unique_ptr m_tilemap; // internal data from tilemap.cpp std::unique_ptr m_debug_view; // internal data from debugvw.cpp std::unique_ptr m_network; // internal data from network.cpp std::unique_ptr m_bookkeeping;// internal data from bookkeeping.cpp std::unique_ptr m_configuration; // internal data from config.cpp std::unique_ptr m_output; // internal data from output.cpp std::unique_ptr m_crosshair; // internal data from crsshair.cpp std::unique_ptr m_image; // internal data from image.cpp std::unique_ptr m_rom_load; // internal data from romload.cpp std::unique_ptr 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 uint32_t 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 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> 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> 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; }; //************************************************************************** // MEMBER TEMPLATES //************************************************************************** /*------------------------------------------------- popmessage - pop up a user-visible message -------------------------------------------------*/ template 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::value(fmt)) popup_clear(); else popup_message(util::make_format_argument_pack(std::forward(fmt), std::forward(args)...)); } /*------------------------------------------------- logerror - log to the debugger and any other OSD-defined output streams -------------------------------------------------*/ template 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(fmt), std::forward(args)...); m_string_buffer.put('\0'); strlog(&m_string_buffer.vec()[0]); g_profiler.stop(); } } #endif /* __MACHINE_H__ */