Skip to content

Commit 7a1819b

Browse files
committed
[Memcard Manager] PNG exports for pocketstation icons.
1 parent ca44079 commit 7a1819b

2 files changed

Lines changed: 51 additions & 26 deletions

File tree

src/gui/widgets/memcard_manager.cc

Lines changed: 48 additions & 25 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,9 @@
2323
#include "fmt/format.h"
2424
#include "gui/widgets/memcard_manager.h"
2525

26+
#define STB_IMAGE_WRITE_IMPLEMENTATION
27+
#include "stb/stb_image_write.h"
28+
2629
PCSX::Widgets::MemcardManager::MemcardManager() {
2730
m_memoryEditor.OptShowDataPreview = true;
2831
m_memoryEditor.OptUpperCaseHex = false;
@@ -167,6 +170,12 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
167170
selectedBlock = i;
168171
m_pendingAction.popupText = fmt::format("Choose block to swap block {} with", selectedBlock);
169172
}
173+
ImGui::SameLine();
174+
175+
buttonName = fmt::format(_("Export PNG##{}"), i);
176+
if (ImGui::SmallButton(buttonName.c_str())) {
177+
exportPNG(i, block);
178+
}
170179
}
171180
ImGui::EndTable();
172181
}
@@ -212,7 +221,7 @@ bool PCSX::Widgets::MemcardManager::draw(const char* title) {
212221
return changed;
213222
}
214223

215-
void PCSX::Widgets::MemcardManager::drawIcon(int blockNumber, PCSX::SIO::McdBlock& block) {
224+
void PCSX::Widgets::MemcardManager::drawIcon(int blockNumber, const PCSX::SIO::McdBlock& block) {
216225
int currentFrame = 0; // 1st frame = 0, 2nd frame = 1, 3rd frame = 2 and so on
217226
const auto texture = m_iconTextures[blockNumber - 1];
218227
glBindTexture(GL_TEXTURE_2D, texture);
@@ -231,30 +240,7 @@ void PCSX::Widgets::MemcardManager::drawIcon(int blockNumber, PCSX::SIO::McdBloc
231240
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 16, 16, GL_RGBA, GL_UNSIGNED_SHORT_1_5_5_5_REV, icon);
232241
} else {
233242
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-
243+
getPocketstationIcon(pixels, blockNumber);
258244
glTexSubImage2D(GL_TEXTURE_2D, 0, 0, 0, 32, 32, GL_RGBA, GL_UNSIGNED_BYTE, pixels);
259245
}
260246

@@ -311,3 +297,40 @@ void PCSX::Widgets::MemcardManager::performAction() {
311297

312298
m_pendingAction.type = Actions::None; // Cancel action
313299
}
300+
301+
// Extract the pocketstation icon from the block indicated by blockNumber into the pixels array (In RGBA8888)
302+
void PCSX::Widgets::MemcardManager::getPocketstationIcon(uint32_t* pixels, int blockNumber) {
303+
const auto data = m_currentCardData;
304+
const auto titleFrame = data + blockNumber * PCSX::SIO::MCD_BLOCK_SIZE;
305+
306+
// Calculate icon offset using the header info documented here
307+
// https://psx-spx.consoledev.net/pocketstation/#pocketstation-file-headericons
308+
int iconOffset = 0x80 + (titleFrame[0x2] & 0xf) * 0x80;
309+
iconOffset += (titleFrame[0x57] * 8 + 0x7f) & ~0x7f;
310+
const auto icon = (uint32_t*)(titleFrame + iconOffset);
311+
312+
int index = 0;
313+
for (auto scanline = 0; scanline < 32; scanline++) {
314+
auto line = icon[scanline];
315+
316+
for (auto pixel = 0; pixel < 32; pixel++) {
317+
if ((line & 1) != 0) {
318+
pixels[index++] = 0xff; // Black
319+
} else {
320+
pixels[index++] = 0xffffffff; // White
321+
}
322+
323+
line >>= 1; // lsb = next pixel
324+
}
325+
}
326+
}
327+
328+
void PCSX::Widgets::MemcardManager::exportPNG(int blockNumber, const PCSX::SIO::McdBlock& block) {
329+
if (m_drawPocketstationIcons) {
330+
uint32_t pixels[32 * 32];
331+
getPocketstationIcon(pixels, blockNumber);
332+
333+
const auto filename = fmt::format("icon{}.png", blockNumber);
334+
stbi_write_png(filename.c_str(), 32, 32, 4, pixels, 128); // Stride = 32 pixels, 4 bytes each, so 128
335+
}
336+
}

src/gui/widgets/memcard_manager.h

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -62,7 +62,9 @@ class MemcardManager {
6262
char textInput[3] = "";
6363
} m_pendingAction;
6464

65-
void drawIcon(int blockNumber, PCSX::SIO::McdBlock& block);
65+
void drawIcon(int blockNumber, const PCSX::SIO::McdBlock& block);
66+
void exportPNG(int blockNumber, const PCSX::SIO::McdBlock& block);
67+
void getPocketstationIcon(uint32_t* pixels, int blockNumber);
6668
void performAction();
6769
};
6870

0 commit comments

Comments
 (0)