Merge branch 'master' of git://github.com/libretro/RetroArch

This commit is contained in:
Themaister 2013-09-11 16:36:20 +02:00
commit 00495aa9dd
116 changed files with 5828 additions and 1390 deletions

159
Makefile.emscripten Normal file
View File

@ -0,0 +1,159 @@
TARGET = retroarch.js
OBJ = frontend/frontend_emscripten.o \
retroarch.o \
file.o \
file_path.o \
driver.o \
conf/config_file.o \
settings.o \
hash.o \
dynamic.o \
dynamic_dummy.o \
message.o \
rewind.o \
movie.o \
gfx/gfx_common.o \
input/input_common.o \
input/rwebinput_input.o \
core_options.o \
patch.o \
compat/compat.o \
compat/rxml/rxml.o \
screenshot.o \
cheats.o \
audio/utils.o \
audio/rwebaudio.o \
input/overlay.o \
fifo_buffer.o \
gfx/scaler/scaler.o \
gfx/scaler/pixconv.o \
gfx/scaler/scaler_int.o \
gfx/scaler/filter.o \
gfx/state_tracker.o \
gfx/shader_parse.o \
gfx/fonts/fonts.o \
gfx/fonts/bitmapfont.o \
gfx/image.o \
audio/resampler.o \
audio/sinc.o \
audio/null.o \
performance.o
HAVE_OPENGL = 1
HAVE_RGUI = 1
HAVE_SDL = 0
HAVE_ZLIB = 1
HAVE_FBO = 1
WANT_MINIZ = 1
MEMORY = 67108864
LTO = 0
FAST_DOUBLES = 1
ifneq ($(NATIVE_ZLIB),)
WANT_MINIZ = 0
endif
libretro = libretro_emscripten.bc
LIBS = -lm
DEFINES = -DHAVE_SCREENSHOTS -DHAVE_NULLAUDIO -DHAVE_BSV_MOVIE -DPACKAGE_VERSION=\"0.9.9.3\"
LDFLAGS = -L. -s TOTAL_MEMORY=$(MEMORY) --js-library emscripten/library_rwebaudio.js --js-library emscripten/library_rwebinput.js
ifeq ($(PERF_TEST), 1)
DEFINES += -DPERF_TEST
endif
ifeq ($(HAVE_RGUI), 1)
DEFINES += -DHAVE_RGUI
OBJ += frontend/menu/menu_common.o frontend/menu/rgui.o frontend/menu/history.o
endif
ifeq ($(HAVE_SDL), 1)
OBJ += input/sdl_input.o
LIBS += -lSDL
DEFINES += -ISDL -DHAVE_SDL
endif
ifeq ($(HAVE_OPENGL), 1)
OBJ += gfx/gl.o gfx/math/matrix.o gfx/fonts/gl_font.o gfx/fonts/gl_raster_font.o gfx/gfx_context.o gfx/context/emscriptenegl_ctx.o gfx/shader_glsl.o gfx/glsym/rglgen.o gfx/glsym/glsym_es2.o
DEFINES += -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_EGL -DHAVE_OVERLAY -DHAVE_GLSL
endif
ifeq ($(HAVE_ZLIB), 1)
OBJ += gfx/rpng/rpng.o file_extract.o
DEFINES += -DHAVE_ZLIB
ifeq ($(WANT_MINIZ), 1)
OBJ += deps/miniz/miniz.o
DEFINES += -DWANT_MINIZ
else
LIBS += -lz
DEFINES += -DHAVE_ZLIB_DEFLATE
endif
endif
ifeq ($(HAVE_FBO), 1)
DEFINES += -DHAVE_FBO
endif
ifneq ($(V), 1)
Q := @
endif
ifeq ($(DEBUG), 1)
LDFLAGS += -O0 -g
CFLAGS += -O0 -g
else
LDFLAGS += -O2
# WARNING: some optimizations can break some cores (ex: LTO breaks tyrquake)
ifeq ($(FAST_DOUBLES), 1)
LDFLAGS += -s DOUBLE_MODE=0
endif
ifeq ($(LTO), 1)
LDFLAGS += --llvm-lto 3
endif
CFLAGS += -O2
endif
CFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I. -std=gnu99
all: $(TARGET)
$(TARGET): $(OBJ)
@$(if $(Q), $(shell echo echo LD $@),)
$(Q)$(LD) -o $@ $(OBJ) $(libretro) $(LIBS) $(LDFLAGS)
%.o: %.c
@$(if $(Q), $(shell echo echo CC $<),)
$(Q)$(CC) $(CFLAGS) $(DEFINES) -c -o $@ $<
%.o: %.cpp
@$(if $(Q), $(shell echo echo CXX $<),)
$(Q)$(CXX) $(CXXFLAGS) $(DEFINES) -c -o $@ $<
clean:
rm -f *.o
rm -f deps/miniz/*.o
rm -f frontend/*.o
rm -f frontend/menu/*.o
rm -f audio/*.o
rm -f audio/xaudio-c/*.o
rm -f compat/*.o
rm -f compat/rxml/*.o
rm -f conf/*.o
rm -f gfx/scaler/*.o
rm -f gfx/*.o
rm -f gfx/d3d9/*.o
rm -f gfx/context/*.o
rm -f gfx/math/*.o
rm -f gfx/fonts/*.o
rm -f gfx/py_state/*.o
rm -f gfx/rpng/*.o
rm -f gfx/glsym/*.o
rm -f record/*.o
rm -f input/*.o
rm -f tools/*.o
rm -f $(TARGET)
.PHONY: all clean

View File

@ -17,6 +17,7 @@ OBJ = frontend/frontend.o \
movie.o \
gfx/gfx_common.o \
input/input_common.o \
input/autoconf/builtin_win.o \
core_options.o \
patch.o \
compat/compat.o \
@ -44,7 +45,8 @@ JOBJ := conf/config_file.o \
compat/compat.o \
file_path.o \
tools/input_common_joyconfig.o \
input/dinput.o
input/dinput.o \
input/winxinput_joypad.o
CC = gcc
CXX = g++
@ -62,6 +64,9 @@ HAVE_STDIN_CMD = 1
HAVE_THREADS = 1
HAVE_RGUI = 1
DYNAMIC = 1
HAVE_WIN32GUI = 1
HAVE_WINXINPUT = 1
ifeq ($(SLIM),)
HAVE_SDL = 1
@ -78,7 +83,7 @@ endif
libretro ?= -lretro
LIBS = -lm
DEFINES = -I. -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE
DEFINES = -I. -DHAVE_SCREENSHOTS -DHAVE_BSV_MOVIE -DHAVE_BUILTIN_AUTOCONFIG
LDFLAGS = -L. -static-libgcc
ifeq ($(TDM_GCC),)
@ -100,6 +105,10 @@ ifeq ($(HAVE_RGUI), 1)
OBJ += frontend/menu/menu_common.o frontend/menu/rgui.o frontend/menu/history.o
endif
ifeq ($(HAVE_WIN32GUI), 1)
DEFINES += -DHAVE_WIN32GUI
endif
ifeq ($(HAVE_SDL), 1)
OBJ += gfx/sdl_gfx.o input/sdl_input.o input/sdl_joypad.o audio/sdl_audio.o
JOBJ += input/sdl_joypad.o
@ -212,6 +221,11 @@ ifeq ($(HAVE_PYTHON), 1)
OBJ += gfx/py_state/py_state.o
endif
ifeq ($(HAVE_WINXINPUT), 1)
DEFINES += -DHAVE_WINXINPUT
OBJ += input/winxinput_joypad.o
endif
ifeq ($(HAVE_DINPUT), 1)
LIBS += -ldinput8 -ldxguid -lole32
DEFINES += -DHAVE_DINPUT

View File

@ -48,7 +48,7 @@ ifeq ($(PERF_TEST), 1)
LOCAL_CFLAGS += -DPERF_TEST
endif
LOCAL_CFLAGS += -Wall -pthread -Wno-unused-function -O3 -fno-stack-protector -funroll-loops -DNDEBUG -DRARCH_MOBILE -DHAVE_GRIFFIN -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_FBO -DHAVE_OVERLAY -DHAVE_OPENGLES -DHAVE_VID_CONTEXT -DHAVE_OPENGLES2 -DGLSL_DEBUG -DHAVE_GLSL -DHAVE_RGUI -DHAVE_SCREENSHOTS -DWANT_MINIZ -DHAVE_ZLIB -DINLINE=inline -DLSB_FIRST -DHAVE_THREADS -D__LIBRETRO__ -DRARCH_PERFORMANCE_MODE -std=gnu99 -I../../../deps/miniz
LOCAL_CFLAGS += -Wall -pthread -Wno-unused-function -O3 -fno-stack-protector -funroll-loops -DNDEBUG -DRARCH_MOBILE -DHAVE_GRIFFIN -DANDROID -DHAVE_DYNAMIC -DHAVE_OPENGL -DHAVE_FBO -DHAVE_OVERLAY -DHAVE_OPENGLES -DHAVE_VID_CONTEXT -DHAVE_OPENGLES2 -DGLSL_DEBUG -DHAVE_GLSL -DHAVE_RGUI -DHAVE_SCREENSHOTS -DWANT_MINIZ -DHAVE_ZLIB -DINLINE=inline -DLSB_FIRST -DHAVE_THREADS -D__LIBRETRO__ -std=gnu99 -I../../../deps/miniz
LOCAL_LDLIBS := -L$(SYSROOT)/usr/lib -landroid -lEGL -lGLESv2 $(LOGGER_LDLIBS) -ldl

View File

@ -1855,7 +1855,7 @@ static int16_t android_input_state(void *data, const struct retro_keybind **bind
static bool android_input_key_pressed(void *data, int key)
{
return ((g_extern.lifecycle_state | driver.overlay_state) & (1ULL << key));
return ((g_extern.lifecycle_state | driver.overlay_state.buttons) & (1ULL << key));
}
static void android_input_free_input(void *data)

View File

@ -1,6 +1,6 @@
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="org.retroarch"
android:versionCode="23"
android:versionCode="24"
android:versionName="0.9.9.6" >
<uses-feature android:glEsVersion="0x00020000" />
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
@ -29,6 +29,7 @@
<activity android:name=".browser.LazyPopupMenu"></activity>
<activity android:name=".browser.PopupMenuAbstract"></activity>
<activity android:name=".browser.ReportIME"></activity>
<activity android:name=".browser.IMEActivity"></activity>
<activity android:name=".browser.HelpActivity"></activity>
<activity android:name=".browser.FileWrapper"></activity>
<activity android:name=".browser.DirectoryActivity"></activity>

View File

@ -43,6 +43,7 @@
<ListPreference
android:entries="@array/aspect_ratios"
android:entryValues="@array/aspect_values"
android:defaultValue="auto"
android:key="video_aspect_ratio"
android:summary="Aspect ratio to enforce."
android:title="Aspect ratio" />
@ -123,17 +124,25 @@
</PreferenceScreen>
<PreferenceScreen android:title="Input Options" >
<PreferenceCategory android:title="General" >
<CheckBoxPreference android:title="Enable global configuration"
android:summary="Enable global settings for all cores. Leave disabled if you want per-core settings."
android:key="global_config_enable"
android:defaultValue="true"/>
<ListPreference
android:entries="@array/back_options"
android:entryValues="@array/back_options_values"
android:defaultValue="0"
android:key="input_back_behavior"
android:summary="Select how you want the Back button to behave."
android:title="Back behavior" />
</PreferenceCategory>
<PreferenceCategory android:title="IME" >
<Preference
android:summary="Sets IME to be used in-game."
android:title="Set Input Method" >
<intent
android:targetClass="org.retroarch.browser.IMEActivity"
android:targetPackage="org.retroarch" />
</Preference>
</PreferenceCategory>
<PreferenceCategory android:title="Configuration Autodetect" >
<CheckBoxPreference
android:defaultValue="true"
@ -468,6 +477,14 @@
</PreferenceCategory>
</PreferenceScreen>
<PreferenceScreen android:title="Settings" >
<PreferenceCategory android:title="Configuration style" >
<CheckBoxPreference
android:defaultValue="true"
android:key="global_config_enable"
android:summary="Enable global settings for all cores. Leave disabled if you want per-core settings."
android:title="Enable global configuration" />
</PreferenceCategory>
<PreferenceCategory android:title="General" >
<CheckBoxPreference
android:defaultValue="true"

View File

@ -80,6 +80,10 @@ public class ConfigFile {
public void setDouble(String key, double value) {
map.put(key, Double.toString(value));
}
public void setFloat(String key, float value) {
map.put(key, Float.toString(value));
}
public boolean keyExists(String key) {
return map.containsKey(key);
@ -108,6 +112,14 @@ public class ConfigFile {
else
throw new NumberFormatException();
}
public float getFloat(String key) throws NumberFormatException {
String str = getString(key);
if (str != null)
return Float.parseFloat(str);
else
throw new NumberFormatException();
}
public boolean getBoolean(String key) {
String str = getString(key);

View File

@ -9,7 +9,6 @@ import android.content.*;
import android.app.*;
import android.media.AudioManager;
import android.os.*;
import android.preference.PreferenceManager;
import android.widget.*;
import android.view.*;
@ -107,7 +106,7 @@ public class DirectoryActivity extends Activity implements
private void finishWithPath(String path) {
if (pathSettingKey != null && !pathSettingKey.isEmpty()) {
SharedPreferences settings = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences settings = MainMenuActivity.getPreferences();
SharedPreferences.Editor editor = settings.edit();
editor.putString(pathSettingKey, path);
editor.commit();

View File

@ -8,7 +8,6 @@ import android.content.SharedPreferences;
import android.opengl.GLES20;
import android.opengl.GLSurfaceView;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.util.Log;
import android.view.WindowManager;
import android.widget.Toast;
@ -36,7 +35,7 @@ public class DisplayRefreshRateTest extends Activity {
}
private void setFPSSetting(double fps) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.valueOf(fps).toString());
edit.commit();
@ -117,7 +116,7 @@ public class DisplayRefreshRateTest extends Activity {
@Override
protected void onDestroy() {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = MainMenuActivity.getPreferences();
String fps = prefs.getString("video_refresh_rate", "ERROR");
Toast.makeText(this, "Refresh rate measured to: " + fps + " Hz.", Toast.LENGTH_LONG).show();
super.onDestroy();

View File

@ -0,0 +1,16 @@
package org.retroarch.browser;
import android.app.Activity;
import android.content.Context;
import android.os.Bundle;
import android.view.inputmethod.InputMethodManager;
public class IMEActivity extends Activity {
@Override
protected void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
imm.showInputMethodPicker();
finish();
}
}

View File

@ -11,12 +11,15 @@ import android.content.Context;
import android.content.DialogInterface;
import android.content.Intent;
import android.content.SharedPreferences;
import android.content.pm.PackageManager;
import android.content.pm.PackageManager.NameNotFoundException;
import android.content.res.AssetManager;
import android.media.AudioManager;
import android.media.AudioTrack;
import android.os.Bundle;
import android.os.Handler;
import android.preference.CheckBoxPreference;
import android.preference.Preference;
import android.preference.PreferenceActivity;
import android.preference.PreferenceManager;
import android.provider.Settings;
@ -31,20 +34,58 @@ public class MainMenuActivity extends PreferenceActivity {
static private final String TAG = "MainMenu";
static private String libretro_path;
static private String libretro_name;
private boolean globalConfigEnable = true;
@SuppressWarnings("deprecation")
private void refreshPreferenceScreen() {
readbackConfigFile();
setPreferenceScreen(null);
addPreferencesFromResource(R.xml.prefs);
setCoreTitle(libretro_name);
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
final CheckBoxPreference param = (CheckBoxPreference) findPreference("global_config_enable");
globalConfigEnable = param.isChecked();
param.setOnPreferenceClickListener(new Preference.OnPreferenceClickListener() {
@Override
public boolean onPreferenceClick(Preference preference) {
updateConfigFile();
globalConfigEnable = param.isChecked();
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences.Editor edit = prefs.edit();
edit.putBoolean("global_config_enable", param.isChecked());
edit.commit();
refreshPreferenceScreen();
return true;
}
});
}
private boolean usePerCoreConfig() {
boolean config_same_as_native_lib_dir = libretro_path
.equals(getApplicationInfo().nativeLibraryDir);
return !globalConfigEnable && !config_same_as_native_lib_dir;
}
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
instance = this;
SharedPreferences prefs = getPreferences();
libretro_path = prefs.getString("libretro_path", getApplicationInfo().nativeLibraryDir);
libretro_name = prefs.getString("libretro_name", "No core");
addPreferencesFromResource(R.xml.prefs);
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
refreshPreferenceScreen();
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
extractAssets();
if (!prefs.getBoolean("first_time_refreshrate_calculate", false)) {
@ -56,37 +97,11 @@ public class MainMenuActivity extends PreferenceActivity {
.setTitle("Welcome to RetroArch")
.setMessage(
"This is your first time starting up RetroArch. RetroArch will now be preconfigured for the best possible gameplay experience.")
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences.Editor edit = prefs
.edit();
edit.putBoolean("video_threaded", true);
edit.commit();
}
});
.setPositiveButton("OK", null);
alert.show();
}
}
if (prefs.getString("libretro_path", "").isEmpty() == false) {
libretro_path = prefs.getString("libretro_path", "");
setCoreTitle("No core");
if (prefs.getString("libretro_name", "").isEmpty() == false) {
libretro_name = prefs.getString("libretro_name", "No core");
setCoreTitle(libretro_name);
}
} else {
libretro_path = MainMenuActivity.getInstance().getApplicationInfo().nativeLibraryDir;
libretro_name = "No core";
setCoreTitle("No core");
}
Intent startedByIntent = getIntent();
if (null != startedByIntent.getStringExtra("ROM")
&& null != startedByIntent.getStringExtra("LIBRETRO")) {
@ -119,19 +134,17 @@ public class MainMenuActivity extends PreferenceActivity {
public static final double getRefreshRate() {
double rate = 0;
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(MainMenuActivity.getInstance()
.getBaseContext());
SharedPreferences prefs = getPreferences();
String refresh_rate = prefs.getString("video_refresh_rate", "");
if (!refresh_rate.isEmpty()) {
try {
rate = Double.parseDouble(refresh_rate);
} catch (NumberFormatException e) {
Log.e(TAG, "Cannot parse: " + refresh_rate + " as a double!");
rate = MainMenuActivity.getInstance().getDisplayRefreshRate();
rate = getInstance().getDisplayRefreshRate();
}
} else {
rate = MainMenuActivity.getInstance().getDisplayRefreshRate();
rate = getInstance().getDisplayRefreshRate();
}
Log.i(TAG, "Using refresh rate: " + rate + " Hz.");
@ -157,12 +170,29 @@ public class MainMenuActivity extends PreferenceActivity {
@TargetApi(17)
public static int getLowLatencyOptimalSamplingRate() {
AudioManager manager = (AudioManager) MainMenuActivity.getInstance()
AudioManager manager = (AudioManager) getInstance()
.getApplicationContext()
.getSystemService(Context.AUDIO_SERVICE);
return Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
}
@TargetApi(17)
public static int getLowLatencyBufferSize() {
AudioManager manager = (AudioManager) getInstance()
.getApplicationContext()
.getSystemService(Context.AUDIO_SERVICE);
int buffersize = Integer.parseInt(manager
.getProperty(AudioManager.PROPERTY_OUTPUT_FRAMES_PER_BUFFER));
Log.i(TAG, "Queried ideal buffer size (frames): " + buffersize);
return buffersize;
}
@TargetApi(17)
public static boolean hasLowLatencyAudio() {
PackageManager pm = getInstance().getPackageManager();
return pm.hasSystemFeature(PackageManager.FEATURE_AUDIO_LOW_LATENCY);
}
public static int getOptimalSamplingRate() {
int ret;
@ -175,27 +205,24 @@ public class MainMenuActivity extends PreferenceActivity {
Log.i(TAG, "Using sampling rate: " + ret + " Hz");
return ret;
}
private static String sanitizeLibretroPath(String path) {
String sanitized_name = path.substring(
path.lastIndexOf("/") + 1,
path.lastIndexOf("."));
sanitized_name = sanitized_name.replace("neon", "");
sanitized_name = sanitized_name.replace("libretro_", "");
return sanitized_name;
}
public static String getDefaultConfigPath() {
String internal = System.getenv("INTERNAL_STORAGE");
String external = System.getenv("EXTERNAL_STORAGE");
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(MainMenuActivity.getInstance()
.getBaseContext());
boolean global_config_enable = prefs.getBoolean("global_config_enable",
true);
boolean config_same_as_native_lib_dir = libretro_path
.equals(MainMenuActivity.getInstance().getApplicationInfo().nativeLibraryDir);
String append_path;
if (!global_config_enable && (config_same_as_native_lib_dir == false)) {
String sanitized_name = libretro_path.substring(
libretro_path.lastIndexOf("/") + 1,
libretro_path.lastIndexOf("."));
sanitized_name = sanitized_name.replace("neon", "");
sanitized_name = sanitized_name.replace("libretro_", "");
append_path = File.separator + sanitized_name + "retroarch.cfg";
if (getInstance().usePerCoreConfig()) {
String sanitized_name = sanitizeLibretroPath(libretro_path);
append_path = File.separator + sanitized_name + ".cfg";
} else {
append_path = File.separator + "retroarch.cfg";
}
@ -219,40 +246,138 @@ public class MainMenuActivity extends PreferenceActivity {
else if (external != null
&& new File(internal + append_path).canWrite())
return external + append_path;
else if ((MainMenuActivity.getInstance().getApplicationInfo().dataDir) != null)
return (MainMenuActivity.getInstance().getApplicationInfo().dataDir)
else if ((getInstance().getApplicationInfo().dataDir) != null)
return (getInstance().getApplicationInfo().dataDir)
+ append_path;
else
// emergency fallback, all else failed
return "/mnt/sd" + append_path;
}
public void updateConfigFile() {
private void readbackString(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putString(key, cfg.getString(key));
else
edit.remove(key);
}
private void readbackBool(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putBoolean(key, cfg.getBoolean(key));
else
edit.remove(key);
}
private void readbackDouble(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putFloat(key, (float)cfg.getDouble(key));
else
edit.remove(key);
}
private void readbackFloat(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putFloat(key, cfg.getFloat(key));
else
edit.remove(key);
}
private void readbackInt(ConfigFile cfg, SharedPreferences.Editor edit, String key) {
if (cfg.keyExists(key))
edit.putInt(key, cfg.getInt(key));
else
edit.remove(key);
}
public void readbackConfigFile() {
String path = getDefaultConfigPath();
ConfigFile config;
try {
config = new ConfigFile(new File(getDefaultConfigPath()));
config = new ConfigFile(new File(path));
} catch (IOException e) {
return;
}
Log.i(TAG, "Config readback from: " + path);
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs.edit();
readbackString(config, edit, "rgui_browser_directory");
readbackString(config, edit, "savefile_directory");
readbackString(config, edit, "savestate_directory");
readbackBool(config, edit, "savefile_directory_enable"); // Ignored by RetroArch
readbackBool(config, edit, "savestate_directory_enable"); // Ignored by RetroArch
readbackString(config, edit, "input_overlay");
readbackBool(config, edit, "input_overlay_enable");
readbackBool(config, edit, "video_scale_integer");
readbackBool(config, edit, "video_smooth");
readbackBool(config, edit, "video_threaded");
readbackBool(config, edit, "rewind_enable");
readbackBool(config, edit, "savestate_auto_load");
readbackBool(config, edit, "savestate_auto_save");
//readbackDouble(config, edit, "video_refresh_rate");
readbackBool(config, edit, "audio_rate_control");
readbackBool(config, edit, "audio_enable");
// TODO: other audio settings
readbackDouble(config, edit, "input_overlay_opacity");
readbackBool(config, edit, "input_autodetect_enable");
//readbackInt(config, edit, "input_back_behavior");
readbackBool(config, edit, "video_allow_rotate");
readbackBool(config, edit, "video_font_enable");
readbackBool(config, edit, "video_vsync");
edit.commit();
}
public void updateConfigFile() {
String path = getDefaultConfigPath();
ConfigFile config;
try {
config = new ConfigFile(new File(path));
} catch (IOException e) {
config = new ConfigFile();
}
Log.i(TAG, "Writing config to: " + path);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(MainMenuActivity.getInstance()
.getBaseContext());
SharedPreferences prefs = getPreferences();
config.setString("libretro_path", libretro_path);
config.setString("libretro_name", libretro_name);
setCoreTitle(libretro_name);
config.setString("rgui_browser_directory",
prefs.getString("rgui_browser_directory", ""));
config.setBoolean("global_config_enable",
prefs.getBoolean("global_config_enable", true));
config.setBoolean("audio_rate_control",
prefs.getBoolean("audio_rate_control", true));
config.setInt("audio_out_rate",
MainMenuActivity.getOptimalSamplingRate());
config.setInt("audio_latency",
prefs.getBoolean("audio_high_latency", false) ? 160 : 64);
int optimalRate = getOptimalSamplingRate();
config.setInt("audio_out_rate", optimalRate);
// Refactor this entire mess and make this usable for per-core config
if (android.os.Build.VERSION.SDK_INT >= 17) {
int buffersize = getLowLatencyBufferSize();
boolean lowLatency = hasLowLatencyAudio();
Log.i(TAG, "Audio is low latency: " + (lowLatency ? "yes" : "no"));
if (lowLatency && !prefs.getBoolean("audio_high_latency", false)) {
config.setInt("audio_latency", 64);
config.setInt("audio_block_frames", buffersize);
} else {
config.setInt("audio_latency", prefs.getBoolean(
"audio_high_latency", false) ? 160 : 64);
config.setInt("audio_block_frames", 0);
}
} else {
config.setInt("audio_latency",
prefs.getBoolean("audio_high_latency", false) ? 160 : 64);
}
config.setBoolean("audio_enable",
prefs.getBoolean("audio_enable", true));
config.setBoolean("video_smooth",
@ -286,10 +411,12 @@ public class MainMenuActivity extends PreferenceActivity {
"0")));
config.setDouble("video_refresh_rate",
MainMenuActivity.getRefreshRate());
getRefreshRate());
config.setBoolean("video_threaded",
prefs.getBoolean("video_threaded", true));
// Refactor these weird values - 'full', 'auto', 'square', whatever -
// go by what we have in RGUI - makes maintaining state easier too
String aspect = prefs.getString("video_aspect_ratio", "auto");
if (aspect.equals("full")) {
config.setBoolean("video_force_aspect", false);
@ -317,9 +444,10 @@ public class MainMenuActivity extends PreferenceActivity {
&& new File(shaderPath).exists());
boolean useOverlay = prefs.getBoolean("input_overlay_enable", true);
config.setBoolean("input_overlay_enable", useOverlay); // Not used by RetroArch directly.
if (useOverlay) {
String overlayPath = prefs
.getString("input_overlay", (MainMenuActivity.getInstance()
.getString("input_overlay", (getInstance()
.getApplicationInfo().dataDir)
+ "/overlays/snes-landscape.cfg");
config.setString("input_overlay", overlayPath);
@ -328,7 +456,6 @@ public class MainMenuActivity extends PreferenceActivity {
} else {
config.setString("input_overlay", "");
}
config.setString(
"savefile_directory",
prefs.getBoolean("savefile_directory_enable", false) ? prefs
@ -345,7 +472,7 @@ public class MainMenuActivity extends PreferenceActivity {
config.setBoolean("video_font_enable",
prefs.getBoolean("video_font_enable", true));
config.setString("game_history_path", MainMenuActivity.getInstance()
config.setString("game_history_path", getInstance()
.getApplicationInfo().dataDir + "/retroarch-history.txt");
for (int i = 1; i <= 4; i++) {
@ -359,11 +486,10 @@ public class MainMenuActivity extends PreferenceActivity {
}
}
String confPath = getDefaultConfigPath();
try {
config.write(new File(confPath));
config.write(new File(path));
} catch (IOException e) {
Log.e(TAG, "Failed to save config file to: " + confPath);
Log.e(TAG, "Failed to save config file to: " + path);
}
}
@ -499,20 +625,28 @@ public class MainMenuActivity extends PreferenceActivity {
dialog.show();
}
public static SharedPreferences getPreferences() {
return PreferenceManager.getDefaultSharedPreferences(getInstance().getBaseContext());
}
public void setModule(String core_path, String core_name) {
updateConfigFile();
libretro_path = core_path;
libretro_name = core_name;
File libretro_path_file = new File(core_path);
setCoreTitle((libretro_path_file.isDirectory() == true) ? "No core"
: core_name);
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs.edit();
edit.putString("libretro_path", libretro_path);
edit.putString("libretro_name", libretro_name);
edit.commit();
if (usePerCoreConfig())
refreshPreferenceScreen();
else {
setCoreTitle(libretro_name); // this still needs to be applied
}
}
public void setCoreTitle(String core_name) {
@ -538,8 +672,7 @@ public class MainMenuActivity extends PreferenceActivity {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs
.edit();
edit.putString("video_refresh_rate", Double
@ -562,8 +695,7 @@ public class MainMenuActivity extends PreferenceActivity {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs
.edit();
edit.putBoolean("input_overlay_enable",
@ -585,8 +717,7 @@ public class MainMenuActivity extends PreferenceActivity {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs
.edit();
edit.putBoolean("input_overlay_enable",
@ -598,6 +729,27 @@ public class MainMenuActivity extends PreferenceActivity {
});
alert.show();
retval = true;
} else if (android.os.Build.MODEL.equals("R800x")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle("Xperia Play detected")
.setMessage(message)
.setPositiveButton("OK",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs
.edit();
edit.putBoolean("input_overlay_enable",
false);
edit.putBoolean("input_autodetect_enable",
true);
edit.commit();
}
});
alert.show();
retval = true;
} else if (android.os.Build.ID.equals("JSS15J")) {
AlertDialog.Builder alert = new AlertDialog.Builder(this)
.setTitle("Nexus 7 2013 detected")
@ -607,8 +759,7 @@ public class MainMenuActivity extends PreferenceActivity {
@Override
public void onClick(DialogInterface dialog,
int which) {
SharedPreferences prefs = PreferenceManager
.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = getPreferences();
SharedPreferences.Editor edit = prefs
.edit();
edit.putString("video_refresh_rate", Double
@ -626,6 +777,8 @@ public class MainMenuActivity extends PreferenceActivity {
"Device either not detected in list or doesn't have any optimal settings in our database.",
Toast.LENGTH_SHORT).show();
}
refreshPreferenceScreen();
return retval;
}
@ -668,7 +821,7 @@ public class MainMenuActivity extends PreferenceActivity {
myIntent.putExtra("ROM", data.getStringExtra("PATH"));
myIntent.putExtra("LIBRETRO", libretro_path);
myIntent.putExtra("CONFIGFILE",
MainMenuActivity.getDefaultConfigPath());
getDefaultConfigPath());
myIntent.putExtra("IME", current_ime);
startActivity(myIntent);
}

View File

@ -4,13 +4,12 @@ import java.io.File;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
public class ROMActivity extends DirectoryActivity {
@Override
public void onCreate(Bundle savedInstanceState) {
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = MainMenuActivity.getPreferences();
String startPath = prefs.getString("rgui_browser_directory", "");
if (!startPath.isEmpty() && new File(startPath).exists())
super.setStartDirectory(startPath);

View File

@ -4,7 +4,6 @@ import android.app.Activity;
import android.content.Context;
import android.content.SharedPreferences;
import android.os.Bundle;
import android.preference.PreferenceManager;
import android.view.Display;
import android.view.WindowManager;
import android.widget.Toast;
@ -18,7 +17,7 @@ public class RefreshRateSetOS extends Activity {
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
final Display display = wm.getDefaultDisplay();
double rate = display.getRefreshRate();
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
SharedPreferences prefs = MainMenuActivity.getPreferences();
SharedPreferences.Editor edit = prefs.edit();
edit.putString("video_refresh_rate", Double.valueOf(rate).toString());
edit.commit();

View File

@ -2,6 +2,7 @@ package org.retroarch.browser;
import android.app.Activity;
import android.app.AlertDialog;
import android.content.DialogInterface;
import android.os.Bundle;
import android.provider.Settings;
@ -9,7 +10,27 @@ public class ReportIME extends Activity {
@Override
public void onCreate(Bundle savedInstanceState) {
super.onCreate(savedInstanceState);
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
new AlertDialog.Builder(this).setMessage(current_ime).setNeutralButton("Close", null).show();
String current_ime = Settings.Secure.getString(getContentResolver(),
Settings.Secure.DEFAULT_INPUT_METHOD);
final Activity ctx = this;
AlertDialog.Builder dialog = new AlertDialog.Builder(this)
.setMessage(current_ime)
.setNeutralButton("Close",
new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog,
int which) {
ctx.finish();
}
}).setCancelable(true)
.setOnCancelListener(new DialogInterface.OnCancelListener() {
@Override
public void onCancel(DialogInterface dialog) {
ctx.finish();
}
});
dialog.show();
}
}

View File

@ -0,0 +1,384 @@
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="NS.object.0">3084</string>
</object>
<array key="IBDocument.IntegratedClassDependencies">
<string>IBNSLayoutConstraint</string>
<string>NSButton</string>
<string>NSButtonCell</string>
<string>NSCustomObject</string>
<string>NSTextField</string>
<string>NSTextFieldCell</string>
<string>NSView</string>
<string>NSWindowTemplate</string>
</array>
<array key="IBDocument.PluginDependencies">
<string>com.apple.InterfaceBuilder.CocoaPlugin</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="NSCustomObject" id="1001">
<string key="NSClassName">NSWindowController</string>
</object>
<object class="NSCustomObject" id="1003">
<string key="NSClassName">FirstResponder</string>
</object>
<object class="NSCustomObject" id="1004">
<string key="NSClassName">NSApplication</string>
</object>
<object class="NSWindowTemplate" id="1005">
<int key="NSWindowStyleMask">15</int>
<int key="NSWindowBacking">2</int>
<string key="NSWindowRect">{{196, 240}, {480, 109}}</string>
<int key="NSWTFlags">544735232</int>
<string key="NSWindowTitle">Window</string>
<string key="NSWindowClass">RAInputBinder</string>
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="1006">
<reference key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="693377980">
<reference key="NSNextResponder" ref="1006"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{17, 72}, {446, 17}}</string>
<reference key="NSSuperview" ref="1006"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="606338068"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
<object class="NSTextFieldCell" key="NSCell" id="270729776">
<int key="NSCellFlags">68157504</int>
<int key="NSCellFlags2">138413056</int>
<string key="NSContents">Press a Key, Joystick Button, or move a Joystick Axis</string>
<object class="NSFont" key="NSSupport" id="965449829">
<string key="NSName">LucidaGrande</string>
<double key="NSSize">13</double>
<int key="NSfFlags">1044</int>
</object>
<string key="NSCellIdentifier">_NS:1535</string>
<reference key="NSControlView" ref="693377980"/>
<object class="NSColor" key="NSBackgroundColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MC42NjY2NjY2NjY3AA</bytes>
</object>
</object>
<object class="NSColor" key="NSTextColor">
<int key="NSColorSpace">6</int>
<string key="NSCatalogName">System</string>
<string key="NSColorName">controlTextColor</string>
<object class="NSColor" key="NSColor">
<int key="NSColorSpace">3</int>
<bytes key="NSWhite">MAA</bytes>
</object>
</object>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
<object class="NSButton" id="606338068">
<reference key="NSNextResponder" ref="1006"/>
<int key="NSvFlags">268</int>
<string key="NSFrame">{{384, 13}, {82, 32}}</string>
<reference key="NSSuperview" ref="1006"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="548104382">
<int key="NSCellFlags">67108864</int>
<int key="NSCellFlags2">134217728</int>
<string key="NSContents">Cancel</string>
<reference key="NSSupport" ref="965449829"/>
<string key="NSCellIdentifier">_NS:9</string>
<reference key="NSControlView" ref="606338068"/>
<int key="NSButtonFlags">-2038284288</int>
<int key="NSButtonFlags2">129</int>
<reference key="NSAlternateImage" ref="965449829"/>
<string key="NSAlternateContents"/>
<string type="base64-UTF8" key="NSKeyEquivalent">Gw</string>
<int key="NSPeriodicDelay">200</int>
<int key="NSPeriodicInterval">25</int>
</object>
<bool key="NSAllowsLogicalLayoutDirection">NO</bool>
</object>
</array>
<string key="NSFrameSize">{480, 109}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="693377980"/>
</object>
<string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
<bool key="NSWindowIsRestorable">YES</bool>
</object>
</array>
<object class="IBObjectContainer" key="IBDocument.Objects">
<array class="NSMutableArray" key="connectionRecords">
<object class="IBConnectionRecord">
<object class="IBOutletConnection" key="connection">
<string key="label">window</string>
<reference key="source" ref="1001"/>
<reference key="destination" ref="1005"/>
</object>
<int key="connectionID">3</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">goAway:</string>
<reference key="source" ref="1005"/>
<reference key="destination" ref="606338068"/>
</object>
<int key="connectionID">20</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">-2</int>
<reference key="object" ref="1001"/>
<reference key="parent" ref="0"/>
<string key="objectName">File's Owner</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-1</int>
<reference key="object" ref="1003"/>
<reference key="parent" ref="0"/>
<string key="objectName">First Responder</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">-3</int>
<reference key="object" ref="1004"/>
<reference key="parent" ref="0"/>
<string key="objectName">Application</string>
</object>
<object class="IBObjectRecord">
<int key="objectID">1</int>
<reference key="object" ref="1005"/>
<array class="NSMutableArray" key="children">
<reference ref="1006"/>
</array>
<reference key="parent" ref="0"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">2</int>
<reference key="object" ref="1006"/>
<array class="NSMutableArray" key="children">
<object class="IBNSLayoutConstraint" id="952757161">
<reference key="firstItem" ref="1006"/>
<int key="firstAttribute">4</int>
<int key="relation">0</int>
<reference key="secondItem" ref="606338068"/>
<int key="secondAttribute">4</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1006"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="1024300700">
<reference key="firstItem" ref="1006"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="606338068"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1006"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="547048879">
<reference key="firstItem" ref="693377980"/>
<int key="firstAttribute">3</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1006"/>
<int key="secondAttribute">3</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1006"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="101981711">
<reference key="firstItem" ref="1006"/>
<int key="firstAttribute">6</int>
<int key="relation">0</int>
<reference key="secondItem" ref="693377980"/>
<int key="secondAttribute">6</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1006"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<object class="IBNSLayoutConstraint" id="362753409">
<reference key="firstItem" ref="693377980"/>
<int key="firstAttribute">5</int>
<int key="relation">0</int>
<reference key="secondItem" ref="1006"/>
<int key="secondAttribute">5</int>
<float key="multiplier">1</float>
<object class="IBNSLayoutSymbolicConstant" key="constant">
<double key="value">20</double>
</object>
<float key="priority">1000</float>
<reference key="containingView" ref="1006"/>
<int key="scoringType">8</int>
<float key="scoringTypeFloat">29</float>
<int key="contentType">3</int>
</object>
<reference ref="693377980"/>
<reference ref="606338068"/>
</array>
<reference key="parent" ref="1005"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">4</int>
<reference key="object" ref="693377980"/>
<array class="NSMutableArray" key="children">
<reference ref="270729776"/>
</array>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">5</int>
<reference key="object" ref="270729776"/>
<reference key="parent" ref="693377980"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">9</int>
<reference key="object" ref="362753409"/>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">10</int>
<reference key="object" ref="101981711"/>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">11</int>
<reference key="object" ref="547048879"/>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">12</int>
<reference key="object" ref="606338068"/>
<array class="NSMutableArray" key="children">
<reference ref="548104382"/>
</array>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">13</int>
<reference key="object" ref="548104382"/>
<reference key="parent" ref="606338068"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">14</int>
<reference key="object" ref="1024300700"/>
<reference key="parent" ref="1006"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">15</int>
<reference key="object" ref="952757161"/>
<reference key="parent" ref="1006"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
<string key="-1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="-3.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="1.IBWindowTemplateEditedContentRect">{{357, 418}, {480, 270}}</string>
<boolean value="NO" key="1.NSWindowTemplate.visibleAtLaunch"/>
<string key="10.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="11.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="12.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="12.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="13.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="14.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="15.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<array key="2.IBNSViewMetadataConstraints">
<reference ref="362753409"/>
<reference ref="101981711"/>
<reference ref="547048879"/>
<reference ref="1024300700"/>
<reference ref="952757161"/>
</array>
<string key="2.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<boolean value="NO" key="4.IBNSViewMetadataTranslatesAutoresizingMaskIntoConstraints"/>
<string key="4.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="5.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="9.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="unlocalizedProperties"/>
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">20</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
<object class="IBPartialClassDescription">
<string key="className">NSLayoutConstraint</string>
<string key="superclassName">NSObject</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/NSLayoutConstraint.h</string>
</object>
</object>
<object class="IBPartialClassDescription">
<string key="className">RAInputBinder</string>
<string key="superclassName">NSWindow</string>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/RAInputBinder.h</string>
</object>
</object>
</array>
</object>
<int key="IBDocument.localizationMode">0</int>
<string key="IBDocument.TargetRuntimeIdentifier">IBCocoaFramework</string>
<bool key="IBDocument.PluginDeclaredDependenciesTrackSystemTargetVersion">YES</bool>
<int key="IBDocument.defaultPropertyAccessControl">3</int>
<bool key="IBDocument.UseAutolayout">YES</bool>
</data>
</archive>

View File

@ -2,9 +2,9 @@
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
<data>
<int key="IBDocument.SystemTarget">1080</int>
<string key="IBDocument.SystemVersion">12D78</string>
<string key="IBDocument.SystemVersion">12E55</string>
<string key="IBDocument.InterfaceBuilderVersion">3084</string>
<string key="IBDocument.AppKitVersion">1187.37</string>
<string key="IBDocument.AppKitVersion">1187.39</string>
<string key="IBDocument.HIToolboxVersion">626.00</string>
<object class="NSMutableDictionary" key="IBDocument.PluginVersions">
<string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -297,6 +297,28 @@
</array>
</object>
</object>
<object class="NSMenuItem" id="1225315">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">Go</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
<string key="NSAction">submenuAction:</string>
<object class="NSMenu" key="NSSubmenu" id="715293634">
<string key="NSTitle">Go</string>
<array class="NSMutableArray" key="NSMenuItems">
<object class="NSMenuItem" id="777071989">
<reference key="NSMenu" ref="715293634"/>
<string key="NSTitle">Cores Directory</string>
<string key="NSKeyEquiv"/>
<int key="NSMnemonicLoc">2147483647</int>
<reference key="NSOnImage" ref="35465992"/>
<reference key="NSMixedImage" ref="502551668"/>
</object>
</array>
</object>
</object>
<object class="NSMenuItem" id="713487014">
<reference key="NSMenu" ref="649796088"/>
<string key="NSTitle">Window</string>
@ -397,11 +419,9 @@
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="439893737">
<reference key="NSNextResponder"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<string key="NSFrameSize">{480, 360}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
</object>
<string key="NSScreenRect">{{0, 0}, {2560, 1418}}</string>
<string key="NSMaxSize">{10000000000000, 10000000000000}</string>
@ -420,7 +440,7 @@
<nil key="NSViewClass"/>
<nil key="NSUserInterfaceItemIdentifier"/>
<object class="NSView" key="NSWindowView" id="327272550">
<reference key="NSNextResponder"/>
<nil key="NSNextResponder"/>
<int key="NSvFlags">256</int>
<array class="NSMutableArray" key="NSSubviews">
<object class="NSTextField" id="981013832">
@ -428,7 +448,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{17, 72}, {242, 17}}</string>
<reference key="NSSuperview" ref="327272550"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="481701893"/>
<string key="NSReuseIdentifierKey">_NS:1535</string>
<bool key="NSEnabled">YES</bool>
@ -470,7 +489,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{20, 45}, {239, 26}}</string>
<reference key="NSSuperview" ref="327272550"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="59737118"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<int key="NSTag">1</int>
@ -499,7 +517,7 @@
<object class="NSComboTableView" key="NSTableView" id="845451530">
<reference key="NSNextResponder"/>
<int key="NSvFlags">274</int>
<string key="NSFrameSize">{13, 0}</string>
<string key="NSFrameSize">{15, 0}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:24</string>
@ -508,7 +526,7 @@
<bool key="NSControlAllowsExpansionToolTips">YES</bool>
<array class="NSMutableArray" key="NSTableColumns">
<object class="NSTableColumn">
<double key="NSWidth">10</double>
<double key="NSWidth">12</double>
<double key="NSMinWidth">10</double>
<double key="NSMaxWidth">1000</double>
<object class="NSTableHeaderCell" key="NSHeaderCell">
@ -559,7 +577,7 @@
</object>
<double key="NSRowHeight">19</double>
<string key="NSAction">tableViewAction:</string>
<int key="NSTvFlags">-765427712</int>
<int key="NSTvFlags">-767524864</int>
<reference key="NSDelegate" ref="50876060"/>
<reference key="NSDataSource" ref="50876060"/>
<reference key="NSTarget" ref="50876060"/>
@ -578,7 +596,6 @@
<int key="NSvFlags">268</int>
<string key="NSFrame">{{180, 13}, {82, 32}}</string>
<reference key="NSSuperview" ref="327272550"/>
<reference key="NSWindow"/>
<string key="NSReuseIdentifierKey">_NS:9</string>
<bool key="NSEnabled">YES</bool>
<object class="NSButtonCell" key="NSCell" id="404714727">
@ -599,8 +616,6 @@
</object>
</array>
<string key="NSFrameSize">{276, 89}</string>
<reference key="NSSuperview"/>
<reference key="NSWindow"/>
<reference key="NSNextKeyView" ref="981013832"/>
<string key="NSReuseIdentifierKey">_NS:21</string>
</object>
@ -787,6 +802,14 @@
</object>
<int key="connectionID">584</int>
</object>
<object class="IBConnectionRecord">
<object class="IBActionConnection" key="connection">
<string key="label">showCoresDirectory:</string>
<reference key="source" ref="976324537"/>
<reference key="destination" ref="777071989"/>
</object>
<int key="connectionID">588</int>
</object>
</array>
<object class="IBMutableOrderedSet" key="objectRecords">
<array key="orderedObjects">
@ -823,6 +846,7 @@
<reference ref="379814623"/>
<reference ref="448692316"/>
<reference ref="265357942"/>
<reference ref="1225315"/>
</array>
<reference key="parent" ref="0"/>
</object>
@ -1339,6 +1363,27 @@
<reference key="object" ref="257009827"/>
<reference key="parent" ref="835318025"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">585</int>
<reference key="object" ref="1225315"/>
<array class="NSMutableArray" key="children">
<reference ref="715293634"/>
</array>
<reference key="parent" ref="649796088"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">586</int>
<reference key="object" ref="715293634"/>
<array class="NSMutableArray" key="children">
<reference ref="777071989"/>
</array>
<reference key="parent" ref="1225315"/>
</object>
<object class="IBObjectRecord">
<int key="objectID">587</int>
<reference key="object" ref="777071989"/>
<reference key="parent" ref="715293634"/>
</object>
</array>
</object>
<dictionary class="NSMutableDictionary" key="flattenedProperties">
@ -1417,6 +1462,9 @@
<string key="579.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="58.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="582.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="585.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="586.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="587.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="72.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="73.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
<string key="79.IBPluginDependency">com.apple.InterfaceBuilder.CocoaPlugin</string>
@ -1428,7 +1476,7 @@
<nil key="activeLocalization"/>
<dictionary class="NSMutableDictionary" key="localizations"/>
<nil key="sourceID"/>
<int key="maxID">584</int>
<int key="maxID">588</int>
</object>
<object class="IBClassDescriber" key="IBDocument.Classes">
<array class="NSMutableArray" key="referencedPartialClassDescriptions">
@ -1443,6 +1491,39 @@
<object class="IBPartialClassDescription">
<string key="className">RetroArch_OSX</string>
<string key="superclassName">NSObject</string>
<dictionary class="NSMutableDictionary" key="actions">
<string key="coreWasChosen:">id</string>
<string key="showCoresDirectory:">id</string>
<string key="showPreferences:">id</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="actionInfosByName">
<object class="IBActionInfo" key="coreWasChosen:">
<string key="name">coreWasChosen:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showCoresDirectory:">
<string key="name">showCoresDirectory:</string>
<string key="candidateClassName">id</string>
</object>
<object class="IBActionInfo" key="showPreferences:">
<string key="name">showPreferences:</string>
<string key="candidateClassName">id</string>
</object>
</dictionary>
<dictionary class="NSMutableDictionary" key="outlets">
<string key="_coreSelectSheet">NSWindow</string>
<string key="window">NSWindow</string>
</dictionary>
<dictionary class="NSMutableDictionary" key="toOneOutletInfosByName">
<object class="IBToOneOutletInfo" key="_coreSelectSheet">
<string key="name">_coreSelectSheet</string>
<string key="candidateClassName">NSWindow</string>
</object>
<object class="IBToOneOutletInfo" key="window">
<string key="name">window</string>
<string key="candidateClassName">NSWindow</string>
</object>
</dictionary>
<object class="IBClassDescriptionSource" key="sourceIdentifier">
<string key="majorKey">IBProjectSource</string>
<string key="minorKey">./Classes/RetroArch_OSX.h</string>

File diff suppressed because it is too large Load Diff

View File

@ -14,14 +14,44 @@
*/
#include <IOKit/hid/IOHIDManager.h>
#include "../RetroArch/apple_input.h"
#include "apple/common/apple_input.h"
// NOTE: I pieced this together through trial and error, any corrections are welcome
static IOHIDManagerRef g_hid_manager;
static uint32_t g_num_pads;
static uint32_t g_pad_slots;
static void hid_input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef inIOHIDValueRef)
#define HID_ISSET(t, x) (t & (1 << x))
#define HID_SET(t, x) { t |= (1 << x); }
#define HID_CLEAR(t, x) { t &= ~(1 << x); }
// Set the LEDs on PS3 controllers, if slot >= MAX_PADS the LEDs will be cleared
static void osx_pad_set_leds(IOHIDDeviceRef device, uint32_t slot)
{
char buffer[1024];
CFStringRef device_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
if (device_name)
{
CFStringGetCString(device_name, buffer, 1024, kCFStringEncodingUTF8);
if (strncmp(buffer, "PLAYSTATION(R)3 Controller", 1024) == 0)
{
static uint8_t report_buffer[] = {
0x01,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0x27,
0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0xff, 0x27, 0x10, 0x00,
0x32, 0xff, 0x27, 0x10, 0x00, 0x32, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00
};
report_buffer[10] = (slot >= MAX_PADS) ? 0 : (1 << (slot + 1));
IOHIDDeviceSetReport(device, kIOHIDReportTypeOutput, 0x01, report_buffer, sizeof(report_buffer));
}
}
}
static void hid_device_input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef inIOHIDValueRef)
{
IOHIDElementRef element = IOHIDValueGetElement(inIOHIDValueRef);
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
@ -82,25 +112,49 @@ static void hid_input_callback(void* inContext, IOReturn inResult, void* inSende
}
}
static void hid_device_attached(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef inDevice)
static void hid_device_removed(void* inContext, IOReturn inResult, void* inSender)
{
void* context = 0;
IOHIDDeviceRef inDevice = (IOHIDDeviceRef)inSender;
if (IOHIDDeviceConformsTo(inDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))
{
if (g_num_pads > 4)
return;
context = (void*)(g_num_pads++);
uint32_t pad_index = (uint32_t)inContext;
if (pad_index < MAX_PADS)
{
HID_CLEAR(g_pad_slots, pad_index);
g_current_input_data.pad_buttons[pad_index] = 0;
memset(g_current_input_data.pad_axis[pad_index], 0, sizeof(g_current_input_data.pad_axis));
}
}
IOHIDDeviceOpen(inDevice, kIOHIDOptionsTypeNone);
IOHIDDeviceScheduleWithRunLoop(inDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDDeviceRegisterInputValueCallback(inDevice, hid_input_callback, context);
osx_pad_set_leds(inDevice, MAX_PADS);
IOHIDDeviceClose(inDevice, kIOHIDOptionsTypeNone);
}
static void hid_device_removed(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef inDevice)
static void hid_manager_device_attached(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef inDevice)
{
IOHIDDeviceClose(inDevice, kIOHIDOptionsTypeNone);
uint32_t pad_index = 0;
if (IOHIDDeviceConformsTo(inDevice, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))
{
if ((g_pad_slots & 0xF) == 0xF)
return;
for (pad_index = 0; pad_index != MAX_PADS; pad_index ++)
if (!HID_ISSET(g_pad_slots, pad_index))
{
HID_SET(g_pad_slots, pad_index);
break;
}
}
IOHIDDeviceOpen(inDevice, kIOHIDOptionsTypeNone);
IOHIDDeviceScheduleWithRunLoop(inDevice, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
IOHIDDeviceRegisterInputValueCallback(inDevice, hid_device_input_callback, (void*)pad_index);
IOHIDDeviceRegisterRemovalCallback(inDevice, hid_device_removed, (void*)pad_index);
osx_pad_set_leds(inDevice, pad_index);
}
static CFMutableDictionaryRef build_matching_dictionary(uint32_t page, uint32_t use)
@ -137,9 +191,8 @@ void osx_pad_init()
IOHIDManagerSetDeviceMatchingMultiple(g_hid_manager, matcher);
CFRelease(matcher);
IOHIDManagerRegisterDeviceMatchingCallback(g_hid_manager, hid_device_attached, 0);
IOHIDManagerRegisterDeviceRemovalCallback(g_hid_manager, hid_device_removed, 0);
IOHIDManagerScheduleWithRunLoop(g_hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerRegisterDeviceMatchingCallback(g_hid_manager, hid_manager_device_attached, 0);
IOHIDManagerScheduleWithRunLoop(g_hid_manager, CFRunLoopGetMain(), kCFRunLoopCommonModes);
IOHIDManagerOpen(g_hid_manager, kIOHIDOptionsTypeNone);
}
@ -150,7 +203,7 @@ void osx_pad_quit()
if (g_hid_manager)
{
IOHIDManagerClose(g_hid_manager, kIOHIDOptionsTypeNone);
IOHIDManagerUnscheduleFromRunLoop(g_hid_manager, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
IOHIDManagerUnscheduleFromRunLoop(g_hid_manager, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
CFRelease(g_hid_manager);
}

View File

@ -37,6 +37,10 @@
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
@property (strong, nonatomic) NSString* configDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (strong, nonatomic) NSString* globalConfigFile; // e.g. /var/mobile/Documents/.RetroArch/retroarch.cfg
@property (strong, nonatomic) NSString* coreDirectory; // e.g. /Applications/RetroArch.app/modules
@end
#endif

View File

@ -18,15 +18,7 @@
#import "RetroArch_Apple.h"
#include "rarch_wrapper.h"
#include "../RetroArch/apple_input.h"
// If USE_XATTR is defined any loaded file will get a com.RetroArch.Core extended attribute
// specifying which core was used to load.
//#define USE_XATTR
#if defined(USE_XATTR)
#include "sys/xattr.h"
#endif
#include "apple/common/apple_input.h"
#include "file.h"
@ -66,6 +58,11 @@
apple_platform = self;
_loaded = true;
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
self.configDirectory = [paths[0] stringByAppendingPathComponent:@"RetroArch"];
self.globalConfigFile = [NSString stringWithFormat:@"%@/retroarch.cfg", self.configDirectory];
self.coreDirectory = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"Contents/Resources/modules"];
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
RAGameView.get.frame = [window.contentView bounds];
@ -76,16 +73,16 @@
// Create core select list
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
for (RAModuleInfo* i in RAModuleInfo.getModules)
for (RAModuleInfo* i in apple_get_modules())
[cb addItemWithObjectValue:i];
if (cb.numberOfItems)
[cb selectItemAtIndex:0];
else
apple_display_alert(@"No libretro cores were found.", @"RetroArch");
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)
if (!_wantReload || apple_argv)
apple_run_core(nil, 0);
else
[self chooseCore];
@ -162,23 +159,6 @@
- (void)chooseCore
{
#ifdef USE_XATTR
char stored_name[PATH_MAX];
if (getxattr(_file.UTF8String, "com.RetroArch.Core", stored_name, PATH_MAX, 0, 0) > 0)
{
for (RAModuleInfo* i in RAModuleInfo.getModules)
{
const char* core_name = i.path.lastPathComponent.UTF8String;
if (strcmp(core_name, stored_name) == 0)
{
_core = i;
[self runCore];
return;
}
}
}
#endif
[NSApplication.sharedApplication beginSheet:_coreSelectSheet modalForWindow:window modalDelegate:nil didEndSelector:nil contextInfo:nil];
[NSApplication.sharedApplication runModalForWindow:_coreSelectSheet];
}
@ -202,14 +182,7 @@
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
{
if (file)
{
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:[NSURL fileURLWithPath:[NSString stringWithUTF8String:file]]];
#ifdef USE_XATTR
const char* core_name = core.path.lastPathComponent.UTF8String;
setxattr(file, "com.RetroArch.Core", core_name, strlen(core_name) + 1, 0, 0);
#endif
}
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:[NSURL fileURLWithPath:@(file)]];
}
- (void)unloadingCore:(RAModuleInfo*)core
@ -227,21 +200,16 @@
_wantReload = false;
}
- (NSString*)retroarchConfigPath
{
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
return [paths[0] stringByAppendingPathComponent:@"RetroArch"];
}
- (NSString*)corePath
{
return [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"Contents/Resources/modules"];
}
#pragma mark Menus
- (IBAction)showCoresDirectory:(id)sender
{
[[NSWorkspace sharedWorkspace] openFile:self.coreDirectory];
}
- (IBAction)showPreferences:(id)sender
{
[[[NSWindowController alloc] initWithWindowNibName:@"Settings"] window];
NSWindowController* wc = [[NSWindowController alloc] initWithWindowNibName:@"Settings"];
[NSApp runModalForWindow:wc.window];
}
- (IBAction)basicEvent:(id)sender
@ -259,6 +227,23 @@
int main(int argc, char *argv[])
{
uint32_t current_argc = 0;
for (int i = 0; i != argc; i ++)
{
if (strcmp(argv[i], "--") == 0)
{
current_argc = 1;
apple_argv = malloc(sizeof(char*) * (argc + 1));
memset(apple_argv, 0, sizeof(char*) * (argc + 1));
apple_argv[0] = argv[0];
}
else if (current_argc)
{
apple_argv[current_argc ++] = argv[i];
}
}
return NSApplicationMain(argc, (const char **) argv);
}

