(Apple) Big merge - merge ios_ui_refactor by hand - note to meancoot -

don't let a branch get out of date for this long - merging it by
hand was not pretty
This commit is contained in:
twinaphex 2013-11-22 15:30:02 +01:00
parent 0386ae6e1b
commit a96e813fe1
31 changed files with 2374 additions and 2742 deletions

View File

@ -1,553 +0,0 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.CocoaTouch.iPad.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1552</int>
<string key="IBDocument.SystemVersion">12D78</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.37</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="NS.object.0">2083</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBProxyObject</string>
<string>IBUIButton</string>
<string>IBUISegmentedControl</string>
<string>IBUIView</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</array>
<object class="NSMutableDictionary" key="IBDocument.Metadata">
<string key="NS.key.0">PluginDependencyRecalculationVersion</string>
<integer value="1" key="NS.object.0"/>
</object>
<array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
<object class="IBProxyObject" id="372490531">
<string key="IBProxiedObjectIdentifier">IBFilesOwner</string>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
<object class="IBProxyObject" id="975951072">
<string key="IBProxiedObjectIdentifier">IBFirstResponder</string>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
<object class="IBUIView" id="191373211">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="IBUIButton" id="61755535">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{160, 237}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">4</int>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Exit</string>
<object class="NSColor" key="IBUIHighlightedTitleColor" id="428922964">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
</object>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<object class="NSColor" key="IBUINormalTitleShadowColor" id="899103122">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC41AA</bytes>
</object>
<object class="IBUIFontDescription" key="IBUIFontDescription" id="230061939">
<int key="type">2</int>
<double key="pointSize">15</double>
</object>
<object class="NSFont" key="IBUIFont" id="495303882">
<string key="NSName">Helvetica-Bold</string>
<double key="NSSize">15</double>
<int key="NSfFlags">16</int>
</object>
</object>
<object class="IBUIButton" id="38801877">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 20}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="344367644"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Resume Game</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUIButton" id="344367644">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{160, 20}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="1033465661"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Toggle RGUI</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUIButton" id="721040644">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 237}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="61755535"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">1</int>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Reset</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUIButton" id="694263183">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 186}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="58186559"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">3</int>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Save State</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUIButton" id="58186559">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{160, 186}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="721040644"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">2</int>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Load State</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUISegmentedControl" id="562513162">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 135}, {260, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="694263183"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<int key="IBUITag">10</int>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBNumberOfSegments">10</int>
<int key="IBSelectedSegmentIndex">0</int>
<array key="IBSegmentTitles">
<string>0</string>
<string>1</string>
<string>2</string>
<string>3</string>
<string>4</string>
<string>5</string>
<string>6</string>
<string>7</string>
<string>8</string>
<string>9</string>
</array>
<array class="NSMutableArray" key="IBSegmentWidths">
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
<real value="0.0"/>
</array>
<array class="NSMutableArray" key="IBSegmentEnabledStates">
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
<boolean value="YES"/>
</array>
<array class="NSMutableArray" key="IBSegmentContentOffsets">
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
<string>{0, 0}</string>
</array>
<array class="NSMutableArray" key="IBSegmentImages">
<object class="NSNull" id="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
<reference ref="4"/>
</array>
</object>
<object class="IBUIButton" id="1033465661">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{20, 71}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="374409903"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">System Config</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
<object class="IBUIButton" id="374409903">
<reference key="NSNextResponder" ref="191373211"/>
<int key="NSvFlags">292</int>
<string key="NSFrame">{{160, 71}, {120, 44}}</string>
<reference key="NSSuperview" ref="191373211"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="562513162"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="IBUIOpaque">NO</bool>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
<int key="IBUIContentHorizontalAlignment">0</int>
<int key="IBUIContentVerticalAlignment">0</int>
<int key="IBUIButtonType">1</int>
<string key="IBUINormalTitle">Core Config</string>
<reference key="IBUIHighlightedTitleColor" ref="428922964"/>
<object class="NSColor" key="IBUINormalTitleColor">
<int key="NSColorSpace">1</int>
<bytes key="NSRGB">MC4xOTYwNzg0MzQ2IDAuMzA5ODAzOTMyOSAwLjUyMTU2ODY1NgA</bytes>
</object>
<reference key="IBUINormalTitleShadowColor" ref="899103122"/>
<reference key="IBUIFontDescription" ref="230061939"/>
<reference key="IBUIFont" ref="495303882"/>
</object>
</array>
<string key="NSFrame">{{0, 20}, {300, 300}}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="38801877"/>
<object class="NSColor" key="IBUIBackgroundColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MQA</bytes>
<object class="NSColorSpace" key="NSCustomColorSpace">
<int key="NSID">2</int>
</object>
</object>
<bool key="IBUIOpaque">NO</bool>
<float key="IBUIAlpha">0.0</float>
<object class="IBUISimulatedStatusBarMetrics" key="IBUISimulatedStatusBarMetrics">
<int key="IBUIStatusBarStyle">2</int>
</object>
<object class="IBUISimulatedSizeMetrics" key="IBUISimulatedDestinationMetrics">
<string key="IBUISimulatedSizeMetricsClass">IBUISimulatedFreeformSizeMetricsSentinel</string>
<string key="IBUIDisplayName">Freeform</string>
</object>
<string key="targetRuntimeIdentifier">IBIPadFramework</string>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">basicEvent:</string>
<reference key="source" ref="61755535"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">215</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">closePauseMenu:</string>
<reference key="source" ref="38801877"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">25</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">basicEvent:</string>
<reference key="source" ref="721040644"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">214</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">basicEvent:</string>
<reference key="source" ref="694263183"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">212</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">basicEvent:</string>
<reference key="source" ref="58186559"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">213</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">chooseState:</string>
<reference key="source" ref="562513162"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">13</int>
</object>
<int key="connectionID">139</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">showSystemSettings</string>
<reference key="source" ref="1033465661"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">166</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">showSettings</string>
<reference key="source" ref="374409903"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">154</int>
</object>
<object class="IBConnectionRecord">
<object class="IBCocoaTouchEventConnection" key="connection">
<string key="label">showRGUI:</string>
<reference key="source" ref="344367644"/>
<reference key="destination" ref="372490531"/>
<int key="IBEventType">7</int>
</object>
<int key="connectionID">179</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
<object class="IBObjectRecord">
<int key="objectID">0</int>
<array key="object" id="0"/>
<reference key="children" ref="1000"/>
<nil key="parent"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="191373211"/>
<array class="NSMutableArray" key="children">
<reference ref="694263183"/>
<reference ref="38801877"/>
<reference ref="58186559"/>
<reference ref="562513162"/>
<reference ref="61755535"/>
<reference ref="374409903"/>
<reference ref="1033465661"/>
<reference ref="344367644"/>
<reference ref="721040644"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="372490531"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-2</int>
<reference key="object" ref="975951072"/>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">12</int>
<reference key="object" ref="61755535"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">17</int>
<reference key="object" ref="38801877"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">30</int>
<reference key="object" ref="721040644"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">86</int>
<reference key="object" ref="694263183"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">122</int>
<reference key="object" ref="58186559"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">131</int>
<reference key="object" ref="562513162"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">140</int>
<reference key="object" ref="1033465661"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">152</int>
<reference key="object" ref="374409903"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">170</int>
<reference key="object" ref="344367644"/>
<array class="NSMutableArray" key="children"/>
<reference key="parent" ref="191373211"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.CustomClassName">RetroArch_iOS</string>
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="-2.CustomClassName">UIResponder</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="122.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="131.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<integer value="9" key="131.IUISegmentedControlInspectorSelectedSegmentMetadataKey"/>
<string key="140.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="152.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="17.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="170.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="30.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
<string key="86.IBPluginDependency">com.apple.InterfaceBuilder.IBCocoaTouchPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">215</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">RetroArch_iOS</string>
<string key="superclassName">UINavigationController</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/RetroArch_iOS.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBIPadFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<string key="IBCocoaTouchPluginVersion">2083</string>
</data>
</archive>

Binary file not shown.

Before

Width:  |  Height:  |  Size: 2.8 KiB

View File

@ -34,8 +34,8 @@
+ (RetroArch_OSX*)get;
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
- (void)loadingCore:(NSString*)core withFile:(const char*)file;
- (void)unloadingCore:(NSString*)core;
@property (nonatomic) NSString* configDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (nonatomic) NSString* globalConfigFile; // e.g. /var/mobile/Documents/.RetroArch/retroarch.cfg

View File

@ -16,12 +16,16 @@
#include <pthread.h>
#include <string.h>
#include <objc/runtime.h>
#import "RetroArch_Apple.h"
#include "rarch_wrapper.h"
#include "apple/common/apple_input.h"
#include "file.h"
static const void* const associated_core_key = &associated_core_key;
@interface RApplication : NSApplication
@end
@ -45,7 +49,7 @@
bool _loaded;
bool _wantReload;
NSString* _file;
RAModuleInfo* _core;
NSString* _core;
}
+ (RetroArch_OSX*)get
@ -72,15 +76,22 @@
// Create core select list
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
for (RAModuleInfo* i in apple_get_modules())
[cb addItemWithObjectValue:i];
apple_core_info_set_core_path(self.coreDirectory.UTF8String);
apple_core_info_set_config_path(self.configDirectory.UTF8String);
const core_info_list_t* cores = apple_core_info_list_get();
for (int i = 0; cores && i != cores->count; i ++)
{
NSString* desc = @(cores->list[i].display_name);
objc_setAssociatedObject(desc, associated_core_key, apple_get_core_id(&cores->list[i]), OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[cb addItemWithObjectValue:desc];
}
if (cb.numberOfItems)
[cb selectItemAtIndex:0];
else
apple_display_alert(@"No libretro cores were found.\nSelect \"Go->Cores Directory\" from the menu and place libretro dylib files there.", @"RetroArch");
// Run RGUI if needed
if (!_wantReload || apple_argv)
apple_run_core(nil, 0);
@ -173,19 +184,19 @@
return;
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
_core = (RAModuleInfo*)cb.objectValueOfSelectedItem;
_core = objc_getAssociatedObject(cb.objectValueOfSelectedItem, associated_core_key);
[self runCore];
}
#pragma mark RetroArch_Platform
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
- (void)loadingCore:(const NSString*)core withFile:(const char*)file
{
if (file)
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:[NSURL fileURLWithPath:@(file)]];
}
- (void)unloadingCore:(RAModuleInfo*)core
- (void)unloadingCore:(const NSString*)core
{
if (_isTerminating)
[NSApplication.sharedApplication terminate:nil];

View File

@ -21,112 +21,8 @@
#include "driver.h"
#include "input/input_common.h"
struct settings fake_settings;
struct global fake_extern;
static const void* associated_name_tag = (void*)&associated_name_tag;
#define BINDFOR(s) (*(struct retro_keybind*)(&s)->value)
static const char* key_name_for_id(uint32_t hidkey)
{
for (int i = 0; apple_key_name_map[i].hid_id; i ++)
if (apple_key_name_map[i].hid_id == hidkey)
return apple_key_name_map[i].keyname;
return "nul";
}
static uint32_t key_id_for_name(const char* name)
{
for (int i = 0; apple_key_name_map[i].hid_id; i ++)
if (strcmp(name, apple_key_name_map[i].keyname) == 0)
return apple_key_name_map[i].hid_id;
return 0;
}
#define key_name_for_rk(X) key_name_for_id(input_translate_rk_to_keysym(X))
#define key_rk_for_name(X) input_translate_keysym_to_rk(key_id_for_name(X))
static const char* get_input_config_key(const rarch_setting_t* setting, const char* type)
{
static char buffer[32];
if (setting->input_player)
snprintf(buffer, 32, "input_player%d_%s%c%s", setting->input_player, setting->name, type ? '_' : '\0', type);
else
snprintf(buffer, 32, "input_%s%c%s", setting->name, type ? '_' : '\0', type);
return buffer;
}
static const char* get_button_name(const rarch_setting_t* setting)
{
static char buffer[32];
if (BINDFOR(*setting).joykey == NO_BTN)
return "nul";
snprintf(buffer, 32, "%lld", BINDFOR(*setting).joykey);
return buffer;
}
static const char* get_axis_name(const rarch_setting_t* setting)
{
static char buffer[32];
uint32_t joyaxis = BINDFOR(*setting).joyaxis;
if (AXIS_NEG_GET(joyaxis) != AXIS_DIR_NONE)
snprintf(buffer, 8, "-%d", AXIS_NEG_GET(joyaxis));
else if (AXIS_POS_GET(joyaxis) != AXIS_DIR_NONE)
snprintf(buffer, 8, "+%d", AXIS_POS_GET(joyaxis));
else
return "nul";
return buffer;
}
@interface RANumberFormatter : NSNumberFormatter
@end
@implementation RANumberFormatter
- (id)initWithFloatSupport:(bool)allowFloat minimum:(double)min maximum:(double)max
{
self = [super init];
self.allowsFloats = allowFloat;
self.maximumFractionDigits = 10;
if (min || max)
{
self.minimum = [NSNumber numberWithInt:min];
self.maximum = [NSNumber numberWithInt:max];
}
return self;
}
- (BOOL)isPartialStringValid:(NSString*)partialString newEditingString:(NSString**)newString errorDescription:(NSString**)error
{
bool hasDot = false;
if (partialString.length)
for (int i = 0; i != partialString.length; i ++)
{
unichar ch = [partialString characterAtIndex:i];
if (i == 0 && (!self.minimum || self.minimum.intValue < 0) && ch == '-')
continue;
else if (self.allowsFloats && !hasDot && ch == '.')
hasDot = true;
else if (!isdigit(ch))
return NO;
}
return YES;
}
@end
@interface RAInputBinder : NSWindow
@end
@ -163,11 +59,9 @@ static const char* get_axis_name(const rarch_setting_t* setting)
if (!_setting)
return;
if (aSetting->type == ST_INT || aSetting->type == ST_FLOAT)
if (aSetting->type == ST_INT || aSetting->type == ST_UINT || aSetting->type == ST_FLOAT)
{
self.textField.formatter = [[RANumberFormatter alloc] initWithFloatSupport:aSetting->type == ST_FLOAT
minimum:aSetting->min
maximum:aSetting->max];
self.textField.formatter = [[RANumberFormatter alloc] initWithSetting:aSetting];
}
else
self.textField.formatter = nil;
@ -175,11 +69,12 @@ static const char* get_axis_name(const rarch_setting_t* setting)
// Set value
switch (aSetting->type)
{
case ST_INT: self.numericValue = @(*(int*)aSetting->value); break;
case ST_FLOAT: self.numericValue = @(*(float*)aSetting->value); break;
case ST_STRING: self.stringValue = @((const char*)aSetting->value); break;
case ST_PATH: self.stringValue = @((const char*)aSetting->value); break;
case ST_BOOL: self.booleanValue = *(bool*)aSetting->value; break;
case ST_INT: self.numericValue = @(*aSetting->value.integer); break;
case ST_UINT: self.numericValue = @(*aSetting->value.unsigned_integer); break;
case ST_FLOAT: self.numericValue = @(*aSetting->value.fraction); break;
case ST_STRING: self.stringValue = @( aSetting->value.string); break;
case ST_PATH: self.stringValue = @( aSetting->value.string); break;
case ST_BOOL: self.booleanValue = *aSetting->value.boolean; break;
case ST_BIND: [self updateInputString]; break;
default: break;
}
@ -199,9 +94,11 @@ static const char* get_axis_name(const rarch_setting_t* setting)
_numericValue = numericValue;
if (_setting && _setting->type == ST_INT)
*(int*)_setting->value = _numericValue.intValue;
*_setting->value.integer = _numericValue.intValue;
else if (_setting && _setting->type == ST_UINT)
*_setting->value.unsigned_integer = _numericValue.intValue;
else if (_setting && _setting->type == ST_FLOAT)
*(float*)_setting->value = _numericValue.floatValue;
*_setting->value.fraction = _numericValue.floatValue;
}
- (void)setBooleanValue:(bool)booleanValue
@ -209,7 +106,7 @@ static const char* get_axis_name(const rarch_setting_t* setting)
_booleanValue = booleanValue;
if (_setting && _setting->type == ST_BOOL)
*(bool*)_setting->value = _booleanValue;
*_setting->value.boolean= _booleanValue;
}
- (void)setStringValue:(NSString *)stringValue
@ -217,15 +114,14 @@ static const char* get_axis_name(const rarch_setting_t* setting)
_stringValue = stringValue ? stringValue : @"";
if (_setting && (_setting->type == ST_STRING || _setting->type == ST_PATH))
strlcpy(_setting->value, _stringValue.UTF8String, _setting->size);
strlcpy(_setting->value.string, _stringValue.UTF8String, _setting->size);
}
// Input Binding
- (void)updateInputString
{
self.stringValue = [NSString stringWithFormat:@"[KB:%s] [JS:%s] [AX:%s]", key_name_for_rk(BINDFOR(*_setting).key),
get_button_name(_setting),
get_axis_name(_setting)];
char buffer[256];
self.stringValue = @(setting_data_get_string_representation(_setting, buffer, sizeof(buffer)));
}
- (void)dismissBinder
@ -291,8 +187,9 @@ static const char* get_axis_name(const rarch_setting_t* setting)
NSMutableArray* thisSubGroup = nil;
_settings = [NSMutableArray array];
memcpy(&fake_settings, &g_settings, sizeof(struct settings));
memcpy(&fake_extern, &g_extern, sizeof(struct global));
setting_data_load_current();
const rarch_setting_t* setting_data = setting_data_get_list();
for (int i = 0; setting_data[i].type; i ++)
{
@ -334,67 +231,12 @@ static const char* get_axis_name(const rarch_setting_t* setting)
}
}
[self load];
}
- (void)load
{
config_file_t* conf = config_file_new(apple_platform.globalConfigFile.UTF8String);
for (int i = 0; setting_data[i].type; i ++)
{
switch (setting_data[i].type)
{
case ST_BOOL: config_get_bool (conf, setting_data[i].name, (bool*)setting_data[i].value); break;
case ST_INT: config_get_int (conf, setting_data[i].name, (int*)setting_data[i].value); break;
case ST_FLOAT: config_get_float (conf, setting_data[i].name, (float*)setting_data[i].value); break;
case ST_PATH: config_get_array (conf, setting_data[i].name, (char*)setting_data[i].value, setting_data[i].size); break;
case ST_STRING: config_get_array (conf, setting_data[i].name, (char*)setting_data[i].value, setting_data[i].size); break;
case ST_BIND:
{
input_config_parse_key (conf, "input_player1", setting_data[i].name, setting_data[i].value);
input_config_parse_joy_button(conf, "input_player1", setting_data[i].name, setting_data[i].value);
input_config_parse_joy_axis (conf, "input_player1", setting_data[i].name, setting_data[i].value);
break;
}
case ST_HEX: break;
default: break;
}
}
config_file_free(conf);
setting_data_load_config_path(setting_data_get_list(), apple_platform.globalConfigFile.UTF8String);
}
- (void)windowWillClose:(NSNotification *)notification
{
config_file_t* conf = config_file_new(apple_platform.globalConfigFile.UTF8String);
conf = conf ? conf : config_file_new(0);
for (int i = 0; setting_data[i].type; i ++)
{
switch (setting_data[i].type)
{
case ST_BOOL: config_set_bool (conf, setting_data[i].name, * (bool*)setting_data[i].value); break;
case ST_INT: config_set_int (conf, setting_data[i].name, * (int*)setting_data[i].value); break;
case ST_FLOAT: config_set_float (conf, setting_data[i].name, *(float*)setting_data[i].value); break;
case ST_PATH: config_set_string(conf, setting_data[i].name, (char*)setting_data[i].value); break;
case ST_STRING: config_set_string(conf, setting_data[i].name, (char*)setting_data[i].value); break;
case ST_BIND:
{
config_set_string(conf, get_input_config_key(&setting_data[i], 0 ), key_name_for_rk(BINDFOR(setting_data[i]).key));
config_set_string(conf, get_input_config_key(&setting_data[i], "btn" ), get_button_name(&setting_data[i]));
config_set_string(conf, get_input_config_key(&setting_data[i], "axis"), get_axis_name(&setting_data[i]));
break;
}
case ST_HEX: break;
default: break;
}
}
config_file_write(conf, apple_platform.globalConfigFile.UTF8String);
config_file_free(conf);
setting_data_save_config_path(setting_data_get_list(), apple_platform.globalConfigFile.UTF8String);
apple_exit_stasis(true);
@ -457,6 +299,7 @@ static const char* get_axis_name(const rarch_setting_t* setting)
}
else
{
const rarch_setting_t* setting_data = setting_data_get_list();
const rarch_setting_t* setting = &setting_data[[item intValue]];
if ([tableColumn.identifier isEqualToString:@"title"])
@ -466,13 +309,29 @@ static const char* get_axis_name(const rarch_setting_t* setting)
RASettingCell* s = nil;
switch (setting->type)
{
case ST_BOOL: s = [outlineView makeViewWithIdentifier:@"RABooleanSetting" owner:nil]; break;
case ST_INT: s = [outlineView makeViewWithIdentifier:@"RANumericSetting" owner:nil]; break;
case ST_FLOAT: s = [outlineView makeViewWithIdentifier:@"RANumericSetting" owner:nil]; break;
case ST_PATH: s = [outlineView makeViewWithIdentifier:@"RAPathSetting" owner:nil]; break;
case ST_STRING: s = [outlineView makeViewWithIdentifier:@"RAStringSetting" owner:nil]; break;
case ST_BIND: s = [outlineView makeViewWithIdentifier:@"RABindSetting" owner:nil]; break;
default: break;
case ST_BOOL:
s = [outlineView makeViewWithIdentifier:@"RABooleanSetting" owner:nil];
break;
case ST_INT:
s = [outlineView makeViewWithIdentifier:@"RANumericSetting" owner:nil];
break;
case ST_UINT:
s = [outlineView makeViewWithIdentifier:@"RANumericSetting" owner:nil];
break;
case ST_FLOAT:
s = [outlineView makeViewWithIdentifier:@"RANumericSetting" owner:nil];
break;
case ST_PATH:
s = [outlineView makeViewWithIdentifier:@"RAPathSetting" owner:nil];
break;
case ST_STRING:
s = [outlineView makeViewWithIdentifier:@"RAStringSetting" owner:nil];
break;
case ST_BIND:
s = [outlineView makeViewWithIdentifier:@"RABindSetting" owner:nil];
break;
default:
break;
}
s.setting = setting;
return s;

View File

@ -17,7 +17,6 @@
967894941788ECDB00D6CA69 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 967894911788ECDB00D6CA69 /* MainMenu.xib */; };
967894961788ED1100D6CA69 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894951788ED1100D6CA69 /* main.m */; };
9678949D1788F02600D6CA69 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894971788F02600D6CA69 /* RAGameView.m */; };
9678949E1788F02600D6CA69 /* RAModuleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894991788F02600D6CA69 /* RAModuleInfo.m */; };
9678949F1788F02600D6CA69 /* utility.m in Sources */ = {isa = PBXBuildFile; fileRef = 9678949C1788F02600D6CA69 /* utility.m */; };
967894A11788F07D00D6CA69 /* griffin.c in Sources */ = {isa = PBXBuildFile; fileRef = 967894A01788F07D00D6CA69 /* griffin.c */; };
967894A41788F0C200D6CA69 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 967894A21788F0C200D6CA69 /* CoreAudio.framework */; };
@ -45,8 +44,6 @@
967894921788ECDB00D6CA69 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = OSX/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
967894951788ED1100D6CA69 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
967894971788F02600D6CA69 /* RAGameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAGameView.m; sourceTree = "<group>"; };
967894981788F02600D6CA69 /* RAModuleInfo.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RAModuleInfo.h; sourceTree = "<group>"; };
967894991788F02600D6CA69 /* RAModuleInfo.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAModuleInfo.m; sourceTree = "<group>"; };
9678949A1788F02600D6CA69 /* rarch_wrapper.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = rarch_wrapper.h; sourceTree = "<group>"; };
9678949B1788F02600D6CA69 /* RetroArch_Apple.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; path = RetroArch_Apple.h; sourceTree = "<group>"; };
9678949C1788F02600D6CA69 /* utility.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = utility.m; sourceTree = "<group>"; };
@ -119,8 +116,6 @@
9620F662178FD4D3001B3B81 /* settings.m */,
967894A01788F07D00D6CA69 /* griffin.c */,
967894971788F02600D6CA69 /* RAGameView.m */,
967894981788F02600D6CA69 /* RAModuleInfo.h */,
967894991788F02600D6CA69 /* RAModuleInfo.m */,
9678949A1788F02600D6CA69 /* rarch_wrapper.h */,
9678949B1788F02600D6CA69 /* RetroArch_Apple.h */,
9678949C1788F02600D6CA69 /* utility.m */,
@ -219,7 +214,6 @@
files = (
967894961788ED1100D6CA69 /* main.m in Sources */,
9678949D1788F02600D6CA69 /* RAGameView.m in Sources */,
9678949E1788F02600D6CA69 /* RAModuleInfo.m in Sources */,
9678949F1788F02600D6CA69 /* utility.m in Sources */,
967894A11788F07D00D6CA69 /* griffin.c in Sources */,
9620F663178FD4D3001B3B81 /* settings.m in Sources */,

View File

@ -7,7 +7,7 @@
objects = {
/* Begin PBXBuildFile section */
9605EA9B170288EA001D47B0 /* RAModuleInfo.m in Sources */ = {isa = PBXBuildFile; fileRef = 9605EA9A170288EA001D47B0 /* RAModuleInfo.m */; };
509FC979183F9F18007A5A30 /* menu.m in Sources */ = {isa = PBXBuildFile; fileRef = 509FC978183F9F18007A5A30 /* menu.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 */; };
96297A0F16C5AEA100E6DCE0 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 96297A0E16C5AEA100E6DCE0 /* main.m */; };
@ -22,13 +22,9 @@
966B9CC116E41E7A005B61E1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBA16E41E7A005B61E1 /* Default@2x.png */; };
966B9CC316E41E7A005B61E1 /* Icon-72.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBB16E41E7A005B61E1 /* Icon-72.png */; };
966B9CC516E41E7A005B61E1 /* Icon.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBC16E41E7A005B61E1 /* Icon.png */; };
966B9CC916E41EC1005B61E1 /* PauseView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC716E41EC1005B61E1 /* PauseView.xib */; };
966B9CCB16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */; };
9678945B1788EAAE00D6CA69 /* browser.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894571788EAAE00D6CA69 /* browser.m */; };
9678945C1788EAAE00D6CA69 /* RALogView.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894581788EAAE00D6CA69 /* RALogView.m */; };
9678945D1788EAAE00D6CA69 /* settings.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894591788EAAE00D6CA69 /* settings.m */; };
967894631788EBD800D6CA69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 967894611788EBD800D6CA69 /* InfoPlist.strings */; };
967D646F16E45428006BA1F2 /* ic_pause.png in Resources */ = {isa = PBXBuildFile; fileRef = 967D646E16E45428006BA1F2 /* ic_pause.png */; };
967D647516E6EA04006BA1F2 /* modules in Resources */ = {isa = PBXBuildFile; fileRef = 967D647416E6EA04006BA1F2 /* modules */; };
96AFAE2A16C1D4EA009DE44C /* UIKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2916C1D4EA009DE44C /* UIKit.framework */; };
96AFAE2C16C1D4EA009DE44C /* Foundation.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96AFAE2B16C1D4EA009DE44C /* Foundation.framework */; };
@ -39,8 +35,7 @@
/* End PBXBuildFile section */
/* 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>"; };
509FC978183F9F18007A5A30 /* menu.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = menu.m; path = iOS/menu.m; sourceTree = SOURCE_ROOT; };
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>"; };
96297A0E16C5AEA100E6DCE0 /* main.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = main.m; sourceTree = "<group>"; };
@ -56,15 +51,11 @@
966B9CBA16E41E7A005B61E1 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
966B9CBB16E41E7A005B61E1 /* Icon-72.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Icon-72.png"; sourceTree = "<group>"; };
966B9CBC16E41E7A005B61E1 /* Icon.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Icon.png; sourceTree = "<group>"; };
966B9CC716E41EC1005B61E1 /* PauseView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PauseView.xib; sourceTree = "<group>"; };
966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; path = PauseIndicatorView.xib; sourceTree = "<group>"; };
967894571788EAAE00D6CA69 /* browser.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = browser.m; path = iOS/browser.m; sourceTree = SOURCE_ROOT; };
967894581788EAAE00D6CA69 /* RALogView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = RALogView.m; path = iOS/RALogView.m; sourceTree = SOURCE_ROOT; };
967894591788EAAE00D6CA69 /* settings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = settings.m; path = iOS/settings.m; sourceTree = SOURCE_ROOT; };
9678945A1788EAAE00D6CA69 /* views.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = views.h; path = iOS/views.h; sourceTree = SOURCE_ROOT; };
9678945F1788EBD000D6CA69 /* RetroArch-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "RetroArch-Info.plist"; path = "iOS/RetroArch-Info.plist"; sourceTree = SOURCE_ROOT; };
967894621788EBD800D6CA69 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = iOS/en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
967D646E16E45428006BA1F2 /* ic_pause.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = ic_pause.png; sourceTree = "<group>"; };
967D647416E6EA04006BA1F2 /* modules */ = {isa = PBXFileReference; lastKnownFileType = folder; path = modules; sourceTree = SOURCE_ROOT; };
96AFAE2516C1D4EA009DE44C /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; };
96AFAE2916C1D4EA009DE44C /* UIKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = UIKit.framework; path = System/Library/Frameworks/UIKit.framework; sourceTree = SDKROOT; };
@ -108,10 +99,8 @@
966B9CBA16E41E7A005B61E1 /* Default@2x.png */,
962979F416C43B9500E6DCE0 /* ic_dir.png */,
962979F516C43B9500E6DCE0 /* ic_file.png */,
967D646E16E45428006BA1F2 /* ic_pause.png */,
966B9CBB16E41E7A005B61E1 /* Icon-72.png */,
966B9CBC16E41E7A005B61E1 /* Icon.png */,
966B9CC716E41EC1005B61E1 /* PauseView.xib */,
966B9CC816E41EC1005B61E1 /* PauseIndicatorView.xib */,
);
path = Assets;
@ -154,15 +143,12 @@
96AFAE3316C1D4EA009DE44C /* common */ = {
isa = PBXGroup;
children = (
509FC978183F9F18007A5A30 /* menu.m */,
9646869417BBBEAE00C5EA69 /* platform.m */,
967894571788EAAE00D6CA69 /* browser.m */,
967894581788EAAE00D6CA69 /* RALogView.m */,
967894591788EAAE00D6CA69 /* settings.m */,
9678945A1788EAAE00D6CA69 /* views.h */,
96297A0E16C5AEA100E6DCE0 /* main.m */,
963F5AC516CC523B009BBD19 /* RAGameView.m */,
9605EA9A170288EA001D47B0 /* RAModuleInfo.m */,
9605EA99170288EA001D47B0 /* RAModuleInfo.h */,
96C19C2616D455BE00FE8D5A /* rarch_wrapper.h */,
96355CD11788CF190010DBFA /* RetroArch_Apple.h */,
96337E81176AC6E5004685F3 /* utility.m */,
@ -285,9 +271,7 @@
966B9CC116E41E7A005B61E1 /* Default@2x.png in Resources */,
966B9CC316E41E7A005B61E1 /* Icon-72.png in Resources */,
966B9CC516E41E7A005B61E1 /* Icon.png in Resources */,
966B9CC916E41EC1005B61E1 /* PauseView.xib in Resources */,
966B9CCB16E41EC1005B61E1 /* PauseIndicatorView.xib in Resources */,
967D646F16E45428006BA1F2 /* ic_pause.png in Resources */,
967D647516E6EA04006BA1F2 /* modules in Resources */,
967894631788EBD800D6CA69 /* InfoPlist.strings in Resources */,
);
@ -303,11 +287,9 @@
96297A0F16C5AEA100E6DCE0 /* main.m in Sources */,
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */,
D48581DE16F823F9004BEB17 /* griffin.c in Sources */,
9605EA9B170288EA001D47B0 /* RAModuleInfo.m in Sources */,
96337E82176AC6E5004685F3 /* utility.m in Sources */,
509FC979183F9F18007A5A30 /* menu.m in Sources */,
9678945B1788EAAE00D6CA69 /* browser.m in Sources */,
9678945C1788EAAE00D6CA69 /* RALogView.m in Sources */,
9678945D1788EAAE00D6CA69 /* settings.m in Sources */,
9646869517BBBEAE00C5EA69 /* platform.m in Sources */,
);
runOnlyForDeploymentPostprocessing = 0;

