summaryrefslogtreecommitdiffstatshomepage
diff options
context:
space:
mode:
author Aaron Giles <aaron@aarongiles.com>2021-04-09 21:16:37 -0700
committer Aaron Giles <aaron@aarongiles.com>2021-04-09 21:16:37 -0700
commit902cce39106ed1f7c181c46c491f2c9e3b9a199d (patch)
tree9ea33245c216aab54beb94251f00846a5a37d423
parentb8c568b279f9ebaedac014d51eb48ed9b530566a (diff)
Add explicit unique_ptr/vector containers. Fix registration checks. Added modern saving to namco and ymfm sound.
-rw-r--r--src/devices/sound/namco.cpp45
-rw-r--r--src/devices/sound/namco.h16
-rw-r--r--src/devices/sound/ym2151.cpp17
-rw-r--r--src/devices/sound/ym2151.h1
-rw-r--r--src/devices/sound/ymfm.cpp121
-rw-r--r--src/devices/sound/ymfm.h17
-rw-r--r--src/emu/device.cpp29
-rw-r--r--src/emu/device.h1
-rw-r--r--src/emu/save.cpp72
-rw-r--r--src/emu/save.h123
-rw-r--r--src/emu/tilemap.h6
11 files changed, 287 insertions, 161 deletions
diff --git a/src/devices/sound/namco.cpp b/src/devices/sound/namco.cpp
index 6d112d4dc1f..1007d1525bd 100644
--- a/src/devices/sound/namco.cpp
+++ b/src/devices/sound/namco.cpp
@@ -103,15 +103,6 @@ void namco_audio_device::device_start()
/* start with sound enabled, many games don't have a sound enable register */
m_sound_enable = true;
- /* register with the save state system */
- if (m_wave_ptr == nullptr)
- save_pointer(NAME(m_wavedata), 0x400);
-
- save_item(NAME(m_voices));
- save_item(NAME(m_sound_enable));
- for (int v = 0; v < MAX_VOLUME; v++)
- save_pointer(NAME(m_waveform[v]), 32 * 8 * (1+m_wave_size), v);
-
/* reset all the voices */
for (sound_channel *voice = m_channel_list; voice < m_last_channel; voice++)
{
@@ -125,17 +116,19 @@ void namco_audio_device::device_start()
voice->noise_counter = 0;
voice->noise_hold = 0;
}
+}
+
+void namco_audio_device::device_register_save(save_registrar &save)
+{
+ if (m_wave_ptr == nullptr)
+ save.reg(NAME(m_wavedata), 0x400);
- /* register with the save state system */
- save_pointer(STRUCT_MEMBER(m_channel_list, frequency), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, counter), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, volume), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, noise_sw), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, noise_state), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, noise_seed), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, noise_hold), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, noise_counter), m_voices);
- save_pointer(STRUCT_MEMBER(m_channel_list, waveform_select), m_voices);
+ save.reg(NAME(m_sound_enable));
+ for (int v = 0; v < MAX_VOLUME; v++)
+ save.reg(m_waveform[v], string_format("waveform[%d]", v).c_str(), 32 * 8 * (1+m_wave_size));
+
+// save.reg(NAME(m_channel_list), m_voices);
+ save.reg(NAME(m_channel_list));
}
@@ -144,7 +137,12 @@ void namco_device::device_start()
namco_audio_device::device_start();
m_soundregs = make_unique_clear<uint8_t[]>(0x400);
- save_pointer(NAME(m_soundregs), 0x400);
+}
+
+void namco_device::device_register_save(save_registrar &save)
+{
+ namco_audio_device::device_register_save(save);
+ save.reg(NAME(m_soundregs), 0x400);
}
@@ -153,7 +151,12 @@ void namco_15xx_device::device_start()
namco_audio_device::device_start();
m_soundregs = make_unique_clear<uint8_t[]>(0x400);
- save_pointer(NAME(m_soundregs), 0x400);
+}
+
+void namco_15xx_device::device_register_save(save_registrar &save)
+{
+ namco_audio_device::device_register_save(save);
+ save.reg(NAME(m_soundregs), 0x400);
}
diff --git a/src/devices/sound/namco.h b/src/devices/sound/namco.h
index f032a71a536..497f4ca3af2 100644
--- a/src/devices/sound/namco.h
+++ b/src/devices/sound/namco.h
@@ -32,6 +32,19 @@ protected:
uint32_t noise_counter;
int32_t noise_hold;
int32_t waveform_select;
+
+ void register_save(save_registrar &save)
+ {
+ save.reg(NAME(frequency))
+ .reg(NAME(counter))
+ .reg(NAME(volume))
+ .reg(NAME(noise_sw))
+ .reg(NAME(noise_state))
+ .reg(NAME(noise_seed))
+ .reg(NAME(noise_hold))
+ .reg(NAME(noise_counter))
+ .reg(NAME(waveform_select));
+ }
};
namco_audio_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, uint32_t clock);
@@ -39,6 +52,7 @@ protected:
// device-level overrides
virtual void device_start() override;
virtual void device_clock_changed() override;
+ virtual void device_register_save(save_registrar &save) override;
// internal state
@@ -86,6 +100,7 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
+ virtual void device_register_save(save_registrar &save) override;
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
@@ -106,6 +121,7 @@ public:
protected:
// device-level overrides
virtual void device_start() override;
+ virtual void device_register_save(save_registrar &save) override;
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
diff --git a/src/devices/sound/ym2151.cpp b/src/devices/sound/ym2151.cpp
index a8e0bf4ab7a..2d4feb5389a 100644
--- a/src/devices/sound/ym2151.cpp
+++ b/src/devices/sound/ym2151.cpp
@@ -124,12 +124,23 @@ void ym2151_device::device_start()
// call this for the variants that need to adjust the rate
device_clock_changed();
+ // initialize the FM engine
+ m_fm.init();
+}
+
+
+//-------------------------------------------------
+// device_register_save - register for save state
+//-------------------------------------------------
+
+void ym2151_device::device_register_save(save_registrar &save)
+{
// save our data
- save_item(YMFM_NAME(m_address));
- save_item(YMFM_NAME(m_reset_state));
+ save.reg(NAME(m_address))
+ .reg(NAME(m_reset_state));
// save the engines
- m_fm.save(*this);
+ m_fm.register_save(save);
}
diff --git a/src/devices/sound/ym2151.h b/src/devices/sound/ym2151.h
index d48a5939071..d5038e7967a 100644
--- a/src/devices/sound/ym2151.h
+++ b/src/devices/sound/ym2151.h
@@ -41,6 +41,7 @@ protected:
virtual void device_start() override;
virtual void device_reset() override;
virtual void device_clock_changed() override;
+ virtual void device_register_save(save_registrar &save) override;
// sound overrides
virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs) override;
diff --git a/src/devices/sound/ymfm.cpp b/src/devices/sound/ymfm.cpp
index 44a869bc1fd..0e91e9b7349 100644
--- a/src/devices/sound/ymfm.cpp
+++ b/src/devices/sound/ymfm.cpp
@@ -745,18 +745,18 @@ ymopm_registers::ymopm_registers() :
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
-void ymopm_registers::save(device_t &device)
+void ymopm_registers::register_save(save_registrar &save)
{
- device.save_item(YMFM_NAME(m_lfo_counter));
- device.save_item(YMFM_NAME(m_lfo_am));
- device.save_item(YMFM_NAME(m_noise_lfsr));
- device.save_item(YMFM_NAME(m_noise_counter));
- device.save_item(YMFM_NAME(m_noise_state));
- device.save_item(YMFM_NAME(m_noise_lfo));
- device.save_item(YMFM_NAME(m_regdata));
+ save.reg(NAME(m_lfo_counter))
+ .reg(NAME(m_lfo_am))
+ .reg(NAME(m_noise_lfsr))
+ .reg(NAME(m_noise_counter))
+ .reg(NAME(m_noise_state))
+ .reg(NAME(m_noise_lfo))
+ .reg(NAME(m_regdata));
}
@@ -1063,18 +1063,18 @@ ymopn_registers_base<IsOpnA>::ymopn_registers_base() :
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
template<bool IsOpnA>
-void ymopn_registers_base<IsOpnA>::save(device_t &device)
+void ymopn_registers_base<IsOpnA>::register_save(save_registrar &save)
{
if (IsOpnA)
{
- device.save_item(YMFM_NAME(m_lfo_counter));
- device.save_item(YMFM_NAME(m_lfo_am));
+ save.reg(NAME(m_lfo_counter))
+ .reg(NAME(m_lfo_am));
}
- device.save_item(YMFM_NAME(m_regdata));
+ save.reg(NAME(m_regdata));
}
@@ -1472,17 +1472,17 @@ ymopl_registers_base<Revision>::ymopl_registers_base() :
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
template<int Revision>
-void ymopl_registers_base<Revision>::save(device_t &device)
+void ymopl_registers_base<Revision>::register_save(save_registrar &save)
{
- device.save_item(YMFM_NAME(m_lfo_am_counter));
- device.save_item(YMFM_NAME(m_lfo_pm_counter));
- device.save_item(YMFM_NAME(m_lfo_am));
- device.save_item(YMFM_NAME(m_noise_lfsr));
- device.save_item(YMFM_NAME(m_regdata));
+ save.reg(NAME(m_lfo_am_counter))
+ .reg(NAME(m_lfo_pm_counter))
+ .reg(NAME(m_lfo_am))
+ .reg(NAME(m_noise_lfsr))
+ .reg(NAME(m_regdata));
}
@@ -1819,16 +1819,16 @@ ymopll_registers::ymopll_registers() :
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
-void ymopll_registers::save(device_t &device)
+void ymopll_registers::register_save(save_registrar &save)
{
- device.save_item(YMFM_NAME(m_lfo_am_counter));
- device.save_item(YMFM_NAME(m_lfo_pm_counter));
- device.save_item(YMFM_NAME(m_lfo_am));
- device.save_item(YMFM_NAME(m_noise_lfsr));
- device.save_item(YMFM_NAME(m_regdata));
+ save.reg(NAME(m_lfo_am_counter))
+ .reg(NAME(m_lfo_pm_counter))
+ .reg(NAME(m_lfo_am))
+ .reg(NAME(m_noise_lfsr))
+ .reg(NAME(m_regdata));
}
@@ -2103,21 +2103,19 @@ ymfm_operator<RegisterType>::ymfm_operator(ymfm_engine_base<RegisterType> &owner
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
-ALLOW_SAVE_TYPE(ymfm_envelope_state);
-
template<class RegisterType>
-void ymfm_operator<RegisterType>::save(device_t &device, u32 index)
+void ymfm_operator<RegisterType>::register_save(save_registrar &save)
{
// save our data
- device.save_item(YMFM_NAME(m_phase), index);
- device.save_item(YMFM_NAME(m_env_attenuation), index);
- device.save_item(YMFM_NAME(m_env_state), index);
- device.save_item(YMFM_NAME(m_ssg_inverted), index);
- device.save_item(YMFM_NAME(m_key_state), index);
- device.save_item(YMFM_NAME(m_keyon_live), index);
+ save.reg(NAME(m_phase))
+ .reg(NAME(m_env_attenuation))
+ .reg(NAME(m_env_state))
+ .reg(NAME(m_ssg_inverted))
+ .reg(NAME(m_key_state))
+ .reg(NAME(m_keyon_live));
}
@@ -2518,15 +2516,15 @@ ymfm_channel<RegisterType>::ymfm_channel(ymfm_engine_base<RegisterType> &owner,
//-------------------------------------------------
-// save - register for save states
+// register_save - register for save states
//-------------------------------------------------
template<class RegisterType>
-void ymfm_channel<RegisterType>::save(device_t &device, u32 index)
+void ymfm_channel<RegisterType>::register_save(save_registrar &save)
{
// save our data
- device.save_item(YMFM_NAME(m_feedback), index);
- device.save_item(YMFM_NAME(m_feedback_in), index);
+ save.reg(NAME(m_feedback))
+ .reg(NAME(m_feedback_in));
}
@@ -2893,37 +2891,38 @@ ymfm_engine_base<RegisterType>::ymfm_engine_base(device_t &device) :
//-------------------------------------------------
-// save - register for save states
+// init - initialize our state
//-------------------------------------------------
template<class RegisterType>
-void ymfm_engine_base<RegisterType>::save(device_t &device)
+void ymfm_engine_base<RegisterType>::init()
{
// allocate our timers
for (int tnum = 0; tnum < 2; tnum++)
- m_timer[tnum] = device.machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ymfm_engine_base::timer_handler), this));
+ m_timer[tnum] = m_device.machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(ymfm_engine_base::timer_handler), this));
// resolve the IRQ handler while we're here
m_irq_handler.resolve();
+}
- // save our data
- device.save_item(YMFM_NAME(m_env_counter));
- device.save_item(YMFM_NAME(m_status));
- device.save_item(YMFM_NAME(m_clock_prescale));
- device.save_item(YMFM_NAME(m_irq_mask));
- device.save_item(YMFM_NAME(m_irq_state));
- device.save_item(YMFM_NAME(m_busy_end));
-
- // save the register/family data
- m_regs.save(device);
- // save channel data
- for (int chnum = 0; chnum < CHANNELS; chnum++)
- m_channel[chnum]->save(device, chnum);
+//-------------------------------------------------
+// register_save - register for save states
+//-------------------------------------------------
- // save operator data
- for (int opnum = 0; opnum < OPERATORS; opnum++)
- m_operator[opnum]->save(device, opnum);
+template<class RegisterType>
+void ymfm_engine_base<RegisterType>::register_save(save_registrar &save)
+{
+ // save our data
+ save.reg(NAME(m_env_counter))
+ .reg(NAME(m_status))
+ .reg(NAME(m_clock_prescale))
+ .reg(NAME(m_irq_mask))
+ .reg(NAME(m_irq_state))
+ .reg(NAME(m_busy_end))
+ .reg(NAME(m_channel))
+ .reg(NAME(m_operator))
+ .reg(NAME(m_regs));
}
diff --git a/src/devices/sound/ymfm.h b/src/devices/sound/ymfm.h
index 8ab0ddc9d03..f0f949b423b 100644
--- a/src/devices/sound/ymfm.h
+++ b/src/devices/sound/ymfm.h
@@ -312,7 +312,7 @@ public:
ymopm_registers();
// register for save states
- void save(device_t &device);
+ void register_save(save_registrar &save);
// reset to initial state
void reset();
@@ -518,7 +518,7 @@ public:
ymopn_registers_base();
// register for save states
- void save(device_t &device);
+ void register_save(save_registrar &save);
// reset to initial state
void reset();
@@ -735,7 +735,7 @@ public:
ymopl_registers_base();
// register for save states
- void save(device_t &device);
+ void register_save(save_registrar &save);
// reset to initial state
void reset();
@@ -948,7 +948,7 @@ public:
ymopll_registers();
// register for save states
- void save(device_t &device);
+ void register_save(save_registrar &save);
// reset to initial state
void reset();
@@ -1113,7 +1113,7 @@ public:
ymfm_operator(ymfm_engine_base<RegisterType> &owner, u32 opoffs);
// register for save states
- void save(device_t &device, u32 index);
+ void register_save(save_registrar &save);
// reset the operator state
void reset();
@@ -1185,7 +1185,7 @@ public:
ymfm_channel(ymfm_engine_base<RegisterType> &owner, u32 choffs);
// register for save states
- void save(device_t &device, u32 index);
+ void register_save(save_registrar &save);
// reset the channel state
void reset();
@@ -1279,8 +1279,11 @@ public:
// configuration helpers
auto irq_handler() { return m_irq_handler.bind(); }
+ // initialize our state
+ void init();
+
// register for save states
- void save(device_t &device);
+ void register_save(save_registrar &device);
// reset the overall state
void reset();
diff --git a/src/emu/device.cpp b/src/emu/device.cpp
index edcfa116562..84e67ac6db9 100644
--- a/src/emu/device.cpp
+++ b/src/emu/device.cpp
@@ -105,6 +105,7 @@ device_t::device_t(const machine_config &mconfig, device_type type, const char *
, m_config_complete(false)
, m_started(false)
, m_auto_finder_list(nullptr)
+ , m_save_registrations(0)
{
if (owner != nullptr)
m_tag.assign((owner->owner() == nullptr) ? "" : owner->tag()).append(":").append(tag);
@@ -575,22 +576,10 @@ void device_t::start()
for (device_interface &intf : interfaces())
intf.interface_pre_start();
- // remember the number of state registrations
+ // start the device, tracking how many state registrations they did
int state_registrations = machine().save().registration_count();
-
- // start the device
device_start();
-
- // complain if nothing was registered by the device
- state_registrations = machine().save().registration_count() - state_registrations;
- device_execute_interface *exec;
- device_sound_interface *sound;
- if (state_registrations == 0 && (interface(exec) || interface(sound)) && type() != SPEAKER)
- {
- logerror("Device did not register any state to save!\n");
- if ((machine().system().flags & MACHINE_SUPPORTS_SAVE) != 0)
- fatalerror("Device '%s' did not register any state to save!\n", tag());
- }
+ m_save_registrations += machine().save().registration_count() - state_registrations;
// let the interfaces do their post-work
for (device_interface &intf : interfaces())
@@ -707,7 +696,19 @@ void device_t::register_save(save_registrar &save)
intf.interface_register_save(save);
// notify the device
+ int state_registrations = machine().save().registration_count();
device_register_save(save);
+ m_save_registrations += machine().save().registration_count() - state_registrations;
+
+ // complain if registrations didn't happen
+ device_execute_interface *exec;
+ device_sound_interface *sound;
+ if (state_registrations == 0 && (interface(exec) || interface(sound)) && type() != SPEAKER)
+ {
+ logerror("Device did not register any state to save!\n");
+ if ((machine().system().flags & MACHINE_SUPPORTS_SAVE) != 0)
+ fatalerror("Device '%s' did not register any state to save!\n", tag());
+ }
}
diff --git a/src/emu/device.h b/src/emu/device.h
index 41e99c461a8..f2b63f2aa98 100644
--- a/src/emu/device.h
+++ b/src/emu/device.h
@@ -860,6 +860,7 @@ private:
std::list<devcb_base *> m_callbacks;
std::vector<memory_view *> m_viewlist; // list of views
std::unique_ptr<save_registrar> m_legacy_save; // bucket for legacy save stuff
+ int m_save_registrations; // number of save registrations
// string formatting buffer for logerror
mutable util::ovectorstream m_string_buffer;
diff --git a/src/emu/save.cpp b/src/emu/save.cpp
index e0e51bea359..55e4e6ce600 100644
--- a/src/emu/save.cpp
+++ b/src/emu/save.cpp
@@ -1031,7 +1031,7 @@ void save_manager::state_entry::flip_data()
save_registered_item::save_registered_item() :
m_ptr_offset(0),
- m_type(TYPE_STRUCT),
+ m_type(TYPE_CONTAINER),
m_native_size(0)
{
}
@@ -1043,6 +1043,9 @@ save_registered_item::save_registered_item(uintptr_t ptr_offset, save_type type,
m_native_size(native_size),
m_name(name)
{
+ // cleanup names a bit
+ if (m_name[0] == '*')
+ m_name.erase(0, 1);
if (m_name[0] == 'm' && m_name[1] == '_')
m_name.erase(0, 2);
}
@@ -1052,8 +1055,26 @@ save_registered_item::save_registered_item(uintptr_t ptr_offset, save_type type,
// append - append a new item to the current one
//-------------------------------------------------
+static std::string type_string(save_registered_item::save_type type, uint32_t native_size)
+{
+ switch (type)
+ {
+ case save_registered_item::TYPE_CONTAINER: return "CONTAINER";
+ case save_registered_item::TYPE_POINTER: return "POINTER";
+ case save_registered_item::TYPE_UNIQUE: return "UNIQUE";
+ case save_registered_item::TYPE_VECTOR: return "VECTOR";
+ case save_registered_item::TYPE_STRUCT: return "STRUCT";
+ case save_registered_item::TYPE_BOOL: return "BOOL";
+ case save_registered_item::TYPE_INT: return string_format("INT%d", 8 * native_size);
+ case save_registered_item::TYPE_UINT: return string_format("UINT%d", 8 * native_size);
+ case save_registered_item::TYPE_FLOAT: return string_format("FLOAT%d", 8 * native_size);
+ default: return string_format("ARRAY[%d]", int(type));
+ }
+}
+
save_registered_item &save_registered_item::append(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name)
{
+printf("%s '%s': adding %s '%s' @ %llX, size %d\n", type_string(m_type, m_native_size).c_str(), m_name.c_str(), type_string(type, native_size).c_str(), name, ptr_offset, native_size);
m_items.emplace_back(ptr_offset, type, native_size, name);
return m_items.back();
}
@@ -1064,7 +1085,7 @@ save_registered_item &save_registered_item::append(uintptr_t ptr_offset, save_ty
// items into a binary form
//-------------------------------------------------
-uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintptr_t objbase)
+uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintptr_t objbase) const
{
// update the base pointer with our local base/offset
objbase += m_ptr_offset;
@@ -1089,6 +1110,24 @@ uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintpt
offset += m_native_size;
break;
+ // unique ptrs retrieve the pointer from their container
+ case TYPE_UNIQUE:
+ objbase = reinterpret_cast<uintptr_t>(reinterpret_cast<generic_unique *>(objbase)->get());
+ offset += m_items.front().save_binary(&ptr[offset], length, objbase);
+ break;
+
+ // vectors retrieve the pointer from their container
+ case TYPE_VECTOR:
+ objbase = reinterpret_cast<uintptr_t>(&(*reinterpret_cast<generic_vector *>(objbase))[0]);
+ offset += m_items.front().save_binary(&ptr[offset], length, objbase);
+ break;
+
+ // vectors retrieve the pointer from their container
+ case TYPE_POINTER:
+ objbase = reinterpret_cast<uintptr_t>(*reinterpret_cast<generic_pointer *>(objbase));
+ offset += m_items.front().save_binary(&ptr[offset], length, objbase);
+ break;
+
// structs and containers iterate over owned items
case TYPE_CONTAINER:
objbase = 0;
@@ -1116,7 +1155,7 @@ uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintpt
// owned items from binary form
//-------------------------------------------------
-uint64_t save_registered_item::restore_binary(uint8_t const *ptr, uint64_t length, uintptr_t objbase)
+uint64_t save_registered_item::restore_binary(uint8_t const *ptr, uint64_t length, uintptr_t objbase) const
{
// update the base pointer with our local base/offset
objbase += m_ptr_offset;
@@ -1211,17 +1250,34 @@ void save_registered_item::save_json(std::ostringstream &output, int indent, boo
break;
}
+ // unique ptrs retrieve the pointer from their container
+ case TYPE_UNIQUE:
+ objbase = reinterpret_cast<uintptr_t>(reinterpret_cast<generic_unique *>(objbase)->get());
+ m_items.front().save_json(output, indent, inline_form, objbase);
+ break;
+
+ // vectors retrieve the pointer from their container
+ case TYPE_VECTOR:
+ objbase = reinterpret_cast<uintptr_t>(&(*reinterpret_cast<generic_vector *>(objbase))[0]);
+ m_items.front().save_json(output, indent, inline_form, objbase);
+ break;
+
+ // vectors retrieve the pointer from their container
+ case TYPE_POINTER:
+ objbase = reinterpret_cast<uintptr_t>(*reinterpret_cast<generic_pointer *>(objbase));
+ m_items.front().save_json(output, indent, inline_form, objbase);
+ break;
+
// structs and containers iterate over owned items
case TYPE_CONTAINER:
- objbase = 0;
case TYPE_STRUCT:
- if (inline_form || compute_binary_size() <= 16)
+ if (inline_form || compute_binary_size(objbase - m_ptr_offset) <= 16)
{
// inline form outputs everything on a single line
output << "{ ";
for (auto &item : m_items)
{
- item.save_json(output, indent, true, objbase);
+ item.save_json(output, indent, true, (m_type == TYPE_CONTAINER) ? 0 : objbase);
if (&item != &m_items.back())
output << ", ";
}
@@ -1234,7 +1290,7 @@ void save_registered_item::save_json(std::ostringstream &output, int indent, boo
for (auto &item : m_items)
{
output << std::setw(indent + 1) << std::setfill('\t') << "" << std::setw(0);
- item.save_json(output, indent + 1, false, objbase);
+ item.save_json(output, indent + 1, false, (m_type == TYPE_CONTAINER) ? 0 : objbase);
if (&item != &m_items.back())
output << ",";
output << std::endl;
@@ -1249,7 +1305,7 @@ void save_registered_item::save_json(std::ostringstream &output, int indent, boo
if (m_type < TYPE_ARRAY)
{
auto &item = m_items.front();
- uint32_t item_size = item.compute_binary_size();
+ uint32_t item_size = item.compute_binary_size(objbase);
if (inline_form || m_type * item_size <= 16)
{
// strictly inline form outputs everything on a single line
diff --git a/src/emu/save.h b/src/emu/save.h
index 694f9fbcee4..232b69f5748 100644
--- a/src/emu/save.h
+++ b/src/emu/save.h
@@ -89,16 +89,23 @@ typedef named_delegate<void ()> save_prepost_delegate;
class save_registered_item
{
+ using generic_unique = std::unique_ptr<int> const;
+ using generic_vector = std::vector<int> const;
+ using generic_pointer = void * const;
+
public:
enum save_type : uint32_t
{
- TYPE_ARRAY = 0xffff0000,
- TYPE_CONTAINER,
- TYPE_STRUCT,
- TYPE_BOOL,
- TYPE_INT,
- TYPE_UINT,
- TYPE_FLOAT
+ TYPE_ARRAY = 0xffff0000, // array is relative, and contains 1 data item that is replicated
+ TYPE_CONTAINER, // container is absolute, and contains absolute data
+ TYPE_POINTER, // pointer is absolute, and contains 1 data item pointed to by the pointer
+ TYPE_UNIQUE, // unique is relative, and contains 1 data item pointed to by std::unique_ptr
+ TYPE_VECTOR, // vector is relative, and contains an array of items pointed to by std::vector
+ TYPE_STRUCT, // struct is relative, and contains a list of relative items
+ TYPE_BOOL, // bool is relative, size 1
+ TYPE_INT, // int is relative, same size as native
+ TYPE_UINT, // uint is relative, same size as native
+ TYPE_FLOAT // float is relative, same size as native
};
// root constructor
@@ -111,13 +118,13 @@ public:
save_registered_item &append(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name);
// compute the binary size by just saving with a null
- uint64_t compute_binary_size() { return save_binary(nullptr, 0); }
+ uint64_t compute_binary_size(uintptr_t objbase = 0) const { return save_binary(nullptr, 0, objbase); }
// save this item and all owned items into a binary form
- uint64_t save_binary(uint8_t *ptr, uint64_t length, uintptr_t objbase = 0);
+ uint64_t save_binary(uint8_t *ptr, uint64_t length, uintptr_t objbase = 0) const;
// restore this item and all owned items from binary form
- uint64_t restore_binary(uint8_t const *ptr, uint64_t length, uintptr_t objbase = 0);
+ uint64_t restore_binary(uint8_t const *ptr, uint64_t length, uintptr_t objbase = 0) const;
// save this item into a JSON stream
void save_json(std::ostringstream &output, int indent = 0, bool inline_form = false, uintptr_t objbase = 0);
@@ -143,70 +150,101 @@ class save_registrar
{
friend class save_manager;
+ // extended constructor for internal use only
+ save_registrar(save_registrar &parent, save_registered_item::save_type type, uint32_t native_size, char const *name, void *baseptr = nullptr, void *containerbase = nullptr) :
+ m_parent(parent.parent_item().append((baseptr == nullptr) ? 0 : uintptr_t(baseptr) - parent.m_baseptr, type, native_size, name)),
+ m_baseptr((containerbase == nullptr) ? uintptr_t(baseptr) : uintptr_t(containerbase))
+ {
+ }
+
public:
// construct a container within parent
save_registrar(save_registrar &parent, char const *name) :
- m_parent(parent.parent_item().append(0, save_registered_item::TYPE_CONTAINER, 0, name)),
- m_baseptr(0)
+ save_registrar(parent, save_registered_item::TYPE_CONTAINER, 0, name)
{
}
// return a reference to the parent item
save_registered_item &parent_item() const { return m_parent; }
- // enum types
- template<typename T, std::enable_if_t<std::is_enum<T>::value, bool> = true>
- save_registrar &reg(T &data, char const *name) { return register_internal(&data, save_registered_item::TYPE_INT, sizeof(data), name); }
+ // enum types -- these are equivalent to ints of the save size
+ template<typename T>
+ std::enable_if_t<std::is_enum<T>::value, save_registrar> &reg(T &data, char const *name)
+ {
+ return register_internal(&data, save_registered_item::TYPE_INT, sizeof(data), name);
+ }
// signed integral types
- template<typename T, std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, bool> = true>
- save_registrar &reg(T &data, char const *name) { return register_internal(&data, save_registered_item::TYPE_INT, sizeof(data), name); }
+ template<typename T>
+ std::enable_if_t<std::is_integral<T>::value && std::is_signed<T>::value, save_registrar> &reg(T &data, char const *name)
+ {
+ return register_internal(&data, save_registered_item::TYPE_INT, sizeof(data), name);
+ }
// unsigned integral types
- template<typename T, std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, bool> = true>
- save_registrar &reg(T &data, char const *name) { return register_internal(&data, save_registered_item::TYPE_UINT, sizeof(data), name); }
+ template<typename T>
+ std::enable_if_t<std::is_integral<T>::value && std::is_unsigned<T>::value, save_registrar> &reg(T &data, char const *name)
+ {
+ return register_internal(&data, save_registered_item::TYPE_UINT, sizeof(data), name);
+ }
// floating-point types
- template<typename T, std::enable_if_t<std::is_floating_point<T>::value, bool> = true>
- save_registrar &reg(T &data, char const *name) { return register_internal(&data, save_registered_item::TYPE_FLOAT, sizeof(data), name); }
+ template<typename T>
+ std::enable_if_t<std::is_floating_point<T>::value, save_registrar> &reg(T &data, char const *name)
+ {
+ return register_internal(&data, save_registered_item::TYPE_FLOAT, sizeof(data), name);
+ }
- // unique_ptrs
+ // unique_ptrs -- these are containers with a single "unique" item within
template<typename T>
- save_registrar &reg(std::unique_ptr<T> &dataptr, char const *name)
+ save_registrar &reg(std::unique_ptr<T> &data, char const *name)
{
- if (dataptr.get() == nullptr)
+ if (data.get() == nullptr)
throw emu_fatalerror("Passed null pointer to save state registration.");
- reg(*dataptr.get(), name);
+
+ save_registrar container(*this, save_registered_item::TYPE_UNIQUE, sizeof(data), "", &data, data.get());
+ container.reg(*data.get(), name);
return *this;
}
- // arrays
+ // arrays -- these are containers with a single item representing the underlying data,
+ // which is replicated across the whole array
template<typename T, std::size_t N>
save_registrar &reg(T (&data)[N], char const *name)
{
- auto &item = m_parent.append(uintptr_t(&data[0]) - m_baseptr, save_registered_item::save_type(N), sizeof(data[0]), name);
- save_registrar sub(item, &data[0]);
- sub.reg(data[0], "");
+ save_registrar container(*this, save_registered_item::save_type(N), sizeof(data[0]), name, &data[0]);
+ container.reg(data[0], "");
return *this;
}
- // vectors
+ // vectors -- these are treated as arrays, with the size coming from the vector
template<typename T>
save_registrar &reg(std::vector<T> &data, char const *name)
{
- auto &item = m_parent.append(uintptr_t(&data[0]) - m_baseptr, save_registered_item::save_type(data.size()), sizeof(data[0]), name);
- save_registrar sub(item, &data[0]);
- sub.reg(data[0], "");
+ // skip if nothing
+ if (data.size() == 0)
+ return *this;
+
+ // create an outer container for the vector
+ save_registrar container(*this, save_registered_item::TYPE_VECTOR, sizeof(data), "", &data, &data[0]);
+
+ // then an array container within
+ save_registrar subcontainer(container, save_registered_item::save_type(data.size()), sizeof(data[0]), name, &data[0]);
+ subcontainer.reg(data[0], "");
return *this;
}
// unique_ptrs with arrays
template<typename T>
- save_registrar &reg(std::unique_ptr<T[]> &dataptr, char const *name, std::size_t count)
+ save_registrar &reg(std::unique_ptr<T[]> &data, char const *name, std::size_t count)
{
- if (dataptr.get() == nullptr)
+ if (data.get() == nullptr)
throw emu_fatalerror("Passed null pointer to save state registration.");
- reg(dataptr.get(), name, count);
+
+ save_registrar container(*this, save_registered_item::TYPE_UNIQUE, sizeof(data), "", &data, &data[0]);
+
+ save_registrar subcontainer(container, save_registered_item::save_type(count), sizeof(data[0]), name, &data[0]);
+ subcontainer.reg(data[0], "");
return *this;
}
@@ -216,9 +254,9 @@ public:
{
if (dataptr == nullptr)
throw emu_fatalerror("Passed null pointer to save state registration.");
- auto &item = m_parent.append(uintptr_t(dataptr) - m_baseptr, save_registered_item::save_type(sizeof(*dataptr) * count), sizeof(*dataptr), name);
- save_registrar sub(item, dataptr);
- sub.reg(dataptr[0], "");
+
+ save_registrar container(*this, save_registered_item::save_type(count), sizeof(dataptr), name, &dataptr, dataptr);
+ container.reg(dataptr[0], "");
return *this;
}
@@ -226,9 +264,8 @@ public:
template<typename T, std::enable_if_t<std::is_class<T>::value, bool> = true>
save_registrar &reg(T &data, char const *name)
{
- auto &item = m_parent.append(uintptr_t(&data) - m_baseptr, save_registered_item::TYPE_STRUCT, sizeof(data), name);
- save_registrar sub(item, &data);
- data.register_save(sub);
+ save_registrar container(*this, save_registered_item::TYPE_STRUCT, sizeof(data), name, &data);
+ data.register_save(container);
return *this;
}
@@ -344,7 +381,7 @@ public:
// getters
running_machine &machine() const { return m_machine; }
rewinder *rewind() { return m_rewind.get(); }
- int registration_count() const { return m_entry_list.size(); }
+ int registration_count() const { return m_entry_list.size() + m_root_item.compute_binary_size(); }
bool registration_allowed() const { return m_reg_allowed; }
// registration control
diff --git a/src/emu/tilemap.h b/src/emu/tilemap.h
index 31f817bd42d..de917efc2fb 100644
--- a/src/emu/tilemap.h
+++ b/src/emu/tilemap.h
@@ -663,9 +663,7 @@ public:
// register for saves
void register_save(save_registrar &save)
{
- int index = 0;
- for (auto &tmap : m_tilemap_list)
- save.reg(tmap, string_format("%d", index++).c_str());
+ save.reg(NAME(m_tilemap_list));
}
private:
@@ -784,7 +782,7 @@ protected:
virtual void device_start() override;
// register for save states
- void device_register_save(save_registrar &save) override
+ virtual void device_register_save(save_registrar &save) override
{
save.reg(*static_cast<tilemap_t *>(this), "tilemap");
}