summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
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
commit34b805da310630e2d33b13a82ccd2a776671d05b (patch)
tree51b1cdf13382d493a719219a1889feb260477076
parent9394ff0593f142ad1ebf439052c3b57e19edd0fd (diff)
Differentiated raw arrays from vector arrays. Add warnings for raw arrays that are not in containers.
-rw-r--r--src/emu/debug/dvsave.cpp8
-rw-r--r--src/emu/save.cpp101
-rw-r--r--src/emu/save.h61
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 &reg(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 &reg(save_registrar &src, char const *name);
// bool as a special case
save_registrar &reg(bool &data, char const *name)
@@ -304,7 +286,7 @@ public:
template<typename T>
save_registrar &reg(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> &reg(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 &register_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;
};