diff options
author | Aaron Giles <aaron@aarongiles.com> | 2021-04-19 14:11:39 -0700 |
---|---|---|
committer | Aaron Giles <aaron@aarongiles.com> | 2021-04-19 14:11:39 -0700 |
commit | 34b805da310630e2d33b13a82ccd2a776671d05b (patch) | |
tree | 51b1cdf13382d493a719219a1889feb260477076 | |
parent | 9394ff0593f142ad1ebf439052c3b57e19edd0fd (diff) |
Differentiated raw arrays from vector arrays. Add warnings for raw arrays that are not in containers.
-rw-r--r-- | src/emu/debug/dvsave.cpp | 8 | ||||
-rw-r--r-- | src/emu/save.cpp | 101 | ||||
-rw-r--r-- | src/emu/save.h | 61 |
3 files changed, 123 insertions, 47 deletions
diff --git a/src/emu/debug/dvsave.cpp b/src/emu/debug/dvsave.cpp index efea78a58c4..eda3fb59235 100644 --- a/src/emu/debug/dvsave.cpp +++ b/src/emu/debug/dvsave.cpp @@ -86,7 +86,8 @@ void debug_view_save::build_list_recursive(save_registered_item &item, uintptr_t // arrays are multiples of a single item case save_registered_item::TYPE_STATIC_ARRAY: - case save_registered_item::TYPE_RUNTIME_ARRAY: + case save_registered_item::TYPE_VECTOR_ARRAY: + case save_registered_item::TYPE_RAW_ARRAY: { m_save_list.push_back(save_item(item, objbase, depth, count)); auto subitem = item.subitems().begin(); @@ -123,7 +124,7 @@ void debug_view_save::recompute() reset(); // build the list of items - build_list_recursive(machine().save().root_registrar().parent_item(), 0, 0); + build_list_recursive(machine().save().root_registrar().item(), 0, 0); m_save_list[0].set_collapse(false); for (auto &item : m_save_list) item.update_value(); @@ -386,7 +387,8 @@ std::string debug_view_save::save_item::value(save_registered_item &item, int co // arrays are multiples of a single item case save_registered_item::TYPE_STATIC_ARRAY: - case save_registered_item::TYPE_RUNTIME_ARRAY: + case save_registered_item::TYPE_VECTOR_ARRAY: + case save_registered_item::TYPE_RAW_ARRAY: { if (!collapsed) catprintf(tempbuf, pos, "[%d]", item.count()); diff --git a/src/emu/save.cpp b/src/emu/save.cpp index 26669466746..370fc56c196 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -1367,7 +1367,8 @@ bool save_registered_item::is_replicatable(bool parent_is_array) const // unique pointers, vectors, and runtime arrays are non-replicatable case TYPE_UNIQUE: case TYPE_VECTOR: - case TYPE_RUNTIME_ARRAY: + case TYPE_VECTOR_ARRAY: + case TYPE_RAW_ARRAY: return false; // structs, containers, and static arrays are replicatable if all their owned items are @@ -1490,7 +1491,8 @@ u64 save_registered_item::save_binary(u8 *ptr, u64 length, uintptr_t objbase) co // arrays are multiples of a single item case TYPE_STATIC_ARRAY: - case TYPE_RUNTIME_ARRAY: + case TYPE_VECTOR_ARRAY: + case TYPE_RAW_ARRAY: { auto item = m_items.begin(); auto last = std::prev(m_items.end()); @@ -1547,7 +1549,8 @@ u64 save_registered_item::restore_binary(u8 const *ptr, u64 length, uintptr_t ob // arrays are multiples of a single item case TYPE_STATIC_ARRAY: - case TYPE_RUNTIME_ARRAY: + case TYPE_VECTOR_ARRAY: + case TYPE_RAW_ARRAY: { auto item = m_items.begin(); auto last = std::prev(m_items.end()); @@ -1642,7 +1645,8 @@ void save_registered_item::save_json(save_zip_state &zipstate, char const *namep // arrays are multiples of a single item case TYPE_STATIC_ARRAY: - case TYPE_RUNTIME_ARRAY: + case TYPE_VECTOR_ARRAY: + case TYPE_RAW_ARRAY: { // look for large arrays of ints/floats u32 total, unitsize; @@ -1841,7 +1845,8 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep // arrays are multiples of a single item case TYPE_STATIC_ARRAY: - case TYPE_RUNTIME_ARRAY: + case TYPE_VECTOR_ARRAY: + case TYPE_RAW_ARRAY: { auto item = m_items.begin(); auto last = std::prev(m_items.end()); @@ -2117,6 +2122,92 @@ bool save_registered_item::is_endpoint_array(u32 &total, u32 &unitsize) const //************************************************************************** +// SAVE REGISTRAR +//************************************************************************** + +//------------------------------------------------- +// save_registrar - minimal internal constructor +//------------------------------------------------- + +save_registrar::save_registrar(save_registered_item &item, void *baseptr) : + m_item(item), + m_regcontainerbase(uintptr_t(baseptr)), + m_regcontainersize(0) +{ +} + + +//------------------------------------------------- +// save_registrar - extended internal constructor +//------------------------------------------------- + +save_registrar::save_registrar(save_registrar &parent, void *baseptr, save_registered_item::save_type type, u32 size, char const *name, u32 count, void *regcontainerbase, u32 regcontainersize) : + m_item(parent.item().append(parent.ptr_to_offset(baseptr, size, type), type, size, name, count)), + m_regcontainerbase(uintptr_t(regcontainerbase)), + m_regcontainersize(regcontainersize) +{ +} + + +//------------------------------------------------- +// reg - append all items from the source +// registrar into a new container; note that the +// items are stolen, not copied +//------------------------------------------------- + +save_registrar &save_registrar::reg(save_registrar &src, char const *name) +{ + save_registrar container(*this, name); + auto &srcitems = src.item().subitems(); + auto &dstitems = container.item().subitems(); + dstitems.splice(dstitems.end(), srcitems); + return *this; +} + + +//------------------------------------------------- +// ptr_to_offset - given a pointer and size, +// make sure the item fits within its container, +// applying rules based on the container's type +// and the new item's type +//------------------------------------------------- + +uintptr_t save_registrar::ptr_to_offset(void *ptr, u32 size, save_registered_item::save_type type) +{ + save_registered_item::save_type parent_type = m_item.type(); + + // anything you add to a container is at an absolute offset, so just return + // the unadjusted value + if (parent_type == save_registered_item::TYPE_CONTAINER) + return uintptr_t(ptr); + + // if you are adding a container, the base pointer doesn't matter, so treat it as 0; + // if you are adding a unique or vector, the pointer for owned objects comes from the + // object itself, so also treat those as 0 + else if (type == save_registered_item::TYPE_CONTAINER || + parent_type == save_registered_item::TYPE_UNIQUE || + parent_type == save_registered_item::TYPE_VECTOR) + return 0; + + // compute the offset relative to the container base + uintptr_t offset = uintptr_t(ptr) - m_regcontainerbase; + + // raw arrays get a pass (though they should be rare) + if (type == save_registered_item::TYPE_RAW_ARRAY) + { + osd_printf_warning("Raw array registered for saving; should be moved to a container\n"); + return offset; + } + + // everyone else gets a full check + if (m_regcontainersize != 0 && offset + size > m_regcontainersize) + throw emu_fatalerror("Attempted to register item outside of parent element's bounds"); + return offset; +} + + + +//************************************************************************** // SAVE MANAGER //************************************************************************** diff --git a/src/emu/save.h b/src/emu/save.h index e826b38dddb..bfe4ce88ec5 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -108,11 +108,12 @@ public: TYPE_CONTAINER, // 0 0 list of contained items TYPE_STRUCT, // sizeof(struct) relative list of contained items - TYPE_STATIC_ARRAY, // space-between-elems relative l - TYPE_RUNTIME_ARRAY, // space-between-elems relative + TYPE_STATIC_ARRAY, // space-between-elems relative either 1 replicated item, or n items + TYPE_VECTOR_ARRAY, // space-between-elems relative either 1 replicated item, or n items + TYPE_RAW_ARRAY, // space-between-elems relative either 1 replicated item, or n items TYPE_UNIQUE, // sizeof(unique_ptr) relative item at pointer - TYPE_VECTOR, // sizeof(vector) relative TYPE_RUNTIME_ARRAY at pointer + TYPE_VECTOR, // sizeof(vector) relative TYPE_VECTOR_ARRAY at pointer }; // root constructor @@ -126,7 +127,7 @@ public: save_type type() const { return save_type(m_type_count & 15); } u32 count() const { return m_type_count >> 4; } bool is_struct_or_container() const { return (type() == TYPE_STRUCT || type() == TYPE_CONTAINER); } - bool is_array() const { return (type() == TYPE_STATIC_ARRAY || type() == TYPE_RUNTIME_ARRAY); } + bool is_array() const { return (type() == TYPE_STATIC_ARRAY || type() == TYPE_VECTOR_ARRAY || type() == TYPE_RAW_ARRAY); } bool is_int() const { return (type() == TYPE_INT || type() == TYPE_UINT); } bool is_int_or_float() const { return (is_int() || type() == TYPE_FLOAT); } std::list<save_registered_item> &subitems() { return m_items; } @@ -206,21 +207,9 @@ class save_registrar friend class save_manager; friend class device_t; - // extended constructor for internal use only - save_registrar(save_registrar &parent, void *baseptr, save_registered_item::save_type type, u32 native_size, char const *name, u32 count, void *regcontainerbase, u32 regcontainersize) : - m_parent_item(parent.parent_item().append((baseptr == nullptr) ? 0 : uintptr_t(baseptr) - parent.m_regcontainerbase, type, native_size, name, count)), - m_regcontainerbase(uintptr_t(regcontainerbase)), - m_regcontainersize(regcontainersize) - { - } - - // internal constructor - save_registrar(save_registered_item &parent, void *baseptr = nullptr) : - m_parent_item(parent), - m_regcontainerbase(uintptr_t(baseptr)), - m_regcontainersize(0) - { - } + // internal constructors + save_registrar(save_registrar &parent, void *baseptr, save_registered_item::save_type type, u32 size, char const *name, u32 count, void *regcontainerbase, u32 regcontainersize); + save_registrar(save_registered_item &item, void *baseptr = nullptr); public: // items that are signed_int_like are interpreted as 8/16/32/64-bit signed integers; this includes @@ -246,17 +235,10 @@ public: } // return a reference to the parent item - save_registered_item &parent_item() const { return m_parent_item; } + save_registered_item &item() const { return m_item; } // append a bucket by stealing its items - save_registrar ®(save_registrar &src, char const *name) - { - save_registrar container(*this, name); - auto &srcitems = src.parent_item().subitems(); - auto &dstitems = container.parent_item().subitems(); - dstitems.splice(dstitems.end(), srcitems); - return *this; - } + save_registrar ®(save_registrar &src, char const *name); // bool as a special case save_registrar ®(bool &data, char const *name) @@ -304,7 +286,7 @@ public: template<typename T> save_registrar ®(T *data, char const *name, std::size_t count) { - return register_array(data, save_registered_item::TYPE_RUNTIME_ARRAY, name, count); + return register_array(data, save_registered_item::TYPE_RAW_ARRAY, name, count); } // arrays -- these are containers with a single item representing the underlying data, @@ -332,7 +314,7 @@ public: // create an outer container for the vector, then a regular array container within save_registrar container(*this, &data, save_registered_item::TYPE_VECTOR, sizeof(data), name, 0, &data[0], sizeof(T)); - container.register_array(&data[0], save_registered_item::TYPE_RUNTIME_ARRAY, name, data.size()); + container.register_array(&data[0], save_registered_item::TYPE_VECTOR_ARRAY, name, data.size()); return *this; } @@ -346,7 +328,7 @@ public: // create an outer container for the unique_ptr, then a regular array container within save_registrar container(*this, &data, save_registered_item::TYPE_UNIQUE, sizeof(data), name, 0, data.get(), sizeof(T)); - container.register_array(&data[0], save_registered_item::TYPE_RUNTIME_ARRAY, name, count); + container.register_array(&data[0], save_registered_item::TYPE_RAW_ARRAY, name, count); return *this; } @@ -371,9 +353,10 @@ public: template<typename BitmapType> std::enable_if_t<std::is_base_of<bitmap_t, BitmapType>::value, save_registrar> ®(BitmapType &data, char const *name) { + save_registrar container(*this, name); void *pixbase = data.raw_pixptr(0); - save_registrar rows(*this, pixbase, save_registered_item::TYPE_RUNTIME_ARRAY, data.rowbytes(), name, data.height(), pixbase, 0); - save_registrar cols(rows, pixbase, save_registered_item::TYPE_RUNTIME_ARRAY, sizeof(BitmapType::pixel_t), "", data.width(), pixbase, 0); + save_registrar rows(container, pixbase, save_registered_item::TYPE_RAW_ARRAY, data.rowbytes(), name, data.height(), pixbase, 0); + save_registrar cols(rows, pixbase, save_registered_item::TYPE_STATIC_ARRAY, sizeof(BitmapType::pixel_t), "", data.width(), pixbase, 0); cols.register_endpoint(pixbase, save_registered_item::TYPE_UINT, sizeof(BitmapType::pixel_t), ""); return *this; } @@ -382,10 +365,7 @@ private: // register an endpoint item (containing no subitems) save_registrar ®ister_endpoint(void *memptr, save_registered_item::save_type type, std::size_t itemsize, char const *itemname) { - uintptr_t delta = uintptr_t(memptr) - m_regcontainerbase; - if (m_regcontainersize != 0 && delta >= m_regcontainersize) - throw emu_fatalerror("Attempted to register item outside of parent element's bounds"); - m_parent_item.append(delta, type, itemsize, itemname); + m_item.append(ptr_to_offset(memptr, itemsize, type), type, itemsize, itemname); return *this; } @@ -406,7 +386,7 @@ private: container.reg(data[0], ""); // if the first item was non-replicatable, register remaining items independently - if (!container.m_parent_item.subitems().front().is_replicatable(true)) + if (!container.m_item.subitems().front().is_replicatable(true)) for (int index = 1; index < count; index++) { container.m_regcontainerbase = uintptr_t(&data[index]); @@ -415,8 +395,11 @@ private: return *this; } + // helper to verify an item against its container, and also compute the offset to store + uintptr_t ptr_to_offset(void *ptr, u32 size, save_registered_item::save_type type); + // internal state - save_registered_item &m_parent_item; + save_registered_item &m_item; uintptr_t m_regcontainerbase; u32 m_regcontainersize; }; |