Merge branch 'xexp'

This commit is contained in:
Dr. Chat 2018-10-28 12:20:02 -05:00
commit c95ba803a8
13 changed files with 1394 additions and 1598 deletions

View File

@ -69,6 +69,8 @@ template <typename T>
inline T byte_swap(T value) {
if (sizeof(T) == 4) {
return static_cast<T>(byte_swap(static_cast<uint32_t>(value)));
} else if (sizeof(T) == 2) {
return static_cast<T>(byte_swap(static_cast<uint16_t>(value)));
} else {
assert_always("not handled");
}

File diff suppressed because it is too large Load Diff

View File

@ -14,7 +14,6 @@
#include <vector>
#include "xenia/cpu/module.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/util/xex2_info.h"
namespace xe {
@ -30,10 +29,24 @@ class Runtime;
class XexModule : public xe::cpu::Module {
public:
struct ImportLibraryFn {
public:
uint32_t ordinal;
uint32_t value_address;
uint32_t thunk_address;
};
struct ImportLibrary {
public:
std::string name;
uint32_t id;
xe_xex2_version_t version;
xe_xex2_version_t min_version;
std::vector<ImportLibraryFn> imports;
};
XexModule(Processor* processor, kernel::KernelState* kernel_state);
virtual ~XexModule();
xe_xex2_ref xex() const { return xex_; }
bool loaded() const { return loaded_; }
const xex2_header* xex_header() const {
return reinterpret_cast<const xex2_header*>(xex_header_mem_.data());
@ -42,49 +55,113 @@ class XexModule : public xe::cpu::Module {
return GetSecurityInfo(xex_header());
}
uint32_t image_size() const {
assert_not_zero(base_address_);
// Calculate the new total size of the XEX image from its headers.
auto heap = memory()->LookupHeap(base_address_);
uint32_t total_size = 0;
for (uint32_t i = 0; i < xex_security_info()->page_descriptor_count; i++) {
// Byteswap the bitfield manually.
xex2_page_descriptor desc;
desc.value =
xe::byte_swap(xex_security_info()->page_descriptors[i].value);
total_size += desc.size * heap->page_size();
}
return total_size;
}
const std::vector<ImportLibrary>* import_libraries() const {
return &import_libs_;
}
const xex2_opt_execution_info* opt_execution_info() const {
xex2_opt_execution_info* retval = nullptr;
GetOptHeader(XEX_HEADER_EXECUTION_INFO, &retval);
return retval;
}
const xex2_opt_file_format_info* opt_file_format_info() const {
xex2_opt_file_format_info* retval = nullptr;
GetOptHeader(XEX_HEADER_FILE_FORMAT_INFO, &retval);
return retval;
}
const uint32_t base_address() const { return base_address_; }
const bool is_dev_kit() const { return is_dev_kit_; }
// Gets an optional header. Returns NULL if not found.
// Special case: if key & 0xFF == 0x00, this function will return the value,
// not a pointer! This assumes out_ptr points to uint32_t.
static bool GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
static bool GetOptHeader(const xex2_header* header, xex2_header_keys key,
void** out_ptr);
bool GetOptHeader(xe_xex2_header_keys key, void** out_ptr) const;
bool GetOptHeader(xex2_header_keys key, void** out_ptr) const;
// Ultra-cool templated version
// Special case: if key & 0xFF == 0x00, this function will return the value,
// not a pointer! This assumes out_ptr points to uint32_t.
template <typename T>
static bool GetOptHeader(const xex2_header* header, xe_xex2_header_keys key,
static bool GetOptHeader(const xex2_header* header, xex2_header_keys key,
T* out_ptr) {
return GetOptHeader(header, key, reinterpret_cast<void**>(out_ptr));
}
template <typename T>
bool GetOptHeader(xe_xex2_header_keys key, T* out_ptr) const {
bool GetOptHeader(xex2_header_keys key, T* out_ptr) const {
return GetOptHeader(key, reinterpret_cast<void**>(out_ptr));
}
static const xex2_security_info* GetSecurityInfo(const xex2_header* header);
const PESection* GetPESection(const char* name);
uint32_t GetProcAddress(uint16_t ordinal) const;
uint32_t GetProcAddress(const char* name) const;
bool ApplyPatch(XexModule* module);
int ApplyPatch(XexModule* module);
bool Load(const std::string& name, const std::string& path,
const void* xex_addr, size_t xex_length);
bool Load(const std::string& name, const std::string& path, xe_xex2_ref xex);
bool LoadContinue();
bool Unload();
bool ContainsAddress(uint32_t address) override;
const std::string& name() const override { return name_; }
bool is_executable() const override {
return (xex_header()->module_flags & XEX_MODULE_TITLE) != 0;
}
bool ContainsAddress(uint32_t address) override;
bool is_valid_executable() const {
assert_not_zero(base_address_);
if (!base_address_) {
return false;
}
uint8_t* buffer = memory()->TranslateVirtual(base_address_);
return *(uint32_t*)buffer == 0x905A4D;
}
bool is_patch() const {
assert_not_null(xex_header());
if (!xex_header()) {
return false;
}
return (xex_header()->module_flags &
(XEX_MODULE_MODULE_PATCH | XEX_MODULE_PATCH_DELTA |
XEX_MODULE_PATCH_FULL));
}
protected:
std::unique_ptr<Function> CreateFunction(uint32_t address) override;
private:
int ReadImage(const void* xex_addr, size_t xex_length, bool use_dev_key);
int ReadImageUncompressed(const void* xex_addr, size_t xex_length);
int ReadImageBasicCompressed(const void* xex_addr, size_t xex_length);
int ReadImageCompressed(const void* xex_addr, size_t xex_length);
int ReadPEHeaders();
bool SetupLibraryImports(const char* name,
const xex2_import_library* library);
bool FindSaveRest();
@ -93,9 +170,18 @@ class XexModule : public xe::cpu::Module {
kernel::KernelState* kernel_state_ = nullptr;
std::string name_;
std::string path_;
xe_xex2_ref xex_ = nullptr;
std::vector<uint8_t> xex_header_mem_; // Holds the xex header
bool loaded_ = false; // Loaded into memory?
std::vector<uint8_t> xexp_data_mem_; // Holds XEXP patch data
std::vector<ImportLibrary>
import_libs_; // pre-loaded import libraries for ease of use
std::vector<PESection> pe_sections_;
uint8_t session_key_[0x10];
bool is_dev_kit_ = false;
bool loaded_ = false; // Loaded into memory?
bool finished_load_ = false; // PE/imports/symbols/etc all loaded?
uint32_t base_address_ = 0;
uint32_t low_address_ = 0;

View File

@ -95,7 +95,36 @@ X_STATUS UserModule::LoadFromFile(std::string path) {
file->Destroy();
}
return result;
// Only XEX returns X_STATUS_PENDING
if (result != X_STATUS_PENDING) {
return result;
}
// Search for xexp patch file
auto patch_entry = kernel_state()->file_system()->ResolvePath(path_ + "p");
if (patch_entry) {
auto patch_path = patch_entry->absolute_path();
XELOGI("Loading XEX patch from %s", patch_path.c_str());
auto patch_module = object_ref<UserModule>(new UserModule(kernel_state_));
result = patch_module->LoadFromFile(patch_path);
if (!result) {
result = patch_module->xex_module()->ApplyPatch(xex_module());
if (result) {
XELOGE("Failed to apply XEX patch, code: %d", result);
}
} else {
XELOGE("Failed to load XEX patch, code: %d", result);
}
if (result) {
return X_STATUS_UNSUCCESSFUL;
}
}
return LoadXexContinue();
}
X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
@ -130,35 +159,13 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
return X_STATUS_UNSUCCESSFUL;
}
// Copy the xex2 header into guest memory.
auto header = this->xex_module()->xex_header();
auto security_header = this->xex_module()->xex_security_info();
guest_xex_header_ = memory()->SystemHeapAlloc(header->header_size);
// Only XEX headers + image are loaded right now
// Caller will have to call LoadXexContinue after they've loaded in a patch
// (or after patch isn't found anywhere)
// or if this is an XEXP being loaded return success since there's nothing
// else to load
return this->xex_module()->is_patch() ? X_STATUS_SUCCESS : X_STATUS_PENDING;
uint8_t* xex_header_ptr = memory()->TranslateVirtual(guest_xex_header_);
std::memcpy(xex_header_ptr, header, header->header_size);
// Setup the loader data entry
auto ldr_data =
memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(hmodule_ptr_);
ldr_data->dll_base = 0; // GetProcAddress will read this.
ldr_data->xex_header_base = guest_xex_header_;
ldr_data->full_image_size = security_header->image_size;
this->xex_module()->GetOptHeader(XEX_HEADER_ENTRY_POINT,
&ldr_data->entry_point);
xe::be<uint32_t>* image_base_ptr = nullptr;
if (this->xex_module()->GetOptHeader(XEX_HEADER_IMAGE_BASE_ADDRESS,
&image_base_ptr)) {
ldr_data->image_base = *image_base_ptr;
}
// Cache some commonly used headers...
this->xex_module()->GetOptHeader(XEX_HEADER_ENTRY_POINT, &entry_point_);
this->xex_module()->GetOptHeader(XEX_HEADER_DEFAULT_STACK_SIZE,
&stack_size_);
is_dll_module_ = !!(header->module_flags & XEX_MODULE_DLL_MODULE);
} else if (module_format_ == kModuleFormatElf) {
auto elf_module =
std::make_unique<cpu::ElfModule>(processor, kernel_state());
@ -181,6 +188,52 @@ X_STATUS UserModule::LoadFromMemory(const void* addr, const size_t length) {
return X_STATUS_SUCCESS;
}
X_STATUS UserModule::LoadXexContinue() {
// LoadXexContinue: finishes loading XEX after a patch has been applied (or
// patch wasn't found)
if (!this->xex_module()) {
return X_STATUS_UNSUCCESSFUL;
}
// If guest_xex_header is set we must have already loaded the XEX
if (guest_xex_header_) {
return X_STATUS_SUCCESS;
}
// Finish XexModule load (PE sections/imports/symbols...)
if (!xex_module()->LoadContinue()) {
return X_STATUS_UNSUCCESSFUL;
}
// Copy the xex2 header into guest memory.
auto header = this->xex_module()->xex_header();
auto security_header = this->xex_module()->xex_security_info();
guest_xex_header_ = memory()->SystemHeapAlloc(header->header_size);
uint8_t* xex_header_ptr = memory()->TranslateVirtual(guest_xex_header_);
std::memcpy(xex_header_ptr, header, header->header_size);
// Cache some commonly used headers...
this->xex_module()->GetOptHeader(XEX_HEADER_ENTRY_POINT, &entry_point_);
this->xex_module()->GetOptHeader(XEX_HEADER_DEFAULT_STACK_SIZE, &stack_size_);
is_dll_module_ = !!(header->module_flags & XEX_MODULE_DLL_MODULE);
// Setup the loader data entry
auto ldr_data =
memory()->TranslateVirtual<X_LDR_DATA_TABLE_ENTRY*>(hmodule_ptr_);
ldr_data->dll_base = 0; // GetProcAddress will read this.
ldr_data->xex_header_base = guest_xex_header_;
ldr_data->full_image_size = security_header->image_size;
ldr_data->image_base = this->xex_module()->base_address();
ldr_data->entry_point = entry_point_;
OnLoad();
return X_STATUS_SUCCESS;
}
X_STATUS UserModule::Unload() {
if (module_format_ == kModuleFormatXex &&
(!processor_module_ || !xex_module()->loaded())) {
@ -229,7 +282,7 @@ X_STATUS UserModule::GetSection(const char* name, uint32_t* out_section_data,
return X_STATUS_NOT_FOUND;
}
X_STATUS UserModule::GetOptHeader(xe_xex2_header_keys key, void** out_ptr) {
X_STATUS UserModule::GetOptHeader(xex2_header_keys key, void** out_ptr) {
assert_not_null(out_ptr);
if (module_format_ == kModuleFormatElf) {
@ -245,7 +298,7 @@ X_STATUS UserModule::GetOptHeader(xe_xex2_header_keys key, void** out_ptr) {
return X_STATUS_SUCCESS;
}
X_STATUS UserModule::GetOptHeader(xe_xex2_header_keys key,
X_STATUS UserModule::GetOptHeader(xex2_header_keys key,
uint32_t* out_header_guest_ptr) {
if (module_format_ == kModuleFormatElf) {
// Quick die.
@ -262,7 +315,7 @@ X_STATUS UserModule::GetOptHeader(xe_xex2_header_keys key,
}
X_STATUS UserModule::GetOptHeader(uint8_t* membase, const xex2_header* header,
xe_xex2_header_keys key,
xex2_header_keys key,
uint32_t* out_header_guest_ptr) {
assert_not_null(out_header_guest_ptr);
uint32_t field_value = 0;
@ -575,7 +628,7 @@ void UserModule::Dump() {
auto dir =
reinterpret_cast<const xex2_opt_data_directory*>(opt_header_ptr);
auto exe_address = xex_module()->xex_security_info()->load_address;
auto exe_address = xex_module()->base_address();
auto e = memory()->TranslateVirtual<const X_IMAGE_EXPORT_DIRECTORY*>(
exe_address + dir->offset);
auto e_base = reinterpret_cast<uintptr_t>(e);
@ -624,8 +677,8 @@ void UserModule::Dump() {
}
const uint32_t page_size =
security_info->load_address < 0x90000000 ? 64 * 1024 : 4 * 1024;
uint32_t start_address = security_info->load_address + (page * page_size);
xex_module()->base_address() < 0x90000000 ? 64 * 1024 : 4 * 1024;
uint32_t start_address = xex_module()->base_address() + (page * page_size);
uint32_t end_address = start_address + (page_descriptor.size * page_size);
sb.AppendFormat(" %3u %s %3u pages %.8X - %.8X (%d bytes)\n", page,
@ -635,18 +688,16 @@ void UserModule::Dump() {
}
// Print out imports.
// TODO(benvanik): figure out a way to remove dependency on old xex header.
auto old_header = xe_xex2_get_header(xex_module()->xex());
auto import_libs = xex_module()->import_libraries();
sb.AppendFormat("Imports:\n");
for (size_t n = 0; n < old_header->import_library_count; n++) {
const xe_xex2_import_library_t* library = &old_header->import_libraries[n];
xe_xex2_import_info_t* import_infos;
size_t import_info_count;
if (!xe_xex2_get_import_infos(xex_module()->xex(), library, &import_infos,
&import_info_count)) {
sb.AppendFormat(" %s - %lld imports\n", library->name, import_info_count);
for (std::vector<cpu::XexModule::ImportLibrary>::const_iterator library =
import_libs->begin();
library != import_libs->end(); ++library) {
if (library->imports.size() > 0) {
sb.AppendFormat(" %s - %lld imports\n", library->name.c_str(),
library->imports.size());
sb.AppendFormat(" Version: %d.%d.%d.%d\n", library->version.major,
library->version.minor, library->version.build,
library->version.qfe);
@ -660,12 +711,13 @@ void UserModule::Dump() {
int unknown_count = 0;
int impl_count = 0;
int unimpl_count = 0;
for (size_t m = 0; m < import_info_count; m++) {
const xe_xex2_import_info_t* info = &import_infos[m];
if (kernel_state_->IsKernelModule(library->name)) {
auto kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
for (std::vector<cpu::XexModule::ImportLibraryFn>::const_iterator info =
library->imports.begin();
info != library->imports.end(); ++info) {
if (kernel_state_->IsKernelModule(library->name.c_str())) {
auto kernel_export = export_resolver->GetExportByOrdinal(
library->name.c_str(), info->ordinal);
if (kernel_export) {
known_count++;
if (kernel_export->is_implemented()) {
@ -678,7 +730,7 @@ void UserModule::Dump() {
unimpl_count++;
}
} else {
auto module = kernel_state_->GetModule(library->name);
auto module = kernel_state_->GetModule(library->name.c_str());
if (module) {
uint32_t export_addr =
module->GetProcAddressByOrdinal(info->ordinal);
@ -695,8 +747,8 @@ void UserModule::Dump() {
}
}
}
float total_count = static_cast<float>(import_info_count) / 100.0f;
sb.AppendFormat(" Total: %4llu\n", import_info_count);
float total_count = static_cast<float>(library->imports.size()) / 100.0f;
sb.AppendFormat(" Total: %4llu\n", library->imports.size());
sb.AppendFormat(" Known: %3d%% (%d known, %d unknown)\n",
static_cast<int>(known_count / total_count), known_count,
unknown_count);
@ -706,21 +758,22 @@ void UserModule::Dump() {
sb.AppendFormat("\n");
// Listing.
for (size_t m = 0; m < import_info_count; m++) {
const xe_xex2_import_info_t* info = &import_infos[m];
for (std::vector<cpu::XexModule::ImportLibraryFn>::const_iterator info =
library->imports.begin();
info != library->imports.end(); ++info) {
const char* name = "UNKNOWN";
bool implemented = false;
cpu::Export* kernel_export = nullptr;
if (kernel_state_->IsKernelModule(library->name)) {
kernel_export =
export_resolver->GetExportByOrdinal(library->name, info->ordinal);
if (kernel_state_->IsKernelModule(library->name.c_str())) {
kernel_export = export_resolver->GetExportByOrdinal(
library->name.c_str(), info->ordinal);
if (kernel_export) {
name = kernel_export->name;
implemented = kernel_export->is_implemented();
}
} else {
auto module = kernel_state_->GetModule(library->name);
auto module = kernel_state_->GetModule(library->name.c_str());
if (module && module->GetProcAddressByOrdinal(info->ordinal)) {
// TODO(benvanik): name lookup.
implemented = true;
@ -733,9 +786,8 @@ void UserModule::Dump() {
implemented ? " " : "!!", name);
} else if (info->thunk_address) {
sb.AppendFormat(" F %.8X %.8X %.3X (%3d) %s %s\n",
info->value_address, info->thunk_address,
info->ordinal, info->ordinal,
implemented ? " " : "!!", name);
info->value_address, info->thunk_address, info->ordinal,
info->ordinal, implemented ? " " : "!!", name);
}
}
}

View File

@ -71,19 +71,18 @@ class UserModule : public XModule {
uint32_t* out_section_size) override;
// Get optional header - FOR HOST USE ONLY!
X_STATUS GetOptHeader(xe_xex2_header_keys key, void** out_ptr);
X_STATUS GetOptHeader(xex2_header_keys key, void** out_ptr);
// Get optional header - FOR HOST USE ONLY!
template <typename T>
X_STATUS GetOptHeader(xe_xex2_header_keys key, T* out_ptr) {
X_STATUS GetOptHeader(xex2_header_keys key, T* out_ptr) {
return GetOptHeader(key, reinterpret_cast<void**>(out_ptr));
}
// Get optional header that can safely be returned to guest code.
X_STATUS GetOptHeader(xe_xex2_header_keys key,
uint32_t* out_header_guest_ptr);
X_STATUS GetOptHeader(xex2_header_keys key, uint32_t* out_header_guest_ptr);
static X_STATUS GetOptHeader(uint8_t* membase, const xex2_header* header,
xe_xex2_header_keys key,
xex2_header_keys key,
uint32_t* out_header_guest_ptr);
void Dump();
@ -93,6 +92,8 @@ class UserModule : public XModule {
ByteStream* stream, std::string path);
private:
X_STATUS LoadXexContinue();
uint32_t guest_xex_header_ = 0;
ModuleFormat module_format_ = kModuleFormatUndefined;

File diff suppressed because it is too large Load Diff

View File

@ -1,72 +0,0 @@
/**
******************************************************************************
* Xenia : Xbox 360 Emulator Research Project *
******************************************************************************
* Copyright 2013 Ben Vanik. All rights reserved. *
* Released under the BSD license - see LICENSE in the root for more details. *
******************************************************************************
*/
#ifndef XENIA_KERNEL_UTIL_XEX2_H_
#define XENIA_KERNEL_UTIL_XEX2_H_
#include "xenia/kernel/util/xex2_info.h"
#include "xenia/memory.h"
namespace xe {} // namespace xe
typedef struct {
int reserved;
} xe_xex2_options_t;
struct xe_xex2;
typedef struct xe_xex2* xe_xex2_ref;
typedef struct {
uint32_t ordinal;
uint32_t value_address; // address to place value
uint32_t thunk_address; // NULL or address of thunk
} xe_xex2_import_info_t;
enum xe_pe_section_flags_e : uint32_t {
kXEPESectionContainsCode = 0x00000020,
kXEPESectionContainsDataInit = 0x00000040,
kXEPESectionContainsDataUninit = 0x00000080,
kXEPESectionMemoryExecute = 0x20000000,
kXEPESectionMemoryRead = 0x40000000,
kXEPESectionMemoryWrite = 0x80000000,
};
class PESection {
public:
char name[9]; // 8 + 1 for \0
uint32_t raw_address;
uint32_t raw_size;
uint32_t address;
uint32_t size;
uint32_t flags; // kXEPESection*
};
struct PEExport {
const char* name;
uint32_t ordinal;
uint64_t addr; // Function address
};
xe_xex2_ref xe_xex2_load(xe::Memory* memory, const void* addr,
const size_t length, xe_xex2_options_t options);
void xe_xex2_dealloc(xe_xex2_ref xex);
const xe_xex2_header_t* xe_xex2_get_header(xe_xex2_ref xex);
const PESection* xe_xex2_get_pe_section(xe_xex2_ref xex, const char* name);
int xe_xex2_get_import_infos(xe_xex2_ref xex,
const xe_xex2_import_library_t* library,
xe_xex2_import_info_t** out_import_infos,
size_t* out_import_info_count);
uint32_t xe_xex2_lookup_export(xe_xex2_ref xex, const char* name);
uint32_t xe_xex2_lookup_export(xe_xex2_ref xex, uint16_t ordinal);
#endif // XENIA_KERNEL_UTIL_XEX2_H_

View File

@ -14,40 +14,103 @@
#include "xenia/base/byte_order.h"
enum xe_xex2_header_keys : uint32_t {
XEX_HEADER_RESOURCE_INFO = 0x000002FF,
XEX_HEADER_FILE_FORMAT_INFO = 0x000003FF,
XEX_HEADER_DELTA_PATCH_DESCRIPTOR = 0x000005FF,
XEX_HEADER_BASE_REFERENCE = 0x00000405,
XEX_HEADER_BOUNDING_PATH = 0x000080FF,
XEX_HEADER_DEVICE_ID = 0x00008105,
XEX_HEADER_ORIGINAL_BASE_ADDRESS = 0x00010001,
XEX_HEADER_ENTRY_POINT = 0x00010100,
XEX_HEADER_IMAGE_BASE_ADDRESS = 0x00010201,
XEX_HEADER_IMPORT_LIBRARIES = 0x000103FF,
XEX_HEADER_CHECKSUM_TIMESTAMP = 0x00018002,
XEX_HEADER_ENABLED_FOR_CALLCAP = 0x00018102,
XEX_HEADER_ENABLED_FOR_FASTCAP = 0x00018200,
XEX_HEADER_ORIGINAL_PE_NAME = 0x000183FF,
XEX_HEADER_STATIC_LIBRARIES = 0x000200FF,
XEX_HEADER_TLS_INFO = 0x00020104,
XEX_HEADER_DEFAULT_STACK_SIZE = 0x00020200,
XEX_HEADER_DEFAULT_FILESYSTEM_CACHE_SIZE = 0x00020301,
XEX_HEADER_DEFAULT_HEAP_SIZE = 0x00020401,
XEX_HEADER_PAGE_HEAP_SIZE_AND_FLAGS = 0x00028002,
XEX_HEADER_SYSTEM_FLAGS = 0x00030000,
XEX_HEADER_EXECUTION_INFO = 0x00040006,
XEX_HEADER_TITLE_WORKSPACE_SIZE = 0x00040201,
XEX_HEADER_GAME_RATINGS = 0x00040310,
XEX_HEADER_LAN_KEY = 0x00040404,
XEX_HEADER_XBOX360_LOGO = 0x000405FF,
XEX_HEADER_MULTIDISC_MEDIA_IDS = 0x000406FF,
XEX_HEADER_ALTERNATE_TITLE_IDS = 0x000407FF,
XEX_HEADER_ADDITIONAL_TITLE_MEMORY = 0x00040801,
XEX_HEADER_EXPORTS_BY_NAME = 0x00E10402,
union xe_xex2_version_t {
uint32_t value;
struct {
uint32_t major : 4;
uint32_t minor : 4;
uint32_t build : 16;
uint32_t qfe : 8;
};
};
enum xe_xex2_module_flags : uint32_t {
enum xe_pe_section_flags_e : uint32_t {
kXEPESectionContainsCode = 0x00000020,
kXEPESectionContainsDataInit = 0x00000040,
kXEPESectionContainsDataUninit = 0x00000080,
kXEPESectionMemoryExecute = 0x20000000,
kXEPESectionMemoryRead = 0x40000000,
kXEPESectionMemoryWrite = 0x80000000,
};
class PESection {
public:
char name[9]; // 8 + 1 for \0
uint32_t raw_address;
uint32_t raw_size;
uint32_t address;
uint32_t size;
uint32_t flags; // kXEPESection*
};
struct PEExport {
const char* name;
uint32_t ordinal;
uint64_t addr; // Function address
};
namespace xe {
enum xex2_section_type {
XEX_SECTION_CODE = 1,
XEX_SECTION_DATA = 2,
XEX_SECTION_READONLY_DATA = 3,
};
enum xex2_image_flags : uint32_t {
XEX_IMAGE_MANUFACTURING_UTILITY = 0x00000002,
XEX_IMAGE_MANUFACTURING_SUPPORT_TOOLS = 0x00000004,
XEX_IMAGE_XGD2_MEDIA_ONLY = 0x00000008,
XEX_IMAGE_CARDEA_KEY = 0x00000100,
XEX_IMAGE_XEIKA_KEY = 0x00000200,
XEX_IMAGE_USERMODE_TITLE = 0x00000400,
XEX_IMAGE_USERMODE_SYSTEM = 0x00000800,
XEX_IMAGE_ORANGE0 = 0x00001000,
XEX_IMAGE_ORANGE1 = 0x00002000,
XEX_IMAGE_ORANGE2 = 0x00004000,
XEX_IMAGE_IPTV_SIGNUP_APPLICATION = 0x00010000,
XEX_IMAGE_IPTV_TITLE_APPLICATION = 0x00020000,
XEX_IMAGE_KEYVAULT_PRIVILEGES_REQUIRED = 0x04000000,
XEX_IMAGE_ONLINE_ACTIVATION_REQUIRED = 0x08000000,
XEX_IMAGE_PAGE_SIZE_4KB = 0x10000000, // else 64KB
XEX_IMAGE_REGION_FREE = 0x20000000,
XEX_IMAGE_REVOCATION_CHECK_OPTIONAL = 0x40000000,
XEX_IMAGE_REVOCATION_CHECK_REQUIRED = 0x80000000,
};
enum xex2_media_flags : uint32_t {
XEX_MEDIA_HARDDISK = 0x00000001,
XEX_MEDIA_DVD_X2 = 0x00000002,
XEX_MEDIA_DVD_CD = 0x00000004,
XEX_MEDIA_DVD_5 = 0x00000008,
XEX_MEDIA_DVD_9 = 0x00000010,
XEX_MEDIA_SYSTEM_FLASH = 0x00000020,
XEX_MEDIA_MEMORY_UNIT = 0x00000080,
XEX_MEDIA_USB_MASS_STORAGE_DEVICE = 0x00000100,
XEX_MEDIA_NETWORK = 0x00000200,
XEX_MEDIA_DIRECT_FROM_MEMORY = 0x00000400,
XEX_MEDIA_RAM_DRIVE = 0x00000800,
XEX_MEDIA_SVOD = 0x00001000,
XEX_MEDIA_INSECURE_PACKAGE = 0x01000000,
XEX_MEDIA_SAVEGAME_PACKAGE = 0x02000000,
XEX_MEDIA_LOCALLY_SIGNED_PACKAGE = 0x04000000,
XEX_MEDIA_LIVE_SIGNED_PACKAGE = 0x08000000,
XEX_MEDIA_XBOX_PACKAGE = 0x10000000,
};
enum xex2_region_flags : uint32_t {
XEX_REGION_NTSCU = 0x000000FF,
XEX_REGION_NTSCJ = 0x0000FF00,
XEX_REGION_NTSCJ_JAPAN = 0x00000100,
XEX_REGION_NTSCJ_CHINA = 0x00000200,
XEX_REGION_PAL = 0x00FF0000,
XEX_REGION_PAL_AU_NZ = 0x00010000,
XEX_REGION_OTHER = 0xFF000000,
XEX_REGION_ALL = 0xFFFFFFFF,
};
enum xex2_module_flags : uint32_t {
XEX_MODULE_TITLE = 0x00000001,
XEX_MODULE_EXPORTS_TO_TITLE = 0x00000002,
XEX_MODULE_SYSTEM_DEBUGGER = 0x00000004,
@ -58,7 +121,7 @@ enum xe_xex2_module_flags : uint32_t {
XEX_MODULE_USER_MODE = 0x00000080,
};
enum xe_xex2_system_flags : uint32_t {
enum xex2_system_flags : uint32_t {
XEX_SYSTEM_NO_FORCED_REBOOT = 0x00000001,
XEX_SYSTEM_FOREGROUND_TASKS = 0x00000002,
XEX_SYSTEM_NO_ODD_MAPPING = 0x00000004,
@ -102,7 +165,7 @@ enum xe_xex2_system_flags : uint32_t {
};
// ESRB (Entertainment Software Rating Board)
enum xe_xex2_rating_esrb_value : uint32_t {
enum xex2_rating_esrb_value : uint32_t {
XEX_RATING_ESRB_eC = 0x00,
XEX_RATING_ESRB_E = 0x02,
XEX_RATING_ESRB_E10 = 0x04,
@ -112,7 +175,7 @@ enum xe_xex2_rating_esrb_value : uint32_t {
XEX_RATING_ESRB_UNRATED = 0xFF,
};
// PEGI (Pan European Game Information)
enum xe_xex2_rating_pegi_value : uint32_t {
enum xex2_rating_pegi_value : uint32_t {
XEX_RATING_PEGI_3_PLUS = 0,
XEX_RATING_PEGI_7_PLUS = 4,
XEX_RATING_PEGI_12_PLUS = 9,
@ -121,7 +184,7 @@ enum xe_xex2_rating_pegi_value : uint32_t {
XEX_RATING_PEGI_UNRATED = 0xFF,
};
// PEGI (Pan European Game Information) - Finland
enum xe_xex2_rating_pegi_fi_value : uint32_t {
enum xex2_rating_pegi_fi_value : uint32_t {
XEX_RATING_PEGI_FI_3_PLUS = 0,
XEX_RATING_PEGI_FI_7_PLUS = 4,
XEX_RATING_PEGI_FI_11_PLUS = 8,
@ -130,7 +193,7 @@ enum xe_xex2_rating_pegi_fi_value : uint32_t {
XEX_RATING_PEGI_FI_UNRATED = 0xFF,
};
// PEGI (Pan European Game Information) - Portugal
enum xe_xex2_rating_pegi_pt_value : uint32_t {
enum xex2_rating_pegi_pt_value : uint32_t {
XEX_RATING_PEGI_PT_4_PLUS = 1,
XEX_RATING_PEGI_PT_6_PLUS = 3,
XEX_RATING_PEGI_PT_12_PLUS = 9,
@ -139,7 +202,7 @@ enum xe_xex2_rating_pegi_pt_value : uint32_t {
XEX_RATING_PEGI_PT_UNRATED = 0xFF,
};
// BBFC (British Board of Film Classification) - UK/Ireland
enum xe_xex2_rating_bbfc_value : uint32_t {
enum xex2_rating_bbfc_value : uint32_t {
XEX_RATING_BBFC_UNIVERSAL = 1,
XEX_RATING_BBFC_PG = 5,
XEX_RATING_BBFC_3_PLUS = 0,
@ -151,7 +214,7 @@ enum xe_xex2_rating_bbfc_value : uint32_t {
XEX_RATING_BBFC_UNRATED = 0xFF,
};
// CERO (Computer Entertainment Rating Organization)
enum xe_xex2_rating_cero_value : uint32_t {
enum xex2_rating_cero_value : uint32_t {
XEX_RATING_CERO_A = 0,
XEX_RATING_CERO_B = 2,
XEX_RATING_CERO_C = 4,
@ -160,7 +223,7 @@ enum xe_xex2_rating_cero_value : uint32_t {
XEX_RATING_CERO_UNRATED = 0xFF,
};
// USK (Unterhaltungssoftware SelbstKontrolle)
enum xe_xex2_rating_usk_value : uint32_t {
enum xex2_rating_usk_value : uint32_t {
XEX_RATING_USK_ALL = 0,
XEX_RATING_USK_6_PLUS = 2,
XEX_RATING_USK_12_PLUS = 4,
@ -169,7 +232,7 @@ enum xe_xex2_rating_usk_value : uint32_t {
XEX_RATING_USK_UNRATED = 0xFF,
};
// OFLC (Office of Film and Literature Classification) - Australia
enum xe_xex2_rating_oflc_au_value : uint32_t {
enum xex2_rating_oflc_au_value : uint32_t {
XEX_RATING_OFLC_AU_G = 0,
XEX_RATING_OFLC_AU_PG = 2,
XEX_RATING_OFLC_AU_M = 4,
@ -177,7 +240,7 @@ enum xe_xex2_rating_oflc_au_value : uint32_t {
XEX_RATING_OFLC_AU_UNRATED = 0xFF,
};
// OFLC (Office of Film and Literature Classification) - New Zealand
enum xe_xex2_rating_oflc_nz_value : uint32_t {
enum xex2_rating_oflc_nz_value : uint32_t {
XEX_RATING_OFLC_NZ_G = 0,
XEX_RATING_OFLC_NZ_PG = 2,
XEX_RATING_OFLC_NZ_M = 4,
@ -185,7 +248,7 @@ enum xe_xex2_rating_oflc_nz_value : uint32_t {
XEX_RATING_OFLC_NZ_UNRATED = 0xFF,
};
// KMRB (Korea Media Rating Board)
enum xe_xex2_rating_kmrb_value : uint32_t {
enum xex2_rating_kmrb_value : uint32_t {
XEX_RATING_KMRB_ALL = 0,
XEX_RATING_KMRB_12_PLUS = 2,
XEX_RATING_KMRB_15_PLUS = 4,
@ -193,7 +256,7 @@ enum xe_xex2_rating_kmrb_value : uint32_t {
XEX_RATING_KMRB_UNRATED = 0xFF,
};
// Brazil
enum xe_xex2_rating_brazil_value : uint32_t {
enum xex2_rating_brazil_value : uint32_t {
XEX_RATING_BRAZIL_ALL = 0,
XEX_RATING_BRAZIL_12_PLUS = 2,
XEX_RATING_BRAZIL_14_PLUS = 4,
@ -202,7 +265,7 @@ enum xe_xex2_rating_brazil_value : uint32_t {
XEX_RATING_BRAZIL_UNRATED = 0xFF,
};
// FPB (Film and Publication Board)
enum xe_xex2_rating_fpb_value : uint32_t {
enum xex2_rating_fpb_value : uint32_t {
XEX_RATING_FPB_ALL = 0,
XEX_RATING_FPB_PG = 6,
XEX_RATING_FPB_10_PLUS = 7,
@ -212,252 +275,102 @@ enum xe_xex2_rating_fpb_value : uint32_t {
XEX_RATING_FPB_UNRATED = 0xFF,
};
struct xe_xex2_game_ratings_t {
xe_xex2_rating_esrb_value esrb;
xe_xex2_rating_pegi_value pegi;
xe_xex2_rating_pegi_fi_value pegifi;
xe_xex2_rating_pegi_pt_value pegipt;
xe_xex2_rating_bbfc_value bbfc;
xe_xex2_rating_cero_value cero;
xe_xex2_rating_usk_value usk;
xe_xex2_rating_oflc_au_value oflcau;
xe_xex2_rating_oflc_nz_value oflcnz;
xe_xex2_rating_kmrb_value kmrb;
xe_xex2_rating_brazil_value brazil;
xe_xex2_rating_fpb_value fpb;
enum xex2_header_keys : uint32_t {
XEX_HEADER_RESOURCE_INFO = 0x000002FF,
XEX_HEADER_FILE_FORMAT_INFO = 0x000003FF,
XEX_HEADER_DELTA_PATCH_DESCRIPTOR = 0x000005FF,
XEX_HEADER_BASE_REFERENCE = 0x00000405,
XEX_HEADER_BOUNDING_PATH = 0x000080FF,
XEX_HEADER_DEVICE_ID = 0x00008105,
XEX_HEADER_ORIGINAL_BASE_ADDRESS = 0x00010001,
XEX_HEADER_ENTRY_POINT = 0x00010100,
XEX_HEADER_IMAGE_BASE_ADDRESS = 0x00010201,
XEX_HEADER_IMPORT_LIBRARIES = 0x000103FF,
XEX_HEADER_CHECKSUM_TIMESTAMP = 0x00018002,
XEX_HEADER_ENABLED_FOR_CALLCAP = 0x00018102,
XEX_HEADER_ENABLED_FOR_FASTCAP = 0x00018200,
XEX_HEADER_ORIGINAL_PE_NAME = 0x000183FF,
XEX_HEADER_STATIC_LIBRARIES = 0x000200FF,
XEX_HEADER_TLS_INFO = 0x00020104,
XEX_HEADER_DEFAULT_STACK_SIZE = 0x00020200,
XEX_HEADER_DEFAULT_FILESYSTEM_CACHE_SIZE = 0x00020301,
XEX_HEADER_DEFAULT_HEAP_SIZE = 0x00020401,
XEX_HEADER_PAGE_HEAP_SIZE_AND_FLAGS = 0x00028002,
XEX_HEADER_SYSTEM_FLAGS = 0x00030000,
XEX_HEADER_EXECUTION_INFO = 0x00040006,
XEX_HEADER_TITLE_WORKSPACE_SIZE = 0x00040201,
XEX_HEADER_GAME_RATINGS = 0x00040310,
XEX_HEADER_LAN_KEY = 0x00040404,
XEX_HEADER_XBOX360_LOGO = 0x000405FF,
XEX_HEADER_MULTIDISC_MEDIA_IDS = 0x000406FF,
XEX_HEADER_ALTERNATE_TITLE_IDS = 0x000407FF,
XEX_HEADER_ADDITIONAL_TITLE_MEMORY = 0x00040801,
XEX_HEADER_EXPORTS_BY_NAME = 0x00E10402,
};
union xe_xex2_version_t {
uint32_t value;
struct {
uint32_t major : 4;
uint32_t minor : 4;
uint32_t build : 16;
uint32_t qfe : 8;
};
};
struct xe_xex2_opt_header_t {
uint32_t key;
uint32_t length;
union {
uint32_t value;
uint32_t offset;
};
};
struct xe_xex2_resource_info_t {
char name[9];
uint32_t address;
uint32_t size;
};
struct xe_xex2_execution_info_t {
uint32_t media_id;
xe_xex2_version_t version;
xe_xex2_version_t base_version;
uint32_t title_id;
uint8_t platform;
uint8_t executable_table;
uint8_t disc_number;
uint8_t disc_count;
uint32_t savegame_id;
};
struct xe_xex2_tls_info_t {
uint32_t slot_count;
uint32_t raw_data_address;
uint32_t data_size;
uint32_t raw_data_size;
};
struct xe_xex2_import_library_t {
char name[32];
uint8_t digest[20];
uint32_t import_id;
xe_xex2_version_t version;
xe_xex2_version_t min_version;
size_t record_count;
uint32_t* records;
};
enum xe_xex2_approval_type : uint32_t {
XEX_APPROVAL_UNAPPROVED = 0,
XEX_APPROVAL_POSSIBLE = 1,
XEX_APPROVAL_APPROVED = 2,
XEX_APPROVAL_EXPIRED = 3,
};
struct xe_xex2_static_library_t {
char name[9]; // 8 + 1 for \0
uint16_t major;
uint16_t minor;
uint16_t build;
uint16_t qfe;
xe_xex2_approval_type approval;
};
enum xe_xex2_encryption_type : uint32_t {
enum xex2_encryption_type : uint16_t {
XEX_ENCRYPTION_NONE = 0,
XEX_ENCRYPTION_NORMAL = 1,
};
enum xe_xex2_compression_type : uint32_t {
enum xex2_compression_type : uint16_t {
XEX_COMPRESSION_NONE = 0,
XEX_COMPRESSION_BASIC = 1,
XEX_COMPRESSION_NORMAL = 2,
XEX_COMPRESSION_DELTA = 3,
};
struct xe_xex2_file_basic_compression_block_t {
uint32_t data_size;
uint32_t zero_size;
enum xex2_approval_type : uint32_t {
XEX_APPROVAL_UNAPPROVED = 0,
XEX_APPROVAL_POSSIBLE = 1,
XEX_APPROVAL_APPROVED = 2,
XEX_APPROVAL_EXPIRED = 3,
};
struct xe_xex2_file_basic_compression_info_t {
uint32_t block_count;
xe_xex2_file_basic_compression_block_t* blocks;
struct xex2_game_ratings_t {
xe::be<xex2_rating_esrb_value> esrb;
xe::be<xex2_rating_pegi_value> pegi;
xe::be<xex2_rating_pegi_fi_value> pegifi;
xe::be<xex2_rating_pegi_pt_value> pegipt;
xe::be<xex2_rating_bbfc_value> bbfc;
xe::be<xex2_rating_cero_value> cero;
xe::be<xex2_rating_usk_value> usk;
xe::be<xex2_rating_oflc_au_value> oflcau;
xe::be<xex2_rating_oflc_nz_value> oflcnz;
xe::be<xex2_rating_kmrb_value> kmrb;
xe::be<xex2_rating_brazil_value> brazil;
xe::be<xex2_rating_fpb_value> fpb;
};
struct xe_xex2_file_normal_compression_info_t {
uint32_t window_size;
uint32_t window_bits;
uint32_t block_size;
struct xex2_file_basic_compression_block {
xe::be<uint32_t> data_size;
xe::be<uint32_t> zero_size;
};
struct xex2_file_basic_compression_info {
xex2_file_basic_compression_block blocks[1];
};
struct xex2_compressed_block_info {
xe::be<uint32_t> block_size;
uint8_t block_hash[20];
};
struct xe_xex2_file_format_info_t {
xe_xex2_encryption_type encryption_type;
xe_xex2_compression_type compression_type;
struct xex2_file_normal_compression_info {
xe::be<uint32_t> window_size;
xex2_compressed_block_info first_block;
};
struct xex2_opt_file_format_info {
xe::be<uint32_t> info_size;
xe::be<xex2_encryption_type> encryption_type;
xe::be<xex2_compression_type> compression_type;
union {
xe_xex2_file_basic_compression_info_t basic;
xe_xex2_file_normal_compression_info_t normal;
xex2_file_basic_compression_info basic;
xex2_file_normal_compression_info normal;
} compression_info;
};
enum xe_xex2_image_flags : uint32_t {
XEX_IMAGE_MANUFACTURING_UTILITY = 0x00000002,
XEX_IMAGE_MANUFACTURING_SUPPORT_TOOLS = 0x00000004,
XEX_IMAGE_XGD2_MEDIA_ONLY = 0x00000008,
XEX_IMAGE_CARDEA_KEY = 0x00000100,
XEX_IMAGE_XEIKA_KEY = 0x00000200,
XEX_IMAGE_USERMODE_TITLE = 0x00000400,
XEX_IMAGE_USERMODE_SYSTEM = 0x00000800,
XEX_IMAGE_ORANGE0 = 0x00001000,
XEX_IMAGE_ORANGE1 = 0x00002000,
XEX_IMAGE_ORANGE2 = 0x00004000,
XEX_IMAGE_IPTV_SIGNUP_APPLICATION = 0x00010000,
XEX_IMAGE_IPTV_TITLE_APPLICATION = 0x00020000,
XEX_IMAGE_KEYVAULT_PRIVILEGES_REQUIRED = 0x04000000,
XEX_IMAGE_ONLINE_ACTIVATION_REQUIRED = 0x08000000,
XEX_IMAGE_PAGE_SIZE_4KB = 0x10000000, // else 64KB
XEX_IMAGE_REGION_FREE = 0x20000000,
XEX_IMAGE_REVOCATION_CHECK_OPTIONAL = 0x40000000,
XEX_IMAGE_REVOCATION_CHECK_REQUIRED = 0x80000000,
};
enum xe_xex2_media_flags : uint32_t {
XEX_MEDIA_HARDDISK = 0x00000001,
XEX_MEDIA_DVD_X2 = 0x00000002,
XEX_MEDIA_DVD_CD = 0x00000004,
XEX_MEDIA_DVD_5 = 0x00000008,
XEX_MEDIA_DVD_9 = 0x00000010,
XEX_MEDIA_SYSTEM_FLASH = 0x00000020,
XEX_MEDIA_MEMORY_UNIT = 0x00000080,
XEX_MEDIA_USB_MASS_STORAGE_DEVICE = 0x00000100,
XEX_MEDIA_NETWORK = 0x00000200,
XEX_MEDIA_DIRECT_FROM_MEMORY = 0x00000400,
XEX_MEDIA_RAM_DRIVE = 0x00000800,
XEX_MEDIA_SVOD = 0x00001000,
XEX_MEDIA_INSECURE_PACKAGE = 0x01000000,
XEX_MEDIA_SAVEGAME_PACKAGE = 0x02000000,
XEX_MEDIA_LOCALLY_SIGNED_PACKAGE = 0x04000000,
XEX_MEDIA_LIVE_SIGNED_PACKAGE = 0x08000000,
XEX_MEDIA_XBOX_PACKAGE = 0x10000000,
};
enum xe_xex2_region_flags : uint32_t {
XEX_REGION_NTSCU = 0x000000FF,
XEX_REGION_NTSCJ = 0x0000FF00,
XEX_REGION_NTSCJ_JAPAN = 0x00000100,
XEX_REGION_NTSCJ_CHINA = 0x00000200,
XEX_REGION_PAL = 0x00FF0000,
XEX_REGION_PAL_AU_NZ = 0x00010000,
XEX_REGION_OTHER = 0xFF000000,
XEX_REGION_ALL = 0xFFFFFFFF,
};
struct xe_xex2_loader_info_t {
uint32_t header_size;
uint32_t image_size;
uint8_t rsa_signature[256];
uint32_t unklength;
xe_xex2_image_flags image_flags;
uint32_t load_address;
uint8_t section_digest[20];
uint32_t import_table_count;
uint8_t import_table_digest[20];
uint8_t media_id[16];
uint8_t file_key[16];
uint32_t export_table; // address of the export table
uint8_t header_digest[20];
xe_xex2_region_flags game_regions;
xe_xex2_media_flags media_flags;
};
enum xe_xex2_section_type {
XEX_SECTION_CODE = 1,
XEX_SECTION_DATA = 2,
XEX_SECTION_READONLY_DATA = 3,
};
struct xe_xex2_section_t {
uint32_t page_size;
union {
struct {
xe_xex2_section_type type : 4;
uint32_t page_count : 28; // # of pages
};
uint32_t value; // To make uint8_t swapping easier
} info;
uint8_t digest[20];
};
struct xe_xex2_header_t {
uint32_t xex2;
xe_xex2_module_flags module_flags;
uint32_t exe_offset;
uint32_t unknown0;
uint32_t certificate_offset;
xe_xex2_system_flags system_flags;
xe_xex2_execution_info_t execution_info;
xe_xex2_game_ratings_t game_ratings;
xe_xex2_tls_info_t tls_info;
size_t import_library_count;
xe_xex2_import_library_t import_libraries[32];
uint32_t pe_export_table_offset; // PE Export Directory
size_t static_library_count;
xe_xex2_static_library_t static_libraries[32];
xe_xex2_file_format_info_t file_format_info;
xe_xex2_loader_info_t loader_info;
uint8_t session_key[16];
uint32_t exe_address;
uint32_t exe_entry_point;
uint32_t exe_stack_size;
uint32_t exe_heap_size;
size_t header_count;
xe_xex2_opt_header_t headers[64];
size_t resource_info_count;
xe_xex2_resource_info_t* resource_infos;
size_t section_count;
xe_xex2_section_t* sections;
};
namespace xe {
union xex2_version {
xe::be<uint32_t> value;
struct {
@ -523,12 +436,20 @@ struct xex2_opt_resource_info {
xex2_resource resources[1]; // 0x4
};
struct xex2_delta_patch {
xe::be<uint32_t> old_addr;
xe::be<uint32_t> new_addr;
xe::be<uint16_t> uncompressed_len;
xe::be<uint16_t> compressed_len;
char patch_data[1];
};
struct xex2_opt_delta_patch_descriptor {
xe::be<uint32_t> size; // 0x0
xex2_version target_version; // 0x4
xex2_version source_version; // 0x8
char digest_source[0x14]; // 0xC
char image_key_source[0x10]; // 0x20
uint8_t digest_source[0x14]; // 0xC
uint8_t image_key_source[0x10]; // 0x20
xe::be<uint32_t> size_of_target_headers; // 0x30
xe::be<uint32_t> delta_headers_source_offset; // 0x34
xe::be<uint32_t> delta_headers_source_size; // 0x38
@ -536,8 +457,8 @@ struct xex2_opt_delta_patch_descriptor {
xe::be<uint32_t> delta_image_source_offset; // 0x40
xe::be<uint32_t> delta_image_source_size; // 0x44
xe::be<uint32_t> delta_image_target_offset; // 0x48
xex2_delta_patch info; // 0x4C
};
static_assert_size(xex2_opt_delta_patch_descriptor, 0x4C);
struct xex2_opt_execution_info {
xe::be<uint32_t> media_id; // 0x0
@ -580,12 +501,12 @@ struct xex2_opt_header {
};
struct xex2_header {
xe::be<uint32_t> magic; // 0x0 'XEX2'
xe::be<xe_xex2_module_flags> module_flags; // 0x4
xe::be<uint32_t> header_size; // 0x8
xe::be<uint32_t> reserved; // 0xC
xe::be<uint32_t> security_offset; // 0x10
xe::be<uint32_t> header_count; // 0x14
xe::be<uint32_t> magic; // 0x0 'XEX2'
xe::be<xex2_module_flags> module_flags; // 0x4
xe::be<uint32_t> header_size; // 0x8
xe::be<uint32_t> reserved; // 0xC
xe::be<uint32_t> security_offset; // 0x10
xe::be<uint32_t> header_count; // 0x14
xex2_opt_header headers[1]; // 0x18
};

View File

@ -11,7 +11,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xam/xam_module.h"
#include "xenia/kernel/xam/xam_private.h"
#include "xenia/kernel/xenumerator.h"

View File

@ -15,7 +15,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_error.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xthread.h"

View File

@ -12,7 +12,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/xbox.h"

View File

@ -19,7 +19,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
#include "xenia/kernel/xevent.h"
@ -285,7 +284,7 @@ pointer_result_t RtlImageXexHeaderField(pointer_t<xex2_header> xex_header,
uint32_t field = field_dword; // VS acts weird going from dword_t -> enum
UserModule::GetOptHeader(kernel_memory()->virtual_membase(), xex_header,
xe_xex2_header_keys(field), &field_value);
xex2_header_keys(field), &field_value);
return field_value;
}

View File

@ -15,7 +15,6 @@
#include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/util/shim_utils.h"
#include "xenia/kernel/util/xex2.h"
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
#include "xenia/kernel/xthread.h"
#include "xenia/xbox.h"