Beispiel #1
0
void laserdisc_device::update_slider_pos()
{
	attotime curtime = machine().time();

	// if not moving, update to now
	if (m_attospertrack == 0)
		m_sliderupdate = curtime;

	// otherwise, compute the number of tracks covered
	else
	{
		attoseconds_t delta = (curtime - m_sliderupdate).as_attoseconds();

		// determine how many tracks we covered and advance
		if (m_attospertrack >= 0)
		{
			INT32 tracks_covered = delta / m_attospertrack;
			add_and_clamp_track(tracks_covered);
			if (tracks_covered != 0)
				m_sliderupdate += attotime(0, tracks_covered * m_attospertrack);
		}
		else
		{
			INT32 tracks_covered = delta / -m_attospertrack;
			add_and_clamp_track(-tracks_covered);
			if (tracks_covered != 0)
				m_sliderupdate += attotime(0, tracks_covered * -m_attospertrack);
		}
	}
}
Beispiel #2
0
void speaker_level_w(device_t *device, int new_level)
{
	speaker_state *sp = get_safe_token(device);
	int volume;
	attotime time;

	if (new_level == sp->level)
		return;

	if (new_level < 0)
		new_level = 0;
	else
	if (new_level >= sp->num_levels)
		new_level = sp->num_levels - 1;

	volume = sp->levels[sp->level];
	time = device->machine().time();

	if (time < sp->channel_next_sample_time)
	{
		/* Stream sample is yet unfinished, but we may have one or more interm. samples */
		update_interm_samples(sp, time, volume);

		/* Do not forget to update speaker state before returning! */
		sp->level = new_level;
		return;
	}
	/* Reaching here means such time has passed since last stream update
     * that we can add at least one complete sample to the stream.
     * The details have to be handled by speaker_sound_update()
     */

	/* Force streams.c to update sound until this point in time now */
	sp->channel->update();

	/* This is redundant because time update has to be done within speaker_sound_update() anyway,
     * however this ensures synchronization between the speaker and stream timing:
     */
	sp->channel_last_sample_time = sp->channel->sample_time();
	sp->channel_next_sample_time = sp->channel_last_sample_time + attotime(0, sp->channel_sample_period);
	sp->next_interm_sample_time = sp->channel_last_sample_time + attotime(0, sp->interm_sample_period);
	sp->last_update_time = sp->channel_last_sample_time;

	/* Assertion: time - last_update_time < channel_sample_period, i.e. time < channel_next_sample_time */

	/* The overshooting fraction of time will make zero, one or more interm. samples: */
	update_interm_samples(sp, time, volume);

	/* Finally update speaker state before returning */
	sp->level = new_level;

} /* speaker_level_w */
Beispiel #3
0
DRIVER_INIT_MEMBER(europc_pc_state,europc)
{
	UINT8 *rom = &memregion("maincpu")->base()[0];

	int i;
	/*
	  fix century rom bios bug !
	  if year <79 month (and not CENTURY) is loaded with 0x20
	*/
	if (rom[0xff93e]==0xb6){ // mov dh,
		UINT8 a;
		rom[0xff93e]=0xb5; // mov ch,
		for (i=0xf8000, a=0; i<0xfffff; i++ ) a+=rom[i];
		rom[0xfffff]=256-a;
	}

	memset(&m_rtc_data,0,sizeof(m_rtc_data));
	m_rtc_reg = 0;
	m_rtc_state = 0;
	m_rtc_data[0xf]=1;

	m_rtc_timer = timer_alloc();
	m_rtc_timer->adjust(attotime::zero, 0, attotime(1,0));
	//  europc_rtc_set_time();

	machine().device<nvram_device>("nvram")->set_base(m_rtc_data, sizeof(m_rtc_data));
	m_aga = machine().device<isa8_aga_device>("aga:aga");

}
Beispiel #4
0
ROM_END


/*-------------------------------------------------
    device start callback
-------------------------------------------------*/

