forgot the files

This commit is contained in:
Maufeat 2026-02-08 06:19:33 +01:00
parent 23b5b23b8b
commit c04bdcbc6b
2 changed files with 215 additions and 0 deletions

View File

@ -0,0 +1,179 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#include "overrides_updater.h"
#include <QCheckBox>
#include <QMessageBox>
#include <QPushButton>
#include <QtConcurrent>
#include <fstream>
#include "common/logging/log.h"
#include "core/game_overrides.h"
#include "qt_common/config/uisettings.h"
#include <httplib.h>
#ifdef YUZU_BUNDLED_OPENSSL
#include <openssl/cert.h>
#endif
OverridesUpdater::OverridesUpdater(QWidget* parent)
: QObject(parent), parent_widget(parent) {}
OverridesUpdater::~OverridesUpdater() = default;
void OverridesUpdater::CheckAndUpdate() {
if (!UISettings::values.enable_global_overrides.GetValue()) {
return;
}
if (!UISettings::values.overrides_consent_given.GetValue()) {
ShowConsentDialog();
return;
}
if (UISettings::values.auto_update_overrides.GetValue()) {
(void)QtConcurrent::run([this] {
DownloadAndSave();
});
}
}
void OverridesUpdater::ShowConsentDialog() {
QMessageBox msgBox(parent_widget);
msgBox.setWindowTitle(tr("Game Overrides Database"));
msgBox.setIcon(QMessageBox::Question);
msgBox.setText(tr("Would you like to update the game overrides database?"));
msgBox.setInformativeText(
tr("This will download a config file from GitHub to enable critical per-game settings.\n\n"
"Your choice will be saved. You can change this later in:\n"
"Settings -> General -> Enable global game overrides"));
QCheckBox autoUpdateCheckbox(tr("Automatically update the list"), &msgBox);
autoUpdateCheckbox.setChecked(true);
msgBox.setCheckBox(&autoUpdateCheckbox);
auto* yesButton = msgBox.addButton(tr("Yes, Enable"), QMessageBox::AcceptRole);
msgBox.addButton(tr("No Thanks"), QMessageBox::RejectRole);
msgBox.setDefaultButton(yesButton);
msgBox.exec();
auto* clicked = msgBox.clickedButton();
UISettings::values.overrides_consent_given.SetValue(true);
if (clicked == yesButton) {
UISettings::values.auto_update_overrides.SetValue(autoUpdateCheckbox.isChecked());
UISettings::values.enable_global_overrides.SetValue(true);
emit ConfigChanged();
DownloadOverrides();
} else {
UISettings::values.auto_update_overrides.SetValue(false);
UISettings::values.enable_global_overrides.SetValue(false);
emit ConfigChanged();
}
}
void OverridesUpdater::DownloadOverrides() {
(void)QtConcurrent::run([this] {
const bool success = DownloadAndSave();
emit UpdateCompleted(success, success
? tr("Game overrides updated successfully.")
: tr("Failed to download game overrides."));
});
}
std::optional<std::string> OverridesUpdater::FetchOverridesFile() {
try {
constexpr std::size_t timeout_seconds = 3;
std::unique_ptr<httplib::Client> client = std::make_unique<httplib::Client>(kOverridesUrl);
client->set_connection_timeout(timeout_seconds);
client->set_read_timeout(timeout_seconds);
client->set_write_timeout(timeout_seconds);
#ifdef YUZU_BUNDLED_OPENSSL
client->load_ca_cert_store(kCert, sizeof(kCert));
#endif
httplib::Request request{
.method = "GET",
.path = kOverridesPath,
};
client->set_follow_location(true);
httplib::Result result = client->send(request);
if (!result) {
LOG_ERROR(Frontend, "GET to {}{} returned null", kOverridesUrl, kOverridesPath);
return {};
}
return result.value().body;
} catch (const std::exception& e) {
LOG_ERROR(Frontend, "Failed to fetch overrides: {}", e.what());
return {};
}
}
bool OverridesUpdater::DownloadAndSave() {
LOG_INFO(Frontend, "Checking for game overrides updates...");
const auto response = FetchOverridesFile();
if (!response) {
return false;
}
const auto& data = *response;
auto remote_version = ParseVersion(data);
if (!remote_version) {
LOG_ERROR(Frontend, "Downloaded overrides file has invalid format (no version header)");
return false;
}
auto local_version = Core::GameOverrides::GetOverridesFileVersion();
if (local_version && *local_version >= *remote_version) {
LOG_INFO(Frontend, "Game overrides are up to date (v{})", *local_version);
return true;
}
const auto path = Core::GameOverrides::GetOverridesPath();
std::filesystem::create_directories(path.parent_path());
std::ofstream file(path, std::ios::binary);
if (!file.is_open()) {
LOG_ERROR(Frontend, "Failed to write overrides file: {}", path.string());
return false;
}
file.write(data.data(), static_cast<std::streamsize>(data.size()));
file.close();
LOG_INFO(Frontend, "Game overrides updated to version {}", *remote_version);
return true;
}
std::optional<std::uint32_t> OverridesUpdater::ParseVersion(const std::string& data) {
// Look for "; version=X" on first line
const auto newline_pos = data.find('\n');
const std::string first_line = (newline_pos != std::string::npos)
? data.substr(0, newline_pos)
: data;
constexpr const char* prefix = "; version=";
const auto prefix_pos = first_line.find(prefix);
if (prefix_pos == std::string::npos) {
return {};
}
const auto version_str = first_line.substr(prefix_pos + std::strlen(prefix));
try {
return static_cast<std::uint32_t>(std::stoul(version_str));
} catch (...) {
return {};
}
}

View File

@ -0,0 +1,36 @@
// SPDX-FileCopyrightText: Copyright 2026 Eden Emulator Project
// SPDX-License-Identifier: GPL-3.0-or-later
#pragma once
#include <QObject>
#include <QString>
#include <optional>
class QWidget;
class OverridesUpdater : public QObject {
Q_OBJECT
public:
explicit OverridesUpdater(QWidget* parent = nullptr);
~OverridesUpdater() override;
void CheckAndUpdate();
void DownloadOverrides();
signals:
void ConfigChanged();
void UpdateCompleted(bool success, const QString& message);
private:
void ShowConsentDialog();
bool DownloadAndSave();
static std::optional<std::uint32_t> ParseVersion(const std::string& data);
static std::optional<std::string> FetchOverridesFile();
QWidget* parent_widget{};
static constexpr const char* kOverridesUrl = "https://raw.githubusercontent.com";
static constexpr const char* kOverridesPath = "/eden-emulator/eden-overrides/refs/heads/master/overrides.ini";
};