Merge pull request #604 from magcius/wip/emu-cleanup-2

Start cleaning up the input interface
This commit is contained in:
Lioncash 2014-07-15 12:11:17 -04:00
commit ebd029973a
41 changed files with 765 additions and 1630 deletions

View File

@ -150,6 +150,7 @@ void SConfig::SaveSettings()
SaveCoreSettings(ini);
SaveMovieSettings(ini);
SaveDSPSettings(ini);
SaveInputSettings(ini);
SaveFifoPlayerSettings(ini);
ini.Save(File::GetUserPath(F_DOLPHINCONFIG_IDX));
@ -329,6 +330,13 @@ void SConfig::SaveDSPSettings(IniFile& ini)
dsp->Set("CaptureLog", m_DSPCaptureLog);
}
void SConfig::SaveInputSettings(IniFile& ini)
{
IniFile::Section* input = ini.GetOrCreateSection("Input");
input->Set("BackgroundInput", m_BackgroundInput);
}
void SConfig::SaveFifoPlayerSettings(IniFile& ini)
{
IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");
@ -350,6 +358,7 @@ void SConfig::LoadSettings()
LoadCoreSettings(ini);
LoadMovieSettings(ini);
LoadDSPSettings(ini);
LoadInputSettings(ini);
LoadFifoPlayerSettings(ini);
m_SYSCONF = new SysConf();
@ -556,6 +565,13 @@ void SConfig::LoadDSPSettings(IniFile& ini)
dsp->Get("CaptureLog", &m_DSPCaptureLog, false);
}
void SConfig::LoadInputSettings(IniFile& ini)
{
IniFile::Section* input = ini.GetOrCreateSection("Input");
input->Get("BackgroundInput", &m_BackgroundInput, false);
}
void SConfig::LoadFifoPlayerSettings(IniFile& ini)
{
IniFile::Section* fifoplayer = ini.GetOrCreateSection("FifoPlayer");

View File

@ -97,6 +97,9 @@ struct SConfig : NonCopyable
int m_Volume;
std::string sBackend;
// Input settings
bool m_BackgroundInput;
SysConf* m_SYSCONF;
// save settings
@ -122,6 +125,7 @@ private:
void SaveGameListSettings(IniFile& ini);
void SaveCoreSettings(IniFile& ini);
void SaveDSPSettings(IniFile& ini);
void SaveInputSettings(IniFile& ini);
void SaveMovieSettings(IniFile& ini);
void SaveFifoPlayerSettings(IniFile& ini);
@ -132,6 +136,7 @@ private:
void LoadGameListSettings(IniFile& ini);
void LoadCoreSettings(IniFile& ini);
void LoadDSPSettings(IniFile& ini);
void LoadInputSettings(IniFile& ini);
void LoadMovieSettings(IniFile& ini);
void LoadFifoPlayerSettings(IniFile& ini);

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@ -357,7 +357,6 @@
<ClInclude Include="HW\WiimoteEmu\Attachment\Turntable.h" />
<ClInclude Include="HW\WiimoteEmu\Encryption.h" />
<ClInclude Include="HW\WiimoteEmu\MatrixMath.h" />
<ClInclude Include="HW\WiimoteEmu\UDPTLayer.h" />
<ClInclude Include="HW\WiimoteEmu\WiimoteEmu.h" />
<ClInclude Include="HW\WiimoteEmu\WiimoteHid.h" />
<ClInclude Include="HW\WiimoteReal\WiimoteReal.h" />

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="ActionReplay">
@ -1005,9 +1005,6 @@
<ClInclude Include="HW\WiimoteEmu\MatrixMath.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu</Filter>
</ClInclude>
<ClInclude Include="HW\WiimoteEmu\UDPTLayer.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu</Filter>
</ClInclude>
<ClInclude Include="HW\WiimoteEmu\WiimoteEmu.h">
<Filter>HW %28Flipper/Hollywood%29\Wiimote\Emu</Filter>
</ClInclude>

View File

@ -79,7 +79,7 @@ GCPad::GCPad(const unsigned int index) : m_index(index)
// options
groups.emplace_back(m_options = new ControlGroup(_trans("Options")));
m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Background Input"), false));
m_options->settings.emplace_back(new ControlGroup::BackgroundInputSetting(_trans("Background Input")));
}
std::string GCPad::GetName() const
@ -89,9 +89,8 @@ std::string GCPad::GetName() const
void GCPad::GetInput(GCPadStatus* const pad)
{
// if window has focus or background input enabled
if (Host_RendererHasFocus() || m_options[0].settings[0]->value)
{
double x, y, triggers[2];
// buttons
m_buttons->GetState(&pad->button, button_bitmasks);
@ -103,20 +102,18 @@ void GCPad::GetInput(GCPadStatus* const pad)
m_dpad->GetState(&pad->button, dpad_bitmasks);
// sticks
m_main_stick->GetState(&pad->stickX, &pad->stickY, 0x80, 127);
m_c_stick->GetState(&pad->substickX, &pad->substickY, 0x80, 127);
m_main_stick->GetState(&x, &y);
pad->stickX = 0x7F + (x * 0x80);
pad->stickY = 0x7F + (y * 0x80);
m_c_stick->GetState(&x, &y);
pad->substickX = 0x7F + (x * 0x80);
pad->substickY = 0x7F + (y * 0x80);
// triggers
m_triggers->GetState(&pad->button, trigger_bitmasks, &pad->triggerLeft, 0xFF);
}
else
{
// center sticks
pad->stickX = 0x80;
pad->stickY = 0x80;
pad->substickX = 0x80;
pad->substickY = 0x80;
}
m_triggers->GetState(&pad->button, trigger_bitmasks, triggers);
pad->triggerLeft = triggers[0] * 0xFF;
pad->triggerRight = triggers[1] * 0xFF;
}
void GCPad::SetMotor(const u8 on)
@ -126,17 +123,12 @@ void GCPad::SetMotor(const u8 on)
if (state < 0.5)
force = -force;
// only rumble if window has focus or background input is enabled
if (Host_RendererHasFocus() || m_options[0].settings[0]->value)
m_rumble->controls[0]->control_ref->State(force);
else
m_rumble->controls[0]->control_ref->State(0);
}
void GCPad::SetOutput(const u8 on)
{
// only rumble if window has focus or background input is enabled
m_rumble->controls[0]->control_ref->State(on && (Host_RendererHasFocus() || m_options[0].settings[0]->value));
m_rumble->controls[0]->control_ref->State(on);
}
void GCPad::LoadDefaults(const ControllerInterface& ciface)

View File

@ -42,7 +42,7 @@ void Attachment::Reset()
}
void ControllerEmu::Extension::GetState(u8* const data, const bool focus)
void ControllerEmu::Extension::GetState(u8* const data)
{
((WiimoteEmu::Attachment*)attachments[active_extension].get())->GetState(data, focus);
((WiimoteEmu::Attachment*)attachments[active_extension].get())->GetState(data);
}

View File

@ -15,7 +15,7 @@ class Attachment : public ControllerEmu
public:
Attachment(const char* const _name, WiimoteEmu::ExtensionReg& _reg);
virtual void GetState(u8* const data, const bool focus = true) {}
virtual void GetState(u8* const data) {}
void Reset();
std::string GetName() const override;

View File

