Skip to content

Commit 6ed1e70

Browse files
committed
export ps2 icon textures
1 parent 85c34aa commit 6ed1e70

File tree

4 files changed

+308
-2
lines changed

4 files changed

+308
-2
lines changed

Makefile

+1-1
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
TOOLS = src/main
22
PS1TOOLS= src/ps1main
3-
COMMON = src/util.o src/mcio.o src/ps1card.o src/aes.o
3+
COMMON = src/util.o src/mcio.o src/ps1card.o src/aes.o src/ps2icon.o
44
DEPS = Makefile
55

66
CC = gcc

include/ps2icon.h

+103
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,103 @@
1+
/*
2+
*
3+
* Copyright (c) 2008 Andreas Weis (http://www.ghulbus-inc.de/)
4+
*
5+
* Permission is hereby granted, free of charge, to any person obtaining a
6+
* copy of this software and associated documentation files (the
7+
* "Software"), to deal in the Software without restriction, including
8+
* without limitation the rights to use, copy, modify, merge, publish,
9+
* distribute, sublicense, and/or sell copies of the Software, and to
10+
* permit persons to whom the Software is furnished to do so, subject to
11+
* the following conditions:
12+
*
13+
* The above copyright notice and this permission notice shall be included
14+
* in all copies or substantial portions of the Software.
15+
*
16+
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS
17+
* OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18+
* MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
19+
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY
20+
* CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION OF CONTRACT,
21+
* TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION WITH THE
22+
* SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
23+
*/
24+
25+
//================================================================================================
26+
// Typedefs and Defines
27+
//================================================================================================
28+
29+
typedef struct
30+
{
31+
char magic[4];
32+
uint16_t padding1; // 0000
33+
uint16_t secondLineOffset;
34+
uint32_t padding2; // 00000000
35+
uint32_t transparencyVal; // 0x00 (clear) to 0x80 (opaque)
36+
uint8_t bgColourUpperLeft[16];
37+
uint8_t bgColourUpperRight[16];
38+
uint8_t bgColourLowerLeft[16];
39+
uint8_t bgColourLowerRight[16];
40+
uint8_t light1Direction[16];
41+
uint8_t light2Direction[16];
42+
uint8_t light3Direction[16];
43+
uint8_t light1RGB[16];
44+
uint8_t light2RGB[16];
45+
uint8_t light3RGB[16];
46+
uint8_t ambientLightRGB[16];
47+
char title[68]; // null terminated, S-JIS
48+
char IconName[64]; // null terminated
49+
char copyIconName[64]; // null terminated
50+
char deleteIconName[64]; // null terminated
51+
uint8_t padding3[512];
52+
} ps2_IconSys_t;
53+
54+
/** File header
55+
*/
56+
typedef struct Icon_Header_t {
57+
unsigned int file_id; ///< reserved; should be: 0x010000 (but does not have to ;) )
58+
unsigned int animation_shapes; ///< number of animation shapes per vertex
59+
unsigned int texture_type; ///< texture type - 0x07: uncompressed, 0x06: uncompresses, 0x0f: RLE compression
60+
unsigned int reserved; ///< reserved; should be: 0x3F800000 (but does not have to ;) )
61+
unsigned int n_vertices; ///< number of vertices; must be a multiple of 3
62+
} Icon_Header;
63+
/** Set of vertex coordinates
64+
* @note The f16_* fields indicate float16 data; divide by 4096.0f to convert to float32;
65+
*/
66+
typedef struct Vertex_Coord_t {
67+
short f16_x; ///< vertex x coordinate in float16
68+
short f16_y; ///< vertex y coordinate in float16
69+
short f16_z; ///< vertex z coordinate in float16
70+
short f16_unknown; ///< unknown; seems to influence lightning?
71+
} Vertex_Coord;
72+
/** Set of texture coordinates
73+
* @note The f16_* fields indicate float16 data; divide by 4096.0f to convert to float32;
74+
*/
75+
typedef struct Texture_Data_t {
76+
short f16_u; ///< vertex u texture coordinate in float16
77+
short f16_v; ///< vertex v texture coordinate in float16
78+
unsigned int color; ///< vertex color (32 bit RGBA)
79+
} Texture_Data;
80+
/** Animation header
81+
*/
82+
typedef struct Animation_Header_t {
83+
unsigned int id_tag; ///< ???
84+
unsigned int frame_length; ///< ???
85+
float anim_speed; ///< ???
86+
unsigned int play_offset; ///< ???
87+
unsigned int n_frames; ///< number of frames in the animation
88+
} Animation_Header;
89+
/** Per-frame animation data
90+
*/
91+
typedef struct Frame_Data_t {
92+
unsigned int shape_id; ///< shape used for this frame
93+
unsigned int n_keys; ///< number of keys corresponding to this frame
94+
} Frame_Data;
95+
/** Per-key animation data
96+
*/
97+
typedef struct Frame_Key_t {
98+
float time; ///< ???
99+
float value; ///< ???
100+
} Frame_Key;
101+
102+
//Get icon data as bytes
103+
uint8_t* getIconPS2(const char* folder, const char* iconfile);

