diff options
Diffstat (limited to 'src/emu')
34 files changed, 234 insertions, 184 deletions
diff --git a/src/emu/devcpu.cpp b/src/emu/devcpu.cpp index 03df7990a3d..67968a69efa 100644 --- a/src/emu/devcpu.cpp +++ b/src/emu/devcpu.cpp @@ -21,7 +21,7 @@ // cpu_device - constructor //------------------------------------------------- -cpu_device::cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) +cpu_device::cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, type, tag, owner, clock), device_execute_interface(mconfig, *this), device_memory_interface(mconfig, *this), diff --git a/src/emu/devcpu.h b/src/emu/devcpu.h index 6e9251ab3a9..222a941a325 100644 --- a/src/emu/devcpu.h +++ b/src/emu/devcpu.h @@ -38,7 +38,7 @@ public: protected: // construction/destruction - cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock); + cpu_device(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock); private: // configured state diff --git a/src/emu/device.cpp b/src/emu/device.cpp index 425ce52d461..f0ecdc1053d 100644 --- a/src/emu/device.cpp +++ b/src/emu/device.cpp @@ -82,16 +82,16 @@ emu::detail::device_registrar const registered_device_types; // from the provided config //------------------------------------------------- -device_t::device_t(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, u32 clock) +device_t::device_t(const machine_config &mconfig, device_type type, const char *tag, device_t *owner, const XTAL &clock) : m_type(type) , m_owner(owner) , m_next(nullptr) - , m_configured_clock(clock) - , m_unscaled_clock(clock) - , m_clock(clock) + , m_configured_clock(clock.dvalue()) + , m_unscaled_clock(clock.dvalue()) + , m_clock(clock.dvalue()) , m_clock_scale(1.0) - , m_attoseconds_per_clock((clock == 0) ? 0 : HZ_TO_ATTOSECONDS(clock)) + , m_attoseconds_per_clock(clock.disabled() ? 0 : HZ_TO_ATTOSECONDS(clock)) , m_machine_config(mconfig) , m_input_defaults(nullptr) @@ -234,7 +234,7 @@ void device_t::add_machine_configuration(machine_config &config) // a device //------------------------------------------------- -void device_t::set_clock(u32 clock) +void device_t::internal_set_clock(u32 clock) { m_configured_clock = clock; @@ -242,7 +242,7 @@ void device_t::set_clock(u32 clock) if ((clock & 0xff000000) == 0xff000000) calculate_derived_clock(); else - set_unscaled_clock(clock); + internal_set_unscaled_clock(clock); } @@ -365,7 +365,7 @@ void device_t::reset() // unscaled clock //------------------------------------------------- -void device_t::set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain) +void device_t::internal_set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain) { // do nothing if no actual change if (clock == m_unscaled_clock) @@ -420,7 +420,7 @@ void device_t::calculate_derived_clock() if ((m_configured_clock & 0xff000000) == 0xff000000) { assert(m_owner != nullptr); - set_unscaled_clock(m_owner->m_clock * ((m_configured_clock >> 12) & 0xfff) / ((m_configured_clock >> 0) & 0xfff)); + internal_set_unscaled_clock(m_owner->m_clock * ((m_configured_clock >> 12) & 0xfff) / ((m_configured_clock >> 0) & 0xfff)); } } diff --git a/src/emu/device.h b/src/emu/device.h index 402bbb1ccff..4392ede1a7c 100644 --- a/src/emu/device.h +++ b/src/emu/device.h @@ -32,7 +32,7 @@ //************************************************************************** // macro for specifying a clock derived from an owning device -#define DERIVED_CLOCK(num, den) (0xff000000 | ((num) << 12) | ((den) << 0)) +#define DERIVED_CLOCK(num, den) XTAL::u((0xff000000 | ((num) << 12) | ((den) << 0))) @@ -191,7 +191,7 @@ class device_type_impl_base private: friend class device_registrar; - typedef std::unique_ptr<device_t> (*create_func)(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, u32 clock); + typedef std::unique_ptr<device_t> (*create_func)(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, const XTAL &clock); device_type_impl_base(device_type_impl_base const &) = delete; device_type_impl_base(device_type_impl_base &&) = delete; @@ -199,16 +199,15 @@ private: device_type_impl_base &operator=(device_type_impl_base &&) = delete; template <typename DeviceClass> - static std::unique_ptr<device_t> create_device(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + static std::unique_ptr<device_t> create_device(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, const XTAL &clock) { return std::make_unique<DeviceClass>(mconfig, tag, owner, clock); } template <typename DriverClass> - static std::unique_ptr<device_t> create_driver(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) + static std::unique_ptr<device_t> create_driver(device_type_impl_base const &type, machine_config const &mconfig, char const *tag, device_t *owner, const XTAL &clock) { assert(!owner); - assert(!clock); return std::make_unique<DriverClass>(mconfig, type, tag); } @@ -276,7 +275,7 @@ public: device_feature::type imperfect_features() const { return m_imperfect_features; } device_type_impl_base const *parent_rom_device_type() const { return m_parent_rom; } - std::unique_ptr<device_t> create(machine_config const &mconfig, char const *tag, device_t *owner, u32 clock) const + std::unique_ptr<device_t> create(machine_config const &mconfig, char const *tag, device_t *owner, const XTAL &clock) const { return m_creator(*this, mconfig, tag, owner, clock); } @@ -575,7 +574,7 @@ protected: device_type type, const char *tag, device_t *owner, - u32 clock); + const XTAL &clock = XTAL()); public: // device flags @@ -634,7 +633,7 @@ public: const char *source() const { return m_type.source(); } device_t *owner() const { return m_owner; } device_t *next() const { return m_next; } - u32 configured_clock() const { return m_configured_clock; } + XTAL configured_clock() const { return XTAL::u(m_configured_clock); } const machine_config &mconfig() const { return m_machine_config; } const input_device_default *input_ports_defaults() const { return m_input_defaults; } const std::vector<rom_entry> &rom_region_vector() const; @@ -677,8 +676,11 @@ public: // configuration helpers void add_machine_configuration(machine_config &config); - void set_clock(u32 clock); - void set_clock(const XTAL &xtal) { set_clock(xtal.value()); } + +private: + void internal_set_clock(u32 clock); +public: + void set_clock(const XTAL &xtal) { internal_set_clock(xtal.value()); } void set_input_default(const input_device_default *config) { m_input_defaults = config; } template <typename... Params> void set_default_bios_tag(Params &&... args) { assert(!configured()); m_default_bios_tag.assign(std::forward<Params>(args)...); } @@ -690,12 +692,14 @@ public: void reset(); // clock/timing accessors - u32 clock() const { return m_clock; } - u32 unscaled_clock() const { return m_unscaled_clock; } - void set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain = false); - void set_unscaled_clock(const XTAL &xtal, bool sync_on_new_clock_domain = false) { set_unscaled_clock(xtal.value(), sync_on_new_clock_domain); } - void set_unscaled_clock_int(u32 clock) { set_unscaled_clock(clock, false); } // non-overloaded name because binding to overloads is ugly - void set_unscaled_clock_int_sync(u32 clock) { set_unscaled_clock(clock, true); } // non-overloaded name because binding to overloads is ugly + XTAL clock() const { return XTAL::u(m_clock); } + XTAL unscaled_clock() const { return XTAL::u(m_unscaled_clock); } +private: + void internal_set_unscaled_clock(u32 clock, bool sync_on_new_clock_domain = false); +public: + void set_unscaled_clock(const XTAL &xtal, bool sync_on_new_clock_domain = false) { internal_set_unscaled_clock(xtal.value(), sync_on_new_clock_domain); } + void set_unscaled_clock_ns(const XTAL &clock) { set_unscaled_clock(clock, false); } // non-overloaded name because binding to overloads is ugly + void set_unscaled_clock_s(const XTAL &clock) { set_unscaled_clock(clock, true); } // non-overloaded name because binding to overloads is ugly double clock_scale() const { return m_clock_scale; } void set_clock_scale(double clockscale); attotime clocks_to_attotime(u64 clocks) const noexcept; diff --git a/src/emu/device.ipp b/src/emu/device.ipp index c7b2d43346b..b886bb47205 100644 --- a/src/emu/device.ipp +++ b/src/emu/device.ipp @@ -21,7 +21,7 @@ // TYPE DEFINITIONS //************************************************************************** -typedef device_delegate<void (u32)> clock_update_delegate; +typedef device_delegate<void (const XTAL &)> clock_update_delegate; //************************************************************************** diff --git a/src/emu/diexec.cpp b/src/emu/diexec.cpp index b1f885e2b9d..eab91b55f89 100644 --- a/src/emu/diexec.cpp +++ b/src/emu/diexec.cpp @@ -442,7 +442,7 @@ void device_execute_interface::interface_pre_reset() // enable all devices (except for disabled and unclocked devices) if (disabled()) suspend(SUSPEND_REASON_DISABLE, true); - else if (device().clock() != 0) + else if (!device().clock().disabled()) resume(SUSPEND_ANY_REASON); } @@ -486,7 +486,7 @@ void device_execute_interface::interface_post_reset() void device_execute_interface::interface_clock_changed(bool sync_on_new_clock_domain) { // a clock of zero disables the device - if (device().clock() == 0) + if (device().clock().disabled()) { suspend(SUSPEND_REASON_CLOCK, true); return; @@ -497,7 +497,7 @@ void device_execute_interface::interface_clock_changed(bool sync_on_new_clock_do resume(SUSPEND_REASON_CLOCK); // recompute cps and spc - m_cycles_per_second = clocks_to_cycles(device().clock()); + m_cycles_per_second = clocks_to_cycles(device().clock().value()); m_attoseconds_per_cycle = HZ_TO_ATTOSECONDS(m_cycles_per_second); // resynchronize the localtime to the clock domain when asked to @@ -557,13 +557,13 @@ int device_execute_interface::standard_irq_callback(int irqline) attoseconds_t device_execute_interface::minimum_quantum() const { // if we don't have a clock, return a huge factor - if (device().clock() == 0) + if (device().clock().disabled()) return ATTOSECONDS_PER_SECOND - 1; // if we don't have the quantum time, compute it attoseconds_t basetick = m_attoseconds_per_cycle; if (basetick == 0) - basetick = HZ_TO_ATTOSECONDS(clocks_to_cycles(device().clock())); + basetick = HZ_TO_ATTOSECONDS(clocks_to_cycles(device().clock().value())); // apply the minimum cycle count return basetick * min_cycles(); diff --git a/src/emu/diserial.h b/src/emu/diserial.h index 62b13c028a1..3c6e42456c6 100644 --- a/src/emu/diserial.h +++ b/src/emu/diserial.h @@ -90,13 +90,10 @@ protected: void set_rcv_rate(const attotime &rate); void set_tra_rate(const attotime &rate); - void set_rcv_rate(u32 clock, int div) { set_rcv_rate((clock && div) ? (attotime::from_hz(clock) * div) : attotime::never); } - void set_tra_rate(u32 clock, int div) { set_tra_rate((clock && div) ? (attotime::from_hz(clock) * div) : attotime::never); } - void set_rcv_rate(int baud) { set_rcv_rate(baud ? attotime::from_hz(baud) : attotime::never); } - void set_tra_rate(int baud) { set_tra_rate(baud ? attotime::from_hz(baud) : attotime::never); } + void set_rcv_rate(const XTAL &clock) { set_rcv_rate(clock.disabled() ? attotime::never : attotime::from_seconds(1/clock.dvalue())); } + void set_tra_rate(const XTAL &clock) { set_tra_rate(clock.disabled() ? attotime::never : attotime::from_seconds(1/clock.dvalue())); } void set_rate(const attotime &rate) { set_rcv_rate(rate); set_tra_rate(rate); } - void set_rate(u32 clock, int div) { set_rcv_rate(clock, div); set_tra_rate(clock, div); } - void set_rate(int baud) { set_rcv_rate(baud); set_tra_rate(baud); } + void set_rate(const XTAL &clock) { set_rcv_rate(clock); set_tra_rate(clock); } void transmit_register_reset(); void transmit_register_add_bit(int bit); diff --git a/src/emu/dislot.h b/src/emu/dislot.h index dd2fde5fac1..b337e5b4e3a 100644 --- a/src/emu/dislot.h +++ b/src/emu/dislot.h @@ -54,13 +54,12 @@ public: char const *default_bios() const { return m_default_bios; } std::function<void (device_t *)> const &machine_config() const { return m_machine_config; } input_device_default const *input_device_defaults() const { return m_input_device_defaults; } - u32 clock() const { return m_clock; } + XTAL clock() const { return m_clock; } slot_option &default_bios(char const *default_bios) { m_default_bios = default_bios; return *this; } template <typename Object> slot_option &machine_config(Object &&cb) { m_machine_config = std::forward<Object>(cb); return *this; } slot_option &input_device_defaults(input_device_default const *dev_inp_def) { m_input_device_defaults = dev_inp_def; return *this; } - slot_option &clock(u32 clock) { m_clock = clock; return *this; } - slot_option &clock(XTAL clock) { clock.validate(std::string("Configuring slot option ") + m_name); m_clock = clock.value(); return *this; } + slot_option &clock(const XTAL &clock) { clock.validate(std::string("Configuring slot option ") + m_name); m_clock = clock; return *this; } private: // internal state @@ -70,7 +69,7 @@ public: char const *m_default_bios; std::function<void (device_t *)> m_machine_config; input_device_default const *m_input_device_defaults; - u32 m_clock; + XTAL m_clock; }; virtual ~device_slot_interface(); @@ -171,12 +170,12 @@ public: protected: device_slot_interface(machine_config const &mconfig, device_t &device); virtual void interface_validity_check(validity_checker &valid) const override ATTR_COLD; - void set_default_clock(u32 clock) { m_default_clock = clock; } + void set_default_clock(const XTAL &clock) { m_default_clock = clock; } private: // internal state std::unordered_map<std::string, std::unique_ptr<slot_option>> m_options; - u32 m_default_clock; + XTAL m_default_clock; char const *m_default_option; bool m_fixed; device_t *m_card_device; diff --git a/src/emu/disound.cpp b/src/emu/disound.cpp index 83d2c2bf084..0a57a9d4bd7 100644 --- a/src/emu/disound.cpp +++ b/src/emu/disound.cpp @@ -71,12 +71,12 @@ device_sound_interface &device_sound_interface::add_route(u32 output, device_t & // associated with this device //------------------------------------------------- -sound_stream *device_sound_interface::stream_alloc(int inputs, int outputs, int sample_rate) +sound_stream *device_sound_interface::stream_alloc(int inputs, int outputs, const XTAL &sample_rate) { return device().machine().sound().stream_alloc(*this, inputs, outputs, sample_rate, stream_update_delegate(&device_sound_interface::sound_stream_update, this), STREAM_DEFAULT_FLAGS); } -sound_stream *device_sound_interface::stream_alloc(int inputs, int outputs, int sample_rate, sound_stream_flags flags) +sound_stream *device_sound_interface::stream_alloc(int inputs, int outputs, const XTAL &sample_rate, sound_stream_flags flags) { return device().machine().sound().stream_alloc(*this, inputs, outputs, sample_rate, stream_update_delegate(&device_sound_interface::sound_stream_update, this), flags); } diff --git a/src/emu/disound.h b/src/emu/disound.h index e48ba290bc6..8ad9dbd8494 100644 --- a/src/emu/disound.h +++ b/src/emu/disound.h @@ -80,8 +80,8 @@ public: virtual void sound_stream_update(sound_stream &stream, std::vector<read_stream_view> const &inputs, std::vector<write_stream_view> &outputs); // stream creation - sound_stream *stream_alloc(int inputs, int outputs, int sample_rate); - sound_stream *stream_alloc(int inputs, int outputs, int sample_rate, sound_stream_flags flags); + sound_stream *stream_alloc(int inputs, int outputs, const XTAL &sample_rate); + sound_stream *stream_alloc(int inputs, int outputs, const XTAL &sample_rate, sound_stream_flags flags); // helpers int inputs() const; diff --git a/src/emu/drawgfx.cpp b/src/emu/drawgfx.cpp index 8a63d71467c..42b2b5db79e 100644 --- a/src/emu/drawgfx.cpp +++ b/src/emu/drawgfx.cpp @@ -58,7 +58,7 @@ static inline s32 normalize_yscroll(const bitmap_t &bitmap, s32 yscroll) DEFINE_DEVICE_TYPE(GFXDECODE, gfxdecode_device, "gfxdecode", "gfxdecode") -gfxdecode_device::gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : +gfxdecode_device::gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, GFXDECODE, tag, owner, clock), device_gfx_interface(mconfig, *this) { diff --git a/src/emu/drawgfx.h b/src/emu/drawgfx.h index 4b5be8a4fa3..f88d3f98c9b 100644 --- a/src/emu/drawgfx.h +++ b/src/emu/drawgfx.h @@ -539,12 +539,12 @@ public: // construction/destruction template <typename T> gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&palette_tag, const gfx_decode_entry *gfxinfo) - : gfxdecode_device(mconfig, tag, owner, 0) + : gfxdecode_device(mconfig, tag, owner) { set_palette(std::forward<T>(palette_tag)); set_info(gfxinfo); } - gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + gfxdecode_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock = XTAL()); protected: virtual void device_start() override {} diff --git a/src/emu/driver.cpp b/src/emu/driver.cpp index 9b0dd9c5e59..09690110829 100644 --- a/src/emu/driver.cpp +++ b/src/emu/driver.cpp @@ -23,7 +23,7 @@ //------------------------------------------------- driver_device::driver_device(const machine_config &mconfig, device_type type, const char *tag) - : device_t(mconfig, type, tag, nullptr, 0) + : device_t(mconfig, type, tag, nullptr, XTAL()) , m_system(mconfig.gamedrv()) , m_flip_screen_x(0) , m_flip_screen_y(0) diff --git a/src/emu/drivers/testcpu.cpp b/src/emu/drivers/testcpu.cpp index 95e3d5a1ec2..e7fa0cbbb13 100644 --- a/src/emu/drivers/testcpu.cpp +++ b/src/emu/drivers/testcpu.cpp @@ -193,7 +193,7 @@ void testcpu_state::ppc_mem(address_map &map) void testcpu_state::testcpu(machine_config &config) { // CPUs - PPC603E(config, m_cpu, 66000000); + PPC603E(config, m_cpu, XTAL::u(66000000)); m_cpu->set_bus_frequency(66000000); // Multiplier 1, Bus = 66MHz, Core = 66MHz m_cpu->set_addrmap(AS_PROGRAM, &testcpu_state::ppc_mem); } diff --git a/src/emu/emupal.cpp b/src/emu/emupal.cpp index 9e1370a24ed..f83d2150b61 100644 --- a/src/emu/emupal.cpp +++ b/src/emu/emupal.cpp @@ -19,7 +19,7 @@ DEFINE_DEVICE_TYPE(PALETTE, palette_device, "palette", "palette") palette_device::palette_device(const machine_config &mconfig, const char *tag, device_t *owner, init_delegate &&init, u32 entries, u32 indirect) - : palette_device(mconfig, tag, owner, 0U) + : palette_device(mconfig, tag, owner) { set_entries(entries, indirect); m_init = std::move(init); @@ -101,7 +101,7 @@ palette_device::palette_device(const machine_config &mconfig, const char *tag, d } -palette_device::palette_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +palette_device::palette_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, PALETTE, tag, owner, clock) , device_palette_interface(mconfig, *this) , m_entries(0) diff --git a/src/emu/emupal.h b/src/emu/emupal.h index cb4884a72fb..60bab6efc6c 100644 --- a/src/emu/emupal.h +++ b/src/emu/emupal.h @@ -267,7 +267,7 @@ public: palette_device(const machine_config &mconfig, const char *tag, device_t *owner, bgr_555_t); palette_device(const machine_config &mconfig, const char *tag, device_t *owner, rgb_565_t); palette_device(const machine_config &mconfig, const char *tag, device_t *owner, bgr_565_t); - palette_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + palette_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock = XTAL()); template <typename T> palette_device(const machine_config &mconfig, const char *tag, device_t *owner, rgb_444_prom_t, T &®ion, u32 entries) @@ -278,11 +278,11 @@ public: template <typename F> palette_device(const machine_config &mconfig, const char *tag, device_t *owner, F &&init, std::enable_if_t<init_delegate::supports_callback<F>::value, const char *> name, u32 entries = 0U, u32 indirect = 0U) - : palette_device(mconfig, tag, owner, 0U) + : palette_device(mconfig, tag, owner) { set_init(std::forward<F>(init), name).set_entries(entries, indirect); } template <typename T, typename F> palette_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&devname, F &&init, std::enable_if_t<init_delegate::supports_callback<F>::value, const char *> name, u32 entries = 0U, u32 indirect = 0U) - : palette_device(mconfig, tag, owner, 0U) + : palette_device(mconfig, tag, owner) { set_init(std::forward<T>(devname), std::forward<F>(init), name).set_entries(entries, indirect); } // configuration diff --git a/src/emu/machine.h b/src/emu/machine.h index a49c5f1dbf9..cd99867ac95 100644 --- a/src/emu/machine.h +++ b/src/emu/machine.h @@ -147,7 +147,7 @@ public: bool hard_reset_pending() const { return m_hard_reset_pending; } bool ui_active() const { return m_ui_active; } const std::string &basename() const { return m_basename; } - int sample_rate() const { return m_sample_rate; } + XTAL sample_rate() const { return XTAL::u(m_sample_rate); } bool save_or_load_pending() const { return !m_saveload_pending_file.empty(); } // RAII-based side effect disable diff --git a/src/emu/mconfig.cpp b/src/emu/mconfig.cpp index 2c8c1aa011b..26debad4119 100644 --- a/src/emu/mconfig.cpp +++ b/src/emu/mconfig.cpp @@ -48,7 +48,7 @@ machine_config::machine_config(const game_driver &gamedrv, emu_options &options) , m_perfect_quantum_device(nullptr, "") { // add the root device - device_add("root", gamedrv.type, 0); + device_add("root", gamedrv.type, XTAL()); // intialize slot devices - make sure that any required devices have been allocated for (device_slot_interface &slot : slot_interface_enumerator(root_device())) @@ -195,8 +195,9 @@ void machine_config::set_maximum_quantum(attotime const &quantum) // new device //------------------------------------------------- -device_t *machine_config::device_add(const char *tag, device_type type, u32 clock) +device_t *machine_config::device_add(const char *tag, device_type type, const XTAL &clock) { + clock.validate(std::string("Instanciating device ") + tag); std::pair<const char *, device_t *> const owner(resolve_owner(tag)); return &add_device(type.create(*this, owner.first, owner.second, clock), owner.second); } @@ -207,8 +208,9 @@ device_t *machine_config::device_add(const char *tag, device_type type, u32 cloc // replace one device with a new device //------------------------------------------------- -device_t *machine_config::device_replace(const char *tag, device_type type, u32 clock) +device_t *machine_config::device_replace(const char *tag, device_type type, const XTAL &clock) { + clock.validate(std::string("Replacing device ") + tag); std::tuple<const char *, device_t *, device_t *> const existing(prepare_replace(tag)); std::unique_ptr<device_t> device(type.create(*this, std::get<0>(existing), std::get<1>(existing), clock)); return &replace_device(std::move(device), *std::get<1>(existing), std::get<2>(existing)); diff --git a/src/emu/mconfig.h b/src/emu/mconfig.h index c6cacde581f..203c213f649 100644 --- a/src/emu/mconfig.h +++ b/src/emu/mconfig.h @@ -180,9 +180,9 @@ public: m_current_device = &device; return token(*this, device); } - device_t *device_add(const char *tag, device_type type, u32 clock); + device_t *device_add(const char *tag, device_type type, const XTAL &clock = XTAL()); template <typename Creator> - device_t *device_add(const char *tag, Creator &&type, u32 clock) + device_t *device_add(const char *tag, Creator &&type, const XTAL &clock = XTAL()) { return device_add(tag, device_type(type), clock); } @@ -196,15 +196,9 @@ public: add_device(std::move(device), owner.second); return &result; } - template <typename Creator, typename... Params> - auto device_add(const char *tag, Creator &&type, XTAL clock, Params &&... args) - { - clock.validate(std::string("Instantiating device ") + tag); - return device_add(tag, std::forward<Creator>(type), clock.value(), std::forward<Params>(args)...); - } - device_t *device_replace(const char *tag, device_type type, u32 clock); + device_t *device_replace(const char *tag, device_type type, const XTAL &clock = XTAL()); template <typename Creator> - device_t *device_replace(const char *tag, Creator &&type, u32 clock) + device_t *device_replace(const char *tag, Creator &&type, const XTAL &clock = XTAL()) { return device_replace(tag, device_type(type), clock); } @@ -218,12 +212,6 @@ public: replace_device(std::move(device), *std::get<1>(existing), std::get<2>(existing)); return &result; } - template <typename Creator, typename... Params> - auto device_replace(const char *tag, Creator &&type, XTAL clock, Params &&... args) - { - clock.validate(std::string("Replacing device ") + tag); - return device_replace(tag, std::forward<Creator>(type), clock.value(), std::forward<Params>(args)...); - } device_t *device_remove(const char *tag); private: diff --git a/src/emu/recording.cpp b/src/emu/recording.cpp index 611e5ae327b..2208d2fe7b2 100644 --- a/src/emu/recording.cpp +++ b/src/emu/recording.cpp @@ -186,12 +186,12 @@ bool avi_movie_recording::initialize(running_machine &machine, std::unique_ptr<e info.video_depth = 24; info.audio_format = 0; - info.audio_timescale = machine.sample_rate(); + info.audio_timescale = machine.sample_rate().value(); info.audio_sampletime = 1; info.audio_numsamples = 0; info.audio_channels = 2; info.audio_samplebits = 16; - info.audio_samplerate = machine.sample_rate(); + info.audio_samplerate = machine.sample_rate().value(); // compute the frame time set_frame_period(attotime::from_seconds(1000) / info.video_timescale); diff --git a/src/emu/save.h b/src/emu/save.h index 677f127853a..330533d07cd 100644 --- a/src/emu/save.h +++ b/src/emu/save.h @@ -285,6 +285,43 @@ public: save_item(device, module, tag, index, value, &attotime::m_seconds, tempstr.c_str(), count); } + // specializations for XTAL + template <typename ItemType> + std::enable_if_t<std::is_same<typename save_manager::array_unwrap<ItemType>::underlying_type, XTAL>::value> save_item(device_t *device, const char *module, const char *tag, int index, ItemType &value, const char *valname) + { + std::string tempstr; + tempstr.assign(valname).append(".base_clock"); + save_item(device, module, tag, index, value, &XTAL::m_base_clock, tempstr.c_str()); + tempstr.assign(valname).append(".current_clock"); + save_item(device, module, tag, index, value, &XTAL::m_current_clock, tempstr.c_str()); + tempstr.assign(valname).append(".disable_validation"); + save_item(device, module, tag, index, value, &XTAL::m_disable_validation, tempstr.c_str()); + } + + template <typename ItemType> + std::enable_if_t<std::is_same<typename save_manager::array_unwrap<ItemType>::underlying_type, XTAL>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, ItemType *value, const char *valname, u32 count) + { + std::string tempstr; + tempstr.assign(valname).append(".base_clock"); + save_item(device, module, tag, index, value, &XTAL::m_base_clock, tempstr.c_str()); + tempstr.assign(valname).append(".current_clock"); + save_item(device, module, tag, index, value, &XTAL::m_current_clock, tempstr.c_str()); + tempstr.assign(valname).append(".disable_validation"); + save_item(device, module, tag, index, value, &XTAL::m_disable_validation, tempstr.c_str()); + } + + template <typename ItemType> + std::enable_if_t<std::is_same<typename save_manager::array_unwrap<ItemType>::underlying_type, XTAL>::value> save_pointer(device_t *device, const char *module, const char *tag, int index, const std::unique_ptr<ItemType []> &value, const char *valname, u32 count) + { + std::string tempstr; + tempstr.assign(valname).append(".base_clock"); + save_item(device, module, tag, index, value, &XTAL::m_base_clock, tempstr.c_str()); + tempstr.assign(valname).append(".current_clock"); + save_item(device, module, tag, index, value, &XTAL::m_current_clock, tempstr.c_str()); + tempstr.assign(valname).append(".disable_validation"); + save_item(device, module, tag, index, value, &XTAL::m_disable_validation, tempstr.c_str()); + } + // global memory registration template <typename ItemType> void save_item(ItemType &value, const char *valname, int index = 0) diff --git a/src/emu/screen.cpp b/src/emu/screen.cpp index f69a03ac13e..3932ffa7b94 100644 --- a/src/emu/screen.cpp +++ b/src/emu/screen.cpp @@ -526,7 +526,7 @@ void screen_device::svg_renderer::rebuild_cache() // screen_device - constructor //------------------------------------------------- -screen_device::screen_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +screen_device::screen_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, SCREEN, tag, owner, clock) , m_type(SCREEN_TYPE_RASTER) , m_orientation(ROT0) diff --git a/src/emu/screen.h b/src/emu/screen.h index 685d4c913a9..daafa2c822a 100644 --- a/src/emu/screen.h +++ b/src/emu/screen.h @@ -167,15 +167,15 @@ class screen_device : public device_t public: // construction/destruction - screen_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock); + screen_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock); screen_device(const machine_config &mconfig, const char *tag, device_t *owner, screen_type_enum type) - : screen_device(mconfig, tag, owner, u32(0)) + : screen_device(mconfig, tag, owner, XTAL()) { set_type(type); } screen_device(const machine_config &mconfig, const char *tag, device_t *owner, screen_type_enum type, rgb_t color) - : screen_device(mconfig, tag, owner, u32(0)) + : screen_device(mconfig, tag, owner, XTAL()) { set_type(type); set_color(color); @@ -222,10 +222,10 @@ public: /// \param [in] vbstart Index of first line in vertical blanking /// period after visible lines. /// \return Reference to device for method chaining. - screen_device &set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) +private: + screen_device &internal_set_raw(u32 pixclock, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) { assert(pixclock != 0); - set_clock(pixclock); m_refresh = HZ_TO_ATTOSECONDS(pixclock) * htotal * vtotal; m_vblank = m_refresh / vtotal * (vtotal - (vbstart - vbend)); m_width = htotal; @@ -233,10 +233,12 @@ public: m_visarea.set(hbend, hbstart ? hbstart - 1 : htotal - 1, vbend, vbstart - 1); return *this; } +public: screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 hbend, u16 hbstart, u16 vtotal, u16 vbend, u16 vbstart) { xtal.validate(std::string("Configuring screen ") + tag()); - return set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart); + set_clock(xtal); + return internal_set_raw(xtal.value(), htotal, hbend, hbstart, vtotal, vbend, vbstart); } screen_device &set_raw(const XTAL &xtal, u16 htotal, u16 vtotal, rectangle visarea) { diff --git a/src/emu/softlist_dev.cpp b/src/emu/softlist_dev.cpp index 6db85f917cf..0098dd7d02d 100644 --- a/src/emu/softlist_dev.cpp +++ b/src/emu/softlist_dev.cpp @@ -85,7 +85,7 @@ bool image_software_list_loader::load_software(device_image_interface &image, so // software_list_device - constructor //------------------------------------------------- -software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) : +software_list_device::software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, SOFTWARE_LIST, tag, owner, clock), m_list_type(softlist_type::ORIGINAL_SYSTEM), m_filter(nullptr), diff --git a/src/emu/softlist_dev.h b/src/emu/softlist_dev.h index 9e919dabe78..19275e379bc 100644 --- a/src/emu/softlist_dev.h +++ b/src/emu/softlist_dev.h @@ -99,7 +99,7 @@ public: }; // construction/destruction - software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + software_list_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock = XTAL()); // inline configuration helpers software_list_device &set_type(const char *list, softlist_type list_type) { m_list_name.assign(list); m_list_type = list_type; return *this; } diff --git a/src/emu/sound.cpp b/src/emu/sound.cpp index 6862845e8da..b52111dc612 100644 --- a/src/emu/sound.cpp +++ b/src/emu/sound.cpp @@ -55,12 +55,12 @@ const attotime sound_manager::STREAMS_UPDATE_ATTOTIME = attotime::from_hz(STREAM // stream_buffer - constructor //------------------------------------------------- -stream_buffer::stream_buffer(u32 sample_rate) : +stream_buffer::stream_buffer(const XTAL &sample_rate) : m_end_second(0), m_end_sample(0), m_sample_rate(sample_rate), - m_sample_attos((sample_rate == 0) ? ATTOSECONDS_PER_SECOND : ((ATTOSECONDS_PER_SECOND + sample_rate - 1) / sample_rate)), - m_buffer(sample_rate) + m_sample_attos(sample_rate.disabled() ? ATTOSECONDS_PER_SECOND : ((ATTOSECONDS_PER_SECOND + sample_rate.value() - 1) / sample_rate.value())), + m_buffer(sample_rate.disabled() ? 1 : sample_rate.value()) { } @@ -83,15 +83,16 @@ stream_buffer::~stream_buffer() // this buffer //------------------------------------------------- -void stream_buffer::set_sample_rate(u32 rate, bool resample) +void stream_buffer::set_sample_rate(const XTAL &rate, bool resample) { // skip if nothing is actually changing if (rate == m_sample_rate) return; + u32 irate = rate.value(); + // force resampling off if coming to or from an invalid rate, or if we're at time 0 (startup) - sound_assert(rate >= SAMPLE_RATE_MINIMUM - 1); - if (rate < SAMPLE_RATE_MINIMUM || m_sample_rate < SAMPLE_RATE_MINIMUM || (m_end_second == 0 && m_end_sample == 0)) + if (rate.disabled() || !m_sample_rate.disabled() || (m_end_second == 0 && m_end_sample == 0)) resample = false; // note the time and period of the current buffer (end_time is AFTER the final sample) @@ -99,7 +100,7 @@ void stream_buffer::set_sample_rate(u32 rate, bool resample) attotime prevend = end_time(); // compute the time and period of the new buffer - attotime newperiod = attotime(0, (ATTOSECONDS_PER_SECOND + rate - 1) / rate); + attotime newperiod = attotime(0, (ATTOSECONDS_PER_SECOND + irate - 1) / irate); attotime newend = attotime(prevend.seconds(), (prevend.attoseconds() / newperiod.attoseconds()) * newperiod.attoseconds()); // buffer a short runway of previous samples; in order to support smooth @@ -109,11 +110,11 @@ void stream_buffer::set_sample_rate(u32 rate, bool resample) // voice when jumping off the edge in Q*Bert; without this extra effort // it is crackly and/or glitchy at times sample_t buffer[64]; - int buffered_samples = std::min(m_sample_rate, std::min(rate, u32(std::size(buffer)))); + int buffered_samples = std::min(m_sample_rate.value(), std::min(irate, u32(std::size(buffer)))); // if the new rate is lower, downsample into our holding buffer; // otherwise just copy into our holding buffer for later upsampling - bool new_rate_higher = (rate > m_sample_rate); + bool new_rate_higher = (irate > m_sample_rate.value()); if (resample) { if (!new_rate_higher) @@ -137,8 +138,8 @@ void stream_buffer::set_sample_rate(u32 rate, bool resample) } // ensure our buffer is large enough to hold a full second at the new rate - if (m_buffer.size() < rate) - m_buffer.resize(rate); + if (m_buffer.size() < irate) + m_buffer.resize(irate); // set the new rate m_sample_rate = rate; @@ -529,7 +530,7 @@ read_stream_view sound_stream_input::update(attotime start, attotime end) // them of our current rate //------------------------------------------------- -void sound_stream_input::apply_sample_rate_changes(u32 updatenum, u32 downstream_rate) +void sound_stream_input::apply_sample_rate_changes(u32 updatenum, const XTAL &downstream_rate) { // shouldn't get here unless valid sound_assert(valid()); @@ -553,21 +554,21 @@ void sound_stream_input::apply_sample_rate_changes(u32 updatenum, u32 downstream // sound_stream - private common constructor //------------------------------------------------- -sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, sound_stream_flags flags) : +sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, const XTAL &sample_rate, u32 flags) : m_device(device), m_next(nullptr), - m_sample_rate((sample_rate < SAMPLE_RATE_MINIMUM) ? (SAMPLE_RATE_MINIMUM - 1) : (sample_rate < SAMPLE_RATE_OUTPUT_ADAPTIVE) ? sample_rate : 48000), - m_pending_sample_rate(SAMPLE_RATE_INVALID), + m_sample_rate(sample_rate), + m_pending_sample_rate(), m_last_sample_rate_update(0), - m_input_adaptive(sample_rate == SAMPLE_RATE_INPUT_ADAPTIVE), - m_output_adaptive(sample_rate == SAMPLE_RATE_OUTPUT_ADAPTIVE), + m_input_adaptive(flags & SAMPLE_RATE_INPUT_ADAPTIVE), + m_output_adaptive(flags & SAMPLE_RATE_OUTPUT_ADAPTIVE), m_synchronous((flags & STREAM_SYNCHRONOUS) != 0), m_resampling_disabled((flags & STREAM_DISABLE_INPUT_RESAMPLING) != 0), m_sync_timer(nullptr), m_last_update_end_time(attotime::zero), m_input(inputs), m_input_view(inputs), - m_empty_buffer(100), + m_empty_buffer(), m_output_base(output_base), m_output(outputs), m_output_view(outputs) @@ -620,7 +621,7 @@ sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output // sound_stream - constructor //------------------------------------------------- -sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags) : +sound_stream::sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, const XTAL &sample_rate, stream_update_delegate callback, u32 flags) : sound_stream(device, inputs, outputs, output_base, sample_rate, flags) { m_callback_ex = std::move(callback); @@ -641,7 +642,7 @@ sound_stream::~sound_stream() // given stream //------------------------------------------------- -void sound_stream::set_sample_rate(u32 new_rate) +void sound_stream::set_sample_rate(const XTAL &new_rate) { // we will update this on the next global update if (new_rate != sample_rate()) @@ -724,7 +725,7 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out // skip if nothing to do u32 samples = m_output_view[0].samples(); sound_assert(samples >= 0); - if (samples != 0 && m_sample_rate >= SAMPLE_RATE_MINIMUM) + if (samples != 0 && m_sample_rate.enabled()) { sound_assert(!synchronous() || samples == 1); @@ -771,16 +772,11 @@ read_stream_view sound_stream::update_view(attotime start, attotime end, u32 out // pending sample rate change, apply it now //------------------------------------------------- -void sound_stream::apply_sample_rate_changes(u32 updatenum, u32 downstream_rate) +void sound_stream::apply_sample_rate_changes(u32 updatenum, const XTAL &downstream_rate) { // grab the new rate and invalidate - u32 new_rate = (m_pending_sample_rate != SAMPLE_RATE_INVALID) ? m_pending_sample_rate : m_sample_rate; - m_pending_sample_rate = SAMPLE_RATE_INVALID; - - // clamp to the minimum - 1 (anything below minimum means "off" and - // will not call the sound callback at all) - if (new_rate < SAMPLE_RATE_MINIMUM) - new_rate = SAMPLE_RATE_MINIMUM - 1; + XTAL new_rate = m_pending_sample_rate.enabled() ? m_pending_sample_rate : m_sample_rate; + m_pending_sample_rate = XTAL(); // if we're input adaptive, override with the rate of our input if (input_adaptive() && m_input.size() > 0 && m_input[0].valid()) @@ -797,11 +793,11 @@ void sound_stream::apply_sample_rate_changes(u32 updatenum, u32 downstream_rate) } // if something is different, process the change - if (new_rate != SAMPLE_RATE_INVALID && new_rate != m_sample_rate) + if (new_rate.enabled() && new_rate != m_sample_rate) { // update to the new rate and notify everyone #if (SOUND_DEBUG) - printf("stream %s changing rates %d -> %d\n", name().c_str(), m_sample_rate, new_rate); + printf("stream %s changing rates %d -> %d\n", name().c_str(), m_sample_rate.value(), new_rate.value()); #endif m_sample_rate = new_rate; sample_rate_changed(); @@ -845,7 +841,7 @@ void sound_stream::print_graph_recursive(int indent, int index) void sound_stream::sample_rate_changed() { // if invalid, just punt - if (m_sample_rate == SAMPLE_RATE_INVALID) + if (m_sample_rate.disabled()) return; // update all output buffers @@ -938,7 +934,7 @@ read_stream_view sound_stream::empty_view(attotime start, attotime end) //------------------------------------------------- default_resampler_stream::default_resampler_stream(device_t &device) : - sound_stream(device, 1, 1, 0, SAMPLE_RATE_OUTPUT_ADAPTIVE, stream_update_delegate(&default_resampler_stream::resampler_sound_update, this), STREAM_DISABLE_INPUT_RESAMPLING), + sound_stream(device, 1, 1, 0, XTAL(), stream_update_delegate(&default_resampler_stream::resampler_sound_update, this), STREAM_DISABLE_INPUT_RESAMPLING|SAMPLE_RATE_OUTPUT_ADAPTIVE), m_max_latency(0) { // create a name @@ -963,7 +959,7 @@ void default_resampler_stream::resampler_sound_update(sound_stream &stream, std: auto &output = outputs[0]; // if the input has an invalid rate, just fill with zeros - if (input.sample_rate() <= 1) + if (input.sample_rate().disabled()) { output.fill(0); return; @@ -973,7 +969,7 @@ void default_resampler_stream::resampler_sound_update(sound_stream &stream, std: sound_assert(input.sample_rate() != output.sample_rate()); // compute the stepping value and the inverse - stream_buffer::sample_t step = stream_buffer::sample_t(input.sample_rate()) / stream_buffer::sample_t(output.sample_rate()); + stream_buffer::sample_t step = stream_buffer::sample_t(input.sample_rate().value()) / stream_buffer::sample_t(output.sample_rate().value()); stream_buffer::sample_t stepinv = 1.0 / step; // determine the latency we need to introduce, in input samples: @@ -1080,9 +1076,9 @@ sound_manager::sound_manager(running_machine &machine) : m_last_update(attotime::zero), m_finalmix_leftover(0), m_samples_this_update(0), - m_finalmix(machine.sample_rate()), - m_leftmix(machine.sample_rate()), - m_rightmix(machine.sample_rate()), + m_finalmix(machine.sample_rate().value()), + m_leftmix(machine.sample_rate().value()), + m_rightmix(machine.sample_rate().value()), m_compressor_scale(1.0), m_compressor_counter(0), m_compressor_enabled(machine.options().compressor()), @@ -1135,7 +1131,7 @@ sound_manager::~sound_manager() // new-style callback and flags //------------------------------------------------- -sound_stream *sound_manager::stream_alloc(device_t &device, u32 inputs, u32 outputs, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags) +sound_stream *sound_manager::stream_alloc(device_t &device, u32 inputs, u32 outputs, const XTAL &sample_rate, stream_update_delegate callback, u32 flags) { // determine output base u32 output_base = 0; @@ -1156,7 +1152,7 @@ bool sound_manager::start_recording(std::string_view filename) { if (m_wavfile) return false; - m_wavfile = util::wav_open(filename, machine().sample_rate(), 2); + m_wavfile = util::wav_open(filename, machine().sample_rate().value(), 2); return bool(m_wavfile); } diff --git a/src/emu/sound.h b/src/emu/sound.h index 15f6a5743a2..9387a6bc30c 100644 --- a/src/emu/sound.h +++ b/src/emu/sound.h @@ -65,20 +65,6 @@ //************************************************************************** -// CONSTANTS -//************************************************************************** - -// special sample-rate values -constexpr u32 SAMPLE_RATE_INVALID = 0xffffffff; -constexpr u32 SAMPLE_RATE_INPUT_ADAPTIVE = 0xfffffffe; -constexpr u32 SAMPLE_RATE_OUTPUT_ADAPTIVE = 0xfffffffd; - -// anything below this sample rate is effectively treated as "off" -constexpr u32 SAMPLE_RATE_MINIMUM = 50; - - - -//************************************************************************** // DEBUGGING //************************************************************************** @@ -119,7 +105,7 @@ public: private: // constructor/destructor - stream_buffer(u32 sample_rate = 48000); + stream_buffer(const XTAL &sample_rate = XTAL()); ~stream_buffer(); // disable copying of stream_buffers directly @@ -127,10 +113,10 @@ private: stream_buffer &operator=(stream_buffer const &rhs) = delete; // return the current sample rate - u32 sample_rate() const { return m_sample_rate; } + XTAL sample_rate() const { return m_sample_rate; } // set a new sample rate - void set_sample_rate(u32 rate, bool resample); + void set_sample_rate(const XTAL &rate, bool resample); // return the current sample period in attoseconds attoseconds_t sample_period_attoseconds() const { return m_sample_attos; } @@ -148,7 +134,7 @@ private: // return the effective buffer size; currently it is a full second of audio // at the current sample rate, but this maybe change in the future - u32 size() const { return m_sample_rate; } + u32 size() const { return m_sample_rate.value(); } // read the sample at the given index (clamped); should be valid in all cases sample_t get(s32 index) const @@ -202,7 +188,7 @@ private: // internal state u32 m_end_second; // current full second of the buffer end u32 m_end_sample; // current sample number within the final second - u32 m_sample_rate; // sample rate of the data in the buffer + XTAL m_sample_rate; // sample rate of the data in the buffer attoseconds_t m_sample_attos; // pre-computed attoseconds per sample std::vector<sample_t> m_buffer; // vector of actual buffer data @@ -288,7 +274,7 @@ public: sample_t gain() const { return m_gain; } // return the sample rate of the data - u32 sample_rate() const { return m_buffer->sample_rate(); } + XTAL sample_rate() const { return m_buffer->sample_rate(); } // return the sample period (in attoseconds) of the data attoseconds_t sample_period_attoseconds() const { return m_buffer->sample_period_attoseconds(); } @@ -492,7 +478,7 @@ public: attotime end_time() const { return m_buffer.end_time(); } u32 index() const { return m_index; } stream_buffer::sample_t gain() const { return m_gain; } - u32 buffer_sample_rate() const { return m_buffer.sample_rate(); } + XTAL buffer_sample_rate() const { return m_buffer.sample_rate(); } // simple setters void set_gain(float gain) { m_gain = gain; } @@ -501,7 +487,7 @@ public: std::string name() const; // handle a changing sample rate - void sample_rate_changed(u32 rate) { m_buffer.set_sample_rate(rate, true); } + void sample_rate_changed(const XTAL &rate) { m_buffer.set_sample_rate(rate, true); } // return an output view covering a time period write_stream_view view(attotime start, attotime end) { return write_stream_view(m_buffer, start, end); } @@ -563,7 +549,7 @@ public: read_stream_view update(attotime start, attotime end); // tell inputs to apply sample rate changes - void apply_sample_rate_changes(u32 updatenum, u32 downstream_rate); + void apply_sample_rate_changes(u32 updatenum, const XTAL &downstream_rate); private: // internal state @@ -596,7 +582,15 @@ enum sound_stream_flags : u32 // specify that input streams should not be resampled; stream update handler // must be able to accommodate multiple strams of differing input rates - STREAM_DISABLE_INPUT_RESAMPLING = 0x02 + STREAM_DISABLE_INPUT_RESAMPLING = 0x02, + + // specify that the input frequency should be set to the connected + // source frequency + SAMPLE_RATE_INPUT_ADAPTIVE = 0x04, + + // specify that the output frequency should be set to the connected + // sink frequency + SAMPLE_RATE_OUTPUT_ADAPTIVE = 0x08, }; @@ -607,11 +601,11 @@ class sound_stream friend class sound_manager; // private common constructopr - sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, sound_stream_flags flags); + sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, const XTAL &sample_rate, u32 flags); public: // construction/destruction - sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags = STREAM_DEFAULT_FLAGS); + sound_stream(device_t &device, u32 inputs, u32 outputs, u32 output_base, const XTAL &sample_rate, stream_update_delegate callback, u32 flags = STREAM_DEFAULT_FLAGS); virtual ~sound_stream(); // simple getters @@ -631,13 +625,13 @@ public: sound_stream_output &output(int index) { sound_assert(index >= 0 && index < m_output.size()); return m_output[index]; } // sample rate and timing getters - u32 sample_rate() const { return (m_pending_sample_rate != SAMPLE_RATE_INVALID) ? m_pending_sample_rate : m_sample_rate; } + XTAL sample_rate() const { return m_pending_sample_rate.enabled() ? m_pending_sample_rate : m_sample_rate; } attotime sample_time() const { return m_output[0].end_time(); } attotime sample_period() const { return attotime(0, sample_period_attoseconds()); } - attoseconds_t sample_period_attoseconds() const { return (m_sample_rate != SAMPLE_RATE_INVALID) ? HZ_TO_ATTOSECONDS(m_sample_rate) : ATTOSECONDS_PER_SECOND; } + attoseconds_t sample_period_attoseconds() const { return m_sample_rate.enabled() ? HZ_TO_ATTOSECONDS(m_sample_rate.dvalue()) : ATTOSECONDS_PER_SECOND; } // set the sample rate of the stream; will kick in at the next global update - void set_sample_rate(u32 sample_rate); + void set_sample_rate(const XTAL &sample_rate); // connect the output 'outputnum' of given input_stream to this stream's input 'inputnum' void set_input(int inputnum, sound_stream *input_stream, int outputnum = 0, float gain = 1.0f); @@ -649,7 +643,7 @@ public: read_stream_view update_view(attotime start, attotime end, u32 outputnum = 0); // apply any pending sample rate changes; should only be called by the sound manager - void apply_sample_rate_changes(u32 updatenum, u32 downstream_rate); + void apply_sample_rate_changes(u32 updatenum, const XTAL &downstream_rate); #if (SOUND_DEBUG) // print one level of the sound graph and recursively tell our inputs to do the same @@ -662,7 +656,7 @@ protected: private: // perform most of the initialization here - void init_common(u32 inputs, u32 outputs, u32 sample_rate, sound_stream_flags flags); + void init_common(u32 inputs, u32 outputs, const XTAL &sample_rate, u32 flags); // if the sample rate has changed, this gets called to update internals void sample_rate_changed(); @@ -687,8 +681,8 @@ private: sound_stream *m_next; // next stream in the chain // general information - u32 m_sample_rate; // current live sample rate - u32 m_pending_sample_rate; // pending sample rate for dynamic changes + XTAL m_sample_rate; // current live sample rate + XTAL m_pending_sample_rate; // pending sample rate for dynamic changes u32 m_last_sample_rate_update; // update number of last sample rate change bool m_input_adaptive; // adaptive stream that runs at the sample rate of its input bool m_output_adaptive; // adaptive stream that runs at the sample rate of its output @@ -771,7 +765,7 @@ public: stream_buffer::sample_t compressor_scale() const { return m_compressor_scale; } // allocate a new stream with a new-style callback - sound_stream *stream_alloc(device_t &device, u32 inputs, u32 outputs, u32 sample_rate, stream_update_delegate callback, sound_stream_flags flags); + sound_stream *stream_alloc(device_t &device, u32 inputs, u32 outputs, const XTAL &sample_rate, stream_update_delegate callback, u32 flags); // WAV recording bool is_recording() const { return bool(m_wavfile); } diff --git a/src/emu/speaker.cpp b/src/emu/speaker.cpp index 3cbb14355a4..58792327ad1 100644 --- a/src/emu/speaker.cpp +++ b/src/emu/speaker.cpp @@ -31,7 +31,7 @@ DEFINE_DEVICE_TYPE(SPEAKER, speaker_device, "speaker", "Speaker") // speaker_device - constructor //------------------------------------------------- -speaker_device::speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +speaker_device::speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, SPEAKER, tag, owner, clock) , device_mixer_interface(mconfig, *this) , m_x(0.0) @@ -73,7 +73,7 @@ void speaker_device::mix(stream_buffer::sample_t *leftmix, stream_buffer::sample // track maximum sample value for each 0.1s bucket if (machine().options().speaker_report() != 0) { - u32 samples_per_bucket = m_mixer_stream->sample_rate() / BUCKETS_PER_SECOND; + u32 samples_per_bucket = m_mixer_stream->sample_rate().value() / BUCKETS_PER_SECOND; for (int sample = 0; sample < expected_samples; sample++) { m_current_max = std::max(m_current_max, fabsf(view.get(sample))); diff --git a/src/emu/speaker.h b/src/emu/speaker.h index 54aa00603c9..751ba29e566 100644 --- a/src/emu/speaker.h +++ b/src/emu/speaker.h @@ -46,11 +46,11 @@ class speaker_device : public device_t, public device_mixer_interface public: // construction/destruction speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, double x, double y, double z) - : speaker_device(mconfig, tag, owner, 0) + : speaker_device(mconfig, tag, owner) { set_position(x, y, z); } - speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + speaker_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock = XTAL()); virtual ~speaker_device(); // inline configuration helpers diff --git a/src/emu/tilemap.cpp b/src/emu/tilemap.cpp index 5757f35341f..422aca9bbd6 100644 --- a/src/emu/tilemap.cpp +++ b/src/emu/tilemap.cpp @@ -1659,7 +1659,7 @@ DEFINE_DEVICE_TYPE(TILEMAP, tilemap_device, "tilemap", "Tilemap") // tilemap_device - constructor //------------------------------------------------- -tilemap_device::tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock) +tilemap_device::tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock) : device_t(mconfig, TILEMAP, tag, owner, clock) , tilemap_t(static_cast<device_t &>(*this)) , m_gfxdecode(*this, finder_base::DUMMY_TAG) diff --git a/src/emu/tilemap.h b/src/emu/tilemap.h index b6b2c566bfa..46ffe2a836b 100644 --- a/src/emu/tilemap.h +++ b/src/emu/tilemap.h @@ -669,7 +669,7 @@ public: template <typename T> tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&gfxtag, int entrybytes , u16 tilewidth, u16 tileheight, tilemap_standard_mapper mapper, u32 columns, u32 rows, pen_t transpen) - : tilemap_device(mconfig, tag, owner, (u32)0) + : tilemap_device(mconfig, tag, owner) { set_gfxdecode(std::forward<T>(gfxtag)); set_bytes_per_entry(entrybytes); @@ -681,7 +681,7 @@ public: template <typename T> tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&gfxtag, int entrybytes , u16 tilewidth, u16 tileheight, tilemap_standard_mapper mapper, u32 columns, u32 rows) - : tilemap_device(mconfig, tag, owner, (u32)0) + : tilemap_device(mconfig, tag, owner) { set_gfxdecode(std::forward<T>(gfxtag)); set_bytes_per_entry(entrybytes); @@ -691,14 +691,14 @@ public: template <typename T> tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, T &&gfxtag, int entrybytes, u16 tilewidth, u16 tileheight) - : tilemap_device(mconfig, tag, owner, (u32)0) + : tilemap_device(mconfig, tag, owner) { set_gfxdecode(std::forward<T>(gfxtag)); set_bytes_per_entry(entrybytes); set_tile_size(tilewidth, tileheight); } - tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, u32 clock = 0); + tilemap_device(const machine_config &mconfig, const char *tag, device_t *owner, const XTAL &clock = XTAL()); template <typename T> void set_gfxdecode(T &&tag) { m_gfxdecode.set_tag(std::forward<T>(tag)); } void set_bytes_per_entry(int bpe) { m_bytes_per_entry = bpe; } diff --git a/src/emu/validity.cpp b/src/emu/validity.cpp index 8fed2d6def0..6b23a8831d8 100644 --- a/src/emu/validity.cpp +++ b/src/emu/validity.cpp @@ -2656,7 +2656,7 @@ void validity_checker::validate_device_types() machine_config::token const tok(config.begin_configuration(config.root_device())); for (device_type type : registered_device_types) { - device_t *const dev = config.device_add(type.shortname(), type, 0); + device_t *const dev = config.device_add(type.shortname(), type); char const *name((dev->shortname() && *dev->shortname()) ? dev->shortname() : type.type().name()); std::string const description((dev->source() && *dev->source()) ? util::string_format("%s(%s)", core_filename_extract_base(dev->source()), name) : name); @@ -2696,7 +2696,7 @@ void validity_checker::validate_device_types() } else if (!devname.second) { - device_t *const dup = config.device_add("_dup", *devname.first->second, 0); + device_t *const dup = config.device_add("_dup", *devname.first->second); osd_printf_error("Device %s short name is a duplicate of %s(%s)\n", description, core_filename_extract_base(dup->source()), dup->shortname()); config.device_remove("_dup"); } @@ -2720,7 +2720,7 @@ void validity_checker::validate_device_types() } else if (!devdesc.second) { - device_t *const dup = config.device_add("_dup", *devdesc.first->second, 0); + device_t *const dup = config.device_add("_dup", *devdesc.first->second); osd_printf_error("Device %s name '%s' is a duplicate of %s(%s)\n", description, dev->name(), core_filename_extract_base(dup->source()), dup->shortname()); config.device_remove("_dup"); } diff --git a/src/emu/xtal.cpp b/src/emu/xtal.cpp index fc606c4f7db..5f9d661acf6 100644 --- a/src/emu/xtal.cpp +++ b/src/emu/xtal.cpp @@ -550,12 +550,18 @@ bool XTAL::validate(double base_clock) void XTAL::validate(const char *message) const { + if(!m_base_clock || m_disable_validation) + return; + if(!validate(m_base_clock)) fail(m_base_clock, message); } void XTAL::validate(const std::string &message) const { + if(!m_base_clock || m_disable_validation) + return; + if(!validate(m_base_clock)) fail(m_base_clock, message); } diff --git a/src/emu/xtal.h b/src/emu/xtal.h index b58f00943b2..700e75e730f 100644 --- a/src/emu/xtal.h +++ b/src/emu/xtal.h @@ -45,27 +45,47 @@ Usage: class XTAL { public: + constexpr explicit XTAL() : m_base_clock(0), m_current_clock(0), m_disable_validation(true) {} - constexpr explicit XTAL(double base_clock) : m_base_clock(base_clock), m_current_clock(base_clock) {} + constexpr explicit XTAL(double base_clock) : m_base_clock(base_clock), m_current_clock(base_clock), m_disable_validation(true) {} constexpr double dvalue() const noexcept { return m_current_clock; } constexpr u32 value() const noexcept { return u32(m_current_clock + 1e-3); } constexpr double base() const noexcept { return m_base_clock; } - template <typename T> constexpr XTAL operator *(T &&mult) const noexcept { return XTAL(m_base_clock, m_current_clock * mult); } - template <typename T> constexpr XTAL operator /(T &&div) const noexcept { return XTAL(m_base_clock, m_current_clock / div); } + template <typename T> constexpr XTAL operator *(T &&mult) const noexcept { return XTAL(m_base_clock, m_current_clock * mult, m_disable_validation); } + template <typename T> constexpr XTAL operator /(T &&div) const noexcept { return XTAL(m_base_clock, m_current_clock / div, m_disable_validation); } friend constexpr XTAL operator *(int mult, const XTAL &xtal); friend constexpr XTAL operator *(unsigned int mult, const XTAL &xtal); - friend constexpr XTAL operator *(double mult, const XTAL &xtal); + friend constexpr XTAL operator *(const XTAL &xtal, int mult); + friend constexpr XTAL operator *(const XTAL &xtal, unsigned int mult); + friend constexpr XTAL operator /(const XTAL &xtal, int div); + friend constexpr XTAL operator /(const XTAL &xtal, unsigned int div); + + static constexpr XTAL u(unsigned int clock); void validate(const char *message) const; void validate(const std::string &message) const; + bool disabled() const noexcept { return m_base_clock == 0; } + bool enabled() const noexcept { return m_base_clock != 0; } + + bool operator == (const XTAL &clock) const { + return clock.m_base_clock == m_base_clock && clock.m_current_clock == m_current_clock; + } + + bool operator != (const XTAL &clock) const { + return !(*this == clock); + } + + private: + friend class save_manager; double m_base_clock, m_current_clock; + bool m_disable_validation; - constexpr XTAL(double base_clock, double current_clock) noexcept : m_base_clock(base_clock), m_current_clock(current_clock) {} + constexpr XTAL(double base_clock, double current_clock, bool disable_validation) noexcept : m_base_clock(base_clock), m_current_clock(current_clock), m_disable_validation(disable_validation) {} static const double known_xtals[]; static double last_correct_value, xtal_error_low, xtal_error_high; @@ -76,9 +96,14 @@ private: template <typename T> constexpr auto operator /(T &&div, const XTAL &xtal) { return div / xtal.dvalue(); } -constexpr XTAL operator *(int mult, const XTAL &xtal) { return XTAL(xtal.base(), mult * xtal.dvalue()); } -constexpr XTAL operator *(unsigned int mult, const XTAL &xtal) { return XTAL(xtal.base(), mult * xtal.dvalue()); } -constexpr XTAL operator *(double mult, const XTAL &xtal) { return XTAL(xtal.base(), mult * xtal.dvalue()); } +constexpr XTAL operator *(int mult, const XTAL &xtal) { return XTAL(xtal.base(), xtal.dvalue() * mult, xtal.m_disable_validation); } +constexpr XTAL operator *(unsigned int mult, const XTAL &xtal) { return XTAL(xtal.base(), xtal.dvalue() * mult, xtal.m_disable_validation); } +constexpr XTAL operator *(const XTAL &xtal, int mult) { return XTAL(xtal.base(), xtal.dvalue() * mult, xtal.m_disable_validation); } +constexpr XTAL operator *(const XTAL &xtal, unsigned int mult) { return XTAL(xtal.base(), xtal.dvalue() * mult, xtal.m_disable_validation); } +constexpr XTAL operator /(const XTAL &xtal, int div) { return XTAL(xtal.base(), xtal.dvalue() / div, xtal.m_disable_validation); } +constexpr XTAL operator /(const XTAL &xtal, unsigned int div) { return XTAL(xtal.base(), xtal.dvalue() / div, xtal.m_disable_validation); } + +constexpr XTAL XTAL::u(unsigned int clock) { return XTAL(clock, clock, true); } constexpr XTAL operator ""_Hz_XTAL(long double clock) { return XTAL(double(clock)); } constexpr XTAL operator ""_kHz_XTAL(long double clock) { return XTAL(double(clock * 1e3)); } |