[XEX] - add more file signatures
- Add older xex file signatures - Add xex1 devkit key - Add xex1 support
This commit is contained in:
committed by
Radosław Gliński
parent
8486e97a06
commit
131503f68d
@@ -54,6 +54,9 @@ DECLARE_bool(disable_context_promotion);
|
||||
static constexpr uint8_t xe_xex1_retail_key[16] = {
|
||||
0xA2, 0x6C, 0x10, 0xF7, 0x1F, 0xD9, 0x35, 0xE9,
|
||||
0x8B, 0x99, 0x92, 0x2C, 0xE9, 0x32, 0x15, 0x72};
|
||||
static constexpr uint8_t xe_xex1_devkit_key[16] = {
|
||||
0xA8, 0xB0, 0x05, 0x12, 0xED, 0xE3, 0x63, 0x8D,
|
||||
0xC6, 0x58, 0xB3, 0x10, 0x1F, 0x9F, 0x50, 0xD1};
|
||||
static constexpr uint8_t xe_xex2_retail_key[16] = {
|
||||
0x20, 0xB1, 0x85, 0xA5, 0x9D, 0x28, 0xFD, 0xC3,
|
||||
0x40, 0x58, 0x3F, 0xBB, 0x08, 0x96, 0xBF, 0x91};
|
||||
@@ -884,32 +887,37 @@ int XexModule::ReadPEHeaders() {
|
||||
}
|
||||
|
||||
void XexModule::ReadSecurityInfo() {
|
||||
if (xex_format_ == kFormatXex1) {
|
||||
const xex1_security_info* xex1_sec_info =
|
||||
reinterpret_cast<const xex1_security_info*>(
|
||||
GetSecurityInfo(xex_header()));
|
||||
switch (xex_format_) {
|
||||
case kFormatXex1: {
|
||||
const xex1_security_info* xex1_sec_info =
|
||||
reinterpret_cast<const xex1_security_info*>(
|
||||
GetSecurityInfo(xex_header()));
|
||||
|
||||
security_info_.rsa_signature = xex1_sec_info->rsa_signature;
|
||||
security_info_.aes_key = xex1_sec_info->aes_key;
|
||||
security_info_.image_size = xex1_sec_info->image_size;
|
||||
security_info_.image_flags = xex1_sec_info->image_flags;
|
||||
security_info_.export_table = xex1_sec_info->export_table;
|
||||
security_info_.load_address = xex1_sec_info->load_address;
|
||||
security_info_.page_descriptor_count = xex1_sec_info->page_descriptor_count;
|
||||
security_info_.page_descriptors = xex1_sec_info->page_descriptors;
|
||||
} else if (xex_format_ == kFormatXex2) {
|
||||
const xex2_security_info* xex2_sec_info =
|
||||
reinterpret_cast<const xex2_security_info*>(
|
||||
GetSecurityInfo(xex_header()));
|
||||
security_info_.rsa_signature = xex1_sec_info->rsa_signature;
|
||||
security_info_.aes_key = xex1_sec_info->aes_key;
|
||||
security_info_.image_size = xex1_sec_info->image_size;
|
||||
security_info_.image_flags = xex1_sec_info->image_flags;
|
||||
security_info_.export_table = xex1_sec_info->export_table;
|
||||
security_info_.load_address = xex1_sec_info->load_address;
|
||||
security_info_.page_descriptor_count =
|
||||
xex1_sec_info->page_descriptor_count;
|
||||
security_info_.page_descriptors = xex1_sec_info->page_descriptors;
|
||||
} break;
|
||||
case kFormatXex2: {
|
||||
const xex2_security_info* xex2_sec_info =
|
||||
reinterpret_cast<const xex2_security_info*>(
|
||||
GetSecurityInfo(xex_header()));
|
||||
|
||||
security_info_.rsa_signature = xex2_sec_info->rsa_signature;
|
||||
security_info_.aes_key = xex2_sec_info->aes_key;
|
||||
security_info_.image_size = xex2_sec_info->image_size;
|
||||
security_info_.image_flags = xex2_sec_info->image_flags;
|
||||
security_info_.export_table = xex2_sec_info->export_table;
|
||||
security_info_.load_address = xex2_sec_info->load_address;
|
||||
security_info_.page_descriptor_count = xex2_sec_info->page_descriptor_count;
|
||||
security_info_.page_descriptors = xex2_sec_info->page_descriptors;
|
||||
security_info_.rsa_signature = xex2_sec_info->rsa_signature;
|
||||
security_info_.aes_key = xex2_sec_info->aes_key;
|
||||
security_info_.image_size = xex2_sec_info->image_size;
|
||||
security_info_.image_flags = xex2_sec_info->image_flags;
|
||||
security_info_.export_table = xex2_sec_info->export_table;
|
||||
security_info_.load_address = xex2_sec_info->load_address;
|
||||
security_info_.page_descriptor_count =
|
||||
xex2_sec_info->page_descriptor_count;
|
||||
security_info_.page_descriptors = xex2_sec_info->page_descriptors;
|
||||
} break;
|
||||
}
|
||||
}
|
||||
|
||||
@@ -917,12 +925,32 @@ bool XexModule::Load(const std::string_view name, const std::string_view path,
|
||||
const void* xex_addr, size_t xex_length) {
|
||||
auto src_header = reinterpret_cast<const xex2_header*>(xex_addr);
|
||||
|
||||
if (src_header->magic == kXEX1Signature) {
|
||||
xex_format_ = kFormatXex1;
|
||||
} else if (src_header->magic == kXEX2Signature) {
|
||||
xex_format_ = kFormatXex2;
|
||||
} else {
|
||||
return false;
|
||||
switch (src_header->magic) {
|
||||
case kXEX0Signature:
|
||||
XELOGE("XEX0 format not supported");
|
||||
return false;
|
||||
break;
|
||||
case kXEXQSignature:
|
||||
XELOGE("XEX? format not supported");
|
||||
return false;
|
||||
break;
|
||||
case kXEXHSignature:
|
||||
XELOGE("XEX- format not supported");
|
||||
return false;
|
||||
break;
|
||||
case kXEXPSignature:
|
||||
XELOGE("XEX% format not supported");
|
||||
return false;
|
||||
break;
|
||||
case kXEX1Signature:
|
||||
xex_format_ = kFormatXex1;
|
||||
break;
|
||||
case kXEX2Signature:
|
||||
xex_format_ = kFormatXex2;
|
||||
break;
|
||||
default:
|
||||
XELOGE("XEX format not supported");
|
||||
return false;
|
||||
}
|
||||
|
||||
assert_false(loaded_);
|
||||
@@ -958,13 +986,23 @@ bool XexModule::Load(const std::string_view name, const std::string_view path,
|
||||
|
||||
result_code = ReadImage(xex_addr, xex_length, xe_xex2_devkit_key);
|
||||
if (result_code) {
|
||||
XELOGE("XEX load failed with code {}, trying with xex1 encryption key...",
|
||||
result_code);
|
||||
XELOGE(
|
||||
"XEX load failed with code {}, trying with xex1 retail encryption "
|
||||
"key...",
|
||||
result_code);
|
||||
|
||||
result_code = ReadImage(xex_addr, xex_length, xe_xex1_retail_key);
|
||||
if (result_code) {
|
||||
XELOGE("XEX load failed with code {}", result_code);
|
||||
return false;
|
||||
XELOGE(
|
||||
"XEX load failed with code {}, trying with xex1 devkit encryption "
|
||||
"key...",
|
||||
result_code);
|
||||
|
||||
result_code = ReadImage(xex_addr, xex_length, xe_xex1_devkit_key);
|
||||
if (result_code) {
|
||||
XELOGE("XEX load failed with code {}", result_code);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
@@ -25,9 +25,14 @@ class KernelState;
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
constexpr fourcc_t kXEX0Signature = make_fourcc("XEX0");
|
||||
constexpr fourcc_t kXEXQSignature = make_fourcc("XEX?");
|
||||
constexpr fourcc_t kXEXHSignature = make_fourcc("XEX-");
|
||||
constexpr fourcc_t kXEXPSignature = make_fourcc("XEX%");
|
||||
constexpr fourcc_t kXEX1Signature = make_fourcc("XEX1");
|
||||
constexpr fourcc_t kXEX2Signature = make_fourcc("XEX2");
|
||||
constexpr fourcc_t kElfSignature = make_fourcc(0x7F, 'E', 'L', 'F');
|
||||
constexpr fourcc_t kXBESignature = make_fourcc("XBEH");
|
||||
|
||||
class Runtime;
|
||||
struct InfoCacheFlags {
|
||||
@@ -115,6 +120,10 @@ class XexModule : public xe::cpu::Module {
|
||||
};
|
||||
enum XexFormat {
|
||||
kFormatUnknown,
|
||||
kFormatXex0,
|
||||
kFormatXexQ, // ?
|
||||
kFormatXexH, // -
|
||||
kFormatXexP, // %
|
||||
kFormatXex1,
|
||||
kFormatXex2,
|
||||
};
|
||||
|
||||
@@ -370,6 +370,10 @@ const std::unique_ptr<vfs::Device> Emulator::CreateVfsDevice(
|
||||
const std::filesystem::path& path, const std::string_view mount_path) {
|
||||
// Must check if the type has changed e.g. XamSwapDisc
|
||||
switch (GetFileSignature(path)) {
|
||||
case FileSignatureType::XEX0:
|
||||
case FileSignatureType::XEXQ:
|
||||
case FileSignatureType::XEXH:
|
||||
case FileSignatureType::XEXP:
|
||||
case FileSignatureType::XEX1:
|
||||
case FileSignatureType::XEX2:
|
||||
case FileSignatureType::ELF: {
|
||||
@@ -389,6 +393,7 @@ const std::unique_ptr<vfs::Device> Emulator::CreateVfsDevice(
|
||||
case FileSignatureType::ZAR: {
|
||||
return std::make_unique<vfs::DiscZarchiveDevice>(mount_path, path);
|
||||
} break;
|
||||
case FileSignatureType::XBE:
|
||||
case FileSignatureType::EXE:
|
||||
case FileSignatureType::Unknown:
|
||||
default:
|
||||
@@ -488,6 +493,14 @@ Emulator::FileSignatureType Emulator::GetFileSignature(
|
||||
fclose(file);
|
||||
|
||||
switch (magic_value) {
|
||||
case xe::cpu::kXEX0Signature:
|
||||
return FileSignatureType::XEX0;
|
||||
case xe::cpu::kXEXQSignature:
|
||||
return FileSignatureType::XEXQ;
|
||||
case xe::cpu::kXEXHSignature:
|
||||
return FileSignatureType::XEXH;
|
||||
case xe::cpu::kXEXPSignature:
|
||||
return FileSignatureType::XEXP;
|
||||
case xe::cpu::kXEX1Signature:
|
||||
return FileSignatureType::XEX1;
|
||||
case xe::cpu::kXEX2Signature:
|
||||
@@ -500,6 +513,8 @@ Emulator::FileSignatureType Emulator::GetFileSignature(
|
||||
return FileSignatureType::PIRS;
|
||||
case xe::vfs::kXSFSignature:
|
||||
return FileSignatureType::XISO;
|
||||
case xe::cpu::kXBESignature:
|
||||
return FileSignatureType::XBE;
|
||||
case xe::cpu::kElfSignature:
|
||||
return FileSignatureType::ELF;
|
||||
default:
|
||||
@@ -542,6 +557,10 @@ X_STATUS Emulator::LaunchPath(const std::filesystem::path& path) {
|
||||
X_STATUS mount_result = X_STATUS_SUCCESS;
|
||||
|
||||
switch (GetFileSignature(path)) {
|
||||
case FileSignatureType::XEX0:
|
||||
case FileSignatureType::XEXQ:
|
||||
case FileSignatureType::XEXH:
|
||||
case FileSignatureType::XEXP:
|
||||
case FileSignatureType::XEX1:
|
||||
case FileSignatureType::XEX2:
|
||||
case FileSignatureType::ELF: {
|
||||
@@ -558,6 +577,10 @@ X_STATUS Emulator::LaunchPath(const std::filesystem::path& path) {
|
||||
mount_result = MountPath(path, "\\Device\\Cdrom0");
|
||||
return mount_result ? mount_result : LaunchDiscImage(path);
|
||||
} break;
|
||||
case FileSignatureType::XBE: {
|
||||
XELOGE("OG Xbox games are not supported");
|
||||
return X_STATUS_NOT_SUPPORTED;
|
||||
} break;
|
||||
case FileSignatureType::ZAR: {
|
||||
mount_result = MountPath(path, "\\Device\\Cdrom0");
|
||||
return mount_result ? mount_result : LaunchDiscArchive(path);
|
||||
|
||||
@@ -201,6 +201,10 @@ class Emulator {
|
||||
const std::string_view mount_path);
|
||||
|
||||
enum class FileSignatureType {
|
||||
XEX0,
|
||||
XEXQ,
|
||||
XEXH,
|
||||
XEXP,
|
||||
XEX1,
|
||||
XEX2,
|
||||
ELF,
|
||||
@@ -208,6 +212,7 @@ class Emulator {
|
||||
LIVE,
|
||||
PIRS,
|
||||
XISO,
|
||||
XBE,
|
||||
ZAR,
|
||||
EXE,
|
||||
Unknown
|
||||
|
||||
@@ -132,7 +132,9 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||
|
||||
be<fourcc_t> magic;
|
||||
magic.value = xe::load<fourcc_t>(addr);
|
||||
if (magic == xe::cpu::kXEX2Signature || magic == xe::cpu::kXEX1Signature) {
|
||||
if (magic == xe::cpu::kXEX2Signature || magic == xe::cpu::kXEX1Signature ||
|
||||
magic == xe::cpu::kXEXQSignature || magic == xe::cpu::kXEXHSignature ||
|
||||
magic == xe::cpu::kXEXPSignature || magic == xe::cpu::kXEX0Signature) {
|
||||
module_format_ = kModuleFormatXex;
|
||||
} else if (magic == xe::cpu::kElfSignature) {
|
||||
module_format_ = kModuleFormatElf;
|
||||
@@ -146,6 +148,8 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
|
||||
XELOGE("XNA executables are not yet implemented");
|
||||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
} else {
|
||||
// restore it back
|
||||
magic.value = xe::load<fourcc_t>(addr);
|
||||
XELOGE("Unknown module magic: {:08X}", magic.get());
|
||||
return X_STATUS_NOT_IMPLEMENTED;
|
||||
}
|
||||
|
||||
@@ -794,7 +794,7 @@ struct xex2_security_info {
|
||||
xe::be<uint32_t> header_size; // 0x0
|
||||
xe::be<uint32_t> image_size; // 0x4
|
||||
char rsa_signature[0x100]; // 0x8
|
||||
xe::be<uint32_t> unk_108; // 0x108 unk length
|
||||
xe::be<uint32_t> info_size; // 0x108
|
||||
xe::be<xex2_image_flags> image_flags; // 0x10C
|
||||
xe::be<uint32_t> load_address; // 0x110
|
||||
char section_digest[0x14]; // 0x114
|
||||
|
||||
Reference in New Issue
Block a user