예제 #1
0
/**
 * check_fast_forward_button:
 * @fastforward_pressed  : is fastforward key pressed?
 * @hold_pressed         : is fastforward key pressed and held?
 * @old_hold_pressed     : was fastforward key pressed and held the last frame?
 *
 * Checks if the fast forward key has been pressed for this frame.
 *
 **/
static void check_fast_forward_button(bool fastforward_pressed,
      bool hold_pressed, bool old_hold_pressed)
{
   /* 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 (fastforward_pressed)
   {
      if (input_driver_ctl(RARCH_INPUT_CTL_IS_NONBLOCK_STATE, NULL))
         input_driver_ctl(RARCH_INPUT_CTL_UNSET_NONBLOCK_STATE, NULL);
      else
         input_driver_ctl(RARCH_INPUT_CTL_SET_NONBLOCK_STATE, NULL);
   }
   else if (old_hold_pressed != hold_pressed)
   {
      if (hold_pressed)
         input_driver_ctl(RARCH_INPUT_CTL_SET_NONBLOCK_STATE, NULL);
      else
         input_driver_ctl(RARCH_INPUT_CTL_UNSET_NONBLOCK_STATE, NULL);
   }
   else
      return;

   driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL);
}
예제 #2
0
static retro_input_t input_driver_keys_pressed(void)
{
   unsigned key;
   retro_input_t                ret = 0;

   for (key = 0; key < RARCH_BIND_LIST_END; key++)
   {
      bool state = false;
      if ((!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL) && ((key < RARCH_FIRST_META_KEY)))
            || !input_driver_ctl(RARCH_INPUT_CTL_IS_HOTKEY_BLOCKED, NULL))
         state = input_driver_ctl(RARCH_INPUT_CTL_KEY_PRESSED, &key);

      if (key >= RARCH_FIRST_META_KEY)
         state |= current_input->meta_key_pressed(current_input_data, key);

#ifdef HAVE_OVERLAY
      state |= input_overlay_key_pressed(key);
#endif

#ifdef HAVE_COMMAND
      if (input_driver_command)
         state |= rarch_cmd_get(input_driver_command, key);
#endif

#ifdef HAVE_NETWORK_GAMEPAD
      if (input_driver_remote)
         state |= input_remote_key_pressed(key,0);
#endif

      if (state)
         ret |= (UINT64_C(1) << key);
   }
   return ret;
}
예제 #3
0
static void runloop_iterate_linefeed_overlay(settings_t *settings)
{
   static char prev_overlay_restore = false;
   bool osk_enable = input_driver_ctl(RARCH_INPUT_CTL_IS_OSK_ENABLED, NULL);

   if (osk_enable && !input_driver_ctl(
            RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED, NULL))
   {
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_OSK_ENABLED, NULL);
      prev_overlay_restore  = true;
      event_cmd_ctl(EVENT_CMD_OVERLAY_DEINIT, NULL);
   }
   else if (!osk_enable && input_driver_ctl(
            RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED, NULL))
   {
      input_driver_ctl(RARCH_INPUT_CTL_SET_OSK_ENABLED, NULL);
      prev_overlay_restore  = false;
      event_cmd_ctl(EVENT_CMD_OVERLAY_INIT, NULL);
   }
   else if (prev_overlay_restore)
   {
      if (!settings->input.overlay_hide_in_menu)
         event_cmd_ctl(EVENT_CMD_OVERLAY_INIT, NULL);
      prev_overlay_restore = false;
   }
}
예제 #4
0
/* task_data = overlay_task_data_t* */
static void input_overlay_loaded(void *task_data, void *user_data, const char *err)
{
   size_t i;
   input_overlay_t       *ol;
   overlay_task_data_t *data = (overlay_task_data_t*)task_data;
   settings_t      *settings = config_get_ptr();
   const video_overlay_interface_t *iface = NULL;

   if (err)
      return;

#ifdef HAVE_MENU
   /* We can't display when the menu is up */
   if (settings->input.overlay_hide_in_menu && menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      if (!input_driver_ctl(RARCH_INPUT_CTL_IS_OSK_ENABLED, NULL)
            && settings->input.overlay_enable)
         goto abort_load;
   }
#endif

   if (!settings->input.overlay_enable)
      goto abort_load;

   if (!video_driver_overlay_interface(&iface) || !iface)
   {
      RARCH_ERR("Overlay interface is not present in video driver.\n");
      goto abort_load;
   }

   ol = (input_overlay_t*)calloc(1, sizeof(*ol));
   ol->overlays = data->overlays;
   ol->size     = data->size;
   ol->active   = data->active;
   ol->iface      = iface;
   ol->iface_data = video_driver_get_ptr(true);

   overlay_ptr = ol;

   input_overlay_load_active(settings->input.overlay_opacity);
   input_overlay_enable(input_driver_ctl(RARCH_INPUT_CTL_IS_OSK_ENABLED, NULL) ? settings->osk.enable : settings->input.overlay_enable);
   input_overlay_set_scale_factor(settings->input.overlay_scale);

   ol->next_index = (ol->index + 1) % ol->size;
   ol->state      = OVERLAY_STATUS_NONE;
   ol->alive      = true;

   free(data);
   return;

abort_load:
   for (i = 0; i < data->size; i++)
      input_overlay_free_overlay(&data->overlays[i]);

   free(data->overlays);
   free(data);
}
예제 #5
0
static void input_keyboard_line_toggle_osk(bool enable)
{
   settings_t *settings = config_get_ptr();

   if (!settings->osk.enable)
      return;

   if (enable)
      input_driver_ctl(RARCH_INPUT_CTL_SET_KEYBOARD_LINEFEED_ENABLED, NULL);
   else
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_KEYBOARD_LINEFEED_ENABLED, NULL);
}
예제 #6
0
/**
 * input_keys_pressed:
 *
 * Grab an input sample for this frame.
 *
 * TODO: In case RARCH_BIND_LIST_END starts exceeding 64,
 * and you need a bitmask of more than 64 entries, reimplement
 * it to use something like rarch_bits_t.
 *
 * Returns: Input sample containg a mask of all pressed keys.
 */
retro_input_t input_keys_pressed(void)
{
   unsigned i, key;
   const struct retro_keybind *binds[MAX_USERS];
   retro_input_t             ret = 0;
   settings_t *settings          = config_get_ptr();

   for (i = 0; i < MAX_USERS; i++)
      binds[i] = settings->input.binds[i];

   if (!current_input || !current_input_data)
      return 0;

   input_driver_turbo_btns.count++;

   key = RARCH_ENABLE_HOTKEY;
   
   if (check_input_driver_block_hotkey(input_driver_ctl(RARCH_INPUT_CTL_KEY_PRESSED, &key)))
      input_driver_ctl(RARCH_INPUT_CTL_SET_LIBRETRO_INPUT_BLOCKED, NULL);
   else
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_LIBRETRO_INPUT_BLOCKED, NULL);

   for (i = 0; i < settings->input.max_users; i++)
   {
      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]);

      input_driver_turbo_btns.frame_enable[i] = 0;
   }

   if (!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL))
   {
      for (i = 0; i < settings->input.max_users; i++)
         input_driver_turbo_btns.frame_enable[i] = input_driver_state(binds,
               i, RETRO_DEVICE_JOYPAD, 0, RARCH_TURBO_ENABLE);
   }

   ret = input_driver_keys_pressed();

   for (i = 0; i < settings->input.max_users; i++)
   {
      input_pop_analog_dpad(settings->input.binds[i]);
      input_pop_analog_dpad(settings->input.autoconf_binds[i]);
   }

   return ret;
}
예제 #7
0
static bool runloop_cmd_get_state_menu_toggle_button_combo(
      settings_t *settings,
      retro_input_t input, retro_input_t old_input,
      retro_input_t trigger_input)
{
   switch (settings->input.menu_toggle_gamepad_combo)
   {
      case 0:
         return false;
      case 1:
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_DOWN))
            return false;
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_Y))
            return false;
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_L))
            return false;
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_R))
            return false;
         break;
      case 2:
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_L3))
            return false;
         if (!BIT64_GET(input, RETRO_DEVICE_ID_JOYPAD_R3))
            return false;
         break;
   }

   input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);
   return true;
}
예제 #8
0
static void menu_driver_toggle(bool latch)
{
   retro_keyboard_event_t *key_event          = NULL;
   retro_keyboard_event_t *frontend_key_event = NULL;
   settings_t                 *settings       = config_get_ptr();
   
   menu_driver_ctl(RARCH_MENU_CTL_TOGGLE, &latch);

   if (latch)
      menu_driver_ctl(RARCH_MENU_CTL_SET_ALIVE, NULL);
   else
      menu_driver_ctl(RARCH_MENU_CTL_UNSET_ALIVE, NULL);

   runloop_ctl(RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET, &frontend_key_event);
   runloop_ctl(RUNLOOP_CTL_KEY_EVENT_GET,          &key_event);

   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      bool refresh = false;
      menu_entries_ctl(MENU_ENTRIES_CTL_SET_REFRESH, &refresh);

      /* Menu should always run with vsync on. */
      event_cmd_ctl(EVENT_CMD_VIDEO_SET_BLOCKING_STATE, NULL);
      /* Stop all rumbling before entering the menu. */
      event_cmd_ctl(EVENT_CMD_RUMBLE_STOP, NULL);

      if (settings->menu.pause_libretro)
         event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL);

      /* Override keyboard callback to redirect to menu instead.
       * We'll use this later for something ... */

      if (key_event && frontend_key_event)
      {
         *frontend_key_event        = *key_event;
         *key_event                 = menu_input_key_event;

         runloop_ctl(RUNLOOP_CTL_SET_FRAME_TIME_LAST, NULL);
      }
   }
   else
   {
      if (!runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL))
         driver_ctl(RARCH_DRIVER_CTL_SET_NONBLOCK_STATE, NULL);

      if (settings && settings->menu.pause_libretro)
         event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);

      /* Prevent stray input from going to libretro core */
      input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);

      /* Restore libretro keyboard callback. */
      if (key_event && frontend_key_event)
         *key_event = *frontend_key_event;
   }
}
예제 #9
0
void input_driver_set(const input_driver_t **input, void **input_data)
{
   if (input && input_data)
   {
      *input      = current_input;
      *input_data = current_input_data;
   }
   
   input_driver_ctl(RARCH_INPUT_CTL_SET_OWN_DRIVER, NULL);
}
예제 #10
0
static void input_driver_command_init(void)
{
   settings_t *settings = config_get_ptr();

   if (!settings->stdin_cmd_enable && !settings->network_cmd_enable)
      return;

   if (settings->stdin_cmd_enable 
         && input_driver_ctl(RARCH_INPUT_CTL_GRAB_STDIN, NULL))
   {
      RARCH_WARN("stdin command interface is desired, but input driver has already claimed stdin.\n"
            "Cannot use this command interface.\n");
   }

   if (!(input_driver_command = rarch_cmd_new(settings->stdin_cmd_enable
               && !input_driver_ctl(RARCH_INPUT_CTL_GRAB_STDIN, NULL),
               settings->network_cmd_enable, settings->network_cmd_port)))
      RARCH_ERR("Failed to initialize command interface.\n");
}
예제 #11
0
static void menu_driver_toggle(bool latch)
{
   const menu_ctx_driver_t *menu_driver = menu_ctx_driver_get_ptr();
   settings_t                 *settings = config_get_ptr();
   global_t                   *global   = global_get_ptr();
   rarch_system_info_t          *system = rarch_system_info_get_ptr();

   if (menu_driver->toggle)
      menu_driver->toggle(latch);

   if (latch)
      menu_driver_ctl(RARCH_MENU_CTL_SET_ALIVE, NULL);
   else
      menu_driver_ctl(RARCH_MENU_CTL_UNSET_ALIVE, NULL);

   if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
   {
      menu_entries_set_refresh(false);

      /* Menu should always run with vsync on. */
      event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE);
      /* Stop all rumbling before entering the menu. */
      event_command(EVENT_CMD_RUMBLE_STOP);

      if (settings->menu.pause_libretro)
         event_command(EVENT_CMD_AUDIO_STOP);

      /* Override keyboard callback to redirect to menu instead.
       * We'll use this later for something ...
       * FIXME: This should probably be moved to menu_common somehow. */
      if (global)
      {
         global->frontend_key_event = system->key_event;
         system->key_event          = menu_input_key_event;

         runloop_ctl(RUNLOOP_CTL_SET_FRAME_TIME_LAST, NULL);
      }
   }
   else
   {
      if (!runloop_ctl(RUNLOOP_CTL_IS_SHUTDOWN, NULL))
         driver_set_nonblock_state();

      if (settings && settings->menu.pause_libretro)
         event_command(EVENT_CMD_AUDIO_START);

      /* Prevent stray input from going to libretro core */
      input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);

      /* Restore libretro keyboard callback. */
      if (global)
         system->key_event = global->frontend_key_event;
   }
}
예제 #12
0
static void menu_input_key_end_line(void)
{
   bool keyboard_display    = false;

   menu_input_ctl(MENU_INPUT_CTL_SET_KEYBOARD_DISPLAY, &keyboard_display);
   menu_input_ctl(MENU_INPUT_CTL_UNSET_KEYBOARD_LABEL, NULL);
   menu_input_ctl(MENU_INPUT_CTL_UNSET_KEYBOARD_LABEL_SETTING, NULL);

   /* Avoid triggering states on pressing return. */
   input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);
}
예제 #13
0
/**
 * check_input_driver_block_hotkey:
 * @enable_hotkey        : Is hotkey enable key enabled?
 *
 * Checks if 'hotkey enable' key is pressed.
 **/