View File

@ -16,7 +16,7 @@
#import "RetroArch_Apple.h"
#include "rarch_wrapper.h"
#include "general.h"
#include "../../general.h"
#include "gfx/gfx_common.h"
#include "gfx/gfx_context.h"
@ -60,10 +60,10 @@
#ifdef IOS
#include <GLKit/GLKit.h>
#import "views.h"
static const float ALMOST_INVISIBLE = .021f;
static GLKView* g_view;
static UIView* g_pause_view;
static UIView* g_pause_indicator_view;
static UITextField* g_text_hide;
@ -154,16 +154,12 @@ static bool g_is_syncing = true;
{
self = [super init];
UINib* xib = [UINib nibWithNibName:@"PauseView" bundle:nil];
g_pause_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
xib = [UINib nibWithNibName:@"PauseIndicatorView" bundle:nil];
UINib *xib = [UINib nibWithNibName:@"PauseIndicatorView" bundle:nil];
g_pause_indicator_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
g_view = [GLKView new];
g_view.multipleTouchEnabled = YES;
g_view.enableSetNeedsDisplay = NO;
[g_view addSubview:g_pause_view];
[g_view addSubview:g_pause_indicator_view];
if (is_ios_7())
@ -190,7 +186,6 @@ static bool g_is_syncing = true;
float tenpctw = width / 10.0f;
float tenpcth = height / 10.0f;
g_pause_view.frame = CGRectMake(width / 2.0f - 150.0f, height / 2.0f - 150.0f, 300.0f, 300.0f);
g_pause_indicator_view.frame = CGRectMake(tenpctw * 4.0f, 0.0f, tenpctw * 2.0f, tenpcth);
[g_pause_indicator_view viewWithTag:1].frame = CGRectMake(0, 0, tenpctw * 2.0f, tenpcth);
@ -198,30 +193,6 @@ static bool g_is_syncing = true;
[g_text_hide becomeFirstResponder];
}
- (void)openPauseMenu
{
// Setup save state selector
UISegmentedControl* stateSelect = (UISegmentedControl*)[g_pause_view viewWithTag:10];
stateSelect.selectedSegmentIndex = (g_extern.state_slot < 10) ? g_extern.state_slot : -1;
g_extern.is_paused = true;
//
[UIView animateWithDuration:0.2
animations:^{ g_pause_view.alpha = 1.0f; }
completion:^(BOOL finished) { }];
}
- (void)closePauseMenu
{
[UIView animateWithDuration:0.2
animations:^{ g_pause_view.alpha = 0.0f; }
completion:^(BOOL finished) { }
];
g_extern.is_paused = false;
}
- (void)hidePauseButton
{
[UIView animateWithDuration:0.2
@ -271,7 +242,7 @@ static RAScreen* get_chosen_screen()
#endif
}
bool apple_gfx_ctx_init()
bool apple_gfx_ctx_init(void)
{
dispatch_sync(dispatch_get_main_queue(),
^{
@ -290,7 +261,7 @@ bool apple_gfx_ctx_init()
return true;
}
void apple_gfx_ctx_destroy()
void apple_gfx_ctx_destroy(void)
{
g_initialized = false;

View File

@ -1,45 +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/>.
*/
#ifndef _RA_MODULE_INFO_H
#define _RA_MODULE_INFO_H
#import <Foundation/Foundation.h>
#include "compat/apple_compat.h"
#include "conf/config_file.h"
#include "core_info.h"
extern NSArray* apple_get_modules();
@interface RAModuleInfo : NSObject
@property (nonatomic) NSString* path; // e.g. /path/to/corename_libretro.dylib
@property (nonatomic) NSString* baseName; // e.g. corename_libretro
@property (nonatomic) core_info_t* info;
@property (nonatomic) config_file_t* data;
@property (nonatomic) NSString* description; // Friendly name from config file, else just the filename
@property (nonatomic) NSString* customConfigFile; // Path where custom config file would reside
@property (nonatomic) NSString* configFile; // Path to effective config file
- (bool)supportsFileAtPath:(NSString*)path;
- (void)createCustomConfig;
- (void)deleteCustomConfig;
- (bool)hasCustomConfig;
@end
#endif

View File

@ -1,185 +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 "RetroArch_Apple.h"
#import "RAModuleInfo.h"
#include "file.h"
#include "core_info.h"
static NSMutableArray* moduleList;
static core_info_list_t* coreList;
NSArray* apple_get_modules()
{
if (!moduleList)
{
coreList = core_info_list_new(apple_platform.coreDirectory.UTF8String);
if (!coreList)
return nil;
moduleList = [NSMutableArray arrayWithCapacity:coreList->count];
for (int i = 0; coreList && i < coreList->count; i ++)
{
core_info_t* core = &coreList->list[i];
RAModuleInfo* newInfo = [RAModuleInfo new];
newInfo.path = [NSString stringWithCString:core->path encoding:NSUTF8StringEncoding];
newInfo.baseName = newInfo.path.lastPathComponent.stringByDeletingPathExtension;
newInfo.info = core;
newInfo.data = core->data;
newInfo.description = [NSString stringWithCString:core->display_name encoding:NSUTF8StringEncoding];
newInfo.customConfigFile = [NSString stringWithFormat:@"%@/%@.cfg", apple_platform.configDirectory, newInfo.baseName];
newInfo.configFile = newInfo.hasCustomConfig ? newInfo.customConfigFile : apple_platform.globalConfigFile;
[moduleList addObject:newInfo];
}
[moduleList sortUsingComparator:^(RAModuleInfo* left, RAModuleInfo* right)
{
return [left.description caseInsensitiveCompare:right.description];
}];
}
return moduleList;
}
@implementation RAModuleInfo
- (id)copyWithZone:(NSZone *)zone
{
return self;
}
- (bool)supportsFileAtPath:(NSString*)path
{
return core_info_does_support_file(self.info, path.UTF8String);
}
- (void)createCustomConfig
{
if (!self.hasCustomConfig)
[NSFileManager.defaultManager copyItemAtPath:apple_platform.globalConfigFile toPath:self.customConfigFile error:nil];
}
- (void)deleteCustomConfig
{
if (self.hasCustomConfig)
[NSFileManager.defaultManager removeItemAtPath:self.customConfigFile error:nil];
}
- (bool)hasCustomConfig
{
return path_file_exists(self.customConfigFile.UTF8String);
}
@end
#ifdef IOS
#import "../iOS/views.h"
static const void* const associated_string_key = &associated_string_key;
// Build a string with a second associated string
static NSString* build_string_pair(NSString* stringA, NSString* stringB)
{
NSString* string_pair = [NSString stringWithString:stringA];
objc_setAssociatedObject(string_pair, associated_string_key, stringB, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return string_pair;
}
@implementation RAModuleInfoList
{
RAModuleInfo* _data;
uint32_t _firmwareSectionIndex;
}
- (id)initWithModuleInfo:(RAModuleInfo*)info
{
self = [super initWithStyle:UITableViewStyleGrouped];
_data = info;
[self.sections addObject: [NSArray arrayWithObjects:@"Core",
build_string_pair(@"Core Name", objc_get_value_from_config(_data.data, @"corename", @"Unspecified")),
nil]];
[self.sections addObject: [NSArray arrayWithObjects:@"Hardware/Software",
build_string_pair(@"Developer", objc_get_value_from_config(_data.data, @"manufacturer", @"Unspecified")),
build_string_pair(@"Name", objc_get_value_from_config(_data.data, @"systemname", @"Unspecified")),
nil]];
// Firmware
_firmwareSectionIndex = 1000;
uint32_t firmwareCount = 0;
if (_data.data && config_get_uint(_data.data, "firmware_count", &firmwareCount) && firmwareCount)
{
NSMutableArray* firmwareSection = [NSMutableArray arrayWithObject:@"Firmware"];
for (int i = 0; i < firmwareCount; i ++)
{
NSString* path = objc_get_value_from_config(_data.data, [NSString stringWithFormat:@"firmware%d_path", i], @"Unspecified");
path = [path stringByReplacingOccurrencesOfString:@"%sysdir%" withString:[RetroArch_iOS get].systemDirectory];
[firmwareSection addObject:build_string_pair(objc_get_value_from_config(_data.data, [NSString stringWithFormat:@"firmware%d_desc", i], @"Unspecified"), path)];
}
_firmwareSectionIndex = self.sections.count;
[self.sections addObject:firmwareSection];
}
return self;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
if (indexPath.section == _firmwareSectionIndex)
{
NSString* item = (NSString*)[self itemForIndexPath:indexPath];
apple_display_alert(objc_getAssociatedObject(item, associated_string_key), item);
}
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* const cell_id = @"datacell";
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
cell.selectionStyle = UITableViewCellSelectionStyleNone;
cell.detailTextLabel.adjustsFontSizeToFitWidth = YES;
}
NSString* item = (NSString*)[self itemForIndexPath:indexPath];
NSString* value = (NSString*)objc_getAssociatedObject(item, associated_string_key);
cell.textLabel.text = item;
cell.detailTextLabel.text = value;
if (indexPath.section == _firmwareSectionIndex)
cell.backgroundColor = path_file_exists(value.UTF8String) ? [UIColor blueColor] : [UIColor redColor];
else
cell.backgroundColor = [UIColor whiteColor];
return cell;
}
@end
#endif

View File

@ -19,15 +19,18 @@
#include <Foundation/Foundation.h>
#import <CoreFoundation/CoreFoundation.h>
#import "RAModuleInfo.h"
#include "core_info.h"
#include "core_info_ext.h"
#include "setting_data.h"
#include "apple_export.h"
#define GSEVENT_TYPE_KEYDOWN 10
#define GSEVENT_TYPE_KEYUP 11
@protocol RetroArch_Platform
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
- (void)loadingCore:(NSString*)core withFile:(const char*)file;
- (void)unloadingCore:(NSString*)core;
- (NSString*)configDirectory; // < This returns the directory that contains retroarch.cfg and other custom configs
- (NSString*)globalConfigFile; // < This is the full path to retroarch.cfg
@ -35,6 +38,7 @@
@end
#ifdef IOS
#include <UIKit/UIKit.h>
#import "../iOS/platform.h"
#elif defined(OSX)
#import "../OSX/platform.h"
@ -44,16 +48,26 @@ extern char** apple_argv;
extern bool apple_is_paused;
extern bool apple_is_running;
extern bool apple_use_tv_mode;
extern RAModuleInfo* apple_core;
extern NSString* apple_core;
extern id<RetroArch_Platform> apple_platform;
// main.m
extern void apple_run_core(RAModuleInfo* core, const char* file);
extern void apple_run_core(NSString* core, const char* file);
// utility.m
extern void apple_display_alert(NSString* message, NSString* title);
extern NSString* objc_get_value_from_config(config_file_t* config, NSString* name, NSString* defaultValue);
extern NSString *objc_get_value_from_config(config_file_t* config, NSString* name, NSString* defaultValue);
extern NSString *apple_get_core_id(const core_info_t *core);
extern NSString *apple_get_core_display_name(NSString *core_id);
@interface RANumberFormatter : NSNumberFormatter
#ifdef IOS
<UITextFieldDelegate>
#endif
- (id)initWithSetting:(const rarch_setting_t*)setting;
@end
// frontend/platform/platform_apple.c
extern void apple_frontend_post_event(void (*fn)(void*), void* userdata);

View File

@ -86,12 +86,12 @@ void apple_input_enable_icade(bool on)
icade_buttons = 0;
}
uint32_t apple_input_get_icade_buttons()
uint32_t apple_input_get_icade_buttons(void)
{
return icade_enabled ? icade_buttons : 0;
}
void apple_input_reset_icade_buttons()
void apple_input_reset_icade_buttons(void)
{
icade_buttons = 0;
}
@ -107,8 +107,10 @@ void apple_input_handle_key_event(unsigned keycode, bool down)
}
int32_t apple_input_find_any_key()
int32_t apple_input_find_any_key(void)
{
input_init_keyboard_lut(apple_key_map_hidusage);
for (int i = 0; apple_key_name_map[i].hid_id; i++)
if (g_current_input_data.keys[apple_key_name_map[i].hid_id])
return apple_key_name_map[i].hid_id;

View File

@ -67,11 +67,11 @@ extern apple_input_data_t g_polled_input_data;
// Main thread only
void apple_input_enable_icade(bool on);
uint32_t apple_input_get_icade_buttons();
void apple_input_reset_icade_buttons();
uint32_t apple_input_get_icade_buttons(void);
void apple_input_reset_icade_buttons(void);
void apple_input_handle_key_event(unsigned keycode, bool down);
extern int32_t apple_input_find_any_key();
extern int32_t apple_input_find_any_key(void);
extern int32_t apple_input_find_any_button(uint32_t port);
extern int32_t apple_input_find_any_axis(uint32_t port);

View File

@ -0,0 +1,112 @@
/* 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 "core_info_ext.h"
static core_info_list_t* global_core_list = 0;
static char core_config_path[PATH_MAX];
void apple_core_info_set_core_path(const char* core_path)
{
if (global_core_list)
core_info_list_free(global_core_list);
global_core_list = core_path ? core_info_list_new(core_path) : 0;
if (!global_core_list)
RARCH_WARN("No cores were found at %s", core_path ? core_path : "(null");
}
void apple_core_info_set_config_path(const char* config_path)
{
if (!config_path || strlcpy(core_config_path, config_path, sizeof(core_config_path)) >= PATH_MAX)
*core_config_path = '\0';
}
core_info_list_t* apple_core_info_list_get(void)
{
if (!global_core_list)
RARCH_WARN("apple_core_info_list_get() called before apple_core_info_set_core_path()");
return global_core_list;
}
const core_info_t* apple_core_info_list_get_by_id(const char* core_id)
{
if (core_id)
{
const core_info_list_t* cores = apple_core_info_list_get();
for (int i = 0; i != cores->count; i ++)
if (cores->list[i].path && strcmp(core_id, cores->list[i].path) == 0)
return &cores->list[i];
}
return 0;
}
const char* apple_core_info_get_id(const core_info_t* info, char* buffer, size_t buffer_length)
{
if (!buffer || !buffer_length)
return "";
if (info && info->path && strlcpy(buffer, info->path, buffer_length) < buffer_length)
return buffer;
*buffer = 0;
return buffer;
}
const char* apple_core_info_get_custom_config(const char* core_id, char* buffer, size_t buffer_length)
{
if (!core_id || !buffer || !buffer_length)
return 0;
snprintf(buffer, buffer_length, "%s/%s", core_config_path, path_basename(core_id));
fill_pathname(buffer, buffer, ".cfg", buffer_length);
return buffer;
}
bool apple_core_info_has_custom_config(const char* core_id)
{
if (!core_id)
return false;
char path[PATH_MAX];
apple_core_info_get_custom_config(core_id, path, sizeof(path));
return path_file_exists(path);
}
// ROM HISTORY EXTENSIONS
const char* apple_rom_history_get_path(rom_history_t* history, uint32_t index)
{
const char *path, *core_path, *core_name;
rom_history_get_index(history, index, &path, &core_path, &core_name);
return path ? path : "";
}
const char* apple_rom_history_get_core_path(rom_history_t* history, uint32_t index)
{
const char *path, *core_path, *core_name;
rom_history_get_index(history, index, &path, &core_path, &core_name);
return core_path ? core_path : "";
}
const char* apple_rom_history_get_core_name(rom_history_t* history, uint32_t index)
{
const char *path, *core_path, *core_name;
rom_history_get_index(history, index, &path, &core_path, &core_name);
return core_name ? core_name : "";
}

View File

@ -0,0 +1,38 @@
/* 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/>.
*/
#ifndef __APPLE_RARCH_CORE_INFO_EXT_H__
#define __APPLE_RARCH_CORE_INFO_EXT_H__
#include "core_info.h"
#include "frontend/menu/history.h"
void apple_core_info_set_core_path(const char* core_path);
void apple_core_info_set_config_path(const char* config_path);
core_info_list_t* apple_core_info_list_get(void);
const core_info_t* apple_core_info_list_get_by_id(const char* core_id);
const char* apple_core_info_get_id(const core_info_t* info, char* buffer, size_t buffer_length);
const char* apple_core_info_get_custom_config(const char* core_id, char* buffer, size_t buffer_length);
bool apple_core_info_has_custom_config(const char* core_id);
// ROM HISTORY EXTENSIONS
const char* apple_rom_history_get_path(rom_history_t* history, uint32_t index);
const char* apple_rom_history_get_core_path(rom_history_t* history, uint32_t index);
const char* apple_rom_history_get_core_name(rom_history_t* history, uint32_t index);
#endif

View File

@ -1,5 +1,6 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - Jason Fetters
* Copyright (C) 2011-2013 - Daniel De Matteis
*
* 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-
@ -29,15 +30,18 @@ id<RetroArch_Platform> apple_platform;
#pragma mark EMULATION
static pthread_t apple_retro_thread;
bool apple_is_paused;
bool apple_is_running;
bool apple_use_tv_mode;
RAModuleInfo* apple_core;
NSString* apple_core;
void apple_run_core(RAModuleInfo* core, const char* file)
void apple_run_core(NSString* core, const char* file)
{
if (!apple_is_running)
{
if (file && access([@(file) stringByDeletingLastPathComponent].UTF8String, R_OK | W_OK | X_OK))
apple_display_alert(@"The directory containing the selected file has limited permissions. This may "
"prevent zipped games from loading, and will cause some cores to not function.", 0);
[apple_platform loadingCore:core withFile:file];
apple_core = core;
@ -49,15 +53,17 @@ void apple_run_core(RAModuleInfo* core, const char* file)
if (!apple_argv)
{
NSString* config_to_use = apple_core ? apple_core.configFile : apple_platform.globalConfigFile;
strlcpy(config_path, config_to_use.UTF8String, sizeof(config_path));
if (apple_core_info_has_custom_config(apple_core.UTF8String))
apple_core_info_get_custom_config(apple_core.UTF8String, config_path, sizeof(config_path));
else
strlcpy(config_path, apple_platform.globalConfigFile.UTF8String, sizeof(config_path));
static const char* const argv_game[] = { "retroarch", "-c", config_path, "-L", core_path, file_path, 0 };
static const char* const argv_menu[] = { "retroarch", "-c", config_path, "--menu", 0 };
if (file && core)
{
strlcpy(core_path, apple_core.path.UTF8String, sizeof(core_path));
strlcpy(core_path, apple_core.UTF8String, sizeof(core_path));
strlcpy(file_path, file, sizeof(file_path));
}
@ -83,8 +89,8 @@ void apple_rarch_exited(void* result)
if (result)
apple_display_alert(@"Failed to load game.", 0);
RAModuleInfo* used_core = apple_core;
apple_core = nil;
NSString* used_core = apple_core;
apple_core = 0;
if (apple_is_running)
{

View File

@ -23,21 +23,21 @@
void apple_rarch_exited (void* result);
// These functions must only be called in gfx/context/apple_gl_context.c
bool apple_gfx_ctx_init();
void apple_gfx_ctx_destroy();
bool apple_gfx_ctx_init(void);
void apple_gfx_ctx_destroy(void);
bool apple_gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor);
void apple_gfx_ctx_swap_interval(unsigned interval);
bool apple_gfx_ctx_set_video_mode(unsigned width, unsigned height, bool fullscreen);
void apple_gfx_ctx_get_video_size(unsigned* width, unsigned* height);
void apple_gfx_ctx_update_window_title(void);
bool apple_gfx_ctx_has_focus(void);
void apple_gfx_ctx_swap_buffers();
void apple_gfx_ctx_swap_buffers(void);
gfx_ctx_proc_t apple_gfx_ctx_get_proc_address(const char *symbol_name);
#ifdef IOS
void apple_bind_game_view_fbo(void);
#endif
void ios_add_log_message(const char* format, ...);
#define ios_add_log_message(...) printf(__VA_ARGS__)
#endif

585
apple/common/setting_data.c Normal file
View File

@ -0,0 +1,585 @@
/* 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 "setting_data.h"
#include "config.def.h"
// Input
static const char* get_input_config_prefix(const rarch_setting_t* setting)
{
static char buffer[32];
snprintf(buffer, 32, "input%cplayer%d", setting->index ? '_' : '\0', setting->index);
return buffer;
}
static const char* get_input_config_key(const rarch_setting_t* setting, const char* type)
{
static char buffer[64];
snprintf(buffer, 64, "%s_%s%c%s", get_input_config_prefix(setting), setting->name, type ? '_' : '\0', type);
return buffer;
}
static const char* get_key_name(const rarch_setting_t* setting)
{
if (BINDFOR(*setting).key == RETROK_UNKNOWN)
return "nul";
uint32_t hidkey = input_translate_rk_to_keysym(BINDFOR(*setting).key);
for (int i = 0; apple_key_name_map[i].hid_id; i ++)
if (apple_key_name_map[i].hid_id == hidkey)
return apple_key_name_map[i].keyname;
return "nul";
}
static const char* get_button_name(const rarch_setting_t* setting)
{
static char buffer[32];
if (BINDFOR(*setting).joykey == NO_BTN)
return "nul";
snprintf(buffer, 32, "%lld", BINDFOR(*setting).joykey);
return buffer;
}
static const char* get_axis_name(const rarch_setting_t* setting)
{
static char buffer[32];
uint32_t joyaxis = BINDFOR(*setting).joyaxis;
if (AXIS_NEG_GET(joyaxis) != AXIS_DIR_NONE)
snprintf(buffer, 8, "-%d", AXIS_NEG_GET(joyaxis));
else if (AXIS_POS_GET(joyaxis) != AXIS_DIR_NONE)
snprintf(buffer, 8, "+%d", AXIS_POS_GET(joyaxis));
else
return "nul";
return buffer;
}
//
void setting_data_reset(const rarch_setting_t* settings)
{
for (const rarch_setting_t* i = settings; i->type != ST_NONE; i ++)
{
switch (i->type)
{
case ST_BOOL: *i->value.boolean = i->default_value.boolean; break;
case ST_INT: *i->value.integer = i->default_value.integer; break;
case ST_UINT: *i->value.unsigned_integer = i->default_value.unsigned_integer; break;
case ST_FLOAT: *i->value.fraction = i->default_value.fraction; break;
case ST_BIND: *i->value.keybind = *i->default_value.keybind; break;
default: break;
}
}
}
bool setting_data_load_config_path(const rarch_setting_t* settings, const char* path)
{
config_file_t* config = config_file_new(path);
if (config)
{
setting_data_load_config(settings, config);
config_file_free(config);
}
return config;
}
bool setting_data_load_config(const rarch_setting_t* settings, config_file_t* config)
{
if (!config)
return false;
for (const rarch_setting_t* i = settings; i->type != ST_NONE; i ++)
{
switch (i->type)
{
case ST_BOOL: config_get_bool (config, i->name, i->value.boolean); break;
case ST_INT: config_get_int (config, i->name, i->value.integer); break;
case ST_UINT: config_get_uint (config, i->name, i->value.unsigned_integer); break;
case ST_FLOAT: config_get_float (config, i->name, i->value.fraction); break;
case ST_PATH: config_get_array (config, i->name, i->value.string, i->size); break;
case ST_STRING: config_get_array (config, i->name, i->value.string, i->size); break;
case ST_BIND:
{
const char* prefix = get_input_config_prefix(i);
input_config_parse_key (config, prefix, i->name, i->value.keybind);
input_config_parse_joy_button(config, prefix, i->name, i->value.keybind);
input_config_parse_joy_axis (config, prefix, i->name, i->value.keybind);
break;
}
case ST_HEX: break;
default: break;
}
}
return true;
}
bool setting_data_save_config_path(const rarch_setting_t* settings, const char* path)
{
config_file_t* config = config_file_new(path);
if (!config)
config = config_file_new(0);
setting_data_save_config(settings, config);
bool result = config_file_write(config, path);
config_file_free(config);
return result;
}
bool setting_data_save_config(const rarch_setting_t* settings, config_file_t* config)
{
if (!config)
return false;
for (const rarch_setting_t* i = settings; i->type != ST_NONE; i ++)
{
switch (i->type)
{
case ST_BOOL: config_set_bool (config, i->name, *i->value.boolean); break;
case ST_INT: config_set_int (config, i->name, *i->value.integer); break;
case ST_UINT: config_set_uint64(config, i->name, *i->value.unsigned_integer); break;
case ST_FLOAT: config_set_float (config, i->name, *i->value.fraction); break;
case ST_PATH: config_set_string(config, i->name, i->value.string); break;
case ST_STRING: config_set_string(config, i->name, i->value.string); break;
case ST_BIND:
{
config_set_string(config, get_input_config_key(i, 0 ), get_key_name(i));
config_set_string(config, get_input_config_key(i, "btn" ), get_button_name(i));
config_set_string(config, get_input_config_key(i, "axis"), get_axis_name(i));
break;
}
case ST_HEX: break;
default: break;
}
}
return true;
}
const rarch_setting_t* setting_data_find_setting(const rarch_setting_t* settings, const char* name)
{
if (!name)
return 0;
for (const rarch_setting_t* i = settings; i->type != ST_NONE; i ++)
if (i->type <= ST_GROUP && strcmp(i->name, name) == 0)
return i;
return 0;
}
void setting_data_set_with_string_representation(const rarch_setting_t* setting, const char* value)
{
if (!setting || !value)
return;
switch (setting->type)
{
case ST_INT: sscanf(value, "%d", setting->value.integer); break;
case ST_UINT: sscanf(value, "%u", setting->value.unsigned_integer); break;
case ST_FLOAT: sscanf(value, "%f", setting->value.fraction); break;
case ST_PATH: strlcpy(setting->value.string, value, setting->size); break;
case ST_STRING: strlcpy(setting->value.string, value, setting->size); break;
default: return;
}
}
const char* setting_data_get_string_representation(const rarch_setting_t* setting, char* buffer, size_t length)
{
if (!setting || !buffer || !length)
return "";
switch (setting->type)
{
case ST_BOOL: snprintf(buffer, length, "%s", *setting->value.boolean ? "True" : "False"); break;
case ST_INT: snprintf(buffer, length, "%d", *setting->value.integer); break;
case ST_UINT: snprintf(buffer, length, "%u", *setting->value.unsigned_integer); break;
case ST_FLOAT: snprintf(buffer, length, "%f", *setting->value.fraction); break;
case ST_PATH: strlcpy(buffer, setting->value.string, length); break;
case ST_STRING: strlcpy(buffer, setting->value.string, length); break;
case ST_BIND:
{
snprintf(buffer, length, "[KB:%s] [JS:%s] [AX:%s]", get_key_name(setting), get_button_name(setting), get_axis_name(setting));
break;
}
default: return "";
}
return buffer;
}
rarch_setting_t setting_data_group_setting(enum setting_type type, const char* name)
{
rarch_setting_t result = { type, name };
return result;
}
rarch_setting_t setting_data_bool_setting(const char* name, const char* description, bool* target, bool default_value)
{
rarch_setting_t result = { ST_BOOL, name, sizeof(bool), description };
result.value.boolean = target;
result.default_value.boolean = default_value;
return result;
}
rarch_setting_t setting_data_int_setting(const char* name, const char* description, int* target, int default_value)
{
rarch_setting_t result = { ST_INT, name, sizeof(bool), description };
result.value.integer = target;
result.default_value.integer = default_value;
return result;
}
rarch_setting_t setting_data_uint_setting(const char* name, const char* description, unsigned int* target, unsigned int default_value)
{
rarch_setting_t result = { ST_UINT, name, sizeof(bool), description };
result.value.unsigned_integer = target;
result.default_value.unsigned_integer = default_value;
return result;
}
rarch_setting_t setting_data_float_setting(const char* name, const char* description, float* target, float default_value)
{
rarch_setting_t result = { ST_FLOAT, name, sizeof(bool), description };
result.value.fraction = target;
result.default_value.fraction = default_value;
return result;
}
rarch_setting_t setting_data_path_setting(const char* name, const char* description, char* target, unsigned size, char* default_value)
{
rarch_setting_t result = { ST_PATH, name, size, description };
result.value.string = target;
result.default_value.string = default_value;
return result;
}
rarch_setting_t setting_data_string_setting(const char* name, const char* description, char* target, unsigned size, char* default_value)
{
rarch_setting_t result = { ST_STRING, name, size, description };
result.value.string = target;
result.default_value.string = default_value;
return result;
}
rarch_setting_t setting_data_bind_setting(const char* name, const char* description, struct retro_keybind* target, uint32_t index,
const struct retro_keybind* default_value)
{
rarch_setting_t result = { ST_BIND, name, 0, description };
result.value.keybind = target;
result.default_value.keybind = default_value;
result.index = index;
return result;
}
// HACK
struct settings fake_settings;
struct global fake_extern;
void setting_data_load_current()
{
memcpy(&fake_settings, &g_settings, sizeof(struct settings));
memcpy(&fake_extern, &g_extern, sizeof(struct global));
}
#define g_settings fake_settings
#define g_extern fake_extern
#define DEFAULT_ME_YO 0
#define NEXT (list[index++])
#define START_GROUP(NAME) NEXT = setting_data_group_setting (ST_GROUP, NAME);
#define END_GROUP() NEXT = setting_data_group_setting (ST_END_GROUP, 0);
#define START_SUB_GROUP(NAME) NEXT = setting_data_group_setting (ST_SUB_GROUP, NAME);
#define END_SUB_GROUP() NEXT = setting_data_group_setting (ST_END_SUB_GROUP, 0);
#define CONFIG_BOOL(TARGET, NAME, SHORT, DEF) NEXT = setting_data_bool_setting (NAME, SHORT, &TARGET, DEF);
#define CONFIG_INT(TARGET, NAME, SHORT, DEF) NEXT = setting_data_int_setting (NAME, SHORT, &TARGET, DEF);
#define CONFIG_UINT(TARGET, NAME, SHORT, DEF) NEXT = setting_data_uint_setting (NAME, SHORT, &TARGET, DEF);
#define CONFIG_FLOAT(TARGET, NAME, SHORT, DEF) NEXT = setting_data_float_setting (NAME, SHORT, &TARGET, DEF);
#define CONFIG_PATH(TARGET, NAME, SHORT, DEF) NEXT = setting_data_path_setting (NAME, SHORT, TARGET, sizeof(TARGET), DEF);
#define CONFIG_STRING(TARGET, NAME, SHORT, DEF) NEXT = setting_data_string_setting(NAME, SHORT, TARGET, sizeof(TARGET), DEF);
#define CONFIG_HEX(TARGET, NAME, SHORT)
#define CONFIG_BIND(TARGET, PLAYER, NAME, SHORT, DEF) \
NEXT = setting_data_bind_setting (NAME, SHORT, &TARGET, PLAYER, DEF);
// TODO: Add black_frame_insertion, swap_interval msg_color video.rotation audio.block_frames audio.in_rate fast_forward_ratio
// rgui_show_start_screen
const rarch_setting_t* setting_data_get_list()
{
static rarch_setting_t list[512] = { 0 };
if (list[0].type == ST_NONE)
{
unsigned index = 0;
/***********/
/* DRIVERS */
/***********/
#if 0
START_GROUP("Drivers")
START_SUB_GROUP("Drivers")
CONFIG_STRING(g_settings.video.driver, "video_driver", "Video Driver", "")
CONFIG_STRING(g_settings.video.gl_context, "video_gl_context", "OpenGL Driver", "")
CONFIG_STRING(g_settings.audio.driver, "audio_driver", "Audio Driver", "")
CONFIG_STRING(g_settings.input.driver, "input_driver", "Input Driver", "")
CONFIG_STRING(g_settings.input.joypad_driver, "input_joypad_driver", "Joypad Driver", "")
END_SUB_GROUP()
END_GROUP()
#endif
/*********/
/* PATHS */
/*********/
START_GROUP("Paths")
START_SUB_GROUP("Paths")
CONFIG_PATH(g_settings.libretro, "libretro_path", "libretro Path", "")
CONFIG_PATH(g_settings.core_options_path, "core_options_path", "Core Options Path", DEFAULT_ME_YO)
CONFIG_PATH(g_settings.screenshot_directory, "screenshot_directory", "Screenshot Directory", DEFAULT_ME_YO)
CONFIG_PATH(g_settings.cheat_database, "cheat_database_path", "Cheat Database", DEFAULT_ME_YO)
CONFIG_PATH(g_settings.cheat_settings_path, "cheat_settings_path", "Cheat Settings", DEFAULT_ME_YO)
CONFIG_PATH(g_settings.game_history_path, "game_history_path", "Game History Path", DEFAULT_ME_YO)
CONFIG_UINT(g_settings.game_history_size, "game_history_size", "Game History Size", game_history_size)
#ifdef HAVE_RGUI
CONFIG_PATH(g_settings.rgui_browser_directory, "rgui_browser_directory", "Browser Directory", DEFAULT_ME_YO)
#endif
#ifdef HAVE_OVERLAY
CONFIG_PATH(g_extern.overlay_dir, "overlay_directory", "Overlay Directory", DEFAULT_ME_YO)
#endif
END_SUB_GROUP()
END_GROUP()
/*************/
/* EMULATION */
/*************/
START_GROUP("Emulation")
START_SUB_GROUP("Emulation")
CONFIG_BOOL(g_settings.pause_nonactive, "pause_nonactive", "Pause when inactive", pause_nonactive)
CONFIG_BOOL(g_settings.rewind_enable, "rewind_enable", "Enable Rewind", rewind_enable)
// CONFIG_INT(g_settings.rewind_buffer_size, "rewind_buffer_size", "Rewind Buffer Size", rewind_buffer_size) /* *= 1000000 */
CONFIG_UINT(g_settings.rewind_granularity, "rewind_granularity", "Rewind Granularity", rewind_granularity)
CONFIG_FLOAT(g_settings.slowmotion_ratio, "slowmotion_ratio", "Slow motion ratio", slowmotion_ratio) /* >= 1.0f */
/* Saves */
CONFIG_UINT(g_settings.autosave_interval, "autosave_interval", "Autosave Interval", autosave_interval)
CONFIG_BOOL(g_settings.block_sram_overwrite, "block_sram_overwrite", "Block SRAM overwrite", block_sram_overwrite)
CONFIG_BOOL(g_settings.savestate_auto_index, "savestate_auto_index", "Save State Auto Index", savestate_auto_index)
CONFIG_BOOL(g_settings.savestate_auto_save, "savestate_auto_save", "Auto Save State", savestate_auto_save)
CONFIG_BOOL(g_settings.savestate_auto_load, "savestate_auto_load", "Auto Load State", savestate_auto_load)
END_SUB_GROUP()
END_GROUP()
/*********/
/* VIDEO */
/*********/
START_GROUP("Video")
START_SUB_GROUP("Monitor")
CONFIG_UINT(g_settings.video.monitor_index, "video_monitor_index", "Monitor Index", monitor_index)
CONFIG_BOOL(g_settings.video.fullscreen, "video_fullscreen", "Use Fullscreen mode", g_extern.force_fullscreen ? true : fullscreen) // if (!g_extern.force_fullscreen)
CONFIG_BOOL(g_settings.video.windowed_fullscreen, "video_windowed_fullscreen", "Windowed Fullscreen Mode", windowed_fullscreen)
CONFIG_UINT(g_settings.video.fullscreen_x, "video_fullscreen_x", "Fullscreen Width", fullscreen_x)
CONFIG_UINT(g_settings.video.fullscreen_y, "video_fullscreen_y", "Fullscreen Height", fullscreen_y)
CONFIG_FLOAT(g_settings.video.refresh_rate, "video_refresh_rate", "Refresh Rate", refresh_rate)
END_SUB_GROUP()
#if 0
/* Video: Window Manager */
START_SUB_GROUP("Window Manager")
CONFIG_BOOL(g_settings.video.disable_composition, "video_disable_composition", "Disable WM Composition", disable_composition)
END_SUB_GROUP()
#endif
START_SUB_GROUP("Aspect")
CONFIG_BOOL(g_settings.video.force_aspect, "video_force_aspect", "Force aspect ratio", force_aspect)
CONFIG_FLOAT(g_settings.video.aspect_ratio, "video_aspect_ratio", "Aspect Ratio", aspect_ratio)
CONFIG_BOOL(g_settings.video.aspect_ratio_auto, "video_aspect_ratio_auto", "Use Auto Aspect Ratio", aspect_ratio_auto)
CONFIG_UINT(g_settings.video.aspect_ratio_idx, "aspect_ratio_index", "Aspect Ratio Index", aspect_ratio_idx)
END_SUB_GROUP()
START_SUB_GROUP("Scaling")
CONFIG_FLOAT(g_settings.video.xscale, "video_xscale", "X Scale", xscale)
CONFIG_FLOAT(g_settings.video.yscale, "video_yscale", "Y Scale", yscale)
CONFIG_BOOL(g_settings.video.scale_integer, "video_scale_integer", "Force integer scaling", scale_integer)
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.x, "custom_viewport_x", "Custom Viewport X", 0)
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.y, "custom_viewport_y", "Custom Viewport Y", 0)
CONFIG_UINT(g_extern.console.screen.viewports.custom_vp.width, "custom_viewport_width", "Custom Viewport Width", 0)
CONFIG_UINT(g_extern.console.screen.viewports.custom_vp.height, "custom_viewport_height", "Custom Viewport Height", 0)
CONFIG_BOOL(g_settings.video.smooth, "video_smooth", "Use bilinear filtering", video_smooth)
END_SUB_GROUP()
START_SUB_GROUP("Shader")
CONFIG_BOOL(g_settings.video.shader_enable, "video_shader_enable", "Enable Shaders", shader_enable)
CONFIG_PATH(g_settings.video.shader_dir, "video_shader_dir", "Shader Directory", DEFAULT_ME_YO)
CONFIG_PATH(g_settings.video.shader_path, "video_shader", "Shader", DEFAULT_ME_YO)
END_SUB_GROUP()
START_SUB_GROUP("Sync")
CONFIG_BOOL(g_settings.video.threaded, "video_threaded", "Use threaded video", video_threaded)
CONFIG_BOOL(g_settings.video.vsync, "video_vsync", "Use VSync", vsync)
CONFIG_BOOL(g_settings.video.hard_sync, "video_hard_sync", "Use OpenGL Hard Sync", hard_sync)
CONFIG_UINT(g_settings.video.hard_sync_frames, "video_hard_sync_frames", "Number of Hard Sync frames", hard_sync_frames) // 0 - 3
END_SUB_GROUP()
START_SUB_GROUP("Misc")
CONFIG_BOOL(g_settings.video.post_filter_record, "video_post_filter_record", "Post filter record", post_filter_record)
CONFIG_BOOL(g_settings.video.gpu_record, "video_gpu_record", "GPU Record", gpu_record)
CONFIG_BOOL(g_settings.video.gpu_screenshot, "video_gpu_screenshot", "GPU Screenshot", gpu_screenshot)
CONFIG_BOOL(g_settings.video.allow_rotate, "video_allow_rotate", "Allow rotation", allow_rotate)
CONFIG_BOOL(g_settings.video.crop_overscan, "video_crop_overscan", "Crop Overscan", crop_overscan)
#ifdef HAVE_DYLIB
CONFIG_PATH(g_settings.video.filter_path, "video_filter", "Software filter"),
#endif
END_SUB_GROUP()
START_SUB_GROUP("Messages")
CONFIG_PATH(g_settings.video.font_path, "video_font_path", "Font Path", DEFAULT_ME_YO)
CONFIG_FLOAT(g_settings.video.font_size, "video_font_size", "Font Size", font_size)
CONFIG_BOOL(g_settings.video.font_enable, "video_font_enable", "Font Enable", font_enable)
CONFIG_BOOL(g_settings.video.font_scale, "video_font_scale", "Font Scale", font_scale)
CONFIG_FLOAT(g_settings.video.msg_pos_x, "video_message_pos_x", "Message X Position", message_pos_offset_x)
CONFIG_FLOAT(g_settings.video.msg_pos_y, "video_message_pos_y", "Message Y Position", message_pos_offset_y)
/* message color */
END_SUB_GROUP()
END_GROUP()
/*********/
/* AUDIO */
/*********/
START_GROUP("Audio")
START_SUB_GROUP("State")
CONFIG_BOOL(g_settings.audio.enable, "audio_enable", "Enable", audio_enable)
CONFIG_FLOAT(g_settings.audio.volume, "audio_volume", "Volume", audio_volume)
END_SUB_GROUP()
START_SUB_GROUP("Sync")
CONFIG_BOOL(g_settings.audio.sync, "audio_sync", "Enable Sync", audio_sync)
CONFIG_UINT(g_settings.audio.latency, "audio_latency", "Latency", out_latency)
CONFIG_BOOL(g_settings.audio.rate_control, "audio_rate_control", "Enable Rate Control", rate_control)
CONFIG_FLOAT(g_settings.audio.rate_control_delta, "audio_rate_control_delta", "Rate Control Delta", rate_control_delta)
END_SUB_GROUP()
START_SUB_GROUP("Misc")
CONFIG_STRING(g_settings.audio.device, "audio_device", "Device", DEFAULT_ME_YO)
CONFIG_UINT(g_settings.audio.out_rate, "audio_out_rate", "Ouput Rate", out_rate)
CONFIG_PATH(g_settings.audio.dsp_plugin, "audio_dsp_plugin", "DSP Plugin", DEFAULT_ME_YO)
END_SUB_GROUP()
END_GROUP()
/*********/
/* INPUT */
/*********/
START_GROUP("Input")
START_SUB_GROUP("Input")
/* Input: Autoconfig */
CONFIG_BOOL(g_settings.input.autodetect_enable, "input_autodetect_enable", "Use joypad autodetection", input_autodetect_enable)
CONFIG_PATH(g_settings.input.autoconfig_dir, "joypad_autoconfig_dir", "Joypad Autoconfig Directory", DEFAULT_ME_YO)
END_SUB_GROUP()
START_SUB_GROUP("Joypad Mapping")
CONFIG_INT(g_settings.input.joypad_map[0], "input_player1_joypad_index", "Player 1 Pad Index", 0)
CONFIG_INT(g_settings.input.joypad_map[1], "input_player2_joypad_index", "Player 2 Pad Index", 1)
CONFIG_INT(g_settings.input.joypad_map[2], "input_player3_joypad_index", "Player 3 Pad Index", 2)
CONFIG_INT(g_settings.input.joypad_map[3], "input_player4_joypad_index", "Player 4 Pad Index", 3)
CONFIG_INT(g_settings.input.joypad_map[4], "input_player5_joypad_index", "Player 5 Pad Index", 4)
END_SUB_GROUP()
START_SUB_GROUP("Turbo/Deadzone")
CONFIG_FLOAT(g_settings.input.axis_threshold, "input_axis_threshold", "Axis Deadzone", axis_threshold)
CONFIG_UINT(g_settings.input.turbo_period, "input_turbo_period", "Turbo Period", turbo_period)
CONFIG_UINT(g_settings.input.turbo_duty_cycle, "input_duty_cycle", "Duty Cycle", turbo_duty_cycle)
END_SUB_GROUP()
START_SUB_GROUP("Misc")
CONFIG_BOOL(g_settings.input.netplay_client_swap_input, "netplay_client_swap_input", "Swap Netplay Input", netplay_client_swap_input)
CONFIG_BOOL(g_settings.input.debug_enable, "input_debug_enable", "Enable Input Debugging", input_debug_enable)
END_SUB_GROUP()
#ifdef HAVE_OVERLAY
START_SUB_GROUP("Overlay")
CONFIG_PATH(g_settings.input.overlay, "input_overlay", "Input Overlay", DEFAULT_ME_YO)
CONFIG_FLOAT(g_settings.input.overlay_opacity, "input_overlay_opacity", "Overlay Opacity", 1.0f)
CONFIG_FLOAT(g_settings.input.overlay_scale, "input_overlay_scale", "Overlay Scale", 1.0f)
END_SUB_GROUP()
#endif
/* Input: Android */
#ifdef ANDROID
START_SUB_GROUP("Android")
CONFIG_INT(g_settings.input.back_behavior, "input_back_behavior", "Back Behavior", BACK_BUTTON_QUIT)
CONFIG_INT(g_settings.input.icade_profile[0], "input_autodetect_icade_profile_pad1", "iCade 1", DEFAULT_ME_YO)
CONFIG_INT(g_settings.input.icade_profile[1], "input_autodetect_icade_profile_pad2", "iCade 2", DEFAULT_ME_YO)
CONFIG_INT(g_settings.input.icade_profile[2], "input_autodetect_icade_profile_pad3", "iCade 3", DEFAULT_ME_YO)
CONFIG_INT(g_settings.input.icade_profile[3], "input_autodetect_icade_profile_pad4", "iCade 4", DEFAULT_ME_YO)
END_SUB_GROUP()
#endif
START_SUB_GROUP("Meta Keys")
for (int i = 0; i != RARCH_BIND_LIST_END; i ++)
if (input_config_bind_map[i].meta)
{
const struct input_bind_map* bind = &input_config_bind_map[i];
CONFIG_BIND(g_settings.input.binds[0][i], 0, bind->base, bind->desc, &retro_keybinds_1[i])
}
END_SUB_GROUP()
START_SUB_GROUP("Player 1")
for (int i = 0; i != RARCH_BIND_LIST_END; i ++)
if (!input_config_bind_map[i].meta)
{
const struct input_bind_map* bind = &input_config_bind_map[i];
CONFIG_BIND(g_settings.input.binds[0][i], 0, bind->base, bind->desc, &retro_keybinds_1[i])
}
END_SUB_GROUP()
END_GROUP()
/********/
/* Misc */
/********/
START_GROUP("Misc")
START_SUB_GROUP("Misc")
CONFIG_BOOL(g_extern.config_save_on_exit, "config_save_on_exit", "Save Config On Exit", config_save_on_exit)
CONFIG_BOOL(g_settings.network_cmd_enable, "network_cmd_enable", "Network Commands", network_cmd_enable)
// CONFIG_INT(g_settings.network_cmd_port, "network_cmd_port", "Network Command Port", network_cmd_port)
CONFIG_BOOL(g_settings.stdin_cmd_enable, "stdin_cmd_enable", "stdin command", stdin_cmd_enable)
END_SUB_GROUP()
END_GROUP()
}
return list;
}

View File

@ -18,7 +18,7 @@
#include "general.h"
enum setting_type { ST_NONE, ST_BOOL, ST_INT, ST_FLOAT, ST_PATH, ST_STRING, ST_HEX, ST_BIND,
enum setting_type { ST_NONE, ST_BOOL, ST_INT, ST_UINT, ST_FLOAT, ST_PATH, ST_STRING, ST_HEX, ST_BIND,
ST_GROUP, ST_SUB_GROUP, ST_END_GROUP, ST_END_SUB_GROUP };
typedef struct
@ -26,322 +26,68 @@ typedef struct
enum setting_type type;
const char* name;
void* value;
uint32_t size;
const char* short_description;
uint32_t input_player;
uint32_t index;
double min;
double max;
bool allow_blank;
union
{
bool boolean;
int integer;
unsigned int unsigned_integer;
float fraction;
const char* string;
const struct retro_keybind* keybind;
} default_value;
union
{
bool* boolean;
int* integer;
unsigned int* unsigned_integer;
float* fraction;
char* string;
struct retro_keybind* keybind;
} value;
} rarch_setting_t;
extern struct settings fake_settings;
extern struct global fake_extern;
// HACK
#define g_settings fake_settings
#define g_extern fake_extern
#define START_GROUP(NAME) { ST_GROUP, NAME },
#define END_GROUP() { ST_END_GROUP },
#define START_SUB_GROUP(NAME) { ST_SUB_GROUP, NAME },
#define END_SUB_GROUP() { ST_END_SUB_GROUP },
#define CONFIG_BOOL(TARGET, NAME, SHORT) { ST_BOOL, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_INT(TARGET, NAME, SHORT) { ST_INT, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_FLOAT(TARGET, NAME, SHORT) { ST_FLOAT, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_PATH(TARGET, NAME, SHORT) { ST_PATH, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_STRING(TARGET, NAME, SHORT) { ST_STRING, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_HEX(TARGET, NAME, SHORT) { ST_HEX, NAME, &TARGET, sizeof(TARGET), SHORT },
#define CONFIG_BIND(TARGET, PLAYER, NAME, SHORT) { ST_BIND, NAME, &TARGET, sizeof(TARGET), SHORT, PLAYER },
const rarch_setting_t setting_data[] =
{
/***********/
/* DRIVERS */
/***********/
#if 0
START_GROUP("Drivers")
START_SUB_GROUP("Drivers")
CONFIG_STRING(g_settings.video.driver, "video_driver", "Video Driver")
CONFIG_STRING(g_settings.video.gl_context, "video_gl_context", "OpenGL Driver")
CONFIG_STRING(g_settings.audio.driver, "audio_driver", "Audio Driver")
CONFIG_STRING(g_settings.input.driver, "input_driver", "Input Driver")
CONFIG_STRING(g_settings.input.joypad_driver, "input_joypad_driver", "Joypad Driver")
END_SUB_GROUP()
END_GROUP()
#endif
/*********/
/* PATHS */
/*********/
START_GROUP("Paths")
START_SUB_GROUP("Paths")
CONFIG_PATH(g_settings.libretro, "libretro_path", "libretro Path")
CONFIG_PATH(g_settings.core_options_path, "core_options_path", "Core Options Path")
CONFIG_PATH(g_settings.screenshot_directory, "screenshot_directory", "Screenshot Directory")
CONFIG_PATH(g_settings.cheat_database, "cheat_database_path", "Cheat Database")
CONFIG_PATH(g_settings.cheat_settings_path, "cheat_settings_path", "Cheat Settings")
CONFIG_PATH(g_settings.game_history_path, "game_history_path", "Game History Path")
CONFIG_INT(g_settings.game_history_size, "game_history_size", "Game History Size")
#ifdef HAVE_RGUI
CONFIG_PATH(g_settings.rgui_browser_directory, "rgui_browser_directory", "Browser Directory")
#endif
#ifdef HAVE_OVERLAY
CONFIG_PATH(g_extern.overlay_dir, "overlay_directory", "Overlay Directory")
#endif
END_SUB_GROUP()
END_GROUP()
#define BINDFOR(s) (*(&s)->value.keybind)
/*************/
/* EMULATION */
/*************/
START_GROUP("Emulation")
START_SUB_GROUP("Emulation")
CONFIG_BOOL(g_settings.pause_nonactive, "pause_nonactive", "Pause when inactive")
CONFIG_BOOL(g_settings.rewind_enable, "rewind_enable", "Enable Rewind")
CONFIG_INT(g_settings.rewind_buffer_size, "rewind_buffer_size", "Rewind Buffer Size") /* *= 1000000 */
CONFIG_INT(g_settings.rewind_granularity, "rewind_granularity", "Rewind Granularity")
CONFIG_FLOAT(g_settings.slowmotion_ratio, "slowmotion_ratio", "Slow motion ratio") /* >= 1.0f */
void setting_data_reset(const rarch_setting_t* settings);
/* Saves */
CONFIG_INT(g_settings.autosave_interval, "autosave_interval", "Autosave Interval")
CONFIG_BOOL(g_settings.block_sram_overwrite, "block_sram_overwrite", "Block SRAM overwrite")
CONFIG_BOOL(g_settings.savestate_auto_index, "savestate_auto_index", "Save State Auto Index")
CONFIG_BOOL(g_settings.savestate_auto_save, "savestate_auto_save", "Auto Save State")
CONFIG_BOOL(g_settings.savestate_auto_load, "savestate_auto_load", "Auto Load State")
END_SUB_GROUP()
END_GROUP()
bool setting_data_load_config_path(const rarch_setting_t* settings, const char* path);
bool setting_data_load_config(const rarch_setting_t* settings, config_file_t* config);
bool setting_data_save_config_path(const rarch_setting_t* settings, const char* path);
bool setting_data_save_config(const rarch_setting_t* settings, config_file_t* config);
/*********/
/* VIDEO */
/*********/
START_GROUP("Video")
START_SUB_GROUP("Monitor")
CONFIG_INT(g_settings.video.monitor_index, "video_monitor_index", "Monitor Index")
CONFIG_BOOL(g_settings.video.fullscreen, "video_fullscreen", "Use Fullscreen mode") // if (!g_extern.force_fullscreen)
CONFIG_BOOL(g_settings.video.windowed_fullscreen, "video_windowed_fullscreen", "Windowed Fullscreen Mode")
CONFIG_INT(g_settings.video.fullscreen_x, "video_fullscreen_x", "Fullscreen Width")
CONFIG_INT(g_settings.video.fullscreen_y, "video_fullscreen_y", "Fullscreen Height")
CONFIG_FLOAT(g_settings.video.refresh_rate, "video_refresh_rate", "Refresh Rate")
END_SUB_GROUP()
const rarch_setting_t* setting_data_find_setting(const rarch_setting_t* settings, const char* name);
#if 0
/* Video: Window Manager */
START_SUB_GROUP("Window Manager")
CONFIG_BOOL(g_settings.video.disable_composition, "video_disable_composition", "Disable WM Composition")
END_SUB_GROUP()
#endif
void setting_data_set_with_string_representation(const rarch_setting_t* setting, const char* value);
const char* setting_data_get_string_representation(const rarch_setting_t* setting, char* buffer, size_t length);
START_SUB_GROUP("Aspect")
CONFIG_BOOL(g_settings.video.force_aspect, "video_force_aspect", "Force aspect ratio")
CONFIG_FLOAT(g_settings.video.aspect_ratio, "video_aspect_ratio", "Aspect Ratio")
CONFIG_BOOL(g_settings.video.aspect_ratio_auto, "video_aspect_ratio_auto", "Use Auto Aspect Ratio")
CONFIG_INT(g_settings.video.aspect_ratio_idx, "aspect_ratio_index", "Aspect Ratio Index")
END_SUB_GROUP()
// List building helper functions
rarch_setting_t setting_data_group_setting(enum setting_type type, const char* name);
rarch_setting_t setting_data_bool_setting(const char* name, const char* description, bool* target, bool default_value);
rarch_setting_t setting_data_int_setting(const char* name, const char* description, int* target, int default_value);
rarch_setting_t setting_data_uint_setting(const char* name, const char* description, unsigned int* target, unsigned int default_value);
rarch_setting_t setting_data_float_setting(const char* name, const char* description, float* target, float default_value);
rarch_setting_t setting_data_path_setting(const char* name, const char* description, char* target, unsigned size, char* default_value);
rarch_setting_t setting_data_string_setting(const char* name, const char* description, char* target, unsigned size, char* default_value);
rarch_setting_t setting_data_bind_setting(const char* name, const char* description, struct retro_keybind* target, uint32_t index,
const struct retro_keybind* default_value);
START_SUB_GROUP("Scaling")
CONFIG_FLOAT(g_settings.video.xscale, "video_xscale", "X Scale")
CONFIG_FLOAT(g_settings.video.yscale, "video_yscale", "Y Scale")
CONFIG_BOOL(g_settings.video.scale_integer, "video_scale_integer", "Force integer scaling")
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.x, "custom_viewport_x", "Custom Viewport X")
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.y, "custom_viewport_y", "Custom Viewport Y")
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.width, "custom_viewport_width", "Custom Viewport Width")
CONFIG_INT(g_extern.console.screen.viewports.custom_vp.height, "custom_viewport_height", "Custom Viewport Height")
CONFIG_BOOL(g_settings.video.smooth, "video_smooth", "Use bilinear filtering")
END_SUB_GROUP()
START_SUB_GROUP("Shader")
CONFIG_BOOL(g_settings.video.shader_enable, "video_shader_enable", "Enable Shaders")
CONFIG_PATH(g_settings.video.shader_dir, "video_shader_dir", "Shader Directory")
CONFIG_PATH(g_settings.video.shader_path, "video_shader", "Shader")
END_SUB_GROUP()
START_SUB_GROUP("Sync")
CONFIG_BOOL(g_settings.video.threaded, "video_threaded", "Use threaded video")
CONFIG_BOOL(g_settings.video.vsync, "video_vsync", "Use VSync")
CONFIG_BOOL(g_settings.video.hard_sync, "video_hard_sync", "Use OpenGL Hard Sync")
CONFIG_INT(g_settings.video.hard_sync_frames, "video_hard_sync_frames", "Number of Hard Sync frames") // 0 - 3
END_SUB_GROUP()
START_SUB_GROUP("Misc")
CONFIG_BOOL(g_settings.video.post_filter_record, "video_post_filter_record", "Post filter record")
CONFIG_BOOL(g_settings.video.gpu_record, "video_gpu_record", "GPU Record")
CONFIG_BOOL(g_settings.video.gpu_screenshot, "video_gpu_screenshot", "GPU Screenshot")
CONFIG_BOOL(g_settings.video.allow_rotate, "video_allow_rotate", "Allow rotation")
CONFIG_BOOL(g_settings.video.crop_overscan, "video_crop_overscan", "Crop Overscan")
#ifdef HAVE_DYLIB
CONFIG_PATH(g_settings.video.filter_path, "video_filter", "Software filter"),
#endif
END_SUB_GROUP()
START_SUB_GROUP("Messages")
CONFIG_PATH(g_settings.video.font_path, "video_font_path", "Font Path")
CONFIG_FLOAT(g_settings.video.font_size, "video_font_size", "Font Size")
CONFIG_BOOL(g_settings.video.font_enable, "video_font_enable", "Font Enable")
CONFIG_BOOL(g_settings.video.font_scale, "video_font_scale", "Font Scale")
CONFIG_FLOAT(g_settings.video.msg_pos_x, "video_message_pos_x", "Message X Position")
CONFIG_FLOAT(g_settings.video.msg_pos_y, "video_message_pos_y", "Message Y Position")
/* message color */
END_SUB_GROUP()
END_GROUP()
/*********/
/* AUDIO */
/*********/
START_GROUP("Audio")
START_SUB_GROUP("Audio")
CONFIG_BOOL(g_settings.audio.enable, "audio_enable", "Enable")
CONFIG_FLOAT(g_settings.audio.volume, "audio_volume", "Volume")
/* Audio: Sync */
CONFIG_BOOL(g_settings.audio.sync, "audio_sync", "Enable Sync")
CONFIG_INT(g_settings.audio.latency, "audio_latency", "Latency")
CONFIG_BOOL(g_settings.audio.rate_control, "audio_rate_control", "Enable Rate Control")
CONFIG_FLOAT(g_settings.audio.rate_control_delta, "audio_rate_control_delta", "Rate Control Delta")
/* Audio: Other */
CONFIG_STRING(g_settings.audio.device, "audio_device", "Device")
CONFIG_INT(g_settings.audio.out_rate, "audio_out_rate", "Ouput Rate")
CONFIG_PATH(g_settings.audio.dsp_plugin, "audio_dsp_plugin", "DSP Plugin")
END_SUB_GROUP()
END_GROUP()
/*********/
/* INPUT */
/*********/
START_GROUP("Input")
START_SUB_GROUP("Input")
/* Input: Autoconfig */
CONFIG_BOOL(g_settings.input.autodetect_enable, "input_autodetect_enable", "Use joypad autodetection")
CONFIG_PATH(g_settings.input.autoconfig_dir, "joypad_autoconfig_dir", "Joypad Autoconfig Directory")
/* Input: Joypad mapping */
CONFIG_INT(g_settings.input.joypad_map[0], "input_player1_joypad_index", "Player 1 Pad Index")
CONFIG_INT(g_settings.input.joypad_map[1], "input_player2_joypad_index", "Player 2 Pad Index")
CONFIG_INT(g_settings.input.joypad_map[2], "input_player3_joypad_index", "Player 3 Pad Index")
CONFIG_INT(g_settings.input.joypad_map[3], "input_player4_joypad_index", "Player 4 Pad Index")
CONFIG_INT(g_settings.input.joypad_map[4], "input_player5_joypad_index", "Player 5 Pad Index")
/* Input: Turbo/Axis options */
CONFIG_FLOAT(g_settings.input.axis_threshold, "input_axis_threshold", "Axis Deadzone")
CONFIG_INT(g_settings.input.turbo_period, "input_turbo_period", "Turbo Period")
CONFIG_INT(g_settings.input.turbo_duty_cycle, "input_duty_cycle", "Duty Cycle")
/* Input: Misc */
CONFIG_BOOL(g_settings.input.netplay_client_swap_input, "netplay_client_swap_input", "Swap Netplay Input")
CONFIG_BOOL(g_settings.input.debug_enable, "input_debug_enable", "Enable Input Debugging")
/* Input: Overlay */
#ifdef HAVE_OVERLAY
CONFIG_PATH(g_settings.input.overlay, "input_overlay", "Input Overlay")
CONFIG_FLOAT(g_settings.input.overlay_opacity, "input_overlay_opacity", "Overlay Opacity")
CONFIG_FLOAT(g_settings.input.overlay_scale, "input_overlay_scale", "Overlay Scale")
#endif
/* Input: Android */
#ifdef ANDROID
CONFIG_INT(g_settings.input.back_behavior, "input_back_behavior", "Back Behavior")
CONFIG_INT(g_settings.input.icade_profile[0], "input_autodetect_icade_profile_pad1", "iCade 1")
CONFIG_INT(g_settings.input.icade_profile[1], "input_autodetect_icade_profile_pad2", "iCade 2")
CONFIG_INT(g_settings.input.icade_profile[2], "input_autodetect_icade_profile_pad3", "iCade 3")
CONFIG_INT(g_settings.input.icade_profile[3], "input_autodetect_icade_profile_pad4", "iCade 4")
#endif
END_SUB_GROUP()
START_SUB_GROUP("Meta Keys")
CONFIG_BIND(g_settings.input.binds[0][RARCH_FAST_FORWARD_KEY], 0, "toggle_fast_forward", "Fast forward toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_FAST_FORWARD_HOLD_KEY], 0, "hold_fast_forward", "Fast forward hold")
CONFIG_BIND(g_settings.input.binds[0][RARCH_LOAD_STATE_KEY], 0, "load_state", "Load state")
CONFIG_BIND(g_settings.input.binds[0][RARCH_SAVE_STATE_KEY], 0, "save_state", "Save state")
CONFIG_BIND(g_settings.input.binds[0][RARCH_FULLSCREEN_TOGGLE_KEY], 0, "toggle_fullscreen", "Fullscreen toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_QUIT_KEY], 0, "exit_emulator", "Quit RetroArch")
CONFIG_BIND(g_settings.input.binds[0][RARCH_STATE_SLOT_PLUS], 0, "state_slot_increase", "Savestate slot +")
CONFIG_BIND(g_settings.input.binds[0][RARCH_STATE_SLOT_MINUS], 0, "state_slot_decrease", "Savestate slot -")
CONFIG_BIND(g_settings.input.binds[0][RARCH_REWIND], 0, "rewind", "Rewind")
CONFIG_BIND(g_settings.input.binds[0][RARCH_MOVIE_RECORD_TOGGLE], 0, "movie_record_toggle", "Movie record toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_PAUSE_TOGGLE], 0, "pause_toggle", "Pause toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_FRAMEADVANCE], 0, "frame_advance", "Frameadvance")
CONFIG_BIND(g_settings.input.binds[0][RARCH_RESET], 0, "reset", "Reset game")
CONFIG_BIND(g_settings.input.binds[0][RARCH_SHADER_NEXT], 0, "shader_next", "Next shader")
CONFIG_BIND(g_settings.input.binds[0][RARCH_SHADER_PREV], 0, "shader_prev", "Previous shader")
CONFIG_BIND(g_settings.input.binds[0][RARCH_CHEAT_INDEX_PLUS], 0, "cheat_index_plus", "Cheat index +")
CONFIG_BIND(g_settings.input.binds[0][RARCH_CHEAT_INDEX_MINUS], 0, "cheat_index_minus", "Cheat index -")
CONFIG_BIND(g_settings.input.binds[0][RARCH_CHEAT_TOGGLE], 0, "cheat_toggle", "Cheat toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_SCREENSHOT], 0, "screenshot", "Take screenshot")
CONFIG_BIND(g_settings.input.binds[0][RARCH_DSP_CONFIG], 0, "dsp_config", "DSP config")
CONFIG_BIND(g_settings.input.binds[0][RARCH_MUTE], 0, "audio_mute", "Audio mute toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_NETPLAY_FLIP], 0, "netplay_flip_players", "Netplay flip players")
CONFIG_BIND(g_settings.input.binds[0][RARCH_SLOWMOTION], 0, "slowmotion", "Slow motion")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ENABLE_HOTKEY], 0, "enable_hotkey", "Enable hotkeys")
CONFIG_BIND(g_settings.input.binds[0][RARCH_VOLUME_UP], 0, "volume_up", "Volume +")
CONFIG_BIND(g_settings.input.binds[0][RARCH_VOLUME_DOWN], 0, "volume_down", "Volume -")
CONFIG_BIND(g_settings.input.binds[0][RARCH_OVERLAY_NEXT], 0, "overlay_next", "Overlay next")
CONFIG_BIND(g_settings.input.binds[0][RARCH_DISK_EJECT_TOGGLE], 0, "disk_eject_toggle", "Disk eject toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_DISK_NEXT], 0, "disk_next", "Disk next")
CONFIG_BIND(g_settings.input.binds[0][RARCH_GRAB_MOUSE_TOGGLE], 0, "grab_mouse_toggle", "Grab mouse toggle")
CONFIG_BIND(g_settings.input.binds[0][RARCH_MENU_TOGGLE], 0, "menu_toggle", "RGUI menu toggle")
END_SUB_GROUP()
START_SUB_GROUP("Player 1")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_UP], 1, "up", "Up D-pad")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_DOWN], 1, "down", "Down D-pad")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_LEFT], 1, "left", "Left D-pad")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_RIGHT], 1, "right", "Right D-pad")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_SELECT],1, "select", "Select button")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_START], 1, "start", "Start button")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_B], 1, "b", "B button (down)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_A], 1, "a", "A button (right)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_X], 1, "x", "X button (top)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_Y], 1, "y", "Y button (left)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L], 1, "l", "L button (left shoulder)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R], 1, "r", "R button (right shoulder)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L2], 1, "l2", "L2 button (left shoulder #2)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R2], 1, "r2", "R2 button (right shoulder #2)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L3], 1, "l3", "L3 button (left analog button)")
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R3], 1, "r3", "R3 button (right analog button)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_Y_MINUS], 1, "l_y_minus", "Left analog Y- (up)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_Y_PLUS], 1, "l_y_plus", "Left analog Y+ (down)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_X_MINUS], 1, "l_x_minus", "Left analog X- (left)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_X_PLUS], 1, "l_x_plus", "Left analog X+ (right)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_Y_MINUS], 1, "r_y_minus", "Right analog Y- (up)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_Y_PLUS], 1, "r_y_plus", "Right analog Y+ (down)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_X_MINUS], 1, "r_x_minus", "Right analog X- (left)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_X_PLUS], 1, "r_x_plus", "Right analog X+ (right)")
CONFIG_BIND(g_settings.input.binds[0][RARCH_TURBO_ENABLE], 1, "turbo", "Turbo enable")
END_SUB_GROUP()
END_GROUP()
/********/
/* Misc */
/********/
START_GROUP("Misc")
START_SUB_GROUP("Misc")
CONFIG_BOOL(g_extern.config_save_on_exit, "config_save_on_exit", "Save Config On Exit")
CONFIG_BOOL(g_settings.network_cmd_enable, "network_cmd_enable", "Network Commands")
CONFIG_INT(g_settings.network_cmd_port, "network_cmd_port", "Network Command Port")
CONFIG_BOOL(g_settings.stdin_cmd_enable, "stdin_cmd_enable", "stdin command")
END_SUB_GROUP()
END_GROUP()
{ 0 }
};
// HACK
#undef g_settings
#undef g_extern
// These functions operate only on RetroArch's main settings list
void setting_data_load_current();
const rarch_setting_t* setting_data_get_list();
// Keyboard
#include "keycode.h"
#endif
#endif

