mirror of https://github.com/inolen/redream.git
109 lines
2.6 KiB
C
109 lines
2.6 KiB
C
#include <stdio.h>
|
|
#include "core/core.h"
|
|
#include "core/filesystem.h"
|
|
#include "guest/pvr/tex.h"
|
|
|
|
#define STB_IMAGE_WRITE_IMPLEMENTATION
|
|
#include "stb_image_write.h"
|
|
|
|
char *texture_fmt_names[] = {
|
|
NULL,
|
|
"TWIDDLED",
|
|
"TWIDDLED_MIPMAPS",
|
|
"VQ",
|
|
"VQ_MIPMAPS",
|
|
"PALETTE_4BPP",
|
|
NULL,
|
|
"PALETTE_8BPP",
|
|
NULL,
|
|
"PLANAR_RECT",
|
|
NULL,
|
|
"PLANAR",
|
|
NULL,
|
|
"TWIDDLED_RECT",
|
|
};
|
|
|
|
char *pixel_fmt_names[] = {
|
|
"ARGB1555", "RGB565", "ARGB4444", "YUV422",
|
|
};
|
|
|
|
uint8_t *read_tex(const char *filename) {
|
|
FILE *fp = fopen(filename, "rb");
|
|
if (!fp) {
|
|
LOG_WARNING("failed to open '%s'", filename);
|
|
return 0;
|
|
}
|
|
|
|
fseek(fp, 0, SEEK_END);
|
|
int size = ftell(fp);
|
|
fseek(fp, 0, SEEK_SET);
|
|
|
|
uint8_t *buffer = malloc(size);
|
|
int n = (int)fread(buffer, 1, size, fp);
|
|
CHECK_EQ(n, size);
|
|
fclose(fp);
|
|
|
|
return buffer;
|
|
}
|
|
|
|
void convert_tex(const char *texname) {
|
|
LOG_INFO("#==--------------------------------------------------==#");
|
|
LOG_INFO("# %s", texname);
|
|
LOG_INFO("#==--------------------------------------------------==#");
|
|
|
|
uint8_t *buffer = read_tex(texname);
|
|
|
|
const struct pvr_tex_header *header = pvr_tex_header(buffer);
|
|
|
|
if (!header) {
|
|
LOG_WARNING("convert_tex failed to find a valid PVRT header");
|
|
return;
|
|
}
|
|
|
|
const uint8_t *data = pvr_tex_data(buffer);
|
|
|
|
CHECK_LT(header->pixel_fmt, ARRAY_SIZE(pixel_fmt_names));
|
|
|
|
/* dump header */
|
|
LOG_INFO("version: %.4s", (char *)&header->version);
|
|
LOG_INFO("size: %d bytes", header->size);
|
|
LOG_INFO("pixel_fmt: %s", pixel_fmt_names[header->pixel_fmt]);
|
|
LOG_INFO("texture_fmt: %s", texture_fmt_names[header->texture_fmt]);
|
|
LOG_INFO("width: %d", header->width);
|
|
LOG_INFO("height: %d", header->height);
|
|
LOG_INFO("");
|
|
|
|
/* convert each mip level to png */
|
|
static uint8_t converted[1024 * 1024 * 4];
|
|
int mipmaps = pvr_tex_mipmaps(header->texture_fmt);
|
|
int levels = mipmaps ? ctz32(header->width) + 1 : 1;
|
|
|
|
while (levels--) {
|
|
int mip_width = header->width >> levels;
|
|
int mip_height = header->height >> levels;
|
|
pvr_tex_decode(data, mip_width, mip_height, mip_width, header->texture_fmt,
|
|
header->pixel_fmt, NULL, 0, converted, sizeof(converted));
|
|
|
|
char pngname[PATH_MAX];
|
|
snprintf(pngname, sizeof(pngname), "%s.%dx%d.png", texname, mip_width,
|
|
mip_height);
|
|
|
|
LOG_INFO("writing %s", pngname);
|
|
|
|
int stride = mip_width * 4;
|
|
int res =
|
|
stbi_write_png(pngname, mip_width, mip_height, 4, converted, stride);
|
|
CHECK_NE(res, 0);
|
|
}
|
|
|
|
free(buffer);
|
|
}
|
|
|
|
int main(int argc, char **argv) {
|
|
for (int i = 1; i < argc; i++) {
|
|
convert_tex(argv[i]);
|
|
}
|
|
|
|
return EXIT_SUCCESS;
|
|
}
|