Exemplo n.º 1
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);
	if (m_snap_bitmap != NULL)
		global_free(m_snap_bitmap);

	// print a final result if we have at least 5 seconds' worth of data
	if (m_overall_emutime.seconds >= 5)
	{
		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);
	}
}
Exemplo n.º 2
0
void poly_wait(poly_manager *poly, const char *debug_reason)
{
	osd_ticks_t time;

	/* remember the start time if we're logging */
	if (LOG_WAITS)
		time = get_profile_ticks();

	/* wait for all pending work items to complete */
	if (poly->queue != NULL)
		osd_work_queue_wait(poly->queue, osd_ticks_per_second() * 100);

	/* if we don't have a queue, just run the whole list now */
	else
	{
		int unitnum;
		for (unitnum = 0; unitnum < poly->unit_next; unitnum++)
			poly_item_callback(poly->unit[unitnum], 0);
	}

	/* log any long waits */
	if (LOG_WAITS)
	{
		time = get_profile_ticks() - time;
		if (time > LOG_WAIT_THRESHOLD)
			logerror("Poly:Waited %d cycles for %s\n", (int)time, debug_reason);
	}

	/* reset the state */
	poly->polygon_next = poly->unit_next = 0;
	memset(poly->unit_bucket, 0xff, sizeof(poly->unit_bucket));

	/* we need to preserve the last extra data that was supplied */
	if (poly->extra_next > 1)
		memcpy(poly->extra[0], poly->extra[poly->extra_next - 1], poly->extra_size);
	poly->extra_next = 1;
}
Exemplo n.º 3
0
bool ui_input_pressed_repeat(running_machine &machine, int code, int speed)
{
    ui_input_private *uidata = machine.ui_input_data;
    int pressed;

    g_profiler.start(PROFILER_INPUT);

    /* get the status of this key (assumed to be only in the defaults) */
    assert(code >= IPT_UI_CONFIGURE && code <= IPT_OSD_16);
    pressed = (uidata->seqpressed[code] == SEQ_PRESSED_TRUE);

    /* if down, handle it specially */
    if (pressed)
    {
        osd_ticks_t tps = osd_ticks_per_second();

        /* if this is the first press, set a 3x delay and leave pressed = 1 */
        if (uidata->next_repeat[code] == 0)
            uidata->next_repeat[code] = osd_ticks() + 3 * speed * tps / 60;

        /* if this is an autorepeat case, set a 1x delay and leave pressed = 1 */
        else if (speed > 0 && (osd_ticks() + tps - uidata->next_repeat[code]) >= tps)
            uidata->next_repeat[code] += 1 * speed * tps / 60;

        /* otherwise, reset pressed = 0 */
        else
            pressed = false;
    }

    /* if we're not pressed, reset the memory field */
    else
        uidata->next_repeat[code] = 0;

    g_profiler.stop();

    return pressed;
}
Exemplo n.º 4
0
void renderer_sdl2::render_quad(texture_info *texture, const render_primitive &prim, const int x, const int y)
{
	SDL_Rect target_rect;

	target_rect.x = x;
	target_rect.y = y;
	target_rect.w = round_nearest(prim.bounds.x1 - prim.bounds.x0);
	target_rect.h = round_nearest(prim.bounds.y1 - prim.bounds.y0);

	if (texture)
	{
		copy_info_t *copyinfo = texture->m_copyinfo;
		copyinfo->time -= osd_ticks();
		texture->render_quad(prim, x, y);
		copyinfo->time += osd_ticks();

		copyinfo->pixel_count += std::max(STAT_PIXEL_THRESHOLD , (texture->raw_width() * texture->raw_height()));
		if (m_last_blit_pixels)
		{
			copyinfo->time += (m_last_blit_time * (INT64) (texture->raw_width() * texture->raw_height())) / (INT64) m_last_blit_pixels;
		}
		copyinfo->samples++;
		copyinfo->perf = ( texture->m_copyinfo->pixel_count * (osd_ticks_per_second()/1000)) / texture->m_copyinfo->time;
	}
	else
	{
		UINT32 sr = (UINT32)(255.0f * prim.color.r);
		UINT32 sg = (UINT32)(255.0f * prim.color.g);
		UINT32 sb = (UINT32)(255.0f * prim.color.b);
		UINT32 sa = (UINT32)(255.0f * prim.color.a);

		SDL_SetRenderDrawBlendMode(m_sdl_renderer, map_blendmode(PRIMFLAG_GET_BLENDMODE(prim.flags)));
		SDL_SetRenderDrawColor(m_sdl_renderer, sr, sg, sb, sa);
		SDL_RenderFillRect(m_sdl_renderer, &target_rect);
	}
}
Exemplo n.º 5
0
void watchdog::setTimeout(int timeout)
{
	m_timeout = timeout * osd_ticks_per_second();
	this->reset();
}
Exemplo n.º 6
0
void mc146818_device::device_timer(emu_timer &timer, device_timer_id id, int param, void *ptr)
{
	int year/*, month*/;

	if (id == TIMER_PERIODIC) {
		m_data[0x0c] |= 0xc0;
		if (!m_out_irq_func.isnull()) m_out_irq_func(CLEAR_LINE);
		return;
	}

	if (m_type == MC146818_UTC) {
		// hack: set correct real time even for overloaded emulation
		// (at least for apollo)
		static osd_ticks_t t0 = 0;
		osd_ticks_t t1 = osd_ticks();
		int n_seconds;

		if (t0 == 0) {
			t0 = t1;
		}

		n_seconds =  (t1 - t0) / osd_ticks_per_second();
		t0 = t1 - (t1 - t0) % osd_ticks_per_second();
		if (n_seconds <= 0) {
			// we were called to early
			return;
		}

		m_data[0] += n_seconds;
	} else {
		m_data[0] += 1;
	}

	if (BCD_MODE)
	{
		m_data[0]=bcd_adjust(m_data[0]/*+1*/);
		if (m_data[0]>=0x60)
		{
			m_data[0]=0;
			m_data[2]=bcd_adjust(m_data[2]+1);
			if (m_data[2]>=0x60)
			{
				m_data[2]=0;
				m_data[4]=bcd_adjust(m_data[4]+1);
				// different handling of hours
				if (m_data[4]>=0x24)
				{
					m_data[4]=0;
					WEEK_DAY=bcd_adjust(WEEK_DAY+1)%7;
					DAY=bcd_adjust(DAY+1);
					//month=bcd_2_dec(MONTH);
					year=bcd_2_dec(YEAR);
					if (m_type!=MC146818_IGNORE_CENTURY) year+=bcd_2_dec(CENTURY)*100;
					else year+=2000; // save for julian_days_in_month calculation
					DAY=bcd_adjust(DAY+1);
					if (DAY>gregorian_days_in_month(MONTH, year))
					{
						DAY=1;
						MONTH=bcd_adjust(MONTH+1);
						if (MONTH>0x12)
						{
							MONTH=1;
							YEAR=year=bcd_adjust(YEAR+1);
							if (m_type!=MC146818_IGNORE_CENTURY)
							{
								if (year>=0x100)
								{
									CENTURY=bcd_adjust(CENTURY+1);
								}
							}
						}
					}
				}
			}
		}
	}
	else
	{
		/*m_data[0]=m_data[0]+1;*/
		if (m_data[0]>=60)
		{
			m_data[0] -= 60;
			m_data[2]=m_data[2]+1;
			if (m_data[2]>=60) {
				m_data[2]=0;
				m_data[4]=m_data[4]+1;
				// different handling of hours //?
				if (m_data[4]>=24) {
					m_data[4]=0;
					WEEK_DAY=(WEEK_DAY+1)%7;
					year=YEAR;
					if (m_type!=MC146818_IGNORE_CENTURY) year+=CENTURY*100;
					else year+=2000; // save for julian_days_in_month calculation
					if (++DAY>gregorian_days_in_month(MONTH, year)) {
						DAY=1;
						if (++MONTH>12) {
							MONTH=1;
							YEAR++;
							if (m_type!=MC146818_IGNORE_CENTURY) {
								if (YEAR>=100) { CENTURY++;YEAR=0; }
							} else {
								YEAR%=100;
							}
						}
					}
				}
			}
		}
	}

	if (m_data[1] == m_data[0] && //
		m_data[3] == m_data[2] && //
		m_data[5] == m_data[4]) {
		// set the alarm interrupt flag AF
		m_data[0x0c] |= 0x20;
	} else {
		// clear the alarm interrupt flag AF
		m_data[0x0c] &= ~0x20;
		if ((m_data[0x0c] & 0x70) == 0) {
			// clear IRQF
			m_data[0x0c] &= ~0x80;
		}
	}

	// set the update-ended interrupt Flag UF
	m_data[0x0c] |=  0x10;

	// set the interrupt request flag IRQF
	// FIXME: should throw IRQ line as well
	if ((m_data[0x0b] & m_data[0x0c] & 0x30) != 0) {
		m_data[0x0c] |=  0x80;
	}

	// IRQ line is active low
	if (!m_out_irq_func.isnull()) m_out_irq_func((m_data[0x0c] & 0x80) ? CLEAR_LINE : ASSERT_LINE);

	m_updated = true;  /* clock has been updated */
	m_last_refresh = machine().time();
}
Exemplo n.º 7
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;
}
Exemplo n.º 8
0
void sdlwindow_video_window_update(running_machine &machine, sdl_window_info *window)
{

	osd_ticks_t		event_wait_ticks;
	ASSERT_MAIN_THREAD();

	// adjust the cursor state
	sdlwindow_update_cursor_state(machine, window);

	// if we're visible and running and not in the middle of a resize, draw
	if (window->target != NULL)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		window->target->compute_minimum_size(tempwidth, tempheight);
		if (video_config.switchres && window->fullscreen && machine.options().changeres())
		{
			if (machine.switchRes.resolution.changeres) 
				switchres_resolution_change(machine, window, tempwidth, tempheight);
		}
		else if (tempwidth != window->minwidth || tempheight != window->minheight)
		{
			window->minwidth = tempwidth;
			window->minheight = tempheight;
			if (!window->fullscreen)
			{
				sdlwindow_blit_surface_size(window, window->width, window->height);
				sdlwindow_resize(window, window->blitwidth, window->blitheight);
			}
			else if (video_config.switchres)
			{
				pick_best_mode(window, &tempwidth, &tempheight);
				sdlwindow_resize(window, tempwidth, tempheight);
			}
		}

		if (video_config.waitvsync || video_config.syncrefresh)
			event_wait_ticks = osd_ticks_per_second(); // block at most a second
		else
			event_wait_ticks = 0;

		if (osd_event_wait(window->rendered_event, event_wait_ticks))
		{
			worker_param wp;
			render_primitive_list *primlist;

			clear_worker_param(&wp);

			// ensure the target bounds are up-to-date, and then get the primitives
			primlist = &window->get_primitives(window);

			// and redraw now

			wp.list = primlist;
			wp.window = window;
			wp.m_machine = &machine;

			execute_async(&draw_video_contents_wt, &wp);
		}
	}
}
Exemplo n.º 9
0
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;
	ASSERT_MAIN_THREAD();

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	execute_async(&update_cursor_state_wt, worker_param(this));

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != NULL)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (video_config.switchres && m_fullscreen && machine().options().changeres() && machine().switchres.game.changeres)
		{
			switchres_resolution_change(this);
			return;
		}
		else if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		int got_lock = false;
		got_lock = osd_lock_try(m_render_lock);

		// only render if we were able to get the lock
		if (got_lock)
		{
			// don't hold the lock; we just used it to see if rendering was still happening
			osd_lock_release(m_render_lock);

			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *m_renderer->get_primitives();

			// and redraw now
			osd_event_reset(m_rendered_event);
			execute_async(&draw_video_contents_wt, worker_param(this, primlist));

			if (video_config.waitvsync && machine().video().throttled())
			{
				event_wait_ticks = osd_ticks_per_second(); // block at most a second
				osd_event_wait(m_rendered_event, event_wait_ticks);
			}
		}
	}
}
Exemplo n.º 10
0
void sdl_window_info::update()
{
	osd_ticks_t     event_wait_ticks;

	// adjust the cursor state
	//sdlwindow_update_cursor_state(machine, window);

	update_cursor_state();

	// if we're visible and running and not in the middle of a resize, draw
	if (m_target != nullptr)
	{
		int tempwidth, tempheight;

		// see if the games video mode has changed
		m_target->compute_minimum_size(tempwidth, tempheight);
		if (osd_dim(tempwidth, tempheight) != m_minimum_dim)
		{
			m_minimum_dim = osd_dim(tempwidth, tempheight);

			if (!this->m_fullscreen)
			{
				//Don't resize window without user interaction;
				//window_resize(blitwidth, blitheight);
			}
			else if (video_config.switchres)
			{
				osd_dim tmp = this->pick_best_mode();
				resize(tmp.width(), tmp.height());
			}
		}

		if (video_config.waitvsync && video_config.syncrefresh)
			event_wait_ticks = osd_ticks_per_second(); // block at most a second
		else
			event_wait_ticks = 0;

		if (m_rendered_event.wait(event_wait_ticks))
		{
			const int update = 1;

			// ensure the target bounds are up-to-date, and then get the primitives

			render_primitive_list &primlist = *renderer().get_primitives();

			// and redraw now

			// Some configurations require events to be polled in the worker thread
			downcast< sdl_osd_interface& >(machine().osd()).process_events_buf();

			// Check whether window has vector screens

			{
				const screen_device *screen = screen_device_iterator(machine().root_device()).byindex(m_index);
				if ((screen != nullptr) && (screen->screen_type() == SCREEN_TYPE_VECTOR))
					renderer().set_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
				else
					renderer().clear_flags(osd_renderer::FLAG_HAS_VECTOR_SCREEN);
			}

			m_primlist = &primlist;

			// if no bitmap, just fill
			if (m_primlist == nullptr)
			{
			}
			// otherwise, render with our drawing system
			else
			{
				if( video_config.perftest )
					measure_fps(update);
				else
					renderer().draw(update);
			}

			/* all done, ready for next */
			m_rendered_event.set();
		}
	}
}
Exemplo n.º 11
0
	virtual void process_event(SDL_Event &sdlevent) override
	{
		switch (sdlevent.type)
		{
		case SDL_MOUSEMOTION:
			mouse.lX += sdlevent.motion.xrel * INPUT_RELATIVE_PER_PIXEL;
			mouse.lY += sdlevent.motion.yrel * INPUT_RELATIVE_PER_PIXEL;

			{
				int cx = -1, cy = -1;
				auto window = GET_FOCUS_WINDOW(&sdlevent.motion);

				if (window != nullptr && window->xy_to_render_target(sdlevent.motion.x, sdlevent.motion.y, &cx, &cy))
					machine().ui_input().push_mouse_move_event(window->target(), cx, cy);
			}
			break;

		case SDL_MOUSEBUTTONDOWN:
			mouse.buttons[sdlevent.button.button - 1] = 0x80;
			//printf("But down %d %d %d %d %s\n", event.button.which, event.button.button, event.button.x, event.button.y, devinfo->name.c_str());
			if (sdlevent.button.button == 1)
			{
				// FIXME Move static declaration
				static osd_ticks_t last_click = 0;
				static int last_x = 0;
				static int last_y = 0;
				int cx, cy;
				osd_ticks_t click = osd_ticks() * 1000 / osd_ticks_per_second();
				auto window = GET_FOCUS_WINDOW(&sdlevent.button);
				if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
				{
					machine().ui_input().push_mouse_down_event(window->target(), cx, cy);
					// FIXME Parameter ?
					if ((click - last_click < 250)
						&& (cx >= last_x - 4 && cx <= last_x + 4)
						&& (cy >= last_y - 4 && cy <= last_y + 4))
					{
						last_click = 0;
						machine().ui_input().push_mouse_double_click_event(window->target(), cx, cy);
					}
					else
					{
						last_click = click;
						last_x = cx;
						last_y = cy;
					}
				}
			}

			else if (sdlevent.button.button == 3)
			{
				int cx, cy;
				auto window = GET_FOCUS_WINDOW(&sdlevent.button);

				if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
				{
					machine().ui_input().push_mouse_rdown_event(window->target(), cx, cy);
				}
			}
			break;

		case SDL_MOUSEBUTTONUP:
			mouse.buttons[sdlevent.button.button - 1] = 0;
			//printf("But up %d %d %d %d\n", event.button.which, event.button.button, event.button.x, event.button.y);

			if (sdlevent.button.button == 1)
			{
				int cx, cy;
				auto window = GET_FOCUS_WINDOW(&sdlevent.button);

				if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
				{
					machine().ui_input().push_mouse_up_event(window->target(), cx, cy);
				}
			}
			else if (sdlevent.button.button == 3)
			{
				int cx, cy;
				auto window = GET_FOCUS_WINDOW(&sdlevent.button);

				if (window != nullptr && window->xy_to_render_target(sdlevent.button.x, sdlevent.button.y, &cx, &cy))
				{
					machine().ui_input().push_mouse_rup_event(window->target(), cx, cy);
				}
			}
			break;

		case SDL_MOUSEWHEEL:
			auto window = GET_FOCUS_WINDOW(&sdlevent.wheel);
			if (window != nullptr)
				machine().ui_input().push_mouse_wheel_event(window->target(), 0, 0, sdlevent.wheel.y, 3);
			break;
		}
	}
