Merge pull request #4948 from Maschell/wiiu_controller_patcher

[Wii U] Adding support for HID Controllers
This commit is contained in:
Twinaphex 2017-05-20 20:28:58 +02:00 committed by GitHub
commit 8b4c92291f
46 changed files with 7742 additions and 36 deletions

4
.gitmodules vendored Normal file
View File

@ -0,0 +1,4 @@
[submodule "wiiu/controller_patcher"]
path = wiiu/controller_patcher
url = https://github.com/Maschell/controller_patcher
branch = retroarch

View File

@ -1,18 +1,33 @@
TARGET := retroarch_wiiu
BUILD_HBL_ELF = 1
BUILD_RPX = 1
BUILD_RPX = 1
DEBUG = 0
GRIFFIN_BUILD = 0
WHOLE_ARCHIVE_LINK = 0
PC_DEVELOPMENT_IP_ADDRESS =
PC_DEVELOPMENT_TCP_PORT =
PC_DEVELOPMENT_IP_ADDRESS =
PC_DEVELOPMENT_TCP_PORT =
OBJ :=
OBJ += wiiu/system/memory.o
OBJ += wiiu/system/exception_handler.o
OBJ += wiiu/fs/sd_fat_devoptab.o
OBJ += wiiu/fs/fs_utils.o
OBJ += wiiu/controller_patcher/ControllerPatcher.o
OBJ += wiiu/controller_patcher/ControllerPatcherWrapper.o
OBJ += wiiu/controller_patcher/ConfigReader.o
OBJ += wiiu/controller_patcher/config/ConfigParser.o
OBJ += wiiu/controller_patcher/config/ConfigValues.o
OBJ += wiiu/controller_patcher/network/ControllerPatcherNet.o
OBJ += wiiu/controller_patcher/network/TCPServer.o
OBJ += wiiu/controller_patcher/network/UDPClient.o
OBJ += wiiu/controller_patcher/network/UDPServer.o
OBJ += wiiu/controller_patcher/patcher/ControllerPatcherUtils.o
OBJ += wiiu/controller_patcher/patcher/ControllerPatcherHID.o
OBJ += wiiu/controller_patcher/utils/CPRetainVars.o
OBJ += wiiu/controller_patcher/utils/CPStringTools.o
OBJ += wiiu/controller_patcher/utils/PadConst.o
OBJ += wiiu/controller_patcher/utils/FSHelper.o
OBJ += wiiu/tex_shader.o
OBJ += wiiu/hbl.o
@ -138,7 +153,7 @@ ifeq ($(WHOLE_ARCHIVE_LINK), 1)
WHOLE_START := -Wl,--whole-archive
WHOLE_END := -Wl,--no-whole-archive
endif
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions
CXXFLAGS := $(CFLAGS) -fno-rtti -fno-exceptions -D_GNU_SOURCE
LDFLAGS += -Wl,--gc-sections

View File

@ -54,9 +54,10 @@
#include <wiiu/vpad.h>
#include <wiiu/kpad.h>
#include "wiiu/controller_patcher/ControllerPatcherWrapper.h"
#include <fat.h>
#include <iosuhax.h>
#include "wiiu_dbg.h"
#include "hbl.h"
@ -405,7 +406,8 @@ int main(int argc, char **argv)
#endif
verbosity_enable();
printf("starting\n");
ControllerPatcherInit();
fflush(stdout);
DEBUG_VAR(ARGV_PTR);
if(ARGV_PTR && ((u32)ARGV_PTR < 0x01000000))
@ -458,6 +460,8 @@ int main(int argc, char **argv)
}
while (1);
ControllerPatcherDeInit();
main_exit(NULL);
#endif
#endif

View File

@ -21,6 +21,8 @@
#include <wiiu/vpad.h>
#include <wiiu/kpad.h>
#include "wiiu/controller_patcher/ControllerPatcherWrapper.h"
#include "../input_config.h"
#include "../input_driver.h"
#include "../input_joypad_driver.h"
@ -33,7 +35,7 @@
#include "wiiu_dbg.h"
#ifndef MAX_PADS
#define MAX_PADS 5
#define MAX_PADS 16
#endif
#define WIIUINPUT_TYPE_WIIMOTE 0x00
@ -42,22 +44,33 @@
#define WIIUINPUT_TYPE_PRO_CONTROLLER 0x1F
#define WIIUINPUT_TYPE_NONE 0xFD
#define GAMEPAD_COUNT 1
#define KPAD_COUNT 4
#define HID_COUNT (MAX_PADS - GAMEPAD_COUNT - KPAD_COUNT)
#define GAMEPAD_OFFSET 0
#define KPAD_OFFSET (GAMEPAD_OFFSET + GAMEPAD_COUNT)
#define HID_OFFSET (KPAD_OFFSET + KPAD_COUNT)
static uint64_t pad_state[MAX_PADS];
static u8 pad_type[MAX_PADS - 1] = {WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE};
static u8 pad_type[KPAD_COUNT] = {WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE, WIIUINPUT_TYPE_NONE};
static u8 hid_status[HID_COUNT];
static InputData hid_data[HID_COUNT];
static int16_t analog_state[MAX_PADS][2][2];
extern uint64_t lifecycle_state;
static bool wiiu_pad_inited = false;
static char hidName[HID_COUNT][255];
static const char* wiiu_joypad_name(unsigned pad)
{
if (pad == 0)
return "WIIU Gamepad";
if (pad < MAX_PADS)
if (pad < MAX_PADS && pad < (HID_OFFSET) && pad > GAMEPAD_OFFSET)
{
switch (pad_type[pad - 1])
int i = pad - KPAD_OFFSET;
switch (pad_type[i])
{
case WIIUINPUT_TYPE_NONE:
return "N/A";
@ -76,6 +89,12 @@ static const char* wiiu_joypad_name(unsigned pad)
}
}
if(pad < MAX_PADS){
s32 hid_index = pad-HID_OFFSET;
sprintf(hidName[hid_index],"HID %04X/%04X",hid_data[hid_index].device_info.vidpid.vid,hid_data[hid_index].device_info.vidpid.pid);
return hidName[hid_index];
}
return "unknown";
}
@ -89,7 +108,7 @@ static void wiiu_joypad_autodetect_add(unsigned autoconf_pad)
0,
0
))
input_config_set_device_name(autoconf_pad, wiiu_joypad_name(autoconf_pad));
input_config_set_device_name(autoconf_pad, wiiu_joypad_name(autoconf_pad));
}
static bool wiiu_joypad_button(unsigned port_num, uint16_t key)
@ -158,9 +177,7 @@ static void wiiu_joypad_poll(void)
int c;
VPADStatus vpad;
VPADReadError vpadError;
VPADRead(0, &vpad, 1, &vpadError);
if (!vpadError)
{
pad_state[0] = vpad.hold & ~0x7F800000; /* clear out emulated analog sticks */
@ -228,11 +245,40 @@ static void wiiu_joypad_poll(void)
break;
}
}
memset(hid_data,0,sizeof(hid_data));
int result = gettingInputAllDevices(hid_data,HID_COUNT);
if(result+HID_OFFSET > MAX_PADS){
result = MAX_PADS - HID_OFFSET;
}
for(int i = HID_OFFSET;i<result+HID_OFFSET;i++){
int hid_index = i-HID_OFFSET;
u8 old_status = hid_status[hid_index];
u8 new_status = hid_data[hid_index].status; //TODO: defines for the status.
if(old_status == 1 || new_status == 1){
hid_status[hid_index] = new_status;
if(old_status == 0 && new_status == 1){ //Pas was attached
wiiu_joypad_autodetect_add(i);
}else if(old_status == 1 && new_status == 0){ //Pad was detached
input_autoconfigure_disconnect(i, wiiu_joypad.ident);
}else if(old_status == 1 && new_status == 1){ // Pad is still connected
pad_state[i] = hid_data[hid_index].button_data.hold & ~0x7F800000; /* clear out emulated analog sticks */
analog_state[i][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_X] = hid_data[hid_index].stick_data.leftStickX * 0x7FF0;
analog_state[i][RETRO_DEVICE_INDEX_ANALOG_LEFT] [RETRO_DEVICE_ID_ANALOG_Y] = hid_data[hid_index].stick_data.leftStickY * 0x7FF0;
analog_state[i][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_X] = hid_data[hid_index].stick_data.rightStickX * 0x7FF0;
analog_state[i][RETRO_DEVICE_INDEX_ANALOG_RIGHT] [RETRO_DEVICE_ID_ANALOG_Y] = hid_data[hid_index].stick_data.rightStickY * 0x7FF0;
}
}
}
}
static bool wiiu_joypad_init(void* data)
{
wiiu_joypad_autodetect_add(0);
memset(hid_status,0,sizeof(hid_status));
wiiu_joypad_poll();
wiiu_pad_inited = true;
(void)data;

View File

@ -540,6 +540,7 @@ const char* const input_builtin_autoconfs[] =
#endif
#ifdef WIIU
DECL_AUTOCONF_DEVICE("WIIU Gamepad", "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("HID Controller", "wiiu", WIIUINPUT_GAMEPAD_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("WIIU Pro Controller", "wiiu", WIIUINPUT_PRO_CONTROLLER_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Wiimote Controller", "wiiu", WIIUINPUT_WIIMOTE_DEFAULT_BINDS),
DECL_AUTOCONF_DEVICE("Nunchuk Controller", "wiiu", WIIUINPUT_NUNCHUK_DEFAULT_BINDS),

View File

@ -0,0 +1,158 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "./ConfigReader.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <map>
#include "wiiu/fs.h"
#include "wiiu/controller_patcher/utils/FSHelper.h"
#define FS_MOUNT_SOURCE_SIZE 0x300
#define FS_MAX_MOUNTPATH_SIZE 12
#define FS_CLIENT_SIZE 0x1700
#define FS_CMD_BLOCK_SIZE 0xA80
#define FS_SOURCETYPE_EXTERNAL 0
#define FS_SOURCETYPE_HFIO 1
s32 ConfigReader::numberValidFiles = 0;
ConfigReader *ConfigReader::instance = NULL;
ConfigReader::ConfigReader(){
}
void ConfigReader::ReadAllConfigs(){
std::vector<std::string> fileList = ScanFolder();
if(fileList.size() > 0){
if(HID_DEBUG){ printf("ConfigReader::ConfigReader(line %d): Found %d config files\n",__LINE__,fileList.size()); }
processFileList(fileList);
}
}
ConfigReader::~ConfigReader(){
if(HID_DEBUG){ printf("ConfigReader::~ConfigReader(line %d): ~ConfigReader\n",__LINE__); }
freeFSHandles();
}
void ConfigReader::freeFSHandles(){
if(this->pClient != NULL){
FSDelClient((FSClient *)this->pClient,-1);
free(this->pClient);
this->pClient = NULL;
}
if(this->pCmd != NULL){
free(this->pCmd);
this->pCmd = NULL;
}
}
// Mounting the sdcard without any external lib to be portable (Currently broken)
s32 ConfigReader::InitSDCard(){
if(HID_DEBUG){ printf("ConfigReader::InitSDCard(line %d): InitSDCard\n",__LINE__); }
int result = -1;
// get command and client
this->pClient = malloc(sizeof(FSClient));
this->pCmd = malloc(sizeof(FSCmdBlock));
if(!pClient || !pCmd) {
// just in case free if not 0
if(pClient)
free(pClient);
if(pCmd)
free(pCmd);
return -2;
}
FSInit();
FSInitCmdBlock((FSCmdBlock*)pCmd);
FSAddClient((FSClient*)pClient, -1);
char *mountPath = NULL;
if((result = FS_Helper_MountFS(pClient, pCmd, &mountPath)) == 0) {
//free(mountPath);
}
return result;
}
std::vector<std::string> ConfigReader::ScanFolder(){
std::string path = CONTROLLER_PATCHER_PATH;
s32 dirhandle = 0;
if(HID_DEBUG){ printf("ConfigReader::ScanFolder(line %d): Opening %s\n",__LINE__,path.c_str()); }
std::vector<std::string> config_files;
if (this->pClient && this->pCmd){
s32 status = 0;
if((status = FSOpenDir((FSClient*)this->pClient,(FSCmdBlock*)this->pCmd,path.c_str(),(FSDirectoryHandle *)&dirhandle,-1)) == FS_STATUS_OK){
FSDirectoryEntry dir_entry;
while (FSReadDir((FSClient*)this->pClient,(FSCmdBlock*)this->pCmd, dirhandle, &dir_entry, -1) == FS_STATUS_OK){
std::string full_path = path + "/" + dir_entry.name;
if((dir_entry.info.flags&FS_STAT_DIRECTORY) != FS_STAT_DIRECTORY){
if(CPStringTools::EndsWith(std::string(dir_entry.name),".ini")){
config_files.push_back(full_path);
if(HID_DEBUG){ printf("ConfigReader::ScanFolder(line %d): %s \n",__LINE__,full_path.c_str()); }
}
}
}
FSCloseDir((FSClient*)this->pClient,(FSCmdBlock*)this->pCmd,dirhandle,-1);
}else{
printf("ConfigReader::ScanFolder(line %d): Failed to open %s!\n",__LINE__,path.c_str());
}
}
return config_files;
}
void ConfigReader::processFileList(std::vector<std::string> path){
for(std::vector<std::string>::iterator it = path.begin(); it != path.end(); ++it) {
printf("ConfigReader::processFileList(line %d): Reading %s\n",__LINE__,it->c_str());
std::string result = loadFileToString(*it);
ConfigParser parser(result);
parser.parseIni();
}
}
std::string ConfigReader::loadFileToString(std::string path){
FSFileHandle handle = 0;
s32 status = 0;
std::string strBuffer;
char * result = NULL;
if(FS_Helper_GetFile(this->pClient,this->pCmd,path.c_str(), &result) == 0){
if(result != NULL){
strBuffer = std::string((char *)result);
free(result);
result = NULL;
//! remove all windows crap signs
strBuffer = CPStringTools::removeCharFromString(strBuffer,'\r');
strBuffer = CPStringTools::removeCharFromString(strBuffer,' ');
strBuffer = CPStringTools::removeCharFromString(strBuffer,'\t');
}
}else{
printf("ConfigReader::loadFileToString(line %d): Failed to load %s\n",__LINE__,path.c_str());
}
return strBuffer;
}

View File

@ -0,0 +1,74 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _ConfigReader_H_
#define _ConfigReader_H_
#include <wiiu/types.h>
#include <string>
#include <vector>
#include "./ControllerPatcher.hpp"
#define CONTROLLER_PATCHER_PATH "/vol/external01/wiiu/controller";
class ConfigReader{
friend class ControllerPatcher;
friend class ConfigParser;
private:
static ConfigReader *getInstance() {
if(!instance){
instance = new ConfigReader();
}
return instance;
}
static void destroyInstance() {
if(instance){
delete instance;
instance = NULL;
}
}
static s32 getNumberOfLoadedFiles(){
return ConfigReader::numberValidFiles;
}
static void increaseNumberOfLoadedFiles(){
ConfigReader::numberValidFiles++;
}
void ReadAllConfigs();
static s32 numberValidFiles;
//!Constructor
ConfigReader();
//!Destructor
~ConfigReader();
s32 InitSDCard();
void freeFSHandles();
void * pClient = NULL;
void * pCmd = NULL;
static ConfigReader *instance;
std::string loadFileToString(std::string path);
void processFileList(std::vector<std::string> path);
std::vector<std::string> ScanFolder();
};
#endif

File diff suppressed because it is too large Load Diff

View File

@ -0,0 +1,251 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* @file ControllerPatcher.hpp
* @author Maschell
* @date 30 Mar 2017
* \brief This files contain all public accessible functions of the controller patcher engine
*
* @see https://github.com/Maschell/controller_patcher
*/
#ifndef _CONTROLLER_PATCHER_H_
#define _CONTROLLER_PATCHER_H_
#include <string>
#include "./patcher/ControllerPatcherDefs.h"
#include "./utils/ControllerPatcherThread.hpp"
#include "./utils/CPRetainVars.hpp"
#include "./utils/PadConst.hpp"
#include "./utils/CPStringTools.hpp"
#include "./patcher/ControllerPatcherHID.hpp"
#include "./patcher/ControllerPatcherUtils.hpp"
#include "./config/ConfigValues.hpp"
#include "./config/ConfigParser.hpp"
#include "./network/ControllerPatcherNet.hpp"
#include "./network/TCPServer.hpp"
#include "./network/UDPServer.hpp"
#include "./network/UDPClient.hpp"
#include "./ConfigReader.hpp"
#include "wiiu/vpad.h"
#define BUS_SPEED 248625000
#define SECS_TO_TICKS(sec) (((unsigned long long)(sec)) * (BUS_SPEED/4))
#define MILLISECS_TO_TICKS(msec) (SECS_TO_TICKS(msec) / 1000)
#define MICROSECS_TO_TICKS(usec) (SECS_TO_TICKS(usec) / 1000000)
#define wiiu_os_usleep(usecs) OSSleepTicks(MICROSECS_TO_TICKS(usecs))
#define HID_DEBUG 0
class ControllerPatcher{
public:
/*-----------------------------------------------------------------------------------------------------------------------------------
* Initialization
*----------------------------------------------------------------------------------------------------------------------------------*/
/**
\brief Resets the data thats used by the controller configuration
**/
static void ResetConfig();
/**
\brief Initializes the libraries, functions, values and arrays. Need to be called on each start of an Application. Returns false on errors.
**/
static bool Init();
/**
\brief De-Initialises the controller_patcher
**/
static void DeInit();
/**
Initialises the button remapping
**/
static void InitButtonMapping();
/**
Starts the network server
**/
static void startNetworkServer();
/**
Stops the network server
**/
static void stopNetworkServer();
/*-----------------------------------------------------------------------------------------------------------------------------------
* Initialization
*----------------------------------------------------------------------------------------------------------------------------------*/
/**
Sets the data in a given data from HID Devices. The information about which HID Device will be used is stored in the gControllerMapping array int slot 1-4 (counting starts at 0, which is the gamepad). The \p
chan provides the information of the channel from which the data will be used. The mode sets the type of the buffer.
@param buffer: A pointer to the struct where the result will be stored.
@param chan: Indicates the channel from which slot the information about the mapped HID Device will be used.
@param mode: Sets the type of the buffer. PRO_CONTROLLER_MODE_KPADDATA or PRO_CONTROLLER_MODE_WPADReadData
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setProControllerDataFromHID(void * data,s32 chan,s32 mode = PRO_CONTROLLER_MODE_KPADDATA);
/**
Sets the data in a given VPADStatus from HID Devices. The information about which HID Device will be used is stored in the gControllerMapping array in slot 0.
@param buffer: A pointer to an KPADData struct where the result will be stored.
@param chan: Indicates the channel from which slot the information about the mapped HID Device will be used.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setControllerDataFromHID(VPADStatus * buffer);
/*-----------------------------------------------------------------------------------------------------------------------------------
* Useful functions
*----------------------------------------------------------------------------------------------------------------------------------*/
/**
Enable the Controller mapping.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR enableControllerMapping();
/**
Disbale the Controller mapping. Afterwards all connected controllers will be used for the gamepad.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR disableControllerMapping();
/**
Disables the energy settings for the WiiU. Settings can be restored via restoreWiiUEnergySetting.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR disableWiiUEnergySetting();
/**
Restores the WiiU Energy Settings.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR restoreWiiUEnergySetting();
/**
Resets the controller mapping for a given controller type.
@param type: The type of the controller.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR resetControllerMapping(UController_Type type);
/**
Adds a controller mapping
@param type: The type of the controller.
@param config: information about the added controller.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR addControllerMapping(UController_Type type,ControllerMappingPADInfo config);
/**
@return The first active mapping slot for the given controller type will be returned. If the controller type is not set active, -1 will be returned.
**/
static s32 getActiveMappingSlot(UController_Type type);
/**
@param type: The type of the controller.
@param mapping_slot: information about the added controller.
@return When the functions failed result < 0 is returned. Otherwise a pointer to a ControllerMappingPADInfo is returned.
**/
static ControllerMappingPADInfo * getControllerMappingInfo(UController_Type type,s32 mapping_slot);
/**
Checks if a emulated controller is connected for the given controller type / mapping slot.
@param type: The type of the controller.
@param mapping_slot: Slot of the controller mapped to this controller type (usually 0)
@return
**/
static bool isControllerConnectedAndActive(UController_Type type,s32 mapping_slot = 0);
/**
Search for a connected mouse and returns a pointer to it's data.
@return A pointer to the first connected mouse that is found. NULL if no mouse is connected.
**/
static HID_Mouse_Data * getMouseData();
/**
Sets a rumble status for a controller.
@param type: The type of the controller.
@param status: status of the rumble. 0 for off, 1 for on.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setRumble(UController_Type type,u32 status);
/**
Reads the input of all connected HID devices. Each attached controller will write his date into given array until it's full.
@param output: A pointer to an InputData array where the result will be stored. (Make sure to reset the array before using this function).
@param array_size: Size of the given InputData array.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful. If the result is > 0 the number of stored sets in the array is returned.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR gettingInputAllDevices(InputData * output,s32 array_size);
/**
Remaps the buttons in the given \p VPADStatus pointer. InitButtonMapping() needs to be called before calling this. The information about the remapping is stored in the config_controller array.
One easy way to set it is using the a config file on the SD Card.
@param buffer: A pointer to the buffer where the input will be read from and the result will be stored.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR buttonRemapping(VPADStatus * buffer, s32 buffer_count);
/**
Prints the current pressed down buttons of the given \p VPADStatus pointer. Uses the utils/logger.c UDP logger..
@param buffer: A pointer to the buffer where the input will be read from.
@return When the functions failed result < 0 is returned. If the result is == 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR printVPADButtons(VPADStatus * buffer);
static std::string getIdentifierByVIDPID(u16 vid,u16 pid);
static void destroyConfigHelper();
static CONTROLLER_PATCHER_RESULT_OR_ERROR doSamplingForDeviceSlot(u16 device_slot);
static CONTROLLER_PATCHER_RESULT_OR_ERROR setRumbleActivated(bool value);
static bool isRumbleActivated();
};
#endif /* _CONTROLLER_PATCHER_H_ */

View File

@ -0,0 +1,39 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "controller_patcher/ControllerPatcher.hpp"
#include "controller_patcher/ControllerPatcherWrapper.h"
extern "C" void ControllerPatcherInit(void){
ControllerPatcher::Init();
ControllerPatcher::disableControllerMapping();
ControllerPatcher::startNetworkServer();
ControllerPatcher::disableWiiUEnergySetting();
}
extern "C" CONTROLLER_PATCHER_RESULT_OR_ERROR setControllerDataFromHID(VPADStatus * data){
ControllerPatcher::setControllerDataFromHID(data);
}
extern "C" CONTROLLER_PATCHER_RESULT_OR_ERROR gettingInputAllDevices(InputData * output,s32 array_size){
ControllerPatcher::gettingInputAllDevices(output,array_size);
}
extern "C" void ControllerPatcherDeInit(void){
ControllerPatcher::restoreWiiUEnergySetting();
ControllerPatcher::stopNetworkServer();
ControllerPatcher::DeInit();
}

View File

@ -0,0 +1,23 @@
#ifndef _CONTROLLER_PATCHER_WRAPPER_H_
#define _CONTROLLER_PATCHER_WRAPPER_H_
#include "wiiu/vpad.h"
/* Main */
#ifdef __cplusplus
extern "C" {
#endif
#include "./patcher/ControllerPatcherDefs.h"
//! C wrapper for our C++ functions
void ControllerPatcherInit(void);
void ControllerPatcherDeInit(void);
CONTROLLER_PATCHER_RESULT_OR_ERROR setControllerDataFromHID(VPADStatus * data);
CONTROLLER_PATCHER_RESULT_OR_ERROR gettingInputAllDevices(InputData * output,s32 array_size);
#ifdef __cplusplus
}
#endif
#endif

View File

@ -0,0 +1,337 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "./ConfigParser.hpp"
#include <algorithm>
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ConfigParser::ConfigParser(std::string configData){
this->content = configData;
this->contentLines = CPStringTools::StringSplit(content, "\n");
if(contentLines.empty())
return;
//remove the comments and make everything uppercase
for(u32 i = 0; i < contentLines.size(); i++){
std::vector<std::string> comments = CPStringTools::StringSplit(contentLines[i], "//");
if(!comments.empty()){
contentLines[i] = comments[0];
}
//we want everything uppercase
std::transform(contentLines[i].begin(), contentLines[i].end(),contentLines[i].begin(), ::toupper);
}
//remove empty lines
std::vector<std::string> contentline2;
for(u32 i = 0; i < contentLines.size(); i++){
if(strlen(contentLines[i].c_str()) > 0){
contentline2.push_back(contentLines[i]);
}
}
contentLines = contentline2;
Init();
}
ConfigParser::~ConfigParser(){
}
PARSE_TYPE ConfigParser::getType(){
return type_b;
}
void ConfigParser::setType(PARSE_TYPE newType){
this->type_b = newType;
}
u16 ConfigParser::getSlot(){
return this->slot_b;
}
void ConfigParser::setSlot(u16 newSlot){
this->slot_b = newSlot;
}
bool ConfigParser::Init(){
if(contentLines.size() == 0){
printf("ConfigParser::Init(line %d): Files seems to be empty. Make sure to have a proper header\n",__LINE__);
return false;
}
const char * line = contentLines[0].c_str();
s32 len = strlen(line);
std::string identify;
if(line[0] == '[' && line[len-1] == ']'){
identify = contentLines[0].substr(1,len-2);
}else{
printf("ConfigParser::Init((line %d): Not a proper config file!\n",__LINE__);
return false;
}
if(identify.compare("GAMEPAD") == 0){
printf("ConfigParser::Init((line %d): Its a gamepad config file!\n",__LINE__);
setSlot(gGamePadSlot);
setType(PARSE_GAMEPAD);
}else if(identify.compare("MOUSE") == 0){
printf("ConfigParser::Init((line %d): Its a mouse config file!\n",__LINE__);
setSlot(gMouseSlot);
setType(PARSE_MOUSE);
this->vid = HID_MOUSE_VID;
this->pid = HID_MOUSE_PID;
}else if(identify.compare("KEYBOARD") == 0){
printf("ConfigParser::Init((line %d): Its a keyboard config file!\n",__LINE__);
setSlot(gHID_SLOT_KEYBOARD);
setType(PARSE_KEYBOARD);
this->vid = HID_KEYBOARD_VID;
this->pid = HID_KEYBOARD_PID;
}else{
printf("ConfigParser::Init((line %d): Its a controller config file!\n",__LINE__);
setSlot(getSlotController(identify));
setType(PARSE_CONTROLLER);
}
if(getSlot() == HID_INVALID_SLOT){
return false;
}
ConfigReader::increaseNumberOfLoadedFiles();
return true;
}
void ConfigParser::parseSingleLine(std::string line){
std::vector<std::string> cur_values = CPStringTools::StringSplit(line,"=");
if(cur_values.size() != 2){
if(HID_DEBUG || cur_values.size() > 2){ printf("ConfigParser::parseSingleLine(line %d): Not a valid key=pair line %s\n",__LINE__,line.c_str()); }
return;
}else{
u16 hid_slot = getSlot();
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): leftpart = \"%s\" \n",__LINE__,cur_values[0].c_str()); }
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): rightpart = \"%s\" \n",__LINE__,cur_values[1].c_str()); }
s32 keyslot = -1;
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Checking single value\n",__LINE__); }
if(getType() == PARSE_GAMEPAD || getType() == PARSE_KEYBOARD){
keyslot = ConfigValues::getKeySlotGamePad(cur_values[0]);
}else if(getType() == PARSE_MOUSE){
keyslot = ConfigValues::getKeySlotMouse(cur_values[0]);
}else{
keyslot = ConfigValues::getKeySlotDefaultSingleValue(cur_values[0]);
}
if(keyslot != -1){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Its a single value\n",__LINE__); }
long rightValue = -1;
bool valueSet = false;
if(cur_values[0].compare("DPAD_MODE") == 0){
const u8 * values_ = NULL;
if((values_ = ConfigValues::getValuesStickPreset(cur_values[1])) != NULL){
if(values_[STICK_CONF_MAGIC_VERSION] != STICK_CONF_MAGIC_VALUE)
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Settings preset DPAD MODE and Mask\n",__LINE__); }
config_controller[hid_slot][CONTRPS_DPAD_MODE][0] = CONTROLLER_PATCHER_VALUE_SET;
config_controller[hid_slot][CONTRPS_DPAD_MODE][1] = values_[CONTRDPAD_MODE];
if(values_[CONTRDPAD_MASK] != 0x00){
config_controller[hid_slot][CONTRPS_DPAD_MASK][0] = CONTROLLER_PATCHER_VALUE_SET;
config_controller[hid_slot][CONTRPS_DPAD_MASK][1] = values_[CONTRDPAD_MASK];
}
valueSet = true;
}
}
if(!valueSet){
if(getType() == PARSE_KEYBOARD){
if((rightValue = ConfigValues::getPresetValuesKeyboard(cur_values[1]))!= -1){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Used pre-defined Keyboard! \"%s\" is %d\n",__LINE__,cur_values[1].c_str(),rightValue);}
}else{
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): I need to parse %s\n",__LINE__,cur_values[1].c_str()); }
char * ptr;
rightValue = strtol(cur_values[1].c_str(),&ptr,16);
}
}else{
rightValue = ConfigValues::getPresetValue(cur_values[1]);
if(getType() == PARSE_MOUSE){ //No parsing for the mouse
if(rightValue == -1){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Invalid mouse value, lets skip it %s\n",__LINE__,cur_values[1].c_str()); }
return;
}
}else{
if(rightValue == -1){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): I need to parse %s\n",__LINE__,cur_values[1].c_str()); }
char * ptr;
rightValue = strtol(cur_values[1].c_str(),&ptr,16);
}
}
}
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Setting value to %d\n",__LINE__,rightValue); }
config_controller[hid_slot][keyslot][0] = CONTROLLER_PATCHER_VALUE_SET;
config_controller[hid_slot][keyslot][1] = rightValue;
}
}else{
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Check pair value\n",__LINE__); }
keyslot = ConfigValues::getKeySlotDefaultPairedValue(cur_values[0]);
if(keyslot != -1){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Its a pair value\n",__LINE__); }
if(!ConfigValues::getInstance()->setIfValueIsAControllerPreset(cur_values[1],getSlot(),keyslot)){
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): And its no preset\n",__LINE__); }
std::vector<std::string> rightvalues = CPStringTools::StringSplit(cur_values[1],",");
if(rightvalues.size() != 2){
printf("ConfigParser::parseSingleLine(line %d): %d instead of 2 key=values pairs in line\n",__LINE__,rightvalues.size());
return;
}
char * ptr;
long firstValue = strtol(rightvalues[0].c_str(),&ptr,16);
long secondValue = strtol(rightvalues[1].c_str(),&ptr,16);
config_controller[hid_slot][keyslot][0] = firstValue;
config_controller[hid_slot][keyslot][1] = secondValue;
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Set %02X,%02X\n",__LINE__,firstValue,secondValue); }
}else{
if(HID_DEBUG){ printf("ConfigParser::parseSingleLine(line %d): Found preset value!!\n",__LINE__); }
}
}else{
printf("ConfigParser::parseSingleLine(line %d): The setting \"%s\" is unknown!\n",__LINE__,cur_values[0].c_str());
}
}
}
}
bool ConfigParser::resetConfig(){
s32 slot = getSlot();
if(slot >= gHIDMaxDevices) return false;
for(s32 j = (CONTRPS_PID+1);j< CONTRPS_MAX_VALUE;j++){
config_controller[slot][j][0] = CONTROLLER_PATCHER_INVALIDVALUE;
config_controller[slot][j][1] = CONTROLLER_PATCHER_INVALIDVALUE;
}
return true;
}
s32 ConfigParser::getSlotController(std::string identify){
if(HID_DEBUG){ printf("ConfigParser::getSlotController(line %d): Getting Controller Slot\n",__LINE__); }
std::vector<std::string> values = CPStringTools::StringSplit(identify,",");
if(values.size() != 2){
printf("ConfigParser::getSlotController(line %d): You need to provide a VID and PID. e.g. \"[vid=0x451,pid=0x152]\". (%s)\n",__LINE__,identify.c_str());
return HID_INVALID_SLOT;
}
s32 vid = getValueFromKeyValue(values[0],"VID","=");
if(vid < 0){
return HID_INVALID_SLOT;
}
s32 pid = getValueFromKeyValue(values[1],"PID","=");
if(pid < 0){
return HID_INVALID_SLOT;
}
printf("ConfigParser::getSlotController(line %d): VID: %04x PID: %04x\n",__LINE__,vid,pid);
this->vid = vid;
this->pid = pid;
DeviceInfo deviceinfo;
memset(&deviceinfo,0,sizeof(deviceinfo));
deviceinfo.vidpid.vid = vid;
deviceinfo.vidpid.pid = pid;
s32 result = ControllerPatcherUtils::getDeviceInfoFromVidPid(&deviceinfo);
s32 slot = deviceinfo.slotdata.deviceslot;
s32 hid = 0;
if(result < 0){
if(HID_DEBUG){ printf("ConfigParser::getSlotController(line %d): Its a new controller, lets save it\n",__LINE__); }
HIDSlotData slotdata;
ControllerPatcherUtils::getNextSlotData(&slotdata);
slot = slotdata.deviceslot;
hid = slotdata.hidmask;
if(slot >= gHIDMaxDevices){
printf("ConfigParser::getSlotController(line %d): ConfigParser::getSlotController: We don't a space for a new controller, please delete .inis\n",__LINE__);
return HID_INVALID_SLOT;
}
if(HID_DEBUG){ printf("ConfigParser::getSlotController(line %d): Got new slot! slot: %d hid %s .. Lets registrate it!\n",__LINE__,slot,CPStringTools::byte_to_binary(hid)); }
config_controller[slot][CONTRPS_VID][0] = (vid & 0xFF00) >> 8;
config_controller[slot][CONTRPS_VID][1] = (vid & 0x00FF);
config_controller[slot][CONTRPS_PID][0] = (pid & 0xFF00) >> 8;
config_controller[slot][CONTRPS_PID][1] = (pid & 0x00FF);
if(HID_DEBUG){
printf("ConfigParser::getSlotController(line %d): Saved vid: %04X pid: %04X\n",__LINE__,
config_controller[slot][CONTRPS_VID][0] * 0x100 + config_controller[slot][CONTRPS_VID][1],
config_controller[slot][CONTRPS_PID][0] * 0x100 + config_controller[slot][CONTRPS_PID][1]); }
config_controller_hidmask[slot] = hid;
if(HID_DEBUG){ printf("ConfigParser::getSlotController(line %d): Saved the hid\n",__LINE__); }
}else{
if(slot < gHIDMaxDevices){
hid = config_controller_hidmask[slot];
if(HID_DEBUG){ printf("ConfigParser::getSlotController(line %d): >>>>>> found slot %d (hid:%s). Modifing existing data <<<<<<<<\n",__LINE__,slot,CPStringTools::byte_to_binary(hid)); }
printf("ConfigParser::getSlotController(line %d): We already have data of this controller, lets modify it\n",__LINE__);
}else{
printf("ConfigParser::getSlotController(line %d): Something really odd happend to the slots. %d is bigger then max (%d)\n",__LINE__,slot,gHIDMaxDevices);
return HID_INVALID_SLOT;
}
}
printf("ConfigParser::getSlotController(line %d): using slot: %d hid %08X\n",__LINE__,slot,hid);
return slot;
}
bool ConfigParser::parseIni(){
if(getSlot() == HID_INVALID_SLOT){
printf("ConfigParser::parseIni(line %d): Couldn't parse file. Not a valid slot. Probably broken config. Or you tried to have more than %d devices\n",__LINE__,getType(),gHIDMaxDevices);
}
if(HID_DEBUG){ printf("ConfigParser::parseIni(line %d): Parsing content, type %d\n",__LINE__,getType()); }
s32 start = 1;
if(contentLines[1].compare("[IGNOREDEFAULT]") == 0){
resetConfig();
printf("ConfigParser::parseIni(line %d): Ignoring existing settings of this device\n",__LINE__);
start++;
}
for(u32 i = start; i < contentLines.size(); i++){
if(HID_DEBUG){ printf("ConfigParser::parseIni(line %d): line %d: \"%s\" \n",__LINE__,(i+1),contentLines[i].c_str()); }
parseSingleLine(contentLines[i]);
}
if(HID_DEBUG){ printf("ConfigParser::parseIni(line %d): Parsing of the file is done.\n",__LINE__); }
return true;
}
s32 ConfigParser::getValueFromKeyValue(std::string value_pair,std::string expectedKey,std::string delimiter){
std::vector<std::string> string_value = CPStringTools::StringSplit(value_pair,delimiter);
if(string_value.size() != 2){
if(HID_DEBUG || string_value.size() > 2){ printf("ConfigParser::getValueFromKeyValue(line %d): Not a valid key=pair line %s\n",__LINE__,value_pair.c_str()); }
return -1;
}
if(string_value[0].compare(expectedKey) != 0){
printf("ConfigParser::getValueFromKeyValue(line %d): Key part not %s, its %s",__LINE__,expectedKey.c_str(),string_value[0].c_str());
return -1;
}
char * ptr;
s32 value = strtol(string_value[1].c_str(),&ptr,16);
return value;
}

