mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 16:25:45 +00:00
[frontend] refactor: extract common firmware & key functions (#38)
Extracts some firmware version/verification functions into `frontend_common` to reduce duplicate code, especially for the new QML frontend. Additionally adds a check for games that are known to require firmware (e.g. MK8DX) and warns the user if they don't have firmware installed and attempt to run the game. Firmware installation is to be in a separate PR. Signed-off-by: crueter <crueter@eden-emu.dev> Co-authored-by: Aleksandr Popovich <popovich@eden-emu.dev> Reviewed-on: https://git.eden-emu.dev/eden-emu/eden/pulls/38
This commit is contained in:
parent
55a7797378
commit
03351a4f8b
39 changed files with 1146 additions and 1078 deletions
139
src/frontend_common/firmware_manager.cpp
Normal file
139
src/frontend_common/firmware_manager.cpp
Normal file
|
@ -0,0 +1,139 @@
|
|||
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
||||
// SPDX-License-Identifier: GPL-3.0-or-later
|
||||
|
||||
#include "firmware_manager.h"
|
||||
#include <filesystem>
|
||||
#include <common/fs/fs_paths.h>
|
||||
|
||||
#include "common/fs/fs.h"
|
||||
#include "common/fs/path_util.h"
|
||||
|
||||
#include "common/logging/backend.h"
|
||||
|
||||
#include "core/crypto/key_manager.h"
|
||||
#include "frontend_common/content_manager.h"
|
||||
|
||||
#ifdef ANDROID
|
||||
#include <jni.h>
|
||||
#include <common/android/id_cache.h>
|
||||
#include <common/android/android_common.h>
|
||||
#endif
|
||||
|
||||
FirmwareManager::KeyInstallResult
|
||||
FirmwareManager::InstallKeys(std::string location, std::string extension) {
|
||||
LOG_INFO(Frontend, "Installing key files from {}", location);
|
||||
|
||||
const auto keys_dir = Common::FS::GetEdenPath(Common::FS::EdenPath::KeysDir);
|
||||
|
||||
#ifdef ANDROID
|
||||
JNIEnv *env = Common::Android::GetEnvForThread();
|
||||
|
||||
jstring jsrc = Common::Android::ToJString(env, location);
|
||||
|
||||
jclass native = Common::Android::GetNativeLibraryClass();
|
||||
jmethodID getExtension = Common::Android::GetFileExtension();
|
||||
|
||||
jstring jext = static_cast<jstring>(env->CallStaticObjectMethod(
|
||||
native,
|
||||
getExtension,
|
||||
jsrc
|
||||
));
|
||||
|
||||
std::string ext = Common::Android::GetJString(env, jext);
|
||||
|
||||
if (ext != extension) {
|
||||
return ErrorWrongFilename;
|
||||
}
|
||||
|
||||
jmethodID copyToStorage = Common::Android::GetCopyToStorage();
|
||||
jstring jdest = Common::Android::ToJString(env, keys_dir.string());
|
||||
|
||||
jboolean copyResult = env->CallStaticBooleanMethod(
|
||||
native,
|
||||
copyToStorage,
|
||||
jsrc,
|
||||
jdest
|
||||
);
|
||||
|
||||
if (!copyResult) {
|
||||
return ErrorFailedCopy;
|
||||
}
|
||||
#else
|
||||
if (!location.ends_with(extension)) {
|
||||
return ErrorWrongFilename;
|
||||
}
|
||||
|
||||
bool prod_keys_found = false;
|
||||
|
||||
const std::filesystem::path prod_key_path = location;
|
||||
const std::filesystem::path key_source_path = prod_key_path.parent_path();
|
||||
|
||||
if (!Common::FS::IsDir(key_source_path)) {
|
||||
return InvalidDir;
|
||||
}
|
||||
|
||||
std::vector<std::filesystem::path> source_key_files;
|
||||
|
||||
if (Common::FS::Exists(prod_key_path)) {
|
||||
prod_keys_found = true;
|
||||
source_key_files.emplace_back(prod_key_path);
|
||||
}
|
||||
|
||||
if (Common::FS::Exists(key_source_path / "title.keys")) {
|
||||
source_key_files.emplace_back(key_source_path / "title.keys");
|
||||
}
|
||||
|
||||
if (Common::FS::Exists(key_source_path / "key_retail.bin")) {
|
||||
source_key_files.emplace_back(key_source_path / "key_retail.bin");
|
||||
}
|
||||
|
||||
if (source_key_files.empty() || !prod_keys_found) {
|
||||
return ErrorWrongFilename;
|
||||
}
|
||||
|
||||
for (const auto &key_file : source_key_files) {
|
||||
std::filesystem::path destination_key_file = keys_dir / key_file.filename();
|
||||
if (!std::filesystem::copy_file(key_file,
|
||||
destination_key_file,
|
||||
std::filesystem::copy_options::overwrite_existing)) {
|
||||
LOG_ERROR(Frontend,
|
||||
"Failed to copy file {} to {}",
|
||||
key_file.string(),
|
||||
destination_key_file.string());
|
||||
return ErrorFailedCopy;
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
// Reinitialize the key manager
|
||||
Core::Crypto::KeyManager::Instance().ReloadKeys();
|
||||
|
||||
if (ContentManager::AreKeysPresent()) {
|
||||
return Success;
|
||||
}
|
||||
|
||||
// Let the frontend handle everything else
|
||||
return ErrorFailedInit;
|
||||
}
|
||||
|
||||
FirmwareManager::FirmwareCheckResult FirmwareManager::VerifyFirmware(Core::System &system) {
|
||||
if (!CheckFirmwarePresence(system)) {
|
||||
return ErrorFirmwareMissing;
|
||||
} else {
|
||||
const auto pair = GetFirmwareVersion(system);
|
||||
const auto firmware_data = pair.first;
|
||||
const auto result = pair.second;
|
||||
|
||||
if (result.IsError()) {
|
||||
LOG_INFO(Frontend, "Unable to read firmware");
|
||||
return ErrorFirmwareCorrupted;
|
||||
}
|
||||
|
||||
// TODO: update this whenever newer firmware is properly supported
|
||||
if (firmware_data.major > 19) {
|
||||
return ErrorFirmwareTooNew;
|
||||
}
|
||||
}
|
||||
|
||||
return FirmwareGood;
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue