Starting to properly attribute virtual vs. physical memory accesses.

This commit is contained in:
Ben Vanik 2015-03-29 11:11:35 -07:00
parent ab90e0932b
commit ec84a688e9
42 changed files with 346 additions and 372 deletions

View File

@ -25,6 +25,10 @@ class AudioDriver {
virtual void SubmitFrame(uint32_t samples_ptr) = 0; virtual void SubmitFrame(uint32_t samples_ptr) = 0;
protected: protected:
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
return memory_->TranslatePhysical(guest_address);
}
Emulator* emulator_; Emulator* emulator_;
Memory* memory_; Memory* memory_;
cpu::Processor* processor_; cpu::Processor* processor_;

View File

@ -182,7 +182,7 @@ uint32_t AudioSystem::AllocateXmaContext() {
auto guest_ptr = xma_context_free_list_.back(); auto guest_ptr = xma_context_free_list_.back();
xma_context_free_list_.pop_back(); xma_context_free_list_.pop_back();
auto context_ptr = memory()->Translate(guest_ptr); auto context_ptr = memory()->TranslateVirtual(guest_ptr);
// Initialize? // Initialize?
@ -192,7 +192,7 @@ uint32_t AudioSystem::AllocateXmaContext() {
void AudioSystem::ReleaseXmaContext(uint32_t guest_ptr) { void AudioSystem::ReleaseXmaContext(uint32_t guest_ptr) {
std::lock_guard<std::mutex> lock(lock_); std::lock_guard<std::mutex> lock(lock_);
auto context_ptr = memory()->Translate(guest_ptr); auto context_ptr = memory()->TranslateVirtual(guest_ptr);
std::memset(context_ptr, 0, kXmaContextSize); std::memset(context_ptr, 0, kXmaContextSize);
xma_context_free_list_.push_back(guest_ptr); xma_context_free_list_.push_back(guest_ptr);
@ -217,8 +217,7 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
unused_clients_.pop(); unused_clients_.pop();
uint32_t ptr = memory()->SystemHeapAlloc(0x4); uint32_t ptr = memory()->SystemHeapAlloc(0x4);
auto mem = memory()->membase(); poly::store_and_swap<uint32_t>(memory()->TranslateVirtual(ptr), callback_arg);
poly::store_and_swap<uint32_t>(mem + ptr, callback_arg);
clients_[index] = {driver, callback, callback_arg, ptr}; clients_[index] = {driver, callback, callback_arg, ptr};
@ -301,7 +300,7 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) {
// feeding data. // feeding data.
uint32_t guest_ptr = uint32_t guest_ptr =
registers_.xma_context_array_ptr + context_id * kXmaContextSize; registers_.xma_context_array_ptr + context_id * kXmaContextSize;
auto context_ptr = memory()->Translate(guest_ptr); auto context_ptr = memory()->TranslateVirtual(guest_ptr);
uint32_t dword0 = poly::load_and_swap<uint32_t>(context_ptr + 0); uint32_t dword0 = poly::load_and_swap<uint32_t>(context_ptr + 0);
bool has_valid_input = (dword0 & 0x00300000) != 0; bool has_valid_input = (dword0 & 0x00300000) != 0;
if (has_valid_input) { if (has_valid_input) {

View File

@ -122,7 +122,7 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) {
// Process samples! They are big-endian floats. // Process samples! They are big-endian floats.
HRESULT hr; HRESULT hr;
auto input_frame = reinterpret_cast<float*>(emulator_->memory()->membase() + frame_ptr); auto input_frame = memory_->TranslatePhysical<float*>(frame_ptr);
auto output_frame = reinterpret_cast<float*>(frame_); auto output_frame = reinterpret_cast<float*>(frame_);
auto interleave_channels = frame_channels_; auto interleave_channels = frame_channels_;

View File

@ -368,8 +368,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) {
auto thread_state = *reinterpret_cast<ThreadState**>(raw_context); auto thread_state = *reinterpret_cast<ThreadState**>(raw_context);
uint32_t str_ptr = uint32_t(thread_state->context()->r[3]); uint32_t str_ptr = uint32_t(thread_state->context()->r[3]);
uint16_t str_len = uint16_t(thread_state->context()->r[4]); uint16_t str_len = uint16_t(thread_state->context()->r[4]);
const char* str = auto str = thread_state->memory()->TranslateVirtual<const char*>(str_ptr);
reinterpret_cast<const char*>(thread_state->memory()->Translate(str_ptr));
// TODO(benvanik): truncate to length? // TODO(benvanik): truncate to length?
PLOGD("(DebugPrint) %s", str); PLOGD("(DebugPrint) %s", str);
return 0; return 0;

View File

@ -37,7 +37,7 @@ int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; }
int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) { int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) {
auto backend = (X64Backend*)thread_state->runtime()->backend(); auto backend = (X64Backend*)thread_state->runtime()->backend();
auto thunk = backend->host_to_guest_thunk(); auto thunk = backend->host_to_guest_thunk();
thunk(machine_code_, thread_state->raw_context(), thunk(machine_code_, thread_state->context(),
reinterpret_cast<void*>(uintptr_t(return_address))); reinterpret_cast<void*>(uintptr_t(return_address)));
return 0; return 0;
} }

View File

@ -44,7 +44,7 @@ typedef struct alignas(64) PPCContext_s {
// TODO(benvanik): find a nice way to describe this to the JIT. // TODO(benvanik): find a nice way to describe this to the JIT.
ThreadState* thread_state; ThreadState* thread_state;
// TODO(benvanik): this is getting nasty. Must be here. // TODO(benvanik): this is getting nasty. Must be here.
uint8_t* membase; uint8_t* virtual_membase;
// Most frequently used registers first. // Most frequently used registers first.
uint64_t r[32]; // General purpose registers uint64_t r[32]; // General purpose registers
@ -210,6 +210,8 @@ typedef struct alignas(64) PPCContext_s {
// current runtime and its data. // current runtime and its data.
Runtime* runtime; Runtime* runtime;
uint8_t* physical_membase;
void SetRegFromString(const char* name, const char* value); void SetRegFromString(const char* name, const char* value);
bool CompareRegWithString(const char* name, const char* value, bool CompareRegWithString(const char* name, const char* value,
char* out_value, size_t out_value_size); char* out_value, size_t out_value_size);

View File

@ -46,7 +46,6 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
SCOPE_profile_cpu_f("cpu"); SCOPE_profile_cpu_f("cpu");
Memory* memory = frontend_->memory(); Memory* memory = frontend_->memory();
const uint8_t* p = memory->membase();
symbol_info_ = symbol_info; symbol_info_ = symbol_info;
start_address_ = symbol_info->address(); start_address_ = symbol_info->address();
@ -80,7 +79,7 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) {
for (uint32_t address = start_address, offset = 0; address <= end_address; for (uint32_t address = start_address, offset = 0; address <= end_address;
address += 4, offset++) { address += 4, offset++) {
i.address = address; i.address = address;
i.code = poly::load_and_swap<uint32_t>(p + address); i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// TODO(benvanik): find a way to avoid using the opcode tables. // TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code); i.type = GetInstrType(i.code);
trace_info_.dest_count = 0; trace_info_.dest_count = 0;

View File

@ -50,7 +50,6 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
// split up and the second half is treated as another function. // split up and the second half is treated as another function.
Memory* memory = frontend_->memory(); Memory* memory = frontend_->memory();
const uint8_t* p = memory->membase();
LOGPPC("Analyzing function %.8X...", symbol_info->address()); LOGPPC("Analyzing function %.8X...", symbol_info->address());
@ -64,7 +63,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
InstrData i; InstrData i;
while (true) { while (true) {
i.address = address; i.address = address;
i.code = poly::load_and_swap<uint32_t>(p + address); i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// If we fetched 0 assume that we somehow hit one of the awesome // If we fetched 0 assume that we somehow hit one of the awesome
// 'no really we meant to end after that bl' functions. // 'no really we meant to end after that bl' functions.
@ -281,7 +280,6 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) {
std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) { std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
Memory* memory = frontend_->memory(); Memory* memory = frontend_->memory();
const uint8_t* p = memory->membase();
std::map<uint32_t, BlockInfo> block_map; std::map<uint32_t, BlockInfo> block_map;
@ -292,7 +290,7 @@ std::vector<BlockInfo> PPCScanner::FindBlocks(FunctionInfo* symbol_info) {
InstrData i; InstrData i;
for (uint32_t address = start_address; address <= end_address; address += 4) { for (uint32_t address = start_address; address <= end_address; address += 4) {
i.address = address; i.address = address;
i.code = poly::load_and_swap<uint32_t>(p + address); i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
if (!i.code) { if (!i.code) {
continue; continue;
} }

View File

@ -175,7 +175,6 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info,
void PPCTranslator::DumpSource(FunctionInfo* symbol_info, void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
poly::StringBuffer* string_buffer) { poly::StringBuffer* string_buffer) {
Memory* memory = frontend_->memory(); Memory* memory = frontend_->memory();
const uint8_t* p = memory->membase();
string_buffer->Append("%s fn %.8X-%.8X %s\n", string_buffer->Append("%s fn %.8X-%.8X %s\n",
symbol_info->module()->name().c_str(), symbol_info->module()->name().c_str(),
@ -184,14 +183,14 @@ void PPCTranslator::DumpSource(FunctionInfo* symbol_info,
auto blocks = scanner_->FindBlocks(symbol_info); auto blocks = scanner_->FindBlocks(symbol_info);
uint64_t start_address = symbol_info->address(); uint32_t start_address = symbol_info->address();
uint64_t end_address = symbol_info->end_address(); uint32_t end_address = symbol_info->end_address();
InstrData i; InstrData i;
auto block_it = blocks.begin(); auto block_it = blocks.begin();
for (uint64_t address = start_address, offset = 0; address <= end_address; for (uint32_t address = start_address, offset = 0; address <= end_address;
address += 4, offset++) { address += 4, offset++) {
i.address = address; i.address = address;
i.code = poly::load_and_swap<uint32_t>(p + address); i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
// TODO(benvanik): find a way to avoid using the opcode tables. // TODO(benvanik): find a way to avoid using the opcode tables.
i.type = GetInstrType(i.code); i.type = GetInstrType(i.code);

View File

@ -241,7 +241,7 @@ class TestRunner {
auto address_str = it.second.substr(0, space_pos); auto address_str = it.second.substr(0, space_pos);
auto bytes_str = it.second.substr(space_pos + 1); auto bytes_str = it.second.substr(space_pos + 1);
uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16); uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16);
auto p = memory->Translate(address); auto p = memory->TranslateVirtual(address);
const char* c = bytes_str.c_str(); const char* c = bytes_str.c_str();
while (*c) { while (*c) {
while (*c == ' ') ++c; while (*c == ' ') ++c;
@ -283,7 +283,7 @@ class TestRunner {
auto address_str = it.second.substr(0, space_pos); auto address_str = it.second.substr(0, space_pos);
auto bytes_str = it.second.substr(space_pos + 1); auto bytes_str = it.second.substr(space_pos + 1);
uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16); uint32_t address = std::strtoul(address_str.c_str(), nullptr, 16);
auto base_address = memory->Translate(address); auto base_address = memory->TranslateVirtual(address);
auto p = base_address; auto p = base_address;
const char* c = bytes_str.c_str(); const char* c = bytes_str.c_str();
while (*c) { while (*c) {

View File

@ -88,7 +88,7 @@ int Function::Call(ThreadState* thread_state, uint32_t return_address) {
} }
if (handler) { if (handler) {
handler(thread_state->raw_context(), symbol_info_->extern_arg0(), handler(thread_state->context(), symbol_info_->extern_arg0(),
symbol_info_->extern_arg1()); symbol_info_->extern_arg1());
} else { } else {
PLOGW("undefined extern call to %.8llX %s", symbol_info_->address(), PLOGW("undefined extern call to %.8llX %s", symbol_info_->address(),

View File

@ -163,8 +163,8 @@ uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address,
std::lock_guard<std::mutex> lock(interrupt_thread_lock_); std::lock_guard<std::mutex> lock(interrupt_thread_lock_);
// Set 0x10C(r13) to the current CPU ID. // Set 0x10C(r13) to the current CPU ID.
uint8_t* p = memory_->membase(); poly::store_and_swap<uint8_t>(
poly::store_and_swap<uint8_t>(p + interrupt_thread_block_ + 0x10C, cpu); memory_->TranslateVirtual(interrupt_thread_block_ + 0x10C), cpu);
// Execute interrupt. // Execute interrupt.
uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count); uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count);

View File

@ -30,8 +30,8 @@ int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) {
// Allocate memory. // Allocate memory.
// Since we have no real heap just load it wherever. // Since we have no real heap just load it wherever.
base_address_ = base_address; base_address_ = base_address;
uint8_t* p = memory_->Translate(base_address_); uint8_t* p = memory_->TranslateVirtual(base_address_);
memset(p, 0, file_length); std::memset(p, 0, file_length);
// Read into memory. // Read into memory.
fread(p, file_length, 1, file); fread(p, file_length, 1, file);

View File

@ -29,7 +29,6 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
thread_id_(thread_id), thread_id_(thread_id),
name_(""), name_(""),
backend_data_(0), backend_data_(0),
raw_context_(0),
stack_size_(stack_size), stack_size_(stack_size),
thread_state_address_(thread_state_address) { thread_state_address_(thread_state_address) {
if (thread_id_ == UINT_MAX) { if (thread_id_ == UINT_MAX) {
@ -50,13 +49,16 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
assert_not_zero(stack_address_); assert_not_zero(stack_address_);
// Allocate with 64b alignment. // Allocate with 64b alignment.
context_ = (PPCContext*)calloc(1, sizeof(PPCContext)); context_ =
assert_true(((uint64_t)context_ & 0xF) == 0); reinterpret_cast<PPCContext*>(_aligned_malloc(sizeof(PPCContext), 64));
assert_true(((uint64_t)context_ & 0x3F) == 0);
std::memset(context_, 0, sizeof(PPCContext));
// Stash pointers to common structures that callbacks may need. // Stash pointers to common structures that callbacks may need.
context_->reserve_address = memory_->reserve_address(); context_->reserve_address = memory_->reserve_address();
context_->reserve_value = memory_->reserve_value(); context_->reserve_value = memory_->reserve_value();
context_->membase = memory_->membase(); context_->virtual_membase = memory_->virtual_membase();
context_->physical_membase = memory_->physical_membase();
context_->runtime = runtime; context_->runtime = runtime;
context_->thread_state = this; context_->thread_state = this;
context_->thread_id = thread_id_; context_->thread_id = thread_id_;
@ -69,8 +71,6 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id,
// 16 to 32b. // 16 to 32b.
context_->r[1] -= 64; context_->r[1] -= 64;
raw_context_ = context_;
runtime_->debugger()->OnThreadCreated(this); runtime_->debugger()->OnThreadCreated(this);
} }
@ -84,7 +84,7 @@ ThreadState::~ThreadState() {
thread_state_ = nullptr; thread_state_ = nullptr;
} }
free(context_); _aligned_free(context_);
if (stack_allocated_) { if (stack_allocated_) {
memory()->SystemHeapFree(stack_address_); memory()->SystemHeapFree(stack_address_);
} }

View File

@ -38,7 +38,6 @@ class ThreadState {
const std::string& name() const { return name_; } const std::string& name() const { return name_; }
void set_name(const std::string& value) { name_ = value; } void set_name(const std::string& value) { name_ = value; }
void* backend_data() const { return backend_data_; } void* backend_data() const { return backend_data_; }
void* raw_context() const { return raw_context_; }
uint32_t stack_address() const { return stack_address_; } uint32_t stack_address() const { return stack_address_; }
size_t stack_size() const { return stack_size_; } size_t stack_size() const { return stack_size_; }
uint32_t thread_state_address() const { return thread_state_address_; } uint32_t thread_state_address() const { return thread_state_address_; }
@ -60,7 +59,6 @@ class ThreadState {
uint32_t thread_id_; uint32_t thread_id_;
std::string name_; std::string name_;
void* backend_data_; void* backend_data_;
void* raw_context_;
uint32_t stack_address_; uint32_t stack_address_;
bool stack_allocated_; bool stack_allocated_;
uint32_t stack_size_; uint32_t stack_size_;

View File

@ -99,8 +99,6 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
return 1; return 1;
} }
uint8_t* membase = memory_->membase();
char name[128]; char name[128];
for (size_t n = 0; n < import_info_count; n++) { for (size_t n = 0; n < import_info_count; n++) {
const xe_xex2_import_info_t* info = &import_infos[n]; const xe_xex2_import_info_t* info = &import_infos[n];
@ -129,7 +127,7 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
// Grab, if available. // Grab, if available.
if (kernel_export) { if (kernel_export) {
uint32_t* slot = (uint32_t*)(membase + info->value_address); auto slot = memory_->TranslateVirtual<uint32_t*>(info->value_address);
if (kernel_export->type == KernelExport::Function) { if (kernel_export->type == KernelExport::Function) {
// Not exactly sure what this should be... // Not exactly sure what this should be...
if (info->thunk_address) { if (info->thunk_address) {
@ -176,7 +174,7 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) {
// blr // blr
// nop // nop
// nop // nop
uint8_t* p = memory()->Translate(info->thunk_address); uint8_t* p = memory()->TranslateVirtual(info->thunk_address);
poly::store_and_swap<uint32_t>(p + 0x0, 0x44000002); poly::store_and_swap<uint32_t>(p + 0x0, 0x44000002);
poly::store_and_swap<uint32_t>(p + 0x4, 0x4E800020); poly::store_and_swap<uint32_t>(p + 0x4, 0x4E800020);
poly::store_and_swap<uint32_t>(p + 0x8, 0x60000000); poly::store_and_swap<uint32_t>(p + 0x8, 0x60000000);

View File

@ -202,7 +202,7 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base()); auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base());
if (ev) { if (ev) {
ev->type = xdb::protocol::EventType::PROCESS_START; ev->type = xdb::protocol::EventType::PROCESS_START;
ev->membase = reinterpret_cast<uint64_t>(memory()->membase()); ev->membase = reinterpret_cast<uint64_t>(memory()->virtual_membase());
auto path_length = poly::to_string(path) auto path_length = poly::to_string(path)
.copy(ev->launch_path, sizeof(ev->launch_path) - 1); .copy(ev->launch_path, sizeof(ev->launch_path) - 1);
ev->launch_path[path_length] = 0; ev->launch_path[path_length] = 0;

View File

@ -51,10 +51,9 @@ CommandProcessor::CachedPipeline::~CachedPipeline() {
CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system) CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system)
: memory_(graphics_system->memory()), : memory_(graphics_system->memory()),
membase_(graphics_system->memory()->membase()),
graphics_system_(graphics_system), graphics_system_(graphics_system),
register_file_(graphics_system_->register_file()), register_file_(graphics_system_->register_file()),
trace_writer_(graphics_system->memory()->membase()), trace_writer_(graphics_system->memory()->physical_membase()),
trace_state_(TraceState::kDisabled), trace_state_(TraceState::kDisabled),
worker_running_(true), worker_running_(true),
swap_mode_(SwapMode::kNormal), swap_mode_(SwapMode::kNormal),
@ -212,8 +211,8 @@ void CommandProcessor::WorkerMain() {
// TODO(benvanik): use reader->Read_update_freq_ and only issue after moving // TODO(benvanik): use reader->Read_update_freq_ and only issue after moving
// that many indices. // that many indices.
if (read_ptr_writeback_ptr_) { if (read_ptr_writeback_ptr_) {
poly::store_and_swap<uint32_t>(membase_ + read_ptr_writeback_ptr_, poly::store_and_swap<uint32_t>(
read_ptr_index_); memory_->TranslatePhysical(read_ptr_writeback_ptr_), read_ptr_index_);
} }
} }
@ -488,7 +487,7 @@ void CommandProcessor::WriteRegister(uint32_t index, uint32_t value) {
// Enabled - write to address. // Enabled - write to address.
uint32_t scratch_addr = regs->values[XE_GPU_REG_SCRATCH_ADDR].u32; uint32_t scratch_addr = regs->values[XE_GPU_REG_SCRATCH_ADDR].u32;
uint32_t mem_addr = scratch_addr + (scratch_reg * 4); uint32_t mem_addr = scratch_addr + (scratch_reg * 4);
poly::store_and_swap<uint32_t>(membase_ + xenos::GpuToCpu(mem_addr), poly::store_and_swap<uint32_t>(memory_->TranslatePhysical(mem_addr),
value); value);
} }
} }
@ -651,8 +650,8 @@ void CommandProcessor::ExecutePrimaryBuffer(uint32_t start_index,
// Execute commands! // Execute commands!
uint32_t ptr_mask = (primary_buffer_size_ / sizeof(uint32_t)) - 1; uint32_t ptr_mask = (primary_buffer_size_ / sizeof(uint32_t)) - 1;
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, start_ptr, RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
end_ptr); ptr_mask, start_ptr, end_ptr);
while (reader.can_read()) { while (reader.can_read()) {
ExecutePacket(&reader); ExecutePacket(&reader);
} }
@ -670,8 +669,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) {
// Execute commands! // Execute commands!
uint32_t ptr_mask = 0; uint32_t ptr_mask = 0;
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr, RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
ptr + length * sizeof(uint32_t)); ptr_mask, ptr, ptr + length * sizeof(uint32_t));
while (reader.can_read()) { while (reader.can_read()) {
ExecutePacket(&reader); ExecutePacket(&reader);
} }
@ -681,8 +680,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) {
void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) { void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) {
uint32_t ptr_mask = 0; uint32_t ptr_mask = 0;
RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr, RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_,
ptr + count * sizeof(uint32_t)); ptr_mask, ptr, ptr + count * sizeof(uint32_t));
while (reader.can_read()) { while (reader.can_read()) {
ExecutePacket(&reader); ExecutePacket(&reader);
} }
@ -992,7 +991,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingbufferReader* reader,
// Memory. // Memory.
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3); auto endianness = static_cast<Endian>(poll_reg_addr & 0x3);
poll_reg_addr &= ~0x3; poll_reg_addr &= ~0x3;
value = poly::load<uint32_t>(membase_ + GpuToCpu(poll_reg_addr)); value = poly::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
value = GpuSwap(value, endianness); value = GpuSwap(value, endianness);
trace_writer_.WriteMemoryRead(poll_reg_addr, 4); trace_writer_.WriteMemoryRead(poll_reg_addr, 4);
} else { } else {
@ -1095,7 +1094,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3); auto endianness = static_cast<Endian>(poll_reg_addr & 0x3);
poll_reg_addr &= ~0x3; poll_reg_addr &= ~0x3;
trace_writer_.WriteMemoryRead(poll_reg_addr, 4); trace_writer_.WriteMemoryRead(poll_reg_addr, 4);
value = poly::load<uint32_t>(membase_ + GpuToCpu(poll_reg_addr)); value = poly::load<uint32_t>(memory_->TranslatePhysical(poll_reg_addr));
value = GpuSwap(value, endianness); value = GpuSwap(value, endianness);
} else { } else {
// Register. // Register.
@ -1136,7 +1135,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
auto endianness = static_cast<Endian>(write_reg_addr & 0x3); auto endianness = static_cast<Endian>(write_reg_addr & 0x3);
write_reg_addr &= ~0x3; write_reg_addr &= ~0x3;
write_data = GpuSwap(write_data, endianness); write_data = GpuSwap(write_data, endianness);
poly::store(membase_ + GpuToCpu(write_reg_addr), write_data); poly::store(memory_->TranslatePhysical(write_reg_addr), write_data);
trace_writer_.WriteMemoryWrite(write_reg_addr, 4); trace_writer_.WriteMemoryWrite(write_reg_addr, 4);
} else { } else {
// Register. // Register.
@ -1182,7 +1181,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_SHD(
auto endianness = static_cast<Endian>(address & 0x3); auto endianness = static_cast<Endian>(address & 0x3);
address &= ~0x3; address &= ~0x3;
data_value = GpuSwap(data_value, endianness); data_value = GpuSwap(data_value, endianness);
poly::store(membase_ + GpuToCpu(address), data_value); poly::store(memory_->TranslatePhysical(address), data_value);
trace_writer_.WriteMemoryWrite(address, 4); trace_writer_.WriteMemoryWrite(address, 4);
return true; return true;
} }
@ -1207,7 +1206,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT(
}; };
assert_true(endianness == xenos::Endian::k8in16); assert_true(endianness == xenos::Endian::k8in16);
poly::copy_and_swap_16_aligned( poly::copy_and_swap_16_aligned(
reinterpret_cast<uint16_t*>(membase_ + GpuToCpu(address)), extents, reinterpret_cast<uint16_t*>(memory_->TranslatePhysical(address)), extents,
poly::countof(extents)); poly::countof(extents));
trace_writer_.WriteMemoryWrite(address, sizeof(extents)); trace_writer_.WriteMemoryWrite(address, sizeof(extents));
return true; return true;
@ -1367,8 +1366,8 @@ bool CommandProcessor::ExecutePacketType3_LOAD_ALU_CONSTANT(
} }
trace_writer_.WriteMemoryRead(address, size_dwords * 4); trace_writer_.WriteMemoryRead(address, size_dwords * 4);
for (uint32_t n = 0; n < size_dwords; n++, index++) { for (uint32_t n = 0; n < size_dwords; n++, index++) {
uint32_t data = uint32_t data = poly::load_and_swap<uint32_t>(
poly::load_and_swap<uint32_t>(membase_ + GpuToCpu(address + n * 4)); memory_->TranslatePhysical(address + n * 4));
WriteRegister(index, data); WriteRegister(index, data);
} }
return true; return true;
@ -1397,8 +1396,7 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingbufferReader* reader,
uint32_t size_dwords = start_size & 0xFFFF; // dwords uint32_t size_dwords = start_size & 0xFFFF; // dwords
assert_true(start == 0); assert_true(start == 0);
trace_writer_.WriteMemoryRead(addr, size_dwords * 4); trace_writer_.WriteMemoryRead(addr, size_dwords * 4);
LoadShader(shader_type, LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(addr),
reinterpret_cast<uint32_t*>(membase_ + GpuToCpu(addr)),
size_dwords); size_dwords);
return true; return true;
} }
@ -1414,8 +1412,8 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE(
uint32_t size_dwords = start_size & 0xFFFF; // dwords uint32_t size_dwords = start_size & 0xFFFF; // dwords
assert_true(start == 0); assert_true(start == 0);
reader->CheckRead(size_dwords); reader->CheckRead(size_dwords);
LoadShader(shader_type, reinterpret_cast<uint32_t*>(membase_ + reader->ptr()), LoadShader(shader_type, reader->ptr(),
size_dwords); memory_->TranslatePhysical<uint32_t*>(reader->ptr()), size_dwords);
reader->Advance(size_dwords); reader->Advance(size_dwords);
return true; return true;
} }
@ -1429,11 +1427,12 @@ bool CommandProcessor::ExecutePacketType3_INVALIDATE_STATE(
} }
bool CommandProcessor::LoadShader(ShaderType shader_type, bool CommandProcessor::LoadShader(ShaderType shader_type,
const uint32_t* address, uint32_t guest_address,
const uint32_t* host_address,
uint32_t dword_count) { uint32_t dword_count) {
// Hash the input memory and lookup the shader. // Hash the input memory and lookup the shader.
GL4Shader* shader_ptr = nullptr; GL4Shader* shader_ptr = nullptr;
uint64_t hash = XXH64(address, dword_count * sizeof(uint32_t), 0); uint64_t hash = XXH64(host_address, dword_count * sizeof(uint32_t), 0);
auto it = shader_cache_.find(hash); auto it = shader_cache_.find(hash);
if (it != shader_cache_.end()) { if (it != shader_cache_.end()) {
// Found in the cache. // Found in the cache.
@ -1442,17 +1441,16 @@ bool CommandProcessor::LoadShader(ShaderType shader_type,
} else { } else {
// Not found in cache. // Not found in cache.
// No translation is performed here, as it depends on program_cntl. // No translation is performed here, as it depends on program_cntl.
auto shader = auto shader = std::make_unique<GL4Shader>(shader_type, hash, host_address,
std::make_unique<GL4Shader>(shader_type, hash, address, dword_count); dword_count);
shader_ptr = shader.get(); shader_ptr = shader.get();
shader_cache_.insert({hash, shader_ptr}); shader_cache_.insert({hash, shader_ptr});
all_shaders_.emplace_back(std::move(shader)); all_shaders_.emplace_back(std::move(shader));
XELOGGPU("Set %s shader at %0.8X (%db):\n%s", XELOGGPU("Set %s shader at %0.8X (%db):\n%s",
shader_type == ShaderType::kVertex ? "vertex" : "pixel", shader_type == ShaderType::kVertex ? "vertex" : "pixel",
uint32_t(reinterpret_cast<uintptr_t>(address) - guest_address, dword_count * 4,
reinterpret_cast<uintptr_t>(membase_)), shader_ptr->ucode_disassembly().c_str());
dword_count * 4, shader_ptr->ucode_disassembly().c_str());
} }
switch (shader_type) { switch (shader_type) {
case ShaderType::kVertex: case ShaderType::kVertex:
@ -2299,11 +2297,11 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateIndexBuffer() {
&allocation)) { &allocation)) {
if (info.format == IndexFormat::kInt32) { if (info.format == IndexFormat::kInt32) {
auto dest = reinterpret_cast<uint32_t*>(allocation.host_ptr); auto dest = reinterpret_cast<uint32_t*>(allocation.host_ptr);
auto src = reinterpret_cast<const uint32_t*>(membase_ + info.guest_base); auto src = memory_->TranslatePhysical<const uint32_t*>(info.guest_base);
poly::copy_and_swap_32_aligned(dest, src, info.count); poly::copy_and_swap_32_aligned(dest, src, info.count);
} else { } else {
auto dest = reinterpret_cast<uint16_t*>(allocation.host_ptr); auto dest = reinterpret_cast<uint16_t*>(allocation.host_ptr);
auto src = reinterpret_cast<const uint16_t*>(membase_ + info.guest_base); auto src = memory_->TranslatePhysical<const uint16_t*>(info.guest_base);
poly::copy_and_swap_16_aligned(dest, src, info.count); poly::copy_and_swap_16_aligned(dest, src, info.count);
} }
draw_batcher_.set_index_buffer(allocation); draw_batcher_.set_index_buffer(allocation);
@ -2357,7 +2355,7 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateVertexBuffers() {
// it (and if it matches just discard and reuse). // it (and if it matches just discard and reuse).
poly::copy_and_swap_32_aligned( poly::copy_and_swap_32_aligned(
reinterpret_cast<uint32_t*>(allocation.host_ptr), reinterpret_cast<uint32_t*>(allocation.host_ptr),
reinterpret_cast<const uint32_t*>(membase_ + (fetch->address << 2)), memory_->TranslatePhysical<const uint32_t*>(fetch->address << 2),
valid_range / 4); valid_range / 4);
if (!has_bindless_vbos_) { if (!has_bindless_vbos_) {
@ -2697,7 +2695,7 @@ bool CommandProcessor::IssueCopy() {
assert_true(fetch->type == 3); assert_true(fetch->type == 3);
assert_true(fetch->endian == 2); assert_true(fetch->endian == 2);
assert_true(fetch->size == 6); assert_true(fetch->size == 6);
const uint8_t* vertex_addr = membase_ + (fetch->address << 2); const uint8_t* vertex_addr = memory_->TranslatePhysical(fetch->address << 2);
trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4); trace_writer_.WriteMemoryRead(fetch->address << 2, fetch->size * 4);
int32_t dest_min_x = int32_t((std::min( int32_t dest_min_x = int32_t((std::min(
std::min( std::min(
@ -2734,7 +2732,7 @@ bool CommandProcessor::IssueCopy() {
// Destination pointer in guest memory. // Destination pointer in guest memory.
// We have GL throw bytes directly into it. // We have GL throw bytes directly into it.
// TODO(benvanik): copy to staging texture then PBO back? // TODO(benvanik): copy to staging texture then PBO back?
void* ptr = membase_ + GpuToCpu(copy_dest_base); void* ptr = memory_->TranslatePhysical(copy_dest_base);
// Make active so glReadPixels reads from us. // Make active so glReadPixels reads from us.
switch (copy_command) { switch (copy_command) {

View File

@ -193,8 +193,8 @@ class CommandProcessor {
bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader, bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader,
uint32_t packet, uint32_t count); uint32_t packet, uint32_t count);
bool LoadShader(ShaderType shader_type, const uint32_t* address, bool LoadShader(ShaderType shader_type, uint32_t guest_address,
uint32_t dword_count); const uint32_t* host_address, uint32_t dword_count);
bool IssueDraw(); bool IssueDraw();
UpdateStatus UpdateShaders(PrimitiveType prim_type); UpdateStatus UpdateShaders(PrimitiveType prim_type);
@ -214,7 +214,6 @@ class CommandProcessor {
GLuint depth_target); GLuint depth_target);
Memory* memory_; Memory* memory_;
uint8_t* membase_;
GL4GraphicsSystem* graphics_system_; GL4GraphicsSystem* graphics_system_;
RegisterFile* register_file_; RegisterFile* register_file_;

View File

@ -181,7 +181,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
case TraceCommandType::kPacketStart: { case TraceCommandType::kPacketStart: {
auto cmd = reinterpret_cast<const PacketStartCommand*>(trace_ptr); auto cmd = reinterpret_cast<const PacketStartCommand*>(trace_ptr);
trace_ptr += sizeof(*cmd); trace_ptr += sizeof(*cmd);
std::memcpy(memory()->Translate(cmd->base_ptr), trace_ptr, std::memcpy(memory()->TranslatePhysical(cmd->base_ptr), trace_ptr,
cmd->count * 4); cmd->count * 4);
trace_ptr += cmd->count * 4; trace_ptr += cmd->count * 4;
pending_packet = cmd; pending_packet = cmd;
@ -203,7 +203,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
case TraceCommandType::kMemoryRead: { case TraceCommandType::kMemoryRead: {
auto cmd = reinterpret_cast<const MemoryReadCommand*>(trace_ptr); auto cmd = reinterpret_cast<const MemoryReadCommand*>(trace_ptr);
trace_ptr += sizeof(*cmd); trace_ptr += sizeof(*cmd);
std::memcpy(memory()->Translate(cmd->base_ptr), trace_ptr, std::memcpy(memory()->TranslatePhysical(cmd->base_ptr), trace_ptr,
cmd->length); cmd->length);
trace_ptr += cmd->length; trace_ptr += cmd->length;
break; break;

View File

@ -676,7 +676,8 @@ void TextureSwap(Endian endianness, void* dest, const void* src,
bool TextureCache::UploadTexture2D(GLuint texture, bool TextureCache::UploadTexture2D(GLuint texture,
const TextureInfo& texture_info) { const TextureInfo& texture_info) {
const auto host_address = memory_->Translate(texture_info.guest_address); const auto host_address =
memory_->TranslatePhysical(texture_info.guest_address);
const auto& config = const auto& config =
texture_configs[uint32_t(texture_info.format_info->format)]; texture_configs[uint32_t(texture_info.format_info->format)];
@ -778,7 +779,8 @@ bool TextureCache::UploadTexture2D(GLuint texture,
bool TextureCache::UploadTextureCube(GLuint texture, bool TextureCache::UploadTextureCube(GLuint texture,
const TextureInfo& texture_info) { const TextureInfo& texture_info) {
const auto host_address = memory_->Translate(texture_info.guest_address); const auto host_address =
memory_->TranslatePhysical(texture_info.guest_address);
const auto& config = const auto& config =
texture_configs[uint32_t(texture_info.format_info->format)]; texture_configs[uint32_t(texture_info.format_info->format)];

View File

@ -832,7 +832,7 @@ class TracePlayer : public TraceReader {
}; };
void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player, void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player,
uint8_t* membase) { Memory* memory) {
ImGui::SetNextWindowPos(ImVec2(5, 5), ImGuiSetCondition_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(5, 5), ImGuiSetCondition_FirstUseEver);
if (!ImGui::Begin("Controller", nullptr, ImVec2(340, 60))) { if (!ImGui::Begin("Controller", nullptr, ImVec2(340, 60))) {
ImGui::End(); ImGui::End();
@ -871,7 +871,7 @@ void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player,
} }
void DrawCommandListUI(xe::ui::MainWindow* window, TracePlayer& player, void DrawCommandListUI(xe::ui::MainWindow* window, TracePlayer& player,
uint8_t* membase) { Memory* memory) {
ImGui::SetNextWindowPos(ImVec2(5, 70), ImGuiSetCondition_FirstUseEver); ImGui::SetNextWindowPos(ImVec2(5, 70), ImGuiSetCondition_FirstUseEver);
if (!ImGui::Begin("Command List", nullptr, ImVec2(200, 640))) { if (!ImGui::Begin("Command List", nullptr, ImVec2(200, 640))) {
ImGui::End(); ImGui::End();
@ -1013,7 +1013,7 @@ ShaderDisplayType DrawShaderTypeUI() {
} }
void DrawShaderUI(xe::ui::MainWindow* window, TracePlayer& player, void DrawShaderUI(xe::ui::MainWindow* window, TracePlayer& player,
uint8_t* membase, gl4::GL4Shader* shader, Memory* memory, gl4::GL4Shader* shader,
ShaderDisplayType display_type) { ShaderDisplayType display_type) {
// Must be prepared for advanced display modes. // Must be prepared for advanced display modes.
if (display_type != ShaderDisplayType::kUcode) { if (display_type != ShaderDisplayType::kUcode) {
@ -1166,10 +1166,10 @@ void DrawTextureInfo(TracePlayer& player, const Shader::SamplerDesc& desc) {
ImGui::Columns(1); ImGui::Columns(1);
} }
void DrawVertexFetcher(const uint8_t* membase, gl4::GL4Shader* shader, void DrawVertexFetcher(const Memory* memory, gl4::GL4Shader* shader,
const Shader::BufferDesc& desc, const Shader::BufferDesc& desc,
const xe_gpu_vertex_fetch_t* fetch) { const xe_gpu_vertex_fetch_t* fetch) {
const uint8_t* addr = membase + (fetch->address << 2); const uint8_t* addr = memory->TranslatePhysical(fetch->address << 2);
uint32_t vertex_count = (fetch->size * 4) / desc.stride_words; uint32_t vertex_count = (fetch->size * 4) / desc.stride_words;
int column_count = 0; int column_count = 0;
for (uint32_t el_index = 0; el_index < desc.element_count; ++el_index) { for (uint32_t el_index = 0; el_index < desc.element_count; ++el_index) {
@ -1379,7 +1379,7 @@ static const char* kEndiannessNames[] = {
}; };
void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player, void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
uint8_t* membase) { Memory* memory) {
auto gs = static_cast<gl4::GL4GraphicsSystem*>(player.graphics_system()); auto gs = static_cast<gl4::GL4GraphicsSystem*>(player.graphics_system());
auto cp = gs->command_processor(); auto cp = gs->command_processor();
auto& regs = *gs->register_file(); auto& regs = *gs->register_file();
@ -1809,7 +1809,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
ImGui::BeginChild("#vertex_shader_text", ImVec2(0, 400)); ImGui::BeginChild("#vertex_shader_text", ImVec2(0, 400));
auto shader = cp->active_vertex_shader(); auto shader = cp->active_vertex_shader();
if (shader) { if (shader) {
DrawShaderUI(window, player, membase, shader, shader_display_type); DrawShaderUI(window, player, memory, shader, shader_display_type);
} else { } else {
ImGui::TextColored(kColorError, "ERROR: no vertex shader set"); ImGui::TextColored(kColorError, "ERROR: no vertex shader set");
} }
@ -1820,7 +1820,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
ImGui::BeginChild("#pixel_shader_text", ImVec2(0, 400)); ImGui::BeginChild("#pixel_shader_text", ImVec2(0, 400));
auto shader = cp->active_pixel_shader(); auto shader = cp->active_pixel_shader();
if (shader) { if (shader) {
DrawShaderUI(window, player, membase, shader, shader_display_type); DrawShaderUI(window, player, memory, shader, shader_display_type);
} else { } else {
ImGui::TextColored(kColorError, "ERROR: no pixel shader set"); ImGui::TextColored(kColorError, "ERROR: no pixel shader set");
} }
@ -1864,10 +1864,10 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
ImGui::NextColumn(); ImGui::NextColumn();
ImGui::Separator(); ImGui::Separator();
} }
size_t element_size = uint32_t element_size =
draw_info.index_format == IndexFormat::kInt32 ? 4 : 2; draw_info.index_format == IndexFormat::kInt32 ? 4 : 2;
const uint8_t* data_ptr = const uint8_t* data_ptr = memory->TranslatePhysical(
membase + draw_info.index_buffer_ptr + (display_start * element_size); draw_info.index_buffer_ptr + (display_start * element_size));
for (int i = display_start; i < display_end; for (int i = display_start; i < display_end;
++i, data_ptr += element_size) { ++i, data_ptr += element_size) {
if (i < 10) { if (i < 10) {
@ -1927,7 +1927,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
fetch->size * 4, fetch->size * 4,
kEndiannessNames[int(fetch->endian)])) { kEndiannessNames[int(fetch->endian)])) {
ImGui::BeginChild("#vertices", ImVec2(0, 300)); ImGui::BeginChild("#vertices", ImVec2(0, 300));
DrawVertexFetcher(membase, shader, desc, fetch); DrawVertexFetcher(memory, shader, desc, fetch);
ImGui::EndChild(); ImGui::EndChild();
ImGui::TreePop(); ImGui::TreePop();
} }
@ -2019,7 +2019,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player,
} }
void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player, void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player,
uint8_t* membase) { Memory* memory) {
ImGui::SetNextWindowCollapsed(true, ImGuiSetCondition_FirstUseEver); ImGui::SetNextWindowCollapsed(true, ImGuiSetCondition_FirstUseEver);
ImGui::SetNextWindowPos(ImVec2(float(window->width()) - 500 - 5, 5), ImGui::SetNextWindowPos(ImVec2(float(window->width()) - 500 - 5, 5),
ImGuiSetCondition_FirstUseEver); ImGuiSetCondition_FirstUseEver);
@ -2160,13 +2160,13 @@ void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player,
ImGui::End(); ImGui::End();
} }
void DrawUI(xe::ui::MainWindow* window, TracePlayer& player, uint8_t* membase) { void DrawUI(xe::ui::MainWindow* window, TracePlayer& player, Memory* memory) {
ImGui::ShowTestWindow(); ImGui::ShowTestWindow();
DrawControllerUI(window, player, membase); DrawControllerUI(window, player, memory);
DrawCommandListUI(window, player, membase); DrawCommandListUI(window, player, memory);
DrawStateUI(window, player, membase); DrawStateUI(window, player, memory);
DrawPacketDisassemblerUI(window, player, membase); DrawPacketDisassemblerUI(window, player, memory);
} }
void ImImpl_Setup(); void ImImpl_Setup();
@ -2276,7 +2276,7 @@ int trace_viewer_main(std::vector<std::wstring>& args) {
ImGui::NewFrame(); ImGui::NewFrame();
DrawUI(window, player, emulator->memory()->membase()); DrawUI(window, player, emulator->memory());
glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y);
ImGui::Render(); ImGui::Render();

View File

@ -16,8 +16,8 @@ namespace kernel {
XApp::XApp(KernelState* kernel_state, uint32_t app_id) XApp::XApp(KernelState* kernel_state, uint32_t app_id)
: kernel_state_(kernel_state), : kernel_state_(kernel_state),
app_id_(app_id), memory_(kernel_state->memory()),
membase_(kernel_state->memory()->membase()) {} app_id_(app_id) {}
void XAppManager::RegisterApp(std::unique_ptr<XApp> app) { void XAppManager::RegisterApp(std::unique_ptr<XApp> app) {
assert_zero(app_lookup_.count(app->app_id())); assert_zero(app_lookup_.count(app->app_id()));

View File

@ -33,8 +33,8 @@ class XApp {
XApp(KernelState* kernel_state, uint32_t app_id); XApp(KernelState* kernel_state, uint32_t app_id);
KernelState* kernel_state_; KernelState* kernel_state_;
Memory* memory_;
uint32_t app_id_; uint32_t app_id_;
uint8_t* membase_;
}; };
class XAppManager { class XAppManager {

View File

@ -22,6 +22,7 @@ XXGIApp::XXGIApp(KernelState* kernel_state) : XApp(kernel_state, 0xFB) {}
X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
uint32_t buffer_length) { uint32_t buffer_length) {
// NOTE: buffer_length may be zero or valid. // NOTE: buffer_length may be zero or valid.
auto buffer = memory_->TranslateVirtual(buffer_ptr);
switch (message) { switch (message) {
case 0x000B0006: { case 0x000B0006: {
assert_true(!buffer_length || buffer_length == 24); assert_true(!buffer_length || buffer_length == 24);
@ -30,35 +31,26 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
// qword 0 // qword 0
// dword r4 context enum // dword r4 context enum
// dword r5 value // dword r5 value
uint32_t user_index = uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t context_id = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t context_id = uint32_t context_value = poly::load_and_swap<uint32_t>(buffer + 20);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t context_value =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
XELOGD("XUserSetContextEx(%.8X, %.8X, %.8X)", user_index, context_id, XELOGD("XUserSetContextEx(%.8X, %.8X, %.8X)", user_index, context_id,
context_value); context_value);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x000B0007: { case 0x000B0007: {
uint32_t user_index = uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t property_id = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t property_id = uint32_t value_size = poly::load_and_swap<uint32_t>(buffer + 20);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16); uint32_t value_ptr = poly::load_and_swap<uint32_t>(buffer + 24);
uint32_t value_size =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
uint32_t value_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 24);
XELOGD("XUserSetPropertyEx(%.8X, %.8X, %d, %.8X)", user_index, XELOGD("XUserSetPropertyEx(%.8X, %.8X, %d, %.8X)", user_index,
property_id, value_size, value_ptr); property_id, value_size, value_ptr);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x000B0008: { case 0x000B0008: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t achievement_count = uint32_t achievement_count = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t achievements_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t achievements_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
XELOGD("XUserWriteAchievements(%.8X, %.8X)", achievement_count, XELOGD("XUserWriteAchievements(%.8X, %.8X)", achievement_count,
achievements_ptr); achievements_ptr);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
@ -76,16 +68,14 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
case 0x000B0041: { case 0x000B0041: {
assert_true(!buffer_length || buffer_length == 32); assert_true(!buffer_length || buffer_length == 32);
// 00000000 2789fecc 00000000 00000000 200491e0 00000000 200491f0 20049340 // 00000000 2789fecc 00000000 00000000 200491e0 00000000 200491f0 20049340
uint32_t user_index = uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t context_ptr = poly::load_and_swap<uint32_t>(buffer + 16);
uint32_t context_ptr = auto context = memory_->TranslateVirtual(context_ptr);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16); uint32_t context_id = poly::load_and_swap<uint32_t>(context + 0);
uint32_t context_id =
poly::load_and_swap<uint32_t>(membase_ + context_ptr + 0);
XELOGD("XUserGetContext(%.8X, %.8X(%.8X))", user_index, context_ptr, XELOGD("XUserGetContext(%.8X, %.8X(%.8X))", user_index, context_ptr,
context_id); context_id);
uint32_t value = 0; uint32_t value = 0;
poly::store_and_swap<uint32_t>(membase_ + context_ptr + 4, value); poly::store_and_swap<uint32_t>(context + 4, value);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x000B0071: { case 0x000B0071: {

View File

@ -24,12 +24,13 @@ X_RESULT XXLiveBaseApp::DispatchMessageSync(uint32_t message,
uint32_t buffer_ptr, uint32_t buffer_ptr,
uint32_t buffer_length) { uint32_t buffer_length) {
// NOTE: buffer_length may be zero or valid. // NOTE: buffer_length may be zero or valid.
auto buffer = memory_->TranslateVirtual(buffer_ptr);
switch (message) { switch (message) {
case 0x00058004: { case 0x00058004: {
// Called on startup, seems to just return a bool in the buffer. // Called on startup, seems to just return a bool in the buffer.
assert_true(!buffer_length || buffer_length == 4); assert_true(!buffer_length || buffer_length == 4);
XELOGD("XLiveBaseGetLogonId(%.8X)", buffer_ptr); XELOGD("XLiveBaseGetLogonId(%.8X)", buffer_ptr);
poly::store_and_swap<uint32_t>(membase_ + buffer_ptr + 0, 1); // ? poly::store_and_swap<uint32_t>(buffer + 0, 1); // ?
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x00058020: { case 0x00058020: {

View File

@ -34,7 +34,7 @@ X_RESULT XXMPApp::XMPGetStatus(uint32_t state_ptr) {
Sleep(1); Sleep(1);
XELOGD("XMPGetStatus(%.8X)", state_ptr); XELOGD("XMPGetStatus(%.8X)", state_ptr);
poly::store_and_swap<uint32_t>(membase_ + state_ptr, poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(state_ptr),
static_cast<uint32_t>(state_)); static_cast<uint32_t>(state_));
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
@ -54,30 +54,32 @@ X_RESULT XXMPApp::XMPCreateTitlePlaylist(
for (uint32_t i = 0; i < song_count; ++i) { for (uint32_t i = 0; i < song_count; ++i) {
auto song = std::make_unique<Song>(); auto song = std::make_unique<Song>();
song->handle = ++next_song_handle_; song->handle = ++next_song_handle_;
uint8_t* song_base = membase_ + songs_ptr + (i * 36); uint8_t* song_base = memory_->TranslateVirtual(songs_ptr + (i * 36));
song->file_path = poly::load_and_swap<std::wstring>( song->file_path =
membase_ + poly::load_and_swap<uint32_t>(song_base + 0)); poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->name = poly::load_and_swap<std::wstring>( poly::load_and_swap<uint32_t>(song_base + 0)));
membase_ + poly::load_and_swap<uint32_t>(song_base + 4)); song->name = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->artist = poly::load_and_swap<std::wstring>( poly::load_and_swap<uint32_t>(song_base + 4)));
membase_ + poly::load_and_swap<uint32_t>(song_base + 8)); song->artist = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->album = poly::load_and_swap<std::wstring>( poly::load_and_swap<uint32_t>(song_base + 8)));
membase_ + poly::load_and_swap<uint32_t>(song_base + 12)); song->album = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
song->album_artist = poly::load_and_swap<std::wstring>( poly::load_and_swap<uint32_t>(song_base + 12)));
membase_ + poly::load_and_swap<uint32_t>(song_base + 16)); song->album_artist =
song->genre = poly::load_and_swap<std::wstring>( poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
membase_ + poly::load_and_swap<uint32_t>(song_base + 20)); poly::load_and_swap<uint32_t>(song_base + 16)));
song->genre = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
poly::load_and_swap<uint32_t>(song_base + 20)));
song->track_number = poly::load_and_swap<uint32_t>(song_base + 24); song->track_number = poly::load_and_swap<uint32_t>(song_base + 24);
song->duration_ms = poly::load_and_swap<uint32_t>(song_base + 28); song->duration_ms = poly::load_and_swap<uint32_t>(song_base + 28);
song->format = static_cast<Song::Format>( song->format = static_cast<Song::Format>(
poly::load_and_swap<uint32_t>(song_base + 32)); poly::load_and_swap<uint32_t>(song_base + 32));
if (out_song_handles) { if (out_song_handles) {
poly::store_and_swap<uint32_t>(membase_ + out_song_handles + (i * 4), poly::store_and_swap<uint32_t>(
song->handle); memory_->TranslateVirtual(out_song_handles + (i * 4)), song->handle);
} }
playlist->songs.emplace_back(std::move(song)); playlist->songs.emplace_back(std::move(song));
} }
poly::store_and_swap<uint32_t>(membase_ + out_playlist_handle, poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(out_playlist_handle),
playlist->handle); playlist->handle);
std::lock_guard<std::mutex> lock(mutex_); std::lock_guard<std::mutex> lock(mutex_);
@ -195,64 +197,53 @@ void XXMPApp::OnStateChanged() {
X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
uint32_t buffer_length) { uint32_t buffer_length) {
// NOTE: buffer_length may be zero or valid. // NOTE: buffer_length may be zero or valid.
auto buffer = memory_->TranslateVirtual(buffer_ptr);
switch (message) { switch (message) {
case 0x00070002: { case 0x00070002: {
assert_true(!buffer_length || buffer_length == 12); assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t playlist_handle = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t playlist_handle = uint32_t song_handle = poly::load_and_swap<uint32_t>(buffer + 8); // 0?
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t song_handle =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8); // 0?
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPPlayTitlePlaylist(playlist_handle, song_handle); return XMPPlayTitlePlaylist(playlist_handle, song_handle);
} }
case 0x00070003: { case 0x00070003: {
assert_true(!buffer_length || buffer_length == 4); assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPContinue(); return XMPContinue();
} }
case 0x00070004: { case 0x00070004: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t unk = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPStop(unk); return XMPStop(unk);
} }
case 0x00070005: { case 0x00070005: {
assert_true(!buffer_length || buffer_length == 4); assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPPause(); return XMPPause();
} }
case 0x00070006: { case 0x00070006: {
assert_true(!buffer_length || buffer_length == 4); assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPNext(); return XMPNext();
} }
case 0x00070007: { case 0x00070007: {
assert_true(!buffer_length || buffer_length == 4); assert_true(!buffer_length || buffer_length == 4);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPPrevious(); return XMPPrevious();
} }
case 0x00070008: { case 0x00070008: {
assert_true(!buffer_length || buffer_length == 16); assert_true(!buffer_length || buffer_length == 16);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t playback_mode = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t playback_mode = uint32_t repeat_mode = poly::load_and_swap<uint32_t>(buffer + 8);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); uint32_t flags = poly::load_and_swap<uint32_t>(buffer + 12);
uint32_t repeat_mode =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t flags =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode, XELOGD("XMPSetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode,
repeat_mode, flags); repeat_mode, flags);
@ -264,29 +255,27 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
} }
case 0x00070009: { case 0x00070009: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t state_ptr = poly::load_and_swap<uint32_t>( uint32_t state_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0 buffer + 4); // out ptr to 4b - expect 0
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPGetStatus(state_ptr); return XMPGetStatus(state_ptr);
} }
case 0x0007000B: { case 0x0007000B: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t float_ptr = poly::load_and_swap<uint32_t>( uint32_t float_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - floating point buffer + 4); // out ptr to 4b - floating point
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetVolume(%.8X)", float_ptr); XELOGD("XMPGetVolume(%.8X)", float_ptr);
poly::store_and_swap<float>(membase_ + float_ptr, volume_); poly::store_and_swap<float>(memory_->TranslateVirtual(float_ptr),
volume_);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x0007000C: { case 0x0007000C: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); float float_value = poly::load_and_swap<float>(buffer + 4);
float float_value = poly::load_and_swap<float>(membase_ + buffer_ptr + 4);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
XELOGD("XMPSetVolume(%g)", float_value); XELOGD("XMPSetVolume(%g)", float_value);
volume_ = float_value; volume_ = float_value;
@ -294,27 +283,19 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
} }
case 0x0007000D: { case 0x0007000D: {
assert_true(!buffer_length || buffer_length == 36); assert_true(!buffer_length || buffer_length == 36);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t dummy_alloc_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t dummy_alloc_ptr = uint32_t dummy_alloc_size = poly::load_and_swap<uint32_t>(buffer + 8);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); uint32_t songs_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
uint32_t dummy_alloc_size = uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 16);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8); uint32_t playlist_name_ptr = poly::load_and_swap<uint32_t>(buffer + 20);
uint32_t songs_ptr = uint32_t flags = poly::load_and_swap<uint32_t>(buffer + 24);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
uint32_t song_count =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
uint32_t playlist_name_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
uint32_t flags =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 24);
uint32_t song_handles_ptr = uint32_t song_handles_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 28); // 0? poly::load_and_swap<uint32_t>(buffer + 28); // 0?
uint32_t playlist_handle_ptr = uint32_t playlist_handle_ptr = poly::load_and_swap<uint32_t>(buffer + 32);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 32);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
auto playlist_name = auto playlist_name = poly::load_and_swap<std::wstring>(
poly::load_and_swap<std::wstring>(membase_ + playlist_name_ptr); memory_->TranslateVirtual(playlist_name_ptr));
// dummy_alloc_ptr is the result of a XamAlloc of dummy_alloc_size. // dummy_alloc_ptr is the result of a XamAlloc of dummy_alloc_size.
assert_true(dummy_alloc_size == song_count * 128); assert_true(dummy_alloc_size == song_count * 128);
return XMPCreateTitlePlaylist(songs_ptr, song_count, playlist_name_ptr, return XMPCreateTitlePlaylist(songs_ptr, song_count, playlist_name_ptr,
@ -323,12 +304,10 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
} }
case 0x0007000E: { case 0x0007000E: {
assert_true(!buffer_length || buffer_length == 12); assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t unk_ptr = poly::load_and_swap<uint32_t>(buffer + 4); // 0
uint32_t unk_ptr = uint32_t info_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); // 0 auto info = memory_->TranslateVirtual(info_ptr);
uint32_t info_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
assert_zero(unk_ptr); assert_zero(unk_ptr);
XELOGE("XMPGetInfo?(%.8X, %.8X)", unk_ptr, info_ptr); XELOGE("XMPGetInfo?(%.8X, %.8X)", unk_ptr, info_ptr);
@ -336,41 +315,31 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
return X_ERROR_NOT_FOUND; return X_ERROR_NOT_FOUND;
} }
auto& song = active_playlist_->songs[active_song_index_]; auto& song = active_playlist_->songs[active_song_index_];
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 0, song->handle); poly::store_and_swap<uint32_t>(info + 0, song->handle);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 0, poly::store_and_swap<std::wstring>(info + 4 + 572 + 0, song->name);
song->name); poly::store_and_swap<std::wstring>(info + 4 + 572 + 40, song->artist);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 40, poly::store_and_swap<std::wstring>(info + 4 + 572 + 80, song->album);
song->artist); poly::store_and_swap<std::wstring>(info + 4 + 572 + 120,
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 80,
song->album);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 120,
song->album_artist); song->album_artist);
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 160, poly::store_and_swap<std::wstring>(info + 4 + 572 + 160, song->genre);
song->genre); poly::store_and_swap<uint32_t>(info + 4 + 572 + 200, song->track_number);
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 200, poly::store_and_swap<uint32_t>(info + 4 + 572 + 204, song->duration_ms);
song->track_number); poly::store_and_swap<uint32_t>(info + 4 + 572 + 208,
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 204,
song->duration_ms);
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 208,
static_cast<uint32_t>(song->format)); static_cast<uint32_t>(song->format));
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x00070013: { case 0x00070013: {
assert_true(!buffer_length || buffer_length == 8); assert_true(!buffer_length || buffer_length == 8);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t playlist_handle = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t playlist_handle =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
return XMPDeleteTitlePlaylist(playlist_handle); return XMPDeleteTitlePlaylist(playlist_handle);
} }
case 0x0007001A: { case 0x0007001A: {
assert_true(!buffer_length || buffer_length == 12); assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t unk1 = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t unk1 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); uint32_t enabled = poly::load_and_swap<uint32_t>(buffer + 8);
uint32_t enabled =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
assert_zero(unk1); assert_zero(unk1);
XELOGD("XMPSetEnabled(%.8X, %.8X)", unk1, enabled); XELOGD("XMPSetEnabled(%.8X, %.8X)", unk1, enabled);
@ -383,53 +352,49 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr,
} }
case 0x0007001B: { case 0x0007001B: {
assert_true(!buffer_length || buffer_length == 12); assert_true(!buffer_length || buffer_length == 12);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
uint32_t unk_ptr = poly::load_and_swap<uint32_t>( uint32_t unk_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0 buffer + 4); // out ptr to 4b - expect 0
uint32_t disabled_ptr = poly::load_and_swap<uint32_t>( uint32_t disabled_ptr = poly::load_and_swap<uint32_t>(
membase_ + buffer_ptr + 8); // out ptr to 4b - expect 1 (to skip) buffer + 8); // out ptr to 4b - expect 1 (to skip)
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetEnabled(%.8X, %.8X)", unk_ptr, disabled_ptr); XELOGD("XMPGetEnabled(%.8X, %.8X)", unk_ptr, disabled_ptr);
poly::store_and_swap<uint32_t>(membase_ + unk_ptr, 0); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(unk_ptr), 0);
poly::store_and_swap<uint32_t>(membase_ + disabled_ptr, disabled_); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(disabled_ptr),
disabled_);
// Atrain spawns a thread 82437FD0 to call this in a tight loop forever. // Atrain spawns a thread 82437FD0 to call this in a tight loop forever.
poly::threading::Sleep(std::chrono::milliseconds(10)); poly::threading::Sleep(std::chrono::milliseconds(10));
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x00070029: { case 0x00070029: {
assert_true(!buffer_length || buffer_length == 16); assert_true(!buffer_length || buffer_length == 16);
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t playback_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t playback_mode_ptr = uint32_t repeat_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); uint32_t unk3_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
uint32_t repeat_mode_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
uint32_t unk3_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 12);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
XELOGD("XMPGetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode_ptr, XELOGD("XMPGetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode_ptr,
repeat_mode_ptr, unk3_ptr); repeat_mode_ptr, unk3_ptr);
poly::store_and_swap<uint32_t>(membase_ + playback_mode_ptr, poly::store_and_swap<uint32_t>(
static_cast<uint32_t>(playback_mode_)); memory_->TranslateVirtual(playback_mode_ptr),
poly::store_and_swap<uint32_t>(membase_ + repeat_mode_ptr, static_cast<uint32_t>(playback_mode_));
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(repeat_mode_ptr),
static_cast<uint32_t>(repeat_mode_)); static_cast<uint32_t>(repeat_mode_));
poly::store_and_swap<uint32_t>(membase_ + unk3_ptr, unknown_flags_); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(unk3_ptr),
unknown_flags_);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x0007002E: { case 0x0007002E: {
assert_true(!buffer_length || buffer_length == 12); assert_true(!buffer_length || buffer_length == 12);
// Query of size for XamAlloc - the result of the alloc is passed to // Query of size for XamAlloc - the result of the alloc is passed to
// 0x0007000D. // 0x0007000D.
uint32_t xmp_client = uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0); uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 4);
uint32_t song_count = uint32_t size_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
uint32_t size_ptr =
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
assert_true(xmp_client == 0x00000002); assert_true(xmp_client == 0x00000002);
// We don't use the storage, so just fudge the number. // We don't use the storage, so just fudge the number.
poly::store_and_swap<uint32_t>(membase_ + size_ptr, song_count * 128); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(size_ptr),
song_count * 128);
return X_ERROR_SUCCESS; return X_ERROR_SUCCESS;
} }
case 0x0007003D: { case 0x0007003D: {

View File

@ -204,7 +204,7 @@ void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) {
void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result,
uint32_t length) { uint32_t length) {
auto ptr = memory()->membase() + overlapped_ptr; auto ptr = memory()->TranslateVirtual(overlapped_ptr);
XOverlappedSetResult(ptr, result); XOverlappedSetResult(ptr, result);
XOverlappedSetLength(ptr, length); XOverlappedSetLength(ptr, length);
XOverlappedSetExtendedError(ptr, result); XOverlappedSetExtendedError(ptr, result);
@ -233,7 +233,7 @@ void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result,
void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr, void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr,
X_RESULT result, X_RESULT result,
uint32_t length) { uint32_t length) {
auto ptr = memory()->membase() + overlapped_ptr; auto ptr = memory()->TranslateVirtual(overlapped_ptr);
XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle()); XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle());
CompleteOverlapped(overlapped_ptr, result, length); CompleteOverlapped(overlapped_ptr, result, length);
} }

View File

@ -16,41 +16,44 @@ NativeList::NativeList(Memory* memory)
: memory_(memory), head_(kInvalidPointer) {} : memory_(memory), head_(kInvalidPointer) {}
void NativeList::Insert(uint32_t ptr) { void NativeList::Insert(uint32_t ptr) {
uint8_t* mem = memory_->membase(); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0), head_);
poly::store_and_swap<uint32_t>(mem + ptr + 0, head_); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4), 0);
poly::store_and_swap<uint32_t>(mem + ptr + 4, 0);
if (head_) { if (head_) {
poly::store_and_swap<uint32_t>(mem + head_ + 4, ptr); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(head_ + 4), ptr);
} }
head_ = ptr; head_ = ptr;
} }
bool NativeList::IsQueued(uint32_t ptr) { bool NativeList::IsQueued(uint32_t ptr) {
uint8_t* mem = memory_->membase(); uint32_t flink =
uint32_t flink = poly::load_and_swap<uint32_t>(mem + ptr + 0); poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0));
uint32_t blink = poly::load_and_swap<uint32_t>(mem + ptr + 4); uint32_t blink =
poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4));
return head_ == ptr || flink || blink; return head_ == ptr || flink || blink;
} }
void NativeList::Remove(uint32_t ptr) { void NativeList::Remove(uint32_t ptr) {
uint8_t* mem = memory_->membase(); uint32_t flink =
uint32_t flink = poly::load_and_swap<uint32_t>(mem + ptr + 0); poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0));
uint32_t blink = poly::load_and_swap<uint32_t>(mem + ptr + 4); uint32_t blink =
poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4));
if (ptr == head_) { if (ptr == head_) {
head_ = flink; head_ = flink;
if (flink) { if (flink) {
poly::store_and_swap<uint32_t>(mem + flink + 4, 0); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(flink + 4), 0);
} }
} else { } else {
if (blink) { if (blink) {
poly::store_and_swap<uint32_t>(mem + blink + 0, flink); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(blink + 0),
flink);
} }
if (flink) { if (flink) {
poly::store_and_swap<uint32_t>(mem + flink + 4, blink); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(flink + 4),
blink);
} }
} }
poly::store_and_swap<uint32_t>(mem + ptr + 0, 0); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0), 0);
poly::store_and_swap<uint32_t>(mem + ptr + 4, 0); poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4), 0);
} }
uint32_t NativeList::Shift() { uint32_t NativeList::Shift() {

View File

@ -118,12 +118,12 @@ uint32_t XThread::thread_state() { return thread_state_address_; }
uint32_t XThread::thread_id() { return thread_id_; } uint32_t XThread::thread_id() { return thread_id_; }
uint32_t XThread::last_error() { uint32_t XThread::last_error() {
uint8_t* p = memory()->Translate(thread_state_address_); uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
return poly::load_and_swap<uint32_t>(p + 0x160); return poly::load_and_swap<uint32_t>(p + 0x160);
} }
void XThread::set_last_error(uint32_t error_code) { void XThread::set_last_error(uint32_t error_code) {
uint8_t* p = memory()->Translate(thread_state_address_); uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x160, error_code); poly::store_and_swap<uint32_t>(p + 0x160, error_code);
} }
@ -176,7 +176,7 @@ X_STATUS XThread::Create() {
memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size); memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size);
// Setup the thread state block (last error/etc). // Setup the thread state block (last error/etc).
uint8_t* p = memory()->Translate(thread_state_address_); uint8_t* p = memory()->TranslateVirtual(thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x000, tls_address_); poly::store_and_swap<uint32_t>(p + 0x000, tls_address_);
poly::store_and_swap<uint32_t>(p + 0x100, thread_state_address_); poly::store_and_swap<uint32_t>(p + 0x100, thread_state_address_);
poly::store_and_swap<uint32_t>(p + 0x14C, thread_id_); poly::store_and_swap<uint32_t>(p + 0x14C, thread_id_);
@ -382,7 +382,7 @@ void XThread::DeliverAPCs(void* data) {
// http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=1 // http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=1
// http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7 // http://www.drdobbs.com/inside-nts-asynchronous-procedure-call/184416590?pgno=7
XThread* thread = reinterpret_cast<XThread*>(data); XThread* thread = reinterpret_cast<XThread*>(data);
auto membase = thread->memory()->membase(); auto memory = thread->memory();
auto processor = thread->kernel_state()->processor(); auto processor = thread->kernel_state()->processor();
auto apc_list = thread->apc_list(); auto apc_list = thread->apc_list();
thread->LockApc(); thread->LockApc();
@ -390,7 +390,7 @@ void XThread::DeliverAPCs(void* data) {
// Get APC entry (offset for LIST_ENTRY offset) and cache what we need. // Get APC entry (offset for LIST_ENTRY offset) and cache what we need.
// Calling the routine may delete the memory/overwrite it. // Calling the routine may delete the memory/overwrite it.
uint32_t apc_address = apc_list->Shift() - 8; uint32_t apc_address = apc_list->Shift() - 8;
uint8_t* apc_ptr = membase + apc_address; uint8_t* apc_ptr = memory->TranslateVirtual(apc_address);
uint32_t kernel_routine = poly::load_and_swap<uint32_t>(apc_ptr + 16); uint32_t kernel_routine = poly::load_and_swap<uint32_t>(apc_ptr + 16);
uint32_t normal_routine = poly::load_and_swap<uint32_t>(apc_ptr + 24); uint32_t normal_routine = poly::load_and_swap<uint32_t>(apc_ptr + 24);
uint32_t normal_context = poly::load_and_swap<uint32_t>(apc_ptr + 28); uint32_t normal_context = poly::load_and_swap<uint32_t>(apc_ptr + 28);
@ -405,7 +405,7 @@ void XThread::DeliverAPCs(void* data) {
// The routine can modify all of its arguments before passing it on. // The routine can modify all of its arguments before passing it on.
// Since we need to give guest accessible pointers over, we copy things // Since we need to give guest accessible pointers over, we copy things
// into and out of scratch. // into and out of scratch.
uint8_t* scratch_ptr = membase + thread->scratch_address_; uint8_t* scratch_ptr = memory->TranslateVirtual(thread->scratch_address_);
poly::store_and_swap<uint32_t>(scratch_ptr + 0, normal_routine); poly::store_and_swap<uint32_t>(scratch_ptr + 0, normal_routine);
poly::store_and_swap<uint32_t>(scratch_ptr + 4, normal_context); poly::store_and_swap<uint32_t>(scratch_ptr + 4, normal_context);
poly::store_and_swap<uint32_t>(scratch_ptr + 8, system_arg1); poly::store_and_swap<uint32_t>(scratch_ptr + 8, system_arg1);
@ -438,13 +438,12 @@ void XThread::DeliverAPCs(void* data) {
} }
void XThread::RundownAPCs() { void XThread::RundownAPCs() {
auto membase = memory()->membase();
LockApc(); LockApc();
while (apc_list_->HasPending()) { while (apc_list_->HasPending()) {
// Get APC entry (offset for LIST_ENTRY offset) and cache what we need. // Get APC entry (offset for LIST_ENTRY offset) and cache what we need.
// Calling the routine may delete the memory/overwrite it. // Calling the routine may delete the memory/overwrite it.
uint32_t apc_address = apc_list_->Shift() - 8; uint32_t apc_address = apc_list_->Shift() - 8;
uint8_t* apc_ptr = membase + apc_address; uint8_t* apc_ptr = memory()->TranslateVirtual(apc_address);
uint32_t rundown_routine = poly::load_and_swap<uint32_t>(apc_ptr + 20); uint32_t rundown_routine = poly::load_and_swap<uint32_t>(apc_ptr + 20);
// Mark as uninserted so that it can be reinserted again by the routine. // Mark as uninserted so that it can be reinserted again by the routine.

View File

@ -107,15 +107,15 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) {
// Load the XEX into memory and decrypt. // Load the XEX into memory and decrypt.
xe_xex2_options_t xex_options = {0}; xe_xex2_options_t xex_options = {0};
xex_ = xe_xex2_load(kernel_state()->memory(), addr, length, xex_options); xex_ = xe_xex2_load(memory(), addr, length, xex_options);
if (!xex_) { if (!xex_) {
return X_STATUS_UNSUCCESSFUL; return X_STATUS_UNSUCCESSFUL;
} }
// Store execution info for later use. // Store execution info for later use.
// TODO(benvanik): just put entire xex header in memory somewhere? // TODO(benvanik): just put entire xex header in memory somewhere?
execution_info_ptr_ = kernel_state()->memory()->SystemHeapAlloc(24); execution_info_ptr_ = memory()->SystemHeapAlloc(24);
auto eip = kernel_state()->memory()->membase() + execution_info_ptr_; auto eip = memory()->TranslateVirtual(execution_info_ptr_);
const auto& ex = xe_xex2_get_header(xex_)->execution_info; const auto& ex = xe_xex2_get_header(xex_)->execution_info;
poly::store_and_swap<uint32_t>(eip + 0x00, ex.media_id); poly::store_and_swap<uint32_t>(eip + 0x00, ex.media_id);
poly::store_and_swap<uint32_t>(eip + 0x04, ex.version.value); poly::store_and_swap<uint32_t>(eip + 0x04, ex.version.value);

View File

@ -26,8 +26,8 @@ using PPCContext = xe::cpu::frontend::PPCContext;
shim_data, \ shim_data, \
(xe_kernel_export_shim_fn)export_name##_shim); (xe_kernel_export_shim_fn)export_name##_shim);
#define SHIM_MEM_BASE ppc_state->membase #define SHIM_MEM_BASE ppc_state->virtual_membase
#define SHIM_MEM_ADDR(a) (a ? (ppc_state->membase + a) : nullptr) #define SHIM_MEM_ADDR(a) (a ? (ppc_state->virtual_membase + a) : nullptr)
#define SHIM_MEM_8(a) poly::load_and_swap<uint8_t>(SHIM_MEM_ADDR(a)) #define SHIM_MEM_8(a) poly::load_and_swap<uint8_t>(SHIM_MEM_ADDR(a))
#define SHIM_MEM_16(a) poly::load_and_swap<uint16_t>(SHIM_MEM_ADDR(a)) #define SHIM_MEM_16(a) poly::load_and_swap<uint16_t>(SHIM_MEM_ADDR(a))

View File

@ -538,7 +538,7 @@ int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header,
uncompressed_size); uncompressed_size);
return 2; return 2;
} }
uint8_t *buffer = memory->Translate(header->exe_address); uint8_t *buffer = memory->TranslateVirtual(header->exe_address);
std::memset(buffer, 0, uncompressed_size); std::memset(buffer, 0, uncompressed_size);
const uint8_t *p = (const uint8_t *)xex_addr + header->exe_offset; const uint8_t *p = (const uint8_t *)xex_addr + header->exe_offset;
@ -588,7 +588,7 @@ int xe_xex2_read_image_basic_compressed(const xe_xex2_header_t *header,
uncompressed_size); uncompressed_size);
return 1; return 1;
} }
uint8_t *buffer = memory->Translate(header->exe_address); uint8_t *buffer = memory->TranslateVirtual(header->exe_address);
uint8_t *d = buffer; uint8_t *d = buffer;
std::memset(buffer, 0, uncompressed_size); std::memset(buffer, 0, uncompressed_size);
@ -726,7 +726,7 @@ int xe_xex2_read_image_compressed(const xe_xex2_header_t *header,
result_code = 2; result_code = 2;
goto XECLEANUP; goto XECLEANUP;
} }
uint8_t *buffer = memory->Translate(header->exe_address); uint8_t *buffer = memory->TranslateVirtual(header->exe_address);
std::memset(buffer, 0, uncompressed_size); std::memset(buffer, 0, uncompressed_size);
// Setup decompressor and decompress. // Setup decompressor and decompress.
@ -792,7 +792,7 @@ int xe_xex2_read_image(xe_xex2_ref xex, const uint8_t *xex_addr,
int xe_xex2_load_pe(xe_xex2_ref xex) { int xe_xex2_load_pe(xe_xex2_ref xex) {
const xe_xex2_header_t *header = &xex->header; const xe_xex2_header_t *header = &xex->header;
const uint8_t *p = xex->memory->Translate(header->exe_address); const uint8_t *p = xex->memory->TranslateVirtual(header->exe_address);
// Verify DOS signature (MZ). // Verify DOS signature (MZ).
const IMAGE_DOS_HEADER *doshdr = (const IMAGE_DOS_HEADER *)p; const IMAGE_DOS_HEADER *doshdr = (const IMAGE_DOS_HEADER *)p;
@ -886,7 +886,6 @@ const PESection *xe_xex2_get_pe_section(xe_xex2_ref xex, const char *name) {
int xe_xex2_find_import_infos(xe_xex2_ref xex, int xe_xex2_find_import_infos(xe_xex2_ref xex,
const xe_xex2_import_library_t *library) { const xe_xex2_import_library_t *library) {
uint8_t *mem = xex->memory->membase();
auto header = xe_xex2_get_header(xex); auto header = xe_xex2_get_header(xex);
// Find library index for verification. // Find library index for verification.
@ -910,7 +909,8 @@ int xe_xex2_find_import_infos(xe_xex2_ref xex,
size_t info_count = 0; size_t info_count = 0;
for (size_t n = 0; n < library->record_count; n++) { for (size_t n = 0; n < library->record_count; n++) {
const uint32_t record = library->records[n]; const uint32_t record = library->records[n];
const uint32_t value = poly::load_and_swap<uint32_t>(mem + record); const uint32_t value =
poly::load_and_swap<uint32_t>(xex->memory->TranslateVirtual(record));
if (value & 0xFF000000) { if (value & 0xFF000000) {
// Thunk for previous record - ignore. // Thunk for previous record - ignore.
} else { } else {
@ -929,7 +929,8 @@ int xe_xex2_find_import_infos(xe_xex2_ref xex,
// Construct infos. // Construct infos.
for (size_t n = 0, i = 0; n < library->record_count; n++) { for (size_t n = 0, i = 0; n < library->record_count; n++) {
const uint32_t record = library->records[n]; const uint32_t record = library->records[n];
const uint32_t value = poly::load_and_swap<uint32_t>(mem + record); const uint32_t value =
poly::load_and_swap<uint32_t>(xex->memory->TranslateVirtual(record));
const uint32_t type = (value & 0xFF000000) >> 24; const uint32_t type = (value & 0xFF000000) >> 24;
// Verify library index matches given library. // Verify library index matches given library.

View File

@ -151,10 +151,6 @@ struct XMAContextData {
}; };
static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed"); static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed");
void StoreXmaRegister(uint8_t* membase, uint32_t num, uint32_t value) {
poly::store<uint32_t>(membase + (0x7FEA0000 + num), value);
}
void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg,
uint32_t context_ptr) { uint32_t context_ptr) {
auto audio_system = state->emulator()->audio_system(); auto audio_system = state->emulator()->audio_system();
@ -162,7 +158,8 @@ void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg,
XMAContextData::kSize; XMAContextData::kSize;
uint32_t reg_num = base_reg + (hw_index >> 5) * 4; uint32_t reg_num = base_reg + (hw_index >> 5) * 4;
uint32_t reg_value = 1 << (hw_index & 0x1F); uint32_t reg_value = 1 << (hw_index & 0x1F);
StoreXmaRegister(state->memory()->membase(), reg_num, reg_value); poly::store<uint32_t>(state->memory()->TranslateVirtual(0x7FEA0000 + reg_num),
reg_value);
} }
SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) { SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) {

View File

@ -44,23 +44,23 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
xboxkrnl::RegisterUsbcamExports(export_resolver_, kernel_state_); xboxkrnl::RegisterUsbcamExports(export_resolver_, kernel_state_);
xboxkrnl::RegisterVideoExports(export_resolver_, kernel_state_); xboxkrnl::RegisterVideoExports(export_resolver_, kernel_state_);
uint8_t* mem = memory_->membase();
// KeDebugMonitorData (?*) // KeDebugMonitorData (?*)
// Set to a valid value when a remote debugger is attached. // Set to a valid value when a remote debugger is attached.
// Offset 0x18 is a 4b pointer to a handler function that seems to take two // Offset 0x18 is a 4b pointer to a handler function that seems to take two
// arguments. If we wanted to see what would happen we could fake that. // arguments. If we wanted to see what would happen we could fake that.
uint32_t pKeDebugMonitorData = memory_->SystemHeapAlloc(256); uint32_t pKeDebugMonitorData = memory_->SystemHeapAlloc(256);
auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData); "xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData);
poly::store_and_swap<uint32_t>(mem + pKeDebugMonitorData, 0); poly::store_and_swap<uint32_t>(lpKeDebugMonitorData, 0);
// KeCertMonitorData (?*) // KeCertMonitorData (?*)
// Always set to zero, ignored. // Always set to zero, ignored.
uint32_t pKeCertMonitorData = memory_->SystemHeapAlloc(4); uint32_t pKeCertMonitorData = memory_->SystemHeapAlloc(4);
auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData); "xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData);
poly::store_and_swap<uint32_t>(mem + pKeCertMonitorData, 0); poly::store_and_swap<uint32_t>(lpKeCertMonitorData, 0);
// XboxHardwareInfo (XboxHardwareInfo_t, 16b) // XboxHardwareInfo (XboxHardwareInfo_t, 16b)
// flags cpu# ? ? ? ? ? ? // flags cpu# ? ? ? ? ? ?
@ -71,11 +71,11 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// aomega08 says the value is 0x02000817, bit 27: debug mode on. // aomega08 says the value is 0x02000817, bit 27: debug mode on.
// When that is set, though, allocs crash in weird ways. // When that is set, though, allocs crash in weird ways.
uint32_t pXboxHardwareInfo = memory_->SystemHeapAlloc(16); uint32_t pXboxHardwareInfo = memory_->SystemHeapAlloc(16);
auto lpXboxHardwareInfo = memory_->TranslateVirtual(pXboxHardwareInfo);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::XboxHardwareInfo, pXboxHardwareInfo); "xboxkrnl.exe", ordinals::XboxHardwareInfo, pXboxHardwareInfo);
poly::store_and_swap<uint32_t>(mem + pXboxHardwareInfo + 0, 0); // flags poly::store_and_swap<uint32_t>(lpXboxHardwareInfo + 0, 0); // flags
poly::store_and_swap<uint8_t>(mem + pXboxHardwareInfo + 4, poly::store_and_swap<uint8_t>(lpXboxHardwareInfo + 4, 0x06); // cpu count
0x06); // cpu count
// Remaining 11b are zeroes? // Remaining 11b are zeroes?
// XexExecutableModuleHandle (?**) // XexExecutableModuleHandle (?**)
@ -88,13 +88,17 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// 0x80101058 <- pointer to xex header // 0x80101058 <- pointer to xex header
// 0x80101100 <- xex header base // 0x80101100 <- xex header base
uint32_t ppXexExecutableModuleHandle = memory_->SystemHeapAlloc(4); uint32_t ppXexExecutableModuleHandle = memory_->SystemHeapAlloc(4);
auto lppXexExecutableModuleHandle =
memory_->TranslateVirtual(ppXexExecutableModuleHandle);
export_resolver_->SetVariableMapping("xboxkrnl.exe", export_resolver_->SetVariableMapping("xboxkrnl.exe",
ordinals::XexExecutableModuleHandle, ordinals::XexExecutableModuleHandle,
ppXexExecutableModuleHandle); ppXexExecutableModuleHandle);
uint32_t pXexExecutableModuleHandle = memory_->SystemHeapAlloc(256); uint32_t pXexExecutableModuleHandle = memory_->SystemHeapAlloc(256);
poly::store_and_swap<uint32_t>(mem + ppXexExecutableModuleHandle, auto lpXexExecutableModuleHandle =
memory_->TranslateVirtual(pXexExecutableModuleHandle);
poly::store_and_swap<uint32_t>(lppXexExecutableModuleHandle,
pXexExecutableModuleHandle); pXexExecutableModuleHandle);
poly::store_and_swap<uint32_t>(mem + pXexExecutableModuleHandle + 0x58, poly::store_and_swap<uint32_t>(lpXexExecutableModuleHandle + 0x58,
0x80101100); 0x80101100);
// ExLoadedCommandLine (char*) // ExLoadedCommandLine (char*)
@ -102,41 +106,44 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
// Perhaps it's how swap disc/etc data is sent? // Perhaps it's how swap disc/etc data is sent?
// Always set to "default.xex" (with quotes) for now. // Always set to "default.xex" (with quotes) for now.
uint32_t pExLoadedCommandLine = memory_->SystemHeapAlloc(1024); uint32_t pExLoadedCommandLine = memory_->SystemHeapAlloc(1024);
auto lpExLoadedCommandLine = memory_->TranslateVirtual(pExLoadedCommandLine);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::ExLoadedCommandLine, pExLoadedCommandLine); "xboxkrnl.exe", ordinals::ExLoadedCommandLine, pExLoadedCommandLine);
char command_line[] = "\"default.xex\""; char command_line[] = "\"default.xex\"";
memcpy(mem + pExLoadedCommandLine, command_line, std::memcpy(lpExLoadedCommandLine, command_line,
poly::countof(command_line) + 1); poly::countof(command_line) + 1);
// XboxKrnlVersion (8b) // XboxKrnlVersion (8b)
// Kernel version, looks like 2b.2b.2b.2b. // Kernel version, looks like 2b.2b.2b.2b.
// I've only seen games check >=, so we just fake something here. // I've only seen games check >=, so we just fake something here.
uint32_t pXboxKrnlVersion = memory_->SystemHeapAlloc(8); uint32_t pXboxKrnlVersion = memory_->SystemHeapAlloc(8);
auto lpXboxKrnlVersion = memory_->TranslateVirtual(pXboxKrnlVersion);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::XboxKrnlVersion, pXboxKrnlVersion); "xboxkrnl.exe", ordinals::XboxKrnlVersion, pXboxKrnlVersion);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 0, 2); poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 0, 2);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 2, 0xFFFF); poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 2, 0xFFFF);
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 4, 0xFFFF); poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 4, 0xFFFF);
poly::store_and_swap<uint8_t>(mem + pXboxKrnlVersion + 6, 0x80); poly::store_and_swap<uint8_t>(lpXboxKrnlVersion + 6, 0x80);
poly::store_and_swap<uint8_t>(mem + pXboxKrnlVersion + 7, 0x00); poly::store_and_swap<uint8_t>(lpXboxKrnlVersion + 7, 0x00);
// KeTimeStampBundle (ad) // KeTimeStampBundle (ad)
// This must be updated during execution, at 1ms intevals. // This must be updated during execution, at 1ms intevals.
// We setup a system timer here to do that. // We setup a system timer here to do that.
uint32_t pKeTimeStampBundle = memory_->SystemHeapAlloc(24); uint32_t pKeTimeStampBundle = memory_->SystemHeapAlloc(24);
auto lpKeTimeStampBundle = memory_->TranslateVirtual(pKeTimeStampBundle);
export_resolver_->SetVariableMapping( export_resolver_->SetVariableMapping(
"xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle); "xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 0, 0); poly::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0);
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 8, 0); poly::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0);
poly::store_and_swap<uint32_t>(mem + pKeTimeStampBundle + 16, GetTickCount()); poly::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16, GetTickCount());
poly::store_and_swap<uint32_t>(mem + pKeTimeStampBundle + 20, 0); poly::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0);
CreateTimerQueueTimer( CreateTimerQueueTimer(
&timestamp_timer_, nullptr, &timestamp_timer_, nullptr,
[](PVOID param, BOOLEAN timer_or_wait_fired) { [](PVOID param, BOOLEAN timer_or_wait_fired) {
auto timestamp_bundle = reinterpret_cast<uint8_t*>(param); auto timestamp_bundle = reinterpret_cast<uint8_t*>(param);
poly::store_and_swap<uint32_t>(timestamp_bundle + 16, GetTickCount()); poly::store_and_swap<uint32_t>(timestamp_bundle + 16, GetTickCount());
}, },
mem + pKeTimeStampBundle, 0, lpKeTimeStampBundle, 0,
1, // 1ms 1, // 1ms
WT_EXECUTEINTIMERTHREAD); WT_EXECUTEINTIMERTHREAD);
} }

