Exemplo n.º 1
0
static int action_ok_file_load_with_detect_core(const char *path,
      const char *label, unsigned type, size_t idx)
{
   int ret;
   menu_displaylist_info_t info = {0};
   const char *menu_path    = NULL;
   menu_handle_t *menu      = menu_driver_get_ptr();
   settings_t *settings     = config_get_ptr();
   global_t *global         = global_get_ptr();

   if (!menu)
      return -1;

   menu_list_get_last_stack(menu->menu_list,
         &menu_path, NULL, NULL);

   ret = rarch_defer_core(global->core_info,
         menu_path, path, label, menu->deferred_path,
         sizeof(menu->deferred_path));

   if (ret == -1)
   {

      if (!strcmp(label, "collection"))
      {
         info.list          = menu->menu_list->menu_stack;
         info.type          = 0;
         info.directory_ptr = idx;
         rdb_entry_start_game_selection_ptr = idx;
         strlcpy(info.path, settings->libretro_directory, sizeof(info.path));
         strlcpy(info.label, "deferred_core_list_set", sizeof(info.label));

         return menu_displaylist_push_list(&info, DISPLAYLIST_GENERIC);
      }
      else
      {
         event_command(EVENT_CMD_LOAD_CORE);
         menu_entries_common_load_content(false);
         return -1;
      }
   }

   if (ret == 0)
   {
      info.list          = menu->menu_list->menu_stack;
      info.type          = 0;
      info.directory_ptr = idx;
      strlcpy(info.path, settings->libretro_directory, sizeof(info.path));
      if (!strcmp(label, "collection"))
      {
         rdb_entry_start_game_selection_ptr = idx;
         strlcpy(info.label, "deferred_core_list_set", sizeof(info.label));
      }
      else
         strlcpy(info.label, "deferred_core_list", sizeof(info.label));

      ret = menu_displaylist_push_list(&info, DISPLAYLIST_GENERIC);
   }

   return ret;
}
Exemplo n.º 2
0
static int action_iterate_menu_viewport(char *s, size_t len,
      const char *label, unsigned action, uint32_t hash)
{
   int stride_x = 1, stride_y = 1;
   menu_displaylist_info_t info     = {0};
   struct retro_game_geometry *geom = NULL;
   const char *base_msg             = NULL;
   unsigned type                    = 0;
   video_viewport_t *custom         = video_viewport_get_custom();
   menu_display_t *disp             = menu_display_get_ptr();
   menu_navigation_t *nav           = menu_navigation_get_ptr();
   menu_list_t *menu_list           = menu_list_get_ptr();
   settings_t *settings             = config_get_ptr();
   struct retro_system_av_info *av_info = video_viewport_get_system_av_info();

   if (!menu_list)
      return -1;

   menu_list_get_last_stack(menu_list, NULL, NULL, &type, NULL);

   geom = (struct retro_game_geometry*)&av_info->geometry;

   if (settings->video.scale_integer)
   {
      stride_x = geom->base_width;
      stride_y = geom->base_height;
   }

   switch (action)
   {
      case MENU_ACTION_UP:
         if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
         {
            custom->y      -= stride_y;
            custom->height += stride_y;
         }
         else if (custom->height >= (unsigned)stride_y)
            custom->height -= stride_y;

         event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);
         break;

      case MENU_ACTION_DOWN:
         if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
         {
            custom->y += stride_y;
            if (custom->height >= (unsigned)stride_y)
               custom->height -= stride_y;
         }
         else
            custom->height += stride_y;

         event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);
         break;

      case MENU_ACTION_LEFT:
         if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
         {
            custom->x     -= stride_x;
            custom->width += stride_x;
         }
         else if (custom->width >= (unsigned)stride_x)
            custom->width -= stride_x;

         event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);
         break;

      case MENU_ACTION_RIGHT:
         if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
         {
            custom->x += stride_x;
            if (custom->width >= (unsigned)stride_x)
               custom->width -= stride_x;
         }
         else
            custom->width += stride_x;

         event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);
         break;

      case MENU_ACTION_CANCEL:
         menu_list_pop_stack(menu_list);

         if (hash == MENU_LABEL_CUSTOM_VIEWPORT_2)
         {
            info.list          = menu_list->menu_stack;
            info.type          = MENU_SETTINGS_CUSTOM_VIEWPORT;
            info.directory_ptr = nav->selection_ptr;

            menu_displaylist_push_list(&info, DISPLAYLIST_INFO);
         }
         break;

      case MENU_ACTION_OK:
         menu_list_pop_stack(menu_list);

         if (type == MENU_SETTINGS_CUSTOM_VIEWPORT
               && !settings->video.scale_integer)
         {
            info.list          = menu_list->menu_stack;
            strlcpy(info.label,
                  menu_hash_to_str(MENU_LABEL_CUSTOM_VIEWPORT_2),
                  sizeof(info.label));
            info.type          = 0;
            info.directory_ptr = nav->selection_ptr;

            menu_displaylist_push_list(&info, DISPLAYLIST_INFO);
         }
         break;

      case MENU_ACTION_START:
         if (!settings->video.scale_integer)
         {
            video_viewport_t vp;
            video_driver_viewport_info(&vp);

            if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
            {
               custom->width  += custom->x;
               custom->height += custom->y;
               custom->x       = 0;
               custom->y       = 0;
            }
            else
            {
               custom->width   = vp.full_width - custom->x;
               custom->height  = vp.full_height - custom->y;
            }

            event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);
         }
         break;

      case MENU_ACTION_MESSAGE:
         if (disp)
            disp->msg_force = true;
         break;

      default:
         break;
   }

   menu_list_get_last_stack(menu_list, NULL, &label, &type, NULL);

   menu_driver_render();

   if (settings->video.scale_integer)
   {
      custom->x     = 0;
      custom->y     = 0;
      custom->width = ((custom->width + geom->base_width - 1) /
            geom->base_width) * geom->base_width;
      custom->height = ((custom->height + geom->base_height - 1) /
            geom->base_height) * geom->base_height;
      base_msg       = "Set scale";
       
      snprintf(s, len, "%s (%4ux%4u, %u x %u scale)",
            base_msg,
            custom->width, custom->height,
            custom->width / geom->base_width,
            custom->height / geom->base_height);
   }
   else
   {
      if (type == MENU_SETTINGS_CUSTOM_VIEWPORT)
         base_msg = menu_hash_to_str(MENU_LABEL_VALUE_CUSTOM_VIEWPORT_1);
      else if (hash == MENU_LABEL_CUSTOM_VIEWPORT_2)
         base_msg = menu_hash_to_str(MENU_LABEL_VALUE_CUSTOM_VIEWPORT_2);

      snprintf(s, len, "%s (%d, %d : %4ux%4u)",
            base_msg, custom->x, custom->y, custom->width, custom->height);
   }

   menu_driver_render_messagebox(s);

   if (!custom->width)
      custom->width = stride_x;
   if (!custom->height)
      custom->height = stride_y;

   aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
      (float)custom->width / custom->height;

   event_command(EVENT_CMD_VIDEO_APPLY_STATE_CHANGES);

   return 0;
}
Exemplo n.º 3
0
/**
 * main_entry:
 *
 * Main function of RetroArch.
 *
 * If HAVE_MAIN is not defined, will contain main loop and will not
 * be exited from until we exit the program. Otherwise, will
 * just do initialization.
 *
 * Returns: varies per platform.
 **/
int rarch_main(int argc, char *argv[], void *data)
{
   void *args                      = (void*)data;
   int ret                         = 0;
   settings_t *settings            = NULL;

   rarch_ctl(RARCH_CTL_PREINIT, NULL);

   frontend_driver_init_first(args);
   rarch_ctl(RARCH_CTL_INIT, NULL);

#ifdef HAVE_THREADS
   async_jobs = async_job_new();
#endif
   
   if (frontend_driver_is_inited())
   {
      ret = main_load_content(argc, argv, args,
            frontend_driver_environment_get_ptr());

      if (!ret)
         return ret;
   }

   event_command(EVENT_CMD_HISTORY_INIT);

   settings = config_get_ptr();

   if (settings->history_list_enable)
   {
      char *fullpath              = NULL;
      global_t *global            = global_get_ptr();
      rarch_system_info_t *system = NULL;
      
      runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);

      runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);

      if (global->inited.content || system->no_content)
         history_playlist_push(
               g_defaults.history,
               fullpath,
               settings->libretro,
               system ? &system->info : NULL);
   }

   ui_companion_driver_init_first();

#ifndef HAVE_MAIN
   do
   {
      unsigned sleep_ms = 0;
      ret = runloop_iterate(&sleep_ms);

      if (ret == 1 && sleep_ms > 0)
         retro_sleep(sleep_ms);
      runloop_ctl(RUNLOOP_CTL_DATA_ITERATE, NULL);
   }while(ret != -1);

   main_exit(args);
#endif

#ifdef HAVE_THREADS
   async_job_free(async_jobs);
   async_jobs = NULL;
#endif

   return 0;
}
Exemplo n.º 4
0
/**
 * do_state_checks:
 *
 * Checks for state changes in this frame.
 *
 * Returns: 1 if RetroArch is in pause mode, 0 otherwise.
 **/
