From 266d987fc72d4fa5ebe1c6e2e2b2192b780b366d Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 20 Jan 2020 17:25:15 +0000 Subject: [PATCH] [XAM] Return error in XamContentGetLicenseMask if we're not running from package This fixes Halo CEA putting itself into a packaged/demo mode, where it doesn't perform some DVD checks & skips cache mounting, and probably other things too. Now CEA should actually mount & write some stuff into the cache dir while the intro cinematic plays (first writes a pak_stream.s3dpak file, then after a few seconds into the intro video it writes fileList.ps, which seems to have some strange values inside..) I also added an exception to the code for arcade titles, since they'll probably need to use XamContentGetLicenseMask even when ran outside of a package. --- src/xenia/emulator.cc | 3 +++ src/xenia/emulator.h | 4 ++++ src/xenia/kernel/xam/xam_content.cc | 11 +++++++++++ src/xenia/xbox.h | 1 + 4 files changed, 19 insertions(+) diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index 3af5d5c4f..66b8831a6 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -310,6 +310,7 @@ X_STATUS Emulator::LaunchXexFile(std::wstring path) { auto file_name = xe::find_name_from_path(path); // Launch the game. + title_packaged_ = false; std::string fs_path = "game:\\" + xe::to_string(file_name); return CompleteLaunch(path, fs_path); } @@ -333,6 +334,7 @@ X_STATUS Emulator::LaunchDiscImage(std::wstring path) { file_system_->RegisterSymbolicLink("d:", mount_path); // Launch the game. + title_packaged_ = false; auto module_path(FindLaunchModule()); return CompleteLaunch(path, module_path); } @@ -356,6 +358,7 @@ X_STATUS Emulator::LaunchStfsContainer(std::wstring path) { file_system_->RegisterSymbolicLink("d:", mount_path); // Launch the game. + title_packaged_ = true; auto module_path(FindLaunchModule()); return CompleteLaunch(path, module_path); } diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index b9db4a31a..0043667ef 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -66,6 +66,9 @@ class Emulator { // Are we currently running a title? bool is_title_open() const { return title_id_ != 0; } + // Is the title running from an STFS package? + bool is_title_packaged() const { return title_packaged_; } + // Window used for displaying graphical output. ui::Window* display_window() const { return display_window_; } @@ -178,6 +181,7 @@ class Emulator { std::unique_ptr kernel_state_; kernel::object_ref main_thread_; uint32_t title_id_; // Currently running title ID + bool title_packaged_ = false; // Is title running from a package? bool paused_; bool restoring_; diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index 24df8ae9e..848b38f88 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -68,6 +68,17 @@ dword_result_t XamContentGetLicenseMask(lpdword_t mask_ptr, // if the game is purchased or not. *mask_ptr = static_cast(cvars::license_mask); + // Halo CEA calls this function to check if it's being ran from a package + // (maybe to know if it's a demo or something?) + // If we don't error it'll skip a bunch of things (DVD check/cache mount/...) + // So make sure to error if it's not running from package: + if (!kernel_state()->emulator()->is_title_packaged()) { + // Hack to still allow arcade titles get the license mask: + if ((kernel_state()->emulator()->title_id() & 0xFFFF0000) != 0x58410000) { + return X_E_ACCESS_DENIED; + } + } + if (overlapped_ptr) { kernel_state()->CompleteOverlappedImmediate(overlapped_ptr, X_ERROR_SUCCESS); diff --git a/src/xenia/xbox.h b/src/xenia/xbox.h index 90bc1a328..da801a7bf 100644 --- a/src/xenia/xbox.h +++ b/src/xenia/xbox.h @@ -111,6 +111,7 @@ typedef uint32_t X_HRESULT; #define X_E_FALSE static_cast(0x80000000L) #define X_E_SUCCESS X_HRESULT_FROM_WIN32(X_ERROR_SUCCESS) +#define X_E_ACCESS_DENIED X_HRESULT_FROM_WIN32(X_ERROR_ACCESS_DENIED) #define X_E_INVALIDARG X_HRESULT_FROM_WIN32(X_ERROR_INVALID_PARAMETER) #define X_E_DEVICE_NOT_CONNECTED X_HRESULT_FROM_WIN32(X_ERROR_DEVICE_NOT_CONNECTED) #define X_E_NOTFOUND X_HRESULT_FROM_WIN32(X_ERROR_NOT_FOUND)