View File

@ -0,0 +1,74 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _ConfigParser_H_
#define _ConfigParser_H_
#include <string>
#include <vector>
#include <map>
#include <stdio.h>
#include "../ControllerPatcher.hpp"
enum PARSE_TYPE{
PARSE_CONTROLLER,
PARSE_GAMEPAD,
PARSE_MOUSE,
PARSE_KEYBOARD
};
class ConfigParser{
friend class ConfigReader;
friend class ControllerPatcher;
private:
//!Constructor
ConfigParser(std::string configData);
//!Destructor
~ConfigParser();
PARSE_TYPE getType();
void setType(PARSE_TYPE newType);
u16 getSlot();
void setSlot(u16 newSlot);
bool parseIni();
bool Init();
bool parseConfigString(std::string content);
s32 getSlotController(std::string identify);
s32 checkExistingController(s32 vid, s32 pid);
s32 getValueFromKeyValue(std::string value_pair,std::string expectedKey,std::string delimiter);
bool resetConfig();
void parseSingleLine(std::string line);
u16 slot_b;
PARSE_TYPE type_b;
u16 vid;
u16 pid;
std::string content;
std::vector<std::string> contentLines;
};
#endif

View File

@ -0,0 +1,121 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "./ConfigValues.hpp"
#include <stdio.h>
#include <stdlib.h>
#include <string.h>
ConfigValues *ConfigValues::instance = NULL;
ConfigValues::ConfigValues(){
InitValues();
}
ConfigValues::~ConfigValues(){
if(HID_DEBUG){ printf("ConfigValues::~ConfigValues(line %d){\n",__LINE__);}
}
const u8 * ConfigValues::getValuesForPreset(std::map<std::string,const u8*> values,std::string possibleValue){
std::map<std::string,const u8*>::iterator it;
it = values.find(possibleValue);
if (it != values.end()){
return it->second;
}
return NULL;
}
bool ConfigValues::setIfValueIsAControllerPresetEx(std::string value,s32 slot,s32 keyslot){
if(setIfValueIsPreset(presetGCValues,value,slot,keyslot)) return true;
if(setIfValueIsPreset(presetDS3Values,value,slot,keyslot)) return true;
if(setIfValueIsPreset(presetDS4Values,value,slot,keyslot)) return true;
if(setIfValueIsPreset(presetXInputValues,value,slot,keyslot)) return true;
if(setIfValueIsPreset(presetSwitchProValues,value,slot,keyslot)) return true;
return false;
}
//We need this function here so we can use preset sticks.
bool ConfigValues::setIfValueIsPreset(std::map<std::string,const u8*> values,std::string possibleValue,s32 slot,s32 keyslot){
if(slot > gHIDMaxDevices || slot < 0 || keyslot < 0 || keyslot >= CONTRPS_MAX_VALUE){
return false;
}
const u8 * values_ = NULL;
if( keyslot == CONTRPS_VPAD_BUTTON_L_STICK_X ||
keyslot == CONTRPS_VPAD_BUTTON_L_STICK_Y ||
keyslot == CONTRPS_VPAD_BUTTON_R_STICK_X ||
keyslot == CONTRPS_VPAD_BUTTON_R_STICK_Y){
if(HID_DEBUG){ printf("ConfigValues::setIfValueIsPreset(line %d): This may be a predefined stick %s\n",__LINE__,possibleValue.c_str());}
if((values_ = ConfigValues::getValuesStickPreset(possibleValue)) != NULL){
if(HID_DEBUG){ printf("ConfigValues::setIfValueIsPreset(line %d): Found predefined stick!\n",__LINE__);}
config_controller[slot][keyslot][0] = values_[STICK_CONF_BYTE]; //CONTRPS_VPAD_BUTTON_L_STICK_X
config_controller[slot][keyslot][1] = values_[STICK_CONF_DEFAULT];
config_controller[slot][keyslot+DEF_STICK_OFFSET_INVERT][0] = CONTROLLER_PATCHER_VALUE_SET; //CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT
config_controller[slot][keyslot+DEF_STICK_OFFSET_INVERT][1] = values_[STICK_CONF_INVERT];
config_controller[slot][keyslot+DEF_STICK_OFFSET_DEADZONE][0] = CONTROLLER_PATCHER_VALUE_SET; //CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE
config_controller[slot][keyslot+DEF_STICK_OFFSET_DEADZONE][1] = values_[STICK_CONF_DEADZONE];
config_controller[slot][keyslot+DEF_STICK_OFFSET_MINMAX][0] = values_[STICK_CONF_MIN]; //CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX
config_controller[slot][keyslot+DEF_STICK_OFFSET_MINMAX][1] = values_[STICK_CONF_MAX];
return true;
}
}
if((values_ = getValuesForPreset(values,possibleValue)) != NULL){
config_controller[slot][keyslot][0] = values_[0];
config_controller[slot][keyslot][1] = values_[1];
return true;
}
return false;
}
s32 ConfigValues::getValueFromMap(std::map<std::string,int> values,std::string nameOfString){
std::map<std::string,int>::iterator it;
it = values.find(nameOfString);
if (it != values.end()){
return it->second;
}
//Value not found
return -1;
}
s32 ConfigValues::getPresetValueEx(std::string possibleString){
s32 rightValue = -1;
if((rightValue = getValueFromMap(gGamePadValuesToCONTRPSString,possibleString))!= -1){
if(HID_DEBUG){ printf("ConfigValues::getPresetValueEx(line %d): Used pre-defined VPAD_VALUE! \"%s\" is %d\n",__LINE__,possibleString.c_str(),rightValue); }
}else if((rightValue = getValueFromMap(presetValues,possibleString))!= -1){
if(HID_DEBUG){ printf("ConfigValues::getPresetValueEx(line %d): Used pre-defined value! \"%s\" is %d\n",__LINE__,possibleString.c_str(),rightValue); }
}
return rightValue;
}
void ConfigValues::addDeviceNameEx(u16 vid,u16 pid,std::string value){
deviceNames[CPStringTools::strfmt("%04X%04X",vid,pid).c_str()] = value;
}
std::string ConfigValues::getStringByVIDPIDEx(u16 vid,u16 pid){
std::string result = "";
std::map<std::string,std::string>::iterator it;
it = deviceNames.find(CPStringTools::strfmt("%04X%04X",vid,pid));
if (it != deviceNames.end()){
result = it->second;
}else{
result = CPStringTools::strfmt("VID: 0x%04X\nPID: 0x%04X",vid,pid);
}
return result;
}

View File