static int do_state_checks(driver_t *driver, settings_t *settings,
      global_t *global, runloop_t *runloop, event_cmd_state_t *cmd)
{
   if (runloop->is_idle)
      return 1;

   if (cmd->screenshot_pressed)
      event_command(EVENT_CMD_TAKE_SCREENSHOT);

   if (cmd->mute_pressed)
      event_command(EVENT_CMD_AUDIO_MUTE_TOGGLE);

   if (cmd->osk_pressed)
      driver->keyboard_linefeed_enable = !driver->keyboard_linefeed_enable;
      
   if (cmd->volume_up_pressed)
      event_command(EVENT_CMD_VOLUME_UP);
   else if (cmd->volume_down_pressed)
      event_command(EVENT_CMD_VOLUME_DOWN);

#ifdef HAVE_NETPLAY
   if (driver->netplay_data)
      return do_netplay_state_checks(cmd->netplay_flip_pressed,
            cmd->fullscreen_toggle);
#endif

   check_pause(driver, settings, runloop,
         cmd->pause_pressed, cmd->frameadvance_pressed);

   if (do_pause_state_checks(
            runloop,
            cmd->pause_pressed,
            cmd->frameadvance_pressed,
            cmd->fullscreen_toggle,
            cmd->rewind_pressed))
      return 1;

   check_fast_forward_button(driver,
         cmd->fastforward_pressed,
         cmd->hold_pressed, cmd->old_hold_pressed);
   check_stateslots(settings, cmd->state_slot_increase,
         cmd->state_slot_decrease);

   if (cmd->save_state_pressed)
      event_command(EVENT_CMD_SAVE_STATE);
   else if (cmd->load_state_pressed)
      event_command(EVENT_CMD_LOAD_STATE);

   check_rewind(settings, global, runloop, cmd->rewind_pressed);
   check_slowmotion(settings, global, runloop,
         cmd->slowmotion_pressed);

   if (cmd->movie_record)
      check_movie(global);

   check_shader_dir(global, cmd->shader_next_pressed,
         cmd->shader_prev_pressed);

   if (cmd->disk_eject_pressed)
      event_command(EVENT_CMD_DISK_EJECT_TOGGLE);
   else if (cmd->disk_next_pressed)
      event_command(EVENT_CMD_DISK_NEXT);
   else if (cmd->disk_prev_pressed)
      event_command(EVENT_CMD_DISK_PREV);	  

   if (cmd->reset_pressed)
      event_command(EVENT_CMD_RESET);

   if (global->cheat)
   {
      if (cmd->cheat_index_plus_pressed)
         cheat_manager_index_next(global->cheat);
      else if (cmd->cheat_index_minus_pressed)
         cheat_manager_index_prev(global->cheat);
      else if (cmd->cheat_toggle_pressed)
         cheat_manager_toggle(global->cheat);
   }

   return 0;
}
Exemplo n.º 5
0
void recording_dump_frame(const void *data, unsigned width,
      unsigned height, size_t pitch)
{
   struct ffemu_video_data ffemu_data = {0};
   driver_t *driver = driver_get_ptr();
   global_t *global = global_get_ptr();

   if (!driver->recording_data)
      return;

   ffemu_data.pitch   = pitch;
   ffemu_data.width   = width;
   ffemu_data.height  = height;
   ffemu_data.data    = data;

   if (global->record.gpu_buffer)
   {
      struct video_viewport vp = {0};

      video_driver_viewport_info(&vp);

      if (!vp.width || !vp.height)
      {
         RARCH_WARN("%s \n",
               msg_hash_to_str(MSG_VIEWPORT_SIZE_CALCULATION_FAILED));
         event_command(EVENT_CMD_GPU_RECORD_DEINIT);

         recording_dump_frame(data, width, height, pitch);
         return;
      }

      /* User has resized. We kinda have a problem now. */
      if (vp.width != global->record.gpu_width ||
            vp.height != global->record.gpu_height)
      {
         RARCH_WARN("%s\n", msg_hash_to_str(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE));

         rarch_main_msg_queue_push_new(MSG_RECORDING_TERMINATED_DUE_TO_RESIZE, 1, 180, true);
         event_command(EVENT_CMD_RECORD_DEINIT);
         return;
      }

      /* Big bottleneck.
       * Since we might need to do read-backs asynchronously,
       * it might take 3-4 times before this returns true. */
      if (!video_driver_read_viewport(global->record.gpu_buffer))
            return;

      ffemu_data.pitch  = global->record.gpu_width * 3;
      ffemu_data.width  = global->record.gpu_width;
      ffemu_data.height = global->record.gpu_height;
      ffemu_data.data   = global->record.gpu_buffer +
         (ffemu_data.height - 1) * ffemu_data.pitch;

      ffemu_data.pitch  = -ffemu_data.pitch;
   }

   if (!global->record.gpu_buffer)
      ffemu_data.is_dupe = !data;

   if (driver->recording && driver->recording->push_video)
      driver->recording->push_video(driver->recording_data, &ffemu_data);
}
Exemplo n.º 6
0
/**
 * rarch_main_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 rarch_main_iterate(unsigned *sleep_ms)
{
   unsigned i;
   retro_input_t trigger_input;
   event_cmd_state_t    cmd;
   bool do_quit                    = false;
   static retro_input_t last_input = 0;
   driver_t *driver                = driver_get_ptr();
   settings_t *settings            = config_get_ptr();
   global_t   *global              = global_get_ptr();
   retro_input_t input             = input_keys_pressed(driver, settings, global);
   rarch_system_info_t *system     = rarch_system_info_get_ptr();
   retro_input_t old_input         = last_input;

   last_input                      = input;

   if (driver->flushing_input)
   {
      driver->flushing_input = false;
      if (input)
      {
         input = 0;

         /* If core was paused before entering menu, evoke
          * pause toggle to wake it up. */
         if (main_is_paused)
            BIT64_SET(input, RARCH_PAUSE_TOGGLE);
         driver->flushing_input = true;
      }
   }

   trigger_input = input & ~old_input;

   rarch_main_cmd_get_state(driver, settings, &cmd, input, old_input, trigger_input);

   if (time_to_exit(driver, global, system, &cmd))
      do_quit = true;

   if (system->frame_time.callback)
      rarch_update_frame_time(driver, settings->slowmotion_ratio, system);

   do_pre_state_checks(settings, global, &cmd);

#ifdef HAVE_OVERLAY
   rarch_main_iterate_linefeed_overlay(driver, settings);
#endif

   if (global->exec)
   {
      global->exec = false;
      do_quit      = true;
   }

   if (do_quit)
   {
      /* Quits out of RetroArch main loop.
       * On special case, loads dummy core 
       * instead of exiting RetroArch completely.
       * Aborts core shutdown if invoked.
       */
      if (global->core_shutdown_initiated
            && settings->load_dummy_on_core_shutdown)
      {
         if (!event_command(EVENT_CMD_PREPARE_DUMMY))
            return -1;

         system->shutdown = false;
         global->core_shutdown_initiated = false;

         return 0;
      }

      return -1;
   }
   
#ifdef HAVE_MENU
   if (menu_driver_alive())
   {
      menu_handle_t *menu = menu_driver_get_ptr();
      if (menu)
         if (menu_iterate(true, menu_input_frame(input, trigger_input)) == -1)
            rarch_main_set_state(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED);

      if (!input && settings->menu.pause_libretro)
        return 1;
      return rarch_limit_frame_time(settings->fastforward_ratio, sleep_ms);
   }
#endif

   if (do_state_checks(driver, settings, global, &cmd))
   {
      /* RetroArch has been paused. */
      driver->retro_ctx.poll_cb();
      *sleep_ms = 10;
      return 1;
   }

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

#ifdef HAVE_NETPLAY
   if (driver->netplay_data)
      netplay_pre_frame((netplay_t*)driver->netplay_data);
#endif

   if (global->bsv.movie)
      bsv_movie_set_frame_start(global->bsv.movie);

   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) && !driver->nonblock_state)
      rarch_sleep(settings->video.frame_delay);

   /* Run libretro for one frame. */
   pretro_run();

   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 (global->bsv.movie)
      bsv_movie_set_frame_end(global->bsv.movie);

#ifdef HAVE_NETPLAY
   if (driver->netplay_data)
      netplay_post_frame((netplay_t*)driver->netplay_data);
#endif

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

   return rarch_limit_frame_time(settings->fastforward_ratio, sleep_ms);
}
Exemplo n.º 7
0
static bool netplay_get_cmd(netplay_t *netplay)
{
   uint32_t cmd;
   uint32_t flip_frame;
   size_t cmd_size;

   if (!socket_receive_all_blocking(netplay->fd, &cmd, sizeof(cmd)))
      return false;

   cmd = ntohl(cmd);

   cmd_size = cmd & 0xffff;
   cmd      = cmd >> 16;

   switch (cmd)
   {
      case NETPLAY_CMD_FLIP_PLAYERS:
         if (cmd_size != sizeof(uint32_t))
         {
            RARCH_ERR("CMD_FLIP_PLAYERS recieved an unexpected command size.\n");
            return netplay_cmd_nak(netplay);
         }

         if (!socket_receive_all_blocking(netplay->fd, &flip_frame, sizeof(flip_frame)))
         {
            RARCH_ERR("Failed to receive CMD_FLIP_PLAYERS argument.\n");
            return netplay_cmd_nak(netplay);
         }

         flip_frame = ntohl(flip_frame);

         if (flip_frame < netplay->flip_frame)
         {
            RARCH_ERR("Host asked us to flip users in the past. Not possible ...\n");
            return netplay_cmd_nak(netplay);
         }

         netplay->flip ^= true;
         netplay->flip_frame = flip_frame;

         RARCH_LOG("Netplay users are flipped.\n");
         rarch_main_msg_queue_push("Netplay users are flipped.", 1, 180, false);

         return netplay_cmd_ack(netplay);

      case NETPLAY_CMD_SPECTATE:
         RARCH_ERR("NETPLAY_CMD_SPECTATE unimplemented.\n");
         return netplay_cmd_nak(netplay);

      case NETPLAY_CMD_DISCONNECT:
         warn_hangup();
         return netplay_cmd_ack(netplay);

      case NETPLAY_CMD_LOAD_SAVESTATE:
         RARCH_ERR("NETPLAY_CMD_LOAD_SAVESTATE unimplemented.\n");
         return netplay_cmd_nak(netplay);

      case NETPLAY_CMD_PAUSE:
         event_command(EVENT_CMD_PAUSE);
         return netplay_cmd_ack(netplay);

      case NETPLAY_CMD_RESUME:
         event_command(EVENT_CMD_UNPAUSE);
         return netplay_cmd_ack(netplay);

      default: break;
   }

   RARCH_ERR("Unknown netplay command received.\n");
   return netplay_cmd_nak(netplay);
}
Exemplo n.º 8
0
/**
 * rarch_main_deinit:
 *
 * Deinitializes the program.
 **/
void rarch_main_deinit(void)
{
   global_t *global = global_get_ptr();

   event_command(EVENT_CMD_NETPLAY_DEINIT);
   event_command(EVENT_CMD_COMMAND_DEINIT);

   if (global->sram.use)
      event_command(EVENT_CMD_AUTOSAVE_DEINIT);

   event_command(EVENT_CMD_RECORD_DEINIT);
   event_command(EVENT_CMD_SAVEFILES);

   event_command(EVENT_CMD_REWIND_DEINIT);
   event_command(EVENT_CMD_CHEATS_DEINIT);
   event_command(EVENT_CMD_BSV_MOVIE_DEINIT);

   event_command(EVENT_CMD_AUTOSAVE_STATE);

   event_command(EVENT_CMD_CORE_DEINIT);

   event_command(EVENT_CMD_TEMPORARY_CONTENT_DEINIT);
   event_command(EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT);
   event_command(EVENT_CMD_SAVEFILES_DEINIT);

   global->inited.main = false;
}
Exemplo n.º 9
0
void cmd_load_state(void)
{
   event_command(EVENT_CMD_LOAD_STATE);
}
Exemplo n.º 10
0
void cmd_take_screenshot(void)
{
   event_command(EVENT_CMD_TAKE_SCREENSHOT);
}
Exemplo n.º 11
0
void cmd_save_state(void)
{
   event_command(EVENT_CMD_SAVE_STATE);
}
Exemplo n.º 12
0
void cmd_savefiles(void)
{
   event_command(EVENT_CMD_SAVEFILES);
}
Exemplo n.º 13
0
/**
 * event_command:
 * @cmd                  : Event command index.
 *
 * Performs program event command with index @cmd.
 *
 * Returns: true (1) on success, otherwise false (0).
 **/
bool event_command(enum event_command cmd)
{
   unsigned i                = 0;
   bool boolean              = false;
   global_t  *global         = global_get_ptr();
   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_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO);

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

               video_driver_set_video_mode(width, height, true);

               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_command(EVENT_CMD_LOAD_CORE);
#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_command(EVENT_CMD_LOAD_CONTENT_PERSIST);
#else
            char *fullpath = NULL;
            runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath);
            rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH,
                  (void*)settings->libretro);
            rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)fullpath);
            event_command(EVENT_CMD_QUIT);