View File

@ -541,7 +541,7 @@ SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_state,
// XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr); // XELOGD("RtlEnterCriticalSection(%.8X)", cs_ptr);
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13]; const uint8_t* thread_state_block = SHIM_MEM_ADDR(ppc_state->r[13]);
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block); uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr); auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);
@ -583,7 +583,7 @@ SHIM_CALL RtlTryEnterCriticalSection_shim(PPCContext* ppc_state,
// XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr); // XELOGD("RtlTryEnterCriticalSection(%.8X)", cs_ptr);
const uint8_t* thread_state_block = ppc_state->membase + ppc_state->r[13]; const uint8_t* thread_state_block = SHIM_MEM_ADDR(ppc_state->r[13]);
uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block); uint32_t thread_id = XThread::GetCurrentThreadId(thread_state_block);
auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr); auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr);

View File

@ -62,11 +62,10 @@ void AssertNoNameCollision(KernelState* state, uint32_t obj_attributes_ptr) {
// with a success of NAME_EXISTS. // with a success of NAME_EXISTS.
// If the name exists and its type doesn't match, we do NAME_COLLISION. // If the name exists and its type doesn't match, we do NAME_COLLISION.
// Otherwise, we add like normal. // Otherwise, we add like normal.
auto membase = state->memory()->membase(); uint32_t name_str_ptr = poly::load_and_swap<uint32_t>(
uint32_t name_str_ptr = state->memory()->TranslateVirtual(obj_attributes_ptr + 4));
poly::load_and_swap<uint32_t>(membase + obj_attributes_ptr + 4);
if (name_str_ptr) { if (name_str_ptr) {
X_ANSI_STRING name_str(membase, name_str_ptr); X_ANSI_STRING name_str(state->memory()->virtual_membase(), name_str_ptr);
auto name = name_str.to_string(); auto name = name_str.to_string();
X_HANDLE handle = X_INVALID_HANDLE_VALUE; X_HANDLE handle = X_INVALID_HANDLE_VALUE;
X_RESULT result = state->object_table()->GetObjectByName(name, &handle); X_RESULT result = state->object_table()->GetObjectByName(name, &handle);

View File

@ -447,7 +447,6 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
SHIM_SET_MAPPING("xboxkrnl.exe", VdSwap, state); SHIM_SET_MAPPING("xboxkrnl.exe", VdSwap, state);
Memory* memory = state->memory(); Memory* memory = state->memory();
uint8_t* mem = memory->membase();
// VdGlobalDevice (4b) // VdGlobalDevice (4b)
// Pointer to a global D3D device. Games only seem to set this, so we don't // Pointer to a global D3D device. Games only seem to set this, so we don't
@ -456,7 +455,7 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical); memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGlobalDevice, export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGlobalDevice,
pVdGlobalDevice); pVdGlobalDevice);
poly::store_and_swap<uint32_t>(mem + pVdGlobalDevice, 0); poly::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGlobalDevice), 0);
// VdGlobalXamDevice (4b) // VdGlobalXamDevice (4b)
// Pointer to the XAM D3D device, which we don't have. // Pointer to the XAM D3D device, which we don't have.
@ -464,7 +463,8 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical); memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
export_resolver->SetVariableMapping( export_resolver->SetVariableMapping(
"xboxkrnl.exe", ordinals::VdGlobalXamDevice, pVdGlobalXamDevice); "xboxkrnl.exe", ordinals::VdGlobalXamDevice, pVdGlobalXamDevice);
poly::store_and_swap<uint32_t>(mem + pVdGlobalXamDevice, 0); poly::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGlobalXamDevice),
0);
// VdGpuClockInMHz (4b) // VdGpuClockInMHz (4b)
// GPU clock. Xenos is 500MHz. Hope nothing is relying on this timing... // GPU clock. Xenos is 500MHz. Hope nothing is relying on this timing...
@ -472,7 +472,8 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical); memory->SystemHeapAlloc(4, 32, kSystemHeapPhysical);
export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGpuClockInMHz, export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGpuClockInMHz,
pVdGpuClockInMHz); pVdGpuClockInMHz);
poly::store_and_swap<uint32_t>(mem + pVdGpuClockInMHz, 500); poly::store_and_swap<uint32_t>(memory->TranslateVirtual(pVdGpuClockInMHz),
500);
// VdHSIOCalibrationLock (28b) // VdHSIOCalibrationLock (28b)
// CriticalSection. // CriticalSection.
@ -481,7 +482,7 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver,
export_resolver->SetVariableMapping( export_resolver->SetVariableMapping(
"xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock); "xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock);
auto hsio_lock = auto hsio_lock =
reinterpret_cast<X_RTL_CRITICAL_SECTION*>(mem + pVdHSIOCalibrationLock); memory->TranslateVirtual<X_RTL_CRITICAL_SECTION*>(pVdHSIOCalibrationLock);
xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock, xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock,
10000); 10000);
} }

