Implement set_mitm

This commit is contained in:
Michael Scire 2019-11-21 19:32:41 -08:00 committed by SciresM
parent 5228768841
commit 8764d94fd9
13 changed files with 341 additions and 12 deletions

View file

@ -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>(),

View 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();
}
}

View file

@ -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),
};
};

View file

@ -17,7 +17,7 @@
#include "set_mitm_service.hpp"
#include "setsys_mitm_service.hpp"
namespace ams::mitm::set {
namespace ams::mitm::settings {
namespace {

View file

@ -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);

View file

@ -16,7 +16,7 @@
#pragma once
#include <stratosphere.hpp>
namespace ams::mitm::set {
namespace ams::mitm::settings {
class SetSysMitmService : public sf::IMitmServiceObject {
private:

View file

@ -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"

View file

@ -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);

View file

@ -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;
};
}

View file

@ -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) {

View file

@ -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"

View file

@ -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;
}
}

View file

@ -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);