Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
2 changes: 1 addition & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -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.
Expand Down
29 changes: 18 additions & 11 deletions XenonUtils/byteswap.h
Original file line number Diff line number Diff line change
Expand Up @@ -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);
}
9 changes: 7 additions & 2 deletions XenonUtils/xex.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -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{};
Expand All @@ -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);
Expand Down
26 changes: 25 additions & 1 deletion XenonUtils/xex.h
Original file line number Diff line number Diff line change
Expand Up @@ -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
Expand Down Expand Up @@ -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;
Expand All @@ -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
{
Expand Down