diff options
| author | 2021-04-19 10:57:25 -0700 | |
|---|---|---|
| committer | 2021-04-19 10:57:25 -0700 | |
| commit | 9394ff0593f142ad1ebf439052c3b57e19edd0fd (patch) | |
| tree | 4f3aeeb1e12d1af0c2828b5a572a3afee4a94232 | |
| parent | eac508c0c5cb6b2da59603094e154776b944e99e (diff) | |
Detect array members that can't be replicated and manually register each item instead. Remove old ALLOW_SAVE_TYPE now that enums are implicitly supported. Add stricter checking of endpoint offsets. Some other cleanups.
49 files changed, 430 insertions, 464 deletions
diff --git a/src/devices/bus/pc_kbd/hle_mouse.cpp b/src/devices/bus/pc_kbd/hle_mouse.cpp index 9cb96f94983..b1e0d829ec0 100644 --- a/src/devices/bus/pc_kbd/hle_mouse.cpp +++ b/src/devices/bus/pc_kbd/hle_mouse.cpp @@ -49,8 +49,6 @@ DEFINE_DEVICE_TYPE(HLE_PS2_MOUSE, hle_ps2_mouse_device, "hle_ps2_mouse", "HLE PS/2 Mouse") -ALLOW_SAVE_TYPE(hle_ps2_mouse_device::serial_state); - INPUT_PORTS_START(hle_ps2_mouse_device) PORT_START("mouse_x_axis") PORT_BIT(0xffff, 0, IPT_MOUSE_X) PORT_SENSITIVITY(100) diff --git a/src/devices/cpu/bcp/dp8344.cpp b/src/devices/cpu/bcp/dp8344.cpp index 3e78cb0d0dd..9fd361e8256 100644 --- a/src/devices/cpu/bcp/dp8344.cpp +++ b/src/devices/cpu/bcp/dp8344.cpp @@ -56,8 +56,6 @@ DEFINE_DEVICE_TYPE(DP8344B, dp8344b_device, "dp8344b", "National Semiconductor D // DEVICE CONSTRUCTION AND INITIALIZATION //************************************************************************** -ALLOW_SAVE_TYPE(dp8344_device::inst_state); - //------------------------------------------------- // dp8344_device - constructor //------------------------------------------------- diff --git a/src/devices/cpu/cosmac/cosmac.cpp b/src/devices/cpu/cosmac/cosmac.cpp index 978c4e76fc8..2160f45317a 100644 --- a/src/devices/cpu/cosmac/cosmac.cpp +++ b/src/devices/cpu/cosmac/cosmac.cpp @@ -20,10 +20,6 @@ TODO: #include "cosmac.h" #include "coreutil.h" -// permit our enums to be saved -ALLOW_SAVE_TYPE(cosmac_device::cosmac_mode); -ALLOW_SAVE_TYPE(cosmac_device::cosmac_state); - //************************************************************************** // CONSTANTS diff --git a/src/devices/cpu/dsp16/dsp16.cpp b/src/devices/cpu/dsp16/dsp16.cpp index d7da812acf2..beb7809106d 100644 --- a/src/devices/cpu/dsp16/dsp16.cpp +++ b/src/devices/cpu/dsp16/dsp16.cpp @@ -111,11 +111,6 @@ DEFINE_DEVICE_TYPE(DSP16A, dsp16a_device, "dsp16a", "WE|AT&T DSP16A") DSP16 SERIES BASE IMPLEMENTATION ***************************************************************************/ -ALLOW_SAVE_TYPE(dsp16_device_base::cache); -ALLOW_SAVE_TYPE(dsp16_device_base::phase); -ALLOW_SAVE_TYPE(dsp16_device_base::flags); -ALLOW_SAVE_TYPE(dsp16_device_base::sio_flags); - WRITE_LINE_MEMBER(dsp16_device_base::exm_w) { if (bool(state) != bool(m_exm_in)) diff --git a/src/devices/cpu/mcs40/mcs40.cpp b/src/devices/cpu/mcs40/mcs40.cpp index 969f08c4197..7665967fd8d 100644 --- a/src/devices/cpu/mcs40/mcs40.cpp +++ b/src/devices/cpu/mcs40/mcs40.cpp @@ -73,11 +73,6 @@ DEFINE_DEVICE_TYPE(I4004, i4004_cpu_device, "i4004", "Intel 4004") DEFINE_DEVICE_TYPE(I4040, i4040_cpu_device, "i4040", "Intel 4040") -ALLOW_SAVE_TYPE(mcs40_cpu_device_base::cycle); -ALLOW_SAVE_TYPE(mcs40_cpu_device_base::pmem); -ALLOW_SAVE_TYPE(mcs40_cpu_device_base::phase); - - static constexpr u8 f_cm_ram_table[8] = { 0x0eU, 0x0dU, 0x0bU, 0x07U, 0x09U, 0x05U, 0x03U, 0x01U }; diff --git a/src/devices/cpu/mips/mips1.cpp b/src/devices/cpu/mips/mips1.cpp index c5f18b2989e..a35030b3728 100644 --- a/src/devices/cpu/mips/mips1.cpp +++ b/src/devices/cpu/mips/mips1.cpp @@ -54,8 +54,6 @@ DEFINE_DEVICE_TYPE(R3071, r3071_device, "r3071", "IDT R3071") DEFINE_DEVICE_TYPE(R3081, r3081_device, "r3081", "IDT R3081") DEFINE_DEVICE_TYPE(SONYPS2_IOP, iop_device, "sonyiop", "Sony Playstation 2 IOP") -ALLOW_SAVE_TYPE(mips1core_device_base::branch_state); - mips1core_device_base::mips1core_device_base(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, u32 cpurev, size_t icache_size, size_t dcache_size) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config_be("program", ENDIANNESS_BIG, 32, 32) diff --git a/src/devices/cpu/pace/pace.cpp b/src/devices/cpu/pace/pace.cpp index 2bfba2cc338..ec01b564e68 100644 --- a/src/devices/cpu/pace/pace.cpp +++ b/src/devices/cpu/pace/pace.cpp @@ -56,8 +56,6 @@ DEFINE_DEVICE_TYPE(INS8900, ins8900_device, "ins8900", "National Semiconductor I // DEVICE CONSTRUCTION AND INITIALIZATION //************************************************************************** -ALLOW_SAVE_TYPE(pace_device::cycle); - //------------------------------------------------- // pace_device - constructor //------------------------------------------------- diff --git a/src/devices/cpu/pic17/pic17.cpp b/src/devices/cpu/pic17/pic17.cpp index 99dff413d54..6d46ce3af49 100644 --- a/src/devices/cpu/pic17/pic17.cpp +++ b/src/devices/cpu/pic17/pic17.cpp @@ -62,8 +62,6 @@ #include "pic17.h" #include "pic17d.h" -ALLOW_SAVE_TYPE(pic17_cpu_device::exec_phase); - pic17_cpu_device::pic17_cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u16 rom_size, address_map_constructor data_map) : cpu_device(mconfig, type, tag, owner, clock) , m_program_config("program", ENDIANNESS_LITTLE, 16, 16, -1, address_map_constructor(FUNC(pic17_cpu_device::program_map), this)) diff --git a/src/devices/cpu/rii/riscii.cpp b/src/devices/cpu/rii/riscii.cpp index 804280dc6e1..d3f9baa068d 100644 --- a/src/devices/cpu/rii/riscii.cpp +++ b/src/devices/cpu/rii/riscii.cpp @@ -25,8 +25,6 @@ // device type definitions DEFINE_DEVICE_TYPE(EPG3231, epg3231_device, "epg3231", "Elan ePG3231") -ALLOW_SAVE_TYPE(riscii_series_device::exec_state); - //************************************************************************** // DEVICE CONSTRUCTION AND INITIALIZATION diff --git a/src/devices/cpu/romp/romp.cpp b/src/devices/cpu/romp/romp.cpp index d68988cb876..8109d2b4fb3 100644 --- a/src/devices/cpu/romp/romp.cpp +++ b/src/devices/cpu/romp/romp.cpp @@ -31,8 +31,6 @@ DEFINE_DEVICE_TYPE(ROMP, romp_device, "romp", "IBM ROMP") -ALLOW_SAVE_TYPE(romp_device::branch_state); - romp_device::romp_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : cpu_device(mconfig, ROMP, tag, owner, clock) , m_mem_config("memory", ENDIANNESS_BIG, 32, 32) diff --git a/src/devices/cpu/tlcs90/tlcs90.cpp b/src/devices/cpu/tlcs90/tlcs90.cpp index bd02b9cc197..e90c204d97d 100644 --- a/src/devices/cpu/tlcs90/tlcs90.cpp +++ b/src/devices/cpu/tlcs90/tlcs90.cpp @@ -17,8 +17,6 @@ #include "tlcs90.h" #include "tlcs90d.h" -ALLOW_SAVE_TYPE(tlcs90_device::e_mode); // allow save_item on a non-fundamental type - DEFINE_DEVICE_TYPE(TMP90840, tmp90840_device, "tmp90840", "Toshiba TMP90840") DEFINE_DEVICE_TYPE(TMP90841, tmp90841_device, "tmp90841", "Toshiba TMP90841") diff --git a/src/devices/cpu/vt61/vt61.cpp b/src/devices/cpu/vt61/vt61.cpp index 216187e0a55..2fb0378c48a 100644 --- a/src/devices/cpu/vt61/vt61.cpp +++ b/src/devices/cpu/vt61/vt61.cpp @@ -15,9 +15,6 @@ // device type definition DEFINE_DEVICE_TYPE(VT61_CPU, vt61_cpu_device, "vt61_cpu", "DEC VT61 CPU") -ALLOW_SAVE_TYPE(vt61_cpu_device::state); -ALLOW_SAVE_TYPE(vt61_cpu_device::pc_mode); - vt61_cpu_device::vt61_cpu_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : cpu_device(mconfig, VT61_CPU, tag, owner, clock) , m_program_config("microprogram", ENDIANNESS_LITTLE, 16, 10, -1) diff --git a/src/devices/machine/28fxxx.cpp b/src/devices/machine/28fxxx.cpp index e434a761c46..2e28a718ded 100644 --- a/src/devices/machine/28fxxx.cpp +++ b/src/devices/machine/28fxxx.cpp @@ -46,8 +46,6 @@ DEFINE_DEVICE_TYPE(INTEL_28F010, intel_28f010_device, "intel_28f010", "Intel 28F DEFINE_DEVICE_TYPE(AMD_28F010, amd_28f010_device, "amd_28f010", "Am28F010 1 Megabit (128K x 8-Bit) CMOS 12.0 Volt, Bulk Erase Flash Memory") DEFINE_DEVICE_TYPE(AMD_28F020, amd_28f020_device, "amd_28f020", "Am28F020 2 Megabit (256K x 8-Bit) CMOS 12.0 Volt, Bulk Erase Flash Memory") -ALLOW_SAVE_TYPE(base_28fxxx_device::state); - base_28fxxx_device::base_28fxxx_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock, u32 size, u8 manufacturer_code, u8 device_code) : device_t(mconfig, type, tag, owner, clock) , device_nvram_interface(mconfig, *this) diff --git a/src/devices/machine/adc0804.cpp b/src/devices/machine/adc0804.cpp index 048b99734b6..7d6e8d358d7 100644 --- a/src/devices/machine/adc0804.cpp +++ b/src/devices/machine/adc0804.cpp @@ -46,8 +46,6 @@ DEFINE_DEVICE_TYPE(ADC0803, adc0803_device, "adc0803", "ADC0803 A/D Converter") DEFINE_DEVICE_TYPE(ADC0804, adc0804_device, "adc0804", "ADC0804 A/D Converter") -ALLOW_SAVE_TYPE(adc0804_device::read_mode); - //************************************************************************** // DEVICE CONSTRUCTION AND INITIALIZATION diff --git a/src/devices/machine/adc0808.cpp b/src/devices/machine/adc0808.cpp index 3988254dc71..f7a0f6ee53b 100644 --- a/src/devices/machine/adc0808.cpp +++ b/src/devices/machine/adc0808.cpp @@ -32,9 +32,6 @@ DEFINE_DEVICE_TYPE(M58990, m58990_device, "m58990", "M58990 A/D Converter") // LIVE DEVICE //************************************************************************** -// permit our enum to be saved -ALLOW_SAVE_TYPE(adc0808_device::state); - //------------------------------------------------- // adc0808_device - constructor //------------------------------------------------- diff --git a/src/devices/machine/ay31015.h b/src/devices/machine/ay31015.h index 4e27bc8e11f..748bda40227 100644 --- a/src/devices/machine/ay31015.h +++ b/src/devices/machine/ay31015.h @@ -164,8 +164,6 @@ protected: }; -ALLOW_SAVE_TYPE(ay31015_device::state_t); - DECLARE_DEVICE_TYPE(AY31015, ay31015_device) // For AY-3-1014A, AY-3-1015(D) and HD6402 variants DECLARE_DEVICE_TYPE(AY51013, ay51013_device) // For AY-3-1014, AY-5-1013 and AY-6-1013 variants diff --git a/src/devices/machine/cxd1185.cpp b/src/devices/machine/cxd1185.cpp index b599d307783..36fe299010d 100644 --- a/src/devices/machine/cxd1185.cpp +++ b/src/devices/machine/cxd1185.cpp @@ -41,8 +41,6 @@ static unsigned const SCSI_BUS_SETTLE = 400; static unsigned const SCSI_BUS_SKEW = 10; static unsigned const SCSI_RST_HOLD = 25'000; -ALLOW_SAVE_TYPE(cxd1185_device::state); - cxd1185_device::cxd1185_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) : nscsi_device(mconfig, CXD1185, tag, owner, clock) , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF) diff --git a/src/devices/machine/ds1315.h b/src/devices/machine/ds1315.h index 720c4a08202..95232eeb926 100644 --- a/src/devices/machine/ds1315.h +++ b/src/devices/machine/ds1315.h @@ -58,8 +58,6 @@ private: uint8_t m_raw_data[8*8]; }; -ALLOW_SAVE_TYPE(ds1315_device::mode_t); - DECLARE_DEVICE_TYPE(DS1315, ds1315_device) #endif // MAME_MACHINE_DS1315_H diff --git a/src/devices/machine/eepromser.cpp b/src/devices/machine/eepromser.cpp index a8502e72fe3..33060eb30e8 100644 --- a/src/devices/machine/eepromser.cpp +++ b/src/devices/machine/eepromser.cpp @@ -139,15 +139,6 @@ //************************************************************************** -// TYPE DEFINITIONS -//************************************************************************** - -ALLOW_SAVE_TYPE(eeprom_serial_base_device::eeprom_command); -ALLOW_SAVE_TYPE(eeprom_serial_base_device::eeprom_state); - - - -//************************************************************************** // BASE DEVICE IMPLEMENTATION //************************************************************************** diff --git a/src/devices/machine/i82586.cpp b/src/devices/machine/i82586.cpp index 7dfc6272435..d543a019d7d 100644 --- a/src/devices/machine/i82586.cpp +++ b/src/devices/machine/i82586.cpp @@ -42,9 +42,6 @@ #include "logmacro.h" -ALLOW_SAVE_TYPE(i82586_base_device::cu_state); -ALLOW_SAVE_TYPE(i82586_base_device::ru_state); - DEFINE_DEVICE_TYPE(I82586, i82586_device, "i82586", "Intel 82586 IEEE 802.3 Ethernet LAN Coprocessor") DEFINE_DEVICE_TYPE(I82596_LE16, i82596_le16_device, "i82596sx_le", "Intel 82596 SX High-Performance 32-Bit Local Area Network Coprocessor (little)") DEFINE_DEVICE_TYPE(I82596_BE16, i82596_be16_device, "i82596sx_be", "Intel 82596 SX High-Performance 32-Bit Local Area Network Coprocessor (big)") diff --git a/src/devices/machine/i8291a.cpp b/src/devices/machine/i8291a.cpp index 3692ba95a28..8d32baab895 100644 --- a/src/devices/machine/i8291a.cpp +++ b/src/devices/machine/i8291a.cpp @@ -23,19 +23,6 @@ #include "logmacro.h" DEFINE_DEVICE_TYPE(I8291A, i8291a_device, "i8291a", "Intel I8291A GPIB Talker/Listener") -ALLOW_SAVE_TYPE(i8291a_device::listener_state); -ALLOW_SAVE_TYPE(i8291a_device::talker_state); -ALLOW_SAVE_TYPE(i8291a_device::talker_primary_state); -ALLOW_SAVE_TYPE(i8291a_device::listener_primary_state); -ALLOW_SAVE_TYPE(i8291a_device::parallel_poll_state); -ALLOW_SAVE_TYPE(i8291a_device::device_trigger_state); -ALLOW_SAVE_TYPE(i8291a_device::device_clear_state); -ALLOW_SAVE_TYPE(i8291a_device::talker_serial_poll_state); -ALLOW_SAVE_TYPE(i8291a_device::serial_poll_state); -ALLOW_SAVE_TYPE(i8291a_device::remote_local_state); -ALLOW_SAVE_TYPE(i8291a_device::source_handshake_state); -ALLOW_SAVE_TYPE(i8291a_device::acceptor_handshake_state); - i8291a_device::i8291a_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t{mconfig, I8291A, tag, owner, clock}, diff --git a/src/devices/machine/m3002.cpp b/src/devices/machine/m3002.cpp index fd93666a55f..3414346e8ad 100644 --- a/src/devices/machine/m3002.cpp +++ b/src/devices/machine/m3002.cpp @@ -28,8 +28,6 @@ DEFINE_DEVICE_TYPE(M3000, m3000_device, "m3000", "EM M 3000 Real Time Clock") // DEVICE CONSTRUCTION AND INITIALIZATION //************************************************************************** -ALLOW_SAVE_TYPE(m3002_device::mux_state); - //------------------------------------------------- // m3002_device - constructor //------------------------------------------------- diff --git a/src/devices/machine/ncr5380n.cpp b/src/devices/machine/ncr5380n.cpp index a74b744f9da..f2a22f34c9e 100644 --- a/src/devices/machine/ncr5380n.cpp +++ b/src/devices/machine/ncr5380n.cpp @@ -29,8 +29,6 @@ DEFINE_DEVICE_TYPE(NCR5380N, ncr5380n_device, "ncr5380_new", "NCR 5380 SCSI (new DEFINE_DEVICE_TYPE(NCR53C80, ncr53c80_device, "ncr53c80", "NCR 53C80 SCSI") DEFINE_DEVICE_TYPE(CXD1180, cxd1180_device, "cxd1180", "Sony CXD1180") -ALLOW_SAVE_TYPE(ncr5380n_device::state); - ncr5380n_device::ncr5380n_device(machine_config const &mconfig, device_type type, char const *tag, device_t *owner, u32 clock, bool has_lbs) : nscsi_device(mconfig, type, tag, owner, clock) , nscsi_slot_card_interface(mconfig, *this, DEVICE_SELF) diff --git a/src/devices/machine/pic8259.cpp b/src/devices/machine/pic8259.cpp index d5104413691..a1a6a67448e 100644 --- a/src/devices/machine/pic8259.cpp +++ b/src/devices/machine/pic8259.cpp @@ -27,8 +27,6 @@ #define LOGOCW(...) LOGMASKED(LOG_OCW, __VA_ARGS__) -ALLOW_SAVE_TYPE(pic8259_device::state_t); // allow save_item on a non-fundamental type - void pic8259_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr) { /* check the various IRQs */ diff --git a/src/devices/machine/rtc9701.cpp b/src/devices/machine/rtc9701.cpp index a8ccc5cec7f..8cbf5e4066a 100644 --- a/src/devices/machine/rtc9701.cpp +++ b/src/devices/machine/rtc9701.cpp @@ -15,9 +15,6 @@ #include "machine/rtc9701.h" -ALLOW_SAVE_TYPE(rtc9701_device::state_t); - - //************************************************************************** // GLOBAL VARIABLES //************************************************************************** diff --git a/src/devices/machine/scn_pci.cpp b/src/devices/machine/scn_pci.cpp index 73ef2590e66..91142db8132 100644 --- a/src/devices/machine/scn_pci.cpp +++ b/src/devices/machine/scn_pci.cpp @@ -150,9 +150,6 @@ const u16 scn2641_device::s_br_divisors[16] = { // DEVICE CONSTRUCTION & INITIALIZATION //************************************************************************** -ALLOW_SAVE_TYPE(scn_pci_device::rcvr_state); -ALLOW_SAVE_TYPE(scn_pci_device::xmtr_state); - //------------------------------------------------- // scn_pci_device - constructor //------------------------------------------------- diff --git a/src/devices/machine/serflash.cpp b/src/devices/machine/serflash.cpp index c616b4d34a7..5ea6c22292b 100644 --- a/src/devices/machine/serflash.cpp +++ b/src/devices/machine/serflash.cpp @@ -10,8 +10,6 @@ #include <algorithm> -ALLOW_SAVE_TYPE(serflash_device::flash_state_t); - //************************************************************************** // LIVE DEVICE //************************************************************************** diff --git a/src/devices/machine/upd7004.cpp b/src/devices/machine/upd7004.cpp index e3cfb911864..f49a0b84eb3 100644 --- a/src/devices/machine/upd7004.cpp +++ b/src/devices/machine/upd7004.cpp @@ -25,9 +25,6 @@ DEFINE_DEVICE_TYPE(UPD7004, upd7004_device, "upd7004", "UPD7004 A/D Converter") -// permit our enum to be saved -ALLOW_SAVE_TYPE(upd7004_device::state); - //************************************************************************** // LIVE DEVICE diff --git a/src/devices/machine/wtl3132.cpp b/src/devices/machine/wtl3132.cpp index 3b82466529e..d7a5fec6478 100644 --- a/src/devices/machine/wtl3132.cpp +++ b/src/devices/machine/wtl3132.cpp @@ -24,7 +24,6 @@ //#define VERBOSE (LOG_GENERAL|LOG_REGS|LOG_IO|LOG_BYPASS) #include "logmacro.h" -ALLOW_SAVE_TYPE(float32_t); SAVE_TYPE_AS_FLOAT(float32_t); // helper for extracting opcode fields diff --git a/src/devices/sound/flt_biquad.cpp b/src/devices/sound/flt_biquad.cpp index 659c8a5cd29..665c2531724 100644 --- a/src/devices/sound/flt_biquad.cpp +++ b/src/devices/sound/flt_biquad.cpp @@ -33,9 +33,6 @@ // device type definition DEFINE_DEVICE_TYPE(FILTER_BIQUAD, filter_biquad_device, "filter_biquad", "Biquad Filter") -// allow the enum class for the biquad filter type to be saved by the savestate system -ALLOW_SAVE_TYPE(filter_biquad_device::biquad_type); - //************************************************************************** // LIVE DEVICE //************************************************************************** diff --git a/src/devices/sound/mas3507d.cpp b/src/devices/sound/mas3507d.cpp index c2b50088d11..de21090cd1e 100644 --- a/src/devices/sound/mas3507d.cpp +++ b/src/devices/sound/mas3507d.cpp @@ -31,11 +31,6 @@ #define LOGCONFIG(...) LOGMASKED(LOG_CONFIG, __VA_ARGS__) #define LOGOTHER(...) LOGMASKED(LOG_OTHER, __VA_ARGS__) -ALLOW_SAVE_TYPE(mas3507d_device::i2c_bus_state_t) -ALLOW_SAVE_TYPE(mas3507d_device::i2c_bus_address_t) -ALLOW_SAVE_TYPE(mas3507d_device::i2c_subdest_t) -ALLOW_SAVE_TYPE(mas3507d_device::i2c_command_t) - // device type definition DEFINE_DEVICE_TYPE(MAS3507D, mas3507d_device, "mas3507d", "MAS 3507D MPEG decoder") diff --git a/src/devices/sound/mea8000.cpp b/src/devices/sound/mea8000.cpp index 3cf2ad51a6e..b2a468bddb4 100644 --- a/src/devices/sound/mea8000.cpp +++ b/src/devices/sound/mea8000.cpp @@ -39,9 +39,6 @@ /******************* utilitiy function and macros ********************/ -ALLOW_SAVE_TYPE( mea8000_device::mea8000_state ); - - /* digital filters work at 8 kHz */ #define F0 (clock() / 480) diff --git a/src/devices/sound/multipcm.cpp b/src/devices/sound/multipcm.cpp index 7243340c9fe..e6c76e923c9 100644 --- a/src/devices/sound/multipcm.cpp +++ b/src/devices/sound/multipcm.cpp @@ -38,7 +38,6 @@ #include "multipcm.h" #include "wavwrite.h" -ALLOW_SAVE_TYPE(multipcm_device::state_t); // allow save_item on a non-fundamental type /******************************* ENVELOPE SECTION diff --git a/src/devices/sound/s14001a.cpp b/src/devices/sound/s14001a.cpp index 50f2ca07eaa..b1338699173 100644 --- a/src/devices/sound/s14001a.cpp +++ b/src/devices/sound/s14001a.cpp @@ -210,8 +210,6 @@ s14001a_device::s14001a_device(const machine_config &mconfig, const char *tag, d // device_start - device-specific startup //------------------------------------------------- -ALLOW_SAVE_TYPE(s14001a_device::states); // allow save_item on a non-fundamental type - void s14001a_device::device_start() { m_stream = stream_alloc(0, 1, clock() ? clock() : machine().sample_rate()); diff --git a/src/devices/sound/s_dsp.cpp b/src/devices/sound/s_dsp.cpp index 98cd204b503..6da6d3c4a60 100644 --- a/src/devices/sound/s_dsp.cpp +++ b/src/devices/sound/s_dsp.cpp @@ -135,9 +135,6 @@ static const int ENVCNT[0x20] }; -ALLOW_SAVE_TYPE(s_dsp_device::env_state_t32); - - DEFINE_DEVICE_TYPE(S_DSP, s_dsp_device, "s_dsp", "Nintendo/Sony S-DSP") diff --git a/src/devices/video/huc6270.cpp b/src/devices/video/huc6270.cpp index 09f49963ba9..e384d53932e 100644 --- a/src/devices/video/huc6270.cpp +++ b/src/devices/video/huc6270.cpp @@ -80,9 +80,6 @@ enum { DVSSR = 0x13 }; -ALLOW_SAVE_TYPE(huc6270_device::v_state); -ALLOW_SAVE_TYPE(huc6270_device::h_state); - /* Bits in the VDC status register */ #define HUC6270_BSY 0x40 /* Set when the VDC accesses VRAM */ diff --git a/src/devices/video/t6963c.cpp b/src/devices/video/t6963c.cpp index a853e6d7b00..3d3f85c0945 100644 --- a/src/devices/video/t6963c.cpp +++ b/src/devices/video/t6963c.cpp @@ -26,8 +26,6 @@ DEFINE_DEVICE_TYPE(LM24014H, lm24014h_device, "lm24014h", "LM24014H LCD Unit (24 // T6963C LCD CONTROLLER //************************************************************************** -ALLOW_SAVE_TYPE(t6963c_device::auto_mode); - //------------------------------------------------- // t6963c_device - constructor //------------------------------------------------- diff --git a/src/devices/video/tms3556.cpp b/src/devices/video/tms3556.cpp index 3088e02e685..688d41466d0 100644 --- a/src/devices/video/tms3556.cpp +++ b/src/devices/video/tms3556.cpp @@ -44,8 +44,6 @@ #define VDP_BAGC3 m_address_regs[6] #define VDP_BAMTF m_address_regs[7] -ALLOW_SAVE_TYPE(tms3556_device::dma_mode_tt); - //************************************************************************** diff --git a/src/emu/debug/dvsave.cpp b/src/emu/debug/dvsave.cpp index 67fc5707a97..efea78a58c4 100644 --- a/src/emu/debug/dvsave.cpp +++ b/src/emu/debug/dvsave.cpp @@ -60,7 +60,7 @@ void debug_view_save::reset() void debug_view_save::build_list_recursive(save_registered_item &item, uintptr_t objbase, int depth, int count) { // update the base pointer and forward if a trivial unwrap - if (item.unwrap_and_update_objbase(objbase)) + if (item.unwrap_and_update_base(objbase)) return build_list_recursive(item.subitems().front(), objbase, depth, count); // switch off the type @@ -85,27 +85,35 @@ void debug_view_save::build_list_recursive(save_registered_item &item, uintptr_t break; // arrays are multiples of a single item - default: - if (m_type < save_registered_item::TYPE_ARRAY) + case save_registered_item::TYPE_STATIC_ARRAY: + case save_registered_item::TYPE_RUNTIME_ARRAY: + { + m_save_list.push_back(save_item(item, objbase, depth, count)); + auto subitem = item.subitems().begin(); + auto last = std::prev(item.subitems().end()); + int items_per_row = 1; + if (subitem == last) { - m_save_list.push_back(save_item(item, objbase, depth, count)); - auto &subitem = item.subitems().front(); - int items_per_row = 1; - if (subitem.type() == save_registered_item::TYPE_BOOL) + if (subitem->type() == save_registered_item::TYPE_BOOL) items_per_row = 32; - else if (subitem.type() == save_registered_item::TYPE_INT || subitem.type() == save_registered_item::TYPE_UINT) + else if (subitem->is_int()) { - if (subitem.native_size() <= 2) - items_per_row = 16 / subitem.native_size(); + if (subitem->native_size() <= 2) + items_per_row = 16 / subitem->native_size(); else - items_per_row = 32 / subitem.native_size(); + items_per_row = 32 / subitem->native_size(); } - else if (subitem.type() == save_registered_item::TYPE_FLOAT) + else if (subitem->type() == save_registered_item::TYPE_FLOAT) items_per_row = 4; - for (uint32_t rep = 0; rep < item.count(); rep += items_per_row) - build_list_recursive(subitem, objbase + rep * item.native_size(), depth + 1, std::min<int>(items_per_row, item.count() - rep)); + } + for (uint32_t rep = 0; rep < item.count(); rep += items_per_row) + { + build_list_recursive(*subitem, objbase + rep * item.native_size(), depth + 1, std::min<int>(items_per_row, item.count() - rep)); + if (subitem != last) + ++subitem; } break; + } } } @@ -293,7 +301,7 @@ std::string debug_view_save::save_item::value() std::string debug_view_save::save_item::value(save_registered_item &item, int count, uintptr_t objbase, bool collapsed) { // update the base pointer and forward if a trivial unwrap - if (item.unwrap_and_update_objbase(objbase)) + if (item.unwrap_and_update_base(objbase)) return value(item.subitems().front(), 0, objbase, collapsed); char tempbuf[256]; @@ -377,25 +385,30 @@ std::string debug_view_save::save_item::value(save_registered_item &item, int co } // arrays are multiples of a single item - default: - if (item.type() < save_registered_item::TYPE_ARRAY) + case save_registered_item::TYPE_STATIC_ARRAY: + case save_registered_item::TYPE_RUNTIME_ARRAY: + { + if (!collapsed) + catprintf(tempbuf, pos, "[%d]", item.count()); + else { - if (!collapsed) - catprintf(tempbuf, pos, "[%d]", item.count()); - else + catprintf(tempbuf, pos, "["); + auto subitem = item.subitems().begin(); + auto last = std::prev(item.subitems().end()); + for (int num = 0; num < item.count(); num++) { - catprintf(tempbuf, pos, "["); - auto &subitem = item.subitems().front(); - for (int num = 0; num < item.count(); num++) - { - std::string val = value(subitem, 0, objbase + num * item.native_size(), true); - if (!catprintf(tempbuf, pos, "%s%s", (num == 0) ? "" : ",", val.c_str())) - break; - } - catprintf(tempbuf, pos, "]"); + std::string val = value(*subitem, 0, objbase + num * item.native_size(), true); + if (!catprintf(tempbuf, pos, "%s%s", (num == 0) ? "" : ",", val.c_str())) + break; + if (subitem != last) + ++subitem; } - return tempbuf; + catprintf(tempbuf, pos, "]"); } + return tempbuf; + } + + default: return "(unknown)"; } } diff --git a/src/emu/debug/dvsave.h b/src/emu/debug/dvsave.h index 9a85aa2c339..0290008789d 100644 --- a/src/emu/debug/dvsave.h +++ b/src/emu/debug/dvsave.h @@ -50,12 +50,7 @@ private: { } - bool collapsible() const - { - return (m_item.type() == save_registered_item::TYPE_CONTAINER || - m_item.type() == save_registered_item::TYPE_STRUCT || - m_item.type() < save_registered_item::TYPE_ARRAY); - } + bool collapsible() const { return (m_item.is_struct_or_container() || m_item.is_array()); } char const *name() const { return m_item.name(); } std::string value(); save_registered_item::save_type type() const { return m_item.type(); } diff --git a/src/emu/machine.cpp b/src/emu/machine.cpp index f57a8624667..7e7952f935e 100644 --- a/src/emu/machine.cpp +++ b/src/emu/machine.cpp @@ -263,7 +263,7 @@ void running_machine::start() save().register_presave(save_prepost_delegate(FUNC(running_machine::presave_all_devices), this)); start_all_devices(); for (device_t &device : device_enumerator(root_device())) - m_save.root_registrar().reg(device, device.tag()); + m_save.root_registrar().reg(device, device.tag(), device.type().size()); save().register_postload(save_prepost_delegate(FUNC(running_machine::postload_all_devices), this)); // save outputs created before start time diff --git a/src/emu/save.cpp b/src/emu/save.cpp index c23b27b0218..26669466746 100644 --- a/src/emu/save.cpp +++ b/src/emu/save.cpp @@ -227,8 +227,8 @@ public: save_zip_state &json_append(char const *buffer); save_zip_state &json_append_indent(int count); save_zip_state &json_append_name(char const *name); - save_zip_state &json_append_signed(int64_t value); - save_zip_state &json_append_unsigned(uint64_t value); + save_zip_state &json_append_signed(s64 value); + save_zip_state &json_append_unsigned(u64 value); save_zip_state &json_append_float(double value); // stage an item to be output as raw data @@ -333,12 +333,12 @@ save_zip_state &save_zip_state::json_append_name(char const *name) // value to the JSON stream //------------------------------------------------- -save_zip_state &save_zip_state::json_append_signed(int64_t value) +save_zip_state &save_zip_state::json_append_signed(s64 value) { json_check_reserve(); // quote values that don't fit into a double - bool quote = (int64_t(double(value)) != value); + bool quote = (s64(double(value)) != value); if (quote) json_append('"'); @@ -359,12 +359,12 @@ save_zip_state &save_zip_state::json_append_signed(int64_t value) // integer value to the JSON stream //------------------------------------------------- -save_zip_state &save_zip_state::json_append_unsigned(uint64_t value) +save_zip_state &save_zip_state::json_append_unsigned(u64 value) { json_check_reserve(); // quote values that don't fit into a double - bool quote = (uint64_t(double(value)) != value); + bool quote = (u64(double(value)) != value); if (quote) json_append('"'); @@ -912,8 +912,8 @@ public: bool json_matches(char target); bool json_matches(char const *target); bool json_parse_number(double &result); - bool json_parse_int_string(int64_t &result); - bool json_parse_uint_string(uint64_t &result); + bool json_parse_int_string(s64 &result); + bool json_parse_uint_string(u64 &result); bool json_parse_string(std::string &result); // initialize, checking the input file basic validity @@ -1031,7 +1031,7 @@ bool load_zip_state::json_parse_number(double &result) // integer from a string //------------------------------------------------- -bool load_zip_state::json_parse_int_string(int64_t &result) +bool load_zip_state::json_parse_int_string(s64 &result) { if (!json_matches('"')) return false; @@ -1046,7 +1046,7 @@ bool load_zip_state::json_parse_int_string(int64_t &result) // integer from a string //------------------------------------------------- -bool load_zip_state::json_parse_uint_string(uint64_t &result) +bool load_zip_state::json_parse_uint_string(u64 &result) { if (!json_matches('"')) return false; @@ -1276,15 +1276,15 @@ bool load_zip_state::read_data_recursive(zlib_read_streamer &zlib, save_register save_registered_item::save_registered_item() : m_ptr_offset(0), - m_type(TYPE_CONTAINER), + m_type_count(TYPE_CONTAINER), m_native_size(0) { } // constructor for a new item -save_registered_item::save_registered_item(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name) : +save_registered_item::save_registered_item(uintptr_t ptr_offset, save_type type, u32 native_size, char const *name, u32 count) : m_ptr_offset(ptr_offset), - m_type(type), + m_type_count(u32(type) | (count << 4)), m_native_size(native_size), m_name(name) { @@ -1300,12 +1300,11 @@ save_registered_item::save_registered_item(uintptr_t ptr_offset, save_type type, // append - append a new item to the current one //------------------------------------------------- -std::string type_string(save_registered_item::save_type type, uint32_t native_size) +std::string type_string(save_registered_item::save_type type, u32 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"; @@ -1317,7 +1316,7 @@ std::string type_string(save_registered_item::save_type type, uint32_t native_si } } -save_registered_item &save_registered_item::append(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name) +save_registered_item &save_registered_item::append(uintptr_t ptr_offset, save_type type, u32 native_size, char const *name, u32 count) { // make sure there are no duplicates if (find(name) != nullptr) @@ -1326,7 +1325,7 @@ save_registered_item &save_registered_item::append(uintptr_t ptr_offset, save_ty //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); // add the item to the back of the list - m_items.emplace_back(ptr_offset, type, native_size, name); + m_items.emplace_back(ptr_offset, type, native_size, name, count); return m_items.back(); } @@ -1350,6 +1349,44 @@ save_registered_item *save_registered_item::find(char const *name) //------------------------------------------------- +// is_replicatable - can this item be replicated +// across an array? +//------------------------------------------------- + +bool save_registered_item::is_replicatable(bool parent_is_array) const +{ + switch (type()) + { + // numeric types are always replicatable + case TYPE_BOOL: + case TYPE_INT: + case TYPE_UINT: + case TYPE_FLOAT: + return true; + + // unique pointers, vectors, and runtime arrays are non-replicatable + case TYPE_UNIQUE: + case TYPE_VECTOR: + case TYPE_RUNTIME_ARRAY: + return false; + + // structs, containers, and static arrays are replicatable if all their owned items are + case TYPE_STATIC_ARRAY: + case TYPE_CONTAINER: + case TYPE_STRUCT: + for (auto &item : m_items) + if (!item.is_replicatable(false)) + return false; + return true; + + // when it doubt, no + default: + return false; + } +} + + +//------------------------------------------------- // sort_and_prune - prune empty subitems and // sort them by name //------------------------------------------------- @@ -1370,7 +1407,7 @@ bool save_registered_item::sort_and_prune() } // then sort the rest if we have more than 1 - if (m_items.size() > 1) + if (is_struct_or_container() && m_items.size() > 1) m_items.sort([] (auto const &x, auto const &y) { return (std::strcmp(x.name(), y.name()) < 0); }); // return true if we have nothing @@ -1379,17 +1416,17 @@ bool save_registered_item::sort_and_prune() //------------------------------------------------- -// unwrap_and_update_objbase - unwrap trivial -// type and update the object base +// unwrap_and_update_base - unwrap special +// types and update the object base //------------------------------------------------- -bool save_registered_item::unwrap_and_update_objbase(uintptr_t &objbase) const +bool save_registered_item::unwrap_and_update_base(uintptr_t &objbase) const { // update the base pointer with our local base/offset objbase += m_ptr_offset; // switch off the type - switch (m_type) + switch (type()) { // unique ptrs retrieve the pointer from their container case TYPE_UNIQUE: @@ -1401,11 +1438,6 @@ bool save_registered_item::unwrap_and_update_objbase(uintptr_t &objbase) const objbase = reinterpret_cast<uintptr_t>(&(*reinterpret_cast<generic_vector *>(objbase))[0]); return true; - // pointers just extract the pointer directly - case TYPE_POINTER: - objbase = reinterpret_cast<uintptr_t>(*reinterpret_cast<generic_pointer *>(objbase)); - return true; - // containers are always based at 0 case TYPE_CONTAINER: objbase = 0; @@ -1423,15 +1455,15 @@ bool save_registered_item::unwrap_and_update_objbase(uintptr_t &objbase) const // items into a binary form //------------------------------------------------- -uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintptr_t objbase) const +u64 save_registered_item::save_binary(u8 *ptr, u64 length, uintptr_t objbase) const { - // update the base pointer and forward if a trivial unwrap - if (unwrap_and_update_objbase(objbase)) + // update the base pointer and forward if a special unwrap + if (unwrap_and_update_base(objbase)) return m_items.front().save_binary(ptr, length, objbase); // switch off the type - uint64_t offset = 0; - switch (m_type) + u64 offset = 0; + switch (type()) { // boolean types save as a single byte case TYPE_BOOL: @@ -1457,14 +1489,19 @@ uint64_t save_registered_item::save_binary(uint8_t *ptr, uint64_t length, uintpt break; // arrays are multiples of a single item - default: - if (is_array()) + case TYPE_STATIC_ARRAY: + case TYPE_RUNTIME_ARRAY: + { + auto item = m_items.begin(); + auto last = std::prev(m_items.end()); + for (u32 rep = 0; rep < count(); rep++) { - auto &item = m_items.front(); - for (uint32_t rep = 0; rep < m_type; rep++) - offset += item.save_binary(&ptr[offset], (offset < length) ? length - offset : 0, objbase + rep * m_native_size); + offset += item->save_binary(&ptr[offset], (offset < length) ? length - offset : 0, objbase + rep * m_native_size); + if (item != last) + ++item; } break; + } } return offset; } @@ -1475,15 +1512,15 @@ 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) const +u64 save_registered_item::restore_binary(u8 const *ptr, u64 length, uintptr_t objbase) const { // update the base pointer and forward if a trivial unwrap - if (unwrap_and_update_objbase(objbase)) + if (unwrap_and_update_base(objbase)) return m_items.front().restore_binary(ptr, length, objbase); // switch off the type - uint64_t offset = 0; - switch (m_type) + u64 offset = 0; + switch (type()) { // boolean types save as a single byte case TYPE_BOOL: @@ -1509,14 +1546,19 @@ uint64_t save_registered_item::restore_binary(uint8_t const *ptr, uint64_t lengt break; // arrays are multiples of a single item - default: - if (is_array()) + case TYPE_STATIC_ARRAY: + case TYPE_RUNTIME_ARRAY: + { + auto item = m_items.begin(); + auto last = std::prev(m_items.end()); + for (u32 rep = 0; rep < count(); rep++) { - auto &item = m_items.front(); - for (uint32_t rep = 0; rep < m_type; rep++) - offset += item.restore_binary(&ptr[offset], (offset < length) ? length - offset : 0, objbase + rep * m_native_size); + offset += item->restore_binary(&ptr[offset], (offset < length) ? length - offset : 0, objbase + rep * m_native_size); + if (item != last) + ++item; } break; + } } return offset; } @@ -1529,7 +1571,7 @@ uint64_t save_registered_item::restore_binary(uint8_t const *ptr, uint64_t lengt void save_registered_item::save_json(save_zip_state &zipstate, char const *nameprefix, int indent, bool inline_form, uintptr_t objbase) { // update the base pointer and forward if a trivial unwrap - if (unwrap_and_update_objbase(objbase)) + if (unwrap_and_update_base(objbase)) return m_items.front().save_json(zipstate, nameprefix, indent, inline_form, objbase); // update the name prefix @@ -1545,7 +1587,7 @@ void save_registered_item::save_json(save_zip_state &zipstate, char const *namep zipstate.json_append_name(m_name.c_str()); // switch off the type - switch (m_type) + switch (type()) { // boolean types case TYPE_BOOL: @@ -1599,75 +1641,75 @@ void save_registered_item::save_json(save_zip_state &zipstate, char const *namep break; // arrays are multiples of a single item - default: - if (is_array()) + case TYPE_STATIC_ARRAY: + case TYPE_RUNTIME_ARRAY: + { + // look for large arrays of ints/floats + u32 total, unitsize; + if (is_endpoint_array(total, unitsize) && total * unitsize >= save_zip_state::JSON_EXTERNAL_BINARY_THRESHOLD) { - auto &item = m_items.front(); + char const *filename = zipstate.add_data_file(localname.c_str(), *this, objbase); + + zipstate.json_append('[').json_append('{'); + zipstate.json_append_name("external_file"); + zipstate.json_append('"').json_append(filename).json_append('"').json_append(','); + zipstate.json_append_name("unit"); + zipstate.json_append_signed(unitsize).json_append(','); + zipstate.json_append_name("count"); + zipstate.json_append_signed(total).json_append(','); + zipstate.json_append_name("little_endian"); + zipstate.json_append((ENDIANNESS_NATIVE == ENDIANNESS_LITTLE) ? "true" : "false"); + zipstate.json_append('}').json_append(']'); + } + else + { + auto item = m_items.begin(); + auto last = std::prev(m_items.end()); - // look for large arrays of ints/floats - save_registered_item *inner = &item; - u32 total = count(); - while (inner->is_array()) + // compute the size of an item to determine if we show it inline + u32 item_size = item->compute_binary_size(objbase); + if (inline_form || count() * item_size <= 16) { - total *= inner->count(); - inner = &inner->m_items.front(); - } - if (inner->is_int_or_float() && total * inner->m_native_size >= save_zip_state::JSON_EXTERNAL_BINARY_THRESHOLD) - { - char const *filename = zipstate.add_data_file(localname.c_str(), *this, objbase); - - zipstate.json_append('[').json_append('{'); - zipstate.json_append_name("external_file"); - zipstate.json_append('"').json_append(filename).json_append('"').json_append(','); - zipstate.json_append_name("unit"); - zipstate.json_append_signed(inner->m_native_size).json_append(','); - zipstate.json_append_name("count"); - zipstate.json_append_signed(total).json_append(','); - zipstate.json_append_name("little_endian"); - zipstate.json_append((ENDIANNESS_NATIVE == ENDIANNESS_LITTLE) ? "true" : "false"); - zipstate.json_append('}').json_append(']'); + // strictly inline form outputs everything on a single line + zipstate.json_append('['); + for (u32 rep = 0; rep < count(); rep++) + { + item->save_json(zipstate, localname.c_str(), 0, true, objbase + rep * m_native_size); + if (rep != count() - 1) + zipstate.json_append(','); + if (item != last) + ++item; + } + zipstate.json_append(']'); } else { - 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 - zipstate.json_append('['); - for (uint32_t rep = 0; rep < m_type; rep++) - { - item.save_json(zipstate, localname.c_str(), 0, true, objbase + rep * m_native_size); - if (rep != m_type - 1) - zipstate.json_append(','); - } - zipstate.json_append(']'); - } - else + // normal form outputs a certain number of items per row + zipstate.json_append('[').json_append_eol(); + u32 items_per_row = 1; + if (item->is_int_or_float()) + items_per_row = (item_size <= 2) ? 32 : 16; + + // iterate over the items + for (u32 rep = 0; rep < count(); rep++) { - // normal form outputs a certain number of items per row - zipstate.json_append('[').json_append_eol(); - uint32_t items_per_row = 1; - if (item.is_int_or_float()) - items_per_row = (item_size <= 2) ? 32 : 16; - - // iterate over the items - for (uint32_t rep = 0; rep < m_type; rep++) - { - if (rep % items_per_row == 0) - zipstate.json_append_indent(indent + 1); - item.save_json(zipstate, localname.c_str(), indent + 1, false, objbase + rep * m_native_size); - if (rep != m_type - 1) - zipstate.json_append(','); - if (rep % items_per_row == items_per_row - 1) - zipstate.json_append_eol(); - } - if (m_type % items_per_row != 0) + if (rep % items_per_row == 0) + zipstate.json_append_indent(indent + 1); + item->save_json(zipstate, localname.c_str(), indent + 1, false, objbase + rep * m_native_size); + if (rep != count() - 1) + zipstate.json_append(','); + if (rep % items_per_row == items_per_row - 1) zipstate.json_append_eol(); - zipstate.json_append_indent(indent).json_append(']'); + if (item != last) + ++item; } + if (count() % items_per_row != 0) + zipstate.json_append_eol(); + zipstate.json_append_indent(indent).json_append(']'); } } break; + } } } @@ -1680,7 +1722,7 @@ void save_registered_item::save_json(save_zip_state &zipstate, char const *namep void save_registered_item::restore_json(load_zip_state &input, char const *nameprefix, json_restore_mode mode, uintptr_t objbase) { // update the base pointer and forward if a trivial unwrap - if (unwrap_and_update_objbase(objbase)) + if (unwrap_and_update_base(objbase)) return m_items.front().restore_json(input, nameprefix, mode, objbase); // update the name prefix @@ -1693,7 +1735,7 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep } // switch off the type - switch (m_type) + switch (type()) { // boolean types case TYPE_BOOL: @@ -1716,12 +1758,12 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep case TYPE_INT: { double dvalue; - int64_t ivalue; + s64 ivalue; if (input.json_parse_number(dvalue)) { if (mode == RESTORE_DATA && !write_int_signed(objbase, m_native_size, dvalue)) input.report_warning("%s: Value of out range: %1.17g", localname.c_str(), dvalue); - else if (mode == COMPARE_DATA && read_int_signed(objbase, m_native_size) != int64_t(dvalue)) + else if (mode == COMPARE_DATA && read_int_signed(objbase, m_native_size) != s64(dvalue)) input.report_warning("%s: Compare failed: JSON says %I64d, data says %1.17g", localname.c_str(), dvalue, read_int_signed(objbase, m_native_size)); } else if (input.json_parse_int_string(ivalue)) @@ -1740,12 +1782,12 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep case TYPE_UINT: { double dvalue; - uint64_t ivalue; + u64 ivalue; if (input.json_parse_number(dvalue)) { if (mode == RESTORE_DATA && !write_int_unsigned(objbase, m_native_size, dvalue)) input.report_warning("%s: Value of out range: %1.17g", localname.c_str(), dvalue); - else if (mode == COMPARE_DATA && read_int_unsigned(objbase, m_native_size) != uint64_t(dvalue)) + else if (mode == COMPARE_DATA && read_int_unsigned(objbase, m_native_size) != u64(dvalue)) input.report_warning("%s: Compare failed: JSON says %I64d, data says %1.17g", localname.c_str(), dvalue, read_int_unsigned(objbase, m_native_size)); } else if (input.json_parse_uint_string(ivalue)) @@ -1789,7 +1831,7 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep save_registered_item *target = find(name.c_str()); if (target == nullptr) input.report_warning("%s: Found extraneous item '%s'", localname.c_str(), name.c_str()); - target->restore_json(input, nameprefix, (target == nullptr) ? PARSE_ONLY : mode, objbase); + target->restore_json(input, localname.c_str(), (target == nullptr) ? PARSE_ONLY : mode, objbase); if (input.json_matches('}')) break; if (!input.json_matches(',')) @@ -1798,35 +1840,38 @@ void save_registered_item::restore_json(load_zip_state &input, char const *namep break; // arrays are multiples of a single item - default: - if (is_array()) + case TYPE_STATIC_ARRAY: + case TYPE_RUNTIME_ARRAY: + { + auto item = m_items.begin(); + auto last = std::prev(m_items.end()); + if (!input.json_matches('[')) + input.report_error(STATERR_INCOMPATIBLE_DATA, "%s: Expected '['", localname.c_str()); + if (parse_external_data(input, *this, localname.c_str(), mode, objbase)) { - auto &item = m_items.front(); - if (!input.json_matches('[')) - input.report_error(STATERR_INCOMPATIBLE_DATA, "%s: Expected '['", localname.c_str()); - if (parse_external_data(input, *this, localname.c_str(), mode, objbase)) - { - if (!input.json_matches(']')) - input.report_error(STATERR_MALFORMED_JSON, "%s: Expected ']'", localname.c_str()); - } - else - { - u32 rep = 0; - if (!input.json_matches(']')) - while (1) - { - item.restore_json(input, nameprefix, (rep >= count()) ? PARSE_ONLY : mode, objbase + rep * m_native_size); - rep++; - if (input.json_matches(']')) - break; - if (!input.json_matches(',')) - input.report_error(STATERR_MALFORMED_JSON, "%s: Expected ','", localname.c_str()); - } - if (rep != count()) - input.report_warning("%s: Found %s array items than expected", localname.c_str(), (rep < count()) ? "fewer" : "more"); - } + if (!input.json_matches(']')) + input.report_error(STATERR_MALFORMED_JSON, "%s: Expected ']'", localname.c_str()); + } + else + { + u32 rep = 0; + if (!input.json_matches(']')) + while (1) + { + item->restore_json(input, localname.c_str(), (rep >= count()) ? PARSE_ONLY : mode, objbase + rep * m_native_size); + rep++; + if (item != last) + ++item; + if (input.json_matches(']')) + break; + if (!input.json_matches(',')) + input.report_error(STATERR_MALFORMED_JSON, "%s: Expected ','", localname.c_str()); + } + if (rep != count()) + input.report_warning("%s: Found %s array items than expected", localname.c_str(), (rep < count()) ? "fewer" : "more"); } break; + } } } @@ -1926,14 +1971,14 @@ bool save_registered_item::parse_external_data(load_zip_state &input, save_regis // of the given size //------------------------------------------------- -uint64_t save_registered_item::read_int_unsigned(uintptr_t objbase, int size) const +u64 save_registered_item::read_int_unsigned(uintptr_t objbase, int size) const { switch (size) { - case 1: return *reinterpret_cast<uint8_t const *>(objbase); - case 2: return *reinterpret_cast<uint16_t const *>(objbase); - case 4: return *reinterpret_cast<uint32_t const *>(objbase); - case 8: return *reinterpret_cast<uint64_t const *>(objbase); + case 1: return *reinterpret_cast<u8 const *>(objbase); + case 2: return *reinterpret_cast<u16 const *>(objbase); + case 4: return *reinterpret_cast<u32 const *>(objbase); + case 8: return *reinterpret_cast<u64 const *>(objbase); } return 0; } @@ -1944,14 +1989,14 @@ uint64_t save_registered_item::read_int_unsigned(uintptr_t objbase, int size) co // given size //------------------------------------------------- -int64_t save_registered_item::read_int_signed(uintptr_t objbase, int size) const +s64 save_registered_item::read_int_signed(uintptr_t objbase, int size) const { switch (size) { - case 1: return *reinterpret_cast<int8_t const *>(objbase); - case 2: return *reinterpret_cast<int16_t const *>(objbase); - case 4: return *reinterpret_cast<int32_t const *>(objbase); - case 8: return *reinterpret_cast<int64_t const *>(objbase); + case 1: return *reinterpret_cast<s8 const *>(objbase); + case 2: return *reinterpret_cast<s16 const *>(objbase); + case 4: return *reinterpret_cast<s32 const *>(objbase); + case 8: return *reinterpret_cast<s64 const *>(objbase); } return 0; } @@ -1978,21 +2023,21 @@ double save_registered_item::read_float(uintptr_t objbase, int size) const // the given size //------------------------------------------------- -bool save_registered_item::write_int_signed(uintptr_t objbase, int size, int64_t data) const +bool save_registered_item::write_int_signed(uintptr_t objbase, int size, s64 data) const { switch (size) { - case 1: *reinterpret_cast<int8_t *>(objbase) = int8_t(data); return (data >= -0x80 && data <= 0x7f); - case 2: *reinterpret_cast<int16_t *>(objbase) = int16_t(data); return (data >= -0x8000 && data <= 0x7fff); - case 4: *reinterpret_cast<int32_t *>(objbase) = int32_t(data); return (data >= -0x80000000ll && data <= 0x7fffffffll); - case 8: *reinterpret_cast<int64_t *>(objbase) = int64_t(data); return true; + case 1: *reinterpret_cast<s8 *>(objbase) = s8(data); return (data >= -0x80 && data <= 0x7f); + case 2: *reinterpret_cast<s16 *>(objbase) = s16(data); return (data >= -0x8000 && data <= 0x7fff); + case 4: *reinterpret_cast<s32 *>(objbase) = s32(data); return (data >= -0x80000000ll && data <= 0x7fffffffll); + case 8: *reinterpret_cast<s64 *>(objbase) = s64(data); return true; } return false; } bool save_registered_item::write_int_signed(uintptr_t objbase, int size, double data) const { - int64_t converted = int64_t(data); + s64 converted = s64(data); bool ok = (double(converted) == data); return write_int_signed(objbase, size, converted) && ok; } @@ -2003,21 +2048,21 @@ bool save_registered_item::write_int_signed(uintptr_t objbase, int size, double // of the given size //------------------------------------------------- -bool save_registered_item::write_int_unsigned(uintptr_t objbase, int size, uint64_t data) const +bool save_registered_item::write_int_unsigned(uintptr_t objbase, int size, u64 data) const { switch (size) { - case 1: *reinterpret_cast<uint8_t *>(objbase) = uint8_t(data); return (data <= 0xff); - case 2: *reinterpret_cast<uint16_t *>(objbase) = uint16_t(data); return (data <= 0xffff); - case 4: *reinterpret_cast<uint32_t *>(objbase) = uint32_t(data); return (data <= 0xffffffffull); - case 8: *reinterpret_cast<uint64_t *>(objbase) = uint64_t(data); return true; + case 1: *reinterpret_cast<u8 *>(objbase) = u8(data); return (data <= 0xff); + case 2: *reinterpret_cast<u16 *>(objbase) = u16(data); return (data <= 0xffff); + case 4: *reinterpret_cast<u32 *>(objbase) = u32(data); return (data <= 0xffffffffull); + case 8: *reinterpret_cast<u64 *>(objbase) = u64(data); return true; } return false; } bool save_registered_item::write_int_unsigned(uintptr_t objbase, int size, double data) const { - uint64_t converted = uint64_t(data); + u64 converted = u64(data); bool ok = (data >= 0 && double(converted) == data); return write_int_unsigned(objbase, size, converted) && ok; } @@ -2039,6 +2084,37 @@ bool save_registered_item::write_float(uintptr_t objbase, int size, double data) } +//------------------------------------------------- +// is_endpoint_array - return true if this item +// is a (multi-dimensional) array of an endpoint +// type +//------------------------------------------------- + +bool save_registered_item::is_endpoint_array(u32 &total, u32 &unitsize) const +{ + // we must be an array ourselves + if (!is_array()) + return false; + + // scan downward through simple arrays + save_registered_item const *current = this; + total = 1; + while (current->is_array() && current->m_items.size() == 1) + { + total *= current->count(); + current = ¤t->m_items.front(); + } + + // if we didn't end at an endpoint type, fail + if (!current->is_int_or_float()) + return false; + + // set the unit size and return true + unitsize = current->native_size(); + return true; +} + + //************************************************************************** // SAVE MANAGER diff --git a/src/emu/save.h b/src/emu/save.h index 368a9584882..e826b38dddb 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -51,43 +51,22 @@ enum save_error // MACROS //************************************************************************** -/* -TEST: -#define REGISTER_SAVE_1(a) .reg(a, #a) -#define REGISTER_SAVE_2(a,b) REGISTER_SAVE_1(a) REGISTER_SAVE_1(b) -#define REGISTER_SAVE_3(a,b,c) REGISTER_SAVE_1(a) REGISTER_SAVE_2(b,c) -#define REGISTER_SAVE_4(a,b,c,d) REGISTER_SAVE_1(a) REGISTER_SAVE_3(b,c,d) -#define REGISTER_SAVE_5(a,b,c,d,e) REGISTER_SAVE_1(a) REGISTER_SAVE_4(b,c,d,e) -#define REGISTER_SAVE_6(a,b,c,d,e,f) REGISTER_SAVE_1(a) REGISTER_SAVE_5(b,c,d,e,f) -#define REGISTER_SAVE_7(a,b,c,d,e,f,g) REGISTER_SAVE_1(a) REGISTER_SAVE_6(b,c,d,e,f,g) -#define REGISTER_SAVE_8(a,b,c,d,e,f,g,h) REGISTER_SAVE_1(a) REGISTER_SAVE_7(b,c,d,e,f,g,h) -#define REGISTER_SAVE_9(a,b,c,d,e,f,g,h,i) REGISTER_SAVE_1(a) REGISTER_SAVE_8(b,c,d,e,f,g,h,i) - -#define GET_SAVE_N(_1, _2, _3, _4, _5, _6, _7, _8, _9, NAME, ...) NAME -#define REGISTER_SAVE(...) GET_SAVE_N(__VA_ARGS__, REGISTER_SAVE_9, REGISTER_SAVE_8, REGISTER_SAVE_7, REGISTER_SAVE_6, REGISTER_SAVE_5, REGISTER_SAVE_4, REGISTER_SAVE_3, REGISTER_SAVE_2, REGISTER_SAVE_1)(__VA_ARGS__) -*/ - - // callback delegate for presave/postload typedef named_delegate<void ()> save_prepost_delegate; - +// use this macro to save a given type as a signed integer #define SAVE_TYPE_AS_INT(Type) \ template<> struct save_registrar::is_signed_int_like<Type> { static constexpr bool value = true; }; +// use this macro to save a given type as an unsigned integer #define SAVE_TYPE_AS_UINT(Type) \ template<> struct save_registrar::is_unsigned_int_like<Type> { static constexpr bool value = true; }; +// use this macro to save a given type as a floating-point value #define SAVE_TYPE_AS_FLOAT(Type) \ template<> struct save_registrar::is_floating_point_like<Type> { static constexpr bool value = true; }; - -// remove me -#define ALLOW_SAVE_TYPE(TYPE) -#define ALLOW_SAVE_TYPE_AND_VECTOR(TYPE) - - //************************************************************************** // TYPE DEFINITIONS //************************************************************************** @@ -119,86 +98,101 @@ public: }; // the various types supported - enum save_type : uint32_t + enum save_type : u32 { - 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 + // type native_size ptr_offset items + TYPE_BOOL, // sizeof(bool) relative none + TYPE_INT, // sizeof(value) relative none + TYPE_UINT, // sizeof(value) relative none + TYPE_FLOAT, // sizeof(value) relative none + + 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_UNIQUE, // sizeof(unique_ptr) relative item at pointer + TYPE_VECTOR, // sizeof(vector) relative TYPE_RUNTIME_ARRAY at pointer }; // root constructor save_registered_item(); // constructor for a new item - save_registered_item(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name); + save_registered_item(uintptr_t ptr_offset, save_type type, u32 native_size, char const *name, u32 count = 0); // simple getters char const *name() const { return m_name.c_str(); } - save_type type() const { return m_type; } - bool is_struct_or_container() const { return (m_type == TYPE_STRUCT || m_type == TYPE_CONTAINER); } - bool is_array() const { return (m_type < TYPE_ARRAY); } - bool is_int() const { return (m_type == TYPE_INT || m_type == TYPE_UINT); } - bool is_int_or_float() const { return (is_int() || m_type == TYPE_FLOAT); } + 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_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; } - uint32_t native_size() const { return m_native_size; } - uint32_t count() const { return is_array() ? m_type : 1; } + u32 native_size() const { return m_native_size; } uintptr_t ptr_offset() const { return m_ptr_offset; } // append a new item to the current one - save_registered_item &append(uintptr_t ptr_offset, save_type type, uint32_t native_size, char const *name); + save_registered_item &append(uintptr_t ptr_offset, save_type type, u32 native_size, char const *name, u32 count = 0); // find an item by name save_registered_item *find(char const *name); + // is this item replicatable (i.e., can we replicate it for all elements in an array?) + bool is_replicatable(bool parent_is_array) const; + // sort subitems by name and prune any empty items bool sort_and_prune(); - // update the object base and unwrap trivial items - bool unwrap_and_update_objbase(uintptr_t &objbase) const; + // update the object base and unwrap special items + bool unwrap_and_update_base(uintptr_t &objbase) const; // compute the binary size by just saving with a null - uint64_t compute_binary_size(uintptr_t objbase = 0) const { return save_binary(nullptr, 0, objbase); } + u64 compute_binary_size(uintptr_t parentbase = 0) const { return save_binary(nullptr, 0, parentbase); } // 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) const; + u64 save_binary(u8 *ptr, u64 length, uintptr_t parentbase = 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) const; + u64 restore_binary(u8 const *ptr, u64 length, uintptr_t parentbase = 0) const; // save this item into a JSON stream - void save_json(save_zip_state &output, char const *nameprefix = "", int indent = 0, bool inline_form = false, uintptr_t objbase = 0); + void save_json(save_zip_state &output, char const *nameprefix = "", int indent = 0, bool inline_form = false, uintptr_t parentbase = 0); // restore this item from a JSON stream - void restore_json(load_zip_state &input, char const *nameprefix = "", json_restore_mode mode = RESTORE_DATA, uintptr_t objbase = 0); - - // read/write helpers - bool read_bool(uintptr_t objbase) const { return *reinterpret_cast<bool const *>(objbase); } - uint64_t read_int_unsigned(uintptr_t objbase, int size) const; - int64_t read_int_signed(uintptr_t objbase, int size) const; - double read_float(uintptr_t objbase, int size) const; - void write_bool(uintptr_t objbase, bool data) const { *reinterpret_cast<bool *>(objbase) = data; } - bool write_int_signed(uintptr_t objbase, int size, int64_t data) const; - bool write_int_signed(uintptr_t objbase, int size, double data) const; - bool write_int_unsigned(uintptr_t objbase, int size, uint64_t data) const; - bool write_int_unsigned(uintptr_t objbase, int size, double data) const; - bool write_float(uintptr_t objbase, int size, double data) const; + void restore_json(load_zip_state &input, char const *nameprefix = "", json_restore_mode mode = RESTORE_DATA, uintptr_t parentbase = 0); + + // read/write helpers for bools + bool read_bool(uintptr_t objptr) const { return *reinterpret_cast<bool const *>(objptr); } + void write_bool(uintptr_t objptr, bool data) const { *reinterpret_cast<bool *>(objptr) = data; } + + // read/write helpers for signed integers + s64 read_int_signed(uintptr_t objptr, int size) const; + bool write_int_signed(uintptr_t objptr, int size, s64 data) const; + bool write_int_signed(uintptr_t objptr, int size, double data) const; + + // read/write helpers for unsigned integers + u64 read_int_unsigned(uintptr_t objptr, int size) const; + bool write_int_unsigned(uintptr_t objptr, int size, u64 data) const; + bool write_int_unsigned(uintptr_t objptr, int size, double data) const; + + // read/write helpers for floats + double read_float(uintptr_t objptr, int size) const; + bool write_float(uintptr_t objptr, int size, double data) const; private: + // true if this item is an array of endpoints + bool is_endpoint_array(u32 &total, u32 &unitsize) const; + // parse out an external file spec from the JSON - bool parse_external_data(load_zip_state &input, save_registered_item &baseitem, char const *localname, bool parseonly, uintptr_t objbase); + bool parse_external_data(load_zip_state &input, save_registered_item &baseitem, char const *localname, bool parseonly, uintptr_t parentbase); // internal state std::list<save_registered_item> m_items; // list of embedded items uintptr_t m_ptr_offset; // pointer or offset - save_type m_type; // type of native - uint32_t m_native_size; // native size of item + u32 m_type_count; // type and count + u32 m_native_size; // native size of item std::string m_name; // name of item }; @@ -213,12 +207,21 @@ class save_registrar friend class device_t; // 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)) + 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) + { + } + public: // items that are signed_int_like are interpreted as 8/16/32/64-bit signed integers; this includes // proper signed integral values and enums by default; additional types may be added via the @@ -233,22 +236,22 @@ public: // proper float and double values; additional types may be added via the SAVE_TYPE_AS_FLOAT macro template<typename T> struct is_floating_point_like { static constexpr bool value = std::is_floating_point<T>::value; }; - // items are considered atoms if they fall into one of the three classes above - template<typename T> struct is_atom { static constexpr bool value = (is_signed_int_like<T>::value || is_unsigned_int_like<T>::value || is_floating_point_like<T>::value); }; + // items are considered endpoints if they fall into one of the three classes above + template<typename T> struct is_endpoint { static constexpr bool value = (is_signed_int_like<T>::value || is_unsigned_int_like<T>::value || is_floating_point_like<T>::value); }; // construct a container within parent save_registrar(save_registrar &parent, char const *name) : - save_registrar(parent, save_registered_item::TYPE_CONTAINER, 0, name) + save_registrar(parent, nullptr, save_registered_item::TYPE_CONTAINER, 0, name, 0, nullptr, 0) { } // return a reference to the parent item - save_registered_item &parent_item() const { return m_parent; } + save_registered_item &parent_item() const { return m_parent_item; } - // append a bucket + // append a bucket by stealing its items save_registrar ®(save_registrar &src, char const *name) { - save_registrar container(*this, save_registered_item::TYPE_CONTAINER, 0, name); + save_registrar container(*this, name); auto &srcitems = src.parent_item().subitems(); auto &dstitems = container.parent_item().subitems(); dstitems.splice(dstitems.end(), srcitems); @@ -258,7 +261,7 @@ public: // bool as a special case save_registrar ®(bool &data, char const *name) { - return register_internal(&data, save_registered_item::TYPE_BOOL, sizeof(data), name); + return register_endpoint(&data, save_registered_item::TYPE_BOOL, sizeof(data), name); } // signed integral types @@ -266,7 +269,7 @@ public: std::enable_if_t<is_signed_int_like<T>::value, save_registrar> ®(T &data, char const *name) { static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); - return register_internal(&data, save_registered_item::TYPE_INT, sizeof(data), name); + return register_endpoint(&data, save_registered_item::TYPE_INT, sizeof(data), name); } // unsigned integral types @@ -274,7 +277,7 @@ public: std::enable_if_t<is_unsigned_int_like<T>::value, save_registrar> ®(T &data, char const *name) { static_assert(sizeof(T) == 1 || sizeof(T) == 2 || sizeof(T) == 4 || sizeof(T) == 8); - return register_internal(&data, save_registered_item::TYPE_UINT, sizeof(data), name); + return register_endpoint(&data, save_registered_item::TYPE_UINT, sizeof(data), name); } // floating-point types @@ -282,7 +285,7 @@ public: std::enable_if_t<is_floating_point_like<T>::value, save_registrar> ®(T &data, char const *name) { static_assert(sizeof(T) == 4 || sizeof(T) == 8); - return register_internal(&data, save_registered_item::TYPE_FLOAT, sizeof(data), name); + return register_endpoint(&data, save_registered_item::TYPE_FLOAT, sizeof(data), name); } // std::unique_ptrs -- these are containers with a single "unique" item within @@ -292,82 +295,66 @@ public: if (data.get() == nullptr) throw emu_fatalerror("Passed null pointer to save state registration."); - save_registrar container(*this, save_registered_item::TYPE_UNIQUE, sizeof(data), name, &data, data.get()); + save_registrar container(*this, &data, save_registered_item::TYPE_UNIQUE, sizeof(data), name, 0, data.get(), sizeof(T)); container.reg(*data.get(), name); return *this; } + // pointers with count -- treat as an array + 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); + } + // 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> + template<typename T, u32 N> save_registrar ®(T (&data)[N], char const *name) - { - save_registrar container(*this, save_registered_item::save_type(N), uintptr_t(&data[1]) - uintptr_t(&data[0]), name, &data[0]); - container.reg(data[0], ""); - return *this; - } + { + return register_array(&data[0], save_registered_item::TYPE_STATIC_ARRAY, name, N); + } // std::arrays -- treat these identically to arrays - template<typename T, std::size_t N> + template<typename T, u32 N> save_registrar ®(std::array<T, N> &data, char const *name) - { - save_registrar container(*this, save_registered_item::save_type(N), uintptr_t(&data[1]) - uintptr_t(&data[0]), name, &data[0]); - container.reg(data[0], ""); - return *this; - } - - // pointers -- treat as an array with a specific count - template<typename T> - save_registrar ®(T *data, char const *name, std::size_t count) { - if (data == nullptr) - throw emu_fatalerror("Passed null pointer to save state registration."); - - save_registrar container(*this, save_registered_item::save_type(count), uintptr_t(&data[1]) - uintptr_t(&data[0]), name, &data[0]); - container.reg(data[0], ""); - return *this; + return register_array(&data[0], save_registered_item::TYPE_STATIC_ARRAY, name, N); } // std::vectors -- these are treated as arrays, but wrapped template<typename T> save_registrar ®(std::vector<T> &data, char const *name) { - // skip if nothing + // skip if no items if (data.size() == 0) return *this; - // create an outer container for the vector - save_registrar container(*this, save_registered_item::TYPE_VECTOR, sizeof(data), name, &data, &data[0]); - - // then an array container within - save_registrar subcontainer(container, save_registered_item::save_type(data.size()), uintptr_t(&data[1]) - uintptr_t(&data[0]), name, &data[0]); - subcontainer.reg(data[0], ""); - return *this; + // 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()); + return *this; } // std::unique_ptrs with arrays template<typename T> save_registrar ®(std::unique_ptr<T[]> &data, char const *name, std::size_t count) { - // skip if nothing + // skip if no items if (count == 0) return *this; - if (data.get() == nullptr) - throw emu_fatalerror("Passed null pointer to save state registration."); - - save_registrar container(*this, save_registered_item::TYPE_UNIQUE, sizeof(data), name, &data, data.get()); - - save_registrar subcontainer(container, save_registered_item::save_type(count), uintptr_t(&data[1]) - uintptr_t(&data[0]), name, &data[0]); - subcontainer.reg(data[0], ""); + // 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); return *this; } // structures & unions (must have a register_save method) - template<typename T, std::enable_if_t<(std::is_class<T>::value || std::is_union<T>::value) && !std::is_base_of<bitmap_t, T>::value && !is_atom<T>::value, bool> = true> - save_registrar ®(T &data, char const *name) + template<typename T, std::enable_if_t<(std::is_class<T>::value || std::is_union<T>::value) && !std::is_base_of<bitmap_t, T>::value && !is_endpoint<T>::value, bool> = true> + save_registrar ®(T &data, char const *name, std::size_t datasize = 0) { - save_registrar container(*this, save_registered_item::TYPE_STRUCT, sizeof(data), name, &data); + save_registrar container(*this, &data, save_registered_item::TYPE_STRUCT, sizeof(data), name, 0, &data, (datasize == 0) ? sizeof(T) : datasize); data.register_save(container); return *this; } @@ -375,11 +362,8 @@ public: // rectangle as a special case, since it's from an external library save_registrar ®(rectangle &data, char const *name) { - save_registrar container(*this, save_registered_item::TYPE_STRUCT, sizeof(data), name, &data); - container.reg(data.min_x, "min_x") - .reg(data.max_x, "max_x") - .reg(data.min_y, "min_y") - .reg(data.max_y, "max_y"); + save_registrar container(*this, &data, save_registered_item::TYPE_STRUCT, sizeof(data), name, 0, &data, sizeof(data)); + container.reg(data.min_x, "min_x").reg(data.max_x, "max_x").reg(data.min_y, "min_y").reg(data.max_y, "max_y"); return *this; } @@ -387,30 +371,54 @@ 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 rows(*this, save_registered_item::save_type(data.height()), data.rowbytes(), name, data.raw_pixptr(0)); - save_registrar cols(rows, save_registered_item::save_type(data.width()), sizeof(BitmapType::pixel_t), "", data.raw_pixptr(0)); - cols.register_internal(data.raw_pixptr(0), save_registered_item::TYPE_UINT, sizeof(BitmapType::pixel_t), ""); + 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); + cols.register_endpoint(pixbase, save_registered_item::TYPE_UINT, sizeof(BitmapType::pixel_t), ""); return *this; } private: - // internal constructor - save_registrar(save_registered_item &parent, void *baseptr = nullptr) : - m_parent(parent), - m_baseptr(uintptr_t(baseptr)) + // 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) { - } - - // internal registration - save_registrar ®ister_internal(void *memptr, save_registered_item::save_type type, std::size_t itemsize, char const *itemname) - { - m_parent.append(uintptr_t(memptr) - m_baseptr, type, itemsize, 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); return *this; } + // register an array item + template<typename T> + save_registrar ®ister_array(T *data, save_registered_item::save_type type, char const *name, std::size_t count) + { + // skip 0-length items + if (count == 0) + return *this; + + // error on null pointer + if (data == nullptr) + throw emu_fatalerror("Passed null pointer to save state registration."); + + // create a container and register the first item + save_registrar container(*this, data, type, uintptr_t(&data[1]) - uintptr_t(&data[0]), name, count, &data[0], sizeof(T)); + 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)) + for (int index = 1; index < count; index++) + { + container.m_regcontainerbase = uintptr_t(&data[index]); + container.reg(data[index], ""); + } + return *this; + } + // internal state - save_registered_item &m_parent; - uintptr_t m_baseptr; + save_registered_item &m_parent_item; + uintptr_t m_regcontainerbase; + u32 m_regcontainersize; }; // these types are small structures/unions that embed an integral type; treat them as raw diff --git a/src/mame/drivers/namcos22.cpp b/src/mame/drivers/namcos22.cpp index 55389d5814d..aae9ed5567b 100644 --- a/src/mame/drivers/namcos22.cpp +++ b/src/mame/drivers/namcos22.cpp @@ -3607,9 +3607,6 @@ void namcos22_state::device_post_load() m_gfxdecode->gfx(0)->mark_all_dirty(); } -// allow save_item on a non-fundamental type -ALLOW_SAVE_TYPE(namcos22_dsp_upload_state); - void namcos22_state::machine_start() { m_mcu_out.resolve(); diff --git a/src/mame/drivers/subsino2.cpp b/src/mame/drivers/subsino2.cpp index 726ee99f967..d4cfe01dfea 100644 --- a/src/mame/drivers/subsino2.cpp +++ b/src/mame/drivers/subsino2.cpp @@ -65,8 +65,6 @@ enum tilesize_t : uint8_t TILE_64x32 }; -ALLOW_SAVE_TYPE(tilesize_t); - enum vram_t { VRAM_LO, diff --git a/src/mame/drivers/ttchamp.cpp b/src/mame/drivers/ttchamp.cpp index 17523eb68fe..b595ee3ded3 100644 --- a/src/mame/drivers/ttchamp.cpp +++ b/src/mame/drivers/ttchamp.cpp @@ -149,8 +149,6 @@ private: void ttchamp_map(address_map &map); }; -ALLOW_SAVE_TYPE(ttchamp_state::picmode); - void ttchamp_state::machine_start() { diff --git a/src/mame/machine/rosetta.cpp b/src/mame/machine/rosetta.cpp index a459647b933..f06e83dbd15 100644 --- a/src/mame/machine/rosetta.cpp +++ b/src/mame/machine/rosetta.cpp @@ -173,8 +173,6 @@ static u8 const led_pattern[16] = DEFINE_DEVICE_TYPE(ROSETTA, rosetta_device, "rosetta", "IBM Rosetta") -ALLOW_SAVE_TYPE(rosetta_device::mear_state) - rosetta_device::rosetta_device(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock, ram_size ram) : device_t(mconfig, ROSETTA, tag, owner, clock) , rsc_cpu_interface(mconfig, *this) diff --git a/src/mame/machine/thomflop.cpp b/src/mame/machine/thomflop.cpp index 2179377c8b5..1352c937f44 100644 --- a/src/mame/machine/thomflop.cpp +++ b/src/mame/machine/thomflop.cpp @@ -836,8 +836,6 @@ enum : uint8_t DEFINE_DEVICE_TYPE(THMFC1, thmfc1_device, "thmfc1", "Thomson THMFC1 floppy controller") -ALLOW_SAVE_TYPE(thmfc1_device::thmfc1_op); - thmfc1_device::thmfc1_device(const machine_config &mconfig, const char *tag, device_t *owner, uint32_t clock) : device_t(mconfig, THMFC1, tag, owner, clock) , thomson_legacy_floppy_interface(mconfig, *this) diff --git a/src/mame/machine/x68k_hdc.cpp b/src/mame/machine/x68k_hdc.cpp index d3051b8bcb9..cfa2ce9902e 100644 --- a/src/mame/machine/x68k_hdc.cpp +++ b/src/mame/machine/x68k_hdc.cpp @@ -22,8 +22,6 @@ #include "imagedev/harddriv.h" #include "image.h" -ALLOW_SAVE_TYPE(x68k_hdc_image_device::sasi_phase); - DEFINE_DEVICE_TYPE(X68KHDC, x68k_hdc_image_device, "x68k_hdc_image", "SASI Hard Disk") x68k_hdc_image_device::x68k_hdc_image_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) |