static DEVICE_START( namco_52xx )
{
	namco_52xx_interface *intf = (namco_52xx_interface *)device->static_config();
	namco_52xx_state *state = get_safe_token(device);
	astring tempstring;

	/* find our CPU */
	state->m_cpu = device->subdevice("mcu");
	assert(state->m_cpu != NULL);

	/* find the attached discrete sound device */
	assert(intf->discrete != NULL);
	state->m_discrete = device->machine().device(intf->discrete);
	assert(state->m_discrete != NULL);
	state->m_basenode = intf->firstnode;

	/* resolve our read/write callbacks */
	state->m_romread.resolve(intf->romread, *device);
	state->m_si.resolve(intf->si, *device);

	/* start the external clock */
	if (intf->extclock != 0)
		device->machine().scheduler().timer_pulse(attotime(0, intf->extclock), FUNC(external_clock_pulse), 0, device);
}
Beispiel #5
0
void ttl74123_device::start_pulse()
{
	attotime duration = compute_duration();

	if(timer_running())
	{
		/* retriggering, but not if we are called to quickly */
		attotime delay_time = attotime(0, ATTOSECONDS_PER_SECOND * m_cap * 220);

		if(m_timer->elapsed() >= delay_time)
		{
			m_timer->adjust(duration);

			if (LOG) logerror("74123 %s:  Retriggering pulse.  Duration: %f\n", tag(), duration.as_double());
		}
		else
		{
			if (LOG) logerror("74123 %s:  Retriggering failed.\n", tag());
		}
	}
	else
	{
		/* starting */
		m_timer->adjust(duration);

		set_output();

		if (LOG) logerror("74123 %s:  Starting pulse.  Duration: %f\n", tag(), duration.as_double());
	}
}
Beispiel #6
0
void video_manager::recompute_speed(const attotime &emutime)
{
	// if we don't have a starting time yet, or if we're paused, reset our starting point
	if (m_speed_last_realtime == 0 || machine().paused())
	{
		m_speed_last_realtime = osd_ticks();
		m_speed_last_emutime = emutime;
	}

	// if it has been more than the update interval, update the time
	attotime delta_emutime = emutime - m_speed_last_emutime;
	if (delta_emutime > attotime(0, ATTOSECONDS_PER_SPEED_UPDATE))
	{
		// convert from ticks to attoseconds
		osd_ticks_t realtime = osd_ticks();
		osd_ticks_t delta_realtime = realtime - m_speed_last_realtime;
		osd_ticks_t tps = osd_ticks_per_second();
		m_speed_percent = delta_emutime.as_double() * (double)tps / (double)delta_realtime;

		// remember the last times
		m_speed_last_realtime = realtime;
		m_speed_last_emutime = emutime;

		// if we're throttled, this time period counts for overall speed; otherwise, we reset the counter
		if (!m_fastforward)
			m_overall_valid_counter++;
		else
			m_overall_valid_counter = 0;

		// if we've had at least 4 consecutive valid periods, accumulate stats
		if (m_overall_valid_counter >= 4)
		{
			m_overall_real_ticks += delta_realtime;
			while (m_overall_real_ticks >= tps)
			{
				m_overall_real_ticks -= tps;
				m_overall_real_seconds++;
			}
			m_overall_emutime += delta_emutime;
		}
	}

	// if we're past the "time-to-execute" requested, signal an exit
	if (m_seconds_to_run != 0 && emutime.seconds() >= m_seconds_to_run)
	{
		screen_device *screen = machine().first_screen();
		if (screen != nullptr)
		{
			// create a final screenshot
			emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
			osd_file::error filerr = file.open(machine().basename(), PATH_SEPARATOR "final.png");
			if (filerr == osd_file::error::NONE)
				save_snapshot(screen, file);
		}
		//printf("Scheduled exit at %f\n", emutime.as_double());
		// schedule our demise
		machine().schedule_exit();
	}
}
Beispiel #7
0
void europc_rtc_init(running_machine &machine)
{
	memset(&europc_rtc,0,sizeof(europc_rtc));
	europc_rtc.data[0xf]=1;

	europc_rtc.timer = machine.scheduler().timer_alloc(FUNC(europc_rtc_timer));
	europc_rtc.timer->adjust(attotime::zero, 0, attotime(1,0));
}
Beispiel #8
0
/* Called via stream->update().
 * This can be triggered by the core (based on emulated time) or via speaker_level_w().
 */