#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_command(EVENT_CMD_LOAD_CORE_DEINIT);
         {
#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))
               event_update_system_info(system, ptr);
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE:
         event_command(EVENT_CMD_LOAD_CORE_PERSIST);
#ifndef HAVE_DYNAMIC
         event_command(EVENT_CMD_QUIT);
#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
         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_command(EVENT_CMD_REINIT);

            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_new(MSG_RESET, 1, 120, true);

#ifdef HAVE_CHEEVOS
         cheevos_set_cheats();
#endif
         core.retro_reset();

         /* bSNES since v073r01 resets controllers to JOYPAD
          * after a reset, so just enforce it here. */
         event_command(EVENT_CMD_CONTROLLERS_INIT);
         break;
      case EVENT_CMD_SAVE_STATE:
         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_command(EVENT_CMD_LOAD_CORE_DEINIT);
         break;
      case EVENT_CMD_QUIT:
         rarch_ctl(RARCH_CTL_QUIT, NULL);
         break;
      case EVENT_CMD_REINIT:
         {
            const struct retro_hw_render_callback *hw_render =
               (const struct retro_hw_render_callback*)video_driver_callback();

            if (hw_render->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_command(EVENT_CMD_RESET_CONTEXT);
            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_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE);
#endif
         }
         break;
      case EVENT_CMD_CHEATS_DEINIT:
         cheat_manager_state_free();
         break;
      case EVENT_CMD_CHEATS_INIT:
         event_command(EVENT_CMD_CHEATS_DEINIT);
         event_init_cheats();
         break;
      case EVENT_CMD_CHEATS_APPLY:
         cheat_manager_apply_cheats();
         break;
      case EVENT_CMD_REMAPPING_DEINIT:
         break;
      case EVENT_CMD_REMAPPING_INIT:
         event_command(EVENT_CMD_REMAPPING_DEINIT);
         event_init_remapping();
         break;
      case EVENT_CMD_REWIND_DEINIT:
#ifdef HAVE_NETPLAY
         if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
            return false;
#endif
         state_manager_event_deinit();
         break;
      case EVENT_CMD_REWIND_INIT:
#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_command(EVENT_CMD_REWIND_INIT);
         else
            event_command(EVENT_CMD_REWIND_DEINIT);
         break;
      case EVENT_CMD_AUTOSAVE_DEINIT:
#ifdef HAVE_THREADS
         autosave_event_deinit();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_INIT:
         event_command(EVENT_CMD_AUTOSAVE_DEINIT);
#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_command(EVENT_CMD_OVERLAY_DEINIT);
#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_command(EVENT_CMD_DSP_FILTER_DEINIT);
         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_command(EVENT_CMD_HISTORY_DEINIT);
         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_command(EVENT_CMD_HISTORY_DEINIT);
         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:
         runloop_ctl(RUNLOOP_CTL_CURRENT_CORE_LIST_FREE, NULL);
         break;
      case EVENT_CMD_CORE_INFO_INIT:
         event_command(EVENT_CMD_CORE_INFO_DEINIT);

         if (*settings->libretro_directory)
            runloop_ctl(RUNLOOP_CTL_CURRENT_CORE_LIST_INIT, NULL);
         break;
      case EVENT_CMD_CORE_DEINIT:
         {
            struct retro_hw_render_callback *cb = video_driver_callback();
            event_deinit_core(true);

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

            break;
         }
      case EVENT_CMD_CORE_INIT:
         if (!event_init_core())
            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_DRIVERS_DEINIT:
         {
            int flags = DRIVERS_CMD_ALL;
            driver_ctl(RARCH_DRIVER_CTL_UNINIT, &flags);
         }
         break;
      case EVENT_CMD_DRIVERS_INIT:
         {
            int flags = DRIVERS_CMD_ALL;
            driver_ctl(RARCH_DRIVER_CTL_INIT, &flags);
         }
         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:
         event_command(EVENT_CMD_DRIVERS_DEINIT);
         event_command(EVENT_CMD_DRIVERS_INIT);
         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_RESUME:
         rarch_ctl(RARCH_CTL_MENU_RUNNING_FINISHED, NULL);
         break;
      case EVENT_CMD_RESTART_RETROARCH:
         {
#if defined(GEKKO) && defined(HW_RVL)
            char new_path[PATH_MAX_LENGTH];
            fill_pathname_join(new_path, g_defaults.dir.core, SALAMANDER_FILE, sizeof(new_path));
            runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, new_path);
#endif
            frontend_driver_set_fork(true, 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_command(EVENT_CMD_AUDIO_STOP);

            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_command(EVENT_CMD_AUDIO_START);
         }
         break;
      case EVENT_CMD_PAUSE_TOGGLE:
         boolean = runloop_ctl(RUNLOOP_CTL_IS_PAUSED,  NULL);
         boolean = !boolean;
         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_UNPAUSE:
         boolean = false;

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

         runloop_ctl(RUNLOOP_CTL_SET_PAUSED, &boolean);
         event_command(EVENT_CMD_PAUSE_CHECKS);
         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_command(EVENT_CMD_AUDIO_STOP);
            else
               event_command(EVENT_CMD_AUDIO_START);
         }
         else
         {
            if (settings->menu.pause_libretro)
               event_command(EVENT_CMD_AUDIO_START);
         }
#endif
         break;
      case EVENT_CMD_SHADER_DIR_DEINIT:
         runloop_ctl(RUNLOOP_CTL_SHADER_DIR_DEINIT, NULL);
         break;
      case EVENT_CMD_SHADER_DIR_INIT:
         event_command(EVENT_CMD_SHADER_DIR_DEINIT);

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

         for (i = 0; i < global->savefiles->size; i++)
         {
            unsigned type    = global->savefiles->elems[i].attr.i;
            const char *path = global->savefiles->elems[i].data;
            RARCH_LOG("%s #%u %s \"%s\".\n",
                  msg_hash_to_str(MSG_SAVING_RAM_TYPE),
                  type,
                  msg_hash_to_str(MSG_TO),
                  path);
            save_ram_file(path, type);
         }
         return true;
      case EVENT_CMD_SAVEFILES_DEINIT:
         if (!global)
            break;

         if (global->savefiles)
            string_list_free(global->savefiles);
         global->savefiles = NULL;
         break;
      case EVENT_CMD_SAVEFILES_INIT:
         global->sram.use = global->sram.use && !global->sram.save_disable
#ifdef HAVE_NETPLAY
            && (!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_command(EVENT_CMD_AUTOSAVE_INIT);
         break;
      case EVENT_CMD_BSV_MOVIE_DEINIT:
         bsv_movie_ctl(BSV_MOVIE_CTL_DEINIT, NULL);
         break;
      case EVENT_CMD_BSV_MOVIE_INIT:
         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);
         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_command(EVENT_CMD_NETPLAY_DEINIT);
#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_command(EVENT_CMD_REINIT);
         break;
      case EVENT_CMD_COMMAND_DEINIT:
         input_driver_ctl(RARCH_INPUT_CTL_COMMAND_DEINIT, NULL);
         break;
      case EVENT_CMD_COMMAND_INIT:
         event_command(EVENT_CMD_COMMAND_DEINIT);
         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_command(EVENT_CMD_REMOTE_DEINIT);
         input_driver_ctl(RARCH_INPUT_CTL_REMOTE_INIT, NULL);
         break;
      case EVENT_CMD_TEMPORARY_CONTENT_DEINIT:
         content_temporary_free();
         break;
      case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT:
         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_EJECT_TOGGLE:
         if (info && info->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &info->disk_control;

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

            if (!control)
               return false;

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

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

            if (!control)
               return false;

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

            event_check_disk_prev(control);
         }
         else
            runloop_msg_queue_push_new(
                  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:
         {
            static bool grab_mouse_state  = false;
            bool grab_mouse_state_tmp;

            grab_mouse_state = !grab_mouse_state;

            if (!input_driver_grab_mouse(grab_mouse_state))
               return false;

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

            grab_mouse_state_tmp = !grab_mouse_state;
            video_driver_ctl(RARCH_DISPLAY_CTL_SHOW_MOUSE, &grab_mouse_state_tmp);
         }
         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_NONE:
      default:
         return false;
   }

   return true;
}
Exemplo n.º 14
0
/**
 * rarch_main_init:
 * @argc                 : Count of (commandline) arguments.
 * @argv                 : (Commandline) arguments. 
 *
 * Initializes the program.
 *
 * Returns: 0 on success, otherwise 1 if there was an error.
 **/
int rarch_main_init(int argc, char *argv[])
{
   int sjlj_ret;
   global_t     *global = global_get_ptr();

   init_state();

   if ((sjlj_ret = setjmp(global->error_sjlj_context)) > 0)
   {
      RARCH_ERR("Fatal error received in: \"%s\"\n", global->error_string);
      return sjlj_ret;
   }
   global->inited.error = true;
   global->log_file     = stderr;
   parse_input(argc, argv);

   if (global->verbosity)
   {
      char str[PATH_MAX_LENGTH] = {0};

      RARCH_LOG_OUTPUT("=== Build =======================================");
      rarch_info_get_capabilities(RARCH_CAPABILITIES_CPU, str, sizeof(str));
      fprintf(stderr, "%s", str);
      fprintf(stderr, "Built: %s\n", __DATE__);
      RARCH_LOG_OUTPUT("Version: %s\n", PACKAGE_VERSION);
#ifdef HAVE_GIT_VERSION
      RARCH_LOG_OUTPUT("Git: %s\n", rarch_git_version);
#endif
      RARCH_LOG_OUTPUT("=================================================\n");
   }

   rarch_ctl(RARCH_ACTION_STATE_VALIDATE_CPU_FEATURES, NULL);
   config_load();

   {
      settings_t *settings = config_get_ptr();

      if (settings && (settings->multimedia.builtin_mediaplayer_enable ||
            settings->multimedia.builtin_imageviewer_enable))
      {
         switch (rarch_path_is_media_type(global->path.fullpath))
         {
            case RARCH_CONTENT_MOVIE:
            case RARCH_CONTENT_MUSIC:
               if (settings->multimedia.builtin_mediaplayer_enable)
               {
#ifdef HAVE_FFMPEG
                  global->has_set.libretro              = false;
                  global->inited.core.type              = CORE_TYPE_FFMPEG;
#endif
               }
               break;
#ifdef HAVE_IMAGEVIEWER
            case RARCH_CONTENT_IMAGE:
               if (settings->multimedia.builtin_imageviewer_enable)
               {
                  global->has_set.libretro              = false;
                  global->inited.core.type              = CORE_TYPE_IMAGEVIEWER;
               }
               break;
#endif
            default:
               break;
         }
      }
   }

   init_libretro_sym(global->inited.core.type);
   rarch_system_info_init();

   init_drivers_pre();

   if (!event_command(EVENT_CMD_CORE_INIT))
      goto error;

   event_command(EVENT_CMD_DRIVERS_INIT);
   event_command(EVENT_CMD_COMMAND_INIT);
   event_command(EVENT_CMD_REWIND_INIT);
   event_command(EVENT_CMD_CONTROLLERS_INIT);
   event_command(EVENT_CMD_RECORD_INIT);
   event_command(EVENT_CMD_CHEATS_INIT);
   event_command(EVENT_CMD_REMAPPING_INIT);

   event_command(EVENT_CMD_SAVEFILES_INIT);
#if defined(GEKKO) && defined(HW_RVL)
   {
      settings_t *settings = config_get_ptr();

      if (settings)
      {
         event_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO);
         video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx);
      }

      unsigned width = 0, height = 0;

      (void)width;
      (void)height;

      width = global->console.screen.resolutions.width;
      height = global->console.screen.resolutions.height;
      video_driver_set_video_mode(width, height, true);

      char msg[PATH_MAX_LENGTH] = {0};
      snprintf(msg, sizeof(msg),"Resolution: %dx%d",width, height);
      rarch_main_msg_queue_push(msg, 1, 100, true);
   }
