about summary refs log tree commit diff
path: root/src/engine/client
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-05-27 00:47:07 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-05-27 00:47:07 +0000
commitbdcc0b09ddc630c166f0dfebcf376765fb1f9801 (patch)
tree90fd22f041b6e4519f3459fcad983930afc2a647 /src/engine/client
parent4a128a9609cc5fc61077b3cd73ffa831551b7dc2 (diff)
downloadzcatch-bdcc0b09ddc630c166f0dfebcf376765fb1f9801.tar.gz
zcatch-bdcc0b09ddc630c166f0dfebcf376765fb1f9801.zip
major update. added png support. fixed abit with the network
Diffstat (limited to 'src/engine/client')
-rw-r--r--src/engine/client/client.cpp15
-rw-r--r--src/engine/client/gfx.cpp91
-rw-r--r--src/engine/client/pnglite/pnglite.c612
-rw-r--r--src/engine/client/pnglite/pnglite.h212
4 files changed, 915 insertions, 15 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index 4aceaf0f..dd52608c 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -6,6 +6,7 @@
 
 #include <string.h>
 #include <stdarg.h>
+#include <stdlib.h>
 #include <math.h>
 #include <engine/interface.h>
 
@@ -331,7 +332,7 @@ public:
 		*/
 		
 		packet p(NETMSG_CLIENT_CONNECT);
-		p.write_str(TEEWARS_NETVERSION); // payload
+		p.write_str(TEEWARS_VERSION); // payload
 		p.write_str(name);
 		p.write_str("no clan");
 		p.write_str("password");
@@ -388,7 +389,7 @@ public:
 	
 	bool load_data()
 	{
-		debug_font = gfx_load_texture_tga("data/debug_font.tga");
+		debug_font = gfx_load_texture("data/debug_font.png");
 		return true;
 	}
 	
@@ -420,8 +421,8 @@ public:
 			
 			if (!inited)
 			{
-				tee_texture = gfx_load_texture_tga("data/gui_tee.tga");
-				connecting_texture = gfx_load_texture_tga("data/gui/connecting.tga");
+				tee_texture = gfx_load_texture("data/gui_tee.png");
+				connecting_texture = gfx_load_texture("data/gui/connecting.png");
 					
 				inited = true;
 			}
@@ -565,7 +566,11 @@ public:
 
 	void process_packet(packet *p)
 	{
-		if(p->msg() == NETMSG_SERVER_ACCEPT)
+		if(p->version() != TEEWARS_NETVERSION)
+		{
+			error("wrong version");
+		}
+		else if(p->msg() == NETMSG_SERVER_ACCEPT)
 		{
 			const char *map;
 			map = p->read_str();
diff --git a/src/engine/client/gfx.cpp b/src/engine/client/gfx.cpp
index a824feac..71b5de7d 100644
--- a/src/engine/client/gfx.cpp
+++ b/src/engine/client/gfx.cpp
@@ -4,6 +4,11 @@
 
 #include <engine/interface.h>
 
+#include "pnglite/pnglite.h"
+
+#include <string.h>
+
+
 using namespace baselib;
 
 static opengl::context context;
@@ -150,7 +155,7 @@ bool gfx_init(bool fullscreen)
 	textures[MAX_TEXTURES-1].next = -1;
 	
 	// create null texture, will get id=0
-	gfx_load_texture_raw(4,4,null_texture_data);
+	gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data);
 	
 	return true;
 }
@@ -175,7 +180,7 @@ void gfx_blend_additive()
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
 }
 
-int gfx_load_texture_raw(int w, int h, const void *data)
+int gfx_load_texture_raw(int w, int h, int format, const void *data)
 {
 	// grab texture
 	int tex = first_free_texture;
@@ -185,20 +190,51 @@ int gfx_load_texture_raw(int w, int h, const void *data)
 	// set data and return
 	// TODO: should be RGBA, not BGRA
 	dbg_msg("gfx", "%d = %dx%d", tex, w, h);
-	textures[tex].tex.data2d(w, h, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, data);
+	if(format == IMG_RGB)
+		textures[tex].tex.data2d(w, h, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data);
+	else if(format == IMG_RGBA)
+		textures[tex].tex.data2d(w, h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data);
+	else if(format == IMG_BGR)
+		textures[tex].tex.data2d(w, h, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, data);
+	else if(format == IMG_BGRA)
+		textures[tex].tex.data2d(w, h, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, data);
 	return tex;
 }
 
 // simple uncompressed RGBA loaders
