about summary refs log tree commit diff
diff options
context:
space:
mode:
-rw-r--r--datasrc/teewars.ds14
-rw-r--r--default.bam78
-rw-r--r--scripts/dat2c.py17
-rw-r--r--src/editor/editor.cpp2
-rw-r--r--src/engine/client/client.cpp4
-rw-r--r--src/engine/client/gfx.cpp358
-rw-r--r--src/engine/client/pnglite/pnglite.c283
-rw-r--r--src/engine/client/pnglite/pnglite.h19
-rw-r--r--src/engine/interface.h8
-rw-r--r--src/engine/server/server.cpp2
-rw-r--r--src/game/client/game_client.cpp18
-rw-r--r--src/game/client/mapres_tilemap.cpp110
-rw-r--r--src/game/client/menu.cpp14
-rw-r--r--src/game/server/game_server.cpp2
-rw-r--r--src/tools/crapnet.cpp (renamed from src/crapnet/crapnet.cpp)0
-rw-r--r--src/tools/dilate.c98
-rw-r--r--src/tools/tileset_borderfix.c83
17 files changed, 796 insertions, 314 deletions
diff --git a/datasrc/teewars.ds b/datasrc/teewars.ds
index 9dc1eb67..25145b0a 100644
--- a/datasrc/teewars.ds
+++ b/datasrc/teewars.ds
@@ -148,7 +148,19 @@ images {
 	
 	backdrop {
 		filename "data/mountain_paralax.png"
-	}	
+	}
+	
+	cloud_1 {
+		filename "data/cloud-1.png"
+	}
+
+	cloud_2 {
+		filename "data/cloud-2.png"
+	}
+
+	cloud_3 {
+		filename "data/cloud-3.png"
+	}
 }
 
 particles {
diff --git a/default.bam b/default.bam
index 9078a232..d0093552 100644
--- a/default.bam
+++ b/default.bam
@@ -31,11 +31,21 @@ function Copy(outputdir, ...)
 	return outputs
 end
 
-dc_compiler = "scripts/compiler.py"
+dc_compiler = "python scripts/compiler.py"
 if family == "windows" then
 	dc_compiler = "scripts\\compiler.py"
 end
 
+dat2c_compiler = "python scripts/dat2c.py"
+if family == "windows" then
+	dat2c_compiler = "scripts\\dat2c.py"
+end
+
+function dat2c(output, data, name)
+	print("dat2c " .. PathFilename(output) .. " = " .. PathFilename(data))
+	return os.execute(dat2c_compiler .. " " .. data .. " " .. name .. " > " .. output)
+end
+
 function dc_header(output, data, script)
 	print("dc_header " .. PathFilename(output) .. " = " .. PathFilename(data) .. " ~ " .. PathFilename(script))
 	return os.execute(dc_compiler .. " " .. data .. " " .. script .. " -h " .. output)
@@ -51,25 +61,12 @@ function dc_data(output, data, script)
 	return os.execute(dc_compiler .. " " .. data .. " " .. script .. " -d " .. output)
 end
 
-
-function DataCompile_Header(datafile, scriptfile, outputfile)
+function Dat2c(datafile, sourcefile, arrayname)
 	datafile = Path(datafile)
-	scriptfile = Path(scriptfile)
-	outputfile = Path(outputfile)
-	bam_add_job("dc_header", outputfile, datafile, scriptfile)
-	bam_add_dependency(outputfile, datafile)
-	bam_add_dependency(outputfile, scriptfile)
-	return outputfile
-end
-
-function DataCompile_Source(datafile, scriptfile, outputfile)
-	datafile = Path(datafile)
-	scriptfile = Path(scriptfile)
-	outputfile = Path(outputfile)
-	bam_add_job("dc_source", outputfile, datafile, scriptfile)
-	bam_add_dependency(outputfile, datafile)
-	bam_add_dependency(outputfile, scriptfile)
-	return outputfile
+	sourcefile = Path(sourcefile)
+	bam_add_job("dat2c", sourcefile, datafile, arrayname)
+	bam_add_dependency(sourcefile, datafile)
+	return sourcefile
 end
 
 function DataCompile(datafile, scriptfile, headerfile, sourcefile, outputdatafile)
@@ -95,6 +92,16 @@ config_name = "debug"
 config_ext = ""
 
 settings = NewSettings()
+settings.cc.debug = 1
+settings.cc.optimize = 0
+
+if family == "windows" then
+	settings.cc.flags = "/wd4244"
+else
+	settings.cc.flags = "-Wall"
+	settings.linker.flags = ""
+end
+
 --settings.cc.output = function(input, extention)
 --	return Path("objs/" .. PathFilename(input) .. config_ext .. extention)
 --end
@@ -107,17 +114,13 @@ baselib.apply(settings, "all")
 server_settings = NewSettings()
 baselib.apply(server_settings, "network")
 
-if family == "windows" then
-	settings.cc.flags = "/wd4244"
-else
-	settings.cc.flags = "-Wall"
-end
-
 settings.cc.includes:add("src")
 settings.cc.includes:add("../baselib/src/external/zlib")
 
-serverdata = DataCompile("datasrc/teewars.ds", "datasrc/server.dts", "src/game/server/data.h", "src/game/server/data/server_data.cpp", "data/server.dat")
-clientdata = DataCompile("datasrc/teewars.ds", "datasrc/client.dts", "src/game/client/data.h", "src/game/client/data/client_data.cpp", "data/client.dat")
+serverdata = DataCompile("datasrc/teewars.ds", "datasrc/server.dts", "src/game/server/data.h", "src/game/server/data/server_data.cpp", "datasrc/server.dat")
+clientdata = DataCompile("datasrc/teewars.ds", "datasrc/client.dts", "src/game/client/data.h", "src/game/client/data/client_data.cpp", "datasrc/client.dat")
+internal_clientdata = Dat2c("datasrc/client.dat", "src/game/client/data/client_internal.cpp", "internal_client_data");
+internal_serverdata = Dat2c("datasrc/server.dat", "src/game/server/data/server_internal.cpp", "internal_server_data");
 
 function build(config)
 	engine = Compile(settings, Collect("src/engine/*.cpp"))
@@ -125,23 +128,28 @@ function build(config)
 	server = Compile(settings, Collect("src/engine/server/*.cpp"))
 	masterserver = Compile(settings, Collect("src/mastersrv/*.cpp"))
 	game_shared = Compile(settings, Collect("src/game/*.cpp"))
-	game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source)
-	game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source)
+	game_client = Compile(settings, Collect("src/game/client/*.cpp"), clientdata.source, internal_clientdata)
+	game_server = Compile(settings, Collect("src/game/server/*.cpp"), serverdata.source, internal_serverdata)
 	editor = Compile(settings, Collect("src/editor/*.cpp"))
 
-	crapnet = Compile(settings, Collect("src/crapnet/*.cpp"))
-
+	-- build tools
+	tools_src = Collect("src/tools/*.cpp", "src/tools/*.c")
+	
+	objs = Compile(settings, tools_src)
+	tools = {}
+	for i,v in objs do
+		toolname = PathFilename(file_base(v))
+		tools[i] = Link(settings, toolname, v)
+	end
+	
 	client_exe = Link(settings, "teewars"..config_ext, engine, client, editor, game_shared, game_client)
 	server_exe = Link(server_settings, "teewars_srv"..config_ext, engine, server, game_shared, game_server)
 	masterserver_exe = Link(server_settings, "mastersrv"..config_ext, masterserver, engine)
