From e3e57bdb47af35b111d7150c39b2801949872098 Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Mon, 20 Apr 2026 20:41:40 +0200 Subject: [PATCH 1/3] [XAM/XMP] Fixed incorrect size of XMP_SONGINFO structure Thanks The-Little-Wolf --- src/xenia/kernel/xam/apps/xmp_app.h | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xam/apps/xmp_app.h b/src/xenia/kernel/xam/apps/xmp_app.h index e389edc19..8d7afa044 100644 --- a/src/xenia/kernel/xam/apps/xmp_app.h +++ b/src/xenia/kernel/xam/apps/xmp_app.h @@ -48,8 +48,9 @@ struct XMP_SONGINFO { xe::be track_number; xe::be duration; xe::be song_format; + xe::be unknown_1; }; -static_assert_size(XMP_SONGINFO, 988); +static_assert_size(XMP_SONGINFO, 0x3E0); struct XMP_PLAY_TITLE_PLAYLIST { xe::be xmp_client; From e91faca1c44790b26410084c43bead9ef2edd3f0 Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Tue, 21 Apr 2026 21:58:49 +0200 Subject: [PATCH 2/3] [VFS] Return more proper error codes in OpenFile - Added handling for opening file with directory flag --- src/xenia/vfs/virtual_file_system.cc | 14 +++++++++----- src/xenia/xbox.h | 2 ++ 2 files changed, 11 insertions(+), 5 deletions(-) diff --git a/src/xenia/vfs/virtual_file_system.cc b/src/xenia/vfs/virtual_file_system.cc index 01ca0dd8c..248e9a9a2 100644 --- a/src/xenia/vfs/virtual_file_system.cc +++ b/src/xenia/vfs/virtual_file_system.cc @@ -230,7 +230,7 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry, : root_entry->ResolvePath(base_path); if (!parent_entry) { *out_action = FileAction::kDoesNotExist; - return X_STATUS_NO_SUCH_FILE; + return X_STATUS_OBJECT_PATH_NOT_FOUND; } auto file_name = xe::utf8::find_name_from_guest_path(path); @@ -244,13 +244,17 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry, return X_STATUS_FILE_IS_A_DIRECTORY; } + if (!(entry->attributes() & kFileAttributeDirectory) && is_directory) { + return X_STATUS_NOT_A_DIRECTORY; + } + // If the entry does not exist on the host then remove the cached entry if (parent_entry) { - const xe::vfs::HostPathEntry* host_Path = + const xe::vfs::HostPathEntry* host_path = dynamic_cast(parent_entry); - if (host_Path) { - auto const file_path = host_Path->host_path() / entry->name(); + if (host_path) { + auto const file_path = host_path->host_path() / entry->name(); if (!std::filesystem::exists(file_path)) { // Remove cached entry @@ -268,7 +272,7 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry, // Must exist. if (!entry) { *out_action = FileAction::kDoesNotExist; - return X_STATUS_NO_SUCH_FILE; + return X_STATUS_OBJECT_NAME_NOT_FOUND; } break; case FileDisposition::kCreate: diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 2565380d6..334578599 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -58,6 +58,7 @@ typedef uint32_t X_STATUS; #define X_STATUS_OBJECT_NAME_INVALID ((X_STATUS)0xC0000033L) #define X_STATUS_OBJECT_NAME_NOT_FOUND ((X_STATUS)0xC0000034L) #define X_STATUS_OBJECT_NAME_COLLISION ((X_STATUS)0xC0000035L) +#define X_STATUS_OBJECT_PATH_NOT_FOUND ((X_STATUS)0xC000003AL) #define X_STATUS_INVALID_PAGE_PROTECTION ((X_STATUS)0xC0000045L) #define X_STATUS_MUTANT_NOT_OWNED ((X_STATUS)0xC0000046L) #define X_STATUS_SEMAPHORE_LIMIT_EXCEEDED ((X_STATUS)0xC0000047L) @@ -72,6 +73,7 @@ typedef uint32_t X_STATUS; #define X_STATUS_INVALID_PARAMETER_1 ((X_STATUS)0xC00000EFL) #define X_STATUS_INVALID_PARAMETER_2 ((X_STATUS)0xC00000F0L) #define X_STATUS_INVALID_PARAMETER_3 ((X_STATUS)0xC00000F1L) +#define X_STATUS_NOT_A_DIRECTORY ((X_STATUS)0xC0000103L) #define X_STATUS_PROCESS_IS_TERMINATING ((X_STATUS)0xC000010AL) #define X_STATUS_DLL_NOT_FOUND ((X_STATUS)0xC0000135L) #define X_STATUS_ENTRYPOINT_NOT_FOUND ((X_STATUS)0xC0000139L) From 68d409ebbae1560a13cfb5db8d524de6096f7770 Mon Sep 17 00:00:00 2001 From: Adrian <78108584+AdrianCassar@users.noreply.github.com> Date: Sun, 12 Apr 2026 22:44:48 +0100 Subject: [PATCH 3/3] [Kernel] Fixed releasing XObject handles on title termination --- src/xenia/kernel/kernel_state.cc | 5 +--- src/xenia/kernel/util/object_table.cc | 2 +- src/xenia/kernel/xam/xam_info.cc | 40 +++++++++++++++++++-------- 3 files changed, 30 insertions(+), 17 deletions(-) diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc index 19be10b0f..dce43d151 100644 --- a/src/xenia/kernel/kernel_state.cc +++ b/src/xenia/kernel/kernel_state.cc @@ -903,10 +903,7 @@ void KernelState::TerminateTitle() { // Third: Unload all user modules (including the executable). for (size_t i = 0; i < user_modules_.size(); i++) { - X_STATUS status = user_modules_[i]->Unload(); - assert_true(XSUCCEEDED(status)); - - object_table_.RemoveHandle(user_modules_[i]->handle()); + user_modules_[i]->ReleaseHandle(); } user_modules_.clear(); diff --git a/src/xenia/kernel/util/object_table.cc b/src/xenia/kernel/util/object_table.cc index 4e6dc1b65..2e29bb96b 100644 --- a/src/xenia/kernel/util/object_table.cc +++ b/src/xenia/kernel/util/object_table.cc @@ -276,7 +276,7 @@ void ObjectTable::PurgeAllObjects() { auto& entry = table_[slot]; if (entry.object) { entry.handle_ref_count = 0; - entry.object->Release(); + entry.object->ReleaseHandle(); entry.object = nullptr; } diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 047a029a5..9369c9646 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -383,27 +383,43 @@ void XamLoaderLaunchTitle_entry(lpstring_t raw_name_ptr, dword_t flags) { auto& loader_data = xam->loader_data(); loader_data.launch_flags = flags; + std::string title; + std::string message; + // Translate the launch path to a full path. if (raw_name_ptr && !raw_name_ptr.value().empty()) { loader_data.launch_path = xe::path_to_utf8(raw_name_ptr.value()); loader_data.launch_data_present = true; xam->SaveLoaderData(); - - auto display_window = kernel_state()->emulator()->display_window(); - auto imgui_drawer = kernel_state()->emulator()->imgui_drawer(); - - if (display_window && imgui_drawer) { - display_window->app_context().CallInUIThreadSynchronous([imgui_drawer]() { - xe::ui::ImGuiDialog::ShowMessageBox( - imgui_drawer, "Title was restarted", - "Title closed with new launch data. \nPlease restart Xenia. " - "Game will be loaded automatically."); - }); - } + title = "Title was restarted"; + message = + "Title closed with new launch data. \nPlease restart Xenia. " + "Game will be loaded automatically."; } else { + title = "Title terminated"; + message = "Game requested exit to dashboard."; assert_always("Game requested exit to dashboard via XamLoaderLaunchTitle"); } + auto display_window = kernel_state()->emulator()->display_window(); + auto imgui_drawer = kernel_state()->emulator()->imgui_drawer(); + + if (display_window && imgui_drawer) { + display_window->app_context().CallInUIThreadSynchronous( + [imgui_drawer, title, message]() { + auto dialog = xe::ui::ImGuiDialog::ShowMessageBox( + imgui_drawer, title.c_str(), message.c_str()); + + std::jthread([dialog]() { + while (!dialog->IsClosing()) { + std::this_thread::yield(); + } + + std::quick_exit(0); + }).detach(); + }); + } + // This function does not return. kernel_state()->TerminateTitle(); }