/** ****************************************************************************** * Xenia : Xbox 360 Emulator Research Project * ****************************************************************************** * Copyright 2021 Ben Vanik. All rights reserved. * * Released under the BSD license - see LICENSE in the root for more details. * ****************************************************************************** */ #include "xenia/kernel/xam/apps/xam_app.h" #include "xenia/base/logging.h" #include "xenia/base/threading.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/xam/xam_content_device.h" #include "xenia/kernel/xenumerator.h" /* Notes: - Messages ids that start with 0x00021xxx are UI calls - Messages ids that start with 0x00023xxx are used for the user profile - Messages ids that start with 0x0002Bxxx are used by the Kinect device usually for camera related functions - Messages ids that start with 0x0002Cxxx are used by the XamNuiIdentity functions */ namespace xe { namespace kernel { namespace xam { namespace apps { XamApp::XamApp(KernelState* kernel_state) : App(kernel_state, 0xFE) {} X_HRESULT XamApp::DispatchMessageSync(uint32_t message, uint32_t buffer_ptr, uint32_t buffer_length) { // NOTE: buffer_length may be zero or valid. auto buffer = memory_->TranslateVirtual(buffer_ptr); switch (message) { case 0x0002000E: { struct message_data { xe::be user_index; xe::be unk_04; xe::be extra_ptr; xe::be buffer_ptr; xe::be buffer_size; xe::be unk_14; xe::be length_ptr; xe::be unk_1C; }* data = reinterpret_cast(buffer); XELOGD( "XamAppEnumerateContentAggregate({}, {:08X}, {:08X}, {:08X}, {}, " "{:08X}, {:08X}, {:08X})", (uint32_t)data->user_index, (uint32_t)data->unk_04, (uint32_t)data->extra_ptr, (uint32_t)data->buffer_ptr, (uint32_t)data->buffer_size, (uint32_t)data->unk_14, (uint32_t)data->length_ptr, (uint32_t)data->unk_1C); if (!data->buffer_ptr || !data->extra_ptr) { return X_E_INVALIDARG; } auto extra = memory_->TranslateVirtual( data->extra_ptr); auto buffer = memory_->TranslateVirtual(data->buffer_ptr); auto e = kernel_state_->object_table()->LookupObject( extra->handle); if (!e) { return X_E_INVALIDARG; } assert_true(extra->magic == kXObjSignature); if (data->buffer_size) { std::memset(buffer, 0, data->buffer_size); } uint32_t item_count = 0; auto result = e->WriteItems(data->buffer_ptr, buffer, &item_count); if (result == X_ERROR_SUCCESS && item_count >= 1) { if (data->length_ptr) { auto length_ptr = memory_->TranslateVirtual*>(data->length_ptr); *length_ptr = 1; } return X_E_SUCCESS; } return X_E_NO_MORE_FILES; } case 0x00020021: { struct XContentQueryVolumeDeviceType { char root_name[64]; xe::be is_title_process; xe::be device_type_ptr; xe::be overlapped_ptr; }* data = reinterpret_cast(buffer); assert_true(buffer_length == sizeof(XContentQueryVolumeDeviceType)); xe::be* device_type_ptr = memory_->TranslateVirtual*>( static_cast(data->device_type_ptr.get())); switch (kernel_state_->deployment_type_) { case XDeploymentType::kGoD: case XDeploymentType::kHardDrive: { *device_type_ptr = DeviceType::HDD; } break; case XDeploymentType::kOpticalDisc: { *device_type_ptr = DeviceType::ODD; } break; default: { *device_type_ptr = DeviceType::Invalid; } break; } XELOGD("XContentQueryVolumeDeviceType('{}', {:08X}, {:08X}, {:08X})", data->root_name, static_cast(data->is_title_process.get()), static_cast(data->device_type_ptr.get()), static_cast(data->overlapped_ptr.get())); return X_E_SUCCESS; } case 0x00021012: { uint32_t enabled = xe::load_and_swap(buffer); XELOGD("XEnableGuestSignin: {}", enabled ? "true" : "false"); return X_E_SUCCESS; } case 0x00022005: { struct message_data { xe::be deployment_type_ptr; xe::be overlapped_ptr; }* data = reinterpret_cast(buffer); assert_true(buffer_length == sizeof(message_data)); auto deployment_type = memory_->TranslateVirtual(data->deployment_type_ptr); *deployment_type = static_cast(kernel_state_->deployment_type_); XELOGD("XTitleGetDeploymentType({:08X}, {:08X}", data->deployment_type_ptr.get(), data->overlapped_ptr.get()); return X_E_SUCCESS; } case 0x0002B003: { // Games used in: // 4D5309C9 XELOGD("XamUnk2B003({:08X}, {:08X}), unimplemented", buffer_ptr, buffer_length); return X_E_SUCCESS; } } XELOGE( "Unimplemented XAM message app={:08X}, msg={:08X}, arg1={:08X}, " "arg2={:08X}", app_id(), message, buffer_ptr, buffer_length); return X_E_FAIL; } } // namespace apps } // namespace xam } // namespace kernel } // namespace xe