@ -0,0 +1,569 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _ConfigValues_H_
#define _ConfigValues_H_
#include <string>
#include <vector>
#include <map>
#include "../ControllerPatcher.hpp"
class ConfigValues
{
friend class ConfigParser;
friend class ControllerPatcher;
private:
static ConfigValues *getInstance() {
if(instance == NULL){
printf("ConfigValues: We need a new instance!!!\n");
instance = new ConfigValues();
}
return instance;
}
static void destroyInstance() {
if(instance){
delete instance;
instance = NULL;
}
}
/**
Returns NULL if not a preset!
**/
static const u8 * getValuesStickPreset(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return NULL;
return cur_instance->getValuesForPreset(cur_instance->presetSticks,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getKeySlotGamePad(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getValueFromMap(cur_instance->CONTPRStringToValue,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getKeySlotMouse(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getValueFromMap(cur_instance->mouseLeftValues,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getKeySlotDefaultSingleValue(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getValueFromMap(cur_instance->CONTPRStringToValueSingle,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getKeySlotDefaultPairedValue(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getValueFromMap(cur_instance->CONTPRStringToValue,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getPresetValuesKeyboard(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getValueFromMap(cur_instance->presetKeyboardValues,possibleValue);
}
/**
Returns -1 if not found
**/
static s32 getPresetValue(std::string possibleValue)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->getPresetValueEx(possibleValue);
}
/**
Returns -1 if not found
**/
static s32 setIfValueIsAControllerPreset(std::string value,s32 slot,s32 keyslot)
{
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return -1;
return cur_instance->setIfValueIsAControllerPresetEx(value,slot,keyslot);
}
static void addDeviceName(u16 vid,u16 pid,std::string value){
ConfigValues * cur_instance = getInstance();
if(cur_instance != NULL){
cur_instance->addDeviceNameEx(vid,pid,value);
}
}
/**
Returns empty String if not found
**/
static std::string getStringByVIDPID(u16 vid,u16 pid){
ConfigValues * cur_instance = getInstance();
if(cur_instance == NULL) return "";
return cur_instance->getStringByVIDPIDEx(vid,pid);
}
//!Constructor
ConfigValues();
//!Destructor
~ConfigValues();
static ConfigValues *instance;
std::map<std::string,int> mouseLeftValues;
std::map<std::string,int> CONTPRStringToValue;
std::map<std::string,int> CONTPRStringToValueSingle;
std::map<std::string,int> presetValues;
std::map<std::string,int> gGamePadValuesToCONTRPSString;
std::map<std::string,int> presetKeyboardValues;
std::map<std::string,std::string> deviceNames;
std::map<std::string,const u8*> presetGCValues;
std::map<std::string,const u8*> presetDS3Values;
std::map<std::string,const u8*> presetDS4Values;
std::map<std::string,const u8*> presetXInputValues;
std::map<std::string,const u8*> presetSwitchProValues;
std::map<std::string,const u8*> presetSticks;
s32 getValueFromMap(std::map<std::string,int> values,std::string nameOfString);
bool checkIfValueIsAControllerPreset(std::string value,s32 slot,s32 keyslot);
s32 getPresetValueEx(std::string possibleString);
void InitValues(){
printf("ConfigValues::InitValues: Init values for the configuration\n");
CONTPRStringToValue["VPAD_BUTTON_A"] = CONTRPS_VPAD_BUTTON_A;
CONTPRStringToValue["VPAD_BUTTON_B"] = CONTRPS_VPAD_BUTTON_B;
CONTPRStringToValue["VPAD_BUTTON_X"] = CONTRPS_VPAD_BUTTON_X;
CONTPRStringToValue["VPAD_BUTTON_Y"] = CONTRPS_VPAD_BUTTON_Y;
/* Normal DPAD */
CONTPRStringToValue["VPAD_BUTTON_LEFT"] = CONTRPS_VPAD_BUTTON_LEFT;
CONTPRStringToValue["VPAD_BUTTON_RIGHT"] = CONTRPS_VPAD_BUTTON_RIGHT;
CONTPRStringToValue["VPAD_BUTTON_UP"] = CONTRPS_VPAD_BUTTON_UP;
CONTPRStringToValue["VPAD_BUTTON_DOWN"] = CONTRPS_VPAD_BUTTON_DOWN;
/* DPAD hat mode */
CONTPRStringToValue["VPAD_BUTTON_DPAD_N"] = CONTRPS_VPAD_BUTTON_DPAD_N;
CONTPRStringToValue["VPAD_BUTTON_DPAD_NE"] = CONTRPS_VPAD_BUTTON_DPAD_NE;
CONTPRStringToValue["VPAD_BUTTON_DPAD_E"] = CONTRPS_VPAD_BUTTON_DPAD_E;
CONTPRStringToValue["VPAD_BUTTON_DPAD_SE"] = CONTRPS_VPAD_BUTTON_DPAD_SE;
CONTPRStringToValue["VPAD_BUTTON_DPAD_S"] = CONTRPS_VPAD_BUTTON_DPAD_S;
CONTPRStringToValue["VPAD_BUTTON_DPAD_SW"] = CONTRPS_VPAD_BUTTON_DPAD_SW;
CONTPRStringToValue["VPAD_BUTTON_DPAD_W"] = CONTRPS_VPAD_BUTTON_DPAD_W;
CONTPRStringToValue["VPAD_BUTTON_DPAD_NW"] = CONTRPS_VPAD_BUTTON_DPAD_NW;
CONTPRStringToValue["VPAD_BUTTON_DPAD_NEUTRAL"] = CONTRPS_VPAD_BUTTON_DPAD_NEUTRAL;
/* DPAD Absolute mode */
CONTPRStringToValue["VPAD_BUTTON_DPAD_ABS_UP"] = CONTRPS_VPAD_BUTTON_DPAD_ABS_UP;
CONTPRStringToValue["VPAD_BUTTON_DPAD_ABS_DOWN"] = CONTRPS_VPAD_BUTTON_DPAD_ABS_DOWN;
CONTPRStringToValue["VPAD_BUTTON_DPAD_ABS_LEFT"] = CONTRPS_VPAD_BUTTON_DPAD_ABS_LEFT;
CONTPRStringToValue["VPAD_BUTTON_DPAD_ABS_RIGHT"] = CONTRPS_VPAD_BUTTON_DPAD_ABS_RIGHT;
/* */
CONTPRStringToValue["VPAD_BUTTON_ZL"] = CONTRPS_VPAD_BUTTON_ZL;
CONTPRStringToValue["VPAD_BUTTON_ZR"] = CONTRPS_VPAD_BUTTON_ZR;
CONTPRStringToValue["VPAD_BUTTON_L"] = CONTRPS_VPAD_BUTTON_L;
CONTPRStringToValue["VPAD_BUTTON_R"] = CONTRPS_VPAD_BUTTON_R;
CONTPRStringToValue["VPAD_BUTTON_PLUS"] = CONTRPS_VPAD_BUTTON_PLUS;
CONTPRStringToValue["VPAD_BUTTON_MINUS"] = CONTRPS_VPAD_BUTTON_MINUS;
CONTPRStringToValue["VPAD_BUTTON_HOME"] = CONTRPS_VPAD_BUTTON_HOME;
CONTPRStringToValue["VPAD_BUTTON_SYNC"] = CONTRPS_VPAD_BUTTON_SYNC;
CONTPRStringToValue["VPAD_BUTTON_STICK_R"] = CONTRPS_VPAD_BUTTON_STICK_R;
CONTPRStringToValue["VPAD_BUTTON_STICK_L"] = CONTRPS_VPAD_BUTTON_STICK_L;
CONTPRStringToValue["VPAD_STICK_R_EMULATION_LEFT"] = CONTRPS_VPAD_STICK_R_EMULATION_LEFT;
CONTPRStringToValue["VPAD_STICK_R_EMULATION_RIGHT"] = CONTRPS_VPAD_STICK_R_EMULATION_RIGHT;
CONTPRStringToValue["VPAD_STICK_R_EMULATION_UP"] = CONTRPS_VPAD_STICK_R_EMULATION_UP;
CONTPRStringToValue["VPAD_STICK_R_EMULATION_DOWN"] = CONTRPS_VPAD_STICK_R_EMULATION_DOWN;
CONTPRStringToValue["VPAD_STICK_L_EMULATION_LEFT"] = CONTRPS_VPAD_STICK_L_EMULATION_LEFT;
CONTPRStringToValue["VPAD_STICK_L_EMULATION_RIGHT"] = CONTRPS_VPAD_STICK_L_EMULATION_RIGHT;
CONTPRStringToValue["VPAD_STICK_L_EMULATION_UP"] = CONTRPS_VPAD_STICK_L_EMULATION_UP;
CONTPRStringToValue["VPAD_STICK_L_EMULATION_DOWN"] = CONTRPS_VPAD_STICK_L_EMULATION_DOWN;
CONTPRStringToValue["VPAD_L_STICK_UP"] = CONTRPS_VPAD_BUTTON_L_STICK_UP;
CONTPRStringToValue["VPAD_L_STICK_DOWN"] = CONTRPS_VPAD_BUTTON_L_STICK_DOWN;
CONTPRStringToValue["VPAD_L_STICK_LEFT"] = CONTRPS_VPAD_BUTTON_L_STICK_LEFT;
CONTPRStringToValue["VPAD_L_STICK_RIGHT"] = CONTRPS_VPAD_BUTTON_L_STICK_RIGHT;
CONTPRStringToValue["VPAD_R_STICK_UP"] = CONTRPS_VPAD_BUTTON_R_STICK_UP;
CONTPRStringToValue["VPAD_R_STICK_DOWN"] = CONTRPS_VPAD_BUTTON_R_STICK_DOWN;
CONTPRStringToValue["VPAD_R_STICK_LEFT"] = CONTRPS_VPAD_BUTTON_R_STICK_LEFT;
CONTPRStringToValue["VPAD_R_STICK_RIGHT"] = CONTRPS_VPAD_BUTTON_R_STICK_RIGHT;
CONTPRStringToValue["VPAD_L_STICK_X"] = CONTRPS_VPAD_BUTTON_L_STICK_X;
CONTPRStringToValue["VPAD_L_STICK_X_MINMAX"] = CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX;
CONTPRStringToValue["VPAD_L_STICK_Y"] = CONTRPS_VPAD_BUTTON_L_STICK_Y;
CONTPRStringToValue["VPAD_L_STICK_Y_MINMAX"] = CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX;
CONTPRStringToValue["VPAD_R_STICK_X"] = CONTRPS_VPAD_BUTTON_R_STICK_X;
CONTPRStringToValue["VPAD_R_STICK_X_MINMAX"] = CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX;
CONTPRStringToValue["VPAD_R_STICK_Y"] = CONTRPS_VPAD_BUTTON_R_STICK_Y;
CONTPRStringToValue["VPAD_R_STICK_Y_MINMAX"] = CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX;
CONTPRStringToValue["VPAD_BUTTON_TV"] = CONTRPS_VPAD_BUTTON_TV;
CONTPRStringToValue["DOUBLE_USE_BUTTON_ACTIVATOR"] = CONTRPS_DOUBLE_USE_BUTTON_ACTIVATOR,
CONTPRStringToValue["INPUT_FILTER"] = CONTRPS_INPUT_FILTER;
CONTPRStringToValue["PAD1_FILTER"] = CONTRPS_PAD1_FILTER;
CONTPRStringToValue["PAD2_FILTER"] = CONTRPS_PAD2_FILTER;
CONTPRStringToValue["PAD3_FILTER"] = CONTRPS_PAD3_FILTER;
CONTPRStringToValue["PAD4_FILTER"] = CONTRPS_PAD4_FILTER;
CONTPRStringToValue["PAD5_FILTER"] = CONTRPS_PAD5_FILTER;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_1_PRESSED"] = CONTRPS_DOUBLE_USE_BUTTON_1_PRESSED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_2_PRESSED"] = CONTRPS_DOUBLE_USE_BUTTON_2_PRESSED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_3_PRESSED"] = CONTRPS_DOUBLE_USE_BUTTON_3_PRESSED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_4_PRESSED"] = CONTRPS_DOUBLE_USE_BUTTON_4_PRESSED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_5_PRESSED"] = CONTRPS_DOUBLE_USE_BUTTON_5_PRESSED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_1_RELEASED"] = CONTRPS_DOUBLE_USE_BUTTON_1_RELEASED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_2_RELEASED"] = CONTRPS_DOUBLE_USE_BUTTON_2_RELEASED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_3_RELEASED"] = CONTRPS_DOUBLE_USE_BUTTON_3_RELEASED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_4_RELEASED"] = CONTRPS_DOUBLE_USE_BUTTON_4_RELEASED;
CONTPRStringToValueSingle["DOUBLE_USE_BUTTON_5_RELEASED"] = CONTRPS_DOUBLE_USE_BUTTON_5_RELEASED;
CONTPRStringToValueSingle["BUF_SIZE"] = CONTRPS_BUF_SIZE;
CONTPRStringToValueSingle["DPAD_MODE"] = CONTRPS_DPAD_MODE;
CONTPRStringToValueSingle["DPAD_MASK"] = CONTRPS_DPAD_MASK;
CONTPRStringToValueSingle["VPAD_L_STICK_X_DEADZONE"] = CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE;
CONTPRStringToValueSingle["VPAD_L_STICK_Y_DEADZONE"] = CONTRPS_VPAD_BUTTON_L_STICK_Y_DEADZONE;
CONTPRStringToValueSingle["VPAD_R_STICK_X_DEADZONE"] = CONTRPS_VPAD_BUTTON_R_STICK_X_DEADZONE;
CONTPRStringToValueSingle["VPAD_R_STICK_Y_DEADZONE"] = CONTRPS_VPAD_BUTTON_R_STICK_Y_DEADZONE;
CONTPRStringToValueSingle["VPAD_L_STICK_X_INVERT"] = CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT;
CONTPRStringToValueSingle["VPAD_L_STICK_Y_INVERT"] = CONTRPS_VPAD_BUTTON_L_STICK_Y_INVERT;
CONTPRStringToValueSingle["VPAD_R_STICK_X_INVERT"] = CONTRPS_VPAD_BUTTON_R_STICK_X_INVERT;
CONTPRStringToValueSingle["VPAD_R_STICK_Y_INVERT"] = CONTRPS_VPAD_BUTTON_R_STICK_Y_INVERT;
CONTPRStringToValueSingle["DOUBLE_USE"] = CONTRPS_DOUBLE_USE;
CONTPRStringToValueSingle["PAD_COUNT"] = CONTRPS_PAD_COUNT;
mouseLeftValues["LEFT_CLICK"] = CONTRPS_VPAD_BUTTON_LEFT;
mouseLeftValues["RIGHT_CLICK"] = CONTRPS_VPAD_BUTTON_RIGHT;
mouseLeftValues["EMULATED_STICK"] = CONTRPS_MOUSE_STICK;
presetGCValues["GC_BUTTON_A"] = HID_GC_BUTTON_A;
presetGCValues["GC_BUTTON_B"] = HID_GC_BUTTON_B;
presetGCValues["GC_BUTTON_X"] = HID_GC_BUTTON_X;
presetGCValues["GC_BUTTON_Y"] = HID_GC_BUTTON_Y;
presetGCValues["GC_BUTTON_LEFT"] = HID_GC_BUTTON_LEFT;
presetGCValues["GC_BUTTON_RIGHT"] = HID_GC_BUTTON_RIGHT;
presetGCValues["GC_BUTTON_DOWN"] = HID_GC_BUTTON_DOWN;
presetGCValues["GC_BUTTON_UP"] = HID_GC_BUTTON_UP;
presetGCValues["GC_BUTTON_START"] = HID_GC_BUTTON_START;
presetGCValues["GC_BUTTON_Z"] = HID_GC_BUTTON_Z;
presetGCValues["GC_BUTTON_L"] = HID_GC_BUTTON_L;
presetGCValues["GC_BUTTON_R"] = HID_GC_BUTTON_R;
presetDS3Values["DS3_BUTTON_CROSS"] = HID_DS3_BUTTON_CROSS;
presetDS3Values["DS3_BUTTON_CIRCLE"] = HID_DS3_BUTTON_CIRCLE;
presetDS3Values["DS3_BUTTON_SQUARE"] = HID_DS3_BUTTON_SQUARE;
presetDS3Values["DS3_BUTTON_TRIANGLE"] = HID_DS3_BUTTON_TRIANGLE;
presetDS3Values["DS3_BUTTON_L1"] = HID_DS3_BUTTON_L1;
presetDS3Values["DS3_BUTTON_L2"] = HID_DS3_BUTTON_L2;
presetDS3Values["DS3_BUTTON_L3"] = HID_DS3_BUTTON_L3;
presetDS3Values["DS3_BUTTON_R1"] = HID_DS3_BUTTON_R1;
presetDS3Values["DS3_BUTTON_R2"] = HID_DS3_BUTTON_R2;
presetDS3Values["DS3_BUTTON_R3"] = HID_DS3_BUTTON_R3;
presetDS3Values["DS3_BUTTON_SELECT"] = HID_DS3_BUTTON_SELECT;
presetDS3Values["DS3_BUTTON_START"] = HID_DS3_BUTTON_START;
presetDS3Values["DS3_BUTTON_LEFT"] = HID_DS3_BUTTON_LEFT;
presetDS3Values["DS3_BUTTON_RIGHT"] = HID_DS3_BUTTON_RIGHT;
presetDS3Values["DS3_BUTTON_UP"] = HID_DS3_BUTTON_UP;
presetDS3Values["DS3_BUTTON_DOWN"] = HID_DS3_BUTTON_DOWN;
presetDS3Values["DS3_BUTTON_GUIDE"] = HID_DS3_BUTTON_GUIDE;
presetDS4Values["DS4_BUTTON_CROSS"] = HID_DS4_BUTTON_CROSS;
presetDS4Values["DS4_BUTTON_CIRCLE"] = HID_DS4_BUTTON_CIRCLE;
presetDS4Values["DS4_BUTTON_SQUARE"] = HID_DS4_BUTTON_SQUARE;
presetDS4Values["DS4_BUTTON_TRIANGLE"] = HID_DS4_BUTTON_TRIANGLE;
presetDS4Values["DS4_BUTTON_L1"] = HID_DS4_BUTTON_L1;
presetDS4Values["DS4_BUTTON_L2"] = HID_DS4_BUTTON_L2;
presetDS4Values["DS4_BUTTON_L3"] = HID_DS4_BUTTON_L3;
presetDS4Values["DS4_BUTTON_R1"] = HID_DS4_BUTTON_R1;
presetDS4Values["DS4_BUTTON_R2"] = HID_DS4_BUTTON_R2;
presetDS4Values["DS4_BUTTON_R3"] = HID_DS4_BUTTON_R3;
presetDS4Values["DS4_BUTTON_SHARE"] = HID_DS4_BUTTON_SHARE;
presetDS4Values["DS4_BUTTON_OPTIONS"] = HID_DS4_BUTTON_OPTIONS;
presetDS4Values["DS4_BUTTON_DPAD_TYPE"] = HID_DS4_BUTTON_DPAD_TYPE;
presetDS4Values["DS4_BUTTON_DPAD_N"] = HID_DS4_BUTTON_DPAD_N;
presetDS4Values["DS4_BUTTON_DPAD_NE"] = HID_DS4_BUTTON_DPAD_NE;
presetDS4Values["DS4_BUTTON_DPAD_E"] = HID_DS4_BUTTON_DPAD_E;
presetDS4Values["DS4_BUTTON_DPAD_SE"] = HID_DS4_BUTTON_DPAD_SE;
presetDS4Values["DS4_BUTTON_DPAD_S"] = HID_DS4_BUTTON_DPAD_S;
presetDS4Values["DS4_BUTTON_DPAD_SW"] = HID_DS4_BUTTON_DPAD_SW;
presetDS4Values["DS4_BUTTON_DPAD_W"] = HID_DS4_BUTTON_DPAD_W;
presetDS4Values["DS4_BUTTON_DPAD_NW"] = HID_DS4_BUTTON_DPAD_NW;
presetDS4Values["DS4_BUTTON_DPAD_NEUTRAL"] = HID_DS4_BUTTON_DPAD_NEUTRAL;
presetDS4Values["DS4_BUTTON_GUIDE"] = HID_DS4_BUTTON_GUIDE;
presetDS4Values["DS4_BUTTON_T_PAD_CLICK"] = HID_DS4_BUTTON_T_PAD_CLICK;
presetXInputValues["XINPUT_BUTTON_A"] = HID_XINPUT_BUTTON_A;
presetXInputValues["XINPUT_BUTTON_B"] = HID_XINPUT_BUTTON_B;
presetXInputValues["XINPUT_BUTTON_X"] = HID_XINPUT_BUTTON_X;
presetXInputValues["XINPUT_BUTTON_Y"] = HID_XINPUT_BUTTON_Y;
presetXInputValues["XINPUT_BUTTON_LB"] = HID_XINPUT_BUTTON_LB;
presetXInputValues["XINPUT_BUTTON_LT"] = HID_XINPUT_BUTTON_LT;
presetXInputValues["XINPUT_BUTTON_L3"] = HID_XINPUT_BUTTON_L3;
presetXInputValues["XINPUT_BUTTON_RB"] = HID_XINPUT_BUTTON_RB;
presetXInputValues["XINPUT_BUTTON_RT"] = HID_XINPUT_BUTTON_RT;
presetXInputValues["XINPUT_BUTTON_R3"] = HID_XINPUT_BUTTON_R3;
presetXInputValues["XINPUT_BUTTON_START"] = HID_XINPUT_BUTTON_START;
presetXInputValues["XINPUT_BUTTON_BACK"] = HID_XINPUT_BUTTON_BACK;
presetXInputValues["XINPUT_BUTTON_DPAD_TYPE"] = HID_XINPUT_BUTTON_DPAD_TYPE;
presetXInputValues["XINPUT_BUTTON_DPAD_UP"] = HID_XINPUT_BUTTON_UP;
presetXInputValues["XINPUT_BUTTON_DPAD_DOWN"] = HID_XINPUT_BUTTON_DOWN;
presetXInputValues["XINPUT_BUTTON_DPAD_LEFT"] = HID_XINPUT_BUTTON_LEFT;
presetXInputValues["XINPUT_BUTTON_DPAD_RIGHT"] = HID_XINPUT_BUTTON_RIGHT;
presetXInputValues["XINPUT_BUTTON_GUIDE"] = HID_XINPUT_BUTTON_GUIDE;
presetSwitchProValues["SWITCH_PRO_BUTTON_A"] = HID_SWITCH_PRO_BT_BUTTON_A;
presetSwitchProValues["SWITCH_PRO_BUTTON_B"] = HID_SWITCH_PRO_BT_BUTTON_B;
presetSwitchProValues["SWITCH_PRO_BUTTON_X"] = HID_SWITCH_PRO_BT_BUTTON_X;
presetSwitchProValues["SWITCH_PRO_BUTTON_Y"] = HID_SWITCH_PRO_BT_BUTTON_Y;
presetSwitchProValues["SWITCH_PRO_BUTTON_PLUS"] = HID_SWITCH_PRO_BT_BUTTON_PLUS;
presetSwitchProValues["SWITCH_PRO_BUTTON_MINUS"] = HID_SWITCH_PRO_BT_BUTTON_MINUS;
presetSwitchProValues["SWITCH_PRO_BUTTON_HOME"] = HID_SWITCH_PRO_BT_BUTTON_HOME;
presetSwitchProValues["SWITCH_PRO_BUTTON_L"] = HID_SWITCH_PRO_BT_BUTTON_L;
presetSwitchProValues["SWITCH_PRO_BUTTON_R"] = HID_SWITCH_PRO_BT_BUTTON_R;
presetSwitchProValues["SWITCH_PRO_BUTTON_ZL"] = HID_SWITCH_PRO_BT_BUTTON_ZL;
presetSwitchProValues["SWITCH_PRO_BUTTON_ZR"] = HID_SWITCH_PRO_BT_BUTTON_ZR;
presetSwitchProValues["SWITCH_PRO_BUTTON_STICK_L"] = HID_SWITCH_PRO_BT_BUTTON_STICK_L;
presetSwitchProValues["SWITCH_PRO_BUTTON_STICK_R"] = HID_SWITCH_PRO_BT_BUTTON_STICK_R;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_N"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_N;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_NE"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_NE;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_E"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_E;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_SE"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_SE;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_S"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_S;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_SW"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_SW;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_W"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_W;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_NW"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_NW;
presetSwitchProValues["SWITCH_PRO_BUTTON_DPAD_NEUTRAL"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL;
presetKeyboardValues["KEYBOARD_SHIFT"] = HID_KEYBOARD_BUTTON_SHIFT;
presetKeyboardValues["KEYBOARD_A"] = HID_KEYBOARD_BUTTON_A;
presetKeyboardValues["KEYBOARD_B"] = HID_KEYBOARD_BUTTON_B;
presetKeyboardValues["KEYBOARD_C"] = HID_KEYBOARD_BUTTON_C;
presetKeyboardValues["KEYBOARD_D"] = HID_KEYBOARD_BUTTON_D;
presetKeyboardValues["KEYBOARD_E"] = HID_KEYBOARD_BUTTON_E;
presetKeyboardValues["KEYBOARD_F"] = HID_KEYBOARD_BUTTON_F;
presetKeyboardValues["KEYBOARD_G"] = HID_KEYBOARD_BUTTON_G;
presetKeyboardValues["KEYBOARD_H"] = HID_KEYBOARD_BUTTON_H;
presetKeyboardValues["KEYBOARD_I"] = HID_KEYBOARD_BUTTON_I;
presetKeyboardValues["KEYBOARD_J"] = HID_KEYBOARD_BUTTON_J;
presetKeyboardValues["KEYBOARD_K"] = HID_KEYBOARD_BUTTON_K;
presetKeyboardValues["KEYBOARD_L"] = HID_KEYBOARD_BUTTON_L;
presetKeyboardValues["KEYBOARD_M"] = HID_KEYBOARD_BUTTON_M;
presetKeyboardValues["KEYBOARD_N"] = HID_KEYBOARD_BUTTON_N;
presetKeyboardValues["KEYBOARD_O"] = HID_KEYBOARD_BUTTON_O;
presetKeyboardValues["KEYBOARD_P"] = HID_KEYBOARD_BUTTON_P;
presetKeyboardValues["KEYBOARD_Q"] = HID_KEYBOARD_BUTTON_Q;
presetKeyboardValues["KEYBOARD_R"] = HID_KEYBOARD_BUTTON_R;
presetKeyboardValues["KEYBOARD_S"] = HID_KEYBOARD_BUTTON_S;
presetKeyboardValues["KEYBOARD_T"] = HID_KEYBOARD_BUTTON_T;
presetKeyboardValues["KEYBOARD_U"] = HID_KEYBOARD_BUTTON_U;
presetKeyboardValues["KEYBOARD_V"] = HID_KEYBOARD_BUTTON_V;
presetKeyboardValues["KEYBOARD_W"] = HID_KEYBOARD_BUTTON_W;
presetKeyboardValues["KEYBOARD_X"] = HID_KEYBOARD_BUTTON_X;
presetKeyboardValues["KEYBOARD_Y"] = HID_KEYBOARD_BUTTON_Y;
presetKeyboardValues["KEYBOARD_Z"] = HID_KEYBOARD_BUTTON_Z;
presetKeyboardValues["KEYBOARD_F1"] = HID_KEYBOARD_BUTTON_F1;
presetKeyboardValues["KEYBOARD_F2"] = HID_KEYBOARD_BUTTON_F2;
presetKeyboardValues["KEYBOARD_F3"] = HID_KEYBOARD_BUTTON_F3;
presetKeyboardValues["KEYBOARD_F4"] = HID_KEYBOARD_BUTTON_F4;
presetKeyboardValues["KEYBOARD_F5"] = HID_KEYBOARD_BUTTON_F5;
presetKeyboardValues["KEYBOARD_F6"] = HID_KEYBOARD_BUTTON_F6;
presetKeyboardValues["KEYBOARD_F7"] = HID_KEYBOARD_BUTTON_F7;
presetKeyboardValues["KEYBOARD_F8"] = HID_KEYBOARD_BUTTON_F8;
presetKeyboardValues["KEYBOARD_F9"] = HID_KEYBOARD_BUTTON_F9;
presetKeyboardValues["KEYBOARD_F10"] = HID_KEYBOARD_BUTTON_F10;
presetKeyboardValues["KEYBOARD_F11"] = HID_KEYBOARD_BUTTON_F11;
presetKeyboardValues["KEYBOARD_F12"] = HID_KEYBOARD_BUTTON_F12;
presetKeyboardValues["KEYBOARD_1"] = HID_KEYBOARD_BUTTON_1;
presetKeyboardValues["KEYBOARD_2"] = HID_KEYBOARD_BUTTON_2;
presetKeyboardValues["KEYBOARD_3"] = HID_KEYBOARD_BUTTON_3;
presetKeyboardValues["KEYBOARD_4"] = HID_KEYBOARD_BUTTON_4;
presetKeyboardValues["KEYBOARD_5"] = HID_KEYBOARD_BUTTON_5;
presetKeyboardValues["KEYBOARD_6"] = HID_KEYBOARD_BUTTON_6;
presetKeyboardValues["KEYBOARD_7"] = HID_KEYBOARD_BUTTON_7;
presetKeyboardValues["KEYBOARD_8"] = HID_KEYBOARD_BUTTON_8;
presetKeyboardValues["KEYBOARD_9"] = HID_KEYBOARD_BUTTON_9;
presetKeyboardValues["KEYBOARD_0"] = HID_KEYBOARD_BUTTON_0;
presetKeyboardValues["KEYBOARD_RETURN"] = HID_KEYBOARD_BUTTON_RETURN;
presetKeyboardValues["KEYBOARD_ESCAPE"] = HID_KEYBOARD_BUTTON_ESCAPE;
presetKeyboardValues["KEYBOARD_DELETE"] = HID_KEYBOARD_BUTTON_DELETE;
presetKeyboardValues["KEYBOARD_TAB"] = HID_KEYBOARD_BUTTON_TAB;
presetKeyboardValues["KEYBOARD_SPACEBAR"] = HID_KEYBOARD_BUTTON_SPACEBAR;
presetKeyboardValues["KEYBOARD_CAPSLOCK"] = HID_KEYBOARD_BUTTON_CAPSLOCK;
presetKeyboardValues["KEYBOARD_PRINTSCREEN"] = HID_KEYBOARD_BUTTON_PRINTSCREEN;
presetKeyboardValues["KEYBOARD_SCROLLLOCK"] = HID_KEYBOARD_BUTTON_SCROLLLOCK;
presetKeyboardValues["KEYBOARD_PAUSE"] = HID_KEYBOARD_BUTTON_PAUSE;
presetKeyboardValues["KEYBOARD_INSERT"] = HID_KEYBOARD_BUTTON_INSERT;
presetKeyboardValues["KEYBOARD_HOME"] = HID_KEYBOARD_BUTTON_HOME;
presetKeyboardValues["KEYBOARD_PAGEUP"] = HID_KEYBOARD_BUTTON_PAGEUP;
presetKeyboardValues["KEYBOARD_PAGEDOWN"] = HID_KEYBOARD_BUTTON_PAGEDOWN;
presetKeyboardValues["KEYBOARD_DELETEFORWARD"] = HID_KEYBOARD_BUTTON_DELETEFORWARD;
presetKeyboardValues["KEYBOARD_LEFT_CONTROL"] = HID_KEYBOARD_BUTTON_LEFT_CONTROL;
presetKeyboardValues["KEYBOARD_LEFT_ALT"] = HID_KEYBOARD_BUTTON_LEFT_ALT;
presetKeyboardValues["KEYBOARD_RIGHT_CONTROL"] = HID_KEYBOARD_BUTTON_RIGHT_CONTROL;
presetKeyboardValues["KEYBOARD_RIGHT_SHIFT"] = HID_KEYBOARD_BUTTON_RIGHT_SHIFT;
presetKeyboardValues["KEYBOARD_RIGHT_ALT"] = HID_KEYBOARD_BUTTON_RIGHT_ALT;
presetKeyboardValues["KEYBOARD_END"] = HID_KEYBOARD_BUTTON_END;
presetKeyboardValues["KEYBOARD_LEFT"] = HID_KEYBOARD_BUTTON_LEFT;
presetKeyboardValues["KEYBOARD_RIGHT"] = HID_KEYBOARD_BUTTON_RIGHT;
presetKeyboardValues["KEYBOARD_DOWN"] = HID_KEYBOARD_BUTTON_DOWN;
presetKeyboardValues["KEYBOARD_UP"] = HID_KEYBOARD_BUTTON_UP;
presetKeyboardValues["KEYBOARD_KEYPAD_1"] = HID_KEYBOARD_KEYPAD_BUTTON_1;
presetKeyboardValues["KEYBOARD_KEYPAD_2"] = HID_KEYBOARD_KEYPAD_BUTTON_2;
presetKeyboardValues["KEYBOARD_KEYPAD_3"] = HID_KEYBOARD_KEYPAD_BUTTON_3;
presetKeyboardValues["KEYBOARD_KEYPAD_4"] = HID_KEYBOARD_KEYPAD_BUTTON_4;
presetKeyboardValues["KEYBOARD_KEYPAD_5"] = HID_KEYBOARD_KEYPAD_BUTTON_5;
presetKeyboardValues["KEYBOARD_KEYPAD_6"] = HID_KEYBOARD_KEYPAD_BUTTON_6;
presetKeyboardValues["KEYBOARD_KEYPAD_7"] = HID_KEYBOARD_KEYPAD_BUTTON_7;
presetKeyboardValues["KEYBOARD_KEYPAD_8"] = HID_KEYBOARD_KEYPAD_BUTTON_8;
presetKeyboardValues["KEYBOARD_KEYPAD_9"] = HID_KEYBOARD_KEYPAD_BUTTON_9;
presetKeyboardValues["KEYBOARD_KEYPAD_0"] = HID_KEYBOARD_KEYPAD_BUTTON_0;
presetKeyboardValues["KEYBOARD_KEYPAD_NUMLOCK"] = HID_KEYBOARD_KEYPAD_BUTTON_NUMLOCK;
presetKeyboardValues["KEYBOARD_KEYPAD_MINUS"] = HID_KEYBOARD_KEYPAD_BUTTON_MINUS;
presetKeyboardValues["KEYBOARD_KEYPAD_PLUS"] = HID_KEYBOARD_KEYPAD_BUTTON_PLUS;
presetValues["VPAD_L_STICK"] = DEF_L_STICK;
presetValues["VPAD_R_STICK"] = DEF_R_STICK;
presetValues["DPAD_NORMAL"] = CONTRPDM_Normal;
presetValues["DPAD_HAT"] = CONTRPDM_Hat;
presetValues["DPAD_ABSOLUTE_2VALUES"] = CONTRPDM_Absolute_2Values;
presetValues["TRUE"] = 1;
presetValues["YES"] = 1;
presetValues["ON"] = 1;
presetValues["FALSE"] = 0;
presetValues["NO"] = 0;
presetValues["OFF"] = 0;
presetSticks["GC_STICK_L_X"] = HID_GC_STICK_L_X;
presetSticks["GC_STICK_L_Y"] = HID_GC_STICK_L_Y;
presetSticks["GC_STICK_R_X"] = HID_GC_STICK_R_X;
presetSticks["GC_STICK_R_Y"] = HID_GC_STICK_R_Y;
presetSticks["DS3_STICK_L_X"] = HID_DS3_STICK_L_X;
presetSticks["DS3_STICK_L_Y"] = HID_DS3_STICK_L_Y;
presetSticks["DS3_STICK_R_X"] = HID_DS3_STICK_R_X;
presetSticks["DS3_STICK_R_Y"] = HID_DS3_STICK_R_Y;
presetSticks["DS4_STICK_L_X"] = HID_DS4_STICK_L_X;
presetSticks["DS4_STICK_L_Y"] = HID_DS4_STICK_L_Y;
presetSticks["DS4_STICK_R_X"] = HID_DS4_STICK_R_X;
presetSticks["DS4_STICK_R_Y"] = HID_DS4_STICK_R_Y;
presetSticks["XINPUT_STICK_L_X"] = HID_XINPUT_STICK_L_X;
presetSticks["XINPUT_STICK_L_Y"] = HID_XINPUT_STICK_L_Y;
presetSticks["XINPUT_STICK_R_X"] = HID_XINPUT_STICK_R_X;
presetSticks["XINPUT_STICK_R_Y"] = HID_XINPUT_STICK_R_Y;
presetSticks["SWITCH_PRO_STICK_L_X"] = HID_SWITCH_PRO_BT_STICK_L_X;
presetSticks["SWITCH_PRO_STICK_L_Y"] = HID_SWITCH_PRO_BT_STICK_L_Y;
presetSticks["SWITCH_PRO_STICK_R_X"] = HID_SWITCH_PRO_BT_STICK_R_X;
presetSticks["SWITCH_PRO_STICK_R_Y"] = HID_SWITCH_PRO_BT_STICK_R_Y;
presetSticks["GC_DPAD_MODE"] = HID_GC_BUTTON_DPAD_TYPE;
presetSticks["DS3_DPAD_MODE"] = HID_DS3_BUTTON_DPAD_TYPE;
presetSticks["DS4_DPAD_MODE"] = HID_DS4_BUTTON_DPAD_TYPE;
presetSticks["XINPUT_DPAD_MODE"] = HID_XINPUT_BUTTON_DPAD_TYPE;
presetSticks["SWITCH_PRO_DPAD_MODE"] = HID_SWITCH_PRO_BT_BUTTON_DPAD_TYPE;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_A"] = CONTRPS_VPAD_BUTTON_A;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_B"] = CONTRPS_VPAD_BUTTON_B;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_X"] = CONTRPS_VPAD_BUTTON_X;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_Y"] = CONTRPS_VPAD_BUTTON_Y;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_LEFT"] = CONTRPS_VPAD_BUTTON_LEFT;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_RIGHT"] = CONTRPS_VPAD_BUTTON_RIGHT;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_UP"] = CONTRPS_VPAD_BUTTON_UP;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_DOWN"] = CONTRPS_VPAD_BUTTON_DOWN;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_ZL"] = CONTRPS_VPAD_BUTTON_ZL;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_ZR"] = CONTRPS_VPAD_BUTTON_ZR;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_L"] = CONTRPS_VPAD_BUTTON_L;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_R"] = CONTRPS_VPAD_BUTTON_R;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_PLUS"] = CONTRPS_VPAD_BUTTON_PLUS;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_MINUS"] = CONTRPS_VPAD_BUTTON_MINUS;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_HOME"] = CONTRPS_VPAD_BUTTON_HOME;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_SYNC"] = CONTRPS_VPAD_BUTTON_SYNC;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_STICK_R"] = CONTRPS_VPAD_BUTTON_STICK_R;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_STICK_L"] = CONTRPS_VPAD_BUTTON_STICK_L;
gGamePadValuesToCONTRPSString["VPAD_BUTTON_TV"] = CONTRPS_VPAD_BUTTON_TV;
gGamePadValuesToCONTRPSString["VPAD_STICK_R_EMULATION_LEFT"] = CONTRPS_VPAD_STICK_R_EMULATION_LEFT;
gGamePadValuesToCONTRPSString["VPAD_STICK_R_EMULATION_RIGHT"] = CONTRPS_VPAD_STICK_R_EMULATION_RIGHT;
gGamePadValuesToCONTRPSString["VPAD_STICK_R_EMULATION_UP"] = CONTRPS_VPAD_STICK_R_EMULATION_UP;
gGamePadValuesToCONTRPSString["VPAD_STICK_R_EMULATION_DOWN"] = CONTRPS_VPAD_STICK_R_EMULATION_DOWN;
gGamePadValuesToCONTRPSString["VPAD_STICK_L_EMULATION_LEFT"] = CONTRPS_VPAD_STICK_L_EMULATION_LEFT;
gGamePadValuesToCONTRPSString["VPAD_STICK_L_EMULATION_RIGHT"] = CONTRPS_VPAD_STICK_L_EMULATION_RIGHT;
gGamePadValuesToCONTRPSString["VPAD_STICK_L_EMULATION_UP"] = CONTRPS_VPAD_STICK_L_EMULATION_UP;
gGamePadValuesToCONTRPSString["VPAD_STICK_L_EMULATION_DOWN"] = CONTRPS_VPAD_STICK_L_EMULATION_DOWN;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_GC_VID, HID_GC_PID).c_str()] = HID_GC_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_KEYBOARD_VID, HID_KEYBOARD_PID).c_str()] = HID_KEYBOARD_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_MOUSE_VID, HID_MOUSE_PID).c_str()] = HID_MOUSE_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_DS3_VID, HID_DS3_PID).c_str()] = HID_DS3_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_NEW_DS4_VID, HID_NEW_DS4_PID).c_str()] = HID_NEW_DS4_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_DS4_VID, HID_DS4_PID).c_str()] = HID_DS4_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_XINPUT_VID, HID_XINPUT_PID).c_str()] = HID_XINPUT_STRING;
deviceNames[CPStringTools::strfmt("%04X%04X",HID_SWITCH_PRO_VID,HID_SWITCH_PRO_PID).c_str()] = HID_SWITCH_PRO_STRING;
}
const u8 * getValuesForPreset(std::map<std::string,const u8*> values,std::string possibleValue);
bool setIfValueIsPreset(std::map<std::string,const u8*> values,std::string possibleValue,s32 slot,s32 keyslot);
bool setIfValueIsAControllerPresetEx(std::string value,s32 slot,s32 keyslot);
void addDeviceNameEx(u16 vid,u16 pid,std::string value);
std::string getStringByVIDPIDEx(u16 vid,u16 pid);
};
#endif

View File

@ -0,0 +1,50 @@
#include "ControllerPatcherNet.hpp"
#include "wiiu/os.h"
#include "sys/socket.h"
s32 ControllerPatcherNet::recvwait(s32 sock, void *buffer, s32 len) {
s32 ret;
while (len > 0) {
ret = recv(sock, buffer, len, 0);
if(ret < 0) return ret;
len -= ret;
buffer = (void *)(((char *) buffer) + ret);
}
return 0;
}
u8 ControllerPatcherNet::recvbyte(s32 sock) {
unsigned char buffer[1];
s32 ret;
ret = recvwait(sock, buffer, 1);
if (ret < 0) return ret;
return buffer[0];
}
s32 ControllerPatcherNet::checkbyte(s32 sock) {
unsigned char buffer[1];
s32 ret;
ret = recv(sock, buffer, 1, MSG_DONTWAIT);
if (ret < 0) return ret;
if (ret == 0) return -1;
return buffer[0];
}
s32 ControllerPatcherNet::sendwait(s32 sock, const void *buffer, s32 len) {
s32 ret;
while (len > 0) {
ret = send(sock, buffer, len, 0);
if(ret < 0) return ret;
len -= ret;
buffer = (void *)(((char *) buffer) + ret);
}
return 0;
}
s32 ControllerPatcherNet::sendbyte(s32 sock, unsigned char byte) {
unsigned char buffer[1];
buffer[0] = byte;
return sendwait(sock, buffer, 1);
}

View File

@ -0,0 +1,17 @@
#ifndef _CONTROLLERPATCHERNET_H_
#define _CONTROLLERPATCHERNET_H_
#include "wiiu/types.h"
class ControllerPatcherNet{
friend class TCPServer;
friend class UDPServer;
private:
static s32 recvwait(s32 sock, void *buffer, s32 len);
static u8 recvbyte(s32 sock);
static s32 checkbyte(s32 sock);
static s32 sendwait(s32 sock, const void *buffer, s32 len);
static s32 sendbyte(s32 sock, unsigned char byte);
};
#endif

View File

