From 397b43b3e7af82f56eb7793b895a223bf704f25c Mon Sep 17 00:00:00 2001 From: Aaron Culliney Date: Sun, 10 Nov 2019 16:10:08 -0800 Subject: [PATCH] Improve joystick button reset procedure --- Android/jni/jnihooks.c | 2 +- src/cpu-supp.c | 2 +- src/interface.c | 6 +++--- src/joystick.c | 42 +++++++++++++++++++++++++----------------- src/joystick.h | 2 +- src/video/glnode.c | 2 +- src/vm.c | 2 +- 7 files changed, 33 insertions(+), 25 deletions(-) diff --git a/Android/jni/jnihooks.c b/Android/jni/jnihooks.c index efd00ee2..b6bf6e32 100644 --- a/Android/jni/jnihooks.c +++ b/Android/jni/jnihooks.c @@ -291,7 +291,7 @@ void Java_org_deadc0de_apple2ix_Apple2View_nativeRender(JNIEnv *env, jclass cls) void Java_org_deadc0de_apple2ix_Apple2Activity_nativeReboot(JNIEnv *env, jclass cls, jint resetState) { LOG("..."); if (resetState) { - // joystick button settings should be balanced by c_joystick_reset() triggered on CPU thread + // joystick button settings should be balanced by joystick_reset() triggered on CPU thread if (resetState == 1) { run_args.joy_button0 = 0xff; run_args.joy_button1 = 0x0; diff --git a/src/cpu-supp.c b/src/cpu-supp.c index c6d42fbe..7488c553 100644 --- a/src/cpu-supp.c +++ b/src/cpu-supp.c @@ -662,7 +662,7 @@ void cpu65_uninterrupt(int reason) { } void cpu65_reboot(void) { - run_args.joy_button0 = 0xff; // OpenApple -- should be balanced by c_joystick_reset() triggers on CPU thread + run_args.joy_button0 = 0xff; // OpenApple -- should be balanced by joystick_reset() triggers on CPU thread cpu65_interrupt(ResetSig); } diff --git a/src/interface.c b/src/interface.c index 4daf4a14..73c589ef 100644 --- a/src/interface.c +++ b/src/interface.c @@ -1089,7 +1089,7 @@ void c_interface_parameters() else if ((ch == kESC) || c_keys_is_interface_key(ch)) { timing_initialize(); - c_joystick_reset(); + joystick_reset(); #if !TESTING prefs_save(); #endif @@ -1183,7 +1183,7 @@ void c_interface_parameters() /* calibrate joystick */ if ((ch == 13) && (option == OPT_CALIBRATE)) { - c_joystick_reset(); + joystick_reset(); c_calibrate_joystick(); c_interface_print_screen( screen ); } @@ -1246,7 +1246,7 @@ void c_interface_parameters() ch = toupper(ch); if (ch == 'Y') { - c_joystick_reset(); + joystick_reset(); cpu65_reboot(); c_interface_exit(ch); break; diff --git a/src/joystick.c b/src/joystick.c index dc9cda01..74271de5 100644 --- a/src/joystick.c +++ b/src/joystick.c @@ -32,6 +32,11 @@ short joy_step = 1; bool joy_auto_recenter = false; #endif +static struct { + video_frame_callback_fn frameCallback; + uint8_t frameCount; +} joystickReset = { 0 }; + void (*joydriver_resetJoystick)(void) = NULL; static void joystick_prefsChanged(const char *domain) { @@ -59,8 +64,13 @@ static void joystick_prefsChanged(const char *domain) { #endif } -static __attribute__((constructor)) void _init_joystick(void) { +static void _init_joystick(void) { prefs_registerListener(PREF_DOMAIN_JOYSTICK, &joystick_prefsChanged); + video_registerFrameCallback(&joystickReset.frameCallback); +} + +static __attribute__((constructor)) void __init_joystick(void) { + emulator_registerStartupCallback(CTOR_PRIORITY_LATE, &_init_joystick); } #ifdef INTERFACE_CLASSIC @@ -270,24 +280,24 @@ void c_calibrate_joystick() #endif // INTERFACE_CLASSIC #if !TESTING -// HACK : avoid resetting joystick button values too quickly. This should allow for ClosedApple-Reset. (This is still a -// race, but hopefully much less likely to trigger). -static void *_joystick_resetDelayed(void *ctx) { - (void)ctx; - SCOPE_TRACE_INTERFACE("_joystick_resetDelayed"); +// NOTE : reset joystick buttons after a number of frames, which should allow for Open/Closed-Apple reset sequence. +void _joystick_frameCallback(uint8_t textFlashCounter) { + (void)textFlashCounter; - // delay - sleep(1); + // When activated, this is called every video frame -- ~16.688 millis - run_args.joy_button0 = 0x0; - run_args.joy_button1 = 0x0; + ASSERT_ON_CPU_THREAD(); - return NULL; + --joystickReset.frameCount; + if (joystickReset.frameCount == 0) { + run_args.joy_button0 = 0x0; + run_args.joy_button1 = 0x0; + joystickReset.frameCallback = NULL; // unlatch + } } #endif -void c_joystick_reset(void) -{ +void joystick_reset(void) { if (joydriver_resetJoystick) { joydriver_resetJoystick(); } @@ -297,10 +307,8 @@ void c_joystick_reset(void) run_args.joy_button0 = 0x0; run_args.joy_button1 = 0x0; #else - pthread_t pid; - int err = TEMP_FAILURE_RETRY(pthread_create(&pid, NULL, (void *)&_joystick_resetDelayed, (void *)NULL)); - assert(!err); - pthread_detach(pid); + joystickReset.frameCount = 2; // >= 1 full frame of processing insures that reset is handled + joystickReset.frameCallback = &_joystick_frameCallback; #endif joy_x = HALF_JOY_RANGE; diff --git a/src/joystick.h b/src/joystick.h index 3e2cdac5..781ff27f 100644 --- a/src/joystick.h +++ b/src/joystick.h @@ -43,7 +43,7 @@ extern bool joy_auto_recenter; extern short joy_step; #endif -void c_joystick_reset(void); +void joystick_reset(void); #ifdef INTERFACE_CLASSIC void c_calibrate_joystick(void); diff --git a/src/video/glnode.c b/src/video/glnode.c index b052452f..b6aa8302 100644 --- a/src/video/glnode.c +++ b/src/video/glnode.c @@ -134,7 +134,7 @@ static void _glnode_initGLUTPost(void) { glutSpecialUpFunc(gldriver_on_key_special_up); //glutMouseFunc(gldriver_mouse); //glutMotionFunc(gldriver_mouse_drag); - c_joystick_reset(); + joystick_reset(); } #endif diff --git a/src/vm.c b/src/vm.c index 021b57dd..d81f7982 100644 --- a/src/vm.c +++ b/src/vm.c @@ -1501,7 +1501,7 @@ void vm_initialize(void) { _initialize_tables(); disk6_init(); _initialize_iie_switches(); - c_joystick_reset(); + joystick_reset(); } bool vm_saveState(StateHelper_s *helper) {