View File

@ -23,9 +23,8 @@ XObject::XObject(KernelState* kernel_state, Type type)
pointer_ref_count_(1), pointer_ref_count_(1),
type_(type), type_(type),
handle_(X_INVALID_HANDLE_VALUE) { handle_(X_INVALID_HANDLE_VALUE) {
// Added pointer check to support usage without a kernel_state // Added pointer check to support usage without a kernel_state
if (kernel_state != nullptr){ if (kernel_state != nullptr) {
kernel_state->object_table()->AddHandle(this, &handle_); kernel_state->object_table()->AddHandle(this, &handle_);
} }
} }
@ -35,8 +34,6 @@ XObject::~XObject() {
assert_zero(pointer_ref_count_); assert_zero(pointer_ref_count_);
} }
Memory* XObject::memory() const { return kernel_state_->memory(); }
XObject::Type XObject::type() { return type_; } XObject::Type XObject::type() { return type_; }
X_HANDLE XObject::handle() const { return handle_; } X_HANDLE XObject::handle() const { return handle_; }
@ -78,7 +75,7 @@ void XObject::SetAttributes(const uint8_t* obj_attrs_ptr) {
uint32_t name_str_ptr = poly::load_and_swap<uint32_t>(obj_attrs_ptr + 4); uint32_t name_str_ptr = poly::load_and_swap<uint32_t>(obj_attrs_ptr + 4);
if (name_str_ptr) { if (name_str_ptr) {
X_ANSI_STRING name_str(membase(), name_str_ptr); X_ANSI_STRING name_str(memory()->virtual_membase(), name_str_ptr);
name_ = name_str.to_string(); name_ = name_str.to_string();
kernel_state_->object_table()->AddNameMapping(name_, handle_); kernel_state_->object_table()->AddNameMapping(name_, handle_);
} }
@ -157,8 +154,8 @@ X_STATUS XObject::WaitMultiple(uint32_t count, XObject** objects,
void XObject::SetNativePointer(uint32_t native_ptr) { void XObject::SetNativePointer(uint32_t native_ptr) {
std::lock_guard<std::mutex> lock(kernel_state_->object_mutex()); std::lock_guard<std::mutex> lock(kernel_state_->object_mutex());
DISPATCH_HEADER* header_be = auto header_be =
(DISPATCH_HEADER*)kernel_state_->memory()->Translate(native_ptr); kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(native_ptr);
DISPATCH_HEADER header; DISPATCH_HEADER header;
header.type_flags = poly::byte_swap(header_be->type_flags); header.type_flags = poly::byte_swap(header_be->type_flags);
header.signal_state = poly::byte_swap(header_be->signal_state); header.signal_state = poly::byte_swap(header_be->signal_state);

View File

@ -13,7 +13,6 @@
#include <atomic> #include <atomic>
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/xbox.h" #include "xenia/xbox.h"
namespace xe { namespace xe {
@ -46,7 +45,7 @@ class XObject {
Emulator* emulator() const { return kernel_state_->emulator_; } Emulator* emulator() const { return kernel_state_->emulator_; }
KernelState* kernel_state() const { return kernel_state_; } KernelState* kernel_state() const { return kernel_state_; }
uint8_t* membase() const { return kernel_state_->memory()->membase(); } Memory* memory() const { return kernel_state_->memory(); }
Type type(); Type type();
X_HANDLE handle() const; X_HANDLE handle() const;
@ -79,7 +78,6 @@ class XObject {
virtual void* GetWaitHandle() { return 0; } virtual void* GetWaitHandle() { return 0; }
protected: protected:
Memory* memory() const;
void SetNativePointer(uint32_t native_ptr); void SetNativePointer(uint32_t native_ptr);
static uint32_t TimeoutTicksToMs(int64_t timeout_ticks); static uint32_t TimeoutTicksToMs(int64_t timeout_ticks);

View File

@ -116,7 +116,8 @@ class xe::MemoryHeap {
uint32_t MemoryHeap::next_heap_id_ = 1; uint32_t MemoryHeap::next_heap_id_ = 1;
Memory::Memory() Memory::Memory()
: membase_(nullptr), : virtual_membase_(nullptr),
physical_membase_(nullptr),
reserve_address_(0), reserve_address_(0),
reserve_value_(0), reserve_value_(0),
trace_base_(0), trace_base_(0),
@ -134,7 +135,7 @@ Memory::~Memory() {
if (mapping_base_) { if (mapping_base_) {
// GPU writeback. // GPU writeback.
VirtualFree(Translate(0xC0000000), 0x00100000, MEM_DECOMMIT); VirtualFree(TranslateVirtual(0xC0000000), 0x00100000, MEM_DECOMMIT);
} }
delete physical_heap_; delete physical_heap_;
@ -147,6 +148,9 @@ Memory::~Memory() {
mapping_base_ = 0; mapping_base_ = 0;
mapping_ = 0; mapping_ = 0;
} }
virtual_membase_ = nullptr;
physical_membase_ = nullptr;
} }
int Memory::Initialize() { int Memory::Initialize() {
@ -184,7 +188,8 @@ int Memory::Initialize() {
assert_always(); assert_always();
return 1; return 1;
} }
membase_ = mapping_base_; virtual_membase_ = mapping_base_;
physical_membase_ = virtual_membase_;
// Prepare heaps. // Prepare heaps.
virtual_heap_->Initialize(kMemoryVirtualHeapLow, kMemoryVirtualHeapHigh); virtual_heap_->Initialize(kMemoryVirtualHeapLow, kMemoryVirtualHeapHigh);
@ -193,7 +198,8 @@ int Memory::Initialize() {
// GPU writeback. // GPU writeback.
// 0xC... is physical, 0x7F... is virtual. We may need to overlay these. // 0xC... is physical, 0x7F... is virtual. We may need to overlay these.
VirtualAlloc(Translate(0x00000000), 0x00100000, MEM_COMMIT, PAGE_READWRITE); VirtualAlloc(TranslatePhysical(0x00000000), 0x00100000, MEM_COMMIT,
PAGE_READWRITE);
// Add handlers for MMIO. // Add handlers for MMIO.
mmio_handler_ = cpu::MMIOHandler::Install(mapping_base_); mmio_handler_ = cpu::MMIOHandler::Install(mapping_base_);
@ -204,9 +210,10 @@ int Memory::Initialize() {
} }
// I have no idea what this is, but games try to read/write there. // I have no idea what this is, but games try to read/write there.
VirtualAlloc(Translate(0x40000000), 0x00010000, MEM_COMMIT, PAGE_READWRITE); VirtualAlloc(TranslateVirtual(0x40000000), 0x00010000, MEM_COMMIT,
poly::store_and_swap<uint32_t>(Translate(0x40000000), 0x00C40000); PAGE_READWRITE);
poly::store_and_swap<uint32_t>(Translate(0x40000004), 0x00010000); poly::store_and_swap<uint32_t>(TranslateVirtual(0x40000000), 0x00C40000);
poly::store_and_swap<uint32_t>(TranslateVirtual(0x40000004), 0x00010000);
return 0; return 0;
} }
@ -266,26 +273,24 @@ void Memory::UnmapViews() {
} }
void Memory::Zero(uint32_t address, uint32_t size) { void Memory::Zero(uint32_t address, uint32_t size) {
uint8_t* p = membase_ + address; std::memset(TranslateVirtual(address), 0, size);
std::memset(p, 0, size);
} }
void Memory::Fill(uint32_t address, uint32_t size, uint8_t value) { void Memory::Fill(uint32_t address, uint32_t size, uint8_t value) {
uint8_t* p = membase_ + address; std::memset(TranslateVirtual(address), value, size);
std::memset(p, value, size);
} }
void Memory::Copy(uint32_t dest, uint32_t src, uint32_t size) { void Memory::Copy(uint32_t dest, uint32_t src, uint32_t size) {
uint8_t* pdest = membase_ + dest; uint8_t* pdest = TranslateVirtual(dest);
const uint8_t* psrc = membase_ + src; const uint8_t* psrc = TranslateVirtual(src);
std::memcpy(pdest, psrc, size); std::memcpy(pdest, psrc, size);
} }
uint32_t Memory::SearchAligned(uint32_t start, uint32_t end, uint32_t Memory::SearchAligned(uint32_t start, uint32_t end,
const uint32_t* values, size_t value_count) { const uint32_t* values, size_t value_count) {
assert_true(start <= end); assert_true(start <= end);
const uint32_t* p = reinterpret_cast<const uint32_t*>(membase_ + start); auto p = TranslateVirtual<const uint32_t*>(start);
const uint32_t* pe = reinterpret_cast<const uint32_t*>(membase_ + end); auto pe = TranslateVirtual<const uint32_t*>(end);
while (p != pe) { while (p != pe) {
if (*p == values[0]) { if (*p == values[0]) {
const uint32_t* pc = p + 1; const uint32_t* pc = p + 1;
@ -297,7 +302,7 @@ uint32_t Memory::SearchAligned(uint32_t start, uint32_t end,
matched++; matched++;
} }
if (matched == value_count) { if (matched == value_count) {
return uint32_t(reinterpret_cast<const uint8_t*>(p) - membase_); return uint32_t(reinterpret_cast<const uint8_t*>(p) - virtual_membase_);
} }
} }
p++; p++;
@ -309,7 +314,7 @@ bool Memory::AddMappedRange(uint32_t address, uint32_t mask, uint32_t size,
void* context, cpu::MMIOReadCallback read_callback, void* context, cpu::MMIOReadCallback read_callback,
cpu::MMIOWriteCallback write_callback) { cpu::MMIOWriteCallback write_callback) {
DWORD protect = PAGE_NOACCESS; DWORD protect = PAGE_NOACCESS;
if (!VirtualAlloc(Translate(address), size, MEM_COMMIT, protect)) { if (!VirtualAlloc(TranslateVirtual(address), size, MEM_COMMIT, protect)) {
XELOGE("Unable to map range; commit/protect failed"); XELOGE("Unable to map range; commit/protect failed");
return false; return false;
} }
@ -361,7 +366,7 @@ uint32_t Memory::HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags,
} }
if (result) { if (result) {
if (flags & MEMORY_FLAG_ZERO) { if (flags & MEMORY_FLAG_ZERO) {
memset(Translate(result), 0, size); memset(TranslateVirtual(result), 0, size);
} }
} }
return result; return result;
@ -379,7 +384,7 @@ uint32_t Memory::HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags,
return 0; return 0;
} }
uint8_t* p = Translate(base_address); uint8_t* p = TranslateVirtual(base_address);
// TODO(benvanik): check if address range is in use with a query. // TODO(benvanik): check if address range is in use with a query.
void* pv = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE); void* pv = VirtualAlloc(p, size, MEM_COMMIT, PAGE_READWRITE);
@ -405,20 +410,20 @@ int Memory::HeapFree(uint32_t address, uint32_t size) {
return physical_heap_->Free(address, size) ? 0 : 1; return physical_heap_->Free(address, size) ? 0 : 1;
} else { } else {
// A placed address. Decommit. // A placed address. Decommit.
uint8_t* p = Translate(address); uint8_t* p = TranslateVirtual(address);
return VirtualFree(p, size, MEM_DECOMMIT) ? 0 : 1; return VirtualFree(p, size, MEM_DECOMMIT) ? 0 : 1;
} }
} }
bool Memory::QueryInformation(uint32_t base_address, AllocationInfo* mem_info) { bool Memory::QueryInformation(uint32_t base_address, AllocationInfo* mem_info) {
uint8_t* p = Translate(base_address); uint8_t* p = TranslateVirtual(base_address);
MEMORY_BASIC_INFORMATION mbi; MEMORY_BASIC_INFORMATION mbi;
if (!VirtualQuery(p, &mbi, sizeof(mbi))) { if (!VirtualQuery(p, &mbi, sizeof(mbi))) {
return false; return false;
} }
mem_info->base_address = base_address; mem_info->base_address = base_address;
mem_info->allocation_base = static_cast<uint32_t>( mem_info->allocation_base = static_cast<uint32_t>(
reinterpret_cast<uint8_t*>(mbi.AllocationBase) - membase_); reinterpret_cast<uint8_t*>(mbi.AllocationBase) - virtual_membase_);
mem_info->allocation_protect = mbi.AllocationProtect; mem_info->allocation_protect = mbi.AllocationProtect;
mem_info->region_size = mbi.RegionSize; mem_info->region_size = mbi.RegionSize;
mem_info->state = mbi.State; mem_info->state = mbi.State;
@ -436,7 +441,7 @@ uint32_t Memory::QuerySize(uint32_t base_address) {
return physical_heap_->QuerySize(base_address); return physical_heap_->QuerySize(base_address);
} else { } else {
// A placed address. // A placed address.
uint8_t* p = Translate(base_address); uint8_t* p = TranslateVirtual(base_address);
MEMORY_BASIC_INFORMATION mem_info; MEMORY_BASIC_INFORMATION mem_info;
if (VirtualQuery(p, &mem_info, sizeof(mem_info))) { if (VirtualQuery(p, &mem_info, sizeof(mem_info))) {
return uint32_t(mem_info.RegionSize); return uint32_t(mem_info.RegionSize);
@ -448,7 +453,7 @@ uint32_t Memory::QuerySize(uint32_t base_address) {
} }
int Memory::Protect(uint32_t address, uint32_t size, uint32_t access) { int Memory::Protect(uint32_t address, uint32_t size, uint32_t access) {
uint8_t* p = Translate(address); uint8_t* p = TranslateVirtual(address);
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
p += heap_guard_size; p += heap_guard_size;
@ -464,7 +469,7 @@ int Memory::Protect(uint32_t address, uint32_t size, uint32_t access) {
} }
uint32_t Memory::QueryProtect(uint32_t address) { uint32_t Memory::QueryProtect(uint32_t address) {
uint8_t* p = Translate(address); uint8_t* p = TranslateVirtual(address);
MEMORY_BASIC_INFORMATION info; MEMORY_BASIC_INFORMATION info;
size_t info_size = VirtualQuery((void*)p, &info, sizeof(info)); size_t info_size = VirtualQuery((void*)p, &info, sizeof(info));
if (!info_size) { if (!info_size) {
@ -563,7 +568,7 @@ uint32_t MemoryHeap::Alloc(uint32_t base_address, uint32_t size, uint32_t flags,
} }
uint32_t MemoryHeap::Free(uint32_t address, uint32_t size) { uint32_t MemoryHeap::Free(uint32_t address, uint32_t size) {
uint8_t* p = memory_->Translate(address); uint8_t* p = memory_->TranslateVirtual(address);
// Heap allocated address. // Heap allocated address.
size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; size_t heap_guard_size = FLAGS_heap_guard_pages * 4096;
@ -606,7 +611,7 @@ uint32_t MemoryHeap::Free(uint32_t address, uint32_t size) {
} }
uint32_t MemoryHeap::QuerySize(uint32_t base_address) { uint32_t MemoryHeap::QuerySize(uint32_t base_address) {
uint8_t* p = memory_->Translate(base_address); uint8_t* p = memory_->TranslateVirtual(base_address);
// Heap allocated address. // Heap allocated address.
uint32_t heap_guard_size = uint32_t(FLAGS_heap_guard_pages * 4096); uint32_t heap_guard_size = uint32_t(FLAGS_heap_guard_pages * 4096);

View File

@ -55,10 +55,25 @@ class Memory {
int Initialize(); int Initialize();
inline uint8_t* membase() const { return membase_; } inline uint8_t* virtual_membase() const { return virtual_membase_; }
inline uint8_t* Translate(uint64_t guest_address) const { inline uint8_t* TranslateVirtual(uint32_t guest_address) const {
return membase_ + guest_address; return virtual_membase_ + guest_address;
}; };
template <typename T>
inline T TranslateVirtual(uint32_t guest_address) const {
return reinterpret_cast<T>(virtual_membase_ + guest_address);
};
inline uint8_t* physical_membase() const { return physical_membase_; }
inline uint8_t* TranslatePhysical(uint32_t guest_address) const {
return physical_membase_ + (guest_address & 0x1FFFFFFF);
}
template <typename T>
inline T TranslatePhysical(uint32_t guest_address) const {
return reinterpret_cast<T>(physical_membase_ +
(guest_address & 0x1FFFFFFF));
}
inline uint64_t* reserve_address() { return &reserve_address_; } inline uint64_t* reserve_address() { return &reserve_address_; }
inline uint64_t* reserve_value() { return &reserve_value_; } inline uint64_t* reserve_value() { return &reserve_value_; }
@ -100,7 +115,8 @@ class Memory {
private: private:
uint32_t system_page_size_; uint32_t system_page_size_;
uint8_t* membase_; uint8_t* virtual_membase_;
uint8_t* physical_membase_;
uint64_t reserve_address_; uint64_t reserve_address_;
uint64_t reserve_value_; uint64_t reserve_value_;
uint64_t trace_base_; uint64_t trace_base_;