View File

@ -16,6 +16,7 @@
#include <sys/stat.h>
#include "RetroArch_Apple.h"
#include "setting_data.h"
#include "general.h"
#include "file.h"
@ -54,56 +55,81 @@ NSString* objc_get_value_from_config(config_file_t* config, NSString* name, NSSt
return result;
}
#ifdef IOS
#include "../iOS/views.h"
// Simple class to reduce code duplication for fixed table views
@implementation RATableViewController
- (id)initWithStyle:(UITableViewStyle)style
// Get a core ID as an NSString
NSString *apple_get_core_id(const core_info_t *core)
{
self = [super initWithStyle:style];
self.sections = [NSMutableArray array];
char buf[PATH_MAX];
return @(apple_core_info_get_id(core, buf, sizeof(buf)));
}
NSString *apple_get_core_display_name(NSString *core_id)
{
const core_info_t *core = apple_core_info_list_get_by_id(core_id.UTF8String);
return core ? @(core->display_name) : core_id;
}
// Number formatter class for setting strings
@implementation RANumberFormatter
- (id)initWithSetting:(const rarch_setting_t*)setting
{
if ((self = [super init]))
{
self.allowsFloats = (setting->type == ST_FLOAT);
if (setting->min != setting->max)
{
self.minimum = @(setting->min);
self.maximum = @(setting->max);
}
else
{
if (setting->type == ST_INT)
{
self.minimum = @(INT_MIN);
self.maximum = @(INT_MAX);
}
else if (setting->type == ST_UINT)
{
self.minimum = @(0);
self.maximum = @(UINT_MAX);
}
else if (setting->type == ST_FLOAT)
{
self.minimum = @(FLT_MIN);
self.maximum = @(FLT_MAX);
}
}
}
return self;
}
- (bool)getCellFor:(NSString*)reuseID withStyle:(UITableViewCellStyle)style result:(UITableViewCell**)output
- (BOOL)isPartialStringValid:(NSString*)partialString newEditingString:(NSString**)newString errorDescription:(NSString**)error
{
UITableViewCell* result = [self.tableView dequeueReusableCellWithIdentifier:reuseID];
if (result)
*output = result;
else
*output = [[UITableViewCell alloc] initWithStyle:style reuseIdentifier:reuseID];
return !result;
bool hasDot = false;
if (partialString.length)
for (int i = 0; i != partialString.length; i ++)
{
unichar ch = [partialString characterAtIndex:i];
if (i == 0 && (!self.minimum || self.minimum.intValue < 0) && ch == '-')
continue;
else if (self.allowsFloats && !hasDot && ch == '.')
hasDot = true;
else if (!isdigit(ch))
return NO;
}
return YES;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
#ifdef IOS
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return self.sections.count;
NSString* text = [textField.text stringByReplacingCharactersInRange:range withString:string];
return [self isPartialStringValid:text newEditingString:nil errorDescription:nil];
}
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return self.hidesHeaders ? nil : 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];
}
- (void)reset
{
self.sections = [NSMutableArray array];
[self.tableView reloadData];
}
@end
#endif
@end