View File

@ -14,16 +14,272 @@
*/
#import <objc/runtime.h>
#import "../RetroArch/RetroArch_Apple.h"
#include "../RetroArch/setting_data.h"
#import "apple/common/RetroArch_Apple.h"
#include "apple/common/setting_data.h"
#include "apple/common/apple_input.h"
#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 = @(min);
self.maximum = @(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
@implementation RAInputBinder
- (IBAction)goAway:(id)sender
{
[NSApp endSheet:self];
[self orderOut:nil];
}
// Stop the annoying sound when pressing a key
- (void)keyDown:(NSEvent*)theEvent
{
}
@end
@interface RASettingCell : NSTableCellView
@property (nonatomic) const rarch_setting_t* setting;
@property (nonatomic) NSString* stringValue;
@property (nonatomic) IBOutlet NSNumber* numericValue;
@property (nonatomic) bool booleanValue;
@property (nonatomic) NSTimer* bindTimer;
@end
@implementation RASettingCell
- (void)setSetting:(const rarch_setting_t *)aSetting
{
_setting = aSetting;
if (!_setting)
return;
if (aSetting->type == ST_INT || aSetting->type == ST_FLOAT)
{
self.textField.formatter = [[RANumberFormatter alloc] initWithFloatSupport:aSetting->type == ST_FLOAT
minimum:aSetting->min
maximum:aSetting->max];
}
else
self.textField.formatter = nil;
// 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_BIND: [self updateInputString]; break;
default: break;
}
}
- (IBAction)doBrowse:(id)sender
{
NSOpenPanel* panel = [NSOpenPanel new];
[panel runModal];
if (panel.URLs.count == 1)
self.stringValue = panel.URL.path;
}
- (void)setNumericValue:(NSNumber *)numericValue
{
_numericValue = numericValue;
if (_setting && _setting->type == ST_INT)
*(int*)_setting->value = _numericValue.intValue;
else if (_setting && _setting->type == ST_FLOAT)
*(float*)_setting->value = _numericValue.floatValue;
}
- (void)setBooleanValue:(bool)booleanValue
{
_booleanValue = booleanValue;
if (_setting && _setting->type == ST_BOOL)
*(bool*)_setting->value = _booleanValue;
}
- (void)setStringValue:(NSString *)stringValue
{
_stringValue = stringValue ? stringValue : @"";
if (_setting && (_setting->type == ST_STRING || _setting->type == ST_PATH))
strlcpy(_setting->value, _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)];
}
- (void)dismissBinder
{
[self.bindTimer invalidate];
self.bindTimer = nil;
[self updateInputString];
[(id)self.window.attachedSheet goAway:nil];
}
- (void)checkBind:(NSTimer*)send
{
int32_t value = 0;
if ((value = apple_input_find_any_key()))
BINDFOR(*_setting).key = input_translate_keysym_to_rk(value);
else if ((value = apple_input_find_any_button(0)) >= 0)
BINDFOR(*_setting).joykey = value;
else if ((value = apple_input_find_any_axis(0)))
BINDFOR(*_setting).joyaxis = (value > 0) ? AXIS_POS(value - 1) : AXIS_NEG(value - 1);
else
return;
[self dismissBinder];
}
- (IBAction)doGetBind:(id)sender
{
static NSWindowController* controller;
if (!controller)
controller = [[NSWindowController alloc] initWithWindowNibName:@"InputBinder"];
self.bindTimer = [NSTimer timerWithTimeInterval:.1f target:self selector:@selector(checkBind:) userInfo:nil repeats:YES];
[[NSRunLoop currentRunLoop] addTimer:self.bindTimer forMode:NSModalPanelRunLoopMode];
[NSApp beginSheet:controller.window modalForWindow:self.window modalDelegate:nil didEndSelector:nil contextInfo:nil];
}
@end
@protocol RASettingView
@property const rarch_setting_t* setting;
@end
@interface RASettingsDelegate : NSObject<NSTableViewDataSource, NSTableViewDelegate,
NSOutlineViewDataSource, NSOutlineViewDelegate>
NSOutlineViewDataSource, NSOutlineViewDelegate,
NSWindowDelegate>
@end
@implementation RASettingsDelegate
{
NSWindow IBOutlet* _window;
NSWindow IBOutlet* _inputWindow;
NSTableView IBOutlet* _table;
NSOutlineView IBOutlet* _outline;
@ -33,10 +289,15 @@
- (void)awakeFromNib
{
apple_enter_stasis();
NSMutableArray* thisGroup = nil;
NSMutableArray* thisSubGroup = nil;
_settings = [NSMutableArray array];
memcpy(&fake_settings, &g_settings, sizeof(struct settings));
memcpy(&fake_extern, &g_extern, sizeof(struct global));
for (int i = 0; setting_data[i].type; i ++)
{
switch (setting_data[i].type)
@ -44,7 +305,7 @@
case ST_GROUP:
{
thisGroup = [NSMutableArray array];
objc_setAssociatedObject(thisGroup, "NAME", [NSString stringWithFormat:@"%s", setting_data[i].name], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(thisGroup, associated_name_tag, [NSString stringWithFormat:@"%s", setting_data[i].name], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
break;
}
@ -58,7 +319,7 @@
case ST_SUB_GROUP:
{
thisSubGroup = [NSMutableArray array];
objc_setAssociatedObject(thisSubGroup, "NAME", [NSString stringWithFormat:@"%s", setting_data[i].name], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
objc_setAssociatedObject(thisSubGroup, associated_name_tag, [NSString stringWithFormat:@"%s", setting_data[i].name], OBJC_ASSOCIATION_RETAIN_NONATOMIC);
break;
}
@ -77,49 +338,81 @@
}
}
[NSApplication.sharedApplication beginSheet:_window modalForWindow:RetroArch_OSX.get->window modalDelegate:nil didEndSelector:nil contextInfo:nil];
[NSApplication.sharedApplication runModalForWindow:_window];
[self load];
}
- (IBAction)close:(id)sender
- (void)load
{
[NSApplication.sharedApplication stopModal];
[NSApplication.sharedApplication endSheet:_window returnCode:0];
[_window orderOut:nil];
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);
}
- (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);
apple_exit_stasis(true);
[NSApp stopModal];
}
#pragma mark View Builders
- (NSView*)labelAccessoryFor:(NSString*)text onTable:(NSTableView*)table
{
NSTextField* result = [table makeViewWithIdentifier:@"label" owner:self];
if (result == nil)
{
result = [NSTextField new];
result.bordered = NO;
result.drawsBackground = NO;
result.identifier = @"label";
}
RASettingCell* result = [table makeViewWithIdentifier:@"RALabelSetting" owner:nil];
result.stringValue = text;
return result;
}
- (NSView*)booleanAccessoryFor:(const rarch_setting_t*)setting onTable:(NSTableView*)table
{
NSButton* result = [table makeViewWithIdentifier:@"boolean" owner:self];
if (!result)
{
result = [NSButton new];
result.buttonType = NSSwitchButton;
result.title = @"";
}
result.state = *(bool*)setting->value;
return result;
}
#pragma mark Section Table
- (NSInteger)numberOfRowsInTableView:(NSTableView*)view
{
@ -128,7 +421,7 @@
- (NSView *)tableView:(NSTableView *)tableView viewForTableColumn:(NSTableColumn *)tableColumn row:(NSInteger)row
{
return [self labelAccessoryFor:objc_getAssociatedObject(_settings[row], "NAME") onTable:tableView];
return [self labelAccessoryFor:objc_getAssociatedObject(_settings[row], associated_name_tag) onTable:tableView];
}
- (void)tableViewSelectionDidChange:(NSNotification *)aNotification
@ -153,12 +446,16 @@
return [item isKindOfClass:[NSArray class]];
}
- (BOOL)validateProposedFirstResponder:(NSResponder *)responder forEvent:(NSEvent *)event {
return YES;
}
- (NSView *)outlineView:(NSOutlineView *)outlineView viewForTableColumn:(NSTableColumn *)tableColumn item:(id)item
{
if ([item isKindOfClass:[NSArray class]])
{
if ([tableColumn.identifier isEqualToString:@"title"])
return [self labelAccessoryFor:objc_getAssociatedObject(item, "NAME") onTable:outlineView];
return [self labelAccessoryFor:objc_getAssociatedObject(item, associated_name_tag) onTable:outlineView];
else
return [self labelAccessoryFor:[NSString stringWithFormat:@"%d items", (int)[item count]] onTable:outlineView];
}
@ -167,25 +464,22 @@
const rarch_setting_t* setting = &setting_data[[item intValue]];
if ([tableColumn.identifier isEqualToString:@"title"])
return [self labelAccessoryFor:[NSString stringWithFormat:@"%s", setting->short_description] onTable:outlineView]; // < The outlineView will fill the value
return [self labelAccessoryFor:@(setting->short_description) onTable:outlineView];
else if([tableColumn.identifier isEqualToString:@"accessory"])
{
RASettingCell* s = nil;
switch (setting->type)
{
case ST_BOOL: return [self booleanAccessoryFor:setting onTable:outlineView];
case ST_PATH:
case ST_STRING:
return [self labelAccessoryFor:[NSString stringWithFormat:@"%s", (const char*)setting->value] onTable:outlineView];
case ST_INT:
return [self labelAccessoryFor:[NSString stringWithFormat:@"%d", *(int*)setting->value] onTable:outlineView];
case ST_FLOAT:
return [self labelAccessoryFor:[NSString stringWithFormat:@"%f", *(float*)setting->value] onTable:outlineView];
default: abort();
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;
}
s.setting = setting;
return s;
}
}

View File

@ -8,10 +8,11 @@
/* Begin PBXBuildFile section */
9620F663178FD4D3001B3B81 /* settings.m in Sources */ = {isa = PBXBuildFile; fileRef = 9620F662178FD4D3001B3B81 /* settings.m */; };
9620F6651790004F001B3B81 /* Settings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 9620F6641790004F001B3B81 /* Settings.xib */; };
962EE0E2178B3DF6004224FF /* IOKit.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 962EE0E1178B3DF6004224FF /* IOKit.framework */; };
96355CE31788E72A0010DBFA /* Cocoa.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96355CE21788E72A0010DBFA /* Cocoa.framework */; };
9646869817BBC14E00C5EA69 /* platform.m in Sources */ = {isa = PBXBuildFile; fileRef = 9646869617BBC14E00C5EA69 /* platform.m */; };
964DE7C117D84B34001CBB6C /* InputBinder.xib in Resources */ = {isa = PBXBuildFile; fileRef = 964DE7C317D84B34001CBB6C /* InputBinder.xib */; };
964DE7C417D84B57001CBB6C /* Settings.xib in Resources */ = {isa = PBXBuildFile; fileRef = 964DE7C617D84B57001CBB6C /* Settings.xib */; };
967894931788ECDB00D6CA69 /* InfoPlist.strings in Resources */ = {isa = PBXBuildFile; fileRef = 9678948F1788ECDB00D6CA69 /* InfoPlist.strings */; };
967894941788ECDB00D6CA69 /* MainMenu.xib in Resources */ = {isa = PBXBuildFile; fileRef = 967894911788ECDB00D6CA69 /* MainMenu.xib */; };
967894961788ED1100D6CA69 /* main.m in Sources */ = {isa = PBXBuildFile; fileRef = 967894951788ED1100D6CA69 /* main.m */; };
@ -29,7 +30,6 @@
/* Begin PBXFileReference section */
9620F662178FD4D3001B3B81 /* settings.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = settings.m; path = OSX/settings.m; sourceTree = SOURCE_ROOT; };
9620F6641790004F001B3B81 /* Settings.xib */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = file.xib; name = Settings.xib; path = OSX/Settings.xib; sourceTree = "<group>"; };
962EE0E1178B3DF6004224FF /* IOKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = IOKit.framework; path = ../../../../../../../System/Library/Frameworks/IOKit.framework; sourceTree = "<group>"; };
96355CDF1788E72A0010DBFA /* RetroArch.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RetroArch.app; sourceTree = BUILT_PRODUCTS_DIR; };
96355CE21788E72A0010DBFA /* Cocoa.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Cocoa.framework; path = System/Library/Frameworks/Cocoa.framework; sourceTree = SDKROOT; };
@ -38,6 +38,8 @@
96355CE71788E72A0010DBFA /* Foundation.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = Foundation.framework; path = System/Library/Frameworks/Foundation.framework; sourceTree = SDKROOT; };
9646869617BBC14E00C5EA69 /* platform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = platform.m; path = OSX/platform.m; sourceTree = SOURCE_ROOT; };
9646869717BBC14E00C5EA69 /* platform.h */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.h; name = platform.h; path = OSX/platform.h; sourceTree = SOURCE_ROOT; };
964DE7C217D84B34001CBB6C /* en */ = {isa = PBXFileReference; lastKnownFileType = file; name = en; path = en.lproj/InputBinder.xib; sourceTree = "<group>"; };
964DE7C517D84B57001CBB6C /* en */ = {isa = PBXFileReference; lastKnownFileType = file; name = en; path = en.lproj/Settings.xib; sourceTree = "<group>"; };
9678948D1788ECCA00D6CA69 /* RetroArch-Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; name = "RetroArch-Info.plist"; path = "OSX/RetroArch-Info.plist"; sourceTree = SOURCE_ROOT; };
967894901788ECDB00D6CA69 /* en */ = {isa = PBXFileReference; lastKnownFileType = text.plist.strings; name = en; path = OSX/en.lproj/InfoPlist.strings; sourceTree = SOURCE_ROOT; };
967894921788ECDB00D6CA69 /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = en; path = OSX/en.lproj/MainMenu.xib; sourceTree = SOURCE_ROOT; };
@ -78,7 +80,7 @@
isa = PBXGroup;
children = (
962EE0E1178B3DF6004224FF /* IOKit.framework */,
96355CE81788E72A0010DBFA /* RetroArch */,
96355CE81788E72A0010DBFA /* common */,
967894E7178A2E9B00D6CA69 /* Assets */,
96355CE11788E72A0010DBFA /* Frameworks */,
96355CE01788E72A0010DBFA /* Products */,
@ -109,7 +111,7 @@
name = Frameworks;
sourceTree = "<group>";
};
96355CE81788E72A0010DBFA /* RetroArch */ = {
96355CE81788E72A0010DBFA /* common */ = {
isa = PBXGroup;
children = (
9646869617BBC14E00C5EA69 /* platform.m */,
@ -124,7 +126,7 @@
9678949C1788F02600D6CA69 /* utility.m */,
967894951788ED1100D6CA69 /* main.m */,
);
path = RetroArch;
path = common;
sourceTree = "<group>";
};
96355CE91788E72A0010DBFA /* Supporting Files */ = {
@ -143,7 +145,8 @@
967894E8178A2EB400D6CA69 /* modules */,
967894911788ECDB00D6CA69 /* MainMenu.xib */,
C15874EE178F2094001171D4 /* RetroArch.icns */,
9620F6641790004F001B3B81 /* Settings.xib */,
964DE7C617D84B57001CBB6C /* Settings.xib */,
964DE7C317D84B34001CBB6C /* InputBinder.xib */,
);
name = Assets;
sourceTree = "<group>";
@ -202,7 +205,8 @@
967894941788ECDB00D6CA69 /* MainMenu.xib in Resources */,
967894E9178A2EB400D6CA69 /* modules in Resources */,
C15874EF178F2094001171D4 /* RetroArch.icns in Resources */,
9620F6651790004F001B3B81 /* Settings.xib in Resources */,
964DE7C417D84B57001CBB6C /* Settings.xib in Resources */,
964DE7C117D84B34001CBB6C /* InputBinder.xib in Resources */,
);
runOnlyForDeploymentPostprocessing = 0;
};
@ -226,6 +230,24 @@
/* End PBXSourcesBuildPhase section */
/* Begin PBXVariantGroup section */
964DE7C317D84B34001CBB6C /* InputBinder.xib */ = {
isa = PBXVariantGroup;
children = (
964DE7C217D84B34001CBB6C /* en */,
);
name = InputBinder.xib;
path = OSX;
sourceTree = "<group>";
};
964DE7C617D84B57001CBB6C /* Settings.xib */ = {
isa = PBXVariantGroup;
children = (
964DE7C517D84B57001CBB6C /* en */,
);
name = Settings.xib;
path = OSX;
sourceTree = "<group>";
};
9678948F1788ECDB00D6CA69 /* InfoPlist.strings */ = {
isa = PBXVariantGroup;
children = (
@ -303,7 +325,6 @@
"-DINLINE=inline",
"-DLSB_FIRST",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DWANT_RPNG",
"-DHAVE_COREAUDIO",
"-DHAVE_DYNAMIC",
@ -349,23 +370,22 @@
"-DHAVE_RARCH_MAIN_WRAP",
"-DHAVE_GRIFFIN",
"-DHAVE_RGUI",
"-DIOS",
"-DOSX",
"-DHAVE_OPENGL",
"-DHAVE_FBO",
"-DHAVE_VID_CONTEXT",
"-DHAVE_OPENGLES2",
"-DHAVE_GLSL",
"-DINLINE=inline",
"-DLSB_FIRST",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DRARCH_MOBILE",
"-DWANT_RPNG",
"-DHAVE_COREAUDIO",
"-DHAVE_DYNAMIC",
"-DHAVE_OVERLAY",
"-DHAVE_ZLIB",
"-DWANT_MINIZ",
"-DSINC_LOWER_QUALITY",
"-DHAVE_NETPLAY",
);
PRODUCT_NAME = "$(TARGET_NAME)";
SDKROOT = "";

View File

@ -120,7 +120,7 @@
96AFAE1A16C1D4EA009DE44C = {
isa = PBXGroup;
children = (
96AFAE3316C1D4EA009DE44C /* RetroArch */,
96AFAE3316C1D4EA009DE44C /* common */,
96AFAE9C16C1D976009DE44C /* core */,
966B9CB716E41E7A005B61E1 /* Assets */,
96AFAE2816C1D4EA009DE44C /* Frameworks */,
@ -151,7 +151,7 @@
name = Frameworks;
sourceTree = "<group>";
};
96AFAE3316C1D4EA009DE44C /* RetroArch */ = {
96AFAE3316C1D4EA009DE44C /* common */ = {
isa = PBXGroup;
children = (
9646869417BBBEAE00C5EA69 /* platform.m */,
@ -167,7 +167,7 @@
96355CD11788CF190010DBFA /* RetroArch_Apple.h */,
96337E81176AC6E5004685F3 /* utility.m */,
);
path = RetroArch;
path = common;
sourceTree = "<group>";
};
96AFAE3416C1D4EA009DE44C /* Supporting Files */ = {
@ -367,7 +367,6 @@
"-DLSB_FIRST",
"-DHAVE_THREAD",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DRARCH_MOBILE",
"-std=gnu99",
"-DHAVE_COREAUDIO",
@ -417,7 +416,6 @@
"-DLSB_FIRST",
"-DHAVE_THREAD",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DRARCH_MOBILE",
"-std=gnu99",
"-DHAVE_COREAUDIO",
@ -458,7 +456,6 @@
"-DINLINE=inline",
"-DLSB_FIRST",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DRARCH_MOBILE",
"-DHAVE_COREAUDIO",
"-DHAVE_DYNAMIC",
@ -501,7 +498,6 @@
"-DINLINE=inline",
"-DLSB_FIRST",
"-D__LIBRETRO__",
"-DRARCH_PERFORMANCE_MODE",
"-DRARCH_MOBILE",
"-DHAVE_COREAUDIO",
"-DHAVE_DYNAMIC",

View File

@ -17,6 +17,7 @@
#include "rarch_wrapper.h"
#include "general.h"
#include "gfx/gfx_common.h"
#ifdef IOS
@ -33,6 +34,7 @@ static UIView* g_pause_indicator_view;
#include "apple_input.h"
static bool g_has_went_fullscreen;
static RAGameView* g_instance;
static NSOpenGLContext* g_context;
static NSOpenGLPixelFormat* g_format;
@ -312,6 +314,73 @@ void *apple_get_proc_address(const char *symbol_name)
#endif
}
void apple_update_window_title(void)
{
static char buf[128];
bool got_text = gfx_get_fps(buf, sizeof(buf), false);
#ifdef OSX
static const char* const text = buf; // < Can't access buf directly in the block
if (got_text)
{
// NOTE: This could go bad if buf is updated again before this completes.
// If it poses a problem it should be changed to dispatch_sync.
dispatch_async(dispatch_get_main_queue(), ^
{
g_view.window.title = @(text);
});
}
#endif
}
bool apple_game_view_has_focus(void)
{
#ifdef OSX
return [NSApp isActive];
#else
return true;
#endif
}
bool apple_set_video_mode(unsigned width, unsigned height, bool fullscreen)
{
__block bool result = true;
#ifdef OSX
dispatch_sync(dispatch_get_main_queue(),
^{
// TODO: Sceen mode support
if (fullscreen && !g_has_went_fullscreen)
{
if (g_settings.video.monitor_index >= [NSScreen screens].count)
{
apple_display_alert(@"Could not go fullscreen: Monitor index out of range.", nil);
result = false;
return;
}
[g_view enterFullScreenMode:[NSScreen screens][g_settings.video.monitor_index] withOptions:nil];
[NSCursor hide];
}
else if (!fullscreen && g_has_went_fullscreen)
{
[g_view exitFullScreenModeWithOptions:nil];
[g_view.window makeFirstResponder:g_view];
[NSCursor unhide];
}
g_has_went_fullscreen = fullscreen;
if (!g_has_went_fullscreen)
[g_view.window setContentSize:NSMakeSize(width, height)];
});
#endif
// TODO: Maybe iOS users should be apple to show/hide the status bar here?
return result;
}
#ifdef IOS
void apple_bind_game_view_fbo(void)
{

View File

@ -22,22 +22,22 @@
#include "conf/config_file.h"
#include "core_info.h"
extern NSArray* apple_get_modules();
@interface RAModuleInfo : NSObject
@property (strong) NSString* path;
@property NSString* path; // e.g. /path/to/corename_libretro.dylib
@property NSString* baseName; // e.g. corename_libretro
@property core_info_t* info;
@property config_file_t* data;
@property (strong) NSString* description;
@property (strong) NSString* customConfigPath;
@property NSString* description; // Friendly name from config file, else just the filename
@property NSString* customConfigFile; // Path where custom config file would reside
@property NSString* configFile; // Path to effective config file
+ (NSArray*)getModules;
- (bool)supportsFileAtPath:(NSString*)path;
+ (NSString*)globalConfigPath;
- (void)createCustomConfig;
- (void)deleteCustomConfig;
- (bool)hasCustomConfig;
- (NSString*)configPath;
@end

View File

@ -22,30 +22,29 @@
static NSMutableArray* moduleList;
static core_info_list_t* coreList;
@implementation RAModuleInfo
+ (NSArray*)getModules
NSArray* apple_get_modules()
{
if (!moduleList)
{
coreList = get_core_info_list(apple_platform.corePath.UTF8String);
coreList = get_core_info_list(apple_platform.coreDirectory.UTF8String);
if (!coreList)
return nil;
moduleList = [NSMutableArray arrayWithCapacity:coreList->count];
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 stringWithUTF8String:core->path];
newInfo.path = @(core->path);
newInfo.baseName = newInfo.path.lastPathComponent.stringByDeletingPathExtension;
newInfo.info = core;
newInfo.data = core->data;
newInfo.description = [NSString stringWithUTF8String:core->display_name];
NSString* baseName = newInfo.path.lastPathComponent.stringByDeletingPathExtension;
newInfo.customConfigPath = [NSString stringWithFormat:@"%@/%@.cfg", apple_platform.retroarchConfigPath, baseName];
newInfo.description = @(core->display_name);
newInfo.customConfigFile = [NSString stringWithFormat:@"%@/%@.cfg", apple_platform.configDirectory, newInfo.baseName];
newInfo.configFile = newInfo.hasCustomConfig ? newInfo.customConfigFile : apple_platform.globalConfigFile;
[moduleList addObject:newInfo];
}
@ -59,9 +58,7 @@ static core_info_list_t* coreList;
return moduleList;
}
- (void)dealloc
{
}
@implementation RAModuleInfo
- (id)copyWithZone:(NSZone *)zone
{
@ -73,35 +70,21 @@ static core_info_list_t* coreList;
return does_core_support_file(self.info, path.UTF8String);
}
+ (NSString*)globalConfigPath
{
static NSString* path;
if (!path)
path = [NSString stringWithFormat:@"%@/retroarch.cfg", apple_platform.retroarchConfigPath];
return path;
}
- (void)createCustomConfig
{
if (!self.hasCustomConfig)
[NSFileManager.defaultManager copyItemAtPath:RAModuleInfo.globalConfigPath toPath:self.customConfigPath error:nil];
[NSFileManager.defaultManager copyItemAtPath:apple_platform.globalConfigFile toPath:self.customConfigFile error:nil];
}
- (void)deleteCustomConfig
{
if (self.hasCustomConfig)
[NSFileManager.defaultManager removeItemAtPath:self.customConfigPath error:nil];
[NSFileManager.defaultManager removeItemAtPath:self.customConfigFile error:nil];
}
- (bool)hasCustomConfig
{
return path_file_exists(self.customConfigPath.UTF8String);
}
- (NSString*)configPath
{
return self.hasCustomConfig ? self.customConfigPath : RAModuleInfo.globalConfigPath;
return path_file_exists(self.customConfigFile.UTF8String);
}
@end
@ -148,7 +131,7 @@ static NSString* build_string_pair(NSString* stringA, NSString* stringB)
for (int i = 0; i < firmwareCount; i ++)
{
NSString* path = objc_get_value_from_config(_data.data, [NSString stringWithFormat:@"firmware%d_path", i + 1], @"Unspecified");
path = [path stringByReplacingOccurrencesOfString:@"%sysdir%" withString:RetroArch_iOS.get.systemDirectory];
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 + 1], @"Unspecified"), path)];
}

