示例#1
0
/**
 * runloop_iterate:
 *
 * Run Libretro core in RetroArch for one frame.
 *
 * Returns: 0 on success, 1 if we have to wait until 
 * button input in order to wake up the loop, 
 * -1 if we forcibly quit out of the RetroArch iteration loop.
 **/
int runloop_iterate(unsigned *sleep_ms)
{
   unsigned i;
   event_cmd_state_t    cmd;
   retro_time_t current, target, to_sleep_ms;
   static retro_input_t last_input              = {0};
   event_cmd_state_t   *cmd_ptr                 = &cmd;
   static retro_time_t frame_limit_minimum_time = 0.0;
   static retro_time_t frame_limit_last_time    = 0.0;
   settings_t *settings                         = config_get_ptr();

   cmd.state[1]                                 = last_input;
   cmd.state[0]                                 = input_keys_pressed();
   last_input                                   = cmd.state[0];

   runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_TIME_LAST, NULL);

   if (runloop_ctl(RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT, NULL))
   {
      struct retro_system_av_info *av_info = 
         video_viewport_get_system_av_info();
      float fastforward_ratio              = 
         (settings->fastforward_ratio == 0.0f) 
         ? 1.0f : settings->fastforward_ratio;

      frame_limit_last_time    = cpu_features_get_time_usec();
      frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f 
            / (av_info->timing.fps * fastforward_ratio));

      runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_LIMIT, NULL);
   }

   if (input_driver_is_flushing_input())
   {
      input_driver_unset_flushing_input();
      if (cmd.state[0].state)
      {
         cmd.state[0].state = 0;

         /* If core was paused before entering menu, evoke
          * pause toggle to wake it up. */
         if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL))
            BIT64_SET(cmd.state[0].state, RARCH_PAUSE_TOGGLE);
         input_driver_set_flushing_input();
      }
   }
   
   if (runloop_frame_time.callback)
   {
      /* Updates frame timing if frame timing callback is in use by the core.
       * Limits frame time if fast forward ratio throttle is enabled. */

      retro_time_t current     = cpu_features_get_time_usec();
      retro_time_t delta       = current - runloop_frame_time_last;
      bool is_locked_fps       = (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) ||
                                  input_driver_is_nonblock_state()) |
                                  !!recording_driver_get_data_ptr();


      if (!runloop_frame_time_last || is_locked_fps)
         delta = runloop_frame_time.reference;

      if (!is_locked_fps && runloop_ctl(RUNLOOP_CTL_IS_SLOWMOTION, NULL))
         delta /= settings->slowmotion_ratio;

      runloop_frame_time_last = current;

      if (is_locked_fps)
         runloop_frame_time_last = 0;

      runloop_frame_time.callback(delta);
   }

   cmd.state[2].state      = cmd.state[0].state & ~cmd.state[1].state;  /* trigger  */

   if (runloop_cmd_triggered(cmd_ptr, RARCH_OVERLAY_NEXT))
      command_event(CMD_EVENT_OVERLAY_NEXT, NULL);

   if (runloop_cmd_triggered(cmd_ptr, RARCH_FULLSCREEN_TOGGLE_KEY))
   {
      bool fullscreen_toggled = !runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL);
#ifdef HAVE_MENU
      fullscreen_toggled = fullscreen_toggled || 
         menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL);
#endif

      if (fullscreen_toggled)
         command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
   }

   if (runloop_cmd_triggered(cmd_ptr, RARCH_GRAB_MOUSE_TOGGLE))
      command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);

#ifdef HAVE_MENU
   if (runloop_cmd_menu_press(cmd_ptr) || 
         rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
   {
      if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
      {
         if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) && 
               !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
      }
      else
         rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL);
   }
#endif

#ifdef HAVE_OVERLAY
   runloop_iterate_linefeed_overlay(settings);
#endif

   if (runloop_iterate_time_to_exit(
            runloop_cmd_press(cmd_ptr, RARCH_QUIT_KEY)) != 1)
   {
      frame_limit_last_time = 0.0;
      return -1;
   }


#ifdef HAVE_MENU
   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      int ret = runloop_iterate_menu((enum menu_action)
      menu_input_frame_retropad(cmd.state[0], cmd.state[2]),
      sleep_ms);

      if (ret == -1)
         goto end;
      return ret;
   }