-int gfx_load_texture_tga(const char *filename)
+int gfx_load_texture(const char *filename)
 {
-	image_info img;
-	
-	if(gfx_load_tga(&img, filename))
+	int l = strlen(filename);
+	if(l < 3)
+		return 0;
+
+	if(	(filename[l-3] == 't' || filename[l-3] == 'T') &&
+		(filename[l-2] == 'g' || filename[l-2] == 'G') &&
+		(filename[l-1] == 'a' || filename[l-1] == 'A'))
+	{
+		image_info img;
+		if(gfx_load_tga(&img, filename))
+		{
+			int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data);
+			mem_free(img.data);
+			return id;
+		}
+		return 0;
+	}
+
+	if(	(filename[l-3] == 'p' || filename[l-3] == 'P') &&
+		(filename[l-2] == 'n' || filename[l-2] == 'N') &&
+		(filename[l-1] == 'g' || filename[l-1] == 'G'))
 	{
-		int id = gfx_load_texture_raw(img.width, img.height, img.data);
-		mem_free(img.data);
-		return id;
+		image_info img;
+		if(gfx_load_png(&img, filename))
+		{
+			int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data);
+			mem_free(img.data);
+			return id;
+		}
+		
+		return 0;
 	}
 	
 	return 0;
@@ -240,6 +276,7 @@ int gfx_load_tga(image_info *img, const char *filename)
 	// read data
 	int data_size = img->width*img->height*4;
 	img->data = mem_alloc(data_size, 1);
+	img->format = IMG_BGRA;
 
 	if (flipy)
 	{
@@ -255,6 +292,40 @@ int gfx_load_tga(image_info *img, const char *filename)
 	return 1;
 }
 
+
+
+int gfx_load_png(image_info *img, const char *filename)
+{
+	// open file for reading
+	png_init(0,0);
+
+	png_t png;
+	if(png_open_file(&png, filename) != PNG_NO_ERROR)
+	{
+		dbg_msg("game/png", "failed to open file. filename='%s'", filename);
+		return 0;
+	}
+	
+	if(png.depth != 8 || (png.color_type != PNG_TRUECOLOR && png.color_type != PNG_TRUECOLOR_ALPHA))
+	{
+		dbg_msg("game/png", "invalid format. filename='%s'", filename);
+		png_close_file(&png);
+	}
+		
+	unsigned char *buffer = (unsigned char *)mem_alloc(png.width * png.height * png.bpp, 1);
+	png_get_data(&png, buffer);
+	png_close_file(&png);
+	
+	img->width = png.width;
+	img->height = png.height;
+	if(png.color_type == PNG_TRUECOLOR)
+		img->format = IMG_RGB;
+	else if(png.color_type == PNG_TRUECOLOR_ALPHA)
+		img->format = IMG_RGBA;
+	img->data = buffer;
+	return 1;
+}
+
 void gfx_shutdown()
 {
 	if (g_pVertices)
diff --git a/src/engine/client/pnglite/pnglite.c b/src/engine/client/pnglite/pnglite.c
new file mode 100644
index 00000000..c0e96ec6
--- /dev/null
+++ b/src/engine/client/pnglite/pnglite.c
@@ -0,0 +1,612 @@
+/*  pnglite.c - pnglite library

+    For conditions of distribution and use, see copyright notice in pnglite.h

+*/

+

+#include <zlib.h>

+#include "pnglite.h"

+#include <stdio.h>

+#include <stdlib.h>

+#include <string.h>

+

+

+#define DO_CRC_CHECKS 1

+

+static png_alloc_t png_alloc;

+static png_free_t png_free;

+

+static size_t file_read(png_t* png, void* out, size_t size, size_t numel)

+{

+	size_t result;

+	if(png->read_fun)

+	{

+		result = png->read_fun(out, size, numel, png->user_pointer);

+	}

+	else

+	{

+		if(!out)

+		{

+			result = fseek(png->user_pointer, (long)(size*numel), SEEK_CUR);

+		}

+		else

+		{

+			result = fread(out, size, numel, png->user_pointer);

+		}

+	}

+

+	return result;

+}

+

+static unsigned file_read_ul(png_t* png)

+{

+	unsigned result;

+	unsigned char buf[4];

+

+	if(file_read(png, buf, 1, 4) != 4)

+		return PNG_FILE_ERROR;

+

+	result = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];

+

+	return result;

+}

