summaryrefslogtreecommitdiffstatshomepage
path: root/src/emu/devfind.h
diff options
context:
space:
mode:
Diffstat (limited to 'src/emu/devfind.h')
-rw-r--r--src/emu/devfind.h385
1 files changed, 385 insertions, 0 deletions
diff --git a/src/emu/devfind.h b/src/emu/devfind.h
new file mode 100644
index 00000000000..006373fcff8
--- /dev/null
+++ b/src/emu/devfind.h
@@ -0,0 +1,385 @@
+/***************************************************************************
+
+ devfind.h
+
+ Device finding template helpers.
+
+****************************************************************************
+
+ Copyright Aaron Giles
+ All rights reserved.
+
+ Redistribution and use in source and binary forms, with or without
+ modification, are permitted provided that the following conditions are
+ met:
+
+ * Redistributions of source code must retain the above copyright
+ notice, this list of conditions and the following disclaimer.
+ * Redistributions in binary form must reproduce the above copyright
+ notice, this list of conditions and the following disclaimer in
+ the documentation and/or other materials provided with the
+ distribution.
+ * Neither the name 'MAME' nor the names of its contributors may be
+ used to endorse or promote products derived from this software
+ without specific prior written permission.
+
+ THIS SOFTWARE IS PROVIDED BY AARON GILES ''AS IS'' AND ANY EXPRESS OR
+ IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE IMPLIED
+ WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE ARE
+ DISCLAIMED. IN NO EVENT SHALL AARON GILES BE LIABLE FOR ANY DIRECT,
+ INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL DAMAGES
+ (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS OR
+ SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
+ HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT,
+ STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING
+ IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE
+ POSSIBILITY OF SUCH DAMAGE.
+
+***************************************************************************/
+
+#pragma once
+
+#ifndef __EMU_H__
+#error Dont include this file directly; include emu.h instead.
+#endif
+
+#ifndef __DEVFIND_H__
+#define __DEVFIND_H__
+
+
+//**************************************************************************
+// 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;
+
+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 _ObjectClass>
+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 _DeviceClass, bool _Required>
+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 mame_printf_warning(const char *format, ...) ATTR_PRINTF(1,2);
+ mame_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 _DeviceClass>
+class optional_device : public device_finder<_DeviceClass, false>
+{
+public:
+ optional_device(device_t &base, const char *tag) : device_finder<_DeviceClass, false>(base, tag) { }
+};
+
+// required devices are similar but throw an error if they are not found
+template<class _DeviceClass>
+class required_device : public device_finder<_DeviceClass, true>
+{
+public:
+ required_device(device_t &base, const char *tag) : device_finder<_DeviceClass, true>(base, tag) { }
+};
+
+
+// ======================> memory_region_finder
+
+// device finder template
+template<bool _Required>
+class memory_region_finder : public object_finder_base<memory_region>
+{
+public:
+ // construction/destruction
+ memory_region_finder(device_t &base, const char *tag)
+ : object_finder_base<memory_region>(base, tag) { }
+
+ // make reference use transparent as well
+ operator memory_region &() { assert(object_finder_base<memory_region>::m_target != NULL); return *object_finder_base<memory_region>::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<false>
+{
+public:
+ optional_memory_region(device_t &base, const char *tag) : memory_region_finder<false>(base, tag) { }
+};
+
+// required devices are similar but throw an error if they are not found
+class required_memory_region : public memory_region_finder<true>
+{
+public:
+ required_memory_region(device_t &base, const char *tag) : memory_region_finder<true>(base, tag) { }
+};
+
+
+// ======================> memory_bank_finder
+
+// device finder template
+template<bool _Required>
+class memory_bank_finder : public object_finder_base<memory_bank>
+{
+public:
+ // construction/destruction
+ memory_bank_finder(device_t &base, const char *tag)
+ : object_finder_base<memory_bank>(base, tag) { }
+
+ // make reference use transparent as well
+ operator memory_bank &() { assert(object_finder_base<memory_bank>::m_target != NULL); return *object_finder_base<memory_bank>::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<false>
+{
+public:
+ optional_memory_bank(device_t &base, const char *tag) : memory_bank_finder<false>(base, tag) { }
+};
+
+// required devices are similar but throw an error if they are not found
+class required_memory_bank : public memory_bank_finder<true>
+{
+public:
+ required_memory_bank(device_t &base, const char *tag) : memory_bank_finder<true>(base, tag) { }
+};
+
+
+// ======================> ioport_finder
+
+// device finder template
+template<bool _Required>
+class ioport_finder : public object_finder_base<ioport_port>
+{
+public:
+ // construction/destruction
+ ioport_finder(device_t &base, const char *tag)
+ : object_finder_base<ioport_port>(base, tag) { }
+
+ // make reference use transparent as well
+ operator ioport_port &() { assert(object_finder_base<ioport_port>::m_target != NULL); return *object_finder_base<ioport_port>::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<false>
+{
+public:
+ optional_ioport(device_t &base, const char *tag) : ioport_finder<false>(base, tag) { }
+};
+
+// required devices are similar but throw an error if they are not found
+class required_ioport : public ioport_finder<true>
+{
+public:
+ required_ioport(device_t &base, const char *tag) : ioport_finder<true>(base, tag) { }
+};
+
+
+// ======================> shared_ptr_finder
+
+// shared pointer finder template
+template<typename _PointerType, bool _Required>
+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_allocated(false),
+ m_width(width) { }
+
+ virtual ~shared_ptr_finder() { if (m_allocated) global_free(this->m_target); }
+
+ // 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; }
+
+ // 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);
+ m_allocated = true;
+ this->m_target = global_alloc_array_clear(_PointerType, entries);
+ m_bytes = entries * sizeof(_PointerType);
+ this->m_base.save_pointer(this->m_target, this->m_tag, entries);
+ }
+
+ // 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;
+ bool m_allocated;
+ UINT8 m_width;
+};
+
+// optional shared pointer finder
+template<class _PointerType>
+class optional_shared_ptr : public shared_ptr_finder<_PointerType, false>
+{
+public:
+ optional_shared_ptr(device_t &base, const char *tag, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_finder<_PointerType, false>(base, tag, width) { }
+};
+
+// required shared pointer finder
+template<class _PointerType>
+class required_shared_ptr : public shared_ptr_finder<_PointerType, true>
+{
+public:
+ required_shared_ptr(device_t &base, const char *tag, UINT8 width = sizeof(_PointerType) * 8) : shared_ptr_finder<_PointerType, true>(base, tag, width) { }
+};
+
+
+// ======================> shared_ptr_array_finder
+
+// shared pointer array finder template
+template<typename _PointerType, int _Count, bool _Required>
+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] = global_alloc(shared_ptr_type(base, m_tag[index].format("%s.%d", basetag, index), width));
+ }
+
+ virtual ~shared_ptr_array_finder()
+ {
+ for (int index = 0; index < _Count; index++)
+ global_free(m_array[index]);
+ }
+
+ // 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
+ shared_ptr_type *m_array[_Count+1];
+ astring m_tag[_Count+1];
+};
+
+// optional shared pointer array finder
+template<class _PointerType, int _Count>
+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 _PointerType, int _Count>
+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__ */