flTexture.c

Go to the documentation of this file.
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 // Texture tree prototypes
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) { // TODO - Fix mipmapping of clut
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; // Black
01008      tempPalData[1]  = 0xFF7F7F7F; // Med. Gray
01009      tempPalData[2]  = 0xFFCFCFCF; // Lig. Gray
01010      tempPalData[3]  = 0xFFFFFFFF; // White
01011      tempPalData[4]  = 0xFF00007F; // Dark Red
01012      tempPalData[5]  = 0xFF0000FF; // Red
01013      tempPalData[6]  = 0xFF007F7F; // Dark Yellow
01014      tempPalData[7]  = 0xFF00FFFF; // Yellow
01015      tempPalData[8]  = 0xFF007F00; // Dark Green
01016      tempPalData[9]  = 0xFF00FF00; // Green
01017      tempPalData[10] = 0xFF7F7F00; // Dark Turqoise
01018      tempPalData[11] = 0xFFFFFF00; // Turqoise
01019      tempPalData[12] = 0xFF7F0000; // Dark Blue
01020      tempPalData[13] = 0xFFFF0000; // Blue
01021      tempPalData[14] = 0xFF7F007F; // Dark Purple
01022      tempPalData[15] = 0xFFFF00FF; // Purple
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      //if(texPalettized(inTex))
01101      //     palMoveVMem(inTex->texPalette);
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 /*void texAddMagMap(Texture* inTex) {
01182      if(!inTex || !inTex->texData) {
01183           #if FL_DEBUG_WARNING != 0
01184           debugWarning("Trying to magnify a NULL texture or a texture with NULL data.");
01185           #endif
01186           return;
01187      }
01188      if(((inTex->texDataWidth << 1) > 512) || ((inTex->texDataHeight << 1) > 512)) {
01189           #if FL_DEBUG_WARNING != 0
01190           debugWarning("Trying to magnify a texture of dimensions (%ux%u:%u), this would overstep the 512x512 boundry.", (unsigned int)inTex->texWidth, (unsigned int)inTex->texHeight, (unsigned int)texBPP(inTex));
01191           #endif
01192           return;
01193      }
01194      
01195      u32 tempDataSize = (texDataSize(inTex) << 2);
01196      u8* tempData = memAlloc(tempDataSize);
01197      
01198      // TODO
01199 }*/
01200 
01201 
01202 
01203 
01204 
01205 
01206 // Texture tree functions.
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

Generated on Wed Sep 5 19:04:01 2007 for funcLib by  doxygen 1.5.1