#endif

   if (!runloop_check_state(&cmd, &runloop_shader_dir))
   {
      /* RetroArch has been paused. */
      core_poll();
      *sleep_ms = 10;
      return 1;
   }

#if defined(HAVE_THREADS)
   autosave_lock();
#endif

#ifdef HAVE_NETPLAY
   netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL);
#endif

   if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
      bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL);

   camera_driver_ctl(RARCH_CAMERA_CTL_POLL, NULL);

   /* Update binds for analog dpad modes. */
   for (i = 0; i < settings->input.max_users; i++)
   {
      if (!settings->input.analog_dpad_mode[i])
         continue;

      input_push_analog_dpad(settings->input.binds[i],
            settings->input.analog_dpad_mode[i]);
      input_push_analog_dpad(settings->input.autoconf_binds[i],
            settings->input.analog_dpad_mode[i]);
   }

   if ((settings->video.frame_delay > 0) && 
         !input_driver_is_nonblock_state())
      retro_sleep(settings->video.frame_delay);

   core_run();

#ifdef HAVE_CHEEVOS
   cheevos_test();
#endif

   for (i = 0; i < settings->input.max_users; i++)
   {
      if (!settings->input.analog_dpad_mode[i])
         continue;

      input_pop_analog_dpad(settings->input.binds[i]);
      input_pop_analog_dpad(settings->input.autoconf_binds[i]);
   }

   if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
      bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL);

#ifdef HAVE_NETPLAY
   netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL);
#endif

#if defined(HAVE_THREADS)
   autosave_unlock();
#endif

   if (!settings->fastforward_ratio)
      return 0;
#ifdef HAVE_MENU
end:
#endif

   current                        = cpu_features_get_time_usec();
   target                         = frame_limit_last_time + 
      frame_limit_minimum_time;
   to_sleep_ms                    = (target - current) / 1000;

   if (to_sleep_ms > 0)
   {
      *sleep_ms = (unsigned)to_sleep_ms;
      /* Combat jitter a bit. */
      frame_limit_last_time += frame_limit_minimum_time;
      return 1;
   }

   frame_limit_last_time  = cpu_features_get_time_usec();

   return 0;
}
示例#2
0
/**
 * runloop_iterate:
 *
 * Run Libretro core in RetroArch for one frame.
 *
 * Returns: 0 on success, 1 if we have to wait until button input in order
 * to wake up the loop, -1 if we forcibly quit out of the RetroArch iteration loop.
 **/
int runloop_iterate(unsigned *sleep_ms)
{
   unsigned i;
   event_cmd_state_t    cmd;
   event_cmd_state_t   *cmd_ptr                 = &cmd;
   retro_time_t current, target, to_sleep_ms;
   static retro_usec_t frame_time_last          = 0;
   static retro_time_t frame_limit_minimum_time = 0.0;
   static retro_time_t frame_limit_last_time    = 0.0;
   static retro_input_t last_input              = 0;
   settings_t *settings                         = config_get_ptr();
   global_t   *global                           = global_get_ptr();
   rarch_system_info_t *system                  = NULL;

   cmd.state[1]                                 = last_input;
   cmd.state[0]                                 = input_keys_pressed();
   last_input                                   = cmd.state[0];

   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);

   if (runloop_ctl(RUNLOOP_CTL_IS_FRAME_TIME_LAST, NULL))
   {
      frame_time_last = 0;
      runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_TIME_LAST, NULL);
   }

   if (runloop_ctl(RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT, NULL))
   {
      struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
      float fastforward_ratio              = (settings->fastforward_ratio == 0.0f) 
         ? 1.0f : settings->fastforward_ratio;

      frame_limit_last_time    = retro_get_time_usec();
      frame_limit_minimum_time = (retro_time_t)roundf(1000000.0f 
            / (av_info->timing.fps * fastforward_ratio));

      runloop_ctl(RUNLOOP_CTL_UNSET_FRAME_LIMIT, NULL);
   }

   if (input_driver_ctl(RARCH_INPUT_CTL_IS_FLUSHING_INPUT, NULL))
   {
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_FLUSHING_INPUT, NULL);
      if (cmd.state[0])
      {
         cmd.state[0] = 0;

         /* If core was paused before entering menu, evoke
          * pause toggle to wake it up. */
         if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL))
            BIT64_SET(cmd.state[0], RARCH_PAUSE_TOGGLE);
         input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);
      }
   }

   if (system->frame_time.callback)
   {
      /* Updates frame timing if frame timing callback is in use by the core.
       * Limits frame time if fast forward ratio throttle is enabled. */

      bool is_slowmotion;
      retro_time_t current     = retro_get_time_usec();
      retro_time_t delta       = current - frame_time_last;
      bool is_locked_fps       = (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL) ||
            input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL)) |
         !!recording_driver_get_data_ptr();

      runloop_ctl(RUNLOOP_CTL_IS_SLOWMOTION, &is_slowmotion);

      if (!frame_time_last || is_locked_fps)
         delta = system->frame_time.reference;

      if (!is_locked_fps && is_slowmotion)
         delta /= settings->slowmotion_ratio;

      frame_time_last = current;

      if (is_locked_fps)
         frame_time_last = 0;

      system->frame_time.callback(delta);
   }

   cmd.state[2]      = cmd.state[0] & ~cmd.state[1];  /* trigger  */

   if (runloop_cmd_triggered(cmd_ptr, RARCH_OVERLAY_NEXT))
      event_command(EVENT_CMD_OVERLAY_NEXT);

   if (runloop_cmd_triggered(cmd_ptr, RARCH_FULLSCREEN_TOGGLE_KEY))
   {
      bool fullscreen_toggled = !runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL);
