parent
effe241a11
commit
e4cef38d95
|
@ -515,27 +515,28 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path,
|
||||||
return X_STATUS_UNSUCCESSFUL;
|
return X_STATUS_UNSUCCESSFUL;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Try and load the resource database (xex only)
|
// Try and load the resource database (xex only)
|
||||||
char title[9] = { 0 };
|
char title[9] = {0};
|
||||||
sprintf(title, "%08X", module->title_id());
|
sprintf(title, "%08X", module->title_id());
|
||||||
|
|
||||||
uint32_t resource_data = 0;
|
uint32_t resource_data = 0;
|
||||||
uint32_t resource_size = 0;
|
uint32_t resource_size = 0;
|
||||||
if (XSUCCEEDED(module->GetSection(title, &resource_data, &resource_size))) {
|
if (XSUCCEEDED(module->GetSection(title, &resource_data, &resource_size))) {
|
||||||
auto xdb_ptr = module->memory()->TranslateVirtual(resource_data);
|
auto xdb_ptr = module->memory()->TranslateVirtual(resource_data);
|
||||||
if (xdb_ptr != nullptr) {
|
if (xdb_ptr != nullptr) {
|
||||||
xe::xdbf::XdbfWrapper db;
|
xe::xdbf::XdbfWrapper db;
|
||||||
if (db.initialize(xdb_ptr, static_cast<size_t>(resource_size))) {
|
if (db.initialize(xdb_ptr, static_cast<size_t>(resource_size))) {
|
||||||
std::wstring title(xe::to_wstring(xe::xdbf::get_title(db)));
|
std::wstring title(xe::to_wstring(xe::xdbf::get_title(db)));
|
||||||
display_window_->set_title(title);
|
display_window_->set_title(title);
|
||||||
|
|
||||||
xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db);
|
xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db);
|
||||||
if (icon_block.buffer != nullptr) {
|
if (icon_block.buffer != nullptr) {
|
||||||
display_window_->set_icon_from_buffer(icon_block.buffer, icon_block.size);
|
display_window_->set_icon_from_buffer(icon_block.buffer,
|
||||||
}
|
icon_block.size);
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
}
|
||||||
|
|
||||||
main_thread_ = main_xthread->thread();
|
main_thread_ = main_xthread->thread();
|
||||||
WaitUntilExit();
|
WaitUntilExit();
|
||||||
|
|
|
@ -167,22 +167,23 @@ bool Win32Window::set_title(const std::wstring& title) {
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::set_icon_from_buffer(void *buffer, size_t size) {
|
bool Win32Window::set_icon_from_buffer(void* buffer, size_t size) {
|
||||||
|
if (icon_ != nullptr) {
|
||||||
|
DestroyIcon(icon_);
|
||||||
|
}
|
||||||
|
|
||||||
if (icon_ != nullptr) {
|
HICON icon = CreateIconFromResourceEx(reinterpret_cast<BYTE*>(buffer),
|
||||||
DestroyIcon(icon_);
|
static_cast<DWORD>(size), TRUE,
|
||||||
}
|
0x00030000, 0, 0, LR_DEFAULTCOLOR);
|
||||||
|
|
||||||
HICON icon = CreateIconFromResourceEx(reinterpret_cast<BYTE *>(buffer), static_cast<DWORD>(size), TRUE, 0x00030000, 0, 0, LR_DEFAULTCOLOR);
|
if (icon != nullptr) {
|
||||||
|
icon_ = icon;
|
||||||
|
|
||||||
if (icon != nullptr) {
|
SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(icon));
|
||||||
icon_ = icon;
|
SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icon));
|
||||||
|
}
|
||||||
|
|
||||||
SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast<LPARAM>(icon));
|
return false;
|
||||||
SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast<LPARAM>(icon));
|
|
||||||
}
|
|
||||||
|
|
||||||
return false;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
bool Win32Window::is_fullscreen() const { return fullscreen_; }
|
bool Win32Window::is_fullscreen() const { return fullscreen_; }
|
||||||
|
|
|
@ -12,121 +12,114 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace xdbf {
|
namespace xdbf {
|
||||||
|
|
||||||
XdbfWrapper::XdbfWrapper() = default;
|
XdbfWrapper::XdbfWrapper() = default;
|
||||||
|
|
||||||
XBDF_HEADER& XdbfWrapper::get_header() const
|
XBDF_HEADER& XdbfWrapper::get_header() const { return *state_.header; }
|
||||||
{
|
|
||||||
return *state_.header;
|
|
||||||
}
|
|
||||||
|
|
||||||
XBDF_ENTRY& XdbfWrapper::get_entry(uint32_t n) const
|
XBDF_ENTRY& XdbfWrapper::get_entry(uint32_t n) const {
|
||||||
{
|
return state_.entries[n];
|
||||||
return state_.entries[n];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
XBDF_FILE_LOC& XdbfWrapper::get_file(uint32_t n) const
|
XBDF_FILE_LOC& XdbfWrapper::get_file(uint32_t n) const {
|
||||||
{
|
return state_.files[n];
|
||||||
return state_.files[n];
|
}
|
||||||
}
|
|
||||||
|
|
||||||
bool XdbfWrapper::initialize(uint8_t* buffer, size_t length)
|
bool XdbfWrapper::initialize(uint8_t* buffer, size_t length) {
|
||||||
{
|
if (length <= sizeof(XBDF_HEADER)) {
|
||||||
if (length <= sizeof(XBDF_HEADER)) {
|
return false;
|
||||||
return false;
|
}
|
||||||
}
|
|
||||||
|
|
||||||
XdbfState state;
|
XdbfState state;
|
||||||
|
|
||||||
state.data = buffer;
|
state.data = buffer;
|
||||||
state.size = length;
|
state.size = length;
|
||||||
|
|
||||||
uint8_t* ptr = state.data;
|
uint8_t* ptr = state.data;
|
||||||
|
|
||||||
state.header = reinterpret_cast<XBDF_HEADER*>(ptr);
|
state.header = reinterpret_cast<XBDF_HEADER*>(ptr);
|
||||||
ptr += sizeof(XBDF_HEADER);
|
ptr += sizeof(XBDF_HEADER);
|
||||||
|
|
||||||
state.entries = reinterpret_cast<XBDF_ENTRY*>(ptr);
|
state.entries = reinterpret_cast<XBDF_ENTRY*>(ptr);
|
||||||
ptr += (sizeof(XBDF_ENTRY) * state.header->entry_max);
|
ptr += (sizeof(XBDF_ENTRY) * state.header->entry_max);
|
||||||
|
|
||||||
state.files = reinterpret_cast<XBDF_FILE_LOC*>(ptr);
|
state.files = reinterpret_cast<XBDF_FILE_LOC*>(ptr);
|
||||||
ptr += (sizeof(XBDF_FILE_LOC) * state.header->free_max);
|
ptr += (sizeof(XBDF_FILE_LOC) * state.header->free_max);
|
||||||
|
|
||||||
state.offset = ptr;
|
state.offset = ptr;
|
||||||
|
|
||||||
if (state.header->magic == 'XDBF') {
|
if (state.header->magic == 'XDBF') {
|
||||||
state_ = state;
|
state_ = state;
|
||||||
return true;
|
return true;
|
||||||
}
|
}
|
||||||
|
|
||||||
return false;
|
return false;
|
||||||
}
|
}
|
||||||
|
|
||||||
XdbfBlock XdbfWrapper::get_entry(XdbfSection section, uint64_t id) const {
|
XdbfBlock XdbfWrapper::get_entry(XdbfSection section, uint64_t id) const {
|
||||||
|
XdbfBlock block = {nullptr, 0};
|
||||||
|
uint32_t x = 0;
|
||||||
|
|
||||||
XdbfBlock block = { nullptr,0 };
|
while (x < get_header().entry_current) {
|
||||||
uint32_t x = 0;
|
auto& entry = get_entry(x);
|
||||||
|
|
||||||
while( x < get_header().entry_current ) {
|
if (entry.section == section && entry.id == id) {
|
||||||
auto &entry = get_entry(x);
|
block.buffer = state_.offset + entry.offset;
|
||||||
|
block.size = entry.size;
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
if (entry.section == section && entry.id == id) {
|
++x;
|
||||||
block.buffer = state_.offset + entry.offset;
|
}
|
||||||
block.size = entry.size;
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
|
|
||||||
++x;
|
return block;
|
||||||
}
|
}
|
||||||
|
|
||||||
return block;
|
XdbfBlock get_icon(XdbfWrapper& ref) {
|
||||||
}
|
return ref.get_entry(kSectionImage, 0x8000);
|
||||||
|
}
|
||||||
|
|
||||||
XdbfBlock get_icon(XdbfWrapper& ref)
|
std::string get_title(XdbfWrapper& ref) {
|
||||||
{
|
std::string title_str;
|
||||||
return ref.get_entry(kSectionImage, 0x8000);
|
|
||||||
}
|
|
||||||
|
|
||||||
std::string get_title(XdbfWrapper& ref)
|
XdbfBlock block = ref.get_entry(kSectionMetadata, 0x58535443);
|
||||||
{
|
if (block.buffer != nullptr) {
|
||||||
std::string title_str;
|
XDBF_XSTC* xstc = reinterpret_cast<XDBF_XSTC*>(block.buffer);
|
||||||
|
|
||||||
XdbfBlock block = ref.get_entry(kSectionMetadata, 0x58535443);
|
assert_true(xstc->magic == 'XSTC');
|
||||||
if (block.buffer != nullptr) {
|
uint32_t def_language = xstc->default_language;
|
||||||
XDBF_XSTC* xstc = reinterpret_cast<XDBF_XSTC*>(block.buffer);
|
|
||||||
|
|
||||||
assert_true(xstc->magic == 'XSTC');
|
XdbfBlock lang_block =
|
||||||
uint32_t def_language = xstc->default_language;
|
ref.get_entry(kSectionStringTable, static_cast<uint64_t>(def_language));
|
||||||
|
|
||||||
XdbfBlock lang_block = ref.get_entry(kSectionStringTable, static_cast<uint64_t>(def_language));
|
if (lang_block.buffer != nullptr) {
|
||||||
|
XDBF_XSTR_HEADER* xstr_head =
|
||||||
|
reinterpret_cast<XDBF_XSTR_HEADER*>(lang_block.buffer);
|
||||||
|
|
||||||
if (lang_block.buffer != nullptr) {
|
assert_true(xstr_head->magic == 'XSTR');
|
||||||
XDBF_XSTR_HEADER* xstr_head = reinterpret_cast<XDBF_XSTR_HEADER*>(lang_block.buffer);
|
assert_true(xstr_head->version == 1);
|
||||||
|
|
||||||
assert_true(xstr_head->magic == 'XSTR');
|
uint16_t str_count = xstr_head->string_count;
|
||||||
assert_true(xstr_head->version == 1);
|
uint8_t* currentAddress = lang_block.buffer + sizeof(XDBF_XSTR_HEADER);
|
||||||
|
|
||||||
uint16_t str_count = xstr_head->string_count;
|
uint16_t s = 0;
|
||||||
uint8_t *currentAddress = lang_block.buffer + sizeof(XDBF_XSTR_HEADER);
|
while (s < str_count && title_str.empty()) {
|
||||||
|
XDBF_STRINGTABLE_ENTRY* entry =
|
||||||
|
reinterpret_cast<XDBF_STRINGTABLE_ENTRY*>(currentAddress);
|
||||||
|
currentAddress += sizeof(XDBF_STRINGTABLE_ENTRY);
|
||||||
|
uint16_t len = entry->string_length;
|
||||||
|
|
||||||
uint16_t s = 0;
|
if (entry->id == 0x00008000) {
|
||||||
while( s < str_count && title_str.empty() ) {
|
title_str.resize(static_cast<size_t>(len));
|
||||||
XDBF_STRINGTABLE_ENTRY* entry = reinterpret_cast<XDBF_STRINGTABLE_ENTRY*>(currentAddress);
|
std::copy(currentAddress, currentAddress + len, title_str.begin());
|
||||||
currentAddress += sizeof(XDBF_STRINGTABLE_ENTRY);
|
}
|
||||||
uint16_t len = entry->string_length;
|
|
||||||
|
|
||||||
if (entry->id == 0x00008000) {
|
currentAddress += len;
|
||||||
title_str.resize(static_cast<size_t>(len));
|
}
|
||||||
std::copy(currentAddress, currentAddress + len, title_str.begin());
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
currentAddress += len;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
return title_str;
|
|
||||||
}
|
|
||||||
|
|
||||||
|
return title_str;
|
||||||
|
}
|
||||||
|
|
||||||
} // namespace xdbf
|
} // namespace xdbf
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
|
@ -18,103 +18,102 @@
|
||||||
namespace xe {
|
namespace xe {
|
||||||
namespace xdbf {
|
namespace xdbf {
|
||||||
|
|
||||||
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.h
|
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.h
|
||||||
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.cpp
|
// http://freestyledash.googlecode.com/svn/trunk/Freestyle/Tools/XEX/SPA.cpp
|
||||||
|
|
||||||
enum XdbfSection : uint16_t {
|
enum XdbfSection : uint16_t {
|
||||||
kSectionMetadata = 0x0001,
|
kSectionMetadata = 0x0001,
|
||||||
kSectionImage = 0x0002,
|
kSectionImage = 0x0002,
|
||||||
kSectionStringTable = 0x0003,
|
kSectionStringTable = 0x0003,
|
||||||
};
|
};
|
||||||
|
|
||||||
enum XdbfLocale : uint32_t {
|
enum XdbfLocale : uint32_t {
|
||||||
kLocaleDefault = 0,
|
kLocaleDefault = 0,
|
||||||
kLocaleEnglish = 1,
|
kLocaleEnglish = 1,
|
||||||
kLocaleJapanese = 2,
|
kLocaleJapanese = 2,
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XBDF_HEADER {
|
struct XBDF_HEADER {
|
||||||
xe::be<uint32_t> magic;
|
xe::be<uint32_t> magic;
|
||||||
xe::be<uint32_t> version;
|
xe::be<uint32_t> version;
|
||||||
xe::be<uint32_t> entry_max;
|
xe::be<uint32_t> entry_max;
|
||||||
xe::be<uint32_t> entry_current;
|
xe::be<uint32_t> entry_current;
|
||||||
xe::be<uint32_t> free_max;
|
xe::be<uint32_t> free_max;
|
||||||
xe::be<uint32_t> free_current;
|
xe::be<uint32_t> free_current;
|
||||||
};
|
};
|
||||||
static_assert_size(XBDF_HEADER, 24);
|
static_assert_size(XBDF_HEADER, 24);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct XBDF_ENTRY {
|
struct XBDF_ENTRY {
|
||||||
xe::be<uint16_t> section;
|
xe::be<uint16_t> section;
|
||||||
xe::be<uint64_t> id;
|
xe::be<uint64_t> id;
|
||||||
xe::be<uint32_t> offset;
|
xe::be<uint32_t> offset;
|
||||||
xe::be<uint32_t> size;
|
xe::be<uint32_t> size;
|
||||||
};
|
};
|
||||||
static_assert_size(XBDF_ENTRY, 18);
|
static_assert_size(XBDF_ENTRY, 18);
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct XBDF_FILE_LOC {
|
struct XBDF_FILE_LOC {
|
||||||
xe::be<uint32_t> offset;
|
xe::be<uint32_t> offset;
|
||||||
xe::be<uint32_t> size;
|
xe::be<uint32_t> size;
|
||||||
};
|
};
|
||||||
static_assert_size(XBDF_FILE_LOC, 8);
|
static_assert_size(XBDF_FILE_LOC, 8);
|
||||||
|
|
||||||
struct XDBF_XSTC {
|
struct XDBF_XSTC {
|
||||||
xe::be<uint32_t> magic;
|
xe::be<uint32_t> magic;
|
||||||
xe::be<uint32_t> version;
|
xe::be<uint32_t> version;
|
||||||
xe::be<uint32_t> size;
|
xe::be<uint32_t> size;
|
||||||
xe::be<uint32_t> default_language;
|
xe::be<uint32_t> default_language;
|
||||||
};
|
};
|
||||||
static_assert_size(XDBF_XSTC, 16);
|
static_assert_size(XDBF_XSTC, 16);
|
||||||
|
|
||||||
#pragma pack(push, 1)
|
#pragma pack(push, 1)
|
||||||
struct XDBF_XSTR_HEADER {
|
struct XDBF_XSTR_HEADER {
|
||||||
xe::be<uint32_t> magic;
|
xe::be<uint32_t> magic;
|
||||||
xe::be<uint32_t> version;
|
xe::be<uint32_t> version;
|
||||||
xe::be<uint32_t> size;
|
xe::be<uint32_t> size;
|
||||||
xe::be<uint16_t> string_count;
|
xe::be<uint16_t> string_count;
|
||||||
};
|
};
|
||||||
static_assert_size(XDBF_XSTR_HEADER, 14);
|
static_assert_size(XDBF_XSTR_HEADER, 14);
|
||||||
#pragma pack(pop)
|
#pragma pack(pop)
|
||||||
|
|
||||||
struct XDBF_STRINGTABLE_ENTRY {
|
struct XDBF_STRINGTABLE_ENTRY {
|
||||||
xe::be<uint16_t> id;
|
xe::be<uint16_t> id;
|
||||||
xe::be<uint16_t> string_length;
|
xe::be<uint16_t> string_length;
|
||||||
};
|
};
|
||||||
static_assert_size(XDBF_STRINGTABLE_ENTRY, 4);
|
static_assert_size(XDBF_STRINGTABLE_ENTRY, 4);
|
||||||
|
|
||||||
struct XdbfState {
|
struct XdbfState {
|
||||||
XBDF_HEADER* header;
|
XBDF_HEADER* header;
|
||||||
XBDF_ENTRY* entries;
|
XBDF_ENTRY* entries;
|
||||||
XBDF_FILE_LOC* files;
|
XBDF_FILE_LOC* files;
|
||||||
uint8_t* offset;
|
uint8_t* offset;
|
||||||
uint8_t* data;
|
uint8_t* data;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
struct XdbfBlock {
|
struct XdbfBlock {
|
||||||
uint8_t* buffer;
|
uint8_t* buffer;
|
||||||
size_t size;
|
size_t size;
|
||||||
};
|
};
|
||||||
|
|
||||||
class XdbfWrapper {
|
class XdbfWrapper {
|
||||||
public:
|
public:
|
||||||
XdbfWrapper();
|
XdbfWrapper();
|
||||||
|
|
||||||
bool initialize(uint8_t* buffer, size_t length);
|
bool initialize(uint8_t* buffer, size_t length);
|
||||||
XdbfBlock get_entry(XdbfSection section, uint64_t id) const;
|
XdbfBlock get_entry(XdbfSection section, uint64_t id) const;
|
||||||
|
|
||||||
private:
|
private:
|
||||||
XBDF_HEADER& get_header() const;
|
XBDF_HEADER& get_header() const;
|
||||||
XBDF_ENTRY& get_entry(uint32_t n) const;
|
XBDF_ENTRY& get_entry(uint32_t n) const;
|
||||||
XBDF_FILE_LOC& get_file(uint32_t n) const;
|
XBDF_FILE_LOC& get_file(uint32_t n) const;
|
||||||
|
|
||||||
XdbfState state_;
|
XdbfState state_;
|
||||||
};
|
};
|
||||||
|
|
||||||
XdbfBlock get_icon(XdbfWrapper& ref);
|
|
||||||
std::string get_title(XdbfWrapper& ref);
|
|
||||||
|
|
||||||
|
XdbfBlock get_icon(XdbfWrapper& ref);
|
||||||
|
std::string get_title(XdbfWrapper& ref);
|
||||||
|
|
||||||
} // namespace xdbf
|
} // namespace xdbf
|
||||||
} // namespace xe
|
} // namespace xe
|
||||||
|
|
Loading…
Reference in New Issue