Merge branch 'xenia-canary:canary_experimental' into pr_clean
This commit is contained in:
commit
5e055c16a6
|
@ -103,3 +103,6 @@
|
|||
[submodule "third_party/pugixml"]
|
||||
path = third_party/pugixml
|
||||
url = https://github.com/zeux/pugixml.git
|
||||
[submodule "third_party/libusb"]
|
||||
path = third_party/libusb
|
||||
url = https://github.com/libusb/libusb.git
|
||||
|
|
10
premake5.lua
10
premake5.lua
|
@ -7,6 +7,11 @@ location(build_root)
|
|||
targetdir(build_bin)
|
||||
objdir(build_obj)
|
||||
|
||||
-- Define variables for enabling specific submodules
|
||||
-- Todo: Add changing from xb command
|
||||
enableTests = false
|
||||
enableMiscSubprojects = false
|
||||
|
||||
-- Define an ARCH variable
|
||||
-- Only use this to enable architecture-specific functionality.
|
||||
if os.istarget("linux") then
|
||||
|
@ -278,6 +283,10 @@ workspace("xenia")
|
|||
include("third_party/zlib.lua")
|
||||
include("third_party/pugixml.lua")
|
||||
|
||||
if os.istarget("windows") then
|
||||
include("third_party/libusb.lua")
|
||||
end
|
||||
|
||||
if not os.istarget("android") then
|
||||
-- SDL2 requires sdl2-config, and as of November 2020 isn't high-quality on
|
||||
-- Android yet, most importantly in game controllers - the keycode and axis
|
||||
|
@ -312,6 +321,7 @@ workspace("xenia")
|
|||
include("src/xenia/gpu/vulkan")
|
||||
include("src/xenia/hid")
|
||||
include("src/xenia/hid/nop")
|
||||
include("src/xenia/hid/skylander")
|
||||
include("src/xenia/kernel")
|
||||
include("src/xenia/patcher")
|
||||
include("src/xenia/ui")
|
||||
|
|
|
@ -569,6 +569,93 @@ void EmulatorWindow::DisplayConfigDialog::OnDraw(ImGuiIO& io) {
|
|||
}
|
||||
}
|
||||
|
||||
void EmulatorWindow::ContentInstallDialog::OnDraw(ImGuiIO& io) {
|
||||
ImGui::SetNextWindowPos(ImVec2(20, 20), ImGuiCond_FirstUseEver);
|
||||
ImGui::SetNextWindowSize(ImVec2(20, 20), ImGuiCond_FirstUseEver);
|
||||
|
||||
bool dialog_open = true;
|
||||
if (!ImGui::Begin(
|
||||
fmt::format("Installation Progress###{}", window_id_).c_str(),
|
||||
&dialog_open,
|
||||
ImGuiWindowFlags_NoCollapse | ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
Close();
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
|
||||
bool is_everything_installed = true;
|
||||
for (const auto& entry : *installation_entries_) {
|
||||
ImGui::BeginTable(fmt::format("table_{}", entry.name_).c_str(), 2);
|
||||
ImGui::TableNextRow(0);
|
||||
ImGui::TableSetColumnIndex(0);
|
||||
if (entry.icon_) {
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(entry.icon_.get()),
|
||||
ui::default_image_icon_size);
|
||||
} else {
|
||||
ImGui::Dummy(ui::default_image_icon_size);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
ImGui::Text("Name: %s", entry.name_.c_str());
|
||||
ImGui::Text("Installation Path:");
|
||||
ImGui::SameLine();
|
||||
if (ImGui::TextLink(
|
||||
xe::path_to_utf8(entry.data_installation_path_).c_str())) {
|
||||
LaunchFileExplorer(emulator_window_.emulator_->content_root() /
|
||||
entry.data_installation_path_);
|
||||
}
|
||||
|
||||
if (entry.content_type_ != xe::XContentType::kInvalid) {
|
||||
ImGui::Text("Content Type: %s",
|
||||
XContentTypeMap.at(entry.content_type_).c_str());
|
||||
}
|
||||
|
||||
if (entry.installation_result_ != X_ERROR_SUCCESS) {
|
||||
ImGui::Text("Status: %s (0x%08X)",
|
||||
entry.installation_error_message_.c_str(),
|
||||
entry.installation_result_);
|
||||
} else if (entry.currently_installed_size_ == entry.content_size_ &&
|
||||
entry.installation_result_ == X_ERROR_SUCCESS) {
|
||||
ImGui::Text("Status: Success");
|
||||
}
|
||||
ImGui::EndTable();
|
||||
|
||||
if (entry.content_size_ > 0) {
|
||||
ImGui::ProgressBar(static_cast<float>(entry.currently_installed_size_) /
|
||||
entry.content_size_);
|
||||
|
||||
if (entry.currently_installed_size_ != entry.content_size_ &&
|
||||
entry.installation_result_ == X_ERROR_SUCCESS) {
|
||||
is_everything_installed = false;
|
||||
}
|
||||
} else {
|
||||
ImGui::ProgressBar(0.0f);
|
||||
}
|
||||
|
||||
if (installation_entries_->size() > 1) {
|
||||
ImGui::Separator();
|
||||
}
|
||||
}
|
||||
ImGui::Spacing();
|
||||
|
||||
ImGui::BeginDisabled(!is_everything_installed);
|
||||
if (ImGui::Button("Close")) {
|
||||
ImGui::EndDisabled();
|
||||
Close();
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
|
||||
if (!dialog_open && is_everything_installed) {
|
||||
Close();
|
||||
ImGui::End();
|
||||
return;
|
||||
}
|
||||
ImGui::End();
|
||||
}
|
||||
|
||||
bool EmulatorWindow::Initialize() {
|
||||
window_->AddListener(&window_listener_);
|
||||
window_->AddInputListener(&window_listener_, kZOrderEmulatorWindowInput);
|
||||
|
@ -1088,62 +1175,27 @@ void EmulatorWindow::InstallContent() {
|
|||
return;
|
||||
}
|
||||
|
||||
using content_installation_data =
|
||||
std::tuple<X_STATUS, std::string, std::string>;
|
||||
std::map<XContentType, std::vector<content_installation_data>>
|
||||
content_installation_details;
|
||||
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>>
|
||||
content_installation_status =
|
||||
std::make_shared<std::vector<Emulator::ContentInstallEntry>>();
|
||||
|
||||
for (const auto& path : paths) {
|
||||
// Normalize the path and make absolute.
|
||||
auto abs_path = std::filesystem::absolute(path);
|
||||
|
||||
Emulator::ContentInstallationInfo installation_info;
|
||||
auto result = emulator_->InstallContentPackage(abs_path, installation_info);
|
||||
|
||||
auto entry =
|
||||
content_installation_details.find(installation_info.content_type);
|
||||
|
||||
// There is no entry with that specific type of XContent, so we must add it.
|
||||
if (entry == content_installation_details.end()) {
|
||||
content_installation_details.insert({installation_info.content_type, {}});
|
||||
entry = content_installation_details.find(installation_info.content_type);
|
||||
};
|
||||
|
||||
entry->second.push_back({result, installation_info.content_name,
|
||||
installation_info.installation_path});
|
||||
content_installation_status->push_back({path});
|
||||
}
|
||||
|
||||
// Prepare installation process summary message
|
||||
std::string summary = "Installation result: \n";
|
||||
for (auto& entry : *content_installation_status) {
|
||||
emulator_->ProcessContentPackageHeader(entry.path_, entry);
|
||||
}
|
||||
|
||||
for (const auto& content_type : content_installation_details) {
|
||||
if (XContentTypeMap.find(content_type.first) != XContentTypeMap.cend()) {
|
||||
summary += XContentTypeMap.at(content_type.first) + ":\n";
|
||||
} else {
|
||||
summary += "Unknown:\n";
|
||||
auto installationThread = std::thread([this, content_installation_status] {
|
||||
for (auto& entry : *content_installation_status) {
|
||||
emulator_->InstallContentPackage(entry.path_, entry);
|
||||
}
|
||||
});
|
||||
installationThread.detach();
|
||||
|
||||
for (const auto& content_installation_entry : content_type.second) {
|
||||
const std::string status =
|
||||
std::get<0>(content_installation_entry) == X_STATUS_SUCCESS
|
||||
? "Success"
|
||||
: fmt::format("Failed (0x{:08X})",
|
||||
std::get<0>(content_installation_entry));
|
||||
|
||||
summary += fmt::format("\t{} - {} => {}\n", status,
|
||||
std::get<1>(content_installation_entry),
|
||||
std::get<2>(content_installation_entry));
|
||||
}
|
||||
|
||||
summary += "\n";
|
||||
}
|
||||
|
||||
if (content_installation_details.count(XContentType::kProfile)) {
|
||||
emulator_->kernel_state()->xam_state()->profile_manager()->ReloadProfiles();
|
||||
}
|
||||
|
||||
xe::ui::ImGuiDialog::ShowMessageBox(imgui_drawer_.get(),
|
||||
"Content Installation Summary", summary);
|
||||
new ContentInstallDialog(imgui_drawer_.get(), *this,
|
||||
content_installation_status);
|
||||
}
|
||||
|
||||
void EmulatorWindow::ExtractZarchive() {
|
||||
|
|
|
@ -167,6 +167,34 @@ class EmulatorWindow {
|
|||
EmulatorWindow& emulator_window_;
|
||||
};
|
||||
|
||||
class ContentInstallDialog final : public ui::ImGuiDialog {
|
||||
public:
|
||||
ContentInstallDialog(
|
||||
ui::ImGuiDrawer* imgui_drawer, EmulatorWindow& emulator_window,
|
||||
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>> entries)
|
||||
: ui::ImGuiDialog(imgui_drawer),
|
||||
emulator_window_(emulator_window),
|
||||
installation_entries_(entries) {
|
||||
window_id_ = GetWindowId();
|
||||
}
|
||||
|
||||
~ContentInstallDialog() {
|
||||
for (auto& entry : *installation_entries_) {
|
||||
entry.icon_.release();
|
||||
}
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnDraw(ImGuiIO& io) override;
|
||||
|
||||
private:
|
||||
uint64_t window_id_;
|
||||
|
||||
EmulatorWindow& emulator_window_;
|
||||
std::shared_ptr<std::vector<Emulator::ContentInstallEntry>>
|
||||
installation_entries_;
|
||||
};
|
||||
|
||||
class DisplayConfigDialog final : public ui::ImGuiDialog {
|
||||
public:
|
||||
DisplayConfigDialog(ui::ImGuiDrawer* imgui_drawer,
|
||||
|
|
|
@ -54,11 +54,13 @@ project("xenia-app")
|
|||
-- Unified library containing all apps as StaticLibs, not just the main
|
||||
-- emulator windowed app.
|
||||
kind("SharedLib")
|
||||
links({
|
||||
"xenia-gpu-vulkan-trace-viewer",
|
||||
"xenia-hid-demo",
|
||||
"xenia-ui-window-vulkan-demo",
|
||||
})
|
||||
if enableMiscSubprojects then
|
||||
links({
|
||||
"xenia-gpu-vulkan-trace-viewer",
|
||||
"xenia-hid-demo",
|
||||
"xenia-ui-window-vulkan-demo",
|
||||
})
|
||||
end
|
||||
filter(NOT_SINGLE_LIBRARY_FILTER)
|
||||
kind("WindowedApp")
|
||||
|
||||
|
@ -114,15 +116,13 @@ project("xenia-app")
|
|||
"xenia-ui-d3d12",
|
||||
})
|
||||
|
||||
filter({"platforms:Windows", SINGLE_LIBRARY_FILTER})
|
||||
links({
|
||||
"xenia-gpu-d3d12-trace-viewer",
|
||||
"xenia-ui-window-d3d12-demo",
|
||||
})
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
if enableMiscSubprojects then
|
||||
filter({"platforms:Windows", SINGLE_LIBRARY_FILTER})
|
||||
links({
|
||||
"xenia-gpu-d3d12-trace-viewer",
|
||||
"xenia-ui-window-d3d12-demo",
|
||||
})
|
||||
end
|
||||
|
||||
filter("platforms:Windows")
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
|
|
|
@ -95,9 +95,15 @@ UPDATE_from_bool(mount_cache, 2024, 8, 31, 20, false);
|
|||
DEFINE_transient_path(target, "",
|
||||
"Specifies the target .xex or .iso to execute.",
|
||||
"General");
|
||||
#ifndef XE_PLATFORM_WIN32
|
||||
DEFINE_transient_bool(portable, false,
|
||||
"Specifies if Xenia should run in portable mode.",
|
||||
"General");
|
||||
#else
|
||||
DEFINE_transient_bool(portable, true,
|
||||
"Specifies if Xenia should run in portable mode.",
|
||||
"General");
|
||||
#endif
|
||||
|
||||
DECLARE_bool(debug);
|
||||
|
||||
|
@ -421,7 +427,7 @@ bool EmulatorApp::OnInitialize() {
|
|||
if (!cvars::portable &&
|
||||
!std::filesystem::exists(storage_root / "portable.txt")) {
|
||||
storage_root = xe::filesystem::GetUserFolder();
|
||||
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_GNU_LINUX)
|
||||
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_LINUX)
|
||||
storage_root = storage_root / "Xenia";
|
||||
#else
|
||||
// TODO(Triang3l): Point to the app's external storage "files" directory
|
||||
|
|
|
@ -24,6 +24,19 @@ bool CreateParentFolder(const std::filesystem::path& path) {
|
|||
return true;
|
||||
}
|
||||
|
||||
std::error_code CreateFolder(const std::filesystem::path& path) {
|
||||
if (std::filesystem::exists(path)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
std::error_code ec;
|
||||
if (std::filesystem::create_directories(path, ec)) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return ec;
|
||||
}
|
||||
|
||||
std::vector<FileInfo> ListDirectories(const std::filesystem::path& path) {
|
||||
std::vector<FileInfo> files = ListFiles(path);
|
||||
std::vector<FileInfo> directories = {};
|
||||
|
|
|
@ -45,6 +45,10 @@ std::filesystem::path GetUserFolder();
|
|||
// attempting to create it.
|
||||
bool CreateParentFolder(const std::filesystem::path& path);
|
||||
|
||||
// Creates folder on specified path.
|
||||
// If folder already exists it returns success (no error).
|
||||
std::error_code CreateFolder(const std::filesystem::path& path);
|
||||
|
||||
// Creates an empty file at the given path, overwriting if it exists.
|
||||
bool CreateEmptyFile(const std::filesystem::path& path);
|
||||
|
||||
|
|
|
@ -17,4 +17,6 @@ project("xenia-base")
|
|||
"debug_visualizers.natvis",
|
||||
})
|
||||
|
||||
include("testing")
|
||||
if enableTests then
|
||||
include("testing")
|
||||
end
|
|
@ -17,6 +17,7 @@ project("xenia-cpu-ppc-tests")
|
|||
"xenia-base",
|
||||
"xenia-kernel",
|
||||
"xenia-patcher",
|
||||
"xenia-hid-skylander",
|
||||
})
|
||||
files({
|
||||
"ppc_testing_main.cc",
|
||||
|
|
|
@ -21,9 +21,7 @@ project("xenia-cpu")
|
|||
local_platform_files("hir")
|
||||
local_platform_files("ppc")
|
||||
|
||||
include("testing")
|
||||
include("ppc/testing")
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
if enableTests then
|
||||
include("testing")
|
||||
include("ppc/testing")
|
||||
end
|
||||
|
|
|
@ -10,6 +10,7 @@ test_suite("xenia-cpu-tests", project_root, ".", {
|
|||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-hid-skylander",
|
||||
|
||||
-- TODO(benvanik): cut these dependencies?
|
||||
"xenia-kernel",
|
||||
|
|
|
@ -785,53 +785,85 @@ X_STATUS Emulator::DataMigration(const uint64_t xuid) {
|
|||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS Emulator::InstallContentPackage(
|
||||
const std::filesystem::path& path,
|
||||
ContentInstallationInfo& installation_info) {
|
||||
std::unique_ptr<vfs::Device> device =
|
||||
X_STATUS Emulator::ProcessContentPackageHeader(
|
||||
const std::filesystem::path& path, ContentInstallEntry& installation_info) {
|
||||
installation_info.name_ = "Invalid Content Package!";
|
||||
installation_info.content_type_ = XContentType::kInvalid;
|
||||
installation_info.data_installation_path_ = xe::path_to_utf8(path.filename());
|
||||
|
||||
std::unique_ptr<vfs::XContentContainerDevice> device =
|
||||
vfs::XContentContainerDevice::CreateContentDevice("", path);
|
||||
|
||||
installation_info.content_name = "Invalid Content Package!";
|
||||
installation_info.content_type = static_cast<XContentType>(0);
|
||||
installation_info.installation_path = xe::path_to_utf8(path.filename());
|
||||
if (!device || !device->Initialize()) {
|
||||
installation_info.installation_result_ = X_STATUS_INVALID_PARAMETER;
|
||||
installation_info.installation_error_message_ = "Invalid Package Type!";
|
||||
XELOGE("Failed to initialize device");
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
// Always install savefiles to user signed to slot 0.
|
||||
const auto profile =
|
||||
kernel_state_->xam_state()->profile_manager()->GetProfile(
|
||||
static_cast<uint8_t>(0));
|
||||
|
||||
uint64_t xuid = device->xuid();
|
||||
if (device->content_type() ==
|
||||
static_cast<uint32_t>(XContentType::kSavedGame) &&
|
||||
profile) {
|
||||
xuid = profile->xuid();
|
||||
}
|
||||
|
||||
installation_info.data_installation_path_ =
|
||||
fmt::format("{:016X}/{:08X}/{:08X}/{}", xuid, device->title_id(),
|
||||
device->content_type(), path.filename());
|
||||
|
||||
installation_info.header_installation_path_ =
|
||||
fmt::format("{:016X}/{:08X}/Headers/{:08X}/{}", xuid, device->title_id(),
|
||||
device->content_type(), path.filename());
|
||||
|
||||
installation_info.name_ =
|
||||
xe::to_utf8(device->content_header().display_name());
|
||||
installation_info.content_type_ =
|
||||
static_cast<XContentType>(device->content_type());
|
||||
installation_info.content_size_ = device->data_size();
|
||||
|
||||
installation_info.icon_ =
|
||||
imgui_drawer_->LoadImGuiIcon(std::span<const uint8_t>(
|
||||
device->GetContainerHeader()->content_metadata.title_thumbnail,
|
||||
device->GetContainerHeader()->content_metadata.title_thumbnail_size));
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS Emulator::InstallContentPackage(
|
||||
const std::filesystem::path& path, ContentInstallEntry& installation_info) {
|
||||
std::unique_ptr<vfs::XContentContainerDevice> device =
|
||||
vfs::XContentContainerDevice::CreateContentDevice("", path);
|
||||
|
||||
if (!device || !device->Initialize()) {
|
||||
XELOGE("Failed to initialize device");
|
||||
return X_STATUS_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const vfs::XContentContainerDevice* dev =
|
||||
(vfs::XContentContainerDevice*)device.get();
|
||||
const std::filesystem::path installation_path =
|
||||
content_root() / installation_info.data_installation_path_;
|
||||
|
||||
// Always install savefiles to user signed to slot 0.
|
||||
const auto profile =
|
||||
kernel_state_->xam_state()->profile_manager()->GetProfile(
|
||||
static_cast<uint8_t>(0));
|
||||
const std::filesystem::path header_path =
|
||||
content_root() / installation_info.header_installation_path_;
|
||||
|
||||
uint64_t xuid = dev->xuid();
|
||||
if (dev->content_type() == static_cast<uint32_t>(XContentType::kSavedGame) &&
|
||||
profile) {
|
||||
xuid = profile->xuid();
|
||||
if (!std::filesystem::exists(content_root())) {
|
||||
const std::error_code ec = xe::filesystem::CreateFolder(content_root());
|
||||
if (ec) {
|
||||
installation_info.installation_error_message_ = ec.message();
|
||||
installation_info.installation_result_ = X_STATUS_ACCESS_DENIED;
|
||||
return X_STATUS_ACCESS_DENIED;
|
||||
}
|
||||
}
|
||||
|
||||
std::filesystem::path installation_path =
|
||||
content_root() / fmt::format("{:016X}", xuid) /
|
||||
fmt::format("{:08X}", dev->title_id()) /
|
||||
fmt::format("{:08X}", dev->content_type()) / path.filename();
|
||||
|
||||
std::filesystem::path header_path =
|
||||
content_root() / fmt::format("{:016X}", xuid) /
|
||||
fmt::format("{:08X}", dev->title_id()) / "Headers" /
|
||||
fmt::format("{:08X}", dev->content_type()) / path.filename();
|
||||
|
||||
installation_info.installation_path =
|
||||
fmt::format("{:016X}/{:08X}/{:08X}/{}", xuid, dev->title_id(),
|
||||
dev->content_type(), path.filename());
|
||||
|
||||
installation_info.content_name =
|
||||
xe::to_utf8(dev->content_header().display_name());
|
||||
installation_info.content_type =
|
||||
static_cast<XContentType>(dev->content_type());
|
||||
const auto disk_space = std::filesystem::space(content_root());
|
||||
if (disk_space.available < installation_info.content_size_ * 1.1f) {
|
||||
installation_info.installation_error_message_ = "Insufficient disk space!";
|
||||
installation_info.installation_result_ = X_STATUS_DISK_FULL;
|
||||
return X_STATUS_DISK_FULL;
|
||||
}
|
||||
|
||||
if (std::filesystem::exists(installation_path)) {
|
||||
// TODO(Gliniak): Popup
|
||||
|
@ -840,7 +872,9 @@ X_STATUS Emulator::InstallContentPackage(
|
|||
std::error_code error_code;
|
||||
std::filesystem::create_directories(installation_path, error_code);
|
||||
if (error_code) {
|
||||
installation_info.content_name = "Cannot Create Content Directory!";
|
||||
installation_info.installation_error_message_ =
|
||||
"Cannot Create Content Directory!";
|
||||
installation_info.installation_result_ = error_code.value();
|
||||
return error_code.value();
|
||||
}
|
||||
}
|
||||
|
@ -848,13 +882,19 @@ X_STATUS Emulator::InstallContentPackage(
|
|||
vfs::VirtualFileSystem::ExtractContentHeader(device.get(), header_path);
|
||||
|
||||
X_STATUS error_code = vfs::VirtualFileSystem::ExtractContentFiles(
|
||||
device.get(), installation_path);
|
||||
device.get(), installation_path,
|
||||
installation_info.currently_installed_size_);
|
||||
if (error_code != X_ERROR_SUCCESS) {
|
||||
return error_code;
|
||||
}
|
||||
|
||||
installation_info.currently_installed_size_ = installation_info.content_size_;
|
||||
kernel_state()->BroadcastNotification(kXNotificationLiveContentInstalled, 0);
|
||||
|
||||
if (installation_info.content_type_ == XContentType::kProfile) {
|
||||
kernel_state_->xam_state()->profile_manager()->ReloadProfiles();
|
||||
}
|
||||
|
||||
return error_code;
|
||||
}
|
||||
|
||||
|
@ -879,7 +919,9 @@ X_STATUS Emulator::ExtractZarchivePackage(
|
|||
}
|
||||
}
|
||||
|
||||
return vfs::VirtualFileSystem::ExtractContentFiles(device.get(), extract_dir);
|
||||
uint64_t progress = 0;
|
||||
return vfs::VirtualFileSystem::ExtractContentFiles(device.get(), extract_dir,
|
||||
progress);
|
||||
}
|
||||
|
||||
X_STATUS Emulator::CreateZarchivePackage(
|
||||
|
@ -1333,19 +1375,9 @@ std::string Emulator::FindLaunchModule() {
|
|||
}
|
||||
|
||||
static std::string format_version(xex2_version version) {
|
||||
// fmt::format doesn't like bit fields
|
||||
uint32_t major, minor, build, qfe;
|
||||
major = version.major;
|
||||
minor = version.minor;
|
||||
build = version.build;
|
||||
qfe = version.qfe;
|
||||
if (qfe) {
|
||||
return fmt::format("{}.{}.{}.{}", major, minor, build, qfe);
|
||||
}
|
||||
if (build) {
|
||||
return fmt::format("{}.{}.{}", major, minor, build);
|
||||
}
|
||||
return fmt::format("{}.{}", major, minor);
|
||||
// fmt::format doesn't like bit fields we use + to bypass it
|
||||
return fmt::format("{}.{}.{}.{}", +version.major, +version.minor,
|
||||
+version.build, +version.qfe);
|
||||
}
|
||||
|
||||
X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||
|
|
|
@ -26,6 +26,7 @@
|
|||
#include "xenia/memory.h"
|
||||
#include "xenia/patcher/patcher.h"
|
||||
#include "xenia/patcher/plugin_loader.h"
|
||||
#include "xenia/ui/immediate_drawer.h"
|
||||
#include "xenia/vfs/device.h"
|
||||
#include "xenia/vfs/virtual_file_system.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
@ -234,18 +235,32 @@ class Emulator {
|
|||
|
||||
X_STATUS LaunchDefaultModule(const std::filesystem::path& path);
|
||||
|
||||
struct ContentInstallationInfo {
|
||||
XContentType content_type;
|
||||
std::string installation_path;
|
||||
std::string content_name;
|
||||
struct ContentInstallEntry {
|
||||
ContentInstallEntry(std::filesystem::path path) : path_(path) {};
|
||||
|
||||
std::string name_{};
|
||||
std::filesystem::path path_;
|
||||
std::filesystem::path data_installation_path_;
|
||||
std::filesystem::path header_installation_path_;
|
||||
|
||||
uint64_t content_size_ = 0;
|
||||
uint64_t currently_installed_size_ = 0;
|
||||
X_STATUS installation_result_{};
|
||||
std::string installation_error_message_{};
|
||||
XContentType content_type_{};
|
||||
|
||||
std::unique_ptr<ui::ImmediateTexture> icon_;
|
||||
};
|
||||
|
||||
// Migrates data from content to content/xuid with respect to common data.
|
||||
X_STATUS DataMigration(const uint64_t xuid);
|
||||
|
||||
X_STATUS ProcessContentPackageHeader(const std::filesystem::path& path,
|
||||
ContentInstallEntry& installation_info);
|
||||
|
||||
// Extract content of package to content specific directory.
|
||||
X_STATUS InstallContentPackage(const std::filesystem::path& path,
|
||||
ContentInstallationInfo& installation_info);
|
||||
ContentInstallEntry& installation_info);
|
||||
|
||||
// Extract content of zar package to desired directory.
|
||||
X_STATUS ExtractZarchivePackage(const std::filesystem::path& path,
|
||||
|
|
|
@ -19,106 +19,110 @@ project("xenia-gpu-d3d12")
|
|||
"../shaders/bytecode/d3d12_5_1/*.h",
|
||||
})
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-d3d12-trace-viewer")
|
||||
uuid("7b5b9fcb-7bf1-43ff-a774-d4c41c8706be")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-d3d12",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-kernel",
|
||||
"xenia-patcher",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
"xenia-vfs",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"dxbc",
|
||||
"fmt",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
files({
|
||||
"d3d12_trace_viewer_main.cc",
|
||||
"../../ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-viewer.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-viewer.txt",
|
||||
})
|
||||
end
|
||||
|
||||
filter("architecture:x86_64")
|
||||
if enableMiscSubprojects then
|
||||
group("src")
|
||||
project("xenia-gpu-d3d12-trace-viewer")
|
||||
uuid("7b5b9fcb-7bf1-43ff-a774-d4c41c8706be")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-d3d12",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-hid-skylander",
|
||||
"xenia-kernel",
|
||||
"xenia-patcher",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
"xenia-vfs",
|
||||
})
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-d3d12-trace-dump")
|
||||
uuid("686b859c-0046-44c4-a02c-41fc3fb75698")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-d3d12",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-kernel",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
"xenia-vfs",
|
||||
"xenia-patcher",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"dxbc",
|
||||
"fmt",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
files({
|
||||
"d3d12_trace_dump_main.cc",
|
||||
"../../base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-dump.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-dump.txt",
|
||||
})
|
||||
end
|
||||
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"dxbc",
|
||||
"fmt",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
files({
|
||||
"d3d12_trace_viewer_main.cc",
|
||||
"../../ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-viewer.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-viewer.txt",
|
||||
})
|
||||
end
|
||||
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
})
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-d3d12-trace-dump")
|
||||
uuid("686b859c-0046-44c4-a02c-41fc3fb75698")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-d3d12",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-hid-skylander",
|
||||
"xenia-kernel",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
"xenia-vfs",
|
||||
"xenia-patcher",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"dxbc",
|
||||
"fmt",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
files({
|
||||
"d3d12_trace_dump_main.cc",
|
||||
"../../base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-d3d12-trace-dump.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-dump.txt",
|
||||
})
|
||||
end
|
||||
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
})
|
||||
end
|
|
@ -902,7 +902,8 @@ bool COMMAND_PROCESSOR::ExecutePacketType3_EVENT_WRITE_SHD(
|
|||
data_value = GpuSwap(data_value, endianness);
|
||||
uint8_t* write_destination = memory_->TranslatePhysical(address);
|
||||
if (address > 0x1FFFFFFF) {
|
||||
uint32_t writeback_base = register_file_->values[XE_GPU_REG_WRITEBACK_BASE];
|
||||
uint32_t writeback_base =
|
||||
register_file_->values[XE_GPU_REG_WRITEBACK_START];
|
||||
uint32_t writeback_size = register_file_->values[XE_GPU_REG_WRITEBACK_SIZE];
|
||||
uint32_t writeback_offset = address - writeback_base;
|
||||
// check whether the guest has written writeback base. if they haven't, skip
|
||||
|
|
File diff suppressed because it is too large
Load Diff
|
@ -23,130 +23,134 @@ project("xenia-gpu-vulkan")
|
|||
"../shaders/bytecode/vulkan_spirv/*.h",
|
||||
})
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-vulkan-trace-viewer")
|
||||
uuid("86a1dddc-a26a-4885-8c55-cf745225d93e")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-vulkan",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-kernel",
|
||||
"xenia-patcher",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
"xenia-vfs",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"fmt",
|
||||
"glslang-spirv",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"vulkan_trace_viewer_main.cc",
|
||||
"../../ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
|
||||
filter("architecture:x86_64")
|
||||
if enableMiscSubprojects then
|
||||
group("src")
|
||||
project("xenia-gpu-vulkan-trace-viewer")
|
||||
uuid("86a1dddc-a26a-4885-8c55-cf745225d93e")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-vulkan",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-hid-skylander",
|
||||
"xenia-kernel",
|
||||
"xenia-patcher",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
"xenia-vfs",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"fmt",
|
||||
"glslang-spirv",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"vulkan_trace_viewer_main.cc",
|
||||
"../../ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
|
||||
filter("platforms:Linux")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
})
|
||||
|
||||
filter("platforms:Windows")
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-viewer.txt",
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
})
|
||||
end
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-vulkan-trace-dump")
|
||||
uuid("0dd0dd1c-b321-494d-ab9a-6c062f0c65cc")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-vulkan",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-kernel",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
"xenia-vfs",
|
||||
"xenia-patcher",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"fmt",
|
||||
"glslang-spirv",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"vulkan_trace_dump_main.cc",
|
||||
"../../base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
})
|
||||
|
||||
filter("platforms:Linux")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
})
|
||||
|
||||
filter("platforms:Windows")
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-dump.txt",
|
||||
filter("platforms:Linux")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
})
|
||||
end
|
||||
|
||||
filter("platforms:Windows")
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-viewer.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-viewer.txt",
|
||||
})
|
||||
end
|
||||
|
||||
group("src")
|
||||
project("xenia-gpu-vulkan-trace-dump")
|
||||
uuid("0dd0dd1c-b321-494d-ab9a-6c062f0c65cc")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-apu",
|
||||
"xenia-apu-nop",
|
||||
"xenia-base",
|
||||
"xenia-core",
|
||||
"xenia-cpu",
|
||||
"xenia-gpu",
|
||||
"xenia-gpu-vulkan",
|
||||
"xenia-hid",
|
||||
"xenia-hid-nop",
|
||||
"xenia-hid-skylander",
|
||||
"xenia-kernel",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
"xenia-vfs",
|
||||
"xenia-patcher",
|
||||
})
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"fmt",
|
||||
"glslang-spirv",
|
||||
"imgui",
|
||||
"libavcodec",
|
||||
"libavutil",
|
||||
"mspack",
|
||||
"snappy",
|
||||
"xxhash",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"vulkan_trace_dump_main.cc",
|
||||
"../../base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
|
||||
filter("architecture:x86_64")
|
||||
links({
|
||||
"xenia-cpu-backend-x64",
|
||||
})
|
||||
|
||||
filter("platforms:Linux")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
})
|
||||
|
||||
filter("platforms:Windows")
|
||||
-- Only create the .user file if it doesn't already exist.
|
||||
local user_file = project_root.."/build/xenia-gpu-vulkan-trace-dump.vcxproj.user"
|
||||
if not os.isfile(user_file) then
|
||||
debugdir(project_root)
|
||||
debugargs({
|
||||
"2>&1",
|
||||
"1>scratch/stdout-trace-dump.txt",
|
||||
})
|
||||
end
|
||||
end
|
|
@ -16,6 +16,11 @@
|
|||
#include "xenia/hid/input_driver.h"
|
||||
#include "xenia/kernel/util/shim_utils.h"
|
||||
|
||||
#include "xenia/hid/skylander/skylander_emulated.h"
|
||||
#ifdef XE_PLATFORM_WIN32
|
||||
#include "xenia/hid/skylander/skylander_hardware.h"
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
|
@ -28,7 +33,13 @@ DEFINE_double(
|
|||
right_stick_deadzone_percentage, 0.0,
|
||||
"Defines deadzone level for right stick. Allowed range [0.0-1.0].", "HID");
|
||||
|
||||
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {}
|
||||
InputSystem::InputSystem(xe::ui::Window* window) : window_(window) {
|
||||
skylander_portal_ = std::make_unique<SkylanderPortalEmulated>();
|
||||
|
||||
#ifdef XE_PLATFORM_WIN32
|
||||
skylander_portal_ = std::make_unique<SkylanderPortalLibusb>();
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
}
|
||||
|
||||
InputSystem::~InputSystem() = default;
|
||||
|
||||
|
|
|
@ -16,6 +16,7 @@
|
|||
#include "xenia/base/mutex.h"
|
||||
#include "xenia/hid/input.h"
|
||||
#include "xenia/hid/input_driver.h"
|
||||
#include "xenia/hid/skylander/skylander_portal.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
|
@ -55,6 +56,8 @@ class InputSystem {
|
|||
|
||||
uint32_t GetLastUsedSlot() const { return last_used_slot; }
|
||||
|
||||
SkylanderPortal* GetSkylanderPortal() { return skylander_portal_.get(); }
|
||||
|
||||
std::unique_lock<xe_unlikely_mutex> lock();
|
||||
|
||||
private:
|
||||
|
@ -74,6 +77,8 @@ class InputSystem {
|
|||
|
||||
std::vector<std::unique_ptr<InputDriver>> drivers_;
|
||||
|
||||
std::unique_ptr<SkylanderPortal> skylander_portal_;
|
||||
|
||||
std::bitset<XUserMaxUserCount> connected_slots = {};
|
||||
std::array<std::pair<joystick_value, joystick_value>, XUserMaxUserCount>
|
||||
controllers_max_joystick_value = {};
|
||||
|
|
|
@ -8,6 +8,7 @@ project("xenia-hid")
|
|||
language("C++")
|
||||
links({
|
||||
"xenia-base",
|
||||
"xenia-hid-skylander",
|
||||
})
|
||||
defines({
|
||||
})
|
||||
|
|
|
@ -0,0 +1,23 @@
|
|||
project_root = "../../../.."
|
||||
include(project_root.."/tools/build")
|
||||
|
||||
group("src")
|
||||
project("xenia-hid-skylander")
|
||||
uuid("ddc114da-a279-4868-8b20-53108599bd78")
|
||||
kind("StaticLib")
|
||||
language("C++")
|
||||
files({
|
||||
"skylander_portal.h",
|
||||
"skylander_portal.cc",
|
||||
"skylander_emulated.h",
|
||||
"skylander_emulated.cc"
|
||||
})
|
||||
|
||||
filter({"platforms:Windows"})
|
||||
links({
|
||||
"libusb",
|
||||
})
|
||||
files({
|
||||
"skylander_hardware.h",
|
||||
"skylander_hardware.cc"
|
||||
})
|
|
@ -0,0 +1,32 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/hid/skylander/skylander_emulated.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
SkylanderPortalEmulated::SkylanderPortalEmulated() : SkylanderPortal() {}
|
||||
|
||||
SkylanderPortalEmulated::~SkylanderPortalEmulated() {}
|
||||
|
||||
bool SkylanderPortalEmulated::init_device() { return false; }
|
||||
|
||||
void SkylanderPortalEmulated::destroy_device() {}
|
||||
|
||||
X_STATUS SkylanderPortalEmulated::read(std::vector<uint8_t>& data) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
X_STATUS SkylanderPortalEmulated::write(std::vector<uint8_t>& data) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
};
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
|
@ -0,0 +1,34 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_EMULATED_H_
|
||||
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_EMULATED_H_
|
||||
|
||||
#include "xenia/hid/skylander/skylander_portal.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
class SkylanderPortalEmulated final : public SkylanderPortal {
|
||||
public:
|
||||
SkylanderPortalEmulated();
|
||||
~SkylanderPortalEmulated() override;
|
||||
|
||||
X_STATUS read(std::vector<uint8_t>& data) override;
|
||||
X_STATUS write(std::vector<uint8_t>& data) override;
|
||||
|
||||
private:
|
||||
bool init_device() override;
|
||||
void destroy_device() override;
|
||||
};
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
||||
|
||||
#endif
|
|
@ -0,0 +1,121 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/hid/skylander/skylander_hardware.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
SkylanderPortalLibusb::SkylanderPortalLibusb() : SkylanderPortal() {
|
||||
libusb_init(&context_);
|
||||
}
|
||||
|
||||
SkylanderPortalLibusb::~SkylanderPortalLibusb() {
|
||||
if (handle_) {
|
||||
destroy_device();
|
||||
}
|
||||
|
||||
libusb_exit(context_);
|
||||
}
|
||||
|
||||
bool SkylanderPortalLibusb::init_device() {
|
||||
if (!context_) {
|
||||
return false;
|
||||
}
|
||||
|
||||
libusb_device** devs;
|
||||
ssize_t cnt = libusb_get_device_list(context_, &devs);
|
||||
if (cnt < 0) {
|
||||
// No device available... It might appear later.
|
||||
return false;
|
||||
}
|
||||
|
||||
bool device_found = false;
|
||||
for (ssize_t i = 0; i < cnt; ++i) {
|
||||
libusb_device* dev = devs[i];
|
||||
|
||||
struct libusb_device_descriptor desc;
|
||||
if (libusb_get_device_descriptor(dev, &desc) == 0) {
|
||||
// Check if this device matches the target Vendor ID and Product ID
|
||||
if (desc.idVendor == portal_vendor_product_id.first &&
|
||||
desc.idProduct == portal_vendor_product_id.second) {
|
||||
libusb_device_handle* handle;
|
||||
if (libusb_open(dev, &handle) == 0) {
|
||||
libusb_claim_interface(handle, 0);
|
||||
handle_ = reinterpret_cast<uintptr_t*>(handle);
|
||||
device_found = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
libusb_free_device_list(devs, 0);
|
||||
|
||||
return device_found;
|
||||
}
|
||||
|
||||
void SkylanderPortalLibusb::destroy_device() {
|
||||
libusb_release_interface(reinterpret_cast<libusb_device_handle*>(handle_), 0);
|
||||
libusb_close(reinterpret_cast<libusb_device_handle*>(handle_));
|
||||
handle_ = nullptr;
|
||||
}
|
||||
|
||||
X_STATUS SkylanderPortalLibusb::read(std::vector<uint8_t>& data) {
|
||||
if (!is_initialized()) {
|
||||
if (!init_device()) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() > skylander_buffer_size) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const int result = libusb_interrupt_transfer(
|
||||
reinterpret_cast<libusb_device_handle*>(handle_), read_endpoint,
|
||||
data.data(), static_cast<int>(data.size()), nullptr, timeout);
|
||||
|
||||
if (result == LIBUSB_ERROR_NO_DEVICE) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
destroy_device();
|
||||
}
|
||||
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS SkylanderPortalLibusb::write(std::vector<uint8_t>& data) {
|
||||
if (!is_initialized()) {
|
||||
if (!init_device()) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
}
|
||||
|
||||
if (data.size() > skylander_buffer_size) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const int result = libusb_interrupt_transfer(
|
||||
reinterpret_cast<libusb_device_handle*>(handle_), write_endpoint,
|
||||
data.data(), static_cast<int>(data.size()), nullptr, timeout);
|
||||
|
||||
if (result == LIBUSB_ERROR_NO_DEVICE) {
|
||||
return X_ERROR_DEVICE_NOT_CONNECTED;
|
||||
}
|
||||
|
||||
if (result < 0) {
|
||||
destroy_device();
|
||||
}
|
||||
|
||||
return X_ERROR_SUCCESS;
|
||||
};
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
|
@ -0,0 +1,47 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_LIBUSB_H_
|
||||
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_LIBUSB_H_
|
||||
|
||||
// Include order is important here. Including skylander_portal.h after libusb
|
||||
// will cause conflicts.
|
||||
#include "xenia/hid/skylander/skylander_portal.h"
|
||||
|
||||
#include "third_party/libusb/libusb/libusb.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
class SkylanderPortalLibusb final : public SkylanderPortal {
|
||||
public:
|
||||
SkylanderPortalLibusb();
|
||||
~SkylanderPortalLibusb() override;
|
||||
|
||||
X_STATUS read(std::vector<uint8_t>& data) override;
|
||||
X_STATUS write(std::vector<uint8_t>& data) override;
|
||||
|
||||
private:
|
||||
bool init_device() override;
|
||||
void destroy_device() override;
|
||||
|
||||
bool is_initialized() const { return handle_ != nullptr; }
|
||||
|
||||
const uint8_t read_endpoint = 0x81;
|
||||
const uint8_t write_endpoint = 0x02;
|
||||
const uint16_t timeout = 300;
|
||||
|
||||
libusb_context* context_ = nullptr;
|
||||
uintptr_t* handle_ = nullptr;
|
||||
};
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
||||
|
||||
#endif
|
|
@ -0,0 +1,19 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#include "xenia/hid/skylander/skylander_portal.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
SkylanderPortal::SkylanderPortal() {}
|
||||
SkylanderPortal::~SkylanderPortal() {}
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
|
@ -0,0 +1,40 @@
|
|||
/**
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2025 Xenia Canary. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
||||
#ifndef XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_H_
|
||||
#define XENIA_HID_SKYLANDER_SKYLANDER_PORTAL_H_
|
||||
|
||||
#include <vector>
|
||||
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
namespace xe {
|
||||
namespace hid {
|
||||
|
||||
constexpr std::pair<uint16_t, uint16_t> portal_vendor_product_id = {0x1430,
|
||||
0x1F17};
|
||||
constexpr uint8_t skylander_buffer_size = 0x20;
|
||||
|
||||
class SkylanderPortal {
|
||||
public:
|
||||
SkylanderPortal();
|
||||
virtual ~SkylanderPortal();
|
||||
|
||||
virtual X_STATUS read(std::vector<uint8_t>& data) = 0;
|
||||
virtual X_STATUS write(std::vector<uint8_t>& data) = 0;
|
||||
|
||||
private:
|
||||
virtual bool init_device() = 0;
|
||||
virtual void destroy_device() = 0;
|
||||
};
|
||||
|
||||
} // namespace hid
|
||||
} // namespace xe
|
||||
|
||||
#endif
|
|
@ -375,10 +375,10 @@ struct xex2_opt_file_format_info {
|
|||
union xex2_version {
|
||||
uint32_t value;
|
||||
struct {
|
||||
uint32_t major : 4;
|
||||
uint32_t minor : 4;
|
||||
uint32_t build : 16;
|
||||
uint32_t qfe : 8;
|
||||
uint32_t build : 16;
|
||||
uint32_t minor : 4;
|
||||
uint32_t major : 4;
|
||||
};
|
||||
};
|
||||
|
||||
|
|
|
@ -15,10 +15,14 @@
|
|||
#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 for the Kinect
|
||||
/* 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 {
|
||||
|
|
|
@ -661,8 +661,10 @@ dword_result_t XamContentLaunchImageFromFileInternal_entry(
|
|||
const std::filesystem::path host_path =
|
||||
kernel_state()->emulator()->content_root() / entry->name();
|
||||
if (!std::filesystem::exists(host_path)) {
|
||||
uint64_t progress = 0;
|
||||
|
||||
vfs::VirtualFileSystem::ExtractContentFile(
|
||||
entry, kernel_state()->emulator()->content_root(), true);
|
||||
entry, kernel_state()->emulator()->content_root(), progress, true);
|
||||
}
|
||||
|
||||
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
|
||||
|
@ -716,8 +718,9 @@ dword_result_t XamContentLaunchImageInternal_entry(lpvoid_t content_data_ptr,
|
|||
kernel_state()->emulator()->content_root() / entry->name();
|
||||
|
||||
if (!std::filesystem::exists(host_path)) {
|
||||
uint64_t progress = 0;
|
||||
kernel_state()->file_system()->ExtractContentFile(
|
||||
entry, kernel_state()->emulator()->content_root(), true);
|
||||
entry, kernel_state()->emulator()->content_root(), progress, true);
|
||||
}
|
||||
|
||||
auto xam = kernel_state()->GetKernelModule<XamModule>("xam.xex");
|
||||
|
|
|
@ -227,6 +227,44 @@ X_HRESULT_result_t XamUserGetDeviceContext_entry(
|
|||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserGetDeviceContext, kInput, kStub);
|
||||
|
||||
X_HRESULT_result_t XamInputNonControllerGetRaw_entry(
|
||||
lpdword_t state_ptr, lpdword_t buffer_length_ptr, lpdword_t buffer_ptr) {
|
||||
if (!state_ptr || !buffer_length_ptr || !buffer_ptr) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
const uint32_t data_size = *buffer_length_ptr;
|
||||
|
||||
if (data_size == 0 || data_size > 0x20) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto input_system = kernel_state()->emulator()->input_system();
|
||||
|
||||
std::vector<uint8_t> data(data_size, 0);
|
||||
const auto result = input_system->GetSkylanderPortal()->read(data);
|
||||
*state_ptr = 1;
|
||||
memcpy(buffer_ptr, data.data(), data.size());
|
||||
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamInputNonControllerGetRaw, kInput, kStub);
|
||||
|
||||
X_HRESULT_result_t XamInputNonControllerSetRaw_entry(dword_t buffer_length,
|
||||
lpdword_t buffer_ptr) {
|
||||
if (!buffer_ptr || !buffer_length || buffer_length > 0x20) {
|
||||
return X_ERROR_INVALID_PARAMETER;
|
||||
}
|
||||
|
||||
auto input_system = kernel_state()->emulator()->input_system();
|
||||
|
||||
std::vector<uint8_t> data(buffer_length, 0);
|
||||
memcpy(data.data(), buffer_ptr, buffer_length);
|
||||
|
||||
return input_system->GetSkylanderPortal()->write(data);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamInputNonControllerSetRaw, kInput, kStub);
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -20,6 +20,7 @@ namespace kernel {
|
|||
namespace xam {
|
||||
|
||||
std::atomic<int> xam_dialogs_shown_ = {0};
|
||||
std::atomic<int> xam_nui_dialogs_shown_ = {0};
|
||||
|
||||
// FixMe(RodoMa92): Same hack as main_init_posix.cc:40
|
||||
// Force initialization before constructor calling, mimicking
|
||||
|
@ -33,6 +34,7 @@ static std::vector<xe::cpu::Export*>
|
|||
xam_exports(4096);
|
||||
|
||||
bool xeXamIsUIActive() { return xam_dialogs_shown_ > 0; }
|
||||
bool xeXamIsNuiUIActive() { return xam_nui_dialogs_shown_ > 0; }
|
||||
|
||||
XamModule::XamModule(Emulator* emulator, KernelState* kernel_state)
|
||||
: KernelModule(kernel_state, "xe:\\xam.xex"), loader_data_() {
|
||||
|
|
|
@ -22,6 +22,7 @@ namespace kernel {
|
|||
namespace xam {
|
||||
|
||||
bool xeXamIsUIActive();
|
||||
bool xeXamIsNuiUIActive();
|
||||
|
||||
static constexpr std::string_view kXamModuleLoaderDataFileName =
|
||||
"launch_data.bin";
|
||||
|
|
|
@ -2,7 +2,7 @@
|
|||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2022 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2025 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
|
@ -19,13 +19,35 @@
|
|||
#include "xenia/ui/windowed_app_context.h"
|
||||
#include "xenia/xbox.h"
|
||||
|
||||
DEFINE_bool(Allow_nui_initialization, false,
|
||||
"Enable NUI initialization\n"
|
||||
" Only set true when testing kinect games. Certain games may\n"
|
||||
" require avatar implementation.",
|
||||
"Kernel");
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
namespace xam {
|
||||
|
||||
extern std::atomic<int> xam_dialogs_shown_;
|
||||
extern std::atomic<int> xam_nui_dialogs_shown_;
|
||||
|
||||
// https://web.cs.ucdavis.edu/~okreylos/ResDev/Kinect/MainPage.html
|
||||
|
||||
struct X_NUI_DEVICE_STATUS {
|
||||
/* Notes:
|
||||
- for one side func of XamNuiGetDeviceStatus
|
||||
- if some data addressis less than zero then unk1 = it
|
||||
- else another func is called and its return can set unk1 = c0051200 or
|
||||
some value involving DetroitDeviceRequest
|
||||
- next PsCamDeviceRequest is called and if its return is less than zero
|
||||
then X_NUI_DEVICE_STATUS = return of PsCamDeviceRequest
|
||||
- else it equals an unknown local_1c
|
||||
- finally McaDeviceRequest is called and if its return is less than zero
|
||||
then unk2 = return of McaDeviceRequest
|
||||
- else it equals an unknown local_14
|
||||
- status can be set to X_NUI_DEVICE_STATUS[3] | 0x44 or | 0x40
|
||||
*/
|
||||
xe::be<uint32_t> unk0;
|
||||
xe::be<uint32_t> unk1;
|
||||
xe::be<uint32_t> unk2;
|
||||
|
@ -35,23 +57,300 @@ struct X_NUI_DEVICE_STATUS {
|
|||
};
|
||||
static_assert(sizeof(X_NUI_DEVICE_STATUS) == 24, "Size matters");
|
||||
|
||||
void XamNuiGetDeviceStatus_entry(pointer_t<X_NUI_DEVICE_STATUS> status_ptr) {
|
||||
// Get
|
||||
dword_result_t XamNuiGetDeviceStatus_entry(
|
||||
pointer_t<X_NUI_DEVICE_STATUS> status_ptr) {
|
||||
/* Notes:
|
||||
- it does return a value that is not always used
|
||||
- returns values are X_ERROR_SUCCESS, 0xC0050006, and others
|
||||
- 1) On func start *status_ptr = 0, status_ptr->unk1 = 0, status_ptr->unk2
|
||||
= 0, and status_ptr->status = 0
|
||||
- 2) calls XamXStudioRequest(6,&var <- = 0);
|
||||
- if return is greater than -1 && var & 0x80000000 != 0 then set
|
||||
status_ptr->unk1 = 0xC000009D, status_ptr->unk2 = 0xC000009D, and
|
||||
status_ptr->status = status_ptr[3] = 0x20
|
||||
- lots of branching functions after
|
||||
*/
|
||||
|
||||
status_ptr.Zero();
|
||||
status_ptr->status = 0; // Not connected.
|
||||
status_ptr->status = cvars::Allow_nui_initialization;
|
||||
return cvars::Allow_nui_initialization ? X_ERROR_SUCCESS : 0xC0050006;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiGetDeviceStatus, kNone, kStub);
|
||||
|
||||
dword_result_t XamUserNuiGetUserIndex_entry(unknown_t unk, lpdword_t index) {
|
||||
return X_E_NO_SUCH_USER;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserNuiGetUserIndex, kNone, kStub);
|
||||
|
||||
dword_result_t XamUserNuiGetUserIndexForSignin_entry(lpdword_t index) {
|
||||
for (uint32_t i = 0; i < XUserMaxUserCount; i++) {
|
||||
auto profile = kernel_state()->xam_state()->GetUserProfile(i);
|
||||
if (profile) {
|
||||
*index = i;
|
||||
return X_E_SUCCESS;
|
||||
}
|
||||
}
|
||||
|
||||
return X_E_ACCESS_DENIED;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserNuiGetUserIndexForSignin, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamUserNuiGetUserIndexForBind_entry(lpdword_t index) {
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserNuiGetUserIndexForBind, kNone, kStub);
|
||||
|
||||
dword_result_t XamNuiGetDepthCalibration_entry(lpdword_t unk1) {
|
||||
/* Notes:
|
||||
- Possible returns X_STATUS_NO_SUCH_FILE, and 0x10000000
|
||||
*/
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiGetDepthCalibration, kNone, kStub);
|
||||
|
||||
// Skeleton
|
||||
qword_result_t XamNuiSkeletonGetBestSkeletonIndex_entry(int_t unk) {
|
||||
return 0xffffffffffffffff;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiSkeletonGetBestSkeletonIndex, kNone, kStub);
|
||||
|
||||
/* XamNuiCamera Notes
|
||||
- most require message calls to xam in 0x0002Bxxx area
|
||||
*/
|
||||
|
||||
dword_result_t XamNuiCameraTiltGetStatus_entry(lpvoid_t unk) {
|
||||
/* Notes:
|
||||
- Used by XamNuiCameraElevationGetAngle, and XamNuiCameraSetFlags
|
||||
- if it returns anything greater than -1 then both above functions continue
|
||||
- Both funcs send in a param of *unk = 0x50 bytes to copy
|
||||
- unk2
|
||||
- Ghidra decompile fails
|
||||
*/
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiCameraTiltGetStatus, kNone, kStub);
|
||||
|
||||
dword_result_t XamNuiCameraElevationGetAngle_entry(lpqword_t unk1,
|
||||
lpdword_t unk2) {
|
||||
/* Notes:
|
||||
- Xam 12611 does not show what unk1 is used for (Ghidra)
|
||||
*/
|
||||
uint32_t tilt_status[] = {0x58745373, 0x50}; // (XtSs)? & bytes to copy
|
||||
X_STATUS result = XamNuiCameraTiltGetStatus_entry(tilt_status);
|
||||
if (XSUCCEEDED(result)) {
|
||||
// operation here
|
||||
// *unk1 = output1
|
||||
// *unk2 = output2
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiCameraElevationGetAngle, kNone, kStub);
|
||||
|
||||
dword_result_t XamNuiCameraGetTiltControllerType_entry() {
|
||||
/* Notes:
|
||||
- undefined unk[8]
|
||||
- undefined8 local_28;
|
||||
- undefined8 local_20;
|
||||
- undefined8 local_18;
|
||||
- undefined4 local_10;
|
||||
- local_20 = 0;
|
||||
- local_18 = 0;
|
||||
- local_10 = 0;
|
||||
- local_28 = 0xf030000000000;
|
||||
- calls DetroitDeviceRequest(unk) -> result
|
||||
- returns (ulonglong)(LZCOUNT(result) << 0x20) >> 0x25
|
||||
*/
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiCameraGetTiltControllerType, kNone, kStub);
|
||||
|
||||
dword_result_t XamNuiCameraSetFlags_entry(qword_t unk1, dword_t unk2) {
|
||||
/* Notes:
|
||||
- if XamNuiCameraGetTiltControllerType returns 1 then operation is done
|
||||
- else 0xffffffff8007048f
|
||||
*/
|
||||
X_STATUS result = X_E_DEVICE_NOT_CONNECTED;
|
||||
int Controller_Type = XamNuiCameraGetTiltControllerType_entry();
|
||||
|
||||
if (Controller_Type == 1) {
|
||||
uint32_t tilt_status[] = {0x58745373, 0x50}; // (XtSs)? & bytes to copy
|
||||
result = XamNuiCameraTiltGetStatus_entry(tilt_status);
|
||||
if (XSUCCEEDED(result)) {
|
||||
// op here
|
||||
// result =
|
||||
}
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiCameraSetFlags, kNone, kStub);
|
||||
|
||||
dword_result_t XamIsNuiUIActive_entry() { return xeXamIsNuiUIActive(); }
|
||||
DECLARE_XAM_EXPORT1(XamIsNuiUIActive, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamNuiIsDeviceReady_entry() {
|
||||
/* device_state Notes:
|
||||
- used with XNotifyBroadcast(kXNotificationSystemNUIHardwareStatusChanged,
|
||||
device_state)
|
||||
- known values:
|
||||
- 0x0001
|
||||
- 0x0004
|
||||
- 0x0040
|
||||
*/
|
||||
uint16_t device_state = cvars::Allow_nui_initialization ? 1 : 0;
|
||||
return device_state >> 1 & 1;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiIsDeviceReady, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamIsNuiAutomationEnabled_entry(unknown_t unk1, unknown_t unk2) {
|
||||
/* Notes:
|
||||
- XamIsNuiAutomationEnabled = XamIsNatalPlaybackEnabled
|
||||
- Always returns X_E_SUCCESS? Maybe check later versions
|
||||
- Recieves param but never interacts with them
|
||||
- No Operations
|
||||
*/
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT2(XamIsNuiAutomationEnabled, kNone, kStub, kHighFrequency);
|
||||
|
||||
dword_result_t XamIsNatalPlaybackEnabled_entry(unknown_t unk1, unknown_t unk2) {
|
||||
/* Notes:
|
||||
- XamIsNuiAutomationEnabled = XamIsNatalPlaybackEnabled
|
||||
- Always returns X_E_SUCCESS? Maybe check later versions
|
||||
- Recieves param but never interacts with them
|
||||
- No Operations
|
||||
*/
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT2(XamIsNatalPlaybackEnabled, kNone, kStub, kHighFrequency);
|
||||
|
||||
dword_result_t XamNuiIsChatMicEnabled_entry() {
|
||||
/* Notes:
|
||||
- calls a second function with a param of uint local_20 [4];
|
||||
- Second function calls ExGetXConfigSetting(7,9,local_30,0x1c,local_40);
|
||||
- Result is sent to *local_20[0] = ^
|
||||
- Once sent back to XamNuiIsChatMicEnabled it looks for byte that
|
||||
correlates to NUI mic setting
|
||||
- return uVar2 = (~(ulonglong)local_20[0] << 0x20) >> 0x23 & 1;
|
||||
- unless the second function returns something -1 or less then
|
||||
XamNuiIsChatMicEnabled 1
|
||||
*/
|
||||
return false;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiIsChatMicEnabled, kNone, kImplemented);
|
||||
|
||||
/* HUD Notes:
|
||||
- XamNuiHudGetEngagedTrackingID, XamNuiHudIsEnabled,
|
||||
XamNuiHudSetEngagedTrackingID, XamNuiHudInterpretFrame, and
|
||||
XamNuiHudGetEngagedEnrollmentIndex all utilize the same data address
|
||||
- engaged_tracking_id set second param of XamShowNuiTroubleshooterUI
|
||||
*/
|
||||
uint32_t nui_unknown_1 = 0;
|
||||
uint32_t engaged_tracking_id = 0;
|
||||
char nui_unknown_2 = '\0';
|
||||
|
||||
dword_result_t XamNuiHudSetEngagedTrackingID_entry(dword_t id) {
|
||||
if (!id) {
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
if (nui_unknown_1 != 0) {
|
||||
engaged_tracking_id = id;
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiHudSetEngagedTrackingID, kNone, kImplemented);
|
||||
|
||||
qword_result_t XamNuiHudGetEngagedTrackingID_entry() {
|
||||
if (nui_unknown_1 != 0) {
|
||||
return engaged_tracking_id;
|
||||
}
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiHudGetEngagedTrackingID, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamNuiHudIsEnabled_entry() {
|
||||
/* Notes:
|
||||
- checks if XamNuiIsDeviceReady false, if nui_unknown_1 exists, and
|
||||
nui_unknown_2 is equal to null terminated string
|
||||
- only returns true if one check fails and allows for other NUI functions
|
||||
to progress
|
||||
*/
|
||||
bool result = XamNuiIsDeviceReady_entry();
|
||||
if (nui_unknown_1 != 0 && nui_unknown_2 != '\0' && result) {
|
||||
return true;
|
||||
}
|
||||
return false;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiHudIsEnabled, kNone, kImplemented);
|
||||
|
||||
uint32_t XeXamNuiHudCheck(dword_t unk1) {
|
||||
uint32_t check = XamNuiHudIsEnabled_entry();
|
||||
if (check == 0) {
|
||||
return X_ERROR_ACCESS_DENIED;
|
||||
}
|
||||
|
||||
check = XamNuiHudSetEngagedTrackingID_entry(unk1);
|
||||
if (check != 0) {
|
||||
return X_ERROR_FUNCTION_FAILED;
|
||||
}
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
dword_result_t XamNuiHudGetInitializeFlags_entry() {
|
||||
/* HUD_Flags Notes:
|
||||
- set by 0x2B003
|
||||
- set to 0 by unnamed func alongside version_id
|
||||
- known values:
|
||||
- 0x40000000
|
||||
- 0x200
|
||||
*/
|
||||
return 0;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiHudGetInitializeFlags, kNone, kImplemented);
|
||||
|
||||
void XamNuiHudGetVersions_entry(lpqword_t unk1, lpqword_t unk2) {
|
||||
/* version_id Notes:
|
||||
- set by 0x2B003
|
||||
- set to 0 by unnamed func alongside HUD_Flags
|
||||
*/
|
||||
if (unk1) {
|
||||
*unk1 = 0;
|
||||
}
|
||||
if (unk2) {
|
||||
*unk2 = 0;
|
||||
}
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiHudGetVersions, kNone, kImplemented);
|
||||
|
||||
// UI
|
||||
dword_result_t XamShowNuiTroubleshooterUI_entry(unknown_t unk1, unknown_t unk2,
|
||||
dword_t flag) {
|
||||
/* Notes:
|
||||
- unk1 is 0xFF - possibly user index?
|
||||
- unk2 appear to always be zero.
|
||||
- First calls XamPackageManagerGetExperienceMode and checks if the return
|
||||
is less than zero
|
||||
- If less than zero then returns error message below
|
||||
- else it checks if flag = 0x800000 if it does then call
|
||||
XamNuiGetDeviceStatus. if not return error
|
||||
- calls XamPackageManagerGetExperienceMode(&var) with var = 1
|
||||
- If returns less than zero or (var & 1) == 0 then get error message:
|
||||
- if XamPackageManagerGetExperienceMode = 0 then call XamShowMessageBoxUI
|
||||
- if XamShowMessageBoxUI returns 0x3e5 then XamShowNuiTroubleshooterUI
|
||||
returns 0
|
||||
- else XamShowNuiTroubleshooterUI returns 0x65b and call another func
|
||||
- else:
|
||||
- call XamNuiHudSetEngagedTrackingID(unk2) and doesn't care aboot return
|
||||
and set var2 = 2
|
||||
- checks if (flag & 0x800000) == 0
|
||||
- if true call XamNuiGetDeviceStatus.
|
||||
- if XamNuiGetDeviceStatus != 0 set var2 = 3
|
||||
- else var2 = 4
|
||||
- XamAppRequestLoadEx(var2);
|
||||
- if return = 0 then XamShowNuiTroubleshooterUI returns 5
|
||||
- else set buffer[8] and call
|
||||
XMsgSystemProcessCall(0xfe,0x21028,buffer,0xc);
|
||||
- XamNuiNatalCameraUpdateComplete calls
|
||||
XamShowNuiTroubleshooterUI(0xff,0,0) if param = -0x7ff8fffe
|
||||
*/
|
||||
|
||||
if (cvars::headless) {
|
||||
|
@ -75,7 +374,7 @@ dword_result_t XamShowNuiTroubleshooterUI_entry(unknown_t unk1, unknown_t unk2,
|
|||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowNuiTroubleshooterUI, kNone, kStub);
|
||||
|
||||
|
@ -88,6 +387,86 @@ dword_result_t XamShowNuiHardwareRequiredUI_entry(unknown_t unk1) {
|
|||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowNuiHardwareRequiredUI, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamShowNuiGuideUI_entry(unknown_t unk1, unknown_t unk2) {
|
||||
/* Notes:
|
||||
- calls an unnamed function that checks XamNuiHudIsEnabled and
|
||||
XamNuiHudSetEngagedTrackingID
|
||||
- if XamNuiHudIsEnabled returns false then fuctions fails return
|
||||
X_ERROR_ACCESS_DENIED
|
||||
- else calls XamNuiHudSetEngagedTrackingID and if returns less than 0 then
|
||||
returns X_ERROR_FUNCTION_FAILED
|
||||
- else return X_ERROR_SUCCESS
|
||||
- if return offunc is X_ERROR_SUCCESS then call up ui screen
|
||||
- else return value of func
|
||||
*/
|
||||
|
||||
// decompiler error stops me from knowing which param gets used here
|
||||
uint32_t result = XeXamNuiHudCheck(0);
|
||||
if (!result) {
|
||||
// operations here
|
||||
// XMsgSystemProcessCall(0xfe,0x21030, undefined local_30[8] ,0xc);
|
||||
}
|
||||
return result;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowNuiGuideUI, kNone, kStub);
|
||||
|
||||
/* XamNuiIdentity Notes:
|
||||
- most require message calls to xam in 0x0002Cxxx area
|
||||
*/
|
||||
uint64_t NUI_Session_Id = 0;
|
||||
|
||||
qword_result_t XamNuiIdentityGetSessionId_entry() {
|
||||
if (NUI_Session_Id == 0) {
|
||||
// xboxkrnl::XeCryptRandom_entry(NUI_Session_Id, 8);
|
||||
NUI_Session_Id = 0xDEADF00DDEADF00D;
|
||||
}
|
||||
return NUI_Session_Id;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiIdentityGetSessionId, kNone, kImplemented);
|
||||
|
||||
dword_result_t XamNuiIdentityEnrollForSignIn_entry(dword_t unk1, qword_t unk2,
|
||||
qword_t unk3, dword_t unk4) {
|
||||
/* Notes:
|
||||
- Decompiler issues so double check
|
||||
*/
|
||||
if (XamNuiHudIsEnabled_entry() == false) {
|
||||
return X_E_FAIL;
|
||||
}
|
||||
// buffer [2]
|
||||
// buffer[0] = unk
|
||||
// var = unk4
|
||||
// return func(0xfe,0x2c010,buffer,0xc,unk3);
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiIdentityEnrollForSignIn, kNone, kStub);
|
||||
|
||||
dword_result_t XamNuiIdentityAbort_entry(dword_t unk) {
|
||||
if (XamNuiHudIsEnabled_entry() == false) {
|
||||
return X_E_FAIL;
|
||||
}
|
||||
// buffer [4]
|
||||
// buffer[0] = unk
|
||||
// return func(0xfe,0x2c00e,buffer,4,0)
|
||||
return X_E_FAIL;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiIdentityAbort, kNone, kStub);
|
||||
|
||||
// Other
|
||||
dword_result_t XamUserNuiEnableBiometric_entry(dword_t user_index,
|
||||
int_t enable) {
|
||||
return X_E_INVALIDARG;
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamUserNuiEnableBiometric, kNone, kStub);
|
||||
|
||||
void XamNuiPlayerEngagementUpdate_entry(qword_t unk1, unknown_t unk2,
|
||||
lpunknown_t unk3) {
|
||||
/* Notes:
|
||||
- Only calls a second function with the params unk3, 0, and 0x1c in that
|
||||
order
|
||||
*/
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamNuiPlayerEngagementUpdate, kNone, kStub);
|
||||
|
||||
} // namespace xam
|
||||
} // namespace kernel
|
||||
} // namespace xe
|
||||
|
|
|
@ -19,6 +19,7 @@ namespace kernel {
|
|||
namespace xam {
|
||||
|
||||
bool xeXamIsUIActive();
|
||||
bool xeXamIsNuiUIActive();
|
||||
|
||||
xe::cpu::Export* RegisterExport_xam(xe::cpu::Export* export_entry);
|
||||
|
||||
|
|
|
@ -58,8 +58,6 @@ namespace xam {
|
|||
|
||||
extern std::atomic<int> xam_dialogs_shown_;
|
||||
|
||||
constexpr ImVec2 default_image_icon_size = ImVec2(75.f, 75.f);
|
||||
|
||||
class XamDialog : public xe::ui::ImGuiDialog {
|
||||
public:
|
||||
void set_close_callback(std::function<void()> close_callback) {
|
||||
|
@ -509,7 +507,8 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
: XamDialog(imgui_drawer),
|
||||
drawing_position_(drawing_position),
|
||||
title_info_(*title_info),
|
||||
profile_(profile) {
|
||||
profile_(profile),
|
||||
window_id_(GetWindowId()) {
|
||||
LoadAchievementsData();
|
||||
}
|
||||
|
||||
|
@ -616,9 +615,9 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
const auto icon = GetIcon(achievement_entry);
|
||||
if (icon) {
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(GetIcon(achievement_entry)),
|
||||
default_image_icon_size);
|
||||
ui::default_image_icon_size);
|
||||
} else {
|
||||
ImGui::Dummy(default_image_icon_size);
|
||||
ImGui::Dummy(ui::default_image_icon_size);
|
||||
}
|
||||
ImGui::TableNextColumn();
|
||||
|
||||
|
@ -632,7 +631,7 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
GetAchievementDescription(achievement_entry).c_str());
|
||||
ImGui::PopTextWrapPos();
|
||||
|
||||
ImGui::SetCursorPosY(start_drawing_pos.y + default_image_icon_size.x -
|
||||
ImGui::SetCursorPosY(start_drawing_pos.y + ui::default_image_icon_size.x -
|
||||
ImGui::GetTextLineHeight());
|
||||
|
||||
if (achievement_entry.IsUnlocked()) {
|
||||
|
@ -644,7 +643,8 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
// TODO(Gliniak): There is no easy way to align text to middle, so I have to
|
||||
// do it manually.
|
||||
const float achievement_row_middle_alignment =
|
||||
((default_image_icon_size.x / 2.f) - ImGui::GetTextLineHeight() / 2.f) *
|
||||
((ui::default_image_icon_size.x / 2.f) -
|
||||
ImGui::GetTextLineHeight() / 2.f) *
|
||||
0.85f;
|
||||
|
||||
ImGui::SetCursorPosY(ImGui::GetCursorPosY() +
|
||||
|
@ -667,10 +667,13 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
|
||||
bool dialog_open = true;
|
||||
|
||||
if (!ImGui::Begin(fmt::format("{} Achievements List",
|
||||
xe::to_utf8(title_info_.title_name))
|
||||
.c_str(),
|
||||
&dialog_open,
|
||||
std::string title_name = xe::to_utf8(title_info_.title_name);
|
||||
title_name.erase(std::remove(title_name.begin(), title_name.end(), '\0'),
|
||||
title_name.end());
|
||||
|
||||
const std::string window_name =
|
||||
fmt::format("{} Achievements###{}", title_name, window_id_);
|
||||
if (!ImGui::Begin(window_name.c_str(), &dialog_open,
|
||||
ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
|
@ -688,7 +691,7 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
if (ImGui::BeginTable("", 3,
|
||||
ImGuiTableFlags_::ImGuiTableFlags_BordersInnerH)) {
|
||||
for (const auto& entry : achievements_info_) {
|
||||
ImGui::TableNextRow(0, default_image_icon_size.y);
|
||||
ImGui::TableNextRow(0, ui::default_image_icon_size.y);
|
||||
DrawTitleAchievementInfo(io, entry);
|
||||
}
|
||||
|
||||
|
@ -707,6 +710,7 @@ class GameAchievementsDialog final : public XamDialog {
|
|||
|
||||
bool show_locked_info_ = false;
|
||||
|
||||
uint64_t window_id_;
|
||||
const ImVec2 drawing_position_ = {};
|
||||
|
||||
const TitleInfo title_info_;
|
||||
|
@ -724,7 +728,8 @@ class GamesInfoDialog final : public XamDialog {
|
|||
drawing_position_(drawing_position),
|
||||
profile_(profile),
|
||||
profile_manager_(kernel_state()->xam_state()->profile_manager()),
|
||||
dialog_name_(fmt::format("{}'s Games List", profile->name())) {
|
||||
dialog_name_(fmt::format("{}'s Games List###{}", profile->name(),
|
||||
GetWindowId())) {
|
||||
LoadProfileGameInfo(imgui_drawer, profile);
|
||||
}
|
||||
|
||||
|
@ -762,9 +767,9 @@ class GamesInfoDialog final : public XamDialog {
|
|||
|
||||
if (title_icon.count(entry.id)) {
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(title_icon.at(entry.id).get()),
|
||||
default_image_icon_size);
|
||||
ui::default_image_icon_size);
|
||||
} else {
|
||||
ImGui::Dummy(default_image_icon_size);
|
||||
ImGui::Dummy(ui::default_image_icon_size);
|
||||
}
|
||||
|
||||
// Second Column
|
||||
|
@ -779,7 +784,7 @@ class GamesInfoDialog final : public XamDialog {
|
|||
entry.title_earned_gamerscore)
|
||||
.c_str());
|
||||
|
||||
ImGui::SetCursorPosY(start_position.y + default_image_icon_size.y -
|
||||
ImGui::SetCursorPosY(start_position.y + ui::default_image_icon_size.y -
|
||||
ImGui::GetTextLineHeight());
|
||||
|
||||
if (entry.WasTitlePlayed()) {
|
||||
|
@ -881,7 +886,7 @@ class GamesInfoDialog final : public XamDialog {
|
|||
|
||||
if (ImGui::BeginTable("", 2,
|
||||
ImGuiTableFlags_::ImGuiTableFlags_BordersInnerH)) {
|
||||
ImGui::TableNextRow(0, default_image_icon_size.y);
|
||||
ImGui::TableNextRow(0, ui::default_image_icon_size.y);
|
||||
for (auto& entry : info_) {
|
||||
std::string filter(title_name_filter_);
|
||||
if (!filter.empty()) {
|
||||
|
@ -1564,9 +1569,10 @@ bool xeDrawProfileContent(ui::ImGuiDrawer* imgui_drawer, const uint64_t xuid,
|
|||
// In the future it can be replaced with profile icon.
|
||||
const auto icon = imgui_drawer->GetNotificationIcon(user_index);
|
||||
if (icon && user_index < XUserMaxUserCount) {
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(icon), default_image_icon_size);
|
||||
ImGui::Image(reinterpret_cast<ImTextureID>(icon),
|
||||
ui::default_image_icon_size);
|
||||
} else {
|
||||
ImGui::Dummy(default_image_icon_size);
|
||||
ImGui::Dummy(ui::default_image_icon_size);
|
||||
}
|
||||
|
||||
ImGui::SameLine();
|
||||
|
@ -1935,6 +1941,75 @@ class SigninDialog : public XamDialog {
|
|||
char gamertag_[16] = "";
|
||||
};
|
||||
|
||||
class CreateProfileDialog final : public XamDialog {
|
||||
public:
|
||||
CreateProfileDialog(ui::ImGuiDrawer* imgui_drawer, Emulator* emulator)
|
||||
: XamDialog(imgui_drawer), emulator_(emulator) {
|
||||
memset(gamertag_, 0, sizeof(gamertag_));
|
||||
}
|
||||
|
||||
protected:
|
||||
void OnDraw(ImGuiIO& io) override;
|
||||
|
||||
bool has_opened_ = false;
|
||||
char gamertag_[16] = "";
|
||||
Emulator* emulator_;
|
||||
};
|
||||
|
||||
void CreateProfileDialog::OnDraw(ImGuiIO& io) {
|
||||
if (!has_opened_) {
|
||||
ImGui::OpenPopup("Create Profile");
|
||||
has_opened_ = true;
|
||||
}
|
||||
|
||||
auto profile_manager =
|
||||
emulator_->kernel_state()->xam_state()->profile_manager();
|
||||
|
||||
bool dialog_open = true;
|
||||
if (!ImGui::BeginPopupModal("Create Profile", &dialog_open,
|
||||
ImGuiWindowFlags_NoCollapse |
|
||||
ImGuiWindowFlags_AlwaysAutoResize |
|
||||
ImGuiWindowFlags_HorizontalScrollbar)) {
|
||||
Close();
|
||||
return;
|
||||
}
|
||||
|
||||
if (ImGui::IsWindowFocused(ImGuiFocusedFlags_RootAndChildWindows) &&
|
||||
!ImGui::IsAnyItemActive() && !ImGui::IsMouseClicked(0)) {
|
||||
ImGui::SetKeyboardFocusHere(0);
|
||||
}
|
||||
|
||||
ImGui::TextUnformatted("Gamertag:");
|
||||
ImGui::InputText("##Gamertag", gamertag_, sizeof(gamertag_));
|
||||
|
||||
const std::string gamertag_string = std::string(gamertag_);
|
||||
bool valid = profile_manager->IsGamertagValid(gamertag_string);
|
||||
|
||||
ImGui::BeginDisabled(!valid);
|
||||
if (ImGui::Button("Create")) {
|
||||
if (!profile_manager->CreateProfile(gamertag_string, false)) {
|
||||
XELOGE("Failed to create profile: {}", gamertag_string);
|
||||
}
|
||||
std::fill(std::begin(gamertag_), std::end(gamertag_), '\0');
|
||||
dialog_open = false;
|
||||
}
|
||||
ImGui::EndDisabled();
|
||||
ImGui::SameLine();
|
||||
|
||||
if (ImGui::Button("Cancel")) {
|
||||
std::fill(std::begin(gamertag_), std::end(gamertag_), '\0');
|
||||
dialog_open = false;
|
||||
}
|
||||
|
||||
if (!dialog_open) {
|
||||
ImGui::CloseCurrentPopup();
|
||||
Close();
|
||||
ImGui::EndPopup();
|
||||
return;
|
||||
}
|
||||
ImGui::EndPopup();
|
||||
}
|
||||
|
||||
X_RESULT xeXamShowSigninUI(uint32_t user_index, uint32_t users_needed,
|
||||
uint32_t flags) {
|
||||
// Mask values vary. Probably matching user types? Local/remote?
|
||||
|
@ -1967,6 +2042,21 @@ X_RESULT xeXamShowSigninUI(uint32_t user_index, uint32_t users_needed,
|
|||
new SigninDialog(imgui_drawer, users_needed), close);
|
||||
}
|
||||
|
||||
X_RESULT xeXamShowCreateProfileUIEx(uint32_t user_index, dword_t unkn,
|
||||
char* unkn2_ptr) {
|
||||
Emulator* emulator = kernel_state()->emulator();
|
||||
ui::ImGuiDrawer* imgui_drawer = emulator->imgui_drawer();
|
||||
|
||||
if (cvars::headless) {
|
||||
return X_ERROR_SUCCESS;
|
||||
}
|
||||
|
||||
auto close = [](CreateProfileDialog* dialog) -> void {};
|
||||
|
||||
return xeXamDispatchDialogAsync<CreateProfileDialog>(
|
||||
new CreateProfileDialog(imgui_drawer, emulator), close);
|
||||
}
|
||||
|
||||
dword_result_t XamShowSigninUI_entry(dword_t users_needed, dword_t flags) {
|
||||
return xeXamShowSigninUI(XUserIndexAny, users_needed, flags);
|
||||
}
|
||||
|
@ -1978,6 +2068,17 @@ dword_result_t XamShowSigninUIp_entry(dword_t user_index, dword_t users_needed,
|
|||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowSigninUIp, kUserProfiles, kImplemented);
|
||||
|
||||
dword_result_t XamShowCreateProfileUIEx_entry(dword_t user_index, dword_t unkn,
|
||||
lpstring_t unkn2_ptr) {
|
||||
return xeXamShowCreateProfileUIEx(user_index, unkn, unkn2_ptr);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowCreateProfileUIEx, kUserProfiles, kImplemented);
|
||||
|
||||
dword_result_t XamShowCreateProfileUI_entry(dword_t user_index, dword_t unkn) {
|
||||
return xeXamShowCreateProfileUIEx(user_index, unkn, 0);
|
||||
}
|
||||
DECLARE_XAM_EXPORT1(XamShowCreateProfileUI, kUserProfiles, kImplemented);
|
||||
|
||||
dword_result_t XamShowAchievementsUI_entry(dword_t user_index,
|
||||
dword_t unk_mask) {
|
||||
auto user = kernel_state()->xam_state()->GetUserProfile(user_index);
|
||||
|
|
|
@ -10,33 +10,30 @@ project("xenia-ui-d3d12")
|
|||
"xenia-base",
|
||||
"xenia-ui",
|
||||
})
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
-- filter {}
|
||||
local_platform_files()
|
||||
files({
|
||||
"../shaders/bytecode/d3d12_5_1/*.h",
|
||||
})
|
||||
|
||||
group("demos")
|
||||
project("xenia-ui-window-d3d12-demo")
|
||||
uuid("3b9686a7-0f04-4e17-8b00-aeb78ae1107c")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"imgui",
|
||||
"xenia-base",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
})
|
||||
files({
|
||||
"../window_demo.cc",
|
||||
"d3d12_window_demo.cc",
|
||||
project_root.."/src/xenia/ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
if enableMiscSubprojects then
|
||||
group("demos")
|
||||
project("xenia-ui-window-d3d12-demo")
|
||||
uuid("3b9686a7-0f04-4e17-8b00-aeb78ae1107c")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"imgui",
|
||||
"xenia-base",
|
||||
"xenia-ui",
|
||||
"xenia-ui-d3d12",
|
||||
})
|
||||
files({
|
||||
"../window_demo.cc",
|
||||
"d3d12_window_demo.cc",
|
||||
project_root.."/src/xenia/ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
end
|
|
@ -16,9 +16,12 @@
|
|||
namespace xe {
|
||||
namespace ui {
|
||||
|
||||
uint64_t ImGuiDialog::next_window_id_ = 0;
|
||||
|
||||
ImGuiDialog::ImGuiDialog(ImGuiDrawer* imgui_drawer)
|
||||
: imgui_drawer_(imgui_drawer) {
|
||||
imgui_drawer_->AddDialog(this);
|
||||
next_window_id_++;
|
||||
}
|
||||
|
||||
ImGuiDialog::~ImGuiDialog() {
|
||||
|
|
|
@ -40,6 +40,7 @@ class ImGuiDialog {
|
|||
ImGuiDrawer* imgui_drawer() const { return imgui_drawer_; }
|
||||
ImGuiIO& GetIO();
|
||||
|
||||
uint64_t GetWindowId() const { return next_window_id_; }
|
||||
// Closes the dialog and returns to any waiters.
|
||||
void Close();
|
||||
|
||||
|
@ -48,6 +49,8 @@ class ImGuiDialog {
|
|||
virtual void OnDraw(ImGuiIO& io) {}
|
||||
|
||||
private:
|
||||
static uint64_t next_window_id_;
|
||||
|
||||
ImGuiDrawer* imgui_drawer_ = nullptr;
|
||||
bool has_close_pending_ = false;
|
||||
std::vector<xe::threading::Fence*> waiting_fences_;
|
||||
|
|
|
@ -234,6 +234,25 @@ std::optional<ImGuiKey> ImGuiDrawer::VirtualKeyToImGuiKey(VirtualKey vkey) {
|
|||
}
|
||||
}
|
||||
|
||||
std::unique_ptr<ImmediateTexture> ImGuiDrawer::LoadImGuiIcon(
|
||||
std::span<const uint8_t> data) {
|
||||
if (!immediate_drawer_) {
|
||||
return {};
|
||||
}
|
||||
|
||||
int width, height, channels;
|
||||
unsigned char* image_data =
|
||||
stbi_load_from_memory(data.data(), static_cast<int>(data.size()), &width,
|
||||
&height, &channels, STBI_rgb_alpha);
|
||||
if (!image_data) {
|
||||
return {};
|
||||
}
|
||||
|
||||
return immediate_drawer_->CreateTexture(
|
||||
width, height, ImmediateTextureFilter::kLinear, true,
|
||||
reinterpret_cast<uint8_t*>(image_data));
|
||||
}
|
||||
|
||||
std::map<uint32_t, std::unique_ptr<ImmediateTexture>> ImGuiDrawer::LoadIcons(
|
||||
IconsData data) {
|
||||
std::map<uint32_t, std::unique_ptr<ImmediateTexture>> icons_;
|
||||
|
@ -242,21 +261,9 @@ std::map<uint32_t, std::unique_ptr<ImmediateTexture>> ImGuiDrawer::LoadIcons(
|
|||
return icons_;
|
||||
}
|
||||
|
||||
int width, height, channels;
|
||||
|
||||
for (const auto& icon : data) {
|
||||
unsigned char* image_data = stbi_load_from_memory(
|
||||
icon.second.data(), static_cast<int>(icon.second.size()), &width,
|
||||
&height, &channels, STBI_rgb_alpha);
|
||||
|
||||
if (!image_data) {
|
||||
continue;
|
||||
}
|
||||
icons_[icon.first] = (immediate_drawer_->CreateTexture(
|
||||
width, height, ImmediateTextureFilter::kLinear, true,
|
||||
reinterpret_cast<uint8_t*>(image_data)));
|
||||
icons_[icon.first] = LoadImGuiIcon(icon.second);
|
||||
}
|
||||
|
||||
return icons_;
|
||||
}
|
||||
|
||||
|
|
|
@ -37,6 +37,8 @@ class Window;
|
|||
|
||||
using IconsData = std::map<uint32_t, std::span<const uint8_t>>;
|
||||
|
||||
constexpr ImVec2 default_image_icon_size = ImVec2(75.f, 75.f);
|
||||
|
||||
class ImGuiDrawer : public WindowInputListener, public UIDrawer {
|
||||
public:
|
||||
ImGuiDrawer(Window* window, size_t z_order);
|
||||
|
@ -64,6 +66,8 @@ class ImGuiDrawer : public WindowInputListener, public UIDrawer {
|
|||
void ClearDialogs();
|
||||
void EnableNotifications(bool enable) { are_notifications_enabled_ = enable; }
|
||||
|
||||
std::unique_ptr<ImmediateTexture> LoadImGuiIcon(
|
||||
std::span<const uint8_t> data);
|
||||
std::map<uint32_t, std::unique_ptr<ImmediateTexture>> LoadIcons(
|
||||
IconsData data);
|
||||
|
||||
|
|
|
@ -14,10 +14,6 @@ project("xenia-ui")
|
|||
local_platform_files()
|
||||
removefiles({"*_demo.cc"})
|
||||
removefiles({"windowed_app_main_*.cc"})
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
filter("platforms:Android-*")
|
||||
-- Exports JNI functions.
|
||||
wholelib("On")
|
||||
|
|
|
@ -10,11 +10,6 @@ project("xenia-ui-vulkan")
|
|||
"xenia-base",
|
||||
"xenia-ui",
|
||||
})
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
-- filter {}
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
|
@ -24,33 +19,35 @@ project("xenia-ui-vulkan")
|
|||
"../shaders/bytecode/vulkan_spirv/*.h",
|
||||
})
|
||||
|
||||
group("demos")
|
||||
project("xenia-ui-window-vulkan-demo")
|
||||
uuid("97598f13-3177-454c-8e58-c59e2b6ede27")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"imgui",
|
||||
"xenia-base",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"../window_demo.cc",
|
||||
"vulkan_window_demo.cc",
|
||||
project_root.."/src/xenia/ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
|
||||
filter("platforms:Linux")
|
||||
if enableMiscSubprojects then
|
||||
group("demos")
|
||||
project("xenia-ui-window-vulkan-demo")
|
||||
uuid("97598f13-3177-454c-8e58-c59e2b6ede27")
|
||||
single_library_windowed_app_kind()
|
||||
language("C++")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
"fmt",
|
||||
"imgui",
|
||||
"xenia-base",
|
||||
"xenia-ui",
|
||||
"xenia-ui-vulkan",
|
||||
})
|
||||
includedirs({
|
||||
project_root.."/third_party/Vulkan-Headers/include",
|
||||
})
|
||||
files({
|
||||
"../window_demo.cc",
|
||||
"vulkan_window_demo.cc",
|
||||
project_root.."/src/xenia/ui/windowed_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
|
||||
filter("platforms:Linux")
|
||||
links({
|
||||
"X11",
|
||||
"xcb",
|
||||
"X11-xcb",
|
||||
})
|
||||
end
|
|
@ -15,7 +15,8 @@
|
|||
namespace xe {
|
||||
namespace vfs {
|
||||
|
||||
std::unique_ptr<Device> XContentContainerDevice::CreateContentDevice(
|
||||
std::unique_ptr<XContentContainerDevice>
|
||||
XContentContainerDevice::CreateContentDevice(
|
||||
const std::string_view mount_path, const std::filesystem::path& host_path) {
|
||||
if (!std::filesystem::exists(host_path)) {
|
||||
XELOGE("Path to XContent container does not exist: {}", host_path);
|
||||
|
|
|
@ -31,7 +31,7 @@ class XContentContainerDevice : public Device {
|
|||
public:
|
||||
constexpr static uint32_t kBlockSize = 0x1000;
|
||||
|
||||
static std::unique_ptr<Device> CreateContentDevice(
|
||||
static std::unique_ptr<XContentContainerDevice> CreateContentDevice(
|
||||
const std::string_view mount_path,
|
||||
const std::filesystem::path& host_path);
|
||||
|
||||
|
@ -74,6 +74,10 @@ class XContentContainerDevice : public Device {
|
|||
return final_license;
|
||||
}
|
||||
|
||||
const XContentContainerHeader* GetContainerHeader() const {
|
||||
return header_.get();
|
||||
}
|
||||
|
||||
protected:
|
||||
XContentContainerDevice(const std::string_view mount_path,
|
||||
const std::filesystem::path& host_path);
|
||||
|
@ -106,10 +110,6 @@ class XContentContainerDevice : public Device {
|
|||
|
||||
const std::filesystem::path& GetHostPath() const { return host_path_; }
|
||||
|
||||
const XContentContainerHeader* GetContainerHeader() const {
|
||||
return header_.get();
|
||||
}
|
||||
|
||||
std::string name_;
|
||||
std::filesystem::path host_path_;
|
||||
|
||||
|
|
|
@ -7,35 +7,37 @@ project("xenia-vfs")
|
|||
kind("StaticLib")
|
||||
language("C++")
|
||||
links({
|
||||
"xenia-base", "zstd", "zarchive"
|
||||
"xenia-base",
|
||||
"zstd",
|
||||
"zarchive"
|
||||
})
|
||||
defines({
|
||||
})
|
||||
-- filter({"configurations:Release", "platforms:Windows"})
|
||||
-- buildoptions({
|
||||
-- "/O1",
|
||||
-- })
|
||||
-- filter {}
|
||||
|
||||
recursive_platform_files()
|
||||
removefiles({"vfs_dump.cc"})
|
||||
|
||||
project("xenia-vfs-dump")
|
||||
uuid("2EF270C7-41A8-4D0E-ACC5-59693A9CCE32")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"xenia-base",
|
||||
"xenia-vfs",
|
||||
})
|
||||
defines({})
|
||||
if enableMiscSubprojects then
|
||||
project("xenia-vfs-dump")
|
||||
uuid("2EF270C7-41A8-4D0E-ACC5-59693A9CCE32")
|
||||
kind("ConsoleApp")
|
||||
language("C++")
|
||||
links({
|
||||
"fmt",
|
||||
"xenia-base",
|
||||
"xenia-vfs",
|
||||
})
|
||||
defines({})
|
||||
|
||||
files({
|
||||
"vfs_dump.cc",
|
||||
project_root.."/src/xenia/base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
include("testing")
|
||||
files({
|
||||
"vfs_dump.cc",
|
||||
project_root.."/src/xenia/base/console_app_main_"..platform_suffix..".cc",
|
||||
})
|
||||
resincludedirs({
|
||||
project_root,
|
||||
})
|
||||
end
|
||||
|
||||
if enableTests then
|
||||
include("testing")
|
||||
end
|
||||
|
|
|
@ -44,7 +44,10 @@ int vfs_dump_main(const std::vector<std::string>& args) {
|
|||
XELOGE("Failed to initialize device");
|
||||
return 1;
|
||||
}
|
||||
return VirtualFileSystem::ExtractContentFiles(device.get(), base_path);
|
||||
|
||||
uint64_t progress = 0;
|
||||
return VirtualFileSystem::ExtractContentFiles(device.get(), base_path,
|
||||
progress);
|
||||
}
|
||||
|
||||
} // namespace vfs
|
||||
|
|
|
@ -335,6 +335,7 @@ X_STATUS VirtualFileSystem::OpenFile(Entry* root_entry,
|
|||
|
||||
X_STATUS VirtualFileSystem::ExtractContentFile(Entry* entry,
|
||||
std::filesystem::path base_path,
|
||||
uint64_t& progress,
|
||||
bool extract_to_root) {
|
||||
// Allocate a buffer when needed.
|
||||
size_t buffer_size = 0;
|
||||
|
@ -369,27 +370,33 @@ X_STATUS VirtualFileSystem::ExtractContentFile(Entry* entry,
|
|||
in_file->Destroy();
|
||||
return 1;
|
||||
}
|
||||
constexpr size_t write_buffer_size = 4_MiB;
|
||||
|
||||
if (entry->can_map()) {
|
||||
auto map = entry->OpenMapped(xe::MappedMemory::Mode::kRead);
|
||||
fwrite(map->data(), map->size(), 1, file);
|
||||
|
||||
auto remaining_size = map->size();
|
||||
auto offset = 0;
|
||||
|
||||
while (remaining_size > 0) {
|
||||
fwrite(map->data() + offset, write_buffer_size, 1, file);
|
||||
offset += write_buffer_size;
|
||||
remaining_size -= write_buffer_size;
|
||||
}
|
||||
map->Close();
|
||||
} else {
|
||||
// Can't map the file into memory. Read it into a temporary buffer.
|
||||
if (!buffer || entry->size() > buffer_size) {
|
||||
// Resize the buffer.
|
||||
if (buffer) {
|
||||
delete[] buffer;
|
||||
}
|
||||
auto remaining_size = entry->size();
|
||||
size_t offset = 0;
|
||||
buffer = new uint8_t[write_buffer_size];
|
||||
|
||||
// Allocate a buffer rounded up to the nearest 512MB.
|
||||
buffer_size = xe::round_up(entry->size(), 512_MiB);
|
||||
buffer = new uint8_t[buffer_size];
|
||||
while (remaining_size > 0) {
|
||||
size_t bytes_read = 0;
|
||||
in_file->ReadSync(buffer, write_buffer_size, offset, &bytes_read);
|
||||
fwrite(buffer, bytes_read, 1, file);
|
||||
offset += bytes_read;
|
||||
remaining_size -= bytes_read;
|
||||
progress += bytes_read;
|
||||
}
|
||||
|
||||
size_t bytes_read = 0;
|
||||
in_file->ReadSync(buffer, entry->size(), 0, &bytes_read);
|
||||
fwrite(buffer, bytes_read, 1, file);
|
||||
}
|
||||
|
||||
fclose(file);
|
||||
|
@ -401,8 +408,9 @@ X_STATUS VirtualFileSystem::ExtractContentFile(Entry* entry,
|
|||
return 0;
|
||||
}
|
||||
|
||||
X_STATUS VirtualFileSystem::ExtractContentFiles(
|
||||
Device* device, std::filesystem::path base_path) {
|
||||
X_STATUS VirtualFileSystem::ExtractContentFiles(Device* device,
|
||||
std::filesystem::path base_path,
|
||||
uint64_t& progress) {
|
||||
// Run through all the files, breadth-first style.
|
||||
std::queue<vfs::Entry*> queue;
|
||||
auto root = device->ResolvePath("/");
|
||||
|
@ -415,7 +423,7 @@ X_STATUS VirtualFileSystem::ExtractContentFiles(
|
|||
queue.push(entry.get());
|
||||
}
|
||||
|
||||
ExtractContentFile(entry, base_path);
|
||||
ExtractContentFile(entry, base_path, progress);
|
||||
}
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -51,9 +51,11 @@ class VirtualFileSystem {
|
|||
|
||||
static X_STATUS ExtractContentFile(Entry* entry,
|
||||
std::filesystem::path base_path,
|
||||
uint64_t& progress,
|
||||
bool extract_to_root = false);
|
||||
static X_STATUS ExtractContentFiles(Device* device,
|
||||
std::filesystem::path base_path);
|
||||
std::filesystem::path base_path,
|
||||
uint64_t& progress);
|
||||
static void ExtractContentHeader(Device* device,
|
||||
std::filesystem::path base_path);
|
||||
|
||||
|
|
|
@ -67,6 +67,7 @@ typedef uint32_t X_STATUS;
|
|||
#define X_STATUS_THREAD_IS_TERMINATING ((X_STATUS)0xC000004BL)
|
||||
#define X_STATUS_PROCEDURE_NOT_FOUND ((X_STATUS)0xC000007AL)
|
||||
#define X_STATUS_INVALID_IMAGE_FORMAT ((X_STATUS)0xC000007BL)
|
||||
#define X_STATUS_DISK_FULL ((X_STATUS)0xC000007FL)
|
||||
#define X_STATUS_INSUFFICIENT_RESOURCES ((X_STATUS)0xC000009AL)
|
||||
#define X_STATUS_MEMORY_NOT_ALLOCATED ((X_STATUS)0xC00000A0L)
|
||||
#define X_STATUS_FILE_IS_A_DIRECTORY ((X_STATUS)0xC00000BAL)
|
||||
|
@ -108,6 +109,7 @@ typedef uint32_t X_RESULT;
|
|||
#define X_ERROR_DEVICE_NOT_CONNECTED X_RESULT_FROM_WIN32(0x0000048FL)
|
||||
#define X_ERROR_NOT_FOUND X_RESULT_FROM_WIN32(0x00000490L)
|
||||
#define X_ERROR_CANCELLED X_RESULT_FROM_WIN32(0x000004C7L)
|
||||
#define X_ERROR_ABORTED X_RESULT_FROM_WIN32(0x000004D3L)
|
||||
#define X_ERROR_NOT_LOGGED_ON X_RESULT_FROM_WIN32(0x000004DDL)
|
||||
#define X_ERROR_NO_SUCH_USER X_RESULT_FROM_WIN32(0x00000525L)
|
||||
#define X_ERROR_FUNCTION_FAILED X_RESULT_FROM_WIN32(0x0000065BL)
|
||||
|
@ -273,7 +275,7 @@ constexpr uint8_t XUserIndexAny = 0xFF;
|
|||
// https://github.com/ThirteenAG/Ultimate-ASI-Loader/blob/master/source/xlive/xliveless.h
|
||||
typedef uint32_t XNotificationID;
|
||||
enum : XNotificationID {
|
||||
/* Notes:
|
||||
/* XNotification Notes:
|
||||
- Notification Ids are split into three Sections: Area, Version, and
|
||||
Message Id.
|
||||
- Each Area has the potential to hold 65535 unique notifications as it
|
||||
|
@ -292,6 +294,12 @@ enum : XNotificationID {
|
|||
kXNotifyAll = 0x000000EF,
|
||||
|
||||
// XNotification System
|
||||
/* System Notes:
|
||||
- for some functions if XamIsNuiUIActive returns false then
|
||||
XNotifyBroadcast(kXNotificationSystemNUIPause, unk data) is called
|
||||
- XNotifyBroadcast(kXNotificationSystemNUIHardwareStatusChanged,
|
||||
device_state)
|
||||
*/
|
||||
kXNotificationSystemUI = 0x00000009,
|
||||
kXNotificationSystemSignInChanged = 0x0000000A,
|
||||
kXNotificationSystemStorageDevicesChanged = 0x0000000B,
|
||||
|
@ -310,7 +318,7 @@ enum : XNotificationID {
|
|||
kXNotificationSystemNUIBindingChanged = 0x0006001D,
|
||||
kXNotificationSystemAudioLatencyChanged = 0x0008001E,
|
||||
kXNotificationSystemNUIChatBindingChanged = 0x0008001F,
|
||||
kXNotificationSystemInputActivityChanged = 0x00009020,
|
||||
kXNotificationSystemInputActivityChanged = 0x00090020,
|
||||
|
||||
// XNotification Live
|
||||
kXNotificationLiveConnectionChanged = 0x02000001,
|
||||
|
@ -331,9 +339,18 @@ enum : XNotificationID {
|
|||
kXNotificationCustomGamercard = 0x06010004,
|
||||
|
||||
// XNotification Dvd ?
|
||||
kXNotificationDvdDriveUnknown = 0x80000003,
|
||||
/* Dvd Drive? Notes:
|
||||
- after XamLoaderGetMediaInfoEx(media_type?, title_id?, unk) is used for
|
||||
some funcs the first param is used with
|
||||
XNotifyBroadcast(kXNotificationDvdDriveTrayStateChanged, media_type?)
|
||||
- after XamLoaderGetMediaInfoEx(media_type?, title_id?, unk) is used for
|
||||
some funcs the third param is used with
|
||||
XNotifyBroadcast(kXNotificationDvdDriveUnknown2, unk)
|
||||
*/
|
||||
kXNotificationDvdDriveUnknown1 = 0x80000003,
|
||||
kXNotificationDvdDriveUnknownDashContext = 0x8000000C,
|
||||
kXNotificationDvdDriveTrayStateChanged = 0x8000000D,
|
||||
kXNotificationDvdDriveUnknown2 = 0x80010014,
|
||||
|
||||
// XNotification XMP
|
||||
kXNotificationXmpStateChanged = 0x0A000001,
|
||||
|
|
|
@ -0,0 +1 @@
|
|||
Subproject commit a61afe5f75d969c4561a1d0ad753aa23cee6329a
|
|
@ -0,0 +1,46 @@
|
|||
group("third_party")
|
||||
project("libusb")
|
||||
uuid("5f8b5485-fde5-4a42-8a13-8545fcf6d25b")
|
||||
kind("StaticLib")
|
||||
language("C")
|
||||
defines({
|
||||
"_LIB",
|
||||
})
|
||||
includedirs({"libusb/libusb/"})
|
||||
|
||||
files({
|
||||
"libusb/libusb/core.c",
|
||||
"libusb/libusb/descriptor.c",
|
||||
"libusb/libusb/hotplug.c",
|
||||
"libusb/libusb/io.c",
|
||||
"libusb/libusb/strerror.c",
|
||||
"libusb/libusb/sync.c",
|
||||
})
|
||||
|
||||
filter({"platforms:Windows"})
|
||||
includedirs({"libusb/msvc/"})
|
||||
files({
|
||||
"libusb/libusb/os/events_windows.c",
|
||||
"libusb/libusb/os/events_windows.h",
|
||||
"libusb/libusb/os/threads_windows.c",
|
||||
"libusb/libusb/os/threads_windows.h",
|
||||
"libusb/libusb/os/windows_common.c",
|
||||
"libusb/libusb/os/windows_common.h",
|
||||
"libusb/libusb/os/windows_usbdk.c",
|
||||
"libusb/libusb/os/windows_usbdk.h",
|
||||
"libusb/libusb/os/windows_winusb.c",
|
||||
"libusb/libusb/os/windows_winusb.h"
|
||||
})
|
||||
|
||||
filter({"platforms:Linux"})
|
||||
files({
|
||||
"libusb/libusb/config.h",
|
||||
"libusb/libusb/os/events_posix.c",
|
||||
"libusb/libusb/os/events_posix.h",
|
||||
"libusb/libusb/os/threads_posix.c",
|
||||
"libusb/libusb/os/threads_posix.h",
|
||||
"libusb/libusb/os/linux_netlink.c",
|
||||
"libusb/libusb/os/linux_udev.c",
|
||||
"libusb/libusb/os/linux_usbfs.c",
|
||||
"libusb/libusb/os/linux_usbfs.h"
|
||||
})
|
Loading…
Reference in New Issue