00001 #include "flGlobal.h"
00002 #if FL_TEXTURE != 0
00003 #include <string.h>
00004 #include <stdio.h>
00005 #include <pspgu.h>
00006 #include <pspkernel.h>
00007
00008 #if FL_INCLUDE_ALL_C == 0
00009 #include "flTexture.h"
00010 #include "flMemory.h"
00011 #include "flColor.h"
00012 #include "flMath.h"
00013 #include "flString.h"
00014
00015 #if FL_DEBUG != 0
00016 #include "flDebug.h"
00017 #endif
00018
00019 #if FL_GRAPHICS != 0
00020 #include "flGraphics.h"
00021 #endif
00022
00023 #if FL_TEXTURE_PCX != 0
00024 #include "flTexturePCX.h"
00025 #endif
00026 #if FL_TEXTURE_TGA != 0
00027 #include "flTextureTGA.h"
00028 #endif
00029 #if FL_TEXTURE_BMP != 0
00030 #include "flTextureBMP.h"
00031 #endif
00032 #if FL_TEXTURE_WAL != 0
00033 #include "flTextureWAL.h"
00034 #endif
00035 #if FL_TEXTURE_FTF != 0
00036 #include "flTextureFTF.h"
00037 #endif
00038 #if FL_TEXTURE_RAW != 0
00039 #include "flTextureRAW.h"
00040 #endif
00041 #endif
00042
00043
00044
00045
00046
00047 typedef struct {
00048 char texNodePath[244];
00049 Texture* texNodeData;
00050 void* texNodeNext[2];
00051 } texTreeNode;
00052
00053 bool texTreeAdd(char* inPath, Texture* inTex);
00054 Texture* texTreeFindTexByPath(char* inPath);
00055 texTreeNode* texTreeFindNodeByTexR(Texture* inTex, texTreeNode* inNode);
00056 char* texTreeFindPathByTex(Texture* inTex);
00057 texTreeNode* texTreeFindNodeByTex(Texture* inTex);
00058 void texTreeAddR(texTreeNode* inNode);
00059 void texTreeDelR(texTreeNode* inNode);
00060 bool texTreeDelNodeByTex(Texture* inTex);
00061
00062 texTreeNode* texTree = NULL;
00063
00064
00065
00066
00067 #if FL_TEXTURE_ERRORTEX != 0
00068 #if FL_TEXTURE_ERRORTEX_COMPILE != 0
00069 #include "flTexError.c"
00070 #endif
00071 Texture* texError = NULL;
00072 #endif
00073
00074 void* texBound = NULL;
00075 void* palBound = NULL;
00076
00077 Palette* palGrayscaleT8Ptr = NULL;
00078 Palette* palGrayscaleT4Ptr = NULL;
00079 Palette* palDefaultColorT4Ptr = NULL;
00080
00081 static int getNextPower2(int inNum) {
00082 int tempOut = inNum;
00083 int tempBits;
00084 for(tempBits = 0; tempOut != 0; tempBits++)
00085 tempOut >>= 1;
00086 tempOut = 1 << tempBits;
00087 if(tempOut == (inNum << 1))
00088 tempOut = inNum;
00089 return tempOut;
00090 }
00091
00092 static inline int getPaletteSize(int inEntries) {
00093 while(inEntries & 7)
00094 inEntries++;
00095 return inEntries;
00096 }
00097
00098 #if FL_GRAPHICS != 0
00099 inline u8 texBPP(Texture* inTex) {
00100 switch(inTex->texPixelFormat) {
00101 case GU_PSM_8888:
00102 case GU_PSM_T32:
00103 return 32;
00104 case GU_PSM_4444:
00105 case GU_PSM_5650:
00106 case GU_PSM_5551:
00107 case GU_PSM_T16:
00108 return 16;
00109 case GU_PSM_DXT3:
00110 case GU_PSM_DXT5:
00111 case GU_PSM_T8:
00112 return 8;
00113 case GU_PSM_DXT1:
00114 case GU_PSM_T4:
00115 return 4;
00116 }
00117 return 0;
00118 }
00119 #endif
00120
00121 inline u8 texPalettized(Texture* inTex) {
00122 return (inTex->texPixelFormat & 4);
00123 }
00124
00125 inline u8 palBPP(Palette* inPal) {
00126 #if FL_GRAPHICS != 0
00127 if(inPal->palPixelFormat > GU_PSM_8888) {
00128 #if FL_DEBUG_WARNING != 0
00129 debugWarning("Warning, erroneous palette BPP %u.", (unsigned int)inPal->palPixelFormat);
00130 #endif
00131 return 0;
00132 }
00133 return graphicsPixelFormatBPP(inPal->palPixelFormat);
00134 #else
00135 switch(inPal->palPixelFormat) {
00136 case GU_PSM_8888:
00137 return 32;
00138 case GU_PSM_4444:
00139 case GU_PSM_5650:
00140 case GU_PSM_5551:
00141 return 16;
00142 case GU_PSM_T32:
00143 case GU_PSM_T16:
00144 case GU_PSM_DXT3:
00145 case GU_PSM_DXT5:
00146 case GU_PSM_T8:
00147 case GU_PSM_DXT1:
00148 case GU_PSM_T4:
00149 #if FL_DEBUG_WARNING != 0
00150 debugWarning("Warning, erroneous palette BPP %u.", (unsigned int)inPath->palPixelFormat);
00151 #endif
00152 return 0;
00153 }
00154 return 0;
00155 #endif
00156 }
00157
00158 inline void palBind(Palette* inPalette) {
00159 if(palBound && (inPalette == palBound))
00160 return;
00161
00162 sceGuClutMode(inPalette->palPixelFormat, 0, 0xFF, 0);
00163 sceGuClutLoad((inPalette->palEntries >> 3), inPalette->palData);
00164
00165 palBound = inPalette->palData;
00166 }
00167
00168 void texInit() {
00169 #if FL_TEXTURE_ERRORTEX != 0
00170 #if FL_TEXTURE_ERRORTEX_COMPILE != 0
00171 texError = &texErrorStruct;
00172 #else
00173 texError = texLoad(FL_TEXTURE_ERRORTEX_PATH);
00174 #endif
00175 #endif
00176 }
00177
00178 Texture* texLoad(char* inPath) {
00179 if(!inPath || (inPath[0] == 0)) {
00180 #if FL_DEBUG_WARNING != 0
00181 debugWarning("Invalid texture file path \"%s\".", inPath);
00182 #endif
00183 return NULL;
00184 }
00185
00186 inPath = filePathValidate(inPath);
00187
00188 Texture* tempOut = texTreeFindTexByPath(inPath);
00189 if(tempOut) {
00190 tempOut->texUseCount++;
00191 return tempOut;
00192 }
00193
00194 char* tempExt = fileExtension(inPath);
00195 if(!tempExt || !tempExt[0]) {
00196 #if FL_DEBUG_WARNING != 0
00197 debugWarning("Cannot determine file extension for texture \"%s\".", inPath);
00198 #endif
00199 return NULL;
00200 }
00201 strLCase((u8*)tempExt);
00202
00203 if((strcmp(tempExt, "pcx") == 0) || (strcmp(tempExt, "pcc") == 0)){
00204 #if FL_TEXTURE_PCX != 0
00205 tempOut = texLoadPCX(inPath);
00206 #else
00207 #if FL_DEBUG_ERROR != 0
00208 debugError("PCX textures not supported in this build.");
00209 #endif
00210 #endif
00211 } else if((strcmp(tempExt, "tga") == 0) || (strcmp(tempExt, "tpic") == 0)) {
00212 #if FL_TEXTURE_TGA != 0
00213 tempOut = texLoadTGA(inPath);
00214 #else
00215 #if FL_DEBUG_ERROR != 0
00216 debugError("TGA textures not supported in this build.");
00217 #endif
00218 #endif
00219 } else if((strcmp(tempExt, "bmp") == 0) || (strcmp(tempExt, "dib") == 0)){
00220 #if FL_TEXTURE_BMP != 0
00221 tempOut = texLoadBMP(inPath);
00222 #else
00223 #if FL_DEBUG_ERROR != 0
00224 debugError("BMP textures not supported in this build.");
00225 #endif
00226 #endif
00227 } else if(strcmp(tempExt, "wal") == 0) {
00228 #if FL_TEXTURE_WAL != 0
00229 tempOut = texLoadWAL(inPath);
00230 #else
00231 #if FL_DEBUG_ERROR != 0
00232 debugError("WAL textures not supported in this build.");
00233 #endif
00234 #endif
00235 } else if(strcmp(tempExt, "ftf") == 0) {
00236 #if FL_TEXTURE_FTF != 0
00237 tempOut = texLoadFTF(inPath);
00238 #else
00239 #if FL_DEBUG_ERROR != 0
00240 debugError("FTF textures not supported in this build.");
00241 #endif
00242 #endif
00243 } else {
00244 #if FL_DEBUG_WARNING != 0
00245 debugWarning("Texture format \"%s\" not supported.", tempExt);
00246 #endif
00247 }
00248
00249 memFree(tempExt);
00250
00251 if(!tempOut)
00252 return NULL;
00253
00254 #if FL_TEXTURE_AUTOMIPMAP != 0
00255 #if FL_TEXTURE_AUTOMIPMAP_PALETTED == 0
00256 if(!texPalettized(tempOut)) {
00257 #endif
00258 texMipMap(tempOut, FL_TEXTURE_AUTOMIPMAP);
00259 #if FL_TEXTURE_AUTOMIPMAP_PALETTED == 0
00260 }
00261 #endif
00262 #endif
00263
00264 #if FL_TEXTURE_AUTOSWIZZLE != 0
00265 texSwizzle(tempOut);
00266 #endif
00267
00268 #if ((FL_TEXTURE_AUTOMIPMAP == 0) && (FL_TEXTURE_AUTOSWIZZLE == 0))
00269 if(memIsCachedPointer(tempOut->texData)) {
00270 if(texDataSize(tempOut) >= 16384)
00271 sceKernelDcacheWritebackInvalidateAll();
00272 else
00273 sceKernelDcacheWritebackInvalidateRange(tempOut->texData, texDataSize(tempOut));
00274 }
00275 #endif
00276
00277 texTreeAdd(inPath, tempOut);
00278
00279 return tempOut;
00280 }
00281
00282 bool texSave(Texture* inTex, char* inPath) {
00283 if(!inTex) {
00284 #if FL_DEBUG_WARNING != 0
00285 debugWarning("Trying to save a NULL texture.");
00286 #endif
00287 return false;
00288 }
00289 if(!inPath || (inPath[0] == 0)) {
00290 #if FL_DEBUG_WARNING != 0
00291 debugWarning("Invalid texture save file path \"%s\".", inPath);
00292 #endif
00293 return false;
00294 }
00295
00296 inPath = filePathValidate(inPath);
00297
00298 char* tempExt = fileExtension(inPath);
00299 if(!tempExt || !tempExt[0]) {
00300 #if FL_DEBUG_WARNING != 0
00301 debugWarning("Cannot determine file extension for texture \"%s\".", inPath);
00302 #endif
00303 return false;
00304 }
00305 strLCase((u8*)tempExt);
00306
00307 if((strcmp(tempExt, "pcx") == 0) || (strcmp(tempExt, "pcc") == 0)){
00308 #if FL_TEXTURE_PCX != 0
00309 return texSavePCX(inTex, inPath);
00310 #else
00311 #if FL_DEBUG_ERROR != 0
00312 debugError("PCX textures not supported in this build.");
00313 #endif
00314 return false;
00315 #endif
00316 } else if((strcmp(tempExt, "tga") == 0) || (strcmp(tempExt, "tpic") == 0)) {
00317 #if FL_TEXTURE_TGA != 0
00318 return texSaveTGA(inTex, inPath);
00319 #else
00320 #if FL_DEBUG_ERROR != 0
00321 debugError("TGA textures not supported in this build.");
00322 #endif
00323 return false;
00324 #endif
00325 } else if((strcmp(tempExt, "bmp") == 0) || (strcmp(tempExt, "dib") == 0)){
00326 #if FL_TEXTURE_BMP != 0
00327 return texSaveBMP(inTex, inPath);
00328 #else
00329 #if FL_DEBUG_ERROR != 0
00330 debugError("BMP textures not supported in this build.");
00331 #endif
00332 return false;
00333 #endif
00334 } else if(strcmp(tempExt, "wal") == 0) {
00335 #if FL_TEXTURE_WAL != 0
00336 return texSaveWAL(inTex, inPath);
00337 #else
00338 #if FL_DEBUG_ERROR != 0
00339 debugError("WAL textures not supported in this build.");
00340 #endif
00341 return false;
00342 #endif
00343 } else if(strcmp(tempExt, "ftf") == 0) {
00344 #if FL_TEXTURE_FTF != 0
00345 return texSaveFTF(inTex, inPath);
00346 #else
00347 #if FL_DEBUG_ERROR != 0
00348 debugError("FTF textures not supported in this build.");
00349 #endif
00350 return false;
00351 #endif
00352 } else if(strcmp(tempExt, "raw") == 0) {
00353 #if FL_TEXTURE_FTF != 0
00354 return texSaveRAW(inTex, inPath);
00355 #else
00356 #if FL_DEBUG_ERROR != 0
00357 debugError("RAW textures not supported in this build.");
00358 #endif
00359 return false;
00360 #endif
00361 }
00362
00363 #if FL_DEBUG_WARNING != 0
00364 debugWarning("Texture format \"%s\"not supported.", tempExt);
00365 #endif
00366
00367 memFree(tempExt);
00368
00369 return false;
00370 }
00371
00372 char* texPath(Texture* inTex) {
00373 return texTreeFindPathByTex(inTex);
00374 }
00375
00376 Texture* texCreate(u32 inWidth, u32 inHeight, u8 inPixelFormat) {
00377 Texture* tempOut = (Texture*)memAlloc(sizeof(Texture));
00378 if(!tempOut) {
00379 #if FL_DEBUG_ERROR != 0
00380 debugError("Couldn't create texture struct.\nOut of memory.");
00381 #endif
00382 return NULL;
00383 }
00384 tempOut->texWidth = inWidth;
00385 tempOut->texHeight = inHeight;
00386 tempOut->texPixelFormat = inPixelFormat;
00387 tempOut->texDataWidth = getNextPower2(inWidth);
00388 tempOut->texDataHeight = getNextPower2(inHeight);
00389 tempOut->texStride = tempOut->texDataWidth;
00390 tempOut->texUseCount = 1;
00391 tempOut->texSwizzled = false;
00392 tempOut->texMipMaps = 0;
00393 #if FL_TEXTURE_PRESERVENONALPHA != 0
00394 tempOut->texAlpha = true;
00395 #endif
00396
00397 #if FL_TEXTURE_UNCACHED != 0
00398 tempOut->texData = (char*)memAllocUncached(texDataSize(tempOut));
00399 #else
00400 tempOut->texData = (char*)memAlign(16, texDataSize(tempOut));
00401 #endif
00402
00403 if(!tempOut->texData) {
00404 #if FL_DEBUG_ERROR != 0
00405 debugError("Couldn't create texture(%ux%u:%i).\nOut of memory.", (unsigned int)tempOut->texDataWidth, (unsigned int)tempOut->texDataHeight, texBPP(tempOut));
00406 #endif
00407 memFree(tempOut);
00408 return NULL;
00409 }
00410 #if (FL_TEXTURE_UNCACHED != 0) && (FL_MEMORY == 0)
00411 tempOut->texData = (char*)((unsigned int)tempOut->texData | 0x40000000);
00412 sceKernelDcacheWritebackAll();
00413 #endif
00414 tempOut->texPalette = NULL;
00415 memClear(tempOut->texMipData, 8);
00416
00417 if(tempOut->texDataWidth != inWidth) {
00418 u32 j;
00419 for(j = 0; j < inHeight; j++)
00420 memClear(&tempOut->texData[(((j * tempOut->texDataWidth) + inWidth) * texBPP(tempOut)) >> 3], ((tempOut->texDataWidth - inWidth) * texBPP(tempOut)) >> 3);
00421 }
00422 if(tempOut->texDataHeight != inHeight)
00423 memClear(&tempOut->texData[((inHeight * tempOut->texDataWidth) * texBPP(tempOut)) >> 3], ((tempOut->texDataWidth * (tempOut->texDataHeight - inHeight) * texBPP(tempOut)) >> 3));
00424
00425 return tempOut;
00426 }
00427
00428 Texture* texCreateBlank(u32 inWidth, u32 inHeight, u8 inPixelFormat) {
00429 Texture* tempOut = texCreate(inWidth, inHeight, inPixelFormat);
00430 if(!tempOut)
00431 return NULL;
00432
00433 memClear(tempOut->texData, ((tempOut->texDataHeight * tempOut->texDataWidth * texBPP(tempOut)) >> 3));
00434
00435 return tempOut;
00436 }
00437
00438 #if FL_GRAPHICS != 0
00439 bool texSwizzle(Texture* inTex) {
00440 if(inTex->texSwizzled) {
00441 #if FL_DEBUG_WARNING != 0
00442 debugWarning("Trying to swizzle a swizzled texture.");
00443 #endif
00444 return false;
00445 }
00446
00447 if(!graphicsSwizzleData((u8*)inTex->texData, inTex->texDataWidth, inTex->texHeight, inTex->texPixelFormat)) {
00448 #if FL_DEBUG_WARNING != 0
00449 debugWarning("Error swizzling texture.");
00450 #endif
00451 return false;
00452 }
00453
00454 if(inTex->texMipMaps) {
00455 u8 i;
00456 for(i = 0; i < inTex->texMipMaps; i++) {
00457 if(!inTex->texMipData[i] || !(inTex->texDataWidth >> (i + 1)) || (((inTex->texDataWidth * texBPP(inTex)) >> (i + 4)) & 15) || ((inTex->texDataHeight >> (i + 1)) & 7))
00458 break;
00459 if(!graphicsSwizzleData((u8*)inTex->texMipData[i], (inTex->texDataWidth >> (i + 1)), (inTex->texDataHeight >> (i + 1)), inTex->texPixelFormat)) {
00460 #if FL_DEBUG_WARNING != 0
00461 debugWarning("Error swizzling texture mipmap %i.", i);
00462 #endif
00463 break;
00464 }
00465 }
00466 }
00467
00468 inTex->texSwizzled = true;
00469 return true;
00470 }
00471
00472 bool texUnswizzle(Texture* inTex) {
00473 if(!inTex->texSwizzled) {
00474 #if FL_DEBUG_WARNING != 0
00475 debugWarning("Trying to unswizzle an unswizzled texture.");
00476 #endif
00477 return false;
00478 }
00479
00480 if(!graphicsUnswizzleData((u8*)inTex->texData, inTex->texDataWidth, inTex->texHeight, inTex->texPixelFormat)) {
00481 #if FL_DEBUG_WARNING != 0
00482 debugWarning("Error unswizzling texture.");
00483 #endif
00484 return false;
00485 }
00486
00487 if(inTex->texMipMaps) {
00488 u8 i;
00489 for(i = 1; i <= inTex->texMipMaps; i++) {
00490 if(!inTex->texMipData[i] || !(inTex->texDataWidth >> (i + 1)) || (((inTex->texDataWidth * texBPP(inTex)) >> (i + 4)) & 15) || ((inTex->texDataHeight >> (i + 1)) & 7))
00491 break;
00492 if(!graphicsUnswizzleData((u8*)inTex->texMipData[i - 1], (inTex->texDataWidth >> i), (inTex->texDataHeight >> i), inTex->texPixelFormat)) {
00493 #if FL_DEBUG_WARNING != 0
00494 debugWarning("Error unswizzling texture mipmap %i.", i);
00495 #endif
00496 return false;
00497 }
00498 }
00499 }
00500
00501 inTex->texSwizzled = false;
00502 return true;
00503 }
00504 #endif
00505
00506 void texBind(Texture* inTex) {
00507 if((!inTex) || (!inTex->texData)) {
00508 #if FL_DEBUG_WARNING != 0
00509 debugWarning("Trying to bind a NULL texture or a texture with NULL data.");
00510 #endif
00511 #if FL_TEXTURE_ERRORTEX != 0
00512 inTex = texError;
00513 #else
00514 return;
00515 #endif
00516 } else if(texPalettized(inTex) && (inTex->texPalette == NULL)) {
00517 #if FL_DEBUG_WARNING != 0
00518 debugWarning("Trying to bind a palettized texture without a palette.");
00519 #endif
00520 #if FL_TEXTURE_ERRORTEX != 0
00521 inTex = texError;
00522 #else
00523 return;
00524 #endif
00525 }
00526
00527 if(texPalettized(inTex))
00528 palBind(inTex->texPalette);
00529
00530 if(texBound && (texBound == inTex->texData))
00531 return;
00532
00533 sceGuTexMode(inTex->texPixelFormat, inTex->texMipMaps, 0, inTex->texSwizzled);
00534 sceGuTexImage(0, inTex->texDataWidth, inTex->texDataHeight, inTex->texStride, (void*)inTex->texData);
00535 if(inTex->texMipMaps) {
00536 u8 i;
00537 for(i = 1; i <= inTex->texMipMaps; i++)
00538 sceGuTexImage(i, (inTex->texDataWidth >> i), (inTex->texDataHeight >> i), (inTex->texStride >> i), (void*)inTex->texMipData[i - 1]);
00539 }
00540
00541 sceGuTexWrap(GU_REPEAT, GU_REPEAT);
00542
00543 texBound = inTex->texData;
00544 }
00545
00546 void texFree(void* inTex) {
00547 Texture* tempTex = (Texture*)inTex;
00548
00549 tempTex->texUseCount--;
00550 if(tempTex->texUseCount)
00551 return;
00552
00553 #if FL_MEMORY
00554 if(tempTex) {
00555 if(tempTex->texData == texBound)
00556 texBound = NULL;
00557 memFree(tempTex->texData);
00558 if(tempTex->texMipMaps) {
00559 u8 i;
00560 for(i = 1; i <= tempTex->texMipMaps; i++)
00561 memFree(tempTex->texMipData[i - 1]);
00562 }
00563 if(tempTex->texPalette && !tempTex->texPalette->palGlobal)
00564 palFree(tempTex->texPalette);
00565 memFree(tempTex);
00566 }
00567 #else
00568 if(tempTex) {
00569 if(tempTex->texData) {
00570 free(tempTex->texData);
00571 if(tempTex->texData == texBound)
00572 texBound = NULL;
00573 }
00574 if(tempTex->texMipMaps) {
00575 u8 i;
00576 for(i = 1; i <= tempTex->texMipMaps; i++) {
00577 if(inTex->texMipData[i - 1])
00578 memFree(tempTex->texMipData[i - 1]);
00579 }
00580 }
00581 if(tempTex->texPalette && !tempTex->texPalette->palGlobal)
00582 palFree(tempTex->texPalette);
00583 free(tempTex);
00584 }
00585 #endif
00586
00587 texTreeDelNodeByTex(tempTex);
00588 }
00589
00590 int texMipMap(Texture* inTex, u8 inLevel) {
00591 if(!inLevel)
00592 return 0;
00593 if(!inTex) {
00594 #if FL_DEBUG_WARNING != 0
00595 debugWarning("Trying to mipmap NULL texture.");
00596 #endif
00597 return -1;
00598 }
00599
00600 inLevel = min(inLevel, 8);
00601 while(!(inTex->texDataWidth >> inLevel) || !(inTex->texDataHeight >> inLevel))
00602 inLevel--;
00603
00604 while(inTex->texMipMaps < inLevel) {
00605 if(!texMipMapAdd(inTex))
00606 break;
00607 }
00608 return inTex->texMipMaps;
00609 }
00610
00611 bool texMipMapAdd(Texture* inTex) {
00612 if(!inTex) {
00613 #if FL_DEBUG_WARNING != 0
00614 debugWarning("Trying to mipmap NULL texture.");
00615 #endif
00616 return false;
00617 }
00618 if(inTex->texMipMaps >= 8) {
00619 #if FL_DEBUG_WARNING != 0
00620 debugWarning("Trying to mipmap a fully mipmapped texture.");
00621 #endif
00622 return false;
00623 }
00624 #if FL_COLOR == 0
00625 if(texPalettized(inTex) {
00626 #if FL_DEBUG_DEVWARNING != 0
00627 debugDevWarning("Mipmapping of paletted textures requires FL_COLOR.");
00628 #endif
00629 return false;
00630 }
00631 #endif
00632
00633 bool tempSwizzle = false;
00634 if(inTex->texSwizzled) {
00635 #if FL_DEBUG_DEVWARNING != 0
00636 debugDevWarning("Mip-mapping swizzled textures requires them to be unswizzled, mip-mapped, then swizzled again.");
00637 #endif
00638 tempSwizzle = true;
00639 texUnswizzle(inTex);
00640 }
00641
00642
00643 u8 tempLevel = (inTex->texMipMaps + 1);
00644 u32 tempWidth = inTex->texDataWidth >> tempLevel;
00645 u32 tempHeight = inTex->texDataHeight >> tempLevel;
00646 if(!tempWidth || !tempHeight) {
00647 #if FL_DEBUG_WARNING != 0
00648 debugWarning("Trying to create mipmap smaller than a pixel.");
00649 #endif
00650 return false;
00651 }
00652 u32 tempDataSize = ((inTex->texDataWidth * inTex->texDataHeight * texBPP(inTex)) >> (3 + (tempLevel << 1)));
00653
00654 u8* tempMipMap = NULL;
00655 u8* tempLastMip;
00656 if(tempLevel == 1)
00657 tempLastMip = (u8*)inTex->texData;
00658 else
00659 tempLastMip = (u8*)inTex->texMipData[tempLevel - 2];
00660
00661 bool tempVMem = false;
00662 #if FL_MEMORY_VMEM != 0
00663 tempVMem = vmemPointer(inTex->texData);
00664 if(tempVMem)
00665 tempMipMap = vmemAlloc(tempDataSize);
00666 tempVMem = (tempMipMap != NULL);
00667 #endif
00668 if(!tempVMem)
00669 tempMipMap = memAlign(16, tempDataSize);
00670 if(!tempMipMap) {
00671 #if FL_DEBUG_WARNING != 0
00672 debugWarning("Couldn't allocate mip-map, probably out of memory.");
00673 #endif
00674 return false;
00675 }
00676
00677 int i, j;
00678 if(inTex->texPixelFormat == GU_PSM_8888) {
00679 u32* tempMipMap32 = (u32*)tempMipMap;
00680 u32* tempLastMip32 = (u32*)tempLastMip;
00681 u32 tempMerge32[4];
00682 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00683 for(i = 0; i < tempWidth; i++) {
00684 tempMerge32[0] = tempLastMip32[(((j << 1) + 0) * (tempWidth << 1)) + ((i << 1) + 0)];
00685 tempMerge32[1] = tempLastMip32[(((j << 1) + 0) * (tempWidth << 1)) + ((i << 1) + 1)];
00686 tempMerge32[2] = tempLastMip32[(((j << 1) + 1) * (tempWidth << 1)) + ((i << 1) + 0)];
00687 tempMerge32[3] = tempLastMip32[(((j << 1) + 1) * (tempWidth << 1)) + ((i << 1) + 1)];
00688 tempMipMap32[(j * tempWidth) + i] = color8888_Merge4(tempMerge32[0], tempMerge32[1], tempMerge32[2], tempMerge32[3]);
00689 }
00690 }
00691 } else if(inTex->texPixelFormat < GU_PSM_8888) {
00692 u16* tempMipMap16 = (u16*)tempMipMap;
00693 u16* tempLastMip16 = (u16*)tempLastMip;
00694 u16 tempMerge16[4];
00695 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00696 for(i = 0; i < tempWidth; i++) {
00697 tempMerge16[0] = tempLastMip16[(((j << 1) + 0) * (tempWidth << 1)) + ((i << 1) + 0)];
00698 tempMerge16[1] = tempLastMip16[(((j << 1) + 0) * (tempWidth << 1)) + ((i << 1) + 1)];
00699 tempMerge16[2] = tempLastMip16[(((j << 1) + 1) * (tempWidth << 1)) + ((i << 1) + 0)];
00700 tempMerge16[3] = tempLastMip16[(((j << 1) + 1) * (tempWidth << 1)) + ((i << 1) + 1)];
00701 if(inTex->texPixelFormat == GU_PSM_4444)
00702 tempMipMap16[(j * tempWidth) + i] = color4444_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]);
00703 else if(inTex->texPixelFormat == GU_PSM_5551)
00704 tempMipMap16[(j * tempWidth) + i] = color5551_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]);
00705 else if(inTex->texPixelFormat == GU_PSM_5650)
00706 tempMipMap16[(j * tempWidth) + i] = color5650_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]);
00707 }
00708 }
00709 #if FL_COLOR != 0
00710 } else if(inTex->texPixelFormat == GU_PSM_T8) {
00711 int k, l;
00712 tempLastMip = (u8*)inTex->texData;
00713 if(inTex->texPalette->palPixelFormat == GU_PSM_8888) {
00714 u32* tempPalEntries32 = (u32*)inTex->texPalette->palData;
00715 u32 tempMerge32[(1 << tempLevel) * (1 << tempLevel)];
00716 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00717 for(i = 0; i < tempWidth; i++) {
00718 for(k = 0; k < (1 << tempLevel); k++) {
00719 for(l = 0; l < (1 << tempLevel); l++) {
00720 tempMerge32[(k * (1 << tempLevel)) + l] = tempPalEntries32[tempLastMip[(((j << tempLevel) + k) * inTex->texWidth) + ((i << tempLevel) + l)]];
00721 }
00722 }
00723 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, colorMergeN8888(tempMerge32, ((1 << tempLevel) * (1 << tempLevel))));
00724 }
00725 }
00726 } else {
00727 u16* tempPalEntries16 = (u16*)inTex->texPalette->palData;
00728 u16 tempMerge16[(1 << tempLevel) * (1 << tempLevel)];
00729 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00730 for(i = 0; i < tempWidth; i++) {
00731 for(k = 0; k < (1 << tempLevel); k++) {
00732 for(l = 0; l < (1 << tempLevel); l++) {
00733 tempMerge16[(k * (1 << tempLevel)) + l] = tempPalEntries16[tempLastMip[(((j << tempLevel) + k) * inTex->texWidth) + ((i << tempLevel) + l)]];
00734 }
00735 }
00736 if(inTex->texPalette->palPixelFormat == GU_PSM_4444)
00737 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, colorMergeN4444(tempMerge16, ((1 << tempLevel) * (1 << tempLevel))));
00738 else if(inTex->texPalette->palPixelFormat == GU_PSM_5551)
00739 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, colorMergeN5551(tempMerge16, ((1 << tempLevel) * (1 << tempLevel))));
00740 else if(inTex->texPalette->palPixelFormat == GU_PSM_5650)
00741 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, colorMergeN5650(tempMerge16, ((1 << tempLevel) * (1 << tempLevel))));
00742 }
00743 }
00744 }
00745 } else if(inTex->texPixelFormat == GU_PSM_T4) {
00746 memClear(tempMipMap, tempDataSize);
00747 if(inTex->texPalette->palPixelFormat == GU_PSM_8888) {
00748 u32* tempPalEntries32 = (u32*)inTex->texPalette->palData;
00749 u32 tempMerge32[4];
00750 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00751 for(i = 0; i < tempWidth; i++) {
00752 tempMerge32[0] = tempPalEntries32[tempLastMip[(((j << 1) + 0) * tempWidth) + i] & 0x0F];
00753 tempMerge32[1] = tempPalEntries32[(tempLastMip[(((j << 1) + 0) * tempWidth) + i] & 0xF0) >> 4];
00754 tempMerge32[2] = tempPalEntries32[tempLastMip[(((j << 1) + 1) * tempWidth) + i] & 0x0F];
00755 tempMerge32[3] = tempPalEntries32[(tempLastMip[(((j << 1) + 1) * tempWidth) + i] & 0xF0) >> 4];
00756 if(i & 1) {
00757 tempMipMap[(j * tempWidth) + i] += (palClosestColor(inTex->texPalette, color8888_Merge4(tempMerge32[0], tempMerge32[1], tempMerge32[2], tempMerge32[3])) << 4);
00758 } else {
00759 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, color8888_Merge4(tempMerge32[0], tempMerge32[1], tempMerge32[2], tempMerge32[3]));
00760 }
00761 }
00762 }
00763 } else {
00764 u16* tempPalEntries16 = (u16*)inTex->texPalette->palData;
00765 u16 tempMerge16[4];
00766 for(j = 0; j < (inTex->texDataHeight >> tempLevel); j++) {
00767 for(i = 0; i < tempWidth; i++) {
00768 tempMerge16[0] = tempPalEntries16[tempLastMip[(((j << 1) + 0) * tempWidth) + i] & 0x0F];
00769 tempMerge16[1] = tempPalEntries16[(tempLastMip[(((j << 1) + 0) * tempWidth) + i] & 0xF0) >> 4];
00770 tempMerge16[2] = tempPalEntries16[tempLastMip[(((j << 1) + 1) * tempWidth) + i] & 0x0F];
00771 tempMerge16[3] = tempPalEntries16[(tempLastMip[(((j << 1) + 1) * tempWidth) + i] & 0xF0) >> 4];
00772 if(inTex->texPalette->palPixelFormat == GU_PSM_4444)
00773 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, color4444_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]));
00774 else if(inTex->texPalette->palPixelFormat == GU_PSM_5551)
00775 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, color5551_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]));
00776 else if(inTex->texPalette->palPixelFormat == GU_PSM_5650)
00777 tempMipMap[(j * tempWidth) + i] = palClosestColor(inTex->texPalette, color5650_Merge4(tempMerge16[0], tempMerge16[1], tempMerge16[2], tempMerge16[3]));
00778 }
00779 }
00780 }
00781 #endif
00782 } else {
00783 #if FL_DEBUG_WARNING != 0
00784 debugWarning("Can't mipmap textures with palettes of over 8 bits, or DXT compressed.");
00785 #endif
00786 return false;
00787 }
00788
00789 inTex->texMipMaps = tempLevel;
00790 inTex->texMipData[tempLevel - 1] = (char*)tempMipMap;
00791
00792 if(tempSwizzle)
00793 texSwizzle(inTex);
00794
00795 if(memIsCachedPtr(tempMipMap)) {
00796 if(tempDataSize > 16384)
00797 sceKernelDcacheWritebackAll();
00798 else
00799 sceKernelDcacheWritebackRange(tempMipMap, tempDataSize);
00800 }
00801
00802 return true;
00803 }
00804
00805 Palette* palCreate(u32 inEntries, u8 inFormat, bool inGlobal) {
00806 if(inFormat > GU_PSM_8888) {
00807 #if FL_DEBUG_ERROR != 0
00808 debugError("Trying to create a palette with incorrect format.\nDXT and palettized palettes are not supported.");
00809 #endif
00810 return NULL;
00811 }
00812 if(inEntries > 256) {
00813 #if FL_DEBUG_ERROR != 0
00814 debugError("Trying to create a palette with %u entries (Max: 256).", (unsigned int)inEntries);
00815 #endif
00816 return NULL;
00817 }
00818 #if FL_DEBUG_DEVWARNING != 0
00819 if(!inEntries)
00820 debugDevWarning("Creating palette with 0 entries.");
00821 #endif
00822 Palette* tempOut = (Palette*)memAlloc(sizeof(Palette));
00823 if(!tempOut) {
00824 #if FL_DEBUG_ERROR != 0
00825 debugError("Couldn't create palette structure.\nOut of memory.");
00826 #endif
00827 return NULL;
00828 }
00829 tempOut->palEntries = getPaletteSize(inEntries);
00830 tempOut->palPixelFormat = inFormat;
00831 tempOut->palGlobal = inGlobal;
00832 #if FL_MEMORY != 0
00833 #if FL_TEXTURE_UNCACHED != 0
00834 tempOut->palData = (char*)memAllocUncached((tempOut->palEntries * palBPP(tempOut)) >> 3);
00835 #else
00836 tempOut->palData = (char*)memAlign(16, ((tempOut->palEntries * palBPP(tempOut)) >> 3));
00837 #endif
00838 #else
00839 tempOut->palData = (char*)memalign(16, ((tempOut->palEntries * palBPP(tempOut)) >> 3));
00840 #endif
00841 if(!tempOut->palData) {
00842 #if FL_DEBUG_ERROR != 0
00843 debugError("Couldn't create palette data.\nOut of memory");
00844 #endif
00845 memFree(tempOut);
00846 return NULL;
00847 }
00848 #if (FL_TEXTURE_UNCACHED != 0) && (FL_MEMORY == 0)
00849 tempOut->palData = (char*)((unsigned int)tempOut->palData | 0x40000000);
00850 sceKernelDcacheWritebackAll();
00851 #endif
00852 if(tempOut->palEntries > inEntries)
00853 memClear(&tempOut->palData[(inEntries * palBPP(tempOut)) >> 3], (((tempOut->palEntries - inEntries) * palBPP(tempOut)) >> 3));
00854 #if FL_TEXTURE_UNCACHED == 0
00855 sceKernelDcacheWritebackAll();
00856 #endif
00857 return tempOut;
00858 }
00859
00860 void palFree(Palette* inPalette) {
00861 #if FL_MEMORY != 0
00862 memFree(inPalette->palData);
00863 memFree(inPalette);
00864 #else
00865 if(!inPalette)
00866 return;
00867 if(inPalette->palData)
00868 free(inPalette->palData);
00869 free(inPalette);
00870 #endif
00871 if(inPalette == palBound)
00872 palBound = NULL;
00873 }
00874
00875 s32 palClosestColor(Palette* inPal, u32 inColor) {
00876 if(!inPal) {
00877 #if FL_DEBUG_WARNING != 0
00878 debugWarning("Trying to find closest entry in NULL palette.");
00879 #endif
00880 return -1;
00881 }
00882 if(inPal->palPixelFormat > GU_PSM_8888) {
00883 #if FL_DEBUG_WARNING != 0
00884 debugWarning("Trying to find closest entry in invalid palette.");
00885 #endif
00886 return -2;
00887 }
00888 if(!inPal->palEntries) {
00889 #if FL_DEBUG_WARNING != 0
00890 debugWarning("Trying to find closest entry in palette with 0 entries.");
00891 #endif
00892 return -3;
00893 }
00894 u8 tempByPP = 4;
00895 if(inPal->palPixelFormat != GU_PSM_8888) {
00896 inColor &= 0x0000FFFF;
00897 tempByPP = 2;
00898 }
00899 int i, tempCmp;
00900 int tempClosest = 0;
00901 int tempDiff = (1 << 30);
00902 u32* tempColor32 = (u32*)inPal->palData;
00903 u16* tempColor16 = (u16*)inPal->palData;
00904 if(inPal->palPixelFormat == GU_PSM_8888) {
00905 for(i = 0; i < inPal->palEntries; i++) {
00906 if(tempColor32[i] == inColor) {
00907 return i;
00908 } else {
00909 tempCmp = color8888_Cmp(inColor, tempColor32[i]);
00910 if(tempCmp < tempDiff) {
00911 tempClosest = i;
00912 tempDiff = tempCmp;
00913 }
00914 }
00915 }
00916 } else if(inPal->palPixelFormat == GU_PSM_4444) {
00917 for(i = 0; i < inPal->palEntries; i++) {
00918 if(tempColor16[i] == inColor) {
00919 return i;
00920 } else {
00921 tempCmp = color4444_Cmp(inColor, tempColor16[i]);
00922 if(tempCmp < tempDiff) {
00923 tempClosest = i;
00924 tempDiff = tempCmp;
00925 }
00926 }
00927 }
00928 } else if(inPal->palPixelFormat == GU_PSM_5551) {
00929 for(i = 0; i < inPal->palEntries; i++) {
00930 if(tempColor16[i] == inColor) {
00931 return i;
00932 } else {
00933 tempCmp = color5551_Cmp(inColor, tempColor16[i]);
00934 if(tempCmp < tempDiff) {
00935 tempClosest = i;
00936 tempDiff = tempCmp;
00937 }
00938 }
00939 }
00940 } else if(inPal->palPixelFormat == GU_PSM_5650) {
00941 for(i = 0; i < inPal->palEntries; i++) {
00942 if(tempColor16[i] == inColor) {
00943 return i;
00944 } else {
00945 tempCmp = color5650_Cmp(inColor, tempColor16[i]);
00946 if(tempCmp < tempDiff) {
00947 tempClosest = i;
00948 tempDiff = tempCmp;
00949 }
00950 }
00951 }
00952 }
00953 return tempClosest;
00954 }
00955
00956 Palette* palCreateGrayscaleT8() {
00957 Palette* tempOut = palCreate(256, GU_PSM_8888, false);
00958 u8* tempData = (u8*)tempOut->palData;
00959 int i;
00960 for(i = 0; i < 256; i++) {
00961 tempData[i << 2] = i;
00962 tempData[(i << 2) + 1] = i;
00963 tempData[(i << 2) + 2] = i;
00964 tempData[(i << 2) + 3] = 0xFF;
00965 }
00966 #if FL_TEXTURE_UNCACHED == 0
00967 sceKernelDcacheWritebackInvalidateAll();
00968 #endif
00969 return tempOut;
00970 }
00971
00972 Palette* palCreateGrayscaleT4() {
00973 Palette* tempOut = palCreate(16, GU_PSM_8888, false);
00974 u8* tempData = (u8*)tempOut->palData;
00975 int i;
00976 for(i = 0; i < 16; i++) {
00977 tempData[i << 2] = ((i * 0xFF) / 15);
00978 tempData[(i << 2) + 1] = ((i * 0xFF) / 15);
00979 tempData[(i << 2) + 2] = ((i * 0xFF) / 15);
00980 tempData[(i << 2) + 3] = 0xFF;
00981 }
00982 #if FL_TEXTURE_UNCACHED == 0
00983 sceKernelDcacheWritebackInvalidateAll();
00984 #endif
00985 return tempOut;
00986 }
00987
00988 Palette* palCreateMonoT4(u32 inForeColor, u32 inBackColor) {
00989 Palette* tempOut = palCreate(16, GU_PSM_8888, false);
00990 u8* tempData = (u8*)tempOut->palData;
00991 int i;
00992 for(i = 0; i < 16; i++) {
00993 tempData[i << 2] = (((i * (inForeColor & 0x000000FF)) + ((15 - i) * (inBackColor & 0x000000FF))) / 15);
00994 tempData[(i << 2) + 1] = (((i * ((inForeColor & 0x0000FF00) >> 8)) + ((15 - i) * ((inBackColor & 0x0000FF00) >> 8))) / 15);
00995 tempData[(i << 2) + 2] = (((i * ((inForeColor & 0x00FF0000) >> 16)) + ((15 - i) * ((inBackColor & 0x00FF0000) >> 16))) / 15);
00996 tempData[(i << 2) + 3] = (((i * ((inForeColor & 0xFF000000) >> 24)) + ((15 - i) * ((inBackColor & 0xFF000000) >> 24))) / 15);
00997 }
00998 #if FL_TEXTURE_UNCACHED == 0
00999 sceKernelDcacheWritebackInvalidateAll();
01000 #endif
01001 return tempOut;
01002 }
01003
01004 Palette* palCreateDefaultColorT4() {
01005 Palette* tempOut = palCreate(16, GU_PSM_8888, false);
01006 u32* tempPalData = (u32*)tempOut->palData;
01007 tempPalData[0] = 0xFF000000;
01008 tempPalData[1] = 0xFF7F7F7F;
01009 tempPalData[2] = 0xFFCFCFCF;
01010 tempPalData[3] = 0xFFFFFFFF;
01011 tempPalData[4] = 0xFF00007F;
01012 tempPalData[5] = 0xFF0000FF;
01013 tempPalData[6] = 0xFF007F7F;
01014 tempPalData[7] = 0xFF00FFFF;
01015 tempPalData[8] = 0xFF007F00;
01016 tempPalData[9] = 0xFF00FF00;
01017 tempPalData[10] = 0xFF7F7F00;
01018 tempPalData[11] = 0xFFFFFF00;
01019 tempPalData[12] = 0xFF7F0000;
01020 tempPalData[13] = 0xFFFF0000;
01021 tempPalData[14] = 0xFF7F007F;
01022 tempPalData[15] = 0xFFFF00FF;
01023 #if FL_TEXTURE_UNCACHED == 0
01024 sceKernelDcacheWritebackInvalidateAll();
01025 #endif
01026 return tempOut;
01027 }
01028
01029 Palette* palGrayscaleT8() {
01030 if(!palGrayscaleT8Ptr) {
01031 palGrayscaleT8Ptr = palCreateGrayscaleT8();
01032 palGrayscaleT8Ptr->palGlobal = true;
01033 }
01034 return palGrayscaleT8Ptr;
01035 }
01036
01037 Palette* palGrayscaleT4() {
01038 if(!palGrayscaleT4Ptr) {
01039 palGrayscaleT4Ptr = palCreateGrayscaleT4();
01040 palGrayscaleT4Ptr->palGlobal = true;
01041 }
01042 return palGrayscaleT4Ptr;
01043 }
01044
01045 Palette* palDefaultColorT4() {
01046 if(!palDefaultColorT4Ptr) {
01047 palDefaultColorT4Ptr = palCreateDefaultColorT4();
01048 palDefaultColorT4Ptr->palGlobal = true;
01049 }
01050 return palDefaultColorT4Ptr;
01051 }
01052
01053 #if FL_GRAPHICS != 0
01054 Texture* texScreenshot() {
01055 Texture* tempOut = texCreate(SCREEN_WIDTH, SCREEN_HEIGHT, GU_PSM_8888);
01056 if(!tempOut) {
01057 #if FL_DEBUG_ERROR != 0
01058 debugError("Error creating screenshot.\nMost likely out of memory.");
01059 #endif
01060 return NULL;
01061 }
01062 u32 j;
01063 #if FL_MEMORY != 0
01064 char* tempDispBuffer = (char*)vmemAbsolutePtr(graphicsDispBuffer);
01065 #else
01066 char* tempDispBuffer = (char*)((unsigned int)graphicsDispBuffer | 0x04000000);
01067 #endif
01068 for(j = 0; j < SCREEN_HEIGHT; j++)
01069 memCopy(&tempOut->texData[(j * tempOut->texDataWidth) << 2], &tempDispBuffer[(j * SCREEN_STRIDE) << 2], (SCREEN_WIDTH << 2));
01070 #if FL_TEXTURE_UNCACHED == 0
01071 sceKernelDcacheWritebackInvalidateAll();
01072 #endif
01073 #if FL_TEXTURE_PRESERVENONALPHA != 0
01074 tempOut->texAlpha = false;
01075 #endif
01076 return tempOut;
01077 }
01078 #endif
01079
01080 #if FL_MEMORY_VMEM != 0
01081 bool texMoveVMem(Texture* inTex) {
01082 int tempSize = texDataSize(inTex);
01083 void* tempVPtr = vmemAlloc(tempSize);
01084 if(!tempVPtr) {
01085 #if DEBUG_WARNING != 0
01086 debugWarning("Couldn't move texture to vram\nProbably out of video memory.");
01087 #endif
01088 return false;
01089 }
01090 #if FL_GRAPHICS != 0
01091 if(!graphicsFrame)
01092 sceGuStart(GU_DIRECT, graphicsDisplayList);
01093 sceGuCopyImage(inTex->texPixelFormat, 0, 0, inTex->texDataWidth, inTex->texDataHeight, inTex->texDataWidth, inTex->texData, 0, 0, inTex->texDataWidth, tempVPtr);
01094 #else
01095 memCopy(tempVPtr, inTex->texData, tempSize);
01096 #endif
01097 memFree(inTex->texData);
01098 inTex->texData = tempVPtr;
01099
01100
01101
01102
01103 u8 i;
01104 if(inTex->texMipMaps) {
01105 for(i = 1; i <= inTex->texMipMaps; i++) {
01106 tempSize >>= 2;
01107 tempVPtr = vmemAlloc(tempSize);
01108 if(!tempVPtr) {
01109 #if FL_DEBUG_WARNING
01110 debugWarning("Couldn't copy all mip-maps to vram.");
01111 #endif
01112 return true;
01113 }
01114 #if FL_GRAPHICS != 0
01115 sceGuCopyImage(inTex->texPixelFormat, 0, 0, (inTex->texDataWidth >> i), (inTex->texDataHeight >> i), (inTex->texDataWidth >> i), inTex->texMipData[i - 1], 0, 0, (inTex->texDataWidth >> i), tempVPtr);
01116 #else
01117 memCopy(tempVPtr, inTex->texMipData[i - 1], tempSize);
01118 #endif
01119 memFree(inTex->texMipData[i - 1]);
01120 inTex->texMipData[i - 1] = tempVPtr;
01121 }
01122 }
01123
01124 #if FL_GRAPHICS != 0
01125 if(!graphicsFrame)
01126 sceGuFinish();
01127 #endif
01128
01129 return true;
01130 }
01131
01132 bool palMoveVMem(Palette* inPal) {
01133 if(!inPal) {
01134 #if DEBUG_WARNING != 0
01135 debugWarning("Can't move NULL palette to vmem.");
01136 #endif
01137 return false;
01138 }
01139
01140 void* tempVPtr = vmemAlloc((inPal->palEntries * palBPP(inPal)) >> 3);
01141 if(!tempVPtr) {
01142 #if DEBUG_WARNING != 0
01143 debugWarning("Couldn't move palette to vram\nProbably out of video memory.");
01144 #endif
01145 return false;
01146 }
01147 #if FL_GRAPHICS != 0
01148 if(!graphicsFrame)
01149 sceGuStart(GU_DIRECT, graphicsDisplayList);
01150 sceGuCopyImage(inPal->palPixelFormat, 0, 0, 8, (inPal->palEntries >> 3), 8, inPal->palData, 0, 0, 8, tempVPtr);
01151 if(!graphicsFrame)
01152 sceGuFinish();
01153 #else
01154 memCopy(tempVPtr, inPal->palData, ((inPal->palEntries * palBPP(inPal)) >> 3));
01155 #endif
01156
01157 memFree(inPal->palData);
01158
01159 inPal->palData = tempVPtr;
01160 return true;
01161 }
01162 #endif
01163
01164 u32 texPixel(Texture* inTex, int inX, int inY) {
01165 while(inX < 0)
01166 inX += inTex->texWidth;
01167 while(inX > inTex->texWidth)
01168 inX -= inTex->texWidth;
01169 while(inY < 0)
01170 inY += inTex->texHeight;
01171 while(inY > inTex->texHeight)
01172 inY -= inTex->texHeight;
01173 u32 tempOut = 0;
01174 if(texBPP(inTex) >= 8)
01175 memCopy(&tempOut, &inTex->texData[(((inY * inTex->texDataWidth) + inX) * texBPP(inTex)) >> 3], (texBPP(inTex) >> 3));
01176 else
01177 tempOut= ((inTex->texData[(((inY * inTex->texDataWidth) + inX) * texBPP(inTex)) >> 3] & (0x0F << (inX & 1))) >> (inX & 1));
01178 return tempOut;
01179 }
01180
01181
01182
01183
01184
01185
01186
01187
01188
01189
01190
01191
01192
01193
01194
01195
01196
01197
01198
01199
01200
01201
01202
01203
01204
01205
01206
01207
01208 bool texTreeAdd(char* inPath, Texture* inTex) {
01209 if(!inPath || !inTex || !inPath[0])
01210 return false;
01211 texTreeNode* tempNodeAdd = (texTreeNode*)memAlloc(sizeof(texTreeNode));
01212 if(!tempNodeAdd) {
01213 #if FL_DEBUG_WARNING != 0
01214 debugWarning("Unable to add texture to tree.\nProbably out of memory.");
01215 #endif
01216 return false;
01217 }
01218
01219 strcpy(tempNodeAdd->texNodePath, inPath);
01220 tempNodeAdd->texNodeData = inTex;
01221 tempNodeAdd->texNodeNext[0] = NULL;
01222 tempNodeAdd->texNodeNext[1] = NULL;
01223
01224 if(!texTree) {
01225 texTree = tempNodeAdd;
01226 return true;
01227 }
01228
01229 texTreeNode* tempNode = texTree;
01230 int tempCmp = 0;
01231 while(flRunning) {
01232 tempCmp = strcmp(inPath, tempNode->texNodePath);
01233 if(!tempCmp) {
01234 #if FL_DEBUG_WARNING != 0
01235 debugWarning("Trying to add texture to tree, but texture is already in the tree.");
01236 #endif
01237 return false;
01238 }
01239 tempCmp = (tempCmp > 0 ? 1 : 0);
01240 if(!tempNode->texNodeNext[tempCmp]) {
01241 tempNode->texNodeNext[tempCmp] = tempNodeAdd;
01242 return true;
01243 }
01244 tempNode = tempNode->texNodeNext[tempCmp];
01245 }
01246
01247 return false;
01248 }
01249
01250 Texture* texTreeFindTexByPath(char* inPath) {
01251 if(!inPath || !inPath[0] || !texTree)
01252 return NULL;
01253 texTreeNode* tempNode = texTree;
01254 int tempCmp = 0;
01255 while(flRunning) {
01256 tempCmp = strcmp(inPath, tempNode->texNodePath);
01257 if(!tempCmp)
01258 return tempNode->texNodeData;
01259 tempCmp = (tempCmp > 0 ? 1 : 0);
01260 if(!tempNode->texNodeNext[tempCmp])
01261 return NULL;
01262 tempNode = tempNode->texNodeNext[tempCmp];
01263 }
01264 return NULL;
01265 }
01266
01267 texTreeNode* texTreeFindNodeByTexR(Texture* inTex, texTreeNode* inNode) {
01268 if(!inNode)
01269 return NULL;
01270 if(inTex == inNode->texNodeData)
01271 return inNode;
01272 texTreeNode* tempOut = NULL;
01273 if(inNode->texNodeNext[0]) {
01274 tempOut = texTreeFindNodeByTexR(inTex, inNode->texNodeNext[0]);
01275 if(tempOut)
01276 return tempOut;
01277 }
01278 if(inNode->texNodeNext[1])
01279 tempOut = texTreeFindNodeByTexR(inTex, inNode->texNodeNext[1]);
01280 return tempOut;
01281 }
01282
01283 char* texTreeFindPathByTex(Texture* inTex) {
01284 if(!texTree || !inTex)
01285 return NULL;
01286 return texTreeFindNodeByTexR(inTex, texTree)->texNodePath;
01287 }
01288
01289 texTreeNode* texTreeFindNodeByTex(Texture* inTex) {
01290 if(!texTree || !inTex)
01291 return NULL;
01292 return texTreeFindNodeByTexR(inTex, texTree);
01293 }
01294
01295 void texTreeAddR(texTreeNode* inNode) {
01296 texTreeAdd(inNode->texNodePath, inNode->texNodeData);
01297 if(inNode->texNodeNext[0])
01298 texTreeAddR(inNode->texNodeNext[0]);
01299 if(inNode->texNodeNext[1])
01300 texTreeAddR(inNode->texNodeNext[1]);
01301 }
01302
01303 void texTreeDelR(texTreeNode* inNode) {
01304 if(inNode->texNodeNext[0])
01305 texTreeDelR(inNode->texNodeNext[0]);
01306 if(inNode->texNodeNext[1])
01307 texTreeDelR(inNode->texNodeNext[1]);
01308 free(inNode);
01309 }
01310
01311 bool texTreeDelNodeByTex(Texture* inTex) {
01312 if(!texTree || !inTex)
01313 return false;
01314 texTreeNode* tempNodeDel = texTreeFindNodeByTex(inTex);
01315 if(!tempNodeDel) {
01316 #if FL_DEBUG_WARNING != 0
01317 debugWarning("Trying to delete non-existant texture node from tree.");
01318 #endif
01319 return false;
01320 }
01321 if(tempNodeDel->texNodeNext[0])
01322 texTreeAddR(tempNodeDel->texNodeNext[0]);
01323 if(tempNodeDel->texNodeNext[1])
01324 texTreeAddR(tempNodeDel->texNodeNext[1]);
01325 texTreeDelR(tempNodeDel);
01326
01327 return true;
01328 }
01329
01330 #endif