Use platform-specific user directory to store content. Create a file named portable.txt next to xenia.exe to restore previous behavior.
This commit is contained in:
parent
eb55d68e1f
commit
1ba5dd5eb1
|
@ -44,6 +44,8 @@ DEFINE_string(hid, "any", "Input system. Use: [any, nop, winkey, xinput]");
|
|||
DEFINE_string(target, "", "Specifies the target .xex or .iso to execute.");
|
||||
DEFINE_bool(fullscreen, false, "Toggles fullscreen");
|
||||
|
||||
DEFINE_string(content_root, "", "Root path for content (save/etc) storage.");
|
||||
|
||||
DEFINE_bool(mount_scratch, false, "Enable scratch mount");
|
||||
DEFINE_bool(mount_cache, false, "Enable cache mount");
|
||||
|
||||
|
@ -129,8 +131,35 @@ int xenia_main(const std::vector<std::wstring>& args) {
|
|||
Profiler::Initialize();
|
||||
Profiler::ThreadEnter("main");
|
||||
|
||||
// Figure out where content should go.
|
||||
std::wstring content_root;
|
||||
if (!FLAGS_content_root.empty()) {
|
||||
content_root = xe::to_wstring(FLAGS_content_root);
|
||||
} else {
|
||||
auto base_path = xe::filesystem::GetExecutableFolder();
|
||||
base_path = xe::to_absolute_path(base_path);
|
||||
|
||||
auto portable_path = xe::join_paths(base_path, L"portable.txt");
|
||||
if (xe::filesystem::PathExists(portable_path)) {
|
||||
content_root = xe::join_paths(base_path, L"content");
|
||||
} else {
|
||||
content_root = xe::filesystem::GetUserFolder();
|
||||
#if defined(XE_PLATFORM_WIN32)
|
||||
content_root = xe::join_paths(content_root, L"Xenia");
|
||||
#elif defined(XE_PLATFORM_LINUX)
|
||||
content_root = xe::join_paths(content_root, L".xenia");
|
||||
#else
|
||||
#warning Unhandled platform for content root.
|
||||
content_root = xe::join_paths(content_root, L"Xenia");
|
||||
#endif
|
||||
content_root = xe::join_paths(content_root, L"content");
|
||||
}
|
||||
|
||||
content_root = xe::to_absolute_path(content_root);
|
||||
}
|
||||
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
auto emulator = std::make_unique<Emulator>(L"");
|
||||
auto emulator = std::make_unique<Emulator>(L"", content_root);
|
||||
|
||||
// Main emulator display window.
|
||||
auto emulator_window = EmulatorWindow::Create(emulator.get());
|
||||
|
|
|
@ -20,6 +20,15 @@
|
|||
namespace xe {
|
||||
namespace filesystem {
|
||||
|
||||
// Get executable path.
|
||||
std::wstring GetExecutablePath();
|
||||
|
||||
// Get executable folder.
|
||||
std::wstring GetExecutableFolder();
|
||||
|
||||
// Get user folder.
|
||||
std::wstring GetUserFolder();
|
||||
|
||||
// Canonicalizes a path, removing ..'s.
|
||||
std::string CanonicalizePath(const std::string& original_path);
|
||||
|
||||
|
|
|
@ -21,6 +21,21 @@
|
|||
namespace xe {
|
||||
namespace filesystem {
|
||||
|
||||
std::wstring GetExecutablePath() {
|
||||
assert_always(); // IMPLEMENT ME.
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
std::wstring GetExecutableFolder() {
|
||||
assert_always(); // IMPLEMENT ME.
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
std::wstring GetUserFolder() {
|
||||
assert_always(); // IMPLEMENT ME.
|
||||
return std::wstring();
|
||||
}
|
||||
|
||||
bool PathExists(const std::wstring& path) {
|
||||
struct stat st;
|
||||
return stat(xe::to_string(path).c_str(), &st) == 0;
|
||||
|
|
|
@ -12,11 +12,33 @@
|
|||
|
||||
#include <string>
|
||||
|
||||
#include <shlobj.h>
|
||||
|
||||
#include "xenia/base/platform_win.h"
|
||||
|
||||
namespace xe {
|
||||
namespace filesystem {
|
||||
|
||||
std::wstring GetExecutablePath() {
|
||||
wchar_t* path;
|
||||
auto error = _get_wpgmptr(&path);
|
||||
return !error ? std::wstring(path) : std::wstring();
|
||||
}
|
||||
|
||||
std::wstring GetExecutableFolder() {
|
||||
auto path = GetExecutablePath();
|
||||
return xe::find_base_path(path);
|
||||
}
|
||||
|
||||
std::wstring GetUserFolder() {
|
||||
wchar_t path[MAX_PATH];
|
||||
if (!SUCCEEDED(SHGetFolderPathW(nullptr, CSIDL_MYDOCUMENTS, nullptr,
|
||||
SHGFP_TYPE_CURRENT, path))) {
|
||||
return std::wstring();
|
||||
}
|
||||
return std::wstring(path);
|
||||
}
|
||||
|
||||
bool PathExists(const std::wstring& path) {
|
||||
DWORD attrib = GetFileAttributes(path.c_str());
|
||||
return attrib != INVALID_FILE_ATTRIBUTES;
|
||||
|
|
|
@ -48,8 +48,9 @@ DEFINE_double(time_scalar, 1.0,
|
|||
|
||||
namespace xe {
|
||||
|
||||
Emulator::Emulator(const std::wstring& command_line)
|
||||
: command_line_(command_line) {}
|
||||
Emulator::Emulator(const std::wstring& command_line,
|
||||
const std::wstring& content_root)
|
||||
: command_line_(command_line), content_root_(content_root) {}
|
||||
|
||||
Emulator::~Emulator() {
|
||||
// Note that we delete things in the reverse order they were initialized.
|
||||
|
|
|
@ -47,12 +47,16 @@ namespace xe {
|
|||
// This is responsible for initializing and managing all the various subsystems.
|
||||
class Emulator {
|
||||
public:
|
||||
explicit Emulator(const std::wstring& command_line);
|
||||
explicit Emulator(const std::wstring& command_line,
|
||||
const std::wstring& content_root);
|
||||
~Emulator();
|
||||
|
||||
// Full command line used when launching the process.
|
||||
const std::wstring& command_line() const { return command_line_; }
|
||||
|
||||
// Folder content is stored in.
|
||||
const std::wstring& content_root() const { return content_root_; }
|
||||
|
||||
// Title of the game in the default language.
|
||||
const std::wstring& game_title() const { return game_title_; }
|
||||
|
||||
|
@ -154,6 +158,8 @@ class Emulator {
|
|||
const std::string& module_path);
|
||||
|
||||
std::wstring command_line_;
|
||||
std::wstring content_root_;
|
||||
|
||||
std::wstring game_title_;
|
||||
|
||||
ui::Window* display_window_;
|
||||
|
|
|
@ -103,7 +103,7 @@ int TraceDump::Main(const std::vector<std::wstring>& args) {
|
|||
|
||||
bool TraceDump::Setup() {
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
emulator_ = std::make_unique<Emulator>(L"");
|
||||
emulator_ = std::make_unique<Emulator>(L"", L"");
|
||||
X_STATUS result = emulator_->Setup(
|
||||
nullptr, nullptr, [this]() { return CreateGraphicsSystem(); }, nullptr);
|
||||
if (XFAILED(result)) {
|
||||
|
|
|
@ -122,7 +122,7 @@ bool TraceViewer::Setup() {
|
|||
window_->Resize(1920, 1200);
|
||||
|
||||
// Create the emulator but don't initialize so we can setup the window.
|
||||
emulator_ = std::make_unique<Emulator>(L"");
|
||||
emulator_ = std::make_unique<Emulator>(L"", L"");
|
||||
X_STATUS result =
|
||||
emulator_->Setup(window_.get(), nullptr,
|
||||
[this]() { return CreateGraphicsSystem(); }, nullptr);
|
||||
|
|
|
@ -31,8 +31,6 @@
|
|||
|
||||
DEFINE_bool(headless, false,
|
||||
"Don't display any UI, using defaults for prompts as needed.");
|
||||
DEFINE_string(content_root, "content",
|
||||
"Root path for content (save/etc) storage.");
|
||||
|
||||
namespace xe {
|
||||
namespace kernel {
|
||||
|
@ -57,7 +55,7 @@ KernelState::KernelState(Emulator* emulator)
|
|||
app_manager_ = std::make_unique<xam::AppManager>();
|
||||
user_profile_ = std::make_unique<xam::UserProfile>();
|
||||
|
||||
auto content_root = xe::to_wstring(FLAGS_content_root);
|
||||
auto content_root = emulator_->content_root();
|
||||
content_root = xe::to_absolute_path(content_root);
|
||||
content_manager_ = std::make_unique<xam::ContentManager>(this, content_root);
|
||||
|
||||
|
|
Loading…
Reference in New Issue