diff --git a/Source/Core/DolphinQt/CMakeLists.txt b/Source/Core/DolphinQt/CMakeLists.txt
index 8449920c61..1121424812 100644
--- a/Source/Core/DolphinQt/CMakeLists.txt
+++ b/Source/Core/DolphinQt/CMakeLists.txt
@@ -200,6 +200,8 @@ add_executable(dolphin-emu
GameList/GridProxyModel.h
GameList/ListProxyModel.cpp
GameList/ListProxyModel.h
+ GCMemcardCreateNewDialog.cpp
+ GCMemcardCreateNewDialog.h
GCMemcardManager.cpp
GCMemcardManager.h
QtUtils/BlockUserInputFilter.cpp
diff --git a/Source/Core/DolphinQt/DolphinQt.vcxproj b/Source/Core/DolphinQt/DolphinQt.vcxproj
index 023f50a5e1..936a412a7e 100644
--- a/Source/Core/DolphinQt/DolphinQt.vcxproj
+++ b/Source/Core/DolphinQt/DolphinQt.vcxproj
@@ -153,6 +153,7 @@
+
@@ -225,6 +226,7 @@
+
@@ -401,6 +403,7 @@
+
diff --git a/Source/Core/DolphinQt/GCMemcardCreateNewDialog.cpp b/Source/Core/DolphinQt/GCMemcardCreateNewDialog.cpp
new file mode 100644
index 0000000000..cbd77ee32a
--- /dev/null
+++ b/Source/Core/DolphinQt/GCMemcardCreateNewDialog.cpp
@@ -0,0 +1,87 @@
+// Copyright 2019 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#include "DolphinQt/GCMemcardCreateNewDialog.h"
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+#include "Common/FileUtil.h"
+#include "Common/MsgHandler.h"
+
+#include "Core/HW/GCMemcard/GCMemcard.h"
+
+GCMemcardCreateNewDialog::GCMemcardCreateNewDialog(QWidget* parent) : QDialog(parent)
+{
+ m_combobox_size = new QComboBox();
+ m_combobox_size->addItem(tr("4 Mbit (59 blocks)"), 4);
+ m_combobox_size->addItem(tr("8 Mbit (123 blocks)"), 8);
+ m_combobox_size->addItem(tr("16 Mbit (251 blocks)"), 16);
+ m_combobox_size->addItem(tr("32 Mbit (507 blocks)"), 32);
+ m_combobox_size->addItem(tr("64 Mbit (1019 blocks)"), 64);
+ m_combobox_size->addItem(tr("128 Mbit (2043 blocks)"), 128);
+ m_combobox_size->setCurrentIndex(5);
+
+ m_radio_western = new QRadioButton(tr("Western (Windows-1252)"));
+ m_radio_shiftjis = new QRadioButton(tr("Japanese (Shift-JIS)"));
+ m_radio_western->setChecked(true);
+
+ auto* card_size_label = new QLabel(tr("Card Size"));
+ auto* card_encoding_label = new QLabel(tr("Encoding"));
+ auto* button_box = new QDialogButtonBox(QDialogButtonBox::Ok | QDialogButtonBox::Cancel, this);
+ button_box->button(QDialogButtonBox::Ok)->setText(tr("Create..."));
+
+ auto* layout = new QGridLayout();
+ layout->addWidget(card_size_label, 0, 0);
+ layout->addWidget(m_combobox_size, 0, 1);
+ layout->addWidget(card_encoding_label, 1, 0);
+ layout->addWidget(m_radio_western, 1, 1);
+ layout->addWidget(m_radio_shiftjis, 2, 1);
+ layout->addWidget(button_box, 3, 0, 1, 2, Qt::AlignRight);
+ setLayout(layout);
+
+ connect(button_box, &QDialogButtonBox::rejected, this, &QDialog::reject);
+ connect(button_box, &QDialogButtonBox::accepted, [this] {
+ if (CreateCard())
+ accept();
+ });
+
+ setWindowTitle(tr("Create New Memory Card"));
+ setWindowFlags(windowFlags() & ~Qt::WindowContextHelpButtonHint);
+}
+
+GCMemcardCreateNewDialog::~GCMemcardCreateNewDialog() = default;
+
+bool GCMemcardCreateNewDialog::CreateCard()
+{
+ const u16 size = static_cast(m_combobox_size->currentData().toInt());
+ const bool is_shift_jis = m_radio_shiftjis->isChecked();
+
+ const QString path = QFileDialog::getSaveFileName(
+ this, tr("Create New Memory Card"), QString::fromStdString(File::GetUserPath(D_GCUSER_IDX)),
+ tr("GameCube Memory Cards (*.raw *.gcp)") + QStringLiteral(";;") + tr("All Files (*)"));
+
+ if (path.isEmpty())
+ return false;
+
+ const std::string p = path.toStdString();
+ auto memcard = GCMemcard::Create(p, size, is_shift_jis);
+ if (memcard && memcard->Save())
+ {
+ m_card_path = p;
+ return true;
+ }
+
+ return false;
+}
+
+std::string GCMemcardCreateNewDialog::GetMemoryCardPath() const
+{
+ return m_card_path;
+}
diff --git a/Source/Core/DolphinQt/GCMemcardCreateNewDialog.h b/Source/Core/DolphinQt/GCMemcardCreateNewDialog.h
new file mode 100644
index 0000000000..571699ea49
--- /dev/null
+++ b/Source/Core/DolphinQt/GCMemcardCreateNewDialog.h
@@ -0,0 +1,28 @@
+// Copyright 2019 Dolphin Emulator Project
+// Licensed under GPLv2+
+// Refer to the license.txt file included.
+
+#pragma once
+
+#include
+
+class QComboBox;
+class QRadioButton;
+
+class GCMemcardCreateNewDialog : public QDialog
+{
+ Q_OBJECT
+public:
+ explicit GCMemcardCreateNewDialog(QWidget* parent = nullptr);
+ ~GCMemcardCreateNewDialog();
+
+ std::string GetMemoryCardPath() const;
+
+private:
+ bool CreateCard();
+
+ QComboBox* m_combobox_size;
+ QRadioButton* m_radio_western;
+ QRadioButton* m_radio_shiftjis;
+ std::string m_card_path;
+};
diff --git a/Source/Core/DolphinQt/GCMemcardManager.cpp b/Source/Core/DolphinQt/GCMemcardManager.cpp
index 52c2dcfa35..6a20522980 100644
--- a/Source/Core/DolphinQt/GCMemcardManager.cpp
+++ b/Source/Core/DolphinQt/GCMemcardManager.cpp
@@ -30,6 +30,7 @@
#include "Core/Config/MainSettings.h"
#include "Core/HW/GCMemcard/GCMemcard.h"
+#include "DolphinQt/GCMemcardCreateNewDialog.h"
#include "DolphinQt/QtUtils/ModalMessageBox.h"
constexpr float ROW_HEIGHT = 28;
@@ -91,7 +92,8 @@ void GCMemcardManager::CreateWidgets()
{
m_slot_group[i] = new QGroupBox(i == 0 ? tr("Slot A") : tr("Slot B"));
m_slot_file_edit[i] = new QLineEdit;
- m_slot_file_button[i] = new QPushButton(tr("&Browse..."));
+ m_slot_open_button[i] = new QPushButton(tr("&Open..."));
+ m_slot_create_button[i] = new QPushButton(tr("&Create..."));
m_slot_table[i] = new QTableWidget;
m_slot_table[i]->setTabKeyNavigation(false);
m_slot_stat_label[i] = new QLabel;
@@ -107,8 +109,9 @@ void GCMemcardManager::CreateWidgets()
m_slot_group[i]->setLayout(slot_layout);
slot_layout->addWidget(m_slot_file_edit[i], 0, 0);
- slot_layout->addWidget(m_slot_file_button[i], 0, 1);
- slot_layout->addWidget(m_slot_table[i], 1, 0, 1, 2);
+ slot_layout->addWidget(m_slot_open_button[i], 0, 1);
+ slot_layout->addWidget(m_slot_create_button[i], 0, 2);
+ slot_layout->addWidget(m_slot_table[i], 1, 0, 1, 3);
slot_layout->addWidget(m_slot_stat_label[i], 2, 0);
layout->addWidget(m_slot_group[i], 0, i * 2, 9, 1);
@@ -143,8 +146,10 @@ void GCMemcardManager::ConnectWidgets()
{
connect(m_slot_file_edit[slot], &QLineEdit::textChanged,
[this, slot](const QString& path) { SetSlotFile(slot, path); });
- connect(m_slot_file_button[slot], &QPushButton::clicked,
+ connect(m_slot_open_button[slot], &QPushButton::clicked,
[this, slot] { SetSlotFileInteractive(slot); });
+ connect(m_slot_create_button[slot], &QPushButton::clicked,
+ [this, slot] { CreateNewCard(slot); });
connect(m_slot_table[slot], &QTableWidget::itemSelectionChanged, this,
&GCMemcardManager::UpdateActions);
}
@@ -459,6 +464,13 @@ void GCMemcardManager::FixChecksums()
PanicAlertT("File write failed");
}
+void GCMemcardManager::CreateNewCard(int slot)
+{
+ GCMemcardCreateNewDialog dialog(this);
+ if (dialog.exec() == QDialog::Accepted)
+ m_slot_file_edit[slot]->setText(QString::fromStdString(dialog.GetMemoryCardPath()));
+}
+
void GCMemcardManager::DrawIcons()
{
const auto column = 3;
diff --git a/Source/Core/DolphinQt/GCMemcardManager.h b/Source/Core/DolphinQt/GCMemcardManager.h
index 1f8b8ad3a3..ccacf98c2c 100644
--- a/Source/Core/DolphinQt/GCMemcardManager.h
+++ b/Source/Core/DolphinQt/GCMemcardManager.h
@@ -54,6 +54,7 @@ private:
void ExportFiles(bool prompt);
void ExportAllFiles();
void FixChecksums();
+ void CreateNewCard(int slot);
void DrawIcons();
QPixmap GetBannerFromSaveFile(int file_index, int slot);
@@ -75,7 +76,8 @@ private:
std::array, SLOT_COUNT> m_slot_memcard;
std::array m_slot_group;
std::array m_slot_file_edit;
- std::array m_slot_file_button;
+ std::array m_slot_open_button;
+ std::array m_slot_create_button;
std::array m_slot_table;
std::array m_slot_stat_label;