// license:BSD-3-Clause // copyright-holders:Aaron Giles /*************************************************************************** devfind.h Device finding template helpers. ***************************************************************************/ #pragma once #ifndef __EMU_H__ #error Dont include this file directly; include emu.h instead. #endif #ifndef __DEVFIND_H__ #define __DEVFIND_H__ #define FINDER_DUMMY_TAG "finder_dummy_tag" //************************************************************************** // TYPE DEFINITIONS //************************************************************************** // ======================> finder_base // helper class to request auto-object discovery in the constructor of a derived class class finder_base { friend class device_t; public: // construction/destruction finder_base(device_t &base, const char *tag); virtual ~finder_base(); // getters virtual bool findit(bool isvalidation = false) = 0; // setter for setting the object void set_tag(const char *tag) { m_tag = tag; } protected: // helpers void *find_memory(UINT8 width, size_t &bytes, bool required); bool report_missing(bool found, const char *objname, bool required); // internal state finder_base *m_next; device_t &m_base; const char *m_tag; }; // ======================> object_finder_base // helper class to find objects of a particular type template class object_finder_base : public finder_base { public: // construction/destruction object_finder_base(device_t &base, const char *tag) : finder_base(base, tag), m_target(NULL) { } // operators to make use transparent operator _ObjectClass *() const { return m_target; } _ObjectClass *operator->() const { assert(m_target != NULL); return m_target; } // getter for explicit fetching _ObjectClass *target() const { return m_target; } // setter for setting the object void set_target(_ObjectClass *target) { m_target = target; } protected: // internal state _ObjectClass *m_target; }; // ======================> device_finder // device finder template template class device_finder : public object_finder_base<_DeviceClass> { public: // construction/destruction device_finder(device_t &base, const char *tag) : object_finder_base<_DeviceClass>(base, tag) { } // make reference use transparent as well operator _DeviceClass &() { assert(object_finder_base<_DeviceClass>::m_target != NULL); return *object_finder_base<_DeviceClass>::m_target; } // finder virtual bool findit(bool isvalidation = false) { device_t *device = this->m_base.subdevice(this->m_tag); this->m_target = dynamic_cast<_DeviceClass *>(device); if (device != NULL && this->m_target == NULL) { void osd_printf_warning(const char *format, ...) ATTR_PRINTF(1,2); osd_printf_warning("Device '%s' found but is of incorrect type (actual type is %s)\n", this->m_tag, device->name()); } return this->report_missing(this->m_target != NULL, "device", _Required); } }; // optional device finder template class optional_device : public device_finder<_DeviceClass, false> { public: optional_device(device_t &base, const char *tag = FINDER_DUMMY_TAG) : device_finder<_DeviceClass, false>(base, tag) { } }; // required devices are similar but throw an error if they are not found template class required_device : public device_finder<_DeviceClass, true> { public: required_device(device_t &base, const char *tag = FINDER_DUMMY_TAG) : device_finder<_DeviceClass, true>(base, tag) { } }; // ======================> memory_region_finder // device finder template template class memory_region_finder : public object_finder_base { public: // construction/destruction memory_region_finder(device_t &base, const char *tag) : object_finder_base(base, tag) { } // make reference use transparent as well operator memory_region &() { assert(object_finder_base::m_target != NULL); return *object_finder_base::m_target; } // finder virtual bool findit(bool isvalidation = false) { if (isvalidation) return true; m_target = m_base.memregion(m_tag); return this->report_missing(m_target != NULL, "memory region", _Required); } }; // optional device finder class optional_memory_region : public memory_region_finder { public: optional_memory_region(device_t &base, const char *tag = FINDER_DUMMY_TAG) : memory_region_finder(base, tag) { } }; // required devices are similar but throw an error if they are not found class required_memory_region : public memory_region_finder { public: required_memory_region(device_t &base, const char *tag = FINDER_DUMMY_TAG) : memory_region_finder(base, tag) { } }; // ======================> memory_bank_finder // device finder template template class memory_bank_finder : public object_finder_base { public: // construction/destruction memory_bank_finder(device_t &base, const char *tag) : object_finder_base(base, tag) { } // make reference use transparent as well operator memory_bank &() { assert(object_finder_base::m_target != NULL); return *object_finder_base::m_target; } // finder virtual bool findit(bool isvalidation = false) { if (isvalidation) return true; m_target = m_base.membank(m_tag); return this->report_missing(m_target != NULL, "memory bank", _Required); } }; // optional device finder class optional_memory_bank : public memory_bank_finder { public: optional_memory_bank(device_t &base, const char *tag = FINDER_DUMMY_TAG) : memory_bank_finder(base, tag) { } }; // required devices are similar but throw an error if they are not found class required_memory_bank : public memory_bank_finder { public: required_memory_bank(device_t &base, const char *tag = FINDER_DUMMY_TAG) : memory_bank_finder(base, tag) { } }; // ======================> ioport_finder // device finder template template class ioport_finder : public object_finder_base { public: // construction/destruction ioport_finder(device_t &base, const char *tag) : object_finder_base(base, tag) { } // make reference use transparent as well operator ioport_port &() { assert(object_finder_base::m_target != NULL); return *object_finder_base::m_target; } // finder virtual bool findit(bool isvalidation = false) { if (isvalidation) return true; m_target = m_base.ioport(m_tag); return this->report_missing(m_target != NULL, "I/O port", _Required); } }; // optional device finder class optional_ioport : public ioport_finder { public: optional_ioport(device_t &base, const char *tag = FINDER_DUMMY_TAG) : ioport_finder(base, tag) { } }; // required devices are similar but throw an error if they are not found class required_ioport : public ioport_finder { public: required_ioport(device_t &base, const char *tag = FINDER_DUMMY_TAG) : ioport_finder(base, tag) { } }; // ======================> ioport_array_finder // ioport array finder template template class ioport_array_finder { typedef ioport_finder<_Required> ioport_finder_type; public: // construction/destruction ioport_array_finder(device_t &base, const char *basetag) { for (int index = 0; index < _Count; index++) m_array[index].reset(global_alloc(ioport_finder_type(base, m_tag[index].format("%s.%d", basetag, index)))); } ioport_array_finder(device_t &base, const char * const *tags) { for (int index = 0; index < _Count; index++) m_array[index].reset(global_alloc(ioport_finder_type(base, tags[index]))); } // array accessors const ioport_finder_type &operator[](int index) const { assert(index < _Count); return *m_array[index]; } ioport_finder_type &operator[](int index) { assert(index < _Count); return *m_array[index]; } protected: // internal state auto_pointer m_array[_Count]; astring m_tag[_Count]; }; // optional ioport array finder template class optional_ioport_array: public ioport_array_finder<_Count, false> { public: optional_ioport_array(device_t &base, const char *basetag) : ioport_array_finder<_Count, false>(base, basetag) { } optional_ioport_array(device_t &base, const char * const *tags) : ioport_array_finder<_Count, false>(base, tags) { } }; // required ioport array finder template class required_ioport_array: public ioport_array_finder<_Count, true> { public: required_ioport_array(device_t &base, const char *basetag) : ioport_array_finder<_Count, true>(base, basetag) { } required_ioport_array(device_t &base, const char * const *tags) : ioport_array_finder<_Count, true>(base, tags) { } }; // ======================> shared_ptr_finder // shared pointer finder template template class shared_ptr_finder : public object_finder_base<_PointerType> { public: // construction/destruction shared_ptr_finder(device_t &base, const char *tag, UINT8 width = sizeof(_PointerType) * 8) : object_finder_base<_PointerType>(base, tag), m_bytes(0), m_width(width) { } // operators to make use transparent _PointerType operator[](int index) const { return this->m_target[index]; } _PointerType &operator[](int index) { return this->m_target[index]; } // getter for explicit fetching UINT32 bytes() const { return m_bytes; } UINT32 mask() const { return m_bytes - 1; } // setter for setting the object void set_target(_PointerType *target, size_t bytes) { this->m_target = target; m_bytes = bytes; } // dynamic allocation of a shared pointer void allocate(UINT32 entries) { assert(m_allocated.count() == 0); m_allocated.resize(entries); this->m_target = m_allocated; m_bytes = entries * sizeof(_PointerType); this->m_base.save_item(this->m_allocated, this->m_tag); } // finder virtual bool findit(bool isvalidation = false) { if (isvalidation) return true; this->m_target = reinterpret_cast<_PointerType *>(this->find_memory(m_width, m_bytes, _Required)); return this->report_missing(this->m_target != NULL, "shared pointer", _Required); } protected: // internal state size_t m_bytes; UINT8 m_width; dynamic_array<_PointerType> m_allocated; }; // optional shared pointer finder template class optional_shared_ptr : public shared_ptr_finder<_PointerType, false> { public: optional_shared_ptr(device_t &base, const char *tag = FINDER_DUMMY_TAG, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_finder<_PointerType, false>(base, tag, width) { } }; // required shared pointer finder template class required_shared_ptr : public shared_ptr_finder<_PointerType, true> { public: required_shared_ptr(device_t &base, const char *tag = FINDER_DUMMY_TAG, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_finder<_PointerType, true>(base, tag, width) { } }; // ======================> shared_ptr_array_finder // shared pointer array finder template template class shared_ptr_array_finder { typedef shared_ptr_finder<_PointerType, _Required> shared_ptr_type; public: // construction/destruction shared_ptr_array_finder(device_t &base, const char *basetag, UINT8 width = sizeof(_PointerType) * 8) { for (int index = 0; index < _Count; index++) m_array[index].reset(global_alloc(shared_ptr_type(base, m_tag[index].format("%s.%d", basetag, index), width))); } // array accessors const shared_ptr_type &operator[](int index) const { assert(index < _Count); return *m_array[index]; } shared_ptr_type &operator[](int index) { assert(index < _Count); return *m_array[index]; } protected: // internal state auto_pointer m_array[_Count]; astring m_tag[_Count]; }; // optional shared pointer array finder template class optional_shared_ptr_array : public shared_ptr_array_finder<_PointerType, _Count, false> { public: optional_shared_ptr_array(device_t &base, const char *tag, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_array_finder<_PointerType, _Count, false>(base, tag, width) { } }; // required shared pointer array finder template class required_shared_ptr_array : public shared_ptr_array_finder<_PointerType, _Count, true> { public: required_shared_ptr_array(device_t &base, const char *tag, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_array_finder<_PointerType, _Count, true>(base, tag, width) { } }; #endif /* __DEVFIND_H__ */