[App] Improve title tracking.
[App] Improve title tracking. [App] Show title version in emulator window title, when available.
This commit is contained in:
parent
0419a9f13d
commit
ea1f2b114a
|
@ -435,7 +435,13 @@ void EmulatorWindow::UpdateTitle() {
|
|||
|
||||
// Title information, if available
|
||||
if (emulator()->is_title_open()) {
|
||||
sb.AppendFormat(u8" | [{:08X}]", emulator()->title_id());
|
||||
sb.AppendFormat(u8" | [{:08X}", emulator()->title_id());
|
||||
auto title_version = emulator()->title_version();
|
||||
if (!title_version.empty()) {
|
||||
sb.Append(u8" v");
|
||||
sb.Append(title_version);
|
||||
}
|
||||
sb.Append(u8"]");
|
||||
|
||||
auto title_name = emulator()->title_name();
|
||||
if (!title_name.empty()) {
|
||||
|
|
|
@ -68,7 +68,8 @@ Emulator::Emulator(const std::filesystem::path& command_line,
|
|||
storage_root_(storage_root),
|
||||
content_root_(content_root),
|
||||
cache_root_(cache_root),
|
||||
game_title_(),
|
||||
title_name_(),
|
||||
title_version_(),
|
||||
display_window_(nullptr),
|
||||
memory_(),
|
||||
audio_system_(),
|
||||
|
@ -78,7 +79,7 @@ Emulator::Emulator(const std::filesystem::path& command_line,
|
|||
file_system_(),
|
||||
kernel_state_(),
|
||||
main_thread_(),
|
||||
title_id_(0),
|
||||
title_id_({}),
|
||||
paused_(false),
|
||||
restoring_(false),
|
||||
restore_fence_() {}
|
||||
|
@ -246,8 +247,9 @@ X_STATUS Emulator::TerminateTitle() {
|
|||
}
|
||||
|
||||
kernel_state_->TerminateTitle();
|
||||
title_id_ = 0;
|
||||
game_title_ = "";
|
||||
title_id_ = {};
|
||||
title_name_ = "";
|
||||
title_version_ = "";
|
||||
on_terminate();
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
@ -419,7 +421,10 @@ bool Emulator::SaveToFile(const std::filesystem::path& path) {
|
|||
// Save the emulator state to a file
|
||||
ByteStream stream(map->data(), map->size());
|
||||
stream.Write('XSAV');
|
||||
stream.Write(title_id_);
|
||||
stream.Write(title_id_.has_value());
|
||||
if (title_id_.has_value()) {
|
||||
stream.Write(title_id_.value());
|
||||
}
|
||||
|
||||
// It's important we don't hold the global lock here! XThreads need to step
|
||||
// forward (possibly through guarded regions) without worry!
|
||||
|
@ -453,8 +458,15 @@ bool Emulator::RestoreFromFile(const std::filesystem::path& path) {
|
|||
return false;
|
||||
}
|
||||
|
||||
auto title_id = stream.Read<uint32_t>();
|
||||
if (title_id != title_id_) {
|
||||
auto has_title_id = stream.Read<bool>();
|
||||
std::optional<uint32_t> title_id;
|
||||
if (!has_title_id) {
|
||||
title_id = {};
|
||||
} else {
|
||||
title_id = stream.Read<uint32_t>();
|
||||
}
|
||||
if (title_id_.has_value() != title_id.has_value() ||
|
||||
title_id_.value() != title_id.value()) {
|
||||
// Swapping between titles is unsupported at the moment.
|
||||
assert_always();
|
||||
return false;
|
||||
|
@ -642,11 +654,28 @@ std::string Emulator::FindLaunchModule() {
|
|||
return path + default_module;
|
||||
}
|
||||
|
||||
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);
|
||||
}
|
||||
|
||||
X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||
const std::string_view module_path) {
|
||||
// Reset state.
|
||||
title_id_ = 0;
|
||||
game_title_ = "";
|
||||
title_id_ = {};
|
||||
title_name_ = "";
|
||||
title_version_ = "";
|
||||
display_window_->SetIcon(nullptr, 0);
|
||||
|
||||
// Allow xam to request module loads.
|
||||
|
@ -662,8 +691,15 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
|||
// Grab the current title ID.
|
||||
xex2_opt_execution_info* info = nullptr;
|
||||
module->GetOptHeader(XEX_HEADER_EXECUTION_INFO, &info);
|
||||
if (info) {
|
||||
|
||||
if (!info) {
|
||||
title_id_ = 0;
|
||||
} else {
|
||||
title_id_ = info->title_id;
|
||||
auto title_version = info->version();
|
||||
if (title_version.value != 0) {
|
||||
title_version_ = format_version(title_version);
|
||||
}
|
||||
}
|
||||
|
||||
// Try and load the resource database (xex only).
|
||||
|
@ -678,10 +714,10 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
|||
module->memory()->TranslateVirtual(resource_data), resource_size);
|
||||
if (db.is_valid()) {
|
||||
// TODO(gibbed): get title respective to user locale.
|
||||
game_title_ = db.title(kernel::util::XdbfLocale::kEnglish);
|
||||
if (game_title_.empty()) {
|
||||
title_name_ = db.title(kernel::util::XdbfLocale::kEnglish);
|
||||
if (title_name_.empty()) {
|
||||
// If English title is unavailable, get the title in default locale.
|
||||
game_title_ = db.title();
|
||||
title_name_ = db.title();
|
||||
}
|
||||
auto icon_block = db.icon();
|
||||
if (icon_block) {
|
||||
|
@ -696,7 +732,7 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
|||
// playing before the video can be seen if doing this in parallel with the
|
||||
// main thread.
|
||||
on_shader_storage_initialization(true);
|
||||
graphics_system_->InitializeShaderStorage(cache_root_, title_id_, true);
|
||||
graphics_system_->InitializeShaderStorage(cache_root_, title_id_.value(), true);
|
||||
on_shader_storage_initialization(false);
|
||||
|
||||
auto main_thread = kernel_state_->LaunchModule(module);
|
||||
|
@ -704,7 +740,7 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
|||
return X_STATUS_UNSUCCESSFUL;
|
||||
}
|
||||
main_thread_ = main_thread;
|
||||
on_launch(title_id_, game_title_);
|
||||
on_launch(title_id_.value(), title_name_);
|
||||
|
||||
return X_STATUS_SUCCESS;
|
||||
}
|
||||
|
|
|
@ -11,6 +11,7 @@
|
|||
#define XENIA_EMULATOR_H_
|
||||
|
||||
#include <functional>
|
||||
#include <optional>
|
||||
#include <string>
|
||||
|
||||
#include "xenia/base/delegate.h"
|
||||
|
@ -65,14 +66,19 @@ class Emulator {
|
|||
// Folder files safe to remove without significant side effects are stored in.
|
||||
const std::filesystem::path& cache_root() const { return cache_root_; }
|
||||
|
||||
// Title of the game in the default language.
|
||||
const std::string& game_title() const { return game_title_; }
|
||||
// Name of the title in the default language.
|
||||
const std::string& title_name() const { return title_name_; }
|
||||
|
||||
// Version of the title as a string.
|
||||
const std::string& title_version() const { return title_version_; }
|
||||
|
||||
// Currently running title ID
|
||||
uint32_t title_id() const { return title_id_; }
|
||||
uint32_t title_id() const {
|
||||
return !title_id_.has_value() ? 0 : title_id_.value();
|
||||
}
|
||||
|
||||
// Are we currently running a title?
|
||||
bool is_title_open() const { return title_id_ != 0; }
|
||||
bool is_title_open() const { return title_id_.has_value(); }
|
||||
|
||||
// Window used for displaying graphical output.
|
||||
ui::Window* display_window() const { return display_window_; }
|
||||
|
@ -172,7 +178,8 @@ class Emulator {
|
|||
std::filesystem::path content_root_;
|
||||
std::filesystem::path cache_root_;
|
||||
|
||||
std::string game_title_;
|
||||
std::string title_name_;
|
||||
std::string title_version_;
|
||||
|
||||
ui::Window* display_window_;
|
||||
|
||||
|
@ -188,7 +195,7 @@ class Emulator {
|
|||
|
||||
std::unique_ptr<kernel::KernelState> kernel_state_;
|
||||
kernel::object_ref<kernel::XThread> main_thread_;
|
||||
uint32_t title_id_; // Currently running title ID
|
||||
std::optional<uint32_t> title_id_; // Currently running title ID
|
||||
|
||||
bool paused_;
|
||||
bool restoring_;
|
||||
|
|
Loading…
Reference in New Issue