-	-- editor_exe = Link(settings, "editor", engine, game_shared, editor)
-	crapnet_exe = Link(server_settings, "crapnet"..config_ext, crapnet)
 
 	Target(PseudoTarget("client", client_exe, clientdata.data))
 	Target(PseudoTarget("server", server_exe, serverdata.data))
 	Target(PseudoTarget("masterserver", masterserver_exe))
-	Target(PseudoTarget("tools", crapnet_exe))
-	-- Target(PseudoTarget("editor", editor_exe))
+	Target(PseudoTarget("tools", tools))
 end
 
 build("debug")
diff --git a/scripts/dat2c.py b/scripts/dat2c.py
new file mode 100644
index 00000000..87dfd114
--- /dev/null
+++ b/scripts/dat2c.py
@@ -0,0 +1,17 @@
+import sys
+
+data = file(sys.argv[1], "rb").read()
+
+i = 0
+print "const char", sys.argv[2], "[] = {"
+print str(ord(data[0])),
+for d in data[1:]:
+	s = ","+str(ord(d))
+	print s,
+	i += len(s)+1
+
+	if i >= 70:
+		print ""
+		i = 0
+print ""
+print "};"
diff --git a/src/editor/editor.cpp b/src/editor/editor.cpp
index 2be62690..5da2a018 100644
--- a/src/editor/editor.cpp
+++ b/src/editor/editor.cpp
@@ -1210,7 +1210,7 @@ int editor_main(int argc, char **argv)
 {
 	dbg_msg("editor", "starting...");
 	
-	config_load("editor.cfg");
+	config_load("default.cfg");
 	
 	// parse arguments
 	for(int i = 1; i < argc; i++)
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index c768e83d..1d3b7d2b 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -500,7 +500,7 @@ void client::run(const char *direct_connect_server)
 			break;
 
 		// be nice
-		thread_sleep(1);
+		//thread_sleep(1);
 		
 		if(reporttime < time_get())
 		{
@@ -826,7 +826,7 @@ int main(int argc, char **argv)
 	dbg_msg("client", "starting...");
 	
 	config_reset();
-	config_load("teewars.cfg");
+	config_load("default.cfg");
 
 	const char *direct_connect_server = 0x0;
 	snd_set_master_volume(config.volume / 255.0f);
diff --git a/src/engine/client/gfx.cpp b/src/engine/client/gfx.cpp
index 1e5aa19e..657f7874 100644
--- a/src/engine/client/gfx.cpp
+++ b/src/engine/client/gfx.cpp
@@ -1,4 +1,5 @@
 #include <baselib/opengl.h>
+#include <baselib/math.h>
 #include <baselib/vmath.h>
 #include <baselib/stream/file.h>
 
@@ -22,19 +23,19 @@ struct custom_vertex
 	vec4 color;
 };
 
-const int vertexBufferSize = 2048;
+const int vertex_buffer_size = 2048*32;
 //static custom_vertex vertices[4];
-static custom_vertex* g_pVertices = 0;
-static int g_iVertexStart = 0;
-static int g_iVertexEnd = 0;
-static vec4 g_QuadColor[4];
-static vec2 g_QuadTexture[4];
+static custom_vertex *vertices = 0;
+static int num_vertices = 0;
+static vec4 color[4];
+static vec2 texture[4];
 
 static opengl::vertex_buffer vertex_buffer;
 //static int screen_width = 800;
 //static int screen_height = 600;
 static float rotation = 0;
 static int quads_drawing = 0;
+
 static float screen_x0 = 0;
 static float screen_y0 = 0;
 static float screen_x1 = 0;
@@ -61,19 +62,19 @@ static const unsigned char null_texture_data[] = {
 
 static void draw_quad(bool _bflush = false)
 {
-	if (!_bflush && ((g_iVertexEnd + 4) < vertexBufferSize))
+	if (!_bflush && ((num_vertices + 4) < vertex_buffer_size))
 	{
 		// Just add
-		g_iVertexEnd += 4;
+		num_vertices += 4;
 	}
-	else if (g_iVertexEnd)
+	else if (num_vertices)
 	{
 		if (!_bflush)
-			g_iVertexEnd += 4;
+			num_vertices += 4;
 		if(GLEW_ARB_vertex_buffer_object)
 		{
 			// set the data
-			vertex_buffer.data(g_pVertices, vertexBufferSize * sizeof(custom_vertex), GL_DYNAMIC_DRAW);
+			vertex_buffer.data(vertices, num_vertices * sizeof(custom_vertex), GL_DYNAMIC_DRAW);
 			opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0);
 			opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT,
 					sizeof(custom_vertex),
@@ -81,28 +82,81 @@ static void draw_quad(bool _bflush = false)
 			opengl::stream_color(&vertex_buffer, 4, GL_FLOAT,
 					sizeof(custom_vertex),
 					sizeof(vec3)+sizeof(vec2));		
-			opengl::draw_arrays(GL_QUADS, 0, g_iVertexEnd);
+			opengl::draw_arrays(GL_QUADS, 0, num_vertices);
 		}
 		else
 		{
 			glVertexPointer(3, GL_FLOAT,
 					sizeof(custom_vertex),
-					(char*)g_pVertices);
+					(char*)vertices);
 			glTexCoordPointer(2, GL_FLOAT,
 					sizeof(custom_vertex),
-					(char*)g_pVertices + sizeof(vec3));
+					(char*)vertices + sizeof(vec3));
 			glColorPointer(4, GL_FLOAT,
 					sizeof(custom_vertex),
-					(char*)g_pVertices + sizeof(vec3) + sizeof(vec2));
+					(char*)vertices + sizeof(vec3) + sizeof(vec2));
 			glEnableClientState(GL_VERTEX_ARRAY);
 			glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 			glEnableClientState(GL_COLOR_ARRAY);
-			glDrawArrays(GL_QUADS, 0, g_iVertexEnd);
+			glDrawArrays(GL_QUADS, 0, num_vertices);
 		}
+		
 		// Reset pointer
-		g_iVertexEnd = 0;
+		num_vertices = 0;
 	}
 }
