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;
|
||||
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,
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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),
|
||||
|
|
|
@ -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
|
||||
|
|
|
@ -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
|
||||
|
|
Loading…
Reference in New Issue