@@ -1515,11 +1515,40 @@ static int16_t input_state_device(
15151515
15161516 if (id <= RETRO_DEVICE_ID_JOYPAD_R3 )
15171517 {
1518- /* Apply turbo button if activated. */
15191518 uint8_t turbo_period = settings -> uints .input_turbo_period ;
15201519 uint8_t turbo_duty_cycle = settings -> uints .input_turbo_duty_cycle ;
15211520 uint8_t turbo_mode = settings -> uints .input_turbo_mode ;
15221521
1522+ /* Apply hold button logic.
1523+ * When hold modifier is pressed, tapping buttons toggles their held state.
1524+ * Held buttons report as pressed even when not physically touched.
1525+ * Physical presses pass through normally (no modification). */
1526+
1527+ /* Handle hold modifier state and toggle logic */
1528+ if (!input_st -> hold_btns .frame_enable [port ])
1529+ {
1530+ /* Hold modifier not pressed - clear edge detection state */
1531+ input_st -> hold_btns .hold_pressed [port ] = 0 ;
1532+ }
1533+ else
1534+ {
1535+ /* Hold modifier is pressed - handle toggle on rising edge */
1536+ if (!res )
1537+ input_st -> hold_btns .hold_pressed [port ] &= ~(1 << id );
1538+ else if (!(input_st -> hold_btns .hold_pressed [port ] & (1 << id )))
1539+ {
1540+ /* Rising edge - toggle hold for this button */
1541+ input_st -> hold_btns .hold_pressed [port ] |= (1 << id );
1542+ input_st -> hold_btns .enable [port ] ^= (1 << id );
1543+ }
1544+ }
1545+
1546+ /* Apply hold effect: if button is held and not physically pressed */
1547+ if (!res && (input_st -> hold_btns .enable [port ] & (1 << id )))
1548+ res = 1 ;
1549+
1550+ /* Apply turbo button if activated. */
1551+
15231552 /* Don't allow classic mode turbo for D-pad unless explicitly allowed. */
15241553 if ( turbo_mode <= INPUT_TURBO_MODE_CLASSIC_TOGGLE
15251554 && !settings -> bools .input_turbo_allow_dpad
@@ -6091,7 +6120,10 @@ void input_driver_poll(void)
60916120 if (input_st -> flags & INP_FLAG_BLOCK_LIBRETRO_INPUT )
60926121 {
60936122 for (i = 0 ; i < max_users ; i ++ )
6123+ {
60946124 input_st -> turbo_btns .frame_enable [i ] = 0 ;
6125+ input_st -> hold_btns .frame_enable [i ] = 0 ;
6126+ }
60956127 return ;
60966128 }
60976129
@@ -6130,6 +6162,27 @@ void input_driver_poll(void)
61306162#endif
61316163 }
61326164
6165+ /* Poll hold button modifier state */
6166+ for (i = 0 ; i < max_users ; i ++ )
6167+ {
6168+ input_st -> hold_btns .frame_enable [i ] =
6169+ (* input_st -> libretro_input_binds [i ])[RARCH_HOLD_ENABLE ].valid ?
6170+ input_state_wrap (input_st -> current_driver , input_st -> current_data ,
6171+ joypad , sec_joypad , & joypad_info [i ],
6172+ (* input_st -> libretro_input_binds ),
6173+ (input_st -> flags & INP_FLAG_KB_MAPPING_BLOCKED ) ? true : false,
6174+ (unsigned )i ,
6175+ RETRO_DEVICE_JOYPAD , 0 , RARCH_HOLD_ENABLE ) : 0 ;
6176+
6177+ #ifdef HAVE_OVERLAY
6178+ if ( (i == 0 )
6179+ && input_st -> overlay_ptr
6180+ && (input_st -> overlay_ptr -> flags & INPUT_OVERLAY_ALIVE )
6181+ && BIT256_GET (input_st -> overlay_ptr -> overlay_state .buttons , RARCH_HOLD_ENABLE ))
6182+ input_st -> hold_btns .frame_enable [i ] = true;
6183+ #endif
6184+ }
6185+
61336186#ifdef HAVE_MENU
61346187 if (!(menu_state_get_ptr ()-> flags & MENU_ST_FLAG_ALIVE ))
61356188#endif
0 commit comments