mirror of
https://github.com/hedge-dev/XenonRecomp.git
synced 2025-04-19 10:51:18 +00:00
PowerUtils: implemented XDBF wrapper
This commit is contained in:
parent
7dd4f91ac6
commit
dd85501f11
203
PowerUtils/xdbf.h
Normal file
203
PowerUtils/xdbf.h
Normal file
@ -0,0 +1,203 @@
|
||||
#pragma once
|
||||
|
||||
#include <xbox.h>
|
||||
|
||||
#define XDBF_SIGNATURE 0x58444246
|
||||
#define XACH_SIGNATURE 0x58414348
|
||||
|
||||
struct XDBFHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> EntryTableLength;
|
||||
be<uint32_t> EntryCount;
|
||||
be<uint32_t> FreeSpaceTableLength;
|
||||
be<uint32_t> FreeSpaceTableEntryCount;
|
||||
};
|
||||
|
||||
enum EXDBFNamespace : uint16_t
|
||||
{
|
||||
XDBF_SPA_NAMESPACE_METADATA = 1,
|
||||
XDBF_SPA_NAMESPACE_IMAGE = 2,
|
||||
XDBF_SPA_NAMESPACE_STRING_TABLE = 3,
|
||||
XDBF_GPD_NAMESPACE_ACHIEVEMENT = 1,
|
||||
XDBF_GPD_NAMESPACE_IMAGE = 2,
|
||||
XDBF_GPD_NAMESPACE_SETTING = 3,
|
||||
XDBF_GPD_NAMESPACE_TITLE = 4,
|
||||
XDBF_GPD_NAMESPACE_STRING = 5,
|
||||
XDBF_GPD_NAMESPACE_ACHIEVEMENT_SECURITY_GFWL = 6,
|
||||
XDBF_GPD_NAMESPACE_AVATAR_AWARD_360 = 6
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct XDBFEntry
|
||||
{
|
||||
be<EXDBFNamespace> NamespaceID;
|
||||
be<uint64_t> ResourceID;
|
||||
be<uint32_t> Offset;
|
||||
be<uint32_t> Length;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct XDBFFreeSpaceEntry
|
||||
{
|
||||
be<uint32_t> Offset;
|
||||
be<uint32_t> Length;
|
||||
};
|
||||
|
||||
enum EXDBFLanguage : uint32_t
|
||||
{
|
||||
XDBF_LANGUAGE_UNKNOWN = 0,
|
||||
XDBF_LANGUAGE_ENGLISH = 1,
|
||||
XDBF_LANGUAGE_JAPANESE = 2,
|
||||
XDBF_LANGUAGE_GERMAN = 3,
|
||||
XDBF_LANGUAGE_FRENCH = 4,
|
||||
XDBF_LANGUAGE_SPANISH = 5,
|
||||
XDBF_LANGUAGE_ITALIAN = 6,
|
||||
XDBF_LANGUAGE_KOREAN = 7,
|
||||
XDBF_LANGUAGE_CHINESE_TRAD = 8,
|
||||
XDBF_LANGUAGE_PORTUGUESE = 9,
|
||||
XDBF_LANGUAGE_CHINESE_SIMP = 10,
|
||||
XDBF_LANGUAGE_POLISH = 11,
|
||||
XDBF_LANGUAGE_RUSSIAN = 12,
|
||||
XDBF_LANGUAGE_MAX
|
||||
};
|
||||
|
||||
struct XSTCHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
be<EXDBFLanguage> Language;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct XSTRHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
be<uint16_t> StringCount;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct XSTREntry
|
||||
{
|
||||
be<uint16_t> ID;
|
||||
be<uint16_t> Length;
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct XACHHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
be<uint16_t> AchievementCount;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
enum EXACHFlags : uint32_t
|
||||
{
|
||||
XACH_TYPE_COMPLETION = 1U,
|
||||
XACH_TYPE_LEVELING = 2U,
|
||||
XACH_TYPE_UNLOCK = 3U,
|
||||
XACH_TYPE_EVENT = 4U,
|
||||
XACH_TYPE_TOURNAMENT = 5U,
|
||||
XACH_TYPE_CHECKPOINT = 6U,
|
||||
XACH_TYPE_OTHER = 7U,
|
||||
XACH_TYPE_MASK = 7U,
|
||||
XACH_STATUS_UNACHIEVED = (1U << 4),
|
||||
XACH_STATUS_EARNED_ONLINE = (1U << 16),
|
||||
XACH_STATUS_EARNED = (1U << 17),
|
||||
XACH_STATUS_EDITED = (1U << 20)
|
||||
};
|
||||
|
||||
struct XACHEntry
|
||||
{
|
||||
be<uint16_t> AchievementID;
|
||||
be<uint16_t> NameID;
|
||||
be<uint16_t> UnlockedDescID;
|
||||
be<uint16_t> LockedDescID;
|
||||
be<uint32_t> ImageID;
|
||||
be<uint16_t> Gamerscore;
|
||||
char pad0[0x02];
|
||||
be<EXACHFlags> Flags;
|
||||
char pad1[0x10];
|
||||
};
|
||||
|
||||
union XDBFTitleID
|
||||
{
|
||||
struct
|
||||
{
|
||||
be<uint16_t> u16;
|
||||
char u8[0x02];
|
||||
};
|
||||
|
||||
be<uint32_t> u32;
|
||||
};
|
||||
|
||||
struct XDBFTitleVersion
|
||||
{
|
||||
be<uint16_t> Major;
|
||||
be<uint16_t> Minor;
|
||||
be<uint16_t> Build;
|
||||
be<uint16_t> Revision;
|
||||
};
|
||||
|
||||
enum EXDBFTitleType : uint32_t
|
||||
{
|
||||
XDBF_TITLE_TYPE_SYSTEM = 0,
|
||||
XDBF_TITLE_TYPE_FULL = 1,
|
||||
XDBF_TITLE_TYPE_DEMO = 2,
|
||||
XDBF_TITLE_TYPE_DOWNLOAD = 3
|
||||
};
|
||||
|
||||
struct XTHDHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
XDBFTitleID TitleID;
|
||||
be<EXDBFTitleType> Type;
|
||||
XDBFTitleVersion TitleVersion;
|
||||
char pad0[0x10];
|
||||
};
|
||||
|
||||
#pragma pack(1)
|
||||
struct XGAAHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
be<uint16_t> Count;
|
||||
};
|
||||
#pragma pack()
|
||||
|
||||
struct XGAAEntry
|
||||
{
|
||||
char pad0[0x04];
|
||||
be<uint16_t> AvatarAwardID;
|
||||
char pad1[0x06];
|
||||
XDBFTitleID TitleID;
|
||||
be<uint16_t> NameID;
|
||||
be<uint16_t> UnlockedDescID;
|
||||
be<uint16_t> LockedDescID;
|
||||
char pad2[0x02];
|
||||
be<uint32_t> ImageID;
|
||||
char pad3[0x08];
|
||||
};
|
||||
|
||||
struct XSRCHeader
|
||||
{
|
||||
be<uint32_t> Signature;
|
||||
be<uint32_t> Version;
|
||||
be<uint32_t> Size;
|
||||
be<uint32_t> FileNameLength;
|
||||
};
|
||||
|
||||
struct XSRCHeader2
|
||||
{
|
||||
be<uint32_t> UncompressedSize;
|
||||
be<uint32_t> CompressedSize;
|
||||
};
|
152
PowerUtils/xdbf_wrapper.cpp
Normal file
152
PowerUtils/xdbf_wrapper.cpp
Normal file
@ -0,0 +1,152 @@
|
||||
#include "xdbf_wrapper.h"
|
||||
|
||||
XDBFWrapper::XDBFWrapper(const uint8_t* buffer, size_t bufferSize) : pBuffer(buffer), BufferSize(bufferSize)
|
||||
{
|
||||
if (!buffer || bufferSize <= sizeof(XDBFHeader))
|
||||
{
|
||||
pBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
auto seek = pBuffer;
|
||||
|
||||
pHeader = (XDBFHeader*)seek;
|
||||
seek += sizeof(XDBFHeader);
|
||||
|
||||
if (pHeader->Signature != XDBF_SIGNATURE)
|
||||
{
|
||||
pBuffer = nullptr;
|
||||
return;
|
||||
}
|
||||
|
||||
pEntries = (XDBFEntry*)seek;
|
||||
seek += sizeof(XDBFEntry) * pHeader->EntryCount;
|
||||
|
||||
pFiles = (XDBFFreeSpaceEntry*)seek;
|
||||
seek += sizeof(XDBFFreeSpaceEntry) * pHeader->FreeSpaceTableLength;
|
||||
|
||||
pContent = seek;
|
||||
}
|
||||
|
||||
XDBFBlock XDBFWrapper::GetResource(EXDBFNamespace ns, uint64_t id) const
|
||||
{
|
||||
for (int i = 0; i < pHeader->EntryCount; i++)
|
||||
{
|
||||
auto& entry = pEntries[i];
|
||||
|
||||
if (entry.NamespaceID == ns && entry.ResourceID == id)
|
||||
{
|
||||
XDBFBlock block{};
|
||||
block.pBuffer = pContent + entry.Offset;
|
||||
block.BufferSize = entry.Length;
|
||||
return block;
|
||||
}
|
||||
}
|
||||
|
||||
return { nullptr };
|
||||
}
|
||||
|
||||
std::string XDBFWrapper::GetString(EXDBFLanguage language, uint16_t id) const
|
||||
{
|
||||
auto languageBlock = GetResource(XDBF_SPA_NAMESPACE_STRING_TABLE, (uint64_t)language);
|
||||
|
||||
if (!languageBlock)
|
||||
return "";
|
||||
|
||||
auto pHeader = (XSTRHeader*)languageBlock.pBuffer;
|
||||
auto seek = languageBlock.pBuffer + sizeof(XSTRHeader);
|
||||
|
||||
for (int i = 0; i < pHeader->StringCount; i++)
|
||||
{
|
||||
auto entry = (XSTREntry*)seek;
|
||||
|
||||
seek += sizeof(XSTREntry);
|
||||
|
||||
if (entry->ID == id)
|
||||
return std::string((const char*)seek, entry->Length);
|
||||
|
||||
seek += entry->Length;
|
||||
}
|
||||
|
||||
return "";
|
||||
}
|
||||
|
||||
std::vector<Achievement> XDBFWrapper::GetAchievements(EXDBFLanguage language) const
|
||||
{
|
||||
std::vector<Achievement> result;
|
||||
|
||||
auto achievementsBlock = GetResource(XDBF_SPA_NAMESPACE_METADATA, XACH_SIGNATURE);
|
||||
|
||||
if (!achievementsBlock)
|
||||
return result;
|
||||
|
||||
auto pHeader = (XACHHeader*)achievementsBlock.pBuffer;
|
||||
auto seek = achievementsBlock.pBuffer + sizeof(XACHHeader);
|
||||
|
||||
for (int i = 0; i < pHeader->AchievementCount; i++)
|
||||
{
|
||||
auto entry = (XACHEntry*)seek;
|
||||
|
||||
seek += sizeof(XACHEntry);
|
||||
|
||||
Achievement achievement{};
|
||||
achievement.ID = entry->AchievementID;
|
||||
achievement.Name = GetString(language, entry->NameID);
|
||||
achievement.UnlockedDesc = GetString(language, entry->UnlockedDescID);
|
||||
achievement.LockedDesc = GetString(language, entry->LockedDescID);
|
||||
achievement.Score = entry->Gamerscore;
|
||||
|
||||
auto imageBlock = GetResource(XDBF_SPA_NAMESPACE_IMAGE, entry->ImageID);
|
||||
|
||||
if (imageBlock)
|
||||
{
|
||||
achievement.pImageBuffer = imageBlock.pBuffer;
|
||||
achievement.ImageBufferSize = imageBlock.BufferSize;
|
||||
}
|
||||
|
||||
result.push_back(achievement);
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
Achievement XDBFWrapper::GetAchievement(EXDBFLanguage language, uint16_t id) const
|
||||
{
|
||||
Achievement result{};
|
||||
|
||||
auto achievementsBlock = GetResource(XDBF_SPA_NAMESPACE_METADATA, 0x58414348);
|
||||
|
||||
if (!achievementsBlock)
|
||||
return result;
|
||||
|
||||
auto pHeader = (XACHHeader*)achievementsBlock.pBuffer;
|
||||
auto seek = achievementsBlock.pBuffer + sizeof(XACHHeader);
|
||||
|
||||
for (int i = 0; i < pHeader->AchievementCount; i++)
|
||||
{
|
||||
auto entry = (XACHEntry*)seek;
|
||||
|
||||
seek += sizeof(XACHEntry);
|
||||
|
||||
if (entry->AchievementID == id)
|
||||
{
|
||||
result.ID = entry->AchievementID;
|
||||
result.Name = GetString(language, entry->NameID);
|
||||
result.UnlockedDesc = GetString(language, entry->UnlockedDescID);
|
||||
result.LockedDesc = GetString(language, entry->LockedDescID);
|
||||
result.Score = entry->Gamerscore;
|
||||
|
||||
auto imageBlock = GetResource(XDBF_SPA_NAMESPACE_IMAGE, entry->ImageID);
|
||||
|
||||
if (imageBlock)
|
||||
{
|
||||
result.pImageBuffer = imageBlock.pBuffer;
|
||||
result.ImageBufferSize = imageBlock.BufferSize;
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
47
PowerUtils/xdbf_wrapper.h
Normal file
47
PowerUtils/xdbf_wrapper.h
Normal file
@ -0,0 +1,47 @@
|
||||
#pragma once
|
||||
|
||||
#include "xdbf.h"
|
||||
|
||||
struct Achievement
|
||||
{
|
||||
uint16_t ID;
|
||||
std::string Name;
|
||||
std::string UnlockedDesc;
|
||||
std::string LockedDesc;
|
||||
const uint8_t* pImageBuffer;
|
||||
size_t ImageBufferSize;
|
||||
uint16_t Score;
|
||||
};
|
||||
|
||||
struct XDBFBlock
|
||||
{
|
||||
const uint8_t* pBuffer;
|
||||
size_t BufferSize;
|
||||
|
||||
operator bool() const
|
||||
{
|
||||
return pBuffer;
|
||||
}
|
||||
};
|
||||
|
||||
class XDBFWrapper
|
||||
{
|
||||
public:
|
||||
const uint8_t* pBuffer;
|
||||
size_t BufferSize;
|
||||
|
||||
const uint8_t* pContent;
|
||||
|
||||
const XDBFHeader* pHeader;
|
||||
const XDBFEntry* pEntries;
|
||||
const XDBFFreeSpaceEntry* pFiles;
|
||||
|
||||
XDBFWrapper() {}
|
||||
XDBFWrapper(const uint8_t* pBuffer, size_t bufferSize);
|
||||
XDBFBlock GetResource(EXDBFNamespace ns, uint64_t id) const;
|
||||
std::string GetString(EXDBFLanguage language, uint16_t id) const;
|
||||
std::vector<Achievement> GetAchievements(EXDBFLanguage language) const;
|
||||
Achievement GetAchievement(EXDBFLanguage language, uint16_t id) const;
|
||||
};
|
||||
|
||||
extern XDBFWrapper g_xdbf;
|
@ -54,6 +54,14 @@ typedef struct _XEX_FILE_FORMAT_INFO
|
||||
be<uint16_t> CompressionType;
|
||||
} XEX_FILE_FORMAT_INFO;
|
||||
|
||||
typedef struct _XEX_RESOURCE_INFO
|
||||
{
|
||||
be<uint32_t> SizeOfHeader;
|
||||
uint8_t ResourceID[8];
|
||||
be<uint32_t> Offset;
|
||||
be<uint32_t> SizeOfData;
|
||||
} XEX_RESOURCE_INFO;
|
||||
|
||||
typedef struct _XEX_BASIC_FILE_COMPRESSION_INFO
|
||||
{
|
||||
be<uint32_t> SizeOfData;
|
||||
|
Loading…
x
Reference in New Issue
Block a user