src/main.c

+72-1
Original file line numberDiff line numberDiff line change
@@ -28,9 +28,11 @@
2828

2929
#include "mcio.h"
3030
#include "util.h"
31+
#include "ps2icon.h"
32+
#include "svpng.h"
3133

3234
#define PROGRAM_NAME "PS2VMC-TOOL"
33-
#define PROGRAM_VER "1.1.2"
35+
#define PROGRAM_VER "1.2.0"
3436

3537
#define PSV_MAGIC 0x50535600
3638

@@ -42,6 +44,7 @@ enum ps2vmc_cmd {
4244
CMD_ECC_IMG,
4345
CMD_LIST,
4446
CMD_PSU_EXPORT,
47+
CMD_ICONS_PNG,
4548
CMD_EXTRACT,
4649
CMD_MCFORMAT,
4750
CMD_INJECT,
@@ -69,6 +72,7 @@ static void print_usage(int argc, char **argv)
6972
printf("\t --ecc-image, -ecc <output filepath>\n");
7073
printf("\t --mc-format\n");
7174
printf("\t --list, -ls <mc path>\n");
75+
printf("\t --icons-png <mc path>\n");
7276
printf("\t --extract-file, -x <mc filepath> <output filepath>\n");
7377
printf("\t --inject-file, -in <input filepath> <mc filepath>\n");
7478
printf("\t --make-directory, -mkdir <mc path>\n");
@@ -298,6 +302,60 @@ static int cmd_export(const char* path, const char* output)
298302
return dd;
299303
}
300304

