예제 #1
0
/**
 * parse_input:
 * @argc                 : Count of (commandline) arguments.
 * @argv                 : (Commandline) arguments.
 *
 * Parses (commandline) arguments passed to program.
 *
 **/
static void parse_input(int argc, char *argv[])
{
   const char *optstring = NULL;
   global_t  *global     = global_get_ptr();
   settings_t *settings  = config_get_ptr();

   const struct option opts[] = {
#ifdef HAVE_DYNAMIC
      { "libretro",     1, NULL, 'L' },
#endif
      { "menu",         0, NULL, RA_OPT_MENU },
      { "help",         0, NULL, 'h' },
      { "save",         1, NULL, 's' },
      { "fullscreen",   0, NULL, 'f' },
      { "record",       1, NULL, 'r' },
      { "recordconfig", 1, NULL, RA_OPT_RECORDCONFIG },
      { "size",         1, NULL, RA_OPT_SIZE },
      { "verbose",      0, NULL, 'v' },
      { "config",       1, NULL, 'c' },
      { "appendconfig", 1, NULL, RA_OPT_APPENDCONFIG },
      { "nodevice",     1, NULL, 'N' },
      { "dualanalog",   1, NULL, 'A' },
      { "device",       1, NULL, 'd' },
      { "savestate",    1, NULL, 'S' },
      { "bsvplay",      1, NULL, 'P' },
      { "bsvrecord",    1, NULL, 'R' },
      { "sram-mode",    1, NULL, 'M' },
#ifdef HAVE_NETPLAY
      { "host",         0, NULL, 'H' },
      { "connect",      1, NULL, 'C' },
      { "frames",       1, NULL, 'F' },
      { "port",         1, NULL, RA_OPT_PORT },
      { "spectate",     0, NULL, RA_OPT_SPECTATE },
#endif
      { "nick",         1, NULL, RA_OPT_NICK },
#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
      { "command",      1, NULL, RA_OPT_COMMAND },
#endif
      { "ups",          1, NULL, 'U' },
      { "bps",          1, NULL, RA_OPT_BPS },
      { "ips",          1, NULL, RA_OPT_IPS },
      { "no-patch",     0, NULL, RA_OPT_NO_PATCH },
      { "detach",       0, NULL, 'D' },
      { "features",     0, NULL, RA_OPT_FEATURES },
      { "subsystem",    1, NULL, RA_OPT_SUBSYSTEM },
      { "max-frames",   1, NULL, RA_OPT_MAX_FRAMES },
      { "eof-exit",     0, NULL, RA_OPT_EOF_EXIT },
      { "version",      0, NULL, RA_OPT_VERSION },
#ifdef HAVE_FILE_LOGGER
      { "log-file",     1, NULL, RA_OPT_LOG_FILE },
#endif
      { NULL, 0, NULL, 0 }
   };

   global->inited.core.no_content        = false;
   global->inited.core.type              = CORE_TYPE_PLAIN;
   *global->subsystem                    = '\0';
   global->has_set.save_path             = false;
   global->has_set.state_path            = false;
   global->has_set.libretro              = false;
   global->has_set.libretro_directory    = false;
   global->has_set.verbosity             = false;

   global->has_set.netplay_mode          = false;
   global->has_set.username              = false;
   global->has_set.netplay_ip_address    = false;
   global->has_set.netplay_delay_frames  = false;
   global->has_set.netplay_ip_port       = false;

   global->has_set.ups_pref              = false;
   global->has_set.bps_pref              = false;
   global->has_set.ips_pref              = false;
   global->patch.ups_pref                = false;
   global->patch.bps_pref                = false;
   global->patch.ips_pref                = false;
   *global->name.ups                     = '\0';
   *global->name.bps                     = '\0';
   *global->name.ips                     = '\0';

   global->overrides_active              = false;

   if (argc < 2)
   {
      global->inited.core.type           = CORE_TYPE_DUMMY;
      return;
   }

   /* Make sure we can call parse_input several times ... */
   optind    = 0;
   optstring = "hs:fvS:A:c:U:DN:d:" BSV_MOVIE_ARG NETPLAY_ARG DYNAMIC_ARG FFMPEG_RECORD_ARG;

   for (;;)
   {
      int port;
      int c = getopt_long(argc, argv, optstring, opts, NULL);

      if (c == -1)
         break;

      switch (c)
      {
         case 'h':
            print_help(argv[0]);
            exit(0);

         case 'd':
         {
            unsigned id = 0;
            struct string_list *list = string_split(optarg, ":");

            port = 0;

            if (list && list->size == 2)
            {
               port = strtol(list->elems[0].data, NULL, 0);
               id = strtoul(list->elems[1].data, NULL, 0);
            }
            string_list_free(list);

            if (port < 1 || port > MAX_USERS)
            {
               RARCH_ERR("Connect device to a valid port.\n");
               print_help(argv[0]);
               rarch_fail(1, "parse_input()");
            }
            settings->input.libretro_device[port - 1] = id;
            global->has_set.libretro_device[port - 1] = true;
            break;
         }

         case 'A':
            port = strtol(optarg, NULL, 0);
            if (port < 1 || port > MAX_USERS)
            {
               RARCH_ERR("Connect dualanalog to a valid port.\n");
               print_help(argv[0]);
               rarch_fail(1, "parse_input()");
            }
            settings->input.libretro_device[port - 1] = RETRO_DEVICE_ANALOG;
            global->has_set.libretro_device[port - 1] = true;
            break;

         case 's':
            strlcpy(global->name.savefile, optarg,
                  sizeof(global->name.savefile));
            global->has_set.save_path = true;
            break;

         case 'f':
            global->force_fullscreen = true;
            break;

         case 'S':
            strlcpy(global->name.savestate, optarg,
                  sizeof(global->name.savestate));
            global->has_set.state_path = true;
            break;

         case 'v':
            global->verbosity = true;
            global->has_set.verbosity = true;
            break;

         case 'N':
            port = strtol(optarg, NULL, 0);
            if (port < 1 || port > MAX_USERS)
            {
               RARCH_ERR("Disconnect device from a valid port.\n");
               print_help(argv[0]);
               rarch_fail(1, "parse_input()");
            }
            settings->input.libretro_device[port - 1] = RETRO_DEVICE_NONE;
            global->has_set.libretro_device[port - 1] = true;
            break;

         case 'c':
            strlcpy(global->path.config, optarg,
                  sizeof(global->path.config));
            break;

         case 'r':
            strlcpy(global->record.path, optarg,
                  sizeof(global->record.path));
            global->record.enable = true;
            break;

#ifdef HAVE_DYNAMIC
         case 'L':
            if (path_is_directory(optarg))
            {
               *settings->libretro = '\0';
               strlcpy(settings->libretro_directory, optarg,
                     sizeof(settings->libretro_directory));
               global->has_set.libretro = true;
               global->has_set.libretro_directory = true;
               RARCH_WARN("Using old --libretro behavior. Setting libretro_directory to \"%s\" instead.\n", optarg);
            }
            else
            {
               strlcpy(settings->libretro, optarg,
                     sizeof(settings->libretro));
               global->has_set.libretro = true;
            }
            break;
#endif
         case 'P':
         case 'R':
            strlcpy(global->bsv.movie_start_path, optarg,
                  sizeof(global->bsv.movie_start_path));
            global->bsv.movie_start_playback  = (c == 'P');
            global->bsv.movie_start_recording = (c == 'R');
            break;

         case 'M':
            if (!strcmp(optarg, "noload-nosave"))
            {
               global->sram.load_disable = true;
               global->sram.save_disable = true;
            }
            else if (!strcmp(optarg, "noload-save"))
               global->sram.load_disable = true;
            else if (!strcmp(optarg, "load-nosave"))
               global->sram.save_disable = true;
            else if (strcmp(optarg, "load-save") != 0)
            {
               RARCH_ERR("Invalid argument in --sram-mode.\n");
               print_help(argv[0]);
               rarch_fail(1, "parse_input()");
            }
            break;

#ifdef HAVE_NETPLAY
         case 'H':
            global->has_set.netplay_ip_address = true;
            global->netplay.enable = true;
            *global->netplay.server = '\0';
            break;

         case 'C':
            global->has_set.netplay_ip_address = true;
            global->netplay.enable = true;
            strlcpy(global->netplay.server, optarg,
                  sizeof(global->netplay.server));
            break;

         case 'F':
            global->netplay.sync_frames = strtol(optarg, NULL, 0);
            global->has_set.netplay_delay_frames = true;
            break;
#endif

         case RA_OPT_BPS:
            strlcpy(global->name.bps, optarg,
                  sizeof(global->name.bps));
            global->patch.bps_pref   = true;
            global->has_set.bps_pref = true;
            break;

         case 'U':
            strlcpy(global->name.ups, optarg,
                  sizeof(global->name.ups));
            global->patch.ups_pref   = true;
            global->has_set.ups_pref = true;
            break;

         case RA_OPT_IPS:
            strlcpy(global->name.ips, optarg,
                  sizeof(global->name.ips));
            global->patch.ips_pref   = true;
            global->has_set.ips_pref = true;
            break;

         case RA_OPT_NO_PATCH:
            global->patch.block_patch = true;
            break;

         case 'D':
#if defined(_WIN32) && !defined(_XBOX)
            FreeConsole();
#endif
            break;
         
         case RA_OPT_MENU:
            global->inited.core.type        = CORE_TYPE_DUMMY;
            break;

#ifdef HAVE_NETPLAY
         case RA_OPT_PORT:
            global->has_set.netplay_ip_port = true;
            global->netplay.port = strtoul(optarg, NULL, 0);
            break;

         case RA_OPT_SPECTATE:
            global->has_set.netplay_mode = true;
            global->netplay.is_spectate = true;
            break;

#endif
         case RA_OPT_NICK:
            global->has_set.username = true;
            strlcpy(settings->username, optarg,
                  sizeof(settings->username));
            break;

#if defined(HAVE_NETWORK_CMD) && defined(HAVE_NETPLAY)
         case RA_OPT_COMMAND:
            if (network_cmd_send(optarg))
               exit(0);
            else
               rarch_fail(1, "network_cmd_send()");
            break;
#endif

         case RA_OPT_APPENDCONFIG:
            strlcpy(global->path.append_config, optarg,
                  sizeof(global->path.append_config));
            break;

         case RA_OPT_SIZE:
         {
            if (sscanf(optarg, "%ux%u", &global->record.width,
                     &global->record.height) != 2)
            {
               RARCH_ERR("Wrong format for --size.\n");
               print_help(argv[0]);
               rarch_fail(1, "parse_input()");
            }
            break;
         }

         case RA_OPT_RECORDCONFIG:
            strlcpy(global->record.config, optarg,
                  sizeof(global->record.config));
            break;

         case RA_OPT_MAX_FRAMES:
            {
               unsigned max_frames = strtoul(optarg, NULL, 10);
               rarch_main_ctl(RARCH_MAIN_CTL_SET_MAX_FRAMES, &max_frames);
            }
            break;

         case RA_OPT_SUBSYSTEM:
            strlcpy(global->subsystem, optarg, sizeof(global->subsystem));
            break;

         case RA_OPT_FEATURES:
            print_features();
            exit(0);

         case RA_OPT_EOF_EXIT:
            global->bsv.eof_exit = true;
            break;

         case RA_OPT_VERSION:
            print_version();
            exit(0);

#ifdef HAVE_FILE_LOGGER
         case RA_OPT_LOG_FILE:
            global->log_file = fopen(optarg, "wb");
            break;
#endif

         case '?':
            print_help(argv[0]);
            rarch_fail(1, "parse_input()");

         default:
            RARCH_ERR("Error parsing arguments.\n");
            rarch_fail(1, "parse_input()");
      }
   }

   if (global->inited.core.type == CORE_TYPE_DUMMY)
   {
      if (optind < argc)
      {
         RARCH_ERR("--menu was used, but content file was passed as well.\n");
         rarch_fail(1, "parse_input()");
      }
   }
   else if (!*global->subsystem && optind < argc)
      rarch_set_paths(argv[optind]);
   else if (*global->subsystem && optind < argc)
      set_special_paths(argv + optind, argc - optind);
   else
      global->inited.core.no_content = true;


   /* Copy SRM/state dirs used, so they can be reused on reentrancy. */
   if (global->has_set.save_path &&
         path_is_directory(global->name.savefile))
      strlcpy(global->dir.savefile, global->name.savefile,
            sizeof(global->dir.savefile));

   if (global->has_set.state_path &&
         path_is_directory(global->name.savestate))
      strlcpy(global->dir.savestate, global->name.savestate,
            sizeof(global->dir.savestate));
}
예제 #2
0
static void *alsa_qsa_init(const char *device,
      unsigned rate, unsigned latency)
{
   int err, card, dev, i;
   snd_pcm_channel_info_t pi;
   snd_pcm_channel_params_t params = {0};
   snd_pcm_channel_setup_t setup   = {0};
   settings_t *settings            = config_get_ptr();
   alsa_t *alsa                    = (alsa_t*)calloc(1, sizeof(alsa_t));
   if (!alsa)
      return NULL;

   (void)device;
   (void)rate;
   (void)latency;

   if ((err = snd_pcm_open_preferred(&alsa->pcm, &card, &dev,
               SND_PCM_OPEN_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Audio open error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if((err = snd_pcm_nonblock_mode(alsa->pcm, 1)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Can't set blocking mode: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&pi, 0, sizeof(pi));
   pi.channel = SND_PCM_CHANNEL_PLAYBACK;
   if ((err = snd_pcm_channel_info(alsa->pcm, &pi)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: snd_pcm_channel_info failed: %s\n",
            snd_strerror(err));
      goto error;
   }

   memset(&params, 0, sizeof(params));

   params.channel = SND_PCM_CHANNEL_PLAYBACK;
   params.mode = SND_PCM_MODE_BLOCK;

   params.format.interleave = 1;
   params.format.format = SND_PCM_SFMT_S16_LE;
   params.format.rate = DEFAULT_RATE;
   params.format.voices = 2;

   params.start_mode = SND_PCM_START_FULL;
   params.stop_mode = SND_PCM_STOP_STOP;

   params.buf.block.frag_size = pi.max_fragment_size;
   params.buf.block.frags_min = 2;
   params.buf.block.frags_max = 8;

   RARCH_LOG("Fragment size: %d\n", params.buf.block.frag_size);
   RARCH_LOG("Min Fragment size: %d\n", params.buf.block.frags_min);
   RARCH_LOG("Max Fragment size: %d\n", params.buf.block.frags_max);

   if ((err = snd_pcm_channel_params(alsa->pcm, &params)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   setup.channel = SND_PCM_CHANNEL_PLAYBACK;

   if ((err = snd_pcm_channel_setup(alsa->pcm, &setup)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Parameter Read Back Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   if (settings->audio.block_frames)
      alsa->buf_size = settings->audio.block_frames * 4;
   else
      alsa->buf_size = next_pow2(32 * latency);

   RARCH_LOG("[ALSA QSA]: buffer size: %u bytes\n", alsa->buf_size);

   alsa->buf_count = (latency * 4 * rate + 500) / 1000;
   alsa->buf_count = (alsa->buf_count + alsa->buf_size / 2) / alsa->buf_size;

   if ((err = snd_pcm_channel_prepare(alsa->pcm,
               SND_PCM_CHANNEL_PLAYBACK)) < 0)
   {
      RARCH_ERR("[ALSA QSA]: Channel Prepare Error: %s\n",
            snd_strerror(err));
      goto error;
   }

   alsa->buffer = (uint8_t**)calloc(sizeof(uint8_t*), alsa->buf_count);
   if (!alsa->buffer)
      goto error;

   alsa->buffer_chunk = (uint8_t*)calloc(alsa->buf_count, alsa->buf_size);
   if (!alsa->buffer_chunk)
      goto error;

   for (i = 0; i < alsa->buf_count; i++)
      alsa->buffer[i] = alsa->buffer_chunk + i * alsa->buf_size;

   alsa->has_float = false;
   alsa->can_pause = true;
   RARCH_LOG("[ALSA QSA]: Can pause: %s.\n",
         alsa->can_pause ? "yes" : "no");

   return alsa;

error:
   return (void*)-1;
}
예제 #3
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);
}
예제 #4
0
static void *coreaudio_init(const char *device,
      unsigned rate, unsigned latency)
{
   size_t fifo_size;
   UInt32 i_size;
   AudioStreamBasicDescription real_desc;
#ifdef OSX_PPC
   Component comp;
#else
   AudioComponent comp;
#endif
#ifndef TARGET_OS_IPHONE
   AudioChannelLayout layout               = {0};
#endif
   AURenderCallbackStruct cb               = {0};
   AudioStreamBasicDescription stream_desc = {0};
   bool component_unavailable              = false;
   static bool session_initialized         = false;
   coreaudio_t *dev                        = NULL;
#ifdef OSX_PPC
   ComponentDescription desc               = {0};
#else
   AudioComponentDescription desc          = {0};
#endif
   settings_t *settings                    = config_get_ptr();

   (void)session_initialized;
   (void)device;

   dev = (coreaudio_t*)calloc(1, sizeof(*dev));
   if (!dev)
      return NULL;

   dev->lock = slock_new();
   dev->cond = scond_new();

#if TARGET_OS_IPHONE
   if (!session_initialized)
   {
      session_initialized = true;
      AudioSessionInitialize(0, 0, coreaudio_interrupt_listener, 0);
      AudioSessionSetActive(true);
   }
#endif

   /* Create AudioComponent */
   desc.componentType = kAudioUnitType_Output;
#if TARGET_OS_IPHONE
   desc.componentSubType = kAudioUnitSubType_RemoteIO;
#else
   desc.componentSubType = kAudioUnitSubType_HALOutput;
#endif
   desc.componentManufacturer = kAudioUnitManufacturer_Apple;

#ifdef OSX_PPC
   comp = FindNextComponent(NULL, &desc);
#else
   comp = AudioComponentFindNext(NULL, &desc);
#endif
   if (comp == NULL)
      goto error;
   
#ifdef OSX_PPC
   component_unavailable = (OpenAComponent(comp, &dev->dev) != noErr);
#else
   component_unavailable = (AudioComponentInstanceNew(comp, &dev->dev) != noErr);
#endif

   if (component_unavailable)
      goto error;

#if !TARGET_OS_IPHONE
   if (device)
      choose_output_device(dev, device);
#endif

   dev->dev_alive = true;

   /* Set audio format */
   stream_desc.mSampleRate       = rate;
   stream_desc.mBitsPerChannel   = sizeof(float) * CHAR_BIT;
   stream_desc.mChannelsPerFrame = 2;
   stream_desc.mBytesPerPacket   = 2 * sizeof(float);
   stream_desc.mBytesPerFrame    = 2 * sizeof(float);
   stream_desc.mFramesPerPacket  = 1;
   stream_desc.mFormatID         = kAudioFormatLinearPCM;
   stream_desc.mFormatFlags      = kAudioFormatFlagIsFloat | 
      kAudioFormatFlagIsPacked | (is_little_endian() ? 
            0 : kAudioFormatFlagIsBigEndian);
   
   if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_StreamFormat,
         kAudioUnitScope_Input, 0, &stream_desc, sizeof(stream_desc)) != noErr)
      goto error;
   
   /* Check returned audio format. */
   i_size = sizeof(real_desc);
   if (AudioUnitGetProperty(dev->dev, kAudioUnitProperty_StreamFormat, 
            kAudioUnitScope_Input, 0, &real_desc, &i_size) != noErr)
      goto error;

   if (real_desc.mChannelsPerFrame != stream_desc.mChannelsPerFrame)
      goto error;
   if (real_desc.mBitsPerChannel != stream_desc.mBitsPerChannel)
      goto error;
   if (real_desc.mFormatFlags != stream_desc.mFormatFlags)
      goto error;
   if (real_desc.mFormatID != stream_desc.mFormatID)
      goto error;

   RARCH_LOG("[CoreAudio]: Using output sample rate of %.1f Hz\n",
         (float)real_desc.mSampleRate);
   settings->audio.out_rate = real_desc.mSampleRate;

   /* Set channel layout (fails on iOS). */
#ifndef TARGET_OS_IPHONE
   layout.mChannelLayoutTag = kAudioChannelLayoutTag_Stereo;
   if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_AudioChannelLayout,
         kAudioUnitScope_Input, 0, &layout, sizeof(layout)) != noErr)
      goto error;
#endif

   /* Set callbacks and finish up. */
   cb.inputProc = audio_write_cb;
   cb.inputProcRefCon = dev;

   if (AudioUnitSetProperty(dev->dev, kAudioUnitProperty_SetRenderCallback,
         kAudioUnitScope_Input, 0, &cb, sizeof(cb)) != noErr)
      goto error;

   if (AudioUnitInitialize(dev->dev) != noErr)
      goto error;

   fifo_size = (latency * settings->audio.out_rate) / 1000;
   fifo_size *= 2 * sizeof(float);
   dev->buffer_size = fifo_size;

   dev->buffer = fifo_new(fifo_size);
   if (!dev->buffer)
      goto error;

   RARCH_LOG("[CoreAudio]: Using buffer size of %u bytes: (latency = %u ms)\n",
         (unsigned)fifo_size, latency);

   if (AudioOutputUnitStart(dev->dev) != noErr)
      goto error;

   return dev;

error:
   RARCH_ERR("[CoreAudio]: Failed to initialize driver ...\n");
   coreaudio_free(dev);
   return NULL;
}
예제 #5
0
static void d3d_calculate_rect(void *data,
      unsigned *width, unsigned *height,
      int *x, int *y,
      bool force_full,
      bool allow_rotate)
{
   float device_aspect  = (float)*width / *height;
   d3d_video_t *d3d     = (d3d_video_t*)data;
   settings_t *settings = config_get_ptr();

   video_driver_get_size(width, height);
   gfx_ctx_translate_aspect(&device_aspect, *width, *height);

   *x = 0;
   *y = 0;

   if (settings->video.scale_integer && !force_full)
   {
      struct video_viewport vp = {0};
      video_viewport_get_scaled_integer(&vp,
            *width,
            *height,
            video_driver_get_aspect_ratio(), d3d->keep_aspect);
      *x          = vp.x;
      *y          = vp.y;
      *width  = vp.width;
      *height = vp.height;
   }
   else if (d3d->keep_aspect && !force_full)
   {
      float desired_aspect = video_driver_get_aspect_ratio();

#if defined(HAVE_MENU)
      if (settings->video.aspect_ratio_idx == ASPECT_RATIO_CUSTOM)
      {
         video_viewport_t *custom = video_viewport_get_custom();

         if (custom)
         {
            *x          = custom->x;
            *y          = custom->y;
            *width      = custom->width;
            *height     = custom->height;
         }
      }
      else
#endif
      {
         float delta;

         if (fabsf(device_aspect - desired_aspect) < 0.0001f)
         {
            /* If the aspect ratios of screen and desired aspect 
             * ratio are sufficiently equal (floating point stuff), 
             * assume they are actually equal.
             */
         }
         else if (device_aspect > desired_aspect)
         {
            delta       = (desired_aspect / device_aspect - 1.0f) / 2.0f + 0.5f;
            *x           = int(roundf(*width * (0.5f - delta)));
            *width       = unsigned(roundf(2.0f * (*width) * delta));
         }
         else
         {
            delta       = (device_aspect / desired_aspect - 1.0f) / 2.0f + 0.5f;
            *y           = int(roundf(*height * (0.5f - delta)));
            *height      = unsigned(roundf(2.0f * (*height) * delta));
         }
      }
   }
}
예제 #6
0
static bool load_content_from_compressed_archive(
      struct string_list *temporary_content,
      struct retro_game_info *info, unsigned i,
      struct string_list* additional_path_allocs,
      bool need_fullpath, const char *path)
{
   union string_list_elem_attr attributes;
   char new_path[PATH_MAX_LENGTH];
   char new_basedir[PATH_MAX_LENGTH];
   ssize_t new_path_len              = 0;
   bool ret                          = false;
   settings_t *settings              = config_get_ptr();
   rarch_system_info_t      *sys_info= NULL;

   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &sys_info);

   if (sys_info && sys_info->info.block_extract)
      return true;
   if (!need_fullpath || !path_contains_compressed_file(path))
      return true;

   RARCH_LOG("Compressed file in case of need_fullpath."
         " Now extracting to temporary directory.\n");

   strlcpy(new_basedir, settings->cache_directory,
         sizeof(new_basedir));

   if (string_is_empty(new_basedir) || !path_is_directory(new_basedir))
   {
      RARCH_WARN("Tried extracting to cache directory, but "
            "cache directory was not set or found. "
            "Setting cache directory to directory "
            "derived by basename...\n");
      fill_pathname_basedir(new_basedir, path,
            sizeof(new_basedir));
   }

   attributes.i = 0;
   fill_pathname_join(new_path, new_basedir,
         path_basename(path), sizeof(new_path));

   ret = content_file_compressed_read(path, NULL, new_path, &new_path_len);

   if (!ret || new_path_len < 0)
   {
      RARCH_ERR("%s \"%s\".\n",
            msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE),
            path);
      return false;
   }

   RARCH_LOG("New path is: [%s]\n", new_path);

   string_list_append(additional_path_allocs, new_path, attributes);
   info[i].path = 
      additional_path_allocs->elems[additional_path_allocs->size -1 ].data;

   if (!string_list_append(temporary_content, new_path, attributes))
      return false;

   return true;
}
예제 #7
0
static bool gfx_ctx_glx_set_video_mode(void *data,
      unsigned width, unsigned height,
      bool fullscreen)
{
   XEvent event;
   bool true_full = false, windowed_full;
   int val, x_off = 0, y_off = 0;
   XVisualInfo *vi = NULL;
   XSetWindowAttributes swa = {0};
   int (*old_handler)(Display*, XErrorEvent*) = NULL;
   driver_t *driver = driver_get_ptr();
   gfx_ctx_glx_data_t *glx = (gfx_ctx_glx_data_t*)driver->video_context_data;
   struct sigaction sa = {{0}};
   settings_t *settings    = config_get_ptr();

   sa.sa_handler = glx_sighandler;
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

   if (!glx)
      return false;

   windowed_full = settings->video.windowed_fullscreen;
   true_full = false;

   vi = glXGetVisualFromFBConfig(glx->g_dpy, glx->g_fbc);
   if (!vi)
      goto error;

   swa.colormap = glx->g_cmap = XCreateColormap(glx->g_dpy,
         RootWindow(glx->g_dpy, vi->screen), vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask | KeyReleaseMask |
      ButtonReleaseMask | ButtonPressMask;
   swa.override_redirect = fullscreen ? True : False;

   if (fullscreen && !windowed_full)
   {
      if (x11_enter_fullscreen(glx->g_dpy, width, height, &glx->g_desktop_mode))
      {
         glx->g_should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[GLX]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   if (settings->video.monitor_index)
      glx->g_screen = settings->video.monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || glx->g_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (x11_get_xinerama_coord(glx->g_dpy, glx->g_screen,
               &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[GLX]: Using Xinerama on screen #%u.\n", glx->g_screen);
      else
         RARCH_LOG("[GLX]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[GLX]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   glx->g_win = XCreateWindow(glx->g_dpy, RootWindow(glx->g_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual, 
         CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa);
   XSetWindowBackground(glx->g_dpy, glx->g_win, 0);

   glx->g_glx_win = glXCreateWindow(glx->g_dpy, glx->g_fbc, glx->g_win, 0);

   x11_set_window_attr(glx->g_dpy, glx->g_win);

   if (fullscreen)
      x11_show_mouse(glx->g_dpy, glx->g_win, false);

   if (true_full)
   {
      RARCH_LOG("[GLX]: Using true fullscreen.\n");
      XMapRaised(glx->g_dpy, glx->g_win);
   }
   else if (fullscreen) /* We attempted true fullscreen, but failed. Attempt using windowed fullscreen. */
   {
      XMapRaised(glx->g_dpy, glx->g_win);
      RARCH_LOG("[GLX]: Using windowed fullscreen.\n");
      /* We have to move the window to the screen we want to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(glx->g_dpy, glx->g_win, x_off, y_off, width, height);
      x11_windowed_fullscreen(glx->g_dpy, glx->g_win);
   }
   else
   {
      XMapWindow(glx->g_dpy, glx->g_win);
      // If we want to map the window on a different screen, we'll have to do it by force.
      // Otherwise, we should try to let the window manager sort it out.
      // x_off and y_off usually get ignored in XCreateWindow().
      if (glx->g_screen)
         x11_move_window(glx->g_dpy, glx->g_win, x_off, y_off, width, height);
   }

   XIfEvent(glx->g_dpy, &event, glx_wait_notify, NULL);

   if (!glx->g_ctx)
   {
      if (glx->g_core_es || glx->g_debug)
      {
         int attribs[16];
         int *aptr = attribs;

         if (glx->g_core_es)
         {
            *aptr++ = GLX_CONTEXT_MAJOR_VERSION_ARB;
            *aptr++ = g_major;
            *aptr++ = GLX_CONTEXT_MINOR_VERSION_ARB;
            *aptr++ = g_minor;

            if (glx->g_core_es_core)
            {
               /* Technically, we don't have core/compat until 3.2.
                * Version 3.1 is either compat or not depending on GL_ARB_compatibility.
                */
               *aptr++ = GLX_CONTEXT_PROFILE_MASK_ARB;
#ifdef HAVE_OPENGLES2
               *aptr++ = GLX_CONTEXT_ES_PROFILE_BIT_EXT;
#else
               *aptr++ = GLX_CONTEXT_CORE_PROFILE_BIT_ARB;
#endif
            }
         }

         if (glx->g_debug)
         {
            *aptr++ = GLX_CONTEXT_FLAGS_ARB;
            *aptr++ = GLX_CONTEXT_DEBUG_BIT_ARB;
         }

         *aptr = None;
         glx->g_ctx = glx_create_context_attribs(glx->g_dpy, glx->g_fbc, NULL, True, attribs);
         if (glx->g_use_hw_ctx)
         {
            RARCH_LOG("[GLX]: Creating shared HW context.\n");
            glx->g_hw_ctx = glx_create_context_attribs(glx->g_dpy, glx->g_fbc, glx->g_ctx, True, attribs);
            if (!glx->g_hw_ctx)
               RARCH_ERR("[GLX]: Failed to create new shared context.\n");
         }
      }
      else
      {
         glx->g_ctx = glXCreateNewContext(glx->g_dpy, glx->g_fbc, GLX_RGBA_TYPE, 0, True);
         if (glx->g_use_hw_ctx)
         {
            glx->g_hw_ctx = glXCreateNewContext(glx->g_dpy, glx->g_fbc, GLX_RGBA_TYPE, glx->g_ctx, True);
            if (!glx->g_hw_ctx)
               RARCH_ERR("[GLX]: Failed to create new shared context.\n");
         }
      }

      if (!glx->g_ctx)
      {
         RARCH_ERR("[GLX]: Failed to create new context.\n");
         goto error;
      }
   }
   else
   {
      driver->video_cache_context_ack = true;
      RARCH_LOG("[GLX]: Using cached GL context.\n");
   }

   glXMakeContextCurrent(glx->g_dpy, glx->g_glx_win, glx->g_glx_win, glx->g_ctx);
   XSync(glx->g_dpy, False);

   g_quit_atom = XInternAtom(glx->g_dpy, "WM_DELETE_WINDOW", False);
   if (g_quit_atom)
      XSetWMProtocols(glx->g_dpy, glx->g_win, &g_quit_atom, 1);

   glXGetConfig(glx->g_dpy, vi, GLX_DOUBLEBUFFER, &val);
   glx->g_is_double = val;

   if (glx->g_is_double)
   {
      const char *swap_func = NULL;

      g_pglSwapIntervalEXT = (void (*)(Display*, GLXDrawable, int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalEXT");
      g_pglSwapIntervalSGI = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalSGI");
      g_pglSwapInterval    = (int (*)(int))glXGetProcAddress((const GLubyte*)"glXSwapIntervalMESA");

      if (g_pglSwapIntervalEXT)
         swap_func = "glXSwapIntervalEXT";
      else if (g_pglSwapInterval)
         swap_func = "glXSwapIntervalMESA";
      else if (g_pglSwapIntervalSGI)
         swap_func = "glXSwapIntervalSGI";

      if (!g_pglSwapInterval && !g_pglSwapIntervalEXT && !g_pglSwapIntervalSGI)
         RARCH_WARN("[GLX]: Cannot find swap interval call.\n");
      else
         RARCH_LOG("[GLX]: Found swap function: %s.\n", swap_func);
   }
   else
      RARCH_WARN("[GLX]: Context is not double buffered!.\n");

   gfx_ctx_glx_swap_interval(data, glx->g_interval);

   /* This can blow up on some drivers. It's not fatal, so override errors for this call. */
   old_handler = XSetErrorHandler(glx_nul_handler);
   XSetInputFocus(glx->g_dpy, glx->g_win, RevertToNone, CurrentTime);
   XSync(glx->g_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   glx->g_has_focus = true;

   if (!x11_create_input_context(glx->g_dpy, glx->g_win, &glx->g_xim, &glx->g_xic))
      goto error;

   driver->display_type  = RARCH_DISPLAY_X11;
   driver->video_display = (uintptr_t)glx->g_dpy;
   driver->video_window  = (uintptr_t)glx->g_win;
   glx->g_true_full = true_full;

   return true;

error:
   if (vi)
      XFree(vi);

   ctx_glx_destroy_resources(glx);

   if (glx)
      free(glx);

   return false;
}
예제 #8
0
unsigned menu_input_frame(retro_input_t input, retro_input_t trigger_input)
{
   float delta_time;
   unsigned ret                            = MENU_ACTION_NOOP;
   static bool initial_held                = true;
   static bool first_held                  = false;
   static const retro_input_t input_repeat =
        (1UL << RETRO_DEVICE_ID_JOYPAD_UP)
      | (1UL << RETRO_DEVICE_ID_JOYPAD_DOWN)
      | (1UL << RETRO_DEVICE_ID_JOYPAD_LEFT)
      | (1UL << RETRO_DEVICE_ID_JOYPAD_RIGHT)
      | (1UL << RETRO_DEVICE_ID_JOYPAD_L)
      | (1UL << RETRO_DEVICE_ID_JOYPAD_R);
   bool set_scroll                         = false;
   size_t new_scroll_accel                 = 0;
   menu_input_t *menu_input                = menu_input_get_ptr();
   driver_t *driver                        = driver_get_ptr();
   settings_t *settings                    = config_get_ptr();

   if (!driver || !menu_input)
      return 0;

   driver->retro_ctx.poll_cb();

   /* don't run anything first frame, only capture held inputs
    * for old_input_state. */

   if (input & input_repeat)
   {
      if (!first_held)
      {
         first_held = true;
         menu_input->delay.timer = initial_held ? 12 : 6;
         menu_input->delay.count = 0;
      }

      if (menu_input->delay.count >= menu_input->delay.timer)
      {
         set_scroll     = true;
         first_held     = false;
         trigger_input |= input & input_repeat;

         menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SCROLL_ACCEL,
               &new_scroll_accel);

         new_scroll_accel = min(new_scroll_accel + 1, 64);
      }

      initial_held  = false;
   }
   else
   {
      set_scroll   = true;
      first_held   = false;
      initial_held = true;
   }

   if (set_scroll)
      menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SCROLL_ACCEL,
            &new_scroll_accel);

   menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time);

   menu_input->delay.count += delta_time / IDEAL_DT;

   if (menu_input->keyboard.display)
   {
      /* send return key to close keyboard input window */
      if (trigger_input & (UINT64_C(1) << settings->menu_cancel_btn))
         input_keyboard_event(true, '\n', '\n', 0, RETRO_DEVICE_KEYBOARD);

      trigger_input = 0;
   }

   if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_UP))
      ret = MENU_ACTION_UP;
   else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_DOWN))
      ret = MENU_ACTION_DOWN;
   else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_LEFT))
      ret = MENU_ACTION_LEFT;
   else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_RIGHT))
      ret = MENU_ACTION_RIGHT;
   else if (trigger_input & (UINT64_C(1) << settings->menu_scroll_up_btn))
      ret = MENU_ACTION_SCROLL_UP;
   else if (trigger_input & (UINT64_C(1) << settings->menu_scroll_down_btn))
      ret = MENU_ACTION_SCROLL_DOWN;
   else if (trigger_input & (UINT64_C(1) << settings->menu_cancel_btn))
      ret = MENU_ACTION_CANCEL;
   else if (trigger_input & (UINT64_C(1) << settings->menu_ok_btn))
      ret = MENU_ACTION_OK;
   else if (trigger_input & (UINT64_C(1) << settings->menu_search_btn))
      ret = MENU_ACTION_SEARCH;
   else if (trigger_input & (UINT64_C(1) << RETRO_DEVICE_ID_JOYPAD_Y))
      ret = MENU_ACTION_SCAN;
   else if (trigger_input & (UINT64_C(1) << settings->menu_default_btn))
      ret = MENU_ACTION_START;
   else if (trigger_input & (UINT64_C(1) << settings->menu_info_btn))
      ret = MENU_ACTION_INFO;
   else if (trigger_input & (UINT64_C(1) << RARCH_MENU_TOGGLE))
      ret = MENU_ACTION_TOGGLE;

   if (settings->menu.mouse.enable)
      menu_input_mouse(&ret);

   if (settings->menu.pointer.enable)
      menu_input_pointer(&ret);

   return ret;
}
예제 #9
0
static int menu_input_mouse(unsigned *action)
{
   unsigned fb_width, fb_height;
   video_viewport_t vp;
   const struct retro_keybind *binds[MAX_USERS];
   menu_input_t *menu_input  = menu_input_get_ptr();
   settings_t *settings      = config_get_ptr();

   menu_display_ctl(MENU_DISPLAY_CTL_WIDTH,  &fb_width);
   menu_display_ctl(MENU_DISPLAY_CTL_HEIGHT, &fb_height);

   if (!settings->menu.mouse.enable
#ifdef HAVE_OVERLAY
       || (settings->input.overlay_enable && input_overlay_is_alive())
#endif
      )
   {
      memset(&menu_input->mouse, 0, sizeof(menu_input->mouse));
      return 0;
   }

   if (!video_driver_viewport_info(&vp))
      return -1;

   if (menu_input->mouse.hwheeldown)
   {
      *action = MENU_ACTION_LEFT;
      menu_input->mouse.hwheeldown = false;
      return 0;
   }

   if (menu_input->mouse.hwheelup)
   {
      *action = MENU_ACTION_RIGHT;
      menu_input->mouse.hwheelup = false;
      return 0;
   }

   menu_input->mouse.left       = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_LEFT);
   menu_input->mouse.right      = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_RIGHT);
   menu_input->mouse.wheelup    = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_WHEELUP);
   menu_input->mouse.wheeldown  = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_WHEELDOWN);
   menu_input->mouse.hwheelup   = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELUP);
   menu_input->mouse.hwheeldown = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_HORIZ_WHEELDOWN);
   menu_input->mouse.dx         = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_X);
   menu_input->mouse.dy         = input_driver_state(binds, 0, RETRO_DEVICE_MOUSE,
         0, RETRO_DEVICE_ID_MOUSE_Y);

   menu_input->mouse.screen_x += menu_input->mouse.dx;
   menu_input->mouse.screen_y += menu_input->mouse.dy;

   menu_input->mouse.x         = ((int)menu_input->mouse.screen_x * (int)fb_width) / (int)vp.width;
   menu_input->mouse.y         = ((int)menu_input->mouse.screen_y * (int)fb_height) / (int)vp.height;

   if (menu_input->mouse.x < 5)
      menu_input->mouse.x       = 5;
   if (menu_input->mouse.y < 5)
      menu_input->mouse.y       = 5;
   if (menu_input->mouse.x > (int)fb_width - 5)
      menu_input->mouse.x       = fb_width - 5;
   if (menu_input->mouse.y > (int)fb_height - 5)
      menu_input->mouse.y       = fb_height - 5;

   menu_input->mouse.scrollup   = (menu_input->mouse.y == 5);
   menu_input->mouse.scrolldown = (menu_input->mouse.y == (int)fb_height - 5);

   if (
         (menu_input->mouse.dx != 0)     ||
         (menu_input->mouse.dy !=0)      ||
         menu_input->mouse.left          ||
         menu_input->mouse.wheelup       ||
         menu_input->mouse.wheeldown     ||
         menu_input->mouse.hwheelup      ||
         menu_input->mouse.hwheeldown    ||
         menu_input->mouse.scrollup      ||
         menu_input->mouse.scrolldown
      )
      menu_animation_ctl(MENU_ANIMATION_CTL_SET_ACTIVE, NULL);

   return 0;
}
예제 #10
0
static bool ffmpeg_init_audio(ffmpeg_t *handle)
{
   settings_t *settings = config_get_ptr();
   struct ff_config_param *params = &handle->config;
   struct ff_audio_info *audio    = &handle->audio;
   struct ffemu_params *param     = &handle->params;
   AVCodec *codec                 = avcodec_find_encoder_by_name(
         *params->acodec ? params->acodec : "flac");
   if (!codec)
   {
      RARCH_ERR("[FFmpeg]: Cannot find acodec %s.\n",
            *params->acodec ? params->acodec : "flac");
      return false;
   }

   audio->encoder = codec;

   audio->codec = avcodec_alloc_context3(codec);

   audio->codec->codec_type     = AVMEDIA_TYPE_AUDIO;
   audio->codec->channels       = param->channels;
   audio->codec->channel_layout = (param->channels > 1)
      ? AV_CH_LAYOUT_STEREO : AV_CH_LAYOUT_MONO;

   ffmpeg_audio_resolve_format(audio, codec);
   ffmpeg_audio_resolve_sample_rate(handle, codec);

   if (params->sample_rate)
   {
      audio->ratio = (double)params->sample_rate / param->samplerate;
      audio->codec->sample_rate = params->sample_rate;
      audio->codec->time_base = av_d2q(1.0 / params->sample_rate, 1000000);

      rarch_resampler_realloc(&audio->resampler_data,
            &audio->resampler,
            settings->audio.resampler,
            audio->ratio);
   }
   else
   {
      audio->codec->sample_fmt = AV_SAMPLE_FMT_S16;
      audio->codec->sample_rate = (int)roundf(param->samplerate);
      audio->codec->time_base = av_d2q(1.0 / param->samplerate, 1000000);
   }

   if (params->audio_qscale)
   {
      audio->codec->flags |= CODEC_FLAG_QSCALE;
      audio->codec->global_quality = params->audio_global_quality;
   }
   else if (params->audio_bit_rate)
      audio->codec->bit_rate = params->audio_bit_rate;

   /* Allow experimental codecs. */
   audio->codec->strict_std_compliance = FF_COMPLIANCE_EXPERIMENTAL;

   if (handle->muxer.ctx->oformat->flags & AVFMT_GLOBALHEADER)
      audio->codec->flags |= CODEC_FLAG_GLOBAL_HEADER;

   if (avcodec_open2(audio->codec, codec, params->audio_opts ? &params->audio_opts : NULL) != 0)
      return false;

   if (!audio->codec->frame_size) /* If not set (PCM), just set something. */
      audio->codec->frame_size = 1024;

   audio->buffer = (uint8_t*)av_malloc(
         audio->codec->frame_size *
         audio->codec->channels *
         audio->sample_size);

#if 0
   RARCH_LOG("[FFmpeg]: Audio frame size: %d.\n", audio->codec->frame_size);
#endif

   if (!audio->buffer)
      return false;

   audio->outbuf_size = FF_MIN_BUFFER_SIZE;
   audio->outbuf = (uint8_t*)av_malloc(audio->outbuf_size);
   if (!audio->outbuf)
      return false;

   return true;
}
예제 #11
0
static int menu_input_pointer_post_iterate(menu_file_list_cbs_t *cbs,
      menu_entry_t *entry, unsigned action)
{
   unsigned header_height;
   size_t selection;
   int ret                  = 0;
   menu_list_t *menu_list   = menu_list_get_ptr();
   menu_input_t *menu_input = menu_input_get_ptr();
   settings_t *settings     = config_get_ptr();

   if (!menu_input)
      return -1;
   if (!menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection))
      return -1;
   menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);

   if (!settings->menu.pointer.enable
#ifdef HAVE_OVERLAY
       || (settings->input.overlay_enable && input_overlay_is_alive())
#endif
      )
      return 0;

   if (menu_input->pointer.pressed[0])
   {
      int16_t pointer_x = menu_input_pointer_state(MENU_POINTER_X_AXIS);
      int16_t pointer_y = menu_input_pointer_state(MENU_POINTER_Y_AXIS);

      if (!menu_input->pointer.oldpressed[0])
      {
         menu_input->pointer.accel         = 0;
         menu_input->pointer.accel0        = 0;
         menu_input->pointer.accel1        = 0;
         menu_input->pointer.start_x       = pointer_x;
         menu_input->pointer.start_y       = pointer_y;
         menu_input->pointer.old_x         = pointer_x;
         menu_input->pointer.old_y         = pointer_y;
         menu_input->pointer.oldpressed[0] = true;
      }
      else if (abs(pointer_x - menu_input->pointer.start_x) > 3
            || abs(pointer_y - menu_input->pointer.start_y) > 3)
      {
         float s, delta_time;
         menu_input->pointer.dragging      = true;
         menu_input->pointer.dx            = pointer_x - menu_input->pointer.old_x;
         menu_input->pointer.dy            = pointer_y - menu_input->pointer.old_y;
         menu_input->pointer.old_x         = pointer_x;
         menu_input->pointer.old_y         = pointer_y;

         menu_animation_ctl(MENU_ANIMATION_CTL_DELTA_TIME, &delta_time);

         s =  menu_input->pointer.dy / delta_time * 1000000.0;
         menu_input->pointer.accel = (menu_input->pointer.accel0 + menu_input->pointer.accel1 + s) / 3;
         menu_input->pointer.accel0 = menu_input->pointer.accel1;
         menu_input->pointer.accel1 = menu_input->pointer.accel;
      }
   }
   else
   {
      if (menu_input->pointer.oldpressed[0])
      {
         if (!menu_input->pointer.dragging)
         {
            if ((unsigned)menu_input->pointer.start_y < header_height)
            {
               menu_list_pop_stack(menu_list, &selection);
               menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
            }
            else if (menu_input->pointer.ptr <= menu_list_get_size(menu_list)-1)
            {
               menu_input->pointer.oldpressed[0] = false;
               ret = pointer_tap(cbs, entry, action);
            }
         }

         menu_input->pointer.oldpressed[0] = false;
         menu_input->pointer.start_x       = 0;
         menu_input->pointer.start_y       = 0;
         menu_input->pointer.old_x         = 0;
         menu_input->pointer.old_y         = 0;
         menu_input->pointer.dx            = 0;
         menu_input->pointer.dy            = 0;
         menu_input->pointer.dragging      = false;
      }
   }

   if (menu_input->pointer.back)
   {
      if (!menu_input->pointer.oldback)
      {
         menu_input->pointer.oldback = true;
         menu_list_pop_stack(menu_list, &selection);
         menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
      }
   }
   menu_input->pointer.oldback = menu_input->pointer.back;

   return ret;
}
예제 #12
0
파일: menu.c 프로젝트: 6lackmag3/RetroArch
/**
 * menu_init:
 * @data                     : Menu context handle.
 *
 * Create and initialize menu handle.
 *
 * Returns: menu handle on success, otherwise NULL.
 **/