static bool check_input_driver_block_hotkey(bool enable_hotkey)
{
   bool use_hotkey_enable;
   settings_t *settings          = config_get_ptr();
   const struct retro_keybind *bind =
      &settings->input.binds[0][RARCH_ENABLE_HOTKEY];
   const struct retro_keybind *autoconf_bind =
      &settings->input.autoconf_binds[0][RARCH_ENABLE_HOTKEY];
   bool kb_mapping_is_blocked = input_driver_ctl(
         RARCH_INPUT_CTL_KB_MAPPING_IS_BLOCKED, NULL);

   /* Don't block the check to RARCH_ENABLE_HOTKEY
    * unless we're really supposed to. */
   if (kb_mapping_is_blocked)
      input_driver_ctl(RARCH_INPUT_CTL_SET_HOTKEY_BLOCK, NULL);
   else
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_HOTKEY_BLOCK, NULL);

   /* If we haven't bound anything to this,
    * always allow hotkeys. */
   use_hotkey_enable          =
         (bind->key != RETROK_UNKNOWN)
      || (bind->joykey != NO_BTN)
      || (bind->joyaxis != AXIS_NONE)
      || (autoconf_bind->key != RETROK_UNKNOWN )
      || (autoconf_bind->joykey != NO_BTN)
      || (autoconf_bind->joyaxis != AXIS_NONE);

   if (kb_mapping_is_blocked || (use_hotkey_enable && !enable_hotkey))
      input_driver_ctl(RARCH_INPUT_CTL_SET_HOTKEY_BLOCK, NULL);
   else
      input_driver_ctl(RARCH_INPUT_CTL_UNSET_HOTKEY_BLOCK, NULL);

   /* If we hold ENABLE_HOTKEY button, block all libretro input to allow
    * hotkeys to be bound to same keys as RetroPad. */
   return (use_hotkey_enable && enable_hotkey);
}
예제 #14
0
파일: netplay.c 프로젝트: pponso1/RetroArch
/**
 * get_self_input_state:
 * @netplay              : pointer to netplay object
 *
 * Grab our own input state and send this over the network.
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
static bool get_self_input_state(netplay_t *netplay)
{
   uint32_t state          = 0;
   struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr];
   settings_t *settings    = config_get_ptr();

   if (!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL) && netplay->frame_count > 0)
   {
      unsigned i;

      /* First frame we always give zero input since relying on 
       * input from first frame screws up when we use -F 0. */
      retro_input_state_t cb = netplay->cbs.state_cb;
      for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
      {
         int16_t tmp = cb(settings->input.netplay_client_swap_input ?
               0 : !netplay->port,
               RETRO_DEVICE_JOYPAD, 0, i);
         state |= tmp ? 1 << i : 0;
      }

      for (i = RARCH_FIRST_CUSTOM_BIND; i < RARCH_FIRST_META_KEY; i++)
      {
         int16_t tmp = cb(settings->input.netplay_client_swap_input ?
               0 : !netplay->port,
               RETRO_DEVICE_ANALOG, 0, i);
         state |= tmp ? 1 << i : 0;
      }
   }

   memmove(netplay->packet_buffer, netplay->packet_buffer + 2,
         sizeof (netplay->packet_buffer) - 2 * sizeof(uint32_t));
   netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * 2] = htonl(netplay->frame_count); 
   netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * 2 + 1] = htonl(state);

   if (!send_chunk(netplay))
   {
      warn_hangup();
      netplay->has_connection = false;
      return false;
   }

   ptr->self_state = state;
   netplay->self_ptr = NEXT_PTR(netplay->self_ptr);
   return true;
}
예제 #15
0
static PyObject *py_read_input(PyObject *self, PyObject *args)
{
   unsigned user, key, i;
   const struct retro_keybind *py_binds[MAX_USERS];
   int16_t res = 0;
   settings_t *settings = config_get_ptr();
   
   for (i = 0; i < MAX_USERS; i++)
      py_binds[i] = settings->input.binds[i];
   
   (void)self;

   if (!PyArg_ParseTuple(args, "II", &user, &key))
      return NULL;

   if (user > MAX_USERS || user < 1 || key >= RARCH_FIRST_META_KEY)
      return NULL;

   if (!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL))
      res = input_driver_state(py_binds, user - 1, RETRO_DEVICE_JOYPAD, 0, key);
   return PyBool_FromLong(res);
}
예제 #16
0
/**
 * input_poll:
 *
 * Input polling callback function.
 **/
void input_poll(void)
{
   size_t i;
   settings_t *settings           = config_get_ptr();

   input_driver_ctl(RARCH_INPUT_CTL_POLL, NULL);

   for (i = 0; i < MAX_USERS; i++)
      libretro_input_binds[i] = settings->input.binds[i];

#ifdef HAVE_OVERLAY
   input_poll_overlay(settings->input.overlay_opacity);
#endif

#ifdef HAVE_COMMAND
   if (input_driver_command)
      rarch_cmd_poll(input_driver_command);
#endif

#ifdef HAVE_NETWORK_GAMEPAD
   if (input_driver_remote)
      rarch_remote_poll(input_driver_remote);
#endif
}
예제 #17
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;
}
예제 #18
0
static bool menu_input_key_bind_iterate(char *s, size_t len)
{
   struct menu_bind_state binds;
   bool               timed_out = false;
   menu_input_t *menu_input     = menu_input_get_ptr();
   int64_t current              = retro_get_time_usec();
   int timeout                  = 
      (menu_input->binds.timeout_end - current) / 1000000;

   if (timeout <= 0)
   {
      input_driver_keyboard_mapping_set_block(false);

      menu_input->binds.begin++;
      menu_input->binds.target++;
      menu_input->binds.timeout_end = retro_get_time_usec() +
         MENU_KEYBOARD_BIND_TIMEOUT_SECONDS * 1000000;
      timed_out = true;
   }

   snprintf(s, len,
         "[%s]\npress keyboard or joypad\n(timeout %d %s)",
         input_config_bind_map_get_desc(
         menu_input->binds.begin - MENU_SETTINGS_BIND_BEGIN),
         timeout,
         menu_hash_to_str(MENU_VALUE_SECONDS));

   /* binds.begin is updated in keyboard_press callback. */
   if (menu_input->binds.begin > menu_input->binds.last)
   {
      /* Avoid new binds triggering things right away. */
      input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);

      /* We won't be getting any key events, so just cancel early. */
      if (timed_out)
         input_keyboard_ctl(RARCH_INPUT_KEYBOARD_CTL_CANCEL_WAIT_KEYS, NULL);

      return true;
   }

   binds = menu_input->binds;

   input_driver_keyboard_mapping_set_block(true);
   menu_input_key_bind_poll_bind_state(&binds, bind_port, timed_out);

   if ((binds.skip && !menu_input->binds.skip) ||
         menu_input_key_bind_poll_find_trigger(&menu_input->binds, &binds))
   {
      input_driver_keyboard_mapping_set_block(false);

      /* Avoid new binds triggering things right away. */
      input_driver_ctl(RARCH_INPUT_CTL_SET_FLUSHING_INPUT, NULL);

      binds.begin++;

      if (binds.begin > binds.last)
      {
         input_keyboard_ctl(RARCH_INPUT_KEYBOARD_CTL_CANCEL_WAIT_KEYS, NULL);
         return true;
      }

      binds.target++;
      binds.timeout_end = retro_get_time_usec() +
         MENU_KEYBOARD_BIND_TIMEOUT_SECONDS * 1000000;
   }
   menu_input->binds = binds;

   return false;
}
예제 #19
0
/**
 * event_cmd_ctl:
 * @cmd                  : Event command index.
 *
 * Performs program event command with index @cmd.
 *
 * Returns: true (1) on success, otherwise false (0).
 **/
bool event_cmd_ctl(enum event_command cmd, void *data)
{
   unsigned i                = 0;
   bool boolean              = false;
   settings_t *settings      = config_get_ptr();
   rarch_system_info_t *info = NULL;

   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &info);

   (void)i;

   switch (cmd)
   {
      case EVENT_CMD_MENU_REFRESH:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_REFRESH, NULL);
#endif
         break;
      case EVENT_CMD_SET_PER_GAME_RESOLUTION:
#if defined(GEKKO)
         {
            unsigned width = 0, height = 0;

            event_cmd_ctl(EVENT_CMD_VIDEO_SET_ASPECT_RATIO, NULL);

            if (video_driver_get_video_output_size(&width, &height))
            {
               char msg[128] = {0};

               video_driver_set_video_mode(width, height, true);

               if (width == 0 || height == 0)
                  strlcpy(msg, "Resolution: DEFAULT", sizeof(msg));
               else
                  snprintf(msg, sizeof(msg),"Resolution: %dx%d",width, height);
               runloop_msg_queue_push(msg, 1, 100, true);
            }
         }
#endif
         break;
      case EVENT_CMD_LOAD_CONTENT_PERSIST:
#ifdef HAVE_DYNAMIC
         event_cmd_ctl(EVENT_CMD_LOAD_CORE, NULL);
#endif
         rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
         break;
#ifdef HAVE_FFMPEG
      case EVENT_CMD_LOAD_CONTENT_FFMPEG:
         rarch_ctl(RARCH_CTL_LOAD_CONTENT_FFMPEG, NULL);
         break;
#endif
      case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER:
         rarch_ctl(RARCH_CTL_LOAD_CONTENT_IMAGEVIEWER, NULL);
         break;
      case EVENT_CMD_LOAD_CONTENT:
         {
#ifdef HAVE_DYNAMIC
            event_cmd_ctl(EVENT_CMD_LOAD_CONTENT_PERSIST, NULL);
#else
            char *fullpath = NULL;
            runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);
            runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, settings->libretro);
            event_cmd_ctl(EVENT_CMD_EXEC, (void*)fullpath);
            event_cmd_ctl(EVENT_CMD_QUIT, NULL);
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE_DEINIT:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_DEINIT, NULL);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_PERSIST:
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL);
         {
#ifdef HAVE_MENU
            bool *ptr = NULL;
            struct retro_system_info *system = NULL;

            menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &system);

            if (menu_driver_ctl(RARCH_MENU_CTL_LOAD_NO_CONTENT_GET, &ptr))
            {
               core_info_ctx_find_t info_find;

#if defined(HAVE_DYNAMIC)
               if (!(*settings->libretro))
                  return false;

               libretro_get_system_info(settings->libretro, system,
                     ptr);
#endif
               info_find.path = settings->libretro;

               if (!core_info_ctl(CORE_INFO_CTL_LOAD, &info_find))
                  return false;
            }
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE:
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_PERSIST, NULL);
#ifndef HAVE_DYNAMIC
         event_cmd_ctl(EVENT_CMD_QUIT, NULL);
#endif
         break;
      case EVENT_CMD_LOAD_STATE:
         /* Immutable - disallow savestate load when
          * we absolutely cannot change game state. */
         if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;

#ifdef HAVE_NETPLAY
         if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
            return false;
#endif

#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         event_main_state(cmd);
         break;
      case EVENT_CMD_RESIZE_WINDOWED_SCALE:
         {
            unsigned idx = 0;
            unsigned *window_scale = NULL;

            runloop_ctl(RUNLOOP_CTL_GET_WINDOWED_SCALE, &window_scale);

            if (*window_scale == 0)
               return false;

            settings->video.scale = *window_scale;

            if (!settings->video.fullscreen)
               event_cmd_ctl(EVENT_CMD_REINIT, NULL);

            runloop_ctl(RUNLOOP_CTL_SET_WINDOWED_SCALE, &idx);
         }
         break;
      case EVENT_CMD_MENU_TOGGLE:
#ifdef HAVE_MENU
         if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
            rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
         else
            rarch_ctl(RARCH_CTL_MENU_RUNNING, NULL);
#endif
         break;
      case EVENT_CMD_CONTROLLERS_INIT:
         event_init_controllers();
         break;
      case EVENT_CMD_RESET:
         RARCH_LOG("%s.\n", msg_hash_to_str(MSG_RESET));
         runloop_msg_queue_push(msg_hash_to_str(MSG_RESET), 1, 120, true);

#ifdef HAVE_CHEEVOS
         cheevos_ctl(CHEEVOS_CTL_SET_CHEATS, NULL);
