/
Formats.h
231 lines (197 loc) · 5.36 KB
/
Formats.h
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
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
// Copyright 2017 Dolphin Emulator Project
// Licensed under GPLv2+
// Refer to the license.txt file included.
// Utilities to manipulate files and formats from the Wii's ES module: tickets,
// TMD, and other title informations.
#pragma once
#include <array>
#include <string>
#include <vector>
#include "Common/ChunkFile.h"
#include "Common/CommonTypes.h"
#include "Common/NandPaths.h"
#include "DiscIO/Enums.h"
namespace IOS
{
namespace ES
{
enum class TitleType : u32
{
System = 0x00000001,
Game = 0x00010000,
Channel = 0x00010001,
SystemChannel = 0x00010002,
GameWithChannel = 0x00010004,
DLC = 0x00010005,
HiddenChannel = 0x00010008,
};
bool IsTitleType(u64 title_id, TitleType title_type);
bool IsDiscTitle(u64 title_id);
bool IsChannel(u64 title_id);
#pragma pack(push, 4)
struct TMDHeader
{
u32 signature_type;
u8 rsa_2048_signature[256];
u8 fill[60];
u8 issuer[64];
u8 tmd_version;
u8 ca_crl_version;
u8 signer_crl_version;
u64 ios_id;
u64 title_id;
u32 title_type;
u16 group_id;
u16 zero;
u16 region;
u8 ratings[16];
u8 reserved[12];
u8 ipc_mask[12];
u8 reserved2[18];
u32 access_rights;
u16 title_version;
u16 num_contents;
u16 boot_index;
u16 fill2;
};
static_assert(sizeof(TMDHeader) == 0x1e4, "TMDHeader has the wrong size");
struct Content
{
bool IsShared() const;
u32 id;
u16 index;
u16 type;
u64 size;
std::array<u8, 20> sha1;
};
static_assert(sizeof(Content) == 36, "Content has the wrong size");
struct TimeLimit
{
u32 enabled;
u32 seconds;
};
struct TicketView
{
u32 view;
u64 ticket_id;
u32 device_id;
u64 title_id;
u16 access_mask;
u32 permitted_title_id;
u32 permitted_title_mask;
u8 title_export_allowed;
u8 common_key_index;
u8 unknown2[0x30];
u8 content_access_permissions[0x40];
TimeLimit time_limits[8];
};
static_assert(sizeof(TicketView) == 0xd8, "TicketView has the wrong size");
struct Ticket
{
u8 signature_issuer[0x40];
u8 server_public_key[0x3c];
u8 version;
u8 ca_crl_version;
u8 signer_crl_version;
u8 title_key[0x10];
u64 ticket_id;
u32 device_id;
u64 title_id;
u16 access_mask;
u16 ticket_version;
u32 permitted_title_id;
u32 permitted_title_mask;
u8 title_export_allowed;
u8 common_key_index;
u8 unknown2[0x30];
u8 content_access_permissions[0x40];
TimeLimit time_limits[8];
};
static_assert(sizeof(Ticket) == 356, "Ticket has the wrong size");
#pragma pack(pop)
class TMDReader final
{
public:
TMDReader() = default;
explicit TMDReader(const std::vector<u8>& bytes);
explicit TMDReader(std::vector<u8>&& bytes);
void SetBytes(const std::vector<u8>& bytes);
void SetBytes(std::vector<u8>&& bytes);
bool IsValid() const;
// Returns the TMD or parts of it without any kind of parsing. Intended for use by ES.
const std::vector<u8>& GetRawTMD() const;
std::vector<u8> GetRawHeader() const;
std::vector<u8> GetRawView() const;
u16 GetBootIndex() const;
u64 GetIOSId() const;
DiscIO::Region GetRegion() const;
u64 GetTitleId() const;
u16 GetTitleVersion() const;
u16 GetGroupId() const;
// Constructs a 6-character game ID in the format typically used by Dolphin.
// If the 6-character game ID would contain unprintable characters,
// the title ID converted to hexadecimal is returned instead.
std::string GetGameID() const;
u16 GetNumContents() const;
bool GetContent(u16 index, Content* content) const;
std::vector<Content> GetContents() const;
bool FindContentById(u32 id, Content* content) const;
void DoState(PointerWrap& p);
private:
std::vector<u8> m_bytes;
};
class TicketReader final
{
public:
TicketReader() = default;
explicit TicketReader(const std::vector<u8>& bytes);
explicit TicketReader(std::vector<u8>&& bytes);
void SetBytes(const std::vector<u8>& bytes);
void SetBytes(std::vector<u8>&& bytes);
bool IsValid() const;
void DoState(PointerWrap& p);
const std::vector<u8>& GetRawTicket() const;
u32 GetNumberOfTickets() const;
u32 GetOffset() const;
// Returns a "raw" ticket view, without byte swapping. Intended for use from ES.
// Theoretically, a ticket file can contain one or more tickets. In practice, most (all?)
// official titles only have one ticket, but IOS *does* have code to handle ticket files with
// more than just one ticket and generate ticket views for them, so we implement it too.
std::vector<u8> GetRawTicketView(u32 ticket_num) const;
u32 GetDeviceId() const;
u64 GetTitleId() const;
std::vector<u8> GetTitleKey() const;
// Decrypts the title key field for a "personalised" ticket -- one that is device-specific
// and has a title key that must be decrypted first.
s32 Unpersonalise();
private:
std::vector<u8> m_bytes;
};
class SharedContentMap final
{
public:
explicit SharedContentMap(Common::FromWhichRoot root);
~SharedContentMap();
std::string GetFilenameFromSHA1(const std::array<u8, 20>& sha1) const;
std::string AddSharedContent(const std::array<u8, 20>& sha1);
std::vector<std::array<u8, 20>> GetHashes() const;
private:
struct Entry;
Common::FromWhichRoot m_root;
u32 m_last_id = 0;
std::string m_file_path;
std::vector<Entry> m_entries;
};
class UIDSys final
{
public:
explicit UIDSys(Common::FromWhichRoot root);
u32 GetUIDFromTitle(u64 title_id);
void AddTitle(u64 title_id);
u32 GetNextUID() const;
private:
std::string m_file_path;
std::map<u32, u64> m_entries;
};
} // namespace ES
} // namespace IOS