Merge pull request #3498 from wwylele/cfg-new-framework
Service/CFG: convert to ServiceFramework
This commit is contained in:
commit
171cb4452f
|
@ -42,22 +42,16 @@ void ConfigureSystem::setConfiguration() {
|
||||||
enabled = !Core::System::GetInstance().IsPoweredOn();
|
enabled = !Core::System::GetInstance().IsPoweredOn();
|
||||||
|
|
||||||
if (!enabled) {
|
if (!enabled) {
|
||||||
|
cfg = Service::CFG::GetCurrentModule();
|
||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
ui->group_system_settings->setEnabled(false);
|
ui->group_system_settings->setEnabled(false);
|
||||||
} else {
|
} else {
|
||||||
// This tab is enabled only when game is not running (i.e. all service are not initialized).
|
// This tab is enabled only when game is not running (i.e. all service are not initialized).
|
||||||
// Temporarily register archive types and load the config savegame file to memory.
|
// Temporarily register archive types and load the config savegame file to memory.
|
||||||
Service::FS::RegisterArchiveTypes();
|
Service::FS::RegisterArchiveTypes();
|
||||||
ResultCode result = Service::CFG::LoadConfigNANDSaveFile();
|
cfg = std::make_shared<Service::CFG::Module>();
|
||||||
Service::FS::UnregisterArchiveTypes();
|
Service::FS::UnregisterArchiveTypes();
|
||||||
|
|
||||||
if (result.IsError()) {
|
|
||||||
ui->label_disable_info->setText(tr("Failed to load system settings data."));
|
|
||||||
ui->group_system_settings->setEnabled(false);
|
|
||||||
enabled = false;
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
ReadSystemSettings();
|
ReadSystemSettings();
|
||||||
ui->label_disable_info->hide();
|
ui->label_disable_info->hide();
|
||||||
}
|
}
|
||||||
|
@ -65,14 +59,14 @@ void ConfigureSystem::setConfiguration() {
|
||||||
|
|
||||||
void ConfigureSystem::ReadSystemSettings() {
|
void ConfigureSystem::ReadSystemSettings() {
|
||||||
// set username
|
// set username
|
||||||
username = Service::CFG::GetUsername();
|
username = cfg->GetUsername();
|
||||||
// TODO(wwylele): Use this when we move to Qt 5.5
|
// TODO(wwylele): Use this when we move to Qt 5.5
|
||||||
// ui->edit_username->setText(QString::fromStdU16String(username));
|
// ui->edit_username->setText(QString::fromStdU16String(username));
|
||||||
ui->edit_username->setText(
|
ui->edit_username->setText(
|
||||||
QString::fromUtf16(reinterpret_cast<const ushort*>(username.data())));
|
QString::fromUtf16(reinterpret_cast<const ushort*>(username.data())));
|
||||||
|
|
||||||
// set birthday
|
// set birthday
|
||||||
std::tie(birthmonth, birthday) = Service::CFG::GetBirthday();
|
std::tie(birthmonth, birthday) = cfg->GetBirthday();
|
||||||
ui->combo_birthmonth->setCurrentIndex(birthmonth - 1);
|
ui->combo_birthmonth->setCurrentIndex(birthmonth - 1);
|
||||||
updateBirthdayComboBox(
|
updateBirthdayComboBox(
|
||||||
birthmonth -
|
birthmonth -
|
||||||
|
@ -80,15 +74,15 @@ void ConfigureSystem::ReadSystemSettings() {
|
||||||
ui->combo_birthday->setCurrentIndex(birthday - 1);
|
ui->combo_birthday->setCurrentIndex(birthday - 1);
|
||||||
|
|
||||||
// set system language
|
// set system language
|
||||||
language_index = Service::CFG::GetSystemLanguage();
|
language_index = cfg->GetSystemLanguage();
|
||||||
ui->combo_language->setCurrentIndex(language_index);
|
ui->combo_language->setCurrentIndex(language_index);
|
||||||
|
|
||||||
// set sound output mode
|
// set sound output mode
|
||||||
sound_index = Service::CFG::GetSoundOutputMode();
|
sound_index = cfg->GetSoundOutputMode();
|
||||||
ui->combo_sound->setCurrentIndex(sound_index);
|
ui->combo_sound->setCurrentIndex(sound_index);
|
||||||
|
|
||||||
// set the console id
|
// set the console id
|
||||||
u64 console_id = Service::CFG::GetConsoleUniqueId();
|
u64 console_id = cfg->GetConsoleUniqueId();
|
||||||
ui->label_console_id->setText(
|
ui->label_console_id->setText(
|
||||||
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
tr("Console ID: 0x%1").arg(QString::number(console_id, 16).toUpper()));
|
||||||
}
|
}
|
||||||
|
@ -105,7 +99,7 @@ void ConfigureSystem::applyConfiguration() {
|
||||||
std::u16string new_username(
|
std::u16string new_username(
|
||||||
reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16()));
|
reinterpret_cast<const char16_t*>(ui->edit_username->text().utf16()));
|
||||||
if (new_username != username) {
|
if (new_username != username) {
|
||||||
Service::CFG::SetUsername(new_username);
|
cfg->SetUsername(new_username);
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -113,27 +107,27 @@ void ConfigureSystem::applyConfiguration() {
|
||||||
int new_birthmonth = ui->combo_birthmonth->currentIndex() + 1;
|
int new_birthmonth = ui->combo_birthmonth->currentIndex() + 1;
|
||||||
int new_birthday = ui->combo_birthday->currentIndex() + 1;
|
int new_birthday = ui->combo_birthday->currentIndex() + 1;
|
||||||
if (birthmonth != new_birthmonth || birthday != new_birthday) {
|
if (birthmonth != new_birthmonth || birthday != new_birthday) {
|
||||||
Service::CFG::SetBirthday(new_birthmonth, new_birthday);
|
cfg->SetBirthday(new_birthmonth, new_birthday);
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply language
|
// apply language
|
||||||
int new_language = ui->combo_language->currentIndex();
|
int new_language = ui->combo_language->currentIndex();
|
||||||
if (language_index != new_language) {
|
if (language_index != new_language) {
|
||||||
Service::CFG::SetSystemLanguage(static_cast<Service::CFG::SystemLanguage>(new_language));
|
cfg->SetSystemLanguage(static_cast<Service::CFG::SystemLanguage>(new_language));
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// apply sound
|
// apply sound
|
||||||
int new_sound = ui->combo_sound->currentIndex();
|
int new_sound = ui->combo_sound->currentIndex();
|
||||||
if (sound_index != new_sound) {
|
if (sound_index != new_sound) {
|
||||||
Service::CFG::SetSoundOutputMode(static_cast<Service::CFG::SoundOutputMode>(new_sound));
|
cfg->SetSoundOutputMode(static_cast<Service::CFG::SoundOutputMode>(new_sound));
|
||||||
modified = true;
|
modified = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
// update the config savegame if any item is modified.
|
// update the config savegame if any item is modified.
|
||||||
if (modified)
|
if (modified)
|
||||||
Service::CFG::UpdateConfigNANDSavegame();
|
cfg->UpdateConfigNANDSavegame();
|
||||||
}
|
}
|
||||||
|
|
||||||
void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) {
|
void ConfigureSystem::updateBirthdayComboBox(int birthmonth_index) {
|
||||||
|
@ -173,9 +167,9 @@ void ConfigureSystem::refreshConsoleID() {
|
||||||
return;
|
return;
|
||||||
u32 random_number;
|
u32 random_number;
|
||||||
u64 console_id;
|
u64 console_id;
|
||||||
Service::CFG::GenerateConsoleUniqueId(random_number, console_id);
|
cfg->GenerateConsoleUniqueId(random_number, console_id);
|
||||||
Service::CFG::SetConsoleUniqueId(random_number, console_id);
|
cfg->SetConsoleUniqueId(random_number, console_id);
|
||||||
Service::CFG::UpdateConfigNANDSavegame();
|
cfg->UpdateConfigNANDSavegame();
|
||||||
ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper());
|
ui->label_console_id->setText("Console ID: 0x" + QString::number(console_id, 16).toUpper());
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -11,6 +11,12 @@ namespace Ui {
|
||||||
class ConfigureSystem;
|
class ConfigureSystem;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
namespace Service {
|
||||||
|
namespace CFG {
|
||||||
|
class Module;
|
||||||
|
} // namespace CFG
|
||||||
|
} // namespace Service
|
||||||
|
|
||||||
class ConfigureSystem : public QWidget {
|
class ConfigureSystem : public QWidget {
|
||||||
Q_OBJECT
|
Q_OBJECT
|
||||||
|
|
||||||
|
@ -32,6 +38,7 @@ private:
|
||||||
std::unique_ptr<Ui::ConfigureSystem> ui;
|
std::unique_ptr<Ui::ConfigureSystem> ui;
|
||||||
bool enabled;
|
bool enabled;
|
||||||
|
|
||||||
|
std::shared_ptr<Service::CFG::Module> cfg;
|
||||||
std::u16string username;
|
std::u16string username;
|
||||||
int birthmonth, birthday;
|
int birthmonth, birthday;
|
||||||
int language_index;
|
int language_index;
|
||||||
|
|
|
@ -10,7 +10,6 @@
|
||||||
#include <utility>
|
#include <utility>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/kernel/handle_table.h"
|
|
||||||
#include "core/hle/kernel/hle_ipc.h"
|
#include "core/hle/kernel/hle_ipc.h"
|
||||||
#include "core/hle/kernel/kernel.h"
|
#include "core/hle/kernel/kernel.h"
|
||||||
|
|
||||||
|
@ -18,7 +17,7 @@ namespace IPC {
|
||||||
|
|
||||||
class RequestHelperBase {
|
class RequestHelperBase {
|
||||||
protected:
|
protected:
|
||||||
Kernel::HLERequestContext* context = nullptr;
|
Kernel::HLERequestContext* context;
|
||||||
u32* cmdbuf;
|
u32* cmdbuf;
|
||||||
ptrdiff_t index = 1;
|
ptrdiff_t index = 1;
|
||||||
Header header;
|
Header header;
|
||||||
|
@ -27,9 +26,6 @@ public:
|
||||||
RequestHelperBase(Kernel::HLERequestContext& context, Header desired_header)
|
RequestHelperBase(Kernel::HLERequestContext& context, Header desired_header)
|
||||||
: context(&context), cmdbuf(context.CommandBuffer()), header(desired_header) {}
|
: context(&context), cmdbuf(context.CommandBuffer()), header(desired_header) {}
|
||||||
|
|
||||||
RequestHelperBase(u32* command_buffer, Header command_header)
|
|
||||||
: cmdbuf(command_buffer), header(command_header) {}
|
|
||||||
|
|
||||||
/// Returns the total size of the request in words
|
/// Returns the total size of the request in words
|
||||||
size_t TotalSize() const {
|
size_t TotalSize() const {
|
||||||
return 1 /* command header */ + header.normal_params_size + header.translate_params_size;
|
return 1 /* command header */ + header.normal_params_size + header.translate_params_size;
|
||||||
|
@ -62,19 +58,6 @@ public:
|
||||||
: RequestBuilder(
|
: RequestBuilder(
|
||||||
context, Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) {}
|
context, Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) {}
|
||||||
|
|
||||||
RequestBuilder(u32* command_buffer, Header command_header)
|
|
||||||
: RequestHelperBase(command_buffer, command_header) {
|
|
||||||
cmdbuf[0] = header.raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
explicit RequestBuilder(u32* command_buffer, u32 command_header)
|
|
||||||
: RequestBuilder(command_buffer, Header{command_header}) {}
|
|
||||||
|
|
||||||
RequestBuilder(u32* command_buffer, u16 command_id, unsigned normal_params_size,
|
|
||||||
unsigned translate_params_size)
|
|
||||||
: RequestBuilder(command_buffer,
|
|
||||||
MakeHeader(command_id, normal_params_size, translate_params_size)) {}
|
|
||||||
|
|
||||||
// Validate on destruction, as there shouldn't be any case where we don't want it
|
// Validate on destruction, as there shouldn't be any case where we don't want it
|
||||||
~RequestBuilder() {
|
~RequestBuilder() {
|
||||||
ValidateHeader();
|
ValidateHeader();
|
||||||
|
@ -217,27 +200,13 @@ public:
|
||||||
Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) {
|
Header{MakeHeader(command_id, normal_params_size, translate_params_size)}) {
|
||||||
}
|
}
|
||||||
|
|
||||||
RequestParser(u32* command_buffer, Header command_header)
|
|
||||||
: RequestHelperBase(command_buffer, command_header) {}
|
|
||||||
|
|
||||||
explicit RequestParser(u32* command_buffer, u32 command_header)
|
|
||||||
: RequestParser(command_buffer, Header{command_header}) {}
|
|
||||||
|
|
||||||
RequestParser(u32* command_buffer, u16 command_id, unsigned normal_params_size,
|
|
||||||
unsigned translate_params_size)
|
|
||||||
: RequestParser(command_buffer,
|
|
||||||
MakeHeader(command_id, normal_params_size, translate_params_size)) {}
|
|
||||||
|
|
||||||
RequestBuilder MakeBuilder(u32 normal_params_size, u32 translate_params_size,
|
RequestBuilder MakeBuilder(u32 normal_params_size, u32 translate_params_size,
|
||||||
bool validateHeader = true) {
|
bool validateHeader = true) {
|
||||||
if (validateHeader)
|
if (validateHeader)
|
||||||
ValidateHeader();
|
ValidateHeader();
|
||||||
Header builderHeader{MakeHeader(static_cast<u16>(header.command_id), normal_params_size,
|
Header builderHeader{MakeHeader(static_cast<u16>(header.command_id), normal_params_size,
|
||||||
translate_params_size)};
|
translate_params_size)};
|
||||||
if (context != nullptr)
|
return {*context, builderHeader};
|
||||||
return {*context, builderHeader};
|
|
||||||
else
|
|
||||||
return {cmdbuf, builderHeader};
|
|
||||||
}
|
}
|
||||||
|
|
||||||
template <typename T>
|
template <typename T>
|
||||||
|
|
|
@ -79,7 +79,7 @@ static u64 GetTitleIdForApplet(AppletId id) {
|
||||||
|
|
||||||
ASSERT_MSG(itr != applet_titleids.end(), "Unknown applet id 0x%03X", static_cast<u32>(id));
|
ASSERT_MSG(itr != applet_titleids.end(), "Unknown applet id 0x%03X", static_cast<u32>(id));
|
||||||
|
|
||||||
return itr->title_ids[CFG::GetRegionValue()];
|
return itr->title_ids[CFG::GetCurrentModule()->GetRegionValue()];
|
||||||
}
|
}
|
||||||
|
|
||||||
AppletManager::AppletSlotData* AppletManager::GetAppletSlotData(AppletId id) {
|
AppletManager::AppletSlotData* AppletManager::GetAppletSlotData(AppletId id) {
|
||||||
|
|
|
@ -103,7 +103,7 @@ static u32 DecompressLZ11(const u8* in, u8* out) {
|
||||||
|
|
||||||
bool Module::LoadSharedFont() {
|
bool Module::LoadSharedFont() {
|
||||||
u8 font_region_code;
|
u8 font_region_code;
|
||||||
switch (CFG::GetRegionValue()) {
|
switch (CFG::GetCurrentModule()->GetRegionValue()) {
|
||||||
case 4: // CHN
|
case 4: // CHN
|
||||||
font_region_code = 2;
|
font_region_code = 2;
|
||||||
break;
|
break;
|
||||||
|
|
|
@ -3,7 +3,6 @@
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include <algorithm>
|
#include <algorithm>
|
||||||
#include <array>
|
|
||||||
#include <cryptopp/osrng.h>
|
#include <cryptopp/osrng.h>
|
||||||
#include <cryptopp/sha.h>
|
#include <cryptopp/sha.h>
|
||||||
#include "common/file_util.h"
|
#include "common/file_util.h"
|
||||||
|
@ -13,7 +12,6 @@
|
||||||
#include "core/file_sys/archive_systemsavedata.h"
|
#include "core/file_sys/archive_systemsavedata.h"
|
||||||
#include "core/file_sys/errors.h"
|
#include "core/file_sys/errors.h"
|
||||||
#include "core/file_sys/file_backend.h"
|
#include "core/file_sys/file_backend.h"
|
||||||
#include "core/hle/ipc.h"
|
|
||||||
#include "core/hle/ipc_helpers.h"
|
#include "core/hle/ipc_helpers.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
|
@ -21,9 +19,6 @@
|
||||||
#include "core/hle/service/cfg/cfg_nor.h"
|
#include "core/hle/service/cfg/cfg_nor.h"
|
||||||
#include "core/hle/service/cfg/cfg_s.h"
|
#include "core/hle/service/cfg/cfg_s.h"
|
||||||
#include "core/hle/service/cfg/cfg_u.h"
|
#include "core/hle/service/cfg/cfg_u.h"
|
||||||
#include "core/hle/service/fs/archive.h"
|
|
||||||
#include "core/hle/service/service.h"
|
|
||||||
#include "core/memory.h"
|
|
||||||
#include "core/settings.h"
|
#include "core/settings.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
|
@ -113,35 +108,44 @@ static const std::array<float, 8> STEREO_CAMERA_SETTINGS = {
|
||||||
static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20,
|
static_assert(sizeof(STEREO_CAMERA_SETTINGS) == 0x20,
|
||||||
"STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
|
"STEREO_CAMERA_SETTINGS must be exactly 0x20 bytes");
|
||||||
|
|
||||||
static const u32 CONFIG_SAVEFILE_SIZE = 0x8000;
|
|
||||||
static std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
|
||||||
|
|
||||||
static Service::FS::ArchiveHandle cfg_system_save_data_archive;
|
|
||||||
static const std::vector<u8> cfg_system_savedata_id = {
|
static const std::vector<u8> cfg_system_savedata_id = {
|
||||||
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00,
|
0x00, 0x00, 0x00, 0x00, 0x17, 0x00, 0x01, 0x00,
|
||||||
};
|
};
|
||||||
|
|
||||||
static u32 preferred_region_code = 0;
|
static std::weak_ptr<Module> current_cfg;
|
||||||
|
|
||||||
void GetCountryCodeString(Service::Interface* self) {
|
std::shared_ptr<Module> GetCurrentModule() {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
auto cfg = current_cfg.lock();
|
||||||
u32 country_code_id = cmd_buff[1];
|
ASSERT_MSG(cfg, "No CFG module running!");
|
||||||
|
return cfg;
|
||||||
|
}
|
||||||
|
|
||||||
|
Module::Interface::Interface(std::shared_ptr<Module> cfg, const char* name, u32 max_session)
|
||||||
|
: ServiceFramework(name, max_session), cfg(std::move(cfg)) {}
|
||||||
|
|
||||||
|
Module::Interface::~Interface() = default;
|
||||||
|
|
||||||
|
void Module::Interface::GetCountryCodeString(Kernel::HLERequestContext& ctx) {
|
||||||
|
IPC::RequestParser rp(ctx, 0x09, 1, 0);
|
||||||
|
u16 country_code_id = rp.Pop<u16>();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) {
|
if (country_code_id >= country_codes.size() || 0 == country_codes[country_code_id]) {
|
||||||
LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id);
|
LOG_ERROR(Service_CFG, "requested country code id=%d is invalid", country_code_id);
|
||||||
cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
|
rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
|
||||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent)
|
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
|
||||||
.raw;
|
rb.Skip(1, false);
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_buff[1] = 0;
|
rb.Push(RESULT_SUCCESS);
|
||||||
cmd_buff[2] = country_codes[country_code_id];
|
// the real CFG service copies only three bytes (including the null-terminator) here
|
||||||
|
rb.Push<u32>(country_codes[country_code_id]);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetCountryCodeID(Service::Interface* self) {
|
void Module::Interface::GetCountryCodeID(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x0A, 1, 0);
|
||||||
u16 country_code = static_cast<u16>(cmd_buff[1]);
|
u16 country_code = rp.Pop<u16>();
|
||||||
u16 country_code_id = 0;
|
u16 country_code_id = 0;
|
||||||
|
|
||||||
// The following algorithm will fail if the first country code isn't 0.
|
// The following algorithm will fail if the first country code isn't 0.
|
||||||
|
@ -154,42 +158,43 @@ void GetCountryCodeID(Service::Interface* self) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
if (0 == country_code_id) {
|
if (0 == country_code_id) {
|
||||||
LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff,
|
LOG_ERROR(Service_CFG, "requested country code name=%c%c is invalid", country_code & 0xff,
|
||||||
country_code >> 8);
|
country_code >> 8);
|
||||||
cmd_buff[1] = ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
|
rb.Push(ResultCode(ErrorDescription::NotFound, ErrorModule::Config,
|
||||||
ErrorSummary::WrongArgument, ErrorLevel::Permanent)
|
ErrorSummary::WrongArgument, ErrorLevel::Permanent));
|
||||||
.raw;
|
rb.Push<u16>(0x00FF);
|
||||||
cmd_buff[2] = 0xFFFF;
|
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
cmd_buff[1] = 0;
|
rb.Push(RESULT_SUCCESS);
|
||||||
cmd_buff[2] = country_code_id;
|
rb.Push<u16>(country_code_id);
|
||||||
}
|
}
|
||||||
|
|
||||||
u32 GetRegionValue() {
|
u32 Module::GetRegionValue() {
|
||||||
if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT)
|
if (Settings::values.region_value == Settings::REGION_VALUE_AUTO_SELECT)
|
||||||
return preferred_region_code;
|
return preferred_region_code;
|
||||||
|
|
||||||
return Settings::values.region_value;
|
return Settings::values.region_value;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SecureInfoGetRegion(Service::Interface* self) {
|
void Module::Interface::SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, id, 0, 0);
|
||||||
|
|
||||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
cmd_buff[2] = GetRegionValue();
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
rb.Push<u8>(cfg->GetRegionValue());
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenHashConsoleUnique(Service::Interface* self) {
|
void Module::Interface::GenHashConsoleUnique(Kernel::HLERequestContext& ctx) {
|
||||||
IPC::RequestParser rp(Kernel::GetCommandBuffer(), 0x03, 1, 0);
|
IPC::RequestParser rp(ctx, 0x03, 1, 0);
|
||||||
const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF;
|
const u32 app_id_salt = rp.Pop<u32>() & 0x000FFFFF;
|
||||||
|
|
||||||
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
|
IPC::RequestBuilder rb = rp.MakeBuilder(3, 0);
|
||||||
|
|
||||||
std::array<u8, 12> buffer;
|
std::array<u8, 12> buffer;
|
||||||
const ResultCode result = GetConfigInfoBlock(ConsoleUniqueID2BlockID, 8, 2, buffer.data());
|
const ResultCode result = cfg->GetConfigInfoBlock(ConsoleUniqueID2BlockID, 8, 2, buffer.data());
|
||||||
rb.Push(result);
|
rb.Push(result);
|
||||||
if (result.IsSuccess()) {
|
if (result.IsSuccess()) {
|
||||||
std::memcpy(&buffer[8], &app_id_salt, sizeof(u32));
|
std::memcpy(&buffer[8], &app_id_salt, sizeof(u32));
|
||||||
|
@ -208,105 +213,94 @@ void GenHashConsoleUnique(Service::Interface* self) {
|
||||||
LOG_DEBUG(Service_CFG, "called app_id_salt=0x%X", app_id_salt);
|
LOG_DEBUG(Service_CFG, "called app_id_salt=0x%X", app_id_salt);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetRegionCanadaUSA(Service::Interface* self) {
|
void Module::Interface::GetRegionCanadaUSA(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x04, 0, 0);
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
|
|
||||||
cmd_buff[1] = RESULT_SUCCESS.raw;
|
rb.Push(RESULT_SUCCESS);
|
||||||
|
|
||||||
u8 canada_or_usa = 1;
|
u8 canada_or_usa = 1;
|
||||||
if (canada_or_usa == GetRegionValue()) {
|
if (canada_or_usa == cfg->GetRegionValue()) {
|
||||||
cmd_buff[2] = 1;
|
rb.Push(true);
|
||||||
} else {
|
} else {
|
||||||
cmd_buff[2] = 0;
|
rb.Push(false);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetSystemModel(Service::Interface* self) {
|
void Module::Interface::GetSystemModel(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x05, 0, 0);
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
u32 data;
|
u32 data;
|
||||||
|
|
||||||
// TODO(Subv): Find out the correct error codes
|
// TODO(Subv): Find out the correct error codes
|
||||||
cmd_buff[1] =
|
rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data)));
|
||||||
Service::CFG::GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data))
|
rb.Push<u8>(data & 0xFF);
|
||||||
.raw;
|
|
||||||
cmd_buff[2] = data & 0xFF;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetModelNintendo2DS(Service::Interface* self) {
|
void Module::Interface::GetModelNintendo2DS(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x06, 0, 0);
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(2, 0);
|
||||||
u32 data;
|
u32 data;
|
||||||
|
|
||||||
// TODO(Subv): Find out the correct error codes
|
// TODO(Subv): Find out the correct error codes
|
||||||
cmd_buff[1] =
|
rb.Push(cfg->GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data)));
|
||||||
Service::CFG::GetConfigInfoBlock(ConsoleModelBlockID, 4, 0x8, reinterpret_cast<u8*>(&data))
|
|
||||||
.raw;
|
|
||||||
|
|
||||||
u8 model = data & 0xFF;
|
u8 model = data & 0xFF;
|
||||||
if (model == Service::CFG::NINTENDO_2DS)
|
rb.Push(model != Service::CFG::NINTENDO_2DS);
|
||||||
cmd_buff[2] = 0;
|
|
||||||
else
|
|
||||||
cmd_buff[2] = 1;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetConfigInfoBlk2(Service::Interface* self) {
|
void Module::Interface::GetConfigInfoBlk2(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x01, 2, 2);
|
||||||
u32 size = cmd_buff[1];
|
u32 size = rp.Pop<u32>();
|
||||||
u32 block_id = cmd_buff[2];
|
u32 block_id = rp.Pop<u32>();
|
||||||
VAddr data_pointer = cmd_buff[4];
|
auto& buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
if (!Memory::IsValidVirtualAddress(data_pointer)) {
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
cmd_buff[1] = -1; // TODO(Subv): Find the right error code
|
std::vector<u8> data(size);
|
||||||
return;
|
rb.Push(cfg->GetConfigInfoBlock(block_id, size, 0x2, data.data()));
|
||||||
}
|
buffer.Write(data.data(), 0, data.size());
|
||||||
|
rb.PushMappedBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::GetConfigInfoBlk8(Kernel::HLERequestContext& ctx, u16 id) {
|
||||||
|
IPC::RequestParser rp(ctx, id, 2, 2);
|
||||||
|
u32 size = rp.Pop<u32>();
|
||||||
|
u32 block_id = rp.Pop<u32>();
|
||||||
|
auto& buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
|
std::vector<u8> data(size);
|
||||||
|
rb.Push(cfg->GetConfigInfoBlock(block_id, size, 0x8, data.data()));
|
||||||
|
buffer.Write(data.data(), 0, data.size());
|
||||||
|
rb.PushMappedBuffer(buffer);
|
||||||
|
}
|
||||||
|
|
||||||
|
void Module::Interface::SetConfigInfoBlk4(Kernel::HLERequestContext& ctx, u16 id) {
|
||||||
|
IPC::RequestParser rp(ctx, id, 2, 2);
|
||||||
|
u32 block_id = rp.Pop<u32>();
|
||||||
|
u32 size = rp.Pop<u32>();
|
||||||
|
auto& buffer = rp.PopMappedBuffer();
|
||||||
|
|
||||||
std::vector<u8> data(size);
|
std::vector<u8> data(size);
|
||||||
cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x2, data.data()).raw;
|
buffer.Read(data.data(), 0, data.size());
|
||||||
Memory::WriteBlock(data_pointer, data.data(), data.size());
|
|
||||||
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 2);
|
||||||
|
rb.Push(cfg->SetConfigInfoBlock(block_id, size, 0x4, data.data()));
|
||||||
|
rb.PushMappedBuffer(buffer);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GetConfigInfoBlk8(Service::Interface* self) {
|
void Module::Interface::UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx, u16 id) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, id, 0, 0);
|
||||||
u32 size = cmd_buff[1];
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
u32 block_id = cmd_buff[2];
|
rb.Push(cfg->UpdateConfigNANDSavegame());
|
||||||
VAddr data_pointer = cmd_buff[4];
|
|
||||||
|
|
||||||
if (!Memory::IsValidVirtualAddress(data_pointer)) {
|
|
||||||
cmd_buff[1] = -1; // TODO(Subv): Find the right error code
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> data(size);
|
|
||||||
cmd_buff[1] = Service::CFG::GetConfigInfoBlock(block_id, size, 0x8, data.data()).raw;
|
|
||||||
Memory::WriteBlock(data_pointer, data.data(), data.size());
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetConfigInfoBlk4(Service::Interface* self) {
|
void Module::Interface::FormatConfig(Kernel::HLERequestContext& ctx) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
IPC::RequestParser rp(ctx, 0x0806, 0, 0);
|
||||||
u32 block_id = cmd_buff[1];
|
IPC::RequestBuilder rb = rp.MakeBuilder(1, 0);
|
||||||
u32 size = cmd_buff[2];
|
rb.Push(cfg->FormatConfig());
|
||||||
VAddr data_pointer = cmd_buff[4];
|
|
||||||
|
|
||||||
if (!Memory::IsValidVirtualAddress(data_pointer)) {
|
|
||||||
cmd_buff[1] = -1; // TODO(Subv): Find the right error code
|
|
||||||
return;
|
|
||||||
}
|
|
||||||
|
|
||||||
std::vector<u8> data(size);
|
|
||||||
Memory::ReadBlock(data_pointer, data.data(), data.size());
|
|
||||||
cmd_buff[1] = Service::CFG::SetConfigInfoBlock(block_id, size, 0x4, data.data()).raw;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void UpdateConfigNANDSavegame(Service::Interface* self) {
|
ResultVal<void*> Module::GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) {
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
||||||
cmd_buff[1] = Service::CFG::UpdateConfigNANDSavegame().raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
void FormatConfig(Service::Interface* self) {
|
|
||||||
u32* cmd_buff = Kernel::GetCommandBuffer();
|
|
||||||
cmd_buff[1] = Service::CFG::FormatConfig().raw;
|
|
||||||
}
|
|
||||||
|
|
||||||
static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag) {
|
|
||||||
// Read the header
|
// Read the header
|
||||||
SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
|
SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
|
||||||
|
|
||||||
|
@ -346,7 +340,7 @@ static ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 fl
|
||||||
return MakeResult<void*>(pointer);
|
return MakeResult<void*>(pointer);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
|
ResultCode Module::GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
|
||||||
void* pointer;
|
void* pointer;
|
||||||
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
||||||
memcpy(output, pointer, size);
|
memcpy(output, pointer, size);
|
||||||
|
@ -354,14 +348,14 @@ ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output) {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) {
|
ResultCode Module::SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input) {
|
||||||
void* pointer;
|
void* pointer;
|
||||||
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
CASCADE_RESULT(pointer, GetConfigInfoBlockPointer(block_id, size, flag));
|
||||||
memcpy(pointer, input, size);
|
memcpy(pointer, input, size);
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data) {
|
ResultCode Module::CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data) {
|
||||||
SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
|
SaveFileConfig* config = reinterpret_cast<SaveFileConfig*>(cfg_config_file_buffer.data());
|
||||||
if (config->total_entries >= CONFIG_FILE_MAX_BLOCK_ENTRIES)
|
if (config->total_entries >= CONFIG_FILE_MAX_BLOCK_ENTRIES)
|
||||||
return ResultCode(-1); // TODO(Subv): Find the right error code
|
return ResultCode(-1); // TODO(Subv): Find the right error code
|
||||||
|
@ -393,12 +387,12 @@ ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* da
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode DeleteConfigNANDSaveFile() {
|
ResultCode Module::DeleteConfigNANDSaveFile() {
|
||||||
FileSys::Path path("/config");
|
FileSys::Path path("/config");
|
||||||
return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path);
|
return Service::FS::DeleteFileFromArchive(cfg_system_save_data_archive, path);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode UpdateConfigNANDSavegame() {
|
ResultCode Module::UpdateConfigNANDSavegame() {
|
||||||
FileSys::Mode mode = {};
|
FileSys::Mode mode = {};
|
||||||
mode.write_flag.Assign(1);
|
mode.write_flag.Assign(1);
|
||||||
mode.create_flag.Assign(1);
|
mode.create_flag.Assign(1);
|
||||||
|
@ -414,7 +408,7 @@ ResultCode UpdateConfigNANDSavegame() {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode FormatConfig() {
|
ResultCode Module::FormatConfig() {
|
||||||
ResultCode res = DeleteConfigNANDSaveFile();
|
ResultCode res = DeleteConfigNANDSaveFile();
|
||||||
// The delete command fails if the file doesn't exist, so we have to check that too
|
// The delete command fails if the file doesn't exist, so we have to check that too
|
||||||
if (!res.IsSuccess() && res != FileSys::ERROR_FILE_NOT_FOUND) {
|
if (!res.IsSuccess() && res != FileSys::ERROR_FILE_NOT_FOUND) {
|
||||||
|
@ -533,7 +527,7 @@ ResultCode FormatConfig() {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode LoadConfigNANDSaveFile() {
|
ResultCode Module::LoadConfigNANDSaveFile() {
|
||||||
// Open the SystemSaveData archive 0x00010017
|
// Open the SystemSaveData archive 0x00010017
|
||||||
FileSys::Path archive_path(cfg_system_savedata_id);
|
FileSys::Path archive_path(cfg_system_savedata_id);
|
||||||
auto archive_result =
|
auto archive_result =
|
||||||
|
@ -570,18 +564,11 @@ ResultCode LoadConfigNANDSaveFile() {
|
||||||
return FormatConfig();
|
return FormatConfig();
|
||||||
}
|
}
|
||||||
|
|
||||||
void Init() {
|
Module::Module() {
|
||||||
AddService(new CFG_I);
|
|
||||||
AddService(new CFG_NOR);
|
|
||||||
AddService(new CFG_S);
|
|
||||||
AddService(new CFG_U);
|
|
||||||
|
|
||||||
LoadConfigNANDSaveFile();
|
LoadConfigNANDSaveFile();
|
||||||
|
|
||||||
preferred_region_code = 0;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
void Shutdown() {}
|
Module::~Module() = default;
|
||||||
|
|
||||||
/// Checks if the language is available in the chosen region, and returns a proper one
|
/// Checks if the language is available in the chosen region, and returns a proper one
|
||||||
static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage language) {
|
static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage language) {
|
||||||
|
@ -610,7 +597,7 @@ static SystemLanguage AdjustLanguageInfoBlock(u32 region, SystemLanguage languag
|
||||||
return language;
|
return language;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetPreferredRegionCode(u32 region_code) {
|
void Module::SetPreferredRegionCode(u32 region_code) {
|
||||||
preferred_region_code = region_code;
|
preferred_region_code = region_code;
|
||||||
LOG_INFO(Service_CFG, "Preferred region code set to %u", preferred_region_code);
|
LOG_INFO(Service_CFG, "Preferred region code set to %u", preferred_region_code);
|
||||||
|
|
||||||
|
@ -626,14 +613,14 @@ void SetPreferredRegionCode(u32 region_code) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetUsername(const std::u16string& name) {
|
void Module::SetUsername(const std::u16string& name) {
|
||||||
ASSERT(name.size() <= 10);
|
ASSERT(name.size() <= 10);
|
||||||
UsernameBlock block{};
|
UsernameBlock block{};
|
||||||
name.copy(block.username, name.size());
|
name.copy(block.username, name.size());
|
||||||
SetConfigInfoBlock(UsernameBlockID, sizeof(block), 4, &block);
|
SetConfigInfoBlock(UsernameBlockID, sizeof(block), 4, &block);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string GetUsername() {
|
std::u16string Module::GetUsername() {
|
||||||
UsernameBlock block;
|
UsernameBlock block;
|
||||||
GetConfigInfoBlock(UsernameBlockID, sizeof(block), 8, &block);
|
GetConfigInfoBlock(UsernameBlockID, sizeof(block), 8, &block);
|
||||||
|
|
||||||
|
@ -646,40 +633,40 @@ std::u16string GetUsername() {
|
||||||
return username;
|
return username;
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetBirthday(u8 month, u8 day) {
|
void Module::SetBirthday(u8 month, u8 day) {
|
||||||
BirthdayBlock block = {month, day};
|
BirthdayBlock block = {month, day};
|
||||||
SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
|
SetConfigInfoBlock(BirthdayBlockID, sizeof(block), 4, &block);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::tuple<u8, u8> GetBirthday() {
|
std::tuple<u8, u8> Module::GetBirthday() {
|
||||||
BirthdayBlock block;
|
BirthdayBlock block;
|
||||||
GetConfigInfoBlock(BirthdayBlockID, sizeof(block), 8, &block);
|
GetConfigInfoBlock(BirthdayBlockID, sizeof(block), 8, &block);
|
||||||
return std::make_tuple(block.month, block.day);
|
return std::make_tuple(block.month, block.day);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSystemLanguage(SystemLanguage language) {
|
void Module::SetSystemLanguage(SystemLanguage language) {
|
||||||
u8 block = language;
|
u8 block = language;
|
||||||
SetConfigInfoBlock(LanguageBlockID, sizeof(block), 4, &block);
|
SetConfigInfoBlock(LanguageBlockID, sizeof(block), 4, &block);
|
||||||
}
|
}
|
||||||
|
|
||||||
SystemLanguage GetSystemLanguage() {
|
SystemLanguage Module::GetSystemLanguage() {
|
||||||
u8 block;
|
u8 block;
|
||||||
GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block);
|
GetConfigInfoBlock(LanguageBlockID, sizeof(block), 8, &block);
|
||||||
return static_cast<SystemLanguage>(block);
|
return static_cast<SystemLanguage>(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void SetSoundOutputMode(SoundOutputMode mode) {
|
void Module::SetSoundOutputMode(SoundOutputMode mode) {
|
||||||
u8 block = mode;
|
u8 block = mode;
|
||||||
SetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 4, &block);
|
SetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 4, &block);
|
||||||
}
|
}
|
||||||
|
|
||||||
SoundOutputMode GetSoundOutputMode() {
|
SoundOutputMode Module::GetSoundOutputMode() {
|
||||||
u8 block;
|
u8 block;
|
||||||
GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block);
|
GetConfigInfoBlock(SoundOutputModeBlockID, sizeof(block), 8, &block);
|
||||||
return static_cast<SoundOutputMode>(block);
|
return static_cast<SoundOutputMode>(block);
|
||||||
}
|
}
|
||||||
|
|
||||||
void GenerateConsoleUniqueId(u32& random_number, u64& console_id) {
|
void Module::GenerateConsoleUniqueId(u32& random_number, u64& console_id) {
|
||||||
CryptoPP::AutoSeededRandomPool rng;
|
CryptoPP::AutoSeededRandomPool rng;
|
||||||
random_number = rng.GenerateWord32(0, 0xFFFF);
|
random_number = rng.GenerateWord32(0, 0xFFFF);
|
||||||
u64_le local_friend_code_seed;
|
u64_le local_friend_code_seed;
|
||||||
|
@ -688,7 +675,7 @@ void GenerateConsoleUniqueId(u32& random_number, u64& console_id) {
|
||||||
console_id = (local_friend_code_seed & 0x3FFFFFFFF) | (static_cast<u64>(random_number) << 48);
|
console_id = (local_friend_code_seed & 0x3FFFFFFFF) | (static_cast<u64>(random_number) << 48);
|
||||||
}
|
}
|
||||||
|
|
||||||
ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) {
|
ResultCode Module::SetConsoleUniqueId(u32 random_number, u64 console_id) {
|
||||||
u64_le console_id_le = console_id;
|
u64_le console_id_le = console_id;
|
||||||
ResultCode res =
|
ResultCode res =
|
||||||
SetConfigInfoBlock(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le);
|
SetConfigInfoBlock(ConsoleUniqueID1BlockID, sizeof(console_id_le), 0xE, &console_id_le);
|
||||||
|
@ -708,11 +695,20 @@ ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id) {
|
||||||
return RESULT_SUCCESS;
|
return RESULT_SUCCESS;
|
||||||
}
|
}
|
||||||
|
|
||||||
u64 GetConsoleUniqueId() {
|
u64 Module::GetConsoleUniqueId() {
|
||||||
u64_le console_id_le;
|
u64_le console_id_le;
|
||||||
GetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le);
|
GetConfigInfoBlock(ConsoleUniqueID2BlockID, sizeof(console_id_le), 0xE, &console_id_le);
|
||||||
return console_id_le;
|
return console_id_le;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void InstallInterfaces(SM::ServiceManager& service_manager) {
|
||||||
|
auto cfg = std::make_shared<Module>();
|
||||||
|
std::make_shared<CFG_I>(cfg)->InstallAsService(service_manager);
|
||||||
|
std::make_shared<CFG_S>(cfg)->InstallAsService(service_manager);
|
||||||
|
std::make_shared<CFG_U>(cfg)->InstallAsService(service_manager);
|
||||||
|
std::make_shared<CFG_NOR>()->InstallAsService(service_manager);
|
||||||
|
current_cfg = cfg;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
} // namespace Service
|
} // namespace Service
|
||||||
|
|
|
@ -5,15 +5,12 @@
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include <array>
|
#include <array>
|
||||||
|
#include <memory>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include "common/common_types.h"
|
#include "common/common_types.h"
|
||||||
|
#include "core/hle/service/fs/archive.h"
|
||||||
union ResultCode;
|
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
|
|
||||||
class Interface;
|
|
||||||
|
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
enum SystemModel {
|
enum SystemModel {
|
||||||
|
@ -82,289 +79,321 @@ static const std::array<u16, 187> country_codes = {{
|
||||||
C("SM"), C("VA"), C("BM"), // 184-186
|
C("SM"), C("VA"), C("BM"), // 184-186
|
||||||
}};
|
}};
|
||||||
|
|
||||||
/**
|
class Module final {
|
||||||
* CFG::GetCountryCodeString service function
|
public:
|
||||||
* Inputs:
|
Module();
|
||||||
* 1 : Country Code ID
|
~Module();
|
||||||
* Outputs:
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
* 2 : Country's 2-char string
|
|
||||||
*/
|
|
||||||
void GetCountryCodeString(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
class Interface : public ServiceFramework<Interface> {
|
||||||
* CFG::GetCountryCodeID service function
|
public:
|
||||||
* Inputs:
|
Interface(std::shared_ptr<Module> cfg, const char* name, u32 max_session);
|
||||||
* 1 : Country Code 2-char string
|
~Interface();
|
||||||
* Outputs:
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
* 2 : Country Code ID
|
|
||||||
*/
|
|
||||||
void GetCountryCodeID(Service::Interface* self);
|
|
||||||
|
|
||||||
u32 GetRegionValue();
|
/**
|
||||||
|
* CFG::GetCountryCodeString service function
|
||||||
|
* Inputs:
|
||||||
|
* 1 : Country Code ID
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
* 2 : Country's 2-char string
|
||||||
|
*/
|
||||||
|
void GetCountryCodeString(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::SecureInfoGetRegion service function
|
* CFG::GetCountryCodeID service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 1 : None
|
* 1 : Country Code 2-char string
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 0 : Result Header code
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 2 : Country Code ID
|
||||||
* 2 : Region value loaded from SecureInfo offset 0x100
|
*/
|
||||||
*/
|
void GetCountryCodeID(Kernel::HLERequestContext& ctx);
|
||||||
void SecureInfoGetRegion(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
u32 GetRegionValue();
|
||||||
* CFG::GenHashConsoleUnique service function
|
|
||||||
* Inputs:
|
|
||||||
* 1 : 20 bit application ID salt
|
|
||||||
* Outputs:
|
|
||||||
* 0 : Result Header code
|
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
* 2 : Hash/"ID" lower word
|
|
||||||
* 3 : Hash/"ID" upper word
|
|
||||||
*/
|
|
||||||
void GenHashConsoleUnique(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetRegionCanadaUSA service function
|
* CFG::SecureInfoGetRegion service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 1 : None
|
* 1 : None
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 0 : Result Header code
|
* 0 : Result Header code
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* 2 : 1 if the system is a Canada or USA model, 0 otherwise
|
* 2 : Region value loaded from SecureInfo offset 0x100
|
||||||
*/
|
*/
|
||||||
void GetRegionCanadaUSA(Service::Interface* self);
|
void SecureInfoGetRegion(Kernel::HLERequestContext& ctx, u16 id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetSystemModel service function
|
* CFG::GenHashConsoleUnique service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x00050000
|
* 1 : 20 bit application ID salt
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 0 : Result Header code
|
||||||
* 2 : Model of the console
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
*/
|
* 2 : Hash/"ID" lower word
|
||||||
void GetSystemModel(Service::Interface* self);
|
* 3 : Hash/"ID" upper word
|
||||||
|
*/
|
||||||
|
void GenHashConsoleUnique(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetModelNintendo2DS service function
|
* CFG::GetRegionCanadaUSA service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x00060000
|
* 1 : None
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 0 : Result Header code
|
||||||
* 2 : 0 if the system is a Nintendo 2DS, 1 otherwise
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
*/
|
* 2 : 1 if the system is a Canada or USA model, 0 otherwise
|
||||||
void GetModelNintendo2DS(Service::Interface* self);
|
*/
|
||||||
|
void GetRegionCanadaUSA(Kernel::HLERequestContext& ctx);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetConfigInfoBlk2 service function
|
* CFG::GetSystemModel service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x00010082
|
* 0 : 0x00050000
|
||||||
* 1 : Size
|
* Outputs:
|
||||||
* 2 : Block ID
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* 3 : Descriptor for the output buffer
|
* 2 : Model of the console
|
||||||
* 4 : Output buffer pointer
|
*/
|
||||||
* Outputs:
|
void GetSystemModel(Kernel::HLERequestContext& ctx);
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
*/
|
|
||||||
void GetConfigInfoBlk2(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::GetConfigInfoBlk8 service function
|
* CFG::GetModelNintendo2DS service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x04010082 / 0x08010082
|
* 0 : 0x00060000
|
||||||
* 1 : Size
|
* Outputs:
|
||||||
* 2 : Block ID
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* 3 : Descriptor for the output buffer
|
* 2 : 0 if the system is a Nintendo 2DS, 1 otherwise
|
||||||
* 4 : Output buffer pointer
|
*/
|
||||||
* Outputs:
|
void GetModelNintendo2DS(Kernel::HLERequestContext& ctx);
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
|
||||||
*/
|
|
||||||
void GetConfigInfoBlk8(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::SetConfigInfoBlk4 service function
|
* CFG::GetConfigInfoBlk2 service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x04020082 / 0x08020082
|
* 0 : 0x00010082
|
||||||
* 1 : Block ID
|
* 1 : Size
|
||||||
* 2 : Size
|
* 2 : Block ID
|
||||||
* 3 : Descriptor for the output buffer
|
* 3 : Descriptor for the output buffer
|
||||||
* 4 : Output buffer pointer
|
* 4 : Output buffer pointer
|
||||||
* Outputs:
|
* Outputs:
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* Note:
|
*/
|
||||||
* The parameters order is different from GetConfigInfoBlk2/8's,
|
void GetConfigInfoBlk2(Kernel::HLERequestContext& ctx);
|
||||||
* where Block ID and Size are switched.
|
|
||||||
*/
|
|
||||||
void SetConfigInfoBlk4(Service::Interface* self);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::UpdateConfigNANDSavegame service function
|
* CFG::GetConfigInfoBlk8 service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x04030000 / 0x08030000
|
* 0 : 0x04010082 / 0x08010082
|
||||||
* Outputs:
|
* 1 : Size
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 2 : Block ID
|
||||||
*/
|
* 3 : Descriptor for the output buffer
|
||||||
void UpdateConfigNANDSavegame(Service::Interface* self);
|
* 4 : Output buffer pointer
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
*/
|
||||||
|
void GetConfigInfoBlk8(Kernel::HLERequestContext& ctx, u16 id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* CFG::FormatConfig service function
|
* CFG::SetConfigInfoBlk4 service function
|
||||||
* Inputs:
|
* Inputs:
|
||||||
* 0 : 0x08060000
|
* 0 : 0x04020082 / 0x08020082
|
||||||
* Outputs:
|
* 1 : Block ID
|
||||||
* 1 : Result of function, 0 on success, otherwise error code
|
* 2 : Size
|
||||||
*/
|
* 3 : Descriptor for the output buffer
|
||||||
void FormatConfig(Service::Interface* self);
|
* 4 : Output buffer pointer
|
||||||
|
* Outputs:
|
||||||
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
|
* Note:
|
||||||
|
* The parameters order is different from GetConfigInfoBlk2/8's,
|
||||||
|
* where Block ID and Size are switched.
|
||||||
|
*/
|
||||||
|
void SetConfigInfoBlk4(Kernel::HLERequestContext& ctx, u16 id);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads a block with the specified id and flag from the Config savegame buffer
|
* CFG::UpdateConfigNANDSavegame service function
|
||||||
* and writes the output to output. The input size must match exactly the size of the requested
|
* Inputs:
|
||||||
* block.
|
* 0 : 0x04030000 / 0x08030000
|
||||||
*
|
* Outputs:
|
||||||
* @param block_id The id of the block we want to read
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* @param size The size of the block we want to read
|
*/
|
||||||
* @param flag The requested block must have this flag set
|
void UpdateConfigNANDSavegame(Kernel::HLERequestContext& ctx, u16 id);
|
||||||
* @param output A pointer where we will write the read data
|
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
|
||||||
*/
|
|
||||||
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Reads data from input and writes to a block with the specified id and flag
|
* CFG::FormatConfig service function
|
||||||
* in the Config savegame buffer. The input size must match exactly the size of the target block.
|
* Inputs:
|
||||||
*
|
* 0 : 0x08060000
|
||||||
* @param block_id The id of the block we want to write
|
* Outputs:
|
||||||
* @param size The size of the block we want to write
|
* 1 : Result of function, 0 on success, otherwise error code
|
||||||
* @param flag The target block must have this flag set
|
*/
|
||||||
* @param input A pointer where we will read data and write to Config savegame buffer
|
void FormatConfig(Kernel::HLERequestContext& ctx);
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
|
||||||
*/
|
|
||||||
ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input);
|
|
||||||
|
|
||||||
/**
|
/// A helper function for dispatching service functions that have multiple IDs
|
||||||
* Creates a block with the specified id and writes the input data to the cfg savegame buffer in
|
template <void (Interface::*function)(Kernel::HLERequestContext& ctx, u16 id), u16 id>
|
||||||
* memory. The config savegame file in the filesystem is not updated.
|
void D(Kernel::HLERequestContext& ctx) {
|
||||||
*
|
(this->*function)(ctx, id);
|
||||||
* @param block_id The id of the block we want to create
|
}
|
||||||
* @param size The size of the block we want to create
|
|
||||||
* @param flags The flags of the new block
|
|
||||||
* @param data A pointer containing the data we will write to the new block
|
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
|
||||||
*/
|
|
||||||
ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data);
|
|
||||||
|
|
||||||
/**
|
private:
|
||||||
* Deletes the config savegame file from the filesystem, the buffer in memory is not affected
|
std::shared_ptr<Module> cfg;
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
};
|
||||||
*/
|
|
||||||
ResultCode DeleteConfigNANDSaveFile();
|
|
||||||
|
|
||||||
/**
|
private:
|
||||||
* Writes the config savegame memory buffer to the config savegame file in the filesystem
|
ResultVal<void*> GetConfigInfoBlockPointer(u32 block_id, u32 size, u32 flag);
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
|
||||||
*/
|
|
||||||
ResultCode UpdateConfigNANDSavegame();
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Re-creates the config savegame file in memory and the filesystem with the default blocks
|
* Reads a block with the specified id and flag from the Config savegame buffer
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
* and writes the output to output. The input size must match exactly the size of the requested
|
||||||
*/
|
* block.
|
||||||
ResultCode FormatConfig();
|
*
|
||||||
|
* @param block_id The id of the block we want to read
|
||||||
|
* @param size The size of the block we want to read
|
||||||
|
* @param flag The requested block must have this flag set
|
||||||
|
* @param output A pointer where we will write the read data
|
||||||
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode GetConfigInfoBlock(u32 block_id, u32 size, u32 flag, void* output);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Open the config savegame file and load it to the memory buffer
|
* Reads data from input and writes to a block with the specified id and flag
|
||||||
* @returns ResultCode indicating the result of the operation, 0 on success
|
* in the Config savegame buffer. The input size must match exactly the size of the target
|
||||||
*/
|
* block.
|
||||||
ResultCode LoadConfigNANDSaveFile();
|
*
|
||||||
|
* @param block_id The id of the block we want to write
|
||||||
|
* @param size The size of the block we want to write
|
||||||
|
* @param flag The target block must have this flag set
|
||||||
|
* @param input A pointer where we will read data and write to Config savegame buffer
|
||||||
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode SetConfigInfoBlock(u32 block_id, u32 size, u32 flag, const void* input);
|
||||||
|
|
||||||
/// Initialize the config service
|
/**
|
||||||
void Init();
|
* Creates a block with the specified id and writes the input data to the cfg savegame buffer in
|
||||||
|
* memory. The config savegame file in the filesystem is not updated.
|
||||||
|
*
|
||||||
|
* @param block_id The id of the block we want to create
|
||||||
|
* @param size The size of the block we want to create
|
||||||
|
* @param flags The flags of the new block
|
||||||
|
* @param data A pointer containing the data we will write to the new block
|
||||||
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode CreateConfigInfoBlk(u32 block_id, u16 size, u16 flags, const void* data);
|
||||||
|
|
||||||
/// Shutdown the config service
|
/**
|
||||||
void Shutdown();
|
* Deletes the config savegame file from the filesystem, the buffer in memory is not affected
|
||||||
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode DeleteConfigNANDSaveFile();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Set the region code preferred by the game so that CFG will adjust to it when the region setting
|
* Re-creates the config savegame file in memory and the filesystem with the default blocks
|
||||||
* is auto.
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
* @param region_code the preferred region code to set
|
*/
|
||||||
*/
|
ResultCode FormatConfig();
|
||||||
void SetPreferredRegionCode(u32 region_code);
|
|
||||||
|
|
||||||
// Utilities for frontend to set config data.
|
/**
|
||||||
// Note: before calling these functions, LoadConfigNANDSaveFile should be called,
|
* Open the config savegame file and load it to the memory buffer
|
||||||
// and UpdateConfigNANDSavegame should be called after making changes to config data.
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode LoadConfigNANDSaveFile();
|
||||||
|
|
||||||
/**
|
public:
|
||||||
* Sets the username in config savegame.
|
u32 GetRegionValue();
|
||||||
* @param name the username to set. The maximum size is 10 in char16_t.
|
|
||||||
*/
|
|
||||||
void SetUsername(const std::u16string& name);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the username from config savegame.
|
* Set the region code preferred by the game so that CFG will adjust to it when the region
|
||||||
* @returns the username
|
* setting
|
||||||
*/
|
* is auto.
|
||||||
std::u16string GetUsername();
|
* @param region_code the preferred region code to set
|
||||||
|
*/
|
||||||
|
void SetPreferredRegionCode(u32 region_code);
|
||||||
|
|
||||||
/**
|
// Utilities for frontend to set config data.
|
||||||
* Sets the profile birthday in config savegame.
|
// Note: UpdateConfigNANDSavegame should be called after making changes to config data.
|
||||||
* @param month the month of birthday.
|
|
||||||
* @param day the day of the birthday.
|
|
||||||
*/
|
|
||||||
void SetBirthday(u8 month, u8 day);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the profile birthday from the config savegame.
|
* Sets the username in config savegame.
|
||||||
* @returns a tuple of (month, day) of birthday
|
* @param name the username to set. The maximum size is 10 in char16_t.
|
||||||
*/
|
*/
|
||||||
std::tuple<u8, u8> GetBirthday();
|
void SetUsername(const std::u16string& name);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the system language in config savegame.
|
* Gets the username from config savegame.
|
||||||
* @param language the system language to set.
|
* @returns the username
|
||||||
*/
|
*/
|
||||||
void SetSystemLanguage(SystemLanguage language);
|
std::u16string GetUsername();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the system language from config savegame.
|
* Sets the profile birthday in config savegame.
|
||||||
* @returns the system language
|
* @param month the month of birthday.
|
||||||
*/
|
* @param day the day of the birthday.
|
||||||
SystemLanguage GetSystemLanguage();
|
*/
|
||||||
|
void SetBirthday(u8 month, u8 day);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the sound output mode in config savegame.
|
* Gets the profile birthday from the config savegame.
|
||||||
* @param mode the sound output mode to set
|
* @returns a tuple of (month, day) of birthday
|
||||||
*/
|
*/
|
||||||
void SetSoundOutputMode(SoundOutputMode mode);
|
std::tuple<u8, u8> GetBirthday();
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the sound output mode from config savegame.
|
* Sets the system language in config savegame.
|
||||||
* @returns the sound output mode
|
* @param language the system language to set.
|
||||||
*/
|
*/
|
||||||
SoundOutputMode GetSoundOutputMode();
|
void SetSystemLanguage(SystemLanguage language);
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Generates a new random console unique id.
|
* Gets the system language from config savegame.
|
||||||
* @param random_number a random generated 16bit number stored at 0x90002, used for generating the
|
* @returns the system language
|
||||||
* console_id
|
*/
|
||||||
* @param console_id the randomly created console id
|
SystemLanguage GetSystemLanguage();
|
||||||
*/
|
|
||||||
void GenerateConsoleUniqueId(u32& random_number, u64& console_id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Sets the random_number and the console unique id in the config savegame.
|
* Sets the sound output mode in config savegame.
|
||||||
* @param random_number the random_number to set
|
* @param mode the sound output mode to set
|
||||||
* @param console_id the console id to set
|
*/
|
||||||
*/
|
void SetSoundOutputMode(SoundOutputMode mode);
|
||||||
ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id);
|
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* Gets the console unique id from config savegame.
|
* Gets the sound output mode from config savegame.
|
||||||
* @returns the console unique id
|
* @returns the sound output mode
|
||||||
*/
|
*/
|
||||||
u64 GetConsoleUniqueId();
|
SoundOutputMode GetSoundOutputMode();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Generates a new random console unique id.
|
||||||
|
* @param random_number a random generated 16bit number stored at 0x90002, used for generating
|
||||||
|
* the
|
||||||
|
* console_id
|
||||||
|
* @param console_id the randomly created console id
|
||||||
|
*/
|
||||||
|
void GenerateConsoleUniqueId(u32& random_number, u64& console_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Sets the random_number and the console unique id in the config savegame.
|
||||||
|
* @param random_number the random_number to set
|
||||||
|
* @param console_id the console id to set
|
||||||
|
*/
|
||||||
|
ResultCode SetConsoleUniqueId(u32 random_number, u64 console_id);
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Gets the console unique id from config savegame.
|
||||||
|
* @returns the console unique id
|
||||||
|
*/
|
||||||
|
u64 GetConsoleUniqueId();
|
||||||
|
|
||||||
|
/**
|
||||||
|
* Writes the config savegame memory buffer to the config savegame file in the filesystem
|
||||||
|
* @returns ResultCode indicating the result of the operation, 0 on success
|
||||||
|
*/
|
||||||
|
ResultCode UpdateConfigNANDSavegame();
|
||||||
|
|
||||||
|
private:
|
||||||
|
static constexpr u32 CONFIG_SAVEFILE_SIZE = 0x8000;
|
||||||
|
std::array<u8, CONFIG_SAVEFILE_SIZE> cfg_config_file_buffer;
|
||||||
|
Service::FS::ArchiveHandle cfg_system_save_data_archive;
|
||||||
|
u32 preferred_region_code = 0;
|
||||||
|
};
|
||||||
|
|
||||||
|
void InstallInterfaces(SM::ServiceManager& service_manager);
|
||||||
|
std::shared_ptr<Module> GetCurrentModule();
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
} // namespace Service
|
} // namespace Service
|
||||||
|
|
|
@ -2,62 +2,62 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
|
||||||
#include "core/hle/service/cfg/cfg_i.h"
|
#include "core/hle/service/cfg/cfg_i.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
const Interface::FunctionInfo FunctionTable[] = {
|
CFG_I::CFG_I(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "cfg:i", 23) {
|
||||||
// cfg common
|
static const FunctionInfo functions[] = {
|
||||||
{0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
// cfg common
|
||||||
{0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
|
{0x00010082, &CFG_I::GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
||||||
{0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
|
{0x00020000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"},
|
||||||
{0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
{0x00030040, &CFG_I::GenHashConsoleUnique, "GenHashConsoleUnique"},
|
||||||
{0x00050000, GetSystemModel, "GetSystemModel"},
|
{0x00040000, &CFG_I::GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
||||||
{0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
|
{0x00050000, &CFG_I::GetSystemModel, "GetSystemModel"},
|
||||||
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
{0x00060000, &CFG_I::GetModelNintendo2DS, "GetModelNintendo2DS"},
|
||||||
{0x00080080, nullptr, "GoThroughTable"},
|
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
||||||
{0x00090040, GetCountryCodeString, "GetCountryCodeString"},
|
{0x00080080, nullptr, "GoThroughTable"},
|
||||||
{0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
|
{0x00090040, &CFG_I::GetCountryCodeString, "GetCountryCodeString"},
|
||||||
{0x000B0000, nullptr, "IsFangateSupported"},
|
{0x000A0040, &CFG_I::GetCountryCodeID, "GetCountryCodeID"},
|
||||||
// cfg:i
|
{0x000B0000, nullptr, "IsFangateSupported"},
|
||||||
{0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
|
// cfg:i
|
||||||
{0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
|
{0x04010082, &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0401>, "GetConfigInfoBlk8"},
|
||||||
{0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
{0x04020082, &CFG_I::D<&CFG_I::SetConfigInfoBlk4, 0x0402>, "SetConfigInfoBlk4"},
|
||||||
{0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
|
{0x04030000, &CFG_I::D<&CFG_I::UpdateConfigNANDSavegame, 0x0403>,
|
||||||
{0x04050000, nullptr, "GetLocalFriendCodeSeed"},
|
"UpdateConfigNANDSavegame"},
|
||||||
{0x04060000, SecureInfoGetRegion, "SecureInfoGetRegion"},
|
{0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
|
||||||
{0x04070000, nullptr, "SecureInfoGetByte101"},
|
{0x04050000, nullptr, "GetLocalFriendCodeSeed"},
|
||||||
{0x04080042, nullptr, "SecureInfoGetSerialNo"},
|
{0x04060000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"},
|
||||||
{0x04090000, nullptr, "UpdateConfigBlk00040003"},
|
{0x04070000, nullptr, "SecureInfoGetByte101"},
|
||||||
{0x08010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
|
{0x04080042, nullptr, "SecureInfoGetSerialNo"},
|
||||||
{0x08020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
|
{0x04090000, nullptr, "UpdateConfigBlk00040003"},
|
||||||
{0x08030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
{0x08010082, &CFG_I::D<&CFG_I::GetConfigInfoBlk8, 0x0801>, "GetConfigInfoBlk8"},
|
||||||
{0x080400C2, nullptr, "CreateConfigInfoBlk"},
|
{0x08020082, &CFG_I::D<&CFG_I::SetConfigInfoBlk4, 0x0802>, "SetConfigInfoBlk4"},
|
||||||
{0x08050000, nullptr, "DeleteConfigNANDSavefile"},
|
{0x08030000, &CFG_I::D<&CFG_I::UpdateConfigNANDSavegame, 0x0803>,
|
||||||
{0x08060000, FormatConfig, "FormatConfig"},
|
"UpdateConfigNANDSavegame"},
|
||||||
{0x08080000, nullptr, "UpdateConfigBlk1"},
|
{0x080400C2, nullptr, "CreateConfigInfoBlk"},
|
||||||
{0x08090000, nullptr, "UpdateConfigBlk2"},
|
{0x08050000, nullptr, "DeleteConfigNANDSavefile"},
|
||||||
{0x080A0000, nullptr, "UpdateConfigBlk3"},
|
{0x08060000, &CFG_I::FormatConfig, "FormatConfig"},
|
||||||
{0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
|
{0x08080000, nullptr, "UpdateConfigBlk1"},
|
||||||
{0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
|
{0x08090000, nullptr, "UpdateConfigBlk2"},
|
||||||
{0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
|
{0x080A0000, nullptr, "UpdateConfigBlk3"},
|
||||||
{0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
|
{0x080B0082, nullptr, "SetGetLocalFriendCodeSeedData"},
|
||||||
{0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
|
{0x080C0042, nullptr, "SetLocalFriendCodeSeedSignature"},
|
||||||
{0x08100000, nullptr, "GetLocalFriendCodeSeed"},
|
{0x080D0000, nullptr, "DeleteCreateNANDLocalFriendCodeSeed"},
|
||||||
{0x08110084, nullptr, "SetSecureInfo"},
|
{0x080E0000, nullptr, "VerifySigLocalFriendCodeSeed"},
|
||||||
{0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
|
{0x080F0042, nullptr, "GetLocalFriendCodeSeedData"},
|
||||||
{0x08130000, nullptr, "VerifySigSecureInfo"},
|
{0x08100000, nullptr, "GetLocalFriendCodeSeed"},
|
||||||
{0x08140042, nullptr, "SecureInfoGetData"},
|
{0x08110084, nullptr, "SetSecureInfo"},
|
||||||
{0x08150042, nullptr, "SecureInfoGetSignature"},
|
{0x08120000, nullptr, "DeleteCreateNANDSecureInfo"},
|
||||||
{0x08160000, SecureInfoGetRegion, "SecureInfoGetRegion"},
|
{0x08130000, nullptr, "VerifySigSecureInfo"},
|
||||||
{0x08170000, nullptr, "SecureInfoGetByte101"},
|
{0x08140042, nullptr, "SecureInfoGetData"},
|
||||||
{0x08180042, nullptr, "SecureInfoGetSerialNo"},
|
{0x08150042, nullptr, "SecureInfoGetSignature"},
|
||||||
};
|
{0x08160000, &CFG_I::D<&CFG_I::SecureInfoGetRegion, 0x0816>, "SecureInfoGetRegion"},
|
||||||
|
{0x08170000, nullptr, "SecureInfoGetByte101"},
|
||||||
CFG_I::CFG_I() {
|
{0x08180042, nullptr, "SecureInfoGetSerialNo"},
|
||||||
Register(FunctionTable);
|
};
|
||||||
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -4,18 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
class CFG_I final : public Interface {
|
class CFG_I final : public Module::Interface {
|
||||||
public:
|
public:
|
||||||
CFG_I();
|
explicit CFG_I(std::shared_ptr<Module> cfg);
|
||||||
|
|
||||||
std::string GetPortName() const override {
|
|
||||||
return "cfg:i";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -2,21 +2,19 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
|
||||||
#include "core/hle/service/cfg/cfg_nor.h"
|
#include "core/hle/service/cfg/cfg_nor.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
const Interface::FunctionInfo FunctionTable[] = {
|
CFG_NOR::CFG_NOR() : ServiceFramework("cfg:nor", 23) {
|
||||||
{0x00010040, nullptr, "Initialize"},
|
static const FunctionInfo functions[] = {
|
||||||
{0x00020000, nullptr, "Shutdown"},
|
{0x00010040, nullptr, "Initialize"},
|
||||||
{0x00050082, nullptr, "ReadData"},
|
{0x00020000, nullptr, "Shutdown"},
|
||||||
{0x00060082, nullptr, "WriteData"},
|
{0x00050082, nullptr, "ReadData"},
|
||||||
};
|
{0x00060082, nullptr, "WriteData"},
|
||||||
|
};
|
||||||
CFG_NOR::CFG_NOR() {
|
RegisterHandlers(functions);
|
||||||
Register(FunctionTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -9,13 +9,9 @@
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
class CFG_NOR final : public Interface {
|
class CFG_NOR final : public ServiceFramework<CFG_NOR> {
|
||||||
public:
|
public:
|
||||||
CFG_NOR();
|
CFG_NOR();
|
||||||
|
|
||||||
std::string GetPortName() const override {
|
|
||||||
return "cfg:nor";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -2,39 +2,38 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
|
||||||
#include "core/hle/service/cfg/cfg_s.h"
|
#include "core/hle/service/cfg/cfg_s.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
const Interface::FunctionInfo FunctionTable[] = {
|
CFG_S::CFG_S(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "cfg:s", 23) {
|
||||||
// cfg common
|
static const FunctionInfo functions[] = {
|
||||||
{0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
// cfg common
|
||||||
{0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
|
{0x00010082, &CFG_S::GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
||||||
{0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
|
{0x00020000, &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"},
|
||||||
{0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
{0x00030040, &CFG_S::GenHashConsoleUnique, "GenHashConsoleUnique"},
|
||||||
{0x00050000, GetSystemModel, "GetSystemModel"},
|
{0x00040000, &CFG_S::GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
||||||
{0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
|
{0x00050000, &CFG_S::GetSystemModel, "GetSystemModel"},
|
||||||
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
{0x00060000, &CFG_S::GetModelNintendo2DS, "GetModelNintendo2DS"},
|
||||||
{0x00080080, nullptr, "GoThroughTable"},
|
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
||||||
{0x00090040, GetCountryCodeString, "GetCountryCodeString"},
|
{0x00080080, nullptr, "GoThroughTable"},
|
||||||
{0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
|
{0x00090040, &CFG_S::GetCountryCodeString, "GetCountryCodeString"},
|
||||||
{0x000B0000, nullptr, "IsFangateSupported"},
|
{0x000A0040, &CFG_S::GetCountryCodeID, "GetCountryCodeID"},
|
||||||
// cfg:s
|
{0x000B0000, nullptr, "IsFangateSupported"},
|
||||||
{0x04010082, GetConfigInfoBlk8, "GetConfigInfoBlk8"},
|
// cfg:s
|
||||||
{0x04020082, SetConfigInfoBlk4, "SetConfigInfoBlk4"},
|
{0x04010082, &CFG_S::D<&CFG_S::GetConfigInfoBlk8, 0x0401>, "GetConfigInfoBlk8"},
|
||||||
{0x04030000, UpdateConfigNANDSavegame, "UpdateConfigNANDSavegame"},
|
{0x04020082, &CFG_S::D<&CFG_S::SetConfigInfoBlk4, 0x0402>, "SetConfigInfoBlk4"},
|
||||||
{0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
|
{0x04030000, &CFG_S::D<&CFG_S::UpdateConfigNANDSavegame, 0x0403>,
|
||||||
{0x04050000, nullptr, "GetLocalFriendCodeSeed"},
|
"UpdateConfigNANDSavegame"},
|
||||||
{0x04060000, nullptr, "SecureInfoGetRegion"},
|
{0x04040042, nullptr, "GetLocalFriendCodeSeedData"},
|
||||||
{0x04070000, nullptr, "SecureInfoGetByte101"},
|
{0x04050000, nullptr, "GetLocalFriendCodeSeed"},
|
||||||
{0x04080042, nullptr, "SecureInfoGetSerialNo"},
|
{0x04060000, &CFG_S::D<&CFG_S::SecureInfoGetRegion, 0x0406>, "SecureInfoGetRegion"},
|
||||||
{0x04090000, nullptr, "UpdateConfigBlk00040003"},
|
{0x04070000, nullptr, "SecureInfoGetByte101"},
|
||||||
};
|
{0x04080042, nullptr, "SecureInfoGetSerialNo"},
|
||||||
|
{0x04090000, nullptr, "UpdateConfigBlk00040003"},
|
||||||
CFG_S::CFG_S() {
|
};
|
||||||
Register(FunctionTable);
|
RegisterHandlers(functions);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -4,18 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
class CFG_S final : public Interface {
|
class CFG_S final : public Module::Interface {
|
||||||
public:
|
public:
|
||||||
CFG_S();
|
explicit CFG_S(std::shared_ptr<Module> cfg);
|
||||||
|
|
||||||
std::string GetPortName() const override {
|
|
||||||
return "cfg:s";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -2,29 +2,27 @@
|
||||||
// Licensed under GPLv2 or any later version
|
// Licensed under GPLv2 or any later version
|
||||||
// Refer to the license.txt file included.
|
// Refer to the license.txt file included.
|
||||||
|
|
||||||
#include "core/hle/service/cfg/cfg.h"
|
|
||||||
#include "core/hle/service/cfg/cfg_u.h"
|
#include "core/hle/service/cfg/cfg_u.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
const Interface::FunctionInfo FunctionTable[] = {
|
CFG_U::CFG_U(std::shared_ptr<Module> cfg) : Module::Interface(std::move(cfg), "cfg:u", 23) {
|
||||||
// cfg common
|
static const FunctionInfo functions[] = {
|
||||||
{0x00010082, GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
// cfg common
|
||||||
{0x00020000, SecureInfoGetRegion, "SecureInfoGetRegion"},
|
{0x00010082, &CFG_U::GetConfigInfoBlk2, "GetConfigInfoBlk2"},
|
||||||
{0x00030040, GenHashConsoleUnique, "GenHashConsoleUnique"},
|
{0x00020000, &CFG_U::D<&CFG_U::SecureInfoGetRegion, 0x0002>, "SecureInfoGetRegion"},
|
||||||
{0x00040000, GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
{0x00030040, &CFG_U::GenHashConsoleUnique, "GenHashConsoleUnique"},
|
||||||
{0x00050000, GetSystemModel, "GetSystemModel"},
|
{0x00040000, &CFG_U::GetRegionCanadaUSA, "GetRegionCanadaUSA"},
|
||||||
{0x00060000, GetModelNintendo2DS, "GetModelNintendo2DS"},
|
{0x00050000, &CFG_U::GetSystemModel, "GetSystemModel"},
|
||||||
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
{0x00060000, &CFG_U::GetModelNintendo2DS, "GetModelNintendo2DS"},
|
||||||
{0x00080080, nullptr, "GoThroughTable"},
|
{0x00070040, nullptr, "WriteToFirstByteCfgSavegame"},
|
||||||
{0x00090040, GetCountryCodeString, "GetCountryCodeString"},
|
{0x00080080, nullptr, "GoThroughTable"},
|
||||||
{0x000A0040, GetCountryCodeID, "GetCountryCodeID"},
|
{0x00090040, &CFG_U::GetCountryCodeString, "GetCountryCodeString"},
|
||||||
{0x000B0000, nullptr, "IsFangateSupported"},
|
{0x000A0040, &CFG_U::GetCountryCodeID, "GetCountryCodeID"},
|
||||||
};
|
{0x000B0000, nullptr, "IsFangateSupported"},
|
||||||
|
};
|
||||||
CFG_U::CFG_U() {
|
RegisterHandlers(functions);
|
||||||
Register(FunctionTable);
|
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -4,18 +4,14 @@
|
||||||
|
|
||||||
#pragma once
|
#pragma once
|
||||||
|
|
||||||
#include "core/hle/service/service.h"
|
#include "core/hle/service/cfg/cfg.h"
|
||||||
|
|
||||||
namespace Service {
|
namespace Service {
|
||||||
namespace CFG {
|
namespace CFG {
|
||||||
|
|
||||||
class CFG_U final : public Interface {
|
class CFG_U final : public Module::Interface {
|
||||||
public:
|
public:
|
||||||
CFG_U();
|
explicit CFG_U(std::shared_ptr<Module> cfg);
|
||||||
|
|
||||||
std::string GetPortName() const override {
|
|
||||||
return "cfg:u";
|
|
||||||
}
|
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace CFG
|
} // namespace CFG
|
||||||
|
|
|
@ -9,6 +9,7 @@
|
||||||
#include "common/string_util.h"
|
#include "common/string_util.h"
|
||||||
#include "core/hle/ipc.h"
|
#include "core/hle/ipc.h"
|
||||||
#include "core/hle/kernel/client_port.h"
|
#include "core/hle/kernel/client_port.h"
|
||||||
|
#include "core/hle/kernel/handle_table.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/kernel/server_port.h"
|
#include "core/hle/kernel/server_port.h"
|
||||||
#include "core/hle/kernel/server_session.h"
|
#include "core/hle/kernel/server_session.h"
|
||||||
|
@ -242,7 +243,7 @@ void Init() {
|
||||||
BOSS::Init();
|
BOSS::Init();
|
||||||
CAM::InstallInterfaces(*SM::g_service_manager);
|
CAM::InstallInterfaces(*SM::g_service_manager);
|
||||||
CECD::Init();
|
CECD::Init();
|
||||||
CFG::Init();
|
CFG::InstallInterfaces(*SM::g_service_manager);
|
||||||
DLP::Init();
|
DLP::Init();
|
||||||
FRD::InstallInterfaces(*SM::g_service_manager);
|
FRD::InstallInterfaces(*SM::g_service_manager);
|
||||||
GSP::InstallInterfaces(*SM::g_service_manager);
|
GSP::InstallInterfaces(*SM::g_service_manager);
|
||||||
|
@ -273,7 +274,6 @@ void Init() {
|
||||||
void Shutdown() {
|
void Shutdown() {
|
||||||
NDM::Shutdown();
|
NDM::Shutdown();
|
||||||
DLP::Shutdown();
|
DLP::Shutdown();
|
||||||
CFG::Shutdown();
|
|
||||||
CECD::Shutdown();
|
CECD::Shutdown();
|
||||||
BOSS::Shutdown();
|
BOSS::Shutdown();
|
||||||
FS::ArchiveShutdown();
|
FS::ArchiveShutdown();
|
||||||
|
|
|
@ -135,7 +135,7 @@ void AppLoader_NCCH::ParseRegionLockoutInfo() {
|
||||||
constexpr u32 REGION_COUNT = 7;
|
constexpr u32 REGION_COUNT = 7;
|
||||||
for (u32 region = 0; region < REGION_COUNT; ++region) {
|
for (u32 region = 0; region < REGION_COUNT; ++region) {
|
||||||
if (region_lockout & 1) {
|
if (region_lockout & 1) {
|
||||||
Service::CFG::SetPreferredRegionCode(region);
|
Service::CFG::GetCurrentModule()->SetPreferredRegionCode(region);
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
region_lockout >>= 1;
|
region_lockout >>= 1;
|
||||||
|
|
Reference in New Issue