From 7344cadfbd7460cde874e320fd9e86c59350091d Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sun, 2 Aug 2015 11:28:48 -0700 Subject: [PATCH] More joystick settings including calibration mode --- .../deadc0de/apple2ix/Apple2AbstractMenu.java | 4 + .../org/deadc0de/apple2ix/Apple2Activity.java | 15 +- .../deadc0de/apple2ix/Apple2DisksMenu.java | 4 + .../apple2ix/Apple2JoystickCalibration.java | 107 +++++++++++++++ .../apple2ix/Apple2JoystickSettingsMenu.java | 69 +++++----- .../apple2ix/Apple2KeypadSettingsMenu.java | 128 ++++++++++++++++++ .../org/deadc0de/apple2ix/Apple2MenuView.java | 2 + .../deadc0de/apple2ix/Apple2Preferences.java | 80 +++++++++-- .../deadc0de/apple2ix/Apple2SettingsMenu.java | 97 ++++++++++++- .../deadc0de/apple2ix/Apple2SplashScreen.java | 4 + .../layout/activity_calibrate_joystick.xml | 23 ++++ Android/app/src/main/res/values/strings.xml | 12 +- Android/jni/jnihooks.c | 6 - Android/jni/jniprefs.c | 25 ++++ src/joystick.c | 5 + src/joystick.h | 15 ++ src/video/gltouchjoy.c | 73 ++++++++-- 17 files changed, 590 insertions(+), 79 deletions(-) create mode 100644 Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java create mode 100644 Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java create mode 100644 Android/app/src/main/res/layout/activity_calibrate_joystick.xml diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java index 806dcc8b..c037c1b8 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2AbstractMenu.java @@ -59,6 +59,10 @@ public abstract class Apple2AbstractMenu implements Apple2MenuView { return mSettingsView; } + public boolean isCalibrating() { + return false; + } + // ------------------------------------------------------------------------ // required overrides ... diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java index e35fa31f..e25eacaf 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Activity.java @@ -400,7 +400,7 @@ public class Apple2Activity extends Activity { } Apple2MenuView apple2MenuView = peekApple2View(); - if (apple2MenuView != null) { + if ((apple2MenuView != null) && (!apple2MenuView.isCalibrating())) { break; } @@ -528,6 +528,19 @@ public class Apple2Activity extends Activity { return mMenuStack.get(lastIndex); } + public synchronized Apple2MenuView peekApple2View(int index) { + int lastIndex = mMenuStack.size() - 1; + if (lastIndex < 0) { + return null; + } + + try { + return mMenuStack.get(index); + } catch (IndexOutOfBoundsException e) { + return null; + } + } + public synchronized Apple2MenuView popApple2View(Apple2MenuView apple2MenuView) { boolean wasRemoved = mMenuStack.remove(apple2MenuView); _disposeApple2View(apple2MenuView); diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java index b6ec73a3..f35b6c14 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2DisksMenu.java @@ -121,6 +121,10 @@ public class Apple2DisksMenu implements Apple2MenuView { }); } + public final boolean isCalibrating() { + return false; + } + public void show() { if (isShowing()) { return; diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java new file mode 100644 index 00000000..d4969368 --- /dev/null +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickCalibration.java @@ -0,0 +1,107 @@ +/* + * Apple // emulator for *nix + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +package org.deadc0de.apple2ix; + +import android.content.Context; +import android.support.annotation.NonNull; +import android.view.LayoutInflater; +import android.view.View; +import android.widget.SeekBar; + +import java.util.ArrayList; + +public class Apple2JoystickCalibration implements Apple2MenuView { + + private final static String TAG = "Apple2JoystickCalibration"; + + private Apple2Activity mActivity = null; + private View mSettingsView = null; + private ArrayList mViewStack = null; + private boolean mTouchMenuEnabled = false; + private int mSavedTouchDevice = Apple2Preferences.TouchDeviceVariant.NONE.ordinal(); + + public Apple2JoystickCalibration(Apple2Activity activity, ArrayList viewStack, Apple2Preferences.TouchDeviceVariant variant) { + mActivity = activity; + mViewStack = viewStack; + if (!(variant == Apple2Preferences.TouchDeviceVariant.JOYSTICK || variant == Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD)) { + throw new RuntimeException("You're doing it wrong"); + } + + setup(variant); + } + + private void setup(Apple2Preferences.TouchDeviceVariant variant) { + LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE); + mSettingsView = inflater.inflate(R.layout.activity_calibrate_joystick, null, false); + + SeekBar sb = (SeekBar) mSettingsView.findViewById(R.id.seekBar); + sb.setOnSeekBarChangeListener(new SeekBar.OnSeekBarChangeListener() { + @Override + public void onProgressChanged(SeekBar seekBar, int progress, boolean fromUser) { + if (!fromUser) { + return; + } + Apple2Preferences.JOYSTICK_DIVIDER.saveInt(mActivity, progress); + } + + @Override + public void onStartTrackingTouch(SeekBar seekBar) { + } + + @Override + public void onStopTrackingTouch(SeekBar seekBar) { + } + }); + + sb.setMax(0); // http://stackoverflow.com/questions/10278467/seekbar-not-setting-actual-progress-setprogress-not-working-on-early-android + sb.setMax(Apple2Preferences.JOYSTICK_DIVIDER_NUM_CHOICES); + sb.setProgress(Apple2Preferences.JOYSTICK_DIVIDER.intValue(mActivity)); + + mTouchMenuEnabled = Apple2Preferences.TOUCH_MENU_ENABLED.booleanValue(mActivity); + Apple2Preferences.nativeSetTouchMenuEnabled(false); + mSavedTouchDevice = Apple2Preferences.CURRENT_TOUCH_DEVICE.intValue(mActivity); + Apple2Preferences.nativeSetCurrentTouchDevice(variant.ordinal()); + + Apple2Preferences.nativeTouchJoystickBeginCalibrationMode(); + } + + public final boolean isCalibrating() { + return true; + } + + public void show() { + if (isShowing()) { + return; + } + mActivity.pushApple2View(this); + } + + public void dismiss() { + for (Apple2MenuView apple2MenuView : mViewStack) { + mActivity.pushApple2View(apple2MenuView); + } + + Apple2Preferences.nativeSetTouchMenuEnabled(mTouchMenuEnabled); + Apple2Preferences.nativeSetCurrentTouchDevice(mSavedTouchDevice); + Apple2Preferences.nativeTouchJoystickEndCalibrationMode(); + + mActivity.popApple2View(this); + } + + public boolean isShowing() { + return mSettingsView.isShown(); + } + + public View getView() { + return mSettingsView; + } +} diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java index bb533b79..146dc18c 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2JoystickSettingsMenu.java @@ -16,6 +16,8 @@ import android.widget.CheckBox; import android.widget.CompoundButton; import android.widget.TextView; +import java.util.ArrayList; + public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { private final static String TAG = "Apple2JoystickSettingsMenu"; @@ -44,11 +46,11 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { if (position < 0 || position >= SETTINGS.size) { throw new ArrayIndexOutOfBoundsException(); } - return position != SETTINGS.AXIS_SENSITIVIY.ordinal() && position != SETTINGS.JOYSTICK_TAPDELAY.ordinal(); + return position != SETTINGS.JOYSTICK_AXIS_SENSITIVIY.ordinal(); } enum SETTINGS implements Apple2AbstractMenu.IMenuEnum { - AXIS_SENSITIVIY { + JOYSTICK_AXIS_SENSITIVIY { @Override public final String getTitle(Apple2Activity activity) { return ""; @@ -61,20 +63,21 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { @Override public View getView(final Apple2Activity activity, View convertView) { - return _sliderView(activity, this, Apple2Preferences.AXIS_SENSITIVITY_NUM_CHOICES, new IPreferenceSlider() { + return _sliderView(activity, this, Apple2Preferences.JOYSTICK_AXIS_SENSITIVITY_NUM_CHOICES, new IPreferenceSlider() { @Override public void saveInt(int progress) { - Apple2Preferences.AXIS_SENSITIVIY.saveInt(activity, progress); + Apple2Preferences.JOYSTICK_AXIS_SENSITIVIY.saveInt(activity, progress); } @Override public int intValue() { - return Apple2Preferences.AXIS_SENSITIVIY.intValue(activity); + return Apple2Preferences.JOYSTICK_AXIS_SENSITIVIY.intValue(activity); } @Override public void showValue(int progress, final TextView seekBarValue) { - int percent = (int) (Apple2Preferences.AXIS_SENSITIVIY.floatValue(activity) * 100.f); + saveInt(progress); + int percent = (int) (Apple2Preferences.JOYSTICK_AXIS_SENSITIVIY.floatValue(activity) * 100.f); seekBarValue.setText("" + percent + "%"); } }); @@ -194,37 +197,6 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { }); } }, - JOYSTICK_TAPDELAY { - @Override - public final String getTitle(Apple2Activity activity) { - return ""; - } - - @Override - public final String getSummary(Apple2Activity activity) { - return activity.getResources().getString(R.string.joystick_button_tapdelay_summary); - } - - @Override - public View getView(final Apple2Activity activity, View convertView) { - return _sliderView(activity, this, Apple2Preferences.TAPDELAY_NUM_CHOICES, new IPreferenceSlider() { - @Override - public void saveInt(int progress) { - Apple2Preferences.JOYSTICK_TAPDELAY.saveInt(activity, progress); - } - - @Override - public int intValue() { - return Apple2Preferences.JOYSTICK_TAPDELAY.intValue(activity); - } - - @Override - public void showValue(int progress, final TextView seekBarValue) { - seekBarValue.setText("" + (((float) progress / Apple2Preferences.TAPDELAY_NUM_CHOICES) * Apple2Preferences.TAPDELAY_SCALE)); - } - }); - } - }, JOYSTICK_CALIBRATE { @Override public final String getTitle(Apple2Activity activity) { @@ -238,7 +210,28 @@ public class Apple2JoystickSettingsMenu extends Apple2AbstractMenu { @Override public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) { - //new Apple2JoystickCalibration(activity).show(); + ArrayList viewStack = new ArrayList(); + { + int idx = 0; + while (true) { + Apple2MenuView apple2MenuView = activity.peekApple2View(idx); + if (apple2MenuView == null) { + break; + } + viewStack.add(apple2MenuView); + ++idx; + } + } + + Apple2JoystickCalibration calibration = new Apple2JoystickCalibration(activity, viewStack, Apple2Preferences.TouchDeviceVariant.JOYSTICK); + + // show this new view... + calibration.show(); + + // ...with nothing else underneath 'cept the emulator OpenGL layer + for (Apple2MenuView apple2MenuView : viewStack) { + activity.popApple2View(apple2MenuView); + } } }; diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java new file mode 100644 index 00000000..878daa10 --- /dev/null +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2KeypadSettingsMenu.java @@ -0,0 +1,128 @@ +/* + * Apple // emulator for *nix + * + * This software package is subject to the GNU General Public License + * version 2 or later (your choice) as published by the Free Software + * Foundation. + * + * THERE ARE NO WARRANTIES WHATSOEVER. + * + */ + +package org.deadc0de.apple2ix; + +import android.view.View; +import android.widget.CheckBox; +import android.widget.CompoundButton; +import android.widget.TextView; + +import java.util.ArrayList; + +public class Apple2KeypadSettingsMenu extends Apple2AbstractMenu { + + private final static String TAG = "Apple2KeypadSettingsMenu"; + + public Apple2KeypadSettingsMenu(Apple2Activity activity) { + super(activity); + } + + @Override + public final String[] allTitles() { + return SETTINGS.titles(mActivity); + } + + @Override + public final IMenuEnum[] allValues() { + return SETTINGS.values(); + } + + @Override + public final boolean areAllItemsEnabled() { + return true; + } + + @Override + public final boolean isEnabled(int position) { + if (position < 0 || position >= SETTINGS.size) { + throw new ArrayIndexOutOfBoundsException(); + } + return true; + } + + enum SETTINGS implements Apple2AbstractMenu.IMenuEnum { + KEYPAD_CHOOSE_BUTTONS { + @Override + public final String getTitle(Apple2Activity activity) { + return activity.getResources().getString(R.string.keypad_choose); + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.keypad_choose_summary); + } + + @Override + public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) { + //new Apple2KeypadChooser(activity).show(); + } + }, + KEYPAD_CALIBRATE { + @Override + public final String getTitle(Apple2Activity activity) { + return activity.getResources().getString(R.string.keypad_calibrate); + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.keypad_calibrate_summary); + } + + @Override + public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) { + ArrayList viewStack = new ArrayList(); + { + int idx = 0; + while (true) { + Apple2MenuView apple2MenuView = activity.peekApple2View(idx); + if (apple2MenuView == null) { + break; + } + viewStack.add(apple2MenuView); + ++idx; + } + } + + Apple2JoystickCalibration calibration = new Apple2JoystickCalibration(activity, viewStack, Apple2Preferences.TouchDeviceVariant.JOYSTICK_KEYPAD); + + // show this new view... + calibration.show(); + + // ...with nothing else underneath 'cept the emulator OpenGL layer + for (Apple2MenuView apple2MenuView : viewStack) { + activity.popApple2View(apple2MenuView); + } + } + }; + + public static final int size = SETTINGS.values().length; + + @Override + public void handleSelection(Apple2Activity activity, Apple2AbstractMenu settingsMenu, boolean isChecked) { + /* ... */ + } + + @Override + public View getView(Apple2Activity activity, View convertView) { + return _basicView(activity, this, convertView); + } + + public static String[] titles(Apple2Activity activity) { + String[] titles = new String[size]; + int i = 0; + for (SETTINGS setting : values()) { + titles[i++] = setting.getTitle(activity); + } + return titles; + } + } +} diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java index 741d0d71..4ffad6cd 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2MenuView.java @@ -22,4 +22,6 @@ public interface Apple2MenuView { public void dismiss(); public View getView(); + + public boolean isCalibrating(); } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java index c68a1516..82008eea 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2Preferences.java @@ -157,7 +157,7 @@ public enum Apple2Preferences { return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 5); } }, - AXIS_SENSITIVIY { + JOYSTICK_AXIS_SENSITIVIY { @Override public void load(Apple2Activity activity) { float sensitivity = floatValue(activity); @@ -166,25 +166,37 @@ public enum Apple2Preferences { @Override public int intValue(Apple2Activity activity) { - final int pivot = AXIS_SENSITIVITY_DEC_NUMCHOICES; + final int pivot = JOYSTICK_AXIS_SENSITIVITY_DEC_NUMCHOICES; return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), pivot); } @Override public float floatValue(Apple2Activity activity) { int tick = intValue(activity); - final int pivot = AXIS_SENSITIVITY_DEC_NUMCHOICES; + final int pivot = JOYSTICK_AXIS_SENSITIVITY_DEC_NUMCHOICES; float sensitivity = 1.f; if (tick < pivot) { int decAmount = (pivot - tick); - sensitivity -= (AXIS_SENSITIVITY_DEC * decAmount); + sensitivity -= (JOYSTICK_AXIS_SENSITIVITY_DEC_STEP * decAmount); } else if (tick > pivot) { int incAmount = (tick - pivot); - sensitivity += (AXIS_SENSITIVITY_INC * incAmount); + sensitivity += (JOYSTICK_AXIS_SENSITIVITY_INC_STEP * incAmount); } return sensitivity; } }, + JOYSTICK_BUTTON_THRESHOLD { + @Override + public void load(Apple2Activity activity) { + int tick = intValue(activity); + nativeSetTouchJoystickButtonSwitchThreshold(tick * JOYSTICK_BUTTON_THRESHOLD_STEP); + } + + @Override + public int intValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), 5); + } + }, JOYSTICK_TAP_BUTTON { @Override public void load(Apple2Activity activity) { @@ -230,6 +242,29 @@ public enum Apple2Preferences { public int intValue(Apple2Activity activity) { return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), TouchJoystickButtons.BUTTON2.ordinal()); } + }, + JOYSTICK_AXIS_ON_LEFT { + @Override + public void load(Apple2Activity activity) { + nativeTouchJoystickSetAxisOnLeft(booleanValue(activity)); + } + + @Override + public boolean booleanValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getBoolean(toString(), true); + } + }, + JOYSTICK_DIVIDER { + @Override + public void load(Apple2Activity activity) { + int tick = intValue(activity); + nativeTouchJoystickSetScreenDivision(((float) tick / JOYSTICK_DIVIDER_NUM_CHOICES)); + } + + @Override + public int intValue(Apple2Activity activity) { + return activity.getPreferences(Context.MODE_PRIVATE).getInt(toString(), JOYSTICK_DIVIDER_NUM_CHOICES>>1); + } }; public enum HiresColor { @@ -298,19 +333,24 @@ public enum Apple2Preferences { public final static int DECENT_AMOUNT_OF_CHOICES = 20; public final static int AUDIO_LATENCY_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES; public final static int ALPHA_SLIDER_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES; + public final static int JOYSTICK_DIVIDER_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES; + public final static int TAPDELAY_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES; public final static float TAPDELAY_SCALE = 0.5f; + public final static String TAG = "Apple2Preferences"; - public final static float AXIS_SENSITIVITY_MIN = 0.25f; - public final static float AXIS_SENSITIVITY_DEFAULT = 1.f; - public final static float AXIS_SENSITIVITY_MAX = 4.f; - public final static float AXIS_SENSITIVITY_DEC = 0.05f; - public final static float AXIS_SENSITIVITY_INC = 0.25f; - public final static int AXIS_SENSITIVITY_DEC_NUMCHOICES = (int) ((AXIS_SENSITIVITY_DEFAULT - AXIS_SENSITIVITY_MIN) / AXIS_SENSITIVITY_DEC); // 15 - public final static int AXIS_SENSITIVITY_INC_NUMCHOICES = (int) ((AXIS_SENSITIVITY_MAX - AXIS_SENSITIVITY_DEFAULT) / AXIS_SENSITIVITY_INC); // 12 - public final static int AXIS_SENSITIVITY_NUM_CHOICES = AXIS_SENSITIVITY_DEC_NUMCHOICES + AXIS_SENSITIVITY_INC_NUMCHOICES; // 15 + 12 + public final static int JOYSTICK_BUTTON_THRESHOLD_NUM_CHOICES = DECENT_AMOUNT_OF_CHOICES; + public final static int JOYSTICK_BUTTON_THRESHOLD_STEP = 5; + public final static float JOYSTICK_AXIS_SENSITIVITY_MIN = 0.25f; + public final static float JOYSTICK_AXIS_SENSITIVITY_DEFAULT = 1.f; + public final static float JOYSTICK_AXIS_SENSITIVITY_MAX = 4.f; + public final static float JOYSTICK_AXIS_SENSITIVITY_DEC_STEP = 0.05f; + public final static float JOYSTICK_AXIS_SENSITIVITY_INC_STEP = 0.25f; + public final static int JOYSTICK_AXIS_SENSITIVITY_DEC_NUMCHOICES = (int) ((JOYSTICK_AXIS_SENSITIVITY_DEFAULT - JOYSTICK_AXIS_SENSITIVITY_MIN) / JOYSTICK_AXIS_SENSITIVITY_DEC_STEP); // 15 + public final static int JOYSTICK_AXIS_SENSITIVITY_INC_NUMCHOICES = (int) ((JOYSTICK_AXIS_SENSITIVITY_MAX - JOYSTICK_AXIS_SENSITIVITY_DEFAULT) / JOYSTICK_AXIS_SENSITIVITY_INC_STEP); // 12 + public final static int JOYSTICK_AXIS_SENSITIVITY_NUM_CHOICES = JOYSTICK_AXIS_SENSITIVITY_DEC_NUMCHOICES + JOYSTICK_AXIS_SENSITIVITY_INC_NUMCHOICES; // 15 + 12 // set and apply @@ -387,7 +427,7 @@ public enum Apple2Preferences { private static native void nativeSetAudioLatency(float latencySecs); - private static native void nativeSetCurrentTouchDevice(int device); + public static native void nativeSetCurrentTouchDevice(int device); private static native void nativeSetTouchJoystickButtonTypes(int down, int north, int south); @@ -395,7 +435,9 @@ public enum Apple2Preferences { private static native void nativeSetTouchJoystickAxisSensitivity(float multiplier); - private static native void nativeSetTouchMenuEnabled(boolean enabled); + private static native void nativeSetTouchJoystickButtonSwitchThreshold(int delta); + + public static native void nativeSetTouchMenuEnabled(boolean enabled); private static native void nativeSetTouchMenuVisibility(float alpha); @@ -404,4 +446,12 @@ public enum Apple2Preferences { public static native int nativeGetCPUSpeed(); public static native void nativeSetCPUSpeed(int percentSpeed); + + public static native void nativeTouchJoystickSetScreenDivision(float division); + + public static native void nativeTouchJoystickSetAxisOnLeft(boolean axisIsOnLeft); + + public static native void nativeTouchJoystickBeginCalibrationMode(); + + public static native void nativeTouchJoystickEndCalibrationMode(); } diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java index 58b0604c..5809b7d0 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SettingsMenu.java @@ -40,7 +40,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu { @Override public final boolean areAllItemsEnabled() { - return true; + return false; } @Override @@ -48,7 +48,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu { if (position < 0 || position >= SETTINGS.size) { throw new ArrayIndexOutOfBoundsException(); } - return true; + return position != SETTINGS.JOYSTICK_TAPDELAY.ordinal() && position != SETTINGS.JOYSTICK_BUTTON_THRESHOLD.ordinal(); } enum SETTINGS implements Apple2AbstractMenu.IMenuEnum { @@ -94,6 +94,7 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu { public void saveInt(int progress) { Apple2Preferences.TOUCH_MENU_VISIBILITY.saveInt(activity, progress); } + @Override public int intValue() { return Apple2Preferences.TOUCH_MENU_VISIBILITY.intValue(activity); @@ -172,7 +173,97 @@ public class Apple2SettingsMenu extends Apple2AbstractMenu { @Override public void handleSelection(final Apple2Activity activity, final Apple2AbstractMenu settingsMenu, boolean isChecked) { - //new Apple2JoystickSettingsMenu(activity).show(); + new Apple2KeypadSettingsMenu(activity).show(); + } + }, + JOYSTICK_TAPDELAY { + @Override + public final String getTitle(Apple2Activity activity) { + return ""; + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.joystick_button_tapdelay_summary); + } + + @Override + public View getView(final Apple2Activity activity, View convertView) { + return _sliderView(activity, this, Apple2Preferences.TAPDELAY_NUM_CHOICES, new IPreferenceSlider() { + @Override + public void saveInt(int progress) { + Apple2Preferences.JOYSTICK_TAPDELAY.saveInt(activity, progress); + } + + @Override + public int intValue() { + return Apple2Preferences.JOYSTICK_TAPDELAY.intValue(activity); + } + + @Override + public void showValue(int progress, final TextView seekBarValue) { + seekBarValue.setText("" + (((float) progress / Apple2Preferences.TAPDELAY_NUM_CHOICES) * Apple2Preferences.TAPDELAY_SCALE)); + } + }); + } + }, + JOYSTICK_AXIS_ON_LEFT { + @Override + public final String getTitle(Apple2Activity activity) { + return activity.getResources().getString(R.string.joystick_axisleft); + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.joystick_axisleft_summary); + } + + @Override + public View getView(final Apple2Activity activity, View convertView) { + convertView = _basicView(activity, this, convertView); + CheckBox cb = _addCheckbox(activity, this, convertView, Apple2Preferences.JOYSTICK_AXIS_ON_LEFT.booleanValue(activity)); + cb.setOnCheckedChangeListener(new CompoundButton.OnCheckedChangeListener() { + @Override + public void onCheckedChanged(CompoundButton buttonView, boolean isChecked) { + Apple2Preferences.JOYSTICK_AXIS_ON_LEFT.saveBoolean(activity, isChecked); + } + }); + return convertView; + } + }, + JOYSTICK_BUTTON_THRESHOLD { + @Override + public final String getTitle(Apple2Activity activity) { + return ""; + } + + @Override + public final String getSummary(Apple2Activity activity) { + return activity.getResources().getString(R.string.joystick_button_threshold_summary); + } + + @Override + public View getView(final Apple2Activity activity, View convertView) { + return _sliderView(activity, this, Apple2Preferences.JOYSTICK_BUTTON_THRESHOLD_NUM_CHOICES, new IPreferenceSlider() { + @Override + public void saveInt(int progress) { + if (progress == 0) { + progress = 1; + } + Apple2Preferences.JOYSTICK_BUTTON_THRESHOLD.saveInt(activity, progress); + } + + @Override + public int intValue() { + return Apple2Preferences.JOYSTICK_BUTTON_THRESHOLD.intValue(activity); + } + + @Override + public void showValue(int progress, final TextView seekBarValue) { + int threshold = progress * Apple2Preferences.JOYSTICK_BUTTON_THRESHOLD_STEP; + seekBarValue.setText("" + threshold + " pts"); + } + }); } }, KEYBOARD_CONFIGURE { diff --git a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java index 8764b69b..1ea23f24 100644 --- a/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java +++ b/Android/app/src/main/java/org/deadc0de/apple2ix/Apple2SplashScreen.java @@ -53,6 +53,10 @@ public class Apple2SplashScreen implements Apple2MenuView { }); } + public final boolean isCalibrating() { + return false; + } + public void show() { if (isShowing()) { return; diff --git a/Android/app/src/main/res/layout/activity_calibrate_joystick.xml b/Android/app/src/main/res/layout/activity_calibrate_joystick.xml new file mode 100644 index 00000000..abbb40c3 --- /dev/null +++ b/Android/app/src/main/res/layout/activity_calibrate_joystick.xml @@ -0,0 +1,23 @@ + + + + + diff --git a/Android/app/src/main/res/values/strings.xml b/Android/app/src/main/res/values/strings.xml index a0cf2f28..522207a8 100644 --- a/Android/app/src/main/res/values/strings.xml +++ b/Android/app/src/main/res/values/strings.xml @@ -41,23 +41,29 @@ None Tap fire Button to fire on tap down - Tap delay in secs (interval to determine if tap or swipe) + Joystick/keypad tap delay in secs Swipe up fire Button to fire on swipe up Swipe down fire Button to fire on swipe down + Joystick/keypad button switch threshold in pts Calibrate… Configure and test current settings Configure joystick… Axis touch/tilt, buttons, etc Current joystick flavor Emulated physical joystick or keypad - Swap axis and buttons - Axis target on right and button + Joystick/keypad axis on left + Joystick/keypad axis on left (buttons on right) Keypad Joystick Touch Keypad Joystick + Calibrate… + Configure and test current settings + Choose keys… + Choose axis and button keys Configure keypad joystick… Axis touch/tilt, buttons, etc + Keypad sensitivity threshold Keyboard Configure keyboard… Transparency, fading, custom keys diff --git a/Android/jni/jnihooks.c b/Android/jni/jnihooks.c index 13ef36f2..5492fa28 100644 --- a/Android/jni/jnihooks.c +++ b/Android/jni/jnihooks.c @@ -281,12 +281,6 @@ jlong Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnTouch(JNIEnv *env, jobje return 0x0LL; } - if (cpu_isPaused()) { - LOG("UNPAUSING NATIVE CPU THREAD"); - cpu_resume(); - return 0x0LL; - } - jfloat *x_coords = (*env)->GetFloatArrayElements(env, xCoords, 0); jfloat *y_coords = (*env)->GetFloatArrayElements(env, yCoords, 0); diff --git a/Android/jni/jniprefs.c b/Android/jni/jniprefs.c index 64db15ef..8f1776ef 100644 --- a/Android/jni/jniprefs.c +++ b/Android/jni/jniprefs.c @@ -160,6 +160,31 @@ void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickAxisSens joydriver_setTouchAxisSensitivity(multiplier); } +void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeSetTouchJoystickButtonSwitchThreshold(JNIEnv *env, jclass cls, jint delta) { + LOG("nativeSetTouchJoystickButtonSwitchThreshold() : %d", delta); + joydriver_setButtonSwitchThreshold(delta); +} + +void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeTouchJoystickSetScreenDivision(JNIEnv *env, jclass cls, jfloat division) { + LOG("nativeTouchJoystickSetScreenDivision() : %f", division); + joydriver_setScreenDivision(division); +} + +void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeTouchJoystickSetAxisOnLeft(JNIEnv *env, jclass cls, jboolean axisIsOnLeft) { + LOG("nativeTouchJoystickSetAxisOnLeft() : %d", axisIsOnLeft); + joydriver_setAxisOnLeft(axisIsOnLeft); +} + +void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeTouchJoystickBeginCalibrationMode(JNIEnv *env, jclass cls) { + LOG("nativeTouchJoystickBeginCalibrationMode() ..."); + joydriver_beginCalibration(); +} + +void Java_org_deadc0de_apple2ix_Apple2Preferences_nativeTouchJoystickEndCalibrationMode(JNIEnv *env, jclass cls) { + LOG("nativeTouchJoystickEndCalibrationMode() ..."); + joydriver_endCalibration(); +} + jint Java_org_deadc0de_apple2ix_Apple2Preferences_nativeGetCPUSpeed(JNIEnv *env, jclass cls) { LOG("nativeGetCPUSpeed() ..."); return (jint)round(cpu_scale_factor * 100.0); diff --git a/src/joystick.c b/src/joystick.c index 66c8e96a..c0f53fc4 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -265,8 +265,13 @@ void (*joydriver_setTouchButtonValues)(char button0Val, char button1Val, char bu void (*joydriver_setTouchButtonTypes)(touchjoy_button_type_t down, touchjoy_button_type_t north, touchjoy_button_type_t south) = NULL; void (*joydriver_setTapDelay)(float secs) = NULL; void (*joydriver_setTouchAxisSensitivity)(float multiplier) = NULL; +void (*joydriver_setButtonSwitchThreshold)(int delta) = NULL; void (*joydriver_setTouchVariant)(touchjoy_variant_t variant) = NULL; touchjoy_variant_t (*joydriver_getTouchVariant)(void) = NULL; void (*joydriver_setTouchAxisValues)(char up, char left, char right, char down) = NULL; +void (*joydriver_setScreenDivision)(float division) = NULL; +void (*joydriver_setAxisOnLeft)(bool axisIsOnLeft) = NULL; +void (*joydriver_beginCalibration)(void) = NULL; +void (*joydriver_endCalibration)(void) = NULL; #endif diff --git a/src/joystick.h b/src/joystick.h index b8b39f97..cd2f2aaf 100644 --- a/src/joystick.h +++ b/src/joystick.h @@ -70,6 +70,9 @@ extern void (*joydriver_setTapDelay)(float secs); // set the touch axis sensitivity multiplier extern void (*joydriver_setTouchAxisSensitivity)(float multiplier); +// set the touch button switch threshold +extern void (*joydriver_setButtonSwitchThreshold)(int delta); + // set the joystick variant extern void (*joydriver_setTouchVariant)(touchjoy_variant_t variant); @@ -79,6 +82,18 @@ extern touchjoy_variant_t (*joydriver_getTouchVariant)(void); // set the axis visuals (these key values are also fired for keyboard variant) extern void (*joydriver_setTouchAxisValues)(char north, char west, char east, char south); +// set screen divide between axis and buttons +extern void (*joydriver_setScreenDivision)(float division); + +// swap axis and buttons sides +extern void (*joydriver_setAxisOnLeft)(bool axisIsOnLeft); + +// begin calibration mode +extern void (*joydriver_beginCalibration)(void); + +// end calibration mode +extern void (*joydriver_endCalibration)(void); + #endif // INTERFACE_TOUCH #endif // whole file diff --git a/src/video/gltouchjoy.c b/src/video/gltouchjoy.c index 090d715e..5edede29 100644 --- a/src/video/gltouchjoy.c +++ b/src/video/gltouchjoy.c @@ -436,20 +436,38 @@ static void gltouchjoy_render(void) { static void gltouchjoy_reshape(int w, int h) { LOG("gltouchjoy_reshape(%d, %d)", w, h); - touchport.axisX = 0; - touchport.axisY = 0; - touchport.buttonY = 0; + if (joyglobals.axisIsOnLeft) { + touchport.axisX = 0; + touchport.axisY = 0; + touchport.buttonY = 0; - if (w > touchport.width) { - touchport.width = w; - touchport.axisXMax = w>>1; - touchport.buttonX = w>>1; - touchport.buttonXMax = w; - } - if (h > touchport.height) { - touchport.height = h; - touchport.axisYMax = h; - touchport.buttonYMax = h; + if (w >= touchport.width) { + touchport.width = w; + touchport.axisXMax = (w * joyglobals.screenDivider); + touchport.buttonX = (w * joyglobals.screenDivider); + touchport.buttonXMax = w; + } + if (h >= touchport.height) { + touchport.height = h; + touchport.axisYMax = h; + touchport.buttonYMax = h; + } + } else { + touchport.buttonX = 0; + touchport.buttonY = 0; + touchport.axisY = 0; + + if (w >= touchport.width) { + touchport.width = w; + touchport.buttonXMax = (w * joyglobals.screenDivider); + touchport.axisX = (w * joyglobals.screenDivider); + touchport.axisXMax = w; + } + if (h >= touchport.height) { + touchport.height = h; + touchport.buttonYMax = h; + touchport.axisYMax = h; + } } } @@ -732,6 +750,10 @@ static void gltouchjoy_setTouchAxisSensitivity(float multiplier) { axes.multiplier = multiplier; } +static void gltouchjoy_setButtonSwitchThreshold(int delta) { + buttons.switchThreshold = delta; +} + static void gltouchjoy_setTouchVariant(touchjoy_variant_t axisType) { axes.type = axisType; _setup_axis_object(axes.model); @@ -749,6 +771,26 @@ static void gltouchjoy_setTouchAxisValues(char north, char west, char east, char _setup_axis_object(axes.model); } +static void gltouchjoy_setScreenDivision(float screenDivider) { + joyglobals.screenDivider = screenDivider; + // force reshape here to apply changes ... + gltouchjoy_reshape(touchport.width, touchport.height); +} + +static void gltouchjoy_setAxisOnLeft(bool axisIsOnLeft) { + joyglobals.axisIsOnLeft = axisIsOnLeft; + // force reshape here to apply changes ... + gltouchjoy_reshape(touchport.width, touchport.height); +} + +static void gltouchjoy_beginCalibration(void) { + joyglobals.isCalibrating = true; +} + +static void gltouchjoy_endCalibration(void) { + joyglobals.isCalibrating = false; +} + __attribute__((constructor(CTOR_PRIORITY_LATE))) static void _init_gltouchjoy(void) { LOG("Registering OpenGL software touch joystick"); @@ -798,9 +840,14 @@ static void _init_gltouchjoy(void) { joydriver_setTouchButtonTypes = &gltouchjoy_setTouchButtonTypes; joydriver_setTapDelay = &gltouchjoy_setTapDelay; joydriver_setTouchAxisSensitivity = &gltouchjoy_setTouchAxisSensitivity; + joydriver_setButtonSwitchThreshold = &gltouchjoy_setButtonSwitchThreshold; joydriver_setTouchVariant = &gltouchjoy_setTouchVariant; joydriver_getTouchVariant = &gltouchjoy_getTouchVariant; joydriver_setTouchAxisValues = &gltouchjoy_setTouchAxisValues; + joydriver_setScreenDivision = &gltouchjoy_setScreenDivision; + joydriver_setAxisOnLeft = &gltouchjoy_setAxisOnLeft; + joydriver_beginCalibration = &gltouchjoy_beginCalibration; + joydriver_endCalibration = &gltouchjoy_endCalibration; glnode_registerNode(RENDER_LOW, (GLNode){ .setup = &gltouchjoy_setup,