#ifdef HAVE_MENU
      fullscreen_toggled = fullscreen_toggled || menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL);
#endif

      if (fullscreen_toggled)
         event_command(EVENT_CMD_FULLSCREEN_TOGGLE);
   }

   if (runloop_cmd_triggered(cmd_ptr, RARCH_GRAB_MOUSE_TOGGLE))
      event_command(EVENT_CMD_GRAB_MOUSE_TOGGLE);

#ifdef HAVE_MENU
   if (runloop_cmd_menu_press(cmd_ptr) || (global->inited.core.type == CORE_TYPE_DUMMY))
   {
      if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
      {
         if (global->inited.main && (global->inited.core.type != CORE_TYPE_DUMMY))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
      }
      else
         rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL);
   }
#endif

#ifdef HAVE_OVERLAY
   runloop_iterate_linefeed_overlay(settings);
#endif

   if (runloop_iterate_time_to_exit(runloop_cmd_press(cmd_ptr, RARCH_QUIT_KEY)) != 1)
   {
      frame_limit_last_time = 0.0;
      return -1;
   }


#ifdef HAVE_MENU
   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      bool focused = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL) && !ui_companion_is_on_foreground();
      bool is_idle = runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL);

      if (menu_driver_iterate((enum menu_action)menu_input_frame_retropad(cmd.state[0], cmd.state[2])) == -1)
         rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);

      if (focused || !is_idle)
         menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL);

      if (!focused || is_idle)
      {
         *sleep_ms = 10;
         return 1;
      }

      goto end;
   }
#endif

   if (!runloop_ctl(RUNLOOP_CTL_CHECK_STATE, &cmd))
   {
      /* RetroArch has been paused. */
      retro_ctx.poll_cb();
      *sleep_ms = 10;
      return 1;
   }

#if defined(HAVE_THREADS)
   lock_autosave();
#endif

#ifdef HAVE_NETPLAY
   netplay_driver_ctl(RARCH_NETPLAY_CTL_PRE_FRAME, NULL);
#endif

   if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
      bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_START, NULL);

   if (system->camera_callback.caps)
      driver_camera_poll();

   /* Update binds for analog dpad modes. */
   for (i = 0; i < settings->input.max_users; i++)
   {
      if (!settings->input.analog_dpad_mode[i])
         continue;

      input_push_analog_dpad(settings->input.binds[i],
            settings->input.analog_dpad_mode[i]);
      input_push_analog_dpad(settings->input.autoconf_binds[i],
            settings->input.analog_dpad_mode[i]);
   }

   if ((settings->video.frame_delay > 0) && 
         !input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL))
      retro_sleep(settings->video.frame_delay);

   /* Run libretro for one frame. */
   core.retro_run();

#ifdef HAVE_CHEEVOS
   /* Test the achievements. */
   cheevos_test();
