Skip to content

Commit ca44079

Browse files
committed
[Memcard Mangaer] Initial Pocketstation icon support
1 parent 2370673 commit ca44079

3 files changed

Lines changed: 70 additions & 27 deletions

File tree

src/gui/gui.cc

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -427,7 +427,7 @@ end)(jit.status()))
427427
m_mainVRAMviewer.setMain();
428428
m_mainVRAMviewer.setTitle([]() { return _("Main VRAM Viewer"); });
429429
m_clutVRAMviewer.setTitle([]() { return _("CLUT VRAM selector"); });
430-
m_memcardManager.init();
430+
m_memcardManager.initTextures();
431431

432432
unsigned counter = 1;
433433
for (auto& viewer : m_VRAMviewers) {

src/gui/widgets/memcard_manager.cc

Lines changed: 63 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,6 @@
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)
226265
void 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;

src/gui/widgets/memcard_manager.h

Lines changed: 6 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919

2020
#pragma once
2121

22+
#include "core/sio.h"
2223
#include "GL/gl3w.h"
2324
#include "imgui.h"
2425
#include "imgui_memory_editor/imgui_memory_editor.h"
@@ -35,13 +36,16 @@ class MemcardManager {
3536
int m_frameCount = 0;
3637

3738
MemcardManager();
38-
void init();
39+
void initTextures();
3940

4041
private:
4142
int m_selectedCard = 1;
4243
int m_iconSize = 32; // The width and length of the icon images
4344
int m_selectedBlock;
4445
bool m_showMemoryEditor = false;
46+
bool m_drawPocketstationIcons = false;
47+
uint8_t* m_currentCardData = (uint8_t*)g_emulator->m_sio->GetMcdData(m_selectedCard);
48+
4549
GLuint m_iconTextures[15];
4650
MemoryEditor m_memoryEditor;
4751

@@ -58,7 +62,7 @@ class MemcardManager {
5862
char textInput[3] = "";
5963
} m_pendingAction;
6064

61-
void drawIcon(int blockNumber, uint16_t* icon);
65+
void drawIcon(int blockNumber, PCSX::SIO::McdBlock& block);
6266
void performAction();
6367
};
6468

0 commit comments

Comments
 (0)