(iOS) Reduce the amount of object files for Obj-C compiled code

by combining similar files
This commit is contained in:
twinaphex 2013-04-04 07:54:33 +02:00
parent 0d4d3940b8
commit 8ae3fcb6c1
8 changed files with 534 additions and 612 deletions

View File

@ -8,10 +8,8 @@
/* Begin PBXBuildFile section */
9605EA9B170288EA001D47B0 /* RAModuleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9605EA9A170288EA001D47B0 /* RAModuleInfo.m */; };
96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; };
962979F616C43B9500E6DCE0 /* ic_dir.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F416C43B9500E6DCE0 /* ic_dir.png */; };
962979F716C43B9500E6DCE0 /* ic_file.png in Resources */ = {isa = PBXBuildFile; fileRef = 962979F516C43B9500E6DCE0 /* ic_file.png */; };
96297A0C16C5AD8D00E6DCE0 /* RetroArch_iOS.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */; };
96297A0F16C5AEA100E6DCE0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0E16C5AEA100E6DCE0 /* main.m */; };
96297A2716C82FF100E6DCE0 /* overlays in Resources */ = {isa = PBXBuildFile; fileRef = 96297A2616C82FF100E6DCE0 /* overlays */; };
96366C5516C9AC3300D64A22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5416C9AC3300D64A22 /* CoreAudio.framework */; };
@ -22,8 +20,6 @@
963F5AC316CC522F009BBD19 /* RASettingsList.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5ABF16CC522F009BBD19 /* RASettingsList.m */; };
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; };
966B9CAE16E41C07005B61E1 /* browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAA16E41C07005B61E1 /* browser.m */; };
966B9CB016E41C07005B61E1 /* RADirectoryGrid.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */; };
966B9CB216E41C07005B61E1 /* RADirectoryList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAC16E41C07005B61E1 /* RADirectoryList.m */; };
966B9CB416E41C07005B61E1 /* RAModuleList.m in Sources */ = {isa = PBXBuildFile; fileRef = 966B9CAD16E41C07005B61E1 /* RAModuleList.m */; };
966B9CBD16E41E7A005B61E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */; };
966B9CBF16E41E7A005B61E1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB916E41E7A005B61E1 /* Default.png */; };
@ -47,12 +43,10 @@
/* Begin PBXFileReference section */
9605EA99170288EA001D47B0 /* RAModuleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAModuleInfo.h; sourceTree = "<group>"; };
9605EA9A170288EA001D47B0 /* RAModuleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfo.m; sourceTree = "<group>"; };
96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = "<group>"; };
9614C71F16DDC018000B36EF /* RetroArch copy-Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; name = "RetroArch copy-Info.plist"; path = "/Users/jason/Documents/Projects/ios/RetroArch/ios/RetroArch copy-Info.plist"; sourceTree = "<absolute>"; };
962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = "<group>"; };
962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = "<group>"; };
96297A0A16C5AD8D00E6DCE0 /* RetroArch_iOS.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetroArch_iOS.h; sourceTree = "<group>"; };
96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RetroArch_iOS.m; sourceTree = "<group>"; };
96297A0D16C5ADDA00E6DCE0 /* views.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = views.h; sourceTree = "<group>"; };
96297A0E16C5AEA100E6DCE0 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
96297A2616C82FF100E6DCE0 /* overlays */ = {isa = PBXFileReference; lastKnownFileType = folder; name = overlays; path = ../../media/overlays; sourceTree = "<group>"; };
@ -66,8 +60,6 @@
963F5AC516CC523B009BBD19 /* RAGameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAGameView.m; sourceTree = "<group>"; };
966B9CA916E41C07005B61E1 /* browser.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = browser.h; sourceTree = "<group>"; };
966B9CAA16E41C07005B61E1 /* browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = browser.m; sourceTree = "<group>"; };
966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RADirectoryGrid.m; sourceTree = "<group>"; };
966B9CAC16E41C07005B61E1 /* RADirectoryList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RADirectoryList.m; sourceTree = "<group>"; };
966B9CAD16E41C07005B61E1 /* RAModuleList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleList.m; sourceTree = "<group>"; };
966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
966B9CB916E41E7A005B61E1 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
@ -131,8 +123,6 @@
children = (
966B9CA916E41C07005B61E1 /* browser.h */,
966B9CAA16E41C07005B61E1 /* browser.m */,
966B9CAB16E41C07005B61E1 /* RADirectoryGrid.m */,
966B9CAC16E41C07005B61E1 /* RADirectoryList.m */,
966B9CAD16E41C07005B61E1 /* RAModuleList.m */,
);
path = browser;
@ -201,10 +191,8 @@
96F9C28216FFA55F002455B3 /* RALogView.m */,
9605EA9A170288EA001D47B0 /* RAModuleInfo.m */,
9605EA99170288EA001D47B0 /* RAModuleInfo.h */,
96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */,
96C19C2616D455BE00FE8D5A /* rarch_wrapper.h */,
96297A0A16C5AD8D00E6DCE0 /* RetroArch_iOS.h */,
96297A0B16C5AD8D00E6DCE0 /* RetroArch_iOS.m */,
96297A0D16C5ADDA00E6DCE0 /* views.h */,
);
path = RetroArch;
@ -342,17 +330,13 @@
isa = PBXSourcesBuildPhase;
buildActionMask = 2147483647;
files = (
96297A0C16C5AD8D00E6DCE0 /* RetroArch_iOS.m in Sources */,
96297A0F16C5AEA100E6DCE0 /* main.m in Sources */,
963F5AC016CC522F009BBD19 /* RAButtonGetter.m in Sources */,
963F5AC116CC522F009BBD19 /* RASettingEnumerationList.m in Sources */,
963F5AC216CC522F009BBD19 /* RASettingsSubList.m in Sources */,
963F5AC316CC522F009BBD19 /* RASettingsList.m in Sources */,
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */,
96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */,
966B9CAE16E41C07005B61E1 /* browser.m in Sources */,
966B9CB016E41C07005B61E1 /* RADirectoryGrid.m in Sources */,
966B9CB216E41C07005B61E1 /* RADirectoryList.m in Sources */,
966B9CB416E41C07005B61E1 /* RAModuleList.m in Sources */,
D48581DE16F823F9004BEB17 /* griffin.c in Sources */,
96F9C28316FFA55F002455B3 /* RALogView.m in Sources */,

View File

@ -17,6 +17,10 @@
#import "RAModuleInfo.h"
static NSMutableArray* moduleList;
static NSString* const labels[3] = {@"Core Name", @"Developer", @"Name"};
static const char* const keys[3] = {"corename", "manufacturer", "systemname"};
static NSString* const sectionNames[2] = {@"Emulator", @"Hardware"};
static const uint32_t sectionSizes[2] = {1, 2};
@implementation RAModuleInfo
+ (NSArray*)getModules
@ -81,3 +85,56 @@ static NSMutableArray* moduleList;
}
@end
@implementation RAModuleInfoList
{
RAModuleInfo* _data;
}
- (id)initWithModuleInfo:(RAModuleInfo*)info
{
self = [super initWithStyle:UITableViewStyleGrouped];
_data = info;
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
return sizeof(sectionSizes) / sizeof(sectionSizes[0]);
}
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return sectionNames[section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return sectionSizes[section];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"datacell"];
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"datacell"];
uint32_t sectionBase = 0;
for (int i = 0; i != indexPath.section; i ++)
{
sectionBase += sectionSizes[i];
}
cell.textLabel.text = labels[sectionBase + indexPath.row];
char* val = 0;
if (_data.data)
config_get_string(_data.data, keys[sectionBase + indexPath.row], &val);
cell.detailTextLabel.text = val ? [NSString stringWithUTF8String:val] : @"Unspecified";
free(val);
return cell;
}
@end