View File

@ -28,8 +28,9 @@
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
- (NSString*)retroarchConfigPath; // < This returns the directory that contains retroarch.cfg and other custom configs
- (NSString*)corePath;
- (NSString*)configDirectory; // < This returns the directory that contains retroarch.cfg and other custom configs
- (NSString*)globalConfigFile; // < This is the full path to retroarch.cfg
- (NSString*)coreDirectory; // < This is the default path to where libretro cores are installed
@end
#ifdef IOS
@ -38,6 +39,7 @@
#import "../OSX/platform.h"
#endif
extern char** apple_argv;
extern bool apple_is_paused;
extern bool apple_is_running;
extern bool apple_use_tv_mode;
@ -53,7 +55,7 @@ extern void apple_event_show_rgui(void* userdata);
extern void apple_refresh_config();
extern void apple_enter_stasis();
extern void apple_exit_stasis();
extern void apple_exit_stasis(bool reload_config);
extern void apple_run_core(RAModuleInfo* core, const char* file);
// utility.m

View File

@ -22,14 +22,14 @@
#include "general.h"
#include "driver.h"
#include "keycode.inc"
extern const rarch_joypad_driver_t apple_joypad;
static const rarch_joypad_driver_t* const g_joydriver = &apple_joypad;
apple_input_data_t g_current_input_data;
apple_input_data_t g_polled_input_data;
static const struct rarch_key_map rarch_key_map_hidusage[];
#ifdef OSX // Taken from https://github.com/depp/keycode, check keycode.h for license
const unsigned char MAC_NATIVE_TO_HID[128] = {
4, 22, 7, 9, 11, 10, 29, 27, 6, 25,255, 5, 20, 26, 8, 21,
@ -101,6 +101,42 @@ void apple_input_handle_key_event(unsigned keycode, bool down)
g_current_input_data.keys[keycode] = down;
}
int32_t apple_input_find_any_key()
{
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;
return 0;
}
int32_t apple_input_find_any_button(uint32_t port)
{
uint32_t buttons = g_current_input_data.pad_buttons[port] |
((port == 0) ? apple_input_get_icade_buttons() : 0);
if (g_current_input_data.pad_buttons[port])
for (int i = 0; i != 32; i ++)
if (buttons & (1 << i))
return i;
return -1;
}
int32_t apple_input_find_any_axis(uint32_t port)
{
for (int i = 0; i < 4; i++)
{
int16_t value = g_current_input_data.pad_axis[port][i];
if (abs(value) > 0x4000)
return (value < 0) ? -(i + 1) : i + 1;
}
return 0;
}
// Game thread interface
static bool apple_key_pressed(enum retro_key key)
{
@ -118,7 +154,7 @@ static bool apple_is_pressed(unsigned port_num, const struct retro_keybind *bind
// Exported input driver
static void *apple_input_init(void)
{
input_init_keyboard_lut(rarch_key_map_hidusage);
input_init_keyboard_lut(apple_key_map_hidusage);
memset(&g_polled_input_data, 0, sizeof(g_polled_input_data));
return (void*)-1;
}
@ -273,150 +309,3 @@ const input_driver_t input_apple = {
apple_input_set_keybinds,
"apple_input",
};
// Key table
#include "keycode.h"
static const struct rarch_key_map rarch_key_map_hidusage[] = {
{ KEY_Delete, RETROK_BACKSPACE },
{ KEY_Tab, RETROK_TAB },
// RETROK_CLEAR },
{ KEY_Enter, RETROK_RETURN },
{ KEY_Pause, RETROK_PAUSE },
{ KEY_Escape, RETROK_ESCAPE },
{ KEY_Space, RETROK_SPACE },
// RETROK_EXCLAIM },
// RETROK_QUOTEDBL },
// RETROK_HASH },
// RETROK_DOLLAR },
// RETROK_AMPERSAND },
{ KEY_Quote, RETROK_QUOTE },
// RETROK_LEFTPAREN },
// RETROK_RIGHTPAREN },
// RETROK_ASTERISK },
// RETROK_PLUS },
{ KEY_Comma, RETROK_COMMA },
{ KEY_Minus, RETROK_MINUS },
{ KEY_Period, RETROK_PERIOD },
{ KEY_Slash, RETROK_SLASH },
{ KEY_0, RETROK_0 },
{ KEY_1, RETROK_1 },
{ KEY_2, RETROK_2 },
{ KEY_3, RETROK_3 },
{ KEY_4, RETROK_4 },
{ KEY_5, RETROK_5 },
{ KEY_6, RETROK_6 },
{ KEY_7, RETROK_7 },
{ KEY_8, RETROK_8 },
{ KEY_9, RETROK_9 },
// RETROK_COLON },
{ KEY_Semicolon, RETROK_SEMICOLON },
// RETROK_LESS },
{ KEY_Equals, RETROK_EQUALS },
// RETROK_GREATER },
// RETROK_QUESTION },
// RETROK_AT },
{ KEY_LeftBracket, RETROK_LEFTBRACKET },
{ KEY_Backslash, RETROK_BACKSLASH },
{ KEY_RightBracket, RETROK_RIGHTBRACKET },
// RETROK_CARET },
// RETROK_UNDERSCORE },
{ KEY_Grave, RETROK_BACKQUOTE },
{ KEY_A, RETROK_a },
{ KEY_B, RETROK_b },
{ KEY_C, RETROK_c },
{ KEY_D, RETROK_d },
{ KEY_E, RETROK_e },
{ KEY_F, RETROK_f },
{ KEY_G, RETROK_g },
{ KEY_H, RETROK_h },
{ KEY_I, RETROK_i },
{ KEY_J, RETROK_j },
{ KEY_K, RETROK_k },
{ KEY_L, RETROK_l },
{ KEY_M, RETROK_m },
{ KEY_N, RETROK_n },
{ KEY_O, RETROK_o },
{ KEY_P, RETROK_p },
{ KEY_Q, RETROK_q },
{ KEY_R, RETROK_r },
{ KEY_S, RETROK_s },
{ KEY_T, RETROK_t },
{ KEY_U, RETROK_u },
{ KEY_V, RETROK_v },
{ KEY_W, RETROK_w },
{ KEY_X, RETROK_x },
{ KEY_Y, RETROK_y },
{ KEY_Z, RETROK_z },
{ KEY_DeleteForward, RETROK_DELETE },
{ KP_0, RETROK_KP0 },
{ KP_1, RETROK_KP1 },
{ KP_2, RETROK_KP2 },
{ KP_3, RETROK_KP3 },
{ KP_4, RETROK_KP4 },
{ KP_5, RETROK_KP5 },
{ KP_6, RETROK_KP6 },
{ KP_7, RETROK_KP7 },
{ KP_8, RETROK_KP8 },
{ KP_9, RETROK_KP9 },
{ KP_Point, RETROK_KP_PERIOD },
{ KP_Divide, RETROK_KP_DIVIDE },
{ KP_Multiply, RETROK_KP_MULTIPLY },
{ KP_Subtract, RETROK_KP_MINUS },
{ KP_Add, RETROK_KP_PLUS },
{ KP_Enter, RETROK_KP_ENTER },
{ KP_Equals, RETROK_KP_EQUALS },
{ KEY_Up, RETROK_UP },
{ KEY_Down, RETROK_DOWN },
{ KEY_Right, RETROK_RIGHT },
{ KEY_Left, RETROK_LEFT },
{ KEY_Insert, RETROK_INSERT },
{ KEY_Home, RETROK_HOME },
{ KEY_End, RETROK_END },
{ KEY_PageUp, RETROK_PAGEUP },
{ KEY_PageDown, RETROK_PAGEDOWN },
{ KEY_F1, RETROK_F1 },
{ KEY_F2, RETROK_F2 },
{ KEY_F3, RETROK_F3 },
{ KEY_F4, RETROK_F4 },
{ KEY_F5, RETROK_F5 },
{ KEY_F6, RETROK_F6 },
{ KEY_F7, RETROK_F7 },
{ KEY_F8, RETROK_F8 },
{ KEY_F9, RETROK_F9 },
{ KEY_F10, RETROK_F10 },
{ KEY_F11, RETROK_F11 },
{ KEY_F12, RETROK_F12 },
{ KEY_F13, RETROK_F13 },
{ KEY_F14, RETROK_F14 },
{ KEY_F15, RETROK_F15 },
// RETROK_NUMLOCK },
{ KEY_CapsLock, RETROK_CAPSLOCK },
// RETROK_SCROLLOCK },
{ KEY_RightShift, RETROK_RSHIFT },
{ KEY_LeftShift, RETROK_LSHIFT },
{ KEY_RightControl, RETROK_RCTRL },
{ KEY_LeftControl, RETROK_LCTRL },
{ KEY_RightAlt, RETROK_RALT },
{ KEY_LeftAlt, RETROK_LALT },
{ KEY_RightGUI, RETROK_RMETA },
{ KEY_LeftGUI, RETROK_RMETA },
// RETROK_LSUPER },
// RETROK_RSUPER },
// RETROK_MODE },
// RETROK_COMPOSE },
// RETROK_HELP },
{ KEY_PrintScreen, RETROK_PRINT },
// RETROK_SYSREQ },
// RETROK_BREAK },
{ KEY_Menu, RETROK_MENU },
// RETROK_POWER },
// RETROK_EURO },
// RETROK_UNDO },
{ 0, RETROK_UNKNOWN }
};

View File

@ -50,4 +50,8 @@ void apple_input_enable_icade(bool on);
uint32_t apple_input_get_icade_buttons();
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_button(uint32_t port);
extern int32_t apple_input_find_any_axis(uint32_t port);
#endif

View File

@ -17,12 +17,12 @@
#include "general.h"
#ifdef IOS
#include "../iOS/input/BTStack/btdynamic.c"
#include "../iOS/input/BTStack/wiimote.c"
#include "../iOS/input/BTStack/btpad.c"
#include "../iOS/input/BTStack/btpad_ps3.c"
#include "../iOS/input/BTStack/btpad_wii.c"
#include "../iOS/input/BTStack/btpad_queue.c"
#include "apple/iOS/bluetooth/btdynamic.c"
#include "apple/iOS/bluetooth/wiimote.c"
#include "apple/iOS/bluetooth/btpad.c"
#include "apple/iOS/bluetooth/btpad_ps3.c"
#include "apple/iOS/bluetooth/btpad_wii.c"
#include "apple/iOS/bluetooth/btpad_queue.c"
#elif defined(OSX)
#include "../OSX/hid_pad.c"
#endif

View File

@ -153,4 +153,21 @@ enum {
KEY_RightAlt = 230,
KEY_RightGUI = 231
};
//
#include "input/input_common.h" // < For rarch_key_map
struct apple_key_name_map_entry
{
const char* const keyname;
const uint32_t hid_id;
};
extern const struct apple_key_name_map_entry apple_key_name_map[];
extern const struct rarch_key_map apple_key_map_hidusage[];
const char* apple_keycode_hidusage_to_name(uint32_t hid_usage);
#endif

222
apple/common/keycode.inc Normal file
View File

@ -0,0 +1,222 @@
/* 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 "keycode.h"
const struct apple_key_name_map_entry apple_key_name_map[] =
{
{ "left", KEY_Left }, { "right", KEY_Right },
{ "up", KEY_Up }, { "down", KEY_Down },
{ "enter", KEY_Enter }, { "kp_enter", KP_Enter },
{ "space", KEY_Space }, { "tab", KEY_Tab },
{ "shift", KEY_LeftShift }, { "rshift", KEY_RightShift },
{ "ctrl", KEY_LeftControl }, { "alt", KEY_LeftAlt },
{ "escape", KEY_Escape }, { "backspace", KEY_DeleteForward },
{ "backquote", KEY_Grave }, { "pause", KEY_Pause },
{ "f1", KEY_F1 }, { "f2", KEY_F2 },
{ "f3", KEY_F3 }, { "f4", KEY_F4 },
{ "f5", KEY_F5 }, { "f6", KEY_F6 },
{ "f7", KEY_F7 }, { "f8", KEY_F8 },
{ "f9", KEY_F9 }, { "f10", KEY_F10 },
{ "f11", KEY_F11 }, { "f12", KEY_F12 },
{ "num0", KEY_0 }, { "num1", KEY_1 },
{ "num2", KEY_2 }, { "num3", KEY_3 },
{ "num4", KEY_4 }, { "num5", KEY_5 },
{ "num6", KEY_6 }, { "num7", KEY_7 },
{ "num8", KEY_8 }, { "num9", KEY_9 },
{ "insert", KEY_Insert }, { "del", KEY_DeleteForward },
{ "home", KEY_Home }, { "end", KEY_End },
{ "pageup", KEY_PageUp }, { "pagedown", KEY_PageDown },
{ "add", KP_Add }, { "subtract", KP_Subtract },
{ "multiply", KP_Multiply }, { "divide", KP_Divide },
{ "keypad0", KP_0 }, { "keypad1", KP_1 },
{ "keypad2", KP_2 }, { "keypad3", KP_3 },
{ "keypad4", KP_4 }, { "keypad5", KP_5 },
{ "keypad6", KP_6 }, { "keypad7", KP_7 },
{ "keypad8", KP_8 }, { "keypad9", KP_9 },
{ "period", KEY_Period }, { "capslock", KEY_CapsLock },
{ "numlock", KP_NumLock }, { "print_screen", KEY_PrintScreen },
{ "scroll_lock", KEY_ScrollLock },
{ "a", KEY_A }, { "b", KEY_B }, { "c", KEY_C }, { "d", KEY_D },
{ "e", KEY_E }, { "f", KEY_F }, { "g", KEY_G }, { "h", KEY_H },
{ "i", KEY_I }, { "j", KEY_J }, { "k", KEY_K }, { "l", KEY_L },
{ "m", KEY_M }, { "n", KEY_N }, { "o", KEY_O }, { "p", KEY_P },
{ "q", KEY_Q }, { "r", KEY_R }, { "s", KEY_S }, { "t", KEY_T },
{ "u", KEY_U }, { "v", KEY_V }, { "w", KEY_W }, { "x", KEY_X },
{ "y", KEY_Y }, { "z", KEY_Z },
{ "nul", 0x00},
};
const struct rarch_key_map apple_key_map_hidusage[] =
{
{ KEY_Delete, RETROK_BACKSPACE },
{ KEY_Tab, RETROK_TAB },
// RETROK_CLEAR },
{ KEY_Enter, RETROK_RETURN },
{ KEY_Pause, RETROK_PAUSE },
{ KEY_Escape, RETROK_ESCAPE },
{ KEY_Space, RETROK_SPACE },
// RETROK_EXCLAIM },
// RETROK_QUOTEDBL },
// RETROK_HASH },
// RETROK_DOLLAR },
// RETROK_AMPERSAND },
{ KEY_Quote, RETROK_QUOTE },
// RETROK_LEFTPAREN },
// RETROK_RIGHTPAREN },
// RETROK_ASTERISK },
// RETROK_PLUS },
{ KEY_Comma, RETROK_COMMA },
{ KEY_Minus, RETROK_MINUS },
{ KEY_Period, RETROK_PERIOD },
{ KEY_Slash, RETROK_SLASH },
{ KEY_0, RETROK_0 },
{ KEY_1, RETROK_1 },
{ KEY_2, RETROK_2 },
{ KEY_3, RETROK_3 },
{ KEY_4, RETROK_4 },
{ KEY_5, RETROK_5 },
{ KEY_6, RETROK_6 },
{ KEY_7, RETROK_7 },
{ KEY_8, RETROK_8 },
{ KEY_9, RETROK_9 },
// RETROK_COLON },
{ KEY_Semicolon, RETROK_SEMICOLON },
// RETROK_LESS },
{ KEY_Equals, RETROK_EQUALS },
// RETROK_GREATER },
// RETROK_QUESTION },
// RETROK_AT },
{ KEY_LeftBracket, RETROK_LEFTBRACKET },
{ KEY_Backslash, RETROK_BACKSLASH },
{ KEY_RightBracket, RETROK_RIGHTBRACKET },
// RETROK_CARET },
// RETROK_UNDERSCORE },
{ KEY_Grave, RETROK_BACKQUOTE },
{ KEY_A, RETROK_a },
{ KEY_B, RETROK_b },
{ KEY_C, RETROK_c },
{ KEY_D, RETROK_d },
{ KEY_E, RETROK_e },
{ KEY_F, RETROK_f },
{ KEY_G, RETROK_g },
{ KEY_H, RETROK_h },
{ KEY_I, RETROK_i },
{ KEY_J, RETROK_j },
{ KEY_K, RETROK_k },
{ KEY_L, RETROK_l },
{ KEY_M, RETROK_m },
{ KEY_N, RETROK_n },
{ KEY_O, RETROK_o },
{ KEY_P, RETROK_p },
{ KEY_Q, RETROK_q },
{ KEY_R, RETROK_r },
{ KEY_S, RETROK_s },
{ KEY_T, RETROK_t },
{ KEY_U, RETROK_u },
{ KEY_V, RETROK_v },
{ KEY_W, RETROK_w },
{ KEY_X, RETROK_x },
{ KEY_Y, RETROK_y },
{ KEY_Z, RETROK_z },
{ KEY_DeleteForward, RETROK_DELETE },
{ KP_0, RETROK_KP0 },
{ KP_1, RETROK_KP1 },
{ KP_2, RETROK_KP2 },
{ KP_3, RETROK_KP3 },
{ KP_4, RETROK_KP4 },
{ KP_5, RETROK_KP5 },
{ KP_6, RETROK_KP6 },
{ KP_7, RETROK_KP7 },
{ KP_8, RETROK_KP8 },
{ KP_9, RETROK_KP9 },
{ KP_Point, RETROK_KP_PERIOD },
{ KP_Divide, RETROK_KP_DIVIDE },
{ KP_Multiply, RETROK_KP_MULTIPLY },
{ KP_Subtract, RETROK_KP_MINUS },
{ KP_Add, RETROK_KP_PLUS },
{ KP_Enter, RETROK_KP_ENTER },
{ KP_Equals, RETROK_KP_EQUALS },
{ KEY_Up, RETROK_UP },
{ KEY_Down, RETROK_DOWN },
{ KEY_Right, RETROK_RIGHT },
{ KEY_Left, RETROK_LEFT },
{ KEY_Insert, RETROK_INSERT },
{ KEY_Home, RETROK_HOME },
{ KEY_End, RETROK_END },
{ KEY_PageUp, RETROK_PAGEUP },
{ KEY_PageDown, RETROK_PAGEDOWN },
{ KEY_F1, RETROK_F1 },
{ KEY_F2, RETROK_F2 },
{ KEY_F3, RETROK_F3 },
{ KEY_F4, RETROK_F4 },
{ KEY_F5, RETROK_F5 },
{ KEY_F6, RETROK_F6 },
{ KEY_F7, RETROK_F7 },
{ KEY_F8, RETROK_F8 },
{ KEY_F9, RETROK_F9 },
{ KEY_F10, RETROK_F10 },
{ KEY_F11, RETROK_F11 },
{ KEY_F12, RETROK_F12 },
{ KEY_F13, RETROK_F13 },
{ KEY_F14, RETROK_F14 },
{ KEY_F15, RETROK_F15 },
// RETROK_NUMLOCK },
{ KEY_CapsLock, RETROK_CAPSLOCK },
// RETROK_SCROLLOCK },
{ KEY_RightShift, RETROK_RSHIFT },
{ KEY_LeftShift, RETROK_LSHIFT },
{ KEY_RightControl, RETROK_RCTRL },
{ KEY_LeftControl, RETROK_LCTRL },
{ KEY_RightAlt, RETROK_RALT },
{ KEY_LeftAlt, RETROK_LALT },
{ KEY_RightGUI, RETROK_RMETA },
{ KEY_LeftGUI, RETROK_RMETA },
// RETROK_LSUPER },
// RETROK_RSUPER },
// RETROK_MODE },
// RETROK_COMPOSE },
// RETROK_HELP },
{ KEY_PrintScreen, RETROK_PRINT },
// RETROK_SYSREQ },
// RETROK_BREAK },
{ KEY_Menu, RETROK_MENU },
// RETROK_POWER },
// RETROK_EURO },
// RETROK_UNDO },
{ 0, RETROK_UNKNOWN }
};
const char* apple_keycode_hidusage_to_name(uint32_t hid_usage)
{
for (int i = 0; apple_key_name_map[i].hid_id; i ++)
if (apple_key_name_map[i].hid_id == hid_usage)
return apple_key_name_map[i].keyname;
return "nul";
}

View File

@ -23,7 +23,7 @@
#include "file.h"
//#define HAVE_DEBUG_FILELOG
char** apple_argv;
id<RetroArch_Platform> apple_platform;
@ -71,8 +71,6 @@ pthread_mutex_t stasis_mutex = PTHREAD_MUTEX_INITIALIZER;
static void event_stasis(void* userdata)
{
// HACK: uninit_drivers is the nuclear option; uninit_audio would be better but will
// crash when resuming.
uninit_drivers();
pthread_mutex_lock(&stasis_mutex);
pthread_mutex_unlock(&stasis_mutex);
@ -88,8 +86,14 @@ void apple_enter_stasis()
}
}
void apple_exit_stasis()
void apple_exit_stasis(bool reload_config)
{
if (reload_config)
{
objc_clear_config_hack();
config_load();
}
if (apple_is_running)
pthread_mutex_unlock(&stasis_mutex);
}
@ -125,37 +129,38 @@ void apple_run_core(RAModuleInfo* core, const char* file)
apple_core = core;
apple_is_running = true;
static char config_path[PATH_MAX];
static char core_path[PATH_MAX];
static char file_path[PATH_MAX];
static const char* argv[] = { "retroarch", "-c", config_path, "-L", core_path, file_path, 0 };
if (apple_core)
strlcpy(config_path, apple_core.configPath.UTF8String, sizeof(config_path));
else
strlcpy(config_path, RAModuleInfo.globalConfigPath.UTF8String, sizeof(config_path));
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));
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)
{
argv[3] = "-L";
argv[4] = core_path;
strlcpy(core_path, apple_core.path.UTF8String, sizeof(core_path));
strlcpy(file_path, file, sizeof(file_path));
}
else
{
argv[3] = "--menu";
argv[4] = 0;
if (file && core)
{
strlcpy(core_path, apple_core.path.UTF8String, sizeof(core_path));
strlcpy(file_path, file, sizeof(file_path));
}
apple_argv = (char**)((file && core) ? argv_game : argv_menu);
}
if (pthread_create(&apple_retro_thread, 0, rarch_main_spring, argv))
if (pthread_create(&apple_retro_thread, 0, rarch_main_spring, apple_argv))
{
apple_argv = 0;
apple_rarch_exited((void*)1);
return;
}
apple_argv = 0;
pthread_detach(apple_retro_thread);
}
}

View File

@ -23,12 +23,15 @@ char* ios_get_rarch_system_directory();
// These functions should only be called as arguments to dispatch_sync
void apple_rarch_exited (void* result);
// These functions must only be called in gfx/context/ioseagl_ctx.c
// These functions must only be called in gfx/context/apple_gl_context.c
bool apple_init_game_view(void);
void apple_destroy_game_view(void);
bool apple_set_video_mode(unsigned width, unsigned height, bool fullscreen);
void apple_flip_game_view(void);
void apple_set_game_view_sync(unsigned interval);
void apple_get_game_view_size(unsigned *width, unsigned *height);
void apple_update_window_title(void);
bool apple_game_view_has_focus(void);
void *apple_get_proc_address(const char *symbol_name);
#ifdef IOS

View File

@ -18,8 +18,8 @@
#include "general.h"
enum setting_type { ST_NONE, ST_BOOL, ST_INT, ST_FLOAT, ST_PATH, ST_STRING, ST_HEX, ST_GROUP, ST_SUB_GROUP,
ST_END_GROUP, ST_END_SUB_GROUP };
enum setting_type { ST_NONE, ST_BOOL, ST_INT, ST_FLOAT, ST_PATH, ST_STRING, ST_HEX, ST_BIND,
ST_GROUP, ST_SUB_GROUP, ST_END_GROUP, ST_END_SUB_GROUP };
typedef struct
{
@ -28,36 +28,43 @@ typedef struct
const char* name;
void* value;
uint32_t size;
const char* short_description;
const char* long_description;
const char** values;
uint32_t input_player;
double min;
double max;
bool allow_blank;
} rarch_setting_t;
#define START_GROUP(NAME) { ST_GROUP, NAME, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define END_GROUP() { ST_END_GROUP, 0, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define START_SUB_GROUP(NAME) { ST_SUB_GROUP, NAME, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define END_SUB_GROUP() { ST_END_SUB_GROUP, 0, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define START_GROUP(NAME) { ST_GROUP, NAME, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define END_GROUP() { ST_END_GROUP, 0, 0, 0, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_BOOL(TARGET, NAME, SHORT) { ST_BOOL, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_INT(TARGET, NAME, SHORT) { ST_INT, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_FLOAT(TARGET, NAME, SHORT) { ST_FLOAT, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_PATH(TARGET, NAME, SHORT) { ST_PATH, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_STRING(TARGET, NAME, SHORT) { ST_STRING, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
#define CONFIG_HEX(TARGET, NAME, SHORT) { ST_HEX, NAME, &TARGET, SHORT, 0, 0, 0, 0.0, 0.0, false },
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")
@ -67,6 +74,7 @@ const rarch_setting_t setting_data[] =
CONFIG_STRING(g_settings.input.joypad_driver, "input_joypad_driver", "Joypad Driver")
END_SUB_GROUP()
END_GROUP()
#endif
/*********/
/* PATHS */
@ -92,7 +100,6 @@ const rarch_setting_t setting_data[] =
END_GROUP()
/*************/
/* EMULATION */
/*************/
@ -113,6 +120,82 @@ const rarch_setting_t setting_data[] =
END_SUB_GROUP()
END_GROUP()
/*********/
/* 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()
#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
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()
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 */
/*********/
@ -162,8 +245,8 @@ const rarch_setting_t setting_data[] =
/* Input: Overlay */
#ifdef HAVE_OVERLAY
CONFIG_PATH(g_settings.input.overlay, "input_overlay", "Input Overlay")
CONFIG_FLOAT(g_settings.input.overlay_opacity, "overlay_opacity", "Overlay Opacity")
CONFIG_FLOAT(g_settings.input.overlay_scale, "overlay_scale", "Overlay Scale")
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 */
@ -175,79 +258,67 @@ const rarch_setting_t setting_data[] =
CONFIG_INT(g_settings.input.icade_profile[3], "input_autodetect_icade_profile_pad4", "iCade 4")
#endif
END_SUB_GROUP()
END_GROUP()
/*********/
/* 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()
/* Video: Window Manager */
START_SUB_GROUP("Window Manager")
CONFIG_BOOL(g_settings.video.disable_composition, "video_disable_composition", "Disable WM Composition")
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("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_INT(g_settings.video.aspect_ratio_idx, "aspect_ratio_index", "Aspect Ratio Index")
CONFIG_BOOL(g_settings.video.aspect_ratio_auto, "video_aspect_ratio_auto", "Use Auto Aspect Ratio")
END_SUB_GROUP()
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 */
START_SUB_GROUP("Player 1")
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_Y], 1, "y", "Y button (left)")
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_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_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_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_TURBO_ENABLE], 1, "turbo", "Turbo enable")
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_LEFT_X_MINUS], 1, "l_x_minus", "Left analog X- (left)")
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_Y_MINUS], 1, "l_y_minus", "Left analog Y- (up)")
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_ANALOG_RIGHT_X_MINUS], 1, "r_x_minus", "Right analog X- (left)")
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_Y_MINUS], 1, "r_y_minus", "Right analog Y- (up)")
END_SUB_GROUP()
END_GROUP()
@ -266,4 +337,11 @@ const rarch_setting_t setting_data[] =
{ 0 }
};
// HACK
#undef g_settings
#undef g_extern
// Keyboard
#include "keycode.h"
#endif