#endif
         core_ctl(CORE_CTL_RETRO_RESET, NULL);
         break;
      case EVENT_CMD_SAVE_STATE:
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         if (settings->savestate_auto_index)
            settings->state_slot++;

         event_main_state(cmd);
         break;
      case EVENT_CMD_SAVE_STATE_DECREMENT:
         /* Slot -1 is (auto) slot. */
         if (settings->state_slot >= 0)
            settings->state_slot--;
         break;
      case EVENT_CMD_SAVE_STATE_INCREMENT:
         settings->state_slot++;
         break;
      case EVENT_CMD_TAKE_SCREENSHOT:
         if (!take_screenshot())
            return false;
         break;
      case EVENT_CMD_UNLOAD_CORE:
         runloop_ctl(RUNLOOP_CTL_PREPARE_DUMMY, NULL);
         event_cmd_ctl(EVENT_CMD_LOAD_CORE_DEINIT, NULL);
         break;
      case EVENT_CMD_QUIT:
         rarch_ctl(RARCH_CTL_QUIT, NULL);
         break;
      case EVENT_CMD_CHEEVOS_HARDCORE_MODE_TOGGLE:
#ifdef HAVE_CHEEVOS
         cheevos_ctl(CHEEVOS_CTL_TOGGLE_HARDCORE_MODE, NULL);
#endif
         break;
      case EVENT_CMD_REINIT:
         {
            struct retro_hw_render_callback *hwr = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);

            if (hwr->cache_context)
               video_driver_ctl(
                     RARCH_DISPLAY_CTL_SET_VIDEO_CACHE_CONTEXT, NULL);
            else
               video_driver_ctl(
                     RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL);

            video_driver_ctl(
                  RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT_ACK, NULL);
            event_cmd_ctl(EVENT_CMD_RESET_CONTEXT, NULL);
            video_driver_ctl(
                  RARCH_DISPLAY_CTL_UNSET_VIDEO_CACHE_CONTEXT, NULL);

            /* Poll input to avoid possibly stale data to corrupt things. */
            input_driver_ctl(RARCH_INPUT_CTL_POLL, NULL);

#ifdef HAVE_MENU
            menu_display_ctl(
                  MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL);

            if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
               event_cmd_ctl(EVENT_CMD_VIDEO_SET_BLOCKING_STATE, NULL);
#endif
         }
         break;
      case EVENT_CMD_CHEATS_DEINIT:
         cheat_manager_state_free();
         break;
      case EVENT_CMD_CHEATS_INIT:
         event_cmd_ctl(EVENT_CMD_CHEATS_DEINIT, NULL);
         event_init_cheats();
         break;
      case EVENT_CMD_CHEATS_APPLY:
         cheat_manager_apply_cheats();
         break;
      case EVENT_CMD_REWIND_DEINIT:
#ifdef HAVE_NETPLAY
         if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
            return false;
#endif
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif

         state_manager_event_deinit();
         break;
      case EVENT_CMD_REWIND_INIT:
#ifdef HAVE_CHEEVOS
         if (settings->cheevos.hardcore_mode_enable)
            return false;
#endif
#ifdef HAVE_NETPLAY
         if (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
#endif
            init_rewind();
         break;
      case EVENT_CMD_REWIND_TOGGLE:
         if (settings->rewind_enable)
            event_cmd_ctl(EVENT_CMD_REWIND_INIT, NULL);
         else
            event_cmd_ctl(EVENT_CMD_REWIND_DEINIT, NULL);
         break;
      case EVENT_CMD_AUTOSAVE_DEINIT:
#ifdef HAVE_THREADS
         autosave_event_deinit();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_INIT:
         event_cmd_ctl(EVENT_CMD_AUTOSAVE_DEINIT, NULL);
#ifdef HAVE_THREADS
         autosave_event_init();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_STATE:
         event_save_auto_state();
         break;
      case EVENT_CMD_AUDIO_STOP:
         if (!audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL))
            return false;

         if (!audio_driver_ctl(RARCH_AUDIO_CTL_STOP, NULL))
            return false;
         break;
      case EVENT_CMD_AUDIO_START:
         if (audio_driver_ctl(RARCH_AUDIO_CTL_ALIVE, NULL))
            return false;

         if (!settings->audio.mute_enable && 
               !audio_driver_ctl(RARCH_AUDIO_CTL_START, NULL))
         {
            RARCH_ERR("Failed to start audio driver. "
                  "Will continue without audio.\n");
            audio_driver_ctl(RARCH_AUDIO_CTL_UNSET_ACTIVE, NULL);
         }
         break;
      case EVENT_CMD_AUDIO_MUTE_TOGGLE:
         {
            const char *msg = !settings->audio.mute_enable ?
               msg_hash_to_str(MSG_AUDIO_MUTED):
               msg_hash_to_str(MSG_AUDIO_UNMUTED);

            if (!audio_driver_ctl(RARCH_AUDIO_CTL_MUTE_TOGGLE, NULL))
            {
               RARCH_ERR("%s.\n",
                     msg_hash_to_str(MSG_FAILED_TO_UNMUTE_AUDIO));
               return false;
            }

            runloop_msg_queue_push(msg, 1, 180, true);
            RARCH_LOG("%s\n", msg);
         }
         break;
      case EVENT_CMD_OVERLAY_DEINIT:
#ifdef HAVE_OVERLAY
         input_overlay_free();
#endif
         break;
      case EVENT_CMD_OVERLAY_INIT:
         event_cmd_ctl(EVENT_CMD_OVERLAY_DEINIT, NULL);
#ifdef HAVE_OVERLAY
         input_overlay_init();
#endif
         break;
      case EVENT_CMD_OVERLAY_NEXT:
#ifdef HAVE_OVERLAY
         input_overlay_next(settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_DSP_FILTER_DEINIT:
         audio_driver_dsp_filter_free();
         break;
      case EVENT_CMD_DSP_FILTER_INIT:
         event_cmd_ctl(EVENT_CMD_DSP_FILTER_DEINIT, NULL);
         if (!*settings->audio.dsp_plugin)
            break;
         audio_driver_dsp_filter_init(settings->audio.dsp_plugin);
         break;
      case EVENT_CMD_GPU_RECORD_DEINIT:
         video_driver_ctl(RARCH_DISPLAY_CTL_GPU_RECORD_DEINIT, NULL);
         break;
      case EVENT_CMD_RECORD_DEINIT:
         if (!recording_deinit())
            return false;
         break;
      case EVENT_CMD_RECORD_INIT:
         event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL);
         if (!recording_init())
            return false;
         break;
      case EVENT_CMD_HISTORY_DEINIT:
         if (g_defaults.history)
         {
            content_playlist_write_file(g_defaults.history);
            content_playlist_free(g_defaults.history);
         }
         g_defaults.history = NULL;
         break;
      case EVENT_CMD_HISTORY_INIT:
         event_cmd_ctl(EVENT_CMD_HISTORY_DEINIT, NULL);
         if (!settings->history_list_enable)
            return false;
         RARCH_LOG("%s: [%s].\n",
               msg_hash_to_str(MSG_LOADING_HISTORY_FILE),
               settings->content_history_path);
         g_defaults.history = content_playlist_init(
               settings->content_history_path,
               settings->content_history_size);
         break;
      case EVENT_CMD_CORE_INFO_DEINIT:
         core_info_ctl(CORE_INFO_CTL_LIST_DEINIT, NULL);
         break;
      case EVENT_CMD_CORE_INFO_INIT:
         event_cmd_ctl(EVENT_CMD_CORE_INFO_DEINIT, NULL);

         if (*settings->libretro_directory)
            core_info_ctl(CORE_INFO_CTL_LIST_INIT, NULL);
         break;
      case EVENT_CMD_CORE_DEINIT:
         {
            struct retro_hw_render_callback *hwr = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);
            event_deinit_core(true);

            if (hwr)
               memset(hwr, 0, sizeof(*hwr));

            break;
         }
      case EVENT_CMD_CORE_INIT:
         if (!event_init_core(data))
            return false;
         break;
      case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES:
         video_driver_ctl(RARCH_DISPLAY_CTL_APPLY_STATE_CHANGES, NULL);
         break;
      case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_VIDEO_SET_BLOCKING_STATE:
         video_driver_ctl(RARCH_DISPLAY_CTL_SET_NONBLOCK_STATE, &boolean);
         break;
      case EVENT_CMD_VIDEO_SET_ASPECT_RATIO:
         video_driver_ctl(RARCH_DISPLAY_CTL_SET_ASPECT_RATIO, NULL);
         break;
      case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_AUDIO_SET_BLOCKING_STATE:
         audio_driver_set_nonblocking_state(boolean);
         break;
      case EVENT_CMD_OVERLAY_SET_SCALE_FACTOR:
#ifdef HAVE_OVERLAY
         input_overlay_set_scale_factor(settings->input.overlay_scale);
#endif
         break;
      case EVENT_CMD_OVERLAY_SET_ALPHA_MOD:
#ifdef HAVE_OVERLAY
         input_overlay_set_alpha_mod(settings->input.overlay_opacity);
#endif
         break;
      case EVENT_CMD_AUDIO_REINIT:
         {
            int flags = DRIVER_AUDIO;
            driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);
            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
         }
         break;
      case EVENT_CMD_RESET_CONTEXT:
         {
            /* RARCH_DRIVER_CTL_UNINIT clears the callback struct so we
             * need to make sure to keep a copy */
            struct retro_hw_render_callback *hwr = NULL;
            struct retro_hw_render_callback hwr_copy;
            int flags = DRIVERS_CMD_ALL;

            video_driver_ctl(RARCH_DISPLAY_CTL_HW_CONTEXT_GET, &hwr);

            memcpy(&hwr_copy, hwr, sizeof(hwr_copy));

            driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);

            memcpy(hwr, &hwr_copy, sizeof(*hwr));

            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
         }
         break;
      case EVENT_CMD_QUIT_RETROARCH:
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         break;
      case EVENT_CMD_SHUTDOWN:
#if defined(__linux__) && !defined(ANDROID)
         runloop_msg_queue_push("Shutting down...", 1, 180, true);
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         system("shutdown -P now");
#endif
         break;
      case EVENT_CMD_REBOOT:
#if defined(__linux__) && !defined(ANDROID)
         runloop_msg_queue_push("Rebooting...", 1, 180, true);
         rarch_ctl(RARCH_CTL_FORCE_QUIT, NULL);
         system("shutdown -r now");
#endif
         break;
      case EVENT_CMD_RESUME:
         rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
         if (ui_companion_is_on_foreground())
            ui_companion_driver_toggle();
         break;
      case EVENT_CMD_RESTART_RETROARCH:
         if (!frontend_driver_set_fork(FRONTEND_FORK_RESTART))
            return false;
         break;
      case EVENT_CMD_MENU_SAVE_CURRENT_CONFIG:
         event_save_current_config();
         break;
      case EVENT_CMD_MENU_SAVE_CONFIG:
         if (!event_save_core_config())
            return false;
         break;
      case EVENT_CMD_SHADERS_APPLY_CHANGES:
#ifdef HAVE_MENU
         menu_shader_manager_apply_changes();
#endif
         break;
      case EVENT_CMD_PAUSE_CHECKS:
         if (runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL))
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED));
            event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL);

            if (settings->video.black_frame_insertion)
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);
         }
         else
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED));
            event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
         break;
      case EVENT_CMD_PAUSE_TOGGLE:
         boolean = runloop_ctl(RUNLOOP_CTL_IS_PAUSED,  NULL);
         boolean = !boolean;
         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_UNPAUSE:
         boolean = false;

         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_PAUSE:
         boolean = true;

         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_cmd_ctl(EVENT_CMD_PAUSE_CHECKS, NULL);
         break;
      case EVENT_CMD_MENU_PAUSE_LIBRETRO:
#ifdef HAVE_MENU
         if (menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL))
         {
            if (settings->menu.pause_libretro)
               event_cmd_ctl(EVENT_CMD_AUDIO_STOP, NULL);
            else
               event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
         else
         {
            if (settings->menu.pause_libretro)
               event_cmd_ctl(EVENT_CMD_AUDIO_START, NULL);
         }
#endif
         break;
      case EVENT_CMD_SHADER_DIR_DEINIT:
         runloop_ctl(RUNLOOP_CTL_SHADER_DIR_DEINIT, NULL);
         break;
      case EVENT_CMD_SHADER_DIR_INIT:
         event_cmd_ctl(EVENT_CMD_SHADER_DIR_DEINIT, NULL);

         if (!runloop_ctl(RUNLOOP_CTL_SHADER_DIR_INIT, NULL))
            return false;
         break;
      case EVENT_CMD_SAVEFILES:
         {
            global_t  *global         = global_get_ptr();
            if (!global->savefiles || !global->sram.use)
               return false;

            for (i = 0; i < global->savefiles->size; i++)
            {
               ram_type_t ram;
               ram.type    = global->savefiles->elems[i].attr.i;
               ram.path    = global->savefiles->elems[i].data;

               RARCH_LOG("%s #%u %s \"%s\".\n",
                     msg_hash_to_str(MSG_SAVING_RAM_TYPE),
                     ram.type,
                     msg_hash_to_str(MSG_TO),
                     ram.path);
               content_ctl(CONTENT_CTL_SAVE_RAM_FILE, &ram);
            }
         }
         return true;
      case EVENT_CMD_SAVEFILES_DEINIT:
         {
            global_t  *global         = global_get_ptr();
            if (!global)
               break;

            if (global->savefiles)
               string_list_free(global->savefiles);
            global->savefiles = NULL;
         }
         break;
      case EVENT_CMD_SAVEFILES_INIT:
         {
            global_t  *global         = global_get_ptr();
            global->sram.use = global->sram.use && !global->sram.save_disable;
#ifdef HAVE_NETPLAY
            global->sram.use = global->sram.use && 
               (!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)
                || !global->netplay.is_client);
#endif

            if (!global->sram.use)
               RARCH_LOG("%s\n",
                     msg_hash_to_str(MSG_SRAM_WILL_NOT_BE_SAVED));

            if (global->sram.use)
               event_cmd_ctl(EVENT_CMD_AUTOSAVE_INIT, NULL);
         }
         break;
      case EVENT_CMD_BSV_MOVIE_DEINIT:
         bsv_movie_ctl(BSV_MOVIE_CTL_DEINIT, NULL);
         break;
      case EVENT_CMD_BSV_MOVIE_INIT:
         event_cmd_ctl(EVENT_CMD_BSV_MOVIE_DEINIT, NULL);
         bsv_movie_ctl(BSV_MOVIE_CTL_INIT, NULL);
         break;
      case EVENT_CMD_NETPLAY_DEINIT:
