Merge pull request #1245 from emoose/exports
[Kernel] Add 12 kernel/xam exports used by dash.xex
This commit is contained in:
commit
66c10a4b9f
|
@ -23,7 +23,7 @@ struct DeviceInfo {
|
||||||
uint32_t device_type;
|
uint32_t device_type;
|
||||||
uint64_t total_bytes;
|
uint64_t total_bytes;
|
||||||
uint64_t free_bytes;
|
uint64_t free_bytes;
|
||||||
std::wstring name;
|
wchar_t name[28];
|
||||||
};
|
};
|
||||||
static const DeviceInfo dummy_device_info_ = {
|
static const DeviceInfo dummy_device_info_ = {
|
||||||
0xF00D0000,
|
0xF00D0000,
|
||||||
|
@ -57,7 +57,7 @@ dword_result_t XamContentGetDeviceName(dword_t device_id,
|
||||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
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;
|
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);
|
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,
|
dword_result_t XamContentCreateEx(dword_t user_index, lpstring_t root_name,
|
||||||
lpvoid_t content_data_ptr, dword_t flags,
|
lpvoid_t content_data_ptr, dword_t flags,
|
||||||
lpdword_t disposition_ptr,
|
lpdword_t disposition_ptr,
|
||||||
|
|
|
@ -17,6 +17,10 @@
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
|
#if XE_PLATFORM_WIN32
|
||||||
|
#include "xenia/base/platform_win.h"
|
||||||
|
#endif
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xam {
|
namespace xam {
|
||||||
|
@ -24,6 +28,150 @@ namespace xam {
|
||||||
constexpr uint32_t X_LANGUAGE_ENGLISH = 1;
|
constexpr uint32_t X_LANGUAGE_ENGLISH = 1;
|
||||||
constexpr uint32_t X_LANGUAGE_JAPANESE = 2;
|
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() {
|
dword_result_t XamGetSystemVersion() {
|
||||||
// eh, just picking one. If we go too low we may break new games, but
|
// 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
|
// this value seems to be used for conditionally loading symbols and if
|
||||||
|
|
|
@ -18,7 +18,8 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xam {
|
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?
|
// r4=1 may indicate user process?
|
||||||
|
|
||||||
auto listener =
|
auto listener =
|
||||||
|
@ -30,6 +31,12 @@ dword_result_t XamNotifyCreateListener(qword_t mask, dword_t one) {
|
||||||
|
|
||||||
return handle;
|
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);
|
DECLARE_XAM_EXPORT1(XamNotifyCreateListener, kNone, kImplemented);
|
||||||
|
|
||||||
// https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgSignIn.cpp
|
// https://github.com/CodeAsm/ffplay360/blob/master/Common/AtgSignIn.cpp
|
||||||
|
|
|
@ -588,7 +588,7 @@ XE_EXPORT(xam, 0x00000318, XamVoiceGetMicArrayStatus,
|
||||||
XE_EXPORT(xam, 0x00000319, XamVoiceSetAudioCaptureRoutine, kFunction),
|
XE_EXPORT(xam, 0x00000319, XamVoiceSetAudioCaptureRoutine, kFunction),
|
||||||
XE_EXPORT(xam, 0x0000031A, XamVoiceGetDirectionalData, kFunction),
|
XE_EXPORT(xam, 0x0000031A, XamVoiceGetDirectionalData, kFunction),
|
||||||
XE_EXPORT(xam, 0x0000031B, XamBuildResourceLocator, 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, 0x0000031D, XamBuildGamercardResourceLocator, kFunction),
|
||||||
XE_EXPORT(xam, 0x0000031E, XamBuildDynamicResourceLocator, kFunction),
|
XE_EXPORT(xam, 0x0000031E, XamBuildDynamicResourceLocator, kFunction),
|
||||||
XE_EXPORT(xam, 0x0000031F, XamBuildXamResourceLocator, kFunction),
|
XE_EXPORT(xam, 0x0000031F, XamBuildXamResourceLocator, kFunction),
|
||||||
|
|
|
@ -159,6 +159,14 @@ XboxkrnlModule::XboxkrnlModule(Emulator* emulator, KernelState* kernel_state)
|
||||||
xe::store_and_swap<uint8_t>(lpXboxHardwareInfo + 4, 0x06); // cpu count
|
xe::store_and_swap<uint8_t>(lpXboxHardwareInfo + 4, 0x06); // cpu count
|
||||||
// Remaining 11b are zeroes?
|
// 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 (?**)
|
// XexExecutableModuleHandle (?**)
|
||||||
// Games try to dereference this to get a pointer to some module struct.
|
// 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
|
// So far it seems like it's just in loader code, and only used to look up
|
||||||
|
|
|
@ -1009,6 +1009,46 @@ SHIM_CALL _vsnprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||||
SHIM_SET_RETURN_32(count);
|
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
|
// https://msdn.microsoft.com/en-us/library/28d5ce15.aspx
|
||||||
SHIM_CALL vsprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
SHIM_CALL vsprintf_shim(PPCContext* ppc_context, KernelState* kernel_state) {
|
||||||
uint32_t buffer_ptr = SHIM_GET_ARG_32(0);
|
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", vsprintf, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", _vscwprintf, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", _vscwprintf, state);
|
||||||
SHIM_SET_MAPPING("xboxkrnl.exe", vswprintf, state);
|
SHIM_SET_MAPPING("xboxkrnl.exe", vswprintf, state);
|
||||||
|
SHIM_SET_MAPPING("xboxkrnl.exe", _vsnwprintf, state);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace xboxkrnl
|
} // namespace xboxkrnl
|
||||||
|
|
Loading…
Reference in New Issue