mirror of
https://github.com/libretro/RetroArch
synced 2025-04-15 23:42:30 +00:00
(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:
parent
0386ae6e1b
commit
a96e813fe1
@ -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 |
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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;
|
||||
|
@ -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 */,
|
||||
|
@ -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;
|
||||
|
@ -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;
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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);
|
||||
|
@ -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;
|
||||
|
@ -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);
|
||||
|
||||
|
112
apple/common/core_info_ext.c
Normal file
112
apple/common/core_info_ext.c
Normal 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 : "";
|
||||
}
|
38
apple/common/core_info_ext.h
Normal file
38
apple/common/core_info_ext.h
Normal 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
|
@ -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)
|
||||
{
|
||||
|
@ -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
585
apple/common/setting_data.c
Normal 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;
|
||||
}
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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
|
@ -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
197
apple/iOS/menu.h
Normal 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
952
apple/iOS/menu.m
Normal 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
|
@ -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
|
||||
|
||||
|
@ -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]));
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -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
|
||||
|
@ -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
|
||||
|
@ -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];
|
||||
|
@ -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);
|
||||
|
@ -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
|
||||
}
|
||||
|
Loading…
x
Reference in New Issue
Block a user