#ifdef HAVE_NETPLAY
         deinit_netplay();
#endif
         break;
      case EVENT_CMD_NETWORK_DEINIT:
#ifdef HAVE_NETWORKING
         network_deinit();
#endif
         break;
      case EVENT_CMD_NETWORK_INIT:
#ifdef HAVE_NETWORKING
         network_init();
#endif
         break;
      case EVENT_CMD_NETPLAY_INIT:
         event_cmd_ctl(EVENT_CMD_NETPLAY_DEINIT, NULL);
#ifdef HAVE_NETPLAY
         if (!init_netplay())
            return false;
#endif
         break;
      case EVENT_CMD_NETPLAY_FLIP_PLAYERS:
#ifdef HAVE_NETPLAY
         netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, NULL);
#endif
         break;
      case EVENT_CMD_FULLSCREEN_TOGGLE:
         if (!video_driver_ctl(RARCH_DISPLAY_CTL_HAS_WINDOWED, NULL))
            return false;

         /* If we go fullscreen we drop all drivers and
          * reinitialize to be safe. */
         settings->video.fullscreen = !settings->video.fullscreen;
         event_cmd_ctl(EVENT_CMD_REINIT, NULL);
         break;
      case EVENT_CMD_COMMAND_DEINIT:
         input_driver_ctl(RARCH_INPUT_CTL_COMMAND_DEINIT, NULL);
         break;
      case EVENT_CMD_COMMAND_INIT:
         event_cmd_ctl(EVENT_CMD_COMMAND_DEINIT, NULL);
         input_driver_ctl(RARCH_INPUT_CTL_COMMAND_INIT, NULL);
         break;
      case EVENT_CMD_REMOTE_DEINIT:
         input_driver_ctl(RARCH_INPUT_CTL_REMOTE_DEINIT, NULL);
         break;
      case EVENT_CMD_REMOTE_INIT:
         event_cmd_ctl(EVENT_CMD_REMOTE_DEINIT, NULL);
         input_driver_ctl(RARCH_INPUT_CTL_REMOTE_INIT, NULL);
         break;
      case EVENT_CMD_TEMPORARY_CONTENT_DEINIT:
         content_ctl(CONTENT_CTL_DEINIT, NULL);
         break;
      case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT:
         {
            global_t  *global         = global_get_ptr();
            if (!global)
               break;

            if (global->subsystem_fullpaths)
               string_list_free(global->subsystem_fullpaths);
            global->subsystem_fullpaths = NULL;
         }
         break;
      case EVENT_CMD_LOG_FILE_DEINIT:
         retro_main_log_file_deinit();
         break;
      case EVENT_CMD_DISK_APPEND_IMAGE:
         {
            const char *path = (const char*)data;
            if (string_is_empty(path))
               return false;
            return event_disk_control_append_image(path);
         }
      case EVENT_CMD_DISK_EJECT_TOGGLE:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (control)
            {
               bool new_state = !control->get_eject_state();
               event_disk_control_set_eject(new_state, true);
            }
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_DISK_NEXT:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_next(control);
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_DISK_PREV:
         if (info && info->disk_control_cb.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control_cb;

            if (!control)
               return false;

            if (!control->get_eject_state())
               return false;

            event_check_disk_prev(control);
         }
         else
            runloop_msg_queue_push(
                  msg_hash_to_str(MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS),
                  1, 120, true);
         break;
      case EVENT_CMD_RUMBLE_STOP:
         for (i = 0; i < MAX_USERS; i++)
         {
            input_driver_set_rumble_state(i, RETRO_RUMBLE_STRONG, 0);
            input_driver_set_rumble_state(i, RETRO_RUMBLE_WEAK, 0);
         }
         break;
      case EVENT_CMD_GRAB_MOUSE_TOGGLE:
         {
            bool ret = false;
            static bool grab_mouse_state  = false;

            grab_mouse_state = !grab_mouse_state;

            if (grab_mouse_state)
               ret = input_driver_ctl(RARCH_INPUT_CTL_GRAB_MOUSE, NULL);
            else
               ret = input_driver_ctl(RARCH_INPUT_CTL_UNGRAB_MOUSE, NULL);

            if (!ret)
               return false;

            RARCH_LOG("%s: %s.\n",
                  msg_hash_to_str(MSG_GRAB_MOUSE_STATE),
                  grab_mouse_state ? "yes" : "no");

            if (grab_mouse_state)
               video_driver_ctl(RARCH_DISPLAY_CTL_HIDE_MOUSE, NULL);
            else
               video_driver_ctl(RARCH_DISPLAY_CTL_SHOW_MOUSE, NULL);
         }
         break;
      case EVENT_CMD_PERFCNT_REPORT_FRONTEND_LOG:
         rarch_perf_log();
         break;
      case EVENT_CMD_VOLUME_UP:
         event_set_volume(0.5f);
         break;
      case EVENT_CMD_VOLUME_DOWN:
         event_set_volume(-0.5f);
         break;
      case EVENT_CMD_SET_FRAME_LIMIT:
         runloop_ctl(RUNLOOP_CTL_SET_FRAME_LIMIT, NULL);
         break;
      case EVENT_CMD_EXEC:
         return event_cmd_exec(data);
      case EVENT_CMD_NONE:
      default:
         return false;
   }

   return true;
}
예제 #20
0
/**
 * get_self_input_state:
 * @netplay              : pointer to netplay object
 *
 * Grab our own input state and send this over the network.
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
static bool get_self_input_state(netplay_t *netplay)
{
    uint32_t state[UDP_WORDS_PER_FRAME - 1] = {0};
    struct delta_frame *ptr                 = &netplay->buffer[netplay->self_ptr];
    settings_t *settings                    = config_get_ptr();

    if (!input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL)
            && netplay->frame_count > 0)
    {
        unsigned i;

        /* First frame we always give zero input since relying on
         * input from first frame screws up when we use -F 0. */
        retro_input_state_t cb = netplay->cbs.state_cb;
        for (i = 0; i < RARCH_FIRST_CUSTOM_BIND; i++)
        {
            int16_t tmp = cb(settings->input.netplay_client_swap_input ?
                             0 : !netplay->port,
                             RETRO_DEVICE_JOYPAD, 0, i);
            state[0] |= tmp ? 1 << i : 0;
        }

        for (i = 0; i < 2; i++)
        {
            int16_t tmp_x = cb(settings->input.netplay_client_swap_input ?
                               0 : !netplay->port,
                               RETRO_DEVICE_ANALOG, i, 0);
            int16_t tmp_y = cb(settings->input.netplay_client_swap_input ?
                               0 : !netplay->port,
                               RETRO_DEVICE_ANALOG, i, 1);
            state[1 + i] = (uint16_t)tmp_x | (((uint16_t)tmp_y) << 16);
        }
    }

    /* Here we construct the payload format:
     * frame {
     *    uint32_t frame_number
     *    uint32_t RETRO_DEVICE_JOYPAD state (top 16 bits zero)
     *    uint32_t ANALOG state[0]
     *    uint32_t ANALOG state[1]
     * }
     *
     * payload {
     *    ; To compat packet losses, send input in a sliding window
     *    frame redundancy_frames[UDP_FRAME_PACKETS];
     * }
     */
    memmove(netplay->packet_buffer, netplay->packet_buffer + UDP_WORDS_PER_FRAME,
            sizeof (netplay->packet_buffer) - UDP_WORDS_PER_FRAME * sizeof(uint32_t));
    netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME] = htonl(netplay->frame_count);
    netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 1] = htonl(state[0]);
    netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 2] = htonl(state[1]);
    netplay->packet_buffer[(UDP_FRAME_PACKETS - 1) * UDP_WORDS_PER_FRAME + 3] = htonl(state[2]);

    if (!send_chunk(netplay))
    {
        warn_hangup();
        netplay->has_connection = false;
        return false;
    }

    memcpy(ptr->self_state, state, sizeof(state));
    netplay->self_ptr = NEXT_PTR(netplay->self_ptr);
    return true;
}
예제 #21
0
/**
 * input_state:
 * @port                 : user number.
 * @device               : device identifier of user.
 * @idx                  : index value of user.
 * @id                   : identifier of key pressed by user.
 *
 * Input state callback function.
 *
 * Returns: Non-zero if the given key (identified by @id) was pressed by the user
 * (assigned to @port).
 **/
int16_t input_state(unsigned port, unsigned device,
      unsigned idx, unsigned id)
{
   int16_t res                     = 0;
   settings_t *settings            = config_get_ptr();
   

   device &= RETRO_DEVICE_MASK;

   if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_ON, NULL))
   {
      int16_t ret;
      if (bsv_movie_ctl(BSV_MOVIE_CTL_GET_INPUT, &ret))
         return ret;

      bsv_movie_ctl(BSV_MOVIE_CTL_SET_END, NULL);
   }

   if (settings->input.remap_binds_enable)
      input_remapping_state(port, &device, &idx, &id);

   if (!input_driver_ctl(RARCH_INPUT_CTL_IS_FLUSHING_INPUT, NULL) 
         && !input_driver_ctl(RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED, NULL))
   {
      if (((id < RARCH_FIRST_META_KEY) || (device == RETRO_DEVICE_KEYBOARD)))
         res = current_input->input_state(
               current_input_data, libretro_input_binds, port, device, idx, id);

#ifdef HAVE_OVERLAY
      input_state_overlay(&res, port, device, idx, id);
#endif

#ifdef HAVE_NETWORK_GAMEPAD
      input_state_remote(&res, port, device, idx, id);
#endif
   }

   /* Don't allow turbo for D-pad. */
   if (device == RETRO_DEVICE_JOYPAD && (id < RETRO_DEVICE_ID_JOYPAD_UP ||
            id > RETRO_DEVICE_ID_JOYPAD_RIGHT))
   {
      /*
       * Apply turbo button if activated.
       *
       * If turbo button is held, all buttons pressed except
       * for D-pad will go into a turbo mode. Until the button is
       * released again, the input state will be modulated by a 
       * periodic pulse defined by the configured duty cycle. 
       */
      if (res && input_driver_turbo_btns.frame_enable[port])
         input_driver_turbo_btns.enable[port] |= (1 << id);
      else if (!res)
         input_driver_turbo_btns.enable[port] &= ~(1 << id);

      if (input_driver_turbo_btns.enable[port] & (1 << id))
      {
         /* if turbo button is enabled for this key ID */
         res = res && ((input_driver_turbo_btns.count % settings->input.turbo_period)
               < settings->input.turbo_duty_cycle);
      }
   }

   if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_OFF, NULL))
      bsv_movie_ctl(BSV_MOVIE_CTL_SET_INPUT, &res);

   return res;
}
예제 #22
0
/**
 * rarch_environment_cb:
 * @cmd                          : Identifier of command.
 * @data                         : Pointer to data.
 *
 * Environment callback function implementation.
 *
 * Returns: true (1) if environment callback command could
 * be performed, otherwise false (0).
 **/