View File

@ -1,84 +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 <stdarg.h>
#include <stdio.h>
#include <pthread.h>
#import "views.h"
static NSMutableArray* g_messages;
static pthread_mutex_t g_lock = PTHREAD_MUTEX_INITIALIZER;
void ios_add_log_message(const char* format, ...)
{
pthread_mutex_lock(&g_lock);
g_messages = g_messages ? g_messages : [NSMutableArray array];
char buffer[512];
va_list args;
va_start(args, format);
vsnprintf(buffer, 512, format, args);
va_end(args);
[g_messages addObject:@(buffer)];
pthread_mutex_unlock(&g_lock);
}
@implementation RALogView
- (RALogView*)init
{
self = [super initWithStyle:UITableViewStyleGrouped];
[self setTitle:@"RetroArch Diagnostic Log"];
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
return 1;
}
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return @"Messages";
}
- (NSInteger)tableView:(UITableView *)tableView numberOfRowsInSection:(NSInteger)section
{
pthread_mutex_lock(&g_lock);
NSInteger count = g_messages ? g_messages.count : 0;
pthread_mutex_unlock(&g_lock);
return count;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* const cell_id = @"message";
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
cell = cell ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
pthread_mutex_lock(&g_lock);
cell.textLabel.text = g_messages[indexPath.row];
pthread_mutex_unlock(&g_lock);
return cell;
}
@end