@ -80,7 +80,7 @@ Classic::Classic(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Classic"),
memcpy(&id, classic_id, sizeof(classic_id));
}
void Classic::GetState(u8* const data, const bool focus)
void Classic::GetState(u8* const data)
{
wm_classic_extension* const ccdata = (wm_classic_extension*)data;
ccdata->bt = 0;
@ -89,41 +89,46 @@ void Classic::GetState(u8* const data, const bool focus)
// left stick
{
u8 x, y;
m_left_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
double x, y;
m_left_stick->GetState(&x, &y);
ccdata->lx = x;
ccdata->ly = y;
ccdata->lx = (x * 0x1F) + 0x20;
ccdata->ly = (y * 0x1F) + 0x20;
}
// right stick
{
u8 x, y;
m_right_stick->GetState(&x, &y, 0x10, focus ? 0x0F /*0x0C*/ : 0);
double x, y;
u8 x_, y_;
m_right_stick->GetState(&x, &y);
ccdata->rx1 = x;
ccdata->rx2 = x >> 1;
ccdata->rx3 = x >> 3;
ccdata->ry = y;
x_ = (x * 0x1F) + 0x20;
y_ = (y * 0x1F) + 0x20;
ccdata->rx1 = x_;
ccdata->rx2 = x_ >> 1;
ccdata->rx3 = x_ >> 3;
ccdata->ry = y_;
}
//triggers
{
u8 trigs[2];
m_triggers->GetState(&ccdata->bt, classic_trigger_bitmasks, trigs, focus ? 0x1F : 0);
double trigs[2] = { 0, 0 };
u8 lt, rt;
m_triggers->GetState(&ccdata->bt, classic_trigger_bitmasks, trigs);
ccdata->lt1 = trigs[0];
ccdata->lt2 = trigs[0] >> 3;
ccdata->rt = trigs[1];
lt = trigs[0] * 0x1F;
rt = trigs[1] * 0x1F;
ccdata->lt1 = lt;
ccdata->lt2 = lt >> 3;
ccdata->rt = rt;
}
if (focus)
{
// buttons
m_buttons->GetState(&ccdata->bt, classic_button_bitmasks);
// dpad
m_dpad->GetState(&ccdata->bt, classic_dpad_bitmasks);
}
// flip button bits
ccdata->bt ^= 0xFFFF;

View File

@ -13,7 +13,7 @@ class Classic : public Attachment
{
public:
Classic(WiimoteEmu::ExtensionReg& _reg);
void GetState(u8* const data, const bool focus) override;
void GetState(u8* const data) override;
enum
{

View File

@ -51,7 +51,7 @@ Drums::Drums(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Drums"), _reg)
memcpy(&id, drums_id, sizeof(drums_id));
}
void Drums::GetState(u8* const data, const bool focus)
void Drums::GetState(u8* const data)
{
wm_drums_extension* const ddata = (wm_drums_extension*)data;
ddata->bt = 0;
@ -60,24 +60,21 @@ void Drums::GetState(u8* const data, const bool focus)
// stick
{
u8 x, y;
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
double x, y;
m_stick->GetState(&x, &y);
ddata->sx = x;
ddata->sy = y;
ddata->sx = (x * 0x1F) + 0x20;
ddata->sx = (y * 0x1F) + 0x20;
}
// TODO: softness maybe
data[2] = 0xFF;
data[3] = 0xFF;
if (focus)
{
// buttons
m_buttons->GetState(&ddata->bt, drum_button_bitmasks);
// pads
m_pads->GetState(&ddata->bt, drum_pad_bitmasks);
}
// flip button bits
ddata->bt ^= 0xFFFF;

View File

@ -13,7 +13,7 @@ class Drums : public Attachment
{
public:
Drums(WiimoteEmu::ExtensionReg& _reg);
void GetState(u8* const data, const bool focus) override;
void GetState(u8* const data) override;
enum
{

View File

@ -64,7 +64,7 @@ Guitar::Guitar(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Guitar"), _r
memcpy(&id, guitar_id, sizeof(guitar_id));
}
void Guitar::GetState(u8* const data, const bool focus)
void Guitar::GetState(u8* const data)
{
wm_guitar_extension* const gdata = (wm_guitar_extension*)data;
gdata->bt = 0;
@ -73,30 +73,27 @@ void Guitar::GetState(u8* const data, const bool focus)
// stick
{
u8 x, y;
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
double x, y;
m_stick->GetState(&x, &y);
gdata->sx = x;
gdata->sy = y;
gdata->sx = (x * 0x1F) + 0x20;
gdata->sy = (y * 0x1F) + 0x20;
}
// TODO: touch bar, probably not
gdata->tb = 0x0F; // not touched
// whammy bar
u8 whammy;
m_whammy->GetState(&whammy, 0x1F);
gdata->whammy = whammy;
double whammy;
m_whammy->GetState(&whammy);
gdata->whammy = whammy * 0x1F;
if (focus)
{
// buttons
m_buttons->GetState(&gdata->bt, guitar_button_bitmasks);
// frets
m_frets->GetState(&gdata->bt, guitar_fret_bitmasks);
// strum
m_strum->GetState(&gdata->bt, guitar_strum_bitmasks);
}
// flip button bits
gdata->bt ^= 0xFFFF;

View File

@ -13,7 +13,7 @@ class Guitar : public Attachment
{
public:
Guitar(WiimoteEmu::ExtensionReg& _reg);
void GetState(u8* const data, const bool focus) override;
void GetState(u8* const data) override;
enum
{

View File

@ -4,9 +4,6 @@
#include "Core/HW/WiimoteEmu/Attachment/Nunchuk.h"
#include "InputCommon/UDPWiimote.h"
#include "InputCommon/UDPWrapper.h"
namespace WiimoteEmu
{
@ -31,8 +28,7 @@ static const u8 nunchuk_button_bitmasks[] =
Nunchuk::BUTTON_Z,
};
Nunchuk::Nunchuk(UDPWrapper *wrp, WiimoteEmu::ExtensionReg& _reg)
: Attachment(_trans("Nunchuk"), _reg) , m_udpWrap(wrp)
Nunchuk::Nunchuk(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Nunchuk"), _reg)
{
// buttons
groups.emplace_back(m_buttons = new Buttons("Buttons"));
@ -64,23 +60,23 @@ Nunchuk::Nunchuk(UDPWrapper *wrp, WiimoteEmu::ExtensionReg& _reg)
memset(m_shake_step, 0, sizeof(m_shake_step));
}
void Nunchuk::GetState(u8* const data, const bool focus)
void Nunchuk::GetState(u8* const data)
{
wm_extension* const ncdata = (wm_extension*)data;
ncdata->bt = 0;
// stick
ControlState state[2];
m_stick->GetState(&state[0], &state[1], 0, 1);
double state[2];
m_stick->GetState(&state[0], &state[1]);
nu_cal &cal = *(nu_cal*)&reg.calibration;
nu_js cal_js[2];
cal_js[0] = *&cal.jx;
cal_js[1] = *&cal.jy;
cal_js[0] = cal.jx;
cal_js[1] = cal.jy;
for (int i = 0; i < 2; i++) {
ControlState &s = *&state[i];
nu_js c = *&cal_js[i];
double &s = state[i];
nu_js c = cal_js[i];
if (s < 0)
s = s * abs(c.min - c.center) + c.center;
else if (s > 0)
@ -100,59 +96,21 @@ void Nunchuk::GetState(u8* const data, const bool focus)
ncdata->jx = cal.jx.center + 1;
}
if (!focus)
{
ncdata->jx = cal.jx.center;
ncdata->jy = cal.jy.center;
}
AccelData accel;
// tilt
EmulateTilt(&accel, m_tilt, focus);
EmulateTilt(&accel, m_tilt);
if (focus)
{
// swing
EmulateSwing(&accel, m_swing);
// shake
EmulateShake(&accel, m_shake, m_shake_step);
// buttons
m_buttons->GetState(&ncdata->bt, nunchuk_button_bitmasks);
}
// flip the button bits :/
ncdata->bt ^= 0x03;
if (m_udpWrap->inst)
{
if (m_udpWrap->updNun)
{
u8 mask;
float x, y;
m_udpWrap->inst->getNunchuck(&x, &y, &mask);
// buttons
if (mask & UDPWM_NC)
ncdata->bt &= ~WiimoteEmu::Nunchuk::BUTTON_C;
if (mask & UDPWM_NZ)
ncdata->bt &= ~WiimoteEmu::Nunchuk::BUTTON_Z;
// stick
if (ncdata->jx == 0x80 && ncdata->jy == 0x80)
{
ncdata->jx = u8(0x80 + x*127);
ncdata->jy = u8(0x80 + y*127);
}
}
if (m_udpWrap->updNunAccel)
{
float x, y, z;
m_udpWrap->inst->getNunchuckAccel(&x, &y, &z);
accel.x = x;
accel.y = y;
accel.z = z;
}
}
FillRawAccelFromGForceData(*(wm_accel*)&ncdata->ax, *(accel_cal*)&reg.calibration, accel);
}

View File

@ -6,17 +6,15 @@
#include "Core/HW/WiimoteEmu/Attachment/Attachment.h"
class UDPWrapper;
namespace WiimoteEmu
{
class Nunchuk : public Attachment
{
public:
Nunchuk(UDPWrapper * wrp, WiimoteEmu::ExtensionReg& _reg);
Nunchuk(WiimoteEmu::ExtensionReg& _reg);
virtual void GetState(u8* const data, const bool focus) override;
virtual void GetState(u8* const data) override;
enum
{
@ -36,8 +34,6 @@ private:
AnalogStick* m_stick;
u8 m_shake_step[3];
UDPWrapper* const m_udpWrap;
};
}

View File

@ -55,63 +55,68 @@ Turntable::Turntable(WiimoteEmu::ExtensionReg& _reg) : Attachment(_trans("Turnta
memcpy(&id, turntable_id, sizeof(turntable_id));
}
void Turntable::GetState(u8* const data, const bool focus)
void Turntable::GetState(u8* const data)
{
wm_turntable_extension* const ttdata = (wm_turntable_extension*)data;
ttdata->bt = 0;
// stick
{
u8 x, y;
m_stick->GetState(&x, &y, 0x20, focus ? 0x1F /*0x15*/ : 0);
double x, y;
m_stick->GetState(&x, &y);
ttdata->sx = x;
ttdata->sy = y;
ttdata->sx = (x * 0x1F) + 0x20;
ttdata->sy = (y * 0x1F) + 0x20;
}
// left table
{
s8 tt = 0;
m_left_table->GetState(&tt, focus ? 0x1F : 0);
double tt;
s8 tt_;
m_left_table->GetState(&tt);
ttdata->ltable1 = tt;
ttdata->ltable2 = tt >> 5;
tt_ = tt * 0x1F;
ttdata->ltable1 = tt_;
ttdata->ltable2 = tt_ >> 5;
}
// right table
{
s8 tt = 0;
m_right_table->GetState(&tt, focus ? 0x1F : 0);
double tt;
s8 tt_;
m_right_table->GetState(&tt);
ttdata->rtable1 = tt;
ttdata->rtable2 = tt >> 1;
ttdata->rtable3 = tt >> 3;
ttdata->rtable4 = tt >> 5;
tt_ = tt * 0x1F;
ttdata->rtable1 = tt_;
ttdata->rtable2 = tt_ >> 1;
ttdata->rtable3 = tt_ >> 3;
ttdata->rtable4 = tt_ >> 5;
}
// effect dial
{
u8 dial = 0;
m_effect_dial->GetState(&dial, focus ? 0xF : 0);
double dial;
u8 dial_;
m_effect_dial->GetState(&dial);
ttdata->dial1 = dial;
ttdata->dial2 = dial >> 3;
dial_ = dial * 0x0F;
ttdata->dial1 = dial_;
ttdata->dial2 = dial_ >> 3;
}
// crossfade slider
{
s8 cfs = 0;
m_crossfade->GetState(&cfs, focus ? 7 : 0);
cfs += 8;
double cfs;
m_crossfade->GetState(&cfs);
ttdata->slider = cfs;
ttdata->slider = (cfs * 0x07) + 0x08;
}
if (focus)
{
// buttons
m_buttons->GetState(&ttdata->bt, turntable_button_bitmasks);
}
// flip button bits :/
ttdata->bt ^= (

View File

@ -13,7 +13,7 @@ class Turntable : public Attachment
{
public:
Turntable(WiimoteEmu::ExtensionReg& _reg);
void GetState(u8* const data, const bool focus) override;
void GetState(u8* const data) override;
enum
{

View File

@ -1,54 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
//UDP Wiimote Translation Layer
#pragma once
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "InputCommon/UDPWiimote.h"
namespace UDPTLayer
{
static void GetButtons(UDPWrapper * m , wm_core * butt)
{
if (!(m->inst)) return;
if (!(m->updButt)) return;
u32 mask = m->inst->getButtons();
*butt |= (mask & UDPWM_BA) ? WiimoteEmu::Wiimote::BUTTON_A : 0;
*butt |= (mask & UDPWM_BB) ? WiimoteEmu::Wiimote::BUTTON_B : 0;
*butt |= (mask & UDPWM_B1) ? WiimoteEmu::Wiimote::BUTTON_ONE : 0;
*butt |= (mask & UDPWM_B2) ? WiimoteEmu::Wiimote::BUTTON_TWO : 0;
*butt |= (mask & UDPWM_BP) ? WiimoteEmu::Wiimote::BUTTON_PLUS : 0;
*butt |= (mask & UDPWM_BM) ? WiimoteEmu::Wiimote::BUTTON_MINUS : 0;
*butt |= (mask & UDPWM_BH) ? WiimoteEmu::Wiimote::BUTTON_HOME : 0;
*butt |= (mask & UDPWM_BU) ? WiimoteEmu::Wiimote::PAD_UP : 0;
*butt |= (mask & UDPWM_BD) ? WiimoteEmu::Wiimote::PAD_DOWN : 0;
*butt |= (mask & UDPWM_BL) ? WiimoteEmu::Wiimote::PAD_LEFT : 0;
*butt |= (mask & UDPWM_BR) ? WiimoteEmu::Wiimote::PAD_RIGHT : 0;
}
static void GetAcceleration(UDPWrapper * m , WiimoteEmu::AccelData * const data)
{
if (!(m->inst)) return;
if (!(m->updAccel)) return;
float x, y, z;
m->inst->getAccel(&x, &y, &z);
data->x = x;
data->y = y;
data->z = z;
}
static void GetIR( UDPWrapper * m, float * x, float * y, float * z)
{
if (!(m->inst)) return;
if (!(m->updIR)) return;
if ((*x >= -0.999) && (*x <= 0.999) && (*y >= -0.999) && (*y <= 0.999)) return; //the received values are used ONLY when the normal pointer is offscreen
float _x, _y;
m->inst->getIR(&_x, &_y);
*x = _x * 2 - 1;
*y = -(_y * 2 - 1);
*z = 0;
}
}

View File

@ -13,7 +13,6 @@
#include "Core/NetPlayClient.h"
#include "Core/HW/WiimoteEmu/MatrixMath.h"
#include "Core/HW/WiimoteEmu/UDPTLayer.h"
#include "Core/HW/WiimoteEmu/WiimoteEmu.h"
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
#include "Core/HW/WiimoteEmu/Attachment/Classic.h"
@ -119,11 +118,14 @@ void EmulateShake(AccelData* const accel
void EmulateTilt(AccelData* const accel
, ControllerEmu::Tilt* const tilt_group
, const bool focus, const bool sideways, const bool upright)
, const bool sideways, const bool upright)
{
float roll, pitch;
double roll, pitch;
// 180 degrees
tilt_group->GetState(&roll, &pitch, 0, focus ? PI : 0);
tilt_group->GetState(&roll, &pitch);
roll *= PI;
pitch *= PI;
unsigned int ud = 0, lr = 0, fb = 0;
@ -145,7 +147,7 @@ void EmulateTilt(AccelData* const accel
if (!sideways && upright)
sgn[ud] *= -1;
(&accel->x)[ud] = (sin((PI / 2) - std::max(fabsf(roll), fabsf(pitch))))*sgn[ud];
(&accel->x)[ud] = (sin((PI / 2) - std::max(fabs(roll), fabs(pitch))))*sgn[ud];
(&accel->x)[lr] = -sin(roll)*sgn[lr];
(&accel->x)[fb] = sin(pitch)*sgn[fb];
}
@ -156,8 +158,8 @@ void EmulateSwing(AccelData* const accel
, ControllerEmu::Force* const swing_group
, const bool sideways, const bool upright)
{
float swing[3];
swing_group->GetState(swing, 0, SWING_INTENSITY);
double swing[3];
swing_group->GetState(swing);
s8 g_dir[3] = {-1, -1, -1};
u8 axis_map[3];
@ -175,7 +177,7 @@ void EmulateSwing(AccelData* const accel
g_dir[axis_map[0]] *= -1;
for (unsigned int i=0; i<3; ++i)
(&accel->x)[axis_map[i]] += swing[i] * g_dir[i];
(&accel->x)[axis_map[i]] += swing[i] * g_dir[i] * SWING_INTENSITY;
}
const u16 button_bitmasks[] =
@ -266,9 +268,6 @@ Wiimote::Wiimote( const unsigned int index )
for (auto& named_button : named_buttons)
m_buttons->controls.emplace_back(new ControlGroup::Input( named_button));
// udp
groups.emplace_back(m_udp = new UDPWrapper(m_index, _trans("UDP Wiimote")));
// ir
groups.emplace_back(m_ir = new Cursor(_trans("IR")));
@ -287,7 +286,7 @@ Wiimote::Wiimote( const unsigned int index )
// extension
groups.emplace_back(m_extension = new Extension(_trans("Extension")));
m_extension->attachments.emplace_back(new WiimoteEmu::None(m_reg_ext));
m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_udp, m_reg_ext));
m_extension->attachments.emplace_back(new WiimoteEmu::Nunchuk(m_reg_ext));
m_extension->attachments.emplace_back(new WiimoteEmu::Classic(m_reg_ext));
m_extension->attachments.emplace_back(new WiimoteEmu::Guitar(m_reg_ext));
m_extension->attachments.emplace_back(new WiimoteEmu::Drums(m_reg_ext));
@ -306,7 +305,7 @@ Wiimote::Wiimote( const unsigned int index )
// options
groups.emplace_back( m_options = new ControlGroup(_trans("Options")));
m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Background Input"), false));
m_options->settings.emplace_back(new ControlGroup::BackgroundInputSetting(_trans("Background Input")));
m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Sideways Wiimote"), false));
m_options->settings.emplace_back(new ControlGroup::Setting(_trans("Upright Wiimote"), false));
@ -322,26 +321,17 @@ std::string Wiimote::GetName() const
return std::string("Wiimote") + char('1'+m_index);
}
// if windows is focused or background input is enabled
#define HAS_FOCUS (Host_RendererHasFocus() || (m_options->settings[0]->value != 0))
bool Wiimote::Step()
{
const bool has_focus = HAS_FOCUS;
// TODO: change this a bit
m_motion_plus_present = m_extension->settings[0]->value != 0;
// no rumble if no focus
if (false == has_focus)
m_rumble_on = false;
m_rumble->controls[0]->control_ref->State(m_rumble_on);
// when a movie is active, this button status update is disabled (moved), because movies only record data reports.
if (!(Movie::IsPlayingInput() || Movie::IsRecordingInput()) || NetPlay::IsNetPlayRunning())
{
UpdateButtonsStatus(has_focus);
UpdateButtonsStatus();
}
// check if there is a read data request
@ -381,17 +371,13 @@ bool Wiimote::Step()
return false;
}
void Wiimote::UpdateButtonsStatus(bool has_focus)
void Wiimote::UpdateButtonsStatus()
{
// update buttons in status struct
m_status.buttons = 0;
if (has_focus)
{
const bool is_sideways = m_options->settings[1]->value != 0;
m_buttons->GetState(&m_status.buttons, button_bitmasks);
m_dpad->GetState(&m_status.buttons, is_sideways ? dpad_sideways_bitmasks : dpad_bitmasks);
UDPTLayer::GetButtons(m_udp, &m_status.buttons);
}
}
void Wiimote::GetCoreData(u8* const data)
@ -399,7 +385,7 @@ void Wiimote::GetCoreData(u8* const data)
// when a movie is active, the button update happens here instead of Wiimote::Step, to avoid potential desync issues.
if (Movie::IsPlayingInput() || Movie::IsRecordingInput() || NetPlay::IsNetPlayRunning())
{
UpdateButtonsStatus(HAS_FOCUS);
UpdateButtonsStatus();
}
*(wm_core*)data |= m_status.buttons;
@ -407,21 +393,16 @@ void Wiimote::GetCoreData(u8* const data)
void Wiimote::GetAccelData(u8* const data)
{
const bool has_focus = HAS_FOCUS;
const bool is_sideways = m_options->settings[1]->value != 0;
const bool is_upright = m_options->settings[2]->value != 0;
// ----TILT----
EmulateTilt(&m_accel, m_tilt, has_focus, is_sideways, is_upright);
EmulateTilt(&m_accel, m_tilt, is_sideways, is_upright);
// ----SWING----
// ----SHAKE----
if (has_focus)
{
EmulateSwing(&m_accel, m_swing, is_sideways, is_upright);
EmulateShake(&m_accel, m_shake, m_shake_step);
UDPTLayer::GetAcceleration(m_udp, &m_accel);
}
FillRawAccelFromGForceData(*(wm_accel*)data, *(accel_cal*)&m_eeprom[0x16], m_accel);
}
@ -435,14 +416,10 @@ inline void LowPassFilter(double & var, double newval, double period)
void Wiimote::GetIRData(u8* const data, bool use_accel)
{
const bool has_focus = HAS_FOCUS;
u16 x[4], y[4];
memset(x, 0xFF, sizeof(x));
if (has_focus)
{
float xx = 10000, yy = 0, zz = 0;
double xx = 10000, yy = 0, zz = 0;
double nsin,ncos;
if (use_accel)
@ -476,7 +453,6 @@ void Wiimote::GetIRData(u8* const data, bool use_accel)
LowPassFilter(ir_cos,ncos,1.0f/60);
m_ir->GetState(&xx, &yy, &zz, true);
UDPTLayer::GetIR(m_udp, &xx, &yy, &zz);
Vertex v[4];
@ -522,7 +498,7 @@ void Wiimote::GetIRData(u8* const data, bool use_accel)
// PanicAlert("%f %f\n%f %f\n%f %f\n%f %f\n%d %d\n%d %d\n%d %d\n%d %d",
// v[0].x,v[0].y,v[1].x,v[1].y,v[2].x,v[2].y,v[3].x,v[3].y,
// x[0],y[0],x[1],y[1],x[2],y[2],x[3],y[38]);
}
// Fill report with valid data when full handshake was done
if (m_reg_ir.data[0x30])
// ir mode
@ -582,7 +558,7 @@ void Wiimote::GetIRData(u8* const data, bool use_accel)
void Wiimote::GetExtData(u8* const data)
{
m_extension->GetState(data, HAS_FOCUS);
m_extension->GetState(data);
// i dont think anything accesses the extension data like this, but ill support it. Indeed, commercial games don't do this.
// i think it should be unencrpyted in the register, encrypted when read.

View File

@ -12,7 +12,6 @@
#include "Core/HW/WiimoteEmu/Encryption.h"
#include "Core/HW/WiimoteEmu/WiimoteHid.h"
#include "InputCommon/ControllerEmu.h"
#include "InputCommon/UDPWrapper.h"
// Registry sizes
#define WIIMOTE_EEPROM_SIZE (16*1024)
@ -78,7 +77,7 @@ void EmulateShake(AccelData* const accel_data
void EmulateTilt(AccelData* const accel
, ControllerEmu::Tilt* const tilt_group
, const bool focus, const bool sideways = false, const bool upright = false);
, const bool sideways = false, const bool upright = false);
void EmulateSwing(AccelData* const accel
, ControllerEmu::Force* const tilt_group
@ -129,7 +128,7 @@ protected:
bool Step();
void HidOutputReport(const wm_report* const sr, const bool send_ack = true);
void HandleExtensionSwap();
void UpdateButtonsStatus(bool has_focus);
void UpdateButtonsStatus();
void GetCoreData(u8* const data);
void GetAccelData(u8* const data);
@ -175,8 +174,6 @@ private:
double ir_sin, ir_cos; //for the low pass filter
UDPWrapper* m_udp;
bool m_rumble_on;
bool m_speaker_mute;
bool m_motion_plus_present;

View File

@ -89,7 +89,6 @@ if(wxWidgets_FOUND)
PHackSettings.cpp
PatchAddEdit.cpp
TASInputDlg.cpp
UDPConfigDiag.cpp
VideoConfigDiag.cpp
WXInputBase.cpp
WiimoteConfigDiag.cpp

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@ -95,7 +95,6 @@
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="TASInputDlg.cpp" />
<ClCompile Include="UDPConfigDiag.cpp" />
<ClCompile Include="VideoConfigDiag.cpp" />
<ClCompile Include="WiimoteConfigDiag.cpp" />
<ClCompile Include="WXInputBase.cpp" />
@ -144,7 +143,6 @@
<ClInclude Include="PHackSettings.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="TASInputDlg.h" />
<ClInclude Include="UDPConfigDiag.h" />
<ClInclude Include="VideoConfigDiag.h" />
<ClInclude Include="WiimoteConfigDiag.h" />
<ClInclude Include="WXInputBase.h" />

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="GUI">
@ -152,9 +152,6 @@
<ClCompile Include="TASInputDlg.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="UDPConfigDiag.cpp">
<Filter>GUI</Filter>
</ClCompile>
<ClCompile Include="WiimoteConfigDiag.cpp">
<Filter>GUI</Filter>
</ClCompile>
@ -280,9 +277,6 @@
<ClInclude Include="TASInputDlg.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="UDPConfigDiag.h">
<Filter>GUI</Filter>
</ClInclude>
<ClInclude Include="WiimoteConfigDiag.h">
<Filter>GUI</Filter>
</ClInclude>

View File

@ -753,24 +753,15 @@ void CFrame::OnRenderWindowSizeRequest(int width, int height)
bool CFrame::RendererHasFocus()
{
if (m_RenderParent == nullptr)
return false;
#ifdef _WIN32
if (m_RenderParent->GetParent()->GetHWND() == GetForegroundWindow())
return true;
#else
wxWindow *window = wxWindow::FindFocus();
if (window == nullptr)
return false;
// Why these different cases?
if (m_RenderParent == window ||
m_RenderParent == window->GetParent() ||
m_RenderParent->GetParent() == window->GetParent())
{
return true;
}
#endif
return false;
// RendererHasFocus should return true any time any one of our
// windows has the focus, including any dialogs or other windows.
//
// wxGetActiveWindow() returns the current wxWindow which has
// focus. If it's not one of our windows, then it will return
// null.
wxWindow *focusWindow = wxGetActiveWindow();
return (focusWindow != nullptr);
}
void CFrame::OnGameListCtrl_ItemActivated(wxListEvent& WXUNUSED (event))

View File

@ -45,7 +45,6 @@
#include "Common/MsgHandler.h"
#include "Core/HW/Wiimote.h"
#include "DolphinWX/InputConfigDiag.h"
#include "DolphinWX/UDPConfigDiag.h"
#include "DolphinWX/WxUtils.h"
#include "InputCommon/ControllerEmu.h"
#include "InputCommon/InputConfig.h"
@ -53,18 +52,10 @@
#include "InputCommon/ControllerInterface/Device.h"
#include "InputCommon/ControllerInterface/ExpressionParser.h"
class UDPWrapper;
class wxWindow;
using namespace ciface::ExpressionParser;
void GamepadPage::ConfigUDPWii(wxCommandEvent &event)
{
UDPWrapper* const wrp = ((UDPConfigButton*)event.GetEventObject())->wrapper;
UDPConfigDiag diag(this, wrp);
diag.ShowModal();
}
void GamepadPage::ConfigExtension(wxCommandEvent& event)
{
ControllerEmu::Extension* const ex = ((ExtensionButton*)event.GetEventObject())->extension;
@ -113,32 +104,32 @@ void PadSettingExtension::UpdateValue()
extension->switch_extension = ((wxChoice*)wxcontrol)->GetSelection();
}
PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const std::string& label)
: PadSetting(new wxCheckBox(parent, -1, wxGetTranslation(StrToWxStr(label))))
, value(_value)
PadSettingCheckBox::PadSettingCheckBox(wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const _setting)
: PadSetting(new wxCheckBox(parent, -1, wxGetTranslation(StrToWxStr(_setting->name))))
, setting(_setting)
{
UpdateGUI();
}
void PadSettingCheckBox::UpdateGUI()
{
((wxCheckBox*)wxcontrol)->SetValue(value > 0);
((wxCheckBox*)wxcontrol)->SetValue(setting->GetValue());
}
void PadSettingCheckBox::UpdateValue()
{
// 0.01 so its saved to the ini file as just 1. :(
value = 0.01 * ((wxCheckBox*)wxcontrol)->GetValue();
setting->SetValue(0.01 * ((wxCheckBox*)wxcontrol)->GetValue());
}
void PadSettingSpin::UpdateGUI()
{
((wxSpinCtrl*)wxcontrol)->SetValue((int)(value * 100));
((wxSpinCtrl*)wxcontrol)->SetValue((int)(setting->GetValue() * 100));
}
void PadSettingSpin::UpdateValue()
{
value = float(((wxSpinCtrl*)wxcontrol)->GetValue()) / 100;
setting->SetValue(float(((wxSpinCtrl*)wxcontrol)->GetValue()) / 100);
}
ControlDialog::ControlDialog(GamepadPage* const parent, InputPlugin& plugin, ControllerInterface::ControlReference* const ref)
@ -883,19 +874,12 @@ ControlGroupBox::ControlGroupBox(ControllerEmu::ControlGroup* const group, wxWin
Add(configure_btn, 0, wxALL|wxEXPAND, 3);
}
break;
case GROUP_TYPE_UDPWII:
{
wxButton* const btn = new UDPConfigButton(parent, (UDPWrapper*)group);
btn->Bind(wxEVT_BUTTON, &GamepadPage::ConfigUDPWii, eventsink);
Add(btn, 0, wxALL|wxEXPAND, 3);
}
break;
default:
{
//options
for (auto& groupSetting : group->settings)
{
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting->value, groupSetting->name);
PadSettingCheckBox* setting_cbox = new PadSettingCheckBox(parent, groupSetting.get());
setting_cbox->wxcontrol->Bind(wxEVT_CHECKBOX, &GamepadPage::AdjustSetting, eventsink);
options.push_back(setting_cbox);

View File

@ -29,7 +29,6 @@
#include "InputCommon/ControllerInterface/Device.h"
class InputPlugin;
class UDPWrapper;
class wxComboBox;
class wxCommandEvent;
class wxEvent;
@ -70,25 +69,25 @@ public:
class PadSettingSpin : public PadSetting
{
public:
PadSettingSpin(wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const setting)
: PadSetting(new wxSpinCtrl(parent, -1, wxEmptyString, wxDefaultPosition
, wxSize(54, -1), 0, setting->low, setting->high, (int)(setting->value * 100)))
, value(setting->value) {}
PadSettingSpin(wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const _setting)
: PadSetting(new wxSpinCtrl(parent, -1, wxEmptyString, wxDefaultPosition,
wxSize(54, -1), 0, _setting->low, _setting->high, (int)(_setting->value * 100)))
, setting(_setting) {}
void UpdateGUI() override;
void UpdateValue() override;
ControlState& value;
ControllerEmu::ControlGroup::Setting* const setting;
};
class PadSettingCheckBox : public PadSetting
{
public:
PadSettingCheckBox(wxWindow* const parent, ControlState& _value, const std::string& label);
PadSettingCheckBox(wxWindow* const parent, ControllerEmu::ControlGroup::Setting* const setting);
void UpdateGUI() override;
void UpdateValue() override;
ControlState& value;
ControllerEmu::ControlGroup::Setting* const setting;
};
class GamepadPage;
@ -147,16 +146,6 @@ public:
ControllerInterface::ControlReference* const control_reference;
};
class UDPConfigButton : public wxButton
{
public:
UDPWrapper* const wrapper;
UDPConfigButton(wxWindow* const parent, UDPWrapper * udp)
: wxButton(parent, -1, _("Configure"), wxDefaultPosition)
, wrapper(udp)
{}
};
class ControlGroupBox : public wxBoxSizer
{
public:
@ -200,8 +189,6 @@ public:
void ConfigExtension(wxCommandEvent& event);
void ConfigUDPWii(wxCommandEvent& event);
void SetDevice(wxCommandEvent& event);
void ClearAll(wxCommandEvent& event);

View File

@ -29,36 +29,29 @@
class wxTimerEvent;
void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
static void DrawCenteredRectangle(wxDC &dc, int x, int y, int w, int h)
{
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
x -= w / 2;
y -= h / 2;
dc.DrawRectangle(x, y, w, h);
}
g_controller_interface.UpdateInput();
#define VIS_BITMAP_SIZE 64
// don't want game thread updating input when we are using it here
std::unique_lock<std::recursive_mutex> lk(g_controller_interface.update_lock, std::try_to_lock);
if (!lk.owns_lock())
return;
#define VIS_NORMALIZE(a) ((a / 2.0) + 0.5)
#define VIS_COORD(a) ((VIS_NORMALIZE(a)) * VIS_BITMAP_SIZE)
GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection());
#define COORD_VIS_SIZE 4
for (ControlGroupBox* g : current_page->control_groups)
static void DrawCoordinate(wxDC &dc, double x, double y)
{
// if this control group has a bitmap
if (g->static_bitmap)
int xc = VIS_COORD(x);
int yc = VIS_COORD(y);
DrawCenteredRectangle(dc, xc, yc, COORD_VIS_SIZE, COORD_VIS_SIZE);
}
static void DrawControlGroupBox(wxDC &dc, ControlGroupBox *g)
{
wxMemoryDC dc;
wxBitmap bitmap(g->static_bitmap->GetBitmap());
dc.SelectObject(bitmap);
dc.Clear();
dc.SetFont(small_font);
dc.SetTextForeground(0xC0C0C0);
// label for sticks and stuff
if (64 == bitmap.GetHeight())
dc.DrawText(StrToWxStr(g->control_group->name).Upper(), 4, 2);
switch (g->control_group->type)
{
case GROUP_TYPE_TILT :
@ -67,33 +60,21 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
{
// this is starting to be a mess combining all these in one case
float x = 0, y = 0, z = 0;
float xx, yy;
double x = 0, y = 0, z = 0;
switch (g->control_group->type)
{
case GROUP_TYPE_STICK :
((ControllerEmu::AnalogStick*)g->control_group)->GetState(&x, &y, 32.0, 32-1.5);
((ControllerEmu::AnalogStick*)g->control_group)->GetState(&x, &y);
break;
case GROUP_TYPE_TILT :
((ControllerEmu::Tilt*)g->control_group)->GetState(&x, &y, 32.0, 32-1.5);
((ControllerEmu::Tilt*)g->control_group)->GetState(&x, &y);
break;
case GROUP_TYPE_CURSOR :
((ControllerEmu::Cursor*)g->control_group)->GetState(&x, &y, &z);
x *= (32-1.5); x+= 32;
y *= (32-1.5); y+= 32;
break;
}
xx = g->control_group->controls[3]->control_ref->State();
xx -= g->control_group->controls[2]->control_ref->State();
yy = g->control_group->controls[1]->control_ref->State();
yy -= g->control_group->controls[0]->control_ref->State();
xx *= 32 - 1; xx += 32;
yy *= 32 - 1; yy += 32;
// draw the shit
// ir cursor forward movement
if (GROUP_TYPE_CURSOR == g->control_group->type)
{
@ -171,81 +152,92 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
}
// raw dot
{
float xx, yy;
xx = g->control_group->controls[3]->control_ref->State();
xx -= g->control_group->controls[2]->control_ref->State();
yy = g->control_group->controls[1]->control_ref->State();
yy -= g->control_group->controls[0]->control_ref->State();
dc.SetPen(*wxGREY_PEN);
dc.SetBrush(*wxGREY_BRUSH);
// i like the dot better than the cross i think
dc.DrawRectangle(xx - 2, yy - 2, 4, 4);
//dc.DrawRectangle(xx-1, 64-yy-4, 2, 8);
//dc.DrawRectangle(xx-4, 64-yy-1, 8, 2);
DrawCoordinate(dc, xx, yy);
}
// adjusted dot
if (x!=32 || y!=32)
if (x != 0 && y != 0)
{
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(x-2, 64-y-2, 4, 4);
// i like the dot better than the cross i think
//dc.DrawRectangle(x-1, 64-y-4, 2, 8);
//dc.DrawRectangle(x-4, 64-y-1, 8, 2);
// XXX: The adjusted values flip the Y axis to be in the format
// the Wii expects. Should this be in WiimoteEmu.cpp instead?
DrawCoordinate(dc, x, -y);
}
}
break;
case GROUP_TYPE_FORCE :
{
float raw_dot[3];
float adj_dot[3];
const float deadzone = 32 * g->control_group->settings[0]->value;
double raw_dot[3];
double adj_dot[3];
const float deadzone = g->control_group->settings[0]->value;
// adjusted
((ControllerEmu::Force*)g->control_group)->GetState(adj_dot, 32.0, 32-1.5);
((ControllerEmu::Force*)g->control_group)->GetState(adj_dot);
// raw
for (unsigned int i=0; i<3; ++i)
{
raw_dot[i] = g->control_group->controls[i*2 + 1]->control_ref->State()
- g->control_group->controls[i*2]->control_ref->State();
raw_dot[i] *= 32 - 1; raw_dot[i] += 32;
raw_dot[i] = (g->control_group->controls[i*2 + 1]->control_ref->State() -
g->control_group->controls[i*2]->control_ref->State());
}
// deadzone rect for forward/backward visual
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
dc.SetPen(*wxLIGHT_GREY_PEN);
dc.DrawRectangle(0, 32 - deadzone, 64, deadzone * 2);
int deadzone_height = deadzone * VIS_BITMAP_SIZE;
DrawCenteredRectangle(dc, 0, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE, deadzone_height);
#define LINE_HEIGHT 2
int line_y;
// raw forward/background line
dc.SetPen(*wxGREY_PEN);
dc.SetBrush(*wxGREY_BRUSH);
dc.DrawRectangle(0, raw_dot[2] - 1, 64, 2);
line_y = VIS_COORD(raw_dot[2]);
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
// adjusted forward/background line
if (adj_dot[2]!=32)
if (adj_dot[2] != 0.0)
{
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(0, adj_dot[2] - 1, 64, 2);
line_y = VIS_COORD(adj_dot[2]);
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, line_y, VIS_BITMAP_SIZE, LINE_HEIGHT);
}
// a rectangle, for looks i guess
#define DEADZONE_RECT_SIZE 32
// empty deadzone square
dc.SetBrush(*wxWHITE_BRUSH);
dc.SetPen(*wxLIGHT_GREY_PEN);
dc.DrawRectangle(16, 16, 32, 32);
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, DEADZONE_RECT_SIZE, DEADZONE_RECT_SIZE);
// deadzone square
dc.SetBrush(*wxLIGHT_GREY_BRUSH);
dc.DrawRectangle(32 - deadzone, 32 - deadzone, deadzone * 2, deadzone * 2);
int dz_size = (deadzone * DEADZONE_RECT_SIZE);
DrawCenteredRectangle(dc, VIS_BITMAP_SIZE / 2, VIS_BITMAP_SIZE / 2, dz_size, dz_size);
// raw dot
dc.SetPen(*wxGREY_PEN);
dc.SetBrush(*wxGREY_BRUSH);
dc.DrawRectangle(raw_dot[1] - 2, raw_dot[0] - 2, 4, 4);
DrawCoordinate(dc, raw_dot[1], raw_dot[0]);
// adjusted dot
if (adj_dot[1]!=32 || adj_dot[0]!=32)
if (adj_dot[1] != 0 && adj_dot[0] != 0)
{
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(adj_dot[1]-2, adj_dot[0]-2, 4, 4);
DrawCoordinate(dc, adj_dot[1], adj_dot[0]);
}
}
@ -295,8 +287,8 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
dc.SetPen(*wxGREY_PEN);
ControlState deadzone = g->control_group->settings[0]->value;
unsigned int* const trigs = new unsigned int[trigger_count];
((ControllerEmu::Triggers*)g->control_group)->GetState(trigs, 64);
double* const trigs = new double[trigger_count];
((ControllerEmu::Triggers*)g->control_group)->GetState(trigs);
for (unsigned int n = 0; n < trigger_count; ++n)
{
@ -313,7 +305,7 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
// deadzone affected
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(0, n*12, trigs[n], 14);
dc.DrawRectangle(0, n*12, trigs[n]*64, 14);
// text
dc.DrawText(StrToWxStr(g->control_group->controls[n]->name), 3, n*12 + 1);
@ -371,12 +363,13 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
dc.SetBrush(*wxGREY_BRUSH);
dc.DrawRectangle(31 + state * 30, 0, 2, 14);
((ControllerEmu::Slider*)g->control_group)->GetState(&state, 1);
double adj_state;
((ControllerEmu::Slider*)g->control_group)->GetState(&adj_state);
if (state)
{
dc.SetPen(*wxRED_PEN);
dc.SetBrush(*wxRED_BRUSH);
dc.DrawRectangle(31 + state * 30, 0, 2, 14);
dc.DrawRectangle(31 + adj_state * 30, 0, 2, 14);
}
// deadzone box
@ -388,6 +381,39 @@ void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
default:
break;
}
}
void InputConfigDialog::UpdateBitmaps(wxTimerEvent& WXUNUSED(event))
{
wxFont small_font(6, wxFONTFAMILY_DEFAULT, wxFONTSTYLE_NORMAL, wxFONTWEIGHT_BOLD);
g_controller_interface.UpdateInput();
// don't want game thread updating input when we are using it here
std::unique_lock<std::recursive_mutex> lk(g_controller_interface.update_lock, std::try_to_lock);
if (!lk.owns_lock())
return;
GamepadPage* const current_page = (GamepadPage*)m_pad_notebook->GetPage(m_pad_notebook->GetSelection());
for (ControlGroupBox* g : current_page->control_groups)
{
// if this control group has a bitmap
if (g->static_bitmap)
{
wxMemoryDC dc;
wxBitmap bitmap(g->static_bitmap->GetBitmap());
dc.SelectObject(bitmap);
dc.Clear();
dc.SetFont(small_font);
dc.SetTextForeground(0xC0C0C0);
// label for sticks and stuff
if (64 == bitmap.GetHeight())
dc.DrawText(StrToWxStr(g->control_group->name).Upper(), 4, 2);
DrawControlGroupBox(dc, g);
// box outline
// Windows XP color

View File

@ -1,86 +0,0 @@
#include <string>
#include <wx/checkbox.h>
#include <wx/defs.h>
#include <wx/dialog.h>
#include <wx/event.h>
#include <wx/gdicmn.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
#include <wx/textctrl.h>
#include <wx/translation.h>
#include "DolphinWX/UDPConfigDiag.h"
#include "DolphinWX/WxUtils.h"
#include "InputCommon/UDPWrapper.h"
class wxWindow;
UDPConfigDiag::UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp) :
wxDialog(parent, -1, _("UDP Wiimote")),
wrp(_wrp)
{
wxBoxSizer *const outer_sizer = new wxBoxSizer(wxVERTICAL);
wxBoxSizer *const sizer1 = new wxBoxSizer(wxVERTICAL);
wxStaticBoxSizer *const sizer2 = new wxStaticBoxSizer(wxVERTICAL, this, _("Update"));
outer_sizer->Add(sizer1, 0, wxTOP | wxLEFT | wxRIGHT | wxEXPAND, 5);
outer_sizer->Add(sizer2, 1, wxLEFT | wxRIGHT | wxEXPAND, 10);
enable = new wxCheckBox(this, wxID_ANY, _("Enable"));
butt = new wxCheckBox(this, wxID_ANY, _("Buttons"));
accel = new wxCheckBox(this, wxID_ANY, _("Acceleration"));
point = new wxCheckBox(this, wxID_ANY, _("IR Pointer"));
nun = new wxCheckBox(this, wxID_ANY, _("Nunchuk"));
nunaccel = new wxCheckBox(this, wxID_ANY, _("Nunchuk Acceleration"));
wxBoxSizer *const port_sizer = new wxBoxSizer(wxHORIZONTAL);
port_sizer->Add(new wxStaticText(this, wxID_ANY, _("UDP Port:")), 0, wxALIGN_CENTER);
port_tbox = new wxTextCtrl(this, wxID_ANY, StrToWxStr(wrp->port));
port_sizer->Add(port_tbox, 1, wxLEFT | wxEXPAND, 5);
enable->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeState, this);
butt->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeUpdateFlags, this);
accel->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeUpdateFlags, this);
point->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeUpdateFlags, this);
nun->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeUpdateFlags, this);
nunaccel->Bind(wxEVT_CHECKBOX, &UDPConfigDiag::ChangeUpdateFlags, this);
port_tbox->Bind(wxEVT_TEXT, &UDPConfigDiag::ChangeState, this);
enable->SetValue(wrp->udpEn);
butt->SetValue(wrp->updButt);
accel->SetValue(wrp->updAccel);
point->SetValue(wrp->updIR);
nun->SetValue(wrp->updNun);
nunaccel->SetValue(wrp->updNunAccel);
sizer1->Add(enable, 1, wxALL | wxEXPAND, 5);
sizer1->Add(port_sizer, 1, wxBOTTOM | wxLEFT| wxRIGHT | wxEXPAND, 5);
sizer2->Add(butt, 1, wxALL | wxEXPAND, 5);
sizer2->Add(accel, 1, wxALL | wxEXPAND, 5);
sizer2->Add(point, 1, wxALL | wxEXPAND, 5);
sizer2->Add(nun, 1, wxALL | wxEXPAND, 5);
sizer2->Add(nunaccel, 1, wxALL | wxEXPAND, 5);
outer_sizer->Add(CreateButtonSizer(wxOK), 0, wxALL | wxALIGN_RIGHT, 5);
SetSizerAndFit(outer_sizer);
Center();
SetFocus();
}
void UDPConfigDiag::ChangeUpdateFlags(wxCommandEvent & WXUNUSED(event))
{
wrp->updAccel=accel->GetValue();
wrp->updButt=butt->GetValue();
wrp->updIR=point->GetValue();
wrp->updNun=nun->GetValue();
wrp->updNunAccel=nunaccel->GetValue();
}
void UDPConfigDiag::ChangeState(wxCommandEvent & WXUNUSED(event))
{
wrp->udpEn = enable->GetValue();
wrp->port = WxStrToStr(port_tbox->GetValue());
wrp->Refresh();
}

View File

@ -1,27 +0,0 @@
#pragma once
#include <wx/dialog.h>
class UDPWrapper;
class wxCheckBox;
class wxCommandEvent;
class wxTextCtrl;
class wxWindow;
class UDPConfigDiag : public wxDialog
{
public:
UDPConfigDiag(wxWindow * const parent, UDPWrapper * _wrp);
private:
UDPWrapper * wrp;
void ChangeUpdateFlags(wxCommandEvent & event);
void ChangeState(wxCommandEvent & event);
void OKPressed(wxCommandEvent & event);
wxCheckBox * enable;
wxCheckBox * butt;
wxCheckBox * accel;
wxCheckBox * point;
wxCheckBox * nun;
wxCheckBox * nunaccel;
wxTextCtrl * port_tbox;
};

View File

@ -1,7 +1,5 @@
set(SRCS ControllerEmu.cpp
InputConfig.cpp
UDPWiimote.cpp
UDPWrapper.cpp
ControllerInterface/ControllerInterface.cpp
ControllerInterface/Device.cpp
ControllerInterface/ExpressionParser.cpp)

View File

@ -4,10 +4,6 @@
#include "InputCommon/ControllerEmu.h"
#if defined(HAVE_X11) && HAVE_X11
#include <X11/Xlib.h>
#endif
void ControllerEmu::UpdateReferences(ControllerInterface& devi)
{
for (auto& ctrlGroup : groups)
@ -47,6 +43,8 @@ void ControllerEmu::ControlGroup::LoadConfig(IniFile::Section *sec, const std::s
// settings
for (auto& s : settings)
{
if (s->is_virtual)
continue;
sec->Get(group + s->name, &s->value, s->default_value * 100);
s->value /= 100;
}
@ -103,7 +101,11 @@ void ControllerEmu::ControlGroup::SaveConfig(IniFile::Section *sec, const std::s
std::string group(base + name); group += "/";
for (auto& s : settings)
{
if (s->is_virtual)
continue;
sec->Set(group + s->name, s->value*100.0f, s->default_value*100.0f);
}
for (auto& c : controls)
{
@ -144,8 +146,6 @@ ControllerEmu::AnalogStick::AnalogStick(const char* const _name) : ControlGroup(
settings.emplace_back(new Setting(_trans("Radius"), 0.7f, 0, 100));
settings.emplace_back(new Setting(_trans("Dead Zone"), 0, 0, 50));
settings.emplace_back(new Setting(_trans("Square Stick"), 0));
}
ControllerEmu::Buttons::Buttons(const std::string& _name) : ControlGroup(_name, GROUP_TYPE_BUTTONS)
@ -185,8 +185,7 @@ ControllerEmu::Force::Force(const std::string& _name) : ControlGroup(_name, GROU
settings.emplace_back(new Setting(_trans("Dead Zone"), 0, 0, 50));
}
ControllerEmu::Tilt::Tilt(const std::string& _name)
: ControlGroup(_name, GROUP_TYPE_TILT)
ControllerEmu::Tilt::Tilt(const std::string& _name) : ControlGroup(_name, GROUP_TYPE_TILT)
{
memset(m_tilt, 0, sizeof(m_tilt));

View File

@ -14,6 +14,7 @@
#include <vector>
#include "Common/IniFile.h"
#include "Core/ConfigManager.h"
#include "InputCommon/GCPadStatus.h"
#include "InputCommon/ControllerInterface/ControllerInterface.h"
@ -30,7 +31,6 @@ enum
GROUP_TYPE_TILT,
GROUP_TYPE_CURSOR,
GROUP_TYPE_TRIGGERS,
GROUP_TYPE_UDPWII,
GROUP_TYPE_SLIDER,
};
@ -38,7 +38,6 @@ enum
{
SETTING_RADIUS,
SETTING_DEADZONE,
SETTING_SQUARE,
};
const char* const named_directions[] =
@ -96,12 +95,43 @@ public:
, value(def_value)
, default_value(def_value)
, low(_low)
, high(_high){}
, high(_high)
, is_virtual(false) {}
const std::string name;
ControlState value;
const ControlState default_value;
const unsigned int low, high;
bool is_virtual;
virtual void SetValue(ControlState new_value)
{
value = new_value;
}
virtual ControlState GetValue()
{
return value;
}
};
class BackgroundInputSetting : public Setting
{
public:
BackgroundInputSetting(const std::string &_name) : Setting(_name, false)
{
is_virtual = true;
}
void SetValue(ControlState new_value) override
{
SConfig::GetInstance().m_BackgroundInput = new_value;
}
ControlState GetValue() override
{
return SConfig::GetInstance().m_BackgroundInput;
}
};
ControlGroup(const std::string& _name, const unsigned int _type = GROUP_TYPE_OTHER) : name(_name), type(_type) {}
@ -121,66 +151,41 @@ public:
class AnalogStick : public ControlGroup
{
public:
AnalogStick(const char* const _name);
template <typename C>
void GetState(C* const x, C* const y, const unsigned int base, const unsigned int range)
void GetState(double* const x, double* const y)
{
// this is all a mess
ControlState yy = controls[0]->control_ref->State() - controls[1]->control_ref->State();
ControlState xx = controls[3]->control_ref->State() - controls[2]->control_ref->State();
ControlState radius = settings[SETTING_RADIUS]->value;
ControlState deadzone = settings[SETTING_DEADZONE]->value;
ControlState square = settings[SETTING_SQUARE]->value;
ControlState m = controls[4]->control_ref->State();
// modifier code
if (m)
{
yy = (fabsf(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (fabsf(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / square stick code
if (radius != 1 || deadzone || square)
{
// this section might be all wrong, but its working good enough, I think
ControlState ang = atan2(yy, xx);
ControlState ang_sin = sin(ang);
ControlState ang_cos = cos(ang);
// the amt a full square stick would have at current angle
ControlState square_full = std::min(ang_sin ? 1/fabsf(ang_sin) : 2, ang_cos ? 1/fabsf(ang_cos) : 2);
// the amt a full stick would have that was ( user setting squareness) at current angle
// I think this is more like a pointed circle rather than a rounded square like it should be
ControlState stick_full = (1 + (square_full - 1) * square);
ControlState dist = sqrt(xx*xx + yy*yy);
// dead zone code
dist = std::max(0.0f, dist - deadzone * stick_full);
dist = std::max(0.0f, dist - deadzone);
dist /= (1 - deadzone);
// square stick code
ControlState amt = dist / stick_full;
dist -= ((square_full - 1) * amt * square);
// radius
dist *= radius;
// The modifier halves the distance by 50%, which is useful
// for keyboard controls.
if (m)
dist *= 0.5;
yy = std::max(-1.0f, std::min(1.0f, ang_sin * dist));
xx = std::max(-1.0f, std::min(1.0f, ang_cos * dist));
*y = yy;
*x = xx;
}
*y = C(yy * range + base);
*x = C(xx * range + base);
}
AnalogStick(const char* const _name);
};
class Buttons : public ControlGroup
@ -205,64 +210,55 @@ public:
class MixedTriggers : public ControlGroup
{
public:
MixedTriggers(const std::string& _name);
template <typename C, typename S>
void GetState(C* const digital, const C* bitmasks, S* analog, const unsigned int range)
void GetState(u16 *const digital, const u16* bitmasks, double* analog)
{
const unsigned int trig_count = ((unsigned int) (controls.size() / 2));
for (unsigned int i=0; i<trig_count; ++i,++bitmasks,++analog)
{
if (controls[i]->control_ref->State() > settings[0]->value) //threshold
{
*analog = range;
*analog = 1.0;
*digital |= *bitmasks;
}
else
{
*analog = S(controls[i+trig_count]->control_ref->State() * range);
*analog = controls[i+trig_count]->control_ref->State();
}
}
}
MixedTriggers(const std::string& _name);
};
class Triggers : public ControlGroup
{
public:
Triggers(const std::string& _name);
template <typename S>
void GetState(S* analog, const unsigned int range)
void GetState(double* analog)
{
const unsigned int trig_count = ((unsigned int) (controls.size()));
const ControlState deadzone = settings[0]->value;
for (unsigned int i=0; i<trig_count; ++i,++analog)
*analog = S(std::max(controls[i]->control_ref->State() - deadzone, 0.0f) / (1 - deadzone) * range);
*analog = std::max(controls[i]->control_ref->State() - deadzone, 0.0f) / (1 - deadzone);
}
Triggers(const std::string& _name);
};
class Slider : public ControlGroup
{
public:
Slider(const std::string& _name);
template <typename S>
void GetState(S* const slider, const unsigned int range, const unsigned int base = 0)
void GetState(double* const slider)
{
const float deadzone = settings[0]->value;
const float state = controls[1]->control_ref->State() - controls[0]->control_ref->State();
if (fabsf(state) > deadzone)
*slider = (S)((state - (deadzone * sign(state))) / (1 - deadzone) * range + base);
*slider = (state - (deadzone * sign(state))) / (1 - deadzone);
else
*slider = 0;
}
Slider(const std::string& _name);
};
class Force : public ControlGroup
@ -270,8 +266,7 @@ public:
public:
Force(const std::string& _name);
template <typename C, typename R>
void GetState(C* axis, const u8 base, const R range)
void GetState(double* axis)
{
const float deadzone = settings[0]->value;
for (unsigned int i=0; i<6; i+=2)
@ -282,7 +277,7 @@ public:
tmpf = ((state - (deadzone * sign(state))) / (1 - deadzone));
float &ax = m_swing[i >> 1];
*axis++ = (C)((tmpf - ax) * range + base);
*axis++ = (tmpf - ax);
ax = tmpf;
}
}
@ -296,8 +291,7 @@ public:
public:
Tilt(const std::string& _name);
template <typename C, typename R>
void GetState(C* const x, C* const y, const unsigned int base, const R range, const bool step = true)
void GetState(double* const x, double* const y, const bool step = true)
{
// this is all a mess
@ -309,16 +303,7 @@ public:
auto const angle = settings[2]->value / 1.8f;
ControlState m = controls[4]->control_ref->State();
// modifier code
if (m)
{
yy = (fabsf(yy)>deadzone) * sign(yy) * (m + deadzone/2);
xx = (fabsf(xx)>deadzone) * sign(xx) * (m + deadzone/2);
}
// deadzone / circle stick code
if (deadzone || circle)
{
// this section might be all wrong, but its working good enough, I think
ControlState ang = atan2(yy, xx);
@ -342,9 +327,11 @@ public:
ControlState amt = dist / stick_full;
dist += (square_full - 1) * amt * circle;
if (m)
dist *= 0.5;
yy = std::max(-1.0f, std::min(1.0f, ang_sin * dist));
xx = std::max(-1.0f, std::min(1.0f, ang_cos * dist));
}
// this is kinda silly here
// gui being open will make this happen 2x as fast, o well
@ -363,8 +350,8 @@ public:
m_tilt[1] = std::max(m_tilt[1] - 0.1f, yy);
}
*y = C(m_tilt[1] * angle * range + base);
*x = C(m_tilt[0] * angle * range + base);
*y = m_tilt[1] * angle;
*x = m_tilt[0] * angle;
}
private:
@ -376,8 +363,7 @@ public:
public:
Cursor(const std::string& _name);
template <typename C>
void GetState(C* const x, C* const y, C* const z, const bool adjusted = false)
void GetState(double* const x, double* const y, double* const z, const bool adjusted = false)
{
const float zz = controls[4]->control_ref->State() - controls[5]->control_ref->State();
@ -425,7 +411,7 @@ public:
~Extension() {}
void GetState(u8* const data, const bool focus = true);
void GetState(u8* const data);
std::vector<std::unique_ptr<ControllerEmu>> attachments;

View File

@ -5,6 +5,12 @@
#include <sstream>
#include <string>
// For InputGateOn()
// This is a really bad layering violation, but it's the cleanest
// place I could find to put it.
#include "Core/ConfigManager.h"
#include "Core/Host.h"
#include "InputCommon/ControllerInterface/Device.h"
namespace ciface
@ -74,6 +80,16 @@ void Device::ClearInputState()
// kinda slow but, w/e, should only happen when user unplugs a device while playing
}
bool Device::Control::InputGateOn()
{
if (SConfig::GetInstance().m_BackgroundInput)
return true;
else if (Host_RendererHasFocus())
return true;
else
return false;
}
//
// DeviceQualifier :: ToString
//

View File

@ -42,6 +42,8 @@ public:
virtual std::string GetName() const = 0;
virtual ~Control() {}
bool InputGateOn();
virtual Input* ToInput() { return nullptr; }
virtual Output* ToOutput() { return nullptr; }
};
@ -59,6 +61,16 @@ public:
virtual ControlState GetState() const = 0;
bool ShouldHaveInput();
ControlState GetGatedState()
{
if (InputGateOn())
return GetState();
else
return 0.0;
}
Input* ToInput() override { return this; }
};
@ -74,6 +86,12 @@ public:
virtual void SetState(ControlState state) = 0;
void SetGatedState(ControlState state)
{
if (InputGateOn())
SetState(state);
}
Output* ToOutput() override { return this; }
};

View File

@ -228,12 +228,12 @@ public:
virtual ControlState GetValue() override
{
return control->ToInput()->GetState();
return control->ToInput()->GetGatedState();
}
virtual void SetValue(ControlState value) override
{
control->ToOutput()->SetState(value);
control->ToOutput()->SetGatedState(value);
}
virtual int CountNumControls() override

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="12.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|x64">
@ -48,8 +48,6 @@
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader>Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="UDPWiimote.cpp" />
<ClCompile Include="UDPWrapper.cpp" />
</ItemGroup>
<ItemGroup>
<ClInclude Include="ControllerEmu.h" />
@ -64,8 +62,6 @@
<ClInclude Include="GCPadStatus.h" />
<ClInclude Include="InputConfig.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="UDPWiimote.h" />
<ClInclude Include="UDPWrapper.h" />
</ItemGroup>
<ItemGroup>
<Text Include="CMakeLists.txt" />

View File

@ -1,4 +1,4 @@
<?xml version="1.0" encoding="utf-8"?>
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="ControllerInterface">
@ -17,8 +17,6 @@
<ItemGroup>
<ClCompile Include="ControllerEmu.cpp" />
<ClCompile Include="InputConfig.cpp" />
<ClCompile Include="UDPWiimote.cpp" />
<ClCompile Include="UDPWrapper.cpp" />
<ClCompile Include="ControllerInterface\DInput\DInput.cpp">
<Filter>ControllerInterface\DInput</Filter>
</ClCompile>
@ -49,8 +47,6 @@
<ClInclude Include="ControllerEmu.h" />
<ClInclude Include="GCPadStatus.h" />
<ClInclude Include="InputConfig.h" />
<ClInclude Include="UDPWiimote.h" />
<ClInclude Include="UDPWrapper.h" />
<ClInclude Include="ControllerInterface\DInput\DInput.h">
<Filter>ControllerInterface\DInput</Filter>
</ClInclude>

View File

@ -1,439 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include <ctime>
#include <functional>
#include <list>
#include <string>
#include "Common/Thread.h"
#include "Common/Timer.h"
#include "InputCommon/UDPWiimote.h"
#ifdef _WIN32
#include <winsock2.h>
#include <ws2tcpip.h>
#define sock_t SOCKET
#define ERRNO WSAGetLastError()
#undef EWOULDBLOCK
#define EWOULDBLOCK WSAEWOULDBLOCK
#define BAD_SOCK INVALID_SOCKET
#define close(x) closesocket(x)
#define cleanup do {noinst--; if (noinst==0) WSACleanup();} while (0)
#define blockingoff(sock) ioctlsocket(sock, FIONBIO, &iMode)
#define dataz char*
#ifdef _MSC_VER
#pragma comment (lib, "Ws2_32.lib")
#endif
#else
#include <unistd.h>
#include <errno.h>
#include <sys/types.h>
#include <sys/socket.h>
#include <netinet/in.h>
#include <arpa/inet.h>
#include <netdb.h>
#include <unistd.h>
#include <fcntl.h>
#define BAD_SOCK -1
#define ERRNO errno
#define cleanup noinst--
#define blockingoff(sock) fcntl(sock, F_SETFL, O_NONBLOCK)
#define dataz void*
#define sock_t int
#endif
struct UDPWiimote::_d
{
std::thread thread;
std::list<sock_t> sockfds;
std::mutex termLock, mutex, nameMutex;
volatile bool exit;
sock_t bipv4_fd, bipv6_fd;
};
int UDPWiimote::noinst = 0;
UDPWiimote::UDPWiimote(const std::string& _port, const std::string& name, int _index) :
port(_port), displayName(name), d(new _d),
waX(0), waY(0), waZ(1), naX(0), naY(0), naZ(-1), nunX(0), nunY(0),
pointerX(1001.0f / 2), pointerY(0), nunMask(0), wiimoteMask(0), index(_index), int_port(atoi(_port.c_str()))
{
static bool sranded=false;
if (!sranded)
{
srand((unsigned int)time(nullptr));
sranded=true;
}
bcastMagic=rand() & 0xFFFF;
#ifdef _WIN32
u_long iMode = 1;
#endif
struct addrinfo hints, *servinfo, *p;
int rv;
#ifdef _WIN32
if (noinst==0)
{
WORD sockVersion;
WSADATA wsaData;
sockVersion = MAKEWORD(2, 2);
WSAStartup(sockVersion, &wsaData);
}
#endif
noinst++;
memset(&hints, 0, sizeof hints);
hints.ai_family = AF_INET;
hints.ai_socktype = SOCK_DGRAM;
hints.ai_flags = AI_PASSIVE; // use my IP
if (!int_port)
{
cleanup;
err=-1;
return;
}
if ((rv = getaddrinfo(nullptr, _port.c_str(), &hints, &servinfo)) != 0)
{
cleanup;
err=-1;
return;
}
// loop through all the results and bind to everything we can
for (p = servinfo; p != nullptr; p = p->ai_next)
{
sock_t sock;
if ((sock = socket(p->ai_family, p->ai_socktype, p->ai_protocol)) == BAD_SOCK)
{
continue;
}
if (bind(sock, p->ai_addr, (int)p->ai_addrlen) == -1)
{
close(sock);
continue;
}
d->sockfds.push_back(sock);
}
if (d->sockfds.empty())
{
cleanup;
err=-2;
return;
}
freeaddrinfo(servinfo);
err=0;
d->exit=false;
initBroadcastIPv4();
initBroadcastIPv6();
std::lock_guard<std::mutex> lk(d->termLock);
d->thread = std::thread(std::mem_fn(&UDPWiimote::mainThread), this);
return;
}
void UDPWiimote::mainThread()
{
std::unique_lock<std::mutex> lk(d->termLock);
Common::Timer time;
fd_set fds;
struct timeval timeout;
timeout.tv_sec=0;
timeout.tv_usec=0;
time.Update();
do
{
int maxfd=0;
FD_ZERO(&fds);
for (auto& fd : d->sockfds)
{
FD_SET(fd,&fds);
#ifndef _WIN32
if (fd>=maxfd)
maxfd=(fd)+1;
#endif
}
u64 tleft=timeout.tv_sec*1000+timeout.tv_usec/1000;
u64 telapsed=time.GetTimeDifference();
time.Update();
if (tleft<=telapsed)
{
timeout.tv_sec=1;
timeout.tv_usec=500000;
broadcastPresence();
}
else
{
tleft-=telapsed;
timeout.tv_sec=(long)(tleft/1000);
timeout.tv_usec=(tleft%1000)*1000;
}
lk.unlock(); //VERY hacky. don't like it
if (d->exit) return;
int rt=select(maxfd,&fds,nullptr,nullptr,&timeout);
if (d->exit) return;
lk.lock();
if (d->exit) return;
if (rt)
{
for (sock_t fd : d->sockfds)
{
if (FD_ISSET(fd,&fds))
{
u8 bf[64];
int size=60;
size_t addr_len;
struct sockaddr_storage their_addr;
addr_len = sizeof their_addr;
if ((size = recvfrom(fd,
(dataz)bf,
size , 0,(struct sockaddr *)&their_addr, (socklen_t*)&addr_len)) == -1)
{
ERROR_LOG(WIIMOTE,"UDPWii Packet error");
}
else
{
std::lock_guard<std::mutex> lkm(d->mutex);
if (pharsePacket(bf,size)==0)
{
//NOTICE_LOG(WIIMOTE,"UDPWII New pack");
}
else
{
//NOTICE_LOG(WIIMOTE,"UDPWII Wrong pack format... ignoring");
}
}
}
}
}
} while (!(d->exit));
}
UDPWiimote::~UDPWiimote()
{
d->exit = true;
{
std::lock_guard<std::mutex> lk(d->termLock);
d->thread.join();
}
for (auto& elem : d->sockfds)
close(elem);
close(d->bipv4_fd);
close(d->bipv6_fd);
cleanup;
delete d;
}
#define ACCEL_FLAG (1 << 0)
#define BUTT_FLAG (1 << 1)
#define IR_FLAG (1 << 2)
#define NUN_FLAG (1 << 3)
#define NUNACCEL_FLAG (1 << 4)
int UDPWiimote::pharsePacket(u8 * bf, size_t size)
{
if (size < 3)
return -1;
if (bf[0] != 0xde)
return -1;
//if (bf[1]==0)
// time=0;
//if (bf[1]<time) //NOT LONGER NEEDED TO ALLOW MULTIPLE IPHONES ON A SINGLE PORT
// return -1;
//time=bf[1];
u32 *p=(u32*)(&bf[3]);
if (bf[2] & ACCEL_FLAG)
{
if ((size-(((u8*)p)-bf)) < 12)
return -1;
double ux,uy,uz;
ux=(double)((s32)ntohl(*p)); p++;
uy=(double)((s32)ntohl(*p)); p++;
uz=(double)((s32)ntohl(*p)); p++;
waX=ux/1048576; //packet accel data
waY=uy/1048576;
waZ=uz/1048576;
}
if (bf[2] & BUTT_FLAG)
{
if ((size-(((u8*)p)-bf)) < 4)
return -1;
wiimoteMask = ntohl(*p); p++;
}
if (bf[2] & IR_FLAG)
{
if ((size-(((u8*)p)-bf)) < 8)
return -1;
pointerX=((double)((s32)ntohl(*p)))/1048576; p++;
pointerY=((double)((s32)ntohl(*p)))/1048576; p++;
}
if (bf[2] & NUN_FLAG)
{
if ((size-(((u8*)p)-bf)) < 9)
return -1;
nunMask=*((u8*)p); p=(u32*)(((u8*)p)+1);
nunX=((double)((s32)ntohl(*p)))/1048576; p++;
nunY=((double)((s32)ntohl(*p)))/1048576; p++;
}
if (bf[2] & NUNACCEL_FLAG)
{
if ((size-(((u8*)p)-bf)) < 12)
return -1;
double ux,uy,uz;
ux=(double)((s32)ntohl(*p)); p++;
uy=(double)((s32)ntohl(*p)); p++;
uz=(double)((s32)ntohl(*p)); p++;
naX=ux/1048576; //packet accel data
naY=uy/1048576;
naZ=uz/1048576;
}
return 0;
}
void UDPWiimote::initBroadcastIPv4()
{
d->bipv4_fd=socket(AF_INET, SOCK_DGRAM, 0);
if (d->bipv4_fd == BAD_SOCK)
{
WARN_LOG(WIIMOTE,"socket() failed");
return;
}
int broad=1;
if (setsockopt(d->bipv4_fd,SOL_SOCKET,SO_BROADCAST, (const dataz)(&broad), sizeof broad) == -1)
{
WARN_LOG(WIIMOTE,"setsockopt(SO_BROADCAST) failed");
return;
}
}
void UDPWiimote::broadcastIPv4(const void * data, size_t size)
{
struct sockaddr_in their_addr;
their_addr.sin_family = AF_INET;
their_addr.sin_port = htons(4431);
their_addr.sin_addr.s_addr = INADDR_BROADCAST;
memset(their_addr.sin_zero, '\0', sizeof their_addr.sin_zero);
int num;
if ((num=sendto(d->bipv4_fd,(const dataz)data,(int)size,0,(struct sockaddr *) &their_addr, sizeof their_addr)) == -1)
{
WARN_LOG(WIIMOTE,"sendto() failed");
return;
}
}
void UDPWiimote::initBroadcastIPv6()
{
//TODO: IPv6 support
}
void UDPWiimote::broadcastIPv6(const void * data, size_t size)
{
//TODO: IPv6 support
}
void UDPWiimote::broadcastPresence()
{
size_t slen;
u8 bf[512];
bf[0]=0xdf; //magic number
*((u16*)(&(bf[1])))=htons(bcastMagic); //unique per-wiimote 16-bit ID
bf[3]=(u8)index; //wiimote index
*((u16*)(&(bf[4])))=htons(int_port); //port
{
std::lock_guard<std::mutex> lk(d->nameMutex);
slen=displayName.size();
if (slen>=256)
slen=255;
bf[6]=(u8)slen; //display name size (max 255)
memcpy(&(bf[7]),displayName.c_str(),slen); //display name
}
broadcastIPv4(bf,7+slen);
broadcastIPv6(bf,7+slen);
}
void UDPWiimote::getAccel(float* x, float* y, float* z)
{
std::lock_guard<std::mutex> lk(d->mutex);
*x = (float)waX;
*y = (float)waY;
*z = (float)waZ;
}
u32 UDPWiimote::getButtons()
{
u32 msk;
std::lock_guard<std::mutex> lk(d->mutex);
msk = wiimoteMask;
return msk;
}
void UDPWiimote::getIR(float* x, float* y)
{
std::lock_guard<std::mutex> lk(d->mutex);
*x = (float)pointerX;
*y = (float)pointerY;
}
void UDPWiimote::getNunchuck(float* x, float* y, u8* mask)
{
std::lock_guard<std::mutex> lk(d->mutex);
*x = (float)nunX;
*y = (float)nunY;
*mask = nunMask;
}
void UDPWiimote::getNunchuckAccel(float* x, float* y, float* z)
{
std::lock_guard<std::mutex> lk(d->mutex);
*x = (float)naX;
*y = (float)naY;
*z = (float)naZ;
}
const std::string& UDPWiimote::getPort()
{
return port;
}
void UDPWiimote::changeName(const std::string& name)
{
std::lock_guard<std::mutex> lk(d->nameMutex);
displayName = name;
}

View File

@ -1,64 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <string>
#include "Common/Common.h"
#define UDPWM_B1 (1<<0)
#define UDPWM_B2 (1<<1)
#define UDPWM_BA (1<<2)
#define UDPWM_BB (1<<3)
#define UDPWM_BP (1<<4)
#define UDPWM_BM (1<<5)
#define UDPWM_BH (1<<6)
#define UDPWM_BU (1<<7)
#define UDPWM_BD (1<<8)
#define UDPWM_BL (1<<9)
#define UDPWM_BR (1<<10)
#define UDPWM_SK (1<<11)
#define UDPWM_NC (1<<0)
#define UDPWM_NZ (1<<1)
class UDPWiimote
{
public:
UDPWiimote(const std::string& port, const std::string& name, int index);
virtual ~UDPWiimote();
void getAccel(float* x, float* y, float* z);
u32 getButtons();
void getNunchuck(float* x, float* y, u8* mask);
void getIR(float* x, float* y);
void getNunchuckAccel(float* x, float* y, float* z);
int getErrNo()
{
return err;
}
const std::string& getPort();
void changeName(const std::string& name);
void mainThread();
private:
std::string port,displayName;
int pharsePacket(u8* data, size_t size);
struct _d; //using pimpl because Winsock2.h doesn't have include guards -_-
_d* d;
double waX, waY, waZ;
double naX, naY, naZ;
double nunX, nunY;
double pointerX, pointerY;
u8 nunMask;
u32 wiimoteMask;
u16 bcastMagic;
int err;
int index;
int int_port;
static int noinst;
void broadcastPresence();
void broadcastIPv4(const void* data, size_t size);
void broadcastIPv6(const void* data, size_t size);
void initBroadcastIPv4();
void initBroadcastIPv6();
};

View File

@ -1,96 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#include <cstdio>
#include <cstdlib>
#include <cstring>
#include "InputCommon/UDPWrapper.h"
static const std::string DefaultPort(const int index)
{
static std::string s;
s = "443";
s += (char)('2' + index);
return s;
}
UDPWrapper::UDPWrapper(int indx, const char* const _name) :
ControllerEmu::ControlGroup(_name,GROUP_TYPE_UDPWII),
inst(nullptr), index(indx),
updIR(false),updAccel(false),
updButt(false),udpEn(false)
, port(DefaultPort(indx))
{
//PanicAlert("UDPWrapper #%d ctor",index);
}
void UDPWrapper::LoadConfig(IniFile::Section *sec, const std::string& defdev, const std::string& base )
{
ControlGroup::LoadConfig(sec,defdev,base);
std::string group( base + name ); group += "/";
int _updAccel,_updIR,_updButt,_udpEn,_updNun,_updNunAccel;
sec->Get(group + "Enable",&_udpEn, 0);
sec->Get(group + "Port", &port, DefaultPort(index));
sec->Get(group + "Update_Accel", &_updAccel, 1);
sec->Get(group + "Update_IR", &_updIR, 1);
sec->Get(group + "Update_Butt", &_updButt, 1);
sec->Get(group + "Update_Nunchuk", &_updNun, 1);
sec->Get(group + "Update_NunchukAccel", &_updNunAccel, 0);
udpEn=(_udpEn>0);
updAccel=(_updAccel>0);
updIR=(_updIR>0);
updButt=(_updButt>0);
updNun=(_updNun>0);
updNunAccel=(_updNunAccel>0);
Refresh();
}
void UDPWrapper::SaveConfig(IniFile::Section *sec, const std::string& defdev, const std::string& base )
{
ControlGroup::SaveConfig(sec,defdev,base);
std::string group( base + name ); group += "/";
sec->Set(group + "Enable", (int)udpEn, 0);
sec->Set(group + "Port", port, DefaultPort(index));
sec->Set(group + "Update_Accel", (int)updAccel, 1);
sec->Set(group + "Update_IR", (int)updIR, 1);
sec->Set(group + "Update_Butt", (int)updButt, 1);
sec->Set(group + "Update_Nunchuk", (int)updNun, 1);
sec->Set(group + "Update_NunchukAccel", (int)updNunAccel, 0);
}
void UDPWrapper::Refresh()
{
bool udpAEn=(inst!=nullptr);
if (udpEn && udpAEn)
{
if (inst->getPort() == port)
{
delete inst;
inst = new UDPWiimote(port, "Dolphin-Emu", index); //TODO: Changeable display name
}
return;
}
if (!udpEn)
{
if (inst)
delete inst;
inst = nullptr;
return;
}
//else
inst = new UDPWiimote(port, "Dolphin-Emu", index);
}
UDPWrapper::~UDPWrapper()
{
if (inst)
delete inst;
}

View File

@ -1,27 +0,0 @@
// Copyright 2013 Dolphin Emulator Project
// Licensed under GPLv2
// Refer to the license.txt file included.
#pragma once
#include <string>
#include "Common/Common.h"
#include "Common/IniFile.h"
#include "InputCommon/ControllerEmu.h"
#include "InputCommon/UDPWiimote.h"
class UDPWrapper : public ControllerEmu::ControlGroup
{
public:
UDPWiimote * inst;
int index;
bool updIR, updAccel, updButt, updNun, updNunAccel, udpEn; //upd from update and udp from... well... UDP
std::string port;
UDPWrapper(int index, const char* const _name);
virtual void LoadConfig(IniFile::Section *sec, const std::string& defdev = "", const std::string& base = "") override;
virtual void SaveConfig(IniFile::Section *sec, const std::string& defdev = "", const std::string& base = "") override;
void Refresh();
virtual ~UDPWrapper();
};