mirror of
https://github.com/libretro/RetroArch
synced 2025-03-01 07:13:35 +00:00
(iOS) Major refactoring and simplification of UI logic
This commit is contained in:
parent
30209b3ca9
commit
735bbdd013
@ -16,102 +16,157 @@
|
|||||||
#include "general.h"
|
#include "general.h"
|
||||||
#include "rarch_wrapper.h"
|
#include "rarch_wrapper.h"
|
||||||
|
|
||||||
static float screen_scale;
|
static const float ALMOST_INVISIBLE = .021f;
|
||||||
static int frame_skips = 4;
|
static float g_screen_scale;
|
||||||
static bool is_syncing = true;
|
static int g_frame_skips = 4;
|
||||||
|
static bool g_is_syncing = true;
|
||||||
|
static RAGameView* g_instance;
|
||||||
|
|
||||||
@implementation RAGameView
|
@implementation RAGameView
|
||||||
{
|
{
|
||||||
EAGLContext* _glContext;
|
EAGLContext* _glContext;
|
||||||
|
|
||||||
|
UIView* _pauseView;
|
||||||
|
UIView* _pauseIndicatorView;
|
||||||
|
}
|
||||||
|
|
||||||
|
+ (RAGameView*)get
|
||||||
|
{
|
||||||
|
if (!g_instance)
|
||||||
|
g_instance = [RAGameView new];
|
||||||
|
|
||||||
|
return g_instance;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (id)init
|
- (id)init
|
||||||
{
|
{
|
||||||
self = [super init];
|
self = [super init];
|
||||||
screen_scale = [[UIScreen mainScreen] scale];
|
|
||||||
|
UINib* xib = [UINib nibWithNibName:@"PauseView" bundle:nil];
|
||||||
_glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
_pauseView = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
|
||||||
[EAGLContext setCurrentContext:_glContext];
|
|
||||||
|
|
||||||
|
xib = [UINib nibWithNibName:@"PauseIndicatorView" bundle:nil];
|
||||||
|
_pauseIndicatorView = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
|
||||||
|
|
||||||
self.view = [GLKView new];
|
self.view = [GLKView new];
|
||||||
((GLKView*)self.view).context = _glContext;
|
|
||||||
self.view.multipleTouchEnabled = YES;
|
self.view.multipleTouchEnabled = YES;
|
||||||
|
[self.view addSubview:_pauseView];
|
||||||
|
[self.view addSubview:_pauseIndicatorView];
|
||||||
|
|
||||||
return self;
|
return self;
|
||||||
}
|
}
|
||||||
|
|
||||||
- (void)needsToDie
|
// Driver
|
||||||
|
- (void)driverInit
|
||||||
|
{
|
||||||
|
g_screen_scale = [[UIScreen mainScreen] scale];
|
||||||
|
|
||||||
|
_glContext = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||||
|
[EAGLContext setCurrentContext:_glContext];
|
||||||
|
((GLKView*)self.view).context = _glContext;
|
||||||
|
|
||||||
|
// Show pause button for a few seconds, so people know it's there
|
||||||
|
_pauseIndicatorView.alpha = 1.0f;
|
||||||
|
[self performSelector:@selector(hidePauseButton) withObject:self afterDelay:3.0f];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)driverQuit
|
||||||
{
|
{
|
||||||
glFinish();
|
glFinish();
|
||||||
|
|
||||||
GLKView* glview = (GLKView*)self.view;
|
((GLKView*)self.view).context = nil;
|
||||||
glview.context = nil;
|
|
||||||
_glContext = nil;
|
|
||||||
[EAGLContext setCurrentContext:nil];
|
[EAGLContext setCurrentContext:nil];
|
||||||
|
_glContext = nil;
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)flip
|
||||||
|
{
|
||||||
|
if (--g_frame_skips < 0)
|
||||||
|
{
|
||||||
|
[self.view setNeedsDisplay];
|
||||||
|
[(GLKView*)self.view bindDrawable];
|
||||||
|
g_frame_skips = g_is_syncing ? 0 : 3;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Pause Menus
|
||||||
|
- (void)viewWillLayoutSubviews
|
||||||
|
{
|
||||||
|
UIInterfaceOrientation orientation = self.interfaceOrientation;
|
||||||
|
CGRect screenSize = [[UIScreen mainScreen] bounds];
|
||||||
|
|
||||||
|
const float width = ((int)orientation < 3) ? CGRectGetWidth(screenSize) : CGRectGetHeight(screenSize);
|
||||||
|
const float height = ((int)orientation < 3) ? CGRectGetHeight(screenSize) : CGRectGetWidth(screenSize);
|
||||||
|
|
||||||
|
float tenpctw = width / 10.0f;
|
||||||
|
float tenpcth = height / 10.0f;
|
||||||
|
|
||||||
|
_pauseView.frame = CGRectMake(width / 2.0f - 150.0f, height / 2.0f - 150.0f, 300.0f, 300.0f);
|
||||||
|
_pauseIndicatorView.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth);
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)openPauseMenu
|
||||||
|
{
|
||||||
|
// Setup save state selector
|
||||||
|
UISegmentedControl* stateSelect = (UISegmentedControl*)[_pauseView viewWithTag:1];
|
||||||
|
stateSelect.selectedSegmentIndex = (g_extern.state_slot < 10) ? g_extern.state_slot : -1;
|
||||||
|
|
||||||
|
//
|
||||||
|
[UIView animateWithDuration:0.2
|
||||||
|
animations:^ { _pauseView.alpha = 1.0f; }
|
||||||
|
completion:^(BOOL finished){}];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)closePauseMenu
|
||||||
|
{
|
||||||
|
[UIView animateWithDuration:0.2
|
||||||
|
animations:^ { _pauseView.alpha = 0.0f; }
|
||||||
|
completion:^(BOOL finished) { }
|
||||||
|
];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)hidePauseButton
|
||||||
|
{
|
||||||
|
[UIView animateWithDuration:0.2
|
||||||
|
animations:^ { _pauseIndicatorView.alpha = ALMOST_INVISIBLE; }
|
||||||
|
completion:^(BOOL finished) { }
|
||||||
|
];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
|
||||||
static RAGameView* gameViewer;
|
|
||||||
|
|
||||||
bool ios_init_game_view()
|
bool ios_init_game_view()
|
||||||
{
|
{
|
||||||
if (!gameViewer)
|
[RAGameView.get driverInit];
|
||||||
{
|
|
||||||
gameViewer = [RAGameView new];
|
|
||||||
[[RetroArch_iOS get] pushViewController:gameViewer isGame:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ios_destroy_game_view()
|
void ios_destroy_game_view()
|
||||||
{
|
{
|
||||||
if (gameViewer)
|
[RAGameView.get driverQuit];
|
||||||
{
|
|
||||||
[gameViewer needsToDie];
|
|
||||||
[[RetroArch_iOS get] popViewController];
|
|
||||||
gameViewer = nil;
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ios_flip_game_view()
|
void ios_flip_game_view()
|
||||||
{
|
{
|
||||||
if (gameViewer)
|
[RAGameView.get flip];
|
||||||
{
|
|
||||||
GLKView* gl_view = (GLKView*)gameViewer.view;
|
|
||||||
|
|
||||||
if (--frame_skips < 0)
|
|
||||||
{
|
|
||||||
[gl_view setNeedsDisplay];
|
|
||||||
[gl_view bindDrawable];
|
|
||||||
frame_skips = is_syncing ? 0 : 3;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ios_set_game_view_sync(bool on)
|
void ios_set_game_view_sync(bool on)
|
||||||
{
|
{
|
||||||
is_syncing = on;
|
g_is_syncing = on;
|
||||||
frame_skips = on ? 0 : 3;
|
g_frame_skips = on ? 0 : 3;
|
||||||
}
|
}
|
||||||
|
|
||||||
void ios_get_game_view_size(unsigned *width, unsigned *height)
|
void ios_get_game_view_size(unsigned *width, unsigned *height)
|
||||||
{
|
{
|
||||||
if (gameViewer)
|
*width = RAGameView.get.view.bounds.size.width * g_screen_scale;
|
||||||
{
|
*width = *width ? *width : 640;
|
||||||
GLKView* gl_view = (GLKView*)gameViewer.view;
|
|
||||||
|
|
||||||
*width = gl_view.bounds.size.width * screen_scale;
|
*height = RAGameView.get.view.bounds.size.height * g_screen_scale;
|
||||||
*height = gl_view.bounds.size.height * screen_scale;
|
*height = *height ? *height : 480;
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void ios_bind_game_view_fbo()
|
void ios_bind_game_view_fbo()
|
||||||
{
|
{
|
||||||
if (gameViewer)
|
[(GLKView*)RAGameView.get.view bindDrawable];
|
||||||
{
|
|
||||||
GLKView* gl_view = (GLKView*)gameViewer.view;
|
|
||||||
[gl_view bindDrawable];
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
|
@ -15,23 +15,18 @@
|
|||||||
|
|
||||||
#import <UIKit/UIKit.h>
|
#import <UIKit/UIKit.h>
|
||||||
|
|
||||||
@interface RetroArch_iOS : UIResponder <UIApplicationDelegate>
|
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate>
|
||||||
|
|
||||||
+ (void)displayErrorMessage:(NSString*)message;
|
+ (void)displayErrorMessage:(NSString*)message;
|
||||||
|
|
||||||
+ (RetroArch_iOS*)get;
|
+ (RetroArch_iOS*)get;
|
||||||
- (void)runGame:(NSString*)path;
|
- (void)runGame:(NSString*)path;
|
||||||
|
|
||||||
- (void)pushViewController:(UIViewController*)theView isGame:(BOOL)game;
|
|
||||||
- (UIViewController*)popViewController;
|
|
||||||
|
|
||||||
- (IBAction)showSettings;
|
- (IBAction)showSettings;
|
||||||
- (IBAction)showWiiRemoteConfig;
|
- (IBAction)showWiiRemoteConfig;
|
||||||
|
|
||||||
@property (strong, nonatomic) RAModuleInfo* moduleInfo;
|
@property (strong, nonatomic) RAModuleInfo* moduleInfo;
|
||||||
|
|
||||||
@property (strong, nonatomic) NSString* system_directory;
|
@property (strong, nonatomic) NSString* system_directory;
|
||||||
@property (strong, nonatomic) UIImage* file_icon;
|
|
||||||
@property (strong, nonatomic) UIImage* folder_icon;
|
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -23,75 +23,14 @@
|
|||||||
#import "input/BTStack/WiiMoteHelper.h"
|
#import "input/BTStack/WiiMoteHelper.h"
|
||||||
#endif
|
#endif
|
||||||
|
|
||||||
|
|
||||||
#define ALMOST_INVISIBLE .021f
|
|
||||||
|
|
||||||
@interface RANavigator : UINavigationController<UINavigationControllerDelegate>
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation RANavigator
|
|
||||||
{
|
|
||||||
RetroArch_iOS* _delegate;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (id)initWithAppDelegate:(RetroArch_iOS*)delegate
|
|
||||||
{
|
|
||||||
self = [super init];
|
|
||||||
self.delegate = self;
|
|
||||||
|
|
||||||
assert(delegate);
|
|
||||||
_delegate = delegate;
|
|
||||||
|
|
||||||
return self;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIViewController *)popViewControllerAnimated:(BOOL)animated
|
|
||||||
{
|
|
||||||
return [_delegate popViewController];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIViewController*)reallyPopViewControllerAnimated:(BOOL)animated
|
|
||||||
{
|
|
||||||
return [super popViewControllerAnimated:animated];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)willRotateToInterfaceOrientation:(UIInterfaceOrientation)toInterfaceOrientation duration:(NSTimeInterval)duration
|
|
||||||
{
|
|
||||||
[_delegate performSelector:@selector(screenDidRotate) withObject:nil afterDelay:.01f];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
|
||||||
{
|
|
||||||
#ifdef WIIMOTE
|
|
||||||
navigationController.topViewController.navigationItem.rightBarButtonItem = (![WiiMoteHelper isBluetoothRunning]) ? nil :
|
|
||||||
[[UIBarButtonItem alloc]
|
|
||||||
initWithTitle:@"Stop Bluetooth"
|
|
||||||
style:UIBarButtonItemStyleBordered
|
|
||||||
target:[RetroArch_iOS get]
|
|
||||||
action:@selector(stopBluetooth)];
|
|
||||||
#endif
|
|
||||||
}
|
|
||||||
|
|
||||||
@end
|
|
||||||
|
|
||||||
@implementation RetroArch_iOS
|
@implementation RetroArch_iOS
|
||||||
{
|
{
|
||||||
UIWindow* _window;
|
UIWindow* _window;
|
||||||
RANavigator* _navigator;
|
|
||||||
NSTimer* _gameTimer;
|
NSTimer* _gameTimer;
|
||||||
|
|
||||||
UIView* _pauseView;
|
|
||||||
UIView* _pauseIndicatorView;
|
|
||||||
RAGameView* _game;
|
|
||||||
|
|
||||||
|
bool _isGameTop;
|
||||||
bool _isPaused;
|
bool _isPaused;
|
||||||
bool _isRunning;
|
bool _isRunning;
|
||||||
|
|
||||||
// 0 if no RAGameView is in the navigator
|
|
||||||
// 1 if a RAGameView is the top
|
|
||||||
// 2+ if there are views pushed ontop of the RAGameView
|
|
||||||
unsigned _gameAndAbove;
|
|
||||||
|
|
||||||
}
|
}
|
||||||
|
|
||||||
+ (void)displayErrorMessage:(NSString*)message
|
+ (void)displayErrorMessage:(NSString*)message
|
||||||
@ -109,178 +48,22 @@
|
|||||||
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
|
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UIApplicationDelegate
|
||||||
- (void)applicationDidFinishLaunching:(UIApplication *)application
|
- (void)applicationDidFinishLaunching:(UIApplication *)application
|
||||||
{
|
{
|
||||||
// TODO: Relocate this!
|
// TODO: Relocate this!
|
||||||
self.system_directory = @"/var/mobile/Library/RetroArch/";
|
self.system_directory = @"/var/mobile/Library/RetroArch/";
|
||||||
mkdir([self.system_directory UTF8String], 0755);
|
mkdir([self.system_directory UTF8String], 0755);
|
||||||
|
|
||||||
// Load icons
|
|
||||||
self.file_icon = [UIImage imageNamed:@"ic_file"];
|
|
||||||
self.folder_icon = [UIImage imageNamed:@"ic_dir"];
|
|
||||||
|
|
||||||
// Load pause menu
|
|
||||||
UINib* xib = [UINib nibWithNibName:@"PauseView" bundle:nil];
|
|
||||||
_pauseView = [[xib instantiateWithOwner:self options:nil] lastObject];
|
|
||||||
|
|
||||||
xib = [UINib nibWithNibName:@"PauseIndicatorView" bundle:nil];
|
|
||||||
_pauseIndicatorView = [[xib instantiateWithOwner:self options:nil] lastObject];
|
|
||||||
|
|
||||||
// Show status bar
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:NO withAnimation:UIStatusBarAnimationNone];
|
|
||||||
|
|
||||||
// Setup window
|
// Setup window
|
||||||
_navigator = [[RANavigator alloc] initWithAppDelegate:self];
|
self.delegate = self;
|
||||||
[_navigator pushViewController: [RADirectoryList directoryListOrGridWithPath:nil] animated:YES];
|
[self pushViewController:[RADirectoryList directoryListOrGridWithPath:nil] animated:YES];
|
||||||
|
|
||||||
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||||
_window.rootViewController = _navigator;
|
_window.rootViewController = self;
|
||||||
[_window makeKeyAndVisible];
|
[_window makeKeyAndVisible];
|
||||||
}
|
}
|
||||||
|
|
||||||
#pragma mark VIEW MANAGEMENT
|
|
||||||
- (void)screenDidRotate
|
|
||||||
{
|
|
||||||
UIInterfaceOrientation orientation = _navigator.interfaceOrientation;
|
|
||||||
CGRect screenSize = [[UIScreen mainScreen] bounds];
|
|
||||||
|
|
||||||
const float width = ((int)orientation < 3) ? CGRectGetWidth(screenSize) : CGRectGetHeight(screenSize);
|
|
||||||
const float height = ((int)orientation < 3) ? CGRectGetHeight(screenSize) : CGRectGetWidth(screenSize);
|
|
||||||
|
|
||||||
float tenpctw = width / 10.0f;
|
|
||||||
float tenpcth = height / 10.0f;
|
|
||||||
|
|
||||||
_pauseView.frame = CGRectMake(width / 2.0f - 150.0f, height / 2.0f - 150.0f, 300.0f, 300.0f);
|
|
||||||
_pauseIndicatorView.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth);
|
|
||||||
_pauseIndicatorView.hidden = NO;
|
|
||||||
|
|
||||||
[self performSelector:@selector(hidePauseButton) withObject:self afterDelay:3.0f];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)hidePauseButton
|
|
||||||
{
|
|
||||||
[UIView animateWithDuration:0.2
|
|
||||||
animations:^ { _pauseIndicatorView.alpha = ALMOST_INVISIBLE; }
|
|
||||||
completion:^(BOOL finished) { }
|
|
||||||
];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)pushViewController:(UIViewController*)theView isGame:(BOOL)game
|
|
||||||
{
|
|
||||||
assert(!game || _gameAndAbove == 0);
|
|
||||||
|
|
||||||
_gameAndAbove += (game || _gameAndAbove) ? 1 : 0;
|
|
||||||
|
|
||||||
// Update status and navigation bars
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:game withAnimation:UIStatusBarAnimationNone];
|
|
||||||
_navigator.navigationBarHidden = game;
|
|
||||||
|
|
||||||
//
|
|
||||||
[_navigator pushViewController:theView animated:!(_gameAndAbove == 1 || _gameAndAbove == 2)];
|
|
||||||
|
|
||||||
if (game)
|
|
||||||
{
|
|
||||||
_game = (RAGameView*)theView;
|
|
||||||
|
|
||||||
_pauseIndicatorView.alpha = 1.0f;
|
|
||||||
_pauseIndicatorView.hidden = YES;
|
|
||||||
|
|
||||||
[theView.view addSubview:_pauseView];
|
|
||||||
[theView.view addSubview:_pauseIndicatorView];
|
|
||||||
|
|
||||||
[self startTimer];
|
|
||||||
[self performSelector:@selector(screenDidRotate) withObject:nil afterDelay:.01f];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (UIViewController*)popViewController
|
|
||||||
{
|
|
||||||
const bool poppingFromGame = _gameAndAbove == 1;
|
|
||||||
const bool poppingToGame = _gameAndAbove == 2;
|
|
||||||
|
|
||||||
_gameAndAbove -= (_gameAndAbove) ? 1 : 0;
|
|
||||||
|
|
||||||
if (poppingToGame)
|
|
||||||
[self startTimer];
|
|
||||||
|
|
||||||
// Update status and navigation bar
|
|
||||||
[[UIApplication sharedApplication] setStatusBarHidden:poppingToGame withAnimation:UIStatusBarAnimationNone];
|
|
||||||
_navigator.navigationBarHidden = poppingToGame;
|
|
||||||
|
|
||||||
//
|
|
||||||
if (poppingFromGame)
|
|
||||||
{
|
|
||||||
[_pauseView removeFromSuperview];
|
|
||||||
[_pauseIndicatorView removeFromSuperview];
|
|
||||||
}
|
|
||||||
|
|
||||||
return [_navigator reallyPopViewControllerAnimated:!poppingToGame && !poppingFromGame];
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark EMULATION
|
|
||||||
- (void)runGame:(NSString*)path
|
|
||||||
{
|
|
||||||
[RASettingsList refreshConfigFile];
|
|
||||||
|
|
||||||
const char* const sd = [[RetroArch_iOS get].system_directory UTF8String];
|
|
||||||
const char* const cf =[[RetroArch_iOS get].moduleInfo.configPath UTF8String];
|
|
||||||
const char* const libretro = [[RetroArch_iOS get].moduleInfo.path UTF8String];
|
|
||||||
|
|
||||||
struct rarch_main_wrap main_wrapper = {[path UTF8String], sd, sd, cf, libretro};
|
|
||||||
if (rarch_main_init_wrap(&main_wrapper) == 0)
|
|
||||||
{
|
|
||||||
_isRunning = true;
|
|
||||||
rarch_init_msg_queue();
|
|
||||||
[self startTimer];
|
|
||||||
}
|
|
||||||
else
|
|
||||||
{
|
|
||||||
_isRunning = false;
|
|
||||||
[RetroArch_iOS displayErrorMessage:@"Failed to load game."];
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)closeGame
|
|
||||||
{
|
|
||||||
if (_isRunning)
|
|
||||||
{
|
|
||||||
rarch_main_deinit();
|
|
||||||
rarch_deinit_msg_queue();
|
|
||||||
|
|
||||||
#ifdef PERF_TEST
|
|
||||||
rarch_perf_log();
|
|
||||||
#endif
|
|
||||||
|
|
||||||
rarch_main_clear_state();
|
|
||||||
}
|
|
||||||
|
|
||||||
[self stopTimer];
|
|
||||||
_isRunning = false;
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)iterate
|
|
||||||
{
|
|
||||||
if (_isPaused || !_isRunning || _gameAndAbove != 1)
|
|
||||||
[self stopTimer];
|
|
||||||
else if (_isRunning && !rarch_main_iterate())
|
|
||||||
[self closeGame];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)startTimer
|
|
||||||
{
|
|
||||||
if (!_gameTimer)
|
|
||||||
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:0.001f target:self selector:@selector(iterate) userInfo:nil repeats:YES];
|
|
||||||
}
|
|
||||||
|
|
||||||
- (void)stopTimer
|
|
||||||
{
|
|
||||||
if (_gameTimer)
|
|
||||||
[_gameTimer invalidate];
|
|
||||||
|
|
||||||
_gameTimer = nil;
|
|
||||||
}
|
|
||||||
|
|
||||||
#pragma mark LIFE CYCLE
|
|
||||||
- (void)applicationDidBecomeActive:(UIApplication*)application
|
- (void)applicationDidBecomeActive:(UIApplication*)application
|
||||||
{
|
{
|
||||||
[self startTimer];
|
[self startTimer];
|
||||||
@ -303,19 +86,105 @@
|
|||||||
uninit_drivers();
|
uninit_drivers();
|
||||||
}
|
}
|
||||||
|
|
||||||
|
// UINavigationControllerDelegate
|
||||||
|
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||||
|
{
|
||||||
|
_isGameTop = [viewController isKindOfClass:[RAGameView class]];
|
||||||
|
[[UIApplication sharedApplication] setStatusBarHidden:_isGameTop withAnimation:UIStatusBarAnimationNone];
|
||||||
|
self.navigationBarHidden = _isGameTop;
|
||||||
|
|
||||||
|
if (_isGameTop)
|
||||||
|
[self startTimer];
|
||||||
|
|
||||||
|
#ifdef WIIMOTE
|
||||||
|
navigationController.topViewController.navigationItem.rightBarButtonItem = (![WiiMoteHelper isBluetoothRunning]) ? nil :
|
||||||
|
[[UIBarButtonItem alloc]
|
||||||
|
initWithTitle:@"Stop Bluetooth"
|
||||||
|
style:UIBarButtonItemStyleBordered
|
||||||
|
target:[RetroArch_iOS get]
|
||||||
|
action:@selector(stopBluetooth)];
|
||||||
|
#endif
|
||||||
|
}
|
||||||
|
|
||||||
|
// UINavigationController: Never animate when pushing onto, or popping, an RAGameView
|
||||||
|
- (void)pushViewController:(UIViewController*)theView animated:(BOOL)animated
|
||||||
|
{
|
||||||
|
[super pushViewController:theView animated:animated && !_isGameTop];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (UIViewController*)popViewControllerAnimated:(BOOL)animated
|
||||||
|
{
|
||||||
|
return [super popViewControllerAnimated:animated && !_isGameTop];
|
||||||
|
}
|
||||||
|
|
||||||
|
#pragma mark EMULATION
|
||||||
|
- (void)runGame:(NSString*)path
|
||||||
|
{
|
||||||
|
[RASettingsList refreshConfigFile];
|
||||||
|
|
||||||
|
const char* const sd = [[RetroArch_iOS get].system_directory UTF8String];
|
||||||
|
const char* const cf =[[RetroArch_iOS get].moduleInfo.configPath UTF8String];
|
||||||
|
const char* const libretro = [[RetroArch_iOS get].moduleInfo.path UTF8String];
|
||||||
|
|
||||||
|
struct rarch_main_wrap main_wrapper = {[path UTF8String], sd, sd, cf, libretro};
|
||||||
|
if (rarch_main_init_wrap(&main_wrapper) == 0)
|
||||||
|
{
|
||||||
|
rarch_init_msg_queue();
|
||||||
|
|
||||||
|
[self pushViewController:RAGameView.get animated:NO];
|
||||||
|
_isRunning = true;
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
_isRunning = false;
|
||||||
|
[RetroArch_iOS displayErrorMessage:@"Failed to load game."];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)closeGame
|
||||||
|
{
|
||||||
|
if (_isRunning)
|
||||||
|
{
|
||||||
|
_isRunning = false;
|
||||||
|
|
||||||
|
rarch_main_deinit();
|
||||||
|
rarch_deinit_msg_queue();
|
||||||
|
rarch_main_clear_state();
|
||||||
|
|
||||||
|
[self popToViewController:[RAGameView get] animated:NO];
|
||||||
|
[self popViewControllerAnimated:NO];
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)iterate
|
||||||
|
{
|
||||||
|
if (_isPaused || !_isRunning || !_isGameTop)
|
||||||
|
[self stopTimer];
|
||||||
|
else if (_isRunning && !rarch_main_iterate())
|
||||||
|
[self closeGame];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)startTimer
|
||||||
|
{
|
||||||
|
if (!_gameTimer)
|
||||||
|
_gameTimer = [NSTimer scheduledTimerWithTimeInterval:0.001f target:self selector:@selector(iterate) userInfo:nil repeats:YES];
|
||||||
|
}
|
||||||
|
|
||||||
|
- (void)stopTimer
|
||||||
|
{
|
||||||
|
if (_gameTimer)
|
||||||
|
[_gameTimer invalidate];
|
||||||
|
|
||||||
|
_gameTimer = nil;
|
||||||
|
}
|
||||||
|
|
||||||
#pragma mark PAUSE MENU
|
#pragma mark PAUSE MENU
|
||||||
- (IBAction)showPauseMenu:(id)sender
|
- (IBAction)showPauseMenu:(id)sender
|
||||||
{
|
{
|
||||||
if (_isRunning && !_isPaused && _gameAndAbove == 1)
|
if (_isRunning && !_isPaused && _isGameTop)
|
||||||
{
|
{
|
||||||
_isPaused = true;
|
_isPaused = true;
|
||||||
|
[[RAGameView get] openPauseMenu];
|
||||||
UISegmentedControl* stateSelect = (UISegmentedControl*)[_pauseView viewWithTag:1];
|
|
||||||
stateSelect.selectedSegmentIndex = (g_extern.state_slot < 10) ? g_extern.state_slot : -1;
|
|
||||||
|
|
||||||
[UIView animateWithDuration:0.2
|
|
||||||
animations:^ { _pauseView.alpha = 1.0f; }
|
|
||||||
completion:^(BOOL finished){}];
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -344,15 +213,13 @@
|
|||||||
|
|
||||||
- (IBAction)closePauseMenu:(id)sender
|
- (IBAction)closePauseMenu:(id)sender
|
||||||
{
|
{
|
||||||
|
[[RAGameView get] closePauseMenu];
|
||||||
|
|
||||||
if (_isPaused)
|
if (_isPaused)
|
||||||
[UIView animateWithDuration:0.2
|
{
|
||||||
animations:^ { _pauseView.alpha = 0.0f; }
|
_isPaused = false;
|
||||||
completion:^(BOOL finished)
|
[self startTimer];
|
||||||
{
|
}
|
||||||
_isPaused = false;
|
|
||||||
[self startTimer];
|
|
||||||
}
|
|
||||||
];
|
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)closeGamePressed:(id)sender
|
- (IBAction)closeGamePressed:(id)sender
|
||||||
@ -363,7 +230,7 @@
|
|||||||
|
|
||||||
- (IBAction)showSettings
|
- (IBAction)showSettings
|
||||||
{
|
{
|
||||||
[self pushViewController:[RASettingsList new] isGame:NO];
|
[self pushViewController:[RASettingsList new] animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (IBAction)showWiiRemoteConfig
|
- (IBAction)showWiiRemoteConfig
|
||||||
@ -377,7 +244,7 @@
|
|||||||
{
|
{
|
||||||
#ifdef WIIMOTE
|
#ifdef WIIMOTE
|
||||||
[WiiMoteHelper stopBluetooth];
|
[WiiMoteHelper stopBluetooth];
|
||||||
[_navigator.topViewController.navigationItem setRightBarButtonItem:nil animated:YES];
|
[self.topViewController.navigationItem setRightBarButtonItem:nil animated:YES];
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -58,9 +58,9 @@
|
|||||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||||
|
|
||||||
if(path.isDirectory)
|
if(path.isDirectory)
|
||||||
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
|
||||||
else
|
else
|
||||||
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
|
||||||
@ -74,7 +74,7 @@
|
|||||||
|
|
||||||
if (!cell.backgroundView)
|
if (!cell.backgroundView)
|
||||||
{
|
{
|
||||||
cell.backgroundView = [[UIImageView alloc] initWithImage:[RetroArch_iOS get].folder_icon];
|
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_dir"]];
|
||||||
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
|
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@
|
|||||||
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
|
||||||
|
|
||||||
if(path.isDirectory)
|
if(path.isDirectory)
|
||||||
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
|
||||||
else
|
else
|
||||||
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
||||||
@ -73,7 +73,7 @@
|
|||||||
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"];
|
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"];
|
||||||
cell.textLabel.text = [path.path lastPathComponent];
|
cell.textLabel.text = [path.path lastPathComponent];
|
||||||
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
|
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
|
||||||
cell.imageView.image = (path.isDirectory) ? [RetroArch_iOS get].folder_icon : [RetroArch_iOS get].file_icon;
|
cell.imageView.image = [UIImage imageNamed:(path.isDirectory) ? @"ic_dir" : @"ic_file"];
|
||||||
return cell;
|
return cell;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -107,7 +107,7 @@ static bool btOK;
|
|||||||
[[BTstackManager sharedInstance] addListener:discoveryView];
|
[[BTstackManager sharedInstance] addListener:discoveryView];
|
||||||
}
|
}
|
||||||
|
|
||||||
[[RetroArch_iOS get] pushViewController:discoveryView isGame:NO];
|
[[RetroArch_iOS get] pushViewController:discoveryView animated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
// BTStackManagerListener
|
// BTStackManagerListener
|
||||||
|
@ -57,7 +57,7 @@
|
|||||||
_value.value = (indexPath.section == 1) ? [_value.subValues objectAtIndex:indexPath.row] : @"";
|
_value.value = (indexPath.section == 1) ? [_value.subValues objectAtIndex:indexPath.row] : @"";
|
||||||
|
|
||||||
[_view reloadData];
|
[_view reloadData];
|
||||||
[[RetroArch_iOS get] popViewController];
|
[[RetroArch_iOS get] popViewControllerAnimated:YES];
|
||||||
}
|
}
|
||||||
|
|
||||||
@end
|
@end
|
||||||
|
@ -100,7 +100,7 @@ static RASettingData* custom_action(NSString* action)
|
|||||||
[NSArray arrayWithObjects:@"General",
|
[NSArray arrayWithObjects:@"General",
|
||||||
custom_action(@"Module Info"),
|
custom_action(@"Module Info"),
|
||||||
#ifdef WIIMOTE
|
#ifdef WIIMOTE
|
||||||
custom_action(@"Connect WiiMotes");
|
custom_action(@"Connect WiiMotes"),
|
||||||
#endif
|
#endif
|
||||||
nil],
|
nil],
|
||||||
|
|
||||||
@ -157,7 +157,6 @@ static RASettingData* custom_action(NSString* action)
|
|||||||
nil]),
|
nil]),
|
||||||
nil],
|
nil],
|
||||||
|
|
||||||
|
|
||||||
[NSArray arrayWithObjects:@"Save States",
|
[NSArray arrayWithObjects:@"Save States",
|
||||||
boolean_setting(config, @"rewind_enable", @"Enable Rewinding", @"false"),
|
boolean_setting(config, @"rewind_enable", @"Enable Rewinding", @"false"),
|
||||||
boolean_setting(config, @"block_sram_overwrite", @"Disable SRAM on Load", @"false"),
|
boolean_setting(config, @"block_sram_overwrite", @"Disable SRAM on Load", @"false"),
|
||||||
@ -179,7 +178,7 @@ static RASettingData* custom_action(NSString* action)
|
|||||||
- (void)handleCustomAction:(NSString*)action
|
- (void)handleCustomAction:(NSString*)action
|
||||||
{
|
{
|
||||||
if ([@"Module Info" isEqualToString:action])
|
if ([@"Module Info" isEqualToString:action])
|
||||||
[[RetroArch_iOS get] pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:[RetroArch_iOS get].moduleInfo] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:[RetroArch_iOS get].moduleInfo] animated:YES];
|
||||||
else if([@"Connect WiiMotes" isEqualToString:action])
|
else if([@"Connect WiiMotes" isEqualToString:action])
|
||||||
[[RetroArch_iOS get] showWiiRemoteConfig];
|
[[RetroArch_iOS get] showWiiRemoteConfig];
|
||||||
}
|
}
|
||||||
|
@ -88,7 +88,7 @@ static const char* const SETTINGID = "SETTING";
|
|||||||
{
|
{
|
||||||
case EnumerationSetting:
|
case EnumerationSetting:
|
||||||
case FileListSetting:
|
case FileListSetting:
|
||||||
[[RetroArch_iOS get] pushViewController:[[RASettingEnumerationList alloc] initWithSetting:setting fromTable:(UITableView*)self.view] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[[RASettingEnumerationList alloc] initWithSetting:setting fromTable:(UITableView*)self.view] animated:YES];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case ButtonSetting:
|
case ButtonSetting:
|
||||||
@ -96,7 +96,7 @@ static const char* const SETTINGID = "SETTING";
|
|||||||
break;
|
break;
|
||||||
|
|
||||||
case GroupSetting:
|
case GroupSetting:
|
||||||
[[RetroArch_iOS get] pushViewController:[[RASettingsSubList alloc] initWithSettings:setting.subValues title:setting.label] isGame:NO];
|
[[RetroArch_iOS get] pushViewController:[[RASettingsSubList alloc] initWithSettings:setting.subValues title:setting.label] animated:YES];
|
||||||
break;
|
break;
|
||||||
|
|
||||||
case CustomAction:
|
case CustomAction:
|
||||||
|
@ -19,6 +19,9 @@
|
|||||||
#import "RAConfig.h"
|
#import "RAConfig.h"
|
||||||
|
|
||||||
@interface RAGameView : UIViewController
|
@interface RAGameView : UIViewController
|
||||||
|
+ (RAGameView*)get;
|
||||||
|
- (void)openPauseMenu;
|
||||||
|
- (void)closePauseMenu;
|
||||||
@end
|
@end
|
||||||
|
|
||||||
@interface RAModuleInfo : NSObject
|
@interface RAModuleInfo : NSObject
|
||||||
|
Loading…
x
Reference in New Issue
Block a user