Merge pull request #61 from chrisps/canary_experimental
performance improvements, kernel fixes, cpu accuracy improvements
This commit is contained in:
@@ -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() {
|
||||
|
||||
@@ -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 {
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
|
||||
@@ -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);
|
||||
|
||||
|
||||
@@ -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) {
|
||||
|
||||
Reference in New Issue
Block a user