From 0a55b67a7b85071794855680b41a3d3113458168 Mon Sep 17 00:00:00 2001 From: angie Date: Thu, 6 Jun 2024 18:04:29 -0400 Subject: [PATCH] connected_device_info_t --- ultramodern/include/ultramodern/input.hpp | 31 ++++++++++++ ultramodern/src/input.cpp | 59 +++++++++++++++++++---- 2 files changed, 80 insertions(+), 10 deletions(-) diff --git a/ultramodern/include/ultramodern/input.hpp b/ultramodern/include/ultramodern/input.hpp index 6973dfa..1dab1b8 100644 --- a/ultramodern/include/ultramodern/input.hpp +++ b/ultramodern/include/ultramodern/input.hpp @@ -5,24 +5,55 @@ namespace ultramodern { namespace input { + enum class Device { + None, + Controller, + // Mouse, + // VRU, + }; + + enum class Pak { + None, + RumblePak, + // ControllerPak, + // TransferPak + }; + + struct connected_device_info_t { + Device connected_device; + Pak connected_pak; + }; + struct callbacks_t { using poll_input_t = void(void); using get_input_t = bool(int controller_num, uint16_t* buttons, float* x, float* y); using set_rumble_t = void(int controller_num, bool rumble); + using get_connected_device_info_t = connected_device_info_t(int controller_num); poll_input_t* poll_input; /** * Requests the state of the pressed buttons and the analog stick for the given `controller_num`. * + * `controller_num` is zero-indexed, meaning 0 corresponds to the first controller. + * * Returns `true` if was able to fetch the specified data, `false` otherwise and the parameter arguments are left untouched. */ get_input_t* get_input; /** * Turns on or off rumbling for the specified controller. + * + * `controller_num` is zero-indexed, meaning 0 corresponds to the first controller. */ set_rumble_t* set_rumble; + + /** + * Returns the connected device info for the given `controller_num` (as in, the controller port of the console). + * + * `controller_num` is zero-indexed, meaning 0 corresponds to the first controller. + */ + get_connected_device_info_t* get_connected_device_info; }; void set_callbacks(const callbacks_t& callbacks); diff --git a/ultramodern/src/input.cpp b/ultramodern/src/input.cpp index 811abdc..b7391a2 100644 --- a/ultramodern/src/input.cpp +++ b/ultramodern/src/input.cpp @@ -24,23 +24,61 @@ void ultramodern::measure_input_latency() { #define MAXCONTROLLERS 4 +#define CONT_NO_RESPONSE_ERROR 0x8 + +#define CONT_TYPE_NORMAL 0x0005 +#define CONT_TYPE_MOUSE 0x0002 +#define CONT_TYPE_VOICE 0x0100 + static int max_controllers = 0; /* Plain controller */ +static u16 get_controller_type(ultramodern::input::Device device_type) { + switch (device_type) { + case ultramodern::input::Device::None: + return 0; + + case ultramodern::input::Device::Controller: + return CONT_TYPE_NORMAL; + +#if 0 + case ultramodern::input::Device::Mouse: + return CONT_TYPE_MOUSE; + + case ultramodern::input::Device::VRU: + return CONT_TYPE_VOICE; +#endif + } + + return 0; +} + static void __osContGetInitData(u8* pattern, OSContStatus *data) { - // Set bit 0 to indicate that controller 0 is present - *pattern = 0x01; + *pattern = 0x00; - // Mark controller 0 as present - data[0].type = 0x0005; // type: CONT_TYPE_NORMAL (from joybus) - data[0].status = 0x01; // status: 0x01 (from joybus, indicates that a pak is plugged into the controller) - data[0].err_no = 0x00; // errno: 0 (from libultra) + for (int controller = 0; controller < max_controllers; controller++) { + ultramodern::input::connected_device_info_t device_info{}; - // Mark controllers 1-3 as not connected - for (int controller = 1; controller < max_controllers; controller++) { - // Libultra doesn't write status or type for absent controllers - data[controller].err_no = 0x80 >> 4; // errno: CONT_NO_RESPONSE_ERROR >> 4 + if (input_callbacks.get_connected_device_info != nullptr) { + device_info = input_callbacks.get_connected_device_info(controller); + } + + if (device_info.connected_device != ultramodern::input::Device::None) { + // Mark controller as present + + data[controller].type = get_controller_type(device_info.connected_device); + data[controller].status = device_info.connected_pak != ultramodern::input::Pak::None; + data[controller].err_no = 0x00; + + *pattern = 1 << controller; + } + else { + // Mark controller as not connected + + // Libultra doesn't write status or type for absent controllers + data[controller].err_no = CONT_NO_RESPONSE_ERROR; // CHNL_ERR_NORESP >> 4 + } } } @@ -136,6 +174,7 @@ s32 __osMotorAccess(RDRAM_ARG PTR(OSPfs) pfs_, s32 flag) { OSPfs *pfs = TO_PTR(OSPfs, pfs_); if (input_callbacks.set_rumble != nullptr) { + // TODO: Should we check if the Rumble Pak is connected? Or just rumble regardless of the connected Pak? input_callbacks.set_rumble(pfs->channel, flag); }