Allow mouse options to be changed at runtime

This commit is contained in:
ergo720 2020-09-19 12:37:55 +02:00
parent 1ea6c5485e
commit 6e265244cf
16 changed files with 306 additions and 94 deletions

View File

@ -52,6 +52,6 @@ typedef enum class _IPC_UPDATE_KERNEL {
, CONFIG_INPUT_SYNC
} IPC_UPDATE_KERNEL;
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const unsigned int value, const unsigned int hwnd);
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd);
#endif

View File

@ -62,8 +62,9 @@ uint16_t g_LibVersion_DSOUND = 0;
// * 5: (ergo720), added new input gui settings and revision to core
// * 6: (RadWolfie), added loader executable member to core, only for clean up loader expertimental setting
// * 7: (RadWolfie), fix allowAdminPrivilege not align with other boolean members
// * 8: (ergo720), added general input settings
///////////////////////////
const unsigned int settings_version = 7;
const unsigned int settings_version = 8;
Settings* g_Settings = nullptr;
@ -125,15 +126,21 @@ static struct {
const char* adapter_name = "adapter_name";
} sect_network_keys;
static const char *section_input_general = "input-general";
static struct {
const char *mo_axis_range = "MouseAxisRange";
const char *mo_wheel_range = "MouseWheelRange";
} sect_input_general;
static const char* section_controller_dinput = "controller-dinput";
static const char* section_controller_port = "controller-port";
static const char* section_input = "input-port-";
static const char* section_input_port = "input-port-";
static struct {
const char* type = "Type";
const char* device = "DeviceName";
const char* config = "ProfileName";
} sect_input;
} sect_input_port;
static const char* section_input_profiles = "input-profile-";
static struct {
@ -366,6 +373,10 @@ bool Settings::LoadConfig()
// ==== Core End ============
// Delete/update legacy configs from previous revisions
RemoveLegacyConfigs(m_core.Revision);
m_core.Revision = settings_version;
// ==== Hack Begin ==========
m_hacks.DisablePixelShaders = m_si.GetBoolValue(section_hack, sect_hack_keys.DisablePixelShaders, /*Default=*/false);
@ -435,21 +446,28 @@ bool Settings::LoadConfig()
// ==== Network End =========
// ==== Input Begin ====
// ==== Input General Begin ====
m_input_general.MoAxisRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_axis_range, MO_AXIS_DEFAULT_RANGE);
m_input_general.MoWheelRange = m_si.GetLongValue(section_input_general, sect_input_general.mo_wheel_range, MO_WHEEL_DEFAULT_RANGE);
// ==== Input General End ==============
// ==== Input Port Begin ====
for (int port_num = 0; port_num < 4; port_num++) {
std::string current_section = std::string(section_input) + std::to_string(port_num);
int ret = m_si.GetLongValue(current_section.c_str(), sect_input.type, -2);
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
int ret = m_si.GetLongValue(current_section.c_str(), sect_input_port.type, -2);
if (ret == -2) {
m_input[port_num].Type = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
m_input_port[port_num].Type = to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID);
continue;
}
m_input[port_num].Type = ret;
m_input[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input.device);
m_input[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input.config));
m_input_port[port_num].Type = ret;
m_input_port[port_num].DeviceName = m_si.GetValue(current_section.c_str(), sect_input_port.device);
m_input_port[port_num].ProfileName = TrimQuoteFromString(m_si.GetValue(current_section.c_str(), sect_input_port.config));
}
// ==== Input End ==============
// ==== Input Port End ==============
// ==== Input Profile Begin ====
std::array<std::vector<std::string>, to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX)> control_names;
@ -488,10 +506,6 @@ bool Settings::LoadConfig()
// ==== Input Profile End ======
// Delete legacy configs from previous revisions
RemoveLegacyConfigs(m_core.Revision);
m_core.Revision = settings_version;
return true;
}
@ -582,18 +596,25 @@ bool Settings::Save(std::string file_path)
// ==== Network End =========
// ==== Input Begin ====
// ==== Input General Begin =======
m_si.SetLongValue(section_input_general, sect_input_general.mo_axis_range, m_input_general.MoAxisRange, nullptr, false, true);
m_si.SetLongValue(section_input_general, sect_input_general.mo_wheel_range, m_input_general.MoWheelRange, nullptr, false, true);
// ==== Input General End =========
// ==== Input Port Begin ====
for (int port_num = 0; port_num < 4; port_num++) {
std::string current_section = std::string(section_input) + std::to_string(port_num);
std::string quoted_prf_str = m_input[port_num].ProfileName.insert(0, "\"");
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
std::string quoted_prf_str = m_input_port[port_num].ProfileName.insert(0, "\"");
quoted_prf_str += "\"";
m_si.SetLongValue(current_section.c_str(), sect_input.type, m_input[port_num].Type, nullptr, false, true);
m_si.SetValue(current_section.c_str(), sect_input.device, m_input[port_num].DeviceName.c_str(), nullptr, true);
m_si.SetValue(current_section.c_str(), sect_input.config, quoted_prf_str.c_str(), nullptr, true);
m_si.SetLongValue(current_section.c_str(), sect_input_port.type, m_input_port[port_num].Type, nullptr, false, true);
m_si.SetValue(current_section.c_str(), sect_input_port.device, m_input_port[port_num].DeviceName.c_str(), nullptr, true);
m_si.SetValue(current_section.c_str(), sect_input_port.config, quoted_prf_str.c_str(), nullptr, true);
}
// ==== Input End ==============
// ==== Input Port End ==============
// ==== Input Profile Begin ====
@ -693,19 +714,19 @@ void Settings::SyncToEmulator()
// register input settings
for (int i = 0; i < 4; i++) {
g_EmuShared->SetInputDevTypeSettings(&m_input[i].Type, i);
if (m_input[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
g_EmuShared->SetInputDevNameSettings(m_input[i].DeviceName.c_str(), i);
auto it = std::find_if(m_input_profiles[m_input[i].Type].begin(),
m_input_profiles[m_input[i].Type].end(), [this, i](const auto& profile) {
if (profile.ProfileName == m_input[i].ProfileName) {
g_EmuShared->SetInputDevTypeSettings(&m_input_port[i].Type, i);
if (m_input_port[i].Type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
g_EmuShared->SetInputDevNameSettings(m_input_port[i].DeviceName.c_str(), i);
auto it = std::find_if(m_input_profiles[m_input_port[i].Type].begin(),
m_input_profiles[m_input_port[i].Type].end(), [this, i](const auto& profile) {
if (profile.ProfileName == m_input_port[i].ProfileName) {
return true;
}
return false;
});
if (it != m_input_profiles[m_input[i].Type].end()) {
if (it != m_input_profiles[m_input_port[i].Type].end()) {
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
for (int index = 0; index < dev_num_buttons[m_input[i].Type]; index++) {
for (int index = 0; index < dev_num_buttons[m_input_port[i].Type]; index++) {
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
}
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, i);
@ -713,6 +734,9 @@ void Settings::SyncToEmulator()
}
}
g_EmuShared->SetInputMoAxisSettings(m_input_general.MoAxisRange);
g_EmuShared->SetInputMoWheelSettings(m_input_general.MoWheelRange);
// register Hacks settings
g_EmuShared->SetHackSettings(&m_hacks);
@ -893,4 +917,38 @@ void Settings::RemoveLegacyConfigs(unsigned int CurrentRevision)
default:
break;
}
if (CurrentRevision < 8) {
const std::string kb_str = "Keyboard";
for (unsigned port_num = 0; port_num < 4; ++port_num) {
std::string current_section = std::string(section_input_port) + std::to_string(port_num);
std::string device_name = m_si.GetValue(current_section.c_str(), sect_input_port.device);
// NOTE: with C++20, this can be simplified by simply calling device_name.ends_with()
if (device_name.length() >= kb_str.length()) {
if (device_name.compare(device_name.length() - kb_str.length(), kb_str.length(), kb_str) == 0) {
device_name += "Mouse";
m_si.SetValue(current_section.c_str(), sect_input_port.device, device_name.c_str(), nullptr, true);
}
}
}
for (unsigned index = 0; ; ++index) {
std::string current_section = std::string(section_input_profiles) + std::to_string(index);
if (m_si.GetSectionSize(current_section.c_str()) == -1) {
break;
}
std::string device_name = m_si.GetValue(current_section.c_str(), sect_input_profiles.device);
// NOTE: with C++20, this can be simplified by simply calling device_name.ends_with()
if (device_name.length() >= kb_str.length()) {
if (device_name.compare(device_name.length() - kb_str.length(), kb_str.length(), kb_str) == 0) {
device_name += "Mouse";
m_si.SetValue(current_section.c_str(), sect_input_profiles.device, device_name.c_str(), nullptr, true);
}
}
}
}
}

View File

@ -134,12 +134,18 @@ public:
} m_audio;
static_assert(sizeof(s_audio) == 0x4C, assert_check_shared_memory(s_audio));
struct s_input {
struct s_input_general {
long MoAxisRange;
long MoWheelRange;
};
s_input_general m_input_general;
struct s_input_port {
int Type;
std::string DeviceName;
std::string ProfileName;
};
std::array<s_input, 4> m_input;
std::array<s_input_port, 4> m_input_port;
struct s_input_profiles {
int Type;

View File

@ -51,8 +51,6 @@ namespace DInput
#include "DInputKeyboardCodes.h"
};
bool bKbMoEnumerated = false;
void InitKeyboardMouse(IDirectInput8* idi8)
{
// From Dolphin: "mouse and keyboard are a combined device, to allow shift+click and stuff
@ -136,8 +134,8 @@ namespace DInput
const LONG &ax = (&m_state_in.mouse.lX)[i];
// each axis gets a negative and a positive input instance associated with it
AddInput(new Axis(i, ax, (2 == i) ? -10 : -80));
AddInput(new Axis(i, ax, -(2 == i) ? 10 : 80));
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_neg : mo_axis_range_neg));
AddInput(new Axis(i, ax, (2 == i) ? mo_wheel_range_pos : mo_axis_range_pos));
}
}

View File

@ -34,7 +34,11 @@
namespace DInput
{
extern bool bKbMoEnumerated;
inline bool bKbMoEnumerated = false;
inline LONG mo_axis_range_pos = 0;
inline LONG mo_axis_range_neg = 0;
inline LONG mo_wheel_range_pos = 0;
inline LONG mo_wheel_range_neg = 0;
void GetDeviceChanges();
void PopulateDevices();
@ -76,13 +80,13 @@ namespace DInput
class Axis : public Input
{
public:
Axis(uint8_t index, const LONG &axis, LONG range) : m_axis(axis), m_range(range), m_index(index) {}
Axis(uint8_t index, const LONG &axis, const LONG &range) : m_axis(axis), m_range(range), m_index(index) {}
std::string GetName() const override;
ControlState GetState() const override;
private:
const LONG &m_axis;
const LONG m_range;
const LONG &m_range;
const uint8_t m_index;
};

View File

@ -48,6 +48,8 @@
#define DIRECTION_IN 0
#define DIRECTION_OUT 1
#define MO_AXIS_DEFAULT_RANGE 10l
#define MO_WHEEL_DEFAULT_RANGE 80l
typedef double ControlState;

View File

@ -78,9 +78,9 @@ void InputDeviceManager::Initialize(bool is_gui)
std::unique_lock<std::mutex> lck(m_Mtx);
m_bPendingShutdown = false;
m_PollingThread = std::thread([this]() {
m_PollingThread = std::thread([this, is_gui]() {
XInput::Init(m_Mtx);
Sdl::Init(m_Mtx, m_Cv);
Sdl::Init(m_Mtx, m_Cv, is_gui);
});
m_Cv.wait(lck, []() {
@ -93,6 +93,7 @@ void InputDeviceManager::Initialize(bool is_gui)
CxbxKrnlCleanup("Failed to initialize input subsystem! Consult debug log for more information");
}
UpdateOpt(is_gui);
RefreshDevices();
if (!is_gui) {
@ -519,3 +520,22 @@ std::shared_ptr<InputDevice> InputDeviceManager::FindDevice(int usb_port, int du
return nullptr;
}
}
void InputDeviceManager::UpdateOpt(bool is_gui)
{
if (!is_gui) {
long axis_range, wheel_range;
g_EmuShared->GetInputMoAxisSettings(&axis_range);
g_EmuShared->GetInputMoWheelSettings(&wheel_range);
DInput::mo_axis_range_pos = axis_range;
DInput::mo_wheel_range_pos = wheel_range;
DInput::mo_axis_range_neg = -(axis_range);
DInput::mo_wheel_range_neg = -(wheel_range);
}
else {
DInput::mo_axis_range_pos = g_Settings->m_input_general.MoAxisRange;
DInput::mo_wheel_range_pos = g_Settings->m_input_general.MoWheelRange;
DInput::mo_axis_range_neg = -(g_Settings->m_input_general.MoAxisRange);
DInput::mo_wheel_range_neg = -(g_Settings->m_input_general.MoWheelRange);
}
}

View File

@ -82,6 +82,8 @@ public:
std::shared_ptr<InputDevice> FindDevice(int usb_port, int dummy) const;
// attach/detach guest devices to the emulated machine
void UpdateDevices(int port, bool ack);
// update input options
void UpdateOpt(bool is_gui);
private:

View File

@ -337,8 +337,8 @@ void InputWindow::LoadProfile(const std::string& name)
for (int index = 0; index < m_max_num_buttons; index++) {
m_DeviceConfig->FindButtonByIndex(index)->UpdateText(profile->ControlList[index].c_str());
}
g_Settings->m_input[m_port_num].DeviceName = profile->DeviceName;
g_Settings->m_input[m_port_num].ProfileName = profile->ProfileName;
g_Settings->m_input_port[m_port_num].DeviceName = profile->DeviceName;
g_Settings->m_input_port[m_port_num].ProfileName = profile->ProfileName;
m_bHasChanges = false;
}
@ -364,8 +364,8 @@ bool InputWindow::SaveProfile(const std::string& name)
}
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
reinterpret_cast<LPARAM>(profile.ProfileName.c_str())), 0);
g_Settings->m_input[m_port_num].DeviceName = profile.DeviceName;
g_Settings->m_input[m_port_num].ProfileName = profile.ProfileName;
g_Settings->m_input_port[m_port_num].DeviceName = profile.DeviceName;
g_Settings->m_input_port[m_port_num].ProfileName = profile.ProfileName;
g_Settings->m_input_profiles[m_dev_type].push_back(std::move(profile));
m_bHasChanges = false;
return true;
@ -379,16 +379,16 @@ void InputWindow::DeleteProfile(const std::string& name)
}
SendMessage(m_hwnd_profile_list, CB_DELETESTRING, SendMessage(m_hwnd_profile_list, CB_FINDSTRINGEXACT, 1,
reinterpret_cast<LPARAM>(profile->ProfileName.c_str())), 0);
if (profile->ProfileName == g_Settings->m_input[m_port_num].ProfileName) {
if (profile->ProfileName == g_Settings->m_input_port[m_port_num].ProfileName) {
SendMessage(m_hwnd_profile_list, CB_SETCURSEL, -1, 0);
UpdateCurrentDevice();
ClearBindings();
g_Settings->m_input[m_port_num].DeviceName = "";
g_Settings->m_input[m_port_num].ProfileName = "";
g_Settings->m_input_port[m_port_num].DeviceName = "";
g_Settings->m_input_port[m_port_num].ProfileName = "";
m_bHasChanges = false;
}
else {
LoadProfile(g_Settings->m_input[m_port_num].ProfileName);
LoadProfile(g_Settings->m_input_port[m_port_num].ProfileName);
}
g_Settings->m_input_profiles[m_dev_type].erase(profile);
}
@ -411,7 +411,7 @@ void InputWindow::LoadDefaultProfile()
SendMessage(m_hwnd_profile_list, CB_ADDSTRING, 0,
reinterpret_cast<LPARAM>(g_Settings->m_input_profiles[m_dev_type][index].ProfileName.c_str()));
}
LoadProfile(g_Settings->m_input[m_port_num].ProfileName);
LoadProfile(g_Settings->m_input_port[m_port_num].ProfileName);
}
void InputWindow::UpdateCurrentDevice()