View File

@ -57,7 +57,7 @@ NSString* objc_get_value_from_config(config_file_t* config, NSString* name, NSSt
if (config)
config_get_string(config, [name UTF8String], &data);
NSString* result = data ? [NSString stringWithUTF8String:data] : defaultValue;
NSString* result = data ? @(data) : defaultValue;
free(data);
return result;
}
@ -110,6 +110,11 @@ char* ios_get_rarch_system_directory()
return self.sections[indexPath.section][indexPath.row + 1];
}
- (void)reset
{
self.sections = [NSMutableArray array];
[self.tableView reloadData];
}
@end
#endif

View File

@ -34,7 +34,7 @@ void ios_add_log_message(const char* format, ...)
va_start(args, format);
vsnprintf(buffer, 512, format, args);
va_end(args);
[g_messages addObject:[NSString stringWithUTF8String: buffer]];
[g_messages addObject:@(buffer)];
pthread_mutex_unlock(&g_lock);
}

View File

@ -17,7 +17,7 @@
#include <dlfcn.h>
#include <CoreFoundation/CFRunLoop.h>
#include "../../../RetroArch/rarch_wrapper.h"
#include "apple/common/rarch_wrapper.h"
#define BUILDING_BTDYNAMIC
#include "btdynamic.h"

View File