@ -0,0 +1,371 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "TCPServer.hpp"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#define wiiu_errno (*__gh_errno_ptr())
ControllerPatcherThread * TCPServer::pThread = NULL;
TCPServer * TCPServer::instance = NULL;
TCPServer::TCPServer(s32 port){
this->sockfd = -1;
this->clientfd = -1;
memset(&(this->sock_addr),0,sizeof(this->sock_addr));
TCPServer::AttachDetach(DETACH);
StartTCPThread(this);
}
TCPServer::~TCPServer(){
CloseSockets();
if(HID_DEBUG){ printf("TCPServer::~TCPServer(line %d): Thread will be closed\n",__LINE__); }
TCPServer::AttachDetach(DETACH);
exitThread = 1;
if(TCPServer::pThread != NULL){
if(HID_DEBUG){ printf("TCPServer::~TCPServer(line %d): Deleting it!\n",__LINE__); }
delete TCPServer::pThread;
}
if(HID_DEBUG){ printf("TCPServer::~TCPServer(line %d): Thread done\n",__LINE__); }
TCPServer::pThread = NULL;
}
void TCPServer::CloseSockets(){
if (this->sockfd != -1){
socketclose(this->sockfd);
}
if (this->clientfd != -1){
socketclose(this->clientfd);
}
this->sockfd = -1;
this->clientfd = -1;
}
void TCPServer::StartTCPThread(TCPServer * server){
s32 priority = 28;
if(OSGetTitleID() == 0x00050000101c9300 || //The Legend of Zelda Breath of the Wild JPN
OSGetTitleID() == 0x00050000101c9400 || //The Legend of Zelda Breath of the Wild USA
OSGetTitleID() == 0x00050000101c9500 || //The Legend of Zelda Breath of the Wild EUR
OSGetTitleID() == 0x00050000101c9b00 || //The Binding of Isaac: Rebirth EUR
OSGetTitleID() == 0x00050000101a3c00){ //The Binding of Isaac: Rebirth USA
priority = 10;
printf("TCPServer::StartTCPThread(line %d): This game needs higher thread priority. We set it to %d\n",__LINE__,priority);
}
TCPServer::pThread = ControllerPatcherThread::create(TCPServer::DoTCPThread, (void*)server, ControllerPatcherThread::eAttributeAffCore2,priority);
TCPServer::pThread->resumeThread();
}
void TCPServer::AttachDetach(s32 attach){
if(HID_DEBUG){
if(attach){
printf("TCPServer::AttachDetach(line %d): Network Attach\n",__LINE__);
}else{
printf("TCPServer::AttachDetach(line %d): Network Detach\n",__LINE__);
}
}
for(s32 i= 0;i< gHIDMaxDevices;i++){
for(s32 j= 0;j< HID_MAX_PADS_COUNT;j++){
if(gNetworkController[i][j][NETWORK_CONTROLLER_ACTIVE] > 0){
printf("TCPServer::AttachDetach(line %d): Found a registered pad in deviceslot %d and padslot %d! Lets detach it.\n",__LINE__,i,j);
HIDDevice device;
memset(&device,0,sizeof(device));
device.interface_index = 0;
device.vid = gNetworkController[i][j][NETWORK_CONTROLLER_VID];
device.pid = gNetworkController[i][j][NETWORK_CONTROLLER_PID];
device.handle = gNetworkController[i][j][NETWORK_CONTROLLER_HANDLE];
device.max_packet_size_rx = 8;
ControllerPatcherHID::externAttachDetachCallback(&device,attach);
memset(gNetworkController[i][j],0,sizeof(gNetworkController[i][j]));
}
}
}
if(HID_DEBUG){
if(attach){
printf("TCPServer::AttachDetach(line %d): Network Attach DONE!\n",__LINE__);
}else{
printf("TCPServer::AttachDetach(line %d): Network Detach DONE!\n",__LINE__);
}
}
}
void TCPServer::DetachAndDelete(){
TCPServer::AttachDetach(DETACH);
memset(&gNetworkController,0,sizeof(gNetworkController));
}
s32 TCPServer::RunTCP(){
s32 ret;
while (1) {
if(exitThread) break;
ret = ControllerPatcherNet::checkbyte(clientfd);
if (ret < 0) {
if(wiiu_errno != 6) return ret;
wiiu_os_usleep(1000);
continue;
}
//printf("got byte from tcp! %01X\n",ret);
switch (ret) {
case WIIU_CP_TCP_ATTACH: { /*attach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
s32 handle;
ret = ControllerPatcherNet::recvwait(clientfd, &handle, 4);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: recvwait handle\n",__LINE__,WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): got handle %d\n",handle); }
u16 vid = 0;
u16 pid = 0;
ret = ControllerPatcherNet::recvwait(clientfd, &vid, 2);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: recvwait vid\n",__LINE__,WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): got vid %04X\n",vid); }
ret = ControllerPatcherNet::recvwait(clientfd, &pid, 2);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: recvwait pid\n",__LINE__,WIIU_CP_TCP_ATTACH);
return ret;
}
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): got pid %04X\n",pid); }
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vid);
device.pid = SWAP16(pid);
device.max_packet_size_rx = 8;
my_cb_user * user = NULL;
ControllerPatcherHID::externAttachDetachCallback(&device,1);
if((ret = ControllerPatcherUtils::getDataByHandle(handle,&user)) < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: getDataByHandle(%d,%08X).\n",__LINE__,WIIU_CP_TCP_ATTACH,handle,&user);
printf("TCPServer::RunTCP(line %d): Error in %02X: Config for the controller is missing.\n",__LINE__,WIIU_CP_TCP_ATTACH);
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND) < 0)){
printf("TCPServer::RunTCP(line %d): Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND byte failed. Error: %d.\n",__LINE__,WIIU_CP_TCP_ATTACH,ret);
}
return -1;
}
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_CONFIG_FOUND) < 0)){
printf("TCPServer::RunTCP(line %d): Error in %02X: Sending the WIIU_CP_TCP_ATTACH_CONFIG_FOUND byte failed. Error: %d.\n",__LINE__,WIIU_CP_TCP_ATTACH,ret);
return ret;
}
if(user != NULL){
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_OKAY) < 0)){
printf("TCPServer::RunTCP(line %d): Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_OKAY byte failed. Error: %d.\n",__LINE__,WIIU_CP_TCP_ATTACH,ret);
return ret;
}
ret = ControllerPatcherNet::sendwait(clientfd,&user->slotdata.deviceslot,2);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: sendwait slotdata: %04X\n",__LINE__,WIIU_CP_TCP_ATTACH,user->slotdata.deviceslot);
return ret;
}
ret = ControllerPatcherNet::sendwait(clientfd,&user->pad_slot,1);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: sendwait pad_slot: %04X\n",__LINE__,WIIU_CP_TCP_ATTACH,user->pad_slot);
return ret;
}
}else{
printf("TCPServer::RunTCP(line %d): Error in %02X: invalid user data.\n",__LINE__,WIIU_CP_TCP_ATTACH);
if((ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_ATTACH_USER_DATA_BAD) < 0)){
printf("TCPServer::RunTCP(line %d): Error in %02X: Sending the WIIU_CP_TCP_ATTACH_USER_DATA_BAD byte failed. Error: %d.\n",__LINE__,WIIU_CP_TCP_ATTACH,ret);
return ret;
}
return -1;
break;
}
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): attachted to device slot: %d , pad slot is: %d\n",__LINE__,user->slotdata.deviceslot,user->pad_slot); }
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_VID] = device.vid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_PID] = device.pid;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_ACTIVE] = 1;
gNetworkController[user->slotdata.deviceslot][user->pad_slot][NETWORK_CONTROLLER_HANDLE] = handle;
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): handle %d connected! vid: %02X pid: %02X deviceslot %d, padslot %d\n",__LINE__,handle,vid,pid,user->slotdata.deviceslot,user->pad_slot); }
break;
}
break;
}
case WIIU_CP_TCP_DETACH: { /*detach */
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
s32 handle;
ret = ControllerPatcherNet::recvwait(clientfd, &handle, 4);
if(ret < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: recvwait handle\n",__LINE__,WIIU_CP_TCP_DETACH);
return ret;
break;
}
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): got detach for handle: %d\n",__LINE__,handle); }
my_cb_user * user = NULL;
if(ControllerPatcherUtils::getDataByHandle(handle,&user) < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: getDataByHandle(%d,%08X).\n",__LINE__,WIIU_CP_TCP_DETACH,handle,&user);
return -1;
break;
}
if(user == NULL){
printf("TCPServer::RunTCP(line %d): Error in %02X: invalid user data.\n",__LINE__,WIIU_CP_TCP_DETACH);
return -1;
break;
}
s32 deviceslot = user->slotdata.deviceslot;
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): device slot is: %d , pad slot is: %d\n",__LINE__,deviceslot,user->pad_slot); }
DeviceVIDPIDInfo vidpid;
s32 result;
if((result = ControllerPatcherUtils::getVIDPIDbyDeviceSlot(deviceslot,&vidpid)) < 0){
printf("TCPServer::RunTCP(line %d): Error in %02X: Couldn't find a valid VID/PID for device slot %d. Error: %d\n",__LINE__,WIIU_CP_TCP_DETACH,deviceslot,ret);
return -1;
break;
}
HIDDevice device;
memset(&device,0,sizeof(device));
device.handle = handle;
device.interface_index = 0;
device.vid = SWAP16(vidpid.vid);
device.pid = SWAP16(vidpid.pid);
device.max_packet_size_rx = 14;
ControllerPatcherHID::externAttachDetachCallback(&device,DETACH);
memset(gNetworkController[deviceslot][user->pad_slot],0,sizeof(gNetworkController[deviceslot][user->pad_slot]));
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): handle %d disconnected!\n",__LINE__,handle); }
break;
}
break;
}
case WIIU_CP_TCP_PING: { /*ping*/
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
if(HID_DEBUG){ printf("TCPServer::RunTCP(line %d): Got Ping, sending now a Pong\n",__LINE__); }
s32 ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_PONG);
if(ret < 0){ printf("TCPServer::RunTCP(line %d): Error in %02X: sendbyte PONG\n",__LINE__); return -1;}
break;
}
break;
}
default:
return -1;
break;
}
}
return 0;
}
void TCPServer::ErrorHandling(){
CloseSockets();
wiiu_os_usleep(1000*1000*2);
}
void TCPServer::DoTCPThreadInternal(){
s32 ret;
s32 len;
while (1) {
if(exitThread) break;
memset(&(this->sock_addr),0,sizeof(sock_addr));
sock_addr.sin_family = AF_INET;
sock_addr.sin_port = DEFAULT_TCP_PORT;
sock_addr.sin_addr.s_addr = 0;
this->sockfd = ret = socket(AF_INET, SOCK_STREAM, IPPROTO_TCP);
if(ret == -1){ ErrorHandling(); continue;}
s32 enable = 1;
setsockopt(this->sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
ret = bind(this->sockfd, (sockaddr *)&sock_addr, 16);
if(ret < 0) { ErrorHandling(); continue;}
ret = listen(this->sockfd, 1);
if(ret < 0){ ErrorHandling(); continue;}
do{
if(HID_DEBUG){ printf("TCPServer::DoTCPThreadInternal(line %d): Waiting for a connection\n",__LINE__); }
if(exitThread) break;
len = 16;
/**
Handshake
1. At first this server sends his protocol version
2. The network clients answers with his preferred version (which needs to be equals or lower the version this server sent him) or an abort command.
3a. If the client sent a abort, close the connection and wait for another connection
3b. If the client sent his highest supported version, the server confirm that he is able to use this version (by sending the version back) or sending a abort command to disconnect.
**/
clientfd = ret = (s32)accept(sockfd, (sockaddr *)&(sock_addr),(socklen_t *) &len);
if(ret == -1){ ErrorHandling(); break;}
printf("TCPServer::DoTCPThreadInternal(line %d): TCP Connection accepted! Sending my protocol version: %d (0x%02X)\n",__LINE__, (WIIU_CP_TCP_HANDSHAKE - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,WIIU_CP_TCP_HANDSHAKE);
gUDPClientip = sock_addr.sin_addr.s_addr;
UDPClient::createInstance();
s32 ret;
ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE); //Hey I'm a WiiU console!
if(ret < 0){ printf("TCPServer::DoTCPThreadInternal(line %d): Error sendbyte: %02X\n",__LINE__,WIIU_CP_TCP_HANDSHAKE); ErrorHandling(); break;}
u8 clientProtocolVersion = ControllerPatcherNet::recvbyte(clientfd);
if(ret < 0){ printf("TCPServer::DoTCPThreadInternal(line %d): Error recvbyte: %02X\n",__LINE__,WIIU_CP_TCP_HANDSHAKE); ErrorHandling(); break;}
if(clientProtocolVersion == WIIU_CP_TCP_HANDSHAKE_ABORT){
printf("TCPServer::DoTCPThreadInternal(line %d): The network client wants to abort.\n",__LINE__);
ErrorHandling(); break;
}
printf("TCPServer::DoTCPThreadInternal(line %d): received protocol version: %d (0x%02X)\n",__LINE__,(clientProtocolVersion - WIIU_CP_TCP_HANDSHAKE_VERSION_1)+1,clientProtocolVersion);
if(clientProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_MIN && clientProtocolVersion <= WIIU_CP_TCP_HANDSHAKE_VERSION_MAX){
printf("TCPServer::DoTCPThreadInternal(line %d): We support this protocol version. Let's confirm it to the network client.\n",__LINE__);
gUsedProtocolVersion = clientProtocolVersion;
ret = ControllerPatcherNet::sendbyte(clientfd, clientProtocolVersion);
if(ret < 0){ printf("TCPServer::DoTCPThreadInternal(line %d): Error sendbyte: %02X\n",__LINE__,clientProtocolVersion); ErrorHandling(); break;}
}else{
printf("TCPServer::DoTCPThreadInternal(line %d): We don't support this protocol version. We need to abort =(.\n",__LINE__);
ret = ControllerPatcherNet::sendbyte(clientfd, WIIU_CP_TCP_HANDSHAKE_ABORT);
ErrorHandling(); break;
}
printf("TCPServer::DoTCPThreadInternal(line %d): Handshake done! Success!\n",__LINE__);
TCPServer::DetachAndDelete(); //Clear connected controller
RunTCP();
if(clientfd != -1){
socketclose(clientfd);
}
clientfd = -1;
}while(0);
printf("TCPServer::DoTCPThreadInternal(line %d): Connection closed\n",__LINE__);
gUDPClientip = 0;
UDPClient::destroyInstance();
TCPServer::DetachAndDelete(); //Clear connected controller
CloseSockets();
continue;
}
}
void TCPServer::DoTCPThread(ControllerPatcherThread *thread, void *arg){
TCPServer * args = (TCPServer * )arg;
return args->DoTCPThreadInternal();
}

View File

@ -0,0 +1,93 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _TCPSERVER_WINDOW_H_
#define _TCPSERVER_WINDOW_H_
#include "../ControllerPatcher.hpp"
#include "sys/socket.h"
#include "wiiu/os.h"
#define WIIU_CP_TCP_HANDSHAKE WIIU_CP_TCP_HANDSHAKE_VERSION_3
#define WIIU_CP_TCP_HANDSHAKE_VERSION_MIN WIIU_CP_TCP_HANDSHAKE_VERSION_1
#define WIIU_CP_TCP_HANDSHAKE_VERSION_MAX WIIU_CP_TCP_HANDSHAKE_VERSION_3
#define WIIU_CP_TCP_HANDSHAKE_VERSION_1 0x12
#define WIIU_CP_TCP_HANDSHAKE_VERSION_2 0x13
#define WIIU_CP_TCP_HANDSHAKE_VERSION_3 0x14
#define WIIU_CP_TCP_HANDSHAKE_ABORT 0x30
#define ATTACH 0x01
#define DETACH 0x00
#define WIIU_CP_TCP_ATTACH 0x01
#define WIIU_CP_TCP_DETACH 0x02
#define WIIU_CP_TCP_PING 0xF0
#define WIIU_CP_TCP_PONG 0xF1
#define WIIU_CP_TCP_ATTACH_CONFIG_FOUND 0xE0
#define WIIU_CP_TCP_ATTACH_CONFIG_NOT_FOUND 0xE1
#define WIIU_CP_TCP_ATTACH_USER_DATA_OKAY 0xE8
#define WIIU_CP_TCP_ATTACH_USER_DATA_BAD 0xE9
#define DEFAULT_TCP_PORT 8112
class TCPServer{
friend class ControllerPatcher;
private:
static TCPServer *getInstance() {
if(!instance)
instance = new TCPServer(DEFAULT_TCP_PORT);
return instance;
}
static void destroyInstance() {
if(instance){
delete instance;
instance = NULL;
}
}
TCPServer(s32 port);
~TCPServer();
void CloseSockets();
void ErrorHandling();
void StartTCPThread(TCPServer * server);
static void DoTCPThread(ControllerPatcherThread *thread, void *arg);
void DoTCPThreadInternal();
static void DetachConnectedNetworkController();
static void AttachDetach(s32 attach);
void DetachAndDelete();
static TCPServer *instance;
s32 RunTCP();
struct sockaddr_in sock_addr;
volatile s32 sockfd = -1;
volatile s32 clientfd = -1;
volatile s32 exitThread = 0;
static ControllerPatcherThread *pThread;
};
#endif //_TCPSERVER_WINDOW_H_

View File

@ -0,0 +1,58 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "UDPClient.hpp"
#include <stdio.h>
#include <string.h>
#define MAX_UDP_SIZE 0x578
UDPClient * UDPClient::instance = NULL;
UDPClient::UDPClient(u32 ip, s32 port){
sockfd = socket(AF_INET, SOCK_DGRAM, IPPROTO_UDP);
if (sockfd < 0)
return;
struct sockaddr_in connect_addr;
memset(&connect_addr, 0, sizeof(connect_addr));
connect_addr.sin_family = AF_INET;
connect_addr.sin_port = port;
connect_addr.sin_addr.s_addr = ip;
if(connect(sockfd, (struct sockaddr*)&connect_addr, sizeof(connect_addr)) < 0)
{
socketclose(sockfd);
sockfd = -1;
}
}
UDPClient::~UDPClient(){
if (this->sockfd != -1){
socketclose(sockfd);
}
if(HID_DEBUG){ printf("UDPClient::~UDPClient(line %d): Thread has been closed\n",__LINE__); }
}
bool UDPClient::sendData(char * data,s32 length){
if(sockfd < 0 || data == 0 || length < 0 || gUsedProtocolVersion < WIIU_CP_TCP_HANDSHAKE_VERSION_3){
return false;
}
if(length > 1400) length = 1400;
s32 ret = send(sockfd, data, length, 0);
return (ret >= 0);
}

View File

@ -0,0 +1,66 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _UDPCLIENT_WINDOW_H_
#define _UDPCLIENT_WINDOW_H_
#include "../ControllerPatcher.hpp"
#include "sys/socket.h"
#define DEFAULT_UDP_CLIENT_PORT 8114
class UDPClient{
friend class ControllerPatcher;
friend class ControllerPatcherHID;
friend class TCPServer;
public:
private:
static UDPClient *getInstance() {
if(instance == NULL){
createInstance();
}
return instance;
}
static UDPClient *createInstance() {
if(instance != NULL){
destroyInstance();
}
instance = new UDPClient(gUDPClientip,DEFAULT_UDP_CLIENT_PORT);
return getInstance();
}
static void destroyInstance() {
if(instance != NULL){
delete instance;
instance = NULL;
}
}
UDPClient(u32 ip,s32 port);
~UDPClient();
bool sendData(char * data, s32 length);
volatile s32 sockfd = -1;
struct sockaddr_in addr;
static UDPClient *instance;
};
#endif //_UDPClient_WINDOW_H_

View File

@ -0,0 +1,168 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "UDPServer.hpp"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "sys/socket.h"
#define MAX_UDP_SIZE 0x578
#define wiiu_errno (*__gh_errno_ptr())
ControllerPatcherThread * UDPServer::pThread = NULL;
UDPServer * UDPServer::instance = NULL;
UDPServer::UDPServer(s32 port){
s32 ret;
struct sockaddr_in addr;
addr.sin_family = AF_INET;
addr.sin_port = port;
addr.sin_addr.s_addr = 0;
this->sockfd = ret = socket(AF_INET, SOCK_DGRAM, 0);
if(ret == -1) return;
s32 enable = 1;
setsockopt(sockfd, SOL_SOCKET, SO_REUSEADDR, &enable, sizeof(enable));
ret = bind(sockfd, (sockaddr *)&addr, 16);
if(ret < 0) return;
StartUDPThread(this);
}
UDPServer::~UDPServer(){
ControllerPatcherThread * pThreadPointer = UDPServer::pThread;
if(pThreadPointer != NULL){
exitThread = 1;
if(pThreadPointer != NULL){
delete pThreadPointer;
UDPServer::pThread = NULL;
if (this->sockfd != -1){
socketclose(sockfd);
}
this->sockfd = -1;
}
}
if(HID_DEBUG){ printf("UDPServer::~UDPServer(line %d): Thread has been closed\n",__LINE__); }
}
void UDPServer::StartUDPThread(UDPServer * server){
s32 priority = 28;
if(OSGetTitleID() == 0x00050000101c9300 || //The Legend of Zelda Breath of the Wild JPN
OSGetTitleID() == 0x00050000101c9400 || //The Legend of Zelda Breath of the Wild USA
OSGetTitleID() == 0x00050000101c9500 || //The Legend of Zelda Breath of the Wild EUR
OSGetTitleID() == 0x00050000101c9b00 || //The Binding of Isaac: Rebirth EUR
OSGetTitleID() == 0x00050000101a3c00){ //The Binding of Isaac: Rebirth USA
priority = 10;
printf("UDPServer::StartUDPThread(line %d): This game needs higher thread priority. We set it to %d\n",__LINE__,priority);
}
UDPServer::pThread = ControllerPatcherThread::create(UDPServer::DoUDPThread, (void*)server, ControllerPatcherThread::eAttributeAffCore2,priority);
UDPServer::pThread->resumeThread();
}
bool UDPServer::cpyIncrementBufferOffset(void * target, void * source, s32 * offset, s32 typesize, s32 maximum){
if(((int)*offset + typesize) > maximum){
printf("UDPServer::cpyIncrementBufferOffset(line %d): Transfer error. Excepted %04X bytes, but only got %04X\n",__LINE__,(*offset + typesize),maximum);
return false;
}
memcpy(target,(void*)((u32)source+(*offset)),typesize);
*offset += typesize;
return true;
}
void UDPServer::DoUDPThread(ControllerPatcherThread *thread, void *arg){
UDPServer * args = (UDPServer * )arg;
args->DoUDPThreadInternal();
}
void UDPServer::DoUDPThreadInternal(){
u8 buffer[MAX_UDP_SIZE];
s32 n;
my_cb_user user;
while(1){
//s32 usingVar = exitThread;
if(exitThread)break;
memset(buffer,0,MAX_UDP_SIZE);
n = recv(sockfd,buffer,MAX_UDP_SIZE,0);
if (n < 0){
s32 errno_ = wiiu_errno;
wiiu_os_usleep(2000);
if(errno_ != 11 && errno_ != 9){
break;
}
continue;
}
s32 bufferoffset = 0;
u8 type;
memcpy((void *)&type,buffer,sizeof(type));
bufferoffset += sizeof(type);
switch (buffer[0]) {
case WIIU_CP_UDP_CONTROLLER_READ_DATA: {
if(gUsedProtocolVersion >= WIIU_CP_TCP_HANDSHAKE_VERSION_1){
u8 count_commands;
memcpy((void *)&count_commands,buffer+bufferoffset,sizeof(count_commands));
bufferoffset += sizeof(count_commands);
for(s32 i = 0;i<count_commands;i++){
s32 handle;
u16 deviceSlot;
u32 hid;
u8 padslot;
u8 datasize;
if(!cpyIncrementBufferOffset((void *)&handle, (void *)buffer,&bufferoffset,sizeof(handle), n))continue;
if(!cpyIncrementBufferOffset((void *)&deviceSlot, (void *)buffer,&bufferoffset,sizeof(deviceSlot),n))continue;
hid = (1 << deviceSlot);
if(!cpyIncrementBufferOffset((void *)&padslot, (void *)buffer,&bufferoffset,sizeof(padslot), n))continue;
if(!cpyIncrementBufferOffset((void *)&datasize, (void *)buffer,&bufferoffset,sizeof(datasize), n))continue;
u8 * databuffer = (u8*) malloc(datasize * sizeof(u8));
if(!databuffer){
printf("UDPServer::DoUDPThreadInternal(line %d): Allocating memory failed\n",__LINE__);
continue;
}
if(!cpyIncrementBufferOffset((void *)databuffer, (void *)buffer,&bufferoffset,datasize, n))continue;
//printf("UDPServer::DoUDPThreadInternal(): Got handle: %d slot %04X hid %04X pad %02X datasize %02X\n",handle,deviceSlot,hid,padslot,datasize);
user.pad_slot = padslot;
user.slotdata.deviceslot = deviceSlot;
user.slotdata.hidmask = hid;
if(gNetworkController[deviceSlot][padslot][0] == 0){
printf("UDPServer::DoUDPThreadInternal(line %d): Ehm. Pad is not connected. STOP SENDING DATA ;) \n",__LINE__);
}else{
ControllerPatcherHID::externHIDReadCallback(handle,databuffer,datasize,&user);
}
if(databuffer){
free(databuffer);
databuffer = NULL;
}
}
break;
}
break;
}
default:{
break;
}
}
}
if(HID_DEBUG){ printf("UDPServer::DoUDPThreadInternal(line %d): UDPServer Thread ended\n",__LINE__); }
}

View File

@ -0,0 +1,57 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _UDPSERVER_WINDOW_H_
#define _UDPSERVER_WINDOW_H_
#include "../ControllerPatcher.hpp"
#define DEFAULT_UDP_PORT 8113
#define WIIU_CP_UDP_CONTROLLER_READ_DATA 0x03
class UDPServer{
friend class ControllerPatcher;
private:
static UDPServer *getInstance() {
if(instance == NULL)
instance = new UDPServer(DEFAULT_UDP_PORT);
return instance;
}
static void destroyInstance() {
if(instance != NULL){
delete instance;
instance = NULL;
}
}
UDPServer(s32 port);
~UDPServer();
void StartUDPThread(UDPServer * server);
static void DoUDPThread(ControllerPatcherThread *thread, void *arg);
void DoUDPThreadInternal();
bool cpyIncrementBufferOffset(void * target, void * source, s32 * offset, s32 typesize, s32 maximum);
volatile s32 sockfd = -1;
volatile s32 exitThread = 0;
static UDPServer *instance;
static ControllerPatcherThread *pThread;
};
#endif //_UDPSERVER_WINDOW_H_

View File

@ -0,0 +1,703 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* @file ControllerPatcherDefs.h
* @author Maschell
* @date 30 Mar 2017
* \brief This files contain all definitions for the ControllerPatcher engine
*
* @see https://github.com/Maschell/controller_patcher
*/
#ifndef _CONTROLLER_PATCHER_DEFS_H_
#define _CONTROLLER_PATCHER_DEFS_H_
#include <wiiu/types.h>
#define FIRST_INSTRUCTION_IN_SAMPLING_CALLBACK 0x9421FFB8
#define HID_INIT_NOT_DONE 0
#define HID_INIT_DONE 1
#define HID_SDCARD_READ 2
#define gHIDMaxDevices 32
#define HID_MAX_DATA_LENGTH_PER_PAD 16
#define HID_MAX_PADS_COUNT 5
#define HID_MAX_DEVICES_PER_SLOT 2
#define NETWORK_CONTROLLER_VID 0
#define NETWORK_CONTROLLER_PID 1
#define NETWORK_CONTROLLER_ACTIVE 2
#define NETWORK_CONTROLLER_HANDLE 3
#define CONTROLLER_PATCHER_VALUE_SET 0x01
#define CONTROLLER_PATCHER_GC_DOUBLE_USE 0x01
#define CONTROLLER_PATCHER_INVALIDVALUE 0xFF
#define HID_INVALID_SLOT 0xFFFF
#define HID_INVALID_HIDMASK 0xFFFFFFFF
typedef int CONTROLLER_PATCHER_RESULT_OR_ERROR;
#define CONTROLLER_PATCHER_ERROR_NONE 0
#define CONTROLLER_PATCHER_ERROR_INVALID_CHAN -1
#define CONTROLLER_PATCHER_ERROR_UNKNOWN_VID_PID -2
#define CONTROLLER_PATCHER_ERROR_FAILED_TO_GET_HIDDATA -3
#define CONTROLLER_PATCHER_ERROR_MAPPING_DISABLED -4
#define CONTROLLER_PATCHER_ERROR_INVALID_BUFFER -5
#define CONTROLLER_PATCHER_ERROR_HID_NOT_CONNECTED -6
#define CONTROLLER_PATCHER_ERROR_NO_PAD_CONNECTED -7
#define CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND -8
#define CONTROLLER_PATCHER_ERROR_NULL_POINTER -9
#define CONTROLLER_PATCHER_ERROR_CONFIG_NOT_DONE -10
#define CONTROLLER_PATCHER_ERROR_NO_FREE_SLOT -11
#define CONTROLLER_PATCHER_ERROR_UNKNOWN -50
#define PRO_CONTROLLER_MODE_KPADDATA 0
#define PRO_CONTROLLER_MODE_WPADReadData 1
#define STICK_VALUE_UP 1 << 1
#define STICK_VALUE_DOWN 1 << 2
#define STICK_VALUE_LEFT 1 << 3
#define STICK_VALUE_RIGHT 1 << 4
/**
* @brief The enumeration of Controller sticks defines
*/
enum Controller_Stick_Defines
{
STICK_CONF_MAGIC_VERSION, /**< Version of the stick configuration. Changes with every format*/
STICK_CONF_BYTE, /**< Byte where the stick-axis data is stored*/
STICK_CONF_DEFAULT, /**< Default value*/
STICK_CONF_DEADZONE, /**< Size of the deadzone */
STICK_CONF_INVERT, /**< Is 1 when the axis is inverted */
STICK_CONF_MIN, /**< Value that represent the minimum value (-1.0f)*/
STICK_CONF_MAX, /**< Value that represent the maximum value (1.0f) */
STICK_CONF_ENUM_MAXVALUE /**< Maxmimum enum value for iteration*/
};
#define STICK_CONF_MAGIC_VALUE 0xF0 // When you change the enum above, Dont forget to change the magic version!!!!
//! most data has the format: byte,value (byte starting at 0)
enum Controller_Patcher_Settings
{
CONTRPS_VID, //! pid: 0x451d would be 0x45,0x1d
CONTRPS_PID, //! vid: 0x488d would be 0x48,0x8d
CONTRPS_BUF_SIZE, //! To set: CONTROLLER_PATCHER_VALUE_SET, BUF_SIZE (default is 64)
CONTRPS_VPAD_BUTTON_A,
CONTRPS_VPAD_BUTTON_B,
CONTRPS_VPAD_BUTTON_X,
CONTRPS_VPAD_BUTTON_Y,
CONTRPS_DPAD_MODE, //! To set mode: CONTROLLER_PATCHER_VALUE_SET, Controller_Patcher_DPAD_MODE (default is normal mode)
CONTRPS_DPAD_MASK, //! Mask needed for hat mode: CONTROLLER_PATCHER_VALUE_SET, mask
/* Normal DPAD */
CONTRPS_VPAD_BUTTON_LEFT,
CONTRPS_VPAD_BUTTON_RIGHT,
CONTRPS_VPAD_BUTTON_UP,
CONTRPS_VPAD_BUTTON_DOWN,
/* DPAD hat mode */
CONTRPS_VPAD_BUTTON_DPAD_N,
CONTRPS_VPAD_BUTTON_DPAD_NE,
CONTRPS_VPAD_BUTTON_DPAD_E,
CONTRPS_VPAD_BUTTON_DPAD_SE,
CONTRPS_VPAD_BUTTON_DPAD_S,
CONTRPS_VPAD_BUTTON_DPAD_SW,
CONTRPS_VPAD_BUTTON_DPAD_W,
CONTRPS_VPAD_BUTTON_DPAD_NW,
CONTRPS_VPAD_BUTTON_DPAD_NEUTRAL,
/* DPAD Absolute mode */
CONTRPS_VPAD_BUTTON_DPAD_ABS_UP,
CONTRPS_VPAD_BUTTON_DPAD_ABS_DOWN,
CONTRPS_VPAD_BUTTON_DPAD_ABS_LEFT,
CONTRPS_VPAD_BUTTON_DPAD_ABS_RIGHT,
/* */
CONTRPS_VPAD_BUTTON_ZL,
CONTRPS_VPAD_BUTTON_ZR,
CONTRPS_VPAD_BUTTON_L,
CONTRPS_VPAD_BUTTON_R,
CONTRPS_VPAD_BUTTON_PLUS,
CONTRPS_VPAD_BUTTON_MINUS,
CONTRPS_VPAD_BUTTON_HOME,
CONTRPS_VPAD_BUTTON_SYNC,
CONTRPS_VPAD_BUTTON_STICK_R,
CONTRPS_VPAD_BUTTON_STICK_L,
CONTRPS_VPAD_STICK_R_EMULATION_LEFT,
CONTRPS_VPAD_STICK_R_EMULATION_RIGHT,
CONTRPS_VPAD_STICK_R_EMULATION_UP,
CONTRPS_VPAD_STICK_R_EMULATION_DOWN,
CONTRPS_VPAD_STICK_L_EMULATION_LEFT,
CONTRPS_VPAD_STICK_L_EMULATION_RIGHT,
CONTRPS_VPAD_STICK_L_EMULATION_UP,
CONTRPS_VPAD_STICK_L_EMULATION_DOWN,
CONTRPS_VPAD_BUTTON_L_STICK_X, //! byte, default value
CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT, //! To invert: CONTROLLER_PATCHER_VALUE_SET, 0x01
CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE, //! Deadzone
CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX, //! min,max
CONTRPS_VPAD_BUTTON_L_STICK_Y, //! byte, default value
CONTRPS_VPAD_BUTTON_L_STICK_Y_INVERT, //! To invert: CONTROLLER_PATCHER_VALUE_SET, 0x01
CONTRPS_VPAD_BUTTON_L_STICK_Y_DEADZONE, //! Deadzone
CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX, //! min,max
CONTRPS_VPAD_BUTTON_R_STICK_X, //! byte, default value
CONTRPS_VPAD_BUTTON_R_STICK_X_INVERT, //! To invert: CONTROLLER_PATCHER_VALUE_SET, 0x01
CONTRPS_VPAD_BUTTON_R_STICK_X_DEADZONE, //! Deadzone
CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX, //! min,max
CONTRPS_VPAD_BUTTON_R_STICK_Y, //! byte, default value
CONTRPS_VPAD_BUTTON_R_STICK_Y_INVERT, //! To invert: CONTROLLER_PATCHER_VALUE_SET, 0x01
CONTRPS_VPAD_BUTTON_R_STICK_Y_DEADZONE, //! Deadzone
CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX, //! min,max
CONTRPS_VPAD_BUTTON_L_STICK_UP,
CONTRPS_VPAD_BUTTON_L_STICK_DOWN,
CONTRPS_VPAD_BUTTON_L_STICK_LEFT,
CONTRPS_VPAD_BUTTON_L_STICK_RIGHT,
CONTRPS_VPAD_BUTTON_R_STICK_UP,
CONTRPS_VPAD_BUTTON_R_STICK_DOWN,
CONTRPS_VPAD_BUTTON_R_STICK_LEFT,
CONTRPS_VPAD_BUTTON_R_STICK_RIGHT,
CONTRPS_VPAD_BUTTON_TV,
CONTRPS_DOUBLE_USE, //!When used: e.g. CONTROLLER_PATCHER_VALUE_SET, CONTROLLER_PATCHER_GC_DOUBLE_USE
CONTRPS_DOUBLE_USE_BUTTON_ACTIVATOR,
CONTRPS_DOUBLE_USE_BUTTON_1_PRESSED,
CONTRPS_DOUBLE_USE_BUTTON_2_PRESSED,
CONTRPS_DOUBLE_USE_BUTTON_3_PRESSED,
CONTRPS_DOUBLE_USE_BUTTON_4_PRESSED,
CONTRPS_DOUBLE_USE_BUTTON_5_PRESSED,
CONTRPS_DOUBLE_USE_BUTTON_1_RELEASED,
CONTRPS_DOUBLE_USE_BUTTON_2_RELEASED,
CONTRPS_DOUBLE_USE_BUTTON_3_RELEASED,
CONTRPS_DOUBLE_USE_BUTTON_4_RELEASED,
CONTRPS_DOUBLE_USE_BUTTON_5_RELEASED,
CONTRPS_PAD_COUNT, //!
CONTRPS_CONNECTED_PADS, //!
CONTRPS_INPUT_FILTER, //!
CONTRPS_PAD1_FILTER, //!
CONTRPS_PAD2_FILTER, //!
CONTRPS_PAD3_FILTER, //!
CONTRPS_PAD4_FILTER, //!
CONTRPS_PAD5_FILTER, //!
CONTRPS_MOUSE_STICK,
CONTRPS_MAX_VALUE
};
/**
* @brief The enumeration of different DPAD-Modes
*/
enum Controller_Patcher_DPAD_MODE
{
CONTRPDM_Normal, /**< Normal mode */
CONTRPDM_Hat, /**< Hat mode */
CONTRPDM_Absolute_2Values, /**< DPAD Value stored in 2 values (one for each axis), acting like a stick */
};
/**
* @brief The enumeration of DPAD Settings. Needed for saving both in the PADConst.
*/
enum Controller_Patcher_DPAD_Settings
{
CONTRDPAD_MODE = 0, /**< Byte where the DPAD Mode is stored */
CONTRDPAD_MASK = 1, /**< Byte where the DPAD Mask is stored */
};
/**
* @brief Stores data if the Slot the device is using in gHID_Devices
*/
typedef struct _HIDSlotData{
u16 deviceslot; /**< deviceslot number */
u32 hidmask; /**< Used HID-Mask */
}HIDSlotData;
/**
* @brief Stores a VID and PID
*/
typedef struct _DeviceVIDPIDInfo{
u16 vid; /**< Vendor ID of this device */
u16 pid; /**< Product ID of this device */
}DeviceVIDPIDInfo;
/**
* @brief Struct where the data for the callback funtion is stored
*/
typedef struct _my_cb_user{
u8 *buf; /**< pointer the buffer that is used */
u32 transfersize; /**< number of transfered data */
u32 handle; /**< HID handle */
HIDSlotData slotdata; /**< Information about the deviceslot and hidmask */
u32 pads_per_device; /**< Number of maximum pads of this device */
u8 pad_slot; /**< number of the pad that will be used */
u8 rumblestatus[HID_MAX_PADS_COUNT]; /**< Current status of the device rumble */
u8 forceRumbleInTicks[HID_MAX_PADS_COUNT];
DeviceVIDPIDInfo vidpid; /**< The VID/PID of the device */
}my_cb_user;
/**
* @brief Stores data for the mouse
*/
typedef struct _HID_Mouse_Data {
u8 left_click; /**< Is 1 when the left mouse button is pressed */
u8 right_click; /**< Is 1 when the right mouse button is pressed */
s16 X; /**< X position of the cursor */
s16 Y; /**< Y position of the cursor */
s16 deltaX; /**< difference of the X value since the last call */
s16 deltaY; /**< difference of the Y value since the last call */
u8 valuedChanged; /**< Is 1 when the value has changed */
} HID_Mouse_Data;
/**
* @brief The enumeration of device types
*/
typedef enum DEVICE_TYPE_
{
DEVICE_TYPE_CONTROLLER = 0, /**< Normal Controller */
DEVICE_TYPE_MOUSE = 1, /**< Mouse */
}DEVICE_TYPE;
/**
* @brief Stores all data of the HID Device for accessing
*/
typedef struct _HID_Data {
u32 handle; /**< The HID-handle this device is using */
u8 rumbleActive; /**< 1 when rumble is active */
u32 last_buttons; /**< The last pressed buttons, based on VPAD_BUTTON_XXX data */
union{
struct{
u8 cur_hid_data[HID_MAX_DATA_LENGTH_PER_PAD]; /**< Array where the current controller data is stored */
u8 last_hid_data[HID_MAX_DATA_LENGTH_PER_PAD]; /**< Array where the last controller data is stored */
} controller; /**< Used when the device in a controller. Using u8 array where the raw data of the controller is placed. */
struct{
HID_Mouse_Data cur_mouse_data; /**< Struct where the current mouse data is stored */
HID_Mouse_Data last_mouse_data; /**< Struct where the last mouse data is stored */
} mouse; /**< Used when the device in a mouse. Using a new struct to store the data. */
}data_union; /**< The data union where the current and last data is stored.*/
DEVICE_TYPE type; /**< The device type*/
HIDSlotData slotdata; /**< Information about the deviceslot and his mask*/
my_cb_user * user_data; /**< Pointer to the user data the read callback is using*/
} HID_Data;
/**
* @brief Struct where current hid data of one device type is stored
*/
typedef struct _HID_DEVICE_DATA {
HID_Data pad_data[HID_MAX_PADS_COUNT];
} HID_DEVICE_DATA;
/**
* @brief Infos of the device
*/
typedef struct _DeviceInfo{
HIDSlotData slotdata; /**< The slot used by this device */
DeviceVIDPIDInfo vidpid; /**< The VID/PID of the device */
u8 pad_count; /**< Number of maximum pads this device can have*/
}DeviceInfo;
/**
* @brief The enumeration of Controller-Mapping types
*/
typedef enum ControllerMapping_Type_Defines_{
CM_Type_Controller = 0, /**< Device with single input */
CM_Type_RealController = 1, /**< Real Pro Controller */
CM_Type_Mouse = 2, /**< Mouse */
CM_Type_Keyboard = 3, /**< Keyboard */
} ControllerMapping_Type_Defines;
/**
* @brief Infos of a mapped controller
*/
typedef struct _ControllerMappingPADInfo{
u8 active; /**< Set to one if mapped */
ControllerMapping_Type_Defines type; /**< Type of the controller mapping */
DeviceVIDPIDInfo vidpid; /**< The VID/PID of the device */
u8 pad; /**< Stores which pad it mapped */
}ControllerMappingPADInfo;
/**
* @brief Infos of a mapped controller
*/
typedef struct _ControllerMappingPAD{
ControllerMappingPADInfo pad_infos[HID_MAX_DEVICES_PER_SLOT]; //lets limit this to HID_MAX_DEVICES_PER_SLOT.
u8 useAll;
u8 rumble; /**< Set when the controller should rumble */
}ControllerMappingPAD;
/**
* @brief Stores informations about all mapped controller
*/
typedef struct _ControllerMapping{
ControllerMappingPAD gamepad; /**< Information about the gamepad mapping */
ControllerMappingPAD proController[4]; /**< Information about the Pro Controller mapping */
}ControllerMapping;
/**
* @brief Pressed/Released/Down Button data.
*/
typedef struct _InputButtonData{
u32 hold; /**< Buttons beeing hold */
u32 trigger; /**< Buttons that started pressing */
u32 release; /**< Buttons that were button released */
}InputButtonData;
typedef struct _InputStickData{
f32 leftStickX;
f32 leftStickY;
f32 rightStickX;
f32 rightStickY;
}InputStickData;
/**
* @brief Struct where the inputdata of a device for all HID_MAX_PADS_COUNT pads can be stored
*/
typedef struct _InputData{
DeviceInfo device_info; /**< Infos about the device where the data is coming from */
u8 status;
InputButtonData button_data;
InputStickData stick_data;
}InputData;
/**
* @brief The enumeration of WiiU Controller types
*/
enum UController_Type{
UController_Type_Gamepad,
UController_Type_Pro1,
UController_Type_Pro2,
UController_Type_Pro3,
UController_Type_Pro4,
};
#define UController_Type_Gamepad_Name gettext("GamePad")
#define UController_Type_Pro1_Name gettext("Pro Controller 1")
#define UController_Type_Pro2_Name gettext("Pro Controller 2")
#define UController_Type_Pro3_Name gettext("Pro Controller 3")
#define UController_Type_Pro4_Name gettext("Pro Controller 4")
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* VID/PID values
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_GC_VID 0x057e
#define HID_GC_PID 0x0337
#define HID_KEYBOARD_VID 0xAFFE
#define HID_KEYBOARD_PID 0XAAAC
#define HID_MOUSE_VID 0xAFFE
#define HID_MOUSE_PID 0XAAAB
#define HID_DS3_VID 0x054c
#define HID_DS3_PID 0x0268
#define HID_DS4_VID 0x054c
#define HID_DS4_PID 0x05c4
#define HID_NEW_DS4_VID 0x054c
#define HID_NEW_DS4_PID 0x09CC
#define HID_XINPUT_VID 0x7331
#define HID_XINPUT_PID 0x1337
#define HID_SWITCH_PRO_VID 0x057e
#define HID_SWITCH_PRO_PID 0x2009
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* GC Adapter
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_GC_BUTTON_A_VALUE 0x01
#define HID_GC_BUTTON_B_VALUE 0x02
#define HID_GC_BUTTON_X_VALUE 0x04
#define HID_GC_BUTTON_Y_VALUE 0x08
#define HID_GC_BUTTON_LEFT_VALUE 0x10
#define HID_GC_BUTTON_RIGHT_VALUE 0x20
#define HID_GC_BUTTON_DOWN_VALUE 0x40
#define HID_GC_BUTTON_UP_VALUE 0x80
#define HID_GC_BUTTON_START_VALUE 0x01
#define HID_GC_BUTTON_L_VALUE 0x80
#define HID_GC_BUTTON_R_VALUE 0x80
#define HID_GC_BUTTON_Z_VALUE 0x02
#define HID_GC_PAD_COUNT 4
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* DS3
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define PS3_F4_REPORT_LEN 4
#define PS3_F5_REPORT_LEN 8
#define PS3_01_REPORT_LEN 48
#define HID_REPORT_FEATURE 3
#define HID_REPORT_OUTPUT 2
#define PS3_F4_REPORT_ID 0xF4
#define PS3_01_REPORT_ID 0x01
#define PS3_F5_REPORT_ID 0xF5
#define HID_DS3_BUTTON_CROSS_VALUE 0x40 // 3
#define HID_DS3_BUTTON_CIRCLE_VALUE 0x20 // 3
#define HID_DS3_BUTTON_SQUARE_VALUE 0x80 // 3
#define HID_DS3_BUTTON_TRIANGLE_VALUE 0x10 // 3
#define HID_DS3_BUTTON_L1_VALUE 0x04 // 3
#define HID_DS3_BUTTON_L2_VALUE 0x01 // 3
#define HID_DS3_BUTTON_R1_VALUE 0x08 // 3
#define HID_DS3_BUTTON_R2_VALUE 0x02 // 3
#define HID_DS3_BUTTON_L3_VALUE 0x02 // 2
#define HID_DS3_BUTTON_R3_VALUE 0x04 // 2
#define HID_DS3_BUTTON_SELECT_VALUE 0x01 // 2
#define HID_DS3_BUTTON_START_VALUE 0x08 // 2
#define HID_DS3_BUTTON_LEFT_VALUE 0x80 // 2
#define HID_DS3_BUTTON_RIGHT_VALUE 0x20 // 2
#define HID_DS3_BUTTON_UP_VALUE 0x10 // 2
#define HID_DS3_BUTTON_DOWN_VALUE 0x40 // 2
#define HID_DS3_BUTTON_GUIDE_VALUE 0x01 // 4
#define HID_DS3_PAD_COUNT 1
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* DS4
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_DS4_BUTTON_CROSS_VALUE 0x20 // 5
#define HID_DS4_BUTTON_SQUARE_VALUE 0x10 // 5
#define HID_DS4_BUTTON_CIRCLE_VALUE 0x40 // 5
#define HID_DS4_BUTTON_TRIANGLE_VALUE 0x80 // 5
#define HID_DS4_BUTTON_L1_VALUE 0x01 // 6
#define HID_DS4_BUTTON_L2_VALUE 0x04 // 6
#define HID_DS4_BUTTON_L3_VALUE 0x40 // 6
#define HID_DS4_BUTTON_R1_VALUE 0x02 // 6
#define HID_DS4_BUTTON_R2_VALUE 0x08 // 6
#define HID_DS4_BUTTON_R3_VALUE 0x80 // 6
#define HID_DS4_BUTTON_SHARE_VALUE 0x10 // 6
#define HID_DS4_BUTTON_OPTIONS_VALUE 0x20 // 6
#define HID_DS4_BUTTON_DPAD_MASK_VALUE 0x0F
#define HID_DS4_BUTTON_DPAD_N_VALUE 0x00 // 5
#define HID_DS4_BUTTON_DPAD_NE_VALUE 0x01 // 5
#define HID_DS4_BUTTON_DPAD_E_VALUE 0x02 // 5
#define HID_DS4_BUTTON_DPAD_SE_VALUE 0x03 // 5
#define HID_DS4_BUTTON_DPAD_S_VALUE 0x04 // 5
#define HID_DS4_BUTTON_DPAD_SW_VALUE 0x05 // 5
#define HID_DS4_BUTTON_DPAD_W_VALUE 0x06 // 5
#define HID_DS4_BUTTON_DPAD_NW_VALUE 0x07 // 5
#define HID_DS4_BUTTON_DPAD_NEUTRAL_VALUE 0x08 // 5
#define HID_DS4_BUTTON_GUIDE_VALUE 0x01 // 7
#define HID_DS4_BUTTON_T_PAD_CLICK_VALUE 0x02 // 7
#define HID_DS4_PAD_COUNT 1
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* XInput
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_XINPUT_BUTTON_A_VALUE 0x01 // 7
#define HID_XINPUT_BUTTON_B_VALUE 0x02 // 7
#define HID_XINPUT_BUTTON_X_VALUE 0x04 // 7
#define HID_XINPUT_BUTTON_Y_VALUE 0x08 // 7
#define HID_XINPUT_BUTTON_START_VALUE 0x02 // 6
#define HID_XINPUT_BUTTON_BACK_VALUE 0x01 // 6
#define HID_XINPUT_BUTTON_GUIDE_VALUE 0x80 // 6
#define HID_XINPUT_BUTTON_LB_VALUE 0x04 // 6
#define HID_XINPUT_BUTTON_RB_VALUE 0x08 // 6
#define HID_XINPUT_BUTTON_L3_VALUE 0x10 // 6
#define HID_XINPUT_BUTTON_R3_VALUE 0x20 // 6
#define HID_XINPUT_BUTTON_LT_VALUE 0x80 // 4
#define HID_XINPUT_BUTTON_RT_VALUE 0x80 // 5
#define HID_XINPUT_BUTTON_DPAD_MASK_VALUE 0xF0
#define HID_XINPUT_BUTTON_LEFT_VALUE 0x10 // 7
#define HID_XINPUT_BUTTON_RIGHT_VALUE 0x40 // 7
#define HID_XINPUT_BUTTON_DOWN_VALUE 0x80 // 7
#define HID_XINPUT_BUTTON_UP_VALUE 0x20 // 7
#define HID_XINPUT_PAD_COUNT 1
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Switch Pro Controller
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_SWITCH_PRO_USB_BUTTON_A_VALUE 0x08000000
#define HID_SWITCH_PRO_USB_BUTTON_B_VALUE 0x04000000
#define HID_SWITCH_PRO_USB_BUTTON_X_VALUE 0x02000000
#define HID_SWITCH_PRO_USB_BUTTON_Y_VALUE 0x01000000
#define HID_SWITCH_PRO_USB_BUTTON_PLUS_VALUE 0x00020000
#define HID_SWITCH_PRO_USB_BUTTON_MINUS_VALUE 0x00010000
#define HID_SWITCH_PRO_USB_BUTTON_HOME_VALUE 0x00100000
#define HID_SWITCH_PRO_USB_BUTTON_SCREENSHOT_VALUE 0x00200000
#define HID_SWITCH_PRO_USB_BUTTON_R_VALUE 0x40000000
#define HID_SWITCH_PRO_USB_BUTTON_ZR_VALUE 0x80000000
#define HID_SWITCH_PRO_USB_BUTTON_STICK_R_VALUE 0x00040000
#define HID_SWITCH_PRO_USB_BUTTON_L_VALUE 0x00004000
#define HID_SWITCH_PRO_USB_BUTTON_ZL_VALUE 0x00008000
#define HID_SWITCH_PRO_USB_BUTTON_STICK_L_VALUE 0x00080000
#define HID_SWITCH_PRO_USB_BUTTON_DPAD_MASK_VALUE 0x0F
#define HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE 0x08 // 2
#define HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE 0x04 // 2
#define HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE 0x01 // 2
#define HID_SWITCH_PRO_USB_BUTTON_UP_VALUE 0x02 // 2
#define HID_SWITCH_PRO_BT_BUTTON_A_VALUE 0x02000000
#define HID_SWITCH_PRO_BT_BUTTON_B_VALUE 0x01000000
#define HID_SWITCH_PRO_BT_BUTTON_X_VALUE 0x08000000
#define HID_SWITCH_PRO_BT_BUTTON_Y_VALUE 0x04000000
#define HID_SWITCH_PRO_BT_BUTTON_PLUS_VALUE 0x00020000
#define HID_SWITCH_PRO_BT_BUTTON_MINUS_VALUE 0x00010000
#define HID_SWITCH_PRO_BT_BUTTON_HOME_VALUE 0x00100000
#define HID_SWITCH_PRO_BT_BUTTON_R_VALUE 0x20000000
#define HID_SWITCH_PRO_BT_BUTTON_ZR_VALUE 0x80000000
#define HID_SWITCH_PRO_BT_BUTTON_STICK_R_VALUE 0x00080000
#define HID_SWITCH_PRO_BT_BUTTON_L_VALUE 0x10000000
#define HID_SWITCH_PRO_BT_BUTTON_ZL_VALUE 0x40000000
#define HID_SWITCH_PRO_BT_BUTTON_STICK_L_VALUE 0x00040000
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_MASK_VALUE 0x0F
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_N_VALUE 0x00 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_NE_VALUE 0x01 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_E_VALUE 0x02 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_SE_VALUE 0x03 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_S_VALUE 0x04 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_SW_VALUE 0x05 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_W_VALUE 0x06 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_NW_VALUE 0x07 // 2
#define HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL_VALUE 0x08 // 2
#define HID_SWITCH_PRO_BT_PAD_COUNT 1
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Keyboard (Full list is on: http://www.freebsddiary.org/APC/usb_hid_usages.php)
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_KEYBOARD_BUTTON_SHIFT 0x02
#define HID_KEYBOARD_BUTTON_A 0x04
#define HID_KEYBOARD_BUTTON_B 0x05
#define HID_KEYBOARD_BUTTON_C 0x06
#define HID_KEYBOARD_BUTTON_D 0x07
#define HID_KEYBOARD_BUTTON_E 0x08
#define HID_KEYBOARD_BUTTON_F 0x09
#define HID_KEYBOARD_BUTTON_G 0x0A
#define HID_KEYBOARD_BUTTON_H 0x0B
#define HID_KEYBOARD_BUTTON_I 0x0C
#define HID_KEYBOARD_BUTTON_J 0x0D
#define HID_KEYBOARD_BUTTON_K 0x0E
#define HID_KEYBOARD_BUTTON_L 0x0F
#define HID_KEYBOARD_BUTTON_M 0x10
#define HID_KEYBOARD_BUTTON_N 0x11
#define HID_KEYBOARD_BUTTON_O 0x12
#define HID_KEYBOARD_BUTTON_P 0x13
#define HID_KEYBOARD_BUTTON_Q 0x14
#define HID_KEYBOARD_BUTTON_R 0x15
#define HID_KEYBOARD_BUTTON_S 0x16
#define HID_KEYBOARD_BUTTON_T 0x17
#define HID_KEYBOARD_BUTTON_U 0x18
#define HID_KEYBOARD_BUTTON_V 0x19
#define HID_KEYBOARD_BUTTON_W 0x1A
#define HID_KEYBOARD_BUTTON_X 0x1B
#define HID_KEYBOARD_BUTTON_Y 0x1C
#define HID_KEYBOARD_BUTTON_Z 0x1D
#define HID_KEYBOARD_BUTTON_F1 0x3A
#define HID_KEYBOARD_BUTTON_F2 0x3B
#define HID_KEYBOARD_BUTTON_F3 0x3C
#define HID_KEYBOARD_BUTTON_F4 0x3D
#define HID_KEYBOARD_BUTTON_F5 0x3E
#define HID_KEYBOARD_BUTTON_F6 0x3F
#define HID_KEYBOARD_BUTTON_F7 0x40
#define HID_KEYBOARD_BUTTON_F8 0x41
#define HID_KEYBOARD_BUTTON_F9 0x42
#define HID_KEYBOARD_BUTTON_F10 0x43
#define HID_KEYBOARD_BUTTON_F11 0x44
#define HID_KEYBOARD_BUTTON_F12 0x45
#define HID_KEYBOARD_BUTTON_1 0x1E
#define HID_KEYBOARD_BUTTON_2 0x1F
#define HID_KEYBOARD_BUTTON_3 0x20
#define HID_KEYBOARD_BUTTON_4 0x21
#define HID_KEYBOARD_BUTTON_5 0x22
#define HID_KEYBOARD_BUTTON_6 0x23
#define HID_KEYBOARD_BUTTON_7 0x24
#define HID_KEYBOARD_BUTTON_8 0x25
#define HID_KEYBOARD_BUTTON_9 0x26
#define HID_KEYBOARD_BUTTON_0 0x27
#define HID_KEYBOARD_BUTTON_RETURN 0x28
#define HID_KEYBOARD_BUTTON_ESCAPE 0x29
#define HID_KEYBOARD_BUTTON_DELETE 0x2A
#define HID_KEYBOARD_BUTTON_TAB 0x2B
#define HID_KEYBOARD_BUTTON_SPACEBAR 0x2C
#define HID_KEYBOARD_BUTTON_CAPSLOCK 0x39
#define HID_KEYBOARD_BUTTON_PRINTSCREEN 0x46
#define HID_KEYBOARD_BUTTON_SCROLLLOCK 0x47
#define HID_KEYBOARD_BUTTON_PAUSE 0x48
#define HID_KEYBOARD_BUTTON_INSERT 0x49
#define HID_KEYBOARD_BUTTON_HOME 0x4A
#define HID_KEYBOARD_BUTTON_PAGEUP 0x4B
#define HID_KEYBOARD_BUTTON_PAGEDOWN 0x4E
#define HID_KEYBOARD_BUTTON_DELETEFORWARD 0x4C
#define HID_KEYBOARD_BUTTON_END 0x4D
#define HID_KEYBOARD_BUTTON_LEFT_CONTROL 0xE0
#define HID_KEYBOARD_BUTTON_LEFT_ALT 0xE2
#define HID_KEYBOARD_BUTTON_RIGHT_CONTROL 0xE4
#define HID_KEYBOARD_BUTTON_RIGHT_SHIFT 0xE5
#define HID_KEYBOARD_BUTTON_RIGHT_ALT 0xE6
#define HID_KEYBOARD_BUTTON_LEFT 0x50
#define HID_KEYBOARD_BUTTON_RIGHT 0x4f
#define HID_KEYBOARD_BUTTON_DOWN 0x51
#define HID_KEYBOARD_BUTTON_UP 0x52
#define HID_KEYBOARD_KEYPAD_BUTTON_1 0x59
#define HID_KEYBOARD_KEYPAD_BUTTON_2 0x5A
#define HID_KEYBOARD_KEYPAD_BUTTON_3 0x5B
#define HID_KEYBOARD_KEYPAD_BUTTON_4 0x5C
#define HID_KEYBOARD_KEYPAD_BUTTON_5 0x5D
#define HID_KEYBOARD_KEYPAD_BUTTON_6 0x5E
#define HID_KEYBOARD_KEYPAD_BUTTON_7 0x5F
#define HID_KEYBOARD_KEYPAD_BUTTON_8 0x60
#define HID_KEYBOARD_KEYPAD_BUTTON_9 0x61
#define HID_KEYBOARD_KEYPAD_BUTTON_0 0x62
#define HID_KEYBOARD_KEYPAD_BUTTON_NUMLOCK 0x53
#define HID_KEYBOARD_KEYPAD_BUTTON_MINUS 0x56
#define HID_KEYBOARD_KEYPAD_BUTTON_PLUS 0x57
#define HID_KEYBOARD_PAD_COUNT 1
#define HID_KEYBOARD_DATA_LENGTH 8
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Mouse
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
#define HID_MOUSE_BUTTON_LEFTCLICK 0x04
#define HID_MOUSE_BUTTON_RIGHTCLICK 0x05
#define HID_MOUSE_PAD_COUNT 1
#define HID_MOUSE_MODE_AIM 0x01
#define HID_MOUSE_MODE_TOUCH 0x02
#endif /* _CONTROLLER_PATCHER_DEFS_H_ */

View File

@ -0,0 +1,707 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "ControllerPatcherHID.hpp"
#include <malloc.h>
#include <stdio.h>
#include <string.h>
#include "wiiu/os.h"
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* public implementation for the network controller
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
s32 ControllerPatcherHID::externAttachDetachCallback(HIDDevice *p_device, u32 attach){
HIDClient client;
memset(&client,0,sizeof(client));
return AttachDetachCallback(&client,p_device,attach);
}
void ControllerPatcherHID::externHIDReadCallback(u32 handle, unsigned char *buf, u32 bytes_transfered, my_cb_user * usr){
HIDReadCallback(handle,buf,bytes_transfered,usr);
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* private implementation for the HID Api.
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
s32 ControllerPatcherHID::myAttachDetachCallback(HIDClient *p_client, HIDDevice *p_device, u32 attach){
return AttachDetachCallback(p_client,p_device,attach);
}
void ControllerPatcherHID::myHIDMouseReadCallback(u32 handle, s32 error, unsigned char *buf, u32 bytes_transfered, void *p_user){
if(error == 0){
my_cb_user *usr = (my_cb_user*)p_user;
u32 slot = 0;
if(usr->pad_slot < HID_MAX_PADS_COUNT){
slot = usr->pad_slot;
}
HID_Data * data_ptr = &(gHID_Devices[usr->slotdata.deviceslot].pad_data[slot]);
HID_Mouse_Data * cur_mouse_data = &data_ptr->data_union.mouse.cur_mouse_data;
data_ptr->type = DEVICE_TYPE_MOUSE;
//printf("%02X %02X %02X %02X %02X bytes_transfered: %d\n",buf[0],buf[1],buf[2],buf[3],buf[4],bytes_transfered);
if(buf[0] == 2 && bytes_transfered > 3){ // using the other mouse mode
buf +=1;
}
s8 x_value = 0;
s8 y_value = 0;
x_value = buf[1];
y_value = buf[2];
cur_mouse_data->X += x_value;
cur_mouse_data->deltaX = x_value;
cur_mouse_data->Y += y_value;
cur_mouse_data->deltaY = y_value;
cur_mouse_data->left_click = buf[0];
cur_mouse_data->right_click = buf[0]>>1;
if(cur_mouse_data->X < 0) cur_mouse_data->X = 0;
if(cur_mouse_data->X > 1280) cur_mouse_data->X = 1280;
if(cur_mouse_data->Y < 0) cur_mouse_data->Y = 0;
if(cur_mouse_data->Y > 720) cur_mouse_data->Y = 720;
cur_mouse_data->valuedChanged = 1;
//printf("%02X %02X %02X %02X %02X %02X %02X %02X %d = X: %d Y: %d \n",buf[0],buf[1],buf[2],buf[3],buf[4],buf[5],buf[6],buf[7],bytes_transfered,x_value,y_value);
HIDRead(handle, usr->buf, bytes_transfered, myHIDMouseReadCallback, usr);
}
}
void ControllerPatcherHID::myHIDReadCallback(u32 handle, s32 error, unsigned char *buf, u32 bytes_transfered, void *p_user){
if(error == 0 && p_user != NULL && gHIDAttached){
my_cb_user *usr = (my_cb_user*)p_user;
HIDReadCallback(handle,buf,bytes_transfered,usr);
if(usr->slotdata.hidmask == gHID_LIST_DS4){
wiiu_os_usleep(1000*2); //DS4 is way tooo fast. sleeping to reduce lag. (need to check the other pads)
}
HIDRead(handle, usr->buf, bytes_transfered, myHIDReadCallback, usr);
}
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Intern Callback actions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
s32 ControllerPatcherHID::AttachDetachCallback(HIDClient *p_client, HIDDevice *p_device, u32 attach){
if(attach){
printf("ControllerPatcherHID::AttachDetachCallback(line %d): vid %04x pid %04x connected\n",__LINE__, SWAP16(p_device->vid),SWAP16(p_device->pid));
if(HID_DEBUG){ printf("interface index %02x\n", p_device->interface_index);
printf("sub class %02x\n", p_device->sub_class);
printf("protocol %02x\n", p_device->protocol);
printf("max packet in %02x\n", p_device->max_packet_size_rx);
printf("max packet out %02x\n", p_device->max_packet_size_tx); }
}
if(!attach){
printf("ControllerPatcherHID::AttachDetachCallback(line %d): vid %04x pid %04x disconnected\n",__LINE__, SWAP16(p_device->vid),SWAP16(p_device->pid));
}
DeviceInfo device_info;
memset(&device_info,0,sizeof(DeviceInfo));
device_info.slotdata.deviceslot = -1;
device_info.vidpid.vid = SWAP16(p_device->vid);
device_info.vidpid.pid = SWAP16(p_device->pid);
HIDSlotData * slotdata = &(device_info.slotdata);
if ((p_device->sub_class == 1) && (p_device->protocol == 1)) { //Keyboard
slotdata->hidmask = gHID_LIST_KEYBOARD;
slotdata->deviceslot = gHID_SLOT_KEYBOARD;
//printf("Found Keyboard: device: %s slot: %d\n",byte_to_binary(device_info.slotdata.hidmask),device_info.slotdata.deviceslot);
}else if ((p_device->sub_class == 1) && (p_device->protocol == 2)){ // MOUSE
slotdata->hidmask = gHID_LIST_MOUSE;
slotdata->deviceslot = gMouseSlot;
//printf("Found Mouse: device: %s slot: %d\n",byte_to_binary(device_info.hid),device_info.slot);
}else{
s32 ret;
if((ret = ControllerPatcherUtils::getDeviceInfoFromVidPid(&device_info)) < 0){
printf("ControllerPatcherHID::AttachDetachCallback(line %d): ControllerPatcherUtils::getDeviceInfoFromVidPid(&device_info) failed %d \n",__LINE__,ret);
return HID_DEVICE_DETACH;
}else{
//printf("ControllerPatcherHID::AttachDetachCallback(line %d): ControllerPatcherUtils::getDeviceInfoFromVidPid(&device_info) success %d \n",__LINE__,ret);
}
}
if(slotdata->hidmask){
if(attach){
s32 bufSize = 64;
if(slotdata->hidmask != gHID_LIST_MOUSE && config_controller[slotdata->deviceslot][CONTRPS_BUF_SIZE][0] == CONTROLLER_PATCHER_VALUE_SET){
bufSize = config_controller[slotdata->deviceslot][CONTRPS_BUF_SIZE][1];
}
unsigned char *buf = (unsigned char *) memalign(64,bufSize);
memset(buf,0,bufSize);
my_cb_user *usr = (my_cb_user *) memalign(64,sizeof(my_cb_user));
usr->buf = buf;
usr->slotdata = device_info.slotdata;
usr->transfersize = p_device->max_packet_size_rx;
usr->handle = p_device->handle;
usr->vidpid = device_info.vidpid;
gHIDAttached |= slotdata->hidmask;
gHIDCurrentDevice |= slotdata->hidmask;
s32 pads_per_device = 1;
if(config_controller[slotdata->deviceslot][CONTRPS_PAD_COUNT][0] != CONTROLLER_PATCHER_INVALIDVALUE){
pads_per_device = config_controller[slotdata->deviceslot][CONTRPS_PAD_COUNT][1];
if(pads_per_device > HID_MAX_PADS_COUNT){//maximum of HID_MAX_PADS_COUNT
pads_per_device = HID_MAX_PADS_COUNT;
}
}
s32 pad_count = config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1];
if(pad_count > 0x0F) pad_count = 0; //???
s32 pad_slot = 0;
s32 failed = 1;
for(s32 i = 0;i<HID_MAX_PADS_COUNT;i += pads_per_device){
if(!(pad_count & (1 << i))){
failed = 0;
pad_count |= (1 << i);
pad_slot = i;
break;
}
}
if(failed){
printf("ControllerPatcherHID::AttachDetachCallback(line %d) error: I can only handle %d devices of the same type. Sorry \n",__LINE__,HID_MAX_PADS_COUNT);
if(buf){
free(buf);
buf = NULL;
}
if(usr){
free(usr);
usr = NULL;
}
return 0;
}
config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1] = pad_count;
DCFlushRange(&config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1],sizeof(config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1]));
DCInvalidateRange(&config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1],sizeof(config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1]));
usr->pads_per_device = pads_per_device;
usr->pad_slot = pad_slot;
for(s32 i = 0;i<pads_per_device;i++){
memset(&gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i],0,sizeof(HID_Data));
gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i].handle = p_device->handle;
//printf("ControllerPatcherHID::AttachDetachCallback(line %d): saved handle %d to slot %d and pad %d\n",__LINE__,p_device->handle,slotdata->deviceslot,pad_slot);
gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i].user_data = usr;
gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i].slotdata = device_info.slotdata;
DCFlushRange(&gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i],sizeof(HID_Data));
DCInvalidateRange(&gHID_Devices[slotdata->deviceslot].pad_data[pad_slot+i],sizeof(HID_Data));
}
for(s32 j = 0;j < pads_per_device; j++){
for(s32 i = 0;i < gHIDMaxDevices; i++){
if(connectionOrderHelper[i] == NULL){
connectionOrderHelper[i] = usr;
break;
}
}
}
if(HID_DEBUG){ printf("ControllerPatcherHID::AttachDetachCallback(line %d): Device successfully attached\n",__LINE__); }
if(slotdata->hidmask == gHID_LIST_GC){ // GC PAD
//The GC Adapter has all ports in one device. Set them all.
gHID_Devices[slotdata->deviceslot].pad_data[0].slotdata = device_info.slotdata;
gHID_Devices[slotdata->deviceslot].pad_data[1].slotdata = device_info.slotdata;
gHID_Devices[slotdata->deviceslot].pad_data[2].slotdata = device_info.slotdata;
gHID_Devices[slotdata->deviceslot].pad_data[3].slotdata = device_info.slotdata;
buf[0] = 0x13;
HIDWrite(p_device->handle, usr->buf, 1, NULL,NULL);
HIDRead(p_device->handle, usr->buf, usr->transfersize, myHIDReadCallback, usr);
}else if (slotdata->hidmask == gHID_LIST_MOUSE){
HIDSetProtocol(p_device->handle, p_device->interface_index, 0, 0, 0);
//HIDGetDescriptor(p_device->handle,0x22,0x00,0,my_buf,512,my_foo_cb,NULL);
HIDSetIdle(p_device->handle,p_device->interface_index,1,NULL,NULL);
gHID_Mouse_Mode = HID_MOUSE_MODE_AIM;
HIDRead(p_device->handle, buf, p_device->max_packet_size_rx, myHIDMouseReadCallback, usr);
}else if (slotdata->hidmask == gHID_LIST_SWITCH_PRO){
s32 read_result = HIDRead(p_device->handle, usr->buf, usr->transfersize, NULL, NULL);
if(read_result == 64){
if(usr->buf[01] == 0x01){ //We need to do the handshake
printf("ControllerPatcherHID::AttachDetachCallback(line %d): Switch Pro Controller handshake needed\n",__LINE__);
/**
Thanks to ShinyQuagsire23 for the values (https://github.com/shinyquagsire23/HID-Joy-Con-Whispering)
**/
//Get MAC
buf[0] = 0x80;
buf[1] = 0x01;
HIDWrite(p_device->handle, usr->buf, 2, NULL,NULL);
HIDRead(p_device->handle, usr->buf, usr->transfersize, NULL, NULL);
//Do handshake
buf[0] = 0x80;
buf[1] = 0x02;
HIDWrite(p_device->handle, usr->buf, 2, NULL,NULL);
HIDRead(p_device->handle, usr->buf, usr->transfersize, NULL, NULL);
//Talk over HID only.
buf[0] = 0x80;
buf[1] = 0x04;
HIDWrite(p_device->handle, usr->buf, 2, NULL,NULL);
HIDRead(p_device->handle, usr->buf, usr->transfersize, NULL, NULL);
}else{
printf("ControllerPatcherHID::AttachDetachCallback(line %d): Switch Pro Controller handshake already done\n",__LINE__);
}
HIDRead(p_device->handle, usr->buf, usr->transfersize, myHIDReadCallback, usr);
}
}else if (slotdata->hidmask == gHID_LIST_KEYBOARD){
HIDSetProtocol(p_device->handle, p_device->interface_index, 1, 0, 0);
HIDSetIdle(p_device->handle, p_device->interface_index, 0, 0, 0);
HIDRead(p_device->handle, buf, p_device->max_packet_size_rx, myHIDReadCallback, usr);
}else if (slotdata->hidmask == gHID_LIST_DS3){
HIDSetProtocol(p_device->handle, p_device->interface_index, 1, 0, 0);
HIDDS3Rumble(p_device->handle,usr,0);
buf[0] = 0x42; buf[1] = 0x0c; buf[2] = 0x00; buf[3] = 0x00;
HIDSetReport(p_device->handle, HID_REPORT_FEATURE, PS3_F4_REPORT_ID, buf, PS3_F4_REPORT_LEN, NULL, NULL);
HIDRead(p_device->handle, usr->buf, p_device->max_packet_size_rx, myHIDReadCallback, usr);
}else{
HIDRead(p_device->handle, usr->buf, p_device->max_packet_size_rx, myHIDReadCallback, usr);
}
return HID_DEVICE_ATTACH;
}else{
my_cb_user * user_data = NULL;
s32 founddata = 0;
for(s32 i = 0;i<HID_MAX_PADS_COUNT;i++){
if(gHID_Devices[slotdata->deviceslot].pad_data[i].handle == p_device->handle){
gHID_Devices[slotdata->deviceslot].pad_data[i].handle = 0;
DCFlushRange(&gHID_Devices[slotdata->deviceslot].pad_data[i].handle,sizeof(gHID_Devices[slotdata->deviceslot].pad_data[i].handle));
DCInvalidateRange(&gHID_Devices[slotdata->deviceslot].pad_data[i].handle,sizeof(gHID_Devices[slotdata->deviceslot].pad_data[i].handle));
user_data = (my_cb_user *) gHID_Devices[slotdata->deviceslot].pad_data[i].user_data;
founddata = 1;
break;
}
}
if(user_data){
for(s32 j = 0;j < user_data->pads_per_device; j++){
for(s32 i = 0;i < gHIDMaxDevices; i++){
if(connectionOrderHelper[i] == user_data){
connectionOrderHelper[i] = NULL;
break;
}
}
}
config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1] &= ~ (1 << user_data->pad_slot);
DCFlushRange(&config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1],sizeof(config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1]));
DCInvalidateRange(&config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1],sizeof(config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1]));
if(user_data->buf){
free(user_data->buf);
user_data->buf = NULL;
}
free(user_data);
user_data = NULL;
}else{
if(founddata){ printf("ControllerPatcherHID::AttachDetachCallback(line %d): user_data null. You may have a memory leak.\n",__LINE__); }
return HID_DEVICE_DETACH;
}
if(config_controller[slotdata->deviceslot][CONTRPS_CONNECTED_PADS][1] == 0){
gHIDAttached &= ~slotdata->hidmask;
gHIDCurrentDevice &= ~slotdata->hidmask;
DCFlushRange(&gHIDAttached,sizeof(gHIDAttached));
DCInvalidateRange(&gHIDAttached,sizeof(gHIDAttached));
DCFlushRange(&gHIDCurrentDevice,sizeof(gHIDCurrentDevice));
DCInvalidateRange(&gHIDCurrentDevice,sizeof(gHIDCurrentDevice));
if (slotdata->hidmask == gHID_LIST_MOUSE){
gHID_Mouse_Mode = HID_MOUSE_MODE_AIM;
}
}else{
if(HID_DEBUG){printf("ControllerPatcherHID::AttachDetachCallback(line %d): We still have pad for deviceslot %d connected.\n",__LINE__,slotdata->deviceslot); }
}
if(HID_DEBUG){printf("ControllerPatcherHID::AttachDetachCallback(line %d): Device successfully detached\n",__LINE__); }
}
}else{
printf("ControllerPatcherHID::AttachDetachCallback(line %d): HID-Device currently not supported! You can add support through config files\n",__LINE__);
}
return HID_DEVICE_DETACH;
}
void ControllerPatcherHID::HIDReadCallback(u32 handle, unsigned char *buf, u32 bytes_transfered, my_cb_user * usr){
ControllerPatcherUtils::doSampling(usr->slotdata.deviceslot,usr->pad_slot,false);
//printf("my_read_cbInternal: %d %08X %d\n",bytes_transfered,usr->slotdata.hidmask,usr->slotdata.deviceslot);
if(usr->slotdata.hidmask == gHID_LIST_GC){
HID_Data * data_ptr = NULL;
//Copy the data for all 4 pads
for(s32 i = 0;i<4;i++){
data_ptr = &(gHID_Devices[gHID_SLOT_GC].pad_data[i]);
memcpy(&(data_ptr->data_union.controller.last_hid_data[0]),&(data_ptr->data_union.controller.cur_hid_data[0]),10); //save last data.
memcpy(&(data_ptr->data_union.controller.cur_hid_data[0]),&buf[(i*9)+1],9); //save new data.
}
/*
s32 i = 0;
printf("GC1 %08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X ", buf[i*9+0],buf[i*9+1],buf[i*9+2],buf[i*9+3],buf[i*9+4],buf[i*9+5],buf[i*9+6],buf[i*9+7],buf[i*9+8]);i++;
printf("GC2 %08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X ", buf[i*9+0],buf[i*9+1],buf[i*9+2],buf[i*9+3],buf[i*9+4],buf[i*9+5],buf[i*9+6],buf[i*9+7],buf[i*9+8]);i++;
printf("GC3 %08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X ", buf[i*9+0],buf[i*9+1],buf[i*9+2],buf[i*9+3],buf[i*9+4],buf[i*9+5],buf[i*9+6],buf[i*9+7],buf[i*9+8]);i++;
printf("GC4 %08X: %02X %02X %02X %02X %02X %02X %02X %02X %02X \n", buf[i*9+0],buf[i*9+1],buf[i*9+2],buf[i*9+3],buf[i*9+4],buf[i*9+5],buf[i*9+6],buf[i*9+7],buf[i*9+8]);*/
HIDGCRumble(handle,usr);
}else if(usr->slotdata.hidmask != 0){
//Depending on how the switch pro controller is connected, it has a different data format. At first we had the Bluetooth version, so we need to convert
//the USB one into it now. (When it's connected via USB). The network client always sends the BT version, even if connected via USB to the PC.
if(usr->slotdata.hidmask == gHID_LIST_SWITCH_PRO && buf != NULL && bytes_transfered >= 0x20){
u8 buffer[0x13];
memcpy(buffer,buf+0x0D,0x013);
/**
Thanks to ShinyQuagsire23 for the values (https://github.com/shinyquagsire23/HID-Joy-Con-Whispering)
**/
buf[0] = 0x80;
buf[1] = 0x92;
buf[2] = 0x00;
buf[3] = 0x01;
buf[4] = 0x00;
buf[5] = 0x00;
buf[6] = 0x00;
buf[7] = 0x00;
buf[8] = 0x1F;
//We want to get the next input!
s32 res = HIDWrite(handle, buf, 9, NULL,NULL);
if(res == 9){ //Check if it's the USB data format.
if(buffer[1] == 0) return;
//Converting the buttons
u32 buttons = (((u32*)(buffer))[0]) & 0xFFFFFF00;
u32 newButtons = 0;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_A_VALUE) == HID_SWITCH_PRO_USB_BUTTON_A_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_A_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_B_VALUE) == HID_SWITCH_PRO_USB_BUTTON_B_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_B_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_X_VALUE) == HID_SWITCH_PRO_USB_BUTTON_X_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_X_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_Y_VALUE) == HID_SWITCH_PRO_USB_BUTTON_Y_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_Y_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_PLUS_VALUE) == HID_SWITCH_PRO_USB_BUTTON_PLUS_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_PLUS_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_MINUS_VALUE) == HID_SWITCH_PRO_USB_BUTTON_MINUS_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_MINUS_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_HOME_VALUE) == HID_SWITCH_PRO_USB_BUTTON_HOME_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_HOME_VALUE;
//if((buttons & SWITCH_PRO_USB_BUTTON_SCREENSHOT) == HID_SWITCH_PRO_USB_BUTTON_SCREENSHOT) newButtons |= HID_SWITCH_PRO_BT_BUTTON_SCREENSHOT;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_R_VALUE) == HID_SWITCH_PRO_USB_BUTTON_R_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_R_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_ZR_VALUE) == HID_SWITCH_PRO_USB_BUTTON_ZR_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_ZR_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_STICK_R_VALUE) == HID_SWITCH_PRO_USB_BUTTON_STICK_R_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_STICK_R_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_L_VALUE) == HID_SWITCH_PRO_USB_BUTTON_L_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_L_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_ZL_VALUE) == HID_SWITCH_PRO_USB_BUTTON_ZL_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_ZL_VALUE;
if((buttons & HID_SWITCH_PRO_USB_BUTTON_STICK_L_VALUE) == HID_SWITCH_PRO_USB_BUTTON_STICK_L_VALUE) newButtons |= HID_SWITCH_PRO_BT_BUTTON_STICK_L_VALUE;
u8 dpad = buffer[2];
u8 dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL_VALUE;
//Converting the DPAD
if(((dpad & HID_SWITCH_PRO_USB_BUTTON_UP_VALUE) == HID_SWITCH_PRO_USB_BUTTON_UP_VALUE) &&
((dpad & HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE)){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_NE_VALUE;
}else if(((dpad & HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE) == HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE) &&
((dpad & HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE)){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_SE_VALUE;
}else if(((dpad & HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE) == HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE) &&
((dpad & HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE)){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_SW_VALUE;
}else if(((dpad & HID_SWITCH_PRO_USB_BUTTON_UP_VALUE) == HID_SWITCH_PRO_USB_BUTTON_UP_VALUE) &&
((dpad & HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE)){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_NW_VALUE;
}else if((dpad & HID_SWITCH_PRO_USB_BUTTON_UP_VALUE) == HID_SWITCH_PRO_USB_BUTTON_UP_VALUE){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_N_VALUE;
}else if((dpad & HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_RIGHT_VALUE){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_E_VALUE;
}else if((dpad & HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE) == HID_SWITCH_PRO_USB_BUTTON_DOWN_VALUE){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_S_VALUE;
}else if((dpad & HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE) == HID_SWITCH_PRO_USB_BUTTON_LEFT_VALUE){
dpadResult = HID_SWITCH_PRO_BT_BUTTON_DPAD_W_VALUE;
}
//Converting the stick data
u8 LX = (u8) ((u16) ((buffer[0x04] << 8 &0xFF00) | (((u16)buffer[0x03])&0xFF)) >> 0x04);
u8 LY = (u8)((buffer[0x05] *-1));
u8 RX = (u8) ((u16) ((buffer[0x07] << 8 &0xFF00) | (((u16)buffer[0x06])&0xFF)) >> 0x04);
u8 RY = (u8)((buffer[0x08] *-1));
buf[0] = (newButtons >> 24) & 0xFF;
buf[1] = (newButtons >> 16) & 0xFF;
buf[2] |= dpadResult;
buf[4] = LX;
buf[6] = LY;
buf[8] = RX;
buf[10] = RY;
}
}
s32 dsize = (HID_MAX_DATA_LENGTH_PER_PAD > bytes_transfered)? bytes_transfered : HID_MAX_DATA_LENGTH_PER_PAD;
s32 skip = 0;
//Input filter
if( config_controller[usr->slotdata.deviceslot][CONTRPS_INPUT_FILTER][0] != CONTROLLER_PATCHER_INVALIDVALUE){
if(buf[config_controller[usr->slotdata.deviceslot][CONTRPS_INPUT_FILTER][0]] != config_controller[usr->slotdata.deviceslot][CONTRPS_INPUT_FILTER][1]){
skip = 1;
}
}
if(!skip){
u32 slot = 0;
if(usr->pad_slot < HID_MAX_PADS_COUNT){
slot = usr->pad_slot;
}
slot += ControllerPatcherUtils::getPadSlotInAdapter(usr->slotdata.deviceslot,buf); // If the controller has multiple slots, we need to use the right one.
HID_Data * data_ptr = &(gHID_Devices[usr->slotdata.deviceslot].pad_data[slot]);
memcpy(&(data_ptr->data_union.controller.last_hid_data[0]),&(data_ptr->data_union.controller.cur_hid_data[0]),dsize); // save the last data.
memcpy(&(data_ptr->data_union.controller.cur_hid_data[0]),&buf[0],dsize); // save the new data.
DCFlushRange(&gHID_Devices[usr->slotdata.deviceslot].pad_data[slot],sizeof(HID_Data));
data_ptr = &(gHID_Devices[usr->slotdata.deviceslot].pad_data[slot]);
HIDRumble(handle,usr,slot);
}
}
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Other functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherHID::setVPADControllerData(VPADStatus * buffer,std::vector<HID_Data *>& data){
if(buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
HID_Data * data_cur;
s32 buttons_hold;
for(u32 i = 0;i<data.size();i++){
data_cur = data[i];
if(data_cur->slotdata.hidmask & gHID_LIST_MOUSE){ //Reset the input when we have no new inputs
HID_Mouse_Data * mouse_data = &data_cur->data_union.mouse.cur_mouse_data;
if(mouse_data->valuedChanged == 1){ //Fix for the mouse cursor
mouse_data->valuedChanged = 0;
}else{
mouse_data->deltaX = 0;
mouse_data->deltaY = 0;
}
}
buttons_hold = 0;
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_A);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_B);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_X);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_Y);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_LEFT);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_RIGHT);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_DOWN);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_UP);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_MINUS);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_L);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_R);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_PLUS);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_ZL);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_ZR);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_HOME);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_STICK_L);
ControllerPatcherUtils::getButtonPressed(data_cur,&buttons_hold,VPAD_BUTTON_STICK_R);
u32 last_emulate_stick = (data_cur->last_buttons) & VPAD_MASK_EMULATED_STICKS; // We should only need the emulated stick data.
s32 last_realbuttons = (data_cur->last_buttons) & VPAD_MASK_BUTTONS;
buffer->hold |= buttons_hold;
buffer->trigger |= (buttons_hold & (~last_realbuttons));
buffer->release |= (last_realbuttons & (~buttons_hold));
ControllerPatcherUtils::convertAnalogSticks(data_cur,buffer);
ControllerPatcherUtils::setEmulatedSticks(buffer,&last_emulate_stick);
ControllerPatcherUtils::checkAndSetMouseMode(data_cur);
ControllerPatcherUtils::setTouch(data_cur,buffer);
data_cur->last_buttons = buttons_hold & VPAD_MASK_BUTTONS;
data_cur->last_buttons |= last_emulate_stick;
}
// Caculates a valid stick position
if(data.size() > 0){
ControllerPatcherUtils::normalizeStickValues(&buffer->leftStick);
ControllerPatcherUtils::normalizeStickValues(&buffer->rightStick);
}
return CONTROLLER_PATCHER_ERROR_NONE;
}
std::vector<HID_Data *> ControllerPatcherHID::getHIDDataAll(){
u32 hid = gHIDCurrentDevice;
std::vector<HID_Data *> data_list;
for(s32 i = 0;i < gHIDMaxDevices;i++){
if((hid & (1 << i)) != 0){
u32 cur_hidmask = config_controller_hidmask[i];
for(s32 pad = 0; pad < HID_MAX_PADS_COUNT; pad++){
s32 res;
HID_Data * new_data = NULL;
if((res = ControllerPatcherHID::getHIDData(cur_hidmask,pad,&new_data)) < 0){ // Checks if the pad is invalid.
//printf("ControllerPatcherHID::getHIDDataAll(line %d): error: Error getting the HID data from HID(%s) CHAN(). Error %d\n",__LINE__,CPStringTools::byte_to_binary(cur_hidmask),pad,res);
continue;
}
if(new_data != NULL) data_list.push_back(new_data);
}
}
}
return data_list;
}
/*
The slotdata in the HID_Data pointer is empty. We need to provide the hidmask via the parameter
*/
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherHID::getHIDData(u32 hidmask, s32 pad, HID_Data ** data){
if(data == NULL) return CONTROLLER_PATCHER_ERROR_INVALID_BUFFER;
if(!(hidmask & gHIDCurrentDevice)) return CONTROLLER_PATCHER_ERROR_HID_NOT_CONNECTED;
if(pad < 0 && pad > 3) return CONTROLLER_PATCHER_ERROR_INVALID_CHAN;
s32 device_slot = ControllerPatcherUtils::getDeviceSlot(hidmask);
if(device_slot < 0){
return CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND;
}
s32 real_pad = pad;
if((device_slot != gHID_SLOT_GC) && config_controller[device_slot][CONTRPS_PAD_COUNT][0] != CONTROLLER_PATCHER_INVALIDVALUE){
s32 pad_count = config_controller[device_slot][CONTRPS_PAD_COUNT][1];
if(pad_count > HID_MAX_PADS_COUNT) pad_count = HID_MAX_PADS_COUNT;
pad = (pad/(pad_count))*pad_count;
}
s32 result = ControllerPatcherUtils::checkActivePad(hidmask,pad);
if(result < 0){ //Not pad connected to adapter
return CONTROLLER_PATCHER_ERROR_NO_PAD_CONNECTED;
}
*data = &gHID_Devices[device_slot].pad_data[real_pad];
return CONTROLLER_PATCHER_ERROR_NONE;
}
void ControllerPatcherHID::HIDGCRumble(u32 handle,my_cb_user *usr){
if(usr == NULL) return;
if(!ControllerPatcher::isRumbleActivated()) return;
s32 rumblechanged = 0;
for(s32 i = 0;i<HID_GC_PAD_COUNT;i++){
HID_Data * data_ptr = &(gHID_Devices[usr->slotdata.deviceslot].pad_data[i]);
if(data_ptr->rumbleActive != usr->rumblestatus[i]){
rumblechanged = 1;
}
usr->rumblestatus[i] = data_ptr->rumbleActive;
usr->buf[i+1] = usr->rumblestatus[i];
}
usr->forceRumbleInTicks[0]--;
if(rumblechanged || usr->forceRumbleInTicks[0] <= 0){
usr->buf[0] = 0x11;
HIDWrite(handle, usr->buf, 5, NULL, NULL);
usr->forceRumbleInTicks[0] = 10;
}
}
void ControllerPatcherHID::HIDRumble(u32 handle,my_cb_user *usr,u32 pad){
if(usr == NULL || pad > HID_MAX_PADS_COUNT) return;
if(!ControllerPatcher::isRumbleActivated()) return;
s32 rumblechanged = 0;
HID_Data * data_ptr = &(gHID_Devices[usr->slotdata.deviceslot].pad_data[pad]);
if(data_ptr->rumbleActive != usr->rumblestatus[pad]){
usr->rumblestatus[pad] = data_ptr->rumbleActive;
rumblechanged = 1;
}
usr->forceRumbleInTicks[pad]--;
if(rumblechanged || usr->forceRumbleInTicks[pad] <= 0){
//printf("Rumble: %d %d\n",usr->rumblestatus[pad],usr->rumbleForce[pad]);
//Seding to the network client!
char bytes[6];
s32 i = 0;
bytes[i++] = 0x01;
bytes[i++] = (handle >> 24) & 0xFF;
bytes[i++] = (handle >> 16) & 0xFF;
bytes[i++] = (handle >> 8) & 0xFF;
bytes[i++] = handle & 0xFF;
bytes[i++] = usr->rumblestatus[pad];
UDPClient * instance = UDPClient::getInstance();
if(instance != NULL){
instance->sendData(bytes,6);
}
if(usr->slotdata.hidmask == gHID_LIST_DS3){
HIDDS3Rumble(handle,usr,usr->rumblestatus[pad]);
}else{
// Not implemented for other devices =(
}
usr->forceRumbleInTicks[pad] = 10;
}
}
static u8 ds3_rumble_Report[48] =
{
0x00, 0xFF, 0x00, 0xFF, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0xFF, 0x27, 0x10, 0x00, 0x32,
0xFF, 0x27, 0x10, 0x00, 0x32,
0xFF, 0x27, 0x10, 0x00, 0x32,
0xFF, 0x27, 0x10, 0x00, 0x32,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00, 0x00, 0x00,
0x00, 0x00, 0x00,
};
void ControllerPatcherHID::HIDDS3Rumble(u32 handle,my_cb_user *usr,s32 rumble){
memcpy(usr->buf, ds3_rumble_Report, 48);
if (rumble) {
usr->buf[2] = 0x01;
usr->buf[4] = 0xff;
}
HIDSetReport(handle, HID_REPORT_OUTPUT, PS3_01_REPORT_ID, usr->buf, 48, NULL, NULL);
}