View File

@ -57,7 +57,7 @@ namespace Sdl
int SdlInitStatus = SDL_NOT_INIT;
bool SdlPopulateOK = false;
void Init(std::mutex& Mtx, std::condition_variable& Cv)
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui)
{
SDL_Event Event;
uint32_t CustomEvent_t;
@ -155,9 +155,15 @@ namespace Sdl
break;
}
else if (Event.type == UpdateInputEvent_t) {
XInput::GetDeviceChanges();
DInput::GetDeviceChanges();
g_InputDeviceManager.UpdateDevices(*static_cast<int*>(Event.user.data1), false);
if ((*static_cast<int *>(Event.user.data1)) == PORT_INVALID) {
g_InputDeviceManager.UpdateOpt(is_gui);
}
else {
XInput::GetDeviceChanges();
DInput::GetDeviceChanges();
g_InputDeviceManager.UpdateDevices(*static_cast<int *>(Event.user.data1), false);
}
delete Event.user.data1;
Event.user.data1 = nullptr;
}

View File

@ -51,7 +51,7 @@ namespace Sdl
extern bool SdlPopulateOK;
// initialize SDL
void Init(std::mutex& Mtx, std::condition_variable& Cv);
void Init(std::mutex& Mtx, std::condition_variable& Cv, bool is_gui);
// shutdown SDL
void DeInit(std::thread& Thr);
// open the sdl joystick with the specified index