Exemplo n.º 12
0
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
#ifdef WIN32
   int ret = WaitForSingleObject((HANDLE) event, timeout * 1000 / osd_ticks_per_second());
   if (ret != WAIT_OBJECT_0)
      return FALSE;
#else

   pthread_mutex_lock(&event->mutex);
   if (!timeout)
   {
      if (!event->signalled)
      {
         pthread_mutex_unlock(&event->mutex);
         return FALSE;
      }
   }
   else
   {
      if (!event->signalled)
      {
         struct timespec   ts;
         struct timeval    tp;
         UINT64 msec ;//= timeout * 1000 / osd_ticks_per_second();
         UINT64 nsec;

         gettimeofday(&tp, NULL);
	      
	 if(timeout!=OSD_EVENT_WAIT_INFINITE)

	 	msec = timeout * 1000 / osd_ticks_per_second();
	 else 
		msec = (OSD_EVENT_WAIT_INFINITE - tp.tv_usec * (UINT64) 1000)/osd_ticks_per_second();

         ts.tv_sec  = tp.tv_sec;
         nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
         ts.tv_nsec = nsec % (UINT64) 1000000000;
         ts.tv_sec += nsec / (UINT64) 1000000000;

         do
         {
            int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
            if ( ret == ETIMEDOUT )
            {
               if (event->signalled)
                  break;
               pthread_mutex_unlock(&event->mutex);
               return FALSE;
            }
            if (ret == 0)
               break;

         } while (TRUE);
      }
   }

   if (event->autoreset)
      event->signalled = 0;

   pthread_mutex_unlock(&event->mutex);

