/*****
*
* This program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program; if not, write to the Free Software
* Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
*
*****/
#include "uop.h"
#include <SDL/SDL.h>
#include "artfactory.h"
#include "sprite.h"
/**
* Factory production function for art.mul. It will
* produce anything in art.mul as a Sprite.
* @param index The index in artidx.mul that references
* the art you wish to load.
* @param sprite The sprite that will contain the art.
* @todo Add code to prevent out-of-file read errors
* and any catchable cases of error-prone data
*/
ArtFactory::ArtFactory(string indexfilename, string artfilename){
artidx.open(indexfilename.c_str(), ios::in|ios::binary);
assert(artidx.is_open());
artfile.open(artfilename.c_str(), ios::in|ios::binary);
assert(artfile.is_open());
}
void ArtFactory::produce(Uint32 index, UOSprite &sprite)
{
// Find index file size and make sure entry exists
artidx.seekg(0, ios::end);
unsigned long idxE = artidx.tellg();
unsigned long maxIndex = idxE/12;
// Drop out if the entry is invalid
if (index > maxIndex)
return;
Uint32 lookup, length;
// Find the lookup
artidx.seekg(index*12);
artidx.read((char*)&lookup, 4);
artidx.read((char*)&length, 4);
if (lookup == 0xFFFFFFFF) // Then it dosen't exist
return;
// Seek to the lookup
artfile.seekg(lookup);
// Load either a land tile or static
if (index < 0x4000)
{
// Load a land tile
sprite.resize(44, 44);
Uint8 *buffer = (Uint8*)new Uint16[1024];
artfile.read((char*)buffer, 1024*2);
// Convert the entire buffer to 16-bit color
for (Uint16 *cur = (Uint16*)buffer; cur < ((Uint16*)buffer)+1024; cur++)
{
Uint16 victim = *cur;
if (victim)
{
Uint8 red = (victim >> 10)&0x1f;
Uint8 green = (victim >> 5)&0x1f;
Uint8 blue = victim&0x1f;
(*cur) = (red << 11) | (green << 6) | blue;
}
else
{
// Convert to a similar shade of black
// This will prevent it from being considered
// transparent.
(*cur) = (1 << 11) | (1 << 6) | 1;
}
}
Uint8 *src = buffer;
int y;
for (y = 0; y < 22; y++)
{
memcpy(sprite.data + (y*44) + (21-y), src, (y+1) << 2);
src += ((y+1)*4);
}
for (y = 22; y < 44; y++)
{
memcpy(sprite.data + (y*44) + (y-22), src, (44-y) << 2);
src += ((44-y)*4);
}
delete [] buffer;
}
else
{
// Already seeked to lookup, so time to
// load a static
Uint16 width, height;
Uint16 *lookupTable;
Uint32 orunFileOffset;
artfile.seekg(4, ios::cur);
artfile.read((char*)&width, 2);
artfile.read((char*)&height, 2);
lookupTable = new Uint16[height];
artfile.read((char*)lookupTable, height*2);
orunFileOffset = artfile.tellg();
sprite.resize(width, height);
artfile.seekg(orunFileOffset + lookupTable[0]*2);
int dX = 0, cY = 0;
while (cY < height)
{
Uint16 xOffset, xRun;
artfile.read((char*)&xOffset, 2);
artfile.read((char*)&xRun, 2);
if (xOffset + xRun)
{
dX += xOffset;
artfile.read((char*)sprite.data + width*cY*2 + dX*2, xRun*2);
dX += xRun;
}
else
{
dX = 0;
cY++;
artfile.seekg(orunFileOffset + lookupTable[cY]*2);
}
}
// Convert everything to 16-bit color
for (Uint16 *cur = (Uint16*)sprite.data;
cur < ((Uint16*)sprite.data)+width*height;
cur++)
{
Uint16 victim = *cur;
if (victim)
{
Uint8 red = (victim >> 10)&0x1f;
Uint8 green = (victim >> 5)&0x1f;
Uint8 blue = victim&0x1f;
(*cur) = (red << 11) | (green << 6) | blue;
}
}
delete [] lookupTable;
}
}
void ArtFactory::recycle(UOSprite &sprite)
{
sprite.~UOSprite();
}