View File

@ -149,6 +149,14 @@ class EmuShared : public Mutex
Unlock();
}
// ******************************************************************
// * Input option Accessors
// ******************************************************************
void GetInputMoAxisSettings(long *axis) { Lock(); *axis = m_MoAxisRange; Unlock(); }
void SetInputMoAxisSettings(const long axis) { Lock(); m_MoAxisRange = axis; Unlock(); }
void GetInputMoWheelSettings(long *wheel) { Lock(); *wheel = m_MoWheelRange; Unlock(); }
void SetInputMoWheelSettings(const long wheel) { Lock(); m_MoWheelRange = wheel; Unlock(); }
// ******************************************************************
// * LLE Flags Accessors
// ******************************************************************
@ -291,7 +299,9 @@ class EmuShared : public Mutex
int m_DeviceType[4];
char m_DeviceControlNames[4][XBOX_CTRL_NUM_BUTTONS][30]; // macro should be num of buttons of dev with highest num buttons
char m_DeviceName[4][50];
int m_Reserved99[28]; // Reserve space
long m_MoAxisRange;
long m_MoWheelRange;
int m_Reserved99[26]; // Reserve space
// Settings class in memory should not be tampered by third-party.
// Third-party program should only be allow to edit settings.ini file.

View File

@ -76,7 +76,7 @@ void ipc_send_gui_update(IPC_UPDATE_GUI command, const unsigned int value)
}
}
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const unsigned int value, const unsigned int hwnd)
void ipc_send_kernel_update(IPC_UPDATE_KERNEL command, const int value, const unsigned int hwnd)
{
// Don't send if GUI process didn't create kernel process.
if (hwnd == NULL) {

View File

@ -37,35 +37,45 @@
// Windows dialog procedure for the input menu
static INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPARAM lParam);
// Window procedure of the subclass
LRESULT CALLBACK EditControlSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam, LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData);
HWND g_ChildWnd = NULL;
static bool g_bHasOptChanges = false;
void SyncInputSettings(int port_num, int dev_type)
void SyncInputSettings(int port_num, int dev_type, bool is_opt)
{
if (g_ChildWnd) {
// Sync updated input to kernel process to use run-time settings.
g_EmuShared->SetInputDevTypeSettings(&g_Settings->m_input[port_num].Type, port_num);
if (!is_opt) {
// Sync updated input to kernel process to use run-time settings.
g_EmuShared->SetInputDevTypeSettings(&g_Settings->m_input_port[port_num].Type, port_num);
if (dev_type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
std::string dev_name = g_Settings->m_input[port_num].DeviceName;
std::string profile_name = g_Settings->m_input[port_num].ProfileName;
if (dev_type != to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
std::string dev_name = g_Settings->m_input_port[port_num].DeviceName;
std::string profile_name = g_Settings->m_input_port[port_num].ProfileName;
g_EmuShared->SetInputDevNameSettings(dev_name.c_str(), port_num);
auto it = std::find_if(g_Settings->m_input_profiles[dev_type].begin(),
g_Settings->m_input_profiles[dev_type].end(), [&profile_name](const auto& profile) {
if (profile.ProfileName == profile_name) {
return true;
g_EmuShared->SetInputDevNameSettings(dev_name.c_str(), port_num);
auto it = std::find_if(g_Settings->m_input_profiles[dev_type].begin(),
g_Settings->m_input_profiles[dev_type].end(), [&profile_name](const auto &profile) {
if (profile.ProfileName == profile_name) {
return true;
}
return false;
});
if (it != g_Settings->m_input_profiles[dev_type].end()) {
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
for (int index = 0; index < dev_num_buttons[dev_type]; index++) {
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
}
return false;
});
if (it != g_Settings->m_input_profiles[dev_type].end()) {
char controls_name[XBOX_CTRL_NUM_BUTTONS][30];
for (int index = 0; index < dev_num_buttons[dev_type]; index++) {
strncpy(controls_name[index], it->ControlList[index].c_str(), 30);
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, port_num);
}
g_EmuShared->SetInputBindingsSettings(controls_name, XBOX_CTRL_NUM_BUTTONS, port_num);
}
}
else {
g_EmuShared->SetInputMoAxisSettings(g_Settings->m_input_general.MoAxisRange);
g_EmuShared->SetInputMoWheelSettings(g_Settings->m_input_general.MoWheelRange);
port_num = PORT_INVALID;
}
#if 0 // lle usb
ipc_send_kernel_update(IPC_UPDATE_KERNEL::CONFIG_INPUT_SYNC, PORT_DEC(Gui2XboxPortArray[port_num]),
reinterpret_cast<std::uintptr_t>(g_ChildWnd));
@ -75,6 +85,15 @@ void SyncInputSettings(int port_num, int dev_type)
}
}
void UpdateInputOpt(HWND hwnd)
{
char buffer[30];
SendMessage(GetDlgItem(hwnd, IDC_MOUSE_RANGE), WM_GETTEXT, 30, reinterpret_cast<LPARAM>(buffer));
g_Settings->m_input_general.MoAxisRange = std::stol(buffer);
SendMessage(GetDlgItem(hwnd, IDC_WHEEL_RANGE), WM_GETTEXT, 30, reinterpret_cast<LPARAM>(buffer));
g_Settings->m_input_general.MoWheelRange = std::stol(buffer);
}
void ShowInputConfig(HWND hwnd, HWND ChildWnd)
{
g_InputDeviceManager.Initialize(true);
@ -90,20 +109,18 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
{
case WM_INITDIALOG:
{
HWND hHandle;
// Set window icon
SetClassLong(hWndDlg, GCL_HICON, (LONG)LoadIcon(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDI_CXBX)));
for (int i = 0, j = 0; i != 4; i++) {
hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + i);
HWND hHandle = GetDlgItem(hWndDlg, IDC_DEVICE_PORT1 + i);
for (auto str : { "None", "MS Controller Duke", "MS Controller S" }) {
LRESULT index = SendMessage(hHandle, CB_ADDSTRING, 0, reinterpret_cast<LPARAM>(str));
SendMessage(hHandle, CB_SETITEMDATA, index,
to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j);
if (g_Settings->m_input[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j) {
if (g_Settings->m_input_port[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID) + j) {
SendMessage(hHandle, CB_SETCURSEL, index, 0);
if (g_Settings->m_input[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
if (g_Settings->m_input_port[i].Type == to_underlying(XBOX_INPUT_DEVICE::DEVICE_INVALID)) {
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + i), FALSE);
}
}
@ -111,11 +128,28 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
}
j = 0;
}
for (auto i : { IDC_MOUSE_RANGE, IDC_WHEEL_RANGE }) {
HWND hEditControlArray = GetDlgItem(hWndDlg, i);
SetWindowSubclass(hEditControlArray, EditControlSubclassProc, i, 0);
SendMessage(hEditControlArray, EM_SETLIMITTEXT, 6, 0);
SendMessage(hEditControlArray, WM_SETTEXT, 0, reinterpret_cast<LPARAM>((i == IDC_MOUSE_RANGE) ?
std::to_string(g_Settings->m_input_general.MoAxisRange).c_str() :
std::to_string(g_Settings->m_input_general.MoWheelRange).c_str()));
}
// Reset option changes flag
g_bHasOptChanges = false;
}
break;
case WM_CLOSE:
{
if (g_bHasOptChanges) {
UpdateInputOpt(hWndDlg);
SyncInputSettings(0, 0, true);
}
g_InputDeviceManager.Shutdown();
g_ChildWnd = NULL;
EndDialog(hWndDlg, wParam);
@ -144,6 +178,11 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
{
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_DUKE):
case to_underlying(XBOX_INPUT_DEVICE::MS_CONTROLLER_S): {
if (g_bHasOptChanges) {
UpdateInputOpt(hWndDlg);
g_InputDeviceManager.UpdateOpt(true);
}
DialogBoxParam(GetModuleHandle(nullptr), MAKEINTRESOURCE(IDD_XID_DUKE_CFG), hWndDlg, DlgXidControllerConfigProc,
(DeviceType << 8) | port);
}
@ -156,7 +195,7 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
DeviceType < to_underlying(XBOX_INPUT_DEVICE::DEVICE_MAX));
// Also inform the kernel process if it exists
SyncInputSettings(port, DeviceType);
SyncInputSettings(port, DeviceType, false);
}
}
break;
@ -183,16 +222,66 @@ INT_PTR CALLBACK DlgInputConfigProc(HWND hWndDlg, UINT uMsg, WPARAM wParam, LPAR
EnableWindow(GetDlgItem(hWndDlg, IDC_CONFIGURE_PORT1 + port), TRUE);
}
g_Settings->m_input[port].Type = dev_type;
g_Settings->m_input_port[port].Type = dev_type;
// Also inform the kernel process if it exists
SyncInputSettings(port, dev_type);
SyncInputSettings(port, dev_type, false);
}
}
break;
case IDC_MOUSE_RANGE:
case IDC_WHEEL_RANGE:
{
if (HIWORD(wParam) == EN_CHANGE) {
g_bHasOptChanges = true;
}
}
}
}
break;
}
return FALSE;
}
LRESULT CALLBACK EditControlSubclassProc(HWND hWnd, UINT uMsg, WPARAM wParam,
LPARAM lParam, UINT_PTR uIdSubclass, DWORD_PTR dwRefData)
{
switch (uMsg)
{
// Remove the window subclass when this window is destroyed
case WM_NCDESTROY:
RemoveWindowSubclass(hWnd, EditControlSubclassProc, uIdSubclass);
break;
// Override the default system behaviour and process WM_CHAR ourselves
case WM_GETDLGCODE:
if (lParam) {
LPMSG lpmsg = reinterpret_cast<LPMSG>(lParam);
if (lpmsg->message == WM_CHAR) {
return DLGC_WANTCHARS;
}
}
break;
case WM_CHAR:
{
// Make sure we only allow decimal numbers and some special keys to delete characters
if (!((wParam >= '0' && wParam <= '9')
|| wParam == VK_CANCEL
|| wParam == VK_CLEAR
|| wParam == VK_DELETE
|| wParam == VK_BACK))
{
return FALSE;
}
}
break;
// Don't allow pasting operations, they can be used to bypass the filtering done in WM_CHAR
case WM_PASTE:
return FALSE;
}
return DefSubclassProc(hWnd, uMsg, wParam, lParam);
}

