diff --git a/apple_runtime.h b/apple_runtime.h index 4ed2ab9a05..1eb25926ed 100644 --- a/apple_runtime.h +++ b/apple_runtime.h @@ -242,6 +242,23 @@ typedef id (*apple_rt_init_id_long_fn)(APPLE_RT_CONSUMED id, SEL, id, long) /* A class by name, nil when this OS (or this binary) does not have it. */ #define apple_rt_class(name) ((id)objc_getClass(name)) +/* Gives a class a method at run time. For a delegate method the SDK + * marks deprecated or unavailable that an older OS still calls: the + * class answers it only on the releases that need it, done once from + * +initialize, and implementing it does not warn. @fn is a C function + * taking (id self, SEL _cmd, ...) and @types its Objective-C type + * encoding, which must outlive the call. class_addMethod is 10.5 and + * the 10.4 binary may not import it at all, so it is found by name; on + * 10.4 nothing is added. */ +#define apple_rt_add_method(cls, name, fn, types) \ + do { \ + BOOL (*add_)(Class, SEL, IMP, const char *) = \ + (BOOL (*)(Class, SEL, IMP, const char *)) \ + dlsym(RTLD_DEFAULT, "class_addMethod"); \ + if (add_) \ + add_((Class)(cls), sel_registerName(name), (IMP)(fn), (types)); \ + } while (0) + /* The address of an exported object constant (an NSString * such as * AVCaptureDeviceTypeExternal) by name, NULL when this OS does not * export it; apple_rt_obj_at reads the object, which stays the diff --git a/configuration.c b/configuration.c index 9701062017..95e0d98c6c 100644 --- a/configuration.c +++ b/configuration.c @@ -10863,7 +10863,7 @@ uint8_t input_config_bind_map_get_retro_key(unsigned bind_index) void input_config_reset_autoconfig_binds(unsigned port) { - size_t i; + unsigned i; input_sensor_map_t map; if (port >= MAX_USERS) diff --git a/gfx/drivers/gl3.c b/gfx/drivers/gl3.c index fb77e1b459..3dda3af15e 100644 --- a/gfx/drivers/gl3.c +++ b/gfx/drivers/gl3.c @@ -4385,7 +4385,7 @@ static bool gl3_read_viewport_hdr(void *data, uint16_t *buffer, static bool gl3_read_viewport(void *data, uint8_t *buffer, bool is_idle) { gl3_t *gl = (gl3_t*)data; - unsigned num_pixels = 0; + size_t num_pixels = 0; if (!gl) return false; diff --git a/libretro-common/cdrom/cdrom.c b/libretro-common/cdrom/cdrom.c index 85e621ecec..6a488e322e 100644 --- a/libretro-common/cdrom/cdrom.c +++ b/libretro-common/cdrom/cdrom.c @@ -1362,7 +1362,7 @@ static int cdrom_read_track_info(libretro_vfs_implementation_file *stream, unsig pregap_lba_len = (toc->track[track - 1].audio ? 0 : (toc->track[track - 1].lba - toc->track[track - 1].lba_start)); - toc->track[track - 1].track_bytes = (track_size - pregap_lba_len) * 2352; + toc->track[track - 1].track_bytes = (unsigned)((track_size - pregap_lba_len) * 2352); toc->track[track - 1].mode = buf[6] & 0xF; #ifdef CDROM_DEBUG diff --git a/libretro-common/formats/chd/rchd.c b/libretro-common/formats/chd/rchd.c index 5716f64218..8f636b4670 100644 --- a/libretro-common/formats/chd/rchd.c +++ b/libretro-common/formats/chd/rchd.c @@ -2656,10 +2656,14 @@ int rchd_read_extent(const rchd_t *chd, uint32_t lba, uint32_t count, if (!chd->track_count) return RCHD_ERROR_STATE; + /* Frame numbers are 32-bit: an extent running past the last one + * cannot be in the image. */ + if ((uint64_t)lba + count > 0xFFFFFFFFu + (uint64_t)1) + return RCHD_ERROR_PARAM; + for (i = 0; i < count; i++) { - const rchd_track_t *t = rchd_track_for_lba(chd, - (uint64_t)lba + i); + const rchd_track_t *t = rchd_track_for_lba(chd, lba + i); if (!t) return RCHD_ERROR_PARAM; diff --git a/libretro-common/media/media_detect_cd.c b/libretro-common/media/media_detect_cd.c index ae460f1a0d..7afb987f81 100644 --- a/libretro-common/media/media_detect_cd.c +++ b/libretro-common/media/media_detect_cd.c @@ -34,7 +34,7 @@ static void media_zero_trailing_spaces(char *s, size_t len) { int i; - for (i = len - 1; i >= 0; i--) + for (i = (int)len - 1; i >= 0; i--) { if (s[i] == ' ') s[i] = '\0'; diff --git a/libretro-common/vfs/vfs_implementation_cdrom.c b/libretro-common/vfs/vfs_implementation_cdrom.c index 05564c8bc6..fdd9313334 100644 --- a/libretro-common/vfs/vfs_implementation_cdrom.c +++ b/libretro-common/vfs/vfs_implementation_cdrom.c @@ -82,7 +82,7 @@ int64_t retro_vfs_file_seek_cdrom( && (ext[2] == 'n' || ext[2] == 'N') && ext[3] == '\0') { - int lba = (offset / 2352); + int lba = (int)(offset / 2352); unsigned char min = 0; unsigned char sec = 0; unsigned char frame = 0; @@ -99,7 +99,7 @@ int64_t retro_vfs_file_seek_cdrom( seek_type = "SEEK_CUR"; #endif stream->cdrom->byte_pos += offset; - new_lba = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (stream->cdrom->byte_pos / 2352); + new_lba = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (unsigned)(stream->cdrom->byte_pos / 2352); cdrom_lba_to_msf(new_lba, &min, &sec, &frame); } break; @@ -112,7 +112,7 @@ int64_t retro_vfs_file_seek_cdrom( #ifdef CDROM_DEBUG seek_type = "SEEK_END"; #endif - cdrom_lba_to_msf(lba_len + lba, &min, &sec, &frame); + cdrom_lba_to_msf((unsigned)(lba_len + lba), &min, &sec, &frame); stream->cdrom->byte_pos = lba_len * 2352; } break; @@ -123,7 +123,7 @@ int64_t retro_vfs_file_seek_cdrom( seek_type = "SEEK_SET"; #endif stream->cdrom->byte_pos = offset; - cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (stream->cdrom->byte_pos / 2352), &min, &sec, &frame); + cdrom_lba_to_msf(vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba + (unsigned)(stream->cdrom->byte_pos / 2352), &min, &sec, &frame); } break; } @@ -604,7 +604,7 @@ int64_t retro_vfs_file_read_cdrom(libretro_vfs_implementation_file *stream, stream->cdrom->byte_pos += len; stream->cdrom->cur_lba = vfs_cdrom_toc.track[stream->cdrom->cur_track - 1].lba - + (stream->cdrom->byte_pos / 2352); + + (unsigned)(stream->cdrom->byte_pos / 2352); cdrom_lba_to_msf(stream->cdrom->cur_lba, &stream->cdrom->cur_min, diff --git a/location/drivers/corelocation.m b/location/drivers/corelocation.m index af11a4d0a5..94e5028902 100644 --- a/location/drivers/corelocation.m +++ b/location/drivers/corelocation.m @@ -31,8 +31,28 @@ - (void)applyAuthorizationStatus:(CLAuthorizationStatus)status; @end +/* -locationManager:didChangeAuthorizationStatus:, which macOS 11 / iOS 14 + * replaced with -locationManagerDidChangeAuthorization: and deprecated: + * installed by +initialize on the releases before, the only ones that + * call it. */ +static void corelocation_did_change_status(id self, SEL _cmd, + id manager, int status) +{ + [(CoreLocationManager*)self + applyAuthorizationStatus:(CLAuthorizationStatus)status]; +} + @implementation CoreLocationManager ++ (void)initialize { + if (self != [CoreLocationManager class]) + return; + if (!apple_runtime_available(APPLE_RUNTIME_VER(11, 0, 0), APPLE_RUNTIME_VER(14, 0, 0), APPLE_RUNTIME_VER(14, 0, 0))) + apple_rt_add_method(self, + "locationManager:didChangeAuthorizationStatus:", + corelocation_did_change_status, "v@:@i"); +} + + (instancetype)sharedInstance { static CoreLocationManager *sharedInstance = nil; static dispatch_once_t onceToken; @@ -93,8 +113,9 @@ NSLog(@"Location manager failed with error: %@", error); } -- (void)locationManager:(CLLocationManager *)manager didChangeAuthorizationStatus:(CLAuthorizationStatus)status { - [self applyAuthorizationStatus:status]; +- (void)locationManagerDidChangeAuthorization:(CLLocationManager *)manager { + [self applyAuthorizationStatus:(CLAuthorizationStatus)apple_rt_get_int( + manager, @selector(authorizationStatus))]; } - (void)applyAuthorizationStatus:(CLAuthorizationStatus)status { diff --git a/pkg/apple/fastlane/Fastfile b/pkg/apple/fastlane/Fastfile index 06a949bea9..89176860e3 100644 --- a/pkg/apple/fastlane/Fastfile +++ b/pkg/apple/fastlane/Fastfile @@ -190,12 +190,15 @@ private_lane :ra_prior_build_in_review do in_review = false begin app = Spaceship::ConnectAPI::App.find(app_id) - builds = Spaceship::ConnectAPI::Build.all( - app_id: app.id, - filter: { "preReleaseVersion.platform" => plat }, + # Build.all takes no filter and pages through every build the app + # has; one page of the newest few, with their review submissions, + # is all this needs. + builds = Spaceship::ConnectAPI.get_builds( + filter: { app: app.id, "preReleaseVersion.platform" => plat }, + includes: "preReleaseVersion,betaAppReviewSubmission", sort: "-uploadedDate", limit: 5 - ) + ).to_models in_review = builds.any? do |b| state = b.beta_app_review_submission&.beta_review_state state == "WAITING_FOR_REVIEW" || state == "IN_REVIEW" diff --git a/pkg/apple/make-frameworks.sh b/pkg/apple/make-frameworks.sh index 1467f22be1..f9ff80d228 100755 --- a/pkg/apple/make-frameworks.sh +++ b/pkg/apple/make-frameworks.sh @@ -48,6 +48,23 @@ process_one() { intermediate="${intermediate/%$SUFFIX/}" fi fwName="${intermediate//_/.}" + + # App Store Connect takes an iOS/tvOS binary only with an + # LC_ENCRYPTION_INFO_64 that is not yet encrypted (cryptid 0), which + # Apple's ld writes and other linkers do not; one core without it + # fails the whole upload (ITMS-90125). Leave such a core out of an + # App Store build and name it, rather than lose every other core. + if [ -n "$APPSTORE_BUILD" ] && [ "$PLATFORM_FAMILY_NAME" = "iOS" -o "$PLATFORM_FAMILY_NAME" = "tvOS" ] ; then + cryptid=$(otool -l "$dylib" | awk '/cmd LC_ENCRYPTION_INFO/ { f = 1 } f && $1 == "cryptid" { print $2; exit }') + if [ -z "$cryptid" ] ; then + echo "warning: leaving $fwName out of the App Store build: $(basename "$dylib") has no LC_ENCRYPTION_INFO_64 (not linked by Apple's ld)" + return 0 + elif [ "$cryptid" != "0" ] ; then + echo "warning: leaving $fwName out of the App Store build: $(basename "$dylib") is already encrypted (cryptid $cryptid)" + return 0 + fi + fi + echo Making framework $fwName from $dylib fwDir="${OUTDIR}/${fwName}.framework" @@ -94,7 +111,7 @@ process_one() { } export -f process_one export OUTDIR DSYM_OUTDIR SUFFIX PLATFORM_FAMILY_NAME PLATFORM \ - DEPLOYMENT_TARGET CODE_SIGN_IDENTITY_FOR_ITEMS + DEPLOYMENT_TARGET CODE_SIGN_IDENTITY_FOR_ITEMS APPSTORE_BUILD JOBS=$(sysctl -n hw.ncpu) if [ "$JOBS" -gt 8 ] ; then JOBS=8 ; fi diff --git a/ui/drivers/cocoa/cocoa_common.m b/ui/drivers/cocoa/cocoa_common.m index 5445b8a441..df67dc7f6a 100644 --- a/ui/drivers/cocoa/cocoa_common.m +++ b/ui/drivers/cocoa/cocoa_common.m @@ -130,14 +130,45 @@ static CocoaView* g_instance; void *glkitview_init(void); void cocoa_file_load_with_detect_core(const char *filename); -@interface CocoaView() #if TARGET_OS_IOS -,UIDocumentPickerDelegate +- (void)importDocumentAtURL:(NSURL *)url; #endif -> @end #endif +/* Methods a release before the deployment target's SDK still calls but + * the SDK marks deprecated or unavailable: +initialize installs each + * only on the releases that call it (apple_rt_add_method). */ +#if TARGET_OS_OSX +/* NSView's own -layer:shouldInheritContentsScale:fromWindow: (10.7, + * asked when the view hosts a layer such as the Vulkan CAMetalLayer), + * deprecated in 11.0 for the NSViewLayerContentScaleDelegate method + * of the same name. */ +static BOOL cocoa_view_inherit_contents_scale(id self, SEL _cmd, + id layer, CGFloat scale, id window) +{ + return YES; +} +#elif TARGET_OS_IOS +/* Before iOS 6 the only rotation question. */ +static BOOL cocoa_view_autorotate_to(id self, SEL _cmd, NSInteger orientation) +{ + return YES; +} + +/* The iOS 8 - 10 document picker's answer; 11 sends the URL array. */ +static void cocoa_view_picked_document(id self, SEL _cmd, + id controller, NSURL *url) +{ + [(CocoaView*)self importDocumentAtURL:url]; +} +#endif + static CFRunLoopObserverRef iterate_observer; static void rarch_draw_observer(CFRunLoopObserverRef observer, @@ -205,11 +236,33 @@ void rarch_stop_draw_observer(void) @implementation CocoaView ++ (void)initialize +{ + if (self != [CocoaView class]) + return; +#if TARGET_OS_OSX + if (apple_runtime_available(APPLE_RUNTIME_VER(10, 7, 0), 0, 0)) + { + static char types[32]; + snprintf(types, sizeof(types), "%s@:@%s@", @encode(BOOL), @encode(CGFloat)); + apple_rt_add_method(self, "layer:shouldInheritContentsScale:fromWindow:", + cocoa_view_inherit_contents_scale, types); + } +#elif TARGET_OS_IOS + if (!apple_runtime_available(0, APPLE_RUNTIME_VER(6, 0, 0), 0)) + { + static char types[32]; + snprintf(types, sizeof(types), "%s@:%s", @encode(BOOL), @encode(NSInteger)); + apple_rt_add_method(self, "shouldAutorotateToInterfaceOrientation:", + cocoa_view_autorotate_to, types); + } + if (!apple_runtime_available(0, APPLE_RUNTIME_VER(11, 0, 0), 0)) + apple_rt_add_method(self, "documentPicker:didPickDocumentAtURL:", + cocoa_view_picked_document, "v@:@@"); +#endif +} + #if TARGET_OS_OSX -/* CALayerDelegate, asked from 10.7 on when the view hosts a layer (the - * Vulkan CAMetalLayer); a plain method that older releases never - * call. */ -- (BOOL)layer:(CALayer *)layer shouldInheritContentsScale:(CGFloat)newScale fromWindow:(NSWindow *)window { return YES; } - (void)scrollWheel:(NSEvent *)theEvent { } #endif @@ -597,8 +650,16 @@ retro_time_t cocoa_last_vblank_time(void) #pragma mark UIDocumentPickerViewController /* The document picker is iOS 8: UIKit calls these only there, and - * ios_show_file_sheet() checks the OS before it asks for one. */ --(void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentAtURL:(NSURL *)url API_AVAILABLE(ios(8.0)) + * ios_show_file_sheet() checks the OS before it asks for one. iOS 11 + * answers with an array; 8 - 10 with the one URL, through the method + * +initialize installs there. */ +-(void)documentPicker:(UIDocumentPickerViewController *)controller didPickDocumentsAtURLs:(NSArray *)urls API_AVAILABLE(ios(11.0)) +{ + if ([urls count]) + [self importDocumentAtURL:[urls objectAtIndex:0]]; +} + +-(void)importDocumentAtURL:(NSURL *)url { NSFileManager *manager = [NSFileManager defaultManager]; NSString *filename = (NSString*)url.path.lastPathComponent; @@ -639,7 +700,7 @@ retro_time_t cocoa_last_vblank_time(void) UIDocumentPickerViewController *documentPicker = apple_rt_init_id_long( [UIDocumentPickerViewController alloc], sel_registerName("initWithDocumentTypes:inMode:"), types, 0); - documentPicker.delegate = self; + documentPicker.delegate = (id)self; documentPicker.modalPresentationStyle = UIModalPresentationFormSheet; [self presentViewController:documentPicker animated:YES completion:nil]; } @@ -894,20 +955,16 @@ retro_time_t cocoa_last_vblank_time(void) return NO; return YES; } - -/* NOTE: This version runs on iOS2-iOS5, but not iOS6+. */ -- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation -{ - return YES; -} #endif #ifdef HAVE_COCOATOUCH +#if !TARGET_OS_TV -(BOOL) prefersPointerLocked API_AVAILABLE(ios(14.0)) { return cocoa_input_mouse_grabbed() ? YES : NO; } +#endif #pragma mark - UIViewController Lifecycle diff --git a/ui/drivers/ui_cocoa.m b/ui/drivers/ui_cocoa.m index cb9a6fa41f..5de1f2e6ae 100644 --- a/ui/drivers/ui_cocoa.m +++ b/ui/drivers/ui_cocoa.m @@ -75,6 +75,28 @@ #include "../../steam/steam.h" #endif +/* Selectors this file names with @selector() for methods newer than an + * old SDK (each call is behind -respondsToSelector: or a version + * check): declared for -Wundeclared-selector only where the SDK has + * none, and never implemented, so @selector() stays a constant. */ +#if !defined(MAC_OS_X_VERSION_10_6) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_6 +@interface NSObject (RetroArchSelectors106) +- (void)setDirectoryURL:(NSURL *)url; +- (void)setActivationPolicy:(NSInteger)policy; +@end +#endif +#if !defined(MAC_OS_X_VERSION_10_7) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_7 +@interface NSObject (RetroArchSelectors107) +- (void)toggleFullScreen:(id)sender; +@end +#endif +#if !defined(MAC_OS_X_VERSION_10_9) || MAC_OS_X_VERSION_MAX_ALLOWED < MAC_OS_X_VERSION_10_9 +@interface NSObject (RetroArchSelectors109) +- (id)beginActivityWithOptions:(unsigned long long)options reason:(NSString *)reason; +- (void)endActivity:(id)activity; +@end +#endif + typedef struct ui_application_cocoa { void *empty; @@ -214,7 +236,27 @@ static bool ui_browser_window_cocoa_open(ui_browser_window_state_t *state) * under ARC, required under MRC or the array leaks every time * the picker opens with a filter). */ NSArray *filetypes = [[NSArray alloc] initWithObjects:BOXSTRING(state->filters), BOXSTRING(state->filters_title), nil]; - [panel setAllowedFileTypes:filetypes]; + id utt; + /* -setAllowedFileTypes: (10.3) is deprecated in 12.0 for + * -setAllowedContentTypes: and UTTypes (11.0): 11 on gives the + * panel content types, earlier releases the extensions; both by + * selector. */ + if ( apple_runtime_available(APPLE_RUNTIME_VER(11, 0, 0), 0, 0) + && (utt = apple_rt_class("UTType"))) + { + NSUInteger i; + NSMutableArray *types = [NSMutableArray array]; + SEL by_ext = sel_registerName("typeWithFilenameExtension:"); + for (i = 0; i < [filetypes count]; i++) + { + id t = apple_rt_get_id_arg(utt, by_ext, [filetypes objectAtIndex:i]); + if (t) + [types addObject:t]; + } + apple_rt_send_id(panel, sel_registerName("setAllowedContentTypes:"), types); + } + else + apple_rt_send_id(panel, sel_registerName("setAllowedFileTypes:"), filetypes); RARCH_RELEASE(filetypes); } @@ -342,7 +384,7 @@ static enum ui_msg_window_response ui_msg_window_cocoa_dialog(ui_msg_window_stat #pragma GCC diagnostic ignored "-Wdeprecated-declarations" [alert beginSheetModalForWindow:main_window modalDelegate:apple_platform - didEndSelector:@selector(alertDidEnd:returnCode:contextInfo:) + didEndSelector:sel_registerName("alertDidEnd:returnCode:contextInfo:") contextInfo:nil]; #pragma GCC diagnostic pop response = [[NSApplication sharedApplication] runModalForWindow:[alert window]]; @@ -1333,7 +1375,9 @@ static void open_document_handler( { settings_t *settings = config_get_ptr(); const char *path_dir_libretro = settings->paths.directory_libretro; - [[NSWorkspace sharedWorkspace] openFile:BOXSTRING(path_dir_libretro)]; + /* -openFile: is deprecated in 11.0; -openURL: with a file URL opens + * the folder the same way on every release. */ + [[NSWorkspace sharedWorkspace] openURL:[NSURL fileURLWithPath:BOXSTRING(path_dir_libretro)]]; } - (IBAction)basicEvent:(id)sender diff --git a/ui/drivers/ui_cocoa_companion.m b/ui/drivers/ui_cocoa_companion.m index e49cee7cec..330ef12841 100644 --- a/ui/drivers/ui_cocoa_companion.m +++ b/ui/drivers/ui_cocoa_companion.m @@ -110,6 +110,32 @@ static NSString *companion_filenames_type(void) #endif } +/* The generic folder icon. -iconForFileType: (10.0) is deprecated in + * 12.0 for -iconForContentType: and a UTType (11.0), so 11 on asks by + * content type and earlier releases by the 'fldr' HFS type (the named + * constant is in Carbon's Icons.h, not pulled in here); both by + * selector. Autoreleased, as both methods return it. */ +static NSImage *companion_folder_icon(void) +{ + NSWorkspace *ws = [NSWorkspace sharedWorkspace]; +#ifdef GNUSTEP + return [ws iconForFileType:NSFileTypeForHFSTypeCode('fldr')]; +#else + id utt; + if ( apple_runtime_available(APPLE_RUNTIME_VER(11, 0, 0), 0, 0) + && (utt = apple_rt_class("UTType"))) + { + id folder = apple_rt_get_id_arg(utt, + sel_registerName("typeWithIdentifier:"), @"public.folder"); + if (folder) + return apple_rt_get_id_arg(ws, + sel_registerName("iconForContentType:"), folder); + } + return apple_rt_get_id_arg(ws, sel_registerName("iconForFileType:"), + NSFileTypeForHFSTypeCode('fldr')); +#endif +} + #include "../../command.h" #include "../../configuration.h" #include "../../retroarch.h" @@ -894,10 +920,7 @@ static const companion_callbacks_t cc_callbacks = { if (wimp && playlistIcons) { size_t i, n = companion_core_playlist_count(wimp->core); - /* 'fldr' is the generic folder HFS type; the named constant lives - * in Carbon's Icons.h, which is not pulled in here. */ - NSImage *folder = [[NSWorkspace sharedWorkspace] iconForFileType: - NSFileTypeForHFSTypeCode('fldr')]; + NSImage *folder = companion_folder_icon(); [playlistIcons removeAllObjects]; for (i = 0; i < n; i++) { @@ -1427,8 +1450,7 @@ static void cc_thumb_done(void *ud, const char *path, unsigned dims, if (companion_core_folder_icon_path(wimp->core, icon, sizeof(icon))) folderIcon = [[NSImage alloc] initWithContentsOfFile:BOXSTRING(icon)]; if (!folderIcon) - folderIcon = RETAIN_COMPAT([[NSWorkspace sharedWorkspace] - iconForFileType:NSFileTypeForHFSTypeCode('fldr')]); + folderIcon = RETAIN_COMPAT(companion_folder_icon()); } browserTabs = [[NSTabView alloc] initWithFrame:NSMakeRect(0, 0, CC_PANE_W, 300)];