Implement RtlRandom (which despite its name is located in Xam, not xboxkrnl, which is why its not in xboxkrnl_rtl)
Stub XamVoiceSubmitPacket Stubs for __CAP_Start_Profiling/End_Profiling/Enter_Function/Exit_Function add a note about io_status_block in NtDeviceIoControlFile, change the param's type move the X_IOCTL_ constants from NtDeviceIoControlFile's body into xbox.h add X_STATUS_INVALID_IMAGE_FORMAT to xbox.h Implement XexLoadImageHeaders Much more correct version of IoCreateDevice, properly initializes/allocates device extension data Stub version of IoDeleteDevice Open the quickstart guide in the browser the first time a user opens the emulator Add some persistent flags that are stored in the registry on windows, not in the config. These are just used to indicate whether one-time tasks have run, like showing the quickstart guide. On non-windows platforms a default value is returned that skips any of these tasks so they don't run every single time. If the user opens a .iso file, show a warning telling them that we do not condone or support piracy. If the user closes the messagebox within two seconds set a sticky flag that will show them the warning every time instead. Otherwise the warning is never shown again. The Beep function is used to spook them a bit, to hopefully make them less likely to skip the message If a user opens an archive file, which we do not support, explain to them that they're dumb. Removed messages intended to "catch" pirates. If they're out there, we don't want to know about them. A huge chunk of the discourse on our discord is now about piracy. Hopefully these changes will deter them from coming to us for now, but some of these messages may backfire
This commit is contained in:
@@ -616,6 +616,55 @@ dword_result_t XamIsCurrentTitleDash_entry(const ppc_context_t& ctx) {
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamIsCurrentTitleDash, kNone, kImplemented);
|
||||
|
||||
dword_result_t XGetAudioFlags_entry() { return 65537; }
|
||||
DECLARE_XAM_EXPORT1(XGetAudioFlags, kNone, kStub);
|
||||
|
||||
/*
|
||||
todo: this table should instead be pointed to by a member of kernel state and initialized along with the process
|
||||
*/
|
||||
static int32_t XamRtlRandomTable[128] = {
|
||||
1284227242, 1275210071, 573735546, 790525478, 2139871995, 1547161642,
|
||||
179605362, 789336058, 688789844, 1801674531, 1563985344, 1957994488,
|
||||
1364589140, 1645522239, 287218729, 606747145, 1972579041, 1085031214,
|
||||
1425521274, 1482476501, 1844823847, 57989841, 1897051121, 1935655697,
|
||||
1078145449, 1960408961, 1682526488, 842925246, 1500820517, 1214440339,
|
||||
1647877149, 682003330, 261478967, 2052111302, 162531612, 583907252,
|
||||
1336601894, 1715567821, 413027322, 484763869, 1383384898, 1004336348,
|
||||
764733703, 854245398, 651377827, 1614895754, 838170752, 1757981266,
|
||||
602609370, 1644491937, 926492609, 220523388, 115176313, 725345543,
|
||||
261903793, 746137067, 920026266, 1123561945, 1580818891, 1708537768,
|
||||
616249376, 1292428093, 562591055, 343818398, 1788223648, 1659004503,
|
||||
2077806209, 299502267, 1604221776, 602162358, 630328440, 1606980848,
|
||||
1580436667, 1078081533, 492894223, 839522115, 1979792683, 117609710,
|
||||
1767777339, 1454471165, 1965331169, 1844237615, 308236825, 329068152,
|
||||
412668190, 796845957, 1303643608, 436374069, 1677128483, 527237240,
|
||||
813497703, 1060284298, 1770027372, 1177238915, 884357618, 1409082233,
|
||||
1958367476, 448539723, 1592454029, 861567501, 963894560, 73586283,
|
||||
362288127, 507921405, 113007714, 823518204, 152049171, 1202660629,
|
||||
1326574676, 2025429265, 1035525444, 515967899, 1532298954, 2000478354,
|
||||
1450960922, 1417001333, 2049760794, 1229272821, 879983540, 1993962763,
|
||||
706699826, 776561741, 2111687655, 1343024091, 1637723038, 1220945662,
|
||||
484061587, 1390067357};
|
||||
|
||||
/*
|
||||
Follows xam exactly, the updates to the random table are probably racy.
|
||||
*/
|
||||
dword_result_t RtlRandom_entry(lpdword_t seed_out) {
|
||||
int32_t table_seed_new = (0x7FFFFFED * *seed_out + 0x7FFFFFC3) % 0x7FFFFFFF;
|
||||
*seed_out = table_seed_new;
|
||||
uint32_t param_seed_new =
|
||||
(0x7FFFFFED * table_seed_new + 0x7FFFFFC3) % 0x7FFFFFFFu;
|
||||
*seed_out = param_seed_new;
|
||||
|
||||
int32_t* update_table_position = &XamRtlRandomTable[param_seed_new & 0x7F];
|
||||
|
||||
int32_t result = *update_table_position;
|
||||
*update_table_position = table_seed_new;
|
||||
return result;
|
||||
}
|
||||
|
||||
DECLARE_XAM_EXPORT1(RtlRandom, kNone, kImplemented);
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -38,6 +38,13 @@ DECLARE_XAM_EXPORT1(XamVoiceClose, kNone, kStub);
|
||||
dword_result_t XamVoiceHeadsetPresent_entry(lpunknown_t voice_ptr) { return 0; }
|
||||
DECLARE_XAM_EXPORT1(XamVoiceHeadsetPresent, kNone, kStub);
|
||||
|
||||
dword_result_t XamVoiceSubmitPacket_entry(lpdword_t unk1, dword_t unk2,
|
||||
lpdword_t unk3) {
|
||||
// also may return 0xD000009D
|
||||
return 0x800700AA;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamVoiceSubmitPacket, kNone, kStub);
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -119,6 +119,22 @@ dword_result_t DmGetConsoleDebugMemoryStatus_entry() {
|
||||
}
|
||||
DECLARE_XBDM_EXPORT1(DmGetConsoleDebugMemoryStatus, kDebug, kStub);
|
||||
|
||||
void __CAP_Start_Profiling_entry(dword_t a1, dword_t a2) {}
|
||||
|
||||
DECLARE_XBDM_EXPORT1(__CAP_Start_Profiling, kDebug, kStub);
|
||||
|
||||
void __CAP_End_Profiling_entry() {}
|
||||
|
||||
DECLARE_XBDM_EXPORT1(__CAP_End_Profiling, kDebug, kStub);
|
||||
|
||||
void __CAP_Enter_Function_entry() {}
|
||||
|
||||
DECLARE_XBDM_EXPORT1(__CAP_Enter_Function, kDebug, kStub);
|
||||
|
||||
void __CAP_Exit_Function_entry() {}
|
||||
|
||||
DECLARE_XBDM_EXPORT1(__CAP_Exit_Function, kDebug, kStub);
|
||||
|
||||
} // namespace xbdm
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -672,20 +672,17 @@ dword_result_t FscSetCacheElementCount_entry(dword_t unk_0, dword_t unk_1) {
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(FscSetCacheElementCount, kFileSystem, kStub);
|
||||
|
||||
// todo: this should fill in the io status block and queue the apc
|
||||
dword_result_t NtDeviceIoControlFile_entry(
|
||||
dword_t handle, dword_t event_handle, dword_t apc_routine,
|
||||
dword_t apc_context, dword_t io_status_block, dword_t io_control_code,
|
||||
lpvoid_t input_buffer, dword_t input_buffer_len, lpvoid_t output_buffer,
|
||||
dword_t output_buffer_len) {
|
||||
dword_t apc_context, pointer_t<X_IO_STATUS_BLOCK> io_status_block,
|
||||
dword_t io_control_code, lpvoid_t input_buffer, dword_t input_buffer_len,
|
||||
lpvoid_t output_buffer, dword_t output_buffer_len) {
|
||||
// Called by XMountUtilityDrive cache-mounting code
|
||||
// (checks if the returned values look valid, values below seem to pass the
|
||||
// checks)
|
||||
const uint32_t cache_size = 0xFF000;
|
||||
|
||||
const uint32_t X_IOCTL_DISK_GET_DRIVE_GEOMETRY = 0x70000;
|
||||
const uint32_t X_IOCTL_DISK_GET_PARTITION_INFO = 0x74004;
|
||||
|
||||
if (io_control_code == X_IOCTL_DISK_GET_DRIVE_GEOMETRY) {
|
||||
if (output_buffer_len < 0x8) {
|
||||
assert_always();
|
||||
@@ -710,30 +707,89 @@ dword_result_t NtDeviceIoControlFile_entry(
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(NtDeviceIoControlFile, kFileSystem, kStub);
|
||||
// device_extension_size = additional bytes of data (aligned up to 8 byte
|
||||
// granularity) that will be allocated at the tail of the resulting device
|
||||
// object. although it is allocated at the tail, it is accessed through a
|
||||
// pointer at offset 0x18 so in theory a guest could be unaware that its a
|
||||
// single allocation device_name is optional, extra_device_object_attributes
|
||||
// gets assigned to the attributes field of the OBJECT_ATTRIBUTES used for
|
||||
// ObCreateObject
|
||||
|
||||
dword_result_t IoCreateDevice_entry(dword_t device_struct, dword_t r4,
|
||||
dword_t r5, dword_t r6, dword_t r7,
|
||||
lpdword_t out_struct) {
|
||||
// todo: need device guest object struct + host object for device
|
||||
dword_result_t IoCreateDevice_entry(dword_t driver_object,
|
||||
dword_t device_extension_size,
|
||||
pointer_t<X_ANSI_STRING> device_name,
|
||||
dword_t device_type,
|
||||
dword_t extra_device_object_attributes,
|
||||
lpdword_t device_object,
|
||||
const ppc_context_t& ctx) {
|
||||
// Called from XMountUtilityDrive XAM-task code
|
||||
// That code tries writing things to a pointer at out_struct+0x18
|
||||
// We'll alloc some scratch space for it so it doesn't cause any exceptions
|
||||
|
||||
// 0x24 is guessed size from accesses to out_struct - likely incorrect
|
||||
auto out_guest = kernel_memory()->SystemHeapAlloc(0x24);
|
||||
auto current_kernel = ctx->kernel_state;
|
||||
|
||||
auto out = kernel_memory()->TranslateVirtual<uint8_t*>(out_guest);
|
||||
memset(out, 0, 0x24);
|
||||
uint32_t required_size = 80 + xe::align<uint32_t>(device_extension_size, 8);
|
||||
|
||||
// XMountUtilityDrive writes some kind of header here
|
||||
// 0x1000 bytes should be enough to store it
|
||||
auto out_guest2 = kernel_memory()->SystemHeapAlloc(0x1000);
|
||||
xe::store_and_swap(out + 0x18, out_guest2);
|
||||
auto kernel_mem = current_kernel->memory();
|
||||
|
||||
*out_struct = out_guest;
|
||||
auto out_guest = kernel_mem->SystemHeapAlloc(required_size);
|
||||
|
||||
auto out = kernel_mem->TranslateVirtual<uint8_t*>(out_guest);
|
||||
|
||||
memset(out, 0, required_size);
|
||||
|
||||
xe::store<unsigned char>(out, 3); // maybe device object's Ob type?
|
||||
|
||||
// this stores the total object size, without alignment!
|
||||
|
||||
xe::store_and_swap<uint16_t>(out + 2, device_extension_size + 80);
|
||||
|
||||
// from 17559
|
||||
if (device_type == 7 || device_type == 58 || device_type == 62 ||
|
||||
device_type == 45 || device_type == 2 || device_type == 60 ||
|
||||
device_type == 61 || device_type == 36 || device_type == 64 ||
|
||||
device_type == 65 || device_type == 66 || device_type == 67 ||
|
||||
device_type == 68 || device_type == 69 || device_type == 70 ||
|
||||
device_type == 72 || device_type == 73) {
|
||||
xe::store_and_swap<uint32_t>(out + 0xC, 0);
|
||||
} else {
|
||||
// pointer to itself?
|
||||
xe::store_and_swap<uint32_t>(out + 0xC, out_guest);
|
||||
}
|
||||
xe::store<uint8_t>(out + 0x1C, static_cast<uint8_t>(device_type));
|
||||
|
||||
uint32_t flags_field_value = 16;
|
||||
if (device_name) {
|
||||
flags_field_value |= 8;
|
||||
}
|
||||
xe::store<unsigned char>(out + 0x1e, 1);
|
||||
xe::store_and_swap<uint32_t>(out + 0x14, flags_field_value);
|
||||
if (device_extension_size != 0) {
|
||||
// pointer to device specific data
|
||||
// XMountUtilityDrive writes some kind of header here
|
||||
xe::store_and_swap<uint32_t>(out + 0x18, out_guest + 80);
|
||||
}
|
||||
|
||||
xe::store_and_swap<uint32_t>(out + 8, driver_object);
|
||||
|
||||
*device_object = out_guest;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(IoCreateDevice, kFileSystem, kStub);
|
||||
|
||||
//supposed to invoke a callback on the driver object! its some sort of destructor function
|
||||
//intended to be called for all devices created from the driver
|
||||
void IoDeleteDevice_entry(dword_t device_ptr, const ppc_context_t& ctx) {
|
||||
if (device_ptr) {
|
||||
auto kernel_mem = ctx->kernel_state->memory();
|
||||
kernel_mem->SystemHeapFree(device_ptr);
|
||||
}
|
||||
}
|
||||
|
||||
DECLARE_XBOXKRNL_EXPORT1(IoDeleteDevice, kFileSystem, kStub);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
||||
@@ -13,6 +13,7 @@
|
||||
#include "xenia/kernel/kernel_state.h"
|
||||
#include "xenia/kernel/user_module.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
#include "xenia/kernel/util/xex2_info.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_private.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
@@ -215,6 +216,65 @@ void ExRegisterTitleTerminateNotification_entry(
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(ExRegisterTitleTerminateNotification, kModules,
|
||||
kImplemented);
|
||||
// todo: replace magic numbers
|
||||
dword_result_t XexLoadImageHeaders_entry(pointer_t<X_ANSI_STRING> path,
|
||||
pointer_t<xex2_header> header,
|
||||
dword_t buffer_size,
|
||||
const ppc_context_t& ctx) {
|
||||
if (buffer_size < 0x800) {
|
||||
return X_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
auto current_kernel = ctx->kernel_state;
|
||||
auto target_path = util::TranslateAnsiString(current_kernel->memory(), path);
|
||||
|
||||
vfs::File* vfs_file = nullptr;
|
||||
vfs::FileAction file_action;
|
||||
X_STATUS result = current_kernel->file_system()->OpenFile(
|
||||
nullptr, target_path, vfs::FileDisposition::kOpen,
|
||||
vfs::FileAccess::kGenericRead, false, true, &vfs_file, &file_action);
|
||||
|
||||
if (!vfs_file) {
|
||||
return result;
|
||||
}
|
||||
size_t bytes_read = 0;
|
||||
|
||||
X_STATUS result_status = vfs_file->ReadSync(
|
||||
reinterpret_cast<void*>(header.host_address()), 2048, 0, &bytes_read);
|
||||
|
||||
if (result_status < 0) {
|
||||
vfs_file->Destroy();
|
||||
return result_status;
|
||||
}
|
||||
|
||||
if (header->magic != 'XEX2') {
|
||||
vfs_file->Destroy();
|
||||
return X_STATUS_INVALID_IMAGE_FORMAT;
|
||||
}
|
||||
unsigned int header_size = header->header_size;
|
||||
|
||||
if (header_size < 0x800 || header_size > 0x10000 ||
|
||||
(header_size & 0x7FF) != 0) {
|
||||
result_status = X_STATUS_INVALID_IMAGE_FORMAT;
|
||||
} else if (header_size <= buffer_size) {
|
||||
if (header_size <= 0x800) {
|
||||
result_status = X_STATUS_SUCCESS;
|
||||
} else {
|
||||
result_status = vfs_file->ReadSync(
|
||||
reinterpret_cast<void*>(header.host_address() + 2048),
|
||||
header_size - 2048, 2048, &bytes_read);
|
||||
if (result_status >= X_STATUS_SUCCESS) {
|
||||
result_status = X_STATUS_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
} else {
|
||||
result_status = X_STATUS_BUFFER_TOO_SMALL;
|
||||
}
|
||||
|
||||
vfs_file->Destroy();
|
||||
return result_status;
|
||||
}
|
||||
DECLARE_XBOXKRNL_EXPORT1(XexLoadImageHeaders, kModules, kImplemented);
|
||||
|
||||
} // namespace xboxkrnl
|
||||
} // namespace kernel
|
||||
|
||||
Reference in New Issue
Block a user