static STREAM_UPDATE( speaker_sound_update )
{
	speaker_state *sp = (speaker_state *) param;
	stream_sample_t *buffer = outputs[0];
	int volume = sp->levels[sp->level];
	double filtered_volume;
	attotime sampled_time = attotime::zero;

	if (samples > 0)
	{
		/* Prepare to update time state */
		sampled_time = attotime(0, sp->channel_sample_period);
		if (samples > 1)
			sampled_time *= samples;

		/* Note: since the stream is in the process of being updated,
         * stream->sample_time() will return the time before the update! (MAME 0.130)
         * Avoid using it here in order to avoid a subtle dependence on the stream implementation.
         */
	}

	if (samples-- > 0)
	{
		/* Note that first interm. sample may be composed... */
		filtered_volume = update_interm_samples_get_filtered_volume(sp, volume);

		/* Composite volume is now quantized to the stream resolution */
		*buffer++ = (stream_sample_t)filtered_volume;

		/* Any additional samples will be homogeneous, however may need filtering across samples: */
		while (samples-- > 0)
		{
			filtered_volume = update_interm_samples_get_filtered_volume(sp, volume);
			*buffer++ = (stream_sample_t)filtered_volume;
		}

		/* Update the time state */
		sp->channel_last_sample_time += sampled_time;
		sp->channel_next_sample_time = sp->channel_last_sample_time + attotime(0, sp->channel_sample_period);
		sp->next_interm_sample_time = sp->channel_last_sample_time + attotime(0, sp->interm_sample_period);
		sp->last_update_time = sp->channel_last_sample_time;
	}

} /* speaker_sound_update */
Beispiel #9
0
void europc_pc_state::europc_rtc_init()
{
	memset(&m_rtc_data,0,sizeof(m_rtc_data));
	m_rtc_reg = 0;
	m_rtc_state = 0;
	m_rtc_data[0xf]=1;

	m_rtc_timer = machine().scheduler().timer_alloc(timer_expired_delegate(FUNC(europc_pc_state::europc_rtc_timer),this));
	m_rtc_timer->adjust(attotime::zero, 0, attotime(1,0));
}
Beispiel #10
0
void namco_52xx_device::device_start()
{
	/* resolve our read/write callbacks */
	m_romread.resolve_safe(0);
	m_si.resolve_safe(0);

	/* start the external clock */
	if (m_extclock != 0)
		machine().scheduler().timer_pulse(attotime(0, m_extclock), timer_expired_delegate(FUNC(namco_52xx_device::external_clock_pulse),this), 0);
}
Beispiel #11
0
void speaker_sound_device::device_reset()
{
	int i;

	m_level = 0;
	for (i = 0; i < FILTER_LENGTH; i++)
		m_composed_volume[i] = 0;

	m_composed_sample_index = 0;
	m_last_update_time = machine().time();
	m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate());
	m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period);
	m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER;
	m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period);
	m_channel_last_sample_time = m_channel->sample_time();
	m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
	m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
	m_interm_sample_index = 0;
	m_prevx = m_prevy = 0.0;
}
Beispiel #12
0
void speaker_sound_device::finalize_interm_sample(int volume)
{
	double fraction;

	/* Fill the composed sample up if it was incomplete */
	fraction = make_fraction(m_next_interm_sample_time, m_last_update_time, m_interm_sample_period_secfrac);
	m_composed_volume[m_composed_sample_index] += volume * fraction;
	/* Update time state */
	m_last_update_time = m_next_interm_sample_time;
	m_next_interm_sample_time += attotime(0, m_interm_sample_period);

	/* For compatibility with filtering, do not incr. index and initialise next sample yet. */
}
Beispiel #13
0
static void finalize_interm_sample(speaker_state *sp, int volume)
{
	double fraction;

	/* Fill the composed sample up if it was incomplete */
	fraction = make_fraction(sp->next_interm_sample_time,
	                         sp->last_update_time,
	                         sp->interm_sample_period_secfrac);
	sp->composed_volume[sp->composed_sample_index] += volume * fraction;
	/* Update time state */
	sp->last_update_time = sp->next_interm_sample_time;
	sp->next_interm_sample_time += attotime(0, sp->interm_sample_period);

	/* For compatibility with filtering, do not incr. index and initialise next sample yet. */
}
Beispiel #14
0
INPUT_PORTS_END


