C++17ification.
C++17ification! - Filesystem interaction now uses std::filesystem::path. - Usage of const char*, std::string have been changed to std::string_view where appropriate. - Usage of printf-style functions changed to use fmt.
This commit is contained in:
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -39,11 +39,10 @@ void DiscordPresence::NotPlaying() {
|
||||
Discord_UpdatePresence(&discordPresence);
|
||||
}
|
||||
|
||||
void DiscordPresence::PlayingTitle(const std::wstring& game_title) {
|
||||
auto discord_game_title = xe::to_string(game_title);
|
||||
void DiscordPresence::PlayingTitle(const std::string_view game_title) {
|
||||
DiscordRichPresence discordPresence = {};
|
||||
discordPresence.state = "In Game";
|
||||
discordPresence.details = discord_game_title.c_str();
|
||||
discordPresence.details = std::string(game_title).c_str();
|
||||
// TODO(gibbed): we don't have state icons yet.
|
||||
// discordPresence.smallImageKey = "app";
|
||||
// discordPresence.largeImageKey = "state_ingame";
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -19,7 +19,7 @@ class DiscordPresence {
|
||||
public:
|
||||
static void Initialize();
|
||||
static void NotPlaying();
|
||||
static void PlayingTitle(const std::wstring& game_title);
|
||||
static void PlayingTitle(const std::string_view game_title);
|
||||
static void Shutdown();
|
||||
};
|
||||
|
||||
|
||||
@@ -9,9 +9,7 @@
|
||||
|
||||
#include "xenia/app/emulator_window.h"
|
||||
|
||||
// Autogenerated by `xb premake`.
|
||||
#include "build/version.h"
|
||||
|
||||
#include "third_party/fmt/include/fmt/format.h"
|
||||
#include "third_party/imgui/imgui.h"
|
||||
#include "xenia/base/clock.h"
|
||||
#include "xenia/base/cvar.h"
|
||||
@@ -19,14 +17,17 @@
|
||||
#include "xenia/base/logging.h"
|
||||
#include "xenia/base/platform.h"
|
||||
#include "xenia/base/profiling.h"
|
||||
#include "xenia/base/system.h"
|
||||
#include "xenia/base/threading.h"
|
||||
#include "xenia/emulator.h"
|
||||
#include "xenia/gpu/graphics_system.h"
|
||||
|
||||
#include "xenia/ui/file_picker.h"
|
||||
#include "xenia/ui/imgui_dialog.h"
|
||||
#include "xenia/ui/imgui_drawer.h"
|
||||
|
||||
// Autogenerated by `xb premake`.
|
||||
#include "build/version.h"
|
||||
|
||||
DECLARE_bool(debug);
|
||||
|
||||
namespace xe {
|
||||
@@ -38,7 +39,7 @@ using xe::ui::MenuItem;
|
||||
using xe::ui::MouseEvent;
|
||||
using xe::ui::UIEvent;
|
||||
|
||||
const std::wstring kBaseTitle = L"xenia";
|
||||
const std::string kBaseTitle = "xenia";
|
||||
|
||||
EmulatorWindow::EmulatorWindow(Emulator* emulator)
|
||||
: emulator_(emulator),
|
||||
@@ -47,14 +48,13 @@ EmulatorWindow::EmulatorWindow(Emulator* emulator)
|
||||
base_title_ = kBaseTitle +
|
||||
#ifdef DEBUG
|
||||
#if _NO_DEBUG_HEAP == 1
|
||||
L" DEBUG" +
|
||||
" DEBUG"
|
||||
#else
|
||||
L" CHECKED" +
|
||||
" CHECKED"
|
||||
#endif
|
||||
#endif
|
||||
L" (" + xe::to_wstring(XE_BUILD_BRANCH) + L"/" +
|
||||
xe::to_wstring(XE_BUILD_COMMIT_SHORT) + L"/" +
|
||||
xe::to_wstring(XE_BUILD_DATE) + L")";
|
||||
" (" XE_BUILD_BRANCH "/" XE_BUILD_COMMIT_SHORT "/" XE_BUILD_DATE
|
||||
")";
|
||||
}
|
||||
|
||||
EmulatorWindow::~EmulatorWindow() {
|
||||
@@ -123,13 +123,13 @@ bool EmulatorWindow::Initialize() {
|
||||
// Save to file
|
||||
// TODO: Choose path based on user input, or from options
|
||||
// TODO: Spawn a new thread to do this.
|
||||
emulator()->SaveToFile(L"test.sav");
|
||||
emulator()->SaveToFile("test.sav");
|
||||
} break;
|
||||
case 0x77: { // VK_F8
|
||||
// Restore from file
|
||||
// TODO: Choose path from user
|
||||
// TODO: Spawn a new thread to do this.
|
||||
emulator()->RestoreFromFile(L"test.sav");
|
||||
emulator()->RestoreFromFile("test.sav");
|
||||
} break;
|
||||
case 0x7A: { // VK_F11
|
||||
ToggleFullscreen();
|
||||
@@ -182,105 +182,102 @@ bool EmulatorWindow::Initialize() {
|
||||
// Main menu.
|
||||
// FIXME: This code is really messy.
|
||||
auto main_menu = MenuItem::Create(MenuItem::Type::kNormal);
|
||||
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&File");
|
||||
auto file_menu = MenuItem::Create(MenuItem::Type::kPopup, "&File");
|
||||
{
|
||||
file_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, L"&Open...", L"Ctrl+O",
|
||||
MenuItem::Create(MenuItem::Type::kString, "&Open...", "Ctrl+O",
|
||||
std::bind(&EmulatorWindow::FileOpen, this)));
|
||||
file_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, L"Close",
|
||||
MenuItem::Create(MenuItem::Type::kString, "Close",
|
||||
std::bind(&EmulatorWindow::FileClose, this)));
|
||||
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
file_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"Show content directory...",
|
||||
MenuItem::Type::kString, "Show content directory...",
|
||||
std::bind(&EmulatorWindow::ShowContentDirectory, this)));
|
||||
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, L"E&xit",
|
||||
L"Alt+F4",
|
||||
file_menu->AddChild(MenuItem::Create(MenuItem::Type::kString, "E&xit",
|
||||
"Alt+F4",
|
||||
[this]() { window_->Close(); }));
|
||||
}
|
||||
main_menu->AddChild(std::move(file_menu));
|
||||
|
||||
// CPU menu.
|
||||
auto cpu_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&CPU");
|
||||
auto cpu_menu = MenuItem::Create(MenuItem::Type::kPopup, "&CPU");
|
||||
{
|
||||
cpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"&Reset Time Scalar", L"Numpad *",
|
||||
MenuItem::Type::kString, "&Reset Time Scalar", "Numpad *",
|
||||
std::bind(&EmulatorWindow::CpuTimeScalarReset, this)));
|
||||
cpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"Time Scalar /= 2", L"Numpad -",
|
||||
MenuItem::Type::kString, "Time Scalar /= 2", "Numpad -",
|
||||
std::bind(&EmulatorWindow::CpuTimeScalarSetHalf, this)));
|
||||
cpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"Time Scalar *= 2", L"Numpad +",
|
||||
MenuItem::Type::kString, "Time Scalar *= 2", "Numpad +",
|
||||
std::bind(&EmulatorWindow::CpuTimeScalarSetDouble, this)));
|
||||
}
|
||||
cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
{
|
||||
cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kString,
|
||||
L"Toggle Profiler &Display", L"F3",
|
||||
"Toggle Profiler &Display", "F3",
|
||||
[]() { Profiler::ToggleDisplay(); }));
|
||||
cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kString,
|
||||
L"&Pause/Resume Profiler", L"`",
|
||||
"&Pause/Resume Profiler", "`",
|
||||
[]() { Profiler::TogglePause(); }));
|
||||
}
|
||||
cpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
{
|
||||
cpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"&Break and Show Guest Debugger",
|
||||
L"Pause/Break",
|
||||
std::bind(&EmulatorWindow::CpuBreakIntoDebugger, this)));
|
||||
MenuItem::Type::kString, "&Break and Show Guest Debugger",
|
||||
"Pause/Break", std::bind(&EmulatorWindow::CpuBreakIntoDebugger, this)));
|
||||
cpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"&Break into Host Debugger",
|
||||
L"Ctrl+Pause/Break",
|
||||
MenuItem::Type::kString, "&Break into Host Debugger",
|
||||
"Ctrl+Pause/Break",
|
||||
std::bind(&EmulatorWindow::CpuBreakIntoHostDebugger, this)));
|
||||
}
|
||||
main_menu->AddChild(std::move(cpu_menu));
|
||||
|
||||
// GPU menu.
|
||||
auto gpu_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&GPU");
|
||||
auto gpu_menu = MenuItem::Create(MenuItem::Type::kPopup, "&GPU");
|
||||
{
|
||||
gpu_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, L"&Trace Frame", L"F4",
|
||||
MenuItem::Create(MenuItem::Type::kString, "&Trace Frame", "F4",
|
||||
std::bind(&EmulatorWindow::GpuTraceFrame, this)));
|
||||
}
|
||||
gpu_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
{
|
||||
gpu_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"&Clear Runtime Caches", L"F5",
|
||||
std::bind(&EmulatorWindow::GpuClearCaches, this)));
|
||||
gpu_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, "&Clear Runtime Caches", "F5",
|
||||
std::bind(&EmulatorWindow::GpuClearCaches, this)));
|
||||
}
|
||||
main_menu->AddChild(std::move(gpu_menu));
|
||||
|
||||
// Window menu.
|
||||
auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Window");
|
||||
auto window_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Window");
|
||||
{
|
||||
window_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, L"&Fullscreen", L"F11",
|
||||
MenuItem::Create(MenuItem::Type::kString, "&Fullscreen", "F11",
|
||||
std::bind(&EmulatorWindow::ToggleFullscreen, this)));
|
||||
}
|
||||
main_menu->AddChild(std::move(window_menu));
|
||||
|
||||
// Help menu.
|
||||
auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, L"&Help");
|
||||
auto help_menu = MenuItem::Create(MenuItem::Type::kPopup, "&Help");
|
||||
{
|
||||
help_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, "Build commit on GitHub...",
|
||||
"F2", std::bind(&EmulatorWindow::ShowCommitID, this)));
|
||||
help_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"Build commit on GitHub...", L"F2",
|
||||
std::bind(&EmulatorWindow::ShowCommitID, this)));
|
||||
help_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"Recent changes on GitHub...", [this]() {
|
||||
std::wstring url =
|
||||
std::wstring(L"https://github.com/xenia-project/xenia/compare/") +
|
||||
xe::to_wstring(XE_BUILD_COMMIT) + L"..." +
|
||||
xe::to_wstring(XE_BUILD_BRANCH);
|
||||
LaunchBrowser(url.c_str());
|
||||
MenuItem::Type::kString, "Recent changes on GitHub...", [this]() {
|
||||
LaunchWebBrowser(
|
||||
"https://github.com/xenia-project/xenia/compare/" XE_BUILD_COMMIT
|
||||
"..." XE_BUILD_BRANCH);
|
||||
}));
|
||||
help_menu->AddChild(MenuItem::Create(MenuItem::Type::kSeparator));
|
||||
help_menu->AddChild(
|
||||
MenuItem::Create(MenuItem::Type::kString, L"&Website...", L"F1",
|
||||
MenuItem::Create(MenuItem::Type::kString, "&Website...", "F1",
|
||||
std::bind(&EmulatorWindow::ShowHelpWebsite, this)));
|
||||
help_menu->AddChild(MenuItem::Create(
|
||||
MenuItem::Type::kString, L"&About...",
|
||||
[this]() { LaunchBrowser(L"https://xenia.jp/about/"); }));
|
||||
MenuItem::Type::kString, "&About...",
|
||||
[this]() { LaunchWebBrowser("https://xenia.jp/about/"); }));
|
||||
}
|
||||
main_menu->AddChild(std::move(help_menu));
|
||||
|
||||
@@ -293,7 +290,7 @@ bool EmulatorWindow::Initialize() {
|
||||
return true;
|
||||
}
|
||||
|
||||
void EmulatorWindow::FileDrop(const wchar_t* filename) {
|
||||
void EmulatorWindow::FileDrop(const std::filesystem::path& filename) {
|
||||
auto result = emulator_->LaunchPath(filename);
|
||||
if (XFAILED(result)) {
|
||||
// TODO: Display a message box.
|
||||
@@ -302,19 +299,19 @@ void EmulatorWindow::FileDrop(const wchar_t* filename) {
|
||||
}
|
||||
|
||||
void EmulatorWindow::FileOpen() {
|
||||
std::wstring path;
|
||||
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(L"Select Content Package");
|
||||
file_picker->set_title("Select Content Package");
|
||||
file_picker->set_extensions({
|
||||
{L"Supported Files", L"*.iso;*.xex;*.xcp;*.*"},
|
||||
{L"Disc Image (*.iso)", L"*.iso"},
|
||||
{L"Xbox Executable (*.xex)", L"*.xex"},
|
||||
//{ L"Content Package (*.xcp)", L"*.xcp" },
|
||||
{L"All Files (*.*)", L"*.*"},
|
||||
{"Supported Files", "*.iso;*.xex;*.xcp;*.*"},
|
||||
{"Disc Image (*.iso)", "*.iso"},
|
||||
{"Xbox Executable (*.xex)", "*.xex"},
|
||||
//{"Content Package (*.xcp)", "*.xcp" },
|
||||
{"All Files (*.*)", "*.*"},
|
||||
});
|
||||
if (file_picker->Show(window_->native_handle())) {
|
||||
auto selected_files = file_picker->selected_files();
|
||||
@@ -325,8 +322,7 @@ void EmulatorWindow::FileOpen() {
|
||||
|
||||
if (!path.empty()) {
|
||||
// Normalize the path and make absolute.
|
||||
std::wstring abs_path = xe::to_absolute_path(path);
|
||||
|
||||
auto abs_path = std::filesystem::absolute(path);
|
||||
auto result = emulator_->LaunchPath(abs_path);
|
||||
if (XFAILED(result)) {
|
||||
// TODO: Display a message box.
|
||||
@@ -342,16 +338,16 @@ void EmulatorWindow::FileClose() {
|
||||
}
|
||||
|
||||
void EmulatorWindow::ShowContentDirectory() {
|
||||
std::wstring target_path;
|
||||
std::filesystem::path target_path;
|
||||
|
||||
auto content_root = emulator_->content_root();
|
||||
if (!emulator_->is_title_open() || !emulator_->kernel_state()) {
|
||||
target_path = content_root;
|
||||
} else {
|
||||
// TODO(gibbed): expose this via ContentManager?
|
||||
wchar_t title_id[9] = L"00000000";
|
||||
std::swprintf(title_id, 9, L"%.8X", emulator_->kernel_state()->title_id());
|
||||
auto package_root = xe::join_paths(content_root, title_id);
|
||||
auto title_id =
|
||||
fmt::format("{:08X}", emulator_->kernel_state()->title_id());
|
||||
auto package_root = content_root / title_id;
|
||||
target_path = package_root;
|
||||
}
|
||||
|
||||
@@ -359,7 +355,7 @@ void EmulatorWindow::ShowContentDirectory() {
|
||||
xe::filesystem::CreateFolder(target_path);
|
||||
}
|
||||
|
||||
LaunchBrowser(target_path.c_str());
|
||||
LaunchFileExplorer(target_path);
|
||||
}
|
||||
|
||||
void EmulatorWindow::CheckHideCursor() {
|
||||
@@ -426,36 +422,36 @@ void EmulatorWindow::ToggleFullscreen() {
|
||||
}
|
||||
}
|
||||
|
||||
void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser(L"https://xenia.jp"); }
|
||||
void EmulatorWindow::ShowHelpWebsite() { LaunchWebBrowser("https://xenia.jp"); }
|
||||
|
||||
void EmulatorWindow::ShowCommitID() {
|
||||
std::wstring url =
|
||||
std::wstring(L"https://github.com/xenia-project/xenia/commit/") +
|
||||
xe::to_wstring(XE_BUILD_COMMIT) + L"/";
|
||||
LaunchBrowser(url.c_str());
|
||||
LaunchWebBrowser(
|
||||
"https://github.com/xenia-project/xenia/commit/" XE_BUILD_COMMIT "/");
|
||||
}
|
||||
|
||||
void EmulatorWindow::UpdateTitle() {
|
||||
std::wstring title(base_title_);
|
||||
std::string title(base_title_);
|
||||
|
||||
if (emulator()->is_title_open()) {
|
||||
auto game_title = emulator()->game_title();
|
||||
title += xe::format_string(L" | [%.8X] %s", emulator()->title_id(),
|
||||
game_title.c_str());
|
||||
title += fmt::format(" | [{:08X}] {}", emulator()->title_id(), game_title);
|
||||
}
|
||||
|
||||
auto graphics_system = emulator()->graphics_system();
|
||||
if (graphics_system) {
|
||||
auto graphics_name = graphics_system->name();
|
||||
title += L" <" + graphics_name + L">";
|
||||
title += fmt::format(" <{}>", graphics_name);
|
||||
}
|
||||
|
||||
if (Clock::guest_time_scalar() != 1.0) {
|
||||
title += xe::format_string(L" (@%.2fx)", Clock::guest_time_scalar());
|
||||
title += fmt::format(" (@{:.2f}x)", Clock::guest_time_scalar());
|
||||
}
|
||||
|
||||
if (initializing_shader_storage_) {
|
||||
title += L" (Preloading shaders\u2026)";
|
||||
title +=
|
||||
" (Preloading shaders"
|
||||
u8"\u2026"
|
||||
")";
|
||||
}
|
||||
|
||||
window_->set_title(title);
|
||||
|
||||
@@ -2,7 +2,7 @@
|
||||
******************************************************************************
|
||||
* Xenia : Xbox 360 Emulator Research Project *
|
||||
******************************************************************************
|
||||
* Copyright 2015 Ben Vanik. All rights reserved. *
|
||||
* Copyright 2020 Ben Vanik. All rights reserved. *
|
||||
* Released under the BSD license - see LICENSE in the root for more details. *
|
||||
******************************************************************************
|
||||
*/
|
||||
@@ -44,7 +44,7 @@ class EmulatorWindow {
|
||||
|
||||
bool Initialize();
|
||||
|
||||
void FileDrop(const wchar_t* filename);
|
||||
void FileDrop(const std::filesystem::path& filename);
|
||||
void FileOpen();
|
||||
void FileClose();
|
||||
void ShowContentDirectory();
|
||||
@@ -62,7 +62,7 @@ class EmulatorWindow {
|
||||
Emulator* emulator_;
|
||||
std::unique_ptr<ui::Loop> loop_;
|
||||
std::unique_ptr<ui::Window> window_;
|
||||
std::wstring base_title_;
|
||||
std::string base_title_;
|
||||
uint64_t cursor_hide_time_ = 0;
|
||||
bool initializing_shader_storage_ = false;
|
||||
};
|
||||
|
||||
@@ -10,6 +10,7 @@ project("xenia-app")
|
||||
links({
|
||||
"aes_128",
|
||||
"capstone",
|
||||
"fmt",
|
||||
"dxbc",
|
||||
"discord-rpc",
|
||||
"glslang-spirv",
|
||||
|
||||
@@ -44,6 +44,7 @@
|
||||
#include "xenia/hid/xinput/xinput_hid.h"
|
||||
#endif // XE_PLATFORM_WIN32
|
||||
|
||||
#include "third_party/fmt/include/fmt/format.h"
|
||||
#include "third_party/xbyak/xbyak/xbyak_util.h"
|
||||
|
||||
DEFINE_string(apu, "any", "Audio system. Use: [any, nop, sdl, xaudio2]", "APU");
|
||||
@@ -54,13 +55,13 @@ DEFINE_string(hid, "any", "Input system. Use: [any, nop, sdl, winkey, xinput]",
|
||||
|
||||
DEFINE_bool(fullscreen, false, "Toggles fullscreen", "GPU");
|
||||
|
||||
DEFINE_string(
|
||||
DEFINE_path(
|
||||
storage_root, "",
|
||||
"Root path for persistent internal data storage (config, etc.), or empty "
|
||||
"to use the path preferred for the OS, such as the documents folder, or "
|
||||
"the emulator executable directory if portable.txt is present in it.",
|
||||
"Storage");
|
||||
DEFINE_string(
|
||||
DEFINE_path(
|
||||
content_root, "",
|
||||
"Root path for guest content storage (saves, etc.), or empty to use the "
|
||||
"content folder under the storage root.",
|
||||
@@ -69,9 +70,9 @@ DEFINE_string(
|
||||
DEFINE_bool(mount_scratch, false, "Enable scratch mount", "Storage");
|
||||
DEFINE_bool(mount_cache, false, "Enable cache mount", "Storage");
|
||||
|
||||
DEFINE_transient_string(target, "",
|
||||
"Specifies the target .xex or .iso to execute.",
|
||||
"General");
|
||||
DEFINE_transient_path(target, "",
|
||||
"Specifies the target .xex or .iso to execute.",
|
||||
"General");
|
||||
DECLARE_bool(debug);
|
||||
|
||||
DEFINE_bool(discord, true, "Enable Discord rich presence", "General");
|
||||
@@ -91,25 +92,25 @@ class Factory {
|
||||
std::vector<Creator> creators_;
|
||||
|
||||
public:
|
||||
void Add(const std::string& name, std::function<bool()> is_available,
|
||||
void Add(const std::string_view name, std::function<bool()> is_available,
|
||||
std::function<std::unique_ptr<T>(Args...)> instantiate) {
|
||||
creators_.push_back({name, is_available, instantiate});
|
||||
creators_.push_back({std::string(name), is_available, instantiate});
|
||||
}
|
||||
|
||||
void Add(const std::string& name,
|
||||
void Add(const std::string_view name,
|
||||
std::function<std::unique_ptr<T>(Args...)> instantiate) {
|
||||
auto always_available = []() { return true; };
|
||||
Add(name, always_available, instantiate);
|
||||
}
|
||||
|
||||
template <typename DT>
|
||||
void Add(const std::string& name) {
|
||||
void Add(const std::string_view name) {
|
||||
Add(name, DT::IsAvailable, [](Args... args) {
|
||||
return std::make_unique<DT>(std::forward<Args>(args)...);
|
||||
});
|
||||
}
|
||||
|
||||
std::unique_ptr<T> Create(const std::string& name, Args... args) {
|
||||
std::unique_ptr<T> Create(const std::string_view name, Args... args) {
|
||||
if (!name.empty() && name != "any") {
|
||||
auto it = std::find_if(
|
||||
creators_.cbegin(), creators_.cend(),
|
||||
@@ -129,7 +130,7 @@ class Factory {
|
||||
}
|
||||
}
|
||||
|
||||
std::vector<std::unique_ptr<T>> CreateAll(const std::string& name,
|
||||
std::vector<std::unique_ptr<T>> CreateAll(const std::string_view name,
|
||||
Args... args) {
|
||||
std::vector<std::unique_ptr<T>> instances;
|
||||
if (!name.empty() && name != "any") {
|
||||
@@ -206,35 +207,34 @@ std::vector<std::unique_ptr<hid::InputDriver>> CreateInputDrivers(
|
||||
return drivers;
|
||||
}
|
||||
|
||||
int xenia_main(const std::vector<std::wstring>& args) {
|
||||
int xenia_main(const std::vector<std::string>& args) {
|
||||
Profiler::Initialize();
|
||||
Profiler::ThreadEnter("main");
|
||||
|
||||
// Figure out where internal files and content should go.
|
||||
std::wstring storage_root = xe::to_wstring(cvars::storage_root);
|
||||
std::filesystem::path storage_root = cvars::storage_root;
|
||||
if (storage_root.empty()) {
|
||||
storage_root = xe::filesystem::GetExecutableFolder();
|
||||
if (!xe::filesystem::PathExists(
|
||||
xe::join_paths(storage_root, L"portable.txt"))) {
|
||||
if (!xe::filesystem::PathExists(storage_root / "portable.txt")) {
|
||||
storage_root = xe::filesystem::GetUserFolder();
|
||||
#if defined(XE_PLATFORM_WIN32) || defined(XE_PLATFORM_LINUX)
|
||||
storage_root = xe::join_paths(storage_root, L"Xenia");
|
||||
storage_root = storage_root / "Xenia";
|
||||
#else
|
||||
#warning Unhandled platform for the data root.
|
||||
storage_root = xe::join_paths(storage_root, L"Xenia");
|
||||
storage_root = storage_root / "Xenia";
|
||||
#endif
|
||||
}
|
||||
}
|
||||
storage_root = xe::to_absolute_path(storage_root);
|
||||
storage_root = std::filesystem::absolute(storage_root);
|
||||
XELOGI("Storage root: %S", storage_root.c_str());
|
||||
|
||||
config::SetupConfig(storage_root);
|
||||
|
||||
std::wstring content_root = xe::to_wstring(cvars::content_root);
|
||||
std::filesystem::path content_root = cvars::content_root;
|
||||
if (content_root.empty()) {
|
||||
content_root = xe::join_paths(storage_root, L"content");
|
||||
content_root = storage_root / "content";
|
||||
}
|
||||
content_root = xe::to_absolute_path(content_root);
|
||||
content_root = std::filesystem::absolute(content_root);
|
||||
XELOGI("Content root: %S", content_root.c_str());
|
||||
|
||||
if (cvars::discord) {
|
||||
@@ -243,7 +243,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
}
|
||||
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
auto emulator = std::make_unique<Emulator>(L"", storage_root, content_root);
|
||||
auto emulator = std::make_unique<Emulator>("", storage_root, content_root);
|
||||
|
||||
// Main emulator display window.
|
||||
auto emulator_window = EmulatorWindow::Create(emulator.get());
|
||||
@@ -260,7 +260,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
|
||||
if (cvars::mount_scratch) {
|
||||
auto scratch_device = std::make_unique<xe::vfs::HostPathDevice>(
|
||||
"\\SCRATCH", L"scratch", false);
|
||||
"\\SCRATCH", "scratch", false);
|
||||
if (!scratch_device->Initialize()) {
|
||||
XELOGE("Unable to scan scratch path");
|
||||
} else {
|
||||
@@ -274,7 +274,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
|
||||
if (cvars::mount_cache) {
|
||||
auto cache0_device =
|
||||
std::make_unique<xe::vfs::HostPathDevice>("\\CACHE0", L"cache0", false);
|
||||
std::make_unique<xe::vfs::HostPathDevice>("\\CACHE0", "cache0", false);
|
||||
if (!cache0_device->Initialize()) {
|
||||
XELOGE("Unable to scan cache0 path");
|
||||
} else {
|
||||
@@ -286,7 +286,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
}
|
||||
|
||||
auto cache1_device =
|
||||
std::make_unique<xe::vfs::HostPathDevice>("\\CACHE1", L"cache1", false);
|
||||
std::make_unique<xe::vfs::HostPathDevice>("\\CACHE1", "cache1", false);
|
||||
if (!cache1_device->Initialize()) {
|
||||
XELOGE("Unable to scan cache1 path");
|
||||
} else {
|
||||
@@ -325,7 +325,7 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
emulator->on_launch.AddListener([&](auto title_id, const auto& game_title) {
|
||||
if (cvars::discord) {
|
||||
discord::DiscordPresence::PlayingTitle(
|
||||
game_title.empty() ? L"Unknown Title" : game_title);
|
||||
game_title.empty() ? "Unknown Title" : std::string(game_title));
|
||||
}
|
||||
emulator_window->UpdateTitle();
|
||||
evt->Set();
|
||||
@@ -365,9 +365,9 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
emulator_window->window()->EnableMainMenu();
|
||||
|
||||
// Grab path from the flag or unnamed argument.
|
||||
std::wstring path;
|
||||
std::filesystem::path path;
|
||||
if (!cvars::target.empty()) {
|
||||
path = xe::to_wstring(cvars::target);
|
||||
path = cvars::target;
|
||||
}
|
||||
|
||||
// Toggles fullscreen
|
||||
@@ -375,10 +375,10 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
|
||||
if (!path.empty()) {
|
||||
// Normalize the path and make absolute.
|
||||
std::wstring abs_path = xe::to_absolute_path(path);
|
||||
auto abs_path = std::filesystem::absolute(path);
|
||||
result = emulator->LaunchPath(abs_path);
|
||||
if (XFAILED(result)) {
|
||||
xe::FatalError("Failed to launch target: %.8X", result);
|
||||
xe::FatalError(fmt::format("Failed to launch target: {:08X}", result));
|
||||
emulator.reset();
|
||||
emulator_window.reset();
|
||||
return 1;
|
||||
@@ -416,5 +416,5 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
||||
} // namespace app
|
||||
} // namespace xe
|
||||
|
||||
DEFINE_ENTRY_POINT(L"xenia", xe::app::xenia_main, "[Path to .iso/.xex]",
|
||||
DEFINE_ENTRY_POINT("xenia", xe::app::xenia_main, "[Path to .iso/.xex]",
|
||||
"target");
|
||||
|
||||
Reference in New Issue
Block a user