1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
// Copyright 2018 yuzu emulator team
// Licensed under GPLv2 or any later version
// Refer to the license.txt file included.
#include "common/file_util.h"
#include "common/logging/log.h"
#include "core/file_sys/program_metadata.h"
#include "core/loader/loader.h"
namespace FileSys {
Loader::ResultStatus ProgramMetadata::Load(const std::string& file_path) {
FileUtil::IOFile file(file_path, "rb");
if (!file.IsOpen())
return Loader::ResultStatus::Error;
std::vector<u8> file_data(file.GetSize());
if (!file.ReadBytes(file_data.data(), file_data.size()))
return Loader::ResultStatus::Error;
Loader::ResultStatus result = Load(file_data);
if (result != Loader::ResultStatus::Success)
NGLOG_ERROR(Service_FS, "Failed to load NPDM from file {}!", file_path);
return result;
}
Loader::ResultStatus ProgramMetadata::Load(const std::vector<u8> file_data, size_t offset) {
size_t total_size = static_cast<size_t>(file_data.size() - offset);
if (total_size < sizeof(Header))
return Loader::ResultStatus::Error;
size_t header_offset = offset;
memcpy(&npdm_header, &file_data[offset], sizeof(Header));
size_t aci_offset = header_offset + npdm_header.aci_offset;
size_t acid_offset = header_offset + npdm_header.acid_offset;
memcpy(&aci_header, &file_data[aci_offset], sizeof(AciHeader));
memcpy(&acid_header, &file_data[acid_offset], sizeof(AcidHeader));
size_t fac_offset = acid_offset + acid_header.fac_offset;
size_t fah_offset = aci_offset + aci_header.fah_offset;
memcpy(&acid_file_access, &file_data[fac_offset], sizeof(FileAccessControl));
memcpy(&aci_file_access, &file_data[fah_offset], sizeof(FileAccessHeader));
return Loader::ResultStatus::Success;
}
bool ProgramMetadata::Is64BitProgram() const {
return npdm_header.has_64_bit_instructions;
}
ProgramAddressSpaceType ProgramMetadata::GetAddressSpaceType() const {
return npdm_header.address_space_type;
}
u8 ProgramMetadata::GetMainThreadPriority() const {
return npdm_header.main_thread_priority;
}
u8 ProgramMetadata::GetMainThreadCore() const {
return npdm_header.main_thread_cpu;
}
u32 ProgramMetadata::GetMainThreadStackSize() const {
return npdm_header.main_stack_size;
}
u64 ProgramMetadata::GetTitleID() const {
return aci_header.title_id;
}
u64 ProgramMetadata::GetFilesystemPermissions() const {
return aci_file_access.permissions;
}
void ProgramMetadata::Print() const {
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", npdm_header.magic.data());
NGLOG_DEBUG(Service_FS, "Main thread priority: {:#04X}", npdm_header.main_thread_priority);
NGLOG_DEBUG(Service_FS, "Main thread core: {}", npdm_header.main_thread_cpu);
NGLOG_DEBUG(Service_FS, "Main thread stack size: {:#X} bytes", npdm_header.main_stack_size);
NGLOG_DEBUG(Service_FS, "Process category: {}", npdm_header.process_category);
NGLOG_DEBUG(Service_FS, "Flags: {:02X}", npdm_header.flags);
NGLOG_DEBUG(Service_FS, " > 64-bit instructions: {}",
npdm_header.has_64_bit_instructions ? "YES" : "NO");
auto address_space = "Unknown";
switch (npdm_header.address_space_type) {
case ProgramAddressSpaceType::Is64Bit:
address_space = "64-bit";
break;
case ProgramAddressSpaceType::Is32Bit:
address_space = "32-bit";
break;
}
NGLOG_DEBUG(Service_FS, " > Address space: {}\n", address_space);
// Begin ACID printing (potential perms, signed)
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", acid_header.magic.data());
NGLOG_DEBUG(Service_FS, "Flags: {:02X}", acid_header.flags);
NGLOG_DEBUG(Service_FS, " > Is Retail: {}", acid_header.is_retail ? "YES" : "NO");
NGLOG_DEBUG(Service_FS, "Title ID Min: {:016X}", acid_header.title_id_min);
NGLOG_DEBUG(Service_FS, "Title ID Max: {:016X}", acid_header.title_id_max);
NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", acid_file_access.permissions);
// Begin ACI0 printing (actual perms, unsigned)
NGLOG_DEBUG(Service_FS, "Magic: {:.4}", aci_header.magic.data());
NGLOG_DEBUG(Service_FS, "Title ID: {:016X}", aci_header.title_id);
NGLOG_DEBUG(Service_FS, "Filesystem Access: {:016X}\n", aci_file_access.permissions);
}
} // namespace FileSys
|