305+
static int cmd_export_icons_png(const char* path)
306+
{
307+
int r, fd;
308+
ps2_IconSys_t iconsys;
309+
char filePath[256];
310+
uint8_t* output;
311+
char* fnames[4] = { iconsys.IconName, iconsys.copyIconName, iconsys.deleteIconName, NULL };
312+
313+
if (path[0] == '/') path++;
314+
printf("Exporting '%s' icons...\n", path);
315+
316+
snprintf(filePath, sizeof(filePath), "%s/icon.sys", path);
317+
fd = mcio_mcOpen(filePath, sceMcFileAttrReadable | sceMcFileAttrFile);
318+
if (fd < 0)
319+
return fd;
320+
321+
r = mcio_mcRead(fd, &iconsys, sizeof(ps2_IconSys_t));
322+
if (r != (int)sizeof(ps2_IconSys_t)) {
323+
mcio_mcClose(fd);
324+
return -1001;
325+
}
326+
mcio_mcClose(fd);
327+
328+
printf("- List icon : %s\n", fnames[0]);
329+
printf("- Copy icon : %s\n", fnames[1]);
330+
printf("- Delete icon: %s\n", fnames[2]);
331+
332+
for (int i = 0; i < 3; i++) {
333+
output = getIconPS2(path, fnames[i]);
334+
if (!output) {
335+
return -1002;
336+
}
337+
338+
fnames[3] = strrchr(fnames[i], '.');
339+
if (fnames[3]) {
340+
*fnames[3] = 0;
341+
}
342+
343+
snprintf(filePath, sizeof(filePath), "%.12s_%s.png", path, fnames[i]);
344+
345+
FILE *fh = fopen(filePath, "wb");
346+
if (fh == NULL) {
347+
return -1003;
348+
}
349+
350+
svpng(fh, 128, 128, output, 1);
351+
fclose(fh);
352+
353+
printf("Icon succesfully exported to %s\n", filePath);
354+
}
355+
356+
return 0;
357+
}
358+
301359
static int cmd_mcformat(void)
302360
{
303361
int r;
@@ -702,6 +760,14 @@ int main(int argc, char **argv)
702760
cmd = CMD_LIST;
703761
cmd_args = &argv[3];
704762
}
763+
else if (!strcmp(argv[2], "--icons-png")) {
764+
if (argc < 3) {
765+
print_usage(argc, argv);
766+
return 1;
767+
}
768+
cmd = CMD_ICONS_PNG;
769+
cmd_args = &argv[3];
770+
}
705771
else if (!strcmp(argv[2], "--extract-file") || !strcmp(argv[2], "-x")) {
706772
if (argc < 4) {
707773
print_usage(argc, argv);
@@ -814,6 +880,11 @@ int main(int argc, char **argv)
814880
if (r < 0)
815881
printf("Error: can't create image file... (%d)\n", r);
816882
}
883+
else if (cmd == CMD_ICONS_PNG) {
884+
r = cmd_export_icons_png(cmd_args[0]);
885+
if (r < 0)
886+
printf("Error: can't export icons... (%d)\n", r);
887+
}
817888
else if (cmd == CMD_PSU_EXPORT) {
818889
r = cmd_export(cmd_args[0], cmd_args[1]);
819890
if (r < 0)

src/ps2icon.c

+132
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,132 @@
1+
#include <stdio.h>
2+
#include <stdlib.h>
3+
#include <sys/types.h>
4+
#include <string.h>
5+
6+
#include "ps2icon.h"
7+
#include "mcio.h"
8+
9+
10+
static uint32_t TIM2RGBA(const uint8_t *buf)
11+
{
12+
uint8_t RGBA[4];
13+
uint16_t lRGB = (int16_t) (buf[1] << 8) | buf[0];
14+
15+
RGBA[0] = 8 * (lRGB & 0x1F);
16+
RGBA[1] = 8 * ((lRGB >> 5) & 0x1F);
17+
RGBA[2] = 8 * (lRGB >> 10);
18+
RGBA[3] = 0xFF;
19+
20+
return *((uint32_t *) &RGBA);
21+
}
22+
23+
static void* ps2IconTexture(const uint8_t* iData)
24+
{
25+
uint32_t i;
26+
uint16_t j;
27+
Icon_Header header;
28+
Animation_Header anim_header;
29+
Frame_Data animation;
30+
uint32_t *lTexturePtr, *lRGBA;
31+
32+
lTexturePtr = (uint32_t *) calloc(128 * 128, sizeof(uint32_t));
33+
34+
//read header:
35+
memcpy(&header, iData, sizeof(Icon_Header));
36+
iData += sizeof(Icon_Header);
37+
38+
//n_vertices has to be divisible by three, that's for sure:
39+
if(header.file_id != 0x010000 || header.n_vertices % 3 != 0)
40+
return lTexturePtr;
41+
42+
//read icon data from file: https://ghulbus-inc.de/projects/ps2iconsys/
43+
///Vertex data
44+
// each vertex consists of animation_shapes tuples for vertex coordinates,
45+
// followed by one vertex coordinate tuple for normal coordinates
46+
// followed by one texture data tuple for texture coordinates and color
47+
for(i=0; i<header.n_vertices; i++) {
48+
iData += sizeof(Vertex_Coord) * header.animation_shapes;
49+
iData += sizeof(Vertex_Coord);
50+
iData += sizeof(Texture_Data);
51+
}
52+
53+
//animation data
54+
// preceeded by an animation header, there is a frame data/key set for every frame:
55+
memcpy(&anim_header, iData, sizeof(Animation_Header));
56+
iData += sizeof(Animation_Header);
57+
58+
//read animation data:
59+
for(i=0; i<anim_header.n_frames; i++) {
60+
memcpy(&animation, iData, sizeof(Frame_Data));
61+
iData += sizeof(Frame_Data);
62+
63+
if(animation.n_keys > 0)
64+
iData += sizeof(Frame_Key) * animation.n_keys;
65+
}
66+
67+
lRGBA = lTexturePtr;
68+
69+
if (header.texture_type <= 7)
70+
{ // Uncompressed texture
71+
for (i = 0; i < (128 * 128); i++)
72+
{
73+
*lRGBA = TIM2RGBA(iData);
74+
lRGBA++;
75+
iData += 2;
76+
}
77+
}
78+
else
79+
{ //Compressed texture
80+
iData += 4;
81+
do
82+
{
83+
j = (int16_t) (iData[1] << 8) | iData[0];
84+
if (0xFF00 == (j & 0xFF00))
85+
{
86+
for (j = (0x0000 - j) & 0xFFFF; j > 0; j--)
87+
{
88+
iData += 2;
89+
*lRGBA = TIM2RGBA(iData);
90+
lRGBA++;
91+
}
92+
}
93+
else
94+
{
95+
iData += 2;
96+
for (; j > 0; j--)
97+
{
98+
*lRGBA = TIM2RGBA(iData);
99+
lRGBA++;
100+
}
101+
}
102+
iData += 2;
103+
} while ((lRGBA - lTexturePtr) < 0x4000);
104+
}
105+
106+
return (lTexturePtr);
107+
}
108+
109+
//Get icon data as bytes
110+
uint8_t* getIconPS2(const char* folder, const char* iconfile)
111+
{
112+
int fd;
113+
uint8_t *buf, *out;
114+
char filePath[256];
115+
struct io_dirent st;
116+
117+
snprintf(filePath, sizeof(filePath), "%s/%s", folder, iconfile);
118+
mcio_mcStat(filePath, &st);
119+
120+
fd = mcio_mcOpen(filePath, sceMcFileAttrReadable | sceMcFileAttrFile);
121+
if (fd < 0)
122+
return calloc(128 * 128, sizeof(uint32_t));
123+
124+
buf = malloc(st.stat.size);
125+
mcio_mcRead(fd, buf, st.stat.size);
126+
mcio_mcClose(fd);
127+
128+
out = ps2IconTexture(buf);
129+
free(buf);
130+
131+
return out;
132+
}

0 commit comments

Comments
 (0)