#include "uop.h"
#include <SDL/SDL.h>
#include <SDL/SDL_endian.h>
#include <iostream>
#include <fstream>
#include "gumps.h"
#include "uopconfig.h"
extern UOPConfig *config;
extern Gumps *gumps;
extern SDL_Surface *screen;
Hue::Hue()
{
loaded=false;
}
Hue::~Hue()
{
}
Hue &Gumps::getHue(Uint16 hue)
{
if (hue) hue--;
Hue &idx=hues[hue];
if (idx.loaded) return idx;
Uint16 num=hue>>3;
Uint32 offset=num*708+(hue&7)*88+4;
huefile.seekg(offset);
char source[88];
huefile.read(source,44*2);
Uint16 *src=(Uint16*)source;
for (int i=0;i<32;i++)
idx.colors[i]=SDL_SwapLE16(*src++);
idx.start=SDL_SwapLE16(*src++);
idx.end=SDL_SwapLE16(*src++);
idx.loaded=true;
return idx;
}
GumpIndex::GumpIndex()
{
offset=size=0xffffffff;
x=y=width=height=0;
}
GumpIndex::~GumpIndex()
{
}
Gumps::Gumps()
{
string gumpfname=config->encapDatLoc("gumpidx.mul");
idxfile.open(gumpfname.c_str(),ios::in|ios::binary);
if (!idxfile.is_open())
{
cerr<<"Couldn't open "<<gumpfname<<endl;
exit(1);
}
string huefname=config->encapDatLoc("hues.mul");
huefile.open(huefname.c_str(),ios::in|ios::binary);
if (!huefile.is_open())
{
cerr<<"Couldn't open "<<huefname<<endl;
exit(1);
}
}
Gumps::~Gumps()
{
idxfile.close();
huefile.close();
}
GumpIndex &Gumps::getIndex(int gump)
{
GumpIndex &idx=gumps[gump];
if (idx.offset!=0xffffffff)
return idx;
idx.width=idx.height=0;
if (!gump)
return idx;
Uint32 offset=gump*12;
Uint8 buffer[12];
idxfile.seekg(offset);
idxfile.read((char *)buffer,12);
idx.offset=SDL_SwapLE32(*(Uint32 *)buffer);
idx.size=SDL_SwapLE32(*(Uint32 *)(buffer+4));
idx.height=SDL_SwapLE16(*(Uint16 *)(buffer+8));
idx.width=SDL_SwapLE16(*(Uint16 *)(buffer+10));
idx.patched=false;
return idx;
}
void Gumps::setIndex(int gump,GumpIndex &index)
{
GumpIndex &idx=gumps[gump];
idx.offset=index.offset;
idx.size=index.size;
idx.height=index.height;
idx.width=index.width;
idx.patched=true;
}
Gump::Gump()
{
width=-1;
height=-1;
for (int i=0;i<9;i++)
children[i]=NULL;
}
Gump::~Gump()
{
for (int i=0;i<9;i++)
if (children[i])
delete children[i];
}
void Gump::load(Uint16 gump,Sint16 w,Sint16 h,bool tiled)
{
load(gump,0,0,w,h,tiled);
}
void Gump::load(Uint16 gump,Sint16 offsetx, Sint16 offsety, Sint16 w,Sint16 h,bool tiled)
{
//Uint32 offset;
Uint16 *scr,val,run,y,x,gumpWidth,gumpHeight;
ifstream gumpfile;
GumpIndex &idx=gumps->getIndex(gump);
gumpHeight=idx.height;
gumpWidth=idx.width;
if (gumpHeight <= 0 || gumpWidth <= 0)
{
cerr << "Warning: Gump::load aborted because width/height is less than 1." << endl;
return;
}
if (w<0) w=gumpWidth;
if (h<0) h=gumpHeight;
if (w<=0 || h<=0) return;
if (width==w && height==h)
return;
if (this->data)
delete [] this->data;
this->offsetx=offsetx;
this->offsety=offsety;
Uint8 *fdata = new Uint8[idx.size];
Uint16 *gdata = new Uint16[gumpHeight*gumpWidth];
string gumpfname;
if (idx.patched)
gumpfname=config->encapDatLoc("verdata.mul");
else
gumpfname=config->encapDatLoc("gumpart.mul");
gumpfile.open(gumpfname.c_str(),ios::in|ios::binary);
if (!gumpfile.is_open())
{
cerr<<"Error opening "<<gumpfname<<endl;
exit(1);
}
gumpfile.seekg(idx.offset);
gumpfile.read((char *)fdata,idx.size);
gumpfile.close();
Uint16 *sdata=gdata;
Uint32 row;
Uint16 ty;
Uint32 *g;
for (y=0;y<gumpHeight;y++)
{
ty=y<<2;
row=SDL_SwapLE32(*(Uint32*)(fdata+ty));
g=(Uint32*)(fdata+(row<<2));
for (x=0;x<gumpWidth;)
{
row=SDL_SwapLE32(*g++);
run=row>>16;
val=((row&0x7fe0)<<1)|(row&0x1f);
x+=run;
while (run--) *sdata++=val;
}
}
delete [] fdata;
height=h;
width=w;
if (tiled)
{
data=new Uint16[width*height];
scr=data;
for (y=0;y<height;y++)
{
sdata=gdata+(y%gumpHeight)*gumpWidth;
for (x=0;x<width;x++)
*scr++=sdata[x%gumpWidth];
}
}
else
{
if (width>gumpWidth) width=gumpWidth;
if (height>gumpHeight) height=gumpHeight;
data=new Uint16[width*height];
scr=data;
sdata=gdata;
Uint16 gdelta=gumpWidth-width;
for (y=0;y<height;y++,sdata+=gdelta)
for (x=0;x<width;x++)
*scr++=*sdata++;
}
delete [] gdata;
}
void Gump::load(Uint16 *gumpIDs,Sint16 w,Sint16 h)
{
if (width==w && height==h)
return;
for (int i=0;i<9;i++)
if (children[i]) delete children[i];
GumpIndex &UL=gumps->getIndex(gumpIDs[0]);
GumpIndex &BR=gumps->getIndex(gumpIDs[8]);
Uint16 topX,topY,topW,topH;
Uint16 midX,midY,midW,midH;
Uint16 botX,botY,botW,botH;
topX=topY=0;
topW=UL.width; if (w<topW) topW=w;
topH=UL.height; if (h<topH) topH=h;
botX=w-BR.width; if (w<BR.width) botX=0;
botY=h-BR.height; if (h<BR.height) botY=0;
botW=w-botX;
botH=h-botY;
midX=topW;
midY=topH;
midW=botX-midX; if (botX<midX) midW=0;
midH=botY-midY; if (botY<midY) midH=0;
children[0]=new Gump();
children[0]->load(gumpIDs[0],topX,topY,topW,topH,false);
children[1]=new Gump();
children[1]->load(gumpIDs[1],midX,topY,midW,topH,true);
children[2]=new Gump();
children[2]->load(gumpIDs[2],botX,topY,botW,topH,false);
children[3]=new Gump();
children[3]->load(gumpIDs[3],topX,midY,topW,midH,true);
children[4]=new Gump();
children[4]->load(gumpIDs[4],midX,midY,midW,midH,true);
children[5]=new Gump();
children[5]->load(gumpIDs[5],botX,midY,botW,midH,true);
children[6]=new Gump();
children[6]->load(gumpIDs[6],topX,botY,topW,botH,false);
children[7]=new Gump();
children[7]->load(gumpIDs[7],midX,botY,midW,botH,true);
children[8]=new Gump();
children[8]->load(gumpIDs[8],botX,botY,botW,botH,false);
}
void Gump::blit(Sint16 x,Sint16 y,HueMethod hueMethod,Uint16 hue)
{
if (children[0])
{
for (int i=0;i<9;i++)
children[i]->blit(x,y,hueMethod,hue);
}
else
Sprite::blit(x+offsetx,y+offsety,hueMethod,hue);
}