+struct batch
+{
+	opengl::vertex_buffer vb;
+	int num;
+};
+
+void gfx_quads_draw_batch(void *in_b)
+{
+	batch *b = (batch*)in_b;
+	
+	if(GLEW_ARB_vertex_buffer_object)
+	{
+		// set the data
+		opengl::stream_vertex(&b->vb, 3, GL_FLOAT, sizeof(custom_vertex), 0);
+		opengl::stream_texcoord(&b->vb, 0, 2, GL_FLOAT,
+				sizeof(custom_vertex),
+				sizeof(vec3));
+		opengl::stream_color(&b->vb, 4, GL_FLOAT,
+				sizeof(custom_vertex),
+				sizeof(vec3)+sizeof(vec2));		
+		opengl::draw_arrays(GL_QUADS, 0, b->num);
+	}
+	/*
+	else
+	{
+		glVertexPointer(3, GL_FLOAT,
+				sizeof(custom_vertex),
+				(char*)vertices);
+		glTexCoordPointer(2, GL_FLOAT,
+				sizeof(custom_vertex),
+				(char*)vertices + sizeof(vec3));
+		glColorPointer(4, GL_FLOAT,
+				sizeof(custom_vertex),
+				(char*)vertices + sizeof(vec3) + sizeof(vec2));
+		glEnableClientState(GL_VERTEX_ARRAY);
+		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+		glEnableClientState(GL_COLOR_ARRAY);
+		glDrawArrays(GL_QUADS, 0, b->num);
+	}*/	
+}
+
+
+void *gfx_quads_create_batch()
+{
+	batch *b = new batch;
+	b->num = num_vertices;
+	b->vb.data(vertices, num_vertices*sizeof(custom_vertex), GL_STATIC_DRAW);
+	num_vertices = 0;
+	gfx_quads_end();
+	return b;
+}
+
 	
 bool gfx_init()
 {
@@ -114,11 +168,10 @@ bool gfx_init()
 
 	
 	// Init vertices
-	if (g_pVertices)
-		mem_free(g_pVertices);
-	g_pVertices = (custom_vertex*)mem_alloc(sizeof(custom_vertex) * vertexBufferSize, 1);
-	g_iVertexStart = 0;
-	g_iVertexEnd = 0;
+	if (vertices)
+		mem_free(vertices);
+	vertices = (custom_vertex*)mem_alloc(sizeof(custom_vertex) * vertex_buffer_size, 1);
+	num_vertices = 0;
 
 	context.set_title("---");
 
@@ -137,13 +190,13 @@ bool gfx_init()
 	opengl::matrix_modelview(&mat);
 	
 	// Set all z to -5.0f
-	for (int i = 0; i < vertexBufferSize; i++)
-		g_pVertices[i].pos.z = -5.0f;
+	for (int i = 0; i < vertex_buffer_size; i++)
+		vertices[i].pos.z = -5.0f;
 
 	if(GLEW_ARB_vertex_buffer_object)
 	{
 		// set the streams
-		vertex_buffer.data(g_pVertices, sizeof(vertexBufferSize), GL_DYNAMIC_DRAW);
+		vertex_buffer.data(vertices, sizeof(vertex_buffer_size), GL_DYNAMIC_DRAW);
 		opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0);
 		opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT,
 				sizeof(custom_vertex),
@@ -198,8 +251,6 @@ void gfx_blend_additive()
 	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
 }
 
-int DEBUGTEST_MAPIMAGE = 0;
-
 int gfx_load_texture_raw(int w, int h, int format, const void *data)
 {
 	// grab texture
@@ -210,27 +261,11 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data)
 	// set data and return
 	// TODO: should be RGBA, not BGRA
 	dbg_msg("gfx", "%d = %dx%d", tex, w, h);
-	if(DEBUGTEST_MAPIMAGE)
+	if(format == IMG_RGB)
+		textures[tex].tex.data2d(w, h, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data);
+	else if(format == IMG_RGBA)
 	{
-		if(format == IMG_RGB)
-			textures[tex].tex.data2d_nomip(w, h, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, data);
-		else if(format == IMG_RGBA)
-			textures[tex].tex.data2d_nomip(w, h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data);
-		else if(format == IMG_BGR)
-			textures[tex].tex.data2d_nomip(w, h, GL_RGB, GL_BGR, GL_UNSIGNED_BYTE, data);
-		else if(format == IMG_BGRA)
-			textures[tex].tex.data2d_nomip(w, h, GL_RGBA, GL_BGRA, GL_UNSIGNED_BYTE, data);
-	}
-	else
-	{
-		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);
+		textures[tex].tex.data2d(w, h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, data);
 	}
 	
 	return tex;
@@ -270,93 +305,17 @@ int gfx_load_texture(const char *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_png(&img, filename))
 	{
-		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'))
-	{
-		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;
+		int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data);
+		mem_free(img.data);
+		return id;
 	}
 	
 	return 0;
 }
 
-int gfx_load_tga(image_info *img, const char *filename)
-{
-	// open file for reading
-	file_stream file;
-	if(!file.open_r(filename))
-	{
-		dbg_msg("game/tga", "failed to open file. filename='%s'", filename);
-		return 0;
-	}
-	
-	// read header
-	unsigned char headers[18];
-	file.read(headers, sizeof(headers));
-	img->width = headers[12]+(headers[13]<<8);
-	img->height = headers[14]+(headers[15]<<8);
-
-	bool flipx = (headers[17] >> 4) & 1;
-	bool flipy = !((headers[17] >> 5) & 1);
-	
-	(void)flipx; // TODO: make use of this flag
-
-	if(headers[2] != 2) // needs to be uncompressed RGB
-	{
-		dbg_msg("game/tga", "tga not uncompressed rgb. filename='%s'", filename);
-		return 0;
-	}
-		
-	if(headers[16] != 32) // needs to be RGBA
-	{
-		dbg_msg("game/tga", "tga is 32bit. filename='%s'", filename);
-		return 0;
-	}
-	
-	// read data
-	int data_size = img->width*img->height*4;
-	img->data = mem_alloc(data_size, 1);
-	img->format = IMG_BGRA;
-
-	if (flipy)
-	{
-		for (int i = 0; i < img->height; i++)
-		{
-			file.read((char *)img->data + (img->height-i-1)*img->width*4, img->width*4);
-		}
-	}
-	else
-		file.read(img->data, data_size);
-	file.close();
-
-	return 1;
-}
-
-
-
 int gfx_load_png(image_info *img, const char *filename)
 {
 	// open file for reading
@@ -391,8 +350,8 @@ int gfx_load_png(image_info *img, const char *filename)
 
 void gfx_shutdown()
 {
-	if (g_pVertices)
-		mem_free(g_pVertices);
+	if (vertices)
+		mem_free(vertices);
 	context.destroy();
 }
 
@@ -458,6 +417,9 @@ void gfx_setoffset(float x, float y)
 	opengl::matrix_modelview(&mat);
 }
 
+
+
+
 void gfx_quads_begin()
 {
 	dbg_assert(quads_drawing == 0, "called quads_begin twice");
@@ -485,46 +447,42 @@ void gfx_quads_setrotation(float angle)
 void gfx_quads_setcolorvertex(int i, float r, float g, float b, float a)
 {
 	dbg_assert(quads_drawing == 1, "called gfx_quads_setcolorvertex without quads_begin");
-	g_QuadColor[i].r = r;
-	g_QuadColor[i].g = g;
-	g_QuadColor[i].b = b;
-	g_QuadColor[i].a = a;
+	color[i].r = r;
+	color[i].g = g;
+	color[i].b = b;
+	color[i].a = a;
 }
 
 void gfx_quads_setcolor(float r, float g, float b, float a)
 {
 	dbg_assert(quads_drawing == 1, "called gfx_quads_setcolor without quads_begin");
-	g_QuadColor[0] = vec4(r,g,b,a);
-	g_QuadColor[1] = vec4(r,g,b,a);
-	g_QuadColor[2] = vec4(r,g,b,a);
-	g_QuadColor[3] = vec4(r,g,b,a);
-	/*gfx_quads_setcolorvertex(0,r,g,b,a);
-	gfx_quads_setcolorvertex(1,r,g,b,a);
-	gfx_quads_setcolorvertex(2,r,g,b,a);
-	gfx_quads_setcolorvertex(3,r,g,b,a);*/
+	color[0] = vec4(r,g,b,a);
+	color[1] = vec4(r,g,b,a);
+	color[2] = vec4(r,g,b,a);
+	color[3] = vec4(r,g,b,a);
 }
 
 void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v)
 {
 	dbg_assert(quads_drawing == 1, "called gfx_quads_setsubset without quads_begin");
 
-	g_QuadTexture[0].x = tl_u;
-	g_QuadTexture[0].y = tl_v;
+	texture[0].x = tl_u;
+	texture[0].y = tl_v;
 	//g_pVertices[g_iVertexEnd].tex.u = tl_u;
 	//g_pVertices[g_iVertexEnd].tex.v = tl_v;
 
-	g_QuadTexture[1].x = br_u;
-	g_QuadTexture[1].y = tl_v;
+	texture[1].x = br_u;
+	texture[1].y = tl_v;
 	//g_pVertices[g_iVertexEnd + 2].tex.u = br_u;
 	//g_pVertices[g_iVertexEnd + 2].tex.v = tl_v;
 
-	g_QuadTexture[2].x = br_u;
-	g_QuadTexture[2].y = br_v;
+	texture[2].x = br_u;
+	texture[2].y = br_v;
 	//g_pVertices[g_iVertexEnd + 1].tex.u = tl_u;
 	//g_pVertices[g_iVertexEnd + 1].tex.v = br_v;
 
-	g_QuadTexture[3].x = tl_u;
-	g_QuadTexture[3].y = br_v;
+	texture[3].x = tl_u;
+	texture[3].y = br_v;
 	//g_pVertices[g_iVertexEnd + 3].tex.u = br_u;
 	//g_pVertices[g_iVertexEnd + 3].tex.v = br_v;
 }
