Added GemRB sources

This commit is contained in:
pelya
2010-12-14 09:47:29 +00:00
parent 674da851ef
commit 38bceffddd
455 changed files with 137680 additions and 0 deletions

View File

@@ -0,0 +1,395 @@
/* GemRB - Infinity Engine Emulator
* Copyright (C) 2003 The GemRB Project
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#if defined(__HAIKU__)
#include <unistd.h>
#endif
#ifdef ANDROID
#include "swab.h"
#endif
#include "BAMImporter.h"
#include "win32def.h"
#include "Compressor.h"
#include "GameData.h"
#include "Interface.h"
#include "Palette.h"
#include "Video.h"
#include "System/FileStream.h"
BAMImporter::BAMImporter(void)
{
str = NULL;
autoFree = false;
frames = NULL;
cycles = NULL;
palette = NULL;
FramesCount = 0;
CyclesCount = 0;
}
BAMImporter::~BAMImporter(void)
{
if (str && autoFree) {
delete( str );
}
delete[] frames;
delete[] cycles;
gamedata->FreePalette(palette);
}
bool BAMImporter::Open(DataStream* stream, bool autoFree)
{
unsigned int i;
if (stream == NULL) {
return false;
}
if (str && this->autoFree) {
delete( str );
}
delete[] frames;
delete[] cycles;
gamedata->FreePalette(palette);
str = stream;
this->autoFree = autoFree;
char Signature[8];
str->Read( Signature, 8 );
if (strncmp( Signature, "BAMCV1 ", 8 ) == 0) {
//Check if Decompressed file has already been Cached
char cpath[_MAX_PATH];
strcpy( cpath, core->CachePath );
strcat( cpath, stream->filename );
FILE* exist_in_cache = fopen( cpath, "rb" );
if (exist_in_cache) {
//File was previously cached, using local copy
if (autoFree) {
delete( str );
}
fclose( exist_in_cache );
FileStream* s = new FileStream();
s->Open( cpath );
str = s;
str->Read( Signature, 8 );
} else {
//No file found in Cache, Decompressing and storing for further use
str->Seek( 4, GEM_CURRENT_POS );
if (!core->IsAvailable( PLUGIN_COMPRESSION_ZLIB )) {
printf( "No Compression Manager Available.\nCannot Load Compressed Bam File.\n" );
return false;
}
FILE* newfile = fopen( cpath, "wb" );
if (!newfile) {
printMessage("BAMImporter", " ", RED);
printf( "Cannot write %s.\n", cpath );
return false;
}
PluginHolder<Compressor> comp(PLUGIN_COMPRESSION_ZLIB);
comp->Decompress( newfile, str );
fclose( newfile );
if (autoFree)
delete( str );
FileStream* s = new FileStream();
s->Open( cpath );
str = s;
str->Read( Signature, 8 );
}
}
if (strncmp( Signature, "BAM V1 ", 8 ) != 0) {
return false;
}
str->ReadWord( &FramesCount );
str->Read( &CyclesCount, 1 );
str->Read( &CompressedColorIndex, 1 );
str->ReadDword( &FramesOffset );
str->ReadDword( &PaletteOffset );
str->ReadDword( &FLTOffset );
str->Seek( FramesOffset, GEM_STREAM_START );
frames = new FrameEntry[FramesCount];
DataStart = str->Size();
for (i = 0; i < FramesCount; i++) {
str->ReadWord( &frames[i].Width );
str->ReadWord( &frames[i].Height );
str->ReadWord( &frames[i].XPos );
str->ReadWord( &frames[i].YPos );
str->ReadDword( &frames[i].FrameData );
if ((frames[i].FrameData & 0x7FFFFFFF) < DataStart)
DataStart = (frames[i].FrameData & 0x7FFFFFFF);
}
cycles = new CycleEntry[CyclesCount];
for (i = 0; i < CyclesCount; i++) {
str->ReadWord( &cycles[i].FramesCount );
str->ReadWord( &cycles[i].FirstFrame );
}
str->Seek( PaletteOffset, GEM_STREAM_START );
palette = new Palette();
// no need to switch this
for (i = 0; i < 256; i++) {
RevColor rc;
str->Read( &rc, 4 );
palette->col[i].r = rc.r;
palette->col[i].g = rc.g;
palette->col[i].b = rc.b;
palette->col[i].a = rc.a;
}
return true;
}
int BAMImporter::GetCycleSize(unsigned char Cycle)
{
if(Cycle >= CyclesCount ) {
return -1;
}
return cycles[Cycle].FramesCount;
}
Sprite2D* BAMImporter::GetFrameInternal(unsigned short findex, unsigned char mode,
bool BAMsprite, const unsigned char* data,
AnimationFactory* datasrc)
{
Sprite2D* spr = 0;
if (BAMsprite) {
bool RLECompressed = (frames[findex].FrameData & 0x80000000) == 0;
assert(data);
const unsigned char* framedata = data;
framedata += (frames[findex].FrameData & 0x7FFFFFFF) - DataStart;
if (RLECompressed) {
spr = core->GetVideoDriver()->CreateSpriteBAM8(
frames[findex].Width, frames[findex].Height,
true, framedata, datasrc, palette, CompressedColorIndex);
} else {
spr = core->GetVideoDriver()->CreateSpriteBAM8(
frames[findex].Width, frames[findex].Height, false,
framedata, datasrc, palette, CompressedColorIndex );
}
} else {
void* pixels = GetFramePixels(findex);
spr = core->GetVideoDriver()->CreateSprite8(
frames[findex].Width, frames[findex].Height, 8,
pixels, palette->col, true, 0 );
}
spr->XPos = (ieWordSigned)frames[findex].XPos;
spr->YPos = (ieWordSigned)frames[findex].YPos;
if (mode == IE_SHADED) {
// CHECKME: is this ever used? Should we modify the sprite's palette
// without creating a local copy for this sprite?
Palette* pal = spr->GetPalette();
pal->CreateShadedAlphaChannel();
pal->Release();
}
return spr;
}
void* BAMImporter::GetFramePixels(unsigned short findex)
{
if (findex >= FramesCount) {
findex = cycles[0].FirstFrame;
}
str->Seek( ( frames[findex].FrameData & 0x7FFFFFFF ), GEM_STREAM_START );
unsigned long pixelcount = frames[findex].Height * frames[findex].Width;
void* pixels = malloc( pixelcount );
bool RLECompressed = ( ( frames[findex].FrameData & 0x80000000 ) == 0 );
if (RLECompressed) {
//if RLE Compressed
unsigned long RLESize;
RLESize = ( unsigned long )
( frames[findex].Width * frames[findex].Height * 3 ) / 2 + 1;
//without partial reads, we should be careful
unsigned long remains = str->Remains();
if (RLESize > remains) {
RLESize = remains;
}
unsigned char* inpix;
inpix = (unsigned char*)malloc( RLESize );
if (str->Read( inpix, RLESize ) == GEM_ERROR) {
free( inpix );
return NULL;
}
unsigned char * p = inpix;
unsigned char * Buffer = (unsigned char*)pixels;
unsigned int i = 0;
while (i < pixelcount) {
if (*p == CompressedColorIndex) {
p++;
// FIXME: Czech HOW has apparently broken frame
// #141 in REALMS.BAM. Maybe we should put
// this condition to #ifdef BROKEN_xx ?
// Or maybe rather put correct REALMS.BAM
// into override/ dir?
if (i + ( *p ) + 1 > pixelcount) {
memset( &Buffer[i], CompressedColorIndex, pixelcount - i );
printf ("Broken frame %d\n", findex);
} else {
memset( &Buffer[i], CompressedColorIndex, ( *p ) + 1 );
}
i += *p;
} else
Buffer[i] = *p;
p++;
i++;
}
free( inpix );
} else {
str->Read( pixels, pixelcount );
}
return pixels;
}
ieWord * BAMImporter::CacheFLT(unsigned int &count)
{
int i;
count = 0;
for (i = 0; i < CyclesCount; i++) {
unsigned int tmp = cycles[i].FirstFrame + cycles[i].FramesCount;
if (tmp > count) {
count = tmp;
}
}
ieWord * FLT = ( ieWord * ) calloc( count, sizeof(ieWord) );
str->Seek( FLTOffset, GEM_STREAM_START );
str->Read( FLT, count * sizeof(ieWord) );
if( DataStream::IsEndianSwitch() ) {
//msvc likes it as char *
swab( (char*) FLT, (char*) FLT, count * sizeof(ieWord) );
}
return FLT;
}
AnimationFactory* BAMImporter::GetAnimationFactory(const char* ResRef, unsigned char mode)
{
unsigned int i, count;
AnimationFactory* af = new AnimationFactory( ResRef );
ieWord *FLT = CacheFLT( count );
bool videoBAMsupport = core->GetVideoDriver()->SupportsBAMSprites();
unsigned char* data = NULL;
if (videoBAMsupport) {
str->Seek( DataStart, GEM_STREAM_START );
unsigned long length = str->Remains();
if (length == 0) return af;
//data = new unsigned char[length];
data = (unsigned char *) malloc(length);
str->Read( data, length );
af->SetFrameData(data);
}
for (i = 0; i < FramesCount; ++i) {
Sprite2D* frame = GetFrameInternal(i, mode, videoBAMsupport, data, af);
assert(!videoBAMsupport || frame->BAM);
af->AddFrame(frame);
}
for (i = 0; i < CyclesCount; ++i) {
af->AddCycle( cycles[i] );
}
af->LoadFLT ( FLT, count );
free (FLT);
return af;
}
/** This function will load the Animation as a Font */
Font* BAMImporter::GetFont()
{
unsigned int i;
int w = 0, h = 0;
unsigned int Count;
ieWord *FLT = CacheFLT(Count);
// Numeric fonts have all frames in single cycle
if (CyclesCount > 1) {
Count = CyclesCount;
} else {
Count = FramesCount;
}
for (i = 0; i < Count; i++) {
unsigned int index;
if (CyclesCount > 1) {
index = FLT[cycles[i].FirstFrame];
if (index >= FramesCount)
continue;
} else {
index = i;
}
w = w + frames[index].Width;
if (frames[index].Height > h)
h = frames[index].Height;
}
Font* fnt = new Font( w, h, palette );
for (i = 0; i < Count; i++) {
unsigned int index;
if (CyclesCount > 1) {
index = FLT[cycles[i].FirstFrame];
if (index >= FramesCount) {
fnt->AddChar( NULL, 0, 0, 0, 0 );
continue;
}
} else {
index = i;
}
unsigned char* pixels = (unsigned char*)GetFramePixels( index );
if( !pixels) {
fnt->AddChar( NULL, 0, 0, 0, 0 );
continue;
}
fnt->AddChar( pixels, frames[index].Width,
frames[index].Height,
frames[index].XPos,
frames[index].YPos );
free( pixels );
}
free( FLT );
fnt->FinalizeSprite( true, 0 );
return fnt;
}
/** Debug Function: Returns the Global Animation Palette as a Sprite2D Object.
If the Global Animation Palette is NULL, returns NULL. */
Sprite2D* BAMImporter::GetPalette()
{
unsigned char * pixels = ( unsigned char * ) malloc( 256 );
unsigned char * p = pixels;
for (int i = 0; i < 256; i++) {
*p++ = ( unsigned char ) i;
}
return core->GetVideoDriver()->CreateSprite8( 16, 16, 8, pixels, palette->col, false );
}
#include "plugindef.h"
GEMRB_PLUGIN(0x3AD6427A, "BAM File Importer")
PLUGIN_CLASS(IE_BAM_CLASS_ID, BAMImporter)
END_PLUGIN()