void *menu_init(const void *data)
{
   menu_handle_t *menu         = NULL;
   menu_display_t *disp        = NULL;
   menu_ctx_driver_t *menu_ctx = (menu_ctx_driver_t*)data;
   global_t  *global           = global_get_ptr();
   settings_t *settings        = config_get_ptr();
   
   if (!menu_ctx)
      return NULL;

   if (!(menu = (menu_handle_t*)menu_ctx->init()))
      return NULL;

   strlcpy(settings->menu.driver, menu_ctx->ident,
         sizeof(settings->menu.driver));

   if (!menu_entries_init(menu))
      goto error;

   global->core_info.current = (core_info_t*)calloc(1, sizeof(core_info_t));
   if (!global->core_info.current)
      goto error;

#ifdef HAVE_SHADER_MANAGER
   menu->shader = (struct video_shader*)calloc(1, sizeof(struct video_shader));
   if (!menu->shader)
      goto error;
#endif

   menu->push_help_screen           = settings->menu_show_start_screen;
   menu->help_screen_type           = MENU_HELP_WELCOME;
   settings->menu_show_start_screen = false;

#if 0
   if (settings->bundle_assets_extract_enable &&
         (strcmp(PACKAGE_VERSION, settings->bundle_assets_last_extracted_version) != 0)
      )
   {
      menu->push_help_screen = true;
      menu->help_screen_type = MENU_HELP_EXTRACT;

      rarch_main_data_msg_queue_push(DATA_TYPE_FILE, "cb_bundle_extract", "cb_bundle_extract", 0, 1, true);
   }
#endif

   menu_shader_manager_init(menu);

   if (!menu_display_init(menu))
      goto error;

   disp = &menu->display;

   rarch_assert(disp->msg_queue = msg_queue_new(8));

   return menu;
   
error:
   menu_free(menu);

   return NULL;
}
예제 #13
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;
}
예제 #14
0
static int menu_input_key_bind_set_mode_common(rarch_setting_t  *setting,
      enum menu_input_bind_mode type)
{
   size_t selection;
   unsigned index_offset, bind_type;
   menu_displaylist_info_t info  = {0};
   struct retro_keybind *keybind = NULL;
   file_list_t *menu_stack       = NULL;
   settings_t     *settings      = config_get_ptr();
   menu_input_t      *menu_input = menu_input_get_ptr();

