diff --git a/ios/RetroArch.xcodeproj/project.pbxproj b/ios/RetroArch.xcodeproj/project.pbxproj index 600f53180d..c476742ef5 100644 --- a/ios/RetroArch.xcodeproj/project.pbxproj +++ b/ios/RetroArch.xcodeproj/project.pbxproj @@ -7,6 +7,7 @@ objects = { /* Begin PBXBuildFile section */ + 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */ = {isa = PBXBuildFile; fileRef = 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */; }; 962979EF16C3EA3E00E6DCE0 /* ioseagl_ctx.c in Sources */ = {isa = PBXBuildFile; fileRef = 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */; }; 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 */; }; @@ -89,6 +90,7 @@ /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfoList.m; sourceTree = ""; }; 962979EE16C3EA3E00E6DCE0 /* ioseagl_ctx.c */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.c; path = ioseagl_ctx.c; sourceTree = ""; }; 962979F416C43B9500E6DCE0 /* ic_dir.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_dir.png; path = "../android/phoenix/res/drawable-xhdpi/ic_dir.png"; sourceTree = ""; }; 962979F516C43B9500E6DCE0 /* ic_file.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; name = ic_file.png; path = "../android/phoenix/res/drawable-xhdpi/ic_file.png"; sourceTree = ""; }; @@ -365,6 +367,7 @@ 96AFAE3316C1D4EA009DE44C /* RetroArch */ = { isa = PBXGroup; children = ( + 96096DD716D1ABAF00BF4499 /* RAModuleInfoList.m */, 963F5AC416CC523B009BBD19 /* RADirectoryList.m */, 963F5AC516CC523B009BBD19 /* RAGameView.m */, 963F5AC616CC523B009BBD19 /* RAModuleList.m */, @@ -833,6 +836,7 @@ 963F5AC716CC523B009BBD19 /* RADirectoryList.m in Sources */, 963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */, 963F5AC916CC523B009BBD19 /* RAModuleList.m in Sources */, + 96096DD816D1ABAF00BF4499 /* RAModuleInfoList.m in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; diff --git a/ios/RetroArch/RAModuleInfoList.m b/ios/RetroArch/RAModuleInfoList.m new file mode 100644 index 0000000000..5f3d05e52c --- /dev/null +++ b/ios/RetroArch/RAModuleInfoList.m @@ -0,0 +1,88 @@ +// +// module_list.m +// RetroArch +// +// Created by Jason Fetters on 2/8/13. +// Copyright (c) 2013 RetroArch. All rights reserved. +// + + +@implementation RAModuleInfo ++ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(config_file_t*)theData +{ + RAModuleInfo* new = [RAModuleInfo new]; + + new.path = thePath; + new.data = theData; + return new; +} + +- (void)dealloc +{ + if (self.data) + { + config_file_free(self.data); + } +} + +@end + +static NSString* const labels[3] = {@"Emulator Name", @"Manufacturer", @"Name"}; +static const char* const keys[3] = {"emuname", "manufacturer", "systemname"}; + +static const uint32_t sectionSizes[2] = {1, 2}; +static NSString* const sectionNames[2] = {@"Emulator", @"Hardware"}; + +@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* text = 0; + if (config_get_string(_data.data, keys[sectionBase + indexPath.row], &text)) + cell.detailTextLabel.text = [NSString stringWithUTF8String:text]; + else + cell.detailTextLabel.text = @"Unspecified"; + + free(text); + + return cell; +} + +@end diff --git a/ios/RetroArch/RAModuleList.m b/ios/RetroArch/RAModuleList.m index c1e4c07d13..30464a75d0 100644 --- a/ios/RetroArch/RAModuleList.m +++ b/ios/RetroArch/RAModuleList.m @@ -18,7 +18,7 @@ static void display_error_alert(NSString* message) @implementation RAModuleList { - NSArray* _modules; + NSMutableArray* _modules; } - (id)init @@ -28,19 +28,30 @@ static void display_error_alert(NSString* message) // Get the contents of the modules directory of the bundle. NSString* module_dir = [NSString stringWithFormat:@"%@/modules", [[NSBundle mainBundle] bundlePath]]; - _modules = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:module_dir error:nil]; + NSArray* moduleList = [[NSFileManager defaultManager] contentsOfDirectoryAtPath:module_dir error:nil]; - if (_modules != nil) + if (moduleList != nil) { - _modules = [module_dir stringsByAppendingPaths:_modules]; - _modules = [_modules pathsMatchingExtensions:[NSArray arrayWithObject:@"dylib"]]; + moduleList = [module_dir stringsByAppendingPaths:moduleList]; + moduleList = [moduleList pathsMatchingExtensions:[NSArray arrayWithObject:@"dylib"]]; } - if (_modules == nil || [_modules count] == 0) + if (moduleList == nil || [moduleList count] == 0) { display_error_alert(@"No libretro cores were found."); } + // Load the modules with their data + _modules = [NSMutableArray arrayWithCapacity:[moduleList count]]; + + for (int i = 0; i != [moduleList count]; i ++) + { + NSString* modulePath = [moduleList objectAtIndex:i]; + + NSString* baseName = [[modulePath stringByDeletingPathExtension] stringByAppendingPathExtension:@"info"]; + [_modules addObject:[RAModuleInfo moduleWithPath:modulePath data:config_file_new([baseName UTF8String])]]; + } + [self setTitle:@"Choose Emulator"]; self.navigationItem.rightBarButtonItem = [RetroArch_iOS get].settings_button; @@ -49,10 +60,18 @@ static void display_error_alert(NSString* message) - (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath { - [RetroArch_iOS get].module_path = [_modules objectAtIndex:indexPath.row]; + RAModuleInfo* info = (RAModuleInfo*)[_modules objectAtIndex:indexPath.row]; + [RetroArch_iOS get].module_path = info.path; + [[RetroArch_iOS get] pushViewController:[[RADirectoryList alloc] initWithPath:nil]]; } +- (void)tableView:(UITableView *)tableView accessoryButtonTappedForRowWithIndexPath:(NSIndexPath *)indexPath +{ + RAModuleInfo* info = (RAModuleInfo*)[_modules objectAtIndex:indexPath.row]; + [[RetroArch_iOS get] pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:info]]; +} + - (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section { return _modules ? [_modules count] : 0; @@ -63,7 +82,10 @@ static void display_error_alert(NSString* message) UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"module"]; cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"module"]; - cell.textLabel.text = [[[_modules objectAtIndex:indexPath.row] lastPathComponent] stringByDeletingPathExtension]; + RAModuleInfo* info = (RAModuleInfo*)[_modules objectAtIndex:indexPath.row]; + cell.textLabel.text = [[info.path lastPathComponent] stringByDeletingPathExtension]; + cell.accessoryType = (info.data) ? UITableViewCellAccessoryDetailDisclosureButton : UITableViewCellAccessoryNone; + return cell; } diff --git a/ios/RetroArch/views.h b/ios/RetroArch/views.h index cdb31e9ae6..ff8a6c5270 100644 --- a/ios/RetroArch/views.h +++ b/ios/RetroArch/views.h @@ -6,15 +6,24 @@ @interface RAGameView : UIViewController @end -@interface RAModuleList : UITableViewController +@interface RAModuleInfo : NSObject +@property (strong) NSString* path; +@property config_file_t* data; ++ (RAModuleInfo*)moduleWithPath:(NSString*)thePath data:(config_file_t*)theData; +@end + +@interface RAModuleInfoList : UITableViewController +- (id)initWithModuleInfo:(RAModuleInfo*)info; +@end + +@interface RAModuleList : UITableViewController @end @interface RADirectoryList : UITableViewController - (id)initWithPath:(NSString*)path; @end - @interface RASettingsSubList : UITableViewController - (id)initWithSettings:(NSArray*)values title:(NSString*)title; - (void)writeSettings:(NSArray*)settingList toConfig:(config_file_t*)config;