From 9b582574922cb7af1a9a31c1182c300b90a20c43 Mon Sep 17 00:00:00 2001 From: Vas Crabb Date: Mon, 14 Sep 2020 00:55:00 +1000 Subject: [PATCH] emu/save.h: Added support for saving arrays of attotimes and renamed macros to make purpose more obvious. --- src/emu/devfind.h | 11 +-- src/emu/save.h | 177 ++++++++++++++++++++++++---------------------- 2 files changed, 99 insertions(+), 89 deletions(-) diff --git a/src/emu/devfind.h b/src/emu/devfind.h index 668defe4523..958ae16c3bc 100644 --- a/src/emu/devfind.h +++ b/src/emu/devfind.h @@ -15,6 +15,7 @@ #include #include +#include #include #include #include @@ -1063,11 +1064,11 @@ public: // dynamic allocation of a shared pointer void allocate(u32 entries) { - assert(m_allocated.empty()); - m_allocated.resize(entries); - this->m_target = &m_allocated[0]; + assert(!m_allocated); + m_allocated = std::make_unique(entries); + this->m_target = m_allocated.get(); m_bytes = entries * sizeof(PointerType); - this->m_base.get().save_item(m_allocated, this->m_tag); + this->m_base.get().save_pointer(m_allocated, this->m_tag, entries); } private: @@ -1086,7 +1087,7 @@ private: // internal state u8 const m_width; size_t m_bytes; - std::vector m_allocated; + std::unique_ptr m_allocated; }; template using optional_shared_ptr = shared_ptr_finder; diff --git a/src/emu/save.h b/src/emu/save.h index f015534f02c..c892cd0b2ba 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -55,12 +55,12 @@ typedef named_delegate save_prepost_delegate; // saved; in general, this is intended only to be used for specific enum types // defined by your device #define ALLOW_SAVE_TYPE(TYPE) \ - template <> struct save_manager::type_checker { static constexpr bool is_atom = true; static constexpr bool is_pointer = false; } + template <> struct save_manager::is_atom { static constexpr bool value = true; }; // use this as above, but also to declare that std::vector is safe as well -#define ALLOW_SAVE_TYPE_AND_ARRAY(TYPE) \ - ALLOW_SAVE_TYPE(TYPE); \ - template <> inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, std::vector &value, const char *name) { save_memory(device, module, tag, index, name, &value[0], sizeof(TYPE), value.size()); } +#define ALLOW_SAVE_TYPE_AND_VECTOR(TYPE) \ + ALLOW_SAVE_TYPE(TYPE) \ + template <> struct save_manager::is_vector_safe { static constexpr bool value = true; }; // use this for saving members of structures in arrays #define STRUCT_MEMBER(s, m) s, &save_manager::pointer_unwrap::underlying_type::m, #s "." #m @@ -98,9 +98,9 @@ class save_manager static underlying_type *ptr(std::array &value) { return array_unwrap::ptr(value[0]); } }; - // type_checker is a set of templates to identify valid save types - template struct type_checker { static constexpr bool is_atom = false; static constexpr bool is_pointer = false; }; - template struct type_checker { static constexpr bool is_atom = false; static constexpr bool is_pointer = true; }; + // set of templates to identify valid save types + template struct is_atom { static constexpr bool value = false; }; + template struct is_vector_safe { static constexpr bool value = false; }; class state_entry { @@ -160,10 +160,9 @@ public: // templatized wrapper for general objects and arrays template - void save_item(device_t *device, const char *module, const char *tag, int index, ItemType &value, const char *valname) + std::enable_if_t::underlying_type>::value> save_item(device_t *device, const char *module, const char *tag, int index, ItemType &value, const char *valname) { - static_assert(!type_checker::is_pointer, "Called save_item on a pointer with no count!"); - static_assert(type_checker::underlying_type>::is_atom, "Called save_item on a non-fundamental type!"); + static_assert(!std::is_pointer::value, "Called save_item on a pointer with no count!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(value), array_unwrap::SIZE, array_unwrap::SAVE_COUNT); } @@ -173,16 +172,15 @@ public: { static_assert(std::is_base_of::underlying_type>::value, "Called save_item on a non-matching struct member pointer!"); static_assert(!(sizeof(typename array_unwrap::underlying_type) % sizeof(typename array_unwrap::underlying_type)), "Called save_item on an unaligned struct member!"); - static_assert(!type_checker::is_pointer, "Called save_item on a struct member pointer!"); - static_assert(type_checker::underlying_type>::is_atom, "Called save_item on a non-fundamental type!"); + static_assert(!std::is_pointer::value, "Called save_item on a struct member pointer!"); + static_assert(is_atom::underlying_type>::value, "Called save_item on a non-fundamental type!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(array_unwrap::ptr(value)->*element), array_unwrap::SIZE, array_unwrap::SAVE_COUNT, array_unwrap::SAVE_COUNT, sizeof(typename array_unwrap::underlying_type) / sizeof(typename array_unwrap::underlying_type)); } // templatized wrapper for pointers template - void save_pointer(device_t *device, const char *module, const char *tag, int index, ItemType *value, const char *valname, u32 count) + std::enable_if_t::underlying_type>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, ItemType *value, const char *valname, u32 count) { - static_assert(type_checker::underlying_type>::is_atom, "Called save_pointer on a non-fundamental type!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(value[0]), array_unwrap::SIZE, array_unwrap::SAVE_COUNT * count); } @@ -191,8 +189,8 @@ public: { static_assert(std::is_base_of::underlying_type>::value, "Called save_pointer on a non-matching struct member pointer!"); static_assert(!(sizeof(typename array_unwrap::underlying_type) % sizeof(typename array_unwrap::underlying_type)), "Called save_pointer on an unaligned struct member!"); - static_assert(!type_checker::is_pointer, "Called save_pointer on a struct member pointer!"); - static_assert(type_checker::underlying_type>::is_atom, "Called save_pointer on a non-fundamental type!"); + static_assert(!std::is_pointer::value, "Called save_pointer on a struct member pointer!"); + static_assert(is_atom::underlying_type>::value, "Called save_pointer on a non-fundamental type!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(array_unwrap::ptr(value[0])->*element), array_unwrap::SIZE, array_unwrap::SAVE_COUNT, array_unwrap::SAVE_COUNT * count, sizeof(typename array_unwrap::underlying_type) / sizeof(typename array_unwrap::underlying_type)); } @@ -200,20 +198,79 @@ public: template void save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr &value, const char *valname, u32 count) { - static_assert(type_checker::underlying_type>::is_atom, "Called save_pointer on a non-fundamental type!"); + static_assert(is_atom::underlying_type>::value, "Called save_pointer on a non-fundamental type!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(value[0]), array_unwrap::SIZE, array_unwrap::SAVE_COUNT * count); } template - void save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr &value, ElementType StructType::*element, const char *valname, u32 count) + std::enable_if_t::underlying_type>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr &value, ElementType StructType::*element, const char *valname, u32 count) { static_assert(std::is_base_of::underlying_type>::value, "Called save_pointer on a non-matching struct member pointer!"); static_assert(!(sizeof(typename array_unwrap::underlying_type) % sizeof(typename array_unwrap::underlying_type)), "Called save_pointer on an unaligned struct member!"); - static_assert(!type_checker::is_pointer, "Called save_pointer on a struct member pointer!"); - static_assert(type_checker::underlying_type>::is_atom, "Called save_pointer on a non-fundamental type!"); + static_assert(!std::is_pointer::value, "Called save_pointer on a struct member pointer!"); + static_assert(is_atom::underlying_type>::value, "Called save_pointer on a non-fundamental type!"); save_memory(device, module, tag, index, valname, array_unwrap::ptr(array_unwrap::ptr(value[0])->*element), array_unwrap::SIZE, array_unwrap::SAVE_COUNT, array_unwrap::SAVE_COUNT * count, sizeof(typename array_unwrap::underlying_type) / sizeof(typename array_unwrap::underlying_type)); } + // templatized wrapper for std::vector + template + std::enable_if_t::underlying_type>::value> save_item(device_t *device, const char *module, const char *tag, int index, std::vector &value, const char *valname) + { + save_pointer(device, module, tag, index, &value[0], valname, value.size()); + } + + // specializations for bitmaps + void save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind8 &value, const char *valname) + { + save_memory(device, module, tag, index, valname, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); + } + + void save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind16 &value, const char *valname) + { + save_memory(device, module, tag, index, valname, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); + } + + void save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind32 &value, const char *valname) + { + save_memory(device, module, tag, index, valname, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); + } + + void save_item(device_t *device, const char *module, const char *tag, int index, bitmap_rgb32 &value, const char *valname) + { + save_memory(device, module, tag, index, valname, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); + } + + // specializations for attotimes + template + std::enable_if_t::underlying_type, attotime>::value> save_item(device_t *device, const char *module, const char *tag, int index, ItemType &value, const char *valname) + { + std::string tempstr; + tempstr.assign(valname).append(".attoseconds"); + save_item(device, module, tag, index, value, &attotime::m_attoseconds, tempstr.c_str()); + tempstr.assign(valname).append(".seconds"); + save_item(device, module, tag, index, value, &attotime::m_seconds, tempstr.c_str()); + } + + template + std::enable_if_t::underlying_type, attotime>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, ItemType *value, const char *valname, u32 count) + { + std::string tempstr; + tempstr.assign(valname).append(".attoseconds"); + save_item(device, module, tag, index, value, &attotime::m_attoseconds, tempstr.c_str(), count); + tempstr.assign(valname).append(".seconds"); + save_item(device, module, tag, index, value, &attotime::m_seconds, tempstr.c_str(), count); + } + + template + std::enable_if_t::underlying_type, attotime>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr &value, const char *valname, u32 count) + { + std::string tempstr; + tempstr.assign(valname).append(".attoseconds"); + save_item(device, module, tag, index, value, &attotime::m_attoseconds, tempstr.c_str(), count); + tempstr.assign(valname).append(".seconds"); + save_item(device, module, tag, index, value, &attotime::m_seconds, tempstr.c_str(), count); + } + // global memory registration template void save_item(ItemType &value, const char *valname, int index = 0) @@ -325,70 +382,22 @@ public: // template specializations to enumerate the fundamental atomic types you are allowed to save -ALLOW_SAVE_TYPE_AND_ARRAY(char) -ALLOW_SAVE_TYPE (bool); // std::vector may be packed internally -ALLOW_SAVE_TYPE_AND_ARRAY(osd::s8) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::u8) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::s16) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::u16) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::s32) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::u32) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::s64) -ALLOW_SAVE_TYPE_AND_ARRAY(osd::u64) -ALLOW_SAVE_TYPE_AND_ARRAY(PAIR) -ALLOW_SAVE_TYPE_AND_ARRAY(PAIR64) -ALLOW_SAVE_TYPE_AND_ARRAY(float) -ALLOW_SAVE_TYPE_AND_ARRAY(double) -ALLOW_SAVE_TYPE_AND_ARRAY(endianness_t) -ALLOW_SAVE_TYPE_AND_ARRAY(rgb_t) - - - -//************************************************************************** -// INLINE FUNCTIONS -//************************************************************************** - -//------------------------------------------------- -// save_item - specialized save_item for bitmaps -//------------------------------------------------- - -template <> -inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind8 &value, const char *name) -{ - save_memory(device, module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); -} - -template <> -inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind16 &value, const char *name) -{ - save_memory(device, module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); -} - -template <> -inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, bitmap_ind32 &value, const char *name) -{ - save_memory(device, module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); -} - -template <> -inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, bitmap_rgb32 &value, const char *name) -{ - save_memory(device, module, tag, index, name, &value.pix(0), value.bpp() / 8, value.rowpixels() * value.height()); -} - - -//------------------------------------------------- -// save_item - specialized save_item for attotimes -//------------------------------------------------- - -template <> -inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, attotime &value, const char *name) -{ - std::string tempstr = std::string(name).append(".attoseconds"); - save_memory(device, module, tag, index, tempstr.c_str(), &value.m_attoseconds, sizeof(value.m_attoseconds)); - tempstr.assign(name).append(".seconds"); - save_memory(device, module, tag, index, tempstr.c_str(), &value.m_seconds, sizeof(value.m_seconds)); -} +ALLOW_SAVE_TYPE_AND_VECTOR(char) +ALLOW_SAVE_TYPE (bool) // std::vector may be packed internally +ALLOW_SAVE_TYPE_AND_VECTOR(osd::s8) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::u8) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::s16) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::u16) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::s32) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::u32) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::s64) +ALLOW_SAVE_TYPE_AND_VECTOR(osd::u64) +ALLOW_SAVE_TYPE_AND_VECTOR(PAIR) +ALLOW_SAVE_TYPE_AND_VECTOR(PAIR64) +ALLOW_SAVE_TYPE_AND_VECTOR(float) +ALLOW_SAVE_TYPE_AND_VECTOR(double) +ALLOW_SAVE_TYPE_AND_VECTOR(endianness_t) +ALLOW_SAVE_TYPE_AND_VECTOR(rgb_t) #endif // MAME_EMU_SAVE_H