Пример #1
0
struct string_list *string_list_new_special(enum string_list_type type,
      void *data, unsigned *len, size_t *list_size)
{
   union string_list_elem_attr attr;
   unsigned i;
   core_info_list_t *core_info_list = NULL;
   const core_info_t *core_info     = NULL;
   struct string_list *s            = string_list_new();

   if (!s || !len)
      goto error;

   attr.i = 0;
   *len   = 0;

   switch (type)
   {
      case STRING_LIST_MENU_DRIVERS:
#ifdef HAVE_MENU
         for (i = 0; menu_driver_find_handle(i); i++)
         {
            const char *opt  = menu_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
#endif
      case STRING_LIST_CAMERA_DRIVERS:
#ifdef HAVE_CAMERA
         for (i = 0; camera_driver_find_handle(i); i++)
         {
            const char *opt  = camera_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
#endif
      case STRING_LIST_LOCATION_DRIVERS:
#ifdef HAVE_LOCATION
         for (i = 0; location_driver_find_handle(i); i++)
         {
            const char *opt  = location_driver_find_ident(i);
            *len            += strlen(opt) + 1;
            string_list_append(options_l, opt, attr);
         }
         break;
#endif
      case STRING_LIST_AUDIO_DRIVERS:
         for (i = 0; audio_driver_find_handle(i); i++)
         {
            const char *opt  = audio_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_AUDIO_RESAMPLER_DRIVERS:
         for (i = 0; audio_resampler_driver_find_handle(i); i++)
         {
            const char *opt  = audio_resampler_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_VIDEO_DRIVERS:
         for (i = 0; video_driver_find_handle(i); i++)
         {
            const char *opt  = video_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_INPUT_DRIVERS:
         for (i = 0; input_driver_find_handle(i); i++)
         {
            const char *opt  = input_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_INPUT_HID_DRIVERS:
         for (i = 0; hid_driver_find_handle(i); i++)
         {
            const char *opt  = hid_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_INPUT_JOYPAD_DRIVERS:
         for (i = 0; joypad_driver_find_handle(i); i++)
         {
            const char *opt  = joypad_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_RECORD_DRIVERS:
         for (i = 0; record_driver_find_handle(i); i++)
         {
            const char *opt  = record_driver_find_ident(i);
            *len            += strlen(opt) + 1;

            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_SUPPORTED_CORES_PATHS:
         core_info_get_list(&core_info_list);

         core_info_list_get_supported_cores(core_info_list,
               (const char*)data, &core_info, list_size);

         if (*list_size == 0)
            goto error;

         for (i = 0; i < *list_size; i++)
         {
            const char *opt  = NULL;
            const core_info_t *info = (const core_info_t*)&core_info[i];
            opt              = info ? info->path : NULL;

            if (!opt)
               goto error;

            *len           += strlen(opt) + 1;
            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_SUPPORTED_CORES_NAMES:
         core_info_get_list(&core_info_list);
         core_info_list_get_supported_cores(core_info_list,
               (const char*)data, &core_info, list_size);

         if (*list_size == 0)
            goto error;

         for (i = 0; i < *list_size; i++)
         {
            const core_info_t *info  = (const core_info_t*)&core_info[i];
            const char          *opt = info->display_name;

            if (!opt)
               goto error;

            *len            += strlen(opt) + 1;
            string_list_append(s, opt, attr);
         }
         break;
      case STRING_LIST_NONE:
      default:
         goto error;
   }

   return s;

error:
   string_list_free(s);
   s    = NULL;
   return NULL;
}
Пример #2
0
struct string_list *dir_list_new_special(const char *input_dir,
      enum dir_list_type type, const char *filter)
{
   char ext_shaders[PATH_MAX_LENGTH] = {0};
   char ext_name[PATH_MAX_LENGTH]    = {0};
   const char *dir                   = NULL;
   const char *exts                  = NULL;
   bool include_dirs                 = false;

   (void)input_dir;

   switch (type)
   {
      case DIR_LIST_AUTOCONFIG:
         dir  = input_dir;
         exts = filter;
         break;
      case DIR_LIST_CORES:
         dir  = input_dir;

         if (!frontend_driver_get_core_extension(ext_name, sizeof(ext_name)))
            return NULL;

         exts = ext_name;
         break;
      case DIR_LIST_CORE_INFO:
         {
            core_info_list_t *list = NULL;
            core_info_get_list(&list);

            dir  = input_dir;
            exts = list->all_ext;
         }
         break;
      case DIR_LIST_SHADERS:
         {
            union string_list_elem_attr attr = {0};
            struct string_list *str_list     = string_list_new();

            if (!str_list)
               return NULL;

            dir  = input_dir;
#ifdef HAVE_CG
            string_list_append(str_list, "cg", attr);
            string_list_append(str_list, "cgp", attr);
#endif
#ifdef HAVE_GLSL
            string_list_append(str_list, "glsl", attr);
            string_list_append(str_list, "glslp", attr);
#endif
#ifdef HAVE_VULKAN
            string_list_append(str_list, "slang", attr);
            string_list_append(str_list, "slangp", attr);
#endif
            string_list_join_concat(ext_shaders, sizeof(ext_shaders), str_list, "|");
            string_list_free(str_list);
            exts = ext_shaders;
         }
         break;
      case DIR_LIST_COLLECTIONS:
         dir  = input_dir;
         exts = "lpl";
         break;
      case DIR_LIST_DATABASES:
         dir  = input_dir;
         exts = "rdb";
         break;
      case DIR_LIST_PLAIN:
         dir  = input_dir;
         exts = filter;
         break;
      case DIR_LIST_NONE:
      default:
         return NULL;
   }

   return dir_list_new(dir, exts, include_dirs, type == DIR_LIST_CORE_INFO);
}
Пример #3
0
bool init_content_file(void)
{
   unsigned i;

   g_extern.temporary_content = string_list_new();
   if (!g_extern.temporary_content)
      return false;

   const struct retro_subsystem_info *special = NULL;

   if (*g_extern.subsystem)
   {
      special = libretro_find_subsystem_info(g_extern.system.special, g_extern.system.num_special,
            g_extern.subsystem);

      if (!special)
      {
         RARCH_ERR("Failed to find subsystem \"%s\" in libretro implementation.\n",
               g_extern.subsystem);
         return false;
      }

      if (special->num_roms && !g_extern.subsystem_fullpaths)
      {
         RARCH_ERR("libretro core requires special content, but none were provided.\n");
         return false;
      }
      else if (special->num_roms && special->num_roms != g_extern.subsystem_fullpaths->size)
      {
         RARCH_ERR("libretro core requires %u content files for subsystem \"%s\", but %u content files were provided.\n", special->num_roms, special->desc,
               (unsigned)g_extern.subsystem_fullpaths->size);
         return false;
      }
      else if (!special->num_roms && g_extern.subsystem_fullpaths && g_extern.subsystem_fullpaths->size)
      {
         RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n", special->desc,
               (unsigned)g_extern.subsystem_fullpaths->size);
         return false;
      }
   }

   union string_list_elem_attr attr;
   attr.i = 0;

   struct string_list *content = (struct string_list*)string_list_new();
   if (!content)
      return false;

   if (*g_extern.subsystem)
   {
      for (i = 0; i < g_extern.subsystem_fullpaths->size; i++)
      {
         attr.i  = special->roms[i].block_extract;
         attr.i |= special->roms[i].need_fullpath << 1;
         attr.i |= special->roms[i].required << 2;
         string_list_append(content, g_extern.subsystem_fullpaths->elems[i].data, attr);
      }
   }
   else
   {
      attr.i  = g_extern.system.info.block_extract;
      attr.i |= g_extern.system.info.need_fullpath << 1;
      attr.i |= (!g_extern.system.no_content) << 2;
      string_list_append(content, g_extern.libretro_no_content ? "" : g_extern.fullpath, attr);
   }

#ifdef HAVE_ZLIB
   // Try to extract all content we're going to load if appropriate.
   for (i = 0; i < content->size; i++)
   {
      // block extract check
      if (content->elems[i].attr.i & 1)
         continue;

      const char *ext = path_get_extension(content->elems[i].data);

      const char *valid_ext = special ?
         special->roms[i].valid_extensions :
         g_extern.system.info.valid_extensions;

      if (ext && !strcasecmp(ext, "zip"))
      {
         char temporary_content[PATH_MAX];
         strlcpy(temporary_content, content->elems[i].data, sizeof(temporary_content));
         if (!zlib_extract_first_content_file(temporary_content, sizeof(temporary_content), valid_ext,
                  *g_settings.extraction_directory ? g_settings.extraction_directory : NULL))
         {
            RARCH_ERR("Failed to extract content from zipped file: %s.\n", temporary_content);
            string_list_free(content);
            return false;
         }
         string_list_set(content, i, temporary_content);
         string_list_append(g_extern.temporary_content, temporary_content, attr);
      }
   }
#endif

   // Set attr to need_fullpath as appropriate.
   
   bool ret = load_content(special, content);
   string_list_free(content);
   return ret;
}
Пример #4
0
static struct string_list *compressed_7zip_file_list_new(
      const char *path, const char* ext)
{
   CFileInStream archiveStream;
   CLookToRead lookStream;
   CSzArEx db;
   ISzAlloc allocImp;
   ISzAlloc allocTempImp;
   size_t temp_size             = 0;
   struct string_list     *list = NULL;
   
   /* These are the allocation routines - currently using 
    * the non-standard 7zip choices. */
   allocImp.Alloc     = SzAlloc;
   allocImp.Free      = SzFree;
   allocTempImp.Alloc = SzAllocTemp;
   allocTempImp.Free  = SzFreeTemp;

   if (InFile_Open(&archiveStream.file, path))
   {
      RARCH_ERR("Could not open %s as 7z archive.\n",path);
      return NULL;
   }

   list = string_list_new();

   if (!list)
   {
      File_Close(&archiveStream.file);
      return NULL;
   }

   FileInStream_CreateVTable(&archiveStream);
   LookToRead_CreateVTable(&lookStream, False);
   lookStream.realStream = &archiveStream.s;
   LookToRead_Init(&lookStream);
   CrcGenerateTable();
   SzArEx_Init(&db);

   if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK)
   {
      uint32_t i;
      struct string_list *ext_list = ext ? string_split(ext, "|"): NULL;
      SRes res                     = SZ_OK;
      uint16_t *temp               = NULL;

      for (i = 0; i < db.db.NumFiles; i++)
      {
         union string_list_elem_attr attr;
         char infile[PATH_MAX_LENGTH];
         const char *file_ext         = NULL;
         size_t                   len = 0;
         bool supported_by_core       = false;
         const CSzFileItem         *f = db.db.Files + i;

         /* we skip over everything, which is a directory. */
         if (f->IsDir)
            continue;

         len = SzArEx_GetFileNameUtf16(&db, i, NULL);

         if (len > temp_size)
         {
            free(temp);
            temp_size = len;
            temp      = (uint16_t *)malloc(temp_size * sizeof(temp[0]));

            if (temp == 0)
            {
               res = SZ_ERROR_MEM;
               break;
            }
         }

         SzArEx_GetFileNameUtf16(&db, i, temp);
         res      = utf16_to_char_string(temp, infile, sizeof(infile)) 
            ? SZ_OK : SZ_ERROR_FAIL;
         file_ext = path_get_extension(infile);

         if (string_list_find_elem_prefix(ext_list, ".", file_ext))
            supported_by_core = true;

         /*
          * Currently we only support files without subdirs in the archives.
          * Folders are not supported (differences between win and lin.
          * Archives within archives should imho never be supported.
          */

         if (!supported_by_core)
            continue;

         attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE;

         if (!string_list_append(list, infile, attr))
         {
            res = SZ_ERROR_MEM;
            break;
         }
      }

      string_list_free(ext_list);
      free(temp);

      if (res != SZ_OK)
      {
         /* Error handling */
         RARCH_ERR("Failed to open compressed_file: \"%s\"\n", path);

         string_list_free(list);
         list = NULL;
      }
   }

   SzArEx_Free(&db, &allocImp);
   File_Close(&archiveStream.file);

   return list;
}
Пример #5
0
/**
 * dir_list_new:
 * @dir          : directory path.
 * @ext          : allowed extensions of file directory entries to include.
 * @include_dirs : include directories as part of the finished directory listing?
 *
 * Create a directory listing.
 *
 * Returns: pointer to a directory listing of type 'struct string_list *' on success,
 * NULL in case of error. Has to be freed manually.
 **/
struct string_list *dir_list_new(const char *dir,
      const char *ext, bool include_dirs)
{
#ifdef _WIN32
   WIN32_FIND_DATA ffd;
   HANDLE hFind = INVALID_HANDLE_VALUE;
#else
   DIR *directory = NULL;
   const struct dirent *entry = NULL;
#endif
   char path_buf[PATH_MAX_LENGTH] = {0};
   struct string_list *ext_list   = NULL;
   struct string_list *list       = NULL;

   (void)path_buf;

   if (!(list = string_list_new()))
      return NULL;

   if (ext)
      ext_list = string_split(ext, "|");

#ifdef _WIN32
   snprintf(path_buf, sizeof(path_buf), "%s\\*", dir);

   hFind = FindFirstFile(path_buf, &ffd);
   if (hFind == INVALID_HANDLE_VALUE)
      goto error;

   do
   {
      int ret                         = 0;
      char file_path[PATH_MAX_LENGTH] = {0};
      const char *name                = ffd.cFileName;
      const char *file_ext            = path_get_extension(name);
      bool is_dir                     = ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY;

      fill_pathname_join(file_path, dir, name, sizeof(file_path));

      ret = parse_dir_entry(name, file_path, is_dir,
            include_dirs, list, ext_list, file_ext);

      if (ret == -1)
         goto error;

      if (ret == 1)
         continue;
   }while (FindNextFile(hFind, &ffd) != 0);

   FindClose(hFind);
   string_list_free(ext_list);
   return list;

error:
   if (hFind != INVALID_HANDLE_VALUE)
      FindClose(hFind);
#else
   directory = opendir(dir);
   if (!directory)
      goto error;

   while ((entry = readdir(directory)))
   {
      int ret                         = 0;
      char file_path[PATH_MAX_LENGTH] = {0};
      const char *name                = entry->d_name;
      const char *file_ext            = path_get_extension(name);
      bool is_dir                     = false;

      fill_pathname_join(file_path, dir, name, sizeof(file_path));

      is_dir = dirent_is_directory(file_path, entry);

      ret = parse_dir_entry(name, file_path, is_dir,
            include_dirs, list, ext_list, file_ext);

      if (ret == -1)
         goto error;

      if (ret == 1)
         continue;
   }

   closedir(directory);

   string_list_free(ext_list);
   return list;

error:

   if (directory)
      closedir(directory);

#endif
   string_list_free(list);
   string_list_free(ext_list);
   return NULL;
}
Пример #6
0
/**
 * video_shader_read_conf_cgp:
 * @conf              : Preset file to read from.
 * @shader            : Shader passes handle.
 *
 * Loads preset file and all associated state (passes,
 * textures, imports, etc).
 *
 * Returns: true (1) if successful, otherwise false (0).
 **/
bool video_shader_read_conf_cgp(config_file_t *conf,
      struct video_shader *shader)
{
   unsigned i;
   union string_list_elem_attr attr;
   unsigned shaders                 = 0;
   settings_t *settings             = config_get_ptr();
   struct string_list *file_list    = NULL;

   (void)file_list;

   memset(shader, 0, sizeof(*shader));
   shader->type = RARCH_SHADER_CG;

   if (!config_get_uint(conf, "shaders", &shaders))
   {
      RARCH_ERR("Cannot find \"shaders\" param.\n");
      return false;
   }

   if (!shaders)
   {
      RARCH_ERR("Need to define at least 1 shader.\n");
      return false;
   }

   if (!config_get_int(conf, "feedback_pass",
            &shader->feedback_pass))
      shader->feedback_pass = -1;

   shader->passes = MIN(shaders, GFX_MAX_SHADERS);
   attr.i         = 0;

   strlcpy(shader->path, conf->path, sizeof(shader->path));

   if (settings->bools.video_shader_watch_files)
   {
      if (file_change_data)
         frontend_driver_watch_path_for_changes(NULL,
               0, &file_change_data);

      file_change_data = NULL;
      file_list        = string_list_new();
      string_list_append(file_list, conf->path, attr);
   }

   for (i = 0; i < shader->passes; i++)
   {
      if (!video_shader_parse_pass(conf, &shader->pass[i], i))
      {
         if (file_list)
         {
            string_list_free(file_list);
            file_list = NULL;
         }
         return false;
      }

      if (settings->bools.video_shader_watch_files && file_list)
         string_list_append(file_list,
               shader->pass[i].source.path, attr);
   }

   if (settings->bools.video_shader_watch_files)
   {
      int flags = PATH_CHANGE_TYPE_MODIFIED          |
                  PATH_CHANGE_TYPE_WRITE_FILE_CLOSED |
                  PATH_CHANGE_TYPE_FILE_MOVED        |
                  PATH_CHANGE_TYPE_FILE_DELETED;

      frontend_driver_watch_path_for_changes(file_list,
            flags, &file_change_data);
      if (file_list)
         string_list_free(file_list);
   }

   command_event(CMD_EVENT_SHADER_PRESET_LOADED, NULL);

   if (!video_shader_parse_textures(conf, shader))
      return false;

   if (!video_shader_parse_imports(conf, shader))
      return false;

   return true;
}
Пример #7
0
/**
 * load_content:
 * @special          : subsystem of content to be loaded. Can be NULL.
 * content           :
 *
 * Load content file (for libretro core).
 *
 * Returns : true if successful, otherwise false.
 **/
static bool load_content(
      struct string_list *temporary_content,
      struct retro_game_info *info,
      const struct string_list *content,
      const struct retro_subsystem_info *special
      )
{
   unsigned i;
   retro_ctx_load_content_info_t load_info;
   struct string_list *additional_path_allocs = string_list_new();

   if (!additional_path_allocs)
      return false;

   for (i = 0; i < content->size; i++)
   {
      int         attr     = content->elems[i].attr.i;
      bool need_fullpath   = attr & 2;
      bool require_content = attr & 4;
      const char *path     = content->elems[i].data;

      if (require_content && string_is_empty(path))
      {
         RARCH_LOG("%s\n",
               msg_hash_to_str(MSG_ERROR_LIBRETRO_CORE_REQUIRES_CONTENT));
         goto error;
      }

      info[i].path = NULL;

      if (!string_is_empty(path))
         info[i].path = path;

      if (!need_fullpath && !string_is_empty(path))
      {
         /* Load the content into memory. */

         ssize_t len = 0;

         if (!load_content_into_memory(i, path, (void**)&info[i].data, &len))
         {
            RARCH_ERR("%s \"%s\".\n",
                  msg_hash_to_str(MSG_COULD_NOT_READ_CONTENT_FILE),
                  path);
            goto error;
         }

         info[i].size = len;
      }
      else
      {
         RARCH_LOG("%s\n",
               msg_hash_to_str(
                  MSG_CONTENT_LOADING_SKIPPED_IMPLEMENTATION_WILL_DO_IT));

#ifdef HAVE_COMPRESSION
         if (!load_content_from_compressed_archive(
                  temporary_content,
                  &info[i], i,
                  additional_path_allocs, need_fullpath, path))
            goto error;
#endif
      }
   }

   load_info.content = content;
   load_info.special = special;
   load_info.info    = info;

   if (!core_load_game(&load_info))
   {
      RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_CONTENT));
      goto error;
   }

#ifdef HAVE_CHEEVOS
   if (!special)
   {
      const void *load_data = NULL;

      cheevos_set_cheats();

      if (!string_is_empty(content->elems[0].data))
         load_data = info;
      cheevos_load(load_data);
   }
#endif

   string_list_free(additional_path_allocs);

   return true;

error:
   if (additional_path_allocs)
      string_list_free(additional_path_allocs);
   
   return false;
}
Пример #8
0
static int action_ok_rdb_entry_submenu(const char *path,
      const char *label, unsigned type, size_t idx)
{
   int ret;
   union string_list_elem_attr attr;
   char new_label[PATH_MAX_LENGTH];
   menu_displaylist_info_t info = {0};
   char *rdb = NULL;
   int len = 0;
   struct string_list *str_list  = NULL;
   struct string_list *str_list2 = NULL;
   menu_handle_t *menu = menu_driver_get_ptr();

   if (!menu)
      return -1;

   if (!label)
      return -1;

   str_list = string_split(label, "|");

   if (!str_list)
      return -1;

   str_list2 = string_list_new();
   if (!str_list2)
   {
      string_list_free(str_list);
      return -1;
   }

   /* element 0 : label
    * element 1 : value
    * element 2 : database path
    */

   attr.i = 0;

   len += strlen(str_list->elems[1].data) + 1;
   string_list_append(str_list2, str_list->elems[1].data, attr);

   len += strlen(str_list->elems[2].data) + 1;
   string_list_append(str_list2, str_list->elems[2].data, attr);

   rdb = (char*)calloc(len, sizeof(char));

   if (!rdb)
   {
      string_list_free(str_list);
      string_list_free(str_list2);
      return -1;
   }

   string_list_join_concat(rdb, len, str_list2, "|");

   strlcpy(new_label, "deferred_cursor_manager_list_", sizeof(new_label));
   strlcat(new_label, str_list->elems[0].data, sizeof(new_label));

   info.list          = menu->menu_list->menu_stack;
   info.type          = 0;
   info.directory_ptr = idx;
   strlcpy(info.path, rdb, sizeof(info.path));
   strlcpy(info.label, new_label, sizeof(info.label));

   ret = menu_displaylist_push_list(&info, DISPLAYLIST_GENERIC);

   string_list_free(str_list);
   string_list_free(str_list2);

   return ret;
}
Пример #9
0
/**
 * init_content_file:
 *
 * Initializes and loads a content file for the currently
 * selected libretro core.
 *
 * global->content_is_init will be set to the return value
 * on exit.
 *
 * Returns : true if successful, otherwise false.
 **/
bool init_content_file(void)
{
   unsigned i;
   union string_list_elem_attr attr;
   bool ret                                   = false;
   struct string_list *content                = NULL;
   const struct retro_subsystem_info *special = NULL;
   settings_t *settings                       = config_get_ptr();
   rarch_system_info_t *system                = rarch_system_info_get_ptr();
   global_t   *global                         = global_get_ptr();

   global->temporary_content                  = string_list_new();

   if (!global->temporary_content)
      goto error;

   if (*global->subsystem)
   {
      special = libretro_find_subsystem_info(system->special,
            system->num_special, global->subsystem);

      if (!special)
      {
         RARCH_ERR(
               "Failed to find subsystem \"%s\" in libretro implementation.\n",
               global->subsystem);
         goto error;
      }

      if (special->num_roms && !global->subsystem_fullpaths)
      {
         RARCH_ERR("libretro core requires special content, but none were provided.\n");
         goto error;
      }
      else if (special->num_roms && special->num_roms
            != global->subsystem_fullpaths->size)
      {
         RARCH_ERR("libretro core requires %u content files for subsystem \"%s\", but %u content files were provided.\n",
               special->num_roms, special->desc,
               (unsigned)global->subsystem_fullpaths->size);
         goto error;
      }
      else if (!special->num_roms && global->subsystem_fullpaths
            && global->subsystem_fullpaths->size)
      {
         RARCH_ERR("libretro core takes no content for subsystem \"%s\", but %u content files were provided.\n",
               special->desc,
               (unsigned)global->subsystem_fullpaths->size);
         goto error;
      }
   }

   content = string_list_new();

   attr.i = 0;

   if (!content)
      goto error;

   if (*global->subsystem)
   {
      for (i = 0; i < global->subsystem_fullpaths->size; i++)
      {
         attr.i  = special->roms[i].block_extract;
         attr.i |= special->roms[i].need_fullpath << 1;
         attr.i |= special->roms[i].required << 2;
         string_list_append(content,
               global->subsystem_fullpaths->elems[i].data, attr);
      }
   }
   else
   {
      char *fullpath = NULL;
      rarch_main_ctl(RARCH_MAIN_CTL_GET_CONTENT_PATH, &fullpath);

      attr.i  = system->info.block_extract;
      attr.i |= system->info.need_fullpath << 1;
      attr.i |= (!system->no_content) << 2;
      string_list_append(content,
            (global->inited.core.no_content && settings->core.set_supports_no_game_enable) ? "" : fullpath, attr);
   }

#ifdef HAVE_ZLIB
   /* Try to extract all content we're going to load if appropriate. */
   for (i = 0; i < content->size; i++)
   {
      const char *ext       = NULL;
      const char *valid_ext = NULL;

      /* Block extract check. */
      if (content->elems[i].attr.i & 1)
         continue;

      ext       = path_get_extension(content->elems[i].data);
      valid_ext = special ? special->roms[i].valid_extensions :
         system->info.valid_extensions;

      if (ext && !strcasecmp(ext, "zip"))
      {
         char temporary_content[PATH_MAX_LENGTH] = {0};

         strlcpy(temporary_content, content->elems[i].data,
               sizeof(temporary_content));

         if (!zlib_extract_first_content_file(temporary_content,
                  sizeof(temporary_content), valid_ext,
                  *settings->cache_directory ?
                  settings->cache_directory : NULL))
         {
            RARCH_ERR("Failed to extract content from zipped file: %s.\n",
                  temporary_content);
            goto error;
         }
         string_list_set(content, i, temporary_content);
         string_list_append(global->temporary_content,
               temporary_content, attr);
      }
   }
#endif

   /* Set attr to need_fullpath as appropriate. */
   ret = load_content(special, content);

error:
   global->inited.content = (ret) ? true : false;

   if (content)
      string_list_free(content);
   return ret;
}
Пример #10
0
/**
 * load_content:
 * @special          : subsystem of content to be loaded. Can be NULL.
 * content           :
 *
 * Load content file (for libretro core).
 *
 * Returns : true if successful, otherwise false.
 **/
static bool load_content(const struct retro_subsystem_info *special,
      const struct string_list *content)
{
   unsigned i;
   bool ret = true;
   struct string_list* additional_path_allocs = string_list_new();
   struct retro_game_info *info = (struct retro_game_info*)
      calloc(content->size, sizeof(*info));

   if (!info)
   {
      string_list_free(additional_path_allocs);
      return false;
   }

   for (i = 0; i < content->size; i++)
   {
      const char *path     = content->elems[i].data;
      int         attr     = content->elems[i].attr.i;
      bool need_fullpath   = attr & 2;
      bool require_content = attr & 4;

      if (require_content && !*path)
      {
         RARCH_LOG("libretro core requires content, but nothing was provided.\n");
         ret = false;
         goto end;
      }

      info[i].path = NULL;

      if (*path)
         info[i].path = path;

      if (!need_fullpath && *path)
      {
         if (!load_content_dont_need_fullpath(&info[i], i, path))
            goto end;
      }
      else
      {
         RARCH_LOG("Content loading skipped. Implementation will"
               " load it on its own.\n");

         if (!load_content_need_fullpath(&info[i], i,
                  additional_path_allocs, need_fullpath, path))
            goto end;
      }
   }

   if (special)
      ret = core.retro_load_game_special(special->id, info, content->size);
   else
   {
      ret = core.retro_load_game(*content->elems[0].data ? info : NULL);
      
#ifdef HAVE_CHEEVOS
      /* Load the achievements into memory if the game has content. */

      cheevos_globals.cheats_were_enabled = cheevos_globals.cheats_are_enabled;
      cheevos_load(*content->elems[0].data ? info : NULL);
#endif
   }

   if (!ret)
      RARCH_ERR("%s.\n", msg_hash_to_str(MSG_FAILED_TO_LOAD_CONTENT));

end:
   for (i = 0; i < content->size; i++)
      free((void*)info[i].data);

   string_list_free(additional_path_allocs);
   if (info)
      free(info);
   return ret;
}