summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorJMC47 <JMC4789@gmail.com>2021-11-21 15:55:55 -0500
committerGitHub <noreply@github.com>2021-11-21 15:55:55 -0500
commit37247a51a7ddd7c49caa55b3cd925409ae0effdf (patch)
treede5bceb5cd1acb740abd545ce0a814ef5a496b5b /Source/Core
parent05ecff199f553e705e2a32c213a1de2a590dac2d (diff)
parent8488ff6884b2c1ce2666b1d2dbab6e36afad4572 (diff)
Merge pull request #10240 from AdmiralCurtiss/mgba-save-import-export
GBA: Add import and export save options to context menu.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/Core/HW/GBACore.cpp32
-rw-r--r--Source/Core/Core/HW/GBACore.h2
-rw-r--r--Source/Core/DolphinQt/GBAWidget.cpp42
-rw-r--r--Source/Core/DolphinQt/GBAWidget.h1
4 files changed, 77 insertions, 0 deletions
diff --git a/Source/Core/Core/HW/GBACore.cpp b/Source/Core/Core/HW/GBACore.cpp
index 5b65e82a3d..13eb74b720 100644
--- a/Source/Core/Core/HW/GBACore.cpp
+++ b/Source/Core/Core/HW/GBACore.cpp
@@ -612,6 +612,38 @@ void Core::ExportState(std::string_view state_path)
file.WriteBytes(core_state.data(), core_state.size());
}
+void Core::ImportSave(std::string_view save_path)
+{
+ Flush();
+ if (!IsStarted())
+ return;
+
+ File::IOFile file(std::string(save_path), "rb");
+ std::vector<u8> save_file(file.GetSize());
+ if (!file.ReadBytes(save_file.data(), save_file.size()))
+ return;
+
+ m_core->savedataRestore(m_core, save_file.data(), save_file.size(), true);
+ m_core->reset(m_core);
+}
+
+void Core::ExportSave(std::string_view save_path)
+{
+ Flush();
+ if (!IsStarted())
+ return;
+
+ File::IOFile file(std::string(save_path), "wb");
+
+ void* sram = nullptr;
+ size_t size = m_core->savedataClone(m_core, &sram);
+ if (!sram)
+ return;
+
+ file.WriteBytes(sram, size);
+ free(sram);
+}
+
void Core::DoState(PointerWrap& p)
{
Flush();
diff --git a/Source/Core/Core/HW/GBACore.h b/Source/Core/Core/HW/GBACore.h
index 51fcdf0d10..79f522bd9d 100644
--- a/Source/Core/Core/HW/GBACore.h
+++ b/Source/Core/Core/HW/GBACore.h
@@ -68,6 +68,8 @@ public:
void ImportState(std::string_view state_path);
void ExportState(std::string_view state_path);
+ void ImportSave(std::string_view save_path);
+ void ExportSave(std::string_view save_path);
void DoState(PointerWrap& p);
static bool GetRomInfo(const char* rom_path, std::array<u8, 20>& hash, std::string& title);
diff --git a/Source/Core/DolphinQt/GBAWidget.cpp b/Source/Core/DolphinQt/GBAWidget.cpp
index d7aca071e5..d2eb8dd694 100644
--- a/Source/Core/DolphinQt/GBAWidget.cpp
+++ b/Source/Core/DolphinQt/GBAWidget.cpp
@@ -229,6 +229,36 @@ void GBAWidget::DoState(bool export_state)
false);
}
+void GBAWidget::ImportExportSave(bool export_save)
+{
+ if (!CanControlCore() && !export_save)
+ return;
+ if (!m_core_info.has_rom)
+ return;
+
+ QString save_path = QDir::toNativeSeparators(
+ (export_save ? DolphinFileDialog::getSaveFileName :
+ DolphinFileDialog::getOpenFileName)(this, tr("Select a File"), QString(),
+ tr("Save Game Files (*.sav);;"
+ "All Files (*)"),
+ nullptr, QFileDialog::Options()));
+
+ if (save_path.isEmpty())
+ return;
+
+ Core::RunOnCPUThread(
+ [export_save, core = m_core, save_path = save_path.toStdString()] {
+ if (auto core_ptr = core.lock())
+ {
+ if (export_save)
+ core_ptr->ExportSave(save_path);
+ else
+ core_ptr->ImportSave(save_path);
+ }
+ },
+ false);
+}
+
void GBAWidget::Resize(int scale)
{
showNormal();
@@ -371,6 +401,14 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
reset_action->setEnabled(CanResetCore());
connect(reset_action, &QAction::triggered, this, &GBAWidget::ResetCore);
+ auto* savefile_menu = new QMenu(tr("Save Game"), menu);
+ auto* save_import_action = new QAction(tr("&Import Save Game..."), savefile_menu);
+ save_import_action->setEnabled(CanControlCore() && m_core_info.has_rom);
+ connect(save_import_action, &QAction::triggered, this, [this] { ImportExportSave(false); });
+ auto* save_export_action = new QAction(tr("&Export Save Game..."), savefile_menu);
+ save_export_action->setEnabled(m_core_info.has_rom);
+ connect(save_export_action, &QAction::triggered, this, [this] { ImportExportSave(true); });
+
auto* state_menu = new QMenu(tr("Save State"), menu);
auto* import_action = new QAction(tr("&Import State..."), state_menu);
import_action->setEnabled(CanControlCore());
@@ -418,12 +456,16 @@ void GBAWidget::contextMenuEvent(QContextMenuEvent* event)
menu->addAction(card_action);
menu->addAction(reset_action);
menu->addSeparator();
+ menu->addMenu(savefile_menu);
menu->addMenu(state_menu);
menu->addSeparator();
menu->addAction(mute_action);
menu->addSeparator();
menu->addMenu(options_menu);
+ savefile_menu->addAction(save_import_action);
+ savefile_menu->addAction(save_export_action);
+
state_menu->addAction(import_action);
state_menu->addAction(export_state);
diff --git a/Source/Core/DolphinQt/GBAWidget.h b/Source/Core/DolphinQt/GBAWidget.h
index 949858a4b7..7d90aad37e 100644
--- a/Source/Core/DolphinQt/GBAWidget.h
+++ b/Source/Core/DolphinQt/GBAWidget.h
@@ -51,6 +51,7 @@ public:
void PromptForEReaderCards();
void ResetCore();
void DoState(bool export_state);
+ void ImportExportSave(bool export_save);
void Resize(int scale);
bool IsBorderless() const;