Update README.md
[sm64pc.git] / tools / iplfontutil.c
blob937b6f91dbd4e4cc8f330455b2e4f170c5d54515
1 #include <stdio.h>
2 #include <stdlib.h>
3 #include <stdint.h>
5 #define STBI_NO_LINEAR
6 #define STBI_NO_PSD
7 #define STBI_NO_TGA
8 #define STBI_NO_HDR
9 #define STBI_NO_PIC
10 #define STBI_NO_PNM
11 #define STB_IMAGE_WRITE_IMPLEMENTATION
12 #include <stb/stb_image_write.h>
13 #define STB_IMAGE_IMPLEMENTATION
14 #include <stb/stb_image.h>
16 #define GETBIT(buf, idx) ((buf[(idx)/8] >> (7-((idx)%8))) & 1)
17 #define SETBIT(buf, idx) buf[(idx)/8] |= (1 << (7-((idx)%8)))
19 #define IPL3_FONT_NCHARS 50
20 #define IPL3_FONT_CHAR_W 13
21 #define IPL3_FONT_CHAR_H 14
22 #define IPL3_FONT_CHAR_NPIXELS (IPL3_FONT_CHAR_W * IPL3_FONT_CHAR_H)
23 #define IPL3_FONT_CHAR_NBITS (IPL3_FONT_CHAR_NPIXELS + 2)
24 #define IPL3_FONT_CHAR_NBYTES (IPL3_FONT_CHAR_NBITS / 8)
26 #define IPL3_FONT_FILE_SIZE ((IPL3_FONT_NCHARS * IPL3_FONT_CHAR_NBYTES) + 0x12)
28 int ipl3font_decode(const char *binPath, const char *imgPath)
30 FILE *binfp = fopen(binPath, "rb");
32 if(binfp == NULL)
34 printf("error: could not open %s for input\n", binPath);
35 return EXIT_FAILURE;
38 fseek(binfp, 0, SEEK_END);
39 size_t binSize = ftell(binfp);
41 if(binSize != IPL3_FONT_FILE_SIZE)
43 printf("error: font bin size invalid (must be 0x%X bytes)\n", IPL3_FONT_FILE_SIZE);
44 fclose(binfp);
45 return EXIT_FAILURE;
48 rewind(binfp);
50 char *binBuf = (char *) malloc(binSize);
51 if(fread(binBuf, 1, binSize, binfp) != binSize)
53 printf("error: failed to read from %s\n", binPath);
54 fclose(binfp);
55 return EXIT_FAILURE;
57 fclose(binfp);
59 uint32_t outSize = IPL3_FONT_NCHARS * IPL3_FONT_CHAR_NPIXELS * sizeof(uint32_t);
60 uint32_t *outRgba32 = (uint32_t *) malloc(outSize);
61 int outIdx = 0;
63 for(int nChar = 0; nChar < IPL3_FONT_NCHARS; nChar++)
65 for(int nRow = 0; nRow < IPL3_FONT_CHAR_H; nRow++)
67 for(int nCol = 0; nCol < IPL3_FONT_CHAR_W; nCol++)
69 int idx = (nChar * IPL3_FONT_CHAR_NBITS) + (nRow * IPL3_FONT_CHAR_W) + nCol;
70 int bit = GETBIT(binBuf, idx);
71 outRgba32[outIdx++] = (bit == 1) ? 0xFFFFFFFF : 0xFF000000;
76 int stbres = stbi_write_png(imgPath,
77 IPL3_FONT_CHAR_W,
78 IPL3_FONT_NCHARS * IPL3_FONT_CHAR_H,
80 outRgba32,
81 IPL3_FONT_CHAR_W * sizeof(uint32_t));
83 if(stbres == 0)
85 printf("error: failed to write %s\n", imgPath);
86 free(outRgba32);
87 free(binBuf);
88 return EXIT_FAILURE;
91 free(outRgba32);
92 free(binBuf);
93 return EXIT_SUCCESS;
96 int ipl3font_encode(const char *imgPath, const char *binPath)
98 int x, y, channels_in_file;
99 uint32_t *inRgba32 = (uint32_t *) stbi_load(imgPath, &x, &y, &channels_in_file, 4);
101 if(inRgba32 == NULL)
103 printf("error: failed to load %s\n", imgPath);
104 return EXIT_FAILURE;
107 if(x != IPL3_FONT_CHAR_W || y != IPL3_FONT_NCHARS * IPL3_FONT_CHAR_H)
109 printf("error: invalid ipl3 font image dimensions (must be %dx%d)\n",
110 IPL3_FONT_CHAR_W, IPL3_FONT_NCHARS * IPL3_FONT_CHAR_H);
111 stbi_image_free(inRgba32);
112 return EXIT_FAILURE;
115 char *out = calloc(IPL3_FONT_FILE_SIZE, 1);
117 int inIdx = 0;
119 for(int nChar = 0; nChar < IPL3_FONT_NCHARS; nChar++)
121 for(int nRow = 0; nRow < IPL3_FONT_CHAR_H; nRow++)
123 for(int nCol = 0; nCol < IPL3_FONT_CHAR_W; nCol++)
125 // source pixels that are not 0xFFFFFFFF are ignored
126 if(inRgba32[inIdx++] == 0xFFFFFFFF)
128 int idx = (nChar * IPL3_FONT_CHAR_NBITS) + (nRow * IPL3_FONT_CHAR_W) + nCol;
129 SETBIT(out, idx);
135 FILE * outfp = fopen(binPath, "wb");
137 if(outfp == NULL)
139 printf("error: failed to write to %s\n", binPath);
140 stbi_image_free(inRgba32);
141 free(out);
142 return EXIT_FAILURE;
145 fwrite(out, 1, IPL3_FONT_FILE_SIZE, outfp);
146 fclose(outfp);
148 stbi_image_free(inRgba32);
149 free(out);
151 return EXIT_SUCCESS;
154 int main(int argc, const char *argv[])
156 if(argc < 4)
158 printf("error: no paths\n");
159 printf("iplfontutil e <input_img> <output_bin>\n");
160 printf("iplfontutil d <input_bin> <output_img>\n");
161 return EXIT_FAILURE;
164 const char *mode = argv[1];
166 if(strcmp(mode, "e") == 0)
168 return ipl3font_encode(argv[2], argv[3]);
170 else if(strcmp(mode, "d") == 0)
172 return ipl3font_decode(argv[2], argv[3]);
174 else
176 printf("error: unknown mode\n");
177 return EXIT_FAILURE;