mirror of https://github.com/LIJI32/SameBoy.git
Dynamic rewind/forward speed in iOS
This commit is contained in:
parent
ef8f3aff66
commit
42ce9c410b
|
@ -87,6 +87,7 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
UITouch *_screenTouch;
|
||||
CGPoint _screenSwipeOrigin;
|
||||
bool _screenSwiped;
|
||||
bool _inDynamicSpeedMode;
|
||||
|
||||
UIImageView *_dpadView;
|
||||
UIImageView *_dpadShadowView;
|
||||
|
@ -146,6 +147,7 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
if (@available(iOS 13.0, *)) {
|
||||
_overlayViewContents = [[UIImageView alloc] init];
|
||||
_overlayViewContents.tintColor = [UIColor whiteColor];
|
||||
_overlayViewContents.contentMode = UIViewContentModeCenter;
|
||||
}
|
||||
else {
|
||||
_overlayViewContents = [[UILabel alloc] init];
|
||||
|
@ -182,9 +184,14 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
_screenTouch = touch;
|
||||
_screenSwipeOrigin = point;
|
||||
_screenSwiped = false;
|
||||
_inDynamicSpeedMode = false;
|
||||
_overlayView.alpha = 0;
|
||||
[_fadeTimer invalidate];
|
||||
_fadeTimer = nil;
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
self.viewController.runMode = GBRunModePaused;
|
||||
[self displayOverlayWithImage:@"pause" orTitle:@"Paused"];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -208,6 +215,10 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
|
||||
if ([touches containsObject:_screenTouch]) {
|
||||
_screenTouch = nil;
|
||||
if (self.viewController.runMode == GBRunModePaused) {
|
||||
self.viewController.runMode = GBRunModeNormal;
|
||||
[self fadeOverlayOut];
|
||||
}
|
||||
if (!_screenSwiped) {
|
||||
[self.window.rootViewController presentViewController:[GBMenuViewController menu] animated:true completion:nil];
|
||||
}
|
||||
|
@ -264,6 +275,33 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
CGPoint point = [touch locationInView:self];
|
||||
|
||||
if (touch == _screenTouch) {
|
||||
if (_inDynamicSpeedMode) {
|
||||
double delta = point.x - _screenSwipeOrigin.x;
|
||||
if (fabs(delta) < 32) {
|
||||
self.viewController.runMode = GBRunModePaused;
|
||||
[self displayOverlayWithImage:@"pause" orTitle:@"Paused"];
|
||||
continue;
|
||||
}
|
||||
|
||||
double speed = fabs(delta / _gbView.frame.size.width * 3);
|
||||
if (delta > 0) {
|
||||
if (speed > 1) {
|
||||
[self displayOverlayWithImage:@"forward" orTitle:@"Fast-forwarding…"];
|
||||
}
|
||||
else {
|
||||
[self displayOverlayWithImage:@"play" orTitle:@"Forward…"];
|
||||
}
|
||||
GB_set_clock_multiplier(_gbView.gb, speed);
|
||||
self.viewController.runMode = GBRunModeTurbo;
|
||||
}
|
||||
else {
|
||||
[self displayOverlayWithImage:@"backward" orTitle:@"Rewinding…"];
|
||||
GB_set_clock_multiplier(_gbView.gb, speed);
|
||||
self.viewController.runMode = GBRunModeRewind;
|
||||
|
||||
}
|
||||
continue;
|
||||
}
|
||||
if (_screenSwiped) continue;
|
||||
if (point.x - _screenSwipeOrigin.x > 32) {
|
||||
[self turboSwipe];
|
||||
|
@ -397,11 +435,14 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
}
|
||||
[_overlayViewContents sizeToFit];
|
||||
|
||||
CGRect bounds = _overlayViewContents.bounds;
|
||||
bounds.origin = (CGPoint){8, 8};
|
||||
bounds.size.width += 16;
|
||||
bounds.size.height += 16;
|
||||
_overlayView.frame = bounds;
|
||||
CGRect frame = _overlayViewContents.frame;
|
||||
frame.size.width = MAX(frame.size.width, 25);
|
||||
frame.size.height = MAX(frame.size.height, 22);
|
||||
_overlayViewContents.frame = frame;
|
||||
frame.origin = (CGPoint){8, 8};
|
||||
frame.size.width += 16;
|
||||
frame.size.height += 16;
|
||||
_overlayView.frame = frame;
|
||||
|
||||
_overlayView.alpha = 1.0;
|
||||
}
|
||||
|
@ -418,6 +459,9 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
- (void)turboSwipe
|
||||
{
|
||||
_screenSwiped = true;
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
_inDynamicSpeedMode = true;
|
||||
}
|
||||
[self displayOverlayWithImage:@"forward" orTitle:@"Fast-forwarding…"];
|
||||
self.viewController.runMode = GBRunModeTurbo;
|
||||
}
|
||||
|
@ -425,6 +469,9 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
- (void)rewindSwipe
|
||||
{
|
||||
_screenSwiped = true;
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
_inDynamicSpeedMode = true;
|
||||
}
|
||||
[self displayOverlayWithImage:@"backward" orTitle:@"Rewinding…"];
|
||||
self.viewController.runMode = GBRunModeRewind;
|
||||
}
|
||||
|
@ -437,7 +484,9 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
- (void)saveSwipe
|
||||
{
|
||||
_screenSwiped = true;
|
||||
self.viewController.runMode = GBRunModeNormal;
|
||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBSwipeState"]) {
|
||||
[self fadeOverlayOut];
|
||||
return;
|
||||
}
|
||||
[self displayOverlayWithImage:@"square.and.arrow.down" orTitle:@"Saved state to Slot 1"];
|
||||
|
@ -452,7 +501,9 @@ static GB_key_mask_t angleToKeyMask(double angle)
|
|||
- (void)loadSwipe
|
||||
{
|
||||
_screenSwiped = true;
|
||||
self.viewController.runMode = GBRunModeNormal;
|
||||
if (![[NSUserDefaults standardUserDefaults] boolForKey:@"GBSwipeState"]) {
|
||||
[self fadeOverlayOut];
|
||||
return;
|
||||
}
|
||||
[self displayOverlayWithImage:@"square.and.arrow.up" orTitle:@"Loaded state from Slot 1"];
|
||||
|
|
|
@ -136,7 +136,13 @@ static NSString const *typeLightTemp = @"typeLightTemp";
|
|||
@{@"type": typeRadio, @"pref": @"GBTurboSpeed", @"title": @"200%", @"value": @2,},
|
||||
@{@"type": typeRadio, @"pref": @"GBTurboSpeed", @"title": @"400%", @"value": @4,},
|
||||
@{@"type": typeRadio, @"pref": @"GBTurboSpeed", @"title": @"Uncapped", @"value": @1,},
|
||||
]
|
||||
],
|
||||
@"footer": ^NSString *(){
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
return @"This setting will have no effect because horizontal swipes are configured to dynamically control speed in the “Controls” settings";
|
||||
}
|
||||
return @"";
|
||||
},
|
||||
},
|
||||
@{
|
||||
@"header": @"Rewind Speed",
|
||||
|
@ -144,7 +150,13 @@ static NSString const *typeLightTemp = @"typeLightTemp";
|
|||
@{@"type": typeRadio, @"pref": @"GBRewindSpeed", @"title": @"100%", @"value": @1,},
|
||||
@{@"type": typeRadio, @"pref": @"GBRewindSpeed", @"title": @"200%", @"value": @2,},
|
||||
@{@"type": typeRadio, @"pref": @"GBRewindSpeed", @"title": @"400%", @"value": @4,},
|
||||
]
|
||||
],
|
||||
@"footer": ^NSString *(){
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
return @"This setting will have no effect because horizontal swipes are configured to dynamically control speed in the “Controls” settings";
|
||||
}
|
||||
return @"";
|
||||
}
|
||||
},
|
||||
@{
|
||||
@"header": @"Emulated Revisions",
|
||||
|
@ -310,15 +322,23 @@ static NSString const *typeLightTemp = @"typeLightTemp";
|
|||
},
|
||||
},
|
||||
@{
|
||||
@"header": @"Fast-forward and Rewind Behavior",
|
||||
@"header": @"Horizontal Swipe Behavior",
|
||||
@"items": @[
|
||||
@{@"type": typeCheck, @"pref": @"GBDynamicSpeed", @"title": @"Dynamically Control Speed"},
|
||||
@{@"type": typeCheck, @"pref": @"GBSwipeLock", @"title": @"Lock After Swiping"},
|
||||
],
|
||||
@"footer": ^NSString *(){
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBSwipeLock"]) {
|
||||
return @"Swipe right on the Game Boy screen to fast-forward, and swipe left to rewind. Tap on the Game Boy screen to return to normal.";
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
return @"Swipe right on the Game Boy screen to play forward, and swipe left to rewind. Tap on the Game Boy screen to return to normal. The forward and rewind speeds are determinied by the swipe distance.";
|
||||
}
|
||||
return @"Swipe right on the Game Boy screen to fast-forward, and swipe left to rewind. Tap on the Game Boy screen to return to normal. The turbo and rewind speeds can be configured under “Emulation” settings.";
|
||||
}
|
||||
return @"Swipe right on the Game Boy screen to fast-forward, and swipe left to rewind. Raise the touch to return to normal.";
|
||||
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
return @"Swipe right on the Game Boy screen to play forward, and swipe left to rewind. Raise the touch to return to normal. The forward and rewind speeds are determinied by the swipe distance.";
|
||||
}
|
||||
return @"Swipe right on the Game Boy screen to fast-forward, and swipe left to rewind. Raise the touch to return to normal. The turbo and rewind speeds can be configured under “Emulation” settings.";
|
||||
},
|
||||
},
|
||||
@{
|
||||
|
|
|
@ -5,7 +5,7 @@ typedef enum {
|
|||
GBRunModeNormal,
|
||||
GBRunModeTurbo,
|
||||
GBRunModeRewind,
|
||||
GBRunModeRewindPaused,
|
||||
GBRunModePaused,
|
||||
} GBRunMode;
|
||||
|
||||
@interface GBViewController : UIViewController <UIApplicationDelegate, AVCaptureVideoDataOutputSampleBufferDelegate>
|
||||
|
|
|
@ -22,6 +22,8 @@
|
|||
|
||||
volatile bool _running;
|
||||
volatile bool _stopping;
|
||||
bool _rewind;
|
||||
bool _rewindOver;
|
||||
bool _romLoaded;
|
||||
|
||||
UIInterfaceOrientation _orientation;
|
||||
|
@ -38,7 +40,6 @@
|
|||
|
||||
NSMutableSet *_defaultsObservers;
|
||||
GB_palette_t _palette;
|
||||
bool _rewind;
|
||||
CMMotionManager *_motionManager;
|
||||
|
||||
CVImageBufferRef _cameraImage;
|
||||
|
@ -540,13 +541,22 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
|||
if (_rewind) {
|
||||
_rewind = false;
|
||||
GB_rewind_pop(&_gb);
|
||||
for (unsigned i = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRewindSpeed"]; i--;) {
|
||||
if ([[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
if (!GB_rewind_pop(&_gb)) {
|
||||
self.runMode = GBRunModeRewindPaused;
|
||||
self.runMode = GBRunModePaused;
|
||||
_rewindOver = true;
|
||||
}
|
||||
}
|
||||
else {
|
||||
for (unsigned i = [[NSUserDefaults standardUserDefaults] integerForKey:@"GBRewindSpeed"]; i--;) {
|
||||
if (!GB_rewind_pop(&_gb)) {
|
||||
self.runMode = GBRunModePaused;
|
||||
_rewindOver = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
if (_runMode != GBRunModeRewindPaused) {
|
||||
if (_runMode != GBRunModePaused) {
|
||||
GB_run(&_gb);
|
||||
}
|
||||
}
|
||||
|
@ -705,23 +715,32 @@ static void rumbleCallback(GB_gameboy_t *gb, double amp)
|
|||
|
||||
- (void)setRunMode:(GBRunMode)runMode
|
||||
{
|
||||
if (runMode == GBRunModeRewind && _rewindOver) {
|
||||
runMode = GBRunModePaused;
|
||||
}
|
||||
if (runMode == _runMode) return;
|
||||
if (_runMode == GBRunModeRewindPaused) {
|
||||
if (_runMode == GBRunModePaused) {
|
||||
[_audioClient start];
|
||||
}
|
||||
_runMode = runMode;
|
||||
if (_runMode == GBRunModeRewindPaused) {
|
||||
if (_runMode == GBRunModePaused) {
|
||||
[_audioClient stop];
|
||||
}
|
||||
|
||||
if (_runMode == GBRunModeTurbo) {
|
||||
double multiplier = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboSpeed"];
|
||||
GB_set_turbo_mode(&_gb, multiplier == 1, false);
|
||||
GB_set_clock_multiplier(&_gb, multiplier);
|
||||
if (_runMode == GBRunModeNormal || _runMode == GBRunModeTurbo) {
|
||||
_rewindOver = false;
|
||||
}
|
||||
else {
|
||||
GB_set_turbo_mode(&_gb, false, false);
|
||||
GB_set_clock_multiplier(&_gb, 1.0);
|
||||
|
||||
if (_runMode == GBRunModeNormal || [[NSUserDefaults standardUserDefaults] boolForKey:@"GBDynamicSpeed"]) {
|
||||
if (_runMode == GBRunModeTurbo) {
|
||||
double multiplier = [[NSUserDefaults standardUserDefaults] doubleForKey:@"GBTurboSpeed"];
|
||||
GB_set_turbo_mode(&_gb, multiplier == 1, false);
|
||||
GB_set_clock_multiplier(&_gb, multiplier);
|
||||
}
|
||||
else {
|
||||
GB_set_turbo_mode(&_gb, false, false);
|
||||
GB_set_clock_multiplier(&_gb, 1.0);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -21,6 +21,7 @@ int main(int argc, char * argv[])
|
|||
@"GBButtonHaptics": @YES,
|
||||
@"GBTurboSpeed": @1,
|
||||
@"GBRewindSpeed": @1,
|
||||
@"GBDynamicSpeed": @NO,
|
||||
|
||||
@"GBCurrentTheme": @"Lime (Game Boy)",
|
||||
// Default themes
|
||||
|
|
Loading…
Reference in New Issue