From a74fe21f766a3ef38d06a5c7777ded524ca78eb7 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sun, 25 Jan 2026 20:30:48 +0100 Subject: [PATCH 1/6] [CPU] Disable context promotion only for vertex type --- .../compiler/passes/context_promotion_pass.cc | 35 +++++++++++-------- 1 file changed, 21 insertions(+), 14 deletions(-) diff --git a/src/xenia/cpu/compiler/passes/context_promotion_pass.cc b/src/xenia/cpu/compiler/passes/context_promotion_pass.cc index f5cc368db..969c1a03a 100644 --- a/src/xenia/cpu/compiler/passes/context_promotion_pass.cc +++ b/src/xenia/cpu/compiler/passes/context_promotion_pass.cc @@ -105,7 +105,7 @@ void ContextPromotionPass::PromoteBlock(Block* block) { // Volatile instruction - requires all context values be flushed. validity.reset(); } else if (i->opcode == &OPCODE_LOAD_CONTEXT_info) { - size_t offset = i->src1.offset; + const size_t offset = i->src1.offset; if (validity.test(static_cast(offset))) { // Legit previous value, reuse. Value* previous_value = context_values_[offset]; @@ -113,15 +113,19 @@ void ContextPromotionPass::PromoteBlock(Block* block) { i->set_src1(previous_value); } else { // Store the loaded value into the table. - context_values_[offset] = i->dest; - validity.set(static_cast(offset)); + if (i->dest->type != TypeName::VEC128_TYPE) { + context_values_[offset] = i->dest; + validity.set(static_cast(offset)); + } } } else if (i->opcode == &OPCODE_STORE_CONTEXT_info) { - size_t offset = i->src1.offset; + const size_t offset = i->src1.offset; Value* value = i->src2.value; - // Store value into the table for later. - context_values_[offset] = value; - validity.set(static_cast(offset)); + if (value->type != TypeName::VEC128_TYPE) { + // Store value into the table for later. + context_values_[offset] = value; + validity.set(static_cast(offset)); + } } i = next; } @@ -140,13 +144,16 @@ void ContextPromotionPass::RemoveDeadStoresBlock(Block* block) { // Volatile instruction - requires all context values be flushed. validity.reset(); } else if (i->opcode == &OPCODE_STORE_CONTEXT_info) { - size_t offset = i->src1.offset; - if (!validity.test(static_cast(offset))) { - // Offset not yet written, mark and continue. - validity.set(static_cast(offset)); - } else { - // Already written to. Remove this store. - i->UnlinkAndNOP(); + const size_t offset = i->src1.offset; + const Value* value = i->src2.value; + if (value->type != TypeName::VEC128_TYPE) { + if (!validity.test(static_cast(offset))) { + // Offset not yet written, mark and continue. + validity.set(static_cast(offset)); + } else { + // Already written to. Remove this store. + i->UnlinkAndNOP(); + } } } i = prev; From ac6fd653855f6388bd5cdb30f8dfc85651290598 Mon Sep 17 00:00:00 2001 From: Stayd Date: Thu, 15 Jan 2026 17:12:49 -0700 Subject: [PATCH 2/6] [GPU] Add anisotropic filtering override --- src/xenia/gpu/dxbc_shader_translator.cc | 6 +++++- src/xenia/gpu/gpu_flags.cc | 12 ++++++++++++ src/xenia/gpu/gpu_flags.h | 2 ++ src/xenia/gpu/spirv_shader_translator.cc | 6 +++++- 4 files changed, 24 insertions(+), 2 deletions(-) diff --git a/src/xenia/gpu/dxbc_shader_translator.cc b/src/xenia/gpu/dxbc_shader_translator.cc index 0faa3c5bb..42eac768c 100644 --- a/src/xenia/gpu/dxbc_shader_translator.cc +++ b/src/xenia/gpu/dxbc_shader_translator.cc @@ -17,6 +17,7 @@ #include "xenia/base/cvar.h" #include "xenia/base/math.h" #include "xenia/gpu/dxbc_shader.h" +#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/xenos.h" #include "xenia/ui/graphics_provider.h" @@ -1378,7 +1379,10 @@ void DxbcShaderTranslator::PostTranslation() { shader_binding.mag_filter = translator_binding.mag_filter; shader_binding.min_filter = translator_binding.min_filter; shader_binding.mip_filter = translator_binding.mip_filter; - shader_binding.aniso_filter = translator_binding.aniso_filter; + shader_binding.aniso_filter = + cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 + ? xenos::AnisoFilter(cvars::anisotropic_override) + : translator_binding.aniso_filter; } } } diff --git a/src/xenia/gpu/gpu_flags.cc b/src/xenia/gpu/gpu_flags.cc index c0cc3f290..417a8cb01 100644 --- a/src/xenia/gpu/gpu_flags.cc +++ b/src/xenia/gpu/gpu_flags.cc @@ -70,3 +70,15 @@ DEFINE_int32( "Set to higher number than query_occlusion_sample_lower_threshold. This " "value is ignored if query_occlusion_sample_lower_threshold is set to -1.", "GPU"); + +DEFINE_int32(anisotropic_override, -1, + "Level of anisotropic filtering enforced on all texture fetch " + "instructions.\n" + " -1 = No override\n" + " 0 = Disable anisotropic filtering\n" + " 1 = Force 1x anisotropic filtering\n" + " 2 = Force 2x anisotropic filtering\n" + " 3 = Force 4x anisotropic filtering\n" + " 4 = Force 8x anisotropic filtering\n" + " 5 = Force 16x anisotropic filtering", + "GPU"); diff --git a/src/xenia/gpu/gpu_flags.h b/src/xenia/gpu/gpu_flags.h index 77559f3c2..a85e66e62 100644 --- a/src/xenia/gpu/gpu_flags.h +++ b/src/xenia/gpu/gpu_flags.h @@ -30,6 +30,8 @@ DECLARE_int32(query_occlusion_sample_lower_threshold); DECLARE_int32(query_occlusion_sample_upper_threshold); +DECLARE_int32(anisotropic_override); + DECLARE_bool(disassemble_pm4); #define XE_GPU_FINE_GRAINED_DRAW_SCOPES 1 diff --git a/src/xenia/gpu/spirv_shader_translator.cc b/src/xenia/gpu/spirv_shader_translator.cc index 9046adb2a..7736ca6ee 100644 --- a/src/xenia/gpu/spirv_shader_translator.cc +++ b/src/xenia/gpu/spirv_shader_translator.cc @@ -17,6 +17,7 @@ #include "xenia/base/assert.h" #include "xenia/base/math.h" #include "xenia/base/string_buffer.h" +#include "xenia/gpu/gpu_flags.h" #include "xenia/gpu/spirv_shader.h" namespace xe { @@ -807,7 +808,10 @@ void SpirvShaderTranslator::PostTranslation() { shader_binding.mag_filter = translator_binding.mag_filter; shader_binding.min_filter = translator_binding.min_filter; shader_binding.mip_filter = translator_binding.mip_filter; - shader_binding.aniso_filter = translator_binding.aniso_filter; + shader_binding.aniso_filter = + cvars::anisotropic_override > -1 && cvars::anisotropic_override < 6 + ? xenos::AnisoFilter(cvars::anisotropic_override) + : translator_binding.aniso_filter; } } } From 2ba82072fc6a8873180e0a4efc1a57e1a6601402 Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Thu, 29 Jan 2026 19:45:39 +0100 Subject: [PATCH 3/6] [Kernel] Added stub for: NtCancelIoFile --- src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc | 10 ++++++++++ 1 file changed, 10 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc index 743716d4f..63755db85 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_io.cc @@ -443,6 +443,16 @@ dword_result_t NtRemoveIoCompletion_entry( DECLARE_XBOXKRNL_EXPORT2(NtRemoveIoCompletion, kFileSystem, kImplemented, kHighFrequency); +dword_result_t NtCancelIoFile_entry(dword_t handle) { + auto file = kernel_state()->object_table()->LookupObject(handle); + if (!file) { + return X_STATUS_INVALID_HANDLE; + } + + return X_STATUS_SUCCESS; +} +DECLARE_XBOXKRNL_EXPORT1(NtCancelIoFile, kFileSystem, kStub); + dword_result_t NtQueryFullAttributesFile_entry( pointer_t obj_attribs, pointer_t file_info) { From 603355ae5bf39bb08e5f2815bb37406af83ea6d8 Mon Sep 17 00:00:00 2001 From: Gliniak <153369+Gliniak@users.noreply.github.com> Date: Tue, 27 Jan 2026 22:15:34 +0100 Subject: [PATCH 4/6] [XAM] Fixed enumeration of achievements once again --- src/xenia/kernel/xam/xam_user.cc | 12 ++++-------- src/xenia/kernel/xenumerator.cc | 7 +++---- src/xenia/kernel/xenumerator.h | 3 ++- 3 files changed, 9 insertions(+), 13 deletions(-) diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 1ecfe7771..055cc23b8 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -568,11 +568,11 @@ dword_result_t XamUserCreateAchievementEnumerator_entry( } if (buffer_size_ptr) { - *buffer_size_ptr = static_cast(entry_size) * count; + *buffer_size_ptr = static_cast(entry_size * count); } auto e = object_ref( - new XAchievementEnumerator(kernel_state(), count, flags)); + new XAchievementEnumerator(kernel_state(), count, offset, flags)); auto result = e->Initialize(user_index, 0xFB, 0xB000A, 0xB000B, 0); if (XFAILED(result)) { return result; @@ -595,15 +595,11 @@ dword_result_t XamUserCreateAchievementEnumerator_entry( kernel_state()->achievement_manager()->GetTitleAchievements( requester_xuid, title_id_); - const auto requested_achievements = user_title_achievements | - std::views::drop(offset) | - std::views::take(count); - - if (requested_achievements.empty()) { + if (user_title_achievements.empty()) { return X_ERROR_INVALID_PARAMETER; } - for (const auto& entry : requested_achievements) { + for (const auto& entry : user_title_achievements) { auto unlock_time = X_FILETIME(); if (entry.IsUnlocked() && entry.unlock_time.is_valid()) { unlock_time = entry.unlock_time; diff --git a/src/xenia/kernel/xenumerator.cc b/src/xenia/kernel/xenumerator.cc index 076886c33..fc21e483a 100644 --- a/src/xenia/kernel/xenumerator.cc +++ b/src/xenia/kernel/xenumerator.cc @@ -83,13 +83,12 @@ uint32_t XStaticUntypedEnumerator::WriteItems(uint8_t* buffer_data, uint32_t XAchievementEnumerator::WriteItems(uint8_t* buffer_data, uint32_t buffer_size, uint32_t* written_count) { - size_t count = std::min(items_.size() - current_item_, items_per_enumerate()); - if (!count) { + if (items_.size() - current_item_ <= 0) { return X_ERROR_NO_MORE_FILES; } - size_t size = count * item_size(); - + const size_t count = + std::min(items_.size() - current_item_, items_per_enumerate()); auto details = reinterpret_cast(buffer_data); size_t string_offset = items_per_enumerate() * sizeof(xam::X_ACHIEVEMENT_DETAILS); diff --git a/src/xenia/kernel/xenumerator.h b/src/xenia/kernel/xenumerator.h index 59a8b9578..7f8a8b8a7 100644 --- a/src/xenia/kernel/xenumerator.h +++ b/src/xenia/kernel/xenumerator.h @@ -139,12 +139,13 @@ class XStaticEnumerator : public XStaticUntypedEnumerator { class XAchievementEnumerator : public XEnumerator { public: XAchievementEnumerator(KernelState* kernel_state, size_t items_per_enumerate, - uint32_t flags) + size_t enumeration_offset, uint32_t flags) : XEnumerator( kernel_state, items_per_enumerate, sizeof(xam::X_ACHIEVEMENT_DETAILS) + (!!(flags & 7) ? xam::X_ACHIEVEMENT_DETAILS::kStringBufferSize : 0)), + current_item_(enumeration_offset), flags_(flags) {} void AppendItem(xam::AchievementDetails item) { From e3c4b5aef5f6ab23413d789db29ae18691c59af3 Mon Sep 17 00:00:00 2001 From: Roy Stewart Date: Fri, 19 Dec 2025 08:22:55 -0500 Subject: [PATCH 5/6] refactor xenia-build printing functionality and add color to the outputs --- xenia-build.py | 115 ++++++++++++++++++++++++++++--------------------- 1 file changed, 65 insertions(+), 50 deletions(-) diff --git a/xenia-build.py b/xenia-build.py index b7589419e..3057a39f2 100755 --- a/xenia-build.py +++ b/xenia-build.py @@ -17,6 +17,7 @@ from shutil import rmtree import subprocess import sys import stat +import enum __author__ = "ben.vanik@gmail.com (Ben Vanik)" @@ -28,12 +29,30 @@ class bcolors: # OKBLUE = "\033[94m" OKCYAN = "\033[96m" # OKGREEN = "\033[92m" -# WARNING = "\033[93m" + WARNING = "\033[93m" FAIL = "\033[91m" ENDC = "\033[0m" # BOLD = "\033[1m" # UNDERLINE = "\033[4m" +def print_error(text: str): + print(f"{bcolors.FAIL}ERROR: {text}{bcolors.ENDC}") + +def print_warning(text: str): + print(f"{bcolors.WARNING}WARNING: {text}{bcolors.ENDC}") + +class ResultStatus(enum.Enum): + SUCCESS = enum.auto() + FAILURE = enum.auto() + +def print_status(status: ResultStatus): + match status: + case ResultStatus.SUCCESS: + print(f"{bcolors.OKCYAN}Success!{bcolors.ENDC}") + case ResultStatus.FAILURE: + print(f"{bcolors.FAIL}Error!{bcolors.ENDC}") + + # Detect if building on Android via Termux. host_linux_platform_is_android = False if sys.platform == "linux": @@ -146,19 +165,19 @@ def main(): # Check git exists. if not has_bin("git"): - print("WARNING: Git should be installed and on PATH. Version info will be omitted from all binaries!\n") + print_warning("Git should be installed and on PATH. Version info will be omitted from all binaries!\n") elif not git_is_repository(): - print("WARNING: The source tree is unversioned. Version info will be omitted from all binaries!\n") + print_warning("The source tree is unversioned. Version info will be omitted from all binaries!\n") # Check python version. python_minimum_ver = 3,10 if not sys.version_info[:2] >= (python_minimum_ver[0], python_minimum_ver[1]) or not sys.maxsize > 2**32: - print(f"ERROR: Python {python_minimum_ver[0]}.{python_minimum_ver[1]}+ 64-bit must be installed and on PATH") + print_error(f"Python {python_minimum_ver[0]}.{python_minimum_ver[1]}+ 64-bit must be installed and on PATH") sys.exit(1) # Grab Visual Studio version and execute shell to set up environment. if sys.platform == "win32" and not vs_version: - print("WARNING: Visual Studio not found!" + print_warning("Visual Studio not found!" "\nBuilding for Windows will not be supported." " Please refer to the building guide:" f"\nhttps://github.com/xenia-canary/xenia-canary/blob/{default_branch}/docs/building.md") @@ -327,7 +346,7 @@ def generate_source_class(path): source_path = f"{path}.cc" if os.path.isfile(header_path) or os.path.isfile(source_path): - print("ERROR: Target file already exists") + print_error("Target file already exists") return 1 if generate_source_file(header_path) > 0: @@ -352,13 +371,13 @@ def generate_source_file(path): */""" if os.path.isfile(path): - print("ERROR: Target file already exists") + print_error("Target file already exists") return 1 try: with open(path, "w") as f: f.write(copyright) except Exception as e: - print(f"ERROR: Could not write to file [path {path}]") + print_error(f"Could not write to file [path {path}]") return 1 return 0 @@ -473,7 +492,7 @@ def get_clang_format_binary(): if int(clang_format_out.split("version ")[1].split(".")[0]) == int(clang_format_version_req): print(clang_format_out) return binary - print(f"{bcolors.FAIL}ERROR: clang-format {clang_format_version_req} is not on PATH{bcolors.ENDC}") + print_error(f"clang-format {clang_format_version_req} is not on PATH") sys.exit(1) @@ -502,8 +521,8 @@ def get_premake_target_os(target_os_override=None): if target_os_override == "android": target_os = target_os_override else: - print( - "ERROR: cross-compilation is only supported for Android target") + print_error( + "cross-compilation is only supported for Android target") sys.exit(1) return target_os @@ -707,12 +726,11 @@ class SetupCommand(Command): if git_is_repository(): git_submodule_update() else: - print("WARNING: Git not available or not a repository. Dependencies may be missing.") + print_warning("Git not available or not a repository. Dependencies may be missing.") print("\n- running premake...") ret = run_platform_premake(target_os_override=args["target_os"]) - print("\nSuccess!" if ret == 0 else "\nError!") - + print_status(ResultStatus.SUCCESS if not ret else ResultStatus.FAILURE) return ret @@ -763,7 +781,7 @@ class PullCommand(Command): print("- running premake...") if run_platform_premake(target_os_override=args["target_os"]) == 0: - print("\nSuccess!") + print_status(ResultStatus.SUCCESS) return 0 @@ -791,7 +809,7 @@ class PremakeCommand(Command): print("Running premake...\n") ret = run_platform_premake(target_os_override=args["target_os"], cc=args["cc"], devenv=args["devenv"]) - print("Success!" if ret == 0 else "Error!") + print_status(ResultStatus.SUCCESS if not ret else ResultStatus.FAILURE) return ret @@ -830,7 +848,7 @@ class BaseBuildCommand(Command): args["config"])) if sys.platform == "win32": if not vs_version: - print("ERROR: Visual Studio is not installed.") + print_error("Visual Studio is not installed.") result = 1 else: targets = None @@ -872,14 +890,14 @@ class BaseBuildCommand(Command): ] + pass_args, env=dict(os.environ)) print("") if result != 0: - print("ERROR: cmake failed with one or more errors.") + print_error("cmake failed with one or more errors.") return result result = subprocess.call([ "ninja", f"-Cbuild/build_{args['config']}", ] + pass_args, env=dict(os.environ)) if result != 0: - print("ERROR: ninja failed with one or more errors.") + print_error("ninja failed with one or more errors.") return result @@ -899,10 +917,7 @@ class BuildCommand(BaseBuildCommand): result = super(BuildCommand, self).execute(args, pass_args, cwd) - if not result: - print(f"{bcolors.OKCYAN}Success!{bcolors.ENDC}") - else: - print(f"{bcolors.FAIL}Failed!{bcolors.ENDC}") + print_status(ResultStatus.SUCCESS if not result else ResultStatus.FAILURE) return result @@ -958,7 +973,7 @@ class BuildShadersCommand(Command): # Get the FXC path. fxc = glob(os.path.join(os.environ["ProgramFiles(x86)"], "Windows Kits", "10", "bin", "*", "x64", "fxc.exe")) if not fxc: - print("ERROR: could not find fxc!") + print_error("could not find fxc!") return 1 fxc = fxc[-1] # Highest version is last @@ -996,14 +1011,14 @@ class BuildShadersCommand(Command): "/nologo", src_path, ], stdout=subprocess.DEVNULL) != 0: - print("ERROR: failed to compile a DXBC shader") + print_error("failed to compile a DXBC shader") return 1 else: if all_targets: - print("WARNING: Direct3D DXBC shader building is supported" + print_warning("Direct3D DXBC shader building is supported" " only on Windows") else: - print("ERROR: Direct3D DXBC shader building is supported" + print_error("Direct3D DXBC shader building is supported" " only on Windows") return 1 @@ -1014,28 +1029,28 @@ class BuildShadersCommand(Command): # Get the SPIR-V tool paths. vulkan_sdk_path = os.environ["VULKAN_SDK"] if not os.path.exists(vulkan_sdk_path): - print("ERROR: could not find the Vulkan SDK in $VULKAN_SDK") + print_error("could not find the Vulkan SDK in $VULKAN_SDK") return 1 # bin is lowercase on Linux (even though it's uppercase on Windows). vulkan_bin_path = os.path.join(vulkan_sdk_path, "bin") if not os.path.exists(vulkan_bin_path): - print("ERROR: could not find the Vulkan SDK binaries") + print_error("could not find the Vulkan SDK binaries") return 1 glslang = os.path.join(vulkan_bin_path, "glslangValidator") if not has_bin(glslang): - print("ERROR: could not find glslangValidator") + print_error("could not find glslangValidator") return 1 spirv_opt = os.path.join(vulkan_bin_path, "spirv-opt") if not has_bin(spirv_opt): - print("ERROR: could not find spirv-opt") + print_error("could not find spirv-opt") return 1 spirv_remap = os.path.join(vulkan_bin_path, "spirv-remap") if not has_bin(spirv_remap): - print("ERROR: could not find spirv-remap") + print_error("could not find spirv-remap") return 1 spirv_dis = os.path.join(vulkan_bin_path, "spirv-dis") if not has_bin(spirv_dis): - print("ERROR: could not find spirv-dis") + print_error("could not find spirv-dis") return 1 # Build SPIR-V. @@ -1090,7 +1105,7 @@ class BuildShadersCommand(Command): input=(spirv_xesl_wrapper % src_name) if src_is_xesl else None, text=True).returncode != 0: - print("ERROR: failed to build a SPIR-V shader") + print_error("failed to build a SPIR-V shader") return 1 # spirv-opt input and output files must be different. spirv_file_path = f"{spirv_file_path_base}.spv" @@ -1100,7 +1115,7 @@ class BuildShadersCommand(Command): spirv_glslang_file_path, "-o", spirv_file_path, ]) != 0: - print("ERROR: failed to optimize a SPIR-V shader") + print_error("failed to optimize a SPIR-V shader") return 1 os.remove(spirv_glslang_file_path) # spirv-remap takes the output directory, but it may be the same @@ -1111,7 +1126,7 @@ class BuildShadersCommand(Command): "-i", spirv_file_path, "-o", spirv_dir_path, ]) != 0: - print("ERROR: failed to remap a SPIR-V shader") + print_error("failed to remap a SPIR-V shader") return 1 spirv_dis_file_path = f"{spirv_file_path_base}.txt" if subprocess.call([ @@ -1119,7 +1134,7 @@ class BuildShadersCommand(Command): "-o", spirv_dis_file_path, spirv_file_path, ]) != 0: - print("ERROR: failed to disassemble a SPIR-V shader") + print_error("failed to disassemble a SPIR-V shader") return 1 # Generate the header from the disassembly and the binary. with open(f"{spirv_file_path_base}.h", "w") as out_file: @@ -1139,7 +1154,7 @@ class BuildShadersCommand(Command): c = spirv_file.read(4) while len(c) != 0: if len(c) != 4: - print("ERROR: a SPIR-V shader is misaligned") + print_error("a SPIR-V shader is misaligned") return 1 if index % 6 == 0: out_file.write("\n ") @@ -1200,7 +1215,7 @@ class TestCommand(BaseBuildCommand): for test_target in test_targets] for i in range(0, len(test_targets)): if test_executables[i] is None: - print(f"ERROR: Unable to find {test_targets[i]} - build it.") + print_error(f"Unable to find {test_targets[i]} - build it.") return 1 # Run tests. @@ -1212,13 +1227,13 @@ class TestCommand(BaseBuildCommand): if result: any_failed = True if args["continue"]: - print("ERROR: test failed but continuing due to --continue.") + print_error("test failed but continuing due to --continue.") else: - print("ERROR: test failed, aborting, use --continue to keep going.") + print_error("test failed, aborting, use --continue to keep going.") return result if any_failed: - print("ERROR: one or more tests failed.") + print_error("one or more tests failed.") result = 1 return result @@ -1336,7 +1351,7 @@ class GenTestsCommand(Command): if any_errors: - print("ERROR: failed to build one or more tests.") + print_error("failed to build one or more tests.") return 1 return 0 @@ -1387,7 +1402,7 @@ class GpuTestCommand(BaseBuildCommand): for test_target in test_targets] for i in range(0, len(test_targets)): if test_executables[i] is None: - print(f"ERROR: Unable to find {test_targets[i]} - build it.") + print_error(f"Unable to find {test_targets[i]} - build it.") return 1 output_path = os.path.join(self_path, "build", "gputest") @@ -1416,7 +1431,7 @@ class GpuTestCommand(BaseBuildCommand): any_failed = True if any_failed: - print("ERROR: one or more tests failed.") + print_error("one or more tests failed.") result = 1 print(f"Check {output_path}/results.html for more details.") return result @@ -1441,7 +1456,7 @@ class CleanCommand(Command): "- premake clean...") run_premake(get_premake_target_os(args["target_os"]), "clean") - print("\nSuccess!") + print_status(ResultStatus.SUCCESS) return 0 @@ -1476,7 +1491,7 @@ class NukeCommand(Command): print("\n- running premake...") run_platform_premake(target_os_override=args["target_os"]) - print("\nSuccess!") + print_status(ResultStatus.SUCCESS) return 0 @@ -1586,7 +1601,7 @@ class LintCommand(Command): "--style=file", "--diff", ]) - print("ERROR: 1+ diffs. Stage changes and run 'xb format' to fix.") + print_error("1+ diffs. Stage changes and run 'xb format' to fix.") return 1 else: print("Linting completed successfully.") @@ -1791,7 +1806,7 @@ class StubCommand(Command): print(f"Created file '{file_name}' at {target_dir}") else: - print("ERROR: Please specify a file/class to generate") + print_error("Please specify a file/class to generate") return 1 run_platform_premake(target_os_override=args["target_os"]) @@ -1813,7 +1828,7 @@ class DevenvCommand(Command): show_reload_prompt = False if sys.platform == "win32": if not vs_version: - print("ERROR: Visual Studio is not installed."); + print_error("Visual Studio is not installed."); return 1 print("Launching Visual Studio...") elif sys.platform == "darwin": From 38ccc71afa7885af95cc74c600e618e2890877d4 Mon Sep 17 00:00:00 2001 From: The-Little-Wolf <116989599+The-Little-Wolf@users.noreply.github.com> Date: Fri, 8 Aug 2025 09:29:36 -0700 Subject: [PATCH 6/6] [XboxKrnl/Threading] - implement KeInitializeTimerEx - Taken from Crispy's Nukernel build --- .../kernel/xboxkrnl/xboxkrnl_threading.cc | 21 +++++++++++++++++++ src/xenia/kernel/xobject.h | 1 + 2 files changed, 22 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc index 62ca75e0b..e8740e201 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_threading.cc @@ -1802,6 +1802,27 @@ dword_result_t KeSetPriorityThread_entry(pointer_t thread_ptr, } DECLARE_XBOXKRNL_EXPORT1(KeSetPriorityThread, kThreading, kImplemented); +void xeKeInitializeTimerEx(X_KTIMER* timer, uint32_t type, uint32_t proctype, + PPCContext* context) { + xenia_assert(proctype < 3); + xenia_assert(type == 0 || type == 1); + // other fields are unmodified, they must carry through multiple calls of + // initialize + timer->header.process_type = proctype; + timer->header.inserted = 0; + timer->header.type = type + 8; + timer->header.signal_state = 0; + util::XeInitializeListHead(&timer->header.wait_list, context); + timer->due_time = 0; + timer->period = 0; +} + +void KeInitializeTimerEx_entry(pointer_t timer, dword_t type, + dword_t proctype, const ppc_context_t& context) { + xeKeInitializeTimerEx(timer, type, proctype & 0xFF, context); +} +DECLARE_XBOXKRNL_EXPORT1(KeInitializeTimerEx, kThreading, kImplemented); + } // namespace xboxkrnl } // namespace kernel } // namespace xe diff --git a/src/xenia/kernel/xobject.h b/src/xenia/kernel/xobject.h index be6fe036d..77fbf0870 100644 --- a/src/xenia/kernel/xobject.h +++ b/src/xenia/kernel/xobject.h @@ -48,6 +48,7 @@ typedef struct { union { uint8_t size; uint8_t hand; + uint8_t process_type; }; union { uint8_t inserted;