@ -20,7 +20,7 @@
#include <stdio.h>
#include <string.h>
#include "../../../RetroArch/rarch_wrapper.h"
#include "apple/common/rarch_wrapper.h"
#include "btdynamic.h"
#include "btpad.h"
#include "btpad_queue.h"

View File

@ -18,7 +18,7 @@
#include <stdlib.h>
#include "boolean.h"
#include "../../../RetroArch/rarch_wrapper.h"
#include "apple/common/rarch_wrapper.h"
#include "btdynamic.h"
#include "btpad.h"
@ -37,7 +37,7 @@ struct btpad_ps3_data
static void btpad_ps3_send_control(struct btpad_ps3_data* device)
{
// TODO: Can this be modified to turn of motion tracking?
// TODO: Can this be modified to turn off motion tracking?
static uint8_t report_buffer[] = {
0x52, 0x01,
0x00, 0x00, 0x00, 0x00, 0x00,

View File

@ -18,7 +18,7 @@
#include <stdlib.h>
#include "boolean.h"
#include "../../../RetroArch/rarch_wrapper.h"
#include "apple/common/rarch_wrapper.h"
#include "btdynamic.h"
#include "btpad.h"

View File

@ -16,7 +16,7 @@
#include <dirent.h>
#include <sys/stat.h>
#import "../RetroArch/RetroArch_Apple.h"
#import "apple/common/RetroArch_Apple.h"
#import "views.h"
#include "conf/config_file.h"
@ -29,50 +29,47 @@
{
NSString* _path;
NSMutableArray* _sectionNames;
id<RADirectoryListDelegate> _delegate;
}
+ (id)directoryListAtBrowseRoot
{
NSString* rootPath = RetroArch_iOS.get.documentsDirectory;
NSString* ragPath = [rootPath stringByAppendingPathComponent:@"RetroArchGames"];
RADirectoryList* list = [RADirectoryList directoryListForPath:path_is_directory(ragPath.UTF8String) ? ragPath : rootPath];
return list;
}
+ (id)directoryListForPath:(NSString*)path
{
// NOTE: Don't remove or ignore this abstraction, this function will be expanded when cover art comes back.
return [[RADirectoryList alloc] initWithPath:path];
}
- (id)initWithPath:(NSString*)path
- (id)initWithPath:(NSString*)path delegate:(id<RADirectoryListDelegate>)delegate
{
_path = path;
_delegate = delegate;
self = [super initWithStyle:UITableViewStylePlain];
self.title = path.lastPathComponent;
self.hidesHeaders = YES;
NSMutableArray *toolbarButtons = [[NSMutableArray alloc] initWithCapacity:3];
NSMutableArray *toolbarButtons = [[NSMutableArray alloc] initWithCapacity:3];
UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refresh)];
refreshButton.style = UIBarButtonItemStyleBordered;
[toolbarButtons addObject:refreshButton];
UIBarButtonItem *refreshButton = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemRefresh target:self action:@selector(refresh)];
refreshButton.style = UIBarButtonItemStyleBordered;
[toolbarButtons addObject:refreshButton];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[toolbarButtons addObject:flexibleSpace];
UIBarButtonItem *flexibleSpace = [[UIBarButtonItem alloc] initWithBarButtonSystemItem:UIBarButtonSystemItemFlexibleSpace target:self action:nil];
[toolbarButtons addObject:flexibleSpace];
UIBarButtonItem *newFolderButton = [[UIBarButtonItem alloc] initWithTitle:@"New Folder" style:UIBarButtonItemStyleBordered target:self action:@selector(createNewFolder)];
[toolbarButtons addObject:newFolderButton];
UIBarButtonItem *newFolderButton = [[UIBarButtonItem alloc] initWithTitle:@"New Folder" style:UIBarButtonItemStyleBordered target:self action:@selector(createNewFolder)];
[toolbarButtons addObject:newFolderButton];
[[[RetroArch_iOS get] toolbar] setItems:toolbarButtons];
[self setToolbarItems:toolbarButtons];
[self refresh];
[[[RetroArch_iOS get] toolbar] setItems:toolbarButtons];
[self setToolbarItems:toolbarButtons];
return self;
}
- (void)viewWillAppear:(BOOL)animated
{
[self refresh];
}
- (void)viewDidDisappear:(BOOL)animated
{
[self reset];
}
- (void)refresh
{
static const char sectionNames[28] = { '/', '#', 'A', 'B', 'C', 'D', 'E', 'F', 'G', 'H', 'I', 'J', 'K', 'L',
@ -104,7 +101,7 @@
section = contents->elems[i].attr.b ? 0 : section;
RADirectoryItem* item = RADirectoryItem.new;
item.path = [NSString stringWithUTF8String:contents->elems[i].data];
item.path = @(contents->elems[i].data);
item.isDirectory = contents->elems[i].attr.b;
[sectionLists[section] addObject:item];
}
@ -127,37 +124,27 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = (RADirectoryItem*)[self itemForIndexPath:indexPath];
if(path.isDirectory)
[[RetroArch_iOS get] pushViewController:[RADirectoryList directoryListForPath:path.path] animated:YES];
else
{
if (access(_path.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);
[[RetroArch_iOS get] pushViewController:[[RAModuleList alloc] initWithGame:path.path] animated:YES];
}
[_delegate directoryList:self itemWasSelected:[self itemForIndexPath:indexPath]];
}
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
RADirectoryItem* path = (RADirectoryItem*)[self itemForIndexPath:indexPath];
static NSString *CellIdentifier = @"path";
static NSString* const cell_types[2] = { @"file", @"folder" };
static NSString* const icon_types[2] = { @"ic_file", @"ic_dir" };
static const UITableViewCellAccessoryType accessory_types[2] = { UITableViewCellAccessoryDetailDisclosureButton,
UITableViewCellAccessoryDisclosureIndicator };
RADirectoryItem* path = [self itemForIndexPath:indexPath];
uint32_t type_id = path.isDirectory ? 1 : 0;
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:CellIdentifier];
cell = (cell != nil) ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier];
cell.textLabel.text = [path.path lastPathComponent];
cell.accessoryType = (path.isDirectory) ? UITableViewCellAccessoryDisclosureIndicator : UITableViewCellAccessoryNone;
if (path.isDirectory) {
cell.imageView.image = [UIImage imageNamed:@"ic_dir"];
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
} else {
cell.imageView.image = [UIImage imageNamed:@"ic_file"];
cell.accessoryType = UITableViewCellAccessoryDetailDisclosureButton;
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:cell_types[type_id]];
if (!cell)
{
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:cell_types[type_id]];
cell.imageView.image = [UIImage imageNamed:icon_types[type_id]];
cell.accessoryType = accessory_types[type_id];
}
cell.textLabel.text = [path.path lastPathComponent];
return cell;
}
@ -224,26 +211,25 @@
@implementation RAModuleList
{
NSString* _game;
id<RAModuleListDelegate> _delegate;
}
- (id)initWithGame:(NSString*)path
- (id)initWithGame:(NSString*)path delegate:(id<RAModuleListDelegate>)delegate
{
self = [super initWithStyle:UITableViewStyleGrouped];
[self setTitle:[path lastPathComponent]];
_game = path;
[self setTitle:path ? [path lastPathComponent] : @"Cores"];
_delegate = delegate;
// Load the modules with their data
NSArray* moduleList = [RAModuleInfo getModules];
NSArray* moduleList = apple_get_modules();
NSMutableArray* supported = [NSMutableArray arrayWithObject:@"Suggested Cores"];
NSMutableArray* other = [NSMutableArray arrayWithObject:@"Other Cores"];
for (RAModuleInfo* i in moduleList)
{
if ([i supportsFileAtPath:_game]) [supported addObject:i];
else [other addObject:i];
if (path && [i supportsFileAtPath:path]) [supported addObject:i];
else [other addObject:i];
}
if (supported.count > 1)
@ -257,7 +243,7 @@
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
apple_run_core((RAModuleInfo*)[self itemForIndexPath:indexPath], _game.UTF8String);
[_delegate moduleList:self itemWasSelected:[self itemForIndexPath:indexPath]];
}
- (void)infoButtonTapped:(id)sender
@ -363,21 +349,8 @@
NSString *directoryPath = [currentDirectoryPath stringByAppendingPathComponent:cell.textLabel.text];
NSString *newPath = [directoryPath stringByAppendingPathComponent:fileName];
BOOL didMove = [[NSFileManager defaultManager] moveItemAtPath:selectedFilePath toPath:newPath error:nil];
if (didMove) {
NSArray *viewsControllers = [[self presentingViewController] childViewControllers];
// Searches for RADirectoryList instance and call the refresh method
for (int i = 0; i < viewsControllers.count; i++) {
if ([viewsControllers[i] isKindOfClass:[RADirectoryList class]]) {
[viewsControllers[i] refresh];
break;
}
}
} else {
if (![[NSFileManager defaultManager] moveItemAtPath:selectedFilePath toPath:newPath error:nil])
apple_display_alert(@"It was not possible to move the file", 0);
}
[self dismissViewController];
}

View File

@ -17,22 +17,28 @@
#ifndef __RARCH_IOS_PLATFORM_H
#define __RARCH_IOS_PLATFORM_H
#include "views.h"
@interface RAGameView : UIViewController
+ (RAGameView*)get;
- (void)openPauseMenu;
- (void)closePauseMenu;
@end
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate, RetroArch_Platform>
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate, RetroArch_Platform,
RADirectoryListDelegate, RAModuleListDelegate>
+ (RetroArch_iOS*)get;
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
- (void)unloadingCore:(RAModuleInfo*)core;
- (NSString*)retroarchConfigPath;
- (void)refreshSystemConfig;
@property (strong, nonatomic) NSString* configDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (strong, nonatomic) NSString* globalConfigFile; // e.g. /var/mobile/Documents/.RetroArch/retroarch.cfg
@property (strong, nonatomic) NSString* coreDirectory; // e.g. /Applications/RetroArch.app/modules
@property (strong, nonatomic) NSString* documentsDirectory; // e.g. /var/mobile/Documents
@property (strong, nonatomic) NSString* systemDirectory; // e.g. /var/mobile/Documents/.RetroArch
@property (strong, nonatomic) NSString* systemConfigPath; // e.g. /var/mobile/Documents/.RetroArch/frontend.cfg

View File

