Wiimote: Improved the emulated Wiimote, added gamepad controls for analog tilting.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2207 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
John Peterson 2009-02-10 17:25:08 +00:00
parent 4d57101e29
commit 516a14150a
18 changed files with 491 additions and 132 deletions

View File

@ -94,6 +94,7 @@ float SquareDistance(float deg)
deg = abs(deg);
if( (deg > 45 && deg < 135) ) deg = deg - 90;
// Calculate radians from degrees
float rad = deg * M_PI / 180;
float val = abs(cos(rad));

View File

@ -542,6 +542,10 @@
RelativePath=".\Src\EmuDefinitions.h"
>
</File>
<File
RelativePath=".\Src\EmuDynamics.cpp"
>
</File>
<File
RelativePath=".\Src\EmuMain.cpp"
>

View File

@ -26,6 +26,7 @@ Config g_Config;
Config::Config()
{
// Set all default values to zero
memset(this, 0, sizeof(Config));
}
@ -60,6 +61,8 @@ void Config::Load(bool ChangePad)
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
std::string SectionName = StringFromFormat("Wiimote%i", i + 1);
iniFile.Get(SectionName.c_str(), "NoTriggerFilter", &bNoTriggerFilter, false);
iniFile.Get(SectionName.c_str(), "TriggerType", &Trigger.Type, TRIGGER_OFF);
iniFile.Get(SectionName.c_str(), "TriggerRange", &Trigger.Range, 50);
// Don't update this when we are loading settings from the ConfigBox
if(!ChangePad)
@ -67,6 +70,9 @@ void Config::Load(bool ChangePad)
iniFile.Get(SectionName.c_str(), "DeviceID", &WiiMoteEmu::PadMapping[i].ID, 0);
iniFile.Get(SectionName.c_str(), "Enabled", &WiiMoteEmu::PadMapping[i].enabled, true);
}
// Check if the pad ID is within the range of avaliable pads
if (WiiMoteEmu::PadMapping[i].ID > (WiiMoteEmu::NumPads - 1)) WiiMoteEmu::PadMapping[i].ID = (WiiMoteEmu::NumPads - 1);
// ===================
// ==================================================================
@ -86,18 +92,18 @@ void Config::Load(bool ChangePad)
iniFile.Get(SectionName.c_str(), "left_y", &WiiMoteEmu::PadMapping[i].Axis.Ly, 1);
iniFile.Get(SectionName.c_str(), "right_x", &WiiMoteEmu::PadMapping[i].Axis.Rx, 2);
iniFile.Get(SectionName.c_str(), "right_y", &WiiMoteEmu::PadMapping[i].Axis.Ry, 3);
iniFile.Get(SectionName.c_str(), "l_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tl, 4);
iniFile.Get(SectionName.c_str(), "r_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tr, 5);
iniFile.Get(SectionName.c_str(), "l_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tl, 1004);
iniFile.Get(SectionName.c_str(), "r_trigger", &WiiMoteEmu::PadMapping[i].Axis.Tr, 1005);
iniFile.Get(SectionName.c_str(), "DeadZone", &WiiMoteEmu::PadMapping[i].deadzone, 0);
iniFile.Get(SectionName.c_str(), "TriggerType", &WiiMoteEmu::PadMapping[i].triggertype, 0);
iniFile.Get(SectionName.c_str(), "Diagonal", &WiiMoteEmu::PadMapping[i].SDiagonal, "100%");
iniFile.Get(SectionName.c_str(), "SquareToCircle", &WiiMoteEmu::PadMapping[i].bSquareToCircle, false);
iniFile.Get(SectionName.c_str(), "SquareToCircle", &WiiMoteEmu::PadMapping[i].bSquareToCircle, false);
}
// =============================
Console::Print("Load()\n");
}
void Config::Save()
void Config::Save(int Slot)
{
IniFile iniFile;
iniFile.Load(FULL_CONFIG_DIR "Wiimote.ini");
@ -124,7 +130,9 @@ void Config::Save()
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
std::string SectionName = StringFromFormat("Wiimote%i", i + 1);
iniFile.Set(SectionName.c_str(), "Enabled", WiiMoteEmu::PadMapping[i].enabled);
iniFile.Set(SectionName.c_str(), "NoTriggerFilter", bNoTriggerFilter);
iniFile.Set(SectionName.c_str(), "NoTriggerFilter", bNoTriggerFilter);
iniFile.Set(SectionName.c_str(), "TriggerType", Trigger.Type);
iniFile.Set(SectionName.c_str(), "TriggerRange", Trigger.Range);
// Save the physical device ID number
iniFile.Set(SectionName.c_str(), "DeviceID", WiiMoteEmu::PadMapping[i].ID);

View File

@ -22,7 +22,21 @@ struct Config
{
Config();
void Load(bool ChangePad = false);
void Save();
void Save(int Slot = -1);
struct PadTrigger
{
int Type;
int Range;
};
enum ETriggerType
{
TRIGGER_OFF = 0,
KEYBOARD,
ANALOG,
TRIGGER
};
// Emulated Wiimote
bool bSidewaysDPad;
@ -36,6 +50,7 @@ struct Config
// Gamepad
bool bNoTriggerFilter;
PadTrigger Trigger;
};
extern Config g_Config;

View File

@ -101,6 +101,10 @@ BEGIN_EVENT_TABLE(ConfigDialog,wxDialog)
// Gamepad
EVT_COMBOBOX(ID_TRIGGER_TYPE, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_TILT_INPUT, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(ID_TILT_RANGE, ConfigDialog::GeneralSettingsChanged)
EVT_COMBOBOX(IDC_JOYNAME, ConfigDialog::GeneralSettingsChanged)
EVT_BUTTON(IDB_ANALOG_LEFT_X, ConfigDialog::GetButtons)
EVT_BUTTON(IDB_ANALOG_LEFT_Y, ConfigDialog::GetButtons)
@ -251,6 +255,47 @@ void ConfigDialog::UpdateOnce(wxTimerEvent& event)
//////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// Save Settings
/* ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
Saving is currently done when:
1. Closing the configuration window
2. Changing the gamepad
3. When the gamepad is enabled or disbled
Input: ChangePad needs to be used when we change the pad for a slot. Slot needs to be used when
we only want to save changes to one slot.
*/
void ConfigDialog::DoSave(bool ChangePad, int Slot)
{
// Replace "" with "-1" before we are saving
ToBlank(false);
if(ChangePad)
{
// Since we are selecting the pad to save to by the Id we can't update it when we change the pad
for(int i = 0; i < 4; i++) SaveButtonMapping(i, true);
g_Config.Save(Slot);
// Now we can update the ID
WiiMoteEmu::PadMapping[Page].ID = m_Joyname[Page]->GetSelection();
}
else
{
// Update PadMapping[] from the GUI controls
for(int i = 0; i < 4; i++) SaveButtonMapping(i);
g_Config.Save(Slot);
}
// Then change it back to ""
ToBlank();
}
//////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Bitmap box and dot
// ----------------
@ -338,11 +383,12 @@ void ConfigDialog::CreateGUIControls()
// The tilt list
wxArrayString StrTilt;
StrTilt.Add(wxString::FromAscii("<Off>"));
StrTilt.Add(wxString::FromAscii("Keyboard"));
StrTilt.Add(wxString::FromAscii("Analog stick"));
StrTilt.Add(wxString::FromAscii("Triggers"));
StrTilt.Add(wxString::FromAscii("Keyboard"));
// The range is in degrees and are set at even 5 degrees values
wxArrayString StrTiltRange;
for (int i = 3; i < 15; i++) StrTiltRange.Add(wxString::Format(wxT("%i"), i*5));
for (int i = 2; i < 19; i++) StrTiltRange.Add(wxString::Format(wxT("%i"), i*5));
// The Trigger type list
wxArrayString StrTriggerType;
@ -463,23 +509,27 @@ void ConfigDialog::CreateGUIControls()
// -----------------------------
/**/
// Controls
m_TiltCombo[i] = new wxComboBox(m_Controller[i], ID_TILT_COMBO, StrTilt[0], wxDefaultPosition, wxDefaultSize, StrTilt, wxCB_READONLY);
m_TiltComboRange[i] = new wxComboBox(m_Controller[i], wxID_ANY, StrTiltRange[0], wxDefaultPosition, wxDefaultSize, StrTiltRange, wxCB_READONLY);
m_TiltComboInput[i] = new wxComboBox(m_Controller[i], ID_TILT_INPUT, StrTilt[0], wxDefaultPosition, wxDefaultSize, StrTilt, wxCB_READONLY);
m_TiltComboRange[i] = new wxComboBox(m_Controller[i], ID_TILT_RANGE, StrTiltRange[0], wxDefaultPosition, wxDefaultSize, StrTiltRange, wxCB_READONLY);
m_TiltText[i] = new wxStaticText(m_Controller[i], wxID_ANY, wxT("Range"));
m_TiltHoriz[i] = new wxBoxSizer(wxHORIZONTAL);
m_TiltHoriz[i]->Add(m_TiltText[i], 0, (wxLEFT | wxTOP), 4);
m_TiltHoriz[i]->Add(m_TiltComboRange[i], 0, (wxLEFT | wxRIGHT), 5);
m_gTilt[i] = new wxStaticBoxSizer (wxVERTICAL, m_Controller[i], wxT("Tilt Wiimote"));
m_gTilt[i]->AddStretchSpacer();
m_gTilt[i]->Add(m_TiltCombo[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_gTilt[i]->Add(m_TiltComboInput[i], 0, wxEXPAND | (wxLEFT | wxRIGHT | wxDOWN), 5);
m_gTilt[i]->Add(m_TiltHoriz[i], 0, wxEXPAND | (wxLEFT | wxRIGHT), 5);
m_gTilt[i]->AddStretchSpacer();
//Set values
m_TiltComboInput[i]->SetSelection(g_Config.Trigger.Type);
m_TiltComboRange[i]->SetValue(wxString::Format("%i", g_Config.Trigger.Range));
// Tooltips
m_TiltCombo[i]->SetToolTip(wxT("Control tilting by an analog gamepad stick, an analog trigger or the keyboard."));
m_TiltComboInput[i]->SetToolTip(wxT("Control tilting by an analog gamepad stick, an analog trigger or the keyboard."));
m_TiltComboRange[i]->SetToolTip(wxT("The maximum tilt in degrees"));
// --------------------------------------------------------------------
// Analog triggers
@ -938,6 +988,8 @@ void ConfigDialog::DoExtensionConnectedDisconnected(int Extension)
// ----------------
void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
{
long TmpValue;
switch (event.GetId())
{
case ID_CONNECT_REAL:
@ -1006,6 +1058,15 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
case ID_TRIGGER_TYPE:
WiiMoteEmu::PadMapping[Page].triggertype = m_TriggerType[Page]->GetSelection();
break;
case ID_TILT_INPUT:
g_Config.Trigger.Type = m_TiltComboInput[Page]->GetSelection();
break;
case ID_TILT_RANGE:
m_TiltComboRange[Page]->GetValue().ToLong(&TmpValue); g_Config.Trigger.Range = TmpValue;
break;
case IDC_JOYNAME:
DoChangeJoystick();
break;
//////////////////////////
// Recording
@ -1058,7 +1119,7 @@ void ConfigDialog::GeneralSettingsChanged(wxCommandEvent& event)
// =======================================================
// Update the enabled/disabled status
// -------------
void ConfigDialog::UpdateGUI()
void ConfigDialog::UpdateGUI(int Slot)
{
//Console::Print("UpdateGUI: \n");

View File

@ -44,7 +44,7 @@ class ConfigDialog : public wxDialog
// General open, close and event functions
void CloseClick(wxCommandEvent& event);
void UpdateGUI(); void UpdateGUIButtonMapping(int controller);
void UpdateGUI(int Slot = 0); void UpdateGUIButtonMapping(int controller);
void OnKeyDown(wxKeyEvent& event);
void LoadFile(); void SaveFile();
@ -103,7 +103,7 @@ class ConfigDialog : public wxDialog
wxCheckBox *m_SidewaysDPad[4], *m_WiimoteOnline[4];
wxCheckBox *m_WideScreen[4];
wxCheckBox *m_WiiMotionPlusConnected[4], *m_NunchuckConnected[4], *m_ClassicControllerConnected[4], *m_BalanceBoardConnected[4], *m_GuitarHeroGuitarConnected[4], *m_GuitarHeroWorldTourDrumsConnected[4];
wxComboBox *m_TiltCombo[4], *m_TiltComboRange[4], *m_Joyname[4], *m_TriggerType[4];
wxComboBox *m_TiltComboInput[4], *m_TiltComboRange[4], *m_Joyname[4], *m_TriggerType[4];
// Real Wiimote settings
wxCheckBox *m_ConnectRealWiimote[4], *m_UseRealWiimote[4], *m_UpdateMeters;
@ -147,7 +147,7 @@ class ConfigDialog : public wxDialog
ID_SIDEWAYSDPAD, // Emulated
ID_WIDESCREEN,
ID_NUNCHUCKCONNECTED, ID_CLASSICCONTROLLERCONNECTED,
IDC_JOYNAME, IDC_JOYATTACH, ID_TILT_COMBO, ID_TILT_CHECK,
IDC_JOYNAME, IDC_JOYATTACH,
// Gamepad <It's important that the internal ordering of these are unchanged>
IDB_ANALOG_LEFT_X, IDB_ANALOG_LEFT_Y,
@ -159,7 +159,7 @@ class ConfigDialog : public wxDialog
ID_TRIGGER_L, ID_TRIGGER_R,
// Gamepad settings
ID_TRIGGER_TYPE,
ID_TRIGGER_TYPE, ID_TILT_INPUT, ID_TILT_RANGE,
// Real
ID_CONNECT_REAL, ID_USE_REAL, ID_UPDATE_REAL, IDT_STATUS, ID_NEUTRAL_CHOICE,
@ -186,6 +186,8 @@ class ConfigDialog : public wxDialog
void SaveButtonMapping(int controller, bool DontChangeId = false, int FromSlot = -1); void SaveButtonMappingAll(int Slot);
void ToBlank(bool ToBlank = true);
void PadGetStatus();
void DoSave(bool ChangePad = false, int Slot = -1);
void DoChangeJoystick(); void PadOpen(int Open); void PadClose(int Close);
// Configure buttons
int GetButtonWaitingID, GetButtonWaitingTimer;

View File

@ -35,6 +35,48 @@
//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// Change Joystick
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
/* Function: When changing the joystick we save and load the settings and update the PadMapping
and PadState array. PadState[].joy is the gamepad handle that is used to access the pad throughout
the plugin. Joyinfo[].joy is only used the first time the pads are checked. */
void ConfigDialog::DoChangeJoystick()
{
// Close the current pad, unless it's used by another slot
//if (PadMapping[notebookpage].enabled) PadClose(notebookpage);
// Before changing the pad we save potential changes to the current pad
DoSave(true);
// Load the settings for the new Id
g_Config.Load(true);
UpdateGUI(Page); // Update the GUI
// Open the new pad
if (WiiMoteEmu::PadMapping[Page].enabled) PadOpen(Page);
}
void ConfigDialog::PadOpen(int Open) // Open for slot 1, 2, 3 or 4
{
// Check that we got a good pad
if (!WiiMoteEmu::joyinfo.at(WiiMoteEmu::PadMapping[Open].ID).Good)
{
Console::Print("A bad pad was selected\n");
WiiMoteEmu::PadState[Open].joy = NULL;
return;
}
Console::Print("Update the Slot %i handle to Id %i\n", Page, WiiMoteEmu::PadMapping[Open].ID);
WiiMoteEmu::PadState[Open].joy = SDL_JoystickOpen(WiiMoteEmu::PadMapping[Open].ID);
}
void ConfigDialog::PadClose(int Close) // Close for slot 1, 2, 3 or 4
{
if (SDL_JoystickOpened(WiiMoteEmu::PadMapping[Close].ID)) SDL_JoystickClose(WiiMoteEmu::PadState[Close].joy);
WiiMoteEmu::PadState[Close].joy = NULL;
}
//////////////////////////////////////
///////////////////////////////////////////////////////////////////////////////////
// Change settings
// ¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯¯
@ -368,6 +410,9 @@ void ConfigDialog::DoGetButtons(int GetId)
have the same id, I don't know. So we have to do this. The user may also have selected the same device for
several disabled slots. */
SaveButtonMappingAll(Controller);
Console::Print("Timer Stopped for Pad:%i GetId:%i\n",
WiiMoteEmu::PadMapping[Controller].ID, GetId);
}
// If we got a bad button
@ -429,9 +474,9 @@ void ConfigDialog::PadGetStatus()
// Get physical device status
int PhysicalDevice = WiiMoteEmu::PadMapping[Page].ID;
int TriggerType = WiiMoteEmu::PadMapping[Page].triggertype;
// Check that Dolphin is in focus, otherwise don't update the pad status
if (IsFocus())
//if (IsFocus())
WiiMoteEmu::GetJoyState(WiiMoteEmu::PadState[Page], WiiMoteEmu::PadMapping[Page], Page, WiiMoteEmu::joyinfo[WiiMoteEmu::PadMapping[Page].ID].NumButtons);

View File

@ -110,6 +110,7 @@ void ConfigDialog::SaveFile()
}
file.Save("WiimoteMovement.ini");
Console::Print("Wrote WiimoteMovement.ini\n");
}
/////////////////////////////
@ -413,6 +414,8 @@ void ConfigDialog::ConvertToString()
}
file.Save("WiimoteMovement.ini");
Console::Print("Save recording to WiimoteMovement.ini\n");
}
// Timeout the recording

View File

@ -0,0 +1,102 @@
// Copyright (C) 2003-2008 Dolphin Project.
// This program is free software: you can redistribute it and/or modify
// it under the terms of the GNU General Public License as published by
// the Free Software Foundation, version 2.0.
// This program is distributed in the hope that it will be useful,
// but WITHOUT ANY WARRANTY; without even the implied warranty of
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
// GNU General Public License 2.0 for more details.
// A copy of the GPL 2.0 should have been included with the program.
// If not, see http://www.gnu.org/licenses/
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Includes
// ¯¯¯¯¯¯¯¯¯¯¯¯¯
#include <vector>
#include <string>
#include "../../../Core/InputCommon/Src/SDL.h" // Core
#include "../../../Core/InputCommon/Src/XInput.h"
#include "Common.h" // Common
#include "StringUtil.h" // for ArrayToString()
#include "IniFile.h"
#include "pluginspecs_wiimote.h"
#include "EmuDefinitions.h" // Local
#include "main.h"
#include "wiimote_hid.h"
#include "EmuSubroutines.h"
#include "EmuMain.h"
#include "Encryption.h" // for extension encryption
#include "Logging.h" // for startConsoleWin, Console::Print, GetConsoleHwnd
#include "Config.h" // for g_Config
////////////////////////////////////
namespace WiiMoteEmu
{
void PitchDegreeToAccelerometer(float _Degree, u8 &_y, u8 &_z)
{
// Calculate the radian
float d_rad = _Degree * M_PI / 180.0;
// Calculate a good set of y and z values for the degree
float r = 1.0;
float fy = r * sin(d_rad); // y
float fz = r * cos(d_rad); // x
// Multiple with the neutral of z and its g
float yg = g_accel.cal_g.y;
float zg = g_accel.cal_g.z;
float y_zero = g_accel.cal_zero.y;
float z_zero = g_accel.cal_zero.z;
fy = (int) (y_zero + yg * fy);
fz = (int) (z_zero + zg * fz);
// Boundaries
int iy = (int)fy;
int iz = (int)fz;
if (iy < 0) iy = 0;
if (iy > 255) iy = 255;
_y = iy;
_z = iz;
}
int PitchAccelerometerToDegree(u8 _y, u8 _z)
{
/* find out how much it has to move to be 1g */
float yg = (float)g_accel.cal_g.y;
float zg = (float)g_accel.cal_g.z;
float d = 0;
/* find out how much it actually moved and normalize to +/- 1g */
float y = ((float)_y - (float)g_accel.cal_zero.y) / yg;
float z = ((float)_z - (float)g_accel.cal_zero.z) / zg;
/* make sure x,y,z are between -1 and 1 for the tan function */
if (y < -1.0) y = -1.0;
else if (y > 1.0) y = 1.0;
if (z < -1.0) z = -1.0;
else if (z > 1.0) z = 1.0;
//if (abs(_y - g_accel.cal_zero.y) <= g_accel.cal_g.y)
{
// Calculate the radian
d = atan2(y, z);
// Calculate the degree
d = (d * 180.0) / M_PI;
}
return (int)d;
}
}

View File

@ -123,6 +123,8 @@ void WriteCrypted16(u8* _baseBlock, u16 _address, u16 _value)
// ----------------
void LoadRecordedMovements()
{
Console::Print("LoadRecordedMovements()");
IniFile file;
file.Load("WiimoteMovement.ini");
@ -131,6 +133,9 @@ void LoadRecordedMovements()
// Logging
//Console::Print("Recording%i ", i + 1);
// First clear the list
VRecording.at(i).Recording.clear();
// Get row name
std::string SaveName = StringFromFormat("Recording%i", i + 1);
@ -192,10 +197,10 @@ void LoadRecordedMovements()
// ---------------------------------
// Log results
// ---------
//Console::Print("Time:%f\n", Tmp.Time);
//std::string TmpIRLog = ArrayToString(Tmp.IR, TmpIRBytes, 0, 30);
//Console::Print("IR: %s\n", TmpIRLog.c_str());
//Console::Print("\n");
/*Console::Print("Time:%f\n", Tmp.Time);
std::string TmpIRLog = ArrayToString(Tmp.IR, TmpIRBytes, 0, 30);
Console::Print("IR: %s\n", TmpIRLog.c_str());
Console::Print("\n");*/
}
// Get HotKey
@ -216,7 +221,7 @@ void LoadRecordedMovements()
TmpIRLog = "";
/*
Console::Print("Size:%i HotKey:%i Speed:%i IR: %s\n",
Console::Print("Size:%i HotKey:%i PlSpeed:%i IR: %s\n",
VRecording.at(i).Recording.size(), VRecording.at(i).HotKey, VRecording.at(i).PlaybackSpeed,
TmpIRLog.c_str()
);*/
@ -465,10 +470,13 @@ void InterruptChannel(u16 _channelID, const void* _pData, u32 _Size)
and registry reads and writes. */
// There are no 0x22 replys to these report from the real wiimote from what I could see
// Report 0x10 that seems to be only used for rumble
// Report 0x10 that seems to be only used for rumble, and we don't need to answer that,
// also if we do *we should update the 0x22 to have the core keys* otherwise the game will
// think we release the key every time it rumbles
if(!(data[1] == WM_READ_DATA && data[2] == 0x00)
&& !(data[1] == WM_REQUEST_STATUS)
&& !(data[1] == WM_WRITE_SPEAKER_DATA))
&& !(data[1] == WM_WRITE_SPEAKER_DATA)
&& !(data[1] == WM_RUMBLE))
if (!g_Config.bUseRealWiimote || !g_RealWiiMotePresent) CreateAckDelay((u8)_channelID, (u16)sr->channel);
}
break;

View File

@ -51,6 +51,11 @@ void SetDefaultExtensionRegistry();
// Gamepad
bool Search_Devices(std::vector<InputCommon::CONTROLLER_INFO> &_joyinfo, int &_NumPads, int &_NumGoodPads);
void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONTROLLER_MAPPING_NEW _PadMapping, int controller, int NumButtons);
};
void PitchDegreeToAccelerometer(float _Degree, u8 &_y, u8 &_z);
int PitchAccelerometerToDegree(u8 _y, u8 _z);
}; // WiiMoteEmu
#endif