   if (!setting)
      return -1;

   index_offset = menu_setting_get_index_offset(setting);
   menu_stack   = menu_entries_get_menu_stack_ptr(0);

   menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection);

   switch (type)
   {
      case MENU_INPUT_BIND_NONE:
         return -1;
      case MENU_INPUT_BIND_SINGLE:
         keybind    = (struct retro_keybind*)setting_get_ptr(setting);

         if (!keybind)
            return -1;

         bind_type                = menu_setting_get_bind_type(setting);

         menu_input->binds.begin  = bind_type;
         menu_input->binds.last   = bind_type;
         menu_input->binds.target = keybind;
         menu_input->binds.user   = index_offset;

         info.list                = menu_stack;
         info.type                = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
         info.directory_ptr       = selection;
         strlcpy(info.label,
               menu_hash_to_str(MENU_LABEL_CUSTOM_BIND), sizeof(info.label));

         if (menu_displaylist_push_list(&info, DISPLAYLIST_INFO) == 0)
            menu_displaylist_push_list_process(&info);
         break;
      case MENU_INPUT_BIND_ALL:
         menu_input->binds.target = &settings->input.binds
            [index_offset][0];
         menu_input->binds.begin  = MENU_SETTINGS_BIND_BEGIN;
         menu_input->binds.last   = MENU_SETTINGS_BIND_LAST;

         info.list                = menu_stack;
         info.type                = MENU_SETTINGS_CUSTOM_BIND_KEYBOARD;
         info.directory_ptr       = selection;
         strlcpy(info.label,
               menu_hash_to_str(MENU_LABEL_CUSTOM_BIND_ALL),
               sizeof(info.label));

         if (menu_displaylist_push_list(&info, DISPLAYLIST_INFO) == 0)
            menu_displaylist_push_list_process(&info);
         break;
   }

   return 0;
}
예제 #15
0
int menu_dialog_iterate(char *s, size_t len, const char *label)
{
#ifdef HAVE_CHEEVOS
   cheevos_ctx_desc_t desc_info;
#endif
   bool do_exit              = false;
   settings_t *settings      = config_get_ptr();

   switch (menu_dialog_current_type)
   {
      case MENU_DIALOG_WELCOME:
         {
            static rarch_timer_t timer;

            if (!rarch_timer_is_running(&timer))
               rarch_timer_begin(&timer, 3);

            rarch_timer_tick(&timer);

            menu_hash_get_help_enum(
                  MENU_ENUM_LABEL_WELCOME_TO_RETROARCH,
                  s, len);

            if (!timer.timer_end && rarch_timer_has_expired(&timer))
            {
               rarch_timer_end(&timer);
               do_exit     = true;
            }
         }
         break;
      case MENU_DIALOG_HELP_CONTROLS:
         {
            unsigned i;
            char s2[PATH_MAX_LENGTH];
            const unsigned binds[] = {
               RETRO_DEVICE_ID_JOYPAD_UP,
               RETRO_DEVICE_ID_JOYPAD_DOWN,
               RETRO_DEVICE_ID_JOYPAD_A,
               RETRO_DEVICE_ID_JOYPAD_B,
               RETRO_DEVICE_ID_JOYPAD_SELECT,
               RETRO_DEVICE_ID_JOYPAD_START,
               RARCH_MENU_TOGGLE,
               RARCH_QUIT_KEY,
               RETRO_DEVICE_ID_JOYPAD_X,
               RETRO_DEVICE_ID_JOYPAD_Y,
            };
            char desc[ARRAY_SIZE(binds)][64];

            for (i = 0; i < ARRAY_SIZE(binds); i++)
               desc[i][0] = '\0';

            for (i = 0; i < ARRAY_SIZE(binds); i++)
            {
               const struct retro_keybind *keybind = &input_config_binds[0][binds[i]];
               const struct retro_keybind *auto_bind =
                  (const struct retro_keybind*)
                  input_config_get_bind_auto(0, binds[i]);

               input_config_get_bind_string(desc[i],
                     keybind, auto_bind, sizeof(desc[i]));
            }

            s2[0] = '\0';

            menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_MENU_ENUM_CONTROLS_PROLOG,
                  s2, sizeof(s2));

            snprintf(s, len,
                  "%s"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n"
                  "[%s]: "
                  "%-20s\n",

                  s2,

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_UP),
                  desc[0],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_SCROLL_DOWN),
                  desc[1],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_CONFIRM),
                  desc[2],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_BACK),
                  desc[3],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_INFO),
                  desc[4],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_START),
                  desc[5],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_MENU),
                  desc[6],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_QUIT),
                  desc[7],

                  msg_hash_to_str(
                        MENU_ENUM_LABEL_VALUE_BASIC_MENU_CONTROLS_TOGGLE_KEYBOARD),
                  desc[8]

                  );
         }
         break;

