Merge pull request #61 from chrisps/canary_experimental

performance improvements, kernel fixes, cpu accuracy improvements
This commit is contained in:
Radosław Gliński
2022-08-21 09:31:09 +02:00
committed by GitHub
70 changed files with 1744 additions and 541 deletions

View File

@@ -948,7 +948,11 @@ bool KernelState::Restore(ByteStream* stream) {
}
uint8_t KernelState::GetConnectedUsers() const {
return emulator_->input_system()->GetConnectedSlots();
auto input_sys = emulator_->input_system();
auto lock = input_sys->lock();
return input_sys->GetConnectedSlots();
}
void KernelState::UpdateUsedUserProfiles() {

View File

@@ -58,6 +58,7 @@ dword_result_t XamInputGetCapabilities_entry(
}
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
return input_system->GetCapabilities(actual_user_index, flags, caps);
}
DECLARE_XAM_EXPORT1(XamInputGetCapabilities, kInput, kSketchy);
@@ -81,6 +82,7 @@ dword_result_t XamInputGetCapabilitiesEx_entry(
}
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
return input_system->GetCapabilities(actual_user_index, flags, caps);
}
DECLARE_XAM_EXPORT1(XamInputGetCapabilitiesEx, kInput, kSketchy);
@@ -88,6 +90,13 @@ DECLARE_XAM_EXPORT1(XamInputGetCapabilitiesEx, kInput, kSketchy);
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputgetstate(v=vs.85).aspx
dword_result_t XamInputGetState_entry(dword_t user_index, dword_t flags,
pointer_t<X_INPUT_STATE> input_state) {
if (input_state) {
memset((void*)input_state.host_address(), 0, sizeof X_INPUT_STATE);
}
if (user_index >= 4) {
return X_ERROR_DEVICE_NOT_CONNECTED;
}
// Games call this with a NULL state ptr, probably as a query.
if ((flags & 0xFF) && (flags & XINPUT_FLAG_GAMEPAD) == 0) {
@@ -96,12 +105,14 @@ dword_result_t XamInputGetState_entry(dword_t user_index, dword_t flags,
}
uint32_t actual_user_index = user_index;
// chrispy: change this, logic is not right
if ((actual_user_index & 0xFF) == 0xFF || (flags & XINPUT_FLAG_ANY_USER)) {
// Always pin user to 0.
actual_user_index = 0;
}
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
return input_system->GetState(user_index, input_state);
}
DECLARE_XAM_EXPORT2(XamInputGetState, kInput, kImplemented, kHighFrequency);
@@ -109,6 +120,9 @@ DECLARE_XAM_EXPORT2(XamInputGetState, kInput, kImplemented, kHighFrequency);
// https://msdn.microsoft.com/en-us/library/windows/desktop/microsoft.directx_sdk.reference.xinputsetstate(v=vs.85).aspx
dword_result_t XamInputSetState_entry(dword_t user_index, dword_t unk,
pointer_t<X_INPUT_VIBRATION> vibration) {
if (user_index >= 4) {
return X_E_DEVICE_NOT_CONNECTED;
}
if (!vibration) {
return X_ERROR_BAD_ARGUMENTS;
}
@@ -120,6 +134,7 @@ dword_result_t XamInputSetState_entry(dword_t user_index, dword_t unk,
}
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
return input_system->SetState(user_index, vibration);
}
DECLARE_XAM_EXPORT1(XamInputSetState, kInput, kImplemented);
@@ -147,6 +162,7 @@ dword_result_t XamInputGetKeystroke_entry(
}
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
return input_system->GetKeystroke(user_index, flags, keystroke);
}
DECLARE_XAM_EXPORT1(XamInputGetKeystroke, kInput, kImplemented);
@@ -166,14 +182,15 @@ dword_result_t XamInputGetKeystrokeEx_entry(
uint32_t user_index = *user_index_ptr;
auto input_system = kernel_state()->emulator()->input_system();
auto lock = input_system->lock();
if ((user_index & 0xFF) == 0xFF) {
// Always pin user to 0.
user_index = 0;
}
if (flags & XINPUT_FLAG_ANY_USER) {
// That flag means we should iterate over every connected controller and check which one have pending request.
// That flag means we should iterate over every connected controller and
// check which one have pending request.
auto result = X_ERROR_DEVICE_NOT_CONNECTED;
for (uint32_t i = 0; i < 4; i++) {
auto result = input_system->GetKeystroke(i, flags, keystroke);
@@ -188,6 +205,7 @@ dword_result_t XamInputGetKeystrokeEx_entry(
}
auto result = input_system->GetKeystroke(user_index, flags, keystroke);
if (XSUCCEEDED(result)) {
*user_index_ptr = keystroke->user_index;
}
@@ -202,7 +220,8 @@ X_HRESULT_result_t XamUserGetDeviceContext_entry(dword_t user_index,
// If this function fails they assume zero, so let's fail AND
// set zero just to be safe.
*out_ptr = 0;
if (kernel_state()->IsUserSignedIn(user_index) || (user_index & 0xFF) == 0xFF) {
if (kernel_state()->IsUserSignedIn(user_index) ||
(user_index & 0xFF) == 0xFF) {
*out_ptr = (uint32_t)user_index;
return X_E_SUCCESS;
} else {

View File

@@ -121,7 +121,8 @@ dword_result_t NtAllocateVirtualMemory_entry(lpdword_t base_addr_ptr,
? -int32_t(region_size_ptr.value())
: region_size_ptr.value();
adjusted_size = xe::round_up(adjusted_size, adjusted_base ? page_size : 64 * 1024);
adjusted_size =
xe::round_up(adjusted_size, adjusted_base ? page_size : 64 * 1024);
// Allocate.
uint32_t allocation_type = 0;
@@ -295,10 +296,19 @@ struct X_MEMORY_BASIC_INFORMATION {
be<uint32_t> protect;
be<uint32_t> type;
};
// chrispy: added region_type ? guessed name, havent seen any except 0 used
dword_result_t NtQueryVirtualMemory_entry(
dword_t base_address,
pointer_t<X_MEMORY_BASIC_INFORMATION> memory_basic_information_ptr) {
pointer_t<X_MEMORY_BASIC_INFORMATION> memory_basic_information_ptr,
dword_t region_type) {
switch (region_type) {
case 0:
case 1:
case 2:
break;
default:
return X_STATUS_INVALID_PARAMETER;
}
auto heap = kernel_state()->memory()->LookupHeap(base_address);
HeapAllocationInfo alloc_info;
if (heap == nullptr || !heap->QueryRegionInfo(base_address, &alloc_info)) {
@@ -373,8 +383,9 @@ 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
// 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;
}

View File

@@ -53,21 +53,20 @@ DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemory, kMemory, kImplemented);
// https://msdn.microsoft.com/en-us/library/ff552123
dword_result_t RtlCompareMemoryUlong_entry(lpvoid_t source, dword_t length,
dword_t pattern) {
// Return 0 if source/length not aligned
if (source.guest_address() % 4 || length % 4) {
return 0;
}
uint32_t num_compared_bytes = 0;
uint32_t n = 0;
for (uint32_t i = 0; i < (length / 4); i++) {
// FIXME: This assumes as_array returns xe::be
uint32_t val = source.as_array<uint32_t>()[i];
if (val == pattern) {
n++;
uint32_t swapped_pattern = xe::byte_swap(pattern.value());
char* host_source = (char*)source.host_address();
for (uint32_t aligned_length = length & 0xFFFFFFFCU; aligned_length;
num_compared_bytes += 4) {
if (*(uint32_t*)(host_source + num_compared_bytes) != swapped_pattern) {
break;
}
aligned_length = aligned_length - 4;
}
return n;
return num_compared_bytes;
}
DECLARE_XBOXKRNL_EXPORT1(RtlCompareMemoryUlong, kMemory, kImplemented);
@@ -85,23 +84,61 @@ void RtlFillMemoryUlong_entry(lpvoid_t destination, dword_t length,
}
DECLARE_XBOXKRNL_EXPORT1(RtlFillMemoryUlong, kMemory, kImplemented);
dword_result_t RtlUpperChar_entry(dword_t in) {
char c = in & 0xFF;
if (c >= 'a' && c <= 'z') {
return c ^ 0x20;
}
static constexpr const unsigned char rtl_lower_table[256] = {
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB,
0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67,
0x68, 0x69, 0x6A, 0x6B, 0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73,
0x74, 0x75, 0x76, 0x77, 0x78, 0x79, 0x7A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x61, 0x62, 0x63, 0x64, 0x65, 0x66, 0x67, 0x68, 0x69, 0x6A, 0x6B,
0x6C, 0x6D, 0x6E, 0x6F, 0x70, 0x71, 0x72, 0x73, 0x74, 0x75, 0x76, 0x77,
0x78, 0x79, 0x7A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xE0, 0xE1, 0xE2, 0xE3, 0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB,
0xEC, 0xED, 0xEE, 0xEF, 0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xD7,
0xF8, 0xF9, 0xFA, 0xFB, 0xFC, 0xFD, 0xFE, 0xDF, 0xE0, 0xE1, 0xE2, 0xE3,
0xE4, 0xE5, 0xE6, 0xE7, 0xE8, 0xE9, 0xEA, 0xEB, 0xEC, 0xED, 0xEE, 0xEF,
0xF0, 0xF1, 0xF2, 0xF3, 0xF4, 0xF5, 0xF6, 0xF7, 0xF8, 0xF9, 0xFA, 0xFB,
0xFC, 0xFD, 0xFE, 0xFF};
return c;
static constexpr const unsigned char rtl_upper_table[256] = {
0x0, 0x1, 0x2, 0x3, 0x4, 0x5, 0x6, 0x7, 0x8, 0x9, 0xA, 0xB,
0xC, 0xD, 0xE, 0xF, 0x10, 0x11, 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
0x18, 0x19, 0x1A, 0x1B, 0x1C, 0x1D, 0x1E, 0x1F, 0x20, 0x21, 0x22, 0x23,
0x24, 0x25, 0x26, 0x27, 0x28, 0x29, 0x2A, 0x2B, 0x2C, 0x2D, 0x2E, 0x2F,
0x30, 0x31, 0x32, 0x33, 0x34, 0x35, 0x36, 0x37, 0x38, 0x39, 0x3A, 0x3B,
0x3C, 0x3D, 0x3E, 0x3F, 0x40, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47,
0x48, 0x49, 0x4A, 0x4B, 0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53,
0x54, 0x55, 0x56, 0x57, 0x58, 0x59, 0x5A, 0x5B, 0x5C, 0x5D, 0x5E, 0x5F,
0x60, 0x41, 0x42, 0x43, 0x44, 0x45, 0x46, 0x47, 0x48, 0x49, 0x4A, 0x4B,
0x4C, 0x4D, 0x4E, 0x4F, 0x50, 0x51, 0x52, 0x53, 0x54, 0x55, 0x56, 0x57,
0x58, 0x59, 0x5A, 0x7B, 0x7C, 0x7D, 0x7E, 0x7F, 0x80, 0x81, 0x82, 0x83,
0x84, 0x85, 0x86, 0x87, 0x88, 0x89, 0x8A, 0x8B, 0x8C, 0x8D, 0x8E, 0x8F,
0x90, 0x91, 0x92, 0x93, 0x94, 0x95, 0x96, 0x97, 0x98, 0x99, 0x9A, 0x9B,
0x9C, 0x9D, 0x9E, 0x9F, 0xA0, 0xA1, 0xA2, 0xA3, 0xA4, 0xA5, 0xA6, 0xA7,
0xA8, 0xA9, 0xAA, 0xAB, 0xAC, 0xAD, 0xAE, 0xAF, 0xB0, 0xB1, 0xB2, 0xB3,
0xB4, 0xB5, 0xB6, 0xB7, 0xB8, 0xB9, 0xBA, 0xBB, 0xBC, 0xBD, 0xBE, 0xBF,
0xC0, 0xC1, 0xC2, 0xC3, 0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB,
0xCC, 0xCD, 0xCE, 0xCF, 0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xD7,
0xD8, 0xD9, 0xDA, 0xDB, 0xDC, 0xDD, 0xDE, 0xDF, 0xC0, 0xC1, 0xC2, 0xC3,
0xC4, 0xC5, 0xC6, 0xC7, 0xC8, 0xC9, 0xCA, 0xCB, 0xCC, 0xCD, 0xCE, 0xCF,
0xD0, 0xD1, 0xD2, 0xD3, 0xD4, 0xD5, 0xD6, 0xF7, 0xD8, 0xD9, 0xDA, 0xDB,
0xDC, 0xDD, 0xDE, 0x3F};
dword_result_t RtlUpperChar_entry(dword_t in) {
return rtl_upper_table[in & 0xff];
}
DECLARE_XBOXKRNL_EXPORT1(RtlUpperChar, kNone, kImplemented);
dword_result_t RtlLowerChar_entry(dword_t in) {
char c = in & 0xFF;
if (c >= 'A' && c <= 'Z') {
return c ^ 0x20;
}
return c;
return rtl_lower_table[in & 0xff];
}
DECLARE_XBOXKRNL_EXPORT1(RtlLowerChar, kNone, kImplemented);

View File

@@ -473,7 +473,8 @@ void VdSwap_entry(
dwords[i] = xenos::MakePacketType2();
}
}
DECLARE_XBOXKRNL_EXPORT2(VdSwap, kVideo, kImplemented, kImportant);
DECLARE_XBOXKRNL_EXPORT3(VdSwap, kVideo, kImplemented, kHighFrequency,
kImportant);
void RegisterVideoExports(xe::cpu::ExportResolver* export_resolver,
KernelState* kernel_state) {