mirror of
https://git.eden-emu.dev/eden-emu/eden.git
synced 2025-07-20 08:15:46 +00:00
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
148 lines
37 KiB
C++
148 lines
37 KiB
C++
// SPDX-FileCopyrightText: Copyright 2025 Eden Emulator Project
|
|
// SPDX-License-Identifier: GPL-3.0-or-later
|
|
|
|
#ifndef FIRMWARE_MANAGER_H
|
|
#define FIRMWARE_MANAGER_H
|
|
|
|
#include "common/common_types.h"
|
|
#include "core/core.h"
|
|
#include "core/file_sys/nca_metadata.h"
|
|
#include "core/file_sys/registered_cache.h"
|
|
#include "core/hle/service/filesystem/filesystem.h"
|
|
#include <algorithm>
|
|
#include <array>
|
|
#include <core/hle/service/am/frontend/applet_mii_edit.h>
|
|
#include <string>
|
|
|
|
#include "core/hle/service/set/settings_types.h"
|
|
#include "core/hle/service/set/system_settings_server.h"
|
|
#include "core/hle/result.h"
|
|
|
|
namespace FirmwareManager {
|
|
|
|
static constexpr std::array<const char *, 5> KEY_INSTALL_RESULT_STRINGS = {
|
|
"Decryption Keys were successfully installed",
|
|
"Unable to read key directory, aborting",
|
|
"One or more keys failed to copy.",
|
|
"Verify your keys file has a .keys extension and try again.",
|
|
"Decryption Keys failed to initialize. Check that your dumping tools are up to date and "
|
|
"re-dump keys.",
|
|
};
|
|
|
|
static constexpr std::array<u64, 1> FIRMWARE_REQUIRED_GAMES = {
|
|
0x0100152000022000ULL, // MK8DX
|
|
};
|
|
|
|
enum KeyInstallResult {
|
|
Success,
|
|
InvalidDir,
|
|
ErrorFailedCopy,
|
|
ErrorWrongFilename,
|
|
ErrorFailedInit,
|
|
};
|
|
|
|
/**
|
|
* @brief Installs any arbitrary set of keys for the emulator.
|
|
* @param location Where the keys are located.
|
|
* @param expected_extension What extension the file should have.
|
|
* @return A result code for the operation.
|
|
*/
|
|
KeyInstallResult InstallKeys(std::string location, std::string expected_extension);
|
|
|
|
/**
|
|
* \brief Get a string representation of a result from InstallKeys.
|
|
* \param result The result code.
|
|
* \return A string representation of the passed result code.
|
|
*/
|
|
inline constexpr const char *GetKeyInstallResultString(KeyInstallResult result)
|
|
{
|
|
return KEY_INSTALL_RESULT_STRINGS.at(static_cast<std::size_t>(result));
|
|
}
|
|
|
|
/**
|
|
* \brief Check if the specified program requires firmware to run properly.
|
|
* It is the responsibility of the frontend to properly expose this to the user.
|
|
* \param program_id The program ID to check.
|
|
* \return Whether or not the program requires firmware to run properly.
|
|
*/
|
|
inline constexpr bool GameRequiresFirmware(u64 program_id)
|
|
{
|
|
return std::find(FIRMWARE_REQUIRED_GAMES.begin(), FIRMWARE_REQUIRED_GAMES.end(), program_id)
|
|
!= FIRMWARE_REQUIRED_GAMES.end();
|
|
}
|
|
|
|
|
|
enum FirmwareCheckResult {
|
|
FirmwareGood,
|
|
ErrorFirmwareMissing,
|
|
ErrorFirmwareCorrupted,
|
|
ErrorFirmwareTooNew,
|
|
};
|
|
|
|
static constexpr std::array<const char *, 4> FIRMWARE_CHECK_STRINGS = {
|
|
"",
|
|
"Firmware missing. Firmware is required to run certain games and use the Home Menu. "
|
|
"Eden only works with firmware 19.0.1 and earlier.",
|
|
"Firmware reported as present, but was unable to be read. Check for decryption keys and "
|
|
"redump firmware if necessary.",
|
|
"Firmware is too new or could not be read. Eden only works with firmware 19.0.1 and earlier.",
|
|
};
|
|
|
|
/**
|
|
* \brief Checks for installed firmware within the system.
|
|
* \param system The system to check for firmware.
|
|
* \return Whether or not the system has installed firmware.
|
|
*/
|
|
inline bool CheckFirmwarePresence(Core::System &system)
|
|
{
|
|
constexpr u64 MiiEditId = static_cast<u64>(Service::AM::AppletProgramId::MiiEdit);
|
|
|
|
auto bis_system = system.GetFileSystemController().GetSystemNANDContents();
|
|
if (!bis_system) {
|
|
return false;
|
|
}
|
|
|
|
auto mii_applet_nca = bis_system->GetEntry(MiiEditId, FileSys::ContentRecordType::Program);
|
|
|
|
if (!mii_applet_nca) {
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
/**
|
|
* \brief Verifies if firmware is properly installed and is in the correct version range.
|
|
* \param system The system to check firmware on.
|
|
* \return A result code defining the status of the system's firmware.
|
|
*/
|
|
FirmwareCheckResult VerifyFirmware(Core::System &system);
|
|
|
|
/**
|
|
* \brief Get a string representation of a result from CheckFirmwareVersion.
|
|
* \param result The result code.
|
|
* \return A string representation of the passed result code.
|
|
*/
|
|
inline constexpr const char *GetFirmwareCheckString(FirmwareCheckResult result)
|
|
{
|
|
return FIRMWARE_CHECK_STRINGS.at(static_cast<std::size_t>(result));
|
|
}
|
|
|
|
/**
|
|
* @brief Get the currently installed firmware version.
|
|
* @param system The system to check firmware on.
|
|
* @return A pair of the firmware version format and result code.
|
|
*/
|
|
inline std::pair<Service::Set::FirmwareVersionFormat, Result> GetFirmwareVersion(Core::System &system)
|
|
{
|
|
Service::Set::FirmwareVersionFormat firmware_data{};
|
|
const auto result
|
|
= Service::Set::GetFirmwareVersionImpl(firmware_data,
|
|
system,
|
|
Service::Set::GetFirmwareVersionType::Version2);
|
|
|
|
return {firmware_data, result};
|
|
}
|
|
}
|
|
|
|
#endif // FIRMWARE_MANAGER_H
|