+

+static unsigned get_ul(unsigned char* buf)

+{

+	unsigned result;

+	unsigned char foo[4];

+

+	memcpy(foo, buf, 4);

+

+	result = (foo[0]<<24) | (foo[1]<<16) | (foo[2]<<8) | foo[3];

+

+	return result;

+}

+

+int png_init(png_alloc_t pngalloc, png_free_t pngfree)

+{

+	if(pngalloc)

+		png_alloc = pngalloc;

+	else

+		png_alloc = &malloc;

+

+	if(pngfree)

+		png_free = pngfree;

+	else

+		png_free = &free;

+

+	return PNG_NO_ERROR;

+}

+

+static int png_get_bpp(png_t* png)

+{

+	int bpp;

+

+	switch(png->color_type)

+	{

+	case PNG_GREYSCALE:

+		bpp = 1; break;

+	case PNG_TRUECOLOR:

+		bpp = 3; break;

+	case PNG_INDEXED:

+		bpp = 1; break;

+	case PNG_GREYSCALE_ALPHA:

+		bpp = 2; break;

+	case PNG_TRUECOLOR_ALPHA:

+		bpp = 4; break;

+	default:

+		return PNG_FILE_ERROR;

+	}

+

+	bpp *= png->depth/8;

+

+	return bpp;

+}

+

+static int png_read_ihdr(png_t* png)

+{

+	unsigned length;

+#if DO_CRC_CHECKS

+	unsigned orig_crc;

+	unsigned calc_crc;

+#endif

+	unsigned char ihdr[13+4];		 // length should be 13, make room for type (IHDR)

+

+	length = file_read_ul(png);

+

+	if(length != 13)

+	{

+		printf("%d\n", length);

+		return PNG_CRC_ERROR;

+	}

+

+	if(file_read(png, ihdr, 1, 13+4) != 13+4)

+		return PNG_EOF_ERROR;

+#if DO_CRC_CHECKS

+	orig_crc = file_read_ul(png);

+

+	calc_crc = crc32(0L, Z_NULL, 0);

+	calc_crc = crc32(calc_crc, ihdr, 13+4);

+

+	if(orig_crc != calc_crc)

+		return PNG_CRC_ERROR;

+#else

+	file_read_ul(png);

+#endif

+

+	png->width = get_ul(ihdr+4);

+	png->height = get_ul(ihdr+8);

+	png->depth = ihdr[12];

+	png->color_type = ihdr[13];

+	png->compression_method = ihdr[14];

+	png->filter_method = ihdr[15];

+	png->interlace_method = ihdr[16];

+

+	if(png->color_type == PNG_INDEXED)

+		return PNG_NOT_SUPPORTED;

+

+	if(png->depth != 8 && png->depth != 16)

+		return PNG_NOT_SUPPORTED;

+

+	if(png->interlace_method)

+		return PNG_NOT_SUPPORTED;

+	

+	return PNG_NO_ERROR;

+}

+

+void png_print_info(png_t* png)

+{

+	printf("PNG INFO:\n");

+	printf("\twidth:\t\t%d\n", png->width);

+	printf("\theight:\t\t%d\n", png->height);

+	printf("\tdepth:\t\t%d\n", png->depth);

+	printf("\tcolor:\t\t");

+

+	switch(png->color_type)

+	{

+	case PNG_GREYSCALE:			printf("greyscale\n"); break;

+	case PNG_TRUECOLOR:			printf("truecolor\n"); break;

+	case PNG_INDEXED:			printf("palette\n"); break;

+	case PNG_GREYSCALE_ALPHA:	printf("greyscale with alpha\n"); break;

+	case PNG_TRUECOLOR_ALPHA:	printf("truecolor with alpha\n"); break;

+	default:					printf("unknown, this is not good\n"); break;

+	}

+

+	printf("\tcompression:\t%s\n",	png->compression_method?"unknown, this is not good":"inflate/deflate");

+	printf("\tfilter:\t\t%s\n",		png->filter_method?"unknown, this is not good":"adaptive");

+	printf("\tinterlace:\t%s\n",	png->interlace_method?"interlace":"no interlace");

+}

+

+

+int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer)