#endif
   return TRUE;
}
Exemplo n.º 13
0
static void update_throttle(mame_time emutime)
{
	static double ticks_per_sleep_msec = 0;
	osd_ticks_t target, curr, cps, diffticks;
	int allowed_to_sleep;
	subseconds_t subsecs_per_cycle;
	int paused = mame_is_paused(Machine);

	// if we're only syncing to the refresh, bail now
	if (video_config.syncrefresh)
		return;

	// if we're paused, emutime will not advance; explicitly resync and set us backwards
	// 1/60th of a second
	if (paused)
		throttle_realtime = throttle_emutime = sub_subseconds_from_mame_time(emutime, MAX_SUBSECONDS / PAUSED_REFRESH_RATE);

	// if time moved backwards (reset), or if it's been more than 1 second in emulated time, resync
	if (compare_mame_times(emutime, throttle_emutime) < 0 || sub_mame_times(emutime, throttle_emutime).seconds > 0)
		goto resync;

	// get the current realtime; if it's been more than 1 second realtime, just resync
	cps = osd_ticks_per_second();
	diffticks = osd_ticks() - throttle_last_ticks;
	throttle_last_ticks += diffticks;
	if (diffticks >= cps)
		goto resync;

	// add the time that has passed to the real time
	subsecs_per_cycle = MAX_SUBSECONDS / cps;
	throttle_realtime = add_subseconds_to_mame_time(throttle_realtime, diffticks * subsecs_per_cycle);

	// update the emulated time
	throttle_emutime = emutime;

	// if we're behind, just sync
	if (compare_mame_times(throttle_emutime, throttle_realtime) <= 0)
		goto resync;

	// determine our target ticks value
	target = throttle_last_ticks + sub_mame_times(throttle_emutime, throttle_realtime).subseconds / subsecs_per_cycle;

	// initialize the ticks per sleep
	if (ticks_per_sleep_msec == 0)
		ticks_per_sleep_msec = (double)(cps / 1000);

	// this counts as idle time
	profiler_mark(PROFILER_IDLE);

	// determine whether or not we are allowed to sleep
	allowed_to_sleep = video_config.sleep && (!effective_autoframeskip() || effective_frameskip() == 0);

	// sync
	for (curr = osd_ticks(); curr - target < 0; curr = osd_ticks())
	{
		// if we have enough time to sleep, do it
		// ...but not if we're autoframeskipping and we're behind
		if (paused || (allowed_to_sleep && (target - curr) > (osd_ticks_t)(ticks_per_sleep_msec * 1.1)))
		{
			osd_ticks_t next;

			// keep track of how long we actually slept
			Sleep(1);
			next = osd_ticks();
			ticks_per_sleep_msec = (ticks_per_sleep_msec * 0.90) + ((double)(next - curr) * 0.10);
		}
	}

	// idle time done
	profiler_mark(PROFILER_END);

	// update realtime
	diffticks = osd_ticks() - throttle_last_ticks;
	throttle_last_ticks += diffticks;
	throttle_realtime = add_subseconds_to_mame_time(throttle_realtime, diffticks * subsecs_per_cycle);
	return;

resync:
	// reset realtime and emutime to the same value
	throttle_realtime = throttle_emutime = emutime;
}
Exemplo n.º 14
0
void video_manager::recompute_speed(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;

		// Redraw patch
		m_machine.speed_percent = m_speed_percent;

		// 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)
	{
		if (machine().primary_screen != NULL)
		{
			// create a final screenshot
			emu_file file(machine().options().snapshot_directory(), OPEN_FLAG_WRITE | OPEN_FLAG_CREATE | OPEN_FLAG_CREATE_PATHS);
			file_error filerr = file.open(machine().basename(), PATH_SEPARATOR "final.png");
			if (filerr == FILERR_NONE)
				save_snapshot(machine().primary_screen, file);
		}

		// schedule our demise
		machine().schedule_exit();
	}
}
Exemplo n.º 15
0
int osd_event_wait(osd_event *event, osd_ticks_t timeout)
{
#ifdef WIN32
	int ret = WaitForSingleObject((HANDLE) event, timeout * 1000 / osd_ticks_per_second());
	return ( ret == WAIT_OBJECT_0);
#else

	pthread_mutex_lock(&event->mutex);
	if (!timeout)
	{
		if (!event->signalled)
		{
				pthread_mutex_unlock(&event->mutex);
				return FALSE;
		}
	}
	else
	{
		if (!event->signalled)
		{
			struct timespec   ts;
			struct timeval    tp;
			UINT64 msec = timeout * 1000 / osd_ticks_per_second();
			UINT64 nsec;

			gettimeofday(&tp, NULL);

			ts.tv_sec  = tp.tv_sec;
			nsec = (UINT64) tp.tv_usec * (UINT64) 1000 + (msec * (UINT64) 1000000);
			ts.tv_nsec = nsec % (UINT64) 1000000000;
			ts.tv_sec += nsec / (UINT64) 1000000000;

			do {
				int ret = pthread_cond_timedwait(&event->cond, &event->mutex, &ts);
				if ( ret == ETIMEDOUT )
				{
					if (!event->signalled)
					{
						pthread_mutex_unlock(&event->mutex);
						return FALSE;
					}
					else
						break;
				}
				if (ret == 0)
					break;
				if ( ret != EINTR)
				{
					printf("Error %d while waiting for pthread_cond_timedwait:  %s\n", ret, strerror(ret));
				}

			} while (TRUE);
		}
	}

	if (event->autoreset)
		event->signalled = 0;

	pthread_mutex_unlock(&event->mutex);

	return TRUE;
#endif
}
Exemplo n.º 16
0
bool input_manager::seq_poll()
{
	int curlen = m_poll_seq.length();
	input_code lastcode = m_poll_seq[curlen - 1];

	// switch case: see if we have a new code to process
	input_code newcode;
	if (m_poll_seq_class == ITEM_CLASS_SWITCH)
	{
		newcode = poll_switches();
		if (newcode != INPUT_CODE_INVALID)
		{
			// if code is duplicate, toggle the NOT state on the code
			if (curlen > 0 && newcode == lastcode)
			{
				// back up over the existing code
				m_poll_seq.backspace();

				// if there was a NOT preceding it, delete it as well, otherwise append a fresh one
				if (m_poll_seq[curlen - 2] == input_seq::not_code)
					m_poll_seq.backspace();
				else
					m_poll_seq += input_seq::not_code;
			}
		}
	}

	// absolute/relative case: see if we have an analog change of sufficient amount
	else
	{
		bool has_or = false;
		if (lastcode == input_seq::or_code)
		{
			lastcode = m_poll_seq[curlen - 2];
			has_or = true;
		}
		newcode = poll_axes();

		// if the last code doesn't match absolute/relative of this code, ignore the new one
		if ((lastcode.item_class() == ITEM_CLASS_ABSOLUTE && newcode.item_class() != ITEM_CLASS_ABSOLUTE) ||
			(lastcode.item_class() == ITEM_CLASS_RELATIVE && newcode.item_class() != ITEM_CLASS_RELATIVE))
			newcode = INPUT_CODE_INVALID;

		// if the new code is valid, check for half-axis toggles on absolute controls
		if (newcode != INPUT_CODE_INVALID && curlen > 0 && newcode.item_class() == ITEM_CLASS_ABSOLUTE)
		{
			input_code last_nomodifier = lastcode;
			last_nomodifier.set_item_modifier(ITEM_MODIFIER_NONE);
			if (newcode == last_nomodifier)
			{
				// increment the modifier, wrapping back to none
				switch (lastcode.item_modifier())
				{
					case ITEM_MODIFIER_NONE:    newcode.set_item_modifier(ITEM_MODIFIER_POS);   break;
					case ITEM_MODIFIER_POS:     newcode.set_item_modifier(ITEM_MODIFIER_NEG);   break;
					default:
					case ITEM_MODIFIER_NEG:     newcode.set_item_modifier(ITEM_MODIFIER_NONE);  break;
				}

				// back up over the previous code so we can re-append
				if (has_or)
					m_poll_seq.backspace();
				m_poll_seq.backspace();
			}
		}
	}

	// if we got a new code to append it, append it and reset the timer
	if (newcode != INPUT_CODE_INVALID)
	{
		m_poll_seq += newcode;
		m_poll_seq_last_ticks = osd_ticks();
	}

	// if we're recorded at least one item and 2/3 of a second has passed, we're done
	if (m_poll_seq_last_ticks != 0 && osd_ticks() > m_poll_seq_last_ticks + osd_ticks_per_second() * 2 / 3)
	{
		// if the final result is invalid, reset to nothing
		if (!m_poll_seq.is_valid())
			m_poll_seq.reset();

		// return true to indicate that we are finished
		return true;
	}

	// return false to indicate we are still polling
	return false;
}