@ -19,12 +19,12 @@
#import "RetroArch_Apple.h"
#include "rarch_wrapper.h"
#include "../RetroArch/apple_input.h"
#include "apple/common/apple_input.h"
#import "views.h"
#include "input/BTStack/btpad.h"
#include "input/BTStack/btdynamic.h"
#include "input/BTStack/btpad.h"
#include "bluetooth/btpad.h"
#include "bluetooth/btdynamic.h"
#include "bluetooth/btpad.h"
#include "file.h"
@ -85,6 +85,7 @@ static void handle_touch_event(NSArray* touches)
@implementation RetroArch_iOS
{
UIWindow* _window;
NSString* _path;
bool _isGameTop, _isRomList;
uint32_t _settingMenusInBackStack;
@ -111,28 +112,27 @@ static void handle_touch_event(NSArray* touches)
self.documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
self.systemDirectory = [self.documentsDirectory stringByAppendingPathComponent:@".RetroArch"];
self.systemConfigPath = [self.systemDirectory stringByAppendingPathComponent:@"frontend.cfg"];
self.configDirectory = self.systemDirectory;
self.globalConfigFile = [NSString stringWithFormat:@"%@/retroarch.cfg", self.configDirectory];
self.coreDirectory = [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"modules"];
if (!path_make_and_check_directory(self.documentsDirectory.UTF8String, 0755, R_OK | W_OK | X_OK))
apple_display_alert([NSString stringWithFormat:@"Failed to create or access base directory: %@", self.documentsDirectory], 0);
else if (!path_make_and_check_directory(self.systemDirectory.UTF8String, 0755, R_OK | W_OK | X_OK))
apple_display_alert([NSString stringWithFormat:@"Failed to create or access system directory: %@", self.systemDirectory], 0);
else
{
[self pushViewController:[RADirectoryList directoryListAtBrowseRoot] animated:YES];
[self refreshSystemConfig];
if (apple_use_tv_mode)
apple_run_core(nil, 0);
}
[self beginBrowsingForFile];
// Warn if there are no cores present
if ([RAModuleInfo getModules].count == 0)
if (apple_get_modules().count == 0)
apple_display_alert(@"No libretro cores were found. You will not be able to play any games.", 0);
}
- (void)applicationDidBecomeActive:(UIApplication *)application
{
apple_exit_stasis();
apple_exit_stasis(false);
}
- (void)applicationWillResignActive:(UIApplication *)application
@ -140,6 +140,45 @@ static void handle_touch_event(NSArray* touches)
apple_enter_stasis();
}
#pragma mark Frontend Browsing Logic
- (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)
[[RetroArch_iOS get] 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);
[[RetroArch_iOS get] 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
{
@ -217,16 +256,6 @@ static void handle_touch_event(NSArray* touches)
btpad_set_inquiry_state(true);
}
- (NSString*)retroarchConfigPath
{
return self.systemDirectory;
}
- (NSString*)corePath
{
return [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"modules"];
}
#pragma mark FRONTEND CONFIG
- (void)refreshSystemConfig
{
@ -259,7 +288,7 @@ static void handle_touch_event(NSArray* touches)
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;
apple_use_tv_mode = config_get_bool(conf, "ios_tv_mode", &val) && val;
config_file_free(conf);
}

View File

@ -13,13 +13,13 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#import "../RetroArch/RetroArch_Apple.h"
#import "apple/common/RetroArch_Apple.h"
#import "views.h"
#include "../RetroArch/apple_input.h"
#include "../RetroArch/keycode.h"
#include "input/BTStack/btdynamic.h"
#include "input/BTStack/btpad.h"
#include "apple/common/apple_input.h"
#include "apple/common/keycode.h"
#include "bluetooth/btdynamic.h"
#include "bluetooth/btpad.h"
enum SettingTypes
{
@ -275,7 +275,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
- (id)initWithModule:(RAModuleInfo*)module
{
_module = module;
_configPath = _module ? _module.configPath : RAModuleInfo.globalConfigPath;
_configPath = _module ? _module.configFile : apple_platform.globalConfigFile;
config_file_t* config = config_file_new([_configPath UTF8String]);
@ -308,7 +308,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
[NSArray arrayWithObjects:@"Input",
subpath_setting(config, @"input_overlay", @"Input Overlay", @"", overlay_path, @"cfg"),
range_setting(config, @"overlay_opacity", @"Overlay Opacity", @"1.0", 0.0, 1.0),
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",
@ -408,7 +408,7 @@ static void bluetooth_option_changed(RASettingData* setting)
[modules addObject:@"Cores"];
[modules addObject:custom_action(@"Global Core Config", nil, nil, 0)];
NSArray* moduleList = [RAModuleInfo getModules];
NSArray* moduleList = apple_get_modules();
for (RAModuleInfo* i in moduleList)
{
[modules addObject:custom_action(i.description, nil, i, reload_core_config_state)];
@ -840,97 +840,18 @@ static void bluetooth_option_changed(RASettingData* setting)
- (void)checkInput
{
// Keyboard
static const struct
{
const char* const keyname;
const uint32_t hid_id;
} ios_key_name_map[] = {
{ "left", KEY_Left }, { "right", KEY_Right },
{ "up", KEY_Up }, { "down", KEY_Down },
{ "enter", KEY_Enter }, { "kp_enter", KP_Enter },
{ "space", KEY_Space }, { "tab", KEY_Tab },
{ "shift", KEY_LeftShift }, { "rshift", KEY_RightShift },
{ "ctrl", KEY_LeftControl }, { "alt", KEY_LeftAlt },
{ "escape", KEY_Escape }, { "backspace", KEY_DeleteForward },
{ "backquote", KEY_Grave }, { "pause", KEY_Pause },
int32_t value = 0;
{ "f1", KEY_F1 }, { "f2", KEY_F2 },
{ "f3", KEY_F3 }, { "f4", KEY_F4 },
{ "f5", KEY_F5 }, { "f6", KEY_F6 },
{ "f7", KEY_F7 }, { "f8", KEY_F8 },
{ "f9", KEY_F9 }, { "f10", KEY_F10 },
{ "f11", KEY_F11 }, { "f12", KEY_F12 },
{ "num0", KEY_0 }, { "num1", KEY_1 },
{ "num2", KEY_2 }, { "num3", KEY_3 },
{ "num4", KEY_4 }, { "num5", KEY_5 },
{ "num6", KEY_6 }, { "num7", KEY_7 },
{ "num8", KEY_8 }, { "num9", KEY_9 },
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;
{ "insert", KEY_Insert }, { "del", KEY_DeleteForward },
{ "home", KEY_Home }, { "end", KEY_End },
{ "pageup", KEY_PageUp }, { "pagedown", KEY_PageDown },
{ "add", KP_Add }, { "subtract", KP_Subtract },
{ "multiply", KP_Multiply }, { "divide", KP_Divide },
{ "keypad0", KP_0 }, { "keypad1", KP_1 },
{ "keypad2", KP_2 }, { "keypad3", KP_3 },
{ "keypad4", KP_4 }, { "keypad5", KP_5 },
{ "keypad6", KP_6 }, { "keypad7", KP_7 },
{ "keypad8", KP_8 }, { "keypad9", KP_9 },
{ "period", KEY_Period }, { "capslock", KEY_CapsLock },
{ "numlock", KP_NumLock }, { "print_screen", KEY_PrintScreen },
{ "scroll_lock", KEY_ScrollLock },
{ "a", KEY_A }, { "b", KEY_B }, { "c", KEY_C }, { "d", KEY_D },
{ "e", KEY_E }, { "f", KEY_F }, { "g", KEY_G }, { "h", KEY_H },
{ "i", KEY_I }, { "j", KEY_J }, { "k", KEY_K }, { "l", KEY_L },
{ "m", KEY_M }, { "n", KEY_N }, { "o", KEY_O }, { "p", KEY_P },
{ "q", KEY_Q }, { "r", KEY_R }, { "s", KEY_S }, { "t", KEY_T },
{ "u", KEY_U }, { "v", KEY_V }, { "w", KEY_W }, { "x", KEY_X },
{ "y", KEY_Y }, { "z", KEY_Z },
{ "nul", 0x00},
};
for (int i = 0; ios_key_name_map[i].hid_id; i++)
{
if (g_current_input_data.keys[ios_key_name_map[i].hid_id])
{
_value->value = [NSString stringWithUTF8String:ios_key_name_map[i].keyname];
[self finish];
return;
}
}
// Pad Buttons
uint32_t buttons = g_current_input_data.pad_buttons[_value->player] |
((_value->player == 0) ? apple_input_get_icade_buttons() : 0);
for (int i = 0; buttons && i < sizeof(buttons) * 8; i++)
{
if (buttons & (1 << i))
{
_value->button_bind = [NSString stringWithFormat:@"%d", i];
[self finish];
return;
}
}
// Pad Axis
for (int i = 0; i < 4; i++)
{
int16_t value = g_current_input_data.pad_axis[_value->player][i];
if (abs(value) > 0x1000)
{
_value->axis_bind = [NSString stringWithFormat:@"%s%d", (value > 0x1000) ? "+" : "-", i];
[self finish];
break;
}
}
[self finish];
}
@end

View File

@ -29,6 +29,7 @@
- (id)initWithStyle:(UITableViewStyle)style;
- (id)itemForIndexPath:(NSIndexPath*)indexPath;
- (void)reset;
@end
// browser.m
@ -38,17 +39,22 @@
@end
// browser.m
@protocol RADirectoryListDelegate
- (bool)directoryList:(id)list itemWasSelected:(RADirectoryItem*)path;
@end
@interface RADirectoryList : RATableViewController <UIActionSheetDelegate>
@property (nonatomic, weak) RADirectoryItem *selectedItem;
+ (id)directoryListAtBrowseRoot;
+ (id)directoryListForPath:(NSString*)path;
- (id)initWithPath:(NSString*)path;
- (id)initWithPath:(NSString*)path delegate:(id<RADirectoryListDelegate>)delegate;
@end
// browser.m
@protocol RAModuleListDelegate
- (bool)moduleList:(id)list itemWasSelected:(RAModuleInfo*)module;
@end
@interface RAModuleList : RATableViewController
- (id)initWithGame:(NSString*)path;
- (id)initWithGame:(NSString*)path delegate:(id<RAModuleListDelegate>)delegate;
@end
// browser.m

View File

@ -22,6 +22,10 @@
#include "../boolean.h"
#include <pthread.h>
#ifdef OSX
#include <CoreAudio/CoreAudio.h>
#endif
#include <CoreAudio/CoreAudioTypes.h>
#include <AudioUnit/AudioUnit.h>
#include <AudioUnit/AUComponent.h>
@ -93,6 +97,48 @@ static OSStatus audio_write_cb(void *userdata, AudioUnitRenderActionFlags *actio
return noErr;
}
#ifdef OSX
static void choose_output_device(coreaudio_t *dev, const char* device)
{
AudioObjectPropertyAddress propaddr =
{
kAudioHardwarePropertyDevices,
kAudioObjectPropertyScopeGlobal,
kAudioObjectPropertyElementMaster
};
UInt32 size = 0;
if (AudioObjectGetPropertyDataSize(kAudioObjectSystemObject, &propaddr, 0, 0, &size) != noErr)
return;
UInt32 deviceCount = size / sizeof(AudioDeviceID);
AudioDeviceID *devices = malloc(size);
if (!devices || AudioObjectGetPropertyData(kAudioObjectSystemObject, &propaddr, 0, 0, &size, devices) != noErr)
goto done;
propaddr.mScope = kAudioDevicePropertyScopeOutput;
propaddr.mSelector = kAudioDevicePropertyDeviceName;
size = 1024;
for (unsigned i = 0; i < deviceCount; i ++)
{
char device_name[1024];
device_name[0] = 0;
if (AudioObjectGetPropertyData(devices[i], &propaddr, 0, 0, &size, device_name) == noErr && strcmp(device_name, device) == 0)
{
AudioUnitSetProperty(dev->dev, kAudioOutputUnitProperty_CurrentDevice, kAudioUnitScope_Global, 0, &devices[i], sizeof(AudioDeviceID));
goto done;
}
}
done:
free(devices);
}
#endif
static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
{
(void)device;
@ -121,6 +167,11 @@ static void *coreaudio_init(const char *device, unsigned rate, unsigned latency)
if (AudioComponentInstanceNew(comp, &dev->dev) != noErr)
goto error;
#ifdef OSX
if (device)
choose_output_device(dev, device);
#endif
dev->dev_alive = true;
// Set audio format

View File

@ -115,6 +115,8 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
if (!sl)
goto error;
RARCH_LOG("[SLES]: Requested audio latency: %d ms.", latency);
GOTO_IF_FAIL(slCreateEngine(&sl->engine_object, 0, NULL, 0, NULL, NULL));
GOTO_IF_FAIL(SLObjectItf_Realize(sl->engine_object, SL_BOOLEAN_FALSE));
GOTO_IF_FAIL(SLObjectItf_GetInterface(sl->engine_object, SL_IID_ENGINE, &sl->engine));
@ -122,7 +124,11 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
GOTO_IF_FAIL(SLEngineItf_CreateOutputMix(sl->engine, &sl->output_mix, 0, NULL, NULL));
GOTO_IF_FAIL(SLObjectItf_Realize(sl->output_mix, SL_BOOLEAN_FALSE));
sl->buf_size = next_pow2(32 * latency);
if (g_settings.audio.block_frames)
sl->buf_size = g_settings.audio.block_frames * 4;
else
sl->buf_size = next_pow2(32 * latency);
sl->buf_count = (latency * 4 * out_rate + 500) / 1000;
sl->buf_count = (sl->buf_count + sl->buf_size / 2) / sl->buf_size;
@ -137,7 +143,7 @@ static void *sl_init(const char *device, unsigned rate, unsigned latency)
for (unsigned i = 0; i < sl->buf_count; i++)
sl->buffer[i] = sl->buffer_chunk + i * sl->buf_size;
RARCH_LOG("[SLES] : Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n",
RARCH_LOG("[SLES]: Setting audio latency: Block size = %u, Blocks = %u, Total = %u ...\n",
sl->buf_size, sl->buf_count, sl->buf_size * sl->buf_count);
fmt_pcm.formatType = SL_DATAFORMAT_PCM;

90
audio/rwebaudio.c Normal file
View File

@ -0,0 +1,90 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Michael Lelli
*
* 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 "../driver.h"
#include "../general.h"
#include "../emscripten/RWebAudio.h"
static void ra_free(void *data)
{
RWebAudioFree();
}
static void *ra_init(const char *device, unsigned rate, unsigned latency)
{
(void)device;
(void)rate;
void *data = RWebAudioInit(latency);
if (data)
g_settings.audio.out_rate = RWebAudioSampleRate();
return data;
}
static ssize_t ra_write(void *data, const void *buf, size_t size)
{
(void)data;
return RWebAudioWrite(buf, size);
}
static bool ra_stop(void *data)
{
(void)data;
return RWebAudioStop();
}
static void ra_set_nonblock_state(void *data, bool state)
{
(void)data;
RWebAudioSetNonblockState(state);
}
static bool ra_start(void *data)
{
(void)data;
return RWebAudioStart();
}
static bool ra_use_float(void *data)
{
(void)data;
return true;
}
static size_t ra_write_avail(void *data)
{
(void)data;
return RWebAudioWriteAvail();
}
static size_t ra_buffer_size(void *data)
{
(void)data;
return RWebAudioBufferSize();
}
const audio_driver_t audio_rwebaudio = {
ra_init,
ra_write,
ra_stop,
ra_start,
ra_set_nonblock_state,
ra_free,
ra_use_float,
"rwebaudio",
ra_write_avail,
ra_buffer_size,
};

View File

@ -627,7 +627,7 @@ static int16_t qnx_input_state(void *data, const struct retro_keybind **retro_ke
static bool qnx_input_key_pressed(void *data, int key)
{
return ((g_extern.lifecycle_state | driver.overlay_state ) & (1ULL << key));
return ((g_extern.lifecycle_state | driver.overlay_state.buttons ) & (1ULL << key));
}
static void qnx_input_free_input(void *data)

View File

@ -355,6 +355,54 @@ static config_file_t *config_file_new_internal(const char *path, unsigned depth)
return conf;
}
config_file_t *config_file_new_from_string(const char *from_string)
{
struct config_file *conf = (struct config_file*)calloc(1, sizeof(*conf));
if (!conf)
return NULL;
if (!from_string)
return conf;
conf->path = NULL;
conf->include_depth = 0;
struct string_list *lines = string_split(from_string, "\n");
if (!lines)
return conf;
for (size_t i = 0; i < lines->size; i++)
{
struct config_entry_list *list = (struct config_entry_list*)calloc(1, sizeof(*list));
char* line = lines->elems[i].data;
if (line)
{
if (parse_line(conf, list, line))
{
if (conf->entries)
{
conf->tail->next = list;
conf->tail = list;
}
else
{
conf->entries = list;
conf->tail = list;
}
}
}
if (list != conf->tail)
free(list);
}
string_list_free(lines);
return conf;
}
config_file_t *config_file_new(const char *path)
{
return config_file_new_internal(path, 0);

View File

@ -41,6 +41,8 @@ typedef struct config_file config_file_t;
// Loads a config file. Returns NULL if file doesn't exist.
// NULL path will create an empty config file.
config_file_t *config_file_new(const char *path);
// Load a config file from a string.
config_file_t *config_file_new_from_string(const char *from_string);
// Frees config file.
void config_file_free(config_file_t *conf);

View File

@ -63,6 +63,7 @@ enum
AUDIO_PS3,
AUDIO_XENON360,
AUDIO_WII,
AUDIO_RWEBAUDIO,
AUDIO_NULL,
INPUT_ANDROID,
@ -77,6 +78,7 @@ enum
INPUT_LINUXRAW,
INPUT_APPLE,
INPUT_QNX,
INPUT_RWEBINPUT,
INPUT_NULL
};
@ -130,6 +132,8 @@ enum
#define AUDIO_DEFAULT_DRIVER AUDIO_SL
#elif defined(HAVE_DSOUND)
#define AUDIO_DEFAULT_DRIVER AUDIO_DSOUND
#elif defined(EMSCRIPTEN)
#define AUDIO_DEFAULT_DRIVER AUDIO_RWEBAUDIO
#elif defined(HAVE_SDL)
#define AUDIO_DEFAULT_DRIVER AUDIO_SDL
#elif defined(HAVE_XAUDIO)
@ -152,6 +156,8 @@ enum
#define INPUT_DEFAULT_DRIVER INPUT_ANDROID
#elif defined(_WIN32)
#define INPUT_DEFAULT_DRIVER INPUT_DINPUT
#elif defined(EMSCRIPTEN)
#define INPUT_DEFAULT_DRIVER INPUT_RWEBINPUT
#elif defined(HAVE_SDL)
#define INPUT_DEFAULT_DRIVER INPUT_SDL
#elif defined(__CELLOS_LV2__)
@ -215,6 +221,14 @@ static const bool hard_sync = false;
// 2: Etc ...
static const unsigned hard_sync_frames = 0;
// Inserts a black frame inbetween frames.
// Useful for 120 Hz monitors who want to play 60 Hz material with eliminated ghosting. video_refresh_rate should still be configured as if it is a 60 Hz monitor (divide refresh rate by 2).
static bool black_frame_insertion = false;
// Uses a custom swap interval for VSync.
// Set this to effectively halve monitor refresh rate.
static unsigned swap_interval = 1;
// Threaded video. Will possibly increase performance significantly at cost of worse synchronization and latency.
static const bool video_threaded = false;

View File

@ -84,6 +84,9 @@ static const audio_driver_t *audio_drivers[] = {
#ifdef GEKKO
&audio_gx,
#endif
#ifdef EMSCRIPTEN
&audio_rwebaudio,
#endif
#ifdef HAVE_NULLAUDIO
&audio_null,
#endif
@ -165,6 +168,9 @@ static const input_driver_t *input_drivers[] = {
#ifdef __BLACKBERRY_QNX__
&input_qnx,
#endif
#ifdef EMSCRIPTEN
&input_rwebinput,
#endif
#ifdef HAVE_NULLINPUT
&input_null,
#endif
@ -1058,7 +1064,7 @@ void uninit_video_input(void)
{
input_overlay_free(driver.overlay);
driver.overlay = NULL;
driver.overlay_state = 0;
memset(&driver.overlay_state, 0, sizeof(driver.overlay_state));
}
#endif

View File

@ -19,7 +19,7 @@
#include <sys/types.h>
#include "boolean.h"
#include "libretro.h"
#include "libretro_private.h"
#include <stdlib.h>
#include <stdint.h>
#include "msvc/msvc_compat.h"
@ -462,7 +462,7 @@ typedef struct driver
#ifdef HAVE_OVERLAY
input_overlay_t *overlay;
uint64_t overlay_state;
input_overlay_state_t overlay_state;
#endif
// Interface for "poking".
@ -511,6 +511,7 @@ extern const audio_driver_t audio_coreaudio;
extern const audio_driver_t audio_xenon360;
extern const audio_driver_t audio_ps3;
extern const audio_driver_t audio_gx;
extern const audio_driver_t audio_rwebaudio;
extern const audio_driver_t audio_null;
extern const video_driver_t video_gl;
extern const video_driver_t video_psp1;
@ -536,6 +537,7 @@ extern const input_driver_t input_xinput;
extern const input_driver_t input_linuxraw;
extern const input_driver_t input_apple;
extern const input_driver_t input_qnx;
extern const input_driver_t input_rwebinput;
extern const input_driver_t input_null;
#include "driver_funcs.h"

View File

@ -56,7 +56,7 @@ static inline bool input_key_pressed_func(int key)
bool ret = driver.input->key_pressed(driver.input_data, key);
#ifdef HAVE_OVERLAY
ret |= driver.overlay_state & (UINT64_C(1) << key);
ret |= driver.overlay_state.buttons & (UINT64_C(1) << key);
#endif
#ifdef HAVE_COMMAND

View File

@ -30,7 +30,7 @@
#endif
#include "boolean.h"
#include "libretro.h"
#include "libretro_private.h"
#include "dynamic_dummy.h"
#ifdef NEED_DYNAMIC
@ -93,8 +93,6 @@ unsigned (*pretro_get_region)(void);
void *(*pretro_get_memory_data)(unsigned);
size_t (*pretro_get_memory_size)(unsigned);
static bool environment_cb(unsigned cmd, void *data);
#ifdef HAVE_DYNAMIC
#if defined(__APPLE__)
#define DYNAMIC_EXT "dylib"
@ -397,7 +395,7 @@ void init_libretro_sym(bool dummy)
load_symbols(dummy);
pretro_set_environment(environment_cb);
pretro_set_environment(rarch_environment_cb);
}
void uninit_libretro_sym(void)
@ -471,7 +469,7 @@ void dylib_close(dylib_t lib)
}
#endif
static bool environment_cb(unsigned cmd, void *data)
bool rarch_environment_cb(unsigned cmd, void *data)
{
switch (cmd)
{
@ -758,6 +756,41 @@ static bool environment_cb(unsigned cmd, void *data)
break;
}
case RETRO_ENVIRONMENT_SET_LIBRETRO_PATH:
RARCH_LOG("Environ (Private) SET_LIBRETRO_PATH.\n");
if (path_file_exists((const char*)data))
strlcpy(g_settings.libretro, (const char*)data, sizeof(g_settings.libretro));
else
return false;
break;
case RETRO_ENVIRONMENT_EXEC:
case RETRO_ENVIRONMENT_EXEC_ESCAPE:
if (data)
strlcpy(g_extern.fullpath, (const char*)data, sizeof(g_extern.fullpath));
else
*g_extern.fullpath = '\0';
#if !defined( HAVE_DYNAMIC) && defined(RARCH_CONSOLE)
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN_START_GAME);
#elif defined(HAVE_DYNAMIC)
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
#endif
if (cmd == RETRO_ENVIRONMENT_EXEC_ESCAPE)
{
RARCH_LOG("Environ (Private) EXEC_ESCAPE.\n");
g_extern.exec = true;
}
else
RARCH_LOG("Environ (Private) EXEC.\n");
break;
default:
RARCH_LOG("Environ UNSUPPORTED (#%u).\n", cmd);
return false;

View File

@ -101,6 +101,8 @@ extern unsigned (*pretro_get_region)(void);
extern void *(*pretro_get_memory_data)(unsigned);
extern size_t (*pretro_get_memory_size)(unsigned);
extern bool rarch_environment_cb(unsigned cmd, void *data);
#ifdef __cplusplus
}
#endif

28
emscripten/RWebAudio.h Normal file
View File

@ -0,0 +1,28 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Michael Lelli
*
* 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 <stdlib.h>
#include <unistd.h>
#include <stdbool.h>
unsigned RWebAudioSampleRate(void);
void *RWebAudioInit(unsigned latency);
ssize_t RWebAudioWrite(const void *buf, size_t size);
bool RWebAudioStop(void);
bool RWebAudioStart(void);
void RWebAudioSetNonblockState(bool state);
void RWebAudioFree(void);
size_t RWebAudioWriteAvail(void);
size_t RWebAudioBufferSize(void);

29
emscripten/RWebInput.h Normal file
View File

@ -0,0 +1,29 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Michael Lelli
*
* 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 <stdlib.h>
typedef struct rwebinput_state
{
char keys[32];
int mouse_x;
int mouse_y;
char mouse_l;
char mouse_r;
} rwebinput_state_t;
int RWebInputInit(void);
rwebinput_state_t *RWebInputPoll(int context);
void RWebInputDestroy(int context);

View File

@ -0,0 +1,166 @@
//"use strict";
var LibraryRWebAudio = {
$RA__deps: ['$Browser', 'usleep'],
$RA: {
BUFFER_SIZE: 256,
context: null,
buffers: [],
numBuffers: 0,
bufIndex: 0,
bufOffset: 0,
startTime: 0,
nonblock: false,
currentTimeWorkaround: false,
setStartTime: function() {
if (RA.context.currentTime) {
RA.startTime = window['performance']['now']() - RA.context.currentTime * 1000;
var time1 = RA.context.currentTime;
_usleep(50);
if (time1 === RA.context.currentTime) {
RA.currentTimeWorkaround = true;
if (RA.startTime === 0) throw 'startTime is 0';
}
Module["resumeMainLoop"]();
} else window['setTimeout'](RA.setStartTime, 0);
},
getCurrentPerfTime: function() {
if (!RA.currentTimeWorkaround) return RA.context.currentTime;
else if (RA.startTime) return (window['performance']['now']() - RA.startTime) / 1000;
else throw 'getCurrentPerfTime() called before start time set';
},
process: function(queueBuffers) {
var currentTime = RA.getCurrentPerfTime();
for (var i = 0; i < RA.bufIndex; i++) {
if (RA.buffers[i].endTime < currentTime) {
var buf = RA.buffers.splice(i, 1);
RA.buffers[RA.numBuffers - 1] = buf[0];
i--;
RA.bufIndex--;
}
}
},
fillBuffer: function(buf, samples) {
var count = 0;
var leftBuffer = RA.buffers[RA.bufIndex].getChannelData(0);
var rightBuffer = RA.buffers[RA.bufIndex].getChannelData(1);
while (samples && RA.bufOffset !== RA.BUFFER_SIZE) {
leftBuffer[RA.bufOffset] = {{{ makeGetValue('buf', 'count * 8', 'float') }}};
rightBuffer[RA.bufOffset] = {{{ makeGetValue('buf', 'count * 8 + 4', 'float') }}};
RA.bufOffset++;
count++;
samples--;
}
return count;
},
queueAudio: function() {
var index = RA.bufIndex;
var startTime;
if (RA.bufIndex) startTime = RA.buffers[RA.bufIndex - 1].endTime;
else startTime = RA.context.currentTime;
RA.buffers[index].endTime = startTime + RA.buffers[index].duration;
var bufferSource = RA.context.createBufferSource();
bufferSource.buffer = RA.buffers[index];
bufferSource.connect(RA.context.destination);
bufferSource.start(startTime);
RA.bufIndex++;
RA.bufOffset = 0;
},
block: function() {
do {
RA.process();
} while (RA.bufIndex === RA.numBuffers - 1);
}
},
RWebAudioInit: function(latency) {
var ac = window['AudioContext'] || window['webkitAudioContext'];
if (!ac) return 0;
RA.context = new ac();
RA.numBuffers = ((latency * RA.context.sampleRate) / (1000 * RA.BUFFER_SIZE))|0;
if (RA.numBuffers < 2) RA.numBuffers = 2;
for (var i = 0; i < RA.numBuffers; i++) RA.buffers[i] = RA.context.createBuffer(2, RA.BUFFER_SIZE, RA.context.sampleRate);
RA.nonblock = false;
RA.startTime = 0;
// chrome hack to get currentTime running
RA.context.createGain();
window['setTimeout'](RA.setStartTime, 0);
Module["pauseMainLoop"]();
return 1;
},
RWebAudioSampleRate: function() {
return RA.context.sampleRate;
},
RWebAudioWrite: function (buf, size) {
RA.process();
var samples = size / 8;
var count = 0;
while (samples) {
var fill = RA.fillBuffer(buf, samples);
samples -= fill;
count += fill;
buf += fill * 8;
if (RA.bufOffset === RA.BUFFER_SIZE) {
if (RA.bufIndex === RA.numBuffers - 1) {
if (RA.nonblock) break;
else RA.block();
}
RA.queueAudio();
}
}
return count * 8;
},
RWebAudioStop: function() {
RA.bufIndex = 0;
RA.bufOffset = 0;
return true;
},
RWebAudioStart: function() {
return true;
},
RWebAudioSetNonblockState: function(state) {
RA.nonblock = state;
},
RWebAudioFree: function() {
RA.bufIndex = 0;
RA.bufOffset = 0;
return;
},
RWebAudioBufferSize: function() {
return RA.numBuffers * RA.BUFFER_SIZE + RA.BUFFER_SIZE;
},
RWebAudioWriteAvail: function() {
RA.process();
return ((RA.numBuffers - RA.bufIndex) * RA.BUFFER_SIZE - RA.bufOffset) * 8;
}
};
autoAddDeps(LibraryRWebAudio, '$RA');
mergeInto(LibraryManager.library, LibraryRWebAudio);

View File

@ -0,0 +1,108 @@
//"use strict";
var LibraryRWebInput = {
$RI__deps: ['$Browser'],
$RI: {
temp: null,
contexts: [],
eventHandler: function(event) {
var i;
switch (event.type) {
case 'mousemove':
var x = event['movementX'] || event['mozMovementX'] || event['webkitMovementX'];
var y = event['movementY'] || event['mozMovementY'] || event['webkitMovementY'];
for (i = 0; i < RI.contexts.length; i++) {
var oldX = {{{ makeGetValue('RI.contexts[i].state', '32', 'i32') }}};
var oldY = {{{ makeGetValue('RI.contexts[i].state', '36', 'i32') }}};
x += oldX;
y += oldY;
{{{ makeSetValue('RI.contexts[i].state', '32', 'x', 'i32') }}};
{{{ makeSetValue('RI.contexts[i].state', '36', 'y', 'i32') }}};
}
break;
case 'mouseup':
case 'mousedown':
var value;
var offset;
if (event.button === 0) offset = 40;
else if (event.button === 2) offset = 41;
else break;
if (event.type === 'mouseup') value = 0;
else value = 1;
for (i = 0; i < RI.contexts.length; i++) {
{{{ makeSetValue('RI.contexts[i].state', 'offset', 'value', 'i8') }}};
}
break;
case 'keyup':
case 'keydown':
var key = event.keyCode;
var offset = key >> 3;
var bit = 1 << (key & 7);
if (offset >= 32) throw 'key code error! bad code: ' + key;
for (i = 0; i < RI.contexts.length; i++) {
var value = {{{ makeGetValue('RI.contexts[i].state', 'offset', 'i8') }}};
if (event.type === 'keyup') value &= ~bit;
else value |= bit;
{{{ makeSetValue('RI.contexts[i].state', 'offset', 'value', 'i8') }}};
}
event.preventDefault();
break;
case 'blur':
case 'visibilitychange':
for (i = 0; i < RI.contexts.length; i++) {
_memset(RI.contexts[i].state, 0, 42);
}
break;
}
}
},
RWebInputInit: function(latency) {
if (RI.contexts.length === 0) {
document.addEventListener('keyup', RI.eventHandler, false);
document.addEventListener('keydown', RI.eventHandler, false);
document.addEventListener('mousemove', RI.eventHandler, false);
document.addEventListener('mouseup', RI.eventHandler, false);
document.addEventListener('mousedown', RI.eventHandler, false);
document.addEventListener('blur', RI.eventHandler, false);
document.addEventListener('onvisbilitychange', RI.eventHandler, false);
}
if (RI.temp === null) RI.temp = _malloc(42);
var s = _malloc(42);
_memset(s, 0, 42);
RI.contexts.push({
state: s
});
return RI.contexts.length;
},
RWebInputPoll: function(context) {
context -= 1;
var state = RI.contexts[context].state;
_memcpy(RI.temp, state, 42);
// reset mouse movements
{{{ makeSetValue('RI.contexts[context].state', '32', '0', 'i32') }}};
{{{ makeSetValue('RI.contexts[context].state', '36', '0', 'i32') }}};
return RI.temp;
},
RWebInputDestroy: function (context) {
if (context === RI.contexts.length) {
RI.contexts.pop();
if (RI.contexts.length === 0) {
document.removeEventListener('keyup', RI.eventHandler, false);
document.removeEventListener('keydown', RI.eventHandler, false);
document.removeEventListener('mousemove', RI.eventHandler, false);
document.removeEventListener('mouseup', RI.eventHandler, false);
document.removeEventListener('mousedown', RI.eventHandler, false);
document.removeEventListener('blur', RI.eventHandler, false);
document.removeEventListener('onvisbilitychange', RI.eventHandler, false);
}
}
}
};
autoAddDeps(LibraryRWebInput, '$RI');
mergeInto(LibraryManager.library, LibraryRWebInput);

View File

@ -42,6 +42,8 @@
#define EXT_EXECUTABLES "dol|DOL"
#define SALAMANDER_FILE "boot.dol"
#define DEFAULT_EXE_EXT ".dol"
#elif defined(EMSCRIPTEN)
#define EXT_EXECUTABLES ""
#endif
#endif

View File

@ -63,9 +63,7 @@ static bool libretro_install_core(const char *path_prefix,
return false;
}
strlcpy(g_settings.libretro, new_path,
sizeof(g_settings.libretro));
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)new_path);
return true;
}

View File

@ -36,11 +36,12 @@ static const frontend_ctx_driver_t *frontend_ctx_drivers[] = {
#if defined(IOS) || defined(OSX)
&frontend_ctx_apple,
#endif
NULL // zero length array is not valid
};
const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident)
{
for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++)
for (unsigned i = 0; frontend_ctx_drivers[i]; i++)
{
if (strcmp(frontend_ctx_drivers[i]->ident, ident) == 0)
return frontend_ctx_drivers[i];
@ -51,7 +52,7 @@ const frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident)
const frontend_ctx_driver_t *frontend_ctx_init_first(void)
{
for (unsigned i = 0; i < sizeof(frontend_ctx_drivers) / sizeof(frontend_ctx_drivers[0]); i++)
for (unsigned i = 0; frontend_ctx_drivers[i]; i++)
return frontend_ctx_drivers[i];
return NULL;

View File

@ -0,0 +1,147 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
* 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-
* 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 <emscripten/emscripten.h>
#include "../general.h"
#include "../conf/config_file.h"
#include "../file.h"
#include "../emscripten/RWebAudio.h"
#ifdef HAVE_RGUI
#include "../frontend/menu/rgui.h"
#endif
#if defined(HAVE_RGUI) || defined(HAVE_RMENU) || defined(HAVE_RMENU_XUI)
#define HAVE_MENU
#else
#undef HAVE_MENU
#endif
static bool menuloop;
static void endloop(void)
{
g_extern.system.shutdown = false;
menu_free();
if (g_extern.config_save_on_exit && *g_extern.config_path)
config_save_file(g_extern.config_path);
if (g_extern.main_is_init)
rarch_main_deinit();
rarch_deinit_msg_queue();
#ifdef PERF_TEST
rarch_perf_log();
#endif
rarch_main_clear_state();
exit(0);
}
static void mainloop(void)
{
if (g_extern.system.shutdown)
{
endloop();
}
else if (menuloop)
{
if (!menu_iterate())
{
menuloop = false;
driver_set_nonblock_state(driver.nonblock_state);
if (driver.audio_data && !audio_start_func())
{
RARCH_ERR("Failed to resume audio driver. Will continue without audio.\n");
g_extern.audio_active = false;
}
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_MENU);
}
}
else if (g_extern.lifecycle_mode_state & (1ULL << MODE_LOAD_GAME))
{
load_menu_game_prepare();
// If ROM load fails, we exit RetroArch. On console it might make more sense to go back to menu though ...
if (load_menu_game())
g_extern.lifecycle_mode_state |= (1ULL << MODE_GAME);
else
{
#ifdef RARCH_CONSOLE
g_extern.lifecycle_mode_state |= (1ULL << MODE_MENU);
#else
return;
#endif
}
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_LOAD_GAME);
}
else if (g_extern.lifecycle_mode_state & (1ULL << MODE_GAME))
{
bool r;
if (g_extern.is_paused && !g_extern.is_oneshot)
r = rarch_main_idle_iterate();
else
r = rarch_main_iterate();
if (!r)
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME);
}
else if (g_extern.lifecycle_mode_state & (1ULL << MODE_MENU))
{
g_extern.lifecycle_mode_state |= 1ULL << MODE_MENU_PREINIT;
// Menu should always run with vsync on.
video_set_nonblock_state_func(false);
if (driver.audio_data)
audio_stop_func();
menuloop = true;
}
else
{
g_extern.system.shutdown = true;
}
}
int main(int argc, char *argv[])
{
emscripten_set_canvas_size(800, 600);
rarch_main_clear_state();
rarch_init_msg_queue();
int init_ret;
if ((init_ret = rarch_main_init(argc, argv))) return init_ret;
#ifdef HAVE_MENU
menu_init();
g_extern.lifecycle_mode_state |= 1ULL << MODE_GAME;
// If we started a ROM directly from command line,
// push it to ROM history.
if (!g_extern.libretro_dummy)
menu_rom_history_push_current();
#endif
emscripten_set_main_loop(mainloop, g_settings.video.vsync ? 0 : INT_MAX, 1);
return 0;
}