@@ -550,33 +508,33 @@ void gfx_quads_drawTL(float x, float y, float width, float height)
 	center.y = y + height/2;
 	center.z = 0;
 	
-	g_pVertices[g_iVertexEnd].pos.x = x;
-	g_pVertices[g_iVertexEnd].pos.y = y;
-	g_pVertices[g_iVertexEnd].tex.u = g_QuadTexture[0].x;
-	g_pVertices[g_iVertexEnd].tex.v = g_QuadTexture[0].y;
-	g_pVertices[g_iVertexEnd].color = g_QuadColor[0];
-	rotate(center, g_pVertices[g_iVertexEnd].pos);
-
-	g_pVertices[g_iVertexEnd + 1].pos.x = x+width;
-	g_pVertices[g_iVertexEnd + 1].pos.y = y;
-	g_pVertices[g_iVertexEnd + 1].tex.u = g_QuadTexture[1].x;
-	g_pVertices[g_iVertexEnd + 1].tex.v = g_QuadTexture[1].y;
-	g_pVertices[g_iVertexEnd + 1].color = g_QuadColor[1];
-	rotate(center, g_pVertices[g_iVertexEnd + 1].pos);
-
-	g_pVertices[g_iVertexEnd + 2].pos.x = x + width;
-	g_pVertices[g_iVertexEnd + 2].pos.y = y+height;
-	g_pVertices[g_iVertexEnd + 2].tex.u = g_QuadTexture[2].x;
-	g_pVertices[g_iVertexEnd + 2].tex.v = g_QuadTexture[2].y;
-	g_pVertices[g_iVertexEnd + 2].color = g_QuadColor[2];
-	rotate(center, g_pVertices[g_iVertexEnd + 2].pos);
-
-	g_pVertices[g_iVertexEnd + 3].pos.x = x;
-	g_pVertices[g_iVertexEnd + 3].pos.y = y+height;
-	g_pVertices[g_iVertexEnd + 3].tex.u = g_QuadTexture[3].x;
-	g_pVertices[g_iVertexEnd + 3].tex.v = g_QuadTexture[3].y;
-	g_pVertices[g_iVertexEnd + 3].color = g_QuadColor[3];
-	rotate(center, g_pVertices[g_iVertexEnd + 3].pos);
+	vertices[num_vertices].pos.x = x;
+	vertices[num_vertices].pos.y = y;
+	vertices[num_vertices].tex.u = texture[0].x;
+	vertices[num_vertices].tex.v = texture[0].y;
+	vertices[num_vertices].color = color[0];
+	rotate(center, vertices[num_vertices].pos);
+
+	vertices[num_vertices + 1].pos.x = x+width;
+	vertices[num_vertices + 1].pos.y = y;
+	vertices[num_vertices + 1].tex.u = texture[1].x;
+	vertices[num_vertices + 1].tex.v = texture[1].y;
+	vertices[num_vertices + 1].color = color[1];
+	rotate(center, vertices[num_vertices + 1].pos);
+
+	vertices[num_vertices + 2].pos.x = x + width;
+	vertices[num_vertices + 2].pos.y = y+height;
+	vertices[num_vertices + 2].tex.u = texture[2].x;
+	vertices[num_vertices + 2].tex.v = texture[2].y;
+	vertices[num_vertices + 2].color = color[2];
+	rotate(center, vertices[num_vertices + 2].pos);
+
+	vertices[num_vertices + 3].pos.x = x;
+	vertices[num_vertices + 3].pos.y = y+height;
+	vertices[num_vertices + 3].tex.u = texture[3].x;
+	vertices[num_vertices + 3].tex.v = texture[3].y;
+	vertices[num_vertices + 3].color = color[3];
+	rotate(center, vertices[num_vertices + 3].pos);
 	
 	draw_quad();
 }
@@ -589,29 +547,29 @@ void gfx_quads_draw_freeform(
 {
 	dbg_assert(quads_drawing == 1, "called quads_draw_freeform without quads_begin");
 	
-	g_pVertices[g_iVertexEnd].pos.x = x0;
-	g_pVertices[g_iVertexEnd].pos.y = y0;
-	g_pVertices[g_iVertexEnd].tex.u = g_QuadTexture[0].x;
-	g_pVertices[g_iVertexEnd].tex.v = g_QuadTexture[0].y;
-	g_pVertices[g_iVertexEnd].color = g_QuadColor[0];
-
-	g_pVertices[g_iVertexEnd + 1].pos.x = x1;
-	g_pVertices[g_iVertexEnd + 1].pos.y = y1;
-	g_pVertices[g_iVertexEnd + 1].tex.u = g_QuadTexture[1].x;
-	g_pVertices[g_iVertexEnd + 1].tex.v = g_QuadTexture[1].y;
-	g_pVertices[g_iVertexEnd + 1].color = g_QuadColor[1];
-
-	g_pVertices[g_iVertexEnd + 2].pos.x = x3;
-	g_pVertices[g_iVertexEnd + 2].pos.y = y3;
-	g_pVertices[g_iVertexEnd + 2].tex.u = g_QuadTexture[2].x;
-	g_pVertices[g_iVertexEnd + 2].tex.v = g_QuadTexture[2].y;
-	g_pVertices[g_iVertexEnd + 2].color = g_QuadColor[2];
-
-	g_pVertices[g_iVertexEnd + 3].pos.x = x2;
-	g_pVertices[g_iVertexEnd + 3].pos.y = y2;
-	g_pVertices[g_iVertexEnd + 3].tex.u = g_QuadTexture[3].x;
-	g_pVertices[g_iVertexEnd + 3].tex.v = g_QuadTexture[3].y;
-	g_pVertices[g_iVertexEnd + 3].color = g_QuadColor[3];
+	vertices[num_vertices].pos.x = x0;
+	vertices[num_vertices].pos.y = y0;
+	vertices[num_vertices].tex.u = texture[0].x;
+	vertices[num_vertices].tex.v = texture[0].y;
+	vertices[num_vertices].color = color[0];
+
+	vertices[num_vertices + 1].pos.x = x1;
+	vertices[num_vertices + 1].pos.y = y1;
+	vertices[num_vertices + 1].tex.u = texture[1].x;
+	vertices[num_vertices + 1].tex.v = texture[1].y;
+	vertices[num_vertices + 1].color = color[1];
+
+	vertices[num_vertices + 2].pos.x = x3;
+	vertices[num_vertices + 2].pos.y = y3;
+	vertices[num_vertices + 2].tex.u = texture[2].x;
+	vertices[num_vertices + 2].tex.v = texture[2].y;
+	vertices[num_vertices + 2].color = color[2];
+
+	vertices[num_vertices + 3].pos.x = x2;
+	vertices[num_vertices + 3].pos.y = y2;
+	vertices[num_vertices + 3].tex.u = texture[3].x;
+	vertices[num_vertices + 3].tex.v = texture[3].y;
+	vertices[num_vertices + 3].color = color[3];
 	
 	draw_quad();
 }
diff --git a/src/engine/client/pnglite/pnglite.c b/src/engine/client/pnglite/pnglite.c
index 56e4c259..1874c63a 100644
--- a/src/engine/client/pnglite/pnglite.c
+++ b/src/engine/client/pnglite/pnglite.c
@@ -1,14 +1,21 @@
 /*  pnglite.c - pnglite library

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

 */

+#define DO_CRC_CHECKS 1

+#define USE_ZLIB 1

 

+#if USE_ZLIB

 #include <zlib.h>

+#else

+#include "zlite.h"

+#endif

+

 #include <stdio.h>

 #include <stdlib.h>

 #include <string.h>

 #include "pnglite.h"

 

-#define DO_CRC_CHECKS 1

+

 

 static png_alloc_t png_alloc;

 static png_free_t png_free;

@@ -35,6 +42,22 @@ static size_t file_read(png_t* png, void* out, size_t size, size_t numel)
 	return result;

 }

 

