diff options
-rw-r--r-- | Makefile | 27 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/AutoGrid.h | 17 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/AutoGrid.m | 106 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/Info.plist | bin | 0 -> 1478 bytes | |||
-rw-r--r-- | ios-bootstrap/safety-dance/main.m | 159 | ||||
-rw-r--r-- | ios-bootstrap/safety-dance/white.png | bin | 0 -> 1047 bytes |
6 files changed, 305 insertions, 4 deletions
@@ -7,16 +7,16 @@ CXX := clang++ ARCH := -arch x86_64 XCFLAGS := -O3 -Wall -Wextra -Werror -Ilib $(ARCH) LIB_LDFLAGS := -lobjc -framework CoreFoundation -dynamiclib -fvisibility=hidden -install_name /usr/lib/libsubstitute.0.dylib -dead_strip -override CC := $(CC) $(XCFLAGS) $(CFLAGS) -override CXX := $(CXX) $(XCFLAGS) $(CFLAGS) -fno-exceptions -fno-asynchronous-unwind-tables -IS_IOS := $(findstring -arch arm,$(CC)) - +IOS_APP_LDFLAGS := -framework UIKit -framework Foundation -dead_strip ifneq (,$(IS_IOS)) # I don't know anything in particular that would break this on older versions, # but I don't have any good way to test it and don't really care. So ensure it # doesn't get run on them. XCFLAGS := $(XCFLAGS) -miphoneos-version-min=7.0 endif +override CC := $(CC) $(XCFLAGS) $(CFLAGS) +override CXX := $(CXX) $(XCFLAGS) $(CFLAGS) -fno-exceptions -fno-asynchronous-unwind-tables +IS_IOS := $(findstring -arch arm,$(CC)) # These are only required to rebuild the generated disassemblers. IMAON2 := /Users/comex/c/imaon2 @@ -149,5 +149,24 @@ out/insns-libz-arm.o: test/insns-libz-arm.S Makefile out/insns-libz-thumb2.o: test/insns-libz-arm.S Makefile clang -arch armv7 -c -o $@ $< -DTHUMB2 +# iOS bootstrap... +ifneq (,$(IS_IOS)) +SD_OBJS := out/safety-dance/main.o out/safety-dance/AutoGrid.o +out/safety-dance/%.o: ios-bootstrap/safety-dance/%.m ios-bootstrap/safety-dance/*.h Makefile + @mkdir -p $(dir $@) + $(CC) -c -o $@ $< -fobjc-arc -Wno-unused-parameter +out/safety-dance/SafetyDance.app/SafetyDance: $(SD_OBJS) Makefile + @mkdir -p $(dir $@) + $(CC) -o $@ $(SD_OBJS) $(IOS_APP_LDFLAGS) + ldid -S $@ +out/safety-dance/SafetyDance.app/Info.plist: ios-bootstrap/safety-dance/Info.plist Makefile + @mkdir -p $(dir $@) + plutil -convert binary1 -o $< $@ + cp ios-bootstrap/safety-dance/white.png out/safety-dance/SafetyDance.app/Default.png + cp ios-bootstrap/safety-dance/white.png out/safety-dance/SafetyDance.app/Default@2x.png +safety-dance: out/safety-dance/SafetyDance.app/SafetyDance out/safety-dance/SafetyDance.app/Info.plist +endif + + clean: rm -rf out diff --git a/ios-bootstrap/safety-dance/AutoGrid.h b/ios-bootstrap/safety-dance/AutoGrid.h new file mode 100644 index 0000000..335381a --- /dev/null +++ b/ios-bootstrap/safety-dance/AutoGrid.h @@ -0,0 +1,17 @@ +// +// AutoGrid.h +// SafetyDance +// +// Created by Nicholas Allegra on 1/26/15. +// Copyright (c) 2015 Nicholas Allegra. All rights reserved. +// + +#import <UIKit/UIKit.h> + +@interface AutoGrid : UIView { + NSArray *views; + UIScrollView *scrollView; +} +- (void)setViews:(NSArray *)views; + +@end diff --git a/ios-bootstrap/safety-dance/AutoGrid.m b/ios-bootstrap/safety-dance/AutoGrid.m new file mode 100644 index 0000000..2a8d3ed --- /dev/null +++ b/ios-bootstrap/safety-dance/AutoGrid.m @@ -0,0 +1,106 @@ +// +// AutoGrid.m +// SafetyDance +// +// Created by Nicholas Allegra on 1/26/15. +// Copyright (c) 2015 Nicholas Allegra. All rights reserved. +// + +#import "AutoGrid.h" + +@implementation AutoGrid +- (void)setViews:(NSArray *)_views { + views = _views; + [scrollView removeFromSuperview]; + scrollView = [[UIScrollView alloc] init]; + [self addSubview:scrollView]; + for (UIView *view in views) + [scrollView addSubview:view]; + [self setNeedsLayout]; +} + +- (void)layoutSubviews { + scrollView.frame = self.bounds; + CGFloat paddingX = 22, paddingY = 10; + NSUInteger nviews = [views count]; + CGSize *sizes = malloc(sizeof(*sizes) * nviews); + + for (NSUInteger i = 0; i < nviews; i++) + sizes[i] = [[views objectAtIndex:i] intrinsicContentSize]; + + CGFloat availableWidth = self.bounds.size.width; + /* try to lay out using an increasing number of columns */ + NSUInteger cols; + CGSize contentSize; + CGFloat *colWidths = NULL; + for (cols = 1; ; cols++) { + free(colWidths); + colWidths = malloc(sizeof(*colWidths) * cols); + for (NSUInteger col = 0; col < cols; col++) + colWidths[col] = 0; + CGFloat tentativeHeight = 0; + CGFloat tentativeWidth = 0; + for (NSUInteger row = 0; row < nviews / cols; row++) { + CGFloat totalWidth = 0; + CGFloat maxHeight = 0; + for (NSUInteger col = 0; col < cols; col++) { + NSUInteger i = row * cols + col; + if (i >= nviews) + goto done1; + CGSize size = sizes[i]; + if (size.width > colWidths[col]) + colWidths[col] = size.width; + if (col != 0) + totalWidth += paddingX; + totalWidth += size.width; + if (size.height > maxHeight) + maxHeight = size.height; + } + if (totalWidth > tentativeWidth) + tentativeWidth = totalWidth; + tentativeHeight += maxHeight + paddingY; + } + done1: + if (cols > 1 && tentativeWidth > availableWidth) { + cols--; + break; + } + contentSize = CGSizeMake(tentativeWidth, tentativeHeight); + NSLog(@"%f", contentSize.height); + if (contentSize.width == 0) + break; + + } + scrollView.contentSize = contentSize; + CGFloat y = 0; + for (NSUInteger row = 0; ; row++) { + CGFloat x = 0; + CGFloat maxHeight = 0; + for (NSUInteger col = 0; col < cols; col++) { + NSUInteger i = row * cols + col; + if (i >= nviews) + goto done2; + CGSize size = sizes[i]; + UIView *view = [views objectAtIndex:i]; + if (col != 0) + x += paddingX; + view.frame = CGRectMake(x, y, size.width, size.height); + x += colWidths[col]; + if (size.height > maxHeight) + maxHeight = size.height; + } + y += maxHeight + paddingY; + } +done2: + free(sizes); + free(colWidths); +} +/* +// Only override drawRect: if you perform custom drawing. +// An empty implementation adversely affects performance during animation. +- (void)drawRect:(CGRect)rect { + // Drawing code +} +*/ + +@end diff --git a/ios-bootstrap/safety-dance/Info.plist b/ios-bootstrap/safety-dance/Info.plist Binary files differnew file mode 100644 index 0000000..fd6a1b3 --- /dev/null +++ b/ios-bootstrap/safety-dance/Info.plist diff --git a/ios-bootstrap/safety-dance/main.m b/ios-bootstrap/safety-dance/main.m new file mode 100644 index 0000000..2e9af22 --- /dev/null +++ b/ios-bootstrap/safety-dance/main.m @@ -0,0 +1,159 @@ +#import <UIKit/UIKit.h> +#import "AutoGrid.h" + +@interface ViewController : UIViewController { + AutoGrid *autoGrid; +} + +@end + +@implementation ViewController + +- (void)viewDidLoad { + [super viewDidLoad]; + [self loadStuff]; + NSMutableArray *names = [NSMutableArray array]; + for (int i = 0; i < 100; i++) + [names addObject:[NSString stringWithFormat:@"Some Dylib %d", i]]; + NSMutableArray *views = [NSMutableArray array]; + for (NSString *name in names) { + UILabel *label = [[UILabel alloc] init]; + label.text = name; + [views addObject:label]; + } + [autoGrid setViews:views]; +} + +#define EXPLANATION \ + @"SpringBoard seems to have crashed. The cause might be a Substitute jailbreak extension, or unrelated. Just to be safe, extensions in SpringBoard have been temporarily disabled. You can continue in this mode, or restart SpringBoard normally.\n\nThe following extensions were running:" + +static void hugging(UIView *view, UILayoutPriority pri) { + [view setContentHuggingPriority:pri forAxis:UILayoutConstraintAxisHorizontal]; + [view setContentHuggingPriority:pri forAxis:UILayoutConstraintAxisVertical]; +} +static void compression(UIView *view, UILayoutPriority pri) { + [view setContentCompressionResistancePriority:pri forAxis:UILayoutConstraintAxisHorizontal]; + [view setContentCompressionResistancePriority:pri forAxis:UILayoutConstraintAxisVertical]; +} + +- (void)loadStuff { + self.view.backgroundColor = [UIColor whiteColor]; + + UILabel *top = [[UILabel alloc] init]; + top.translatesAutoresizingMaskIntoConstraints = NO; + top.textAlignment = NSTextAlignmentCenter; + hugging(top, 251); + top.text = @"libsubstitute"; + top.font = [UIFont systemFontOfSize:23]; + [self.view addSubview:top]; + + UILabel *big = [[UILabel alloc] init]; + big.translatesAutoresizingMaskIntoConstraints = NO; + big.textAlignment = NSTextAlignmentCenter; + hugging(big, 251); + [big setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisHorizontal]; + [big setContentHuggingPriority:251 forAxis:UILayoutConstraintAxisVertical]; + big.text = @"Safe Mode"; + big.font = [UIFont systemFontOfSize:32]; + [self.view addSubview:big]; + + UILabel *explain = [[UILabel alloc] init]; + explain.translatesAutoresizingMaskIntoConstraints = NO; + explain.textAlignment = NSTextAlignmentCenter; + hugging(explain, 251); + compression(explain, 999); + explain.text = EXPLANATION; + explain.font = [UIFont systemFontOfSize:14]; + explain.minimumFontSize = 7; + explain.numberOfLines = 0; + [self.view addSubview:explain]; + + UIButton *returnButton = [UIButton buttonWithType:UIButtonTypeSystem]; + returnButton.translatesAutoresizingMaskIntoConstraints = NO; + returnButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; + returnButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; + returnButton.titleLabel.font = [UIFont systemFontOfSize:17]; + [returnButton setTitle:@"Return to Normal" forState:UIControlStateNormal]; + [self.view addSubview:returnButton]; + + UIButton *continueButton = [UIButton buttonWithType:UIButtonTypeSystem]; + continueButton.translatesAutoresizingMaskIntoConstraints = NO; + hugging(continueButton, 999); + compression(continueButton, 300); + continueButton.contentVerticalAlignment = UIControlContentVerticalAlignmentCenter; + continueButton.contentHorizontalAlignment = UIControlContentHorizontalAlignmentCenter; + continueButton.titleLabel.font = [UIFont systemFontOfSize:17]; + [continueButton setTitle:@"Continue in Safe Mode" forState:UIControlStateNormal]; + [self.view addSubview:continueButton]; + + autoGrid = [[AutoGrid alloc] init]; + autoGrid.translatesAutoresizingMaskIntoConstraints = NO; + [self.view addSubview:autoGrid]; + + NSDictionary *viewsDictionary = @{ + @"top": top, + @"big": big, + @"explain": explain, + @"returnButton": returnButton, + @"continueButton": continueButton, + @"grid": autoGrid, + @"topGuide": self.topLayoutGuide, + @"bottomGuide": self.bottomLayoutGuide, + }; + NSMutableArray *constraints = [[NSMutableArray alloc] init]; + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat: + @"V:[topGuide]-10-[top]-0@100-[big]-0@100-[explain]-18@200-[grid]-18-[continueButton]-8-[returnButton]-20@100-[bottomGuide]" + options:NSLayoutFormatAlignAllCenterX metrics:nil views:viewsDictionary]]; + NSArray *additional = @[ + @"[explain(<=650)]", + @"|-10-[explain]-10-|", + @"|-20-[grid]-20-|", + ]; + for (NSString *fmt in additional) { + [constraints addObjectsFromArray: + [NSLayoutConstraint constraintsWithVisualFormat:fmt options:0 metrics:nil views:viewsDictionary]]; + } + [self.view addConstraints:constraints]; +} + + +- (NSUInteger)supportedInterfaceOrientations +{ + if ([UIDevice currentDevice].userInterfaceIdiom == UIUserInterfaceIdiomPad) + return UIInterfaceOrientationMaskAll; + else if ([UIScreen mainScreen].bounds.size.width >= 414) + return UIInterfaceOrientationMaskAllButUpsideDown; + else + return UIInterfaceOrientationMaskPortrait; +} + +@end + +@interface AppDelegate : UIResponder <UIApplicationDelegate> { +} + +@property (strong, nonatomic) UIWindow *window; + + +@end + +@implementation AppDelegate +- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { + NSLog(@"dflwo"); + self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; + ViewController *viewController = [[ViewController alloc] init]; + self.window.rootViewController = viewController; + [self.window makeKeyAndVisible]; + return YES; +} + +@end + +int main(int argc, char *argv[]) { + NSLog(@"main"); + @autoreleasepool { + return UIApplicationMain(argc, argv, nil, @"AppDelegate"); + } +} + diff --git a/ios-bootstrap/safety-dance/white.png b/ios-bootstrap/safety-dance/white.png Binary files differnew file mode 100644 index 0000000..eab5a56 --- /dev/null +++ b/ios-bootstrap/safety-dance/white.png |