ContentManager: add support for STFS packages, title_id override

Normally ContentManager resolves package paths by using kernel_state_->title_id() as the title ID, but if we want to use ContentManager for TU's that won't work, since the XEX won't be fully loaded into kernel_state_->executable_module_ yet.

We can get around this by allowing the title ID used by ContentManager to be overridden, this should also help us support games that load packages from other title IDs.
This commit is contained in:
emoose 2018-11-01 18:26:24 +00:00 committed by illusion
parent d55960fce5
commit d89a4883bb
2 changed files with 21 additions and 25 deletions

View File

@ -16,6 +16,7 @@
#include "xenia/base/string.h" #include "xenia/base/string.h"
#include "xenia/kernel/kernel_state.h" #include "xenia/kernel/kernel_state.h"
#include "xenia/kernel/xam/content_package.h" #include "xenia/kernel/xam/content_package.h"
#include "xenia/kernel/user_module.h"
#include "xenia/kernel/xobject.h" #include "xenia/kernel/xobject.h"
#include "xenia/vfs/devices/host_path_device.h" #include "xenia/vfs/devices/host_path_device.h"
#include "xenia/vfs/devices/stfs_container_device.h" #include "xenia/vfs/devices/stfs_container_device.h"
@ -33,36 +34,24 @@ ContentManager::ContentManager(KernelState* kernel_state,
ContentManager::~ContentManager() = default; ContentManager::~ContentManager() = default;
uint32_t ContentManager::title_id() {
if (title_id_override_) {
return title_id_override_;
}
if (!kernel_state_->GetExecutableModule()) {
return -1;
}
return kernel_state_->title_id();
}
std::filesystem::path ContentManager::ResolvePackageRoot( std::filesystem::path ContentManager::ResolvePackageRoot(
uint32_t content_type) { uint32_t content_type) {
auto title_id = fmt::format("{:8X}", kernel_state_->title_id()); auto title_id_str = fmt::format("{:8X}", title_id());
auto content_type_str = fmt::format("{:8X}", content_type);
std::string type_name;
switch (content_type) {
case 1:
// Save games.
type_name = "00000001";
break;
case 2:
// DLC from the marketplace.
type_name = "00000002";
break;
case 3:
// Publisher content?
type_name = "00000003";
break;
case 0x000D0000:
// ???
type_name = "000D0000";
break;
default:
assert_unhandled_case(data.content_type);
return std::filesystem::path();
}
// Package root path: // Package root path:
// content_root/title_id/type_name/ // content_root/title_id/type_name/
return root_path_ / title_id / type_name; return root_path_ / title_id_str / content_type_str;
} }
std::filesystem::path ContentManager::ResolvePackagePath( std::filesystem::path ContentManager::ResolvePackagePath(

View File

@ -82,16 +82,23 @@ class ContentManager {
X_RESULT DeleteContent(const XCONTENT_DATA& data); X_RESULT DeleteContent(const XCONTENT_DATA& data);
std::filesystem::path ResolveGameUserContentPath(); std::filesystem::path ResolveGameUserContentPath();
void SetTitleIdOverride(uint32_t title_id) { title_id_override_ = title_id; }
private: private:
std::filesystem::path ResolvePackageRoot(uint32_t content_type); std::filesystem::path ResolvePackageRoot(uint32_t content_type);
std::filesystem::path ResolvePackagePath(const XCONTENT_DATA& data); std::filesystem::path ResolvePackagePath(const XCONTENT_DATA& data);
uint32_t title_id();
KernelState* kernel_state_; KernelState* kernel_state_;
std::filesystem::path root_path_; std::filesystem::path root_path_;
// TODO(benvanik): remove use of global lock, it's bad here! // TODO(benvanik): remove use of global lock, it's bad here!
xe::global_critical_region global_critical_region_; xe::global_critical_region global_critical_region_;
std::vector<ContentPackage*> open_packages_; std::vector<ContentPackage*> open_packages_;
uint32_t title_id_override_; // can be used for games/apps that request
// content for other IDs
}; };
} // namespace xam } // namespace xam