bool rarch_environment_cb(unsigned cmd, void *data)
{
   unsigned p;
   settings_t         *settings = config_get_ptr();
   global_t         *global     = global_get_ptr();
   rarch_system_info_t *system  = NULL;
   
   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);

   if (ignore_environment_cb)
      return false;

   switch (cmd)
   {
      case RETRO_ENVIRONMENT_GET_OVERSCAN:
         *(bool*)data = !settings->video.crop_overscan;
         RARCH_LOG("Environ GET_OVERSCAN: %u\n",
               (unsigned)!settings->video.crop_overscan);
         break;

      case RETRO_ENVIRONMENT_GET_CAN_DUPE:
         *(bool*)data = true;
         RARCH_LOG("Environ GET_CAN_DUPE: true\n");
         break;

      case RETRO_ENVIRONMENT_GET_VARIABLE:
         if (!runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_GET, data))
         {
            struct retro_variable *var = (struct retro_variable*)data;

            if (var) {
               RARCH_LOG("Environ GET_VARIABLE %s: not implemented.\n", var->key);
               var->value = NULL;
            }
         }

         break;

      case RETRO_ENVIRONMENT_GET_VARIABLE_UPDATE:
         *(bool*)data = runloop_ctl(RUNLOOP_CTL_IS_CORE_OPTION_UPDATED, NULL);
         break;

      case RETRO_ENVIRONMENT_SET_VARIABLES:
         RARCH_LOG("Environ SET_VARIABLES.\n");

         runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_DEINIT, NULL);
         runloop_ctl(RUNLOOP_CTL_CORE_OPTIONS_INIT,   data);

         break;

      case RETRO_ENVIRONMENT_SET_MESSAGE:
      {
         const struct retro_message *msg = (const struct retro_message*)data;
         RARCH_LOG("Environ SET_MESSAGE: %s\n", msg->msg);
         runloop_msg_queue_push(msg->msg, 1, msg->frames, true);
         break;
      }

      case RETRO_ENVIRONMENT_SET_ROTATION:
      {
         unsigned rotation = *(const unsigned*)data;
         RARCH_LOG("Environ SET_ROTATION: %u\n", rotation);
         if (!settings->video.allow_rotate)
            break;

         system->rotation = rotation;

         if (!video_driver_set_rotation(rotation))
            return false;
         break;
      }

      case RETRO_ENVIRONMENT_SHUTDOWN:
         RARCH_LOG("Environ SHUTDOWN.\n");
         runloop_ctl(RUNLOOP_CTL_SET_SHUTDOWN,      NULL);
         runloop_ctl(RUNLOOP_CTL_SET_CORE_SHUTDOWN, NULL);
         break;

      case RETRO_ENVIRONMENT_SET_PERFORMANCE_LEVEL:
         system->performance_level = *(const unsigned*)data;
         RARCH_LOG("Environ PERFORMANCE_LEVEL: %u.\n",
               system->performance_level);
         break;

      case RETRO_ENVIRONMENT_GET_SYSTEM_DIRECTORY:
         if (string_is_empty(settings->system_directory))
         {
            char *fullpath = NULL;
            runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);

            RARCH_WARN("SYSTEM DIR is empty, assume CONTENT DIR %s\n", fullpath);
            fill_pathname_basedir(global->dir.systemdir, fullpath,
                  sizeof(global->dir.systemdir));

            *(const char**)data = global->dir.systemdir;
            RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n",
               global->dir.systemdir);
         }
         else
         {
            *(const char**)data = settings->system_directory;
            RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n",
               settings->system_directory);
         }

         break;

      case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
         *(const char**)data = rarch_get_current_savefile_dir();
         break;

      case RETRO_ENVIRONMENT_GET_USERNAME:
         *(const char**)data = *settings->username ?
            settings->username : NULL;
         RARCH_LOG("Environ GET_USERNAME: \"%s\".\n",
               settings->username);
         break;

      case RETRO_ENVIRONMENT_GET_LANGUAGE:
         *(unsigned *)data = settings->user_language;
         RARCH_LOG("Environ GET_LANGUAGE: \"%u\".\n",
               settings->user_language);
         break;

      case RETRO_ENVIRONMENT_SET_PIXEL_FORMAT:
      {
         enum retro_pixel_format pix_fmt =
            *(const enum retro_pixel_format*)data;

         switch (pix_fmt)
         {
            case RETRO_PIXEL_FORMAT_0RGB1555:
               RARCH_LOG("Environ SET_PIXEL_FORMAT: 0RGB1555.\n");
               break;

            case RETRO_PIXEL_FORMAT_RGB565:
               RARCH_LOG("Environ SET_PIXEL_FORMAT: RGB565.\n");
               break;
            case RETRO_PIXEL_FORMAT_XRGB8888:
               RARCH_LOG("Environ SET_PIXEL_FORMAT: XRGB8888.\n");
               break;
            default:
               return false;
         }

         video_driver_set_pixel_format(pix_fmt);
         break;
      }

      case RETRO_ENVIRONMENT_SET_INPUT_DESCRIPTORS:
      {
         unsigned retro_id, retro_port;
         const struct retro_input_descriptor *desc = NULL;

         static const char *libretro_btn_desc[] = {
            "B (bottom)", "Y (left)", "Select", "Start",
            "D-Pad Up", "D-Pad Down", "D-Pad Left", "D-Pad Right",
            "A (right)", "X (up)",
            "L", "R", "L2", "R2", "L3", "R3",
         };

         memset(system->input_desc_btn, 0,
               sizeof(system->input_desc_btn));

         desc = (const struct retro_input_descriptor*)data;

         for (; desc->description; desc++)
         {
            retro_port = desc->port;
            retro_id   = desc->id;

            if (desc->port >= MAX_USERS)
               continue;

            /* Ignore all others for now. */
            if (desc->device != RETRO_DEVICE_JOYPAD  &&
                  desc->device != RETRO_DEVICE_ANALOG)
               continue;

            if (desc->id >= RARCH_FIRST_CUSTOM_BIND)
               continue;

            if (desc->device == RETRO_DEVICE_ANALOG)
            {
               switch (retro_id)
               {
                  case RETRO_DEVICE_ID_ANALOG_X:
                     switch (desc->index)
                     {
                        case RETRO_DEVICE_INDEX_ANALOG_LEFT:
                           system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_PLUS] = desc->description;
                           system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_X_MINUS] = desc->description;
                           break;
                        case RETRO_DEVICE_INDEX_ANALOG_RIGHT:
                           system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_PLUS] = desc->description;
                           system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_X_MINUS] = desc->description;
                           break;
                     }
                     break;
                  case RETRO_DEVICE_ID_ANALOG_Y:
                     switch (desc->index)
                     {
                        case RETRO_DEVICE_INDEX_ANALOG_LEFT:
                           system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_PLUS] = desc->description;
                           system->input_desc_btn[retro_port][RARCH_ANALOG_LEFT_Y_MINUS] = desc->description;
                           break;
                        case RETRO_DEVICE_INDEX_ANALOG_RIGHT:
                           system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_PLUS] = desc->description;
                           system->input_desc_btn[retro_port][RARCH_ANALOG_RIGHT_Y_MINUS] = desc->description;
                           break;
                     }
                     break;
               }
            }
            else
               system->input_desc_btn[retro_port][retro_id] = desc->description;
         }

         RARCH_LOG("Environ SET_INPUT_DESCRIPTORS:\n");
         for (p = 0; p < settings->input.max_users; p++)
         {
            for (retro_id = 0; retro_id < RARCH_FIRST_CUSTOM_BIND; retro_id++)
            {
               const char *description = system->input_desc_btn[p][retro_id];

               if (!description)
                  continue;

               RARCH_LOG("\tRetroPad, User %u, Button \"%s\" => \"%s\"\n",
                     p + 1, libretro_btn_desc[retro_id], description);
            }
         }

         global->has_set.input_descriptors = true;

         break;
      }

      case RETRO_ENVIRONMENT_SET_KEYBOARD_CALLBACK:
      {
         retro_keyboard_event_t *frontend_key_event = NULL;
         retro_keyboard_event_t *key_event          = NULL;
         const struct retro_keyboard_callback *info =
            (const struct retro_keyboard_callback*)data;

         runloop_ctl(RUNLOOP_CTL_FRONTEND_KEY_EVENT_GET, &frontend_key_event);
         runloop_ctl(RUNLOOP_CTL_KEY_EVENT_GET, &key_event);

         RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
         if (key_event)
            *key_event                  = info->callback;
         if (frontend_key_event)
            *frontend_key_event         = *key_event;
         break;
      }

      case RETRO_ENVIRONMENT_SET_DISK_CONTROL_INTERFACE:
         RARCH_LOG("Environ SET_DISK_CONTROL_INTERFACE.\n");
         system->disk_control =
            *(const struct retro_disk_control_callback*)data;
         break;

      case RETRO_ENVIRONMENT_SET_HW_RENDER:
      case RETRO_ENVIRONMENT_SET_HW_RENDER | RETRO_ENVIRONMENT_EXPERIMENTAL:
      {
         struct retro_hw_render_callback *hw_render = video_driver_callback();
         struct retro_hw_render_callback *cb =
            (struct retro_hw_render_callback*)data;

         RARCH_LOG("Environ SET_HW_RENDER.\n");

         switch (cb->context_type)
         {
            case RETRO_HW_CONTEXT_NONE:
               RARCH_LOG("Requesting no HW context.\n");
               break;

#if defined(HAVE_OPENGLES2)
            case RETRO_HW_CONTEXT_OPENGLES2:
#if defined(HAVE_OPENGLES3)
            case RETRO_HW_CONTEXT_OPENGLES3:
#endif
               RARCH_LOG("Requesting OpenGLES%u context.\n",
                     cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3);
               break;

#if defined(HAVE_OPENGLES3)
            case RETRO_HW_CONTEXT_OPENGLES_VERSION:
               RARCH_LOG("Requesting OpenGLES%u.%u context.\n",
                     cb->version_major, cb->version_minor);
               break;
#endif

            case RETRO_HW_CONTEXT_OPENGL:
            case RETRO_HW_CONTEXT_OPENGL_CORE:
               RARCH_ERR("Requesting OpenGL context, but RetroArch is compiled against OpenGLES2. Cannot use HW context.\n");
               return false;
#elif defined(HAVE_OPENGL)
            case RETRO_HW_CONTEXT_OPENGLES2:
            case RETRO_HW_CONTEXT_OPENGLES3:
               RARCH_ERR("Requesting OpenGLES%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n",
                     cb->context_type == RETRO_HW_CONTEXT_OPENGLES2 ? 2 : 3);
               return false;

            case RETRO_HW_CONTEXT_OPENGLES_VERSION:
               RARCH_ERR("Requesting OpenGLES%u.%u context, but RetroArch is compiled against OpenGL. Cannot use HW context.\n",
                     cb->version_major, cb->version_minor);
               return false;

            case RETRO_HW_CONTEXT_OPENGL:
               RARCH_LOG("Requesting OpenGL context.\n");
               break;

            case RETRO_HW_CONTEXT_OPENGL_CORE:
               RARCH_LOG("Requesting core OpenGL context (%u.%u).\n",
                     cb->version_major, cb->version_minor);
               break;
#endif

            default:
               RARCH_LOG("Requesting unknown context.\n");
               return false;
         }
         cb->get_current_framebuffer = video_driver_get_current_framebuffer;
         cb->get_proc_address        = video_driver_get_proc_address;

         if (cmd & RETRO_ENVIRONMENT_EXPERIMENTAL) /* Old ABI. Don't copy garbage. */
            memcpy(hw_render,
                  cb, offsetof(struct retro_hw_render_callback, stencil));
         else
            memcpy(hw_render, cb, sizeof(*cb));
         break;
      }

      case RETRO_ENVIRONMENT_SET_SUPPORT_NO_GAME:
      {
         bool state = *(const bool*)data;
         RARCH_LOG("Environ SET_SUPPORT_NO_GAME: %s.\n", state ? "yes" : "no");
         system->no_content = state;
         break;
      }

      case RETRO_ENVIRONMENT_GET_LIBRETRO_PATH:
      {
         const char **path = (const char**)data;
         *path = NULL;
#ifdef HAVE_DYNAMIC
         *path = settings->libretro;
#endif
         break;
      }

      /* FIXME - PS3 audio driver needs to be fixed so that threaded
       * audio works correctly (audio is already on a thread for PS3
       * audio driver so that's probably the problem) */
#if defined(HAVE_THREADS) && !defined(__CELLOS_LV2__)
      case RETRO_ENVIRONMENT_SET_AUDIO_CALLBACK:
      {
         const struct retro_audio_callback *info =
            (const struct retro_audio_callback*)data;
         RARCH_LOG("Environ SET_AUDIO_CALLBACK.\n");

         if (recording_driver_get_data_ptr()) /* A/V sync is a must. */
            return false;

#ifdef HAVE_NETPLAY
         if (global->netplay.enable)
            return false;
#endif

         audio_driver_set_callback(info);
         break;
      }
