Lightly refactor joystick and button handling during reset

- Remove unused button2 variable
    - Remake little-used backend joystick reset function as function pointer
    - Allow soft reset and self-test on Android (although there is still a race condition due to code that directly sets
      joy_button[12] values
This commit is contained in:
Aaron Culliney 2016-04-17 11:26:35 -07:00
parent 13184ec4be
commit 3ed159dd0b
13 changed files with 100 additions and 35 deletions

View File

@ -83,7 +83,7 @@ public class Apple2Activity extends Activity {
private static native void nativeOnQuit();
private static native void nativeReboot();
private static native void nativeReboot(int resetState);
public final static boolean isNativeBarfed() {
return sNativeBarfed;
@ -513,8 +513,8 @@ public class Apple2Activity extends Activity {
}
}
public void rebootEmulation() {
nativeReboot();
public void rebootEmulation(int resetState) {
nativeReboot(resetState);
}
public void saveState(String stateFile) {

View File

@ -23,9 +23,11 @@ import android.view.View;
import android.view.ViewGroup;
import android.widget.AdapterView;
import android.widget.ArrayAdapter;
import android.widget.CompoundButton;
import android.widget.LinearLayout;
import android.widget.ListView;
import android.widget.PopupWindow;
import android.widget.RadioButton;
import android.widget.TextView;
import org.deadc0de.apple2ix.basic.R;
@ -250,14 +252,30 @@ public class Apple2MainMenu {
final AtomicBoolean selectionAlreadyHandled = new AtomicBoolean(false);
AlertDialog rebootQuitDialog = new AlertDialog.Builder(mActivity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.quit_reboot).setMessage(R.string.quit_reboot_choice).setPositiveButton(R.string.reboot, new DialogInterface.OnClickListener() {
LayoutInflater inflater = (LayoutInflater) mActivity.getSystemService(Context.LAYOUT_INFLATER_SERVICE);
final View resetConfirmationView = inflater.inflate(R.layout.a2reset_confirmation, null, false);
final RadioButton openAppleSelected = (RadioButton) resetConfirmationView.findViewById(R.id.radioButton_openApple);
openAppleSelected.setChecked(true);
final RadioButton closedAppleSelected = (RadioButton) resetConfirmationView.findViewById(R.id.radioButton_closedApple);
closedAppleSelected.setChecked(false);
final RadioButton noAppleSelected = (RadioButton) resetConfirmationView.findViewById(R.id.radioButton_noApple);
noAppleSelected.setChecked(false);
AlertDialog.Builder builder = new AlertDialog.Builder(mActivity).setIcon(R.drawable.ic_launcher).setCancelable(true).setTitle(R.string.quit_reboot).setMessage(R.string.quit_reboot_choice).setPositiveButton(R.string.reset, new DialogInterface.OnClickListener() {
@Override
public void onClick(DialogInterface dialog, int which) {
if (!selectionAlreadyHandled.compareAndSet(false, true)) {
Log.v(TAG, "OMG, avoiding nasty UI race in reboot/quit onClick()");
return;
}
mActivity.rebootEmulation();
int resetState = 0;
if (openAppleSelected.isChecked()) {
resetState = 1;
} else if (closedAppleSelected.isChecked()) {
resetState = 2;
}
mActivity.rebootEmulation(resetState);
Apple2MainMenu.this.dismiss();
}
}).setNeutralButton(R.string.quit, new DialogInterface.OnClickListener() {
@ -269,7 +287,10 @@ public class Apple2MainMenu {
}
mActivity.quitEmulator();
}
}).setNegativeButton(R.string.cancel, null).create();
}).setNegativeButton(R.string.cancel, null);
builder.setView(resetConfirmationView);
AlertDialog rebootQuitDialog = builder.create();
mActivity.registerAndShowDialog(rebootQuitDialog);
}

View File

@ -0,0 +1,37 @@
<?xml version="1.0" encoding="utf-8"?>
<LinearLayout xmlns:android="http://schemas.android.com/apk/res/android"
android:layout_width="fill_parent"
android:layout_height="fill_parent"
android:background="@color/black"
android:baselineAligned="false"
android:orientation="vertical">
<RadioGroup
android:layout_width="fill_parent"
android:layout_height="wrap_content"
android:orientation="horizontal">
<RadioButton
android:id="@+id/radioButton_openApple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/reboot" />
<RadioButton
android:id="@+id/radioButton_closedApple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/reset_self_test" />
<RadioButton
android:id="@+id/radioButton_noApple"
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:layout_weight="1"
android:text="@string/reset_soft" />
</RadioGroup>
</LinearLayout>

View File

@ -149,9 +149,12 @@
<string name="preferences_reset_really">Really reset and quit?</string>
<string name="preferences_reset_warning">You will lose your settings</string>
<string name="quit">Quit</string>
<string name="quit_reboot">Reboot or quit emulator…</string>
<string name="quit_reboot_choice">Reboot or quit?</string>
<string name="quit_reboot">Reset or quit emulator…</string>
<string name="quit_reboot_choice">Reset/reboot or quit?</string>
<string name="reboot">Reboot</string>
<string name="reset">Reset</string>
<string name="reset_self_test">Self Test</string>
<string name="reset_soft">Soft</string>
<string name="restore">Quick restore</string>
<string name="save">Quick save</string>
<string name="saverestore">Save &amp; restore…</string>

View File

@ -269,9 +269,18 @@ void Java_org_deadc0de_apple2ix_Apple2View_nativeRender(JNIEnv *env, jclass cls)
video_render();
}
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jclass cls) {
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jclass cls, jint resetState) {
LOG("...");
cpu65_reboot();
if (resetState) {
if (resetState == 1) {
joy_button0 = 0xff;
joy_button1 = 0x0;
} else {
joy_button0 = 0x0;
joy_button1 = 0xff;
}
}
cpu65_interrupt(ResetSig);
}
void Java_org_deadc0de_apple2ix_Apple2Activity_nativeOnQuit(JNIEnv *env, jclass cls) {

View File

@ -21,10 +21,6 @@
- (void)resetJoysticks;
@end
void gldriver_joystick_reset(void) {
[EmulatorJoystickController sharedInstance];
}
@implementation EmulatorJoystickController
@synthesize allJoysticks = _allJoysticks;

View File

@ -27,7 +27,6 @@ uint16_t joy_x = HALF_JOY_RANGE;
uint16_t joy_y = HALF_JOY_RANGE;
uint8_t joy_button0 = 0;
uint8_t joy_button1 = 0;
uint8_t joy_button2 = 0; // unused?
bool joy_clip_to_radius = false;
#ifdef KEYPAD_JOYSTICK
@ -35,6 +34,8 @@ short joy_step = 1;
bool joy_auto_recenter = false;
#endif
void (*joydriver_resetJoystick)(void) = NULL;
static void joystick_prefsChanged(const char *domain) {
assert(strcmp(domain, PREF_DOMAIN_JOYSTICK) == 0);
@ -263,22 +264,17 @@ void c_calibrate_joystick()
}
#endif // INTERFACE_CLASSIC
extern void gldriver_joystick_reset(void);
void c_joystick_reset(void)
{
#if VIDEO_OPENGL && !TESTING
gldriver_joystick_reset();
#endif
if (joydriver_resetJoystick) {
joydriver_resetJoystick();
}
joy_button0 = 0x0;
joy_button1 = 0x0;
joy_button2 = 0x0;
#ifdef KEYPAD_JOYSTICK
if (joy_mode == JOY_KPAD)
{
joy_x = HALF_JOY_RANGE;
joy_y = HALF_JOY_RANGE;
}
#endif
joy_x = HALF_JOY_RANGE;
joy_y = HALF_JOY_RANGE;
}
// clamps modern gamepad controller axis values to the "corners" of a traditional joystick as used on the Apple //e

View File

@ -30,7 +30,6 @@ extern uint16_t joy_x;
extern uint16_t joy_y;
extern uint8_t joy_button0;
extern uint8_t joy_button1;
extern uint8_t joy_button2;
extern bool joy_clip_to_radius;
#ifdef KEYPAD_JOYSTICK
@ -62,6 +61,9 @@ void joydriver_setButton0Pressed(bool pressed);
// set button 1 pressed
void joydriver_setButton1Pressed(bool pressed);
// backend joystick driver reset procedure
extern void (*joydriver_resetJoystick)(void);
#if INTERFACE_TOUCH
typedef enum touchjoy_button_type_t {

View File

@ -26,5 +26,5 @@ void gldriver_on_key_special_down(int key, int x, int y);
void gldriver_on_key_special_up(int key, int x, int y);
// reset joystick function
void gldriver_joystick_reset(void);
void _glutJoystickReset(void);

View File

@ -135,6 +135,7 @@ static void _glnode_initGLUTPost(void) {
glutSpecialUpFunc(gldriver_on_key_special_up);
//glutMouseFunc(gldriver_mouse);
//glutMotionFunc(gldriver_mouse_drag);
c_joystick_reset();
#endif
}
#endif
@ -253,6 +254,10 @@ static void _init_glnode_manager(void) {
#if INTERFACE_TOUCH
interface_onTouchEvent = &glnode_onTouchEvent;
#endif
#if USE_GLUT
joydriver_resetJoystick = &_glutJoystickReset;
#endif
}
static __attribute__((constructor)) void __init_glnode_manager(void) {

View File

@ -949,7 +949,3 @@ void gltouchjoy_registerVariant(interface_device_t variantType, GLTouchJoyVarian
}
}
void gldriver_joystick_reset(void) {
#warning FIXME TODO expunge this olde API ...
}

View File

@ -227,7 +227,7 @@ void gldriver_mouse(int button, int state, int x, int y) {
}
#endif
void gldriver_joystick_reset(void) {
void _glutJoystickReset(void) {
glutJoystickFunc(NULL, 0);
glutJoystickFunc(gldriver_joystick_callback, (int)JOYSTICK_POLL_INTERVAL_MILLIS);
}

View File

@ -298,7 +298,7 @@ GLUE_C_READ(read_button1)
GLUE_C_READ(read_button2)
{
return joy_button2;
return joy_button0 | joy_button1;
}
GLUE_C_READ(read_gc_strobe)