commit
ac45d34b29
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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)
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<PluginType>(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
|
||||
|
|
|
@ -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)))
|
||||
{
|
||||
|
|
|
@ -0,0 +1,30 @@
|
|||
#pragma once
|
||||
#include <Common\stdtypes.h>
|
||||
#include <guiddef.h>
|
||||
|
||||
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 _BUTTON
|
||||
{
|
||||
uint8_t Offset;
|
||||
uint8_t AxisID;
|
||||
BtnType BtnType;
|
||||
GUID DeviceGuid;
|
||||
void * Device;
|
||||
} BUTTON;
|
|
@ -0,0 +1,134 @@
|
|||
#include "CProject64Input.h"
|
||||
#include "InputSettings.h"
|
||||
|
||||
CProject64Input * g_InputPlugin = nullptr;
|
||||
|
||||
CProject64Input::CProject64Input(HINSTANCE hinst) :
|
||||
m_hinst(hinst),
|
||||
m_Scanning(false),
|
||||
m_DisplayCtrlId(0),
|
||||
m_iFirstController(-1)
|
||||
{
|
||||
memset(m_Controllers, 0, sizeof(m_Controllers));
|
||||
}
|
||||
|
||||
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);
|
||||
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;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
m_DirectInput->GetAxis(Controller, Keys);
|
||||
}
|
||||
|
||||
void CProject64Input::StartScanDevices(int32_t DisplayCtrlId)
|
||||
{
|
||||
m_Scanning = true;
|
||||
m_DisplayCtrlId = DisplayCtrlId;
|
||||
m_DirectInput->UpdateDeviceData();
|
||||
}
|
||||
|
||||
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";
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,45 @@
|
|||
#pragma once
|
||||
#include "ControllerSpec1.1.h"
|
||||
#include "DirectInput.h"
|
||||
#include "N64Controller.h"
|
||||
#include <Common\CriticalSection.h>
|
||||
#include <memory>
|
||||
|
||||
class CProject64Input
|
||||
{
|
||||
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);
|
||||
void EndScanDevices(void);
|
||||
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; }
|
||||
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();
|
||||
CProject64Input(const CProject64Input&);
|
||||
CProject64Input& operator=(const CProject64Input&);
|
||||
|
||||
CriticalSection m_CS;
|
||||
CONTROL_INFO m_ControlInfo;
|
||||
N64CONTROLLER m_Controllers[4];
|
||||
std::unique_ptr<CDirectInput> m_DirectInput;
|
||||
HINSTANCE m_hinst;
|
||||
bool m_Scanning;
|
||||
int32_t m_DisplayCtrlId;
|
||||
int32_t m_iFirstController;
|
||||
};
|
||||
|
||||
extern CProject64Input * g_InputPlugin;
|
Binary file not shown.
After Width: | Height: | Size: 83 KiB |
|
@ -0,0 +1,224 @@
|
|||
/**********************************************************************************
|
||||
Project64 Controller plugin spec, version #1.1
|
||||
**********************************************************************************/
|
||||
#pragma once
|
||||
|
||||
#include <Common/stdtypes.h>
|
||||
|
||||
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 X_AXIS : 8;
|
||||
|
||||
signed Y_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);
|
||||
|
|
@ -0,0 +1,34 @@
|
|||
#include "DeviceNotification.h"
|
||||
#include "CProject64Input.h"
|
||||
#include <dbt.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,23 @@
|
|||
#pragma once
|
||||
#include "wtl.h"
|
||||
|
||||
typedef CWinTraits<WS_OVERLAPPED, WS_EX_APPWINDOW> DeviceNotificationTraits;
|
||||
|
||||
class DeviceNotification :
|
||||
public CWindowImpl<DeviceNotification, CWindow, DeviceNotificationTraits>
|
||||
{
|
||||
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);
|
||||
};
|
|
@ -0,0 +1,634 @@
|
|||
#include "DirectInput.h"
|
||||
#include <Common\StdString.h>
|
||||
#include <Common\SyncEvent.h>
|
||||
|
||||
CDirectInput::CDirectInput(HINSTANCE hinst) :
|
||||
m_hDirectInputDLL(nullptr),
|
||||
m_pDIHandle(nullptr),
|
||||
m_hinst(hinst),
|
||||
m_hWnd(nullptr)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
RefreshDeviceList();
|
||||
}
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
BOOL CDirectInput::EnumMakeDeviceList(LPCDIDEVICEINSTANCE lpddi)
|
||||
{
|
||||
uint32_t DeviceType = GET_DIDEVICE_TYPE(lpddi->dwDevType);
|
||||
if (DeviceType == DI8DEVTYPE_DEVICE)
|
||||
{
|
||||
// ignore generic devices
|
||||
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;
|
||||
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<DEVICE_MAP::iterator, bool> 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(itr->first, device.didHandle, device.State.Keyboard, Button);
|
||||
}
|
||||
else if (DeviceType != DI8DEVTYPE_MOUSE)
|
||||
{
|
||||
Result = ScanGamePad(itr->first, device.didHandle, device.State.Joy, Button);
|
||||
}
|
||||
|
||||
if (Result != SCAN_FAILED)
|
||||
{
|
||||
return Result;
|
||||
}
|
||||
}
|
||||
return Result;
|
||||
}
|
||||
|
||||
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);
|
||||
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: ???";
|
||||
}
|
||||
}
|
||||
if (Button.BtnType == BTNTYPE_UNASSIGNED)
|
||||
{
|
||||
return L"";
|
||||
}
|
||||
return L"Unknown";
|
||||
}
|
||||
|
||||
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;
|
||||
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;
|
||||
}
|
||||
|
||||
void CDirectInput::GetAxis(N64CONTROLLER & Controller, BUTTONS * Keys)
|
||||
{
|
||||
enum
|
||||
{
|
||||
N64DIVIDER = 258,
|
||||
};
|
||||
|
||||
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
|
||||
{
|
||||
BUTTON & Button;
|
||||
bool Negative;
|
||||
}
|
||||
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;
|
||||
|
||||
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)
|
||||
{
|
||||
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);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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)
|
||||
{
|
||||
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 (KeyboardState[i] == cKeys[i])
|
||||
{
|
||||
continue;
|
||||
}
|
||||
KeyboardState[i] = cKeys[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;
|
||||
pButton.DeviceGuid = DeviceGuid;
|
||||
pButton.Device = nullptr;
|
||||
return SCAN_SUCCEED;
|
||||
}
|
||||
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();
|
||||
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;
|
||||
}
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,95 @@
|
|||
#pragma once
|
||||
#include "ControllerSpec1.1.h"
|
||||
#include "Button.h"
|
||||
#include "DeviceNotification.h"
|
||||
#include "N64Controller.h"
|
||||
#define DIRECTINPUT_VERSION 0x0800
|
||||
#include <Windows.h>
|
||||
#include <dinput.h>
|
||||
#include <string>
|
||||
#include <map>
|
||||
|
||||
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
|
||||
{
|
||||
SCAN_FAILED = 0x00,
|
||||
SCAN_SUCCEED = 0x01,
|
||||
SCAN_ESCAPE = 0x10,
|
||||
};
|
||||
|
||||
CDirectInput(HINSTANCE hinst);
|
||||
~CDirectInput();
|
||||
|
||||
void Initiate(CONTROL_INFO * ControlInfo);
|
||||
void MapControllerDevice(N64CONTROLLER & Controller);
|
||||
ScanResult ScanDevices(BUTTON & Button);
|
||||
std::wstring ButtonAssignment(BUTTON & Button);
|
||||
bool IsButtonPressed(BUTTON & Button);
|
||||
void GetAxis(N64CONTROLLER & Controller, BUTTONS * Keys);
|
||||
void UpdateDeviceData(void);
|
||||
void DevicesChanged(void);
|
||||
|
||||
private:
|
||||
CDirectInput();
|
||||
CDirectInput(const CDirectInput&);
|
||||
CDirectInput& operator=(const CDirectInput&);
|
||||
|
||||
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
|
||||
{
|
||||
LPDIRECTINPUTDEVICE8 didHandle;
|
||||
uint32_t dwDevType;
|
||||
std::string InstanceName;
|
||||
std::string ProductName;
|
||||
union INPUTSTATE
|
||||
{
|
||||
DIJOYSTATE Joy;
|
||||
DIMOUSESTATE2 Mouse;
|
||||
uint8_t Keyboard[256];
|
||||
} State;
|
||||
} DEVICE;
|
||||
|
||||
struct GUIDComparer
|
||||
{
|
||||
bool operator()(const GUID & Left, const GUID & Right) const
|
||||
{
|
||||
return memcmp(&Left, &Right, sizeof(Right)) < 0;
|
||||
}
|
||||
};
|
||||
typedef std::map<GUID, DEVICE, GUIDComparer> DEVICE_MAP;
|
||||
|
||||
DeviceNotification m_DeviceNotification;
|
||||
DEVICE_MAP m_Devices;
|
||||
HMODULE m_hDirectInputDLL;
|
||||
LPDIRECTINPUT8 m_pDIHandle;
|
||||
HINSTANCE m_hinst;
|
||||
HWND m_hWnd;
|
||||
};
|
|
@ -0,0 +1,284 @@
|
|||
#include "InputConfigUI.h"
|
||||
#include "CProject64Input.h"
|
||||
#include "wtl.h"
|
||||
#include "wtl-BitmapPicture.h"
|
||||
#include "wtl-ScanButton.h"
|
||||
#include <Common\stdtypes.h>
|
||||
#include <Common\StdString.h>
|
||||
#include "resource.h"
|
||||
|
||||
class CControllerSettings :
|
||||
public CPropertyPageImpl<CControllerSettings>
|
||||
{
|
||||
enum
|
||||
{
|
||||
DETECT_KEY_TIMER = 1
|
||||
};
|
||||
public:
|
||||
enum { IDD = IDD_Controller };
|
||||
|
||||
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)
|
||||
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<CControllerSettings>)
|
||||
END_MSG_MAP()
|
||||
|
||||
CControllerSettings(uint32_t ControllerNumber);
|
||||
BOOL OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/);
|
||||
HBRUSH OnCtlColorStatic(CDCHandle dc, CWindow wndStatic);
|
||||
bool OnApply();
|
||||
|
||||
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(); }
|
||||
|
||||
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;
|
||||
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),
|
||||
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),
|
||||
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());
|
||||
}
|
||||
|
||||
BOOL CControllerSettings::OnInitDialog(CWindow /*wndFocus*/, LPARAM /*lInitParam*/)
|
||||
{
|
||||
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_PluggedIn.Attach(GetDlgItem(IDC_CHK_PLUGGED_IN));
|
||||
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_ControllerImg.SubclassWindow(GetDlgItem(IDC_BMP_CONTROLLER));
|
||||
m_ControllerImg.SetBitmap(MAKEINTRESOURCE(IDB_CONTROLLER));
|
||||
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]->SubclassWindow(m_hWnd);
|
||||
Buttons[i]->SetChangeCallback(stButtonChanged, (size_t)this);
|
||||
}
|
||||
DisplayController();
|
||||
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);
|
||||
}
|
||||
|
||||
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;
|
||||
ControlInfo.Plugin = m_cmbDevice.GetItemData(m_cmbDevice.GetCurSel());
|
||||
|
||||
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::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::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;
|
||||
m_ButtonUDPad.DetectKey();
|
||||
}
|
||||
|
||||
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);
|
||||
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);
|
||||
}
|
||||
|
||||
class CInputConfigUI:
|
||||
public CPropertySheetImpl<CInputConfigUI>
|
||||
{
|
||||
public:
|
||||
CInputConfigUI();
|
||||
~CInputConfigUI();
|
||||
|
||||
void OnSheetInitialized();
|
||||
|
||||
private:
|
||||
CControllerSettings m_pgController0, m_pgController1, m_pgController2, m_pgController3;
|
||||
};
|
||||
|
||||
void ConfigInput(void * hParent)
|
||||
{
|
||||
CInputConfigUI().DoModal((HWND)hParent);
|
||||
}
|
||||
|
||||
CInputConfigUI::CInputConfigUI() :
|
||||
m_pgController0(0),
|
||||
m_pgController1(1),
|
||||
m_pgController2(2),
|
||||
m_pgController3(3)
|
||||
{
|
||||
m_psh.pszCaption = L"Configure Input";
|
||||
AddPage(&m_pgController0.m_psp);
|
||||
AddPage(&m_pgController1.m_psp);
|
||||
AddPage(&m_pgController2.m_psp);
|
||||
AddPage(&m_pgController3.m_psp);
|
||||
}
|
||||
|
||||
CInputConfigUI::~CInputConfigUI()
|
||||
{
|
||||
}
|
||||
|
||||
void CInputConfigUI::OnSheetInitialized()
|
||||
{
|
||||
ModifyStyleEx(WS_EX_CONTEXTHELP,0);
|
||||
}
|
|
@ -0,0 +1,3 @@
|
|||
#pragma once
|
||||
|
||||
void ConfigInput(void * hParent);
|
|
@ -0,0 +1,213 @@
|
|||
/****************************************************************************
|
||||
* *
|
||||
* 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 "InputConfigUI.h"
|
||||
#include "Version.h"
|
||||
#include "CProject64Input.h"
|
||||
#include "InputSettings.h"
|
||||
#include <stdio.h>
|
||||
|
||||
/******************************************************************
|
||||
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)
|
||||
{
|
||||
CleanupInputSettings();
|
||||
}
|
||||
|
||||
/******************************************************************
|
||||
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
|
||||
*******************************************************************/
|
||||
#ifdef _WIN32
|
||||
EXPORT void CALL DllConfig(void * hParent)
|
||||
{
|
||||
ConfigInput(hParent);
|
||||
}
|
||||
#endif
|
||||
|
||||
/******************************************************************
|
||||
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)
|
||||
{
|
||||
g_InputPlugin->GetKeys(Control, 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)
|
||||
{
|
||||
if (g_InputPlugin != nullptr)
|
||||
{
|
||||
g_InputPlugin->InitiateControllers(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*/)
|
||||
{
|
||||
}
|
||||
|
||||
EXPORT void CALL PluginLoaded(void)
|
||||
{
|
||||
SetupInputSettings();
|
||||
}
|
||||
|
||||
#include <Windows.h>
|
||||
|
||||
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;
|
||||
}
|
|
@ -0,0 +1,240 @@
|
|||
#include <Settings/Settings.h>
|
||||
#include <Common\StdString.h>
|
||||
#include "InputSettingsID.h"
|
||||
#include "InputSettings.h"
|
||||
|
||||
CInputSettings * g_Settings = nullptr;
|
||||
|
||||
CInputSettings::CInputSettings()
|
||||
{
|
||||
RegisterSettings();
|
||||
}
|
||||
|
||||
CInputSettings::~CInputSettings()
|
||||
{
|
||||
}
|
||||
|
||||
void CInputSettings::LoadController(uint32_t ControlIndex, CONTROL & ControllerInfo, 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])));
|
||||
}
|
||||
|
||||
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; }
|
||||
}
|
||||
|
||||
void CInputSettings::SaveController(uint32_t ControlIndex, const CONTROL & ControllerInfo, 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());
|
||||
}
|
||||
|
||||
InputSettingID PresentSettings[] = { Set_Control0_Present };
|
||||
if (ControlIndex < (sizeof(PresentSettings) / sizeof(PresentSettings[0])))
|
||||
{
|
||||
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])))
|
||||
{
|
||||
SetSetting((short)RangeSettings[ControlIndex], Controller.Range);
|
||||
}
|
||||
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 };
|
||||
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_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");
|
||||
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 <Windows.h>
|
||||
#endif
|
||||
|
||||
extern "C" void UseUnregisteredSetting(int /*SettingID*/)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
DebugBreak();
|
||||
#endif
|
||||
}
|
|
@ -0,0 +1,31 @@
|
|||
#pragma once
|
||||
#include <Common\stdtypes.h>
|
||||
#include <string>
|
||||
#include "N64Controller.h"
|
||||
#include "ControllerSpec1.1.h"
|
||||
|
||||
class CInputSettings
|
||||
{
|
||||
public:
|
||||
CInputSettings();
|
||||
~CInputSettings();
|
||||
|
||||
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&);
|
||||
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);
|
|
@ -0,0 +1,26 @@
|
|||
#pragma once
|
||||
|
||||
enum InputSettingID
|
||||
{
|
||||
Set_Control0_Present,
|
||||
Set_Control0_Plugin,
|
||||
Set_Control0_Range,
|
||||
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,
|
||||
};
|
|
@ -0,0 +1,25 @@
|
|||
#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;
|
||||
BUTTON U_ANALOG;
|
||||
BUTTON D_ANALOG;
|
||||
BUTTON L_ANALOG;
|
||||
BUTTON R_ANALOG;
|
||||
uint8_t Range;
|
||||
} N64CONTROLLER;
|
Binary file not shown.
|
@ -0,0 +1,101 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup Label="ProjectConfigurations">
|
||||
<ProjectConfiguration Include="Debug|Win32">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Debug|x64">
|
||||
<Configuration>Debug</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|Win32">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>Win32</Platform>
|
||||
</ProjectConfiguration>
|
||||
<ProjectConfiguration Include="Release|x64">
|
||||
<Configuration>Release</Configuration>
|
||||
<Platform>x64</Platform>
|
||||
</ProjectConfiguration>
|
||||
</ItemGroup>
|
||||
<PropertyGroup Label="Globals">
|
||||
<ProjectGuid>{D3F979CE-8FA7-48C9-A2B3-A33594B48536}</ProjectGuid>
|
||||
<Keyword>Win32Proj</Keyword>
|
||||
<RootNamespace>Project64input</RootNamespace>
|
||||
</PropertyGroup>
|
||||
<PropertyGroup Label="Configuration">
|
||||
<ConfigurationType>DynamicLibrary</ConfigurationType>
|
||||
</PropertyGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
|
||||
<ImportGroup Label="PropertySheets">
|
||||
<Import Project="$(SolutionDir)PropertySheets\Platform.$(Configuration).props" />
|
||||
</ImportGroup>
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
|
||||
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
|
||||
<PropertyGroup>
|
||||
<TargetName>Project64-Input</TargetName>
|
||||
<TargetName Condition="'$(Configuration)'=='Debug'">Project64-Input_d</TargetName>
|
||||
<OutDir>$(SolutionDir)Plugin\Input\</OutDir>
|
||||
<OutDir Condition="'$(Platform)'=='x64'">$(SolutionDir)Plugin64\Input\</OutDir>
|
||||
</PropertyGroup>
|
||||
<ItemDefinitionGroup>
|
||||
<ClCompile>
|
||||
<PrecompiledHeader>NotUsing</PrecompiledHeader>
|
||||
</ClCompile>
|
||||
<PreBuildEvent>
|
||||
<Command>"$(SolutionDir)Source\Script\UpdateVersion.cmd" "$(Configuration)" "$(Platform)" "$(SolutionDir)Source\Project64-input\Version.h.in" "$(SolutionDir)Source\Project64-input\Version.h"</Command>
|
||||
</PreBuildEvent>
|
||||
<Link>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">dinput8.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">$(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
<Link>
|
||||
<AdditionalDependencies Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">dinput8.lib;dxguid.lib;%(AdditionalDependencies)</AdditionalDependencies>
|
||||
<AdditionalLibraryDirectories Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">$(Root)Source\3rdParty\directx\lib;%(AdditionalLibraryDirectories)</AdditionalLibraryDirectories>
|
||||
<ImageHasSafeExceptionHandlers Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">false</ImageHasSafeExceptionHandlers>
|
||||
</Link>
|
||||
</ItemDefinitionGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="DeviceNotification.cpp" />
|
||||
<ClCompile Include="DirectInput.cpp" />
|
||||
<ClCompile Include="InputConfigUI.cpp" />
|
||||
<ClCompile Include="InputMain.cpp" />
|
||||
<ClCompile Include="CProject64Input.cpp" />
|
||||
<ClCompile Include="InputSettings.cpp" />
|
||||
<ClCompile Include="wtl-BitmapPicture.cpp" />
|
||||
<ClCompile Include="wtl-ScanButton.cpp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="Button.h" />
|
||||
<ClInclude Include="DeviceNotification.h" />
|
||||
<ClInclude Include="InputSettings.h" />
|
||||
<ClInclude Include="InputSettingsID.h" />
|
||||
<ClInclude Include="N64Controller.h" />
|
||||
<ClInclude Include="DirectInput.h" />
|
||||
<ClInclude Include="InputConfigUI.h" />
|
||||
<ClInclude Include="ControllerSpec1.1.h" />
|
||||
<ClInclude Include="CProject64Input.h" />
|
||||
<ClInclude Include="resource.h" />
|
||||
<ClInclude Include="wtl-BitmapPicture.h" />
|
||||
<ClInclude Include="wtl-ScanButton.h" />
|
||||
<ClInclude Include="wtl.h" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Version.h.in" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Project64-input.rc" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Controller.bmp" />
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ProjectReference Include="..\Common\Common.vcxproj">
|
||||
<Project>{b4a4b994-9111-42b1-93c2-6f1ca8bc4421}</Project>
|
||||
</ProjectReference>
|
||||
<ProjectReference Include="..\Settings\Settings.vcxproj">
|
||||
<Project>{8b9961b1-88d9-4ea3-a752-507a00dd9f3d}</Project>
|
||||
</ProjectReference>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -0,0 +1,99 @@
|
|||
<?xml version="1.0" encoding="utf-8"?>
|
||||
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
|
||||
<ItemGroup>
|
||||
<Filter Include="Source Files">
|
||||
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
|
||||
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Header Files">
|
||||
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
|
||||
<Extensions>h;hh;hpp;hxx;hm;inl;inc;xsd</Extensions>
|
||||
</Filter>
|
||||
<Filter Include="Resource Files">
|
||||
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
|
||||
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
|
||||
</Filter>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClCompile Include="InputMain.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputConfigUI.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wtl-BitmapPicture.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="CProject64Input.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DirectInput.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="wtl-ScanButton.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="InputSettings.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
<ClCompile Include="DeviceNotification.cpp">
|
||||
<Filter>Source Files</Filter>
|
||||
</ClCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ClInclude Include="ControllerSpec1.1.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="resource.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InputConfigUI.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wtl-BitmapPicture.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wtl.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="CProject64Input.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DirectInput.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="wtl-ScanButton.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="Button.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="N64Controller.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InputSettings.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="InputSettingsID.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
<ClInclude Include="DeviceNotification.h">
|
||||
<Filter>Header Files</Filter>
|
||||
</ClInclude>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<None Include="Version.h.in">
|
||||
<Filter>Header Files</Filter>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<ResourceCompile Include="Project64-input.rc">
|
||||
<Filter>Resource Files</Filter>
|
||||
</ResourceCompile>
|
||||
</ItemGroup>
|
||||
<ItemGroup>
|
||||
<Image Include="Controller.bmp">
|
||||
<Filter>Resource Files</Filter>
|
||||
</Image>
|
||||
</ItemGroup>
|
||||
</Project>
|
|
@ -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
|
Binary file not shown.
|
@ -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);
|
||||
}
|
|
@ -0,0 +1,34 @@
|
|||
#pragma once
|
||||
#include "wtl.h"
|
||||
#include <string>
|
||||
|
||||
class CBitmapPicture :
|
||||
public CWindowImpl <CBitmapPicture>
|
||||
{
|
||||
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;
|
||||
};
|
|
@ -0,0 +1,185 @@
|
|||
#include "wtl-ScanButton.h"
|
||||
#include "CProject64Input.h"
|
||||
#include <Common\StdString.h>
|
||||
#include <time.h>
|
||||
|
||||
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),
|
||||
m_ChangeCallback(nullptr),
|
||||
m_ChangeCallbackData(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::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());
|
||||
}
|
||||
|
||||
void CScanButton::DetectKey(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, ScanSuccess = false;
|
||||
if (g_InputPlugin)
|
||||
{
|
||||
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)
|
||||
{
|
||||
ScanSuccess = 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");
|
||||
|
||||
if (m_Overlay.m_hWnd != NULL)
|
||||
{
|
||||
m_Overlay.DestroyWindow();
|
||||
m_Overlay = NULL;
|
||||
}
|
||||
|
||||
g_InputPlugin->EndScanDevices();
|
||||
m_DisplayCtrl.Invalidate();
|
||||
m_DisplayCtrl.GetParent().SendMessage(ScanSuccess ? WM_SCAN_SUCCESS : WM_SCAN_CANCELED);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
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);
|
||||
#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)
|
||||
{
|
||||
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->DetectKey();
|
||||
}
|
||||
}
|
||||
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_KEYDOWN || msg == WM_KEYUP)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
if (msg == WM_PAINT)
|
||||
{
|
||||
PAINTSTRUCT ps;
|
||||
BeginPaint(hwnd, &ps);
|
||||
EndPaint(hwnd, &ps);
|
||||
return 0;
|
||||
}
|
||||
return DefWindowProc(hwnd, msg, wParam, lParam);
|
||||
}
|
|
@ -0,0 +1,47 @@
|
|||
#pragma once
|
||||
#include "wtl.h"
|
||||
#include "Button.h"
|
||||
|
||||
class CScanButton
|
||||
{
|
||||
enum
|
||||
{
|
||||
DETECT_KEY_TIMER = 1
|
||||
};
|
||||
|
||||
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 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;
|
||||
ChangeCallback m_ChangeCallback;
|
||||
size_t m_ChangeCallbackData;
|
||||
};
|
|
@ -0,0 +1,16 @@
|
|||
#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 <atlbase.h>
|
||||
#include <WTL/atlapp.h>
|
||||
#include <WTL/atldlgs.h>
|
||||
#include <WTL/atlmisc.h>
|
||||
#include <WTL/atlctrls.h>
|
||||
#include <WTL/atlcrack.h>
|
||||
#pragma warning(pop)
|
|
@ -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;
|
||||
|
||||
|
|
Loading…
Reference in New Issue