#endif

      case RETRO_ENVIRONMENT_SET_FRAME_TIME_CALLBACK:
      {
         const struct retro_frame_time_callback *info =
            (const struct retro_frame_time_callback*)data;

         RARCH_LOG("Environ SET_FRAME_TIME_CALLBACK.\n");

#ifdef HAVE_NETPLAY
         /* retro_run() will be called in very strange and
          * mysterious ways, have to disable it. */
         if (global->netplay.enable)
            return false;
#endif

         system->frame_time = *info;
         break;
      }

      case RETRO_ENVIRONMENT_GET_RUMBLE_INTERFACE:
      {
         struct retro_rumble_interface *iface =
            (struct retro_rumble_interface*)data;

         RARCH_LOG("Environ GET_RUMBLE_INTERFACE.\n");
         iface->set_rumble_state = input_driver_set_rumble_state;
         break;
      }

      case RETRO_ENVIRONMENT_GET_INPUT_DEVICE_CAPABILITIES:
      {
         uint64_t *mask = (uint64_t*)data;

         RARCH_LOG("Environ GET_INPUT_DEVICE_CAPABILITIES.\n");
         if (input_driver_ctl(RARCH_INPUT_CTL_HAS_CAPABILITIES, NULL))
            *mask = input_driver_get_capabilities();
         else
            return false;
         break;
      }

      case RETRO_ENVIRONMENT_GET_SENSOR_INTERFACE:
      {
         struct retro_sensor_interface *iface =
            (struct retro_sensor_interface*)data;

         RARCH_LOG("Environ GET_SENSOR_INTERFACE.\n");
         iface->set_sensor_state = input_sensor_set_state;
         iface->get_sensor_input = input_sensor_get_input;
         break;
      }

      case RETRO_ENVIRONMENT_GET_CAMERA_INTERFACE:
      {
         struct retro_camera_callback *cb =
            (struct retro_camera_callback*)data;

         RARCH_LOG("Environ GET_CAMERA_INTERFACE.\n");
         cb->start                         = driver_camera_start;
         cb->stop                          = driver_camera_stop;
         system->camera_callback           = *cb;
         if (cb->caps != 0)
            camera_driver_ctl(RARCH_CAMERA_CTL_SET_ACTIVE, NULL);
         else
            camera_driver_ctl(RARCH_CAMERA_CTL_UNSET_ACTIVE, NULL);
         break;
      }

      case RETRO_ENVIRONMENT_GET_LOCATION_INTERFACE:
      {
         struct retro_location_callback *cb =
            (struct retro_location_callback*)data;

         RARCH_LOG("Environ GET_LOCATION_INTERFACE.\n");
         cb->start                 = driver_location_start;
         cb->stop                  = driver_location_stop;
         cb->get_position          = driver_location_get_position;
         cb->set_interval          = driver_location_set_interval;
         system->location_callback = *cb;

         location_driver_ctl(RARCH_LOCATION_CTL_UNSET_ACTIVE, NULL);
         break;
      }

      case RETRO_ENVIRONMENT_GET_LOG_INTERFACE:
      {
         struct retro_log_callback *cb = (struct retro_log_callback*)data;

         RARCH_LOG("Environ GET_LOG_INTERFACE.\n");
         cb->log = rarch_log_libretro;
         break;
      }

      case RETRO_ENVIRONMENT_GET_PERF_INTERFACE:
      {
         struct retro_perf_callback *cb = (struct retro_perf_callback*)data;

         RARCH_LOG("Environ GET_PERF_INTERFACE.\n");
         cb->get_time_usec    = retro_get_time_usec;
         cb->get_cpu_features = retro_get_cpu_features;
         cb->get_perf_counter = retro_get_perf_counter;
         cb->perf_register    = retro_perf_register; /* libretro specific path. */
         cb->perf_start       = retro_perf_start;
         cb->perf_stop        = retro_perf_stop;
         cb->perf_log         = retro_perf_log; /* libretro specific path. */
         break;
      }

      case RETRO_ENVIRONMENT_GET_CORE_ASSETS_DIRECTORY:
      {
         const char **dir = (const char**)data;

         *dir = *settings->core_assets_directory ?
            settings->core_assets_directory : NULL;
         RARCH_LOG("Environ CORE_ASSETS_DIRECTORY: \"%s\".\n",
               settings->core_assets_directory);
         break;
      }

      case RETRO_ENVIRONMENT_SET_SYSTEM_AV_INFO:
      {
         RARCH_LOG("Environ SET_SYSTEM_AV_INFO.\n");
         return driver_ctl(RARCH_DRIVER_CTL_UPDATE_SYSTEM_AV_INFO,
               (void**)&data);
      }

      case RETRO_ENVIRONMENT_SET_SUBSYSTEM_INFO:
      {
         unsigned i, j;
         const struct retro_subsystem_info *info =
            (const struct retro_subsystem_info*)data;

         RARCH_LOG("Environ SET_SUBSYSTEM_INFO.\n");

         for (i = 0; info[i].ident; i++)
         {
            RARCH_LOG("Special game type: %s\n", info[i].desc);
            RARCH_LOG("  Ident: %s\n", info[i].ident);
            RARCH_LOG("  ID: %u\n", info[i].id);
            RARCH_LOG("  Content:\n");
            for (j = 0; j < info[i].num_roms; j++)
            {
               RARCH_LOG("    %s (%s)\n",
                     info[i].roms[j].desc, info[i].roms[j].required ?
                     "required" : "optional");
            }
         }

         free(system->special);
         system->special = (struct retro_subsystem_info*)
            calloc(i, sizeof(*system->special));

         if (!system->special)
            return false;

         memcpy(system->special, info,
               i * sizeof(*system->special));
         system->num_special = i;
         break;
      }

      case RETRO_ENVIRONMENT_SET_CONTROLLER_INFO:
      {
         unsigned i, j;
         const struct retro_controller_info *info =
            (const struct retro_controller_info*)data;

         RARCH_LOG("Environ SET_CONTROLLER_INFO.\n");

         for (i = 0; info[i].types; i++)
         {
            RARCH_LOG("Controller port: %u\n", i + 1);
            for (j = 0; j < info[i].num_types; j++)
               RARCH_LOG("   %s (ID: %u)\n", info[i].types[j].desc,
                     info[i].types[j].id);
         }

         free(system->ports);
         system->ports = (struct retro_controller_info*)
            calloc(i, sizeof(*system->ports));
         if (!system->ports)
            return false;

         memcpy(system->ports, info,
               i * sizeof(*system->ports));
         system->num_ports = i;
         break;
      }

      case RETRO_ENVIRONMENT_SET_GEOMETRY:
      {
         struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
         const struct retro_game_geometry *in_geom =
            (const struct retro_game_geometry*)data;
         struct retro_game_geometry *geom = av_info ?
            (struct retro_game_geometry*)&av_info->geometry : NULL;

         if (!geom)
            return false;

         RARCH_LOG("Environ SET_GEOMETRY.\n");

         /* Can potentially be called every frame,
          * don't do anything unless required. */
         if (geom->base_width != in_geom->base_width ||
               geom->base_height != in_geom->base_height ||
               geom->aspect_ratio != in_geom->aspect_ratio)
         {
            geom->base_width   = in_geom->base_width;
            geom->base_height  = in_geom->base_height;
            geom->aspect_ratio = in_geom->aspect_ratio;
            RARCH_LOG("SET_GEOMETRY: %ux%u, aspect: %.3f.\n",
                  geom->base_width, geom->base_height, geom->aspect_ratio);

            /* Forces recomputation of aspect ratios if
             * using core-dependent aspect ratios. */
            event_cmd_ctl(EVENT_CMD_VIDEO_SET_ASPECT_RATIO, NULL);

            /* TODO: Figure out what to do, if anything, with recording. */
         }
         break;
      }

      case RETRO_ENVIRONMENT_GET_CURRENT_SOFTWARE_FRAMEBUFFER:
         return video_driver_get_current_software_framebuffer((struct retro_framebuffer*)data);

      /* Private extensions for internal use, not part of libretro API. */
      case RETRO_ENVIRONMENT_EXEC:
         {
            RARCH_LOG("Environ (Private) EXEC.\n");

            char *fullpath = NULL;
            runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);

            if (fullpath != data)
            {
               runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL);
               if (data)
                  runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, data);
            }

#if defined(RARCH_CONSOLE)
            frontend_driver_set_fork(true, true, false);
#elif defined(HAVE_DYNAMIC)
            rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
#endif

         }
         break;

      default:
         RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
         return false;
   }

   return true;
}
예제 #23
0
bool runloop_ctl(enum runloop_ctl_state state, void *data)
{
   static rarch_dir_list_t runloop_shader_dir;
   static char runloop_fullpath[PATH_MAX_LENGTH];
   static rarch_system_info_t runloop_system;
   static unsigned runloop_pending_windowed_scale;
   static retro_keyboard_event_t runloop_key_event = NULL;
   static unsigned runloop_max_frames              = false;
   static bool runloop_frame_time_last             = false;
   static bool runloop_set_frame_limit             = false;
   static bool runloop_paused                      = false;
   static bool runloop_idle                        = false;
   static bool runloop_exec                        = false;
   static bool runloop_slowmotion                  = false;
   static bool runloop_shutdown_initiated          = false;
   static bool runloop_core_shutdown_initiated     = false;
   static bool runloop_perfcnt_enable              = false;
   static bool runloop_overrides_active            = false;
   static bool runloop_game_options_active         = false;
#ifdef HAVE_THREADS
   static slock_t *runloop_msg_queue_lock          = NULL;
#endif
   static core_info_t *core_info_current           = NULL;
   static core_info_list_t *core_info_curr_list    = NULL;
   settings_t *settings                            = config_get_ptr();

   switch (state)
   {
      case RUNLOOP_CTL_DATA_ITERATE:
         rarch_task_check();
         return true;
      case RUNLOOP_CTL_SHADER_DIR_DEINIT:
         shader_dir_free(&runloop_shader_dir);
         return true;
      case RUNLOOP_CTL_SHADER_DIR_INIT:
         return shader_dir_init(&runloop_shader_dir);
      case RUNLOOP_CTL_SYSTEM_INFO_INIT:
         core.retro_get_system_info(&runloop_system.info);

         if (!runloop_system.info.library_name)
            runloop_system.info.library_name = msg_hash_to_str(MSG_UNKNOWN);
         if (!runloop_system.info.library_version)
            runloop_system.info.library_version = "v0";

#ifndef RARCH_CONSOLE
         strlcpy(runloop_system.title_buf, 
               msg_hash_to_str(MSG_PROGRAM), sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, " : ", sizeof(runloop_system.title_buf));
#endif
         strlcat(runloop_system.title_buf, runloop_system.info.library_name, sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, " ", sizeof(runloop_system.title_buf));
         strlcat(runloop_system.title_buf, runloop_system.info.library_version, sizeof(runloop_system.title_buf));
         strlcpy(runloop_system.valid_extensions, runloop_system.info.valid_extensions ?
               runloop_system.info.valid_extensions : DEFAULT_EXT,
               sizeof(runloop_system.valid_extensions));
         runloop_system.block_extract = runloop_system.info.block_extract;
         break;
      case RUNLOOP_CTL_GET_CORE_OPTION_SIZE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            *idx = core_option_size(runloop_system.core_options);
         }
         return true;
      case RUNLOOP_CTL_HAS_CORE_OPTIONS:
         return runloop_system.core_options;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_FREE:
         if (core_info_curr_list)
            core_info_list_free(core_info_curr_list);
         core_info_curr_list = NULL;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_INIT:
         core_info_curr_list = core_info_list_new();
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_LIST_GET:
         {
            core_info_list_t **core = (core_info_list_t**)data;
            if (!core)
               return false;
            *core = core_info_curr_list;
         }
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_FREE:
         if (core_info_current)
            free(core_info_current);
         core_info_current = NULL;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_INIT:
         core_info_current = (core_info_t*)calloc(1, sizeof(core_info_t));
         if (!core_info_current)
            return false;
         return true;
      case RUNLOOP_CTL_CURRENT_CORE_GET:
         {
            core_info_t **core = (core_info_t**)data;
            if (!core)
               return false;
            *core = core_info_current;
         }
         return true;
      case RUNLOOP_CTL_SYSTEM_INFO_GET:
         {
            rarch_system_info_t **system = (rarch_system_info_t**)data;
            if (!system)
               return false;
            *system = &runloop_system;
         }
         return true;
      case RUNLOOP_CTL_SYSTEM_INFO_FREE:
         if (runloop_system.core_options)
         {
            core_option_flush(runloop_system.core_options);
            core_option_free(runloop_system.core_options);
         }

         runloop_system.core_options = NULL;

         /* No longer valid. */
         if (runloop_system.special)
            free(runloop_system.special);
         runloop_system.special = NULL;
         if (runloop_system.ports)
            free(runloop_system.ports);
         runloop_system.ports   = NULL;

         runloop_key_event = NULL;
         global_get_ptr()->frontend_key_event = NULL;
         audio_driver_unset_callback();
         memset(&runloop_system, 0, sizeof(rarch_system_info_t));
         break;
      case RUNLOOP_CTL_IS_FRAME_COUNT_END:
         {
            uint64_t *frame_count         = NULL;
            video_driver_ctl(RARCH_DISPLAY_CTL_GET_FRAME_COUNT, &frame_count);
            return runloop_max_frames && (*frame_count >= runloop_max_frames);
         }
      case RUNLOOP_CTL_SET_FRAME_TIME_LAST:
         runloop_frame_time_last = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_TIME_LAST:
         runloop_frame_time_last = false;
         break;
      case RUNLOOP_CTL_SET_OVERRIDES_ACTIVE:
         runloop_overrides_active = true;
         break;
      case RUNLOOP_CTL_UNSET_OVERRIDES_ACTIVE:
         runloop_overrides_active = false; 
         break;
      case RUNLOOP_CTL_IS_OVERRIDES_ACTIVE:
         return runloop_overrides_active;
      case RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = true;
         break;
      case RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE:
         runloop_game_options_active = false;
         break;
      case RUNLOOP_CTL_IS_GAME_OPTIONS_ACTIVE:
         return runloop_game_options_active;
      case RUNLOOP_CTL_IS_FRAME_TIME_LAST:
         return runloop_frame_time_last;
      case RUNLOOP_CTL_SET_FRAME_LIMIT:
         runloop_set_frame_limit = true;
         break;
      case RUNLOOP_CTL_UNSET_FRAME_LIMIT:
         runloop_set_frame_limit = false;
         break;
      case RUNLOOP_CTL_SHOULD_SET_FRAME_LIMIT:
         return runloop_set_frame_limit;
      case RUNLOOP_CTL_GET_PERFCNT:
         {
            bool **perfcnt = (bool**)data;
            if (!perfcnt)
               return false;
            *perfcnt = &runloop_perfcnt_enable;
         }
         return true;
      case RUNLOOP_CTL_SET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = true;
         break;
      case RUNLOOP_CTL_UNSET_PERFCNT_ENABLE:
         runloop_perfcnt_enable = false;
         break;
      case RUNLOOP_CTL_IS_PERFCNT_ENABLE:
         return runloop_perfcnt_enable;
      case RUNLOOP_CTL_GET_WINDOWED_SCALE:
         {
            unsigned **scale = (unsigned**)data;
            if (!scale)
               return false;
            *scale       = (unsigned*)&runloop_pending_windowed_scale;
         }
         break;
      case RUNLOOP_CTL_SET_WINDOWED_SCALE:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            runloop_pending_windowed_scale = *idx;
         }
         break;
      case RUNLOOP_CTL_SET_LIBRETRO_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            strlcpy(settings->libretro, fullpath, sizeof(settings->libretro));
         }
         break;
      case RUNLOOP_CTL_CLEAR_CONTENT_PATH:
         *runloop_fullpath = '\0';
         break;
      case RUNLOOP_CTL_GET_CONTENT_PATH:
         {
            char **fullpath = (char**)data;
            if (!fullpath)
               return false;
            *fullpath       = (char*)runloop_fullpath;
         }
         break;
      case RUNLOOP_CTL_SET_CONTENT_PATH:
         {
            const char *fullpath = (const char*)data;
            if (!fullpath)
               return false;
            strlcpy(runloop_fullpath, fullpath, sizeof(runloop_fullpath));
         }
         break;
      case RUNLOOP_CTL_CHECK_FOCUS:
         if (settings->pause_nonactive)
            return video_driver_ctl(RARCH_DISPLAY_CTL_IS_FOCUSED, NULL);
         return true;
      case RUNLOOP_CTL_CHECK_IDLE_STATE:
         {
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;
            bool focused              = runloop_ctl(RUNLOOP_CTL_CHECK_FOCUS, NULL);

            check_pause(settings, focused,
                  runloop_cmd_triggered(cmd, RARCH_PAUSE_TOGGLE),
                  runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE));

            if (!runloop_ctl(RUNLOOP_CTL_CHECK_PAUSE_STATE, cmd) || !focused)
               return false;
            break;
         }
      case RUNLOOP_CTL_CHECK_STATE:
         {
            bool tmp                  = false;
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;

            if (!cmd || runloop_idle)
               return false;

            if (runloop_cmd_triggered(cmd, RARCH_SCREENSHOT))
               event_command(EVENT_CMD_TAKE_SCREENSHOT);

            if (runloop_cmd_triggered(cmd, RARCH_MUTE))
               event_command(EVENT_CMD_AUDIO_MUTE_TOGGLE);

            if (runloop_cmd_triggered(cmd, RARCH_OSK))
            {
               if (input_driver_ctl(RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED, NULL))
                  input_driver_ctl(RARCH_INPUT_CTL_UNSET_KEYBOARD_LINEFEED_ENABLED, NULL);
               else
                  input_driver_ctl(RARCH_INPUT_CTL_SET_KEYBOARD_LINEFEED_ENABLED, NULL);
            }

            if (runloop_cmd_press(cmd, RARCH_VOLUME_UP))
               event_command(EVENT_CMD_VOLUME_UP);
            else if (runloop_cmd_press(cmd, RARCH_VOLUME_DOWN))
               event_command(EVENT_CMD_VOLUME_DOWN);

#ifdef HAVE_NETPLAY
            tmp = runloop_cmd_triggered(cmd, RARCH_NETPLAY_FLIP);
            netplay_driver_ctl(RARCH_NETPLAY_CTL_FLIP_PLAYERS, &tmp);
            tmp = runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY);
            netplay_driver_ctl(RARCH_NETPLAY_CTL_FULLSCREEN_TOGGLE, &tmp);
