Merge ad34f78243ff213c8fd557f327ce232dffa760d5 into dc4460eefd95deb26e86247342ab6a5d9cb8d2d5

This commit is contained in:
Caroline Joy Bell 2025-03-04 07:58:37 -08:00 committed by GitHub
commit af111f8b89
No known key found for this signature in database
GPG Key ID: B5690EEEBB952194
4 changed files with 51 additions and 15 deletions

View File

@ -160,7 +160,7 @@ Property|Description
restgprlr_14_address|Start address of the `__restgprlr_14` function. It starts with `ld r14, -0x98(r1)`, repeating the same operation for the rest of the non-volatile registers and restoring the link register at the end.
savegprlr_14_address|Start address of the `__savegprlr_14` function. It starts with `std r14, -0x98(r1)`, repeating the same operation for the rest of the non-volatile registers and saving the link register at the end.
restfpr_14_address|Start address of the `__restfpr_14` function. It starts with `lfd f14, -0x90(r12)`, repeating the same operation for the rest of the non-volatile FPU registers.
savefpr_14_address|Start address of the `__savefpr_14` function. It starts with `stfd r14, -0x90(r12)`, repeating the same operation for the rest of the non-volatile FPU registers.
savefpr_14_address|Start address of the `__savefpr_14` function. It starts with `stfd f14, -0x90(r12)`, repeating the same operation for the rest of the non-volatile FPU registers.
restvmx_14_address|Start address of the `__restvmx_14` function. It starts with `li r11, -0x120` and `lvx v14, r11, r12`, repeating the same operation for the rest of the non-volatile VMX registers until `v31`.
savevmx_14_address|Start address of the `__savevmx_14` function. It starts with `li r11, -0x120` and `stvx v14, r11, r12`, repeating the same operation for the rest of the non-volatile VMX registers until `v31`.
restvmx_64_address|Start address of the `__restvmx_64` function. It starts with `li r11, -0x400` and `lvx128 v64, r11, r12`, repeating the same operation for the rest of the non-volatile VMX registers.

View File

@ -2,24 +2,31 @@
#include <cassert>
template<typename T>
inline T ByteSwap(T value)
#ifdef __clang__
#define _byte_swap16(value) __builtin_bswap16(static_cast<uint16_t>(value))
#define _byte_swap32(value) __builtin_bswap32(static_cast<uint32_t>(value))
#define _byte_swap64(value) __builtin_bswap64(static_cast<uint64_t>(value))
#elif defined(_MSC_VER)
#define _byte_swap16(value) _byteswap_ushort(static_cast<uint16_t>(value))
#define _byte_swap32(value) _byteswap_ulong(static_cast<uint32_t>(value))
#define _byte_swap64(value) _byteswap_uint64(static_cast<uint64_t>(value))
#endif
template<typename T> T ByteSwap(T value)
{
if constexpr (sizeof(T) == 1)
return value;
else if constexpr (sizeof(T) == 2)
return static_cast<T>(__builtin_bswap16(static_cast<uint16_t>(value)));
else if constexpr (sizeof(T) == 4)
return static_cast<T>(__builtin_bswap32(static_cast<uint32_t>(value)));
else if constexpr (sizeof(T) == 8)
return static_cast<T>(__builtin_bswap64(static_cast<uint64_t>(value)));
if constexpr (sizeof(T) == 2)
return static_cast<T>(_byte_swap16(value));
if constexpr (sizeof(T) == 4)
return static_cast<T>(_byte_swap32(value));
if constexpr (sizeof(T) == 8)
return static_cast<T>(_byte_swap64(value));
assert(false && "Unexpected byte size.");
return value;
}
template<typename T>
inline void ByteSwapInplace(T& value)
template<typename T> void ByteSwapInplace(T& value)
{
value = ByteSwap(value);
}

View File

@ -126,7 +126,8 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize)
{
auto* header = reinterpret_cast<const Xex2Header*>(data);
auto* security = reinterpret_cast<const Xex2SecurityInfo*>(data + header->securityOffset);
const auto* fileFormatInfo = reinterpret_cast<const Xex2OptFileFormatInfo*>(getOptHeaderPtr(data, XEX_HEADER_FILE_FORMAT_INFO));
const auto* fileFormatInfo = static_cast<const Xex2OptFileFormatInfo*>(getOptHeaderPtr(data, XEX_HEADER_FILE_FORMAT_INFO));
const auto* execInfo = static_cast<const Xex2OptExecutionInfo*>(getOptHeaderPtr(data, XEX_HEADER_EXECUTION_INFO));
Image image{};
std::unique_ptr<uint8_t[]> result{};
@ -147,7 +148,11 @@ Image Xex2LoadImage(const uint8_t* data, size_t dataSize)
uint8_t decryptedKey[KeySize];
memcpy(decryptedKey, security->aesKey, KeySize);
AES_init_ctx_iv(&aesContext, Xex2RetailKey, AESBlankIV);
if (!execInfo || !execInfo->titleId) {
AES_init_ctx_iv(&aesContext, Xex2DevkitKey, AESBlankIV);
} else {
AES_init_ctx_iv(&aesContext, Xex2RetailKey, AESBlankIV);
}
AES_CBC_decrypt_buffer(&aesContext, decryptedKey, KeySize);
decryptedData = std::make_unique<uint8_t[]>(dataSize - header->headerSize);

View File

@ -3,6 +3,7 @@
#include "xbox.h"
inline constexpr uint8_t Xex2RetailKey[16] = { 0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3, 0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91 };
inline constexpr uint8_t Xex2DevkitKey[16] = { 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00 };
inline constexpr uint8_t AESBlankIV[16] = {};
enum Xex2ModuleFlags
@ -186,6 +187,19 @@ struct Xex2OptFileFormatInfo
be<uint16_t> compressionType;
};
struct Xex2OptExecutionInfo
{
be<uint32_t> mediaId;
be<uint32_t> version;
be<uint32_t> versionBase;
be<uint32_t> titleId;
uint8_t platform;
uint8_t executableTable;
uint8_t discNumber;
uint8_t discTotal;
be<uint32_t> savedGameId;
};
struct Xex2ImportHeader
{
be<uint32_t> sizeOfHeader;
@ -204,10 +218,20 @@ struct Xex2ImportLibrary
be<uint16_t> numberOfImports;
};
// https://github.com/emoose/idaxex/blob/198b1d52414d35926644bbeec607b3feac5f44e7/formats/pe_structs.hpp#L140-L150
struct Xex2ImportDescriptor
{
be<uint32_t> firstThunk; // VA XEX_THUNK_DATA
union
{
be<uint32_t> characteristics;
be<uint32_t> originalFirstThunk;
};
be<uint32_t> timeDateStamp;
be<uint32_t> forwarderChainId;
be<uint32_t> moduleName;
be<uint32_t> firstThunk;
};
static_assert(sizeof(Xex2ImportDescriptor) == 0x14, "Xex2ImportDescriptor");
struct Xex2ThunkData
{