diff --git a/Source/Core/InputCommon/Src/Configuration.cpp b/Source/Core/InputCommon/Src/Configuration.cpp index 44b5c05555..4756692974 100644 --- a/Source/Core/InputCommon/Src/Configuration.cpp +++ b/Source/Core/InputCommon/Src/Configuration.cpp @@ -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)); diff --git a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj index 0e0ebf7c0e..bb895fe527 100644 --- a/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj +++ b/Source/Plugins/Plugin_Wiimote/Plugin_Wiimote.vcproj @@ -542,6 +542,10 @@ RelativePath=".\Src\EmuDefinitions.h" > + + diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp index 4d952bf4a9..cda5699198 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.cpp @@ -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); diff --git a/Source/Plugins/Plugin_Wiimote/Src/Config.h b/Source/Plugins/Plugin_Wiimote/Src/Config.h index 7139eed991..264738f017 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/Config.h +++ b/Source/Plugins/Plugin_Wiimote/Src/Config.h @@ -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; diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp index 1896cd28cd..a7ca94f237 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.cpp @@ -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("")); + 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"); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h index 36ecc09bc0..8d4f245fb8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigDlg.h @@ -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 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; diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp index 34be1853c7..b0eb4f4eea 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigGamepad.cpp @@ -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); diff --git a/Source/Plugins/Plugin_Wiimote/Src/ConfigRecording.cpp b/Source/Plugins/Plugin_Wiimote/Src/ConfigRecording.cpp index 06195ef474..954a67151a 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ConfigRecording.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ConfigRecording.cpp @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp new file mode 100644 index 0000000000..a06b0ff335 --- /dev/null +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuDynamics.cpp @@ -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 +#include + +#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; +} + +} \ No newline at end of file diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp index 6a86ef0b3b..a285b883a0 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.cpp @@ -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; diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h index f375b548e7..2cfaf5dfc7 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuMain.h @@ -51,6 +51,11 @@ void SetDefaultExtensionRegistry(); // Gamepad bool Search_Devices(std::vector &_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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp b/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp index f780d9aad4..48ec100931 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/EmuPad.cpp @@ -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 );*/ } diff --git a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp index d713ac334b..0692395723 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/FillReport.cpp @@ -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 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 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) diff --git a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp index 40739c8b0d..8bc48a40cc 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/ReadWiimote.cpp @@ -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 diff --git a/Source/Plugins/Plugin_Wiimote/Src/SConscript b/Source/Plugins/Plugin_Wiimote/Src/SConscript index 2ea2af9672..6f8b8d2546 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/SConscript +++ b/Source/Plugins/Plugin_Wiimote/Src/SConscript @@ -10,6 +10,7 @@ files = [ "Config.cpp", "DataReports.cpp", "EmuDefinitions.cpp", + "EmuDynamics.cpp", "EmuMain.cpp", "EmuPad.cpp", "EmuSubroutines.cpp", diff --git a/Source/Plugins/Plugin_Wiimote/Src/main.cpp b/Source/Plugins/Plugin_Wiimote/Src/main.cpp index a584618630..e4ca419653 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/main.cpp +++ b/Source/Plugins/Plugin_Wiimote/Src/main.cpp @@ -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) diff --git a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h index 503ad7a565..7162ae03d8 100644 --- a/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h +++ b/Source/Plugins/Plugin_Wiimote/Src/wiimote_hid.h @@ -49,6 +49,7 @@ struct wm_report { u8 data[0]; }; +#define WM_RUMBLE 0x10 #define WM_LEDS 0x11 struct wm_leds { u8 rumble : 1; diff --git a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp index 87b314ba22..f9e8ad23f1 100644 --- a/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp +++ b/Source/Plugins/Plugin_nJoy_SDL/Src/GUI/ConfigJoypad.cpp @@ -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);