View File

@ -24,16 +24,6 @@
static const void* const associated_module_key = &associated_module_key;
@implementation RADirectoryItem
+ (RADirectoryItem*)directoryItemFromElement:(struct string_list_elem*)element
{
RADirectoryItem* item = [RADirectoryItem new];
item.path = @(element->data);
item.isDirectory = element->attr.b;
return item;
}
@end
enum file_action { FA_DELETE = 10000, FA_CREATE, FA_MOVE };
static void file_action(enum file_action action, NSString* source, NSString* target)
{
@ -54,6 +44,50 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
apple_display_alert(error.localizedDescription, @"Action failed");
}
@implementation RADirectoryItem
+ (RADirectoryItem*)directoryItemFromPath:(NSString*)path
{
RADirectoryItem* item = [RADirectoryItem new];
item.path = path;
item.isDirectory = path_is_absolute(path.UTF8String);
return item;
}
+ (RADirectoryItem*)directoryItemFromElement:(struct string_list_elem*)element
{
RADirectoryItem* item = [RADirectoryItem new];
item.path = @(element->data);
item.isDirectory = element->attr.b;
return item;
}
- (UITableViewCell*)cellForTableView:(UITableView *)tableView
{
static NSString* const cell_id = @"path_item";
static NSString* const icon_types[2] = { @"ic_file", @"ic_dir" };
uint32_t type_id = self.isDirectory ? 1 : 0;
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
if (!result)
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
result.textLabel.text = [self.path lastPathComponent];
result.imageView.image = [UIImage imageNamed:icon_types[type_id]];
return result;
}
- (void)wasSelectedOnTableView:(UITableView *)tableView ofController:(UIViewController *)controller
{
if (self.isDirectory)
[(id)controller browseTo:self.path];
else
[[(id)controller directoryDelegate] directoryList:controller itemWasSelected:self];
}
@end
@implementation RADirectoryList
{
NSString* _path;
@ -61,15 +95,12 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
- (id)initWithPath:(NSString*)path delegate:(id<RADirectoryListDelegate>)delegate
{
self = [super initWithStyle:UITableViewStylePlain];
if (self)
if ((self = [super initWithStyle:UITableViewStylePlain]))
{
_path = path;
_directoryDelegate = delegate;
self = [super initWithStyle:UITableViewStylePlain];
self.title = path.lastPathComponent;
self.hidesHeaders = YES;
self.toolbarItems =
@ -84,34 +115,19 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
[self.tableView addGestureRecognizer:[[UILongPressGestureRecognizer alloc] initWithTarget:self
action:@selector(fileAction:)]];
self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithTitle:@"Up"
style:UIBarButtonItemStyleBordered target:self action:@selector(gotoParent)];
}
return self;
}
- (void)viewWillAppear:(BOOL)animated
- (void)browseTo:(NSString*)path
{
[self refresh];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self reset];
}
_path = path;
self.title = _path.lastPathComponent;
- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView
{
static NSArray* names = nil;
if (!names)
names = @[@"/", @"#", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L",
@"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z"];
return names;
}
- (void)refresh
{
// Need one array per section
self.sections = [NSMutableArray array];
@ -139,34 +155,36 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
}
else
apple_display_alert([NSString stringWithFormat:@"Browsed path is not a directory: %@", _path], 0);
[self.tableView reloadData];
[self.tableView scrollRectToVisible:CGRectMake(0, 0, 1, 1) animated:NO];
[UIView transitionWithView:self.tableView duration:.25f options:UIViewAnimationOptionTransitionCrossDissolve
animations:
^{
[self.tableView reloadData];
} completion:nil];
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
- (void)gotoParent
{
[self.directoryDelegate directoryList:self itemWasSelected:[self itemForIndexPath:indexPath]];
[self browseTo:[_path stringByDeletingLastPathComponent]];
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
- (void)viewWillAppear:(BOOL)animated
{
RADirectoryItem* path = [self itemForIndexPath:indexPath];
uint32_t type_id = path.isDirectory ? 1 : 0;
UITableViewCell* cell = nil;
static NSString* const cell_types[2] = { @"file", @"folder" };
if ([self getCellFor:cell_types[type_id] withStyle:UITableViewCellStyleDefault result:&cell])
{
static NSString* const icon_types[2] = { @"ic_file", @"ic_dir" };
cell.imageView.image = [UIImage imageNamed:icon_types[type_id]];
}
cell.textLabel.text = [path.path lastPathComponent];
return cell;
[super viewWillAppear:animated];
[self browseTo:_path];
}
- (NSArray*)sectionIndexTitlesForTableView:(UITableView*)tableView
{
static NSArray* names = nil;
if (!names)
names = @[@"/", @"#", @"A", @"B", @"C", @"D", @"E", @"F", @"G", @"H", @"I", @"J", @"K", @"L",
@"M", @"N", @"O", @"P", @"Q", @"R", @"S", @"T", @"U", @"V", @"W", @"X", @"Y", @"Z"];
return names;
}
// File management
// Called as a selector from a toolbar button
@ -245,95 +263,35 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
file_action(alertView.tag, self.selectedItem.path, [_path stringByAppendingPathComponent:text]);
}
[self refresh];
[self browseTo:_path];
}
@end
@implementation RAModuleList
- (id)initWithGame:(NSString*)path delegate:(id<RAModuleListDelegate>)delegate
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
{
[self setTitle:path ? [path lastPathComponent] : @"Cores"];
_moduleDelegate = delegate;
// Load the modules with their data
NSArray* moduleList = apple_get_modules();
NSMutableArray* supported = [NSMutableArray arrayWithObject:@"Suggested Cores"];
NSMutableArray* other = [NSMutableArray arrayWithObject:@"Other Cores"];
for (RAModuleInfo* i in moduleList)
{
if (path && [i supportsFileAtPath:path]) [supported addObject:i];
else [other addObject:i];
}
if (supported.count > 1)
[self.sections addObject:supported];
if (other.count > 1)
[self.sections addObject:other];
}
return self;
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
[self.moduleDelegate moduleList:self itemWasSelected:[self itemForIndexPath:indexPath]];
}
- (void)infoButtonTapped:(id)sender
{
RAModuleInfo* info = objc_getAssociatedObject(sender, associated_module_key);
if (info && info.data)
[self.navigationController pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:info] animated:YES];
else
apple_display_alert(@"No information available.", 0);
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
{
static NSString* const cell_id = @"module";
UITableViewCell* cell = nil;
if ([self getCellFor:cell_id withStyle:UITableViewCellStyleDefault result:&cell])
{
UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
[infoButton addTarget:self action:@selector(infoButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
cell.accessoryView = infoButton;
}
RAModuleInfo* info = (RAModuleInfo*)[self itemForIndexPath:indexPath];
cell.textLabel.text = info.description;
objc_setAssociatedObject(cell.accessoryView, associated_module_key, info, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return cell;
}
@interface RAFoldersList()
@property (nonatomic) NSString* path;
@end
@implementation RAFoldersList
{
NSString* _path;
}
- (id)initWithFilePath:(NSString*)path
{
self = [super initWithStyle:UITableViewStyleGrouped];
if (self)
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
RAFoldersList* __weak weakSelf = self;
_path = path;
// Parent item
NSString* sourceItem = _path.stringByDeletingLastPathComponent;
RAMenuItemBasic* parentItem = [RAMenuItemBasic itemWithDescription:@"<Parent>" association:sourceItem.stringByDeletingLastPathComponent
action:^(id userdata){ [weakSelf moveInto:userdata]; } detail:NULL];
[self.sections addObject:@[@"", parentItem]];
// List contents
struct string_list* contents = dir_list_new([_path stringByDeletingLastPathComponent].UTF8String, 0, true);
NSMutableArray* items = [NSMutableArray arrayWithObject:@""];
NSString* sourceDirectory = _path.stringByDeletingLastPathComponent;
if (contents)
{
@ -344,7 +302,10 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
if (contents->elems[i].attr.b)
{
const char* basename = path_basename(contents->elems[i].data);
[items addObject:[sourceDirectory stringByAppendingPathComponent:@(basename)]];
RAMenuItemBasic* item = [RAMenuItemBasic itemWithDescription:@(basename) association:@(contents->elems[i].data)
action:^(id userdata){ [weakSelf moveInto:userdata]; } detail:NULL];
[items addObject:item];
}
}
@ -352,29 +313,17 @@ static void file_action(enum file_action action, NSString* source, NSString* tar
}
[self setTitle:[@"Move " stringByAppendingString:_path.lastPathComponent]];
[self.sections addObject:@[@"", [sourceDirectory stringByDeletingLastPathComponent]]];
[self.sections addObject:items];
}
return self;
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath*)indexPath
- (void)moveInto:(NSString*)path
{
static NSString* const cell_id = @"Directory";
UITableViewCell* cell = nil;
[self getCellFor:cell_id withStyle:UITableViewCellStyleDefault result:&cell];
cell.textLabel.text = [[self itemForIndexPath:indexPath] lastPathComponent];
return cell;
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath*)indexPath
{
NSString* targetPath = [[self itemForIndexPath:indexPath] stringByAppendingPathComponent:_path.lastPathComponent];
file_action(FA_MOVE, _path, targetPath);
NSString* targetPath = [path stringByAppendingPathComponent:self.path.lastPathComponent];
file_action(FA_MOVE, self.path, targetPath);
[self.navigationController popViewControllerAnimated:YES];
}

197
apple/iOS/menu.h Normal file
View File

@ -0,0 +1,197 @@
/* 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/>.
*/
#ifndef __APPLE_RARCH_IOS_MENU_H__
#define __APPLE_RARCH_IOS_MENU_H__
#include "frontend/menu/history.h"
#include "views.h"
#include "apple/common/setting_data.h"
@protocol RAMenuItemBase
- (UITableViewCell*)cellForTableView:(UITableView*)tableView;
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller;
@end
/*********************************************/
/* RAMenuBase */
/* A menu class that displays RAMenuItemBase */
/* objects. */
/*********************************************/
@interface RAMenuBase : UITableViewController
@property (nonatomic) NSMutableArray* sections;
@property (nonatomic) BOOL hidesHeaders;
- (id)initWithStyle:(UITableViewStyle)style;
- (id)itemForIndexPath:(NSIndexPath*)indexPath;
@end
/*********************************************/
/* RAMenuItemBasic */
/* A simple menu item that displays a text */
/* description and calls a block object when */
/* selected. */
/*********************************************/
@interface RAMenuItemBasic : NSObject<RAMenuItemBase>
@property (nonatomic) NSString* description;
@property (nonatomic) id userdata;
@property (copy) void (^action)(id userdata);
@property (copy) NSString* (^detail)(id userdata);
+ (RAMenuItemBasic*)itemWithDescription:(NSString*)description association:(id)userdata action:(void (^)())action detail:(NSString* (^)())detail;
@end
/*********************************************/
/* RAMenuItemBooleanSetting */
/* A simple menu item that displays the */
/* state, and allows editing, of a boolean */
/* setting. */
/*********************************************/
@interface RAMenuItemBooleanSetting : NSObject<RAMenuItemBase>
@property (nonatomic) const rarch_setting_t* setting;
@end
/*********************************************/
/* RAMenuItemGeneralSetting */
/* A simple menu item that displays the */
/* state, and allows editing, of a string or */
/* numeric setting. */
/*********************************************/
@interface RAMenuItemGeneralSetting : NSObject<RAMenuItemBase>
@property (nonatomic) const rarch_setting_t* setting;
@property (nonatomic, weak) UITableView* parentTable;
@end
/*********************************************/
/* RAMenuItemPathSetting */
/* A menu item that displays and allows */
/* browsing for a path setting. */
/*********************************************/
@interface RAMenuItemPathSetting : RAMenuItemGeneralSetting<RAMenuItemBase> @end
/*********************************************/
/* RAMenuItemBindSetting */
/* A menu item that displays and allows */
/* mapping of a keybinding. */
/*********************************************/
@interface RAMenuItemBindSetting : RAMenuItemGeneralSetting<RAMenuItemBase> @end
/*********************************************/
/* RAMainMenu */
/* Menu object that is displayed immediately */
/* after startup. */
/*********************************************/
@interface RAMainMenu : RAMenuBase<RADirectoryListDelegate>
@property (nonatomic) NSString* core;
@end
/*********************************************/
/* RAHistoryMenu */
/* Menu object that displays and allows */
/* launching a file from the ROM history. */
/*********************************************/
@interface RAHistoryMenu : RAMenuBase
@property (nonatomic) rom_history_t* history;
- (id)initWithHistoryPath:(NSString*)historyPath;
@end
/*********************************************/
/* RASettingsGroupMenu */
/* Menu object that displays and allows */
/* editing of the a group of */
/* rarch_setting_t structures. */
/*********************************************/
@interface RASettingsGroupMenu : RAMenuBase
- (id)initWithGroup:(const rarch_setting_t*)settings;
@end
/*********************************************/
/* RACoreSettingsMenu */
/* Menu object that displays and allows */
/* editing of the setting_data list. */
/*********************************************/
@interface RACoreSettingsMenu : RAMenuBase
@property (nonatomic) NSString* core;
- (id)initWithCore:(NSString*)core;
@end
/*********************************************/
/* RAFrontendSettingsMenu */
/* Menu object that displays and allows */
/* editing of cocoa frontend related */
/* settings. */
/*********************************************/
@interface RAFrontendSettingsMenu : RASettingsGroupMenu @end
/*********************************************/
/* RACoreOptionsMenu */
/* Menu object that allows editing of */
/* options specific to the running core. */
/*********************************************/
@interface RACoreOptionsMenu : RAMenuBase @end
/*********************************************/
/* RAMenuItemCoreList */
/* Menu item that handles display and */
/* selection of an item in RAMenuCoreList. */
/* This item will not function on anything */
/* but an RAMenuCoreList type menu. */
/*********************************************/
@class RAMenuCoreList;
@interface RAMenuItemCoreList : NSObject<RAMenuItemBase>
@property (nonatomic, weak) RAMenuCoreList* parent;
@property (nonatomic) NSString* core;
@end
/*********************************************/
/* RAMenuCoreList */
/* Menu object that displays and allows */
/* selection from a list of cores. */
/* If the path is not nil, only cores that */
/* may support the file is listed. */
/* If the path is nil, an 'Auto Detect' */
/* entry is added to the menu, when tapped */
/* the action function will be called with */
/* nil as the argument. */
/*********************************************/
@interface RAMenuCoreList : RAMenuBase
@property (nonatomic) NSString* path;
@property (copy) void (^action)(NSString* coreID);
- (id)initWithPath:(NSString*)path action:(void (^)(NSString*))action;
@end
/*********************************************/
/* RALogMenu */
/* Displays a text file line-by-line. */
/*********************************************/
@interface RALogMenu : RAMenuBase
- (id)initWithFile:(const char*)path;
@end
/*********************************************/
/* RAMenuItemStateSelect */
/* Menu item that allows save state slots */
/* 0-9 to be selected. */
/*********************************************/
@interface RAMenuItemStateSelect : NSObject<RAMenuItemBase> @end
/*********************************************/
/* RAPauseMenu */
/* Menu which provides options for the */
/* currently running game. */
/*********************************************/
@interface RAPauseMenu : RAMenuBase @end
#endif

952
apple/iOS/menu.m Normal file
View File

@ -0,0 +1,952 @@
/* 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 <objc/runtime.h>
#include "apple/common/RetroArch_Apple.h"
#include "apple/common/apple_input.h"
#include "menu.h"
/*********************************************/
/* RAMenuBase */
/* A menu class that displays RAMenuItemBase */
/* objects. */
/*********************************************/
@implementation RAMenuBase
- (id)initWithStyle:(UITableViewStyle)style
{
if ((self = [super initWithStyle:style]))
self.sections = [NSMutableArray array];
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
return self.sections.count;
}
- (NSString*)tableView:(UITableView*)tableView titleForHeaderInSection:(NSInteger)section
{
return self.hidesHeaders ? nil : 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];
}
@end
/*********************************************/
/* RAMenuItemBasic */
/* A simple menu item that displays a text */
/* description and calls a block object when */
/* selected. */
/*********************************************/
@implementation RAMenuItemBasic
+ (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
/*********************************************/
/* RAMenuItemBooleanSetting */
/* A simple menu item that displays the */
/* state, and allows editing, of a boolean */
/* setting. */
/*********************************************/
@implementation RAMenuItemBooleanSetting
+ (RAMenuItemBooleanSetting*)itemForSetting:(const rarch_setting_t*)setting
{
RAMenuItemBooleanSetting* item = [RAMenuItemBooleanSetting new];
item.setting = setting;
return item;
}
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
{
static NSString* const cell_id = @"boolean_setting";
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
if (!result)
{
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
result.selectionStyle = UITableViewCellSelectionStyleNone;
result.accessoryView = [UISwitch new];
}
result.textLabel.text = @(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;
}
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
{
}
@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
+ (RAMenuItemGeneralSetting*)itemForSetting:(const rarch_setting_t*)setting
{
RAMenuItemGeneralSetting* item = [RAMenuItemGeneralSetting new];
item.setting = setting;
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;
}
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
{
static NSString* const cell_id = @"string_setting";
self.parentTable = tableView;
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
if (!result)
{
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
result.selectionStyle = UITableViewCellSelectionStyleNone;
}
char buffer[256];
result.textLabel.text = @(self.setting->short_description);
if (self.setting)
result.detailTextLabel.text = @(setting_data_get_string_representation(self.setting, buffer, sizeof(buffer)));
return result;
}
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
{
UIAlertView* alertView = [[UIAlertView alloc] initWithTitle:@"Enter new value" message:@(self.setting->short_description) delegate:self
cancelButtonTitle:@"Cancel" otherButtonTitles:@"OK", nil];
alertView.alertViewStyle = UIAlertViewStylePlainTextInput;
UITextField* field = [alertView textFieldAtIndex:0];
char buffer[256];
field.delegate = self.formatter;
field.placeholder = @(setting_data_get_string_representation(self.setting, buffer, sizeof(buffer)));
[alertView show];
}
- (void)alertView:(UIAlertView*)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString* text = [alertView textFieldAtIndex:0].text;
if (buttonIndex == alertView.firstOtherButtonIndex && text.length)
{
setting_data_set_with_string_representation(self.setting, text.UTF8String);
[self.parentTable reloadData];
}
}
@end
/*********************************************/
/* RAMenuItemPathSetting */
/* A menu item that displays and allows */
/* browsing for a path setting. */
/*********************************************/
@interface RAMenuItemPathSetting() <RADirectoryListDelegate> @end
@implementation RAMenuItemPathSetting
+ (RAMenuItemPathSetting*)itemForSetting:(const rarch_setting_t*)setting
{
RAMenuItemPathSetting* item = [RAMenuItemPathSetting new];
item.setting = setting;
return item;
}
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
{
RADirectoryList* list = [[RADirectoryList alloc] initWithPath:@"/" delegate:self];
[controller.navigationController pushViewController:list animated:YES];
}
- (bool)directoryList:(id)list itemWasSelected:(RADirectoryItem *)path
{
setting_data_set_with_string_representation(self.setting, path.path.UTF8String);
[[list navigationController] popViewControllerAnimated:YES];
[self.parentTable reloadData];
return true;
}
@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
+ (RAMenuItemBindSetting*)itemForSetting:(const rarch_setting_t*)setting
{
RAMenuItemBindSetting* item = [RAMenuItemBindSetting new];
item.setting = setting;
return item;
}
- (void)wasSelectedOnTableView:(UITableView *)tableView ofController:(UIViewController *)controller
{
self.alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@(self.setting->short_description)
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Clear Keyboard", @"Clear Joystick", @"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;
}
- (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;
if ((value = apple_input_find_any_key()))
BINDFOR(*self.setting).key = input_translate_keysym_to_rk(value);
else if ((value = apple_input_find_any_button(0)) >= 0)
BINDFOR(*self.setting).joykey = value;
else if ((value = apple_input_find_any_axis(0)))
BINDFOR(*self.setting).joyaxis = (value > 0) ? AXIS_POS(value - 1) : AXIS_NEG(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]))
{
RAMainMenu* __weak weakSelf = self;
self.title = @"RetroArch";
self.sections =
(id)@[
@[ @"",
[RAMenuItemBasic itemWithDescription:@"Choose Core"
action:^{ [weakSelf chooseCoreWithPath:nil]; }
detail:^{ return weakSelf.core ? apple_get_core_display_name(weakSelf.core) : @"Auto Detect"; }],
[RAMenuItemBasic itemWithDescription:@"Load Game" action:^{ [weakSelf loadGame]; }],
[RAMenuItemBasic itemWithDescription:@"Load Game (History)" action:^{ [weakSelf loadHistory]; }],
[RAMenuItemBasic itemWithDescription:@"Frontend Settings" action:^{ [[RetroArch_iOS get] showSystemSettings]; }]
]
];
}
return self;
}
- (void)chooseCoreWithPath:(NSString*)path
{
RAMainMenu* __weak weakSelf = self;
RAMenuCoreList* list = [[RAMenuCoreList alloc] initWithPath:path
action: ^(NSString* core)
{
if (path)
apple_run_core(weakSelf.core, path.UTF8String);
else
{
weakSelf.core = core;
[weakSelf.tableView reloadData];
[weakSelf.navigationController popViewControllerAnimated:YES];
}
}];
[self.navigationController pushViewController:list animated:YES];
}
- (void)loadGame
{
NSString* rootPath = RetroArch_iOS.get.documentsDirectory;
NSString* ragPath = [rootPath stringByAppendingPathComponent:@"RetroArchGames"];
NSString* target = path_is_directory(ragPath.UTF8String) ? ragPath : rootPath;
[self.navigationController pushViewController:[[RADirectoryList alloc] initWithPath:target delegate:self] animated:YES];
}
- (void)loadHistory
{
NSString* history_path = [NSString stringWithFormat:@"%@/%s", RetroArch_iOS.get.systemDirectory, ".retroarch-game-history.txt"];
[self.navigationController pushViewController:[[RAHistoryMenu alloc] initWithHistoryPath:history_path] animated:YES];
}
- (bool)directoryList:(id)list itemWasSelected:(RADirectoryItem*)path
{
if (!path.isDirectory)
{
if (self.core)
apple_run_core(self.core, path.path.UTF8String);
else
[self chooseCoreWithPath:path.path];
}
return true;
}
@end
/*********************************************/
/* RAHistoryMenu */
/* Menu object that displays and allows */
/* launching a file from the ROM history. */
/*********************************************/
@implementation RAHistoryMenu
- (id)initWithHistoryPath:(NSString *)historyPath
{
if ((self = [super initWithStyle:UITableViewStylePlain]))
{
RAHistoryMenu* __weak weakSelf = self;
_history = rom_history_init(historyPath.UTF8String, 100);
NSMutableArray* section = [NSMutableArray arrayWithObject:@""];
[self.sections addObject:section];
for (int i = 0; _history && i != rom_history_size(_history); i ++)
{
RAMenuItemBasic* item = [RAMenuItemBasic itemWithDescription:@(path_basename(apple_rom_history_get_path(weakSelf.history, i)))
action:^{ apple_run_core(@(apple_rom_history_get_core_path(weakSelf.history, i)),
apple_rom_history_get_path(weakSelf.history, i)); }
detail:^{ return @(apple_rom_history_get_core_name(weakSelf.history, i)); }];
[section addObject:item];
}
}
return self;
}
- (void)dealloc
{
rom_history_free(self.history);
}
@end
/*********************************************/
/* RASettingsGroupMenu */
/* Menu object that displays and allows */
/* editing of the a group of */
/* rarch_setting_t structures. */
/*********************************************/
@implementation RASettingsGroupMenu
- (id)initWithGroup:(const rarch_setting_t*)group
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
self.title = @(group->name);
NSMutableArray* settings = nil;
for (const rarch_setting_t* i = group + 1; i->type != ST_END_GROUP; i ++)
{
if (i->type == ST_SUB_GROUP)
settings = [NSMutableArray arrayWithObjects:@(i->name), nil];
else if (i->type == ST_END_SUB_GROUP)
{
if (settings.count)
[self.sections addObject:settings];
}
else if (i->type == ST_BOOL)
[settings addObject:[RAMenuItemBooleanSetting itemForSetting:i]];
else if (i->type == ST_INT || i->type == ST_UINT || i->type == ST_FLOAT || i->type == ST_STRING)
[settings addObject:[RAMenuItemGeneralSetting itemForSetting:i]];
else if (i->type == ST_PATH)
[settings addObject:[RAMenuItemPathSetting itemForSetting:i]];
else if (i->type == ST_BIND)
[settings addObject:[RAMenuItemBindSetting itemForSetting:i]];
}
}
return self;
}
@end
/*********************************************/
/* RACoreSettingsMenu */
/* Menu object that displays and allows */
/* editing of the setting_data list. */
/*********************************************/
@interface RACoreSettingsMenu()
@property (nonatomic) NSString* pathToSave; // < Leave nil to not save
@end
@implementation RACoreSettingsMenu
- (id)initWithCore:(NSString*)core
{
char buffer[PATH_MAX];
RACoreSettingsMenu* __weak weakSelf = self;
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
if (apple_core_info_has_custom_config(core.UTF8String))
_pathToSave = @(apple_core_info_get_custom_config(core.UTF8String, buffer, sizeof(buffer)));
else
_pathToSave = apple_platform.globalConfigFile;
const rarch_setting_t* setting_data = setting_data_get_list();
setting_data_reset(setting_data);
setting_data_load_config_path(setting_data, _pathToSave.UTF8String);
// HACK: Load the key mapping table
apple_input_find_any_key();
self.core = core;
self.title = self.core ? apple_get_core_display_name(core) : @"Global Core Config";
NSMutableArray* settings = [NSMutableArray arrayWithObjects:@"", nil];
[self.sections addObject:settings];
for (const rarch_setting_t* i = setting_data; i->type != ST_NONE; i ++)
if (i->type == ST_GROUP)
[settings addObject:[RAMenuItemBasic itemWithDescription:@(i->name) action:
^{
[weakSelf.navigationController pushViewController:[[RASettingsGroupMenu alloc] initWithGroup:i] animated:YES];
}]];
[settings addObject:[RAMenuItemBasic itemWithDescription:@"Core Options"
action:^{ [weakSelf.navigationController pushViewController:[RACoreOptionsMenu new] animated:YES]; }]];
}
return self;
}
- (void)dealloc
{
if (self.pathToSave)
{
config_file_t* config = config_file_new(self.pathToSave.UTF8String);
if (!config)
config = config_file_new(0);
setting_data_save_config(setting_data_get_list(), config);
config_set_string(config, "system_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
config_set_string(config, "savefile_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
config_set_string(config, "savestate_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
config_file_write(config, self.pathToSave.UTF8String);
config_file_free(config);
}
}
@end
/*********************************************/
/* RAFrontendSettingsMenu */
/* Menu object that displays and allows */
/* editing of cocoa frontend related */
/* settings. */
/*********************************************/
static const void* const associated_core_key = &associated_core_key;
@interface RAFrontendSettingsMenu() <UIAlertViewDelegate> @end
@implementation RAFrontendSettingsMenu
- (id)init
{
const rarch_setting_t* apple_get_frontend_settings();
const rarch_setting_t* frontend_setting_data = apple_get_frontend_settings();
if ((self = [super initWithGroup:frontend_setting_data]))
{
RAFrontendSettingsMenu* __weak weakSelf = self;
self.title = @"Frontend Settings";
RAMenuItemBasic* diagnostic_item = [RAMenuItemBasic itemWithDescription:@"Diagnostic Log"
action:^{ [weakSelf.navigationController pushViewController:[[RALogMenu alloc] initWithFile:RetroArch_iOS.get.logPath.UTF8String] animated:YES]; }];
[self.sections insertObject:@[@"", diagnostic_item] atIndex:0];
// Core items to load core settings
NSMutableArray* cores = [NSMutableArray arrayWithObject:@"Cores"];
[cores addObject:[RAMenuItemBasic itemWithDescription:@"Global Core Config"
action: ^{ [weakSelf showCoreConfigFor:nil]; }]];
const core_info_list_t* core_list = apple_core_info_list_get();
for (int i = 0; i < core_list->count; i ++)
[cores addObject:[RAMenuItemBasic itemWithDescription:@(core_list->list[i].display_name)
association:apple_get_core_id(&core_list->list[i])
action: ^(id userdata) { [weakSelf showCoreConfigFor:userdata]; }
detail: ^(id userdata) { return apple_core_info_has_custom_config([userdata UTF8String]) ? @"[Custom]" : @"[Global]"; }]];
[self.sections addObject:cores];
}
return self;
}
- (void)dealloc
{
const rarch_setting_t* apple_get_frontend_settings();
setting_data_save_config_path(apple_get_frontend_settings(), [RetroArch_iOS get].systemConfigPath.UTF8String);
[[RetroArch_iOS get] refreshSystemConfig];
}
- (void)showCoreConfigFor:(NSString*)core
{
if (core && !apple_core_info_has_custom_config(core.UTF8String))
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@"No custom configuration for this core exists, "
"would you like to create one?"
delegate:self
cancelButtonTitle:@"No"
otherButtonTitles:@"Yes", nil];
objc_setAssociatedObject(alert, associated_core_key, core, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[alert show];
}
else
[self.navigationController pushViewController:[[RACoreSettingsMenu alloc] initWithCore:core] animated:YES];
}
- (void)alertView:(UIAlertView *)alertView clickedButtonAtIndex:(NSInteger)buttonIndex
{
NSString* core_id = objc_getAssociatedObject(alertView, associated_core_key);
if (buttonIndex == alertView.firstOtherButtonIndex && core_id)
{
char path[PATH_MAX];
apple_core_info_get_custom_config(core_id.UTF8String, path, sizeof(path));
if (![[NSFileManager defaultManager] copyItemAtPath:apple_platform.globalConfigFile toPath:@(path) error:nil])
RARCH_WARN("Could not create custom config at %s", path);
[self.tableView reloadData];
}
[self.navigationController pushViewController:[[RACoreSettingsMenu alloc] initWithCore:core_id] animated:YES];
}
@end
/*********************************************/
/* RACoreOptionsMenu */
/* Menu object that allows editing of */
/* options specific to the running core. */
/*********************************************/
@interface RACoreOptionsMenu() <UIActionSheetDelegate>
@property (nonatomic) uint32_t currentIndex;
@end
@implementation RACoreOptionsMenu
- (id)init
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
RACoreOptionsMenu* __weak weakSelf = self;
core_option_manager_t* options = g_extern.system.core_options;
NSMutableArray* section = [NSMutableArray arrayWithObject:@""];
[self.sections addObject:section];
if (options)
{
for (int i = 0; i != core_option_size(options); i ++)
[section addObject:[RAMenuItemBasic itemWithDescription:@(core_option_get_desc(options, i)) association:nil
action:^{ [weakSelf editValue:i]; }
detail:^{ return @(core_option_get_val(options, i)); }]];
}
else
[section addObject:[RAMenuItemBasic itemWithDescription:@"The running core has no options." action:NULL]];
}
return self;
}
- (void)editValue:(uint32_t)index
{
self.currentIndex = index;
UIActionSheet* sheet = [UIActionSheet new];
sheet.title = @(core_option_get_desc(g_extern.system.core_options, index));
sheet.delegate = self;
struct string_list* values = core_option_get_vals(g_extern.system.core_options, index);
for (int i = 0; i != values->size; i ++)
[sheet addButtonWithTitle:@(values->elems[i].data)];
[sheet addButtonWithTitle:@"Cancel"];
sheet.cancelButtonIndex = sheet.numberOfButtons - 1;
[sheet showInView:self.tableView];
}
- (void)actionSheet:(UIActionSheet*)actionSheet clickedButtonAtIndex:(NSInteger)buttonIndex
{
if (buttonIndex != actionSheet.cancelButtonIndex)
core_option_set_val(g_extern.system.core_options, self.currentIndex, buttonIndex);
[self.tableView reloadData];
}
@end
/*********************************************/
/* RAMenuItemCoreList */
/* Menu item that handles display and */
/* selection of an item in RAMenuCoreList. */
/* This item will not function on anything */
/* but an RAMenuCoreList type menu. */
/*********************************************/
@implementation RAMenuItemCoreList
- (id)initWithCore:(NSString*)core parent:(RAMenuCoreList* __weak)parent
{
if ((self = [super init]))
{
_core = core;
_parent = parent;
}
return self;
}
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
{
static NSString* const cell_id = @"RAMenuItemCoreList";
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
if (!result)
{
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
// UIButton* infoButton = [UIButton buttonWithType:UIButtonTypeInfoDark];
// [infoButton addTarget:self action:@selector(infoButtonTapped:) forControlEvents:UIControlEventTouchUpInside];
// result.accessoryView = infoButton;
}
result.textLabel.text = apple_get_core_display_name(self.core);
return result;
}
- (void)wasSelectedOnTableView:(UITableView*)tableView ofController:(UIViewController*)controller
{
if (self.parent.action)
self.parent.action(self.core);
}
@end
/*********************************************/
/* RAMenuCoreList */
/* Menu object that displays and allows */
/* selection from a list of cores. */
/* If the path is not nil, only cores that */
/* may support the file is listed. */
/* If the path is nil, an 'Auto Detect' */
/* entry is added to the menu, when tapped */
/* the action function will be called with */
/* nil as the argument. */
/*********************************************/
@implementation RAMenuCoreList
- (id)initWithPath:(NSString*)path action:(void (^)(NSString *))action
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
self.title = @"Choose Core";
_action = action;
_path = path;
if (!_path)
{
RAMenuCoreList* __weak weakSelf = self;
[self.sections addObject: @[@"", [RAMenuItemBasic itemWithDescription:@"Auto Detect"
action: ^{ if(weakSelf.action) weakSelf.action(nil); }]]];
}
NSMutableArray* core_section = [NSMutableArray arrayWithObject:@"Cores"];
[self.sections addObject:core_section];
core_info_list_t* core_list = apple_core_info_list_get();
if (core_list)
{
if (!_path)
[self load:core_list->count coresFromList:core_list->list toSection:core_section];
else
{
const core_info_t* core_support = 0;
size_t core_count = 0;
core_info_list_get_supported_cores(core_list, _path.UTF8String, &core_support, &core_count);
if (core_count == 1 && _action)
_action(apple_get_core_id(&core_support[0]));
else if (core_count > 1)
[self load:core_count coresFromList:core_support toSection:core_section];
}
}
}
return self;
}
- (void)load:(uint32_t)count coresFromList:(const core_info_t*)list toSection:(NSMutableArray*)array
{
for (int i = 0; i < count; i ++)
[array addObject:[[RAMenuItemCoreList alloc] initWithCore:apple_get_core_id(&list[i]) parent:self]];
}
@end
/*********************************************/
/* RALogMenu */
/* Displays a text file line-by-line. */
/*********************************************/
@implementation RALogMenu
- (id)initWithFile:(const char*)path
{
if ((self = [super initWithStyle:UITableViewStylePlain]))
{
NSMutableArray* data = [NSMutableArray arrayWithObject:@""];
fflush(stdout);
fflush(stderr);
FILE* file = fopen(path, "r");
if (file)
{
char buffer[1024];
while (fgets(buffer, 1024, file))
[data addObject:[RAMenuItemBasic itemWithDescription:@(buffer) action:NULL]];
fclose(file);
}
else
[data addObject:[RAMenuItemBasic itemWithDescription:@"Logging not enabled" action:NULL]];
[self.sections addObject:data];
}
return self;
}
@end
/*********************************************/
/* RAMenuItemStateSelect */
/* Menu item that allows save state slots */
/* 0-9 to be selected. */
/*********************************************/
@implementation RAMenuItemStateSelect
- (UITableViewCell*)cellForTableView:(UITableView*)tableView
{
static NSString* const cell_id = @"state_slot_setting";
UITableViewCell* result = [tableView dequeueReusableCellWithIdentifier:cell_id];
if (!result)
{
result = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
result.selectionStyle = UITableViewCellSelectionStyleNone;
result.textLabel.text = @"Slot";
UISegmentedControl* accessory = [[UISegmentedControl alloc] initWithItems:@[@"0", @"1", @"2", @"3", @"4", @"5", @"6", @"7", @"8", @"9"]];
[accessory addTarget:self action:@selector(changed:) forControlEvents:UIControlEventValueChanged];
accessory.segmentedControlStyle = UISegmentedControlStyleBar;
result.accessoryView = accessory;
}
[(id)result.accessoryView setSelectedSegmentIndex:(g_extern.state_slot < 10) ? g_extern.state_slot : -1];
return result;
}
- (void)changed:(UISegmentedControl*)sender
{
g_extern.state_slot = sender.selectedSegmentIndex;
}
- (void)wasSelectedOnTableView:(UITableView *)tableView ofController:(UIViewController *)controller
{
}
@end
/*********************************************/
/* RAPauseMenu */
/* Menu which provides options for the */
/* currently running game. */
/*********************************************/
@implementation RAPauseMenu
- (id)init
{
if ((self = [super initWithStyle:UITableViewStyleGrouped]))
{
RAPauseMenu* __weak weakSelf = self;
[self.sections addObject:@[@"Actions",
[RAMenuItemBasic itemWithDescription:@"Reset Game" action:^{ [weakSelf performBasicAction:RESET]; }],
[RAMenuItemBasic itemWithDescription:@"Close Game" action:^{ [weakSelf performBasicAction:QUIT]; }]
]];
[self.sections addObject:@[@"States",
[RAMenuItemStateSelect new],
[RAMenuItemBasic itemWithDescription:@"Load State" action:^{ [weakSelf performBasicAction:LOAD_STATE]; }],
[RAMenuItemBasic itemWithDescription:@"Save State" action:^{ [weakSelf performBasicAction:SAVE_STATE]; }]
]];
[self.sections addObject:@[@"Settings",
[RAMenuItemBasic itemWithDescription:@"System Config" action:^{ [[RetroArch_iOS get] showSystemSettings]; }],
[RAMenuItemBasic itemWithDescription:@"Core Config" action:^{ [[RetroArch_iOS get] showSettings]; }]
]];
}
return self;
}
- (void)performBasicAction:(enum basic_event_t)action
{
[self.navigationController popViewControllerAnimated:(action != QUIT)];
apple_frontend_post_event(apple_event_basic_command, action);
}
@end

