[Emulator] Improvements to launch_data

Added support for autoload titles on boot with:
- Specific launch data
- Specific xex
- Restarting into packages: XamContentLaunchImageFromFileInternal
This commit is contained in:
Gliniak
2024-02-10 22:38:21 +01:00
committed by Radosław Gliński
parent 7e7784347b
commit 6f287a9597
10 changed files with 275 additions and 116 deletions

View File

@@ -53,8 +53,8 @@
#include "xenia/vfs/devices/disc_zarchive_device.h"
#include "xenia/vfs/devices/host_path_device.h"
#include "xenia/vfs/devices/null_device.h"
#include "xenia/vfs/virtual_file_system.h"
#include "xenia/vfs/devices/xcontent_container_device.h"
#include "xenia/vfs/virtual_file_system.h"
#if XE_ARCH_AMD64
#include "xenia/cpu/backend/x64/x64_backend.h"
@@ -294,7 +294,6 @@ X_STATUS Emulator::Setup(
}
}
// Initialize emulator fallback exception handling last.
ExceptionHandler::Install(Emulator::ExceptionCallbackThunk, this);
@@ -331,12 +330,12 @@ const std::unique_ptr<vfs::Device> Emulator::CreateVfsDeviceBasedOnPath(
mount_path, parent_path, !cvars::allow_game_relative_writes);
} else if (extension == ".zar") {
return std::make_unique<vfs::DiscZarchiveDevice>(mount_path, path);
}
else if (extension == ".7z" || extension == ".zip" || extension == ".rar" ||
} else if (extension == ".7z" || extension == ".zip" || extension == ".rar" ||
extension == ".tar" || extension == ".gz") {
xe::ShowSimpleMessageBox(
xe::SimpleMessageBoxType::Error,
fmt::format("Unsupported format!"
fmt::format(
"Unsupported format!"
"Xenia does not support running software in an archived format."));
}
return std::make_unique<vfs::DiscImageDevice>(mount_path, path);
@@ -399,13 +398,13 @@ X_STATUS Emulator::MountPath(const std::filesystem::path& path,
return X_STATUS_NO_SUCH_FILE;
}
file_system_->UnregisterSymbolicLink("d:");
file_system_->UnregisterSymbolicLink("game:");
file_system_->UnregisterSymbolicLink(kDefaultPartitonSymbolicLink);
file_system_->UnregisterSymbolicLink(kDefaultGameSymbolicLink);
file_system_->UnregisterSymbolicLink("plugins:");
// Create symlinks to the device.
file_system_->RegisterSymbolicLink("game:", mount_path);
file_system_->RegisterSymbolicLink("d:", mount_path);
file_system_->RegisterSymbolicLink(kDefaultGameSymbolicLink, mount_path);
file_system_->RegisterSymbolicLink(kDefaultPartitonSymbolicLink, mount_path);
return X_STATUS_SUCCESS;
}
@@ -763,9 +762,12 @@ bool Emulator::ExceptionCallback(Exception* ex) {
std::string crash_msg;
crash_msg.append("==== CRASH DUMP ====\n");
crash_msg.append(fmt::format("Thread ID (Host: 0x{:08X} / Guest: 0x{:08X})\n",
current_thread->thread()->system_id(), current_thread->thread_id()));
crash_msg.append(fmt::format("Thread Handle: 0x{:08X}\n", current_thread->handle()));
crash_msg.append(fmt::format("PC: 0x{:08X}\n",
current_thread->thread()->system_id(),
current_thread->thread_id()));
crash_msg.append(
fmt::format("Thread Handle: 0x{:08X}\n", current_thread->handle()));
crash_msg.append(
fmt::format("PC: 0x{:08X}\n",
guest_function->MapMachineCodeToGuestAddress(ex->pc())));
crash_msg.append("Registers:\n");
for (int i = 0; i < 32; i++) {
@@ -860,6 +862,32 @@ void Emulator::RemoveGameConfigLoadCallback(GameConfigLoadCallback* callback) {
std::string Emulator::FindLaunchModule() {
std::string path("game:\\");
auto xam = kernel_state()->GetKernelModule<kernel::xam::XamModule>("xam.xex");
if (!xam->loader_data().launch_path.empty()) {
std::string symbolic_link_path;
if (kernel_state_->file_system()->FindSymbolicLink(kDefaultGameSymbolicLink,
symbolic_link_path)) {
std::filesystem::path file_path = symbolic_link_path;
// Remove previous symbolic links.
// Some titles can provide root within specific directory.
kernel_state_->file_system()->UnregisterSymbolicLink(
kDefaultPartitonSymbolicLink);
kernel_state_->file_system()->UnregisterSymbolicLink(
kDefaultGameSymbolicLink);
file_path /= std::filesystem::path(xam->loader_data().launch_path);
kernel_state_->file_system()->RegisterSymbolicLink(
kDefaultPartitonSymbolicLink,
xe::path_to_utf8(file_path.parent_path()));
kernel_state_->file_system()->RegisterSymbolicLink(
kDefaultGameSymbolicLink, xe::path_to_utf8(file_path.parent_path()));
return xe::path_to_utf8(file_path);
}
}
if (!cvars::launch_module.empty()) {
return path + cvars::launch_module;
}
@@ -986,25 +1014,6 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
}
}
if (xam) {
const std::filesystem::path launch_data_dir = "launch_data";
const std::filesystem::path file_path =
launch_data_dir /
fmt::format("{:08X}_launch_data.bin", title_id_.value());
auto file = xe::filesystem::OpenFile(file_path, "rb");
if (file) {
XELOGI("Found launch_data for {}", title_name_);
const uint64_t file_size = std::filesystem::file_size(file_path);
xam->loader_data().launch_data_present = true;
xam->loader_data().launch_data.resize(file_size);
fread(xam->loader_data().launch_data.data(), file_size, 1, file);
fclose(file);
}
}
// Try and load the resource database (xex only).
if (module->title_id()) {
auto title_id = fmt::format("{:08X}", module->title_id());