+{

+	char header[8];

+	int result;

+

+	png->read_fun = read_fun;

+	png->user_pointer = user_pointer;

+

+	if(!read_fun && !user_pointer)

+		return PNG_WRONG_ARGUMENTS;

+

+	if(file_read(png, header, 1, 8) != 8)

+		return PNG_EOF_ERROR;

+

+	if(memcmp(header, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 8) != 0)

+		return PNG_HEADER_ERROR;

+

+	result = png_read_ihdr(png);

+

+	png->bpp = png_get_bpp(png);

+

+	return result;

+}

+

+int png_open_file(png_t *png, const char* filename)

+{

+	FILE* fp = fopen(filename, "rb");

+

+	if(!fp)

+		return PNG_FILE_ERROR;

+

+	return png_open(png, 0, fp);

+}	

+

+int png_close_file(png_t* png)

+{

+	fclose(png->user_pointer);

+

+	return PNG_NO_ERROR;

+}

+

+static int png_init_inflate(png_t* png)

+{

+	z_stream *stream;

+	png->zs = png_alloc(sizeof(z_stream));

+

+	stream = png->zs;

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	memset(stream, 0, sizeof(z_stream));

+

+	if(inflateInit(stream) != Z_OK)

+		return PNG_ZLIB_ERROR;

+

+	stream->next_out = png->png_data;

+	stream->avail_out = png->png_datalen;

+

+	return PNG_NO_ERROR;

+}

+

+static int png_end_inflate(png_t* png)

+{

+	z_stream *stream = png->zs;

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	if(inflateEnd(stream) != Z_OK)

+	{

+		printf("ZLIB says: %s\n", stream->msg);

+		return PNG_ZLIB_ERROR;

+	}

+

+	png_free(png->zs);

+

+	return PNG_NO_ERROR;

+}

+

+static int png_inflate(png_t* png, unsigned char* data, int len)

+{

+	int result;

+	z_stream *stream = png->zs;

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	stream->next_in = data;

+	stream->avail_in = len;

+	

+	result = inflate(stream, Z_SYNC_FLUSH);

+

+	if(result != Z_STREAM_END && result != Z_OK)

+	{

+		printf("%s\n", stream->msg);

+		return PNG_ZLIB_ERROR;

+	}

+

+	if(stream->avail_in != 0)

+		return PNG_ZLIB_ERROR;

+

+	return PNG_NO_ERROR;

+}

+

+static int png_read_idat(png_t* png, unsigned char* output, unsigned out_len, unsigned firstlen) 

+{

+	unsigned type;

+	char *chunk;

+	int result;

+	unsigned length = firstlen;

+	unsigned old_len = length;

+

+#if DO_CRC_CHECKS

+	unsigned orig_crc;

+	unsigned calc_crc;

+#endif

+

+	chunk = png_alloc(firstlen); 

+

+	result = png_init_inflate(png);

+

+	if(result != PNG_NO_ERROR)

+	{

+		png_end_inflate(png);

+		png_free(chunk); 

+		return result;

+	}

+

+	do

+	{

+		if(file_read(png, chunk, 1, length) != length)

+		{

+			png_end_inflate(png);

+			png_free(chunk); 

+			return PNG_FILE_ERROR;

+		}

+

+#if DO_CRC_CHECKS

+		calc_crc = crc32(0L, Z_NULL, 0);

+		calc_crc = crc32(calc_crc, "IDAT", 4);

+		calc_crc = crc32(calc_crc, chunk, length);

+

+		orig_crc = file_read_ul(png);

+

+		if(orig_crc != calc_crc)

+		{

+			result = PNG_CRC_ERROR;

+			break;

+		}

+#else

+		file_read_ul(png);

+#endif

+

+		result = png_inflate(png, chunk, length);

+

+		if(result != PNG_NO_ERROR) break;

+		

+		length = file_read_ul(png);

+

+		if(length > old_len)

+		{

+			png_free(chunk); 

+			chunk = png_alloc(length); 

+			old_len = length;

+		}

+

+		if(file_read(png, &type, 1, 4) != 4)

+		{

+			result = PNG_FILE_ERROR;

+			break;

+		}

+

+	}while(type == *(int*)"IDAT");

+

+	if(type == *(int*)"IEND")

+		result = PNG_DONE;

+

+	png_free(chunk);

+	png_end_inflate(png);

+

+	return result;

+}

