Complete disaster-recovery snapshot: engine/game source, game data assets, VC6 toolchain + DX SDKs, build outputs, deployed game, and _UNUSED archive. Large binaries in Git LFS; text preserved byte-for-byte (core.autocrlf=false, no eol attributes). See RECOVERY.md for the one-clone rebuild procedure.
610 lines
13 KiB
C++
610 lines
13 KiB
C++
#include<string.h>
|
|
#include"image.h"
|
|
#include<GameOS\GameOS.hpp>
|
|
|
|
int Image::IsTga()
|
|
{
|
|
char *spos;
|
|
spos=NULL;
|
|
int i,slen=strlen(fname);
|
|
for(i=slen-1;i>=0 && fname[i]!='.';i--);
|
|
if(i<0) return 0;
|
|
if(fname[i]=='.') spos=fname+i+1;
|
|
return !strcmpi("tga",spos);
|
|
}
|
|
|
|
void Image::GetTgaInfo(Stuff::FileStream *stream)
|
|
{
|
|
int i;
|
|
int cm_index,cm_length,cm_esize,has_color_map,tgaid,xpos,ypos,sta,idlen,ttype;
|
|
xpos=ypos=tgaid=has_color_map=cm_index=cm_length=cm_esize=sta=idlen=ttype=0;
|
|
|
|
stream->ReadBytes(&idlen,1);
|
|
stream->ReadBytes(&has_color_map,1);
|
|
stream->ReadBytes(&tgaid,1);
|
|
stream->ReadBytes(&cm_index,2);
|
|
stream->ReadBytes(&cm_length,2);
|
|
stream->ReadBytes(&cm_esize,1);
|
|
|
|
cm_esize>>=3;
|
|
|
|
if((tgaid!=1 && tgaid!=2 && tgaid!=10 && tgaid!=3) || (has_color_map && cm_esize!=3) )
|
|
{
|
|
char msg[512];
|
|
sprintf(msg,"Unsupported Tga Data Format %s",fname);
|
|
GENNFERR(msg); //confirm uncompressed rgb
|
|
}
|
|
|
|
stream->ReadBytes(&xpos,2);
|
|
stream->ReadBytes(&ypos,2);
|
|
xlen=ylen=0;
|
|
stream->ReadBytes(&xlen,2);
|
|
stream->ReadBytes(&ylen,2);
|
|
|
|
vxlen=xlen;
|
|
vylen=ylen;
|
|
|
|
stream->ReadBytes(&ttype,1);
|
|
if(ttype==32) {itype=ITYPE_RGB; Bpp=32;}
|
|
if(ttype==24) {itype=ITYPE_RGB; Bpp=24;}
|
|
if(ttype==16) {itype=ITYPE_RGB; Bpp=16;}
|
|
if(ttype==8) {itype=ITYPE_INDEXED; Bpp=8; MakeGrayscalePalette();}
|
|
|
|
int byte_per_pix=Bpp>>3;
|
|
|
|
stream->ReadBytes(&sta,1);
|
|
|
|
|
|
if(has_color_map)
|
|
{
|
|
ImgRGBColor col;
|
|
if(cm_esize==3)
|
|
for(i=cm_index;i<cm_index+cm_length;i++)
|
|
{
|
|
col.r=col.g=col.b=0;
|
|
|
|
stream->ReadBytes(&col.r,1);
|
|
stream->ReadBytes(&col.g,1);
|
|
stream->ReadBytes(&col.b,1);
|
|
if(i<256)
|
|
pal[i]=col;
|
|
}
|
|
}
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0xff0000,0x00ff00,0x0000ff);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
}
|
|
}
|
|
|
|
|
|
void Image::LoadTga(Stuff::FileStream *stream)
|
|
{
|
|
int i;
|
|
BYTE *dpt;
|
|
|
|
int cm_index,cm_length,cm_esize,has_color_map,tgaid,xpos,ypos,sta,idlen,ttype;
|
|
xpos=ypos=tgaid=has_color_map=cm_index=cm_length=cm_esize=sta=idlen=ttype=0;
|
|
|
|
stream->ReadBytes(&idlen,1);
|
|
stream->ReadBytes(&has_color_map,1);
|
|
stream->ReadBytes(&tgaid,1);
|
|
stream->ReadBytes(&cm_index,2);
|
|
stream->ReadBytes(&cm_length,2);
|
|
stream->ReadBytes(&cm_esize,1);
|
|
|
|
cm_esize>>=3;
|
|
|
|
|
|
if((tgaid!=1 && tgaid!=2 && tgaid!=10 && tgaid!=3) || (has_color_map && cm_esize!=3) )
|
|
{
|
|
char msg[512];
|
|
sprintf(msg,"Unsupported Tga Data Format %s",fname);
|
|
GENNFERR(msg); //confirm uncompressed rgb
|
|
}
|
|
|
|
stream->ReadBytes(&xpos,2);
|
|
stream->ReadBytes(&ypos,2);
|
|
xlen=ylen=0;
|
|
stream->ReadBytes(&xlen,2);
|
|
stream->ReadBytes(&ylen,2);
|
|
|
|
vxlen=xlen;
|
|
vylen=ylen;
|
|
|
|
stream->ReadBytes(&ttype,1);
|
|
if(ttype==32) {itype=ITYPE_RGB; Bpp=32;}
|
|
if(ttype==24) {itype=ITYPE_RGB; Bpp=24;}
|
|
if(ttype==16) {itype=ITYPE_RGB; Bpp=16;}
|
|
if(ttype==8) {itype=ITYPE_INDEXED; Bpp=8; MakeGrayscalePalette();}
|
|
|
|
int byte_per_pix=Bpp>>3;
|
|
|
|
stream->ReadBytes(&sta,1);
|
|
|
|
|
|
|
|
if(has_color_map)
|
|
{
|
|
ImgRGBColor col;
|
|
if(cm_esize==3)
|
|
for(i=cm_index;i<cm_index+cm_length;i++)
|
|
{
|
|
col.r=col.g=col.b=0;
|
|
|
|
stream->ReadBytes(&col.r,1);
|
|
stream->ReadBytes(&col.g,1);
|
|
stream->ReadBytes(&col.b,1);
|
|
if(i<256)
|
|
pal[i]=col;
|
|
}
|
|
}
|
|
|
|
IAlloc();
|
|
dpt=Lock();
|
|
BYTE *dat=dpt;
|
|
|
|
int x,y,j;
|
|
//get data
|
|
switch(tgaid)
|
|
{
|
|
case 1: //Raw ColorMap
|
|
case 2: //Raw Image
|
|
case 3: //UnCompressed BW Image
|
|
if(sta&0x20)
|
|
{
|
|
/*
|
|
for(y=0;y<ylen;y++,dpt+=Pitch-byte_per_pix*xlen)
|
|
for(x=0;x<xlen;x++,dpt+=byte_per_pix)
|
|
for(j=byte_per_pix-1;j>=0;j--)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
*/
|
|
|
|
stream->ReadBytes(dpt,Pitch*ylen);
|
|
dpt+=Pitch*ylen;
|
|
}
|
|
else //inverted image
|
|
{
|
|
|
|
dpt=dat+((ylen-1)*Pitch);
|
|
for(y=0;y<ylen;y++,dpt-=Pitch)
|
|
stream->ReadBytes(dpt,Pitch);
|
|
|
|
/*
|
|
for(x=0;x<xlen;x++)
|
|
{
|
|
dpt=dat+y*Pitch+x*byte_per_pix;
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
}
|
|
*/
|
|
}
|
|
break;
|
|
|
|
|
|
case 10: //RLEImage
|
|
{
|
|
int PixelSum=xlen*ylen,Pixs,tag;
|
|
BYTE tmpval[4];
|
|
|
|
if(sta&0x20)
|
|
{
|
|
while(PixelSum>0)
|
|
{
|
|
tag=0;
|
|
stream->ReadBytes(&tag,1);
|
|
Pixs=(tag&0x7F)+1;
|
|
if(tag&0x80)
|
|
{
|
|
stream->ReadBytes(tmpval,byte_per_pix);
|
|
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=tmpval[j];
|
|
|
|
}
|
|
else
|
|
{
|
|
int bread=byte_per_pix*Pixs;
|
|
stream->ReadBytes(dpt,bread);
|
|
dpt+=bread;
|
|
|
|
}
|
|
PixelSum-=Pixs;
|
|
}
|
|
}
|
|
else //inverted image
|
|
{
|
|
y=x=0;
|
|
while(PixelSum>0)
|
|
{
|
|
tag=0;
|
|
stream->ReadBytes(&tag,1);
|
|
Pixs=(tag&0x7F)+1;
|
|
if(tag&0x80)
|
|
{
|
|
stream->ReadBytes(tmpval,byte_per_pix);
|
|
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
{
|
|
dpt=dat+(ylen-y)*Pitch+x*(Bpp>>3);
|
|
stream->ReadBytes(dpt,byte_per_pix);
|
|
x++;
|
|
if(x>=xlen) {x=0; y++;}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
{
|
|
dpt=dat+(ylen-y)*Pitch+x*(Bpp>>3);
|
|
stream->ReadBytes(dpt,byte_per_pix);
|
|
x++;
|
|
if(x>=xlen) {x=0; y++;}
|
|
}
|
|
|
|
}
|
|
PixelSum-=Pixs;
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
UnLock();
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0xff0000,0x00ff00,0x0000ff);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
}
|
|
}
|
|
|
|
|
|
void Image::SaveTga(Stuff::FileStream *stream)
|
|
{
|
|
int i;
|
|
WORD tmpint;
|
|
BYTE tbte;
|
|
BYTE *cdata;
|
|
|
|
tbte=0; stream->WriteBytes(&tbte,1); //Size of Header
|
|
tbte=0; stream->WriteBytes(&tbte,1); //ColorMap Flag
|
|
tbte=0x02; stream->WriteBytes(&tbte,1); //Image Type
|
|
|
|
for(i=3;i<=7;i++) //ColorMap
|
|
{ tbte=0; stream->WriteBytes(&tbte,1); }
|
|
|
|
tmpint=0; stream->WriteBytes(&tmpint,2); //Xorg
|
|
tmpint=0; stream->WriteBytes(&tmpint,2); //YOrg
|
|
|
|
|
|
stream->WriteBytes(&xlen,2);
|
|
stream->WriteBytes(&ylen,2);
|
|
tbte=(BYTE)Bpp; stream->WriteBytes(&tbte,1);
|
|
tbte=0x20; stream->WriteBytes(&tbte,1); //Flag
|
|
|
|
if(Bpp==24)
|
|
MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
|
|
else
|
|
if(Bpp==32)
|
|
MaskTo(RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000));
|
|
|
|
cdata=Lock();
|
|
stream->WriteBytes(cdata,(int)xlen*ylen*(Bpp>>3));
|
|
|
|
UnLock();
|
|
}
|
|
|
|
void Image::LoadTga(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::ReadOnly);
|
|
LoadTga(&stream);
|
|
// stream.Close();
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
void Image::GetTgaInfo(FILE *fl)
|
|
{
|
|
int i,idlen,sta,pos;
|
|
int xpos,ypos;
|
|
int tgaid;
|
|
int has_color_map;
|
|
pos=ftell(fl);
|
|
idlen=getc(fl); //get idlenght
|
|
has_color_map=getc(fl);
|
|
tgaid=getc(fl);
|
|
int cm_index,cm_length,cm_esize;
|
|
cm_index=getc(fl); cm_index|=getc(fl)<<8;
|
|
cm_length=getc(fl); cm_length|=getc(fl)<<8;
|
|
cm_esize=getc(fl)>>3;
|
|
|
|
if((tgaid!=1 && tgaid!=2 && tgaid!=10 && tgaid!=3) || (has_color_map && cm_esize!=3) )
|
|
{
|
|
char msg[512];
|
|
sprintf(msg,"Unsupported Tga Data Format %s",fname);
|
|
GENNFERR(msg); //confirm uncompressed rgb
|
|
}
|
|
|
|
xpos=getc(fl); xpos|=getc(fl)<<8;
|
|
ypos=getc(fl); ypos|=getc(fl)<<8;
|
|
xlen=getc(fl); xlen|=getc(fl)<<8;
|
|
ylen=getc(fl); ylen|=getc(fl)<<8;
|
|
|
|
vxlen=xlen;
|
|
vylen=ylen;
|
|
|
|
int ttype=getc(fl);
|
|
if(ttype==32) {itype=ITYPE_RGB; Bpp=32;}
|
|
if(ttype==24) {itype=ITYPE_RGB; Bpp=24;}
|
|
if(ttype==16) {itype=ITYPE_RGB; Bpp=16;}
|
|
if(ttype==8) {itype=ITYPE_INDEXED; Bpp=8; MakeGrayscalePalette();}
|
|
|
|
int byte_per_pix=Bpp>>3;
|
|
|
|
sta=getc(fl);
|
|
|
|
|
|
if(has_color_map)
|
|
{
|
|
ImgRGBColor col;
|
|
if(cm_esize==3)
|
|
for(i=cm_index;i<cm_index+cm_length;i++)
|
|
{
|
|
col.r=getc(fl);
|
|
col.g=getc(fl);
|
|
col.b=getc(fl);
|
|
if(i<256)
|
|
pal[i]=col;
|
|
}
|
|
}
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0xff0000,0x00ff00,0x0000ff);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
}
|
|
}
|
|
|
|
void Image::GetTgaInfo(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::ReadOnly);
|
|
GetTgaInfo(&stream);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
void Image::LoadTga(FILE *fl)
|
|
{
|
|
int i,idlen,sta,pos;
|
|
int xpos,ypos;
|
|
int tgaid;
|
|
int has_color_map;
|
|
BYTE *dpt;
|
|
pos=ftell(fl);
|
|
idlen=getc(fl); //get idlenght
|
|
has_color_map=getc(fl);
|
|
tgaid=getc(fl);
|
|
int cm_index,cm_length,cm_esize;
|
|
cm_index=getc(fl); cm_index|=getc(fl)<<8;
|
|
cm_length=getc(fl); cm_length|=getc(fl)<<8;
|
|
cm_esize=getc(fl)>>3;
|
|
|
|
if((tgaid!=1 && tgaid!=2 && tgaid!=10 && tgaid!=3) || (has_color_map && cm_esize!=3) )
|
|
{
|
|
char msg[512];
|
|
sprintf(msg,"Unsupported Tga Data Format %s",fname);
|
|
GENNFERR(msg); //confirm uncompressed rgb
|
|
}
|
|
|
|
xpos=getc(fl); xpos|=getc(fl)<<8;
|
|
ypos=getc(fl); ypos|=getc(fl)<<8;
|
|
xlen=getc(fl); xlen|=getc(fl)<<8;
|
|
ylen=getc(fl); ylen|=getc(fl)<<8;
|
|
|
|
vxlen=xlen;
|
|
vylen=ylen;
|
|
|
|
int ttype=getc(fl);
|
|
if(ttype==32) {itype=ITYPE_RGB; Bpp=32;}
|
|
if(ttype==24) {itype=ITYPE_RGB; Bpp=24;}
|
|
if(ttype==16) {itype=ITYPE_RGB; Bpp=16;}
|
|
if(ttype==8) {itype=ITYPE_INDEXED; Bpp=8; MakeGrayscalePalette();}
|
|
|
|
int byte_per_pix=Bpp>>3;
|
|
|
|
sta=getc(fl);
|
|
|
|
IAlloc();
|
|
dpt=Lock();
|
|
BYTE *dat=dpt;
|
|
|
|
if(has_color_map)
|
|
{
|
|
ImgRGBColor col;
|
|
if(cm_esize==3)
|
|
for(i=cm_index;i<cm_index+cm_length;i++)
|
|
{
|
|
col.r=getc(fl);
|
|
col.g=getc(fl);
|
|
col.b=getc(fl);
|
|
if(i<256)
|
|
pal[i]=col;
|
|
}
|
|
}
|
|
int x,y,j;
|
|
//get data
|
|
switch(tgaid)
|
|
{
|
|
case 1: //Raw ColorMap
|
|
case 2: //Raw Image
|
|
case 3: //UnCompressed BW Image
|
|
if(sta&0x20)
|
|
{
|
|
/*
|
|
for(y=0;y<ylen;y++,dpt+=Pitch-byte_per_pix*xlen)
|
|
for(x=0;x<xlen;x++,dpt+=byte_per_pix)
|
|
for(j=byte_per_pix-1;j>=0;j--)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
*/
|
|
|
|
for(y=0;y<ylen;y++,dpt+=Pitch)
|
|
fread(dpt,Pitch,1,fl);
|
|
|
|
}
|
|
else //inverted image
|
|
{
|
|
|
|
dpt=dat+((ylen-1)*Pitch);
|
|
for(y=0;y<ylen;y++,dpt-=Pitch)
|
|
fread(dpt,Pitch,1,fl);
|
|
|
|
/*
|
|
for(x=0;x<xlen;x++)
|
|
{
|
|
dpt=dat+y*Pitch+x*byte_per_pix;
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
}
|
|
*/
|
|
}
|
|
break;
|
|
|
|
|
|
case 10: //RLEImage
|
|
{
|
|
int PixelSum=xlen*ylen,Pixs,tag;
|
|
BYTE tmpval[4];
|
|
|
|
if(sta&0x20)
|
|
{
|
|
while(PixelSum>0)
|
|
{
|
|
tag=getc(fl);
|
|
Pixs=(tag&0x7F)+1;
|
|
if(tag&0x80)
|
|
{
|
|
for(j=0;j<byte_per_pix;j++)
|
|
tmpval[j]=getc(fl);
|
|
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=tmpval[j];
|
|
|
|
}
|
|
else
|
|
{
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
|
|
}
|
|
PixelSum-=Pixs;
|
|
}
|
|
}
|
|
else //inverted image
|
|
{
|
|
y=x=0;
|
|
while(PixelSum>0)
|
|
{
|
|
tag=getc(fl);
|
|
Pixs=(tag&0x7F)+1;
|
|
if(tag&0x80)
|
|
{
|
|
for(j=0;j<byte_per_pix;j++)
|
|
tmpval[j]=getc(fl);
|
|
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
{
|
|
dpt=dat+(ylen-y)*Pitch+x*(Bpp>>3);
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=tmpval[j];
|
|
x++;
|
|
if(x>=xlen) {x=0; y++;}
|
|
}
|
|
|
|
}
|
|
else
|
|
{
|
|
for(i=0;i<Pixs;i++,dpt+=byte_per_pix)
|
|
{
|
|
dpt=dat+(ylen-y)*Pitch+x*(Bpp>>3);
|
|
for(j=0;j<byte_per_pix;j++)
|
|
dpt[j]=(BYTE)getc(fl);
|
|
x++;
|
|
if(x>=xlen) {x=0; y++;}
|
|
}
|
|
|
|
}
|
|
PixelSum-=Pixs;
|
|
}
|
|
|
|
}
|
|
}
|
|
break;
|
|
}
|
|
|
|
UnLock();
|
|
if(itype!=ITYPE_INDEXED)
|
|
{
|
|
if(Bpp==24)
|
|
Mask.Set(0xff0000,0x00ff00,0x0000ff);
|
|
else
|
|
if(Bpp==32)
|
|
Mask.Set(0x00ff0000,0x0000ff00,0x000000ff,0xff000000);
|
|
}
|
|
}
|
|
|
|
void Image::SaveTga(char *str)
|
|
{
|
|
Stuff::FileStream stream;
|
|
stream.Open(str,Stuff::FileStream::WriteOnly);
|
|
SaveTga(&stream);
|
|
strcpy(fname,str);
|
|
}
|
|
|
|
void Image::SaveTga(FILE *fl)
|
|
{
|
|
int i;
|
|
WORD tmpint;
|
|
BYTE tbte;
|
|
BYTE *cdata;
|
|
|
|
tbte=0; fwrite(&tbte,1,1,fl); //Size of Header
|
|
tbte=0; fwrite(&tbte,1,1,fl); //ColorMap Flag
|
|
tbte=0x02; fwrite(&tbte,1,1,fl); //Image Type
|
|
|
|
for(i=3;i<=7;i++) //ColorMap
|
|
{ tbte=0; fwrite(&tbte,1,1,fl); }
|
|
|
|
tmpint=0; fwrite(&tmpint,1,2,fl); //Xorg
|
|
tmpint=0; fwrite(&tmpint,1,2,fl); //YOrg
|
|
|
|
|
|
fwrite(&xlen,1,2,fl);
|
|
fwrite(&ylen,1,2,fl);
|
|
tbte=(BYTE)Bpp; fwrite(&tbte,1,1,fl);
|
|
tbte=0x20; fwrite(&tbte,1,1,fl); //Flag
|
|
|
|
if(Bpp==24)
|
|
MaskTo(RGBMask(0xff0000,0x00ff00,0x0000ff));
|
|
else
|
|
if(Bpp==32)
|
|
MaskTo(RGBMask(0x00ff0000,0x0000ff00,0x000000ff,0xff000000));
|
|
|
|
cdata=Lock();
|
|
fwrite(cdata,1,(int)xlen*ylen*(Bpp>>3),fl); //Image Data
|
|
|
|
UnLock();
|
|
}
|