#endif

   global->inited.error = false;
   global->inited.main  = true;
   return 0;

error:
   event_command(EVENT_CMD_CORE_DEINIT);

   global->inited.main  = false;
   return 1;
}
Exemplo n.º 15
0
static bool ctr_frame(void* data, const void* frame,
      unsigned width, unsigned height, 
      uint64_t frame_count,
      unsigned pitch, const char* msg)
{
   uint32_t diff;
   static uint64_t currentTick,lastTick;
   ctr_video_t       *ctr  = (ctr_video_t*)data;
   settings_t   *settings  = config_get_ptr();
   static float        fps = 0.0;
   static int total_frames = 0;
   static int       frames = 0;
   static struct retro_perf_counter ctrframe_f = {0};
   uint32_t state_tmp;
   touchPosition state_tmp_touch;

   extern bool select_pressed;

   if (!width || !height)
   {
      gspWaitForEvent(GSPEVENT_VBlank0, true);
      return true;
   }

   if(!aptMainLoop())
   {
      event_command(EVENT_CMD_QUIT);
      return true;
   }

   if (select_pressed)
   {
      event_command(EVENT_CMD_QUIT);
      return true;
   }

   state_tmp = hidKeysDown();
   hidTouchRead(&state_tmp_touch);
   if((state_tmp & KEY_TOUCH) && (state_tmp_touch.py < 120))
   {
      Handle lcd_handle;
      u8 not_2DS;
      extern PrintConsole* currentConsole;

      gfxBottomFramebuffers[0] = ctr->lcd_buttom_on ? (u8*)ctr->empty_framebuffer:
                                                      (u8*)currentConsole->frameBuffer;

      CFGU_GetModelNintendo2DS(&not_2DS);
      if(not_2DS && srvGetServiceHandle(&lcd_handle, "gsp::Lcd") >= 0)
      {
         u32 *cmdbuf = getThreadCommandBuffer();
         cmdbuf[0] = ctr->lcd_buttom_on? 0x00120040:  0x00110040;
         cmdbuf[1] = 2;
         svcSendSyncRequest(lcd_handle);
         svcCloseHandle(lcd_handle);
      }

      ctr->lcd_buttom_on = !ctr->lcd_buttom_on;
   }

   svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000);
   svcClearEvent(gspEvents[GSPEVENT_P3D]);
   svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000);
   svcClearEvent(gspEvents[GSPEVENT_PPF]);

   frames++;

   if (ctr->vsync)
      svcWaitSynchronization(gspEvents[GSPEVENT_VBlank0], U64_MAX);

   svcClearEvent(gspEvents[GSPEVENT_VBlank0]);

   currentTick = svcGetSystemTick();
   diff        = currentTick - lastTick;
   if(diff > CTR_CPU_TICKS_PER_SECOND)
   {
      fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff);
      lastTick = currentTick;
      frames = 0;
   }

//   extern u32 __linear_heap_size;
//   extern u32 gpuCmdBufOffset;
//   extern u32 __heap_size;
//   printf("0x%08X 0x%08X 0x%08X\r", __heap_size, gpuCmdBufOffset, (__linear_heap_size - linearSpaceFree() +0x3FF) & ~0x3FF);
//   printf("fps: %8.4f frames: %i (%X)\r", fps, total_frames++, (__linear_heap_size - linearSpaceFree()));
   printf("fps: %8.4f frames: %i\r", fps, total_frames++);
   fflush(stdout);

   rarch_perf_init(&ctrframe_f, "ctrframe_f");
   retro_perf_start(&ctrframe_f);

   if (ctr->should_resize)
      ctr_update_viewport(ctr);

   ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000,
                    (u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
                    0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000,
                    (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
                    0x201);

   GPUCMD_SetBufferOffset(0);

   if (width > ctr->texture_width)
      width = ctr->texture_width;
   if (height > ctr->texture_height)
      height = ctr->texture_height;

   if(frame)
   {
      if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x40000000)) /* frame in linear memory */
         && !((u32)frame & 0x7F)                                         /* 128-byte aligned */
         && !((pitch) & 0xF))                                            /* 16-byte aligned */
      {
         /* can copy the buffer directly with the GPU */
         ctrGuCopyImage(false, frame, pitch / (ctr->rgb32? 4: 2), height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false,
                        ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565,  true);
      }
      else
      {
         int i;
         uint8_t      *dst = (uint8_t*)ctr->texture_linear;
         const uint8_t *src = frame;

         for (i = 0; i < height; i++)
         {
            memcpy(dst, src, width * (ctr->rgb32? 4: 2));
            dst += ctr->texture_width * (ctr->rgb32? 4: 2);
            src += pitch;
         }
         GSPGPU_FlushDataCache(ctr->texture_linear,
                               ctr->texture_width * ctr->texture_height * (ctr->rgb32? 4: 2));

         ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->texture_height, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565, false,
                        ctr->texture_swizzled, ctr->texture_width, ctr->rgb32 ? CTRGU_RGBA8: CTRGU_RGB565,  true);

      }

   }

   ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height,
                  (ctr->smooth? GPU_TEXTURE_MAG_FILTER(GPU_LINEAR)  | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR)
                              : GPU_TEXTURE_MAG_FILTER(GPU_NEAREST) | GPU_TEXTURE_MIN_FILTER(GPU_NEAREST)) |
                  GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
                  ctr->rgb32 ? GPU_RGBA8: GPU_RGB565);

   ctr->frame_coords->u = width;
   ctr->frame_coords->v = height;
   GSPGPU_FlushDataCache(ctr->frame_coords, sizeof(ctr_vertex_t));

   ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords));
   ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1);

   /* ARGB --> RGBA */
   if (ctr->rgb32)
   {
      GPU_SetTexEnv(0,
                    GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, 0),
                    GPU_TEVSOURCES(GPU_PRIMARY_COLOR, GPU_PRIMARY_COLOR, 0),
                    GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_G, 0, 0),
                    GPU_TEVOPERANDS(0, 0, 0),
                    GPU_MODULATE, GPU_MODULATE,
                    0x0000FF);
      GPU_SetTexEnv(1,
                    GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS),
                    GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0),
                    GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_B, 0, 0),
                    GPU_TEVOPERANDS(0, 0, 0),
                    GPU_MULTIPLY_ADD, GPU_MODULATE,
                    0x00FF00);
      GPU_SetTexEnv(2,
                    GPU_TEVSOURCES(GPU_TEXTURE0, GPU_CONSTANT, GPU_PREVIOUS),
                    GPU_TEVSOURCES(GPU_PREVIOUS, GPU_PREVIOUS, 0),
                    GPU_TEVOPERANDS(GPU_TEVOP_RGB_SRC_ALPHA, 0, 0),
                    GPU_TEVOPERANDS(0, 0, 0),
                    GPU_MULTIPLY_ADD, GPU_MODULATE,
                    0xFF0000);
   }

   GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1);

   /* restore */
   if (ctr->rgb32)
   {
      GPU_SetTexEnv(0,
                    GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0),
                    GPU_TEVSOURCES(GPU_TEXTURE0, GPU_PRIMARY_COLOR, 0),
                    GPU_TEVOPERANDS(0, 0, 0),
                    GPU_TEVOPERANDS(0, 0, 0),
                    GPU_MODULATE, GPU_MODULATE,
                    0xFFFFFFFF);
      GPU_SetTexEnv(1, GPU_PREVIOUS,GPU_PREVIOUS, 0, 0, 0, 0, 0);
      GPU_SetTexEnv(2, GPU_PREVIOUS,GPU_PREVIOUS, 0, 0, 0, 0, 0);
   }

   if (ctr->menu_texture_enable)
   {

      GSPGPU_FlushDataCache(ctr->menu.texture_linear,
                            ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t));

      ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false,
                     ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444,  true);

      ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height,
                     GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
                     GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
                     GPU_RGBA4);


      ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords));
      ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->menu.scale_vector, 1);
      GPU_DrawArray(GPU_GEOMETRY_PRIM, 0, 1);
   }

   GPU_FinishDrawing();
   GPUCMD_Finalize();
   ctrGuFlushAndRun(true);

   ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8,
                        gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);

   gfxSwapBuffersGpu();
   retro_perf_stop(&ctrframe_f);

   return true;
}
Exemplo n.º 16
0
bool rarch_ctl(enum rarch_ctl_state state, void *data)
{
   driver_t *driver     = driver_get_ptr();
   global_t *global     = global_get_ptr();
   settings_t *settings = config_get_ptr();
   rarch_system_info_t *system = rarch_system_info_get_ptr();

   switch(state)
   {
      case RARCH_ACTION_STATE_REPLACE_CONFIG:
         {
            char *path = (char*)data;

            if (!path)
               return false;

            /* If config file to be replaced is the same as the
             * current config file, exit. */
            if (!strcmp(path, global->path.config))
               return false;

            if (settings->config_save_on_exit && *global->path.config)
               config_save_file(global->path.config);

            strlcpy(global->path.config, path, sizeof(global->path.config));
            global->block_config_read = false;
            *settings->libretro = '\0'; /* Load core in new config. */
         }
         event_command(EVENT_CMD_PREPARE_DUMMY);
         return true;
      case RARCH_ACTION_STATE_MENU_RUNNING:
#ifdef HAVE_MENU
         menu_driver_toggle(true);
#endif
#ifdef HAVE_OVERLAY
         if (settings->input.overlay_hide_in_menu)
            event_command(EVENT_CMD_OVERLAY_DEINIT);
#endif
         break;
      case RARCH_ACTION_STATE_LOAD_CONTENT:
#ifdef HAVE_MENU
         /* If content loading fails, we go back to menu. */
         if (!menu_load_content(CORE_TYPE_PLAIN))
            rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL);
#endif
         if (driver->frontend_ctx && driver->frontend_ctx->content_loaded)
            driver->frontend_ctx->content_loaded();
         break;
#ifdef HAVE_FFMPEG
      case RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG:
#ifdef HAVE_MENU
         /* If content loading fails, we go back to menu. */
         if (!menu_load_content(CORE_TYPE_FFMPEG))
            rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL);
#endif
         if (driver->frontend_ctx && driver->frontend_ctx->content_loaded)
            driver->frontend_ctx->content_loaded();
         break;
#endif
      case RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER:
#ifdef HAVE_MENU
         /* If content loading fails, we go back to menu. */
         if (!menu_load_content(CORE_TYPE_IMAGEVIEWER))
            rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING, NULL);
#endif
         if (driver->frontend_ctx && driver->frontend_ctx->content_loaded)
            driver->frontend_ctx->content_loaded();
         break;
      case RARCH_ACTION_STATE_MENU_RUNNING_FINISHED:
#ifdef HAVE_MENU
         menu_driver_toggle(false);
#endif
         video_driver_set_texture_enable(false, false);
