diff --git a/src/xenia/emulator.cc b/src/xenia/emulator.cc index b96078a75..da8bfd71b 100644 --- a/src/xenia/emulator.cc +++ b/src/xenia/emulator.cc @@ -526,9 +526,13 @@ X_STATUS Emulator::CompleteLaunch(const std::wstring& path, if (xdb_ptr != nullptr) { xe::xdbf::XdbfWrapper db; if (db.initialize(xdb_ptr, static_cast(resource_size))) { - // TODO(x1nixmzeng): Set the application icon std::wstring title(xe::to_wstring(xe::xdbf::get_title(db))); display_window_->set_title(title); + + xe::xdbf::XdbfBlock icon_block = xe::xdbf::get_icon(db); + if (icon_block.buffer != nullptr) { + display_window_->set_icon_from_buffer(icon_block.buffer, icon_block.size); + } } } } diff --git a/src/xenia/ui/window.h b/src/xenia/ui/window.h index cd68db447..e4c757bf0 100644 --- a/src/xenia/ui/window.h +++ b/src/xenia/ui/window.h @@ -53,6 +53,8 @@ class Window { return true; } + virtual bool set_icon_from_buffer(void *buffer, size_t size) = 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 cefaf908d..52cdea006 100644 --- a/src/xenia/ui/window_win.cc +++ b/src/xenia/ui/window_win.cc @@ -14,6 +14,11 @@ #include "xenia/base/platform_win.h" #include "xenia/ui/window_win.h" +#include "third_party/stb/stb_image.h" + +#define STB_IMAGE_IMPLEMENTATION +#include "third_party/stb/stb_image.h" + namespace xe { namespace ui { @@ -163,6 +168,46 @@ bool Win32Window::set_title(const std::wstring& title) { return true; } +bool Win32Window::set_icon_from_buffer(void *buffer, size_t size) { + + if (icon_ != nullptr) { + DestroyIcon(icon_); + } + + // Convert the buffer for Windows + int width, height, bpp; + unsigned char *data = stbi_load_from_memory(reinterpret_cast(buffer), static_cast(size), &width, &height, &bpp, 0); + + int iSize = sizeof(BITMAPINFOHEADER); + int iSizeImage = width * height * bpp; + + std::vector bitmap(iSize + iSizeImage); + BITMAPINFOHEADER *pBitmap(reinterpret_cast(bitmap.data())); + + pBitmap->biSize = sizeof(BITMAPINFOHEADER); + pBitmap->biWidth = width; + pBitmap->biHeight = height; + pBitmap->biPlanes = 1; + pBitmap->biBitCount = bpp * 8; + pBitmap->biCompression = BI_RGB; + pBitmap->biSizeImage = iSizeImage; + + unsigned char *pImage = bitmap.data() + iSize; + + std::copy(data, data + iSizeImage, pImage); + + HICON icon = CreateIconFromResourceEx((BYTE *)pBitmap, iSize + iSizeImage, TRUE, 0x00030000, width, height, LR_DEFAULTCOLOR); + + if (icon != nullptr) { + SendMessage(hwnd_, WM_SETICON, ICON_BIG, reinterpret_cast(icon)); + SendMessage(hwnd_, WM_SETICON, ICON_SMALL, reinterpret_cast(icon)); + + icon_ = icon; + } + + return false; +} + bool Win32Window::is_fullscreen() const { return fullscreen_; } void Win32Window::ToggleFullscreen(bool fullscreen) { @@ -294,6 +339,9 @@ void Win32Window::Close() { Close(); OnClose(); DestroyWindow(hwnd_); + if (icon_ != nullptr) { + DestroyIcon(icon_); + } } void Win32Window::OnMainMenuChange() { diff --git a/src/xenia/ui/window_win.h b/src/xenia/ui/window_win.h index 0f34f6e28..3cedf931f 100644 --- a/src/xenia/ui/window_win.h +++ b/src/xenia/ui/window_win.h @@ -31,6 +31,7 @@ class Win32Window : public Window { HWND hwnd() const { return hwnd_; } bool set_title(const std::wstring& title) override; + bool set_icon_from_buffer(void *buffer, size_t size) override; bool is_fullscreen() const override; void ToggleFullscreen(bool fullscreen) override; @@ -68,6 +69,7 @@ class Win32Window : public Window { bool HandleKeyboard(UINT message, WPARAM wParam, LPARAM lParam); HWND hwnd_ = nullptr; + HICON icon_ = nullptr; bool closing_ = false; bool fullscreen_ = false; diff --git a/src/xenia/xdbf/xdbf_utils.cc b/src/xenia/xdbf/xdbf_utils.cc index 993f88b44..ac08b800a 100644 --- a/src/xenia/xdbf/xdbf_utils.cc +++ b/src/xenia/xdbf/xdbf_utils.cc @@ -81,18 +81,9 @@ namespace xdbf { return block; } - std::vector get_icon(XdbfWrapper& ref) + XdbfBlock get_icon(XdbfWrapper& ref) { - std::vector icon; - - XdbfBlock block = ref.get_entry(kSectionImage, 0x8000); - - if (block.buffer != nullptr) { - icon.resize(block.size); - std::copy(block.buffer, block.buffer + block.size, icon.data()); - } - - return icon; + return ref.get_entry(kSectionImage, 0x8000); } std::string get_title(XdbfWrapper& ref) diff --git a/src/xenia/xdbf/xdbf_utils.h b/src/xenia/xdbf/xdbf_utils.h index f8b80c1af..8299c420f 100644 --- a/src/xenia/xdbf/xdbf_utils.h +++ b/src/xenia/xdbf/xdbf_utils.h @@ -112,7 +112,7 @@ namespace xdbf { XdbfState state_; }; - std::vector get_icon(XdbfWrapper& ref); + XdbfBlock get_icon(XdbfWrapper& ref); std::string get_title(XdbfWrapper& ref);