+static size_t file_write(png_t* png, void* p, size_t size, size_t numel)

+{

+	size_t result;

+

+	if(png->write_fun)

+	{

+		result = png->write_fun(p, size, numel, png->user_pointer);

+	}

+	else

+	{

+		result = fwrite(p, size, numel, png->user_pointer);

+	}

+

+	return result;

+}

+

 static int file_read_ul(png_t* png, unsigned *out)

 {

 	unsigned char buf[4];

@@ -47,6 +70,22 @@ static int file_read_ul(png_t* png, unsigned *out)
 	return PNG_NO_ERROR;

 }

 

+static int file_write_ul(png_t* png, unsigned in)

+{

+	unsigned char buf[4];

+

+	buf[0] = (in>>24) & 0xff;

+	buf[1] = (in>>16) & 0xff;

+	buf[2] = (in>>8) & 0xff;

+	buf[3] = (in) & 0xff;

+

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

+		return PNG_FILE_ERROR;

+

+	return PNG_NO_ERROR;

+}

+	

+

 static unsigned get_ul(unsigned char* buf)

 {

 	unsigned result;

@@ -59,6 +98,16 @@ static unsigned get_ul(unsigned char* buf)
 	return result;

 }

 

+static unsigned set_ul(unsigned char* buf, unsigned in)

+{

+	buf[0] = (in>>24) & 0xff;

+	buf[1] = (in>>16) & 0xff;

+	buf[2] = (in>>8) & 0xff;

+	buf[3] = (in) & 0xff;

+

+	return PNG_NO_ERROR;

+}

+

 int png_init(png_alloc_t pngalloc, png_free_t pngfree)

 {

 	if(pngalloc)

@@ -121,7 +170,7 @@ static int png_read_ihdr(png_t* png)
 #if DO_CRC_CHECKS

 	file_read_ul(png, &orig_crc);

 

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

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

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

 

 	if(orig_crc != calc_crc)

@@ -150,6 +199,38 @@ static int png_read_ihdr(png_t* png)
 	return PNG_NO_ERROR;

 }

 

+static int png_write_ihdr(png_t* png)

+{

+	unsigned char ihdr[13+4];

+	unsigned char *p = ihdr;

+	unsigned crc;

+	

+	file_write(png, "\x89\x50\x4E\x47\x0D\x0A\x1A\x0A", 1, 8);

+

+	file_write_ul(png, 13);

+    

+	*p = 'I';			p++;

+	*p = 'H';			p++;

+	*p = 'D';			p++;

+	*p = 'R';			p++;

+	set_ul(p, png->width);	p+=4;

+	set_ul(p, png->height);	p+=4;

+	*p = png->depth;			p++;

+	*p = png->color_type;	p++;

+	*p = 0;				p++;

+	*p = 0;				p++;

+	*p = 0;				p++;

+

+	file_write(png, ihdr, 1, 13+4);

+

+	crc = crc32(0L, 0, 0);

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

+

+	file_write_ul(png, crc);

+

+	return PNG_NO_ERROR;

+}

+

 void png_print_info(png_t* png)

 {

 	printf("PNG INFO:\n");

@@ -173,13 +254,13 @@ void png_print_info(png_t* png)
 	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)

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

 {

 	char header[8];

 	int result;

 

 	png->read_fun = read_fun;

+	png->write_fun = 0;

 	png->user_pointer = user_pointer;

 

 	if(!read_fun && !user_pointer)

@@ -198,15 +279,47 @@ int png_open(png_t* png, png_read_callback_t read_fun, void* user_pointer)
 	return result;

 }

 

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

+int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer)

+{

+	png->write_fun = write_fun;

+	png->read_fun = 0;

+	png->user_pointer = user_pointer;

+

+	if(!write_fun && !user_pointer)

+		return PNG_WRONG_ARGUMENTS;

+

+	return PNG_NO_ERROR;

+}

+

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

+{

+	return png_open_read(png, read_fun, user_pointer);

+}

+

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

 {

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

 

 	if(!fp)

 		return PNG_FILE_ERROR;

 

-	return png_open(png, 0, fp);

-}	

+	return png_open_read(png, 0, fp);

+}

+

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

+{

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

+

+	if(!fp)

+		return PNG_FILE_ERROR;

+

+	return png_open_write(png, 0, fp);

+}

+

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

+{

+	return png_open_file_read(png, filename);

+}

 

 int png_close_file(png_t* png)

 {

@@ -215,7 +328,7 @@ int png_close_file(png_t* png)
 	return PNG_NO_ERROR;

 }

 

-static int png_init_inflate(png_t* png)

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

 {

 	z_stream *stream;

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

@@ -227,8 +340,41 @@ static int png_init_inflate(png_t* png)
 

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

 

+	if(deflateInit(stream, Z_DEFAULT_COMPRESSION) != Z_OK)

+		return PNG_ZLIB_ERROR;

+

+	stream->next_in = data;

+	stream->avail_in = datalen;

+

+	return PNG_NO_ERROR;

+}

+

+static int png_init_inflate(png_t* png)

+{

+#if USE_ZLIB

+	z_stream *stream;

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

+#else

+	zl_stream *stream;

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

+#endif

+

+	stream = png->zs;

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	

+

+#if USE_ZLIB

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

 	if(inflateInit(stream) != Z_OK)

 		return PNG_ZLIB_ERROR;

+#else

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

+	if(z_inflateInit(stream) != Z_OK)

+		return PNG_ZLIB_ERROR;

+#endif

 

 	stream->next_out = png->png_data;

 	stream->avail_out = png->png_datalen;

@@ -236,14 +382,36 @@ static int png_init_inflate(png_t* png)
 	return PNG_NO_ERROR;

 }

 

+static int png_end_deflate(png_t* png)

+{

+	z_stream *stream = png->zs;

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	deflateEnd(stream);

+

+	png_free(png->zs);

+

+	return PNG_NO_ERROR;

+}

