usb gecko retries
[libogc.git] / libogc / tpl.c
blob0fef325ea911132d8f5305fa0bc6bcc5243c8bc7
1 #include <stdlib.h>
2 #include <string.h>
3 #include <stdio.h>
4 #include <malloc.h>
5 #include <gcutil.h>
6 #include <gccore.h>
7 #include "tpl.h"
8 #include "processor.h"
10 #define TPL_FILE_TYPE_DISC 0
11 #define TPL_FILE_TYPE_MEM 1
13 #define TPL_HDR_VERSION_FIELD 0
14 #define TPL_HDR_NTEXTURE_FIELD 4
15 #define TPL_HDR_HDRSIZE_FIELD 8
16 #define TPL_HDR_DESCR_FIELD 12
18 // texture header
19 typedef struct _tplimgheader TPLImgHeader;
21 struct _tplimgheader {
22 u16 height;
23 u16 width;
24 u32 fmt;
25 void *data;
26 u32 wraps;
27 u32 wrapt;
28 u32 minfilter;
29 u32 magfilter;
30 f32 lodbias;
31 u8 edgelod;
32 u8 minlod;
33 u8 maxlod;
34 u8 unpacked;
35 } ATTRIBUTE_PACKED;
37 // texture palette header
38 typedef struct _tplpalheader TPLPalHeader;
40 struct _tplpalheader {
41 u16 nitems;
42 u8 unpacked;
43 u8 pad;
44 u32 fmt;
45 void *data;
46 } ATTRIBUTE_PACKED;
48 // texture descriptor
49 typedef struct _tpldesc TPLDescHeader;
51 struct _tpldesc {
52 TPLImgHeader *imghead;
53 TPLPalHeader *palhead;
54 } ATTRIBUTE_PACKED;
56 static u32 TPL_GetTextureSize(u32 width,u32 height,u32 fmt)
58 u32 size = 0;
60 switch(fmt) {
61 case GX_TF_I4:
62 case GX_TF_CI4:
63 case GX_TF_CMPR:
64 size = ((width+7)>>3)*((height+7)>>3)*32;
65 break;
66 case GX_TF_I8:
67 case GX_TF_IA4:
68 case GX_TF_CI8:
69 size = ((width+7)>>3)*((height+7)>>2)*32;
70 break;
71 case GX_TF_IA8:
72 case GX_TF_CI14:
73 case GX_TF_RGB565:
74 case GX_TF_RGB5A3:
75 size = ((width+3)>>2)*((height+3)>>2)*32;
76 break;
77 case GX_TF_RGBA8:
78 size = ((width+3)>>2)*((height+3)>>2)*32*2;
79 break;
80 default:
81 break;
83 return size;
86 s32 TPL_OpenTPLFromFile(TPLFile* tdf, const char* file_name)
88 u32 c;
89 u32 version;
90 FILE *f = NULL;
91 TPLDescHeader *deschead = NULL;
92 TPLImgHeader *imghead = NULL;
93 TPLPalHeader *palhead = NULL;
95 if(!file_name) return 0;
97 f = fopen(file_name,"rb");
98 if(!f) return -1;
100 tdf->type = TPL_FILE_TYPE_DISC;
101 tdf->tpl_file = (FHANDLE)f;
103 fread(&version,sizeof(u32),1,f);
104 fread(&tdf->ntextures,sizeof(u32),1,f);
106 fseek(f,TPL_HDR_DESCR_FIELD,SEEK_SET);
108 deschead = malloc(tdf->ntextures*sizeof(TPLDescHeader));
109 if(deschead) {
110 fread(deschead,sizeof(TPLDescHeader),tdf->ntextures,f);
112 for(c=0;c<tdf->ntextures;c++) {
113 imghead = deschead[c].imghead;
114 palhead = deschead[c].palhead;
116 //now read in the image data.
117 fseek(f,(s32)imghead,SEEK_SET);
118 imghead = malloc(sizeof(TPLImgHeader));
119 if(!imghead) goto error_open;
121 fread(imghead,sizeof(TPLImgHeader),1,f);
122 deschead[c].imghead = imghead;
124 if(palhead) {
125 fseek(f,(s32)palhead,SEEK_SET);
127 palhead = malloc(sizeof(TPLPalHeader));
128 if(!palhead) goto error_open;
130 fread(palhead,sizeof(TPLPalHeader),1,f);
131 deschead[c].palhead = palhead;
134 tdf->texdesc = deschead;
136 return 1;
139 error_open:
140 if(deschead) free(deschead);
141 if(palhead) free(palhead);
143 fclose(f);
144 return 0;
147 s32 TPL_OpenTPLFromMemory(TPLFile* tdf, const void *memory,u32 len)
149 u32 c;
150 u32 version,pos;
151 const char *p = memory;
152 TPLDescHeader *deschead = NULL;
153 TPLImgHeader *imghead = NULL;
154 TPLPalHeader *palhead = NULL;
156 if(!memory || !len) return -1; //TPL_ERR_INVALID
158 tdf->type = TPL_FILE_TYPE_MEM;
159 tdf->tpl_file = (FHANDLE)NULL;
161 version = *(u32*)(p + TPL_HDR_VERSION_FIELD);
162 tdf->ntextures = *(u32*)(p + TPL_HDR_NTEXTURE_FIELD);
164 deschead = (TPLDescHeader*)(p + TPL_HDR_DESCR_FIELD);
165 for(c=0;c<tdf->ntextures;c++) {
166 imghead = NULL;
167 palhead = NULL;
169 pos = (u32)deschead[c].imghead;
170 imghead = (TPLImgHeader*)(p + pos);
172 pos = (u32)imghead->data;
173 imghead->data = (char*)(p + pos);
175 pos = (u32)deschead[c].palhead;
176 if(pos) {
177 palhead = (TPLPalHeader*)(p + pos);
179 pos = (u32)palhead->data;
180 palhead->data = (char*)(p + pos);
182 deschead[c].imghead = imghead;
183 deschead[c].palhead = palhead;
185 tdf->texdesc = deschead;
187 return 1;
190 s32 TPL_GetTextureInfo(TPLFile *tdf,s32 id,u32 *fmt,u16 *width,u16 *height)
192 TPLDescHeader *deschead = NULL;
193 TPLImgHeader *imghead = NULL;
195 if(!tdf) return -1;
196 if(id<0 || id>=tdf->ntextures) return -1;
198 deschead = (TPLDescHeader*)tdf->texdesc;
199 if(!deschead) return -1;
201 imghead = deschead[id].imghead;
202 if(!imghead) return -1;
204 if(fmt) *fmt = imghead->fmt;
205 if(width) *width = imghead->width;
206 if(height) *height = imghead->height;
208 return 0;
211 s32 TPL_GetTexture(TPLFile *tdf,s32 id,GXTexObj *texObj)
213 s32 pos;
214 u32 size;
215 FILE *f = NULL;
216 TPLDescHeader *deschead = NULL;
217 TPLImgHeader *imghead = NULL;
218 s32 bMipMap = 0;
219 u8 biasclamp = GX_DISABLE;
221 if(!tdf) return -1;
222 if(!texObj) return -1;
223 if(id<0 || id>=tdf->ntextures) return -1;
225 deschead = (TPLDescHeader*)tdf->texdesc;
226 if(!deschead) return -1;
228 imghead = deschead[id].imghead;
229 if(!imghead) return -1;
231 size = TPL_GetTextureSize(imghead->width,imghead->height,imghead->fmt);
232 if(tdf->type==TPL_FILE_TYPE_DISC) {
233 f = (FILE*)tdf->tpl_file;
234 pos = (s32)imghead->data;
235 imghead->data = memalign(PPC_CACHE_ALIGNMENT,size);
236 if(!imghead->data) return -1;
238 fseek(f,pos,SEEK_SET);
239 fread(imghead->data,1,size,f);
242 if(imghead->maxlod>0) bMipMap = 1;
243 if(imghead->lodbias>0.0f) biasclamp = GX_ENABLE;
245 DCFlushRange(imghead->data,size);
246 GX_InitTexObj(texObj,imghead->data,imghead->width,imghead->height,imghead->fmt,imghead->wraps,imghead->wrapt,bMipMap);
247 if(bMipMap) GX_InitTexObjLOD(texObj,imghead->minfilter,imghead->magfilter,imghead->minlod,imghead->maxlod,
248 imghead->lodbias,biasclamp,biasclamp,imghead->edgelod);
250 return 0;
253 s32 TPL_GetTextureCI(TPLFile *tdf,s32 id,GXTexObj *texObj,GXTlutObj *tlutObj,u8 tluts)
255 s32 pos;
256 u32 size;
257 FILE *f = NULL;
258 TPLDescHeader *deschead = NULL;
259 TPLImgHeader *imghead = NULL;
260 TPLPalHeader *palhead = NULL;
261 s32 bMipMap = 0;
262 u8 biasclamp = GX_DISABLE;
264 if(!tdf) return -1;
265 if(!texObj) return -1;
266 if(!tlutObj) return -1;
267 if(id<0 || id>=tdf->ntextures) return -1;
269 deschead = (TPLDescHeader*)tdf->texdesc;
270 if(!deschead) return -1;
272 imghead = deschead[id].imghead;
273 if(!imghead) return -1;
275 palhead = deschead[id].palhead;
276 if(!palhead) return -1;
278 size = TPL_GetTextureSize(imghead->width,imghead->height,imghead->fmt);
279 if(tdf->type==TPL_FILE_TYPE_DISC) {
280 f = (FILE*)tdf->tpl_file;
281 pos = (s32)imghead->data;
282 imghead->data = memalign(PPC_CACHE_ALIGNMENT,size);
283 if(!imghead->data) return -1;
285 fseek(f,pos,SEEK_SET);
286 fread(imghead->data,1,size,f);
288 pos = (s32)palhead->data;
289 palhead->data = memalign(PPC_CACHE_ALIGNMENT,(palhead->nitems*sizeof(u16)));
290 if(!palhead->data) {
291 free(imghead->data);
292 return -1;
295 fseek(f,pos,SEEK_SET);
296 fread(palhead->data,1,(palhead->nitems*sizeof(u16)),f);
299 if(imghead->maxlod>0) bMipMap = 1;
300 if(imghead->lodbias>0.0f) biasclamp = GX_ENABLE;
302 DCFlushRange(imghead->data,size);
303 DCFlushRange(palhead->data,(palhead->nitems*sizeof(u16)));
304 GX_InitTlutObj(tlutObj,palhead->data,palhead->fmt,palhead->nitems);
305 GX_InitTexObjCI(texObj,imghead->data,imghead->width,imghead->height,imghead->fmt,imghead->wraps,imghead->wrapt,bMipMap,tluts);
306 if(bMipMap) GX_InitTexObjLOD(texObj,imghead->minfilter,imghead->magfilter,imghead->minlod,imghead->maxlod,
307 imghead->lodbias,biasclamp,biasclamp,imghead->edgelod);
309 return 0;
312 void TPL_CloseTPLFile(TPLFile *tdf)
314 int i;
315 FILE *f;
316 TPLPalHeader *palhead;
317 TPLImgHeader *imghead;
318 TPLDescHeader *deschead;
320 if(!tdf) return;
322 if(tdf->type==TPL_FILE_TYPE_DISC) {
323 f = (FILE*)tdf->tpl_file;
324 if(f) fclose(f);
326 deschead = (TPLDescHeader*)tdf->texdesc;
327 if(!deschead) return;
329 for(i=0;i<tdf->ntextures;i++) {
330 imghead = deschead[i].imghead;
331 palhead = deschead[i].palhead;
332 if(imghead) {
333 if(imghead->data) free(imghead->data);
334 free(imghead);
336 if(palhead) {
337 if(palhead->data) free(palhead->data);
338 free(palhead);
341 free(tdf->texdesc);
344 tdf->ntextures = 0;
345 tdf->texdesc = NULL;
346 tdf->tpl_file = NULL;