From 5e9e226c944ef9ebd843683fc1948f04572afd4b Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:39:00 +0100 Subject: [PATCH 1/7] [Kernel] Add XamContentCreateDeviceEnumerator export Also changed name field of DeviceInfo to be a wchar_t* of known length, makes it match the X360 DeviceInfo struct more closely and it's easier to make sure things reading it won't overflow anything. --- src/xenia/kernel/xam/xam_content.cc | 33 +++++++++++++++++++++++++++-- 1 file changed, 31 insertions(+), 2 deletions(-) diff --git a/src/xenia/kernel/xam/xam_content.cc b/src/xenia/kernel/xam/xam_content.cc index 5a3c718c0..8dba3c155 100644 --- a/src/xenia/kernel/xam/xam_content.cc +++ b/src/xenia/kernel/xam/xam_content.cc @@ -23,7 +23,7 @@ struct DeviceInfo { uint32_t device_type; uint64_t total_bytes; uint64_t free_bytes; - std::wstring name; + wchar_t name[28]; }; static const DeviceInfo dummy_device_info_ = { 0xF00D0000, @@ -57,7 +57,7 @@ dword_result_t XamContentGetDeviceName(dword_t device_id, return X_ERROR_DEVICE_NOT_CONNECTED; } - if (name_capacity < dummy_device_info_.name.size() + 1) { + if (name_capacity < wcslen(dummy_device_info_.name) + 1) { return X_ERROR_INSUFFICIENT_BUFFER; } @@ -174,6 +174,35 @@ dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id, } DECLARE_XAM_EXPORT1(XamContentCreateEnumerator, kContent, kImplemented); +dword_result_t XamContentCreateDeviceEnumerator(dword_t content_type, + dword_t content_flags, + dword_t max_count, + lpdword_t buffer_size_ptr, + lpdword_t handle_out) { + assert_not_null(handle_out); + + if (buffer_size_ptr) { + *buffer_size_ptr = sizeof(DeviceInfo) * max_count; + } + + auto e = new XStaticEnumerator(kernel_state(), max_count, sizeof(DeviceInfo)); + e->Initialize(); + + // Copy our dummy device into the enumerator + DeviceInfo* dev = (DeviceInfo*)e->AppendItem(); + if (dev) { + xe::store_and_swap(&dev->device_id, dummy_device_info_.device_id); + xe::store_and_swap(&dev->device_type, dummy_device_info_.device_type); + xe::store_and_swap(&dev->total_bytes, dummy_device_info_.total_bytes); + xe::store_and_swap(&dev->free_bytes, dummy_device_info_.free_bytes); + xe::copy_and_swap(dev->name, dummy_device_info_.name, 28); + } + + *handle_out = e->handle(); + return X_ERROR_SUCCESS; +} +DECLARE_XAM_EXPORT(XamContentCreateDeviceEnumerator, ExportTag::kImplemented); + dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name, lpvoid_t content_data_ptr, dword_t flags, lpdword_t disposition_ptr, From c5056c644f500efae8b66b189894a1d02dacf9ab Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:41:45 +0100 Subject: [PATCH 2/7] [Kernel] Add XamNotifyCreateListenerInternal export (1 unknown param) Just changed the existing XamNotifyCreateListener import to ...CreateListenerInternal, and made a new XamNotifyCreateListener that just calls the internal version. --- src/xenia/kernel/xam/xam_notify.cc | 9 ++++++++- 1 file changed, 8 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xam/xam_notify.cc b/src/xenia/kernel/xam/xam_notify.cc index 1a7337ab8..e3765af25 100644 --- a/src/xenia/kernel/xam/xam_notify.cc +++ b/src/xenia/kernel/xam/xam_notify.cc @@ -18,7 +18,8 @@ namespace xe { namespace kernel { namespace xam { -dword_result_t XamNotifyCreateListener(qword_t mask, dword_t one) { +dword_result_t XamNotifyCreateListenerInternal(qword_t mask, dword_t unk, + dword_t one) { // r4=1 may indicate user process? auto listener = @@ -30,6 +31,12 @@ dword_result_t XamNotifyCreateListener(qword_t mask, dword_t one) { return handle; } +DECLARE_XAM_EXPORT2(XamNotifyCreateListenerInternal, kNone, kImplemented, + kSketchy); + +dword_result_t XamNotifyCreateListener(qword_t mask, dword_t one) { + return XamNotifyCreateListenerInternal(mask, 0, one); +} DECLARE_XAM_EXPORT1(XamNotifyCreateListener, kNone, kImplemented); // https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgSignIn.cpp From 8efbe3286718d05da4579485f8b2067cc4dfbbb1 Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:51:56 +0100 Subject: [PATCH 3/7] [Kernel] Add XamBuild*ResourceLocator & XamFormat*String exports Resource locators are just strings that say where to find a resource, they can either point to a file path or to an XEX resource. Normally the Gamercard/SharedSystem exports use XamBuildResourceLocator to make a locator for the resources inside xam.xex. But since our xam won't have those resources I've made it point them to a local file instead (by passing 0 as the module param for XamBuildResourceLocator). The resources will have to be extracted to the XEX's local path for it to find them though (and XEX will need to have media:\ symlinked too) The XamFormat*String exports are really windows-only right now, but they'll at least empty the buffer for other platforms. They'll also always output MM/DD/YYYY no matter what locale the system is, on 360 this is localized properly of course. I've renamed XamBuildSharedResourceLocator_ to XamBuildLegacySystemResourceLocator too since that seems to be the proper name for it. In earlier Xams this just pointed to ...SharedSystemResourceLocator (as does this code), but later versions seem to have their own function. --- src/xenia/kernel/xam/xam_info.cc | 133 +++++++++++++++++++++++++++++ src/xenia/kernel/xam/xam_table.inc | 2 +- 2 files changed, 134 insertions(+), 1 deletion(-) diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 38fdc04d0..431b5a622 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -17,6 +17,10 @@ #include "xenia/kernel/xthread.h" #include "xenia/xbox.h" +#if XE_PLATFORM_WIN32 +#include "xenia/base/platform_win.h" +#endif + namespace xe { namespace kernel { namespace xam { @@ -24,6 +28,135 @@ namespace xam { constexpr uint32_t X_LANGUAGE_ENGLISH = 1; constexpr uint32_t X_LANGUAGE_JAPANESE = 2; +void XamFormatDateString(dword_t unk, qword_t filetime, lpwstring_t buffer, + dword_t buffer_length) { +// TODO: implement this for other platforms +#if XE_PLATFORM_WIN32 + FILETIME t; + t.dwHighDateTime = filetime >> 32; + t.dwLowDateTime = (uint32_t)filetime; + + SYSTEMTIME st; + SYSTEMTIME stLocal; + + FileTimeToSystemTime(&t, &st); + SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal); + + wchar_t buf[256]; + std::memset(buf, 0, 256 * 2); + size_t size = 256 > buffer_length ? buffer_length : 256; + // TODO: format this depending on users locale? + swprintf_s(buf, size, L"%02d/%02d/%d", stLocal.wMonth, stLocal.wDay, + stLocal.wYear); +#endif + std::memset(buffer, 0, buffer_length * 2); +#if XE_PLATFORM_WIN32 + xe::store_and_swap(buffer, buf); +#endif +} +DECLARE_XAM_EXPORT(XamFormatDateString, ExportTag::kImplemented); + +void XamFormatTimeString(dword_t unk, qword_t filetime, lpwstring_t buffer, + dword_t buffer_length) { +// TODO: implement this for other platforms +#if XE_PLATFORM_WIN32 + FILETIME t; + t.dwHighDateTime = filetime >> 32; + t.dwLowDateTime = (uint32_t)filetime; + + SYSTEMTIME st; + SYSTEMTIME stLocal; + + FileTimeToSystemTime(&t, &st); + SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal); + + wchar_t buf[256]; + std::memset(buf, 0, 256 * 2); + size_t size = 256 > buffer_length ? buffer_length : 256; + swprintf_s(buf, size, L"%02d:%02d", stLocal.wHour, stLocal.wMinute); +#endif + std::memset(buffer, 0, buffer_length * 2); +#if XE_PLATFORM_WIN32 + xe::store_and_swap(buffer, buf); +#endif +} +DECLARE_XAM_EXPORT(XamFormatTimeString, ExportTag::kImplemented); + +dword_result_t keXamBuildResourceLocator(uint64_t module, + const wchar_t* container, + const wchar_t* resource, + lpwstring_t buffer, + uint32_t buffer_length) { + wchar_t buf[256]; + size_t size = 256 > buffer_length ? buffer_length : 256; + + if (!module) { + swprintf_s(buf, size, L"file://media:/%s.xzp#%s", container, resource); + XELOGD( + "XamBuildResourceLocator(%ws) returning locator to local file %ws.xzp", + container, container); + } else { + swprintf_s(buf, size, L"section://%X,%s#%s", (uint32_t)module, container, + resource); + } + + memset(buffer, 0, buffer_length * 2); + xe::store_and_swap(buffer, buf); + + return 0; +} + +dword_result_t XamBuildResourceLocator(qword_t module, lpwstring_t container, + lpwstring_t resource, lpwstring_t buffer, + dword_t buffer_length) { + return keXamBuildResourceLocator(module, container.value().c_str(), + resource.value().c_str(), buffer, + buffer_length); +} +DECLARE_XAM_EXPORT(XamBuildResourceLocator, ExportTag::kImplemented); + +dword_result_t XamBuildGamercardResourceLocator(lpwstring_t filename, + lpwstring_t buffer, + dword_t buffer_length) { + // On an actual xbox these funcs would return a locator to xam.xex resources, + // but for Xenia we can return a locator to the resources as local files. (big + // thanks to MS for letting XamBuildResourceLocator return local file + // locators!) + + // If you're running an app that'll need them, make sure to extract xam.xex + // resources with xextool ("xextool -d . xam.xex") and add a .xzp extension. + + return keXamBuildResourceLocator(0, L"gamercrd", filename.value().c_str(), + buffer, buffer_length); +} +DECLARE_XAM_EXPORT(XamBuildGamercardResourceLocator, ExportTag::kImplemented); + +dword_result_t XamBuildSharedSystemResourceLocator(lpwstring_t filename, + lpwstring_t buffer, + dword_t buffer_length) { + // see notes inside XamBuildGamercardResourceLocator above + return keXamBuildResourceLocator(0, L"shrdres", filename.value().c_str(), + buffer, buffer_length); +} +DECLARE_XAM_EXPORT(XamBuildSharedSystemResourceLocator, + ExportTag::kImplemented); + +dword_result_t XamBuildLegacySystemResourceLocator(lpwstring_t filename, + lpwstring_t buffer, + dword_t buffer_len) { + return XamBuildSharedSystemResourceLocator(filename, buffer, buffer_len); +} +DECLARE_XAM_EXPORT(XamBuildLegacySystemResourceLocator, + ExportTag::kImplemented); + +dword_result_t XamBuildXamResourceLocator(lpwstring_t filename, + lpwstring_t buffer, + dword_t buffer_length) { + return keXamBuildResourceLocator(0, L"xam", filename.value().c_str(), buffer, + buffer_length); +} +DECLARE_XAM_EXPORT(XamBuildXamResourceLocator, ExportTag::kImplemented); + dword_result_t XamGetSystemVersion() { // eh, just picking one. If we go too low we may break new games, but // this value seems to be used for conditionally loading symbols and if diff --git a/src/xenia/kernel/xam/xam_table.inc b/src/xenia/kernel/xam/xam_table.inc index cec253c69..0bc4f02e6 100644 --- a/src/xenia/kernel/xam/xam_table.inc +++ b/src/xenia/kernel/xam/xam_table.inc @@ -588,7 +588,7 @@ XE_EXPORT(xam, 0x00000318, XamVoiceGetMicArrayStatus, XE_EXPORT(xam, 0x00000319, XamVoiceSetAudioCaptureRoutine, kFunction), XE_EXPORT(xam, 0x0000031A, XamVoiceGetDirectionalData, kFunction), XE_EXPORT(xam, 0x0000031B, XamBuildResourceLocator, kFunction), -XE_EXPORT(xam, 0x0000031C, XamBuildSharedSystemResourceLocator_, kFunction), +XE_EXPORT(xam, 0x0000031C, XamBuildLegacySystemResourceLocator, kFunction), XE_EXPORT(xam, 0x0000031D, XamBuildGamercardResourceLocator, kFunction), XE_EXPORT(xam, 0x0000031E, XamBuildDynamicResourceLocator, kFunction), XE_EXPORT(xam, 0x0000031F, XamBuildXamResourceLocator, kFunction), From 65e8872dc15edea5408b16abed08c0930f1a7aee Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:54:20 +0100 Subject: [PATCH 4/7] [Kernel] Add _vsnwprintf export --- src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc | 41 +++++++++++++++++++ 1 file changed, 41 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc index 2067f29e6..aa1bbf245 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc @@ -1009,6 +1009,46 @@ SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { SHIM_SET_RETURN_32(count); } +// https://msdn.microsoft.com/en-us/library/1kt27hek.aspx +SHIM_CALL _vsnwprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { + uint32_t buffer_ptr = SHIM_GET_ARG_32(0); + int32_t buffer_count = SHIM_GET_ARG_32(1); + uint32_t format_ptr = SHIM_GET_ARG_32(2); + uint32_t arg_ptr = SHIM_GET_ARG_32(3); + + XELOGD("_vsnwprintf(%08X, %i, %08X, %08X)", buffer_ptr, buffer_count, + format_ptr, arg_ptr); + + if (buffer_ptr == 0 || buffer_count <= 0 || format_ptr == 0) { + SHIM_SET_RETURN_32(-1); + return; + } + + auto buffer = (uint16_t*)SHIM_MEM_ADDR(buffer_ptr); + auto format = (const uint16_t*)SHIM_MEM_ADDR(format_ptr); + + ArrayArgList args(ppc_context, arg_ptr); + WideStringFormatData data(format); + + int32_t count = format_core(ppc_context, data, args, true); + if (count < 0) { + // Error. + if (buffer_count > 0) { + buffer[0] = '\0'; // write a null, just to be safe + } + } else if (count <= buffer_count) { + // Fit within the buffer. + xe::copy_and_swap(buffer, (uint16_t*)data.wstr().c_str(), count); + if (count < buffer_count) { + buffer[count] = '\0'; + } + } else { + // Overflowed buffer. We still return the count we would have written. + xe::copy_and_swap(buffer, (uint16_t*)data.wstr().c_str(), buffer_count); + } + SHIM_SET_RETURN_32(count); +} + // https://msdn.microsoft.com/en-us/library/28d5ce15.aspx SHIM_CALL vsprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) { uint32_t buffer_ptr = SHIM_GET_ARG_32(0); @@ -1100,6 +1140,7 @@ void RegisterStringExports(xe::cpu::ExportResolver* export_resolver, SHIM_SET_MAPPING("xboxkrnl.exe", vsprintf, state); SHIM_SET_MAPPING("xboxkrnl.exe", _vscwprintf, state); SHIM_SET_MAPPING("xboxkrnl.exe", vswprintf, state); + SHIM_SET_MAPPING("xboxkrnl.exe", _vsnwprintf, state); } } // namespace xboxkrnl From 958882a3ea8766798882e4675ef11cc6dcfb7ff7 Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:55:30 +0100 Subject: [PATCH 5/7] [Kernel] Add ExConsoleGameRegion export variable (set to 0xFFFFFFFF) --- src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc | 8 ++++++++ 1 file changed, 8 insertions(+) diff --git a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc index 706c58ca8..f38d27d35 100644 --- a/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc +++ b/src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc @@ -159,6 +159,14 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state) xe::store_and_swap(lpXboxHardwareInfo + 4, 0x06); // cpu count // Remaining 11b are zeroes? + // ExConsoleGameRegion, probably same values as keyvault region uses? + // Just return all 0xFF, should satisfy anything that checks it + uint32_t pExConsoleGameRegion = memory_->SystemHeapAlloc(4); + auto lpExConsoleGameRegion = memory_->TranslateVirtual(pExConsoleGameRegion); + export_resolver_->SetVariableMapping( + "xboxkrnl.exe", ordinals::ExConsoleGameRegion, pExConsoleGameRegion); + xe::store(lpExConsoleGameRegion, 0xFFFFFFFF); + // XexExecutableModuleHandle (?**) // Games try to dereference this to get a pointer to some module struct. // So far it seems like it's just in loader code, and only used to look up From 8c6e0b86f927bdda5802b084f44d492544fa8c93 Mon Sep 17 00:00:00 2001 From: emoose Date: Wed, 24 Oct 2018 00:32:49 +0100 Subject: [PATCH 6/7] [Kernel] swprintf_s -> swprintf, change how Format*String/Build*ResourceLocator exports copy text New way of copying the text should make it less likely for any buffer overflows to occur. --- src/xenia/kernel/xam/xam_info.cc | 58 ++++++++++++++------------------ 1 file changed, 25 insertions(+), 33 deletions(-) diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 431b5a622..3ff1539a0 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -28,8 +28,10 @@ namespace xam { constexpr uint32_t X_LANGUAGE_ENGLISH = 1; constexpr uint32_t X_LANGUAGE_JAPANESE = 2; -void XamFormatDateString(dword_t unk, qword_t filetime, lpwstring_t buffer, +void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t buffer, dword_t buffer_length) { + std::memset(buffer, 0, buffer_length * 2); + // TODO: implement this for other platforms #if XE_PLATFORM_WIN32 FILETIME t; @@ -43,21 +45,19 @@ void XamFormatDateString(dword_t unk, qword_t filetime, lpwstring_t buffer, SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal); wchar_t buf[256]; - std::memset(buf, 0, 256 * 2); - size_t size = 256 > buffer_length ? buffer_length : 256; // TODO: format this depending on users locale? - swprintf_s(buf, size, L"%02d/%02d/%d", stLocal.wMonth, stLocal.wDay, - stLocal.wYear); -#endif - std::memset(buffer, 0, buffer_length * 2); -#if XE_PLATFORM_WIN32 - xe::store_and_swap(buffer, buf); + swprintf(buf, 256, L"%02d/%02d/%d", stLocal.wMonth, stLocal.wDay, + stLocal.wYear); + + xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length); #endif } DECLARE_XAM_EXPORT(XamFormatDateString, ExportTag::kImplemented); -void XamFormatTimeString(dword_t unk, qword_t filetime, lpwstring_t buffer, +void XamFormatTimeString(dword_t unk, qword_t filetime, lpvoid_t buffer, dword_t buffer_length) { + std::memset(buffer, 0, buffer_length * 2); + // TODO: implement this for other platforms #if XE_PLATFORM_WIN32 FILETIME t; @@ -71,13 +71,9 @@ void XamFormatTimeString(dword_t unk, qword_t filetime, lpwstring_t buffer, SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal); wchar_t buf[256]; - std::memset(buf, 0, 256 * 2); - size_t size = 256 > buffer_length ? buffer_length : 256; - swprintf_s(buf, size, L"%02d:%02d", stLocal.wHour, stLocal.wMinute); -#endif - std::memset(buffer, 0, buffer_length * 2); -#if XE_PLATFORM_WIN32 - xe::store_and_swap(buffer, buf); + swprintf(buf, 256, L"%02d:%02d", stLocal.wHour, stLocal.wMinute); + + xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length); #endif } DECLARE_XAM_EXPORT(XamFormatTimeString, ExportTag::kImplemented); @@ -85,29 +81,26 @@ DECLARE_XAM_EXPORT(XamFormatTimeString, ExportTag::kImplemented); dword_result_t keXamBuildResourceLocator(uint64_t module, const wchar_t* container, const wchar_t* resource, - lpwstring_t buffer, + lpvoid_t buffer, uint32_t buffer_length) { wchar_t buf[256]; - size_t size = 256 > buffer_length ? buffer_length : 256; if (!module) { - swprintf_s(buf, size, L"file://media:/%s.xzp#%s", container, resource); + swprintf(buf, 256, L"file://media:/%s.xzp#%s", container, resource); XELOGD( "XamBuildResourceLocator(%ws) returning locator to local file %ws.xzp", container, container); } else { - swprintf_s(buf, size, L"section://%X,%s#%s", (uint32_t)module, container, - resource); + swprintf(buf, 256, L"section://%X,%s#%s", (uint32_t)module, container, + resource); } - memset(buffer, 0, buffer_length * 2); - xe::store_and_swap(buffer, buf); - + xe::copy_and_swap((wchar_t*)buffer.host_address(), buf, buffer_length); return 0; } dword_result_t XamBuildResourceLocator(qword_t module, lpwstring_t container, - lpwstring_t resource, lpwstring_t buffer, + lpwstring_t resource, lpvoid_t buffer, dword_t buffer_length) { return keXamBuildResourceLocator(module, container.value().c_str(), resource.value().c_str(), buffer, @@ -116,7 +109,7 @@ dword_result_t XamBuildResourceLocator(qword_t module, lpwstring_t container, DECLARE_XAM_EXPORT(XamBuildResourceLocator, ExportTag::kImplemented); dword_result_t XamBuildGamercardResourceLocator(lpwstring_t filename, - lpwstring_t buffer, + lpvoid_t buffer, dword_t buffer_length) { // On an actual xbox these funcs would return a locator to xam.xex resources, // but for Xenia we can return a locator to the resources as local files. (big @@ -132,7 +125,7 @@ dword_result_t XamBuildGamercardResourceLocator(lpwstring_t filename, DECLARE_XAM_EXPORT(XamBuildGamercardResourceLocator, ExportTag::kImplemented); dword_result_t XamBuildSharedSystemResourceLocator(lpwstring_t filename, - lpwstring_t buffer, + lpvoid_t buffer, dword_t buffer_length) { // see notes inside XamBuildGamercardResourceLocator above return keXamBuildResourceLocator(0, L"shrdres", filename.value().c_str(), @@ -142,15 +135,14 @@ DECLARE_XAM_EXPORT(XamBuildSharedSystemResourceLocator, ExportTag::kImplemented); dword_result_t XamBuildLegacySystemResourceLocator(lpwstring_t filename, - lpwstring_t buffer, - dword_t buffer_len) { - return XamBuildSharedSystemResourceLocator(filename, buffer, buffer_len); + lpvoid_t buffer, + dword_t buffer_length) { + return XamBuildSharedSystemResourceLocator(filename, buffer, buffer_length); } DECLARE_XAM_EXPORT(XamBuildLegacySystemResourceLocator, ExportTag::kImplemented); -dword_result_t XamBuildXamResourceLocator(lpwstring_t filename, - lpwstring_t buffer, +dword_result_t XamBuildXamResourceLocator(lpwstring_t filename, lpvoid_t buffer, dword_t buffer_length) { return keXamBuildResourceLocator(0, L"xam", filename.value().c_str(), buffer, buffer_length); From 933588717ef53347326be821696dd0199840b1ed Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 12 Nov 2018 02:20:34 +0000 Subject: [PATCH 7/7] [Kernel] Add XamGetOnlineSchema export, returns dummy data --- src/xenia/kernel/xam/xam_info.cc | 23 +++++++++++++++++++++++ 1 file changed, 23 insertions(+) diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc index 3ff1539a0..7590d96f9 100644 --- a/src/xenia/kernel/xam/xam_info.cc +++ b/src/xenia/kernel/xam/xam_info.cc @@ -28,6 +28,29 @@ namespace xam { constexpr uint32_t X_LANGUAGE_ENGLISH = 1; constexpr uint32_t X_LANGUAGE_JAPANESE = 2; +dword_result_t XamGetOnlineSchema() { + static uint32_t schema_guest = 0; + static uint32_t schema_ptr_guest = 0; + + if (!schema_guest) { + // create a dummy schema, 8 bytes of 0 seems to work fine + // (with another 8 bytes for schema ptr/schema size) + schema_guest = kernel_state()->memory()->SystemHeapAlloc(16); + schema_ptr_guest = schema_guest + 8; + + auto schema = kernel_state()->memory()->TranslateVirtual(schema_guest); + memset(schema, 0, 16); + + // store schema ptr + size + xe::store_and_swap(schema + 0x8, schema_guest); + xe::store_and_swap(schema + 0xC, 0x8); + } + + // return pointer to the schema ptr/schema size struct + return schema_ptr_guest; +} +DECLARE_XAM_EXPORT(XamGetOnlineSchema, ExportTag::kImplemented); + void XamFormatDateString(dword_t unk, qword_t filetime, lpvoid_t buffer, dword_t buffer_length) { std::memset(buffer, 0, buffer_length * 2);