/**************************************************************************** * Copyright (C) 2016,2017 Maschell * * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 3 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see . ****************************************************************************/ #include "ControllerPatcherUtils.hpp" #include #include #include CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getDataByHandle(int32_t handle, my_cb_user **data) { for (int32_t i = 0; i < gHIDMaxDevices; i++) { for (int32_t j = 0; j < 4; j++) { //log_printf("%d %d %d %d",i,j,gHID_Devices[i].pad_data[j].handle,(uint32_t)handle); if (gHID_Devices[i].pad_data[j].handle == (uint32_t) handle) { *data = gHID_Devices[i].pad_data[j].user_data; return CONTROLLER_PATCHER_ERROR_NONE; } } } return CONTROLLER_PATCHER_ERROR_UNKNOWN; } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Analyse inputs *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getButtonPressed(HID_Data *data, int32_t *buttons_hold, int32_t VPADButton) { if (data == NULL || buttons_hold == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t deviceslot = data->slotdata.deviceslot; int32_t result = -1; do { if (data->type == DEVICE_TYPE_MOUSE) { HID_Mouse_Data *ms_data = &data->data_union.mouse.cur_mouse_data; if (ms_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if (gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) { if (VPADButton == VPAD_BUTTON_TOUCH) { if (ms_data->left_click & 0x01) { result = 1; break; } } } else if (gHID_Mouse_Mode == HID_MOUSE_MODE_AIM) { if (config_controller[deviceslot][CONTRPS_VPAD_BUTTON_LEFT][0] == CONTROLLER_PATCHER_VALUE_SET) { if (VPADButton == (int) gGamePadValues[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_LEFT][1]]) { if (ms_data->left_click & 0x01) { result = 1; break; } } } if (config_controller[deviceslot][CONTRPS_VPAD_BUTTON_RIGHT][0] == CONTROLLER_PATCHER_VALUE_SET) { if (VPADButton == (int) gGamePadValues[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_RIGHT][1]]) { if (ms_data->right_click & 0x01) { result = 1; break; } } } } result = 0; break; } uint8_t *cur_data = &data->data_union.controller.cur_hid_data[0]; if (cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t cur_config = 0; if (VPADButton == VPAD_BUTTON_A) { cur_config = CONTRPS_VPAD_BUTTON_A; } else if (VPADButton == VPAD_BUTTON_B) { cur_config = CONTRPS_VPAD_BUTTON_B; } else if (VPADButton == VPAD_BUTTON_X) { cur_config = CONTRPS_VPAD_BUTTON_X; } else if (VPADButton == VPAD_BUTTON_Y) { cur_config = CONTRPS_VPAD_BUTTON_Y; } else if (VPADButton == VPAD_BUTTON_L) { cur_config = CONTRPS_VPAD_BUTTON_L; } else if (VPADButton == VPAD_BUTTON_R) { cur_config = CONTRPS_VPAD_BUTTON_R; } else if (VPADButton == VPAD_BUTTON_ZL) { cur_config = CONTRPS_VPAD_BUTTON_ZL; } else if (VPADButton == VPAD_BUTTON_ZR) { cur_config = CONTRPS_VPAD_BUTTON_ZR; } else if (VPADButton == VPAD_BUTTON_STICK_L) { cur_config = CONTRPS_VPAD_BUTTON_STICK_L; } else if (VPADButton == VPAD_BUTTON_STICK_R) { cur_config = CONTRPS_VPAD_BUTTON_STICK_R; } else if (VPADButton == VPAD_BUTTON_PLUS) { cur_config = CONTRPS_VPAD_BUTTON_PLUS; } else if (VPADButton == VPAD_BUTTON_MINUS) { cur_config = CONTRPS_VPAD_BUTTON_MINUS; } else if (VPADButton == VPAD_BUTTON_HOME) { cur_config = CONTRPS_VPAD_BUTTON_HOME; } //! Special DPAD treatment. if (config_controller[deviceslot][CONTRPS_DPAD_MODE][0] == CONTROLLER_PATCHER_VALUE_SET) { if (config_controller[deviceslot][CONTRPS_DPAD_MODE][1] == CONTRPDM_Hat) { uint8_t mask = 0x0F; if (config_controller[deviceslot][CONTRPS_DPAD_MASK][0] == CONTROLLER_PATCHER_VALUE_SET) { mask = config_controller[deviceslot][CONTRPS_DPAD_MASK][1]; } if (cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NEUTRAL][0]] != config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NEUTRAL][1]) { // Not neutral uint8_t dir1_0 = 0, dir1_1 = 0; uint8_t dir2_0 = 0, dir2_1 = 0; uint8_t dir3_0 = 0, dir3_1 = 0; uint8_t direction = 0; if (VPADButton == VPAD_BUTTON_LEFT) { dir1_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_W][0]; dir2_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NW][0]; dir3_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SW][0]; dir1_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_W][1]; dir2_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NW][1]; dir3_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SW][1]; direction = 1; } else if (VPADButton == VPAD_BUTTON_RIGHT) { dir1_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_E][0]; dir2_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SE][0]; dir3_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NE][0]; dir1_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_E][1]; dir2_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SE][1]; dir3_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NE][1]; direction = 1; } else if (VPADButton == VPAD_BUTTON_DOWN) { dir1_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_S][0]; dir2_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SE][0]; dir3_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SW][0]; dir1_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_S][1]; dir2_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SE][1]; dir3_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_SW][1]; direction = 1; } else if (VPADButton == VPAD_BUTTON_UP) { dir1_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_N][0]; dir2_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NW][0]; dir3_0 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NE][0]; dir1_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_N][1]; dir2_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NW][1]; dir3_1 = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_DPAD_NE][1]; direction = 1; } if (direction && (((cur_data[dir1_0] & mask) == dir1_1) || ((cur_data[dir2_0] & mask) == dir2_1) || ((cur_data[dir3_0] & mask) == dir3_1))) { result = 1; break; } } } else if (config_controller[deviceslot][CONTRPS_DPAD_MODE][1] == CONTRPDM_Absolute_2Values) { int32_t contrps_value = 0; if (VPADButton == VPAD_BUTTON_LEFT) { contrps_value = CONTRPS_VPAD_BUTTON_DPAD_ABS_LEFT; } else if (VPADButton == VPAD_BUTTON_RIGHT) { contrps_value = CONTRPS_VPAD_BUTTON_DPAD_ABS_RIGHT; } else if (VPADButton == VPAD_BUTTON_UP) { contrps_value = CONTRPS_VPAD_BUTTON_DPAD_ABS_UP; } else if (VPADButton == VPAD_BUTTON_DOWN) { contrps_value = CONTRPS_VPAD_BUTTON_DPAD_ABS_DOWN; } if (contrps_value != 0) { int32_t value_byte = CONTROLLER_PATCHER_INVALIDVALUE; if ((value_byte = config_controller[deviceslot][contrps_value][0]) != CONTROLLER_PATCHER_INVALIDVALUE) { if (cur_data[config_controller[deviceslot][contrps_value][0]] == config_controller[deviceslot][contrps_value][1]) { result = 1; break; } } } } } //! Normal DPAD treatment. if (VPADButton == VPAD_BUTTON_LEFT) { cur_config = CONTRPS_VPAD_BUTTON_LEFT; } else if (VPADButton == VPAD_BUTTON_RIGHT) { cur_config = CONTRPS_VPAD_BUTTON_RIGHT; } else if (VPADButton == VPAD_BUTTON_DOWN) { cur_config = CONTRPS_VPAD_BUTTON_DOWN; } else if (VPADButton == VPAD_BUTTON_UP) { cur_config = CONTRPS_VPAD_BUTTON_UP; } if (result && config_controller[deviceslot][CONTRPS_DOUBLE_USE][0] == CONTROLLER_PATCHER_VALUE_SET) { if (config_controller[deviceslot][CONTRPS_DOUBLE_USE][1] == CONTROLLER_PATCHER_GC_DOUBLE_USE) { if (cur_data[config_controller[deviceslot][CONTRPS_DOUBLE_USE_BUTTON_ACTIVATOR][0]] & config_controller[deviceslot][CONTRPS_DOUBLE_USE_BUTTON_ACTIVATOR][1]) { if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_1_RELEASED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_2_RELEASED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_3_RELEASED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_4_RELEASED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_5_RELEASED, cur_config)) { result = 0; break; } } else { if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_1_PRESSED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_2_PRESSED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_3_PRESSED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_4_PRESSED, cur_config)) { result = 0; break; } if (checkValueinConfigController(deviceslot, CONTRPS_DOUBLE_USE_BUTTON_5_PRESSED, cur_config)) { result = 0; break; } } } } if (isValueSet(data, cur_config) == 1) { result = 1; break; } else { //log_printf("Invalid data! deviceslot(slot): %d config: %d",deviceslot,cur_config); } } while (0); //The break will become handy ;) if (result == 1) { *buttons_hold |= VPADButton; // -1 would be also true. return 1; } return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::isValueSet(HID_Data *data, int32_t cur_config) { if (data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; uint8_t *cur_data = &data->data_union.controller.cur_hid_data[0]; if (cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; uint32_t hidmask = data->slotdata.hidmask; int32_t deviceslot = data->slotdata.deviceslot; int32_t result = CONTROLLER_PATCHER_ERROR_NONE; if (config_controller[deviceslot][cur_config][0] != CONTROLLER_PATCHER_INVALIDVALUE) { //Invalid data if (hidmask & gHID_LIST_KEYBOARD) { if (isInKeyboardData(cur_data, config_controller[deviceslot][cur_config][1]) > 0) { result = 1; } } else { if ((cur_data[config_controller[deviceslot][cur_config][0]] & config_controller[deviceslot][cur_config][1]) == config_controller[deviceslot][cur_config][1]) { result = 1; } } } return result; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::isInKeyboardData(unsigned char *keyboardData, int32_t key) { if (keyboardData == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; for (int32_t i = 0; i < HID_KEYBOARD_DATA_LENGTH; i++) { if (keyboardData[i] == 0 && i > 1) { break; } else if (keyboardData[i] == key) { return 1; } } return 0; } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Utils for setting the Button data *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::setButtonRemappingData(VPADStatus *old_buffer, VPADStatus *new_buffer, uint32_t VPADButton, int32_t CONTRPS_SLOT) { if (old_buffer == NULL || new_buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; uint32_t new_value = VPADButton; if (config_controller[gGamePadSlot][CONTRPS_SLOT][0] != CONTROLLER_PATCHER_INVALIDVALUE) { //using new value! new_value = gGamePadValues[config_controller[gGamePadSlot][CONTRPS_SLOT][1]]; } setButtonData(old_buffer, new_buffer, VPADButton, new_value); return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::setButtonData(VPADStatus *old_buffer, VPADStatus *new_buffer, uint32_t oldVPADButton, uint32_t newVPADButton) { if (old_buffer == NULL || new_buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if ((old_buffer->hold & oldVPADButton) == oldVPADButton) { new_buffer->hold |= newVPADButton; } if ((old_buffer->release & oldVPADButton) == oldVPADButton) { new_buffer->release |= newVPADButton; } if ((old_buffer->trigger & oldVPADButton) == oldVPADButton) { new_buffer->trigger |= newVPADButton; } return CONTROLLER_PATCHER_ERROR_NONE; } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Pad Status functions *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::checkActivePad(uint32_t hidmask, int32_t pad) { if (hidmask & gHID_LIST_GC && pad >= 0 && pad <= 3) { if (!(((gHID_Devices[gHID_SLOT_GC].pad_data[pad].data_union.controller.cur_hid_data[0] & 0x10) == 0) && ((gHID_Devices[gHID_SLOT_GC].pad_data[pad].data_union.controller.cur_hid_data[0] & 0x22) != 0x22))) return 1; return CONTROLLER_PATCHER_ERROR_NO_PAD_CONNECTED; } else { int32_t deviceslot = getDeviceSlot(hidmask); if (deviceslot < 0) return CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND; int32_t connected_pads = config_controller[deviceslot][CONTRPS_CONNECTED_PADS][1]; if ((connected_pads & (1 << pad)) > 0) { return 1; } } return CONTROLLER_PATCHER_ERROR_NO_PAD_CONNECTED; } /* CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getActivePad(uint32_t hidmask){ if(hidmask & gHID_LIST_GC){ if (!(((gHID_Devices[gHID_SLOT_GC].pad_data[0].data_union.controller.cur_hid_data[0] & 0x10) == 0) && ((gHID_Devices[gHID_SLOT_GC].pad_data[0].data_union.controller.cur_hid_data[0] & 0x22) != 0x22))) return 0; if (!(((gHID_Devices[gHID_SLOT_GC].pad_data[1].data_union.controller.cur_hid_data[0] & 0x10) == 0) && ((gHID_Devices[gHID_SLOT_GC].pad_data[1].data_union.controller.cur_hid_data[0] & 0x22) != 0x22))) return 1; if (!(((gHID_Devices[gHID_SLOT_GC].pad_data[2].data_union.controller.cur_hid_data[0] & 0x10) == 0) && ((gHID_Devices[gHID_SLOT_GC].pad_data[2].data_union.controller.cur_hid_data[0] & 0x22) != 0x22))) return 2; if (!(((gHID_Devices[gHID_SLOT_GC].pad_data[3].data_union.controller.cur_hid_data[0] & 0x10) == 0) && ((gHID_Devices[gHID_SLOT_GC].pad_data[3].data_union.controller.cur_hid_data[0] & 0x22) != 0x22))) return 3; return CONTROLLER_PATCHER_ERROR_NO_PAD_CONNECTED; } return 0; }*/ /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Stick functions *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ int16_t ControllerPatcherUtils::signExtendValue(uint16_t input, uint8_t bit_length) { // Check if the input is negative in its original bit length if (input & (1 << (bit_length - 1))) { // Sign-extend the value return (int16_t)(input | (~((1 << bit_length) - 1))); } else { // Input is non-negative; return it directly with proper casting return (int16_t)input; } } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::normalizeStickValues(VPADVec2D *stick) { if (stick == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; float max_val = 0.0f; float mul_val = 0.0f; if ((max_val = (fabs(stick->x)) + fabs(stick->y)) > 1.414f) { mul_val = 1.414f / max_val; stick->x *= mul_val; stick->y *= mul_val; } if (stick->x > 1.0f) { stick->x = 1.0f; } if (stick->y > 1.0f) { stick->y = 1.0f; } if (stick->x < -1.0f) { stick->x = -1.0f; } if (stick->y < -1.0f) { stick->y = -1.0f; } return CONTROLLER_PATCHER_ERROR_NONE; } float ControllerPatcherUtils::convertAnalogValue(int32_t value, int32_t default_val, int32_t min, int32_t max, uint8_t invert, uint8_t deadzone){ if(value >= max) return invert == 0x01 ? -1.0f : 1.0f; if(value <= min) return invert == 0x01 ? 1.0f : -1.0f; int32_t range = 0; int32_t adjustedValue = value - default_val; if(std::abs(adjustedValue) <= (int32_t)deadzone) return 0.0f; if(adjustedValue > 0) { range = max - (default_val + deadzone); adjustedValue -= deadzone; } else { range = (default_val - deadzone) - min; adjustedValue += deadzone; } float normalizedValue = (float)adjustedValue / range; return invert == 0x01 ? -normalizedValue : normalizedValue; } VPADVec2D ControllerPatcherUtils::getAnalogValueByButtons(uint8_t stick_values) { VPADVec2D stick; stick.x = 0.0f; stick.y = 0.0f; uint8_t up = ((stick_values & STICK_VALUE_UP) == STICK_VALUE_UP); uint8_t down = ((stick_values & STICK_VALUE_DOWN) == STICK_VALUE_DOWN); uint8_t left = ((stick_values & STICK_VALUE_LEFT) == STICK_VALUE_LEFT); uint8_t right = ((stick_values & STICK_VALUE_RIGHT) == STICK_VALUE_RIGHT); if (up) { if (!down) { stick.y = 1.0f; } if (left || right) { stick.y = 0.707f; if (left) stick.x = -0.707f; if (right) stick.x = 0.707f; } } else if (down) { if (!up) { stick.y = -1.0f; } if (left || right) { stick.y = -0.707f; if (left) stick.x = -0.707f; if (right) stick.x = 0.707f; } } else { if (left) { if (!right) { stick.x = -1.0f; } } else if (right) { if (!down) { stick.x = 1.0f; } } } return stick; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::convertAnalogSticks(HID_Data *data, VPADStatus *buffer) { if (buffer == NULL || data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t deviceslot = data->slotdata.deviceslot; if (data->type == DEVICE_TYPE_MOUSE) { if (gHID_Mouse_Mode == HID_MOUSE_MODE_AIM) { // TODO: tweak values HID_Mouse_Data *ms_data = &data->data_union.mouse.cur_mouse_data; if (ms_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; float x_value = ms_data->deltaX / 10.0f; float y_value = -1.0f * (ms_data->deltaY / 10.0f); if (config_controller[deviceslot][CONTRPS_MOUSE_STICK][0] != CONTROLLER_PATCHER_INVALIDVALUE) { if (config_controller[deviceslot][CONTRPS_MOUSE_STICK][1] == DEF_L_STICK) { buffer->leftStick.x += x_value; buffer->leftStick.y += y_value; return CONTROLLER_PATCHER_ERROR_NONE; } } buffer->rightStick.x += x_value; buffer->rightStick.y += y_value; } } else { uint8_t *cur_data = &data->data_union.controller.cur_hid_data[0]; if (cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; processStickAxis(buffer->leftStick.x, cur_data, deviceslot, CONTRPS_VPAD_BUTTON_L_STICK_X, CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE, CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX, CONTRPS_VPAD_BUTTON_L_STICK_X_BIT_LENGTH, CONTRPS_VPAD_BUTTON_L_STICK_X_BIT_OFFSET, CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX_MSB, CONTRPS_VPAD_BUTTON_L_STICK_X_DEFAULT_MSB, CONTRPS_VPAD_BUTTON_L_STICK_X_SIGNED, CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT); processStickAxis(buffer->leftStick.y, cur_data, deviceslot, CONTRPS_VPAD_BUTTON_L_STICK_Y, CONTRPS_VPAD_BUTTON_L_STICK_Y_DEADZONE, CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX, CONTRPS_VPAD_BUTTON_L_STICK_Y_BIT_LENGTH, CONTRPS_VPAD_BUTTON_L_STICK_Y_BIT_OFFSET, CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX_MSB, CONTRPS_VPAD_BUTTON_L_STICK_Y_DEFAULT_MSB, CONTRPS_VPAD_BUTTON_L_STICK_Y_SIGNED, CONTRPS_VPAD_BUTTON_L_STICK_Y_INVERT); processStickAxis(buffer->rightStick.x, cur_data, deviceslot, CONTRPS_VPAD_BUTTON_R_STICK_X, CONTRPS_VPAD_BUTTON_R_STICK_X_DEADZONE, CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX, CONTRPS_VPAD_BUTTON_R_STICK_X_BIT_LENGTH, CONTRPS_VPAD_BUTTON_R_STICK_X_BIT_OFFSET, CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX_MSB, CONTRPS_VPAD_BUTTON_R_STICK_X_DEFAULT_MSB, CONTRPS_VPAD_BUTTON_R_STICK_X_SIGNED, CONTRPS_VPAD_BUTTON_R_STICK_X_INVERT); processStickAxis(buffer->rightStick.y, cur_data, deviceslot, CONTRPS_VPAD_BUTTON_R_STICK_Y, CONTRPS_VPAD_BUTTON_R_STICK_Y_DEADZONE, CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX, CONTRPS_VPAD_BUTTON_R_STICK_Y_BIT_LENGTH, CONTRPS_VPAD_BUTTON_R_STICK_Y_BIT_OFFSET, CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX_MSB, CONTRPS_VPAD_BUTTON_R_STICK_Y_DEFAULT_MSB, CONTRPS_VPAD_BUTTON_R_STICK_Y_SIGNED, CONTRPS_VPAD_BUTTON_R_STICK_Y_INVERT); uint8_t stick_values = 0; if (isValueSet(data, CONTRPS_VPAD_BUTTON_L_STICK_UP)) { stick_values |= STICK_VALUE_UP; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_L_STICK_DOWN)) { stick_values |= STICK_VALUE_DOWN; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_L_STICK_LEFT)) { stick_values |= STICK_VALUE_LEFT; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_L_STICK_RIGHT)) { stick_values |= STICK_VALUE_RIGHT; } if (stick_values > 0) { VPADVec2D stick = getAnalogValueByButtons(stick_values); buffer->leftStick.x += stick.x; buffer->leftStick.y += stick.y; } stick_values = 0; if (isValueSet(data, CONTRPS_VPAD_BUTTON_R_STICK_UP)) { stick_values |= STICK_VALUE_UP; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_R_STICK_DOWN)) { stick_values |= STICK_VALUE_DOWN; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_R_STICK_LEFT)) { stick_values |= STICK_VALUE_LEFT; } if (isValueSet(data, CONTRPS_VPAD_BUTTON_R_STICK_RIGHT)) { stick_values |= STICK_VALUE_RIGHT; } if (stick_values > 0) { VPADVec2D stick = getAnalogValueByButtons(stick_values); buffer->rightStick.x += stick.x; buffer->rightStick.y += stick.y; } if (config_controller[deviceslot][CONTRPS_VPAD_STICK_L_COPY_DPAD][0] != CONTROLLER_PATCHER_INVALIDVALUE) { if (config_controller[deviceslot][CONTRPS_VPAD_STICK_L_COPY_DPAD][0] == 1) { uint8_t stick_values = 0; if (buffer->hold & VPAD_BUTTON_UP) { stick_values |= STICK_VALUE_UP; } if (buffer->hold & VPAD_BUTTON_DOWN) { stick_values |= STICK_VALUE_DOWN; } if (buffer->hold & VPAD_BUTTON_LEFT) { stick_values |= STICK_VALUE_LEFT; } if (buffer->hold & VPAD_BUTTON_RIGHT) { stick_values |= STICK_VALUE_RIGHT; } if (stick_values > 0) { VPADVec2D stick = getAnalogValueByButtons(stick_values); buffer->leftStick.x += stick.x; buffer->leftStick.y += stick.y; } } } if (config_controller[deviceslot][CONTRPS_VPAD_STICK_R_COPY_DPAD][0] != CONTROLLER_PATCHER_INVALIDVALUE) { if (config_controller[deviceslot][CONTRPS_VPAD_STICK_R_COPY_DPAD][0] == 1) { uint8_t stick_values = 0; if (buffer->hold & VPAD_BUTTON_UP) { stick_values |= STICK_VALUE_UP; } if (buffer->hold & VPAD_BUTTON_DOWN) { stick_values |= STICK_VALUE_DOWN; } if (buffer->hold & VPAD_BUTTON_LEFT) { stick_values |= STICK_VALUE_LEFT; } if (buffer->hold & VPAD_BUTTON_RIGHT) { stick_values |= STICK_VALUE_RIGHT; } if (stick_values > 0) { VPADVec2D stick = getAnalogValueByButtons(stick_values); buffer->rightStick.x += stick.x; buffer->rightStick.y += stick.y; } } } } return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::processStickAxis( float &buffer_axis, const uint8_t *cur_data, int32_t deviceslot, uint8_t axis_code, uint8_t axis_deadzone_code, uint8_t axis_minmax_code, uint8_t axis_bit_length_code, uint8_t axis_bit_offset_code, uint8_t axis_minmax_msb_code, uint8_t axis_default_msb_code, uint8_t axis_signed_code, uint8_t axis_invert_code) { if (cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if (config_controller[deviceslot][axis_code][0] != CONTROLLER_PATCHER_INVALIDVALUE) { uint8_t deadzone = (config_controller[deviceslot][axis_deadzone_code][0] == CONTROLLER_PATCHER_VALUE_SET) ? config_controller[deviceslot][axis_deadzone_code][1] : 0; // Read 1st byte of axis HID data & Min/Max/Default values uint16_t axis_input = cur_data[config_controller[deviceslot][axis_code][0]]; uint16_t axis_min = config_controller[deviceslot][axis_minmax_code][0]; uint16_t axis_max = config_controller[deviceslot][axis_minmax_code][1]; uint16_t axis_default = config_controller[deviceslot][axis_code][1]; // Axis report larger than 8 bits? if (config_controller[deviceslot][axis_bit_length_code][0] == CONTROLLER_PATCHER_VALUE_SET && config_controller[deviceslot][axis_bit_length_code][1] > 8) { // Read 2nd byte of axis HID data axis_input |= (cur_data[config_controller[deviceslot][axis_code][0] + 1] << 8); if (config_controller[deviceslot][axis_bit_offset_code][0] == CONTROLLER_PATCHER_VALUE_SET) { // Shift right to trim unwanted leading bits axis_input >>= config_controller[deviceslot][axis_bit_offset_code][1]; } // Mask off unwanted trailing bits axis_input &= ((1 << config_controller[deviceslot][axis_bit_length_code][1]) - 1); // Combine most significant bytes of Min/Max/Default values axis_min |= (config_controller[deviceslot][axis_minmax_msb_code][0] << 8); axis_max |= (config_controller[deviceslot][axis_minmax_msb_code][1] << 8); if (config_controller[deviceslot][axis_default_msb_code][0] == CONTROLLER_PATCHER_VALUE_SET) { axis_default |= (config_controller[deviceslot][axis_default_msb_code][1] << 8); } } if (config_controller[deviceslot][axis_signed_code][1]) { // Extend sign bits if axis HID data is signed int16_t signed_input = signExtendValue(axis_input, config_controller[deviceslot][axis_bit_length_code][1]); buffer_axis += convertAnalogValue(signed_input, (int16_t)axis_default, (int16_t)axis_min, (int16_t)axis_max, config_controller[deviceslot][axis_invert_code][1], deadzone); } else { buffer_axis += convertAnalogValue(axis_input, axis_default, axis_min, axis_max, config_controller[deviceslot][axis_invert_code][1], deadzone); } } return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::setEmulatedSticks(VPADStatus *buffer, uint32_t *last_emulatedSticks) { if (buffer == NULL || last_emulatedSticks == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; uint32_t emulatedSticks = 0; int32_t l_x_full = (buffer->leftStick.x > 0.5f || buffer->leftStick.x < -0.5f) ? 1 : 0; int32_t l_y_full = (buffer->leftStick.y > 0.5f || buffer->leftStick.y < -0.5f) ? 1 : 0; int32_t r_x_full = (buffer->rightStick.x > 0.5f || buffer->rightStick.x < -0.5f) ? 1 : 0; int32_t r_y_full = (buffer->rightStick.y > 0.5f || buffer->rightStick.y < -0.5f) ? 1 : 0; if ((buffer->leftStick.x > 0.5f) || (buffer->leftStick.x > 0.1f && !l_y_full)) { emulatedSticks |= VPAD_STICK_L_EMULATION_RIGHT; } if ((buffer->leftStick.x < -0.5f) || (buffer->leftStick.x < -0.1f && !l_y_full)) { emulatedSticks |= VPAD_STICK_L_EMULATION_LEFT; } if ((buffer->leftStick.y > 0.5f) || (buffer->leftStick.y > 0.1f && !l_x_full)) { emulatedSticks |= VPAD_STICK_L_EMULATION_UP; } if ((buffer->leftStick.y < -0.5f) || (buffer->leftStick.y < -0.1f && !l_x_full)) { emulatedSticks |= VPAD_STICK_L_EMULATION_DOWN; } if ((buffer->rightStick.x > 0.5f) || (buffer->rightStick.x > 0.1f && !r_y_full)) { emulatedSticks |= VPAD_STICK_R_EMULATION_RIGHT; } if ((buffer->rightStick.x < -0.5f) || (buffer->rightStick.x < -0.1f && !r_y_full)) { emulatedSticks |= VPAD_STICK_R_EMULATION_LEFT; } if ((buffer->rightStick.y > 0.5f) || (buffer->rightStick.y > 0.1f && !r_x_full)) { emulatedSticks |= VPAD_STICK_R_EMULATION_UP; } if ((buffer->rightStick.y < -0.5f) || (buffer->rightStick.y < -0.1f && !r_x_full)) { emulatedSticks |= VPAD_STICK_R_EMULATION_DOWN; } //Setting the emulated sticks buffer->hold |= emulatedSticks; buffer->trigger |= (emulatedSticks & (~*last_emulatedSticks)); buffer->release |= (*last_emulatedSticks & (~emulatedSticks)); *last_emulatedSticks = emulatedSticks; return CONTROLLER_PATCHER_ERROR_NONE; } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Touch functions *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::setTouch(HID_Data *data, VPADStatus *buffer) { if (buffer == NULL || data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if (data->type == DEVICE_TYPE_MOUSE && gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) { int32_t buttons_hold; if (getButtonPressed(data, &buttons_hold, VPAD_BUTTON_TOUCH)) { HID_Mouse_Data *ms_data = &data->data_union.mouse.cur_mouse_data; if (ms_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t x_mouse = 80 + ((int) (((ms_data->X) * 1.0f / 1280.0) * 3890.0f)); int32_t y_mouse = 3910 - ((int) (((ms_data->Y) * 1.0f / 720.0) * 3760.0f)); buffer->tpNormal.x = x_mouse; buffer->tpNormal.y = y_mouse; buffer->tpNormal.touched = 1; buffer->tpNormal.validity = 0; buffer->tpFiltered1.x = x_mouse; buffer->tpFiltered1.y = y_mouse; buffer->tpFiltered1.touched = 1; buffer->tpFiltered1.validity = 0; buffer->tpFiltered2.x = x_mouse; buffer->tpFiltered2.y = y_mouse; buffer->tpFiltered2.touched = 1; buffer->tpFiltered2.validity = 0; } } return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::checkAndSetMouseMode(HID_Data *data) { uint32_t hidmask = data->slotdata.hidmask; if (hidmask & gHID_LIST_KEYBOARD) { uint8_t *cur_data = &data->data_union.controller.cur_hid_data[0]; uint8_t *last_data = &data->data_union.controller.last_hid_data[0]; if ((isInKeyboardData(cur_data, HID_KEYBOARD_BUTTON_F1) > 0) && ((isInKeyboardData(cur_data, HID_KEYBOARD_BUTTON_F1) > 0) != (isInKeyboardData(last_data, HID_KEYBOARD_BUTTON_F1) > 0)) && gMouseModeCoolDown == 0) { gMouseModeCoolDown = 60; if (gHID_Mouse_Mode == HID_MOUSE_MODE_AIM) { gHID_Mouse_Mode = HID_MOUSE_MODE_TOUCH; //log_printf("ControllerPatcherUtils::checkAndSetMouseMode(line %d): Mouse mode changed! to touch ",__LINE__); } else if (gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH) { //log_printf("ControllerPatcherUtils::checkAndSetMouseMode(line %d): Mouse mode changed! to aim ",__LINE__); gHID_Mouse_Mode = HID_MOUSE_MODE_AIM; } } if (gMouseModeCoolDown > 0) { gMouseModeCoolDown--; } } return CONTROLLER_PATCHER_ERROR_NONE; } /*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------- * Other functions *---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/ CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::translateToPro(VPADStatus *vpad_buffer, KPADStatus *pro_buffer, uint32_t *lastButtonsPressesPRO) { if (vpad_buffer == NULL || pro_buffer == NULL || lastButtonsPressesPRO == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t buttons_hold = 0; if (vpad_buffer->hold & VPAD_BUTTON_A) buttons_hold |= WPAD_PRO_BUTTON_A; if (vpad_buffer->hold & VPAD_BUTTON_B) buttons_hold |= WPAD_PRO_BUTTON_B; if (vpad_buffer->hold & VPAD_BUTTON_X) buttons_hold |= WPAD_PRO_BUTTON_X; if (vpad_buffer->hold & VPAD_BUTTON_Y) buttons_hold |= WPAD_PRO_BUTTON_Y; if (vpad_buffer->hold & VPAD_BUTTON_PLUS) buttons_hold |= WPAD_PRO_BUTTON_PLUS; if (vpad_buffer->hold & VPAD_BUTTON_MINUS) buttons_hold |= WPAD_PRO_BUTTON_MINUS; if (vpad_buffer->hold & VPAD_BUTTON_HOME) buttons_hold |= WPAD_PRO_BUTTON_HOME; if (vpad_buffer->hold & VPAD_BUTTON_LEFT) buttons_hold |= WPAD_PRO_BUTTON_LEFT; if (vpad_buffer->hold & VPAD_BUTTON_RIGHT) buttons_hold |= WPAD_PRO_BUTTON_RIGHT; if (vpad_buffer->hold & VPAD_BUTTON_UP) buttons_hold |= WPAD_PRO_BUTTON_UP; if (vpad_buffer->hold & VPAD_BUTTON_DOWN) buttons_hold |= WPAD_PRO_BUTTON_DOWN; if (vpad_buffer->hold & VPAD_BUTTON_L) buttons_hold |= WPAD_PRO_TRIGGER_L; if (vpad_buffer->hold & VPAD_BUTTON_ZL) buttons_hold |= WPAD_PRO_TRIGGER_ZL; if (vpad_buffer->hold & VPAD_BUTTON_R) buttons_hold |= WPAD_PRO_TRIGGER_R; if (vpad_buffer->hold & VPAD_BUTTON_ZR) buttons_hold |= WPAD_PRO_TRIGGER_ZR; if (vpad_buffer->hold & VPAD_BUTTON_STICK_L) buttons_hold |= WPAD_PRO_BUTTON_STICK_L; if (vpad_buffer->hold & VPAD_BUTTON_STICK_R) buttons_hold |= WPAD_PRO_BUTTON_STICK_R; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_LEFT) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_LEFT; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_RIGHT) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_RIGHT; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_UP) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_UP; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_DOWN) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_DOWN; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_LEFT) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_LEFT; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_RIGHT) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_RIGHT; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_UP) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_UP; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_DOWN) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_DOWN; pro_buffer->pro.leftStick.x = vpad_buffer->leftStick.x; pro_buffer->pro.leftStick.y = vpad_buffer->leftStick.y; pro_buffer->pro.rightStick.x = vpad_buffer->rightStick.x; pro_buffer->pro.rightStick.y = vpad_buffer->rightStick.y; /* pro_buffer->unused_1[1] = 0xBF800000; pro_buffer->unused_1[3] = 0x3F800000; pro_buffer->angle_x = 0x3F800000; pro_buffer->unused_3[4] = 0x3F800000; pro_buffer->unused_3[7] = 0x3F800000; pro_buffer->unused_6[17] = 0x3F800000; pro_buffer->unused_7[1] = 0x3F800000; pro_buffer->unused_7[5] = 0x3F800000;*/ pro_buffer->pro.hold = buttons_hold; pro_buffer->pro.trigger = (buttons_hold & (~*lastButtonsPressesPRO)); pro_buffer->pro.release = (*lastButtonsPressesPRO & (~buttons_hold)); *lastButtonsPressesPRO = buttons_hold; pro_buffer->format = WPAD_FMT_PRO_CONTROLLER; pro_buffer->error = 0x00; pro_buffer->extensionType = WPAD_EXT_PRO_CONTROLLER; pro_buffer->pro.wired = 1; pro_buffer->pro.charging = 1; return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::translateToProWPADRead(VPADStatus *vpad_buffer, WPADStatusProController *pro_buffer) { if (vpad_buffer == NULL || pro_buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t buttons_hold = 0; if (vpad_buffer->hold & VPAD_BUTTON_A) buttons_hold |= WPAD_PRO_BUTTON_A; if (vpad_buffer->hold & VPAD_BUTTON_B) buttons_hold |= WPAD_PRO_BUTTON_B; if (vpad_buffer->hold & VPAD_BUTTON_X) buttons_hold |= WPAD_PRO_BUTTON_X; if (vpad_buffer->hold & VPAD_BUTTON_Y) buttons_hold |= WPAD_PRO_BUTTON_Y; if (vpad_buffer->hold & VPAD_BUTTON_PLUS) buttons_hold |= WPAD_PRO_BUTTON_PLUS; if (vpad_buffer->hold & VPAD_BUTTON_MINUS) buttons_hold |= WPAD_PRO_BUTTON_MINUS; if (vpad_buffer->hold & VPAD_BUTTON_HOME) buttons_hold |= WPAD_PRO_BUTTON_HOME; if (vpad_buffer->hold & VPAD_BUTTON_LEFT) buttons_hold |= WPAD_PRO_BUTTON_LEFT; if (vpad_buffer->hold & VPAD_BUTTON_RIGHT) buttons_hold |= WPAD_PRO_BUTTON_RIGHT; if (vpad_buffer->hold & VPAD_BUTTON_UP) buttons_hold |= WPAD_PRO_BUTTON_UP; if (vpad_buffer->hold & VPAD_BUTTON_DOWN) buttons_hold |= WPAD_PRO_BUTTON_DOWN; if (vpad_buffer->hold & VPAD_BUTTON_L) buttons_hold |= WPAD_PRO_TRIGGER_L; if (vpad_buffer->hold & VPAD_BUTTON_ZL) buttons_hold |= WPAD_PRO_TRIGGER_ZL; if (vpad_buffer->hold & VPAD_BUTTON_R) buttons_hold |= WPAD_PRO_TRIGGER_R; if (vpad_buffer->hold & VPAD_BUTTON_ZR) buttons_hold |= WPAD_PRO_TRIGGER_ZR; if (vpad_buffer->hold & VPAD_BUTTON_STICK_L) buttons_hold |= WPAD_PRO_BUTTON_STICK_L; if (vpad_buffer->hold & VPAD_BUTTON_STICK_R) buttons_hold |= WPAD_PRO_BUTTON_STICK_R; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_LEFT) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_LEFT; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_RIGHT) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_RIGHT; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_UP) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_UP; if (vpad_buffer->hold & VPAD_STICK_L_EMULATION_DOWN) buttons_hold |= WPAD_PRO_STICK_L_EMULATION_DOWN; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_LEFT) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_LEFT; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_RIGHT) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_RIGHT; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_UP) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_UP; if (vpad_buffer->hold & VPAD_STICK_R_EMULATION_DOWN) buttons_hold |= WPAD_PRO_STICK_R_EMULATION_DOWN; pro_buffer->leftStick.x = (int16_t) (vpad_buffer->leftStick.x * 950.0f); pro_buffer->leftStick.y = (int16_t) (vpad_buffer->leftStick.y * 950.0f); pro_buffer->rightStick.x = (int16_t) (vpad_buffer->rightStick.x * 950.0f); pro_buffer->rightStick.y = (int16_t) (vpad_buffer->rightStick.y * 950.0f); pro_buffer->buttons = buttons_hold; pro_buffer->dataFormat = WPAD_FMT_PRO_CONTROLLER; pro_buffer->err = 0x00; pro_buffer->extensionType = WPAD_EXT_PRO_CONTROLLER; return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::translateToVPAD(VPADStatus *vpad_buffer, KPADStatus *pro_buffer, uint32_t *lastButtonsPressesVPAD) { if (vpad_buffer == NULL || pro_buffer == NULL || lastButtonsPressesVPAD == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; int32_t buttons_hold = 0; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_A) buttons_hold |= VPAD_BUTTON_A; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_B) buttons_hold |= VPAD_BUTTON_B; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_X) buttons_hold |= VPAD_BUTTON_X; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_Y) buttons_hold |= VPAD_BUTTON_Y; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_PLUS) buttons_hold |= VPAD_BUTTON_PLUS; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_MINUS) buttons_hold |= VPAD_BUTTON_MINUS; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_HOME) buttons_hold |= VPAD_BUTTON_HOME; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_LEFT) buttons_hold |= VPAD_BUTTON_LEFT; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_RIGHT) buttons_hold |= VPAD_BUTTON_RIGHT; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_UP) buttons_hold |= VPAD_BUTTON_UP; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_DOWN) buttons_hold |= VPAD_BUTTON_DOWN; if (pro_buffer->pro.hold & WPAD_PRO_TRIGGER_L) buttons_hold |= VPAD_BUTTON_L; if (pro_buffer->pro.hold & WPAD_PRO_TRIGGER_ZL) buttons_hold |= VPAD_BUTTON_ZL; if (pro_buffer->pro.hold & WPAD_PRO_TRIGGER_R) buttons_hold |= VPAD_BUTTON_R; if (pro_buffer->pro.hold & WPAD_PRO_TRIGGER_ZR) buttons_hold |= VPAD_BUTTON_ZR; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_STICK_L) buttons_hold |= VPAD_BUTTON_STICK_L; if (pro_buffer->pro.hold & WPAD_PRO_BUTTON_STICK_R) buttons_hold |= VPAD_BUTTON_STICK_R; if (pro_buffer->pro.hold & WPAD_PRO_STICK_L_EMULATION_LEFT) buttons_hold |= VPAD_STICK_L_EMULATION_LEFT; if (pro_buffer->pro.hold & WPAD_PRO_STICK_L_EMULATION_RIGHT) buttons_hold |= VPAD_STICK_L_EMULATION_RIGHT; if (pro_buffer->pro.hold & WPAD_PRO_STICK_L_EMULATION_UP) buttons_hold |= VPAD_STICK_L_EMULATION_UP; if (pro_buffer->pro.hold & WPAD_PRO_STICK_L_EMULATION_DOWN) buttons_hold |= VPAD_STICK_L_EMULATION_DOWN; if (pro_buffer->pro.hold & WPAD_PRO_STICK_R_EMULATION_LEFT) buttons_hold |= VPAD_STICK_R_EMULATION_LEFT; if (pro_buffer->pro.hold & WPAD_PRO_STICK_R_EMULATION_RIGHT) buttons_hold |= VPAD_STICK_R_EMULATION_RIGHT; if (pro_buffer->pro.hold & WPAD_PRO_STICK_R_EMULATION_UP) buttons_hold |= VPAD_STICK_R_EMULATION_UP; if (pro_buffer->pro.hold & WPAD_PRO_STICK_R_EMULATION_DOWN) buttons_hold |= VPAD_STICK_R_EMULATION_DOWN; vpad_buffer->leftStick.x = pro_buffer->pro.leftStick.x; vpad_buffer->leftStick.y = pro_buffer->pro.leftStick.y; vpad_buffer->rightStick.x = pro_buffer->pro.rightStick.x; vpad_buffer->rightStick.y = pro_buffer->pro.rightStick.y; vpad_buffer->hold |= buttons_hold; vpad_buffer->trigger |= (buttons_hold & (~*lastButtonsPressesVPAD)); vpad_buffer->release |= (*lastButtonsPressesVPAD & (~buttons_hold)); *lastButtonsPressesVPAD = buttons_hold; return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::checkValueinConfigController(int32_t deviceslot, int32_t CONTRPS_slot, int32_t expectedValue) { if (config_controller[deviceslot][CONTRPS_slot][0] != CONTROLLER_PATCHER_INVALIDVALUE) { if (expectedValue == config_controller[deviceslot][CONTRPS_slot][1]) return 1; } return 0; } void ControllerPatcherUtils::setConfigValue(uint8_t *dest, uint8_t first, uint8_t second) { dest[0] = first; dest[1] = second; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getDeviceSlot(uint32_t hidmask) { for (int32_t i = 0; i < gHIDMaxDevices; i++) { if (hidmask & config_controller_hidmask[i]) { return i; } } return CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getDeviceInfoFromVidPid(DeviceInfo *info) { if (info != NULL) { for (int32_t i = 0; i < gHIDMaxDevices; i++) { uint16_t my_vid = config_controller[i][CONTRPS_VID][0] * 0x100 + config_controller[i][CONTRPS_VID][1]; uint16_t my_pid = config_controller[i][CONTRPS_PID][0] * 0x100 + config_controller[i][CONTRPS_PID][1]; //log_printf("info->vidpid.vid (%04X) == my_vid (%04X) && info->vidpid.pid (%04X) == my_pid (%04X)",info->vidpid.vid,my_vid,info->vidpid.pid,my_pid); if (info->vidpid.vid == my_vid && info->vidpid.pid == my_pid) { info->slotdata.hidmask = config_controller_hidmask[i]; info->slotdata.deviceslot = i; info->pad_count = 1; if (config_controller[i][CONTRPS_PAD_COUNT][0] != CONTROLLER_PATCHER_INVALIDVALUE) { info->pad_count = config_controller[i][CONTRPS_PAD_COUNT][1]; if (info->pad_count > HID_MAX_PADS_COUNT) { info->pad_count = HID_MAX_PADS_COUNT; } } return CONTROLLER_PATCHER_ERROR_NONE; //log_printf("Found device: device: %s slot: %d",byte_to_binary(device),deviceSlot); break; } } return CONTROLLER_PATCHER_ERROR_UNKNOWN_VID_PID; } return CONTROLLER_PATCHER_ERROR_INVALID_BUFFER; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getNextSlotData(HIDSlotData *slotdata) { if (slotdata == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if (gHIDRegisteredDevices >= gHIDMaxDevices) return CONTROLLER_PATCHER_ERROR_NO_FREE_SLOT; slotdata->deviceslot = gHIDRegisteredDevices; slotdata->hidmask = (1 << (gHIDRegisteredDevices)); gHIDRegisteredDevices++; return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getVIDPIDbyDeviceSlot(int32_t deviceslot, DeviceVIDPIDInfo *vidpid) { if (vidpid == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER; if (deviceslot >= gHIDMaxDevices || deviceslot < 0) return CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND; vidpid->vid = config_controller[deviceslot][CONTRPS_VID][0] * 0x100 + config_controller[deviceslot][CONTRPS_VID][1]; vidpid->pid = config_controller[deviceslot][CONTRPS_PID][0] * 0x100 + config_controller[deviceslot][CONTRPS_PID][1]; if (vidpid->vid == 0x0000) return CONTROLLER_PATCHER_ERROR_FAILED_TO_GET_HIDDATA; return CONTROLLER_PATCHER_ERROR_NONE; } int32_t ControllerPatcherUtils::getPadSlotInAdapter(int32_t deviceslot, uint8_t *input_data) { int32_t slot_incr = 0; if (config_controller[deviceslot][CONTRPS_PAD_COUNT][0] != CONTROLLER_PATCHER_INVALIDVALUE) { int32_t pad_count = config_controller[deviceslot][CONTRPS_PAD_COUNT][1]; if (pad_count > HID_MAX_PADS_COUNT) { pad_count = HID_MAX_PADS_COUNT; } for (int32_t i = 0; i < pad_count; i++) { if (config_controller[deviceslot][CONTRPS_PAD1_FILTER + i][0] != CONTROLLER_PATCHER_INVALIDVALUE) { if (input_data[config_controller[deviceslot][CONTRPS_PAD1_FILTER + i][0]] == config_controller[deviceslot][CONTRPS_PAD1_FILTER + i][1]) { slot_incr = i; break; } } } } return slot_incr; } ControllerMappingPAD *ControllerPatcherUtils::getControllerMappingByType(UController_Type type) { ControllerMappingPAD *cm_map_pad = NULL; if (type == UController_Type_Gamepad) { cm_map_pad = &(gControllerMapping.gamepad); } else if (type == UController_Type_Pro1) { cm_map_pad = &(gControllerMapping.proController[0]); } else if (type == UController_Type_Pro2) { cm_map_pad = &(gControllerMapping.proController[1]); } else if (type == UController_Type_Pro3) { cm_map_pad = &(gControllerMapping.proController[2]); } else if (type == UController_Type_Pro4) { cm_map_pad = &(gControllerMapping.proController[3]); } return cm_map_pad; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::doSampling(uint16_t deviceslot, uint8_t padslot = 0, BOOL ignorePadSlot = false) { if (gSamplingCallback != nullptr) { doSamplingSingle(WPAD_CHAN_0, deviceslot, padslot, ignorePadSlot); doSamplingSingle(WPAD_CHAN_1, deviceslot, padslot, ignorePadSlot); doSamplingSingle(WPAD_CHAN_2, deviceslot, padslot, ignorePadSlot); doSamplingSingle(WPAD_CHAN_3, deviceslot, padslot, ignorePadSlot); } return CONTROLLER_PATCHER_ERROR_NONE; } CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::doSamplingSingle(WPADChan chan, uint16_t deviceslot, uint8_t padslot = 0, BOOL ignorePadSlot = false) { ControllerMappingPADInfo *padinfo = gProPadInfo[chan]; if (padinfo->active) { DeviceInfo device_info; memset(&device_info, 0, sizeof(device_info)); device_info.vidpid = padinfo->vidpid; int32_t res = -1; if ((res = ControllerPatcherUtils::getDeviceInfoFromVidPid(&device_info)) >= 0) { if (!ignorePadSlot) { int32_t real_pad = (padinfo->pad / (device_info.pad_count)) * device_info.pad_count; if (real_pad == padslot && device_info.slotdata.deviceslot == deviceslot) { if (ControllerPatcherUtils::checkActivePad(device_info.slotdata.hidmask, padinfo->pad)) { gSamplingCallback(chan); } } } else { gSamplingCallback(chan); } } } return CONTROLLER_PATCHER_ERROR_NONE; }