forked from suyu/suyu
pl_u, applets/web: Decrypt shared fonts to TTF files
This commit is contained in:
parent
46183294b2
commit
d46ca5a015
3 changed files with 117 additions and 18 deletions
|
@ -16,12 +16,14 @@
|
||||||
#include "core/file_sys/romfs.h"
|
#include "core/file_sys/romfs.h"
|
||||||
#include "core/file_sys/system_archive/system_archive.h"
|
#include "core/file_sys/system_archive/system_archive.h"
|
||||||
#include "core/file_sys/vfs_types.h"
|
#include "core/file_sys/vfs_types.h"
|
||||||
|
#include "core/file_sys/vfs_vector.h"
|
||||||
#include "core/frontend/applets/web_browser.h"
|
#include "core/frontend/applets/web_browser.h"
|
||||||
#include "core/hle/kernel/process.h"
|
#include "core/hle/kernel/process.h"
|
||||||
#include "core/hle/result.h"
|
#include "core/hle/result.h"
|
||||||
#include "core/hle/service/am/am.h"
|
#include "core/hle/service/am/am.h"
|
||||||
#include "core/hle/service/am/applets/web_browser.h"
|
#include "core/hle/service/am/applets/web_browser.h"
|
||||||
#include "core/hle/service/filesystem/filesystem.h"
|
#include "core/hle/service/filesystem/filesystem.h"
|
||||||
|
#include "core/hle/service/ns/pl_u.h"
|
||||||
|
|
||||||
namespace Service::AM::Applets {
|
namespace Service::AM::Applets {
|
||||||
|
|
||||||
|
@ -123,6 +125,88 @@ FileSys::VirtualFile GetOfflineRomFS(Core::System& system, u64 title_id,
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void ExtractSharedFonts(Core::System& system) {
|
||||||
|
static constexpr std::array<const char*, 7> DECRYPTED_SHARED_FONTS{
|
||||||
|
"FontStandard.ttf",
|
||||||
|
"FontChineseSimplified.ttf",
|
||||||
|
"FontExtendedChineseSimplified.ttf",
|
||||||
|
"FontChineseTraditional.ttf",
|
||||||
|
"FontKorean.ttf",
|
||||||
|
"FontNintendoExtended.ttf",
|
||||||
|
"FontNintendoExtended2.ttf",
|
||||||
|
};
|
||||||
|
|
||||||
|
for (std::size_t i = 0; i < NS::SHARED_FONTS.size(); ++i) {
|
||||||
|
const auto fonts_dir = Common::FS::SanitizePath(
|
||||||
|
fmt::format("{}/fonts", Common::FS::GetUserPath(Common::FS::UserPath::CacheDir)),
|
||||||
|
Common::FS::DirectorySeparator::PlatformDefault);
|
||||||
|
|
||||||
|
const auto font_file_path =
|
||||||
|
Common::FS::SanitizePath(fmt::format("{}/{}", fonts_dir, DECRYPTED_SHARED_FONTS[i]),
|
||||||
|
Common::FS::DirectorySeparator::PlatformDefault);
|
||||||
|
|
||||||
|
if (Common::FS::Exists(font_file_path)) {
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto font = NS::SHARED_FONTS[i];
|
||||||
|
const auto font_title_id = static_cast<u64>(font.first);
|
||||||
|
|
||||||
|
const auto nca = system.GetFileSystemController().GetSystemNANDContents()->GetEntry(
|
||||||
|
font_title_id, FileSys::ContentRecordType::Data);
|
||||||
|
|
||||||
|
FileSys::VirtualFile romfs;
|
||||||
|
|
||||||
|
if (!nca) {
|
||||||
|
romfs = FileSys::SystemArchive::SynthesizeSystemArchive(font_title_id);
|
||||||
|
} else {
|
||||||
|
romfs = nca->GetRomFS();
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!romfs) {
|
||||||
|
LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} cannot be extracted!",
|
||||||
|
font_title_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto extracted_romfs = FileSys::ExtractRomFS(romfs);
|
||||||
|
|
||||||
|
if (!extracted_romfs) {
|
||||||
|
LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} failed to extract!",
|
||||||
|
font_title_id);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
const auto font_file = extracted_romfs->GetFile(font.second);
|
||||||
|
|
||||||
|
if (!font_file) {
|
||||||
|
LOG_ERROR(Service_AM, "SharedFont RomFS with title_id={:016X} has no font file \"{}\"!",
|
||||||
|
font_title_id, font.second);
|
||||||
|
continue;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<u32> font_data_u32(font_file->GetSize() / sizeof(u32));
|
||||||
|
font_file->ReadBytes<u32>(font_data_u32.data(), font_file->GetSize());
|
||||||
|
|
||||||
|
std::transform(font_data_u32.begin(), font_data_u32.end(), font_data_u32.begin(),
|
||||||
|
Common::swap32);
|
||||||
|
|
||||||
|
std::vector<u8> decrypted_data(font_file->GetSize() - 8);
|
||||||
|
|
||||||
|
NS::DecryptSharedFontToTTF(font_data_u32, decrypted_data);
|
||||||
|
|
||||||
|
FileSys::VirtualFile decrypted_font = std::make_shared<FileSys::VectorVfsFile>(
|
||||||
|
std::move(decrypted_data), DECRYPTED_SHARED_FONTS[i]);
|
||||||
|
|
||||||
|
const auto temp_dir =
|
||||||
|
system.GetFilesystem()->CreateDirectory(fonts_dir, FileSys::Mode::ReadWrite);
|
||||||
|
|
||||||
|
const auto out_file = temp_dir->CreateFile(DECRYPTED_SHARED_FONTS[i]);
|
||||||
|
|
||||||
|
FileSys::VfsRawCopy(decrypted_font, out_file);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace
|
} // namespace
|
||||||
|
|
||||||
WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_)
|
WebBrowser::WebBrowser(Core::System& system_, const Core::Frontend::WebBrowserApplet& frontend_)
|
||||||
|
@ -155,6 +239,8 @@ void WebBrowser::Initialize() {
|
||||||
LOG_DEBUG(Service_AM, "WebArgHeader: total_tlv_entries={}, shim_kind={}",
|
LOG_DEBUG(Service_AM, "WebArgHeader: total_tlv_entries={}, shim_kind={}",
|
||||||
web_arg_header.total_tlv_entries, web_arg_header.shim_kind);
|
web_arg_header.total_tlv_entries, web_arg_header.shim_kind);
|
||||||
|
|
||||||
|
ExtractSharedFonts(system);
|
||||||
|
|
||||||
switch (web_arg_header.shim_kind) {
|
switch (web_arg_header.shim_kind) {
|
||||||
case ShimKind::Shop:
|
case ShimKind::Shop:
|
||||||
InitializeShop();
|
InitializeShop();
|
||||||
|
|
|
@ -27,29 +27,11 @@
|
||||||
|
|
||||||
namespace Service::NS {
|
namespace Service::NS {
|
||||||
|
|
||||||
enum class FontArchives : u64 {
|
|
||||||
Extension = 0x0100000000000810,
|
|
||||||
Standard = 0x0100000000000811,
|
|
||||||
Korean = 0x0100000000000812,
|
|
||||||
ChineseTraditional = 0x0100000000000813,
|
|
||||||
ChineseSimple = 0x0100000000000814,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct FontRegion {
|
struct FontRegion {
|
||||||
u32 offset;
|
u32 offset;
|
||||||
u32 size;
|
u32 size;
|
||||||
};
|
};
|
||||||
|
|
||||||
constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
|
|
||||||
std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"),
|
|
||||||
std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"),
|
|
||||||
};
|
|
||||||
|
|
||||||
// The below data is specific to shared font data dumped from Switch on f/w 2.2
|
// The below data is specific to shared font data dumped from Switch on f/w 2.2
|
||||||
// Virtual address and offsets/sizes likely will vary by dump
|
// Virtual address and offsets/sizes likely will vary by dump
|
||||||
[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
|
[[maybe_unused]] constexpr VAddr SHARED_FONT_MEM_VADDR{0x00000009d3016000ULL};
|
||||||
|
@ -80,6 +62,18 @@ static void DecryptSharedFont(const std::vector<u32>& input, Kernel::PhysicalMem
|
||||||
offset += transformed_font.size() * sizeof(u32);
|
offset += transformed_font.size() * sizeof(u32);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output) {
|
||||||
|
ASSERT_MSG(input[0] == EXPECTED_MAGIC, "Failed to derive key, unexpected magic number");
|
||||||
|
|
||||||
|
const u32 KEY = input[0] ^ EXPECTED_RESULT; // Derive key using an inverse xor
|
||||||
|
std::vector<u32> transformed_font(input.size());
|
||||||
|
// TODO(ogniK): Figure out a better way to do this
|
||||||
|
std::transform(input.begin(), input.end(), transformed_font.begin(),
|
||||||
|
[&KEY](u32 font_data) { return Common::swap32(font_data ^ KEY); });
|
||||||
|
transformed_font[1] = Common::swap32(transformed_font[1]) ^ KEY; // "re-encrypt" the size
|
||||||
|
std::memcpy(output.data(), transformed_font.data() + 2, transformed_font.size() * sizeof(u32));
|
||||||
|
}
|
||||||
|
|
||||||
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
|
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output,
|
||||||
std::size_t& offset) {
|
std::size_t& offset) {
|
||||||
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
|
ASSERT_MSG(offset + (input.size() * sizeof(u32)) < SHARED_FONT_MEM_SIZE,
|
||||||
|
|
|
@ -16,6 +16,25 @@ class FileSystemController;
|
||||||
|
|
||||||
namespace NS {
|
namespace NS {
|
||||||
|
|
||||||
|
enum class FontArchives : u64 {
|
||||||
|
Extension = 0x0100000000000810,
|
||||||
|
Standard = 0x0100000000000811,
|
||||||
|
Korean = 0x0100000000000812,
|
||||||
|
ChineseTraditional = 0x0100000000000813,
|
||||||
|
ChineseSimple = 0x0100000000000814,
|
||||||
|
};
|
||||||
|
|
||||||
|
constexpr std::array<std::pair<FontArchives, const char*>, 7> SHARED_FONTS{
|
||||||
|
std::make_pair(FontArchives::Standard, "nintendo_udsg-r_std_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_org_zh-cn_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::ChineseSimple, "nintendo_udsg-r_ext_zh-cn_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::ChineseTraditional, "nintendo_udjxh-db_zh-tw_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::Korean, "nintendo_udsg-r_ko_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::Extension, "nintendo_ext_003.bfttf"),
|
||||||
|
std::make_pair(FontArchives::Extension, "nintendo_ext2_003.bfttf"),
|
||||||
|
};
|
||||||
|
|
||||||
|
void DecryptSharedFontToTTF(const std::vector<u32>& input, std::vector<u8>& output);
|
||||||
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
|
void EncryptSharedFont(const std::vector<u32>& input, std::vector<u8>& output, std::size_t& offset);
|
||||||
|
|
||||||
class PL_U final : public ServiceFramework<PL_U> {
|
class PL_U final : public ServiceFramework<PL_U> {
|
||||||
|
|
Loading…
Reference in a new issue