375 lines
10 KiB
C++
375 lines
10 KiB
C++
#include <algorithm>
|
|
|
|
typedef unsigned char u8;
|
|
typedef unsigned short u16;
|
|
typedef unsigned long u32;
|
|
|
|
extern bool gb_Endiannes;
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_FixEndian(u8 *src, u32 numBytes)
|
|
{
|
|
#define TPL_BIG_END
|
|
#ifdef TPL_BIG_END
|
|
|
|
u8 tmp[8]; // large enough to hold a double
|
|
u32 max, i;
|
|
|
|
|
|
//TCAssertMsg( (numBytes <= 8), "TCFixEndian: numBytes > 8\n" );
|
|
|
|
if( (numBytes == 0) || (numBytes == 1) )
|
|
{
|
|
return;
|
|
}
|
|
|
|
max = numBytes - 1;
|
|
for(i=0; i< numBytes; i++)
|
|
{
|
|
tmp[(max - i)] = src[i];
|
|
}
|
|
|
|
for(i=0; i< numBytes; i++)
|
|
{
|
|
src[i] = tmp[i];
|
|
}
|
|
|
|
#endif
|
|
}
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_FixCMPWord(u16 *data)
|
|
{
|
|
u16 tmp;
|
|
|
|
tmp = *data;
|
|
|
|
// reverse tuple order within bytes
|
|
*data = ( (tmp & 0x3 ) << 6 ) |
|
|
( (tmp & 0xC ) << 2 ) |
|
|
( (tmp & 0x30) >> 2 ) |
|
|
( (tmp & 0xC0) >> 6 ) |
|
|
|
|
( (tmp & 0x300 ) << 6 ) |
|
|
( (tmp & 0xC00 ) << 2 ) |
|
|
( (tmp & 0x3000) >> 2 ) |
|
|
( (tmp & 0xC000) >> 6 ) ;
|
|
}
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_PackCMPTile
|
|
(
|
|
void * _pv_SrcImg,
|
|
u32 _u32_Width,
|
|
u32 _u32_Height,
|
|
u32 tileX,
|
|
u32 tileY,
|
|
u16 * dstPtr
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
u32 x, y;
|
|
u16 * srcPtr;
|
|
u16 tmp;
|
|
u32 srcTileOffset;
|
|
u32 subTileRows, subRowShorts; // number of s3 4x4 tiles
|
|
u32 srcPadWidth, srcPadHeight;
|
|
u16 * buffPtr;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
// set the padded size of the s3 source image out to a 4-texel boundary
|
|
srcPadWidth = ( (_u32_Width + 3) >> 2 );
|
|
srcPadHeight = ( (_u32_Height + 3) >> 2 );
|
|
|
|
// number of bytes in a single row of 4x4 texel source tiles
|
|
srcTileOffset = srcPadWidth * 8;
|
|
|
|
// number of 4x4 (source) tile rows to copy ( will be 1 or 2 )
|
|
subTileRows = 2;
|
|
if( (srcPadHeight - tileY) < 2 )
|
|
subTileRows = 1;
|
|
|
|
// number of 4x4 tile cols to copy translated into number of short values
|
|
// ( will be 4 or 8 )
|
|
subRowShorts = 8;
|
|
if( (srcPadWidth - tileX) < 2 )
|
|
subRowShorts = 4;
|
|
|
|
for( y=0; y < subTileRows; y++ )
|
|
{
|
|
srcPtr = (u16*)( (u8*)(_pv_SrcImg) + ((tileY + y) * srcTileOffset) + (tileX*8) );
|
|
buffPtr = ( dstPtr + (y * 8) ); // 16 bytes per subRow = 8 shorts
|
|
|
|
// process one or both 4x4 row tiles at once- 4 short each
|
|
for( x=0; x < subRowShorts; x++ )
|
|
{
|
|
switch( x )
|
|
{
|
|
|
|
// color table entries - switch bytes within a 16-bit world only
|
|
case 0:
|
|
case 1:
|
|
case 4:
|
|
case 5:
|
|
tmp = *srcPtr++;
|
|
GDK_images_FixEndian((u8*)(&tmp), 2);
|
|
*buffPtr++ = tmp;
|
|
break;
|
|
|
|
// 2-bit color tuples;
|
|
// reverse tuple order within bytes of a word
|
|
case 2:
|
|
case 3:
|
|
case 6:
|
|
case 7:
|
|
tmp = *srcPtr++;
|
|
GDK_images_FixCMPWord(&tmp);
|
|
*buffPtr++ = tmp;
|
|
break;
|
|
|
|
} // end switch
|
|
} // end for( subRowShorts )
|
|
} // end for( subTileRows )
|
|
}
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
After DXT1 compression, Wii textures must be tiled => CMPR format
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_TileDXTForWii
|
|
(
|
|
void * _pv_DestImg,
|
|
void * _pv_SrcImg,
|
|
u32 _u32_Width,
|
|
u32 _u32_Height
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
u32 tileRow, tileCol;
|
|
u32 srcTileRows, srcTileCols;
|
|
u16 * dstPtr;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
// each source tile is 4x4 texels, 8B
|
|
srcTileRows = ((_u32_Height + 3) >> 2);
|
|
srcTileCols = ((_u32_Width + 3) >> 2);
|
|
|
|
dstPtr = (u16*) _pv_DestImg;
|
|
|
|
// each dst tile is 2x2 source tiles, so move by 2 each iteration
|
|
for (tileRow = 0; tileRow < srcTileRows; tileRow += 2)
|
|
{
|
|
for (tileCol = 0; tileCol < srcTileCols; tileCol += 2)
|
|
{
|
|
GDK_images_PackCMPTile(_pv_SrcImg, _u32_Width, _u32_Height, tileCol, tileRow, dstPtr );
|
|
dstPtr += 16; // 32B per dst tile, short ptr
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
Tile a raw image I8 format for WII
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_TileRawBufferForWiiI8
|
|
(
|
|
void * _pv_DestImg,
|
|
void * _pv_SrcImg,
|
|
u32 _u32_Width,
|
|
u32 _u32_Height
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
u32 row, col;
|
|
u8 * dstPtr;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
dstPtr = (u8*)_pv_DestImg;
|
|
|
|
// one tile is 32B 4 rows x 8 columns
|
|
for (row = 0; row < _u32_Height; row += 4)
|
|
{
|
|
for (col = 0; col < _u32_Width; col += 8)
|
|
{
|
|
u8* src1 = (u8*)_pv_SrcImg + ((row + 0) * _u32_Width + col);
|
|
u8* src2 = (u8*)_pv_SrcImg + ((row + 1) * _u32_Width + col);
|
|
u8* src3 = (u8*)_pv_SrcImg + ((row + 2) * _u32_Width + col);
|
|
u8* src4 = (u8*)_pv_SrcImg + ((row + 3) * _u32_Width + col);
|
|
|
|
for(u32 i = 0; i < 8; ++i, ++dstPtr, ++src1) *dstPtr = *src1;
|
|
for(u32 i = 0; i < 8; ++i, ++dstPtr, ++src2) *dstPtr = *src2;
|
|
for(u32 i = 0; i < 8; ++i, ++dstPtr, ++src3) *dstPtr = *src3;
|
|
for(u32 i = 0; i < 8; ++i, ++dstPtr, ++src4) *dstPtr = *src4;
|
|
}
|
|
}
|
|
}
|
|
|
|
/*
|
|
=======================================================================================================================
|
|
Tile a raw image I8A8 format for WII
|
|
=======================================================================================================================
|
|
*/
|
|
void GDK_images_TileRawBufferForWiiI8A8
|
|
(
|
|
void * _pv_DestImg,
|
|
void * _pv_SrcImg,
|
|
u32 _u32_Width,
|
|
u32 _u32_Height
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
u32 row, col;
|
|
u16 * dstPtr;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
dstPtr = (u16*)_pv_DestImg;
|
|
|
|
// one tile is 32B 4 rows x 4 columns
|
|
for (row = 0; row < _u32_Height; row += 4)
|
|
{
|
|
for (col = 0; col < _u32_Width; col += 4)
|
|
{
|
|
u16* src1 = (u16*)_pv_SrcImg + ((row + 0) * _u32_Width + col);
|
|
u16* src2 = (u16*)_pv_SrcImg + ((row + 1) * _u32_Width + col);
|
|
u16* src3 = (u16*)_pv_SrcImg + ((row + 2) * _u32_Width + col);
|
|
u16* src4 = (u16*)_pv_SrcImg + ((row + 3) * _u32_Width + col);
|
|
|
|
for(u32 i = 0; i < 4; ++i, ++dstPtr, ++src1) *dstPtr = *src1;
|
|
for(u32 i = 0; i < 4; ++i, ++dstPtr, ++src2) *dstPtr = *src2;
|
|
for(u32 i = 0; i < 4; ++i, ++dstPtr, ++src3) *dstPtr = *src3;
|
|
for(u32 i = 0; i < 4; ++i, ++dstPtr, ++src4) *dstPtr = *src4;
|
|
}
|
|
}
|
|
}
|
|
|
|
void GDK_images_TileForWii
|
|
(
|
|
void * _pv_DestImg,
|
|
const void * _pv_SrcImg,
|
|
u32 _u32_Width,
|
|
u32 _u32_Height,
|
|
u32 _u32_BPP
|
|
)
|
|
{
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
const u32 tileSize = 32;
|
|
u32 nbXTiles, nbYTiles, nbTexelsPerTileX = 0, nbTexelsPerTileY = 0;
|
|
u8 u8_BytesPerColor = 0;
|
|
u8 * currARTilePtr = 0;
|
|
u8 * currGBTilePtr = 0;
|
|
u8 * currTilePtr = 0;
|
|
u32 Ix, Iy; // Image x and y;
|
|
u32 tileY, tileX;
|
|
u8 * srcImage = 0;
|
|
u32 tx, ty; // Tile x and y
|
|
u32 u32_Color = 0;
|
|
u16 u16_Color = 0;
|
|
/*~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~~*/
|
|
|
|
// Set tiles and color size according to BPP (if palette, color size is not used)
|
|
switch (_u32_BPP)
|
|
{
|
|
case 32:
|
|
nbTexelsPerTileX = 4;
|
|
nbTexelsPerTileY = 4;
|
|
u8_BytesPerColor = 4;
|
|
break;
|
|
|
|
case 16:
|
|
nbTexelsPerTileX = 4;
|
|
nbTexelsPerTileY = 4;
|
|
u8_BytesPerColor = 2;
|
|
break;
|
|
|
|
case 8:
|
|
nbTexelsPerTileX = 8;
|
|
nbTexelsPerTileY = 4;
|
|
break;
|
|
|
|
default:
|
|
return;
|
|
}
|
|
|
|
// Destination pointers for mipmap 0
|
|
currARTilePtr = (u8 *) _pv_DestImg;
|
|
currGBTilePtr = (u8 *) _pv_DestImg + tileSize;
|
|
currTilePtr = (u8 *) _pv_DestImg;
|
|
|
|
// Set source pointers
|
|
srcImage = (u8 *) _pv_SrcImg;
|
|
|
|
u32 un = 1;
|
|
nbXTiles = std::max(un, _u32_Width / nbTexelsPerTileX);
|
|
nbYTiles = std::max(un, _u32_Height / nbTexelsPerTileY);
|
|
|
|
// For each tile
|
|
for (tileY = 0; tileY < nbYTiles; tileY++)
|
|
{
|
|
for (tileX = 0; tileX < nbXTiles; tileX++)
|
|
{
|
|
// Fill the tiles texel by texel
|
|
for (ty = 0 ; ty < nbTexelsPerTileY ; ty++)
|
|
{
|
|
for (tx = 0 ; tx < nbTexelsPerTileX ; tx++)
|
|
{
|
|
Ix = (tileX * nbTexelsPerTileX + tx);
|
|
Iy = (tileY * nbTexelsPerTileY + ty);
|
|
|
|
if (Ix < _u32_Width && Iy < _u32_Height)
|
|
{
|
|
// Fill dest buffer according to BPP
|
|
switch (_u32_BPP)
|
|
{
|
|
case 32:
|
|
u32_Color = *(u32 *)(srcImage + u8_BytesPerColor * (Iy * _u32_Width + Ix));
|
|
|
|
*currARTilePtr = (u8)((u32_Color & 0xFF000000) >> 24);
|
|
*(currARTilePtr + 1) = (u8)((u32_Color & 0x00FF0000) >> 16);
|
|
//*(currARTilePtr + 1) = (_u32_Flags & K3D_C_texture_NoInvertRB) ? (u8)((u32_Color & 0x0000FF00) >> 8) : (u8)((u32_Color & 0xFF000000) >> 24);
|
|
*currGBTilePtr = (u8)((u32_Color & 0x0000FF00) >> 8);
|
|
*(currGBTilePtr + 1) = (u8)((u32_Color & 0x000000FF) >> 0);
|
|
//*(currGBTilePtr + 1) = (_u32_Flags & K3D_C_texture_NoInvertRB) ? (u8)((u32_Color & 0xFF000000) >> 24) : (u8)((u32_Color & 0x0000FF00) >> 8);
|
|
break;
|
|
|
|
case 16:
|
|
u16_Color = *(u16 *)(srcImage + u8_BytesPerColor * (Iy * _u32_Width + Ix));
|
|
|
|
*currTilePtr = (u8)(u16_Color >> 8);
|
|
*++currTilePtr = (u8)(u16_Color);
|
|
break;
|
|
|
|
case 8:
|
|
*currTilePtr = *(srcImage + _u32_Width * Iy + Ix);
|
|
break;
|
|
|
|
default:
|
|
*currARTilePtr = 0xFF;
|
|
*(currARTilePtr + 1) = 0xFF;
|
|
*currGBTilePtr = 0x00;
|
|
*(currGBTilePtr + 1) = 0x00;
|
|
break;
|
|
}
|
|
}
|
|
|
|
currARTilePtr += 2;
|
|
currGBTilePtr += 2;
|
|
currTilePtr++;
|
|
}
|
|
}
|
|
|
|
currARTilePtr += tileSize;
|
|
currGBTilePtr += tileSize;
|
|
}
|
|
}
|
|
}
|