#ifdef HAVE_CHEEVOS
      case MENU_DIALOG_HELP_CHEEVOS_DESCRIPTION:
         desc_info.idx = menu_dialog_current_id;
         desc_info.s   = s;
         desc_info.len = len;
         cheevos_get_description(&desc_info);
         break;
#endif

      case MENU_DIALOG_HELP_WHAT_IS_A_CORE:
         menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_WHAT_IS_A_CORE_DESC,
               s, len);
         break;
      case MENU_DIALOG_HELP_LOADING_CONTENT:
         menu_hash_get_help_enum(MENU_ENUM_LABEL_LOAD_CONTENT_LIST,
               s, len);
         break;
      case MENU_DIALOG_HELP_CHANGE_VIRTUAL_GAMEPAD:
         menu_hash_get_help_enum(
               MENU_ENUM_LABEL_VALUE_HELP_CHANGE_VIRTUAL_GAMEPAD_DESC,
               s, len);
         break;
      case MENU_DIALOG_HELP_AUDIO_VIDEO_TROUBLESHOOTING:
         menu_hash_get_help_enum(
               MENU_ENUM_LABEL_VALUE_HELP_AUDIO_VIDEO_TROUBLESHOOTING_DESC,
               s, len);
         break;
      case MENU_DIALOG_HELP_SCANNING_CONTENT:
         menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_HELP_SCANNING_CONTENT_DESC,
               s, len);
         break;
      case MENU_DIALOG_HELP_EXTRACT:
         menu_hash_get_help_enum(MENU_ENUM_LABEL_VALUE_EXTRACTING_PLEASE_WAIT,
               s, len);

         if (settings->bools.bundle_finished)
         {
            settings->bools.bundle_finished = false;
            do_exit                         = true;
         }
         break;
      case MENU_DIALOG_QUIT_CONFIRM:
      case MENU_DIALOG_INFORMATION:
      case MENU_DIALOG_QUESTION:
      case MENU_DIALOG_WARNING:
      case MENU_DIALOG_ERROR:
         menu_hash_get_help_enum(menu_dialog_current_msg,
               s, len);
         break;
      case MENU_DIALOG_NONE:
      default:
         break;
   }

   if (do_exit)
   {
      menu_dialog_current_type = MENU_DIALOG_NONE;
      return 1;
   }

   return 0;
}
예제 #16
0
static int menu_input_mouse_post_iterate(uint64_t *input_mouse,
      menu_file_list_cbs_t *cbs, unsigned action)
{
   size_t selection;
   unsigned header_height;
   settings_t *settings     = config_get_ptr();
   menu_input_t *menu_input = menu_input_get_ptr();
   menu_list_t *menu_list   = menu_list_get_ptr();

   *input_mouse = MOUSE_ACTION_NONE;

   menu_navigation_ctl(MENU_NAVIGATION_CTL_GET_SELECTION, &selection);

   if (!settings->menu.mouse.enable
#ifdef HAVE_OVERLAY
       || (settings->input.overlay_enable && input_overlay_is_alive())
#endif
       )
   {
      menu_input->mouse.wheeldown = false;
      menu_input->mouse.wheelup   = false;
      menu_input->mouse.oldleft   = false;
      menu_input->mouse.oldright  = false;
      return 0;
   }

   if (menu_input->mouse.left)
   {
      if (!menu_input->mouse.oldleft)
      {
         menu_display_ctl(MENU_DISPLAY_CTL_HEADER_HEIGHT, &header_height);

         BIT64_SET(*input_mouse, MOUSE_ACTION_BUTTON_L);

         menu_input->mouse.oldleft = true;

         if ((unsigned)menu_input->mouse.y < header_height)
         {
            menu_list_pop_stack(menu_list, &selection);
            menu_navigation_ctl(MENU_NAVIGATION_CTL_SET_SELECTION, &selection);
            return 0;
         }
         if ((menu_input->mouse.ptr == selection) && cbs && cbs->action_select)
         {
            BIT64_SET(*input_mouse, MOUSE_ACTION_BUTTON_L_TOGGLE);
         }
         else if (menu_input->mouse.ptr <= menu_list_get_size(menu_list)-1)
         {
            BIT64_SET(*input_mouse, MOUSE_ACTION_BUTTON_L_SET_NAVIGATION);
         }
      }
   }
   else
      menu_input->mouse.oldleft = false;

   if (menu_input->mouse.right)
   {
      if (!menu_input->mouse.oldright)
      {
         menu_input->mouse.oldright = true;
         BIT64_SET(*input_mouse, MOUSE_ACTION_BUTTON_R);
      }
   }
   else
      menu_input->mouse.oldright = false;

   if (menu_input->mouse.wheeldown)
   {
      BIT64_SET(*input_mouse, MOUSE_ACTION_WHEEL_DOWN);
   }

   if (menu_input->mouse.wheelup)
   {
      BIT64_SET(*input_mouse, MOUSE_ACTION_WHEEL_UP);
   }

   return 0;
}
예제 #17
0
/**
 * content_load_state:
 * @path      : path that state will be loaded from.
 *
 * Load a state from disk to memory.
 *
 * Returns: true if successful, false otherwise.
 **/