#endif

   for (i = 0; i < settings->input.max_users; i++)
   {
      if (!settings->input.analog_dpad_mode[i])
         continue;

      input_pop_analog_dpad(settings->input.binds[i]);
      input_pop_analog_dpad(settings->input.autoconf_binds[i]);
   }

   if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
      bsv_movie_ctl(BSV_MOVIE_CTL_SET_FRAME_END, NULL);

#ifdef HAVE_NETPLAY
   netplay_driver_ctl(RARCH_NETPLAY_CTL_POST_FRAME, NULL);
#endif

#if defined(HAVE_THREADS)
   unlock_autosave();
#endif

#ifdef HAVE_MENU
end:
#endif
   if (!settings->fastforward_ratio)
      return 0;

   current                        = retro_get_time_usec();
   target                         = frame_limit_last_time + frame_limit_minimum_time;
   to_sleep_ms                    = (target - current) / 1000;

   if (to_sleep_ms > 0)
   {
      *sleep_ms = (unsigned)to_sleep_ms;
      /* Combat jitter a bit. */
      frame_limit_last_time += frame_limit_minimum_time;
      return 1;
   }

   frame_limit_last_time  = retro_get_time_usec();

   return 0;
}
示例#3
0
static enum runloop_state runloop_check_state(
      settings_t *settings,
      uint64_t current_input,
      uint64_t old_input,
      unsigned *sleep_ms)
{
   static bool old_focus            = true;
#ifdef HAVE_OVERLAY
   static char prev_overlay_restore = false;
   bool osk_enable                  = input_driver_is_onscreen_keyboard_enabled();
#endif
#ifdef HAVE_NETWORKING
   bool tmp                         = false;
#endif
   bool focused                     = true;
   uint64_t trigger_input           = current_input & ~old_input;
   bool pause_pressed               = runloop_cmd_triggered(trigger_input, RARCH_PAUSE_TOGGLE);

   if (input_driver_is_flushing_input())
   {
      input_driver_unset_flushing_input();
      if (current_input)
      {
         current_input = 0;

         /* If core was paused before entering menu, evoke
          * pause toggle to wake it up. */
         if (runloop_paused)
            BIT64_SET(current_input, RARCH_PAUSE_TOGGLE);
         input_driver_set_flushing_input();
      }
   }

   if (runloop_cmd_triggered(trigger_input, RARCH_OVERLAY_NEXT))
      command_event(CMD_EVENT_OVERLAY_NEXT, NULL);

   if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY))
   {
      bool fullscreen_toggled = !runloop_paused;
#ifdef HAVE_MENU
      fullscreen_toggled = fullscreen_toggled ||
         menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL);
#endif

      if (fullscreen_toggled)
         command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
   }

   if (runloop_cmd_triggered(trigger_input, RARCH_GRAB_MOUSE_TOGGLE))
      command_event(CMD_EVENT_GRAB_MOUSE_TOGGLE, NULL);


#ifdef HAVE_OVERLAY
   if (osk_enable && !input_keyboard_ctl(
            RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL))
   {
      input_driver_unset_onscreen_keyboard_enabled();
      prev_overlay_restore  = true;
      command_event(CMD_EVENT_OVERLAY_DEINIT, NULL);
   }
   else if (!osk_enable && input_keyboard_ctl(
            RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL))
   {
      input_driver_set_onscreen_keyboard_enabled();
      prev_overlay_restore  = false;
      command_event(CMD_EVENT_OVERLAY_INIT, NULL);
   }
   else if (prev_overlay_restore)
   {
      if (!settings->input.overlay_hide_in_menu)
         command_event(CMD_EVENT_OVERLAY_INIT, NULL);
      prev_overlay_restore = false;
   }
#endif

   if (runloop_iterate_time_to_exit(
            runloop_cmd_press(current_input, RARCH_QUIT_KEY)) != 1)
      return RUNLOOP_STATE_QUIT;

#ifdef HAVE_MENU
   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      menu_ctx_iterate_t iter;
      bool skip = false;
#ifdef HAVE_OVERLAY
      skip = osk_enable && input_keyboard_return_pressed();
#endif

      if (!skip)
      {
         enum menu_action action = (enum menu_action)menu_event(current_input, trigger_input);
         bool focused            = settings->pause_nonactive ? video_driver_is_focused() : true;

         focused                 = focused && !ui_companion_is_on_foreground();

         iter.action             = action;

         if (!menu_driver_ctl(RARCH_MENU_CTL_ITERATE, &iter))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);

         if (focused || !runloop_idle)
            menu_driver_ctl(RARCH_MENU_CTL_RENDER, NULL);

         if (!focused)
            return RUNLOOP_STATE_SLEEP;

         if (action == MENU_ACTION_QUIT)
            return RUNLOOP_STATE_QUIT;
      }
   }
