mirror of
https://github.com/Atmosphere-NX/Atmosphere.git
synced 2024-11-22 11:56:40 +00:00
Implement set_mitm
This commit is contained in:
parent
5228768841
commit
8764d94fd9
13 changed files with 341 additions and 12 deletions
|
@ -60,7 +60,7 @@ namespace ams::mitm {
|
|||
|
||||
constexpr ModuleDefinition g_module_definitions[ModuleId_Count] = {
|
||||
GetModuleDefinition<fs::MitmModule>(),
|
||||
GetModuleDefinition<set::MitmModule>(),
|
||||
GetModuleDefinition<settings::MitmModule>(),
|
||||
GetModuleDefinition<bpc::MitmModule>(),
|
||||
GetModuleDefinition<ns::MitmModule>(),
|
||||
GetModuleDefinition<hid::MitmModule>(),
|
||||
|
|
63
stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp
Normal file
63
stratosphere/ams_mitm/source/set_mitm/set_mitm_service.cpp
Normal file
|
@ -0,0 +1,63 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#include "set_mitm_service.hpp"
|
||||
|
||||
namespace ams::mitm::settings {
|
||||
|
||||
using namespace ams::settings;
|
||||
|
||||
Result SetMitmService::EnsureLocale() {
|
||||
std::scoped_lock lk(this->lock);
|
||||
|
||||
const bool is_ns = this->client_info.program_id == ncm::ProgramId::Ns;
|
||||
|
||||
if (!this->got_locale) {
|
||||
std::memset(&this->locale, 0xCC, sizeof(this->locale));
|
||||
ncm::ProgramId program_id = this->client_info.program_id;
|
||||
if (program_id == ncm::ProgramId::Ns) {
|
||||
/* When NS asks for a locale, refresh to get the current application locale. */
|
||||
os::ProcessId application_process_id;
|
||||
R_TRY(pm::dmnt::GetApplicationProcessId(&application_process_id));
|
||||
R_TRY(pm::info::GetProgramId(&program_id, application_process_id));
|
||||
}
|
||||
this->locale = cfg::GetOverrideLocale(program_id);
|
||||
this->got_locale = !is_ns;
|
||||
}
|
||||
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SetMitmService::GetLanguageCode(sf::Out<settings::LanguageCode> out) {
|
||||
this->EnsureLocale();
|
||||
|
||||
/* If there's no override locale, just use the actual one. */
|
||||
R_UNLESS(settings::IsValidLanguageCode(this->locale.language_code), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
out.SetValue(this->locale.language_code);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
Result SetMitmService::GetRegionCode(sf::Out<settings::RegionCode> out) {
|
||||
this->EnsureLocale();
|
||||
|
||||
/* If there's no override locale, just use the actual one. */
|
||||
R_UNLESS(settings::IsValidRegionCode(this->locale.region_code), sm::mitm::ResultShouldForwardToSession());
|
||||
|
||||
out.SetValue(this->locale.region_code);
|
||||
return ResultSuccess();
|
||||
}
|
||||
|
||||
}
|
|
@ -16,25 +16,39 @@
|
|||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::mitm::set {
|
||||
namespace ams::mitm::settings {
|
||||
|
||||
class SetMitmService : public sf::IMitmServiceObject {
|
||||
private:
|
||||
enum class CommandId {
|
||||
/* TODO */
|
||||
GetLanguageCode = 0,
|
||||
GetRegionCode = 4,
|
||||
};
|
||||
private:
|
||||
os::Mutex lock;
|
||||
cfg::OverrideLocale locale;
|
||||
bool got_locale;
|
||||
public:
|
||||
static bool ShouldMitm(const sm::MitmProcessInfo &client_info) {
|
||||
/* TODO */
|
||||
return false;
|
||||
/* We will mitm:
|
||||
* - ns and games, to allow for overriding game locales.
|
||||
*/
|
||||
const bool is_game = (ncm::IsApplicationProgramId(client_info.program_id) && !client_info.override_status.IsHbl());
|
||||
return client_info.program_id == ncm::ProgramId::Ns || is_game;
|
||||
}
|
||||
public:
|
||||
SF_MITM_SERVICE_OBJECT_CTOR(SetMitmService) { /* ... */ }
|
||||
SF_MITM_SERVICE_OBJECT_CTOR(SetMitmService) {
|
||||
this->got_locale = false;
|
||||
}
|
||||
private:
|
||||
Result EnsureLocale();
|
||||
protected:
|
||||
/* TODO */
|
||||
Result GetLanguageCode(sf::Out<ams::settings::LanguageCode> out);
|
||||
Result GetRegionCode(sf::Out<ams::settings::RegionCode> out);
|
||||
public:
|
||||
DEFINE_SERVICE_DISPATCH_TABLE {
|
||||
/* TODO */
|
||||
MAKE_SERVICE_COMMAND_META(GetLanguageCode),
|
||||
MAKE_SERVICE_COMMAND_META(GetRegionCode),
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include "set_mitm_service.hpp"
|
||||
#include "setsys_mitm_service.hpp"
|
||||
|
||||
namespace ams::mitm::set {
|
||||
namespace ams::mitm::settings {
|
||||
|
||||
namespace {
|
||||
|
||||
|
|
|
@ -17,7 +17,7 @@
|
|||
#include <stratosphere.hpp>
|
||||
#include "../amsmitm_module.hpp"
|
||||
|
||||
namespace ams::mitm::set {
|
||||
namespace ams::mitm::settings {
|
||||
|
||||
DEFINE_MITM_MODULE_CLASS(0x8000, 43);
|
||||
|
||||
|
|
|
@ -16,7 +16,7 @@
|
|||
#pragma once
|
||||
#include <stratosphere.hpp>
|
||||
|
||||
namespace ams::mitm::set {
|
||||
namespace ams::mitm::settings {
|
||||
|
||||
class SetSysMitmService : public sf::IMitmServiceObject {
|
||||
private:
|
||||
|
|
|
@ -43,6 +43,7 @@
|
|||
#include "stratosphere/reg.hpp"
|
||||
#include "stratosphere/rnd.hpp"
|
||||
#include "stratosphere/ro.hpp"
|
||||
#include "stratosphere/settings.hpp"
|
||||
#include "stratosphere/sf.hpp"
|
||||
#include "stratosphere/sm.hpp"
|
||||
#include "stratosphere/spl.hpp"
|
||||
|
|
|
@ -15,6 +15,7 @@
|
|||
*/
|
||||
#pragma once
|
||||
#include "cfg_types.hpp"
|
||||
#include "cfg_locale_types.hpp"
|
||||
|
||||
namespace ams::cfg {
|
||||
|
||||
|
@ -31,6 +32,9 @@ namespace ams::cfg {
|
|||
/* Override key utilities. */
|
||||
OverrideStatus CaptureOverrideStatus(ncm::ProgramId program_id);
|
||||
|
||||
/* Locale utilities. */
|
||||
OverrideLocale GetOverrideLocale(ncm::ProgramId program_id);
|
||||
|
||||
/* Flag utilities. */
|
||||
bool HasFlag(ncm::ProgramId program_id, const char *flag);
|
||||
bool HasContentSpecificFlag(ncm::ProgramId program_id, const char *flag);
|
||||
|
|
|
@ -0,0 +1,27 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
#pragma once
|
||||
#include "cfg_types.hpp"
|
||||
#include "../settings/settings_types.hpp"
|
||||
|
||||
namespace ams::cfg {
|
||||
|
||||
struct OverrideLocale {
|
||||
settings::LanguageCode language_code;
|
||||
settings::RegionCode region_code;
|
||||
};
|
||||
|
||||
}
|
|
@ -52,7 +52,7 @@ namespace ams::cfg {
|
|||
static_assert(std::is_pod<OverrideStatus>::value, "std::is_pod<OverrideStatus>::value");
|
||||
|
||||
constexpr inline bool operator==(const OverrideStatus &lhs, const OverrideStatus &rhs) {
|
||||
return lhs.keys_held == rhs.keys_held && lhs.flags == rhs.flags;
|
||||
return std::memcmp(&lhs, &rhs, sizeof(lhs)) == 0;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const OverrideStatus &lhs, const OverrideStatus &rhs) {
|
||||
|
|
|
@ -0,0 +1,19 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "settings/settings_types.hpp"
|
|
@ -0,0 +1,175 @@
|
|||
/*
|
||||
* Copyright (c) 2018-2019 Atmosphère-NX
|
||||
*
|
||||
* This program is free software; you can redistribute it and/or modify it
|
||||
* under the terms and conditions of the GNU General Public License,
|
||||
* version 2, as published by the Free Software Foundation.
|
||||
*
|
||||
* This program is distributed in the hope it will be useful, but WITHOUT
|
||||
* ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
|
||||
* FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
|
||||
* more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License
|
||||
* along with this program. If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#pragma once
|
||||
#include <atmosphere/common.hpp>
|
||||
|
||||
namespace ams::settings {
|
||||
|
||||
enum Language {
|
||||
Language_Japanese,
|
||||
Language_AmericanEnglish,
|
||||
Language_French,
|
||||
Language_German,
|
||||
Language_Italian,
|
||||
Language_Spanish,
|
||||
Language_Chinese,
|
||||
Language_Korean,
|
||||
Language_Dutch,
|
||||
Language_Portuguese,
|
||||
Language_Russian,
|
||||
Language_Taiwanese,
|
||||
Language_BritishEnglish,
|
||||
Language_CanadianFrench,
|
||||
Language_LatinAmericanSpanish,
|
||||
/* 4.0.0+ */
|
||||
Language_SimplifiedChinese,
|
||||
Language_TraditionalChinese,
|
||||
|
||||
Language_Count,
|
||||
};
|
||||
|
||||
struct LanguageCode {
|
||||
static constexpr size_t MaxLength = 8;
|
||||
|
||||
char name[MaxLength];
|
||||
|
||||
static constexpr LanguageCode Encode(const char *name, size_t name_size) {
|
||||
LanguageCode out{};
|
||||
for (size_t i = 0; i < MaxLength && i < name_size; i++) {
|
||||
out.name[i] = name[i];
|
||||
}
|
||||
return out;
|
||||
}
|
||||
|
||||
static constexpr LanguageCode Encode(const char *name) {
|
||||
return Encode(name, std::strlen(name));
|
||||
}
|
||||
|
||||
template<Language Lang>
|
||||
static constexpr inline LanguageCode EncodeLanguage = [] {
|
||||
if constexpr (false) { /* ... */ }
|
||||
#define AMS_MATCH_LANGUAGE(lang, enc) else if constexpr (Lang == Language_##lang) { return LanguageCode::Encode(enc); }
|
||||
AMS_MATCH_LANGUAGE(Japanese, "ja")
|
||||
AMS_MATCH_LANGUAGE(AmericanEnglish, "en-US")
|
||||
AMS_MATCH_LANGUAGE(French, "fr")
|
||||
AMS_MATCH_LANGUAGE(German, "de")
|
||||
AMS_MATCH_LANGUAGE(Italian, "it")
|
||||
AMS_MATCH_LANGUAGE(Spanish, "es")
|
||||
AMS_MATCH_LANGUAGE(Chinese, "zh-CN")
|
||||
AMS_MATCH_LANGUAGE(Korean, "ko")
|
||||
AMS_MATCH_LANGUAGE(Dutch, "nl")
|
||||
AMS_MATCH_LANGUAGE(Portuguese, "pt")
|
||||
AMS_MATCH_LANGUAGE(Russian, "ru")
|
||||
AMS_MATCH_LANGUAGE(Taiwanese, "zh-TW")
|
||||
AMS_MATCH_LANGUAGE(BritishEnglish, "en-GB")
|
||||
AMS_MATCH_LANGUAGE(CanadianFrench, "fr-CA")
|
||||
AMS_MATCH_LANGUAGE(LatinAmericanSpanish, "es-419")
|
||||
/* 4.0.0+ */
|
||||
AMS_MATCH_LANGUAGE(SimplifiedChinese, "zh-Hans")
|
||||
AMS_MATCH_LANGUAGE(TraditionalChinese, "zh-Hant")
|
||||
#undef AMS_MATCH_LANGUAGE
|
||||
else { static_assert(Lang != Language_Japanese); }
|
||||
}();
|
||||
|
||||
static constexpr inline LanguageCode Encode(const Language language) {
|
||||
constexpr LanguageCode EncodedLanguages[Language_Count] = {
|
||||
EncodeLanguage<Language_Japanese>,
|
||||
EncodeLanguage<Language_AmericanEnglish>,
|
||||
EncodeLanguage<Language_French>,
|
||||
EncodeLanguage<Language_German>,
|
||||
EncodeLanguage<Language_Italian>,
|
||||
EncodeLanguage<Language_Spanish>,
|
||||
EncodeLanguage<Language_Chinese>,
|
||||
EncodeLanguage<Language_Korean>,
|
||||
EncodeLanguage<Language_Dutch>,
|
||||
EncodeLanguage<Language_Portuguese>,
|
||||
EncodeLanguage<Language_Russian>,
|
||||
EncodeLanguage<Language_Taiwanese>,
|
||||
EncodeLanguage<Language_BritishEnglish>,
|
||||
EncodeLanguage<Language_CanadianFrench>,
|
||||
EncodeLanguage<Language_LatinAmericanSpanish>,
|
||||
/* 4.0.0+ */
|
||||
EncodeLanguage<Language_SimplifiedChinese>,
|
||||
EncodeLanguage<Language_TraditionalChinese>,
|
||||
};
|
||||
return EncodedLanguages[language];
|
||||
}
|
||||
|
||||
};
|
||||
|
||||
constexpr inline bool operator==(const LanguageCode &lhs, const LanguageCode &rhs) {
|
||||
return std::strncmp(lhs.name, rhs.name, sizeof(lhs)) == 0;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const LanguageCode &lhs, const LanguageCode &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
constexpr inline bool operator==(const LanguageCode &lhs, const Language &rhs) {
|
||||
return lhs == LanguageCode::Encode(rhs);
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const LanguageCode &lhs, const Language &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
constexpr inline bool operator==(const Language &lhs, const LanguageCode &rhs) {
|
||||
return rhs == lhs;
|
||||
}
|
||||
|
||||
constexpr inline bool operator!=(const Language &lhs, const LanguageCode &rhs) {
|
||||
return !(lhs == rhs);
|
||||
}
|
||||
|
||||
namespace impl {
|
||||
|
||||
template<size_t ...Is>
|
||||
constexpr inline bool IsValidLanguageCode(const LanguageCode &lc, std::index_sequence<Is...>) {
|
||||
return ((lc == LanguageCode::Encode(static_cast<Language>(Is))) || ...);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
constexpr inline bool IsValidLanguageCodeDeprecated(const LanguageCode &lc) {
|
||||
return impl::IsValidLanguageCode(lc, std::make_index_sequence<Language_Count - 2>{});
|
||||
}
|
||||
|
||||
constexpr inline bool IsValidLanguageCode(const LanguageCode &lc) {
|
||||
return impl::IsValidLanguageCode(lc, std::make_index_sequence<Language_Count>{});
|
||||
}
|
||||
|
||||
static_assert(std::is_pod<LanguageCode>::value);
|
||||
static_assert(sizeof(LanguageCode) == sizeof(u64));
|
||||
|
||||
/* Not an official type, but convenient. */
|
||||
enum RegionCode : s32 {
|
||||
RegionCode_Japan,
|
||||
RegionCode_America,
|
||||
RegionCode_Europe,
|
||||
RegionCode_Australia,
|
||||
RegionCode_China,
|
||||
RegionCode_Korea,
|
||||
RegionCode_Taiwan,
|
||||
|
||||
RegionCode_Count,
|
||||
};
|
||||
|
||||
constexpr inline bool IsValidRegionCode(const RegionCode rc) {
|
||||
return 0 <= rc && rc < RegionCode_Count;
|
||||
}
|
||||
|
||||
}
|
|
@ -36,6 +36,7 @@ namespace ams::cfg {
|
|||
struct ContentSpecificOverrideConfig {
|
||||
OverrideKey override_key;
|
||||
OverrideKey cheat_enable_key;
|
||||
OverrideLocale locale;
|
||||
};
|
||||
|
||||
/* Override globals. */
|
||||
|
@ -164,10 +165,29 @@ namespace ams::cfg {
|
|||
config->override_key = ParseOverrideKey(value);
|
||||
} else if (strcasecmp(name, "cheat_enable_key") == 0) {
|
||||
config->cheat_enable_key = ParseOverrideKey(value);
|
||||
} else if (strcasecmp(name, "override_language") == 0) {
|
||||
config->locale.language_code = settings::LanguageCode::Encode(value);
|
||||
} else if (strcasecmp(name, "override_region") == 0) {
|
||||
if (strcasecmp(value, "jpn") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_Japan;
|
||||
} else if (strcasecmp(value, "usa") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_America;
|
||||
} else if (strcasecmp(value, "eur") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_Europe;
|
||||
} else if (strcasecmp(value, "aus") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_Australia;
|
||||
} else if (strcasecmp(value, "chn") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_China;
|
||||
} else if (strcasecmp(value, "kor") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_Korea;
|
||||
} else if (strcasecmp(value, "twn") == 0) {
|
||||
config->locale.region_code = settings::RegionCode_Taiwan;
|
||||
}
|
||||
}
|
||||
} else {
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
|
@ -215,6 +235,8 @@ namespace ams::cfg {
|
|||
.override_key = g_default_override_key,
|
||||
.cheat_enable_key = g_default_cheat_enable_key,
|
||||
};
|
||||
std::memset(&config.locale, 0xCC, sizeof(config.locale));
|
||||
|
||||
ParseIniFile(ContentSpecificIniHandler, path, &config);
|
||||
return config;
|
||||
}
|
||||
|
@ -264,6 +286,10 @@ namespace ams::cfg {
|
|||
return status;
|
||||
}
|
||||
|
||||
OverrideLocale GetOverrideLocale(ncm::ProgramId program_id) {
|
||||
return GetContentOverrideConfig(program_id).locale;
|
||||
}
|
||||
|
||||
/* HBL Configuration utilities. */
|
||||
bool IsHblProgramId(ncm::ProgramId program_id) {
|
||||
return IsApplicationHblProgramId(program_id) || IsSpecificHblProgramId(program_id);
|
||||
|
|
Loading…
Reference in a new issue