static bool content_load_state(const char *path)
{
   unsigned i;
   ssize_t size;
   retro_ctx_serialize_info_t serial_info;
   unsigned num_blocks       = 0;
   void *buf                 = NULL;
   struct sram_block *blocks = NULL;
   settings_t *settings      = config_get_ptr();
   global_t *global          = global_get_ptr();
   bool ret                  = filestream_read_file(path, &buf, &size);

   RARCH_LOG("%s: \"%s\".\n",
         msg_hash_to_str(MSG_LOADING_STATE),
         path);

   if (!ret || size < 0)
      goto error;

   RARCH_LOG("%s: %u %s.\n",
         msg_hash_to_str(MSG_STATE_SIZE),
         (unsigned)size,
         msg_hash_to_str(MSG_BYTES));

   if (settings->block_sram_overwrite && global->savefiles
         && global->savefiles->size)
   {
      RARCH_LOG("%s.\n",
            msg_hash_to_str(MSG_BLOCKING_SRAM_OVERWRITE));
      blocks = (struct sram_block*)
         calloc(global->savefiles->size, sizeof(*blocks));

      if (blocks)
      {
         num_blocks = global->savefiles->size;
         for (i = 0; i < num_blocks; i++)
            blocks[i].type = global->savefiles->elems[i].attr.i;
      }
   }


   for (i = 0; i < num_blocks; i++)
   {
      retro_ctx_memory_info_t    mem_info;

      mem_info.id = blocks[i].type;
      core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info);

      blocks[i].size = mem_info.size;
   }

   for (i = 0; i < num_blocks; i++)
      if (blocks[i].size)
         blocks[i].data = malloc(blocks[i].size);

   /* Backup current SRAM which is overwritten by unserialize. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         retro_ctx_memory_info_t    mem_info;
         const void *ptr = NULL;

         mem_info.id = blocks[i].type;

         core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info);

         ptr = mem_info.data;
         if (ptr)
            memcpy(blocks[i].data, ptr, blocks[i].size);
      }
   }

   serial_info.data_const = buf;
   serial_info.size       = size;
   ret = core_ctl(CORE_CTL_RETRO_UNSERIALIZE, &serial_info);

   /* Flush back. */
   for (i = 0; i < num_blocks; i++)
   {
      if (blocks[i].data)
      {
         retro_ctx_memory_info_t    mem_info;
         void *ptr = NULL;

         mem_info.id = blocks[i].type;

         core_ctl(CORE_CTL_RETRO_GET_MEMORY, &mem_info);

         ptr = mem_info.data;
         if (ptr)
            memcpy(ptr, blocks[i].data, blocks[i].size);
      }
   }

   for (i = 0; i < num_blocks; i++)
      free(blocks[i].data);
   free(blocks);
   free(buf);
   
   if (!ret)
      goto error;

   return true;