#endif
   
   if (runloop_idle)
      return RUNLOOP_STATE_SLEEP;

#ifdef HAVE_MENU
   if (menu_event_keyboard_is_set(RETROK_F1) == 1)
   {
      if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
      {
         if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) &&
               !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
         {
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
            menu_event_keyboard_set(false, RETROK_F1);
         }
      }
   }
   else if ((!menu_event_keyboard_is_set(RETROK_F1) && runloop_cmd_menu_press(current_input, old_input, trigger_input)) ||
         rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
   {
      if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
      {
         if (rarch_ctl(RARCH_CTL_IS_INITED, NULL) &&
               !rarch_ctl(RARCH_CTL_IS_DUMMY_CORE, NULL))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
      }
      else
      {
        menu_display_toggle_set_reason(MENU_TOGGLE_REASON_USER);
        rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL);
      }
   }
   else
      menu_event_keyboard_set(false, RETROK_F1);

   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      if (!settings->menu.throttle_framerate && !settings->fastforward_ratio)
         return RUNLOOP_STATE_MENU_ITERATE;

      return RUNLOOP_STATE_END;
   }
#endif

   if (settings->pause_nonactive)
      focused                = video_driver_is_focused();

   if (runloop_cmd_triggered(trigger_input, RARCH_SCREENSHOT))
      command_event(CMD_EVENT_TAKE_SCREENSHOT, NULL);

   if (runloop_cmd_triggered(trigger_input, RARCH_MUTE))
      command_event(CMD_EVENT_AUDIO_MUTE_TOGGLE, NULL);

   if (runloop_cmd_triggered(trigger_input, RARCH_OSK))
   {
      if (input_keyboard_ctl(
               RARCH_INPUT_KEYBOARD_CTL_IS_LINEFEED_ENABLED, NULL))
         input_keyboard_ctl(
               RARCH_INPUT_KEYBOARD_CTL_UNSET_LINEFEED_ENABLED, NULL);
      else
         input_keyboard_ctl(
               RARCH_INPUT_KEYBOARD_CTL_SET_LINEFEED_ENABLED, NULL);
   }

   if (runloop_cmd_press(current_input, RARCH_VOLUME_UP))
      command_event(CMD_EVENT_VOLUME_UP, NULL);
   else if (runloop_cmd_press(current_input, RARCH_VOLUME_DOWN))
      command_event(CMD_EVENT_VOLUME_DOWN, NULL);

#ifdef HAVE_NETWORKING
   tmp = runloop_cmd_triggered(trigger_input, RARCH_NETPLAY_FLIP);
   netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp);
   tmp = runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY);
   netplay_driver_ctl(RARCH_NETPLAY_CTL_FULLSCREEN_TOGGLE, &tmp);
