mirror of
https://github.com/libretro/RetroArch.git
synced 2024-12-04 22:46:46 +00:00
747 lines
23 KiB
Objective-C
747 lines
23 KiB
Objective-C
/* RetroArch - A frontend for libretro.
|
|
* Copyright (C) 2013-2014 - Jason Fetters
|
|
* Copyright (C) 2014-2015 - Jay McCarthy
|
|
*
|
|
* 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 <objc/runtime.h>
|
|
#include "../common/RetroArch_Apple.h"
|
|
#include "../../input/input_common.h"
|
|
#include "../../input/input_keymaps.h"
|
|
#include "../../input/drivers/apple_input.h"
|
|
#include <file/file_path.h>
|
|
#include <retro_miscellaneous.h>
|
|
#include "menu.h"
|
|
|
|
#include "../../menu/menu.h"
|
|
#include "../../menu/menu_entries.h"
|
|
#include "../../menu/drivers/shared.h"
|
|
|
|
/*********************************************/
|
|
/* RunActionSheet */
|
|
/* Creates and displays a UIActionSheet with */
|
|
/* buttons pulled from a RetroArch */
|
|
/* string_list structure. */
|
|
/*********************************************/
|
|
static const void* const associated_delegate_key = &associated_delegate_key;
|
|
|
|
typedef void (^RAActionSheetCallback)(UIActionSheet*, NSInteger);
|
|
|
|
@interface RARunActionSheetDelegate : NSObject<UIActionSheetDelegate>
|
|
@property (nonatomic, copy) RAActionSheetCallback callbackBlock;
|
|
@end
|
|
|
|
@implementation RARunActionSheetDelegate
|
|
|
|
- (id)initWithCallbackBlock:(RAActionSheetCallback)callback
|
|
{
|
|
if ((self = [super init]))
|
|
_callbackBlock = callback;
|
|
return self;
|
|
}
|
|
|
|
- (void)actionSheet:(UIActionSheet *)actionSheet willDismissWithButtonIndex:(NSInteger)buttonIndex
|
|
{
|
|
if (self.callbackBlock)
|
|
self.callbackBlock(actionSheet, buttonIndex);
|
|
}
|
|
|
|
@end
|
|
|
|
static void RunActionSheet(const char* title, const struct string_list* items, UIView* parent, RAActionSheetCallback callback)
|
|
{
|
|
size_t i;
|
|
RARunActionSheetDelegate* delegate = [[RARunActionSheetDelegate alloc] initWithCallbackBlock:callback];
|
|
UIActionSheet* actionSheet = [UIActionSheet new];
|
|
|
|
actionSheet.title = BOXSTRING(title);
|
|
actionSheet.delegate = delegate;
|
|
|
|
for (i = 0; i < items->size; i ++)
|
|
[actionSheet addButtonWithTitle:BOXSTRING(items->elems[i].data)];
|
|
|
|
actionSheet.cancelButtonIndex = [actionSheet addButtonWithTitle:BOXSTRING("Cancel")];
|
|
|
|
objc_setAssociatedObject(actionSheet, associated_delegate_key, delegate, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
|
|
|
[actionSheet showInView:parent];
|
|
}
|
|
|
|
|
|
/*********************************************/
|
|
/* RAMenuBase */
|
|
/* A menu class that displays RAMenuItemBase */
|
|
/* objects. */
|
|
/*********************************************/
|
|
@implementation RAMenuBase
|
|
|
|
- (id)initWithStyle:(UITableViewStyle)style
|
|
{
|
|
if ((self = [super initWithStyle:style]))
|
|
_sections = [NSMutableArray array];
|
|
return self;
|
|
}
|
|
|
|
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
|
{
|
|
return self.sections.count;
|
|
}
|
|
|
|
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
|
|
{
|
|
if (self.hidesHeaders)
|
|
return nil;
|
|
return self.sections[section][0];
|
|
}
|
|
|
|
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
|
|
{
|
|
return [self.sections[section] count] - 1;
|
|
}
|
|
|
|
- (id)itemForIndexPath:(NSIndexPath*)indexPath
|
|
{
|
|
return self.sections[indexPath.section][indexPath.row + 1];
|
|
}
|
|
|
|
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
return [[self itemForIndexPath:indexPath] cellForTableView:tableView];
|
|
}
|
|
|
|
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
|
{
|
|
[[self itemForIndexPath:indexPath] wasSelectedOnTableView:tableView ofController:self];
|
|
}
|
|
|
|
- (void)willReloadData
|
|
{
|
|
|
|
}
|
|
|
|
- (void)reloadData
|
|
{
|
|
[self willReloadData];
|
|
[[self tableView] reloadData];
|
|
}
|
|
|
|
@end
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemBasic */
|
|
/* A simple menu item that displays a text */
|
|
/* description and calls a block object when */
|
|
/* selected. */
|
|
/*********************************************/
|
|
@implementation RAMenuItemBasic
|
|
@synthesize description;
|
|
@synthesize userdata;
|
|
@synthesize action;
|
|
@synthesize detail;
|
|
|
|
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action
|
|
{
|
|
return [self itemWithDescription:description action:action detail:Nil];
|
|
}
|
|
|
|
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description action:(void (^)())action detail:(NSString* (^)())detail
|
|
{
|
|
return [self itemWithDescription:description association:nil action:action detail:detail];
|
|
}
|
|
|
|
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description association:(id)userdata action:(void (^)())action detail:(NSString* (^)())detail
|
|
{
|
|
RAMenuItemBasic* item = [RAMenuItemBasic new];
|
|
item.description = description;
|
|
item.userdata = userdata;
|
|
item.action = action;
|
|
item.detail = detail;
|
|
return item;
|
|
}
|
|
|
|
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
|
|
{
|
|
static NSString* const cell_id = @"text";
|
|
|
|
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
|
|
if (!result)
|
|
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
|
|
|
|
result.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
result.textLabel.text = self.description;
|
|
result.detailTextLabel.text = self.detail ? self.detail(self.userdata) : nil;
|
|
return result;
|
|
}
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
|
{
|
|
if (self.action)
|
|
self.action(self.userdata);
|
|
}
|
|
|
|
@end
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemGeneralSetting */
|
|
/* A simple menu item that displays the */
|
|
/* state, and allows editing, of a string or */
|
|
/* numeric setting. */
|
|
/*********************************************/
|
|
@interface RAMenuItemGeneralSetting() <UIAlertViewDelegate>
|
|
@property (nonatomic) RANumberFormatter* formatter;
|
|
@end
|
|
|
|
@implementation RAMenuItemGeneralSetting
|
|
|
|
+ (id)itemForSetting:(rarch_setting_t*)setting action:(void (^)())action
|
|
{
|
|
switch (setting->type) {
|
|
case ST_NONE:
|
|
case ST_ACTION:
|
|
return [RAMenuItemBasic itemWithDescription:BOXSTRING("Shouldn't be called with ST_NONE or ST_ACTION")
|
|
action:^{}];
|
|
case ST_BOOL:
|
|
return [[RAMenuItemBooleanSetting alloc] initWithSetting:setting action:action];
|
|
case ST_INT:
|
|
case ST_UINT:
|
|
case ST_FLOAT:
|
|
break;
|
|
case ST_PATH:
|
|
case ST_DIR:
|
|
return [[RAMenuItemPathSetting alloc] initWithSetting:setting action:action];
|
|
case ST_STRING:
|
|
case ST_HEX:
|
|
break;
|
|
case ST_BIND:
|
|
return [[RAMenuItemBindSetting alloc] initWithSetting:setting action:action];
|
|
case ST_GROUP:
|
|
case ST_SUB_GROUP:
|
|
case ST_END_GROUP:
|
|
case ST_END_SUB_GROUP:
|
|
default:
|
|
return [RAMenuItemBasic itemWithDescription:BOXSTRING("Shouldn't be called with ST_*GROUP")
|
|
action:^{}];
|
|
}
|
|
|
|
if (setting->type == ST_STRING && setting->values)
|
|
return [[RAMenuItemEnumSetting alloc] initWithSetting:setting action:action];
|
|
|
|
RAMenuItemGeneralSetting* item = [[RAMenuItemGeneralSetting alloc] initWithSetting:setting action:action];
|
|
|
|
if (item.setting->type == ST_INT ||
|
|
item.setting->type == ST_UINT ||
|
|
item.setting->type == ST_FLOAT)
|
|
item.formatter = [[RANumberFormatter alloc] initWithSetting:item.setting];
|
|
|
|
return item;
|
|
}
|
|
|
|
- (id)initWithSetting:(rarch_setting_t*)setting action:(void (^)())action
|
|
{
|
|
if ((self = [super init])) {
|
|
_setting = setting;
|
|
_action = action;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
|
|
{
|
|
char buffer[PATH_MAX_LENGTH];
|
|
UITableViewCell* result;
|
|
static NSString* const cell_id = @"string_setting";
|
|
|
|
self.parentTable = tableView;
|
|
|
|
result = [tableView dequeueReusableCellWithIdentifier:cell_id];
|
|
if (!result)
|
|
{
|
|
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
|
|
result.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
}
|
|
|
|
[self attachDefaultingGestureTo:result];
|
|
|
|
result.textLabel.text = BOXSTRING("<Uninitialized>");
|
|
|
|
if (self.setting)
|
|
{
|
|
if (self.setting->short_description)
|
|
result.textLabel.text = BOXSTRING(self.setting->short_description);
|
|
|
|
setting_data_get_string_representation(self.setting, buffer, sizeof(buffer));
|
|
if (buffer[0] == '\0')
|
|
strlcpy(buffer, "<default>", sizeof(buffer));
|
|
|
|
result.detailTextLabel.text = BOXSTRING(buffer);
|
|
|
|
if (self.setting->type == ST_PATH)
|
|
result.detailTextLabel.text = [result.detailTextLabel.text lastPathComponent];
|
|
}
|
|
return result;
|
|
}
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
|
{
|
|
char buffer[PATH_MAX_LENGTH];
|
|
NSString *desc = BOXSTRING("N/A");
|
|
UIAlertView *alertView;
|
|
UITextField *field;
|
|
|
|
if (self.setting && self.setting->short_description)
|
|
desc = BOXSTRING(self.setting->short_description);
|
|
|
|
alertView = [[UIAlertView alloc] initWithTitle:BOXSTRING("Enter new value") message:desc delegate:self cancelButtonTitle:BOXSTRING("Cancel") otherButtonTitles:BOXSTRING("OK"), nil];
|
|
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
|
|
|
|
field = [alertView textFieldAtIndex:0];
|
|
|
|
field.delegate = self.formatter;
|
|
|
|
setting_data_get_string_representation(self.setting, buffer, sizeof(buffer));
|
|
if (buffer[0] == '\0')
|
|
strlcpy(buffer, "N/A", sizeof(buffer));
|
|
|
|
field.placeholder = BOXSTRING(buffer);
|
|
|
|
[alertView show];
|
|
}
|
|
|
|
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
|
|
{
|
|
NSString* text = (NSString*)[alertView textFieldAtIndex:0].text;
|
|
|
|
if (buttonIndex != alertView.firstOtherButtonIndex)
|
|
return;
|
|
if (!text.length)
|
|
return;
|
|
|
|
setting_data_set_with_string_representation(self.setting, [text UTF8String]);
|
|
[self.parentTable reloadData];
|
|
}
|
|
|
|
- (void)attachDefaultingGestureTo:(UIView*)view
|
|
{
|
|
for (UIGestureRecognizer* i in view.gestureRecognizers)
|
|
[view removeGestureRecognizer:i];
|
|
[view addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self
|
|
action:@selector(resetValue:)]];
|
|
}
|
|
|
|
- (void)resetValue:(UIGestureRecognizer*)gesture
|
|
{
|
|
struct string_list* items;
|
|
RAMenuItemGeneralSetting __weak* weakSelf;
|
|
|
|
if (gesture.state != UIGestureRecognizerStateBegan)
|
|
return;
|
|
|
|
weakSelf = self;
|
|
items = (struct string_list*)string_split("OK", "|");
|
|
|
|
RunActionSheet("Really Reset Value?", items, self.parentTable,
|
|
^(UIActionSheet* actionSheet, NSInteger buttonIndex)
|
|
{
|
|
if (buttonIndex != actionSheet.cancelButtonIndex)
|
|
setting_data_reset_setting(self.setting);
|
|
[weakSelf.parentTable reloadData];
|
|
});
|
|
|
|
string_list_free(items);
|
|
}
|
|
|
|
@end
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemBooleanSetting */
|
|
/* A simple menu item that displays the */
|
|
/* state, and allows editing, of a boolean */
|
|
/* setting. */
|
|
/*********************************************/
|
|
@implementation RAMenuItemBooleanSetting
|
|
|
|
- (id)initWithSetting:(rarch_setting_t*)setting action:(void (^)())action
|
|
{
|
|
if ((self = [super init]))
|
|
{
|
|
_setting = setting;
|
|
_action = action;
|
|
}
|
|
return self;
|
|
}
|
|
|
|
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
|
|
{
|
|
static NSString* const cell_id = @"boolean_setting";
|
|
|
|
UITableViewCell* result = (UITableViewCell*)[tableView dequeueReusableCellWithIdentifier:cell_id];
|
|
|
|
if (!result)
|
|
{
|
|
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
|
|
result.selectionStyle = UITableViewCellSelectionStyleNone;
|
|
result.accessoryView = [UISwitch new];
|
|
}
|
|
|
|
result.textLabel.text = BOXSTRING(self.setting->short_description);
|
|
[(id)result.accessoryView removeTarget:nil action:NULL forControlEvents:UIControlEventValueChanged];
|
|
[(id)result.accessoryView addTarget:self action:@selector(handleBooleanSwitch:) forControlEvents:UIControlEventValueChanged];
|
|
|
|
if (self.setting)
|
|
[(id)result.accessoryView setOn:*self.setting->value.boolean];
|
|
return result;
|
|
}
|
|
|
|
- (void)handleBooleanSwitch:(UISwitch*)swt
|
|
{
|
|
if (self.setting)
|
|
*self.setting->value.boolean = swt.on ? true : false;
|
|
if (self.action)
|
|
self.action();
|
|
}
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
|
{
|
|
}
|
|
|
|
@end
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemPathSetting */
|
|
/* A menu item that displays and allows */
|
|
/* browsing for a path setting. */
|
|
/*********************************************/
|
|
@interface RAMenuItemPathSetting() @end
|
|
@implementation RAMenuItemPathSetting
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
|
{
|
|
NSString *path;
|
|
RADirectoryList* list;
|
|
RAMenuItemPathSetting __weak* weakSelf = self;
|
|
|
|
if (self.setting && self.setting->type == ST_ACTION &&
|
|
self.setting->flags & SD_FLAG_BROWSER_ACTION &&
|
|
self.setting->action_toggle &&
|
|
self.setting->change_handler )
|
|
self.setting->action_toggle( self.setting, MENU_ACTION_RIGHT );
|
|
|
|
path = BOXSTRING(self.setting->value.string);
|
|
|
|
if ( self.setting->type == ST_PATH )
|
|
path = [path stringByDeletingLastPathComponent];
|
|
|
|
list = [[RADirectoryList alloc] initWithPath:path extensions:self.setting->values action:
|
|
^(RADirectoryList* list, RADirectoryItem* item)
|
|
{
|
|
const char *newval = "";
|
|
if (item)
|
|
{
|
|
if (list.forDirectory && !item.isDirectory)
|
|
return;
|
|
|
|
newval = [item.path UTF8String];
|
|
}
|
|
else
|
|
{
|
|
if (!list.allowBlank)
|
|
return;
|
|
}
|
|
|
|
setting_data_set_with_string_representation(weakSelf.setting, newval);
|
|
[[list navigationController] popViewControllerAnimated:YES];
|
|
|
|
weakSelf.action();
|
|
|
|
[weakSelf.parentTable reloadData];
|
|
}];
|
|
|
|
list.allowBlank = (self.setting->flags & SD_FLAG_ALLOW_EMPTY);
|
|
list.forDirectory = (self.setting->flags & SD_FLAG_PATH_DIR);
|
|
|
|
[controller.navigationController pushViewController:list animated:YES];
|
|
}
|
|
|
|
@end
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemEnumSetting */
|
|
/* A menu item that displays and allows */
|
|
/* a setting to be set from a list of */
|
|
/* allowed choices. */
|
|
/*********************************************/
|
|
@implementation RAMenuItemEnumSetting
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
|
|
{
|
|
struct string_list* items;
|
|
RAMenuItemEnumSetting __weak* weakSelf = self;
|
|
|
|
items = (struct string_list*)string_split(self.setting->values, "|");
|
|
RunActionSheet(self.setting->short_description, items, self.parentTable,
|
|
^(UIActionSheet* actionSheet, NSInteger buttonIndex)
|
|
{
|
|
if (buttonIndex == actionSheet.cancelButtonIndex)
|
|
return;
|
|
|
|
setting_data_set_with_string_representation(self.setting, [[actionSheet buttonTitleAtIndex:buttonIndex] UTF8String]);
|
|
[weakSelf.parentTable reloadData];
|
|
});
|
|
string_list_free(items);
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
/*********************************************/
|
|
/* RAMenuItemBindSetting */
|
|
/* A menu item that displays and allows */
|
|
/* mapping of a keybinding. */
|
|
/*********************************************/
|
|
@interface RAMenuItemBindSetting() <UIAlertViewDelegate>
|
|
@property (nonatomic) NSTimer* bindTimer;
|
|
@property (nonatomic) UIAlertView* alert;
|
|
@end
|
|
|
|
@implementation RAMenuItemBindSetting
|
|
|
|
- (void)wasSelectedOnTableView:(UITableView *)tableView ofController:(UIViewController *)controller
|
|
{
|
|
self.alert = [[UIAlertView alloc] initWithTitle:BOXSTRING("RetroArch")
|
|
message:BOXSTRING(self.setting->short_description)
|
|
delegate:self
|
|
cancelButtonTitle:BOXSTRING("Cancel")
|
|
otherButtonTitles:BOXSTRING("Clear Keyboard"), BOXSTRING("Clear Joystick"), BOXSTRING("Clear Axis"), nil];
|
|
|
|
[self.alert show];
|
|
|
|
[self.parentTable reloadData];
|
|
|
|
self.bindTimer = [NSTimer scheduledTimerWithTimeInterval:.1f target:self selector:@selector(checkBind:)
|
|
userInfo:nil repeats:YES];
|
|
}
|
|
|
|
- (void)finishWithClickedButton:(bool)clicked
|
|
{
|
|
if (!clicked)
|
|
[self.alert dismissWithClickedButtonIndex:self.alert.cancelButtonIndex animated:YES];
|
|
self.alert = nil;
|
|
|
|
[self.parentTable reloadData];
|
|
|
|
[self.bindTimer invalidate];
|
|
self.bindTimer = nil;
|
|
|
|
apple_input_reset_icade_buttons();
|
|
}
|
|
|
|
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
|
|
{
|
|
if (buttonIndex == alertView.firstOtherButtonIndex)
|
|
BINDFOR(*self.setting).key = RETROK_UNKNOWN;
|
|
else if(buttonIndex == alertView.firstOtherButtonIndex + 1)
|
|
BINDFOR(*self.setting).joykey = NO_BTN;
|
|
else if(buttonIndex == alertView.firstOtherButtonIndex + 2)
|
|
BINDFOR(*self.setting).joyaxis = AXIS_NONE;
|
|
|
|
[self finishWithClickedButton:true];
|
|
}
|
|
|
|
- (void)checkBind:(NSTimer*)send
|
|
{
|
|
int32_t value = 0;
|
|
int32_t idx = 0;
|
|
|
|
if (self.setting->index)
|
|
idx = self.setting->index - 1;
|
|
|
|
if ((value = apple_input_find_any_key()))
|
|
BINDFOR(*self.setting).key = input_keymaps_translate_keysym_to_rk(value);
|
|
else if ((value = apple_input_find_any_button(idx)) >= 0)
|
|
BINDFOR(*self.setting).joykey = value;
|
|
else if ((value = apple_input_find_any_axis(idx)))
|
|
BINDFOR(*self.setting).joyaxis = (value > 0) ? AXIS_POS(value - 1) : AXIS_NEG(abs(value) - 1);
|
|
else
|
|
return;
|
|
|
|
[self finishWithClickedButton:false];
|
|
}
|
|
|
|
@end
|
|
|
|
|
|
/*********************************************/
|
|
/* RAMainMenu */
|
|
/* Menu object that is displayed immediately */
|
|
/* after startup. */
|
|
/*********************************************/
|
|
@implementation RAMainMenu
|
|
|
|
- (id)init
|
|
{
|
|
if ((self = [super initWithStyle:UITableViewStylePlain]))
|
|
self.title = BOXSTRING("RetroArch");
|
|
return self;
|
|
}
|
|
|
|
- (void)viewWillAppear:(BOOL)animated
|
|
{
|
|
[self reloadData];
|
|
}
|
|
|
|
- (void)willReloadData
|
|
{
|
|
size_t i, end;
|
|
char title[256], title_msg[256];
|
|
NSMutableArray *everything;
|
|
RAMainMenu* __weak weakSelf;
|
|
const char *core_name = g_extern.menu.info.library_name;
|
|
const char *core_version = g_extern.menu.info.library_version;
|
|
const char *dir = NULL;
|
|
const char *label = NULL;
|
|
unsigned menu_type = 0;
|
|
|
|
menu_list_get_last_stack(driver.menu->menu_list,
|
|
&dir, &label, &menu_type);
|
|
|
|
get_title(label, dir, menu_type, title, sizeof(title));
|
|
|
|
weakSelf = self;
|
|
self.sections = [NSMutableArray array];
|
|
|
|
if (!core_name)
|
|
core_name = g_extern.system.info.library_name;
|
|
if (!core_name)
|
|
core_name = "No Core";
|
|
|
|
if (!core_version)
|
|
core_version = g_extern.system.info.library_version;
|
|
if (!core_version)
|
|
core_version = "";
|
|
|
|
snprintf(title_msg, sizeof(title_msg), "%s - %s %s", PACKAGE_VERSION,
|
|
core_name, core_version);
|
|
self.title = BOXSTRING(title_msg);
|
|
|
|
everything = [NSMutableArray array];
|
|
[everything addObject:BOXSTRING(title)];
|
|
|
|
end = menu_list_get_size(driver.menu->menu_list);
|
|
|
|
for (i = driver.menu->begin; i < end; i++)
|
|
{
|
|
rarch_setting_t *setting;
|
|
char type_str[PATH_MAX_LENGTH], path_buf[PATH_MAX_LENGTH];
|
|
menu_file_list_cbs_t *cbs = NULL;
|
|
const char *path = NULL, *entry_label = NULL;
|
|
unsigned type = 0, w = 0;
|
|
|
|
menu_list_get_at_offset(driver.menu->menu_list->selection_buf, i, &path,
|
|
&entry_label, &type);
|
|
setting =
|
|
(rarch_setting_t*)setting_data_find_setting
|
|
(driver.menu->list_settings,
|
|
driver.menu->menu_list->selection_buf->list[i].label);
|
|
|
|
cbs = (menu_file_list_cbs_t*)menu_list_get_actiondata_at_offset(
|
|
driver.menu->menu_list->selection_buf, i);
|
|
|
|
if (cbs && cbs->action_get_representation) {
|
|
cbs->action_get_representation
|
|
(driver.menu->menu_list->selection_buf,
|
|
&w, type, i, label,
|
|
type_str, sizeof(type_str),
|
|
entry_label, path,
|
|
path_buf, sizeof(path_buf));
|
|
}
|
|
|
|
if (setting && setting->type == ST_ACTION &&
|
|
setting->flags & SD_FLAG_BROWSER_ACTION &&
|
|
setting->action_toggle &&
|
|
setting->change_handler )
|
|
{
|
|
[everything
|
|
addObject:
|
|
[[RAMenuItemPathSetting alloc]
|
|
initWithSetting:setting
|
|
action:^{}]];
|
|
}
|
|
else if (setting && ST_ACTION < setting->type && setting->type < ST_GROUP)
|
|
{
|
|
[everything
|
|
addObject:
|
|
[RAMenuItemGeneralSetting
|
|
itemForSetting:setting
|
|
action:^{
|
|
driver.menu->selection_ptr = i;
|
|
if (cbs && cbs->action_ok)
|
|
cbs->action_ok(path, entry_label, type, i);
|
|
}]];
|
|
}
|
|
else
|
|
{
|
|
[everything
|
|
addObject:
|
|
[RAMenuItemBasic
|
|
itemWithDescription:BOXSTRING(path_buf)
|
|
action:^{
|
|
driver.menu->selection_ptr = i;
|
|
if (cbs && cbs->action_ok)
|
|
cbs->action_ok(path, entry_label, type, i);
|
|
else
|
|
{
|
|
if (cbs && cbs->action_start)
|
|
cbs->action_start(type, entry_label, MENU_ACTION_START);
|
|
if (cbs && cbs->action_toggle)
|
|
cbs->action_toggle(type, entry_label, MENU_ACTION_RIGHT);
|
|
menu_list_push_stack(driver.menu->menu_list, "",
|
|
"info_screen", 0, i);
|
|
}
|
|
|
|
[weakSelf menuRefresh];
|
|
[weakSelf reloadData];
|
|
}]];
|
|
}
|
|
}
|
|
|
|
[self.sections addObject:everything];
|
|
|
|
if (menu_list_get_stack_size(driver.menu->menu_list) > 1)
|
|
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:BOXSTRING("Back") style:UIBarButtonItemStyleBordered target:weakSelf action:@selector(menuBack)];
|
|
else
|
|
self.navigationItem.leftBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:BOXSTRING("Resume") style:UIBarButtonItemStyleBordered target:[RetroArch_iOS get] action:@selector(showGameView)];
|
|
|
|
if ( driver.menu->message_contents[0] != '\0' )
|
|
apple_display_alert(driver.menu->message_contents, NULL);
|
|
}
|
|
|
|
- (void)menuRefresh
|
|
{
|
|
if (!driver.menu->need_refresh)
|
|
return;
|
|
|
|
menu_entries_deferred_push(driver.menu->menu_list->selection_buf,
|
|
driver.menu->menu_list->menu_stack);
|
|
driver.menu->need_refresh = false;
|
|
}
|
|
|
|
- (void)menuBack
|
|
{
|
|
menu_apply_deferred_settings();
|
|
menu_list_pop_stack(driver.menu->menu_list);
|
|
[self menuRefresh];
|
|
[self reloadData];
|
|
}
|
|
|
|
@end
|