error:
   RARCH_ERR("%s \"%s\".\n",
         msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE),
         path);
   return false;
}
예제 #18
0
void input_mapper_poll(input_mapper_t *handle)
{
   unsigned i, j;
   input_bits_t current_input;
   settings_t *settings                       = config_get_ptr();
   unsigned max_users                         =
      *(input_driver_get_uint(INPUT_ACTION_MAX_USERS));
   bool key_event[RARCH_CUSTOM_BIND_LIST_END] = { false };
#ifdef HAVE_OVERLAY
   bool poll_overlay = input_overlay_is_alive(overlay_ptr) ? true : false;
#endif

#ifdef HAVE_MENU
   if (menu_driver_is_alive())
      return;
#endif

   memset(handle->keys, 0, sizeof(handle->keys));

   for (i = 0; i < max_users; i++)
   {
      unsigned device  = settings->uints.input_libretro_device[i];
      device          &= RETRO_DEVICE_MASK;

      switch (device)
      {
            /* keyboard to gamepad remapping */
         case RETRO_DEVICE_KEYBOARD:
            BIT256_CLEAR_ALL_PTR(&current_input);
            input_get_state_for_port(settings, i, &current_input);
            for (j = 0; j < RARCH_CUSTOM_BIND_LIST_END; j++)
            {
               unsigned remap_button         = 
                  settings->uints.input_keymapper_ids[i][j];
               bool remap_valid              = remap_button != RETROK_UNKNOWN;

               if (remap_valid)
               {
                  unsigned current_button_value = BIT256_GET(current_input, j);
#ifdef HAVE_OVERLAY
               if (poll_overlay && i == 0)
                  current_button_value |= input_overlay_key_pressed(overlay_ptr, j);
#endif
                  if ((current_button_value == 1) && (j != remap_button))
                  {
                     MAPPER_SET_KEY (handle,
                           remap_button);
                     input_keyboard_event(true,
                           remap_button,
                           0, 0, RETRO_DEVICE_KEYBOARD);
                     key_event[j] = true;
                  }
                  /* key_event tracks if a key is pressed for ANY PLAYER, so we must check 
                     if the key was used by any player before releasing */
                  else if (!key_event[j])
                  {
                     input_keyboard_event(false,
                           remap_button,
                           0, 0, RETRO_DEVICE_KEYBOARD);
                  }
               }
            }
            break;

            /* gamepad remapping */
         case RETRO_DEVICE_JOYPAD:
         case RETRO_DEVICE_ANALOG:
            /* this loop iterates on all users and all buttons, 
             * and checks if a pressed button is assigned to any 
             * other button than the default one, then it sets 
             * the bit on the mapper input bitmap, later on the 
             * original input is cleared in input_state */
            BIT256_CLEAR_ALL(handle->buttons[i]);
            BIT256_CLEAR_ALL_PTR(&current_input);

            for (j = 0; j < 8; j++)
               handle->analog_value[i][j] = 0;

            input_get_state_for_port(settings, i, &current_input);

            for (j = 0; j < RARCH_FIRST_CUSTOM_BIND; j++)
            {
               bool remap_valid;
               unsigned remap_button;
               unsigned current_button_value = BIT256_GET(current_input, j);
#ifdef HAVE_OVERLAY
               if (poll_overlay && i == 0)
                  current_button_value |= input_overlay_key_pressed(overlay_ptr, j);
#endif

               remap_button                  =
                  settings->uints.input_remap_ids[i][j];
               remap_valid                   = (current_button_value == 1) &&
                  (j != remap_button) && (remap_button != RARCH_UNMAPPED);

               if (remap_valid)
               {
                  if (remap_button < RARCH_FIRST_CUSTOM_BIND)
                  {
                     BIT256_SET(handle->buttons[i], remap_button);
                  }
                  else if (remap_button >= RARCH_FIRST_CUSTOM_BIND)
                  {
                     int invert = 1;

                     if (remap_button % 2 != 0)
                        invert = -1;

                     handle->analog_value[i][
                        remap_button - RARCH_FIRST_CUSTOM_BIND] = 
                           32767 * invert;
                  }
               }
            }

            for (j = 0; j < 8; j++)
            {
               unsigned k                 = j + RARCH_FIRST_CUSTOM_BIND;
               int16_t current_axis_value = current_input.analogs[j];
               unsigned remap_axis        = 
                  settings->uints.input_remap_ids[i][k];

               if (
                     (abs(current_axis_value) > 0 &&
                     (k != remap_axis)            &&
                     (remap_axis != RARCH_UNMAPPED)
                  ))
               {
                  if (remap_axis < RARCH_FIRST_CUSTOM_BIND && 
                     abs(current_axis_value) > *input_driver_get_float(INPUT_ACTION_AXIS_THRESHOLD) * 32767)
                  {
                     BIT256_SET(handle->buttons[i], remap_axis);
                  }
                  else
                  {
                     int invert = 1;

                     if (  (k % 2 == 0 && remap_axis % 2 != 0) || 
                           (k % 2 != 0 && remap_axis % 2 == 0)
                        )
                        invert = -1;

                     handle->analog_value[i][
                        remap_axis - RARCH_FIRST_CUSTOM_BIND] = 
                           current_axis_value * invert;
#if 0
                     RARCH_LOG("axis %d(%d) remapped to axis %d val %d\n",
                           j, k, 
                           remap_axis - RARCH_FIRST_CUSTOM_BIND,
                           current_axis_value);
#endif
                  }
               }

            }
            break;
         default:
            break;
      }
   }
}
예제 #19
0
static bool gfx_ctx_xegl_set_video_mode(void *data,
   unsigned width, unsigned height,
   bool fullscreen)
{
   EGLint egl_attribs[16];
   EGLint *attr;
   EGLint vid, num_visuals;
   bool windowed_full;
   bool true_full = false;
   int x_off = 0;
   int y_off = 0;
   struct sigaction sa = {{0}};
   XVisualInfo temp = {0};
   XSetWindowAttributes swa = {0};
   XVisualInfo *vi = NULL;
   driver_t *driver     = driver_get_ptr();
   settings_t *settings = config_get_ptr();

   int (*old_handler)(Display*, XErrorEvent*) = NULL;

   XEvent event;

   sa.sa_handler = egl_sighandler;
   sa.sa_flags   = SA_RESTART;
   sigemptyset(&sa.sa_mask);
   sigaction(SIGINT, &sa, NULL);
   sigaction(SIGTERM, &sa, NULL);

   windowed_full = settings->video.windowed_fullscreen;
   true_full = false;

   attr = egl_attribs;
   attr = xegl_fill_attribs(attr);

   if (!eglGetConfigAttrib(g_egl_dpy, g_egl_config, EGL_NATIVE_VISUAL_ID, &vid))
      goto error;

   temp.visualid = vid;

   vi = XGetVisualInfo(g_dpy, VisualIDMask, &temp, &num_visuals);
   if (!vi)
      goto error;

   swa.colormap = g_cmap = XCreateColormap(g_dpy, RootWindow(g_dpy, vi->screen),
         vi->visual, AllocNone);
   swa.event_mask = StructureNotifyMask | KeyPressMask | ButtonPressMask | ButtonReleaseMask | KeyReleaseMask;
   swa.override_redirect = fullscreen ? True : False;

   if (fullscreen && !windowed_full)
   {
      if (x11_enter_fullscreen(g_dpy, width, height, &g_desktop_mode))
      {
         g_should_reset_mode = true;
         true_full = true;
      }
      else
         RARCH_ERR("[X/EGL]: Entering true fullscreen failed. Will attempt windowed mode.\n");
   }

   if (settings->video.monitor_index)
      g_screen = settings->video.monitor_index - 1;

#ifdef HAVE_XINERAMA
   if (fullscreen || g_screen != 0)
   {
      unsigned new_width  = width;
      unsigned new_height = height;

      if (x11_get_xinerama_coord(g_dpy, g_screen, &x_off, &y_off, &new_width, &new_height))
         RARCH_LOG("[X/EGL]: Using Xinerama on screen #%u.\n", g_screen);
      else
         RARCH_LOG("[X/EGL]: Xinerama is not active on screen.\n");

      if (fullscreen)
      {
         width  = new_width;
         height = new_height;
      }
   }
#endif

   RARCH_LOG("[X/EGL]: X = %d, Y = %d, W = %u, H = %u.\n",
         x_off, y_off, width, height);

   g_win = XCreateWindow(g_dpy, RootWindow(g_dpy, vi->screen),
         x_off, y_off, width, height, 0,
         vi->depth, InputOutput, vi->visual, 
         CWBorderPixel | CWColormap | CWEventMask | (true_full ? CWOverrideRedirect : 0), &swa);
   XSetWindowBackground(g_dpy, g_win, 0);

   g_egl_ctx = eglCreateContext(g_egl_dpy, g_egl_config, EGL_NO_CONTEXT,
         attr != egl_attribs ? egl_attribs : NULL);

   RARCH_LOG("[X/EGL]: Created context: %p.\n", (void*)g_egl_ctx);

   if (g_egl_ctx == EGL_NO_CONTEXT)
      goto error;

   if (g_use_hw_ctx)
   {
      g_egl_hw_ctx = eglCreateContext(g_egl_dpy, g_egl_config, g_egl_ctx,
            attr != egl_attribs ? egl_attribs : NULL);
      RARCH_LOG("[X/EGL]: Created shared context: %p.\n", (void*)g_egl_hw_ctx);

      if (g_egl_hw_ctx == EGL_NO_CONTEXT)
         goto error;
   }

   g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_egl_config, (EGLNativeWindowType)g_win, NULL);
   if (!g_egl_surf)
      goto error;

   if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
      goto error;

   RARCH_LOG("[X/EGL]: Current context: %p.\n", (void*)eglGetCurrentContext());

   x11_set_window_attr(g_dpy, g_win);

   if (fullscreen)
      x11_show_mouse(g_dpy, g_win, false);

   if (true_full)
   {
      RARCH_LOG("[X/EGL]: Using true fullscreen.\n");
      XMapRaised(g_dpy, g_win);
   }
   else if (fullscreen) 
   {
      /* We attempted true fullscreen, but failed.
       * Attempt using windowed fullscreen. */
      XMapRaised(g_dpy, g_win);
      RARCH_LOG("[X/EGL]: Using windowed fullscreen.\n");

      /* We have to move the window to the screen we 
       * want to go fullscreen on first.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      x11_move_window(g_dpy, g_win, x_off, y_off, width, height);
      x11_windowed_fullscreen(g_dpy, g_win);
   }
   else
   {
      XMapWindow(g_dpy, g_win);

      /* If we want to map the window on a different screen, 
       * we'll have to do it by force.
       *
       * Otherwise, we should try to let the window manager sort it out.
       * x_off and y_off usually get ignored in XCreateWindow().
       */
      if (g_screen)
         x11_move_window(g_dpy, g_win, x_off, y_off, width, height);
   }

   XIfEvent(g_dpy, &event, egl_wait_notify, NULL);

   g_quit_atom = XInternAtom(g_dpy, "WM_DELETE_WINDOW", False);
   if (g_quit_atom)
      XSetWMProtocols(g_dpy, g_win, &g_quit_atom, 1);

   gfx_ctx_xegl_swap_interval(data, g_interval);

   /* This can blow up on some drivers. It's not fatal, 
    * so override errors for this call.
    */
   old_handler = XSetErrorHandler(egl_nul_handler);
   XSetInputFocus(g_dpy, g_win, RevertToNone, CurrentTime);
   XSync(g_dpy, False);
   XSetErrorHandler(old_handler);

   XFree(vi);
   g_has_focus = true;
   g_inited    = true;

   if (!x11_create_input_context(g_dpy, g_win, &g_xim, &g_xic))
      goto error;

   driver->display_type  = RARCH_DISPLAY_X11;
   driver->video_display = (uintptr_t)g_dpy;
   driver->video_window  = (uintptr_t)g_win;
   g_true_full = true_full;

   return true;

error:
   if (vi)
      XFree(vi);

   gfx_ctx_xegl_destroy(data);
   return false;
}
예제 #20
0
static void *gfx_ctx_vc_init(void *video_driver)
{
   VC_DISPMANX_ALPHA_T alpha;
   EGLint n, major, minor;
   static EGL_DISPMANX_WINDOW_T nativewindow;

   DISPMANX_ELEMENT_HANDLE_T dispman_element;
   DISPMANX_DISPLAY_HANDLE_T dispman_display;
   DISPMANX_UPDATE_HANDLE_T dispman_update;
   DISPMANX_MODEINFO_T dispman_modeinfo;
   VC_RECT_T dst_rect;
   VC_RECT_T src_rect;

#ifdef HAVE_EGL
   static const EGLint attribute_list[] =
   {
      EGL_RED_SIZE, 8,
      EGL_GREEN_SIZE, 8,
      EGL_BLUE_SIZE, 8,
      EGL_ALPHA_SIZE, 8,
      EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
      EGL_NONE
   };

   static const EGLint context_attributes[] =
   {
      EGL_CONTEXT_CLIENT_VERSION, 2,
      EGL_NONE
   };
#endif
   settings_t *settings = config_get_ptr();
   vc_ctx_data_t *vc    = NULL;

   if (g_egl_inited)
   {
      RARCH_ERR("[VC/EGL]: Attempted to re-initialize driver.\n");
      return NULL;
   }

   vc = (vc_ctx_data_t*)calloc(1, sizeof(*vc));

   if (!vc)
       return NULL;

   bcm_host_init();

#ifdef HAVE_EGL
   if (!egl_init_context(&vc->egl, EGL_DEFAULT_DISPLAY,
            &major, &minor, &n, attribute_list))
   {
      egl_report_error();
      goto error;
   }

   if (!egl_create_context(&vc->egl, (vc_api == GFX_CTX_OPENGL_ES_API) ? context_attributes : NULL))
   {
      egl_report_error();
      goto error;
   }
#endif

   /* Create an EGL window surface. */
   if (graphics_get_display_size(0 /* LCD */, &vc->fb_width, &vc->fb_height) < 0)
      goto error;

   dst_rect.x = 0;
   dst_rect.y = 0;
   dst_rect.width = vc->fb_width;
   dst_rect.height = vc->fb_height;

   src_rect.x = 0;
   src_rect.y = 0;

   /* Use dispmanx upscaling if fullscreen_x 
    * and fullscreen_y are set. */
   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)vc->fb_width / (float)vc->fb_height;
      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         src_rect.width = (unsigned)(settings->video.fullscreen_y * dstAspect) << 16;
      else
         src_rect.width = settings->video.fullscreen_x << 16;
      src_rect.height = settings->video.fullscreen_y << 16;
   }
   else
   {
      src_rect.width  = vc->fb_width << 16;
      src_rect.height = vc->fb_height << 16;
   }

   dispman_display = vc_dispmanx_display_open(0 /* LCD */);
   vc_dispmanx_display_get_info(dispman_display, &dispman_modeinfo);
   dispman_update = vc_dispmanx_update_start(0);

   alpha.flags = DISPMANX_FLAGS_ALPHA_FIXED_ALL_PIXELS;
   alpha.opacity = 255;
   alpha.mask = 0;

   dispman_element = vc_dispmanx_element_add(dispman_update, dispman_display,
      0 /*layer*/, &dst_rect, 0 /*src*/,
      &src_rect, DISPMANX_PROTECTION_NONE, &alpha, 0 /*clamp*/, DISPMANX_NO_ROTATE);

   nativewindow.element = dispman_element;

   /* Use dispmanx upscaling if fullscreen_x and fullscreen_y are set. */

   if (settings->video.fullscreen_x != 0 &&
      settings->video.fullscreen_y != 0)
   {
      /* Keep input and output aspect ratio equal.
       * There are other aspect ratio settings which 
       * can be used to stretch video output. */

      /* Calculate source and destination aspect ratios. */
      float srcAspect = (float)settings->video.fullscreen_x / (float)settings->video.fullscreen_y;
      float dstAspect = (float)vc->fb_width / (float)vc->fb_height;

      /* If source and destination aspect ratios are not equal correct source width. */
      if (srcAspect != dstAspect)
         nativewindow.width = (unsigned)(settings->video.fullscreen_y * dstAspect);
      else
         nativewindow.width = settings->video.fullscreen_x;
      nativewindow.height = settings->video.fullscreen_y;
   }
   else
   {
      nativewindow.width = vc->fb_width;
      nativewindow.height = vc->fb_height;
   }
   vc_dispmanx_update_submit_sync(dispman_update);

#ifdef HAVE_EGL
   if (!egl_create_surface(&vc->egl, &nativewindow))
      goto error;
#endif

   return vc;

