From 2167a45c242137b91127d04da91f8837f033b51f Mon Sep 17 00:00:00 2001 From: spycrab Date: Thu, 4 Jan 2018 18:38:09 +0000 Subject: [PATCH 1/2] Qt/Mapping: Implement Microphone widget --- Source/Core/DolphinQt2/CMakeLists.txt | 1 + .../Config/Mapping/GCMicrophone.cpp | 45 +++++++++++++++++++ .../DolphinQt2/Config/Mapping/GCMicrophone.h | 29 ++++++++++++ .../Config/Mapping/MappingWindow.cpp | 7 +++ .../DolphinQt2/Config/Mapping/MappingWindow.h | 1 + 5 files changed, 83 insertions(+) create mode 100644 Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.cpp create mode 100644 Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.h diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index 3ed0ffb1c8..e85ddda9d0 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -50,6 +50,7 @@ set(SRCS Config/LogConfigWidget.cpp Config/LogWidget.cpp Config/Mapping/GCKeyboardEmu.cpp + Config/Mapping/GCMicrophone.cpp Config/Mapping/GCPadEmu.cpp Config/Mapping/GCPadWiiUConfigDialog.cpp Config/Mapping/Hotkey3D.cpp diff --git a/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.cpp b/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.cpp new file mode 100644 index 0000000000..bd5037073d --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.cpp @@ -0,0 +1,45 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include +#include +#include +#include + +#include "DolphinQt2/Config/Mapping/GCMicrophone.h" + +#include "InputCommon/InputConfig.h" + +#include "Core/HW/GCPad.h" +#include "Core/HW/GCPadEmu.h" + +GCMicrophone::GCMicrophone(MappingWindow* window) : MappingWidget(window) +{ + CreateMainLayout(); +} + +void GCMicrophone::CreateMainLayout() +{ + m_main_layout = new QHBoxLayout(); + + m_main_layout->addWidget( + CreateGroupBox(tr("Microphone"), Pad::GetGroup(GetPort(), PadGroup::Mic))); + + setLayout(m_main_layout); +} + +void GCMicrophone::LoadSettings() +{ + Pad::LoadConfig(); +} + +void GCMicrophone::SaveSettings() +{ + Pad::GetConfig()->SaveConfig(); +} + +InputConfig* GCMicrophone::GetConfig() +{ + return Pad::GetConfig(); +} diff --git a/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.h b/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.h new file mode 100644 index 0000000000..577a5320f7 --- /dev/null +++ b/Source/Core/DolphinQt2/Config/Mapping/GCMicrophone.h @@ -0,0 +1,29 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include "DolphinQt2/Config/Mapping/MappingWidget.h" + +class QCheckBox; +class QFormLayout; +class QGroupBox; +class QHBoxLayout; +class QLabel; +class QVBoxLayout; + +class GCMicrophone final : public MappingWidget +{ +public: + explicit GCMicrophone(MappingWindow* window); + + InputConfig* GetConfig() override; + +private: + void LoadSettings() override; + void SaveSettings() override; + void CreateMainLayout(); + + QHBoxLayout* m_main_layout; +}; diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp index 18d22b706d..7c0c72d40f 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.cpp @@ -19,6 +19,7 @@ #include "Common/StringUtil.h" #include "Core/Core.h" #include "DolphinQt2/Config/Mapping/GCKeyboardEmu.h" +#include "DolphinQt2/Config/Mapping/GCMicrophone.h" #include "DolphinQt2/Config/Mapping/GCPadEmu.h" #include "DolphinQt2/Config/Mapping/Hotkey3D.h" #include "DolphinQt2/Config/Mapping/HotkeyGeneral.h" @@ -254,6 +255,12 @@ void MappingWindow::SetMappingType(MappingWindow::Type type) setWindowTitle(tr("GameCube Controller at Port %1").arg(GetPort() + 1)); AddWidget(tr("GameCube Controller"), widget); break; + case Type::MAPPING_GC_MICROPHONE: + widget = new GCMicrophone(this); + setWindowTitle(tr("GameCube Microphone Slot %1") + .arg(GetPort() == 0 ? QStringLiteral("A") : QStringLiteral("B"))); + AddWidget(tr("Microphone"), widget); + break; case Type::MAPPING_WIIMOTE_EMU: case Type::MAPPING_WIIMOTE_HYBRID: { diff --git a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h index d97b39d576..e16d120c1a 100644 --- a/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h +++ b/Source/Core/DolphinQt2/Config/Mapping/MappingWindow.h @@ -38,6 +38,7 @@ public: MAPPING_GC_KEYBOARD, MAPPING_GCPAD, MAPPING_GC_STEERINGWHEEL, + MAPPING_GC_MICROPHONE, // Wii MAPPING_WIIMOTE_EMU, MAPPING_WIIMOTE_HYBRID, From fffa883cae74dd60de511b65a05c23fb54bd1c11 Mon Sep 17 00:00:00 2001 From: spycrab Date: Thu, 4 Jan 2018 00:41:31 +0000 Subject: [PATCH 2/2] Qt/Settings: Implement "GameCube pane" --- Source/Core/DolphinQt2/CMakeLists.txt | 1 + .../Core/DolphinQt2/Config/SettingsWindow.cpp | 2 + Source/Core/DolphinQt2/DolphinQt2.vcxproj | 4 + .../Core/DolphinQt2/Settings/GameCubePane.cpp | 339 ++++++++++++++++++ .../Core/DolphinQt2/Settings/GameCubePane.h | 33 ++ 5 files changed, 379 insertions(+) create mode 100644 Source/Core/DolphinQt2/Settings/GameCubePane.cpp create mode 100644 Source/Core/DolphinQt2/Settings/GameCubePane.h diff --git a/Source/Core/DolphinQt2/CMakeLists.txt b/Source/Core/DolphinQt2/CMakeLists.txt index e85ddda9d0..9f8e2467be 100644 --- a/Source/Core/DolphinQt2/CMakeLists.txt +++ b/Source/Core/DolphinQt2/CMakeLists.txt @@ -95,6 +95,7 @@ set(SRCS QtUtils/WindowActivationEventFilter.cpp Settings/AdvancedPane.cpp Settings/AudioPane.cpp + Settings/GameCubePane.cpp Settings/GeneralPane.cpp Settings/InterfacePane.cpp Settings/PathPane.cpp diff --git a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp index 59c9d33fd3..80bc7a574b 100644 --- a/Source/Core/DolphinQt2/Config/SettingsWindow.cpp +++ b/Source/Core/DolphinQt2/Config/SettingsWindow.cpp @@ -12,6 +12,7 @@ #include "DolphinQt2/Settings.h" #include "DolphinQt2/Settings/AdvancedPane.h" #include "DolphinQt2/Settings/AudioPane.h" +#include "DolphinQt2/Settings/GameCubePane.h" #include "DolphinQt2/Settings/GeneralPane.h" #include "DolphinQt2/Settings/InterfacePane.h" #include "DolphinQt2/Settings/PathPane.h" @@ -42,6 +43,7 @@ SettingsWindow::SettingsWindow(QWidget* parent) : QDialog(parent) m_general_pane_index = AddTab(m_tabs, tr("General"), new GeneralPane(), "config"); AddTab(m_tabs, tr("Interface"), new InterfacePane(), "browse"); m_audio_pane_index = AddTab(m_tabs, tr("Audio"), new AudioPane(), "play"); + AddTab(m_tabs, tr("GameCube"), new GameCubePane(), "gcpad"); AddTab(m_tabs, tr("Paths"), new PathPane(), "browse"); AddTab(m_tabs, tr("Advanced"), new AdvancedPane(), "config"); diff --git a/Source/Core/DolphinQt2/DolphinQt2.vcxproj b/Source/Core/DolphinQt2/DolphinQt2.vcxproj index 800825824b..06e4c27293 100644 --- a/Source/Core/DolphinQt2/DolphinQt2.vcxproj +++ b/Source/Core/DolphinQt2/DolphinQt2.vcxproj @@ -186,6 +186,7 @@ + @@ -242,6 +243,7 @@ + @@ -254,6 +256,7 @@ + @@ -275,6 +278,7 @@ + diff --git a/Source/Core/DolphinQt2/Settings/GameCubePane.cpp b/Source/Core/DolphinQt2/Settings/GameCubePane.cpp new file mode 100644 index 0000000000..2b941663ac --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/GameCubePane.cpp @@ -0,0 +1,339 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#include "DolphinQt2/Settings/GameCubePane.h" + +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +#include "Common/CommonPaths.h" +#include "Common/FileUtil.h" +#include "Core/ConfigManager.h" +#include "Core/Core.h" +#include "Core/HW/EXI/EXI.h" +#include "Core/HW/GCMemcard/GCMemcard.h" +#include "DolphinQt2/Config/Mapping/MappingWindow.h" + +constexpr int SLOT_A_INDEX = 0; +constexpr int SLOT_B_INDEX = 1; +constexpr int SLOT_COUNT = 3; + +constexpr int EXP_MEMORYCARD_INDEX = 2; +constexpr int EXP_GECKO_INDEX = 4; + +GameCubePane::GameCubePane() +{ + CreateWidgets(); + ConnectWidgets(); + + LoadSettings(); +} + +void GameCubePane::CreateWidgets() +{ + QVBoxLayout* layout = new QVBoxLayout; + + // IPL Settings + QGroupBox* ipl_box = new QGroupBox(tr("IPL Settings")); + QGridLayout* ipl_layout = new QGridLayout; + ipl_box->setLayout(ipl_layout); + + m_skip_main_menu = new QCheckBox(tr("Skip Main Menu")); + m_override_language_ntsc = new QCheckBox(tr("Override Language on NTSC Games")); + m_language_combo = new QComboBox; + + // Add languages + for (const auto& language : + {tr("English"), tr("German"), tr("French"), tr("Spanish"), tr("Italian"), tr("Dutch")}) + m_language_combo->addItem(language); + + ipl_layout->addWidget(m_skip_main_menu, 0, 0); + ipl_layout->addWidget(new QLabel(tr("System Language:")), 1, 0); + ipl_layout->addWidget(m_language_combo, 1, 1); + ipl_layout->addWidget(m_override_language_ntsc, 2, 0); + + // Device Settings + QGroupBox* device_box = new QGroupBox(tr("Device Settings")); + QGridLayout* device_layout = new QGridLayout; + device_box->setLayout(device_layout); + + m_slot_combos[0] = new QComboBox; + m_slot_combos[1] = new QComboBox; + m_slot_combos[2] = new QComboBox; + + m_slot_buttons[0] = new QPushButton(tr("...")); + m_slot_buttons[1] = new QPushButton(tr("...")); + + m_slot_buttons[0]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + m_slot_buttons[1]->setSizePolicy(QSizePolicy::Fixed, QSizePolicy::Fixed); + + const QString i10n_nothing = tr(""); + const QString i10n_dummy = tr("Dummy"); + + // Add slot devices + + for (const auto& device : {i10n_nothing, i10n_dummy, tr("Memory Card"), tr("GCI Folder"), + tr("USB Gecko"), tr("Advance Game Port"), tr("Microphone")}) + { + m_slot_combos[0]->addItem(device); + m_slot_combos[1]->addItem(device); + } + + // Add SP1 devices + + for (const auto& device : {i10n_nothing, i10n_dummy, tr("Broadband Adapter")}) + { + m_slot_combos[2]->addItem(device); + } + + device_layout->addWidget(new QLabel(tr("Slot A:")), 0, 0); + device_layout->addWidget(m_slot_combos[0], 0, 1); + device_layout->addWidget(m_slot_buttons[0], 0, 2); + device_layout->addWidget(new QLabel(tr("Slot B:")), 1, 0); + device_layout->addWidget(m_slot_combos[1], 1, 1); + device_layout->addWidget(m_slot_buttons[1], 1, 2); + device_layout->addWidget(new QLabel(tr("SP1:")), 2, 0); + device_layout->addWidget(m_slot_combos[2], 2, 1); + + layout->addWidget(ipl_box); + layout->addWidget(device_box); + + setLayout(layout); +} + +void GameCubePane::ConnectWidgets() +{ + // IPL Settings + connect(m_skip_main_menu, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); + connect(m_language_combo, static_cast(&QComboBox::currentIndexChanged), + this, &GameCubePane::SaveSettings); + connect(m_override_language_ntsc, &QCheckBox::stateChanged, this, &GameCubePane::SaveSettings); + + // Device Settings + for (int i = 0; i < SLOT_COUNT; i++) + { + connect(m_slot_combos[i], + static_cast(&QComboBox::currentIndexChanged), this, + &GameCubePane::SaveSettings); + if (i <= SLOT_B_INDEX) + { + connect(m_slot_buttons[i], &QPushButton::pressed, this, [this, i] { OnConfigPressed(i); }); + } + } +} + +void GameCubePane::OnConfigPressed(int slot) +{ + QString filter; + bool memcard = false; + + switch (m_slot_combos[slot]->currentIndex()) + { + // Memory card + case 2: + filter = tr("GameCube Memory Cards (*.raw,*.gcp)"); + memcard = true; + break; + // Advance Game Port + case 5: + filter = tr("Game Boy Advance Carts (*.gba)"); + memcard = false; + break; + // Microphone + case 6: + MappingWindow(this, MappingWindow::Type::MAPPING_GC_MICROPHONE, slot).exec(); + return; + } + + QString filename = + QFileDialog::getOpenFileName(this, tr("Choose a file to open"), QStringLiteral(""), filter); + + if (filename.isEmpty() || !File::Exists(filename.toStdString())) + return; + + QString path_abs = QFileInfo(filename).absolutePath(); + + // Memcard validity checks + if (memcard) + { + GCMemcard mc(filename.toStdString()); + + if (!mc.IsValid()) + { + QMessageBox::critical(this, tr("Error"), tr("Cannot use that file as a memory card.\n%s\n" + "is not a valid GameCube memory card file") + .arg(filename)); + return; + } + + QString path_b = + QFileInfo(QString::fromStdString(slot == 0 ? SConfig::GetInstance().m_strMemoryCardB : + SConfig::GetInstance().m_strMemoryCardA)) + .absolutePath(); + + if (path_abs == path_b) + { + QMessageBox::critical(this, tr("Error"), tr("The same file can't be used in both slots.")); + return; + } + } + + if (memcard) + { + if (slot == SLOT_A_INDEX) + { + SConfig::GetInstance().m_strMemoryCardA = path_abs.toStdString(); + } + else + { + SConfig::GetInstance().m_strMemoryCardB = path_abs.toStdString(); + } + } + else + { + if (slot == SLOT_A_INDEX) + { + SConfig::GetInstance().m_strGbaCartA = path_abs.toStdString(); + } + else + { + SConfig::GetInstance().m_strGbaCartB = path_abs.toStdString(); + } + } +} + +void GameCubePane::LoadSettings() +{ + const SConfig& params = SConfig::GetInstance(); + + // IPL Settings + m_skip_main_menu->setChecked(params.bHLE_BS2); + m_language_combo->setCurrentIndex(params.SelectedLanguage); + m_override_language_ntsc->setChecked(params.bOverrideGCLanguage); + + bool have_menu = false; + + for (const std::string& dir : {USA_DIR, JAP_DIR, EUR_DIR}) + { + const auto& path = DIR_SEP + dir + DIR_SEP GC_IPL; + if (File::Exists(File::GetUserPath(D_GCUSER_IDX) + path) || + File::Exists(File::GetUserPath(D_GCUSER_IDX) + path)) + { + have_menu = true; + break; + } + } + + m_skip_main_menu->setEnabled(have_menu); + m_skip_main_menu->setToolTip(have_menu ? QStringLiteral("") : + tr("Put Main Menu roms in User/GC/{region}.")); + + // Device Settings + + for (int i = 0; i < SLOT_COUNT; i++) + { + int index = 0; + switch (SConfig::GetInstance().m_EXIDevice[i]) + { + case ExpansionInterface::EXIDEVICE_NONE: + index = 0; + break; + case ExpansionInterface::EXIDEVICE_DUMMY: + index = 1; + break; + case ExpansionInterface::EXIDEVICE_MEMORYCARD: + index = 2; + break; + case ExpansionInterface::EXIDEVICE_MEMORYCARDFOLDER: + index = 3; + break; + case ExpansionInterface::EXIDEVICE_GECKO: + index = 4; + break; + case ExpansionInterface::EXIDEVICE_AGP: + index = 5; + break; + case ExpansionInterface::EXIDEVICE_MIC: + index = 6; + break; + default: + break; + } + + if (i <= SLOT_B_INDEX) + { + bool has_config = (index == EXP_MEMORYCARD_INDEX || index > EXP_GECKO_INDEX); + m_slot_buttons[i]->setEnabled(has_config); + } + + m_slot_combos[i]->setCurrentIndex(index); + } +} + +void GameCubePane::SaveSettings() +{ + SConfig& params = SConfig::GetInstance(); + + // IPL Settings + params.bHLE_BS2 = m_skip_main_menu->isChecked(); + params.SelectedLanguage = m_language_combo->currentIndex(); + params.bOverrideGCLanguage = m_override_language_ntsc->isChecked(); + + for (int i = 0; i < SLOT_COUNT; i++) + { + auto& dev = SConfig::GetInstance().m_EXIDevice[i]; + + int index = m_slot_combos[i]->currentIndex(); + + if (i <= SLOT_B_INDEX) + { + bool has_config = (index == 3 || index > 4); + m_slot_buttons[i]->setEnabled(has_config); + } + + switch (index) + { + case 0: + dev = ExpansionInterface::EXIDEVICE_NONE; + break; + case 1: + dev = ExpansionInterface::EXIDEVICE_DUMMY; + break; + case 2: + dev = ExpansionInterface::EXIDEVICE_MEMORYCARD; + break; + case 3: + dev = ExpansionInterface::EXIDEVICE_MEMORYCARDFOLDER; + break; + case 4: + dev = ExpansionInterface::EXIDEVICE_GECKO; + break; + case 5: + dev = ExpansionInterface::EXIDEVICE_AGP; + break; + case 6: + dev = ExpansionInterface::EXIDEVICE_MIC; + break; + } + + if (Core::IsRunning() && SConfig::GetInstance().m_EXIDevice[i] != dev) + { + ExpansionInterface::ChangeDevice( + (index == 1) ? 1 : 0, // SlotB is on channel 1, slotA and SP1 are on 0 + dev, // The device enum to change to + (index == 2) ? 2 : 0); // SP1 is device 2, slots are device 0 + } + + SConfig::GetInstance().m_EXIDevice[i] = dev; + } + LoadSettings(); +} diff --git a/Source/Core/DolphinQt2/Settings/GameCubePane.h b/Source/Core/DolphinQt2/Settings/GameCubePane.h new file mode 100644 index 0000000000..a96f769baa --- /dev/null +++ b/Source/Core/DolphinQt2/Settings/GameCubePane.h @@ -0,0 +1,33 @@ +// Copyright 2018 Dolphin Emulator Project +// Licensed under GPLv2+ +// Refer to the license.txt file included. + +#pragma once + +#include + +class QCheckBox; +class QComboBox; +class QPushButton; + +class GameCubePane : public QWidget +{ +public: + explicit GameCubePane(); + +private: + void CreateWidgets(); + void ConnectWidgets(); + + void LoadSettings(); + void SaveSettings(); + + void OnConfigPressed(int slot); + + QCheckBox* m_skip_main_menu; + QCheckBox* m_override_language_ntsc; + QComboBox* m_language_combo; + + QPushButton* m_slot_buttons[2]; + QComboBox* m_slot_combos[3]; +};