From c8bd306684bcd2a23e96aaaa2050ce55068d9d66 Mon Sep 17 00:00:00 2001 From: Ryan McClelland Date: Fri, 21 Aug 2026 10:33:04 -0700 Subject: [PATCH] libretro.h: add a sensor sub-device index for composite controllers Some controllers carry more than one sensor of the same kind on a single port. A Wii Remote with a Nunchuk attached is one player with two accelerometers, and adding MotionPlus makes it two accelerometers and a gyroscope, but retro_sensor_interface addresses exactly one sensor of each kind per port. A second port is not an alternative, because ports denote players. Carry a sub-device index in the upper bits of the existing ID, the same way RETRO_DEVICE_SUBCLASS encodes a subclass into a device ID. Index 0 denotes the controller itself and encodes to exactly the values already in use, so every existing core and frontend is unaffected. No new environment call or capability flag is needed, because the existing contract already describes the fallback: a frontend that does not implement this returns false from retro_set_sensor_state_t and 0 from retro_sensor_get_input_t, both of which are already documented, and a core that receives either answer behaves as it does today. Cores and frontends can therefore adopt this independently of one another. Definitions only; no behaviour changes. --- libretro-common/include/libretro.h | 36 ++++++++++++++++++++++++++++++ 1 file changed, 36 insertions(+) diff --git a/libretro-common/include/libretro.h b/libretro-common/include/libretro.h index 3def427e4fb..1073e36f5ec 100644 --- a/libretro-common/include/libretro.h +++ b/libretro-common/include/libretro.h @@ -4973,6 +4973,42 @@ enum retro_sensor_action #define RETRO_SENSOR_ILLUMINANCE 6 /** @} */ +/** @defgroup RETRO_SENSOR_SUBDEVICE Sensor Sub-Device Index + * @{ + */ + +/** + * The number of bits that a sub-device index is shifted by within a sensor ID + * or a \c retro_sensor_action. + * + * Addresses more than one sensor of the same kind on a single port. + * Index 0 denotes the controller itself and encodes to the values already in + * use (RETRO_SENSOR_SUBDEVICE(0, id) == id). Index 1 and above denote + * sub-devices, in whatever order the device type implies. + * + * @note \c retro_sensor_action is an enum, so an encoded action must be cast at + * the call site. \c RETRO_SENSOR_DUMMY pins the underlying type to \c int, so + * the encoded value is in range. + * + * @see RETRO_SENSOR_ID + * @see retro_sensor_action + */ +#define RETRO_SENSOR_INDEX_SHIFT 8 + +/** Mask of the bits below the sub-device index. */ +#define RETRO_SENSOR_INDEX_MASK ((1u << RETRO_SENSOR_INDEX_SHIFT) - 1u) + +/** Returns the sub-device index encoded in \c id; 0 is the controller itself. */ +#define RETRO_SENSOR_INDEX(id) ((unsigned)(id) >> RETRO_SENSOR_INDEX_SHIFT) + +/** Returns the sensor ID or action in \c id, without its sub-device index. */ +#define RETRO_SENSOR_BASE(id) ((unsigned)(id) & RETRO_SENSOR_INDEX_MASK) + +/** Addresses sensor \c id on sub-device \c index of a port. */ +#define RETRO_SENSOR_SUBDEVICE(index, id) \ + ((unsigned)((((unsigned)(index)) << RETRO_SENSOR_INDEX_SHIFT) | ((unsigned)(id)))) +/** @} */ + /** * Adjusts the state of a sensor. *