02 Jan 2008

This commit is contained in:
g-cont 2008-01-02 00:00:00 +03:00 committed by Alibek Omarov
parent 2761b9d8ec
commit f031d6f60a
17 changed files with 706 additions and 183 deletions

View File

@ -27,6 +27,7 @@ DDS Converter 2.1
//==================================================
// то, что уже готово
//==================================================
+добавлена поддержка текстур из первого дуума (с прозрачностью)
+запущена в строй wadlib
+добавлена поддержка ВСЕХ существующих типов внутри вадов
+добавлена поддержка wad-файлов

View File

@ -31,7 +31,6 @@ void InitPlatform ( uint funcname, int argc, char **argv )
char source[64], gamedir[64];
basepool = Mem_AllocPool( "Temp" );
zonepool = Mem_AllocPool( "Zone" );
// for custom cmdline parsing
com_argc = argc;
@ -113,6 +112,7 @@ void RunPlatform ( void )
strcpy(searchmask[3], "*.lmp" ); // quake1 menu images
strcpy(searchmask[4], "*.mip" ); // quake1 textures
strcpy(searchmask[5], "*.fnt" ); // half-life fonts
strcpy(searchmask[6], "*.flat"); // doom1 textures
Msg("Processing images ...\n\n");
break;
case BSPLIB:

View File