View File

@ -444,27 +444,18 @@ void load_menu_game_history(unsigned game_index)
rom_history_get_index(rgui->history,
game_index, &path, &core_path, &core_name);
strlcpy(g_settings.libretro, core_path, sizeof(g_settings.libretro));
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)core_path);
if (path)
{
rgui->load_no_rom = false;
strlcpy(g_extern.fullpath, path, sizeof(g_extern.fullpath));
}
else
{
rgui->load_no_rom = true;
*g_extern.fullpath = '\0';
}
#if !defined( HAVE_DYNAMIC) && defined(RARCH_CONSOLE)
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN_START_GAME);
#elif defined(HAVE_DYNAMIC)
rarch_environment_cb(RETRO_ENVIRONMENT_EXEC, (void*)path);
#if defined(HAVE_DYNAMIC)
libretro_free_system_info(&rgui->info);
libretro_get_system_info(g_settings.libretro, &rgui->info, NULL);
g_extern.lifecycle_mode_state |= (1ULL << MODE_LOAD_GAME);
#endif
}
@ -713,7 +704,7 @@ static uint64_t rgui_input(void)
#ifdef HAVE_OVERLAY
for (unsigned i = 0; i < DEVICE_NAV_LAST; i++)
input_state |= driver.overlay_state & menu_nav_binds[0][i].joykey ? (1ULL << i) : 0;
input_state |= driver.overlay_state.buttons & menu_nav_binds[0][i].joykey ? (1ULL << i) : 0;
#endif
#else
static const int maps[] = {
@ -734,7 +725,7 @@ static uint64_t rgui_input(void)
input_state |= input_input_state_func(binds,
0, RETRO_DEVICE_JOYPAD, 0, maps[i + 0]) ? (1ULL << maps[i + 1]) : 0;
#ifdef HAVE_OVERLAY
input_state |= (driver.overlay_state & (UINT64_C(1) << maps[i + 0])) ? (1ULL << maps[i + 1]) : 0;
input_state |= (driver.overlay_state.buttons & (UINT64_C(1) << maps[i + 0])) ? (1ULL << maps[i + 1]) : 0;
#endif
}

View File

@ -118,6 +118,11 @@ typedef enum
RGUI_SETTINGS_VIDEO_VSYNC,
RGUI_SETTINGS_VIDEO_HARD_SYNC,
RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES,
RGUI_SETTINGS_VIDEO_BLACK_FRAME_INSERTION,
RGUI_SETTINGS_VIDEO_SWAP_INTERVAL,
RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X,
RGUI_SETTINGS_VIDEO_WINDOW_SCALE_Y,
RGUI_SETTINGS_VIDEO_CROP_OVERSCAN,
RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO,
RGUI_SETTINGS_VIDEO_OPTIONS_LAST,
#ifdef HAVE_SHADER_MANAGER

View File

@ -418,6 +418,10 @@ static void render_text(rgui_handle_t *rgui)
rgui->selection_ptr - TERM_HEIGHT / 2 : 0;
size_t end = rgui->selection_ptr + TERM_HEIGHT <= rgui->selection_buf->size ?
rgui->selection_ptr + TERM_HEIGHT : rgui->selection_buf->size;
// Do not scroll if all items are visible.
if (rgui->selection_buf->size <= TERM_HEIGHT)
begin = 0;
if (end - begin > TERM_HEIGHT)
end = begin + TERM_HEIGHT;
@ -598,6 +602,21 @@ static void render_text(rgui_handle_t *rgui)
case RGUI_SETTINGS_VIDEO_HARD_SYNC:
strlcpy(type_str, g_settings.video.hard_sync ? "ON" : "OFF", sizeof(type_str));
break;
case RGUI_SETTINGS_VIDEO_BLACK_FRAME_INSERTION:
strlcpy(type_str, g_settings.video.black_frame_insertion ? "ON" : "OFF", sizeof(type_str));
break;
case RGUI_SETTINGS_VIDEO_SWAP_INTERVAL:
snprintf(type_str, sizeof(type_str), "%u", g_settings.video.swap_interval);
break;
case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X:
snprintf(type_str, sizeof(type_str), "%.1fx", g_settings.video.xscale);
break;
case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_Y:
snprintf(type_str, sizeof(type_str), "%.1fx", g_settings.video.yscale);
break;
case RGUI_SETTINGS_VIDEO_CROP_OVERSCAN:
strlcpy(type_str, g_settings.video.crop_overscan ? "ON" : "OFF", sizeof(type_str));
break;
case RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES:
snprintf(type_str, sizeof(type_str), "%u", g_settings.video.hard_sync_frames);
break;
@ -1500,13 +1519,20 @@ static void rgui_settings_video_options_populate_entries(rgui_handle_t *rgui)
rgui_list_push(rgui->selection_buf, "Integer Scale", RGUI_SETTINGS_VIDEO_INTEGER_SCALE, 0);
rgui_list_push(rgui->selection_buf, "Aspect Ratio", RGUI_SETTINGS_VIDEO_ASPECT_RATIO, 0);
rgui_list_push(rgui->selection_buf, "Custom Ratio", RGUI_SETTINGS_CUSTOM_VIEWPORT, 0);
#ifndef RARCH_PERFORMANCE_MODE
#if !defined(RARCH_CONSOLE) && !defined(RARCH_MOBILE)
rgui_list_push(rgui->selection_buf, "Toggle Fullscreen", RGUI_SETTINGS_TOGGLE_FULLSCREEN, 0);
#endif
rgui_list_push(rgui->selection_buf, "Rotation", RGUI_SETTINGS_VIDEO_ROTATION, 0);
rgui_list_push(rgui->selection_buf, "VSync", RGUI_SETTINGS_VIDEO_VSYNC, 0);
rgui_list_push(rgui->selection_buf, "Hard GPU Sync", RGUI_SETTINGS_VIDEO_HARD_SYNC, 0);
rgui_list_push(rgui->selection_buf, "Hard GPU Sync Frames", RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES, 0);
rgui_list_push(rgui->selection_buf, "Black Frame Insertion", RGUI_SETTINGS_VIDEO_BLACK_FRAME_INSERTION, 0);
rgui_list_push(rgui->selection_buf, "VSync Swap Interval", RGUI_SETTINGS_VIDEO_SWAP_INTERVAL, 0);
#if !defined(RARCH_CONSOLE) && !defined(RARCH_MOBILE)
rgui_list_push(rgui->selection_buf, "Windowed Scale (X)", RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X, 0);
rgui_list_push(rgui->selection_buf, "Windowed Scale (Y)", RGUI_SETTINGS_VIDEO_WINDOW_SCALE_Y, 0);
#endif
rgui_list_push(rgui->selection_buf, "Crop Overscan (reload)", RGUI_SETTINGS_VIDEO_CROP_OVERSCAN, 0);
rgui_list_push(rgui->selection_buf, "Estimated Monitor FPS", RGUI_SETTINGS_VIDEO_REFRESH_RATE_AUTO, 0);
}
@ -1854,12 +1880,10 @@ static int video_option_toggle_setting(rgui_handle_t *rgui, unsigned setting, rg
driver.video_poke->set_aspect_ratio(driver.video_data, g_settings.video.aspect_ratio_idx);
break;
#ifndef RARCH_PERFORMANCE_MODE
case RGUI_SETTINGS_TOGGLE_FULLSCREEN:
if (action == RGUI_ACTION_OK)
rarch_set_fullscreen(!g_settings.video.fullscreen);
break;
#endif
#ifdef GEKKO
case RGUI_SETTINGS_VIDEO_RESOLUTION:
@ -1936,6 +1960,105 @@ static int video_option_toggle_setting(rgui_handle_t *rgui, unsigned setting, rg
}
break;
case RGUI_SETTINGS_VIDEO_BLACK_FRAME_INSERTION:
switch (action)
{
case RGUI_ACTION_START:
g_settings.video.black_frame_insertion = false;
break;
case RGUI_ACTION_LEFT:
case RGUI_ACTION_RIGHT:
case RGUI_ACTION_OK:
g_settings.video.black_frame_insertion = !g_settings.video.black_frame_insertion;
break;
default:
break;
}
break;
case RGUI_SETTINGS_VIDEO_CROP_OVERSCAN:
switch (action)
{
case RGUI_ACTION_START:
g_settings.video.crop_overscan = true;
break;
case RGUI_ACTION_LEFT:
case RGUI_ACTION_RIGHT:
case RGUI_ACTION_OK:
g_settings.video.crop_overscan = !g_settings.video.crop_overscan;
break;
default:
break;
}
break;
case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X:
case RGUI_SETTINGS_VIDEO_WINDOW_SCALE_Y:
{
float *scale = setting == RGUI_SETTINGS_VIDEO_WINDOW_SCALE_X ? &g_settings.video.xscale : &g_settings.video.yscale;
float old_scale = *scale;
switch (action)
{
case RGUI_ACTION_START:
*scale = 3.0f;
break;
case RGUI_ACTION_LEFT:
*scale -= 1.0f;
break;
case RGUI_ACTION_RIGHT:
*scale += 1.0f;
break;
default:
break;
}
*scale = roundf(*scale);
*scale = max(*scale, 1.0f);
if (old_scale != *scale && !g_settings.video.fullscreen)
rarch_set_fullscreen(g_settings.video.fullscreen); // Reinit video driver.
break;
}
case RGUI_SETTINGS_VIDEO_SWAP_INTERVAL:
{
unsigned old = g_settings.video.swap_interval;
switch (action)
{
case RGUI_ACTION_START:
g_settings.video.swap_interval = 1;
break;
case RGUI_ACTION_LEFT:
g_settings.video.swap_interval--;
break;
case RGUI_ACTION_RIGHT:
case RGUI_ACTION_OK:
g_settings.video.swap_interval++;
break;
default:
break;
}
g_settings.video.swap_interval = min(g_settings.video.swap_interval, 4);
g_settings.video.swap_interval = max(g_settings.video.swap_interval, 1);
if (old != g_settings.video.swap_interval && driver.video && driver.video_data)
video_set_nonblock_state_func(false); // This will update the current swap interval. Since we're in RGUI now, always apply VSync.
break;
}
case RGUI_SETTINGS_VIDEO_HARD_SYNC_FRAMES:
switch (action)
{
@ -2654,7 +2777,8 @@ int rgui_iterate(rgui_handle_t *rgui)
// Core selection on non-console just updates directory listing.
// Will take affect on new ROM load.
#elif defined(GEKKO) && defined(HW_RVL)
strlcpy(g_settings.libretro, path, sizeof(g_settings.libretro)); // Is this supposed to be here?
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)path);
fill_pathname_join(g_extern.fullpath, default_paths.core_dir,
SALAMANDER_FILE, sizeof(g_extern.fullpath));
g_extern.lifecycle_mode_state &= ~(1ULL << MODE_GAME);

View File

@ -460,7 +460,6 @@ static int select_file(void *data, uint64_t input)
char extensions[128];
char comment[128];
char path[PATH_MAX];
bool ret = true;
bool pop_menu_stack = false;
font_params_t font_parms = {0};
@ -495,7 +494,7 @@ static int select_file(void *data, uint64_t input)
if (input & (1ULL << DEVICE_NAV_B))
{
if (filebrowser_iterate(rgui->browser, FILEBROWSER_ACTION_PATH_ISDIR))
ret = filebrowser_iterate(rgui->browser, FILEBROWSER_ACTION_OK);
filebrowser_iterate(rgui->browser, FILEBROWSER_ACTION_OK);
else
{
strlcpy(path, rgui->browser->current_dir.path, sizeof(path));
@ -560,7 +559,7 @@ static int select_file(void *data, uint64_t input)
true, menu_texture->width, menu_texture->height, 1.0f);
break;
case LIBRETRO_CHOICE:
strlcpy(g_settings.libretro, path, sizeof(g_settings.libretro));
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)path);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
return -1;
}

View File

@ -1222,8 +1222,11 @@ HRESULT CRetroArchCoreBrowser::OnNotifyPress( HXUIOBJ hObjPressed, BOOL& bHandle
wcstombs(str_buffer, (const wchar_t *)XuiListGetText(m_menulist, index), sizeof(str_buffer));
if(path_file_exists(rgui->browser->list->elems[index].data))
{
snprintf(g_settings.libretro, sizeof(g_settings.libretro), "%s\\%s",
rgui->browser->current_dir.directory_path, str_buffer);
struct retro_variable var;
var.key = "core_path";
snprintf(var.value, sizeof(var.value), "%s\\%s", rgui->browser->current_dir.directory_path, str_buffer);
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, &var);
g_extern.lifecycle_mode_state |= (1ULL << MODE_EXITSPAWN);
process_input_ret = -1;
}

View File

@ -15,7 +15,7 @@
#include <dispatch/dispatch.h>
#include <pthread.h>
#include "../../apple/RetroArch/rarch_wrapper.h"
#include "../../apple/common/rarch_wrapper.h"
#include "../frontend_context.h"

View File

