sdk-world v2026.11.05
PS2 SDK - world tier (copyleft-allowed, non-essential packages)
Loading...
Searching...
No Matches
gsToolkit.c
1// ____ ___ | / _____ _____
2// | __ | |___/ | |
3// |___| ___| | \ __|__ | gsKit Open Source Project.
4// ----------------------------------------------------------------------
5// Copyright 2004 - Chris "Neovanglist" Gilbert <Neovanglist@LainOS.org>
6// Licenced under Academic Free License version 2.0
7// Review gsKit README & LICENSE files for further details.
8//
9// gsToolkit.c - Utility library for gsKit
10//
11
12#include <stdio.h>
13#include <stdint.h>
14#include <stdlib.h>
15#include <malloc.h>
16#include <math.h>
17
18#include "gsKit.h"
19#include "gsToolkit.h"
20
21#ifdef HAVE_LIBJPEG
22#include <jpeglib.h>
23#endif
24
25#ifdef HAVE_LIBTIFF
26#include <tiffio.h>
27#endif
28
29#ifdef HAVE_LIBPNG
30#include <png.h>
31#endif
32
33extern int gsKit_texture_finish(GSGLOBAL *gsGlobal, GSTEXTURE *Texture);
34
35int gsKit_texture_finish(GSGLOBAL *gsGlobal, GSTEXTURE *Texture)
36{
37 if(!Texture->Delayed)
38 {
39 Texture->Vram = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(Texture->Width, Texture->Height, Texture->PSM), GSKIT_ALLOC_USERBUFFER);
40 if(Texture->Vram == GSKIT_ALLOC_ERROR)
41 {
42 printf("VRAM Allocation Failed. Will not upload texture.\n");
43 return -1;
44 }
45
46 if(Texture->Clut != NULL)
47 {
48 if(Texture->PSM == GS_PSM_T4)
49 Texture->VramClut = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(8, 2, GS_PSM_CT32), GSKIT_ALLOC_USERBUFFER);
50 else
51 Texture->VramClut = gsKit_vram_alloc(gsGlobal, gsKit_texture_size(16, 16, GS_PSM_CT32), GSKIT_ALLOC_USERBUFFER);
52
53 if(Texture->VramClut == GSKIT_ALLOC_ERROR)
54 {
55 printf("VRAM CLUT Allocation Failed. Will not upload texture.\n");
56 return -1;
57 }
58 }
59
60 // Upload texture
61 gsKit_texture_upload(gsGlobal, Texture);
62 // Free texture
63 free(Texture->Mem);
64 Texture->Mem = NULL;
65 // Free texture CLUT
66 if(Texture->Clut != NULL)
67 {
68 free(Texture->Clut);
69 Texture->Clut = NULL;
70 }
71 }
72 else
73 {
74 gsKit_setup_tbw(Texture);
75 }
76
77 return 0;
78}
79
80int gsKit_texture_png(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path)
81{
82#ifdef HAVE_LIBPNG
83 FILE* File = fopen(Path, "rb");
84 if (File == NULL)
85 {
86 printf("Failed to load PNG file: %s\n", Path);
87 return -1;
88 }
89
90 png_structp png_ptr;
91 png_infop info_ptr;
92 png_uint_32 width, height;
93 png_bytep *row_pointers;
94
95 u32 sig_read = 0;
96 int row, i, k=0, j, bit_depth, color_type, interlace_type;
97
98 png_ptr = png_create_read_struct(PNG_LIBPNG_VER_STRING, (png_voidp) NULL, NULL, NULL);
99
100 if(!png_ptr)
101 {
102 printf("PNG Read Struct Init Failed\n");
103 fclose(File);
104 return -1;
105 }
106
107 info_ptr = png_create_info_struct(png_ptr);
108
109 if(!info_ptr)
110 {
111 printf("PNG Info Struct Init Failed\n");
112 fclose(File);
113 png_destroy_read_struct(&png_ptr, (png_infopp)NULL, (png_infopp)NULL);
114 return -1;
115 }
116
117 if(setjmp(png_jmpbuf(png_ptr)))
118 {
119 printf("Got PNG Error!\n");
120 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp)NULL);
121 fclose(File);
122 return -1;
123 }
124
125 png_init_io(png_ptr, File);
126
127 png_set_sig_bytes(png_ptr, sig_read);
128
129 png_read_info(png_ptr, info_ptr);
130
131 png_get_IHDR(png_ptr, info_ptr, &width, &height, &bit_depth, &color_type,&interlace_type, NULL, NULL);
132
133 if (bit_depth == 16)
134 png_set_strip_16(png_ptr);
135
136 if (color_type == PNG_COLOR_TYPE_GRAY && bit_depth < 4)
137 png_set_expand(png_ptr);
138
139 if (png_get_valid(png_ptr, info_ptr, PNG_INFO_tRNS))
140 png_set_tRNS_to_alpha(png_ptr);
141
142 png_set_filler(png_ptr, 0xff, PNG_FILLER_AFTER);
143
144 png_read_update_info(png_ptr, info_ptr);
145
146 Texture->Width = width;
147 Texture->Height = height;
148
149 Texture->VramClut = 0;
150 Texture->Clut = NULL;
151
152 if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB_ALPHA)
153 {
154 int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
155 Texture->PSM = GS_PSM_CT32;
156 Texture->Mem = memalign(128, gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM));
157
158 row_pointers = calloc(height, sizeof(png_bytep));
159
160 for (row = 0; row < height; row++) row_pointers[row] = malloc(row_bytes);
161
162 png_read_image(png_ptr, row_pointers);
163
164 struct pixel { u8 r,g,b,a; };
165 struct pixel *Pixels = (struct pixel *) Texture->Mem;
166
167 for (i=0;i<height;i++) {
168 for (j=0;j<width;j++) {
169 Pixels[k].r = row_pointers[i][4*j];
170 Pixels[k].g = row_pointers[i][4*j+1];
171 Pixels[k].b = row_pointers[i][4*j+2];
172 Pixels[k++].a = 128-((int) row_pointers[i][4*j+3] * 128 / 255);
173 }
174 }
175
176 for(row = 0; row < height; row++) free(row_pointers[row]);
177
178 free(row_pointers);
179 }
180 else if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_RGB)
181 {
182 int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
183 Texture->PSM = GS_PSM_CT24;
184 Texture->Mem = memalign(128, gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM));
185
186 row_pointers = calloc(height, sizeof(png_bytep));
187
188 for(row = 0; row < height; row++) row_pointers[row] = malloc(row_bytes);
189
190 png_read_image(png_ptr, row_pointers);
191
192 struct pixel3 { u8 r,g,b; };
193 struct pixel3 *Pixels = (struct pixel3 *) Texture->Mem;
194
195 for (i=0;i<height;i++) {
196 for (j=0;j<width;j++) {
197 Pixels[k].r = row_pointers[i][4*j];
198 Pixels[k].g = row_pointers[i][4*j+1];
199 Pixels[k++].b = row_pointers[i][4*j+2];
200 }
201 }
202
203 for(row = 0; row < height; row++) free(row_pointers[row]);
204
205 free(row_pointers);
206 }
207 else if(png_get_color_type(png_ptr, info_ptr) == PNG_COLOR_TYPE_PALETTE)
208 {
209 png_colorp palette = NULL;
210 int num_pallete = 0;
211 png_bytep trans = NULL;
212 int num_trans = 0;
213
214 png_get_PLTE(png_ptr, info_ptr, &palette, &num_pallete);
215 png_get_tRNS(png_ptr, info_ptr, &trans, &num_trans, NULL);
216 Texture->ClutPSM = GS_PSM_CT32;
217
218 struct png_clut { u8 r, g, b, a; };
219
220 if (bit_depth == 4)
221 {
222
223 int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
224 Texture->PSM = GS_PSM_T4;
225 Texture->Mem = memalign(128, gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM));
226
227 row_pointers = calloc(height, sizeof(png_bytep));
228
229 for(row = 0; row < height; row++) row_pointers[row] = malloc(row_bytes);
230
231 png_read_image(png_ptr, row_pointers);
232
233 Texture->Clut = memalign(128, gsKit_texture_size_ee(8, 2, GS_PSM_CT32));
234 memset(Texture->Clut, 0, gsKit_texture_size_ee(8, 2, GS_PSM_CT32));
235
236 unsigned char *pixel = (unsigned char *)Texture->Mem;
237 struct png_clut *clut = (struct png_clut *)Texture->Clut;
238
239 int i, j, k = 0;
240
241 for (i = num_pallete; i < 16; i++) {
242 memset(&clut[i], 0, sizeof(clut[i]));
243 }
244
245 for (i = 0; i < num_pallete; i++) {
246 clut[i].r = palette[i].red;
247 clut[i].g = palette[i].green;
248 clut[i].b = palette[i].blue;
249 clut[i].a = 0x80;
250 }
251
252 for (i = 0; i < num_trans; i++)
253 clut[i].a = trans[i] >> 1;
254
255 for (i = 0; i < Texture->Height; i++) {
256 for (j = 0; j < Texture->Width / 2; j++)
257 memcpy(&pixel[k++], &row_pointers[i][1 * j], 1);
258 }
259
260 int byte;
261 unsigned char *tmpdst = (unsigned char *)Texture->Mem;
262 unsigned char *tmpsrc = (unsigned char *)pixel;
263
264 for (byte = 0; byte < gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM); byte++) tmpdst[byte] = (tmpsrc[byte] << 4) | (tmpsrc[byte] >> 4);
265
266 for(row = 0; row < height; row++) free(row_pointers[row]);
267
268 free(row_pointers);
269
270 }
271 else if (bit_depth == 8)
272 {
273 int row_bytes = png_get_rowbytes(png_ptr, info_ptr);
274 Texture->PSM = GS_PSM_T8;
275 Texture->Mem = memalign(128, gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM));
276
277 row_pointers = calloc(height, sizeof(png_bytep));
278
279 for(row = 0; row < height; row++) row_pointers[row] = malloc(row_bytes);
280
281 png_read_image(png_ptr, row_pointers);
282
283 Texture->Clut = memalign(128, gsKit_texture_size_ee(16, 16, GS_PSM_CT32));
284 memset(Texture->Clut, 0, gsKit_texture_size_ee(16, 16, GS_PSM_CT32));
285
286 unsigned char *pixel = (unsigned char *)Texture->Mem;
287 struct png_clut *clut = (struct png_clut *)Texture->Clut;
288
289 int i, j, k = 0;
290
291 for (i = num_pallete; i < 256; i++) {
292 memset(&clut[i], 0, sizeof(clut[i]));
293 }
294
295 for (i = 0; i < num_pallete; i++) {
296 clut[i].r = palette[i].red;
297 clut[i].g = palette[i].green;
298 clut[i].b = palette[i].blue;
299 clut[i].a = 0x80;
300 }
301
302 for (i = 0; i < num_trans; i++)
303 clut[i].a = trans[i] >> 1;
304
305 // rotate clut
306 for (i = 0; i < num_pallete; i++) {
307 if ((i & 0x18) == 8) {
308 struct png_clut tmp = clut[i];
309 clut[i] = clut[i + 8];
310 clut[i + 8] = tmp;
311 }
312 }
313
314 for (i = 0; i < Texture->Height; i++) {
315 for (j = 0; j < Texture->Width; j++) {
316 memcpy(&pixel[k++], &row_pointers[i][1 * j], 1);
317 }
318 }
319
320 for(row = 0; row < height; row++) free(row_pointers[row]);
321
322 free(row_pointers);
323 }
324 }
325 else
326 {
327 printf("This texture depth is not supported yet!\n");
328 return -1;
329 }
330
331 Texture->Filter = GS_FILTER_NEAREST;
332 png_read_end(png_ptr, NULL);
333 png_destroy_read_struct(&png_ptr, &info_ptr, (png_infopp) NULL);
334 fclose(File);
335
336 return gsKit_texture_finish(gsGlobal, Texture);
337#else
338 printf("ERROR: gsKit_texture_png unimplemented.\n");
339 return -1;
340#endif
341}
342
343int gsKit_texture_bmp(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path)
344{
345 GSBITMAP Bitmap;
346 int x, y;
347 int cy;
348 u32 FTexSize;
349 u8 *image;
350 u8 *p;
351 u32 TextureSize;
352 FILE* File;
353
354 File = fopen(Path, "rb");
355 if (File == NULL)
356 {
357 printf("BMP: Failed to load bitmap: %s\n", Path);
358 return -1;
359 }
360 if (fread(&Bitmap.FileHeader, 1, sizeof(Bitmap.FileHeader), File) != sizeof(Bitmap.FileHeader))
361 {
362 printf("BMP: Could not load bitmap: %s\n", Path);
363 fclose(File);
364 return -1;
365 }
366
367 if (fread(&Bitmap.InfoHeader, 1, sizeof(Bitmap.InfoHeader), File) != sizeof(Bitmap.InfoHeader))
368 {
369 printf("BMP: Could not load bitmap: %s\n", Path);
370 fclose(File);
371 return -1;
372 }
373
374 Texture->Width = Bitmap.InfoHeader.Width;
375 Texture->Height = Bitmap.InfoHeader.Height;
376 Texture->Filter = GS_FILTER_NEAREST;
377
378 if(Bitmap.InfoHeader.BitCount == 4)
379 {
380 GSBMCLUT *clut;
381 int i;
382
383 Texture->PSM = GS_PSM_T4;
384 Texture->Clut = memalign(128, gsKit_texture_size_ee(8, 2, GS_PSM_CT32));
385 Texture->ClutPSM = GS_PSM_CT32;
386
387 memset(Texture->Clut, 0, gsKit_texture_size_ee(8, 2, GS_PSM_CT32));
388 fseek(File, 54, SEEK_SET);
389 if (fread(Texture->Clut, 1, Bitmap.InfoHeader.ColorUsed*sizeof(u32), File) != Bitmap.InfoHeader.ColorUsed*sizeof(u32))
390 {
391 if (Texture->Clut) {
392 free(Texture->Clut);
393 Texture->Clut = NULL;
394 }
395 printf("BMP: Could not load bitmap: %s\n", Path);
396 fclose(File);
397 return -1;
398 }
399
400 clut = (GSBMCLUT *)Texture->Clut;
401 for (i = Bitmap.InfoHeader.ColorUsed; i < 16; i++)
402 {
403 memset(&clut[i], 0, sizeof(clut[i]));
404 }
405
406 for (i = 0; i < 16; i++)
407 {
408 u8 tmp = clut[i].Blue;
409 clut[i].Blue = clut[i].Red;
410 clut[i].Red = tmp;
411 clut[i].Alpha = 0x80;
412 }
413
414 }
415 else if(Bitmap.InfoHeader.BitCount == 8)
416 {
417 GSBMCLUT *clut;
418 int i;
419
420 Texture->PSM = GS_PSM_T8;
421 Texture->Clut = memalign(128, gsKit_texture_size_ee(16, 16, GS_PSM_CT32));
422 Texture->ClutPSM = GS_PSM_CT32;
423
424 memset(Texture->Clut, 0, gsKit_texture_size_ee(16, 16, GS_PSM_CT32));
425 fseek(File, 54, SEEK_SET);
426 if (fread(Texture->Clut, Bitmap.InfoHeader.ColorUsed*sizeof(u32), 1, File) <= 0)
427 {
428 if (Texture->Clut) {
429 free(Texture->Clut);
430 Texture->Clut = NULL;
431 }
432 printf("BMP: Could not load bitmap: %s\n", Path);
433 fclose(File);
434 return -1;
435 }
436
437 clut = (GSBMCLUT *)Texture->Clut;
438 for (i = Bitmap.InfoHeader.ColorUsed; i < 256; i++)
439 {
440 memset(&clut[i], 0, sizeof(clut[i]));
441 }
442
443 for (i = 0; i < 256; i++)
444 {
445 u8 tmp = clut[i].Blue;
446 clut[i].Blue = clut[i].Red;
447 clut[i].Red = tmp;
448 clut[i].Alpha = 0x80;
449 }
450
451 // rotate clut
452 for (i = 0; i < 256; i++)
453 {
454 if ((i&0x18) == 8)
455 {
456 GSBMCLUT tmp = clut[i];
457 clut[i] = clut[i+8];
458 clut[i+8] = tmp;
459 }
460 }
461 }
462 else if(Bitmap.InfoHeader.BitCount == 16)
463 {
464 Texture->PSM = GS_PSM_CT16;
465 Texture->VramClut = 0;
466 Texture->Clut = NULL;
467 }
468 else if(Bitmap.InfoHeader.BitCount == 24)
469 {
470 Texture->PSM = GS_PSM_CT24;
471 Texture->VramClut = 0;
472 Texture->Clut = NULL;
473 }
474
475 fseek(File, 0, SEEK_END);
476 FTexSize = ftell(File);
477 FTexSize -= Bitmap.FileHeader.Offset;
478
479 fseek(File, Bitmap.FileHeader.Offset, SEEK_SET);
480
481 TextureSize = gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM);
482
483 Texture->Mem = memalign(128,TextureSize);
484
485 if(Bitmap.InfoHeader.BitCount == 24)
486 {
487 image = memalign(128, FTexSize);
488 if (image == NULL) {
489 printf("BMP: Failed to allocate memory\n");
490 if (Texture->Mem) {
491 free(Texture->Mem);
492 Texture->Mem = NULL;
493 }
494 if (Texture->Clut) {
495 free(Texture->Clut);
496 Texture->Clut = NULL;
497 }
498 fclose(File);
499 return -1;
500 }
501
502 fread(image, FTexSize, 1, File);
503 p = (void *)((u32)Texture->Mem);
504 for (y = Texture->Height - 1, cy = 0; y >= 0; y--, cy++) {
505 for (x = 0; x < Texture->Width; x++) {
506 p[(y * Texture->Width + x) * 3 + 2] = image[(cy * Texture->Width + x) * 3 + 0];
507 p[(y * Texture->Width + x) * 3 + 1] = image[(cy * Texture->Width + x) * 3 + 1];
508 p[(y * Texture->Width + x) * 3 + 0] = image[(cy * Texture->Width + x) * 3 + 2];
509 }
510 }
511 free(image);
512 image = NULL;
513 }
514 else if(Bitmap.InfoHeader.BitCount == 16)
515 {
516 image = memalign(128, FTexSize);
517 if (image == NULL) {
518 printf("BMP: Failed to allocate memory\n");
519 if (Texture->Mem) {
520 free(Texture->Mem);
521 Texture->Mem = NULL;
522 }
523 if (Texture->Clut) {
524 free(Texture->Clut);
525 Texture->Clut = NULL;
526 }
527 fclose(File);
528 return -1;
529 }
530
531 fread(image, FTexSize, 1, File);
532
533 p = (void *)((u32)Texture->Mem);
534 for (y = Texture->Height - 1, cy = 0; y >= 0; y--, cy++) {
535 for (x = 0; x < Texture->Width; x++) {
536 u16 value;
537 value = *(u16*)&image[(cy * Texture->Width + x) * 2];
538 value = (value & 0x8000) | value << 10 | (value & 0x3E0) | (value & 0x7C00) >> 10; //ARGB -> ABGR
539
540 *(u16*)&p[(y * Texture->Width + x) * 2] = value;
541 }
542 }
543 free(image);
544 image = NULL;
545 }
546 else if(Bitmap.InfoHeader.BitCount == 8 || Bitmap.InfoHeader.BitCount == 4)
547 {
548 char *tex = (char *)((u32)Texture->Mem);
549 image = memalign(128,FTexSize);
550 if (image == NULL) {
551 printf("BMP: Failed to allocate memory\n");
552 if (Texture->Mem) {
553 free(Texture->Mem);
554 Texture->Mem = NULL;
555 }
556 if (Texture->Clut) {
557 free(Texture->Clut);
558 Texture->Clut = NULL;
559 }
560 fclose(File);
561 return -1;
562 }
563
564 if (fread(image, FTexSize, 1, File) != 1)
565 {
566 if (Texture->Mem) {
567 free(Texture->Mem);
568 Texture->Mem = NULL;
569 }
570 if (Texture->Clut) {
571 free(Texture->Clut);
572 Texture->Clut = NULL;
573 }
574 printf("BMP: Read failed!, Size %d\n", FTexSize);
575 free(image);
576 image = NULL;
577 fclose(File);
578 return -1;
579 }
580 for (y = Texture->Height - 1; y >= 0; y--)
581 {
582 if(Bitmap.InfoHeader.BitCount == 8)
583 memcpy(&tex[y * Texture->Width], &image[(Texture->Height - y - 1) * Texture->Width], Texture->Width);
584 else
585 memcpy(&tex[y * (Texture->Width / 2)], &image[(Texture->Height - y - 1) * (Texture->Width / 2)], Texture->Width / 2);
586 }
587 free(image);
588 image = NULL;
589
590 if(Bitmap.InfoHeader.BitCount == 4)
591 {
592 int byte;
593 u8 *tmpdst = (u8 *)((u32)Texture->Mem);
594 u8 *tmpsrc = (u8 *)tex;
595
596 for(byte = 0; byte < FTexSize; byte++)
597 {
598 tmpdst[byte] = (tmpsrc[byte] << 4) | (tmpsrc[byte] >> 4);
599 }
600 }
601 }
602 else
603 {
604 printf("BMP: Unknown bit depth format %d\n", Bitmap.InfoHeader.BitCount);
605 }
606
607 fclose(File);
608
609 return gsKit_texture_finish(gsGlobal, Texture);
610}
611
612#ifdef HAVE_LIBJPEG
613struct my_error_mgr {
614 struct jpeg_error_mgr pub; /* "public" fields */
615
616 jmp_buf setjmp_buffer; /* for return to caller */
617};
618
619typedef struct my_error_mgr *my_error_ptr;
620
621METHODDEF(void)
622my_error_exit(j_common_ptr cinfo)
623{
624 /* cinfo->err really points to a my_error_mgr struct, so coerce pointer */
625 my_error_ptr myerr = (my_error_ptr)cinfo->err;
626
627 /* Always display the message. */
628 /* We could postpone this until after returning, if we chose. */
629 (*cinfo->err->output_message) (cinfo);
630
631 /* Return control to the setjmp point */
632 longjmp(myerr->setjmp_buffer, 1);
633}
634
635// Following official documentation max width or height of the texture is 1024
636#define MAX_TEXTURE 1024
637static void _ps2_load_JPEG_generic(GSTEXTURE *Texture, struct jpeg_decompress_struct *cinfo, struct my_error_mgr *jerr, bool scale_down)
638{
639 int textureSize = 0;
640 if (scale_down) {
641 unsigned int longer = cinfo->image_width > cinfo->image_height ? cinfo->image_width : cinfo->image_height;
642 float downScale = (float)longer / (float)MAX_TEXTURE;
643 cinfo->scale_denom = ceil(downScale);
644 }
645
646 jpeg_start_decompress(cinfo);
647
648 int psm = cinfo->out_color_components == 3 ? GS_PSM_CT24 : GS_PSM_CT32;
649
650 Texture->Width = cinfo->output_width;
651 Texture->Height = cinfo->output_height;
652 Texture->PSM = psm;
653 Texture->Filter = GS_FILTER_NEAREST;
654 Texture->VramClut = 0;
655 Texture->Clut = NULL;
656
657 textureSize = cinfo->output_width*cinfo->output_height*cinfo->out_color_components;
658 #ifdef DEBUG
659 printf("Texture Size = %i\n",textureSize);
660 #endif
661 Texture->Mem = memalign(128, textureSize);
662
663 unsigned int row_stride = textureSize/Texture->Height;
664 unsigned char *row_pointer = (unsigned char *)Texture->Mem;
665 while (cinfo->output_scanline < cinfo->output_height) {
666 jpeg_read_scanlines(cinfo, (JSAMPARRAY)&row_pointer, 1);
667 row_pointer += row_stride;
668 }
669
670 jpeg_finish_decompress(cinfo);
671}
672
673#endif
674
675int gsKit_texture_jpeg_scale(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path, bool scale_down)
676{
677#ifdef HAVE_LIBJPEG
678 FILE *fp;
679 struct jpeg_decompress_struct cinfo;
680 struct my_error_mgr jerr;
681
682 if (Texture == NULL) {
683 printf("jpeg: error Texture is NULL\n");
684 return -1;
685 }
686
687 if ((fp = fopen(Path, "rb")) <= 0) {
688 printf("jpeg: error opening FILE\n");
689 return -1;
690 }
691
692 /* We set up the normal JPEG error routines, then override error_exit. */
693 cinfo.err = jpeg_std_error(&jerr.pub);
694 jerr.pub.error_exit = my_error_exit;
695 /* Establish the setjmp return context for my_error_exit to use. */
696 if (setjmp(jerr.setjmp_buffer)) {
697 /* If we get here, the JPEG code has signaled an error.
698 * We need to clean up the JPEG object, close the input file, and return.
699 */
700 jpeg_destroy_decompress(&cinfo);
701 fclose(fp);
702 if (Texture->Mem)
703 free(Texture->Mem);
704 printf("jpeg: error during processing file\n");
705 return -1;
706 }
707 jpeg_create_decompress(&cinfo);
708 jpeg_stdio_src(&cinfo, fp);
709 jpeg_read_header(&cinfo, TRUE);
710
711 _ps2_load_JPEG_generic(Texture, &cinfo, &jerr, scale_down);
712
713 jpeg_destroy_decompress(&cinfo);
714 fclose(fp);
715
716 #if DEBUG
717 printf("jpeg: File image readed, allocating VRAM\n");
718 #endif
719 return gsKit_texture_finish(gsGlobal, Texture);
720#else
721 printf("ERROR: gsKit_texture_jpeg unimplemented.\n");
722 return -1;
723#endif
724}
725
726int gsKit_texture_jpeg(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path) {
727 return gsKit_texture_jpeg_scale(gsGlobal, Texture, Path, false);
728}
729
730int gsKit_texture_tiff(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path)
731{
732#ifdef HAVE_LIBTIFF
733 int TextureSize = 0;
734
735 TIFF* tif = TIFFOpen(Path, "r");
736 if(tif == NULL)
737 {
738 printf("Error Opening %s\n", Path);
739 return -1;
740 }
741
742 Texture->PSM = GS_PSM_CT32;
743 Texture->Filter = GS_FILTER_NEAREST;
744 Texture->VramClut = 0;
745 Texture->Clut = NULL;
746
747 TIFFGetField(tif, TIFFTAG_IMAGEWIDTH, &Texture->Width);
748 TIFFGetField(tif, TIFFTAG_IMAGELENGTH, &Texture->Height);
749 TextureSize = gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM);
750
751 #ifdef GSKIT_DEBUG
752 printf("Texture Size = %i\n",TextureSize);
753 #endif
754
755 Texture->Mem = memalign(128,TextureSize);
756
757 if (!TIFFReadRGBAImage(tif, Texture->Width, Texture->Height, (uint32_t *)Texture->Mem, 0))
758 {
759 printf("Error Reading TIFF Data\n");
760 TIFFClose(tif);
761 free(Texture->Mem);
762 return -1;
763 }
764
765 TIFFClose(tif);
766
767/*
768 // To dump+debug the RBGA data from tiff
769 FILE* File = fopen("host:texdump.raw", "wb");
770
771 fwrite(Texture->Mem, TextureSize, 1, File);
772
773 fclose(File);
774*/
775
776 return gsKit_texture_finish(gsGlobal, Texture);
777#else
778 printf("ERROR: gsKit_texture_tiff unimplimented.\n");
779 return -1;
780#endif
781}
782
783int gsKit_texture_raw(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path)
784{
785 FILE* File;
786 int FileSize;
787
788 File = fopen(Path, "rb");
789 if (File == NULL)
790 {
791 printf("Failed to load texture: %s\n", Path);
792 return -1;
793 }
794 FileSize = gsKit_texture_size_ee(Texture->Width, Texture->Height, Texture->PSM);
795 Texture->Mem = memalign(128, FileSize);
796
797 if(Texture->PSM != GS_PSM_T8 && Texture->PSM != GS_PSM_T4)
798 {
799 Texture->VramClut = 0;
800 Texture->Clut = NULL;
801 }
802
803 if(fread(Texture->Mem, 1, FileSize, File) != FileSize)
804 {
805 printf("Texture might be bad: %s\n", Path);
806 printf("Texture size: %d\n", FileSize);
807 }
808 fclose(File);
809
810 return gsKit_texture_finish(gsGlobal, Texture);
811}
812
813int gsKit_texture_tga(GSGLOBAL *gsGlobal, GSTEXTURE *Texture, char *Path)
814{
815 printf("ERROR: gsKit_texture_tga unimplimented.\n");
816 return -1;
817}
818
819int gsKit_texture_fnt_raw(GSGLOBAL *gsGlobal, GSFONT *gsFont)
820{
821 u32 *data = (u32*)gsFont->RawData;
822 u32 *mem;
823 int size = 0;
824 int vramsize = 0;
825 int i;
826
827 gsFont->Texture->Width = data[1];
828 gsFont->Texture->Height = data[2];
829 gsFont->Texture->PSM = data[3];
832 {
833 gsFont->Texture->VramClut = 0;
834 gsFont->Texture->Clut = NULL;
835 }
836
837 gsFont->HChars = data[4];
838 gsFont->VChars = data[5];
839 gsFont->CharWidth = data[6];
840 gsFont->CharHeight = data[7];
841
842 size = gsKit_texture_size_ee(gsFont->Texture->Width, gsFont->Texture->Height, gsFont->Texture->PSM);
843 vramsize = gsKit_texture_size(gsFont->Texture->Width, gsFont->Texture->Height, gsFont->Texture->PSM);
844 gsFont->Texture->Mem = memalign(128, size);
847 {
848 printf("VRAM Allocation Failed. Will not upload texture.\n");
849 return -1;
850 }
851
852 memcpy(gsFont->Texture->Mem, &data[288/4], size);
853
854 if (gsFont->Texture->PSM != GS_PSM_CT32) {
855 printf("Unsupported fnt PSM %d\n", gsFont->Texture->PSM);
856 }
857 mem = (u32*)gsFont->Texture->Mem;
858 for (i=0; i<size/4; i++) {
859 if (mem[i] == 0xFF00FFFF) {
860 mem[i] = 0;
861 } else {
862 u32 c = (mem[i] & 0x00FF0000) >> 16;
863 mem[i] = 0x80000000 | (c) | (c<<8) | (c<<16);
864 }
865 }
866
867 gsKit_texture_upload(gsGlobal, gsFont->Texture);
868 free(gsFont->Texture->Mem);
869 return 0;
870}
871
872// TODO:fix
873/*
874int gsKit_texture_fnt(GSGLOBAL *gsGlobal, GSFONT *gsFont)
875{
876 u32 *mem;
877 int size = 0;
878 int vramsize = 0;
879 int i;
880
881 FILE* File = fopen(gsFont->Path, "rb");
882 if (File == NULL)
883 {
884 printf("Failed to load font: %s\n", gsFont->Path);
885 return -1;
886 }
887 fseek(File, 4, SEEK_SET);
888 if(fread(&gsFont->Texture->Width, 4, 1, File) <= 0)
889 {
890 printf("Could not load font: %s\n", gsFont->Path);
891 return -1;
892 }
893 if(fread(&gsFont->Texture->Height, 4, 1, File) <= 0)
894 {
895 printf("Could not load font: %s\n", gsFont->Path);
896 return -1;
897 }
898 if(fread((int*)&gsFont->Texture->PSM, 4, 1, File) <= 0)
899 {
900 printf("Could not load font: %s\n", gsFont->Path);
901 return -1;
902 }
903 if(fread(&gsFont->HChars, 4, 1, File) <= 0)
904 {
905 printf("Could not load font: %s\n", gsFont->Path);
906 return -1;
907 }
908 if(fread(&gsFont->VChars, 4, 1, File) <= 0)
909 {
910 printf("Could not load font: %s\n", gsFont->Path);
911 return -1;
912 }
913 if(fread(&gsFont->CharWidth, 4, 1, File) <= 0)
914 {
915 printf("Could not load font: %s\n", gsFont->Path);
916 return -1;
917 }
918 if(fread(&gsFont->CharHeight, 4, 1, File) <= 0)
919 {
920 printf("Could not load font: %s\n", gsFont->Path);
921 return -1;
922 }
923
924 fseek(File, 284, SEEK_SET);
925
926 gsFont->Texture->Filter = GS_FILTER_NEAREST;
927
928 size = gsKit_texture_size_ee(gsFont->Texture->Width, gsFont->Texture->Height, gsFont->Texture->PSM);
929 vramsize = gsKit_texture_size(gsFont->Texture->Width, gsFont->Texture->Height, gsFont->Texture->PSM);
930 gsFont->Texture->Mem = memalign(128, size); // shouldn't this just be a (char*)malloc(sizeof(char)*256);
931 gsFont->Texture->Vram = gsKit_vram_alloc(gsGlobal, vramsize, GSKIT_ALLOC_USERBUFFER);
932
933 if(gsFont->Texture->Vram == GSKIT_ALLOC_ERROR)
934 {
935 printf("VRAM Allocation Failed. Will not upload texture.\n");
936 return -1;
937 }
938
939 if(fread(gsFont->Texture->Mem, size, 1, File) <= 0)
940 {
941 printf("Font might be bad: %s\n", gsFont->Path);
942 }
943
944 fclose(File);
945
946 if (gsFont->Texture->PSM != 0) {
947 printf("Unsupported fnt PSM %d\n", gsFont->Texture->PSM);
948 }
949
950 mem = (u32*)gsFont->Texture->Mem;
951
952 for (i=0; i<size/4; i++) {
953 if (mem[i] == 0xFF00FFFF) {
954 mem[i] = 0;
955 } else {
956 u32 c = (mem[i] & 0x00FF0000) >> 16;
957 mem[i] = 0x80000000 | (c) | (c<<8) | (c<<16);
958 }
959 }
960
961 gsKit_texture_upload(gsGlobal, gsFont->Texture);
962 free(gsFont->Texture->Mem);
963
964 return 0;
965}
966*/
967
968GSFONT *gsKit_init_font(u8 type, char *path)
969{
970 char *tmp = NULL;
971
972 GSFONT *gsFont = calloc(1,sizeof(GSFONT));
973 gsFont->Texture = calloc(1,sizeof(GSTEXTURE));
974 gsFont->Path = calloc(1,strlen(path));
975 gsFont->Additional=calloc(1,sizeof(short)*256);
976
977 gsFont->Type = type;
978 strcpy(gsFont->Path, path);
979
980 if(gsFont->Type == GSKIT_FTYPE_BMP_DAT || gsFont->Type == GSKIT_FTYPE_PNG_DAT)
981 {
982 gsFont->Path_DAT = calloc(1,strlen(path));
983 strcpy(gsFont->Path_DAT, path);
984
985 if(gsFont->Type == GSKIT_FTYPE_BMP_DAT) tmp = strstr(gsFont->Path_DAT, ".bmp");
986 if(gsFont->Type == GSKIT_FTYPE_PNG_DAT) tmp = strstr(gsFont->Path_DAT, ".png");
987
988 if (tmp == NULL)
989 {
990 free(gsFont->Additional);
991 free(gsFont->Path);
992 free(gsFont->Path_DAT);
993 free(gsFont->Texture);
994 free(gsFont);
995
996 printf("Error initializing .dat\n");
997
998 return NULL;
999 }
1000 else
1001 {
1002 strcpy(tmp, ".dat");
1003 }
1004 }
1005 else
1006 {
1007 gsFont->Path_DAT = NULL;
1008 }
1009
1010 return gsFont;
1011
1012}
1013
1014GSFONT *gsKit_init_font_raw(u8 type, u8 *data, int size)
1015{
1016
1017 GSFONT *gsFont = calloc(1,sizeof(GSFONT));
1018 gsFont->Texture = calloc(1,sizeof(GSTEXTURE));
1019 gsFont->RawData = data;
1020 gsFont->RawSize = size;
1021 gsFont->Type = type;
1022 gsFont->Additional=(short*)malloc(sizeof(short)*256);
1023
1024 return gsFont;
1025}
1026
1027int gsKit_font_upload_raw(GSGLOBAL *gsGlobal, GSFONT *gsFont)
1028{
1029 if( gsFont->Type == GSKIT_FTYPE_FNT )
1030 {
1031 int i;
1032
1033 if( gsKit_texture_fnt_raw(gsGlobal, gsFont) == -1 )
1034 {
1035 printf("Error uploading font!\n");
1036 return -1;
1037 }
1038 for (i=0; i<256; i++) {
1039 gsFont->Additional[i] = (short)gsFont->CharWidth;
1040 }
1041
1042 return 0;
1043 }
1044
1045 return -1; //type unknown
1046}
1047
1048int gsKit_font_upload(GSGLOBAL *gsGlobal, GSFONT *gsFont)
1049{
1050 int i;
1051
1052 if( gsFont->RawData ) {
1053 return gsKit_font_upload_raw(gsGlobal, gsFont);
1054 }
1055
1056 if( gsFont->Type == GSKIT_FTYPE_FNT )
1057 {
1058 //if( gsKit_texture_fnt(gsGlobal, gsFont) == -1 )
1059 //{
1060 printf("Error uploading font!\n");
1061 return -1;
1062 //}
1063
1064 for (i=0; i<256; i++) {
1066 }
1067
1068 return 0;
1069 }
1070 else if( (gsFont->Type == GSKIT_FTYPE_PNG_DAT) ||
1071 (gsFont->Type == GSKIT_FTYPE_BMP_DAT))
1072 {
1073#ifdef HAVE_LIBPNG
1074 if( gsFont->Type == GSKIT_FTYPE_PNG_DAT)
1075 if( gsKit_texture_png(gsGlobal, gsFont->Texture, gsFont->Path) == -1)
1076 {
1077 printf("Error uploading font png!\n");
1078 return -1;
1079 }
1080#endif
1081 if( gsFont->Type == GSKIT_FTYPE_BMP_DAT )
1082 if( gsKit_texture_bmp(gsGlobal, gsFont->Texture, gsFont->Path) == -1 )
1083 {
1084 printf("Error uploading font bmp!\n");
1085 return -1;
1086 }
1087
1088 gsFont->HChars=16;
1089 gsFont->VChars=16;
1092
1093 if(gsFont->Path_DAT != NULL) {
1094 FILE* File = fopen(gsFont->Path_DAT, "rb");
1095 if (File != NULL)
1096 {
1097 fseek(File, 0, SEEK_SET);
1098 for(i=0; i<256; i++) {
1099 if(fread(&gsFont->Additional[i], 1, 2, File) != 2)
1100 {
1101 printf("Problem reading font sizes %s\n", gsFont->Path_DAT);
1102 fclose(File);
1103 return -1;
1104 }
1105 }
1106 fclose(File);
1107 return 0;
1108 }
1109 else
1110 {
1111 for (i=0; i<256; i++) {
1112 gsFont->Additional[i] = (short)gsFont->CharWidth;
1113 return 0;
1114 }
1115 }
1116 }
1117 }
1118
1119 // if it reaches here, something's wrong
1120 printf("Error uploading font!\n");
1121
1122 return -1;
1123}
1124
1125void gsKit_font_print_scaled(GSGLOBAL *gsGlobal, GSFONT *gsFont, float X, float Y, int Z,
1126 float scale, unsigned long color, const char *String)
1127{
1128#ifdef HAVE_LIBPNG
1129 if( gsFont->Type == GSKIT_FTYPE_PNG_DAT)
1130 {
1131 u64 oldalpha = gsGlobal->PrimAlpha;
1132 u8 oldpabe = gsGlobal->PABE;
1133 u8 fixate = 0;
1134 if(gsGlobal->Test->ATE)
1135 {
1137 fixate = 1;
1138 }
1140
1141
1142 int cx,cy,i,l;
1143 u8 c;
1144 cx=X;
1145 cy=Y;
1146
1147 l=strlen( String );
1148 for( i=0;i<l;i++ )
1149 {
1150 c=String[i];
1151 if( c=='\n' )
1152 {
1153 cx=X;
1154 cy+=(gsFont->CharHeight*scale)+1;
1155 }
1156 else
1157 {
1158 int px,py,charsiz;
1159
1160 px=c%16;
1161 py=(c-px)/16;
1162 charsiz=gsFont->Additional[(u8)c];
1163
1164 gsKit_prim_sprite_texture(gsGlobal, gsFont->Texture, cx, cy,
1165 (px*gsFont->CharWidth), (py*gsFont->CharHeight+1),
1166 cx+(charsiz*scale), cy+(gsFont->CharHeight*scale),
1167 (px*gsFont->CharWidth)+charsiz, (py*gsFont->CharHeight)+16+1,
1168 Z, color);
1169 cx+=(charsiz*scale)+1;
1170 }
1171 }
1172 gsGlobal->PABE = oldpabe;
1173 gsGlobal->PrimAlpha=oldalpha;
1175 //gsKit_set_clamp(gsGlobal, GS_CMODE_RESET);
1176
1177 if(fixate)
1179
1180 }
1181#endif
1182 if( gsFont->Type == GSKIT_FTYPE_BMP_DAT ||
1183 gsFont->Type == GSKIT_FTYPE_FNT)
1184 {
1185 u64 oldalpha;
1186 u8 oldpabe;
1187 int cx,cy,i,l;
1188
1189 oldpabe = gsGlobal->PABE;
1190 oldalpha = gsGlobal->PrimAlpha;
1191
1192 gsKit_set_primalpha(gsGlobal, ALPHA_BLEND_ADD, 1);
1193
1194 cx=X;
1195 cy=Y;
1196
1197 l=strlen( String );
1198 for( i=0;i<l;i++ )
1199 {
1200 unsigned char c=String[i];
1201 if( c=='\n' )
1202 {
1203 cx=X;
1204 cy+=(gsFont->CharHeight*scale)+1;
1205 }
1206 else
1207 {
1208 int px,py,charsiz;
1209
1210 px=c%16;
1211 py=(c-px)/16;
1212 charsiz=gsFont->Additional[(u8)c];
1213
1214 gsKit_prim_sprite_texture(gsGlobal, gsFont->Texture, cx, cy,
1215 (px*gsFont->CharWidth), (py*gsFont->CharHeight+1),
1216 cx+(charsiz*scale), cy+(gsFont->CharHeight*scale),
1217 (px*gsFont->CharWidth)+charsiz, (py*gsFont->CharHeight)+16+1,
1218 Z, color);
1219 cx+=(charsiz*scale)+1;
1220 }
1221 }
1222
1223 gsKit_set_primalpha(gsGlobal, oldalpha, oldpabe);
1224 }
1225}
1226
#define GS_ATEST_OFF
Turns off Alpha Testing (Source).
Definition gsCore.h:62
#define GS_ATEST_ON
Turns on Alpha Testing (Source).
Definition gsCore.h:64
u32 gsKit_vram_alloc(GSGLOBAL *gsGlobal, u32 size, u8 type)
GS VRAM Allocation.
Definition gsCore.c:20
#define GS_FILTER_NEAREST
Use simple filtering (nearest neighbor).
Definition gsCore.h:71
#define GSKIT_ALLOC_USERBUFFER
GS VRAM "User" Allocation (Texture, CLUT, etc).
Definition gsCore.h:26
void gsKit_set_primalpha(GSGLOBAL *gsGlobal, u64 AlphaMode, u8 PerPixel)
Sets the Alpha Blending Parameters.
Definition gsCore.c:356
#define GSKIT_ALLOC_ERROR
Return this is VRAM allocation fails.
Definition gsCore.h:29
void gsKit_set_test(GSGLOBAL *gsGlobal, u8 Preset)
Definition gsCore.c:286
#define GS_PSM_CT32
R8 G8 B8 A8 (RGBA32) Texture.
Definition gsInit.h:115
#define GS_PSM_T8
8 Bit Texture with CLUT
Definition gsInit.h:123
#define GS_PSM_T4
4 Bit Texture with CLUT
Definition gsInit.h:127
#define GS_SETREG_ALPHA(A, B, C, D, FIX)
GS ALPHA Packing Macro.
Definition gsInit.h:796
#define GS_PSM_CT24
R8 G8 B8 (RGB24) Texture.
Definition gsInit.h:117
#define GS_PSM_CT16
RGBA16 Texture.
Definition gsInit.h:119
GSFONT * gsKit_init_font(u8 type, char *path)
Initialize Font Object (From Memory).
Definition gsToolkit.c:968
u8 Type
Font Type.
Definition gsToolkit.h:77
u8 * RawData
Raw File Data.
Definition gsToolkit.h:78
char * Path_DAT
Path (string) to the Glyph DAT File.
Definition gsToolkit.h:76
char * Path
Path (string) to the Font File.
Definition gsToolkit.h:75
u32 VChars
Character Columns.
Definition gsToolkit.h:84
int RawSize
Raw File Datasize.
Definition gsToolkit.h:79
GSTEXTURE * Texture
Font Texture Object.
Definition gsToolkit.h:80
u32 HChars
Character Rows.
Definition gsToolkit.h:83
s16 * Additional
Additional Font Data.
Definition gsToolkit.h:85
u32 CharHeight
Character Height.
Definition gsToolkit.h:82
u32 CharWidth
Character Width.
Definition gsToolkit.h:81
GSTEST * Test
TEST Register Value Structure Pointer.
Definition gsInit.h:932
u64 PrimAlpha
Primitive Alpha Value.
Definition gsInit.h:946
u8 PABE
Choose if to do Alpha Blend on a Per-Pixel Basis.
Definition gsInit.h:947
u8 ATE
Alpha Test Enable.
Definition gsInit.h:826
u32 * Clut
EE CLUT Memory Pointer.
Definition gsInit.h:962
u32 * Mem
EE Memory Pointer.
Definition gsInit.h:961
u32 Vram
GS VRAM Memory Pointer.
Definition gsInit.h:963
u32 VramClut
GS VRAM CLUT Memory Pointer.
Definition gsInit.h:964
u8 Delayed
Delay Texture Upload To VRAM.
Definition gsInit.h:967
u8 ClutPSM
CLUT Pixel Storage Method (Color Format).
Definition gsInit.h:959
u8 PSM
Pixel Storage Method (Color Format).
Definition gsInit.h:958
u32 Height
Height of the Texture.
Definition gsInit.h:957
u32 Width
Width of the Texture.
Definition gsInit.h:956
u32 Filter
NEAREST or LINEAR.
Definition gsInit.h:965