mirror of
https://github.com/libretro/RetroArch
synced 2025-03-29 22:20:21 +00:00
Merge branch 'master' of https://github.com/libretro/RetroArch
This commit is contained in:
commit
545cdbad2a
11
.project
Normal file
11
.project
Normal file
@ -0,0 +1,11 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<projectDescription>
|
||||
<name>RetroArch_</name>
|
||||
<comment></comment>
|
||||
<projects>
|
||||
</projects>
|
||||
<buildSpec>
|
||||
</buildSpec>
|
||||
<natures>
|
||||
</natures>
|
||||
</projectDescription>
|
5
Makefile
5
Makefile
@ -337,6 +337,11 @@ ifeq ($(DEBUG), 1)
|
||||
OPTIMIZE_FLAG = -O0
|
||||
endif
|
||||
|
||||
ifeq ($(GL_DEBUG), 1)
|
||||
CFLAGS += -DGL_DEBUG
|
||||
CXXFLAGS += -DGL_DEBUG
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall $(OPTIMIZE_FLAG) $(INCLUDE_DIRS) -g -I.
|
||||
ifeq ($(CXX_BUILD), 1)
|
||||
LD = $(CXX)
|
||||
|
159
Makefile.emscripten
Normal file
159
Makefile.emscripten
Normal 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
|
||||
|
27
Makefile.win
27
Makefile.win
@ -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
|
||||
@ -237,6 +251,11 @@ else
|
||||
LDCXXFLAGS += -s
|
||||
endif
|
||||
|
||||
ifeq ($(GL_DEBUG), 1)
|
||||
CFLAGS += -DGL_DEBUG
|
||||
CXXFLAGS += -DGL_DEBUG
|
||||
endif
|
||||
|
||||
CFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I.
|
||||
CXXFLAGS += -Wall -Wno-unused-result -Wno-unused-variable -I. -std=c++0x -D__STDC_CONSTANT_MACROS
|
||||
ifeq ($(CXX_BUILD), 1)
|
||||
@ -301,10 +320,10 @@ clean:
|
||||
rm -f tools/*.o
|
||||
|
||||
dist_x86: all
|
||||
zip -r retroarch-win32-0.9.9.4.zip $(TARGET) $(JTARGET) retroarch.cfg
|
||||
zip -r retroarch-win32-0.9.9.6.zip $(TARGET) $(JTARGET) retroarch.cfg
|
||||
|
||||
dist_x86_64: all
|
||||
zip -r retroarch-win64-0.9.9.4.zip $(TARGET) $(JTARGET) retroarch.cfg
|
||||
zip -r retroarch-win64-0.9.9.6.zip $(TARGET) $(JTARGET) retroarch.cfg
|
||||
|
||||
libs_x86:
|
||||
wget http://themaister.net/retroarch-dl/RetroArch-win32-libs.zip
|
||||
|
@ -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
|
||||
|
||||
|
@ -423,7 +423,7 @@ static void android_input_set_keybinds(void *data, unsigned device,
|
||||
break;
|
||||
case DEVICE_GAMEMID:
|
||||
g_settings.input.device[port] = device;
|
||||
g_settings.input.dpad_emulation[port] = ANALOG_DPAD_NONE;
|
||||
g_settings.input.dpad_emulation[port] = ANALOG_DPAD_DUALANALOG;
|
||||
strlcpy(g_settings.input.device_names[port], "GameMID",
|
||||
sizeof(g_settings.input.device_names[port]));
|
||||
|
||||
@ -1190,6 +1190,7 @@ static void android_input_set_keybinds(void *data, unsigned device,
|
||||
strlcpy(g_settings.input.device_names[port], "OUYA",
|
||||
sizeof(g_settings.input.device_names[port]));
|
||||
|
||||
g_settings.input.dpad_emulation[port] = ANALOG_DPAD_DUALANALOG;
|
||||
keycode_lut[AKEYCODE_DPAD_UP] |= ((RETRO_DEVICE_ID_JOYPAD_UP+1) << shift);
|
||||
keycode_lut[AKEYCODE_DPAD_DOWN] |= ((RETRO_DEVICE_ID_JOYPAD_DOWN+1) << shift);
|
||||
keycode_lut[AKEYCODE_DPAD_LEFT] |= ((RETRO_DEVICE_ID_JOYPAD_LEFT+1) << shift);
|
||||
@ -1228,6 +1229,7 @@ static void android_input_set_keybinds(void *data, unsigned device,
|
||||
g_settings.input.device[port] = device;
|
||||
strlcpy(g_settings.input.device_names[port], "Xperia Play",
|
||||
sizeof(g_settings.input.device_names[port]));
|
||||
g_settings.input.dpad_emulation[port] = ANALOG_DPAD_NONE;
|
||||
|
||||
if ((zeus_second_id != -1 && (zeus_second_id == id)))
|
||||
{
|
||||
@ -1592,8 +1594,9 @@ static void android_input_set_keybinds(void *data, unsigned device,
|
||||
static void android_input_poll(void *data)
|
||||
{
|
||||
int ident;
|
||||
uint64_t lifecycle_mask = (1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS) | (1ULL << RARCH_QUIT_KEY) | (1ULL << RARCH_MENU_TOGGLE);
|
||||
uint64_t *lifecycle_state = &g_extern.lifecycle_state;
|
||||
*lifecycle_state &= ~((1ULL << RARCH_RESET) | (1ULL << RARCH_REWIND) | (1ULL << RARCH_FAST_FORWARD_KEY) | (1ULL << RARCH_FAST_FORWARD_HOLD_KEY) | (1ULL << RARCH_MUTE) | (1ULL << RARCH_SAVE_STATE_KEY) | (1ULL << RARCH_LOAD_STATE_KEY) | (1ULL << RARCH_STATE_SLOT_PLUS) | (1ULL << RARCH_STATE_SLOT_MINUS) | (1ULL << RARCH_QUIT_KEY));
|
||||
*lifecycle_state &= ~lifecycle_mask;
|
||||
|
||||
while ((ident = ALooper_pollAll((input_key_pressed_func(RARCH_PAUSE_TOGGLE)) ? -1 : 0,
|
||||
NULL, NULL, NULL)) >= 0)
|
||||
@ -1752,9 +1755,6 @@ static void android_input_poll(void *data)
|
||||
}
|
||||
else if (type_event == AINPUT_EVENT_TYPE_KEY)
|
||||
{
|
||||
if (debug_enable)
|
||||
snprintf(msg, sizeof(msg), "Pad %d : %d, ac = %d, src = %d.\n", state_id, keycode, action, source);
|
||||
|
||||
/* Hack - we have to decrease the unpacked value by 1
|
||||
* because we 'added' 1 to each entry in the LUT -
|
||||
* RETRO_DEVICE_ID_JOYPAD_B is 0
|
||||
@ -1764,20 +1764,25 @@ static void android_input_poll(void *data)
|
||||
int action = AKeyEvent_getAction(event);
|
||||
uint64_t *key = NULL;
|
||||
|
||||
if(input_state < (1ULL << RARCH_FIRST_META_KEY))
|
||||
if (debug_enable)
|
||||
snprintf(msg, sizeof(msg), "Pad %d : %d, ac = %d, src = %d.\n", state_id, keycode, action, source);
|
||||
|
||||
if (input_state < (1ULL << RARCH_FIRST_META_KEY))
|
||||
key = &state[state_id];
|
||||
else if(input_state)
|
||||
else if (input_state/* && action == AKEY_EVENT_ACTION_DOWN*/)
|
||||
key = &g_extern.lifecycle_state;
|
||||
|
||||
if(key != NULL)
|
||||
if (key != NULL)
|
||||
{
|
||||
if (action == AKEY_EVENT_ACTION_UP)
|
||||
// some controllers send both the up and down events at once when the button is released for "special" buttons, like menu buttons
|
||||
// work around that by only using down events for meta keys (which get cleared every poll anyway)
|
||||
if (action == AKEY_EVENT_ACTION_UP && !(input_state & lifecycle_mask))
|
||||
*key &= ~(input_state);
|
||||
else if (action == AKEY_EVENT_ACTION_DOWN)
|
||||
*key |= input_state;
|
||||
}
|
||||
|
||||
if((keycode == AKEYCODE_VOLUME_UP || keycode == AKEYCODE_VOLUME_DOWN) && keycode_lut[keycode] == 0)
|
||||
if ((keycode == AKEYCODE_VOLUME_UP || keycode == AKEYCODE_VOLUME_DOWN) && keycode_lut[keycode] == 0)
|
||||
handled = 0;
|
||||
}
|
||||
|
||||
@ -1851,7 +1856,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)
|
||||
|
@ -1,7 +1,7 @@
|
||||
<?xml version="1.0" encoding="UTF-8"?>
|
||||
<classpath>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.ANDROID_FRAMEWORK"/>
|
||||
<classpathentry kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.LIBRARIES"/>
|
||||
<classpathentry exported="true" kind="con" path="com.android.ide.eclipse.adt.DEPENDENCIES"/>
|
||||
<classpathentry kind="src" path="src"/>
|
||||
<classpathentry kind="src" path="gen"/>
|
||||
|
@ -1,7 +1,7 @@
|
||||
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
package="org.retroarch"
|
||||
android:versionCode="20"
|
||||
android:versionName="0.9.9.5" >
|
||||
android:versionCode="24"
|
||||
android:versionName="0.9.9.6" >
|
||||
<uses-feature android:glEsVersion="0x00020000" />
|
||||
<uses-feature android:name="android.hardware.touchscreen" android:required="false"/>
|
||||
<uses-sdk
|
||||
@ -16,9 +16,10 @@
|
||||
android:label="@string/app_name"
|
||||
android:hasCode="true">
|
||||
<activity android:name=".browser.CoreSelection"></activity>
|
||||
<activity android:name=".browser.HistorySelection"></activity>
|
||||
<activity android:name=".browser.DisplayRefreshRateTest"></activity>
|
||||
<activity android:name=".browser.RefreshRateSetOS"></activity>
|
||||
<activity android:name=".browser.MainMenuActivity">
|
||||
<activity android:name=".browser.MainMenuActivity" android:exported="true">
|
||||
<intent-filter>
|
||||
<action android:name="android.intent.action.MAIN" />
|
||||
<category android:name="android.intent.category.LAUNCHER" />
|
||||
@ -28,10 +29,12 @@
|
||||
<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>
|
||||
<activity android:name=".browser.ROMActivity"></activity>
|
||||
<activity android:name=".browser.RetroTVMode"></activity>
|
||||
|
||||
<activity android:name=".browser.ShaderActivity"></activity>
|
||||
<activity android:name=".browser.OverlayActivity"></activity>
|
||||
|
@ -1,26 +1,81 @@
|
||||
libretro_mednafen_pce_fast = "Mednafen PCE-fast (PC Engine/PC Engine CD)"
|
||||
libretro_mednafen_wswan = "Mednafen WSwan (Wonderswan)"
|
||||
libretro_fceumm = "FCEUmm (Nintendo NES)"
|
||||
libretro_mednafen_vb = "Mednafen VB (Virtual Boy)"
|
||||
libretro_fba = "Final Burn Alpha (Arcade)"
|
||||
libretro_mednafen_ngp = "Mednafen NGP (Neo-Geo Pocket)"
|
||||
libretro_mednafen_psx = "Mednafen PSX (PlayStation1)"
|
||||
libretro_gambatte = "Gambatte (GameBoy/GameBoy Color)"
|
||||
libretro_genesis_plus_gx = "Genesis Plus GX (Sega Genesis/Sega CD/Master System)"
|
||||
libretro_picodrive = "Picodrive (Sega Genesis/Sega CD/Master System/32X)"
|
||||
libretro_vba_next = "VBA Next (GameBoy Advance)"
|
||||
libretro_prboom = "PrBoom (DOOM)"
|
||||
libretro_snes9x = "SNES9x (Nintendo SNES)"
|
||||
libretro_snes9x_next = "SNES9x Next (Nintendo SNES)"
|
||||
libretro_nestopia = "Nestopia (Nintendo NES)"
|
||||
libretro_pcsx_rearmed-neon = "PCSX-reARMed (PlayStation1) [NEON]"
|
||||
libretro_pcsx_rearmed = "PCSX-reARMed (PlayStation1)"
|
||||
libretro_nxengine = "NXEngine (Cave Story/Doukutsu Monogatari)"
|
||||
libretro_quicknes = "QuickNES (Nintendo NES)"
|
||||
libretro_tyrquake = "TyrQuake (Quake 1)"
|
||||
libretro_instancingviewer = "InstancingViewer (Images)"
|
||||
libretro_desmume = "Desmume (Nintendo DS)"
|
||||
libretro_stella = "Stella (Atari 2600)"
|
||||
libretro_scenewalker = "SceneWalker (Objects)"
|
||||
libretro_modelviewer = "ModelViewer (Objects)"
|
||||
libretro_mame078 = "MAME 2003 [0.78] (Arcade)"
|
||||
libretro_mednafen_pce_fast = "Mednafen PCE-fast"
|
||||
libretro_mednafen_pce_fast_system = "PC Engine/PC Engine CD"
|
||||
|
||||
libretro_mednafen_wswan = "Mednafen WSwan"
|
||||
libretro_mednafen_wswan_system = "Wonderswan"
|
||||
|
||||
libretro_fceumm = "FCEUmm"
|
||||
libretro_fceumm_system = "Nintendo NES"
|
||||
|
||||
libretro_mednafen_vb = "Mednafen VB"
|
||||
libretro_mednafen_vb_system = "Virtual Boy"
|
||||
|
||||
libretro_fba = "Final Burn Alpha"
|
||||
libretro_fba_system = "Arcade"
|
||||
|
||||
libretro_mednafen_ngp = "Mednafen NGP"
|
||||
libretro_mednafen_ngp_system = "Neo-Geo Pocket"
|
||||
|
||||
libretro_mednafen_psx = "Mednafen PSX"
|
||||
libretro_mednafen_psx_system = "PlayStation1"
|
||||
|
||||
libretro_gambatte = "Gambatte"
|
||||
libretro_gambatte_system = "GameBoy/GameBoy Color"
|
||||
|
||||
libretro_genesis_plus_gx = "Genesis Plus GX"
|
||||
libretro_genesis_plus_gx_system = "Sega Genesis/Sega CD/Master System"
|
||||
|
||||
libretro_picodrive = "Picodrive"
|
||||
libretro_picodrive_system = "Sega Genesis/Sega CD/Master System/32X"
|
||||
|
||||
libretro_vba_next = "VBA Next"
|
||||
libretro_vba_next_system = "GameBoy Advance"
|
||||
|
||||
libretro_prboom = "PrBoom"
|
||||
libretro_prboom_system = "DOOM"
|
||||
|
||||
libretro_snes9x = "SNES9x"
|
||||
libretro_snes9x_system = "Nintendo SNES"
|
||||
|
||||
libretro_snes9x_next = "SNES9x Next"
|
||||
libretro_snes9x_next_system = "Nintendo SNES"
|
||||
|
||||
libretro_nestopia = "Nestopia"
|
||||
libretro_nestopia_system = "Nintendo NES"
|
||||
|
||||
libretro_pcsx_rearmed-neon = "PCSX-reARMed [NEON]"
|
||||
libretro_pcsx_rearmed-neon_system = "PlayStation1"
|
||||
|
||||
libretro_pcsx_rearmed = "PCSX-reARMed"
|
||||
libretro_pcsx_rearmed_system = "PlayStation1"
|
||||
|
||||
libretro_nxengine = "NXEngine"
|
||||
libretro_nxengine_system = "Cave Story/Doukutsu Monogatari"
|
||||
|
||||
libretro_quicknes = "QuickNES"
|
||||
libretro_quicknes_system = "Nintendo NES"
|
||||
|
||||
libretro_tyrquake = "TyrQuake"
|
||||
libretro_tyrquake_system = "Quake 1"
|
||||
|
||||
libretro_instancingviewer = "InstancingViewer"
|
||||
libretro_instancingviewer_system = "Images"
|
||||
|
||||
libretro_desmume = "Desmume"
|
||||
libretro_desmume_system = "Nintendo DS"
|
||||
|
||||
libretro_stella = "Stella"
|
||||
libretro_stella_system = "Atari 2600"
|
||||
|
||||
libretro_scenewalker = "SceneWalker"
|
||||
libretro_scenewalker_system = "Objects"
|
||||
|
||||
libretro_modelviewer = "ModelViewer"
|
||||
libretro_modelviewer_system = "Objects"
|
||||
|
||||
libretro_mame078 = "MAME 2003 [0.78]"
|
||||
libretro_mame078_system = "Arcade"
|
||||
|
||||
libretro_bsnes_performance = "bsnes/higan Performance"
|
||||
libretro_bsnes_performance_system = "Nintendo SNES"
|
||||
|
||||
|
22
android/phoenix/res/layout/assets.xml
Normal file
22
android/phoenix/res/layout/assets.xml
Normal file
@ -0,0 +1,22 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/assets_textview"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:text="@string/extracting_assets_please_wait_" />
|
||||
|
||||
<ProgressBar
|
||||
android:id="@+id/assets_progress"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center" />
|
||||
|
||||
|
||||
</LinearLayout>
|
@ -10,6 +10,49 @@
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_margin="40px"
|
||||
android:text="
|
||||
r21 (August 16, 2013)\n\n
|
||||
* [VBA Next] Fixes serious regressions - most evident in Golden Sun games -\n
|
||||
battle screens etc.\n
|
||||
* [VBA Next] Add a core option to change the control button layout from (left\n
|
||||
to right) B to A to (left to right) A to B.\n
|
||||
r19 (August 15, 2013)\n\n
|
||||
* [Android] Input autodetection fixes -\n
|
||||
- DualShock3 pad controls fixed\n
|
||||
* [Android] It should now be possible to map D-pad to analog on several gamepads, such as:\n
|
||||
- Xbox 360\n
|
||||
- PlayStation3\n
|
||||
- Shield\n
|
||||
* [Android] Threaded video is now the default due to positive user feedback. Purists and accuracy\n
|
||||
people can still go for static syncing for best results - although for PCSX ReARMed threaded\n
|
||||
video is essential. With the combination of threaded video and dynamic audio rate control,\n
|
||||
most of the audio pops and sync issues should be a thing of the past now. Yay.\n
|
||||
* [Android] UI has been reorganized and made less shitty (yes, we know). Still a long way to go.\n
|
||||
The entire menu should be gamepad-controllable now at least - handy for Shield/Ouya.\n
|
||||
* [Android] Shaders that were broken on Nexus 7/4/10 etc. should now work.\n
|
||||
* [Android] Added some additional autodetection rules:\n
|
||||
- Ouya: Input overlays are disabled by default\n
|
||||
* [Android] Added high-latency audio option for crappy/old Android devices that can't handle\n
|
||||
the lower-latency audio that is the default since 0.9.9.4. This should give you the same\n
|
||||
performance as 0.9.9.3 (r17). Turn this on if you get bad sound/performance (and it's not your\n
|
||||
device simply being slow). This might also apply for some of the newer devices - perhaps \n
|
||||
OpenSL driver has not been updated/optimized there.\n
|
||||
* [Android] Added a TV mode. This will launch you straight into RGUI mode. This mode
|
||||
is identical to what you get from the Wii and PC ports of RetroArch at startup. First
|
||||
you select a core, then you select a game to go with it.
|
||||
* [SNES9x] Fixes by Alcaro to libretro port
|
||||
* [SNES9x Next] Fixes savestates from not being able to be loaded.
|
||||
* (LIBRETRO) Added bsnes/higan performance core [v0.92] (Android).\n
|
||||
- bsnes/higan performance core will run all non-coprocessor games at fullspeed on an\n
|
||||
nVidia Shield.\n
|
||||
- Co-processor games (SuperFX/SA-1/DSP/Cx4/SA1) will run between ~40fps and 55-57fps\n
|
||||
on an nVidia Shield - depending on the specific co-processor. Note - you will need\n
|
||||
BIOS files for these games - see byuu boards for information on them.\n
|
||||
* [Mednafen NGP] Fixes input issues in a number of games, such as:\n
|
||||
- Card Fighters games\n
|
||||
- Etc.\n
|
||||
* [Picodrive] Updates/32X compatibility/accuracy improvements\n
|
||||
* [NEStopia] Updated to 1.46 WIP - added ability to load NstDatabase.xml, fixes Vs. System games\n
|
||||
and Startropics 1/2\n
|
||||
r18 (August 7, 2013)\n\n
|
||||
* [Android] ANR issues fixed - Google bug (as ever).\n
|
||||
* [Android] Input autodetection expanded -\n
|
||||
|
@ -3,7 +3,7 @@
|
||||
xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:orientation="horizontal"
|
||||
android:layout_width="fill_parent"
|
||||
android:layout_height="48dp">
|
||||
android:layout_height="wrap_content">
|
||||
|
||||
<ImageView
|
||||
android:id="@+id/icon"
|
||||
@ -11,13 +11,27 @@
|
||||
android:layout_height="48dp"
|
||||
android:contentDescription="@string/file_type_icon"
|
||||
android:padding="8dp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="0dp"
|
||||
|
||||
<LinearLayout
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="center"
|
||||
android:layout_weight="0.5"
|
||||
android:textSize="18sp" />
|
||||
android:layout_gravity="center_vertical"
|
||||
android:orientation="vertical" >
|
||||
|
||||
<TextView
|
||||
android:id="@+id/name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:textSize="18sp" />
|
||||
|
||||
<TextView
|
||||
android:id="@+id/sub_name"
|
||||
android:layout_width="wrap_content"
|
||||
android:layout_height="wrap_content"
|
||||
android:layout_gravity="left"
|
||||
android:visibility="gone"
|
||||
android:textSize="12sp" />
|
||||
</LinearLayout>
|
||||
|
||||
</LinearLayout>
|
||||
|
@ -10,6 +10,20 @@
|
||||
<item>1</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="audio_latency_options">
|
||||
<item> 64ms (Low)</item>
|
||||
<item> 96ms (Medium)</item>
|
||||
<item>128ms (Medium)</item>
|
||||
<item>160ms (High)</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="audio_latency_options_values">
|
||||
<item>64</item>
|
||||
<item>96</item>
|
||||
<item>128</item>
|
||||
<item>160</item>
|
||||
</string-array>
|
||||
|
||||
<string-array name="aspect_ratios">
|
||||
<item>Full screen</item>
|
||||
<item>Auto</item>
|
||||
|
@ -9,5 +9,6 @@
|
||||
<string name="report_refreshrate">Report Refresh Rate</string>
|
||||
<string name="key_bind_detect">Detect</string>
|
||||
<string name="optimal_settings_device">Optimal device settings</string>
|
||||
<string name="extracting_assets_please_wait_">Extracting assets, please wait ...</string>
|
||||
|
||||
</resources>
|
||||
|
@ -1,12 +1,27 @@
|
||||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<PreferenceScreen xmlns:android="http://schemas.android.com/apk/res/android"
|
||||
android:title="RetroArch 0.9.9.5 - Main Menu" >
|
||||
android:title="RetroArch - Main Menu" >
|
||||
|
||||
<PreferenceScreen android:title="Select Game">
|
||||
<PreferenceScreen android:title="TV Mode">
|
||||
<intent
|
||||
android:targetClass="org.retroarch.browser.RetroTVMode"
|
||||
android:targetPackage="org.retroarch" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="Load Core">
|
||||
<intent
|
||||
android:targetClass="org.retroarch.browser.CoreSelection"
|
||||
android:targetPackage="org.retroarch" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="Load Game">
|
||||
<intent
|
||||
android:targetClass="org.retroarch.browser.ROMActivity"
|
||||
android:targetPackage="org.retroarch" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="Load Game (History)">
|
||||
<intent
|
||||
android:targetClass="org.retroarch.browser.HistorySelection"
|
||||
android:targetPackage="org.retroarch" />
|
||||
</PreferenceScreen>
|
||||
<PreferenceScreen android:title="Video Options" >
|
||||
<PreferenceCategory android:title="General" >
|
||||
<CheckBoxPreference
|
||||
@ -28,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" />
|
||||
@ -98,11 +114,19 @@
|
||||
android:summary="Enable dynamic rate control (recommended)."
|
||||
android:title="Dynamic Rate Control"
|
||||
android:dependency="audio_enable" />
|
||||
<ListPreference
|
||||
android:entries="@array/audio_latency_options"
|
||||
android:entryValues="@array/audio_latency_options_values"
|
||||
android:defaultValue="64"
|
||||
android:key="audio_latency"
|
||||
android:summary="Set the amount of desired audio latency. Your mileage may vary on the device you are using."
|
||||
android:title="Audio latency"
|
||||
android:dependency="audio_enable" />
|
||||
<CheckBoxPreference
|
||||
android:defaultValue="false"
|
||||
android:key="audio_high_latency"
|
||||
android:summary="Use (very) high latency audio. Necessary for older Android devices with poor audio drivers."
|
||||
android:title="High latency audio"
|
||||
android:defaultValue="true"
|
||||
android:key="audio_latency_auto"
|
||||
android:summary="Use automatic audio latency detection. Only available for Android 4.1 and up - your mileage may vary based on the device you are using."
|
||||
android:title="Automatic audio latency"
|
||||
android:dependency="audio_enable" />
|
||||
</PreferenceCategory>
|
||||
</PreferenceScreen>
|
||||
@ -111,10 +135,22 @@
|
||||
<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"
|
||||
@ -449,6 +485,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"
|
||||
|
@ -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);
|
||||
|
@ -4,107 +4,35 @@ import org.retroarch.R;
|
||||
|
||||
import java.io.*;
|
||||
|
||||
import android.content.*;
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.*;
|
||||
import android.media.AudioManager;
|
||||
import android.media.AudioTrack;
|
||||
import android.os.*;
|
||||
import android.preference.PreferenceManager;
|
||||
import android.provider.Settings;
|
||||
import android.widget.*;
|
||||
import android.util.Log;
|
||||
import android.view.*;
|
||||
import android.view.ContextMenu.ContextMenuInfo;
|
||||
import android.view.inputmethod.*;
|
||||
|
||||
// JELLY_BEAN_MR1 = 17
|
||||
|
||||
public class CoreSelection extends Activity implements
|
||||
AdapterView.OnItemClickListener {
|
||||
private IconAdapter<ModuleWrapper> adapter;
|
||||
static private final int ACTIVITY_LOAD_ROM = 0;
|
||||
static private String libretro_path;
|
||||
static private final String TAG = "CoreSelection";
|
||||
private ConfigFile config;
|
||||
private ConfigFile core_config;
|
||||
|
||||
private final double getDisplayRefreshRate() {
|
||||
// Android is *very* likely to screw this up.
|
||||
// It is rarely a good value to use, so make sure it's not
|
||||
// completely wrong. Some phones return refresh rates that are completely bogus
|
||||
// (like 0.3 Hz, etc), so try to be very conservative here.
|
||||
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
||||
final Display display = wm.getDefaultDisplay();
|
||||
double rate = display.getRefreshRate();
|
||||
if (rate > 61.0 || rate < 58.0)
|
||||
rate = 59.95;
|
||||
return rate;
|
||||
}
|
||||
|
||||
private final double getRefreshRate() {
|
||||
double rate = 0;
|
||||
SharedPreferences prefs = PreferenceManager
|
||||
.getDefaultSharedPreferences(getBaseContext());
|
||||
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 = getDisplayRefreshRate();
|
||||
}
|
||||
} else {
|
||||
rate = getDisplayRefreshRate();
|
||||
}
|
||||
|
||||
Log.i(TAG, "Using refresh rate: " + rate + " Hz.");
|
||||
return rate;
|
||||
}
|
||||
|
||||
private String readCPUInfo() {
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream("/proc/cpuinfo")));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
result += line + "\n";
|
||||
br.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
private boolean cpuInfoIsNeon(String info) {
|
||||
return info.contains("neon");
|
||||
}
|
||||
|
||||
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
ConfigFile core_config;
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
try {
|
||||
config = new ConfigFile(new File(getDefaultConfigPath()));
|
||||
} catch (IOException e) {
|
||||
config = new ConfigFile();
|
||||
}
|
||||
|
||||
|
||||
core_config = new ConfigFile();
|
||||
try {
|
||||
core_config.append(getAssets().open("libretro_cores.cfg"));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to load libretro_cores.cfg from assets.");
|
||||
}
|
||||
|
||||
String cpuInfo = readCPUInfo();
|
||||
boolean cpuIsNeon = cpuInfoIsNeon(cpuInfo);
|
||||
|
||||
|
||||
String cpuInfo = MainMenuActivity.readCPUInfo();
|
||||
boolean cpuIsNeon = cpuInfo.contains("neon");
|
||||
|
||||
setContentView(R.layout.line_list);
|
||||
|
||||
// Setup the list
|
||||
@ -116,15 +44,16 @@ public class CoreSelection extends Activity implements
|
||||
setTitle("Select Libretro core");
|
||||
|
||||
// Populate the list
|
||||
final String modulePath = getApplicationInfo().nativeLibraryDir;
|
||||
final String modulePath = MainMenuActivity.getInstance()
|
||||
.getApplicationInfo().nativeLibraryDir;
|
||||
final File[] libs = new File(modulePath).listFiles();
|
||||
for (final File lib : libs) {
|
||||
String libName = lib.getName();
|
||||
|
||||
|
||||
// Never append a NEON lib if we don't have NEON.
|
||||
if (libName.contains("neon") && !cpuIsNeon)
|
||||
continue;
|
||||
|
||||
|
||||
// If we have a NEON version with NEON capable CPU,
|
||||
// never append a non-NEON version.
|
||||
if (cpuIsNeon && !libName.contains("neon")) {
|
||||
@ -132,18 +61,20 @@ public class CoreSelection extends Activity implements
|
||||
for (final File lib_ : libs) {
|
||||
String otherName = lib_.getName();
|
||||
String baseName = libName.replace(".so", "");
|
||||
if (otherName.contains("neon") && otherName.startsWith(baseName)) {
|
||||
if (otherName.contains("neon")
|
||||
&& otherName.startsWith(baseName)) {
|
||||
hasNeonVersion = true;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
if (hasNeonVersion)
|
||||
continue;
|
||||
}
|
||||
|
||||
|
||||
// Allow both libretro-core.so and libretro_core.so.
|
||||
if (libName.startsWith("libretro") && !libName.startsWith("libretroarch")) {
|
||||
if (libName.startsWith("libretro")
|
||||
&& !libName.startsWith("libretroarch")) {
|
||||
try {
|
||||
adapter.add(new ModuleWrapper(this, lib, core_config));
|
||||
} catch (IOException e) {
|
||||
@ -151,235 +82,16 @@ public class CoreSelection extends Activity implements
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
|
||||
if (Build.VERSION.SDK_INT < Build.VERSION_CODES.HONEYCOMB) {
|
||||
this.registerForContextMenu(findViewById(android.R.id.content));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> aListView, View aView,
|
||||
int aPosition, long aID) {
|
||||
final ModuleWrapper item = adapter.getItem(aPosition);
|
||||
libretro_path = item.file.getAbsolutePath();
|
||||
|
||||
Intent myIntent;
|
||||
myIntent = new Intent(this, ROMActivity.class);
|
||||
startActivityForResult(myIntent, ACTIVITY_LOAD_ROM);
|
||||
}
|
||||
|
||||
private String getDefaultConfigPath() {
|
||||
String internal = System.getenv("INTERNAL_STORAGE");
|
||||
String external = System.getenv("EXTERNAL_STORAGE");
|
||||
|
||||
if (external != null) {
|
||||
String confPath = external + File.separator + "retroarch.cfg";
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
} else if (internal != null) {
|
||||
String confPath = internal + File.separator + "retroarch.cfg";
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
} else {
|
||||
String confPath = "/mnt/extsd/retroarch.cfg";
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
}
|
||||
|
||||
if (internal != null && new File(internal + File.separator + "retroarch.cfg").canWrite())
|
||||
return internal + File.separator + "retroarch.cfg";
|
||||
else if (external != null && new File(internal + File.separator + "retroarch.cfg").canWrite())
|
||||
return external + File.separator + "retroarch.cfg";
|
||||
else if ((getApplicationInfo().dataDir) != null)
|
||||
return (getApplicationInfo().dataDir) + File.separator + "retroarch.cfg";
|
||||
else // emergency fallback, all else failed
|
||||
return "/mnt/sd/retroarch.cfg";
|
||||
}
|
||||
|
||||
@TargetApi(17)
|
||||
private int getLowLatencyOptimalSamplingRate() {
|
||||
AudioManager manager = (AudioManager)getApplicationContext().getSystemService(Context.AUDIO_SERVICE);
|
||||
return Integer.parseInt(manager.getProperty(AudioManager.PROPERTY_OUTPUT_SAMPLE_RATE));
|
||||
}
|
||||
|
||||
private int getOptimalSamplingRate() {
|
||||
int ret;
|
||||
if (android.os.Build.VERSION.SDK_INT >= 17)
|
||||
ret = getLowLatencyOptimalSamplingRate();
|
||||
else
|
||||
ret = AudioTrack.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
|
||||
|
||||
Log.i(TAG, "Using sampling rate: " + ret + " Hz");
|
||||
return ret;
|
||||
}
|
||||
|
||||
private void updateConfigFile() {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
|
||||
config.setBoolean("audio_rate_control", prefs.getBoolean("audio_rate_control", true));
|
||||
config.setInt("audio_out_rate", getOptimalSamplingRate());
|
||||
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", prefs.getBoolean("video_smooth", true));
|
||||
config.setBoolean("video_allow_rotate", prefs.getBoolean("video_allow_rotate", true));
|
||||
config.setBoolean("savestate_auto_load", prefs.getBoolean("savestate_auto_load", true));
|
||||
config.setBoolean("savestate_auto_save", prefs.getBoolean("savestate_auto_save", false));
|
||||
config.setBoolean("rewind_enable", prefs.getBoolean("rewind_enable", false));
|
||||
config.setBoolean("video_vsync", prefs.getBoolean("video_vsync", true));
|
||||
config.setBoolean("input_autodetect_enable", prefs.getBoolean("input_autodetect_enable", true));
|
||||
config.setBoolean("input_debug_enable", prefs.getBoolean("input_debug_enable", false));
|
||||
config.setInt("input_back_behavior", Integer.valueOf(prefs.getString("input_back_behavior", "0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad1", Integer.valueOf(prefs.getString("input_autodetect_icade_profile_pad1", "0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad2", Integer.valueOf(prefs.getString("input_autodetect_icade_profile_pad2", "0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad3", Integer.valueOf(prefs.getString("input_autodetect_icade_profile_pad3", "0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad4", Integer.valueOf(prefs.getString("input_autodetect_icade_profile_pad4", "0")));
|
||||
|
||||
config.setDouble("video_refresh_rate", getRefreshRate());
|
||||
config.setBoolean("video_threaded", prefs.getBoolean("video_threaded", true));
|
||||
|
||||
String aspect = prefs.getString("video_aspect_ratio", "auto");
|
||||
if (aspect.equals("full")) {
|
||||
config.setBoolean("video_force_aspect", false);
|
||||
} else if (aspect.equals("auto")) {
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setBoolean("video_force_aspect_auto", true);
|
||||
config.setDouble("video_aspect_ratio", -1.0);
|
||||
} else if (aspect.equals("square")) {
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setBoolean("video_force_aspect_auto", false);
|
||||
config.setDouble("video_aspect_ratio", -1.0);
|
||||
} else {
|
||||
double aspect_ratio = Double.parseDouble(aspect);
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setDouble("video_aspect_ratio", aspect_ratio);
|
||||
}
|
||||
|
||||
config.setBoolean("video_scale_integer", prefs.getBoolean("video_scale_integer", false));
|
||||
|
||||
String shaderPath = prefs.getString("video_shader", "");
|
||||
config.setString("video_shader", shaderPath);
|
||||
config.setBoolean("video_shader_enable",
|
||||
prefs.getBoolean("video_shader_enable", false)
|
||||
&& new File(shaderPath).exists());
|
||||
|
||||
boolean useOverlay = prefs.getBoolean("input_overlay_enable", true);
|
||||
if (useOverlay) {
|
||||
String overlayPath = prefs.getString("input_overlay", (getApplicationInfo().dataDir) + "/overlays/snes-landscape.cfg");
|
||||
config.setString("input_overlay", overlayPath);
|
||||
config.setDouble("input_overlay_opacity", prefs.getFloat("input_overlay_opacity", 1.0f));
|
||||
} else {
|
||||
config.setString("input_overlay", "");
|
||||
}
|
||||
|
||||
config.setString("savefile_directory", prefs.getBoolean("savefile_directory_enable", false) ?
|
||||
prefs.getString("savefile_directory", "") : "");
|
||||
config.setString("savestate_directory", prefs.getBoolean("savestate_directory_enable", false) ?
|
||||
prefs.getString("savestate_directory", "") : "");
|
||||
config.setString("system_directory", prefs.getBoolean("system_directory_enable", false) ?
|
||||
prefs.getString("system_directory", "") : "");
|
||||
|
||||
config.setBoolean("video_font_enable", prefs.getBoolean("video_font_enable", true));
|
||||
|
||||
for (int i = 1; i <= 4; i++)
|
||||
{
|
||||
final String btns[] = {"up", "down", "left", "right", "a", "b", "x", "y", "start", "select", "l", "r", "l2", "r2", "l3", "r3" };
|
||||
for (String b : btns)
|
||||
{
|
||||
String p = "input_player" + String.valueOf(i) + "_" + b + "_btn";
|
||||
config.setInt(p, prefs.getInt(p, 0));
|
||||
}
|
||||
}
|
||||
|
||||
String confPath = getDefaultConfigPath();
|
||||
try {
|
||||
config.write(new File(confPath));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save config file to: " + confPath);
|
||||
}
|
||||
}
|
||||
|
||||
protected void onActivityResult(int requestCode, int resultCode, Intent data) {
|
||||
Intent myIntent;
|
||||
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
|
||||
updateConfigFile();
|
||||
|
||||
switch (requestCode) {
|
||||
case ACTIVITY_LOAD_ROM:
|
||||
if (data.getStringExtra("PATH") != null) {
|
||||
Toast.makeText(this,
|
||||
"Loading: [" + data.getStringExtra("PATH") + "]...",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
myIntent = new Intent(this, RetroActivity.class);
|
||||
myIntent.putExtra("ROM", data.getStringExtra("PATH"));
|
||||
myIntent.putExtra("LIBRETRO", libretro_path);
|
||||
myIntent.putExtra("CONFIGFILE", getDefaultConfigPath());
|
||||
myIntent.putExtra("IME", current_ime);
|
||||
startActivity(myIntent);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onCreateOptionsMenu(Menu aMenu) {
|
||||
super.onCreateOptionsMenu(aMenu);
|
||||
getMenuInflater().inflate(R.menu.directory_list, aMenu);
|
||||
return true;
|
||||
}
|
||||
|
||||
public void showPopup(View v) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
PopupMenuAbstract menu = new PopupMenuAbstract(this, v);
|
||||
MenuInflater inflater = menu.getMenuInflater();
|
||||
inflater.inflate(R.menu.context_menu, menu.getMenu());
|
||||
menu.setOnMenuItemClickListener(new PopupMenuAbstract.OnMenuItemClickListener()
|
||||
{
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return onContextItemSelected(item);
|
||||
}
|
||||
|
||||
});
|
||||
menu.show();
|
||||
}
|
||||
else
|
||||
{
|
||||
this.openContextMenu(findViewById(android.R.id.content));
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onCreateContextMenu(ContextMenu menu, View v,
|
||||
ContextMenuInfo menuInfo) {
|
||||
super.onCreateContextMenu(menu, v, menuInfo);
|
||||
MenuInflater inflater = getMenuInflater();
|
||||
inflater.inflate(R.menu.context_menu, menu);
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onOptionsItemSelected(MenuItem aItem) {
|
||||
switch (aItem.getItemId()) {
|
||||
case R.id.settings:
|
||||
showPopup(findViewById(R.id.settings));
|
||||
return true;
|
||||
|
||||
default:
|
||||
return super.onOptionsItemSelected(aItem);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean onContextItemSelected(MenuItem item) {
|
||||
switch (item.getItemId()) {
|
||||
case R.id.input_method_select:
|
||||
InputMethodManager imm = (InputMethodManager) getSystemService(Context.INPUT_METHOD_SERVICE);
|
||||
imm.showInputMethodPicker();
|
||||
return true;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
MainMenuActivity.getInstance().setModule(item.file.getAbsolutePath(), item.getText());
|
||||
MainMenuActivity.getInstance().updateConfigFile();
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
|
@ -43,6 +43,11 @@ class FileWrapper implements IconAdapterItem {
|
||||
else
|
||||
return file.getName();
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubText() {
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResourceId() {
|
||||
|
@ -0,0 +1,84 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import java.io.BufferedReader;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStreamReader;
|
||||
|
||||
import org.retroarch.R;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
import android.view.View;
|
||||
import android.widget.AdapterView;
|
||||
import android.widget.ListView;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class HistorySelection extends Activity implements
|
||||
AdapterView.OnItemClickListener {
|
||||
|
||||
private IconAdapter<HistoryWrapper> adapter;
|
||||
|
||||
@Override
|
||||
protected void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
setContentView(R.layout.line_list);
|
||||
|
||||
// Setup the list
|
||||
adapter = new IconAdapter<HistoryWrapper>(this, R.layout.line_list_item);
|
||||
ListView list = (ListView) findViewById(R.id.list);
|
||||
list.setAdapter(adapter);
|
||||
list.setOnItemClickListener(this);
|
||||
|
||||
setTitle("Recently played games");
|
||||
|
||||
File history = new File(getApplicationInfo().dataDir, "retroarch-history.txt");
|
||||
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream(history)));
|
||||
|
||||
for (;;) {
|
||||
String game = br.readLine();
|
||||
String core = br.readLine();
|
||||
String name = br.readLine();
|
||||
if (game == null || core == null || name == null)
|
||||
break;
|
||||
|
||||
adapter.add(new HistoryWrapper(game, core, name));
|
||||
}
|
||||
br.close();
|
||||
} catch (IOException ex) {
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void onItemClick(AdapterView<?> aListView, View aView,
|
||||
int aPosition, long aID) {
|
||||
final HistoryWrapper item = adapter.getItem(aPosition);
|
||||
final String gamePath = item.getGamePath();
|
||||
final String corePath = item.getCorePath();
|
||||
|
||||
MainMenuActivity.getInstance().setModule(corePath, item.getCoreName());
|
||||
|
||||
Intent myIntent;
|
||||
String current_ime = Settings.Secure.getString(getContentResolver(),
|
||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
|
||||
MainMenuActivity.getInstance().updateConfigFile();
|
||||
|
||||
Toast.makeText(this, "Loading: [" + gamePath + "] ...",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
myIntent = new Intent(this, RetroActivity.class);
|
||||
myIntent.putExtra("ROM", gamePath);
|
||||
myIntent.putExtra("LIBRETRO", corePath);
|
||||
myIntent.putExtra("CONFIGFILE", MainMenuActivity.getDefaultConfigPath());
|
||||
myIntent.putExtra("IME", current_ime);
|
||||
startActivity(myIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
@ -0,0 +1,63 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import java.io.File;
|
||||
|
||||
import android.graphics.drawable.Drawable;
|
||||
|
||||
public class HistoryWrapper implements IconAdapterItem {
|
||||
|
||||
private String gamePath;
|
||||
private String gamePathShort;
|
||||
private String corePath;
|
||||
private String coreName;
|
||||
|
||||
public HistoryWrapper(String gamePath, String corePath, String coreName) {
|
||||
this.gamePath = gamePath;
|
||||
this.corePath = corePath;
|
||||
this.coreName = coreName;
|
||||
|
||||
File file = new File(gamePath);
|
||||
gamePathShort = file.getName();
|
||||
try {
|
||||
gamePathShort = gamePathShort.substring(0, gamePathShort.lastIndexOf('.'));
|
||||
} catch (Exception e) {
|
||||
}
|
||||
}
|
||||
|
||||
public String getGamePath() {
|
||||
return gamePath;
|
||||
}
|
||||
|
||||
public String getCorePath() {
|
||||
return corePath;
|
||||
}
|
||||
|
||||
public String getCoreName() {
|
||||
return coreName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public boolean isEnabled() {
|
||||
return true;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getText() {
|
||||
return gamePathShort;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubText() {
|
||||
return coreName;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResourceId() {
|
||||
return 0;
|
||||
}
|
||||
|
||||
@Override
|
||||
public Drawable getIconDrawable() {
|
||||
return null;
|
||||
}
|
||||
}
|
@ -1,49 +0,0 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
import android.view.View;
|
||||
import android.widget.PopupMenu;
|
||||
|
||||
@TargetApi(Build.VERSION_CODES.HONEYCOMB)
|
||||
class HoneycombPopupMenu extends LazyPopupMenu {
|
||||
private PopupMenu instance;
|
||||
HoneycombPopupMenu.OnMenuItemClickListener listen;
|
||||
|
||||
public HoneycombPopupMenu(Context context, View anchor)
|
||||
{
|
||||
instance = new PopupMenu(context, anchor);
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMenuItemClickListener(HoneycombPopupMenu.OnMenuItemClickListener listener)
|
||||
{
|
||||
listen = listener;
|
||||
instance.setOnMenuItemClickListener(new PopupMenu.OnMenuItemClickListener() {
|
||||
@Override
|
||||
public boolean onMenuItemClick(MenuItem item) {
|
||||
return listen.onMenuItemClick(item);
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
@Override
|
||||
public Menu getMenu() {
|
||||
return instance.getMenu();
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
return instance.getMenuInflater();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
instance.show();
|
||||
}
|
||||
}
|
16
android/phoenix/src/org/retroarch/browser/IMEActivity.java
Normal file
16
android/phoenix/src/org/retroarch/browser/IMEActivity.java
Normal 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();
|
||||
}
|
||||
}
|
@ -10,11 +10,9 @@ import android.widget.*;
|
||||
|
||||
interface IconAdapterItem {
|
||||
public abstract boolean isEnabled();
|
||||
|
||||
public abstract String getText();
|
||||
|
||||
public abstract String getSubText();
|
||||
public abstract int getIconResourceId();
|
||||
|
||||
public abstract Drawable getIconDrawable();
|
||||
}
|
||||
|
||||
@ -23,7 +21,6 @@ class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
|
||||
|
||||
public IconAdapter(Activity aContext, int aLayout) {
|
||||
super(aContext, aLayout);
|
||||
|
||||
layout = aLayout;
|
||||
}
|
||||
|
||||
@ -45,6 +42,16 @@ class IconAdapter<T extends IconAdapterItem> extends ArrayAdapter<T> {
|
||||
textView.setText(item.getText());
|
||||
textView.setEnabled(enabled);
|
||||
}
|
||||
|
||||
textView = (TextView) aConvertView.findViewById(R.id.sub_name);
|
||||
if (null != textView) {
|
||||
String subText = item.getSubText();
|
||||
if (null != subText) {
|
||||
textView.setVisibility(View.VISIBLE);
|
||||
textView.setEnabled(item.isEnabled());
|
||||
textView.setText(subText);
|
||||
}
|
||||
}
|
||||
|
||||
ImageView imageView = (ImageView) aConvertView.findViewById(R.id.icon);
|
||||
if (null != imageView) {
|
||||
|
@ -1,15 +0,0 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.MenuItem;
|
||||
|
||||
abstract class LazyPopupMenu {
|
||||
public abstract Menu getMenu();
|
||||
public abstract MenuInflater getMenuInflater();
|
||||
public abstract void setOnMenuItemClickListener(LazyPopupMenu.OnMenuItemClickListener listener);
|
||||
public abstract void show();
|
||||
public interface OnMenuItemClickListener {
|
||||
public abstract boolean onMenuItemClick(MenuItem item);
|
||||
}
|
||||
}
|
@ -1,71 +1,497 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import java.io.BufferedOutputStream;
|
||||
import java.io.DataInputStream;
|
||||
import java.io.DataOutputStream;
|
||||
import java.io.File;
|
||||
import java.io.FileInputStream;
|
||||
import java.io.FileOutputStream;
|
||||
import java.io.IOException;
|
||||
import java.io.InputStream;
|
||||
import java.io.*;
|
||||
|
||||
import org.retroarch.R;
|
||||
|
||||
import android.annotation.TargetApi;
|
||||
import android.app.AlertDialog;
|
||||
import android.app.Dialog;
|
||||
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;
|
||||
import android.util.Log;
|
||||
import android.view.Display;
|
||||
import android.view.WindowManager;
|
||||
import android.widget.Toast;
|
||||
|
||||
public class MainMenuActivity extends PreferenceActivity {
|
||||
private static MainMenuActivity instance = null;
|
||||
static private final int ACTIVITY_LOAD_ROM = 0;
|
||||
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);
|
||||
addPreferencesFromResource(R.xml.prefs);
|
||||
PreferenceManager.setDefaultValues(this, R.xml.prefs, false);
|
||||
instance = this;
|
||||
|
||||
SharedPreferences prefs = getPreferences();
|
||||
|
||||
libretro_path = prefs.getString("libretro_path", getApplicationInfo().nativeLibraryDir);
|
||||
libretro_name = prefs.getString("libretro_name", "No core");
|
||||
|
||||
refreshPreferenceScreen();
|
||||
|
||||
this.setVolumeControlStream(AudioManager.STREAM_MUSIC);
|
||||
|
||||
// Extracting assets appears to take considerable amount of time, so
|
||||
// move extraction to a thread.
|
||||
Thread assetThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
extractAssets();
|
||||
}
|
||||
});
|
||||
assetThread.start();
|
||||
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
|
||||
|
||||
|
||||
extractAssets();
|
||||
|
||||
if (!prefs.getBoolean("first_time_refreshrate_calculate", false)) {
|
||||
prefs.edit().putBoolean("first_time_refreshrate_calculate", true).commit();
|
||||
|
||||
if (!detectDevice(false))
|
||||
{
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.setTitle("Welcome to RetroArch")
|
||||
.setMessage("This is your first time starting up RetroArch. RetroArch will now be preconfigured for the best possible gameplay experience. Please be aware that it might take some time until all shader and overlay assets are extracted.\n\nNOTE: Advanced users who want to finetune for the best possible audio/video experience should use static synchronization and turn off threaded video. Be aware that this is hard to configure right and might result in unpleasant audio crackles when it has been configured wrong.\n\nThreaded video should work fine on most devices, but applies some adaptive video jittering to achieve this. ")
|
||||
.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();
|
||||
}
|
||||
});
|
||||
alert.show();
|
||||
prefs.edit().putBoolean("first_time_refreshrate_calculate", true)
|
||||
.commit();
|
||||
|
||||
if (!detectDevice(false)) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.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", null);
|
||||
alert.show();
|
||||
}
|
||||
}
|
||||
|
||||
Intent startedByIntent = getIntent();
|
||||
if (null != startedByIntent.getStringExtra("ROM")
|
||||
&& null != startedByIntent.getStringExtra("LIBRETRO")) {
|
||||
if (null == savedInstanceState
|
||||
|| !savedInstanceState.getBoolean("romexec"))
|
||||
loadRomExternal(startedByIntent.getStringExtra("ROM"),
|
||||
startedByIntent.getStringExtra("LIBRETRO"));
|
||||
else
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
public static MainMenuActivity getInstance() {
|
||||
return instance;
|
||||
}
|
||||
|
||||
private final double getDisplayRefreshRate() {
|
||||
// Android is *very* likely to screw this up.
|
||||
// It is rarely a good value to use, so make sure it's not
|
||||
// completely wrong. Some phones return refresh rates that are
|
||||
// completely bogus
|
||||
// (like 0.3 Hz, etc), so try to be very conservative here.
|
||||
final WindowManager wm = (WindowManager) getSystemService(Context.WINDOW_SERVICE);
|
||||
final Display display = wm.getDefaultDisplay();
|
||||
double rate = display.getRefreshRate();
|
||||
if (rate > 61.0 || rate < 58.0)
|
||||
rate = 59.95;
|
||||
return rate;
|
||||
}
|
||||
|
||||
public static final double getRefreshRate() {
|
||||
double rate = 0;
|
||||
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 = getInstance().getDisplayRefreshRate();
|
||||
}
|
||||
} else {
|
||||
rate = getInstance().getDisplayRefreshRate();
|
||||
}
|
||||
|
||||
Log.i(TAG, "Using refresh rate: " + rate + " Hz.");
|
||||
return rate;
|
||||
}
|
||||
|
||||
public static String readCPUInfo() {
|
||||
String result = "";
|
||||
|
||||
try {
|
||||
BufferedReader br = new BufferedReader(new InputStreamReader(
|
||||
new FileInputStream("/proc/cpuinfo")));
|
||||
|
||||
String line;
|
||||
while ((line = br.readLine()) != null)
|
||||
result += line + "\n";
|
||||
br.close();
|
||||
} catch (IOException ex) {
|
||||
ex.printStackTrace();
|
||||
}
|
||||
return result;
|
||||
}
|
||||
|
||||
@TargetApi(17)
|
||||
public static int getLowLatencyOptimalSamplingRate() {
|
||||
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;
|
||||
if (android.os.Build.VERSION.SDK_INT >= 17)
|
||||
ret = getLowLatencyOptimalSamplingRate();
|
||||
else
|
||||
ret = AudioTrack
|
||||
.getNativeOutputSampleRate(AudioManager.STREAM_MUSIC);
|
||||
|
||||
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");
|
||||
|
||||
String append_path;
|
||||
if (getInstance().usePerCoreConfig()) {
|
||||
String sanitized_name = sanitizeLibretroPath(libretro_path);
|
||||
append_path = File.separator + sanitized_name + ".cfg";
|
||||
} else {
|
||||
append_path = File.separator + "retroarch.cfg";
|
||||
}
|
||||
|
||||
if (external != null) {
|
||||
String confPath = external + append_path;
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
} else if (internal != null) {
|
||||
String confPath = internal + append_path;
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
} else {
|
||||
String confPath = "/mnt/extsd" + append_path;
|
||||
if (new File(confPath).exists())
|
||||
return confPath;
|
||||
}
|
||||
|
||||
if (internal != null && new File(internal + append_path).canWrite())
|
||||
return internal + append_path;
|
||||
else if (external != null
|
||||
&& new File(internal + append_path).canWrite())
|
||||
return external + append_path;
|
||||
else if ((getInstance().getApplicationInfo().dataDir) != null)
|
||||
return (getInstance().getApplicationInfo().dataDir)
|
||||
+ append_path;
|
||||
else
|
||||
// emergency fallback, all else failed
|
||||
return "/mnt/sd" + append_path;
|
||||
}
|
||||
|
||||
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(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 = getPreferences();
|
||||
|
||||
config.setString("libretro_path", libretro_path);
|
||||
|
||||
config.setString("rgui_browser_directory",
|
||||
prefs.getString("rgui_browser_directory", ""));
|
||||
config.setBoolean("audio_rate_control",
|
||||
prefs.getBoolean("audio_rate_control", true));
|
||||
|
||||
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 &&
|
||||
prefs.getBoolean("audio_latency_auto", true) == true) {
|
||||
int buffersize = getLowLatencyBufferSize();
|
||||
|
||||
boolean lowLatency = hasLowLatencyAudio();
|
||||
Log.i(TAG, "Audio is low latency: " + (lowLatency ? "yes" : "no"));
|
||||
|
||||
config.setInt("audio_latency", 64);
|
||||
if (lowLatency) {
|
||||
config.setInt("audio_block_frames", buffersize);
|
||||
} else {
|
||||
config.setInt("audio_block_frames", 0);
|
||||
}
|
||||
} else {
|
||||
String latency_audio = prefs.getString("audio_latency", "64");
|
||||
config.setInt("audio_latency", Integer.parseInt(latency_audio));
|
||||
}
|
||||
|
||||
config.setBoolean("audio_enable",
|
||||
prefs.getBoolean("audio_enable", true));
|
||||
config.setBoolean("video_smooth",
|
||||
prefs.getBoolean("video_smooth", true));
|
||||
config.setBoolean("video_allow_rotate",
|
||||
prefs.getBoolean("video_allow_rotate", true));
|
||||
config.setBoolean("savestate_auto_load",
|
||||
prefs.getBoolean("savestate_auto_load", true));
|
||||
config.setBoolean("savestate_auto_save",
|
||||
prefs.getBoolean("savestate_auto_save", false));
|
||||
config.setBoolean("rewind_enable",
|
||||
prefs.getBoolean("rewind_enable", false));
|
||||
config.setBoolean("video_vsync", prefs.getBoolean("video_vsync", true));
|
||||
config.setBoolean("input_autodetect_enable",
|
||||
prefs.getBoolean("input_autodetect_enable", true));
|
||||
config.setBoolean("input_debug_enable",
|
||||
prefs.getBoolean("input_debug_enable", false));
|
||||
config.setInt("input_back_behavior",
|
||||
Integer.valueOf(prefs.getString("input_back_behavior", "0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad1", Integer
|
||||
.valueOf(prefs.getString("input_autodetect_icade_profile_pad1",
|
||||
"0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad2", Integer
|
||||
.valueOf(prefs.getString("input_autodetect_icade_profile_pad2",
|
||||
"0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad3", Integer
|
||||
.valueOf(prefs.getString("input_autodetect_icade_profile_pad3",
|
||||
"0")));
|
||||
config.setInt("input_autodetect_icade_profile_pad4", Integer
|
||||
.valueOf(prefs.getString("input_autodetect_icade_profile_pad4",
|
||||
"0")));
|
||||
|
||||
config.setDouble("video_refresh_rate",
|
||||
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);
|
||||
} else if (aspect.equals("auto")) {
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setBoolean("video_force_aspect_auto", true);
|
||||
config.setDouble("video_aspect_ratio", -1.0);
|
||||
} else if (aspect.equals("square")) {
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setBoolean("video_force_aspect_auto", false);
|
||||
config.setDouble("video_aspect_ratio", -1.0);
|
||||
} else {
|
||||
double aspect_ratio = Double.parseDouble(aspect);
|
||||
config.setBoolean("video_force_aspect", true);
|
||||
config.setDouble("video_aspect_ratio", aspect_ratio);
|
||||
}
|
||||
|
||||
config.setBoolean("video_scale_integer",
|
||||
prefs.getBoolean("video_scale_integer", false));
|
||||
|
||||
String shaderPath = prefs.getString("video_shader", "");
|
||||
config.setString("video_shader", shaderPath);
|
||||
config.setBoolean("video_shader_enable",
|
||||
prefs.getBoolean("video_shader_enable", false)
|
||||
&& 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", (getInstance()
|
||||
.getApplicationInfo().dataDir)
|
||||
+ "/overlays/snes-landscape.cfg");
|
||||
config.setString("input_overlay", overlayPath);
|
||||
config.setDouble("input_overlay_opacity",
|
||||
prefs.getFloat("input_overlay_opacity", 1.0f));
|
||||
} else {
|
||||
config.setString("input_overlay", "");
|
||||
}
|
||||
config.setString(
|
||||
"savefile_directory",
|
||||
prefs.getBoolean("savefile_directory_enable", false) ? prefs
|
||||
.getString("savefile_directory", "") : "");
|
||||
config.setString(
|
||||
"savestate_directory",
|
||||
prefs.getBoolean("savestate_directory_enable", false) ? prefs
|
||||
.getString("savestate_directory", "") : "");
|
||||
config.setString(
|
||||
"system_directory",
|
||||
prefs.getBoolean("system_directory_enable", false) ? prefs
|
||||
.getString("system_directory", "") : "");
|
||||
|
||||
config.setBoolean("video_font_enable",
|
||||
prefs.getBoolean("video_font_enable", true));
|
||||
|
||||
config.setString("game_history_path", getInstance()
|
||||
.getApplicationInfo().dataDir + "/retroarch-history.txt");
|
||||
|
||||
for (int i = 1; i <= 4; i++) {
|
||||
final String btns[] = { "up", "down", "left", "right", "a", "b",
|
||||
"x", "y", "start", "select", "l", "r", "l2", "r2", "l3",
|
||||
"r3" };
|
||||
for (String b : btns) {
|
||||
String p = "input_player" + String.valueOf(i) + "_" + b
|
||||
+ "_btn";
|
||||
config.setInt(p, prefs.getInt(p, 0));
|
||||
}
|
||||
}
|
||||
|
||||
try {
|
||||
config.write(new File(path));
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to save config file to: " + path);
|
||||
}
|
||||
}
|
||||
|
||||
private byte[] loadAsset(String asset) throws IOException {
|
||||
String path = asset;
|
||||
InputStream stream = getAssets().open(path);
|
||||
@ -74,22 +500,24 @@ public class MainMenuActivity extends PreferenceActivity {
|
||||
stream.read(buf, 0, len);
|
||||
return buf;
|
||||
}
|
||||
|
||||
private void extractAssets(AssetManager manager, String dataDir, String relativePath, int level) throws IOException {
|
||||
|
||||
private void extractAssets(AssetManager manager, String dataDir,
|
||||
String relativePath, int level) throws IOException {
|
||||
final String[] paths = manager.list(relativePath);
|
||||
if (paths != null && paths.length > 0) { // Directory
|
||||
//Log.d(TAG, "Extracting assets directory: " + relativePath);
|
||||
// Log.d(TAG, "Extracting assets directory: " + relativePath);
|
||||
for (final String path : paths)
|
||||
extractAssets(manager, dataDir, relativePath + (level > 0 ? File.separator : "") + path, level + 1);
|
||||
extractAssets(manager, dataDir, relativePath
|
||||
+ (level > 0 ? File.separator : "") + path, level + 1);
|
||||
} else { // File, extract.
|
||||
//Log.d(TAG, "Extracting assets file: " + relativePath);
|
||||
|
||||
// Log.d(TAG, "Extracting assets file: " + relativePath);
|
||||
|
||||
String parentPath = new File(relativePath).getParent();
|
||||
if (parentPath != null) {
|
||||
File parentFile = new File(dataDir, parentPath);
|
||||
parentFile.mkdirs(); // Doesn't throw.
|
||||
}
|
||||
|
||||
|
||||
byte[] asset = loadAsset(relativePath);
|
||||
BufferedOutputStream writer = new BufferedOutputStream(
|
||||
new FileOutputStream(new File(dataDir, relativePath)));
|
||||
@ -99,130 +527,337 @@ public class MainMenuActivity extends PreferenceActivity {
|
||||
writer.close();
|
||||
}
|
||||
}
|
||||
|
||||
private void extractAssets() {
|
||||
|
||||
private int getVersionCode() {
|
||||
int version = 0;
|
||||
try {
|
||||
version = getPackageManager().getPackageInfo(getPackageName(), 0).versionCode;
|
||||
} catch(NameNotFoundException e) {
|
||||
// weird exception, shouldn't happen
|
||||
} catch (NameNotFoundException e) {
|
||||
}
|
||||
|
||||
|
||||
return version;
|
||||
}
|
||||
|
||||
private boolean areAssetsExtracted() {
|
||||
int version = getVersionCode();
|
||||
|
||||
try {
|
||||
AssetManager assets = getAssets();
|
||||
String dataDir = getApplicationInfo().dataDir;
|
||||
File cacheVersion = new File(dataDir, ".cacheversion");
|
||||
if (cacheVersion != null && cacheVersion.isFile() && cacheVersion.canRead() && cacheVersion.canWrite())
|
||||
{
|
||||
DataInputStream cacheStream = new DataInputStream(new FileInputStream(cacheVersion));
|
||||
if (cacheVersion != null && cacheVersion.isFile()
|
||||
&& cacheVersion.canRead() && cacheVersion.canWrite()) {
|
||||
DataInputStream cacheStream = new DataInputStream(
|
||||
new FileInputStream(cacheVersion));
|
||||
|
||||
int currentCacheVersion = 0;
|
||||
try {
|
||||
currentCacheVersion = cacheStream.readInt();
|
||||
} catch (IOException e) {}
|
||||
cacheStream.close();
|
||||
|
||||
if (currentCacheVersion == version)
|
||||
{
|
||||
} catch (IOException e) {
|
||||
}
|
||||
cacheStream.close();
|
||||
|
||||
if (currentCacheVersion == version) {
|
||||
Log.i("ASSETS", "Assets already extracted, skipping...");
|
||||
return;
|
||||
return true;
|
||||
}
|
||||
}
|
||||
|
||||
//extractAssets(assets, cacheDir, "", 0);
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to extract assets to cache.");
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
private void extractAssetsThread() {
|
||||
try {
|
||||
AssetManager assets = getAssets();
|
||||
String dataDir = getApplicationInfo().dataDir;
|
||||
File cacheVersion = new File(dataDir, ".cacheversion");
|
||||
|
||||
// extractAssets(assets, cacheDir, "", 0);
|
||||
Log.i("ASSETS", "Extracting shader assets now ...");
|
||||
try {
|
||||
extractAssets(assets, dataDir, "shaders_glsl", 1);
|
||||
} catch (IOException e) {
|
||||
Log.i("ASSETS", "Failed to extract shaders ...");
|
||||
}
|
||||
|
||||
|
||||
Log.i("ASSETS", "Extracting overlay assets now ...");
|
||||
try {
|
||||
extractAssets(assets, dataDir, "overlays", 1);
|
||||
} catch (IOException e) {
|
||||
Log.i("ASSETS", "Failed to extract overlays ...");
|
||||
}
|
||||
|
||||
DataOutputStream outputCacheVersion = new DataOutputStream(new FileOutputStream(cacheVersion, false));
|
||||
outputCacheVersion.writeInt(version);
|
||||
|
||||
DataOutputStream outputCacheVersion = new DataOutputStream(
|
||||
new FileOutputStream(cacheVersion, false));
|
||||
outputCacheVersion.writeInt(getVersionCode());
|
||||
outputCacheVersion.close();
|
||||
} catch (IOException e) {
|
||||
Log.e(TAG, "Failed to extract assets to cache.");
|
||||
Log.e(TAG, "Failed to extract assets to cache.");
|
||||
}
|
||||
}
|
||||
|
||||
private void extractAssets() {
|
||||
if (areAssetsExtracted())
|
||||
return;
|
||||
|
||||
final Dialog dialog = new Dialog(this);
|
||||
final Handler handler = new Handler();
|
||||
dialog.setContentView(R.layout.assets);
|
||||
dialog.setCancelable(false);
|
||||
dialog.setTitle("Asset extraction");
|
||||
|
||||
// Java is fun :)
|
||||
Thread assetsThread = new Thread(new Runnable() {
|
||||
public void run() {
|
||||
extractAssetsThread();
|
||||
handler.post(new Runnable() {
|
||||
public void run() {
|
||||
dialog.dismiss();
|
||||
}
|
||||
});
|
||||
}
|
||||
});
|
||||
assetsThread.start();
|
||||
|
||||
dialog.show();
|
||||
}
|
||||
|
||||
boolean detectDevice(boolean show_dialog)
|
||||
{
|
||||
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;
|
||||
|
||||
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) {
|
||||
setTitle("RetroArch : " + core_name);
|
||||
}
|
||||
|
||||
boolean detectDevice(boolean show_dialog) {
|
||||
boolean retval = false;
|
||||
|
||||
|
||||
boolean mentionPlayStore = !android.os.Build.MODEL
|
||||
.equals("OUYA Console");
|
||||
final String message = "The ideal configuration options for your device will now be preconfigured.\n\nNOTE: For optimal performance, turn off Google Account sync, "
|
||||
+ (mentionPlayStore ? "Google Play Store auto-updates, " : "")
|
||||
+ "GPS and Wi-Fi in your Android settings menu.";
|
||||
|
||||
Log.i("Device MODEL", android.os.Build.MODEL);
|
||||
if (android.os.Build.MODEL.equals("SHIELD"))
|
||||
{
|
||||
if (android.os.Build.MODEL.equals("SHIELD")) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.setTitle("NVidia Shield detected")
|
||||
.setMessage("The ideal configuration options for your device will now be preconfigured.\nNOTE: For optimal performance, turn off Google Account sync, Google Play Store auto-updates, GPS and Wifi in your Android settings menu.")
|
||||
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
|
||||
SharedPreferences.Editor edit = prefs.edit();
|
||||
edit.putString("video_refresh_rate", Double.valueOf(60.00d).toString());
|
||||
edit.putBoolean("input_overlay_enable", false);
|
||||
edit.putBoolean("input_autodetect_enable", true);
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
.setTitle("NVidia Shield 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.putString("video_refresh_rate", Double
|
||||
.valueOf(60.00d).toString());
|
||||
edit.putBoolean("input_overlay_enable",
|
||||
false);
|
||||
edit.putBoolean("input_autodetect_enable",
|
||||
true);
|
||||
edit.putString("audio_latency", "64");
|
||||
edit.putBoolean("audio_latency_auto", true);
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
alert.show();
|
||||
retval = true;
|
||||
} else if (android.os.Build.MODEL.equals("GAMEMID_BT")) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.setTitle("GameMID 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.putString("audio_latency", "160");
|
||||
edit.putBoolean("audio_latency_auto", false);
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
alert.show();
|
||||
retval = true;
|
||||
} else if (android.os.Build.MODEL.equals("OUYA Console")) {
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.setTitle("OUYA 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.putString("audio_latency", "64");
|
||||
edit.putBoolean("audio_latency_auto", true);
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
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("video_threaded", false);
|
||||
edit.putBoolean("input_overlay_enable",
|
||||
false);
|
||||
edit.putBoolean("input_autodetect_enable",
|
||||
true);
|
||||
edit.putString("video_refresh_rate", Double
|
||||
.valueOf(59.19132938771038).toString());
|
||||
edit.putString("audio_latency", "128");
|
||||
edit.putBoolean("audio_latency_auto", false);
|
||||
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")
|
||||
.setMessage(message)
|
||||
.setPositiveButton("OK",
|
||||
new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog,
|
||||
int which) {
|
||||
SharedPreferences prefs = getPreferences();
|
||||
SharedPreferences.Editor edit = prefs
|
||||
.edit();
|
||||
edit.putString("video_refresh_rate", Double
|
||||
.valueOf(59.65).toString());
|
||||
edit.putString("audio_latency", "64");
|
||||
edit.putBoolean("audio_latency_auto", false);
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
alert.show();
|
||||
retval = true;
|
||||
}
|
||||
else if (android.os.Build.MODEL.equals( "OUYA Console"))
|
||||
{
|
||||
AlertDialog.Builder alert = new AlertDialog.Builder(this)
|
||||
.setTitle("OUYA detected")
|
||||
.setMessage("The ideal configuration options for your device will now be preconfigured.\nNOTE: For optimal performance, turn off Google Account sync, GPS and Wifi in your Android settings menu.")
|
||||
.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("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")
|
||||
.setMessage("The ideal configuration options for your device will now be preconfigured.\nNOTE: For optimal performance, turn off Google Account sync, Google Play Store auto-updates, GPS and Wifi in your Android settings menu.")
|
||||
.setPositiveButton("OK", new DialogInterface.OnClickListener() {
|
||||
@Override
|
||||
public void onClick(DialogInterface dialog, int which) {
|
||||
SharedPreferences prefs = PreferenceManager.getDefaultSharedPreferences(getBaseContext());
|
||||
SharedPreferences.Editor edit = prefs.edit();
|
||||
edit.putString("video_refresh_rate", Double.valueOf(59.65).toString());
|
||||
edit.commit();
|
||||
}
|
||||
});
|
||||
alert.show();
|
||||
retval = true;
|
||||
}
|
||||
|
||||
|
||||
if (show_dialog) {
|
||||
Toast.makeText(this,
|
||||
"Device either not detected in list or doesn't have any optimal settings in our database.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
Toast.makeText(
|
||||
this,
|
||||
"Device either not detected in list or doesn't have any optimal settings in our database.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
|
||||
refreshPreferenceScreen();
|
||||
|
||||
return retval;
|
||||
}
|
||||
|
||||
|
||||
@Override
|
||||
protected void onStart() {
|
||||
super.onStart();
|
||||
}
|
||||
|
||||
@Override
|
||||
public void startActivity(Intent intent) {
|
||||
if (intent.getComponent().getClassName()
|
||||
.equals("org.retroarch.browser.ROMActivity")) {
|
||||
if (new File(libretro_path).isDirectory() == false) {
|
||||
super.startActivityForResult(intent, ACTIVITY_LOAD_ROM);
|
||||
} else {
|
||||
Toast.makeText(this,
|
||||
"Go to 'Load Core' and select a core first.",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
}
|
||||
} else {
|
||||
super.startActivity(intent);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onActivityResult(int reqCode, int resCode, Intent data) {
|
||||
switch (reqCode) {
|
||||
case ACTIVITY_LOAD_ROM: {
|
||||
if (data.getStringExtra("PATH") != null) {
|
||||
updateConfigFile();
|
||||
Intent myIntent;
|
||||
String current_ime = Settings.Secure.getString(
|
||||
getContentResolver(),
|
||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
Toast.makeText(this,
|
||||
"Loading: [" + data.getStringExtra("PATH") + "]...",
|
||||
Toast.LENGTH_SHORT).show();
|
||||
myIntent = new Intent(this, RetroActivity.class);
|
||||
myIntent.putExtra("ROM", data.getStringExtra("PATH"));
|
||||
myIntent.putExtra("LIBRETRO", libretro_path);
|
||||
myIntent.putExtra("CONFIGFILE",
|
||||
getDefaultConfigPath());
|
||||
myIntent.putExtra("IME", current_ime);
|
||||
startActivity(myIntent);
|
||||
}
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
protected void onSaveInstanceState(Bundle data) {
|
||||
super.onSaveInstanceState(data);
|
||||
data.putBoolean("romexec", true);
|
||||
}
|
||||
|
||||
private void loadRomExternal(String rom, String core) {
|
||||
updateConfigFile();
|
||||
Intent myIntent = new Intent(this, RetroActivity.class);
|
||||
String current_ime = Settings.Secure.getString(getContentResolver(),
|
||||
Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
Toast.makeText(this, "Loading: [" + rom + "]...", Toast.LENGTH_SHORT)
|
||||
.show();
|
||||
myIntent.putExtra("ROM", rom);
|
||||
myIntent.putExtra("LIBRETRO", core);
|
||||
myIntent.putExtra("CONFIGFILE", getDefaultConfigPath());
|
||||
myIntent.putExtra("IME", current_ime);
|
||||
startActivity(myIntent);
|
||||
}
|
||||
}
|
||||
|
@ -28,6 +28,15 @@ class ModuleWrapper implements IconAdapterItem {
|
||||
} else
|
||||
return stripped;
|
||||
}
|
||||
|
||||
@Override
|
||||
public String getSubText() {
|
||||
String stripped = file.getName().replace(".so", "") + "_system";
|
||||
if (config.keyExists(stripped)) {
|
||||
return config.getString(stripped);
|
||||
} else
|
||||
return null;
|
||||
}
|
||||
|
||||
@Override
|
||||
public int getIconResourceId() {
|
||||
|
@ -1,60 +0,0 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import android.content.Context;
|
||||
import android.os.Build;
|
||||
import android.view.Menu;
|
||||
import android.view.MenuInflater;
|
||||
import android.view.View;
|
||||
|
||||
class PopupMenuAbstract extends LazyPopupMenu
|
||||
{
|
||||
private LazyPopupMenu lazy;
|
||||
|
||||
public PopupMenuAbstract(Context context, View anchor)
|
||||
{
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
lazy = new HoneycombPopupMenu(context, anchor);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public Menu getMenu() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
return lazy.getMenu();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public MenuInflater getMenuInflater() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
return lazy.getMenuInflater();
|
||||
}
|
||||
else
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void setOnMenuItemClickListener(PopupMenuAbstract.OnMenuItemClickListener listener) {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
lazy.setOnMenuItemClickListener(listener);
|
||||
}
|
||||
}
|
||||
|
||||
@Override
|
||||
public void show() {
|
||||
if (Build.VERSION.SDK_INT >= Build.VERSION_CODES.HONEYCOMB)
|
||||
{
|
||||
lazy.show();
|
||||
}
|
||||
}
|
||||
}
|
@ -4,14 +4,13 @@ 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());
|
||||
String startPath = prefs.getString("phoenix_rom_dir", "");
|
||||
SharedPreferences prefs = MainMenuActivity.getPreferences();
|
||||
String startPath = prefs.getString("rgui_browser_directory", "");
|
||||
if (!startPath.isEmpty() && new File(startPath).exists())
|
||||
super.setStartDirectory(startPath);
|
||||
|
||||
|
@ -5,7 +5,7 @@ import android.os.Bundle;
|
||||
public class ROMDirActivity extends DirectoryActivity {
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.setPathSettingKey("phoenix_rom_dir");
|
||||
super.setPathSettingKey("rgui_browser_directory");
|
||||
super.setIsDirectoryTarget(true);
|
||||
super.onCreate(savedInstanceState);
|
||||
}
|
||||
|
@ -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();
|
||||
|
@ -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();
|
||||
}
|
||||
}
|
||||
|
25
android/phoenix/src/org/retroarch/browser/RetroTVMode.java
Normal file
25
android/phoenix/src/org/retroarch/browser/RetroTVMode.java
Normal file
@ -0,0 +1,25 @@
|
||||
package org.retroarch.browser;
|
||||
|
||||
import android.app.Activity;
|
||||
import android.content.Intent;
|
||||
import android.os.Bundle;
|
||||
import android.provider.Settings;
|
||||
|
||||
public class RetroTVMode extends Activity {
|
||||
|
||||
@Override
|
||||
public void onCreate(Bundle savedInstanceState) {
|
||||
super.onCreate(savedInstanceState);
|
||||
|
||||
MainMenuActivity.getInstance().updateConfigFile();
|
||||
|
||||
Intent myIntent = new Intent(this, RetroActivity.class);
|
||||
String current_ime = Settings.Secure.getString(getContentResolver(), Settings.Secure.DEFAULT_INPUT_METHOD);
|
||||
myIntent.putExtra("CONFIGFILE", MainMenuActivity.getDefaultConfigPath());
|
||||
myIntent.putExtra("IME", current_ime);
|
||||
startActivity(myIntent);
|
||||
finish();
|
||||
}
|
||||
}
|
||||
|
||||
|
384
apple/OSX/en.lproj/InputBinder.xib
Normal file
384
apple/OSX/en.lproj/InputBinder.xib
Normal 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>
|
@ -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
@ -14,27 +14,45 @@
|
||||
*/
|
||||
|
||||
#include <IOKit/hid/IOHIDManager.h>
|
||||
#include "../RetroArch/apple_input.h"
|
||||
#include "apple/common/apple_input.h"
|
||||
#include "apple/common/hidpad/hidpad.h"
|
||||
|
||||
// NOTE: I pieced this together through trial and error, any corrections are welcome
|
||||
struct hidpad_connection
|
||||
{
|
||||
uint32_t slot;
|
||||
|
||||
struct hidpad_interface* interface;
|
||||
void* hidpad;
|
||||
|
||||
IOHIDDeviceRef device;
|
||||
|
||||
uint8_t data[2048];
|
||||
};
|
||||
|
||||
static IOHIDManagerRef g_hid_manager;
|
||||
static struct hidpad_connection g_connected_pads[MAX_PADS];
|
||||
|
||||
static void hid_input_callback(void* inContext, IOReturn inResult, void* inSender, IOHIDValueRef inIOHIDValueRef)
|
||||
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size)
|
||||
{
|
||||
IOHIDElementRef element = IOHIDValueGetElement(inIOHIDValueRef);
|
||||
IOHIDDeviceRef device = IOHIDElementGetDevice(element);
|
||||
IOHIDDeviceSetReport(connection->device, kIOHIDReportTypeOutput, 0x01, data, size);
|
||||
}
|
||||
|
||||
// NOTE: I pieced this together through trial and error, any corrections are welcome
|
||||
static void hid_device_input_callback(void* context, IOReturn result, void* sender, IOHIDValueRef value)
|
||||
{
|
||||
struct hidpad_connection* connection = context;
|
||||
|
||||
IOHIDElementRef element = IOHIDValueGetElement(value);
|
||||
uint32_t type = IOHIDElementGetType(element);
|
||||
uint32_t page = IOHIDElementGetUsagePage(element);
|
||||
uint32_t use = IOHIDElementGetUsage(element);
|
||||
|
||||
// Mouse handler
|
||||
if (IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse))
|
||||
if (!connection)
|
||||
{
|
||||
if (type == kIOHIDElementTypeInput_Button && page == kHIDPage_Button)
|
||||
{
|
||||
CFIndex state = IOHIDValueGetIntegerValue(inIOHIDValueRef);
|
||||
CFIndex state = IOHIDValueGetIntegerValue(value);
|
||||
|
||||
if (state) g_current_input_data.mouse_buttons |= (1 << (use - 1));
|
||||
else g_current_input_data.mouse_buttons &= ~(1 << (use - 1));
|
||||
@ -45,22 +63,18 @@ static void hid_input_callback(void* inContext, IOReturn inResult, void* inSende
|
||||
|
||||
for (int i = 0; i < 2; i ++)
|
||||
if (use == axis_use_ids[i])
|
||||
g_current_input_data.mouse_delta[i] += IOHIDValueGetIntegerValue(inIOHIDValueRef);
|
||||
g_current_input_data.mouse_delta[i] += IOHIDValueGetIntegerValue(value);
|
||||
}
|
||||
}
|
||||
// Joystick handler
|
||||
else if (IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))
|
||||
// Joystick handler: TODO: Can GamePad work the same?
|
||||
else if (IOHIDDeviceConformsTo(connection->device, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick))
|
||||
{
|
||||
uint32_t slot = (uint32_t)inContext;
|
||||
if (slot >= 4)
|
||||
return;
|
||||
|
||||
if (type == kIOHIDElementTypeInput_Button && page == kHIDPage_Button)
|
||||
{
|
||||
CFIndex state = IOHIDValueGetIntegerValue(inIOHIDValueRef);
|
||||
CFIndex state = IOHIDValueGetIntegerValue(value);
|
||||
|
||||
if (state) g_current_input_data.pad_buttons[slot] |= (1 << (use - 1));
|
||||
else g_current_input_data.pad_buttons[slot] &= ~(1 << (use - 1));
|
||||
if (state) g_current_input_data.pad_buttons[connection->slot] |= (1 << (use - 1));
|
||||
else g_current_input_data.pad_buttons[connection->slot] &= ~(1 << (use - 1));
|
||||
}
|
||||
else if (type == kIOHIDElementTypeInput_Misc && page == kHIDPage_GenericDesktop)
|
||||
{
|
||||
@ -71,29 +85,94 @@ static void hid_input_callback(void* inContext, IOReturn inResult, void* inSende
|
||||
{
|
||||
CFIndex min = IOHIDElementGetPhysicalMin(element);
|
||||
CFIndex max = IOHIDElementGetPhysicalMax(element) - min;
|
||||
CFIndex state = IOHIDValueGetIntegerValue(inIOHIDValueRef) - min;
|
||||
CFIndex state = IOHIDValueGetIntegerValue(value) - min;
|
||||
|
||||
float val = (float)state / (float)max;
|
||||
g_current_input_data.pad_axis[slot][i] = ((val * 2.0f) - 1.0f) * 32767.0f;
|
||||
g_current_input_data.pad_axis[connection->slot][i] = ((val * 2.0f) - 1.0f) * 32767.0f;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
static void hid_device_attached(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef inDevice)
|
||||
static void hid_device_removed(void* context, IOReturn result, void* sender)
|
||||
{
|
||||
IOHIDDeviceOpen(inDevice, kIOHIDOptionsTypeNone);
|
||||
IOHIDDeviceScheduleWithRunLoop(inDevice, CFRunLoopGetCurrent(), kCFRunLoopDefaultMode);
|
||||
IOHIDDeviceRegisterInputValueCallback(inDevice, hid_input_callback, 0);
|
||||
struct hidpad_connection* connection = (struct hidpad_connection*)context;
|
||||
|
||||
if (connection && connection->slot < MAX_PADS)
|
||||
{
|
||||
g_current_input_data.pad_buttons[connection->slot] = 0;
|
||||
memset(g_current_input_data.pad_axis[connection->slot], 0, sizeof(g_current_input_data.pad_axis));
|
||||
|
||||
if (connection->interface)
|
||||
connection->interface->disconnect(connection->hidpad);
|
||||
memset(connection, 0, sizeof(*connection));
|
||||
}
|
||||
|
||||
IOHIDDeviceClose(sender, kIOHIDOptionsTypeNone);
|
||||
}
|
||||
|
||||
static void hid_device_removed(void* inContext, IOReturn inResult, void* inSender, IOHIDDeviceRef inDevice)
|
||||
static void hid_device_report(void* context, IOReturn result, void *sender, IOHIDReportType type, uint32_t reportID, uint8_t *report, CFIndex reportLength)
|
||||
{
|
||||
IOHIDDeviceClose(inDevice, kIOHIDOptionsTypeNone);
|
||||
struct hidpad_connection* connection = (struct hidpad_connection*)context;
|
||||
connection->interface->packet_handler(connection->hidpad, report, reportLength);
|
||||
}
|
||||
|
||||
static CFMutableDictionaryRef build_matching_dictionary(uint32_t page, uint32_t use)
|
||||
static void hid_manager_device_attached(void* context, IOReturn result, void* sender, IOHIDDeviceRef device)
|
||||
{
|
||||
bool is_pad = (IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick) ||
|
||||
IOHIDDeviceConformsTo(device, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad));
|
||||
|
||||
struct hidpad_connection* connection = 0;
|
||||
|
||||
if (is_pad)
|
||||
{
|
||||
for (int i = 0; i != MAX_PADS; i ++)
|
||||
{
|
||||
if (!g_connected_pads[i].device)
|
||||
{
|
||||
connection = &g_connected_pads[i];
|
||||
connection->device = device;
|
||||
connection->slot = i;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (!connection)
|
||||
return;
|
||||
}
|
||||
|
||||
IOHIDDeviceOpen(device, kIOHIDOptionsTypeNone);
|
||||
IOHIDDeviceScheduleWithRunLoop(device, CFRunLoopGetCurrent(), kCFRunLoopCommonModes);
|
||||
IOHIDDeviceRegisterRemovalCallback(device, hid_device_removed, connection);
|
||||
|
||||
CFStringRef device_name = IOHIDDeviceGetProperty(device, CFSTR(kIOHIDProductKey));
|
||||
if (is_pad && device_name)
|
||||
{
|
||||
static const struct { const char* name; struct hidpad_interface* iface; } hidpad_map[] = {
|
||||
{ "Nintendo RVL-CNT-01", &hidpad_wii },
|
||||
{ "PLAYSTATION(R)3 Controller", &hidpad_ps3 },
|
||||
{ 0, 0} };
|
||||
|
||||
char buffer[1024];
|
||||
CFStringGetCString(device_name, buffer, 1024, kCFStringEncodingUTF8);
|
||||
|
||||
for (int i = 0; hidpad_map[i].name; i ++)
|
||||
{
|
||||
if (strstr(buffer, hidpad_map[i].name))
|
||||
{
|
||||
connection->interface = hidpad_map[i].iface;
|
||||
IOHIDDeviceRegisterInputReportCallback(device, connection->data, 2048, hid_device_report, connection);
|
||||
connection->hidpad = connection->interface->connect(connection, connection->slot);
|
||||
return;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
IOHIDDeviceRegisterInputValueCallback(device, hid_device_input_callback, connection);
|
||||
}
|
||||
|
||||
static void append_matching_dictionary(CFMutableArrayRef array, uint32_t page, uint32_t use)
|
||||
{
|
||||
CFMutableDictionaryRef matcher = CFDictionaryCreateMutable(kCFAllocatorDefault, 0, &kCFTypeDictionaryKeyCallBacks, &kCFTypeDictionaryValueCallBacks);
|
||||
|
||||
@ -105,7 +184,8 @@ static CFMutableDictionaryRef build_matching_dictionary(uint32_t page, uint32_t
|
||||
CFDictionarySetValue(matcher, CFSTR(kIOHIDDeviceUsageKey), usen);
|
||||
CFRelease(usen);
|
||||
|
||||
return matcher;
|
||||
CFArrayAppendValue(array, matcher);
|
||||
CFRelease(matcher);
|
||||
}
|
||||
|
||||
void osx_pad_init()
|
||||
@ -115,21 +195,15 @@ void osx_pad_init()
|
||||
g_hid_manager = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
|
||||
CFMutableArrayRef matcher = CFArrayCreateMutable(kCFAllocatorDefault, 0, &kCFTypeArrayCallBacks);
|
||||
|
||||
CFMutableDictionaryRef mouse = build_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse);
|
||||
CFArrayAppendValue(matcher, mouse);
|
||||
CFRelease(mouse);
|
||||
|
||||
CFMutableDictionaryRef joystick = build_matching_dictionary(kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
|
||||
CFArrayAppendValue(matcher, joystick);
|
||||
CFRelease(joystick);
|
||||
append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_Mouse);
|
||||
append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_Joystick);
|
||||
append_matching_dictionary(matcher, kHIDPage_GenericDesktop, kHIDUsage_GD_GamePad);
|
||||
|
||||
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);
|
||||
}
|
||||
@ -140,7 +214,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);
|
||||
}
|
||||
|
46
apple/OSX/platform.h
Normal file
46
apple/OSX/platform.h
Normal file
@ -0,0 +1,46 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013 - Jason Fetters
|
||||
* Copyright (C) 2011-2013 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* 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 __RARCH_OSX_PLATFORM_H
|
||||
#define __RARCH_OSX_PLATFORM_H
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@interface RAGameView : NSView
|
||||
|
||||
+ (RAGameView*)get;
|
||||
- (void)display;
|
||||
|
||||
@end
|
||||
|
||||
@interface RetroArch_OSX : NSObject<RetroArch_Platform, NSApplicationDelegate>
|
||||
{
|
||||
@public
|
||||
NSWindow IBOutlet *window;
|
||||
}
|
||||
|
||||
+ (RetroArch_OSX*)get;
|
||||
|
||||
- (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
|
249
apple/OSX/platform.m
Normal file
249
apple/OSX/platform.m
Normal file
@ -0,0 +1,249 @@
|
||||
/* 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 <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#import "RetroArch_Apple.h"
|
||||
#include "rarch_wrapper.h"
|
||||
#include "apple/common/apple_input.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
@interface RApplication : NSApplication
|
||||
@end
|
||||
|
||||
@implementation RApplication
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
[super sendEvent:event];
|
||||
|
||||
if (event.type == GSEVENT_TYPE_KEYDOWN || event.type == GSEVENT_TYPE_KEYUP)
|
||||
apple_input_handle_key_event(event.keyCode, event.type == GSEVENT_TYPE_KEYDOWN);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RetroArch_OSX
|
||||
{
|
||||
NSWindow IBOutlet* _coreSelectSheet;
|
||||
|
||||
bool _isTerminating;
|
||||
bool _loaded;
|
||||
bool _wantReload;
|
||||
NSString* _file;
|
||||
RAModuleInfo* _core;
|
||||
}
|
||||
|
||||
+ (RetroArch_OSX*)get
|
||||
{
|
||||
return (RetroArch_OSX*)[[NSApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
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];
|
||||
[window.contentView setAutoresizesSubviews:YES];
|
||||
[window.contentView addSubview:RAGameView.get];
|
||||
[window makeFirstResponder:RAGameView.get];
|
||||
|
||||
// Create core select list
|
||||
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
|
||||
|
||||
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.\nSelect \"Go->Cores Directory\" from the menu and place libretro dylib files there.", @"RetroArch");
|
||||
|
||||
// Run RGUI if needed
|
||||
if (!_wantReload || apple_argv)
|
||||
apple_run_core(nil, 0);
|
||||
else
|
||||
[self chooseCore];
|
||||
|
||||
_wantReload = false;
|
||||
|
||||
extern void osx_pad_init();
|
||||
osx_pad_init();
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
_isTerminating = true;
|
||||
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(apple_event_basic_command, (void*)QUIT);
|
||||
|
||||
return apple_is_running ? NSTerminateCancel : NSTerminateNow;
|
||||
}
|
||||
|
||||
|
||||
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
|
||||
{
|
||||
if (filenames.count == 1 && filenames[0])
|
||||
{
|
||||
_file = filenames[0];
|
||||
|
||||
if (!_loaded)
|
||||
_wantReload = true;
|
||||
else
|
||||
[self chooseCore];
|
||||
|
||||
[sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
|
||||
}
|
||||
else
|
||||
{
|
||||
apple_display_alert(@"Cannot open multiple files", @"RetroArch");
|
||||
[sender replyToOpenOrPrint:NSApplicationDelegateReplyFailure];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)openDocument:(id)sender
|
||||
{
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
[panel beginSheetModalForWindow:window completionHandler:^(NSInteger result)
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
|
||||
if (result == NSOKButton && panel.URL)
|
||||
{
|
||||
_file = panel.URL.path;
|
||||
[self performSelector:@selector(chooseCore) withObject:nil afterDelay:.5f];
|
||||
}
|
||||
}];
|
||||
[NSApplication.sharedApplication runModalForWindow:panel];
|
||||
}
|
||||
|
||||
// This utility function will queue the _core and _file instance values for running.
|
||||
// If the emulator thread is already running it will tell it to quit.
|
||||
- (void)runCore
|
||||
{
|
||||
_wantReload = apple_is_running;
|
||||
|
||||
if (!apple_is_running)
|
||||
apple_run_core(_core, _file.UTF8String);
|
||||
else
|
||||
apple_frontend_post_event(apple_event_basic_command, (void*)QUIT);
|
||||
}
|
||||
|
||||
- (void)chooseCore
|
||||
{
|
||||
[NSApplication.sharedApplication beginSheet:_coreSelectSheet modalForWindow:window modalDelegate:nil didEndSelector:nil contextInfo:nil];
|
||||
[NSApplication.sharedApplication runModalForWindow:_coreSelectSheet];
|
||||
}
|
||||
|
||||
- (IBAction)coreWasChosen:(id)sender
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
[NSApplication.sharedApplication endSheet:_coreSelectSheet returnCode:0];
|
||||
[_coreSelectSheet orderOut:self];
|
||||
|
||||
if (_isTerminating)
|
||||
return;
|
||||
|
||||
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
|
||||
_core = (RAModuleInfo*)cb.objectValueOfSelectedItem;
|
||||
|
||||
[self runCore];
|
||||
}
|
||||
|
||||
#pragma mark RetroArch_Platform
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
|
||||
{
|
||||
if (file)
|
||||
[NSDocumentController.sharedDocumentController noteNewRecentDocumentURL:[NSURL fileURLWithPath:@(file)]];
|
||||
}
|
||||
|
||||
- (void)unloadingCore:(RAModuleInfo*)core
|
||||
{
|
||||
if (_isTerminating)
|
||||
[NSApplication.sharedApplication terminate:nil];
|
||||
|
||||
if (_wantReload)
|
||||
apple_run_core(_core, _file.UTF8String);
|
||||
else if(apple_use_tv_mode)
|
||||
apple_run_core(nil, 0);
|
||||
else
|
||||
[NSApplication.sharedApplication terminate:nil];
|
||||
|
||||
_wantReload = false;
|
||||
}
|
||||
|
||||
#pragma mark Menus
|
||||
- (IBAction)showCoresDirectory:(id)sender
|
||||
{
|
||||
[[NSWorkspace sharedWorkspace] openFile:self.coreDirectory];
|
||||
}
|
||||
|
||||
- (IBAction)showPreferences:(id)sender
|
||||
{
|
||||
NSWindowController* wc = [[NSWindowController alloc] initWithWindowNibName:@"Settings"];
|
||||
[NSApp runModalForWindow:wc.window];
|
||||
}
|
||||
|
||||
- (IBAction)basicEvent:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&apple_event_basic_command, (void*)((NSMenuItem*)sender).tag);
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
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);
|
||||
}
|
||||
|
@ -14,16 +14,268 @@
|
||||
*/
|
||||
|
||||
#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
|
||||
|
||||
@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 +285,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 +301,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 +315,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 +334,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 +417,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 +442,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 +460,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;
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1,711 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013 - Jason Fetters
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#import "RetroArch_Apple.h"
|
||||
#include "rarch_wrapper.h"
|
||||
|
||||
#include "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
|
||||
|
||||
#ifdef IOS
|
||||
#import "views.h"
|
||||
#include "../iOS/input/BTStack/btpad.h"
|
||||
#include "../iOS/input/BTStack/btdynamic.h"
|
||||
#include "../iOS/input/BTStack/btpad.h"
|
||||
#elif defined(USE_XATTR)
|
||||
#include "sys/xattr.h"
|
||||
#endif
|
||||
|
||||
#include "file.h"
|
||||
|
||||
#define GSEVENT_TYPE_KEYDOWN 10
|
||||
#define GSEVENT_TYPE_KEYUP 11
|
||||
|
||||
//#define HAVE_DEBUG_FILELOG
|
||||
static bool use_tv_mode;
|
||||
|
||||
id<RetroArch_Platform> apple_platform;
|
||||
|
||||
// From frontend/frontend_ios.c
|
||||
extern void* rarch_main(void* args);
|
||||
extern void apple_frontend_post_event(void (*fn)(void*), void* userdata);
|
||||
|
||||
|
||||
// These are based on the tag property of the button used to trigger the event
|
||||
enum basic_event_t { RESET = 1, LOAD_STATE = 2, SAVE_STATE = 3, QUIT = 4 };
|
||||
static void event_basic_command(void* userdata)
|
||||
{
|
||||
switch ((enum basic_event_t)userdata)
|
||||
{
|
||||
case RESET: rarch_game_reset(); return;
|
||||
case LOAD_STATE: rarch_load_state(); return;
|
||||
case SAVE_STATE: rarch_save_state(); return;
|
||||
case QUIT: g_extern.system.shutdown = true; return;
|
||||
}
|
||||
}
|
||||
|
||||
static void event_set_state_slot(void* userdata)
|
||||
{
|
||||
g_extern.state_slot = (uint32_t)userdata;
|
||||
}
|
||||
|
||||
static void event_show_rgui(void* userdata)
|
||||
{
|
||||
const bool in_menu = g_extern.lifecycle_mode_state & (1 << MODE_MENU);
|
||||
g_extern.lifecycle_mode_state &= ~(1ULL << (in_menu ? MODE_MENU : MODE_GAME));
|
||||
g_extern.lifecycle_mode_state |= (1ULL << (in_menu ? MODE_GAME : MODE_MENU));
|
||||
}
|
||||
|
||||
static void event_reload_config(void* userdata)
|
||||
{
|
||||
objc_clear_config_hack();
|
||||
|
||||
uninit_drivers();
|
||||
config_load();
|
||||
init_drivers();
|
||||
}
|
||||
|
||||
#pragma mark EMULATION
|
||||
static pthread_t apple_retro_thread;
|
||||
static bool apple_is_paused;
|
||||
static bool apple_is_running;
|
||||
static RAModuleInfo* apple_core;
|
||||
|
||||
void apple_run_core(RAModuleInfo* core, const char* file)
|
||||
{
|
||||
if (!apple_is_running)
|
||||
{
|
||||
[apple_platform loadingCore:core withFile:file];
|
||||
|
||||
apple_core = core;
|
||||
apple_is_running = true;
|
||||
|
||||
struct rarch_main_wrap* load_data = malloc(sizeof(struct rarch_main_wrap));
|
||||
memset(load_data, 0, sizeof(struct rarch_main_wrap));
|
||||
|
||||
load_data->config_path = strdup(apple_platform.retroarchConfigPath.UTF8String);
|
||||
|
||||
#ifdef IOS
|
||||
load_data->sram_path = strdup(RetroArch_iOS.get.systemDirectory.UTF8String);
|
||||
load_data->state_path = strdup(RetroArch_iOS.get.systemDirectory.UTF8String);
|
||||
#endif
|
||||
|
||||
if (file && core)
|
||||
{
|
||||
load_data->libretro_path = strdup(apple_core.path.UTF8String);
|
||||
load_data->rom_path = strdup(file);
|
||||
}
|
||||
|
||||
if (pthread_create(&apple_retro_thread, 0, rarch_main, load_data))
|
||||
{
|
||||
apple_rarch_exited((void*)1);
|
||||
return;
|
||||
}
|
||||
|
||||
pthread_detach(apple_retro_thread);
|
||||
}
|
||||
}
|
||||
|
||||
void apple_rarch_exited(void* result)
|
||||
{
|
||||
if (result)
|
||||
apple_display_alert(@"Failed to load game.", 0);
|
||||
|
||||
RAModuleInfo* used_core = apple_core;
|
||||
apple_core = nil;
|
||||
|
||||
if (apple_is_running)
|
||||
{
|
||||
apple_is_running = false;
|
||||
[apple_platform unloadingCore:used_core];
|
||||
}
|
||||
|
||||
if (use_tv_mode)
|
||||
apple_run_core(nil, 0);
|
||||
}
|
||||
|
||||
//
|
||||
// IOS
|
||||
//
|
||||
#pragma mark IOS
|
||||
#ifdef IOS
|
||||
// Input helpers: This is kept here because it needs objective-c
|
||||
static void handle_touch_event(NSArray* touches)
|
||||
{
|
||||
const int numTouches = [touches count];
|
||||
const float scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
g_current_input_data.touch_count = 0;
|
||||
|
||||
for(int i = 0; i != numTouches && g_current_input_data.touch_count < MAX_TOUCHES; i ++)
|
||||
{
|
||||
UITouch* touch = [touches objectAtIndex:i];
|
||||
const CGPoint coord = [touch locationInView:touch.view];
|
||||
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
g_current_input_data.touches[g_current_input_data.touch_count ].screen_x = coord.x * scale;
|
||||
g_current_input_data.touches[g_current_input_data.touch_count ++].screen_y = coord.y * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@interface RApplication : UIApplication
|
||||
@end
|
||||
|
||||
@implementation RApplication
|
||||
|
||||
- (void)sendEvent:(UIEvent *)event
|
||||
{
|
||||
[super sendEvent:event];
|
||||
|
||||
if ([[event allTouches] count])
|
||||
handle_touch_event(event.allTouches.allObjects);
|
||||
else if ([event respondsToSelector:@selector(_gsEvent)])
|
||||
{
|
||||
// Stolen from: http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html
|
||||
uint8_t* eventMem = (uint8_t*)(void*)CFBridgingRetain([event performSelector:@selector(_gsEvent)]);
|
||||
int eventType = eventMem ? *(int*)&eventMem[8] : 0;
|
||||
|
||||
if (eventType == GSEVENT_TYPE_KEYDOWN || eventType == GSEVENT_TYPE_KEYUP)
|
||||
apple_input_handle_key_event(*(uint16_t*)&eventMem[0x3C], eventType == GSEVENT_TYPE_KEYDOWN);
|
||||
|
||||
CFBridgingRelease(eventMem);
|
||||
}
|
||||
}
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
#if defined(HAVE_DEBUG_FILELOG) && (TARGET_IPHONE_SIMULATOR == 0)
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console_stdout.log"];
|
||||
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stdout);
|
||||
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stderr);
|
||||
#endif
|
||||
return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class]));
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RetroArch_iOS
|
||||
{
|
||||
UIWindow* _window;
|
||||
|
||||
bool _isGameTop, _isRomList;
|
||||
uint32_t _settingMenusInBackStack;
|
||||
uint32_t _enabledOrientations;
|
||||
|
||||
RAModuleInfo* _module;
|
||||
}
|
||||
|
||||
+ (RetroArch_iOS*)get
|
||||
{
|
||||
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
// UIApplicationDelegate
|
||||
- (void)applicationDidFinishLaunching:(UIApplication *)application
|
||||
{
|
||||
apple_platform = self;
|
||||
self.delegate = self;
|
||||
|
||||
// Setup window
|
||||
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
_window.rootViewController = self;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
// Build system paths and test permissions
|
||||
self.documentsDirectory = [NSHomeDirectory() stringByAppendingPathComponent:@"Documents"];
|
||||
self.systemDirectory = [self.documentsDirectory stringByAppendingPathComponent:@".RetroArch"];
|
||||
self.systemConfigPath = [self.systemDirectory stringByAppendingPathComponent:@"frontend.cfg"];
|
||||
|
||||
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 (use_tv_mode)
|
||||
apple_run_core(nil, 0);
|
||||
}
|
||||
|
||||
// Warn if there are no cores present
|
||||
if ([RAModuleInfo getModules].count == 0)
|
||||
apple_display_alert(@"No libretro cores were found. You will not be able to play any games.", 0);
|
||||
}
|
||||
|
||||
- (void)applicationWillEnterForeground:(UIApplication *)application
|
||||
{
|
||||
[RAGameView.get resume];
|
||||
}
|
||||
|
||||
- (void)applicationDidEnterBackground:(UIApplication *)application
|
||||
{
|
||||
[RAGameView.get suspend];
|
||||
}
|
||||
|
||||
// UINavigationControllerDelegate
|
||||
- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated
|
||||
{
|
||||
_isGameTop = [viewController isKindOfClass:[RAGameView class]];
|
||||
_isRomList = [viewController isKindOfClass:[RADirectoryList class]];
|
||||
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:_isGameTop withAnimation:UIStatusBarAnimationNone];
|
||||
[[UIApplication sharedApplication] setIdleTimerDisabled:_isGameTop];
|
||||
|
||||
self.navigationBarHidden = _isGameTop;
|
||||
[self setToolbarHidden:!_isRomList animated:YES];
|
||||
self.topViewController.navigationItem.rightBarButtonItem = [self createSettingsButton];
|
||||
}
|
||||
|
||||
// UINavigationController: Never animate when pushing onto, or popping, an RAGameView
|
||||
- (void)pushViewController:(UIViewController*)theView animated:(BOOL)animated
|
||||
{
|
||||
if ([theView respondsToSelector:@selector(isSettingsView)] && [(id)theView isSettingsView])
|
||||
_settingMenusInBackStack ++;
|
||||
|
||||
[super pushViewController:theView animated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
- (UIViewController*)popViewControllerAnimated:(BOOL)animated
|
||||
{
|
||||
if ([self.topViewController respondsToSelector:@selector(isSettingsView)] && [(id)self.topViewController isSettingsView])
|
||||
_settingMenusInBackStack --;
|
||||
|
||||
return [super popViewControllerAnimated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
// NOTE: This version only runs on iOS6
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
return _isGameTop ? _enabledOrientations
|
||||
: UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
// NOTE: This version runs on iOS2-iOS5, but not iOS6
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
if (_isGameTop)
|
||||
switch (interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskPortrait);
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskPortraitUpsideDown);
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskLandscapeLeft);
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskLandscapeRight);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark RetroArch_Platform
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
|
||||
{
|
||||
[self pushViewController:RAGameView.get animated:NO];
|
||||
[RASettingsList refreshModuleConfig:core];
|
||||
|
||||
btpad_set_inquiry_state(false);
|
||||
|
||||
[self refreshSystemConfig];
|
||||
}
|
||||
|
||||
- (void)unloadingCore:(RAModuleInfo*)core
|
||||
{
|
||||
[self popToViewController:[RAGameView get] animated:NO];
|
||||
[self popViewControllerAnimated:NO];
|
||||
|
||||
btpad_set_inquiry_state(true);
|
||||
}
|
||||
|
||||
- (NSString*)retroarchConfigPath
|
||||
{
|
||||
return [NSString stringWithFormat:@"%@/retroarch.cfg", self.systemDirectory];
|
||||
}
|
||||
|
||||
- (NSString*)corePath
|
||||
{
|
||||
return [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"modules"];
|
||||
}
|
||||
|
||||
- (void)refreshConfig
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&event_reload_config, 0);
|
||||
else
|
||||
objc_clear_config_hack();
|
||||
}
|
||||
|
||||
- (void)refreshSystemConfig
|
||||
{
|
||||
// Read load time settings
|
||||
config_file_t* conf = config_file_new([self.systemConfigPath UTF8String]);
|
||||
|
||||
if (conf)
|
||||
{
|
||||
// Get enabled orientations
|
||||
static const struct { const char* setting; uint32_t orientation; } orientationSettings[4] =
|
||||
{
|
||||
{ "ios_allow_portrait", UIInterfaceOrientationMaskPortrait },
|
||||
{ "ios_allow_portrait_upside_down", UIInterfaceOrientationMaskPortraitUpsideDown },
|
||||
{ "ios_allow_landscape_left", UIInterfaceOrientationMaskLandscapeLeft },
|
||||
{ "ios_allow_landscape_right", UIInterfaceOrientationMaskLandscapeRight }
|
||||
};
|
||||
|
||||
_enabledOrientations = 0;
|
||||
|
||||
for (int i = 0; i < 4; i ++)
|
||||
{
|
||||
bool enabled = false;
|
||||
bool found = config_get_bool(conf, orientationSettings[i].setting, &enabled);
|
||||
|
||||
if (!found || enabled)
|
||||
_enabledOrientations |= orientationSettings[i].orientation;
|
||||
}
|
||||
|
||||
//
|
||||
bool val;
|
||||
apple_input_enable_icade(config_get_bool(conf, "ios_use_icade", &val) && val);
|
||||
btstack_set_poweron(config_get_bool(conf, "ios_use_btstack", &val) && val);
|
||||
use_tv_mode = config_get_bool(conf, "ios_tv_mode", & val) && val;
|
||||
|
||||
config_file_free(conf);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark PAUSE MENU
|
||||
- (UIBarButtonItem*)createSettingsButton
|
||||
{
|
||||
if (_settingMenusInBackStack == 0)
|
||||
return [[UIBarButtonItem alloc]
|
||||
initWithTitle:@"Settings"
|
||||
style:UIBarButtonItemStyleBordered
|
||||
target:[RetroArch_iOS get]
|
||||
action:@selector(showSystemSettings)];
|
||||
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (IBAction)showPauseMenu:(id)sender
|
||||
{
|
||||
if (apple_is_running && !apple_is_paused && _isGameTop)
|
||||
{
|
||||
apple_is_paused = true;
|
||||
[[RAGameView get] openPauseMenu];
|
||||
|
||||
btpad_set_inquiry_state(true);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)basicEvent:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&event_basic_command, ((UIView*)sender).tag);
|
||||
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)chooseState:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(event_set_state_slot, (void*)((UISegmentedControl*)sender).selectedSegmentIndex);
|
||||
}
|
||||
|
||||
- (IBAction)showRGUI:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(event_show_rgui, 0);
|
||||
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)closePauseMenu:(id)sender
|
||||
{
|
||||
[[RAGameView get] closePauseMenu];
|
||||
apple_is_paused = false;
|
||||
|
||||
btpad_set_inquiry_state(false);
|
||||
}
|
||||
|
||||
- (IBAction)showSettings
|
||||
{
|
||||
[self pushViewController:[[RASettingsList alloc] initWithModule:_module] animated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)showSystemSettings
|
||||
{
|
||||
[self pushViewController:[RASystemSettingsList new] animated:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
//
|
||||
// OSX
|
||||
//
|
||||
#pragma mark OSX
|
||||
#ifdef OSX
|
||||
|
||||
@interface RApplication : NSApplication
|
||||
@end
|
||||
|
||||
@implementation RApplication
|
||||
|
||||
- (void)sendEvent:(NSEvent *)event
|
||||
{
|
||||
[super sendEvent:event];
|
||||
|
||||
if (event.type == GSEVENT_TYPE_KEYDOWN || event.type == GSEVENT_TYPE_KEYUP)
|
||||
apple_input_handle_key_event(event.keyCode, event.type == GSEVENT_TYPE_KEYDOWN);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RetroArch_OSX
|
||||
{
|
||||
NSWindow IBOutlet* _coreSelectSheet;
|
||||
|
||||
bool _isTerminating;
|
||||
bool _loaded;
|
||||
bool _wantReload;
|
||||
NSString* _file;
|
||||
RAModuleInfo* _core;
|
||||
}
|
||||
|
||||
+ (RetroArch_OSX*)get
|
||||
{
|
||||
return (RetroArch_OSX*)[[NSApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
- (void)applicationDidFinishLaunching:(NSNotification *)aNotification
|
||||
{
|
||||
apple_platform = self;
|
||||
_loaded = true;
|
||||
|
||||
[window setCollectionBehavior:NSWindowCollectionBehaviorFullScreenPrimary];
|
||||
|
||||
RAGameView.get.frame = [window.contentView bounds];
|
||||
[window.contentView setAutoresizesSubviews:YES];
|
||||
[window.contentView addSubview:RAGameView.get];
|
||||
[window makeFirstResponder:RAGameView.get];
|
||||
|
||||
// Create core select list
|
||||
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
|
||||
|
||||
for (RAModuleInfo* i in RAModuleInfo.getModules)
|
||||
[cb addItemWithObjectValue:i];
|
||||
|
||||
if (cb.numberOfItems)
|
||||
[cb selectItemAtIndex:0];
|
||||
else
|
||||
apple_display_alert(@"No libretro cores were found.", @"RetroArch");
|
||||
|
||||
// Run RGUI if needed
|
||||
if (!_wantReload)
|
||||
apple_run_core(nil, 0);
|
||||
else
|
||||
[self chooseCore];
|
||||
|
||||
_wantReload = false;
|
||||
|
||||
extern void osx_pad_init();
|
||||
osx_pad_init();
|
||||
}
|
||||
|
||||
- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)theApplication
|
||||
{
|
||||
return YES;
|
||||
}
|
||||
|
||||
- (NSApplicationTerminateReply)applicationShouldTerminate:(NSApplication *)sender
|
||||
{
|
||||
_isTerminating = true;
|
||||
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(event_basic_command, (void*)QUIT);
|
||||
|
||||
return apple_is_running ? NSTerminateCancel : NSTerminateNow;
|
||||
}
|
||||
|
||||
|
||||
- (void)application:(NSApplication *)sender openFiles:(NSArray *)filenames
|
||||
{
|
||||
if (filenames.count == 1 && filenames[0])
|
||||
{
|
||||
_file = filenames[0];
|
||||
|
||||
if (!_loaded)
|
||||
_wantReload = true;
|
||||
else
|
||||
[self chooseCore];
|
||||
|
||||
[sender replyToOpenOrPrint:NSApplicationDelegateReplySuccess];
|
||||
}
|
||||
else
|
||||
{
|
||||
apple_display_alert(@"Cannot open multiple files", @"RetroArch");
|
||||
[sender replyToOpenOrPrint:NSApplicationDelegateReplyFailure];
|
||||
}
|
||||
}
|
||||
|
||||
- (void)openDocument:(id)sender
|
||||
{
|
||||
NSOpenPanel* panel = [NSOpenPanel openPanel];
|
||||
[panel beginSheetModalForWindow:window completionHandler:^(NSInteger result)
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
|
||||
if (result == NSOKButton && panel.URL)
|
||||
{
|
||||
_file = panel.URL.path;
|
||||
[self performSelector:@selector(chooseCore) withObject:nil afterDelay:.5f];
|
||||
}
|
||||
}];
|
||||
[NSApplication.sharedApplication runModalForWindow:panel];
|
||||
}
|
||||
|
||||
// This utility function will queue the _core and _file instance values for running.
|
||||
// If the emulator thread is already running it will tell it to quit.
|
||||
- (void)runCore
|
||||
{
|
||||
_wantReload = apple_is_running;
|
||||
|
||||
if (!apple_is_running)
|
||||
apple_run_core(_core, _file.UTF8String);
|
||||
else
|
||||
apple_frontend_post_event(event_basic_command, (void*)QUIT);
|
||||
}
|
||||
|
||||
- (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];
|
||||
}
|
||||
|
||||
- (IBAction)coreWasChosen:(id)sender
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
[NSApplication.sharedApplication endSheet:_coreSelectSheet returnCode:0];
|
||||
[_coreSelectSheet orderOut:self];
|
||||
|
||||
if (_isTerminating)
|
||||
return;
|
||||
|
||||
NSComboBox* cb = (NSComboBox*)[_coreSelectSheet.contentView viewWithTag:1];
|
||||
_core = (RAModuleInfo*)cb.objectValueOfSelectedItem;
|
||||
|
||||
[self runCore];
|
||||
}
|
||||
|
||||
#pragma mark RetroArch_Platform
|
||||
- (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
|
||||
}
|
||||
}
|
||||
|
||||
- (void)unloadingCore:(RAModuleInfo*)core
|
||||
{
|
||||
if (_isTerminating)
|
||||
[NSApplication.sharedApplication terminate:nil];
|
||||
|
||||
if (_wantReload)
|
||||
apple_run_core(_core, _file.UTF8String);
|
||||
else if(use_tv_mode)
|
||||
apple_run_core(nil, 0);
|
||||
else
|
||||
[NSApplication.sharedApplication terminate:nil];
|
||||
|
||||
_wantReload = false;
|
||||
}
|
||||
|
||||
- (NSString*)retroarchConfigPath
|
||||
{
|
||||
NSArray* paths = NSSearchPathForDirectoriesInDomains(NSApplicationSupportDirectory, NSUserDomainMask, YES);
|
||||
return [paths[0] stringByAppendingPathComponent:@"RetroArch/retroarch.cfg"];
|
||||
}
|
||||
|
||||
- (NSString*)corePath
|
||||
{
|
||||
return [NSBundle.mainBundle.bundlePath stringByAppendingPathComponent:@"Contents/Resources/modules"];
|
||||
}
|
||||
|
||||
#pragma mark Menus
|
||||
- (IBAction)showPreferences:(id)sender
|
||||
{
|
||||
[[[NSWindowController alloc] initWithWindowNibName:@"Settings"] window];
|
||||
}
|
||||
|
||||
- (IBAction)basicEvent:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&event_basic_command, (void*)((NSMenuItem*)sender).tag);
|
||||
}
|
||||
|
||||
- (void)alertDidEnd:(NSAlert *)alert returnCode:(NSInteger)returnCode contextInfo:(void *)contextInfo
|
||||
{
|
||||
[NSApplication.sharedApplication stopModal];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
return NSApplicationMain(argc, (const char **) argv);
|
||||
}
|
||||
|
||||
#endif
|
@ -8,9 +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 */; };
|
||||
@ -28,13 +30,16 @@
|
||||
|
||||
/* 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; };
|
||||
96355CE51788E72A0010DBFA /* AppKit.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AppKit.framework; path = System/Library/Frameworks/AppKit.framework; sourceTree = SDKROOT; };
|
||||
96355CE61788E72A0010DBFA /* CoreData.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreData.framework; path = System/Library/Frameworks/CoreData.framework; sourceTree = SDKROOT; };
|
||||
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.xib; name = en; path = en.lproj/InputBinder.xib; sourceTree = "<group>"; };
|
||||
964DE7C517D84B57001CBB6C /* en */ = {isa = PBXFileReference; lastKnownFileType = file.xib; 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; };
|
||||
@ -75,7 +80,7 @@
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
962EE0E1178B3DF6004224FF /* IOKit.framework */,
|
||||
96355CE81788E72A0010DBFA /* RetroArch */,
|
||||
96355CE81788E72A0010DBFA /* common */,
|
||||
967894E7178A2E9B00D6CA69 /* Assets */,
|
||||
96355CE11788E72A0010DBFA /* Frameworks */,
|
||||
96355CE01788E72A0010DBFA /* Products */,
|
||||
@ -106,9 +111,11 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
96355CE81788E72A0010DBFA /* RetroArch */ = {
|
||||
96355CE81788E72A0010DBFA /* common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9646869617BBC14E00C5EA69 /* platform.m */,
|
||||
9646869717BBC14E00C5EA69 /* platform.h */,
|
||||
9620F662178FD4D3001B3B81 /* settings.m */,
|
||||
967894A01788F07D00D6CA69 /* griffin.c */,
|
||||
967894971788F02600D6CA69 /* RAGameView.m */,
|
||||
@ -119,7 +126,7 @@
|
||||
9678949C1788F02600D6CA69 /* utility.m */,
|
||||
967894951788ED1100D6CA69 /* main.m */,
|
||||
);
|
||||
path = RetroArch;
|
||||
path = common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
96355CE91788E72A0010DBFA /* Supporting Files */ = {
|
||||
@ -138,7 +145,8 @@
|
||||
967894E8178A2EB400D6CA69 /* modules */,
|
||||
967894911788ECDB00D6CA69 /* MainMenu.xib */,
|
||||
C15874EE178F2094001171D4 /* RetroArch.icns */,
|
||||
9620F6641790004F001B3B81 /* Settings.xib */,
|
||||
964DE7C617D84B57001CBB6C /* Settings.xib */,
|
||||
964DE7C317D84B34001CBB6C /* InputBinder.xib */,
|
||||
);
|
||||
name = Assets;
|
||||
sourceTree = "<group>";
|
||||
@ -197,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;
|
||||
};
|
||||
@ -214,12 +223,31 @@
|
||||
9678949F1788F02600D6CA69 /* utility.m in Sources */,
|
||||
967894A11788F07D00D6CA69 /* griffin.c in Sources */,
|
||||
9620F663178FD4D3001B3B81 /* settings.m in Sources */,
|
||||
9646869817BBC14E00C5EA69 /* platform.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
/* 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 = (
|
||||
@ -262,7 +290,6 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
@ -278,7 +305,6 @@
|
||||
"$(inherited)",
|
||||
);
|
||||
GCC_SYMBOLS_PRIVATE_EXTERN = NO;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
@ -297,7 +323,6 @@
|
||||
"-DINLINE=inline",
|
||||
"-DLSB_FIRST",
|
||||
"-D__LIBRETRO__",
|
||||
"-DRARCH_PERFORMANCE_MODE",
|
||||
"-DWANT_RPNG",
|
||||
"-DHAVE_COREAUDIO",
|
||||
"-DHAVE_DYNAMIC",
|
||||
@ -321,7 +346,6 @@
|
||||
CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x";
|
||||
CLANG_CXX_LIBRARY = "libc++";
|
||||
CLANG_ENABLE_OBJC_ARC = YES;
|
||||
CLANG_WARN_CONSTANT_CONVERSION = YES;
|
||||
CLANG_WARN_EMPTY_BODY = YES;
|
||||
CLANG_WARN_ENUM_CONVERSION = YES;
|
||||
CLANG_WARN_INT_CONVERSION = YES;
|
||||
@ -331,7 +355,6 @@
|
||||
DEBUG_INFORMATION_FORMAT = "dwarf-with-dsym";
|
||||
GCC_C_LANGUAGE_STANDARD = gnu99;
|
||||
GCC_ENABLE_OBJC_EXCEPTIONS = YES;
|
||||
GCC_WARN_64_TO_32_BIT_CONVERSION = YES;
|
||||
GCC_WARN_ABOUT_RETURN_TYPE = YES;
|
||||
GCC_WARN_UNINITIALIZED_AUTOS = YES;
|
||||
GCC_WARN_UNUSED_VARIABLE = YES;
|
||||
@ -343,23 +366,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 = "";
|
||||
|
@ -16,6 +16,7 @@
|
||||
96366C5516C9AC3300D64A22 /* CoreAudio.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5416C9AC3300D64A22 /* CoreAudio.framework */; };
|
||||
96366C5916C9ACF500D64A22 /* AudioToolbox.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 96366C5816C9ACF500D64A22 /* AudioToolbox.framework */; };
|
||||
963F5AC816CC523B009BBD19 /* RAGameView.m in Sources */ = {isa = PBXBuildFile; fileRef = 963F5AC516CC523B009BBD19 /* RAGameView.m */; };
|
||||
9646869517BBBEAE00C5EA69 /* platform.m in Sources */ = {isa = PBXBuildFile; fileRef = 9646869417BBBEAE00C5EA69 /* platform.m */; };
|
||||
966B9CBD16E41E7A005B61E1 /* Default-568h@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */; };
|
||||
966B9CBF16E41E7A005B61E1 /* Default.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CB916E41E7A005B61E1 /* Default.png */; };
|
||||
966B9CC116E41E7A005B61E1 /* Default@2x.png in Resources */ = {isa = PBXBuildFile; fileRef = 966B9CBA16E41E7A005B61E1 /* Default@2x.png */; };
|
||||
@ -49,6 +50,7 @@
|
||||
96366C5416C9AC3300D64A22 /* CoreAudio.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = CoreAudio.framework; path = System/Library/Frameworks/CoreAudio.framework; sourceTree = SDKROOT; };
|
||||
96366C5816C9ACF500D64A22 /* AudioToolbox.framework */ = {isa = PBXFileReference; lastKnownFileType = wrapper.framework; name = AudioToolbox.framework; path = System/Library/Frameworks/AudioToolbox.framework; sourceTree = SDKROOT; };
|
||||
963F5AC516CC523B009BBD19 /* RAGameView.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; path = RAGameView.m; sourceTree = "<group>"; };
|
||||
9646869417BBBEAE00C5EA69 /* platform.m */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.c.objc; name = platform.m; path = iOS/platform.m; sourceTree = SOURCE_ROOT; };
|
||||
966B9CB816E41E7A005B61E1 /* Default-568h@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default-568h@2x.png"; sourceTree = "<group>"; };
|
||||
966B9CB916E41E7A005B61E1 /* Default.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = Default.png; sourceTree = "<group>"; };
|
||||
966B9CBA16E41E7A005B61E1 /* Default@2x.png */ = {isa = PBXFileReference; lastKnownFileType = image.png; path = "Default@2x.png"; sourceTree = "<group>"; };
|
||||
@ -118,7 +120,7 @@
|
||||
96AFAE1A16C1D4EA009DE44C = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
96AFAE3316C1D4EA009DE44C /* RetroArch */,
|
||||
96AFAE3316C1D4EA009DE44C /* common */,
|
||||
96AFAE9C16C1D976009DE44C /* core */,
|
||||
966B9CB716E41E7A005B61E1 /* Assets */,
|
||||
96AFAE2816C1D4EA009DE44C /* Frameworks */,
|
||||
@ -149,9 +151,10 @@
|
||||
name = Frameworks;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
96AFAE3316C1D4EA009DE44C /* RetroArch */ = {
|
||||
96AFAE3316C1D4EA009DE44C /* common */ = {
|
||||
isa = PBXGroup;
|
||||
children = (
|
||||
9646869417BBBEAE00C5EA69 /* platform.m */,
|
||||
967894571788EAAE00D6CA69 /* browser.m */,
|
||||
967894581788EAAE00D6CA69 /* RALogView.m */,
|
||||
967894591788EAAE00D6CA69 /* settings.m */,
|
||||
@ -164,7 +167,7 @@
|
||||
96355CD11788CF190010DBFA /* RetroArch_Apple.h */,
|
||||
96337E81176AC6E5004685F3 /* utility.m */,
|
||||
);
|
||||
path = RetroArch;
|
||||
path = common;
|
||||
sourceTree = "<group>";
|
||||
};
|
||||
96AFAE3416C1D4EA009DE44C /* Supporting Files */ = {
|
||||
@ -305,6 +308,7 @@
|
||||
9678945B1788EAAE00D6CA69 /* browser.m in Sources */,
|
||||
9678945C1788EAAE00D6CA69 /* RALogView.m in Sources */,
|
||||
9678945D1788EAAE00D6CA69 /* settings.m in Sources */,
|
||||
9646869517BBBEAE00C5EA69 /* platform.m in Sources */,
|
||||
);
|
||||
runOnlyForDeploymentPostprocessing = 0;
|
||||
};
|
||||
@ -363,7 +367,6 @@
|
||||
"-DLSB_FIRST",
|
||||
"-DHAVE_THREAD",
|
||||
"-D__LIBRETRO__",
|
||||
"-DRARCH_PERFORMANCE_MODE",
|
||||
"-DRARCH_MOBILE",
|
||||
"-std=gnu99",
|
||||
"-DHAVE_COREAUDIO",
|
||||
@ -413,7 +416,6 @@
|
||||
"-DLSB_FIRST",
|
||||
"-DHAVE_THREAD",
|
||||
"-D__LIBRETRO__",
|
||||
"-DRARCH_PERFORMANCE_MODE",
|
||||
"-DRARCH_MOBILE",
|
||||
"-std=gnu99",
|
||||
"-DHAVE_COREAUDIO",
|
||||
@ -454,7 +456,6 @@
|
||||
"-DINLINE=inline",
|
||||
"-DLSB_FIRST",
|
||||
"-D__LIBRETRO__",
|
||||
"-DRARCH_PERFORMANCE_MODE",
|
||||
"-DRARCH_MOBILE",
|
||||
"-DHAVE_COREAUDIO",
|
||||
"-DHAVE_DYNAMIC",
|
||||
@ -497,7 +498,6 @@
|
||||
"-DINLINE=inline",
|
||||
"-DLSB_FIRST",
|
||||
"-D__LIBRETRO__",
|
||||
"-DRARCH_PERFORMANCE_MODE",
|
||||
"-DRARCH_MOBILE",
|
||||
"-DHAVE_COREAUDIO",
|
||||
"-DHAVE_DYNAMIC",
|
||||
|
@ -17,15 +17,48 @@
|
||||
#include "rarch_wrapper.h"
|
||||
|
||||
#include "general.h"
|
||||
#include "gfx/gfx_common.h"
|
||||
#include "gfx/gfx_context.h"
|
||||
|
||||
// Define compatibility symbols and categories
|
||||
#ifdef IOS
|
||||
#define APP_HAS_FOCUS ([UIApplication sharedApplication].applicationState == UIApplicationStateActive)
|
||||
|
||||
#define GLContextClass EAGLContext
|
||||
#define GLAPIType GFX_CTX_OPENGL_ES_API
|
||||
#define GLFrameworkID CFSTR("com.apple.opengles")
|
||||
#define RAScreen UIScreen
|
||||
|
||||
@interface EAGLContext (OSXCompat) @end
|
||||
@implementation EAGLContext (OSXCompat)
|
||||
+ (void)clearCurrentContext { EAGLContext.currentContext = nil; }
|
||||
- (void)makeCurrentContext { EAGLContext.currentContext = self; }
|
||||
@end
|
||||
|
||||
#elif defined(OSX)
|
||||
#define APP_HAS_FOCUS ([NSApp isActive])
|
||||
|
||||
#define GLContextClass NSOpenGLContext
|
||||
#define GLAPIType GFX_CTX_OPENGL_API
|
||||
#define GLFrameworkID CFSTR("com.apple.opengl")
|
||||
#define RAScreen NSScreen
|
||||
|
||||
#define g_view g_instance // < RAGameView is a container on iOS; on OSX these are both the same object
|
||||
|
||||
@interface NSScreen (IOSCompat) @end
|
||||
@implementation NSScreen (IOSCompat)
|
||||
- (CGRect)bounds { return CGRectMake(0, 0, CGRectGetWidth(self.frame), CGRectGetHeight(self.frame)); }
|
||||
- (float) scale { return 1.0f; }
|
||||
@end
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef IOS
|
||||
|
||||
#import "views.h"
|
||||
|
||||
static const float ALMOST_INVISIBLE = .021f;
|
||||
static RAGameView* g_instance;
|
||||
static GLKView* g_view;
|
||||
static EAGLContext* g_context;
|
||||
static UIView* g_pause_view;
|
||||
static UIView* g_pause_indicator_view;
|
||||
|
||||
@ -33,16 +66,19 @@ static UIView* g_pause_indicator_view;
|
||||
|
||||
#include "apple_input.h"
|
||||
|
||||
static RAGameView* g_instance;
|
||||
static NSOpenGLContext* g_context;
|
||||
|
||||
#define g_view g_instance // < RAGameView is a container on iOS; on OSX these are both the same object
|
||||
static bool g_has_went_fullscreen;
|
||||
static NSOpenGLPixelFormat* g_format;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
static bool g_initialized;
|
||||
static RAGameView* g_instance;
|
||||
static GLContextClass* g_context;
|
||||
|
||||
static int g_fast_forward_skips;
|
||||
static bool g_is_syncing = true;
|
||||
static float g_screen_scale = 1.0f;
|
||||
|
||||
|
||||
@implementation RAGameView
|
||||
+ (RAGameView*)get
|
||||
@ -57,30 +93,22 @@ static float g_screen_scale = 1.0f;
|
||||
|
||||
- (id)init
|
||||
{
|
||||
static const NSOpenGLPixelFormatAttribute attributes [] = {
|
||||
NSOpenGLPFAWindow,
|
||||
NSOpenGLPFADoubleBuffer, // double buffered
|
||||
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer
|
||||
(NSOpenGLPixelFormatAttribute)nil
|
||||
};
|
||||
|
||||
self = [super initWithFrame:CGRectMake(0, 0, 100, 100) pixelFormat:[[NSOpenGLPixelFormat alloc] initWithAttributes:attributes]];
|
||||
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
|
||||
g_context = self.openGLContext;
|
||||
[g_context makeCurrentContext];
|
||||
|
||||
self = [super init];
|
||||
self.autoresizingMask = NSViewWidthSizable | NSViewHeightSizable;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setFrame:(NSRect)frameRect
|
||||
{
|
||||
[super setFrame:frameRect];
|
||||
|
||||
if (g_view && g_context)
|
||||
[g_context update];
|
||||
}
|
||||
|
||||
- (void)display
|
||||
{
|
||||
[self.openGLContext flushBuffer];
|
||||
}
|
||||
|
||||
- (void)bindDrawable
|
||||
{
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, 0);
|
||||
[g_context flushBuffer];
|
||||
}
|
||||
|
||||
// Stop the annoying sound when pressing a key
|
||||
@ -121,8 +149,6 @@ static float g_screen_scale = 1.0f;
|
||||
{
|
||||
self = [super init];
|
||||
|
||||
g_screen_scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
UINib* xib = [UINib nibWithNibName:@"PauseView" bundle:nil];
|
||||
g_pause_view = [[xib instantiateWithOwner:[RetroArch_iOS get] options:nil] lastObject];
|
||||
|
||||
@ -189,115 +215,189 @@ static float g_screen_scale = 1.0f;
|
||||
];
|
||||
}
|
||||
|
||||
- (void)suspend
|
||||
{
|
||||
g_view.context = nil;
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
}
|
||||
|
||||
- (void)resume
|
||||
{
|
||||
g_view.context = g_context;
|
||||
[EAGLContext setCurrentContext:g_context];
|
||||
}
|
||||
#endif
|
||||
|
||||
@end
|
||||
|
||||
// Realistically these functions don't create or destroy the view; just the OpenGL context.
|
||||
bool apple_init_game_view()
|
||||
static RAScreen* get_chosen_screen()
|
||||
{
|
||||
#ifdef IOS
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
unsigned monitor = g_settings.video.monitor_index;
|
||||
|
||||
if (monitor >= RAScreen.screens.count)
|
||||
{
|
||||
RARCH_WARN("video_monitor_index is greater than the number of connected monitors; using main screen instead.\n");
|
||||
return RAScreen.mainScreen;
|
||||
}
|
||||
|
||||
return RAScreen.screens[monitor];
|
||||
}
|
||||
|
||||
bool apple_gfx_ctx_init()
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
// Make sure the view was created
|
||||
[RAGameView get];
|
||||
|
||||
g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
[EAGLContext setCurrentContext:g_context];
|
||||
g_view.context = g_context;
|
||||
|
||||
// Show pause button for a few seconds, so people know it's there
|
||||
[RAGameView get];
|
||||
|
||||
#ifdef IOS // Show pause button for a few seconds, so people know it's there
|
||||
g_pause_indicator_view.alpha = 1.0f;
|
||||
[NSObject cancelPreviousPerformRequestsWithTarget:g_instance];
|
||||
[g_instance performSelector:@selector(hidePauseButton) withObject:g_instance afterDelay:3.0f];
|
||||
#endif
|
||||
});
|
||||
|
||||
[EAGLContext setCurrentContext:g_context];
|
||||
#else
|
||||
[g_context makeCurrentContext];
|
||||
#endif
|
||||
g_initialized = true;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
void apple_destroy_game_view()
|
||||
void apple_gfx_ctx_destroy()
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
// Clear the view, otherwise the last frame from this game will be displayed
|
||||
// briefly on the next game.
|
||||
[g_view bindDrawable];
|
||||
glClearColor(0, 0, 0, 1);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
[g_view display];
|
||||
|
||||
glFinish();
|
||||
|
||||
g_initialized = false;
|
||||
|
||||
[GLContextClass clearCurrentContext];
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
#ifdef IOS
|
||||
g_view.context = nil;
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
g_context = nil;
|
||||
#endif
|
||||
[GLContextClass clearCurrentContext];
|
||||
g_context = nil;
|
||||
});
|
||||
}
|
||||
|
||||
bool apple_gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor)
|
||||
{
|
||||
if (api != GLAPIType)
|
||||
return false;
|
||||
|
||||
|
||||
[GLContextClass clearCurrentContext];
|
||||
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
[GLContextClass clearCurrentContext];
|
||||
|
||||
#ifdef OSX
|
||||
[g_context clearDrawable];
|
||||
g_context = nil;
|
||||
g_format = nil;
|
||||
|
||||
NSOpenGLPixelFormatAttribute attributes [] = {
|
||||
NSOpenGLPFADoubleBuffer, // double buffered
|
||||
NSOpenGLPFADepthSize, (NSOpenGLPixelFormatAttribute)16, // 16 bit depth buffer
|
||||
(major || minor) ? NSOpenGLPFAOpenGLProfile : 0, (major << 12) | (minor << 8),
|
||||
(NSOpenGLPixelFormatAttribute)nil
|
||||
};
|
||||
|
||||
g_format = [[NSOpenGLPixelFormat alloc] initWithAttributes:attributes];
|
||||
g_context = [[NSOpenGLContext alloc] initWithFormat:g_format shareContext:nil];
|
||||
g_context.view = g_view;
|
||||
#else
|
||||
g_context = [[EAGLContext alloc] initWithAPI:kEAGLRenderingAPIOpenGLES2];
|
||||
g_view.context = g_context;
|
||||
#endif
|
||||
|
||||
[g_context makeCurrentContext];
|
||||
});
|
||||
|
||||
#ifdef IOS
|
||||
[EAGLContext setCurrentContext:nil];
|
||||
#else
|
||||
[NSOpenGLContext clearCurrentContext];
|
||||
#endif
|
||||
[g_context makeCurrentContext];
|
||||
return true;
|
||||
}
|
||||
|
||||
void apple_flip_game_view()
|
||||
{
|
||||
if (--g_fast_forward_skips < 0)
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(), ^{
|
||||
[g_view display];
|
||||
});
|
||||
g_fast_forward_skips = g_is_syncing ? 0 : 3;
|
||||
}
|
||||
}
|
||||
|
||||
void apple_set_game_view_sync(unsigned interval)
|
||||
void apple_gfx_ctx_swap_interval(unsigned interval)
|
||||
{
|
||||
#ifdef IOS // < No way to disable Vsync on iOS?
|
||||
// Just skip presents so fast forward still works.
|
||||
g_is_syncing = interval ? true : false;
|
||||
g_fast_forward_skips = interval ? 0 : 3;
|
||||
#elif defined(OSX)
|
||||
GLint value = interval ? 1 : 0;
|
||||
[g_view.openGLContext setValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||
[g_context setValues:&value forParameter:NSOpenGLCPSwapInterval];
|
||||
#endif
|
||||
}
|
||||
|
||||
void apple_get_game_view_size(unsigned *width, unsigned *height)
|
||||
bool apple_gfx_ctx_set_video_mode(unsigned width, unsigned height, bool fullscreen)
|
||||
{
|
||||
*width = g_view.bounds.size.width * g_screen_scale;
|
||||
*width = *width ? *width : 640;
|
||||
#ifdef OSX
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
// TODO: Sceen mode support
|
||||
|
||||
if (fullscreen && !g_has_went_fullscreen)
|
||||
{
|
||||
[g_view enterFullScreenMode:get_chosen_screen() 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 true;
|
||||
}
|
||||
|
||||
void apple_gfx_ctx_get_video_size(unsigned* width, unsigned* height)
|
||||
{
|
||||
RAScreen* screen = get_chosen_screen();
|
||||
CGRect size = g_initialized ? g_view.bounds : screen.bounds;
|
||||
|
||||
*width = CGRectGetWidth(size) * screen.scale;
|
||||
*height = CGRectGetHeight(size) * screen.scale;
|
||||
}
|
||||
|
||||
void apple_gfx_ctx_update_window_title(void)
|
||||
{
|
||||
#ifdef OSX
|
||||
static char buf[128];
|
||||
bool got_text = gfx_get_fps(buf, sizeof(buf), false);
|
||||
static const char* const text = buf; // < Can't access buf directly in the block
|
||||
|
||||
*height = g_view.bounds.size.height * g_screen_scale;
|
||||
*height = *height ? *height : 480;
|
||||
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
|
||||
}
|
||||
|
||||
void *apple_get_proc_address(const char *symbol_name)
|
||||
bool apple_gfx_ctx_has_focus(void)
|
||||
{
|
||||
#ifdef IOS
|
||||
(void)symbol_name; // We don't need symbols above GLES2 on iOS.
|
||||
return NULL;
|
||||
#else
|
||||
CFStringRef symbol = CFStringCreateWithCString(kCFAllocatorDefault, symbol_name, kCFStringEncodingASCII);
|
||||
void *proc = CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(CFSTR("com.apple.opengl")),
|
||||
symbol);
|
||||
CFRelease(symbol);
|
||||
return proc;
|
||||
#endif
|
||||
return APP_HAS_FOCUS;
|
||||
}
|
||||
|
||||
void apple_gfx_ctx_swap_buffers()
|
||||
{
|
||||
if (--g_fast_forward_skips < 0)
|
||||
{
|
||||
dispatch_sync(dispatch_get_main_queue(),
|
||||
^{
|
||||
[g_view display];
|
||||
});
|
||||
|
||||
g_fast_forward_skips = g_is_syncing ? 0 : 3;
|
||||
}
|
||||
}
|
||||
|
||||
gfx_ctx_proc_t apple_gfx_ctx_get_proc_address(const char *symbol_name)
|
||||
{
|
||||
return (gfx_ctx_proc_t)CFBundleGetFunctionPointerForName(CFBundleGetBundleWithIdentifier(GLFrameworkID),
|
||||
(__bridge CFStringRef)(@(symbol_name)));
|
||||
}
|
||||
|
||||
#ifdef IOS
|
@ -22,15 +22,23 @@
|
||||
#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 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;
|
||||
|
||||
- (void)createCustomConfig;
|
||||
- (void)deleteCustomConfig;
|
||||
- (bool)hasCustomConfig;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
@ -22,27 +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];
|
||||
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];
|
||||
}
|
||||
@ -56,9 +58,7 @@ static core_info_list_t* coreList;
|
||||
return moduleList;
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
}
|
||||
@implementation RAModuleInfo
|
||||
|
||||
- (id)copyWithZone:(NSZone *)zone
|
||||
{
|
||||
@ -70,6 +70,23 @@ static core_info_list_t* coreList;
|
||||
return does_core_support_file(self.info, path.UTF8String);
|
||||
}
|
||||
|
||||
- (void)createCustomConfig
|
||||
{
|
||||
if (!self.hasCustomConfig)
|
||||
[NSFileManager.defaultManager copyItemAtPath:apple_platform.globalConfigFile toPath:self.customConfigFile error:nil];
|
||||
}
|
||||
|
||||
- (void)deleteCustomConfig
|
||||
{
|
||||
if (self.hasCustomConfig)
|
||||
[NSFileManager.defaultManager removeItemAtPath:self.customConfigFile error:nil];
|
||||
}
|
||||
|
||||
- (bool)hasCustomConfig
|
||||
{
|
||||
return path_file_exists(self.customConfigFile.UTF8String);
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#ifdef IOS
|
||||
@ -114,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)];
|
||||
}
|
||||
|
@ -21,71 +21,42 @@
|
||||
#import <CoreFoundation/CoreFoundation.h>
|
||||
#import "RAModuleInfo.h"
|
||||
|
||||
void apple_run_core(RAModuleInfo* core, const char* file);
|
||||
#define GSEVENT_TYPE_KEYDOWN 10
|
||||
#define GSEVENT_TYPE_KEYUP 11
|
||||
|
||||
@protocol RetroArch_Platform
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
|
||||
- (void)unloadingCore:(RAModuleInfo*)core;
|
||||
- (NSString*)retroarchConfigPath;
|
||||
- (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
|
||||
#import "../iOS/platform.h"
|
||||
#elif defined(OSX)
|
||||
#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;
|
||||
extern RAModuleInfo* apple_core;
|
||||
|
||||
extern id<RetroArch_Platform> apple_platform;
|
||||
|
||||
#ifdef IOS
|
||||
// main.m
|
||||
enum basic_event_t { RESET = 1, LOAD_STATE = 2, SAVE_STATE = 3, QUIT = 4 };
|
||||
extern void apple_event_basic_command(void* userdata);
|
||||
extern void apple_event_set_state_slot(void* userdata);
|
||||
extern void apple_event_show_rgui(void* userdata);
|
||||
|
||||
// RAGameView.m
|
||||
@interface RAGameView : UIViewController
|
||||
+ (RAGameView*)get;
|
||||
- (void)openPauseMenu;
|
||||
- (void)closePauseMenu;
|
||||
|
||||
- (void)suspend;
|
||||
- (void)resume;
|
||||
@end
|
||||
|
||||
@interface RetroArch_iOS : UINavigationController<UIApplicationDelegate, UINavigationControllerDelegate, RetroArch_Platform>
|
||||
|
||||
+ (RetroArch_iOS*)get;
|
||||
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
|
||||
- (void)unloadingCore:(RAModuleInfo*)core;
|
||||
- (NSString*)retroarchConfigPath;
|
||||
|
||||
- (void)refreshConfig;
|
||||
- (void)refreshSystemConfig;
|
||||
|
||||
@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
|
||||
|
||||
@end
|
||||
|
||||
#elif defined(OSX)
|
||||
|
||||
#import <AppKit/AppKit.h>
|
||||
|
||||
@interface RAGameView : NSOpenGLView
|
||||
|
||||
+ (RAGameView*)get;
|
||||
- (void)display;
|
||||
|
||||
@end
|
||||
|
||||
@interface RetroArch_OSX : NSObject<RetroArch_Platform, NSApplicationDelegate>
|
||||
{
|
||||
@public
|
||||
NSWindow IBOutlet *window;
|
||||
}
|
||||
|
||||
+ (RetroArch_OSX*)get;
|
||||
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
|
||||
- (void)unloadingCore:(RAModuleInfo*)core;
|
||||
|
||||
@end
|
||||
|
||||
#endif
|
||||
extern void apple_refresh_config();
|
||||
extern void apple_enter_stasis();
|
||||
extern void apple_exit_stasis(bool reload_config);
|
||||
extern void apple_run_core(RAModuleInfo* core, const char* file);
|
||||
|
||||
// utility.m
|
||||
extern void apple_display_alert(NSString* message, NSString* title);
|
||||
@ -93,4 +64,7 @@ extern void objc_clear_config_hack();
|
||||
extern bool path_make_and_check_directory(const char* path, mode_t mode, int amode);
|
||||
extern NSString* objc_get_value_from_config(config_file_t* config, NSString* name, NSString* defaultValue);
|
||||
|
||||
// frontend/platform/platform_apple.c
|
||||
extern void apple_frontend_post_event(void (*fn)(void*), void* userdata);
|
||||
|
||||
#endif
|
@ -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 }
|
||||
};
|
@ -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
|
@ -17,16 +17,17 @@
|
||||
#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/btpad.c"
|
||||
#include "apple/iOS/bluetooth/btpad_queue.c"
|
||||
#elif defined(OSX)
|
||||
#include "../OSX/hid_pad.c"
|
||||
#endif
|
||||
|
||||
#include "apple/common/hidpad/wiimote.c"
|
||||
#include "apple/common/hidpad/hidpad_ps3.c"
|
||||
#include "apple/common/hidpad/hidpad_wii.c"
|
||||
|
||||
|
||||
static bool apple_joypad_init(void)
|
||||
{
|
||||
@ -56,7 +57,7 @@ static bool apple_joypad_button(unsigned port, uint16_t joykey)
|
||||
|
||||
static int16_t apple_joypad_axis(unsigned port, uint32_t joyaxis)
|
||||
{
|
||||
if (joyaxis == AXIS_NONE || port != 0)
|
||||
if (joyaxis == AXIS_NONE)
|
||||
return 0;
|
||||
|
||||
int16_t val = 0;
|
32
apple/common/hidpad/hidpad.h
Normal file
32
apple/common/hidpad/hidpad.h
Normal file
@ -0,0 +1,32 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013 - Jason Fetters
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __IOS_RARCH_HIDPAD_H__
|
||||
#define __IOS_RARCH_HIDPAD_H__
|
||||
|
||||
struct hidpad_connection;
|
||||
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size);
|
||||
|
||||
struct hidpad_interface
|
||||
{
|
||||
void* (*connect)(struct hidpad_connection* connection, uint32_t slot);
|
||||
void (*disconnect)(void* device);
|
||||
void (*packet_handler)(void* device, uint8_t *packet, uint16_t size);
|
||||
};
|
||||
|
||||
extern struct hidpad_interface hidpad_wii;
|
||||
extern struct hidpad_interface hidpad_ps3;
|
||||
|
||||
#endif
|
@ -18,26 +18,23 @@
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "boolean.h"
|
||||
#include "../../../RetroArch/rarch_wrapper.h"
|
||||
#include "apple/common/rarch_wrapper.h"
|
||||
|
||||
#include "btdynamic.h"
|
||||
#include "btpad.h"
|
||||
#include "hidpad.h"
|
||||
|
||||
struct btpad_ps3_data
|
||||
struct hidpad_ps3_data
|
||||
{
|
||||
struct hidpad_connection* connection;
|
||||
|
||||
uint8_t data[512];
|
||||
|
||||
bd_addr_t address;
|
||||
uint32_t handle;
|
||||
uint32_t channels[2];
|
||||
|
||||
|
||||
uint32_t slot;
|
||||
bool have_led;
|
||||
};
|
||||
|
||||
static void btpad_ps3_send_control(struct btpad_ps3_data* device)
|
||||
static void hidpad_ps3_send_control(struct hidpad_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,
|
||||
@ -52,35 +49,38 @@ static void btpad_ps3_send_control(struct btpad_ps3_data* device)
|
||||
};
|
||||
|
||||
report_buffer[11] = 1 << ((device->slot % 4) + 1);
|
||||
bt_send_l2cap_ptr(device->channels[0], report_buffer, sizeof(report_buffer));
|
||||
#ifdef IOS
|
||||
hidpad_send_control(device->connection, report_buffer, sizeof(report_buffer));
|
||||
#else
|
||||
hidpad_send_control(device->connection, report_buffer + 1, sizeof(report_buffer) - 1);
|
||||
#endif
|
||||
}
|
||||
|
||||
static void* btpad_ps3_connect(const btpad_connection_t* connection)
|
||||
static void* hidpad_ps3_connect(struct hidpad_connection* connection, uint32_t slot)
|
||||
{
|
||||
struct btpad_ps3_data* device = malloc(sizeof(struct btpad_ps3_data));
|
||||
struct hidpad_ps3_data* device = malloc(sizeof(struct hidpad_ps3_data));
|
||||
memset(device, 0, sizeof(*device));
|
||||
|
||||
memcpy(device->address, connection->address, BD_ADDR_LEN);
|
||||
device->handle = connection->handle;
|
||||
device->channels[0] = connection->channels[0];
|
||||
device->channels[1] = connection->channels[1];
|
||||
device->slot = connection->slot;
|
||||
device->connection = connection;
|
||||
device->slot = slot;
|
||||
|
||||
// Magic packet to start reports
|
||||
#ifdef IOS
|
||||
static uint8_t data[] = {0x53, 0xF4, 0x42, 0x03, 0x00, 0x00};
|
||||
bt_send_l2cap_ptr(device->channels[0], data, 6);
|
||||
hidpad_send_control(device->connection, data, 6);
|
||||
#endif
|
||||
|
||||
// Without this the digital buttons won't be reported
|
||||
btpad_ps3_send_control(device);
|
||||
hidpad_ps3_send_control(device);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void btpad_ps3_disconnect(struct btpad_ps3_data* device)
|
||||
static void hidpad_ps3_disconnect(struct hidpad_ps3_data* device)
|
||||
{
|
||||
free(device);
|
||||
}
|
||||
|
||||
static uint32_t btpad_ps3_get_buttons(struct btpad_ps3_data* device)
|
||||
static uint32_t hidpad_ps3_get_buttons(struct hidpad_ps3_data* device)
|
||||
{
|
||||
#define KEY(X) RETRO_DEVICE_ID_JOYPAD_##X
|
||||
static const uint32_t button_mapping[17] =
|
||||
@ -102,7 +102,7 @@ static uint32_t btpad_ps3_get_buttons(struct btpad_ps3_data* device)
|
||||
return result;
|
||||
}
|
||||
|
||||
static int16_t btpad_ps3_get_axis(struct btpad_ps3_data* device, unsigned axis)
|
||||
static int16_t hidpad_ps3_get_axis(struct hidpad_ps3_data* device, unsigned axis)
|
||||
{
|
||||
if (axis < 4)
|
||||
{
|
||||
@ -114,28 +114,28 @@ static int16_t btpad_ps3_get_axis(struct btpad_ps3_data* device, unsigned axis)
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btpad_ps3_packet_handler(struct btpad_ps3_data* device, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
static void hidpad_ps3_packet_handler(struct hidpad_ps3_data* device, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
if (packet_type == L2CAP_DATA_PACKET && packet[0] == 0xA1)
|
||||
if (!device->have_led)
|
||||
{
|
||||
if (!device->have_led)
|
||||
{
|
||||
btpad_ps3_send_control(device);
|
||||
device->have_led = true;
|
||||
}
|
||||
|
||||
memcpy(device->data, packet, size);
|
||||
g_current_input_data.pad_buttons[device->slot] = btpad_ps3_get_buttons(device);
|
||||
for (int i = 0; i < 4; i ++)
|
||||
g_current_input_data.pad_axis[device->slot][i] = btpad_ps3_get_axis(device, i);
|
||||
hidpad_ps3_send_control(device);
|
||||
device->have_led = true;
|
||||
}
|
||||
|
||||
#ifdef IOS
|
||||
memcpy(device->data, packet, size);
|
||||
#else
|
||||
memcpy(device->data + 1, packet, size);
|
||||
#endif
|
||||
|
||||
g_current_input_data.pad_buttons[device->slot] = hidpad_ps3_get_buttons(device);
|
||||
for (int i = 0; i < 4; i ++)
|
||||
g_current_input_data.pad_axis[device->slot][i] = hidpad_ps3_get_axis(device, i);
|
||||
}
|
||||
|
||||
struct btpad_interface btpad_ps3 =
|
||||
struct hidpad_interface hidpad_ps3 =
|
||||
{
|
||||
(void*)&btpad_ps3_connect,
|
||||
(void*)&btpad_ps3_disconnect,
|
||||
(void*)&btpad_ps3_get_buttons,
|
||||
(void*)&btpad_ps3_get_axis,
|
||||
(void*)&btpad_ps3_packet_handler
|
||||
(void*)&hidpad_ps3_connect,
|
||||
(void*)&hidpad_ps3_disconnect,
|
||||
(void*)&hidpad_ps3_packet_handler
|
||||
};
|
113
apple/common/hidpad/hidpad_wii.c
Normal file
113
apple/common/hidpad/hidpad_wii.c
Normal file
@ -0,0 +1,113 @@
|
||||
/* 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 <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "boolean.h"
|
||||
#include "apple/common/rarch_wrapper.h"
|
||||
|
||||
#include "wiimote.h"
|
||||
#include "hidpad.h"
|
||||
|
||||
static void* hidpad_wii_connect(struct hidpad_connection* connection, uint32_t slot)
|
||||
{
|
||||
struct wiimote_t* device = malloc(sizeof(struct wiimote_t));
|
||||
memset(device, 0, sizeof(struct wiimote_t));
|
||||
|
||||
device->connection = connection;
|
||||
device->unid = slot;
|
||||
device->state = WIIMOTE_STATE_CONNECTED;
|
||||
device->exp.type = EXP_NONE;
|
||||
|
||||
wiimote_handshake(device, -1, NULL, -1);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void hidpad_wii_disconnect(struct wiimote_t* device)
|
||||
{
|
||||
free(device);
|
||||
}
|
||||
|
||||
static int16_t hidpad_wii_get_axis(struct wiimote_t* device, unsigned axis)
|
||||
{
|
||||
/* TODO
|
||||
if (device->.exp.type == EXP_CLASSIC)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case 0: return device->wiimote.exp.classic.ljs.rx * 0x7FFF;
|
||||
case 1: return device->wiimote.exp.classic.ljs.ry * 0x7FFF;
|
||||
case 2: return device->wiimote.exp.classic.rjs.rx * 0x7FFF;
|
||||
case 3: return device->wiimote.exp.classic.rjs.ry * 0x7FFF;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void hidpad_wii_packet_handler(struct wiimote_t* device, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
#ifdef IOS
|
||||
byte* msg = packet + 2;
|
||||
switch (packet[1])
|
||||
#else
|
||||
byte* msg = packet + 1;
|
||||
switch (packet[0])
|
||||
#endif
|
||||
{
|
||||
case WM_RPT_BTN:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_READ:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handshake(device, WM_RPT_READ, msg + 5, ((msg[2] & 0xF0) >> 4) + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handshake(device,WM_RPT_CTRL_STATUS,msg,-1);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_BTN_EXP:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handle_expansion(device, msg+2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_current_input_data.pad_buttons[device->unid] = device->btns | (device->exp.classic.btns << 16);
|
||||
for (int i = 0; i < 4; i ++)
|
||||
g_current_input_data.pad_axis[device->unid][i] = hidpad_wii_get_axis(device, i);
|
||||
}
|
||||
|
||||
struct hidpad_interface hidpad_wii =
|
||||
{
|
||||
(void*)&hidpad_wii_connect,
|
||||
(void*)&hidpad_wii_disconnect,
|
||||
(void*)&hidpad_wii_packet_handler
|
||||
};
|
@ -45,8 +45,6 @@
|
||||
#include <unistd.h>
|
||||
#include "boolean.h"
|
||||
|
||||
#include "btdynamic.h"
|
||||
#include "btstack/btstack.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len);
|
||||
@ -360,7 +358,11 @@ int wiimote_send(struct wiimote_t* wm, byte report_type, byte* msg, int len)
|
||||
printf("\n");
|
||||
#endif
|
||||
|
||||
bt_send_l2cap_ptr( wm->c_source_cid, buf, len+2);
|
||||
#ifdef IOS
|
||||
hidpad_send_control(wm->connection, buf, len + 2);
|
||||
#else
|
||||
hidpad_send_control(wm->connection, buf + 1, len + 1);
|
||||
#endif
|
||||
return 1;
|
||||
}
|
||||
|
@ -41,7 +41,7 @@
|
||||
#ifndef __WIIMOTE_H__
|
||||
#define __WIIMOTE_H__
|
||||
|
||||
#include "btstack/utils.h"
|
||||
#include "hidpad.h"
|
||||
|
||||
#if defined(__cplusplus)
|
||||
extern "C" {
|
||||
@ -232,11 +232,7 @@ extern "C" {
|
||||
typedef struct wiimote_t {
|
||||
int unid; /**< user specified id */
|
||||
|
||||
uint16_t wiiMoteConHandle;
|
||||
uint16_t i_source_cid;
|
||||
uint16_t c_source_cid;
|
||||
bd_addr_t addr;
|
||||
|
||||
struct hidpad_connection* connection;
|
||||
int state; /**< various state flags */
|
||||
byte leds; /**< currently lit leds */
|
||||
float battery_level; /**< battery level */
|
@ -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
222
apple/common/keycode.inc
Normal 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";
|
||||
}
|
184
apple/common/main.m
Normal file
184
apple/common/main.m
Normal file
@ -0,0 +1,184 @@
|
||||
/* 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 <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#import "RetroArch_Apple.h"
|
||||
#include "rarch_wrapper.h"
|
||||
|
||||
#include "apple_input.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
char** apple_argv;
|
||||
|
||||
id<RetroArch_Platform> apple_platform;
|
||||
|
||||
void apple_event_basic_command(void* userdata)
|
||||
{
|
||||
switch ((enum basic_event_t)userdata)
|
||||
{
|
||||
case RESET: rarch_game_reset(); return;
|
||||
case LOAD_STATE: rarch_load_state(); return;
|
||||
case SAVE_STATE: rarch_save_state(); return;
|
||||
case QUIT: g_extern.system.shutdown = true; return;
|
||||
}
|
||||
}
|
||||
|
||||
void apple_event_set_state_slot(void* userdata)
|
||||
{
|
||||
g_extern.state_slot = (uint32_t)userdata;
|
||||
}
|
||||
|
||||
void apple_event_show_rgui(void* userdata)
|
||||
{
|
||||
const bool in_menu = g_extern.lifecycle_mode_state & (1 << MODE_MENU);
|
||||
g_extern.lifecycle_mode_state &= ~(1ULL << (in_menu ? MODE_MENU : MODE_GAME));
|
||||
g_extern.lifecycle_mode_state |= (1ULL << (in_menu ? MODE_GAME : MODE_MENU));
|
||||
}
|
||||
|
||||
static void event_reload_config(void* userdata)
|
||||
{
|
||||
objc_clear_config_hack();
|
||||
|
||||
uninit_drivers();
|
||||
config_load();
|
||||
init_drivers();
|
||||
}
|
||||
|
||||
void apple_refresh_config()
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&event_reload_config, 0);
|
||||
else
|
||||
objc_clear_config_hack();
|
||||
}
|
||||
|
||||
pthread_mutex_t stasis_mutex = PTHREAD_MUTEX_INITIALIZER;
|
||||
|
||||
static void event_stasis(void* userdata)
|
||||
{
|
||||
uninit_drivers();
|
||||
pthread_mutex_lock(&stasis_mutex);
|
||||
pthread_mutex_unlock(&stasis_mutex);
|
||||
init_drivers();
|
||||
}
|
||||
|
||||
void apple_enter_stasis()
|
||||
{
|
||||
if (apple_is_running)
|
||||
{
|
||||
pthread_mutex_lock(&stasis_mutex);
|
||||
apple_frontend_post_event(event_stasis, 0);
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
#pragma mark EMULATION
|
||||
static pthread_t apple_retro_thread;
|
||||
bool apple_is_paused;
|
||||
bool apple_is_running;
|
||||
bool apple_use_tv_mode;
|
||||
RAModuleInfo* apple_core;
|
||||
|
||||
void* rarch_main_spring(void* args)
|
||||
{
|
||||
char** argv = args;
|
||||
|
||||
uint32_t argc = 0;
|
||||
while (argv && argv[argc]) argc++;
|
||||
|
||||
if (rarch_main(argc, argv))
|
||||
{
|
||||
rarch_main_clear_state();
|
||||
dispatch_async_f(dispatch_get_main_queue(), (void*)1, apple_rarch_exited);
|
||||
}
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void apple_run_core(RAModuleInfo* core, const char* file)
|
||||
{
|
||||
if (!apple_is_running)
|
||||
{
|
||||
[apple_platform loadingCore:core withFile: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];
|
||||
|
||||
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)
|
||||
{
|
||||
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, apple_argv))
|
||||
{
|
||||
apple_argv = 0;
|
||||
|
||||
apple_rarch_exited((void*)1);
|
||||
return;
|
||||
}
|
||||
|
||||
apple_argv = 0;
|
||||
|
||||
pthread_detach(apple_retro_thread);
|
||||
}
|
||||
}
|
||||
|
||||
void apple_rarch_exited(void* result)
|
||||
{
|
||||
if (result)
|
||||
apple_display_alert(@"Failed to load game.", 0);
|
||||
|
||||
RAModuleInfo* used_core = apple_core;
|
||||
apple_core = nil;
|
||||
|
||||
if (apple_is_running)
|
||||
{
|
||||
apple_is_running = false;
|
||||
[apple_platform unloadingCore:used_core];
|
||||
}
|
||||
|
||||
if (apple_use_tv_mode)
|
||||
apple_run_core(nil, 0);
|
||||
}
|
@ -17,19 +17,25 @@
|
||||
#ifndef __APPLE_RARCH_WRAPPER_H__
|
||||
#define __APPLE_RARCH_WRAPPER_H__
|
||||
|
||||
#include "gfx/gfx_context.h"
|
||||
|
||||
// The result needs to be free()'d
|
||||
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
|
||||
bool apple_init_game_view(void);
|
||||
void apple_destroy_game_view(void);
|
||||
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_get_proc_address(const char *symbol_name);
|
||||
// These functions must only be called in gfx/context/apple_gl_context.c
|
||||
bool apple_gfx_ctx_init();
|
||||
void apple_gfx_ctx_destroy();
|
||||
bool apple_gfx_ctx_bind_api(enum gfx_ctx_api api, unsigned major, unsigned minor);
|
||||
void apple_gfx_ctx_swap_interval(unsigned interval);
|
||||
bool apple_gfx_ctx_set_video_mode(unsigned width, unsigned height, bool fullscreen);
|
||||
void apple_gfx_ctx_get_video_size(unsigned* width, unsigned* height);
|
||||
void apple_gfx_ctx_update_window_title(void);
|
||||
bool apple_gfx_ctx_has_focus(void);
|
||||
void apple_gfx_ctx_swap_buffers();
|
||||
gfx_ctx_proc_t apple_gfx_ctx_get_proc_address(const char *symbol_name);
|
||||
|
||||
#ifdef IOS
|
||||
void apple_bind_game_view_fbo(void);
|
@ -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_UP], 1, "up", "Up D-pad")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_DOWN], 1, "down", "Down D-pad")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_LEFT], 1, "left", "Left D-pad")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_RIGHT], 1, "right", "Right D-pad")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_SELECT],1, "select", "Select button")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_START], 1, "start", "Start button")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_B], 1, "b", "B button (down)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_A], 1, "a", "A button (right)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_X], 1, "x", "X button (top)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_Y], 1, "y", "Y button (left)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L], 1, "l", "L button (left shoulder)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R], 1, "r", "R button (right shoulder)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L2], 1, "l2", "L2 button (left shoulder #2)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R2], 1, "r2", "R2 button (right shoulder #2)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_L3], 1, "l3", "L3 button (left analog button)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RETRO_DEVICE_ID_JOYPAD_R3], 1, "r3", "R3 button (right analog button)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_Y_MINUS], 1, "l_y_minus", "Left analog Y- (up)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_Y_PLUS], 1, "l_y_plus", "Left analog Y+ (down)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_X_MINUS], 1, "l_x_minus", "Left analog X- (left)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_LEFT_X_PLUS], 1, "l_x_plus", "Left analog X+ (right)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_Y_MINUS], 1, "r_y_minus", "Right analog Y- (up)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_Y_PLUS], 1, "r_y_plus", "Right analog Y+ (down)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_X_MINUS], 1, "r_x_minus", "Right analog X- (left)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_ANALOG_RIGHT_X_PLUS], 1, "r_x_plus", "Right analog X+ (right)")
|
||||
CONFIG_BIND(g_settings.input.binds[0][RARCH_TURBO_ENABLE], 1, "turbo", "Turbo enable")
|
||||
END_SUB_GROUP()
|
||||
END_GROUP()
|
||||
|
||||
@ -266,4 +337,11 @@ const rarch_setting_t setting_data[] =
|
||||
{ 0 }
|
||||
};
|
||||
|
||||
// HACK
|
||||
#undef g_settings
|
||||
#undef g_extern
|
||||
|
||||
// Keyboard
|
||||
#include "keycode.h"
|
||||
|
||||
#endif
|
@ -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
|
@ -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);
|
||||
}
|
||||
|
@ -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"
|
@ -20,15 +20,39 @@
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../../../RetroArch/rarch_wrapper.h"
|
||||
#include "apple/common/rarch_wrapper.h"
|
||||
#include "apple/common/hidpad/hidpad.h"
|
||||
#include "btdynamic.h"
|
||||
#include "btpad.h"
|
||||
#include "btpad_queue.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
static btpad_connection_t btpad_connection[MAX_PADS];
|
||||
static struct btpad_interface* btpad_iface[MAX_PADS];
|
||||
static void* btpad_device[MAX_PADS];
|
||||
// Private interface
|
||||
enum btpad_state { BTPAD_EMPTY, BTPAD_CONNECTING, BTPAD_CONNECTED };
|
||||
|
||||
struct hidpad_connection
|
||||
{
|
||||
uint32_t slot;
|
||||
|
||||
struct hidpad_interface* interface;
|
||||
void* hidpad;
|
||||
|
||||
enum btpad_state state;
|
||||
|
||||
bool has_address;
|
||||
bd_addr_t address;
|
||||
|
||||
uint16_t handle;
|
||||
uint16_t channels[2]; //0: Control, 1: Interrupt
|
||||
};
|
||||
|
||||
static struct hidpad_connection g_connected_pads[MAX_PADS];
|
||||
|
||||
void hidpad_send_control(struct hidpad_connection* connection, uint8_t* data, size_t size)
|
||||
{
|
||||
bt_send_l2cap_ptr(connection->channels[0], data, size);
|
||||
}
|
||||
|
||||
|
||||
static bool inquiry_off;
|
||||
static bool inquiry_running;
|
||||
|
||||
@ -41,35 +65,18 @@ void btpad_set_inquiry_state(bool on)
|
||||
btpad_queue_hci_inquiry(HCI_INQUIRY_LAP, 3, 1);
|
||||
}
|
||||
|
||||
// MAIN THREAD ONLY
|
||||
uint32_t btpad_get_buttons(uint32_t slot)
|
||||
{
|
||||
if (slot < MAX_PADS && btpad_device[slot] && btpad_iface[slot])
|
||||
return btpad_iface[slot]->get_buttons(btpad_device[slot]);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
int16_t btpad_get_axis(uint32_t slot, unsigned axis)
|
||||
{
|
||||
if (slot < MAX_PADS && btpad_device[slot] && btpad_iface[slot])
|
||||
return btpad_iface[slot]->get_axis(btpad_device[slot], axis);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
// Internal interface:
|
||||
static int32_t btpad_find_slot_for(uint16_t handle, bd_addr_t address)
|
||||
{
|
||||
for (int i = 0; i < MAX_PADS; i ++)
|
||||
{
|
||||
if (!btpad_connection[i].handle && !btpad_connection[i].has_address)
|
||||
if (!g_connected_pads[i].handle && !g_connected_pads[i].has_address)
|
||||
continue;
|
||||
|
||||
if (handle && btpad_connection[i].handle && handle != btpad_connection[i].handle)
|
||||
if (handle && g_connected_pads[i].handle && handle != g_connected_pads[i].handle)
|
||||
continue;
|
||||
|
||||
if (address && btpad_connection[i].has_address && (BD_ADDR_CMP(address, btpad_connection[i].address)))
|
||||
if (address && g_connected_pads[i].has_address && (BD_ADDR_CMP(address, g_connected_pads[i].address)))
|
||||
continue;
|
||||
|
||||
return i;
|
||||
@ -81,7 +88,7 @@ static int32_t btpad_find_slot_for(uint16_t handle, bd_addr_t address)
|
||||
static int32_t btpad_find_slot_with_state(enum btpad_state state)
|
||||
{
|
||||
for (int i = 0; i < MAX_PADS; i ++)
|
||||
if (btpad_connection[i].state == state)
|
||||
if (g_connected_pads[i].state == state)
|
||||
return i;
|
||||
|
||||
return -1;
|
||||
@ -92,19 +99,16 @@ static void btpad_disconnect_pad(uint32_t slot)
|
||||
if (slot > MAX_PADS)
|
||||
return;
|
||||
|
||||
if (btpad_iface[slot] && btpad_device[slot])
|
||||
if (g_connected_pads[slot].interface && g_connected_pads[slot].hidpad)
|
||||
{
|
||||
ios_add_log_message("BTpad: Disconnecting slot %d", slot);
|
||||
|
||||
btpad_iface[slot]->disconnect(btpad_device[slot]);
|
||||
btpad_device[slot] = 0;
|
||||
btpad_iface[slot] = 0;
|
||||
g_connected_pads[slot].interface->disconnect(g_connected_pads[slot].hidpad);
|
||||
}
|
||||
|
||||
if (btpad_connection[slot].handle)
|
||||
btpad_queue_hci_disconnect(btpad_connection[slot].handle, 0x15);
|
||||
if (g_connected_pads[slot].handle)
|
||||
btpad_queue_hci_disconnect(g_connected_pads[slot].handle, 0x15);
|
||||
|
||||
memset(&btpad_connection[slot], 0, sizeof(btpad_connection_t));
|
||||
memset(&g_connected_pads[slot], 0, sizeof(struct hidpad_connection));
|
||||
}
|
||||
|
||||
static void btpad_disconnect_all_pads()
|
||||
@ -134,7 +138,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
btpad_queue_run(1);
|
||||
}
|
||||
else if(packet[2] > HCI_STATE_WORKING && btpad_iface && btpad_device)
|
||||
else if(packet[2] > HCI_STATE_WORKING)
|
||||
{
|
||||
btpad_disconnect_all_pads();
|
||||
}
|
||||
@ -171,14 +175,14 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
{
|
||||
ios_add_log_message("BTpad: Inquiry found device (Slot %d)", slot);
|
||||
|
||||
memcpy(btpad_connection[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
memcpy(g_connected_pads[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
|
||||
btpad_connection[slot].has_address = true;
|
||||
btpad_connection[slot].state = BTPAD_CONNECTING;
|
||||
btpad_connection[slot].slot = slot;
|
||||
g_connected_pads[slot].has_address = true;
|
||||
g_connected_pads[slot].state = BTPAD_CONNECTING;
|
||||
g_connected_pads[slot].slot = slot;
|
||||
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, btpad_connection[slot].address, PSM_HID_CONTROL);
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, btpad_connection[slot].address, PSM_HID_INTERRUPT);
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, g_connected_pads[slot].address, PSM_HID_CONTROL);
|
||||
bt_send_cmd_ptr(l2cap_create_channel_ptr, g_connected_pads[slot].address, PSM_HID_INTERRUPT);
|
||||
}
|
||||
}
|
||||
}
|
||||
@ -213,19 +217,19 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
}
|
||||
|
||||
ios_add_log_message("BTpad: L2CAP channel opened: (Slot: %d, PSM: %02X)", slot, psm);
|
||||
btpad_connection[slot].handle = handle;
|
||||
g_connected_pads[slot].handle = handle;
|
||||
|
||||
if (psm == PSM_HID_CONTROL)
|
||||
btpad_connection[slot].channels[0] = channel_id;
|
||||
g_connected_pads[slot].channels[0] = channel_id;
|
||||
else if (psm == PSM_HID_INTERRUPT)
|
||||
btpad_connection[slot].channels[1] = channel_id;
|
||||
g_connected_pads[slot].channels[1] = channel_id;
|
||||
else
|
||||
ios_add_log_message("BTpad: Got unknown L2CAP PSM, ignoring (Slot: %d, PSM: %02X)", slot, psm);
|
||||
|
||||
if (btpad_connection[slot].channels[0] && btpad_connection[slot].channels[1])
|
||||
if (g_connected_pads[slot].channels[0] && g_connected_pads[slot].channels[1])
|
||||
{
|
||||
ios_add_log_message("BTpad: Got both L2CAP channels, requesting name (Slot: %d)", slot);
|
||||
btpad_queue_hci_remote_name_request(btpad_connection[slot].address, 0, 0, 0);
|
||||
btpad_queue_hci_remote_name_request(g_connected_pads[slot].address, 0, 0, 0);
|
||||
}
|
||||
}
|
||||
else
|
||||
@ -249,12 +253,12 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
{
|
||||
ios_add_log_message("BTpad: Got new incoming connection (Slot: %d)", slot);
|
||||
|
||||
memcpy(btpad_connection[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
memcpy(g_connected_pads[slot].address, event_addr, sizeof(bd_addr_t));
|
||||
|
||||
btpad_connection[slot].has_address = true;
|
||||
btpad_connection[slot].handle = handle;
|
||||
btpad_connection[slot].state = BTPAD_CONNECTING;
|
||||
btpad_connection[slot].slot = slot;
|
||||
g_connected_pads[slot].has_address = true;
|
||||
g_connected_pads[slot].handle = handle;
|
||||
g_connected_pads[slot].state = BTPAD_CONNECTING;
|
||||
g_connected_pads[slot].slot = slot;
|
||||
}
|
||||
else break;
|
||||
}
|
||||
@ -277,14 +281,14 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
|
||||
ios_add_log_message("BTpad: Got %.200s (Slot: %d)", (char*)&packet[9], slot);
|
||||
if (strncmp((char*)&packet[9], "PLAYSTATION(R)3 Controller", 26) == 0)
|
||||
btpad_iface[slot] = &btpad_ps3;
|
||||
g_connected_pads[slot].interface = &hidpad_ps3;
|
||||
else if (strncmp((char*)&packet[9], "Nintendo RVL-CNT-01", 19) == 0)
|
||||
btpad_iface[slot] = &btpad_wii;
|
||||
g_connected_pads[slot].interface = &hidpad_wii;
|
||||
|
||||
if (btpad_iface[slot])
|
||||
if (g_connected_pads[slot].interface)
|
||||
{
|
||||
btpad_device[slot] = btpad_iface[slot]->connect(&btpad_connection[slot]);
|
||||
btpad_connection[slot].state = BTPAD_CONNECTED;
|
||||
g_connected_pads[slot].hidpad = g_connected_pads[slot].interface->connect(&g_connected_pads[slot], slot);
|
||||
g_connected_pads[slot].state = BTPAD_CONNECTED;
|
||||
}
|
||||
}
|
||||
break;
|
||||
@ -307,7 +311,7 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
const int32_t slot = btpad_find_slot_for(handle, 0);
|
||||
if (slot >= 0)
|
||||
{
|
||||
btpad_connection[slot].handle = 0;
|
||||
g_connected_pads[slot].handle = 0;
|
||||
btpad_disconnect_pad(slot);
|
||||
|
||||
ios_add_log_message("BTpad: Device disconnected (Slot: %d)", slot);
|
||||
@ -326,8 +330,14 @@ void btpad_packet_handler(uint8_t packet_type, uint16_t channel, uint8_t *packet
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
for (int i = 0; i < MAX_PADS; i ++)
|
||||
if (btpad_device[i] && btpad_iface[i] && (btpad_connection[i].channels[0] == channel || btpad_connection[i].channels[1] == channel))
|
||||
btpad_iface[i]->packet_handler(btpad_device[i], packet_type, channel, packet, size);
|
||||
else if (packet_type == L2CAP_DATA_PACKET)
|
||||
{
|
||||
for (int i = 0; i < MAX_PADS; i ++)
|
||||
{
|
||||
struct hidpad_connection* connection = &g_connected_pads[i];
|
||||
|
||||
if (connection->hidpad && connection->interface && (connection->channels[0] == channel || connection->channels[1] == channel))
|
||||
connection->interface->packet_handler(connection->hidpad, packet, size);
|
||||
}
|
||||
}
|
||||
}
|
@ -20,39 +20,4 @@
|
||||
|
||||
void btpad_set_inquiry_state(bool on);
|
||||
|
||||
uint32_t btpad_get_buttons(uint32_t slot);
|
||||
int16_t btpad_get_axis(uint32_t slot, unsigned axis);
|
||||
|
||||
// Private interface
|
||||
enum btpad_state { BTPAD_EMPTY, BTPAD_CONNECTING, BTPAD_CONNECTED };
|
||||
|
||||
typedef struct
|
||||
{
|
||||
enum btpad_state state;
|
||||
|
||||
uint32_t slot;
|
||||
uint16_t handle;
|
||||
|
||||
bool has_address;
|
||||
bd_addr_t address;
|
||||
|
||||
uint16_t channels[2]; //0: Control, 1: Interrupt
|
||||
|
||||
bool connected;
|
||||
} btpad_connection_t;
|
||||
|
||||
struct btpad_interface
|
||||
{
|
||||
void* (*connect)(const btpad_connection_t* connection);
|
||||
void (*disconnect)(void* device);
|
||||
|
||||
uint32_t (*get_buttons)(void* device);
|
||||
int16_t (*get_axis)(void* device, unsigned axis);
|
||||
|
||||
void (*packet_handler)(void* device, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size);
|
||||
};
|
||||
|
||||
extern struct btpad_interface btpad_ps3;
|
||||
extern struct btpad_interface btpad_wii;
|
||||
|
||||
#endif
|
@ -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 = nil;
|
||||
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];
|
||||
}
|
||||
|
@ -1,123 +0,0 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013 - Jason Fetters
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "boolean.h"
|
||||
#include "../../../RetroArch/rarch_wrapper.h"
|
||||
|
||||
#include "btdynamic.h"
|
||||
#include "btpad.h"
|
||||
#include "wiimote.h"
|
||||
|
||||
static void* btpad_wii_connect(const btpad_connection_t* connection)
|
||||
{
|
||||
struct wiimote_t* device = malloc(sizeof(struct wiimote_t));
|
||||
memset(device, 0, sizeof(struct wiimote_t));
|
||||
|
||||
memcpy(device->addr, connection->address, BD_ADDR_LEN);
|
||||
|
||||
device->unid = connection->slot;
|
||||
device->wiiMoteConHandle = connection->handle;
|
||||
device->c_source_cid = connection->channels[0];
|
||||
device->i_source_cid = connection->channels[1];
|
||||
device->state = WIIMOTE_STATE_CONNECTED;
|
||||
device->exp.type = EXP_NONE;
|
||||
|
||||
wiimote_handshake(device, -1, NULL, -1);
|
||||
|
||||
return device;
|
||||
}
|
||||
|
||||
static void btpad_wii_disconnect(struct wiimote_t* device)
|
||||
{
|
||||
}
|
||||
|
||||
static uint32_t btpad_wii_get_buttons(struct wiimote_t* device)
|
||||
{
|
||||
return device->btns | (device->exp.classic.btns << 16);
|
||||
}
|
||||
|
||||
static int16_t btpad_wii_get_axis(struct wiimote_t* device, unsigned axis)
|
||||
{
|
||||
/* TODO
|
||||
if (device->.exp.type == EXP_CLASSIC)
|
||||
{
|
||||
switch (axis)
|
||||
{
|
||||
case 0: return device->wiimote.exp.classic.ljs.rx * 0x7FFF;
|
||||
case 1: return device->wiimote.exp.classic.ljs.ry * 0x7FFF;
|
||||
case 2: return device->wiimote.exp.classic.rjs.rx * 0x7FFF;
|
||||
case 3: return device->wiimote.exp.classic.rjs.ry * 0x7FFF;
|
||||
default: return 0;
|
||||
}
|
||||
}
|
||||
*/
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static void btpad_wii_packet_handler(struct wiimote_t* device, uint8_t packet_type, uint16_t channel, uint8_t *packet, uint16_t size)
|
||||
{
|
||||
if(packet_type == L2CAP_DATA_PACKET)
|
||||
{
|
||||
byte* msg = packet + 2;
|
||||
|
||||
switch (packet[1])
|
||||
{
|
||||
case WM_RPT_BTN:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_READ:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handshake(device, WM_RPT_READ, msg + 5, ((msg[2] & 0xF0) >> 4) + 1);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_CTRL_STATUS:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handshake(device,WM_RPT_CTRL_STATUS,msg,-1);
|
||||
break;
|
||||
}
|
||||
|
||||
case WM_RPT_BTN_EXP:
|
||||
{
|
||||
wiimote_pressed_buttons(device, msg);
|
||||
wiimote_handle_expansion(device, msg+2);
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
g_current_input_data.pad_buttons[device->unid] = btpad_wii_get_buttons(device);
|
||||
for (int i = 0; i < 4; i ++)
|
||||
g_current_input_data.pad_axis[device->unid][i] = btpad_wii_get_axis(device, i);
|
||||
}
|
||||
}
|
||||
|
||||
struct btpad_interface btpad_wii =
|
||||
{
|
||||
(void*)&btpad_wii_connect,
|
||||
(void*)&btpad_wii_disconnect,
|
||||
(void*)&btpad_wii_get_buttons,
|
||||
(void*)&btpad_wii_get_axis,
|
||||
(void*)&btpad_wii_packet_handler
|
||||
};
|
51
apple/iOS/platform.h
Normal file
51
apple/iOS/platform.h
Normal file
@ -0,0 +1,51 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2013 - Jason Fetters
|
||||
* Copyright (C) 2011-2013 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* 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 __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,
|
||||
RADirectoryListDelegate, RAModuleListDelegate>
|
||||
|
||||
+ (RetroArch_iOS*)get;
|
||||
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file;
|
||||
- (void)unloadingCore:(RAModuleInfo*)core;
|
||||
|
||||
- (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
|
||||
|
||||
@end
|
||||
|
||||
// modes are: keyboard, icade and btstack
|
||||
void ios_set_bluetooth_mode(NSString* mode);
|
||||
|
||||
#endif
|
376
apple/iOS/platform.m
Normal file
376
apple/iOS/platform.m
Normal file
@ -0,0 +1,376 @@
|
||||
/* 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 <pthread.h>
|
||||
#include <string.h>
|
||||
|
||||
#import "RetroArch_Apple.h"
|
||||
#include "rarch_wrapper.h"
|
||||
|
||||
#include "apple/common/apple_input.h"
|
||||
|
||||
#import "views.h"
|
||||
#include "bluetooth/btpad.h"
|
||||
#include "bluetooth/btdynamic.h"
|
||||
#include "bluetooth/btpad.h"
|
||||
|
||||
#include "file.h"
|
||||
|
||||
//#define HAVE_DEBUG_FILELOG
|
||||
void ios_set_bluetooth_mode(NSString* mode)
|
||||
{
|
||||
apple_input_enable_icade([mode isEqualToString:@"icade"]);
|
||||
btstack_set_poweron([mode isEqualToString:@"btstack"]);
|
||||
}
|
||||
|
||||
// Input helpers: This is kept here because it needs objective-c
|
||||
static void handle_touch_event(NSArray* touches)
|
||||
{
|
||||
const int numTouches = [touches count];
|
||||
const float scale = [[UIScreen mainScreen] scale];
|
||||
|
||||
g_current_input_data.touch_count = 0;
|
||||
|
||||
for(int i = 0; i != numTouches && g_current_input_data.touch_count < MAX_TOUCHES; i ++)
|
||||
{
|
||||
UITouch* touch = [touches objectAtIndex:i];
|
||||
const CGPoint coord = [touch locationInView:touch.view];
|
||||
|
||||
if (touch.phase != UITouchPhaseEnded && touch.phase != UITouchPhaseCancelled)
|
||||
{
|
||||
g_current_input_data.touches[g_current_input_data.touch_count ].screen_x = coord.x * scale;
|
||||
g_current_input_data.touches[g_current_input_data.touch_count ++].screen_y = coord.y * scale;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@interface RApplication : UIApplication
|
||||
@end
|
||||
|
||||
@implementation RApplication
|
||||
|
||||
- (void)sendEvent:(UIEvent *)event
|
||||
{
|
||||
[super sendEvent:event];
|
||||
|
||||
if ([[event allTouches] count])
|
||||
handle_touch_event(event.allTouches.allObjects);
|
||||
else if ([event respondsToSelector:@selector(_gsEvent)])
|
||||
{
|
||||
// Stolen from: http://nacho4d-nacho4d.blogspot.com/2012/01/catching-keyboard-events-in-ios.html
|
||||
uint8_t* eventMem = (uint8_t*)(void*)CFBridgingRetain([event performSelector:@selector(_gsEvent)]);
|
||||
int eventType = eventMem ? *(int*)&eventMem[8] : 0;
|
||||
|
||||
if (eventType == GSEVENT_TYPE_KEYDOWN || eventType == GSEVENT_TYPE_KEYUP)
|
||||
apple_input_handle_key_event(*(uint16_t*)&eventMem[0x3C], eventType == GSEVENT_TYPE_KEYDOWN);
|
||||
|
||||
CFBridgingRelease(eventMem);
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
@implementation RetroArch_iOS
|
||||
{
|
||||
UIWindow* _window;
|
||||
NSString* _path;
|
||||
|
||||
bool _isGameTop, _isRomList;
|
||||
uint32_t _settingMenusInBackStack;
|
||||
uint32_t _enabledOrientations;
|
||||
}
|
||||
|
||||
+ (RetroArch_iOS*)get
|
||||
{
|
||||
return (RetroArch_iOS*)[[UIApplication sharedApplication] delegate];
|
||||
}
|
||||
|
||||
#pragma mark LIFECYCLE (UIApplicationDelegate)
|
||||
- (void)applicationDidFinishLaunching:(UIApplication *)application
|
||||
{
|
||||
apple_platform = self;
|
||||
self.delegate = self;
|
||||
|
||||
// Setup window
|
||||
_window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
|
||||
_window.rootViewController = self;
|
||||
[_window makeKeyAndVisible];
|
||||
|
||||
// Build system paths and test permissions
|
||||
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 beginBrowsingForFile];
|
||||
|
||||
|
||||
// Warn if there are no cores present
|
||||
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(false);
|
||||
}
|
||||
|
||||
- (void)applicationWillResignActive:(UIApplication *)application
|
||||
{
|
||||
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
|
||||
{
|
||||
_isGameTop = [viewController isKindOfClass:[RAGameView class]];
|
||||
_isRomList = [viewController isKindOfClass:[RADirectoryList class]];
|
||||
|
||||
[[UIApplication sharedApplication] setStatusBarHidden:_isGameTop withAnimation:UIStatusBarAnimationNone];
|
||||
[[UIApplication sharedApplication] setIdleTimerDisabled:_isGameTop];
|
||||
|
||||
self.navigationBarHidden = _isGameTop;
|
||||
[self setToolbarHidden:!_isRomList animated:YES];
|
||||
self.topViewController.navigationItem.rightBarButtonItem = [self createSettingsButton];
|
||||
}
|
||||
|
||||
// UINavigationController: Never animate when pushing onto, or popping, an RAGameView
|
||||
- (void)pushViewController:(UIViewController*)theView animated:(BOOL)animated
|
||||
{
|
||||
if ([theView respondsToSelector:@selector(isSettingsView)] && [(id)theView isSettingsView])
|
||||
_settingMenusInBackStack ++;
|
||||
|
||||
[super pushViewController:theView animated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
- (UIViewController*)popViewControllerAnimated:(BOOL)animated
|
||||
{
|
||||
if ([self.topViewController respondsToSelector:@selector(isSettingsView)] && [(id)self.topViewController isSettingsView])
|
||||
_settingMenusInBackStack --;
|
||||
|
||||
return [super popViewControllerAnimated:animated && !_isGameTop];
|
||||
}
|
||||
|
||||
// NOTE: This version only runs on iOS6
|
||||
- (NSUInteger)supportedInterfaceOrientations
|
||||
{
|
||||
return _isGameTop ? _enabledOrientations
|
||||
: UIInterfaceOrientationMaskAll;
|
||||
}
|
||||
|
||||
// NOTE: This version runs on iOS2-iOS5, but not iOS6
|
||||
- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
|
||||
{
|
||||
if (_isGameTop)
|
||||
switch (interfaceOrientation)
|
||||
{
|
||||
case UIInterfaceOrientationPortrait:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskPortrait);
|
||||
case UIInterfaceOrientationPortraitUpsideDown:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskPortraitUpsideDown);
|
||||
case UIInterfaceOrientationLandscapeLeft:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskLandscapeLeft);
|
||||
case UIInterfaceOrientationLandscapeRight:
|
||||
return (_enabledOrientations & UIInterfaceOrientationMaskLandscapeRight);
|
||||
}
|
||||
|
||||
return YES;
|
||||
}
|
||||
|
||||
|
||||
#pragma mark RetroArch_Platform
|
||||
- (void)loadingCore:(RAModuleInfo*)core withFile:(const char*)file
|
||||
{
|
||||
[self pushViewController:RAGameView.get animated:NO];
|
||||
[RASettingsList refreshModuleConfig:core];
|
||||
|
||||
btpad_set_inquiry_state(false);
|
||||
|
||||
[self refreshSystemConfig];
|
||||
}
|
||||
|
||||
- (void)unloadingCore:(RAModuleInfo*)core
|
||||
{
|
||||
[self popToViewController:[RAGameView get] animated:NO];
|
||||
[self popViewControllerAnimated:NO];
|
||||
|
||||
btpad_set_inquiry_state(true);
|
||||
}
|
||||
|
||||
#pragma mark FRONTEND CONFIG
|
||||
- (void)refreshSystemConfig
|
||||
{
|
||||
// Read load time settings
|
||||
config_file_t* conf = config_file_new([self.systemConfigPath UTF8String]);
|
||||
|
||||
if (conf)
|
||||
{
|
||||
// Get enabled orientations
|
||||
static const struct { const char* setting; uint32_t orientation; } orientationSettings[4] =
|
||||
{
|
||||
{ "ios_allow_portrait", UIInterfaceOrientationMaskPortrait },
|
||||
{ "ios_allow_portrait_upside_down", UIInterfaceOrientationMaskPortraitUpsideDown },
|
||||
{ "ios_allow_landscape_left", UIInterfaceOrientationMaskLandscapeLeft },
|
||||
{ "ios_allow_landscape_right", UIInterfaceOrientationMaskLandscapeRight }
|
||||
};
|
||||
|
||||
_enabledOrientations = 0;
|
||||
|
||||
for (int i = 0; i < 4; i ++)
|
||||
{
|
||||
bool enabled = false;
|
||||
bool found = config_get_bool(conf, orientationSettings[i].setting, &enabled);
|
||||
|
||||
if (!found || enabled)
|
||||
_enabledOrientations |= orientationSettings[i].orientation;
|
||||
}
|
||||
|
||||
// Setup bluetooth mode
|
||||
ios_set_bluetooth_mode(objc_get_value_from_config(conf, @"ios_btmode", @"keyboard"));
|
||||
|
||||
bool val;
|
||||
apple_use_tv_mode = config_get_bool(conf, "ios_tv_mode", &val) && val;
|
||||
|
||||
config_file_free(conf);
|
||||
}
|
||||
}
|
||||
|
||||
#pragma mark PAUSE MENU
|
||||
- (UIBarButtonItem*)createSettingsButton
|
||||
{
|
||||
if (_settingMenusInBackStack == 0)
|
||||
return [[UIBarButtonItem alloc]
|
||||
initWithTitle:@"Settings"
|
||||
style:UIBarButtonItemStyleBordered
|
||||
target:[RetroArch_iOS get]
|
||||
action:@selector(showSystemSettings)];
|
||||
|
||||
else
|
||||
return nil;
|
||||
}
|
||||
|
||||
- (IBAction)showPauseMenu:(id)sender
|
||||
{
|
||||
if (apple_is_running && !apple_is_paused && _isGameTop)
|
||||
{
|
||||
apple_is_paused = true;
|
||||
[[RAGameView get] openPauseMenu];
|
||||
|
||||
btpad_set_inquiry_state(true);
|
||||
}
|
||||
}
|
||||
|
||||
- (IBAction)basicEvent:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(&apple_event_basic_command, ((UIView*)sender).tag);
|
||||
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)chooseState:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(apple_event_set_state_slot, (void*)((UISegmentedControl*)sender).selectedSegmentIndex);
|
||||
}
|
||||
|
||||
- (IBAction)showRGUI:(id)sender
|
||||
{
|
||||
if (apple_is_running)
|
||||
apple_frontend_post_event(apple_event_show_rgui, 0);
|
||||
|
||||
[self closePauseMenu:sender];
|
||||
}
|
||||
|
||||
- (IBAction)closePauseMenu:(id)sender
|
||||
{
|
||||
[[RAGameView get] closePauseMenu];
|
||||
apple_is_paused = false;
|
||||
|
||||
btpad_set_inquiry_state(false);
|
||||
}
|
||||
|
||||
- (IBAction)showSettings
|
||||
{
|
||||
[self pushViewController:[[RASettingsList alloc] initWithModule:apple_core] animated:YES];
|
||||
}
|
||||
|
||||
- (IBAction)showSystemSettings
|
||||
{
|
||||
[self pushViewController:[RASystemSettingsList new] animated:YES];
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
int main(int argc, char *argv[])
|
||||
{
|
||||
@autoreleasepool {
|
||||
#if defined(HAVE_DEBUG_FILELOG) && (TARGET_IPHONE_SIMULATOR == 0)
|
||||
NSArray *paths = NSSearchPathForDirectoriesInDomains(NSDocumentDirectory, NSUserDomainMask, YES);
|
||||
NSString *documentsDirectory = [paths objectAtIndex:0];
|
||||
NSString *logPath = [documentsDirectory stringByAppendingPathComponent:@"console_stdout.log"];
|
||||
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stdout);
|
||||
freopen([logPath cStringUsingEncoding:NSASCIIStringEncoding], "a", stderr);
|
||||
#endif
|
||||
return UIApplicationMain(argc, argv, NSStringFromClass([RApplication class]), NSStringFromClass([RetroArch_iOS class]));
|
||||
}
|
||||
}
|
@ -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
|
||||
{
|
||||
@ -28,34 +28,79 @@ enum SettingTypes
|
||||
};
|
||||
|
||||
@interface RASettingData : NSObject
|
||||
@property enum SettingTypes type;
|
||||
{
|
||||
@public
|
||||
enum SettingTypes type;
|
||||
|
||||
@property (strong) NSString* label;
|
||||
@property (strong) NSString* name;
|
||||
@property (strong) NSString* value;
|
||||
NSString* label; // < The label displayed in the settings menu
|
||||
NSString* name; // < The key name of the value in the config file
|
||||
NSString* value; // < The current state of the setting
|
||||
|
||||
@property (strong) NSString* path;
|
||||
@property (strong) NSArray* subValues;
|
||||
@property (strong) NSMutableArray* msubValues;
|
||||
uint32_t player; // < The player that a ButtonSetting represents
|
||||
NSString* button_bind; // < The Gamepad button binding string
|
||||
NSString* axis_bind; // < The Gamepad axis binding string
|
||||
|
||||
NSString* path; // < The base path for FileListSettings
|
||||
NSArray* subValues; // < The available options for EnumerationSettings and FileListSettings
|
||||
bool haveNoneOption; // < Determines if a 'None' option is added to an Enumeration or FileList
|
||||
bool haveDescriptions; // < Determines if subValues containts friendly descriptions for each value
|
||||
|
||||
double rangeMin; // < The mininum value of a range setting
|
||||
double rangeMax; // < The maximum value of a range setting
|
||||
|
||||
void (*changed)(RASettingData* action);
|
||||
void (*reload)(RASettingData* action, id userdata);
|
||||
}
|
||||
|
||||
@property double rangeMin;
|
||||
@property double rangeMax;
|
||||
- (void)setValue:(NSString*)aValue;
|
||||
|
||||
@property uint32_t player;
|
||||
|
||||
@property bool haveNoneOption;
|
||||
|
||||
- (id)initWithType:(enum SettingTypes)aType label:(NSString*)aLabel name:(NSString*)aName;
|
||||
@end
|
||||
|
||||
@implementation RASettingData
|
||||
- (id)initWithType:(enum SettingTypes)aType label:(NSString*)aLabel name:(NSString*)aName
|
||||
{
|
||||
self.type = aType;
|
||||
self.label = aLabel;
|
||||
self.name = aName;
|
||||
type = aType;
|
||||
label = aLabel;
|
||||
name = aName;
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)setValue:(NSString*)aValue;
|
||||
{
|
||||
value = aValue;
|
||||
|
||||
if (changed)
|
||||
changed(self);
|
||||
}
|
||||
|
||||
- (uint32_t)enumerationCount
|
||||
{
|
||||
return subValues.count / (haveDescriptions ? 2 : 1);
|
||||
}
|
||||
|
||||
- (NSString*)valueForEnumerationIndex:(uint32_t)index
|
||||
{
|
||||
return subValues[index * (haveDescriptions ? 2 : 1)];
|
||||
}
|
||||
|
||||
- (NSString*)labelForEnumerationIndex:(uint32_t)index
|
||||
{
|
||||
return subValues[index * (haveDescriptions ? 2 : 1) + (haveDescriptions ? 1 : 0)];
|
||||
}
|
||||
|
||||
- (NSString*)labelForEnumerationValue
|
||||
{
|
||||
const uint32_t count = self.enumerationCount;
|
||||
|
||||
for (int i = 0; haveDescriptions && i < count; i ++)
|
||||
{
|
||||
if ([value isEqualToString:subValues[i * 2]])
|
||||
return subValues[i * 2 + 1];
|
||||
}
|
||||
|
||||
return value;
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
// Helper view definitions
|
||||
@ -71,7 +116,7 @@ enum SettingTypes
|
||||
static RASettingData* boolean_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:BooleanSetting label:label name:name];
|
||||
result.value = objc_get_value_from_config(config, name, defaultValue);
|
||||
result->value = objc_get_value_from_config(config, name, defaultValue);
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -80,27 +125,26 @@ static RASettingData* button_setting(config_file_t* config, uint32_t player, NSS
|
||||
NSString* realname = player ? [NSString stringWithFormat:@"input_player%d_%@", player, name] : name;
|
||||
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:ButtonSetting label:label name:realname];
|
||||
result.msubValues = [NSMutableArray arrayWithObjects:
|
||||
objc_get_value_from_config(config, realname, defaultValue),
|
||||
objc_get_value_from_config(config, [realname stringByAppendingString:@"_btn"], @"nul"),
|
||||
objc_get_value_from_config(config, [realname stringByAppendingString:@"_axis"], @"nul"),
|
||||
nil];
|
||||
result.player = player ? player - 1 : 0;
|
||||
result->player = player ? player - 1 : 0;
|
||||
result->value = objc_get_value_from_config(config, realname, defaultValue);
|
||||
result->button_bind = objc_get_value_from_config(config, [realname stringByAppendingString:@"_btn"], @"nul");
|
||||
result->axis_bind = objc_get_value_from_config(config, [realname stringByAppendingString:@"_axis"], @"nul");
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* group_setting(NSString* label, NSArray* settings)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:GroupSetting label:label name:nil];
|
||||
result.subValues = settings;
|
||||
result->subValues = settings;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* enumeration_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, NSArray* values)
|
||||
static RASettingData* enumeration_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, NSArray* values, bool haveDescriptions)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:EnumerationSetting label:label name:name];
|
||||
result.value = objc_get_value_from_config(config, name, defaultValue);
|
||||
result.subValues = values;
|
||||
result->value = objc_get_value_from_config(config, name, defaultValue);
|
||||
result->subValues = values;
|
||||
result->haveDescriptions = haveDescriptions;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -113,19 +157,19 @@ static RASettingData* subpath_setting(config_file_t* config, NSString* name, NSS
|
||||
values = [values pathsMatchingExtensions:[NSArray arrayWithObject:extension]];
|
||||
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:FileListSetting label:label name:name];
|
||||
result.value = value;
|
||||
result.subValues = values;
|
||||
result.path = path;
|
||||
result.haveNoneOption = true;
|
||||
result->value = value;
|
||||
result->subValues = values;
|
||||
result->path = path;
|
||||
result->haveNoneOption = true;
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* range_setting(config_file_t* config, NSString* name, NSString* label, NSString* defaultValue, double minValue, double maxValue)
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:RangeSetting label:label name:name];
|
||||
result.value = objc_get_value_from_config(config, name, defaultValue);
|
||||
result.rangeMin = minValue;
|
||||
result.rangeMax = maxValue;
|
||||
result->value = objc_get_value_from_config(config, name, defaultValue);
|
||||
result->rangeMin = minValue;
|
||||
result->rangeMax = maxValue;
|
||||
return result;
|
||||
}
|
||||
|
||||
@ -133,8 +177,8 @@ static RASettingData* aspect_setting(config_file_t* config, NSString* label)
|
||||
{
|
||||
// Why does this need to be so difficult?
|
||||
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:AspectSetting label:label name:@"fram"];
|
||||
result.subValues = [NSArray arrayWithObjects:@"Fill Screen", @"Game Aspect", @"Pixel Aspect", @"4:3", @"16:9", nil];
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:AspectSetting label:label name:@""];
|
||||
result->subValues = [NSArray arrayWithObjects:@"Fill Screen", @"Game Aspect", @"Pixel Aspect", @"4:3", @"16:9", nil];
|
||||
|
||||
bool videoForceAspect = true;
|
||||
bool videoAspectAuto = false;
|
||||
@ -148,19 +192,20 @@ static RASettingData* aspect_setting(config_file_t* config, NSString* label)
|
||||
}
|
||||
|
||||
if (!videoForceAspect)
|
||||
result.value = @"Fill Screen";
|
||||
result->value = @"Fill Screen";
|
||||
else if (videoAspect < 0.0)
|
||||
result.value = videoAspectAuto ? @"Game Aspect" : @"Pixel Aspect";
|
||||
result->value = videoAspectAuto ? @"Game Aspect" : @"Pixel Aspect";
|
||||
else
|
||||
result.value = (videoAspect < 1.5) ? @"4:3" : @"16:9";
|
||||
result->value = (videoAspect < 1.5) ? @"4:3" : @"16:9";
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
static RASettingData* custom_action(NSString* action, NSString* value, id data)
|
||||
static RASettingData* custom_action(NSString* action, NSString* value, id data, void (*reload_func)(RASettingData* action, id userdata))
|
||||
{
|
||||
RASettingData* result = [[RASettingData alloc] initWithType:CustomAction label:action name:nil];
|
||||
result.value = value;
|
||||
result->value = value;
|
||||
result->reload = reload_func;
|
||||
|
||||
if (data != nil)
|
||||
objc_setAssociatedObject(result, "USERDATA", data, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
@ -168,25 +213,36 @@ static RASettingData* custom_action(NSString* action, NSString* value, id data)
|
||||
return result;
|
||||
}
|
||||
|
||||
// This adds a change notify function to a setting and returns it; done this way so it can be used in NSArray
|
||||
// init lists.
|
||||
static RASettingData* change_notify(RASettingData* setting, void (*change_func)(RASettingData* setting))
|
||||
{
|
||||
setting->changed = change_func;
|
||||
return setting;
|
||||
}
|
||||
|
||||
static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
{
|
||||
// Only player 1 should have default key bindings
|
||||
#define DEFKEY(val) (player == 1) ? val : @"nul"
|
||||
|
||||
return [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:[NSString stringWithFormat:@"Player %d", player],
|
||||
button_setting(config, player, @"up", @"Up", @"up"),
|
||||
button_setting(config, player, @"down", @"Down", @"down"),
|
||||
button_setting(config, player, @"left", @"Left", @"left"),
|
||||
button_setting(config, player, @"right", @"Right", @"right"),
|
||||
button_setting(config, player, @"up", @"Up", DEFKEY(@"up")),
|
||||
button_setting(config, player, @"down", @"Down", DEFKEY(@"down")),
|
||||
button_setting(config, player, @"left", @"Left", DEFKEY(@"left")),
|
||||
button_setting(config, player, @"right", @"Right", DEFKEY(@"right")),
|
||||
|
||||
button_setting(config, player, @"start", @"Start", @"enter"),
|
||||
button_setting(config, player, @"select", @"Select", @"rshift"),
|
||||
button_setting(config, player, @"start", @"Start", DEFKEY(@"enter")),
|
||||
button_setting(config, player, @"select", @"Select", DEFKEY(@"rshift")),
|
||||
|
||||
button_setting(config, player, @"b", @"B", @"z"),
|
||||
button_setting(config, player, @"a", @"A", @"x"),
|
||||
button_setting(config, player, @"x", @"X", @"s"),
|
||||
button_setting(config, player, @"y", @"Y", @"a"),
|
||||
button_setting(config, player, @"b", @"B", DEFKEY(@"z")),
|
||||
button_setting(config, player, @"a", @"A", DEFKEY(@"x")),
|
||||
button_setting(config, player, @"x", @"X", DEFKEY(@"s")),
|
||||
button_setting(config, player, @"y", @"Y", DEFKEY(@"a")),
|
||||
|
||||
button_setting(config, player, @"l", @"L", @"q"),
|
||||
button_setting(config, player, @"r", @"R", @"w"),
|
||||
button_setting(config, player, @"l", @"L", DEFKEY(@"q")),
|
||||
button_setting(config, player, @"r", @"R", DEFKEY(@"w")),
|
||||
button_setting(config, player, @"l2", @"L2", @"nul"),
|
||||
button_setting(config, player, @"r2", @"R2", @"nul"),
|
||||
button_setting(config, player, @"l3", @"L3", @"nul"),
|
||||
@ -219,7 +275,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
- (id)initWithModule:(RAModuleInfo*)module
|
||||
{
|
||||
_module = module;
|
||||
_configPath = RetroArch_iOS.get.retroarchConfigPath;
|
||||
_configPath = _module ? _module.configFile : apple_platform.globalConfigFile;
|
||||
|
||||
config_file_t* config = config_file_new([_configPath UTF8String]);
|
||||
|
||||
@ -228,7 +284,8 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
|
||||
NSArray* settings = [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:@"Core",
|
||||
custom_action(@"Core Info", nil, nil),
|
||||
custom_action(@"Core Info", nil, nil, 0),
|
||||
_module.hasCustomConfig ? custom_action(@"Delete Custom Config", nil, nil, 0) : nil,
|
||||
nil],
|
||||
|
||||
[NSArray arrayWithObjects:@"Video",
|
||||
@ -305,37 +362,71 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
if (config)
|
||||
{
|
||||
config_set_string(config, "system_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
|
||||
config_set_string(config, "savefile_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
|
||||
config_set_string(config, "savestate_directory", [[RetroArch_iOS get].systemDirectory UTF8String]);
|
||||
[self writeSettings:nil toConfig:config];
|
||||
config_file_write(config, [_configPath UTF8String]);
|
||||
config_file_free(config);
|
||||
}
|
||||
|
||||
[[RetroArch_iOS get] refreshConfig];
|
||||
apple_refresh_config();
|
||||
}
|
||||
}
|
||||
|
||||
- (void)handleCustomAction:(RASettingData*)setting
|
||||
{
|
||||
if ([@"Core Info" isEqualToString:setting.label])
|
||||
if ([@"Core Info" isEqualToString:setting->label])
|
||||
[[RetroArch_iOS get] pushViewController:[[RAModuleInfoList alloc] initWithModuleInfo:_module] animated:YES];
|
||||
else if([@"Delete Custom Config" isEqualToString:setting->label])
|
||||
{
|
||||
[_module deleteCustomConfig];
|
||||
_cancelSave = true;
|
||||
[self.navigationController popViewControllerAnimated:YES];
|
||||
}
|
||||
}
|
||||
|
||||
@end
|
||||
|
||||
#pragma mark System Settings
|
||||
|
||||
static void reload_core_config_state(RASettingData* action, RAModuleInfo* userdata)
|
||||
{
|
||||
[action setValue:userdata.hasCustomConfig ? @"[Custom]" : @"[Global]"];
|
||||
}
|
||||
|
||||
static void bluetooth_option_changed(RASettingData* setting)
|
||||
{
|
||||
ios_set_bluetooth_mode(setting->value);
|
||||
}
|
||||
|
||||
@implementation RASystemSettingsList
|
||||
- (id)init
|
||||
{
|
||||
config_file_t* config = config_file_new([[RetroArch_iOS get].systemConfigPath UTF8String]);
|
||||
|
||||
NSMutableArray* modules = [NSMutableArray array];
|
||||
[modules addObject:@"Cores"];
|
||||
[modules addObject:custom_action(@"Global Core Config", nil, nil, 0)];
|
||||
|
||||
NSArray* moduleList = apple_get_modules();
|
||||
for (RAModuleInfo* i in moduleList)
|
||||
{
|
||||
[modules addObject:custom_action(i.description, nil, i, reload_core_config_state)];
|
||||
}
|
||||
|
||||
|
||||
NSArray* bluetoothOptions = [NSArray arrayWithObjects:@"keyboard", @"Keyboard",
|
||||
@"icade", @"iCade Device",
|
||||
btstack_try_load() ? @"btstack" : nil, @"WiiMote/SixAxis (BTstack)",
|
||||
nil];
|
||||
|
||||
NSArray* settings = [NSArray arrayWithObjects:
|
||||
[NSArray arrayWithObjects:@"Frontend",
|
||||
custom_action(@"Diagnostic Log", nil, nil),
|
||||
custom_action(@"Diagnostic Log", nil, nil, 0),
|
||||
boolean_setting(config, @"ios_tv_mode", @"TV Mode", @"false"),
|
||||
nil],
|
||||
[NSArray arrayWithObjects:@"Bluetooth",
|
||||
// TODO: Note that with this turned off the native bluetooth is expected to be a real keyboard
|
||||
boolean_setting(config, @"ios_use_icade", @"Native BT is iCade", @"false"),
|
||||
btstack_try_load() ? boolean_setting(config, @"ios_use_btstack", @"Enable BTstack", @"false") : nil,
|
||||
change_notify(enumeration_setting(config, @"ios_btmode", @"Mode", @"keyboard", bluetoothOptions, true), bluetooth_option_changed),
|
||||
nil],
|
||||
[NSArray arrayWithObjects:@"Orientations",
|
||||
boolean_setting(config, @"ios_allow_portrait", @"Portrait", @"true"),
|
||||
@ -343,9 +434,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
boolean_setting(config, @"ios_allow_landscape_left", @"Landscape Left", @"true"),
|
||||
boolean_setting(config, @"ios_allow_landscape_right", @"Landscape Right", @"true"),
|
||||
nil],
|
||||
[NSArray arrayWithObjects:@"Cores",
|
||||
custom_action(@"Core Configuration", nil, nil),
|
||||
nil],
|
||||
modules,
|
||||
nil
|
||||
];
|
||||
|
||||
@ -356,6 +445,12 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
return self;
|
||||
}
|
||||
|
||||
- (void)viewDidAppear:(BOOL)animated
|
||||
{
|
||||
[self.tableView reloadData];
|
||||
[super viewDidAppear:animated];
|
||||
}
|
||||
|
||||
- (void)dealloc
|
||||
{
|
||||
config_file_t* config = config_file_new([[RetroArch_iOS get].systemConfigPath UTF8String]);
|
||||
@ -375,12 +470,49 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
|
||||
- (void)handleCustomAction:(RASettingData*)setting
|
||||
{
|
||||
if ([@"Diagnostic Log" isEqualToString:setting.label])
|
||||
if ([@"Diagnostic Log" isEqualToString:setting->label])
|
||||
[[RetroArch_iOS get] pushViewController:[RALogView new] animated:YES];
|
||||
else if ([@"Enable BTstack" isEqualToString:setting.label])
|
||||
btstack_set_poweron([setting.value isEqualToString:@"true"]);
|
||||
else if([@"Core Configuration" isEqualToString:setting.label])
|
||||
else if ([@"Enable BTstack" isEqualToString:setting->label])
|
||||
btstack_set_poweron([setting->value isEqualToString:@"true"]);
|
||||
else if([@"Global Core Config" isEqualToString:setting->label])
|
||||
[RetroArch_iOS.get pushViewController:[[RASettingsList alloc] initWithModule:nil] animated:YES];
|
||||
else
|
||||
{
|
||||
RAModuleInfo* data = (RAModuleInfo*)objc_getAssociatedObject(setting, "USERDATA");
|
||||
if (data)
|
||||
{
|
||||
if (!data.hasCustomConfig)
|
||||
{
|
||||
UIAlertView* alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
|
||||
message:@"No custom configuration for this core exists, "
|
||||
"would you like to create one?"
|
||||
delegate:self
|
||||
cancelButtonTitle:@"No"
|
||||
otherButtonTitles:@"Yes", nil];
|
||||
objc_setAssociatedObject(alert, "MODULE", data, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
[alert show];
|
||||
}
|
||||
else
|
||||
[RetroArch_iOS.get pushViewController:[[RASettingsList alloc] initWithModule:data] animated:YES];
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
- (void)alertView:(UIAlertView*)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
RAModuleInfo* data = (RAModuleInfo*)objc_getAssociatedObject(alertView, "MODULE");
|
||||
|
||||
if (data)
|
||||
{
|
||||
if (buttonIndex == alertView.firstOtherButtonIndex)
|
||||
{
|
||||
[data createCustomConfig];
|
||||
[self.tableView reloadData];
|
||||
}
|
||||
|
||||
[RetroArch_iOS.get pushViewController:[[RASettingsList alloc] initWithModule:data] animated:YES];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
@end
|
||||
@ -420,35 +552,35 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
{
|
||||
RASettingData* setting = [group objectAtIndex:j];
|
||||
|
||||
switch (setting.type)
|
||||
switch (setting->type)
|
||||
{
|
||||
case GroupSetting:
|
||||
[self writeSettings:setting.subValues toConfig:config];
|
||||
[self writeSettings:setting->subValues toConfig:config];
|
||||
break;
|
||||
|
||||
case FileListSetting:
|
||||
if ([setting.value length] > 0)
|
||||
config_set_string(config, [setting.name UTF8String], [[setting.path stringByAppendingPathComponent:setting.value] UTF8String]);
|
||||
if ([setting->value length] > 0)
|
||||
config_set_string(config, [setting->name UTF8String], [[setting->path stringByAppendingPathComponent:setting->value] UTF8String]);
|
||||
else
|
||||
config_set_string(config, [setting.name UTF8String], "");
|
||||
config_set_string(config, [setting->name UTF8String], "");
|
||||
break;
|
||||
|
||||
case ButtonSetting:
|
||||
if (setting.msubValues[0])
|
||||
config_set_string(config, [setting.name UTF8String], [setting.msubValues[0] UTF8String]);
|
||||
if (setting.msubValues[1])
|
||||
config_set_string(config, [[setting.name stringByAppendingString:@"_btn"] UTF8String], [setting.msubValues[1] UTF8String]);
|
||||
if (setting.msubValues[2])
|
||||
config_set_string(config, [[setting.name stringByAppendingString:@"_axis"] UTF8String], [setting.msubValues[2] UTF8String]);
|
||||
if (setting->value)
|
||||
config_set_string(config, [setting->name UTF8String], [setting->value UTF8String]);
|
||||
if (setting->button_bind)
|
||||
config_set_string(config, [[setting->name stringByAppendingString:@"_btn"] UTF8String], [setting->button_bind UTF8String]);
|
||||
if (setting->axis_bind)
|
||||
config_set_string(config, [[setting->name stringByAppendingString:@"_axis"] UTF8String], [setting->axis_bind UTF8String]);
|
||||
break;
|
||||
|
||||
case AspectSetting:
|
||||
config_set_string(config, "video_force_aspect", [@"Fill Screen" isEqualToString:setting.value] ? "false" : "true");
|
||||
config_set_string(config, "video_aspect_ratio_auto", [@"Game Aspect" isEqualToString:setting.value] ? "true" : "false");
|
||||
config_set_string(config, "video_force_aspect", [@"Fill Screen" isEqualToString:setting->value] ? "false" : "true");
|
||||
config_set_string(config, "video_aspect_ratio_auto", [@"Game Aspect" isEqualToString:setting->value] ? "true" : "false");
|
||||
config_set_string(config, "video_aspect_ratio", "-1.0");
|
||||
if([@"4:3" isEqualToString:setting.value])
|
||||
if([@"4:3" isEqualToString:setting->value])
|
||||
config_set_string(config, "video_aspect_ratio", "1.33333333");
|
||||
else if([@"16:9" isEqualToString:setting.value])
|
||||
else if([@"16:9" isEqualToString:setting->value])
|
||||
config_set_string(config, "video_aspect_ratio", "1.77777777");
|
||||
break;
|
||||
|
||||
@ -456,7 +588,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
break;
|
||||
|
||||
default:
|
||||
config_set_string(config, [setting.name UTF8String], [setting.value UTF8String]);
|
||||
config_set_string(config, [setting->name UTF8String], [setting->value UTF8String]);
|
||||
break;
|
||||
}
|
||||
}
|
||||
@ -467,7 +599,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
{
|
||||
RASettingData* setting = (RASettingData*)[self itemForIndexPath:indexPath];
|
||||
|
||||
switch (setting.type)
|
||||
switch (setting->type)
|
||||
{
|
||||
case EnumerationSetting:
|
||||
case FileListSetting:
|
||||
@ -480,7 +612,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
break;
|
||||
|
||||
case GroupSetting:
|
||||
[[RetroArch_iOS get] pushViewController:[[RASettingsSubList alloc] initWithSettings:setting.subValues title:setting.label] animated:YES];
|
||||
[[RetroArch_iOS get] pushViewController:[[RASettingsSubList alloc] initWithSettings:setting->subValues title:setting->label] animated:YES];
|
||||
break;
|
||||
|
||||
default:
|
||||
@ -493,7 +625,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
- (void)handleBooleanSwitch:(UISwitch*)swt
|
||||
{
|
||||
RASettingData* setting = objc_getAssociatedObject(swt, "SETTING");
|
||||
setting.value = (swt.on ? @"true" : @"false");
|
||||
[setting setValue:swt.on ? @"true" : @"false"];
|
||||
|
||||
[self handleCustomAction:setting];
|
||||
}
|
||||
@ -501,7 +633,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
- (void)handleSlider:(UISlider*)sld
|
||||
{
|
||||
RASettingData* setting = objc_getAssociatedObject(sld, "SETTING");
|
||||
setting.value = [NSString stringWithFormat:@"%f", sld.value];
|
||||
[setting setValue:[NSString stringWithFormat:@"%f", sld.value]];
|
||||
|
||||
[self handleCustomAction:setting];
|
||||
}
|
||||
@ -512,7 +644,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
|
||||
UITableViewCell* cell = nil;
|
||||
|
||||
switch (setting.type)
|
||||
switch (setting->type)
|
||||
{
|
||||
case BooleanSetting:
|
||||
{
|
||||
@ -529,10 +661,10 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
|
||||
}
|
||||
|
||||
cell.textLabel.text = setting.label;
|
||||
cell.textLabel.text = setting->label;
|
||||
|
||||
UISwitch* swt = (UISwitch*)cell.accessoryView;
|
||||
swt.on = [setting.value isEqualToString:@"true"];
|
||||
swt.on = [setting->value isEqualToString:@"true"];
|
||||
objc_setAssociatedObject(swt, "SETTING", setting, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
|
||||
return cell;
|
||||
@ -554,12 +686,12 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
[cell setSelectionStyle:UITableViewCellSelectionStyleNone];
|
||||
}
|
||||
|
||||
cell.textLabel.text = setting.label;
|
||||
cell.textLabel.text = setting->label;
|
||||
|
||||
UISlider* sld = (UISlider*)cell.accessoryView;
|
||||
sld.minimumValue = setting.rangeMin;
|
||||
sld.maximumValue = setting.rangeMax;
|
||||
sld.value = [setting.value doubleValue];
|
||||
sld.minimumValue = setting->rangeMin;
|
||||
sld.maximumValue = setting->rangeMax;
|
||||
sld.value = [setting->value doubleValue];
|
||||
objc_setAssociatedObject(sld, "SETTING", setting, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
|
||||
|
||||
return cell;
|
||||
@ -575,16 +707,21 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
cell = [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleValue1 reuseIdentifier:@"default"];
|
||||
cell.accessoryType = UITableViewCellAccessoryDisclosureIndicator;
|
||||
}
|
||||
|
||||
cell.textLabel.text = setting.label;
|
||||
|
||||
if (setting->reload)
|
||||
setting->reload(setting, objc_getAssociatedObject(setting, "USERDATA"));
|
||||
|
||||
cell.textLabel.text = setting->label;
|
||||
|
||||
if (setting.type != ButtonSetting)
|
||||
cell.detailTextLabel.text = setting.value;
|
||||
else
|
||||
if (setting->type == ButtonSetting)
|
||||
cell.detailTextLabel.text = [NSString stringWithFormat:@"[KB:%@] [JS:%@] [AX:%@]",
|
||||
[setting.msubValues[0] length] ? setting.msubValues[0] : @"nul",
|
||||
[setting.msubValues[1] length] ? setting.msubValues[1] : @"nul",
|
||||
[setting.msubValues[2] length] ? setting.msubValues[2] : @"nul"];
|
||||
[setting->value length] ? setting->value : @"nul",
|
||||
[setting->button_bind length] ? setting->button_bind : @"nul",
|
||||
[setting->axis_bind length] ? setting->axis_bind : @"nul"];
|
||||
else if(setting->type == EnumerationSetting)
|
||||
cell.detailTextLabel.text = setting.labelForEnumerationValue;
|
||||
else
|
||||
cell.detailTextLabel.text = setting->value;
|
||||
|
||||
return cell;
|
||||
}
|
||||
@ -606,20 +743,20 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
|
||||
_value = setting;
|
||||
_view = table;
|
||||
_mainSection = _value.haveNoneOption ? 1 : 0;
|
||||
_mainSection = _value->haveNoneOption ? 1 : 0;
|
||||
|
||||
[self setTitle: _value.label];
|
||||
[self setTitle: _value->label];
|
||||
return self;
|
||||
}
|
||||
|
||||
- (NSInteger)numberOfSectionsInTableView:(UITableView*)tableView
|
||||
{
|
||||
return _value.haveNoneOption ? 2 : 1;
|
||||
return _value->haveNoneOption ? 2 : 1;
|
||||
}
|
||||
|
||||
- (NSInteger)tableView:(UITableView*)tableView numberOfRowsInSection:(NSInteger)section
|
||||
{
|
||||
return (section == _mainSection) ? _value.subValues.count : 1;
|
||||
return (section == _mainSection) ? _value.enumerationCount : 1;
|
||||
}
|
||||
|
||||
- (UITableViewCell*)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
@ -627,14 +764,17 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
UITableViewCell* cell = [self.tableView dequeueReusableCellWithIdentifier:@"option"];
|
||||
cell = cell ? cell : [[UITableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:@"option"];
|
||||
|
||||
cell.textLabel.text = (indexPath.section == _mainSection) ? _value.subValues[indexPath.row] : @"None";
|
||||
if (indexPath.section == _mainSection)
|
||||
cell.textLabel.text = [_value labelForEnumerationIndex:indexPath.row];
|
||||
else
|
||||
cell.textLabel.text = @"None";
|
||||
|
||||
return cell;
|
||||
}
|
||||
|
||||
- (void)tableView:(UITableView*)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath
|
||||
{
|
||||
_value.value = (indexPath.section == _mainSection) ? _value.subValues[indexPath.row] : @"";
|
||||
[_value setValue: (indexPath.section == _mainSection) ? [_value valueForEnumerationIndex:indexPath.row] : @""];
|
||||
|
||||
[_view reloadData];
|
||||
[[RetroArch_iOS get] popViewControllerAnimated:YES];
|
||||
@ -661,7 +801,7 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
_me = self;
|
||||
|
||||
_alert = [[UIAlertView alloc] initWithTitle:@"RetroArch"
|
||||
message:_value.label
|
||||
message:_value->label
|
||||
delegate:self
|
||||
cancelButtonTitle:@"Cancel"
|
||||
otherButtonTitles:@"Clear Keyboard", @"Clear Joystick", @"Clear Axis", nil];
|
||||
@ -689,108 +829,29 @@ static NSArray* build_input_port_group(config_file_t* config, uint32_t player)
|
||||
- (void)alertView:(UIAlertView*)alertView willDismissWithButtonIndex:(NSInteger)buttonIndex
|
||||
{
|
||||
if (buttonIndex == _alert.firstOtherButtonIndex)
|
||||
_value.msubValues[0] = @"nul";
|
||||
_value->value = @"nul";
|
||||
else if(buttonIndex == _alert.firstOtherButtonIndex + 1)
|
||||
_value.msubValues[1] = @"nul";
|
||||
_value->button_bind = @"nul";
|
||||
else if(buttonIndex == _alert.firstOtherButtonIndex + 2)
|
||||
_value.msubValues[2] = @"nul";
|
||||
_value->axis_bind = @"nul";
|
||||
|
||||
[self finish];
|
||||
}
|
||||
|
||||
- (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.msubValues[0] = [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.msubValues[1] = [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.msubValues[2] = [NSString stringWithFormat:@"%s%d", (value > 0x1000) ? "+" : "-", i];
|
||||
[self finish];
|
||||
break;
|
||||
}
|
||||
}
|
||||
[self finish];
|
||||
}
|
||||
|
||||
@end
|
||||
|
@ -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
|
||||
|
5
apple/modules/bsnes_performance_libretro.info
Normal file
5
apple/modules/bsnes_performance_libretro.info
Normal file
@ -0,0 +1,5 @@
|
||||
display_name = "SNES / Super Famicom (SNES9x Next)"
|
||||
supported_extensions = "smc|sfc"
|
||||
corename = "bsnes/higan Performance"
|
||||
manufacturer = "Nintendo"
|
||||
systemname = "Super Nintendo Entertainment System"
|
@ -1,4 +1,4 @@
|
||||
display_name = "Nintendo DS"
|
||||
display_name = "Nintendo DS (DeSmuME)"
|
||||
supported_extensions = "nds"
|
||||
corename = "DeSmuME"
|
||||
manufacturer = "Nintendo"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Game Boy / Game Boy Color"
|
||||
display_name = "Game Boy / Game Boy Color (Gambatte)"
|
||||
supported_extensions = "gb|gbc|dmg"
|
||||
corename = "gambatte"
|
||||
manufacturer = "Nintendo"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Sega (MS/GG/MD/CD)"
|
||||
display_name = "Sega MS/GG/MD/CD (Genesis Plus GX)"
|
||||
supported_extensions = "md|smd|gen|sms|gg|sg|bin|cue|ios"
|
||||
corename = "Genesis Plus GX"
|
||||
manufacturer = "Sega"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "InstancingViewer"
|
||||
display_name = "PNG Images (InstancingViewer)"
|
||||
recommended_extensions = "png"
|
||||
corename = "InstancingViewer"
|
||||
manufacturer = "Various"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Neo Geo Pocket (Color)"
|
||||
display_name = "Neo Geo Pocket/Color (Mednafen Neopop)"
|
||||
supported_extensions = "ngp|ngc"
|
||||
corename = "Mednafen Neopop"
|
||||
manufacturer = "SNK"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "PC Engine/TurboGrafx-16"
|
||||
display_name = "PC Engine/TurboGrafx-16 (Mednafen PCE Fast)"
|
||||
supported_extensions = "pce|sgx|cue"
|
||||
corename = "Mednafen PCE Fast"
|
||||
manufacturer = "NEC"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Virtual Boy"
|
||||
display_name = "Virtual Boy (Mednafen VB)"
|
||||
supported_extensions = "vb|vboy|bin"
|
||||
corename = "Mednafen VB"
|
||||
manufacturer = "Nintendo"
|
||||
|
@ -1,6 +1,6 @@
|
||||
display_name = "WonderSwan (Color)"
|
||||
display_name = "WonderSwan/Color (Mednafen Cygne)"
|
||||
supported_extensions = "ws|wsc"
|
||||
corename = "Mednafen WonderSwan"
|
||||
manufacturer = "Bandai"
|
||||
systemname = "WonderSwan (Color)"
|
||||
systemname = "WonderSwan/Color"
|
||||
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Modelviewer"
|
||||
display_name = "3D Models (Modelviewer)"
|
||||
recommended_extensions = "obj"
|
||||
corename = "Modelviewer"
|
||||
manufacturer = "Various"
|
||||
|
@ -1,3 +1,3 @@
|
||||
display_name = "NXEngine (Cave Story)"
|
||||
display_name = "Cave Story (NXEngine)"
|
||||
supported_extensions = "exe"
|
||||
corename = "NXEngine"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Sega (MS/GG/MD/CD/32X)"
|
||||
display_name = "Sega MS/GG/MD/CD/32X (Picodrive)"
|
||||
supported_extensions = "md|smd|gen|sms|gg|sg|bin|cue|ios|32x"
|
||||
corename = "Picodrive"
|
||||
manufacturer = "Sega"
|
||||
|
@ -1,3 +1,3 @@
|
||||
display_name = "PrBoom (DOOM)"
|
||||
display_name = "Doom (PrBoom)"
|
||||
supported_extensions = "wad|iwad"
|
||||
corename = "prboom"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "SceneWalker"
|
||||
display_name = "3D Models (SceneWalker)"
|
||||
recommended_extensions = "obj"
|
||||
corename = "SceneWalker"
|
||||
manufacturer = "Various"
|
||||
|
@ -1,4 +1,4 @@
|
||||
display_name = "Atari 2600"
|
||||
display_name = "Atari 2600 (Stella)"
|
||||
supported_extensions = "a26|bin"
|
||||
corename = "Stella"
|
||||
manufacturer = "Atari"
|
||||
|
@ -1,3 +1,3 @@
|
||||
display_name = "TyrQuake"
|
||||
display_name = "Quake 1 (TyrQuake)"
|
||||
supported_extensions = "pak"
|
||||
corename = "prboom"
|
||||
|
@ -23,7 +23,7 @@ if [ -z "$NOCODESIGN" ] ; then
|
||||
|
||||
xcrun -sdk iphoneos PackageApplication "$BUILD_PATH/RetroArch.app" -o "$BUILD_PATH/RetroArch.ipa" --sign "$CODE_SIGN_IDENTITY" --embed "$BUILD_PATH/RetroArch.app/embedded.mobileprovision"
|
||||
else
|
||||
xcodebuild -verbose -sdk iphoneos -configuration Release
|
||||
xcodebuild -verbose -sdk iphoneos -configuration Release -project $PROJECT_NAME
|
||||
echo "Building for Jailbroken system"
|
||||
fi
|
||||
|
||||
|
@ -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
|
||||
|
@ -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;
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user