summaryrefslogblamecommitdiffstatshomepage
path: root/src/emu/distate.h
blob: dc3476d5ba70fd7ea05b827d2fe868bb42e8a5b3 (plain) (tree)
1
2
3
4
5
6
7
8

                                





                                                                            







                                                                            

                          








                                                                            



                                                                                                














                                                                            
       
                                   
                                                                                                                        
                                                                   
                                      


                                      

                                                                                                                                        



                                                                                 
                                                                                 
 

                                             

                                                         
                                                               
                                                                      
                                                                          
                                                              
                                                                      
                                                                             
                                                                     


                             





                                                                                                              
                                                                                                   
                                                                                                              






                                                                                         
                                                                
                                                        
                                                                          


                                                                           
                                        
                                            

                                                 



                                                      

                                                          
 
                  
                                                                                              

                                   
                                                                                      
                                                                                               


                                                                                        

                                                                                                                     
                                                                                                    
                                                                                          


  








                                                                                                         
                                                                                                                                                       

                                    
                                                                                                                                  











                                                                                            





















                                                                                                     























                                                                                                       












                                                                                                                                            
                                                                                                                    














                                                                                        
 






                                                      
                                                                                

                                          
                               
                                                                                                              

                        
                                 
                                                  
                                               


                                                              
                                                         

                        
                                                 
                                                             
                                                                  
 
                                                                            
                               
                                                         
 
                               
 










                                                                                                               
         

                                                                                                                                                      
         







                                                                                                                                                              
 
                                  
                                                                                                                                 
 



                                                                   
                                                                                            
                                                                                                  

                                       
                                                     

                                           
                                                                    

                    

                                                                                                   

                
                                                                                                            
                                                                                                  


                                                                                                                                                                        


                                                                                   
                                
// license:BSD-3-Clause
// copyright-holders:Aaron Giles
/***************************************************************************

    distate.h

    Device state interfaces.

***************************************************************************/

#pragma once

#ifndef __EMU_H__
#error Dont include this file directly; include emu.h instead.
#endif

#ifndef MAME_EMU_DISTATE_H
#define MAME_EMU_DISTATE_H


//**************************************************************************
//  CONSTANTS
//**************************************************************************

// standard state indexes
enum
{
	STATE_GENPC = -1,               // generic program counter (live)
	STATE_GENPCBASE = -2,           // generic program counter (base of current instruction)
	STATE_GENSP = -3,               // generic stack pointer
	STATE_GENFLAGS = -4             // generic flags
};



//**************************************************************************
//  TYPE DEFINITIONS
//**************************************************************************


// ======================> device_state_entry

// 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);
	device_state_entry(int index, device_state_interface *dev);
	virtual ~device_state_entry();

public:
	// post-construction modifiers
	device_state_entry &mask(u64 _mask) { m_datamask = _mask; format_from_mask(); return *this; }
	device_state_entry &signed_mask(u64 _mask) { m_datamask = _mask; m_flags |= DSF_IMPORT_SEXT; format_from_mask(); return *this; }
	device_state_entry &formatstr(const char *_format);
	device_state_entry &callimport() { m_flags |= DSF_IMPORT; return *this; }
	device_state_entry &callexport() { m_flags |= DSF_EXPORT; return *this; }
	device_state_entry &noshow() { m_flags |= DSF_NOSHOW; return *this; }
	device_state_entry &readonly() { m_flags |= DSF_READONLY; return *this; }

	// query information
	int index() const { return m_index; }
	void *dataptr() const { return entry_baseptr(); }
	u64 datamask() const { return m_datamask; }
	const char *symbol() const { return m_symbol.c_str(); }
	bool visible() const { return ((m_flags & DSF_NOSHOW) == 0); }
	bool writeable() const { return ((m_flags & DSF_READONLY) == 0); }
	bool divider() const { return m_flags & DSF_DIVIDER; }
	bool is_float() const { return m_flags & DSF_FLOATING_POINT; }
	device_state_interface *parent_state() const {return m_device_state;}
	const std::string &format_string() const { return m_format; }

protected:
	// device state flags
	static constexpr u8 DSF_NOSHOW          = 0x01; // don't display this entry in the registers view
	static constexpr u8 DSF_IMPORT          = 0x02; // call the import function after writing new data
	static constexpr u8 DSF_IMPORT_SEXT     = 0x04; // sign-extend the data when writing new data
	static constexpr u8 DSF_EXPORT          = 0x08; // call the export function prior to fetching the data
	static constexpr u8 DSF_CUSTOM_STRING   = 0x10; // set if the format has a custom string
	static constexpr u8 DSF_DIVIDER         = 0x20; // set if this is a divider entry
	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;
	virtual void entry_set_value(u64 value) const;
	virtual double entry_dvalue() const;
	virtual void entry_set_dvalue(double value) const;

	// statics
	static const u64 k_decimal_divisor[20];      // divisors for outputting decimal values

	// public state description
	device_state_interface *m_device_state;         // link to parent device state
	u32                     m_index;                // index by which this item is referred
	u64                     m_datamask;             // mask that applies to the data
	u8                      m_datasize;             // size of the data
	u8                      m_flags;                // flags for this data
	std::string             m_symbol;               // symbol for display; all lower-case version for expressions
	std::string             m_format;               // supported formats
	bool                    m_default_format;       // true if we are still using default format
	u64                     m_sizemask;             // mask derived from the data size
};