@ -18,7 +18,7 @@
#include <stdbool.h>
#include "../../driver.h"
#include "../../general.h"
#include "../../libretro.h"
#include "../../libretro_private.h"
#include "../../console/rarch_console.h"
#include "../../file.h"
@ -367,7 +367,11 @@ static int system_process_args(int argc, char *argv[], void *args)
// a big hack: sometimes salamander doesn't save the new core it loads on first boot,
// so we make sure g_settings.libretro is set here
if (!g_settings.libretro[0] && argc >= 1 && strrchr(argv[0], '/'))
strlcpy(g_settings.libretro, strrchr(argv[0], '/') + 1, sizeof(g_settings.libretro));
{
char path[PATH_MAX];
strlcpy(path, strrchr(argv[0], '/') + 1, sizeof(path));
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, path);
}
if (argc > 2 && argv[1] != NULL && argv[2] != NULL)
{

View File

@ -20,6 +20,8 @@
#include "../../boolean.h"
#include <stddef.h>
#include <string.h>
#include "../../dynamic.h"
#include "../../libretro_private.h"
static void get_environment_settings(int argc, char *argv[], void *args)
{
@ -28,7 +30,8 @@ static void get_environment_settings(int argc, char *argv[], void *args)
/* FIXME - should this apply for both BB10 and PB? */
#if defined(__QNX__) && !defined(HAVE_BB10)
strlcpy(g_settings.libretro, "app/native/lib", sizeof(g_settings.libretro));
rarch_environment_cb(RETRO_ENVIRONMENT_SET_LIBRETRO_PATH, (void*)"app/native/lib");
strlcpy(g_extern.config_path, "app/native/retroarch.cfg", sizeof(g_extern.config_path));
strlcpy(g_settings.video.shader_dir, "app/native/shaders_glsl", sizeof(g_settings.video.shader_dir));
#endif

View File

@ -159,6 +159,8 @@ struct settings
unsigned fullscreen_y;
bool vsync;
bool hard_sync;
bool black_frame_insertion;
unsigned swap_interval;
unsigned hard_sync_frames;
bool smooth;
bool force_aspect;
@ -201,6 +203,7 @@ struct settings
char driver[32];
bool enable;
unsigned out_rate;
unsigned block_frames;
float in_rate;
char device[PATH_MAX];
unsigned latency;
@ -471,6 +474,8 @@ struct global
msg_queue_t *msg_queue;
bool exec;
// Rewind support.
state_manager_t *state_manager;
void *state_buf;

View File

@ -25,7 +25,7 @@
#include "../shader_glsl.h"
#endif
#include "../../apple/RetroArch/rarch_wrapper.h"
#include "../../apple/common/rarch_wrapper.h"
static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor)
{
@ -38,22 +38,6 @@ static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned mino
#endif
}
static bool gfx_ctx_set_video_mode(
unsigned width, unsigned height,
bool fullscreen)
{
(void)width;
(void)height;
(void)fullscreen;
return true;
}
static void gfx_ctx_update_window_title(void)
{
char buf[128];
gfx_get_fps(buf, sizeof(buf), false);
}
static void gfx_ctx_check_window(bool *quit,
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
{
@ -77,16 +61,6 @@ static void gfx_ctx_set_resize(unsigned width, unsigned height)
(void)height;
}
static bool gfx_ctx_has_focus(void)
{
return true;
}
static void gfx_ctx_swap_buffers(void)
{
apple_flip_game_view();
}
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
{
*input = NULL;
@ -105,13 +79,13 @@ const gfx_ctx_driver_t gfx_ctx_apple = {
apple_destroy_game_view,
gfx_ctx_bind_api,
apple_set_game_view_sync,
gfx_ctx_set_video_mode,
apple_set_video_mode,
apple_get_game_view_size,
NULL,
gfx_ctx_update_window_title,
apple_update_window_title,
gfx_ctx_check_window,
gfx_ctx_set_resize,
gfx_ctx_has_focus,
apple_game_view_has_focus,
apple_flip_game_view,
gfx_ctx_input_driver,
gfx_ctx_get_proc_address,

View File

@ -93,6 +93,8 @@ static void sighandler(int sig)
static void gfx_ctx_swap_interval(unsigned interval)
{
g_interval = interval;
if (interval > 1)
RARCH_WARN("[KMS/EGL]: Swap intervals > 1 currently not supported. Will use swap interval of 1.\n");
}
static void gfx_ctx_check_window(bool *quit,

View File

@ -0,0 +1,275 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2013 - Hans-Kristian Arntzen
* Copyright (C) 2012 - Michael Lelli
*
* 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/>.
*/
// VideoCore context, for Rasperry Pi.
#include "../../driver.h"
#include "../gfx_context.h"
#include "../gl_common.h"
#include "../gfx_common.h"
#ifdef HAVE_CONFIG_H
#include "../../config.h"
#endif
#include <stdint.h>
#include <unistd.h>
#include <emscripten/emscripten.h>
#include <EGL/egl.h>
#include <EGL/eglext.h>
static EGLContext g_egl_ctx;
static EGLSurface g_egl_surf;
static EGLDisplay g_egl_dpy;
static EGLConfig g_config;
static bool g_inited;
static unsigned g_fb_width;
static unsigned g_fb_height;
static void gfx_ctx_swap_interval(unsigned interval)
{
// no way to control vsync in WebGL
(void)interval;
}
static void gfx_ctx_check_window(bool *quit,
bool *resize, unsigned *width, unsigned *height, unsigned frame_count)
{
(void)frame_count;
int iWidth, iHeight, isFullscreen;
emscripten_get_canvas_size(&iWidth, &iHeight, &isFullscreen);
*width = (unsigned) iWidth;
*height = (unsigned) iHeight;
if (*width != g_fb_width || *height != g_fb_height)
*resize = true;
else
*resize = false;
g_fb_width = (unsigned) iWidth;
g_fb_height = (unsigned) iHeight;
*quit = false;
}
static void gfx_ctx_swap_buffers(void)
{
// no-op in emscripten, no way to force swap/wait for vsync in browsers
//eglSwapBuffers(g_egl_dpy, g_egl_surf);
}
static void gfx_ctx_set_resize(unsigned width, unsigned height)
{
(void)width;
(void)height;
}
static void gfx_ctx_update_window_title(void)
{
char buf[128];
if (gfx_get_fps(buf, sizeof(buf), false))
RARCH_LOG("%s\n", buf);
}
static void gfx_ctx_get_video_size(unsigned *width, unsigned *height)
{
*width = g_fb_width;
*height = g_fb_height;
}
static void gfx_ctx_destroy(void);
static bool gfx_ctx_init(void)
{
EGLint width;
EGLint height;
RARCH_LOG("[EMSCRIPTEN/EGL]: Initializing...\n");
if (g_inited)
{
RARCH_LOG("[EMSCRIPTEN/EGL]: Attempted to re-initialize driver.\n");
return true;
}
EGLint num_config;
static const EGLint attribute_list[] =
{
EGL_RED_SIZE, 8,
EGL_GREEN_SIZE, 8,
EGL_BLUE_SIZE, 8,
EGL_ALPHA_SIZE, 8,
EGL_SURFACE_TYPE, EGL_WINDOW_BIT,
EGL_NONE
};
static const EGLint context_attributes[] =
{
EGL_CONTEXT_CLIENT_VERSION, 2,
EGL_NONE
};
// get an EGL display connection
g_egl_dpy = eglGetDisplay(EGL_DEFAULT_DISPLAY);
if (!g_egl_dpy)
goto error;
// initialize the EGL display connection
if (!eglInitialize(g_egl_dpy, NULL, NULL))
goto error;
// get an appropriate EGL frame buffer configuration
if (!eglChooseConfig(g_egl_dpy, attribute_list, &g_config, 1, &num_config))
goto error;
// create an EGL rendering context
g_egl_ctx = eglCreateContext(g_egl_dpy, g_config, EGL_NO_CONTEXT, context_attributes);
if (!g_egl_ctx)
goto error;
// create an EGL window surface
g_egl_surf = eglCreateWindowSurface(g_egl_dpy, g_config, 0, NULL);
if (!g_egl_surf)
goto error;
// connect the context to the surface
if (!eglMakeCurrent(g_egl_dpy, g_egl_surf, g_egl_surf, g_egl_ctx))
goto error;
eglQuerySurface(g_egl_dpy, g_egl_surf, EGL_WIDTH, &width);
eglQuerySurface(g_egl_dpy, g_egl_surf, EGL_HEIGHT, &height);
g_fb_width = width;
g_fb_height = height;
RARCH_LOG("[EMSCRIPTEN/EGL]: Dimensions: %ux%u\n", width, height);
return true;
error:
gfx_ctx_destroy();
return false;
}
static bool gfx_ctx_set_video_mode(
unsigned width, unsigned height,
bool fullscreen)
{
if (g_inited)
return false;
g_inited = true;
return true;
}
static bool gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor)
{
(void)major;
(void)minor;
switch (api)
{
case GFX_CTX_OPENGL_ES_API:
return eglBindAPI(EGL_OPENGL_ES_API);
default:
return false;
}
}
static void gfx_ctx_destroy(void)
{
if (g_egl_dpy)
{
eglMakeCurrent(g_egl_dpy, EGL_NO_SURFACE, EGL_NO_SURFACE, EGL_NO_CONTEXT);
if (g_egl_ctx)
{
eglDestroyContext(g_egl_dpy, g_egl_ctx);
}
if (g_egl_surf)
{
eglDestroySurface(g_egl_dpy, g_egl_surf);
}
eglTerminate(g_egl_dpy);
}
g_egl_ctx = NULL;
g_egl_surf = NULL;
g_egl_dpy = NULL;
g_config = 0;
g_inited = false;
}
static void gfx_ctx_input_driver(const input_driver_t **input, void **input_data)
{
*input = NULL;
void *rwebinput = input_rwebinput.init();
if (rwebinput)
{
*input = &input_rwebinput;
*input_data = rwebinput;
}
}
static bool gfx_ctx_has_focus(void)
{
return g_inited;
}
static gfx_ctx_proc_t gfx_ctx_get_proc_address(const char *symbol)
{
return eglGetProcAddress(symbol);
}
static float gfx_ctx_translate_aspect(unsigned width, unsigned height)
{
return (float)width / height;
}
static bool gfx_ctx_init_egl_image_buffer(const video_info_t *video)
{
return false;
}
static bool gfx_ctx_write_egl_image(const void *frame, unsigned width, unsigned height, unsigned pitch, bool rgb32, unsigned index, void **image_handle)
{
return false;
}
const gfx_ctx_driver_t gfx_ctx_emscripten = {
gfx_ctx_init,
gfx_ctx_destroy,
gfx_ctx_bind_api,
gfx_ctx_swap_interval,
gfx_ctx_set_video_mode,
gfx_ctx_get_video_size,
gfx_ctx_translate_aspect,
gfx_ctx_update_window_title,
gfx_ctx_check_window,
gfx_ctx_set_resize,
gfx_ctx_has_focus,
gfx_ctx_swap_buffers,
gfx_ctx_input_driver,
gfx_ctx_get_proc_address,
gfx_ctx_init_egl_image_buffer,
gfx_ctx_write_egl_image,
NULL,
"emscripten",
};

View File

@ -469,6 +469,7 @@ static bool gfx_ctx_set_video_mode(
if (!g_hwnd)
goto error;
#ifdef HAVE_WIN32GUI
if (!fullscreen)
{
SetMenu(g_hwnd, LoadMenu(GetModuleHandle(NULL), MAKEINTRESOURCE(IDR_MENU)));
@ -477,6 +478,7 @@ static bool gfx_ctx_set_video_mode(
unsigned menu_height = rcTemp.top + rect.top; // rect.top is negative after AdjustWindowRect().
SetWindowPos(g_hwnd, NULL, 0, 0, width, height + menu_height, SWP_NOMOVE);
}
#endif
if (!fullscreen || windowed_full)
{

View File

@ -145,7 +145,20 @@ void D3DVideo::make_d3dpp(const video_info_t &info, D3DPRESENT_PARAMETERS &d3dpp
d3dpp.Windowed = g_settings.video.windowed_fullscreen || !info.fullscreen;
d3dpp.PresentationInterval = info.vsync ? D3DPRESENT_INTERVAL_ONE : D3DPRESENT_INTERVAL_IMMEDIATE;
if (info.vsync)
{
switch (g_settings.video.swap_interval)
{
default:
case 1: d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_ONE; break;
case 2: d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_TWO; break;
case 3: d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_THREE; break;
case 4: d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_FOUR; break;
}
}
else
d3dpp.PresentationInterval = D3DPRESENT_INTERVAL_IMMEDIATE;
d3dpp.SwapEffect = D3DSWAPEFFECT_DISCARD;
d3dpp.hDeviceWindow = hWnd;
d3dpp.BackBufferCount = 2;
@ -614,6 +627,17 @@ bool D3DVideo::frame(const void *frame,
dev->SetViewport(&screen_vp);
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
// Insert black frame first, so we can screenshot, etc.
if (g_settings.video.black_frame_insertion)
{
if (dev->Present(nullptr, nullptr, nullptr, nullptr) != D3D_OK)
{
needs_restore = true;
return true;
}
dev->Clear(0, 0, D3DCLEAR_TARGET, 0, 1, 0);
}
if (!chain->render(frame, width, height, pitch, rotation))
{
RARCH_ERR("[D3D9]: Failed to render scene.\n");

View File

@ -13,6 +13,7 @@
* If not, see <http://www.gnu.org/licenses/>.
*/
#include "../general.h"
#include "gfx_context.h"
#include "../general.h"
#include <string.h>
@ -52,6 +53,9 @@ static const gfx_ctx_driver_t *gfx_ctx_drivers[] = {
#if defined(IOS) || defined(OSX) //< Don't use __APPLE__ as it breaks basic SDL builds
&gfx_ctx_apple,
#endif
#ifdef EMSCRIPTEN
&gfx_ctx_emscripten,
#endif
};
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident)

View File

@ -108,6 +108,7 @@ extern const gfx_ctx_driver_t gfx_ctx_wgl;
extern const gfx_ctx_driver_t gfx_ctx_videocore;
extern const gfx_ctx_driver_t gfx_ctx_bbqnx;
extern const gfx_ctx_driver_t gfx_ctx_apple;
extern const gfx_ctx_driver_t gfx_ctx_emscripten;
extern const gfx_ctx_driver_t gfx_ctx_null;
const gfx_ctx_driver_t *gfx_ctx_find_driver(const char *ident); // Finds driver with ident. Does not initialize.

View File

@ -1402,18 +1402,7 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
#ifdef HAVE_FBO
// Data is already on GPU :) Have to reset some state however incase core changed it.
if (gl->hw_render_fbo_init)
{
gl_update_input_size(gl, width, height, pitch, false);
if (!gl->fbo_inited)
{
gl_bind_backbuffer();
gl_set_viewport(gl, gl->win_width, gl->win_height, false, true);
}
}
else
if (!gl->hw_render_fbo_init)
#endif
{
gl_update_input_size(gl, width, height, pitch, true);
@ -1430,6 +1419,13 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
#ifdef HAVE_FBO
if (gl->hw_render_fbo_init)
{
gl_update_input_size(gl, width, height, pitch, false);
if (!gl->fbo_inited)
{
gl_bind_backbuffer();
gl_set_viewport(gl, gl->win_width, gl->win_height, false, true);
}
#ifndef HAVE_OPENGLES
if (!gl->core_context)
glEnable(GL_TEXTURE_2D);
@ -1454,6 +1450,11 @@ static bool gl_frame(void *data, const void *frame, unsigned width, unsigned hei
memcpy(tex_info.coord, gl->tex_coords, sizeof(gl->tex_coords));
glClear(GL_COLOR_BUFFER_BIT);
if (g_settings.video.black_frame_insertion)
{
context_swap_buffers_func();
glClear(GL_COLOR_BUFFER_BIT);
}
if (gl->shader)
gl->shader->set_params(width, height,
@ -1623,7 +1624,7 @@ static void gl_set_nonblock_state(void *data, bool state)
gl_t *gl = (gl_t*)data;
(void)gl;
context_swap_interval_func(state ? 0 : 1);
context_swap_interval_func(state ? 0 : g_settings.video.swap_interval);
}
static bool resolve_extensions(gl_t *gl)
@ -1945,7 +1946,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
context_get_video_size_func(&gl->full_x, &gl->full_y);
RARCH_LOG("Detecting screen resolution %ux%u.\n", gl->full_x, gl->full_y);
context_swap_interval_func(video->vsync ? 1 : 0);
context_swap_interval_func(video->vsync ? g_settings.video.swap_interval : 0);
unsigned win_width = video->width;
unsigned win_height = video->height;

View File

@ -87,7 +87,7 @@ static void *vg_init(const video_info_t *video, const input_driver_t **input, vo
if (!vg)
return NULL;
vg->driver = gfx_ctx_init_first(GFX_CTX_OPENVG_API);
vg->driver = gfx_ctx_init_first(GFX_CTX_OPENVG_API, 0, 0);
if (!vg->driver)
{

View File

@ -298,8 +298,8 @@ INPUT
#include "../android/native/jni/input_autodetect.c"
#include "../android/native/jni/input_android.c"
#elif defined(IOS) || defined(OSX)
#include "../apple/RetroArch/apple_input.c"
#include "../apple/RetroArch/apple_joypad.c"
#include "../apple/common/apple_input.c"
#include "../apple/common/apple_joypad.c"
#elif defined(__BLACKBERRY_QNX__)
#include "../blackberry-qnx/qnx_input.c"
#endif

24
input/autoconf/builtin.h Normal file
View File

@ -0,0 +1,24 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - pinumbernumber
*
* 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 AUTOCONF_BUILTIN_H__
#define AUTOCONF_BUILTIN_H__
#include "../input_common.h"
#define DECL_BTN(btn, bind) "input_" #btn "_btn = " #bind "\n"
#define DECL_AXIS(axis, bind) "input_" #axis "_axis = " #bind "\n"
#endif

View File

@ -0,0 +1,92 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2013 - pinumbernumber
*
* 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 "builtin.h"
#define XINPUT_DEFAULT_BINDS \
DECL_BTN(a, 1) \
DECL_BTN(b, 0) \
DECL_BTN(x, 3) \
DECL_BTN(y, 2) \
DECL_BTN(start, 6) \
DECL_BTN(select, 7) \
DECL_BTN(up, h0up) \
DECL_BTN(down, h0down) \
DECL_BTN(left, h0left) \
DECL_BTN(right, h0right) \
DECL_BTN(l, 4) \
DECL_BTN(r, 5) \
DECL_BTN(l3, 8 )\
DECL_BTN(r3, 9) \
DECL_BTN(menu_toggle, 10) \
DECL_AXIS(l2, +4) \
DECL_AXIS(r2, +5) \
DECL_AXIS(l_x_plus, +0) \
DECL_AXIS(l_x_minus, -0) \
DECL_AXIS(l_y_plus, -1) \
DECL_AXIS(l_y_minus, +1) \
DECL_AXIS(r_x_plus, +2) \
DECL_AXIS(r_x_minus, -2) \
DECL_AXIS(r_y_plus, -3) \
DECL_AXIS(r_y_minus, +3)
// Some hardcoded autoconfig information. Will be used for pads with no autoconfig cfg files.
const char* const input_builtin_autoconfs[] =
{
"input_device = \"XInput Controller (Player 1)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 2)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 3)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"XInput Controller (Player 4)\" \n"
"input_driver = \"winxinput\" \n"
XINPUT_DEFAULT_BINDS,
"input_device = \"Dual Trigger 3-in-1\" \n"
"input_driver = \"dinput\" \n"
DECL_BTN(a, 2)
DECL_BTN(b, 1)
DECL_BTN(x, 3)
DECL_BTN(y, 0)
DECL_BTN(start, 9)
DECL_BTN(select, 8)
DECL_BTN(up, h0up)
DECL_BTN(down, h0down)
DECL_BTN(left, h0left)
DECL_BTN(right, h0right)
DECL_BTN(l, 4)
DECL_BTN(r, 5)
DECL_BTN(l2, 6)
DECL_BTN(r2, 7)
DECL_BTN(l3, 10)
DECL_BTN(r3, 11)
DECL_AXIS(l_x_plus, +0)
DECL_AXIS(l_x_minus, -0)
DECL_AXIS(l_y_plus, +1)
DECL_AXIS(l_y_minus, -1)
DECL_AXIS(r_x_plus, +2)
DECL_AXIS(r_x_minus, -2)
DECL_AXIS(r_y_plus, +5)
DECL_AXIS(r_y_minus, -5),
NULL
};

View File

@ -49,6 +49,7 @@ struct dinput_joypad
{
LPDIRECTINPUTDEVICE8 joypad;
DIJOYSTATE2 joy_state;
char* joy_name;
};
static unsigned g_joypad_cnt;
@ -68,12 +69,6 @@ static bool dinput_init_context(void)
if (g_ctx)
return true;
if (driver.display_type != RARCH_DISPLAY_WIN32)
{
RARCH_ERR("Cannot open DInput as no Win32 window is present.\n");
return false;
}
CoInitialize(NULL);
// Who said we shouldn't have same call signature in a COM API? <_<
@ -351,6 +346,11 @@ const input_driver_t input_dinput = {
dinput_grab_mouse,
};
// Keep track of which pad indexes are 360 controllers
// not static, will be read in winxinput_joypad.c
// -1 = not xbox pad, otherwise 0..3
int g_xbox_pad_indexes[MAX_PLAYERS];
static void dinput_joypad_destroy(void)
{
for (unsigned i = 0; i < MAX_PLAYERS; i++)
@ -360,6 +360,10 @@ static void dinput_joypad_destroy(void)
IDirectInputDevice8_Unacquire(g_pads[i].joypad);
IDirectInputDevice8_Release(g_pads[i].joypad);
}
free(g_pads[i].joy_name);
g_pads[i].joy_name = NULL;
}
g_joypad_cnt = 0;
@ -386,6 +390,54 @@ static BOOL CALLBACK enum_axes_cb(const DIDEVICEOBJECTINSTANCE *inst, void *p)
return DIENUM_CONTINUE;
}
// TODO: Use a better way of detecting dual XInput/DInput pads. This current method
// will not work correctly for third-party controllers or future MS pads (Xbox One?).
// An example of this is provided in the DX SDK, which advises "Enum each PNP device
// using WMI and check each device ID to see if it contains "IG_"". Unfortunately the
// example code is a horrible unsightly mess.
static const char* const XINPUT_PAD_NAMES[] =
{
"XBOX 360 For Windows",
"Controller (Gamepad for Xbox 360)",
"Controller (XBOX 360 For Windows)",
"Controller (Xbox 360 Wireless Receiver for Windows)",
"Controller (Xbox wireless receiver for windows)",
"XBOX 360 For Windows (Controller)",
"Xbox 360 Wireless Receiver",
"Xbox 360 Wireless Controller",
"Xbox Receiver for Windows (Wireless Controller)",
"Xbox wireless receiver for windows (Controller)",
"Gamepad F310 (Controller)",
"Controller (Gamepad F310)",
"Wireless Gamepad F710 (Controller)",
"Controller (Batarang wired controller (XBOX))",
"Afterglow Gamepad for Xbox 360 (Controller)"
"Controller (Rumble Gamepad F510)",
"Controller (Wireless Gamepad F710)",
"Controller (Xbox 360 Wireless Receiver for Windows)",
"Controller (Xbox wireless receiver for windows)",
"Controller (XBOX360 GAMEPAD)",
"MadCatz GamePad",
NULL
};
static bool name_is_360_pad(const char* name)
{
for (unsigned i = 0; ; ++i)
{
const char* t = XINPUT_PAD_NAMES[i];
if (t == NULL)
return false;
else if (strcasecmp(name, t) == 0)
return true;
}
}
// Forward declaration
static const char *dinput_joypad_name(unsigned pad);
static int g_last_xbox_pad_index;
static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
{
(void)p;
@ -399,7 +451,22 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
#else
if (FAILED(IDirectInput8_CreateDevice(g_ctx, &inst->guidInstance, pad, NULL)))
#endif
return DIENUM_CONTINUE;
return DIENUM_CONTINUE;
g_pads[g_joypad_cnt].joy_name = strdup(inst->tszProductName);
#ifdef HAVE_WINXINPUT
bool is_360_pad = name_is_360_pad(inst->tszProductName);
if (is_360_pad)
{
if (g_last_xbox_pad_index < 4)
g_xbox_pad_indexes[g_joypad_cnt] = g_last_xbox_pad_index;
++g_last_xbox_pad_index;
goto enum_iteration_done;
}
#endif
IDirectInputDevice8_SetDataFormat(*pad, &c_dfDIJoystick2);
IDirectInputDevice8_SetCooperativeLevel(*pad, (HWND)driver.video_window,
@ -407,9 +474,17 @@ static BOOL CALLBACK enum_joypad_cb(const DIDEVICEINSTANCE *inst, void *p)
IDirectInputDevice8_EnumObjects(*pad, enum_axes_cb,
*pad, DIDFT_ABSAXIS);
#ifdef HAVE_WINXINPUT
if (!is_360_pad)
#endif
{
strlcpy(g_settings.input.device_names[g_joypad_cnt], dinput_joypad_name(g_joypad_cnt), sizeof(g_settings.input.device_names[g_joypad_cnt]));
input_config_autoconfigure_joypad(g_joypad_cnt, dinput_joypad_name(g_joypad_cnt), dinput_joypad.ident);
}
enum_iteration_done:
g_joypad_cnt++;
return DIENUM_CONTINUE;
}
@ -417,6 +492,14 @@ static bool dinput_joypad_init(void)
{
if (!dinput_init_context())
return false;
g_last_xbox_pad_index = 0;
for (unsigned i = 0; i < MAX_PLAYERS; ++i)
{
g_xbox_pad_indexes[i] = -1;
g_pads[i].joy_name = NULL;
}
RARCH_LOG("Enumerating DInput joypads ...\n");
IDirectInput8_EnumDevices(g_ctx, DI8DEVCLASS_GAMECTRL,
@ -524,7 +607,7 @@ static void dinput_joypad_poll(void)
{
struct dinput_joypad *pad = &g_pads[i];
if (pad->joypad)
if ((pad->joypad) && (g_xbox_pad_indexes[i] == -1))
{
memset(&pad->joy_state, 0, sizeof(pad->joy_state));
@ -555,10 +638,13 @@ static bool dinput_joypad_query_pad(unsigned pad)
return pad < MAX_PLAYERS && g_pads[pad].joypad;
}
static const char *dinput_joypad_name(unsigned pad)
{
(void)pad;
// FIXME
if (pad < MAX_PLAYERS)
return g_pads[pad].joy_name;
return NULL;
}

Some files were not shown because too many files have changed in this diff Show More