summaryrefslogtreecommitdiff
path: root/Source/Core
diff options
context:
space:
mode:
authorEmptyChaos <EmptyChaos@users.noreply.github.com>2016-08-02 06:21:01 +0000
committerEmptyChaos <EmptyChaos@users.noreply.github.com>2016-10-04 13:47:21 +1100
commitb6fb56e97870ff020fed378a65d4ba4099f92bfc (patch)
tree6a774932b15ee0a609cdf7b9ae469f5cc2530aa8 /Source/Core
parent3b11581aff0fc7b1e248f1e9a67e35854f7c32b8 (diff)
WX: HiDPI: MemcardManager
Required a partial rewrite of the image loading code because it was working in unscaled wxBitmaps. Needed to make it produce wxImages and scale them instead.
Diffstat (limited to 'Source/Core')
-rw-r--r--Source/Core/DolphinWX/MemcardManager.cpp198
-rw-r--r--Source/Core/DolphinWX/MemcardManager.h1
2 files changed, 107 insertions, 92 deletions
diff --git a/Source/Core/DolphinWX/MemcardManager.cpp b/Source/Core/DolphinWX/MemcardManager.cpp
index d181e1da07..f5da01a43a 100644
--- a/Source/Core/DolphinWX/MemcardManager.cpp
+++ b/Source/Core/DolphinWX/MemcardManager.cpp
@@ -17,7 +17,6 @@
#include <wx/listbase.h>
#include <wx/menu.h>
#include <wx/msgdlg.h>
-#include <wx/mstream.h>
#include <wx/sizer.h>
#include <wx/stattext.h>
@@ -34,37 +33,24 @@
#define FIRSTPAGE 0
#define ARROWS slot ? "" : ARROW[slot], slot ? ARROW[slot] : ""
-static wxBitmap wxBitmapFromMemoryRGBA(const unsigned char* data, u32 width, u32 height)
+static wxImage wxImageFromMemoryRGBA(const u32* data, u32 width, u32 height)
{
- static const std::array<u8, 54> header = {
- {0x42, 0x4D, 0x38, 0x30, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x36, 0x00,
- 0x00, 0x00, 0x28, 0x00, 0x00, 0x00, 0x20, 0x00, 0x00, 0x00, // Width
- 0x20, 0x00, 0x00, 0x00, // Height
- 0x01, 0x00, 0x20, 0x00, 0x00, 0x00, 0x00, 0x00, 0x02, 0x30, 0x00, 0x00, // Data size
- 0x12, 0x0B, 0x00, 0x00, 0x12, 0x0B, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
- 0x00, 0x00, 0x00, 0x00}};
-
- u32 stride = (4 * width);
-
- u32 bytes = (stride * height) + header.size();
- bytes = (bytes + 3) & ~3;
-
- u32 data_length = bytes - header.size();
-
- std::vector<u8> pdata(bytes);
- std::copy(header.begin(), header.end(), pdata.begin());
-
- u8* const pixelData = &pdata[header.size()];
-
- for (u32 y = 0; y < height; y++)
- std::memcpy(&pixelData[y * stride], &data[(height - y - 1) * stride], stride);
-
- std::memcpy(&pdata[18], &width, sizeof(u32));
- std::memcpy(&pdata[22], &height, sizeof(u32));
- std::memcpy(&pdata[34], &data_length, sizeof(u32));
-
- wxMemoryInputStream is(pdata.data(), bytes);
- return wxBitmap(wxImage(is, wxBITMAP_TYPE_BMP));
+ wxImage image(width, height, false);
+ image.InitAlpha();
+ u8* rgb = image.GetData();
+ u8* alpha = image.GetAlpha();
+ for (u32 y = 0; y < height; ++y)
+ {
+ for (u32 x = 0; x < width; ++x)
+ {
+ u32 pixel = data[y * width + x];
+ *rgb++ = (pixel & 0x00FF0000) >> 16; // Red
+ *rgb++ = (pixel & 0x0000FF00) >> 8; // Green
+ *rgb++ = (pixel & 0x000000FF) >> 0; // Blue
+ *alpha++ = (pixel & 0xFF000000) >> 24;
+ }
+ }
+ return image;
}
BEGIN_EVENT_TABLE(CMemcardManager, wxDialog)
@@ -94,7 +80,8 @@ END_EVENT_TABLE()
CMemcardManager::CMemcardManager(wxWindow* parent)
: wxDialog(parent, wxID_ANY, _("Memory Card Manager"), wxDefaultPosition, wxDefaultSize,
wxCAPTION | wxSYSTEM_MENU | wxDIALOG_NO_PARENT | wxCLOSE_BOX | wxRESIZE_BORDER |
- wxMAXIMIZE_BOX)
+ wxMAXIMIZE_BOX),
+ m_image_list_size(FromDIP(wxSize(96, 32)))
{
memoryCard[SLOT_A] = nullptr;
memoryCard[SLOT_B] = nullptr;
@@ -179,6 +166,7 @@ bool CMemcardManager::SaveSettings()
void CMemcardManager::CreateGUIControls()
{
// Create the controls for both memcards
+ const int space5 = FromDIP(5);
const char* ARROW[2] = {"<-", "->"};
@@ -203,11 +191,11 @@ void CMemcardManager::CreateGUIControls()
t_Status[slot] = new wxStaticText(this, 0, wxEmptyString, wxDefaultPosition, wxDefaultSize, 0,
wxEmptyString);
- wxBoxSizer* const sPages = new wxBoxSizer(wxHORIZONTAL);
- sPages->Add(m_PrevPage[slot], 0, wxEXPAND | wxALL, 1);
- sPages->Add(t_Status[slot], 0, wxEXPAND | wxALL, 5);
- sPages->Add(0, 0, 1, wxEXPAND | wxALL, 0);
- sPages->Add(m_NextPage[slot], 0, wxEXPAND | wxALL, 1);
+ wxFlexGridSizer* const paging_sizer = new wxFlexGridSizer(3, wxSize(space5, space5));
+ paging_sizer->AddGrowableCol(1);
+ paging_sizer->Add(m_PrevPage[slot], 0, wxEXPAND);
+ paging_sizer->Add(t_Status[slot], 0, wxALIGN_CENTER);
+ paging_sizer->Add(m_NextPage[slot], 0, wxEXPAND);
m_MemcardPath[slot] = new wxFilePickerCtrl(
this, ID_MEMCARDPATH_A + slot, StrToWxStr(File::GetUserPath(D_GCUSER_IDX)),
@@ -216,41 +204,51 @@ void CMemcardManager::CreateGUIControls()
wxDefaultSize, wxFLP_USE_TEXTCTRL | wxFLP_OPEN);
m_MemcardList[slot] = new CMemcardListCtrl(
- this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, wxSize(350, 400),
+ this, ID_MEMCARDLIST_A + slot, wxDefaultPosition, FromDIP(wxSize(350, 400)),
wxLC_REPORT | wxSUNKEN_BORDER | wxLC_ALIGN_LEFT | wxLC_SINGLE_SEL, mcmSettings);
- m_MemcardList[slot]->AssignImageList(new wxImageList(96, 32), wxIMAGE_LIST_SMALL);
+ m_MemcardList[slot]->AssignImageList(
+ new wxImageList(m_image_list_size.GetWidth(), m_image_list_size.GetHeight()),
+ wxIMAGE_LIST_SMALL);
sMemcard[slot] = new wxStaticBoxSizer(wxVERTICAL, this,
_("Memory Card") + wxString::Format(" %c", 'A' + slot));
- sMemcard[slot]->Add(m_MemcardPath[slot], 0, wxEXPAND | wxALL, 5);
- sMemcard[slot]->Add(m_MemcardList[slot], 1, wxEXPAND | wxALL, 5);
- sMemcard[slot]->Add(sPages, 0, wxEXPAND | wxALL, 1);
+ sMemcard[slot]->AddSpacer(space5);
+ sMemcard[slot]->Add(m_MemcardPath[slot], 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ sMemcard[slot]->AddSpacer(space5);
+ sMemcard[slot]->Add(m_MemcardList[slot], 1, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ sMemcard[slot]->AddSpacer(space5);
+ sMemcard[slot]->Add(paging_sizer, 0, wxEXPAND | wxLEFT | wxRIGHT, space5);
+ sMemcard[slot]->AddSpacer(space5);
}
wxBoxSizer* const sButtons = new wxBoxSizer(wxVERTICAL);
sButtons->AddStretchSpacer(2);
- sButtons->Add(m_CopyFrom[SLOT_B], 0, wxEXPAND, 5);
- sButtons->Add(m_CopyFrom[SLOT_A], 0, wxEXPAND, 5);
- sButtons->AddStretchSpacer(1);
- sButtons->Add(m_SaveImport[SLOT_A], 0, wxEXPAND, 5);
- sButtons->Add(m_SaveExport[SLOT_A], 0, wxEXPAND, 5);
- sButtons->AddStretchSpacer(1);
- sButtons->Add(m_ConvertToGci, 0, wxEXPAND, 5);
- sButtons->AddStretchSpacer(1);
- sButtons->Add(m_SaveImport[SLOT_B], 0, wxEXPAND, 5);
- sButtons->Add(m_SaveExport[SLOT_B], 0, wxEXPAND, 5);
- sButtons->AddStretchSpacer(1);
- sButtons->Add(m_Delete[SLOT_A], 0, wxEXPAND, 5);
- sButtons->Add(m_Delete[SLOT_B], 0, wxEXPAND, 5);
+ sButtons->Add(m_CopyFrom[SLOT_B], 0, wxEXPAND);
+ sButtons->Add(m_CopyFrom[SLOT_A], 0, wxEXPAND);
+ sButtons->AddStretchSpacer();
+ sButtons->Add(m_SaveImport[SLOT_A], 0, wxEXPAND);
+ sButtons->Add(m_SaveExport[SLOT_A], 0, wxEXPAND);
sButtons->AddStretchSpacer();
- sButtons->Add(new wxButton(this, wxID_OK, _("Close")), 0, wxEXPAND, 5);
+ sButtons->Add(m_ConvertToGci, 0, wxEXPAND);
+ sButtons->AddStretchSpacer();
+ sButtons->Add(m_SaveImport[SLOT_B], 0, wxEXPAND);
+ sButtons->Add(m_SaveExport[SLOT_B], 0, wxEXPAND);
+ sButtons->AddStretchSpacer();
+ sButtons->Add(m_Delete[SLOT_A], 0, wxEXPAND);
+ sButtons->Add(m_Delete[SLOT_B], 0, wxEXPAND);
+ sButtons->AddStretchSpacer();
+ sButtons->Add(new wxButton(this, wxID_OK, _("Close")), 0, wxEXPAND);
sButtons->AddStretchSpacer();
wxBoxSizer* const sMain = new wxBoxSizer(wxHORIZONTAL);
- sMain->Add(sMemcard[SLOT_A], 1, wxEXPAND | wxALL, 5);
- sMain->Add(sButtons, 0, wxEXPAND, 0);
- sMain->Add(sMemcard[SLOT_B], 1, wxEXPAND | wxALL, 5);
+ sMain->AddSpacer(space5);
+ sMain->Add(sMemcard[SLOT_A], 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
+ sMain->AddSpacer(space5);
+ sMain->Add(sButtons, 0, wxEXPAND | wxTOP | wxBOTTOM, space5);
+ sMain->AddSpacer(space5);
+ sMain->Add(sMemcard[SLOT_B], 1, wxEXPAND | wxTOP | wxBOTTOM, space5);
+ sMain->AddSpacer(space5);
SetSizerAndFit(sMain);
Center();
@@ -653,57 +651,73 @@ bool CMemcardManager::ReloadMemcard(const std::string& fileName, int card)
u8 nFiles = memoryCard[card]->GetNumFiles();
std::vector<int> images(nFiles * 2);
+ static constexpr unsigned int BANNER_WIDTH = 96;
+ static constexpr unsigned int ANIM_FRAME_WIDTH = 32;
+ static constexpr unsigned int IMAGE_HEIGHT = 32;
+ static constexpr unsigned int ANIM_MAX_FRAMES = 8;
+
+ std::vector<u32> pxdata(BANNER_WIDTH * IMAGE_HEIGHT);
+ std::vector<u8> anim_delay(ANIM_MAX_FRAMES);
+ std::vector<u32> anim_data(ANIM_FRAME_WIDTH * IMAGE_HEIGHT * ANIM_MAX_FRAMES);
for (u8 i = 0; i < nFiles; i++)
{
- static u32 pxdata[96 * 32];
- static u8 animDelay[8];
- static u32 animData[32 * 32 * 8];
+ u8 file_index = memoryCard[card]->GetFileIndex(i);
+ u32 num_frames =
+ memoryCard[card]->ReadAnimRGBA8(file_index, anim_data.data(), anim_delay.data());
- u8 fileIndex = memoryCard[card]->GetFileIndex(i);
- int numFrames = memoryCard[card]->ReadAnimRGBA8(fileIndex, animData, animDelay);
-
- if (!memoryCard[card]->ReadBannerRGBA8(fileIndex, pxdata))
+ // Decode Save File Animation
+ wxImage anim_img_strip;
+ if (num_frames > 0)
{
- memset(pxdata, 0, 96 * 32 * 4);
+ unsigned int frames = BANNER_WIDTH / ANIM_FRAME_WIDTH;
- if (numFrames > 0) // Just use the first one
+ if (num_frames < frames)
{
- u32* icdata = animData;
+ frames = num_frames;
+
+ // Clear unused frame's pixels from the buffer.
+ std::fill(pxdata.begin(), pxdata.end(), 0);
+ }
- for (int y = 0; y < 32; y++)
+ for (unsigned int f = 0; f < frames; ++f)
+ {
+ for (unsigned int y = 0; y < IMAGE_HEIGHT; ++y)
{
- for (int x = 0; x < 32; x++)
+ for (unsigned int x = 0; x < ANIM_FRAME_WIDTH; ++x)
{
- pxdata[y * 96 + x + 32] = icdata[y * 32 + x]; // | 0xFF000000
+ // NOTE: pxdata is stacked horizontal, anim_data is stacked vertical
+ pxdata[y * BANNER_WIDTH + f * ANIM_FRAME_WIDTH + x] =
+ anim_data[f * ANIM_FRAME_WIDTH * IMAGE_HEIGHT + y * IMAGE_HEIGHT + x];
}
}
}
+ anim_img_strip = wxImageFromMemoryRGBA(pxdata.data(), BANNER_WIDTH, IMAGE_HEIGHT);
}
-
- wxBitmap map = wxBitmapFromMemoryRGBA((u8*)pxdata, 96, 32);
- images[i * 2] = list->Add(map);
-
- if (numFrames > 0)
+ else
{
- memset(pxdata, 0, 96 * 32 * 4);
- int frames = 3;
-
- if (numFrames < frames)
- frames = numFrames;
+ // No Animation found, use an empty placeholder instead.
+ anim_img_strip.Create(BANNER_WIDTH, IMAGE_HEIGHT, false);
+ anim_img_strip.Clear(0xFF);
+ anim_img_strip.SetMaskColour(0xFF, 0xFF, 0xFF);
+ }
- for (int f = 0; f < frames; f++)
+ // Decode Banner if it exists
+ {
+ wxImage image;
+ if (memoryCard[card]->ReadBannerRGBA8(file_index, pxdata.data()))
{
- for (int y = 0; y < 32; y++)
- {
- for (int x = 0; x < 32; x++)
- {
- pxdata[y * 96 + x + 32 * f] = animData[f * 32 * 32 + y * 32 + x];
- }
- }
+ image = wxImageFromMemoryRGBA(pxdata.data(), BANNER_WIDTH, IMAGE_HEIGHT);
+ }
+ else
+ {
+ // Use first frame of animation instead.
+ image = anim_img_strip.Size(wxSize(ANIM_FRAME_WIDTH, IMAGE_HEIGHT), wxPoint(0, 0));
}
- wxBitmap icon = wxBitmapFromMemoryRGBA((u8*)pxdata, 96, 32);
- images[i * 2 + 1] = list->Add(icon);
+ images[i * 2] = list->Add(WxUtils::ScaleImageToBitmap(image, this, m_image_list_size));
}
+
+ images[i * 2 + 1] =
+ list->Add(WxUtils::ScaleImageToBitmap(anim_img_strip, this, m_image_list_size));
}
int pagesMax = (mcmSettings.usePages) ? (page[card] + 1) * itemsPerPage : 128;
diff --git a/Source/Core/DolphinWX/MemcardManager.h b/Source/Core/DolphinWX/MemcardManager.h
index 3f307117b9..edfd5fac74 100644
--- a/Source/Core/DolphinWX/MemcardManager.h
+++ b/Source/Core/DolphinWX/MemcardManager.h
@@ -131,5 +131,6 @@ private:
void OnRightClick(wxMouseEvent& event);
};
+ wxSize m_image_list_size;
CMemcardListCtrl* m_MemcardList[2];
};