summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorRick Gibbed <rick@gibbed.us>2018-11-23 16:40:56 -0600
committerGitHub <noreply@github.com>2018-11-23 16:40:56 -0600
commit66c10a4b9fe50a2b2c673e50584d71fc463f424e (patch)
tree7ef5adaeb71f929ccf8ef327f6cc924e1143fb6b
parentd68c27d78b05a30d927e4bfe580836309b0dc99e (diff)
parent933588717ef53347326be821696dd0199840b1ed (diff)
Merge pull request #1245 from emoose/exports
[Kernel] Add 12 kernel/xam exports used by dash.xex
-rw-r--r--src/xenia/kernel/xam/xam_content.cc33
-rw-r--r--src/xenia/kernel/xam/xam_info.cc148
-rw-r--r--src/xenia/kernel/xam/xam_notify.cc9
-rw-r--r--src/xenia/kernel/xam/xam_table.inc2
-rw-r--r--src/xenia/kernel/xboxkrnl/xboxkrnl_module.cc8
-rw-r--r--src/xenia/kernel/xboxkrnl/xboxkrnl_strings.cc41
6 files changed, 237 insertions, 4 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,
diff --git a/src/xenia/kernel/xam/xam_info.cc b/src/xenia/kernel/xam/xam_info.cc
index 38fdc04d0..7590d96f9 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,150 @@ 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<uint32_t>(schema + 0x8, schema_guest);
+ xe::store_and_swap<uint32_t>(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);
+
+// 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];
+ // TODO: format this depending on users locale?
+ 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, 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;
+ t.dwHighDateTime = filetime >> 32;
+ t.dwLowDateTime = (uint32_t)filetime;
+
+ SYSTEMTIME st;
+ SYSTEMTIME stLocal;
+
+ FileTimeToSystemTime(&t, &st);
+ SystemTimeToTzSpecificLocalTime(NULL, &st, &stLocal);
+
+ wchar_t buf[256];
+ 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);
+
+dword_result_t keXamBuildResourceLocator(uint64_t module,
+ const wchar_t* container,
+ const wchar_t* resource,
+ lpvoid_t buffer,
+ uint32_t buffer_length) {
+ wchar_t buf[256];
+
+ if (!module) {
+ 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(buf, 256, L"section://%X,%s#%s", (uint32_t)module, container,
+ resource);
+ }
+
+ 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, lpvoid_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,
+ 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
+ // 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,
+ lpvoid_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,
+ 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, lpvoid_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_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
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),
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<uint8_t>(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<uint32_t>(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
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