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 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& 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;