#endif
            if (!runloop_ctl(RUNLOOP_CTL_CHECK_IDLE_STATE, data))
               return false;

            check_fast_forward_button(
                  runloop_cmd_triggered(cmd, RARCH_FAST_FORWARD_KEY),
                  runloop_cmd_press    (cmd, RARCH_FAST_FORWARD_HOLD_KEY),
                  runloop_cmd_pressed  (cmd, RARCH_FAST_FORWARD_HOLD_KEY));
            check_stateslots(settings,
                  runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_PLUS),
                  runloop_cmd_triggered(cmd, RARCH_STATE_SLOT_MINUS)
                  );

            if (runloop_cmd_triggered(cmd, RARCH_SAVE_STATE_KEY))
               event_command(EVENT_CMD_SAVE_STATE);
            else if (runloop_cmd_triggered(cmd, RARCH_LOAD_STATE_KEY))
               event_command(EVENT_CMD_LOAD_STATE);

            state_manager_check_rewind(runloop_cmd_press(cmd, RARCH_REWIND));

            tmp = runloop_cmd_press(cmd, RARCH_SLOWMOTION);

            runloop_ctl(RUNLOOP_CTL_CHECK_SLOWMOTION, &tmp);

            if (runloop_cmd_triggered(cmd, RARCH_MOVIE_RECORD_TOGGLE))
               runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE, NULL);

            check_shader_dir(&runloop_shader_dir,
                  runloop_cmd_triggered(cmd, RARCH_SHADER_NEXT),
                  runloop_cmd_triggered(cmd, RARCH_SHADER_PREV));

            if (runloop_cmd_triggered(cmd, RARCH_DISK_EJECT_TOGGLE))
               event_command(EVENT_CMD_DISK_EJECT_TOGGLE);
            else if (runloop_cmd_triggered(cmd, RARCH_DISK_NEXT))
               event_command(EVENT_CMD_DISK_NEXT);
            else if (runloop_cmd_triggered(cmd, RARCH_DISK_PREV))
               event_command(EVENT_CMD_DISK_PREV);

            if (runloop_cmd_triggered(cmd, RARCH_RESET))
               event_command(EVENT_CMD_RESET);

            cheat_manager_state_checks(
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_PLUS),
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_INDEX_MINUS),
                  runloop_cmd_triggered(cmd, RARCH_CHEAT_TOGGLE));
         }
         break;
      case RUNLOOP_CTL_CHECK_PAUSE_STATE:
         {
            bool check_is_oneshot;
            event_cmd_state_t *cmd    = (event_cmd_state_t*)data;

            if (!cmd)
               return false;

            check_is_oneshot     = runloop_cmd_triggered(cmd, RARCH_FRAMEADVANCE) 
               || runloop_cmd_press(cmd, RARCH_REWIND);

            if (!runloop_paused)
               return true;

            if (runloop_cmd_triggered(cmd, RARCH_FULLSCREEN_TOGGLE_KEY))
            {
               event_command(EVENT_CMD_FULLSCREEN_TOGGLE);
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);
            }

            if (!check_is_oneshot)
               return false;
         }
         break;
      case RUNLOOP_CTL_CHECK_SLOWMOTION:
         {
            bool *ptr            = (bool*)data;

            if (!ptr)
               return false;

            runloop_slowmotion   = *ptr;

            if (!runloop_slowmotion)
               return false;

            if (settings->video.black_frame_insertion)
               video_driver_ctl(RARCH_DISPLAY_CTL_CACHED_FRAME_RENDER, NULL);

            if (state_manager_frame_is_reversed())
               runloop_msg_queue_push_new(MSG_SLOW_MOTION_REWIND, 0, 30, true);
            else
               runloop_msg_queue_push_new(MSG_SLOW_MOTION, 0, 30, true);
         }
         break;
      case RUNLOOP_CTL_CHECK_MOVIE:
         if (bsv_movie_ctl(BSV_MOVIE_CTL_PLAYBACK_ON, NULL))
            return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK, NULL);
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_INIT, NULL);
         return runloop_ctl(RUNLOOP_CTL_CHECK_MOVIE_RECORD, NULL);
      case RUNLOOP_CTL_CHECK_MOVIE_RECORD:
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;

         runloop_msg_queue_push_new(
               MSG_MOVIE_RECORD_STOPPED, 2, 180, true);
         RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_RECORD_STOPPED));

         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);
         break;
      case RUNLOOP_CTL_CHECK_MOVIE_INIT:
         if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            return false;
         {
            char msg[128];
            char path[PATH_MAX_LENGTH];

            settings->rewind_granularity = 1;

            if (settings->state_slot > 0)
               snprintf(path, sizeof(path), "%s%d",
                     bsv_movie_get_path(), settings->state_slot);
            else
               strlcpy(path, bsv_movie_get_path(), sizeof(path));

            strlcat(path, ".bsv", sizeof(path));

            snprintf(msg, sizeof(msg), "%s \"%s\".",
                  msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
                  path);

            bsv_movie_init_handle(path, RARCH_MOVIE_RECORD);

            if (!bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
               return false;
            else if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
            {
               runloop_msg_queue_push(msg, 1, 180, true);
               RARCH_LOG("%s \"%s\".\n",
                     msg_hash_to_str(MSG_STARTING_MOVIE_RECORD_TO),
                     path);
            }
            else
            {
               runloop_msg_queue_push_new(
                     MSG_FAILED_TO_START_MOVIE_RECORD,
                     1, 180, true);
               RARCH_ERR("%s\n", msg_hash_to_str(MSG_FAILED_TO_START_MOVIE_RECORD));
            }
         }
         break;
      case RUNLOOP_CTL_CHECK_MOVIE_PLAYBACK:
         if (!bsv_movie_ctl(BSV_MOVIE_CTL_END, NULL))
            return false;

         runloop_msg_queue_push_new(
               MSG_MOVIE_PLAYBACK_ENDED, 1, 180, false);
         RARCH_LOG("%s\n", msg_hash_to_str(MSG_MOVIE_PLAYBACK_ENDED));

         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);

         bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_END, NULL);
         bsv_movie_ctl(BSV_MOVIE_CTL_UNSET_PLAYBACK, NULL);
         break;
      case RUNLOOP_CTL_STATE_FREE:
         runloop_perfcnt_enable     = false;
         runloop_idle               = false;
         runloop_paused             = false;
         runloop_slowmotion         = false;
         runloop_frame_time_last    = false;
         runloop_set_frame_limit    = false;
         runloop_overrides_active   = false;
         runloop_max_frames         = 0;
         break;
      case RUNLOOP_CTL_GLOBAL_FREE:
         {
            global_t *global;
            event_command(EVENT_CMD_TEMPORARY_CONTENT_DEINIT);
            event_command(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT);
            event_command(EVENT_CMD_RECORD_DEINIT);
            event_command(EVENT_CMD_LOG_FILE_DEINIT);

            rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
            runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH,  NULL);
            runloop_overrides_active   = false;

            global = global_get_ptr();
            memset(global, 0, sizeof(struct global));
         }
         break;
      case RUNLOOP_CTL_CLEAR_STATE:
         driver_ctl(RARCH_DRIVER_CTL_DEINIT,  NULL);
         runloop_ctl(RUNLOOP_CTL_STATE_FREE,  NULL);
         runloop_ctl(RUNLOOP_CTL_GLOBAL_FREE, NULL);
         break;
      case RUNLOOP_CTL_SET_MAX_FRAMES:
         {
            unsigned *ptr = (unsigned*)data;
            if (!ptr)
               return false;
            runloop_max_frames = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_IDLE:
         return runloop_idle;
      case RUNLOOP_CTL_SET_IDLE:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_idle = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_SLOWMOTION:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            *ptr = runloop_slowmotion;
         }
         break;
      case RUNLOOP_CTL_SET_SLOWMOTION:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_slowmotion = *ptr;
         }
         break;
      case RUNLOOP_CTL_SET_PAUSED:
         {
            bool *ptr = (bool*)data;
            if (!ptr)
               return false;
            runloop_paused = *ptr;
         }
         break;
      case RUNLOOP_CTL_IS_PAUSED:
         return runloop_paused;
      case RUNLOOP_CTL_MSG_QUEUE_FREE:
