Merge pull request #1245 from emoose/exports

[Kernel] Add 12 kernel/xam exports used by dash.xex
This commit is contained in:
Rick Gibbed 2018-11-23 16:40:56 -06:00 committed by GitHub
commit 66c10a4b9f
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
6 changed files with 237 additions and 4 deletions

View File

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

View File

@ -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

View File

@ -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

View File

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

View File

@ -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

View File

@ -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