Merge remote-tracking branch 'GliniakRepo/xam_swap_disc' into canary_experimental
This commit is contained in:
@@ -40,6 +40,7 @@
|
||||
#include "xenia/kernel/xbdm/xbdm_module.h"
|
||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_module.h"
|
||||
#include "xenia/memory.h"
|
||||
#include "xenia/ui/file_picker.h"
|
||||
#include "xenia/ui/imgui_dialog.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
#include "xenia/ui/window.h"
|
||||
@@ -48,7 +49,6 @@
|
||||
#include "xenia/vfs/devices/host_path_device.h"
|
||||
#include "xenia/vfs/devices/null_device.h"
|
||||
#include "xenia/vfs/devices/stfs_container_device.h"
|
||||
#include "xenia/vfs/virtual_file_system.h"
|
||||
|
||||
DEFINE_double(time_scalar, 1.0,
|
||||
"Scalar used to speed or slow time (1x, 2x, 1/2x, etc).",
|
||||
@@ -267,19 +267,56 @@ X_STATUS Emulator::TerminateTitle() {
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
const std::unique_ptr<vfs::Device> Emulator::CreateVfsDeviceBasedOnPath(
|
||||
const std::filesystem::path& path, const std::string_view mount_path) {
|
||||
if (!path.has_extension()) {
|
||||
return std::make_unique<vfs::StfsContainerDevice>(mount_path, path);
|
||||
}
|
||||
auto extension = xe::utf8::lower_ascii(xe::path_to_utf8(path.extension()));
|
||||
if (extension == ".xex" || extension == ".elf" || extension == ".exe") {
|
||||
auto parent_path = path.parent_path();
|
||||
return std::make_unique<vfs::HostPathDevice>(mount_path, parent_path, true);
|
||||
} else {
|
||||
return std::make_unique<vfs::DiscImageDevice>(mount_path, path);
|
||||
}
|
||||
}
|
||||
|
||||
X_STATUS Emulator::MountPath(const std::filesystem::path& path,
|
||||
const std::string_view mount_path) {
|
||||
auto device = CreateVfsDeviceBasedOnPath(path, mount_path);
|
||||
if (!device->Initialize()) {
|
||||
xe::FatalError("Unable to mount {}; file not found or corrupt.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
if (!file_system_->RegisterDevice(std::move(device))) {
|
||||
xe::FatalError("Unable to register {}.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
file_system_->UnregisterSymbolicLink("d:");
|
||||
file_system_->UnregisterSymbolicLink("game:");
|
||||
// Create symlinks to the device.
|
||||
file_system_->RegisterSymbolicLink("game:", mount_path);
|
||||
file_system_->RegisterSymbolicLink("d:", mount_path);
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
||||
X_STATUS Emulator::LaunchPath(const std::filesystem::path& path) {
|
||||
// Launch based on file type.
|
||||
// This is a silly guess based on file extension.
|
||||
if (!path.has_extension()) {
|
||||
// Likely an STFS container.
|
||||
MountPath(path, "\\Device\\Cdrom0");
|
||||
return LaunchStfsContainer(path);
|
||||
};
|
||||
auto extension = xe::utf8::lower_ascii(xe::path_to_utf8(path.extension()));
|
||||
if (extension == ".xex" || extension == ".elf" || extension == ".exe") {
|
||||
// Treat as a naked xex file.
|
||||
MountPath(path, "\\Device\\Harddisk0\\Partition1");
|
||||
return LaunchXexFile(path);
|
||||
} else {
|
||||
// Assume a disc image.
|
||||
MountPath(path, "\\Device\\Cdrom0");
|
||||
return LaunchDiscImage(path);
|
||||
}
|
||||
}
|
||||
@@ -291,26 +328,6 @@ X_STATUS Emulator::LaunchXexFile(const std::filesystem::path& path) {
|
||||
// \\Device\\Harddisk0\\Partition1
|
||||
// and then get that symlinked to game:\, so
|
||||
// -> game:\foo.xex
|
||||
|
||||
auto mount_path = "\\Device\\Harddisk0\\Partition1";
|
||||
|
||||
// Register the local directory in the virtual filesystem.
|
||||
auto parent_path = path.parent_path();
|
||||
auto device =
|
||||
std::make_unique<vfs::HostPathDevice>(mount_path, parent_path, true);
|
||||
if (!device->Initialize()) {
|
||||
XELOGE("Unable to scan host path");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
if (!file_system_->RegisterDevice(std::move(device))) {
|
||||
XELOGE("Unable to register host path");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
// Create symlinks to the device.
|
||||
file_system_->RegisterSymbolicLink("game:", mount_path);
|
||||
file_system_->RegisterSymbolicLink("d:", mount_path);
|
||||
|
||||
// Get just the filename (foo.xex).
|
||||
auto file_name = path.filename();
|
||||
|
||||
@@ -320,47 +337,11 @@ X_STATUS Emulator::LaunchXexFile(const std::filesystem::path& path) {
|
||||
}
|
||||
|
||||
X_STATUS Emulator::LaunchDiscImage(const std::filesystem::path& path) {
|
||||
auto mount_path = "\\Device\\Cdrom0";
|
||||
|
||||
// Register the disc image in the virtual filesystem.
|
||||
auto device = std::make_unique<vfs::DiscImageDevice>(mount_path, path);
|
||||
if (!device->Initialize()) {
|
||||
xe::FatalError("Unable to mount disc image; file not found or corrupt.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
if (!file_system_->RegisterDevice(std::move(device))) {
|
||||
xe::FatalError("Unable to register disc image.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
// Create symlinks to the device.
|
||||
file_system_->RegisterSymbolicLink("game:", mount_path);
|
||||
file_system_->RegisterSymbolicLink("d:", mount_path);
|
||||
|
||||
// Launch the game.
|
||||
auto module_path(FindLaunchModule());
|
||||
return CompleteLaunch(path, module_path);
|
||||
}
|
||||
|
||||
X_STATUS Emulator::LaunchStfsContainer(const std::filesystem::path& path) {
|
||||
auto mount_path = "\\Device\\Cdrom0";
|
||||
|
||||
// Register the container in the virtual filesystem.
|
||||
auto device = std::make_unique<vfs::StfsContainerDevice>(mount_path, path);
|
||||
if (!device->Initialize()) {
|
||||
xe::FatalError(
|
||||
"Unable to mount STFS container; file not found or corrupt.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
if (!file_system_->RegisterDevice(std::move(device))) {
|
||||
xe::FatalError("Unable to register STFS container.");
|
||||
return X_STATUS_NO_SUCH_FILE;
|
||||
}
|
||||
|
||||
file_system_->RegisterSymbolicLink("game:", mount_path);
|
||||
file_system_->RegisterSymbolicLink("d:", mount_path);
|
||||
|
||||
// Launch the game.
|
||||
auto module_path(FindLaunchModule());
|
||||
return CompleteLaunch(path, module_path);
|
||||
}
|
||||
@@ -532,9 +513,38 @@ void Emulator::LaunchNextTitle() {
|
||||
auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex");
|
||||
auto next_title = xam->loader_data().launch_path;
|
||||
|
||||
// Swap disk doesn't require reloading
|
||||
// This function should be purged?
|
||||
CompleteLaunch("", next_title);
|
||||
}
|
||||
|
||||
const std::filesystem::path Emulator::GetNewDiscPath(
|
||||
std::string window_message) {
|
||||
std::filesystem::path path = "";
|
||||
|
||||
auto file_picker = xe::ui::FilePicker::Create();
|
||||
file_picker->set_mode(ui::FilePicker::Mode::kOpen);
|
||||
file_picker->set_type(ui::FilePicker::Type::kFile);
|
||||
file_picker->set_multi_selection(false);
|
||||
file_picker->set_title(!window_message.empty() ? window_message
|
||||
: "Select Content Package");
|
||||
file_picker->set_extensions({
|
||||
{"Supported Files", "*.iso;*.xex;*.xcp;*.*"},
|
||||
{"Disc Image (*.iso)", "*.iso"},
|
||||
{"Xbox Executable (*.xex)", "*.xex"},
|
||||
{"All Files (*.*)", "*.*"},
|
||||
});
|
||||
|
||||
if (file_picker->Show(
|
||||
kernel_state()->emulator()->display_window()->native_handle())) {
|
||||
auto selected_files = file_picker->selected_files();
|
||||
if (!selected_files.empty()) {
|
||||
path = selected_files[0];
|
||||
}
|
||||
}
|
||||
return path;
|
||||
}
|
||||
|
||||
bool Emulator::ExceptionCallbackThunk(Exception* ex, void* data) {
|
||||
return reinterpret_cast<Emulator*>(data)->ExceptionCallback(ex);
|
||||
}
|
||||
@@ -592,7 +602,6 @@ bool Emulator::ExceptionCallback(Exception* ex) {
|
||||
context->v[i].u32[0], context->v[i].u32[1], context->v[i].u32[2],
|
||||
context->v[i].u32[3]);
|
||||
}
|
||||
|
||||
// Display a dialog telling the user the guest has crashed.
|
||||
if (display_window_ && imgui_drawer_) {
|
||||
display_window_->app_context().CallInUIThreadSynchronous([this]() {
|
||||
|
||||
Reference in New Issue
Block a user