From 9c93fa5187db4e061a2b13f4b246e76d0ddc6758 Mon Sep 17 00:00:00 2001 From: Ben Vanik Date: Sun, 10 Jan 2016 11:04:55 -0800 Subject: [PATCH] Cleaning up xdbf stuff. - moving next to xex utils - fixing error cases around icon setting (and allowing reset) - making C++11 - abstracting a bit so future additions will be easier - fixing non-xex uses --- premake5.lua | 1 - src/xenia/app/emulator_window.cc | 4 +- src/xenia/app/premake5.lua | 1 - src/xenia/emulator.cc | 37 ++++--- src/xenia/emulator.h | 4 +- src/xenia/gpu/trace_player.cc | 2 +- src/xenia/kernel/util/xdbf_utils.cc | 107 ++++++++++++++++++++ src/xenia/kernel/util/xdbf_utils.h | 146 ++++++++++++++++++++++++++++ src/xenia/ui/window.h | 3 +- src/xenia/ui/window_win.cc | 29 ++++-- src/xenia/ui/window_win.h | 3 +- src/xenia/xdbf/premake5.lua | 17 ---- src/xenia/xdbf/xdbf_utils.cc | 142 --------------------------- src/xenia/xdbf/xdbf_utils.h | 129 ------------------------ 14 files changed, 299 insertions(+), 326 deletions(-) create mode 100644 src/xenia/kernel/util/xdbf_utils.cc create mode 100644 src/xenia/kernel/util/xdbf_utils.h delete mode 100644 src/xenia/xdbf/premake5.lua delete mode 100644 src/xenia/xdbf/xdbf_utils.cc delete mode 100644 src/xenia/xdbf/xdbf_utils.h diff --git a/premake5.lua b/premake5.lua index c559c7361..3431b60da 100644 --- a/premake5.lua +++ b/premake5.lua @@ -190,7 +190,6 @@ solution("xenia") include("src/xenia/ui/gl") include("src/xenia/ui/spirv") include("src/xenia/vfs") - include("src/xenia/xdbf") if os.is("windows") then include("src/xenia/apu/xaudio2") diff --git a/src/xenia/app/emulator_window.cc b/src/xenia/app/emulator_window.cc index 123cbe86e..abd010696 100644 --- a/src/xenia/app/emulator_window.cc +++ b/src/xenia/app/emulator_window.cc @@ -289,9 +289,9 @@ void EmulatorWindow::ShowHelpWebsite() { LaunchBrowser("http://xenia.jp"); } void EmulatorWindow::UpdateTitle() { std::wstring title(base_title_); - const std::wstring &game_title(emulator()->game_title()); + auto game_title = emulator()->game_title(); if (!game_title.empty()) { - title = game_title + L" - " + title; + title += L" - " + game_title; } if (Clock::guest_time_scalar() != 1.0) { diff --git a/src/xenia/app/premake5.lua b/src/xenia/app/premake5.lua index 245e90d69..d72059e22 100644 --- a/src/xenia/app/premake5.lua +++ b/src/xenia/app/premake5.lua @@ -25,7 +25,6 @@ project("xenia-app") "xenia-ui", "xenia-ui-gl", "xenia-vfs", - "xenia-xdbf", }) flags({ "WinMain", -- Use WinMain instead of main. diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index f2182f62f..d0e3a2c2d 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -27,6 +27,7 @@ #include "xenia/hid/input_system.h" #include "xenia/kernel/kernel_state.h" #include "xenia/kernel/user_module.h" +#include "xenia/kernel/util/xdbf_utils.h" #include "xenia/kernel/xam/xam_module.h" #include "xenia/kernel/xboxkrnl/xboxkrnl_module.h" #include "xenia/memory.h" @@ -35,7 +36,6 @@ #include "xenia/vfs/devices/host_path_device.h" #include "xenia/vfs/devices/stfs_container_device.h" #include "xenia/vfs/virtual_file_system.h" -#include "xenia/xdbf/xdbf_utils.h" DEFINE_double(time_scalar, 1.0, "Scalar used to speed or slow time (1x, 2x, 1/2x, etc)."); @@ -498,8 +498,8 @@ void Emulator::WaitUntilExit() { } } -X_STATUS Emulator::CompleteLaunch(const std::wstring &path, - const std::string &module_path, +X_STATUS Emulator::CompleteLaunch(const std::wstring& path, + const std::string& module_path, std::function on_launch) { // Allow xam to request module loads. auto xam = kernel_state()->GetKernelModule("xam.xex"); @@ -516,22 +516,21 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring &path, kernel_state_->SetExecutableModule(module); - // Try and load the resource database (xex only) - char title[9] = {0}; - sprintf(title, "%08X", module->title_id()); - - uint32_t resource_data = 0; - uint32_t resource_size = 0; - if (XSUCCEEDED(module->GetSection(title, &resource_data, &resource_size))) { - auto xdb_ptr = module->memory()->TranslateVirtual(resource_data); - if (xdb_ptr != nullptr) { - xe::xdbf::XdbfWrapper db; - if (db.initialize(xdb_ptr, static_cast(resource_size))) { - game_title_ = xe::to_wstring(xe::xdbf::get_title(db)); - xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db); - if (icon_block.buffer != nullptr) { - display_window_->SetIconFromBuffer(icon_block.buffer, - icon_block.size); + // Try and load the resource database (xex only). + if (module->title_id()) { + char title_id[9] = {0}; + std::sprintf(title_id, "%08X", module->title_id()); + uint32_t resource_data = 0; + uint32_t resource_size = 0; + if (XSUCCEEDED( + module->GetSection(title_id, &resource_data, &resource_size))) { + kernel::util::XdbfGameData db( + module->memory()->TranslateVirtual(resource_data), resource_size); + if (db.is_valid()) { + game_title_ = xe::to_wstring(db.title()); + auto icon_block = db.icon(); + if (icon_block) { + display_window_->SetIcon(icon_block.buffer, icon_block.size); } } } diff --git a/src/xenia/emulator.h b/src/xenia/emulator.h index 23a71561f..692e57f8c 100644 --- a/src/xenia/emulator.h +++ b/src/xenia/emulator.h @@ -135,8 +135,8 @@ class Emulator { static bool ExceptionCallbackThunk(Exception* ex, void* data); bool ExceptionCallback(Exception* ex); - X_STATUS CompleteLaunch(const std::wstring &path, - const std::string &module_path, + X_STATUS CompleteLaunch(const std::wstring& path, + const std::string& module_path, std::function on_launch); std::wstring command_line_; diff --git a/src/xenia/gpu/trace_player.cc b/src/xenia/gpu/trace_player.cc index 8ea2c402d..54c199736 100644 --- a/src/xenia/gpu/trace_player.cc +++ b/src/xenia/gpu/trace_player.cc @@ -35,7 +35,7 @@ TracePlayer::TracePlayer(xe::ui::Loop* loop, GraphicsSystem* graphics_system) TracePlayer::~TracePlayer() = default; const TraceReader::Frame* TracePlayer::current_frame() const { - if (current_frame_index_ > frame_count()) { + if (current_frame_index_ >= frame_count()) { return nullptr; } return frame(current_frame_index_); diff --git a/src/xenia/kernel/util/xdbf_utils.cc b/src/xenia/kernel/util/xdbf_utils.cc new file mode 100644 index 000000000..e79b15449 --- /dev/null +++ b/src/xenia/kernel/util/xdbf_utils.cc @@ -0,0 +1,107 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#include "xenia/kernel/util/xdbf_utils.h" + +namespace xe { +namespace kernel { +namespace util { + +constexpr uint32_t kXdbfMagicXdbf = 'XDBF'; +constexpr uint32_t kXdbfMagicXstc = 'XSTC'; +constexpr uint32_t kXdbfMagicXstr = 'XSTR'; + +XdbfWrapper::XdbfWrapper(const uint8_t* data, size_t data_size) + : data_(data), data_size_(data_size) { + if (!data || data_size <= sizeof(XbdfHeader)) { + data_ = nullptr; + return; + } + + const uint8_t* ptr = data_; + + header_ = reinterpret_cast(ptr); + ptr += sizeof(XbdfHeader); + if (header_->magic != kXdbfMagicXdbf) { + data_ = nullptr; + return; + } + + entries_ = reinterpret_cast(ptr); + ptr += sizeof(XbdfEntry) * header_->entry_count; + + files_ = reinterpret_cast(ptr); + ptr += sizeof(XbdfFileLoc) * header_->free_count; + + content_offset_ = ptr; +} + +XdbfBlock XdbfWrapper::GetEntry(XdbfSection section, uint64_t id) const { + for (uint32_t i = 0; i < header_->entry_used; ++i) { + auto& entry = entries_[i]; + if (entry.section == static_cast(section) && entry.id == id) { + XdbfBlock block; + block.buffer = content_offset_ + entry.offset; + block.size = entry.size; + return block; + } + } + return {0}; +} + +std::string XdbfWrapper::GetStringTableEntry(XdbfLocale locale, + uint16_t string_id) const { + auto language_block = + GetEntry(XdbfSection::kStringTable, static_cast(locale)); + if (!language_block) { + return ""; + } + + auto xstr_head = + reinterpret_cast(language_block.buffer); + assert_true(xstr_head->magic == kXdbfMagicXstr); + assert_true(xstr_head->version == 1); + + const uint8_t* ptr = language_block.buffer + sizeof(XdbfXstrHeader); + for (uint16_t i = 0; i < xstr_head->string_count; ++i) { + auto entry = reinterpret_cast(ptr); + ptr += sizeof(XdbfStringTableEntry); + if (entry->id == string_id) { + return std::string(reinterpret_cast(ptr), + entry->string_length); + } + ptr += entry->string_length; + } + return ""; +} + +constexpr uint64_t kXdbfIdTitle = 0x8000; +constexpr uint64_t kXdbfIdXstc = 0x58535443; + +XdbfBlock XdbfGameData::icon() const { + return GetEntry(XdbfSection::kImage, kXdbfIdTitle); +} + +XdbfLocale XdbfGameData::default_language() const { + auto block = GetEntry(XdbfSection::kMetadata, kXdbfIdXstc); + if (!block.buffer) { + return XdbfLocale::kEnglish; + } + auto xstc = reinterpret_cast(block.buffer); + assert_true(xstc->magic == kXdbfMagicXstc); + return static_cast(static_cast(xstc->default_language)); +} + +std::string XdbfGameData::title() const { + return GetStringTableEntry(default_language(), kXdbfIdTitle); +} + +} // namespace util +} // namespace kernel +} // namespace xe diff --git a/src/xenia/kernel/util/xdbf_utils.h b/src/xenia/kernel/util/xdbf_utils.h new file mode 100644 index 000000000..36631cfc7 --- /dev/null +++ b/src/xenia/kernel/util/xdbf_utils.h @@ -0,0 +1,146 @@ +/** + ****************************************************************************** + * Xenia : Xbox 360 Emulator Research Project * + ****************************************************************************** + * Copyright 2016 Ben Vanik. All rights reserved. * + * Released under the BSD license - see LICENSE in the root for more details. * + ****************************************************************************** + */ + +#ifndef XENIA_KERNEL_UTIL_XDBF_UTILS_H_ +#define XENIA_KERNEL_UTIL_XDBF_UTILS_H_ + +#include +#include + +#include "xenia/base/memory.h" + +namespace xe { +namespace kernel { +namespace util { + +// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.h +// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.cpp + +enum class XdbfSection : uint16_t { + kMetadata = 0x0001, + kImage = 0x0002, + 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 { + const uint8_t* buffer; + size_t size; + + operator bool() const { return buffer != nullptr; } +}; + +// Wraps an XBDF (XboxDataBaseFormat) in-memory database. +// http://www.free60.org/wiki/XDBF +class XdbfWrapper { + public: + XdbfWrapper(const uint8_t* data, size_t data_size); + + // True if the target memory contains a valid XDBF instance. + bool is_valid() const { return data_ != nullptr; } + + // Gets an entry in the given section. + // If the entry is not found the returned block will be nullptr. + XdbfBlock GetEntry(XdbfSection section, uint64_t id) const; + + // Gets a string from the string table in the given language. + // Returns the empty string if the entry is not found. + std::string GetStringTableEntry(XdbfLocale locale, uint16_t string_id) const; + + protected: +#pragma pack(push, 1) + struct XbdfHeader { + xe::be magic; + xe::be version; + xe::be entry_count; + xe::be entry_used; + xe::be free_count; + xe::be free_used; + }; + static_assert_size(XbdfHeader, 24); + + struct XbdfEntry { + xe::be section; + xe::be id; + xe::be offset; + xe::be size; + }; + static_assert_size(XbdfEntry, 18); + + struct XbdfFileLoc { + xe::be offset; + xe::be size; + }; + static_assert_size(XbdfFileLoc, 8); + + struct XdbfXstc { + xe::be magic; + xe::be version; + xe::be size; + xe::be default_language; + }; + static_assert_size(XdbfXstc, 16); + + struct XdbfXstrHeader { + xe::be magic; + xe::be version; + xe::be size; + xe::be string_count; + }; + static_assert_size(XdbfXstrHeader, 14); + + struct XdbfStringTableEntry { + xe::be id; + xe::be string_length; + }; + static_assert_size(XdbfStringTableEntry, 4); +#pragma pack(pop) + + private: + const uint8_t* data_ = nullptr; + size_t data_size_ = 0; + const uint8_t* content_offset_ = nullptr; + + const XbdfHeader* header_ = nullptr; + const XbdfEntry* entries_ = nullptr; + const XbdfFileLoc* files_ = nullptr; +}; + +class XdbfGameData : public XdbfWrapper { + public: + XdbfGameData(const uint8_t* data, size_t data_size) + : XdbfWrapper(data, data_size) {} + + // The game icon image, if found. + XdbfBlock icon() const; + + // The game's default language. + XdbfLocale default_language() const; + + // The game's title in its default language. + std::string title() const; +}; + +} // namespace util +} // namespace kernel +} // namespace xe + +#endif // XENIA_KERNEL_UTIL_XDBF_UTILS_H_ diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index d894d9276..eb14c9f89 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -53,7 +53,8 @@ class Window { return true; } - virtual bool SetIconFromBuffer(void* buffer, size_t size) = 0; + virtual bool SetIcon(const void* buffer, size_t size) = 0; + void ResetIcon() { SetIcon(nullptr, 0); } virtual bool is_fullscreen() const { return false; } virtual void ToggleFullscreen(bool fullscreen) {} diff --git a/src/xenia/ui/window_win.cc b/src/xenia/ui/window_win.cc index d3c6224b7..a02becc75 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -31,7 +31,7 @@ Win32Window::~Win32Window() { CloseWindow(hwnd_); hwnd_ = nullptr; } - if (icon_ != nullptr) { + if (icon_) { DestroyIcon(icon_); icon_ = nullptr; } @@ -167,20 +167,29 @@ bool Win32Window::set_title(const std::wstring& title) { return true; } -bool Win32Window::SetIconFromBuffer(void* buffer, size_t size) { +bool Win32Window::SetIcon(const void* buffer, size_t size) { if (icon_ != nullptr) { DestroyIcon(icon_); + icon_ = nullptr; } - HICON icon = CreateIconFromResourceEx(reinterpret_cast(buffer), - static_cast(size), TRUE, - 0x00030000, 0, 0, LR_DEFAULTCOLOR); + // Reset icon to default. + auto default_icon = LoadIcon(GetModuleHandle(nullptr), L"MAINICON"); + SendMessage(hwnd_, WM_SETICON, ICON_BIG, + reinterpret_cast(default_icon)); + SendMessage(hwnd_, WM_SETICON, ICON_SMALL, + reinterpret_cast(default_icon)); + if (!buffer || !size) { + return true; + } - if (icon != nullptr) { - icon_ = icon; - - SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon)); - SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon)); + // Create icon and set on window (if it's valid). + icon_ = CreateIconFromResourceEx( + reinterpret_cast(const_cast(buffer)), + static_cast(size), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR); + if (icon_) { + SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon_)); + SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon_)); } return false; diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index 296baba45..3240650c6 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -31,7 +31,8 @@ class Win32Window : public Window { HWND hwnd() const { return hwnd_; } bool set_title(const std::wstring& title) override; - bool SetIconFromBuffer(void* buffer, size_t size) override; + + bool SetIcon(const void* buffer, size_t size) override; bool is_fullscreen() const override; void ToggleFullscreen(bool fullscreen) override; diff --git a/src/xenia/xdbf/premake5.lua b/src/xenia/xdbf/premake5.lua deleted file mode 100644 index 44e9e6a64..000000000 --- a/src/xenia/xdbf/premake5.lua +++ /dev/null @@ -1,17 +0,0 @@ -project_root = "../../.." -include(project_root.."/tools/build") - -group("src") -project("xenia-xdbf") - uuid("a95b5fce-1083-4bff-a022-ffdd0bab3db0") - kind("StaticLib") - language("C++") - links({ - "xenia-base", - }) - defines({ - }) - includedirs({ - project_root.."third_party/gflags/src", - }) - recursive_platform_files() diff --git a/src/xenia/xdbf/xdbf_utils.cc b/src/xenia/xdbf/xdbf_utils.cc deleted file mode 100644 index e60a88d80..000000000 --- a/src/xenia/xdbf/xdbf_utils.cc +++ /dev/null @@ -1,142 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#include "xenia/xdbf/xdbf_utils.h" - -namespace xe { -namespace xdbf { - -enum XdbfId : uint64_t { - kIdTitle = 0x8000, - kIdXSTC = 0x58535443, -}; - -enum XdbgMagic : uint32_t { - kMagicXSTC = 'XSTC', - kMagicXSTR = 'XSTR', -}; - -XdbfWrapper::XdbfWrapper() = default; - -XBDF_HEADER& XdbfWrapper::get_header() const { return *state_.header; } - -XBDF_ENTRY& XdbfWrapper::get_entry(uint32_t n) const { - return state_.entries[n]; -} - -XBDF_FILE_LOC& XdbfWrapper::get_file(uint32_t n) const { - return state_.files[n]; -} - -bool XdbfWrapper::initialize(uint8_t* buffer, size_t length) { - if (length <= sizeof(XBDF_HEADER)) { - return false; - } - - XdbfState state; - - state.data = buffer; - state.size = length; - - uint8_t* ptr = state.data; - - state.header = reinterpret_cast(ptr); - ptr += sizeof(XBDF_HEADER); - - state.entries = reinterpret_cast(ptr); - ptr += (sizeof(XBDF_ENTRY) * state.header->entry_count); - - state.files = reinterpret_cast(ptr); - ptr += (sizeof(XBDF_FILE_LOC) * state.header->free_count); - - state.offset = ptr; - - if (state.header->magic == 'XDBF') { - state_ = state; - return true; - } - - return false; -} - -XdbfBlock XdbfWrapper::get_entry(XdbfSection section, uint64_t id) const { - XdbfBlock block = {nullptr, 0}; - uint32_t x = 0; - - while (x < get_header().entry_used) { - auto& entry = get_entry(x); - - if (entry.section == section && entry.id == id) { - block.buffer = state_.offset + entry.offset; - block.size = entry.size; - break; - } - - ++x; - } - - return block; -} - -XdbfBlock get_icon(const XdbfWrapper& ref) { - return ref.get_entry(kSectionImage, kIdTitle); -} - -XdbfLocale get_default_language(const XdbfWrapper& ref) { - XdbfBlock block = ref.get_entry(kSectionMetadata, kIdXSTC); - if (block.buffer != nullptr) { - XDBF_XSTC* xstc = reinterpret_cast(block.buffer); - assert_true(xstc->magic == kMagicXSTC); - - uint32_t default_language = xstc->default_language; - return static_cast(default_language); - } - - return kLocaleEnglish; -} - -std::string get_title(const XdbfWrapper& ref) { - std::string title_str; - - uint64_t language_id = static_cast(get_default_language(ref)); - - XdbfBlock lang_block = ref.get_entry(kSectionStringTable, language_id); - - if (lang_block.buffer != nullptr) { - XDBF_XSTR_HEADER* xstr_head = - reinterpret_cast(lang_block.buffer); - - assert_true(xstr_head->magic == kMagicXSTR); - assert_true(xstr_head->version == 1); - - uint16_t str_count = xstr_head->string_count; - uint8_t* currentAddress = lang_block.buffer + sizeof(XDBF_XSTR_HEADER); - - uint16_t s = 0; - while (s < str_count && title_str.empty()) { - XDBF_STRINGTABLE_ENTRY* entry = - reinterpret_cast(currentAddress); - currentAddress += sizeof(XDBF_STRINGTABLE_ENTRY); - uint16_t len = entry->string_length; - - if (entry->id == static_cast(kIdTitle)) { - title_str.resize(static_cast(len)); - std::copy(currentAddress, currentAddress + len, title_str.begin()); - } - - ++s; - currentAddress += len; - } - } - - return title_str; -} - -} // namespace xdbf -} // namespace xe diff --git a/src/xenia/xdbf/xdbf_utils.h b/src/xenia/xdbf/xdbf_utils.h deleted file mode 100644 index 4431eeda1..000000000 --- a/src/xenia/xdbf/xdbf_utils.h +++ /dev/null @@ -1,129 +0,0 @@ -/** - ****************************************************************************** - * Xenia : Xbox 360 Emulator Research Project * - ****************************************************************************** - * Copyright 2016 Ben Vanik. All rights reserved. * - * Released under the BSD license - see LICENSE in the root for more details. * - ****************************************************************************** - */ - -#ifndef XENIA_XDBF_XDBF_UTILS_H_ -#define XENIA_XDBF_XDBF_UTILS_H_ - -#include -#include - -#include "xenia/base/memory.h" - -namespace xe { -namespace xdbf { - -// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.h -// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.cpp - -enum XdbfSection : uint16_t { - kSectionMetadata = 0x0001, - kSectionImage = 0x0002, - kSectionStringTable = 0x0003, -}; - -// Found by dumping the kSectionStringTable sections of various games: - -enum XdbfLocale : uint32_t { - kLocaleEnglish = 1, - kLocaleJapanese = 2, - kLocaleGerman = 3, - kLocaleFrench = 4, - kLocaleSpanish = 5, - kLocaleItalian = 6, - kLocaleKorean = 7, - kLocaleChinese = 8, -}; - -struct XBDF_HEADER { - xe::be magic; - xe::be version; - xe::be entry_count; - xe::be entry_used; - xe::be free_count; - xe::be free_used; -}; -static_assert_size(XBDF_HEADER, 24); - -#pragma pack(push, 1) -struct XBDF_ENTRY { - xe::be section; - xe::be id; - xe::be offset; - xe::be size; -}; -static_assert_size(XBDF_ENTRY, 18); -#pragma pack(pop) - -struct XBDF_FILE_LOC { - xe::be offset; - xe::be size; -}; -static_assert_size(XBDF_FILE_LOC, 8); - -struct XDBF_XSTC { - xe::be magic; - xe::be version; - xe::be size; - xe::be default_language; -}; -static_assert_size(XDBF_XSTC, 16); - -#pragma pack(push, 1) -struct XDBF_XSTR_HEADER { - xe::be magic; - xe::be version; - xe::be size; - xe::be string_count; -}; -static_assert_size(XDBF_XSTR_HEADER, 14); -#pragma pack(pop) - -struct XDBF_STRINGTABLE_ENTRY { - xe::be id; - xe::be string_length; -}; -static_assert_size(XDBF_STRINGTABLE_ENTRY, 4); - -struct XdbfState { - XBDF_HEADER* header; - XBDF_ENTRY* entries; - XBDF_FILE_LOC* files; - uint8_t* offset; - uint8_t* data; - size_t size; -}; - -struct XdbfBlock { - uint8_t* buffer; - size_t size; -}; - -class XdbfWrapper { - public: - XdbfWrapper(); - - bool initialize(uint8_t* buffer, size_t length); - XdbfBlock get_entry(XdbfSection section, uint64_t id) const; - - private: - XBDF_HEADER& get_header() const; - XBDF_ENTRY& get_entry(uint32_t n) const; - XBDF_FILE_LOC& get_file(uint32_t n) const; - - XdbfState state_; -}; - -XdbfBlock get_icon(const XdbfWrapper& ref); -XdbfLocale get_default_language(const XdbfWrapper& ref); -std::string get_title(const XdbfWrapper& ref); - -} // namespace xdbf -} // namespace xe - -#endif // XENIA_XDBF_XDBF_UTILS_H_