From 46071c487e97cf1faa014a853b032be91fd4b1e2 Mon Sep 17 00:00:00 2001 From: AJR Date: Sun, 30 Aug 2020 23:39:18 -0400 Subject: [PATCH] device_state_interface overhaul - device_state_entry::value and device_state_entry::set_value now do everything except the register lookup, allowing them to be made public. The debugger expression engine now uses these. - device_state_entry::dvalue and device_state_entry::set_dvalue have also been made public, theoretically permitting outside code layers to inspect and modify floating-point registers. - The double specialization of device_pseudo_state_register (now renamed device_functional_state_register) has been added to the core. - state_add now has an additional specialization that takes both a reference and a write function, using the former for reads only. - state_max_length has been eliminated in favor of obtaining the relevant info through device_state_entry::max_length. - The debugger state view no longer adds "flags" as "???" if none have been registered. - set_state_string has been removed. It was never properly implemented, and it is difficult to see how it could have been done in a useful and consistent way. - state_find_entry and its typical callers state_int and set_state_int have been inlined for some hopeful efficiency gains. --- src/devices/machine/netlist.cpp | 34 +----- src/emu/debug/debugcpu.cpp | 4 +- src/emu/debug/dvstate.cpp | 6 +- src/emu/distate.cpp | 206 +++++++++++--------------------- src/emu/distate.h | 156 +++++++++++++++++++----- 5 files changed, 202 insertions(+), 204 deletions(-) diff --git a/src/devices/machine/netlist.cpp b/src/devices/machine/netlist.cpp index f4692a29547..0744b67d87d 100644 --- a/src/devices/machine/netlist.cpp +++ b/src/devices/machine/netlist.cpp @@ -1238,35 +1238,6 @@ netlist_mame_cpu_device::netlist_mame_cpu_device(const machine_config &mconfig, } -// Fixes overflow error in device_pseudo_state_register -template<> -class device_pseudo_state_register : public device_state_entry -{ -public: - typedef typename std::function getter_func; - typedef typename std::function setter_func; - - // construction/destruction - device_pseudo_state_register(int index, const char *symbol, getter_func &&getter, setter_func &&setter, device_state_interface *dev) - : device_state_entry(index, symbol, sizeof(double), ~u64(0), DSF_FLOATING_POINT, dev), - m_getter(std::move(getter)), - m_setter(std::move(setter)) - { - } - -protected: - // device_state_entry overrides - virtual u64 entry_value() const override { return u64(m_getter()); } - virtual void entry_set_value(u64 value) const override { m_setter(double(value)); } - virtual double entry_dvalue() const override { return m_getter(); } - virtual void entry_set_dvalue(double value) const override { m_setter(value); } - -private: - getter_func m_getter; // function to retrieve the data - setter_func m_setter; // function to store the data -}; - - void netlist_mame_cpu_device::device_start() { LOGDEVCALLS("device_start entry\n"); @@ -1299,12 +1270,11 @@ void netlist_mame_cpu_device::device_start() else { auto nl = downcast(n.get()); - state_add(std::make_unique>( + state_add( index++, name.c_str(), [nl]() { return nl->Q_Analog(); }, - [nl](double data) { nl->set_Q_Analog(data); }, - this)); + [nl](double data) { nl->set_Q_Analog(data); }); } } diff --git a/src/emu/debug/debugcpu.cpp b/src/emu/debug/debugcpu.cpp index afdef1362d1..6dacf7acee1 100644 --- a/src/emu/debug/debugcpu.cpp +++ b/src/emu/debug/debugcpu.cpp @@ -513,8 +513,8 @@ device_debug::device_debug(device_t &device) strmakelower(tempstr.assign(entry->symbol())); m_symtable->add( tempstr.c_str(), - std::bind(&device_state_interface::state_int, m_state, entry->index()), - entry->writeable() ? std::bind(&device_state_interface::set_state_int, m_state, entry->index(), _1) : symbol_table::setter_func(nullptr), + std::bind(&device_state_entry::value, entry.get()), + entry->writeable() ? std::bind(&device_state_entry::set_value, entry.get(), _1) : symbol_table::setter_func(nullptr), entry->format_string()); } } diff --git a/src/emu/debug/dvstate.cpp b/src/emu/debug/dvstate.cpp index 13c019be4d5..594d8fdad39 100644 --- a/src/emu/debug/dvstate.cpp +++ b/src/emu/debug/dvstate.cpp @@ -147,7 +147,9 @@ void debug_view_state::recompute() } // add a flags entry: flags:xxxxxxxx - m_state_list.emplace_back(STATE_GENFLAGS, "flags", source.m_stateintf->state_string_max_length(STATE_GENFLAGS)); + const device_state_entry *flags = source.m_stateintf->state_find_entry(STATE_GENFLAGS); + if (flags != nullptr) + m_state_list.emplace_back(STATE_GENFLAGS, "flags", flags->max_length()); // add a divider entry m_state_list.emplace_back(REG_DIVIDER, "", 0); @@ -158,7 +160,7 @@ void debug_view_state::recompute() if (entry->divider()) m_state_list.emplace_back(REG_DIVIDER, "", 0); else if (entry->visible()) - m_state_list.emplace_back(entry->index(), entry->symbol(), source.m_stateintf->state_string_max_length(entry->index())); + m_state_list.emplace_back(entry->index(), entry->symbol(), entry->max_length()); } // count the entries and determine the maximum tag and value sizes diff --git a/src/emu/distate.cpp b/src/emu/distate.cpp index 770a19292c9..ae8ba0b0e63 100644 --- a/src/emu/distate.cpp +++ b/src/emu/distate.cpp @@ -138,6 +138,36 @@ void device_state_entry::format_from_mask() } +//------------------------------------------------- +// value - return the current value as a u64 +//------------------------------------------------- + +u64 device_state_entry::value() const +{ + // call the exporter before we do anything + if ((m_flags & DSF_EXPORT) != 0) + m_device_state->state_export(*this); + + // pick up the value + return entry_value() & m_datamask; +} + + +//------------------------------------------------- +// dvalue - return the current value as a double +//------------------------------------------------- + +double device_state_entry::dvalue() const +{ + // call the exporter before we do anything + if ((m_flags & DSF_EXPORT) != 0) + m_device_state->state_export(*this); + + // pick up the value + return entry_dvalue(); +} + + //------------------------------------------------- // entry_baseptr - return a pointer to where the // data lives (if applicable) @@ -178,7 +208,7 @@ double device_state_entry::entry_dvalue() const std::string device_state_entry::format(const char *string, bool maxout) const { std::string dest; - u64 result = value(); + u64 result = entry_value() & m_datamask; // parse the format bool leadzero = false; @@ -359,6 +389,37 @@ std::string device_state_entry::format(const char *string, bool maxout) const } +//------------------------------------------------- +// to_string - return the value of the given +// piece of indexed state as a string +//------------------------------------------------- + +std::string device_state_entry::to_string() const +{ + // get the custom string if needed + std::string custom; + if ((m_flags & DSF_CUSTOM_STRING) != 0) + m_device_state->state_string_export(*this, custom); + else if ((m_flags & DSF_FLOATING_POINT) != 0) + custom = string_format("%-12G", entry_dvalue()); + + // ask the entry to format itself + return format(custom.c_str()); +} + + +//------------------------------------------------- +// max_length - return the maximum length of the +// given state as a string +//------------------------------------------------- + +int device_state_entry::max_length() const +{ + // ask the entry to format itself maximally + return format("", true).length(); +} + + //------------------------------------------------- // set_value - set the value from a u64 //------------------------------------------------- @@ -376,6 +437,10 @@ void device_state_entry::set_value(u64 value) const // store the value entry_set_value(value); + + // call the importer to finish up + if ((m_flags & DSF_IMPORT) != 0) + m_device_state->state_import(*this); } @@ -389,6 +454,10 @@ void device_state_entry::set_dvalue(double value) const // store the value entry_set_dvalue(value); + + // call the importer to finish up + if ((m_flags & DSF_IMPORT) != 0) + m_device_state->state_import(*this); } @@ -411,16 +480,6 @@ void device_state_entry::entry_set_dvalue(double value) const } -//------------------------------------------------- -// set_value - set the value from a string -//------------------------------------------------- - -void device_state_entry::set_value(const char *string) const -{ - // not implemented -} - - //************************************************************************** // DEVICE STATE INTERFACE @@ -449,110 +508,6 @@ device_state_interface::~device_state_interface() } -//------------------------------------------------- -// state_int - return the value of the given piece -// of indexed state as a u64 -//------------------------------------------------- - -u64 device_state_interface::state_int(int index) -{ - // nullptr or out-of-range entry returns 0 - const device_state_entry *entry = state_find_entry(index); - if (entry == nullptr) - return 0; - - // call the exporter before we do anything - if (entry->needs_export()) - state_export(*entry); - - // pick up the value - return entry->value(); -} - - -//------------------------------------------------- -// state_string - return the value of the given -// pieces of indexed state as a string -//------------------------------------------------- - -std::string device_state_interface::state_string(int index) const -{ - // nullptr or out-of-range entry returns bogus string - const device_state_entry *entry = state_find_entry(index); - if (entry == nullptr) - return std::string("???"); - - // get the custom string if needed - std::string custom; - if (entry->needs_custom_string()) - state_string_export(*entry, custom); - else if (entry->is_float()) - custom = string_format("%-12G", entry->dvalue()); - - // ask the entry to format itself - return entry->format(custom.c_str()); -} - - -//------------------------------------------------- -// state_string_max_length - return the maximum -// length of the given state string -//------------------------------------------------- - -int device_state_interface::state_string_max_length(int index) -{ - // nullptr or out-of-range entry returns bogus string - const device_state_entry *entry = state_find_entry(index); - if (entry == nullptr) - return 3; - - // ask the entry to format itself maximally - return entry->format("", true).length(); -} - - -//------------------------------------------------- -// set_state_int - set the value of the given -// piece of indexed state from a u64 -//------------------------------------------------- - -void device_state_interface::set_state_int(int index, u64 value) -{ - // nullptr or out-of-range entry is a no-op - const device_state_entry *entry = state_find_entry(index); - if (entry == nullptr) - return; - - // set the value - entry->set_value(value); - - // call the importer to finish up - if (entry->needs_import()) - state_import(*entry); -} - - -//------------------------------------------------- -// set_state - set the value of the given piece -// of indexed state from a string -//------------------------------------------------- - -void device_state_interface::set_state_string(int index, const char *string) -{ - // nullptr or out-of-range entry is a no-op - const device_state_entry *entry = state_find_entry(index); - if (entry == nullptr) - return; - - // set the value - entry->set_value(string); - - // call the importer to finish up - if (entry->needs_import()) - state_import(*entry); -} - - //------------------------------------------------- // state_add - add a new piece of indexed state //------------------------------------------------- @@ -626,24 +581,3 @@ void device_state_interface::interface_post_start() if (m_state_list.size() == 0) throw emu_fatalerror("No state registered for device '%s' that supports it!", device().tag()); } - - -//------------------------------------------------- -// state_find_entry - return a pointer to the -// state entry for the given index -//------------------------------------------------- - -const device_state_entry *device_state_interface::state_find_entry(int index) const -{ - // use fast lookup if possible - if (index >= FAST_STATE_MIN && index <= FAST_STATE_MAX) - return m_fast_state[index - FAST_STATE_MIN]; - - // otherwise, scan the first - for (auto &entry : m_state_list) - if (entry->m_index == index) - return entry.get(); - - // handle failure by returning nullptr - return nullptr; -} diff --git a/src/emu/distate.h b/src/emu/distate.h index 5951a0143d4..5ab34a24cf9 100644 --- a/src/emu/distate.h +++ b/src/emu/distate.h @@ -43,7 +43,6 @@ enum // class describing a single item of exposed device state class device_state_entry { - friend class device_state_interface; public: // construction/destruction device_state_entry(int index, const char *symbol, u8 size, u64 sizemask, u8 flags, device_state_interface *dev); @@ -73,6 +72,18 @@ public: device_state_interface *parent_state() const {return m_device_state;} const std::string &format_string() const { return m_format; } + // return the current value + u64 value() const; + double dvalue() const; + + // return the current value as a string + std::string to_string() const; + int max_length() const; + + // set the current value + void set_value(u64 value) const; + void set_dvalue(double value) const; + protected: // device state flags static constexpr u8 DSF_NOSHOW = 0x01; // don't display this entry in the registers view @@ -84,22 +95,6 @@ protected: static constexpr u8 DSF_READONLY = 0x40; // set if this entry does not permit writes static constexpr u8 DSF_FLOATING_POINT = 0x80; // set if this entry represents a floating-point value - // helpers - bool needs_custom_string() const { return ((m_flags & DSF_CUSTOM_STRING) != 0); } - void format_from_mask(); - - // return the current value -- only for our friends who handle export - bool needs_export() const { return ((m_flags & DSF_EXPORT) != 0); } - u64 value() const { return entry_value() & m_datamask; } - double dvalue() const { return entry_dvalue(); } - std::string format(const char *string, bool maxout = false) const; - - // set the current value -- only for our friends who handle import - bool needs_import() const { return ((m_flags & DSF_IMPORT) != 0); } - void set_value(u64 value) const; - void set_dvalue(double value) const; - void set_value(const char *string) const; - // overrides virtual void *entry_baseptr() const; virtual u64 entry_value() const; @@ -107,6 +102,11 @@ protected: virtual double entry_dvalue() const; virtual void entry_set_dvalue(double value) const; +private: + // helpers + void format_from_mask(); + std::string format(const char *string, bool maxout = false) const; + // statics static const u64 k_decimal_divisor[20]; // divisors for outputting decimal values @@ -195,18 +195,47 @@ private: }; -// ======================> device_state_register +// ======================> device_latched_functional_state_register // class template representing a state register of a specific width template -class device_pseudo_state_register : public device_state_entry +class device_latched_functional_state_register : public device_state_entry +{ +public: + typedef typename std::function setter_func; + + // construction/destruction + device_latched_functional_state_register(int index, const char *symbol, ItemType &data, setter_func &&setter, device_state_interface *dev) + : device_state_entry(index, symbol, sizeof(ItemType), std::numeric_limits::max(), 0, dev), + m_data(data), + m_setter(std::move(setter)) + { + } + +protected: + // device_state_entry overrides + virtual void *entry_baseptr() const override { return &m_data; } + virtual u64 entry_value() const override { return m_data; } + virtual void entry_set_value(u64 value) const override { m_setter(value); } + +private: + ItemType & m_data; // reference to where the data lives + setter_func m_setter; // function to store the data +}; + + +// ======================> device_functional_state_register + +// class template representing a state register of a specific width +template +class device_functional_state_register : public device_state_entry { public: typedef typename std::function getter_func; typedef typename std::function setter_func; // construction/destruction - device_pseudo_state_register(int index, const char *symbol, getter_func &&getter, setter_func &&setter, device_state_interface *dev) + device_functional_state_register(int index, const char *symbol, getter_func &&getter, setter_func &&setter, device_state_interface *dev) : device_state_entry(index, symbol, sizeof(ItemType), std::numeric_limits::max(), 0, dev), m_getter(std::move(getter)), m_setter(std::move(setter)) @@ -223,12 +252,41 @@ private: setter_func m_setter; // function to store the data }; +template<> +class device_functional_state_register : public device_state_entry +{ +public: + typedef typename std::function getter_func; + typedef typename std::function setter_func; + + // construction/destruction + device_functional_state_register(int index, const char *symbol, getter_func &&getter, setter_func &&setter, device_state_interface *dev) + : device_state_entry(index, symbol, sizeof(double), ~u64(0), DSF_FLOATING_POINT, dev), + m_getter(std::move(getter)), + m_setter(std::move(setter)) + { + } + +protected: + // device_state_entry overrides + virtual u64 entry_value() const override { return u64(m_getter()); } + virtual void entry_set_value(u64 value) const override { m_setter(double(value)); } + virtual double entry_dvalue() const override { return m_getter(); } + virtual void entry_set_dvalue(double value) const override { m_setter(value); } + +private: + getter_func m_getter; // function to retrieve the data + setter_func m_setter; // function to store the data +}; + // ======================> device_state_interface // class representing interface-specific live state class device_state_interface : public device_interface { + friend class device_state_entry; + public: // construction/destruction device_state_interface(const machine_config &mconfig, device_t &device); @@ -238,17 +296,15 @@ public: const std::vector> &state_entries() const { return m_state_list; } // state getters - u64 state_int(int index); - std::string state_string(int index) const; - int state_string_max_length(int index); + u64 state_int(int index) { const device_state_entry *entry = state_find_entry(index); return (entry == nullptr) ? 0 : entry->value(); } + std::string state_string(int index) const { const device_state_entry *entry = state_find_entry(index); return (entry == nullptr) ? std::string("???") : entry->to_string(); } offs_t pc() { return state_int(STATE_GENPC); } offs_t pcbase() { return state_int(STATE_GENPCBASE); } offs_t sp() { return state_int(STATE_GENSP); } u64 flags() { return state_int(STATE_GENFLAGS); } // state setters - void set_state_int(int index, u64 value); - void set_state_string(int index, const char *string); + void set_state_int(int index, u64 value) { const device_state_entry *entry = state_find_entry(index); if (entry != nullptr) entry->set_value(value); } void set_pc(offs_t pc) { set_state_int(STATE_GENPC, pc); } // find the entry for a given index @@ -267,19 +323,29 @@ public: // protected eventually return state_add(std::make_unique>(index, symbol, data, this)); } - // add a new state pseudo-register item (template argument must be explicit) - template device_state_entry &state_add(int index, const char *symbol, - typename device_pseudo_state_register::getter_func &&getter, - typename device_pseudo_state_register::setter_func &&setter) + // add a new state register item using functional setter + template device_state_entry &state_add(int index, const char *symbol, ItemType &data, + typename device_latched_functional_state_register::setter_func &&setter) { assert(symbol != nullptr); - return state_add(std::make_unique>(index, symbol, std::move(getter), std::move(setter), this)); + return state_add(std::make_unique>(index, symbol, data, std::move(setter), this)); } + + // add a new state register item using functional getter and setter (template argument must be explicit) template device_state_entry &state_add(int index, const char *symbol, - typename device_pseudo_state_register::getter_func &&getter) + typename device_functional_state_register::getter_func &&getter, + typename device_functional_state_register::setter_func &&setter) { assert(symbol != nullptr); - return state_add(std::make_unique>(index, symbol, std::move(getter), [](ItemType){}, this)).readonly(); + return state_add(std::make_unique>(index, symbol, std::move(getter), std::move(setter), this)); + } + + // add a new read-only state register item using functional getter (template argument must be explicit) + template device_state_entry &state_add(int index, const char *symbol, + typename device_functional_state_register::getter_func &&getter) + { + assert(symbol != nullptr); + return state_add(std::make_unique>(index, symbol, std::move(getter), [](ItemType){}, this)).readonly(); } device_state_entry &state_add(std::unique_ptr &&entry); @@ -310,4 +376,30 @@ protected: // iterator typedef device_interface_iterator state_interface_iterator; + + +//************************************************************************** +// INLINE FUNCTIONS +//************************************************************************** + +//------------------------------------------------- +// state_find_entry - return a pointer to the +// state entry for the given index +//------------------------------------------------- + +inline const device_state_entry *device_state_interface::state_find_entry(int index) const +{ + // use fast lookup if possible + if (index >= FAST_STATE_MIN && index <= FAST_STATE_MAX) + return m_fast_state[index - FAST_STATE_MIN]; + + // otherwise, scan the first + for (auto &entry : m_state_list) + if (entry->index() == index) + return entry.get(); + + // handle failure by returning nullptr + return nullptr; +} + #endif /* MAME_EMU_DISTATE_H */