#ifdef HAVE_OVERLAY
         if (settings && settings->input.overlay_hide_in_menu)
            event_command(EVENT_CMD_OVERLAY_INIT);
#endif
         break;
      case RARCH_ACTION_STATE_QUIT:
         if (global)
            system->shutdown = true;
         rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL);
         break;
      case RARCH_ACTION_STATE_FORCE_QUIT:
         rarch_ctl(RARCH_ACTION_STATE_QUIT, NULL);
         break;
      case RARCH_ACTION_STATE_VALIDATE_CPU_FEATURES:
         {
            uint64_t cpu = retro_get_cpu_features();
            (void)cpu;

#ifdef __SSE__
            if (!(cpu & RETRO_SIMD_SSE))
               FAIL_CPU("SSE");
#endif
#ifdef __SSE2__
            if (!(cpu & RETRO_SIMD_SSE2))
               FAIL_CPU("SSE2");
#endif
#ifdef __AVX__
            if (!(cpu & RETRO_SIMD_AVX))
               FAIL_CPU("AVX");
#endif
         }
         break;
      case RARCH_ACTION_STATE_VERIFY_API_VERSION:
         RARCH_LOG("Version of libretro API: %u\n", core.retro_api_version());
         RARCH_LOG("Compiled against API: %u\n",    RETRO_API_VERSION);

         if (core.retro_api_version() != RETRO_API_VERSION)
            RARCH_WARN("%s\n", msg_hash_to_str(MSG_LIBRETRO_ABI_BREAK));
         break;
      case RARCH_ACTION_STATE_FILL_PATHNAMES:
         rarch_init_savefile_paths();
         strlcpy(global->bsv.movie_path, global->name.savefile,
               sizeof(global->bsv.movie_path));

         if (!*global->name.base)
            return false;

         if (!*global->name.ups)
            fill_pathname_noext(global->name.ups, global->name.base, ".ups",
                  sizeof(global->name.ups));
         if (!*global->name.bps)
            fill_pathname_noext(global->name.bps, global->name.base, ".bps",
                  sizeof(global->name.bps));
         if (!*global->name.ips)
            fill_pathname_noext(global->name.ips, global->name.base, ".ips",
                  sizeof(global->name.ips));
         break;
      case RARCH_ACTION_STATE_NONE:
      default:
         return false;
   }

   return true;
}
Exemplo n.º 17
0
/**
 * main_entry:
 *
 * Main function of RetroArch.
 *
 * If HAVE_MAIN is not defined, will contain main loop and will not
 * be exited from until we exit the program. Otherwise, will 
 * just do initialization.
 *
 * Returns: varies per platform.
 **/
int rarch_main(int argc, char *argv[], void *data)
{
   void *args                      = (void*)data;
   int ret                         = 0;
   settings_t *settings            = NULL;
   driver_t *driver                = NULL;

   rarch_main_alloc();

   driver = driver_get_ptr();

   if (driver)
      driver->frontend_ctx = (frontend_ctx_driver_t*)frontend_ctx_init_first();

   if (!driver || !driver->frontend_ctx)
      RARCH_WARN("Frontend context could not be initialized.\n");

   if (driver->frontend_ctx && driver->frontend_ctx->init)
      driver->frontend_ctx->init(args);

   rarch_main_new();

   if (driver->frontend_ctx)
   {
      if (!(ret = (main_load_content(argc, argv, args,
                     driver->frontend_ctx->environment_get,
                     driver->frontend_ctx->process_args))))
         return ret;
   }

   event_command(EVENT_CMD_HISTORY_INIT);

   settings = config_get_ptr();

   if (settings->history_list_enable)
   {
      global_t *global             = global_get_ptr();
      rarch_system_info_t *system = rarch_system_info_get_ptr();

      if (global->inited.content || system->no_content)
         history_playlist_push(
               g_defaults.history,
               global->path.fullpath,
               settings->libretro,
               system ? &system->info : NULL);
   }

   if (driver)
      driver->ui_companion = (ui_companion_driver_t*)ui_companion_init_first();

   if (driver->ui_companion && driver->ui_companion->toggle)
   {
      if (settings->ui.companion_start_on_boot)
         driver->ui_companion->toggle(driver->ui_companion_data);
   }

#ifndef HAVE_MAIN
   do{
      ret = rarch_main_iterate();
      
      if (ret == 1)
         rarch_sleep(10);
      rarch_main_data_iterate();
   }while(ret != -1);

   main_exit(args);
#endif

   return 0;
}
Exemplo n.º 18
0
static void rarch_init_savefile_paths(void)
{
   global_t            *global = global_get_ptr();
   rarch_system_info_t *system = rarch_system_info_get_ptr();

   event_command(EVENT_CMD_SAVEFILES_DEINIT);

   global->savefiles = string_list_new();
   rarch_assert(global->savefiles);

   if (*global->subsystem)
   {
      /* For subsystems, we know exactly which RAM types are supported. */

      unsigned i, j;
      const struct retro_subsystem_info *info =
         libretro_find_subsystem_info(
               system->special,
               system->num_special,
               global->subsystem);

      /* We'll handle this error gracefully later. */
      unsigned num_content = min(info ? info->num_roms : 0,
            global->subsystem_fullpaths ?
            global->subsystem_fullpaths->size : 0);

      bool use_sram_dir = path_is_directory(global->dir.savefile);

      for (i = 0; i < num_content; i++)
      {
         for (j = 0; j < info->roms[i].num_memory; j++)
         {
            union string_list_elem_attr attr;
            char path[PATH_MAX_LENGTH] = {0};
            char ext[32] = {0};
            const struct retro_subsystem_memory_info *mem =
               (const struct retro_subsystem_memory_info*)
               &info->roms[i].memory[j];

            snprintf(ext, sizeof(ext), ".%s", mem->extension);

            if (use_sram_dir)
            {
               /* Redirect content fullpath to save directory. */
               strlcpy(path, global->dir.savefile, sizeof(path));
               fill_pathname_dir(path,
                     global->subsystem_fullpaths->elems[i].data, ext,
                     sizeof(path));
            }
            else
            {
               fill_pathname(path, global->subsystem_fullpaths->elems[i].data,
                     ext, sizeof(path));
            }

            attr.i = mem->type;
            string_list_append(global->savefiles, path, attr);
         }
      }

      /* Let other relevant paths be inferred from the main SRAM location. */
      if (!global->has_set.save_path)
         fill_pathname_noext(global->name.savefile, global->name.base, ".srm",
               sizeof(global->name.savefile));
      if (path_is_directory(global->name.savefile))
      {
         fill_pathname_dir(global->name.savefile, global->name.base, ".srm",
               sizeof(global->name.savefile));
         RARCH_LOG("%s \"%s\".\n",
               msg_hash_to_str(MSG_REDIRECTING_SAVEFILE_TO),
               global->name.savefile);
      }
   }
   else
   {
      union string_list_elem_attr attr;
      char savefile_name_rtc[PATH_MAX_LENGTH] = {0};

      attr.i = RETRO_MEMORY_SAVE_RAM;
      string_list_append(global->savefiles, global->name.savefile, attr);

      /* Infer .rtc save path from save ram path. */
      attr.i = RETRO_MEMORY_RTC;
      fill_pathname(savefile_name_rtc,
            global->name.savefile, ".rtc", sizeof(savefile_name_rtc));
      string_list_append(global->savefiles, savefile_name_rtc, attr);
   }
}
Exemplo n.º 19
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;
}
Exemplo n.º 20
0
/**
 * recording_init:
 *
 * Initializes recording.
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
bool recording_init(void)
{
   char recording_file[PATH_MAX_LENGTH] = {0};
   struct ffemu_params params           = {0};
   global_t *global                     = global_get_ptr();
   driver_t *driver                     = driver_get_ptr();
   settings_t *settings                 = config_get_ptr();
   struct retro_system_av_info *av_info = video_viewport_get_system_av_info();
   const struct retro_hw_render_callback *hw_render = 
      (const struct retro_hw_render_callback*)video_driver_callback();

   if (!global->record.enable)
      return false;

   if (global->inited.core.type == CORE_TYPE_DUMMY)
   {
      RARCH_WARN(msg_hash_to_str(MSG_USING_LIBRETRO_DUMMY_CORE_RECORDING_SKIPPED));
      return false;
   }

   if (!settings->video.gpu_record && hw_render->context_type)
   {
      RARCH_WARN("%s.\n", msg_hash_to_str(MSG_HW_RENDERED_MUST_USE_POSTSHADED_RECORDING));
      return false;
   }

   RARCH_LOG("%s: FPS: %.4f, Sample rate: %.4f\n",
         msg_hash_to_str(MSG_CUSTOM_TIMING_GIVEN),
         (float)av_info->timing.fps,
         (float)av_info->timing.sample_rate);

   strlcpy(recording_file, global->record.path, sizeof(recording_file));

   if (global->record.use_output_dir)
      fill_pathname_join(recording_file,
            global->record.output_dir,
            global->record.path, sizeof(recording_file));

   params.out_width  = av_info->geometry.base_width;
   params.out_height = av_info->geometry.base_height;
   params.fb_width   = av_info->geometry.max_width;
   params.fb_height  = av_info->geometry.max_height;
   params.channels   = 2;
   params.filename   = recording_file;
   params.fps        = av_info->timing.fps;
   params.samplerate = av_info->timing.sample_rate;
   params.pix_fmt    = (video_driver_get_pixel_format() == RETRO_PIXEL_FORMAT_XRGB8888) ?
      FFEMU_PIX_ARGB8888 : FFEMU_PIX_RGB565;
   params.config     = NULL;
   
   if (*global->record.config)
      params.config = global->record.config;

   if (settings->video.gpu_record && driver->video->read_viewport)
   {
      struct video_viewport vp = {0};

      video_driver_viewport_info(&vp);

      if (!vp.width || !vp.height)
      {
         RARCH_ERR("Failed to get viewport information from video driver. "
               "Cannot start recording ...\n");
         return false;
      }

      params.out_width  = vp.width;
      params.out_height = vp.height;
      params.fb_width   = next_pow2(vp.width);
      params.fb_height  = next_pow2(vp.height);

      if (settings->video.force_aspect &&
            (video_driver_get_aspect_ratio() > 0.0f))
         params.aspect_ratio  = video_driver_get_aspect_ratio();
      else
         params.aspect_ratio  = (float)vp.width / vp.height;

      params.pix_fmt             = FFEMU_PIX_BGR24;
      global->record.gpu_width   = vp.width;
      global->record.gpu_height  = vp.height;

      RARCH_LOG("%s %u x %u\n", msg_hash_to_str(MSG_DETECTED_VIEWPORT_OF),
            vp.width, vp.height);

      global->record.gpu_buffer = (uint8_t*)malloc(vp.width * vp.height * 3);
      if (!global->record.gpu_buffer)
         return false;
   }
   else
   {
      if (global->record.width || global->record.height)
      {
         params.out_width  = global->record.width;
         params.out_height = global->record.height;
      }

      if (settings->video.force_aspect &&
            (video_driver_get_aspect_ratio() > 0.0f))
         params.aspect_ratio = video_driver_get_aspect_ratio();
      else
         params.aspect_ratio = (float)params.out_width / params.out_height;

      if (settings->video.post_filter_record && video_driver_frame_filter_alive())
      {
         unsigned max_width  = 0;
         unsigned max_height = 0;

         if (video_driver_frame_filter_is_32bit())
            params.pix_fmt = FFEMU_PIX_ARGB8888;
         else
            params.pix_fmt =  FFEMU_PIX_RGB565;

         rarch_softfilter_get_max_output_size(
               video_driver_frame_filter_get_ptr(),
               &max_width, &max_height);
         params.fb_width  = next_pow2(max_width);
         params.fb_height = next_pow2(max_height);
      }
   }

   RARCH_LOG("%s %s @ %ux%u. (FB size: %ux%u pix_fmt: %u)\n",
         msg_hash_to_str(MSG_RECORDING_TO),
         global->record.path,
         params.out_width, params.out_height,
         params.fb_width, params.fb_height,
         (unsigned)params.pix_fmt);

   if (!record_driver_init_first(&driver->recording, &driver->recording_data, &params))
   {
      RARCH_ERR(msg_hash_to_str(MSG_FAILED_TO_START_RECORDING));
      event_command(EVENT_CMD_GPU_RECORD_DEINIT);

      return false;
   }

   return true;
}
Exemplo n.º 21
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;
}
Exemplo n.º 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  = rarch_system_info_get_ptr();

   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;

            RARCH_LOG("Environ GET_VARIABLE %s:\n", var->key);
            if (var)
               var->value = NULL;
            RARCH_LOG("\t%s\n", var->value ? var->value : "N/A");
         }

         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 (settings->system_directory[0] == '\0')
         {
            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:
      {
         const struct retro_keyboard_callback *info =
            (const struct retro_keyboard_callback*)data;

         RARCH_LOG("Environ SET_KEYBOARD_CALLBACK.\n");
         system->key_event          = info->callback;
         global->frontend_key_event = system->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;
#ifdef HAVE_DYNAMIC
         *path = settings->libretro;
#else
         *path = NULL;
#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_update_system_av_info(
               (const struct retro_system_av_info*)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_command(EVENT_CMD_VIDEO_SET_ASPECT_RATIO);

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

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

         if (!path_file_exists((const char*)data))
            return false;
         runloop_ctl(RUNLOOP_CTL_SET_LIBRETRO_PATH, data);
         break;

      case RETRO_ENVIRONMENT_EXEC:
      case RETRO_ENVIRONMENT_EXEC_ESCAPE:
         {
            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);
#elif defined(HAVE_DYNAMIC)
            rarch_ctl(RARCH_CTL_LOAD_CONTENT, NULL);
#endif

            if (cmd == RETRO_ENVIRONMENT_EXEC_ESCAPE)
            {
               RARCH_LOG("Environ (Private) EXEC_ESCAPE.\n");
               runloop_ctl(RUNLOOP_CTL_SET_EXEC, NULL);
            }
            else
               RARCH_LOG("Environ (Private) EXEC.\n");
         }
         break;

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

   return true;
}
Exemplo n.º 23
0
static int disk_options_disk_idx_left(unsigned type, const char *label,
      bool wraparound)
{
   event_command(EVENT_CMD_DISK_PREV);
   return 0;
}
Exemplo n.º 24
0
/**
 * event_command:
 * @cmd                  : Event command index.
 *
 * Performs program event command with index @cmd.
 *
 * Returns: true (1) on success, otherwise false (0).
 **/
