From f43e400c9149967f8af308f2872caa6adde249e5 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sun, 10 Oct 2021 23:12:57 +0200 Subject: [PATCH 01/16] Do not block XMA when there is no work buffer available --- src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc index 66e988ea0..b0ea18c50 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_audio_xma.cc @@ -385,6 +385,9 @@ dword_result_t XMABlockWhileInUse_entry(lpvoid_t context_ptr) { if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) { break; } + if (!context.work_buffer_ptr) { + break; + } xe::threading::Sleep(std::chrono::milliseconds(1)); } while (true); return 0; From 0eaf032b7190f28d901fee84c34fe5a1f8d6a2e0 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Sat, 30 Oct 2021 11:38:16 +0200 Subject: [PATCH 02/16] Remove applying offset when min & max address range is provided --- src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc | 6 ++++++ 1 file changed, 6 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc index 7d72b3215..55f56dded 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_memory.cc @@ -372,6 +372,12 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry( // min_addr_range/max_addr_range are bounds in physical memory, not virtual. uint32_t heap_base = heap->heap_base(); uint32_t heap_physical_address_offset = heap->GetPhysicalAddress(heap_base); + // TODO(Gliniak): Games like 545108B4 compares min_addr_range with value returned. + // 0x1000 offset causes it to go below that minimal range and goes haywire + if (min_addr_range && max_addr_range) { + heap_physical_address_offset = 0; + } + uint32_t heap_min_addr = xe::sat_sub(min_addr_range.value(), heap_physical_address_offset); uint32_t heap_max_addr = From c80ea14d9d309d88b65e41788ef1ee149f964784 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Wed, 18 Aug 2021 18:31:47 +0200 Subject: [PATCH 03/16] Check if input_buffer exist In some really specific cases there is a chance that one of the buffers is valid, but its pointer is null --- src/xenia/apu/xma_context.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc index e9047654a..8fc17d880 100644 --- a/src/xenia/apu/xma_context.cc +++ b/src/xenia/apu/xma_context.cc @@ -346,6 +346,9 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { data->input_buffer_read_offset, data->current_buffer, current_input_buffer); + if (!current_input_buffer) { + return; + } size_t input_buffer_0_size = data->input_buffer_0_packet_count * kBytesPerPacket; size_t input_buffer_1_size = From 8e35a3d6495b49d85b0a5609bf201881ba0cb43f Mon Sep 17 00:00:00 2001 From: Gliniak Date: Tue, 3 Aug 2021 12:13:42 +0200 Subject: [PATCH 04/16] Invalidate input buffers if decoding fails Should output be invalidated too? --- src/xenia/apu/xma_context.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xenia/apu/xma_context.cc b/src/xenia/apu/xma_context.cc index 8fc17d880..f0337a5e4 100644 --- a/src/xenia/apu/xma_context.cc +++ b/src/xenia/apu/xma_context.cc @@ -603,6 +603,9 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) { */ if (ret < 0) { XELOGE("XmaContext {}: Error during decoding", id()); + data->input_buffer_0_valid = 0; + data->input_buffer_1_valid = 0; + assert_always(); return; // TODO bail out } From c483da91a48f63acc0074c4a682de51747508439 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Thu, 6 Jan 2022 21:35:43 +0100 Subject: [PATCH 05/16] Stop unnecessary spam of 0x601 opcode usage --- src/xenia/apu/xma_decoder.cc | 2 ++ 1 file changed, 2 insertions(+) diff --git a/src/xenia/apu/xma_decoder.cc b/src/xenia/apu/xma_decoder.cc index cd04ebd91..a8dd319a6 100644 --- a/src/xenia/apu/xma_decoder.cc +++ b/src/xenia/apu/xma_decoder.cc @@ -346,6 +346,8 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) { // 0601h (1804h) is written to with 0x02000000 and 0x03000000 around a lock // operation switch (r) { + case 0x601: + break; default: { const auto register_info = register_file_.GetRegisterInfo(r); if (register_info) { From ec976cdd339a387fdd924a3b1f0fe5c5fd909c28 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Mon, 17 Jan 2022 19:38:42 +0100 Subject: [PATCH 06/16] InitializeRingBuffer - Clear buffer space to prevent random data readout --- src/xenia/gpu/command_processor.cc | 3 +++ 1 file changed, 3 insertions(+) diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index 7a4ac4e23..bd2bf4de3 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -265,6 +265,9 @@ void CommandProcessor::InitializeRingBuffer(uint32_t ptr, uint32_t size_log2) { read_ptr_index_ = 0; primary_buffer_ptr_ = ptr; primary_buffer_size_ = uint32_t(1) << (size_log2 + 3); + + std::memset(kernel_state_->memory()->TranslatePhysical(primary_buffer_ptr_), + 0, primary_buffer_size_); } void CommandProcessor::EnableReadPointerWriteBack(uint32_t ptr, From c4d64a0501c0f3805ced2883378f3b8ebf1c8e3b Mon Sep 17 00:00:00 2001 From: Gliniak Date: Thu, 30 Dec 2021 18:17:48 +0100 Subject: [PATCH 07/16] QueryRegionInfo: Adjust allocation_base to contain heap address --- src/xenia/memory.cc | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index c7494e9fa..1e342dfc9 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -1254,7 +1254,8 @@ bool BaseHeap::QueryRegionInfo(uint32_t base_address, out_info->protect = 0; if (start_page_entry.state) { // Committed/reserved region. - out_info->allocation_base = start_page_entry.base_address * page_size_; + out_info->allocation_base = + heap_base_ + start_page_entry.base_address * page_size_; out_info->allocation_protect = start_page_entry.allocation_protect; out_info->allocation_size = start_page_entry.region_page_count * page_size_; out_info->state = start_page_entry.state; From c20c7c930c6eff52d7f8067d30197763156b1435 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Wed, 3 Nov 2021 22:43:47 +0100 Subject: [PATCH 08/16] XamEnumerate: Return X_ERROR_FUNCTION_FAILED for overlapped failures --- src/xenia/kernel/xam/xam_enum.cc | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) diff --git a/src/xenia/kernel/xam/xam_enum.cc b/src/xenia/kernel/xam/xam_enum.cc index 9f5c08bb4..3ad069686 100644 --- a/src/xenia/kernel/xam/xam_enum.cc +++ b/src/xenia/kernel/xam/xam_enum.cc @@ -37,8 +37,8 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr, return X_ERROR_INVALID_HANDLE; } - auto run = [e, buffer_ptr](uint32_t& extended_error, - uint32_t& length) -> X_RESULT { + auto run = [e, buffer_ptr, overlapped_ptr](uint32_t& extended_error, + uint32_t& length) -> X_RESULT { X_RESULT result; uint32_t item_count = 0; if (!buffer_ptr) { @@ -49,6 +49,9 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr, } extended_error = X_HRESULT_FROM_WIN32(result); length = item_count; + if (result && overlapped_ptr) { + result = X_ERROR_FUNCTION_FAILED; + } return result; }; From 498dde6e1ad44383dc5155110bdbc6945335e82a Mon Sep 17 00:00:00 2001 From: Gliniak Date: Tue, 3 Aug 2021 12:14:48 +0200 Subject: [PATCH 09/16] Limit unspecified virtual allocation only to 3/4 of heap --- src/xenia/memory.cc | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/xenia/memory.cc b/src/xenia/memory.cc index 1e342dfc9..2b48091d3 100644 --- a/src/xenia/memory.cc +++ b/src/xenia/memory.cc @@ -831,7 +831,9 @@ bool BaseHeap::Alloc(uint32_t size, uint32_t alignment, size = xe::round_up(size, page_size_); alignment = xe::round_up(alignment, page_size_); uint32_t low_address = heap_base_; - uint32_t high_address = heap_base_ + (heap_size_ - 1); + uint32_t high_address = + heap_base_ + (heap_size_ - 1) - + (heap_type_ == HeapType::kGuestVirtual ? 0x10000000 : 0); return AllocRange(low_address, high_address, size, alignment, allocation_type, protect, top_down, out_address); } From 07a1e77218db3aef95b3ce59ccb57880205dcbbf Mon Sep 17 00:00:00 2001 From: Gliniak Date: Tue, 7 Dec 2021 23:14:40 +0100 Subject: [PATCH 10/16] Allow users to change max amount of queued frames --- src/xenia/apu/audio_system.cc | 10 +++++++--- 1 file changed, 7 insertions(+), 3 deletions(-) diff --git a/src/xenia/apu/audio_system.cc b/src/xenia/apu/audio_system.cc index c137a4853..2e4011edb 100644 --- a/src/xenia/apu/audio_system.cc +++ b/src/xenia/apu/audio_system.cc @@ -33,6 +33,10 @@ // and let the normal AudioSystem handling take it, to prevent duplicate // implementations. They can be found in xboxkrnl_audio_xma.cc +DEFINE_uint32( + max_queued_frames, 64, + "Allows changing max buffered audio frames to reduce audio delay.", "APU"); + namespace xe { namespace apu { @@ -44,7 +48,7 @@ AudioSystem::AudioSystem(cpu::Processor* processor) for (size_t i = 0; i < kMaximumClientCount; ++i) { client_semaphores_[i] = - xe::threading::Semaphore::Create(0, kMaximumQueuedFrames); + xe::threading::Semaphore::Create(0, cvars::max_queued_frames); wait_handles_[i] = client_semaphores_[i].get(); } shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false); @@ -172,7 +176,7 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg, assert_true(index >= 0); auto client_semaphore = client_semaphores_[index].get(); - auto ret = client_semaphore->Release(kMaximumQueuedFrames, nullptr); + auto ret = client_semaphore->Release(cvars::max_queued_frames, nullptr); assert_true(ret); AudioDriver* driver; @@ -275,7 +279,7 @@ bool AudioSystem::Restore(ByteStream* stream) { client.in_use = true; auto client_semaphore = client_semaphores_[id].get(); - auto ret = client_semaphore->Release(kMaximumQueuedFrames, nullptr); + auto ret = client_semaphore->Release(cvars::max_queued_frames, nullptr); assert_true(ret); AudioDriver* driver = nullptr; From dfb4cadcfef13537e1ac2703846e45db28ba14df Mon Sep 17 00:00:00 2001 From: Gliniak Date: Thu, 12 Aug 2021 08:02:48 +0200 Subject: [PATCH 11/16] Return success from DmRegisterCommandProcessor to prevent debug games from crashing --- src/xenia/kernel/xbdm/xbdm_misc.cc | 13 +++++++++---- 1 file changed, 9 insertions(+), 4 deletions(-) diff --git a/src/xenia/kernel/xbdm/xbdm_misc.cc b/src/xenia/kernel/xbdm/xbdm_misc.cc index 7f2b9f960..d66ff3c5b 100644 --- a/src/xenia/kernel/xbdm/xbdm_misc.cc +++ b/src/xenia/kernel/xbdm/xbdm_misc.cc @@ -45,14 +45,19 @@ MAKE_DUMMY_STUB_STATUS(DmGetXboxName); dword_result_t DmIsDebuggerPresent_entry() { return 0; } DECLARE_XBDM_EXPORT1(DmIsDebuggerPresent, kDebug, kStub); -MAKE_DUMMY_STUB_STATUS(DmRegisterCommandProcessor); - void DmSendNotificationString_entry(lpdword_t unk0_ptr) {} DECLARE_XBDM_EXPORT1(DmSendNotificationString, kDebug, kStub); +dword_result_t DmRegisterCommandProcessor_entry(lpdword_t name_ptr, + lpdword_t handler_fn) { + // Return success to prevent some games from crashing + return X_STATUS_SUCCESS; +} +DECLARE_XBDM_EXPORT1(DmRegisterCommandProcessor, kDebug, kStub); + dword_result_t DmRegisterCommandProcessorEx_entry(lpdword_t name_ptr, - lpdword_t handler_fn, - dword_t unk3) { + lpdword_t handler_fn, + dword_t unk3) { // Return success to prevent some games from stalling return X_STATUS_SUCCESS; } From 3a772e60b0fe37c3ba3581f03fa34675bea50345 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Thu, 11 Nov 2021 10:11:01 +0100 Subject: [PATCH 12/16] XamContentCreate: Return X_ERROR_FUNCTION_FAILED for overlapped failures --- src/xenia/kernel/xam/xam_content.cc | 7 ++++++- 1 file changed, 6 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index 11a9cf52b..016289207 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -140,7 +140,7 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name, } auto run = [content_manager, root_name = root_name.value(), flags, - content_data, disposition_ptr, license_mask_ptr]( + content_data, disposition_ptr, license_mask_ptr, overlapped_ptr]( uint32_t& extended_error, uint32_t& length) -> X_RESULT { X_RESULT result = X_ERROR_INVALID_PARAMETER; bool create = false; @@ -214,6 +214,11 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name, extended_error = X_HRESULT_FROM_WIN32(result); length = disposition; + + if (result && overlapped_ptr) { + result = X_ERROR_FUNCTION_FAILED; + } + return result; }; From 9ed3881b3b15c9d9a746f2485cfdbcbffb931853 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Tue, 18 Jan 2022 08:24:54 +0100 Subject: [PATCH 13/16] Skip indirect ringbuffer errors - Thermonuclear war achieved --- src/xenia/gpu/command_processor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index bd2bf4de3..cdbfc8797 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -453,7 +453,7 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t count) { // Return up a level if we encounter a bad packet. XELOGE("**** INDIRECT RINGBUFFER: Failed to execute packet."); assert_always(); - break; + //break; } } while (reader.read_count()); From 080a65cd4f89f3922041ccd08b57d4f52fecff32 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Mon, 31 Jan 2022 20:26:03 +0100 Subject: [PATCH 14/16] [XAM] XGetLanguage: Get user language based on config --- src/xenia/kernel/xam/xam_info.cc | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 0bfe7c97b..e040c5444 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -24,6 +24,8 @@ #include "third_party/fmt/include/fmt/format.h" +DECLARE_int32(user_language); + namespace xe { namespace kernel { namespace xam { @@ -206,16 +208,16 @@ dword_result_t XGetGameRegion_entry() { return xeXGetGameRegion(); } DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub); dword_result_t XGetLanguage_entry() { - auto desired_language = XLanguage::kEnglish; + auto desired_language = static_cast(cvars::user_language); // Switch the language based on game region. // TODO(benvanik): pull from xex header. - uint32_t game_region = XEX_REGION_NTSCU; + /* uint32_t game_region = XEX_REGION_NTSCU; if (game_region & XEX_REGION_NTSCU) { desired_language = XLanguage::kEnglish; } else if (game_region & XEX_REGION_NTSCJ) { desired_language = XLanguage::kJapanese; - } + }*/ // Add more overrides? return uint32_t(desired_language); From e8374d98fe9640105333ee3c4e98a79cbb7812cd Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Rados=C5=82aw=20Gli=C5=84ski?= Date: Tue, 22 Jun 2021 13:08:47 +0200 Subject: [PATCH 15/16] Skip 0xbadf00d gpu packets --- src/xenia/gpu/command_processor.cc | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/src/xenia/gpu/command_processor.cc b/src/xenia/gpu/command_processor.cc index cdbfc8797..fd6da15c6 100644 --- a/src/xenia/gpu/command_processor.cc +++ b/src/xenia/gpu/command_processor.cc @@ -476,7 +476,7 @@ void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) { bool CommandProcessor::ExecutePacket(RingBuffer* reader) { const uint32_t packet = reader->ReadAndSwap(); const uint32_t packet_type = packet >> 30; - if (packet == 0) { + if (packet == 0 || packet == 0x0BADF00D) { trace_writer_.WritePacketStart(uint32_t(reader->read_ptr() - 4), 1); trace_writer_.WritePacketEnd(); return true; From e9b9302cd3eee46c91c0603855a635daf5578086 Mon Sep 17 00:00:00 2001 From: Gliniak Date: Mon, 31 Jan 2022 21:39:56 +0100 Subject: [PATCH 16/16] [XAM] Small XamUserReadProfileSettings improvements --- src/xenia/kernel/xam/xam_user.cc | 8 ++++++-- 1 file changed, 6 insertions(+), 2 deletions(-) diff --git a/src/xenia/kernel/xam/xam_user.cc b/src/xenia/kernel/xam/xam_user.cc index 2155504e8..0d2486535 100644 --- a/src/xenia/kernel/xam/xam_user.cc +++ b/src/xenia/kernel/xam/xam_user.cc @@ -278,12 +278,16 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index, if (xuids) { out_setting->xuid = user_profile->xuid(); } else { + out_setting->xuid = -1; out_setting->user_index = static_cast(user_index); } out_setting->setting_id = setting_id; - if (setting && setting->is_set) { - setting->Append(&out_setting->data, &out_stream); + if (setting) { + out_setting->data.type = uint8_t(setting->type); + if (setting->is_set) { + setting->Append(&out_setting->data, &out_stream); + } } ++out_setting; }