[Base] Move XdbfLocale to xbox.h as XLanguage, let STFS headers use it
Renamed to XLanguage because AFAIK locale on Xbox is a different concept involving countries, this enum only involves languages though.
This commit is contained in:
parent
99b7848a34
commit
ce19d948f0
|
@ -714,7 +714,7 @@ X_STATUS Emulator::CompleteLaunch(const std::filesystem::path& path,
|
||||||
module->memory()->TranslateVirtual(resource_data), resource_size);
|
module->memory()->TranslateVirtual(resource_data), resource_size);
|
||||||
if (db.is_valid()) {
|
if (db.is_valid()) {
|
||||||
// TODO(gibbed): get title respective to user locale.
|
// TODO(gibbed): get title respective to user locale.
|
||||||
title_name_ = db.title(kernel::util::XdbfLocale::kEnglish);
|
title_name_ = db.title(XLanguage::kEnglish);
|
||||||
if (title_name_.empty()) {
|
if (title_name_.empty()) {
|
||||||
// If English title is unavailable, get the title in default locale.
|
// If English title is unavailable, get the title in default locale.
|
||||||
title_name_ = db.title();
|
title_name_ = db.title();
|
||||||
|
|
|
@ -55,10 +55,10 @@ XdbfBlock XdbfWrapper::GetEntry(XdbfSection section, uint64_t id) const {
|
||||||
return {0};
|
return {0};
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string XdbfWrapper::GetStringTableEntry(XdbfLocale locale,
|
std::string XdbfWrapper::GetStringTableEntry(XLanguage language,
|
||||||
uint16_t string_id) const {
|
uint16_t string_id) const {
|
||||||
auto language_block =
|
auto language_block =
|
||||||
GetEntry(XdbfSection::kStringTable, static_cast<uint64_t>(locale));
|
GetEntry(XdbfSection::kStringTable, static_cast<uint64_t>(language));
|
||||||
if (!language_block) {
|
if (!language_block) {
|
||||||
return "";
|
return "";
|
||||||
}
|
}
|
||||||
|
@ -88,22 +88,22 @@ XdbfBlock XdbfGameData::icon() const {
|
||||||
return GetEntry(XdbfSection::kImage, kXdbfIdTitle);
|
return GetEntry(XdbfSection::kImage, kXdbfIdTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
XdbfLocale XdbfGameData::default_language() const {
|
XLanguage XdbfGameData::default_language() const {
|
||||||
auto block = GetEntry(XdbfSection::kMetadata, kXdbfIdXstc);
|
auto block = GetEntry(XdbfSection::kMetadata, kXdbfIdXstc);
|
||||||
if (!block.buffer) {
|
if (!block.buffer) {
|
||||||
return XdbfLocale::kEnglish;
|
return XLanguage::kEnglish;
|
||||||
}
|
}
|
||||||
auto xstc = reinterpret_cast<const XdbfXstc*>(block.buffer);
|
auto xstc = reinterpret_cast<const XdbfXstc*>(block.buffer);
|
||||||
assert_true(xstc->magic == kXdbfMagicXstc);
|
assert_true(xstc->magic == kXdbfMagicXstc);
|
||||||
return static_cast<XdbfLocale>(static_cast<uint32_t>(xstc->default_language));
|
return static_cast<XLanguage>(static_cast<uint32_t>(xstc->default_language));
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string XdbfGameData::title() const {
|
std::string XdbfGameData::title() const {
|
||||||
return GetStringTableEntry(default_language(), kXdbfIdTitle);
|
return GetStringTableEntry(default_language(), kXdbfIdTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::string XdbfGameData::title(XdbfLocale locale) const {
|
std::string XdbfGameData::title(XLanguage language) const {
|
||||||
return GetStringTableEntry(locale, kXdbfIdTitle);
|
return GetStringTableEntry(language, kXdbfIdTitle);
|
||||||
}
|
}
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
|
@ -14,6 +14,7 @@
|
||||||
#include <vector>
|
#include <vector>
|
||||||
|
|
||||||
#include "xenia/base/memory.h"
|
#include "xenia/base/memory.h"
|
||||||
|
#include "xenia/xbox.h"
|
||||||
|
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
|
@ -28,19 +29,6 @@ enum class XdbfSection : uint16_t {
|
||||||
kStringTable = 0x0003,
|
kStringTable = 0x0003,
|
||||||
};
|
};
|
||||||
|
|
||||||
// Found by dumping the kSectionStringTable sections of various games:
|
|
||||||
enum class XdbfLocale : uint32_t {
|
|
||||||
kUnknown = 0,
|
|
||||||
kEnglish = 1,
|
|
||||||
kJapanese = 2,
|
|
||||||
kGerman = 3,
|
|
||||||
kFrench = 4,
|
|
||||||
kSpanish = 5,
|
|
||||||
kItalian = 6,
|
|
||||||
kKorean = 7,
|
|
||||||
kChinese = 8,
|
|
||||||
};
|
|
||||||
|
|
||||||
struct XdbfBlock {
|
struct XdbfBlock {
|
||||||
const uint8_t* buffer;
|
const uint8_t* buffer;
|
||||||
size_t size;
|
size_t size;
|
||||||
|
@ -63,7 +51,7 @@ class XdbfWrapper {
|
||||||
|
|
||||||
// Gets a string from the string table in the given language.
|
// Gets a string from the string table in the given language.
|
||||||
// Returns the empty string if the entry is not found.
|
// Returns the empty string if the entry is not found.
|
||||||
std::string GetStringTableEntry(XdbfLocale locale, uint16_t string_id) const;
|
std::string GetStringTableEntry(XLanguage language, uint16_t string_id) const;
|
||||||
|
|
||||||
protected:
|
protected:
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
|
@ -133,12 +121,12 @@ class XdbfGameData : public XdbfWrapper {
|
||||||
XdbfBlock icon() const;
|
XdbfBlock icon() const;
|
||||||
|
|
||||||
// The game's default language.
|
// The game's default language.
|
||||||
XdbfLocale default_language() const;
|
XLanguage default_language() const;
|
||||||
|
|
||||||
// The game's title in its default language.
|
// The game's title in its default language.
|
||||||
std::string title() const;
|
std::string title() const;
|
||||||
|
|
||||||
std::string title(XdbfLocale locale) const;
|
std::string title(XLanguage language) const;
|
||||||
};
|
};
|
||||||
|
|
||||||
} // namespace util
|
} // namespace util
|
||||||
|
|
|
@ -28,9 +28,6 @@ namespace xe {
|
||||||
namespace kernel {
|
namespace kernel {
|
||||||
namespace xam {
|
namespace xam {
|
||||||
|
|
||||||
constexpr uint32_t X_LANGUAGE_ENGLISH = 1;
|
|
||||||
constexpr uint32_t X_LANGUAGE_JAPANESE = 2;
|
|
||||||
|
|
||||||
dword_result_t XamFeatureEnabled(dword_t unk) { return 0; }
|
dword_result_t XamFeatureEnabled(dword_t unk) { return 0; }
|
||||||
DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub);
|
DECLARE_XAM_EXPORT1(XamFeatureEnabled, kNone, kStub);
|
||||||
|
|
||||||
|
@ -208,19 +205,19 @@ dword_result_t XGetGameRegion() { return xeXGetGameRegion(); }
|
||||||
DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub);
|
DECLARE_XAM_EXPORT1(XGetGameRegion, kNone, kStub);
|
||||||
|
|
||||||
dword_result_t XGetLanguage() {
|
dword_result_t XGetLanguage() {
|
||||||
uint32_t desired_language = X_LANGUAGE_ENGLISH;
|
auto desired_language = XLanguage::kEnglish;
|
||||||
|
|
||||||
// Switch the language based on game region.
|
// Switch the language based on game region.
|
||||||
// TODO(benvanik): pull from xex header.
|
// TODO(benvanik): pull from xex header.
|
||||||
uint32_t game_region = XEX_REGION_NTSCU;
|
uint32_t game_region = XEX_REGION_NTSCU;
|
||||||
if (game_region & XEX_REGION_NTSCU) {
|
if (game_region & XEX_REGION_NTSCU) {
|
||||||
desired_language = X_LANGUAGE_ENGLISH;
|
desired_language = XLanguage::kEnglish;
|
||||||
} else if (game_region & XEX_REGION_NTSCJ) {
|
} else if (game_region & XEX_REGION_NTSCJ) {
|
||||||
desired_language = X_LANGUAGE_JAPANESE;
|
desired_language = XLanguage::kJapanese;
|
||||||
}
|
}
|
||||||
// Add more overrides?
|
// Add more overrides?
|
||||||
|
|
||||||
return desired_language;
|
return uint32_t(desired_language);
|
||||||
}
|
}
|
||||||
DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented);
|
DECLARE_XAM_EXPORT1(XGetLanguage, kNone, kImplemented);
|
||||||
|
|
||||||
|
|
|
@ -268,11 +268,13 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
char16_t description_ex_chars[kNumLanguagesV2 - kNumLanguagesV1][128];
|
char16_t description_ex_chars[kNumLanguagesV2 - kNumLanguagesV1][128];
|
||||||
};
|
};
|
||||||
|
|
||||||
std::u16string display_name(uint32_t lang_id) const {
|
std::u16string display_name(XLanguage language) const {
|
||||||
lang_id--;
|
uint32_t lang_id = uint32_t(language) - 1;
|
||||||
|
|
||||||
if (lang_id >= kNumLanguagesV2) {
|
if (lang_id >= kNumLanguagesV2) {
|
||||||
assert_always();
|
assert_always();
|
||||||
lang_id = 0; // no room for this lang, read from english slot..
|
// no room for this lang, read from english slot..
|
||||||
|
lang_id = uint32_t(XLanguage::kEnglish) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const be<uint16_t>* str = 0;
|
const be<uint16_t>* str = 0;
|
||||||
|
@ -284,17 +286,21 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
// Invalid language ID?
|
||||||
|
assert_always();
|
||||||
return u"";
|
return u"";
|
||||||
}
|
}
|
||||||
|
|
||||||
return load_and_swap<std::u16string>(str);
|
return load_and_swap<std::u16string>(str);
|
||||||
}
|
}
|
||||||
|
|
||||||
std::u16string description(uint32_t lang_id) const {
|
std::u16string description(XLanguage language) const {
|
||||||
lang_id--;
|
uint32_t lang_id = uint32_t(language) - 1;
|
||||||
|
|
||||||
if (lang_id >= kNumLanguagesV2) {
|
if (lang_id >= kNumLanguagesV2) {
|
||||||
assert_always();
|
assert_always();
|
||||||
lang_id = 0; // no room for this lang, read from english slot..
|
// no room for this lang, read from english slot..
|
||||||
|
lang_id = uint32_t(XLanguage::kEnglish) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
const be<uint16_t>* str = 0;
|
const be<uint16_t>* str = 0;
|
||||||
|
@ -306,6 +312,8 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
// Invalid language ID?
|
||||||
|
assert_always();
|
||||||
return u"";
|
return u"";
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -320,11 +328,13 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
return load_and_swap<std::u16string>(title_name_raw);
|
return load_and_swap<std::u16string>(title_name_raw);
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_display_name(uint32_t lang_id, const std::u16string_view value) {
|
bool set_display_name(XLanguage language, const std::u16string_view value) {
|
||||||
lang_id--;
|
uint32_t lang_id = uint32_t(language) - 1;
|
||||||
|
|
||||||
if (lang_id >= kNumLanguagesV2) {
|
if (lang_id >= kNumLanguagesV2) {
|
||||||
assert_always();
|
assert_always();
|
||||||
lang_id = 0; // no room for this lang, store in english slot..
|
// no room for this lang, store in english slot..
|
||||||
|
lang_id = uint32_t(XLanguage::kEnglish) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char16_t* str = 0;
|
char16_t* str = 0;
|
||||||
|
@ -336,6 +346,8 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
// Invalid language ID?
|
||||||
|
assert_always();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -344,11 +356,13 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool set_description(uint32_t lang_id, const std::u16string_view value) {
|
bool set_description(XLanguage language, const std::u16string_view value) {
|
||||||
lang_id--;
|
uint32_t lang_id = uint32_t(language) - 1;
|
||||||
|
|
||||||
if (lang_id >= kNumLanguagesV2) {
|
if (lang_id >= kNumLanguagesV2) {
|
||||||
assert_always();
|
assert_always();
|
||||||
lang_id = 0; // no room for this lang, store in english slot..
|
// no room for this lang, store in english slot..
|
||||||
|
lang_id = uint32_t(XLanguage::kEnglish) - 1;
|
||||||
}
|
}
|
||||||
|
|
||||||
char16_t* str = 0;
|
char16_t* str = 0;
|
||||||
|
@ -360,6 +374,8 @@ XEPACKEDSTRUCT(XContentMetadata, {
|
||||||
}
|
}
|
||||||
|
|
||||||
if (!str) {
|
if (!str) {
|
||||||
|
// Invalid language ID?
|
||||||
|
assert_always();
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -323,6 +323,27 @@ static_assert_size(X_EXCEPTION_RECORD, 0x50);
|
||||||
|
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
|
// Found by dumping the kSectionStringTable sections of various games:
|
||||||
|
// and the language list at
|
||||||
|
// https://free60project.github.io/wiki/Profile_Account/
|
||||||
|
enum class XLanguage : uint32_t {
|
||||||
|
kInvalid = 0,
|
||||||
|
kEnglish = 1,
|
||||||
|
kJapanese = 2,
|
||||||
|
kGerman = 3,
|
||||||
|
kFrench = 4,
|
||||||
|
kSpanish = 5,
|
||||||
|
kItalian = 6,
|
||||||
|
kKorean = 7,
|
||||||
|
kTChinese = 8,
|
||||||
|
kPortuguese = 9,
|
||||||
|
kSChinese = 10,
|
||||||
|
kPolish = 11,
|
||||||
|
kRussian = 12,
|
||||||
|
// STFS headers can't support any more languages than these
|
||||||
|
kMaxLanguages = 13
|
||||||
|
};
|
||||||
|
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
||||||
// clang-format on
|
// clang-format on
|
||||||
|
|
Loading…
Reference in New Issue