Skip to content

Commit dd85501

Browse files
committed
PowerUtils: implemented XDBF wrapper
1 parent 7dd4f91 commit dd85501

4 files changed

Lines changed: 410 additions & 0 deletions

File tree

PowerUtils/xdbf.h

Lines changed: 203 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,203 @@
1+
#pragma once
2+
3+
#include <xbox.h>
4+
5+
#define XDBF_SIGNATURE 0x58444246
6+
#define XACH_SIGNATURE 0x58414348
7+
8+
struct XDBFHeader
9+
{
10+
be<uint32_t> Signature;
11+
be<uint32_t> Version;
12+
be<uint32_t> EntryTableLength;
13+
be<uint32_t> EntryCount;
14+
be<uint32_t> FreeSpaceTableLength;
15+
be<uint32_t> FreeSpaceTableEntryCount;
16+
};
17+
18+
enum EXDBFNamespace : uint16_t
19+
{
20+
XDBF_SPA_NAMESPACE_METADATA = 1,
21+
XDBF_SPA_NAMESPACE_IMAGE = 2,
22+
XDBF_SPA_NAMESPACE_STRING_TABLE = 3,
23+
XDBF_GPD_NAMESPACE_ACHIEVEMENT = 1,
24+
XDBF_GPD_NAMESPACE_IMAGE = 2,
25+
XDBF_GPD_NAMESPACE_SETTING = 3,
26+
XDBF_GPD_NAMESPACE_TITLE = 4,
27+
XDBF_GPD_NAMESPACE_STRING = 5,
28+
XDBF_GPD_NAMESPACE_ACHIEVEMENT_SECURITY_GFWL = 6,
29+
XDBF_GPD_NAMESPACE_AVATAR_AWARD_360 = 6
30+
};
31+
32+
#pragma pack(1)
33+
struct XDBFEntry
34+
{
35+
be<EXDBFNamespace> NamespaceID;
36+
be<uint64_t> ResourceID;
37+
be<uint32_t> Offset;
38+
be<uint32_t> Length;
39+
};
40+
#pragma pack()
41+
42+
struct XDBFFreeSpaceEntry
43+
{
44+
be<uint32_t> Offset;
45+
be<uint32_t> Length;
46+
};
47+
48+
enum EXDBFLanguage : uint32_t
49+
{
50+
XDBF_LANGUAGE_UNKNOWN = 0,
51+
XDBF_LANGUAGE_ENGLISH = 1,
52+
XDBF_LANGUAGE_JAPANESE = 2,
53+
XDBF_LANGUAGE_GERMAN = 3,
54+
XDBF_LANGUAGE_FRENCH = 4,
55+
XDBF_LANGUAGE_SPANISH = 5,
56+
XDBF_LANGUAGE_ITALIAN = 6,
57+
XDBF_LANGUAGE_KOREAN = 7,
58+
XDBF_LANGUAGE_CHINESE_TRAD = 8,
59+
XDBF_LANGUAGE_PORTUGUESE = 9,
60+
XDBF_LANGUAGE_CHINESE_SIMP = 10,
61+
XDBF_LANGUAGE_POLISH = 11,
62+
XDBF_LANGUAGE_RUSSIAN = 12,
63+
XDBF_LANGUAGE_MAX
64+
};
65+
66+
struct XSTCHeader
67+
{
68+
be<uint32_t> Signature;
69+
be<uint32_t> Version;
70+
be<uint32_t> Size;
71+
be<EXDBFLanguage> Language;
72+
};
73+
74+
#pragma pack(1)
75+
struct XSTRHeader
76+
{
77+
be<uint32_t> Signature;
78+
be<uint32_t> Version;
79+
be<uint32_t> Size;
80+
be<uint16_t> StringCount;
81+
};
82+
#pragma pack()
83+
84+
struct XSTREntry
85+
{
86+
be<uint16_t> ID;
87+
be<uint16_t> Length;
88+
};
89+
90+
#pragma pack(1)
91+
struct XACHHeader
92+
{
93+
be<uint32_t> Signature;
94+
be<uint32_t> Version;
95+
be<uint32_t> Size;
96+
be<uint16_t> AchievementCount;
97+
};
98+
#pragma pack()
99+
100+
enum EXACHFlags : uint32_t
101+
{
102+
XACH_TYPE_COMPLETION = 1U,
103+
XACH_TYPE_LEVELING = 2U,
104+
XACH_TYPE_UNLOCK = 3U,
105+
XACH_TYPE_EVENT = 4U,
106+
XACH_TYPE_TOURNAMENT = 5U,
107+
XACH_TYPE_CHECKPOINT = 6U,
108+
XACH_TYPE_OTHER = 7U,
109+
XACH_TYPE_MASK = 7U,
110+
XACH_STATUS_UNACHIEVED = (1U << 4),
111+
XACH_STATUS_EARNED_ONLINE = (1U << 16),
112+
XACH_STATUS_EARNED = (1U << 17),
113+
XACH_STATUS_EDITED = (1U << 20)
114+
};
115+
116+
struct XACHEntry
117+
{
118+
be<uint16_t> AchievementID;
119+
be<uint16_t> NameID;
120+
be<uint16_t> UnlockedDescID;
121+
be<uint16_t> LockedDescID;
122+
be<uint32_t> ImageID;
123+
be<uint16_t> Gamerscore;
124+
char pad0[0x02];
125+
be<EXACHFlags> Flags;
126+
char pad1[0x10];
127+
};
128+
129+
union XDBFTitleID
130+
{
131+
struct
132+
{
133+
be<uint16_t> u16;
134+
char u8[0x02];
135+
};
136+
137+
be<uint32_t> u32;
138+
};
139+
140+
struct XDBFTitleVersion
141+
{
142+
be<uint16_t> Major;
143+
be<uint16_t> Minor;
144+
be<uint16_t> Build;
145+
be<uint16_t> Revision;
146+
};
147+
148+
enum EXDBFTitleType : uint32_t
149+
{
150+
XDBF_TITLE_TYPE_SYSTEM = 0,
151+
XDBF_TITLE_TYPE_FULL = 1,
152+
XDBF_TITLE_TYPE_DEMO = 2,
153+
XDBF_TITLE_TYPE_DOWNLOAD = 3
154+
};
155+
156+
struct XTHDHeader
157+
{
158+
be<uint32_t> Signature;
159+
be<uint32_t> Version;
160+
be<uint32_t> Size;
161+
XDBFTitleID TitleID;
162+
be<EXDBFTitleType> Type;
163+
XDBFTitleVersion TitleVersion;
164+
char pad0[0x10];
165+
};
166+
167+
#pragma pack(1)
168+
struct XGAAHeader
169+
{
170+
be<uint32_t> Signature;
171+
be<uint32_t> Version;
172+
be<uint32_t> Size;
173+
be<uint16_t> Count;
174+
};
175+
#pragma pack()
176+
177+
struct XGAAEntry
178+
{
179+
char pad0[0x04];
180+
be<uint16_t> AvatarAwardID;
181+
char pad1[0x06];
182+
XDBFTitleID TitleID;
183+
be<uint16_t> NameID;
184+
be<uint16_t> UnlockedDescID;
185+
be<uint16_t> LockedDescID;
186+
char pad2[0x02];
187+
be<uint32_t> ImageID;
188+
char pad3[0x08];
189+
};
190+
191+
struct XSRCHeader
192+
{
193+
be<uint32_t> Signature;
194+
be<uint32_t> Version;
195+
be<uint32_t> Size;
196+
be<uint32_t> FileNameLength;
197+
};
198+
199+
struct XSRCHeader2
200+
{
201+
be<uint32_t> UncompressedSize;
202+
be<uint32_t> CompressedSize;
203+
};