error:
   gfx_ctx_vc_destroy(video_driver);
   return NULL;
}
예제 #21
0
static void qnx_process_keyboard_event(
      qnx_input_t *qnx,
      screen_event_t event, int type)
{
   qnx_input_device_t* controller = NULL;
   settings_t *settings = config_get_ptr();
   int i = 0;
   int sym = 0;
   int modifiers = 0;
   int flags = 0;
   int scan = 0;
   int cap = 0;
   uint64_t *state_cur = NULL;

   /* Get Keyboard state. */
   screen_get_event_property_iv(event,
         SCREEN_PROPERTY_KEY_SYM, &sym);
   screen_get_event_property_iv(event,
         SCREEN_PROPERTY_KEY_MODIFIERS, &modifiers);
   screen_get_event_property_iv(event,
         SCREEN_PROPERTY_KEY_FLAGS, &flags);
   screen_get_event_property_iv(event,
         SCREEN_PROPERTY_KEY_SCAN, &scan);
   screen_get_event_property_iv(event,
         SCREEN_PROPERTY_KEY_CAP, &cap);

#ifdef HAVE_BB10
   /* Find device that pressed the key. */
   screen_device_t device;

   screen_get_event_property_pv(event,
         SCREEN_PROPERTY_DEVICE, (void**)&device);

   for (i = 0; i < MAX_PADS; ++i)
   {
      if (device == qnx->devices[i].handle)
      {
         controller = (qnx_input_device_t*)&qnx->devices[i];
         break;
      }
   }

   if (!controller)
      return;
#else
   controller = (qnx_input_device_t*)&qnx->devices[0];
#endif

   if(controller->port == -1)
      return;

   state_cur = &qnx->pad_state[controller->port];
   *state_cur = 0;

   for (b = 0; b < RARCH_FIRST_CUSTOM_BIND; ++b)
   {
      if ((unsigned int)
            settings->input.binds[controller->port][b].joykey 
            == (unsigned int)(sym & 0xFF))
      {
         if (flags & KEY_DOWN)
         {
            controller->buttons |= 1 << b;
            *state_cur |= 1 << b;
         }
         else
            controller->buttons &= ~(1<<b);
      }
   }

   /* TODO: Am I missing something? Is there a better way? */
   if((controller->port == 0) && ((unsigned int)
            settings->input.binds[0][RARCH_MENU_TOGGLE].joykey 
            == (unsigned int)(sym&0xFF)))
   {
      if (flags & KEY_DOWN)
         qnx->lifecycle_state ^= (UINT64_C(1) << RARCH_MENU_TOGGLE);
   }
}
예제 #22
0
static const char *android_joypad_name(unsigned pad)
{
   settings_t *settings = config_get_ptr();
   return settings ? settings->input.device_names[pad] : NULL;
}
예제 #23
0
void d3d_make_d3dpp(void *data,
      const video_info_t *info, D3DPRESENT_PARAMETERS *d3dpp)
{
   d3d_video_t     *d3d = (d3d_video_t*)data;
   settings_t *settings = config_get_ptr();
#ifdef _XBOX
   /* TODO/FIXME - get rid of global state dependencies. */
   global_t *global     = global_get_ptr();
#endif

   memset(d3dpp, 0, sizeof(*d3dpp));

   d3dpp->Windowed             = false;
#ifndef _XBOX
   d3dpp->Windowed             = settings->video.windowed_fullscreen || !info->fullscreen;
#endif
   d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;

   if (info->vsync)
   {
      switch (settings->video.swap_interval)
      {
         default:
         case 1:
            d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_ONE;
            break;
         case 2:
            d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_TWO;
            break;
         case 3:
            d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_THREE;
            break;
         case 4:
            d3dpp->PresentationInterval = D3DPRESENT_INTERVAL_FOUR;
            break;
      }
   }

   d3dpp->SwapEffect = D3DSWAPEFFECT_DISCARD;
   d3dpp->BackBufferCount = 2;
#ifdef _XBOX
   d3dpp->BackBufferFormat =
#ifdef _XBOX360
      global->console.screen.gamma_correction ?
      (D3DFORMAT)MAKESRGBFMT(info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5) :
#endif
      info->rgb32 ? D3DFMT_X8R8G8B8 : D3DFMT_LIN_R5G6B5;
#else
   d3dpp->hDeviceWindow    = win32_get_window();
   d3dpp->BackBufferFormat = !d3dpp->Windowed ? D3DFMT_X8R8G8B8 : D3DFMT_UNKNOWN;
#endif

   if (!d3dpp->Windowed)
   {
#ifdef _XBOX
      unsigned width          = 0;
      unsigned height         = 0;

      gfx_ctx_get_video_size(&width, &height);
      video_driver_set_size(&width, &height);
#endif
      video_driver_get_size(&d3dpp->BackBufferWidth, &d3dpp->BackBufferHeight);
   }

#ifdef _XBOX
   d3dpp->MultiSampleType         = D3DMULTISAMPLE_NONE;
   d3dpp->EnableAutoDepthStencil  = FALSE;
#if defined(_XBOX1)
   /* Get the "video mode" */
   DWORD video_mode               = XGetVideoFlags();

   /* Check if we are able to use progressive mode. */
   if (video_mode & XC_VIDEO_FLAGS_HDTV_480p)
      d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE;
   else
      d3dpp->Flags = D3DPRESENTFLAG_INTERLACED;

   /* Only valid in PAL mode, not valid for HDTV modes. */
   if (XGetVideoStandard() == XC_VIDEO_STANDARD_PAL_I)
   {
      if (video_mode & XC_VIDEO_FLAGS_PAL_60Hz)
         d3dpp->FullScreen_RefreshRateInHz = 60;
      else
         d3dpp->FullScreen_RefreshRateInHz = 50;
   }

   if (XGetAVPack() == XC_AV_PACK_HDTV)
   {
      if (video_mode & XC_VIDEO_FLAGS_HDTV_480p)
         d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE;
      else if (video_mode & XC_VIDEO_FLAGS_HDTV_720p)
         d3dpp->Flags = D3DPRESENTFLAG_PROGRESSIVE;
      else if (video_mode & XC_VIDEO_FLAGS_HDTV_1080i)
         d3dpp->Flags = D3DPRESENTFLAG_INTERLACED;
   }

   if (widescreen_mode)
      d3dpp->Flags |= D3DPRESENTFLAG_WIDESCREEN;
#elif defined(_XBOX360)
   if (!widescreen_mode)
      d3dpp->Flags |= D3DPRESENTFLAG_NO_LETTERBOX;

   if (global->console.screen.gamma_correction)
      d3dpp->FrontBufferFormat       = (D3DFORMAT)MAKESRGBFMT(D3DFMT_LE_X8R8G8B8);
   else
      d3dpp->FrontBufferFormat       = D3DFMT_LE_X8R8G8B8;
   d3dpp->MultiSampleQuality      = 0;
#endif
#endif
}
예제 #24
0
static void init_video_filter(enum retro_pixel_format colfmt)
{
   unsigned width, height, pow2_x, pow2_y, maxsize;
   struct retro_game_geometry *geom = NULL;
   settings_t *settings             = config_get_ptr();
   struct retro_system_av_info *av_info = 
      video_viewport_get_system_av_info();

   deinit_video_filter();

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

   /* Deprecated format. Gets pre-converted. */
   if (colfmt == RETRO_PIXEL_FORMAT_0RGB1555)
      colfmt = RETRO_PIXEL_FORMAT_RGB565;

   if (video_state.hw_render_callback.context_type)
   {
      RARCH_WARN("Cannot use CPU filters when hardware rendering is used.\n");
      return;
   }

   geom    = av_info ? (struct retro_game_geometry*)&av_info->geometry : NULL;
   width   = geom->max_width;
   height  = geom->max_height;

   video_state.filter.filter = rarch_softfilter_new(
         settings->video.softfilter_plugin,
         RARCH_SOFTFILTER_THREADS_AUTO, colfmt, width, height);

   if (!video_state.filter.filter)
   {
      RARCH_ERR("Failed to load filter.\n");
      return;
   }

   rarch_softfilter_get_max_output_size(video_state.filter.filter,
         &width, &height);

   pow2_x                    = next_pow2(width);
   pow2_y                    = next_pow2(height);
   maxsize                   = max(pow2_x, pow2_y); 
   video_state.filter.scale  = maxsize / RARCH_SCALE_BASE;
   video_state.filter.out_rgb32 = rarch_softfilter_get_output_format(
         video_state.filter.filter) == RETRO_PIXEL_FORMAT_XRGB8888;

   video_state.filter.out_bpp = video_state.filter.out_rgb32 ?
      sizeof(uint32_t) : sizeof(uint16_t);

   /* TODO: Aligned output. */
   video_state.filter.buffer = malloc(width * height * video_state.filter.out_bpp);
   if (!video_state.filter.buffer)
      goto error;

   return;

error:
   RARCH_ERR("Softfilter initialization failed.\n");
   deinit_video_filter();
}
예제 #25
0
static bool d3d_construct(d3d_video_t *d3d,
      const video_info_t *info, const input_driver_t **input,
      void **input_data)
{
   unsigned full_x, full_y;
   settings_t    *settings     = config_get_ptr();

   d3d->should_resize = false;

#if defined(HAVE_MENU)
   d3d->menu                = new overlay_t();

   if (!d3d->menu)
      return false;

   d3d->menu->tex_coords[0]  = 0;
   d3d->menu->tex_coords[1]  = 0;
   d3d->menu->tex_coords[2]  = 1;
   d3d->menu->tex_coords[3]  = 1;
   d3d->menu->vert_coords[0] = 0;
   d3d->menu->vert_coords[1] = 1;
   d3d->menu->vert_coords[2] = 1;
   d3d->menu->vert_coords[3] = -1;
#endif

   memset(&d3d->windowClass, 0, sizeof(d3d->windowClass));
#ifdef HAVE_WINDOW
   d3d->windowClass.lpfnWndProc = WndProcD3D;
   win32_window_init(&d3d->windowClass, true, NULL);
#endif

#ifdef HAVE_MONITOR
   bool windowed_full;
   RECT mon_rect;
   MONITORINFOEX current_mon;
   HMONITOR hm_to_use;

   win32_monitor_info(&current_mon, &hm_to_use, &d3d->cur_mon_id);
   mon_rect = current_mon.rcMonitor;
   g_resize_width  = info->width;
   g_resize_height = info->height;

   windowed_full = settings->video.windowed_fullscreen;

   full_x = (windowed_full || info->width  == 0) ?
      (mon_rect.right  - mon_rect.left) : info->width;
   full_y = (windowed_full || info->height == 0) ?
      (mon_rect.bottom - mon_rect.top)  : info->height;
   RARCH_LOG("[D3D]: Monitor size: %dx%d.\n",
         (int)(mon_rect.right  - mon_rect.left),
         (int)(mon_rect.bottom - mon_rect.top));
#else
   gfx_ctx_get_video_size(&full_x, &full_y);
#endif
   {
      unsigned new_width  = info->fullscreen ? full_x : info->width;
      unsigned new_height = info->fullscreen ? full_y : info->height;
      video_driver_set_size(&new_width, &new_height);
   }

#ifdef HAVE_WINDOW
   DWORD style;
   unsigned win_width, win_height;
   RECT rect            = {0};

   video_driver_get_size(&win_width, &win_height);

   win32_set_style(&current_mon, &hm_to_use, &win_width, &win_height, info->fullscreen, windowed_full, &rect, &mon_rect, &style);

   win32_window_create(d3d, style, &mon_rect, win_width,
         win_height, info->fullscreen);

   win32_set_window(&win_width, &win_height, info->fullscreen,
	   windowed_full, &rect);
#endif

#ifdef HAVE_SHADERS
   /* This should only be done once here
    * to avoid set_shader() to be overridden
    * later. */
   enum rarch_shader_type type =
      video_shader_parse_type(settings->video.shader_path, RARCH_SHADER_NONE);
   if (settings->video.shader_enable && type == RARCH_SHADER_CG)
      d3d->shader_path = settings->video.shader_path;

   if (!d3d_process_shader(d3d))
      return false;
#endif

   d3d->video_info = *info;
   if (!d3d_initialize(d3d, &d3d->video_info))
      return false;

   gfx_ctx_input_driver(input, input_data);

   RARCH_LOG("[D3D]: Init complete.\n");
   return true;
}
예제 #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
}
예제 #27
0
파일: vg.c 프로젝트: SAKUJ0/RetroArch
static void *vg_init(const video_info_t *video, const input_driver_t **input, void **input_data)
{
   VGfloat clearColor[4] = {0, 0, 0, 1};
   settings_t *settings = config_get_ptr();
   vg_t *vg             = (vg_t*)calloc(1, sizeof(vg_t));

   if (!vg)
      return NULL;

   vg->driver = gfx_ctx_init_first(vg, settings->video.context_driver,
         GFX_CTX_OPENVG_API, 0, 0, false);

   if (!vg->driver)
   {
      free(vg);
      return NULL;
   }

   vg->driver->get_video_size(vg, &vg->mScreenWidth, &vg->mScreenHeight);
   RARCH_LOG("Detecting screen resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight);

   vg->driver->swap_interval(vg, video->vsync ? 1 : 0);
   vg->driver->update_window_title(vg);

   vg->mTexType = video->rgb32 ? VG_sXRGB_8888 : VG_sRGB_565;
   vg->mKeepAspect = video->force_aspect;

   unsigned win_width  = video->width;
   unsigned win_height = video->height;
   if (video->fullscreen && (win_width == 0) && (win_height == 0))
   {
      win_width  = vg->mScreenWidth;
      win_height = vg->mScreenHeight;
   }

   if (!vg->driver->set_video_mode(vg, win_width, win_height, video->fullscreen))
   {
      free(vg);
      return NULL;
   }

   vg->driver->get_video_size(vg, &vg->mScreenWidth, &vg->mScreenHeight);
   RARCH_LOG("Verified window resolution %ux%u.\n", vg->mScreenWidth, vg->mScreenHeight);
   vg->should_resize = true;

   if (vg->driver->translate_aspect)
      vg->mScreenAspect = vg->driver->translate_aspect(vg, vg->mScreenWidth, vg->mScreenHeight);
   else
      vg->mScreenAspect = (float)vg->mScreenWidth / vg->mScreenHeight;

   vgSetfv(VG_CLEAR_COLOR, 4, clearColor);

   vg->mTextureWidth = vg->mTextureHeight = video->input_scale * RARCH_SCALE_BASE;
   vg->mImage = vgCreateImage(vg->mTexType, vg->mTextureWidth, vg->mTextureHeight,
         video->smooth ? VG_IMAGE_QUALITY_BETTER : VG_IMAGE_QUALITY_NONANTIALIASED);
   vg_set_nonblock_state(vg, !video->vsync);

   vg->driver->input_driver(vg, input, input_data);

   if (settings->video.font_enable && font_renderer_create_default(&vg->font_driver, &vg->mFontRenderer,
            *settings->video.font_path ? settings->video.font_path : NULL, settings->video.font_size))
   {
      vg->mFont = vgCreateFont(0);

      if (vg->mFont != VG_INVALID_HANDLE)
      {
         vg->mFontsOn = true;

         vg->mFontHeight = settings->video.font_size;

         vg->mPaintFg = vgCreatePaint();
         vg->mPaintBg = vgCreatePaint();
         VGfloat paintFg[] = { settings->video.msg_color_r, settings->video.msg_color_g, settings->video.msg_color_b, 1.0f };
         VGfloat paintBg[] = { settings->video.msg_color_r / 2.0f, settings->video.msg_color_g / 2.0f, settings->video.msg_color_b / 2.0f, 0.5f };

         vgSetParameteri(vg->mPaintFg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
         vgSetParameterfv(vg->mPaintFg, VG_PAINT_COLOR, 4, paintFg);

         vgSetParameteri(vg->mPaintBg, VG_PAINT_TYPE, VG_PAINT_TYPE_COLOR);
         vgSetParameterfv(vg->mPaintBg, VG_PAINT_COLOR, 4, paintBg);
      }
   }

   if (vg_query_extension("KHR_EGL_image") && vg->driver->init_egl_image_buffer(vg, video))
   {
      pvgCreateEGLImageTargetKHR = (PFNVGCREATEEGLIMAGETARGETKHRPROC)vg->driver->get_proc_address("vgCreateEGLImageTargetKHR");

      if (pvgCreateEGLImageTargetKHR)
      {
         RARCH_LOG("[VG] Using EGLImage buffer\n");
         vg->mEglImageBuf = true;
      }
   }

#if 0
   const char *ext = (const char*)vgGetString(VG_EXTENSIONS);
   if (ext)
      RARCH_LOG("[VG] Supported extensions: %s\n", ext);
#endif

   return vg;
}
예제 #28
0
static int general_push(menu_displaylist_info_t *info,
      unsigned id, enum menu_displaylist_ctl_state state)
{
   struct retro_system_info *system_menu = NULL;
   settings_t        *settings = config_get_ptr();
   rarch_system_info_t *system = NULL;
   core_info_list_t *list      = NULL;
   menu_handle_t        *menu  = NULL;

   if (!menu_driver_ctl(RARCH_MENU_CTL_DRIVER_DATA_GET, &menu))
      return menu_cbs_exit();

   core_info_get_list(&list);

   menu_driver_ctl(RARCH_MENU_CTL_SYSTEM_INFO_GET, &system_menu);
   runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);

   switch (id)
   {
      case PUSH_DEFAULT:
      case PUSH_DETECT_CORE_LIST:
         break;
      default:
         fill_pathname_join(info->path, menu->scratch2_buf,
               menu->scratch_buf, sizeof(info->path));
         fill_pathname_join(info->label, menu->scratch2_buf,
               menu->scratch_buf, sizeof(info->label));
         break;
   }

   info->type_default = FILE_TYPE_PLAIN;

   switch (id)
   {
      case PUSH_ARCHIVE_OPEN_DETECT_CORE:
      case PUSH_ARCHIVE_OPEN:
      case PUSH_DEFAULT:
         info->setting      = menu_setting_find_enum(info->enum_idx);
         break;
      default:
         break;
   }

   switch (id)
   {
      case PUSH_ARCHIVE_OPEN_DETECT_CORE:
  
         if (!string_is_empty(list->all_ext))
            strlcpy(info->exts, list->all_ext, sizeof(info->exts));
         else if (system_menu->valid_extensions)
         {
            if (*system_menu->valid_extensions)
               strlcpy(info->exts, system_menu->valid_extensions,
                     sizeof(info->exts));
         }
         else
            strlcpy(info->exts, system->valid_extensions, sizeof(info->exts));
         break;
      case PUSH_ARCHIVE_OPEN:
         if (system_menu->valid_extensions)
         {
            if (*system_menu->valid_extensions)
               strlcpy(info->exts, system_menu->valid_extensions,
                     sizeof(info->exts));
         }
         else
            strlcpy(info->exts, system->valid_extensions, sizeof(info->exts));
         break;
      case PUSH_DEFAULT:
         if (menu_setting_get_browser_selection_type(info->setting) == ST_DIR)
         {
         }
         else if (system_menu->valid_extensions)
         {
            if (*system_menu->valid_extensions)
               strlcpy(info->exts, system_menu->valid_extensions,
                     sizeof(info->exts));
         }
         else
         {
            if (!string_is_empty(system->valid_extensions))
               strlcpy(info->exts, system->valid_extensions, sizeof(info->exts));
         }
         break;
      case PUSH_DETECT_CORE_LIST:
         if (!string_is_empty(list->all_ext))
            strlcpy(info->exts, list->all_ext, sizeof(info->exts));
         break;
   }

   (void)settings;

   if (settings->multimedia.builtin_mediaplayer_enable ||
         settings->multimedia.builtin_imageviewer_enable)
   {
      struct retro_system_info sysinfo = {0};

      (void)sysinfo;
#ifdef HAVE_FFMPEG
      if (settings->multimedia.builtin_mediaplayer_enable)
      {
         libretro_ffmpeg_retro_get_system_info(&sysinfo);
         strlcat(info->exts, "|", sizeof(info->exts));
         strlcat(info->exts, sysinfo.valid_extensions, sizeof(info->exts));
      }
#endif
#ifdef HAVE_IMAGEVIEWER
      if (settings->multimedia.builtin_imageviewer_enable)
      {
         libretro_imageviewer_retro_get_system_info(&sysinfo);
         strlcat(info->exts, "|", sizeof(info->exts));
         strlcat(info->exts, sysinfo.valid_extensions, sizeof(info->exts));
      }
#endif
   }

   return deferred_push_dlist(info, state);
}
예제 #29
0
파일: runloop.c 프로젝트: Ezio-PS/RetroArch
/**
 * 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;
   retro_time_t current, target, to_sleep_ms;
   static uint64_t last_input                   = 0;
   enum runloop_state runloop_status            = RUNLOOP_STATE_NONE;
   static retro_time_t frame_limit_minimum_time = 0.0;
   static retro_time_t frame_limit_last_time    = 0.0;
   settings_t *settings                         = config_get_ptr();
   uint64_t current_input                       = menu_driver_ctl(RARCH_MENU_CTL_IS_ALIVE, NULL) ? input_menu_keys_pressed() : input_keys_pressed();
   uint64_t old_input                           = last_input;

   last_input                                   = current_input;

   if (runloop_frame_time_last_enable)
   {
      runloop_frame_time_last        = 0;
      runloop_frame_time_last_enable = false;
   }

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

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

      runloop_set_frame_limit = false;
   }

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

      retro_time_t current     = cpu_features_get_time_usec();
      retro_time_t delta       = current - runloop_frame_time_last;
      bool is_locked_fps       = (runloop_paused ||
                                  input_driver_is_nonblock_state()) |
                                  !!recording_driver_get_data_ptr();


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

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

      runloop_frame_time_last = current;

      if (is_locked_fps)
         runloop_frame_time_last = 0;

      runloop_frame_time.callback(delta);
   }

   runloop_status = runloop_check_state(settings, current_input,
         old_input, sleep_ms);

   switch (runloop_status)
   {
      case RUNLOOP_STATE_QUIT:
         frame_limit_last_time = 0.0;
         command_event(CMD_EVENT_QUIT, NULL);
         return -1;
      case RUNLOOP_STATE_SLEEP:
      case RUNLOOP_STATE_END:
      case RUNLOOP_STATE_MENU_ITERATE:
         core_poll();
#ifdef HAVE_NETWORKING
         /* FIXME: This is an ugly way to tell Netplay this... */
         netplay_driver_ctl(RARCH_NETPLAY_CTL_PAUSE, NULL);
#endif
         if (runloop_status == RUNLOOP_STATE_SLEEP)
            *sleep_ms = 10;
         if (runloop_status == RUNLOOP_STATE_END)
            goto end;
         if (runloop_status == RUNLOOP_STATE_MENU_ITERATE)
            return 0;
         return 1;
      case RUNLOOP_STATE_ITERATE:
      case RUNLOOP_STATE_NONE:
      default:
         break;
   }

   autosave_lock();

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

   camera_driver_ctl(RARCH_CAMERA_CTL_POLL, NULL);

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

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

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

   core_run();