View File

@ -1,72 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
static NSString* const labels[3] = {@"Core Name", @"Developer", @"Name"};
static const char* const keys[3] = {"corename", "manufacturer", "systemname"};
static NSString* const sectionNames[2] = {@"Emulator", @"Hardware"};
static const uint32_t sectionSizes[2] = {1, 2};
@implementation RAModuleInfoList
{
RAModuleInfo* _data;
}
- (id)initWithModuleInfo:(RAModuleInfo*)info
{
self = [super initWithStyle:UITableViewStyleGrouped];
_data = info;
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
return sizeof(sectionSizes) / sizeof(sectionSizes[0]);
}
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return sectionNames[section];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return sectionSizes[section];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"datacell"];
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"datacell"];
uint32_t sectionBase = 0;
for (int i = 0; i != indexPath.section; i ++)
{
sectionBase += sectionSizes[i];
}
cell.textLabel.text = labels[sectionBase + indexPath.row];
char* val = 0;
if (_data.data)
config_get_string(_data.data, keys[sectionBase + indexPath.row], &val);
cell.detailTextLabel.text = val ? [NSString stringWithUTF8String:val] : @"Unspecified";
free(val);
return cell;
}
@end

View File

@ -1,328 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#include <sys/stat.h>
#include <pthread.h>
#include "rarch_wrapper.h"
#include "general.h"
#include "frontend/menu/rmenu.h"
#import "browser/browser.h"
#import "settings/settings.h"
#include "input/BTStack/btdynamic.h"
#include "input/BTStack/btpad.h"
#define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
// From frontend/frontend_ios.c
extern void* rarch_main_ios(void* args);
extern void ios_frontend_post_event(void (*fn)(void*), void* userdata);
static void event_game_reset(void* userdata)
{
rarch_game_reset();
}
static void event_load_state(void* userdata)
{
rarch_load_state();
}
static void event_save_state(void* userdata)
{
rarch_save_state();
}
static void event_set_state_slot(void* userdata)
{
g_extern.state_slot = (uint32_t)userdata;
}
static void event_quit(void* userdata)
{
g_extern.system.shutdown = true;
}
static void event_reload_config(void* userdata)
{
// Need to clear these otherwise stale versions may be used!
memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay));
memset(g_settings.video.xml_shader_path, 0, sizeof(g_settings.video.xml_shader_path));
uninit_drivers();
config_load();
init_drivers();
}
@implementation RetroArch_iOS
{
UIWindow* _window;
pthread_t _retroThread;
bool _isGameTop;
bool _isPaused;
bool _isRunning;
}
+ (void)displayErrorMessage:(NSString*)message
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:message
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
+ (RetroArch_iOS*)get
{
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
}
// UIApplicationDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
self.system_directory = [NSString stringWithFormat:@"%@/.RetroArch", kDOCSFOLDER];
mkdir([self.system_directory UTF8String], 0755);
// Setup window
self.delegate = self;
[self pushViewController:[RADirectoryList directoryListOrGridWithPath:kDOCSFOLDER] animated:YES];
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.rootViewController = self;
[_window makeKeyAndVisible];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[RAGameView.get resume];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[RAGameView.get suspend];
}
// 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;
self.topViewController.navigationItem.rightBarButtonItem = [self createBluetoothButton];
}
// 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
{
if (_isRunning)
return;
assert(self.moduleInfo);
[RASettingsList refreshConfigFile];
[self pushViewController:RAGameView.get animated:NO];
_isRunning = true;
const char* const sd = [[RetroArch_iOS get].system_directory UTF8String];
const char* const cf = (ra_ios_is_file(self.moduleInfo.configPath)) ? [self.moduleInfo.configPath UTF8String] : 0;
const char* const libretro = [self.moduleInfo.path UTF8String];
struct rarch_main_wrap* load_data = malloc(sizeof(struct rarch_main_wrap));
load_data->libretro_path = strdup(libretro);
load_data->rom_path = strdup([path UTF8String]);
load_data->sram_path = strdup(sd);
load_data->state_path = strdup(sd);
load_data->verbose = false;
load_data->config_path = strdup(cf);
if (pthread_create(&_retroThread, 0, rarch_main_ios, load_data))
{
[self rarchExited:NO];
}
pthread_detach(_retroThread);
// Read load time settings
// TODO: Do this better
config_file_t* conf = config_file_new([self.moduleInfo.configPath UTF8String]);
bool autoStartBluetooth = false;
if (conf && config_get_bool(conf, "ios_auto_bluetooth", &autoStartBluetooth) && autoStartBluetooth)
[self startBluetooth];
config_file_free(conf);
}
- (void)rarchExited:(BOOL)successful
{
if (!successful)
{
[RetroArch_iOS displayErrorMessage:@"Failed to load game."];
}
if (_isRunning)
{
_isRunning = false;
// Stop bluetooth (might be annoying but forgetting could eat battery of device AND wiimote)
[self stopBluetooth];
//
[self popToViewController:[RAGameView get] animated:NO];
[self popViewControllerAnimated:NO];
}
}
- (void)refreshConfig
{
if (_isRunning)
ios_frontend_post_event(&event_reload_config, 0);
else
{
// Need to clear these otherwise stale versions may be used!
memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay));
memset(g_settings.video.xml_shader_path, 0, sizeof(g_settings.video.xml_shader_path));
}
}
#pragma mark PAUSE MENU
- (IBAction)showPauseMenu:(id)sender
{
if (_isRunning && !_isPaused && _isGameTop)
{
_isPaused = true;
[[RAGameView get] openPauseMenu];
}
}
- (IBAction)resetGame:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_game_reset, 0);
[self closePauseMenu:sender];
}
- (IBAction)loadState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_load_state, 0);
[self closePauseMenu:sender];
}
- (IBAction)saveState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_save_state, 0);
[self closePauseMenu:sender];
}
- (IBAction)chooseState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(event_set_state_slot, (void*)((UISegmentedControl*)sender).selectedSegmentIndex);
}
- (IBAction)closePauseMenu:(id)sender
{
[[RAGameView get] closePauseMenu];
_isPaused = false;
}
- (IBAction)closeGamePressed:(id)sender
{
[self closePauseMenu:sender];
ios_frontend_post_event(event_quit, 0);
}
- (IBAction)showSettings
{
[self pushViewController:[RASettingsList new] animated:YES];
}
#pragma mark Bluetooth Helpers
- (UIBarButtonItem*)createBluetoothButton
{
if (btstack_is_loaded())
{
const bool isBTOn = btstack_is_running();
return [[UIBarButtonItem alloc]
initWithTitle:isBTOn ? @"Stop Bluetooth" : @"Start Bluetooth"
style:UIBarButtonItemStyleBordered
target:[RetroArch_iOS get]
action:isBTOn ? @selector(stopBluetooth) : @selector(startBluetooth)];
}
else
return nil;
}
- (IBAction)startBluetooth
{
if (btstack_is_loaded() && !btstack_is_running())
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@"Choose Pad Type"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Wii", @"PS3", nil];
[alert show];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (btstack_is_loaded())
{
btpad_set_pad_type(buttonIndex == alertView.firstOtherButtonIndex);
if (buttonIndex != alertView.cancelButtonIndex)
{
btstack_start();
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
}
}
}
- (IBAction)stopBluetooth
{
if (btstack_is_loaded())
{
btstack_stop();
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
}
}
@end
void ios_rarch_exited(void* result)
{
[[RetroArch_iOS get] rarchExited:result ? NO : YES];
}

