diff --git a/src/xenia/kernel/util/xex2.cc b/src/xenia/kernel/util/xex2.cc index ab8d594e4..3eccb68cf 100644 --- a/src/xenia/kernel/util/xex2.cc +++ b/src/xenia/kernel/util/xex2.cc @@ -27,6 +27,34 @@ #include "xenia/base/memory.h" #include "xenia/base/platform.h" +namespace xe { +namespace kernel { +template +T* xex2_get_opt_header(const xex2_header* header, uint32_t key) { + for (int i = 0; i < header->header_count; i++) { + const xex2_opt_header* opt_header = header->headers[i]; + if (opt_header->key != key) { + continue; + } + + if ((opt_header->key & 0xFF) == 0x01) { + // Data is stored in the opt header + return (T*)&opt_header->value; + } else { + // Data stored at offset. + return (T*)((uint8_t*)&header->headers[0] + opt_header->offset); + } + } + + return nullptr; +} + +uint32_t xex2_get_header_size(const xex2_header* header) { + return header->exe_offset; +} +} // namespace kernel +} // namespace xe + // TODO(benvanik): remove. #define XEEXPECTZERO(expr) \ if ((expr) != 0) { \ @@ -126,7 +154,7 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length, xe_xex2_loader_info_t *ldr; header->xex2 = xe::load_and_swap(p + 0x00); - if (header->xex2 != 0x58455832) { + if (header->xex2 != 'XEX2') { return 1; } @@ -356,8 +384,8 @@ int xe_xex2_read_header(const uint8_t *addr, const size_t length, uint32_t window_size = xe::load_and_swap(pp + 0x08); uint32_t window_bits = 0; for (size_t m = 0; m < 32; m++, window_bits++) { - window_size <<= 1; - if (window_size == 0x80000000) { + window_size >>= 1; + if (window_size == 0x00000000) { break; } } diff --git a/src/xenia/kernel/util/xex2.h b/src/xenia/kernel/util/xex2.h index c2c808c6e..536781ceb 100644 --- a/src/xenia/kernel/util/xex2.h +++ b/src/xenia/kernel/util/xex2.h @@ -13,6 +13,15 @@ #include "xenia/kernel/util/xex2_info.h" #include "xenia/memory.h" +namespace xe { +namespace kernel { +template +T* xex2_get_opt_header(const xex2_header* header, uint32_t key); + +uint32_t xex2_get_header_size(const xex2_header* header); +} // namespace kernel +} // namespace xe + typedef struct { int reserved; } xe_xex2_options_t; struct xe_xex2; diff --git a/src/xenia/kernel/util/xex2_info.h b/src/xenia/kernel/util/xex2_info.h index f3a467f46..fa1281935 100644 --- a/src/xenia/kernel/util/xex2_info.h +++ b/src/xenia/kernel/util/xex2_info.h @@ -12,6 +12,8 @@ #include +#include "xenia/base/byte_order.h" + typedef enum { XEX_HEADER_RESOURCE_INFO = 0x000002FF, XEX_HEADER_FILE_FORMAT_INFO = 0x000003FF, @@ -467,4 +469,56 @@ typedef struct { xe_xex2_section_t* sections; } xe_xex2_header_t; +namespace xe { +namespace kernel { +union xex2_version { + uint32_t value; + struct { + uint32_t major : 4; + uint32_t minor : 4; + uint32_t build : 16; + uint32_t qfe : 8; + }; +}; + +struct xex2_opt_execution_info { + xe::be media_id; // 0x0 + xe::be version; // 0x4 + xe::be base_version; // 0x8 + xe::be title_id; // 0xC + uint8_t platform; // 0x10 + uint8_t executable_table; // 0x11 + uint8_t disc_number; // 0x12 + uint8_t disc_count; // 0x13 + xe::be savegame_id; // 0x14 +}; + +struct xex2_opt_header { + xe::be key; // 0x0 + + union { + xe::be value; // 0x4 + xe::be offset; // 0x8 + }; +}; + +struct xex2_header { + xe::be magic; // 0x0 'XEX2' + xe::be module_flags; // 0x4 + xe::be exe_offset; // 0x8 + xe::be reserved; // 0xC + xe::be certificate_offset; // 0x10 + xe::be header_count; // 0x14 + + xex2_opt_header headers[1]; // 0x18 +}; + +struct xex2_loader_info { + xe::be header_size; + xe::be image_size; + +}; +} // namespace kernel +} // namespace xe + #endif // XENIA_KERNEL_XEX2_INFO_H_