Starting to properly attribute virtual vs. physical memory accesses.
This commit is contained in:
parent
ab90e0932b
commit
ec84a688e9
|
@ -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_;
|
||||
|
|
|
@ -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<std::mutex> 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<uint32_t>(mem + ptr, callback_arg);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(context_ptr + 0);
|
||||
bool has_valid_input = (dword0 & 0x00300000) != 0;
|
||||
if (has_valid_input) {
|
||||
|
|
|
@ -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<float*>(emulator_->memory()->membase() + frame_ptr);
|
||||
auto input_frame = memory_->TranslatePhysical<float*>(frame_ptr);
|
||||
auto output_frame = reinterpret_cast<float*>(frame_);
|
||||
auto interleave_channels = frame_channels_;
|
||||
|
||||
|
|
|
@ -368,8 +368,7 @@ uint64_t TrapDebugPrint(void* raw_context, uint64_t address) {
|
|||
auto thread_state = *reinterpret_cast<ThreadState**>(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<const char*>(thread_state->memory()->Translate(str_ptr));
|
||||
auto str = thread_state->memory()->TranslateVirtual<const char*>(str_ptr);
|
||||
// TODO(benvanik): truncate to length?
|
||||
PLOGD("(DebugPrint) %s", str);
|
||||
return 0;
|
||||
|
|
|
@ -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<void*>(uintptr_t(return_address)));
|
||||
return 0;
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<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.
|
||||
i.type = GetInstrType(i.code);
|
||||
trace_info_.dest_count = 0;
|
||||
|
|
|
@ -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<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
|
||||
// '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) {
|
||||
Memory* memory = frontend_->memory();
|
||||
const uint8_t* p = memory->membase();
|
||||
|
||||
std::map<uint32_t, BlockInfo> block_map;
|
||||
|
||||
|
@ -292,7 +290,7 @@ std::vector<BlockInfo> 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<uint32_t>(p + address);
|
||||
i.code = poly::load_and_swap<uint32_t>(memory->TranslateVirtual(address));
|
||||
if (!i.code) {
|
||||
continue;
|
||||
}
|
||||
|
|
|
@ -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<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.
|
||||
i.type = GetInstrType(i.code);
|
||||
|
||||
|
|
|
@ -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) {
|
||||
|
|
|
@ -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(),
|
||||
|
|
|
@ -163,8 +163,8 @@ uint64_t Processor::ExecuteInterrupt(uint32_t cpu, uint32_t address,
|
|||
std::lock_guard<std::mutex> lock(interrupt_thread_lock_);
|
||||
|
||||
// Set 0x10C(r13) to the current CPU ID.
|
||||
uint8_t* p = memory_->membase();
|
||||
poly::store_and_swap<uint8_t>(p + interrupt_thread_block_ + 0x10C, cpu);
|
||||
poly::store_and_swap<uint8_t>(
|
||||
memory_->TranslateVirtual(interrupt_thread_block_ + 0x10C), cpu);
|
||||
|
||||
// Execute interrupt.
|
||||
uint64_t result = Execute(interrupt_thread_state_, address, args, arg_count);
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<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.
|
||||
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_);
|
||||
}
|
||||
|
|
|
@ -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_;
|
||||
|
|
|
@ -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<uint32_t*>(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<uint32_t>(p + 0x0, 0x44000002);
|
||||
poly::store_and_swap<uint32_t>(p + 0x4, 0x4E800020);
|
||||
poly::store_and_swap<uint32_t>(p + 0x8, 0x60000000);
|
||||
|
|
|
@ -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<uint64_t>(memory()->membase());
|
||||
ev->membase = reinterpret_cast<uint64_t>(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;
|
||||
|
|
|
@ -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<uint32_t>(membase_ + read_ptr_writeback_ptr_,
|
||||
read_ptr_index_);
|
||||
poly::store_and_swap<uint32_t>(
|
||||
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<uint32_t>(membase_ + xenos::GpuToCpu(mem_addr),
|
||||
poly::store_and_swap<uint32_t>(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<Endian>(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);
|
||||
trace_writer_.WriteMemoryRead(poll_reg_addr, 4);
|
||||
} else {
|
||||
|
@ -1095,7 +1094,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
|
|||
auto endianness = static_cast<Endian>(poll_reg_addr & 0x3);
|
||||
poll_reg_addr &= ~0x3;
|
||||
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);
|
||||
} else {
|
||||
// Register.
|
||||
|
@ -1136,7 +1135,7 @@ bool CommandProcessor::ExecutePacketType3_COND_WRITE(RingbufferReader* reader,
|
|||
auto endianness = static_cast<Endian>(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<Endian>(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<uint16_t*>(membase_ + GpuToCpu(address)), extents,
|
||||
reinterpret_cast<uint16_t*>(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<uint32_t>(membase_ + GpuToCpu(address + n * 4));
|
||||
uint32_t data = poly::load_and_swap<uint32_t>(
|
||||
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<uint32_t*>(membase_ + GpuToCpu(addr)),
|
||||
LoadShader(shader_type, addr, memory_->TranslatePhysical<uint32_t*>(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<uint32_t*>(membase_ + reader->ptr()),
|
||||
size_dwords);
|
||||
LoadShader(shader_type, reader->ptr(),
|
||||
memory_->TranslatePhysical<uint32_t*>(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<GL4Shader>(shader_type, hash, address, dword_count);
|
||||
auto shader = std::make_unique<GL4Shader>(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<uintptr_t>(address) -
|
||||
reinterpret_cast<uintptr_t>(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<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);
|
||||
} else {
|
||||
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);
|
||||
}
|
||||
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<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);
|
||||
|
||||
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) {
|
||||
|
|
|
@ -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_;
|
||||
|
||||
|
|
|
@ -181,7 +181,7 @@ void GL4GraphicsSystem::PlayTrace(const uint8_t* trace_data, size_t trace_size,
|
|||
case TraceCommandType::kPacketStart: {
|
||||
auto cmd = reinterpret_cast<const PacketStartCommand*>(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<const MemoryReadCommand*>(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;
|
||||
|
|
|
@ -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)];
|
||||
|
|
|
@ -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<gl4::GL4GraphicsSystem*>(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<std::wstring>& 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();
|
||||
|
|
|
@ -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<XApp> app) {
|
||||
assert_zero(app_lookup_.count(app->app_id()));
|
||||
|
|
|
@ -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 {
|
||||
|
|
|
@ -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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t context_id =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
|
||||
uint32_t context_value =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 20);
|
||||
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t context_id = poly::load_and_swap<uint32_t>(buffer + 16);
|
||||
uint32_t context_value = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t property_id =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
|
||||
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);
|
||||
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t property_id = poly::load_and_swap<uint32_t>(buffer + 16);
|
||||
uint32_t value_size = poly::load_and_swap<uint32_t>(buffer + 20);
|
||||
uint32_t value_ptr = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t achievements_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t achievement_count = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t achievements_ptr = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t context_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 16);
|
||||
uint32_t context_id =
|
||||
poly::load_and_swap<uint32_t>(membase_ + context_ptr + 0);
|
||||
uint32_t user_index = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t context_ptr = poly::load_and_swap<uint32_t>(buffer + 16);
|
||||
auto context = memory_->TranslateVirtual(context_ptr);
|
||||
uint32_t context_id = poly::load_and_swap<uint32_t>(context + 0);
|
||||
XELOGD("XUserGetContext(%.8X, %.8X(%.8X))", user_index, context_ptr,
|
||||
context_id);
|
||||
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;
|
||||
}
|
||||
case 0x000B0071: {
|
||||
|
|
|
@ -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<uint32_t>(membase_ + buffer_ptr + 0, 1); // ?
|
||||
poly::store_and_swap<uint32_t>(buffer + 0, 1); // ?
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
case 0x00058020: {
|
||||
|
|
|
@ -34,7 +34,7 @@ X_RESULT XXMPApp::XMPGetStatus(uint32_t state_ptr) {
|
|||
Sleep(1);
|
||||
|
||||
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_));
|
||||
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>();
|
||||
song->handle = ++next_song_handle_;
|
||||
uint8_t* song_base = membase_ + songs_ptr + (i * 36);
|
||||
song->file_path = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 0));
|
||||
song->name = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 4));
|
||||
song->artist = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 8));
|
||||
song->album = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 12));
|
||||
song->album_artist = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 16));
|
||||
song->genre = poly::load_and_swap<std::wstring>(
|
||||
membase_ + poly::load_and_swap<uint32_t>(song_base + 20));
|
||||
uint8_t* song_base = memory_->TranslateVirtual(songs_ptr + (i * 36));
|
||||
song->file_path =
|
||||
poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
|
||||
poly::load_and_swap<uint32_t>(song_base + 0)));
|
||||
song->name = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
|
||||
poly::load_and_swap<uint32_t>(song_base + 4)));
|
||||
song->artist = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
|
||||
poly::load_and_swap<uint32_t>(song_base + 8)));
|
||||
song->album = poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
|
||||
poly::load_and_swap<uint32_t>(song_base + 12)));
|
||||
song->album_artist =
|
||||
poly::load_and_swap<std::wstring>(memory_->TranslateVirtual(
|
||||
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->duration_ms = poly::load_and_swap<uint32_t>(song_base + 28);
|
||||
song->format = static_cast<Song::Format>(
|
||||
poly::load_and_swap<uint32_t>(song_base + 32));
|
||||
if (out_song_handles) {
|
||||
poly::store_and_swap<uint32_t>(membase_ + out_song_handles + (i * 4),
|
||||
song->handle);
|
||||
poly::store_and_swap<uint32_t>(
|
||||
memory_->TranslateVirtual(out_song_handles + (i * 4)), song->handle);
|
||||
}
|
||||
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);
|
||||
|
||||
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,
|
||||
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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t playlist_handle =
|
||||
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?
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t playlist_handle = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t song_handle = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t unk = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t unk = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t playback_mode =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
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);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t playback_mode = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t repeat_mode = poly::load_and_swap<uint32_t>(buffer + 8);
|
||||
uint32_t flags = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
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);
|
||||
return XMPGetStatus(state_ptr);
|
||||
}
|
||||
case 0x0007000B: {
|
||||
assert_true(!buffer_length || buffer_length == 8);
|
||||
uint32_t xmp_client =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
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);
|
||||
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;
|
||||
}
|
||||
case 0x0007000C: {
|
||||
assert_true(!buffer_length || buffer_length == 8);
|
||||
uint32_t xmp_client =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
float float_value = poly::load_and_swap<float>(membase_ + buffer_ptr + 4);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
float float_value = poly::load_and_swap<float>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t dummy_alloc_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t dummy_alloc_size =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
|
||||
uint32_t songs_ptr =
|
||||
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 xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t dummy_alloc_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t dummy_alloc_size = poly::load_and_swap<uint32_t>(buffer + 8);
|
||||
uint32_t songs_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
|
||||
uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 16);
|
||||
uint32_t playlist_name_ptr = poly::load_and_swap<uint32_t>(buffer + 20);
|
||||
uint32_t flags = poly::load_and_swap<uint32_t>(buffer + 24);
|
||||
uint32_t song_handles_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 28); // 0?
|
||||
uint32_t playlist_handle_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 32);
|
||||
poly::load_and_swap<uint32_t>(buffer + 28); // 0?
|
||||
uint32_t playlist_handle_ptr = poly::load_and_swap<uint32_t>(buffer + 32);
|
||||
assert_true(xmp_client == 0x00000002);
|
||||
auto playlist_name =
|
||||
poly::load_and_swap<std::wstring>(membase_ + playlist_name_ptr);
|
||||
auto playlist_name = poly::load_and_swap<std::wstring>(
|
||||
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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t unk_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4); // 0
|
||||
uint32_t info_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t unk_ptr = poly::load_and_swap<uint32_t>(buffer + 4); // 0
|
||||
uint32_t info_ptr = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + info_ptr + 0, song->handle);
|
||||
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 0,
|
||||
song->name);
|
||||
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 40,
|
||||
song->artist);
|
||||
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,
|
||||
poly::store_and_swap<uint32_t>(info + 0, song->handle);
|
||||
poly::store_and_swap<std::wstring>(info + 4 + 572 + 0, song->name);
|
||||
poly::store_and_swap<std::wstring>(info + 4 + 572 + 40, song->artist);
|
||||
poly::store_and_swap<std::wstring>(info + 4 + 572 + 80, song->album);
|
||||
poly::store_and_swap<std::wstring>(info + 4 + 572 + 120,
|
||||
song->album_artist);
|
||||
poly::store_and_swap<std::wstring>(membase_ + info_ptr + 4 + 572 + 160,
|
||||
song->genre);
|
||||
poly::store_and_swap<uint32_t>(membase_ + info_ptr + 4 + 572 + 200,
|
||||
song->track_number);
|
||||
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,
|
||||
poly::store_and_swap<std::wstring>(info + 4 + 572 + 160, song->genre);
|
||||
poly::store_and_swap<uint32_t>(info + 4 + 572 + 200, song->track_number);
|
||||
poly::store_and_swap<uint32_t>(info + 4 + 572 + 204, song->duration_ms);
|
||||
poly::store_and_swap<uint32_t>(info + 4 + 572 + 208,
|
||||
static_cast<uint32_t>(song->format));
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
case 0x00070013: {
|
||||
assert_true(!buffer_length || buffer_length == 8);
|
||||
uint32_t xmp_client =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t playlist_handle =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t playlist_handle = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t unk1 = poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t enabled =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t unk1 = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t enabled = poly::load_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
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>(
|
||||
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<uint32_t>(membase_ + unk_ptr, 0);
|
||||
poly::store_and_swap<uint32_t>(membase_ + disabled_ptr, disabled_);
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(unk_ptr), 0);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t playback_mode_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
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);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t playback_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t repeat_mode_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
|
||||
uint32_t unk3_ptr = poly::load_and_swap<uint32_t>(buffer + 12);
|
||||
assert_true(xmp_client == 0x00000002);
|
||||
XELOGD("XMPGetPlaybackBehavior(%.8X, %.8X, %.8X)", playback_mode_ptr,
|
||||
repeat_mode_ptr, unk3_ptr);
|
||||
poly::store_and_swap<uint32_t>(membase_ + playback_mode_ptr,
|
||||
static_cast<uint32_t>(playback_mode_));
|
||||
poly::store_and_swap<uint32_t>(membase_ + repeat_mode_ptr,
|
||||
poly::store_and_swap<uint32_t>(
|
||||
memory_->TranslateVirtual(playback_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_));
|
||||
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;
|
||||
}
|
||||
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<uint32_t>(membase_ + buffer_ptr + 0);
|
||||
uint32_t song_count =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 4);
|
||||
uint32_t size_ptr =
|
||||
poly::load_and_swap<uint32_t>(membase_ + buffer_ptr + 8);
|
||||
uint32_t xmp_client = poly::load_and_swap<uint32_t>(buffer + 0);
|
||||
uint32_t song_count = poly::load_and_swap<uint32_t>(buffer + 4);
|
||||
uint32_t size_ptr = poly::load_and_swap<uint32_t>(buffer + 8);
|
||||
assert_true(xmp_client == 0x00000002);
|
||||
// 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;
|
||||
}
|
||||
case 0x0007003D: {
|
||||
|
|
|
@ -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);
|
||||
}
|
||||
|
|
|
@ -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<uint32_t>(mem + ptr + 0, head_);
|
||||
poly::store_and_swap<uint32_t>(mem + ptr + 4, 0);
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0), head_);
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4), 0);
|
||||
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;
|
||||
}
|
||||
|
||||
bool NativeList::IsQueued(uint32_t ptr) {
|
||||
uint8_t* mem = memory_->membase();
|
||||
uint32_t flink = poly::load_and_swap<uint32_t>(mem + ptr + 0);
|
||||
uint32_t blink = poly::load_and_swap<uint32_t>(mem + ptr + 4);
|
||||
uint32_t flink =
|
||||
poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0));
|
||||
uint32_t blink =
|
||||
poly::load_and_swap<uint32_t>(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<uint32_t>(mem + ptr + 0);
|
||||
uint32_t blink = poly::load_and_swap<uint32_t>(mem + ptr + 4);
|
||||
uint32_t flink =
|
||||
poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0));
|
||||
uint32_t blink =
|
||||
poly::load_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4));
|
||||
if (ptr == head_) {
|
||||
head_ = 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 {
|
||||
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) {
|
||||
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>(mem + ptr + 4, 0);
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 0), 0);
|
||||
poly::store_and_swap<uint32_t>(memory_->TranslateVirtual(ptr + 4), 0);
|
||||
}
|
||||
|
||||
uint32_t NativeList::Shift() {
|
||||
|
|
|
@ -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<uint32_t>(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<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);
|
||||
|
||||
// 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 + 0x100, thread_state_address_);
|
||||
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=7
|
||||
XThread* thread = reinterpret_cast<XThread*>(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<uint32_t>(apc_ptr + 16);
|
||||
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);
|
||||
|
@ -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<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 + 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<uint32_t>(apc_ptr + 20);
|
||||
|
||||
// Mark as uninserted so that it can be reinserted again by the routine.
|
||||
|
|
|
@ -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<uint32_t>(eip + 0x00, ex.media_id);
|
||||
poly::store_and_swap<uint32_t>(eip + 0x04, ex.version.value);
|
||||
|
|
|
@ -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<uint8_t>(SHIM_MEM_ADDR(a))
|
||||
#define SHIM_MEM_16(a) poly::load_and_swap<uint16_t>(SHIM_MEM_ADDR(a))
|
||||
|
|
|
@ -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<uint32_t>(mem + record);
|
||||
const uint32_t value =
|
||||
poly::load_and_swap<uint32_t>(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<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;
|
||||
|
||||
// Verify library index matches given library.
|
||||
|
|
|
@ -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<uint32_t>(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<uint32_t>(state->memory()->TranslateVirtual(0x7FEA0000 + reg_num),
|
||||
reg_value);
|
||||
}
|
||||
|
||||
SHIM_CALL XMAInitializeContext_shim(PPCContext* ppc_state, KernelState* state) {
|
||||
|
|
|
@ -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<uint32_t>(mem + pKeDebugMonitorData, 0);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(mem + pKeCertMonitorData, 0);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(mem + pXboxHardwareInfo + 0, 0); // flags
|
||||
poly::store_and_swap<uint8_t>(mem + pXboxHardwareInfo + 4,
|
||||
0x06); // cpu count
|
||||
poly::store_and_swap<uint32_t>(lpXboxHardwareInfo + 0, 0); // flags
|
||||
poly::store_and_swap<uint8_t>(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<uint32_t>(mem + ppXexExecutableModuleHandle,
|
||||
auto lpXexExecutableModuleHandle =
|
||||
memory_->TranslateVirtual(pXexExecutableModuleHandle);
|
||||
poly::store_and_swap<uint32_t>(lppXexExecutableModuleHandle,
|
||||
pXexExecutableModuleHandle);
|
||||
poly::store_and_swap<uint32_t>(mem + pXexExecutableModuleHandle + 0x58,
|
||||
poly::store_and_swap<uint32_t>(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<uint16_t>(mem + pXboxKrnlVersion + 0, 2);
|
||||
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 2, 0xFFFF);
|
||||
poly::store_and_swap<uint16_t>(mem + pXboxKrnlVersion + 4, 0xFFFF);
|
||||
poly::store_and_swap<uint8_t>(mem + pXboxKrnlVersion + 6, 0x80);
|
||||
poly::store_and_swap<uint8_t>(mem + pXboxKrnlVersion + 7, 0x00);
|
||||
poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 0, 2);
|
||||
poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 2, 0xFFFF);
|
||||
poly::store_and_swap<uint16_t>(lpXboxKrnlVersion + 4, 0xFFFF);
|
||||
poly::store_and_swap<uint8_t>(lpXboxKrnlVersion + 6, 0x80);
|
||||
poly::store_and_swap<uint8_t>(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<uint64_t>(mem + pKeTimeStampBundle + 0, 0);
|
||||
poly::store_and_swap<uint64_t>(mem + pKeTimeStampBundle + 8, 0);
|
||||
poly::store_and_swap<uint32_t>(mem + pKeTimeStampBundle + 16, GetTickCount());
|
||||
poly::store_and_swap<uint32_t>(mem + pKeTimeStampBundle + 20, 0);
|
||||
poly::store_and_swap<uint64_t>(lpKeTimeStampBundle + 0, 0);
|
||||
poly::store_and_swap<uint64_t>(lpKeTimeStampBundle + 8, 0);
|
||||
poly::store_and_swap<uint32_t>(lpKeTimeStampBundle + 16, GetTickCount());
|
||||
poly::store_and_swap<uint32_t>(lpKeTimeStampBundle + 20, 0);
|
||||
CreateTimerQueueTimer(
|
||||
×tamp_timer_, nullptr,
|
||||
[](PVOID param, BOOLEAN timer_or_wait_fired) {
|
||||
auto timestamp_bundle = reinterpret_cast<uint8_t*>(param);
|
||||
poly::store_and_swap<uint32_t>(timestamp_bundle + 16, GetTickCount());
|
||||
},
|
||||
mem + pKeTimeStampBundle, 0,
|
||||
lpKeTimeStampBundle, 0,
|
||||
1, // 1ms
|
||||
WT_EXECUTEINTIMERTHREAD);
|
||||
}
|
||||
|
|
|
@ -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);
|
||||
|
|
|
@ -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<uint32_t>(membase + obj_attributes_ptr + 4);
|
||||
uint32_t name_str_ptr = poly::load_and_swap<uint32_t>(
|
||||
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);
|
||||
|
|
|
@ -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<uint32_t>(mem + pVdGlobalDevice, 0);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(mem + pVdGlobalXamDevice, 0);
|
||||
poly::store_and_swap<uint32_t>(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<uint32_t>(mem + pVdGpuClockInMHz, 500);
|
||||
poly::store_and_swap<uint32_t>(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<X_RTL_CRITICAL_SECTION*>(mem + pVdHSIOCalibrationLock);
|
||||
memory->TranslateVirtual<X_RTL_CRITICAL_SECTION*>(pVdHSIOCalibrationLock);
|
||||
xeRtlInitializeCriticalSectionAndSpinCount(hsio_lock, pVdHSIOCalibrationLock,
|
||||
10000);
|
||||
}
|
||||
|
|
|
@ -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<uint32_t>(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<std::mutex> lock(kernel_state_->object_mutex());
|
||||
|
||||
DISPATCH_HEADER* header_be =
|
||||
(DISPATCH_HEADER*)kernel_state_->memory()->Translate(native_ptr);
|
||||
auto header_be =
|
||||
kernel_state_->memory()->TranslateVirtual<DISPATCH_HEADER*>(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);
|
||||
|
|
|
@ -13,7 +13,6 @@
|
|||
#include <atomic>
|
||||
|
||||
#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);
|
||||
|
|
|
@ -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<uint32_t>(Translate(0x40000000), 0x00C40000);
|
||||
poly::store_and_swap<uint32_t>(Translate(0x40000004), 0x00010000);
|
||||
VirtualAlloc(TranslateVirtual(0x40000000), 0x00010000, MEM_COMMIT,
|
||||
PAGE_READWRITE);
|
||||
poly::store_and_swap<uint32_t>(TranslateVirtual(0x40000000), 0x00C40000);
|
||||
poly::store_and_swap<uint32_t>(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<const uint32_t*>(membase_ + start);
|
||||
const uint32_t* pe = reinterpret_cast<const uint32_t*>(membase_ + end);
|
||||
auto p = TranslateVirtual<const uint32_t*>(start);
|
||||
auto pe = TranslateVirtual<const uint32_t*>(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<const uint8_t*>(p) - membase_);
|
||||
return uint32_t(reinterpret_cast<const uint8_t*>(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<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->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);
|
||||
|
|
|
@ -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 <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_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_;
|
||||
|
|
Loading…
Reference in New Issue