From 8efbe3286718d05da4579485f8b2067cc4dfbbb1 Mon Sep 17 00:00:00 2001 From: emoose Date: Mon, 22 Oct 2018 17:51:56 +0100 Subject: [PATCH] [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),