From ec84a688e932fcbcee0a7f50783ea9588ccf74e5 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 29 Mar 2015 11:11:35 -0700 Subject: [PATCH] Starting to properly attribute virtual vs. physical memory accesses. --- src/xenia/apu/audio_driver.h | 4 + src/xenia/apu/audio_system.cc | 9 +- src/xenia/apu/xaudio2/xaudio2_audio_driver.cc | 2 +- src/xenia/cpu/backend/x64/x64_emitter.cc | 3 +- src/xenia/cpu/backend/x64/x64_function.cc | 2 +- src/xenia/cpu/frontend/ppc_context.h | 4 +- src/xenia/cpu/frontend/ppc_hir_builder.cc | 3 +- src/xenia/cpu/frontend/ppc_scanner.cc | 6 +- src/xenia/cpu/frontend/ppc_translator.cc | 9 +- .../cpu/frontend/test/xe-cpu-ppc-test.cc | 4 +- src/xenia/cpu/function.cc | 2 +- src/xenia/cpu/processor.cc | 4 +- src/xenia/cpu/raw_module.cc | 4 +- src/xenia/cpu/thread_state.cc | 14 +- src/xenia/cpu/thread_state.h | 2 - src/xenia/cpu/xex_module.cc | 6 +- src/xenia/emulator.cc | 2 +- src/xenia/gpu/gl4/command_processor.cc | 66 +++--- src/xenia/gpu/gl4/command_processor.h | 5 +- src/xenia/gpu/gl4/gl4_graphics_system.cc | 4 +- src/xenia/gpu/gl4/texture_cache.cc | 6 +- src/xenia/gpu/trace_viewer_main.cc | 38 +-- src/xenia/kernel/app.cc | 4 +- src/xenia/kernel/app.h | 2 +- src/xenia/kernel/apps/xgi_app.cc | 40 ++-- src/xenia/kernel/apps/xlivebase_app.cc | 3 +- src/xenia/kernel/apps/xmp_app.cc | 217 ++++++++---------- src/xenia/kernel/kernel_state.cc | 4 +- src/xenia/kernel/native_list.cc | 33 +-- src/xenia/kernel/objects/xthread.cc | 15 +- src/xenia/kernel/objects/xuser_module.cc | 6 +- src/xenia/kernel/util/shim_utils.h | 4 +- src/xenia/kernel/util/xex2.cc | 15 +- src/xenia/kernel/xboxkrnl_audio_xma.cc | 7 +- src/xenia/kernel/xboxkrnl_module.cc | 49 ++-- src/xenia/kernel/xboxkrnl_rtl.cc | 4 +- src/xenia/kernel/xboxkrnl_threading.cc | 7 +- src/xenia/kernel/xboxkrnl_video.cc | 11 +- src/xenia/kernel/xobject.cc | 11 +- src/xenia/kernel/xobject.h | 4 +- src/xenia/memory.cc | 59 ++--- src/xenia/memory.h | 24 +- 42 files changed, 346 insertions(+), 372 deletions(-) diff --git a/src/xenia/apu/audio_driver.h b/src/xenia/apu/audio_driver.h index f2119801e..1ffaf9006 100644 --- a/src/xenia/apu/audio_driver.h +++ b/src/xenia/apu/audio_driver.h @@ -25,6 +25,10 @@ class AudioDriver { virtual void SubmitFrame(uint32_t samples_ptr) = 0; protected: + inline uint8_t* TranslatePhysical(uint32_t guest_address) const { + return memory_->TranslatePhysical(guest_address); + } + Emulator* emulator_; Memory* memory_; cpu::Processor* processor_; diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index d7734388d..632ddf244 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -182,7 +182,7 @@ uint32_t AudioSystem::AllocateXmaContext() { auto guest_ptr = xma_context_free_list_.back(); xma_context_free_list_.pop_back(); - auto context_ptr = memory()->Translate(guest_ptr); + auto context_ptr = memory()->TranslateVirtual(guest_ptr); // Initialize? @@ -192,7 +192,7 @@ uint32_t AudioSystem::AllocateXmaContext() { void AudioSystem::ReleaseXmaContext(uint32_t guest_ptr) { std::lock_guard lock(lock_); - auto context_ptr = memory()->Translate(guest_ptr); + auto context_ptr = memory()->TranslateVirtual(guest_ptr); std::memset(context_ptr, 0, kXmaContextSize); 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(); uint32_t ptr = memory()->SystemHeapAlloc(0x4); - auto mem = memory()->membase(); - poly::store_and_swap(mem + ptr, callback_arg); + poly::store_and_swap(memory()->TranslateVirtual(ptr), callback_arg); clients_[index] = {driver, callback, callback_arg, ptr}; @@ -301,7 +300,7 @@ void AudioSystem::WriteRegister(uint64_t addr, uint64_t value) { // feeding data. uint32_t guest_ptr = 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(context_ptr + 0); bool has_valid_input = (dword0 & 0x00300000) != 0; if (has_valid_input) { diff --git a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc index 8515790e2..7a444344e 100644 --- a/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc +++ b/src/xenia/apu/xaudio2/xaudio2_audio_driver.cc @@ -122,7 +122,7 @@ void XAudio2AudioDriver::SubmitFrame(uint32_t frame_ptr) { // Process samples! They are big-endian floats. HRESULT hr; - auto input_frame = reinterpret_cast(emulator_->memory()->membase() + frame_ptr); + auto input_frame = memory_->TranslatePhysical(frame_ptr); auto output_frame = reinterpret_cast(frame_); auto interleave_channels = frame_channels_; diff --git a/src/xenia/cpu/backend/x64/x64_emitter.cc b/src/xenia/cpu/backend/x64/x64_emitter.cc index 294c5463f..d7745459f 100644 --- a/src/xenia/cpu/backend/x64/x64_emitter.cc +++ b/src/xenia/cpu/backend/x64/x64_emitter.cc @@ -368,8 +368,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) { auto thread_state = *reinterpret_cast(raw_context); uint32_t str_ptr = uint32_t(thread_state->context()->r[3]); uint16_t str_len = uint16_t(thread_state->context()->r[4]); - const char* str = - reinterpret_cast(thread_state->memory()->Translate(str_ptr)); + auto str = thread_state->memory()->TranslateVirtual(str_ptr); // TODO(benvanik): truncate to length? PLOGD("(DebugPrint) %s", str); return 0; diff --git a/src/xenia/cpu/backend/x64/x64_function.cc b/src/xenia/cpu/backend/x64/x64_function.cc index e88967118..705ac5cc7 100644 --- a/src/xenia/cpu/backend/x64/x64_function.cc +++ b/src/xenia/cpu/backend/x64/x64_function.cc @@ -37,7 +37,7 @@ int X64Function::RemoveBreakpointImpl(Breakpoint* breakpoint) { return 0; } int X64Function::CallImpl(ThreadState* thread_state, uint32_t return_address) { auto backend = (X64Backend*)thread_state->runtime()->backend(); auto thunk = backend->host_to_guest_thunk(); - thunk(machine_code_, thread_state->raw_context(), + thunk(machine_code_, thread_state->context(), reinterpret_cast(uintptr_t(return_address))); return 0; } diff --git a/src/xenia/cpu/frontend/ppc_context.h b/src/xenia/cpu/frontend/ppc_context.h index c56f451a1..10e7547a1 100644 --- a/src/xenia/cpu/frontend/ppc_context.h +++ b/src/xenia/cpu/frontend/ppc_context.h @@ -44,7 +44,7 @@ typedef struct alignas(64) PPCContext_s { // TODO(benvanik): find a nice way to describe this to the JIT. ThreadState* thread_state; // TODO(benvanik): this is getting nasty. Must be here. - uint8_t* membase; + uint8_t* virtual_membase; // Most frequently used registers first. uint64_t r[32]; // General purpose registers @@ -210,6 +210,8 @@ typedef struct alignas(64) PPCContext_s { // current runtime and its data. Runtime* runtime; + uint8_t* physical_membase; + void SetRegFromString(const char* name, const char* value); bool CompareRegWithString(const char* name, const char* value, char* out_value, size_t out_value_size); diff --git a/src/xenia/cpu/frontend/ppc_hir_builder.cc b/src/xenia/cpu/frontend/ppc_hir_builder.cc index f1f11577e..7bc180ec0 100644 --- a/src/xenia/cpu/frontend/ppc_hir_builder.cc +++ b/src/xenia/cpu/frontend/ppc_hir_builder.cc @@ -46,7 +46,6 @@ int PPCHIRBuilder::Emit(FunctionInfo* symbol_info, uint32_t flags) { SCOPE_profile_cpu_f("cpu"); Memory* memory = frontend_->memory(); - const uint8_t* p = memory->membase(); symbol_info_ = symbol_info; 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; address += 4, offset++) { i.address = address; - i.code = poly::load_and_swap(p + address); + i.code = poly::load_and_swap(memory->TranslateVirtual(address)); // TODO(benvanik): find a way to avoid using the opcode tables. i.type = GetInstrType(i.code); trace_info_.dest_count = 0; diff --git a/src/xenia/cpu/frontend/ppc_scanner.cc b/src/xenia/cpu/frontend/ppc_scanner.cc index 24cabf19b..9cdee0234 100644 --- a/src/xenia/cpu/frontend/ppc_scanner.cc +++ b/src/xenia/cpu/frontend/ppc_scanner.cc @@ -50,7 +50,6 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { // split up and the second half is treated as another function. Memory* memory = frontend_->memory(); - const uint8_t* p = memory->membase(); LOGPPC("Analyzing function %.8X...", symbol_info->address()); @@ -64,7 +63,7 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { InstrData i; while (true) { i.address = address; - i.code = poly::load_and_swap(p + address); + i.code = poly::load_and_swap(memory->TranslateVirtual(address)); // If we fetched 0 assume that we somehow hit one of the awesome // 'no really we meant to end after that bl' functions. @@ -281,7 +280,6 @@ int PPCScanner::FindExtents(FunctionInfo* symbol_info) { std::vector PPCScanner::FindBlocks(FunctionInfo* symbol_info) { Memory* memory = frontend_->memory(); - const uint8_t* p = memory->membase(); std::map block_map; @@ -292,7 +290,7 @@ std::vector PPCScanner::FindBlocks(FunctionInfo* symbol_info) { InstrData i; for (uint32_t address = start_address; address <= end_address; address += 4) { i.address = address; - i.code = poly::load_and_swap(p + address); + i.code = poly::load_and_swap(memory->TranslateVirtual(address)); if (!i.code) { continue; } diff --git a/src/xenia/cpu/frontend/ppc_translator.cc b/src/xenia/cpu/frontend/ppc_translator.cc index 94cebb28a..419169801 100644 --- a/src/xenia/cpu/frontend/ppc_translator.cc +++ b/src/xenia/cpu/frontend/ppc_translator.cc @@ -175,7 +175,6 @@ int PPCTranslator::Translate(FunctionInfo* symbol_info, void PPCTranslator::DumpSource(FunctionInfo* symbol_info, poly::StringBuffer* string_buffer) { Memory* memory = frontend_->memory(); - const uint8_t* p = memory->membase(); string_buffer->Append("%s fn %.8X-%.8X %s\n", symbol_info->module()->name().c_str(), @@ -184,14 +183,14 @@ void PPCTranslator::DumpSource(FunctionInfo* symbol_info, auto blocks = scanner_->FindBlocks(symbol_info); - uint64_t start_address = symbol_info->address(); - uint64_t end_address = symbol_info->end_address(); + uint32_t start_address = symbol_info->address(); + uint32_t end_address = symbol_info->end_address(); InstrData i; 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++) { i.address = address; - i.code = poly::load_and_swap(p + address); + i.code = poly::load_and_swap(memory->TranslateVirtual(address)); // TODO(benvanik): find a way to avoid using the opcode tables. i.type = GetInstrType(i.code); diff --git a/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc b/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc index 78afe8fac..846667410 100644 --- a/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc +++ b/src/xenia/cpu/frontend/test/xe-cpu-ppc-test.cc @@ -241,7 +241,7 @@ class TestRunner { auto address_str = it.second.substr(0, space_pos); auto bytes_str = it.second.substr(space_pos + 1); 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(); while (*c) { while (*c == ' ') ++c; @@ -283,7 +283,7 @@ class TestRunner { auto address_str = it.second.substr(0, space_pos); auto bytes_str = it.second.substr(space_pos + 1); 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; const char* c = bytes_str.c_str(); while (*c) { diff --git a/src/xenia/cpu/function.cc b/src/xenia/cpu/function.cc index d22812580..35157e71a 100644 --- a/src/xenia/cpu/function.cc +++ b/src/xenia/cpu/function.cc @@ -88,7 +88,7 @@ int Function::Call(ThreadState* thread_state, uint32_t return_address) { } if (handler) { - handler(thread_state->raw_context(), symbol_info_->extern_arg0(), + handler(thread_state->context(), symbol_info_->extern_arg0(), symbol_info_->extern_arg1()); } else { PLOGW("undefined extern call to %.8llX %s", symbol_info_->address(), diff --git a/src/xenia/cpu/processor.cc b/src/xenia/cpu/processor.cc index 13b62d3b3..ed38615bf 100644 --- a/src/xenia/cpu/processor.cc +++ b/src/xenia/cpu/processor.cc @@ -163,8 +163,8 @@ uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address, std::lock_guard lock(interrupt_thread_lock_); // Set 0x10C(r13) to the current CPU ID. - uint8_t* p = memory_->membase(); - poly::store_and_swap(p + interrupt_thread_block_ + 0x10C, cpu); + poly::store_and_swap( + memory_->TranslateVirtual(interrupt_thread_block_ + 0x10C), cpu); // Execute interrupt. uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count); diff --git a/src/xenia/cpu/raw_module.cc b/src/xenia/cpu/raw_module.cc index 461de954a..0ee9afa4d 100644 --- a/src/xenia/cpu/raw_module.cc +++ b/src/xenia/cpu/raw_module.cc @@ -30,8 +30,8 @@ int RawModule::LoadFile(uint32_t base_address, const std::wstring& path) { // Allocate memory. // Since we have no real heap just load it wherever. base_address_ = base_address; - uint8_t* p = memory_->Translate(base_address_); - memset(p, 0, file_length); + uint8_t* p = memory_->TranslateVirtual(base_address_); + std::memset(p, 0, file_length); // Read into memory. fread(p, file_length, 1, file); diff --git a/src/xenia/cpu/thread_state.cc b/src/xenia/cpu/thread_state.cc index 6c5f5fc93..09f6f7f57 100644 --- a/src/xenia/cpu/thread_state.cc +++ b/src/xenia/cpu/thread_state.cc @@ -29,7 +29,6 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id, thread_id_(thread_id), name_(""), backend_data_(0), - raw_context_(0), stack_size_(stack_size), thread_state_address_(thread_state_address) { if (thread_id_ == UINT_MAX) { @@ -50,13 +49,16 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id, assert_not_zero(stack_address_); // Allocate with 64b alignment. - context_ = (PPCContext*)calloc(1, sizeof(PPCContext)); - assert_true(((uint64_t)context_ & 0xF) == 0); + context_ = + reinterpret_cast(_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. context_->reserve_address = memory_->reserve_address(); 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_->thread_state = this; context_->thread_id = thread_id_; @@ -69,8 +71,6 @@ ThreadState::ThreadState(Runtime* runtime, uint32_t thread_id, // 16 to 32b. context_->r[1] -= 64; - raw_context_ = context_; - runtime_->debugger()->OnThreadCreated(this); } @@ -84,7 +84,7 @@ ThreadState::~ThreadState() { thread_state_ = nullptr; } - free(context_); + _aligned_free(context_); if (stack_allocated_) { memory()->SystemHeapFree(stack_address_); } diff --git a/src/xenia/cpu/thread_state.h b/src/xenia/cpu/thread_state.h index fa886a54f..feab50691 100644 --- a/src/xenia/cpu/thread_state.h +++ b/src/xenia/cpu/thread_state.h @@ -38,7 +38,6 @@ class ThreadState { const std::string& name() const { return name_; } void set_name(const std::string& value) { name_ = value; } void* backend_data() const { return backend_data_; } - void* raw_context() const { return raw_context_; } uint32_t stack_address() const { return stack_address_; } size_t stack_size() const { return stack_size_; } uint32_t thread_state_address() const { return thread_state_address_; } @@ -60,7 +59,6 @@ class ThreadState { uint32_t thread_id_; std::string name_; void* backend_data_; - void* raw_context_; uint32_t stack_address_; bool stack_allocated_; uint32_t stack_size_; diff --git a/src/xenia/cpu/xex_module.cc b/src/xenia/cpu/xex_module.cc index 4ea0a8ecb..4845182d1 100644 --- a/src/xenia/cpu/xex_module.cc +++ b/src/xenia/cpu/xex_module.cc @@ -99,8 +99,6 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) { return 1; } - uint8_t* membase = memory_->membase(); - char name[128]; for (size_t n = 0; n < import_info_count; 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. if (kernel_export) { - uint32_t* slot = (uint32_t*)(membase + info->value_address); + auto slot = memory_->TranslateVirtual(info->value_address); if (kernel_export->type == KernelExport::Function) { // Not exactly sure what this should be... if (info->thunk_address) { @@ -176,7 +174,7 @@ int XexModule::SetupLibraryImports(const xe_xex2_import_library_t* library) { // blr // nop // nop - uint8_t* p = memory()->Translate(info->thunk_address); + uint8_t* p = memory()->TranslateVirtual(info->thunk_address); poly::store_and_swap(p + 0x0, 0x44000002); poly::store_and_swap(p + 0x4, 0x4E800020); poly::store_and_swap(p + 0x8, 0x60000000); diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index f7011c15b..afa940772 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -202,7 +202,7 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path, auto ev = xdb::protocol::ProcessStartEvent::Append(memory()->trace_base()); if (ev) { ev->type = xdb::protocol::EventType::PROCESS_START; - ev->membase = reinterpret_cast(memory()->membase()); + ev->membase = reinterpret_cast(memory()->virtual_membase()); auto path_length = poly::to_string(path) .copy(ev->launch_path, sizeof(ev->launch_path) - 1); ev->launch_path[path_length] = 0; diff --git a/src/xenia/gpu/gl4/command_processor.cc b/src/xenia/gpu/gl4/command_processor.cc index fdb69e693..da4451e3a 100644 --- a/src/xenia/gpu/gl4/command_processor.cc +++ b/src/xenia/gpu/gl4/command_processor.cc @@ -51,10 +51,9 @@ CommandProcessor::CachedPipeline::~CachedPipeline() { CommandProcessor::CommandProcessor(GL4GraphicsSystem* graphics_system) : memory_(graphics_system->memory()), - membase_(graphics_system->memory()->membase()), graphics_system_(graphics_system), register_file_(graphics_system_->register_file()), - trace_writer_(graphics_system->memory()->membase()), + trace_writer_(graphics_system->memory()->physical_membase()), trace_state_(TraceState::kDisabled), worker_running_(true), swap_mode_(SwapMode::kNormal), @@ -212,8 +211,8 @@ void CommandProcessor::WorkerMain() { // TODO(benvanik): use reader->Read_update_freq_ and only issue after moving // that many indices. if (read_ptr_writeback_ptr_) { - poly::store_and_swap(membase_ + read_ptr_writeback_ptr_, - read_ptr_index_); + poly::store_and_swap( + 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. uint32_t scratch_addr = regs->values[XE_GPU_REG_SCRATCH_ADDR].u32; uint32_t mem_addr = scratch_addr + (scratch_reg * 4); - poly::store_and_swap(membase_ + xenos::GpuToCpu(mem_addr), + poly::store_and_swap(memory_->TranslatePhysical(mem_addr), value); } } @@ -651,8 +650,8 @@ void CommandProcessor::ExecutePrimaryBuffer(uint32_t start_index, // Execute commands! uint32_t ptr_mask = (primary_buffer_size_ / sizeof(uint32_t)) - 1; - RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, start_ptr, - end_ptr); + RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_, + ptr_mask, start_ptr, end_ptr); while (reader.can_read()) { ExecutePacket(&reader); } @@ -670,8 +669,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) { // Execute commands! uint32_t ptr_mask = 0; - RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr, - ptr + length * sizeof(uint32_t)); + RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_, + ptr_mask, ptr, ptr + length * sizeof(uint32_t)); while (reader.can_read()) { ExecutePacket(&reader); } @@ -681,8 +680,8 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t length) { void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) { uint32_t ptr_mask = 0; - RingbufferReader reader(membase_, primary_buffer_ptr_, ptr_mask, ptr, - ptr + count * sizeof(uint32_t)); + RingbufferReader reader(memory_->physical_membase(), primary_buffer_ptr_, + ptr_mask, ptr, ptr + count * sizeof(uint32_t)); while (reader.can_read()) { ExecutePacket(&reader); } @@ -992,7 +991,7 @@ bool CommandProcessor::ExecutePacketType3_WAIT_REG_MEM(RingbufferReader* reader, // Memory. auto endianness = static_cast(poll_reg_addr & 0x3); poll_reg_addr &= ~0x3; - value = poly::load(membase_ + GpuToCpu(poll_reg_addr)); + value = poly::load(memory_->TranslatePhysical(poll_reg_addr)); value = GpuSwap(value, endianness); trace_writer_.WriteMemoryRead(poll_reg_addr, 4); } else { @@ -1095,7 +1094,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader, auto endianness = static_cast(poll_reg_addr & 0x3); poll_reg_addr &= ~0x3; trace_writer_.WriteMemoryRead(poll_reg_addr, 4); - value = poly::load(membase_ + GpuToCpu(poll_reg_addr)); + value = poly::load(memory_->TranslatePhysical(poll_reg_addr)); value = GpuSwap(value, endianness); } else { // Register. @@ -1136,7 +1135,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader, auto endianness = static_cast(write_reg_addr & 0x3); write_reg_addr &= ~0x3; 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); } else { // Register. @@ -1182,7 +1181,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_SHD( auto endianness = static_cast(address & 0x3); address &= ~0x3; 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); return true; } @@ -1207,7 +1206,7 @@ bool CommandProcessor::ExecutePacketType3_EVENT_WRITE_EXT( }; assert_true(endianness == xenos::Endian::k8in16); poly::copy_and_swap_16_aligned( - reinterpret_cast(membase_ + GpuToCpu(address)), extents, + reinterpret_cast(memory_->TranslatePhysical(address)), extents, poly::countof(extents)); trace_writer_.WriteMemoryWrite(address, sizeof(extents)); return true; @@ -1367,8 +1366,8 @@ bool CommandProcessor::ExecutePacketType3_LOAD_ALU_CONSTANT( } trace_writer_.WriteMemoryRead(address, size_dwords * 4); for (uint32_t n = 0; n < size_dwords; n++, index++) { - uint32_t data = - poly::load_and_swap(membase_ + GpuToCpu(address + n * 4)); + uint32_t data = poly::load_and_swap( + memory_->TranslatePhysical(address + n * 4)); WriteRegister(index, data); } return true; @@ -1397,8 +1396,7 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD(RingbufferReader* reader, uint32_t size_dwords = start_size & 0xFFFF; // dwords assert_true(start == 0); trace_writer_.WriteMemoryRead(addr, size_dwords * 4); - LoadShader(shader_type, - reinterpret_cast(membase_ + GpuToCpu(addr)), + LoadShader(shader_type, addr, memory_->TranslatePhysical(addr), size_dwords); return true; } @@ -1414,8 +1412,8 @@ bool CommandProcessor::ExecutePacketType3_IM_LOAD_IMMEDIATE( uint32_t size_dwords = start_size & 0xFFFF; // dwords assert_true(start == 0); reader->CheckRead(size_dwords); - LoadShader(shader_type, reinterpret_cast(membase_ + reader->ptr()), - size_dwords); + LoadShader(shader_type, reader->ptr(), + memory_->TranslatePhysical(reader->ptr()), size_dwords); reader->Advance(size_dwords); return true; } @@ -1429,11 +1427,12 @@ bool CommandProcessor::ExecutePacketType3_INVALIDATE_STATE( } bool CommandProcessor::LoadShader(ShaderType shader_type, - const uint32_t* address, + uint32_t guest_address, + const uint32_t* host_address, uint32_t dword_count) { // Hash the input memory and lookup the shader. 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); if (it != shader_cache_.end()) { // Found in the cache. @@ -1442,17 +1441,16 @@ bool CommandProcessor::LoadShader(ShaderType shader_type, } else { // Not found in cache. // No translation is performed here, as it depends on program_cntl. - auto shader = - std::make_unique(shader_type, hash, address, dword_count); + auto shader = std::make_unique(shader_type, hash, host_address, + dword_count); shader_ptr = shader.get(); shader_cache_.insert({hash, shader_ptr}); all_shaders_.emplace_back(std::move(shader)); XELOGGPU("Set %s shader at %0.8X (%db):\n%s", shader_type == ShaderType::kVertex ? "vertex" : "pixel", - uint32_t(reinterpret_cast(address) - - reinterpret_cast(membase_)), - dword_count * 4, shader_ptr->ucode_disassembly().c_str()); + guest_address, dword_count * 4, + shader_ptr->ucode_disassembly().c_str()); } switch (shader_type) { case ShaderType::kVertex: @@ -2299,11 +2297,11 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateIndexBuffer() { &allocation)) { if (info.format == IndexFormat::kInt32) { auto dest = reinterpret_cast(allocation.host_ptr); - auto src = reinterpret_cast(membase_ + info.guest_base); + auto src = memory_->TranslatePhysical(info.guest_base); poly::copy_and_swap_32_aligned(dest, src, info.count); } else { auto dest = reinterpret_cast(allocation.host_ptr); - auto src = reinterpret_cast(membase_ + info.guest_base); + auto src = memory_->TranslatePhysical(info.guest_base); poly::copy_and_swap_16_aligned(dest, src, info.count); } draw_batcher_.set_index_buffer(allocation); @@ -2357,7 +2355,7 @@ CommandProcessor::UpdateStatus CommandProcessor::PopulateVertexBuffers() { // it (and if it matches just discard and reuse). poly::copy_and_swap_32_aligned( reinterpret_cast(allocation.host_ptr), - reinterpret_cast(membase_ + (fetch->address << 2)), + memory_->TranslatePhysical(fetch->address << 2), valid_range / 4); if (!has_bindless_vbos_) { @@ -2697,7 +2695,7 @@ bool CommandProcessor::IssueCopy() { assert_true(fetch->type == 3); assert_true(fetch->endian == 2); 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); int32_t dest_min_x = int32_t((std::min( std::min( @@ -2734,7 +2732,7 @@ bool CommandProcessor::IssueCopy() { // Destination pointer in guest memory. // We have GL throw bytes directly into it. // 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. switch (copy_command) { diff --git a/src/xenia/gpu/gl4/command_processor.h b/src/xenia/gpu/gl4/command_processor.h index 1d8aa4142..a919401ba 100644 --- a/src/xenia/gpu/gl4/command_processor.h +++ b/src/xenia/gpu/gl4/command_processor.h @@ -193,8 +193,8 @@ class CommandProcessor { bool ExecutePacketType3_INVALIDATE_STATE(RingbufferReader* reader, uint32_t packet, uint32_t count); - bool LoadShader(ShaderType shader_type, const uint32_t* address, - uint32_t dword_count); + bool LoadShader(ShaderType shader_type, uint32_t guest_address, + const uint32_t* host_address, uint32_t dword_count); bool IssueDraw(); UpdateStatus UpdateShaders(PrimitiveType prim_type); @@ -214,7 +214,6 @@ class CommandProcessor { GLuint depth_target); Memory* memory_; - uint8_t* membase_; GL4GraphicsSystem* graphics_system_; RegisterFile* register_file_; diff --git a/src/xenia/gpu/gl4/gl4_graphics_system.cc b/src/xenia/gpu/gl4/gl4_graphics_system.cc index 0ed7d4691..3e2257881 100644 --- a/src/xenia/gpu/gl4/gl4_graphics_system.cc +++ b/src/xenia/gpu/gl4/gl4_graphics_system.cc @@ -181,7 +181,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size, case TraceCommandType::kPacketStart: { auto cmd = reinterpret_cast(trace_ptr); 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); trace_ptr += cmd->count * 4; pending_packet = cmd; @@ -203,7 +203,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size, case TraceCommandType::kMemoryRead: { auto cmd = reinterpret_cast(trace_ptr); trace_ptr += sizeof(*cmd); - std::memcpy(memory()->Translate(cmd->base_ptr), trace_ptr, + std::memcpy(memory()->TranslatePhysical(cmd->base_ptr), trace_ptr, cmd->length); trace_ptr += cmd->length; break; diff --git a/src/xenia/gpu/gl4/texture_cache.cc b/src/xenia/gpu/gl4/texture_cache.cc index f458182b8..e873415b8 100644 --- a/src/xenia/gpu/gl4/texture_cache.cc +++ b/src/xenia/gpu/gl4/texture_cache.cc @@ -676,7 +676,8 @@ void TextureSwap(Endian endianness, void* dest, const void* src, bool TextureCache::UploadTexture2D(GLuint texture, 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 = texture_configs[uint32_t(texture_info.format_info->format)]; @@ -778,7 +779,8 @@ bool TextureCache::UploadTexture2D(GLuint texture, bool TextureCache::UploadTextureCube(GLuint texture, 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 = texture_configs[uint32_t(texture_info.format_info->format)]; diff --git a/src/xenia/gpu/trace_viewer_main.cc b/src/xenia/gpu/trace_viewer_main.cc index bacce66ea..1a46ca5cf 100644 --- a/src/xenia/gpu/trace_viewer_main.cc +++ b/src/xenia/gpu/trace_viewer_main.cc @@ -832,7 +832,7 @@ class TracePlayer : public TraceReader { }; void DrawControllerUI(xe::ui::MainWindow* window, TracePlayer& player, - uint8_t* membase) { + Memory* memory) { ImGui::SetNextWindowPos(ImVec2(5, 5), ImGuiSetCondition_FirstUseEver); if (!ImGui::Begin("Controller", nullptr, ImVec2(340, 60))) { ImGui::End(); @@ -871,7 +871,7 @@ void DrawControllerUI(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); if (!ImGui::Begin("Command List", nullptr, ImVec2(200, 640))) { ImGui::End(); @@ -1013,7 +1013,7 @@ ShaderDisplayType DrawShaderTypeUI() { } void DrawShaderUI(xe::ui::MainWindow* window, TracePlayer& player, - uint8_t* membase, gl4::GL4Shader* shader, + Memory* memory, gl4::GL4Shader* shader, ShaderDisplayType display_type) { // Must be prepared for advanced display modes. if (display_type != ShaderDisplayType::kUcode) { @@ -1166,10 +1166,10 @@ void DrawTextureInfo(TracePlayer& player, const Shader::SamplerDesc& desc) { 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 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; int column_count = 0; 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, - uint8_t* membase) { + Memory* memory) { auto gs = static_cast(player.graphics_system()); auto cp = gs->command_processor(); 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)); auto shader = cp->active_vertex_shader(); if (shader) { - DrawShaderUI(window, player, membase, shader, shader_display_type); + DrawShaderUI(window, player, memory, shader, shader_display_type); } else { 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)); auto shader = cp->active_pixel_shader(); if (shader) { - DrawShaderUI(window, player, membase, shader, shader_display_type); + DrawShaderUI(window, player, memory, shader, shader_display_type); } else { ImGui::TextColored(kColorError, "ERROR: no pixel shader set"); } @@ -1864,10 +1864,10 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player, ImGui::NextColumn(); ImGui::Separator(); } - size_t element_size = + uint32_t element_size = draw_info.index_format == IndexFormat::kInt32 ? 4 : 2; - const uint8_t* data_ptr = - membase + draw_info.index_buffer_ptr + (display_start * element_size); + const uint8_t* data_ptr = memory->TranslatePhysical( + draw_info.index_buffer_ptr + (display_start * element_size)); for (int i = display_start; i < display_end; ++i, data_ptr += element_size) { if (i < 10) { @@ -1927,7 +1927,7 @@ void DrawStateUI(xe::ui::MainWindow* window, TracePlayer& player, fetch->size * 4, kEndiannessNames[int(fetch->endian)])) { ImGui::BeginChild("#vertices", ImVec2(0, 300)); - DrawVertexFetcher(membase, shader, desc, fetch); + DrawVertexFetcher(memory, shader, desc, fetch); ImGui::EndChild(); ImGui::TreePop(); } @@ -2019,7 +2019,7 @@ void DrawStateUI(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::SetNextWindowPos(ImVec2(float(window->width()) - 500 - 5, 5), ImGuiSetCondition_FirstUseEver); @@ -2160,13 +2160,13 @@ void DrawPacketDisassemblerUI(xe::ui::MainWindow* window, TracePlayer& player, 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(); - DrawControllerUI(window, player, membase); - DrawCommandListUI(window, player, membase); - DrawStateUI(window, player, membase); - DrawPacketDisassemblerUI(window, player, membase); + DrawControllerUI(window, player, memory); + DrawCommandListUI(window, player, memory); + DrawStateUI(window, player, memory); + DrawPacketDisassemblerUI(window, player, memory); } void ImImpl_Setup(); @@ -2276,7 +2276,7 @@ int trace_viewer_main(std::vector& args) { ImGui::NewFrame(); - DrawUI(window, player, emulator->memory()->membase()); + DrawUI(window, player, emulator->memory()); glViewport(0, 0, (int)io.DisplaySize.x, (int)io.DisplaySize.y); ImGui::Render(); diff --git a/src/xenia/kernel/app.cc b/src/xenia/kernel/app.cc index 12deb5ce7..619b0522b 100644 --- a/src/xenia/kernel/app.cc +++ b/src/xenia/kernel/app.cc @@ -16,8 +16,8 @@ namespace kernel { XApp::XApp(KernelState* kernel_state, uint32_t app_id) : kernel_state_(kernel_state), - app_id_(app_id), - membase_(kernel_state->memory()->membase()) {} + memory_(kernel_state->memory()), + app_id_(app_id) {} void XAppManager::RegisterApp(std::unique_ptr app) { assert_zero(app_lookup_.count(app->app_id())); diff --git a/src/xenia/kernel/app.h b/src/xenia/kernel/app.h index c30144479..01d7f2349 100644 --- a/src/xenia/kernel/app.h +++ b/src/xenia/kernel/app.h @@ -33,8 +33,8 @@ class XApp { XApp(KernelState* kernel_state, uint32_t app_id); KernelState* kernel_state_; + Memory* memory_; uint32_t app_id_; - uint8_t* membase_; }; class XAppManager { diff --git a/src/xenia/kernel/apps/xgi_app.cc b/src/xenia/kernel/apps/xgi_app.cc index 717d95c19..e99d36e94 100644 --- a/src/xenia/kernel/apps/xgi_app.cc +++ b/src/xenia/kernel/apps/xgi_app.cc @@ -22,6 +22,7 @@ XXGIApp::XXGIApp(KernelState* kernel_state) : XApp(kernel_state, 0xFB) {} X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) { // NOTE: buffer_length may be zero or valid. + auto buffer = memory_->TranslateVirtual(buffer_ptr); switch (message) { case 0x000B0006: { assert_true(!buffer_length || buffer_length == 24); @@ -30,35 +31,26 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, // qword 0 // dword r4 context enum // dword r5 value - uint32_t user_index = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t context_id = - poly::load_and_swap(membase_ + buffer_ptr + 16); - uint32_t context_value = - poly::load_and_swap(membase_ + buffer_ptr + 20); + uint32_t user_index = poly::load_and_swap(buffer + 0); + uint32_t context_id = poly::load_and_swap(buffer + 16); + uint32_t context_value = poly::load_and_swap(buffer + 20); XELOGD("XUserSetContextEx(%.8X, %.8X, %.8X)", user_index, context_id, context_value); return X_ERROR_SUCCESS; } case 0x000B0007: { - uint32_t user_index = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t property_id = - poly::load_and_swap(membase_ + buffer_ptr + 16); - uint32_t value_size = - poly::load_and_swap(membase_ + buffer_ptr + 20); - uint32_t value_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 24); + uint32_t user_index = poly::load_and_swap(buffer + 0); + uint32_t property_id = poly::load_and_swap(buffer + 16); + uint32_t value_size = poly::load_and_swap(buffer + 20); + uint32_t value_ptr = poly::load_and_swap(buffer + 24); XELOGD("XUserSetPropertyEx(%.8X, %.8X, %d, %.8X)", user_index, property_id, value_size, value_ptr); return X_ERROR_SUCCESS; } case 0x000B0008: { assert_true(!buffer_length || buffer_length == 8); - uint32_t achievement_count = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t achievements_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 4); + uint32_t achievement_count = poly::load_and_swap(buffer + 0); + uint32_t achievements_ptr = poly::load_and_swap(buffer + 4); XELOGD("XUserWriteAchievements(%.8X, %.8X)", achievement_count, achievements_ptr); return X_ERROR_SUCCESS; @@ -76,16 +68,14 @@ X_RESULT XXGIApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, case 0x000B0041: { assert_true(!buffer_length || buffer_length == 32); // 00000000 2789fecc 00000000 00000000 200491e0 00000000 200491f0 20049340 - uint32_t user_index = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t context_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 16); - uint32_t context_id = - poly::load_and_swap(membase_ + context_ptr + 0); + uint32_t user_index = poly::load_and_swap(buffer + 0); + uint32_t context_ptr = poly::load_and_swap(buffer + 16); + auto context = memory_->TranslateVirtual(context_ptr); + uint32_t context_id = poly::load_and_swap(context + 0); XELOGD("XUserGetContext(%.8X, %.8X(%.8X))", user_index, context_ptr, context_id); uint32_t value = 0; - poly::store_and_swap(membase_ + context_ptr + 4, value); + poly::store_and_swap(context + 4, value); return X_ERROR_SUCCESS; } case 0x000B0071: { diff --git a/src/xenia/kernel/apps/xlivebase_app.cc b/src/xenia/kernel/apps/xlivebase_app.cc index e037ac1cf..7488a7ad3 100644 --- a/src/xenia/kernel/apps/xlivebase_app.cc +++ b/src/xenia/kernel/apps/xlivebase_app.cc @@ -24,12 +24,13 @@ X_RESULT XXLiveBaseApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) { // NOTE: buffer_length may be zero or valid. + auto buffer = memory_->TranslateVirtual(buffer_ptr); switch (message) { case 0x00058004: { // Called on startup, seems to just return a bool in the buffer. assert_true(!buffer_length || buffer_length == 4); XELOGD("XLiveBaseGetLogonId(%.8X)", buffer_ptr); - poly::store_and_swap(membase_ + buffer_ptr + 0, 1); // ? + poly::store_and_swap(buffer + 0, 1); // ? return X_ERROR_SUCCESS; } case 0x00058020: { diff --git a/src/xenia/kernel/apps/xmp_app.cc b/src/xenia/kernel/apps/xmp_app.cc index 0ea17b17f..361de7274 100644 --- a/src/xenia/kernel/apps/xmp_app.cc +++ b/src/xenia/kernel/apps/xmp_app.cc @@ -34,7 +34,7 @@ X_RESULT XXMPApp::XMPGetStatus(uint32_t state_ptr) { Sleep(1); XELOGD("XMPGetStatus(%.8X)", state_ptr); - poly::store_and_swap(membase_ + state_ptr, + poly::store_and_swap(memory_->TranslateVirtual(state_ptr), static_cast(state_)); return X_ERROR_SUCCESS; } @@ -54,30 +54,32 @@ X_RESULT XXMPApp::XMPCreateTitlePlaylist( for (uint32_t i = 0; i < song_count; ++i) { auto song = std::make_unique(); song->handle = ++next_song_handle_; - uint8_t* song_base = membase_ + songs_ptr + (i * 36); - song->file_path = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 0)); - song->name = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 4)); - song->artist = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 8)); - song->album = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 12)); - song->album_artist = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 16)); - song->genre = poly::load_and_swap( - membase_ + poly::load_and_swap(song_base + 20)); + uint8_t* song_base = memory_->TranslateVirtual(songs_ptr + (i * 36)); + song->file_path = + poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 0))); + song->name = poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 4))); + song->artist = poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 8))); + song->album = poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 12))); + song->album_artist = + poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 16))); + song->genre = poly::load_and_swap(memory_->TranslateVirtual( + poly::load_and_swap(song_base + 20))); song->track_number = poly::load_and_swap(song_base + 24); song->duration_ms = poly::load_and_swap(song_base + 28); song->format = static_cast( poly::load_and_swap(song_base + 32)); if (out_song_handles) { - poly::store_and_swap(membase_ + out_song_handles + (i * 4), - song->handle); + poly::store_and_swap( + memory_->TranslateVirtual(out_song_handles + (i * 4)), song->handle); } playlist->songs.emplace_back(std::move(song)); } - poly::store_and_swap(membase_ + out_playlist_handle, + poly::store_and_swap(memory_->TranslateVirtual(out_playlist_handle), playlist->handle); std::lock_guard lock(mutex_); @@ -195,64 +197,53 @@ void XXMPApp::OnStateChanged() { X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) { // NOTE: buffer_length may be zero or valid. + auto buffer = memory_->TranslateVirtual(buffer_ptr); switch (message) { case 0x00070002: { assert_true(!buffer_length || buffer_length == 12); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t playlist_handle = - poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t song_handle = - poly::load_and_swap(membase_ + buffer_ptr + 8); // 0? + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t playlist_handle = poly::load_and_swap(buffer + 4); + uint32_t song_handle = poly::load_and_swap(buffer + 8); // 0? assert_true(xmp_client == 0x00000002); return XMPPlayTitlePlaylist(playlist_handle, song_handle); } case 0x00070003: { assert_true(!buffer_length || buffer_length == 4); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); assert_true(xmp_client == 0x00000002); return XMPContinue(); } case 0x00070004: { assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t unk = poly::load_and_swap(membase_ + buffer_ptr + 4); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t unk = poly::load_and_swap(buffer + 4); assert_true(xmp_client == 0x00000002); return XMPStop(unk); } case 0x00070005: { assert_true(!buffer_length || buffer_length == 4); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); assert_true(xmp_client == 0x00000002); return XMPPause(); } case 0x00070006: { assert_true(!buffer_length || buffer_length == 4); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); assert_true(xmp_client == 0x00000002); return XMPNext(); } case 0x00070007: { assert_true(!buffer_length || buffer_length == 4); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); assert_true(xmp_client == 0x00000002); return XMPPrevious(); } case 0x00070008: { assert_true(!buffer_length || buffer_length == 16); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t playback_mode = - poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t repeat_mode = - poly::load_and_swap(membase_ + buffer_ptr + 8); - uint32_t flags = - poly::load_and_swap(membase_ + buffer_ptr + 12); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t playback_mode = poly::load_and_swap(buffer + 4); + uint32_t repeat_mode = poly::load_and_swap(buffer + 8); + uint32_t flags = poly::load_and_swap(buffer + 12); assert_true(xmp_client == 0x00000002); XELOGD("XMPSetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode, repeat_mode, flags); @@ -264,29 +255,27 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, } case 0x00070009: { assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); uint32_t state_ptr = poly::load_and_swap( - membase_ + buffer_ptr + 4); // out ptr to 4b - expect 0 + buffer + 4); // out ptr to 4b - expect 0 assert_true(xmp_client == 0x00000002); return XMPGetStatus(state_ptr); } case 0x0007000B: { assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); uint32_t float_ptr = poly::load_and_swap( - membase_ + buffer_ptr + 4); // out ptr to 4b - floating point + buffer + 4); // out ptr to 4b - floating point assert_true(xmp_client == 0x00000002); XELOGD("XMPGetVolume(%.8X)", float_ptr); - poly::store_and_swap(membase_ + float_ptr, volume_); + poly::store_and_swap(memory_->TranslateVirtual(float_ptr), + volume_); return X_ERROR_SUCCESS; } case 0x0007000C: { assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - float float_value = poly::load_and_swap(membase_ + buffer_ptr + 4); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + float float_value = poly::load_and_swap(buffer + 4); assert_true(xmp_client == 0x00000002); XELOGD("XMPSetVolume(%g)", float_value); volume_ = float_value; @@ -294,27 +283,19 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, } case 0x0007000D: { assert_true(!buffer_length || buffer_length == 36); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t dummy_alloc_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t dummy_alloc_size = - poly::load_and_swap(membase_ + buffer_ptr + 8); - uint32_t songs_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 12); - uint32_t song_count = - poly::load_and_swap(membase_ + buffer_ptr + 16); - uint32_t playlist_name_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 20); - uint32_t flags = - poly::load_and_swap(membase_ + buffer_ptr + 24); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t dummy_alloc_ptr = poly::load_and_swap(buffer + 4); + uint32_t dummy_alloc_size = poly::load_and_swap(buffer + 8); + uint32_t songs_ptr = poly::load_and_swap(buffer + 12); + uint32_t song_count = poly::load_and_swap(buffer + 16); + uint32_t playlist_name_ptr = poly::load_and_swap(buffer + 20); + uint32_t flags = poly::load_and_swap(buffer + 24); uint32_t song_handles_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 28); // 0? - uint32_t playlist_handle_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 32); + poly::load_and_swap(buffer + 28); // 0? + uint32_t playlist_handle_ptr = poly::load_and_swap(buffer + 32); assert_true(xmp_client == 0x00000002); - auto playlist_name = - poly::load_and_swap(membase_ + playlist_name_ptr); + auto playlist_name = poly::load_and_swap( + memory_->TranslateVirtual(playlist_name_ptr)); // dummy_alloc_ptr is the result of a XamAlloc of dummy_alloc_size. assert_true(dummy_alloc_size == song_count * 128); 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: { assert_true(!buffer_length || buffer_length == 12); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t unk_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 4); // 0 - uint32_t info_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 8); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t unk_ptr = poly::load_and_swap(buffer + 4); // 0 + uint32_t info_ptr = poly::load_and_swap(buffer + 8); + auto info = memory_->TranslateVirtual(info_ptr); assert_true(xmp_client == 0x00000002); assert_zero(unk_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; } auto& song = active_playlist_->songs[active_song_index_]; - poly::store_and_swap(membase_ + info_ptr + 0, song->handle); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 0, - song->name); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 40, - song->artist); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 80, - song->album); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 120, + poly::store_and_swap(info + 0, song->handle); + poly::store_and_swap(info + 4 + 572 + 0, song->name); + poly::store_and_swap(info + 4 + 572 + 40, song->artist); + poly::store_and_swap(info + 4 + 572 + 80, song->album); + poly::store_and_swap(info + 4 + 572 + 120, song->album_artist); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 160, - song->genre); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 200, - song->track_number); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 204, - song->duration_ms); - poly::store_and_swap(membase_ + info_ptr + 4 + 572 + 208, + poly::store_and_swap(info + 4 + 572 + 160, song->genre); + poly::store_and_swap(info + 4 + 572 + 200, song->track_number); + poly::store_and_swap(info + 4 + 572 + 204, song->duration_ms); + poly::store_and_swap(info + 4 + 572 + 208, static_cast(song->format)); return X_ERROR_SUCCESS; } case 0x00070013: { assert_true(!buffer_length || buffer_length == 8); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t playlist_handle = - poly::load_and_swap(membase_ + buffer_ptr + 4); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t playlist_handle = poly::load_and_swap(buffer + 4); assert_true(xmp_client == 0x00000002); return XMPDeleteTitlePlaylist(playlist_handle); } case 0x0007001A: { assert_true(!buffer_length || buffer_length == 12); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t unk1 = poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t enabled = - poly::load_and_swap(membase_ + buffer_ptr + 8); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t unk1 = poly::load_and_swap(buffer + 4); + uint32_t enabled = poly::load_and_swap(buffer + 8); assert_true(xmp_client == 0x00000002); assert_zero(unk1); XELOGD("XMPSetEnabled(%.8X, %.8X)", unk1, enabled); @@ -383,53 +352,49 @@ X_RESULT XXMPApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, } case 0x0007001B: { assert_true(!buffer_length || buffer_length == 12); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); uint32_t unk_ptr = poly::load_and_swap( - 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( - 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); XELOGD("XMPGetEnabled(%.8X, %.8X)", unk_ptr, disabled_ptr); - poly::store_and_swap(membase_ + unk_ptr, 0); - poly::store_and_swap(membase_ + disabled_ptr, disabled_); + poly::store_and_swap(memory_->TranslateVirtual(unk_ptr), 0); + poly::store_and_swap(memory_->TranslateVirtual(disabled_ptr), + disabled_); // Atrain spawns a thread 82437FD0 to call this in a tight loop forever. poly::threading::Sleep(std::chrono::milliseconds(10)); return X_ERROR_SUCCESS; } case 0x00070029: { assert_true(!buffer_length || buffer_length == 16); - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t playback_mode_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t repeat_mode_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 8); - uint32_t unk3_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 12); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t playback_mode_ptr = poly::load_and_swap(buffer + 4); + uint32_t repeat_mode_ptr = poly::load_and_swap(buffer + 8); + uint32_t unk3_ptr = poly::load_and_swap(buffer + 12); assert_true(xmp_client == 0x00000002); XELOGD("XMPGetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode_ptr, repeat_mode_ptr, unk3_ptr); - poly::store_and_swap(membase_ + playback_mode_ptr, - static_cast(playback_mode_)); - poly::store_and_swap(membase_ + repeat_mode_ptr, + poly::store_and_swap( + memory_->TranslateVirtual(playback_mode_ptr), + static_cast(playback_mode_)); + poly::store_and_swap(memory_->TranslateVirtual(repeat_mode_ptr), static_cast(repeat_mode_)); - poly::store_and_swap(membase_ + unk3_ptr, unknown_flags_); + poly::store_and_swap(memory_->TranslateVirtual(unk3_ptr), + unknown_flags_); return X_ERROR_SUCCESS; } case 0x0007002E: { assert_true(!buffer_length || buffer_length == 12); // Query of size for XamAlloc - the result of the alloc is passed to // 0x0007000D. - uint32_t xmp_client = - poly::load_and_swap(membase_ + buffer_ptr + 0); - uint32_t song_count = - poly::load_and_swap(membase_ + buffer_ptr + 4); - uint32_t size_ptr = - poly::load_and_swap(membase_ + buffer_ptr + 8); + uint32_t xmp_client = poly::load_and_swap(buffer + 0); + uint32_t song_count = poly::load_and_swap(buffer + 4); + uint32_t size_ptr = poly::load_and_swap(buffer + 8); assert_true(xmp_client == 0x00000002); // We don't use the storage, so just fudge the number. - poly::store_and_swap(membase_ + size_ptr, song_count * 128); + poly::store_and_swap(memory_->TranslateVirtual(size_ptr), + song_count * 128); return X_ERROR_SUCCESS; } case 0x0007003D: { diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index e93f9e96c..c2b175284 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -204,7 +204,7 @@ void KernelState::BroadcastNotification(XNotificationID id, uint32_t data) { void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, uint32_t length) { - auto ptr = memory()->membase() + overlapped_ptr; + auto ptr = memory()->TranslateVirtual(overlapped_ptr); XOverlappedSetResult(ptr, result); XOverlappedSetLength(ptr, length); XOverlappedSetExtendedError(ptr, result); @@ -233,7 +233,7 @@ void KernelState::CompleteOverlapped(uint32_t overlapped_ptr, X_RESULT result, void KernelState::CompleteOverlappedImmediate(uint32_t overlapped_ptr, X_RESULT result, uint32_t length) { - auto ptr = memory()->membase() + overlapped_ptr; + auto ptr = memory()->TranslateVirtual(overlapped_ptr); XOverlappedSetContext(ptr, XThread::GetCurrentThreadHandle()); CompleteOverlapped(overlapped_ptr, result, length); } diff --git a/src/xenia/kernel/native_list.cc b/src/xenia/kernel/native_list.cc index 3a087ef27..039869e97 100644 --- a/src/xenia/kernel/native_list.cc +++ b/src/xenia/kernel/native_list.cc @@ -16,41 +16,44 @@ NativeList::NativeList(Memory* memory) : memory_(memory), head_(kInvalidPointer) {} void NativeList::Insert(uint32_t ptr) { - uint8_t* mem = memory_->membase(); - poly::store_and_swap(mem + ptr + 0, head_); - poly::store_and_swap(mem + ptr + 4, 0); + poly::store_and_swap(memory_->TranslateVirtual(ptr + 0), head_); + poly::store_and_swap(memory_->TranslateVirtual(ptr + 4), 0); if (head_) { - poly::store_and_swap(mem + head_ + 4, ptr); + poly::store_and_swap(memory_->TranslateVirtual(head_ + 4), ptr); } head_ = ptr; } bool NativeList::IsQueued(uint32_t ptr) { - uint8_t* mem = memory_->membase(); - uint32_t flink = poly::load_and_swap(mem + ptr + 0); - uint32_t blink = poly::load_and_swap(mem + ptr + 4); + uint32_t flink = + poly::load_and_swap(memory_->TranslateVirtual(ptr + 0)); + uint32_t blink = + poly::load_and_swap(memory_->TranslateVirtual(ptr + 4)); return head_ == ptr || flink || blink; } void NativeList::Remove(uint32_t ptr) { - uint8_t* mem = memory_->membase(); - uint32_t flink = poly::load_and_swap(mem + ptr + 0); - uint32_t blink = poly::load_and_swap(mem + ptr + 4); + uint32_t flink = + poly::load_and_swap(memory_->TranslateVirtual(ptr + 0)); + uint32_t blink = + poly::load_and_swap(memory_->TranslateVirtual(ptr + 4)); if (ptr == head_) { head_ = flink; if (flink) { - poly::store_and_swap(mem + flink + 4, 0); + poly::store_and_swap(memory_->TranslateVirtual(flink + 4), 0); } } else { if (blink) { - poly::store_and_swap(mem + blink + 0, flink); + poly::store_and_swap(memory_->TranslateVirtual(blink + 0), + flink); } if (flink) { - poly::store_and_swap(mem + flink + 4, blink); + poly::store_and_swap(memory_->TranslateVirtual(flink + 4), + blink); } } - poly::store_and_swap(mem + ptr + 0, 0); - poly::store_and_swap(mem + ptr + 4, 0); + poly::store_and_swap(memory_->TranslateVirtual(ptr + 0), 0); + poly::store_and_swap(memory_->TranslateVirtual(ptr + 4), 0); } uint32_t NativeList::Shift() { diff --git a/src/xenia/kernel/objects/xthread.cc b/src/xenia/kernel/objects/xthread.cc index d92fffaff..c73cf38b2 100644 --- a/src/xenia/kernel/objects/xthread.cc +++ b/src/xenia/kernel/objects/xthread.cc @@ -118,12 +118,12 @@ uint32_t XThread::thread_state() { return thread_state_address_; } uint32_t XThread::thread_id() { return thread_id_; } 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(p + 0x160); } 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(p + 0x160, error_code); } @@ -176,7 +176,7 @@ X_STATUS XThread::Create() { memory()->Copy(tls_address_, header->tls_info.raw_data_address, tls_size); // 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(p + 0x000, tls_address_); poly::store_and_swap(p + 0x100, thread_state_address_); poly::store_and_swap(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=7 XThread* thread = reinterpret_cast(data); - auto membase = thread->memory()->membase(); + auto memory = thread->memory(); auto processor = thread->kernel_state()->processor(); auto apc_list = thread->apc_list(); thread->LockApc(); @@ -390,7 +390,7 @@ void XThread::DeliverAPCs(void* data) { // Get APC entry (offset for LIST_ENTRY offset) and cache what we need. // Calling the routine may delete the memory/overwrite it. 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(apc_ptr + 16); uint32_t normal_routine = poly::load_and_swap(apc_ptr + 24); uint32_t normal_context = poly::load_and_swap(apc_ptr + 28); @@ -405,7 +405,7 @@ void XThread::DeliverAPCs(void* data) { // The routine can modify all of its arguments before passing it on. // Since we need to give guest accessible pointers over, we copy things // 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(scratch_ptr + 0, normal_routine); poly::store_and_swap(scratch_ptr + 4, normal_context); poly::store_and_swap(scratch_ptr + 8, system_arg1); @@ -438,13 +438,12 @@ void XThread::DeliverAPCs(void* data) { } void XThread::RundownAPCs() { - auto membase = memory()->membase(); LockApc(); while (apc_list_->HasPending()) { // Get APC entry (offset for LIST_ENTRY offset) and cache what we need. // Calling the routine may delete the memory/overwrite it. 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(apc_ptr + 20); // Mark as uninserted so that it can be reinserted again by the routine. diff --git a/src/xenia/kernel/objects/xuser_module.cc b/src/xenia/kernel/objects/xuser_module.cc index 447e044e3..a15f00d28 100644 --- a/src/xenia/kernel/objects/xuser_module.cc +++ b/src/xenia/kernel/objects/xuser_module.cc @@ -107,15 +107,15 @@ X_STATUS XUserModule::LoadFromMemory(const void* addr, const size_t length) { // Load the XEX into memory and decrypt. 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_) { return X_STATUS_UNSUCCESSFUL; } // Store execution info for later use. // TODO(benvanik): just put entire xex header in memory somewhere? - execution_info_ptr_ = kernel_state()->memory()->SystemHeapAlloc(24); - auto eip = kernel_state()->memory()->membase() + execution_info_ptr_; + execution_info_ptr_ = memory()->SystemHeapAlloc(24); + auto eip = memory()->TranslateVirtual(execution_info_ptr_); const auto& ex = xe_xex2_get_header(xex_)->execution_info; poly::store_and_swap(eip + 0x00, ex.media_id); poly::store_and_swap(eip + 0x04, ex.version.value); diff --git a/src/xenia/kernel/util/shim_utils.h b/src/xenia/kernel/util/shim_utils.h index 50fc6edc6..7e00286f6 100644 --- a/src/xenia/kernel/util/shim_utils.h +++ b/src/xenia/kernel/util/shim_utils.h @@ -26,8 +26,8 @@ using PPCContext = xe::cpu::frontend::PPCContext; shim_data, \ (xe_kernel_export_shim_fn)export_name##_shim); -#define SHIM_MEM_BASE ppc_state->membase -#define SHIM_MEM_ADDR(a) (a ? (ppc_state->membase + a) : nullptr) +#define SHIM_MEM_BASE ppc_state->virtual_membase +#define SHIM_MEM_ADDR(a) (a ? (ppc_state->virtual_membase + a) : nullptr) #define SHIM_MEM_8(a) poly::load_and_swap(SHIM_MEM_ADDR(a)) #define SHIM_MEM_16(a) poly::load_and_swap(SHIM_MEM_ADDR(a)) diff --git a/src/xenia/kernel/util/xex2.cc b/src/xenia/kernel/util/xex2.cc index b89ddddff..5fe59ceea 100644 --- a/src/xenia/kernel/util/xex2.cc +++ b/src/xenia/kernel/util/xex2.cc @@ -538,7 +538,7 @@ int xe_xex2_read_image_uncompressed(const xe_xex2_header_t *header, uncompressed_size); return 2; } - uint8_t *buffer = memory->Translate(header->exe_address); + uint8_t *buffer = memory->TranslateVirtual(header->exe_address); std::memset(buffer, 0, uncompressed_size); 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); return 1; } - uint8_t *buffer = memory->Translate(header->exe_address); + uint8_t *buffer = memory->TranslateVirtual(header->exe_address); uint8_t *d = buffer; 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; goto XECLEANUP; } - uint8_t *buffer = memory->Translate(header->exe_address); + uint8_t *buffer = memory->TranslateVirtual(header->exe_address); std::memset(buffer, 0, uncompressed_size); // 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) { 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). 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, const xe_xex2_import_library_t *library) { - uint8_t *mem = xex->memory->membase(); auto header = xe_xex2_get_header(xex); // Find library index for verification. @@ -910,7 +909,8 @@ int xe_xex2_find_import_infos(xe_xex2_ref xex, size_t info_count = 0; for (size_t n = 0; n < library->record_count; n++) { const uint32_t record = library->records[n]; - const uint32_t value = poly::load_and_swap(mem + record); + const uint32_t value = + poly::load_and_swap(xex->memory->TranslateVirtual(record)); if (value & 0xFF000000) { // Thunk for previous record - ignore. } else { @@ -929,7 +929,8 @@ int xe_xex2_find_import_infos(xe_xex2_ref xex, // Construct infos. for (size_t n = 0, i = 0; n < library->record_count; n++) { const uint32_t record = library->records[n]; - const uint32_t value = poly::load_and_swap(mem + record); + const uint32_t value = + poly::load_and_swap(xex->memory->TranslateVirtual(record)); const uint32_t type = (value & 0xFF000000) >> 24; // Verify library index matches given library. diff --git a/src/xenia/kernel/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl_audio_xma.cc index ff4bde159..3df6144a4 100644 --- a/src/xenia/kernel/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl_audio_xma.cc @@ -151,10 +151,6 @@ struct XMAContextData { }; static_assert(sizeof(XMAContextData) == 4 * 10, "Must be packed"); -void StoreXmaRegister(uint8_t* membase, uint32_t num, uint32_t value) { - poly::store(membase + (0x7FEA0000 + num), value); -} - void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, uint32_t context_ptr) { auto audio_system = state->emulator()->audio_system(); @@ -162,7 +158,8 @@ void StoreXmaContextIndexedRegister(KernelState* state, uint32_t base_reg, XMAContextData::kSize; uint32_t reg_num = base_reg + (hw_index >> 5) * 4; uint32_t reg_value = 1 << (hw_index & 0x1F); - StoreXmaRegister(state->memory()->membase(), reg_num, reg_value); + poly::store(state->memory()->TranslateVirtual(0x7FEA0000 + reg_num), + reg_value); } SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) { diff --git a/src/xenia/kernel/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl_module.cc index 0c76f70e7..cc47ec99a 100644 --- a/src/xenia/kernel/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl_module.cc @@ -44,23 +44,23 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) xboxkrnl::RegisterUsbcamExports(export_resolver_, kernel_state_); xboxkrnl::RegisterVideoExports(export_resolver_, kernel_state_); - uint8_t* mem = memory_->membase(); - // KeDebugMonitorData (?*) // 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 // arguments. If we wanted to see what would happen we could fake that. uint32_t pKeDebugMonitorData = memory_->SystemHeapAlloc(256); + auto lpKeDebugMonitorData = memory_->TranslateVirtual(pKeDebugMonitorData); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::KeDebugMonitorData, pKeDebugMonitorData); - poly::store_and_swap(mem + pKeDebugMonitorData, 0); + poly::store_and_swap(lpKeDebugMonitorData, 0); // KeCertMonitorData (?*) // Always set to zero, ignored. uint32_t pKeCertMonitorData = memory_->SystemHeapAlloc(4); + auto lpKeCertMonitorData = memory_->TranslateVirtual(pKeCertMonitorData); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::KeCertMonitorData, pKeCertMonitorData); - poly::store_and_swap(mem + pKeCertMonitorData, 0); + poly::store_and_swap(lpKeCertMonitorData, 0); // XboxHardwareInfo (XboxHardwareInfo_t, 16b) // flags cpu# ? ? ? ? ? ? @@ -71,11 +71,11 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // aomega08 says the value is 0x02000817, bit 27: debug mode on. // When that is set, though, allocs crash in weird ways. uint32_t pXboxHardwareInfo = memory_->SystemHeapAlloc(16); + auto lpXboxHardwareInfo = memory_->TranslateVirtual(pXboxHardwareInfo); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::XboxHardwareInfo, pXboxHardwareInfo); - poly::store_and_swap(mem + pXboxHardwareInfo + 0, 0); // flags - poly::store_and_swap(mem + pXboxHardwareInfo + 4, - 0x06); // cpu count + poly::store_and_swap(lpXboxHardwareInfo + 0, 0); // flags + poly::store_and_swap(lpXboxHardwareInfo + 4, 0x06); // cpu count // Remaining 11b are zeroes? // XexExecutableModuleHandle (?**) @@ -88,13 +88,17 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // 0x80101058 <- pointer to xex header // 0x80101100 <- xex header base uint32_t ppXexExecutableModuleHandle = memory_->SystemHeapAlloc(4); + auto lppXexExecutableModuleHandle = + memory_->TranslateVirtual(ppXexExecutableModuleHandle); export_resolver_->SetVariableMapping("xboxkrnl.exe", ordinals::XexExecutableModuleHandle, ppXexExecutableModuleHandle); uint32_t pXexExecutableModuleHandle = memory_->SystemHeapAlloc(256); - poly::store_and_swap(mem + ppXexExecutableModuleHandle, + auto lpXexExecutableModuleHandle = + memory_->TranslateVirtual(pXexExecutableModuleHandle); + poly::store_and_swap(lppXexExecutableModuleHandle, pXexExecutableModuleHandle); - poly::store_and_swap(mem + pXexExecutableModuleHandle + 0x58, + poly::store_and_swap(lpXexExecutableModuleHandle + 0x58, 0x80101100); // ExLoadedCommandLine (char*) @@ -102,41 +106,44 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) // Perhaps it's how swap disc/etc data is sent? // Always set to "default.xex" (with quotes) for now. uint32_t pExLoadedCommandLine = memory_->SystemHeapAlloc(1024); + auto lpExLoadedCommandLine = memory_->TranslateVirtual(pExLoadedCommandLine); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::ExLoadedCommandLine, pExLoadedCommandLine); char command_line[] = "\"default.xex\""; - memcpy(mem + pExLoadedCommandLine, command_line, - poly::countof(command_line) + 1); + std::memcpy(lpExLoadedCommandLine, command_line, + poly::countof(command_line) + 1); // XboxKrnlVersion (8b) // Kernel version, looks like 2b.2b.2b.2b. // I've only seen games check >=, so we just fake something here. uint32_t pXboxKrnlVersion = memory_->SystemHeapAlloc(8); + auto lpXboxKrnlVersion = memory_->TranslateVirtual(pXboxKrnlVersion); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::XboxKrnlVersion, pXboxKrnlVersion); - poly::store_and_swap(mem + pXboxKrnlVersion + 0, 2); - poly::store_and_swap(mem + pXboxKrnlVersion + 2, 0xFFFF); - poly::store_and_swap(mem + pXboxKrnlVersion + 4, 0xFFFF); - poly::store_and_swap(mem + pXboxKrnlVersion + 6, 0x80); - poly::store_and_swap(mem + pXboxKrnlVersion + 7, 0x00); + poly::store_and_swap(lpXboxKrnlVersion + 0, 2); + poly::store_and_swap(lpXboxKrnlVersion + 2, 0xFFFF); + poly::store_and_swap(lpXboxKrnlVersion + 4, 0xFFFF); + poly::store_and_swap(lpXboxKrnlVersion + 6, 0x80); + poly::store_and_swap(lpXboxKrnlVersion + 7, 0x00); // KeTimeStampBundle (ad) // This must be updated during execution, at 1ms intevals. // We setup a system timer here to do that. uint32_t pKeTimeStampBundle = memory_->SystemHeapAlloc(24); + auto lpKeTimeStampBundle = memory_->TranslateVirtual(pKeTimeStampBundle); export_resolver_->SetVariableMapping( "xboxkrnl.exe", ordinals::KeTimeStampBundle, pKeTimeStampBundle); - poly::store_and_swap(mem + pKeTimeStampBundle + 0, 0); - poly::store_and_swap(mem + pKeTimeStampBundle + 8, 0); - poly::store_and_swap(mem + pKeTimeStampBundle + 16, GetTickCount()); - poly::store_and_swap(mem + pKeTimeStampBundle + 20, 0); + poly::store_and_swap(lpKeTimeStampBundle + 0, 0); + poly::store_and_swap(lpKeTimeStampBundle + 8, 0); + poly::store_and_swap(lpKeTimeStampBundle + 16, GetTickCount()); + poly::store_and_swap(lpKeTimeStampBundle + 20, 0); CreateTimerQueueTimer( ×tamp_timer_, nullptr, [](PVOID param, BOOLEAN timer_or_wait_fired) { auto timestamp_bundle = reinterpret_cast(param); poly::store_and_swap(timestamp_bundle + 16, GetTickCount()); }, - mem + pKeTimeStampBundle, 0, + lpKeTimeStampBundle, 0, 1, // 1ms WT_EXECUTEINTIMERTHREAD); } diff --git a/src/xenia/kernel/xboxkrnl_rtl.cc b/src/xenia/kernel/xboxkrnl_rtl.cc index 9089aa893..d86c5c3a8 100644 --- a/src/xenia/kernel/xboxkrnl_rtl.cc +++ b/src/xenia/kernel/xboxkrnl_rtl.cc @@ -541,7 +541,7 @@ SHIM_CALL RtlEnterCriticalSection_shim(PPCContext* ppc_state, // 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); 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); - 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); auto cs = (X_RTL_CRITICAL_SECTION*)SHIM_MEM_ADDR(cs_ptr); diff --git a/src/xenia/kernel/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl_threading.cc index 482c55156..bb6fc4812 100644 --- a/src/xenia/kernel/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl_threading.cc @@ -62,11 +62,10 @@ void AssertNoNameCollision(KernelState* state, uint32_t obj_attributes_ptr) { // with a success of NAME_EXISTS. // If the name exists and its type doesn't match, we do NAME_COLLISION. // Otherwise, we add like normal. - auto membase = state->memory()->membase(); - uint32_t name_str_ptr = - poly::load_and_swap(membase + obj_attributes_ptr + 4); + uint32_t name_str_ptr = poly::load_and_swap( + state->memory()->TranslateVirtual(obj_attributes_ptr + 4)); 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(); X_HANDLE handle = X_INVALID_HANDLE_VALUE; X_RESULT result = state->object_table()->GetObjectByName(name, &handle); diff --git a/src/xenia/kernel/xboxkrnl_video.cc b/src/xenia/kernel/xboxkrnl_video.cc index 087fda8dd..dc0e478a2 100644 --- a/src/xenia/kernel/xboxkrnl_video.cc +++ b/src/xenia/kernel/xboxkrnl_video.cc @@ -447,7 +447,6 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver, SHIM_SET_MAPPING("xboxkrnl.exe", VdSwap, state); Memory* memory = state->memory(); - uint8_t* mem = memory->membase(); // VdGlobalDevice (4b) // 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); export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGlobalDevice, pVdGlobalDevice); - poly::store_and_swap(mem + pVdGlobalDevice, 0); + poly::store_and_swap(memory->TranslateVirtual(pVdGlobalDevice), 0); // VdGlobalXamDevice (4b) // 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); export_resolver->SetVariableMapping( "xboxkrnl.exe", ordinals::VdGlobalXamDevice, pVdGlobalXamDevice); - poly::store_and_swap(mem + pVdGlobalXamDevice, 0); + poly::store_and_swap(memory->TranslateVirtual(pVdGlobalXamDevice), + 0); // VdGpuClockInMHz (4b) // 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); export_resolver->SetVariableMapping("xboxkrnl.exe", ordinals::VdGpuClockInMHz, pVdGpuClockInMHz); - poly::store_and_swap(mem + pVdGpuClockInMHz, 500); + poly::store_and_swap(memory->TranslateVirtual(pVdGpuClockInMHz), + 500); // VdHSIOCalibrationLock (28b) // CriticalSection. @@ -481,7 +482,7 @@ void xe::kernel::xboxkrnl::RegisterVideoExports(ExportResolver* export_resolver, export_resolver->SetVariableMapping( "xboxkrnl.exe", ordinals::VdHSIOCalibrationLock, pVdHSIOCalibrationLock); auto hsio_lock = - reinterpret_cast(mem + pVdHSIOCalibrationLock); + memory->TranslateVirtual(pVdHSIOCalibrationLock); xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock, 10000); } diff --git a/src/xenia/kernel/xobject.cc b/src/xenia/kernel/xobject.cc index 692adab41..48f61783a 100644 --- a/src/xenia/kernel/xobject.cc +++ b/src/xenia/kernel/xobject.cc @@ -23,9 +23,8 @@ XObject::XObject(KernelState* kernel_state, Type type) pointer_ref_count_(1), type_(type), handle_(X_INVALID_HANDLE_VALUE) { - // 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_); } } @@ -35,8 +34,6 @@ XObject::~XObject() { assert_zero(pointer_ref_count_); } -Memory* XObject::memory() const { return kernel_state_->memory(); } - XObject::Type XObject::type() { return type_; } 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(obj_attrs_ptr + 4); 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(); 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) { std::lock_guard lock(kernel_state_->object_mutex()); - DISPATCH_HEADER* header_be = - (DISPATCH_HEADER*)kernel_state_->memory()->Translate(native_ptr); + auto header_be = + kernel_state_->memory()->TranslateVirtual(native_ptr); DISPATCH_HEADER header; header.type_flags = poly::byte_swap(header_be->type_flags); header.signal_state = poly::byte_swap(header_be->signal_state); diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index 32d39103c..632907fab 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -13,7 +13,6 @@ #include #include "xenia/kernel/kernel_state.h" - #include "xenia/xbox.h" namespace xe { @@ -46,7 +45,7 @@ class XObject { Emulator* emulator() const { return kernel_state_->emulator_; } 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(); X_HANDLE handle() const; @@ -79,7 +78,6 @@ class XObject { virtual void* GetWaitHandle() { return 0; } protected: - Memory* memory() const; void SetNativePointer(uint32_t native_ptr); static uint32_t TimeoutTicksToMs(int64_t timeout_ticks); diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index a82fcfbc7..e50580acd 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -116,7 +116,8 @@ class xe::MemoryHeap { uint32_t MemoryHeap::next_heap_id_ = 1; Memory::Memory() - : membase_(nullptr), + : virtual_membase_(nullptr), + physical_membase_(nullptr), reserve_address_(0), reserve_value_(0), trace_base_(0), @@ -134,7 +135,7 @@ Memory::~Memory() { if (mapping_base_) { // GPU writeback. - VirtualFree(Translate(0xC0000000), 0x00100000, MEM_DECOMMIT); + VirtualFree(TranslateVirtual(0xC0000000), 0x00100000, MEM_DECOMMIT); } delete physical_heap_; @@ -147,6 +148,9 @@ Memory::~Memory() { mapping_base_ = 0; mapping_ = 0; } + + virtual_membase_ = nullptr; + physical_membase_ = nullptr; } int Memory::Initialize() { @@ -184,7 +188,8 @@ int Memory::Initialize() { assert_always(); return 1; } - membase_ = mapping_base_; + virtual_membase_ = mapping_base_; + physical_membase_ = virtual_membase_; // Prepare heaps. virtual_heap_->Initialize(kMemoryVirtualHeapLow, kMemoryVirtualHeapHigh); @@ -193,7 +198,8 @@ int Memory::Initialize() { // GPU writeback. // 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. 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. - VirtualAlloc(Translate(0x40000000), 0x00010000, MEM_COMMIT, PAGE_READWRITE); - poly::store_and_swap(Translate(0x40000000), 0x00C40000); - poly::store_and_swap(Translate(0x40000004), 0x00010000); + VirtualAlloc(TranslateVirtual(0x40000000), 0x00010000, MEM_COMMIT, + PAGE_READWRITE); + poly::store_and_swap(TranslateVirtual(0x40000000), 0x00C40000); + poly::store_and_swap(TranslateVirtual(0x40000004), 0x00010000); return 0; } @@ -266,26 +273,24 @@ void Memory::UnmapViews() { } void Memory::Zero(uint32_t address, uint32_t size) { - uint8_t* p = membase_ + address; - std::memset(p, 0, size); + std::memset(TranslateVirtual(address), 0, size); } void Memory::Fill(uint32_t address, uint32_t size, uint8_t value) { - uint8_t* p = membase_ + address; - std::memset(p, value, size); + std::memset(TranslateVirtual(address), value, size); } void Memory::Copy(uint32_t dest, uint32_t src, uint32_t size) { - uint8_t* pdest = membase_ + dest; - const uint8_t* psrc = membase_ + src; + uint8_t* pdest = TranslateVirtual(dest); + const uint8_t* psrc = TranslateVirtual(src); std::memcpy(pdest, psrc, size); } uint32_t Memory::SearchAligned(uint32_t start, uint32_t end, const uint32_t* values, size_t value_count) { assert_true(start <= end); - const uint32_t* p = reinterpret_cast(membase_ + start); - const uint32_t* pe = reinterpret_cast(membase_ + end); + auto p = TranslateVirtual(start); + auto pe = TranslateVirtual(end); while (p != pe) { if (*p == values[0]) { const uint32_t* pc = p + 1; @@ -297,7 +302,7 @@ uint32_t Memory::SearchAligned(uint32_t start, uint32_t end, matched++; } if (matched == value_count) { - return uint32_t(reinterpret_cast(p) - membase_); + return uint32_t(reinterpret_cast(p) - virtual_membase_); } } p++; @@ -309,7 +314,7 @@ bool Memory::AddMappedRange(uint32_t address, uint32_t mask, uint32_t size, void* context, cpu::MMIOReadCallback read_callback, cpu::MMIOWriteCallback write_callback) { 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"); return false; } @@ -361,7 +366,7 @@ uint32_t Memory::HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags, } if (result) { if (flags & MEMORY_FLAG_ZERO) { - memset(Translate(result), 0, size); + memset(TranslateVirtual(result), 0, size); } } return result; @@ -379,7 +384,7 @@ uint32_t Memory::HeapAlloc(uint32_t base_address, uint32_t size, uint32_t flags, 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. 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; } else { // A placed address. Decommit. - uint8_t* p = Translate(address); + uint8_t* p = TranslateVirtual(address); return VirtualFree(p, size, MEM_DECOMMIT) ? 0 : 1; } } 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; if (!VirtualQuery(p, &mbi, sizeof(mbi))) { return false; } mem_info->base_address = base_address; mem_info->allocation_base = static_cast( - reinterpret_cast(mbi.AllocationBase) - membase_); + reinterpret_cast(mbi.AllocationBase) - virtual_membase_); mem_info->allocation_protect = mbi.AllocationProtect; mem_info->region_size = mbi.RegionSize; mem_info->state = mbi.State; @@ -436,7 +441,7 @@ uint32_t Memory::QuerySize(uint32_t base_address) { return physical_heap_->QuerySize(base_address); } else { // A placed address. - uint8_t* p = Translate(base_address); + uint8_t* p = TranslateVirtual(base_address); MEMORY_BASIC_INFORMATION mem_info; if (VirtualQuery(p, &mem_info, sizeof(mem_info))) { 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) { - uint8_t* p = Translate(address); + uint8_t* p = TranslateVirtual(address); size_t heap_guard_size = FLAGS_heap_guard_pages * 4096; 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) { - uint8_t* p = Translate(address); + uint8_t* p = TranslateVirtual(address); MEMORY_BASIC_INFORMATION info; size_t info_size = VirtualQuery((void*)p, &info, sizeof(info)); 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) { - uint8_t* p = memory_->Translate(address); + uint8_t* p = memory_->TranslateVirtual(address); // Heap allocated address. 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) { - uint8_t* p = memory_->Translate(base_address); + uint8_t* p = memory_->TranslateVirtual(base_address); // Heap allocated address. uint32_t heap_guard_size = uint32_t(FLAGS_heap_guard_pages * 4096); diff --git a/src/xenia/memory.h b/src/xenia/memory.h index 86014dfc6..99c50c1e7 100644 --- a/src/xenia/memory.h +++ b/src/xenia/memory.h @@ -55,10 +55,25 @@ class Memory { int Initialize(); - inline uint8_t* membase() const { return membase_; } - inline uint8_t* Translate(uint64_t guest_address) const { - return membase_ + guest_address; + inline uint8_t* virtual_membase() const { return virtual_membase_; } + inline uint8_t* TranslateVirtual(uint32_t guest_address) const { + return virtual_membase_ + guest_address; }; + template + inline T TranslateVirtual(uint32_t guest_address) const { + return reinterpret_cast(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 + inline T TranslatePhysical(uint32_t guest_address) const { + return reinterpret_cast(physical_membase_ + + (guest_address & 0x1FFFFFFF)); + } + inline uint64_t* reserve_address() { return &reserve_address_; } inline uint64_t* reserve_value() { return &reserve_value_; } @@ -100,7 +115,8 @@ class Memory { private: uint32_t system_page_size_; - uint8_t* membase_; + uint8_t* virtual_membase_; + uint8_t* physical_membase_; uint64_t reserve_address_; uint64_t reserve_value_; uint64_t trace_base_;