+

+static int png_process_chunk(png_t* png)

+{

+	int result = PNG_NO_ERROR, idat_len = 0;

+	unsigned type;

+	unsigned length;

+

+	length = file_read_ul(png);

+

+	if(file_read(png, &type, 1, 4) != 4)

+		return PNG_FILE_ERROR;

+

+	if(type == *(int*)"IDAT")	// if we found an idat, all other idats should be followed with no other chunks in between

+	{

+		png->png_datalen = png->width * png->height * png->bpp + png->height;

+		png->png_data = png_alloc(png->png_datalen);

+		

+		if(!png->png_data)

+			return PNG_MEMORY_ERROR;

+

+		return png_read_idat(png, png->png_data, png->png_datalen, length);

+	}

+	else if(type == *(int*)"IEND")

+	{

+		return PNG_DONE;

+	}

+	else

+	{

+		file_read(png, 0, 1, length + 4);		// unknown chunk

+	}

+

+	return result;

+}

+

+static void png_filter_sub(png_t* png, int stride, unsigned char* in, unsigned char* out, int len)

+{

+	int i;

+	unsigned char a = 0;

+

+	for(i = 0; i < len; i++)

+	{

+		if(i >= stride)

+			a = out[i - stride];

+		

+		out[i] = in[i] + a;

+	}

+}

+