View File

@ -99,8 +99,10 @@ void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONT
{
#endif
// If we are using SDL analog triggers the buttons have to be mapped as 1000 or up, otherwise they are not used
_PadState.Axis.Tl = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tl - 1000);
_PadState.Axis.Tr = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tr - 1000);
// We must also check that we are not asking for a negative axis number because SDL_JoystickGetAxis() has
// no good way of handling that
if ((_PadMapping.Axis.Tl - 1000) >= 0) _PadState.Axis.Tl = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tl - 1000);
if ((_PadMapping.Axis.Tr - 1000) >= 0) _PadState.Axis.Tr = SDL_JoystickGetAxis(_PadState.joy, _PadMapping.Axis.Tr - 1000);
#ifdef _WIN32
}
else
@ -115,13 +117,17 @@ void GetJoyState(InputCommon::CONTROLLER_STATE_NEW &_PadState, InputCommon::CONT
Console::Print(
"Controller and handle: %i %i\n"
"Triggers:%i %i %i %i %i\n",
"Triggers:%i %i %i %i %i\n"
"Analog:%06i %06i \n",
controller, (int)_PadState.joy,
_PadMapping.triggertype,
_PadMapping.Axis.Tl, _PadMapping.Axis.Tr,
_PadState.Axis.Tl, _PadState.Axis.Tr
_PadState.Axis.Tl, _PadState.Axis.Tr,
_PadState.Axis.Lx, _PadState.Axis.Ly
);*/
}