#endif

   /* Check if libretro pause key was pressed. If so, pause or
    * unpause the libretro core. */

   /* FRAMEADVANCE will set us into pause mode. */
   pause_pressed |= !runloop_paused && runloop_cmd_triggered(trigger_input, RARCH_FRAMEADVANCE);

   if (focused && pause_pressed)
      command_event(CMD_EVENT_PAUSE_TOGGLE, NULL);
   else if (focused && !old_focus)
      command_event(CMD_EVENT_UNPAUSE, NULL);
   else if (!focused && old_focus)
      command_event(CMD_EVENT_PAUSE, NULL);

   old_focus = focused;

   if (!focused)
      return RUNLOOP_STATE_SLEEP;

   if (runloop_paused)
   {
      /* check pause state */

      bool check_is_oneshot = runloop_cmd_triggered(trigger_input,
            RARCH_FRAMEADVANCE)
         || runloop_cmd_press(current_input, RARCH_REWIND);
      if (runloop_cmd_triggered(trigger_input, RARCH_FULLSCREEN_TOGGLE_KEY))
      {
         command_event(CMD_EVENT_FULLSCREEN_TOGGLE, NULL);
         if (!runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL))
            video_driver_cached_frame();
      }

      if (!check_is_oneshot)
         return RUNLOOP_STATE_SLEEP;
   }

   /* To avoid continous switching if we hold the button down, we require
    * that the button must go from pressed to unpressed back to pressed
    * to be able to toggle between then.
    */
   if (runloop_cmd_triggered(trigger_input, RARCH_FAST_FORWARD_KEY))
   {
      if (input_driver_is_nonblock_state())
         input_driver_unset_nonblock_state();
      else
         input_driver_set_nonblock_state();
      driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL);
   }
   else if ((runloop_cmd_pressed(old_input, RARCH_FAST_FORWARD_HOLD_KEY) 
         != runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY)))
   {
      if (runloop_cmd_press(current_input, RARCH_FAST_FORWARD_HOLD_KEY))
         input_driver_set_nonblock_state();
      else
         input_driver_unset_nonblock_state();
      driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL);
   }

   /* Checks if the state increase/decrease keys have been pressed 
    * for this frame. */
   if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_PLUS))
   {
      char msg[128];

      msg[0] = '\0';

      settings->state_slot++;

      snprintf(msg, sizeof(msg), "%s: %d",
            msg_hash_to_str(MSG_STATE_SLOT),
            settings->state_slot);

      runloop_msg_queue_push(msg, 2, 180, true);

      RARCH_LOG("%s\n", msg);
   }
   else if (runloop_cmd_triggered(trigger_input, RARCH_STATE_SLOT_MINUS))
   {
      char msg[128];

      msg[0] = '\0';

      if (settings->state_slot > 0)
         settings->state_slot--;

      snprintf(msg, sizeof(msg), "%s: %d",
            msg_hash_to_str(MSG_STATE_SLOT),
            settings->state_slot);

      runloop_msg_queue_push(msg, 2, 180, true);

      RARCH_LOG("%s\n", msg);
   }

   if (runloop_cmd_triggered(trigger_input, RARCH_SAVE_STATE_KEY))
      command_event(CMD_EVENT_SAVE_STATE, NULL);
   else if (runloop_cmd_triggered(trigger_input, RARCH_LOAD_STATE_KEY))
      command_event(CMD_EVENT_LOAD_STATE, NULL);

#ifdef HAVE_CHEEVOS
   if (!settings->cheevos.hardcore_mode_enable)
#endif
      state_manager_check_rewind(runloop_cmd_press(current_input, RARCH_REWIND));

   runloop_slowmotion = runloop_cmd_press(current_input, RARCH_SLOWMOTION);

   if (runloop_slowmotion)
   {
      /* Checks if slowmotion toggle/hold was being pressed and/or held. */
      if (settings->video.black_frame_insertion)
      {
         if (!runloop_ctl(RUNLOOP_CTL_IS_IDLE, NULL))
            video_driver_cached_frame();
      }

      if (state_manager_frame_is_reversed())
         runloop_msg_queue_push(msg_hash_to_str(MSG_SLOW_MOTION_REWIND), 2, 30, true);
      else
         runloop_msg_queue_push(msg_hash_to_str(MSG_SLOW_MOTION), 2, 30, true);
   }

   if (runloop_cmd_triggered(trigger_input, RARCH_MOVIE_RECORD_TOGGLE))
      bsv_movie_check();

   if (runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT) ||
      runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV))
      dir_check_shader(
            runloop_cmd_triggered(trigger_input, RARCH_SHADER_NEXT),
            runloop_cmd_triggered(trigger_input, RARCH_SHADER_PREV));

   if (runloop_cmd_triggered(trigger_input, RARCH_DISK_EJECT_TOGGLE))
      command_event(CMD_EVENT_DISK_EJECT_TOGGLE, NULL);
   else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_NEXT))
      command_event(CMD_EVENT_DISK_NEXT, NULL);
   else if (runloop_cmd_triggered(trigger_input, RARCH_DISK_PREV))
      command_event(CMD_EVENT_DISK_PREV, NULL);

   if (runloop_cmd_triggered(trigger_input, RARCH_RESET))
      command_event(CMD_EVENT_RESET, NULL);

   cheat_manager_state_checks(
         runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_PLUS),
         runloop_cmd_triggered(trigger_input, RARCH_CHEAT_INDEX_MINUS),
         runloop_cmd_triggered(trigger_input, RARCH_CHEAT_TOGGLE));

   return RUNLOOP_STATE_ITERATE;
}