#ifdef HAVE_CHEEVOS
   cheevos_test();
#endif

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

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

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

   autosave_unlock();

   if (!settings->fastforward_ratio)
      return 0;

end:

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

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

   frame_limit_last_time  = cpu_features_get_time_usec();

   return 0;
}
예제 #30
0
void set_paths_redirect(const char *path)
{
   global_t                *global   = global_get_ptr();
   settings_t              *settings = config_get_ptr();
   rarch_system_info_t      *info    = rarch_system_info_get_ptr();

   uint32_t global_library_name_hash = ((global && info->info.library_name &&
            (info->info.library_name[0] != '\0'))
         ? msg_hash_calculate(info->info.library_name) : 0);

   if(global_library_name_hash != 0 &&
         (global_library_name_hash != MENU_VALUE_NO_CORE))
   {
      /* per-core saves: append the library_name to the save location */
      if (settings->sort_savefiles_enable && global->dir.savefile[0] != '\0')
      {
         strlcpy(orig_savefile_dir,global->dir.savefile,
               sizeof(orig_savefile_dir));
         fill_pathname_dir(
               global->dir.savefile,
               global->dir.savefile,
               info->info.library_name,
               sizeof(global->dir.savefile));

         /* If path doesn't exist, try to create it,
          * if everything fails revert to the original path. */
         if(!path_is_directory(global->dir.savefile) && global->dir.savefile[0] != '\0')
         {
            path_mkdir(global->dir.savefile);
            if(!path_is_directory(global->dir.savefile))
            {
               RARCH_LOG("Reverting savefile directory to %s\n", orig_savefile_dir);
               strlcpy(global->dir.savefile,
                     orig_savefile_dir,
                     sizeof(global->dir.savefile));
            }
         }
      }

      /* per-core states: append the library_name to the save location */
      if (settings->sort_savestates_enable && global->dir.savestate[0] != '\0')
      {
         strlcpy(orig_savestate_dir,
               global->dir.savestate,
               sizeof(orig_savestate_dir));
         fill_pathname_dir(global->dir.savestate,
               global->dir.savestate,
               info->info.library_name,
               sizeof(global->dir.savestate));

         /* If path doesn't exist, try to create it.
          * If everything fails, revert to the original path. */
         if(!path_is_directory(global->dir.savestate) && global->dir.savestate[0] != '\0')
         {
            path_mkdir(global->dir.savestate);
            if(!path_is_directory(global->dir.savestate))
            {
               RARCH_LOG("Reverting savestate directory to %s\n", orig_savestate_dir);
               strlcpy(global->dir.savestate,
                     orig_savestate_dir,
                     sizeof(global->dir.savestate));
            }
         }
      }
   }

   if(path_is_directory(global->dir.savefile))
      strlcpy(global->name.savefile, global->dir.savefile,
            sizeof(global->name.savefile));

   if(path_is_directory(global->dir.savestate))
      strlcpy(global->name.savestate, global->dir.savestate,
            sizeof(global->name.savestate));

   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);
   }

   if (path_is_directory(global->name.savestate))
   {
      fill_pathname_dir(global->name.savestate, global->name.base,
            ".state", sizeof(global->name.savestate));
      RARCH_LOG("%s \"%s\".\n",
            msg_hash_to_str(MSG_REDIRECTING_SAVESTATE_TO),
            global->name.savestate);
   }

   if (path_is_directory(global->name.cheatfile))
   {
      fill_pathname_dir(global->name.cheatfile, global->name.base,
            ".state", sizeof(global->name.cheatfile));
      RARCH_LOG("%s \"%s\".\n",
            msg_hash_to_str(MSG_REDIRECTING_CHEATFILE_TO),
            global->name.cheatfile);
   }
}