Merge remote-tracking branch 'GliniakRepo/experimentals' into canary_experimental
This commit is contained in:
commit
6c6c5ac14b
|
@ -34,6 +34,10 @@
|
||||||
// and let the normal AudioSystem handling take it, to prevent duplicate
|
// and let the normal AudioSystem handling take it, to prevent duplicate
|
||||||
// implementations. They can be found in xboxkrnl_audio_xma.cc
|
// 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 xe {
|
||||||
namespace apu {
|
namespace apu {
|
||||||
|
|
||||||
|
@ -45,8 +49,7 @@ AudioSystem::AudioSystem(cpu::Processor* processor)
|
||||||
|
|
||||||
for (size_t i = 0; i < kMaximumClientCount; ++i) {
|
for (size_t i = 0; i < kMaximumClientCount; ++i) {
|
||||||
client_semaphores_[i] =
|
client_semaphores_[i] =
|
||||||
xe::threading::Semaphore::Create(0, kMaximumQueuedFrames);
|
xe::threading::Semaphore::Create(0, cvars::max_queued_frames);
|
||||||
assert_not_null(client_semaphores_[i]);
|
|
||||||
wait_handles_[i] = client_semaphores_[i].get();
|
wait_handles_[i] = client_semaphores_[i].get();
|
||||||
}
|
}
|
||||||
shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
shutdown_event_ = xe::threading::Event::CreateAutoResetEvent(false);
|
||||||
|
@ -176,7 +179,7 @@ X_STATUS AudioSystem::RegisterClient(uint32_t callback, uint32_t callback_arg,
|
||||||
assert_true(index >= 0);
|
assert_true(index >= 0);
|
||||||
|
|
||||||
auto client_semaphore = client_semaphores_[index].get();
|
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);
|
assert_true(ret);
|
||||||
|
|
||||||
AudioDriver* driver;
|
AudioDriver* driver;
|
||||||
|
@ -279,7 +282,7 @@ bool AudioSystem::Restore(ByteStream* stream) {
|
||||||
client.in_use = true;
|
client.in_use = true;
|
||||||
|
|
||||||
auto client_semaphore = client_semaphores_[id].get();
|
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);
|
assert_true(ret);
|
||||||
|
|
||||||
AudioDriver* driver = nullptr;
|
AudioDriver* driver = nullptr;
|
||||||
|
|
|
@ -348,6 +348,9 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) {
|
||||||
data->input_buffer_read_offset, data->current_buffer,
|
data->input_buffer_read_offset, data->current_buffer,
|
||||||
current_input_buffer);
|
current_input_buffer);
|
||||||
|
|
||||||
|
if (!current_input_buffer) {
|
||||||
|
return;
|
||||||
|
}
|
||||||
size_t input_buffer_0_size =
|
size_t input_buffer_0_size =
|
||||||
data->input_buffer_0_packet_count * kBytesPerPacket;
|
data->input_buffer_0_packet_count * kBytesPerPacket;
|
||||||
size_t input_buffer_1_size =
|
size_t input_buffer_1_size =
|
||||||
|
@ -602,6 +605,9 @@ void XmaContext::Decode(XMA_CONTEXT_DATA* data) {
|
||||||
*/
|
*/
|
||||||
if (ret < 0) {
|
if (ret < 0) {
|
||||||
XELOGE("XmaContext {}: Error during decoding", id());
|
XELOGE("XmaContext {}: Error during decoding", id());
|
||||||
|
data->input_buffer_0_valid = 0;
|
||||||
|
data->input_buffer_1_valid = 0;
|
||||||
|
|
||||||
assert_always();
|
assert_always();
|
||||||
return; // TODO bail out
|
return; // TODO bail out
|
||||||
}
|
}
|
||||||
|
|
|
@ -347,6 +347,8 @@ void XmaDecoder::WriteRegister(uint32_t addr, uint32_t value) {
|
||||||
// 0601h (1804h) is written to with 0x02000000 and 0x03000000 around a lock
|
// 0601h (1804h) is written to with 0x02000000 and 0x03000000 around a lock
|
||||||
// operation
|
// operation
|
||||||
switch (r) {
|
switch (r) {
|
||||||
|
case 0x601:
|
||||||
|
break;
|
||||||
default: {
|
default: {
|
||||||
const auto register_info = register_file_.GetRegisterInfo(r);
|
const auto register_info = register_file_.GetRegisterInfo(r);
|
||||||
if (register_info) {
|
if (register_info) {
|
||||||
|
|
|
@ -309,6 +309,9 @@ void CommandProcessor::InitializeRingBuffer(uint32_t ptr, uint32_t size_log2) {
|
||||||
read_ptr_index_ = 0;
|
read_ptr_index_ = 0;
|
||||||
primary_buffer_ptr_ = ptr;
|
primary_buffer_ptr_ = ptr;
|
||||||
primary_buffer_size_ = uint32_t(1) << (size_log2 + 3);
|
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,
|
void CommandProcessor::EnableReadPointerWriteBack(uint32_t ptr,
|
||||||
|
@ -567,7 +570,7 @@ void CommandProcessor::ExecuteIndirectBuffer(uint32_t ptr, uint32_t count) {
|
||||||
// Return up a level if we encounter a bad packet.
|
// Return up a level if we encounter a bad packet.
|
||||||
XELOGE("**** INDIRECT RINGBUFFER: Failed to execute packet.");
|
XELOGE("**** INDIRECT RINGBUFFER: Failed to execute packet.");
|
||||||
assert_always();
|
assert_always();
|
||||||
break;
|
//break;
|
||||||
}
|
}
|
||||||
} while (reader.read_count());
|
} while (reader.read_count());
|
||||||
|
|
||||||
|
@ -590,7 +593,7 @@ void CommandProcessor::ExecutePacket(uint32_t ptr, uint32_t count) {
|
||||||
bool CommandProcessor::ExecutePacket(RingBuffer* reader) {
|
bool CommandProcessor::ExecutePacket(RingBuffer* reader) {
|
||||||
const uint32_t packet = reader->ReadAndSwap<uint32_t>();
|
const uint32_t packet = reader->ReadAndSwap<uint32_t>();
|
||||||
const uint32_t packet_type = packet >> 30;
|
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_.WritePacketStart(uint32_t(reader->read_ptr() - 4), 1);
|
||||||
trace_writer_.WritePacketEnd();
|
trace_writer_.WritePacketEnd();
|
||||||
return true;
|
return true;
|
||||||
|
|
|
@ -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,
|
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 {
|
uint32_t& extended_error, uint32_t& length) -> X_RESULT {
|
||||||
X_RESULT result = X_ERROR_INVALID_PARAMETER;
|
X_RESULT result = X_ERROR_INVALID_PARAMETER;
|
||||||
bool create = false;
|
bool create = false;
|
||||||
|
@ -217,6 +217,11 @@ dword_result_t xeXamContentCreate(dword_t user_index, lpstring_t root_name,
|
||||||
|
|
||||||
extended_error = X_HRESULT_FROM_WIN32(result);
|
extended_error = X_HRESULT_FROM_WIN32(result);
|
||||||
length = disposition;
|
length = disposition;
|
||||||
|
|
||||||
|
if (result && overlapped_ptr) {
|
||||||
|
result = X_ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
|
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -37,7 +37,7 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr,
|
||||||
return X_ERROR_INVALID_HANDLE;
|
return X_ERROR_INVALID_HANDLE;
|
||||||
}
|
}
|
||||||
|
|
||||||
auto run = [e, buffer_ptr](uint32_t& extended_error,
|
auto run = [e, buffer_ptr, overlapped_ptr](uint32_t& extended_error,
|
||||||
uint32_t& length) -> X_RESULT {
|
uint32_t& length) -> X_RESULT {
|
||||||
X_RESULT result;
|
X_RESULT result;
|
||||||
uint32_t item_count = 0;
|
uint32_t item_count = 0;
|
||||||
|
@ -49,6 +49,9 @@ uint32_t xeXamEnumerate(uint32_t handle, uint32_t flags, lpvoid_t buffer_ptr,
|
||||||
}
|
}
|
||||||
extended_error = X_HRESULT_FROM_WIN32(result);
|
extended_error = X_HRESULT_FROM_WIN32(result);
|
||||||
length = item_count;
|
length = item_count;
|
||||||
|
if (result && overlapped_ptr) {
|
||||||
|
result = X_ERROR_FUNCTION_FAILED;
|
||||||
|
}
|
||||||
return result;
|
return result;
|
||||||
};
|
};
|
||||||
|
|
||||||
|
|
|
@ -26,6 +26,7 @@
|
||||||
#include "third_party/fmt/include/fmt/format.h"
|
#include "third_party/fmt/include/fmt/format.h"
|
||||||
|
|
||||||
DEFINE_int32(avpack, 8, "Video modes", "Video");
|
DEFINE_int32(avpack, 8, "Video modes", "Video");
|
||||||
|
DECLARE_int32(user_language);
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
@ -210,16 +211,16 @@ dword_result_t XGetGameRegion_entry() { return xeXGetGameRegion(); }
|
||||||
DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub);
|
DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub);
|
||||||
|
|
||||||
dword_result_t XGetLanguage_entry() {
|
dword_result_t XGetLanguage_entry() {
|
||||||
auto desired_language = XLanguage::kEnglish;
|
auto desired_language = static_cast<XLanguage>(cvars::user_language);
|
||||||
|
|
||||||
// Switch the language based on game region.
|
// Switch the language based on game region.
|
||||||
// TODO(benvanik): pull from xex header.
|
// 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) {
|
if (game_region & XEX_REGION_NTSCU) {
|
||||||
desired_language = XLanguage::kEnglish;
|
desired_language = XLanguage::kEnglish;
|
||||||
} else if (game_region & XEX_REGION_NTSCJ) {
|
} else if (game_region & XEX_REGION_NTSCJ) {
|
||||||
desired_language = XLanguage::kJapanese;
|
desired_language = XLanguage::kJapanese;
|
||||||
}
|
}*/
|
||||||
// Add more overrides?
|
// Add more overrides?
|
||||||
|
|
||||||
return uint32_t(desired_language);
|
return uint32_t(desired_language);
|
||||||
|
|
|
@ -278,13 +278,17 @@ uint32_t XamUserReadProfileSettingsEx(uint32_t title_id, uint32_t user_index,
|
||||||
if (xuids) {
|
if (xuids) {
|
||||||
out_setting->xuid = user_profile->xuid();
|
out_setting->xuid = user_profile->xuid();
|
||||||
} else {
|
} else {
|
||||||
|
out_setting->xuid = -1;
|
||||||
out_setting->user_index = static_cast<uint32_t>(user_index);
|
out_setting->user_index = static_cast<uint32_t>(user_index);
|
||||||
}
|
}
|
||||||
out_setting->setting_id = setting_id;
|
out_setting->setting_id = setting_id;
|
||||||
|
|
||||||
if (setting && setting->is_set) {
|
if (setting) {
|
||||||
|
out_setting->data.type = uint8_t(setting->type);
|
||||||
|
if (setting->is_set) {
|
||||||
setting->Append(&out_setting->data, &out_stream);
|
setting->Append(&out_setting->data, &out_stream);
|
||||||
}
|
}
|
||||||
|
}
|
||||||
++out_setting;
|
++out_setting;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -45,11 +45,16 @@ MAKE_DUMMY_STUB_STATUS(DmGetXboxName);
|
||||||
dword_result_t DmIsDebuggerPresent_entry() { return 0; }
|
dword_result_t DmIsDebuggerPresent_entry() { return 0; }
|
||||||
DECLARE_XBDM_EXPORT1(DmIsDebuggerPresent, kDebug, kStub);
|
DECLARE_XBDM_EXPORT1(DmIsDebuggerPresent, kDebug, kStub);
|
||||||
|
|
||||||
MAKE_DUMMY_STUB_STATUS(DmRegisterCommandProcessor);
|
|
||||||
|
|
||||||
void DmSendNotificationString_entry(lpdword_t unk0_ptr) {}
|
void DmSendNotificationString_entry(lpdword_t unk0_ptr) {}
|
||||||
DECLARE_XBDM_EXPORT1(DmSendNotificationString, kDebug, kStub);
|
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,
|
dword_result_t DmRegisterCommandProcessorEx_entry(lpdword_t name_ptr,
|
||||||
lpdword_t handler_fn,
|
lpdword_t handler_fn,
|
||||||
dword_t unk3) {
|
dword_t unk3) {
|
||||||
|
|
|
@ -385,6 +385,9 @@ dword_result_t XMABlockWhileInUse_entry(lpvoid_t context_ptr) {
|
||||||
if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) {
|
if (!context.input_buffer_0_valid && !context.input_buffer_1_valid) {
|
||||||
break;
|
break;
|
||||||
}
|
}
|
||||||
|
if (!context.work_buffer_ptr) {
|
||||||
|
break;
|
||||||
|
}
|
||||||
xe::threading::Sleep(std::chrono::milliseconds(1));
|
xe::threading::Sleep(std::chrono::milliseconds(1));
|
||||||
} while (true);
|
} while (true);
|
||||||
return 0;
|
return 0;
|
||||||
|
|
|
@ -372,6 +372,12 @@ dword_result_t MmAllocatePhysicalMemoryEx_entry(
|
||||||
// min_addr_range/max_addr_range are bounds in physical memory, not virtual.
|
// min_addr_range/max_addr_range are bounds in physical memory, not virtual.
|
||||||
uint32_t heap_base = heap->heap_base();
|
uint32_t heap_base = heap->heap_base();
|
||||||
uint32_t heap_physical_address_offset = heap->GetPhysicalAddress(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 =
|
uint32_t heap_min_addr =
|
||||||
xe::sat_sub(min_addr_range.value(), heap_physical_address_offset);
|
xe::sat_sub(min_addr_range.value(), heap_physical_address_offset);
|
||||||
uint32_t heap_max_addr =
|
uint32_t heap_max_addr =
|
||||||
|
|
|
@ -824,7 +824,9 @@ bool BaseHeap::Alloc(uint32_t size, uint32_t alignment,
|
||||||
size = xe::round_up(size, page_size_);
|
size = xe::round_up(size, page_size_);
|
||||||
alignment = xe::round_up(alignment, page_size_);
|
alignment = xe::round_up(alignment, page_size_);
|
||||||
uint32_t low_address = heap_base_;
|
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,
|
return AllocRange(low_address, high_address, size, alignment, allocation_type,
|
||||||
protect, top_down, out_address);
|
protect, top_down, out_address);
|
||||||
}
|
}
|
||||||
|
@ -1252,7 +1254,8 @@ bool BaseHeap::QueryRegionInfo(uint32_t base_address,
|
||||||
out_info->protect = 0;
|
out_info->protect = 0;
|
||||||
if (start_page_entry.state) {
|
if (start_page_entry.state) {
|
||||||
// Committed/reserved region.
|
// 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_protect = start_page_entry.allocation_protect;
|
||||||
out_info->allocation_size = start_page_entry.region_page_count * page_size_;
|
out_info->allocation_size = start_page_entry.region_page_count * page_size_;
|
||||||
out_info->state = start_page_entry.state;
|
out_info->state = start_page_entry.state;
|
||||||
|
|
Loading…
Reference in New Issue