|
16 | 16 |
|
17 | 17 | #include "common.h"
|
18 | 18 | #include "yar.h" // from z64compress
|
| 19 | +#include "yaz.h" // from z64compress |
19 | 20 | #include "n64texconv.h" // from z64convert
|
20 | 21 | #include "recipe.h"
|
21 | 22 | #include "stb_image_write.h"
|
| 23 | +#include "stb_image.h" |
22 | 24 |
|
23 | 25 | struct YarEntry
|
24 | 26 | {
|
@@ -180,6 +182,92 @@ static int YarDump(const char *input)
|
180 | 182 |
|
181 | 183 | static int YarBuild(const char *input)
|
182 | 184 | {
|
| 185 | + struct Recipe *recipe = RecipeRead(input); |
| 186 | + void *buffer = malloc(512 * 1024); // 512 KiB is plenty |
| 187 | + void *yazCtx = yazCtx_new(); |
| 188 | + FILE *out; |
| 189 | + unsigned int rel; |
| 190 | + |
| 191 | + assert(buffer); |
| 192 | + assert(recipe); |
| 193 | + |
| 194 | + if (!(out = fopen(recipe->yarName, "wb"))) |
| 195 | + { |
| 196 | + fprintf(stderr, "failed to open '%s' for writing\n", recipe->yarName); |
| 197 | + exit(EXIT_FAILURE); |
| 198 | + } |
| 199 | + |
| 200 | + // header |
| 201 | + FilePutBE32(out, (recipe->count + 1) * sizeof(uint32_t)); |
| 202 | + for (int i = 0; i < recipe->count; ++i) |
| 203 | + FilePutBE32(out, 0); |
| 204 | + rel = ftell(out); |
| 205 | + |
| 206 | + for (struct RecipeItem *this = recipe->head; this; this = this->next) |
| 207 | + { |
| 208 | + const char *imgFn = this->imageFilename; |
| 209 | + const char *errmsg = 0; |
| 210 | + void *pix; |
| 211 | + int w; |
| 212 | + int h; |
| 213 | + int unused; |
| 214 | + unsigned int sz; |
| 215 | + |
| 216 | + // load image |
| 217 | + if (!(pix = stbi_load(imgFn, &w, &h, &unused, STBI_rgb_alpha))) |
| 218 | + { |
| 219 | + fprintf(stderr, "failed to load image '%s'\n", imgFn); |
| 220 | + exit(EXIT_FAILURE); |
| 221 | + } |
| 222 | + |
| 223 | + // assert no size change |
| 224 | + if (this->width != w || this->height != h) |
| 225 | + { |
| 226 | + fprintf(stderr, "'%s' image unexpected dimensions\n", imgFn); |
| 227 | + exit(EXIT_FAILURE); |
| 228 | + } |
| 229 | + |
| 230 | + // convert to n64 pixel format |
| 231 | + if ((errmsg = n64texconv_to_n64(pix, pix, 0, -1, this->fmt, this->bpp, w, h, &sz))) |
| 232 | + { |
| 233 | + fprintf(stderr, "'%s' conversion error: %s\n", imgFn, errmsg); |
| 234 | + exit(EXIT_FAILURE); |
| 235 | + } |
| 236 | + |
| 237 | + // compress |
| 238 | + if (yazenc(pix, sz, buffer, &sz, yazCtx)) |
| 239 | + { |
| 240 | + fprintf(stderr, "compression error\n"); |
| 241 | + exit(EXIT_FAILURE); |
| 242 | + } |
| 243 | + |
| 244 | + // write |
| 245 | + if (fwrite(buffer, 1, sz, out) != sz) |
| 246 | + { |
| 247 | + fprintf(stderr, "error writing to file '%s'\n", recipe->yarName); |
| 248 | + exit(EXIT_FAILURE); |
| 249 | + } |
| 250 | + |
| 251 | + // alignment |
| 252 | + while (ftell(out) & 3) |
| 253 | + fputc(0, out); |
| 254 | + |
| 255 | + // used for header later |
| 256 | + this->endOffset = ftell(out) - rel; |
| 257 | + |
| 258 | + // cleanup |
| 259 | + free(pix); |
| 260 | + } |
| 261 | + |
| 262 | + // header |
| 263 | + fseek(out, 4, SEEK_SET); |
| 264 | + for (struct RecipeItem *this = recipe->head; this; this = this->next) |
| 265 | + FilePutBE32(out, this->endOffset); |
| 266 | + |
| 267 | + fclose(out); |
| 268 | + RecipeFree(recipe); |
| 269 | + yazCtx_free(yazCtx); |
| 270 | + free(buffer); |
183 | 271 | return EXIT_SUCCESS;
|
184 | 272 | }
|
185 | 273 |
|
|
0 commit comments