+

 static int png_end_inflate(png_t* png)

 {

+#if USE_ZLIB

 	z_stream *stream = png->zs;

+#else

+	zl_stream *stream = png->zs;

+#endif

 

 	if(!stream)

 		return PNG_MEMORY_ERROR;

 

+#if USE_ZLIB

 	if(inflateEnd(stream) != Z_OK)

+#else

+	if(z_inflateEnd(stream) != Z_OK)

+#endif

 	{

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

 		return PNG_ZLIB_ERROR;

@@ -257,7 +425,11 @@ static int png_end_inflate(png_t* png)
 static int png_inflate(png_t* png, char* data, int len)

 {

 	int result;

+#if USE_ZLIB

 	z_stream *stream = png->zs;

+#else

+	zl_stream *stream = png->zs;

+#endif

 

 	if(!stream)

 		return PNG_MEMORY_ERROR;

@@ -265,7 +437,11 @@ static int png_inflate(png_t* png, char* data, int len)
 	stream->next_in = (unsigned char*)data;

 	stream->avail_in = len;

 	

+#if USE_ZLIB

 	result = inflate(stream, Z_SYNC_FLUSH);

+#else

+	result = z_inflate(stream);

+#endif

 

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

 	{

@@ -279,6 +455,64 @@ static int png_inflate(png_t* png, char* data, int len)
 	return PNG_NO_ERROR;

 }

 

+static int png_deflate(png_t* png, char* outdata, int outlen, int *outwritten)

+{

+	int result;

+

+	z_stream *stream = png->zs;

+

+

+	if(!stream)

+		return PNG_MEMORY_ERROR;

+

+	stream->next_out = (unsigned char*)outdata;

+	stream->avail_out = outlen;

+

+	result = deflate(stream, Z_SYNC_FLUSH);

+

+	*outwritten = outlen - stream->avail_out;

+

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

+	{

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

+		return PNG_ZLIB_ERROR;

+	}

+

+	return result;

+}

+

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

+{

+	unsigned char *chunk;

+	unsigned long written;

+	unsigned long crc;

+	unsigned size = png->width * png->height * png->bpp + png->height;

+	

+	(void)png_init_deflate;

+	(void)png_end_deflate;

+	(void)png_deflate;

+

+	chunk = png_alloc(size);

+	memcpy(chunk, "IDAT", 4);

+	

+	written = size;

+	compress(chunk+4, &written, data, size);

+	

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

+	crc = crc32(crc, chunk, written+4);

+	set_ul(chunk+written+4, crc);

+	file_write_ul(png, written);

+	file_write(png, chunk, 1, written+8);

+	png_free(chunk);

+

+	file_write_ul(png, 0);

+	file_write(png, "IEND", 1, 4);

+	crc = crc32(0L, (const unsigned char *)"IEND", 4);

+	file_write_ul(png, crc);

+	

+	return PNG_NO_ERROR;

+}

+

 static int png_read_idat(png_t* png, unsigned firstlen) 

 {

 	unsigned type = 0;

@@ -493,6 +727,13 @@ static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out,
 	}

 }

 

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

+{

+

+

+	return PNG_NO_ERROR;

+}

+

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

 {

 	unsigned i;

@@ -575,6 +816,31 @@ int png_get_data(png_t* png, unsigned char* data)
 	return result;

 }

 

+int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data)

+{

+	int i;

+	unsigned char *filtered;

+	png->width = width;

+	png->height = height;

+	png->depth = depth;

+	png->color_type = color;

+	png->bpp = png_get_bpp(png);

+

+	filtered = png_alloc(width * height * png->bpp + height);

+

+	for(i = 0; i < png->height; i++)

+	{

+		filtered[i*png->width*png->bpp+i] = 0;

+		memcpy(&filtered[i*png->width*png->bpp+i+1], data + i * png->width*png->bpp, png->width*png->bpp);

+	}

+

+	png_filter(png, filtered);

+	png_write_ihdr(png);

+	png_write_idats(png, filtered);

+	return PNG_NO_ERROR;

+}

+

+

 char* png_error_string(int error)

 {

 	switch(error)

@@ -607,4 +873,3 @@ char* png_error_string(int error)
 		return "Unknown error.";

 	};

 }

-

diff --git a/src/engine/client/pnglite/pnglite.h b/src/engine/client/pnglite/pnglite.h
index 78e1cfe8..f464c46b 100644
--- a/src/engine/client/pnglite/pnglite.h
+++ b/src/engine/client/pnglite/pnglite.h
@@ -70,6 +70,7 @@ enum
 	Typedefs for callbacks.

 */

 

+typedef unsigned (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);

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

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

 typedef void * (*png_alloc_t)(size_t s);

@@ -78,6 +79,7 @@ typedef struct
 {

 	void*					zs;				/* pointer to z_stream */

 	png_read_callback_t		read_fun;

+	png_write_callback_t	write_fun;

 	void*					user_pointer;

 

 	unsigned char*			png_data;

@@ -126,13 +128,23 @@ int png_init(png_alloc_t pngalloc, png_free_t pngfree);
 

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

 

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

+int png_open_file_write(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:

+	This function reads or writes a png from/to the specified callback. The callbacks should be of the format:

 

+	> size_t (*png_write_callback_t)(void* input, size_t size, size_t numel, void* user_pointer);

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

 

+	Only one callback has to be specified. The read callback in case of PNG reading, otherwise the write callback.

+

+	Writing:

+	The callback will be called like fwrite.

+

+	Reading:

 	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 

@@ -149,6 +161,9 @@ int png_open_file(png_t *png, const char* filename);
 

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

 

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

+int png_open_write(png_t* png, png_write_callback_t write_fun, void* user_pointer);

+

 /*

 	Function: png_print_info

 

@@ -190,6 +205,8 @@ char* png_error_string(int error);
 

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

 

+int png_set_data(png_t* png, unsigned width, unsigned height, char depth, int color, unsigned char* data);

+

 /*

 	Function: png_close_file

 

diff --git a/src/engine/interface.h b/src/engine/interface.h
index ad798197..10a8794b 100644
--- a/src/engine/interface.h
+++ b/src/engine/interface.h
@@ -17,9 +17,10 @@ enum
 	SNAP_PREV=1,
 	
 	IMG_RGB=0,
-	IMG_RGBA,
+	IMG_RGBA=1,
+	/*
 	IMG_BGR,
-	IMG_BGRA,
+	IMG_BGRA,*/
 };
 
 struct snap_item
@@ -753,6 +754,9 @@ float gfx_pretty_text_width(float size, const char *text);
 
 void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y);
 
+void gfx_quads_draw_batch(void *batch);
+void *gfx_quads_create_batch();
+
 void mods_message(int msg, int client_id);
 void modc_message(int msg);
 
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index c21dc673..1af0da3b 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -559,7 +559,7 @@ int main(int argc, char **argv)
 	dbg_msg("server", "starting...");
 
 	config_reset();
-	config_load("server.cfg");
+	config_load("default.cfg");
 
 	const char *mapname = "data/demo.map";
 	const char *servername = 0;
diff --git a/src/game/client/game_client.cpp b/src/game/client/game_client.cpp
index f253909f..c34e81ce 100644
--- a/src/game/client/game_client.cpp
+++ b/src/game/client/game_client.cpp
@@ -1239,7 +1239,23 @@ void modc_render()
 	gfx_clear(0.65f,0.78f,0.9f);
 
 	// draw the sun	
-	render_sun(local_player_pos.x*0.5f, local_player_pos.y*0.5f);
+	render_sun(20+screen_x*0.6f, 20+screen_y*0.6f);
+
+
+	static vec2 cloud_pos[6] = {vec2(0,0),vec2(0,200),vec2(0,400)};
+	static float cloud_speed[6] = {30, 20, 10};
+	static int cloud_images[6] = {IMAGE_CLOUD_1, IMAGE_CLOUD_2, IMAGE_CLOUD_3};
+	
+	for(int i = 0; i < 3; i++)
+	{
+		float parallax_amount = 0.55f;
+		gfx_texture_set(data->images[cloud_images[i]].id);
+		gfx_quads_begin();
+		gfx_quads_drawTL((cloud_pos[i].x+fmod(client_localtime()*cloud_speed[i]+i*100.0f, 1000.0f))+screen_x*parallax_amount,
+			cloud_pos[i].y+screen_y*parallax_amount, 300, 300);
+		gfx_quads_end();
+	}
+
 	
 	// draw backdrop
 	gfx_texture_set(data->images[IMAGE_BACKDROP].id);