View File

@ -0,0 +1,74 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* @file ControllerPatcherHID.hpp
* @author Maschell
* @date 25 Aug 2016
* \brief This files contain useful all function for the direct HID Access
*
* @see https://github.com/Maschell/controller_patcher
*/
#ifndef _CONTROLLER_PATCHER_HID_H_
#define _CONTROLLER_PATCHER_HID_H_
#include <vector>
#include "wiiu/syshid.h"
#include "wiiu/vpad.h"
#include "../ControllerPatcher.hpp"
#define SWAP16(x) ((x>>8) | ((x&0xFF)<<8))
#define SWAP8(x) ((x>>4) | ((x&0xF)<<4))
class ControllerPatcherHID{
friend class ControllerPatcher;
friend class ControllerPatcherUtils;
public:
static s32 externAttachDetachCallback(HIDDevice *p_device, u32 attach);
static void externHIDReadCallback(u32 handle, unsigned char *buf, u32 bytes_transfered, my_cb_user * usr);
private:
static CONTROLLER_PATCHER_RESULT_OR_ERROR setVPADControllerData(VPADStatus * buffer,std::vector<HID_Data *>& data);
static std::vector<HID_Data *> getHIDDataAll();
static CONTROLLER_PATCHER_RESULT_OR_ERROR getHIDData(u32 hidmask, s32 pad, HID_Data ** data);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Rumble
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
static void HIDRumble(u32 handle,my_cb_user *usr,u32 pad);
static void HIDGCRumble(u32 handle,my_cb_user *usr);
static void HIDDS3Rumble(u32 handle,my_cb_user *usr,s32 rumble);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* HID Callbacks
*--------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
static s32 myAttachDetachCallback(HIDClient *p_client, HIDDevice *p_device, u32 attach);
static void myHIDMouseReadCallback(u32 handle, s32 error, unsigned char *buf, u32 bytes_transfered, void *p_user);
static void myHIDReadCallback(u32 handle, s32 error, unsigned char *buf, u32 bytes_transfered, void *p_user);
static s32 AttachDetachCallback(HIDClient *p_client, HIDDevice *p_device, u32 attach);
static void HIDReadCallback(u32 handle, unsigned char *buf, u32 bytes_transfered, my_cb_user * usr);
};
#endif /* _CONTROLLER_PATCHER_HID_H_ */

