Exemple #1
0
void osd_update_video_and_audio(struct mame_display *display)
{
	cycles_t cps = osd_cycles_per_second();

	// if this is the first time through, initialize the previous time value
	if (warming_up)
	{
		last_skipcount0_time = osd_cycles() - (int)((double)FRAMESKIP_LEVELS * (double)cps / video_fps);
		warming_up = 0;
	}

	// if this is the first frame in a sequence, adjust the base time for this frame
	if (frameskip_counter == 0)
		this_frame_base = last_skipcount0_time + (int)((double)FRAMESKIP_LEVELS * (double)cps / video_fps);

	// if we're not skipping this frame, draw it
	if (display->changed_flags & GAME_BITMAP_CHANGED)
		update_timing();

	//// if the LEDs have changed, update them
	//if (display->changed_flags & LED_STATE_CHANGED)
	//	osd_set_leds(display->led_state);

	// increment the frameskip counter
	frameskip_counter = (frameskip_counter + 1) % FRAMESKIP_LEVELS;

	// check for inputs
	check_inputs();
}
Exemple #2
0
static void recompute_fps(int skipped_it)
{
	/* increment the frame counters */
	frames_since_last_fps++;
	if (!skipped_it)
		rendered_frames_since_last_fps++;

	/* if we didn't skip this frame, we may be able to compute a new FPS */
	if (!skipped_it && frames_since_last_fps >= FRAMES_PER_FPS_UPDATE)
	{
		cycles_t cps = osd_cycles_per_second();
		cycles_t curr = osd_cycles();
		double seconds_elapsed = (double)(curr - last_fps_time) * (1.0 / (double)cps);
		double frames_per_sec = (double)frames_since_last_fps / seconds_elapsed;

		/* compute the performance data */
		performance.game_speed_percent = 100.0 * frames_per_sec / Machine->refresh_rate;
		performance.frames_per_second = (double)rendered_frames_since_last_fps / seconds_elapsed;

		/* reset the info */
		last_fps_time = curr;
		frames_since_last_fps = 0;
		rendered_frames_since_last_fps = 0;
	}

	/* for vector games, compute the vector update count once/second */
	vfcount++;
	if (vfcount >= (int)Machine->refresh_rate)
	{
		performance.vector_updates_last_second = vector_updates;
		vector_updates = 0;

		vfcount -= (int)Machine->refresh_rate;
	}
}
Exemple #3
0
void profiler_mark(int type)
{
	unsigned int curr_cycles;


	if (!use_profiler)
	{
		FILO_length = 0;
		return;
	}

	if (type >= PROFILER_CPU1 && type <= PROFILER_CPU8)
		profile.cpu_context_switches[memory]++;

	curr_cycles = osd_cycles();

	if (type != PROFILER_END)
	{
		if (FILO_length >= 10)
		{
logerror("Profiler error: FILO buffer overflow\n");
			return;
		}

		if (FILO_length > 0)
		{
			/* handle nested calls */
			profile.count[memory][FILO_type[FILO_length-1]] += (unsigned int)(curr_cycles - FILO_start[FILO_length-1]);
		}
		FILO_type[FILO_length] = type;
		FILO_start[FILO_length] = curr_cycles;
		FILO_length++;
	}
	else
	{
		if (FILO_length <= 0)
		{
logerror("Profiler error: FILO buffer underflow\n");
			return;
		}

		profile.count[memory][FILO_type[FILO_length-1]] += (unsigned int)(curr_cycles - FILO_start[FILO_length-1]);
		FILO_length--;
		if (FILO_length > 0)
		{
			/* handle nested calls */
			FILO_start[FILO_length-1] = curr_cycles;
		}
	}
}
Exemple #4
0
static void update_timing()
{
	cycles_t curr;

	if (fastfrms >= 0)
	{
		if (fastfrms-- == 0) throttle = 1;
		else throttle = 0;
	}

	// if we're throttling, synchronize
	if (throttle || game_is_paused)
		throttle_speed();

	// at the end, we need the current time
	curr = osd_cycles();

	// update stats for the FPS average calculation
	if (start_time == 0)
	{
		// start the timer going 1 second into the game
		if (timer_get_time() > 1.0)
			start_time = curr;
	}
	else
	{
		frames_displayed++;
		if (frames_displayed + 1 == frames_to_display)
			win_trying_to_quit = 1;
		end_time = curr;
	}

	// if we're at the start of a frameskip sequence, compute the speed
	if (frameskip_counter == 0)
		last_skipcount0_time = curr;

	//// update the bitmap we're drawing
	//profiler_mark(PROFILER_BLIT);
	//win_update_video_window(bitmap, bounds, vector_dirty_pixels);
	//profiler_mark(PROFILER_END);

	// if we're throttling and autoframeskip is on, adjust
	if (throttle && autoframeskip && frameskip_counter == 0)
		update_autoframeskip();
}
Exemple #5
0
int video_init(void)
{
	osd_create_params params;
	artwork_callbacks *artcallbacks;
	int bmwidth = Machine->drv->screen_width;
	int bmheight = Machine->drv->screen_height;

	movie_file = NULL;
	movie_frame = 0;

	add_pause_callback(video_pause);
	add_exit_callback(video_exit);

	/* first allocate the necessary palette structures */
	if (palette_start())
		return 1;

#ifndef NEW_RENDER
	/* if we're a vector game, override the screen width and height */
	if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
		scale_vectorgames(options.vector_width, options.vector_height, &bmwidth, &bmheight);

	/* compute the visible area for raster games */
	if (!(Machine->drv->video_attributes & VIDEO_TYPE_VECTOR))
	{
		params.width = Machine->drv->default_visible_area.max_x - Machine->drv->default_visible_area.min_x + 1;
		params.height = Machine->drv->default_visible_area.max_y - Machine->drv->default_visible_area.min_y + 1;
	}
	else
	{
		params.width = bmwidth;
		params.height = bmheight;
	}

	/* fill in the rest of the display parameters */
	compute_aspect_ratio(Machine->drv, &params.aspect_x, &params.aspect_y);
	params.depth = Machine->color_depth;
	params.colors = palette_get_total_colors_with_ui();
	params.fps = Machine->drv->frames_per_second;
	params.video_attributes = Machine->drv->video_attributes;

#ifdef MESS
	artcallbacks = &mess_artwork_callbacks;
#else
	artcallbacks = &mame_artwork_callbacks;
#endif

	/* initialize the display through the artwork (and eventually the OSD) layer */
	if (artwork_create_display(&params, direct_rgb_components, artcallbacks))
		return 1;

	/* the create display process may update the vector width/height, so recompute */
	if (Machine->drv->video_attributes & VIDEO_TYPE_VECTOR)
		scale_vectorgames(options.vector_width, options.vector_height, &bmwidth, &bmheight);

	/* now allocate the screen bitmap */
	scrbitmap[0] = auto_bitmap_alloc_depth(bmwidth, bmheight, Machine->color_depth);
	if (!scrbitmap[0])
		return 1;
#endif

	/* set the default refresh rate */
	set_refresh_rate(Machine->drv->frames_per_second);

	/* set the default visible area */
	set_visible_area(0,1,0,1);	// make sure everything is recalculated on multiple runs
	set_visible_area(
			Machine->drv->default_visible_area.min_x,
			Machine->drv->default_visible_area.max_x,
			Machine->drv->default_visible_area.min_y,
			Machine->drv->default_visible_area.max_y);

	/* create spriteram buffers if necessary */
	if (Machine->drv->video_attributes & VIDEO_BUFFERS_SPRITERAM)
		if (init_buffered_spriteram())
			return 1;

#ifndef NEW_RENDER
#if defined(MAME_DEBUG) && !defined(NEW_DEBUGGER)
	/* if the debugger is enabled, initialize its bitmap and font */
	if (Machine->debug_mode)
	{
		int depth = options.debug_depth ? options.debug_depth : Machine->color_depth;

		/* first allocate the debugger bitmap */
		Machine->debug_bitmap = auto_bitmap_alloc_depth(options.debug_width, options.debug_height, depth);
		if (!Machine->debug_bitmap)
			return 1;

		/* then create the debugger font */
		Machine->debugger_font = build_debugger_font();
		if (Machine->debugger_font == NULL)
			return 1;
	}
#endif
#endif

	/* convert the gfx ROMs into character sets. This is done BEFORE calling the driver's */
	/* palette_init() routine because it might need to check the Machine->gfx[] data */
	if (Machine->drv->gfxdecodeinfo)
		if (allocate_graphics(Machine->drv->gfxdecodeinfo))
			return 1;

	/* initialize the palette - must be done after osd_create_display() */
	if (palette_init())
		return 1;

	/* force the first update to be full */
	set_vh_global_attribute(NULL, 0);

	/* actually decode the graphics */
	if (Machine->drv->gfxdecodeinfo)
		decode_graphics(Machine->drv->gfxdecodeinfo);

	/* reset performance data */
	last_fps_time = osd_cycles();
	rendered_frames_since_last_fps = frames_since_last_fps = 0;
	performance.game_speed_percent = 100;
	performance.frames_per_second = Machine->refresh_rate;
	performance.vector_updates_last_second = 0;

	/* reset video statics and get out of here */
	pdrawgfx_shadow_lowpri = 0;
	leds_status = 0;

	/* initialize tilemaps */
	if (tilemap_init() != 0)
		fatalerror("tilemap_init failed");
	return 0;
}
Exemple #6
0
void throttle_speed_part(int part, int totalparts)
{
	static double ticks_per_sleep_msec = 0;
	cycles_t target, curr, cps;

#ifdef VPINMAME
	if ((g_hEnterThrottle != INVALID_HANDLE_VALUE) && g_iSyncFactor) {
		if (g_iSyncFactor >= 1024)
			SetEvent(g_hEnterThrottle);
		else {
			iCurrentSyncValue += g_iSyncFactor;
			if (iCurrentSyncValue >= 1024) {
				SetEvent(g_hEnterThrottle);
				iCurrentSyncValue -= 1024;
			}
		}
	}
#endif

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

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

	// get the current time and the target time
	curr = osd_cycles();
	cps = osd_cycles_per_second();

	target = this_frame_base + (int)((double)frameskip_counter * (double)cps / video_fps);

	// If we are throttling to a fractional vsync, adjust target to the partial target.
	if (totalparts != 1)
	{
		// Meh.  The points in the code where frameskip counter gets updated is different from where the frame base is
		// reset.  Makes this delay computation complicated.
		if (frameskip_counter == 0)
			target += (int)((double)(FRAMESKIP_LEVELS) * (double)cps / video_fps);
		// MAGIC: Experimentation with actual resuts show the most even distribution if I throttle to 1/7th increments at each 25% timestep.
		target -= ((cycles_t)((double)cps / (video_fps * (totalparts + 3)))) * (totalparts - part + 3);
	}

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

	// Adjust target for sound catchup
	if (g_iThrottleAdj)
	{
		target -= (cycles_t)(g_iThrottleAdj*ticks_per_sleep_msec);
	}
	// sync
	if (curr - target < 0)
	{
#ifdef DEBUG_THROTTLE
		{
			char tmp[91];
			sprintf(tmp, "Throt: part %d of %d FS: %d Delta: %lld\n", part, totalparts, frameskip_counter, curr - target);
			OutputDebugString(tmp);
		}
#endif

		// loop until we reach the target time
		while (curr - target < 0)
		{
#if 1 // VPINMAME
			//if((INT64)((target - curr)/(ticks_per_sleep_msec*1.1))-1 > 0) // pessimistic estimate of stuff below, but still stutters then
			//	uSleep((UINT64)((target - curr)*1000/(ticks_per_sleep_msec*1.1))-1);
			if (totalparts > 1)
				uUnderSleep((UINT64)((target - curr) * 1000 / ticks_per_sleep_msec)); // will sleep too short
			else
				uOverSleep((UINT64)((target - curr) * 1000 / ticks_per_sleep_msec)); // will sleep too long
#else
			// if we have enough time to sleep, do it
			// ...but not if we're autoframeskipping and we're behind
			if (allow_sleep && (!autoframeskip || frameskip == 0) &&
				(target - curr) > (cycles_t)(ticks_per_sleep_msec * 1.1))
			{
				cycles_t next;

				// keep track of how long we actually slept
				uSleep(100); //1000?
				next = osd_cycles();
				ticks_per_sleep_msec = (ticks_per_sleep_msec * 0.90) + ((double)(next - curr) * 0.10);
				curr = next;
			}
			else
#endif
			{
				// update the current time
				curr = osd_cycles();
			}
		}
	}
	else if (curr - target >= (int)(cps / video_fps) && totalparts == 1)
	{
		// We're behind schedule by a frame or more.  Something must
		// have taken longer than it should have (e.g., a CPU emulator
		// time slice must have gone on too long).  We don't have a
		// time machine, so we can't go back and sync this frame to a
		// time in the past, but we can at least sync up the current
		// frame with the current real time.
		//
		// Note that the 12-frame "skip" cycle would eventually get
		// things back in sync even without this adjustment, but it
		// can cause audio glitching if we wait until then.  The skip
		// cycle will try to make up for the lost time by giving shorter
		// time slices to the next batch of 12 frames, but the way it
		// does its calculation, the time taken out of those short
		// frames will pile up in the *next next* skip cycle, causing
		// a long (order of 100ms) pause that can manifset as an audio
		// glitch and/or video hiccup.
		//
		// The adjustment here is simply the amount of real time by
		// which we're behind schedule.  Add this to the base time,
		// since the real time for this frame is later than we expected.
		this_frame_base += curr - target;
	}

	// idle time done
	profiler_mark(PROFILER_END);
}
Exemple #7
0
//---------------------------------------------------------------------
//	MoveCursor
//---------------------------------------------------------------------
void CVirtualKeyboardView::MoveCursor( CInputManager &gp, BOOL unused )
{
	static UINT64		lastTime = 0;
	UINT64 curTime = osd_cycles();
	FLOAT elapsedTime = (FLOAT)(curTime - lastTime) / (FLOAT)osd_cycles_per_second();
	if( !lastTime )
	{
			// lastTime isn't valid yet, so wait for the next frame
		lastTime = curTime;
		return;
	}
	lastTime = curTime;

		// Decrement the dpad movement timer
	if( m_dpadCursorDelay > 0.0f )
	{
		m_dpadCursorDelay -= elapsedTime;
    
		if( m_dpadCursorDelay < 0.0f || !gp.IsOneOfButtonsPressed( GP_DPAD_MASK | GP_LA_MASK ) )
			m_dpadCursorDelay = 0.0f;
	}

  if( m_buttonDelay > 0.0f )
  {
    m_buttonDelay -= elapsedTime;
    if( m_buttonDelay < 0.0f || !(gp.IsOneOfButtonsPressed( GP_A | GP_B ) || gp.IsAnyKeyPressed()) )
      m_buttonDelay = 0.0f;
  }

  if( m_dpadCursorDelay == 0.0f )
  {
    if( gp.IsOneOfButtonsPressed( GP_DPAD_DOWN | GP_LA_DOWN ) )
	  {
      if( m_cursorPositionY < GetNumBodyLines() - 1 )
        ++m_cursorPositionY;
      else
        m_cursorPositionY = 0;

        // Force m_cursorPositionX to be in range
      if( m_cursorPositionY < 4 )
      {
        if( m_cursorPositionX >= wcslen( g_keyboardData[m_cursorPositionY] ) )
          m_cursorPositionX = wcslen( g_keyboardData[m_cursorPositionY] ) - 1;
      }
//      else
//        m_cursorPositionX = 0;

		  m_dpadCursorDelay = DPADCURSORMOVE_TIMEOUT;
	  }
    else if( gp.IsOneOfButtonsPressed( GP_DPAD_UP | GP_LA_UP ) )
	  {
      if( m_cursorPositionY )
        --m_cursorPositionY;
      else
        m_cursorPositionY = GetNumBodyLines() - 1;

        // Force m_cursorPositionX to be in range
      if( m_cursorPositionY < 4 )
      {
        if( m_cursorPositionX >= wcslen( g_keyboardData[m_cursorPositionY] ) )
          m_cursorPositionX = wcslen( g_keyboardData[m_cursorPositionY] ) - 1;
      }

		  m_dpadCursorDelay = DPADCURSORMOVE_TIMEOUT;
	  }
    if( gp.IsOneOfButtonsPressed( GP_DPAD_LEFT | GP_LA_LEFT ) )
	  {
      if( m_cursorPositionY < 4 )
      {
        if( m_cursorPositionX )
          --m_cursorPositionX;
        else
          m_cursorPositionX = wcslen( g_keyboardData[m_cursorPositionY] ) - 1;
      }
		  m_dpadCursorDelay = DPADCURSORMOVE_TIMEOUT;
	  }
    else if( gp.IsOneOfButtonsPressed( GP_DPAD_RIGHT | GP_LA_RIGHT ) )
	  {
      if( m_cursorPositionY < 4 )
      {
        if( m_cursorPositionX < wcslen( g_keyboardData[m_cursorPositionY] ) - 1 )
          ++m_cursorPositionX;
        else
          m_cursorPositionX = 0;
      }

		  m_dpadCursorDelay = DPADCURSORMOVE_TIMEOUT;
	  }
  }


  if( m_buttonDelay == 0.0f )
  {
    if( gp.IsButtonPressed( GP_A ) )
    {       
      m_buttonDelay = DPADCURSORMOVE_TIMEOUT;
     
        // See if the cursor is on OK or Cancel
      if( m_cursorPositionY == 5 )
      {
        m_inputState = MENU_ACCEPTED;
        return;
      }
      else if( m_cursorPositionY == 4 )
      {
        m_inputState = MENU_CANCELLED;
        return;
      }

        // Add the new char
      char newChar[2] = {0};
      wctomb( &newChar[0], g_keyboardData[m_cursorPositionY][m_cursorPositionX] );
      m_data += newChar;

      if( m_data.length() >= (m_maxDisplayableChars - 1) )
        ++m_dataDrawStartPosition;
    }
    else if( gp.IsButtonPressed( GP_B ) )
    {
        // Remove the last character from the data string
      m_buttonDelay = DPADCURSORMOVE_TIMEOUT;
      if( m_data.length() )
      {
        m_data = m_data.substr( 0, m_data.length() - 1 );
        if( m_dataDrawStartPosition )
          --m_dataDrawStartPosition;
      }
    }


        // Check the keyboard
    if( gp.IsKeyPressed( VK_BACK ) )
    {
      m_buttonDelay = KEYBOARDINPUT_TIMEOUT;
      if( m_data.length() )
      {
        m_data = m_data.substr( 0, m_data.length() - 1 );
        if( m_dataDrawStartPosition )
          --m_dataDrawStartPosition;
      }
    }
    else
    {
        // Colon (PERIOD on a German KB, Semicolon on a US)
      BYTE keys[2] = { VK_OEM_PERIOD, VK_OEM_1 };
      if( gp.IsOneOfKeysPressed( keys, 2 ) )
      {
        m_buttonDelay = KEYBOARDINPUT_TIMEOUT;
        m_data += ":";
        if( m_data.length() >= (m_maxDisplayableChars - 1) )
          ++m_dataDrawStartPosition;
      }

        // Slash (German / is handled elsewhere)
      if( gp.IsKeyPressed( VK_OEM_2 ) )
      {
        m_buttonDelay = KEYBOARDINPUT_TIMEOUT;
        m_data += "/";
        if( m_data.length() >= (m_maxDisplayableChars - 1) )
          ++m_dataDrawStartPosition;
      }

        // Backslash (German: VK_OEM_MINUS, US: VK_OEM_5)
      keys[0] = VK_OEM_MINUS;
      keys[1] = VK_OEM_5;
      if( gp.IsOneOfKeysPressed( keys, 2 ) )
      {
        m_buttonDelay = KEYBOARDINPUT_TIMEOUT;
        m_data += "\\";
        if( m_data.length() >= (m_maxDisplayableChars - 1) )
          ++m_dataDrawStartPosition;
      }


      BYTE keyIndex = 'A';
      for( ; keyIndex < 'Z'; ++keyIndex )
      {
        if( gp.IsKeyPressed( keyIndex ) )
        {
          m_buttonDelay = KEYBOARDINPUT_TIMEOUT;
            // Add the new char
          char newChar[2] = {0};
          newChar[0] = (char)keyIndex;

            // Handle the @ symbol (German KB)
          if( keyIndex == 'Q' && gp.IsKeyPressed( VK_RMENU ) )
            newChar[0] = '@';

          m_data += newChar;

          if( m_data.length() >= (m_maxDisplayableChars - 1) )
            ++m_dataDrawStartPosition;
          break;
        }
      }

      keys[0] = VK_LSHIFT;
      keys[1] = VK_RSHIFT;
      for( keyIndex = '0'; keyIndex < '9'; ++keyIndex )
      {
        if( gp.IsKeyPressed( keyIndex ) )
        {
          m_buttonDelay = KEYBOARDINPUT_TIMEOUT;

            // Add the new char
          char newChar[2] = {0};
          newChar[0] = (char)keyIndex;

            // Handle the @ symbol
          if( keyIndex == '2' && gp.IsOneOfKeysPressed( keys, 2 ) )
            newChar[0] = '@';
          else if( keyIndex == '7' && gp.IsOneOfKeysPressed( keys, 2 ) )
          {
              // German '/' key
            newChar[0] = '/';
          }

          m_data += newChar;

          if( m_data.length() >= (m_maxDisplayableChars - 1) )
            ++m_dataDrawStartPosition;
          break;
        }
      }
    }
  }


  if( gp.IsButtonPressed( GP_BACK ) || gp.IsKeyPressed( VK_DELETE ) )
    m_inputState = MENU_CANCELLED;
  else if( gp.IsButtonPressed( GP_START ) || gp.IsKeyPressed( VK_RETURN ) )
    m_inputState = MENU_ACCEPTED;
}