summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/core/CMakeLists.txt2
-rw-r--r--src/core/file_sys/control_metadata.cpp42
-rw-r--r--src/core/file_sys/control_metadata.h81
-rw-r--r--src/core/loader/nro.cpp79
-rw-r--r--src/core/loader/nro.h12
5 files changed, 215 insertions, 1 deletions
diff --git a/src/core/CMakeLists.txt b/src/core/CMakeLists.txt
index 27a5de7fd..fd75854b0 100644
--- a/src/core/CMakeLists.txt
+++ b/src/core/CMakeLists.txt
@@ -12,6 +12,8 @@ add_library(core STATIC
12 core_timing.h 12 core_timing.h
13 file_sys/content_archive.cpp 13 file_sys/content_archive.cpp
14 file_sys/content_archive.h 14 file_sys/content_archive.h
15 file_sys/control_metadata.cpp
16 file_sys/control_metadata.h
15 file_sys/directory.h 17 file_sys/directory.h
16 file_sys/errors.h 18 file_sys/errors.h
17 file_sys/mode.h 19 file_sys/mode.h
diff --git a/src/core/file_sys/control_metadata.cpp b/src/core/file_sys/control_metadata.cpp
new file mode 100644
index 000000000..3ddc9f162
--- /dev/null
+++ b/src/core/file_sys/control_metadata.cpp
@@ -0,0 +1,42 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#include "common/string_util.h"
6#include "common/swap.h"
7#include "core/file_sys/control_metadata.h"
8
9namespace FileSys {
10
11std::string LanguageEntry::GetApplicationName() const {
12 return Common::StringFromFixedZeroTerminatedBuffer(application_name.data(), 0x200);
13}
14
15std::string LanguageEntry::GetDeveloperName() const {
16 return Common::StringFromFixedZeroTerminatedBuffer(developer_name.data(), 0x100);
17}
18
19NACP::NACP(VirtualFile file_) : file(std::move(file_)), raw(std::make_unique<RawNACP>()) {
20 file->ReadObject(raw.get());
21}
22
23const LanguageEntry& NACP::GetLanguageEntry(Language language) const {
24 return raw->language_entries.at(static_cast<u8>(language));
25}
26
27std::string NACP::GetApplicationName(Language language) const {
28 return GetLanguageEntry(language).GetApplicationName();
29}
30
31std::string NACP::GetDeveloperName(Language language) const {
32 return GetLanguageEntry(language).GetDeveloperName();
33}
34
35u64 NACP::GetTitleId() const {
36 return raw->title_id;
37}
38
39std::string NACP::GetVersionString() const {
40 return Common::StringFromFixedZeroTerminatedBuffer(raw->version_string.data(), 0x10);
41}
42} // namespace FileSys
diff --git a/src/core/file_sys/control_metadata.h b/src/core/file_sys/control_metadata.h
new file mode 100644
index 000000000..cc3b745f7
--- /dev/null
+++ b/src/core/file_sys/control_metadata.h
@@ -0,0 +1,81 @@
1// Copyright 2018 yuzu emulator team
2// Licensed under GPLv2 or any later version
3// Refer to the license.txt file included.
4
5#pragma once
6
7#include <array>
8#include <memory>
9#include <string>
10#include "common/common_funcs.h"
11#include "core/file_sys/vfs.h"
12
13namespace FileSys {
14
15// A localized entry containing strings within the NACP.
16// One for each language of type Language.
17struct LanguageEntry {
18 std::array<char, 0x200> application_name;
19 std::array<char, 0x100> developer_name;
20
21 std::string GetApplicationName() const;
22 std::string GetDeveloperName() const;
23};
24static_assert(sizeof(LanguageEntry) == 0x300, "LanguageEntry has incorrect size.");
25
26// The raw file format of a NACP file.
27struct RawNACP {
28 std::array<LanguageEntry, 16> language_entries;
29 INSERT_PADDING_BYTES(0x38);
30 u64_le title_id;
31 INSERT_PADDING_BYTES(0x20);
32 std::array<char, 0x10> version_string;
33 u64_le dlc_base_title_id;
34 u64_le title_id_2;
35 INSERT_PADDING_BYTES(0x28);
36 u64_le product_code;
37 u64_le title_id_3;
38 std::array<u64_le, 0x7> title_id_array;
39 INSERT_PADDING_BYTES(0x8);
40 u64_le title_id_update;
41 std::array<u8, 0x40> bcat_passphrase;
42 INSERT_PADDING_BYTES(0xEC0);
43};
44static_assert(sizeof(RawNACP) == 0x4000, "RawNACP has incorrect size.");
45
46// A language on the NX. These are for names and icons.
47enum class Language : u8 {
48 AmericanEnglish = 0,
49 BritishEnglish = 1,
50 Japanese = 2,
51 French = 3,
52 German = 4,
53 LatinAmericanSpanish = 5,
54 Spanish = 6,
55 Italian = 7,
56 Dutch = 8,
57 CanadianFrench = 9,
58 Portugese = 10,
59 Russian = 11,
60 Korean = 12,
61 Taiwanese = 13,
62 Chinese = 14,
63};
64
65// A class representing the format used by NX metadata files, typically named Control.nacp.
66// These store application name, dev name, title id, and other miscellaneous data.
67class NACP {
68public:
69 explicit NACP(VirtualFile file);
70 const LanguageEntry& GetLanguageEntry(Language language = Language::AmericanEnglish) const;
71 std::string GetApplicationName(Language language = Language::AmericanEnglish) const;
72 std::string GetDeveloperName(Language language = Language::AmericanEnglish) const;
73 u64 GetTitleId() const;
74 std::string GetVersionString() const;
75
76private:
77 VirtualFile file;
78 std::unique_ptr<RawNACP> raw;
79};
80
81} // namespace FileSys
diff --git a/src/core/loader/nro.cpp b/src/core/loader/nro.cpp
index c020399f2..44158655c 100644
--- a/src/core/loader/nro.cpp
+++ b/src/core/loader/nro.cpp
@@ -10,6 +10,8 @@
10#include "common/logging/log.h" 10#include "common/logging/log.h"
11#include "common/swap.h" 11#include "common/swap.h"
12#include "core/core.h" 12#include "core/core.h"
13#include "core/file_sys/control_metadata.h"
14#include "core/file_sys/vfs_offset.h"
13#include "core/gdbstub/gdbstub.h" 15#include "core/gdbstub/gdbstub.h"
14#include "core/hle/kernel/process.h" 16#include "core/hle/kernel/process.h"
15#include "core/hle/kernel/resource_limit.h" 17#include "core/hle/kernel/resource_limit.h"
@@ -49,7 +51,55 @@ struct ModHeader {
49}; 51};
50static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size."); 52static_assert(sizeof(ModHeader) == 0x1c, "ModHeader has incorrect size.");
51 53
52AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(std::move(file)) {} 54struct AssetSection {
55 u64_le offset;
56 u64_le size;
57};
58static_assert(sizeof(AssetSection) == 0x10, "AssetSection has incorrect size.");
59
60struct AssetHeader {
61 u32_le magic;
62 u32_le format_version;
63 AssetSection icon;
64 AssetSection nacp;
65 AssetSection romfs;
66};
67static_assert(sizeof(AssetHeader) == 0x38, "AssetHeader has incorrect size.");
68
69AppLoader_NRO::AppLoader_NRO(FileSys::VirtualFile file) : AppLoader(file) {
70 NroHeader nro_header{};
71 if (file->ReadObject(&nro_header) != sizeof(NroHeader))
72 return;
73
74 if (file->GetSize() >= nro_header.file_size + sizeof(AssetHeader)) {
75 u64 offset = nro_header.file_size;
76 AssetHeader asset_header{};
77 if (file->ReadObject(&asset_header, offset) != sizeof(AssetHeader))
78 return;
79
80 if (asset_header.format_version != 0)
81 LOG_WARNING(Loader,
82 "NRO Asset Header has format {}, currently supported format is 0. If "
83 "strange glitches occur with metadata, check NRO assets.",
84 asset_header.format_version);
85 if (asset_header.magic != Common::MakeMagic('A', 'S', 'E', 'T'))
86 return;
87
88 if (asset_header.nacp.size > 0) {
89 nacp = std::make_unique<FileSys::NACP>(std::make_shared<FileSys::OffsetVfsFile>(
90 file, asset_header.nacp.size, offset + asset_header.nacp.offset, "Control.nacp"));
91 }
92
93 if (asset_header.romfs.size > 0) {
94 romfs = std::make_shared<FileSys::OffsetVfsFile>(
95 file, asset_header.romfs.size, offset + asset_header.romfs.offset, "game.romfs");
96 }
97
98 if (asset_header.icon.size > 0) {
99 icon_data = file->ReadBytes(asset_header.icon.size, offset + asset_header.icon.offset);
100 }
101 }
102}
53 103
54FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) { 104FileType AppLoader_NRO::IdentifyType(const FileSys::VirtualFile& file) {
55 // Read NSO header 105 // Read NSO header
@@ -136,4 +186,31 @@ ResultStatus AppLoader_NRO::Load(Kernel::SharedPtr<Kernel::Process>& process) {
136 return ResultStatus::Success; 186 return ResultStatus::Success;
137} 187}
138 188
189ResultStatus AppLoader_NRO::ReadIcon(std::vector<u8>& buffer) {
190 if (icon_data.empty())
191 return ResultStatus::ErrorNotUsed;
192 buffer = icon_data;
193 return ResultStatus::Success;
194}
195
196ResultStatus AppLoader_NRO::ReadProgramId(u64& out_program_id) {
197 if (nacp == nullptr)
198 return ResultStatus::ErrorNotUsed;
199 out_program_id = nacp->GetTitleId();
200 return ResultStatus::Success;
201}
202
203ResultStatus AppLoader_NRO::ReadRomFS(FileSys::VirtualFile& dir) {
204 if (romfs == nullptr)
205 return ResultStatus::ErrorNotUsed;
206 dir = romfs;
207 return ResultStatus::Success;
208}
209
210ResultStatus AppLoader_NRO::ReadTitle(std::string& title) {
211 if (nacp == nullptr)
212 return ResultStatus::ErrorNotUsed;
213 title = nacp->GetApplicationName();
214 return ResultStatus::Success;
215}
139} // namespace Loader 216} // namespace Loader
diff --git a/src/core/loader/nro.h b/src/core/loader/nro.h
index 2c03d06bb..5f3fc40d2 100644
--- a/src/core/loader/nro.h
+++ b/src/core/loader/nro.h
@@ -6,12 +6,15 @@
6 6
7#include <string> 7#include <string>
8#include "common/common_types.h" 8#include "common/common_types.h"
9#include "core/file_sys/control_metadata.h"
9#include "core/hle/kernel/kernel.h" 10#include "core/hle/kernel/kernel.h"
10#include "core/loader/linker.h" 11#include "core/loader/linker.h"
11#include "core/loader/loader.h" 12#include "core/loader/loader.h"
12 13
13namespace Loader { 14namespace Loader {
14 15
16struct AssetHeader;
17
15/// Loads an NRO file 18/// Loads an NRO file
16class AppLoader_NRO final : public AppLoader, Linker { 19class AppLoader_NRO final : public AppLoader, Linker {
17public: 20public:
@@ -30,8 +33,17 @@ public:
30 33
31 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override; 34 ResultStatus Load(Kernel::SharedPtr<Kernel::Process>& process) override;
32 35
36 ResultStatus ReadIcon(std::vector<u8>& buffer) override;
37 ResultStatus ReadProgramId(u64& out_program_id) override;
38 ResultStatus ReadRomFS(FileSys::VirtualFile& dir) override;
39 ResultStatus ReadTitle(std::string& title) override;
40
33private: 41private:
34 bool LoadNro(FileSys::VirtualFile file, VAddr load_base); 42 bool LoadNro(FileSys::VirtualFile file, VAddr load_base);
43
44 std::vector<u8> icon_data;
45 std::unique_ptr<FileSys::NACP> nacp;
46 FileSys::VirtualFile romfs;
35}; 47};
36 48
37} // namespace Loader 49} // namespace Loader