From ec6e7620d9a88569273dbeaf9be4dbd605809ae2 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 16 Jun 2020 16:11:01 +0930 Subject: [PATCH 01/23] Project64-input: Add basic project --- Source/Project64-input/ControllerSpec1.1.h | 224 ++++++++++++++++++ Source/Project64-input/InputMain.cpp | 181 ++++++++++++++ .../Project64-input/Project64-input.vcxproj | 58 +++++ .../Project64-input.vcxproj.filters | 32 +++ Source/Project64-input/Version.h.in | 43 ++++ 5 files changed, 538 insertions(+) create mode 100644 Source/Project64-input/ControllerSpec1.1.h create mode 100644 Source/Project64-input/InputMain.cpp create mode 100644 Source/Project64-input/Project64-input.vcxproj create mode 100644 Source/Project64-input/Project64-input.vcxproj.filters create mode 100644 Source/Project64-input/Version.h.in diff --git a/Source/Project64-input/ControllerSpec1.1.h b/Source/Project64-input/ControllerSpec1.1.h new file mode 100644 index 000000000..11cd0efcc --- /dev/null +++ b/Source/Project64-input/ControllerSpec1.1.h @@ -0,0 +1,224 @@ +/********************************************************************************** +Project64 Controller plugin spec, version #1.1 +**********************************************************************************/ +#pragma once + +#include + +enum { PLUGIN_TYPE_CONTROLLER = 4 }; + +#if defined(_WIN32) +#define EXPORT extern "C" __declspec(dllexport) +#define CALL __cdecl +#else +#define EXPORT extern "C" __attribute__((visibility("default"))) +#define CALL +#endif + +enum +{ + CONTROLLER_SPECS_VERSION = 0x0102 +}; + +enum +{ + PLUGIN_NONE = 1, + PLUGIN_MEMPAK = 2, + PLUGIN_RUMBLE_PAK = 3, + PLUGIN_TRANSFER_PAK = 4, + PLUGIN_RAW = 5, +}; + +/***** Structures *****/ +typedef struct +{ + uint16_t Version; /* Should be set to 0x0101 */ + uint16_t Type; /* Set to PLUGIN_TYPE_CONTROLLER */ + char Name[100]; /* Name of the DLL */ + int32_t NormalMemory; + int32_t MemoryBswaped; +} PLUGIN_INFO; + +typedef struct +{ + int32_t Present; + int32_t RawData; + int32_t Plugin; +} CONTROL; + +#pragma warning(push) +#pragma warning(disable : 4201) // warning C4201: nonstandard extension used : nameless struct/union + +typedef union +{ + uint32_t Value; + struct + { + unsigned R_DPAD : 1; + unsigned L_DPAD : 1; + unsigned D_DPAD : 1; + unsigned U_DPAD : 1; + unsigned START_BUTTON : 1; + unsigned Z_TRIG : 1; + unsigned B_BUTTON : 1; + unsigned A_BUTTON : 1; + + unsigned R_CBUTTON : 1; + unsigned L_CBUTTON : 1; + unsigned D_CBUTTON : 1; + unsigned U_CBUTTON : 1; + unsigned R_TRIG : 1; + unsigned L_TRIG : 1; + unsigned Reserved1 : 1; + unsigned Reserved2 : 1; + + signed Y_AXIS : 8; + + signed X_AXIS : 8; + }; +} BUTTONS; + +#pragma warning(pop) + +typedef struct +{ + void * hwnd; + void * hinst; + int32_t MemoryBswaped; // Set this to true + uint8_t * HEADER; // This is the rom header (first 40h bytes of the rom) + CONTROL * Controls; // A pointer to an array of 4 controllers .. eg: +} CONTROL_INFO; + +/****************************************************************** + Function: CloseDLL + Purpose: This function is called when the emulator is closing + down allowing the dll to de-initialise. + input: none + output: none + *******************************************************************/ +EXPORT void CALL CloseDLL(void); + +/****************************************************************** + Function: ControllerCommand + Purpose: To process the raw data that has just been sent to a + specific controller. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + + note: This function is only needed if the DLL is allowing raw + data, or the plugin is set to raw + + the data that is being processed looks like this: + initilize controller: 01 03 00 FF FF FF + read controller: 01 04 01 FF FF FF FF + *******************************************************************/ +EXPORT void CALL ControllerCommand(int32_t Control, uint8_t * Command); + +/****************************************************************** + Function: DllAbout + Purpose: This function is optional function that is provided + to give further information about the DLL. + input: a handle to the window that calls this function + output: none + *******************************************************************/ +EXPORT void CALL DllAbout(void * hParent); + +/****************************************************************** + Function: DllConfig + Purpose: This function is optional function that is provided + to allow the user to configure the dll + input: a handle to the window that calls this function + output: none + *******************************************************************/ +EXPORT void CALL DllConfig(void * hParent); + +/****************************************************************** + Function: DllTest + Purpose: This function is optional function that is provided + to allow the user to test the dll + input: a handle to the window that calls this function + output: none + *******************************************************************/ +EXPORT void CALL DllTest(void * hParent); + +/****************************************************************** + Function: GetDllInfo + Purpose: This function allows the emulator to gather information + about the dll by filling in the PluginInfo structure. + input: a pointer to a PLUGIN_INFO stucture that needs to be + filled by the function. (see def above) + output: none + *******************************************************************/ +EXPORT void CALL GetDllInfo(PLUGIN_INFO * PluginInfo); + +/****************************************************************** + Function: GetKeys + Purpose: To get the current state of the controllers buttons. + input: - Controller Number (0 to 3) + - A pointer to a BUTTONS structure to be filled with + the controller state. + output: none + *******************************************************************/ +EXPORT void CALL GetKeys(int32_t Control, BUTTONS * Keys); + +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - The handle to the main window. + - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none + *******************************************************************/ +EXPORT void CALL InitiateControllers(CONTROL_INFO * ControlInfo); + +/****************************************************************** + Function: ReadController + Purpose: To process the raw data in the pif ram that is about to + be read. + input: - Controller Number (0 to 3) and -1 signalling end of + processing the pif ram. + - Pointer of data to be processed. + output: none + note: This function is only needed if the DLL is allowing raw + data. + *******************************************************************/ +EXPORT void CALL ReadController(int Control, uint8_t * Command); + +/****************************************************************** + Function: RomClosed + Purpose: This function is called when a rom is closed. + input: none + output: none + *******************************************************************/ +EXPORT void CALL RomClosed(void); + +/****************************************************************** + Function: RomOpen + Purpose: This function is called when a rom is open. (from the + emulation thread) + input: none + output: none + *******************************************************************/ +EXPORT void CALL RomOpen(void); + +/****************************************************************** + Function: WM_KeyDown + Purpose: To pass the WM_KeyDown message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none + *******************************************************************/ +EXPORT void CALL WM_KeyDown(uint32_t wParam, uint32_t lParam); + +/****************************************************************** + Function: WM_KeyUp + Purpose: To pass the WM_KEYUP message from the emulator to the + plugin. + input: wParam and lParam of the WM_KEYDOWN message. + output: none + *******************************************************************/ +EXPORT void CALL WM_KeyUp(uint32_t wParam, uint32_t lParam); + diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp new file mode 100644 index 000000000..82ded80d8 --- /dev/null +++ b/Source/Project64-input/InputMain.cpp @@ -0,0 +1,181 @@ +/**************************************************************************** +* * +* Project64-audio - A Nintendo 64 audio plugin. * +* http://www.pj64-emu.com/ * +* Copyright (C) 2020 Project64. All rights reserved. * +* * +* License: * +* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * +* * +****************************************************************************/ +#include "ControllerSpec1.1.h" +#include "Version.h" +#include + +/****************************************************************** +Function: CloseDLL +Purpose: This function is called when the emulator is closing +down allowing the dll to de-initialise. +input: none +output: none +*******************************************************************/ +EXPORT void CALL CloseDLL(void) +{ +} + +/****************************************************************** +Function: ControllerCommand +Purpose: To process the raw data that has just been sent to a +specific controller. +input: - Controller Number (0 to 3) and -1 signalling end of +processing the pif ram. +- Pointer of data to be processed. +output: none + +note: This function is only needed if the DLL is allowing raw +data, or the plugin is set to raw + +the data that is being processed looks like this: +initilize controller: 01 03 00 FF FF FF +read controller: 01 04 01 FF FF FF FF +*******************************************************************/ +EXPORT void CALL ControllerCommand(int32_t /*Control*/, uint8_t * /*Command*/) +{ +} + +/****************************************************************** +Function: DllAbout +Purpose: This function is optional function that is provided +to give further information about the DLL. +input: a handle to the window that calls this function +output: none +*******************************************************************/ +/*EXPORT void CALL DllAbout(void * hParent) +{ +}*/ + +/****************************************************************** +Function: DllConfig +Purpose: This function is optional function that is provided +to allow the user to configure the dll +input: a handle to the window that calls this function +output: none +*******************************************************************/ +EXPORT void CALL DllConfig(void * /*hParent*/) +{ +} + +/****************************************************************** +Function: DllTest +Purpose: This function is optional function that is provided +to allow the user to test the dll +input: a handle to the window that calls this function +output: none +*******************************************************************/ +EXPORT void CALL DllTest(void * /*hParent*/) +{ +} + +/****************************************************************** +Function: GetDllInfo +Purpose: This function allows the emulator to gather information +about the dll by filling in the PluginInfo structure. +input: a pointer to a PLUGIN_INFO stucture that needs to be +filled by the function. (see def above) +output: none +*******************************************************************/ +EXPORT void CALL GetDllInfo(PLUGIN_INFO * PluginInfo) +{ + PluginInfo->Version = CONTROLLER_SPECS_VERSION; + PluginInfo->Type = PLUGIN_TYPE_CONTROLLER; +#ifdef _DEBUG + sprintf(PluginInfo->Name, "Project64 Input Plugin (Debug): %s", VER_FILE_VERSION_STR); +#else + sprintf(PluginInfo->Name, "Project64 Input Plugin: %s", VER_FILE_VERSION_STR); +#endif + PluginInfo->MemoryBswaped = true; + PluginInfo->NormalMemory = false; +} + +/****************************************************************** +Function: GetKeys +Purpose: To get the current state of the controllers buttons. +input: - Controller Number (0 to 3) +- A pointer to a BUTTONS structure to be filled with +the controller state. +output: none +*******************************************************************/ +EXPORT void CALL GetKeys(int32_t /*Control*/, BUTTONS * /*Keys*/) +{ +} + +/****************************************************************** + Function: InitiateControllers + Purpose: This function initialises how each of the controllers + should be handled. + input: - A controller structure that needs to be filled for + the emulator to know how to handle each controller. + output: none +*******************************************************************/ +EXPORT void CALL InitiateControllers(CONTROL_INFO * /*ControlInfo*/) +{ +} + +/****************************************************************** +Function: ReadController +Purpose: To process the raw data in the pif ram that is about to +be read. +input: - Controller Number (0 to 3) and -1 signalling end of +processing the pif ram. +- Pointer of data to be processed. +output: none +note: This function is only needed if the DLL is allowing raw +data. +*******************************************************************/ +EXPORT void CALL ReadController(int /*Control*/, uint8_t * /*Command*/) +{ +} + +/****************************************************************** +Function: RomClosed +Purpose: This function is called when a rom is closed. +input: none +output: none +*******************************************************************/ +EXPORT void CALL RomClosed(void) +{ +} + +/****************************************************************** +Function: RomOpen +Purpose: This function is called when a rom is open. (from the +emulation thread) +input: none +output: none +*******************************************************************/ +EXPORT void CALL RomOpen(void) +{ +} + +/****************************************************************** +Function: WM_KeyDown +Purpose: To pass the WM_KeyDown message from the emulator to the +plugin. +input: wParam and lParam of the WM_KEYDOWN message. +output: none +*******************************************************************/ +EXPORT void CALL WM_KeyDown(uint32_t /*wParam*/, uint32_t /*lParam*/) +{ +} + +/****************************************************************** +Function: WM_KeyUp +Purpose: To pass the WM_KEYUP message from the emulator to the +plugin. +input: wParam and lParam of the WM_KEYDOWN message. +output: none +*******************************************************************/ +EXPORT void CALL WM_KeyUp(uint32_t /*wParam*/, uint32_t /*lParam*/) +{ +} + diff --git a/Source/Project64-input/Project64-input.vcxproj b/Source/Project64-input/Project64-input.vcxproj new file mode 100644 index 000000000..73941f6c4 --- /dev/null +++ b/Source/Project64-input/Project64-input.vcxproj @@ -0,0 +1,58 @@ + + + + + Debug + Win32 + + + Debug + x64 + + + Release + Win32 + + + Release + x64 + + + + {D3F979CE-8FA7-48C9-A2B3-A33594B48536} + Win32Proj + Project64input + + + DynamicLibrary + + + + + + + + + Project64-Input + Project64-Input_d + $(SolutionDir)Plugin\Input\ + $(SolutionDir)Plugin64\Input\ + + + + NotUsing + + + "$(SolutionDir)Source\Script\UpdateVersion.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)Source\Project64-input\Version.h.in" "$(SolutionDir)Source\Project64-input\Version.h" + + + + + + + + + + + + \ No newline at end of file diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters new file mode 100644 index 000000000..38409f07c --- /dev/null +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -0,0 +1,32 @@ + + + + + {4FC737F1-C7A5-4376-A066-2A32D752A2FF} + cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx + + + {93995380-89BD-4b04-88EB-625FBE52EBFB} + h;hh;hpp;hxx;hm;inl;inc;xsd + + + {67DA6AB6-F800-4c08-8B7A-83BB121AAD01} + rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms + + + + + Source Files + + + + + Header Files + + + + + Header Files + + + \ No newline at end of file diff --git a/Source/Project64-input/Version.h.in b/Source/Project64-input/Version.h.in new file mode 100644 index 000000000..e26272109 --- /dev/null +++ b/Source/Project64-input/Version.h.in @@ -0,0 +1,43 @@ +/**************************************************************************** +* * +* Project64-input - A Nintendo 64 audio plugin. * +* http://www.pj64-emu.com/ * +* Copyright (C) 2020 Project64. All rights reserved. * +* * +* License: * +* GNU/GPLv2 http://www.gnu.org/licenses/gpl-2.0.html * +* * +****************************************************************************/ +#define STRINGIZE2(s) #s +#define STRINGIZE(s) STRINGIZE2(s) + +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 +#define VERSION_REVISION 0 +#define VERSION_BUILD 9999 +#define GIT_VERSION "" + +#define VER_FILE_DESCRIPTION_STR "Project64-input" +#define VER_FILE_VERSION VERSION_MAJOR, VERSION_MINOR, VERSION_REVISION, VERSION_BUILD +#define VER_FILE_VERSION_STR STRINGIZE(VERSION_MAJOR) \ + "." STRINGIZE(VERSION_MINOR) \ + "." STRINGIZE(VERSION_REVISION) \ + "." STRINGIZE(VERSION_BUILD) \ + "-" GIT_VERSION + +#define VER_PRODUCTNAME_STR "Project64-input" +#define VER_PRODUCT_VERSION VER_FILE_VERSION +#define VER_PRODUCT_VERSION_STR VER_FILE_VERSION_STR +#define VER_ORIGINAL_FILENAME_STR VER_PRODUCTNAME_STR ".dll" +#define VER_INTERNAL_NAME_STR VER_PRODUCTNAME_STR +#define VER_COPYRIGHT_STR "Copyright (C) 2020" + +#ifdef _DEBUG +#define VER_VER_DEBUG VS_FF_DEBUG +#else +#define VER_VER_DEBUG 0 +#endif + +#define VER_FILEOS VOS_NT_WINDOWS32 +#define VER_FILEFLAGS VER_VER_DEBUG +#define VER_FILETYPE VFT_DLL From 51b78c117e085da73dd8a87039472fd3edabc659 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 16 Jun 2020 17:10:03 +0930 Subject: [PATCH 02/23] Plugin-input: Add version resource --- Source/Project64-input/InputMain.cpp | 3 +++ Source/Project64-input/Project64-input.rc | Bin 0 -> 4782 bytes Source/Project64-input/Project64-input.vcxproj | 4 ++++ .../Project64-input.vcxproj.filters | 8 ++++++++ Source/Project64-input/resource.h | 14 ++++++++++++++ 5 files changed, 29 insertions(+) create mode 100644 Source/Project64-input/Project64-input.rc create mode 100644 Source/Project64-input/resource.h diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp index 82ded80d8..5ffe03b73 100644 --- a/Source/Project64-input/InputMain.cpp +++ b/Source/Project64-input/InputMain.cpp @@ -179,3 +179,6 @@ EXPORT void CALL WM_KeyUp(uint32_t /*wParam*/, uint32_t /*lParam*/) { } +EXPORT void CALL PluginLoaded(void) +{ +} \ No newline at end of file diff --git a/Source/Project64-input/Project64-input.rc b/Source/Project64-input/Project64-input.rc new file mode 100644 index 0000000000000000000000000000000000000000..72b4b4519a1a721946ec8ae80e2c1fca93bc6a1f GIT binary patch literal 4782 zcmds*TW=CU6oAjOiT`1xFE*N%YF~V8fg+ItDVJ!{gw#@yq=kk{)WqMeerJZ$-Pv8L zf)8jm%j}#z_uHK1$M-`ylt|8HEY~uVsm!^DvH;ctHkYMb$t}B*yx@vtBsVhQo&jI5 z4uH*Am2Sz?HO~<{z~L4$^at`u3Tv@@P|c7qM&bnS zhO1Kc9M7SXp?aK1OWM+ru9T%FP3g;pRDhOwZb)4|0BQ4kE~h~1Je#hn@9tfuovo2n z@kTlxL;N$9JM3TJ9rZ&8tKaim!|D=tsy`~gUva0S_v?6lcK-Erq5pT!W2TYMjwQa* ztQ%tYX1QUWH@>^InsyPW%;XYIi==Yt}I?x8tE^F20sX;tm z72Y*!^{u>wcN@G@Af6_T(dVtN>e!a`8KCvi!;*JME&p@9Aiv5jCv?^O2%qI+M(+J7 zwpU%JQ0!=R<#*{zDXu!T#?O09skEYR`~j}2~?^r*f*I2G!=?atr^d$s(G zI#cT88-pu#1V)XzuB33xtG0R${Rix{G|#Jr{3aRNr9*Yrax`8cc0Nbb?#%U`D%PFT zgWB{C(@fW*e4*lo;Dk2CR7q@mHa)U3LM~0@8BKOgb5ZP&zQgR(!oyiwg{0{XJLKW} zuf0oiQu~W5>+?H{_UR=c=VtOlu0=UUi#OcI z@{!-LYs55pozLFd+9S$3L8;dY4?337GdcD8>9pWZsI(vTe5_z;iJYwAf1S&89@Sa2 z15EkGeaz&h*L*#~YFsDZYZTYx=5jSQI#bM8^-H0_?;ZP4vevbp2N$gBy}nz|fox-Q z9XTT>wM2H@%U72 + + + + \ No newline at end of file diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters index 38409f07c..867a5d551 100644 --- a/Source/Project64-input/Project64-input.vcxproj.filters +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -23,10 +23,18 @@ Header Files + + Header Files + Header Files + + + Resource Files + + \ No newline at end of file diff --git a/Source/Project64-input/resource.h b/Source/Project64-input/resource.h new file mode 100644 index 000000000..0195a572e --- /dev/null +++ b/Source/Project64-input/resource.h @@ -0,0 +1,14 @@ +//{{NO_DEPENDENCIES}} +// Microsoft Visual C++ generated include file. +// Used by Project64-input.rc + +// Next default values for new objects +// +#ifdef APSTUDIO_INVOKED +#ifndef APSTUDIO_READONLY_SYMBOLS +#define _APS_NEXT_RESOURCE_VALUE 101 +#define _APS_NEXT_COMMAND_VALUE 40001 +#define _APS_NEXT_CONTROL_VALUE 1001 +#define _APS_NEXT_SYMED_VALUE 101 +#endif +#endif From be939dca6582f0cdc562e578eec4c6472528f8c6 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 17 Jun 2020 16:53:10 +0930 Subject: [PATCH 03/23] Project64-input: Add base config UI --- .gitignore | 5 + Project64.sln | 13 +++ Source/Project64-input/Controller.bmp | Bin 0 -> 85438 bytes Source/Project64-input/InputConfigUI.cpp | 83 ++++++++++++++++ Source/Project64-input/InputConfigUI.h | 3 + Source/Project64-input/InputMain.cpp | 6 +- Source/Project64-input/Project64-input.rc | Bin 4782 -> 17130 bytes .../Project64-input/Project64-input.vcxproj | 13 +++ .../Project64-input.vcxproj.filters | 20 ++++ Source/Project64-input/resource.h | Bin 395 -> 8274 bytes Source/Project64-input/wtl-BitmapPicture.cpp | 92 ++++++++++++++++++ Source/Project64-input/wtl-BitmapPicture.h | 34 +++++++ Source/Project64-input/wtl.h | 15 +++ 13 files changed, 283 insertions(+), 1 deletion(-) create mode 100644 Source/Project64-input/Controller.bmp create mode 100644 Source/Project64-input/InputConfigUI.cpp create mode 100644 Source/Project64-input/InputConfigUI.h create mode 100644 Source/Project64-input/wtl-BitmapPicture.cpp create mode 100644 Source/Project64-input/wtl-BitmapPicture.h create mode 100644 Source/Project64-input/wtl.h diff --git a/.gitignore b/.gitignore index 28bf983c2..66d4f78b9 100644 --- a/.gitignore +++ b/.gitignore @@ -50,6 +50,8 @@ Thumbs.db /Plugin/Input/AndroidInput_d.dll /Plugin/Input/PJ64_NRage.dll /Plugin/Input/PJ64_NRage_d.dll +/Plugin/Input/Project64-Input.dll +/Plugin/Input/Project64-Input_d.dll /Plugin/RSP/lib /Plugin/RSP/map /Plugin/RSP/pdb @@ -76,6 +78,8 @@ Thumbs.db /Plugin64/Input/AndroidInput_d.dll /Plugin64/Input/PJ64_NRage.dll /Plugin64/Input/PJ64_NRage_d.dll +/Plugin64/Input/Project64-Input.dll +/Plugin64/Input/Project64-Input_d.dll /Plugin64/RSP/lib /Plugin64/RSP/map /Plugin64/RSP/pdb @@ -86,6 +90,7 @@ Thumbs.db /Source/nragev20/Version.h /Source/Project64-audio/Version.h /Source/Project64-core/Version.h +/Source/Project64-input/Version.h /Source/Project64-video/Version.h /Source/RSP/Version.h /Save diff --git a/Project64.sln b/Project64.sln index da1bb17f1..158d826a4 100644 --- a/Project64.sln +++ b/Project64.sln @@ -60,9 +60,14 @@ EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "JoinSettings", "Source\JoinSettings\JoinSettings.vcxproj", "{B2E592F2-F416-4049-BD22-9CA9090242BB}" EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project64", "Source\Project64\Project64.vcxproj", "{7E534C8E-1ACE-4A88-8807-39A11ED4DA18}" + ProjectSection(ProjectDependencies) = postProject + {D3F979CE-8FA7-48C9-A2B3-A33594B48536} = {D3F979CE-8FA7-48C9-A2B3-A33594B48536} + EndProjectSection EndProject Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "discord-rpc", "Source\3rdParty\discord-rpc\discord-rpc.vcxproj", "{DCC841B2-298A-40F0-84D1-ACBABD3B86E8}" EndProject +Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "Project64-input", "Source\Project64-input\Project64-input.vcxproj", "{D3F979CE-8FA7-48C9-A2B3-A33594B48536}" +EndProject Global GlobalSection(SolutionConfigurationPlatforms) = preSolution Debug|Win32 = Debug|Win32 @@ -222,6 +227,14 @@ Global {DCC841B2-298A-40F0-84D1-ACBABD3B86E8}.Release|Win32.Build.0 = Release|Win32 {DCC841B2-298A-40F0-84D1-ACBABD3B86E8}.Release|x64.ActiveCfg = Release|x64 {DCC841B2-298A-40F0-84D1-ACBABD3B86E8}.Release|x64.Build.0 = Release|x64 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Debug|Win32.ActiveCfg = Debug|Win32 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Debug|Win32.Build.0 = Debug|Win32 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Debug|x64.ActiveCfg = Debug|x64 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Debug|x64.Build.0 = Debug|x64 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Release|Win32.ActiveCfg = Release|Win32 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Release|Win32.Build.0 = Release|Win32 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Release|x64.ActiveCfg = Release|x64 + {D3F979CE-8FA7-48C9-A2B3-A33594B48536}.Release|x64.Build.0 = Release|x64 EndGlobalSection GlobalSection(SolutionProperties) = preSolution HideSolutionNode = FALSE diff --git a/Source/Project64-input/Controller.bmp b/Source/Project64-input/Controller.bmp new file mode 100644 index 0000000000000000000000000000000000000000..c1df41469d87b76f0bceeae0f50f4b7f1dc3b8f4 GIT binary patch literal 85438 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 YYZRQs!k{h2TXRECOnR5z(<^ZL|9!mC{{R30 literal 0 HcmV?d00001 diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp new file mode 100644 index 000000000..179b2a273 --- /dev/null +++ b/Source/Project64-input/InputConfigUI.cpp @@ -0,0 +1,83 @@ +#include "InputConfigUI.h" +#include "wtl.h" +#include "wtl-BitmapPicture.h" +#include +#include +#include "resource.h" + +class CControllerSettings : + public CPropertyPageImpl +{ +public: + enum { IDD = IDD_Controller }; + + BEGIN_MSG_MAP(CDebugSettings) + MSG_WM_INITDIALOG(OnInitDialog) + CHAIN_MSG_MAP(CPropertyPageImpl) + END_MSG_MAP() + + CControllerSettings(); + void SetControllerNumber(uint32_t ControllerNumber); + BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/); + +private: + std::wstring m_Title; + uint32_t m_ControllerNumber; + CBitmapPicture m_ControllerImg; +}; + +CControllerSettings::CControllerSettings() : + m_ControllerNumber((uint32_t)-1) +{ +} + +void CControllerSettings::SetControllerNumber(uint32_t ControllerNumber) +{ + m_Title = stdstr_f("Player %d", ControllerNumber + 1).ToUTF16(); + SetTitle(m_Title.c_str()); + m_ControllerNumber = ControllerNumber; +} + +BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) +{ + m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); + m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); + return TRUE; +} + +class CInputConfigUI: + public CPropertySheetImpl +{ +public: + CInputConfigUI(); + ~CInputConfigUI(); + + void OnSheetInitialized(); + +private: + CControllerSettings m_pgController[4]; +}; + +void ConfigInput(void * hParent) +{ + CInputConfigUI().DoModal((HWND)hParent); +} + +CInputConfigUI::CInputConfigUI() +{ + m_psh.pszCaption = L"Configure Input"; + for (size_t i = 0, n = sizeof(m_pgController) / sizeof(m_pgController[0]); i < n; i++) + { + m_pgController[i].SetControllerNumber(i); + AddPage(&m_pgController[i].m_psp); + } +} + +CInputConfigUI::~CInputConfigUI() +{ +} + +void CInputConfigUI::OnSheetInitialized() +{ + ModifyStyleEx(WS_EX_CONTEXTHELP,0); +} diff --git a/Source/Project64-input/InputConfigUI.h b/Source/Project64-input/InputConfigUI.h new file mode 100644 index 000000000..3646a5449 --- /dev/null +++ b/Source/Project64-input/InputConfigUI.h @@ -0,0 +1,3 @@ +#pragma once + +void ConfigInput(void * hParent); diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp index 5ffe03b73..a48d62d24 100644 --- a/Source/Project64-input/InputMain.cpp +++ b/Source/Project64-input/InputMain.cpp @@ -9,6 +9,7 @@ * * ****************************************************************************/ #include "ControllerSpec1.1.h" +#include "InputConfigUI.h" #include "Version.h" #include @@ -61,9 +62,12 @@ to allow the user to configure the dll input: a handle to the window that calls this function output: none *******************************************************************/ -EXPORT void CALL DllConfig(void * /*hParent*/) +#ifdef _WIN32 +EXPORT void CALL DllConfig(void * hParent) { + ConfigInput(hParent); } +#endif /****************************************************************** Function: DllTest diff --git a/Source/Project64-input/Project64-input.rc b/Source/Project64-input/Project64-input.rc index 72b4b4519a1a721946ec8ae80e2c1fca93bc6a1f..c4d6335786fe6abcf09e61acf37c3291ade57148 100644 GIT binary patch literal 17130 zcmd^HZEqVz5Z=#7{0HL-iHguB&PyArR-E&uQhwj3C?}qN98{zNVjdAS+*GBHfow-Z= zYPhfQskk5A5AF(oLtG!@_yO03II`aj&c4Ta1;04jg}X+ZXYO z{vd6ux&F`GPp(?n`UJg(pl|_-R~X&elFAbq^IT|;|sm_HcC< z=SQyP-r`CZ--m7oS6VnXUdeCyKE|CLEA9Z&$l`Gh`FwQ0VE$uBhjQp))~EPxV%81J zlk(WZ^&0-N=*`CKlgL;5#quwo#Ec`=jvL5|T6d0lKTJ1F@-}X{j>cUD=w88AFM-qu zI#6+60rM;TGMnwd5F6^fd>uP}V0NT~U zhvWWLjR{iwS}ukxZ20@K=jnEXuAW9-Gr^aaw{0Si*`G>qJ6S0 z2DqzM?dMXg0kn@3%;Ytw?*8X|LE6eqCwS!F8f2DkS&{oYnEQcv3bw9HK4~xg-mOkN zHStr4u^0WyLujO;L)GQ|P1U`J-+B*?);Qt0EaGVWfgIhJ&J*#+A7E+pG5Vp8Nco$* zwi!m{@+u)WzXKi3o8FkZr0l zcSWZ8nX_jT(rZD^^qi-V;;MK_{oZivuzz~ZntOqBj>-J!tzg35U5wmC&mMd`bEF>H z(u3=reT;sJyZrSQe|qnY^lHE#H!+TS0n!df);7GF)rL0sWmZO7BOHZq;>|~Va~LR?_YrfGum(Qn^EHo z-+ze4u>~{b3h1rk^QCY@Y#NxMr^8sN8Rt8Z=N@>b>{sNEXWKYmcQ1u&0*rjBebC9pW*krsOQZI5*?9|YSE_5gc?cd#ZsF^{WPLQ zgc%vr)HZ?2ird78(o>Xpr7JqijGVT}nA?=tsyVgCotn@A1-1yeY)kI^3K~Qkq7@xQ zvZ_Wr?x4j{lEWHw#&ftP=lV^r9aZ^U=_JPHb^i=pL<%d8Dp3wI$Mq*5=1xRG_ud9+>Gcf7k_| z)cdVlA4OZB{|@zew)XVlebZL%X=;AO=gKx{tclgVoapo-Exm~1hS1X3w1GL2hsU$_ zA}+TlUXK<&kM7LIY!{L46Jp(6akE^e z3%L$go$rbvGu(aHzhOx3n5C_WR2Sv7^C)_{iX!RK=F5nq=T&huUYCnxM?CpY_rOx4 z@T&;TnmiRTZ&+Lm&Z8MpHau(MQOk&D$gLr&+|GljkE=zoxenjTsLZtpK825gFrT-I zqBGZFZ3Tk)oIZDHd}g%Nh_EVgb32n^&Gz=i5jvzBM`wBk<^%Q|6XpaBa5()rpePeh z(K9XDl4tG5*P;}UraQ{xJi0R*t?98j=FZ0*&8hh8$-HKHVi}gD2m4EvQa!k+~pcz7-wzGse=g1H>6xcGt_itKkY4bCBJwz zHl|UR^+CSZ^;DL-?rJO5ItN?Bs@?PHJzR!^Mh!=bH@;op2X}p`7trSd&CmJ7 zMvr7`8OxDg7ySJSK8vN-1$QU%MCqkBKWDSo2(=Puwg;^c;M;0l_tI*eO?lE= z?25%Sx>|8jgVrl@k6m+7%qwN0mY}@O<2z?dW({1!=!m6S<&|Q|c)hF$ z{Z8nq-!ChMjgN&W@}S-NWozk8*_XBdK1syFBubRqf|e>zLkm zlCJ~j-Urr0?jc(6E@>3gO4quwe^H$E`?LO18hXj>piwMs_bd66e12qPJd*E|+T~++?RX*{qAyab-tx$NH{9W=J24pt z@^aJ~Zml41LjJ4=P`h9z$6X-Y%TvVVbUtEhETXT-n$>Z4!$av38}6SQ;>e1KBYbnO zKuno-t<|<#2Qk3!I_!n@><_2SRmdNODtEkGyWc03$*i=A=`+%|q3eECW*)l76FSsV z&e`;ozw&cu9kJGC+T6{m7a@Z-c=?DpdL#A!Y3aw_EK60b*|aJ?#=0KUnx<(n#jO9l zo9ul|HJ + + + + + @@ -59,4 +64,12 @@ + + + + + + {b4a4b994-9111-42b1-93c2-6f1ca8bc4421} + + \ No newline at end of file diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters index 867a5d551..a54fc15c4 100644 --- a/Source/Project64-input/Project64-input.vcxproj.filters +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -18,6 +18,12 @@ Source Files + + Source Files + + + Source Files + @@ -26,6 +32,15 @@ Header Files + + Header Files + + + Header Files + + + Header Files + @@ -37,4 +52,9 @@ Resource Files + + + Resource Files + + \ No newline at end of file diff --git a/Source/Project64-input/resource.h b/Source/Project64-input/resource.h index 0195a572e8cb23328df4c97ac8f1c009e4d8e6ad..5edaf54828d6d05efd89afc0c33b8696b57a9b6b 100644 GIT binary patch literal 8274 zcmbW6TW{M&5QXPCK>ve)JO+(pJHGT$w>W}rS+FFx@r#f+QQ*Lc17DIBMgMx6Gdtcc zSL7a!1VSRYAU_Ug=FIML|ND1Kw&ZVYV>y$B3}h%1{KnyEEPWZ_Y%2d?`$eAN+AZnG zsa(sI+{vxnULNJW+~BM)FR*pwvwV`T_}!uX0sD_=yGF|uu6o4TC!8va3JHU$|xxp7sT8SK#c+Yxy;BzJc<9JMYjQ?bH49z*e$8y@R(HNDuGV z$6JnNCg<3nU>oA7-R`xA5ecs zcJ7hOVhm#zn%##kb|0Bu^|#iPH?4W{+eU2j&)Xth?be@1m#cQqQDfu#H|>q>)8#6A z0QLWlYS6^hHe+*Lmh!tz^~UzW%Hy<$4)zY@c?tsvL#NGD4L)3H60#p|O41 zsk3<&8r!FxI-6&qv3=U9vw0ROd&jArE^=A@d z#^$8=LErv6;t>&2^dBx$2p(qb_&JTqhrE=4|GV z#P;ekXR|mawpW)qoB2Aixh`WJ)Lx;BalYQ?*({b^JCQvF`2xL-hpX2p`*n+U`tnwe z(Th#ckIkRvBRZcQk?~q$^H@&7)S34XJpEU{T!xt-e+RRh$MOiXg)>+@*@(^SU>{#N z^lO3Ie1SLUJAH0;`(ml=H}J?DKAPbROIu8pz1I@UlqW+l+tiqzXlz~wXYvP_>&{#) z2lp_tVq>4kUT=gP*}M+sd9pfAo)ooeKH=k&Dm$+zI&;vxIc|)rvAK4lPjYU1OpVR8 z)68zGg3;f+4mPvfdY#DTx@=~*^$d~Cbs5?9(Fymt`g^}cmt{8hxv_n^tlQ0fZfu_} z>um0GWBYY!-Sx%#+KF?B=@MbTz~5_Ukg~ zUcYvf`$~9QNfAPbC@*P$ERr^~9|z3V%NPF?2gUgKD*>Ls=N(5cIuohm?;S3Nd1*JaZD z`fC}7_{zb?$UV$Sbgr}R3Z~g@x>UZc;Eu5>`e#_T)iu~9R%aivN~!C(-@^*-BUJRL1<%7gk*!y6w@yzmTTyMM%@@;}yjm|=}is;(1&L}T%bc~tL;OSlU zj<4jNb6l&lMqRZ%k$0d>@vpNpUB8_+dQ7uWpS{36!>3t`a;CUv4khSpZUIZQrp<9& zjj|qF_BX|%iLCKB#ishwd2^ZD33G8>H*Fr#mFQ``n$s=P%~i6AZJyLvaBlQTv|3m6 NKVqGG`Q-il{3n^n=hOfI literal 395 zcmZ|JO>2Wd5C-78zhb~+XjBNjTXzmp-4(xRPK(jmvO(6MYd;A2@71=Kgk&xQ^FA|- z=bg`7NQN15hCGU~xLh31gH*TUFb&E=t*5!^A=+%kv@*xlYEckoMOm>} z$e7pS71=sBS3!;;6Fk|=VxPWm+j0KadL>9lg(zxD&gk#p++ diff --git a/Source/Project64-input/wtl-BitmapPicture.cpp b/Source/Project64-input/wtl-BitmapPicture.cpp new file mode 100644 index 000000000..6c1d80b2b --- /dev/null +++ b/Source/Project64-input/wtl-BitmapPicture.cpp @@ -0,0 +1,92 @@ +#include "wtl-BitmapPicture.h" + +CBitmapPicture::CBitmapPicture() : + m_hBitmap(NULL), + m_nResourceID(-1), + m_ResourceIcon(false) +{ + memset(&m_bmInfo, 0, sizeof(m_bmInfo)); + m_BackgroundBrush.CreateSolidBrush(::GetSysColor(COLOR_3DFACE)); +} + +LRESULT CBitmapPicture::OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &/*bHandled*/) +{ + CPaintDC dc(m_hWnd); + CRect rect; + GetClientRect(&rect); + + CBrush PaintBrush; + HBRUSH OldBrush = dc.SelectBrush(m_BackgroundBrush); + dc.PatBlt(rect.left, rect.top, rect.Width(), rect.Height(), PATCOPY); + if (m_ResourceIcon) + { + CIcon hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), m_nResourceID > 0 ? MAKEINTRESOURCE(m_nResourceID) : m_strResourceName.c_str(), IMAGE_ICON, m_IconWidth, m_IconHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + if (!hIcon.IsNull()) + { + dc.DrawIconEx(0, 0, hIcon, rect.Width(), rect.Height(), 0, NULL, DI_NORMAL); + } + } + else + { + CBitmap hBmp = (HBITMAP)::LoadImage(ModuleHelper::GetResourceInstance(), m_nResourceID > 0 ? MAKEINTRESOURCE(m_nResourceID) : m_strResourceName.c_str(), IMAGE_BITMAP, 0, 0, LR_LOADMAP3DCOLORS); + BITMAP bm; + hBmp.GetBitmap(&bm); + + CDC dcMem; + dcMem.CreateCompatibleDC(dc); + dcMem.SelectBitmap(hBmp); + dc.StretchBlt(rect.left, rect.top, rect.Width(), rect.Height(), dcMem, 0, 0, bm.bmWidth, bm.bmHeight, SRCCOPY); + } + dc.SelectBrush(OldBrush); + return 0; +} + +bool CBitmapPicture::SetIcon(LPCWSTR lpszResourceName, uint32_t nWidth, uint32_t nHeight) +{ + CIcon hIcon = (HICON)::LoadImage(ModuleHelper::GetResourceInstance(), lpszResourceName, IMAGE_ICON, nWidth, nHeight, LR_DEFAULTCOLOR | LR_DEFAULTSIZE); + if (hIcon.IsNull()) + { + return false; + } + ICONINFO IconInfo; + if (!hIcon.GetIconInfo(&IconInfo)) + { + return false; + } + if (IS_INTRESOURCE(lpszResourceName)) + { + m_nResourceID = (int)lpszResourceName; + } + else + { + m_strResourceName = lpszResourceName; + } + m_ResourceIcon = true; + m_IconWidth = nWidth; + m_IconHeight = nHeight; + return true; +} + +bool CBitmapPicture::SetBitmap(HBITMAP hBitmap) +{ + m_hBitmap.Attach(hBitmap); + return ::GetObject(m_hBitmap, sizeof(BITMAP), &m_bmInfo) != 0; +} + +void CBitmapPicture::SetBitmap(LPCWSTR lpszResourceName) +{ + if (IS_INTRESOURCE(lpszResourceName)) + { + m_nResourceID = (int)lpszResourceName; + } + else + { + m_strResourceName = lpszResourceName; + } + m_ResourceIcon = false; +} + +void CBitmapPicture::SetBackroundBrush(HBRUSH brush) +{ + m_BackgroundBrush.Attach(brush); +} diff --git a/Source/Project64-input/wtl-BitmapPicture.h b/Source/Project64-input/wtl-BitmapPicture.h new file mode 100644 index 000000000..8f6f779f5 --- /dev/null +++ b/Source/Project64-input/wtl-BitmapPicture.h @@ -0,0 +1,34 @@ +#pragma once +#include "wtl.h" +#include + +class CBitmapPicture : + public CWindowImpl +{ +public: + BEGIN_MSG_MAP(CBitmapPicture) + MESSAGE_HANDLER(WM_PAINT, OnPaint); + END_MSG_MAP() + + CBitmapPicture(); + + LRESULT OnPaint(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL &/*bHandled*/); + + bool SetIcon(LPCWSTR lpszResourceName, uint32_t nWidth, uint32_t nHeight); + void SetBitmap(LPCWSTR lpszResourceName); + void SetBackroundBrush(HBRUSH brush); + +private: + CBitmapPicture(const CBitmapPicture&); + CBitmapPicture& operator=(const CBitmapPicture&); + + bool CBitmapPicture::SetBitmap(HBITMAP hBitmap); + + int m_nResourceID; + std::wstring m_strResourceName; + uint32_t m_IconWidth, m_IconHeight; + bool m_ResourceIcon; + BITMAP m_bmInfo; + CBitmap m_hBitmap; + CBrush m_BackgroundBrush; +}; \ No newline at end of file diff --git a/Source/Project64-input/wtl.h b/Source/Project64-input/wtl.h new file mode 100644 index 000000000..c6a94d8e1 --- /dev/null +++ b/Source/Project64-input/wtl.h @@ -0,0 +1,15 @@ +#pragma once +#pragma warning(push) +#pragma warning(disable : 4091) // warning C4091: 'typedef ': ignored on left of 'tagGPFIDL_FLAGS' when no variable is declared +#pragma warning(disable : 4302) // warning C4302: 'type cast': truncation from 'LPCTSTR' to 'WORD' +#pragma warning(disable : 4458) // warning C4458: declaration of 'dwCommonButtons' hides class member +#pragma warning(disable : 4838) // warning C4838: conversion from 'int' to 'UINT' requires a narrowing conversion +#pragma warning(disable : 4996) // warning C4996: 'GetVersionExA': was declared deprecated +#pragma warning(disable : 4302) // warning C4302: 'type cast': truncation from 'LPCTSTR' to 'WORD' +#pragma warning(disable : 4457) // warning C4457: declaration of 'pstr' hides function parameter +#include +#include +#include +#include +#include +#pragma warning(pop) \ No newline at end of file From f78e292796ac2626b902a3c0310f455592b32175 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 23 Jun 2020 17:17:46 +0930 Subject: [PATCH 04/23] Input plugin: Start to scan keyboard --- Source/Project64-input/Button.h | 27 +++ Source/Project64-input/CProject64Input.cpp | 55 +++++ Source/Project64-input/CProject64Input.h | 36 +++ Source/Project64-input/DirectInput.cpp | 215 ++++++++++++++++++ Source/Project64-input/DirectInput.h | 59 +++++ Source/Project64-input/InputConfigUI.cpp | 75 ++++-- Source/Project64-input/InputMain.cpp | 23 +- Source/Project64-input/N64Controller.h | 20 ++ .../Project64-input/Project64-input.vcxproj | 18 ++ .../Project64-input.vcxproj.filters | 24 ++ Source/Project64-input/Version.h.in | 4 +- Source/Project64-input/wtl-ScanButton.cpp | 156 +++++++++++++ Source/Project64-input/wtl-ScanButton.h | 37 +++ 13 files changed, 730 insertions(+), 19 deletions(-) create mode 100644 Source/Project64-input/Button.h create mode 100644 Source/Project64-input/CProject64Input.cpp create mode 100644 Source/Project64-input/CProject64Input.h create mode 100644 Source/Project64-input/DirectInput.cpp create mode 100644 Source/Project64-input/DirectInput.h create mode 100644 Source/Project64-input/N64Controller.h create mode 100644 Source/Project64-input/wtl-ScanButton.cpp create mode 100644 Source/Project64-input/wtl-ScanButton.h diff --git a/Source/Project64-input/Button.h b/Source/Project64-input/Button.h new file mode 100644 index 000000000..4977657aa --- /dev/null +++ b/Source/Project64-input/Button.h @@ -0,0 +1,27 @@ +#pragma once +#include + +enum BtnType +{ + BTNTYPE_UNASSIGNED = 0, + + // Joystick + BTNTYPE_JOYBUTTON = 1, + BTNTYPE_JOYAXE = 2, + BTNTYPE_JOYPOV = 3, + BTNTYPE_JOYSLIDER = 4, + + // Keyboard + BTNTYPE_KEYBUTTON = 5, + + // Mouse + BTNTYPE_MOUSEBUTTON = 6, + BTNTYPE_MOUSEAXE = 7, +}; + +typedef struct +{ + uint8_t Offset; + uint8_t AxisID; + BtnType BtnType; +} BUTTON; diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp new file mode 100644 index 000000000..c055bd03b --- /dev/null +++ b/Source/Project64-input/CProject64Input.cpp @@ -0,0 +1,55 @@ +#include "CProject64Input.h" + +CProject64Input * g_InputPlugin = nullptr; + +CProject64Input::CProject64Input(HINSTANCE hinst) : + m_hinst(hinst), + m_Scanning(false), + m_DisplayCtrlId(0) +{ + memset(m_Controllers, 0, sizeof(m_Controllers)); +} + +CProject64Input::~CProject64Input() +{ +} + +void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) +{ + if (m_DirectInput.get() == NULL) + { + m_DirectInput.reset(new CDirectInput(m_hinst)); + } + m_DirectInput->Initiate(ControlInfo); +} + +void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) +{ + m_Scanning = true; + m_DisplayCtrlId = DisplayCtrlId; +} + +void CProject64Input::EndScanDevices(void) +{ + m_Scanning = false; + m_DisplayCtrlId = 0; +} + +CDirectInput::ScanResult CProject64Input::ScanDevices(BUTTON & Button) +{ + CDirectInput::ScanResult Result = CDirectInput::SCAN_FAILED; + if (m_DirectInput.get() != NULL) + { + Result = m_DirectInput->ScanDevices(Button); + } + return Result; +} + +std::wstring CProject64Input::ButtonAssignment(BUTTON & Button) +{ + if (m_DirectInput.get() != NULL) + { + return m_DirectInput->ButtonAssignment(Button); + } + return L"Unknown"; +} diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h new file mode 100644 index 000000000..8ce1aac38 --- /dev/null +++ b/Source/Project64-input/CProject64Input.h @@ -0,0 +1,36 @@ +#pragma once +#include "ControllerSpec1.1.h" +#include "DirectInput.h" +#include "N64Controller.h" +#include + +class CProject64Input +{ +public: + CProject64Input(HINSTANCE hinst); + ~CProject64Input(); + + void InitiateControllers(CONTROL_INFO * ControlInfo); + void StartScanDevices(int32_t DisplayCtrlId); + void EndScanDevices(void); + CDirectInput::ScanResult ScanDevices(BUTTON & Button); + std::wstring ButtonAssignment(BUTTON & Button); + + inline HINSTANCE hInst(void) const { return m_hinst; } + inline bool IsScanning(void) const { return m_Scanning; } + inline int32_t DisplayCtrlId(void) const { return m_DisplayCtrlId; } + inline N64CONTROLLER & Controllers(int32_t Controller) { return m_Controllers[Controller]; } + +private: + CProject64Input(); + CProject64Input(const CProject64Input&); + CProject64Input& operator=(const CProject64Input&); + + N64CONTROLLER m_Controllers[4]; + std::unique_ptr m_DirectInput; + HINSTANCE m_hinst; + bool m_Scanning; + int32_t m_DisplayCtrlId; +}; + +extern CProject64Input * g_InputPlugin; \ No newline at end of file diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp new file mode 100644 index 000000000..de9d9c44e --- /dev/null +++ b/Source/Project64-input/DirectInput.cpp @@ -0,0 +1,215 @@ +#include "DirectInput.h" +#include + +CDirectInput::CDirectInput(HINSTANCE hinst) : + m_hDirectInputDLL(nullptr), + m_pDIHandle(nullptr), + m_hinst(hinst), + m_hWnd(nullptr) +{ + LoadConfig(); + if (m_hDirectInputDLL == nullptr) + { + m_hDirectInputDLL = LoadLibrary(L"dinput8.dll"); + } + if (m_hDirectInputDLL != nullptr) + { + typedef HRESULT(WINAPI *tylpGetDIHandle)(HINSTANCE, DWORD, REFIID, LPVOID*, LPUNKNOWN); + tylpGetDIHandle lpGetDIHandle = (tylpGetDIHandle)GetProcAddress(m_hDirectInputDLL, "DirectInput8Create"); + + if (lpGetDIHandle != NULL) + { + HRESULT hr = lpGetDIHandle(m_hinst, DIRECTINPUT_VERSION, IID_IDirectInput8, (LPVOID*)&m_pDIHandle, NULL); + if (FAILED(hr)) + { + return; + } + } + + if (m_pDIHandle != nullptr) + { + m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY); + } + } +} + +CDirectInput::~CDirectInput() +{ + for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++) + { + if (itr->second.didHandle != nullptr) + { + itr->second.didHandle->Release(); + itr->second.didHandle = NULL; + } + } +} + +void CDirectInput::Initiate(CONTROL_INFO * ControlInfo) +{ + m_hWnd = (HWND)ControlInfo->hwnd; +} + +BOOL CDirectInput::stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) +{ + return ((CDirectInput *)pvRef)->EnumMakeDeviceList(lpddi); +} + +BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi) +{ + uint32_t DeviceType = GET_DIDEVICE_TYPE(lpddi->dwDevType); + if (DeviceType == DI8DEVTYPE_DEVICE) + { + // ignore generic devices + return DIENUM_CONTINUE; + } + + DEVICE Device; + Device.didHandle = nullptr; + Device.dwDevType = lpddi->dwDevType; + Device.ProductName = stdstr().FromUTF16(lpddi->tszProductName); + Device.InstanceName = stdstr().FromUTF16(lpddi->tszInstanceName); + HRESULT hResult = m_pDIHandle->CreateDevice(lpddi->guidInstance, &Device.didHandle, NULL); + if (!SUCCEEDED(hResult)) + { + return DIENUM_CONTINUE; + } + + LPCDIDATAFORMAT ppDiDataFormat = NULL; + if (DeviceType == DI8DEVTYPE_KEYBOARD) + { + ppDiDataFormat = &c_dfDIKeyboard; + } + else if (DeviceType == DI8DEVTYPE_MOUSE) + { + ppDiDataFormat = &c_dfDIMouse2; + } + else + { + ppDiDataFormat = &c_dfDIJoystick; + } + hResult = Device.didHandle->SetDataFormat(ppDiDataFormat); + if (!SUCCEEDED(hResult)) + { + Device.didHandle->Release(); + return DIENUM_CONTINUE; + } + hResult = Device.didHandle->SetCooperativeLevel(m_hWnd, DISCL_NONEXCLUSIVE | DISCL_BACKGROUND); + if (!SUCCEEDED(hResult)) + { + Device.didHandle->Release(); + return DIENUM_CONTINUE; + } + + std::pair res = m_Devices.insert(DEVICE_MAP::value_type(lpddi->guidInstance, Device)); + if (!res.second) + { + Device.didHandle->Release(); + } + return DIENUM_CONTINUE; +} + +CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button) +{ + ScanResult Result = SCAN_FAILED; + + for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++) + { + DEVICE &device = itr->second; + if (device.didHandle == nullptr) + { + continue; + } + if (FAILED(device.didHandle->Poll())) + { + device.didHandle->Acquire(); + } + } + for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++) + { + DEVICE &device = itr->second; + if (device.didHandle == nullptr) + { + continue; + } + uint8_t DeviceType = LOBYTE(device.dwDevType); + if (DeviceType == DI8DEVTYPE_KEYBOARD) + { + Result = ScanKeyboard(device.didHandle, Button); + } + else if (DeviceType == DI8DEVTYPE_MOUSE) + { + //dwReturn = ScanMouse(&g_devList[i], lpdwCounter, pButton); + } + else + { + // dwReturn = ScanGamePad(&g_devList[i], lpdwCounter, pButton, i); + } + + if (Result != SCAN_FAILED) + { + return Result; + } + } + return Result; +} + +std::wstring CDirectInput::ButtonAssignment(BUTTON & Button) +{ + if (Button.BtnType == BTNTYPE_KEYBUTTON) + { + DEVICE_MAP::iterator itr = m_Devices.find(GUID_SysKeyboard); + if (itr != m_Devices.end()) + { + DIDEVICEOBJECTINSTANCE didoi; + didoi.dwSize = sizeof(DIDEVICEOBJECTINSTANCE); + if (itr->second.didHandle->GetObjectInfo(&didoi, Button.Offset, DIPH_BYOFFSET) == DI_OK) + { + return didoi.tszName; + } + return L"Keyboard: ???"; + } + } + else if (Button.BtnType == BTNTYPE_UNASSIGNED) + { + return L""; + } + return L"Unknown"; +} + +CDirectInput::ScanResult CDirectInput::ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton) +{ + if (didHandle == nullptr) + { + return SCAN_FAILED; + } + uint8_t cKeys[256]; + HRESULT hr = didHandle->GetDeviceState(sizeof(cKeys), cKeys); + if (FAILED(hr)) + { + didHandle->Acquire(); + return SCAN_FAILED; + } + + for (size_t i = 0, n = sizeof(cKeys) / sizeof(cKeys[0]); i < n; i++) + { + if ((cKeys[i] & 0x80) == 0) + { + continue; + } + if (i == DIK_ESCAPE) + { + return SCAN_ESCAPE; + } + pButton.Offset = (uint8_t)i; + pButton.AxisID = 0; + pButton.BtnType = BTNTYPE_KEYBUTTON; + return SCAN_SUCCEED; + } + return SCAN_FAILED; +} + +void CDirectInput::LoadConfig(void) +{ + +} diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h new file mode 100644 index 000000000..fdb135e82 --- /dev/null +++ b/Source/Project64-input/DirectInput.h @@ -0,0 +1,59 @@ +#pragma once +#include "ControllerSpec1.1.h" +#include "Button.h" +#define DIRECTINPUT_VERSION 0x0800 +#include +#include +#include +#include + +class CDirectInput +{ +public: + enum ScanResult + { + SCAN_FAILED = 0x00, + SCAN_SUCCEED = 0x01, + SCAN_ESCAPE = 0x10, + }; + + CDirectInput(HINSTANCE hinst); + ~CDirectInput(); + + void Initiate(CONTROL_INFO * ControlInfo); + ScanResult ScanDevices(BUTTON & Button); + std::wstring ButtonAssignment(BUTTON & Button); + +private: + CDirectInput(); + CDirectInput(const CDirectInput&); + CDirectInput& operator=(const CDirectInput&); + + static BOOL CALLBACK stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); + BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); + ScanResult ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton); + void LoadConfig(void); + + typedef struct + { + LPDIRECTINPUTDEVICE8 didHandle; + uint32_t dwDevType; + std::string InstanceName; + std::string ProductName; + } DEVICE; + + struct GUIDComparer + { + bool operator()(const GUID & Left, const GUID & Right) const + { + return memcmp(&Left, &Right, sizeof(Right)) < 0; + } + }; + typedef std::map DEVICE_MAP; + + DEVICE_MAP m_Devices; + HMODULE m_hDirectInputDLL; + LPDIRECTINPUT8 m_pDIHandle; + HINSTANCE m_hinst; + HWND m_hWnd; +}; \ No newline at end of file diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 179b2a273..4b543f015 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -1,6 +1,8 @@ #include "InputConfigUI.h" +#include "CProject64Input.h" #include "wtl.h" #include "wtl-BitmapPicture.h" +#include "wtl-ScanButton.h" #include #include #include "resource.h" @@ -8,43 +10,81 @@ class CControllerSettings : public CPropertyPageImpl { + enum + { + DETECT_KEY_TIMER = 1 + }; public: enum { IDD = IDD_Controller }; BEGIN_MSG_MAP(CDebugSettings) MSG_WM_INITDIALOG(OnInitDialog) + MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) CHAIN_MSG_MAP(CPropertyPageImpl) END_MSG_MAP() - CControllerSettings(); - void SetControllerNumber(uint32_t ControllerNumber); + CControllerSettings(uint32_t ControllerNumber); BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/); + HBRUSH OnCtlColorStatic(CDCHandle dc, CWindow wndStatic); private: std::wstring m_Title; uint32_t m_ControllerNumber; + uint32_t m_ScanCount; CBitmapPicture m_ControllerImg; + CScanButton ButtonUDPad, ButtonDDPad, ButtonLDPad, ButtonRDPad; + CScanButton ButtonCUp, ButtonCDown, ButtonCLeft, ButtonCRight; + CScanButton ButtonA, ButtonB; }; -CControllerSettings::CControllerSettings() : - m_ControllerNumber((uint32_t)-1) -{ -} - -void CControllerSettings::SetControllerNumber(uint32_t ControllerNumber) +CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : + m_ControllerNumber(ControllerNumber), + m_ScanCount(0), + ButtonUDPad(g_InputPlugin->Controllers(ControllerNumber).U_DPAD, IDC_EDIT_DIGITIAL_UP, IDC_BTN_DIGITIAL_UP), + ButtonDDPad(g_InputPlugin->Controllers(ControllerNumber).D_DPAD, IDC_EDIT_DIGITIAL_DOWN, IDC_BTN_DIGITIAL_DOWN), + ButtonLDPad(g_InputPlugin->Controllers(ControllerNumber).L_DPAD, IDC_EDIT_DIGITIAL_LEFT, IDC_BTN_DIGITIAL_LEFT), + ButtonRDPad(g_InputPlugin->Controllers(ControllerNumber).R_DPAD, IDC_EDIT_DIGITIAL_RIGHT, IDC_BTN_DIGITIAL_RIGHT), + ButtonA(g_InputPlugin->Controllers(ControllerNumber).A_BUTTON, IDC_EDIT_BUTTON_A, IDC_BTN_BUTTON_A), + ButtonB(g_InputPlugin->Controllers(ControllerNumber).B_BUTTON, IDC_EDIT_BUTTON_B, IDC_BTN_BUTTON_B), + ButtonCUp(g_InputPlugin->Controllers(ControllerNumber).U_CBUTTON, IDC_EDIT_CBUTTON_UP, IDC_BTN_CBUTTON_UP), + ButtonCDown(g_InputPlugin->Controllers(ControllerNumber).D_CBUTTON, IDC_EDIT_CBUTTON_DOWN, IDC_BTN_CBUTTON_DOWN), + ButtonCLeft(g_InputPlugin->Controllers(ControllerNumber).L_CBUTTON, IDC_EDIT_CBUTTON_LEFT, IDC_BTN_CBUTTON_LEFT), + ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT) { m_Title = stdstr_f("Player %d", ControllerNumber + 1).ToUTF16(); SetTitle(m_Title.c_str()); - m_ControllerNumber = ControllerNumber; } BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); + ButtonUDPad.SubclassWindow(m_hWnd); + ButtonDDPad.SubclassWindow(m_hWnd); + ButtonLDPad.SubclassWindow(m_hWnd); + ButtonRDPad.SubclassWindow(m_hWnd); + ButtonA.SubclassWindow(m_hWnd); + ButtonB.SubclassWindow(m_hWnd); + ButtonCUp.SubclassWindow(m_hWnd); + ButtonCDown.SubclassWindow(m_hWnd); + ButtonCLeft.SubclassWindow(m_hWnd); + ButtonCRight.SubclassWindow(m_hWnd); return TRUE; } +HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic) +{ + if (g_InputPlugin->IsScanning() && wndStatic.GetDlgCtrlID() == g_InputPlugin->DisplayCtrlId()) + { + dc.SetTextColor(GetSysColor(COLOR_HIGHLIGHTTEXT)); + dc.SetBkColor(GetSysColor(COLOR_HIGHLIGHT)); + return ::GetSysColorBrush(COLOR_HIGHLIGHT); + } + dc.SetTextColor(GetSysColor(COLOR_WINDOWTEXT)); + dc.SetBkColor(GetSysColor(COLOR_WINDOW)); + return ::GetSysColorBrush(COLOR_WINDOW); +} + class CInputConfigUI: public CPropertySheetImpl { @@ -55,7 +95,7 @@ public: void OnSheetInitialized(); private: - CControllerSettings m_pgController[4]; + CControllerSettings m_pgController0, m_pgController1, m_pgController2, m_pgController3; }; void ConfigInput(void * hParent) @@ -63,14 +103,17 @@ void ConfigInput(void * hParent) CInputConfigUI().DoModal((HWND)hParent); } -CInputConfigUI::CInputConfigUI() +CInputConfigUI::CInputConfigUI() : + m_pgController0(0), + m_pgController1(1), + m_pgController2(2), + m_pgController3(3) { m_psh.pszCaption = L"Configure Input"; - for (size_t i = 0, n = sizeof(m_pgController) / sizeof(m_pgController[0]); i < n; i++) - { - m_pgController[i].SetControllerNumber(i); - AddPage(&m_pgController[i].m_psp); - } + AddPage(&m_pgController0.m_psp); + AddPage(&m_pgController1.m_psp); + AddPage(&m_pgController2.m_psp); + AddPage(&m_pgController3.m_psp); } CInputConfigUI::~CInputConfigUI() diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp index a48d62d24..f8cdf6862 100644 --- a/Source/Project64-input/InputMain.cpp +++ b/Source/Project64-input/InputMain.cpp @@ -11,6 +11,7 @@ #include "ControllerSpec1.1.h" #include "InputConfigUI.h" #include "Version.h" +#include "CProject64Input.h" #include /****************************************************************** @@ -121,8 +122,12 @@ EXPORT void CALL GetKeys(int32_t /*Control*/, BUTTONS * /*Keys*/) the emulator to know how to handle each controller. output: none *******************************************************************/ -EXPORT void CALL InitiateControllers(CONTROL_INFO * /*ControlInfo*/) +EXPORT void CALL InitiateControllers(CONTROL_INFO * ControlInfo) { + if (g_InputPlugin != nullptr) + { + g_InputPlugin->InitiateControllers(ControlInfo); + } } /****************************************************************** @@ -185,4 +190,20 @@ EXPORT void CALL WM_KeyUp(uint32_t /*wParam*/, uint32_t /*lParam*/) EXPORT void CALL PluginLoaded(void) { +} + +#include + +extern "C" int WINAPI DllMain(HINSTANCE hinst, DWORD fdwReason, LPVOID /*lpReserved*/) +{ + if (fdwReason == DLL_PROCESS_ATTACH) + { + g_InputPlugin = new CProject64Input(hinst); + } + else if (fdwReason == DLL_PROCESS_DETACH) + { + delete g_InputPlugin; + g_InputPlugin = NULL; + } + return TRUE; } \ No newline at end of file diff --git a/Source/Project64-input/N64Controller.h b/Source/Project64-input/N64Controller.h new file mode 100644 index 000000000..4aa560295 --- /dev/null +++ b/Source/Project64-input/N64Controller.h @@ -0,0 +1,20 @@ +#pragma once +#include "Button.h" + +typedef struct +{ + BUTTON U_DPAD; + BUTTON D_DPAD; + BUTTON L_DPAD; + BUTTON R_DPAD; + BUTTON A_BUTTON; + BUTTON B_BUTTON; + BUTTON U_CBUTTON; + BUTTON D_CBUTTON; + BUTTON L_CBUTTON; + BUTTON R_CBUTTON; + BUTTON START_BUTTON; + BUTTON Z_TRIG; + BUTTON R_TRIG; + BUTTON L_TRIG; +} N64CONTROLLER; diff --git a/Source/Project64-input/Project64-input.vcxproj b/Source/Project64-input/Project64-input.vcxproj index cd1455d8d..69b3e27eb 100644 --- a/Source/Project64-input/Project64-input.vcxproj +++ b/Source/Project64-input/Project64-input.vcxproj @@ -45,17 +45,35 @@ "$(SolutionDir)Source\Script\UpdateVersion.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)Source\Project64-input\Version.h.in" "$(SolutionDir)Source\Project64-input\Version.h" + + dinput8.lib;dxguid.lib;%(AdditionalDependencies) + $(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories) + false + + + dinput8.lib;dxguid.lib;%(AdditionalDependencies) + $(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories) + false + + + + + + + + + diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters index a54fc15c4..a064bf712 100644 --- a/Source/Project64-input/Project64-input.vcxproj.filters +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -24,6 +24,15 @@ Source Files + + Source Files + + + Source Files + + + Source Files + @@ -41,6 +50,21 @@ Header Files + + Header Files + + + Header Files + + + Header Files + + + Header Files + + + Header Files + diff --git a/Source/Project64-input/Version.h.in b/Source/Project64-input/Version.h.in index e26272109..14087d707 100644 --- a/Source/Project64-input/Version.h.in +++ b/Source/Project64-input/Version.h.in @@ -11,8 +11,8 @@ #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) -#define VERSION_MAJOR 1 -#define VERSION_MINOR 0 +#define VERSION_MAJOR 0 +#define VERSION_MINOR 1 #define VERSION_REVISION 0 #define VERSION_BUILD 9999 #define GIT_VERSION "" diff --git a/Source/Project64-input/wtl-ScanButton.cpp b/Source/Project64-input/wtl-ScanButton.cpp new file mode 100644 index 000000000..447aab039 --- /dev/null +++ b/Source/Project64-input/wtl-ScanButton.cpp @@ -0,0 +1,156 @@ +#include "wtl-ScanButton.h" +#include "CProject64Input.h" +#include +#include + +CScanButton::CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId) : + m_Button(Button), + m_DisplayCtrlId(DisplayCtrlId), + m_ScanBtnId(ScanBtnId), + m_ScanBtnProc(nullptr), + m_ScanCount(0), + m_ScanStart(0) +{ +} + +void CScanButton::SubclassWindow(CWindow Wnd) +{ + m_DisplayCtrl = Wnd.GetDlgItem(m_DisplayCtrlId); + m_ScanBtn = Wnd.GetDlgItem(m_ScanBtnId); + m_ScanBtnThunk.Init((WNDPROC)ScanButtonProc, this); + m_ScanBtnProc = (WNDPROC)m_ScanBtn.SetWindowLongPtrW(GWLP_WNDPROC, (LONG_PTR)m_ScanBtnThunk.GetWNDPROC()); + DisplayButton(); +} + +void CScanButton::DisplayButton(void) +{ + m_DisplayCtrl.SetWindowText(g_InputPlugin->ButtonAssignment(m_Button).c_str()); +} + +void CScanButton::OnScan(void) +{ + enum + { + SACN_INTERVAL = 20 + }; + m_ScanCount = 0; + time(&m_ScanStart); + g_InputPlugin->StartScanDevices(m_DisplayCtrlId); + m_DisplayCtrl.Invalidate(); + m_ScanBtn.SetTimer(DETECT_KEY_TIMER, SACN_INTERVAL, NULL); + MakeOverlay(); +} + +void CScanButton::OnTimer(UINT_PTR nIDEvent) +{ + if (nIDEvent == DETECT_KEY_TIMER) + { + bool Stop = false; + if (g_InputPlugin) + { + CDirectInput::ScanResult Result = g_InputPlugin->ScanDevices(m_Button); + if (Result == CDirectInput::SCAN_SUCCEED) + { + Stop = true; + DisplayButton(); + } + } + if ((m_ScanCount % 30) == 0) + { + CWindow Dialog = m_ScanBtn.GetParent().GetParent(); + time_t Now = time(nullptr); + if (10 - (Now - m_ScanStart) > 0) + { + Dialog.SetWindowText(stdstr_f("Configure Input: Press Key ... (%d seconds)", 10 - (Now - m_ScanStart)).ToUTF16().c_str()); + } + else + { + Stop = true; + } + } + if (m_ScanCount > 500) + { + Stop = true; + } + else + { + m_ScanCount += 1; + } + + if (Stop) + { + m_ScanBtn.KillTimer(DETECT_KEY_TIMER); + CWindow Dialog = m_ScanBtn.GetParent().GetParent(); + Dialog.SetWindowText(L"Configure Input"); + + m_Overlay.DestroyWindow(); + m_Overlay = NULL; + + g_InputPlugin->EndScanDevices(); + m_DisplayCtrl.Invalidate(); + } + } +} + +void CScanButton::MakeOverlay(void) +{ + WNDCLASS wc = { 0 }; + wc.lpfnWndProc = (WNDPROC)BlockerProc; + wc.hInstance = g_InputPlugin->hInst(); + wc.lpszClassName = L"BlockerClass"; + RegisterClass(&wc); + + CWindow ControllerDlg = m_ScanBtn.GetParent().GetParent(); + CRect size; + ControllerDlg.GetWindowRect(&size); + m_Overlay = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT, L"BlockerClass", L"Blocker", WS_POPUP, size.left, size.top, size.Width(), size.Height(), ControllerDlg, nullptr, g_InputPlugin->hInst(), NULL); + if (m_Overlay == NULL) + { + return; + } + m_Overlay.ShowWindow(SW_SHOWNOACTIVATE); +} + +UINT_PTR CALLBACK CScanButton::ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) +{ + CScanButton * _this = (CScanButton*)hWnd; + UINT_PTR uRet = 0; + if (uMsg == WM_LBUTTONUP) + { + POINT ptCursor = { GET_X_LPARAM(lParam), GET_Y_LPARAM(lParam) }; + _this->m_ScanBtn.ClientToScreen(&ptCursor); + + RECT rect = { 0 }; + _this->m_ScanBtn.GetWindowRect(&rect); + if (PtInRect(&rect, ptCursor)) + { + _this->OnScan(); + } + } + else if (uMsg == WM_TIMER) + { + _this->OnTimer((UINT_PTR)wParam); + } + if (_this->m_ScanBtnProc != nullptr) + { + uRet = _this->m_ScanBtnProc(_this->m_ScanBtn, uMsg, wParam, lParam); + } + return uRet; +} + + +UINT_PTR CALLBACK CScanButton::BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam) +{ + if (msg == WM_CREATE) + { + return 0; + } + if (msg == WM_PAINT) + { + PAINTSTRUCT ps; + BeginPaint(hwnd, &ps); + EndPaint(hwnd, &ps); + return 0; + } + return DefWindowProc(hwnd, msg, wParam, lParam); +} diff --git a/Source/Project64-input/wtl-ScanButton.h b/Source/Project64-input/wtl-ScanButton.h new file mode 100644 index 000000000..81789f0f5 --- /dev/null +++ b/Source/Project64-input/wtl-ScanButton.h @@ -0,0 +1,37 @@ +#pragma once +#include "wtl.h" +#include "Button.h" + +class CScanButton +{ + enum + { + DETECT_KEY_TIMER = 1 + }; + +public: + CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId); + + void SubclassWindow(CWindow Wnd); + +private: + CScanButton(void); + CScanButton(const CScanButton&); + CScanButton& operator=(const CScanButton&); + + void DisplayButton(void); + void OnScan(void); + void OnTimer(UINT_PTR nIDEvent); + void MakeOverlay(void); + static UINT_PTR CALLBACK ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); + static UINT_PTR CALLBACK BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, LPARAM lParam); + + BUTTON & m_Button; + int32_t m_DisplayCtrlId, m_ScanBtnId; + CWindow m_DisplayCtrl, m_ScanBtn; + CWndProcThunk m_ScanBtnThunk; + WNDPROC m_ScanBtnProc; + uint32_t m_ScanCount; + time_t m_ScanStart; + CWindow m_Overlay; +}; \ No newline at end of file From 1a199349160a648468922faba63558f56aa479a6 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 1 Jul 2020 10:24:29 +0930 Subject: [PATCH 05/23] Project64-input: Add device to button --- Source/Project64-input/Button.h | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/Source/Project64-input/Button.h b/Source/Project64-input/Button.h index 4977657aa..b42929e46 100644 --- a/Source/Project64-input/Button.h +++ b/Source/Project64-input/Button.h @@ -1,5 +1,6 @@ #pragma once #include +#include enum BtnType { @@ -19,9 +20,11 @@ enum BtnType BTNTYPE_MOUSEAXE = 7, }; -typedef struct +typedef struct _BUTTON { uint8_t Offset; uint8_t AxisID; BtnType BtnType; + GUID DeviceGuid; + void * Device; } BUTTON; From 31afb1cf6e612eb44c0f39172c4e313558fae9c1 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 1 Jul 2020 10:31:41 +0930 Subject: [PATCH 06/23] Project64-input: Add Analog buttons to n64 controller --- Source/Project64-input/N64Controller.h | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Source/Project64-input/N64Controller.h b/Source/Project64-input/N64Controller.h index 4aa560295..5598356f0 100644 --- a/Source/Project64-input/N64Controller.h +++ b/Source/Project64-input/N64Controller.h @@ -17,4 +17,8 @@ typedef struct BUTTON Z_TRIG; BUTTON R_TRIG; BUTTON L_TRIG; + BUTTON U_ANALOG; + BUTTON D_ANALOG; + BUTTON L_ANALOG; + BUTTON R_ANALOG; } N64CONTROLLER; From acd835cfc40b4e991ca8f5a6c8fa89c108706333 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 1 Jul 2020 11:42:13 +0930 Subject: [PATCH 07/23] Project64-input: Add more buttons to be scanned --- Source/Project64-input/InputConfigUI.cpp | 56 ++++++++++++++++++----- Source/Project64-input/wtl-ScanButton.cpp | 39 +++++++++++++--- Source/Project64-input/wtl-ScanButton.h | 5 ++ 3 files changed, 82 insertions(+), 18 deletions(-) diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 4b543f015..bf5df76cd 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -26,15 +26,21 @@ public: CControllerSettings(uint32_t ControllerNumber); BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/); HBRUSH OnCtlColorStatic(CDCHandle dc, CWindow wndStatic); + bool OnApply(); private: + void ButtonChannged(void); + static void stButtonChanged(size_t data) { ((CControllerSettings *)data)->ButtonChannged(); } + std::wstring m_Title; uint32_t m_ControllerNumber; uint32_t m_ScanCount; CBitmapPicture m_ControllerImg; CScanButton ButtonUDPad, ButtonDDPad, ButtonLDPad, ButtonRDPad; CScanButton ButtonCUp, ButtonCDown, ButtonCLeft, ButtonCRight; - CScanButton ButtonA, ButtonB; + CScanButton ButtonA, ButtonB, ButtonStart; + CScanButton ButtonZtrigger, ButtonRTrigger, ButtonLTrigger; + CScanButton ButtonAnalogU, ButtonAnalogD, ButtonAnalogL, ButtonAnalogR; }; CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : @@ -49,7 +55,15 @@ CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : ButtonCUp(g_InputPlugin->Controllers(ControllerNumber).U_CBUTTON, IDC_EDIT_CBUTTON_UP, IDC_BTN_CBUTTON_UP), ButtonCDown(g_InputPlugin->Controllers(ControllerNumber).D_CBUTTON, IDC_EDIT_CBUTTON_DOWN, IDC_BTN_CBUTTON_DOWN), ButtonCLeft(g_InputPlugin->Controllers(ControllerNumber).L_CBUTTON, IDC_EDIT_CBUTTON_LEFT, IDC_BTN_CBUTTON_LEFT), - ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT) + ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT), + ButtonStart(g_InputPlugin->Controllers(ControllerNumber).START_BUTTON, IDC_EDIT_BUTTON_START, IDC_BTN_BUTTON_START), + ButtonZtrigger(g_InputPlugin->Controllers(ControllerNumber).Z_TRIG, IDC_EDIT_BUTTON_Z, IDC_BTN_BUTTON_Z), + ButtonRTrigger(g_InputPlugin->Controllers(ControllerNumber).R_TRIG, IDC_EDIT_RTRIGGER, IDC_BTN_RTRIGGER), + ButtonLTrigger(g_InputPlugin->Controllers(ControllerNumber).L_TRIG, IDC_EDIT_LTRIGGER, IDC_BTN_LTRIGGER), + ButtonAnalogU(g_InputPlugin->Controllers(ControllerNumber).U_ANALOG, IDC_EDIT_ANALOG_UP, IDC_BTN_ANALOG_UP), + ButtonAnalogD(g_InputPlugin->Controllers(ControllerNumber).D_ANALOG, IDC_EDIT_ANALOG_DOWN, IDC_BTN_ANALOG_DOWN), + ButtonAnalogL(g_InputPlugin->Controllers(ControllerNumber).L_ANALOG, IDC_EDIT_ANALOG_LEFT, IDC_BTN_ANALOG_LEFT), + ButtonAnalogR(g_InputPlugin->Controllers(ControllerNumber).R_ANALOG, IDC_EDIT_ANALOG_RIGHT, IDC_BTN_ANALOG_RIGHT) { m_Title = stdstr_f("Player %d", ControllerNumber + 1).ToUTF16(); SetTitle(m_Title.c_str()); @@ -57,18 +71,26 @@ CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { + GetDlgItem(IDC_BTN_SETUP).EnableWindow(false); + GetDlgItem(IDC_BTN_DEFAULTS).EnableWindow(false); + GetDlgItem(IDC_BTN_LOAD).EnableWindow(false); + GetDlgItem(IDC_BTN_SAVE).EnableWindow(false); + GetDlgItem(IDC_TACK_RANGE).EnableWindow(false); + m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); - ButtonUDPad.SubclassWindow(m_hWnd); - ButtonDDPad.SubclassWindow(m_hWnd); - ButtonLDPad.SubclassWindow(m_hWnd); - ButtonRDPad.SubclassWindow(m_hWnd); - ButtonA.SubclassWindow(m_hWnd); - ButtonB.SubclassWindow(m_hWnd); - ButtonCUp.SubclassWindow(m_hWnd); - ButtonCDown.SubclassWindow(m_hWnd); - ButtonCLeft.SubclassWindow(m_hWnd); - ButtonCRight.SubclassWindow(m_hWnd); + CScanButton * Buttons[] = { + &ButtonUDPad, &ButtonDDPad, &ButtonLDPad, &ButtonRDPad, &ButtonA, &ButtonB, + &ButtonCUp, &ButtonCDown, &ButtonCLeft, &ButtonCRight, &ButtonStart, + &ButtonZtrigger, &ButtonRTrigger, &ButtonLTrigger, + &ButtonAnalogU, &ButtonAnalogD, &ButtonAnalogL, &ButtonAnalogR + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + Buttons[i]->SubclassWindow(m_hWnd); + Buttons[i]->SetChangeCallback(stButtonChanged, (size_t)this); + } return TRUE; } @@ -85,6 +107,16 @@ HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic) return ::GetSysColorBrush(COLOR_WINDOW); } +bool CControllerSettings::OnApply() +{ + return true; +} + +void CControllerSettings::ButtonChannged(void) +{ + CPropertySheetWindow(GetParent()).SetModified(m_hWnd); +} + class CInputConfigUI: public CPropertySheetImpl { diff --git a/Source/Project64-input/wtl-ScanButton.cpp b/Source/Project64-input/wtl-ScanButton.cpp index 447aab039..1b1aeba55 100644 --- a/Source/Project64-input/wtl-ScanButton.cpp +++ b/Source/Project64-input/wtl-ScanButton.cpp @@ -9,7 +9,9 @@ CScanButton::CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId) : m_ScanBtnId(ScanBtnId), m_ScanBtnProc(nullptr), m_ScanCount(0), - m_ScanStart(0) + m_ScanStart(0), + m_ChangeCallback(nullptr), + m_ChangeCallbackData(0) { } @@ -22,6 +24,12 @@ void CScanButton::SubclassWindow(CWindow Wnd) DisplayButton(); } +void CScanButton::SetChangeCallback(ChangeCallback callback, size_t callbackdata) +{ + m_ChangeCallback = callback; + m_ChangeCallbackData = callbackdata; +} + void CScanButton::DisplayButton(void) { m_DisplayCtrl.SetWindowText(g_InputPlugin->ButtonAssignment(m_Button).c_str()); @@ -48,8 +56,17 @@ void CScanButton::OnTimer(UINT_PTR nIDEvent) bool Stop = false; if (g_InputPlugin) { - CDirectInput::ScanResult Result = g_InputPlugin->ScanDevices(m_Button); - if (Result == CDirectInput::SCAN_SUCCEED) + BUTTON Button = m_Button; + CDirectInput::ScanResult Result = g_InputPlugin->ScanDevices(Button); + if (Result == CDirectInput::SCAN_SUCCEED && (Button.Offset != m_Button.Offset || Button.AxisID != m_Button.AxisID || Button.BtnType != m_Button.BtnType)) + { + m_Button = Button; + if (m_ChangeCallback != nullptr) + { + m_ChangeCallback(m_ChangeCallbackData); + } + } + if (Result == CDirectInput::SCAN_SUCCEED || Result == CDirectInput::SCAN_ESCAPE) { Stop = true; DisplayButton(); @@ -83,9 +100,12 @@ void CScanButton::OnTimer(UINT_PTR nIDEvent) CWindow Dialog = m_ScanBtn.GetParent().GetParent(); Dialog.SetWindowText(L"Configure Input"); - m_Overlay.DestroyWindow(); - m_Overlay = NULL; - + if (m_Overlay.m_hWnd != NULL) + { + m_Overlay.DestroyWindow(); + m_Overlay = NULL; + } + g_InputPlugin->EndScanDevices(); m_DisplayCtrl.Invalidate(); } @@ -103,12 +123,15 @@ void CScanButton::MakeOverlay(void) CWindow ControllerDlg = m_ScanBtn.GetParent().GetParent(); CRect size; ControllerDlg.GetWindowRect(&size); +#ifndef _DEBUG m_Overlay = CreateWindowEx(WS_EX_TOPMOST | WS_EX_TRANSPARENT, L"BlockerClass", L"Blocker", WS_POPUP, size.left, size.top, size.Width(), size.Height(), ControllerDlg, nullptr, g_InputPlugin->hInst(), NULL); if (m_Overlay == NULL) { return; } + m_Overlay.SetFocus(); m_Overlay.ShowWindow(SW_SHOWNOACTIVATE); +#endif } UINT_PTR CALLBACK CScanButton::ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam) @@ -145,6 +168,10 @@ UINT_PTR CALLBACK CScanButton::BlockerProc(HWND hwnd, UINT msg, WPARAM wParam, { return 0; } + if (msg == WM_KEYDOWN || msg == WM_KEYUP) + { + return 0; + } if (msg == WM_PAINT) { PAINTSTRUCT ps; diff --git a/Source/Project64-input/wtl-ScanButton.h b/Source/Project64-input/wtl-ScanButton.h index 81789f0f5..a485fcea2 100644 --- a/Source/Project64-input/wtl-ScanButton.h +++ b/Source/Project64-input/wtl-ScanButton.h @@ -10,9 +10,12 @@ class CScanButton }; public: + typedef void(*ChangeCallback)(size_t Data); + CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId); void SubclassWindow(CWindow Wnd); + void SetChangeCallback(ChangeCallback callback, size_t callbackdata); private: CScanButton(void); @@ -34,4 +37,6 @@ private: uint32_t m_ScanCount; time_t m_ScanStart; CWindow m_Overlay; + ChangeCallback m_ChangeCallback; + size_t m_ChangeCallbackData; }; \ No newline at end of file From ba2ea242747f10921744d739e1e0ec05b63c7895 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 1 Jul 2020 13:07:55 +0930 Subject: [PATCH 08/23] Project64-input: Be able to load/save controller --- Source/Project64-input/CProject64Input.cpp | 17 ++ Source/Project64-input/CProject64Input.h | 3 + Source/Project64-input/DirectInput.cpp | 38 ++++ Source/Project64-input/DirectInput.h | 2 + Source/Project64-input/InputConfigUI.cpp | 2 +- Source/Project64-input/InputMain.cpp | 3 + Source/Project64-input/InputSettings.cpp | 173 ++++++++++++++++++ Source/Project64-input/InputSettings.h | 29 +++ Source/Project64-input/InputSettingsID.h | 23 +++ .../Project64-input/Project64-input.vcxproj | 6 + .../Project64-input.vcxproj.filters | 9 + 11 files changed, 304 insertions(+), 1 deletion(-) create mode 100644 Source/Project64-input/InputSettings.cpp create mode 100644 Source/Project64-input/InputSettings.h create mode 100644 Source/Project64-input/InputSettingsID.h diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index c055bd03b..67acfde76 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -1,4 +1,5 @@ #include "CProject64Input.h" +#include "InputSettings.h" CProject64Input * g_InputPlugin = nullptr; @@ -16,11 +17,17 @@ CProject64Input::~CProject64Input() void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) { + CGuard guard(m_CS); if (m_DirectInput.get() == NULL) { m_DirectInput.reset(new CDirectInput(m_hinst)); } m_DirectInput->Initiate(ControlInfo); + for (size_t i = 0, n = sizeof(m_Controllers) / sizeof(m_Controllers[0]); i < n; i++) + { + g_Settings->LoadController(0, m_Controllers[i]); + m_DirectInput->MapControllerDevice(m_Controllers[i]); + } } void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) @@ -53,3 +60,13 @@ std::wstring CProject64Input::ButtonAssignment(BUTTON & Button) } return L"Unknown"; } + +bool CProject64Input::SaveController(uint32_t ControlIndex) +{ + if (ControlIndex >= sizeof(m_Controllers) / sizeof(m_Controllers[0])) + { + return false; + } + g_Settings->SaveController(ControlIndex, m_Controllers[ControlIndex]); + return true; +} diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index 8ce1aac38..d88317826 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -2,6 +2,7 @@ #include "ControllerSpec1.1.h" #include "DirectInput.h" #include "N64Controller.h" +#include #include class CProject64Input @@ -15,6 +16,7 @@ public: void EndScanDevices(void); CDirectInput::ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); + bool SaveController(uint32_t ControlIndex); inline HINSTANCE hInst(void) const { return m_hinst; } inline bool IsScanning(void) const { return m_Scanning; } @@ -26,6 +28,7 @@ private: CProject64Input(const CProject64Input&); CProject64Input& operator=(const CProject64Input&); + CriticalSection m_CS; N64CONTROLLER m_Controllers[4]; std::unique_ptr m_DirectInput; HINSTANCE m_hinst; diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index de9d9c44e..542ce81e6 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -50,6 +50,44 @@ void CDirectInput::Initiate(CONTROL_INFO * ControlInfo) m_hWnd = (HWND)ControlInfo->hwnd; } +void CDirectInput::MapControllerDevice(N64CONTROLLER & Controller) +{ + BUTTON * Buttons[] = + { + &Controller.U_DPAD, + &Controller.D_DPAD, + &Controller.L_DPAD, + &Controller.R_DPAD, + &Controller.A_BUTTON, + &Controller.B_BUTTON, + &Controller.U_CBUTTON, + &Controller.D_CBUTTON, + &Controller.L_CBUTTON, + &Controller.R_CBUTTON, + &Controller.START_BUTTON, + &Controller.Z_TRIG, + &Controller.R_TRIG, + &Controller.L_TRIG, + &Controller.U_ANALOG, + &Controller.D_ANALOG, + &Controller.L_ANALOG, + &Controller.R_ANALOG, + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + DEVICE_MAP::iterator itr = m_Devices.find(Buttons[i]->DeviceGuid); + if (itr != m_Devices.end()) + { + Buttons[i]->Device = &itr->second; + } + else + { + Buttons[i]->Device = nullptr; + } + } +} + BOOL CDirectInput::stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef) { return ((CDirectInput *)pvRef)->EnumMakeDeviceList(lpddi); diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index fdb135e82..8a03a8b9a 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -1,6 +1,7 @@ #pragma once #include "ControllerSpec1.1.h" #include "Button.h" +#include "N64Controller.h" #define DIRECTINPUT_VERSION 0x0800 #include #include @@ -21,6 +22,7 @@ public: ~CDirectInput(); void Initiate(CONTROL_INFO * ControlInfo); + void MapControllerDevice(N64CONTROLLER & Controller); ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index bf5df76cd..400d692ba 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -109,7 +109,7 @@ HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic) bool CControllerSettings::OnApply() { - return true; + return g_InputPlugin->SaveController(m_ControllerNumber); } void CControllerSettings::ButtonChannged(void) diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp index f8cdf6862..7472783c5 100644 --- a/Source/Project64-input/InputMain.cpp +++ b/Source/Project64-input/InputMain.cpp @@ -12,6 +12,7 @@ #include "InputConfigUI.h" #include "Version.h" #include "CProject64Input.h" +#include "InputSettings.h" #include /****************************************************************** @@ -23,6 +24,7 @@ output: none *******************************************************************/ EXPORT void CALL CloseDLL(void) { + CleanupInputSettings(); } /****************************************************************** @@ -190,6 +192,7 @@ EXPORT void CALL WM_KeyUp(uint32_t /*wParam*/, uint32_t /*lParam*/) EXPORT void CALL PluginLoaded(void) { + SetupInputSettings(); } #include diff --git a/Source/Project64-input/InputSettings.cpp b/Source/Project64-input/InputSettings.cpp new file mode 100644 index 000000000..468220b29 --- /dev/null +++ b/Source/Project64-input/InputSettings.cpp @@ -0,0 +1,173 @@ +#include +#include +#include "InputSettingsID.h" +#include "InputSettings.h" + +CInputSettings * g_Settings = nullptr; + +CInputSettings::CInputSettings() +{ + RegisterSettings(); +} + +CInputSettings::~CInputSettings() +{ +} + +void CInputSettings::LoadController(uint32_t ControlIndex, N64CONTROLLER & Controller) +{ + struct { + BUTTON & Button; + InputSettingID SettingId; + uint32_t ControlIndex; + } + Buttons[] = + { + { Controller.U_DPAD, Set_Control0_U_DPAD, 0 }, + { Controller.D_DPAD, Set_Control0_D_DPAD, 0 }, + { Controller.L_DPAD, Set_Control0_L_DPAD, 0 }, + { Controller.R_DPAD, Set_Control0_R_DPAD, 0 }, + { Controller.A_BUTTON, Set_Control0_A_BUTTON, 0 }, + { Controller.B_BUTTON, Set_Control0_B_BUTTON, 0 }, + { Controller.U_CBUTTON, Set_Control0_U_CBUTTON, 0 }, + { Controller.D_CBUTTON, Set_Control0_D_CBUTTON, 0 }, + { Controller.L_CBUTTON, Set_Control0_L_CBUTTON, 0 }, + { Controller.R_CBUTTON, Set_Control0_R_CBUTTON, 0 }, + { Controller.START_BUTTON, Set_Control0_START_BUTTON, 0 }, + { Controller.Z_TRIG, Set_Control0_Z_TRIG, 0 }, + { Controller.R_TRIG, Set_Control0_R_TRIG, 0 }, + { Controller.L_TRIG, Set_Control0_L_TRIG, 0 }, + { Controller.U_ANALOG, Set_Control0_U_ANALOG, 0 }, + { Controller.D_ANALOG, Set_Control0_D_ANALOG, 0 }, + { Controller.L_ANALOG, Set_Control0_L_ANALOG, 0 }, + { Controller.R_ANALOG, Set_Control0_R_ANALOG, 0 }, + }; + + char Buffer[400]; + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + if (Buttons[i].ControlIndex != ControlIndex) + { + continue; + } + Buttons[i].Button = StrToButton(GetSettingSz((short)Buttons[i].SettingId, Buffer, sizeof(Buffer) / sizeof(Buffer[0]))); + } +} + +void CInputSettings::SaveController(uint32_t ControlIndex, const N64CONTROLLER & Controller) +{ + struct { + const BUTTON & Button; + InputSettingID SettingId; + uint32_t ControlIndex; + } + Buttons[] = + { + { Controller.U_DPAD, Set_Control0_U_DPAD, 0 }, + { Controller.D_DPAD, Set_Control0_D_DPAD, 0 }, + { Controller.L_DPAD, Set_Control0_L_DPAD, 0 }, + { Controller.R_DPAD, Set_Control0_R_DPAD, 0 }, + { Controller.A_BUTTON, Set_Control0_A_BUTTON, 0 }, + { Controller.B_BUTTON, Set_Control0_B_BUTTON, 0 }, + { Controller.U_CBUTTON, Set_Control0_U_CBUTTON, 0 }, + { Controller.D_CBUTTON, Set_Control0_D_CBUTTON, 0 }, + { Controller.L_CBUTTON, Set_Control0_L_CBUTTON, 0 }, + { Controller.R_CBUTTON, Set_Control0_R_CBUTTON, 0 }, + { Controller.START_BUTTON, Set_Control0_START_BUTTON, 0 }, + { Controller.Z_TRIG, Set_Control0_Z_TRIG, 0 }, + { Controller.R_TRIG, Set_Control0_R_TRIG, 0 }, + { Controller.L_TRIG, Set_Control0_L_TRIG, 0 }, + { Controller.U_ANALOG, Set_Control0_U_ANALOG, 0 }, + { Controller.D_ANALOG, Set_Control0_D_ANALOG, 0 }, + { Controller.L_ANALOG, Set_Control0_L_ANALOG, 0 }, + { Controller.R_ANALOG, Set_Control0_R_ANALOG, 0 }, + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + if (Buttons[i].ControlIndex != ControlIndex) + { + continue; + } + SetSettingSz((short)Buttons[i].SettingId, ButtonToStr(Buttons[i].Button).c_str()); + } + FlushSettings(); +} + +BUTTON CInputSettings::StrToButton(const char * Buffer) +{ + BUTTON Button = { 0 }; + GUID &guid = Button.DeviceGuid; + uint32_t ButtonOffset = 0, ButtonAxisID = 0, ButtonType = 0; + sscanf(Buffer, + "{%8x-%4hx-%4hx-%2hhx%2hhx-%2hhx%2hhx%2hhx%2hhx%2hhx%2hhx} %x %u %u", + &guid.Data1, &guid.Data2, &guid.Data3, + &guid.Data4[0], &guid.Data4[1], &guid.Data4[2], &guid.Data4[3], + &guid.Data4[4], &guid.Data4[5], &guid.Data4[6], &guid.Data4[7], + &ButtonOffset, &ButtonAxisID, &ButtonType); + Button.Offset = (uint8_t)(ButtonOffset & 0xFF); + Button.AxisID = (uint8_t)(ButtonAxisID & 0xFF); + Button.BtnType = (BtnType)ButtonType; + return Button; +} + +std::string CInputSettings::ButtonToStr(const BUTTON & Button) +{ + return stdstr_f("%s %02X %u %u", GUIDtoString(Button.DeviceGuid).c_str(), Button.Offset, Button.AxisID, Button.BtnType); +} + +std::string CInputSettings::GUIDtoString(const GUID & guid) +{ + return stdstr_f("{%08.8lX-%04.4hX-%04.4hX-%02.2X%02.2X-%02.2X%02.2X%02.2X%02.2X%02.2X%02.2X}", guid.Data1, guid.Data2, guid.Data3, guid.Data4[0], guid.Data4[1], guid.Data4[2], guid.Data4[3], guid.Data4[4], guid.Data4[5], guid.Data4[6], guid.Data4[7]); +} + +void CInputSettings::RegisterSettings(void) +{ + SetModuleName("Input"); + RegisterSetting(Set_Control0_U_DPAD, Data_String_General, "DPadUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 17 0 5"); + RegisterSetting(Set_Control0_D_DPAD, Data_String_General, "DPadDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 25 0 5"); + RegisterSetting(Set_Control0_L_DPAD, Data_String_General, "DPadLeft", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 24 0 5"); + RegisterSetting(Set_Control0_R_DPAD, Data_String_General, "DPadRight", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 26 0 5"); + RegisterSetting(Set_Control0_A_BUTTON, Data_String_General, "ButtonA", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 2D 0 5"); + RegisterSetting(Set_Control0_B_BUTTON, Data_String_General, "ButtonB", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 2E 0 5"); + RegisterSetting(Set_Control0_U_CBUTTON, Data_String_General, "CButtonUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} C7 0 5"); + RegisterSetting(Set_Control0_D_CBUTTON, Data_String_General, "CButtonDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} CF 0 5"); + RegisterSetting(Set_Control0_L_CBUTTON, Data_String_General, "CButtonLeft", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} D1 0 5"); + RegisterSetting(Set_Control0_R_CBUTTON, Data_String_General, "CButtonRight", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} D3 0 5"); + RegisterSetting(Set_Control0_START_BUTTON, Data_String_General, "ButtonStart", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 1C 0 5"); + RegisterSetting(Set_Control0_Z_TRIG, Data_String_General, "ButtonZ", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 2C 0 5"); + RegisterSetting(Set_Control0_R_TRIG, Data_String_General, "ButtonR", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 1F 0 5"); + RegisterSetting(Set_Control0_L_TRIG, Data_String_General, "ButtonL", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 1E 0 5"); + RegisterSetting(Set_Control0_U_ANALOG, Data_String_General, "AnalogUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} C8 0 5"); + RegisterSetting(Set_Control0_D_ANALOG, Data_String_General, "AnalogDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} D0 0 5"); + RegisterSetting(Set_Control0_L_ANALOG, Data_String_General, "AnalogLeft", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} CB 0 5"); + RegisterSetting(Set_Control0_R_ANALOG, Data_String_General, "AnalogRight", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} CD 0 5"); +} + +void SetupInputSettings(void) +{ + if (g_Settings == nullptr) + { + g_Settings = new CInputSettings; + } +} + +void CleanupInputSettings(void) +{ + if (g_Settings) + { + delete g_Settings; + g_Settings = nullptr; + } +} + +#ifdef _WIN32 +#include +#endif + +extern "C" void UseUnregisteredSetting(int /*SettingID*/) +{ +#ifdef _WIN32 + DebugBreak(); +#endif +} diff --git a/Source/Project64-input/InputSettings.h b/Source/Project64-input/InputSettings.h new file mode 100644 index 000000000..275b84acd --- /dev/null +++ b/Source/Project64-input/InputSettings.h @@ -0,0 +1,29 @@ +#pragma once +#include +#include +#include "N64Controller.h" + +class CInputSettings +{ +public: + CInputSettings(); + ~CInputSettings(); + + void LoadController(uint32_t ControlIndex, N64CONTROLLER & Controller); + void SaveController(uint32_t ControlIndex, const N64CONTROLLER & Controller); + +private: + CInputSettings(const CInputSettings&); + CInputSettings& operator=(const CInputSettings&); + + static BUTTON StrToButton(const char * Buffer); + static std::string ButtonToStr(const BUTTON & Button); + static std::string GUIDtoString(const GUID & guid); + + void RegisterSettings(void); +}; + +extern CInputSettings * g_Settings; + +void SetupInputSettings(void); +void CleanupInputSettings(void); diff --git a/Source/Project64-input/InputSettingsID.h b/Source/Project64-input/InputSettingsID.h new file mode 100644 index 000000000..c0f36a57c --- /dev/null +++ b/Source/Project64-input/InputSettingsID.h @@ -0,0 +1,23 @@ +#pragma once + +enum InputSettingID +{ + Set_Control0_U_DPAD, + Set_Control0_D_DPAD, + Set_Control0_L_DPAD, + Set_Control0_R_DPAD, + Set_Control0_A_BUTTON, + Set_Control0_B_BUTTON, + Set_Control0_U_CBUTTON, + Set_Control0_D_CBUTTON, + Set_Control0_L_CBUTTON, + Set_Control0_R_CBUTTON, + Set_Control0_START_BUTTON, + Set_Control0_Z_TRIG, + Set_Control0_R_TRIG, + Set_Control0_L_TRIG, + Set_Control0_U_ANALOG, + Set_Control0_D_ANALOG, + Set_Control0_L_ANALOG, + Set_Control0_R_ANALOG, +}; diff --git a/Source/Project64-input/Project64-input.vcxproj b/Source/Project64-input/Project64-input.vcxproj index 69b3e27eb..21e515f1d 100644 --- a/Source/Project64-input/Project64-input.vcxproj +++ b/Source/Project64-input/Project64-input.vcxproj @@ -61,11 +61,14 @@ + + + @@ -89,5 +92,8 @@ {b4a4b994-9111-42b1-93c2-6f1ca8bc4421} + + {8b9961b1-88d9-4ea3-a752-507a00dd9f3d} + \ No newline at end of file diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters index a064bf712..10ea984db 100644 --- a/Source/Project64-input/Project64-input.vcxproj.filters +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -33,6 +33,9 @@ Source Files + + Source Files + @@ -65,6 +68,12 @@ Header Files + + Header Files + + + Header Files + From 09de7617bf6573328fc1203c909fa232d2c606f7 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 1 Jul 2020 13:17:36 +0930 Subject: [PATCH 09/23] Project64-input: Start to implement GetKeys --- Source/Project64-input/CProject64Input.cpp | 31 ++++++++- Source/Project64-input/CProject64Input.h | 2 + Source/Project64-input/DirectInput.cpp | 74 +++++++++++++++++++++- Source/Project64-input/DirectInput.h | 11 +++- Source/Project64-input/InputMain.cpp | 3 +- 5 files changed, 115 insertions(+), 6 deletions(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index 67acfde76..0b193d71d 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -6,7 +6,8 @@ CProject64Input * g_InputPlugin = nullptr; CProject64Input::CProject64Input(HINSTANCE hinst) : m_hinst(hinst), m_Scanning(false), - m_DisplayCtrlId(0) + m_DisplayCtrlId(0), + m_iFirstController(0) { memset(m_Controllers, 0, sizeof(m_Controllers)); } @@ -30,6 +31,34 @@ void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) } } +void CProject64Input::GetKeys(int32_t Control, BUTTONS * Keys) +{ + if (Control >= sizeof(m_Controllers) / sizeof(m_Controllers[0])) + { + return; + } + CGuard guard(m_CS); + if (Control == m_iFirstController) + { + m_DirectInput->UpdateDeviceData(); + } + N64CONTROLLER & Controller = m_Controllers[Control]; + Keys->R_DPAD = m_DirectInput->IsButtonPressed(Controller.R_DPAD); + Keys->L_DPAD = m_DirectInput->IsButtonPressed(Controller.L_DPAD); + Keys->D_DPAD = m_DirectInput->IsButtonPressed(Controller.D_DPAD); + Keys->U_DPAD = m_DirectInput->IsButtonPressed(Controller.U_DPAD); + Keys->START_BUTTON = m_DirectInput->IsButtonPressed(Controller.START_BUTTON); + Keys->Z_TRIG = m_DirectInput->IsButtonPressed(Controller.Z_TRIG); + Keys->B_BUTTON = m_DirectInput->IsButtonPressed(Controller.B_BUTTON); + Keys->A_BUTTON = m_DirectInput->IsButtonPressed(Controller.A_BUTTON); + Keys->R_CBUTTON = m_DirectInput->IsButtonPressed(Controller.R_CBUTTON); + Keys->L_CBUTTON = m_DirectInput->IsButtonPressed(Controller.L_CBUTTON); + Keys->D_CBUTTON = m_DirectInput->IsButtonPressed(Controller.D_CBUTTON); + Keys->U_CBUTTON = m_DirectInput->IsButtonPressed(Controller.U_CBUTTON); + Keys->R_TRIG = m_DirectInput->IsButtonPressed(Controller.R_TRIG); + Keys->L_TRIG = m_DirectInput->IsButtonPressed(Controller.L_TRIG); +} + void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) { m_Scanning = true; diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index d88317826..b7183d8d8 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -12,6 +12,7 @@ public: ~CProject64Input(); void InitiateControllers(CONTROL_INFO * ControlInfo); + void GetKeys(int32_t Control, BUTTONS * Keys); void StartScanDevices(int32_t DisplayCtrlId); void EndScanDevices(void); CDirectInput::ScanResult ScanDevices(BUTTON & Button); @@ -34,6 +35,7 @@ private: HINSTANCE m_hinst; bool m_Scanning; int32_t m_DisplayCtrlId; + int32_t m_iFirstController; }; extern CProject64Input * g_InputPlugin; \ No newline at end of file diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 542ce81e6..743e804d9 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -102,7 +102,7 @@ BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi) return DIENUM_CONTINUE; } - DEVICE Device; + DEVICE Device = { 0 }; Device.didHandle = nullptr; Device.dwDevType = lpddi->dwDevType; Device.ProductName = stdstr().FromUTF16(lpddi->tszProductName); @@ -173,7 +173,7 @@ CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button) uint8_t DeviceType = LOBYTE(device.dwDevType); if (DeviceType == DI8DEVTYPE_KEYBOARD) { - Result = ScanKeyboard(device.didHandle, Button); + Result = ScanKeyboard(itr->first, device.didHandle, Button); } else if (DeviceType == DI8DEVTYPE_MOUSE) { @@ -215,7 +215,51 @@ std::wstring CDirectInput::ButtonAssignment(BUTTON & Button) return L"Unknown"; } -CDirectInput::ScanResult CDirectInput::ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton) +bool CDirectInput::IsButtonPressed(BUTTON & Button) +{ + if (Button.Device == nullptr) + { + return false; + } + DEVICE & Device = *(DEVICE *)Button.Device; + switch (Button.BtnType) + { + case BTNTYPE_KEYBUTTON: + return (Device.State.Keyboard[Button.Offset] & 0x80) != 0; + } + return false; +} + +void CDirectInput::UpdateDeviceData(void) +{ + for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++) + { + DEVICE & device = itr->second; + LPDIRECTINPUTDEVICE8 & didHandle = device.didHandle; + if (didHandle == nullptr) + { + continue; + } + if (FAILED(didHandle->Poll()) && !AcquireDevice(didHandle)) + { + continue; + } + + switch (LOBYTE(device.dwDevType)) + { + case DI8DEVTYPE_KEYBOARD: + didHandle->GetDeviceState(sizeof(device.State.Keyboard), &device.State.Keyboard); + break; + case DI8DEVTYPE_MOUSE: + didHandle->GetDeviceState(sizeof(device.State.Mouse), &device.State.Mouse); + break; + default: + didHandle->GetDeviceState(sizeof(device.State.Joy), &device.State.Joy); + } + } +} + +CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton) { if (didHandle == nullptr) { @@ -242,11 +286,35 @@ CDirectInput::ScanResult CDirectInput::ScanKeyboard(LPDIRECTINPUTDEVICE8 didHand pButton.Offset = (uint8_t)i; pButton.AxisID = 0; pButton.BtnType = BTNTYPE_KEYBUTTON; + pButton.DeviceGuid = DeviceGuid; + pButton.Device = nullptr; return SCAN_SUCCEED; } return SCAN_FAILED; } +bool CDirectInput::AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice) +{ + HRESULT hResult = lpDirectInputDevice->Acquire(); + if (hResult == DIERR_INPUTLOST) + { + for (uint32_t i = 0; i < 10; i++) + { + hResult = lpDirectInputDevice->Acquire(); + if (hResult != DIERR_INPUTLOST) + { + break; + } + } + } + if (SUCCEEDED(hResult)) + { + lpDirectInputDevice->Poll(); + return true; + } + return false; +} + void CDirectInput::LoadConfig(void) { diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index 8a03a8b9a..b33178a73 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -25,6 +25,8 @@ public: void MapControllerDevice(N64CONTROLLER & Controller); ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); + bool IsButtonPressed(BUTTON & Button); + void UpdateDeviceData(void); private: CDirectInput(); @@ -33,7 +35,8 @@ private: static BOOL CALLBACK stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); - ScanResult ScanKeyboard(LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton); + ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton); + bool AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice); void LoadConfig(void); typedef struct @@ -42,6 +45,12 @@ private: uint32_t dwDevType; std::string InstanceName; std::string ProductName; + union INPUTSTATE + { + DIJOYSTATE Joy; + DIMOUSESTATE2 Mouse; + uint8_t Keyboard[256]; + } State; } DEVICE; struct GUIDComparer diff --git a/Source/Project64-input/InputMain.cpp b/Source/Project64-input/InputMain.cpp index 7472783c5..8a3b4bcdd 100644 --- a/Source/Project64-input/InputMain.cpp +++ b/Source/Project64-input/InputMain.cpp @@ -112,8 +112,9 @@ input: - Controller Number (0 to 3) the controller state. output: none *******************************************************************/ -EXPORT void CALL GetKeys(int32_t /*Control*/, BUTTONS * /*Keys*/) +EXPORT void CALL GetKeys(int32_t Control, BUTTONS * Keys) { + g_InputPlugin->GetKeys(Control, Keys); } /****************************************************************** From 00556d4524f3c54aac363607d53e8290f8cb033a Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:36:10 +0930 Subject: [PATCH 10/23] Project64-input: Flip x/y axis in structure --- Source/Android/PluginInput/Controller_1.1.h | 4 ++-- Source/Project64-core/Plugins/ControllerPlugin.cpp | 2 +- Source/Project64-core/Plugins/ControllerPlugin.h | 10 +++++----- Source/Project64-input/ControllerSpec1.1.h | 4 ++-- Source/nragev20/ControllerSpecs/Controller #1.1.h | 4 ++-- 5 files changed, 12 insertions(+), 12 deletions(-) diff --git a/Source/Android/PluginInput/Controller_1.1.h b/Source/Android/PluginInput/Controller_1.1.h index bd8279332..7e7dae4e5 100644 --- a/Source/Android/PluginInput/Controller_1.1.h +++ b/Source/Android/PluginInput/Controller_1.1.h @@ -68,9 +68,9 @@ typedef union unsigned Reserved1 : 1; unsigned Reserved2 : 1; - signed Y_AXIS : 8; - signed X_AXIS : 8; + + signed Y_AXIS : 8; }; } BUTTONS; #pragma warning(pop) diff --git a/Source/Project64-core/Plugins/ControllerPlugin.cpp b/Source/Project64-core/Plugins/ControllerPlugin.cpp index d775fef71..a69fc8cb7 100644 --- a/Source/Project64-core/Plugins/ControllerPlugin.cpp +++ b/Source/Project64-core/Plugins/ControllerPlugin.cpp @@ -149,7 +149,7 @@ void CControl_Plugin::UpdateKeys(void) if (!m_AllocatedControllers) { return; } for (int32_t cont = 0; cont < sizeof(m_Controllers) / sizeof(m_Controllers[0]); cont++) { - if (!m_Controllers[cont]->m_Present) { continue; } + if (!m_Controllers[cont]->Present()) { continue; } if (!m_Controllers[cont]->m_RawData) { GetKeys(cont, &m_Controllers[cont]->m_Buttons); diff --git a/Source/Project64-core/Plugins/ControllerPlugin.h b/Source/Project64-core/Plugins/ControllerPlugin.h index d752a4058..7468def03 100644 --- a/Source/Project64-core/Plugins/ControllerPlugin.h +++ b/Source/Project64-core/Plugins/ControllerPlugin.h @@ -37,9 +37,9 @@ typedef union unsigned Reserved1 : 1; unsigned Reserved2 : 1; - signed Y_AXIS : 8; - signed X_AXIS : 8; + + signed Y_AXIS : 8; }; } BUTTONS; #pragma warning(pop) @@ -76,7 +76,7 @@ class CCONTROL { public: CCONTROL(int32_t &Present, int32_t &RawData, int32_t &PlugType); - inline bool Present(void) const { return m_Present != 0; } + inline bool Present(void) const { return m_Present != 0; } inline uint32_t Buttons(void) const { return m_Buttons.Value; } inline PluginType Plugin(void) const { return static_cast(m_PlugType); } private: @@ -84,8 +84,8 @@ private: int32_t & m_Present; int32_t & m_RawData; - int32_t & m_PlugType; - BUTTONS m_Buttons; + int32_t & m_PlugType; + BUTTONS m_Buttons; CCONTROL(void); // Disable default constructor CCONTROL(const CCONTROL&); // Disable copy constructor diff --git a/Source/Project64-input/ControllerSpec1.1.h b/Source/Project64-input/ControllerSpec1.1.h index 11cd0efcc..6299b8c8b 100644 --- a/Source/Project64-input/ControllerSpec1.1.h +++ b/Source/Project64-input/ControllerSpec1.1.h @@ -72,9 +72,9 @@ typedef union unsigned Reserved1 : 1; unsigned Reserved2 : 1; - signed Y_AXIS : 8; - signed X_AXIS : 8; + + signed Y_AXIS : 8; }; } BUTTONS; diff --git a/Source/nragev20/ControllerSpecs/Controller #1.1.h b/Source/nragev20/ControllerSpecs/Controller #1.1.h index 7fbc27219..e6e5be5d3 100644 --- a/Source/nragev20/ControllerSpecs/Controller #1.1.h +++ b/Source/nragev20/ControllerSpecs/Controller #1.1.h @@ -82,9 +82,9 @@ extern "C" { unsigned Reserved1 : 1; unsigned Reserved2 : 1; - signed Y_AXIS : 8; - signed X_AXIS : 8; + + signed Y_AXIS : 8; }; } BUTTONS; From 8df9403bce64b0b73024f0efef2892294cfc73ec Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:46:08 +0930 Subject: [PATCH 11/23] Project64-input: Add saving/loading of range --- Source/Project64-input/CProject64Input.h | 2 + Source/Project64-input/InputConfigUI.cpp | 85 +++++++++++++++------- Source/Project64-input/InputSettings.cpp | 13 ++++ Source/Project64-input/InputSettingsID.h | 1 + Source/Project64-input/N64Controller.h | 1 + Source/Project64-input/Project64-input.rc | Bin 17130 -> 17156 bytes Source/Project64-input/resource.h | Bin 8274 -> 8550 bytes Source/Project64-input/wtl.h | 7 +- 8 files changed, 78 insertions(+), 31 deletions(-) diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index b7183d8d8..35749e8c0 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -23,6 +23,7 @@ public: inline bool IsScanning(void) const { return m_Scanning; } inline int32_t DisplayCtrlId(void) const { return m_DisplayCtrlId; } inline N64CONTROLLER & Controllers(int32_t Controller) { return m_Controllers[Controller]; } + inline CONTROL & ControlInfo(int32_t Controller) { return m_ControlInfo.Controls[Controller]; } private: CProject64Input(); @@ -30,6 +31,7 @@ private: CProject64Input& operator=(const CProject64Input&); CriticalSection m_CS; + CONTROL_INFO m_ControlInfo; N64CONTROLLER m_Controllers[4]; std::unique_ptr m_DirectInput; HINSTANCE m_hinst; diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 400d692ba..5d56859f1 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -20,6 +20,8 @@ public: BEGIN_MSG_MAP(CDebugSettings) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) + NOTIFY_HANDLER_EX(IDC_TACK_RANGE, NM_RELEASEDCAPTURE, ItemChangedNotify); + MESSAGE_HANDLER(WM_HSCROLL, OnScroll) CHAIN_MSG_MAP(CPropertyPageImpl) END_MSG_MAP() @@ -29,6 +31,8 @@ public: bool OnApply(); private: + LRESULT OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT ItemChangedNotify(NMHDR* /*pNMHDR*/); void ButtonChannged(void); static void stButtonChanged(size_t data) { ((CControllerSettings *)data)->ButtonChannged(); } @@ -36,34 +40,35 @@ private: uint32_t m_ControllerNumber; uint32_t m_ScanCount; CBitmapPicture m_ControllerImg; - CScanButton ButtonUDPad, ButtonDDPad, ButtonLDPad, ButtonRDPad; - CScanButton ButtonCUp, ButtonCDown, ButtonCLeft, ButtonCRight; - CScanButton ButtonA, ButtonB, ButtonStart; - CScanButton ButtonZtrigger, ButtonRTrigger, ButtonLTrigger; - CScanButton ButtonAnalogU, ButtonAnalogD, ButtonAnalogL, ButtonAnalogR; + CTrackBarCtrl m_Range; + CScanButton m_ButtonUDPad, m_ButtonDDPad, m_ButtonLDPad, m_ButtonRDPad; + CScanButton m_ButtonCUp, m_ButtonCDown, m_ButtonCLeft, m_ButtonCRight; + CScanButton m_ButtonA, m_ButtonB, m_ButtonStart; + CScanButton m_ButtonZtrigger, m_ButtonRTrigger, m_ButtonLTrigger; + CScanButton m_ButtonAnalogU, m_ButtonAnalogD, m_ButtonAnalogL, m_ButtonAnalogR; }; CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : m_ControllerNumber(ControllerNumber), m_ScanCount(0), - ButtonUDPad(g_InputPlugin->Controllers(ControllerNumber).U_DPAD, IDC_EDIT_DIGITIAL_UP, IDC_BTN_DIGITIAL_UP), - ButtonDDPad(g_InputPlugin->Controllers(ControllerNumber).D_DPAD, IDC_EDIT_DIGITIAL_DOWN, IDC_BTN_DIGITIAL_DOWN), - ButtonLDPad(g_InputPlugin->Controllers(ControllerNumber).L_DPAD, IDC_EDIT_DIGITIAL_LEFT, IDC_BTN_DIGITIAL_LEFT), - ButtonRDPad(g_InputPlugin->Controllers(ControllerNumber).R_DPAD, IDC_EDIT_DIGITIAL_RIGHT, IDC_BTN_DIGITIAL_RIGHT), - ButtonA(g_InputPlugin->Controllers(ControllerNumber).A_BUTTON, IDC_EDIT_BUTTON_A, IDC_BTN_BUTTON_A), - ButtonB(g_InputPlugin->Controllers(ControllerNumber).B_BUTTON, IDC_EDIT_BUTTON_B, IDC_BTN_BUTTON_B), - ButtonCUp(g_InputPlugin->Controllers(ControllerNumber).U_CBUTTON, IDC_EDIT_CBUTTON_UP, IDC_BTN_CBUTTON_UP), - ButtonCDown(g_InputPlugin->Controllers(ControllerNumber).D_CBUTTON, IDC_EDIT_CBUTTON_DOWN, IDC_BTN_CBUTTON_DOWN), - ButtonCLeft(g_InputPlugin->Controllers(ControllerNumber).L_CBUTTON, IDC_EDIT_CBUTTON_LEFT, IDC_BTN_CBUTTON_LEFT), - ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT), - ButtonStart(g_InputPlugin->Controllers(ControllerNumber).START_BUTTON, IDC_EDIT_BUTTON_START, IDC_BTN_BUTTON_START), - ButtonZtrigger(g_InputPlugin->Controllers(ControllerNumber).Z_TRIG, IDC_EDIT_BUTTON_Z, IDC_BTN_BUTTON_Z), - ButtonRTrigger(g_InputPlugin->Controllers(ControllerNumber).R_TRIG, IDC_EDIT_RTRIGGER, IDC_BTN_RTRIGGER), - ButtonLTrigger(g_InputPlugin->Controllers(ControllerNumber).L_TRIG, IDC_EDIT_LTRIGGER, IDC_BTN_LTRIGGER), - ButtonAnalogU(g_InputPlugin->Controllers(ControllerNumber).U_ANALOG, IDC_EDIT_ANALOG_UP, IDC_BTN_ANALOG_UP), - ButtonAnalogD(g_InputPlugin->Controllers(ControllerNumber).D_ANALOG, IDC_EDIT_ANALOG_DOWN, IDC_BTN_ANALOG_DOWN), - ButtonAnalogL(g_InputPlugin->Controllers(ControllerNumber).L_ANALOG, IDC_EDIT_ANALOG_LEFT, IDC_BTN_ANALOG_LEFT), - ButtonAnalogR(g_InputPlugin->Controllers(ControllerNumber).R_ANALOG, IDC_EDIT_ANALOG_RIGHT, IDC_BTN_ANALOG_RIGHT) + m_ButtonUDPad(g_InputPlugin->Controllers(ControllerNumber).U_DPAD, IDC_EDIT_DIGITIAL_UP, IDC_BTN_DIGITIAL_UP), + m_ButtonDDPad(g_InputPlugin->Controllers(ControllerNumber).D_DPAD, IDC_EDIT_DIGITIAL_DOWN, IDC_BTN_DIGITIAL_DOWN), + m_ButtonLDPad(g_InputPlugin->Controllers(ControllerNumber).L_DPAD, IDC_EDIT_DIGITIAL_LEFT, IDC_BTN_DIGITIAL_LEFT), + m_ButtonRDPad(g_InputPlugin->Controllers(ControllerNumber).R_DPAD, IDC_EDIT_DIGITIAL_RIGHT, IDC_BTN_DIGITIAL_RIGHT), + m_ButtonA(g_InputPlugin->Controllers(ControllerNumber).A_BUTTON, IDC_EDIT_BUTTON_A, IDC_BTN_BUTTON_A), + m_ButtonB(g_InputPlugin->Controllers(ControllerNumber).B_BUTTON, IDC_EDIT_BUTTON_B, IDC_BTN_BUTTON_B), + m_ButtonCUp(g_InputPlugin->Controllers(ControllerNumber).U_CBUTTON, IDC_EDIT_CBUTTON_UP, IDC_BTN_CBUTTON_UP), + m_ButtonCDown(g_InputPlugin->Controllers(ControllerNumber).D_CBUTTON, IDC_EDIT_CBUTTON_DOWN, IDC_BTN_CBUTTON_DOWN), + m_ButtonCLeft(g_InputPlugin->Controllers(ControllerNumber).L_CBUTTON, IDC_EDIT_CBUTTON_LEFT, IDC_BTN_CBUTTON_LEFT), + m_ButtonCRight(g_InputPlugin->Controllers(ControllerNumber).R_CBUTTON, IDC_EDIT_CBUTTON_RIGHT, IDC_BTN_CBUTTON_RIGHT), + m_ButtonStart(g_InputPlugin->Controllers(ControllerNumber).START_BUTTON, IDC_EDIT_BUTTON_START, IDC_BTN_BUTTON_START), + m_ButtonZtrigger(g_InputPlugin->Controllers(ControllerNumber).Z_TRIG, IDC_EDIT_BUTTON_Z, IDC_BTN_BUTTON_Z), + m_ButtonRTrigger(g_InputPlugin->Controllers(ControllerNumber).R_TRIG, IDC_EDIT_RTRIGGER, IDC_BTN_RTRIGGER), + m_ButtonLTrigger(g_InputPlugin->Controllers(ControllerNumber).L_TRIG, IDC_EDIT_LTRIGGER, IDC_BTN_LTRIGGER), + m_ButtonAnalogU(g_InputPlugin->Controllers(ControllerNumber).U_ANALOG, IDC_EDIT_ANALOG_UP, IDC_BTN_ANALOG_UP), + m_ButtonAnalogD(g_InputPlugin->Controllers(ControllerNumber).D_ANALOG, IDC_EDIT_ANALOG_DOWN, IDC_BTN_ANALOG_DOWN), + m_ButtonAnalogL(g_InputPlugin->Controllers(ControllerNumber).L_ANALOG, IDC_EDIT_ANALOG_LEFT, IDC_BTN_ANALOG_LEFT), + m_ButtonAnalogR(g_InputPlugin->Controllers(ControllerNumber).R_ANALOG, IDC_EDIT_ANALOG_RIGHT, IDC_BTN_ANALOG_RIGHT) { m_Title = stdstr_f("Player %d", ControllerNumber + 1).ToUTF16(); SetTitle(m_Title.c_str()); @@ -71,19 +76,25 @@ CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { + N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); GetDlgItem(IDC_BTN_SETUP).EnableWindow(false); GetDlgItem(IDC_BTN_DEFAULTS).EnableWindow(false); GetDlgItem(IDC_BTN_LOAD).EnableWindow(false); GetDlgItem(IDC_BTN_SAVE).EnableWindow(false); - GetDlgItem(IDC_TACK_RANGE).EnableWindow(false); + m_Range.Attach(GetDlgItem(IDC_SLIDER_RANGE)); + m_Range.SetTicFreq(1); + m_Range.SetRangeMin(1); + m_Range.SetRangeMax(100); + m_Range.SetPos(Controller.Range); + CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); CScanButton * Buttons[] = { - &ButtonUDPad, &ButtonDDPad, &ButtonLDPad, &ButtonRDPad, &ButtonA, &ButtonB, - &ButtonCUp, &ButtonCDown, &ButtonCLeft, &ButtonCRight, &ButtonStart, - &ButtonZtrigger, &ButtonRTrigger, &ButtonLTrigger, - &ButtonAnalogU, &ButtonAnalogD, &ButtonAnalogL, &ButtonAnalogR + &m_ButtonUDPad, &m_ButtonDDPad, &m_ButtonLDPad, &m_ButtonRDPad, &m_ButtonA, &m_ButtonB, + &m_ButtonCUp, &m_ButtonCDown, &m_ButtonCLeft, &m_ButtonCRight, &m_ButtonStart, + &m_ButtonZtrigger, &m_ButtonRTrigger, &m_ButtonLTrigger, + &m_ButtonAnalogU, &m_ButtonAnalogD, &m_ButtonAnalogL, &m_ButtonAnalogR }; for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) @@ -109,9 +120,27 @@ HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic) bool CControllerSettings::OnApply() { + N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); + Controller.Range = (uint8_t)m_Range.GetPos(); return g_InputPlugin->SaveController(m_ControllerNumber); } +LRESULT CControllerSettings::OnScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM lParam, BOOL& /*bHandled*/) +{ + LONG SliderId = CWindow((HWND)lParam).GetWindowLong(GWL_ID); + if (SliderId == IDC_SLIDER_RANGE) + { + CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); + } + return 0; +} + +LRESULT CControllerSettings::ItemChangedNotify(NMHDR* /*pNMHDR*/) +{ + SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0); + return 0; +} + void CControllerSettings::ButtonChannged(void) { CPropertySheetWindow(GetParent()).SetModified(m_hWnd); diff --git a/Source/Project64-input/InputSettings.cpp b/Source/Project64-input/InputSettings.cpp index 468220b29..bdae4d1ba 100644 --- a/Source/Project64-input/InputSettings.cpp +++ b/Source/Project64-input/InputSettings.cpp @@ -52,6 +52,12 @@ void CInputSettings::LoadController(uint32_t ControlIndex, N64CONTROLLER & Contr } Buttons[i].Button = StrToButton(GetSettingSz((short)Buttons[i].SettingId, Buffer, sizeof(Buffer) / sizeof(Buffer[0]))); } + + InputSettingID RangeSettings[] = { Set_Control0_Range }; + + Controller.Range = (uint8_t)(ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0])) ? GetSetting((short)RangeSettings[ControlIndex]) : 100); + if (Controller.Range == 0) { Controller.Range = 1; } + if (Controller.Range > 100) { Controller.Range = 100; } } void CInputSettings::SaveController(uint32_t ControlIndex, const N64CONTROLLER & Controller) @@ -91,6 +97,12 @@ void CInputSettings::SaveController(uint32_t ControlIndex, const N64CONTROLLER & } SetSettingSz((short)Buttons[i].SettingId, ButtonToStr(Buttons[i].Button).c_str()); } + + InputSettingID RangeSettings[] = { Set_Control0_Range }; + if (ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0]))) + { + SetSetting((short)RangeSettings[ControlIndex], Controller.Range); + } FlushSettings(); } @@ -124,6 +136,7 @@ std::string CInputSettings::GUIDtoString(const GUID & guid) void CInputSettings::RegisterSettings(void) { SetModuleName("Input"); + RegisterSetting(Set_Control0_Range, Data_DWORD_General, "Range", "Controller 1", 100, nullptr); RegisterSetting(Set_Control0_U_DPAD, Data_String_General, "DPadUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 17 0 5"); RegisterSetting(Set_Control0_D_DPAD, Data_String_General, "DPadDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 25 0 5"); RegisterSetting(Set_Control0_L_DPAD, Data_String_General, "DPadLeft", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 24 0 5"); diff --git a/Source/Project64-input/InputSettingsID.h b/Source/Project64-input/InputSettingsID.h index c0f36a57c..cdb9491c9 100644 --- a/Source/Project64-input/InputSettingsID.h +++ b/Source/Project64-input/InputSettingsID.h @@ -2,6 +2,7 @@ enum InputSettingID { + Set_Control0_Range, Set_Control0_U_DPAD, Set_Control0_D_DPAD, Set_Control0_L_DPAD, diff --git a/Source/Project64-input/N64Controller.h b/Source/Project64-input/N64Controller.h index 5598356f0..fc8cb29e3 100644 --- a/Source/Project64-input/N64Controller.h +++ b/Source/Project64-input/N64Controller.h @@ -21,4 +21,5 @@ typedef struct BUTTON D_ANALOG; BUTTON L_ANALOG; BUTTON R_ANALOG; + uint8_t Range; } N64CONTROLLER; diff --git a/Source/Project64-input/Project64-input.rc b/Source/Project64-input/Project64-input.rc index c4d6335786fe6abcf09e61acf37c3291ade57148..6a85d28d226d9926bcf8d9e3bd533cfe06c332ab 100644 GIT binary patch delta 60 zcmaFW%GlDzxIsjTJD9-hxIsjTJ%quL!I{B(vb@rMc0&dO1``I8&A*j66#%Fe2 -#include -#include -#include +#include +#include +#include +#include #include #pragma warning(pop) \ No newline at end of file From f1d8910e5f8384e5c46247324a2aa4c4ea97399b Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:50:36 +0930 Subject: [PATCH 12/23] Project64-input: Add controller present --- Source/Project64-input/CProject64Input.cpp | 4 ++-- Source/Project64-input/InputSettings.cpp | 13 +++++++++++-- Source/Project64-input/InputSettings.h | 5 +++-- Source/Project64-input/InputSettingsID.h | 1 + 4 files changed, 17 insertions(+), 6 deletions(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index 0b193d71d..e831fc489 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -26,7 +26,7 @@ void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) m_DirectInput->Initiate(ControlInfo); for (size_t i = 0, n = sizeof(m_Controllers) / sizeof(m_Controllers[0]); i < n; i++) { - g_Settings->LoadController(0, m_Controllers[i]); + g_Settings->LoadController(i, m_ControlInfo.Controls[i], m_Controllers[i]); m_DirectInput->MapControllerDevice(m_Controllers[i]); } } @@ -96,6 +96,6 @@ bool CProject64Input::SaveController(uint32_t ControlIndex) { return false; } - g_Settings->SaveController(ControlIndex, m_Controllers[ControlIndex]); + g_Settings->SaveController(ControlIndex, m_ControlInfo.Controls[ControlIndex], m_Controllers[ControlIndex]); return true; } diff --git a/Source/Project64-input/InputSettings.cpp b/Source/Project64-input/InputSettings.cpp index bdae4d1ba..af4c31cdf 100644 --- a/Source/Project64-input/InputSettings.cpp +++ b/Source/Project64-input/InputSettings.cpp @@ -14,7 +14,7 @@ CInputSettings::~CInputSettings() { } -void CInputSettings::LoadController(uint32_t ControlIndex, N64CONTROLLER & Controller) +void CInputSettings::LoadController(uint32_t ControlIndex, CONTROL & ControllerInfo, N64CONTROLLER & Controller) { struct { BUTTON & Button; @@ -53,14 +53,16 @@ void CInputSettings::LoadController(uint32_t ControlIndex, N64CONTROLLER & Contr Buttons[i].Button = StrToButton(GetSettingSz((short)Buttons[i].SettingId, Buffer, sizeof(Buffer) / sizeof(Buffer[0]))); } + InputSettingID PresentSettings[] = { Set_Control0_Present }; InputSettingID RangeSettings[] = { Set_Control0_Range }; + ControllerInfo.Present = ControlIndex < (sizeof(PresentSettings) / sizeof(PresentSettings[0])) ? GetSetting((short)PresentSettings[ControlIndex]) != 0 : 0; Controller.Range = (uint8_t)(ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0])) ? GetSetting((short)RangeSettings[ControlIndex]) : 100); if (Controller.Range == 0) { Controller.Range = 1; } if (Controller.Range > 100) { Controller.Range = 100; } } -void CInputSettings::SaveController(uint32_t ControlIndex, const N64CONTROLLER & Controller) +void CInputSettings::SaveController(uint32_t ControlIndex, const CONTROL & ControllerInfo, const N64CONTROLLER & Controller) { struct { const BUTTON & Button; @@ -98,6 +100,12 @@ void CInputSettings::SaveController(uint32_t ControlIndex, const N64CONTROLLER & SetSettingSz((short)Buttons[i].SettingId, ButtonToStr(Buttons[i].Button).c_str()); } + InputSettingID PresentSettings[] = { Set_Control0_Present }; + if (ControlIndex < (sizeof(PresentSettings) / sizeof(PresentSettings[0]))) + { + SetSetting((short)PresentSettings[ControlIndex], ControllerInfo.Present); + } + InputSettingID RangeSettings[] = { Set_Control0_Range }; if (ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0]))) { @@ -136,6 +144,7 @@ std::string CInputSettings::GUIDtoString(const GUID & guid) void CInputSettings::RegisterSettings(void) { SetModuleName("Input"); + RegisterSetting(Set_Control0_Present, Data_DWORD_General, "Present", "Controller 1", 1, nullptr); RegisterSetting(Set_Control0_Range, Data_DWORD_General, "Range", "Controller 1", 100, nullptr); RegisterSetting(Set_Control0_U_DPAD, Data_String_General, "DPadUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 17 0 5"); RegisterSetting(Set_Control0_D_DPAD, Data_String_General, "DPadDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 25 0 5"); diff --git a/Source/Project64-input/InputSettings.h b/Source/Project64-input/InputSettings.h index 275b84acd..d727a85e8 100644 --- a/Source/Project64-input/InputSettings.h +++ b/Source/Project64-input/InputSettings.h @@ -2,6 +2,7 @@ #include #include #include "N64Controller.h" +#include "ControllerSpec1.1.h" class CInputSettings { @@ -9,8 +10,8 @@ public: CInputSettings(); ~CInputSettings(); - void LoadController(uint32_t ControlIndex, N64CONTROLLER & Controller); - void SaveController(uint32_t ControlIndex, const N64CONTROLLER & Controller); + void LoadController(uint32_t ControlIndex, CONTROL & ControllerInfo, N64CONTROLLER & Controller); + void SaveController(uint32_t ControlIndex, const CONTROL & ControllerInfo, const N64CONTROLLER & Controller); private: CInputSettings(const CInputSettings&); diff --git a/Source/Project64-input/InputSettingsID.h b/Source/Project64-input/InputSettingsID.h index cdb9491c9..d381df4f9 100644 --- a/Source/Project64-input/InputSettingsID.h +++ b/Source/Project64-input/InputSettingsID.h @@ -2,6 +2,7 @@ enum InputSettingID { + Set_Control0_Present, Set_Control0_Range, Set_Control0_U_DPAD, Set_Control0_D_DPAD, From 7bbba05024c50534d1b5996e141d14f406216f63 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:53:32 +0930 Subject: [PATCH 13/23] Project64-input: Find the first plugin plugged in --- Source/Project64-input/CProject64Input.cpp | 8 +++++++- Source/Project64-input/InputConfigUI.cpp | 13 +++++++++++++ 2 files changed, 20 insertions(+), 1 deletion(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index e831fc489..f45450bd1 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -7,7 +7,7 @@ CProject64Input::CProject64Input(HINSTANCE hinst) : m_hinst(hinst), m_Scanning(false), m_DisplayCtrlId(0), - m_iFirstController(0) + m_iFirstController(-1) { memset(m_Controllers, 0, sizeof(m_Controllers)); } @@ -19,15 +19,21 @@ CProject64Input::~CProject64Input() void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) { CGuard guard(m_CS); + m_ControlInfo = *ControlInfo; if (m_DirectInput.get() == NULL) { m_DirectInput.reset(new CDirectInput(m_hinst)); } m_DirectInput->Initiate(ControlInfo); + m_iFirstController = -1; for (size_t i = 0, n = sizeof(m_Controllers) / sizeof(m_Controllers[0]); i < n; i++) { g_Settings->LoadController(i, m_ControlInfo.Controls[i], m_Controllers[i]); m_DirectInput->MapControllerDevice(m_Controllers[i]); + if (m_ControlInfo.Controls[i].Present != 0 && m_iFirstController < 0) + { + m_iFirstController = i; + } } } diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 5d56859f1..5e8610239 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -20,6 +20,7 @@ public: BEGIN_MSG_MAP(CDebugSettings) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) + COMMAND_HANDLER_EX(IDC_CHK_PLUGGED_IN, BN_CLICKED, ItemChanged) NOTIFY_HANDLER_EX(IDC_TACK_RANGE, NM_RELEASEDCAPTURE, ItemChangedNotify); MESSAGE_HANDLER(WM_HSCROLL, OnScroll) CHAIN_MSG_MAP(CPropertyPageImpl) @@ -32,6 +33,7 @@ public: private: LRESULT OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + void ItemChanged(UINT Code, int id, HWND ctl); LRESULT ItemChangedNotify(NMHDR* /*pNMHDR*/); void ButtonChannged(void); static void stButtonChanged(size_t data) { ((CControllerSettings *)data)->ButtonChannged(); } @@ -40,6 +42,7 @@ private: uint32_t m_ControllerNumber; uint32_t m_ScanCount; CBitmapPicture m_ControllerImg; + CButton m_PluggedIn; CTrackBarCtrl m_Range; CScanButton m_ButtonUDPad, m_ButtonDDPad, m_ButtonLDPad, m_ButtonRDPad; CScanButton m_ButtonCUp, m_ButtonCDown, m_ButtonCLeft, m_ButtonCRight; @@ -77,6 +80,7 @@ CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); + CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); GetDlgItem(IDC_BTN_SETUP).EnableWindow(false); GetDlgItem(IDC_BTN_DEFAULTS).EnableWindow(false); GetDlgItem(IDC_BTN_LOAD).EnableWindow(false); @@ -87,6 +91,8 @@ BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam m_Range.SetRangeMax(100); m_Range.SetPos(Controller.Range); CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); + m_PluggedIn.Attach(GetDlgItem(IDC_CHK_PLUGGED_IN)); + m_PluggedIn.SetCheck(ControlInfo.Present != 0 ? BST_CHECKED : BST_UNCHECKED); m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); @@ -121,7 +127,9 @@ HBRUSH CControllerSettings::OnCtlColorStatic(CDCHandle dc, CWindow wndStatic) bool CControllerSettings::OnApply() { N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); + CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); Controller.Range = (uint8_t)m_Range.GetPos(); + ControlInfo.Present = (m_PluggedIn.GetCheck() == BST_CHECKED) ? 1 : 0; return g_InputPlugin->SaveController(m_ControllerNumber); } @@ -135,6 +143,11 @@ LRESULT CControllerSettings::OnScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM l return 0; } +void CControllerSettings::ItemChanged(UINT /*Code*/, int /*id*/, HWND /*ctl*/) +{ + SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0); +} + LRESULT CControllerSettings::ItemChangedNotify(NMHDR* /*pNMHDR*/) { SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0); From 64a3e69cce84bad0a86e6baa55ffe6b0cc621720 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:56:40 +0930 Subject: [PATCH 14/23] Project64-input: Get axis on GetKeys --- Source/Project64-input/CProject64Input.cpp | 2 ++ Source/Project64-input/DirectInput.cpp | 29 ++++++++++++++++++++++ Source/Project64-input/DirectInput.h | 1 + 3 files changed, 32 insertions(+) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index f45450bd1..480c57fee 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -63,6 +63,8 @@ void CProject64Input::GetKeys(int32_t Control, BUTTONS * Keys) Keys->U_CBUTTON = m_DirectInput->IsButtonPressed(Controller.U_CBUTTON); Keys->R_TRIG = m_DirectInput->IsButtonPressed(Controller.R_TRIG); Keys->L_TRIG = m_DirectInput->IsButtonPressed(Controller.L_TRIG); + Keys->Y_AXIS = m_DirectInput->AxisPos(Controller.U_ANALOG, Controller.D_ANALOG, Controller.Range); + Keys->X_AXIS = m_DirectInput->AxisPos(Controller.R_ANALOG, Controller.L_ANALOG, Controller.Range); } void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 743e804d9..e53e0cbc3 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -230,6 +230,35 @@ bool CDirectInput::IsButtonPressed(BUTTON & Button) return false; } +int8_t CDirectInput::AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range) +{ + int8_t Pos = 0; + if (PosBtn.Device != nullptr) + { + DEVICE & Device = *(DEVICE *)PosBtn.Device; + switch (PosBtn.BtnType) + { + case BTNTYPE_KEYBUTTON: + Pos += (Device.State.Keyboard[PosBtn.Offset] & 0x80) != 0 ? 127 : 0; + } + } + if (NegBtn.Device != nullptr) + { + DEVICE & Device = *(DEVICE *)NegBtn.Device; + switch (NegBtn.BtnType) + { + case BTNTYPE_KEYBUTTON: + Pos -= (Device.State.Keyboard[NegBtn.Offset] & 0x80) != 0 ? 127 : 0; + } + } + + if (Pos != 0) + { + Pos = (int8_t)(Pos * (Range / 100.0)); + } + return Pos; +} + void CDirectInput::UpdateDeviceData(void) { for (DEVICE_MAP::iterator itr = m_Devices.begin(); itr != m_Devices.end(); itr++) diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index b33178a73..709469d16 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -26,6 +26,7 @@ public: ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); bool IsButtonPressed(BUTTON & Button); + int8_t AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range); void UpdateDeviceData(void); private: From 5d59156ee4b40721c132c931e5e32826cef09756 Mon Sep 17 00:00:00 2001 From: zilmar Date: Tue, 7 Jul 2020 11:59:49 +0930 Subject: [PATCH 15/23] Project64-input: Add selecting of device --- Source/Project64-input/InputConfigUI.cpp | 16 ++++++++++++++++ Source/Project64-input/InputSettings.cpp | 8 ++++++++ Source/Project64-input/InputSettingsID.h | 1 + 3 files changed, 25 insertions(+) diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 5e8610239..ca554f582 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -21,6 +21,7 @@ public: MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) COMMAND_HANDLER_EX(IDC_CHK_PLUGGED_IN, BN_CLICKED, ItemChanged) + COMMAND_HANDLER_EX(IDC_CMB_DEVICE, CBN_SELCHANGE, ItemChanged) NOTIFY_HANDLER_EX(IDC_TACK_RANGE, NM_RELEASEDCAPTURE, ItemChangedNotify); MESSAGE_HANDLER(WM_HSCROLL, OnScroll) CHAIN_MSG_MAP(CPropertyPageImpl) @@ -43,6 +44,7 @@ private: uint32_t m_ScanCount; CBitmapPicture m_ControllerImg; CButton m_PluggedIn; + CComboBox m_cmbDevice; CTrackBarCtrl m_Range; CScanButton m_ButtonUDPad, m_ButtonDDPad, m_ButtonLDPad, m_ButtonRDPad; CScanButton m_ButtonCUp, m_ButtonCDown, m_ButtonCLeft, m_ButtonCRight; @@ -93,6 +95,19 @@ BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); m_PluggedIn.Attach(GetDlgItem(IDC_CHK_PLUGGED_IN)); m_PluggedIn.SetCheck(ControlInfo.Present != 0 ? BST_CHECKED : BST_UNCHECKED); + m_cmbDevice.Attach(GetDlgItem(IDC_CMB_DEVICE)); + m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"None"), PLUGIN_NONE); + m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"Mem Pak"), PLUGIN_MEMPAK); + m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"Rumble Pak"), PLUGIN_RUMBLE_PAK); + m_cmbDevice.SetCurSel(0); + for (DWORD i = 0, n = m_cmbDevice.GetCount(); i < n; i++) + { + if (m_cmbDevice.GetItemData(i) == (DWORD)ControlInfo.Plugin) + { + m_cmbDevice.SetCurSel(i); + break; + } + } m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); @@ -130,6 +145,7 @@ bool CControllerSettings::OnApply() CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); Controller.Range = (uint8_t)m_Range.GetPos(); ControlInfo.Present = (m_PluggedIn.GetCheck() == BST_CHECKED) ? 1 : 0; + ControlInfo.Plugin = m_cmbDevice.GetItemData(m_cmbDevice.GetCurSel()); return g_InputPlugin->SaveController(m_ControllerNumber); } diff --git a/Source/Project64-input/InputSettings.cpp b/Source/Project64-input/InputSettings.cpp index af4c31cdf..0ce9413a9 100644 --- a/Source/Project64-input/InputSettings.cpp +++ b/Source/Project64-input/InputSettings.cpp @@ -54,9 +54,11 @@ void CInputSettings::LoadController(uint32_t ControlIndex, CONTROL & ControllerI } InputSettingID PresentSettings[] = { Set_Control0_Present }; + InputSettingID PluginSettings[] = { Set_Control0_Plugin }; InputSettingID RangeSettings[] = { Set_Control0_Range }; ControllerInfo.Present = ControlIndex < (sizeof(PresentSettings) / sizeof(PresentSettings[0])) ? GetSetting((short)PresentSettings[ControlIndex]) != 0 : 0; + ControllerInfo.Plugin = ControlIndex < (sizeof(PluginSettings) / sizeof(PluginSettings[0])) ? GetSetting((short)PluginSettings[ControlIndex]) : PLUGIN_NONE; Controller.Range = (uint8_t)(ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0])) ? GetSetting((short)RangeSettings[ControlIndex]) : 100); if (Controller.Range == 0) { Controller.Range = 1; } if (Controller.Range > 100) { Controller.Range = 100; } @@ -105,6 +107,11 @@ void CInputSettings::SaveController(uint32_t ControlIndex, const CONTROL & Contr { SetSetting((short)PresentSettings[ControlIndex], ControllerInfo.Present); } + InputSettingID PluginSettings[] = { Set_Control0_Plugin }; + if (ControlIndex < (sizeof(PluginSettings) / sizeof(PluginSettings[0]))) + { + SetSetting((short)PluginSettings[ControlIndex], ControllerInfo.Plugin); + } InputSettingID RangeSettings[] = { Set_Control0_Range }; if (ControlIndex < (sizeof(RangeSettings) / sizeof(RangeSettings[0]))) @@ -145,6 +152,7 @@ void CInputSettings::RegisterSettings(void) { SetModuleName("Input"); RegisterSetting(Set_Control0_Present, Data_DWORD_General, "Present", "Controller 1", 1, nullptr); + RegisterSetting(Set_Control0_Plugin, Data_DWORD_General, "Plugin", "Controller 1", PLUGIN_MEMPAK, nullptr); RegisterSetting(Set_Control0_Range, Data_DWORD_General, "Range", "Controller 1", 100, nullptr); RegisterSetting(Set_Control0_U_DPAD, Data_String_General, "DPadUp", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 17 0 5"); RegisterSetting(Set_Control0_D_DPAD, Data_String_General, "DPadDown", "Controller 1", 0, "{6F1D2B61-D5A0-11CF-BFC7-444553540000} 25 0 5"); diff --git a/Source/Project64-input/InputSettingsID.h b/Source/Project64-input/InputSettingsID.h index d381df4f9..a1ea5ae44 100644 --- a/Source/Project64-input/InputSettingsID.h +++ b/Source/Project64-input/InputSettingsID.h @@ -3,6 +3,7 @@ enum InputSettingID { Set_Control0_Present, + Set_Control0_Plugin, Set_Control0_Range, Set_Control0_U_DPAD, Set_Control0_D_DPAD, From 1be3f869d6809c158a01b9a861719f84fdff4657 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 20:01:55 +0930 Subject: [PATCH 16/23] Project64: CSettingTypeApplication::Save: do not compare default if passing NULL --- .../Settings/SettingType/SettingsType-Application.cpp | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Source/Project64-core/Settings/SettingType/SettingsType-Application.cpp b/Source/Project64-core/Settings/SettingType/SettingsType-Application.cpp index 2e22e80bf..0206ffe68 100644 --- a/Source/Project64-core/Settings/SettingType/SettingsType-Application.cpp +++ b/Source/Project64-core/Settings/SettingType/SettingsType-Application.cpp @@ -268,7 +268,7 @@ void CSettingTypeApplication::Save(uint32_t Index, const std::string & Value) void CSettingTypeApplication::Save(uint32_t /*Index*/, const char * Value) { - if (m_DefaultSetting != Default_None && + if (m_DefaultSetting != Default_None && Value != NULL && ((m_DefaultSetting == Default_Constant && strcmp(m_DefaultStr,Value) == 0) || (m_DefaultSetting != Default_Constant && strcmp(g_Settings->LoadStringVal(m_DefaultSetting).c_str(),Value) == 0))) { From d21c3a89f2b51609ef153c04b310cbd7dd4ceed3 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 20:34:23 +0930 Subject: [PATCH 17/23] Project64-input: Add Setup button --- Source/Project64-input/CProject64Input.cpp | 1 + Source/Project64-input/DirectInput.cpp | 15 ++++--- Source/Project64-input/DirectInput.h | 2 +- Source/Project64-input/InputConfigUI.cpp | 47 +++++++++++++++++++++- Source/Project64-input/wtl-ScanButton.cpp | 8 ++-- Source/Project64-input/wtl-ScanButton.h | 9 ++++- 6 files changed, 66 insertions(+), 16 deletions(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index 480c57fee..76aa661ee 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -71,6 +71,7 @@ void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) { m_Scanning = true; m_DisplayCtrlId = DisplayCtrlId; + m_DirectInput->UpdateDeviceData(); } void CProject64Input::EndScanDevices(void) diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index e53e0cbc3..851b74fd0 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -7,7 +7,6 @@ CDirectInput::CDirectInput(HINSTANCE hinst) : m_hinst(hinst), m_hWnd(nullptr) { - LoadConfig(); if (m_hDirectInputDLL == nullptr) { m_hDirectInputDLL = LoadLibrary(L"dinput8.dll"); @@ -173,7 +172,7 @@ CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button) uint8_t DeviceType = LOBYTE(device.dwDevType); if (DeviceType == DI8DEVTYPE_KEYBOARD) { - Result = ScanKeyboard(itr->first, device.didHandle, Button); + Result = ScanKeyboard(itr->first, device.didHandle, device.State.Keyboard, Button); } else if (DeviceType == DI8DEVTYPE_MOUSE) { @@ -288,7 +287,7 @@ void CDirectInput::UpdateDeviceData(void) } } -CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton) +CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton) { if (didHandle == nullptr) { @@ -304,6 +303,11 @@ CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPD for (size_t i = 0, n = sizeof(cKeys) / sizeof(cKeys[0]); i < n; i++) { + if (KeyboardState[i] == cKeys[i]) + { + continue; + } + KeyboardState[i] = cKeys[i]; if ((cKeys[i] & 0x80) == 0) { continue; @@ -343,8 +347,3 @@ bool CDirectInput::AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice) } return false; } - -void CDirectInput::LoadConfig(void) -{ - -} diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index 709469d16..2e759d44a 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -36,7 +36,7 @@ private: static BOOL CALLBACK stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); - ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, BUTTON & pButton); + ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton); bool AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice); void LoadConfig(void); diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index ca554f582..2507ecc55 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -17,13 +17,16 @@ class CControllerSettings : public: enum { IDD = IDD_Controller }; - BEGIN_MSG_MAP(CDebugSettings) + BEGIN_MSG_MAP(CControllerSettings) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) + COMMAND_HANDLER_EX(IDC_BTN_SETUP, BN_CLICKED, SetupBtnClicked) COMMAND_HANDLER_EX(IDC_CHK_PLUGGED_IN, BN_CLICKED, ItemChanged) COMMAND_HANDLER_EX(IDC_CMB_DEVICE, CBN_SELCHANGE, ItemChanged) NOTIFY_HANDLER_EX(IDC_TACK_RANGE, NM_RELEASEDCAPTURE, ItemChangedNotify); MESSAGE_HANDLER(WM_HSCROLL, OnScroll) + MESSAGE_HANDLER(CScanButton::WM_SCAN_SUCCESS, OnScanSuccess) + MESSAGE_HANDLER(CScanButton::WM_SCAN_CANCELED, OnScanCanceled) CHAIN_MSG_MAP(CPropertyPageImpl) END_MSG_MAP() @@ -34,6 +37,9 @@ public: private: LRESULT OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnScanSuccess(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + LRESULT OnScanCanceled(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + void SetupBtnClicked(UINT Code, int id, HWND ctl); void ItemChanged(UINT Code, int id, HWND ctl); LRESULT ItemChangedNotify(NMHDR* /*pNMHDR*/); void ButtonChannged(void); @@ -42,6 +48,7 @@ private: std::wstring m_Title; uint32_t m_ControllerNumber; uint32_t m_ScanCount; + int32_t m_SetupIndex; CBitmapPicture m_ControllerImg; CButton m_PluggedIn; CComboBox m_cmbDevice; @@ -56,6 +63,7 @@ private: CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : m_ControllerNumber(ControllerNumber), m_ScanCount(0), + m_SetupIndex(-1), m_ButtonUDPad(g_InputPlugin->Controllers(ControllerNumber).U_DPAD, IDC_EDIT_DIGITIAL_UP, IDC_BTN_DIGITIAL_UP), m_ButtonDDPad(g_InputPlugin->Controllers(ControllerNumber).D_DPAD, IDC_EDIT_DIGITIAL_DOWN, IDC_BTN_DIGITIAL_DOWN), m_ButtonLDPad(g_InputPlugin->Controllers(ControllerNumber).L_DPAD, IDC_EDIT_DIGITIAL_LEFT, IDC_BTN_DIGITIAL_LEFT), @@ -83,7 +91,6 @@ BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam { N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); - GetDlgItem(IDC_BTN_SETUP).EnableWindow(false); GetDlgItem(IDC_BTN_DEFAULTS).EnableWindow(false); GetDlgItem(IDC_BTN_LOAD).EnableWindow(false); GetDlgItem(IDC_BTN_SAVE).EnableWindow(false); @@ -146,6 +153,7 @@ bool CControllerSettings::OnApply() Controller.Range = (uint8_t)m_Range.GetPos(); ControlInfo.Present = (m_PluggedIn.GetCheck() == BST_CHECKED) ? 1 : 0; ControlInfo.Plugin = m_cmbDevice.GetItemData(m_cmbDevice.GetCurSel()); + return g_InputPlugin->SaveController(m_ControllerNumber); } @@ -159,6 +167,41 @@ LRESULT CControllerSettings::OnScroll(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM l return 0; } +LRESULT CControllerSettings::OnScanSuccess(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + if (m_SetupIndex < 0) + { + return 0; + } + + CScanButton * Buttons[] = { + &m_ButtonUDPad, &m_ButtonDDPad, &m_ButtonLDPad, &m_ButtonRDPad, + &m_ButtonAnalogU, &m_ButtonAnalogD, &m_ButtonAnalogL, &m_ButtonAnalogR, + &m_ButtonCUp, &m_ButtonCDown, &m_ButtonCLeft, &m_ButtonCRight, + &m_ButtonB, &m_ButtonA, &m_ButtonStart, &m_ButtonZtrigger, + &m_ButtonLTrigger, &m_ButtonRTrigger + }; + + m_SetupIndex += 1; + if (m_SetupIndex < (sizeof(Buttons) / sizeof(Buttons[0]))) + { + Buttons[m_SetupIndex]->DetectKey(); + } + return 0; +} + +LRESULT CControllerSettings::OnScanCanceled(UINT /*uMsg*/, WPARAM /*wParam*/, LPARAM /*lParam*/, BOOL& /*bHandled*/) +{ + m_SetupIndex = -1; + return 0; +} + +void CControllerSettings::SetupBtnClicked(UINT /*Code*/, int /*id*/, HWND /*ctl*/) +{ + m_SetupIndex = 0; + m_ButtonUDPad.DetectKey(); +} + void CControllerSettings::ItemChanged(UINT /*Code*/, int /*id*/, HWND /*ctl*/) { SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0); diff --git a/Source/Project64-input/wtl-ScanButton.cpp b/Source/Project64-input/wtl-ScanButton.cpp index 1b1aeba55..0fdbd1781 100644 --- a/Source/Project64-input/wtl-ScanButton.cpp +++ b/Source/Project64-input/wtl-ScanButton.cpp @@ -35,7 +35,7 @@ void CScanButton::DisplayButton(void) m_DisplayCtrl.SetWindowText(g_InputPlugin->ButtonAssignment(m_Button).c_str()); } -void CScanButton::OnScan(void) +void CScanButton::DetectKey(void) { enum { @@ -53,7 +53,7 @@ void CScanButton::OnTimer(UINT_PTR nIDEvent) { if (nIDEvent == DETECT_KEY_TIMER) { - bool Stop = false; + bool Stop = false, ScanSuccess = false; if (g_InputPlugin) { BUTTON Button = m_Button; @@ -68,6 +68,7 @@ void CScanButton::OnTimer(UINT_PTR nIDEvent) } if (Result == CDirectInput::SCAN_SUCCEED || Result == CDirectInput::SCAN_ESCAPE) { + ScanSuccess = Result == CDirectInput::SCAN_SUCCEED; Stop = true; DisplayButton(); } @@ -108,6 +109,7 @@ void CScanButton::OnTimer(UINT_PTR nIDEvent) g_InputPlugin->EndScanDevices(); m_DisplayCtrl.Invalidate(); + m_DisplayCtrl.GetParent().SendMessage(ScanSuccess ? WM_SCAN_SUCCESS : WM_SCAN_CANCELED); } } } @@ -147,7 +149,7 @@ UINT_PTR CALLBACK CScanButton::ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wPara _this->m_ScanBtn.GetWindowRect(&rect); if (PtInRect(&rect, ptCursor)) { - _this->OnScan(); + _this->DetectKey(); } } else if (uMsg == WM_TIMER) diff --git a/Source/Project64-input/wtl-ScanButton.h b/Source/Project64-input/wtl-ScanButton.h index a485fcea2..5f365fbf5 100644 --- a/Source/Project64-input/wtl-ScanButton.h +++ b/Source/Project64-input/wtl-ScanButton.h @@ -10,20 +10,25 @@ class CScanButton }; public: + enum + { + WM_SCAN_SUCCESS = WM_USER + 0x140, + WM_SCAN_CANCELED = WM_USER + 0x141, + }; typedef void(*ChangeCallback)(size_t Data); CScanButton(BUTTON & Button, int DisplayCtrlId, int ScanBtnId); void SubclassWindow(CWindow Wnd); void SetChangeCallback(ChangeCallback callback, size_t callbackdata); + void DetectKey(void); + void DisplayButton(void); private: CScanButton(void); CScanButton(const CScanButton&); CScanButton& operator=(const CScanButton&); - void DisplayButton(void); - void OnScan(void); void OnTimer(UINT_PTR nIDEvent); void MakeOverlay(void); static UINT_PTR CALLBACK ScanButtonProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam); From f2b35fb5b480030cd6c56a9e2ccad17e71795dbb Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 20:40:20 +0930 Subject: [PATCH 18/23] Project64-input: Detect devices changed --- Source/Project64-input/CProject64Input.cpp | 12 +++++++ Source/Project64-input/CProject64Input.h | 1 + Source/Project64-input/DeviceNotification.cpp | 34 +++++++++++++++++++ Source/Project64-input/DeviceNotification.h | 23 +++++++++++++ Source/Project64-input/DirectInput.cpp | 27 ++++++++++++--- Source/Project64-input/DirectInput.h | 5 ++- 6 files changed, 96 insertions(+), 6 deletions(-) create mode 100644 Source/Project64-input/DeviceNotification.cpp create mode 100644 Source/Project64-input/DeviceNotification.h diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index 76aa661ee..aa863958e 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -16,6 +16,15 @@ CProject64Input::~CProject64Input() { } +void CProject64Input::DevicesChanged(void) +{ + CGuard guard(m_CS); + if (m_DirectInput.get() != nullptr) + { + m_DirectInput->DevicesChanged(); + } +} + void CProject64Input::InitiateControllers(CONTROL_INFO * ControlInfo) { CGuard guard(m_CS); @@ -101,10 +110,13 @@ std::wstring CProject64Input::ButtonAssignment(BUTTON & Button) bool CProject64Input::SaveController(uint32_t ControlIndex) { + CGuard guard(m_CS); + if (ControlIndex >= sizeof(m_Controllers) / sizeof(m_Controllers[0])) { return false; } g_Settings->SaveController(ControlIndex, m_ControlInfo.Controls[ControlIndex], m_Controllers[ControlIndex]); + m_DirectInput->MapControllerDevice(m_Controllers[ControlIndex]); return true; } diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index 35749e8c0..ef705c907 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -11,6 +11,7 @@ public: CProject64Input(HINSTANCE hinst); ~CProject64Input(); + void DevicesChanged(void); void InitiateControllers(CONTROL_INFO * ControlInfo); void GetKeys(int32_t Control, BUTTONS * Keys); void StartScanDevices(int32_t DisplayCtrlId); diff --git a/Source/Project64-input/DeviceNotification.cpp b/Source/Project64-input/DeviceNotification.cpp new file mode 100644 index 000000000..6f67e74b4 --- /dev/null +++ b/Source/Project64-input/DeviceNotification.cpp @@ -0,0 +1,34 @@ +#include "DeviceNotification.h" +#include "CProject64Input.h" +#include + +DeviceNotification::DeviceNotification() +{ + Create(NULL); +} + +DeviceNotification::~DeviceNotification() +{ + DestroyWindow(); +} + +int DeviceNotification::OnCreate(LPCREATESTRUCT /*lpCreateStruct*/) +{ + DEV_BROADCAST_DEVICEINTERFACE notificationFilter = { 0 }; + notificationFilter.dbcc_devicetype = DBT_DEVTYP_DEVICEINTERFACE; + notificationFilter.dbcc_size = sizeof(notificationFilter); + + HDEVNOTIFY hDevNotify; + hDevNotify = RegisterDeviceNotification(m_hWnd, ¬ificationFilter, DEVICE_NOTIFY_WINDOW_HANDLE | DEVICE_NOTIFY_ALL_INTERFACE_CLASSES); + + return TRUE; +} + +BOOL DeviceNotification::OnDeviceChange(UINT nEventType, DWORD /*dwData*/) +{ + if (g_InputPlugin != nullptr && (nEventType == DBT_DEVICEARRIVAL || nEventType == DBT_DEVICEREMOVECOMPLETE)) + { + g_InputPlugin->DevicesChanged(); + } + return TRUE; +} diff --git a/Source/Project64-input/DeviceNotification.h b/Source/Project64-input/DeviceNotification.h new file mode 100644 index 000000000..592ba095a --- /dev/null +++ b/Source/Project64-input/DeviceNotification.h @@ -0,0 +1,23 @@ +#pragma once +#include "wtl.h" + +typedef CWinTraits DeviceNotificationTraits; + +class DeviceNotification : + public CWindowImpl +{ +public: + DECLARE_WND_CLASS(_T("My Window Class")) + + BEGIN_MSG_MAP(DeviceNotification) + MSG_WM_CREATE(OnCreate) + MSG_WM_DEVICECHANGE(OnDeviceChange) + END_MSG_MAP() + + DeviceNotification(); + ~DeviceNotification(); + +private: + int OnCreate(LPCREATESTRUCT lpCreateStruct); + BOOL OnDeviceChange(UINT nEventType, DWORD dwData); +}; \ No newline at end of file diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 851b74fd0..21c8a3795 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -1,5 +1,6 @@ #include "DirectInput.h" #include +#include CDirectInput::CDirectInput(HINSTANCE hinst) : m_hDirectInputDLL(nullptr), @@ -25,10 +26,7 @@ CDirectInput::CDirectInput(HINSTANCE hinst) : } } - if (m_pDIHandle != nullptr) - { - m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY); - } + RefreshDeviceList(); } } @@ -101,6 +99,12 @@ BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi) return DIENUM_CONTINUE; } + DEVICE_MAP::iterator itr = m_Devices.find(lpddi->guidInstance); + if (itr != m_Devices.end()) + { + return DIENUM_CONTINUE; + } + DEVICE Device = { 0 }; Device.didHandle = nullptr; Device.dwDevType = lpddi->dwDevType; @@ -207,7 +211,7 @@ std::wstring CDirectInput::ButtonAssignment(BUTTON & Button) return L"Keyboard: ???"; } } - else if (Button.BtnType == BTNTYPE_UNASSIGNED) + if (Button.BtnType == BTNTYPE_UNASSIGNED) { return L""; } @@ -287,6 +291,19 @@ void CDirectInput::UpdateDeviceData(void) } } +void CDirectInput::DevicesChanged(void) +{ + RefreshDeviceList(); +} + +void CDirectInput::RefreshDeviceList(void) +{ + if (m_pDIHandle != nullptr) + { + m_pDIHandle->EnumDevices(DI8DEVCLASS_ALL, stEnumMakeDeviceList, this, DIEDFL_ATTACHEDONLY); + } +} + CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton) { if (didHandle == nullptr) diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index 2e759d44a..1a91beaae 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -1,6 +1,7 @@ #pragma once #include "ControllerSpec1.1.h" #include "Button.h" +#include "DeviceNotification.h" #include "N64Controller.h" #define DIRECTINPUT_VERSION 0x0800 #include @@ -28,6 +29,7 @@ public: bool IsButtonPressed(BUTTON & Button); int8_t AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range); void UpdateDeviceData(void); + void DevicesChanged(void); private: CDirectInput(); @@ -38,7 +40,7 @@ private: BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton); bool AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice); - void LoadConfig(void); + void RefreshDeviceList(void); typedef struct { @@ -63,6 +65,7 @@ private: }; typedef std::map DEVICE_MAP; + DeviceNotification m_DeviceNotification; DEVICE_MAP m_Devices; HMODULE m_hDirectInputDLL; LPDIRECTINPUT8 m_pDIHandle; From 2b049a2a53bfbfbab7c849d9bc897bbc325a3fb2 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 20:42:20 +0930 Subject: [PATCH 19/23] Project64-input: Add Device notification files to project --- Source/Project64-input/Project64-input.vcxproj | 2 ++ Source/Project64-input/Project64-input.vcxproj.filters | 6 ++++++ 2 files changed, 8 insertions(+) diff --git a/Source/Project64-input/Project64-input.vcxproj b/Source/Project64-input/Project64-input.vcxproj index 21e515f1d..693a5a887 100644 --- a/Source/Project64-input/Project64-input.vcxproj +++ b/Source/Project64-input/Project64-input.vcxproj @@ -57,6 +57,7 @@ + @@ -67,6 +68,7 @@ + diff --git a/Source/Project64-input/Project64-input.vcxproj.filters b/Source/Project64-input/Project64-input.vcxproj.filters index 10ea984db..29668a888 100644 --- a/Source/Project64-input/Project64-input.vcxproj.filters +++ b/Source/Project64-input/Project64-input.vcxproj.filters @@ -36,6 +36,9 @@ Source Files + + Source Files + @@ -74,6 +77,9 @@ Header Files + + Header Files + From bdb670f48c6004a2d26baf424ebad833dec0b1ef Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 21:02:48 +0930 Subject: [PATCH 20/23] Project64-input: Add scanning game pad --- Source/Project64-input/CProject64Input.cpp | 3 +- Source/Project64-input/DirectInput.cpp | 325 +++++++++++++++++++-- Source/Project64-input/DirectInput.h | 23 +- 3 files changed, 320 insertions(+), 31 deletions(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index aa863958e..dd2e06ee5 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -72,8 +72,7 @@ void CProject64Input::GetKeys(int32_t Control, BUTTONS * Keys) Keys->U_CBUTTON = m_DirectInput->IsButtonPressed(Controller.U_CBUTTON); Keys->R_TRIG = m_DirectInput->IsButtonPressed(Controller.R_TRIG); Keys->L_TRIG = m_DirectInput->IsButtonPressed(Controller.L_TRIG); - Keys->Y_AXIS = m_DirectInput->AxisPos(Controller.U_ANALOG, Controller.D_ANALOG, Controller.Range); - Keys->X_AXIS = m_DirectInput->AxisPos(Controller.R_ANALOG, Controller.L_ANALOG, Controller.Range); + m_DirectInput->GetAxis(Controller, Keys); } void CProject64Input::StartScanDevices(int32_t DisplayCtrlId) diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 21c8a3795..713afd9cb 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -178,13 +178,9 @@ CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button) { Result = ScanKeyboard(itr->first, device.didHandle, device.State.Keyboard, Button); } - else if (DeviceType == DI8DEVTYPE_MOUSE) + else if (DeviceType != DI8DEVTYPE_MOUSE) { - //dwReturn = ScanMouse(&g_devList[i], lpdwCounter, pButton); - } - else - { - // dwReturn = ScanGamePad(&g_devList[i], lpdwCounter, pButton, i); + Result = ScanGamePad(itr->first, device.didHandle, device.State.Joy, Button); } if (Result != SCAN_FAILED) @@ -197,6 +193,64 @@ CDirectInput::ScanResult CDirectInput::ScanDevices(BUTTON & Button) std::wstring CDirectInput::ButtonAssignment(BUTTON & Button) { + static const char * iGamepad[] = + { + "X-axis", + "Y-axis", + "Z-axis", + "X-rotation", + "Y-rotation", + "Z-rotation", + "Slider", + "Slider", + "PoV", + "PoV", + "PoV", + "PoV", + "Button" + }; + static const char * AxeID[] = + { + " +", + " -", + " /\\", + " >", + " \\/", + " <" + }; + + if (Button.BtnType == BTNTYPE_JOYBUTTON) + { + return stdstr_f("Button %u", Button.Offset).ToUTF16(); + } + if (Button.BtnType == BTNTYPE_JOYAXE) + { + stdstr_f Offset("%u", Button.Offset); + if (Button.Offset < (sizeof(iGamepad) / sizeof(iGamepad[0]))) + { + Offset = iGamepad[Button.Offset]; + } + stdstr_f AxisId(" %u", Button.AxisID); + if (Button.AxisID < (sizeof(AxeID) / sizeof(AxeID[0]))) + { + AxisId = AxeID[Button.AxisID]; + } + return stdstr_f("%s%s", Offset.c_str(), AxisId.c_str()).ToUTF16(); + } + if (Button.BtnType == BTNTYPE_JOYPOV) + { + stdstr_f Offset("%u", Button.Offset); + if (Button.Offset < (sizeof(iGamepad) / sizeof(iGamepad[0]))) + { + Offset = iGamepad[Button.Offset]; + } + stdstr_f AxisId(" %u", Button.AxisID); + if ((Button.AxisID + 2) < (sizeof(AxeID) / sizeof(AxeID[0]))) + { + AxisId = AxeID[Button.AxisID + 2]; + } + return stdstr_f("%s%s", Offset.c_str(), AxisId.c_str()).ToUTF16(); + } if (Button.BtnType == BTNTYPE_KEYBUTTON) { DEVICE_MAP::iterator itr = m_Devices.find(GUID_SysKeyboard); @@ -229,37 +283,110 @@ bool CDirectInput::IsButtonPressed(BUTTON & Button) { case BTNTYPE_KEYBUTTON: return (Device.State.Keyboard[Button.Offset] & 0x80) != 0; + case BTNTYPE_JOYBUTTON: + return (Device.State.Joy.rgbButtons[Button.Offset] & 0x80) != 0; + case BTNTYPE_JOYPOV: + return JoyPadPovPressed((AI_POV)Button.AxisID, ((uint32_t *)&Device.State.Joy)[Button.Offset]); } return false; } -int8_t CDirectInput::AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range) +void CDirectInput::GetAxis(N64CONTROLLER & Controller, BUTTONS * Keys) { - int8_t Pos = 0; - if (PosBtn.Device != nullptr) + enum { - DEVICE & Device = *(DEVICE *)PosBtn.Device; - switch (PosBtn.BtnType) - { - case BTNTYPE_KEYBUTTON: - Pos += (Device.State.Keyboard[PosBtn.Offset] & 0x80) != 0 ? 127 : 0; - } - } - if (NegBtn.Device != nullptr) - { - DEVICE & Device = *(DEVICE *)NegBtn.Device; - switch (NegBtn.BtnType) - { - case BTNTYPE_KEYBUTTON: - Pos -= (Device.State.Keyboard[NegBtn.Offset] & 0x80) != 0 ? 127 : 0; - } - } + N64DIVIDER = 258, + }; - if (Pos != 0) + Keys->X_AXIS = 0; + Keys->Y_AXIS = 0; + + bool b_Value; + long l_Value = 0; + + long lAxisValueX = 0; + long lAxisValueY = 0; + + int bPadDeadZone = 5; + long lDeadZoneValue = bPadDeadZone * RANGE_RELATIVE / 100; + float fDeadZoneRelation = (float)RANGE_RELATIVE / (float)(RANGE_RELATIVE - lDeadZoneValue); + + struct { - Pos = (int8_t)(Pos * (Range / 100.0)); + BUTTON & Button; + bool Negative; } - return Pos; + Buttons[] = + { + { Controller.R_ANALOG, false }, + { Controller.L_ANALOG, true }, + { Controller.D_ANALOG, true }, + { Controller.U_ANALOG, false }, + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + bool fNegInput = Buttons[i].Negative; + BUTTON & btnButton = Buttons[i].Button; + if (btnButton.Device == nullptr) + { + continue; + } + DEVICE & Device = *(DEVICE *)btnButton.Device; + LPLONG plRawState = (LPLONG)&Device.State.Joy; + + switch (btnButton.BtnType) + { + case BTNTYPE_JOYSLIDER: + case BTNTYPE_JOYAXE: + l_Value = (plRawState[btnButton.Offset] - MAX_AXIS_VALUE) * -1; + OutputDebugString(stdstr_f("%d: l_Value: %d\n", i, l_Value).ToUTF16().c_str()); + + if (btnButton.AxisID == AI_AXE_NEGATIVE) + { + fNegInput = !fNegInput; + + b_Value = (l_Value <= -lDeadZoneValue); + if (b_Value) + l_Value = (long)((float)(l_Value + lDeadZoneValue) * fDeadZoneRelation); + } + else + { + b_Value = (l_Value >= lDeadZoneValue); + if (b_Value) + l_Value = (long)((float)(l_Value - lDeadZoneValue) * fDeadZoneRelation); + } + break; + case BTNTYPE_KEYBUTTON: + if ((Device.State.Keyboard[btnButton.Offset] & 0x80) != 0) + { + b_Value = true; + l_Value = MAX_AXIS_VALUE; + } + else + { + b_Value = false; + } + break; + default: + b_Value = false; + } + + if (b_Value) + { + if (fNegInput) + l_Value = -l_Value; + + if (i < 2) + lAxisValueX += l_Value; + else + lAxisValueY += l_Value; + } + } + if (lAxisValueX > MAX_AXIS_VALUE) { lAxisValueX = MAX_AXIS_VALUE; } + if (lAxisValueY > MAX_AXIS_VALUE) { lAxisValueY = MAX_AXIS_VALUE; } + Keys->X_AXIS = lAxisValueX / N64DIVIDER; + Keys->Y_AXIS = lAxisValueY / N64DIVIDER; } void CDirectInput::UpdateDeviceData(void) @@ -343,6 +470,122 @@ CDirectInput::ScanResult CDirectInput::ScanKeyboard(const GUID & DeviceGuid, LPD return SCAN_FAILED; } +CDirectInput::ScanResult CDirectInput::ScanGamePad(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, DIJOYSTATE & BaseState, BUTTON & pButton) +{ + DIJOYSTATE JoyState = { 0 }; + HRESULT hr = didHandle->GetDeviceState(sizeof(DIJOYSTATE), &JoyState); + if (FAILED(hr)) + { + didHandle->Acquire(); + return SCAN_FAILED; + } + + uint32_t JoyPad[][2] = + { + { FIELD_OFFSET(DIJOYSTATE, lX) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, lY) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, lZ) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, lRx) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, lRy) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, lRz) / sizeof(uint32_t), BTNTYPE_JOYAXE }, + { FIELD_OFFSET(DIJOYSTATE, rglSlider[0]) / sizeof(uint32_t), BTNTYPE_JOYSLIDER }, + { FIELD_OFFSET(DIJOYSTATE, rglSlider[1]) / sizeof(uint32_t), BTNTYPE_JOYSLIDER }, + { FIELD_OFFSET(DIJOYSTATE, rgdwPOV[0]) / sizeof(uint32_t), BTNTYPE_JOYPOV }, + { FIELD_OFFSET(DIJOYSTATE, rgdwPOV[1]) / sizeof(uint32_t), BTNTYPE_JOYPOV }, + { FIELD_OFFSET(DIJOYSTATE, rgdwPOV[2]) / sizeof(uint32_t), BTNTYPE_JOYPOV }, + { FIELD_OFFSET(DIJOYSTATE, rgdwPOV[3]) / sizeof(uint32_t), BTNTYPE_JOYPOV } + }; + + uint8_t bAxeDirection = 0; + int32_t foundJoyPad = -1; + for (int32_t i = 0, n = sizeof(JoyPad) / sizeof(JoyPad[0]); i < n; i++) + { + uint32_t lValue = ((int32_t*)&JoyState)[JoyPad[i][0]]; + uint32_t BaseValue = ((int32_t*)&BaseState)[JoyPad[i][0]]; + if (lValue == BaseValue) + { + continue; + } + ((int32_t*)&(BaseState))[JoyPad[i][0]] = lValue; + + if ((JoyPad[i][1] == BTNTYPE_JOYAXE) || (JoyPad[i][1] == BTNTYPE_JOYSLIDER)) + { + enum + { + AXIS_TOP_VALUE = MAX_AXIS_VALUE / 2, + AXIS_BOTTOM_VALUE = MAX_AXIS_VALUE + AXIS_TOP_VALUE, + }; + if (lValue < AXIS_TOP_VALUE && BaseValue >= AXIS_TOP_VALUE) + { + bAxeDirection = AI_AXE_POSITIVE; + foundJoyPad = i; + break; + } + else if (lValue > AXIS_BOTTOM_VALUE && BaseValue <= AXIS_BOTTOM_VALUE) + { + bAxeDirection = AI_AXE_NEGATIVE; + foundJoyPad = i; + break; + } + } + if (JoyPad[i][1] == BTNTYPE_JOYPOV) + { + AI_POV pov[] = + { + AI_POV_UP, + AI_POV_DOWN, + AI_POV_LEFT, + AI_POV_RIGHT, + }; + + for (size_t p = 0; p < (sizeof(pov) / sizeof(pov[0])); p++) + { + if (JoyPadPovPressed(pov[p], lValue) && !JoyPadPovPressed(pov[p], BaseValue)) + { + bAxeDirection = (uint8_t)pov[p]; + foundJoyPad = i; + break; + } + } + if (foundJoyPad >= 0) + { + break; + } + } + } + + if (foundJoyPad >= 0) + { + pButton.Offset = (uint8_t)JoyPad[foundJoyPad][0]; + pButton.AxisID = (uint8_t)bAxeDirection; + pButton.BtnType = (BtnType)JoyPad[foundJoyPad][1]; + pButton.DeviceGuid = DeviceGuid; + pButton.Device = nullptr; + return SCAN_SUCCEED; + } + + for (uint8_t i = 0, n = sizeof(JoyState.rgbButtons) / sizeof(JoyState.rgbButtons[0]); i < n; i++) + { + if (BaseState.rgbButtons[i] == JoyState.rgbButtons[i]) + { + continue; + } + BaseState.rgbButtons[i] = JoyState.rgbButtons[i]; + + if ((JoyState.rgbButtons[i] & 0x80) == 0) + { + continue; + } + pButton.Offset = i; + pButton.AxisID = 0; + pButton.BtnType = BTNTYPE_JOYBUTTON; + pButton.DeviceGuid = DeviceGuid; + pButton.Device = nullptr; + return SCAN_SUCCEED; + } + return SCAN_FAILED; +} + bool CDirectInput::AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice) { HRESULT hResult = lpDirectInputDevice->Acquire(); @@ -364,3 +607,29 @@ bool CDirectInput::AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice) } return false; } + +bool CDirectInput::JoyPadPovPressed(AI_POV Pov, int32_t Angle) +{ + enum + { + POV_ANGLE_THRESH = 5675 + }; + + if (LOWORD(Angle) == 0xFFFF) + { + return false; + } + + switch (Pov) + { + case AI_POV_UP: + return ((Angle >= 36000 - POV_ANGLE_THRESH) || (Angle <= 0 + POV_ANGLE_THRESH)); + case AI_POV_RIGHT: + return ((Angle >= 9000 - POV_ANGLE_THRESH) && (Angle <= 9000 + POV_ANGLE_THRESH)); + case AI_POV_DOWN: + return ((Angle >= 18000 - POV_ANGLE_THRESH) && (Angle <= 18000 + POV_ANGLE_THRESH)); + case AI_POV_LEFT: + return ((Angle >= 27000 - POV_ANGLE_THRESH) && (Angle <= 27000 + POV_ANGLE_THRESH)); + } + return false; +} diff --git a/Source/Project64-input/DirectInput.h b/Source/Project64-input/DirectInput.h index 1a91beaae..966af4e39 100644 --- a/Source/Project64-input/DirectInput.h +++ b/Source/Project64-input/DirectInput.h @@ -11,6 +11,25 @@ class CDirectInput { + enum + { + CONFIG_THRESHOLD = 50, + MAX_AXIS_VALUE = 0x7FFF, + RANGE_RELATIVE = 0x8000, + AI_AXE_POSITIVE = 0, + AI_AXE_NEGATIVE = 1, + THRESHOLD = 50, + ABS_THRESHOLD = (RANGE_RELATIVE * THRESHOLD / 100) + }; + + enum AI_POV + { + AI_POV_UP = 0, + AI_POV_RIGHT = 1, + AI_POV_DOWN = 2, + AI_POV_LEFT = 3, + }; + public: enum ScanResult { @@ -27,7 +46,7 @@ public: ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); bool IsButtonPressed(BUTTON & Button); - int8_t AxisPos(BUTTON & PosBtn, BUTTON & NegBtn, uint8_t Range); + void GetAxis(N64CONTROLLER & Controller, BUTTONS * Keys); void UpdateDeviceData(void); void DevicesChanged(void); @@ -39,8 +58,10 @@ private: static BOOL CALLBACK stEnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi, LPVOID pvRef); BOOL EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi); ScanResult ScanKeyboard(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, uint8_t * KeyboardState, BUTTON & pButton); + ScanResult ScanGamePad(const GUID & DeviceGuid, LPDIRECTINPUTDEVICE8 didHandle, DIJOYSTATE & BaseState, BUTTON & pButton); bool AcquireDevice(LPDIRECTINPUTDEVICE8 lpDirectInputDevice); void RefreshDeviceList(void); + bool JoyPadPovPressed(AI_POV Pov, int32_t Angle); typedef struct { From 22adc2e782c8b6c66c6494ac07f0d34125a2b195 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 21:08:48 +0930 Subject: [PATCH 21/23] Project64-input: Add reset button --- Source/Project64-input/CProject64Input.cpp | 13 +++++ Source/Project64-input/CProject64Input.h | 1 + Source/Project64-input/InputConfigUI.cpp | 55 ++++++++++++++++------ Source/Project64-input/InputSettings.cpp | 37 +++++++++++++++ Source/Project64-input/InputSettings.h | 1 + 5 files changed, 92 insertions(+), 15 deletions(-) diff --git a/Source/Project64-input/CProject64Input.cpp b/Source/Project64-input/CProject64Input.cpp index dd2e06ee5..b694f05f6 100644 --- a/Source/Project64-input/CProject64Input.cpp +++ b/Source/Project64-input/CProject64Input.cpp @@ -119,3 +119,16 @@ bool CProject64Input::SaveController(uint32_t ControlIndex) m_DirectInput->MapControllerDevice(m_Controllers[ControlIndex]); return true; } + +bool CProject64Input::ResetController(uint32_t ControlIndex) +{ + CGuard guard(m_CS); + + if (ControlIndex >= sizeof(m_Controllers) / sizeof(m_Controllers[0])) + { + return false; + } + g_Settings->ResetController(ControlIndex, m_ControlInfo.Controls[ControlIndex], m_Controllers[ControlIndex]); + m_DirectInput->MapControllerDevice(m_Controllers[ControlIndex]); + return true; +} diff --git a/Source/Project64-input/CProject64Input.h b/Source/Project64-input/CProject64Input.h index ef705c907..02541839e 100644 --- a/Source/Project64-input/CProject64Input.h +++ b/Source/Project64-input/CProject64Input.h @@ -19,6 +19,7 @@ public: CDirectInput::ScanResult ScanDevices(BUTTON & Button); std::wstring ButtonAssignment(BUTTON & Button); bool SaveController(uint32_t ControlIndex); + bool ResetController(uint32_t ControlIndex); inline HINSTANCE hInst(void) const { return m_hinst; } inline bool IsScanning(void) const { return m_Scanning; } diff --git a/Source/Project64-input/InputConfigUI.cpp b/Source/Project64-input/InputConfigUI.cpp index 2507ecc55..525ce7901 100644 --- a/Source/Project64-input/InputConfigUI.cpp +++ b/Source/Project64-input/InputConfigUI.cpp @@ -20,6 +20,7 @@ public: BEGIN_MSG_MAP(CControllerSettings) MSG_WM_INITDIALOG(OnInitDialog) MSG_WM_CTLCOLORSTATIC(OnCtlColorStatic) + COMMAND_HANDLER_EX(IDC_BTN_DEFAULTS, BN_CLICKED, DefaultBtnClicked) COMMAND_HANDLER_EX(IDC_BTN_SETUP, BN_CLICKED, SetupBtnClicked) COMMAND_HANDLER_EX(IDC_CHK_PLUGGED_IN, BN_CLICKED, ItemChanged) COMMAND_HANDLER_EX(IDC_CMB_DEVICE, CBN_SELCHANGE, ItemChanged) @@ -39,9 +40,11 @@ private: LRESULT OnScroll(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnScanSuccess(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); LRESULT OnScanCanceled(UINT uMsg, WPARAM wParam, LPARAM lParam, BOOL& bHandled); + void DefaultBtnClicked(UINT Code, int id, HWND ctl); void SetupBtnClicked(UINT Code, int id, HWND ctl); void ItemChanged(UINT Code, int id, HWND ctl); LRESULT ItemChangedNotify(NMHDR* /*pNMHDR*/); + void DisplayController(void); void ButtonChannged(void); static void stButtonChanged(size_t data) { ((CControllerSettings *)data)->ButtonChannged(); } @@ -89,32 +92,17 @@ CControllerSettings::CControllerSettings(uint32_t ControllerNumber) : BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/) { - N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); - CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); - GetDlgItem(IDC_BTN_DEFAULTS).EnableWindow(false); GetDlgItem(IDC_BTN_LOAD).EnableWindow(false); GetDlgItem(IDC_BTN_SAVE).EnableWindow(false); m_Range.Attach(GetDlgItem(IDC_SLIDER_RANGE)); m_Range.SetTicFreq(1); m_Range.SetRangeMin(1); m_Range.SetRangeMax(100); - m_Range.SetPos(Controller.Range); - CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); m_PluggedIn.Attach(GetDlgItem(IDC_CHK_PLUGGED_IN)); - m_PluggedIn.SetCheck(ControlInfo.Present != 0 ? BST_CHECKED : BST_UNCHECKED); m_cmbDevice.Attach(GetDlgItem(IDC_CMB_DEVICE)); m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"None"), PLUGIN_NONE); m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"Mem Pak"), PLUGIN_MEMPAK); m_cmbDevice.SetItemData(m_cmbDevice.AddString(L"Rumble Pak"), PLUGIN_RUMBLE_PAK); - m_cmbDevice.SetCurSel(0); - for (DWORD i = 0, n = m_cmbDevice.GetCount(); i < n; i++) - { - if (m_cmbDevice.GetItemData(i) == (DWORD)ControlInfo.Plugin) - { - m_cmbDevice.SetCurSel(i); - break; - } - } m_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER)); m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER)); @@ -130,6 +118,7 @@ BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam Buttons[i]->SubclassWindow(m_hWnd); Buttons[i]->SetChangeCallback(stButtonChanged, (size_t)this); } + DisplayController(); return TRUE; } @@ -196,6 +185,13 @@ LRESULT CControllerSettings::OnScanCanceled(UINT /*uMsg*/, WPARAM /*wParam*/, LP return 0; } +void CControllerSettings::DefaultBtnClicked(UINT Code, int id, HWND ctl) +{ + g_InputPlugin->ResetController(m_ControllerNumber); + DisplayController(); + SendMessage(GetParent(), PSM_CHANGED, (WPARAM)m_hWnd, 0); +} + void CControllerSettings::SetupBtnClicked(UINT /*Code*/, int /*id*/, HWND /*ctl*/) { m_SetupIndex = 0; @@ -213,6 +209,35 @@ LRESULT CControllerSettings::ItemChangedNotify(NMHDR* /*pNMHDR*/) return 0; } +void CControllerSettings::DisplayController(void) +{ + N64CONTROLLER & Controller = g_InputPlugin->Controllers(m_ControllerNumber); + CONTROL & ControlInfo = g_InputPlugin->ControlInfo(m_ControllerNumber); + m_cmbDevice.SetCurSel(0); + for (DWORD i = 0, n = m_cmbDevice.GetCount(); i < n; i++) + { + if (m_cmbDevice.GetItemData(i) == (DWORD)ControlInfo.Plugin) + { + m_cmbDevice.SetCurSel(i); + break; + } + } + m_PluggedIn.SetCheck(ControlInfo.Present != 0 ? BST_CHECKED : BST_UNCHECKED); + m_Range.SetPos(Controller.Range); + CWindow(GetDlgItem(IDC_LABEL_RANGE)).SetWindowText(stdstr_f("%d%%", m_Range.GetPos()).ToUTF16().c_str()); + CScanButton * Buttons[] = { + &m_ButtonUDPad, &m_ButtonDDPad, &m_ButtonLDPad, &m_ButtonRDPad, &m_ButtonA, &m_ButtonB, + &m_ButtonCUp, &m_ButtonCDown, &m_ButtonCLeft, &m_ButtonCRight, &m_ButtonStart, + &m_ButtonZtrigger, &m_ButtonRTrigger, &m_ButtonLTrigger, + &m_ButtonAnalogU, &m_ButtonAnalogD, &m_ButtonAnalogL, &m_ButtonAnalogR + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + Buttons[i]->DisplayButton(); + } +} + void CControllerSettings::ButtonChannged(void) { CPropertySheetWindow(GetParent()).SetModified(m_hWnd); diff --git a/Source/Project64-input/InputSettings.cpp b/Source/Project64-input/InputSettings.cpp index 0ce9413a9..7928210f2 100644 --- a/Source/Project64-input/InputSettings.cpp +++ b/Source/Project64-input/InputSettings.cpp @@ -121,6 +121,43 @@ void CInputSettings::SaveController(uint32_t ControlIndex, const CONTROL & Contr FlushSettings(); } +void CInputSettings::ResetController(uint32_t ControlIndex, CONTROL & ControllerInfo, N64CONTROLLER & Controller) +{ + struct { + const BUTTON & Button; + InputSettingID SettingId; + uint32_t ControlIndex; + } + Buttons[] = + { + { Controller.U_DPAD, Set_Control0_U_DPAD, 0 }, + { Controller.D_DPAD, Set_Control0_D_DPAD, 0 }, + { Controller.L_DPAD, Set_Control0_L_DPAD, 0 }, + { Controller.R_DPAD, Set_Control0_R_DPAD, 0 }, + { Controller.A_BUTTON, Set_Control0_A_BUTTON, 0 }, + { Controller.B_BUTTON, Set_Control0_B_BUTTON, 0 }, + { Controller.U_CBUTTON, Set_Control0_U_CBUTTON, 0 }, + { Controller.D_CBUTTON, Set_Control0_D_CBUTTON, 0 }, + { Controller.L_CBUTTON, Set_Control0_L_CBUTTON, 0 }, + { Controller.R_CBUTTON, Set_Control0_R_CBUTTON, 0 }, + { Controller.START_BUTTON, Set_Control0_START_BUTTON, 0 }, + { Controller.Z_TRIG, Set_Control0_Z_TRIG, 0 }, + { Controller.R_TRIG, Set_Control0_R_TRIG, 0 }, + { Controller.L_TRIG, Set_Control0_L_TRIG, 0 }, + { Controller.U_ANALOG, Set_Control0_U_ANALOG, 0 }, + { Controller.D_ANALOG, Set_Control0_D_ANALOG, 0 }, + { Controller.L_ANALOG, Set_Control0_L_ANALOG, 0 }, + { Controller.R_ANALOG, Set_Control0_R_ANALOG, 0 }, + }; + + for (size_t i = 0, n = sizeof(Buttons) / sizeof(Buttons[0]); i < n; i++) + { + SetSettingSz((short)Buttons[i].SettingId, NULL); + } + FlushSettings(); + LoadController(ControlIndex, ControllerInfo, Controller); +} + BUTTON CInputSettings::StrToButton(const char * Buffer) { BUTTON Button = { 0 }; diff --git a/Source/Project64-input/InputSettings.h b/Source/Project64-input/InputSettings.h index d727a85e8..87985af10 100644 --- a/Source/Project64-input/InputSettings.h +++ b/Source/Project64-input/InputSettings.h @@ -12,6 +12,7 @@ public: void LoadController(uint32_t ControlIndex, CONTROL & ControllerInfo, N64CONTROLLER & Controller); void SaveController(uint32_t ControlIndex, const CONTROL & ControllerInfo, const N64CONTROLLER & Controller); + void ResetController(uint32_t ControlIndex, CONTROL & ControllerInfo, N64CONTROLLER & Controller); private: CInputSettings(const CInputSettings&); From f7315801cb25bde2239f7d05ce840e99f0e69d91 Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 21:09:32 +0930 Subject: [PATCH 22/23] Project64-input: Set the version as 1.0 --- Source/Project64-input/Version.h.in | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Source/Project64-input/Version.h.in b/Source/Project64-input/Version.h.in index 14087d707..e26272109 100644 --- a/Source/Project64-input/Version.h.in +++ b/Source/Project64-input/Version.h.in @@ -11,8 +11,8 @@ #define STRINGIZE2(s) #s #define STRINGIZE(s) STRINGIZE2(s) -#define VERSION_MAJOR 0 -#define VERSION_MINOR 1 +#define VERSION_MAJOR 1 +#define VERSION_MINOR 0 #define VERSION_REVISION 0 #define VERSION_BUILD 9999 #define GIT_VERSION "" From eef13e78d341c96f70c7c7bb1bea572cb1c4a93d Mon Sep 17 00:00:00 2001 From: zilmar Date: Wed, 15 Jul 2020 21:13:53 +0930 Subject: [PATCH 23/23] Project64-input: remove debug string --- Source/Project64-input/DirectInput.cpp | 1 - 1 file changed, 1 deletion(-) diff --git a/Source/Project64-input/DirectInput.cpp b/Source/Project64-input/DirectInput.cpp index 713afd9cb..ad9c8828d 100644 --- a/Source/Project64-input/DirectInput.cpp +++ b/Source/Project64-input/DirectInput.cpp @@ -340,7 +340,6 @@ void CDirectInput::GetAxis(N64CONTROLLER & Controller, BUTTONS * Keys) case BTNTYPE_JOYSLIDER: case BTNTYPE_JOYAXE: l_Value = (plRawState[btnButton.Offset] - MAX_AXIS_VALUE) * -1; - OutputDebugString(stdstr_f("%d: l_Value: %d\n", i, l_Value).ToUTF16().c_str()); if (btnButton.AxisID == AI_AXE_NEGATIVE) {