View File

@ -1,119 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#import "conf/config_file.h"
#import "browser.h"
@implementation RADirectoryGrid
{
NSString* _path;
NSArray* _list;
}
- (id)initWithPath:(NSString*)path
{
_path = path;
_list = ra_ios_list_directory(_path);
[self setTitle: [_path lastPathComponent]];
unsigned tileWidth = 100;
unsigned tileHeight = 100;
config_file_t* config = config_file_new([[path stringByAppendingPathComponent:@".raconfig"] UTF8String]);
if (config)
{
config_get_uint(config, "cover_width", &tileWidth);
config_get_uint(config, "cover_height", &tileHeight);
config_file_free(config);
}
// Init collection view
UICollectionViewFlowLayout* layout = [UICollectionViewFlowLayout new];
layout.itemSize = CGSizeMake(tileWidth, tileHeight);
self = [super initWithCollectionViewLayout:layout];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"dircell"];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"textcell"];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"imagecell"];
return self;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [_list count];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
if(path.isDirectory)
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
else
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
UICollectionViewCell* cell = nil;
if (path.isDirectory)
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"dircell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_dir"]];
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
}
}
else if (path.coverPath)
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"imagecell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [UIImageView new];
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
}
((UIImageView*)cell.backgroundView).image = [UIImage imageWithContentsOfFile:path.coverPath];
}
else
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"textcell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [UILabel new];
((UILabel*)cell.backgroundView).numberOfLines = 0;
((UILabel*)cell.backgroundView).textAlignment = NSTextAlignmentCenter;
}
((UILabel*)cell.backgroundView).text = [path.path lastPathComponent];
}
return cell;
}
@end