@ -557,7 +557,7 @@ void ROQ_ProcessAudio( void )
{
return;
if(!strlen(soundname)) return;
if(!com.strlen(soundname)) return;
com.strcpy( tempoutname, movieoutname );
FS_StripExtension( tempoutname );

View File

@ -98,6 +98,7 @@ extern uint image_ptr; // common moveable pointer
// image lib utilites
extern uint *d_currentpal;
bool dds_save_image( const char *name, rgbdata_t *pix, int saveformat );
bool Image_Copy8bitRGBA(const byte *in, byte *out, int pixels); // convert indexed image to RGBA
rgbdata_t *Image_CopyRGBA8bit( rgbdata_t *pix, int numcolors ); // convert RGBA image to indexed
void Image_RoundDimensions(int *scaled_width, int *scaled_height);

View File

@ -9,21 +9,41 @@
#define Sum(c) ((c)->r + (c)->g + (c)->b)
bool dds_write_header( vfile_t *f, rgbdata_t *pix, uint cubemap_flags )
/*
===============
GetImageSize
calculate buffer size for current miplevel
===============
*/
uint GetImageSize( int block, int width, int height, int depth, int bpp, int rgbcount )
{
uint BlockSize = 0;
if(block == 0) BlockSize = width * height * bpp;
else if(block > 0) BlockSize = ((width + 3)/4) * ((height + 3)/4) * depth * block;
else if(block < 0 && rgbcount > 0) BlockSize = width * height * depth * rgbcount;
else BlockSize = width * height * abs(block);
return BlockSize;
}
bool dds_write_header( vfile_t *f, rgbdata_t *pix, uint cubemap_flags, uint savetype )
{
uint dwFourCC, dwFlags1 = 0, dwFlags2 = 0, dwCaps1 = 0;
uint dwLinearSize, dwBlockSize, dwCaps2 = 0;
uint dwIdent = DDSHEADER, dwSize = 124, dwSize2 = 32;
uint dwWidth, dwHeight, dwDepth, dwMipCount = 1;
if(!pix || pix->buffer )
if(!pix || !pix->buffer )
return false;
// setup flags
dwFlags1 |= DDS_LINEARSIZE | DDS_MIPMAPCOUNT | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT;
dwFlags1 |= DDS_LINEARSIZE | DDS_WIDTH | DDS_HEIGHT | DDS_CAPS | DDS_PIXELFORMAT;
dwFlags2 |= DDS_FOURCC;
if( pix->numLayers > 1) dwFlags1 |= DDS_DEPTH;
switch( pix->type )
switch( savetype )
{
case PF_DXT1:
dwFourCC = TYPE_DXT1;
@ -53,25 +73,29 @@ bool dds_write_header( vfile_t *f, rgbdata_t *pix, uint cubemap_flags )
MsgDev( D_ERROR, "dds_write_header: unsupported type %s\n", PFDesc[pix->type].name );
return false;
}
dwWidth = pix->width;
dwHeight = pix->height;
VFS_Write(f, &dwIdent, sizeof(uint));
VFS_Write(f, &dwSize, sizeof(uint));
VFS_Write(f, &dwFlags1, sizeof(uint));
VFS_Write(f, &pix->height, sizeof(uint));
VFS_Write(f, &pix->width, sizeof(uint));
VFS_Write(f, &dwHeight, sizeof(uint));
VFS_Write(f, &dwWidth, sizeof(uint));
dwBlockSize = PFDesc[pix->type].block;
dwLinearSize = (((pix->width + 3)/4) * ((pix->height + 3)/4)) * dwBlockSize * pix->numLayers;
dwBlockSize = PFDesc[savetype].block;
dwLinearSize = GetImageSize(PFDesc[savetype].block, pix->width, pix->height, pix->numLayers, PFDesc[savetype].bpp, pix->bitsCount / 8 );
//dwLinearSize = (((pix->width + 3)/4) * ((pix->height + 3)/4)) * dwBlockSize * pix->numLayers;
VFS_Write(f, &dwLinearSize, sizeof(uint)); // TODO: use dds_get_linear_size
if (pix->numLayers > 1)
{
VFS_Write(f, &pix->numLayers, sizeof(uint));
dwDepth = pix->numLayers;
VFS_Write(f, &dwDepth, sizeof(uint));
dwCaps2 |= DDS_VOLUME;
}
else VFS_Write(f, 0, sizeof(uint));
VFS_Write(f, &pix->numMips, sizeof(uint));
VFS_Write(f, &dwMipCount, sizeof(uint));
VFS_Write(f, 0, sizeof(uint));
VFS_Write(f, pix->color, sizeof(vec3_t));
VFS_Write(f, &pix->bump_scale, sizeof(float));
@ -140,6 +164,49 @@ void ChooseEndpoints(word *Block, word *ex0, word *ex1)
*ex1 = Block[Lowest];
}
void CorrectEndDXT1( word *ex0, word *ex1, bool HasAlpha )
{
word Temp;
if( HasAlpha )
{
if(*ex0 > *ex1)
{
Temp = *ex0;
*ex0 = *ex1;
*ex1 = Temp;
}
}
else
{
if (*ex0 < *ex1)
{
Temp = *ex0;
*ex0 = *ex1;
*ex1 = Temp;
}
}
return;
}
void PreMult(word *Data, byte *Alpha)
{
color24 Colour;
uint i;
for (i = 0; i < 16; i++)
{
ShortToColor888(Data[i], &Colour);
Colour.r = (byte)(((uint)Colour.r * Alpha[i]) >> 8);
Colour.g = (byte)(((uint)Colour.g * Alpha[i]) >> 8);
Colour.b = (byte)(((uint)Colour.b * Alpha[i]) >> 8);
Data[i] = Color888ToShort(&Colour);
ShortToColor888(Data[i], &Colour);
}
return;
}
void ChooseAlphaEndpoints( byte *Block, byte *a0, byte *a1)
{
uint i, Lowest = 0xFF, Highest = 0;
@ -153,6 +220,41 @@ void ChooseAlphaEndpoints( byte *Block, byte *a0, byte *a1)
*a1 = Highest;
}
// Assumed to be 16-bit (5:6:5).
bool GetBlock( word *Block, word *Data, rgbdata_t *pix, uint XPos, uint YPos)
{
uint x, y, i = 0, Offset = YPos * pix->width + XPos;
for( y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if(x < pix->width && y < pix->height)
Block[i++] = Data[Offset + x];
else Block[i++] = Data[Offset];
}
Offset += pix->width;
}
return true;
}
bool GetAlphaBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos)
{
uint x, y, i = 0, Offset = YPos * pix->width + XPos;
for (y = 0; y < 4; y++)
{
for (x = 0; x < 4; x++)
{
if (x < pix->width && y < pix->height)
Block[i++] = Data[Offset + x];
else Block[i++] = Data[Offset];
}
Offset += pix->width;
}
return true;
}
bool Get3DcBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos, int channel )
{
uint x, y, i = 0, Offset = 2*(YPos * pix->width + XPos) + channel;
@ -162,7 +264,7 @@ bool Get3DcBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos,
for (x = 0; x < 4; x++)
{
if(x < pix->width && y < pix->height)
Block[i++] = Data[Offset + 2*x];
Block[i++] = Data[Offset + 2 * x];
else Block[i++] = Data[Offset];
}
Offset += 2 * pix->width;
@ -170,6 +272,184 @@ bool Get3DcBlock( byte *Block, byte *Data, rgbdata_t *pix, uint XPos, uint YPos,
return true;
}
byte* GetAlpha( rgbdata_t *pix )
{
byte *Alpha;
uint i, j, Bpc, Size, AlphaOff;
Bpc = PFDesc[pix->type].bpc;
if( Bpc == 0 ) return NULL;
Size = pix->width * pix->height * pix->numLayers * PFDesc[pix->type].bpp;
Alpha = (byte*)Mem_Alloc( Sys.imagepool, Size / PFDesc[pix->type].bpp * Bpc);
if( pix->type == PF_LUMINANCE_ALPHA )
AlphaOff = 2;
else AlphaOff = 4;
for (i = AlphaOff - 1, j = 0; i < Size; i += AlphaOff, j++ )
Alpha[j] = pix->buffer[i];
return Alpha;
}
uint RMSAlpha( byte *Orig, byte *Test )
{
uint RMS = 0, i;
int d;
for (i = 0; i < 16; i++)
{
d = Orig[i] - Test[i];
RMS += d*d;
}
return RMS;
}
uint Distance(color24 *c1, color24 *c2)
{
return (c1->r - c2->r) * (c1->r - c2->r) + (c1->g - c2->g) * (c1->g - c2->g) + (c1->b - c2->b) * (c1->b - c2->b);
}
uint GenBitMask( word ex0, word ex1, uint NumCols, word *In, byte *Alpha, color24 *OutCol )
{
uint i, j, Closest, Dist, BitMask = 0;
byte Mask[16];
color24 c, Colours[4];
ShortToColor888(ex0, &Colours[0]);
ShortToColor888(ex1, &Colours[1]);
if (NumCols == 3)
{
Colours[2].r = (Colours[0].r + Colours[1].r) / 2;
Colours[2].g = (Colours[0].g + Colours[1].g) / 2;
Colours[2].b = (Colours[0].b + Colours[1].b) / 2;
Colours[3].r = (Colours[0].r + Colours[1].r) / 2;
Colours[3].g = (Colours[0].g + Colours[1].g) / 2;
Colours[3].b = (Colours[0].b + Colours[1].b) / 2;
}
else
{ // NumCols == 4
Colours[2].r = (2 * Colours[0].r + Colours[1].r + 1) / 3;
Colours[2].g = (2 * Colours[0].g + Colours[1].g + 1) / 3;
Colours[2].b = (2 * Colours[0].b + Colours[1].b + 1) / 3;
Colours[3].r = (Colours[0].r + 2 * Colours[1].r + 1) / 3;
Colours[3].g = (Colours[0].g + 2 * Colours[1].g + 1) / 3;
Colours[3].b = (Colours[0].b + 2 * Colours[1].b + 1) / 3;
}
for (i = 0; i < 16; i++)
{
if (Alpha)
{
// Test to see if we have 1-bit transparency
if (Alpha[i] < 128)
{
Mask[i] = 3; // Transparent
if (OutCol)
{
OutCol[i].r = Colours[3].r;
OutCol[i].g = Colours[3].g;
OutCol[i].b = Colours[3].b;
}
continue;
}
}
// if no transparency, try to find which colour is the closest.
Closest = UINT_MAX;
ShortToColor888(In[i], &c);
for (j = 0; j < NumCols; j++)
{
Dist = Distance(&c, &Colours[j]);
if( Dist < Closest )
{
Closest = Dist;
Mask[i] = j;
if( OutCol )
{
OutCol[i].r = Colours[j].r;
OutCol[i].g = Colours[j].g;
OutCol[i].b = Colours[j].b;
}
}
}
}
for( i = 0; i < 16; i++ )
{
BitMask |= (Mask[i] << (i*2));
}
return BitMask;
}
void GenAlphaBitMask( byte a0, byte a1, byte *In, byte *Mask, byte *Out )
{
byte Alphas[8], M[16];
uint i, j, Closest, Dist;
Alphas[0] = a0;
Alphas[1] = a1;
// 8-alpha or 6-alpha block?
if (a0 > a1)
{
// 8-alpha block: derive the other six alphas.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alphas[2] = (6 * Alphas[0] + 1 * Alphas[1] + 3) / 7; // bit code 010
Alphas[3] = (5 * Alphas[0] + 2 * Alphas[1] + 3) / 7; // bit code 011
Alphas[4] = (4 * Alphas[0] + 3 * Alphas[1] + 3) / 7; // bit code 100
Alphas[5] = (3 * Alphas[0] + 4 * Alphas[1] + 3) / 7; // bit code 101
Alphas[6] = (2 * Alphas[0] + 5 * Alphas[1] + 3) / 7; // bit code 110
Alphas[7] = (1 * Alphas[0] + 6 * Alphas[1] + 3) / 7; // bit code 111
}
else
{
// 6-alpha block.
// Bit code 000 = alpha_0, 001 = alpha_1, others are interpolated.
Alphas[2] = (4 * Alphas[0] + 1 * Alphas[1] + 2) / 5; // Bit code 010
Alphas[3] = (3 * Alphas[0] + 2 * Alphas[1] + 2) / 5; // Bit code 011
Alphas[4] = (2 * Alphas[0] + 3 * Alphas[1] + 2) / 5; // Bit code 100
Alphas[5] = (1 * Alphas[0] + 4 * Alphas[1] + 2) / 5; // Bit code 101
Alphas[6] = 0x00; // Bit code 110
Alphas[7] = 0xFF; // Bit code 111
}
for (i = 0; i < 16; i++)
{
Closest = UINT_MAX;
for (j = 0; j < 8; j++)
{
Dist = abs((int)In[i] - (int)Alphas[j]);
if (Dist < Closest)
{
Closest = Dist;
M[i] = j;
}
}
}
if( Out )
{
for (i = 0; i < 16; i++)
{
Out[i] = Alphas[M[i]];
}
}
// First three bytes.
Mask[0] = (M[0]) | (M[1] << 3) | ((M[2] & 0x03) << 6);
Mask[1] = ((M[2] & 0x04) >> 2) | (M[3] << 1) | (M[4] << 4) | ((M[5] & 0x01) << 7);
Mask[2] = ((M[5] & 0x06) >> 1) | (M[6] << 2) | (M[7] << 5);
// Second three bytes.
Mask[3] = (M[8]) | (M[9] << 3) | ((M[10] & 0x03) << 6);
Mask[4] = ((M[10] & 0x04) >> 2) | (M[11] << 1) | (M[12] << 4) | ((M[13] & 0x01) << 7);
Mask[5] = ((M[13] & 0x06) >> 1) | (M[14] << 2) | (M[15] << 5);
return;
}
word *dds_compress_565( rgbdata_t *pix )
{
@ -189,11 +469,11 @@ word *dds_compress_565( rgbdata_t *pix )
}
break;
case PF_RGBA_32:
for (i = 0, j = 0; i < pix->size; i += 4, j++)
for( i = 0, j = 0; i < pix->size; i += 4, j++ )
{
Data[j] = (pix->buffer[i+0] >> 3) << 11;
Data[j] |= (pix->buffer[i+1] >> 2) << 5;
Data[j] |= pix->buffer[i+2] >> 3;
Data[j] |= (pix->buffer[i+0]>>3)<<11;
Data[j] |= (pix->buffer[i+1]>>2)<<5;
Data[j] |= (pix->buffer[i+2]>>3);
}
break;
case PF_RGB_24_FLIP:
@ -335,7 +615,7 @@ uint dds_compress_dxt( vfile_t *f, int saveformat, rgbdata_t *pix )
bool HasAlpha;
uint Count = 0;
if(!pix || pix->buffer )
if(!pix || !pix->buffer )
return 0;
if( saveformat == PF_ATI2N)
@ -370,7 +650,7 @@ uint dds_compress_dxt( vfile_t *f, int saveformat, rgbdata_t *pix )
}
Mem_Free( Data3Dc );
}
else if( saveformat == IL_ATI1N )
else if( saveformat == PF_ATI1N )
{
rgbdata_t *lum = NULL;
if (PFDesc[pix->type].bpp != 1)
@ -407,7 +687,7 @@ uint dds_compress_dxt( vfile_t *f, int saveformat, rgbdata_t *pix )
Data = dds_compress_565( pix );
if(!Data) return 0;
Alpha = ilGetAlpha(IL_UNSIGNED_BYTE);
Alpha = GetAlpha( pix );
if(!Alpha)
{
Mem_Free(Data);
@ -430,142 +710,144 @@ uint dds_compress_dxt( vfile_t *f, int saveformat, rgbdata_t *pix )
switch( saveformat )
{
case IL_DXT1:
for (z = 0; z < pix->numLayers; z++) {
for (y = 0; y < Image->Height; y += 4) {
for (x = 0; x < Image->Width; x += 4) {
GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
HasAlpha = IL_FALSE;
for (i = 0 ; i < 16; i++) {
if (AlphaBlock[i] < 128) {
HasAlpha = IL_TRUE;
break;
}
case PF_DXT1:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
HasAlpha = false;
for (i = 0; i < 16; i++)
{
if(AlphaBlock[i] < 128)
{
HasAlpha = true;
break;
}
GetBlock(Block, Runner16, Image, x, y);
ChooseEndpoints(Block, &ex0, &ex1);
CorrectEndDXT1(&ex0, &ex1, HasAlpha);
SaveLittleUShort(ex0);
SaveLittleUShort(ex1);
if (HasAlpha)
BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL);
else
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
SaveLittleUInt(BitMask);
Count += 8;
}
}
Runner16 += Image->Width * Image->Height;
Runner8 += Image->Width * Image->Height;
}
break;
/*case IL_DXT2:
for (y = 0; y < Image->Height; y += 4) {
for (x = 0; x < Image->Width; x += 4) {
GetAlphaBlock(AlphaBlock, Alpha, Image, x, y);
for (i = 0; i < 16; i += 2) {
iputc((ILubyte)(((AlphaBlock[i] >> 4) << 4) | (AlphaBlock[i+1] >> 4)));
}
GetBlock(Block, Data, Image, x, y);
PreMult(Block, AlphaBlock);
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &ex0, &ex1);
SaveLittleUShort(ex0);
SaveLittleUShort(ex1);
CorrectEndDXT1(&ex0, &ex1, HasAlpha);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
if (HasAlpha) BitMask = GenBitMask(ex0, ex1, 3, Block, AlphaBlock, NULL);
else BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, AlphaBitMask, sizeof(uint));
Count += 8;
}
}
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
case PF_DXT2:
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
for (i = 0; i < 16; i += 2)
{
byte tempBlock = ((AlphaBlock[i]>>4)<<4) | (AlphaBlock[i+1]>>4);
VFS_Write(f, &tempBlock, 1 );
}
GetBlock(Block, Runner16, pix, x, y);
PreMult(Block, AlphaBlock);
ChooseEndpoints(Block, &ex0, &ex1);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, &AlphaBitMask, sizeof(uint));
Count += 16;
}
}
break;
case PF_DXT3:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
for (i = 0; i < 16; i += 2)
{
byte tempBlock = ((AlphaBlock[i]>>4)<<4) | (AlphaBlock[i+1]>>4);
VFS_Write(f, &tempBlock, 1 );
}
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = max(t0, t1);
ex1 = min(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
SaveLittleUInt(BitMask);
}
}
break;*/
case IL_DXT3:
for (z = 0; z < Image->Depth; z++) {
for (y = 0; y < Image->Height; y += 4) {
for (x = 0; x < Image->Width; x += 4) {
GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
for (i = 0; i < 16; i += 2) {
iputc((ILubyte)(((AlphaBlock[i+1] >> 4) << 4) | (AlphaBlock[i] >> 4)));
}
GetBlock(Block, Runner16, Image, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = IL_MAX(t0, t1);
ex1 = IL_MIN(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
SaveLittleUShort(ex0);
SaveLittleUShort(ex1);
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
SaveLittleUInt(BitMask);
Count += 16;
}
VFS_Write(f, AlphaBitMask, sizeof(uint));
Count += 16;
}
Runner16 += Image->Width * Image->Height;
Runner8 += Image->Width * Image->Height;
}
break;
case IL_RXGB:
case IL_DXT5:
for (z = 0; z < Image->Depth; z++) {
for (y = 0; y < Image->Height; y += 4) {
for (x = 0; x < Image->Width; x += 4) {
GetAlphaBlock(AlphaBlock, Runner8, Image, x, y);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/);
/*Rms2 = RMSAlpha(AlphaBlock, AlphaOut);
GenAlphaBitMask(a0, a1, 8, AlphaBlock, AlphaBitMask, AlphaOut);
Rms1 = RMSAlpha(AlphaBlock, AlphaOut);
if (Rms2 <= Rms1) { // Yeah, we have to regenerate...
GenAlphaBitMask(a0, a1, 6, AlphaBlock, AlphaBitMask, AlphaOut);
Rms2 = a1; // Just reuse Rms2 as a temporary variable...
a1 = a0;
a0 = Rms2;
}*/
iputc(a0);
iputc(a1);
iwrite(AlphaBitMask, 1, 6);
GetBlock(Block, Runner16, Image, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = IL_MAX(t0, t1);
ex1 = IL_MIN(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
SaveLittleUShort(ex0);
SaveLittleUShort(ex1);
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
SaveLittleUInt(BitMask);
Count += 16;
}
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
case PF_RXGB:
case PF_DXT5:
for (z = 0; z < pix->numLayers; z++)
{
for (y = 0; y < pix->height; y += 4)
{
for (x = 0; x < pix->width; x += 4)
{
GetAlphaBlock(AlphaBlock, Runner8, pix, x, y);
ChooseAlphaEndpoints(AlphaBlock, &a0, &a1);
GenAlphaBitMask(a0, a1, AlphaBlock, AlphaBitMask, NULL/*AlphaOut*/);
VFS_Write(f, &a0, sizeof(byte));
VFS_Write(f, &a1, sizeof(byte));
VFS_Write(f, &AlphaBitMask, sizeof(byte) * 6 );
GetBlock(Block, Runner16, pix, x, y);
ChooseEndpoints(Block, &t0, &t1);
ex0 = max(t0, t1);
ex1 = min(t0, t1);
CorrectEndDXT1(&ex0, &ex1, 0);
VFS_Write(f, &ex0, sizeof(word));
VFS_Write(f, &ex1, sizeof(word));
BitMask = GenBitMask(ex0, ex1, 4, Block, NULL, NULL);
VFS_Write(f, &BitMask, sizeof(uint));
Count += 16;
}
Runner16 += Image->Width * Image->Height;
Runner8 += Image->Width * Image->Height;
}
break;
Runner16 += pix->width * pix->height;
Runner8 += pix->width * pix->height;
}
break;
}
ifree(Data);
ifree(Alpha);
} //else no 3dc
Mem_Free( Data );
Mem_Free( Alpha);
}
return Count;
}
bool dds_save_image( const char *name, rgbdata_t *pix, int saveformat )
{
file_t *file;
vfile_t *vhandle;
file = FS_Open( name, "wb" ); // create real file
vhandle = VFS_Open( file, "w" ); // create virtual file
dds_write_header( vhandle, pix, 0, saveformat );
if(!dds_compress_dxt( vhandle, saveformat, pix ))
{
Msg("dds_save_image: can't create dds file\n");
return false;
}
file = VFS_Close( vhandle ); // write buffer into hdd
FS_Close( file );
return true;
}

View File

@ -124,7 +124,7 @@ void Image_GetPaletteD1( void )
if(!d1palette_init)
{
Image_SetPalette( palette_d1, d_8toD1table );
d_8toD1table[255] = 247; // 247 is transparent
d_8toD1table[247] = 0; // 247 is transparent
d1palette_init = true;
}
d_currentpal = d_8toD1table;
@ -486,6 +486,77 @@ bool LoadWAL( char *name, char *buffer, int filesize )
return FS_AddMipmapToPack( buffer + ofs[0], image_width, image_height );
}
bool LoadFLD( char *name, char *buffer, int filesize )
{
flat_t flat;
vfile_t *f;
word column_loop, row_loop;
int i, column_offset, pointer_position, first_pos;
byte *Data, post, topdelta, length;
if(filesize < (int)sizeof(flat))
{
MsgWarn("LoadFLD: file (%s) have invalid size\n", name );
return false;
}
// stupid copypaste from DevIL, but it works
f = VFS_Create( buffer, filesize );
first_pos = VFS_Tell( f );
VFS_Read(f, &flat, sizeof(flat));
image_width = LittleShort( flat.width );
image_height = LittleShort( flat.height );
flat.desc[0] = LittleShort( flat.desc[0] );
flat.desc[1] = LittleShort( flat.desc[1] );
if(!Image_ValidSize( name )) return false;
Data = (byte *)Mem_Alloc( Sys.imagepool, image_width * image_height );
memset( Data, 247, image_width * image_height ); // set default transparency
image_num_layers = 1;
image_type = PF_RGBA_32;
for( column_loop = 0; column_loop < image_width; column_loop++ )
{
VFS_Read(f, &column_offset, sizeof(int));
pointer_position = VFS_Tell( f );
VFS_Seek( f, first_pos + column_offset, SEEK_SET );
while( 1 )
{
if(VFS_Read(f, &topdelta, 1) != 1) return false;
if(topdelta == 255) break;
if(VFS_Read(f, &length, 1) != 1) return false;
if(VFS_Read(f, &post, 1) != 1) return false;
for (row_loop = 0; row_loop < length; row_loop++)
{
if(VFS_Read(f, &post, 1) != 1) return false;
if(row_loop + topdelta < image_height)
Data[(row_loop + topdelta) * image_width + column_loop] = post;
}
VFS_Read(f, &post, 1);
}
VFS_Seek(f, pointer_position, SEEK_SET );
}
VFS_Close( f );
// scan for transparency
for (i = 0; i < image_width * image_height; i++)
{
if( Data[i] == 247 )
{
image_flags |= IMAGE_HAS_ALPHA;
break;
}
}
Image_GetPaletteD1();
FS_AddMipmapToPack( Data, image_width, image_height );
Mem_Free( Data );
return true;
}
/*
============
LoadLMP
@ -1843,6 +1914,7 @@ loadformat_t load_formats[] =
{"textures/%s%s.%s", "pcx", LoadPCX},
{"textures/%s%s.%s", "lmp", LoadLMP},
{"textures/%s%s.%s", "fnt", LoadFNT},
{"textures/%s%s.%s", "flat",LoadFLD},
{"textures/%s%s.%s", "pal", LoadPAL},
{"%s%s.%s", "dds", LoadDDS},
{"%s%s.%s", "tga", LoadTGA},
@ -1852,6 +1924,7 @@ loadformat_t load_formats[] =
{"%s%s.%s", "pcx", LoadPCX},
{"%s%s.%s", "lmp", LoadLMP},
{"%s%s.%s", "fnt", LoadFNT},
{"%s%s.%s", "flat",LoadFLD},
{"%s%s.%s", "pal", LoadPAL},
{NULL, NULL}
};
@ -2080,7 +2153,7 @@ void FS_FreeImage( rgbdata_t *pack )
image_size = 0;
}
bool SaveBMP( const char *filename, byte *data, int width, int height, bool alpha, int imagetype, byte *palette )
bool SaveBMP( const char *filename, rgbdata_t *pix )
{
file_t *pfile = NULL;
BITMAPFILEHEADER bmfh;
@ -2094,23 +2167,24 @@ bool SaveBMP( const char *filename, byte *data, int width, int height, bool alph
int i, rc = 0;
// bogus parameter check
if(!palette || !data ) return false;
if(!pix->palette || !pix->buffer )
return false;
pfile = FS_Open( filename, "wb");
if(!pfile) return false;
switch( imagetype )
switch( pix->type )
{
case PF_INDEXED_24:
case PF_INDEXED_32:
break;
default:
MsgWarn("SaveBMP: unsupported image type %s\n", PFDesc[imagetype].name );
MsgWarn("SaveBMP: unsupported image type %s\n", PFDesc[pix->type].name );
return false;
}
biTrueWidth = ((width + 3) & ~3);
cbBmpBits = biTrueWidth * height;
biTrueWidth = ((pix->width + 3) & ~3);
cbBmpBits = biTrueWidth * pix->height;
cbPalBytes = 256 * sizeof( RGBQUAD );
// Bogus file header check
@ -2124,9 +2198,9 @@ bool SaveBMP( const char *filename, byte *data, int width, int height, bool alph
FS_Write( pfile, &bmfh, sizeof(bmfh));
// size of structure
bmih.biSize = sizeof bmih;
bmih.biSize = sizeof(bmih);
bmih.biWidth = biTrueWidth;
bmih.biHeight = height;
bmih.biHeight = pix->height;
bmih.biPlanes = 1;
bmih.biBitCount = 8;
bmih.biCompression = BI_RGB;
@ -2138,7 +2212,7 @@ bool SaveBMP( const char *filename, byte *data, int width, int height, bool alph
// Write info header
FS_Write( pfile, &bmih, sizeof(bmih));
pb = palette;
pb = pix->palette;
// copy over used entries
for (i = 0; i < (int)bmih.biClrUsed; i++)
@ -2154,13 +2228,13 @@ bool SaveBMP( const char *filename, byte *data, int width, int height, bool alph
FS_Write( pfile, rgrgbPalette, cbPalBytes );
pbBmpBits = Mem_Alloc( Sys.imagepool, cbBmpBits );
pb = data;
pb += (height - 1) * width;
pb = pix->buffer;
pb += (pix->height - 1) * pix->width;
for(i = 0; i < bmih.biHeight; i++)
{
memmove(&pbBmpBits[biTrueWidth * i], pb, width);
pb -= width;
memmove(&pbBmpBits[biTrueWidth * i], pb, pix->width);
pb -= pix->width;
}
// write bitmap bits (remainder of file)
@ -2175,7 +2249,7 @@ bool SaveBMP( const char *filename, byte *data, int width, int height, bool alph
SaveTGA
=============
*/
bool SaveTGA( const char *filename, byte *data, int width, int height, bool alpha, int imagetype, byte *palette )
bool SaveTGA( const char *filename, rgbdata_t *pix )
{
int y, outsize, pixel_size;
const byte *bufend, *in;
@ -2183,44 +2257,44 @@ bool SaveTGA( const char *filename, byte *data, int width, int height, bool alph
const char *comment = "Generated by Xash ImageLib\0";
char mergedname[MAX_SYSPATH];
if(alpha) outsize = width * height * 4 + 18 + com_strlen(comment);
else outsize = width * height * 3 + 18 + com_strlen(comment);
if( pix->flags & IMAGE_HAS_ALPHA ) outsize = pix->width * pix->height * 4 + 18 + com_strlen(comment);
else outsize = pix->width * pix->height * 3 + 18 + com_strlen(comment);
com_strncpy(mergedname, filename, MAX_SYSPATH );
if(mergedname[0] == '*') mergedname[0] = '!'; // quake1 issues
buffer = (byte *)Malloc( outsize );
memset (buffer, 0, 18);
memset( buffer, 0, 18 );
// prepare header
buffer[0] = com_strlen(comment); // tga comment length
buffer[2] = 2; // uncompressed type
buffer[12] = (width >> 0) & 0xFF;
buffer[13] = (width >> 8) & 0xFF;
buffer[14] = (height >> 0) & 0xFF;
buffer[15] = (height >> 8) & 0xFF;
buffer[16] = alpha ? 32 : 24;
buffer[17] = alpha ? 8 : 0; // 8 bits of alpha
com_strncpy(buffer + 18, comment, com_strlen(comment));
buffer[12] = (pix->width >> 0) & 0xFF;
buffer[13] = (pix->width >> 8) & 0xFF;
buffer[14] = (pix->height >> 0) & 0xFF;
buffer[15] = (pix->height >> 8) & 0xFF;
buffer[16] = ( pix->flags & IMAGE_HAS_ALPHA ) ? 32 : 24;
buffer[17] = ( pix->flags & IMAGE_HAS_ALPHA ) ? 8 : 0; // 8 bits of alpha
com_strncpy( buffer + 18, comment, com_strlen(comment));
out = buffer + 18 + com_strlen(comment);
// get image description
switch( imagetype )
switch( pix->type )
{
case PF_RGB_24_FLIP:
case PF_RGB_24: pixel_size = 3; break;
case PF_RGBA_32: pixel_size = 4; break;
default:
MsgWarn("SaveTGA: unsupported image type %s\n", PFDesc[imagetype].name );
MsgWarn("SaveTGA: unsupported image type %s\n", PFDesc[pix->type].name );
return false;
}
// flip buffer
switch( imagetype )
switch( pix->type )
{
case PF_RGB_24_FLIP:
// glReadPixels rotating image at 180 degrees, flip it
for (in = data; in < data + width * height * pixel_size; in += pixel_size)
for (in = pix->buffer; in < pix->buffer + pix->width * pix->height * pixel_size; in += pixel_size)
{
*out++ = in[2];
*out++ = in[1];
@ -2230,36 +2304,48 @@ bool SaveTGA( const char *filename, byte *data, int width, int height, bool alph
case PF_RGB_24:
case PF_RGBA_32:
// swap rgba to bgra and flip upside down
for (y = height - 1; y >= 0; y--)
for (y = pix->height - 1; y >= 0; y--)
{
in = data + y * width * pixel_size;
bufend = in + width * pixel_size;
in = pix->buffer + y * pix->width * pixel_size;
bufend = in + pix->width * pixel_size;
for ( ;in < bufend; in += pixel_size)
{
*out++ = in[2];
*out++ = in[1];
*out++ = in[0];
if(alpha) *out++ = in[3];
if( pix->flags & IMAGE_HAS_ALPHA )
*out++ = in[3];
}
}
}
MsgDev(D_NOTE, "Writing %s[%d]\n", mergedname, alpha ? 32 : 24 );
MsgDev(D_NOTE, "Writing %s[%d]\n", mergedname, (pix->flags & IMAGE_HAS_ALPHA) ? 32 : 24 );
FS_WriteFile( mergedname, buffer, outsize );
Mem_Free( buffer );
return true;
}
/*
=============
SaveDDS
=============
*/
bool SaveDDS( const char *filename, rgbdata_t *pix )
{
return dds_save_image( filename, pix, PF_DXT5 ); //FIXME
}
typedef struct saveformat_s
{
char *formatstring;
char *ext;
bool (*savefunc)(char *filename, byte *data, int width, int height, bool alpha, int imagetype, byte *pal );
bool (*savefunc)( char *filename, rgbdata_t *pix );
} saveformat_t;
saveformat_t save_formats[] =
{
{"%s%s.%s", "dds", SaveDDS},
{"%s%s.%s", "tga", SaveTGA},
{"%s%s.%s", "bmp", SaveBMP},
{NULL, NULL}
@ -2278,7 +2364,7 @@ void FS_SaveImage( const char *filename, rgbdata_t *pix )
const char *ext = FS_FileExtension( filename );
char path[128], savename[128];
bool anyformat = !stricmp(ext, "") ? true : false;
int i, filesize = 0;
int filesize = 0;
byte *data;
bool has_alpha = false;
@ -2298,7 +2384,7 @@ void FS_SaveImage( const char *filename, rgbdata_t *pix )
if( anyformat || !com_stricmp( ext, format->ext ))
{
com_sprintf( path, format->formatstring, savename, "", format->ext );
if( format->savefunc( path, data, pix->width, pix->height, has_alpha, pix->type, pix->palette ))
if( format->savefunc( path, pix ))
return; // saved
}
}

View File

@ -14,6 +14,7 @@ FILE *logfile;
dll_info_t common_dll = { "common.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
dll_info_t engine_dll = { "engine.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
dll_info_t editor_dll = { "editor.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
dll_info_t idconv_dll = { "comres.dll", NULL, "CreateAPI", NULL, NULL, true, sizeof(launch_exp_t) };
static const char *show_credits = "\n\n\n\n\tCopyright XashXT Group 2007 ©\n\t\
All Rights Reserved\n\n\t Visit www.xash.ru\n";
@ -250,6 +251,16 @@ void Sys_LookupInstance( void )
com_strcpy(Sys.log_path, "editor.log" ); // xash3d root directory
com_strcpy(Sys.caption, va("Xash3D Editor ver.%g", XASH_VERSION ));
}
else if(!com_strcmp(Sys.progname, "host_convertor"))
{
Sys.app_name = HOST_CONVERTOR;
Sys.con_readonly = true;
Sys.log_active = true; // always create log
if(!Sys.debug) Sys.con_showalways = true;
Sys.linked_dll = &idconv_dll; // pointer to comres.dll info
com_sprintf(Sys.log_path, "%s/convert.log", sys_rootdir ); // same as .exe file
com_strcpy(Sys.caption, va("Resource Convertor ver.%g", XASH_VERSION ));
}
else if(!com_strcmp(Sys.progname, "bsplib"))
{
Sys.app_name = BSPLIB;
@ -334,6 +345,7 @@ void Sys_CreateInstance( void )
case HOST_NORMAL:
case HOST_DEDICATED:
case HOST_EDITOR:
case HOST_CONVERTOR:
case BSPLIB:
case QCCLIB:
case ROQLIB:
@ -377,6 +389,7 @@ void Sys_CreateInstance( void )
break;
case HOST_EDITOR:
Con_ShowConsole( false );
case HOST_CONVERTOR:
case BSPLIB:
case QCCLIB:
case ROQLIB:

7
launch/idconv/idconv.c Normal file
View File

@ -0,0 +1,7 @@
//=======================================================================
// Copyright (C) XashXT Group 2007
//=======================================================================
#include "../rundll.h"
Run32( host_convertor );

28
launch/idconv/idconv.rc Normal file
View File

@ -0,0 +1,28 @@
#include <winver.h>
#define IDI_ICON1 101
#define VER_FILEVERSION 0,1
#define VER_FILEVERSION_STR "0.1"
#define VER_PRODUCTVERSION 0,1
#define VER_PRODUCTVERSION_STR "0.1"
#define VER_FILEFLAGSMASK VS_FF_PRERELEASE | VS_FF_PATCHED
#define VER_FILEFLAGS VS_FF_PRERELEASE
#define VER_FILEOS VOS__WINDOWS32
#define VER_FILETYPE VFT_DLL
#define VER_FILESUBTYPE VFT2_UNKNOWN
#define VER_COMPANYNAME_STR "XashXT Group"
#define VER_LEGALCOPYRIGHT_STR "XashXT 2007"
#define VER_PRODUCTNAME_STR "idconv"
#define VER_ANSICP
#define VER_FILEDESCRIPTION_STR "Doom\Quake\Hl Convertor"
#define VER_ORIGINALFILENAME_STR "idconv.exe"
#define VER_INTERNALNAME_STR "host_convertor"
#include <common.ver>
IDI_ICON1 ICON DISCARDABLE "tool.ico"

View File

@ -0,0 +1,28 @@
#=============================
# Makefile to build xash utils
# Author: Unkle Mike <xash.ru>
#
# Please associate .nmake files as NMAKE.EXE "/f" "%1" for build this file
#=============================
!include <win32.mak>
MAINTARGET = idconv
OBJS = $(MAINTARGET).obj
RES = $(MAINTARGET).rc
default: $(MAINTARGET).exe
$(MAINTARGET).exe: $(MAINTARGET).obj idconv.res
$(link) $(OBJS) idconv.res /out:"idconv.exe" /subsystem:windows /opt:nowin98 /nodefaultlib:"libc.lib"
@del $(MAINTARGET).obj $(MAINTARGET).lib $(MAINTARGET).exp $(MAINTARGET).res > nul
@copy $(MAINTARGET).exe D:\Xash3D\bin\$(MAINTARGET).exe
@del $(MAINTARGET).exe
@echo ‘ª®¯¨à®¢ ­® ä ©«®¢: 1.
clean:
.cpp.obj:
$(CC) $(CFLAGS) /c $<
idconv.res : idconv.rc
$(RC) $(RCFLAGS) /r idconv.rc

BIN
launch/idconv/tool.ico Normal file

Binary file not shown.

After

Width:  |  Height:  |  Size: 4.6 KiB

View File

@ -136,6 +136,10 @@ SOURCE=.\common\filesystem.c
# End Source File
# Begin Source File
SOURCE=.\common\image_save.c
# End Source File
# Begin Source File
SOURCE=.\common\imglib.c
# End Source File
# Begin Source File

View File

@ -20,6 +20,10 @@ cd ..
cd imglib
makefile.nmake
cd ..
cd idconv
makefile.nmake
cd ..
cd install
makefile.nmake

42
public/basefiles.h Normal file
View File

@ -0,0 +1,42 @@
//=======================================================================
// Copyright XashXT Group 2007 ©
// basefiles.h - xash supported formats
//=======================================================================
#ifndef BASE_FILES_H
#define BASE_FILES_H
/*
==============================================================================
.aur particle file format
==============================================================================
*/
#define IDAURORAHEADER (('R'<<24)+('U'<<16)+('A'<<8)+'I') // little-endian "IAUR"
#define AURORA_VERSION 1
typedef struct
{
int width, height;
int origin_x, origin_y; // raster coordinates inside pic
char name[MAX_SKINNAME]; // name of pcx file
} daurframe_t;
typedef struct
{
int ident;
int version;
int numframes;
// aurora description
float startcolor[3]; // RGBA
float finalcolor[3]; // RGBA
float startalpha; // alpha-value
float finalalpha;
float framerate;
byte rendermode;
dsprframe_t frames[1]; // variable sized
} daurora_t;
#endif//BASE_FILES_H

View File

@ -131,6 +131,7 @@ enum host_state
HOST_OFFLINE = 0, // host_init( funcname *arg ) same much as:
HOST_NORMAL, // "host_shared"
HOST_DEDICATED, // "host_dedicated"
HOST_CONVERTOR, // "host_convertor"
HOST_EDITOR, // "host_editor"
BSPLIB, // "bsplib"
IMGLIB, // "imglib"

View File

@ -1544,6 +1544,20 @@ typedef struct wal_s
.LMP image format (Quake1 gfx lumps)
========================================================================
*/
typedef struct flat_s
{
short width;
short height;
short desc[2]; // probably not used
} flat_t;
/*
========================================================================
.LMP image format (Quake1 gfx lumps)
========================================================================
*/
typedef struct lmp_s

View File

@ -15,6 +15,18 @@ Package=<4>
###############################################################################
Project: "comres"=".\comres\comres.dsp" - Package Owner=<4>
Package=<5>
{{{
}}}
Package=<4>
{{{
}}}
###############################################################################
Project: "editor"=".\editor\editor.dsp" - Package Owner=<4>
Package=<5>