summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorgibbed <rick@gibbed.us>2018-11-21 18:04:43 -0600
committergibbed <rick@gibbed.us>2018-11-21 18:07:45 -0600
commit1ba5dd5eb1f78b1c018886f9dbb1c07245eb1262 (patch)
tree60b04690ca798e8a3e9ee28cce4e82884dd53c5d
parenteb55d68e1fcb8707756da8fe65ef76963dea91b1 (diff)
Use platform-specific user directory to store content. Create a file named portable.txt next to xenia.exe to restore previous behavior.
-rw-r--r--src/xenia/app/xenia_main.cc31
-rw-r--r--src/xenia/base/filesystem.h9
-rw-r--r--src/xenia/base/filesystem_posix.cc15
-rw-r--r--src/xenia/base/filesystem_win.cc22
-rw-r--r--src/xenia/emulator.cc5
-rw-r--r--src/xenia/emulator.h8
-rw-r--r--src/xenia/gpu/trace_dump.cc2
-rw-r--r--src/xenia/gpu/trace_viewer.cc2
-rw-r--r--src/xenia/kernel/kernel_state.cc4
9 files changed, 89 insertions, 9 deletions
diff --git a/src/xenia/app/xenia_main.cc b/src/xenia/app/xenia_main.cc
index def29b7c5..ee474485b 100644
--- a/src/xenia/app/xenia_main.cc
+++ b/src/xenia/app/xenia_main.cc
@@ -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());
diff --git a/src/xenia/base/filesystem.h b/src/xenia/base/filesystem.h
index f2f2684cf..8cce19719 100644
--- a/src/xenia/base/filesystem.h
+++ b/src/xenia/base/filesystem.h
@@ -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);
diff --git a/src/xenia/base/filesystem_posix.cc b/src/xenia/base/filesystem_posix.cc
index c3c2eaf80..66a90d56f 100644
--- a/src/xenia/base/filesystem_posix.cc
+++ b/src/xenia/base/filesystem_posix.cc
@@ -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;
diff --git a/src/xenia/base/filesystem_win.cc b/src/xenia/base/filesystem_win.cc
index c72ebea07..25b0c319d 100644
--- a/src/xenia/base/filesystem_win.cc
+++ b/src/xenia/base/filesystem_win.cc
@@ -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;
diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc
index 19a82a85e..8030a8078 100644
--- a/src/xenia/emulator.cc
+++ b/src/xenia/emulator.cc
@@ -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.
diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h
index 4492419e7..a60b4e2e7 100644
--- a/src/xenia/emulator.h
+++ b/src/xenia/emulator.h
@@ -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_;
diff --git a/src/xenia/gpu/trace_dump.cc b/src/xenia/gpu/trace_dump.cc
index 8c3de28be..66df289b7 100644
--- a/src/xenia/gpu/trace_dump.cc
+++ b/src/xenia/gpu/trace_dump.cc
@@ -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)) {
diff --git a/src/xenia/gpu/trace_viewer.cc b/src/xenia/gpu/trace_viewer.cc
index 4e08e7081..5549e358c 100644
--- a/src/xenia/gpu/trace_viewer.cc
+++ b/src/xenia/gpu/trace_viewer.cc
@@ -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);
diff --git a/src/xenia/kernel/kernel_state.cc b/src/xenia/kernel/kernel_state.cc
index 5cb8be150..aef2b9bc8 100644
--- a/src/xenia/kernel/kernel_state.cc
+++ b/src/xenia/kernel/kernel_state.cc
@@ -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);