summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Vas Crabb <vas@vastheman.com>2019-12-09 19:07:22 +1100
committer Vas Crabb <vas@vastheman.com>2019-12-09 19:09:51 +1100
commitd27918db8c5a503c7f272e1d4539a410d4807df3 (patch)
treeebdd7ca84bd244b88b78c4a7e5a2c313c84becec
parent017b53b2f58fa3c1b3e0b74d23f248892256dad5 (diff)
Added wrapper for using STRUCT_MEMBER with an indeterminate length array
* Examples in YM2612 family and MultiPCM * Also used STRUCT_MEMBER to reduce clutter in diexec save state registration
-rw-r--r--src/devices/sound/fm2612.cpp21
-rw-r--r--src/devices/sound/multipcm.cpp26
-rw-r--r--src/devices/sound/multipcm.h1
-rw-r--r--src/emu/device.h6
-rw-r--r--src/emu/diexec.cpp15
-rw-r--r--src/emu/diexec.h4
-rw-r--r--src/emu/save.h15
7 files changed, 48 insertions, 40 deletions
diff --git a/src/devices/sound/fm2612.cpp b/src/devices/sound/fm2612.cpp
index 91d27686fe0..7923e46ccbb 100644
--- a/src/devices/sound/fm2612.cpp
+++ b/src/devices/sound/fm2612.cpp
@@ -1697,21 +1697,16 @@ static inline void CSMKeyControll(fm2612_FM_OPN *OPN, fm2612_FM_CH *CH)
/* FM channel save , internal state only */
static void FMsave_state_channel(device_t *device,fm2612_FM_CH *CH,int num_ch)
{
- int slot , ch;
+ /* channel */
+ device->save_pointer(STRUCT_MEMBER(CH, op1_out), num_ch);
+ device->save_pointer(STRUCT_MEMBER(CH, fc), num_ch);
- for(ch=0;ch<num_ch;ch++,CH++)
+ /* slots */
+ for(int ch=0;ch<num_ch;ch++,CH++)
{
- /* channel */
- device->save_item(NAME(CH->op1_out), ch);
- device->save_item(NAME(CH->fc), ch);
- /* slots */
- for(slot=0;slot<4;slot++)
- {
- fm2612_FM_SLOT *SLOT = &CH->SLOT[slot];
- device->save_item(NAME(SLOT->phase), ch * 4 + slot);
- device->save_item(NAME(SLOT->state), ch * 4 + slot);
- device->save_item(NAME(SLOT->volume), ch * 4 + slot);
- }
+ device->save_item(STRUCT_MEMBER(CH->SLOT, phase), ch);
+ device->save_item(STRUCT_MEMBER(CH->SLOT, state), ch);
+ device->save_item(STRUCT_MEMBER(CH->SLOT, volume), ch);
}
}
diff --git a/src/devices/sound/multipcm.cpp b/src/devices/sound/multipcm.cpp
index 285b6ade701..ca8b179ac5d 100644
--- a/src/devices/sound/multipcm.cpp
+++ b/src/devices/sound/multipcm.cpp
@@ -575,23 +575,23 @@ void multipcm_device::device_start()
save_item(NAME(m_address));
// Slots
- m_slots = make_unique_clear<slot_t[]>(28);
+ m_slots = make_unique_clear<slot_t []>(28);
+
+ save_pointer(STRUCT_MEMBER(m_slots, m_regs), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_playing), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_base), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_offset), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_step), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_pan), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_total_level), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_dest_total_level), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_total_level_step), 28);
+ save_pointer(STRUCT_MEMBER(m_slots, m_prev_sample), 28);
+
for (int32_t slot = 0; slot < 28; ++slot)
{
- m_slots[slot].m_slot_index = slot;
m_slots[slot].m_playing = false;
- save_item(NAME(m_slots[slot].m_slot_index), slot);
- save_item(NAME(m_slots[slot].m_regs), slot);
- save_item(NAME(m_slots[slot].m_playing), slot);
- save_item(NAME(m_slots[slot].m_base), slot);
- save_item(NAME(m_slots[slot].m_offset), slot);
- save_item(NAME(m_slots[slot].m_step), slot);
- save_item(NAME(m_slots[slot].m_pan), slot);
- save_item(NAME(m_slots[slot].m_total_level), slot);
- save_item(NAME(m_slots[slot].m_dest_total_level), slot);
- save_item(NAME(m_slots[slot].m_total_level_step), slot);
- save_item(NAME(m_slots[slot].m_prev_sample), slot);
save_item(NAME(m_slots[slot].m_envelope_gen.m_volume), slot);
save_item(NAME(m_slots[slot].m_envelope_gen.m_state), slot);
save_item(NAME(m_slots[slot].m_envelope_gen.step), slot);
diff --git a/src/devices/sound/multipcm.h b/src/devices/sound/multipcm.h
index 626f4c99670..08d1e8d2fcf 100644
--- a/src/devices/sound/multipcm.h
+++ b/src/devices/sound/multipcm.h
@@ -79,7 +79,6 @@ private:
struct slot_t
{
- uint8_t m_slot_index;
uint8_t m_regs[8];
bool m_playing;
sample_t m_sample;
diff --git a/src/emu/device.h b/src/emu/device.h
index 11798068259..b09bf535ed4 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -627,6 +627,12 @@ public:
assert(m_save);
m_save->save_pointer(this, name(), tag(), index, std::forward<ItemType>(value), valname, count);
}
+ template<typename ItemType, typename ElementType>
+ void ATTR_COLD save_pointer(ItemType &&value, ElementType save_manager::pointer_unwrap<ItemType>::underlying_type::*element, const char *valname, u32 count, int index = 0)
+ {
+ assert(m_save);
+ m_save->save_pointer(this, name(), tag(), index, std::forward<ItemType>(value), element, valname, count);
+ }
// debugging
device_debug *debug() const { return m_debug.get(); }
diff --git a/src/emu/diexec.cpp b/src/emu/diexec.cpp
index f04854ee090..842f52b10ab 100644
--- a/src/emu/diexec.cpp
+++ b/src/emu/diexec.cpp
@@ -410,9 +410,13 @@ void device_execute_interface::interface_post_start()
device().save_item(NAME(m_totalcycles));
device().save_item(NAME(m_localtime));
+ // it's more efficient and causes less clutter to save these this way
+ device().save_item(STRUCT_MEMBER(m_input, m_stored_vector));
+ device().save_item(STRUCT_MEMBER(m_input, m_curvector));
+
// fill in the input states and IRQ callback information
for (int line = 0; line < ARRAY_LENGTH(m_input); line++)
- m_input[line].start(this, line);
+ m_input[line].start(*this, line);
}
@@ -668,17 +672,12 @@ device_execute_interface::device_input::device_input()
// can set ourselves up
//-------------------------------------------------
-void device_execute_interface::device_input::start(device_execute_interface *execute, int linenum)
+void device_execute_interface::device_input::start(device_execute_interface &execute, int linenum)
{
- m_execute = execute;
+ m_execute = &execute;
m_linenum = linenum;
reset();
-
- device_t &device = m_execute->device();
- device.save_item(NAME(m_stored_vector), m_linenum);
- device.save_item(NAME(m_curvector), m_linenum);
- device.save_item(NAME(m_curstate), m_linenum);
}
diff --git a/src/emu/diexec.h b/src/emu/diexec.h
index c4a99c63043..8745b15ae03 100644
--- a/src/emu/diexec.h
+++ b/src/emu/diexec.h
@@ -247,12 +247,12 @@ private:
// internal information about the state of inputs
class device_input
{
- static const int USE_STORED_VECTOR = 0xff000000;
+ static constexpr int USE_STORED_VECTOR = 0xff000000;
public:
device_input();
- void start(device_execute_interface *execute, int linenum);
+ void start(device_execute_interface &execute, int linenum);
void reset();
void set_state_synced(int state, int vector = USE_STORED_VECTOR);
diff --git a/src/emu/save.h b/src/emu/save.h
index 5fe6c143c4b..631fd590296 100644
--- a/src/emu/save.h
+++ b/src/emu/save.h
@@ -19,7 +19,10 @@
#include <array>
#include <cassert>
+#include <memory>
+#include <string>
#include <type_traits>
+#include <vector>
@@ -60,7 +63,7 @@ typedef named_delegate<void ()> save_prepost_delegate;
template <> inline void save_manager::save_item(device_t *device, const char *module, const char *tag, int index, std::vector<TYPE> &value, const char *name) { save_memory(device, module, tag, index, name, &value[0], sizeof(TYPE), value.size()); }
// use this for saving members of structures in arrays
-#define STRUCT_MEMBER(s, m) s, &save_manager::array_unwrap<std::remove_reference_t<decltype(s)> >::underlying_type::m, #s "." #m
+#define STRUCT_MEMBER(s, m) s, &save_manager::pointer_unwrap<decltype(s)>::underlying_type::m, #s "." #m
//**************************************************************************
@@ -74,7 +77,7 @@ class save_manager
{
// type_checker is a set of templates to identify valid save types
template <typename ItemType> struct type_checker { static constexpr bool is_atom = false; static constexpr bool is_pointer = false; };
- template <typename ItemType> struct type_checker<ItemType*> { static constexpr bool is_atom = false; static constexpr bool is_pointer = true; };
+ template <typename ItemType> struct type_checker<ItemType *> { static constexpr bool is_atom = false; static constexpr bool is_pointer = true; };
class state_entry
{
@@ -110,7 +113,7 @@ public:
static constexpr std::size_t SIZE = sizeof(underlying_type);
static underlying_type *ptr(T &value) { return &value; }
};
- template <typename T, std::size_t N> struct array_unwrap<T[N]>
+ template <typename T, std::size_t N> struct array_unwrap<T [N]>
{
using underlying_type = typename array_unwrap<T>::underlying_type;
static constexpr std::size_t SAVE_COUNT = N * array_unwrap<T>::SAVE_COUNT;
@@ -125,6 +128,12 @@ public:
static underlying_type *ptr(std::array<T, N> &value) { return array_unwrap<T>::ptr(value[0]); }
};
+ // stuff to allow STRUCT_MEMBER to work with pointers
+ template <typename T> struct pointer_unwrap { using underlying_type = typename array_unwrap<T>::underlying_type; };
+ template <typename T> struct pointer_unwrap<T &> { using underlying_type = typename pointer_unwrap<std::remove_cv_t<T> >::underlying_type; };
+ template <typename T> struct pointer_unwrap<T *> { using underlying_type = typename array_unwrap<T>::underlying_type; };
+ template <typename T> struct pointer_unwrap<std::unique_ptr<T []> > { using underlying_type = typename array_unwrap<T>::underlying_type; };
+
// construction/destruction
save_manager(running_machine &machine);