View File

@ -139,8 +139,10 @@ bool RecordingPlayAccIR(u8 &_x, u8 &_y, u8 &_z, IRReportType &_IR, int Wm)
VRecording.at(g_RecordingPlaying[Wm]).Recording.at(g_RecordingPoint[Wm]).Time, g_RecordingCurrentTime[Wm],
VRecording.at(g_RecordingPlaying[Wm]).Recording.size(), g_RecordingPoint[Wm]
);
Console::Print("Accel x, y, z: %03u %03u %03u\n\n", _x, _y, _z);
Console::Print("Accel x, y, z: %03u %03u %03u\n", _x, _y, _z);
}
//Console::Print("Accel x, y, z: %03u %03u %03u\n", _x, _y, _z);
//Console::Print("Accel x, y, z: %02x %02x %02x\n", _x, _y, _z);
g_RecordingCounter[Wm]++;
@ -233,6 +235,15 @@ int RecordingCheckKeys(int Wiimote)
#endif
}
// check if we have any recording playback key combination
bool CheckKeyCombination()
{
if (RecordingCheckKeys(0) == -1 && RecordingCheckKeys(1) == -1 && RecordingCheckKeys(2) == -1)
return false;
else
return true; // This will also start a recording
}
//******************************************************************************
@ -253,6 +264,9 @@ void FillReportInfo(wm_core& _core)
// Check that Dolphin is in focus
if (!IsFocus()) return;
// Don't interrupt a recording
if (CheckKeyCombination()) return;
// Check the mouse position. Don't allow mouse clicks from outside the window.
float x, y; GetMousePos(x, y);
bool InsideScreen = !(x < 0 || x > 1 || y < 0 || y > 1);
@ -299,22 +313,173 @@ void FillReportInfo(wm_core& _core)
being [y = 0x84, x = 0x84, z = 0x9f] according to a source. The extremes are 0x00 for (-)
and 0xff for (+). It's important that all values are not 0x80, the mouse pointer can disappear
from the screen permanently then, until z is adjusted back. */
// ----------
// Global declarations for FillReportAcc: These variables are global so they can be changed during debugging
//int A = 0, B = 128, C = 64; // for debugging
//int a = 1, b = 1, c = 2, d = -2; // for debugging
//int consoleDisplay = 0;
u8 x, y, z;
int shake = -1, yhistsize = 15; // for the shake function
std::vector<u8> yhist(15); // for the tilt function
// For all functions
u8 x, y, z, X, Y, Z;
// For the shake function
int shake = -1;
// For the tilt function, the size of this list determines how fast Y returns to its neutral value
std::vector<u8> yhist(15, 0); float KbDegree;
// ------------------------------------------
// Single shake of Wiimote while holding it sideways (Wario Land pound ground)
// ---------------
void SingleShake(u8 &_z, u8 &_y)
{
if(GetAsyncKeyState('S'))
{
_z = 0;
_y = 0;
shake = 2;
}
else if(shake == 2)
{
_z = 128;
_y = 0;
shake = 1;
}
else if(shake == 1)
{
_z = Z;
_y = Y;
shake = -1;
}
else // the default Z if nothing is pressed
{
z = Z;
}
}
// ------------------------------------------
/* Tilting Wiimote with gamepad. We can guess that the game will calculate a Wiimote pitch and use it as a
measure of the tilting of the Wiimote. We are interested in this tilting range
90° to -90° */
// ---------------
void TiltWiimoteGamepad(u8 &_y, u8 &_z)
{
// Update the pad state
const int Page = 0;
WiiMoteEmu::GetJoyState(PadState[Page], PadMapping[Page], Page, joyinfo[PadMapping[Page].ID].NumButtons);
// Convert the big values
float Lx = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Lx);
float Ly = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Ly);
float Rx = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Rx);
float Ry = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Ry);
float Tl, Tr;
if (PadMapping[Page].triggertype == InputCommon::CTL_TRIGGER_SDL)
{
Tl = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Tl);
Tr = (float)InputCommon::Pad_Convert(PadState[Page].Axis.Tr);
}
else
{
Tl = (float)PadState[Page].Axis.Tl;
Tr = (float)PadState[Page].Axis.Tr;
}
// It's easier to use a float here
float Degree = 0;
// Calculate the present room between the neutral and the maximum values
float RoomAbove = 255.0 - (float)Y;
float RoomBelow = (float)Y;
// Save the Range in degrees, 45° and 90° are good values in some games
float Range = (float)g_Config.Trigger.Range;
// Trigger
if (g_Config.Trigger.Type == g_Config.TRIGGER)
{
// Make the range the same dimension as the analog stick
Tl = Tl / 2;
Tr = Tr / 2;
Degree = Tl * (Range / 128)
- Tr * (Range / 128);
}
// Analog stick
else
{
// Adjust the trigger to go between negative and positive values
Lx = Lx - 128;
// Produce the final value
Degree = -Lx * (Range / 128);
}
// Calculate the acceleometer value from this tilt angle
PitchDegreeToAccelerometer(Degree, _y, _z);
//Console::ClearScreen();
/*Console::Print("L:%2.1f R:%2.1f Lx:%2.1f Range:%2.1f Degree:%2.1f L:%i R:%i\n",
Tl, Tr, Lx, Range, Degree, PadState[Page].Axis.Tl, PadState[Page].Axis.Tr);*/
/*Console::Print("Degree:%2.1f\n", Degree);*/
}
// ------------------------------------------
// Tilting Wiimote (Wario Land aiming, Mario Kart steering) : For some reason 150 and 40
// seemed like decent starting values.
// ---------------
void TiltWiimoteKeyboard(u8 &_y, u8 &_z)
{
#ifdef _WIN32
if(GetAsyncKeyState('3'))
{
// Stop at the upper end of the range
if(KbDegree < g_Config.Trigger.Range)
KbDegree += 3; // aim left
}
else if(GetAsyncKeyState('4'))
{
// Stop at the lower end of the range
if(KbDegree > -g_Config.Trigger.Range)
KbDegree -= 3; // aim right
}
// -----------------------------------
// Check for inactivity in the tilting, the Y value will be reset after ten inactive updates
// ----------
yhist[yhist.size() - 1] = (
GetAsyncKeyState('3')
|| GetAsyncKeyState('4')
|| shake > 0
);
// Move all items back, and check if any of them are true
bool ypressed = false;
for (int i = 1; i < (int)yhist.size(); i++)
{
yhist[i-1] = yhist[i];
if(yhist[i]) ypressed = true;
}
// Tilting was not used a single time, reset y to its neutral value
if(!ypressed)
{
_y = Y;
}
else
{
PitchDegreeToAccelerometer(KbDegree, _y, _z);
//Console::Print("Degree: %2.1f\n", KbDegree);
}
// --------------------
#endif
}
void FillReportAcc(wm_accel& _acc)
{
// Create shortcut names for the default neutral values
int X = g_accel.cal_zero.x, Y = g_accel.cal_zero.y, Z = g_accel.cal_zero.z + g_accel.cal_g.z;
#ifdef _WIN32
// ------------------------------------
// Recorded movements
// --------------
@ -331,6 +496,11 @@ void FillReportAcc(wm_accel& _acc)
}
// ---------------------
// The default values can change so we need to update them all the time
X = g_accel.cal_zero.x;
Y = g_accel.cal_zero.y;
Z = g_accel.cal_zero.z + g_accel.cal_g.z;
// Check that Dolphin is in focus
if (!IsFocus())
@ -341,102 +511,24 @@ void FillReportAcc(wm_accel& _acc)
return;
}
// ------------------------------------
// ------------------------------------------------
// Wiimote to Gamepad translations
// ----------
// Tilting Wiimote (Wario Land aiming, Mario Kart steering) : For some reason 150 and 40
// seemed like decent starting values.
if(GetAsyncKeyState('3'))
{
//if(a < 128) // for debugging
if(y < 250)
{
y += 4; // aim left
//a += c; // debugging values
//y = A + a; // aim left
}
}
else if(GetAsyncKeyState('4'))
{
// if(b < 128) // for debugging
if(y > 5)
{
y -= 4; // aim right
//b -= d; // debugging values
//y = B + b;
}
}
// ------------
/* Single shake of Wiimote while holding it sideways (Wario Land pound ground)
if(GetAsyncKeyState('S'))
z = 0;
else
z = Z;*/
if(GetAsyncKeyState('S'))
{
z = 0;
y = 0;
shake = 2;
}
else
#endif
if(shake == 2)
{
z = 128;
y = 0;
shake = 1;
}
else if(shake == 1)
{
z = Z;
y = Y;
shake = -1;
}
else // the default Z if nothing is pressed
{
z = Z;
}
// ----------
// -----------------------------
// For tilting: add new value and move all back
// ----------
bool ypressed = false;
#ifdef _WIN32
yhist[yhist.size() - 1] = (
GetAsyncKeyState('3') ? true : false
|| GetAsyncKeyState('4') ? true : false
|| shake > 0
);
#endif
if(yhistsize > (int)yhist.size()) yhistsize = (int)yhist.size();
for (int i = 1; i < yhistsize; i++)
{
yhist[i-1] = yhist[i];
if(yhist[i]) ypressed = true;
}
if(!ypressed) // y was not pressed a single time
{
y = Y; // this is the default value that will occur most of the time
//a = 0; // for debugging
//b = 0;
}
// else if(!GetAsyncKeyState('3') && !GetAsyncKeyState('4'))
// {
// perhaps start dropping acceleration back?
// }
// ----------
// Shake the Wiimote
SingleShake(z, y);
// Tilt Wiimote
if (g_Config.Trigger.Type == g_Config.KEYBOARD)
TiltWiimoteKeyboard(y, z);
else if (g_Config.Trigger.Type == g_Config.TRIGGER || g_Config.Trigger.Type == g_Config.ANALOG)
TiltWiimoteGamepad(y, z);
// Write values
_acc.x = X;
_acc.y = y;
_acc.z = z;
// ----------------------------
// Debugging for translating Wiimote to Keyboard (or Gamepad)

