diff --git a/configuration.h b/configuration.h index 829c914d5e6..6f4d8de42bc 100644 --- a/configuration.h +++ b/configuration.h @@ -524,6 +524,7 @@ typedef struct settings char directory_input_remapping[PATH_MAX_LENGTH]; char directory_overlay[PATH_MAX_LENGTH]; char directory_resampler[PATH_MAX_LENGTH]; + char directory_osk_overlay[PATH_MAX_LENGTH]; char directory_screenshot[PATH_MAX_LENGTH]; char directory_system[PATH_MAX_LENGTH]; char directory_cache[PATH_MAX_LENGTH]; diff --git a/core_info.c b/core_info.c index 2cac6cac9c3..6fbe33d9895 100644 --- a/core_info.c +++ b/core_info.c @@ -1552,7 +1552,15 @@ static bool core_info_get_file_id(const char *core_filename, /* > Remove extension */ strlcpy(core_file_id, core_filename, len); path_remove_extension(core_file_id); - +#if defined(IOS) || defined(OSX) + /* iOS framework names, to quote Apple: + * "must contain only alphanumerics, dots, hyphens and must not end with a dot." + * + * Since core names include underscore, which is not allowed, but not dot, + * which is, we change underscore to dot. Here, we need to change it back. + */ + string_replace_all_chars(core_file_id, '.', '_'); +#endif /* > Remove suffix */ last_underscore = (char*)strrchr(core_file_id, '_'); diff --git a/frontend/frontend_driver.c b/frontend/frontend_driver.c index 33cc8c3f674..21c3f8f2071 100644 --- a/frontend/frontend_driver.c +++ b/frontend/frontend_driver.c @@ -185,6 +185,18 @@ bool frontend_driver_get_core_extension(char *s, size_t len) s[2] = 'l'; s[3] = '\0'; return true; +#elif defined(IOS) || defined(OSX) // && defined(HAVE_APPLE_STORE)) + s[0] = 'f'; + s[1] = 'r'; + s[2] = 'a'; + s[3] = 'm'; + s[4] = 'e'; + s[5] = 'w'; + s[6] = 'o'; + s[7] = 'r'; + s[8] = 'k'; + s[9] = '\0'; + return true; #elif defined(__APPLE__) || defined(__MACH__) s[0] = 'd'; s[1] = 'y'; diff --git a/gfx/common/vulkan_common.c b/gfx/common/vulkan_common.c index ede7676d613..69579757a31 100644 --- a/gfx/common/vulkan_common.c +++ b/gfx/common/vulkan_common.c @@ -1,4 +1,4 @@ -/* RetroArch - A frontend for libretro. +vulkan_context_init/* RetroArch - A frontend for libretro. * Copyright (C) 2016-2017 - Hans-Kristian Arntzen * Copyright (C) 2016-2019 - Brad Parker * @@ -2317,7 +2317,13 @@ bool vulkan_context_init(gfx_ctx_vulkan_data_t *vk, #ifdef _WIN32 vulkan_library = dylib_load("vulkan-1.dll"); #elif __APPLE__ - vulkan_library = dylib_load("MoltenVK.framework/MoltenVK"); + vulkan_library = dylib_load("MoltenVK"); + if(!vulkan_library) { + vulkan_library = dylib_load("MoltenVK.framework"); + } + if(!vulkan_library) { + vulkan_library = dylib_load("MoltenVK.framework/MoltenVK"); + } #else vulkan_library = dylib_load("libvulkan.so.1"); if (!vulkan_library) diff --git a/libretro-common/include/retro_miscellaneous.h b/libretro-common/include/retro_miscellaneous.h index 953ab186001..757c40bd116 100644 --- a/libretro-common/include/retro_miscellaneous.h +++ b/libretro-common/include/retro_miscellaneous.h @@ -98,7 +98,7 @@ static INLINE bool bits_any_different(uint32_t *a, uint32_t *b, uint32_t count) #endif #ifndef NAME_MAX_LENGTH -#define NAME_MAX_LENGTH 256 +#define NAME_MAX_LENGTH 512 #endif #ifndef MAX diff --git a/menu/menu_displaylist.c b/menu/menu_displaylist.c index 57143b7377a..1ab7351127e 100644 --- a/menu/menu_displaylist.c +++ b/menu/menu_displaylist.c @@ -4346,6 +4346,8 @@ static unsigned menu_displaylist_parse_cores( #ifdef IOS /* For various reasons on iOS/tvOS, MoltenVK shows up * in the cores directory; exclude it here */ + if (string_is_equal(path, "MoltenVK")) + continue; if (string_is_equal(path, "MoltenVK.framework/MoltenVK")) continue; #endif diff --git a/playlist.c b/playlist.c index f5a048de07b..370303e45b8 100644 --- a/playlist.c +++ b/playlist.c @@ -1074,11 +1074,39 @@ void playlist_resolve_path(enum playlist_file_mode mode, { #ifdef HAVE_COCOATOUCH char tmp[PATH_MAX_LENGTH]; + int _len = 0; if (mode == PLAYLIST_LOAD) { - fill_pathname_expand_special(tmp, path, sizeof(tmp)); - strlcpy(path, tmp, len); + if (is_core && + string_starts_with(path, ":/Frameworks/") && + string_ends_with(path, ".framework")) + { + /* iOS cores used to be packaged as .dylib files in the modules + * directory; App Store rules require turning them into Frameworks and + * putting them in the Frameworks directory. Because some playlists + * include the old core path, we'll translate it here. + */ + path[string_index_last_occurance(path, '.')] = '\0'; + if (string_ends_with(path, "_ios")) + path[string_index_last_occurance(path, '_')] = '\0'; + _len += strlcpy(tmp + _len, ":/Frameworks/", STRLEN_CONST(":/Frameworks/") + 1); + _len += strlcpy(tmp + _len, path + STRLEN_CONST(":/modules/"), sizeof(tmp) - _len); + /* iOS framework names, to quote Apple: + * "must contain only alphanumerics, dots, hyphens and must not end with a dot." + * + * Since core names include underscore, which is not allowed, but not dot, + * which is, we change underscore to dot. + */ + string_replace_all_chars(tmp, '_', '.'); + strlcpy(tmp + _len, ".framework", sizeof(tmp)); + fill_pathname_expand_special(path, tmp, len); + } + else + { + fill_pathname_expand_special(tmp, path, sizeof(tmp)); + strlcpy(path, tmp, len); + } } else { diff --git a/retroarch.c b/retroarch.c index 9e9de2bad97..5f8ba152e4c 100644 --- a/retroarch.c +++ b/retroarch.c @@ -2179,6 +2179,58 @@ void dir_check_defaults(const char *custom_ini_path) } } +#ifdef __APPLE__ +static void dir_check_config(void) +{ + settings_t *settings = config_get_ptr(); + +#define ENSURE_DIRECTORY(DIRPATH) \ + if (!string_is_empty(DIRPATH)) \ + if (!path_is_directory(DIRPATH)) \ + path_mkdir(DIRPATH) + + /* the order here mimics the order of enum default_dirs */ + /* TODO: not all of these are necessary/used and many are created on demand, make fewer */ + ENSURE_DIRECTORY(settings->paths.directory_menu_content); + ENSURE_DIRECTORY(settings->paths.directory_core_assets); + ENSURE_DIRECTORY(settings->paths.directory_menu_config); + ENSURE_DIRECTORY(settings->paths.directory_autoconfig); + ENSURE_DIRECTORY(settings->paths.directory_audio_filter); + ENSURE_DIRECTORY(settings->paths.directory_video_filter); + ENSURE_DIRECTORY(settings->paths.directory_assets); +#ifdef _3DS + ENSURE_DIRECTORY(settings->paths.directory_bottom_assets); +#endif + ENSURE_DIRECTORY(settings->paths.directory_libretro); + ENSURE_DIRECTORY(settings->paths.path_libretro_info); + ENSURE_DIRECTORY(settings->paths.directory_overlay); + ENSURE_DIRECTORY(settings->paths.directory_osk_overlay); + /* PORT */ + ENSURE_DIRECTORY(settings->paths.directory_video_shader); + ENSURE_DIRECTORY(dir_get_ptr(RARCH_DIR_SAVESTATE)); + ENSURE_DIRECTORY(dir_get_ptr(RARCH_DIR_SAVEFILE)); + ENSURE_DIRECTORY(settings->paths.directory_screenshot); + ENSURE_DIRECTORY(settings->paths.directory_system); + ENSURE_DIRECTORY(settings->paths.directory_playlist); + ENSURE_DIRECTORY(settings->paths.directory_content_favorites); + ENSURE_DIRECTORY(settings->paths.directory_content_history); + ENSURE_DIRECTORY(settings->paths.directory_content_image_history); + ENSURE_DIRECTORY(settings->paths.directory_content_music_history); + ENSURE_DIRECTORY(settings->paths.directory_content_video_history); + ENSURE_DIRECTORY(settings->paths.directory_input_remapping); + ENSURE_DIRECTORY(settings->paths.directory_cache); + ENSURE_DIRECTORY(settings->paths.directory_dynamic_wallpapers); + ENSURE_DIRECTORY(settings->paths.directory_thumbnails); + ENSURE_DIRECTORY(settings->paths.path_content_database); + ENSURE_DIRECTORY(settings->paths.path_cheat_database); + /* RECORD_CONFIG */ + /* RECORD_OUTPUT */ + ENSURE_DIRECTORY(settings->paths.log_dir); + +#undef ENSURE_DIRECTORY +} +#endif + #ifdef HAVE_ACCESSIBILITY bool is_accessibility_enabled(bool accessibility_enable, bool accessibility_enabled) { @@ -5360,7 +5412,12 @@ static void retroarch_parse_input_libretro_path(const char *path) path_stats = path_stat(path); /* Check if path is a directory */ - if ((path_stats & RETRO_VFS_STAT_IS_DIRECTORY) != 0) + if ( + ((path_stats & RETRO_VFS_STAT_IS_DIRECTORY) != 0) +#if defined(IOS) || defined(OSX) + && !string_ends_with(path, ".framework") +#endif + ) { path_clear(RARCH_PATH_CORE); @@ -6323,6 +6380,17 @@ bool retroarch_main_init(int argc, char *argv[]) verbosity_enabled = retroarch_parse_input_and_config(p_rarch, global_get_ptr(), argc, argv); + +#ifdef __APPLE__ + /* This doesn't have to be apple specific but it's currently the only + * platform that doesn't call dir_check_defaults(). This does exactly the + * same thing as dir_check_defaults() except that it makes the directories + * pointed at by the config file rather than the defaults, which is why it + * comes right after parsing the config. osx users seem to be more likely to + * want to do change the default directories. + */ + dir_check_config(); +#endif #ifdef HAVE_ACCESSIBILITY accessibility_enable = settings->bools.accessibility_enable; diff --git a/samples/tasks/database/main.c b/samples/tasks/database/main.c index 3756a5db6ff..98c3f983ffe 100644 --- a/samples/tasks/database/main.c +++ b/samples/tasks/database/main.c @@ -39,7 +39,7 @@ int main(int argc, char *argv[]) #if defined(_WIN32) const char *exts = "dll"; #elif defined(__MACH__) - const char *exts = "dylib"; + const char *exts = "framework"; #else const char *exts = "so"; #endif diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index 19a67a2e1d2..fe1d3c2f5e6 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -940,7 +940,7 @@ - (IBAction)openCore:(id)sender settings_t *settings = config_get_ptr(); const char *path_dir_libretro = settings->paths.directory_libretro; - browser_state.filters = strdup("dylib"); + browser_state.filters = strdup("framework"); browser_state.filters_title = strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_SETTINGS)); browser_state.title = strdup(msg_hash_to_str(MENU_ENUM_LABEL_VALUE_CORE_LIST)); browser_state.startdir = strdup(path_dir_libretro);