[Kernel] XLast: Added posibility to read:
- Title Name - MatchmakingQuery - Input Parameters - Output - Filters (without operators) - Localized Strings
This commit is contained in:
parent
f54dc70d03
commit
c7e97d051b
|
@ -1185,8 +1185,8 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||||
const uint8_t* xlast_ptr =
|
const uint8_t* xlast_ptr =
|
||||||
db.ReadXLast(compressed_size, decompressed_size);
|
db.ReadXLast(compressed_size, decompressed_size);
|
||||||
|
|
||||||
title_xlast_ =
|
title_xlast_ = std::make_unique<kernel::util::XLast>(
|
||||||
kernel::util::XLast(xlast_ptr, compressed_size, decompressed_size);
|
xlast_ptr, compressed_size, decompressed_size);
|
||||||
|
|
||||||
auto icon_block = db.icon();
|
auto icon_block = db.icon();
|
||||||
if (icon_block) {
|
if (icon_block) {
|
||||||
|
|
|
@ -299,7 +299,7 @@ class Emulator {
|
||||||
kernel::object_ref<kernel::XThread> main_thread_;
|
kernel::object_ref<kernel::XThread> main_thread_;
|
||||||
kernel::object_ref<kernel::XHostThread> plugin_loader_thread_;
|
kernel::object_ref<kernel::XHostThread> plugin_loader_thread_;
|
||||||
std::optional<uint32_t> title_id_; // Currently running title ID
|
std::optional<uint32_t> title_id_; // Currently running title ID
|
||||||
kernel::util::XLast title_xlast_;
|
std::unique_ptr<kernel::util::XLast> title_xlast_;
|
||||||
|
|
||||||
bool paused_;
|
bool paused_;
|
||||||
bool restoring_;
|
bool restoring_;
|
||||||
|
|
|
@ -11,12 +11,35 @@
|
||||||
#include "third_party/zlib/zlib.h"
|
#include "third_party/zlib/zlib.h"
|
||||||
#include "xenia/base/filesystem.h"
|
#include "xenia/base/filesystem.h"
|
||||||
#include "xenia/base/logging.h"
|
#include "xenia/base/logging.h"
|
||||||
|
#include "xenia/base/string_util.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
XLast::XLast() {}
|
XLastMatchmakingQuery::XLastMatchmakingQuery() {}
|
||||||
|
XLastMatchmakingQuery::XLastMatchmakingQuery(
|
||||||
|
const pugi::xpath_node query_node) {
|
||||||
|
node_ = query_node;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::string XLastMatchmakingQuery::GetName() const {
|
||||||
|
return node_.node().attribute("friendlyName").value();
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> XLastMatchmakingQuery::GetReturns() const {
|
||||||
|
return XLast::GetAllValuesFromNode(node_, "Returns", "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> XLastMatchmakingQuery::GetParameters() const {
|
||||||
|
return XLast::GetAllValuesFromNode(node_, "Parameters", "id");
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> XLastMatchmakingQuery::GetFilters() const {
|
||||||
|
return XLast::GetAllValuesFromNode(node_, "Filters", "left");
|
||||||
|
}
|
||||||
|
|
||||||
|
XLast::XLast() : parsed_xlast_(nullptr) {}
|
||||||
|
|
||||||
XLast::XLast(const uint8_t* compressed_xml_data,
|
XLast::XLast(const uint8_t* compressed_xml_data,
|
||||||
const uint32_t compressed_data_size,
|
const uint32_t compressed_data_size,
|
||||||
|
@ -26,6 +49,7 @@ XLast::XLast(const uint8_t* compressed_xml_data,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
parsed_xlast_ = std::make_unique<pugi::xml_document>();
|
||||||
xlast_decompressed_xml_.resize(decompressed_data_size);
|
xlast_decompressed_xml_.resize(decompressed_data_size);
|
||||||
|
|
||||||
z_stream stream;
|
z_stream stream;
|
||||||
|
@ -55,17 +79,85 @@ XLast::XLast(const uint8_t* compressed_xml_data,
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
inflateEnd(&stream);
|
inflateEnd(&stream);
|
||||||
|
|
||||||
|
parse_result_ = parsed_xlast_->load_buffer(xlast_decompressed_xml_.data(),
|
||||||
|
xlast_decompressed_xml_.size());
|
||||||
}
|
}
|
||||||
|
|
||||||
XLast::~XLast() {}
|
XLast::~XLast() {}
|
||||||
|
|
||||||
|
std::u16string XLast::GetTitleName() {
|
||||||
|
std::string xpath = "/XboxLiveSubmissionProject/GameConfigProject";
|
||||||
|
|
||||||
|
const pugi::xpath_node node = parsed_xlast_->select_node(xpath.c_str());
|
||||||
|
if (!node) {
|
||||||
|
return std::u16string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xe::to_utf16(node.node().attribute("titleName").value());
|
||||||
|
}
|
||||||
|
|
||||||
|
std::u16string XLast::GetLocalizedString(uint32_t string_id,
|
||||||
|
XLanguage language) {
|
||||||
|
std::string xpath = fmt::format(
|
||||||
|
"/XboxLiveSubmissionProject/GameConfigProject/LocalizedStrings/"
|
||||||
|
"LocalizedString[@id = \"{}\"]",
|
||||||
|
string_id);
|
||||||
|
|
||||||
|
const pugi::xpath_node node = parsed_xlast_->select_node(xpath.c_str());
|
||||||
|
if (!node) {
|
||||||
|
return std::u16string();
|
||||||
|
}
|
||||||
|
|
||||||
|
const std::string locale_name = GetLocaleStringFromLanguage(language);
|
||||||
|
const pugi::xml_node locale_node =
|
||||||
|
node.node().find_child_by_attribute("locale", locale_name.c_str());
|
||||||
|
|
||||||
|
if (!locale_node) {
|
||||||
|
return std::u16string();
|
||||||
|
}
|
||||||
|
|
||||||
|
return xe::to_utf16(locale_node.child_value());
|
||||||
|
}
|
||||||
|
|
||||||
|
XLastMatchmakingQuery* XLast::GetMatchmakingQuery(const uint32_t query_id) {
|
||||||
|
std::string xpath = fmt::format(
|
||||||
|
"/XboxLiveSubmissionProject/GameConfigProject/Matchmaking/Queries/"
|
||||||
|
"Query[@id = \"{}\"]",
|
||||||
|
query_id);
|
||||||
|
|
||||||
|
XLastMatchmakingQuery* query = nullptr;
|
||||||
|
pugi::xpath_node node = parsed_xlast_->select_node(xpath.c_str());
|
||||||
|
if (!node) {
|
||||||
|
return query;
|
||||||
|
}
|
||||||
|
|
||||||
|
return new XLastMatchmakingQuery(node);
|
||||||
|
}
|
||||||
|
|
||||||
|
std::vector<uint32_t> XLast::GetAllValuesFromNode(
|
||||||
|
const pugi::xpath_node node, const std::string child_name,
|
||||||
|
const std::string attirbute_name) {
|
||||||
|
std::vector<uint32_t> result{};
|
||||||
|
|
||||||
|
const auto searched_child = node.node().child(child_name.c_str());
|
||||||
|
|
||||||
|
for (pugi::xml_node_iterator itr = searched_child.begin();
|
||||||
|
itr != searched_child.end(); itr++) {
|
||||||
|
result.push_back(xe::string_util::from_string<uint32_t>(
|
||||||
|
itr->attribute(attirbute_name.c_str()).value(), true));
|
||||||
|
}
|
||||||
|
|
||||||
|
return result;
|
||||||
|
}
|
||||||
|
|
||||||
void XLast::Dump(std::string file_name) {
|
void XLast::Dump(std::string file_name) {
|
||||||
if (xlast_decompressed_xml_.empty()) {
|
if (xlast_decompressed_xml_.empty()) {
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
|
|
||||||
if (file_name.empty()) {
|
if (file_name.empty()) {
|
||||||
// TODO: Read default xlast name from it and use that one.
|
file_name = xe::to_utf8(GetTitleName());
|
||||||
}
|
}
|
||||||
|
|
||||||
FILE* outfile =
|
FILE* outfile =
|
||||||
|
@ -79,6 +171,15 @@ void XLast::Dump(std::string file_name) {
|
||||||
fclose(outfile);
|
fclose(outfile);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
std::string XLast::GetLocaleStringFromLanguage(XLanguage language) {
|
||||||
|
const auto value = language_mapping.find(language);
|
||||||
|
if (value != language_mapping.cend()) {
|
||||||
|
return value->second;
|
||||||
|
}
|
||||||
|
|
||||||
|
return language_mapping.at(XLanguage::kEnglish);
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
} // namespace kernel
|
} // namespace kernel
|
||||||
} // namespace xe
|
} // namespace xe
|
|
@ -10,12 +10,39 @@
|
||||||
#ifndef XENIA_KERNEL_UTIL_XLAST_H_
|
#ifndef XENIA_KERNEL_UTIL_XLAST_H_
|
||||||
#define XENIA_KERNEL_UTIL_XLAST_H_
|
#define XENIA_KERNEL_UTIL_XLAST_H_
|
||||||
|
|
||||||
|
#include <map>
|
||||||
#include <string>
|
#include <string>
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
|
#include "third_party/pugixml/src/pugixml.hpp"
|
||||||
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace util {
|
namespace util {
|
||||||
|
|
||||||
|
static const std::map<XLanguage, std::string> language_mapping = {
|
||||||
|
{XLanguage::kEnglish, "en-US"}, {XLanguage::kJapanese, "ja-JP"},
|
||||||
|
{XLanguage::kGerman, "de-DE"}, {XLanguage::kFrench, "fr-FR"},
|
||||||
|
{XLanguage::kSpanish, "es-ES"}, {XLanguage::kItalian, "it-IT"},
|
||||||
|
{XLanguage::kKorean, "ko-KR"}, {XLanguage::kTChinese, "zh-CHT"},
|
||||||
|
{XLanguage::kPortuguese, "pt-PT"}, {XLanguage::kPolish, "pl-PL"},
|
||||||
|
{XLanguage::kRussian, "ru-RU"}};
|
||||||
|
|
||||||
|
class XLastMatchmakingQuery {
|
||||||
|
public:
|
||||||
|
XLastMatchmakingQuery();
|
||||||
|
XLastMatchmakingQuery(const pugi::xpath_node query_node);
|
||||||
|
|
||||||
|
std::string GetName() const;
|
||||||
|
std::vector<uint32_t> GetReturns() const;
|
||||||
|
std::vector<uint32_t> GetParameters() const;
|
||||||
|
std::vector<uint32_t> GetFilters() const;
|
||||||
|
|
||||||
|
private:
|
||||||
|
pugi::xpath_node node_;
|
||||||
|
};
|
||||||
|
|
||||||
class XLast {
|
class XLast {
|
||||||
public:
|
public:
|
||||||
XLast();
|
XLast();
|
||||||
|
@ -23,10 +50,21 @@ class XLast {
|
||||||
const uint32_t decompressed_data_size);
|
const uint32_t decompressed_data_size);
|
||||||
~XLast();
|
~XLast();
|
||||||
|
|
||||||
|
std::u16string GetTitleName();
|
||||||
|
std::u16string GetLocalizedString(uint32_t string_id, XLanguage language);
|
||||||
|
XLastMatchmakingQuery* GetMatchmakingQuery(uint32_t query_id);
|
||||||
|
static std::vector<uint32_t> GetAllValuesFromNode(
|
||||||
|
const pugi::xpath_node node, const std::string child_name,
|
||||||
|
const std::string attirbute_name);
|
||||||
|
|
||||||
void Dump(std::string file_name);
|
void Dump(std::string file_name);
|
||||||
|
|
||||||
private:
|
private:
|
||||||
|
std::string GetLocaleStringFromLanguage(XLanguage language);
|
||||||
|
|
||||||
std::vector<uint8_t> xlast_decompressed_xml_;
|
std::vector<uint8_t> xlast_decompressed_xml_;
|
||||||
|
std::unique_ptr<pugi::xml_document> parsed_xlast_ = nullptr;
|
||||||
|
pugi::xml_parse_result parse_result_ = {};
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
Loading…
Reference in New Issue