View File

@ -27,6 +27,10 @@ LANGUAGE LANG_NEUTRAL, SUBLANG_NEUTRAL
#ifdef APSTUDIO_INVOKED
GUIDELINES DESIGNINFO
BEGIN
IDD_INPUT_CFG, DIALOG
BEGIN
END
IDD_VIRTUAL_SBC_FEEDBACK, DIALOG
BEGIN
LEFTMARGIN, 7
@ -83,7 +87,7 @@ END
// Dialog
//
IDD_INPUT_CFG DIALOGEX 0, 0, 243, 124
IDD_INPUT_CFG DIALOGEX 0, 0, 243, 175
STYLE DS_SETFONT | DS_MODALFRAME | DS_CENTER | WS_POPUP | WS_CAPTION | WS_SYSMENU
CAPTION "Cxbx-Reloaded : Input Configuration"
FONT 8, "Verdana", 0, 0, 0x1
@ -101,6 +105,11 @@ BEGIN
LTEXT "Port 2",IDC_STATIC,23,48,20,10
LTEXT "Port 3",IDC_STATIC,23,69,20,10
LTEXT "Port 4",IDC_STATIC,23,90,20,10
GROUPBOX "Options",IDC_INPUT_OPTIONS,13,119,217,49,WS_GROUP,WS_EX_CLIENTEDGE
EDITTEXT IDC_MOUSE_RANGE,95,129,121,14
EDITTEXT IDC_WHEEL_RANGE,95,147,121,14
LTEXT "Mouse axis range",IDC_STATIC,23,129,69,14,SS_CENTERIMAGE
LTEXT "Mouse wheel range",IDC_STATIC,23,146,68,14,SS_CENTERIMAGE
END
IDD_XID_DUKE_CFG DIALOGEX 0, 0, 528, 280
@ -531,6 +540,11 @@ BEGIN
0
END
IDD_INPUT_CFG AFX_DIALOG_LAYOUT
BEGIN
0
END
/////////////////////////////////////////////////////////////////////////////
//
@ -589,10 +603,10 @@ BEGIN
MENUITEM "&Open Xbe...", ID_FILE_OPEN_XBE,MFT_STRING,MFS_ENABLED
MENUITEM "Open D&ashboard...\tF7", ID_FILE_OPEN_DASHBOARD,MFT_STRING,MFS_ENABLED
MENUITEM "&Close Xbe", ID_FILE_CLOSE_XBE,MFT_STRING,MFS_ENABLED
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
MENUITEM "&Save Xbe", ID_FILE_SAVEXBEFILE,MFT_STRING,MFS_ENABLED
MENUITEM "Save Xbe &As...", ID_FILE_SAVEXBEFILEAS,MFT_STRING,MFS_ENABLED
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
POPUP "&Recent Xbe Files", 65535,MFT_STRING,MFS_ENABLED
BEGIN
MENUITEM "&0 : Recent Placeholder", ID_FILE_RXBE_0,MFT_STRING,MFS_ENABLED
@ -606,7 +620,7 @@ BEGIN
MENUITEM "&8 : Recent Placeholder", ID_FILE_RXBE_8,MFT_STRING,MFS_ENABLED
MENUITEM "&9 : Recent Placeholder", ID_FILE_RXBE_9,MFT_STRING,MFS_ENABLED
END
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
MENUITEM "E&xit", ID_FILE_EXIT,MFT_STRING,MFS_ENABLED
END
POPUP "&Edit", 65535,MFT_STRING,MFS_ENABLED
@ -621,7 +635,7 @@ BEGIN
MENUITEM "&Allow >64 MB", ID_EDIT_PATCH_ALLOW64MB,MFT_STRING,MFS_ENABLED
MENUITEM "&Debug Mode", ID_EDIT_PATCH_DEBUGMODE,MFT_STRING,MFS_ENABLED
END
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
POPUP "Dump &Xbe Info To...", 65535,MFT_STRING,MFS_ENABLED
BEGIN
MENUITEM "&File...", ID_EDIT_DUMPXBEINFOTO_FILE,MFT_STRING,MFS_ENABLED
@ -660,7 +674,7 @@ BEGIN
MENUITEM "&Clear entire Symbol Cache", ID_CACHE_CLEARHLECACHE_ALL,MFT_STRING,MFS_ENABLED
MENUITEM "&Rescan title Symbol Cache", ID_CACHE_CLEARHLECACHE_CURRENT,MFT_STRING,MFS_ENABLED
END
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
POPUP "Experimental", 65535,MFT_STRING,MFS_ENABLED
BEGIN
POPUP "&LLE", 65535,MFT_STRING,MFS_ENABLED
@ -679,22 +693,22 @@ BEGIN
END
MENUITEM "Use Loader Executable", ID_USELOADEREXEC,MFT_STRING,MFS_ENABLED
MENUITEM "Ignore Invalid Xbe Signature", ID_SETTINGS_IGNOREINVALIDXBESIG,MFT_STRING,MFS_ENABLED
MENUITEM "Ignore Invalid Xbe Sections", ID_SETTINGS_IGNOREINVALIDXBESEC, MFT_STRING, MFS_ENABLED
MENUITEM "Ignore Invalid Xbe Sections", ID_SETTINGS_IGNOREINVALIDXBESEC,MFT_STRING,MFS_ENABLED
MENUITEM "Allow Admin Privilege", ID_SETTINGS_ALLOWADMINPRIVILEGE,MFT_STRING,MFS_ENABLED
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
MENUITEM "Reset To Defaults", ID_SETTINGS_INITIALIZE,MFT_STRING,MFS_ENABLED
END
POPUP "E&mulation", 65535,MFT_STRING,MFS_ENABLED
BEGIN
MENUITEM "&Start\tF5", ID_EMULATION_START,MFT_STRING,MFS_ENABLED
MENUITEM "Start &Debugger...\tF9", ID_EMULATION_STARTDEBUGGER,MFT_STRING,MFS_ENABLED
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
MENUITEM "S&top\tF6", ID_EMULATION_STOP,MFT_STRING,MFS_ENABLED
END
POPUP "&Help", 65535,MFT_STRING,MFS_ENABLED
BEGIN
MENUITEM "&Go To The Official Cxbx Web Site...", ID_HELP_HOMEPAGE,MFT_STRING,MFS_ENABLED
MENUITEM "", -1, MFT_SEPARATOR
MENUITEM MFT_SEPARATOR
MENUITEM "&About", ID_HELP_ABOUT,MFT_STRING,MFS_ENABLED
END
MENUITEM " ", ID_FPS,MFT_STRING | MFT_RIGHTJUSTIFY,MFS_ENABLED

View File

@ -304,6 +304,9 @@
#define IDC_RUMBLE_TEST 1302
#define IDC_NETWORK_ADAPTER 1303
#define IDC_LOG_POPUP_TESTCASE 1304
#define IDC_INPUT_OPTIONS 1305
#define IDC_MOUSE_RANGE 1306
#define IDC_WHEEL_RANGE 1307
#define ID_FILE_EXIT 40005
#define ID_HELP_ABOUT 40008
#define ID_EMULATION_START 40009