[Emulator] Allow saving launch_data and use them on next boot
This commit is contained in:
parent
50b42371a0
commit
6284bfc21c
|
@ -985,7 +985,26 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||||
title_version_ = format_version(title_version);
|
title_version_ = format_version(title_version);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
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).
|
// Try and load the resource database (xex only).
|
||||||
if (module->title_id()) {
|
if (module->title_id()) {
|
||||||
auto title_id = fmt::format("{:08X}", module->title_id());
|
auto title_id = fmt::format("{:08X}", module->title_id());
|
||||||
|
|
|
@ -21,6 +21,10 @@
|
||||||
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
#include "xenia/kernel/xboxkrnl/xboxkrnl_threading.h"
|
||||||
#include "xenia/kernel/xenumerator.h"
|
#include "xenia/kernel/xenumerator.h"
|
||||||
#include "xenia/kernel/xthread.h"
|
#include "xenia/kernel/xthread.h"
|
||||||
|
#include "xenia/ui/imgui_dialog.h"
|
||||||
|
#include "xenia/ui/imgui_drawer.h"
|
||||||
|
#include "xenia/ui/window.h"
|
||||||
|
#include "xenia/ui/windowed_app_context.h"
|
||||||
#include "xenia/xbox.h"
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
#if XE_PLATFORM_WIN32
|
#if XE_PLATFORM_WIN32
|
||||||
|
@ -287,6 +291,24 @@ dword_result_t XamLoaderSetLaunchData_entry(lpvoid_t data, dword_t size) {
|
||||||
loader_data.launch_data_present = size ? true : false;
|
loader_data.launch_data_present = size ? true : false;
|
||||||
loader_data.launch_data.resize(size);
|
loader_data.launch_data.resize(size);
|
||||||
std::memcpy(loader_data.launch_data.data(), data, size);
|
std::memcpy(loader_data.launch_data.data(), data, size);
|
||||||
|
|
||||||
|
// Because we have no way to restart game while it is working. Remove as soon
|
||||||
|
// as possible.
|
||||||
|
const std::filesystem::path launch_data_dir = "launch_data";
|
||||||
|
|
||||||
|
std::filesystem::path file_path =
|
||||||
|
launch_data_dir /
|
||||||
|
fmt::format("{:08X}_launch_data.bin", kernel_state()->title_id());
|
||||||
|
|
||||||
|
if (!std::filesystem::exists(launch_data_dir)) {
|
||||||
|
std::filesystem::create_directories(launch_data_dir);
|
||||||
|
}
|
||||||
|
|
||||||
|
auto file = xe::filesystem::OpenFile(file_path, "wb+");
|
||||||
|
if (file) {
|
||||||
|
fwrite(loader_data.launch_data.data(), size, 1, file);
|
||||||
|
fclose(file);
|
||||||
|
}
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XamLoaderSetLaunchData, kNone, kSketchy);
|
DECLARE_XAM_EXPORT1(XamLoaderSetLaunchData, kNone, kSketchy);
|
||||||
|
@ -343,6 +365,21 @@ void XamLoaderLaunchTitle_entry(lpstring_t raw_name_ptr, dword_t flags) {
|
||||||
}
|
}
|
||||||
loader_data.launch_path = path;
|
loader_data.launch_path = path;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (loader_data.launch_data_present) {
|
||||||
|
auto display_window = kernel_state()->emulator()->display_window();
|
||||||
|
auto imgui_drawer = kernel_state()->emulator()->imgui_drawer();
|
||||||
|
|
||||||
|
if (display_window && imgui_drawer) {
|
||||||
|
display_window->app_context().CallInUIThreadSynchronous(
|
||||||
|
[imgui_drawer]() {
|
||||||
|
xe::ui::ImGuiDialog::ShowMessageBox(
|
||||||
|
imgui_drawer, "Title was restarted",
|
||||||
|
"Title closed with new launch data. \nPlease close Xenia and "
|
||||||
|
"start title again.");
|
||||||
|
});
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
assert_always("Game requested exit to dashboard via XamLoaderLaunchTitle");
|
assert_always("Game requested exit to dashboard via XamLoaderLaunchTitle");
|
||||||
}
|
}
|
||||||
|
@ -434,8 +471,8 @@ dword_result_t RtlSleep_entry(dword_t dwMilliseconds, dword_t bAlertable) {
|
||||||
? LLONG_MAX
|
? LLONG_MAX
|
||||||
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
: static_cast<LONGLONG>(-10000) * dwMilliseconds;
|
||||||
|
|
||||||
X_STATUS result = xboxkrnl::KeDelayExecutionThread(MODE::UserMode, bAlertable,
|
X_STATUS result = xboxkrnl::KeDelayExecutionThread(
|
||||||
(uint64_t*)&delay, nullptr);
|
MODE::UserMode, bAlertable, (uint64_t*)&delay, nullptr);
|
||||||
|
|
||||||
// If the delay was interrupted by an APC, keep delaying the thread
|
// If the delay was interrupted by an APC, keep delaying the thread
|
||||||
while (bAlertable && result == X_STATUS_ALERTED) {
|
while (bAlertable && result == X_STATUS_ALERTED) {
|
||||||
|
|
Loading…
Reference in New Issue