00001 #include "flGlobal.h"
00002 #if FL_TEXTURE_PCX != 0
00003 #include <stdlib.h>
00004 #include <string.h>
00005 #include <pspgu.h>
00006
00007 #if FL_INCLUDE_ALL_C == 0
00008 #include "flTexturePCX.h"
00009 #include "flMemory.h"
00010 #include "flFile.h"
00011
00012 #if FL_DEBUG != 0
00013 #include "flDebug.h"
00014 #endif
00015
00016 #endif
00017
00018 typedef struct {
00019 char manufacturer;
00020 char version;
00021 char encoding;
00022 char bpp;
00023 short xMin;
00024 short yMin;
00025 short xMax;
00026 short yMax;
00027 short horizontalDPI;
00028 short verticalDPI;
00029 char palette[48];
00030 char reserved;
00031 char colorPlanes;
00032 short bytesPerLine;
00033 short paletteType;
00034 short hScrSize;
00035 short vScrSize;
00036 char filler[54];
00037 } pcxFileHeader;
00038
00039 Texture* texLoadPCX(char* inPath) {
00040 #if FL_FILE != 0
00041 File* tempFile = fileOpen(inPath, FILE_MODE_READ | FILE_MODE_BINARY);
00042 #else
00043 FILE* tempFile = fopen(inPath, "rb");
00044 #endif
00045 if(!tempFile) {
00046 #if FL_DEBUG_ERROR != 0
00047 debugError("PCX load error (%s).\nFile cannot be opened", inPath);
00048 #endif
00049 return NULL;
00050 }
00051 pcxFileHeader tempHeader;
00052
00053 fileRead(&tempHeader.manufacturer, 1, tempFile);
00054 fileRead(&tempHeader.version, 1, tempFile);
00055 if((tempHeader.version != 0) && (tempHeader.version != 2) && (tempHeader.version != 5)) {
00056 #if FL_DEBUG_ERROR != 0
00057 debugError("PCX file error (%s).\nVersion not supported (%i).\nSupported versions are 0, 2 & 5.", inPath, tempHeader.version);
00058 #endif
00059 fileClose(tempFile);
00060 return NULL;
00061 }
00062 fileRead(&tempHeader.encoding, 1, tempFile);
00063 fileRead(&tempHeader.bpp, 1, tempFile);
00064 if((tempHeader.bpp != 1) && (tempHeader.bpp != 4) && (tempHeader.bpp != 8) && (tempHeader.bpp != 24)) {
00065 #if FL_DEBUG_ERROR != 0
00066 debugError("PCX file error (%s).\nBPP not supported (%i).\nSupported BPPs are 1, 4, 8 & 24.", inPath, tempHeader.bpp);
00067 #endif
00068 fileClose(tempFile);
00069 return NULL;
00070 }
00071
00072 fileRead(&tempHeader.xMin, 2, tempFile);
00073 fileRead(&tempHeader.yMin, 2, tempFile);
00074 fileRead(&tempHeader.xMax, 2, tempFile);
00075 fileRead(&tempHeader.yMax, 2, tempFile);
00076 fileRead(&tempHeader.horizontalDPI, 2, tempFile);
00077 fileRead(&tempHeader.verticalDPI, 2, tempFile);
00078 fileRead(&tempHeader.palette[0], 48, tempFile);
00079 fileRead(&tempHeader.reserved, 1, tempFile);
00080 fileRead(&tempHeader.colorPlanes, 1, tempFile);
00081
00082
00083 fileRead(&tempHeader.bytesPerLine, 2, tempFile);
00084 fileRead(&tempHeader.paletteType, 2, tempFile);
00085 fileRead(&tempHeader.hScrSize, 2, tempFile);
00086 fileRead(&tempHeader.vScrSize, 2, tempFile);
00087 fileRead(&tempHeader.filler[0], 54, tempFile);
00088
00089 int tempWidth = (tempHeader.xMax - tempHeader.xMin);
00090 int tempHeight = (tempHeader.yMax - tempHeader.yMin);
00091 if(tempWidth <= 0)
00092 tempWidth = 0 - tempWidth;
00093 if(tempHeight <= 0)
00094 tempHeight = 0 - tempHeight;
00095 tempHeight++;
00096 tempWidth++;
00097
00098 u8* tempData = (u8*)memQalloc(tempHeader.bytesPerLine * tempHeader.colorPlanes * tempHeight);
00099 if(!tempData) {
00100 #if FL_DEBUG_ERROR != 0
00101 debugError("PCX load error (%s).\nOut of memory.", inPath);
00102 #endif
00103 fileClose(tempFile);
00104 return NULL;
00105 }
00106 u8 tempChar;
00107 u32 tempX = 0;
00108 u32 tempLine;
00109 u32 tempPlane;
00110 u8 tempCount;
00111 u32 i;
00112 if(tempHeader.encoding == 1) {
00113 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00114 for(tempPlane = 0; tempPlane < tempHeader.colorPlanes; tempPlane++) {
00115 tempX = 0;
00116 while(tempX < tempHeader.bytesPerLine) {
00117 fileRead(&tempChar, 1, tempFile);
00118 if((tempChar & 0xC0) == 0xC0) {
00119 tempCount = (tempChar & 0x3F);
00120 fileRead(&tempChar, 1, tempFile);
00121 } else
00122 tempCount = 1;
00123 for(i = 0; i < tempCount; i++)
00124 tempData[(((tempLine * tempHeader.colorPlanes) + tempPlane) * tempHeader.bytesPerLine) + tempX + i] = tempChar;
00125 tempX += tempCount;
00126 }
00127 }
00128 }
00129 } else if(tempHeader.encoding == 0) {
00130 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00131 for(tempPlane = 0; tempPlane < tempHeader.colorPlanes; tempPlane++)
00132 fileRead(&tempData[((tempLine * tempHeader.colorPlanes) + tempPlane) * tempHeader.bytesPerLine], tempHeader.bytesPerLine, tempFile);
00133 }
00134 } else {
00135 #if FL_DEBUG_ERROR != 0
00136 debugError("PCX load error (%s).\nEncoding type %i not supported.", inPath, tempHeader.encoding);
00137 #endif
00138 fileClose(tempFile);
00139 return NULL;
00140 }
00141
00142 char* tempPalette = tempHeader.palette;
00143 char tempBigPalette[768];
00144 if((tempHeader.bpp == 8) && (tempHeader.colorPlanes == 1)) {
00145 fileSeek(tempFile, -769, FILE_SEEK_END);
00146 fileRead(&tempChar, 1, tempFile);
00147 if(tempChar == 12) {
00148 fileRead(&tempBigPalette[0], 768, tempFile);
00149 tempPalette = tempBigPalette;
00150 }
00151 }
00152 fileClose(tempFile);
00153
00154
00155 u8 tempPixelFormat = GU_PSM_8888;
00156 u8 tempRealBPP = (tempHeader.colorPlanes * tempHeader.bpp);
00157 if(tempRealBPP <= 4) {
00158 tempPixelFormat = GU_PSM_T4;
00159 } else if(tempRealBPP == 8) {
00160 tempPixelFormat = GU_PSM_T8;
00161 }
00162 Texture* tempOut = texCreate(tempWidth, tempHeight, tempPixelFormat);
00163 if(!tempOut) {
00164 #if FL_DEBUG_ERROR != 0
00165 debugError("PCX load error (%s).\nCouldn't create texture struct.", inPath);
00166 #endif
00167 return NULL;
00168 }
00169 #if FL_TEXTURE_PRESERVENONALPHA != 0
00170 tempOut->texAlpha = false;
00171 #endif
00172
00173
00174 if(texPalettized(tempOut)) {
00175 tempOut->texPalette = palCreate((tempPixelFormat == GU_PSM_T4 ? 16 : 256) , GU_PSM_8888, false);
00176 for(i = 0; i < (1 << tempHeader.bpp); i++) {
00177 tempOut->texPalette->palData[i << 2] = tempPalette[i * 3];
00178 tempOut->texPalette->palData[(i << 2) + 1] = tempPalette[(i * 3) + 1];
00179 tempOut->texPalette->palData[(i << 2) + 2] = tempPalette[(i * 3) + 2];
00180 tempOut->texPalette->palData[(i << 2) + 3] = 0xFF;
00181 }
00182 }
00183
00184 if(tempHeader.colorPlanes <= 1) {
00185 if(tempHeader.bpp == 1) {
00186 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00187 for(tempX = 0; tempX < ((tempWidth + 7) >> 3); tempX++) {
00188 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 2)] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x80) >> 3) + ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x40) >> 6);
00189 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 2) + 1] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x20) >> 1) + ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x10) >> 4);
00190 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 2) + 2] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x08) << 1) + ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x04) >> 2);
00191 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 2) + 3] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x02) << 3) + (tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x01);
00192 }
00193 }
00194 } else if(tempHeader.bpp == 2) {
00195 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00196 for(tempX = 0; tempX < ((tempWidth + 3) >> 2); tempX++) {
00197 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 1)] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0xC0) >> 2) + ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x30) >> 4);
00198 tempOut->texData[(tempLine * tempOut->texDataWidth) + (tempX << 1) + 1] = ((tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x0C) << 2) + (tempData[(tempLine * tempHeader.bytesPerLine) + tempX] & 0x03);
00199 }
00200 }
00201 } else if(tempHeader.bpp == 4) {
00202 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00203 for(tempX = 0; tempX < ((tempWidth + 1) >> 1); tempX++) {
00204 tempOut->texData[(tempLine * tempOut->texDataWidth) + tempX] = tempData[(tempLine * tempHeader.bytesPerLine) + tempX];
00205 }
00206 }
00207 } else if(tempHeader.bpp == 8) {
00208 if(tempPalette == tempHeader.palette) {
00209 #if FL_DEBUG_ERROR != 0
00210 debugError("PCX load error (%s).\n256 color image doesn't contain a palette.", inPath);
00211 #endif
00212 memFree(tempData);
00213 texFree(tempOut);
00214 return NULL;
00215 }
00216 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00217 for(tempX = 0; tempX < tempWidth; tempX++) {
00218 tempOut->texData[(tempLine * tempOut->texDataWidth) + tempX] = tempData[(tempLine * tempHeader.bytesPerLine) + tempX];
00219 }
00220 }
00221 } else {
00222 #if FL_DEBUG_ERROR != 0
00223 debugError("PCX load error (%s).\nUnsupported BPP(%i)/ColorPlane(%i) combo.", inPath, tempHeader.bpp, tempHeader.colorPlanes);
00224 #endif
00225 memFree(tempData);
00226 texFree(tempOut);
00227 return NULL;
00228 }
00229 } else if(tempHeader.colorPlanes == 3) {
00230 if(tempHeader.bpp == 8) {
00231 for(tempLine = 0; tempLine < tempHeight; tempLine++) {
00232 for(tempX = 0; tempX < tempWidth; tempX++) {
00233 tempOut->texData[((tempLine * 3) * (tempOut->texDataWidth << 2)) + (tempX << 2)] = tempData[((tempLine * 3) * tempHeader.bytesPerLine) + tempX];
00234 tempOut->texData[((tempLine * 3) * (tempOut->texDataWidth << 2)) + (tempX << 2) + 1] = tempData[(((tempLine * 3) + 1) * tempHeader.bytesPerLine) + tempX];
00235 tempOut->texData[((tempLine * 3) * (tempOut->texDataWidth << 2)) + (tempX << 2) + 2] = tempData[(((tempLine * 3) + 2) * tempHeader.bytesPerLine) + tempX];
00236 tempOut->texData[((tempLine * 3) * (tempOut->texDataWidth << 2)) + (tempX << 2) + 3] = 0xFF;
00237 }
00238 }
00239 } else {
00240 #if FL_DEBUG_ERROR != 0
00241 debugError("PCX load error (%s).\nUnsupported BPP(%i)/ColorPlane(%i) combo.", inPath, tempHeader.bpp, tempHeader.colorPlanes);
00242 #endif
00243 memFree(tempData);
00244 texFree(tempOut);
00245 return NULL;
00246 }
00247 } else {
00248 #if FL_DEBUG_ERROR != 0
00249 debugError("PCX load error (%s).\nUnsupported BPP(%i)/ColorPlane(%i) combo.", inPath, tempHeader.bpp, tempHeader.colorPlanes);
00250 #endif
00251 memFree(tempData);
00252 texFree(tempOut);
00253 return NULL;
00254 }
00255
00256 memFree(tempData);
00257 return tempOut;
00258 }
00259
00260 bool texSavePCX(Texture* inTex, char* inPath) {
00261 #if FL_DEBUG_WARNING != 0
00262 debugWarning("PCX saving not yet implemented.");
00263 #endif
00264 return false;
00265 }
00266
00267 #endif