diff options
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 |
commit | 902cce39106ed1f7c181c46c491f2c9e3b9a199d (patch) | |
tree | 9ea33245c216aab54beb94251f00846a5a37d423 | |
parent | b8c568b279f9ebaedac014d51eb48ed9b530566a (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.cpp | 45 | ||||
-rw-r--r-- | src/devices/sound/namco.h | 16 | ||||
-rw-r--r-- | src/devices/sound/ym2151.cpp | 17 | ||||
-rw-r--r-- | src/devices/sound/ym2151.h | 1 | ||||
-rw-r--r-- | src/devices/sound/ymfm.cpp | 121 | ||||
-rw-r--r-- | src/devices/sound/ymfm.h | 17 | ||||
-rw-r--r-- | src/emu/device.cpp | 29 | ||||
-rw-r--r-- | src/emu/device.h | 1 | ||||
-rw-r--r-- | src/emu/save.cpp | 72 | ||||
-rw-r--r-- | src/emu/save.h | 123 | ||||
-rw-r--r-- | src/emu/tilemap.h | 6 |
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 ®(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> ®(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 ®(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> ®(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 ®(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> ®(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 ®(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> ®(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 ®(std::unique_ptr<T> &dataptr, char const *name) + save_registrar ®(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 ®(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 ®(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 ®(std::unique_ptr<T[]> &dataptr, char const *name, std::size_t count) + save_registrar ®(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 ®(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"); } |