View File

@ -198,13 +198,14 @@ void handle_event(struct wiimote_t* wm)
frame->m_GaugeAccel[2]->SetValue(AccelZ);
frame->m_TextIR->SetLabel(wxString::Format(
wxT("Cursor: %03u %03u\nDistance:%4.0f"), wm->ir.x, wm->ir.y, wm->ir.z));
wxT("Cursor: %03u %03u\nDistance:%4.0f"), wm->ir.x, wm->ir.y, wm->ir.z));
frame->m_TextAccNeutralCurrent->SetLabel(wxString::Format(
wxT("Current: %03u %03u %03u"), AccelX, AccelY, AccelZ));
wxT("Current: %03u %03u %03u"), AccelX, AccelY, AccelZ));
if(frame->m_bRecording)
Console::Print("Wiiuse Recorded accel x, y, z: %03i %03i %03i\n", wm->accel.x, wm->accel.y, wm->accel.z);
//Console::Print("Wiiuse Recorded accel x, y, z: %02x %02x %02x\n", wm->accel.x, wm->accel.y, wm->accel.z);
}
// Send the data to be saved

View File

@ -10,6 +10,7 @@ files = [
"Config.cpp",
"DataReports.cpp",
"EmuDefinitions.cpp",
"EmuDynamics.cpp",
"EmuMain.cpp",
"EmuPad.cpp",
"EmuSubroutines.cpp",

View File

@ -408,6 +408,7 @@ void DisableExtensions()
//g_Config.bDrums = false;
}
void ReadDebugging(bool Emu, const void* _pData, int Size)
{
//
@ -625,8 +626,10 @@ void ReadDebugging(bool Emu, const void* _pData, int Size)
std::string Tmp2 = TmpData.substr(68, (TmpData.length() - 68));
TmpData = Tmp1 + StringFromFormat("%03i %03i %03i", data[19], data[20], data[21]) + Tmp2;
}
// Calculate the Wiimote pitch in degrees
std::string Pitch = StringFromFormat("%i", WiiMoteEmu::PitchAccelerometerToDegree(data[5], data[6]));
Console::Print("Read[%s]: %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str()); // No timestamp
Console::Print("Read[%s]: %s| %s\n", (Emu ? "Emu" : "Real"), TmpData.c_str(), Pitch.c_str()); // No timestamp
//Console::Print(" (%s): %s\n", Tm(true).c_str(), Temp.c_str()); // Timestamp
}
if(g_DebugAccelerometer)

View File

@ -49,6 +49,7 @@ struct wm_report {
u8 data[0];
};
#define WM_RUMBLE 0x10
#define WM_LEDS 0x11
struct wm_leds {
u8 rumble : 1;

View File

@ -286,7 +286,8 @@ void ConfigBox::DoGetButtons(int GetId)
bool LeftRight = (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R);
bool Axis = (GetId >= IDB_ANALOG_MAIN_X && GetId <= IDB_SHOULDER_R)
&& !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) ); // Don't allow SDL here
// Don't allow SDL input for the triggers when XInput is selected
&& !(TriggerType == InputCommon::CTL_TRIGGER_XINPUT && (GetId == IDB_SHOULDER_L || GetId == IDB_SHOULDER_R) );
bool XInput = (TriggerType == InputCommon::CTL_TRIGGER_XINPUT);