PowerUtils/xdbf_wrapper.cpp

Lines changed: 152 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,152 @@
1+
#include "xdbf_wrapper.h"
2+
3+
XDBFWrapper::XDBFWrapper(const uint8_t* buffer, size_t bufferSize) : pBuffer(buffer), BufferSize(bufferSize)
4+
{
5+
if (!buffer || bufferSize <= sizeof(XDBFHeader))
6+
{
7+
pBuffer = nullptr;
8+
return;
9+
}
10+
11+
auto seek = pBuffer;
12+
13+
pHeader = (XDBFHeader*)seek;
14+
seek += sizeof(XDBFHeader);
15+
16+
if (pHeader->Signature != XDBF_SIGNATURE)
17+
{
18+
pBuffer = nullptr;
19+
return;
20+
}
21+
22+
pEntries = (XDBFEntry*)seek;
23+
seek += sizeof(XDBFEntry) * pHeader->EntryCount;
24+
25+
pFiles = (XDBFFreeSpaceEntry*)seek;
26+
seek += sizeof(XDBFFreeSpaceEntry) * pHeader->FreeSpaceTableLength;
27+
28+
pContent = seek;
29+
}
30+
31+
XDBFBlock XDBFWrapper::GetResource(EXDBFNamespace ns, uint64_t id) const
32+
{
33+
for (int i = 0; i < pHeader->EntryCount; i++)
34+
{
35+
auto& entry = pEntries[i];
36+
37+
if (entry.NamespaceID == ns && entry.ResourceID == id)
38+
{
39+
XDBFBlock block{};
40+
block.pBuffer = pContent + entry.Offset;
41+
block.BufferSize = entry.Length;
42+
return block;
43+
}
44+
}
45+
46+
return { nullptr };
47+
}
48+
49+
std::string XDBFWrapper::GetString(EXDBFLanguage language, uint16_t id) const
50+
{
51+
auto languageBlock = GetResource(XDBF_SPA_NAMESPACE_STRING_TABLE, (uint64_t)language);
52+
53+
if (!languageBlock)
54+
return "";
55+
56+
auto pHeader = (XSTRHeader*)languageBlock.pBuffer;
57+
auto seek = languageBlock.pBuffer + sizeof(XSTRHeader);
58+
59+
for (int i = 0; i < pHeader->StringCount; i++)
60+
{
61+
auto entry = (XSTREntry*)seek;
62+
63+
seek += sizeof(XSTREntry);
64+
65+
if (entry->ID == id)
66+
return std::string((const char*)seek, entry->Length);
67+
68+
seek += entry->Length;
69+
}
70+
71+
return "";
72+
}
73+
74+
std::vector<Achievement> XDBFWrapper::GetAchievements(EXDBFLanguage language) const
75+
{
76+
std::vector<Achievement> result;
77+
78+
auto achievementsBlock = GetResource(XDBF_SPA_NAMESPACE_METADATA, XACH_SIGNATURE);
79+
80+
if (!achievementsBlock)
81+
return result;
82+
83+
auto pHeader = (XACHHeader*)achievementsBlock.pBuffer;
84+
auto seek = achievementsBlock.pBuffer + sizeof(XACHHeader);
85+
86+
for (int i = 0; i < pHeader->AchievementCount; i++)
87+
{
88+
auto entry = (XACHEntry*)seek;
89+
90+
seek += sizeof(XACHEntry);
91+
92+
Achievement achievement{};
93+
achievement.ID = entry->AchievementID;
94+
achievement.Name = GetString(language, entry->NameID);
95+
achievement.UnlockedDesc = GetString(language, entry->UnlockedDescID);
96+
achievement.LockedDesc = GetString(language, entry->LockedDescID);
97+
achievement.Score = entry->Gamerscore;
98+
99+
auto imageBlock = GetResource(XDBF_SPA_NAMESPACE_IMAGE, entry->ImageID);
100+
101+
if (imageBlock)
102+
{
103+
achievement.pImageBuffer = imageBlock.pBuffer;
104+
achievement.ImageBufferSize = imageBlock.BufferSize;
105+
}
106+
107+
result.push_back(achievement);
108+
}
109+
110+
return result;
111+
}
112+
113+
Achievement XDBFWrapper::GetAchievement(EXDBFLanguage language, uint16_t id) const
114+
{
115+
Achievement result{};
116+
117+
auto achievementsBlock = GetResource(XDBF_SPA_NAMESPACE_METADATA, 0x58414348);
118+
119+
if (!achievementsBlock)
120+
return result;
121+
122+
auto pHeader = (XACHHeader*)achievementsBlock.pBuffer;
123+
auto seek = achievementsBlock.pBuffer + sizeof(XACHHeader);
124+
125+
for (int i = 0; i < pHeader->AchievementCount; i++)
126+
{
127+
auto entry = (XACHEntry*)seek;
128+
129+
seek += sizeof(XACHEntry);
130+
131+
if (entry->AchievementID == id)
132+
{
133+
result.ID = entry->AchievementID;
134+
result.Name = GetString(language, entry->NameID);
135+
result.UnlockedDesc = GetString(language, entry->UnlockedDescID);
136+
result.LockedDesc = GetString(language, entry->LockedDescID);
137+
result.Score = entry->Gamerscore;
138+
139+
auto imageBlock = GetResource(XDBF_SPA_NAMESPACE_IMAGE, entry->ImageID);
140+
141+
if (imageBlock)
142+
{
143+
result.pImageBuffer = imageBlock.pBuffer;
144+
result.ImageBufferSize = imageBlock.BufferSize;
145+
}
146+
147+
return result;
148+
}
149+
}
150+
151+
return result;
152+
}

0 commit comments

Comments
 (0)