Merge branch 'master' into linux_windowing
This commit is contained in:
@@ -519,7 +519,7 @@ GuestToHostThunk X64ThunkEmitter::EmitGuestToHostThunk() {
|
||||
}
|
||||
|
||||
// X64Emitter handles actually resolving functions.
|
||||
extern "C" uint64_t ResolveFunction(void* raw_context, uint32_t target_address);
|
||||
uint64_t ResolveFunction(void* raw_context, uint64_t target_address);
|
||||
|
||||
ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
|
||||
// ebx = target PPC address
|
||||
@@ -548,7 +548,7 @@ ResolveFunctionThunk X64ThunkEmitter::EmitResolveFunctionThunk() {
|
||||
|
||||
mov(rcx, rsi); // context
|
||||
mov(rdx, rbx);
|
||||
mov(rax, uint64_t(&ResolveFunction));
|
||||
mov(rax, reinterpret_cast<uint64_t>(&ResolveFunction));
|
||||
call(rax);
|
||||
|
||||
EmitLoadVolatileRegs();
|
||||
|
||||
@@ -382,15 +382,14 @@ void X64Emitter::UnimplementedInstr(const hir::Instr* i) {
|
||||
}
|
||||
|
||||
// This is used by the X64ThunkEmitter's ResolveFunctionThunk.
|
||||
extern "C" uint64_t ResolveFunction(void* raw_context,
|
||||
uint64_t target_address) {
|
||||
uint64_t ResolveFunction(void* raw_context, uint64_t target_address) {
|
||||
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
|
||||
|
||||
// TODO(benvanik): required?
|
||||
assert_not_zero(target_address);
|
||||
|
||||
auto fn =
|
||||
thread_state->processor()->ResolveFunction((uint32_t)target_address);
|
||||
auto fn = thread_state->processor()->ResolveFunction(
|
||||
static_cast<uint32_t>(target_address));
|
||||
assert_not_null(fn);
|
||||
auto x64_fn = static_cast<X64Function*>(fn);
|
||||
uint64_t addr = reinterpret_cast<uint64_t>(x64_fn->machine_code());
|
||||
|
||||
@@ -105,8 +105,7 @@ struct Op : OpBase {
|
||||
|
||||
struct VoidOp : Op<VoidOp, KEY_TYPE_X> {
|
||||
protected:
|
||||
template <typename T, KeyType KEY_TYPE>
|
||||
friend struct Op;
|
||||
friend struct Op<VoidOp, KEY_TYPE_X>;
|
||||
template <hir::Opcode OPCODE, typename... Ts>
|
||||
friend struct I;
|
||||
void Load(const Instr::Op& op) {}
|
||||
@@ -116,8 +115,7 @@ struct OffsetOp : Op<OffsetOp, KEY_TYPE_O> {
|
||||
uint64_t value;
|
||||
|
||||
protected:
|
||||
template <typename T, KeyType KEY_TYPE>
|
||||
friend struct Op;
|
||||
friend struct Op<OffsetOp, KEY_TYPE_O>;
|
||||
template <hir::Opcode OPCODE, typename... Ts>
|
||||
friend struct I;
|
||||
void Load(const Instr::Op& op) { this->value = op.offset; }
|
||||
@@ -127,8 +125,7 @@ struct SymbolOp : Op<SymbolOp, KEY_TYPE_S> {
|
||||
Function* value;
|
||||
|
||||
protected:
|
||||
template <typename T, KeyType KEY_TYPE>
|
||||
friend struct Op;
|
||||
friend struct Op<SymbolOp, KEY_TYPE_S>;
|
||||
template <hir::Opcode OPCODE, typename... Ts>
|
||||
friend struct I;
|
||||
bool Load(const Instr::Op& op) {
|
||||
@@ -141,8 +138,7 @@ struct LabelOp : Op<LabelOp, KEY_TYPE_L> {
|
||||
hir::Label* value;
|
||||
|
||||
protected:
|
||||
template <typename T, KeyType KEY_TYPE>
|
||||
friend struct Op;
|
||||
friend struct Op<LabelOp, KEY_TYPE_L>;
|
||||
template <hir::Opcode OPCODE, typename... Ts>
|
||||
friend struct I;
|
||||
void Load(const Instr::Op& op) { this->value = op.label; }
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2014 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -73,14 +73,14 @@ void DataFlowAnalysisPass::AnalyzeFlow(HIRBuilder* builder,
|
||||
// Stash for value map. We may want to maintain this during building.
|
||||
auto arena = builder->arena();
|
||||
auto value_map = reinterpret_cast<Value**>(
|
||||
arena->Alloc(sizeof(Value*) * max_value_estimate));
|
||||
arena->Alloc(sizeof(Value*) * max_value_estimate, alignof(Value)));
|
||||
|
||||
// Allocate incoming bitvectors for use by blocks. We don't need outgoing
|
||||
// because they are only used during the block iteration.
|
||||
// Mapped by block ordinal.
|
||||
// TODO(benvanik): cache this list, grow as needed, etc.
|
||||
auto incoming_bitvectors =
|
||||
(llvm::BitVector**)arena->Alloc(sizeof(llvm::BitVector*) * block_count);
|
||||
auto incoming_bitvectors = (llvm::BitVector**)arena->Alloc(
|
||||
sizeof(llvm::BitVector*) * block_count, alignof(llvm::BitVector));
|
||||
for (auto n = 0u; n < block_count; n++) {
|
||||
incoming_bitvectors[n] = new llvm::BitVector(max_value_estimate);
|
||||
}
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -45,7 +45,7 @@ bool FinalizationPass::Run(HIRBuilder* builder) {
|
||||
while (label) {
|
||||
if (!label->name) {
|
||||
const size_t label_len = 6 + 4;
|
||||
char* name = reinterpret_cast<char*>(arena->Alloc(label_len + 1));
|
||||
char* name = reinterpret_cast<char*>(arena->Alloc(label_len + 1, 1));
|
||||
assert_true(label->id <= 9999);
|
||||
auto end = fmt::format_to_n(name, label_len, "_label{}", label->id);
|
||||
name[end.size] = '\0';
|
||||
|
||||
@@ -39,7 +39,7 @@ enum class ExportCategory : uint8_t {
|
||||
};
|
||||
|
||||
struct ExportTag {
|
||||
typedef uint32_t type;
|
||||
using type = uint32_t;
|
||||
|
||||
// packed like so:
|
||||
// ll...... cccccccc ........ ..bihssi
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -739,7 +739,7 @@ void HIRBuilder::Comment(std::string_view value) {
|
||||
return;
|
||||
}
|
||||
auto size = value.size();
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1));
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1, 1));
|
||||
std::memcpy(p, value.data(), size);
|
||||
p[size] = '\0';
|
||||
Instr* i = AppendInstr(OPCODE_COMMENT_info, 0);
|
||||
@@ -752,7 +752,7 @@ void HIRBuilder::Comment(const StringBuffer& value) {
|
||||
return;
|
||||
}
|
||||
auto size = value.length();
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1));
|
||||
auto p = reinterpret_cast<char*>(arena_->Alloc(size + 1, 1));
|
||||
std::memcpy(p, value.buffer(), size);
|
||||
p[size] = '\0';
|
||||
Instr* i = AppendInstr(OPCODE_COMMENT_info, 0);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -75,7 +75,7 @@ class HIRBuilder {
|
||||
template <typename... Args>
|
||||
void CommentFormat(const std::string_view format, const Args&... args) {
|
||||
static const uint32_t kMaxCommentSize = 1024;
|
||||
char* p = reinterpret_cast<char*>(arena_->Alloc(kMaxCommentSize));
|
||||
char* p = reinterpret_cast<char*>(arena_->Alloc(kMaxCommentSize, 1));
|
||||
auto result = fmt::format_to_n(p, kMaxCommentSize - 1, format, args...);
|
||||
p[result.size] = '\0';
|
||||
size_t rewind = kMaxCommentSize - 1 - result.size;
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -245,65 +245,34 @@ void Value::Convert(TypeName target_type, RoundMode round_mode) {
|
||||
}
|
||||
}
|
||||
|
||||
template <typename T>
|
||||
T __inline RoundValue(RoundMode round_mode, T value) {
|
||||
switch (round_mode) {
|
||||
case ROUND_TO_ZERO:
|
||||
return std::trunc(value);
|
||||
case ROUND_TO_NEAREST:
|
||||
return std::round(value);
|
||||
case ROUND_TO_MINUS_INFINITY:
|
||||
return std::floor(value);
|
||||
case ROUND_TO_POSITIVE_INFINITY:
|
||||
return std::ceil(value);
|
||||
default:
|
||||
assert_unhandled_case(round_mode);
|
||||
return value;
|
||||
}
|
||||
}
|
||||
|
||||
void Value::Round(RoundMode round_mode) {
|
||||
switch (type) {
|
||||
case FLOAT32_TYPE:
|
||||
switch (round_mode) {
|
||||
case ROUND_TO_ZERO:
|
||||
constant.f32 = std::trunc(constant.f32);
|
||||
break;
|
||||
case ROUND_TO_NEAREST:
|
||||
constant.f32 = std::round(constant.f32);
|
||||
return;
|
||||
case ROUND_TO_MINUS_INFINITY:
|
||||
constant.f32 = std::floor(constant.f32);
|
||||
break;
|
||||
case ROUND_TO_POSITIVE_INFINITY:
|
||||
constant.f32 = std::ceil(constant.f32);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(round_mode);
|
||||
return;
|
||||
}
|
||||
constant.f32 = RoundValue(round_mode, constant.f32);
|
||||
return;
|
||||
case FLOAT64_TYPE:
|
||||
switch (round_mode) {
|
||||
case ROUND_TO_ZERO:
|
||||
constant.f64 = std::trunc(constant.f64);
|
||||
break;
|
||||
case ROUND_TO_NEAREST:
|
||||
constant.f64 = std::round(constant.f64);
|
||||
return;
|
||||
case ROUND_TO_MINUS_INFINITY:
|
||||
constant.f64 = std::floor(constant.f64);
|
||||
break;
|
||||
case ROUND_TO_POSITIVE_INFINITY:
|
||||
constant.f64 = std::ceil(constant.f64);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(round_mode);
|
||||
return;
|
||||
}
|
||||
constant.f64 = RoundValue(round_mode, constant.f64);
|
||||
return;
|
||||
case VEC128_TYPE:
|
||||
for (int i = 0; i < 4; i++) {
|
||||
switch (round_mode) {
|
||||
case ROUND_TO_ZERO:
|
||||
constant.v128.f32[i] = std::trunc(constant.v128.f32[i]);
|
||||
break;
|
||||
case ROUND_TO_NEAREST:
|
||||
constant.v128.f32[i] = std::round(constant.v128.f32[i]);
|
||||
break;
|
||||
case ROUND_TO_MINUS_INFINITY:
|
||||
constant.v128.f32[i] = std::floor(constant.v128.f32[i]);
|
||||
break;
|
||||
case ROUND_TO_POSITIVE_INFINITY:
|
||||
constant.v128.f32[i] = std::ceil(constant.v128.f32[i]);
|
||||
break;
|
||||
default:
|
||||
assert_unhandled_case(round_mode);
|
||||
return;
|
||||
}
|
||||
constant.v128.f32[i] = RoundValue(round_mode, constant.v128.f32[i]);
|
||||
}
|
||||
return;
|
||||
default:
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2013 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -426,6 +426,10 @@ int InstrEmit_sc(PPCHIRBuilder& f, const InstrData& i) {
|
||||
// Game code should only ever use LEV=0.
|
||||
// LEV=2 is to signify 'call import' from Xenia.
|
||||
// TODO(gibbed): syscalls!
|
||||
if (i.SC.LEV == 0) {
|
||||
f.CallExtern(f.builtins()->syscall_handler);
|
||||
return 0;
|
||||
}
|
||||
if (i.SC.LEV == 2) {
|
||||
f.CallExtern(f.function());
|
||||
return 0;
|
||||
@@ -807,5 +811,5 @@ void RegisterEmitCategoryControl() {
|
||||
}
|
||||
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
} // namespace cpu
|
||||
} // namespace xe
|
||||
|
||||
@@ -10,6 +10,7 @@
|
||||
#include "xenia/cpu/ppc/ppc_frontend.h"
|
||||
|
||||
#include "xenia/base/atomic.h"
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/cpu/ppc/ppc_context.h"
|
||||
#include "xenia/cpu/ppc/ppc_emit.h"
|
||||
#include "xenia/cpu/ppc/ppc_opcode_info.h"
|
||||
@@ -78,6 +79,17 @@ void LeaveGlobalLock(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||
global_mutex->unlock();
|
||||
}
|
||||
|
||||
void SyscallHandler(PPCContext* ppc_context, void* arg0, void* arg1) {
|
||||
uint64_t syscall_number = ppc_context->r[0];
|
||||
switch (syscall_number) {
|
||||
default:
|
||||
assert_unhandled_case(syscall_number);
|
||||
XELOGE("Unhandled syscall {}!", syscall_number);
|
||||
break;
|
||||
#pragma warning(suppress : 4065)
|
||||
}
|
||||
}
|
||||
|
||||
bool PPCFrontend::Initialize() {
|
||||
void* arg0 = reinterpret_cast<void*>(&xe::global_critical_region::mutex());
|
||||
void* arg1 = reinterpret_cast<void*>(&builtins_.global_lock_count);
|
||||
@@ -87,6 +99,8 @@ bool PPCFrontend::Initialize() {
|
||||
processor_->DefineBuiltin("EnterGlobalLock", EnterGlobalLock, arg0, arg1);
|
||||
builtins_.leave_global_lock =
|
||||
processor_->DefineBuiltin("LeaveGlobalLock", LeaveGlobalLock, arg0, arg1);
|
||||
builtins_.syscall_handler = processor_->DefineBuiltin(
|
||||
"SyscallHandler", SyscallHandler, nullptr, nullptr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
@@ -33,6 +33,7 @@ struct PPCBuiltins {
|
||||
Function* check_global_lock;
|
||||
Function* enter_global_lock;
|
||||
Function* leave_global_lock;
|
||||
Function* syscall_handler;
|
||||
};
|
||||
|
||||
class PPCFrontend {
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -104,8 +104,8 @@ bool PPCHIRBuilder::Emit(GuestFunction* function, uint32_t flags) {
|
||||
// instruction may have a label assigned to it if it hasn't been hit
|
||||
// yet.
|
||||
size_t list_size = instr_count_ * sizeof(void*);
|
||||
instr_offset_list_ = (Instr**)arena_->Alloc(list_size);
|
||||
label_list_ = (Label**)arena_->Alloc(list_size);
|
||||
instr_offset_list_ = (Instr**)arena_->Alloc(list_size, alignof(void*));
|
||||
label_list_ = (Label**)arena_->Alloc(list_size, alignof(void*));
|
||||
std::memset(instr_offset_list_, 0, list_size);
|
||||
std::memset(label_list_, 0, list_size);
|
||||
|
||||
@@ -244,7 +244,7 @@ void PPCHIRBuilder::AnnotateLabel(uint32_t address, Label* label) {
|
||||
char name_buffer[13];
|
||||
auto format_result = fmt::format_to_n(name_buffer, 12, "loc_{:08X}", address);
|
||||
name_buffer[format_result.size] = '\0';
|
||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer));
|
||||
label->name = (char*)arena_->Alloc(sizeof(name_buffer), 1);
|
||||
memcpy(label->name, name_buffer, sizeof(name_buffer));
|
||||
}
|
||||
|
||||
|
||||
@@ -432,12 +432,12 @@ void Processor::LowerIrql(Irql old_value) {
|
||||
}
|
||||
|
||||
bool Processor::Save(ByteStream* stream) {
|
||||
stream->Write('PROC');
|
||||
stream->Write(kProcessorSaveSignature);
|
||||
return true;
|
||||
}
|
||||
|
||||
bool Processor::Restore(ByteStream* stream) {
|
||||
if (stream->Read<uint32_t>() != 'PROC') {
|
||||
if (stream->Read<uint32_t>() != kProcessorSaveSignature) {
|
||||
XELOGE("Processor::Restore - Invalid magic value!");
|
||||
return false;
|
||||
}
|
||||
|
||||
@@ -34,6 +34,8 @@ DECLARE_bool(debug);
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
constexpr fourcc_t kProcessorSaveSignature = make_fourcc("PROC");
|
||||
|
||||
class Breakpoint;
|
||||
class StackWalker;
|
||||
class XexModule;
|
||||
|
||||
@@ -20,7 +20,7 @@
|
||||
#include "xenia/cpu/processor.h"
|
||||
#include "xenia/cpu/test_module.h"
|
||||
|
||||
#include "third_party/catch/single_include/catch.hpp"
|
||||
#include "third_party/catch/include/catch.hpp"
|
||||
|
||||
#define XENIA_TEST_X64 1
|
||||
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2021 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -249,12 +249,11 @@ int XexModule::ApplyPatch(XexModule* module) {
|
||||
|
||||
// Patch base XEX header
|
||||
uint32_t original_image_size = module->image_size();
|
||||
uint32_t header_target_size = patch_header->delta_headers_target_offset +
|
||||
patch_header->delta_headers_source_size;
|
||||
uint32_t header_target_size = patch_header->size_of_target_headers;
|
||||
|
||||
if (!header_target_size) {
|
||||
header_target_size =
|
||||
patch_header->size_of_target_headers; // unsure which is more correct..
|
||||
header_target_size = patch_header->delta_headers_target_offset +
|
||||
patch_header->delta_headers_source_size;
|
||||
}
|
||||
|
||||
size_t mem_size = module->xex_header_mem_.size();
|
||||
@@ -899,9 +898,9 @@ 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 == 'XEX1') {
|
||||
if (src_header->magic == kXEX1Signature) {
|
||||
xex_format_ = kFormatXex1;
|
||||
} else if (src_header->magic == 'XEX2') {
|
||||
} else if (src_header->magic == kXEX2Signature) {
|
||||
xex_format_ = kFormatXex2;
|
||||
} else {
|
||||
return false;
|
||||
@@ -967,6 +966,16 @@ bool XexModule::LoadContinue() {
|
||||
return false;
|
||||
}
|
||||
|
||||
// Parse any "unsafe" headers into safer variants
|
||||
xex2_opt_generic_u32* alternate_titleids;
|
||||
if (GetOptHeader(xex2_header_keys::XEX_HEADER_ALTERNATE_TITLE_IDS,
|
||||
&alternate_titleids)) {
|
||||
auto count = alternate_titleids->count();
|
||||
for (uint32_t i = 0; i < count; i++) {
|
||||
opt_alternate_title_ids_.push_back(alternate_titleids->values[i]);
|
||||
}
|
||||
}
|
||||
|
||||
// Scan and find the low/high addresses.
|
||||
// All code sections are continuous, so this should be easy.
|
||||
auto heap = memory()->LookupHeap(base_address_);
|
||||
|
||||
@@ -25,6 +25,10 @@ class KernelState;
|
||||
namespace xe {
|
||||
namespace cpu {
|
||||
|
||||
constexpr fourcc_t kXEX1Signature = make_fourcc("XEX1");
|
||||
constexpr fourcc_t kXEX2Signature = make_fourcc("XEX2");
|
||||
constexpr fourcc_t kElfSignature = make_fourcc(0x7F, 'E', 'L', 'F');
|
||||
|
||||
class Runtime;
|
||||
|
||||
class XexModule : public xe::cpu::Module {
|
||||
@@ -103,6 +107,10 @@ class XexModule : public xe::cpu::Module {
|
||||
return retval;
|
||||
}
|
||||
|
||||
std::vector<uint32_t> opt_alternate_title_ids() const {
|
||||
return opt_alternate_title_ids_;
|
||||
}
|
||||
|
||||
const uint32_t base_address() const { return base_address_; }
|
||||
const bool is_dev_kit() const { return is_dev_kit_; }
|
||||
|
||||
@@ -194,6 +202,9 @@ class XexModule : public xe::cpu::Module {
|
||||
import_libs_; // pre-loaded import libraries for ease of use
|
||||
std::vector<PESection> pe_sections_;
|
||||
|
||||
// XEX_HEADER_ALTERNATE_TITLE_IDS loaded into a safe std::vector
|
||||
std::vector<uint32_t> opt_alternate_title_ids_;
|
||||
|
||||
uint8_t session_key_[0x10];
|
||||
bool is_dev_kit_ = false;
|
||||
|
||||
|
||||
Reference in New Issue
Block a user