// ======================> device_state_register

// class template representing a state register of a specific width
template<class ItemType>
class device_state_register : public device_state_entry
{
public:
	// construction/destruction
	device_state_register(int index, const char *symbol, ItemType &data, device_state_interface *dev)
		: device_state_entry(index, symbol, sizeof(ItemType), std::numeric_limits<typename std::make_unsigned<ItemType>::type>::max(), 0, dev),
			m_data(data)
	{
		static_assert(std::is_integral<ItemType>().value, "Registration of non-integer types is not currently supported");
	}

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_data = value; }

private:
	ItemType &              m_data;                 // reference to where the data lives
};

// class template representing a boolean state register
template<>
class device_state_register<bool> : public device_state_entry
{
public:
	// construction/destruction
	device_state_register(int index, const char *symbol, bool &data, device_state_interface *dev)
		: device_state_entry(index, symbol, sizeof(bool), 1, 0, dev),
			m_data(data)
	{
	}

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_data = bool(value); }

private:
	bool &                  m_data;                 // reference to where the data lives
};

// class template representing a floating-point state register
template<>
class device_state_register<double> : public device_state_entry
{
public:
	// construction/destruction
	device_state_register(int index, const char *symbol, double &data, device_state_interface *dev)
		: device_state_entry(index, symbol, sizeof(double), ~u64(0), DSF_FLOATING_POINT, dev),
			m_data(data)
	{
	}

protected:
	// device_state_entry overrides
	virtual void *entry_baseptr() const override { return &m_data; }
	virtual u64 entry_value() const override { return u64(m_data); }
	virtual void entry_set_value(u64 value) const override { m_data = double(value); }
	virtual double entry_dvalue() const override { return m_data; }
	virtual void entry_set_dvalue(double value) const override { m_data = value; }

private:
	double &                m_data;                 // reference to where the data lives
};


// ======================> device_state_register

// class template representing a state register of a specific width
template<class ItemType>
class device_pseudo_state_register : public device_state_entry
{
public:
	typedef typename std::function<ItemType ()> getter_func;
	typedef typename std::function<void (ItemType)> 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(ItemType), std::numeric_limits<ItemType>::max(), 0, dev),
			m_getter(std::move(getter)),
			m_setter(std::move(setter))
	{
	}

protected:
	// device_state_entry overrides
	virtual u64 entry_value() const override { return m_getter(); }
	virtual void entry_set_value(u64 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
{
public:
	// construction/destruction
	device_state_interface(const machine_config &mconfig, device_t &device);
	virtual ~device_state_interface();

	// configuration access
	const std::vector<std::unique_ptr<device_state_entry>> &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);
	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_pc(offs_t pc) { set_state_int(STATE_GENPC, pc); }

	// deliberately ambiguous functions; if you have the state interface
	// just use it directly
	device_state_interface &state() { return *this; }

public: // protected eventually

	// add a new state register item
	template<class ItemType> device_state_entry &state_add(int index, const char *symbol, ItemType &data)
	{
		assert(symbol != nullptr);
		return state_add(std::make_unique<device_state_register<ItemType>>(index, symbol, data, this));
	}

	// add a new state pseudo-register item (template argument must be explicit)
	template<class ItemType> device_state_entry &state_add(int index, const char *symbol,
					typename device_pseudo_state_register<ItemType>::getter_func &&getter,
					typename device_pseudo_state_register<ItemType>::setter_func &&setter)
	{
		assert(symbol != nullptr);
		return state_add(std::make_unique<device_pseudo_state_register<ItemType>>(index, symbol, std::move(getter), std::move(setter), this));
	}
	template<class ItemType> device_state_entry &state_add(int index, const char *symbol,
					typename device_pseudo_state_register<ItemType>::getter_func &&getter)
	{
		assert(symbol != nullptr);
		return state_add(std::make_unique<device_pseudo_state_register<ItemType>>(index, symbol, std::move(getter), [](ItemType){}, this)).readonly();
	}

	device_state_entry &state_add(std::unique_ptr<device_state_entry> &&entry);

	// add a new divider entry
	device_state_entry &state_add_divider(int index) { return state_add(std::make_unique<device_state_entry>(index, this)); }

protected:
	// derived class overrides
	virtual void state_import(const device_state_entry &entry);
	virtual void state_export(const device_state_entry &entry);
	virtual void state_string_import(const device_state_entry &entry, std::string &str);
	virtual void state_string_export(const device_state_entry &entry, std::string &str) const;

	// internal operation overrides
	virtual void interface_post_start() override;

	// find the entry for a given index
	const device_state_entry *state_find_entry(int index) const;

	// constants
	static constexpr int FAST_STATE_MIN = -4;                           // range for fast state
	static constexpr int FAST_STATE_MAX = 256;                          // lookups

	// state
	std::vector<std::unique_ptr<device_state_entry>>       m_state_list;           // head of state list
	device_state_entry *                    m_fast_state[FAST_STATE_MAX + 1 - FAST_STATE_MIN];
																	// fast access to common entries
};

// iterator
typedef device_interface_iterator<device_state_interface> state_interface_iterator;

#endif  /* MAME_EMU_DISTATE_H */