+static void png_filter_up(png_t* png, int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

+{

+	int i;

+

+	if(prev_line) 

+    { 

+        for(i = 0; i < len; i++) 

+            out[i] = in[i] + prev_line[i]; 

+    } 

+    else 

+        memcpy(out, in, len);

+}

+

+static void png_filter_average(png_t* png, int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

+{

+	int i;

+	unsigned char a = 0;

+	unsigned char b = 0;

+	unsigned int sum = 0;

+

+	for(i = 0; i < len; i++)

+	{

+		if(prev_line)

+			b = prev_line[i];

+

+		if(i >= stride)

+			a = out[i - stride];

+

+		sum = a;

+		sum += b;

+

+		out[i] = in[i] + sum/2;

+	}

+}

+

+static unsigned char png_paeth(unsigned char a, unsigned char b, unsigned char c)

+{

+	int p = (int)a + b - c;

+	int pa = abs(p - a);

+	int pb = abs(p - b);

+	int pc = abs(p - c);

+

+	int pr;

+

+	if(pa <= pb && pa <= pc)

+		pr = a;

+	else if(pb <= pc)

+		pr = b;

+	else

+		pr = c;

+

+	return pr;

+}

+

+static void png_filter_paeth(png_t* png, int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

+{

+	int i;

+	unsigned char a;

+	unsigned char b;

+	unsigned char c;

+

+	for(i = 0; i < len; i++)

+	{

+		if(prev_line && i >= stride)

+		{

+			a = out[i - stride];

+			b = prev_line[i];

+			c = prev_line[i - stride];

+		}

+		else

+		{

+			if(prev_line)

+				b = prev_line[i];

+			else

+				b = 0;

+	

+			if(i >= stride)

+				a = out[i - stride];

+			else

+				a = 0;

+

+			c = 0;

+		}

+

+		out[i] = in[i] + png_paeth(a, b, c);

+	}

+}

+

+static int png_unfilter(png_t* png, unsigned char* data)

+{

+	unsigned i;

+	unsigned pos = 0;

+	unsigned outpos = 0;

+	unsigned char *filtered = png->png_data;

+

+	int stride = png->bpp;

+

+	while(pos < png->png_datalen)

+	{

+		unsigned char filter = filtered[pos];

+

+		pos++;

+

+		if(png->depth == 16)

+		{

+			for(i = 0; i < png->width * stride; i+=2)

+			{

+				*(short*)(filtered+pos+i) = (filtered[pos+i] << 8) | filtered[pos+i+1];

+			}

+		}

+

+		switch(filter)

+		{

+		case 0: // none

+			memcpy(data+outpos, filtered+pos, png->width * stride);

+			break;

+		case 1: // sub

+			png_filter_sub(png, stride, filtered+pos, data+outpos, png->width * stride);

+			break;

+		case 2: // up

+			if(outpos)

+				png_filter_up(png, stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);

+			else

+				png_filter_up(png, stride, filtered+pos, data+outpos, 0, png->width*stride);

+			break;

+		case 3: // average

+			if(outpos)

+				png_filter_average(png, stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);

+			else

+				png_filter_average(png, stride, filtered+pos, data+outpos, 0, png->width*stride);

+			break;

+		case 4: // paeth

+			if(outpos)

+				png_filter_paeth(png, stride, filtered+pos, data+outpos, data + outpos - (png->width*stride), png->width*stride);

+			else

+				png_filter_paeth(png, stride, filtered+pos, data+outpos, 0, png->width*stride);

+			break;

+		default:

+			return PNG_UNKNOWN_FILTER;

+		}

+

+		outpos += png->width * stride;

+		pos += png->width * stride;

+	}

+

+	return PNG_NO_ERROR;

+}

+

+int png_get_data(png_t* png, unsigned char* data)

+{

+	int result = PNG_NO_ERROR;

+

+	while(result == PNG_NO_ERROR)

+	{

+		result = png_process_chunk(png);

+	}

+

+	if(result != PNG_DONE)

+	{

+		png_free(png->png_data); 

+		return result;

+	}

+

+	result = png_unfilter(png, data);

+

+	png_free(png->png_data); 

+

+	return result;

+}

+

+char* png_error_string(int error)

+{

+	switch(error)

+	{

+	case PNG_NO_ERROR:

+		return "No error";

+	case PNG_FILE_ERROR:

+		return "Unknown file error.";

+	case PNG_HEADER_ERROR:

+		return "No PNG header found. Are you sure this is a PNG?";

+	case PNG_IO_ERROR:

+		return "Failure while reading file.";

+	case PNG_EOF_ERROR:

+		return "Reached end of file.";

+	case PNG_CRC_ERROR:

+		return "CRC or chunk length error.";

+	case PNG_MEMORY_ERROR:

+		return "Could not allocate memory.";

+	case PNG_ZLIB_ERROR:

+		return "zlib reported an error.";

+	case PNG_UNKNOWN_FILTER:

+		return "Unknown filter method used in scanline.";

+	case PNG_DONE:

+		return "PNG done";

+	case PNG_NOT_SUPPORTED:

+		return "The PNG is unsupported by pnglite, too bad for you!";

+	case PNG_WRONG_ARGUMENTS:

+		return "Wrong combination of arguments passed to png_open. You must use either a read_function or supply a file pointer to use.";

+	default:

+		return "Unknown error.";

+	};

+}

+

diff --git a/src/engine/client/pnglite/pnglite.h b/src/engine/client/pnglite/pnglite.h
new file mode 100644
index 00000000..012a38d1
--- /dev/null
+++ b/src/engine/client/pnglite/pnglite.h
@@ -0,0 +1,212 @@
+/*  pnglite.h - Interface for pnglite library

+	Copyright (c) 2007 Daniel Karling

+

+	This software is provided 'as-is', without any express or implied

+	warranty. In no event will the authors be held liable for any damages

+	arising from the use of this software.

+

+	Permission is granted to anyone to use this software for any purpose,

+	including commercial applications, and to alter it and redistribute it

+	freely, subject to the following restrictions:

+

+	1. The origin of this software must not be misrepresented; you must not

+	   claim that you wrote the original software. If you use this software

+	   in a product, an acknowledgment in the product documentation would be

+	   appreciated but is not required.  

+

+	2. Altered source versions must be plainly marked as such, and must not be

+	   misrepresented as being the original software.

+

+	3. This notice may not be removed or altered from any source

+	   distribution.

+

+	Daniel Karling

+	daniel.karling@gmail.com

+ */

+

+

+#ifndef _PNGLITE_H_

+#define _PNGLITE_H_
+
+#ifdef __cplusplus
+extern "C" {
+#endif

+

+/*

+	Enumerations for pnglite.

+	Negative numbers are error codes and 0 and up are okay responses.

+*/

+

+enum

+{

+	PNG_DONE				= 1,

+	PNG_NO_ERROR			= 0,

+	PNG_FILE_ERROR			= -1,

+	PNG_HEADER_ERROR		= -2,

+	PNG_IO_ERROR			= -3,

+	PNG_EOF_ERROR			= -4,

+	PNG_CRC_ERROR			= -5,

+	PNG_MEMORY_ERROR		= -6,

+	PNG_ZLIB_ERROR			= -7,

+	PNG_UNKNOWN_FILTER		= -8,

+	PNG_NOT_SUPPORTED		= -9,

+	PNG_WRONG_ARGUMENTS		= -10

+};

+

+/*

+	The five different kinds of color storage in PNG files.

+*/

+

+enum

+{

+	PNG_GREYSCALE			= 0,

+	PNG_TRUECOLOR			= 2,

+	PNG_INDEXED				= 3,

+	PNG_GREYSCALE_ALPHA		= 4,

+	PNG_TRUECOLOR_ALPHA		= 6

+};

+

+/*

+	Typedefs for callbacks.

+*/

+

+typedef unsigned (*png_read_callback_t)(void* output, unsigned size, unsigned numel, void* user_pointer);

+typedef void (*png_free_t)(void* p);

+typedef void * (*png_alloc_t)(unsigned s);

+

+typedef struct

+{

+	void*					zs;				// pointer to z_stream

+	png_read_callback_t		read_fun;

+	void*					user_pointer;

+

+	unsigned char*			png_data;

+	unsigned				png_datalen;

+

+	unsigned				width;

+	unsigned				height;

+	unsigned char			depth;

+	unsigned char			color_type;

+	unsigned char			compression_method;

+	unsigned char			filter_method;

+	unsigned char			interlace_method;

+	unsigned char			bpp;

+}png_t;

+

+/*

+	Function: png_init

+

+	This function initializes pnglite. The parameters can be used to set your own memory allocation routines following these formats:

+

+	> void* (*custom_alloc)(size_t s)

+	> void (*custom_free)(void* p)

+	Parameters:

+		pngalloc - Pointer to custom allocation routine. If 0 is passed, malloc from libc will be used.

+		pngfree - Pointer to custom free routine. If 0 is passed, free from libc will be used.

+

+	Returns:

+		Always returns PNG_NO_ERROR.

+*/

+

+int png_init(png_alloc_t pngalloc, png_free_t pngfree);

+

+/*

+	Function: png_open_file

+

+	This function is used to open a png file with the internal file IO system. This function should be used instead of

+	png_open if no custom read function is used.

+

+	Parameters:

+		png - Empty png_t struct.

+		filename - Filename of the file to be opened.

+

+	Returns:

+		PNG_NO_ERROR on success, otherwise an error code.

+*/

+

+int png_open_file(png_t *png, const char* filename);

+

+/*

+	Function: png_open

+

+	This function reads a png from the specified callback. The callback should be of the format:

+

+	> size_t (*png_read_callback_t)(void* output, size_t size, size_t numel, void* user_pointer).

+

+	The callback will be called each time pnglite needs more data. The callback should read as much data as requested, 

+	or return 0. This should always be possible if the PNG is sane.	If the output-buffer is a null-pointer the callback 

+	should only skip ahead the specified number of elements. If the callback is a null-pointer the user_pointer will be 

+	treated as a file pointer (use png_open_file instead).

+

+	Parameters:

+		png - png_t struct

+		read_fun - Callback function for reading.

+		user_pointer - User pointer to be passed to read_fun.

+

+	Returns:

+		PNG_NO_ERROR on success, otherwise an error code.

+*/

+

+int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer);

+

+/*

+	Function: png_print_info

+

+	This function prints some info about the opened png file to stdout.

+

+	Parameters:

+		png - png struct to get info from.

+*/

+

+void png_print_info(png_t* png);

+

+/*

+	Function: png_error_string

+

+	This function translates an error code to a human readable string.

+

+	Parameters:

+		error - Error code.

+

+	Returns:

+		Pointer to string.

+*/

+

+char* png_error_string(int error);

+

+/*

+	Function: png_get_data

+

+	This function decodes the opened png file and stores the result in data. data should be big enough to hold the decoded png. Required size will be:

+	

+	> width*height*(bytes per pixel)

+

+	Parameters:

+		data - Where to store result.

+

+	Returns:

+		PNG_NO_ERROR on success, otherwise an error code.

+*/

+

+int png_get_data(png_t* png, unsigned char* data);

+

+/*

+	Function: png_close_file

+

+	Closes an open png file pointer. Should only be used when the png has been opened with png_open_file.

+

+	Parameters:

+		png - png to close.

+	

+	Returns:

+		PNG_NO_ERROR

+*/

+

+int png_close_file(png_t* png);

+
+#ifdef __cplusplus
+}
+#endif
+
+

+#endif