void cms_state::machine_start()
{
	m_bank1->configure_entries(0, 16, m_rom->base(), 0x4000);

	memset(&m_rtc_data, 0, sizeof(m_rtc_data));
	m_rtc_reg = 0;
	m_rtc_state = 0;
	m_rtc_data[0xf] = 1;

	m_rtc_timer = timer_alloc();
	m_rtc_timer->adjust(attotime::zero, 0, attotime(1, 0));
}
Beispiel #15
0
static WRITE8_DEVICE_HANDLER( output_port_0_w )
{
	/*
        Note: We compute the timeout time on a write here. Unfortunately, the situation is
        kind of weird, because the discrete sound system is also affected by this timeout.
        In fact, it is very important that our timing calculation timeout AFTER the sound
        system's equivalent computation, or else we will hang notes.
    */
	hitme_state *state = device->machine->driver_data<hitme_state>();
	UINT8 raw_game_speed = input_port_read(device->machine, "R3");
	double resistance = raw_game_speed * 25000 / 100;
	attotime duration = attotime(0, ATTOSECONDS_PER_SECOND * 0.45 * 6.8e-6 * resistance * (data + 1));
	state->timeout_time = device->machine->time() + duration;

	discrete_sound_w(device, HITME_DOWNCOUNT_VAL, data);
	discrete_sound_w(device, HITME_OUT0, 1);
}
Beispiel #16
0
void running_machine::soft_reset(void *ptr, INT32 param)
{
	logerror("Soft reset\n");

	// temporarily in the reset phase
	m_current_phase = MACHINE_PHASE_RESET;

	// set up the watchdog timer; only start off enabled if explicitly configured
	m_watchdog_enabled = (config().m_watchdog_vblank_count != 0 || config().m_watchdog_time != attotime::zero);
	watchdog_reset();
	m_watchdog_enabled = true;

	// call all registered reset callbacks
	call_notifiers(MACHINE_NOTIFY_RESET);

	// setup autoboot if needed
	m_autoboot_timer->adjust(attotime(options().autoboot_delay(),0),0);

	// now we're running
	m_current_phase = MACHINE_PHASE_RUNNING;
}
Beispiel #17
0
static TIMER_CALLBACK( schaser_effect_555_cb )
{
	_8080bw_state *state = machine.driver_data<_8080bw_state>();
	int effect = param;
	attotime new_time;
	/* Toggle 555 output */
	state->m_schaser_effect_555_is_low = !state->m_schaser_effect_555_is_low;
	state->m_schaser_effect_555_time_remain = attotime::zero;
	state->m_schaser_effect_555_time_remain_savable = state->m_schaser_effect_555_time_remain.as_double();

	if (state->m_schaser_effect_555_is_low)
		new_time = PERIOD_OF_555_ASTABLE(0, RES_K(20), CAP_U(1)) / 2;
	else
	{
		if (effect)
			new_time = attotime(0, ATTOSECONDS_PER_SECOND * .8873 * schaser_effect_rc[effect]);
		else
			new_time = attotime::never;
	}
	state->m_schaser_effect_555_timer->adjust(new_time, effect);
	sn76477_enable_w(state->m_sn, !(state->m_schaser_effect_555_is_low || state->m_schaser_explosion));
	sn76477_one_shot_cap_voltage_w(state->m_sn, !(state->m_schaser_effect_555_is_low || state->m_schaser_explosion) ? 0 : SN76477_EXTERNAL_VOLTAGE_DISCONNECT);
}
Beispiel #18
0
void video_manager::exit()
{
	// stop recording any movie
	for (uint32_t index = 0; index < (std::max)(m_mngs.size(), m_avis.size()); index++)
	{
		if (index < m_avis.size())
			end_recording_avi(index);

		if (index < m_mngs.size())
			end_recording_mng(index);

		if (!m_snap_native)
			break;
	}

	// free the snapshot target
	machine().render().target_free(m_snap_target);
	m_snap_bitmap.reset();

	// print a final result if we have at least 2 seconds' worth of data
	if (!emulator_info::standalone() && m_overall_emutime.seconds() >= 1)
	{
		osd_ticks_t tps = osd_ticks_per_second();
		double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps;
		double final_emu_time = m_overall_emutime.as_double();
		osd_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds());
	}
}
Beispiel #19
0
void video_manager::update_throttle(attotime emutime)
{
/*

   Throttling theory:

   This routine is called periodically with an up-to-date emulated time.
   The idea is to synchronize real time with emulated time. We do this
   by "throttling", or waiting for real time to catch up with emulated
   time.

   In an ideal world, it will take less real time to emulate and render
   each frame than the emulated time, so we need to slow things down to
   get both times in sync.

   There are many complications to this model:

       * some games run too slow, so each frame we get further and
           further behind real time; our only choice here is to not
           throttle

       * some games have very uneven frame rates; one frame will take
           a long time to emulate, and the next frame may be very fast

       * we run on top of multitasking OSes; sometimes execution time
           is taken away from us, and this means we may not get enough
           time to emulate one frame

       * we may be paused, and emulated time may not be marching
           forward

       * emulated time could jump due to resetting the machine or
           restoring from a saved state

*/
	static const UINT8 popcount[256] =
	{
		0,1,1,2,1,2,2,3, 1,2,2,3,2,3,3,4, 1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5,
		1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6,
		1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6,
		2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7,
		1,2,2,3,2,3,3,4, 2,3,3,4,3,4,4,5, 2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6,
		2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7,
		2,3,3,4,3,4,4,5, 3,4,4,5,4,5,5,6, 3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7,
		3,4,4,5,4,5,5,6, 4,5,5,6,5,6,6,7, 4,5,5,6,5,6,6,7, 5,6,6,7,6,7,7,8
	};

	// outer scope so we can break out in case of a resync
	while (1)
	{
		// apply speed factor to emu time
		if (m_speed != 0 && m_speed != 1000)
		{
			// multiply emutime by 1000, then divide by the global speed factor
			emutime = (emutime * 1000) / m_speed;
		}

		// compute conversion factors up front
		osd_ticks_t ticks_per_second = osd_ticks_per_second();
		attoseconds_t attoseconds_per_tick = ATTOSECONDS_PER_SECOND / ticks_per_second * m_throttle_rate;

		// if we're paused, emutime will not advance; instead, we subtract a fixed
		// amount of time (1/60th of a second) from the emulated time that was passed in,
		// and explicitly reset our tracked real and emulated timers to that value ...
		// this means we pretend that the last update was exactly 1/60th of a second
		// ago, and was in sync in both real and emulated time
		if (machine().paused())
		{
			m_throttle_emutime = emutime - attotime(0, ATTOSECONDS_PER_SECOND / PAUSED_REFRESH_RATE);
			m_throttle_realtime = m_throttle_emutime;
		}

		// attempt to detect anomalies in the emulated time by subtracting the previously
		// reported value from our current value; this should be a small value somewhere
		// between 0 and 1/10th of a second ... anything outside of this range is obviously
		// wrong and requires a resync
		attoseconds_t emu_delta_attoseconds = (emutime - m_throttle_emutime).as_attoseconds();
		if (emu_delta_attoseconds < 0 || emu_delta_attoseconds > ATTOSECONDS_PER_SECOND / 10)
		{
			if (LOG_THROTTLE)
				machine().logerror("Resync due to weird emutime delta: %s\n", attotime(0, emu_delta_attoseconds).as_string(18));
			break;
		}

		// now determine the current real time in OSD-specified ticks; we have to be careful
		// here because counters can wrap, so we only use the difference between the last
		// read value and the current value in our computations
		osd_ticks_t diff_ticks = osd_ticks() - m_throttle_last_ticks;
		m_throttle_last_ticks += diff_ticks;

		// if it has been more than a full second of real time since the last call to this
		// function, we just need to resynchronize
		if (diff_ticks >= ticks_per_second)
		{
			if (LOG_THROTTLE)
				machine().logerror("Resync due to real time advancing by more than 1 second\n");
			break;
		}

		// convert this value into attoseconds for easier comparison
		attoseconds_t real_delta_attoseconds = diff_ticks * attoseconds_per_tick;

		// now update our real and emulated timers with the current values
		m_throttle_emutime = emutime;
		m_throttle_realtime += attotime(0, real_delta_attoseconds);

		// keep a history of whether or not emulated time beat real time over the last few
		// updates; this can be used for future heuristics
		m_throttle_history = (m_throttle_history << 1) | (emu_delta_attoseconds > real_delta_attoseconds);

		// determine how far ahead real time is versus emulated time; note that we use the
		// accumulated times for this instead of the deltas for the current update because
		// we want to track time over a longer duration than a single update
		attoseconds_t real_is_ahead_attoseconds = (m_throttle_emutime - m_throttle_realtime).as_attoseconds();

		// if we're more than 1/10th of a second out, or if we are behind at all and emulation
		// is taking longer than the real frame, we just need to resync
		if (real_is_ahead_attoseconds < -ATTOSECONDS_PER_SECOND / 10 ||
			(real_is_ahead_attoseconds < 0 && popcount[m_throttle_history & 0xff] < 6))
		{
			if (LOG_THROTTLE)
				machine().logerror("Resync due to being behind: %s (history=%08X)\n", attotime(0, -real_is_ahead_attoseconds).as_string(18), m_throttle_history);
			break;
		}

		// if we're behind, it's time to just get out
		if (real_is_ahead_attoseconds < 0)
			return;

		// compute the target real time, in ticks, where we want to be
		osd_ticks_t target_ticks = m_throttle_last_ticks + real_is_ahead_attoseconds / attoseconds_per_tick;

		// throttle until we read the target, and update real time to match the final time
		diff_ticks = throttle_until_ticks(target_ticks) - m_throttle_last_ticks;
		m_throttle_last_ticks += diff_ticks;
		m_throttle_realtime += attotime(0, diff_ticks * attoseconds_per_tick);
		return;
	}

	// reset realtime and emutime to the same value
	m_throttle_realtime = m_throttle_emutime = emutime;
}
Beispiel #20
0
void video_manager::exit()
{
	// stop recording any movie
	end_recording(MF_AVI);
	end_recording(MF_MNG);

	// free the snapshot target
	machine().render().target_free(m_snap_target);
	m_snap_bitmap.reset();

	// print a final result if we have at least 2 seconds' worth of data
	if (m_overall_emutime.seconds() >= 1)
	{
		osd_ticks_t tps = osd_ticks_per_second();
		double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps;
		double final_emu_time = m_overall_emutime.as_double();
		osd_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds());
	}
}
Beispiel #21
0
void mame_machine_manager::reset()
{
	// setup autoboot if needed
	m_autoboot_timer->adjust(attotime(options().autoboot_delay(),0),0);
}
Beispiel #22
0
void video_manager::exit()
{
	// stop recording any movie
	end_recording();

	// free all the graphics elements
	for (int i = 0; i < MAX_GFX_ELEMENTS; i++)
		gfx_element_free(machine().gfx[i]);

	// free the snapshot target
	machine().render().target_free(m_snap_target);
	m_snap_bitmap.reset();

	// print a final result if we have at least 2 seconds' worth of data
	if (m_overall_emutime.seconds >= 1)
	{
		osd_ticks_t tps = osd_ticks_per_second();
		double final_real_time = (double)m_overall_real_seconds + (double)m_overall_real_ticks / (double)tps;
		double final_emu_time = m_overall_emutime.as_double();
		mame_printf_info("Average speed: %.2f%% (%d seconds)\n", 100 * final_emu_time / final_real_time, (m_overall_emutime + attotime(0, ATTOSECONDS_PER_SECOND / 2)).seconds);
	}
}
Beispiel #23
0
void device_scheduler::timeslice()
{
	bool call_debugger = ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);

	// build the execution list if we don't have one yet
	if (m_execute_list == NULL)
		rebuild_execute_list();

	// execute timers
	execute_timers();

	// loop until we hit the next timer
	while (m_basetime < m_timer_list->m_expire)
	{
		// by default, assume our target is the end of the next quantum
		attotime target = m_basetime + attotime(0, m_quantum_list.first()->m_actual);

		// however, if the next timer is going to fire before then, override
		if (m_timer_list->m_expire < target)
			target = m_timer_list->m_expire;

		LOG(("------------------\n"));
		LOG(("cpu_timeslice: target = %s\n", target.as_string()));

		// apply pending suspension changes
		UINT32 suspendchanged = 0;
		for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
		{
			suspendchanged |= exec->m_suspend ^ exec->m_nextsuspend;
			exec->m_suspend = exec->m_nextsuspend;
			exec->m_nextsuspend &= ~SUSPEND_REASON_TIMESLICE;
			exec->m_eatcycles = exec->m_nexteatcycles;
		}

		// recompute the execute list if any CPUs changed their suspension state
		if (suspendchanged != 0)
			rebuild_execute_list();

		// loop over non-suspended CPUs
		for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
		{
			// only process if our target is later than the CPU's current time (coarse check)
			if (target.seconds >= exec->m_localtime.seconds)
			{
				// compute how many attoseconds to execute this CPU
				attoseconds_t delta = target.attoseconds - exec->m_localtime.attoseconds;
				if (delta < 0 && target.seconds > exec->m_localtime.seconds)
					delta += ATTOSECONDS_PER_SECOND;
				assert(delta == (target - exec->m_localtime).as_attoseconds());

				// if we have enough for at least 1 cycle, do the math
				if (delta >= exec->m_attoseconds_per_cycle)
				{
					// compute how many cycles we want to execute
					int ran = exec->m_cycles_running = divu_64x32((UINT64)delta >> exec->m_divshift, exec->m_divisor);
					LOG(("  cpu '%s': %d cycles\n", exec->device().tag(), exec->m_cycles_running));

					// if we're not suspended, actually execute
					if (exec->m_suspend == 0)
					{
						g_profiler.start(exec->m_profiler);

						// note that this global variable cycles_stolen can be modified
						// via the call to cpu_execute
						exec->m_cycles_stolen = 0;
						m_executing_device = exec;
						*exec->m_icountptr = exec->m_cycles_running;
						if (!call_debugger)
							exec->run();
						else
						{
							debugger_start_cpu_hook(&exec->device(), target);
							exec->run();
							debugger_stop_cpu_hook(&exec->device());
						}

						// adjust for any cycles we took back
						assert(ran >= *exec->m_icountptr);
						ran -= *exec->m_icountptr;
						assert(ran >= exec->m_cycles_stolen);
						ran -= exec->m_cycles_stolen;
						g_profiler.stop();
					}

					// account for these cycles
					exec->m_totalcycles += ran;

					// update the local time for this CPU
					attotime delta = attotime(0, exec->m_attoseconds_per_cycle * ran);
					assert(delta >= attotime::zero);
					exec->m_localtime += delta;
					LOG(("         %d ran, %d total, time = %s\n", ran, (INT32)exec->m_totalcycles, exec->m_localtime.as_string()));

					// if the new local CPU time is less than our target, move the target up, but not before the base
					if (exec->m_localtime < target)
					{
						assert(exec->m_localtime < target);
						target = max(exec->m_localtime, m_basetime);
						LOG(("         (new target)\n"));
					}
				}
			}
		}
Beispiel #24
0
void js_main_loop() {
	attotime stoptime = scheduler->time() + attotime(0,HZ_TO_ATTOSECONDS(60));
	while (scheduler->time() < stoptime) {
		scheduler->timeslice();
	}
}
Beispiel #25
0
void speaker_sound_device::speaker_postload()
{
	m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
	m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
}
Beispiel #26
0
void speaker_sound_device::device_start()
{
	int i;
	double x;

	m_channel = machine().sound().stream_alloc(*this, 0, 1, machine().sample_rate(), this);

	m_level = 0;
	for (i = 0; i < FILTER_LENGTH; i++)
		m_composed_volume[i] = 0;

	m_composed_sample_index = 0;
	m_last_update_time = machine().time();
	m_channel_sample_period = HZ_TO_ATTOSECONDS(machine().sample_rate());
	m_channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_channel_sample_period);
	m_interm_sample_period = m_channel_sample_period / RATE_MULTIPLIER;
	m_interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(m_interm_sample_period);
	m_channel_last_sample_time = m_channel->sample_time();
	m_channel_next_sample_time = m_channel_last_sample_time + attotime(0, m_channel_sample_period);
	m_next_interm_sample_time = m_channel_last_sample_time + attotime(0, m_interm_sample_period);
	m_interm_sample_index = 0;
	m_prevx = m_prevy = 0.0;

	/* Note: To avoid time drift due to floating point inaccuracies,
	 * it is good if the speaker time synchronizes itself with the stream timing regularly.
	 */

	/* Compute filter kernel; */
	/* (Done for each device though the data is shared...
	 *  No problem really, but should be done as part of system init if I knew how)
	 */
#if 1
	/* This is an approximated sinc (a perfect sinc makes an ideal low-pass filter).
	 * FILTER_STEP determines the cutoff frequency,
	 * which should be below the Nyquist freq, i.e. half the sample rate.
	 * Smaller step => kernel extends in time domain => lower cutoff freq
	 * In this case, with sinc, filter step PI corresponds to the Nyq. freq.
	 * Since we do not get a perfect filter => must lower the cutoff freq some more.
	 * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4;
	 *    With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz.
	 *    With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz.
	 * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage.
	 */
#define FILTER_STEP  (M_PI / 2 / RATE_MULTIPLIER)
	/* Distribute symmetrically on x axis; center has x=0 if length is odd */
	for (i = 0,             x = (0.5 - FILTER_LENGTH / 2.) * FILTER_STEP;
			i < FILTER_LENGTH;
			i++,                x += FILTER_STEP)
	{
		if (x == 0)
			m_ampl[i] = 1;
		else
			m_ampl[i] = sin(x) / x;
	}
#else
	/* Trivial average filter with poor frequency cutoff properties;
	 * First zero (frequency where amplification=0) = sample rate / filter length
	 * Cutoff frequency approx <= first zero / 2
	 */
	for (i = 0, i < FILTER_LENGTH; i++)
		m_ampl[i] = 1;
#endif

	save_item(NAME(m_level));
	save_item(NAME(m_composed_volume));
	save_item(NAME(m_composed_sample_index));
	save_item(NAME(m_channel_last_sample_time));
	save_item(NAME(m_interm_sample_index));
	save_item(NAME(m_last_update_time));
	save_item(NAME(m_prevx));
	save_item(NAME(m_prevy));

	machine().save().register_postload(save_prepost_delegate(FUNC(speaker_sound_device::speaker_postload), this));
}
Beispiel #27
0
static DEVICE_START( speaker )
{
	speaker_state *sp = get_safe_token(device);
	const speaker_interface *intf = (const speaker_interface *) device->static_config();
	int i;
	double x;

	sp->channel = device->machine().sound().stream_alloc(*device, 0, 1, device->machine().sample_rate(), sp, speaker_sound_update);

	if (intf != NULL)
	{
		assert(intf->num_level > 1);
		assert(intf->levels != NULL);
		sp->num_levels = intf->num_level;
		sp->levels = intf->levels;
	}
	else
	{
		sp->num_levels = 2;
		sp->levels = default_levels;
	}

	sp->level = 0;
	for (i = 0; i < FILTER_LENGTH; i++)
		sp->composed_volume[i] = 0;
	sp->composed_sample_index = 0;
	sp->last_update_time = device->machine().time();
	sp->channel_sample_period = HZ_TO_ATTOSECONDS(device->machine().sample_rate());
	sp->channel_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(sp->channel_sample_period);
	sp->interm_sample_period = sp->channel_sample_period / RATE_MULTIPLIER;
	sp->interm_sample_period_secfrac = ATTOSECONDS_TO_DOUBLE(sp->interm_sample_period);
	sp->channel_last_sample_time = sp->channel->sample_time();
	sp->channel_next_sample_time = sp->channel_last_sample_time + attotime(0, sp->channel_sample_period);
	sp->next_interm_sample_time = sp->channel_last_sample_time + attotime(0, sp->interm_sample_period);
	sp->interm_sample_index = 0;
	/* Note: To avoid time drift due to floating point inaccuracies,
     * it is good if the speaker time synchronizes itself with the stream timing regularly.
     */

	/* Compute filter kernel; */
	/* (Done for each device though the data is shared...
     *  No problem really, but should be done as part of system init if I knew how)
     */
#if 1
	/* This is an approximated sinc (a perfect sinc makes an ideal low-pass filter).
     * FILTER_STEP determines the cutoff frequency,
     * which should be below the Nyquist freq, i.e. half the sample rate.
     * Smaller step => kernel extends in time domain => lower cutoff freq
     * In this case, with sinc, filter step PI corresponds to the Nyq. freq.
     * Since we do not get a perfect filter => must lower the cutoff freq some more.
     * For example, step PI/(2*RATE_MULTIPLIER) corresponds to cutoff freq = sample rate / 4;
     *    With -samplerate 48000, cutoff freq is ca 12kHz while the Nyq. freq is 24kHz.
     *    With -samplerate 96000, cutoff freq is ca 24kHz while the Nyq. freq is 48kHz.
     * For a steeper, more efficient filter, increase FILTER_LENGTH at the expense of CPU usage.
     */
	#define FILTER_STEP  (M_PI / 2 / RATE_MULTIPLIER)
	/* Distribute symmetrically on x axis; center has x=0 if length is odd */
	for (i = 0, 			x = (0.5 - FILTER_LENGTH / 2.) * FILTER_STEP;
	     i < FILTER_LENGTH;
		 i++,				x += FILTER_STEP)
	{
		if (x == 0)
			ampl[i] = 1;
		else
			ampl[i] = sin(x) / x;
	}
#else
	/* Trivial average filter with poor frequency cutoff properties;
     * First zero (frequency where amplification=0) = sample rate / filter length
     * Cutoff frequency approx <= first zero / 2
     */
	for (i = 0, i < FILTER_LENGTH; i++)
		ampl[i] = 1;
#endif
}
Beispiel #28
0
void device_scheduler::timeslice()
{
	bool call_debugger = ((machine().debug_flags & DEBUG_FLAG_ENABLED) != 0);

	// build the execution list if we don't have one yet
	if (UNEXPECTED(m_execute_list == NULL))
		rebuild_execute_list();

	// if the current quantum has expired, find a new one
	while (m_basetime >= m_quantum_list.first()->m_expire)
		m_quantum_allocator.reclaim(m_quantum_list.detach_head());

	// loop until we hit the next timer
	while (m_basetime < m_timer_list->m_expire)
	{
		// by default, assume our target is the end of the next quantum
		attotime target = m_basetime + attotime(0, m_quantum_list.first()->m_actual);

		// however, if the next timer is going to fire before then, override
		if (m_timer_list->m_expire < target)
			target = m_timer_list->m_expire;

		// do we have pending suspension changes?
		if (m_suspend_changes_pending)
			apply_suspend_changes();

		// loop over all CPUs
		for (device_execute_interface *exec = m_execute_list; exec != NULL; exec = exec->m_nextexec)
		{
			// only process if this CPU is executing or truly halted (not yielding)
			// and if our target is later than the CPU's current time (coarse check)
			if (EXPECTED((exec->m_suspend == 0 || exec->m_eatcycles) && target.seconds >= exec->m_localtime.seconds))
			{
				// compute how many attoseconds to execute this CPU
				attoseconds_t delta = target.attoseconds - exec->m_localtime.attoseconds;
				if (delta < 0 && target.seconds > exec->m_localtime.seconds)
					delta += ATTOSECONDS_PER_SECOND;
				assert(delta == (target - exec->m_localtime).as_attoseconds());

				// if we have enough for at least 1 cycle, do the math
				if (delta >= exec->m_attoseconds_per_cycle)
				{
					// compute how many cycles we want to execute
					int ran = exec->m_cycles_running = divu_64x32((UINT64)delta >> exec->m_divshift, exec->m_divisor);

					// if we're not suspended, actually execute
					if (exec->m_suspend == 0)
					{
						// note that this global variable cycles_stolen can be modified
						// via the call to cpu_execute
						exec->m_cycles_stolen = 0;
						m_executing_device = exec;
						*exec->m_icountptr = exec->m_cycles_running;
						if (!call_debugger)
							exec->run();
						else
						{
							debugger_start_cpu_hook(&exec->device(), target);
							exec->run();
							debugger_stop_cpu_hook(&exec->device());
						}

						// adjust for any cycles we took back
						assert(ran >= *exec->m_icountptr);
						ran -= *exec->m_icountptr;
						assert(ran >= exec->m_cycles_stolen);
						ran -= exec->m_cycles_stolen;
					}

					// account for these cycles
					exec->m_totalcycles += ran;

					// update the local time for this CPU
					attotime delta(0, exec->m_attoseconds_per_cycle * ran);
					assert(delta >= attotime::zero);
					exec->m_localtime += delta;

					// if the new local CPU time is less than our target, move the target up, but not before the base
					if (exec->m_localtime < target)
					{
						target = max(exec->m_localtime, m_basetime);
					}
				}
			}
		}
Beispiel #29
0
/*-------------------------------------------------
    call_load
-------------------------------------------------*/
bool snapshot_image_device::call_load()
{
	/* adjust the timer */
	m_timer->adjust(attotime(m_delay_seconds, m_delay_attoseconds),0);
	return IMAGE_INIT_PASS;
}