diff --git a/src/game/client/mapres_tilemap.cpp b/src/game/client/mapres_tilemap.cpp
index 6038e67c..197a1a8b 100644
--- a/src/game/client/mapres_tilemap.cpp
+++ b/src/game/client/mapres_tilemap.cpp
@@ -5,8 +5,12 @@
 
 #include <baselib/opengl.h>
 
+bool must_init = true;
+void *batches[32] = {0};
+
 int tilemap_init()
 {
+	must_init = true;
 	return 0;
 }
 
@@ -14,8 +18,7 @@ void tilemap_render(float scale, int fg)
 {
 	if(!map_is_loaded())
 		return;
-	
-	
+		
 	float screen_x0, screen_y0, screen_x1, screen_y1;
 	gfx_getscreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
 	
@@ -23,12 +26,6 @@ void tilemap_render(float scale, int fg)
 	int start, num;
 	map_get_type(MAPRES_TILEMAP, &start, &num);
 
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, GL_REPEAT);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, GL_REPEAT);
-
-
 	// render tilemaps
 	int passed_main = 0;
 	for(int t = 0; t < num; t++)
@@ -42,58 +39,69 @@ void tilemap_render(float scale, int fg)
 		if((fg && passed_main) || (!fg && !passed_main))
 		{
 			gfx_texture_set(img_get(tmap->image));
-			gfx_quads_begin();
 			
-			float frac = (1.0f/1024.0f);//2.0f; //2.0f;
-			float texsize = 1024.0f;
-			float nudge = 0.5f/texsize;
+			glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 			
-			int startx = (int)(screen_x0/scale) - 1;
-			int endx = (int)(screen_x1/scale) + 1;
-			int starty = (int)(screen_y0/scale) - 1;
-			int endy = (int)(screen_y1/scale) + 1;
-			for(int y = starty; y < endy; y++)
-				for(int x = startx; x < endx; x++)
-				{
-					int mx = x;
-					int my = y;
-					if(mx<0) mx = 0;
-					if(mx>=tmap->width) mx = tmap->width-1;
-					if(my<0) my = 0;
-					if(my>=tmap->height) my = tmap->height-1;
-					
-					int c = mx + my*tmap->width;
-						
-					unsigned char d = data[c*2];
-					if(d)
+			if(!batches[t])
+			{
+				gfx_quads_begin();
+				
+				float frac = (1.0f/1024.0f);//2.0f; //2.0f;
+				float texsize = 1024.0f;
+				float nudge = 0.5f/texsize;
+				float s = 1.0f;
+				
+				for(int y = 0; y < tmap->height; y++)
+					for(int x = 0; x < tmap->width; x++)
 					{
-						//gfx_quads_setsubset(
-						//	(d%16)/16.0f*s+frac,
-						//	(d/16)/16.0f*s+frac,
-						//	((d%16)/16.0f+1.0f/16.0f)*s-frac,
-						//	((d/16)/16.0f+1.0f/16.0f)*s-frac);
+						int mx = x;
+						int my = y;
+						if(mx<0) mx = 0;
+						if(mx>=tmap->width) mx = tmap->width-1;
+						if(my<0) my = 0;
+						if(my>=tmap->height) my = tmap->height-1;
+						
+						int c = mx + my*tmap->width;
 							
-						int tx = d%16;
-						int ty = d/16;
-						int px0 = tx*(1024/16);
-						int py0 = ty*(1024/16);
-						int px1 = (tx+1)*(1024/16)-1;
-						int py1 = (ty+1)*(1024/16)-1;
-						gfx_quads_setsubset(
-							nudge + px0/texsize+frac,
-							nudge + py0/texsize+frac,
-							nudge + px1/texsize-frac,
-							nudge + py1/texsize-frac);
+						unsigned char d = data[c*2];
+						if(d)
+						{
+							/*
+							gfx_quads_setsubset(
+								(d%16)/16.0f*s+frac,
+								(d/16)/16.0f*s+frac,
+								((d%16)/16.0f+1.0f/16.0f)*s-frac,
+								((d/16)/16.0f+1.0f/16.0f)*s-frac);
+								*/
+							
+							int tx = d%16;
+							int ty = d/16;
+							int px0 = tx*(1024/16);
+							int py0 = ty*(1024/16);
+							int px1 = (tx+1)*(1024/16)-1;
+							int py1 = (ty+1)*(1024/16)-1;
+							float z = -5.0f;
+
+							gfx_quads_setsubset(
+								nudge + px0/texsize+frac,
+								nudge + py0/texsize+frac,
+								nudge + px1/texsize-frac,
+								nudge + py1/texsize-frac);
 
-						gfx_quads_drawTL(x*scale, y*scale, scale, scale);
+							gfx_quads_drawTL(x*scale, y*scale, scale, scale);
+						}
 					}
-				}
+				
+				//gfx_quads_end();
+				batches[t] = gfx_quads_create_batch();
+			}
 			
-			gfx_quads_end();
+			gfx_quads_draw_batch(batches[t]);
+			//glCallList(lists_start+t);
 		}
 	}
 	
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
+	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 	
 }
diff --git a/src/game/client/menu.cpp b/src/game/client/menu.cpp
index 373da6e6..9143594e 100644
--- a/src/game/client/menu.cpp
+++ b/src/game/client/menu.cpp
@@ -43,7 +43,7 @@ enum gui_tileset_enum
 
 int gui_tileset_texture;
 int cursor_texture;
-int cloud1_texture, cloud2_texture, cloud3_texture;
+//int cloud1_texture, cloud2_texture, cloud3_texture;
 int menu_background_texture;
 int butterflies_texture;
 
@@ -159,7 +159,7 @@ void draw_background(float t)
 
 	render_sun(170, 170);
 