View File

@@ -0,0 +1,90 @@
/* GemRB - Infinity Engine Emulator
* Copyright (C) 2003 The GemRB Project
*
* 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., 51 Franklin Street, Fifth Floor, Boston, MA 02110-1301, USA.
*
*
*/
#ifndef BAMIMPORTER_H
#define BAMIMPORTER_H
#include "AnimationMgr.h"
#include "RGBAColor.h"
#include "globals.h"
struct FrameEntry {
ieWord Width;
ieWord Height;
ieWord XPos;
ieWord YPos;
ieDword FrameData;
};
class Palette;
class BAMImporter : public AnimationMgr {
private:
DataStream* str;
bool autoFree;
FrameEntry* frames;
CycleEntry* cycles;
ieWord FramesCount;
ieByte CyclesCount;
Palette* palette;
ieByte CompressedColorIndex;
ieDword FramesOffset, PaletteOffset, FLTOffset;
unsigned long DataStart;
private:
Sprite2D* GetFrameInternal(unsigned short findex, unsigned char mode,
bool BAMsprite, const unsigned char* data,
AnimationFactory* datasrc);
void* GetFramePixels(unsigned short findex);
ieWord * CacheFLT(unsigned int &count);
public:
BAMImporter(void);
~BAMImporter(void);
bool Open(DataStream* stream, bool autoFree = true);
int GetCycleSize(unsigned char Cycle);
AnimationFactory* GetAnimationFactory(const char* ResRef,
unsigned char mode = IE_NORMAL);
/** This function will load the Animation as a Font */
Font* GetFont();
/** Debug Function: Returns the Global Animation Palette as a Sprite2D Object.
If the Global Animation Palette is NULL, returns NULL. */
Sprite2D* GetPalette();
/** Gets a Pixel Index from the Image, unused */
unsigned int GetPixelIndex(unsigned int /*x*/, unsigned int /*y*/)
{
return 0;
}
/** Gets a Pixel from the Image, unused */
Color GetPixel(unsigned int /*x*/, unsigned int /*y*/)
{
Color null = {
0x00, 0x00, 0x00, 0x00
};
return null;
}
public:
int GetCycleCount()
{
return CyclesCount;
}
};
#endif

View File

@@ -0,0 +1 @@
ADD_GEMRB_PLUGIN (BAMImporter BAMImporter.cpp)

View File

@@ -0,0 +1,3 @@
plugin_LTLIBRARIES = BAMImporter.la
BAMImporter_la_LDFLAGS = -module -avoid-version -shared
BAMImporter_la_SOURCES = BAMImporter.cpp BAMImporter.h