View File

@ -21,21 +21,21 @@
@interface RAGameView : UIViewController
+ (RAGameView*)get;
- (void)openPauseMenu;
- (void)closePauseMenu;
- (void)iOS7SetiCadeMode:(bool)on;
@end
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate, RetroArch_Platform,
RADirectoryListDelegate, RAModuleListDelegate>
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate, RetroArch_Platform>
+ (RetroArch_iOS*)get;
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
- (void)loadingCore:(NSString*)core withFile:(const char*)file;
- (void)unloadingCore:(NSString*)core;
- (void)refreshSystemConfig;
- (IBAction)showSettings;
- (IBAction)showSystemSettings;
@property (nonatomic) NSString* configDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (nonatomic) NSString* globalConfigFile; // e.g. /var/mobile/Documents/.RetroArch/retroarch.cfg
@property (nonatomic) NSString* coreDirectory; // e.g. /Applications/RetroArch.app/modules
@ -43,6 +43,7 @@
@property (nonatomic) NSString* documentsDirectory; // e.g. /var/mobile/Documents
@property (nonatomic) NSString* systemDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (nonatomic) NSString* systemConfigPath; // e.g. /var/mobile/Documents/.RetroArch/frontend.cfg
@property (nonatomic) NSString* logPath;
@end