-    gfx_texture_set(cloud1_texture);
+    gfx_texture_set(data->images[IMAGE_CLOUD_1].id);
     gfx_quads_begin();
     gfx_quads_setcolor(1,1,1,1);
 	gfx_quads_setsubset(
@@ -170,7 +170,7 @@ void draw_background(float t)
     gfx_quads_drawTL(3500 - fmod(t * 20 + 2000, 4524), 0, 512, 512);
     gfx_quads_end();
 
-    gfx_texture_set(cloud2_texture);
+    gfx_texture_set(data->images[IMAGE_CLOUD_2].id);
     gfx_quads_begin();
     gfx_quads_setcolor(1,1,1,1);
 	gfx_quads_setsubset(
@@ -181,7 +181,7 @@ void draw_background(float t)
     gfx_quads_drawTL(3000 - fmod(t * 50 + 1000, 4024), 150, 512, 512);
     gfx_quads_end();
 
-    gfx_texture_set(cloud3_texture);
+    gfx_texture_set(data->images[IMAGE_CLOUD_3].id);
     gfx_quads_begin();
     gfx_quads_setcolor(1,1,1,1);
 	gfx_quads_setsubset(
@@ -704,7 +704,6 @@ static int main_render()
 	if (!inited)
 	{
 		inited = true;
-
 		client_serverbrowse_refresh(0);
 	}
 
@@ -914,7 +913,7 @@ static int settings_render()
 	if (ui_do_button(&save_button, "Save", 0, 482, 490, 128, 48, draw_teewars_button))
 	{
 		config = config_copy;
-		config_save("teewars.cfg");
+		config_save("default.cfg");
 		screen = SCREEN_MAIN;
 	}
 	
@@ -1143,9 +1142,6 @@ void modmenu_init()
 	gui_tileset_texture = gfx_load_texture("data/gui/gui_widgets.png");
     teewars_banner_texture = gfx_load_texture("data/gui_logo.png");
 	cursor_texture = gfx_load_texture("data/gui/cursor.png");
-	cloud1_texture = gfx_load_texture("data/cloud-1.png");
-	cloud2_texture = gfx_load_texture("data/cloud-2.png");
-	cloud3_texture = gfx_load_texture("data/cloud-3.png");
 	menu_background_texture = gfx_load_texture("data/menu_background.png");
 	butterflies_texture = gfx_load_texture("data/menu_butterfly.png");
 
diff --git a/src/game/server/game_server.cpp b/src/game/server/game_server.cpp
index d5c50b17..e063364c 100644
--- a/src/game/server/game_server.cpp
+++ b/src/game/server/game_server.cpp
@@ -343,7 +343,7 @@ game_world world;
 gameobject::gameobject()
 : entity(OBJTYPE_GAME)
 {
-	gametype = GAMETYPE_TDM;
+	gametype = GAMETYPE_DM;
 	game_over_tick = -1;
 	sudden_death = 0;
 	round_start_tick = server_tick();
diff --git a/src/crapnet/crapnet.cpp b/src/tools/crapnet.cpp
index f87803b5..f87803b5 100644
--- a/src/crapnet/crapnet.cpp
+++ b/src/tools/crapnet.cpp
diff --git a/src/tools/dilate.c b/src/tools/dilate.c
new file mode 100644
index 00000000..f53e7656
--- /dev/null
+++ b/src/tools/dilate.c
@@ -0,0 +1,98 @@
+
+#include "../engine/client/pnglite/pnglite.c"
+
+typedef struct pixel_t
+{
+	unsigned char r, g, b, a;
+} pixel;
+
+static int clamp(int v, int min, int max)
+{
+	if(v > max)
+		return max;
+	if(v < min)
+		return min;
+	return v;
+}
+
+static void dilate(int w, int h, pixel *src, pixel *dst)
+{
+	int x, y, k, m, c;
+	int ix, iy;
+
+	m = 0;
+	for(y = 0; y < h; y++)
+	{
+		for(x = 0; x < w; x++, m++)
+		{
+			dst[m] = src[m];
+			if(src[m].a)
+				continue;
+			
+			const int xo[] = {0, -1, 1, 0};
+			const int yo[] = {-1, 0, 0, 1};
+			for(c = 0; c < 4; c++)
+			{
+				ix = clamp(x + xo[c], 0, w-1);
+				iy = clamp(y + yo[c], 0, h-1);
+				k = iy*w+ix;
+				if(src[k].a)
+				{
+					dst[m] = src[k];
+					dst[m].a = 255;
+					break;
+				}
+			}
+		}
+	}
+}
+
+static void copy_alpha(int w, int h, pixel *src, pixel *dst)
+{
+	int x, y, m;
+
+	for(y = 0; y < h; y++)
+		for(x = 0; x < w; x++, m++)
+			dst[m].a = src[m].a;
+}
+
+int main(int argc, char **argv)
+{
+	png_t png;
+	pixel *buffer[3] = {0,0,0};
+	int i, w, h;
+	
+	png_init(0,0);
+	png_open_file(&png, argv[1]);
+	
+	if(png.color_type != PNG_TRUECOLOR_ALPHA)
+	{
+		printf("not an RGBA image\n");
+		return -1;
+	}
+	
+	buffer[0] = (pixel*)malloc(png.width*png.height*sizeof(pixel));
+	buffer[1] = (pixel*)malloc(png.width*png.height*sizeof(pixel));
+	buffer[2] = (pixel*)malloc(png.width*png.height*sizeof(pixel));
+	png_get_data(&png, (unsigned char *)buffer[0]);
+	png_close_file(&png);
+	
+	w = png.width;
+	h = png.height;
+	
+	dilate(w, h, buffer[0], buffer[1]);
+	for(i = 0; i < 5; i++)
+	{
+		dilate(w, h, buffer[1], buffer[2]);
+		dilate(w, h, buffer[2], buffer[1]);
+	}
+	
+	copy_alpha(w, h, buffer[0], buffer[1]);
+	
+	// save here
+	png_open_file_write(&png, argv[1]);
+	png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)buffer[1]);
+	png_close_file(&png);
+	
+	return 0;
+}
diff --git a/src/tools/tileset_borderfix.c b/src/tools/tileset_borderfix.c
new file mode 100644
index 00000000..ba7a40f0
--- /dev/null
+++ b/src/tools/tileset_borderfix.c
@@ -0,0 +1,83 @@
+
+#include "../engine/client/pnglite/pnglite.c"
+
+typedef struct pixel_t
+{
+	unsigned char r, g, b, a;
+} pixel;
+
+static pixel sample(int x, int y, int w, int h, pixel *data, int pitch, float u, float v)
+{
+	x = x + (int)(w*u);
+	y = y + (int)(h*v);
+	return data[y*pitch+x];
+}
+
+static void tilemap_borderfix(int w, int h, pixel *src, pixel *dst)
+{
+	int tilew = w/16;
+	int tileh = h/16;
+	int tx, ty;
+	int x, y;
+	int k;
+	float u, v;
+	
+	memset(dst, 0, sizeof(pixel)*w*h);
+				
+	for(ty = 0; ty < 16; ty++)
+		for(tx = 0; tx < 16; tx++)
+		{
+			for(y = 0; y < tileh-2; y++)
+				for(x = 0; x < tilew-2; x++)
+				{
+					u = 0.5f/tilew + x/(float)(tilew-2);
+					v = 0.5f/tileh + y/(float)(tileh-2);
+					k = (ty*tileh+1+y)*w + tx*tilew+x+1;
+					dst[k] = sample(tx*tilew, ty*tileh, tilew, tileh, src, w, u, v);
+					
+					if(x == 0) dst[k-1] = dst[k];
+					if(x == tilew-2-1) dst[k+1] = dst[k];
+					if(y == 0) dst[k-w] = dst[k];
+					if(y == tileh-2-1) dst[k+w] = dst[k];
+					
+					if(x == 0 && y == 0) dst[k-w-1] = dst[k];
+					if(x == tilew-2-1 && y == 0) dst[k-w+1] = dst[k];
+					if(x == 0 && y == tileh-2-1) dst[k+w-1] = dst[k];
+					if(x == tilew-2-1 && y == tileh-2-1) dst[k+w+1] = dst[k];
+				}
+		}
+}
+
+
+int main(int argc, char **argv)
+{
+	png_t png;
+	pixel *buffer[2] = {0,0};
+	int w, h;
+	
+	png_init(0,0);
+	png_open_file(&png, argv[1]);
+	
+	if(png.color_type != PNG_TRUECOLOR_ALPHA)
+	{
+		printf("not an RGBA image\n");
+		return -1;
+	}
+	
+	w = png.width;
+	h = png.height;
+	
+	buffer[0] = (pixel*)malloc(w*h*sizeof(pixel));
+	buffer[1] = (pixel*)malloc(w*h*sizeof(pixel));
+	png_get_data(&png, (unsigned char *)buffer[0]);
+	png_close_file(&png);
+	
+	tilemap_borderfix(w, h, buffer[0], buffer[1]);
+	
+	// save here
+	png_open_file_write(&png, "output.png");
+	png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)buffer[1]);
+	png_close_file(&png);
+		
+	return 0;
+}