Merge pull request #370 from DrChat/xam_misc

XAM Misc Changes
This commit is contained in:
Ben Vanik 2015-07-27 18:14:15 -07:00
commit 297f5fdcd3
11 changed files with 416 additions and 139 deletions

View File

@ -246,35 +246,41 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
// This'll copy audio samples into the output buffer.
// The samples need to be 2 bytes long!
// Copies one frame at a time, so keep calling this until size == 0
int read_bytes = 0;
int written_bytes = 0;
int decode_attempts_remaining = 3;
uint8_t work_buffer[kOutputMaxSizeBytes];
while (decode_attempts_remaining) {
read_bytes = DecodePacket(work_buffer, 0, output_remaining_bytes);
if (read_bytes >= 0) {
// assert_true((read_bytes % 256) == 0);
auto written_bytes = output_rb.Write(work_buffer, read_bytes);
assert_true(read_bytes == written_bytes);
size_t read_bytes = 0;
written_bytes =
DecodePacket(work_buffer, 0, output_remaining_bytes, &read_bytes);
if (written_bytes >= 0) {
// assert_true((written_bytes % 256) == 0);
auto written_bytes_rb = output_rb.Write(work_buffer, written_bytes);
assert_true(written_bytes == written_bytes_rb);
// Ok.
break;
} else {
} else if (read_bytes % 2048 == 0) {
// Sometimes the decoder will fail on a packet. I think it's
// looking for cross-packet frames and failing. If you run it again
// on the same packet it'll work though.
--decode_attempts_remaining;
} else {
// Failed in the middle of a packet, do not retry!
decode_attempts_remaining = 0;
break;
}
}
if (!decode_attempts_remaining) {
XELOGAPU("XmaContext: libav failed to decode packet (returned %.8X)",
-read_bytes);
-written_bytes);
// Failed out.
if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
// There's new data available - maybe we'll be ok if we decode it?
read_bytes = 0;
written_bytes = 0;
DiscardPacket();
} else {
// No data and hosed - bail.
@ -283,10 +289,10 @@ void XmaContext::DecodePackets(XMA_CONTEXT_DATA& data) {
}
data.output_buffer_write_offset = output_rb.write_offset() / 256;
output_remaining_bytes -= read_bytes;
output_remaining_bytes -= written_bytes;
// If we need more data and the input buffers have it, grab it.
if (read_bytes) {
if (written_bytes) {
// Haven't finished with current packet.
continue;
} else if (data.input_buffer_0_valid || data.input_buffer_1_valid) {
@ -417,9 +423,12 @@ void XmaContext::DiscardPacket() {
}
int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
size_t output_size) {
size_t output_size, size_t* read_bytes) {
size_t to_copy = 0;
size_t original_offset = output_offset;
if (read_bytes) {
*read_bytes = 0;
}
// We're holding onto an already-decoded frame. Copy it out.
if (current_frame_pos_ != frame_samples_size_) {
@ -443,6 +452,10 @@ int XmaContext::DecodePacket(uint8_t* output, size_t output_offset,
return len;
}
if (read_bytes) {
*read_bytes += len;
}
// Offset by decoded length
packet_->size -= len;
packet_->data += len;

View File

@ -171,7 +171,8 @@ class XmaContext {
int sample_rate, int channels);
void DiscardPacket();
int DecodePacket(uint8_t* output, size_t offset, size_t size);
int DecodePacket(uint8_t* output, size_t offset, size_t size,
size_t* read_bytes);
Memory* memory_;

View File

@ -102,6 +102,24 @@ X_RESULT WinKeyInputDriver::GetState(uint32_t user_index,
}
}
// Right stick
if (IS_KEY_DOWN(0x26)) {
// Up
thumb_ry += SHRT_MAX;
}
if (IS_KEY_DOWN(0x28)) {
// Down
thumb_ry += SHRT_MIN;
}
if (IS_KEY_DOWN(0x27)) {
// Right
thumb_rx += SHRT_MAX;
}
if (IS_KEY_DOWN(0x25)) {
// Left
thumb_rx += SHRT_MIN;
}
if (IS_KEY_DOWN(0x4C)) {
// L
buttons |= 0x4000; // XINPUT_GAMEPAD_X
@ -162,6 +180,87 @@ X_RESULT WinKeyInputDriver::GetKeystroke(uint32_t user_index, uint32_t flags,
uint16_t keystroke_flags = 0;
uint8_t hid_code = 0;
if (IS_KEY_TOGGLED(VK_CAPITAL)) {
// dpad toggled
if (IS_KEY_DOWN(0x41)) {
// A
virtual_key = 0x5812; // VK_PAD_DPAD_LEFT
} else if (IS_KEY_DOWN(0x44)) {
// D
virtual_key = 0x5813; // VK_PAD_DPAD_RIGHT
} else if (IS_KEY_DOWN(0x53)) {
// S
virtual_key = 0x5811; // VK_PAD_DPAD_DOWN
} else if (IS_KEY_DOWN(0x57)) {
// W
virtual_key = 0x5810; // VK_PAD_DPAD_UP
}
} else {
// left stick
if (IS_KEY_DOWN(0x57)) {
// W
virtual_key = 0x5820; // VK_PAD_LTHUMB_UP
}
if (IS_KEY_DOWN(0x53)) {
// S
virtual_key = 0x5821; // VK_PAD_LTHUMB_DOWN
}
if (IS_KEY_DOWN(0x44)) {
// D
virtual_key = 0x5822; // VK_PAD_LTHUMB_RIGHT
}
if (IS_KEY_DOWN(0x41)) {
// A
virtual_key = 0x5823; // VK_PAD_LTHUMB_LEFT
}
}
// Right stick
if (IS_KEY_DOWN(0x26)) {
// Up
virtual_key = 0x5830;
}
if (IS_KEY_DOWN(0x28)) {
// Down
virtual_key = 0x5831;
}
if (IS_KEY_DOWN(0x27)) {
// Right
virtual_key = 0x5832;
}
if (IS_KEY_DOWN(0x25)) {
// Left
virtual_key = 0x5833;
}
if (IS_KEY_DOWN(0x4C)) {
// L
virtual_key = 0x5802; // VK_PAD_X
} else if (IS_KEY_DOWN(VK_OEM_7)) {
// '
virtual_key = 0x5801; // VK_PAD_B
} else if (IS_KEY_DOWN(VK_OEM_1)) {
// ;
virtual_key = 0x5800; // VK_PAD_A
} else if (IS_KEY_DOWN(0x50)) {
// P
virtual_key = 0x5803; // VK_PAD_Y
}
if (IS_KEY_DOWN(0x58)) {
// X
virtual_key = 0x5814; // VK_PAD_START
}
if (IS_KEY_DOWN(0x5A)) {
// Z
virtual_key = 0x5815; // VK_PAD_BACK
}
if (virtual_key != 0) {
keystroke_flags |= 0x0001; // XINPUT_KEYSTROKE_DOWN
result = X_ERROR_SUCCESS;
}
out_keystroke->virtual_key = virtual_key;
out_keystroke->unicode = unicode;
out_keystroke->flags = keystroke_flags;

View File

@ -29,10 +29,14 @@ class XEnumerator : public XObject {
virtual uint32_t item_count() const = 0;
virtual void WriteItems(uint8_t* buffer) = 0;
virtual bool WriteItem(uint8_t* buffer) = 0;
size_t current_item() const { return current_item_; }
protected:
size_t item_capacity_;
size_t item_size_;
size_t item_capacity_ = 0;
size_t item_size_ = 0;
size_t current_item_ = 0;
};
class XStaticEnumerator : public XEnumerator {
@ -58,6 +62,18 @@ class XStaticEnumerator : public XEnumerator {
std::memcpy(buffer, buffer_.data(), item_count_ * item_size_);
}
bool WriteItem(uint8_t* buffer) {
if (current_item_ >= item_count_) {
return false;
}
std::memcpy(buffer, buffer_.data() + current_item_ * item_size_,
item_size_);
current_item_++;
return true;
}
private:
uint32_t item_count_;
std::vector<uint8_t> buffer_;

View File

@ -231,7 +231,7 @@ class StringPointerParam : public ParamBase<uint32_t> {
uintptr_t host_address() const {
return reinterpret_cast<uintptr_t>(host_ptr_);
}
STR value() const { return STR(host_ptr_); }
STR value() const { return xe::load_and_swap<STR>(host_ptr_); }
operator CHAR*() const { return host_ptr_; }
operator bool() const { return host_ptr_ != nullptr; }

View File

@ -25,7 +25,11 @@ struct DeviceInfo {
std::wstring name;
};
static const DeviceInfo dummy_device_info_ = {
0xF00D0000, 1, 1024 * 1024 * 1024, 1024 * 1024 * 1024, L"Dummy HDD",
0xF00D0000,
1,
1024ull * 1024ull * 1024ull * 1024ull, // 1TB
1024ull * 1024ull * 1024ull * 1024ull, // 1TB
L"Dummy HDD",
};
SHIM_CALL XamContentGetLicenseMask_shim(PPCContext* ppc_context,
@ -48,40 +52,6 @@ SHIM_CALL XamContentGetLicenseMask_shim(PPCContext* ppc_context,
}
}
SHIM_CALL XamShowDeviceSelectorUI_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t content_type = SHIM_GET_ARG_32(1);
uint32_t content_flags = SHIM_GET_ARG_32(2);
uint64_t total_requested = SHIM_GET_ARG_64(3);
uint32_t device_id_ptr = SHIM_GET_ARG_32(4);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
XELOGD("XamShowDeviceSelectorUI(%d, %.8X, %.8X, %.8X, %.8X, %.8X)",
user_index, content_type, content_flags, total_requested,
device_id_ptr, overlapped_ptr);
switch (content_type) {
case 1: // save game
SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0001);
break;
case 2: // marketplace
SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0002);
break;
case 3: // title/publisher update?
SHIM_SET_MEM_32(device_id_ptr, dummy_device_info_.device_id | 0x0003);
break;
}
X_RESULT result = X_ERROR_SUCCESS;
if (overlapped_ptr) {
kernel_state->CompleteOverlappedImmediate(overlapped_ptr, result);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
} else {
SHIM_SET_RETURN_32(result);
}
}
SHIM_CALL XamContentGetDeviceName_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t device_id = SHIM_GET_ARG_32(0);
@ -149,7 +119,7 @@ SHIM_CALL XamContentGetDeviceData_shim(PPCContext* ppc_context,
const auto& device_info = dummy_device_info_;
SHIM_SET_MEM_32(device_data_ptr + 0, device_info.device_id);
SHIM_SET_MEM_32(device_data_ptr + 4, device_info.device_type);
SHIM_SET_MEM_32(device_data_ptr + 4, device_id & 0xFFFF); // Fake it.
SHIM_SET_MEM_64(device_data_ptr + 8, device_info.total_bytes);
SHIM_SET_MEM_64(device_data_ptr + 16, device_info.free_bytes);
xe::store_and_swap<std::wstring>(SHIM_MEM_ADDR(device_data_ptr + 24),
@ -183,54 +153,49 @@ SHIM_CALL XamContentResolve_shim(PPCContext* ppc_context,
}
// http://gameservice.googlecode.com/svn-history/r14/trunk/ContentManager.cpp
SHIM_CALL XamContentCreateEnumerator_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t user_index = SHIM_GET_ARG_32(0);
uint32_t device_id = SHIM_GET_ARG_32(1);
uint32_t content_type = SHIM_GET_ARG_32(2);
uint32_t content_flags = SHIM_GET_ARG_32(3);
uint32_t item_count = SHIM_GET_ARG_32(4);
uint32_t buffer_size_ptr = SHIM_GET_ARG_32(5);
uint32_t handle_ptr = SHIM_GET_ARG_32(6);
// https://github.com/LestaD/SourceEngine2007/blob/master/se2007/engine/xboxsystem.cpp#L499
dword_result_t XamContentCreateEnumerator(dword_t user_index, dword_t device_id,
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 ((device_id && (device_id & 0xFFFF0000) != dummy_device_info_.device_id) ||
!handle_out) {
if (buffer_size_ptr) {
*buffer_size_ptr = 0;
}
XELOGD("XamContentCreateEnumerator(%d, %.8X, %.8X, %.8X, %.8X, %.8X, %.8X)",
user_index, device_id, content_type, content_flags, item_count,
buffer_size_ptr, handle_ptr);
if (device_id && (device_id & 0xFFFF0000) != dummy_device_info_.device_id) {
// TODO(benvanik): memset 0 the data?
SHIM_SET_RETURN_32(X_E_INVALIDARG);
return;
}
if (!device_id) {
// 0 == whatever
device_id = dummy_device_info_.device_id;
return X_E_INVALIDARG;
}
if (buffer_size_ptr) {
SHIM_SET_MEM_32(buffer_size_ptr, item_count * XCONTENT_DATA::kSize);
*buffer_size_ptr = (uint32_t)XCONTENT_DATA::kSize;
}
auto e =
new XStaticEnumerator(kernel_state, item_count, XCONTENT_DATA::kSize);
new XStaticEnumerator(kernel_state(), max_count, XCONTENT_DATA::kSize);
e->Initialize();
// Get all content data.
auto content_datas =
kernel_state->content_manager()->ListContent(device_id, content_type);
auto content_datas = kernel_state()->content_manager()->ListContent(
device_id ? device_id : dummy_device_info_.device_id, content_type);
for (auto& content_data : content_datas) {
auto ptr = e->AppendItem();
if (!ptr) {
// Too many items.
break;
}
content_data.Write(ptr);
}
SHIM_SET_MEM_32(handle_ptr, e->handle());
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
*handle_out = e->handle();
return X_ERROR_SUCCESS;
}
DECLARE_XAM_EXPORT(XamContentCreateEnumerator, ExportTag::kImplemented);
void XamContentCreateCore(PPCContext* ppc_context, KernelState* kernel_state,
uint32_t user_index, std::string root_name,
@ -542,12 +507,10 @@ SHIM_CALL XamContentDelete_shim(PPCContext* ppc_context,
void xe::kernel::xam::RegisterContentExports(
xe::cpu::ExportResolver* export_resolver, KernelState* kernel_state) {
SHIM_SET_MAPPING("xam.xex", XamContentGetLicenseMask, state);
SHIM_SET_MAPPING("xam.xex", XamShowDeviceSelectorUI, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceName, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceState, state);
SHIM_SET_MAPPING("xam.xex", XamContentGetDeviceData, state);
SHIM_SET_MAPPING("xam.xex", XamContentResolve, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreateEnumerator, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreate, state);
SHIM_SET_MAPPING("xam.xex", XamContentCreateEx, state);
SHIM_SET_MAPPING("xam.xex", XamContentFlush, state);

View File

@ -198,51 +198,44 @@ SHIM_CALL XamFree_shim(PPCContext* ppc_context, KernelState* kernel_state) {
SHIM_SET_RETURN_32(X_ERROR_SUCCESS);
}
SHIM_CALL XamEnumerate_shim(PPCContext* ppc_context,
KernelState* kernel_state) {
uint32_t handle = SHIM_GET_ARG_32(0);
uint32_t zero = SHIM_GET_ARG_32(1);
uint32_t buffer_ptr = SHIM_GET_ARG_32(2);
uint32_t buffer_length = SHIM_GET_ARG_32(3);
uint32_t item_count_ptr = SHIM_GET_ARG_32(4);
uint32_t overlapped_ptr = SHIM_GET_ARG_32(5);
// https://github.com/LestaD/SourceEngine2007/blob/master/se2007/engine/xboxsystem.cpp#L518
dword_result_t XamEnumerate(dword_t handle, dword_t flags, lpvoid_t buffer,
dword_t buffer_length, lpdword_t items_returned,
pointer_t<XAM_OVERLAPPED> overlapped) {
assert_true(flags == 0);
assert_true(zero == 0);
XELOGD("XamEnumerate(%.8X, %d, %.8X, %d, %.8X, %.8X)", handle, zero,
buffer_ptr, buffer_length, item_count_ptr, overlapped_ptr);
auto e = kernel_state->object_table()->LookupObject<XEnumerator>(handle);
auto e = kernel_state()->object_table()->LookupObject<XEnumerator>(handle);
if (!e) {
if (overlapped_ptr) {
kernel_state->CompleteOverlappedImmediateEx(
overlapped_ptr, X_ERROR_INVALID_HANDLE, X_ERROR_INVALID_HANDLE, 0);
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediateEx(
overlapped, X_ERROR_INVALID_HANDLE, X_ERROR_INVALID_HANDLE, 0);
return X_ERROR_IO_PENDING;
} else {
SHIM_SET_RETURN_32(X_ERROR_INVALID_HANDLE);
return X_ERROR_INVALID_HANDLE;
}
return;
}
auto item_count = e->item_count();
e->WriteItems(SHIM_MEM_ADDR(buffer_ptr));
buffer.Zero(buffer_length);
X_RESULT result =
e->WriteItem(buffer) ? X_ERROR_SUCCESS : X_ERROR_NO_MORE_FILES;
if (items_returned) {
assert_true(!overlapped);
*items_returned = result == X_ERROR_SUCCESS ? 1 : 0;
X_RESULT result = item_count ? X_ERROR_SUCCESS : X_ERROR_NO_MORE_FILES;
if (item_count_ptr) {
assert_zero(overlapped_ptr);
SHIM_SET_MEM_32(item_count_ptr, item_count);
} else if (overlapped_ptr) {
assert_zero(item_count_ptr);
kernel_state->CompleteOverlappedImmediateEx(overlapped_ptr, result, result,
item_count);
result = X_ERROR_IO_PENDING;
return result;
} else if (overlapped) {
assert_true(!items_returned);
kernel_state()->CompleteOverlappedImmediateEx(
overlapped, result, result,
result == X_ERROR_SUCCESS ? e->item_count() : 0);
return X_ERROR_IO_PENDING;
} else {
assert_always();
result = X_ERROR_INVALID_PARAMETER;
return X_ERROR_INVALID_PARAMETER;
}
SHIM_SET_RETURN_32(result);
}
DECLARE_XAM_EXPORT(XamEnumerate, ExportTag::kImplemented);
} // namespace kernel
} // namespace xe
@ -258,6 +251,4 @@ void xe::kernel::xam::RegisterInfoExports(
SHIM_SET_MAPPING("xam.xex", XamAlloc, state);
SHIM_SET_MAPPING("xam.xex", XamFree, state);
SHIM_SET_MAPPING("xam.xex", XamEnumerate, state);
}

View File

@ -79,7 +79,9 @@ class MessageBoxWindow : public el::ModalWindow {
}
bool OnEvent(const el::Event& ev) override {
if (ev.target->IsOfType<el::Button>() && ev.type == el::EventType::kClick) {
if (ev.target->IsOfType<el::Button>() &&
(ev.type == el::EventType::kClick ||
ev.special_key == el::SpecialKey::kEnter)) {
int data_value = ev.target->data.as_integer();
if (data_value) {
*out_chosen_button_ = data_value - 100;
@ -166,6 +168,179 @@ SHIM_CALL XamShowMessageBoxUI_shim(PPCContext* ppc_context,
SHIM_SET_RETURN_32(X_ERROR_IO_PENDING);
}
class KeyboardInputWindow : public el::ModalWindow {
public:
KeyboardInputWindow(xe::threading::Fence* fence)
: ModalWindow([fence]() { fence->Signal(); }) {}
~KeyboardInputWindow() override = default;
// TODO(benvanik): icon.
void Show(el::Element* root_element, std::wstring title,
std::wstring description, std::wstring default_text,
std::wstring* out_text, size_t max_length) {
title_ = std::move(title);
description_ = std::move(description);
default_text_ = std::move(default_text);
out_text_ = out_text;
max_length_ = max_length;
// Incase we're cancelled, set as the default text.
if (out_text) {
*out_text = default_text;
}
ModalWindow::Show(root_element);
EnsureFocus();
}
protected:
void BuildUI() override {
using namespace el::dsl;
set_text(xe::to_string(title_));
LoadNodeTree(
LayoutBoxNode()
.axis(Axis::kY)
.gravity(Gravity::kAll)
.position(LayoutPosition::kLeftTop)
.min_width(300)
.distribution(LayoutDistribution::kAvailable)
.distribution_position(LayoutDistributionPosition::kLeftTop)
.child(LabelNode(xe::to_string(description_).c_str()))
.child(LayoutBoxNode()
.axis(Axis::kX)
.distribution(LayoutDistribution::kGravity)
.child(TextBoxNode()
.id("text_input")
.gravity(Gravity::kLeftRight)
.placeholder(xe::to_string(default_text_))
.min_width(150)
.autofocus(true)))
.child(LayoutBoxNode()
.distribution_position(
LayoutDistributionPosition::kRightBottom)
.child(ButtonNode("OK").id("ok_button"))
.child(ButtonNode("Cancel").id("cancel_button"))));
}
bool OnEvent(const el::Event& ev) override {
if (ev.special_key == el::SpecialKey::kEnter ||
(ev.target->id() == TBIDC("ok_button") &&
ev.type == el::EventType::kClick)) {
// Pressed enter or clicked OK
// Grab the text.
if (out_text_) {
*out_text_ =
xe::to_wstring(GetElementById<el::TextBox>("text_input")->text());
}
Die();
return true;
} else if (ev.target->id() == TBIDC("cancel_button") &&
ev.type == el::EventType::kClick) {
// Cancel.
Die();
return true;
}
return ModalWindow::OnEvent(ev);
}
std::wstring title_;
std::wstring description_;
std::wstring default_text_;
std::wstring* out_text_ = nullptr;
size_t max_length_ = 0;
};
// http://www.se7ensins.com/forums/threads/release-how-to-use-xshowkeyboardui-release.906568/
dword_result_t XamShowKeyboardUI(dword_t r3, dword_t flags,
lpwstring_t default_text, lpwstring_t title,
lpwstring_t description, lpwstring_t buffer,
dword_t buffer_length,
pointer_t<XAM_OVERLAPPED> overlapped) {
// Unknown parameters. I've only seen zero.
assert_zero(r3);
assert_zero(flags);
if (!buffer) {
return X_ERROR_INVALID_PARAMETER;
}
if (FLAGS_headless) {
// Redirect default_text back into the buffer.
std::memset(buffer, 0, buffer_length * 2);
if (default_text) {
xe::store_and_swap<std::wstring>(buffer, default_text.value());
}
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
} else {
return X_ERROR_SUCCESS;
}
}
std::wstring out_text;
auto display_window = kernel_state()->emulator()->display_window();
xe::threading::Fence fence;
display_window->loop()->PostSynchronous([&]() {
auto root_element = display_window->root_element();
auto window = new KeyboardInputWindow(&fence);
window->Show(root_element, title ? title.value() : L"",
description ? description.value() : L"",
default_text ? default_text.value() : L"", &out_text,
buffer_length);
});
fence.Wait();
// Zero the output buffer.
std::memset(buffer, 0, buffer_length * 2);
// Truncate the string.
out_text = out_text.substr(0, buffer_length - 1);
xe::store_and_swap<std::wstring>(buffer, out_text);
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
} else {
return X_ERROR_SUCCESS;
}
}
DECLARE_XAM_EXPORT(XamShowKeyboardUI, ExportTag::kImplemented);
dword_result_t XamShowDeviceSelectorUI(dword_t user_index, dword_t content_type,
dword_t content_flags,
qword_t total_requested,
lpdword_t device_id_ptr,
pointer_t<XAM_OVERLAPPED> overlapped) {
// NOTE: 0xF00D0000 magic from xam_content.cc
switch (content_type) {
case 1: // save game
*device_id_ptr = 0xF00D0000 | 0x0001;
break;
case 2: // marketplace
*device_id_ptr = 0xF00D0000 | 0x0002;
break;
case 3: // title/publisher update?
*device_id_ptr = 0xF00D0000 | 0x0003;
break;
}
if (overlapped) {
kernel_state()->CompleteOverlappedImmediate(overlapped, X_ERROR_SUCCESS);
return X_ERROR_IO_PENDING;
} else {
return X_ERROR_SUCCESS;
}
}
DECLARE_XAM_EXPORT(XamShowDeviceSelectorUI, ExportTag::kImplemented);
class DirtyDiscWindow : public el::ModalWindow {
public:
DirtyDiscWindow(xe::threading::Fence* fence)

View File

@ -40,8 +40,8 @@ XObject::~XObject() {
auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(ptr);
// Free the object creation info
if (header->object_create_info) {
memory()->SystemHeapFree(header->object_create_info);
if (header->object_type_ptr) {
memory()->SystemHeapFree(header->object_type_ptr);
}
memory()->SystemHeapFree(ptr);
@ -241,15 +241,13 @@ uint8_t* XObject::CreateNative(uint32_t size) {
auto header = memory()->TranslateVirtual<X_OBJECT_HEADER*>(mem);
auto creation_info =
memory()->SystemHeapAlloc(sizeof(X_OBJECT_CREATE_INFORMATION));
if (creation_info) {
memory()->Zero(creation_info, sizeof(X_OBJECT_CREATE_INFORMATION));
auto object_type =
memory()->SystemHeapAlloc(sizeof(X_OBJECT_TYPE));
if (object_type) {
// Set it up in the header.
// Some kernel method is accessing this struct and dereferencing a member.
// With our current definition that member is non_paged_pool_charge.
header->object_create_info = creation_info;
// Some kernel method is accessing this struct and dereferencing a member
// @ offset 0x14
header->object_type_ptr = object_type;
}
return memory()->TranslateVirtual(guest_object_ptr_);

View File

@ -63,7 +63,6 @@ struct X_OBJECT_HEADER {
xe::be<uint32_t> handle_count;
xe::be<uint32_t> next_to_free;
};
xe::be<uint32_t> object_type_ptr;
uint8_t name_info_offset;
uint8_t handle_info_offset;
uint8_t quota_info_offset;
@ -72,7 +71,8 @@ struct X_OBJECT_HEADER {
xe::be<uint32_t> object_create_info; // X_OBJECT_CREATE_INFORMATION
xe::be<uint32_t> quota_block_charged;
};
xe::be<uint32_t> security_descriptor;
xe::be<uint32_t> object_type_ptr; // -0x8 POBJECT_TYPE
xe::be<uint32_t> unk_04; // -0x4
// Object lives after this header.
// (There's actually a body field here which is the object itself)
@ -80,19 +80,29 @@ struct X_OBJECT_HEADER {
// http://www.nirsoft.net/kernel_struct/vista/OBJECT_CREATE_INFORMATION.html
struct X_OBJECT_CREATE_INFORMATION {
xe::be<uint32_t> attributes;
xe::be<uint32_t> root_directory_ptr;
xe::be<uint32_t> parse_context_ptr;
xe::be<uint32_t> probe_mode;
xe::be<uint32_t> paged_pool_charge;
xe::be<uint32_t> non_paged_pool_charge;
xe::be<uint32_t> security_descriptor_charge;
xe::be<uint32_t> security_descriptor;
xe::be<uint32_t> security_qos_ptr;
xe::be<uint32_t> attributes; // 0x0
xe::be<uint32_t> root_directory_ptr; // 0x4
xe::be<uint32_t> parse_context_ptr; // 0x8
xe::be<uint32_t> probe_mode; // 0xC
xe::be<uint32_t> paged_pool_charge; // 0x10
xe::be<uint32_t> non_paged_pool_charge; // 0x14
xe::be<uint32_t> security_descriptor_charge; // 0x18
xe::be<uint32_t> security_descriptor; // 0x1C
xe::be<uint32_t> security_qos_ptr; // 0x20
// Security QoS here (SECURITY_QUALITY_OF_SERVICE) too!
};
struct X_OBJECT_TYPE {
xe::be<uint32_t> constructor; // 0x0
xe::be<uint32_t> destructor; // 0x4
xe::be<uint32_t> unk_08; // 0x8
xe::be<uint32_t> unk_0C; // 0xC
xe::be<uint32_t> unk_10; // 0x10
xe::be<uint32_t> unk_14; // 0x14 probably offset from ntobject to keobject
xe::be<uint32_t> pool_tag; // 0x18
};
class XObject {
public:
enum Type {

View File

@ -191,6 +191,17 @@ enum X_FILE_INFORMATION_CLASS {
XFileMaximumInformation
};
// Known as XOVERLAPPED to 360 code.
struct XAM_OVERLAPPED {
xe::be<uint32_t> result; // 0x0
xe::be<uint32_t> length; // 0x4
xe::be<uint32_t> context; // 0x8
xe::be<uint32_t> event; // 0xC
xe::be<uint32_t> completion_routine; // 0x10
xe::be<uint32_t> completion_context; // 0x14
xe::be<uint32_t> extended_error; // 0x18
};
inline uint32_t XOverlappedGetResult(void* ptr) {
auto p = reinterpret_cast<uint32_t*>(ptr);
return xe::load_and_swap<uint32_t>(&p[0]);