View File

@ -20,6 +20,8 @@
#include "rarch_wrapper.h"
#include "apple/common/apple_input.h"
#include "apple/common/setting_data.h"
#include "menu.h"
#import "views.h"
#include "bluetooth/btpad.h"
@ -28,6 +30,57 @@
#include "file.h"
static struct
{
bool portrait;
bool portrait_upside_down;
bool landscape_left;
bool landscape_right;
bool logging_enabled;
char bluetooth_mode[64];
struct
{
int stdout;
int stderr;
FILE* file;
} logging;
} apple_frontend_settings;
const rarch_setting_t* apple_get_frontend_settings()
{
static rarch_setting_t settings[16];
settings[0] = setting_data_group_setting(ST_GROUP, "Frontend Settings");
settings[1] = setting_data_group_setting(ST_SUB_GROUP, "Frontend");
settings[2] = setting_data_bool_setting("ios_use_file_log", "Enable File Logging",
&apple_frontend_settings.logging_enabled, false);
settings[3] = setting_data_bool_setting("ios_tv_mode", "TV Mode", &apple_use_tv_mode, false);
settings[4] = setting_data_group_setting(ST_END_SUB_GROUP, 0);
settings[5] = setting_data_group_setting(ST_SUB_GROUP, "Bluetooth");
settings[6] = setting_data_string_setting("ios_btmode", "Mode", apple_frontend_settings.bluetooth_mode,
sizeof(apple_frontend_settings.bluetooth_mode), "keyboard");
settings[7] = setting_data_group_setting(ST_END_SUB_GROUP, 0);
settings[8] = setting_data_group_setting(ST_SUB_GROUP, "Orientations");
settings[9] = setting_data_bool_setting("ios_allow_portrait", "Portrait",
&apple_frontend_settings.portrait, true);
settings[10] = setting_data_bool_setting("ios_allow_portrait_upside_down", "Portrait Upside Down",
&apple_frontend_settings.portrait_upside_down, true);
settings[11] = setting_data_bool_setting("ios_allow_landscape_left", "Landscape Left",
&apple_frontend_settings.landscape_left, true);
settings[12] = setting_data_bool_setting("ios_allow_landscape_right", "Landscape Right",
&apple_frontend_settings.landscape_right, true);
settings[13] = setting_data_group_setting(ST_END_SUB_GROUP, 0);
settings[14] = setting_data_group_setting(ST_END_GROUP, 0);
return settings;
}
//#define HAVE_DEBUG_FILELOG
bool is_ios_7()
{
@ -51,6 +104,29 @@ void ios_set_bluetooth_mode(NSString* mode)
#endif
}
void ios_set_logging_state(bool on)
{
fflush(stdout);
fflush(stderr);
if (on && !apple_frontend_settings.logging.file)
{
apple_frontend_settings.logging.file = fopen([RetroArch_iOS get].logPath.UTF8String, "a");
apple_frontend_settings.logging.stdout = dup(1);
apple_frontend_settings.logging.stderr = dup(2);
dup2(fileno(apple_frontend_settings.logging.file), 1);
dup2(fileno(apple_frontend_settings.logging.file), 2);
}
else if (!on && apple_frontend_settings.logging.file)
{
dup2(apple_frontend_settings.logging.stdout, 1);
dup2(apple_frontend_settings.logging.stderr, 2);
fclose(apple_frontend_settings.logging.file);
apple_frontend_settings.logging.file = 0;
}
}
// Input helpers: This is kept here because it needs objective-c
static void handle_touch_event(NSArray* touches)
{
@ -106,7 +182,7 @@ static void handle_touch_event(NSArray* touches)
{
key_commands = [NSMutableArray array];
for (int i = 0; i != 26; i ++)
for (int i = 0; i < 26; i ++)
{
[key_commands addObject:[UIKeyCommand keyCommandWithInput:[NSString stringWithFormat:@"%c", 'a' + i]
modifierFlags:0 action:@selector(keyGotten:)]];
@ -130,8 +206,7 @@ static void handle_touch_event(NSArray* touches)
UIWindow* _window;
NSString* _path;
bool _isGameTop, _isRomList;
uint32_t _settingMenusInBackStack;
bool _isGameTop;
uint32_t _enabledOrientations;
}
@ -159,6 +234,7 @@ static void handle_touch_event(NSArray* touches)
self.configDirectory = self.systemDirectory;
self.globalConfigFile = [NSString stringWithFormat:@"%@/retroarch.cfg", self.configDirectory];
self.coreDirectory = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"modules"];
self.logPath = [self.systemDirectory stringByAppendingPathComponent:@"stdout.log"];
const char *path = self.documentsDirectory.UTF8String;
path_mkdir(path);
@ -171,11 +247,15 @@ static void handle_touch_event(NSArray* touches)
if (access(path, 0755) != 0)
apple_display_alert([NSString stringWithFormat:@"Failed to create or access system directory: %@", self.systemDirectory], 0);
else
[self beginBrowsingForFile];
[self pushViewController:[RAMainMenu new] animated:YES];
}
// Warn if there are no cores present
if (apple_get_modules().count == 0)
apple_core_info_set_core_path(self.coreDirectory.UTF8String);
apple_core_info_set_config_path(self.configDirectory.UTF8String);
const core_info_list_t* core_list = apple_core_info_list_get();
if (!core_list || core_list->count == 0)
apple_display_alert(@"No libretro cores were found. You will not be able to play any games.", 0);
}
@ -203,77 +283,19 @@ static void handle_touch_event(NSArray* touches)
return true;
}
- (void)beginBrowsingForFile
{
NSString* rootPath = RetroArch_iOS.get.documentsDirectory;
NSString* ragPath = [rootPath stringByAppendingPathComponent:@"RetroArchGames"];
NSString* target = path_is_directory(ragPath.UTF8String) ? ragPath : rootPath;
[self pushViewController:[[RADirectoryList alloc] initWithPath:target delegate:self] animated:YES];
[self refreshSystemConfig];
if (apple_use_tv_mode)
apple_run_core(nil, 0);
}
- (bool)directoryList:(id)list itemWasSelected:(RADirectoryItem*)path
{
if(path.isDirectory)
[self pushViewController:[[RADirectoryList alloc] initWithPath:path.path delegate:self] animated:YES];
else
{
_path = path.path;
if (access([path.path stringByDeletingLastPathComponent].UTF8String, R_OK | W_OK | X_OK))
apple_display_alert(@"The directory containing the selected file has limited permissions. This may "
"prevent zipped games from loading, and will cause some cores to not function.", 0);
[self pushViewController:[[RAModuleList alloc] initWithGame:path.path delegate:self] animated:YES];
}
return true;
}
- (bool)moduleList:(id)list itemWasSelected:(RAModuleInfo*)module
{
apple_run_core(module, _path.UTF8String);
return true;
}
// UINavigationControllerDelegate
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
{
apple_input_reset_icade_buttons();
_isGameTop = [viewController isKindOfClass:[RAGameView class]];
_isRomList = [viewController isKindOfClass:[RADirectoryList class]];
g_extern.is_paused = !_isGameTop;
[[UIApplication sharedApplication] setStatusBarHidden:_isGameTop withAnimation:UIStatusBarAnimationNone];
[[UIApplication sharedApplication] setIdleTimerDisabled:_isGameTop];
self.navigationBarHidden = _isGameTop;
[self setToolbarHidden:!_isRomList animated:YES];
self.topViewController.navigationItem.rightBarButtonItem = [self createSettingsButton];
}
// UINavigationController: Never animate when pushing onto, or popping, an RAGameView
- (void)pushViewController:(UIViewController*)theView animated:(BOOL)animated
{
apple_input_reset_icade_buttons();
if ([theView respondsToSelector:@selector(isSettingsView)] && [(id)theView isSettingsView])
_settingMenusInBackStack ++;
[super pushViewController:theView animated:animated && !_isGameTop];
}
- (UIViewController*)popViewControllerAnimated:(BOOL)animated
{
apple_input_reset_icade_buttons();
if ([self.topViewController respondsToSelector:@selector(isSettingsView)] && [(id)self.topViewController isSettingsView])
_settingMenusInBackStack --;
return [super popViewControllerAnimated:animated && !_isGameTop];
[self setNavigationBarHidden:_isGameTop animated:!_isGameTop];
[self setToolbarHidden:!viewController.toolbarItems.count animated:YES];
}
// NOTE: This version only runs on iOS6
@ -304,17 +326,17 @@ static void handle_touch_event(NSArray* touches)
#pragma mark RetroArch_Platform
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
- (void)loadingCore:(NSString*)core withFile:(const char*)file
{
[self pushViewController:RAGameView.get animated:NO];
[RASettingsList refreshModuleConfig:core];
(void)[[RACoreSettingsMenu alloc] initWithCore:core];
btpad_set_inquiry_state(false);
[self refreshSystemConfig];
}
- (void)unloadingCore:(RAModuleInfo*)core
- (void)unloadingCore:(NSString*)core
{
[self popToViewController:[RAGameView get] animated:NO];
[self popViewControllerAnimated:NO];
@ -325,104 +347,46 @@ static void handle_touch_event(NSArray* touches)
#pragma mark FRONTEND CONFIG
- (void)refreshSystemConfig
{
// Read load time settings
config_file_t* conf = config_file_new([self.systemConfigPath UTF8String]);
const rarch_setting_t* frontend_settings = apple_get_frontend_settings();
setting_data_reset(frontend_settings);
setting_data_load_config_path(frontend_settings, self.systemConfigPath.UTF8String);
// Get enabled orientations
static const struct { const char* setting; uint32_t orientation; } orientationSettings[4] =
static const struct { const bool* value; uint32_t orientation; } orientationSettings[4] =
{
{ "ios_allow_portrait", UIInterfaceOrientationMaskPortrait },
{ "ios_allow_portrait_upside_down", UIInterfaceOrientationMaskPortraitUpsideDown },
{ "ios_allow_landscape_left", UIInterfaceOrientationMaskLandscapeLeft },
{ "ios_allow_landscape_right", UIInterfaceOrientationMaskLandscapeRight }
{ &apple_frontend_settings.portrait, UIInterfaceOrientationMaskPortrait },
{ &apple_frontend_settings.portrait_upside_down, UIInterfaceOrientationMaskPortraitUpsideDown },
{ &apple_frontend_settings.landscape_left, UIInterfaceOrientationMaskLandscapeLeft },
{ &apple_frontend_settings.landscape_right, UIInterfaceOrientationMaskLandscapeRight }
};
_enabledOrientations = 0;
for (int i = 0; i < 4; i ++)
{
bool enabled = false;
bool found = conf && config_get_bool(conf, orientationSettings[i].setting, &enabled);
if (!found || enabled)
_enabledOrientations |= orientationSettings[i].orientation;
}
_enabledOrientations |= (*orientationSettings[i].value) ? orientationSettings[i].orientation : 0;
if (conf)
{
// Setup bluetooth mode
ios_set_bluetooth_mode(objc_get_value_from_config(conf, @"ios_btmode", @"keyboard"));
bool val;
apple_use_tv_mode = config_get_bool(conf, "ios_tv_mode", &val) && val;
config_file_free(conf);
}
// Set bluetooth mode
ios_set_bluetooth_mode(@(apple_frontend_settings.bluetooth_mode));
ios_set_logging_state(apple_frontend_settings.logging_enabled);
}
#pragma mark PAUSE MENU
- (UIBarButtonItem*)createSettingsButton
{
if (_settingMenusInBackStack == 0)
return [[UIBarButtonItem alloc]
initWithTitle:@"Settings"
style:UIBarButtonItemStyleBordered
target:[RetroArch_iOS get]
action:@selector(showSystemSettings)];
else
return nil;
}
- (IBAction)showPauseMenu:(id)sender
{
if (apple_is_running && !apple_is_paused && _isGameTop)
{
apple_is_paused = true;
[[RAGameView get] openPauseMenu];
btpad_set_inquiry_state(true);
}
}
- (IBAction)basicEvent:(id)sender
{
if (apple_is_running)
apple_frontend_post_event(&apple_event_basic_command, ((UIView*)sender).tag);
[self closePauseMenu:sender];
}
- (IBAction)chooseState:(id)sender
{
if (apple_is_running)
apple_frontend_post_event(apple_event_set_state_slot, (void*)((UISegmentedControl*)sender).selectedSegmentIndex);
}
- (IBAction)showRGUI:(id)sender
{
if (apple_is_running)
apple_frontend_post_event(apple_event_show_rgui, 0);
[self closePauseMenu:sender];
}
- (IBAction)closePauseMenu:(id)sender
{
[[RAGameView get] closePauseMenu];
apple_is_paused = false;
btpad_set_inquiry_state(false);
[self pushViewController:[RAPauseMenu new] animated:YES];
}
- (IBAction)showSettings
{
[self pushViewController:[[RASettingsList alloc] initWithModule:apple_core] animated:YES];
[self pushViewController:[[RACoreSettingsMenu alloc] initWithCore:apple_core] animated:YES];
}
- (IBAction)showSystemSettings
{
[self pushViewController:[RASystemSettingsList new] animated:YES];
[self pushViewController:[RAFrontendSettingsMenu new] animated:YES];
}
@end
@ -430,13 +394,7 @@ static void handle_touch_event(NSArray* touches)
int main(int argc, char *argv[])
{
@autoreleasepool {
#if defined(HAVE_DEBUG_FILELOG) && (TARGET_IPHONE_SIMULATOR == 0)
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
NSString *documentsDirectory = [paths objectAtIndex:0];
NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console_stdout.log"];
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stdout);
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stderr);
#endif
return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class]));
}
}

View File