View File

@ -1,77 +0,0 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
#import "browser.h"
@implementation RADirectoryList
{
NSString* _path;
NSArray* _list;
}
+ (id)directoryListOrGridWithPath:(NSString*)path
{
path = ra_ios_check_path(path);
if ([UICollectionViewController instancesRespondToSelector:@selector(initWithCollectionViewLayout:)])
{
NSString* coverDir = [path stringByAppendingPathComponent:@".coverart"];
if (ra_ios_is_directory(coverDir))
return [[RADirectoryGrid alloc] initWithPath:path];
}
return [[RADirectoryList alloc] initWithPath:path];
}
- (id)initWithPath:(NSString*)path
{
self = [super initWithStyle:UITableViewStylePlain];
_path = path;
_list = ra_ios_list_directory(_path);
[self setTitle: [_path lastPathComponent]];
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
if(path.isDirectory)
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
else
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_list count];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"path"];
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"];
cell.textLabel.text = [path.path lastPathComponent];
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
cell.imageView.image = [UIImage imageNamed:(path.isDirectory) ? @"ic_dir" : @"ic_file"];
return cell;
}
@end

View File

@ -16,6 +16,7 @@
#include <dirent.h>
#include <sys/stat.h>
#import "browser.h"
#import "conf/config_file.h"
@implementation RADirectoryItem
+ (RADirectoryItem*)directoryItemFromPath:(const char*)thePath checkForCovers:(BOOL)checkCovers
@ -100,3 +101,166 @@ NSString* ra_ios_check_path(NSString* path)
return [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
}
@implementation RADirectoryList
{
NSString* _path;
NSArray* _list;
}
+ (id)directoryListOrGridWithPath:(NSString*)path
{
path = ra_ios_check_path(path);
if ([UICollectionViewController instancesRespondToSelector:@selector(initWithCollectionViewLayout:)])
{
NSString* coverDir = [path stringByAppendingPathComponent:@".coverart"];
if (ra_ios_is_directory(coverDir))
return [[RADirectoryGrid alloc] initWithPath:path];
}
return [[RADirectoryList alloc] initWithPath:path];
}
- (id)initWithPath:(NSString*)path
{
self = [super initWithStyle:UITableViewStylePlain];
_path = path;
_list = ra_ios_list_directory(_path);
[self setTitle: [_path lastPathComponent]];
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
if(path.isDirectory)
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
else
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
return [_list count];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"path"];
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"path"];
cell.textLabel.text = [path.path lastPathComponent];
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
cell.imageView.image = [UIImage imageNamed:(path.isDirectory) ? @"ic_dir" : @"ic_file"];
return cell;
}
@end
@implementation RADirectoryGrid
{
NSString* _path;
NSArray* _list;
}
- (id)initWithPath:(NSString*)path
{
_path = path;
_list = ra_ios_list_directory(_path);
[self setTitle: [_path lastPathComponent]];
unsigned tileWidth = 100;
unsigned tileHeight = 100;
config_file_t* config = config_file_new([[path stringByAppendingPathComponent:@".raconfig"] UTF8String]);
if (config)
{
config_get_uint(config, "cover_width", &tileWidth);
config_get_uint(config, "cover_height", &tileHeight);
config_file_free(config);
}
// Init collection view
UICollectionViewFlowLayout* layout = [UICollectionViewFlowLayout new];
layout.itemSize = CGSizeMake(tileWidth, tileHeight);
self = [super initWithCollectionViewLayout:layout];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"dircell"];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"textcell"];
[self.collectionView registerClass:[UICollectionViewCell class] forCellWithReuseIdentifier:@"imagecell"];
return self;
}
- (NSInteger)numberOfSectionsInCollectionView:(UICollectionView *)collectionView
{
return 1;
}
- (NSInteger)collectionView:(UICollectionView *)collectionView numberOfItemsInSection:(NSInteger)section
{
return [_list count];
}
- (void)collectionView:(UICollectionView *)collectionView didSelectItemAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
if(path.isDirectory)
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListOrGridWithPath:path.path] animated:YES];
else
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
}
- (UICollectionViewCell *)collectionView:(UICollectionView *)collectionView cellForItemAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = [_list objectAtIndex: indexPath.row];
UICollectionViewCell* cell = nil;
if (path.isDirectory)
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"dircell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [[UIImageView alloc] initWithImage:[UIImage imageNamed:@"ic_dir"]];
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
}
}
else if (path.coverPath)
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"imagecell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [UIImageView new];
((UIImageView*)cell.backgroundView).contentMode = UIViewContentModeScaleAspectFit;
}
((UIImageView*)cell.backgroundView).image = [UIImage imageWithContentsOfFile:path.coverPath];
}
else
{
cell = [self.collectionView dequeueReusableCellWithReuseIdentifier:@"textcell" forIndexPath:indexPath];
if (!cell.backgroundView)
{
cell.backgroundView = [UILabel new];
((UILabel*)cell.backgroundView).numberOfLines = 0;
((UILabel*)cell.backgroundView).textAlignment = NSTextAlignmentCenter;
}
((UILabel*)cell.backgroundView).text = [path.path lastPathComponent];
}
return cell;
}
@end