bool event_command(enum event_command cmd)
{
   unsigned i           = 0;
   bool boolean         = false;
   driver_t  *driver    = driver_get_ptr();
   global_t  *global    = global_get_ptr();
   settings_t *settings = config_get_ptr();
   rarch_system_info_t *system = rarch_system_info_get_ptr();

   (void)i;

   switch (cmd)
   {
      case EVENT_CMD_LOAD_CONTENT_PERSIST:
#ifdef HAVE_DYNAMIC
         event_command(EVENT_CMD_LOAD_CORE);
#endif
         rarch_ctl(RARCH_ACTION_STATE_LOAD_CONTENT, NULL);
         break;
#ifdef HAVE_FFMPEG
      case EVENT_CMD_LOAD_CONTENT_FFMPEG:
         rarch_ctl(RARCH_ACTION_STATE_LOAD_CONTENT_FFMPEG, NULL);
         break;
#endif
      case EVENT_CMD_LOAD_CONTENT_IMAGEVIEWER:
         rarch_ctl(RARCH_ACTION_STATE_LOAD_CONTENT_IMAGEVIEWER, NULL);
         break;
      case EVENT_CMD_LOAD_CONTENT:
#ifdef HAVE_DYNAMIC
         event_command(EVENT_CMD_LOAD_CONTENT_PERSIST);
#else
         rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH,
               (void*)settings->libretro);
         rarch_environment_cb(RETRO_ENVIRONMENT_EXEC,
               (void*)global->path.fullpath);
         event_command(EVENT_CMD_QUIT);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_DEINIT:
#ifdef HAVE_DYNAMIC
         libretro_free_system_info(&global->menu.info);
#endif
         break;
      case EVENT_CMD_LOAD_CORE_PERSIST:
         event_command(EVENT_CMD_LOAD_CORE_DEINIT);
         {
#ifdef HAVE_MENU
            menu_handle_t *menu = menu_driver_get_ptr();
            if (menu)
               event_update_system_info(&global->menu.info,
                     &menu->load_no_content);
#endif
         }
         break;
      case EVENT_CMD_LOAD_CORE:
         event_command(EVENT_CMD_LOAD_CORE_PERSIST);
#ifndef HAVE_DYNAMIC
         event_command(EVENT_CMD_QUIT);
#endif
         break;
      case EVENT_CMD_LOAD_STATE:
         /* Immutable - disallow savestate load when
          * we absolutely cannot change game state. */
         if (global->bsv.movie)
            return false;

#ifdef HAVE_NETPLAY
         if (driver->netplay_data)
            return false;
#endif
         event_main_state(cmd);
         break;
      case EVENT_CMD_RESIZE_WINDOWED_SCALE:
         if (global->pending.windowed_scale == 0)
            return false;

         settings->video.scale = global->pending.windowed_scale;

         if (!settings->video.fullscreen)
            event_command(EVENT_CMD_REINIT);

         global->pending.windowed_scale = 0;
         break;
      case EVENT_CMD_MENU_TOGGLE:
#ifdef HAVE_MENU
         if (menu_driver_alive())
            rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL);
         else
            rarch_ctl(RARCH_ACTION_STATE_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));
         rarch_main_msg_queue_push_new(MSG_RESET, 1, 120, true);
         core.retro_reset();

         /* bSNES since v073r01 resets controllers to JOYPAD
          * after a reset, so just enforce it here. */
         event_command(EVENT_CMD_CONTROLLERS_INIT);
         break;
      case EVENT_CMD_SAVE_STATE:
         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_PREPARE_DUMMY:
         {
#ifdef HAVE_MENU
            menu_handle_t *menu = menu_driver_get_ptr();
            if (menu)
               menu->load_no_content = false;
#endif
            rarch_main_data_deinit();

            *global->path.fullpath = '\0';

            rarch_ctl(RARCH_ACTION_STATE_LOAD_CONTENT, NULL);
         }
         break;
      case EVENT_CMD_UNLOAD_CORE:
         event_command(EVENT_CMD_PREPARE_DUMMY);
         event_command(EVENT_CMD_LOAD_CORE_DEINIT);
         break;
      case EVENT_CMD_QUIT:
         rarch_ctl(RARCH_ACTION_STATE_QUIT, NULL);
         break;
      case EVENT_CMD_REINIT:
         {
            const struct retro_hw_render_callback *hw_render =
               (const struct retro_hw_render_callback*)video_driver_callback();
            const input_driver_t *input     = driver ?
               (const input_driver_t*)driver->input : NULL;

            driver->video_cache_context     = hw_render->cache_context;
            driver->video_cache_context_ack = false;
            event_command(EVENT_CMD_RESET_CONTEXT);
            driver->video_cache_context     = false;

            /* Poll input to avoid possibly stale data to corrupt things. */
            input->poll(driver->input_data);

#ifdef HAVE_MENU
            menu_display_ctl(MENU_DISPLAY_CTL_SET_FRAMEBUFFER_DIRTY_FLAG, NULL);

            if (menu_driver_alive())
               event_command(EVENT_CMD_VIDEO_SET_BLOCKING_STATE);
#endif
         }
         break;
      case EVENT_CMD_CHEATS_DEINIT:
         if (!global)
            break;

         if (global->cheat)
            cheat_manager_free(global->cheat);
         global->cheat = NULL;
         break;
      case EVENT_CMD_CHEATS_INIT:
         event_command(EVENT_CMD_CHEATS_DEINIT);
         event_init_cheats();
         break;
      case EVENT_CMD_CHEATS_APPLY:
         if (!global->cheat)
            break;

         cheat_manager_apply_cheats(global->cheat);
         break;
      case EVENT_CMD_REMAPPING_DEINIT:
         break;
      case EVENT_CMD_REMAPPING_INIT:
         event_command(EVENT_CMD_REMAPPING_DEINIT);
         event_init_remapping();
         break;
      case EVENT_CMD_REWIND_DEINIT:
         if (!global)
            break;
#ifdef HAVE_NETPLAY
         if (driver->netplay_data)
            return false;
#endif
         if (global->rewind.state)
            state_manager_free(global->rewind.state);
         global->rewind.state = NULL;
         break;
      case EVENT_CMD_REWIND_INIT:
         if (!driver->netplay_data)
            init_rewind();
         break;
      case EVENT_CMD_REWIND_TOGGLE:
         if (settings->rewind_enable)
            event_command(EVENT_CMD_REWIND_INIT);
         else
            event_command(EVENT_CMD_REWIND_DEINIT);
         break;
      case EVENT_CMD_AUTOSAVE_DEINIT:
#ifdef HAVE_THREADS
         event_deinit_autosave();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_INIT:
         event_command(EVENT_CMD_AUTOSAVE_DEINIT);
#ifdef HAVE_THREADS
         event_init_autosave();
#endif
         break;
      case EVENT_CMD_AUTOSAVE_STATE:
         event_save_auto_state();
         break;
      case EVENT_CMD_AUDIO_STOP:
         if (!driver->audio_data)
            return false;
         if (!audio_driver_alive())
            return false;

         if (!audio_driver_stop())
            return false;
         break;
      case EVENT_CMD_AUDIO_START:
         if (!driver->audio_data || audio_driver_alive())
            return false;

         if (!settings->audio.mute_enable && !audio_driver_start())
         {
            RARCH_ERR("Failed to start audio driver. Will continue without audio.\n");
            driver->audio_active = false;
         }
         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_mute_toggle())
            {
               RARCH_ERR("%s.\n",
                     msg_hash_to_str(MSG_FAILED_TO_UNMUTE_AUDIO));
               return false;
            }

            rarch_main_msg_queue_push(msg, 1, 180, true);
            RARCH_LOG("%s\n", msg);
         }
         break;
      case EVENT_CMD_OVERLAY_DEINIT:
#ifdef HAVE_OVERLAY
         input_overlay_free_ptr();
#endif
         break;
      case EVENT_CMD_OVERLAY_INIT:
         event_command(EVENT_CMD_OVERLAY_DEINIT);
#ifdef HAVE_OVERLAY
         if (input_overlay_new_ptr() == -1)
            RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_OVERLAY));
