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),