UTXEXPORTTABLE *GetUtxExportTable(UTXHEADER *Header) { UTXEXPORTTABLE *ExportTable; ILuint i; // Go to the name table. iseek(Header->ExportOffset, IL_SEEK_SET); // Allocate the name table. ExportTable = (UTXEXPORTTABLE*)ialloc(Header->ExportCount * sizeof(UTXEXPORTTABLE)); if (ExportTable == NULL) return NULL; for (i = 0; i < Header->ExportCount; i++) { ExportTable[i].Class = UtxReadCompactInteger(); ExportTable[i].Super = UtxReadCompactInteger(); ExportTable[i].Group = GetLittleUInt(); ExportTable[i].ObjectName = UtxReadCompactInteger(); ExportTable[i].ObjectFlags = GetLittleUInt(); ExportTable[i].SerialSize = UtxReadCompactInteger(); ExportTable[i].SerialOffset = UtxReadCompactInteger(); ChangeObjectReference(&ExportTable[i].Class, &ExportTable[i].ClassImported); ChangeObjectReference(&ExportTable[i].Super, &ExportTable[i].SuperImported); ChangeObjectReference(&ExportTable[i].Group, &ExportTable[i].GroupImported); } return ExportTable; }
static ILboolean ReadPalette(PSP_CTX *ctx) { ILuint ChunkSize, PalCount, Padding; if (ctx->Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(ctx->io); PalCount = GetLittleUInt(ctx->io); Padding = (ChunkSize - 4 - 4); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); } else { PalCount = GetLittleUInt(ctx->io); } ctx->Pal.PalSize = PalCount * 4; ctx->Pal.PalType = IL_PAL_BGRA32; ctx->Pal.Palette = (ILubyte*)ialloc(ctx->Pal.PalSize); if (ctx->Pal.Palette == NULL) return IL_FALSE; if (SIOread(ctx->io, ctx->Pal.Palette, ctx->Pal.PalSize, 1) != 1) { ifree(ctx->Pal.Palette); return IL_FALSE; } return IL_TRUE; }
ILboolean ReadPalette(ILuint BlockLen) { ILuint ChunkSize, PalCount, Padding; if (Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(); PalCount = GetLittleUInt(); Padding = (ChunkSize - 4 - 4); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } else { PalCount = GetLittleUInt(); } Pal.PalSize = PalCount * 4; Pal.PalType = IL_PAL_BGRA32; Pal.Palette = (ILubyte*)ialloc(Pal.PalSize); if (Pal.Palette == NULL) return IL_FALSE; if (iread(Pal.Palette, Pal.PalSize, 1) != 1) { ifree(Pal.Palette); return IL_FALSE; } return IL_TRUE; }
// Internal function used to get the Lif header from the current file. ILboolean iGetLifHead(LIF_HEAD *Header) { iread(Header->Id, 1, 8); Header->Version = GetLittleUInt(); Header->Flags = GetLittleUInt(); Header->Width = GetLittleUInt(); Header->Height = GetLittleUInt(); Header->PaletteCRC = GetLittleUInt(); Header->ImageCRC = GetLittleUInt(); Header->PalOffset = GetLittleUInt(); Header->TeamEffect0 = GetLittleUInt(); Header->TeamEffect1 = GetLittleUInt(); return IL_TRUE; }
// Internal function to get the header and check it. ILboolean iIsValidMdl(void) { ILuint Id, Version; Id = GetLittleUInt(); Version = GetLittleUInt(); iseek(-8, IL_SEEK_CUR); // Restore to previous position. // 0x54534449 == "IDST" if (Id != 0x54534449 || Version != 10) return IL_FALSE; return IL_TRUE; }
UTXENTRYNAME *GetUtxNameTable(UTXHEADER *Header) { UTXENTRYNAME *NameEntries; ILuint i, NumRead; // Go to the name table. iseek(Header->NameOffset, IL_SEEK_SET); // Allocate the name table. NameEntries = (UTXENTRYNAME*)ialloc(Header->NameCount * sizeof(UTXENTRYNAME)); if (NameEntries == NULL) return NULL; // Read in the name table. for (NumRead = 0; NumRead < Header->NameCount; NumRead++) { NameEntries[NumRead].Name = GetUtxName(Header); if (NameEntries[NumRead].Name == NULL) break; NameEntries[NumRead].Flags = GetLittleUInt(); } // Did not read all of the entries (most likely GetUtxName failed). if (NumRead < Header->NameCount) { // So we have to free all of the memory we allocated here. for (i = 0; i < NumRead; i++) { ifree(NameEntries[NumRead].Name); } ilSetError(IL_INVALID_FILE_HEADER); return NULL; } return NameEntries; }
static ILboolean ParseChunks(PSP_CTX *ctx) { BLOCKHEAD Block; ILuint Pos; do { if (SIOread(ctx->io, &Block, 1, sizeof(Block)) != sizeof(Block)) { iPopError(); // Get rid of the erroneous IL_FILE_READ_ERROR. break; } if (ctx->Header.MajorVersion == 3) { Block.BlockLen = GetLittleUInt(ctx->io); } else { UInt(&Block.BlockLen); } if ( Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00 ) { break; } UShort(&Block.BlockID); UInt(&Block.BlockLen); Pos = SIOtell(ctx->io); switch (Block.BlockID) { case PSP_LAYER_START_BLOCK: if (!ReadLayerBlock(ctx)) return IL_FALSE; break; case PSP_ALPHA_BANK_BLOCK: if (!ReadAlphaBlock(ctx)) return IL_FALSE; break; case PSP_COLOR_BLOCK: if (!ReadPalette(ctx)) return IL_FALSE; break; // Gets done in the next iseek, so this is now commented out. //default: //SIOseek(ctx->io, Block.BlockLen, IL_SEEK_CUR); } // Skip to next block just in case we didn't read the entire block. SIOseek(ctx->io, Pos + Block.BlockLen, IL_SEEK_SET); // @TODO: Do stuff here. } while (1); return IL_TRUE; }
// Internal function to load a raw image ILboolean iLoadRawInternal() { if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } iCurImage->Width = GetLittleUInt(&iCurImage->io); iCurImage->Height = GetLittleUInt(&iCurImage->io); iCurImage->Depth = GetLittleUInt(&iCurImage->io); iCurImage->Bpp = (ILubyte)iCurImage->io.getc(iCurImage->io.handle); if (iCurImage->io.read(iCurImage->io.handle, &iCurImage->Bpc, 1, 1) != 1) return IL_FALSE; if (!ilTexImage(iCurImage->Width, iCurImage->Height, iCurImage->Depth, iCurImage->Bpp, 0, ilGetTypeBpc(iCurImage->Bpc), NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; // Tries to read the correct amount of data if (iCurImage->io.read(iCurImage->io.handle, iCurImage->Data, 1, iCurImage->SizeOfData) < iCurImage->SizeOfData) return IL_FALSE; if (ilIsEnabled(IL_ORIGIN_SET)) { iCurImage->Origin = ilGetInteger(IL_ORIGIN_MODE); } else { iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; } if (iCurImage->Bpp == 1) iCurImage->Format = IL_LUMINANCE; else if (iCurImage->Bpp == 3) iCurImage->Format = IL_RGB; else // 4 iCurImage->Format = IL_RGBA; return ilFixImage(); }
// Internal function used to get the BLP header from the current file. ILboolean iGetBlp2Head(BLP2HEAD *Header) { ILuint i; iread(Header->Sig, 1, 4); Header->Type = GetLittleUInt(); Header->Compression = igetc(); Header->AlphaBits = igetc(); Header->AlphaType = igetc(); Header->HasMips = igetc(); Header->Width = GetLittleUInt(); Header->Height = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipOffsets[i] = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipLengths[i] = GetLittleUInt(); return IL_TRUE; }
ILboolean ParseChunks(PspLoadState* state, ILimage* image) { BLOCKHEAD Block; do { if (image->io.read(&image->io, &Block, 1, sizeof(Block)) != sizeof(Block)) { il2GetError(); // Get rid of the erroneous IL_FILE_READ_ERROR. return IL_TRUE; } if (state->Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(&image->io); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_TRUE; } UShort(&Block.BlockID); UInt(&Block.BlockLen); auto Pos = image->io.tell(&image->io); switch (Block.BlockID) { case PSP_LAYER_START_BLOCK: if (!ReadLayerBlock(state, Block.BlockLen, image)) return IL_FALSE; break; case PSP_ALPHA_BANK_BLOCK: if (!ReadAlphaBlock(state, Block.BlockLen, image)) return IL_FALSE; break; case PSP_COLOR_BLOCK: if (!ReadPalette(state, Block.BlockLen, image)) return IL_FALSE; break; // Gets done in the next iseek, so this is now commented out. //default: //image->io.seek(&image->io, Block.BlockLen, IL_SEEK_CUR); } // Skip to next block just in case we didn't read the entire block. image->io.seek(&image->io, Pos + Block.BlockLen, IL_SEEK_SET); // @TODO: Do stuff here. } while (1); return IL_TRUE; }
ILboolean GetUtxHead(UTXHEADER *Header) { Header->Signature = GetLittleUInt(); Header->Version = GetLittleUShort(); Header->LicenseMode = GetLittleUShort(); Header->Flags = GetLittleUInt(); Header->NameCount = GetLittleUInt(); Header->NameOffset = GetLittleUInt(); Header->ExportCount = GetLittleUInt(); Header->ExportOffset = GetLittleUInt(); Header->ImportCount = GetLittleUInt(); Header->ImportOffset = GetLittleUInt(); return IL_TRUE; }
// Internal function used to load the FTX. ILboolean iLoadFtxInternal(ILimage* image) { ILuint Width, Height, HasAlpha; SIO * io = &image->io; if (image == NULL) { il2SetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } Width = GetLittleUInt(io); Height = GetLittleUInt(io); HasAlpha = GetLittleUInt(io); // Kind of backwards from what I would think... //@TODO: Right now, it appears that all images are in RGBA format. See if I can find specs otherwise // or images that load incorrectly like this. //if (HasAlpha == 0) { // RGBA format if (!il2TexImage(image, Width, Height, 1, 4, IL_RGBA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; //} //else if (HasAlpha == 1) { // RGB format // if (!ilTexImage(Width, Height, 1, 3, IL_RGB, IL_UNSIGNED_BYTE, NULL)) // return IL_FALSE; //} //else { // Unknown format // il2SetError(IL_INVALID_FILE_HEADER); // return IL_FALSE; //} // The origin will always be in the upper left. image->Origin = IL_ORIGIN_UPPER_LEFT; // All we have to do for this format is read the raw, uncompressed data. if (io->read(io, image->Data, 1, image->SizeOfData) != image->SizeOfData) return IL_FALSE; return il2FixImage(image); }
ILboolean ReadPalette(PspLoadState* state, ILuint BlockLen, ILimage* image) { ILuint ChunkSize, PalCount, Padding; if (state->Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(&image->io); PalCount = GetLittleUInt(&image->io); Padding = (ChunkSize - 4 - 4); if (Padding > 0) image->io.seek(&image->io, Padding, IL_SEEK_CUR); } else { PalCount = GetLittleUInt(&image->io); } if (state->Pal.use(PalCount, NULL, IL_PAL_BGRA32)) return IL_FALSE; if (!state->Pal.readFromFile(&image->io)) return IL_FALSE; return IL_TRUE; }
static ILboolean ReadGenAttributes(PSP_CTX *ctx) { BLOCKHEAD AttHead; ILint Padding; ILuint ChunkLen; if (SIOread(ctx->io, &AttHead, sizeof(AttHead), 1) != 1) return IL_FALSE; UShort(&AttHead.BlockID); UInt(&AttHead.BlockLen); if (AttHead.HeadID[0] != 0x7E || AttHead.HeadID[1] != 0x42 || AttHead.HeadID[2] != 0x4B || AttHead.HeadID[3] != 0x00) { iSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (AttHead.BlockID != PSP_IMAGE_BLOCK) { iSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } ChunkLen = GetLittleUInt(ctx->io); if (ctx->Header.MajorVersion != 3) ChunkLen -= 4; if (SIOread(ctx->io, &ctx->AttChunk, IL_MIN(sizeof(ctx->AttChunk), ChunkLen), 1) != 1) return IL_FALSE; // Can have new entries in newer versions of the spec (4.0). Padding = (ILint)(ChunkLen - sizeof(ctx->AttChunk)); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); // @TODO: Anything but 24 not supported yet... if (ctx->AttChunk.BitDepth != 24 && ctx->AttChunk.BitDepth != 8) { iSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // @TODO; Add support for compression... if (ctx->AttChunk.Compression != PSP_COMP_NONE && ctx->AttChunk.Compression != PSP_COMP_RLE) { iSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // @TODO: Check more things in the general attributes chunk here. return IL_TRUE; }
//! Loads an .plt palette file. ILboolean ilLoadPltPal(ILconst_string FileName) { ILHANDLE PltFile; if (!iCheckExtension(FileName, IL_TEXT("plt"))) { ilSetError(IL_INVALID_EXTENSION); return IL_FALSE; } if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } PltFile = iopenr(FileName); if (PltFile == NULL) { ilSetError(IL_COULD_NOT_OPEN_FILE); return IL_FALSE; } if (iCurImage->Pal.Palette && iCurImage->Pal.PalSize > 0 && iCurImage->Pal.PalType != IL_PAL_NONE) { ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = NULL; } iCurImage->Pal.PalSize = GetLittleUInt(); if (iCurImage->Pal.PalSize == 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } iCurImage->Pal.PalType = IL_PAL_RGB24; iCurImage->Pal.Palette = (ILubyte*)ialloc(iCurImage->Pal.PalSize); if (!iCurImage->Pal.Palette) { icloser(PltFile); return IL_FALSE; } if (iread(iCurImage->Pal.Palette, iCurImage->Pal.PalSize, 1) != 1) { ifree(iCurImage->Pal.Palette); iCurImage->Pal.Palette = NULL; icloser(PltFile); return IL_FALSE; } icloser(PltFile); return IL_TRUE; }
ILboolean iGetBlp1Head(BLP1HEAD *Header) { ILuint i; iread(Header->Sig, 1, 4); Header->Compression = GetLittleUInt(); Header->Flags = GetLittleUInt(); Header->Width = GetLittleUInt(); Header->Height = GetLittleUInt(); Header->PictureType = GetLittleUInt(); Header->PictureSubType = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipOffsets[i] = GetLittleUInt(); for (i = 0; i < 16; i++) Header->MipLengths[i] = GetLittleUInt(); return IL_TRUE; }
// Internal function used to get the .bmp header from the current file. ILboolean iGetBmpHead(BMPHEAD * const Header) { Header->bfType = GetLittleUShort(); Header->bfSize = GetLittleInt(); Header->bfReserved = GetLittleUInt(); Header->bfDataOff = GetLittleInt(); Header->biSize = GetLittleInt(); Header->biWidth = GetLittleInt(); Header->biHeight = GetLittleInt(); Header->biPlanes = GetLittleShort(); Header->biBitCount = GetLittleShort(); Header->biCompression = GetLittleInt(); Header->biSizeImage = GetLittleInt(); Header->biXPelsPerMeter = GetLittleInt(); Header->biYPelsPerMeter = GetLittleInt(); Header->biClrUsed = GetLittleInt(); Header->biClrImportant = GetLittleInt(); return IL_TRUE; }
UTXIMPORTTABLE *GetUtxImportTable(UTXHEADER *Header) { UTXIMPORTTABLE *ImportTable; ILuint i; // Go to the name table. iseek(Header->ImportOffset, IL_SEEK_SET); // Allocate the name table. ImportTable = (UTXIMPORTTABLE*)ialloc(Header->ImportCount * sizeof(UTXIMPORTTABLE)); if (ImportTable == NULL) return NULL; for (i = 0; i < Header->ImportCount; i++) { ImportTable[i].ClassPackage = UtxReadCompactInteger(); ImportTable[i].ClassName = UtxReadCompactInteger(); ImportTable[i].Package = GetLittleUInt(); ImportTable[i].ObjectName = UtxReadCompactInteger(); ChangeObjectReference(&ImportTable[i].Package, &ImportTable[i].PackageImported); } return ImportTable; }
ILboolean iLoadBlp1() { BLP1HEAD Header; ILubyte *DataAndAlpha, *Palette; ILuint i; ILimage *Image = iCurImage; ILboolean BaseCreated = IL_FALSE; #ifndef IL_NO_JPG ILubyte *JpegHeader, *JpegData; ILuint JpegHeaderSize; #endif//IL_NO_JPG if (!iGetBlp1Head(&Header)) return IL_FALSE; if (!iCheckBlp1(&Header)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Remove this. i = 0; switch (Header.Compression) { case BLP_TYPE_JPG: #ifdef IL_NO_JPG // We can only do the Jpeg decoding if we do not have IL_NO_JPEG defined. return IL_FALSE; #else JpegHeaderSize = GetLittleUInt(); JpegHeader = (ILubyte*)ialloc(JpegHeaderSize); if (JpegHeader == NULL) return IL_FALSE; // Read the shared Jpeg header. if (iread(JpegHeader, 1, JpegHeaderSize) != JpegHeaderSize) { ifree(JpegHeader); return IL_FALSE; } //for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps //@TODO: Check return value? iseek(Header.MipOffsets[i], IL_SEEK_SET); JpegData = (ILubyte*)ialloc(JpegHeaderSize + Header.MipLengths[i]); if (JpegData == NULL) { ifree(JpegHeader); return IL_FALSE; } memcpy(JpegData, JpegHeader, JpegHeaderSize); if (iread(JpegData + JpegHeaderSize, Header.MipLengths[i], 1) != 1) return IL_FALSE; // Just send the data straight to the Jpeg loader. if (!ilLoadJpegL(JpegData, JpegHeaderSize + Header.MipLengths[i])) return IL_FALSE; // The image data is in BGR(A) order, even though it is Jpeg-compressed. if (Image->Format == IL_RGBA) Image->Format = IL_BGRA; if (Image->Format == IL_RGB) Image->Format = IL_BGR; ifree(JpegData); //} ifree(JpegHeader); #endif//IL_NO_JPG break; case BLP_RAW: switch (Header.PictureType) { // There is no alpha list, so we just read like a normal indexed image. case BLP_RAW_NO_ALPHA: for (i = 0; i < 16; i++) { // Possible maximum of 16 mipmaps if (!BaseCreated) { // Have not created the base image yet, so use ilTexImage. if (!ilTexImage(Header.Width, Header.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; Image = iCurImage; BaseCreated = IL_TRUE; // We have a BGRA palette. Image->Pal.Palette = (ILubyte*)ialloc(256 * 4); if (Image->Pal.Palette == NULL) return IL_FALSE; Image->Pal.PalSize = 1024; Image->Pal.PalType = IL_PAL_BGRA32; // Read in the palette ... if (iread(Image->Pal.Palette, 1, 1024) != 1024) return IL_FALSE; } else { if (Image->Width == 1 && Image->Height == 1) // Already at the smallest mipmap (1x1), so we are done. break; if (Header.MipOffsets[i] == 0 || Header.MipLengths[i] == 0) // No more mipmaps in the file. break; Image->Mipmaps = ilNewImageFull(Image->Width >> 1, Image->Height >> 1, 1, 1, IL_COLOR_INDEX, IL_UNSIGNED_BYTE, NULL); if (Image->Mipmaps == NULL) return IL_FALSE; // Copy the palette from the first image before we change our Image pointer. Image->Mipmaps->Pal.Palette = (ILubyte*)ialloc(256 * 4); if (Image->Mipmaps->Pal.Palette == NULL) return IL_FALSE; Image->Mipmaps->Pal.PalSize = 1024; Image->Mipmaps->Pal.PalType = IL_PAL_BGRA32; memcpy(Image->Mipmaps->Pal.Palette, Image->Pal.Palette, 1024); // Move to the next mipmap in the linked list. Image = Image->Mipmaps; } // The origin should be in the upper left. Image->Origin = IL_ORIGIN_UPPER_LEFT; // Seek to the data and read it. iseek(Header.MipOffsets[i], IL_SEEK_SET); if (iread(Image->Data, 1, Image->SizeOfData) != Image->SizeOfData) return IL_FALSE; } break; // These cases are identical and have an alpha list following the image data. case BLP_RAW_PLUS_ALPHA1: case BLP_RAW_PLUS_ALPHA2: // Create the image. if (!ilTexImage(Header.Width, Header.Height, 1, 4, IL_BGRA, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; DataAndAlpha = (ILubyte*)ialloc(Header.Width * Header.Height); Palette = (ILubyte*)ialloc(256 * 4); if (DataAndAlpha == NULL || Palette == NULL) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Read in the data and the palette. if (iread(Palette, 1, 1024) != 1024) { ifree(Palette); return IL_FALSE; } // Seek to the data and read it. iseek(Header.MipOffsets[i], IL_SEEK_SET); if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Convert the color-indexed data to BGRX. for (i = 0; i < Header.Width * Header.Height; i++) { Image->Data[i*4] = Palette[DataAndAlpha[i]*4]; Image->Data[i*4+1] = Palette[DataAndAlpha[i]*4+1]; Image->Data[i*4+2] = Palette[DataAndAlpha[i]*4+2]; } // Read in the alpha list. if (iread(DataAndAlpha, Header.Width * Header.Height, 1) != 1) { ifree(DataAndAlpha); ifree(Palette); return IL_FALSE; } // Finally put the alpha data into the image data. for (i = 0; i < Header.Width * Header.Height; i++) { Image->Data[i*4+3] = DataAndAlpha[i]; } ifree(DataAndAlpha); ifree(Palette); break; } break; //default: // Should already be checked by iCheckBlp1. } // Set the origin (always upper left). Image->Origin = IL_ORIGIN_UPPER_LEFT; return ilFixImage(); }
ILboolean iLoadMdlInternal() { ILuint Id, Version, NumTex, TexOff, TexDataOff, Position, ImageNum; ILubyte *TempPal; TEX_HEAD TexHead; ILimage *BaseImage=NULL; ILboolean BaseCreated = IL_FALSE; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } Id = GetLittleUInt(); Version = GetLittleUInt(); // 0x54534449 == "IDST" if (Id != 0x54534449 || Version != 10) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Skips the actual model header. iseek(172, IL_SEEK_CUR); NumTex = GetLittleUInt(); TexOff = GetLittleUInt(); TexDataOff = GetLittleUInt(); if (NumTex == 0 || TexOff == 0 || TexDataOff == 0) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } iseek(TexOff, IL_SEEK_SET); for (ImageNum = 0; ImageNum < NumTex; ImageNum++) { if (iread(TexHead.Name, 1, 64) != 64) return IL_FALSE; TexHead.Flags = GetLittleUInt(); TexHead.Width = GetLittleUInt(); TexHead.Height = GetLittleUInt(); TexHead.Offset = GetLittleUInt(); Position = itell(); if (TexHead.Offset == 0) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (!BaseCreated) { ilTexImage(TexHead.Width, TexHead.Height, 1, 1, IL_COLOUR_INDEX, IL_UNSIGNED_BYTE, NULL); iCurImage->Origin = IL_ORIGIN_LOWER_LEFT; BaseCreated = IL_TRUE; BaseImage = iCurImage; //iCurImage->NumNext = NumTex - 1; // Don't count the first image. } else { //iCurImage->Next = ilNewImage(TexHead.Width, TexHead.Height, 1, 1, 1); iCurImage = iCurImage->Next; iCurImage->Format = IL_COLOUR_INDEX; iCurImage->Type = IL_UNSIGNED_BYTE; } TempPal = (ILubyte*)ialloc(768); if (TempPal == NULL) { iCurImage = BaseImage; return IL_FALSE; } iCurImage->Pal.Palette = TempPal; iCurImage->Pal.PalSize = 768; iCurImage->Pal.PalType = IL_PAL_RGB24; iseek(TexHead.Offset, IL_SEEK_SET); if (iread(iCurImage->Data, TexHead.Width * TexHead.Height, 1) != 1) return IL_FALSE; if (iread(iCurImage->Pal.Palette, 1, 768) != 768) return IL_FALSE; if (ilGetBoolean(IL_CONV_PAL) == IL_TRUE) { ilConvertImage(IL_RGB, IL_UNSIGNED_BYTE); } iseek(Position, IL_SEEK_SET); } iCurImage = BaseImage; return ilFixImage(); }
static ILubyte *GetChannel(PSP_CTX *ctx) { BLOCKHEAD Block; CHANNEL_CHUNK Channel; ILubyte *CompData, *Data; ILuint ChunkSize, Padding; if (SIOread(ctx->io, &Block, 1, sizeof(Block)) != sizeof(Block)) return NULL; if (ctx->Header.MajorVersion == 3) { Block.BlockLen = GetLittleUInt(ctx->io); } else { UInt(&Block.BlockLen); } if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { iSetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (Block.BlockID != PSP_CHANNEL_BLOCK) { iSetError(IL_ILLEGAL_FILE_VALUE); return NULL; } if (ctx->Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(ctx->io); if (SIOread(ctx->io, &Channel, sizeof(Channel), 1) != 1) return NULL; Padding = (ChunkSize - 4) - sizeof(Channel); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); } else { if (SIOread(ctx->io, &Channel, sizeof(Channel), 1) != 1) return NULL; } CompData = (ILubyte*)ialloc(Channel.CompLen); Data = (ILubyte*)ialloc(ctx->AttChunk.Width * ctx->AttChunk.Height); if (CompData == NULL || Data == NULL) { ifree(Data); ifree(CompData); return NULL; } if (SIOread(ctx->io, CompData, 1, Channel.CompLen) != Channel.CompLen) { ifree(CompData); ifree(Data); return NULL; } switch (ctx->AttChunk.Compression) { case PSP_COMP_NONE: ifree(Data); return CompData; case PSP_COMP_RLE: if (!UncompRLE(CompData, Data, Channel.CompLen)) { ifree(CompData); ifree(Data); return NULL; } break; default: ifree(CompData); ifree(Data); iSetError(IL_INVALID_FILE_HEADER); return NULL; } ifree(CompData); return Data; }
static ILboolean ReadAlphaBlock(PSP_CTX *ctx) { BLOCKHEAD Block; ALPHAINFO_CHUNK AlphaInfo; ALPHA_CHUNK AlphaChunk; ILushort StringSize; ILuint ChunkSize, Padding; if (ctx->Header.MajorVersion == 3) { /* ILuint NumAlpha = */ GetLittleUShort(ctx->io); } else { ChunkSize = GetLittleUInt(ctx->io); /* NumAlpha = */ GetLittleUShort(ctx->io); Padding = (ChunkSize - 4 - 2); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); } // Alpha channel header if (SIOread(ctx->io, &Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (ctx->Header.MajorVersion == 3) { Block.BlockLen = GetLittleUInt(ctx->io); } else { UInt(&Block.BlockLen); } if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) return IL_FALSE; if (ctx->Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(ctx->io); StringSize = GetLittleUShort(ctx->io); SIOseek(ctx->io, StringSize, IL_SEEK_CUR); if (SIOread(ctx->io, &AlphaInfo, sizeof(AlphaInfo), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(ctx->io); if (SIOread(ctx->io, &AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); } else { SIOseek(ctx->io, 256, IL_SEEK_CUR); SIOread(ctx->io, &AlphaInfo, sizeof(AlphaInfo), 1); if (SIOread(ctx->io, &AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; } /*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2); if (Alpha == NULL) { return IL_FALSE; }*/ ctx->Alpha = GetChannel(ctx); if (ctx->Alpha == NULL) return IL_FALSE; return IL_TRUE; }
ILboolean ReadAlphaBlock(ILuint BlockLen) { BLOCKHEAD Block; ALPHAINFO_CHUNK AlphaInfo; ALPHA_CHUNK AlphaChunk; ILushort NumAlpha, StringSize; ILuint ChunkSize, Padding; if (Header.MajorVersion == 3) { NumAlpha = GetLittleUShort(); } else { ChunkSize = GetLittleUInt(); NumAlpha = GetLittleUShort(); Padding = (ChunkSize - 4 - 2); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } // Alpha channel header if (iread(&Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (Header.MajorVersion == 3) Block.BlockLen = GetLittleUInt(); else UInt(&Block.BlockLen); if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_ALPHA_CHANNEL_BLOCK) return IL_FALSE; if (Header.MajorVersion >= 4) { ChunkSize = GetLittleUInt(); StringSize = GetLittleUShort(); iseek(StringSize, IL_SEEK_CUR); if (iread(&AlphaInfo, sizeof(AlphaInfo), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - 2 - StringSize - sizeof(AlphaInfo)); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(); if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4 - sizeof(AlphaChunk)); if (Padding > 0) iseek(Padding, IL_SEEK_CUR); } else { iseek(256, IL_SEEK_CUR); iread(&AlphaInfo, sizeof(AlphaInfo), 1); if (iread(&AlphaChunk, sizeof(AlphaChunk), 1) != 1) return IL_FALSE; } /*Alpha = (ILubyte*)ialloc(AlphaInfo.AlphaRect.x2 * AlphaInfo.AlphaRect.y2); if (Alpha == NULL) { return IL_FALSE; }*/ Alpha = GetChannel(); if (Alpha == NULL) return IL_FALSE; return IL_TRUE; }
// Internal function used to load the ROT. ILboolean iLoadRotInternal(void) { ILubyte Form[4], FormName[4]; ILuint FormLen, Width, Height, Format, Channels, CompSize; ILuint MipSize, MipLevel, MipWidth, MipHeight; ILenum FormatIL; ILimage *Image; ILboolean BaseCreated = IL_FALSE; ILubyte *CompData = NULL; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } // The first entry in the file must be 'FORM', 0x20 in a big endian integer and then 'HEAD'. iread(Form, 1, 4); FormLen = GetBigUInt(); iread(FormName, 1, 4); if (strncmp(Form, "FORM", 4) || FormLen != 0x14 || strncmp(FormName, "HEAD", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Next follows the width, height and format in the header. Width = GetLittleUInt(); Height = GetLittleUInt(); Format = GetLittleUInt(); //@TODO: More formats. switch (Format) { case ROT_RGBA32: // 32-bit RGBA format Channels = 4; FormatIL = IL_RGBA; break; case ROT_DXT1: // DXT1 (no alpha) Channels = 4; FormatIL = IL_RGBA; break; case ROT_DXT3: // DXT3 case ROT_DXT5: // DXT5 Channels = 4; FormatIL = IL_RGBA; // Allocates the maximum needed (the first width/height given in the file). CompSize = ((Width + 3) / 4) * ((Height + 3) / 4) * 16; CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; break; default: ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } if (Width == 0 || Height == 0) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Find out what this is. GetLittleUInt(); // Skip this for the moment. This appears to be the number of channels. // Next comes 'FORM', a length and 'MIPS'. iread(Form, 1, 4); FormLen = GetBigUInt(); iread(FormName, 1, 4); //@TODO: Not sure if the FormLen has to be anything specific here. if (strncmp(Form, "FORM", 4) || strncmp(FormName, "MIPS", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } //@TODO: Can these mipmap levels be in any order? Some things may be easier if the answer is no. Image = iCurImage; do { // Then we have 'FORM' again. iread(Form, 1, 4); // This is the size of the mipmap data. MipSize = GetBigUInt(); iread(FormName, 1, 4); if (strncmp(Form, "FORM", 4)) { if (!BaseCreated) { // Our file is malformed. ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // We have reached the end of the mipmap data. break; } if (strncmp(FormName, "MLVL", 4)) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Next is the mipmap attributes (level number, width, height and length) MipLevel = GetLittleUInt(); MipWidth = GetLittleUInt(); MipHeight = GetLittleUInt(); MipSize = GetLittleUInt(); // This is the same as the previous size listed -20 (for attributes). // Lower level mipmaps cannot be larger than the main image. if (MipWidth > Width || MipHeight > Height || MipSize > CompSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } // Just create our images here. if (!BaseCreated) { if (!ilTexImage(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL)) return IL_FALSE; BaseCreated = IL_TRUE; } else { Image->Mipmaps = ilNewImageFull(MipWidth, MipHeight, 1, Channels, FormatIL, IL_UNSIGNED_BYTE, NULL); Image = Image->Mipmaps; } switch (Format) { case ROT_RGBA32: // 32-bit RGBA format if (iread(Image->Data, Image->SizeOfData, 1) != 1) return IL_FALSE; break; case ROT_DXT1: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 8; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT1 data... if (iread(CompData, CompSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT1(Image, CompData)) { ifree(CompData); return IL_FALSE; } if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT1; CompData = NULL; } break; case ROT_DXT3: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT3 data... if (iread(CompData, MipSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT3(Image, CompData)) { ifree(CompData); return IL_FALSE; } if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT3; CompData = NULL; } break; case ROT_DXT5: // Allocates the size of the compressed data. CompSize = ((MipWidth + 3) / 4) * ((MipHeight + 3) / 4) * 16; if (CompSize != MipSize) { ilSetError(IL_INVALID_FILE_HEADER); return IL_FALSE; } CompData = ialloc(CompSize); if (CompData == NULL) return IL_FALSE; // Read in the DXT5 data... if (iread(CompData, MipSize, 1) != 1) return IL_FALSE; // ...and decompress it. if (!DecompressDXT5(Image, CompData)) { ifree(CompData); return IL_FALSE; } // Keeps a copy if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcSize = CompSize; Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT5; CompData = NULL; } break; } ifree(CompData); // Free it if it was not saved. } while (!ieof()); //@TODO: Is there any other condition that should end this? return ilFixImage(); }
// Internal function used to load the UTX. ILboolean iLoadUtxInternal(void) { UTXHEADER Header; UTXENTRYNAME *NameEntries; UTXEXPORTTABLE *ExportTable; UTXIMPORTTABLE *ImportTable; UTXPALETTE *Palettes; ILimage *Image; ILuint NumPal = 0, i, j = 0; ILint Name; ILubyte Type; ILint Val; ILint Size; ILint Width, Height, PalEntry; ILboolean BaseCreated = IL_FALSE, HasPal; ILuint Pos; ILint Format; ILubyte *CompData = NULL; ILubyte ExtraData[9]; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } if (!GetUtxHead(&Header)) return IL_FALSE; if (!CheckUtxHead(&Header)) return IL_FALSE; // Now we grab the name table. NameEntries = GetUtxNameTable(&Header); if (NameEntries == NULL) return IL_FALSE; // Then we get the export table. ExportTable = GetUtxExportTable(&Header); if (ExportTable == NULL) { UtxDestroyNameEntries(NameEntries, &Header); return IL_FALSE; } // Then the last table is the import table. ImportTable = GetUtxImportTable(&Header); if (ImportTable == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); return IL_FALSE; } for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Palette")) NumPal++; } if (NumPal == 0) //@TODO: Take care of UTX files without paletted data. return IL_FALSE; Palettes = (UTXPALETTE*)ialloc(NumPal * sizeof(UTXPALETTE)); if (Palettes == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); UtxDestroyImportTable(ImportTable, &Header); return IL_FALSE; } NumPal = 0; for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Palette")) { //Palettes[i].Name = strdup(NameEntries[ExportTable[i].ObjectName].Name); Palettes[NumPal].Name = i;//ExportTable[i].ObjectName; iseek(ExportTable[NumPal].SerialOffset, IL_SEEK_SET); Name = igetc(); // Skip the 2. Palettes[NumPal].Count = UtxReadCompactInteger(); Palettes[NumPal].Pal = (ILubyte*)ialloc(Palettes[NumPal].Count * 4); if (/*Palettes[NumPal].Name == NULL || */Palettes[NumPal].Pal == NULL) { UtxDestroyNameEntries(NameEntries, &Header); UtxDestroyExportTable(ExportTable, &Header); UtxDestroyImportTable(ImportTable, &Header); UtxDestroyPalettes(Palettes, NumPal); return IL_FALSE; } if (iread(Palettes[NumPal].Pal, Palettes[NumPal].Count * 4, 1) != 1) //@TODO: Deallocations here! return IL_FALSE; NumPal++; } } for (i = 0; i < Header.ExportCount; i++) { if (!strcmp(NameEntries[ImportTable[ExportTable[i].Class].ObjectName].Name, "Texture")) { iseek(ExportTable[i].SerialOffset, IL_SEEK_SET); Width = -1; Height = -1; PalEntry = NumPal; HasPal = IL_FALSE; Format = -1; ++j; j = j; do { Pos = itell(); Name = UtxReadCompactInteger(); if (!strcmp(NameEntries[Name].Name, "None")) break; Type = igetc(); Size = (Type & 0x70) >> 4; if (/*Name == 0 && */Type == 0xA2) igetc(); // Byte is 1 here... switch (Type & 0x0F) { case 1: Val = igetc(); break; case 2: Val = GetLittleUInt(); break; case 3: // Boolean value is in the info byte. igetc(); break; case 4: GetLittleFloat(); break; case 5: case 6: Val = itell(); Val = UtxReadCompactInteger(); break; case 10: Val = igetc(); switch (Size) { case 0: iseek(1, IL_SEEK_CUR); break; case 1: iseek(2, IL_SEEK_CUR); break; case 2: iseek(4, IL_SEEK_CUR); break; case 3: iseek(12, IL_SEEK_CUR); break; } break; default: // Uhm... Val = Val; break; } //@TODO: What should we do if Name >= Header.NameCount? if ((ILuint)Name < Header.NameCount) { if (!strcmp(NameEntries[Name].Name, "Palette")) { Val--; if (HasPal == IL_FALSE) { for (PalEntry = 0; (ILuint)PalEntry < NumPal; PalEntry++) { if (Val == Palettes[PalEntry].Name) { HasPal = IL_TRUE; break; } } } } if (!strcmp(NameEntries[Name].Name, "Format")) if (Format == -1) Format = Val; if (!strcmp(NameEntries[Name].Name, "USize")) if (Width == -1) Width = Val; if (!strcmp(NameEntries[Name].Name, "VSize")) if (Height == -1) Height = Val; } } while (!ieof()); if (Format == -1) Format = UTX_P8; if (Width == -1 || Height == -1 || (PalEntry == NumPal && Format != UTX_DXT1) || (Format != UTX_P8 && Format != UTX_DXT1)) return IL_FALSE; if (BaseCreated == IL_FALSE) { BaseCreated = IL_TRUE; ilTexImage(Width, Height, 1, UtxFormatToBpp(Format), UtxFormatToDevIL(Format), IL_UNSIGNED_BYTE, NULL); Image = iCurImage; } else { Image->Next = ilNewImageFull(Width, Height, 1, UtxFormatToBpp(Format), UtxFormatToDevIL(Format), IL_UNSIGNED_BYTE, NULL); if (Image->Next == NULL) return IL_FALSE; Image = Image->Next; } iseek(5, IL_SEEK_CUR); UtxReadCompactInteger(); switch (Format) { case UTX_P8: Image->Pal.PalSize = Palettes[PalEntry].Count * 4; Image->Pal.Palette = (ILubyte*)ialloc(Image->Pal.PalSize); if (Image->Pal.Palette == NULL) //@TODO: Do all the deallocations needed here! return IL_FALSE; memcpy(Image->Pal.Palette, Palettes[PalEntry].Pal, Image->Pal.PalSize); Image->Pal.PalType = IL_PAL_RGBA32; if (iread(Image->Data, Image->SizeOfData, 1) != 1) return IL_FALSE; //@TODO: Deallocations... break; case UTX_DXT1: // // // HACK!!! // // //igetc(); //ExtraData[0] = igetc(); //if (ExtraData[0] == 0x0C) //iseek(8, IL_SEEK_CUR); // iread(ExtraData+1, 8, 1); //else //iseek(7, IL_SEEK_CUR); // iread(ExtraData+1, 7, 1); //if (igetc() == 0x80) // igetc(); Image->DxtcSize = IL_MAX(Image->Width * Image->Height / 2, 8); CompData = (ILubyte*)ialloc(Image->DxtcSize); if (CompData == NULL) //@TODO: Do all the deallocations needed here! return IL_FALSE; if (iread(CompData, Image->DxtcSize, 1) != 1) { ifree(CompData); return IL_FALSE; //@TODO: Deallocations... } // Keep a copy of the DXTC data if the user wants it. if (ilGetInteger(IL_KEEP_DXTC_DATA) == IL_TRUE) { Image->DxtcData = CompData; Image->DxtcFormat = IL_DXT1; CompData = NULL; } if (DecompressDXT1(Image, CompData) == IL_FALSE) { ifree(CompData); return IL_FALSE; } ifree(CompData); break; } Image->Origin = IL_ORIGIN_UPPER_LEFT; } }
// Note: .Ktx support has not been tested yet! // https://www.khronos.org/opengles/sdk/tools/KTX/file_format_spec/ ILboolean iLoadKtxInternal() { KTX_HEAD Header; ILuint imageSize; ILenum Format; ILubyte Bpp; ILubyte FileIdentifier[12] = { //0xAB, 0x4B, 0x54, 0x58, 0x20, 0x31, 0x31, 0xBB, 0x0D, 0x0A, 0x1A, 0x0A '«', 'K', 'T', 'X', ' ', '1', '1', '»', '\r', '\n', '\x1A', '\n' }; if (iCurImage == NULL) { ilSetError(IL_ILLEGAL_OPERATION); return IL_FALSE; } /*Header.Width = GetLittleShort(); Header.Height = GetLittleShort(); Header.Dummy = GetLittleInt();*/ if (iread(Header.identifier, 1, 12) != 12) return IL_FALSE; Header.endianness = GetLittleUInt(); Header.glType = GetLittleUInt(); Header.glTypeSize = GetLittleUInt(); Header.glFormat = GetLittleUInt(); Header.glInternalFormat = GetLittleUInt(); Header.glBaseInternalFormat = GetLittleUInt(); Header.pixelWidth = GetLittleUInt(); Header.pixelHeight = GetLittleUInt(); Header.pixelDepth = GetLittleUInt(); Header.numberOfArrayElements = GetLittleUInt(); Header.numberOfFaces = GetLittleUInt(); Header.numberOfMipmapLevels = GetLittleUInt(); Header.bytesOfKeyValueData = GetLittleUInt(); if (memcmp(Header.identifier, FileIdentifier, 12) || Header.endianness != 0x04030201) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Additional types if (Header.glType != I_GL_UNSIGNED_BYTE || Header.glTypeSize != 1) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Additional formats if (Header.glFormat <= I_GL_ALPHA || Header.glFormat >= I_GL_LUMINANCE_ALPHA || Header.glInternalFormat != Header.glFormat /*|| Header.glBaseInternalFormat != Header.glFormat*/) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Mipmaps, etc. if (Header.numberOfArrayElements != 0 || Header.numberOfFaces != 1 || Header.numberOfMipmapLevels != 1) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: Parse this data if (iseek(Header.bytesOfKeyValueData, IL_SEEK_CUR)) return IL_FALSE; switch (Header.glFormat) { case I_GL_LUMINANCE: Bpp = 1; Format = IL_LUMINANCE; break; case IL_LUMINANCE_ALPHA: Bpp = 2; Format = IL_LUMINANCE_ALPHA; break; case I_GL_RGB: Bpp = 3; Format = IL_RGB; break; case I_GL_RGBA: Bpp = 4; Format = IL_RGBA; break; default: ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } //@TODO: More than just RGBA if (!ilTexImage(Header.pixelWidth, Header.pixelHeight, 1, Bpp, Format, IL_UNSIGNED_BYTE, NULL)) { return IL_FALSE; } iCurImage->Origin = IL_ORIGIN_UPPER_LEFT; imageSize = GetLittleUInt(); if (imageSize != Header.pixelWidth * Header.pixelHeight * Bpp) { ilSetError(IL_ILLEGAL_FILE_VALUE); return IL_FALSE; } if (iread(iCurImage->Data, Bpp, Header.pixelWidth * Header.pixelHeight) != Header.pixelWidth * Header.pixelHeight) return IL_FALSE; return ilFixImage(); }
static ILboolean ReadLayerBlock(PSP_CTX *ctx) { BLOCKHEAD Block; LAYERINFO_CHUNK LayerInfo; LAYERBITMAP_CHUNK Bitmap; ILuint ChunkSize, Padding, i, j; ILushort NumChars; // Layer sub-block header if (SIOread(ctx->io, &Block, 1, sizeof(Block)) != sizeof(Block)) return IL_FALSE; if (ctx->Header.MajorVersion == 3) { Block.BlockLen = GetLittleUInt(ctx->io); } else { UInt(&Block.BlockLen); } if (Block.HeadID[0] != 0x7E || Block.HeadID[1] != 0x42 || Block.HeadID[2] != 0x4B || Block.HeadID[3] != 0x00) { return IL_FALSE; } if (Block.BlockID != PSP_LAYER_BLOCK) return IL_FALSE; if (ctx->Header.MajorVersion == 3) { SIOseek(ctx->io, 256, IL_SEEK_CUR); // We don't care about the name of the layer. SIOread(ctx->io, &LayerInfo, sizeof(LayerInfo), 1); if (SIOread(ctx->io, &Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; } else { // ctx->Header.MajorVersion >= 4 ChunkSize = GetLittleUInt(ctx->io); NumChars = GetLittleUShort(ctx->io); SIOseek(ctx->io, NumChars, IL_SEEK_CUR); // We don't care about the layer's name. ChunkSize -= (2 + 4 + NumChars); if (SIOread(ctx->io, &LayerInfo, IL_MIN(sizeof(LayerInfo), ChunkSize), 1) != 1) return IL_FALSE; // Can have new entries in newer versions of the spec (5.0). Padding = (ChunkSize) - sizeof(LayerInfo); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); ChunkSize = GetLittleUInt(ctx->io); if (SIOread(ctx->io, &Bitmap, sizeof(Bitmap), 1) != 1) return IL_FALSE; Padding = (ChunkSize - 4) - sizeof(Bitmap); if (Padding > 0) SIOseek(ctx->io, Padding, IL_SEEK_CUR); } ctx->Channels = (ILubyte**)ialloc(sizeof(ILubyte*) * Bitmap.NumChannels); if (ctx->Channels == NULL) { return IL_FALSE; } ctx->NumChannels = Bitmap.NumChannels; for (i = 0; i < ctx->NumChannels; i++) { ctx->Channels[i] = GetChannel(ctx); if (ctx->Channels[i] == NULL) { for (j = 0; j < i; j++) ifree(ctx->Channels[j]); return IL_FALSE; } } return IL_TRUE; }