#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:
         if (!global)
            break;

         audio_driver_dsp_filter_free();
         break;
      case EVENT_CMD_DSP_FILTER_INIT:
         event_command(EVENT_CMD_DSP_FILTER_DEINIT);
         if (!*settings->audio.dsp_plugin)
            break;
         audio_driver_dsp_filter_init(settings->audio.dsp_plugin);
         break;
      case EVENT_CMD_GPU_RECORD_DEINIT:
         if (!global)
            break;

         if (global->record.gpu_buffer)
            free(global->record.gpu_buffer);
         global->record.gpu_buffer = NULL;
         break;
      case EVENT_CMD_RECORD_DEINIT:
         if (!recording_deinit())
            return false;
         break;
      case EVENT_CMD_RECORD_INIT:
         event_command(EVENT_CMD_HISTORY_DEINIT);
         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_command(EVENT_CMD_HISTORY_DEINIT);
         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:
         if (!global)
            break;

         if (global->core_info.list)
            core_info_list_free(global->core_info.list);
         global->core_info.list = NULL;
         break;
      case EVENT_CMD_DATA_RUNLOOP_FREE:
         rarch_main_data_free();
         break;
      case EVENT_CMD_CORE_INFO_INIT:
         event_command(EVENT_CMD_CORE_INFO_DEINIT);

         if (*settings->libretro_directory)
            global->core_info.list = core_info_list_new();
         break;
      case EVENT_CMD_CORE_DEINIT:
         {
            struct retro_hw_render_callback *cb = video_driver_callback();
            event_deinit_core(true);

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

            break;
         }
      case EVENT_CMD_CORE_INIT:
         if (!event_init_core())
            return false;
         break;
      case EVENT_CMD_VIDEO_APPLY_STATE_CHANGES:
         video_driver_apply_state_changes();
         break;
      case EVENT_CMD_VIDEO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_VIDEO_SET_BLOCKING_STATE:
         video_driver_set_nonblock_state(boolean);
         break;
      case EVENT_CMD_VIDEO_SET_ASPECT_RATIO:
         video_driver_set_aspect_ratio(settings->video.aspect_ratio_idx);
         break;
      case EVENT_CMD_AUDIO_SET_NONBLOCKING_STATE:
         boolean = true; /* fall-through */
      case EVENT_CMD_AUDIO_SET_BLOCKING_STATE:
         audio_driver_set_nonblock_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_DRIVERS_DEINIT:
         uninit_drivers(DRIVERS_CMD_ALL);
         break;
      case EVENT_CMD_DRIVERS_INIT:
         init_drivers(DRIVERS_CMD_ALL);
         break;
      case EVENT_CMD_AUDIO_REINIT:
         uninit_drivers(DRIVER_AUDIO);
         init_drivers(DRIVER_AUDIO);
         break;
      case EVENT_CMD_RESET_CONTEXT:
         event_command(EVENT_CMD_DRIVERS_DEINIT);
         event_command(EVENT_CMD_DRIVERS_INIT);
         break;
      case EVENT_CMD_QUIT_RETROARCH:
         rarch_ctl(RARCH_ACTION_STATE_FORCE_QUIT, NULL);
         break;
      case EVENT_CMD_RESUME:
         rarch_ctl(RARCH_ACTION_STATE_MENU_RUNNING_FINISHED, NULL);
         break;
      case EVENT_CMD_RESTART_RETROARCH:
#if defined(GEKKO) && defined(HW_RVL)
         fill_pathname_join(global->path.fullpath, g_defaults.dir.core,
               SALAMANDER_FILE,
               sizeof(global->path.fullpath));
#endif
         if (driver->frontend_ctx && driver->frontend_ctx->set_fork)
            driver->frontend_ctx->set_fork(true, false);
         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:
         rarch_main_ctl(RARCH_MAIN_CTL_IS_PAUSED, &boolean);

         if (boolean)
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_PAUSED));
            event_command(EVENT_CMD_AUDIO_STOP);

            if (settings->video.black_frame_insertion)
               video_driver_cached_frame();
         }
         else
         {
            RARCH_LOG("%s\n", msg_hash_to_str(MSG_UNPAUSED));
            event_command(EVENT_CMD_AUDIO_START);
         }
         break;
      case EVENT_CMD_PAUSE_TOGGLE:
         rarch_main_ctl(RARCH_MAIN_CTL_IS_PAUSED,  &boolean);
         boolean = !boolean;
         rarch_main_ctl(RARCH_MAIN_CTL_SET_PAUSED, &boolean);
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_UNPAUSE:
         boolean = false;

         rarch_main_ctl(RARCH_MAIN_CTL_SET_PAUSED, &boolean);
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_PAUSE:
         boolean = true;

         rarch_main_ctl(RARCH_MAIN_CTL_SET_PAUSED, &boolean);
         event_command(EVENT_CMD_PAUSE_CHECKS);
         break;
      case EVENT_CMD_MENU_PAUSE_LIBRETRO:
#ifdef HAVE_MENU
         if (menu_driver_alive())
         {
            if (settings->menu.pause_libretro)
               event_command(EVENT_CMD_AUDIO_STOP);
            else
               event_command(EVENT_CMD_AUDIO_START);
         }
         else
         {
            if (settings->menu.pause_libretro)
               event_command(EVENT_CMD_AUDIO_START);
         }
#endif
         break;
      case EVENT_CMD_SHADER_DIR_DEINIT:
         if (!global)
            break;

         dir_list_free(global->shader_dir.list);
         global->shader_dir.list = NULL;
         global->shader_dir.ptr  = 0;
         break;
      case EVENT_CMD_SHADER_DIR_INIT:
         event_command(EVENT_CMD_SHADER_DIR_DEINIT);

         if (!*settings->video.shader_dir)
            return false;

         global->shader_dir.list = dir_list_new_special(NULL, DIR_LIST_SHADERS);

         if (!global->shader_dir.list || global->shader_dir.list->size == 0)
         {
            event_command(EVENT_CMD_SHADER_DIR_DEINIT);
            return false;
         }

         global->shader_dir.ptr  = 0;
         dir_list_sort(global->shader_dir.list, false);

         for (i = 0; i < global->shader_dir.list->size; i++)
            RARCH_LOG("%s \"%s\"\n",
                  msg_hash_to_str(MSG_FOUND_SHADER),
                  global->shader_dir.list->elems[i].data);
         break;
      case EVENT_CMD_SAVEFILES:
         event_save_files();
         break;
      case EVENT_CMD_SAVEFILES_DEINIT:
         if (!global)
            break;

         if (global->savefiles)
            string_list_free(global->savefiles);
         global->savefiles = NULL;
         break;
      case EVENT_CMD_SAVEFILES_INIT:
         global->sram.use = global->sram.use && !global->sram.save_disable