View File

@ -18,6 +18,19 @@
#include "input/keycode.h"
#include "libretro.h"
#include <sys/stat.h>
#include <pthread.h>
#include "rarch_wrapper.h"
#include "general.h"
#include "frontend/menu/rmenu.h"
#import "browser/browser.h"
#import "settings/settings.h"
#include "input/BTStack/btdynamic.h"
#include "input/BTStack/btpad.h"
#define GSEVENT_TYPE_KEYDOWN 10
#define GSEVENT_TYPE_KEYUP 11
#define GSEVENT_TYPE_MODS 12
@ -144,3 +157,303 @@ int main(int argc, char *argv[])
}
}
#define kDOCSFOLDER [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"]
// From frontend/frontend_ios.c
extern void* rarch_main_ios(void* args);
extern void ios_frontend_post_event(void (*fn)(void*), void* userdata);
static void event_game_reset(void* userdata)
{
rarch_game_reset();
}
static void event_load_state(void* userdata)
{
rarch_load_state();
}
static void event_save_state(void* userdata)
{
rarch_save_state();
}
static void event_set_state_slot(void* userdata)
{
g_extern.state_slot = (uint32_t)userdata;
}
static void event_quit(void* userdata)
{
g_extern.system.shutdown = true;
}
static void event_reload_config(void* userdata)
{
// Need to clear these otherwise stale versions may be used!
memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay));
memset(g_settings.video.xml_shader_path, 0, sizeof(g_settings.video.xml_shader_path));
uninit_drivers();
config_load();
init_drivers();
}
@implementation RetroArch_iOS
{
UIWindow* _window;
pthread_t _retroThread;
bool _isGameTop;
bool _isPaused;
bool _isRunning;
}
+ (void)displayErrorMessage:(NSString*)message
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:message
delegate:nil
cancelButtonTitle:@"OK"
otherButtonTitles:nil];
[alert show];
}
+ (RetroArch_iOS*)get
{
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
}
// UIApplicationDelegate
- (void)applicationDidFinishLaunching:(UIApplication *)application
{
self.system_directory = [NSString stringWithFormat:@"%@/.RetroArch", kDOCSFOLDER];
mkdir([self.system_directory UTF8String], 0755);
// Setup window
self.delegate = self;
[self pushViewController:[RADirectoryList directoryListOrGridWithPath:kDOCSFOLDER] animated:YES];
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
_window.rootViewController = self;
[_window makeKeyAndVisible];
}
- (void)applicationWillEnterForeground:(UIApplication *)application
{
[RAGameView.get resume];
}
- (void)applicationDidEnterBackground:(UIApplication *)application
{
[RAGameView.get suspend];
}
// 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;
self.topViewController.navigationItem.rightBarButtonItem = [self createBluetoothButton];
}
// 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
{
if (_isRunning)
return;
assert(self.moduleInfo);
[RASettingsList refreshConfigFile];
[self pushViewController:RAGameView.get animated:NO];
_isRunning = true;
const char* const sd = [[RetroArch_iOS get].system_directory UTF8String];
const char* const cf = (ra_ios_is_file(self.moduleInfo.configPath)) ? [self.moduleInfo.configPath UTF8String] : 0;
const char* const libretro = [self.moduleInfo.path UTF8String];
struct rarch_main_wrap* load_data = malloc(sizeof(struct rarch_main_wrap));
load_data->libretro_path = strdup(libretro);
load_data->rom_path = strdup([path UTF8String]);
load_data->sram_path = strdup(sd);
load_data->state_path = strdup(sd);
load_data->verbose = false;
load_data->config_path = strdup(cf);
if (pthread_create(&_retroThread, 0, rarch_main_ios, load_data))
{
[self rarchExited:NO];
}
pthread_detach(_retroThread);
// Read load time settings
// TODO: Do this better
config_file_t* conf = config_file_new([self.moduleInfo.configPath UTF8String]);
bool autoStartBluetooth = false;
if (conf && config_get_bool(conf, "ios_auto_bluetooth", &autoStartBluetooth) && autoStartBluetooth)
[self startBluetooth];
config_file_free(conf);
}
- (void)rarchExited:(BOOL)successful
{
if (!successful)
{
[RetroArch_iOS displayErrorMessage:@"Failed to load game."];
}
if (_isRunning)
{
_isRunning = false;
// Stop bluetooth (might be annoying but forgetting could eat battery of device AND wiimote)
[self stopBluetooth];
//
[self popToViewController:[RAGameView get] animated:NO];
[self popViewControllerAnimated:NO];
}
}
- (void)refreshConfig
{
if (_isRunning)
ios_frontend_post_event(&event_reload_config, 0);
else
{
// Need to clear these otherwise stale versions may be used!
memset(g_settings.input.overlay, 0, sizeof(g_settings.input.overlay));
memset(g_settings.video.xml_shader_path, 0, sizeof(g_settings.video.xml_shader_path));
}
}
#pragma mark PAUSE MENU
- (IBAction)showPauseMenu:(id)sender
{
if (_isRunning && !_isPaused && _isGameTop)
{
_isPaused = true;
[[RAGameView get] openPauseMenu];
}
}
- (IBAction)resetGame:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_game_reset, 0);
[self closePauseMenu:sender];
}
- (IBAction)loadState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_load_state, 0);
[self closePauseMenu:sender];
}
- (IBAction)saveState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(&event_save_state, 0);
[self closePauseMenu:sender];
}
- (IBAction)chooseState:(id)sender
{
if (_isRunning)
ios_frontend_post_event(event_set_state_slot, (void*)((UISegmentedControl*)sender).selectedSegmentIndex);
}
- (IBAction)closePauseMenu:(id)sender
{
[[RAGameView get] closePauseMenu];
_isPaused = false;
}
- (IBAction)closeGamePressed:(id)sender
{
[self closePauseMenu:sender];
ios_frontend_post_event(event_quit, 0);
}
- (IBAction)showSettings
{
[self pushViewController:[RASettingsList new] animated:YES];
}
#pragma mark Bluetooth Helpers
- (UIBarButtonItem*)createBluetoothButton
{
if (btstack_is_loaded())
{
const bool isBTOn = btstack_is_running();
return [[UIBarButtonItem alloc]
initWithTitle:isBTOn ? @"Stop Bluetooth" : @"Start Bluetooth"
style:UIBarButtonItemStyleBordered
target:[RetroArch_iOS get]
action:isBTOn ? @selector(stopBluetooth) : @selector(startBluetooth)];
}
else
return nil;
}
- (IBAction)startBluetooth
{
if (btstack_is_loaded() && !btstack_is_running())
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@"Choose Pad Type"
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Wii", @"PS3", nil];
[alert show];
}
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (btstack_is_loaded())
{
btpad_set_pad_type(buttonIndex == alertView.firstOtherButtonIndex);
if (buttonIndex != alertView.cancelButtonIndex)
{
btstack_start();
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
}
}
}
- (IBAction)stopBluetooth
{
if (btstack_is_loaded())
{
btstack_stop();
[self.topViewController.navigationItem setRightBarButtonItem:[self createBluetoothButton] animated:YES];
}
}
@end
void ios_rarch_exited(void* result)
{
[[RetroArch_iOS get] rarchExited:result ? NO : YES];
}