From 18abc33306bd1bfe8ecc590666da9d7fa3a9b86d Mon Sep 17 00:00:00 2001 From: comex Date: Wed, 25 Sep 2013 03:05:36 -0400 Subject: [PATCH] 2x banner images! --- Externals/wxWidgets3/src/generic/treectlg.cpp | 1 + Externals/wxWidgets3/src/osx/imaglist.cpp | 14 +++---- Source/Core/DiscIO/Src/BannerLoader.h | 2 +- Source/Core/DiscIO/Src/BannerLoaderGC.cpp | 16 ++++---- Source/Core/DiscIO/Src/BannerLoaderGC.h | 2 +- Source/Core/DiscIO/Src/BannerLoaderWii.cpp | 39 ++++-------------- Source/Core/DiscIO/Src/BannerLoaderWii.h | 2 +- Source/Core/DolphinWX/Src/GameListCtrl.cpp | 4 +- Source/Core/DolphinWX/Src/ISOFile.cpp | 40 ++++++++++++------- Source/Core/DolphinWX/Src/ISOFile.h | 5 ++- Source/Core/DolphinWX/Src/ISOProperties.cpp | 2 +- Source/Core/DolphinWX/Src/MainAndroid.cpp | 39 +++++++++++++++++- Source/Core/DolphinWX/Src/WxUtils.cpp | 16 ++++++++ Source/Core/DolphinWX/Src/WxUtils.h | 2 + 14 files changed, 112 insertions(+), 72 deletions(-) diff --git a/Externals/wxWidgets3/src/generic/treectlg.cpp b/Externals/wxWidgets3/src/generic/treectlg.cpp index 4539b8972d..9a90c457d0 100644 --- a/Externals/wxWidgets3/src/generic/treectlg.cpp +++ b/Externals/wxWidgets3/src/generic/treectlg.cpp @@ -1,3 +1,4 @@ +// XXX comex: scale support ///////////////////////////////////////////////////////////////////////////// // Name: src/generic/treectlg.cpp // Purpose: generic tree control implementation diff --git a/Externals/wxWidgets3/src/osx/imaglist.cpp b/Externals/wxWidgets3/src/osx/imaglist.cpp index 8dc07f1467..300a143bfd 100644 --- a/Externals/wxWidgets3/src/osx/imaglist.cpp +++ b/Externals/wxWidgets3/src/osx/imaglist.cpp @@ -73,16 +73,16 @@ int wxImageList::Add( const wxIcon &bitmap ) int wxImageList::Add( const wxBitmap &bitmap ) { - wxASSERT_MSG( (bitmap.GetWidth() >= m_width && bitmap.GetHeight() == m_height) + wxASSERT_MSG( (bitmap.GetScaledWidth() >= m_width && bitmap.GetScaledHeight() == m_height) || (m_width == 0 && m_height == 0), wxT("invalid bitmap size in wxImageList: this might work ") wxT("on this platform but definitely won't under Windows.") ); // Mimic behaviour of Windows ImageList_Add that automatically breaks up the added // bitmap into sub-images of the correct size - if (m_width > 0 && bitmap.GetWidth() > m_width && bitmap.GetHeight() >= m_height) + if (m_width > 0 && bitmap.GetScaledWidth() > m_width && bitmap.GetScaledHeight() >= m_height) { - int numImages = bitmap.GetWidth() / m_width; + int numImages = bitmap.GetScaledWidth() / m_width; for (int subIndex = 0; subIndex < numImages; subIndex++) { wxRect rect(m_width * subIndex, 0, m_width, m_height); @@ -97,8 +97,8 @@ int wxImageList::Add( const wxBitmap &bitmap ) if (m_width == 0 && m_height == 0) { - m_width = bitmap.GetWidth(); - m_height = bitmap.GetHeight(); + m_width = bitmap.GetScaledWidth(); + m_height = bitmap.GetScaledHeight(); } return m_images.GetCount() - 1; @@ -275,8 +275,8 @@ bool wxImageList::GetSize( int index, int &width, int &height ) const else { wxBitmap *bm = static_cast< wxBitmap* >(obj ) ; - width = bm->GetWidth(); - height = bm->GetHeight(); + width = bm->GetScaledWidth(); + height = bm->GetScaledHeight(); } return true; diff --git a/Source/Core/DiscIO/Src/BannerLoader.h b/Source/Core/DiscIO/Src/BannerLoader.h index 7fec9c57bd..da0075f7f3 100644 --- a/Source/Core/DiscIO/Src/BannerLoader.h +++ b/Source/Core/DiscIO/Src/BannerLoader.h @@ -26,7 +26,7 @@ class IBannerLoader virtual bool IsValid() = 0; - virtual bool GetBanner(u32* _pBannerImage) = 0; + virtual std::vector GetBanner(int* pWidth, int* pHeight) = 0; virtual std::vector GetNames() = 0; virtual std::string GetCompany() = 0; diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp index 58b79d12db..cbe09c5804 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.cpp @@ -50,17 +50,15 @@ bool CBannerLoaderGC::IsValid() return m_IsValid; } -bool CBannerLoaderGC::GetBanner(u32* _pBannerImage) +std::vector CBannerLoaderGC::GetBanner(int* pWidth, int* pHeight) { - if (!IsValid()) - { - return false; - } - + std::vector Buffer; + Buffer.resize(DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT); auto const pBanner = (DVDBanner*)m_pBannerFile; - decode5A3image(_pBannerImage, pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); - - return true; + decode5A3image(&Buffer[0], pBanner->image, DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT); + *pWidth = DVD_BANNER_WIDTH; + *pHeight = DVD_BANNER_HEIGHT; + return std::move(Buffer); } diff --git a/Source/Core/DiscIO/Src/BannerLoaderGC.h b/Source/Core/DiscIO/Src/BannerLoaderGC.h index b9674feb58..e18a2fee82 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderGC.h +++ b/Source/Core/DiscIO/Src/BannerLoaderGC.h @@ -20,7 +20,7 @@ class CBannerLoaderGC virtual bool IsValid(); - virtual bool GetBanner(u32* _pBannerImage); + virtual std::vector GetBanner(int* pWidth, int* pHeight); virtual std::vector GetNames(); virtual std::string GetCompany(); diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp index e682ca13c6..915ce4debc 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.cpp +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.cpp @@ -98,38 +98,15 @@ bool CBannerLoaderWii::IsValid() return m_IsValid; } -static inline u32 Average32(u32 a, u32 b) { - return ((a >> 1) & 0x7f7f7f7f) + ((b >> 1) & 0x7f7f7f7f); -} - -static inline u32 GetPixel(u32 *buffer, unsigned int x, unsigned int y) { - // thanks to unsignedness, these also check for <0 automatically. - if (x > 191) return 0; - if (y > 63) return 0; - return buffer[y * 192 + x]; -} - -bool CBannerLoaderWii::GetBanner(u32* _pBannerImage) +std::vector CBannerLoaderWii::GetBanner(int* pWidth, int* pHeight) { - if (IsValid()) - { - SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; - u32* Buffer = new u32[192 * 64]; - decode5A3image(Buffer, (u16*)pBanner->m_BannerTexture, 192, 64); - for (int y = 0; y < 32; y++) - { - for (int x = 0; x < 96; x++) - { - // simplified plus-shaped "gaussian" - u32 surround = Average32( - Average32(GetPixel(Buffer, x*2 - 1, y*2), GetPixel(Buffer, x*2 + 1, y*2)), - Average32(GetPixel(Buffer, x*2, y*2 - 1), GetPixel(Buffer, x*2, y*2 + 1))); - _pBannerImage[y * 96 + x] = Average32(GetPixel(Buffer, x*2, y*2), surround); - } - } - delete[] Buffer; - } - return true; + SWiiBanner* pBanner = (SWiiBanner*)m_pBannerFile; + std::vector Buffer; + Buffer.resize(192 * 64); + decode5A3image(&Buffer[0], (u16*)pBanner->m_BannerTexture, 192, 64); + *pWidth = 192; + *pHeight = 64; + return std::move(Buffer); } bool CBannerLoaderWii::GetStringFromComments(const CommentIndex index, std::string& result) diff --git a/Source/Core/DiscIO/Src/BannerLoaderWii.h b/Source/Core/DiscIO/Src/BannerLoaderWii.h index 33a1dce6ae..455213cbf9 100644 --- a/Source/Core/DiscIO/Src/BannerLoaderWii.h +++ b/Source/Core/DiscIO/Src/BannerLoaderWii.h @@ -20,7 +20,7 @@ class CBannerLoaderWii virtual bool IsValid(); - virtual bool GetBanner(u32* _pBannerImage); + virtual std::vector GetBanner(int* pWidth, int* pHeight); virtual std::vector GetNames(); virtual std::string GetCompany(); diff --git a/Source/Core/DolphinWX/Src/GameListCtrl.cpp b/Source/Core/DolphinWX/Src/GameListCtrl.cpp index 49a38b6ea8..300bf470c0 100644 --- a/Source/Core/DolphinWX/Src/GameListCtrl.cpp +++ b/Source/Core/DolphinWX/Src/GameListCtrl.cpp @@ -402,8 +402,8 @@ void CGameListCtrl::InsertItemInReportView(long _Index) // Insert the platform's image in the first (visible) column SetItemColumnImage(_Index, COLUMN_PLATFORM, m_PlatformImageIndex[rISOFile.GetPlatform()]); - if (rISOFile.GetImage().IsOk()) - ImageIndex = m_imageListSmall->Add(rISOFile.GetImage()); + if (rISOFile.GetBitmap().IsOk()) + ImageIndex = m_imageListSmall->Add(rISOFile.GetBitmap()); // Set the game's banner in the second column SetItemColumnImage(_Index, COLUMN_BANNER, ImageIndex); diff --git a/Source/Core/DolphinWX/Src/ISOFile.cpp b/Source/Core/DolphinWX/Src/ISOFile.cpp index c38f6f5110..2a70a550f7 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.cpp +++ b/Source/Core/DolphinWX/Src/ISOFile.cpp @@ -24,13 +24,11 @@ #include "ChunkFile.h" #include "ConfigManager.h" -static const u32 CACHE_REVISION = 0x114; +static const u32 CACHE_REVISION = 0x115; #define DVD_BANNER_WIDTH 96 #define DVD_BANNER_HEIGHT 32 -static u32 g_ImageTemp[DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT]; - GameListItem::GameListItem(const std::string& _rFileName) : m_FileName(_rFileName) , m_emu_state(0) @@ -38,6 +36,8 @@ GameListItem::GameListItem(const std::string& _rFileName) , m_Revision(0) , m_Valid(false) , m_BlobCompressed(false) + , m_ImageWidth(0) + , m_ImageHeight(0) { if (LoadFromCache()) { @@ -83,17 +83,16 @@ GameListItem::GameListItem(const std::string& _rFileName) m_company = pBannerLoader->GetCompany(); m_descriptions = pBannerLoader->GetDescriptions(); - if (pBannerLoader->GetBanner(g_ImageTemp)) - { - // resize vector to image size - m_pImage.resize(DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT * 3); + std::vector Buffer = pBannerLoader->GetBanner(&m_ImageWidth, &m_ImageHeight); + u32* pData = &Buffer[0]; + // resize vector to image size + m_pImage.resize(m_ImageWidth * m_ImageHeight * 3); - for (size_t i = 0; i < DVD_BANNER_WIDTH * DVD_BANNER_HEIGHT; i++) - { - m_pImage[i * 3 + 0] = (g_ImageTemp[i] & 0xFF0000) >> 16; - m_pImage[i * 3 + 1] = (g_ImageTemp[i] & 0x00FF00) >> 8; - m_pImage[i * 3 + 2] = (g_ImageTemp[i] & 0x0000FF) >> 0; - } + for (int i = 0; i < m_ImageWidth * m_ImageHeight; i++) + { + m_pImage[i * 3 + 0] = (pData[i] & 0xFF0000) >> 16; + m_pImage[i * 3 + 1] = (pData[i] & 0x00FF00) >> 8; + m_pImage[i * 3 + 2] = (pData[i] & 0x0000FF) >> 0; } } delete pBannerLoader; @@ -124,12 +123,21 @@ GameListItem::GameListItem(const std::string& _rFileName) if (!m_pImage.empty()) { - m_Image.Create(DVD_BANNER_WIDTH, DVD_BANNER_HEIGHT, &m_pImage[0], true); + wxImage Image(m_ImageWidth, m_ImageHeight, &m_pImage[0], true); + double Scale = WxUtils::GetCurrentBitmapLogicalScale(); + // Note: This uses nearest neighbor, which subjectively looks a lot + // better for GC banners than smooths caling. + Image.Rescale(DVD_BANNER_WIDTH * Scale, DVD_BANNER_HEIGHT * Scale); +#ifdef __APPLE__ + m_Bitmap = wxBitmap(Image, -1, Scale); +#else + m_Bitmap = wxBitmap(Image, -1); +#endif } else { // default banner - m_Image = wxImage(StrToWxStr(File::GetThemeDir(SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name)) + "nobanner.png", wxBITMAP_TYPE_PNG); + m_Bitmap.LoadFile(StrToWxStr(File::GetThemeDir(SConfig::GetInstance().m_LocalCoreStartupParameter.theme_name)) + "nobanner.png", wxBITMAP_TYPE_PNG); } } @@ -164,6 +172,8 @@ void GameListItem::DoState(PointerWrap &p) p.Do(m_Country); p.Do(m_BlobCompressed); p.Do(m_pImage); + p.Do(m_ImageWidth); + p.Do(m_ImageHeight); p.Do(m_Platform); p.Do(m_IsDiscTwo); p.Do(m_Revision); diff --git a/Source/Core/DolphinWX/Src/ISOFile.h b/Source/Core/DolphinWX/Src/ISOFile.h index 080f45fd32..ffab089a1d 100644 --- a/Source/Core/DolphinWX/Src/ISOFile.h +++ b/Source/Core/DolphinWX/Src/ISOFile.h @@ -41,7 +41,7 @@ public: u64 GetVolumeSize() const {return m_VolumeSize;} bool IsDiscTwo() const {return m_IsDiscTwo;} #if defined(HAVE_WX) && HAVE_WX - const wxImage& GetImage() const {return m_Image;} + const wxBitmap& GetBitmap() const {return m_Bitmap;} #endif void DoState(PointerWrap &p); @@ -78,11 +78,12 @@ private: int m_Revision; #if defined(HAVE_WX) && HAVE_WX - wxImage m_Image; + wxBitmap m_Bitmap; #endif bool m_Valid; bool m_BlobCompressed; std::vector m_pImage; + int m_ImageWidth, m_ImageHeight; bool m_IsDiscTwo; bool LoadFromCache(); diff --git a/Source/Core/DolphinWX/Src/ISOProperties.cpp b/Source/Core/DolphinWX/Src/ISOProperties.cpp index 500a3014fc..e81b710086 100644 --- a/Source/Core/DolphinWX/Src/ISOProperties.cpp +++ b/Source/Core/DolphinWX/Src/ISOProperties.cpp @@ -215,7 +215,7 @@ CISOProperties::CISOProperties(const std::string fileName, wxWindow* parent, wxW ChangeBannerDetails(SConfig::GetInstance().m_SYSCONF->GetData("IPL.LNG")); } - m_Banner->SetBitmap(OpenGameListItem->GetImage()); + m_Banner->SetBitmap(OpenGameListItem->GetBitmap()); m_Banner->Bind(wxEVT_RIGHT_DOWN, &CISOProperties::RightClickOnBanner, this); // Filesystem browser/dumper diff --git a/Source/Core/DolphinWX/Src/MainAndroid.cpp b/Source/Core/DolphinWX/Src/MainAndroid.cpp index 60413b74c5..5b8699bb0d 100644 --- a/Source/Core/DolphinWX/Src/MainAndroid.cpp +++ b/Source/Core/DolphinWX/Src/MainAndroid.cpp @@ -138,6 +138,17 @@ void Host_SetWiiMoteConnectionState(int _State) {} std::vector m_volume_names; std::vector m_names; +static inline u32 Average32(u32 a, u32 b) { + return ((a >> 1) & 0x7f7f7f7f) + ((b >> 1) & 0x7f7f7f7f); +} + +static inline u32 GetPixel(u32 *buffer, unsigned int x, unsigned int y) { + // thanks to unsignedness, these also check for <0 automatically. + if (x > 191) return 0; + if (y > 63) return 0; + return buffer[y * 192 + x]; +} + bool LoadBanner(std::string filename, u32 *Banner) { DiscIO::IVolume* pVolume = DiscIO::CreateVolumeFromFilename(filename); @@ -161,8 +172,32 @@ bool LoadBanner(std::string filename, u32 *Banner) if (pBannerLoader->IsValid()) { m_names = pBannerLoader->GetNames(); - if (pBannerLoader->GetBanner(Banner)) - return true; + int Width, Height; + std::vector BannerVec = pBannerLoader->GetBanner(&Width, &Height); + // This code (along with above inlines) is moved from + // elsewhere. Someone who knows anything about Android + // please get rid of it and use proper high-resolution + // images. + if (Height == 64) + { + u32* Buffer = &BannerVec[0]; + for (int y = 0; y < 32; y++) + { + for (int x = 0; x < 96; x++) + { + // simplified plus-shaped "gaussian" + u32 surround = Average32( + Average32(GetPixel(Buffer, x*2 - 1, y*2), GetPixel(Buffer, x*2 + 1, y*2)), + Average32(GetPixel(Buffer, x*2, y*2 - 1), GetPixel(Buffer, x*2, y*2 + 1))); + Banner[y * 96 + x] = Average32(GetPixel(Buffer, x*2, y*2), surround); + } + } + } + else + { + memcpy(Banner, &BannerVec[0], 96 * 32 * 4); + } + return true; } } } diff --git a/Source/Core/DolphinWX/Src/WxUtils.cpp b/Source/Core/DolphinWX/Src/WxUtils.cpp index 173c07fbcc..ba245c090d 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.cpp +++ b/Source/Core/DolphinWX/Src/WxUtils.cpp @@ -9,6 +9,10 @@ #include "WxUtils.h" +#ifdef __APPLE__ +#import +#endif + namespace WxUtils { // Launch a file according to its mime type @@ -40,6 +44,18 @@ void Explore(const char *path) } } +double GetCurrentBitmapLogicalScale() +{ +#ifdef __APPLE__ + // wx doesn't expose this itself, unfortunately. + if ([[NSScreen mainScreen] respondsToSelector:@selector(backingScaleFactor)]) + { + return [[NSScreen mainScreen] backingScaleFactor]; + } +#endif + return 1.0; +} + } // namespace std::string WxStrToStr(const wxString& str) diff --git a/Source/Core/DolphinWX/Src/WxUtils.h b/Source/Core/DolphinWX/Src/WxUtils.h index 9dee725da3..b14bc614ca 100644 --- a/Source/Core/DolphinWX/Src/WxUtils.h +++ b/Source/Core/DolphinWX/Src/WxUtils.h @@ -17,6 +17,8 @@ void Launch(const char *filename); // Launch an file explorer window on a certain path void Explore(const char *path); +double GetCurrentBitmapLogicalScale(); + } // namespace std::string WxStrToStr(const wxString& str);