From 9f0663efa27a605ce8af8769d6cfa6530f44636c Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Sun, 3 May 2015 17:17:22 -0500 Subject: [PATCH 1/3] XexLoadImage for user modules --- src/xenia/kernel/kernel_state.cc | 31 ++++++++++++++++++++++++++-- src/xenia/kernel/kernel_state.h | 3 +++ src/xenia/kernel/xboxkrnl_modules.cc | 9 +++++++- 3 files changed, 40 insertions(+), 3 deletions(-) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 60933a153..30c5f1581 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -107,8 +107,13 @@ XModule* KernelState::GetModule(const char* name) { // Some games request this, for some reason. wtf. return nullptr; } else { - // TODO(benvanik): support user modules/loading/etc. - assert_always(); + for (XUserModule *module : user_modules_) { + if (module->name() == name) { + module->Retain(); + return module; + } + } + return nullptr; } } @@ -136,6 +141,28 @@ void KernelState::SetExecutableModule(XUserModule* module) { } } +XUserModule* KernelState::LoadUserModule(const char *name) { + // See if we've already loaded it + for (XUserModule *module : user_modules_) { + if (module->name() == name) { + module->Retain(); + return module; + } + } + + // Module wasn't loaded, so load it. + XUserModule *module = new XUserModule(this, name); + X_STATUS status = module->LoadFromFile(name); + if (XFAILED(status)) { + delete module; + return nullptr; + } + + user_modules_.push_back(module); + module->Retain(); + return module; +} + void KernelState::RegisterThread(XThread* thread) { std::lock_guard lock(object_mutex_); threads_by_id_[thread->thread_id()] = thread; diff --git a/src/xenia/kernel/kernel_state.h b/src/xenia/kernel/kernel_state.h index d2d902e90..b2a413607 100644 --- a/src/xenia/kernel/kernel_state.h +++ b/src/xenia/kernel/kernel_state.h @@ -69,6 +69,7 @@ class KernelState { XModule* GetModule(const char* name); XUserModule* GetExecutableModule(); void SetExecutableModule(XUserModule* module); + XUserModule* LoadUserModule(const char *name); void RegisterThread(XThread* thread); void UnregisterThread(XThread* thread); @@ -104,6 +105,8 @@ class KernelState { uint32_t process_type_; XUserModule* executable_module_; + std::vector user_modules_; + friend class XObject; }; diff --git a/src/xenia/kernel/xboxkrnl_modules.cc b/src/xenia/kernel/xboxkrnl_modules.cc index 4351e4f37..6d9578fb9 100644 --- a/src/xenia/kernel/xboxkrnl_modules.cc +++ b/src/xenia/kernel/xboxkrnl_modules.cc @@ -224,7 +224,14 @@ SHIM_CALL XexLoadImage_shim(PPCContext* ppc_state, KernelState* state) { result = X_STATUS_SUCCESS; } else { - result = X_STATUS_NO_SUCH_FILE; + XUserModule* usermod = state->LoadUserModule(module_name); + if (usermod) { + result = X_STATUS_SUCCESS; + + usermod->RetainHandle(); + SHIM_SET_MEM_32(handle_ptr, usermod->handle()); + usermod->Release(); + } } SHIM_SET_RETURN_32(result); From f12a8dbe2017ae341e309c75062c516551e532f6 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Mon, 4 May 2015 22:07:58 -0500 Subject: [PATCH 2/3] Release modules on destruction --- src/xenia/kernel/kernel_state.cc | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 30c5f1581..3472efdec 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -77,6 +77,10 @@ KernelState::~KernelState() { assert_true(shared_kernel_state_ == this); shared_kernel_state_ = nullptr; + + for (XUserModule* mod : user_modules_) { + mod->Release(); + } } KernelState* KernelState::shared() { return shared_kernel_state_; } From 1b111f031341ab6f4441efe914767b774eb8da25 Mon Sep 17 00:00:00 2001 From: "Dr. Chat" Date: Mon, 4 May 2015 22:16:48 -0500 Subject: [PATCH 3/3] Thread safety --- src/xenia/kernel/kernel_state.cc | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 3472efdec..151f862e7 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -111,6 +111,8 @@ XModule* KernelState::GetModule(const char* name) { // Some games request this, for some reason. wtf. return nullptr; } else { + std::lock_guard lock(object_mutex_); + for (XUserModule *module : user_modules_) { if (module->name() == name) { module->Retain(); @@ -146,6 +148,8 @@ void KernelState::SetExecutableModule(XUserModule* module) { } XUserModule* KernelState::LoadUserModule(const char *name) { + std::lock_guard lock(object_mutex_); + // See if we've already loaded it for (XUserModule *module : user_modules_) { if (module->name() == name) { @@ -158,7 +162,7 @@ XUserModule* KernelState::LoadUserModule(const char *name) { XUserModule *module = new XUserModule(this, name); X_STATUS status = module->LoadFromFile(name); if (XFAILED(status)) { - delete module; + module->Release(); return nullptr; }