View File

@ -0,0 +1,935 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "ControllerPatcherUtils.hpp"
#include <math.h>
#include <string.h>
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getDataByHandle(s32 handle, my_cb_user ** data){
for(s32 i = 0;i< gHIDMaxDevices;i++){
for(s32 j = 0;j<4;j++){
//printf("%d %d %d %d\n",i,j,gHID_Devices[i].pad_data[j].handle,(u32)handle);
if(gHID_Devices[i].pad_data[j].handle == (u32)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, s32 * buttons_hold, s32 VPADButton){
if(data == NULL || buttons_hold == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 deviceslot = data->slotdata.deviceslot;
s32 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;
}
u8 * cur_data = &data->data_union.controller.cur_hid_data[0];
if(cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 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){
u8 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
u8 dir1_0 = 0,dir1_1 = 0;
u8 dir2_0 = 0,dir2_1 = 0;
u8 dir3_0 = 0,dir3_1 = 0;
u8 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){
s32 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){
s32 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{
//printf("Invalid data! deviceslot(slot): %d config: %d\n",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,s32 cur_config){
if(data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
u8 * cur_data = &data->data_union.controller.cur_hid_data[0];
if(cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
u32 hidmask = data->slotdata.hidmask;
s32 deviceslot = data->slotdata.deviceslot;
s32 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,s32 key){
if(keyboardData == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
for(s32 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,u32 VPADButton, s32 CONTRPS_SLOT){
if(old_buffer == NULL || new_buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
u32 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,u32 oldVPADButton,u32 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(u32 hidmask,s32 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{
s32 deviceslot = getDeviceSlot(hidmask);
if(deviceslot < 0 ) return CONTROLLER_PATCHER_ERROR_DEVICE_SLOT_NOT_FOUND;
s32 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(u32 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
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::normalizeStickValues(VPADVec2D * stick){
if(stick == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
f32 max_val = 0.0f;
f32 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;
}
f32 ControllerPatcherUtils::convertAnalogValue(u8 value, u8 default_val, u8 min, u8 max, u8 invert,u8 deadzone){
s8 new_value = (s8)(value - default_val);
u8 range = 0;
if(value >= max){
if(invert == 0x01) return -1.0f;
return 1.0f;
}else if(value <= min){
if(invert == 0x01) return 1.0f;
return -1.0f;
}
if((value-deadzone) > default_val){
new_value -= deadzone;
range = (max - (default_val + deadzone));
}else if((value+deadzone) < default_val){
new_value += deadzone;
range = ((default_val - deadzone) - min);
}else{
return 0.0f;
}
if(invert != 0x01){
return (new_value / (1.0f*range));
}else{
return -1.0f*(new_value / (1.0f*range));
}
}
VPADVec2D ControllerPatcherUtils::getAnalogValueByButtons(u8 stick_values){
VPADVec2D stick;
stick.x = 0.0f;
stick.y = 0.0f;
u8 up = ((stick_values & STICK_VALUE_UP) == STICK_VALUE_UP);
u8 down = ((stick_values & STICK_VALUE_DOWN) == STICK_VALUE_DOWN);
u8 left = ((stick_values & STICK_VALUE_LEFT) == STICK_VALUE_LEFT);
u8 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;
s32 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;
f32 x_value = ms_data->deltaX/10.0f;
f32 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{
u8 * cur_data = &data->data_union.controller.cur_hid_data[0];
if(cur_data == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 deadzone = 0;
if( config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X][0] != CONTROLLER_PATCHER_INVALIDVALUE){
if(config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE][0] == CONTROLLER_PATCHER_VALUE_SET){
deadzone = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE][1];
}
buffer->leftStick.x += convertAnalogValue(cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X][0]],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX][0],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT][1],
deadzone);
}
if( config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y][0] != CONTROLLER_PATCHER_INVALIDVALUE){
deadzone = 0;
if(config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y_DEADZONE][0] == CONTROLLER_PATCHER_VALUE_SET){
deadzone = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y_DEADZONE][1];
}
buffer->leftStick.y += convertAnalogValue(cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y][0]],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX][0],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y_MINMAX][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y_INVERT][1],
deadzone);
}
if( config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X][0] != CONTROLLER_PATCHER_INVALIDVALUE){
deadzone = 0;
if(config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X_DEADZONE][0] == CONTROLLER_PATCHER_VALUE_SET){
deadzone = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X_DEADZONE][1];
}
buffer->rightStick.x += convertAnalogValue(cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X][0]],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX][0],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X_MINMAX][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X_INVERT][1],
deadzone);
}
if( config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y][0] != CONTROLLER_PATCHER_INVALIDVALUE){
deadzone = 0;
if(config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y_DEADZONE][0] == CONTROLLER_PATCHER_VALUE_SET){
deadzone = config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y_DEADZONE][1];
}
buffer->rightStick.y += convertAnalogValue(cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y][0]],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX][0],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y_MINMAX][1],
config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y_INVERT][1],
deadzone);
}
u8 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;
}
/*printf("LX %f(%02X) LY %f(%02X) RX %f(%02X) RY %f(%02X)\n",buffer->leftStick.x,cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_X][0]],
buffer->leftStick.y,cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_L_STICK_Y][0]],
buffer->rightStick.x,cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_X][0]],
buffer->rightStick.y,cur_data[config_controller[deviceslot][CONTRPS_VPAD_BUTTON_R_STICK_Y][0]]);*/
}
return CONTROLLER_PATCHER_ERROR_NONE;
}
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::setEmulatedSticks(VPADStatus * buffer, u32 * last_emulatedSticks){
if(buffer == NULL || last_emulatedSticks == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
u32 emulatedSticks = 0;
s32 l_x_full = (buffer->leftStick.x > 0.5f || buffer->leftStick.x < -0.5f)? 1:0;
s32 l_y_full = (buffer->leftStick.y > 0.5f || buffer->leftStick.y < -0.5f)? 1:0;
s32 r_x_full = (buffer->rightStick.x > 0.5f || buffer->rightStick.x < -0.5f)? 1:0;
s32 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){
s32 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;
s32 x_mouse = 80 + ((int)(((ms_data->X)*1.0f/1280.0)*3890.0f));
s32 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){
u32 hidmask = data->slotdata.hidmask;
if(hidmask & gHID_LIST_KEYBOARD){
u8 * cur_data = &data->data_union.controller.cur_hid_data[0];
u8 * 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))){
if(gHID_Mouse_Mode == HID_MOUSE_MODE_AIM){
gHID_Mouse_Mode = HID_MOUSE_MODE_TOUCH;
if(HID_DEBUG){ printf("ControllerPatcherUtils::checkAndSetMouseMode(line %d): Mouse mode changed! to touch \n",__LINE__); }
}else if(gHID_Mouse_Mode == HID_MOUSE_MODE_TOUCH){
if(HID_DEBUG){ printf("ControllerPatcherUtils::checkAndSetMouseMode(line %d): Mouse mode changed! to aim \n",__LINE__); }
gHID_Mouse_Mode = HID_MOUSE_MODE_AIM;
}
}
}
return CONTROLLER_PATCHER_ERROR_NONE;
}
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Other functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::translateToPro(VPADStatus * vpad_buffer,KPADData * pro_buffer,u32 * lastButtonsPressesPRO){
if(vpad_buffer == NULL || pro_buffer == NULL || lastButtonsPressesPRO == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 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.lstick_x = vpad_buffer->leftStick.x;
pro_buffer->pro.lstick_x = vpad_buffer->leftStick.y;
pro_buffer->pro.rstick_x = vpad_buffer->rightStick.x;
pro_buffer->pro.rstick_x = 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->wpad_error = 0x00;
pro_buffer->device_type = 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,WPADReadData * pro_buffer){
if(vpad_buffer == NULL || pro_buffer == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 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->l_stick_x = (s16) (vpad_buffer->leftStick.x * 950.0f);
pro_buffer->l_stick_y = (s16) (vpad_buffer->leftStick.y * 950.0f);
pro_buffer->r_stick_x = (s16) (vpad_buffer->rightStick.x * 950.0f);
pro_buffer->r_stick_y = (s16) (vpad_buffer->rightStick.y * 950.0f);
pro_buffer->buttons = buttons_hold;
pro_buffer->fmt = WPAD_FMT_PRO_CONTROLLER;
pro_buffer->err = 0x00;
pro_buffer->dev = WPAD_EXT_PRO_CONTROLLER;
return CONTROLLER_PATCHER_ERROR_NONE;
}
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::translateToVPAD(VPADStatus * vpad_buffer,KPADData * pro_buffer,u32 * lastButtonsPressesVPAD){
if(vpad_buffer == NULL || pro_buffer == NULL || lastButtonsPressesVPAD == NULL) return CONTROLLER_PATCHER_ERROR_NULL_POINTER;
s32 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.lstick_x;
vpad_buffer->leftStick.y = pro_buffer->pro.lstick_x;
vpad_buffer->rightStick.x = pro_buffer->pro.rstick_x;
vpad_buffer->rightStick.y = pro_buffer->pro.rstick_x;
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(s32 deviceslot,s32 CONTRPS_slot,s32 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(u8 * dest, u8 first, u8 second){
dest[0] = first;
dest[1] = second;
}
CONTROLLER_PATCHER_RESULT_OR_ERROR ControllerPatcherUtils::getDeviceSlot(u32 hidmask){
for(s32 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(s32 i = 0;i< gHIDMaxDevices;i++){
u16 my_vid = config_controller[i][CONTRPS_VID][0] * 0x100 + config_controller[i][CONTRPS_VID][1];
u16 my_pid = config_controller[i][CONTRPS_PID][0] * 0x100 + config_controller[i][CONTRPS_PID][1];
//printf("info->vidpid.vid (%04X) == my_vid (%04X) && info->vidpid.pid (%04X) == my_pid (%04X)\n",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;
//printf("Found device: device: %s slot: %d\n",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(s32 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;
}
s32 ControllerPatcherUtils::getPadSlotInAdapter(s32 deviceslot, u8 * input_data){
s32 slot_incr = 0;
if(config_controller[deviceslot][CONTRPS_PAD_COUNT][0] != CONTROLLER_PATCHER_INVALIDVALUE){
s32 pad_count = config_controller[deviceslot][CONTRPS_PAD_COUNT][1];
if(pad_count > HID_MAX_PADS_COUNT){
pad_count = HID_MAX_PADS_COUNT;
}
for(s32 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(u16 deviceslot,u8 padslot = 0,bool ignorePadSlot = false){
if(gSamplingCallback != NULL){
for(int i=0;i<4;i++){
ControllerMappingPADInfo * padinfo = &gControllerMapping.proController[i].pad_infos[0];
if(padinfo->active){
DeviceInfo device_info;
memset(&device_info,0,sizeof(device_info));
device_info.vidpid = padinfo->vidpid;
s32 res = -1;
if((res = ControllerPatcherUtils::getDeviceInfoFromVidPid(&device_info)) >= 0){
if(!ignorePadSlot){
s32 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(i);
}
}
}else{
gSamplingCallback(i);
}
}
}
}
}
return CONTROLLER_PATCHER_ERROR_NONE;
}

View File

@ -0,0 +1,320 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
/**
* @file ControllerPatcherUtil.hpp
* @author Maschell
* @date 25 Aug 2016
* \brief This files contain useful functions for the controller patcher engine
*
* @see https://github.com/Maschell/controller_patcher
*/
#ifndef _CONTROLLER_PATCHER_UTIL_H_
#define _CONTROLLER_PATCHER_UTIL_H_
#include "wiiu/vpad.h"
#include "wiiu/kpad.h"
#include "../ControllerPatcher.hpp"
class ControllerPatcherUtils{
//give the other classes access to the private functions.
friend class ControllerPatcher;
friend class ControllerPatcherHID;
friend class ConfigParser;
public:
/**
\brief Returns the device slot for a given HID-Mask.
\param hidmask Given HID-Mask
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful. The returned value is the deviceslot of the given HID-Mask
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getDeviceSlot(u32 hidmask);
/**
\brief Returns the device slot for a given HID-Mask.
\param handle Given HID-handle
\param data Given my_cb_user ** where the result will be stored. Valid pointer when result is >= 0.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful. The actual result will be store in the given my_cb_user **.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getDataByHandle(s32 handle, my_cb_user ** data);
/**
\brief Returns the VID/PID for the given device slot.
\param deviceslot Given device slot
\param vidpid Pointer to the DeviceVIDPIDInfo struct where the result will be stored.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful. The actual result will be store in the given DeviceVIDPIDInfo *.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getVIDPIDbyDeviceSlot(s32 deviceslot, DeviceVIDPIDInfo * vidpid);
/** \brief Set the VPAD data for a given KPAD data.
*
* \param vpad_buffer VPADStatus* A pointer to the VPAD Data where the result will be stored.
* \param pro_buffer KPADData* A pointer to the given KPADData data.
* \param lastButtonsPressesPRO u32* A pointer to the button presses of the previous call. Will be updated while calling.
* \return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR translateToVPAD(VPADStatus * vpad_buffer,KPADData * pro_buffer,u32 * lastButtonsPressesVPAD);
private:
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Analyse inputs
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/** \brief Checks if a the given @p VPADButton was pressed in the given HID @data. When it was pressed, the result will be set the in given @p buttons_hold
*
* \param data Pointer to the HID_Data from where the input is read.
* \param buttons_hold Pointer to the u32 where the result will be written to.
* \param VPADButton The button that will be checked
* \return When the functions failed result < 0 is returned.If the result is >= 0 the function was successful.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getButtonPressed(HID_Data * data, s32 * buttons_hold, s32 VPADButton);
/** \brief Checks if a given value is set in the HID_DATA given the data in the slot number provided by cur_config.
*
* \param data Pointer to the HID_Data from where the input is read.
* \param cur_config slot of the configuration array which will be checked.
* \return When the functions failed result < 0 is returned. If the value is set, 1 will be returned. Otherwise 0.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR isValueSet(HID_Data * data,s32 cur_config);
/** \brief Checks if a given key in the keyboard data is pressed.
*
* \param keyboardData A pointer to the keyboard data.
* \param key A pointer to the keyboard data.
* \return When the functions failed result < 0 is returned. If the key is active pressed, 1 is returned.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR isInKeyboardData(unsigned char * keyboardData,s32 key);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Utils for setting the Button data
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/** \brief Checks if a @p VPADButton (VPAD_BUTTON_XXX) is set in the given @p CONTRPS_SLOT (usually the one for buttons remapping) of the GamePad. When its set it'll be
* set for the corresponding Button (aka button remapping). When the @p CONTRPS_SLOT is not valid, the normal buttons layout will be used.
*
* \param old_buffer A pointer to a VPADStatus struct from which will be read.
* \param new_buffer A pointer to a VPADStatus struct where the result will be written.
* \param VPADButton The buttons that will be may replaced
* \param CONTRPS_SLOT The CONTRPS_SLOT where the VPAD_Buttons we want to use instead of the parameter "VPADButton" could be saved.
* \return When the functions failed result < 0 is returned. If the pad is active/connected, 1 is returned.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setButtonRemappingData(VPADStatus * old_buffer, VPADStatus * new_buffer,u32 VPADButton, s32 CONTRPS_SLOT);
/**
\brief Checks if a given button (oldVPADButton) is set in a given VPADStatus struct (old_buffer). If its set, it will set an other
button (newVPADButton) to the second given VPADStatus struct (new_buffer)
\param old_buffer A pointer to a VPADStatus struct from which will be read.
\param new_buffer A pointer to a VPADStatus struct where the result will be written.
\param oldVPADButton The buttons that need to be set in the first VPADStatus
\param newVPADButton The buttons that will be set in the second VPADStatus, when the oldVPADButton is pressed in the first buffer.
\return When the functions failed result < 0 is returned. If the pad is active/connected, 1 is returned.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setButtonData(VPADStatus * old_buffer, VPADStatus * new_buffer,u32 oldVPADButton,u32 newVPADButton);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Pad Status functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/**
\brief Checks if a controller is attached for the given HID-Mask and pad.
\param hidmask Bit-Mask of the target hid-device.
\param pad Defines for which pad the connection will be checked.
\return When the functions failed result < 0 is returned. If the pad is active/connected, 1 is returned.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR checkActivePad(u32 hidmask,s32 pad);
/**
\brief Returns the first active pad of devices with the given HID-Mask. Currently only implemented for the GC-Adapter. Every other pad will always return 0.
\param hidmask Bit-Mask of the target hid-device.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful. The returned value is fist active pad.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getActivePad(u32 hidmask);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Stick functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/**
\brief Normalizes the stick to valid values.
\param stick Pointer to the stick that will be normalized
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR normalizeStickValues(VPADVec2D * stick);
/**
\brief Converts the digital absolute stick data into a float value. It also applies the deadzones, and can invert the result.
\param value Given current value of the stick axis
\param default_val Value in neutral axis-position
\param min Value that represents -1.0f
\param max Value that represents 1.0f
\param invert Set to 1 if the axis needs to be inverted
\param deadzone Deadzone
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static f32 convertAnalogValue(u8 value, u8 default_val, u8 min, u8 max, u8 invert,u8 deadzone);
/**
\brief Calculates a the stick data (VPADVec2D) from given digital direction.
\param stick_values bits need to set for each direction. (STICK_VALUE_UP,STICK_VALUE_DOWN,STICK_VALUE_LEFT,STICK_VALUE_RIGHT)
\return The VPADVec2D with the set values.
**/
static VPADVec2D getAnalogValueByButtons(u8 stick_values);
/**
\brief Handles the analog-stick data of HID devices. The result will written in the VPADStatus buffer.
\param data Pointer to the current data of the HID device
\param buffer Pointer to VPADStatus where the analog-stick data will be set.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR convertAnalogSticks(HID_Data * data,VPADStatus * buffer);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Mouse functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/**
\brief Set the touch data in the VPADStatus buffer.
Currently its only possible to set the touch data from a Mouse
\param data The current data of the HID device
\param buffer Pointer to VPADStatus where the touch data will be set.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setTouch(HID_Data * data,VPADStatus * buffer);
/** \brief Checks if the mouse mode needs to be changed. Sets it to the new mode if necessary.
* Currently the incoming data needs to be from a keyboard.
*
* \param data HID_Data* Pointer to the current data
* \return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR checkAndSetMouseMode(HID_Data * data);
/**
\brief Set the emulated sticks for a given VPAD data.
\param buffer: A pointer to the given VPAD Data.
\param last_emulatedSticks: A pointer to the button presses of the previous call. Will be updated while calling.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR setEmulatedSticks(VPADStatus * buffer, u32 * last_emulatedSticks);
/*----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
* Other functions
*---------------------------------------------------------------------------------------------------------------------------------------------------------------------------*/
/** \brief Set the Pro Controller for a given VPAD data.
*
* \param vpad_buffer VPADStatus* A pointer to the given VPAD Data.
* \param pro_buffer KPADData* A pointer to the KPADData where the result will be stored.
* \param lastButtonsPressesPRO u32* A pointer to the button presses of the previous call. Will be updated while calling.
* \return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
*
*/
static CONTROLLER_PATCHER_RESULT_OR_ERROR translateToPro(VPADStatus * vpad_buffer,KPADData * pro_buffer,u32 * lastButtonsPressesPRO);
static CONTROLLER_PATCHER_RESULT_OR_ERROR translateToProWPADRead(VPADStatus * vpad_buffer,WPADReadData * pro_buffer);
/**
\brief Checks if the value at the given device + CONTRPS slot equals the expected value.
\param device_slot
\param CONTRPS_slot
\param expectedValue
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR checkValueinConfigController(s32 device_slot,s32 CONTRPS_slot,s32 expectedValue);
/**
\brief Sets two u8 values to the given pointer.
\param dest: pointer to the destination array.
\param first: Value that will be written in @p dest[0]
\param second: Value that will be written in @p dest[1]
**/
static void setConfigValue(u8 * dest , u8 first, u8 second);
/**
\brief Saves a new free device slot and the corresponding HID-Mask in the given @p HIDSlotData pointer
\param slotdata Pointer to the HIDSlotData struct where the result will be saved.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getNextSlotData(HIDSlotData * slotdata);
/**
\brief Fills up a given DeviceInfo, which provides a valid VID/PID, with HIDSlotData.
\param info Pointer the target DeviceInfo. The VID/PID need to be set, the HIDSlotData will be filled with data.
\return When the functions failed result < 0 is returned. If the result is >= 0 the function was successful.
**/
static CONTROLLER_PATCHER_RESULT_OR_ERROR getDeviceInfoFromVidPid(DeviceInfo * info);
/**
\brief returns the internal slot number of the device. Some adapters have multiple slot and send the data for each one
alternating (with an identifier at the beginning). This function searches for the identifier (if it's set) and returns the
slot number relative to this pad.
\param device slot
\param current input data
\return The relative slot in the device
**/
static s32 getPadSlotInAdapter(s32 deviceslot, u8 * input_data);
/**
\brief returns a pointer to the ControllerMapping to the given controller type
\param type controller type
\return pointer to ControllerMapping data, null is type was invalid
**/
static ControllerMappingPAD * getControllerMappingByType(UController_Type type);
static CONTROLLER_PATCHER_RESULT_OR_ERROR doSampling(u16 deviceslot,u8 padslot,bool ignorePadSlot);
};
#endif /* _CONTROLLER_PATCHER_UTIL_H_ */

View File

@ -0,0 +1,73 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "../ControllerPatcher.hpp"
ControllerMapping gControllerMapping __attribute__((section(".data")));
u8 gConfig_done __attribute__((section(".data"))) = 0;
u8 gButtonRemappingConfigDone __attribute__((section(".data"))) = 0;
u32 gHIDAttached __attribute__((section(".data"))) = 0;
u32 gHIDCurrentDevice __attribute__((section(".data"))) = 0;
u16 gHIDRegisteredDevices __attribute__((section(".data"))) = 0;
HIDClient gHIDClient __attribute__((section(".data")));
HID_DEVICE_DATA gHID_Devices[gHIDMaxDevices] __attribute__((section(".data")));
u8 gHID_Mouse_Mode __attribute__((section(".data"))) = HID_MOUSE_MODE_TOUCH;
u32 gGamePadValues[CONTRPS_MAX_VALUE] __attribute__((section(".data")));
u8 config_controller[gHIDMaxDevices][CONTRPS_MAX_VALUE][2] __attribute__((section(".data")));
u32 config_controller_hidmask[gHIDMaxDevices] __attribute__((section(".data")));
u32 gHID_LIST_GC __attribute__((section(".data"))) = 0;
u32 gHID_LIST_DS3 __attribute__((section(".data"))) = 0;
u32 gHID_LIST_DS4 __attribute__((section(".data"))) = 0;
u32 gHID_LIST_KEYBOARD __attribute__((section(".data"))) = 0;
u32 gHID_LIST_SWITCH_PRO __attribute__((section(".data"))) = 0;
u32 gHID_LIST_MOUSE __attribute__((section(".data"))) = 0;
u16 gGamePadSlot __attribute__((section(".data"))) = 0;
u16 gHID_SLOT_GC __attribute__((section(".data"))) = 0;
u16 gHID_SLOT_KEYBOARD __attribute__((section(".data"))) = 0;
u16 gMouseSlot __attribute__((section(".data"))) = 0;
u8 gOriginalDimState __attribute__((section(".data"))) = 0;
u8 gOriginalAPDState __attribute__((section(".data"))) = 0;
u16 gNetworkController[gHIDMaxDevices][HID_MAX_PADS_COUNT][4] __attribute__((section(".data")));
s32 gHIDNetworkClientID __attribute__((section(".data"))) = 0;
u8 gUsedProtocolVersion __attribute__((section(".data"))) = WIIU_CP_TCP_HANDSHAKE;
wpad_connect_callback_t gWPADConnectCallback[4] __attribute__((section(".data")));
wpad_connect_callback_t gKPADConnectCallback[4] __attribute__((section(".data")));
wpad_extension_callback_t gExtensionCallback[4] __attribute__((section(".data")));
wpad_sampling_callback_t gSamplingCallback __attribute__((section(".data"))) = 0;
u8 gCallbackCooldown __attribute__((section(".data"))) = 0;
u8 gGlobalRumbleActivated __attribute__((section(".data"))) = 0;
my_cb_user * connectionOrderHelper[gHIDMaxDevices] __attribute__((section(".data")));
u32 gUDPClientip __attribute__((section(".data"))) = 0;
ControllerMappingPADInfo* gProPadInfo[4] __attribute__((section(".data"))) = {&gControllerMapping.proController[0].pad_infos[0],
&gControllerMapping.proController[1].pad_infos[0],
&gControllerMapping.proController[2].pad_infos[0],
&gControllerMapping.proController[3].pad_infos[0]} ;

View File

@ -0,0 +1,76 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef CP_RETAINS_VARS_H_
#define CP_RETAINS_VARS_H_
#include "wiiu/syshid.h"
#include "wiiu/kpad.h"
#include "../patcher/ControllerPatcherDefs.h"
extern ControllerMapping gControllerMapping;
extern u8 gConfig_done;
extern u8 gButtonRemappingConfigDone;
extern u32 gHIDAttached;
extern u32 gHIDCurrentDevice;
extern HIDClient gHIDClient;
extern u16 gHIDRegisteredDevices;
extern HID_DEVICE_DATA gHID_Devices[gHIDMaxDevices];
extern u8 gHID_Mouse_Mode;
extern u32 gGamePadValues[CONTRPS_MAX_VALUE];
extern u8 config_controller[gHIDMaxDevices][CONTRPS_MAX_VALUE][2];
extern u32 config_controller_hidmask[gHIDMaxDevices];
extern u32 gHID_LIST_GC;
extern u32 gHID_LIST_DS3;
extern u32 gHID_LIST_DS4;
extern u32 gHID_LIST_KEYBOARD;
extern u32 gHID_LIST_SWITCH_PRO;
extern u32 gHID_LIST_MOUSE;
extern u16 gGamePadSlot;
extern u16 gHID_SLOT_GC;
extern u16 gHID_SLOT_KEYBOARD;
extern u16 gMouseSlot;
extern u8 gOriginalDimState;
extern u8 gOriginalAPDState;
extern u16 gNetworkController[gHIDMaxDevices][HID_MAX_PADS_COUNT][4];
extern s32 gHIDNetworkClientID;
extern u8 gUsedProtocolVersion;
extern wpad_connect_callback_t gWPADConnectCallback[4];
extern wpad_connect_callback_t gKPADConnectCallback[4];
extern wpad_extension_callback_t gExtensionCallback[4];
extern wpad_sampling_callback_t gSamplingCallback;
extern u8 gCallbackCooldown;
extern u8 gGlobalRumbleActivated;
extern my_cb_user * connectionOrderHelper[gHIDMaxDevices];
extern u32 gUDPClientip;
extern ControllerMappingPADInfo* gProPadInfo[4];
#endif // CP_RETAINS_VARS_H_

View File

@ -0,0 +1,85 @@
#include "CPStringTools.hpp"
#include <string>
#include <vector>
#include <stdio.h>
#include <string.h>
#include <stdarg.h>
#include <stdlib.h>
#include "wiiu/types.h"
bool CPStringTools::EndsWith(const std::string& a, const std::string& b) {
if (b.size() > a.size()) return false;
return std::equal(a.begin() + a.size() - b.size(), a.end(), b.begin());
}
std::vector<std::string> CPStringTools::StringSplit(const std::string & inValue, const std::string & splitter){
std::string value = inValue;
std::vector<std::string> result;
while (true) {
u32 index = value.find(splitter);
if (index == std::string::npos) {
result.push_back(value);
break;
}
std::string first = value.substr(0, index);
result.push_back(first);
if (index + splitter.size() == value.length()) {
result.push_back("");
break;
}
if(index + splitter.size() > value.length()) {
break;
}
value = value.substr(index + splitter.size(), value.length());
}
return result;
}
const char * CPStringTools::byte_to_binary(s32 x){
static char b[9];
b[0] = '\0';
s32 z;
for (z = 128; z > 0; z >>= 1)
{
strcat(b, ((x & z) == z) ? "1" : "0");
}
return b;
}
std::string CPStringTools::removeCharFromString(std::string& input,char toBeRemoved){
std::string output = input;
size_t position;
while(1){
position = output.find(toBeRemoved);
if(position == std::string::npos)
break;
output.erase(position, 1);
}
return output;
}
std::string CPStringTools::strfmt(const char * format, ...){
std::string str;
char * tmp = NULL;
va_list va;
va_start(va, format);
if((vasprintf(&tmp, format, va) >= 0) && tmp)
{
str = tmp;
}
va_end(va);
if(tmp){
free(tmp);
tmp = NULL;
}
return str;
}
//CPStringTools

View File

@ -0,0 +1,17 @@
#ifndef _CPSTRING_TOOLS_H_
#define _CPSTRING_TOOLS_H_
#include <string>
#include <vector>
#include "wiiu/types.h"
class CPStringTools{
public:
static bool EndsWith(const std::string& a, const std::string& b);
static std::vector<std::string> StringSplit(const std::string & inValue, const std::string & splitter);
static std::string removeCharFromString(std::string& input,char toBeRemoved);
static const char * byte_to_binary(s32 test);
static std::string strfmt(const char * format, ...);
};
#endif /* _CPSTRING_TOOLS_H_ */

View File

@ -0,0 +1,119 @@
/****************************************************************************
* Copyright (C) 2015 Dimok
*
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef ControllerPatcherThread_H_
#define ControllerPatcherThread_H_
#include <malloc.h>
#include <unistd.h>
#include "wiiu/os/thread.h"
class ControllerPatcherThread
{
public:
typedef void (* Callback)(ControllerPatcherThread *thread, void *arg);
//! constructor
ControllerPatcherThread(int iAttr, int iPriority = 16, int iStackSize = 0x8000, ControllerPatcherThread::Callback callback = NULL, void *callbackArg = NULL)
: pThread(NULL)
, pThreadStack(NULL)
, pCallback(callback)
, pCallbackArg(callbackArg)
{
//! save attribute assignment
iAttributes = iAttr;
//! allocate the thread
pThread = (OSThread*)memalign(8, sizeof(OSThread));
//! allocate the stack
pThreadStack = (u8 *) memalign(0x20, iStackSize);
//! create the thread
if(pThread && pThreadStack)
OSCreateThread(pThread, &ControllerPatcherThread::threadCallback, 1, (char*)this, pThreadStack+iStackSize, iStackSize, iPriority, iAttributes);
}
//! destructor
virtual ~ControllerPatcherThread() { shutdownThread(); }
static ControllerPatcherThread *create(ControllerPatcherThread::Callback callback, void *callbackArg, int iAttr = eAttributeNone, int iPriority = 16, int iStackSize = 0x8000)
{
return ( new ControllerPatcherThread(iAttr, iPriority, iStackSize, callback, callbackArg) );
}
//! Get thread ID
virtual void* getThread() const { return pThread; }
//! Thread entry function
virtual void executeThread(void)
{
if(pCallback)
pCallback(this, pCallbackArg);
}
//! Suspend thread
virtual void suspendThread(void) { if(isThreadSuspended()) return; if(pThread) OSSuspendThread(pThread); }
//! Resume thread
virtual void resumeThread(void) { if(!isThreadSuspended()) return; if(pThread) OSResumeThread(pThread); }
//! Set thread priority
virtual void setThreadPriority(int prio) { if(pThread) OSSetThreadPriority(pThread, prio); }
//! Check if thread is suspended
virtual bool isThreadSuspended(void) const { if(pThread) return OSIsThreadSuspended(pThread); return false; }
//! Check if thread is terminated
virtual bool isThreadTerminated(void) const { if(pThread) return OSIsThreadTerminated(pThread); return false; }
//! Check if thread is running
virtual bool isThreadRunning(void) const { return !isThreadSuspended() && !isThreadRunning(); }
//! Shutdown thread
virtual void shutdownThread(void)
{
//! wait for thread to finish
if(pThread && !(iAttributes & eAttributeDetach))
{
if(isThreadSuspended())
resumeThread();
OSJoinThread(pThread, NULL);
}
//! free the thread stack buffer
if(pThreadStack)
free(pThreadStack);
if(pThread)
free(pThread);
pThread = NULL;
pThreadStack = NULL;
}
//! Thread attributes
enum eControllerPatcherThreadAttributes
{
eAttributeNone = 0x07,
eAttributeAffCore0 = 0x01,
eAttributeAffCore1 = 0x02,
eAttributeAffCore2 = 0x04,
eAttributeDetach = 0x08,
eAttributePinnedAff = 0x10
};
private:
static int threadCallback(int argc, const char **argv)
{
//! After call to start() continue with the internal function
((ControllerPatcherThread *) argv)->executeThread();
return 0;
}
int iAttributes;
OSThread *pThread;
u8 *pThreadStack;
Callback pCallback;
void *pCallbackArg;
};
#endif

View File

@ -0,0 +1,78 @@
#include <malloc.h>
#include <string.h>
#include <stdio.h>
#include <unistd.h>
#include <fcntl.h>
#include <wiiu/fs.h>
#define FS_MAX_MOUNTPATH_SIZE 128
int FS_Helper_MountFS(void *pClient, void *pCmd, char **mount_path){
int result = -1;
void *mountSrc = malloc(sizeof(FSMountSource));
if(!mountSrc)
return -3;
char* mountPath = (char*) malloc(FS_MAX_MOUNTPATH_SIZE);
if(!mountPath) {
free(mountSrc);
return -4;
}
memset(mountSrc, 0, sizeof(FSMountSource));
memset(mountPath, 0, FS_MAX_MOUNTPATH_SIZE);
// Mount sdcard
if (FSGetMountSource(pClient, pCmd, FS_MOUNT_SOURCE_SD, mountSrc, -1) == 0)
{
result = FSMount(pClient, pCmd, mountSrc, mountPath, FS_MAX_MOUNTPATH_SIZE, -1);
if((result == 0) && mount_path) {
*mount_path = (char*)malloc(strlen(mountPath) + 1);
if(*mount_path)
strcpy(*mount_path, mountPath);
}
}
free(mountPath);
free(mountSrc);
return result;
}
int FS_Helper_GetFile(void * pClient,void * pCmd,const char * path, char *(*result)){
if(pClient == NULL || pCmd == NULL || path == NULL || result == NULL) return -2;
FSStat stats;
s32 status = -1;
s32 handle = 0;
if((status = FSGetStat(pClient,pCmd,path,&stats,-1)) == FS_STATUS_OK){
(*result) = (uint8_t *) memalign(0x40, (sizeof(uint8_t)*stats.size)+1);
if(!(*result)){
printf("FS_Helper_GetFile(line %d): error: Failed to allocate space for reading the file\n",__LINE__);
return -1;
}
(*result)[stats.size] = '\0';
if((status = FSOpenFile(pClient,pCmd,path,"r",&handle,-1)) == FS_STATUS_OK){
s32 total_read = 0;
s32 ret2 = 0;
char * cur_result_pointer = *result;
s32 sizeToRead = stats.size;
while ((ret2 = FSReadFile(pClient,pCmd, cur_result_pointer, 0x01, sizeToRead, handle, 0, -1)) > 0){
total_read += ret2;
cur_result_pointer += ret2;
sizeToRead -= ret2;
}
}else{
printf("FS_Helper_GetFile(line %d): error: (FSOpenFile) Couldn't open file (%s), error: %d",__LINE__,path,status);
free((*result));
(*result)=NULL;
return -1;
}
FSCloseFile(pClient,pCmd,handle,-1);
return 0;
}else{
printf("FS_Helper_GetFile(line %d): error: (GetStat) Couldn't open file (%s), error: %d",__LINE__,path,status);
}
return -1;
}

View File

@ -0,0 +1,17 @@
#ifndef __FSHELPER_H_
#define __FSHELPER_H_
#ifdef __cplusplus
extern "C" {
#endif
#include <wiiu/types.h>
int FS_Helper_MountFS(void *pClient, void *pCmd, char **mount_path);
int FS_Helper_GetFile(void * pClient,void * pCmd,const char *, char **result);
#ifdef __cplusplus
}
#endif
#endif // __FSHELPER_H_

View File

@ -0,0 +1,341 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#include "PadConst.hpp"
const u8 DEF_R_STICK = 220;
const u8 DEF_L_STICK = 221;
const u8 DEF_STICK_OFFSET_INVERT = CONTRPS_VPAD_BUTTON_L_STICK_X_INVERT - CONTRPS_VPAD_BUTTON_L_STICK_X;
const u8 DEF_STICK_OFFSET_DEADZONE = CONTRPS_VPAD_BUTTON_L_STICK_X_DEADZONE - CONTRPS_VPAD_BUTTON_L_STICK_X;
const u8 DEF_STICK_OFFSET_MINMAX = CONTRPS_VPAD_BUTTON_L_STICK_X_MINMAX - CONTRPS_VPAD_BUTTON_L_STICK_X;
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! Device names
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const char *HID_GC_STRING = "GameCube\nUSB-Adapter";
const char *HID_KEYBOARD_STRING = "Keyboard";
const char *HID_MOUSE_STRING = "Mouse";
const char *HID_DS3_STRING = "DualShock 3\nController";
const char *HID_DS4_STRING = "DualShock 4\nController";
const char *HID_NEW_DS4_STRING = "DualShock 4\nController";
const char *HID_XINPUT_STRING = "XInput\nController";
const char *HID_SWITCH_PRO_STRING = "Switch\nPro Controller";
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! GC-Adapter
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const u8 HID_GC_BUTTON_A[] = { 0x01,HID_GC_BUTTON_A_VALUE};
const u8 HID_GC_BUTTON_B[] = { 0x01,HID_GC_BUTTON_B_VALUE};
const u8 HID_GC_BUTTON_X[] = { 0x01,HID_GC_BUTTON_X_VALUE};
const u8 HID_GC_BUTTON_Y[] = { 0x01,HID_GC_BUTTON_Y_VALUE};
const u8 HID_GC_BUTTON_LEFT[] = { 0x01,HID_GC_BUTTON_LEFT_VALUE};
const u8 HID_GC_BUTTON_RIGHT[] = { 0x01,HID_GC_BUTTON_RIGHT_VALUE};
const u8 HID_GC_BUTTON_DOWN[] = { 0x01,HID_GC_BUTTON_DOWN_VALUE};
const u8 HID_GC_BUTTON_UP[] = { 0x01,HID_GC_BUTTON_UP_VALUE};
const u8 HID_GC_BUTTON_START[] = { 0x02,HID_GC_BUTTON_START_VALUE};
const u8 HID_GC_BUTTON_Z[] = { 0x02,HID_GC_BUTTON_Z_VALUE};
const u8 HID_GC_BUTTON_L[] = { 0x07,HID_GC_BUTTON_L_VALUE};
const u8 HID_GC_BUTTON_R[] = { 0x08,HID_GC_BUTTON_R_VALUE};
const u8 HID_GC_BUTTON_DPAD_TYPE[] = { CONTRPDM_Normal,0x00};
const u8 HID_GC_STICK_L_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x03, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x09, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x1A, //STICK_CONF_MIN,
0xE4};//STICK_CONF_MAX,
const u8 HID_GC_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x04, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x09, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x11, //STICK_CONF_MIN,
0xE1};//STICK_CONF_MAX,
const u8 HID_GC_STICK_R_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x05, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x09, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x2B, //STICK_CONF_MIN,
0xE2};//STICK_CONF_MAX,
const u8 HID_GC_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x06, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x09, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x1D, //STICK_CONF_MIN,
0xDB};//STICK_CONF_MAX,
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! DS3
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const u8 HID_DS3_BUTTON_CROSS[] = { 0x03,HID_DS3_BUTTON_CROSS_VALUE};
const u8 HID_DS3_BUTTON_CIRCLE[] = { 0x03,HID_DS3_BUTTON_CIRCLE_VALUE};
const u8 HID_DS3_BUTTON_SQUARE [] = { 0x03,HID_DS3_BUTTON_SQUARE_VALUE};
const u8 HID_DS3_BUTTON_TRIANGLE[] = { 0x03,HID_DS3_BUTTON_TRIANGLE_VALUE};
const u8 HID_DS3_BUTTON_L1[] = { 0x03,HID_DS3_BUTTON_L1_VALUE};
const u8 HID_DS3_BUTTON_L2[] = { 0x03,HID_DS3_BUTTON_L2_VALUE};
const u8 HID_DS3_BUTTON_R1[] = { 0x03,HID_DS3_BUTTON_R1_VALUE};
const u8 HID_DS3_BUTTON_R2[] = { 0x03,HID_DS3_BUTTON_R2_VALUE};
const u8 HID_DS3_BUTTON_L3[] = { 0x02,HID_DS3_BUTTON_L3_VALUE};
const u8 HID_DS3_BUTTON_R3[] = { 0x02,HID_DS3_BUTTON_R3_VALUE};
const u8 HID_DS3_BUTTON_SELECT[] = { 0x02,HID_DS3_BUTTON_SELECT_VALUE};
const u8 HID_DS3_BUTTON_START[] = { 0x02,HID_DS3_BUTTON_START_VALUE};
const u8 HID_DS3_BUTTON_LEFT[] = { 0x02,HID_DS3_BUTTON_LEFT_VALUE};
const u8 HID_DS3_BUTTON_RIGHT[] = { 0x02,HID_DS3_BUTTON_RIGHT_VALUE};
const u8 HID_DS3_BUTTON_UP[] = { 0x02,HID_DS3_BUTTON_UP_VALUE};
const u8 HID_DS3_BUTTON_DOWN[] = { 0x02,HID_DS3_BUTTON_DOWN_VALUE};
const u8 HID_DS3_BUTTON_GUIDE[] = { 0x04,HID_DS3_BUTTON_GUIDE_VALUE};
const u8 HID_DS3_BUTTON_DPAD_TYPE[] = { CONTRPDM_Normal,0x00};
const u8 HID_DS3_STICK_L_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x06, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS3_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x07, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS3_STICK_R_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x08, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS3_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x09, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! DS4
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const u8 HID_DS4_BUTTON_CROSS[] = { 0x05,HID_DS4_BUTTON_CROSS_VALUE};
const u8 HID_DS4_BUTTON_CIRCLE[] = { 0x05,HID_DS4_BUTTON_CIRCLE_VALUE};
const u8 HID_DS4_BUTTON_SQUARE [] = { 0x05,HID_DS4_BUTTON_SQUARE_VALUE};
const u8 HID_DS4_BUTTON_TRIANGLE[] = { 0x05,HID_DS4_BUTTON_TRIANGLE_VALUE};
const u8 HID_DS4_BUTTON_L1[] = { 0x06,HID_DS4_BUTTON_L1_VALUE};
const u8 HID_DS4_BUTTON_L2[] = { 0x06,HID_DS4_BUTTON_L2_VALUE};
const u8 HID_DS4_BUTTON_L3[] = { 0x06,HID_DS4_BUTTON_L3_VALUE};
const u8 HID_DS4_BUTTON_R1[] = { 0x06,HID_DS4_BUTTON_R1_VALUE};
const u8 HID_DS4_BUTTON_R2[] = { 0x06,HID_DS4_BUTTON_R2_VALUE};
const u8 HID_DS4_BUTTON_R3[] = { 0x06,HID_DS4_BUTTON_R3_VALUE};
const u8 HID_DS4_BUTTON_SHARE[] = { 0x06,HID_DS4_BUTTON_SHARE_VALUE};
const u8 HID_DS4_BUTTON_OPTIONS[] = { 0x06,HID_DS4_BUTTON_OPTIONS_VALUE};
const u8 HID_DS4_BUTTON_DPAD_TYPE[] = { CONTRPDM_Hat,HID_DS4_BUTTON_DPAD_MASK_VALUE};
const u8 HID_DS4_BUTTON_DPAD_N[] = { 0x05,HID_DS4_BUTTON_DPAD_N_VALUE};
const u8 HID_DS4_BUTTON_DPAD_NE[] = { 0x05,HID_DS4_BUTTON_DPAD_NE_VALUE};
const u8 HID_DS4_BUTTON_DPAD_E[] = { 0x05,HID_DS4_BUTTON_DPAD_E_VALUE};
const u8 HID_DS4_BUTTON_DPAD_SE[] = { 0x05,HID_DS4_BUTTON_DPAD_SE_VALUE};
const u8 HID_DS4_BUTTON_DPAD_S[] = { 0x05,HID_DS4_BUTTON_DPAD_S_VALUE};
const u8 HID_DS4_BUTTON_DPAD_SW[] = { 0x05,HID_DS4_BUTTON_DPAD_SW_VALUE};
const u8 HID_DS4_BUTTON_DPAD_W[] = { 0x05,HID_DS4_BUTTON_DPAD_W_VALUE};
const u8 HID_DS4_BUTTON_DPAD_NW[] = { 0x05,HID_DS4_BUTTON_DPAD_NW_VALUE};
const u8 HID_DS4_BUTTON_DPAD_NEUTRAL[] = { 0x05,HID_DS4_BUTTON_DPAD_NEUTRAL_VALUE};
const u8 HID_DS4_BUTTON_GUIDE[] = { 0x07,HID_DS4_BUTTON_GUIDE_VALUE};
const u8 HID_DS4_BUTTON_T_PAD_CLICK[] = { 0x07,HID_DS4_BUTTON_T_PAD_CLICK_VALUE};
const u8 HID_DS4_STICK_L_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x01, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS4_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x02, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x05, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS4_STICK_R_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x03, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x07, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_DS4_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x04, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x09, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! XInput
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const u8 HID_XINPUT_BUTTON_A[] = { 0x07,HID_XINPUT_BUTTON_A_VALUE};
const u8 HID_XINPUT_BUTTON_B[] = { 0x07,HID_XINPUT_BUTTON_B_VALUE};
const u8 HID_XINPUT_BUTTON_X[] = { 0x07,HID_XINPUT_BUTTON_X_VALUE};
const u8 HID_XINPUT_BUTTON_Y[] = { 0x07,HID_XINPUT_BUTTON_Y_VALUE};
const u8 HID_XINPUT_BUTTON_LB[] = { 0x06,HID_XINPUT_BUTTON_LB_VALUE};
const u8 HID_XINPUT_BUTTON_LT[] = { 0x04,HID_XINPUT_BUTTON_LT_VALUE};
const u8 HID_XINPUT_BUTTON_L3[] = { 0x06,HID_XINPUT_BUTTON_L3_VALUE};
const u8 HID_XINPUT_BUTTON_RB[] = { 0x06,HID_XINPUT_BUTTON_RB_VALUE};
const u8 HID_XINPUT_BUTTON_RT[] = { 0x05,HID_XINPUT_BUTTON_RT_VALUE};
const u8 HID_XINPUT_BUTTON_R3[] = { 0x06,HID_XINPUT_BUTTON_R3_VALUE};
const u8 HID_XINPUT_BUTTON_START[] = { 0x06,HID_XINPUT_BUTTON_START_VALUE};
const u8 HID_XINPUT_BUTTON_BACK[] = { 0x06,HID_XINPUT_BUTTON_BACK_VALUE};
const u8 HID_XINPUT_BUTTON_GUIDE[] = { 0x06,HID_XINPUT_BUTTON_GUIDE_VALUE};
const u8 HID_XINPUT_BUTTON_DPAD_TYPE[] = { CONTRPDM_Normal,HID_XINPUT_BUTTON_DPAD_MASK_VALUE};
const u8 HID_XINPUT_BUTTON_LEFT[] = { 0x07,HID_XINPUT_BUTTON_LEFT_VALUE};
const u8 HID_XINPUT_BUTTON_RIGHT[] = { 0x07,HID_XINPUT_BUTTON_RIGHT_VALUE};
const u8 HID_XINPUT_BUTTON_DOWN[] = { 0x07,HID_XINPUT_BUTTON_DOWN_VALUE};
const u8 HID_XINPUT_BUTTON_UP[] = { 0x07,HID_XINPUT_BUTTON_UP_VALUE};
const u8 HID_XINPUT_STICK_L_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x00, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x10, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_XINPUT_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x01, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x10, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_XINPUT_STICK_R_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x02, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x10, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
const u8 HID_XINPUT_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x03, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x10, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x00, //STICK_CONF_MIN,
0xFF};//STICK_CONF_MAX,
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! Switch Pro Controller
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
const u8 HID_SWITCH_PRO_BT_BUTTON_A[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_A_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_B[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_B_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_X[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_X_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_Y[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_Y_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_L[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_L_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_ZL[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_ZL_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_STICK_L[] = { 0x01,(u8)((HID_SWITCH_PRO_BT_BUTTON_STICK_L_VALUE >> 16) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_R[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_R_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_ZR[] = { 0x00,(u8)((HID_SWITCH_PRO_BT_BUTTON_ZR_VALUE >> 24) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_STICK_R[] = { 0x01,(u8)((HID_SWITCH_PRO_BT_BUTTON_STICK_R_VALUE >> 16) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_PLUS[] = { 0x01,(u8)((HID_SWITCH_PRO_BT_BUTTON_PLUS_VALUE >> 16) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_MINUS[] = { 0x01,(u8)((HID_SWITCH_PRO_BT_BUTTON_MINUS_VALUE >> 16) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_HOME[] = { 0x01,(u8)((HID_SWITCH_PRO_BT_BUTTON_HOME_VALUE >> 16) & 0xFF)};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_TYPE[] = { CONTRPDM_Hat,HID_SWITCH_PRO_BT_BUTTON_DPAD_MASK_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_N[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_N_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NE[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_NE_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_E[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_E_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_SE[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_SE_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_S[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_S_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_SW[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_SW_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_W[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_W_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NW[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_NW_VALUE};
const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL[] = { 0x02,HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL_VALUE};
const u8 HID_SWITCH_PRO_BT_STICK_L_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x04, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x01, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x28, //STICK_CONF_MIN,
0xDF};//STICK_CONF_MAX,
const u8 HID_SWITCH_PRO_BT_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x06, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x06, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x16, //STICK_CONF_MIN,
0xD7};//STICK_CONF_MAX,
const u8 HID_SWITCH_PRO_BT_STICK_R_X[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x08, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x04, //STICK_CONF_DEADZONE,
0x00, //STICK_CONF_INVERT,
0x29, //STICK_CONF_MIN,
0xE2};//STICK_CONF_MAX,
const u8 HID_SWITCH_PRO_BT_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE] = { STICK_CONF_MAGIC_VALUE, //STICK_CONF_MAGIC_VERSION
0x0A, //STICK_CONF_BYTE,
0x80, //STICK_CONF_DEFAULT,
0x08, //STICK_CONF_DEADZONE,
0x01, //STICK_CONF_INVERT,
0x22, //STICK_CONF_MIN,
0xE4};//STICK_CONF_MAX,

View File

@ -0,0 +1,211 @@
/****************************************************************************
* 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 <http://www.gnu.org/licenses/>.
****************************************************************************/
#ifndef _PAD_CONST_H_
#define _PAD_CONST_H_
#include <string>
#include "../patcher/ControllerPatcherDefs.h"
extern const u8 DEF_R_STICK;
extern const u8 DEF_L_STICK;
extern const u8 DEF_STICK_OFFSET_INVERT;
extern const u8 DEF_STICK_OFFSET_DEADZONE;
extern const u8 DEF_STICK_OFFSET_MINMAX;
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! Device names
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const char *HID_GC_STRING;
extern const char *HID_KEYBOARD_STRING;
extern const char *HID_MOUSE_STRING;
extern const char *HID_DS3_STRING;
extern const char *HID_DS4_STRING;
extern const char *HID_NEW_DS4_STRING;
extern const char *HID_XINPUT_STRING;
extern const char *HID_SWITCH_PRO_STRING;
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! GC_Adapter
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const u8 HID_GC_BUTTON_A[];
extern const u8 HID_GC_BUTTON_B[];
extern const u8 HID_GC_BUTTON_X[];
extern const u8 HID_GC_BUTTON_Y[];
extern const u8 HID_GC_BUTTON_LEFT[];
extern const u8 HID_GC_BUTTON_RIGHT[];
extern const u8 HID_GC_BUTTON_DOWN[];
extern const u8 HID_GC_BUTTON_UP[];
extern const u8 HID_GC_BUTTON_START[];
extern const u8 HID_GC_BUTTON_Z[];
extern const u8 HID_GC_BUTTON_L[];
extern const u8 HID_GC_BUTTON_R[];
extern const u8 HID_GC_BUTTON_DPAD_TYPE[];
extern const u8 HID_GC_STICK_L_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_GC_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_GC_STICK_R_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_GC_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE];
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! DS3
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const u8 HID_DS3_BUTTON_CROSS[];
extern const u8 HID_DS3_BUTTON_CIRCLE[];
extern const u8 HID_DS3_BUTTON_SQUARE [];
extern const u8 HID_DS3_BUTTON_TRIANGLE[];
extern const u8 HID_DS3_BUTTON_L1[];
extern const u8 HID_DS3_BUTTON_L2[];
extern const u8 HID_DS3_BUTTON_R1[];
extern const u8 HID_DS3_BUTTON_R2[];
extern const u8 HID_DS3_BUTTON_L3[];
extern const u8 HID_DS3_BUTTON_R3[];
extern const u8 HID_DS3_BUTTON_SELECT[];
extern const u8 HID_DS3_BUTTON_START[];
extern const u8 HID_DS3_BUTTON_LEFT[];
extern const u8 HID_DS3_BUTTON_RIGHT[];
extern const u8 HID_DS3_BUTTON_UP[];
extern const u8 HID_DS3_BUTTON_DOWN[];
extern const u8 HID_DS3_BUTTON_GUIDE[];
extern const u8 HID_DS3_BUTTON_DPAD_TYPE[];
extern const u8 HID_DS3_STICK_L_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS3_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS3_STICK_R_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS3_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE];
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! DS4
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const u8 HID_DS4_BUTTON_CROSS[];
extern const u8 HID_DS4_BUTTON_CIRCLE[];
extern const u8 HID_DS4_BUTTON_SQUARE [];
extern const u8 HID_DS4_BUTTON_TRIANGLE[];
extern const u8 HID_DS4_BUTTON_L1[];
extern const u8 HID_DS4_BUTTON_L2[];
extern const u8 HID_DS4_BUTTON_L3[];
extern const u8 HID_DS4_BUTTON_R1[];
extern const u8 HID_DS4_BUTTON_R2[];
extern const u8 HID_DS4_BUTTON_R3[];
extern const u8 HID_DS4_BUTTON_SHARE[];
extern const u8 HID_DS4_BUTTON_OPTIONS[];
extern const u8 HID_DS4_BUTTON_DPAD_TYPE[];
extern const u8 HID_DS4_BUTTON_DPAD_N[];
extern const u8 HID_DS4_BUTTON_DPAD_NE[];
extern const u8 HID_DS4_BUTTON_DPAD_E[];
extern const u8 HID_DS4_BUTTON_DPAD_SE[];
extern const u8 HID_DS4_BUTTON_DPAD_S[];
extern const u8 HID_DS4_BUTTON_DPAD_SW[];
extern const u8 HID_DS4_BUTTON_DPAD_W[];
extern const u8 HID_DS4_BUTTON_DPAD_NW[];
extern const u8 HID_DS4_BUTTON_DPAD_NEUTRAL[];
extern const u8 HID_DS4_BUTTON_GUIDE[];
extern const u8 HID_DS4_BUTTON_T_PAD_CLICK[];
extern const u8 HID_DS4_STICK_L_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS4_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS4_STICK_R_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_DS4_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE];
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! XInput
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const u8 HID_XINPUT_BUTTON_A[];
extern const u8 HID_XINPUT_BUTTON_B[];
extern const u8 HID_XINPUT_BUTTON_X[];
extern const u8 HID_XINPUT_BUTTON_Y[];
extern const u8 HID_XINPUT_BUTTON_LB[];
extern const u8 HID_XINPUT_BUTTON_LT[];
extern const u8 HID_XINPUT_BUTTON_L3[];
extern const u8 HID_XINPUT_BUTTON_RB[];
extern const u8 HID_XINPUT_BUTTON_RT[];
extern const u8 HID_XINPUT_BUTTON_R3[];
extern const u8 HID_XINPUT_BUTTON_START[];
extern const u8 HID_XINPUT_BUTTON_BACK[];
extern const u8 HID_XINPUT_BUTTON_GUIDE[];
extern const u8 HID_XINPUT_BUTTON_DPAD_TYPE[];
extern const u8 HID_XINPUT_BUTTON_LEFT[];
extern const u8 HID_XINPUT_BUTTON_RIGHT[];
extern const u8 HID_XINPUT_BUTTON_DOWN[];
extern const u8 HID_XINPUT_BUTTON_UP[];
extern const u8 HID_XINPUT_STICK_L_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_XINPUT_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_XINPUT_STICK_R_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_XINPUT_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE];
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
//! Switch Pro Controller
//!----------------------------------------------------------------------------------------------------------------------------------------------------------------------------
extern const u8 HID_SWITCH_PRO_BT_BUTTON_A[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_B[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_X[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_Y[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_L[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_ZL[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_STICK_L[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_R[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_ZR[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_STICK_R[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_PLUS[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_MINUS[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_HOME[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_TYPE[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_N[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NE[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_E[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_SE[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_S[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_SW[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_W[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NW[];
extern const u8 HID_SWITCH_PRO_BT_BUTTON_DPAD_NEUTRAL[];
extern const u8 HID_SWITCH_PRO_BT_STICK_L_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_SWITCH_PRO_BT_STICK_L_Y[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_SWITCH_PRO_BT_STICK_R_X[STICK_CONF_ENUM_MAXVALUE];
extern const u8 HID_SWITCH_PRO_BT_STICK_R_Y[STICK_CONF_ENUM_MAXVALUE];
#endif /* _PAD_CONST_H_ */

View File

@ -164,6 +164,7 @@ void FSInit();
void FSShutdown();
FSStatus FSAddClient(FSClient *client, uint32_t flags);
FSStatus FSAddClientEx(FSClient *pClient, s32 unk_zero_param, uint32_t errHandling);
FSStatus FSDelClient(FSClient *client, uint32_t flags);
uint32_t FSGetClientNum();
void FSInitCmdBlock(FSCmdBlock *block);

View File

@ -22,7 +22,7 @@ typedef struct _KPADData
u8 device_type;
u8 wpad_error;
u8 pos_valid;
u8 unused_4[1];
u8 format;
union
{
@ -45,6 +45,19 @@ typedef struct _KPADData
f32 rtrigger;
} classic;
struct
{
u32 hold;
u32 trigger;
u32 release;
f32 lstick_x;
f32 lstick_y;
f32 rstick_x;
f32 rstick_y;
s32 charging;
s32 wired;
} pro;
u32 unused_6[20];
};
u32 unused_7[16];
@ -53,6 +66,7 @@ typedef struct _KPADData
void KPADInit (void);
s32 KPADRead(s32 chan, void * data, u32 size);
s32 KPADReadEx(s32 chan, KPADData * data, u32 size, s32 *error);
#ifdef __cplusplus
}

View File

@ -8,6 +8,7 @@
#include <wiiu/os/coroutine.h>
#include <wiiu/os/debug.h>
#include <wiiu/os/dynload.h>
#include <wiiu/os/energy.h>
#include <wiiu/os/event.h>
#include <wiiu/os/exception.h>
#include <wiiu/os/fastcondition.h>

View File

@ -0,0 +1,18 @@
#pragma once
#include <wiiu/types.h>
#ifdef __cplusplus
extern "C" {
#endif
s32 IMEnableDim(void);
s32 IMDisableDim(void);
s32 IMIsDimEnabled(s32 * result);
s32 IMEnableAPD(void);
s32 IMDisableAPD(void);
s32 IMIsAPDEnabled(s32 * result);
s32 IMIsAPDEnabledBySysSettings(s32 * result);
#ifdef __cplusplus
}
#endif

View File

@ -15,6 +15,7 @@ typedef struct
}OSSystemInfo;
OSSystemInfo *OSGetSystemInfo();
s32 * __gh_errno_ptr(void);
#ifdef __cplusplus
}

126
wiiu/include/wiiu/syshid.h Normal file
View File

@ -0,0 +1,126 @@
#pragma once
#include <wiiu/types.h>
typedef struct
{
uint32_t handle;
uint32_t physical_device_inst;
uint16_t vid;
uint16_t pid;
uint8_t interface_index;
uint8_t sub_class;
uint8_t protocol;
uint16_t max_packet_size_rx;
uint16_t max_packet_size_tx;
} HIDDevice;
typedef struct _HIDClient HIDClient;
#define HID_DEVICE_DETACH 0
#define HID_DEVICE_ATTACH 1
typedef int32_t (*HIDAttachCallback)(HIDClient *p_hc,HIDDevice *p_hd,uint32_t attach);
struct _HIDClient
{
HIDClient *next;
HIDAttachCallback attach_cb;
};
typedef void (*HIDCallback)(uint32_t handle,int32_t error,uint8_t *p_buffer,uint32_t bytes_transferred,void *p_user);
#ifdef __cplusplus
extern "C" {
#endif
int32_t
HIDSetup(void);
int32_t
HIDTeardown(void);
int32_t
HIDAddClient(HIDClient *p_client,
HIDAttachCallback attach_callback);
int32_t
HIDDelClient(HIDClient *p_client);
int32_t
HIDGetDescriptor(uint32_t handle,
uint8_t descriptor_type,
uint8_t descriptor_index,
uint16_t language_id,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
int32_t
HIDSetDescriptor(uint32_t handle,
uint8_t descriptor_type,
uint8_t descriptor_index,
uint16_t language_id,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
int32_t
HIDGetReport(uint32_t handle,
uint8_t report_type,
uint8_t report_id,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
int32_t
HIDSetReport(uint32_t handle,
uint8_t report_type,
uint8_t report_id,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
int32_t
HIDSetIdle(uint32_t handle,
uint8_t interface_index,
uint8_t duration,
HIDCallback hc,
void *p_user);
int32_t
HIDSetProtocol(uint32_t handle,
uint8_t int32_terface_index,
uint8_t protocol,
HIDCallback hc,
void *p_user);
int32_t
HIDGetProtocol(uint32_t handle,
uint8_t interface_index,
uint8_t * protocol,
HIDCallback hc,
void *p_user);
int32_t
HIDRead(uint32_t handle,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
int32_t
HIDWrite(uint32_t handle,
uint8_t *p_buffer,
uint32_t buffer_length,
HIDCallback hc,
void *p_user);
#ifdef __cplusplus
}
#endif

View File

@ -7,27 +7,41 @@ extern "C" {
typedef enum VPADButtons
{
VPAD_BUTTON_SYNC = 0x00000001,
VPAD_BUTTON_HOME = 0x00000002,
VPAD_BUTTON_MINUS = 0x00000004,
VPAD_BUTTON_PLUS = 0x00000008,
VPAD_BUTTON_R = 0x00000010,
VPAD_BUTTON_L = 0x00000020,
VPAD_BUTTON_ZR = 0x00000040,
VPAD_BUTTON_ZL = 0x00000080,
VPAD_BUTTON_DOWN = 0x00000100,
VPAD_BUTTON_UP = 0x00000200,
VPAD_BUTTON_RIGHT = 0x00000400,
VPAD_BUTTON_LEFT = 0x00000800,
VPAD_BUTTON_Y = 0x00001000,
VPAD_BUTTON_X = 0x00002000,
VPAD_BUTTON_B = 0x00004000,
VPAD_BUTTON_A = 0x00008000,
VPAD_BUTTON_TV = 0x00010000,
VPAD_BUTTON_STICK_R = 0x00020000,
VPAD_BUTTON_STICK_L = 0x00040000,
VPAD_BUTTON_SYNC = 0x00000001,
VPAD_BUTTON_HOME = 0x00000002,
VPAD_BUTTON_MINUS = 0x00000004,
VPAD_BUTTON_PLUS = 0x00000008,
VPAD_BUTTON_R = 0x00000010,
VPAD_BUTTON_L = 0x00000020,
VPAD_BUTTON_ZR = 0x00000040,
VPAD_BUTTON_ZL = 0x00000080,
VPAD_BUTTON_DOWN = 0x00000100,
VPAD_BUTTON_UP = 0x00000200,
VPAD_BUTTON_RIGHT = 0x00000400,
VPAD_BUTTON_LEFT = 0x00000800,
VPAD_BUTTON_Y = 0x00001000,
VPAD_BUTTON_X = 0x00002000,
VPAD_BUTTON_B = 0x00004000,
VPAD_BUTTON_A = 0x00008000,
VPAD_BUTTON_TV = 0x00010000,
VPAD_BUTTON_STICK_R = 0x00020000,
VPAD_BUTTON_STICK_L = 0x00040000,
VPAD_STICK_R_EMULATION_LEFT = 0x04000000,
VPAD_STICK_R_EMULATION_RIGHT = 0x02000000,
VPAD_STICK_R_EMULATION_UP = 0x01000000,
VPAD_STICK_R_EMULATION_DOWN = 0x00800000,
VPAD_STICK_L_EMULATION_LEFT = 0x40000000,
VPAD_STICK_L_EMULATION_RIGHT = 0x20000000,
VPAD_STICK_L_EMULATION_UP = 0x10000000,
VPAD_STICK_L_EMULATION_DOWN = 0x08000000,
} VPADButtons;
#define VPAD_BUTTON_TOUCH 0x00080000
#define VPAD_MASK_EMULATED_STICKS 0x7F800000
#define VPAD_MASK_BUTTONS ~VPAD_MASK_EMULATED_STICKS
typedef enum VPADTouchPadValidity
{
//! Both X and Y touchpad positions are accurate

View File

@ -6,6 +6,16 @@ extern "C" {
#include <wiiu/types.h>
#define WPAD_EXT_CORE 0
#define WPAD_EXT_NUNCHUK 1
#define WPAD_EXT_CLASSIC 2
#define WPAD_EXT_MPLUS 5
#define WPAD_EXT_MPLUS_NUNCHUK 6
#define WPAD_EXT_MPLUS_CLASSIC 7
#define WPAD_EXT_PRO_CONTROLLER 31
#define WPAD_FMT_PRO_CONTROLLER 22
#define WPAD_BUTTON_LEFT 0x0001
#define WPAD_BUTTON_RIGHT 0x0002
#define WPAD_BUTTON_DOWN 0x0004
@ -36,9 +46,51 @@ extern "C" {
#define WPAD_CLASSIC_BUTTON_DOWN 0x4000
#define WPAD_CLASSIC_BUTTON_RIGHT 0x8000
#define WPAD_PRO_BUTTON_STICK_R 0x10000
#define WPAD_PRO_BUTTON_STICK_L 0x20000
#define WPAD_PRO_BUTTON_UP 0x00000001
#define WPAD_PRO_BUTTON_LEFT 0x00000002
#define WPAD_PRO_TRIGGER_ZR 0x00000004
#define WPAD_PRO_BUTTON_X 0x00000008
#define WPAD_PRO_BUTTON_A 0x00000010
#define WPAD_PRO_BUTTON_Y 0x00000020
#define WPAD_PRO_BUTTON_B 0x00000040
#define WPAD_PRO_TRIGGER_ZL 0x00000080
#define WPAD_PRO_RESERVED 0x00000100
#define WPAD_PRO_TRIGGER_R 0x00000200
#define WPAD_PRO_BUTTON_PLUS 0x00000400
#define WPAD_PRO_BUTTON_HOME 0x00000800
#define WPAD_PRO_BUTTON_MINUS 0x00001000
#define WPAD_PRO_TRIGGER_L 0x00002000
#define WPAD_PRO_BUTTON_DOWN 0x00004000
#define WPAD_PRO_BUTTON_RIGHT 0x00008000
#define WPAD_PRO_BUTTON_STICK_R 0x00010000
#define WPAD_PRO_BUTTON_STICK_L 0x00020000
#define WPAD_PRO_STICK_L_EMULATION_UP 0x00200000
#define WPAD_PRO_STICK_L_EMULATION_DOWN 0x00100000
#define WPAD_PRO_STICK_L_EMULATION_LEFT 0x00040000
#define WPAD_PRO_STICK_L_EMULATION_RIGHT 0x00080000
#define WPAD_PRO_STICK_R_EMULATION_UP 0x02000000
#define WPAD_PRO_STICK_R_EMULATION_DOWN 0x01000000
#define WPAD_PRO_STICK_R_EMULATION_LEFT 0x00400000
#define WPAD_PRO_STICK_R_EMULATION_RIGHT 0x00800000
typedef struct WPADReadData_ {
u8 unknown[40];
u8 dev;
u8 err;
u8 unknown1[2];
u32 buttons;
s16 l_stick_x;
s16 l_stick_y;
s16 r_stick_x;
s16 r_stick_y;
u8 unknown2[8];
u8 fmt;
}WPADReadData;
typedef void (* wpad_sampling_callback_t)(s32 chan);
typedef void (* wpad_extension_callback_t)(s32 chan, s32 status);
typedef void (* wpad_connect_callback_t)(s32 chan, s32 status);
s32 WPADProbe (s32 chan, u32 * pad_type);

View File

@ -17,8 +17,13 @@ IMPORT(OSInitSpinLock);
IMPORT(OSUninterruptibleSpinLock_Acquire);
IMPORT(OSUninterruptibleSpinLock_Release);
IMPORT(OSSleepTicks);
IMPORT(OSGetTitleID);
IMPORT(OSIsThreadTerminated);
IMPORT(OSSetThreadPriority);
IMPORT(OSCreateThread);
IMPORT(OSResumeThread);
IMPORT(OSIsThreadSuspended);
IMPORT(OSSuspendThread);
IMPORT(OSJoinThread);
IMPORT(OSYieldThread);
IMPORT(OSGetSystemTime);
@ -31,10 +36,13 @@ IMPORT(_Exit);
IMPORT(__os_snprintf);
IMPORT(DisassemblePPCRange);
IMPORT(DCInvalidateRange);
IMPORT(DCFlushRange);
IMPORT(DCStoreRange);
IMPORT(DCStoreRangeNoSync);
IMPORT(__gh_errno_ptr);
IMPORT(MEMGetBaseHeapHandle);
IMPORT(MEMCreateExpHeapEx);
IMPORT(MEMDestroyExpHeap);
@ -48,6 +56,7 @@ IMPORT(MEMGetAllocatableSizeForFrmHeapEx);
IMPORT(FSInit);
IMPORT(FSShutdown);
IMPORT(FSAddClient);
IMPORT(FSAddClientEx);
IMPORT(FSDelClient);
IMPORT(FSInitCmdBlock);
IMPORT(FSChangeDir);
@ -77,6 +86,13 @@ IMPORT(IOS_Close);
IMPORT(IOS_Ioctl);
IMPORT(IOS_IoctlAsync);
IMPORT(IMIsAPDEnabled);
IMPORT(IMIsDimEnabled);
IMPORT(IMEnableAPD);
IMPORT(IMEnableDim);
IMPORT(IMDisableAPD);
IMPORT(IMDisableDim);
IMPORT_END();
/* nsysnet */
@ -84,6 +100,11 @@ IMPORT_BEGIN(nsysnet);
IMPORT(socket_lib_init);
IMPORT(socket);
IMPORT(setsockopt);
IMPORT(bind);
IMPORT(listen);
IMPORT(accept);
IMPORT(recv);
IMPORT(socketclose);
IMPORT(connect);
IMPORT(send);
@ -191,6 +212,7 @@ IMPORT(WPADEnableURCC);
IMPORT(WPADEnableWiiRemote);
IMPORT(WPADRead);
IMPORT(KPADRead);
IMPORT(KPADReadEx);
IMPORT_END();
@ -201,3 +223,22 @@ IMPORT(KBDSetup);
IMPORT(KBDTeardown);
IMPORT_END();
/* syshid */
IMPORT_BEGIN(nsyshid);
IMPORT(HIDSetup);
IMPORT(HIDTeardown);
IMPORT(HIDAddClient);
IMPORT(HIDDelClient);
IMPORT(HIDGetDescriptor);
IMPORT(HIDSetDescriptor);
IMPORT(HIDGetReport);
IMPORT(HIDSetReport);
IMPORT(HIDSetIdle);
IMPORT(HIDSetProtocol);
IMPORT(HIDGetProtocol);
IMPORT(HIDRead);
IMPORT(HIDWrite);
IMPORT_END();