1919
2020#include < algorithm>
2121#include < cstdlib>
22- #include " core/sio.h"
2322#include " core/system.h"
2423#include " fmt/format.h"
2524#include " gui/widgets/memcard_manager.h"
@@ -29,15 +28,20 @@ PCSX::Widgets::MemcardManager::MemcardManager() {
2928 m_memoryEditor.OptUpperCaseHex = false ;
3029}
3130
32- void PCSX::Widgets::MemcardManager::init () {
31+ void PCSX::Widgets::MemcardManager::initTextures () {
3332 // Initialize the OpenGL textures used for the icon images
34- // This can't happen in the constructor cause our context won't be ready yet
33+ // This must only be called when our OpenGL context is set up
3534 glGenTextures (15 , m_iconTextures);
3635 for (int i = 0 ; i < 15 ; i++) {
3736 glBindTexture (GL_TEXTURE_2D , m_iconTextures[i]);
3837 glTexParameteri (GL_TEXTURE_2D , GL_TEXTURE_MIN_FILTER , GL_NEAREST );
3938 glTexParameteri (GL_TEXTURE_2D , GL_TEXTURE_MAG_FILTER , GL_NEAREST );
40- glTexStorage2D (GL_TEXTURE_2D , 1 , GL_RGB5_A1 , 16 , 16 );
39+
40+ if (!m_drawPocketstationIcons) {
41+ glTexStorage2D (GL_TEXTURE_2D , 1 , GL_RGB5_A1 , 16 , 16 );
42+ } else {
43+ glTexStorage2D (GL_TEXTURE_2D , 1 , GL_RGBA8 , 32 , 32 );
44+ }
4145 }
4246}
4347
@@ -76,21 +80,27 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
7680 const int otherCard = (m_selectedCard == 1 ) ? 2 : 1 ;
7781 const auto copyButtonText = fmt::format (_ (" Copy all to card {}" ), otherCard);
7882 if (ImGui::Button (copyButtonText.c_str ())) {
79- const auto source = PCSX ::g_emulator-> m_sio -> GetMcdData (m_selectedCard) ;
83+ const auto source = m_currentCardData ;
8084 auto dest = PCSX ::g_emulator->m_sio ->GetMcdData (otherCard);
8185
8286 std::memcpy (dest, source, PCSX ::SIO ::MCD_SIZE );
8387 }
8488 }
8589
8690 ImGui::SliderInt (" Icon size" , &m_iconSize, 16 , 512 );
91+ ImGui::SameLine ();
92+ if (ImGui::Checkbox (" Draw Pockestation icons" , &m_drawPocketstationIcons)) {
93+ glDeleteTextures (15 , m_iconTextures); // Recreate our textures to fit our new format
94+ initTextures ();
95+ }
8796
8897 static const char * cardNames[] = {_ (" Memory card 1" ), _ (" Memory card 2" )};
8998 // Code below is slightly odd because m_selectedCart is 1-indexed while arrays are 0-indexed
9099 if (ImGui::BeginCombo (_ (" Card" ), cardNames[m_selectedCard - 1 ])) {
91- for (unsigned i = 0 ; i < 2 ; i++) {
100+ for (int i = 0 ; i < 2 ; i++) {
92101 if (ImGui::Selectable (cardNames[i], m_selectedCard == i + 1 )) {
93102 m_selectedCard = i + 1 ;
103+ m_currentCardData = (uint8_t *)g_emulator->m_sio ->GetMcdData (m_selectedCard);
94104 }
95105 }
96106 ImGui::EndCombo ();
@@ -112,25 +122,12 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
112122
113123 for (auto i = 1 ; i < 16 ; i++) {
114124 g_emulator->m_sio ->GetMcdBlockInfo (m_selectedCard, i, &block);
115- int currentFrame = 0 ; // 1st frame = 0, 2nd frame = 1, 3rd frame = 2
116- const auto animationFrames = block.IconCount ;
117-
118- // Check if we should display the 3rd frame, then check if we should display the 2nd one
119- if (m_frameCount >= 40 && animationFrames == 3 ) {
120- currentFrame = 2 ;
121- } else if (m_frameCount >= 20 && animationFrames >= 2 ) {
122- currentFrame = 1 ;
123- }
124-
125- // Pointer to the current frame. Skip 16x16 pixels for each frame
126- const auto icon = block.Icon + (currentFrame * 16 * 16 );
127- bool selected = i == 3 ;
128125
129126 ImGui::TableNextRow ();
130127 ImGui::TableSetColumnIndex (0 );
131128 ImGui::Text (" %d" , i);
132129 ImGui::TableSetColumnIndex (1 );
133- drawIcon (i, icon );
130+ drawIcon (i, block );
134131
135132 ImGui::TableSetColumnIndex (2 );
136133 ImGui::Text (block.Title );
@@ -175,7 +172,7 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
175172 }
176173
177174 if (m_showMemoryEditor) {
178- const auto data = g_emulator-> m_sio -> GetMcdData (m_selectedCard) ;
175+ const auto data = m_currentCardData ;
179176 m_memoryEditor.DrawWindow (_ (" Memory Card Viewer" ), data, PCSX ::SIO ::MCD_SIZE );
180177 }
181178
@@ -215,17 +212,59 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
215212 return changed;
216213}
217214
218- void PCSX::Widgets::MemcardManager::drawIcon (int blockNumber, uint16_t * icon) {
215+ void PCSX::Widgets::MemcardManager::drawIcon (int blockNumber, PCSX ::SIO ::McdBlock& block) {
216+ int currentFrame = 0 ; // 1st frame = 0, 2nd frame = 1, 3rd frame = 2 and so on
219217 const auto texture = m_iconTextures[blockNumber - 1 ];
220218 glBindTexture (GL_TEXTURE_2D , texture);
221- glTexSubImage2D (GL_TEXTURE_2D , 0 , 0 , 0 , 16 , 16 , GL_RGBA , GL_UNSIGNED_SHORT_1_5_5_5_REV , icon);
219+
220+ if (!m_drawPocketstationIcons) {
221+ const auto animationFrames = block.IconCount ;
222+ // Check if we should display the 3rd frame, then check if we should display the 2nd one
223+ if (m_frameCount >= 40 && animationFrames == 3 ) {
224+ currentFrame = 2 ;
225+ } else if (m_frameCount >= 20 && animationFrames >= 2 ) {
226+ currentFrame = 1 ;
227+ }
228+
229+ // Pointer to the current frame. Skip 16x16 pixels for each frame
230+ const auto icon = block.Icon + (currentFrame * 16 * 16 );
231+ glTexSubImage2D (GL_TEXTURE_2D , 0 , 0 , 0 , 16 , 16 , GL_RGBA , GL_UNSIGNED_SHORT_1_5_5_5_REV , icon);
232+ } else {
233+ uint32_t pixels[32 * 32 ];
234+ const auto data = m_currentCardData;
235+ const auto titleFrame = data + blockNumber * PCSX ::SIO ::MCD_BLOCK_SIZE ;
236+
237+ // Calculate icon offset using the header info documented here
238+ // https://psx-spx.consoledev.net/pocketstation/#pocketstation-file-headericons
239+ int iconOffset = 0x80 + (titleFrame[0x2 ] & 0xf ) * 0x80 ;
240+ // iconOffset += ~((titleFrame[0x57] * 8 + 0x7f) & 0x7f);
241+ const auto icon = (uint32_t *)(titleFrame + iconOffset);
242+
243+ int index = 0 ;
244+ for (auto scanline = 0 ; scanline < 32 ; scanline++) {
245+ auto line = icon[scanline];
246+
247+ for (auto pixel = 0 ; pixel < 32 ; pixel++) {
248+ if ((line & 1 ) != 0 ) {
249+ pixels[index++] = 0xff ; // Black
250+ } else {
251+ pixels[index++] = 0xffffffff ; // White
252+ }
253+
254+ line >>= 1 ; // lsb = next pixel
255+ }
256+ }
257+
258+ glTexSubImage2D (GL_TEXTURE_2D , 0 , 0 , 0 , 32 , 32 , GL_RGBA , GL_UNSIGNED_BYTE , pixels);
259+ }
260+
222261 ImGui::Image ((void *)texture, ImVec2 (m_iconSize, m_iconSize));
223262}
224263
225264// Perform the pending memory card action (Move, copy, swap)
226265void PCSX::Widgets::MemcardManager::performAction () {
227266 // Data of source and dest cards respectively
228- auto data1 = ( uint8_t *)g_emulator-> m_sio -> GetMcdData (m_selectedCard) ;
267+ auto data1 = m_currentCardData ;
229268 auto data2 = (uint8_t *)g_emulator->m_sio ->GetMcdData (m_pendingAction.targetCard );
230269
231270 const int sourceBlock = m_pendingAction.sourceBlock ;
0 commit comments