aboutsummaryrefslogtreecommitdiff
path: root/tools/TexturePacker
diff options
context:
space:
mode:
authorjmarshallnz <jmarshallnz@svn>2009-10-04 03:30:46 +0000
committerjmarshallnz <jmarshallnz@svn>2009-10-04 03:30:46 +0000
commite0dd2f4f5772a0ec7c977cbcd3ecd1f3ac9ca304 (patch)
treed149429093ed0a0efef5aaefa1461ed68140ee07 /tools/TexturePacker
parente6dd5edab4451ab6f8fd8240b31c9922edf237b0 (diff)
moved: XBMCTexXBT to a slightly less random collection of characters.
git-svn-id: https://xbmc.svn.sourceforge.net/svnroot/xbmc/trunk@23399 568bbfeb-2a22-0410-94d2-cc84cf5bfa90
Diffstat (limited to 'tools/TexturePacker')
-rw-r--r--tools/TexturePacker/Makefile.in24
-rw-r--r--tools/TexturePacker/SDL_anigif.c776
-rw-r--r--tools/TexturePacker/SDL_anigif.h62
-rw-r--r--tools/TexturePacker/Win32/TexturePacker.sln20
-rw-r--r--tools/TexturePacker/Win32/TexturePacker.vcproj239
-rw-r--r--tools/TexturePacker/Win32/dirent.c148
-rw-r--r--tools/TexturePacker/Win32/dirent.h61
-rw-r--r--tools/TexturePacker/XBMCTex.cpp437
-rw-r--r--tools/TexturePacker/XBTFWriter.cpp132
-rw-r--r--tools/TexturePacker/XBTFWriter.h24
-rw-r--r--tools/TexturePacker/cmdlineargs.h123
-rw-r--r--tools/TexturePacker/xwinapi.cpp81
-rw-r--r--tools/TexturePacker/xwinapi.h11
13 files changed, 2138 insertions, 0 deletions
diff --git a/tools/TexturePacker/Makefile.in b/tools/TexturePacker/Makefile.in
new file mode 100644
index 0000000000..9301021a2a
--- /dev/null
+++ b/tools/TexturePacker/Makefile.in
@@ -0,0 +1,24 @@
+ARCH=@ARCH@
+INCLUDES =-I../../xbmc/utils -I../../guilib -I../../xbmc/linux -I../../xbmc/lib/libsquish
+DEFINES =
+ifeq ($(findstring osx,$(ARCH)),osx)
+LIBS = ../../xbmc/lib/libsquish/libsquish-@ARCH@.a -L/opt/local/lib -lSDL_image -lSDL -llzo
+else
+LIBS = ../../xbmc/lib/libsquish/libsquish-@ARCH@.a -lSDL_image -lSDL -llzo2
+endif
+
+OBJS = \
+ SDL_anigif.o \
+ XBTFWriter.o \
+ XBMCTex.o \
+ ../../guilib/XBTF.o
+
+TARGET = XBMCTexXBT
+CLEAN_FILES=$(TARGET)
+
+all: $(TARGET)
+
+include ../../Makefile.include
+
+$(TARGET): $(OBJS)
+ $(CXX) $(OBJS) $(LDFLAGS) $(LIBS) -o $(TARGET)
diff --git a/tools/TexturePacker/SDL_anigif.c b/tools/TexturePacker/SDL_anigif.c
new file mode 100644
index 0000000000..b77b7bcdb0
--- /dev/null
+++ b/tools/TexturePacker/SDL_anigif.c
@@ -0,0 +1,776 @@
+/*
+ SDL_anigif: An example animated GIF image loading library for use with SDL
+ SDL_image Copyright (C) 1997-2006 Sam Lantinga
+ Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#include <stdio.h>
+#include <string.h>
+#include "SDL_anigif.h"
+
+
+
+/* Code from here to end of file has been adapted from XPaint: */
+/* +-------------------------------------------------------------------+ */
+/* | Copyright 1990, 1991, 1993 David Koblas. | */
+/* | Copyright 1996 Torsten Martinsen. | */
+/* | Permission to use, copy, modify, and distribute this software | */
+/* | and its documentation for any purpose and without fee is hereby | */
+/* | granted, provided that the above copyright notice appear in all | */
+/* | copies and that both that copyright notice and this permission | */
+/* | notice appear in supporting documentation. This software is | */
+/* | provided "as is" without express or implied warranty. | */
+/* +-------------------------------------------------------------------+ */
+/* Adapted for use in SDL by Sam Lantinga -- 7/20/98 */
+/* Animated GIF support by Doug McFadyen -- 10/19/06 */
+
+#define MAXCOLORMAPSIZE 256
+
+#define TRUE 1
+#define FALSE 0
+
+#define CM_RED 0
+#define CM_GREEN 1
+#define CM_BLUE 2
+
+#define MAX_LWZ_BITS 12
+
+#define INTERLACE 0x40
+#define LOCALCOLORMAP 0x80
+#define BitSet(byte,bit) (((byte) & (bit)) == (bit))
+#define LM_to_uint(a,b) (((b)<<8)|(a))
+
+#define SDL_SetError(t) ((void)0) /* We're not SDL so ignore error reporting */
+
+
+typedef struct
+{
+ unsigned int Width;
+ unsigned int Height;
+ unsigned char ColorMap[3][MAXCOLORMAPSIZE];
+ unsigned int BitPixel;
+ unsigned int ColorResolution;
+ unsigned int Background;
+ unsigned int AspectRatio;
+} gifscreen;
+
+typedef struct
+{
+ int transparent;
+ int delayTime;
+ int inputFlag;
+ int disposal;
+} gif89;
+
+typedef struct
+{
+ /* global data */
+ SDL_RWops* src;
+ gifscreen gs;
+ gif89 g89;
+ int zerodatablock;
+ /* AG_LoadGIF_RW data */
+ unsigned char localColorMap[3][MAXCOLORMAPSIZE];
+ /* GetCode data */
+ unsigned char buf[280];
+ int curbit, lastbit, done, lastbyte;
+ /* LWZReadByte data */
+ int fresh, code, incode;
+ int codesize, setcodesize;
+ int maxcode, maxcodesize;
+ int firstcode, oldcode;
+ int clearcode, endcode;
+ int table[2][(1 << MAX_LWZ_BITS)];
+ int stack[(1 << (MAX_LWZ_BITS))*2], *sp;
+} gifdata;
+
+
+
+static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] );
+static int DoExtension( gifdata* gd, int label );
+static int GetDataBlock( gifdata* gd, unsigned char* buf );
+static int GetCode( gifdata* gd, int code_size, int flag );
+static int LWZReadByte( gifdata* gd, int flag, int input_code_size );
+static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore );
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_isGIF( SDL_RWops* src )
+{
+ int isGIF = FALSE;
+
+ if ( src )
+ {
+ int start = SDL_RWtell( src );
+ char magic[6];
+
+ if ( SDL_RWread(src,magic,sizeof(magic),1) )
+ {
+ if ( (strncmp(magic,"GIF",3) == 0) && ((memcmp(magic+3,"87a",3) == 0) || (memcmp(magic+3,"89a",3) == 0)) )
+ {
+ isGIF = TRUE;
+ }
+ }
+
+ SDL_RWseek( src, start, SEEK_SET );
+ }
+
+ return isGIF;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_LoadGIF( const char* file, AG_Frame* frames, int size )
+{
+ int n = 0;
+
+ SDL_RWops* src = SDL_RWFromFile( file, "rb" );
+
+ if ( src )
+ {
+ n = AG_LoadGIF_RW( src, frames, size );
+ SDL_RWclose( src );
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+void AG_FreeSurfaces( AG_Frame* frames, int nFrames )
+{
+ int i;
+
+ if ( frames )
+ {
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = NULL;
+ }
+ }
+ }
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
+{
+ int i;
+ int n = 0;
+
+ if ( frames )
+ {
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_Surface* surface = (frames[i].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[i].surface) : SDL_DisplayFormat(frames[i].surface);
+
+ if ( surface )
+ {
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = surface;
+ n++;
+ }
+ }
+ }
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames )
+{
+ int n = 0;
+
+ if ( nFrames > 0 && frames && frames[0].surface )
+ {
+ SDL_Surface* mainSurface = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? SDL_DisplayFormatAlpha(frames[0].surface) : SDL_DisplayFormat(frames[0].surface);
+ const int newDispose = (frames[0].surface->flags & SDL_SRCCOLORKEY) ? AG_DISPOSE_RESTORE_BACKGROUND : AG_DISPOSE_NONE;
+
+ if ( mainSurface )
+ {
+ int i;
+ int lastDispose = AG_DISPOSE_NA;
+ int iRestore = 0;
+ const Uint8 alpha = (frames[0].disposal == AG_DISPOSE_NONE) ? SDL_ALPHA_OPAQUE : SDL_ALPHA_TRANSPARENT;
+
+ SDL_FillRect( mainSurface, NULL, SDL_MapRGBA(mainSurface->format,0,0,0,alpha) );
+
+ for ( i = 0; i < nFrames; i++ )
+ {
+ if ( frames[i].surface )
+ {
+ SDL_Surface* surface = SDL_ConvertSurface( mainSurface, mainSurface->format, mainSurface->flags );
+
+ if ( surface )
+ {
+ SDL_Rect r;
+
+ if ( lastDispose == AG_DISPOSE_NONE )
+ SDL_BlitSurface( frames[i-1].surface, NULL, surface, NULL );
+
+ if ( lastDispose == AG_DISPOSE_RESTORE_PREVIOUS )
+ SDL_BlitSurface( frames[iRestore].surface, NULL, surface, NULL );
+ if ( frames[i].disposal != AG_DISPOSE_RESTORE_PREVIOUS )
+ iRestore = i;
+
+ r.x = (Sint16)frames[i].x;
+ r.y = (Sint16)frames[i].y;
+ SDL_BlitSurface( frames[i].surface, NULL, surface, &r );
+
+ SDL_FreeSurface( frames[i].surface );
+ frames[i].surface = surface;
+ frames[i].x = frames[i].y = 0;
+ lastDispose = frames[i].disposal;
+ frames[i].disposal = newDispose;
+ n++;
+ }
+ }
+ }
+
+ SDL_FreeSurface( mainSurface );
+ }
+ }
+
+ return n;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int maxFrames )
+{
+ int start;
+ unsigned char buf[16];
+ unsigned char c;
+ int useGlobalColormap;
+ int bitPixel;
+ int iFrame = 0;
+ char version[4];
+ SDL_Surface* image = NULL;
+ gifdata* gd;
+
+ if ( src == NULL )
+ return 0;
+
+ gd = malloc( sizeof(*gd) );
+ memset( gd, 0, sizeof(*gd) );
+ gd->src = src;
+
+ start = SDL_RWtell( src );
+
+ if ( !SDL_RWread(src,buf,6,1) )
+ {
+ SDL_SetError( "error reading magic number" );
+ goto done;
+ }
+
+ if ( strncmp((char*)buf,"GIF",3) != 0 )
+ {
+ SDL_SetError( "not a GIF file" );
+ goto done;
+ }
+
+ strncpy( version, (char*)buf+3, 3 );
+ version[3] = '\0';
+
+ if ( (strcmp(version,"87a") != 0) && (strcmp(version,"89a") != 0) )
+ {
+ SDL_SetError( "bad version number, not '87a' or '89a'" );
+ goto done;
+ }
+
+ gd->g89.transparent = -1;
+ gd->g89.delayTime = -1;
+ gd->g89.inputFlag = -1;
+ gd->g89.disposal = AG_DISPOSE_NA;
+
+ if ( !SDL_RWread(src,buf,7,1) )
+ {
+ SDL_SetError( "failed to read screen descriptor" );
+ goto done;
+ }
+
+ gd->gs.Width = LM_to_uint(buf[0],buf[1]);
+ gd->gs.Height = LM_to_uint(buf[2],buf[3]);
+ gd->gs.BitPixel = 2 << (buf[4] & 0x07);
+ gd->gs.ColorResolution = (((buf[4] & 0x70) >> 3) + 1);
+ gd->gs.Background = buf[5];
+ gd->gs.AspectRatio = buf[6];
+
+ if ( BitSet(buf[4],LOCALCOLORMAP) ) /* Global Colormap */
+ {
+ if ( ReadColorMap(gd,gd->gs.BitPixel,gd->gs.ColorMap) )
+ {
+ SDL_SetError( "error reading global colormap" );
+ goto done;
+ }
+ }
+
+ do
+ {
+ if ( !SDL_RWread(src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on image data" );
+ goto done;
+ }
+
+ if ( c == ';' ) /* GIF terminator */
+ goto done;
+
+ if ( c == '!' ) /* Extension */
+ {
+ if ( !SDL_RWread(src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on extention function code" );
+ goto done;
+ }
+ DoExtension( gd, c );
+ continue;
+ }
+
+ if ( c != ',' ) /* Not a valid start character */
+ continue;
+
+ if ( !SDL_RWread(src,buf,9,1) )
+ {
+ SDL_SetError( "couldn't read left/top/width/height" );
+ goto done;
+ }
+
+ useGlobalColormap = !BitSet(buf[8],LOCALCOLORMAP);
+ bitPixel = 1 << ((buf[8] & 0x07) + 1);
+
+ if ( !useGlobalColormap )
+ {
+ if ( ReadColorMap(gd,bitPixel,gd->localColorMap) )
+ {
+ SDL_SetError( "error reading local colormap" );
+ goto done;
+ }
+ image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), bitPixel, gd->localColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
+ }
+ else
+ {
+ image = ReadImage( gd, LM_to_uint(buf[4],buf[5]), LM_to_uint(buf[6],buf[7]), gd->gs.BitPixel, gd->gs.ColorMap, BitSet(buf[8],INTERLACE), (frames==NULL) );
+ }
+
+ if ( frames )
+ {
+ if ( image == NULL )
+ goto done;
+
+ if ( gd->g89.transparent >= 0 )
+ SDL_SetColorKey( image, SDL_SRCCOLORKEY, gd->g89.transparent );
+
+ frames[iFrame].surface = image;
+ frames[iFrame].x = LM_to_uint(buf[0], buf[1]);
+ frames[iFrame].y = LM_to_uint(buf[2], buf[3]);
+ frames[iFrame].disposal = gd->g89.disposal;
+ frames[iFrame].delay = gd->g89.delayTime*10;
+/* gd->g89.transparent = -1; ** Hmmm, not sure if this should be reset for each frame? */
+ }
+
+ iFrame++;
+ } while ( iFrame < maxFrames || frames == NULL );
+
+done:
+ if ( image == NULL )
+ SDL_RWseek( src, start, SEEK_SET );
+
+ free( gd );
+
+ return iFrame;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int ReadColorMap( gifdata* gd, int number, unsigned char buffer[3][MAXCOLORMAPSIZE] )
+{
+ int i;
+ unsigned char rgb[3];
+ int flag;
+
+ flag = TRUE;
+
+ for ( i = 0; i < number; ++i )
+ {
+ if ( !SDL_RWread(gd->src,rgb,sizeof(rgb),1) )
+ {
+ SDL_SetError( "bad colormap" );
+ return 1;
+ }
+
+ buffer[CM_RED][i] = rgb[0];
+ buffer[CM_GREEN][i] = rgb[1];
+ buffer[CM_BLUE][i] = rgb[2];
+ flag &= (rgb[0] == rgb[1] && rgb[1] == rgb[2]);
+ }
+
+ return FALSE;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int DoExtension( gifdata* gd, int label )
+{
+ unsigned char buf[256];
+
+ switch ( label )
+ {
+ case 0x01: /* Plain Text Extension */
+ break;
+
+ case 0xff: /* Application Extension */
+ break;
+
+ case 0xfe: /* Comment Extension */
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+ return FALSE;
+
+ case 0xf9: /* Graphic Control Extension */
+ (void)GetDataBlock( gd, buf );
+ gd->g89.disposal = (buf[0] >> 2) & 0x7;
+ gd->g89.inputFlag = (buf[0] >> 1) & 0x1;
+ gd->g89.delayTime = LM_to_uint(buf[1],buf[2]);
+ if ( (buf[0] & 0x1) != 0 )
+ gd->g89.transparent = buf[3];
+
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+ return FALSE;
+ }
+
+ while ( GetDataBlock(gd,buf) != 0 )
+ ;
+
+ return FALSE;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int GetDataBlock( gifdata* gd, unsigned char* buf )
+{
+ unsigned char count;
+
+ if ( !SDL_RWread(gd->src,&count,1,1) )
+ {
+ /* pm_message("error in getting DataBlock size" ); */
+ return -1;
+ }
+
+ gd->zerodatablock = count == 0;
+
+ if ( (count != 0) && !SDL_RWread(gd->src,buf,count,1) )
+ {
+ /* pm_message("error in reading DataBlock" ); */
+ return -1;
+ }
+
+ return count;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int GetCode( gifdata* gd, int code_size, int flag )
+{
+ int i, j, ret;
+ int count;
+
+ if ( flag )
+ {
+ gd->curbit = 0;
+ gd->lastbit = 0;
+ gd->done = FALSE;
+ return 0;
+ }
+
+ if ( (gd->curbit + code_size) >= gd->lastbit )
+ {
+ if ( gd->done )
+ {
+ if ( gd->curbit >= gd->lastbit )
+ SDL_SetError( "ran off the end of my bits" );
+ return -1;
+ }
+
+ gd->buf[0] = gd->buf[gd->lastbyte - 2];
+ gd->buf[1] = gd->buf[gd->lastbyte - 1];
+
+ if ( (count = GetDataBlock(gd, &gd->buf[2])) == 0 )
+ gd->done = TRUE;
+
+ gd->lastbyte = 2 + count;
+ gd->curbit = (gd->curbit - gd->lastbit) + 16;
+ gd->lastbit = (2 + count)*8;
+ }
+
+ ret = 0;
+ for ( i = gd->curbit, j = 0; j < code_size; ++i, ++j )
+ ret |= ((gd->buf[i / 8] & (1 << (i % 8))) != 0) << j;
+
+ gd->curbit += code_size;
+
+ return ret;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static int LWZReadByte( gifdata* gd, int flag, int input_code_size )
+{
+ int i, code, incode;
+
+ if ( flag )
+ {
+ gd->setcodesize = input_code_size;
+ gd->codesize = gd->setcodesize + 1;
+ gd->clearcode = 1 << gd->setcodesize;
+ gd->endcode = gd->clearcode + 1;
+ gd->maxcodesize = gd->clearcode*2;
+ gd->maxcode = gd->clearcode + 2;
+
+ GetCode( gd, 0, TRUE );
+
+ gd->fresh = TRUE;
+
+ for ( i = 0; i < gd->clearcode; ++i )
+ {
+ gd->table[0][i] = 0;
+ gd->table[1][i] = i;
+ }
+
+ for ( ; i < (1 << MAX_LWZ_BITS); ++i )
+ gd->table[0][i] = gd->table[1][0] = 0;
+
+ gd->sp = gd->stack;
+ return 0;
+ }
+ else if ( gd->fresh )
+ {
+ gd->fresh = FALSE;
+ do
+ {
+ gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
+ } while ( gd->firstcode == gd->clearcode );
+ return gd->firstcode;
+ }
+
+ if ( gd->sp > gd->stack )
+ return *--gd->sp;
+
+ while ( (code = GetCode(gd,gd->codesize,FALSE)) >= 0 )
+ {
+ if ( code == gd->clearcode )
+ {
+ for ( i = 0; i < gd->clearcode; ++i )
+ {
+ gd->table[0][i] = 0;
+ gd->table[1][i] = i;
+ }
+
+ for ( ; i < (1 << MAX_LWZ_BITS); ++i )
+ gd->table[0][i] = gd->table[1][i] = 0;
+
+ gd->codesize = gd->setcodesize + 1;
+ gd->maxcodesize = gd->clearcode*2;
+ gd->maxcode = gd->clearcode + 2;
+ gd->sp = gd->stack;
+ gd->firstcode = gd->oldcode = GetCode( gd, gd->codesize, FALSE );
+ return gd->firstcode;
+ }
+ else if ( code == gd->endcode )
+ {
+ int count;
+ unsigned char buf[260];
+
+ if ( gd->zerodatablock )
+ return -2;
+
+ while ( (count = GetDataBlock(gd,buf)) > 0 )
+ ;
+
+ if ( count != 0 )
+ {
+ /* pm_message("missing EOD in data stream (common occurence)"); */
+ }
+ return -2;
+ }
+
+ incode = code;
+
+ if ( code >= gd->maxcode )
+ {
+ *gd->sp++ = gd->firstcode;
+ code = gd->oldcode;
+ }
+
+ while ( code >= gd->clearcode )
+ {
+ *gd->sp++ = gd->table[1][code];
+ if ( code == gd->table[0][code] )
+ SDL_SetError( "circular table entry BIG ERROR" );
+ code = gd->table[0][code];
+ }
+
+ *gd->sp++ = gd->firstcode = gd->table[1][code];
+
+ if ( (code = gd->maxcode) < (1 << MAX_LWZ_BITS) )
+ {
+ gd->table[0][code] = gd->oldcode;
+ gd->table[1][code] = gd->firstcode;
+ ++gd->maxcode;
+ if ( (gd->maxcode >= gd->maxcodesize) && (gd->maxcodesize < (1 << MAX_LWZ_BITS)) )
+ {
+ gd->maxcodesize *= 2;
+ ++gd->codesize;
+ }
+ }
+
+ gd->oldcode = incode;
+
+ if ( gd->sp > gd->stack )
+ return *--gd->sp;
+ }
+
+ return code;
+}
+
+
+
+/*--------------------------------------------------------------------------*/
+/*
+/*--------------------------------------------------------------------------*/
+static SDL_Surface* ReadImage( gifdata* gd, int len, int height, int cmapSize, unsigned char cmap[3][MAXCOLORMAPSIZE], int interlace, int ignore )
+{
+ SDL_Surface* image;
+ unsigned char c;
+ int i, v;
+ int xpos = 0, ypos = 0, pass = 0;
+
+ /* Initialize the compression routines */
+ if ( !SDL_RWread(gd->src,&c,1,1) )
+ {
+ SDL_SetError( "EOF / read error on image data" );
+ return NULL;
+ }
+
+ if ( LWZReadByte(gd,TRUE,c) < 0 )
+ {
+ SDL_SetError( "error reading image" );
+ return NULL;
+ }
+
+ /* If this is an "uninteresting picture" ignore it. */
+ if ( ignore )
+ {
+ while ( LWZReadByte(gd,FALSE,c) >= 0 )
+ ;
+ return NULL;
+ }
+
+ image = SDL_AllocSurface( SDL_SWSURFACE, len, height, 8, 0, 0, 0, 0 );
+
+ for ( i = 0; i < cmapSize; i++ )
+ {
+ image->format->palette->colors[i].r = cmap[CM_RED][i];
+ image->format->palette->colors[i].g = cmap[CM_GREEN][i];
+ image->format->palette->colors[i].b = cmap[CM_BLUE][i];
+ }
+
+ while ( (v = LWZReadByte(gd,FALSE,c)) >= 0 )
+ {
+ ((Uint8*)image->pixels)[xpos + ypos*image->pitch] = (Uint8)v;
+ ++xpos;
+
+ if ( xpos == len )
+ {
+ xpos = 0;
+ if ( interlace )
+ {
+ switch ( pass )
+ {
+ case 0:
+ case 1: ypos += 8; break;
+ case 2: ypos += 4; break;
+ case 3: ypos += 2; break;
+ }
+
+ if ( ypos >= height )
+ {
+ ++pass;
+ switch ( pass )
+ {
+ case 1: ypos = 4; break;
+ case 2: ypos = 2; break;
+ case 3: ypos = 1; break;
+ default: goto fini;
+ }
+ }
+ }
+ else
+ {
+ ++ypos;
+ }
+ }
+
+ if ( ypos >= height )
+ break;
+ }
+
+fini:
+ return image;
+}
+
diff --git a/tools/TexturePacker/SDL_anigif.h b/tools/TexturePacker/SDL_anigif.h
new file mode 100644
index 0000000000..7fad7c8fdb
--- /dev/null
+++ b/tools/TexturePacker/SDL_anigif.h
@@ -0,0 +1,62 @@
+/*
+ SDL_anigif: An example animated GIF image loading library for use with SDL
+ SDL_image Copyright (C) 1997-2006 Sam Lantinga
+ Animated GIF "derived work" Copyright (C) 2006 Doug McFadyen
+
+ This library is free software; you can redistribute it and/or
+ modify it under the terms of the GNU Lesser General Public
+ License as published by the Free Software Foundation; either
+ version 2.1 of the License, or (at your option) any later version.
+
+ This library 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
+ Lesser General Public License for more details.
+
+ You should have received a copy of the GNU Lesser General Public
+ License along with this library; if not, write to the Free Software
+ Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+*/
+
+#ifndef _SDL_ANIGIF_H
+#define _SDL_ANIGIF_H
+
+#include <SDL/SDL.h>
+#include <SDL/begin_code.h>
+#ifdef __cplusplus
+ extern "C" {
+#endif
+
+
+
+typedef struct
+{
+ SDL_Surface* surface; /* SDL surface for this frame */
+ int x, y; /* Frame offset position */
+ int disposal; /* Disposal code */
+ int delay; /* Frame delay in ms */
+ int user; /* User data (not used by aniGIF) */
+} AG_Frame;
+
+#define AG_DISPOSE_NA 0 /* No disposal specified */
+#define AG_DISPOSE_NONE 1 /* Do not dispose */
+#define AG_DISPOSE_RESTORE_BACKGROUND 2 /* Restore to background */
+#define AG_DISPOSE_RESTORE_PREVIOUS 3 /* Restore to previous */
+
+
+
+extern DECLSPEC int AG_isGIF( SDL_RWops* src );
+extern DECLSPEC int AG_LoadGIF( const char* file, AG_Frame* frames, int maxFrames );
+extern DECLSPEC void AG_FreeSurfaces( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_ConvertSurfacesToDisplayFormat( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_NormalizeSurfacesToDisplayFormat( AG_Frame* frames, int nFrames );
+extern DECLSPEC int AG_LoadGIF_RW( SDL_RWops* src, AG_Frame* frames, int size );
+
+
+
+#ifdef __cplusplus
+ }
+#endif
+#include <SDL/close_code.h>
+
+#endif /* _SDL_ANIGIF_H */
diff --git a/tools/TexturePacker/Win32/TexturePacker.sln b/tools/TexturePacker/Win32/TexturePacker.sln
new file mode 100644
index 0000000000..e2f63546b0
--- /dev/null
+++ b/tools/TexturePacker/Win32/TexturePacker.sln
@@ -0,0 +1,20 @@
+
+Microsoft Visual Studio Solution File, Format Version 10.00
+# Visual C++ Express 2008
+Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "TexturePacker", "TexturePacker.vcproj", "{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}"
+EndProject
+Global
+ GlobalSection(SolutionConfigurationPlatforms) = preSolution
+ Debug|Win32 = Debug|Win32
+ Release|Win32 = Release|Win32
+ EndGlobalSection
+ GlobalSection(ProjectConfigurationPlatforms) = postSolution
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.ActiveCfg = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Debug|Win32.Build.0 = Debug|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.ActiveCfg = Release|Win32
+ {57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}.Release|Win32.Build.0 = Release|Win32
+ EndGlobalSection
+ GlobalSection(SolutionProperties) = preSolution
+ HideSolutionNode = FALSE
+ EndGlobalSection
+EndGlobal
diff --git a/tools/TexturePacker/Win32/TexturePacker.vcproj b/tools/TexturePacker/Win32/TexturePacker.vcproj
new file mode 100644
index 0000000000..4c5ed8eb3a
--- /dev/null
+++ b/tools/TexturePacker/Win32/TexturePacker.vcproj
@@ -0,0 +1,239 @@
+<?xml version="1.0" encoding="Windows-1252"?>
+<VisualStudioProject
+ ProjectType="Visual C++"
+ Version="9.00"
+ Name="TexturePacker"
+ ProjectGUID="{57EC0A84-7E0C-4EEA-9E63-BB4EBF2310D7}"
+ RootNamespace="TexturePacker"
+ Keyword="Win32Proj"
+ TargetFrameworkVersion="196613"
+ >
+ <Platforms>
+ <Platform
+ Name="Win32"
+ />
+ </Platforms>
+ <ToolFiles>
+ </ToolFiles>
+ <Configurations>
+ <Configuration
+ Name="Debug|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="0"
+ AdditionalIncludeDirectories=".;..\..\..\xbmc\win32;..\..\..\guilib;..\..\..\xbmc\utils;..\..\..\xbmc\lib\libsquish;"
+ PreprocessorDefinitions="WIN32;_DEBUG;_CONSOLE"
+ MinimalRebuild="true"
+ BasicRuntimeChecks="3"
+ RuntimeLibrary="3"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="4"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="SDL.lib SDL_image.lib ..\..\..\xbmc\lib\libsquish\lib\squishd.lib ..\..\..\xbmc\lib\liblzo\lzo.lib"
+ LinkIncremental="2"
+ IgnoreDefaultLibraryNames="libc.lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ <Configuration
+ Name="Release|Win32"
+ OutputDirectory="$(SolutionDir)$(ConfigurationName)"
+ IntermediateDirectory="$(ConfigurationName)"
+ ConfigurationType="1"
+ CharacterSet="0"
+ WholeProgramOptimization="1"
+ >
+ <Tool
+ Name="VCPreBuildEventTool"
+ />
+ <Tool
+ Name="VCCustomBuildTool"
+ />
+ <Tool
+ Name="VCXMLDataGeneratorTool"
+ />
+ <Tool
+ Name="VCWebServiceProxyGeneratorTool"
+ />
+ <Tool
+ Name="VCMIDLTool"
+ />
+ <Tool
+ Name="VCCLCompilerTool"
+ Optimization="2"
+ EnableIntrinsicFunctions="true"
+ AdditionalIncludeDirectories=".;..\..\..\xbmc\win32;..\..\..\guilib;..\..\..\xbmc\utils;..\..\..\xbmc\lib\libsquish;"
+ PreprocessorDefinitions="WIN32;NDEBUG;_CONSOLE"
+ RuntimeLibrary="2"
+ EnableFunctionLevelLinking="true"
+ UsePrecompiledHeader="0"
+ WarningLevel="3"
+ DebugInformationFormat="3"
+ />
+ <Tool
+ Name="VCManagedResourceCompilerTool"
+ />
+ <Tool
+ Name="VCResourceCompilerTool"
+ />
+ <Tool
+ Name="VCPreLinkEventTool"
+ />
+ <Tool
+ Name="VCLinkerTool"
+ AdditionalDependencies="SDL.lib SDL_image.lib ..\..\..\xbmc\lib\libsquish\lib\squish.lib ..\..\..\xbmc\lib\liblzo\lzo.lib"
+ LinkIncremental="1"
+ IgnoreDefaultLibraryNames="libc.lib"
+ GenerateDebugInformation="true"
+ SubSystem="1"
+ OptimizeReferences="2"
+ EnableCOMDATFolding="2"
+ TargetMachine="1"
+ />
+ <Tool
+ Name="VCALinkTool"
+ />
+ <Tool
+ Name="VCManifestTool"
+ />
+ <Tool
+ Name="VCXDCMakeTool"
+ />
+ <Tool
+ Name="VCBscMakeTool"
+ />
+ <Tool
+ Name="VCFxCopTool"
+ />
+ <Tool
+ Name="VCAppVerifierTool"
+ />
+ <Tool
+ Name="VCPostBuildEventTool"
+ />
+ </Configuration>
+ </Configurations>
+ <References>
+ </References>
+ <Files>
+ <Filter
+ Name="Source Files"
+ Filter="cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx"
+ UniqueIdentifier="{4FC737F1-C7A5-4376-A066-2A32D752A2FF}"
+ >
+ <File
+ RelativePath=".\dirent.c"
+ >
+ </File>
+ <File
+ RelativePath="..\SDL_anigif.c"
+ >
+ </File>
+ <File
+ RelativePath="..\XBMCTex.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\guilib\XBTF.cpp"
+ >
+ </File>
+ <File
+ RelativePath="..\XBTFWriter.cpp"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Header Files"
+ Filter="h;hpp;hxx;hm;inl;inc;xsd"
+ UniqueIdentifier="{93995380-89BD-4b04-88EB-625FBE52EBFB}"
+ >
+ <File
+ RelativePath="..\cmdlineargs.h"
+ >
+ </File>
+ <File
+ RelativePath=".\dirent.h"
+ >
+ </File>
+ <File
+ RelativePath="..\SDL_anigif.h"
+ >
+ </File>
+ <File
+ RelativePath="..\..\..\guilib\XBTF.h"
+ >
+ </File>
+ <File
+ RelativePath="..\XBTFWriter.h"
+ >
+ </File>
+ </Filter>
+ <Filter
+ Name="Resource Files"
+ Filter="rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav"
+ UniqueIdentifier="{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}"
+ >
+ </Filter>
+ <File
+ RelativePath=".\ReadMe.txt"
+ >
+ </File>
+ </Files>
+ <Globals>
+ </Globals>
+</VisualStudioProject>
diff --git a/tools/TexturePacker/Win32/dirent.c b/tools/TexturePacker/Win32/dirent.c
new file mode 100644
index 0000000000..060da1f23a
--- /dev/null
+++ b/tools/TexturePacker/Win32/dirent.c
@@ -0,0 +1,148 @@
+/*
+
+ Implementation of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+ Rights: See end of file.
+
+*/
+
+#include <dirent.h>
+#include <errno.h>
+#include <io.h> /* _findfirst and _findnext set errno iff they return -1 */
+#include <stdlib.h>
+#include <string.h>
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+struct DIR
+{
+ long handle; /* -1 for failed rewind */
+ struct _finddata_t info;
+ struct dirent result; /* d_name null iff first time */
+ char *name; /* null-terminated char string */
+};
+
+DIR *opendir(const char *name)
+{
+ DIR *dir = 0;
+
+ if(name && name[0])
+ {
+ size_t base_length = strlen(name);
+ const char *all = /* search pattern must end with suitable wildcard */
+ strchr("/\\", name[base_length - 1]) ? "*" : "/*";
+
+ if((dir = (DIR *) malloc(sizeof *dir)) != 0 &&
+ (dir->name = (char *) malloc(base_length + strlen(all) + 1)) != 0)
+ {
+ strcat(strcpy(dir->name, name), all);
+
+ if((dir->handle = (long) _findfirst(dir->name, &dir->info)) != -1)
+ {
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else /* rollback */
+ {
+ free(dir->name);
+ free(dir);
+ dir = 0;
+ }
+ }
+ else /* rollback */
+ {
+ free(dir);
+ dir = 0;
+ errno = ENOMEM;
+ }
+ }
+ else
+ {
+ errno = EINVAL;
+ }
+
+ return dir;
+}
+
+int closedir(DIR *dir)
+{
+ int result = -1;
+
+ if(dir)
+ {
+ if(dir->handle != -1)
+ {
+ result = _findclose(dir->handle);
+ }
+
+ free(dir->name);
+ free(dir);
+ }
+
+ if(result == -1) /* map all errors to EBADF */
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+struct dirent *readdir(DIR *dir)
+{
+ struct dirent *result = 0;
+
+ if(dir && dir->handle != -1)
+ {
+ if(!dir->result.d_name || _findnext(dir->handle, &dir->info) != -1)
+ {
+ result = &dir->result;
+ result->d_name = dir->info.name;
+ result->d_type = (dir->info.attrib == _A_SUBDIR) ? DT_DIR : DT_UNKNOWN;
+ }
+ }
+ else
+ {
+ errno = EBADF;
+ }
+
+ return result;
+}
+
+void rewinddir(DIR *dir)
+{
+ if(dir && dir->handle != -1)
+ {
+ _findclose(dir->handle);
+ dir->handle = (long) _findfirst(dir->name, &dir->info);
+ dir->result.d_name = 0;
+ dir->result.d_type = 0;
+ }
+ else
+ {
+ errno = EBADF;
+ }
+}
+
+#ifdef __cplusplus
+}
+#endif
+
+/*
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+*/
diff --git a/tools/TexturePacker/Win32/dirent.h b/tools/TexturePacker/Win32/dirent.h
new file mode 100644
index 0000000000..d0522db9b9
--- /dev/null
+++ b/tools/TexturePacker/Win32/dirent.h
@@ -0,0 +1,61 @@
+#ifndef DIRENT_INCLUDED
+#define DIRENT_INCLUDED
+
+/*
+
+ Declaration of POSIX directory browsing functions and types for Win32.
+
+ Author: Kevlin Henney (kevlin@acm.org, kevlin@curbralan.com)
+ History: Created March 1997. Updated June 2003.
+ Rights: See end of file.
+
+*/
+
+#ifdef __cplusplus
+extern "C"
+{
+#endif
+
+typedef struct DIR DIR;
+
+#define DT_UNKNOWN 0
+#define DT_FIFO 1
+#define DT_CHR 2
+#define DT_DIR 4
+#define DT_BLK 6
+#define DT_REG 8
+#define DT_LNK 10
+#define DT_SOCK 12
+#define DT_WHT 14
+
+struct dirent
+{
+ char *d_name;
+ unsigned char d_type;
+};
+
+DIR *opendir(const char *);
+int closedir(DIR *);
+struct dirent *readdir(DIR *);
+void rewinddir(DIR *);
+
+/*
+
+ Copyright Kevlin Henney, 1997, 2003. All rights reserved.
+
+ Permission to use, copy, modify, and distribute this software and its
+ documentation for any purpose is hereby granted without fee, provided
+ that this copyright and permissions notice appear in all copies and
+ derivatives.
+
+ This software is supplied "as is" without express or implied warranty.
+
+ But that said, if there are any problems please get in touch.
+
+*/
+
+#ifdef __cplusplus
+}
+#endif
+
+#endif
diff --git a/tools/TexturePacker/XBMCTex.cpp b/tools/TexturePacker/XBMCTex.cpp
new file mode 100644
index 0000000000..07d3ca9302
--- /dev/null
+++ b/tools/TexturePacker/XBMCTex.cpp
@@ -0,0 +1,437 @@
+/*
+ * Copyright (C) 2005-2009 Team XBMC
+ * http://www.xbmc.org
+ *
+ * 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, 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 XBMC; see the file COPYING. If not, write to
+ * the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
+ * http://www.gnu.org/copyleft/gpl.html
+ *
+ */
+
+#include <sys/types.h>
+#include <dirent.h>
+#include <squish.h>
+#include <string>
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+#include <SDL/SDL.h>
+#include <SDL/SDL_image.h>
+#include "XBTF.h"
+#include "XBTFWriter.h"
+#include "SDL_anigif.h"
+#include "cmdlineargs.h"
+#ifdef _WIN32
+#define strncasecmp strnicmp
+#endif
+
+#ifdef _LINUX
+#include <lzo1x.h>
+#else
+#include "../../xbmc/lib/liblzo/LZO1X.H"
+#endif
+
+#define DIR_SEPARATOR "/"
+#define DIR_SEPARATOR_CHAR '/'
+
+#define FLAGS_USE_LZO 1
+#define FLAGS_ALLOW_YCOCG 2
+
+#undef main
+
+const char *GetFormatString(unsigned int format)
+{
+ switch (format)
+ {
+ case XB_FMT_DXT1:
+ return "DXT1 ";
+ case XB_FMT_DXT3:
+ return "DXT3 ";
+ case XB_FMT_DXT5:
+ return "DXT5 ";
+ case XB_FMT_DXT5_YCoCg:
+ return "YCoCg";
+ case XB_FMT_A8R8G8B8:
+ return "ARGB ";
+ case XB_FMT_A8:
+ return "A8 ";
+ default:
+ return "?????";
+ }
+}
+
+// returns true for png, bmp, tga, jpg and dds files, otherwise returns false
+bool IsGraphicsFile(char *strFileName)
+{
+ size_t n = strlen(strFileName);
+ if (n < 4)
+ return false;
+
+ if (strncasecmp(&strFileName[n-4], ".png", 4) &&
+ strncasecmp(&strFileName[n-4], ".bmp", 4) &&
+ strncasecmp(&strFileName[n-4], ".tga", 4) &&
+ strncasecmp(&strFileName[n-4], ".gif", 4) &&
+ strncasecmp(&strFileName[n-4], ".tbn", 4) &&
+ strncasecmp(&strFileName[n-4], ".jpg", 4))
+ return false;
+
+ return true;
+}
+
+// returns true for png, bmp, tga, jpg and dds files, otherwise returns false
+bool IsGIF(const char *strFileName)
+{
+ size_t n = strlen(strFileName);
+ if (n < 4)
+ return false;
+
+ if (strncasecmp(&strFileName[n-4], ".gif", 4))
+ return false;
+
+ return true;
+}
+
+void CreateSkeletonHeaderImpl(CXBTF& xbtf, std::string fullPath, std::string relativePath)
+{
+ struct dirent* dp;
+ DIR *dirp = opendir(fullPath.c_str());
+
+ while ((dp = readdir(dirp)) != NULL)
+ {
+ if (strcmp(dp->d_name, ".") == 0 || strcmp(dp->d_name, "..") == 0)
+ {
+ continue;
+ }
+
+ if (dp->d_type == DT_DIR)
+ {
+ std::string tmpPath = relativePath;
+ if (tmpPath.size() > 0)
+ {
+ tmpPath += "/";
+ }
+
+ CreateSkeletonHeaderImpl(xbtf, fullPath + DIR_SEPARATOR + dp->d_name, tmpPath + dp->d_name);
+ }
+ else if (IsGraphicsFile(dp->d_name))
+ {
+ std::string fileName = "";
+ if (relativePath.size() > 0)
+ {
+ fileName += relativePath;
+ fileName += "/";
+ }
+
+ fileName += dp->d_name;
+
+ CXBTFFile file;
+ file.SetPath(fileName);
+ xbtf.GetFiles().push_back(file);
+ }
+ }
+
+ closedir(dirp);
+}
+
+void CreateSkeletonHeader(CXBTF& xbtf, std::string fullPath)
+{
+ std::string temp;
+ CreateSkeletonHeaderImpl(xbtf, fullPath, temp);
+}
+
+CXBTFFrame appendContent(CXBTFWriter &writer, int width, int height, unsigned char *data, unsigned int size, unsigned int format, unsigned int flags)
+{
+ CXBTFFrame frame;
+ lzo_uint compressedSize = size;
+ if ((flags & FLAGS_USE_LZO) == FLAGS_USE_LZO)
+ {
+ // grab a temporary buffer for unpacking into
+ squish::u8 *compressed = new squish::u8[size + size / 16 + 64 + 3]; // see simple.c in lzo
+ squish::u8 *working = new squish::u8[LZO1X_999_MEM_COMPRESS];
+ if (compressed && working)
+ {
+ if (lzo1x_999_compress(data, size, compressed, (lzo_uint*)&compressedSize, working) != LZO_E_OK || compressedSize > size)
+ {
+ // compression failed, or compressed size is bigger than uncompressed, so store as uncompressed
+ compressedSize = size;
+ writer.AppendContent(data, size);
+ }
+ else
+ { // success
+ lzo_uint optimSize = size;
+ lzo1x_optimize(compressed, compressedSize, data, &optimSize, NULL);
+ writer.AppendContent(compressed, compressedSize);
+ }
+ delete[] working;
+ delete[] compressed;
+ }
+ }
+ else
+ {
+ writer.AppendContent(data, size);
+ }
+ frame.SetPackedSize(compressedSize);
+ frame.SetUnpackedSize(size);
+ frame.SetWidth(width);
+ frame.SetHeight(height);
+ frame.SetFormat(format);
+ frame.SetDuration(0);
+ return frame;
+}
+
+void CompressImage(const squish::u8 *brga, int width, int height, squish::u8 *compressed, unsigned int flags, double &colorMSE, double &alphaMSE)
+{
+ squish::CompressImage(brga, width, height, compressed, flags | squish::kSourceBGRA);
+ squish::ComputeMSE(brga, width, height, compressed, flags | squish::kSourceBGRA, colorMSE, alphaMSE);
+}
+
+CXBTFFrame createXBTFFrame(SDL_Surface* image, CXBTFWriter& writer, double maxMSE, unsigned int flags)
+{
+ // Convert to ARGB
+ SDL_PixelFormat argbFormat;
+ memset(&argbFormat, 0, sizeof(SDL_PixelFormat));
+ argbFormat.BitsPerPixel = 32;
+ argbFormat.BytesPerPixel = 4;
+
+ // For DXT5 we need RGBA
+#if SDL_BYTEORDER == SDL_LIL_ENDIAN
+ argbFormat.Amask = 0xff000000;
+ argbFormat.Ashift = 24;
+ argbFormat.Rmask = 0x00ff0000;
+ argbFormat.Rshift = 16;
+ argbFormat.Gmask = 0x0000ff00;
+ argbFormat.Gshift = 8;
+ argbFormat.Bmask = 0x000000ff;
+ argbFormat.Bshift = 0;
+#else
+ argbFormat.Amask = 0x000000ff;
+ argbFormat.Ashift = 0;
+ argbFormat.Rmask = 0x0000ff00;
+ argbFormat.Rshift = 8;
+ argbFormat.Gmask = 0x00ff0000;
+ argbFormat.Gshift = 16;
+ argbFormat.Bmask = 0xff000000;
+ argbFormat.Bshift = 24;
+#endif
+
+ SDL_Surface *argbImage = SDL_ConvertSurface(image, &argbFormat, 0);
+
+ unsigned int format = 0;
+ double colorMSE, alphaMSE;
+ squish::u8* argb = (squish::u8 *)argbImage->pixels;
+ unsigned int compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5);
+ squish::u8* compressed = new squish::u8[compressedSize];
+ // first try DXT1, which is only 4bits/pixel
+ CompressImage(argb, image->w, image->h, compressed, squish::kDxt1, colorMSE, alphaMSE);
+ if (colorMSE < maxMSE && alphaMSE < maxMSE)
+ { // success - use it
+ compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt1);
+ format = XB_FMT_DXT1;
+ }
+ if (!format && alphaMSE == 0 && (flags & FLAGS_ALLOW_YCOCG) == FLAGS_ALLOW_YCOCG)
+ { // no alpha channel, so DXT5YCoCg is going to be the best DXT5 format
+/* CompressImage(argb, image->w, image->h, compressed, squish::kDxt5 | squish::kUseYCoCg, colorMSE, alphaMSE);
+ if (colorMSE < maxMSE && alphaMSE < maxMSE)
+ { // success - use it
+ compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5);
+ format = XB_FMT_DXT5_YCoCg;
+ }
+ */
+ }
+ if (!format)
+ { // try DXT3 and DXT5 - use whichever is better (color is the same, but alpha will be different)
+ CompressImage(argb, image->w, image->h, compressed, squish::kDxt3, colorMSE, alphaMSE);
+ if (colorMSE < maxMSE)
+ { // color is fine, test DXT5 as well
+ double dxt5MSE;
+ squish::u8* compressed2 = new squish::u8[squish::GetStorageRequirements(image->w, image->h, squish::kDxt5)];
+ CompressImage(argb, image->w, image->h, compressed2, squish::kDxt5, colorMSE, dxt5MSE);
+ if (alphaMSE < maxMSE && alphaMSE < dxt5MSE)
+ { // DXT3 passes and is best
+ compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt3);
+ format = XB_FMT_DXT3;
+ }
+ else if (dxt5MSE < maxMSE)
+ { // DXT5 passes
+ compressedSize = squish::GetStorageRequirements(image->w, image->h, squish::kDxt5);
+ memcpy(compressed, compressed2, compressedSize);
+ format = XB_FMT_DXT5;
+ }
+ delete[] compressed2;
+ }
+ }
+ CXBTFFrame frame;
+ if (!format)
+ { // none of the compressed stuff works for us, so we use 32bit texture
+ format = XB_FMT_A8R8G8B8;
+ frame = appendContent(writer, image->w, image->h, argb, image->w * image->h * 4, format, flags);
+ }
+ else
+ {
+ frame = appendContent(writer, image->w, image->h, compressed, compressedSize, format, flags);
+ }
+ delete[] compressed;
+ SDL_FreeSurface(argbImage);
+ return frame;
+}
+
+void Usage()
+{
+ puts("Usage:");
+ puts(" -help Show this screen.");
+ puts(" -input <dir> Input directory. Default: current dir");
+ puts(" -output <dir> Output directory/filename. Default: Textures.xpr");
+}
+
+int createBundle(const std::string& InputDir, const std::string& OutputFile, double maxMSE, unsigned int flags)
+{
+ CXBTF xbtf;
+ CreateSkeletonHeader(xbtf, InputDir);
+
+ CXBTFWriter writer(xbtf, OutputFile);
+ if (!writer.Create())
+ {
+ printf("Error creating file\n");
+ return 1;
+ }
+
+ std::vector<CXBTFFile>& files = xbtf.GetFiles();
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ CXBTFFile& file = files[i];
+
+ std::string fullPath = InputDir;
+ fullPath += file.GetPath();
+
+ std::string output = file.GetPath();
+ output = output.substr(0, 40);
+ while (output.size() < 46)
+ output += ' ';
+ if (!IsGIF(fullPath.c_str()))
+ {
+ // Load the image
+ SDL_Surface* image = IMG_Load(fullPath.c_str());
+ if (!image)
+ {
+ printf("...unable to load image %s\n", file.GetPath());
+ continue;
+ }
+
+ printf(output.c_str());
+
+ CXBTFFrame frame = createXBTFFrame(image, writer, maxMSE, flags);
+
+ printf("%s (%d,%d @ %"PRIu64" bytes)\n", GetFormatString(frame.GetFormat()), frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize());
+
+ file.SetLoop(0);
+ file.GetFrames().push_back(frame);
+
+ SDL_FreeSurface(image);
+ }
+ else
+ {
+ int gnAG = AG_LoadGIF(fullPath.c_str(), NULL, 0);
+ AG_Frame* gpAG = new AG_Frame[gnAG];
+ AG_LoadGIF(fullPath.c_str(), gpAG, gnAG);
+
+ printf("%s\n", output.c_str());
+
+ for (int j = 0; j < gnAG; j++)
+ {
+ printf(" frame %4i ", j);
+ CXBTFFrame frame = createXBTFFrame(gpAG[j].surface, writer, maxMSE, flags);
+ frame.SetDuration(gpAG[j].delay);
+ file.GetFrames().push_back(frame);
+ printf("%s (%d,%d @ %"PRIu64" bytes)\n", GetFormatString(frame.GetFormat()), frame.GetWidth(), frame.GetHeight(), frame.GetUnpackedSize());
+ }
+
+ AG_FreeSurfaces(gpAG, gnAG);
+ delete [] gpAG;
+
+ file.SetLoop(0);
+ }
+ }
+
+ if (!writer.UpdateHeader())
+ {
+ printf("Error writing header to file\n");
+ return 1;
+ }
+
+ if (!writer.Close())
+ {
+ printf("Error closing file\n");
+ return 1;
+ }
+
+ return 0;
+}
+
+int main(int argc, char* argv[])
+{
+ if (lzo_init() != LZO_E_OK)
+ return 1;
+
+ bool valid = false;
+ CmdLineArgs args(argc, (const char**)argv);
+
+ if (args.size() == 1)
+ {
+ Usage();
+ return 1;
+ }
+
+ std::string InputDir;
+ std::string OutputFilename = "Textures.xbt";
+
+ for (unsigned int i = 1; i < args.size(); ++i)
+ {
+ if (!stricmp(args[i], "-help") || !stricmp(args[i], "-h") || !stricmp(args[i], "-?"))
+ {
+ Usage();
+ return 1;
+ }
+ else if (!stricmp(args[i], "-input") || !stricmp(args[i], "-i"))
+ {
+ InputDir = args[++i];
+ valid = true;
+ }
+ else if (!stricmp(args[i], "-output") || !stricmp(args[i], "-o"))
+ {
+ OutputFilename = args[++i];
+ valid = true;
+#ifdef _LINUX
+ char *c = NULL;
+ while ((c = (char *)strchr(OutputFilename.c_str(), '\\')) != NULL) *c = '/';
+#endif
+ }
+ else
+ {
+ printf("Unrecognized command line flag: %s\n", args[i]);
+ }
+ }
+
+ if (!valid)
+ {
+ Usage();
+ return 1;
+ }
+
+ size_t pos = InputDir.find_last_of(DIR_SEPARATOR);
+ if (pos != InputDir.length() - 1)
+ InputDir += DIR_SEPARATOR;
+
+ double maxMSE = 1.5; // HQ only please
+ unsigned int flags = FLAGS_USE_LZO; // TODO: currently no YCoCg (commandline option?)
+ createBundle(InputDir, OutputFilename, maxMSE, flags);
+}
diff --git a/tools/TexturePacker/XBTFWriter.cpp b/tools/TexturePacker/XBTFWriter.cpp
new file mode 100644
index 0000000000..eea8195382
--- /dev/null
+++ b/tools/TexturePacker/XBTFWriter.cpp
@@ -0,0 +1,132 @@
+#include "XBTFWriter.h"
+#include "EndianSwap.h"
+#define __STDC_FORMAT_MACROS
+#include <inttypes.h>
+
+#define TEMP_FILE "temp.xbt"
+#define TEMP_SIZE (10*1024*1024)
+
+#define WRITE_STR(str, size, file) fwrite(str, size, 1, file)
+#define WRITE_U32(i, file) { uint32_t _n = Endian_SwapLE32(i); fwrite(&_n, 4, 1, file); }
+#define WRITE_U64(i, file) { uint64_t _n = i; _n = Endian_SwapLE64(i); fwrite(&_n, 8, 1, file); }
+
+CXBTFWriter::CXBTFWriter(CXBTF& xbtf, const std::string outputFile) : m_xbtf(xbtf)
+{
+ m_outputFile = outputFile;
+ m_file = NULL;
+}
+
+bool CXBTFWriter::Create()
+{
+ m_file = fopen(m_outputFile.c_str(), "wb");
+ if (m_file == NULL)
+ {
+ return false;
+ }
+
+ m_tempFile = fopen(TEMP_FILE, "wb");
+ if (m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ return true;
+}
+
+bool CXBTFWriter::Close()
+{
+ if (m_file == NULL || m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ fclose(m_tempFile);
+ m_tempFile = fopen(TEMP_FILE, "rb");
+ if (m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ unsigned char* tmp = new unsigned char[10*1024*1024];
+ size_t bytesRead;
+ while ((bytesRead = fread(tmp, 1, TEMP_SIZE, m_tempFile)) > 0)
+ {
+ fwrite(tmp, bytesRead, 1, m_file);
+ }
+
+ fclose(m_file);
+ fclose(m_tempFile);
+ unlink(TEMP_FILE);
+
+ return true;
+}
+
+bool CXBTFWriter::AppendContent(unsigned char const* data, size_t length)
+{
+ if (m_tempFile == NULL)
+ {
+ return false;
+ }
+
+ fwrite(data, length, 1, m_tempFile);
+
+ return true;
+}
+
+bool CXBTFWriter::UpdateHeader()
+{
+ if (m_file == NULL)
+ {
+ return false;
+ }
+
+ uint64_t offset = m_xbtf.GetHeaderSize();
+
+ WRITE_STR(XBTF_MAGIC, 4, m_file);
+ WRITE_STR(XBTF_VERSION, 1, m_file);
+
+ std::vector<CXBTFFile>& files = m_xbtf.GetFiles();
+ WRITE_U32(files.size(), m_file);
+ for (size_t i = 0; i < files.size(); i++)
+ {
+ CXBTFFile& file = files[i];
+
+ // Convert path to lower case
+ char* ch = file.GetPath();
+ while (*ch)
+ {
+ *ch = tolower(*ch);
+ ch++;
+ }
+
+ WRITE_STR(file.GetPath(), 256, m_file);
+ WRITE_U32(file.GetLoop(), m_file);
+
+ std::vector<CXBTFFrame>& frames = file.GetFrames();
+ WRITE_U32(frames.size(), m_file);
+ for (size_t j = 0; j < frames.size(); j++)
+ {
+ CXBTFFrame& frame = frames[j];
+ frame.SetOffset(offset);
+ offset += frame.GetPackedSize();
+
+ WRITE_U32(frame.GetWidth(), m_file);
+ WRITE_U32(frame.GetHeight(), m_file);
+ WRITE_U32(frame.GetFormat(), m_file);
+ WRITE_U64(frame.GetPackedSize(), m_file);
+ WRITE_U64(frame.GetUnpackedSize(), m_file);
+ WRITE_U32(frame.GetDuration(), m_file);
+ WRITE_U64(frame.GetOffset(), m_file);
+ }
+ }
+
+ // Sanity check
+ int64_t pos = ftell(m_file);
+ if (pos != m_xbtf.GetHeaderSize())
+ {
+ printf("Expected header size (%" PRId64 ") != actual size (%" PRId64 ")\n", m_xbtf.GetHeaderSize(), pos);
+ return false;
+ }
+
+ return true;
+}
diff --git a/tools/TexturePacker/XBTFWriter.h b/tools/TexturePacker/XBTFWriter.h
new file mode 100644
index 0000000000..806c468ee6
--- /dev/null
+++ b/tools/TexturePacker/XBTFWriter.h
@@ -0,0 +1,24 @@
+#ifndef XBTFWRITER_H_
+#define XBTFWRITER_H_
+
+#include <string>
+#include <stdio.h>
+#include "XBTF.h"
+
+class CXBTFWriter
+{
+public:
+ CXBTFWriter(CXBTF& xbtf, const std::string outputFile);
+ bool Create();
+ bool Close();
+ bool AppendContent(unsigned char const* data, size_t length);
+ bool UpdateHeader();
+
+private:
+ CXBTF& m_xbtf;
+ std::string m_outputFile;
+ FILE* m_file;
+ FILE* m_tempFile;
+};
+
+#endif
diff --git a/tools/TexturePacker/cmdlineargs.h b/tools/TexturePacker/cmdlineargs.h
new file mode 100644
index 0000000000..a9f5891722
--- /dev/null
+++ b/tools/TexturePacker/cmdlineargs.h
@@ -0,0 +1,123 @@
+#ifndef CMDLINEARGS_H
+#define CMDLINEARGS_H
+
+#ifdef _LINUX
+#include "PlatformDefs.h"
+#include "xwinapi.h"
+typedef LPSTR PSZ;
+#define _snprintf snprintf
+#else
+#include <windows.h>
+#endif
+#include <vector>
+#include <string>
+
+class CmdLineArgs : public std::vector<char*>
+{
+public:
+ CmdLineArgs ()
+ {
+ // Save local copy of the command line string, because
+ // ParseCmdLine() modifies this string while parsing it.
+ PSZ cmdline = GetCommandLine();
+ m_cmdline = new char [strlen (cmdline) + 1];
+ if (m_cmdline)
+ {
+ strcpy (m_cmdline, cmdline);
+ ParseCmdLine();
+ } else {
+#ifdef _LINUX
+ delete[] cmdline;
+#endif
+ }
+ }
+
+ CmdLineArgs (const int argc, const char **argv)
+ {
+ std::string cmdline;
+ for (int i = 0 ; i<argc ; i++)
+ {
+ cmdline += std::string(argv[i]);
+ if ( i != (argc-1) )
+ {
+ cmdline += " ";
+ }
+ }
+ m_cmdline = new char [cmdline.length() + 1];
+ if (m_cmdline)
+ {
+ strcpy(m_cmdline, cmdline.c_str());
+ ParseCmdLine();
+ }
+ }
+
+ ~CmdLineArgs()
+ {
+ delete[] m_cmdline;
+ }
+
+private:
+ PSZ m_cmdline; // the command line string
+
+ ////////////////////////////////////////////////////////////////////////////////
+ // Parse m_cmdline into individual tokens, which are delimited by spaces. If a
+ // token begins with a quote, then that token is terminated by the next quote
+ // followed immediately by a space or terminator. This allows tokens to contain
+ // spaces.
+ // This input string: This "is" a ""test"" "of the parsing" alg"o"rithm.
+ // Produces these tokens: This, is, a, "test", of the parsing, alg"o"rithm
+ ////////////////////////////////////////////////////////////////////////////////
+ void ParseCmdLine ()
+ {
+ enum { TERM = '\0',
+ QUOTE = '\"' };
+
+ bool bInQuotes = false;
+ PSZ pargs = m_cmdline;
+
+ while (*pargs)
+ {
+ while (isspace (*pargs)) // skip leading whitespace
+ pargs++;
+
+ bInQuotes = (*pargs == QUOTE); // see if this token is quoted
+
+ if (bInQuotes) // skip leading quote
+ pargs++;
+
+ push_back (pargs); // store position of current token
+
+ // Find next token.
+ // NOTE: Args are normally terminated by whitespace, unless the
+ // arg is quoted. That's why we handle the two cases separately,
+ // even though they are very similar.
+ if (bInQuotes)
+ {
+ // find next quote followed by a space or terminator
+ while (*pargs &&
+ !(*pargs == QUOTE && (isspace (pargs[1]) || pargs[1] == TERM)))
+ pargs++;
+ if (*pargs)
+ {
+ *pargs = TERM; // terminate token
+ if (pargs[1]) // if quoted token not followed by a terminator
+ pargs += 2; // advance to next token
+ }
+ }
+ else
+ {
+ // skip to next non-whitespace character
+ while (*pargs && !isspace (*pargs))
+ pargs++;
+ if (*pargs && isspace (*pargs)) // end of token
+ {
+ *pargs = TERM; // terminate token
+ pargs++; // advance to next token or terminator
+ }
+ }
+ } // while (*pargs)
+ } // ParseCmdLine()
+}; // class CmdLineArgs
+
+
+#endif // CMDLINEARGS_H
diff --git a/tools/TexturePacker/xwinapi.cpp b/tools/TexturePacker/xwinapi.cpp
new file mode 100644
index 0000000000..ea5955c837
--- /dev/null
+++ b/tools/TexturePacker/xwinapi.cpp
@@ -0,0 +1,81 @@
+
+#include <stdio.h>
+#include <stdlib.h>
+#include <sys/types.h>
+#include <unistd.h>
+#include <string.h>
+#include <errno.h>
+#include "xwinapi.h"
+#ifdef __APPLE__
+#include "OSXGNUReplacements.h"
+#endif
+
+// I hope this doesn't need to handle unicode...
+LPTSTR GetCommandLine() {
+ pid_t pid = 0;
+ char procFile[32],
+ *cmdline = NULL;
+ FILE *fp = NULL;
+ size_t cmdlinelen = 0;
+ int i;
+
+ pid = getpid();
+ sprintf(procFile, "/proc/%u/cmdline", pid);
+ if((fp = fopen(procFile, "r")) == NULL)
+ return NULL;
+
+ // getline() allocates memory so be sure to free it
+ // after calling GetCommandLine()
+ if (getline(&cmdline, &cmdlinelen, fp) == -1)
+ {
+ fclose(fp);
+ return NULL;
+ }
+
+ fclose(fp);
+ fp = NULL;
+
+ for (i = 0; i < (int)cmdlinelen; i++) {
+ if (cmdline[i] == 0x00) {
+ if (cmdline[i + 1] == 0x00)
+ break;
+ cmdline[i] = ' ';
+ }
+ }
+
+ cmdline = (char *)realloc(cmdline, strlen(cmdline) + 1);
+ return cmdline;
+}
+
+DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer) {
+ bool bSizeTest = (nBufferLength == 0 && lpBuffer == NULL);
+ if (getcwd(lpBuffer, nBufferLength) == NULL) {
+ if (errno == ERANGE) {
+ LPTSTR tmp = NULL;
+ if (getcwd(tmp, 0) == NULL )
+ nBufferLength = 0;
+ else
+ nBufferLength = strlen(tmp) + 1;
+
+ free(tmp);
+ return nBufferLength;
+ }
+ return 0;
+ }
+ if (bSizeTest) {
+ nBufferLength = strlen(lpBuffer) + 1;
+ free(lpBuffer);
+ lpBuffer = NULL;
+ return nBufferLength;
+ }
+ return strlen(lpBuffer);
+}
+
+BOOL SetCurrentDirectory(LPCTSTR lpPathName) {
+ return (chdir(lpPathName) == 0);
+}
+
+DWORD GetLastError( ) {
+ return errno;
+}
+
diff --git a/tools/TexturePacker/xwinapi.h b/tools/TexturePacker/xwinapi.h
new file mode 100644
index 0000000000..be97e4c00a
--- /dev/null
+++ b/tools/TexturePacker/xwinapi.h
@@ -0,0 +1,11 @@
+#ifndef XWINAPI_H__
+#define XWINAPI_H__
+
+#include "PlatformDefs.h"
+
+LPTSTR GetCommandLine();
+DWORD GetCurrentDirectory(DWORD nBufferLength, LPTSTR lpBuffer);
+BOOL SetCurrentDirectory(LPCTSTR lpPathName);
+DWORD GetLastError();
+#endif // XWINAPI_H__
+