#ifdef HAVE_NETPLAY
            && (!driver->netplay_data || !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_command(EVENT_CMD_AUTOSAVE_INIT);
         break;
      case EVENT_CMD_MSG_QUEUE_DEINIT:
         rarch_main_msg_queue_free();
         break;
      case EVENT_CMD_MSG_QUEUE_INIT:
         event_command(EVENT_CMD_MSG_QUEUE_DEINIT);
         rarch_main_msg_queue_init();
         rarch_main_data_init_queues();
         break;
      case EVENT_CMD_BSV_MOVIE_DEINIT:
         if (!global)
            break;

         if (global->bsv.movie)
            bsv_movie_free(global->bsv.movie);
         global->bsv.movie = NULL;
         break;
      case EVENT_CMD_BSV_MOVIE_INIT:
         event_command(EVENT_CMD_BSV_MOVIE_DEINIT);
         event_init_movie();
         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_command(EVENT_CMD_NETPLAY_DEINIT);
#ifdef HAVE_NETPLAY
         if (!init_netplay())
            return false;
#endif
         break;
      case EVENT_CMD_NETPLAY_FLIP_PLAYERS:
#ifdef HAVE_NETPLAY
         {
            netplay_t *netplay = (netplay_t*)driver->netplay_data;
            if (!netplay)
               return false;
            netplay_flip_users(netplay);
         }
#endif
         break;
      case EVENT_CMD_FULLSCREEN_TOGGLE:
         if (!video_driver_has_windowed())
            return false;

         /* If we go fullscreen we drop all drivers and
          * reinitialize to be safe. */
         settings->video.fullscreen = !settings->video.fullscreen;
         event_command(EVENT_CMD_REINIT);
         break;
      case EVENT_CMD_COMMAND_DEINIT:
#ifdef HAVE_COMMAND
         if (driver->command)
            rarch_cmd_free(driver->command);
         driver->command = NULL;
#endif
         break;
      case EVENT_CMD_COMMAND_INIT:
         event_command(EVENT_CMD_COMMAND_DEINIT);

#ifdef HAVE_COMMAND
         event_init_command();
#endif
         break;
      case EVENT_CMD_TEMPORARY_CONTENT_DEINIT:
         if (!global)
            break;

         if (global->temporary_content)
            event_free_temporary_content();
         global->temporary_content = NULL;
         break;
      case EVENT_CMD_SUBSYSTEM_FULLPATHS_DEINIT:
         if (!global)
            break;

         if (global->subsystem_fullpaths)
            string_list_free(global->subsystem_fullpaths);
         global->subsystem_fullpaths = NULL;
         break;
      case EVENT_CMD_LOG_FILE_DEINIT:
         if (!global)
            break;

         if (global->log_file && global->log_file != stderr)
            fclose(global->log_file);
         global->log_file = NULL;
         break;
      case EVENT_CMD_DISK_EJECT_TOGGLE:
         if (system && system->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &system->disk_control;

            if (control)
               event_check_disk_eject(control);
         }
         else
            rarch_main_msg_queue_push_new(
                  MSG_CORE_DOES_NOT_SUPPORT_DISK_OPTIONS,
                  1, 120, true);
         break;
      case EVENT_CMD_DISK_NEXT:
         if (system && system->disk_control.get_num_images)
         {
            const struct retro_disk_control_callback *control =
               (const struct retro_disk_control_callback*)
               &system->disk_control;

            if (!control)
               return false;

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

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

            if (!control)
               return false;

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

            event_check_disk_prev(control);
         }
         else
            rarch_main_msg_queue_push_new(
                  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:
         {
            static bool grab_mouse_state  = false;

            grab_mouse_state = !grab_mouse_state;

            if (!driver->input || !input_driver_grab_mouse(grab_mouse_state))
               return false;

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

            video_driver_show_mouse(!grab_mouse_state);
         }
         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:
         rarch_main_ctl(RARCH_MAIN_CTL_SET_FRAME_LIMIT_LAST_TIME, NULL);
         break;
      case EVENT_CMD_NONE:
      default:
         return false;
   }

   return true;
}
Exemplo n.º 25
0
static bool ctr_frame(void* data, const void* frame,
      unsigned width, unsigned height, unsigned pitch, const char* msg)
{
   ctr_video_t* ctr = (ctr_video_t*)data;
   settings_t* settings = config_get_ptr();

   static uint64_t currentTick,lastTick;
   static float fps = 0.0;
   static int total_frames = 0;
   static int frames = 0;

   extern bool select_pressed;

   RARCH_PERFORMANCE_INIT(ctrframe_f);
   RARCH_PERFORMANCE_START(ctrframe_f);

   if (!width || !height)
   {
      gspWaitForEvent(GSPEVENT_VBlank0, true);
      goto end;
   }

   if(!aptMainLoop())
   {
      event_command(EVENT_CMD_QUIT);
      goto end;
   }

   if (select_pressed)
   {
      event_command(EVENT_CMD_QUIT);
      goto end;
   }

   frames++;
   currentTick = svcGetSystemTick();
   uint32_t diff = currentTick - lastTick;
   if(diff > CTR_CPU_TICKS_PER_SECOND)
   {
      fps = (float)frames * ((float) CTR_CPU_TICKS_PER_SECOND / (float) diff);
      lastTick = currentTick;
      frames = 0;
   }

   printf("fps: %8.4f frames: %i\r", fps, total_frames++);
//   fflush(stdout);

   /* enable this to profile the core without video output */
#if 0
   if (!ctr->menu_texture_enable)
      goto end;
#endif

   svcWaitSynchronization(gspEvents[GSPEVENT_P3D], 20000000);
   svcClearEvent(gspEvents[GSPEVENT_P3D]);
   svcWaitSynchronization(gspEvents[GSPEVENT_PPF], 20000000);
   svcClearEvent(gspEvents[GSPEVENT_PPF]);

   gfxSwapBuffersGpu();

   if (ctr->vsync)
         gspWaitForEvent(GSPEVENT_VBlank0, true);

   ctrGuSetMemoryFill(true, (u32*)CTR_GPU_FRAMEBUFFER, 0x00000000,
                    (u32*)(CTR_GPU_FRAMEBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
                    0x201, (u32*)CTR_GPU_DEPTHBUFFER, 0x00000000,
                    (u32*)(CTR_GPU_DEPTHBUFFER + CTR_TOP_FRAMEBUFFER_WIDTH * CTR_TOP_FRAMEBUFFER_HEIGHT * sizeof(uint32_t)),
                    0x201);

   GPUCMD_SetBufferOffset(0);

   if (width > ctr->texture_width)
      width = ctr->texture_width;
   if (height > ctr->texture_height)
      height = ctr->texture_height;

   if(frame)
   {
      if(((((u32)(frame)) >= 0x14000000 && ((u32)(frame)) < 0x1c000000)) /* frame in linear memory */
         && !((u32)frame & 0x7F)                                         /* 128-byte aligned */
         && !((pitch) & 0xF))                                            /* 16-byte aligned */
      {
         /* can copy the buffer directly with the GPU */
         ctrGuCopyImage(false, frame, pitch / 2, height, CTRGU_RGB565, false,
                        ctr->texture_swizzled, ctr->texture_width, CTRGU_RGB565,  true);
      }
      else
      {
         int i;
         uint16_t* dst = (uint16_t*)ctr->texture_linear;
         const uint8_t* src = frame;
         for (i = 0; i < height; i++)
         {
            memcpy(dst, src, width * sizeof(uint16_t));
            dst += ctr->texture_width;
            src += pitch;
         }
         GSPGPU_FlushDataCache(NULL, ctr->texture_linear,
                               ctr->texture_width * ctr->texture_height * sizeof(uint16_t));

         ctrGuCopyImage(false, ctr->texture_linear, ctr->texture_width, ctr->menu.texture_height, CTRGU_RGB565, false,
                        ctr->texture_swizzled, ctr->texture_width, CTRGU_RGB565,  true);

      }

   }


   ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->texture_swizzled), ctr->texture_width, ctr->texture_height,
                  GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
                  GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
                  GPU_RGB565);

   ctr->frame_coords->u = width;
   ctr->frame_coords->v = height;
   GSPGPU_FlushDataCache(NULL, (u8*)ctr->frame_coords, sizeof(ctr_vertex_t));

   ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->frame_coords));
   ctrGuSetVertexShaderFloatUniform(0, (float*)&ctr->scale_vector, 1);
   GPU_DrawArray(GPU_UNKPRIM, 1);

   if (ctr->menu_texture_enable)
   {

      GSPGPU_FlushDataCache(NULL, ctr->menu.texture_linear,
                            ctr->menu.texture_width * ctr->menu.texture_height * sizeof(uint16_t));

      ctrGuCopyImage(false, ctr->menu.texture_linear, ctr->menu.texture_width, ctr->menu.texture_height, CTRGU_RGBA4444,false,
                     ctr->menu.texture_swizzled, ctr->menu.texture_width, CTRGU_RGBA4444,  true);

      ctrGuSetTexture(GPU_TEXUNIT0, VIRT_TO_PHYS(ctr->menu.texture_swizzled), ctr->menu.texture_width, ctr->menu.texture_height,
                     GPU_TEXTURE_MAG_FILTER(GPU_LINEAR) | GPU_TEXTURE_MIN_FILTER(GPU_LINEAR) |
                     GPU_TEXTURE_WRAP_S(GPU_CLAMP_TO_EDGE) | GPU_TEXTURE_WRAP_T(GPU_CLAMP_TO_EDGE),
                     GPU_RGBA4);


      ctrGuSetAttributeBuffersAddress(VIRT_TO_PHYS(ctr->menu.frame_coords));
      ctrGuSetVertexShaderFloatUniform(1, (float*)&ctr->menu.scale_vector, 1);
      GPU_DrawArray(GPU_UNKPRIM, 1);
   }

   GPU_FinishDrawing();
   GPUCMD_Finalize();
   ctrGuFlushAndRun(true);

   ctrGuDisplayTransfer(true, CTR_GPU_FRAMEBUFFER, 240,400, CTRGU_RGBA8,
                        gfxGetFramebuffer(GFX_TOP, GFX_LEFT, NULL, NULL), 240,400,CTRGU_RGB8, CTRGU_MULTISAMPLE_NONE);


end:
//   gspWaitForEvent(GSPEVENT_VBlank0, true);
   RARCH_PERFORMANCE_STOP(ctrframe_f);
   return true;
}
Exemplo n.º 26
0
void init_video(void)
{
   unsigned max_dim, scale, width, height;
   video_viewport_t *custom_vp      = NULL;
   const input_driver_t *tmp        = NULL;
   const struct retro_game_geometry *geom = NULL;
   video_info_t video               = {0};
   static uint16_t dummy_pixels[32] = {0};
   driver_t *driver                 = driver_get_ptr();
   settings_t *settings             = config_get_ptr();
   rarch_system_info_t *system      = rarch_system_info_get_ptr();
   struct retro_system_av_info *av_info =
      video_viewport_get_system_av_info();

   init_video_filter(video_state.pix_fmt);
   event_command(EVENT_CMD_SHADER_DIR_INIT);

   if (av_info)
      geom      = (const struct retro_game_geometry*)&av_info->geometry;
   max_dim   = max(geom->max_width, geom->max_height);
   scale     = next_pow2(max_dim) / RARCH_SCALE_BASE;
   scale     = max(scale, 1);

   if (video_state.filter.filter)
      scale = video_state.filter.scale;

   /* Update core-dependent aspect ratio values. */
   video_viewport_set_square_pixel(geom->base_width, geom->base_height);
   video_viewport_set_core();
   video_viewport_set_config();

   /* Update CUSTOM viewport. */
   custom_vp = video_viewport_get_custom();

   if (settings->video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
   {
      float default_aspect = aspectratio_lut[ASPECT_RATIO_CORE].value;
      aspectratio_lut[ASPECT_RATIO_CUSTOM].value =
         (custom_vp->width && custom_vp->height) ?
         (float)custom_vp->width / custom_vp->height : default_aspect;
   }

   video_driver_set_aspect_ratio_value(
      aspectratio_lut[settings->video.aspect_ratio_idx].value);

   if (settings->video.fullscreen)
   {
      width  = settings->video.fullscreen_x;
      height = settings->video.fullscreen_y;
   }
   else
   {
      if (settings->video.force_aspect)
      {
         /* Do rounding here to simplify integer scale correctness. */
         unsigned base_width =
            roundf(geom->base_height * video_driver_get_aspect_ratio());
         width  = roundf(base_width * settings->video.scale);
      }
      else
         width  = roundf(geom->base_width   * settings->video.scale);
      height = roundf(geom->base_height * settings->video.scale);
   }

   if (width && height)
      RARCH_LOG("Video @ %ux%u\n", width, height);
   else
      RARCH_LOG("Video @ fullscreen\n");

   driver->display_type  = RARCH_DISPLAY_NONE;
   driver->video_display = 0;
   driver->video_window  = 0;

   if (!init_video_pixel_converter(RARCH_SCALE_BASE * scale))
   {
      RARCH_ERR("Failed to initialize pixel converter.\n");
      rarch_fail(1, "init_video()");
   }

   video.width        = width;
   video.height       = height;
   video.fullscreen   = settings->video.fullscreen;
   video.vsync        = settings->video.vsync && !system->force_nonblock;
   video.force_aspect = settings->video.force_aspect;
#ifdef GEKKO
   video.viwidth      = settings->video.viwidth;
   video.vfilter      = settings->video.vfilter;
#endif
   video.smooth       = settings->video.smooth;
   video.input_scale  = scale;
   video.rgb32        = video_state.filter.filter ?
      video_state.filter.out_rgb32 :
      (video_state.pix_fmt == RETRO_PIXEL_FORMAT_XRGB8888);

   tmp = (const input_driver_t*)driver->input;
   /* Need to grab the "real" video driver interface on a reinit. */
   find_video_driver();

#ifdef HAVE_THREADS
   if (settings->video.threaded && !video_state.hw_render_callback.context_type)
   {
      /* Can't do hardware rendering with threaded driver currently. */
      RARCH_LOG("Starting threaded video driver ...\n");

      if (!rarch_threaded_video_init(&driver->video, &driver->video_data,
               &driver->input, &driver->input_data,
               driver->video, &video))
      {
         RARCH_ERR("Cannot open threaded video driver ... Exiting ...\n");
         rarch_fail(1, "init_video()");
      }
   }
   else
#endif
      driver->video_data = driver->video->init(&video, &driver->input,
            &driver->input_data);

   if (!driver->video_data)
   {
      RARCH_ERR("Cannot open video driver ... Exiting ...\n");
      rarch_fail(1, "init_video()");
   }

   driver->video_poke = NULL;
   if (driver->video->poke_interface)
      driver->video->poke_interface(driver->video_data, &driver->video_poke);

   if (driver->video->viewport_info && (!custom_vp->width ||
            !custom_vp->height))
   {
      /* Force custom viewport to have sane parameters. */
      custom_vp->width = width;
      custom_vp->height = height;
      video_driver_viewport_info(custom_vp);
   }

   video_driver_set_rotation(
            (settings->video.rotation + system->rotation) % 4);

   video_driver_suppress_screensaver(settings->ui.suspend_screensaver_enable);

   if (!driver->input)
      init_video_input(tmp);

   event_command(EVENT_CMD_OVERLAY_DEINIT);
   event_command(EVENT_CMD_OVERLAY_INIT);

   video_driver_cached_frame_set(&dummy_pixels, 4, 4, 8);

#if defined(PSP)
   video_driver_set_texture_frame(&dummy_pixels, false, 1, 1, 1.0f);
#endif
}
Exemplo n.º 27
0
static int generic_action_ok_command(enum event_command cmd)
{
   if (!event_command(cmd))
      return -1;
   return 0;
}