protected virtual void set_rmcr(uint8_t data) { if (m_rmcr == data) { return; } m_rmcr = data; switch ((m_rmcr & M6801_RMCR_CC_MASK) >> 2) { case 0: LOGSER("SCI: Using external serial clock: false\n"); m_sci_timer.enable(false); m_use_ext_serclock = false; break; case 3: // external clock LOGSER("SCI: Using external serial clock: true\n"); m_use_ext_serclock = true; m_sci_timer.enable(false); break; case 1: case 2: { int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; attotime period = cycles_to_attotime((uint64_t)divisor); LOGSER("SCI: Setting serial rate, Divisor: {0} Hz: {1}\n", divisor, period.as_hz()); m_sci_timer.adjust(period, 0, period); m_use_ext_serclock = false; } break; } }
keycode_map m_keycode_map = new keycode_map(); // keycode map // construction/destruction //------------------------------------------------- // natural_keyboard - constructor //------------------------------------------------- public natural_keyboard(running_machine machine) { m_machine = machine; m_in_use = false; m_bufbegin = 0; m_bufend = 0; m_fieldnum = 0; m_status_keydown = false; m_last_cr = false; m_timer = null; m_current_rate = attotime.zero; m_queue_chars = null; m_accept_char = null; m_charqueue_empty = null; // try building a list of keycodes; if none are available, don't bother build_codes(machine.ioport()); if (!m_keycode_map.empty()) { m_buffer.resize(KEY_BUFFER_SIZE); m_timer = machine.scheduler().timer_alloc(timer); } // retrieve option setting set_in_use(machine.options().natural_keyboard()); }
emu_timer m_timer; // timer for triggering reset // construction/destruction //------------------------------------------------- // watchdog_timer_device - constructor //------------------------------------------------- watchdog_timer_device(machine_config mconfig, string tag, device_t owner, uint32_t clock = 0) : base(mconfig, WATCHDOG_TIMER, tag, owner, clock) { m_vblank_count = 0; m_time = attotime.zero; m_screen = new optional_device <screen_device>(this, finder_base.DUMMY_TAG); }
void set_rmcr(uint8_t data) { if (m_rmcr == data) { return; } m_rmcr = data; switch ((m_rmcr & M6801_RMCR_CC_MASK) >> 2) { case 0: m_sci_timer.enable(false); m_use_ext_serclock = false; break; case 3: // external clock m_use_ext_serclock = true; m_sci_timer.enable(false); break; case 1: case 2: { int divisor = M6801_RMCR_SS[m_rmcr & M6801_RMCR_SS_MASK]; attotime period = cycles_to_attotime((u64)divisor); m_sci_timer.adjust(period, 0, period); m_use_ext_serclock = false; } break; } }
public static attotime operator*(UInt32 factor, attotime right) { attotime result = right; result *= factor; return(result); }
// construction/destruction //------------------------------------------------- // eeprom_base_device - constructor //------------------------------------------------- protected eeprom_base_device(machine_config mconfig, device_type devtype, string tag, device_t owner) : base(mconfig, devtype, tag, owner, 0) { m_class_interfaces.Add(new device_nvram_interface_eeprom(mconfig, this)); //device_nvram_interface(mconfig, *this), m_nvram_interface = GetClassInterface <device_nvram_interface_eeprom>(); m_region = new optional_memory_region(this, DEVICE_SELF); m_cells = 0; m_address_bits = 0; m_data_bits = 0; m_default_data = null; m_default_data_size = 0; m_default_value = 0; m_default_value_set = false; m_completion_time = attotime.zero; // a 2ms write time is too long for rfjetsa m_operation_time[(int)timing_type.WRITE_TIME] = attotime.from_usec(1750); m_operation_time[(int)timing_type.WRITE_ALL_TIME] = attotime.from_usec(8000); m_operation_time[(int)timing_type.ERASE_TIME] = attotime.from_usec(1000); m_operation_time[(int)timing_type.ERASE_ALL_TIME] = attotime.from_usec(8000); }
public void adjust(attotime start_delay, int param, attotime period) //void adjust(attotime start_delay, s32 param = 0, const attotime &periodicity = attotime::never); { // if this is the callback timer, mark it modified device_scheduler scheduler = machine().scheduler(); if (scheduler.callback_timer() == this) { scheduler.callback_timer_modified_set(true); } // compute the time of the next firing and insert into the list m_param = param; m_enabled = true; // clamp negative times to 0 if (start_delay.seconds() < 0) { start_delay = attotime.zero; } // set the start and expire times m_start = scheduler.time(); m_expire = m_start + start_delay; m_period = period; // remove and re-insert the timer in its new order scheduler.timer_list_remove(this); scheduler.timer_list_insert(this); // if this was inserted as the head, abort the current timeslice and resync if (this == scheduler.first_timer()) { scheduler.abort_timeslice(); } }
//void debugger_exception_hook(int exception) { if (device().machine().debug_flags & DEBUG_FLAG_ENABLED) device().debug()->exception_hook(exception); } //void debugger_privilege_hook() { if (device().machine().debug_flags & DEBUG_FLAG_ENABLED) device().debug()->privilege_hook(); } // internal debugger hooks public void debugger_start_cpu_hook(attotime endtime) { if ((device().machine().debug_flags_get & machine_global.DEBUG_FLAG_ENABLED) != 0) { device().debug().start_hook(endtime); } }
//------------------------------------------------- // operator+ - handle addition between two // attotimes //------------------------------------------------- public static attotime operator+(attotime left, attotime right) { // if one of the items is never, return never if (left.m_seconds >= ATTOTIME_MAX_SECONDS || right.m_seconds >= ATTOTIME_MAX_SECONDS) { return(attotime.never); } // add the seconds and attoseconds attoseconds_t attoseconds = left.m_attoseconds + right.m_attoseconds; seconds_t seconds = left.m_seconds + right.m_seconds; attotime result = new attotime(seconds, attoseconds); // normalize and return if (result.m_attoseconds >= ATTOSECONDS_PER_SECOND) { result.m_attoseconds -= ATTOSECONDS_PER_SECOND; result.m_seconds++; } // overflow if (result.m_seconds >= ATTOTIME_MAX_SECONDS) { return(attotime.never); } return(result); }
//------------------------------------------------- // interface_post_reset - work to be done after a // device is reset //------------------------------------------------- public override void interface_post_reset() { // reset the interrupt vectors and queues for (int line = 0; line < m_input.Length; line++) { m_input[line].reset(); } // reconfingure VBLANK interrupts if (!string.IsNullOrEmpty(m_vblank_interrupt_screen)) { // get the screen that will trigger the VBLANK screen_device screen = device().siblingdevice <screen_device>(m_vblank_interrupt_screen); //assert(screen != NULL); screen.register_vblank_callback(on_vblank); } // reconfigure periodic interrupts if (m_timed_interrupt_period != attotime.zero) { attotime timedint_period = m_timed_interrupt_period; //assert(m_timedint_timer != NULL); m_timedint_timer.adjust(timedint_period, 0, timedint_period); } }
// allocation and re-use //------------------------------------------------- // init - completely initialize the state when // re-allocated as a non-device timer //------------------------------------------------- public emu_timer init(running_machine machine, timer_expired_delegate callback, object o, bool temporary) { // ensure the entire timer state is clean m_machine = machine; m_next = null; m_prev = null; m_callback = callback; m_param = 0; m_ptr = o; m_enabled = false; m_temporary = temporary; m_period = attotime.never; m_start = machine.time(); m_expire = attotime.never; m_device = null; m_id = 0; // if we're not temporary, register ourselves with the save state system if (!m_temporary) { register_save(); } // insert into the list machine.scheduler().timer_list_insert(this); return(this); }
//------------------------------------------------- // interface_post_reset - work to be done after a // device is reset //------------------------------------------------- public override void interface_post_reset() { // reset the interrupt vectors and queues foreach (var elem in m_input) { elem.reset(); } // reconfingure VBLANK interrupts if (!string.IsNullOrEmpty(m_vblank_interrupt_screen)) { // get the screen that will trigger the VBLANK screen_device screen = device().siblingdevice <screen_device>(m_vblank_interrupt_screen); //throw new emu_unimplemented(); #if false assert(screen != nullptr); #endif screen.register_vblank_callback(on_vblank); } // reconfigure periodic interrupts if (m_timed_interrupt_period != attotime.zero) { attotime timedint_period = m_timed_interrupt_period; //throw new emu_unimplemented(); #if false assert(m_timedint_timer != nullptr); #endif m_timedint_timer.adjust(timedint_period, 0, timedint_period); } }
//------------------------------------------------- // init - completely initialize the state when // re-allocated as a device timer //------------------------------------------------- public emu_timer init(device_t device, device_timer_id id, object ptr, bool temporary) { // ensure the entire timer state is clean m_machine = device.machine(); m_next = null; m_prev = null; m_callback = null; m_param = 0; m_ptr = ptr; m_enabled = false; m_temporary = temporary; m_period = attotime.never; m_start = machine().time(); m_expire = attotime.never; m_device = device; m_id = id; // if we're not temporary, register ourselves with the save state system if (!m_temporary) { register_save(); } // insert into the list machine().scheduler().timer_list_insert(this); return(this); }
public static attotime operator/(attotime left, u32 factor) { attotime result = left; result /= factor; return(result); }
void sync_update(object o, int param) //(void *, INT32) { update(); attotime time = m_device.machine().time(); attoseconds_t next_edge = m_attoseconds_per_sample - (time.attoseconds() % m_attoseconds_per_sample); m_sync_timer.adjust(new attotime(0, next_edge)); }
/// \brief Get a device replacement helper /// /// Pass the result in place of the machine configuration itself to /// replace an existing device. /// \return A device replacement helper to pass to a device type /// when replacing an existing device. //emu::detail::machine_config_replace replace() { return emu::detail::machine_config_replace(*this); }; /// \brief Set internal layout for current device /// /// Set internal layout for current device. Each device in the /// system can have its own internal layout. Tags in the layout /// will be resolved relative to the device. Replaces previously /// set layout if any. /// \param [in] layout Reference to the internal layout description /// structure. Neither the description structure nor the /// compressed data is copied. It is the caller's responsibility /// to ensure both remain valid until layouts and views are /// instantiated. //void set_default_layout(internal_layout const &layout); /// \brief Set maximum scheduling quantum /// /// Set the maximum scheduling quantum required for the current /// device. The smallest maximum quantum requested by a device in /// the system will be used. /// \param [in] quantum Maximum scheduling quantum in attoseconds. public void set_maximum_quantum(attotime quantum) { bool ins = m_maximum_quantums.emplace(current_device().tag(), quantum); //std::pair<maximum_quantum_map::iterator, bool> const ins(m_maximum_quantums.emplace(current_device().tag(), quantum)); if (!ins) //if (!ins.second) { m_maximum_quantums[current_device().tag()] = quantum; //ins.first->second = quantum; } }
//------------------------------------------------- // write - write data at the given address //------------------------------------------------- protected void write(offs_t address, uint32_t data) { if (!ready()) { logerror("EEPROM: Write performed before previous operation completed!\n"); } internal_write(address, data); m_completion_time = machine().time() + m_operation_time[(int)timing_type.WRITE_TIME]; }
namco_54xx_device(machine_config mconfig, string tag, device_t owner, u32 clock) : base(mconfig, NAMCO_54XX, tag, owner, clock) { m_cpu = new required_device <mb88_cpu_device>(this, "mcu"); m_discrete = new required_device <discrete_device>(this, finder_base.DUMMY_TAG); m_irq_duration = attotime.from_usec(100); m_basenode = 0; m_latched_cmd = 0; }
//template<class DeviceClass> inline DeviceClass *device(const char *tag) const { return downcast<DeviceClass *>(device(tag)); } public attotime maximum_quantum(attotime default_quantum) { //return std::accumulate( // m_maximum_quantums.begin(), // m_maximum_quantums.end(), // default_quantum, // [] (attotime const &lhs, maximum_quantum_map::value_type const &rhs) { return (std::min)(lhs, rhs.second); }); return(Enumerable.Aggregate(m_maximum_quantums, default_quantum, (current, next) => { return std.min(current, next.second()); })); }
//void trigger(int trigid, const attotime &after = attotime::zero); //------------------------------------------------- // boost_interleave - temporarily boosts the // interleave factor //------------------------------------------------- public void boost_interleave(attotime timeslice_time, attotime boost_duration) { // ignore timeslices > 1 second if (timeslice_time.seconds() > 0) { return; } add_scheduling_quantum(timeslice_time, boost_duration); }
//------------------------------------------------- // schedule_next_period - schedule the next // period //------------------------------------------------- public void schedule_next_period() { // advance by one period m_start = m_expire; m_expire += m_period; // remove and re-insert us device_scheduler scheduler = machine().scheduler(); scheduler.timer_list_remove(this); scheduler.timer_list_insert(this); }
//------------------------------------------------- // record_frame - record a frame of a movie //------------------------------------------------- void record_frame() { // ignore if nothing to do if (!is_recording()) { return; } // start the profiler and get the current time g_profiler.start(profile_type.PROFILER_MOVIE_REC); attotime curtime = machine().time(); throw new emu_unimplemented(); }
bool m_first_time; // indicates that the system is starting (scanline timers only) // construction/destruction //------------------------------------------------- // timer_device - constructor //------------------------------------------------- timer_device(machine_config mconfig, string tag, device_t owner, u32 clock) : base(mconfig, TIMER, tag, owner, clock) { m_type = timer_type.TIMER_TYPE_GENERIC; m_callback = null; m_ptr = null; m_start_delay = attotime.zero; m_period = attotime.zero; m_param = 0; m_screen = new optional_device <screen_device>(this, finder_base.DUMMY_TAG); m_first_vpos = 0; m_increment = 0; m_timer = null; m_first_time = true; }
string m_string_buffer; //mutable util::ovectorstream m_string_buffer; // construction/destruction //------------------------------------------------- // running_machine - constructor //------------------------------------------------- public running_machine(machine_config _config, machine_manager manager) { m_side_effects_disabled = 0; debug_flags = 0; m_config = _config; m_system = _config.gamedrv(); m_manager = manager; m_current_phase = machine_phase.PREINIT; m_paused = false; m_hard_reset_pending = false; m_exit_pending = false; m_soft_reset_timer = null; m_rand_seed = 0x9d14abd7; m_ui_active = _config.options().ui_active(); m_basename = _config.gamedrv().name; m_sample_rate = _config.options().sample_rate(); m_saveload_schedule = saveload_schedule.NONE; m_saveload_schedule_time = attotime.zero; m_saveload_searchpath = null; m_save = new save_manager(this); m_memory = new memory_manager(this); m_ioport = new ioport_manager(this); m_scheduler = new device_scheduler(this); m_scheduler.device_scheduler_after_ctor(this); for (int i = 0; i < m_notifier_list.Length; i++) { m_notifier_list[i] = new std.list <notifier_callback_item>(); } m_base_time = 0; // set the machine on all devices device_enumerator iter = new device_enumerator(root_device()); foreach (device_t device in iter) { device.set_machine(this); } // fetch core options if (options().debug()) { debug_flags = (DEBUG_FLAG_ENABLED | DEBUG_FLAG_CALL_HOOK) | (DEBUG_FLAG_OSD_ENABLED); } }
attotime m_last_update; // last update time // construction/destruction //------------------------------------------------- // sound_manager - constructor //------------------------------------------------- public sound_manager(running_machine machine) { m_machine = machine; m_update_timer = null; m_finalmix_leftover = 0; m_finalmix = new std.vector <s16>(machine.sample_rate()); m_leftmix = new std.vector <s32>(machine.sample_rate()); m_rightmix = new std.vector <s32>(machine.sample_rate()); m_nosound_mode = machine.osd().no_sound() ? 1 : 0; m_wavfile = null; m_update_attoseconds = STREAMS_UPDATE_ATTOTIME.attoseconds(); m_last_update = attotime.zero; // get filename for WAV file or AVI file if specified string wavfile = machine.options().wav_write(); string avifile = machine.options().avi_write(); // handle -nosound and lower sample rate if not recording WAV or AVI if (m_nosound_mode != 0 && string.IsNullOrEmpty(wavfile) && string.IsNullOrEmpty(avifile)) { machine.sample_rate_set(11025); } // count the mixers if (sound_global.VERBOSE) { mixer_interface_iterator iter = new mixer_interface_iterator(machine.root_device()); sound_global.VPRINTF("total mixers = {0}\n", iter.count()); } // register callbacks machine.configuration().config_register("mixer", config_load, config_save); machine.add_notifier(machine_notification.MACHINE_NOTIFY_PAUSE, pause); machine.add_notifier(machine_notification.MACHINE_NOTIFY_RESUME, resume); machine.add_notifier(machine_notification.MACHINE_NOTIFY_RESET, reset); machine.add_notifier(machine_notification.MACHINE_NOTIFY_EXIT, stop_recording); // register global states machine.save().save_item(m_last_update, "m_last_update"); // set the starting attenuation set_attenuation(machine.options().volume()); // start the periodic update flushing timer m_update_timer = machine.scheduler().timer_alloc(update, this); m_update_timer.adjust(STREAMS_UPDATE_ATTOTIME, 0, STREAMS_UPDATE_ATTOTIME); }
//------------------------------------------------- // update - force a stream to update to // the current emulated time //------------------------------------------------- public void update() { if (m_attoseconds_per_sample == 0) { return; } // determine the number of samples since the start of this second attotime time = m_device.machine().time(); int update_sampindex = (int)(time.attoseconds() / m_attoseconds_per_sample); // if we're ahead of the last update, then adjust upwards attotime last_update = m_device.machine().sound().last_update(); if (time.seconds() > last_update.seconds()) { assert(time.seconds() == last_update.seconds() + 1); update_sampindex += (int)m_sample_rate; } // if we're behind the last update, then adjust downwards if (time.seconds() < last_update.seconds()) { assert(time.seconds() == last_update.seconds() - 1); update_sampindex -= (int)m_sample_rate; } if (update_sampindex <= m_output_sampindex) { return; } // generate samples to get us up to the appropriate time profiler_global.g_profiler.start(profile_type.PROFILER_SOUND); //throw new emu_unimplemented(); #if false osdcomm_global.assert(m_output_sampindex - m_output_base_sampindex >= 0); osdcomm_global.assert(update_sampindex - m_output_base_sampindex <= m_output_bufalloc); #endif generate_samples(update_sampindex - m_output_sampindex); profiler_global.g_profiler.stop(); // remember this info for next time m_output_sampindex = update_sampindex; }
// timer helpers //------------------------------------------------- // timer_list_insert - insert a new timer into // the list at the appropriate location //------------------------------------------------- public emu_timer timer_list_insert(emu_timer timer) { // disabled timers sort to the end attotime expire = timer.enabled() ? timer.expire() : attotime.never; // loop over the timer list emu_timer prevtimer = null; for (emu_timer curtimer = m_timer_list; curtimer != null; prevtimer = curtimer, curtimer = curtimer.next()) { // if the current list entry expires after us, we should be inserted before it if (curtimer.expire() > expire) { // link the new guy in before the current list entry timer.m_prev = prevtimer; timer.m_next = curtimer; if (prevtimer != null) { prevtimer.m_next = timer; } else { m_timer_list = timer; } curtimer.m_prev = timer; return(timer); } } // need to insert after the last one if (prevtimer != null) { prevtimer.m_next = timer; } else { m_timer_list = timer; } timer.m_prev = prevtimer; timer.m_next = null; return(timer); }
protected override void device_clock_changed() { int prescaler = get_prescaler(); if (prescaler != 0) { logerror("/{0} prescaler selected\n", prescaler); attotime half_period = clocks_to_attotime((u64)(prescaler / 2)); m_vck_timer.adjust(half_period, 0, half_period); } else { logerror("VCK slave mode selected\n"); m_vck_timer.adjust(attotime.never); } }
//------------------------------------------------- // text - return the current text in an astring //------------------------------------------------- public string text(running_machine machine) { start(profile_type.PROFILER_PROFILER); // get the current time attotime current_time = machine.scheduler().time(); // we only want to update the text periodically if ((m_text_time == attotime.never) || ((current_time - m_text_time).as_double() >= TEXT_UPDATE_TIME)) { update_text(machine); m_text_time = current_time; } stop(); return(m_text); }
attoseconds_t m_quantum_minimum; // duration of minimum quantum // construction/destruction //------------------------------------------------- // device_scheduler - constructor //------------------------------------------------- public device_scheduler(running_machine machine) { m_machine = machine; m_basetime = attotime.zero; m_callback_timer_expire_time = attotime.zero; m_suspend_changes_pending = true; m_quantum_minimum = ATTOSECONDS_IN_NSEC(1) / 1000; // append a single never-expiring timer so there is always one in the list //m_timer_list = m_timer_allocator.alloc().init(machine, null, null, true); //m_timer_list.adjust(attotime.never); // register global states machine.save().save_item(m_basetime, "m_basetime"); machine.save().register_presave(presave); machine.save().register_postload(postload); }