@ -1,890 +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 "apple/common/RetroArch_Apple.h"
#import "views.h"
#include "apple/common/apple_input.h"
#include "apple/common/keycode.h"
#include "bluetooth/btdynamic.h"
#include "bluetooth/btpad.h"
static const void* const associated_userdata_key = &associated_userdata_key;
static const void* const associated_module_key = &associated_module_key;
static const void* const associated_setting_key = &associated_setting_key;
enum SettingTypes
{
BooleanSetting, ButtonSetting, EnumerationSetting, FileListSetting,
GroupSetting, AspectSetting, RangeSetting, CustomAction
};
@interface RASettingData : NSObject
{
@public
enum SettingTypes type;
NSString* label; // < The label displayed in the settings menu
NSString* name; // < The key name of the value in the config file
NSString* value; // < The current state of the setting
uint32_t player; // < The player that a ButtonSetting represents
NSString* button_bind; // < The Gamepad button binding string
NSString* axis_bind; // < The Gamepad axis binding string
NSString* path; // < The base path for FileListSettings
NSArray* subValues; // < The available options for EnumerationSettings and FileListSettings
bool haveNoneOption; // < Determines if a 'None' option is added to an Enumeration or FileList
bool haveDescriptions; // < Determines if subValues containts friendly descriptions for each value
double rangeMin; // < The mininum value of a range setting
double rangeMax; // < The maximum value of a range setting
void (*changed)(RASettingData* action);
void (*reload)(RASettingData* action, id userdata);
}
- (void)setValue:(NSString*)aValue;
@end
@implementation RASettingData
- (id)initWithType:(enum SettingTypes)aType label:(NSString*)aLabel name:(NSString*)aName
{
type = aType;
label = aLabel;
name = aName;
return self;
}
- (void)setValue:(NSString*)aValue;
{
value = aValue;
if (changed)
changed(self);
}
- (uint32_t)enumerationCount
{
return subValues.count / (haveDescriptions ? 2 : 1);
}
- (NSString*)valueForEnumerationIndex:(uint32_t)index
{
return subValues[index * (haveDescriptions ? 2 : 1)];
}
- (NSString*)labelForEnumerationIndex:(uint32_t)index
{
return subValues[index * (haveDescriptions ? 2 : 1) + (haveDescriptions ? 1 : 0)];
}
- (NSString*)labelForEnumerationValue
{
const uint32_t count = self.enumerationCount;
for (int i = 0; haveDescriptions && i < count; i ++)
{
if ([value isEqualToString:subValues[i * 2]])
return subValues[i * 2 + 1];
}
return value;
}
@end
// Helper view definitions
@interface RAButtonGetter : NSObject<UIAlertViewDelegate>
- (id)initFromTable:(UITableView*)table;
- (void)runForSetting:(RASettingData*)setting;
@end
@interface RASettingEnumerationList : UITableViewController
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table;
@end
static RASettingData* boolean_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue)
{
RASettingData* result = [[RASettingData alloc] initWithType:BooleanSetting label:label name:name];
result->value = objc_get_value_from_config(config, name, defaultValue);
return result;
}
static RASettingData* button_setting(config_file_t* config, uint32_t player, NSString* name, NSString* label, NSString* defaultValue)
{
NSString* realname = player ? [NSString stringWithFormat:@"input_player%d_%@", player, name] : name;
RASettingData* result = [[RASettingData alloc] initWithType:ButtonSetting label:label name:realname];
result->player = player ? player - 1 : 0;
result->value = objc_get_value_from_config(config, realname, defaultValue);
result->button_bind = objc_get_value_from_config(config, [realname stringByAppendingString:@"_btn"], @"nul");
result->axis_bind = objc_get_value_from_config(config, [realname stringByAppendingString:@"_axis"], @"nul");
return result;
}
static RASettingData* group_setting(NSString* label, NSArray* settings)
{
RASettingData* result = [[RASettingData alloc] initWithType:GroupSetting label:label name:nil];
result->subValues = settings;
return result;
}
static RASettingData* enumeration_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, NSArray* values, bool haveDescriptions)
{
RASettingData* result = [[RASettingData alloc] initWithType:EnumerationSetting label:label name:name];
result->value = objc_get_value_from_config(config, name, defaultValue);
result->subValues = values;
result->haveDescriptions = haveDescriptions;
return result;
}
static RASettingData* subpath_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, NSString* path, NSString* extension)
{
NSString* value = objc_get_value_from_config(config, name, defaultValue);
value = [value stringByReplacingOccurrencesOfString:path withString:@""];
NSArray* values = [[NSFileManager defaultManager] subpathsOfDirectoryAtPath:path error:nil];
values = [values pathsMatchingExtensions:[NSArray arrayWithObject:extension]];
RASettingData* result = [[RASettingData alloc] initWithType:FileListSetting label:label name:name];
result->value = value;
result->subValues = values;
result->path = path;
result->haveNoneOption = true;
return result;
}
static RASettingData* range_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, double minValue, double maxValue)
{
RASettingData* result = [[RASettingData alloc] initWithType:RangeSetting label:label name:name];
result->value = objc_get_value_from_config(config, name, defaultValue);
result->rangeMin = minValue;
result->rangeMax = maxValue;
return result;
}
static RASettingData* aspect_setting(config_file_t* config, NSString* label)
{
// Why does this need to be so difficult?
RASettingData* result = [[RASettingData alloc] initWithType:AspectSetting label:label name:@""];
result->subValues = [NSArray arrayWithObjects:@"Fill Screen", @"Game Aspect", @"Pixel Aspect", @"4:3", @"16:9", nil];
bool videoForceAspect = true;
bool videoAspectAuto = false;
double videoAspect = -1.0;
if (config)
{
config_get_bool(config, "video_force_aspect", &videoForceAspect);
config_get_bool(config, "video_aspect_auto", &videoAspectAuto);
config_get_double(config, "video_aspect_ratio", &videoAspect);
}
if (!videoForceAspect)
result->value = @"Fill Screen";
else if (videoAspect < 0.0)
result->value = videoAspectAuto ? @"Game Aspect" : @"Pixel Aspect";
else
result->value = (videoAspect < 1.5) ? @"4:3" : @"16:9";
return result;
}
static RASettingData* custom_action(NSString* action, NSString* value, id data, void (*reload_func)(RASettingData* action, id userdata))
{
RASettingData* result = [[RASettingData alloc] initWithType:CustomAction label:action name:nil];
result->value = value;
result->reload = reload_func;
if (data != nil)
objc_setAssociatedObject(result, associated_userdata_key, data, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return result;
}
// This adds a change notify function to a setting and returns it; done this way so it can be used in NSArray
// init lists.
static RASettingData* change_notify(RASettingData* setting, void (*change_func)(RASettingData* setting))
{
setting->changed = change_func;
return setting;
}
static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
{
// Only player 1 should have default key bindings
#define DEFKEY(val) (player == 1) ? val : @"nul"
return [NSArray arrayWithObjects:
[NSArray arrayWithObjects:[NSString stringWithFormat:@"Player %d", player],
button_setting(config, player, @"up", @"Up", DEFKEY(@"up")),
button_setting(config, player, @"down", @"Down", DEFKEY(@"down")),
button_setting(config, player, @"left", @"Left", DEFKEY(@"left")),
button_setting(config, player, @"right", @"Right", DEFKEY(@"right")),
button_setting(config, player, @"start", @"Start", DEFKEY(@"enter")),
button_setting(config, player, @"select", @"Select", DEFKEY(@"rshift")),
button_setting(config, player, @"b", @"B", DEFKEY(@"z")),
button_setting(config, player, @"a", @"A", DEFKEY(@"x")),
button_setting(config, player, @"x", @"X", DEFKEY(@"s")),
button_setting(config, player, @"y", @"Y", DEFKEY(@"a")),
button_setting(config, player, @"l", @"L", DEFKEY(@"q")),
button_setting(config, player, @"r", @"R", DEFKEY(@"w")),
button_setting(config, player, @"l2", @"L2", @"nul"),
button_setting(config, player, @"r2", @"R2", @"nul"),
button_setting(config, player, @"l3", @"L3", @"nul"),
button_setting(config, player, @"r3", @"R3", @"nul"),
button_setting(config, player, @"l_y_minus", @"Left Stick Up", @"nul"),
button_setting(config, player, @"l_y_plus", @"Left Stick Down", @"nul"),
button_setting(config, player, @"l_x_minus", @"Left Stick Left", @"nul"),
button_setting(config, player, @"l_x_plus", @"Left Stick Right", @"nul"),
button_setting(config, player, @"r_y_minus", @"Right Stick Up", @"nul"),
button_setting(config, player, @"r_y_plus", @"Right Stick Down", @"nul"),
button_setting(config, player, @"r_x_minus", @"Right Stick Left", @"nul"),
button_setting(config, player, @"r_x_plus", @"Right Stick Right", @"nul"),
nil],
nil];
}
@implementation RASettingsList
{
RAModuleInfo* _module;
NSString* _configPath;
bool _cancelSave; // Set to prevent dealloc from writing to disk
}
+ (void)refreshModuleConfig:(RAModuleInfo*)module;
{
(void)[[RASettingsList alloc] initWithModule:module];
}
- (id)initWithModule:(RAModuleInfo*)module
{
_module = module;
_configPath = _module ? _module.configFile : apple_platform.globalConfigFile;
config_file_t* config = config_file_new([_configPath UTF8String]);
NSString* overlay_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/overlays/"];
NSString* shader_path = [[[NSBundle mainBundle] bundlePath] stringByAppendingString:@"/shaders_glsl/"];
NSArray* settings = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:@"Core",
custom_action(@"Core Info", nil, nil, 0),
_module.hasCustomConfig ? custom_action(@"Delete Custom Config", nil, nil, 0) : nil,
nil],
[NSArray arrayWithObjects:@"Video",
boolean_setting(config, @"video_smooth", @"Bilinear filtering", @"true"),
boolean_setting(config, @"video_crop_overscan", @"Crop Overscan", @"true"),
boolean_setting(config, @"video_scale_integer", @"Integer Scaling", @"false"),
aspect_setting(config, @"Aspect Ratio"),
nil],
[NSArray arrayWithObjects:@"GPU Shader",
boolean_setting(config, @"video_shader_enable", @"Enable Shader", @"false"),
subpath_setting(config, @"video_shader", @"Shader", @"", shader_path, @"glsl"),
nil],
[NSArray arrayWithObjects:@"Audio",
boolean_setting(config, @"audio_enable", @"Enable Output", @"true"),
boolean_setting(config, @"audio_sync", @"Sync on Audio", @"true"),
boolean_setting(config, @"audio_rate_control", @"Rate Control", @"true"),
nil],
[NSArray arrayWithObjects:@"Input",
subpath_setting(config, @"input_overlay", @"Input Overlay", @"", overlay_path, @"cfg"),
range_setting(config, @"input_overlay_opacity", @"Overlay Opacity", @"1.0", 0.0, 1.0),
group_setting(@"System Keys", [NSArray arrayWithObjects:
// TODO: Many of these strings will be cut off on an iPhone
[NSArray arrayWithObjects:@"System Keys",
button_setting(config, 0, @"input_menu_toggle", @"Show RGUI", @"f1"),
button_setting(config, 0, @"input_disk_eject_toggle", @"Insert/Eject Disk", @"nul"),
button_setting(config, 0, @"input_disk_next", @"Cycle Disks", @"nul"),
button_setting(config, 0, @"input_save_state", @"Save State", @"f2"),
button_setting(config, 0, @"input_load_state", @"Load State", @"f4"),
button_setting(config, 0, @"input_state_slot_increase", @"Next State Slot", @"f7"),
button_setting(config, 0, @"input_state_slot_decrease", @"Previous State Slot", @"f6"),
button_setting(config, 0, @"input_toggle_fast_forward", @"Toggle Fast Forward", @"space"),
button_setting(config, 0, @"input_hold_fast_forward", @"Hold Fast Forward", @"l"),
button_setting(config, 0, @"input_rewind", @"Rewind", @"r"),
button_setting(config, 0, @"input_slowmotion", @"Slow Motion", @"e"),
button_setting(config, 0, @"input_reset", @"Reset", @"h"),
button_setting(config, 0, @"input_exit_emulator", @"Close Game", @"escape"),
button_setting(config, 0, @"input_enable_hotkey", @"Hotkey Enable (Always on if not set)", @"nul"),
nil],
nil]),
group_setting(@"Player 1 Keys", build_input_port_group(config, 1)),
group_setting(@"Player 2 Keys", build_input_port_group(config, 2)),
group_setting(@"Player 3 Keys", build_input_port_group(config, 3)),
group_setting(@"Player 4 Keys", build_input_port_group(config, 4)),
nil],
[NSArray arrayWithObjects:@"Save States",
boolean_setting(config, @"rewind_enable", @"Enable Rewinding", @"false"),
boolean_setting(config, @"block_sram_overwrite", @"Disable SRAM on Load", @"false"),
boolean_setting(config, @"savestate_auto_save", @"Auto Save on Exit", @"false"),
boolean_setting(config, @"savestate_auto_load", @"Auto Load on Startup", @"true"),
nil],
nil
];
if (config)
config_file_free(config);
self = [super initWithSettings:settings title:_module ? _module.description : @"Global Core Config"];
return self;
}
- (void)dealloc
{
if (!_cancelSave)
{
config_file_t* config = config_file_new([_configPath UTF8String]);
if (!config)
config = config_file_new(0);
if (config)
{
config_set_string(config, "system_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
config_set_string(config, "savefile_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
config_set_string(config, "savestate_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
[self writeSettings:nil toConfig:config];
config_file_write(config, [_configPath UTF8String]);
config_file_free(config);
}
apple_refresh_config();
}
}
- (void)handleCustomAction:(RASettingData*)setting
{
if ([@"Core Info" isEqualToString:setting->label])
[self.navigationController pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:_module] animated:YES];
else if([@"Delete Custom Config" isEqualToString:setting->label])
{
[_module deleteCustomConfig];
_cancelSave = true;
[self.navigationController popViewControllerAnimated:YES];
}
}
@end
#pragma mark System Settings
static void reload_core_config_state(RASettingData* action, RAModuleInfo* userdata)
{
[action setValue:userdata.hasCustomConfig ? @"[Custom]" : @"[Global]"];
}
static void bluetooth_option_changed(RASettingData* setting)
{
ios_set_bluetooth_mode(setting->value);
}
@implementation RASystemSettingsList
- (id)init
{
config_file_t* config = config_file_new([[RetroArch_iOS get].systemConfigPath UTF8String]);
NSMutableArray* modules = [NSMutableArray array];
[modules addObject:@"Cores"];
[modules addObject:custom_action(@"Global Core Config", nil, nil, 0)];
NSArray* moduleList = apple_get_modules();
for (RAModuleInfo* i in moduleList)
{
[modules addObject:custom_action(i.description, nil, i, reload_core_config_state)];
}
NSArray* bluetoothOptions = nil;
if (!is_ios_7() && btstack_try_load())
bluetoothOptions = @[@"keyboard", @"Keyboard", @"icade", @"iCade Device", @"btstack", @"WiiMote/SixAxis (BTstack)"];
else if (!is_ios_7())
bluetoothOptions = @[@"keyboard", @"Keyboard", @"icade", @"iCade Device"];
else // if (is_ios_7())
bluetoothOptions = @[@"none", @"None", @"icade", @"iCade Device"];
NSArray* settings = [NSArray arrayWithObjects:
[NSArray arrayWithObjects:@"Frontend",
custom_action(@"Diagnostic Log", nil, nil, 0),
boolean_setting(config, @"ios_tv_mode", @"TV Mode", @"false"),
nil],
[NSArray arrayWithObjects:@"Bluetooth",
change_notify(enumeration_setting(config, @"ios_btmode", @"Mode", @"keyboard", bluetoothOptions, true), bluetooth_option_changed),
nil],
[NSArray arrayWithObjects:@"Orientations",
boolean_setting(config, @"ios_allow_portrait", @"Portrait", @"true"),
boolean_setting(config, @"ios_allow_portrait_upside_down", @"Portrait Upside Down", @"true"),
boolean_setting(config, @"ios_allow_landscape_left", @"Landscape Left", @"true"),
boolean_setting(config, @"ios_allow_landscape_right", @"Landscape Right", @"true"),
nil],
modules,
nil
];
if (config)
config_file_free(config);
self = [super initWithSettings:settings title:@"RetroArch Settings"];
return self;
}
- (void)viewDidAppear:(BOOL)animated
{
[self.tableView reloadData];
[super viewDidAppear:animated];
}
- (void)dealloc
{
config_file_t* config = config_file_new([[RetroArch_iOS get].systemConfigPath UTF8String]);
if (!config)
config = config_file_new(0);
if (config)
{
[self writeSettings:nil toConfig:config];
config_file_write(config, [[RetroArch_iOS get].systemConfigPath UTF8String]);
config_file_free(config);
}
[[RetroArch_iOS get] refreshSystemConfig];
}
- (void)handleCustomAction:(RASettingData*)setting
{
if ([@"Diagnostic Log" isEqualToString:setting->label])
[self.navigationController pushViewController:[RALogView new] animated:YES];
else if ([@"Enable BTstack" isEqualToString:setting->label])
btstack_set_poweron([setting->value isEqualToString:@"true"]);
else if([@"Global Core Config" isEqualToString:setting->label])
[self.navigationController pushViewController:[[RASettingsList alloc] initWithModule:nil] animated:YES];
else
{
RAModuleInfo* data = (RAModuleInfo*)objc_getAssociatedObject(setting, associated_userdata_key);
if (data)
{
if (!data.hasCustomConfig)
{
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@"No custom configuration for this core exists, "
"would you like to create one?"
delegate:self
cancelButtonTitle:@"No"
otherButtonTitles:@"Yes", nil];
objc_setAssociatedObject(alert, associated_module_key, data, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
[alert show];
}
else
[self.navigationController pushViewController:[[RASettingsList alloc] initWithModule:data] animated:YES];
}
}
}
- (void)alertView:(UIAlertView*)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
RAModuleInfo* data = (RAModuleInfo*)objc_getAssociatedObject(alertView, associated_module_key);
if (data)
{
if (buttonIndex == alertView.firstOtherButtonIndex)
{
[data createCustomConfig];
[self.tableView reloadData];
}
[self.navigationController pushViewController:[[RASettingsList alloc] initWithModule:data] animated:YES];
}
}
@end
@implementation RASettingsSubList
{
RAButtonGetter* _binder;
}
- (id)initWithSettings:(NSMutableArray*)values title:(NSString*)title
{
self = [super initWithStyle:UITableViewStyleGrouped];
[self setTitle:title];
self.sections = values;
_binder = [[RAButtonGetter alloc] initFromTable:self.tableView];
return self;
}
- (bool)isSettingsView
{
return true;
}
- (void)handleCustomAction:(RASettingData*)setting
{
}
- (void)writeSettings:(NSArray*)settingList toConfig:(config_file_t*)config
{
if (!config)
return;
NSArray* list = settingList ? settingList : self.sections;
for (int i = 0; i < [list count]; i++)
{
NSArray* group = [list objectAtIndex:i];
for (int j = 1; j < [group count]; j ++)
{
RASettingData* setting = [group objectAtIndex:j];
switch (setting->type)
{
case GroupSetting:
[self writeSettings:setting->subValues toConfig:config];
break;
case FileListSetting:
if ([setting->value length] > 0)
config_set_string(config, [setting->name UTF8String], [[setting->path stringByAppendingPathComponent:setting->value] UTF8String]);
else
config_set_string(config, [setting->name UTF8String], "");
break;
case ButtonSetting:
if (setting->value)
config_set_string(config, [setting->name UTF8String], [setting->value UTF8String]);
if (setting->button_bind)
config_set_string(config, [[setting->name stringByAppendingString:@"_btn"] UTF8String], [setting->button_bind UTF8String]);
if (setting->axis_bind)
config_set_string(config, [[setting->name stringByAppendingString:@"_axis"] UTF8String], [setting->axis_bind UTF8String]);
break;
case AspectSetting:
config_set_string(config, "video_force_aspect", [@"Fill Screen" isEqualToString:setting->value] ? "false" : "true");
config_set_string(config, "video_aspect_ratio_auto", [@"Game Aspect" isEqualToString:setting->value] ? "true" : "false");
config_set_string(config, "video_aspect_ratio", "-1.0");
if([@"4:3" isEqualToString:setting->value])
config_set_string(config, "video_aspect_ratio", "1.33333333");
else if([@"16:9" isEqualToString:setting->value])
config_set_string(config, "video_aspect_ratio", "1.77777777");
break;
case CustomAction:
break;
default:
config_set_string(config, [setting->name UTF8String], [setting->value UTF8String]);
break;
}
}
}
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RASettingData* setting = (RASettingData*)[self itemForIndexPath:indexPath];
switch (setting->type)
{
case EnumerationSetting:
case FileListSetting:
case AspectSetting:
[self.navigationController pushViewController:[[RASettingEnumerationList alloc] initWithSetting:setting fromTable:(UITableView*)self.view] animated:YES];
break;
case ButtonSetting:
[_binder runForSetting:setting];
break;
case GroupSetting:
[self.navigationController pushViewController:[[RASettingsSubList alloc] initWithSettings:setting->subValues title:setting->label] animated:YES];
break;
default:
break;
}
[self handleCustomAction:setting];
}
- (void)handleBooleanSwitch:(UISwitch*)swt
{
RASettingData* setting = objc_getAssociatedObject(swt, associated_setting_key);
[setting setValue:swt.on ? @"true" : @"false"];
[self handleCustomAction:setting];
}
- (void)handleSlider:(UISlider*)sld
{
RASettingData* setting = objc_getAssociatedObject(sld, associated_setting_key);
[setting setValue:[NSString stringWithFormat:@"%f", sld.value]];
[self handleCustomAction:setting];
}
- (UITableViewCell*)tableView:(UITableView*)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RASettingData* setting = (RASettingData*)[self itemForIndexPath:indexPath];
UITableViewCell* cell = nil;
switch (setting->type)
{
case BooleanSetting:
{
static NSString* const cell_id = @"boolean";
cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
UISwitch* accessory = [[UISwitch alloc] init];
[accessory addTarget:self action:@selector(handleBooleanSwitch:) forControlEvents:UIControlEventValueChanged];
cell.accessoryView = accessory;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = setting->label;
UISwitch* swt = (UISwitch*)cell.accessoryView;
swt.on = [setting->value isEqualToString:@"true"];
objc_setAssociatedObject(swt, associated_setting_key, setting, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return cell;
}
case RangeSetting:
{
static NSString* const cell_id = @"range";
cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
if (cell == nil)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
UISlider* accessory = [UISlider new];
[accessory addTarget:self action:@selector(handleSlider:) forControlEvents:UIControlEventValueChanged];
accessory.continuous = NO;
cell.accessoryView = accessory;
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
}
cell.textLabel.text = setting->label;
UISlider* sld = (UISlider*)cell.accessoryView;
sld.minimumValue = setting->rangeMin;
sld.maximumValue = setting->rangeMax;
sld.value = [setting->value doubleValue];
objc_setAssociatedObject(sld, associated_setting_key, setting, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
return cell;
}
break;
default:
{
static NSString* const cell_id = @"default";
cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:cell_id];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
}
if (setting->reload)
setting->reload(setting, objc_getAssociatedObject(setting, associated_userdata_key));
cell.textLabel.text = setting->label;
if (setting->type == ButtonSetting)
cell.detailTextLabel.text = [NSString stringWithFormat:@"[KB:%@] [JS:%@] [AX:%@]",
[setting->value length] ? setting->value : @"nul",
[setting->button_bind length] ? setting->button_bind : @"nul",
[setting->axis_bind length] ? setting->axis_bind : @"nul"];
else if(setting->type == EnumerationSetting)
cell.detailTextLabel.text = setting.labelForEnumerationValue;
else
cell.detailTextLabel.text = setting->value;
return cell;
}
}
}
@end
@implementation RASettingEnumerationList
{
RASettingData* _value;
UITableView* _view;
unsigned _mainSection;
};
- (id)initWithSetting:(RASettingData*)setting fromTable:(UITableView*)table
{
self = [super initWithStyle:UITableViewStyleGrouped];
_value = setting;
_view = table;
_mainSection = _value->haveNoneOption ? 1 : 0;
[self setTitle: _value->label];
return self;
}
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
{
return _value->haveNoneOption ? 2 : 1;
}
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
{
return (section == _mainSection) ? _value.enumerationCount : 1;
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
static NSString* const cell_id = @"option";
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:cell_id];
cell = cell ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_id];
if (indexPath.section == _mainSection)
cell.textLabel.text = [_value labelForEnumerationIndex:indexPath.row];
else
cell.textLabel.text = @"None";
return cell;
}
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
[_value setValue: (indexPath.section == _mainSection) ? [_value valueForEnumerationIndex:indexPath.row] : @""];
[_view reloadData];
[self.navigationController popViewControllerAnimated:YES];
}
@end
@implementation RAButtonGetter
{
RASettingData* _value;
UIAlertView* _alert;
UITableView* _view;
bool _finished;
NSTimer* _btTimer;
}
- (id)initFromTable:(UITableView*)table
{
self = [super init];
_view = table;
_alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
message:@""
delegate:self
cancelButtonTitle:@"Cancel"
otherButtonTitles:@"Clear Keyboard", @"Clear Joystick", @"Clear Axis", nil];
if (is_ios_7())
_alert.alertViewStyle = UIAlertViewStylePlainTextInput;
return self;
}
- (void)runForSetting:(RASettingData*)setting
{
apple_input_reset_icade_buttons();
_value = setting;
_alert.message = _value->name;
[_alert show];
_btTimer = [NSTimer scheduledTimerWithTimeInterval:.05f target:self selector:@selector(checkInput) userInfo:nil repeats:YES];
_finished = false;
}
- (void)finish
{
if (!_finished)
{
_finished = true;
apple_input_reset_icade_buttons();
[_btTimer invalidate];
_btTimer = nil;
[_alert dismissWithClickedButtonIndex:_alert.cancelButtonIndex animated:YES];
[_view reloadData];
}
}
- (void)alertView:(UIAlertView*)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
{
if (buttonIndex == _alert.firstOtherButtonIndex)
_value->value = @"nul";
else if(buttonIndex == _alert.firstOtherButtonIndex + 1)
_value->button_bind = @"nul";
else if(buttonIndex == _alert.firstOtherButtonIndex + 2)
_value->axis_bind = @"nul";
[self finish];
}
- (void)checkInput
{
int32_t value = 0;
if ((value = apple_input_find_any_key()))
_value->value = @(apple_keycode_hidusage_to_name(value));
else if ((value = apple_input_find_any_button(0)) >= 0)
_value->button_bind = [NSString stringWithFormat:@"%d", value];
else if ((value = apple_input_find_any_axis(0)))
_value->axis_bind = [NSString stringWithFormat:@"%s%d", (value > 0) ? "+" : "-", value - 1];
else
return;
[self finish];
}
@end

View File

@ -16,76 +16,34 @@
#ifndef _RARCH_APPLE_VIEWS_H
#define _RARCH_APPLE_VIEWS_H
#import "RAModuleInfo.h"
#include <UIKit/UIKit.h>
#include "core_info.h"
// RALogView.m
@interface RALogView : UITableViewController
@end
// utility.m
@interface RATableViewController : UITableViewController
@property (nonatomic) NSMutableArray* sections;
@property (nonatomic) BOOL hidesHeaders;
- (id)initWithStyle:(UITableViewStyle)style;
- (bool)getCellFor:(NSString*)reuseID withStyle:(UITableViewCellStyle)style result:(UITableViewCell**)output;
- (id)itemForIndexPath:(NSIndexPath*)indexPath;
- (void)reset;
@end
// browser.m
@interface RADirectoryItem : NSObject
@property (nonatomic) NSString* path;
@property (nonatomic) bool isDirectory;
@end
// browser.m
@class RADirectoryItem;
@protocol RADirectoryListDelegate
- (bool)directoryList:(id)list itemWasSelected:(RADirectoryItem*)path;
@end
@interface RADirectoryList : RATableViewController <UIActionSheetDelegate>
#include "menu.h"
// browser.m
@interface RADirectoryItem : NSObject<RAMenuItemBase>
@property (nonatomic) NSString* path;
@property (nonatomic) bool isDirectory;
@end
@interface RADirectoryList : RAMenuBase<UIActionSheetDelegate>
@property (nonatomic, weak) id<RADirectoryListDelegate> directoryDelegate;
@property (nonatomic, weak) RADirectoryItem* selectedItem;
- (id)initWithPath:(NSString*)path delegate:(id<RADirectoryListDelegate>)delegate;
- (void)browseTo:(NSString*)path;
@end
// browser.m
@protocol RAModuleListDelegate
- (bool)moduleList:(id)list itemWasSelected:(RAModuleInfo*)module;
@end
@interface RAModuleList : RATableViewController
@property (nonatomic, weak) id<RAModuleListDelegate> moduleDelegate;
- (id)initWithGame:(NSString*)path delegate:(id<RAModuleListDelegate>)delegate;
@end
// browser.m
@interface RAFoldersList : RATableViewController
@interface RAFoldersList : RAMenuBase
- (id) initWithFilePath:(NSString*)path;
@end
// RAModuleInfo.m
@interface RAModuleInfoList : RATableViewController
- (id)initWithModuleInfo:(RAModuleInfo*)info;
@end
// settings.m
@interface RASettingsSubList : RATableViewController
- (id)initWithSettings:(NSArray*)values title:(NSString*)title;
- (void)writeSettings:(NSArray*)settingList toConfig:(config_file_t*)config;
- (bool)isSettingsView;
@end
// settings.m
@interface RASettingsList : RASettingsSubList
+ (void)refreshModuleConfig:(RAModuleInfo*)module;
- (id)initWithModule:(RAModuleInfo*)module;
@end
// settings.m
@interface RASystemSettingsList : RASettingsSubList<UIAlertViewDelegate>
@end
#endif

View File

@ -200,6 +200,18 @@ const char *core_option_get_val(core_option_manager_t *opt, size_t index)
return option->vals->elems[option->index].data;
}
struct string_list *core_option_get_vals(core_option_manager_t *opt, size_t index)
{
return opt->opts[index].vals;
}
void core_option_set_val(core_option_manager_t *opt, size_t index, size_t val_index)
{
struct core_option *option= (struct core_option*)&opt->opts[index];
option->index = val_index % option->vals->size;
opt->updated = true;
}
void core_option_next(core_option_manager_t *opt, size_t index)
{
struct core_option *option = &opt->opts[index];

View File

@ -40,6 +40,10 @@ size_t core_option_size(core_option_manager_t *opt);
const char *core_option_get_desc(core_option_manager_t *opt, size_t index);
const char *core_option_get_val(core_option_manager_t *opt, size_t index);
// Helpers to present a list of options
struct string_list *core_option_get_vals(core_option_manager_t *opt, size_t index);
void core_option_set_val(core_option_manager_t *opt, size_t index, size_t val_index);
// Cycles through options for an option. Options wrap around.
void core_option_next(core_option_manager_t *opt, size_t index);
void core_option_prev(core_option_manager_t *opt, size_t index);

View File

@ -22,6 +22,7 @@
#include "../ps3/altivec_mem.c"
#endif
/*============================================================
CONSOLE EXTENSIONS
============================================================ */
@ -43,6 +44,8 @@ CONSOLE EXTENSIONS
#include "../file_extract.c"
#endif
/*============================================================
RLAUNCH
============================================================ */
@ -579,6 +582,15 @@ XML
============================================================ */
#define RXML_LIBXML2_COMPAT
#include "../compat/rxml/rxml.c"
/*============================================================
APPLE EXTENSIONS
============================================================ */
#if defined(IOS) || defined(OSX)
#include "../apple/common/setting_data.c"
#include "../apple/common/core_info_ext.c"
#endif
#ifdef __cplusplus
}