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);