#ifdef HAVE_THREADS
         slock_free(runloop_msg_queue_lock);
         runloop_msg_queue_lock = NULL;
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_DEINIT:
         if (!g_msg_queue)
            return true;

         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_LOCK, NULL);

         msg_queue_free(g_msg_queue);

         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_UNLOCK, NULL);
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_FREE, NULL);

         g_msg_queue = NULL;
         break;
      case RUNLOOP_CTL_MSG_QUEUE_INIT:
         runloop_ctl(RUNLOOP_CTL_MSG_QUEUE_DEINIT, NULL);
         g_msg_queue = msg_queue_new(8);
         retro_assert(g_msg_queue);

#ifdef HAVE_THREADS
         runloop_msg_queue_lock = slock_new();
         retro_assert(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_LOCK:
#ifdef HAVE_THREADS
         slock_lock(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_MSG_QUEUE_UNLOCK:
#ifdef HAVE_THREADS
         slock_unlock(runloop_msg_queue_lock);
#endif
         break;
      case RUNLOOP_CTL_PREPARE_DUMMY:
#ifdef HAVE_MENU
         menu_driver_ctl(RARCH_MENU_CTL_UNSET_LOAD_NO_CONTENT, NULL);
#endif
         runloop_data_clear_state();

         runloop_ctl(RUNLOOP_CTL_CLEAR_CONTENT_PATH, NULL);

         rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
         break;
      case RUNLOOP_CTL_SET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_CORE_SHUTDOWN:
         runloop_core_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_CORE_SHUTDOWN:
         return runloop_core_shutdown_initiated;
      case RUNLOOP_CTL_SET_SHUTDOWN:
         runloop_shutdown_initiated = true;
         break;
      case RUNLOOP_CTL_UNSET_SHUTDOWN:
         runloop_shutdown_initiated = false;
         break;
      case RUNLOOP_CTL_IS_SHUTDOWN:
         return runloop_shutdown_initiated;
      case RUNLOOP_CTL_SET_EXEC:
         runloop_exec = true;
         break;
      case RUNLOOP_CTL_UNSET_EXEC:
         runloop_exec = false;
         break;
      case RUNLOOP_CTL_IS_EXEC:
         return runloop_exec;
      case RUNLOOP_CTL_DATA_DEINIT:
         rarch_task_deinit();
         break;
      case RUNLOOP_CTL_IS_CORE_OPTION_UPDATED:
         return runloop_system.core_options ?
            core_option_updated(runloop_system.core_options) : false;
      case RUNLOOP_CTL_CORE_OPTION_PREV:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_prev(runloop_system.core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTION_NEXT:
         {
            unsigned *idx = (unsigned*)data;
            if (!idx)
               return false;
            core_option_next(runloop_system.core_options, *idx);
            if (ui_companion_is_on_foreground())
               ui_companion_driver_notify_refresh();
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTIONS_GET:
         {
            struct retro_variable *var = (struct retro_variable*)data;

            if (!runloop_system.core_options || !var)
               return false;

            RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key);
            core_option_get(runloop_system.core_options, var);
            RARCH_LOG("\t%s\n", var->value ? var->value : "N/A");
         }
         return true;
      case RUNLOOP_CTL_CORE_OPTIONS_INIT:
         {
            char *game_options_path           = NULL;
            bool ret                          = false;
            const struct retro_variable *vars = (const struct retro_variable*)data;
            char buf[PATH_MAX_LENGTH]         = {0};
            global_t *global                  = global_get_ptr();
            const char *options_path          = settings->core_options_path;

            if (!*options_path && *global->path.config)
            {
               fill_pathname_resolve_relative(buf, global->path.config,
                     "retroarch-core-options.cfg", sizeof(buf));
               options_path = buf;
            }


            if (settings->game_specific_options)
               ret = rarch_game_specific_options(&game_options_path);

            if(ret)
            {
               runloop_ctl(RUNLOOP_CTL_SET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_system.core_options = core_option_new(game_options_path, vars);
               free(game_options_path);
            }
            else
            {
               runloop_ctl(RUNLOOP_CTL_UNSET_GAME_OPTIONS_ACTIVE, NULL);
               runloop_system.core_options = core_option_new(options_path, vars);
            }

         }
         break;
      case RUNLOOP_CTL_CORE_OPTIONS_DEINIT:
         if (!runloop_system.core_options)
            return false;

         core_option_flush(runloop_system.core_options);
         core_option_free(runloop_system.core_options);

         runloop_system.core_options = NULL;
         return true;
      case RUNLOOP_CTL_KEY_EVENT_GET:
         {
            retro_keyboard_event_t **key_event = (retro_keyboard_event_t**)data;
            if (!key_event)
               return false;
            *key_event = &runloop_key_event;
         }
         break;
      case RUNLOOP_CTL_NONE:
      default:
         return false;
   }

   return true;
}
예제 #24
0
bool input_driver_ctl(enum rarch_input_ctl_state state, void *data)
{
   static bool input_driver_block_hotkey             = false;
   static bool input_driver_block_libretro_input     = false;
   static bool input_driver_osk_enabled              = false;
   static bool input_driver_keyboard_linefeed_enable = false;
   static bool input_driver_nonblock_state           = false;
   static bool input_driver_flushing_input           = false;
   static bool input_driver_data_own                 = false;
   settings_t *settings                              = config_get_ptr();

   switch (state)
   {
      case RARCH_INPUT_CTL_KEY_PRESSED:
         {
            unsigned *key = (unsigned*)data;
            if (key && current_input->key_pressed)
               return current_input->key_pressed(current_input_data, *key);
         }
         return false;
      case RARCH_INPUT_CTL_HAS_CAPABILITIES:
         if (!current_input->get_capabilities || !current_input_data)
            return false;
         break;
      case RARCH_INPUT_CTL_POLL:
         current_input->poll(current_input_data);
         break;
      case RARCH_INPUT_CTL_INIT:
         if (current_input)
            current_input_data = current_input->init();

         if (!current_input_data)
            return false;
         break;
      case RARCH_INPUT_CTL_DEINIT:
         if (current_input && current_input->free)
            current_input->free(current_input_data);
         current_input_data = NULL;
         break;
      case RARCH_INPUT_CTL_DESTROY_DATA:
         current_input_data = NULL;
         break;
      case RARCH_INPUT_CTL_DESTROY:
         input_driver_block_hotkey             = false;
         input_driver_block_libretro_input     = false;
         input_driver_keyboard_linefeed_enable = false;
         input_driver_nonblock_state           = false;
         input_driver_flushing_input           = false;
         input_driver_data_own                 = false;
         memset(&input_driver_turbo_btns, 0, sizeof(turbo_buttons_t));
         current_input                         = NULL;
         break;
      case RARCH_INPUT_CTL_GRAB_STDIN:
         if (!current_input->grab_stdin)
            return false;
         return current_input->grab_stdin(current_input_data);
      case RARCH_INPUT_CTL_KB_MAPPING_IS_BLOCKED:
         if (!current_input->keyboard_mapping_is_blocked)
            return false;
         return current_input->keyboard_mapping_is_blocked(
               current_input_data);
      case RARCH_INPUT_CTL_FIND_DRIVER:
         {
            int i;
            driver_ctx_info_t drv;

            drv.label = "input_driver";
            drv.s     = settings->input.driver;

            driver_ctl(RARCH_DRIVER_CTL_FIND_INDEX, &drv);

            i = drv.len;

            if (i >= 0)
               current_input = (const input_driver_t*)
                  input_driver_find_handle(i);
            else
            {
               unsigned d;
               RARCH_ERR("Couldn't find any input driver named \"%s\"\n",
                     settings->input.driver);
               RARCH_LOG_OUTPUT("Available input drivers are:\n");
               for (d = 0; input_driver_find_handle(d); d++)
                  RARCH_LOG_OUTPUT("\t%s\n", input_driver_find_ident(d));
               RARCH_WARN("Going to default to first input driver...\n");

               current_input = (const input_driver_t*)
                  input_driver_find_handle(0);

               if (current_input)
                  return true;
               retro_fail(1, "find_input_driver()");
               return false;
            }
         }
         break;
      case RARCH_INPUT_CTL_SET_FLUSHING_INPUT:
         input_driver_flushing_input = true;
         break;
      case RARCH_INPUT_CTL_UNSET_FLUSHING_INPUT:
         input_driver_flushing_input = false;
         break;
      case RARCH_INPUT_CTL_IS_FLUSHING_INPUT:
         return input_driver_flushing_input;
      case RARCH_INPUT_CTL_SET_HOTKEY_BLOCK:
         input_driver_block_hotkey = true;
         break;
      case RARCH_INPUT_CTL_UNSET_HOTKEY_BLOCK:
         input_driver_block_hotkey = false;
         break;
      case RARCH_INPUT_CTL_IS_HOTKEY_BLOCKED:
         return input_driver_block_hotkey;
      case RARCH_INPUT_CTL_SET_LIBRETRO_INPUT_BLOCKED:
         input_driver_block_libretro_input = true;
         break;
      case RARCH_INPUT_CTL_UNSET_LIBRETRO_INPUT_BLOCKED:
         input_driver_block_libretro_input = false;
         break;
      case RARCH_INPUT_CTL_IS_LIBRETRO_INPUT_BLOCKED:
         return input_driver_block_libretro_input;
      case RARCH_INPUT_CTL_SET_NONBLOCK_STATE:
         input_driver_nonblock_state = true;
         break;
      case RARCH_INPUT_CTL_UNSET_NONBLOCK_STATE:
         input_driver_nonblock_state = false;
         break;
      case RARCH_INPUT_CTL_IS_NONBLOCK_STATE:
         return input_driver_nonblock_state;
      case RARCH_INPUT_CTL_SET_OWN_DRIVER:
         input_driver_data_own = true;
         break;
      case RARCH_INPUT_CTL_UNSET_OWN_DRIVER:
         input_driver_data_own = false;
         break;
      case RARCH_INPUT_CTL_OWNS_DRIVER:
         return input_driver_data_own;
      case RARCH_INPUT_CTL_SET_OSK_ENABLED:
         input_driver_osk_enabled = true;
         break;
      case RARCH_INPUT_CTL_UNSET_OSK_ENABLED:
         input_driver_osk_enabled = false;
         break;
      case RARCH_INPUT_CTL_IS_OSK_ENABLED:
         return input_driver_osk_enabled;
      case RARCH_INPUT_CTL_SET_KEYBOARD_LINEFEED_ENABLED:
         input_driver_keyboard_linefeed_enable = true;
         break;
      case RARCH_INPUT_CTL_UNSET_KEYBOARD_LINEFEED_ENABLED:
         input_driver_keyboard_linefeed_enable = false;
         break;
      case RARCH_INPUT_CTL_IS_KEYBOARD_LINEFEED_ENABLED:
         return input_driver_keyboard_linefeed_enable;
      case RARCH_INPUT_CTL_COMMAND_INIT:
#ifdef HAVE_COMMAND
         if (!settings->stdin_cmd_enable && !settings->network_cmd_enable)
            return false;

         if (settings->stdin_cmd_enable 
               && input_driver_ctl(RARCH_INPUT_CTL_GRAB_STDIN, NULL))
         {
            RARCH_WARN("stdin command interface is desired, but input driver has already claimed stdin.\n"
                  "Cannot use this command interface.\n");
         }

         input_driver_command = rarch_cmd_new(settings->stdin_cmd_enable
               && !input_driver_ctl(RARCH_INPUT_CTL_GRAB_STDIN, NULL),
               settings->network_cmd_enable, settings->network_cmd_port);

         if (!input_driver_command)
         {
            RARCH_ERR("Failed to initialize command interface.\n");
            return false;
         }
#endif
         break;
      case RARCH_INPUT_CTL_COMMAND_DEINIT:
#ifdef HAVE_COMMAND
         if (input_driver_command)
            rarch_cmd_ctl(RARCH_CMD_CTL_FREE, input_driver_command);
         input_driver_command = NULL;
#endif
         break;
      case RARCH_INPUT_CTL_REMOTE_DEINIT:
#ifdef HAVE_NETWORK_GAMEPAD
         if (input_driver_remote)
            rarch_remote_free(input_driver_remote);
         input_driver_remote = NULL;
#endif
         break;
      case RARCH_INPUT_CTL_REMOTE_INIT:
#ifdef HAVE_NETWORK_GAMEPAD
         if (settings->network_remote_enable)
         {
            input_driver_remote 
               = rarch_remote_new(settings->network_remote_base_port);

            if (!input_driver_remote)
            {
               RARCH_ERR("Failed to initialize remote gamepad interface.\n");
               return false;
            }
         }
#endif
         break;
      case RARCH_INPUT_CTL_GRAB_MOUSE:
         {
            bool *bool_data = (bool*)data;
            if (!current_input || !current_input->grab_mouse)
               return false;

            current_input->grab_mouse(current_input_data, *bool_data);
         }
         break;
      case RARCH_INPUT_CTL_IS_DATA_PTR_SAME:
         return (current_input_data == data);
      case RARCH_INPUT_CTL_NONE:
      default:
         break;
   }

   return true;
}