about summary refs log tree commit diff
path: root/src/engine/client
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2009-10-27 14:38:53 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2009-10-27 14:38:53 +0000
commit878ede3080ab2cfb627aca505c397d9765052996 (patch)
tree98bff371070e1dca0295f0ca58d64ac4ee8042ce /src/engine/client
parent9b99ec0e60b60134e46f2f71d707230948f7db03 (diff)
downloadzcatch-878ede3080ab2cfb627aca505c397d9765052996.tar.gz
zcatch-878ede3080ab2cfb627aca505c397d9765052996.zip
major update with stuff
Diffstat (limited to 'src/engine/client')
-rw-r--r--src/engine/client/ec_client.cpp (renamed from src/engine/client/ec_client.c)396
-rw-r--r--src/engine/client/ec_gfx.c1020
-rw-r--r--src/engine/client/ec_gfx.cpp992
-rw-r--r--src/engine/client/ec_gfx_text.cpp (renamed from src/engine/client/ec_gfx_text.c)29
-rw-r--r--src/engine/client/ec_inp.cpp (renamed from src/engine/client/ec_inp.c)12
-rw-r--r--src/engine/client/ec_snd.cpp (renamed from src/engine/client/ec_snd.c)22
-rw-r--r--src/engine/client/ec_srvbrowse.cpp (renamed from src/engine/client/ec_srvbrowse.c)69
7 files changed, 1274 insertions, 1266 deletions
diff --git a/src/engine/client/ec_client.c b/src/engine/client/ec_client.cpp
index 0c707ccf..7ba0a2bb 100644
--- a/src/engine/client/ec_client.c
+++ b/src/engine/client/ec_client.cpp
@@ -28,6 +28,28 @@
 #include <mastersrv/mastersrv.h>
 #include <versionsrv/versionsrv.h>
 
+#include "editor.h"
+#include "graphics.h"
+#include "client.h"
+
+static IEditor *m_pEditor = 0;
+static IEngineGraphics *m_pGraphics = 0;
+IEngineGraphics *Graphics() { return m_pGraphics; }
+
+static IGameClient *m_pGameClient = 0;
+
+
+class CClient : public IEngine
+{
+public:
+	virtual class IGraphics *Graphics()
+	{
+		return m_pGraphics;
+	}
+};
+
+static CClient m_Client;
+
 const int prediction_margin = 1000/50/2; /* magic network prediction value */
 
 /*
@@ -43,7 +65,7 @@ const int prediction_margin = 1000/50/2; /* magic network prediction value */
 */
 
 /* network client, must be accessible from other parts like the server browser */
-NETCLIENT *net;
+CNetClient m_NetClient;
 
 /* TODO: ugly, fix me */
 extern void client_serverbrowse_set(NETADDR *addr, int request, int token, SERVER_INFO *info);
@@ -171,22 +193,22 @@ static void graph_render(GRAPH *g, float x, float y, float w, float h, const cha
 	char buf[32];
 	int i;
 
-	gfx_blend_normal();
+	//m_pGraphics->BlendNormal();
 
 	
-	gfx_texture_set(-1);
+	Graphics()->TextureSet(-1);
 	
-	gfx_quads_begin();
-	gfx_setcolor(0, 0, 0, 0.75f);
-	gfx_quads_drawTL(x, y, w, h);
-	gfx_quads_end();
+	m_pGraphics->QuadsBegin();
+	Graphics()->SetColor(0, 0, 0, 0.75f);
+	Graphics()->QuadsDrawTL(x, y, w, h);
+	m_pGraphics->QuadsEnd();
 		
-	gfx_lines_begin();
-	gfx_setcolor(0.95f, 0.95f, 0.95f, 1.00f);
-	gfx_lines_draw(x, y+h/2, x+w, y+h/2);
-	gfx_setcolor(0.5f, 0.5f, 0.5f, 0.75f);
-	gfx_lines_draw(x, y+(h*3)/4, x+w, y+(h*3)/4);
-	gfx_lines_draw(x, y+h/4, x+w, y+h/4);
+	Graphics()->LinesBegin();
+	Graphics()->SetColor(0.95f, 0.95f, 0.95f, 1.00f);
+	Graphics()->LinesDraw(x, y+h/2, x+w, y+h/2);
+	Graphics()->SetColor(0.5f, 0.5f, 0.5f, 0.75f);
+	Graphics()->LinesDraw(x, y+(h*3)/4, x+w, y+(h*3)/4);
+	Graphics()->LinesDraw(x, y+h/4, x+w, y+h/4);
 	for(i = 1; i < GRAPH_MAX; i++)
 	{
 		float a0 = (i-1)/(float)GRAPH_MAX;
@@ -197,22 +219,22 @@ static void graph_render(GRAPH *g, float x, float y, float w, float h, const cha
 		float v0 = (g->values[i0]-g->min) / (g->max-g->min);
 		float v1 = (g->values[i1]-g->min) / (g->max-g->min);
 		
-		gfx_setcolorvertex(0, g->colors[i0][0], g->colors[i0][1], g->colors[i0][2], 0.75f);
-		gfx_setcolorvertex(1, g->colors[i1][0], g->colors[i1][1], g->colors[i1][2], 0.75f);
-		gfx_lines_draw(x+a0*w, y+h-v0*h, x+a1*w, y+h-v1*h);
+		Graphics()->SetColorVertex(0, g->colors[i0][0], g->colors[i0][1], g->colors[i0][2], 0.75f);
+		Graphics()->SetColorVertex(1, g->colors[i1][0], g->colors[i1][1], g->colors[i1][2], 0.75f);
+		Graphics()->LinesDraw(x+a0*w, y+h-v0*h, x+a1*w, y+h-v1*h);
 
 	}
-	gfx_lines_end();
+	Graphics()->LinesEnd();
 	
 
-	gfx_texture_set(debug_font);	
-	gfx_quads_text(x+2, y+h-16, 16, 1,1,1,1, description);
+	Graphics()->TextureSet(debug_font);	
+	Graphics()->QuadsText(x+2, y+h-16, 16, 1,1,1,1, description);
 
 	str_format(buf, sizeof(buf), "%.2f", g->max);
-	gfx_quads_text(x+w-8*strlen(buf)-8, y+2, 16, 1,1,1,1, buf);
+	Graphics()->QuadsText(x+w-8*strlen(buf)-8, y+2, 16, 1,1,1,1, buf);
 	
 	str_format(buf, sizeof(buf), "%.2f", g->min);
-	gfx_quads_text(x+w-8*strlen(buf)-8, y+h-16, 16, 1,1,1,1, buf);
+	Graphics()->QuadsText(x+w-8*strlen(buf)-8, y+h-16, 16, 1,1,1,1, buf);
 	
 }
 
@@ -336,40 +358,40 @@ enum
 };
 
 /* the game snapshots are modifiable by the game */
-SNAPSTORAGE snapshot_storage;
-static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES] = {0, 0};
+CSnapshotStorage snapshot_storage;
+static CSnapshotStorage::CHolder *snapshots[NUM_SNAPSHOT_TYPES] = {0, 0};
 
 static int recived_snapshots = 0;
-static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE];
+static char snapshot_incomming_data[CSnapshot::MAX_SIZE];
 
-static SNAPSTORAGE_HOLDER demorec_snapshotholders[NUM_SNAPSHOT_TYPES];
-static char *demorec_snapshotdata[NUM_SNAPSHOT_TYPES][2][MAX_SNAPSHOT_SIZE];
+static CSnapshotStorage::CHolder demorec_snapshotholders[NUM_SNAPSHOT_TYPES];
+static char *demorec_snapshotdata[NUM_SNAPSHOT_TYPES][2][CSnapshot::MAX_SIZE];
 
 /* --- */
 
 void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
 {
-	SNAPSHOT_ITEM *i;
+	CSnapshotItem *i;
 	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
-	item->datasize = snapshot_get_item_datasize(snapshots[snapid]->alt_snap, index);
-	item->type = snapitem_type(i);
-	item->id = snapitem_id(i);
-	return (void *)snapitem_data(i);
+	i = snapshots[snapid]->m_pAltSnap->GetItem(index);
+	item->datasize = snapshots[snapid]->m_pAltSnap->GetItemSize(index);
+	item->type = i->Type();
+	item->id = i->ID();
+	return (void *)i->Data();
 }
 
 void snap_invalidate_item(int snapid, int index)
 {
-	SNAPSHOT_ITEM *i;
+	CSnapshotItem *i;
 	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	i = snapshot_get_item(snapshots[snapid]->alt_snap, index);
+	i = snapshots[snapid]->m_pAltSnap->GetItem(index);
 	if(i)
 	{
-		if((char *)i < (char *)snapshots[snapid]->alt_snap || (char *)i > (char *)snapshots[snapid]->alt_snap + snapshots[snapid]->snap_size)
+		if((char *)i < (char *)snapshots[snapid]->m_pAltSnap || (char *)i > (char *)snapshots[snapid]->m_pAltSnap + snapshots[snapid]->m_SnapSize)
 			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
-		if((char *)i >= (char *)snapshots[snapid]->snap && (char *)i < (char *)snapshots[snapid]->snap + snapshots[snapid]->snap_size)
+		if((char *)i >= (char *)snapshots[snapid]->m_pSnap && (char *)i < (char *)snapshots[snapid]->m_pSnap + snapshots[snapid]->m_SnapSize)
 			dbg_msg("ASDFASDFASdf", "ASDFASDFASDF");
-		i->type_and_id = -1;
+		i->m_TypeAndID = -1;
 	}
 }
 
@@ -381,11 +403,11 @@ void *snap_find_item(int snapid, int type, int id)
 	if(!snapshots[snapid])
 		return 0x0;
 	
-	for(i = 0; i < snapshots[snapid]->snap->num_items; i++)
+	for(i = 0; i < snapshots[snapid]->m_pSnap->m_NumItems; i++)
 	{
-		SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->alt_snap, i);
-		if(snapitem_type(itm) == type && snapitem_id(itm) == id)
-			return (void *)snapitem_data(itm);
+		CSnapshotItem *itm = snapshots[snapid]->m_pAltSnap->GetItem(i);
+		if(itm->Type() == type && itm->ID() == id)
+			return (void *)itm->Data();
 	}
 	return 0x0;
 }
@@ -395,7 +417,7 @@ int snap_num_items(int snapid)
 	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
 	if(!snapshots[snapid])
 		return 0;
-	return snapshots[snapid]->snap->num_items;
+	return snapshots[snapid]->m_pSnap->m_NumItems;
 }
 
 /* ------ time functions ------ */
@@ -412,35 +434,34 @@ float client_localtime() { return (time_get()-local_start_time)/(float)(time_fre
 /* ----- send functions ----- */
 int client_send_msg()
 {
-	const MSG_INFO *info = msg_get_info();
-	NETCHUNK packet;
+	const MSG_INFO *pInfo = msg_get_info();
+	CNetChunk Packet;
 	
-	if(!info)
+	if(!pInfo)
 		return -1;
 
 	if(client_state() == CLIENTSTATE_OFFLINE)
 		return 0;
 	
-		
-	mem_zero(&packet, sizeof(NETCHUNK));
+	mem_zero(&Packet, sizeof(CNetChunk));
 	
-	packet.client_id = 0;
-	packet.data = info->data;
-	packet.data_size = info->size;
+	Packet.m_ClientID = 0;
+	Packet.m_pData = pInfo->data;
+	Packet.m_DataSize = pInfo->size;
 
-	if(info->flags&MSGFLAG_VITAL)
-		packet.flags |= NETSENDFLAG_VITAL;
-	if(info->flags&MSGFLAG_FLUSH)
-		packet.flags |= NETSENDFLAG_FLUSH;
+	if(pInfo->flags&MSGFLAG_VITAL)
+		Packet.m_Flags |= NETSENDFLAG_VITAL;
+	if(pInfo->flags&MSGFLAG_FLUSH)
+		Packet.m_Flags |= NETSENDFLAG_FLUSH;
 		
-	if(info->flags&MSGFLAG_RECORD)
+	if(pInfo->flags&MSGFLAG_RECORD)
 	{
 		if(demorec_isrecording())
-			demorec_record_message(packet.data, packet.data_size);
+			demorec_record_message(Packet.m_pData, Packet.m_DataSize);
 	}
 
-	if(!(info->flags&MSGFLAG_NOSEND))
-		netclient_send(net, &packet);
+	if(!(pInfo->flags&MSGFLAG_NOSEND))
+		m_NetClient.Send(&Packet);
 	return 0;
 }
 
@@ -494,7 +515,7 @@ void client_rcon(const char *cmd)
 
 int client_connection_problems()
 {
-	return netclient_gotproblems(net);
+	return m_NetClient.GotProblems();
 }
 
 void client_direct_input(int *input, int size)
@@ -594,7 +615,7 @@ static void client_on_enter_game()
 	/* reset snapshots */
 	snapshots[SNAP_CURRENT] = 0;
 	snapshots[SNAP_PREV] = 0;
-	snapstorage_purge_all(&snapshot_storage);
+	snapshot_storage.PurgeAll();
 	recived_snapshots = 0;
 	snapshot_parts = 0;
 	current_predtick = 0;
@@ -645,7 +666,7 @@ void client_connect(const char *server_address_str)
 	
 	rcon_authed = 0;
 	server_address.port = port;
-	netclient_connect(net, &server_address);
+	m_NetClient.Connect(&server_address);
 	client_set_state(CLIENTSTATE_CONNECTING);
 	
 	graph_init(&inputtime_margin_graph, -150.0f, 150.0f);
@@ -659,7 +680,7 @@ void client_disconnect_with_reason(const char *reason)
 	
 	/* */
 	rcon_authed = 0;
-	netclient_disconnect(net, reason);
+	m_NetClient.Disconnect(reason);
 	client_set_state(CLIENTSTATE_OFFLINE);
 	map_unload();
 	
@@ -701,7 +722,7 @@ void client_serverinfo_request()
 
 static int client_load_data()
 {
-	debug_font = gfx_load_texture("debug_font.png", IMG_AUTO, TEXLOAD_NORESAMPLE);
+	debug_font = Graphics()->LoadTexture("debug_font.png", IMG_AUTO, TEXLOAD_NORESAMPLE);
 	return 1;
 }
 
@@ -721,9 +742,9 @@ static void client_debug_render()
 	if(!config.debug)
 		return;
 	
-	gfx_blend_normal();
-	gfx_texture_set(debug_font);
-	gfx_mapscreen(0,0,gfx_screenwidth(),gfx_screenheight());
+	//m_pGraphics->BlendNormal();
+	Graphics()->TextureSet(debug_font);
+	Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight());
 	
 	if(time_get()-last_snap > time_freq())
 	{
@@ -739,13 +760,13 @@ static void client_debug_render()
 		total = 42
 	*/
 	frametime_avg = frametime_avg*0.9f + frametime*0.1f;
-	str_format(buffer, sizeof(buffer), "ticks: %8d %8d mem %dk %d  gfxmem: %dk  fps: %3d",
+	str_format(buffer, sizeof(buffer), "ticks: %8d %8d mem %dk %d  gfxmem: N/A  fps: %3d",
 		current_tick, current_predtick,
 		mem_stats()->allocated/1024,
 		mem_stats()->total_allocations,
-		gfx_memory_usage()/1024,
+		/*gfx_memory_usage()/1024, */ // TODO: Refactor: Reenable this
 		(int)(1.0f/frametime_avg));
-	gfx_quads_text(2, 2, 16, 1,1,1,1, buffer);
+	Graphics()->QuadsText(2, 2, 16, 1,1,1,1, buffer);
 
 	
 	{
@@ -761,7 +782,7 @@ static void client_debug_render()
 		str_format(buffer, sizeof(buffer), "send: %3d %5d+%4d=%5d (%3d kbps) avg: %5d\nrecv: %3d %5d+%4d=%5d (%3d kbps) avg: %5d",
 			send_packets, send_bytes, send_packets*42, send_total, (send_total*8)/1024, send_bytes/send_packets,
 			recv_packets, recv_bytes, recv_packets*42, recv_total, (recv_total*8)/1024, recv_bytes/recv_packets);
-		gfx_quads_text(2, 14, 16, 1,1,1,1, buffer);
+		Graphics()->QuadsText(2, 14, 16, 1,1,1,1, buffer);
 	}
 	
 	/* render rates */
@@ -774,7 +795,7 @@ static void client_debug_render()
 			{
 				str_format(buffer, sizeof(buffer), "%4d %20s: %8d %8d %8d", i, modc_getitemname(i), snapshot_data_rate[i]/8, snapshot_data_updates[i],
 					(snapshot_data_rate[i]/snapshot_data_updates[i])/8);
-				gfx_quads_text(2, 100+y*12, 16, 1,1,1,1, buffer);
+				Graphics()->QuadsText(2, 100+y*12, 16, 1,1,1,1, buffer);
 				y++;
 			}
 		}
@@ -783,16 +804,16 @@ static void client_debug_render()
 	str_format(buffer, sizeof(buffer), "pred: %d ms  %3.2f", 
 		(int)((st_get(&predicted_time, now)-st_get(&game_time, now))*1000/(float)time_freq()),
 		predicted_time.adjustspeed[1]);
-	gfx_quads_text(2, 70, 16, 1,1,1,1, buffer);
+	Graphics()->QuadsText(2, 70, 16, 1,1,1,1, buffer);
 	
 	/* render graphs */
 	if(config.dbg_graphs)
 	{
-		//gfx_mapscreen(0,0,400.0f,300.0f);
-		float w = gfx_screenwidth()/4.0f;
-		float h = gfx_screenheight()/6.0f;
-		float sp = gfx_screenwidth()/100.0f;
-		float x = gfx_screenwidth()-w-sp;
+		//Graphics()->MapScreen(0,0,400.0f,300.0f);
+		float w = Graphics()->ScreenWidth()/4.0f;
+		float h = Graphics()->ScreenHeight()/6.0f;
+		float sp = Graphics()->ScreenWidth()/100.0f;
+		float x = Graphics()->ScreenWidth()-w-sp;
 
 		graph_scale_max(&fps_graph);
 		graph_scale_min(&fps_graph);
@@ -809,13 +830,13 @@ void client_quit()
 
 const char *client_error_string()
 {
-	return netclient_error_string(net);
+	return m_NetClient.ErrorString();
 }
 
 static void client_render()
 {
 	if(config.gfx_clear)	
-		gfx_clear(1,1,0);
+		Graphics()->Clear(1,1,0);
 
 	modc_render();
 	client_debug_render();
@@ -888,15 +909,15 @@ static int player_score_comp(const void *a, const void *b)
 	return -1;
 }
 
-static void client_process_packet(NETCHUNK *packet)
+static void client_process_packet(CNetChunk *pPacket)
 {
-	if(packet->client_id == -1)
+	if(pPacket->m_ClientID == -1)
 	{
 		/* connectionlesss */
-		if(packet->data_size == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) &&
-			memcmp(packet->data, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0)
+		if(pPacket->m_DataSize == (int)(sizeof(VERSIONSRV_VERSION) + sizeof(VERSION_DATA)) &&
+			memcmp(pPacket->m_pData, VERSIONSRV_VERSION, sizeof(VERSIONSRV_VERSION)) == 0)
 		{
-			unsigned char *versiondata = (unsigned char*) packet->data + sizeof(VERSIONSRV_VERSION);
+			unsigned char *versiondata = (unsigned char*)pPacket->m_pData + sizeof(VERSIONSRV_VERSION);
 			int version_match = !memcmp(versiondata, VERSION_DATA, sizeof(VERSION_DATA));
 			
 			dbg_msg("client/version", "version does %s (%d.%d.%d)",
@@ -910,12 +931,12 @@ static void client_process_packet(NETCHUNK *packet)
 			}
 		}
 		
-		if(packet->data_size >= (int)sizeof(SERVERBROWSE_LIST) &&
-			memcmp(packet->data, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
+		if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_LIST) &&
+			memcmp(pPacket->m_pData, SERVERBROWSE_LIST, sizeof(SERVERBROWSE_LIST)) == 0)
 		{
-			int size = packet->data_size-sizeof(SERVERBROWSE_LIST);
+			int size = pPacket->m_DataSize-sizeof(SERVERBROWSE_LIST);
 			int num = size/sizeof(MASTERSRV_ADDR);
-			MASTERSRV_ADDR *addrs = (MASTERSRV_ADDR *)((char*)packet->data+sizeof(SERVERBROWSE_LIST));
+			MASTERSRV_ADDR *addrs = (MASTERSRV_ADDR *)((char*)pPacket->m_pData+sizeof(SERVERBROWSE_LIST));
 			int i;
 
 			for(i = 0; i < num; i++)
@@ -937,47 +958,47 @@ static void client_process_packet(NETCHUNK *packet)
 
 		{
 			int packet_type = 0;
-			if(packet->data_size >= (int)sizeof(SERVERBROWSE_INFO) && memcmp(packet->data, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
+			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_INFO) && memcmp(pPacket->m_pData, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
 				packet_type = 2;
 
-			if(packet->data_size >= (int)sizeof(SERVERBROWSE_OLD_INFO) && memcmp(packet->data, SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO)) == 0)
+			if(pPacket->m_DataSize >= (int)sizeof(SERVERBROWSE_OLD_INFO) && memcmp(pPacket->m_pData, SERVERBROWSE_OLD_INFO, sizeof(SERVERBROWSE_OLD_INFO)) == 0)
 				packet_type = 1;
 			
 			if(packet_type)
 			{
 				/* we got ze info */
-				UNPACKER up;
+				CUnpacker up;
 				SERVER_INFO info = {0};
 				int i;
 				int token = -1;
 				
-				unpacker_reset(&up, (unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO));
+				up.Reset((unsigned char*)pPacket->m_pData+sizeof(SERVERBROWSE_INFO), pPacket->m_DataSize-sizeof(SERVERBROWSE_INFO));
 				if(packet_type >= 2)
-					token = atol(unpacker_get_string(&up));
-				str_copy(info.version, unpacker_get_string(&up), sizeof(info.version));
-				str_copy(info.name, unpacker_get_string(&up), sizeof(info.name));
-				str_copy(info.map, unpacker_get_string(&up), sizeof(info.map));
-				str_copy(info.gametype, unpacker_get_string(&up), sizeof(info.gametype));
-				info.flags = atol(unpacker_get_string(&up));
-				info.progression = atol(unpacker_get_string(&up));
-				info.num_players = atol(unpacker_get_string(&up));
-				info.max_players = atol(unpacker_get_string(&up));
+					token = atol(up.GetString());
+				str_copy(info.version, up.GetString(), sizeof(info.version));
+				str_copy(info.name, up.GetString(), sizeof(info.name));
+				str_copy(info.map, up.GetString(), sizeof(info.map));
+				str_copy(info.gametype, up.GetString(), sizeof(info.gametype));
+				info.flags = atol(up.GetString());
+				info.progression = atol(up.GetString());
+				info.num_players = atol(up.GetString());
+				info.max_players = atol(up.GetString());
 				str_format(info.address, sizeof(info.address), "%d.%d.%d.%d:%d",
-					packet->address.ip[0], packet->address.ip[1], packet->address.ip[2],
-					packet->address.ip[3], packet->address.port);
+					pPacket->m_Address.ip[0], pPacket->m_Address.ip[1], pPacket->m_Address.ip[2],
+					pPacket->m_Address.ip[3], pPacket->m_Address.port);
 				
 				for(i = 0; i < info.num_players; i++)
 				{
-					str_copy(info.players[i].name, unpacker_get_string(&up), sizeof(info.players[i].name));
-					info.players[i].score = atol(unpacker_get_string(&up));
+					str_copy(info.players[i].name, up.GetString(), sizeof(info.players[i].name));
+					info.players[i].score = atol(up.GetString());
 				}
 				
-				if(!up.error)
+				if(!up.Error())
 				{
 					/* sort players */
 					qsort(info.players, info.num_players, sizeof(*info.players), player_score_comp);
 					
-					if(net_addr_comp(&server_address, &packet->address) == 0)
+					if(net_addr_comp(&server_address, &pPacket->m_Address) == 0)
 					{
 						mem_copy(&current_server_info, &info, sizeof(current_server_info));
 						current_server_info.netaddr = server_address;
@@ -986,9 +1007,9 @@ static void client_process_packet(NETCHUNK *packet)
 					else
 					{
 						if(packet_type == 2)
-							client_serverbrowse_set(&packet->address, BROWSESET_TOKEN, token, &info);
+							client_serverbrowse_set(&pPacket->m_Address, BROWSESET_TOKEN, token, &info);
 						else
-							client_serverbrowse_set(&packet->address, BROWSESET_OLD_INTERNET, -1, &info);
+							client_serverbrowse_set(&pPacket->m_Address, BROWSESET_OLD_INTERNET, -1, &info);
 					}
 				}
 			}
@@ -997,7 +1018,7 @@ static void client_process_packet(NETCHUNK *packet)
 	else
 	{
 		int sys;
-		int msg = msg_unpack_start(packet->data, packet->data_size, &sys);
+		int msg = msg_unpack_start(pPacket->m_pData, pPacket->m_DataSize, &sys);
 		
 		if(sys)
 		{
@@ -1193,15 +1214,15 @@ static void client_process_packet(NETCHUNK *packet)
 					mem_copy((char*)snapshot_incomming_data + part*MAX_SNAPSHOT_PACKSIZE, data, part_size);
 					snapshot_parts |= 1<<part;
 				
-					if(snapshot_parts == (1<<num_parts)-1)
+					if(snapshot_parts == (unsigned)((1<<num_parts)-1))
 					{
-						static SNAPSHOT emptysnap;
-						SNAPSHOT *deltashot = &emptysnap;
+						static CSnapshot emptysnap;
+						CSnapshot *deltashot = &emptysnap;
 						int purgetick;
 						void *deltadata;
 						int deltasize;
-						unsigned char tmpbuffer2[MAX_SNAPSHOT_SIZE];
-						unsigned char tmpbuffer3[MAX_SNAPSHOT_SIZE];
+						unsigned char tmpbuffer2[CSnapshot::MAX_SIZE];
+						unsigned char tmpbuffer3[CSnapshot::MAX_SIZE];
 						int snapsize;
 						
 						complete_size = (num_parts-1) * MAX_SNAPSHOT_PACKSIZE + part_size;
@@ -1210,13 +1231,13 @@ static void client_process_packet(NETCHUNK *packet)
 						snapshot_parts = 0;
 						
 						/* find snapshot that we should use as delta */
-						emptysnap.data_size = 0;
-						emptysnap.num_items = 0;
+						emptysnap.m_DataSize = 0;
+						emptysnap.m_NumItems = 0;
 						
 						/* find delta */
 						if(delta_tick >= 0)
 						{
-							int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot, 0);
+							int deltashot_size = snapshot_storage.Get(delta_tick, 0, &deltashot, 0);
 							
 							if(deltashot_size < 0)
 							{
@@ -1233,7 +1254,7 @@ static void client_process_packet(NETCHUNK *packet)
 						}
 
 						/* decompress snapshot */
-						deltadata = snapshot_empty_delta();
+						deltadata = CSnapshot::EmptyDelta();
 						deltasize = sizeof(int)*3;
 
 						if(complete_size)
@@ -1249,19 +1270,19 @@ static void client_process_packet(NETCHUNK *packet)
 						
 						/* unpack delta */
 						purgetick = delta_tick;
-						snapsize = snapshot_unpack_delta(deltashot, (SNAPSHOT*)tmpbuffer3, deltadata, deltasize);
+						snapsize = CSnapshot::UnpackDelta(deltashot, (CSnapshot*)tmpbuffer3, deltadata, deltasize);
 						if(snapsize < 0)
 						{
 							dbg_msg("client", "delta unpack failed!");
 							return;
 						}
 						
-						if(msg != NETMSG_SNAPEMPTY && snapshot_crc((SNAPSHOT*)tmpbuffer3) != crc)
+						if(msg != NETMSG_SNAPEMPTY && ((CSnapshot*)tmpbuffer3)->Crc() != crc)
 						{
 							if(config.debug)
 							{
 								dbg_msg("client", "snapshot crc error #%d - tick=%d wantedcrc=%d gotcrc=%d compressed_size=%d delta_tick=%d",
-									snapcrcerrors, game_tick, crc, snapshot_crc((SNAPSHOT*)tmpbuffer3), complete_size, delta_tick);
+									snapcrcerrors, game_tick, crc, ((CSnapshot*)tmpbuffer3)->Crc(), complete_size, delta_tick);
 							}
 								
 							snapcrcerrors++;
@@ -1282,14 +1303,14 @@ static void client_process_packet(NETCHUNK *packet)
 
 						/* purge old snapshots */
 						purgetick = delta_tick;
-						if(snapshots[SNAP_PREV] && snapshots[SNAP_PREV]->tick < purgetick)
-							purgetick = snapshots[SNAP_PREV]->tick;
-						if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick)
-							purgetick = snapshots[SNAP_PREV]->tick;
-						snapstorage_purge_until(&snapshot_storage, purgetick);
+						if(snapshots[SNAP_PREV] && snapshots[SNAP_PREV]->m_Tick < purgetick)
+							purgetick = snapshots[SNAP_PREV]->m_Tick;
+						if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->m_Tick < purgetick)
+							purgetick = snapshots[SNAP_PREV]->m_Tick;
+						snapshot_storage.PurgeUntil(purgetick);
 						
 						/* add new */
-						snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3, 1);
+						snapshot_storage.Add(game_tick, time_get(), snapsize, (CSnapshot*)tmpbuffer3, 1);
 
 						/* add snapshot to demo */
 						if(demorec_isrecording())
@@ -1320,8 +1341,8 @@ static void client_process_packet(NETCHUNK *packet)
 							st_init(&predicted_time, game_tick*time_freq()/50);
 							predicted_time.adjustspeed[1] = 1000.0f;
 							st_init(&game_time, (game_tick-1)*time_freq()/50);
-							snapshots[SNAP_PREV] = snapshot_storage.first;
-							snapshots[SNAP_CURRENT] = snapshot_storage.last;
+							snapshots[SNAP_PREV] = snapshot_storage.m_pFirst;
+							snapshots[SNAP_CURRENT] = snapshot_storage.m_pLast;
 							local_start_time = time_get();
 							client_set_state(CLIENTSTATE_ONLINE);
 						}
@@ -1345,8 +1366,8 @@ static void client_process_packet(NETCHUNK *packet)
 		{
 			/* game message */
 			if(demorec_isrecording())
-				demorec_record_message(packet->data, packet->data_size);
-				/* demorec_record_write("MESG", packet->data_size, ); */
+				demorec_record_message(pPacket->m_pData, pPacket->m_DataSize);
+				/* demorec_record_write("MESG", pPacket->data_size, ); */
 
 			modc_message(msg);
 		}
@@ -1358,22 +1379,21 @@ int client_mapdownload_totalsize() { return mapdownload_totalsize; }
 
 static void client_pump_network()
 {
-	NETCHUNK packet;
 
-	netclient_update(net);
+	m_NetClient.Update();
 
 	if(client_state() != CLIENTSTATE_DEMOPLAYBACK)
 	{
 		/* check for errors */
-		if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE)
+		if(client_state() != CLIENTSTATE_OFFLINE && m_NetClient.State() == NETSTATE_OFFLINE)
 		{
 			client_set_state(CLIENTSTATE_OFFLINE);
 			client_disconnect();
-			dbg_msg("client", "offline error='%s'", netclient_error_string(net));
+			dbg_msg("client", "offline error='%s'", m_NetClient.ErrorString());
 		}
 
 		/* */
-		if(client_state() == CLIENTSTATE_CONNECTING && netclient_state(net) == NETSTATE_ONLINE)
+		if(client_state() == CLIENTSTATE_CONNECTING && m_NetClient.State() == NETSTATE_ONLINE)
 		{
 			/* we switched to online */
 			dbg_msg("client", "connected, sending info");
@@ -1383,15 +1403,16 @@ static void client_pump_network()
 	}
 	
 	/* process packets */
-	while(netclient_recv(net, &packet))
-		client_process_packet(&packet);
+	CNetChunk Packet;
+	while(m_NetClient.Recv(&Packet))
+		client_process_packet(&Packet);
 }
 
-static void client_democallback_snapshot(void *data, int size)
+static void client_democallback_snapshot(void *pData, int Size)
 {
 	/* update ticks, they could have changed */
 	const DEMOREC_PLAYBACKINFO *info = demorec_playback_info();			
-	SNAPSTORAGE_HOLDER *temp;
+	CSnapshotStorage::CHolder *temp;
 	current_tick = info->current_tick;
 	prev_tick = info->previous_tick;
 	
@@ -1400,8 +1421,8 @@ static void client_democallback_snapshot(void *data, int size)
 	snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
 	snapshots[SNAP_CURRENT] = temp;
 	
-	mem_copy(snapshots[SNAP_CURRENT]->snap, data, size);
-	mem_copy(snapshots[SNAP_CURRENT]->alt_snap, data, size);
+	mem_copy(snapshots[SNAP_CURRENT]->m_pSnap, pData, Size);
+	mem_copy(snapshots[SNAP_CURRENT]->m_pAltSnap, pData, Size);
 	
 	modc_newsnapshot();
 	/*modc_predict();*/
@@ -1476,20 +1497,20 @@ static void client_update()
 
 		while(1)
 		{
-			SNAPSTORAGE_HOLDER *cur = snapshots[SNAP_CURRENT];
-			int64 tickstart = (cur->tick)*time_freq()/50;
+			CSnapshotStorage::CHolder *cur = snapshots[SNAP_CURRENT];
+			int64 tickstart = (cur->m_Tick)*time_freq()/50;
 
 			if(tickstart < now)
 			{
-				SNAPSTORAGE_HOLDER *next = snapshots[SNAP_CURRENT]->next;
+				CSnapshotStorage::CHolder *next = snapshots[SNAP_CURRENT]->m_pNext;
 				if(next)
 				{
 					snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
 					snapshots[SNAP_CURRENT] = next;
 					
 					/* set ticks */
-					current_tick = snapshots[SNAP_CURRENT]->tick;
-					prev_tick = snapshots[SNAP_PREV]->tick;
+					current_tick = snapshots[SNAP_CURRENT]->m_Tick;
+					prev_tick = snapshots[SNAP_PREV]->m_Tick;
 					
 					if(snapshots[SNAP_CURRENT] && snapshots[SNAP_PREV])
 					{
@@ -1506,8 +1527,8 @@ static void client_update()
 
 		if(snapshots[SNAP_CURRENT] && snapshots[SNAP_PREV])
 		{
-			int64 curtick_start = (snapshots[SNAP_CURRENT]->tick)*time_freq()/50;
-			int64 prevtick_start = (snapshots[SNAP_PREV]->tick)*time_freq()/50;
+			int64 curtick_start = (snapshots[SNAP_CURRENT]->m_Tick)*time_freq()/50;
+			int64 prevtick_start = (snapshots[SNAP_PREV]->m_Tick)*time_freq()/50;
 			/*tg_add(&predicted_time_graph, pred_now, 0); */
 			int prev_pred_tick = (int)(pred_now*50/time_freq());
 			int new_pred_tick = prev_pred_tick+1;
@@ -1520,10 +1541,10 @@ static void client_update()
 			prevtick_start = prev_pred_tick*time_freq()/50;
 			predintratick = (pred_now - prevtick_start) / (float)(curtick_start-prevtick_start);
 			
-			if(new_pred_tick < snapshots[SNAP_PREV]->tick-SERVER_TICK_SPEED || new_pred_tick > snapshots[SNAP_PREV]->tick+SERVER_TICK_SPEED)
+			if(new_pred_tick < snapshots[SNAP_PREV]->m_Tick-SERVER_TICK_SPEED || new_pred_tick > snapshots[SNAP_PREV]->m_Tick+SERVER_TICK_SPEED)
 			{
 				dbg_msg("client", "prediction time reset!");
-				st_init(&predicted_time, snapshots[SNAP_CURRENT]->tick*time_freq()/50);
+				st_init(&predicted_time, snapshots[SNAP_CURRENT]->m_Tick*time_freq()/50);
 			}
 			
 			if(new_pred_tick > current_predtick)
@@ -1606,27 +1627,24 @@ static void client_versionupdate()
 	{
 		if(jobs_status(&version_serveraddr.job) == JOBSTATUS_DONE)
 		{
-			NETCHUNK packet;
+			CNetChunk Packet;
 			
-			mem_zero(&packet, sizeof(NETCHUNK));
+			mem_zero(&Packet, sizeof(Packet));
 			
 			version_serveraddr.addr.port = VERSIONSRV_PORT;
 			
-			packet.client_id = -1;
-			packet.address = version_serveraddr.addr;
-			packet.data = VERSIONSRV_GETVERSION;
-			packet.data_size = sizeof(VERSIONSRV_GETVERSION);
-			packet.flags = NETSENDFLAG_CONNLESS;
+			Packet.m_ClientID = -1;
+			Packet.m_Address = version_serveraddr.addr;
+			Packet.m_pData = VERSIONSRV_GETVERSION;
+			Packet.m_DataSize = sizeof(VERSIONSRV_GETVERSION);
+			Packet.m_Flags = NETSENDFLAG_CONNLESS;
 			
-			netclient_send(net, &packet);
+			m_NetClient.Send(&Packet);
 			state++;
 		}
 	}
 }
 
-extern int editor_update_and_render();
-extern void editor_init();
-
 static void client_run()
 {
 	NETADDR bindaddr;
@@ -1640,14 +1658,16 @@ static void client_run()
 	snapshot_parts = 0;
 	
 	/* init graphics and sound */
-	if(gfx_init() != 0)
+	m_pGraphics = CreateEngineGraphics();
+	if(m_pGraphics->Init() != 0)
 		return;
 
 	/* start refreshing addresses while we load */
 	mastersrv_refresh_addresses();
 	
 	/* init the editor */
-	editor_init();
+	m_pEditor = CreateEditor();
+	m_pEditor->Init(m_pGraphics);
 
 	/* sound is allowed to fail */
 	snd_init();
@@ -1657,12 +1677,13 @@ static void client_run()
 		return;
 
 	/* init the mod */
+	m_pGameClient = CreateGameClient(&m_Client);
 	modc_init();
 	dbg_msg("client", "version %s", modc_net_version());
 	
 	/* open socket */
 	mem_zero(&bindaddr, sizeof(bindaddr));
-	net = netclient_open(bindaddr, 0);
+	m_NetClient.Open(bindaddr, 0);
 	
 	/* connect to the server if wanted */
 	/*
@@ -1714,7 +1735,7 @@ static void client_run()
 		}
 		
 		/* release focus */
-		if(!gfx_window_active())
+		if(!Graphics()->WindowActive())
 		{
 			if(window_must_refocus == 0)
 				inp_mouse_mode_absolute();
@@ -1727,7 +1748,7 @@ static void client_run()
 		}
 
 		/* refocus */
-		if(window_must_refocus && gfx_window_active())
+		if(window_must_refocus && Graphics()->WindowActive())
 		{
 			if(window_must_refocus < 3)
 			{
@@ -1767,8 +1788,8 @@ static void client_run()
 		if(config.cl_editor)
 		{
 			client_update();
-			editor_update_and_render();
-			gfx_swap();
+			m_pEditor->UpdateAndRender();
+			m_pGraphics->Swap();
 		}
 		else
 		{
@@ -1784,7 +1805,7 @@ static void client_run()
 				if((frames%10) == 0)
 				{
 					client_render();
-					gfx_swap();
+					m_pGraphics->Swap();
 				}
 			}
 			else
@@ -1799,7 +1820,7 @@ static void client_run()
 				{
 					static PERFORMACE_INFO scope = {"gfx_swap", 0};
 					perf_start(&scope);
-					gfx_swap();
+					m_pGraphics->Swap();
 					perf_end();
 				}
 			}
@@ -1815,7 +1836,7 @@ static void client_run()
 		/* be nice */
 		if(config.dbg_stress)
 			thread_sleep(5);
-		else if(config.cl_cpu_throttle || !gfx_window_active())
+		else if(config.cl_cpu_throttle || !Graphics()->WindowActive())
 			thread_sleep(1);
 			
 		if(config.dbg_hitch)
@@ -1832,7 +1853,7 @@ static void client_run()
 					frames/(float)(reportinterval/time_freq()),
 					1.0f/frametime_high,
 					1.0f/frametime_low,
-					netclient_state(net));
+					m_NetClient.State());
 			}
 			frametime_low = 1;
 			frametime_high = 0;
@@ -1857,10 +1878,15 @@ static void client_run()
 	modc_shutdown();
 	client_disconnect();
 
-	gfx_shutdown();
+	m_pGraphics->Shutdown();
 	snd_shutdown();
 }
 
+void gfx_swap()
+{
+	m_pGraphics->Swap();
+}
+
 static void con_connect(void *result, void *user_data)
 {
 	str_copy(cmd_connect, console_arg_string(result, 0), sizeof(cmd_connect));
@@ -1886,7 +1912,7 @@ static void con_ping(void *result, void *user_data)
 
 static void con_screenshot(void *result, void *user_data)
 {
-	gfx_screenshot();
+	Graphics()->TakeScreenshot();
 }
 
 static void con_rcon(void *result, void *user_data)
@@ -1911,7 +1937,7 @@ const char *client_demoplayer_play(const char *filename)
 	int crc;
 	const char *error;
 	client_disconnect();
-	netclient_error_string_reset(net);
+	m_NetClient.ResetErrorString();
 	
 	/* try to start playback */
 	demorec_playback_registercallbacks(client_democallback_snapshot, client_democallback_message);
@@ -1939,15 +1965,15 @@ const char *client_demoplayer_play(const char *filename)
 	snapshots[SNAP_CURRENT] = &demorec_snapshotholders[SNAP_CURRENT];
 	snapshots[SNAP_PREV] = &demorec_snapshotholders[SNAP_PREV];
 	
-	snapshots[SNAP_CURRENT]->snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_CURRENT][0];
-	snapshots[SNAP_CURRENT]->alt_snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_CURRENT][1];
-	snapshots[SNAP_CURRENT]->snap_size = 0;
-	snapshots[SNAP_CURRENT]->tick = -1;
+	snapshots[SNAP_CURRENT]->m_pSnap = (CSnapshot *)demorec_snapshotdata[SNAP_CURRENT][0];
+	snapshots[SNAP_CURRENT]->m_pAltSnap = (CSnapshot *)demorec_snapshotdata[SNAP_CURRENT][1];
+	snapshots[SNAP_CURRENT]->m_SnapSize = 0;
+	snapshots[SNAP_CURRENT]->m_Tick = -1;
 	
-	snapshots[SNAP_PREV]->snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_PREV][0];
-	snapshots[SNAP_PREV]->alt_snap = (SNAPSHOT *)demorec_snapshotdata[SNAP_PREV][1];
-	snapshots[SNAP_PREV]->snap_size = 0;
-	snapshots[SNAP_PREV]->tick = -1;
+	snapshots[SNAP_PREV]->m_pSnap = (CSnapshot *)demorec_snapshotdata[SNAP_PREV][0];
+	snapshots[SNAP_PREV]->m_pAltSnap = (CSnapshot *)demorec_snapshotdata[SNAP_PREV][1];
+	snapshots[SNAP_PREV]->m_SnapSize = 0;
+	snapshots[SNAP_PREV]->m_Tick = -1;
 
 	/* enter demo playback state */
 	client_set_state(CLIENTSTATE_DEMOPLAYBACK);
diff --git a/src/engine/client/ec_gfx.c b/src/engine/client/ec_gfx.c
deleted file mode 100644
index 1ea9f407..00000000
--- a/src/engine/client/ec_gfx.c
+++ /dev/null
@@ -1,1020 +0,0 @@
-/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
-
-#include <base/detect.h>
-
-#include "SDL.h"
-
-#ifdef CONF_FAMILY_WINDOWS
-	#define WIN32_LEAN_AND_MEAN
-	#include <windows.h>
-#endif
-
-#ifdef CONF_PLATFORM_MACOSX
-	#include <OpenGL/gl.h>
-	#include <OpenGL/glu.h>
-#else
-	#include <GL/gl.h>
-	#include <GL/glu.h>
-#endif
-
-#include <base/system.h>
-#include <engine/external/pnglite/pnglite.h>
-
-#include <engine/e_client_interface.h>
-#include <engine/e_engine.h>
-#include <engine/e_config.h>
-#include <engine/e_keys.h>
-
-#include <string.h>
-#include <stdio.h>
-#include <math.h>
-
-/* compressed textures */
-#define GL_COMPRESSED_RGB_ARB 0x84ED
-#define GL_COMPRESSED_RGBA_ARB 0x84EE
-#define GL_COMPRESSED_ALPHA_ARB 0x84E9
-
-#define TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
-
-enum
-{
-	DRAWING_QUADS=1,
-	DRAWING_LINES=2
-};
-
-/* */
-typedef struct { float x, y, z; } VEC3;
-typedef struct { float u, v; } TEXCOORD;
-typedef struct { float r, g, b, a; } COLOR;
-
-typedef struct
-{
-	VEC3 pos;
-	TEXCOORD tex;
-	COLOR color;
-} VERTEX;
-
-const int vertex_buffer_size = 32*1024;
-static VERTEX *vertices = 0;
-static int num_vertices = 0;
-
-static int no_gfx = 0;
-
-static COLOR color[4];
-static TEXCOORD texture[4];
-
-static int do_screenshot = 0;
-static int render_enable = 1;
-
-static int screen_width = -1;
-static int screen_height = -1;
-static float rotation = 0;
-static int drawing = 0;
-
-static float screen_x0 = 0;
-static float screen_y0 = 0;
-static float screen_x1 = 0;
-static float screen_y1 = 0;
-
-static int invalid_texture = 0;
-
-typedef struct
-{
-	GLuint tex;
-	int memsize;
-	int flags;
-	int next;
-} TEXTURE;
-
-enum
-{
-	MAX_TEXTURES = 1024*4
-};
-
-static TEXTURE textures[MAX_TEXTURES];
-static int first_free_texture;
-static int memory_usage = 0;
-
-static SDL_Surface *screen_surface;
-
-static const unsigned char null_texture_data[] = {
-	0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
-	0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
-	0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
-	0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
-};
-
-static void flush()
-{
-	if(num_vertices == 0)
-		return;
-		
-	if(no_gfx)
-	{
-		num_vertices = 0;
-		return;
-	}
-	
-		
-	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-
-	glVertexPointer(3, GL_FLOAT,
-			sizeof(VERTEX),
-			(char*)vertices);
-	glTexCoordPointer(2, GL_FLOAT,
-			sizeof(VERTEX),
-			(char*)vertices + sizeof(float)*3);
-	glColorPointer(4, GL_FLOAT,
-			sizeof(VERTEX),
-			(char*)vertices + sizeof(float)*5);
-	glEnableClientState(GL_VERTEX_ARRAY);
-	glEnableClientState(GL_TEXTURE_COORD_ARRAY);
-	glEnableClientState(GL_COLOR_ARRAY);
-	
-	if(render_enable)
-	{
-		if(drawing == DRAWING_QUADS)
-			glDrawArrays(GL_QUADS, 0, num_vertices);
-		else if(drawing == DRAWING_LINES)
-			glDrawArrays(GL_LINES, 0, num_vertices);
-	}
-	
-	/* Reset pointer */
-	num_vertices = 0;
-}
-
-static void add_vertices(int count)
-{
-	num_vertices += count;
-	if((num_vertices + count) >= vertex_buffer_size)
-		flush();
-}
-
-static int try_init()
-{
-	const SDL_VideoInfo *info;
-	int flags = SDL_OPENGL;
-	
-	screen_width = config.gfx_screen_width;
-	screen_height = config.gfx_screen_height;
-
-	info = SDL_GetVideoInfo();
-
-	/* set flags */
-	flags  = SDL_OPENGL;
-	flags |= SDL_GL_DOUBLEBUFFER;
-	flags |= SDL_HWPALETTE;
-	if(config.dbg_resizable)
-		flags |= SDL_RESIZABLE;
-
-	if(info->hw_available)
-		flags |= SDL_HWSURFACE;
-	else
-		flags |= SDL_SWSURFACE;
-
-	if(info->blit_hw)
-		flags |= SDL_HWACCEL;
-
-	if(config.gfx_fullscreen)
-		flags |= SDL_FULLSCREEN;
-
-	/* set gl attributes */
-	if(config.gfx_fsaa_samples)
-	{
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config.gfx_fsaa_samples);
-	}
-	else
-	{
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
-		SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
-	}
-
-	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, config.gfx_vsync);
-
-	/* set caption */
-	SDL_WM_SetCaption("Teeworlds", "Teeworlds");
-	
-	/* create window */
-	screen_surface = SDL_SetVideoMode(screen_width, screen_height, 0, flags);
-	if(screen_surface == NULL)
-	{
-		dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
-		return -1;
-	}
-	
-	return 0;
-}
-
-void gfx_font_init();
-
-static int gfx_init_window()
-{
-	if(try_init() == 0)
-		return 0;
-	
-	/* try disabling fsaa */
-	while(config.gfx_fsaa_samples)
-	{
-		config.gfx_fsaa_samples--;
-		
-		if(config.gfx_fsaa_samples)
-			dbg_msg("gfx", "lowering FSAA to %d and trying again", config.gfx_fsaa_samples);
-		else
-			dbg_msg("gfx", "disabling FSAA and trying again");
-
-		if(try_init() == 0)
-			return 0;
-	}
-
-	/* try lowering the resolution */
-	if(config.gfx_screen_width != 640 || config.gfx_screen_height != 480)
-	{
-		dbg_msg("gfx", "setting resolution to 640x480 and trying again");
-		config.gfx_screen_width = 640;
-		config.gfx_screen_height = 480;
-
-		if(try_init() == 0)
-			return 0;
-	}
-
-	dbg_msg("gfx", "out of ideas. failed to init graphics");
-					
-	return -1;		
-}
-
-int gfx_init()
-{
-	int i;
-
-	if(config.dbg_stress)
-		no_gfx = 1;
-
-	{
-		int systems = 0;
-		
-		if(!no_gfx)
-			systems |= SDL_INIT_VIDEO;
-			
-		if(config.snd_enable)
-			systems |= SDL_INIT_AUDIO;
-
-		if(config.cl_eventthread)
-			systems |= SDL_INIT_EVENTTHREAD;
-		
-		if(SDL_Init(systems) < 0)
-		{
-			dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
-			return -1;
-		}
-	}
-	
-    atexit(SDL_Quit);
-
-	if(!no_gfx)
-	{
-		#ifdef CONF_FAMILY_WINDOWS
-			if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED"))
-				putenv("SDL_VIDEO_WINDOW_POS=8,27");
-		#endif
-		
-		if(gfx_init_window() != 0)
-			return -1;
-	}
-	
-	/* Init vertices */
-	if (vertices)
-		mem_free(vertices);
-	vertices = (VERTEX*)mem_alloc(sizeof(VERTEX) * vertex_buffer_size, 1);
-	num_vertices = 0;
-
-
-	/*
-	dbg_msg("gfx", "OpenGL version %d.%d.%d", context.version_major(),
-											  context.version_minor(),
-											  context.version_rev());*/
-
-	
-	/* Set all z to -5.0f */
-	for (i = 0; i < vertex_buffer_size; i++)
-		vertices[i].pos.z = -5.0f;
-
-	/* init textures */
-	first_free_texture = 0;
-	for(i = 0; i < MAX_TEXTURES; i++)
-		textures[i].next = i+1;
-	textures[MAX_TEXTURES-1].next = -1;
-	
-	if(!no_gfx)
-	{
-		SDL_ShowCursor(0);
-		gfx_mapscreen(0,0,config.gfx_screen_width, config.gfx_screen_height);
-
-		/* set some default settings */	
-		glEnable(GL_BLEND);
-		glDisable(GL_CULL_FACE);
-		glDisable(GL_DEPTH_TEST);
-		glMatrixMode(GL_MODELVIEW);
-		glLoadIdentity();
-		
-		glAlphaFunc(GL_GREATER, 0);
-		glEnable(GL_ALPHA_TEST);
-		glDepthMask(0);
-
-		
-		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	}
-
-	/* init input */
-	inp_init();
-	
-	/* create null texture, will get id=0 */
-	invalid_texture = gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data,IMG_RGBA,TEXLOAD_NORESAMPLE);
-	dbg_msg("", "invalid texture id: %d %d", invalid_texture, textures[invalid_texture].tex);
-
-
-	/* font init */
-	gfx_font_init();
-	/* perform some tests */
-	/* pixeltest_dotesting(); */
-	
-	/*if(config.dbg_stress)
-		gfx_minimize();*/
-
-	return 0;
-}
-
-float gfx_screenaspect()
-{
-    return gfx_screenwidth()/(float)gfx_screenheight();
-}
-
-int gfx_window_active()
-{
-	return SDL_GetAppState()&SDL_APPINPUTFOCUS;
-}
-
-int gfx_window_open()
-{
-	return SDL_GetAppState()&SDL_APPACTIVE;
-}
-
-VIDEO_MODE fakemodes[] = {
-	{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
-	{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
-	{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
-	{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
-	{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
-	{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
-	{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
-	{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
-	{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
-	{2048,1536,8,8,8},
-		
-	{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
-	{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
-	{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
-	{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
-	{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
-	{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
-	{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
-	{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
-	{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
-	{2048,1536,5,6,5}
-};
-
-int gfx_get_video_modes(VIDEO_MODE *list, int maxcount)
-{
-	int num_modes = sizeof(fakemodes)/sizeof(VIDEO_MODE);
-	SDL_Rect **modes;
-
-	if(config.gfx_display_all_modes)
-	{
-		int count = sizeof(fakemodes)/sizeof(VIDEO_MODE);
-		mem_copy(list, fakemodes, sizeof(fakemodes));
-		if(maxcount < count)
-			count = maxcount;
-		return count;
-	}
-	
-	/* TODO: fix this code on osx or windows */
-		
-	modes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN);
-	if(modes == NULL)
-	{
-		/* no modes */
-		num_modes = 0;
-	}
-	else if(modes == (SDL_Rect**)-1)
-	{
-		/* all modes */
-	}
-	else
-	{
-		int i;
-		num_modes = 0;
-		for(i = 0; modes[i]; ++i)
-		{
-			if(num_modes == maxcount)
-				break;
-			list[num_modes].width = modes[i]->w;
-			list[num_modes].height = modes[i]->h;
-			list[num_modes].red = 8;
-			list[num_modes].green = 8;
-			list[num_modes].blue = 8;
-			num_modes++;
-		}
-	}
-	
-	return num_modes;
-}
-
-int gfx_unload_texture(int index)
-{
-	if(index == invalid_texture)
-		return 0;
-		
-	if(index < 0)
-		return 0;
-		
-	glDeleteTextures(1, &textures[index].tex);
-	textures[index].next = first_free_texture;
-	memory_usage -= textures[index].memsize;
-	first_free_texture = index;
-	return 0;
-}
-
-void gfx_blend_none()
-{
-	if(no_gfx) return;
-	glDisable(GL_BLEND);
-}
-
-void gfx_blend_normal()
-{
-	if(no_gfx) return;
-	glEnable(GL_BLEND);
-	glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
-}
-
-void gfx_blend_additive()
-{
-	if(no_gfx) return;
-	glEnable(GL_BLEND);
-	glBlendFunc(GL_SRC_ALPHA, GL_ONE);
-}
-
-int gfx_memory_usage() { return memory_usage; }
-
-static unsigned char sample(int w, int h, const unsigned char *data, int u, int v, int offset)
-{
-	return (data[(v*w+u)*4+offset]+
-	data[(v*w+u+1)*4+offset]+
-	data[((v+1)*w+u)*4+offset]+
-	data[((v+1)*w+u+1)*4+offset])/4;
-}
-
-int gfx_load_texture_raw(int w, int h, int format, const void *data, int store_format, int flags)
-{
-	int mipmap = 1;
-	unsigned char *texdata = (unsigned char *)data;
-	unsigned char *tmpdata = 0;
-	int oglformat = 0;
-	int store_oglformat = 0;
-	int tex = 0;
-	
-	/* don't waste memory on texture if we are stress testing */
-	if(config.dbg_stress || no_gfx)
-		return 	invalid_texture;
-	
-	/* grab texture */
-	tex = first_free_texture;
-	first_free_texture = textures[tex].next;
-	textures[tex].next = -1;
-	
-	/* resample if needed */
-	if(!(flags&TEXLOAD_NORESAMPLE) && config.gfx_texture_quality==0)
-	{
-		if(w > 16 && h > 16 && format == IMG_RGBA)
-		{
-			unsigned char *tmpdata;
-			int c = 0;
-			int x, y;
-
-			tmpdata = (unsigned char *)mem_alloc(w*h*4, 1);
-
-			w/=2;
-			h/=2;
-
-			for(y = 0; y < h; y++)
-				for(x = 0; x < w; x++, c++)
-				{
-					tmpdata[c*4] = sample(w*2, h*2, texdata, x*2,y*2, 0);
-					tmpdata[c*4+1] = sample(w*2, h*2, texdata, x*2,y*2, 1);
-					tmpdata[c*4+2] = sample(w*2, h*2, texdata, x*2,y*2, 2);
-					tmpdata[c*4+3] = sample(w*2, h*2, texdata, x*2,y*2, 3);
-				}
-			texdata = tmpdata;
-		}
-	}
-	
-	oglformat = GL_RGBA;
-	if(format == IMG_RGB)
-		oglformat = GL_RGB;
-	else if(format == IMG_ALPHA)
-		oglformat = GL_ALPHA;
-	
-	/* upload texture */
-	if(config.gfx_texture_compression)
-	{
-		store_oglformat = GL_COMPRESSED_RGBA_ARB;
-		if(store_format == IMG_RGB)
-			store_oglformat = GL_COMPRESSED_RGB_ARB;
-		else if(store_format == IMG_ALPHA)
-			store_oglformat = GL_COMPRESSED_ALPHA_ARB;
-	}
-	else
-	{
-		store_oglformat = GL_RGBA;
-		if(store_format == IMG_RGB)
-			store_oglformat = GL_RGB;
-		else if(store_format == IMG_ALPHA)
-			store_oglformat = GL_ALPHA;
-	}
-		
-	glGenTextures(1, &textures[tex].tex);
-	glBindTexture(GL_TEXTURE_2D, textures[tex].tex);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
-	glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
-	gluBuild2DMipmaps(GL_TEXTURE_2D, store_oglformat, w, h, oglformat, GL_UNSIGNED_BYTE, texdata);
-	
-	/* calculate memory usage */
-	{
-		int pixel_size = 4;
-		if(store_format == IMG_RGB)
-			pixel_size = 3;
-		else if(store_format == IMG_ALPHA)
-			pixel_size = 1;
-
-		textures[tex].memsize = w*h*pixel_size;
-		if(mipmap)
-		{
-			while(w > 2 && h > 2)
-			{
-				w>>=1;
-				h>>=1;
-				textures[tex].memsize += w*h*pixel_size;
-			}
-		}
-	}
-	
-	memory_usage += textures[tex].memsize;
-	mem_free(tmpdata);
-	return tex;
-}
-
-/* simple uncompressed RGBA loaders */
-int gfx_load_texture(const char *filename, int store_format, int flags)
-{
-	int l = strlen(filename);
-	int id;
-	IMAGE_INFO img;
-	
-	if(l < 3)
-		return -1;
-	if(gfx_load_png(&img, filename))
-	{
-		if (store_format == IMG_AUTO)
-			store_format = img.format;
-
-		id = gfx_load_texture_raw(img.width, img.height, img.format, img.data, store_format, flags);
-		mem_free(img.data);
-		return id;
-	}
-	
-	return invalid_texture;
-}
-
-int gfx_load_png(IMAGE_INFO *img, const char *filename)
-{
-	char completefilename[512];
-	unsigned char *buffer;
-	png_t png;
-	
-	/* open file for reading */
-	png_init(0,0);
-
-	engine_getpath(completefilename, sizeof(completefilename), filename, IOFLAG_READ);
-	
-	if(png_open_file(&png, completefilename) != PNG_NO_ERROR)
-	{
-		dbg_msg("game/png", "failed to open file. filename='%s'", completefilename);
-		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'", completefilename);
-		png_close_file(&png);
-        return 0;
-	}
-		
-	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 (vertices)
-		mem_free(vertices);
-
-	/* TODO: SDL, is this correct? */
-	SDL_Quit();
-}
-
-void gfx_screenshot()
-{
-	do_screenshot = 1;
-}
-
-
-extern int text_render_codepaths_usage[5];
-
-void gfx_swap()
-{
-	/*dbg_msg("", "%d %d %d %d %d",
-		text_render_codepaths_usage[0],
-		text_render_codepaths_usage[1],
-		text_render_codepaths_usage[2],
-		text_render_codepaths_usage[3],
-		text_render_codepaths_usage[4]);
-
-	text_render_codepaths_usage[0] = 0;
-	text_render_codepaths_usage[1] = 0;
-	text_render_codepaths_usage[2] = 0;
-	text_render_codepaths_usage[3] = 0;
-	text_render_codepaths_usage[4] = 0;*/
-
-	if(do_screenshot)
-	{
-		/* find filename */
-		char filename[128];
-		static int index = 1;
-
-		for(; index < 1000; index++)
-		{
-			IOHANDLE io;
-			str_format(filename, sizeof(filename), "screenshots/screenshot%04d.png", index);
-			io = engine_openfile(filename, IOFLAG_READ);
-			if(io)
-				io_close(io);
-			else
-				break;
-		}
-
-		gfx_screenshot_direct(filename);
-	
-		do_screenshot = 0;	
-	}
-	
-	{
-		static PERFORMACE_INFO pscope = {"glfwSwapBuffers", 0};
-		perf_start(&pscope);
-		SDL_GL_SwapBuffers();
-		perf_end();
-	}
-	
-	if(render_enable && config.gfx_finish)
-		glFinish();
-}
-
-void gfx_screenshot_direct(const char *filename)
-{
-	/* fetch image data */
-	int y;
-	int w = screen_width;
-	int h = screen_height;
-	unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*4, 1);
-	unsigned char *temp_row = pixel_data+w*h*4;
-	glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data);
-	
-	/* flip the pixel because opengl works from bottom left corner */
-	for(y = 0; y < h/2; y++)
-	{
-		mem_copy(temp_row, pixel_data+y*w*4, w*4);
-		mem_copy(pixel_data+y*w*4, pixel_data+(h-y-1)*w*4, w*4);
-		mem_copy(pixel_data+(h-y-1)*w*4, temp_row,w*4);
-	}
-	
-	/* find filename */
-	{
-		char wholepath[1024];
-		png_t png;
-
-		engine_savepath(filename, wholepath, sizeof(wholepath));
-	
-		/* save png */
-		dbg_msg("client", "saved screenshot to '%s'", wholepath);
-		png_open_file_write(&png, wholepath);
-		png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pixel_data);
-		png_close_file(&png);
-	}
-
-	/* clean up */
-	mem_free(pixel_data);
-}
-
-int gfx_screenwidth()
-{
-	return screen_width;
-}
-
-int gfx_screenheight()
-{
-	return screen_height;
-}
-
-void gfx_texture_set(int slot)
-{
-	dbg_assert(drawing == 0, "called gfx_texture_set within begin");
-	if(no_gfx) return;
-	if(slot == -1)
-	{
-		glDisable(GL_TEXTURE_2D);
-	}
-	else
-	{
-		glEnable(GL_TEXTURE_2D);
-		glBindTexture(GL_TEXTURE_2D, textures[slot].tex);
-	}
-}
-
-void gfx_clear(float r, float g, float b)
-{
-	if(no_gfx) return;
-	glClearColor(r,g,b,0.0f);
-	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
-}
-
-void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y)
-{
-	screen_x0 = tl_x;
-	screen_y0 = tl_y;
-	screen_x1 = br_x;
-	screen_y1 = br_y;
-	if(no_gfx) return;
-	glMatrixMode(GL_PROJECTION);
-	glLoadIdentity();
-	glOrtho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f);
-}
-
-void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y)
-{
-	*tl_x = screen_x0;
-	*tl_y = screen_y0;
-	*br_x = screen_x1;
-	*br_y = screen_y1;
-}
-
-void gfx_quads_begin()
-{
-	dbg_assert(drawing == 0, "called quads_begin twice");
-	drawing = DRAWING_QUADS;
-	
-	gfx_quads_setsubset(0,0,1,1);
-	gfx_quads_setrotation(0);
-	gfx_setcolor(1,1,1,1);
-}
-
-void gfx_quads_end()
-{
-	dbg_assert(drawing == DRAWING_QUADS, "called quads_end without begin");
-	flush();
-	drawing = 0;
-}
-
-
-void gfx_quads_setrotation(float angle)
-{
-	dbg_assert(drawing == DRAWING_QUADS, "called gfx_quads_setrotation without begin");
-	rotation = angle;
-}
-
-void gfx_setcolorvertex(int i, float r, float g, float b, float a)
-{
-	dbg_assert(drawing != 0, "called gfx_quads_setcolorvertex without begin");
-	color[i].r = r;
-	color[i].g = g;
-	color[i].b = b;
-	color[i].a = a;
-}
-
-void gfx_setcolor(float r, float g, float b, float a)
-{
-	dbg_assert(drawing != 0, "called gfx_quads_setcolor without begin");
-	gfx_setcolorvertex(0, r, g, b, a);
-	gfx_setcolorvertex(1, r, g, b, a);
-	gfx_setcolorvertex(2, r, g, b, a);
-	gfx_setcolorvertex(3, r, g, b, a);
-}
-
-void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v)
-{
-	dbg_assert(drawing == DRAWING_QUADS, "called gfx_quads_setsubset without begin");
-
-	texture[0].u = tl_u;	texture[1].u = br_u;
-	texture[0].v = tl_v;	texture[1].v = tl_v;
-
-	texture[3].u = tl_u;	texture[2].u = br_u;
-	texture[3].v = br_v;	texture[2].v = br_v;
-}
-
-void gfx_quads_setsubset_free(
-	float x0, float y0, float x1, float y1,
-	float x2, float y2, float x3, float y3)
-{
-	texture[0].u = x0; texture[0].v = y0;
-	texture[1].u = x1; texture[1].v = y1;
-	texture[2].u = x2; texture[2].v = y2;
-	texture[3].u = x3; texture[3].v = y3;
-}
-
-
-static void rotate(VEC3 *center, VEC3 *point)
-{
-	float x = point->x - center->x;
-	float y = point->y - center->y;
-	point->x = x * cosf(rotation) - y * sinf(rotation) + center->x;
-	point->y = x * sinf(rotation) + y * cosf(rotation) + center->y;
-}
-
-void gfx_quads_draw(float x, float y, float w, float h)
-{
-	gfx_quads_drawTL(x-w/2, y-h/2,w,h);
-}
-
-void gfx_quads_drawTL(float x, float y, float width, float height)
-{
-	VEC3 center;
-
-	dbg_assert(drawing == DRAWING_QUADS, "called quads_draw without begin");
-
-	center.x = x + width/2;
-	center.y = y + height/2;
-	center.z = 0;
-	
-	vertices[num_vertices].pos.x = x;
-	vertices[num_vertices].pos.y = y;
-	vertices[num_vertices].tex = texture[0];
-	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 = texture[1];
-	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 = texture[2];
-	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 = texture[3];
-	vertices[num_vertices + 3].color = color[3];
-	rotate(&center, &vertices[num_vertices + 3].pos);
-	
-	add_vertices(4);
-}
-
-void gfx_quads_draw_freeform(
-	float x0, float y0, float x1, float y1,
-	float x2, float y2, float x3, float y3)
-{
-	dbg_assert(drawing == DRAWING_QUADS, "called quads_draw_freeform without begin");
-	
-	vertices[num_vertices].pos.x = x0;
-	vertices[num_vertices].pos.y = y0;
-	vertices[num_vertices].tex = texture[0];
-	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 = texture[1];
-	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 = texture[3];
-	vertices[num_vertices + 2].color = color[3];
-
-	vertices[num_vertices + 3].pos.x = x2;
-	vertices[num_vertices + 3].pos.y = y2;
-	vertices[num_vertices + 3].tex = texture[2];
-	vertices[num_vertices + 3].color = color[2];
-	
-	add_vertices(4);
-}
-
-void gfx_quads_text(float x, float y, float size, float r, float g, float b, float a, const char *text)
-{
-	float startx = x;
-
-	gfx_quads_begin();
-	gfx_setcolor(r,g,b,a);
-
-	while(*text)
-	{
-		char c = *text;
-		text++;
-		
-		if(c == '\n')
-		{
-			x = startx;
-			y += size;
-		}
-		else
-		{
-			gfx_quads_setsubset(
-				(c%16)/16.0f,
-				(c/16)/16.0f,
-				(c%16)/16.0f+1.0f/16.0f,
-				(c/16)/16.0f+1.0f/16.0f);
-			
-			gfx_quads_drawTL(x,y,size,size);
-			x += size/2;
-		}
-	}
-	
-	gfx_quads_end();
-}
-
-void gfx_lines_begin()
-{
-	dbg_assert(drawing == 0, "called begin twice");
-	drawing = DRAWING_LINES;
-	gfx_setcolor(1,1,1,1);
-}
-
-void gfx_lines_end()
-{
-	dbg_assert(drawing == DRAWING_LINES, "called end without begin");
-	flush();
-	drawing = 0;
-}
-
-void gfx_lines_draw(float x0, float y0, float x1, float y1)
-{
-	dbg_assert(drawing == DRAWING_LINES, "called draw without begin");
-	
-	vertices[num_vertices].pos.x = x0;
-	vertices[num_vertices].pos.y = y0;
-	vertices[num_vertices].tex = texture[0];
-	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 = texture[1];
-	vertices[num_vertices + 1].color = color[1];
-	
-	add_vertices(2);
-}
-
-void gfx_clip_enable(int x, int y, int w, int h)
-{
-	if(no_gfx) return;
-	glScissor(x, gfx_screenheight()-(y+h), w, h);
-	glEnable(GL_SCISSOR_TEST);
-}
-
-void gfx_clip_disable()
-{
-	if(no_gfx) return;
-	glDisable(GL_SCISSOR_TEST);
-}
-
-void gfx_minimize()
-{
-	SDL_WM_IconifyWindow();
-}
-
-void gfx_maximize()
-{
-	/* TODO: SDL */
-}
diff --git a/src/engine/client/ec_gfx.cpp b/src/engine/client/ec_gfx.cpp
new file mode 100644
index 00000000..5632581a
--- /dev/null
+++ b/src/engine/client/ec_gfx.cpp
@@ -0,0 +1,992 @@
+/* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
+
+#include <base/detect.h>
+
+#include "SDL.h"
+
+#ifdef CONF_FAMILY_WINDOWS
+	#define WIN32_LEAN_AND_MEAN
+	#include <windows.h>
+#endif
+
+#ifdef CONF_PLATFORM_MACOSX
+	#include <OpenGL/gl.h>
+	#include <OpenGL/glu.h>
+#else
+	#include <GL/gl.h>
+	#include <GL/glu.h>
+#endif
+
+#include <base/system.h>
+#include <engine/external/pnglite/pnglite.h>
+
+#include <engine/e_client_interface.h>
+#include <engine/e_engine.h>
+#include <engine/e_config.h>
+#include <engine/e_keys.h>
+
+#include <string.h>
+#include <stdio.h>
+#include <math.h>
+
+/* compressed textures */
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
+#define GL_COMPRESSED_ALPHA_ARB 0x84E9
+
+#define TEXTURE_MAX_ANISOTROPY_EXT 0x84FE
+
+
+void gfx_font_init();
+
+VIDEO_MODE fakemodes[] = {
+	{320,240,8,8,8}, {400,300,8,8,8}, {640,480,8,8,8},
+	{720,400,8,8,8}, {768,576,8,8,8}, {800,600,8,8,8},
+	{1024,600,8,8,8}, {1024,768,8,8,8}, {1152,864,8,8,8},
+	{1280,768,8,8,8}, {1280,800,8,8,8}, {1280,960,8,8,8},
+	{1280,1024,8,8,8}, {1368,768,8,8,8}, {1400,1050,8,8,8},
+	{1440,900,8,8,8}, {1440,1050,8,8,8}, {1600,1000,8,8,8},
+	{1600,1200,8,8,8}, {1680,1050,8,8,8}, {1792,1344,8,8,8},
+	{1800,1440,8,8,8}, {1856,1392,8,8,8}, {1920,1080,8,8,8},
+	{1920,1200,8,8,8}, {1920,1440,8,8,8}, {1920,2400,8,8,8},
+	{2048,1536,8,8,8},
+		
+	{320,240,5,6,5}, {400,300,5,6,5}, {640,480,5,6,5},
+	{720,400,5,6,5}, {768,576,5,6,5}, {800,600,5,6,5},
+	{1024,600,5,6,5}, {1024,768,5,6,5}, {1152,864,5,6,5},
+	{1280,768,5,6,5}, {1280,800,5,6,5}, {1280,960,5,6,5},
+	{1280,1024,5,6,5}, {1368,768,5,6,5}, {1400,1050,5,6,5},
+	{1440,900,5,6,5}, {1440,1050,5,6,5}, {1600,1000,5,6,5},
+	{1600,1200,5,6,5}, {1680,1050,5,6,5}, {1792,1344,5,6,5},
+	{1800,1440,5,6,5}, {1856,1392,5,6,5}, {1920,1080,5,6,5},
+	{1920,1200,5,6,5}, {1920,1440,5,6,5}, {1920,2400,5,6,5},
+	{2048,1536,5,6,5}
+};
+
+int gfx_get_video_modes(VIDEO_MODE *list, int maxcount)
+{
+	int num_modes = sizeof(fakemodes)/sizeof(VIDEO_MODE);
+	SDL_Rect **modes;
+
+	if(config.gfx_display_all_modes)
+	{
+		int count = sizeof(fakemodes)/sizeof(VIDEO_MODE);
+		mem_copy(list, fakemodes, sizeof(fakemodes));
+		if(maxcount < count)
+			count = maxcount;
+		return count;
+	}
+	
+	/* TODO: fix this code on osx or windows */
+		
+	modes = SDL_ListModes(NULL, SDL_OPENGL|SDL_GL_DOUBLEBUFFER|SDL_FULLSCREEN);
+	if(modes == NULL)
+	{
+		/* no modes */
+		num_modes = 0;
+	}
+	else if(modes == (SDL_Rect**)-1)
+	{
+		/* all modes */
+	}
+	else
+	{
+		int i;
+		num_modes = 0;
+		for(i = 0; modes[i]; ++i)
+		{
+			if(num_modes == maxcount)
+				break;
+			list[num_modes].width = modes[i]->w;
+			list[num_modes].height = modes[i]->h;
+			list[num_modes].red = 8;
+			list[num_modes].green = 8;
+			list[num_modes].blue = 8;
+			num_modes++;
+		}
+	}
+	
+	return num_modes;
+}
+
+
+#include "graphics.h"
+
+class CGraphics_OpenGL : public IEngineGraphics
+{
+protected:
+	/* */
+	typedef struct { float x, y, z; } CPoint;
+	typedef struct { float u, v; } CTexCoord;
+	typedef struct { float r, g, b, a; } CColor;
+
+	typedef struct
+	{
+		CPoint m_Pos;
+		CTexCoord m_Tex;
+		CColor m_Color;
+	} CVertex;
+	
+	enum
+	{
+		MAX_VERTICES = 32*1024,
+		MAX_TEXTURES = 1024*4,
+		
+		DRAWING_QUADS=1,
+		DRAWING_LINES=2		
+	};
+
+	CVertex m_aVertices[MAX_VERTICES];
+	int m_NumVertices;
+
+	CColor m_aColor[4];
+	CTexCoord m_aTexture[4];
+
+	bool m_RenderEnable;
+
+	float m_Rotation;
+	int m_Drawing;
+	bool m_DoScreenshot;
+
+	float m_ScreenX0;
+	float m_ScreenY0;
+	float m_ScreenX1;
+	float m_ScreenY1;
+
+	int m_InvalidTexture;
+
+	struct CTexture
+	{
+		GLuint tex;
+		int memsize;
+		int flags;
+		int next;
+	};
+
+	enum
+	{
+		
+	};
+
+	CTexture m_aTextures[MAX_TEXTURES];
+	int m_FirstFreeTexture;
+	int m_TextureMemoryUsage;
+
+
+	void Flush()
+	{
+		if(m_NumVertices == 0)
+			return;
+			
+		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+
+		glVertexPointer(3, GL_FLOAT,
+				sizeof(CVertex),
+				(char*)m_aVertices);
+		glTexCoordPointer(2, GL_FLOAT,
+				sizeof(CVertex),
+				(char*)m_aVertices + sizeof(float)*3);
+		glColorPointer(4, GL_FLOAT,
+				sizeof(CVertex),
+				(char*)m_aVertices + sizeof(float)*5);
+		glEnableClientState(GL_VERTEX_ARRAY);
+		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
+		glEnableClientState(GL_COLOR_ARRAY);
+		
+		if(m_RenderEnable)
+		{
+			if(m_Drawing == DRAWING_QUADS)
+				glDrawArrays(GL_QUADS, 0, m_NumVertices);
+			else if(m_Drawing == DRAWING_LINES)
+				glDrawArrays(GL_LINES, 0, m_NumVertices);
+		}
+		
+		/* Reset pointer */
+		m_NumVertices = 0;
+	}
+
+	void AddVertices(int count)
+	{
+		m_NumVertices += count;
+		if((m_NumVertices + count) >= MAX_VERTICES)
+			Flush();
+	}
+	
+	void Rotate(CPoint *pCenter, CPoint *pPoint)
+	{
+		float x = pPoint->x - pCenter->x;
+		float y = pPoint->y - pCenter->y;
+		pPoint->x = x * cosf(m_Rotation) - y * sinf(m_Rotation) + pCenter->x;
+		pPoint->y = x * sinf(m_Rotation) + y * cosf(m_Rotation) + pCenter->y;
+	}
+	
+	
+
+
+	static unsigned char sample(int w, int h, const unsigned char *data, int u, int v, int offset)
+	{
+		return (data[(v*w+u)*4+offset]+
+		data[(v*w+u+1)*4+offset]+
+		data[((v+1)*w+u)*4+offset]+
+		data[((v+1)*w+u+1)*4+offset])/4;
+	}	
+public:
+	CGraphics_OpenGL()
+	{
+		m_NumVertices = 0;
+		
+		m_ScreenX0 = 0;
+		m_ScreenY0 = 0;
+		m_ScreenX1 = 0;
+		m_ScreenY1 = 0;
+		
+		m_ScreenWidth = -1;
+		m_ScreenHeight = -1;
+		
+		m_Rotation = 0;
+		m_Drawing = 0;
+		m_InvalidTexture = 0;
+		
+		m_TextureMemoryUsage = 0;
+		
+		m_RenderEnable = true;
+		m_DoScreenshot = false;
+	}
+	
+
+	virtual void ClipEnable(int x, int y, int w, int h)
+	{
+		//if(no_gfx) return;
+		glScissor(x, ScreenHeight()-(y+h), w, h);
+		glEnable(GL_SCISSOR_TEST);
+	}
+
+	virtual void ClipDisable()
+	{
+		//if(no_gfx) return;
+		glDisable(GL_SCISSOR_TEST);
+	}
+		
+
+	virtual void BlendNone()
+	{
+		glDisable(GL_BLEND);
+	}
+
+	virtual void BlendNormal()
+	{
+		glEnable(GL_BLEND);
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE_MINUS_SRC_ALPHA);
+	}
+
+	virtual void BlendAdditive()
+	{
+		glEnable(GL_BLEND);
+		glBlendFunc(GL_SRC_ALPHA, GL_ONE);
+	}
+
+	//int gfx_memory_usage() { return m_MemoryUsage; }	
+		
+	virtual void MapScreen(float tl_x, float tl_y, float br_x, float br_y)
+	{
+		m_ScreenX0 = tl_x;
+		m_ScreenY0 = tl_y;
+		m_ScreenX1 = br_x;
+		m_ScreenY1 = br_y;
+		glMatrixMode(GL_PROJECTION);
+		glLoadIdentity();
+		glOrtho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f);
+	}
+
+	virtual void GetScreen(float *tl_x, float *tl_y, float *br_x, float *br_y)
+	{
+		*tl_x = m_ScreenX0;
+		*tl_y = m_ScreenY0;
+		*br_x = m_ScreenX1;
+		*br_y = m_ScreenY1;
+	}
+
+	virtual void LinesBegin()
+	{
+		dbg_assert(m_Drawing == 0, "called begin twice");
+		m_Drawing = DRAWING_LINES;
+		SetColor(1,1,1,1);
+	}
+
+	virtual void LinesEnd()
+	{
+		dbg_assert(m_Drawing == DRAWING_LINES, "called end without begin");
+		Flush();
+		m_Drawing = 0;
+	}
+
+	virtual void LinesDraw(float x0, float y0, float x1, float y1)
+	{
+		dbg_assert(m_Drawing == DRAWING_LINES, "called draw without begin");
+		
+		m_aVertices[m_NumVertices].m_Pos.x = x0;
+		m_aVertices[m_NumVertices].m_Pos.y = y0;
+		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
+
+		m_aVertices[m_NumVertices + 1].m_Pos.x = x1;
+		m_aVertices[m_NumVertices + 1].m_Pos.y = y1;
+		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
+		
+		AddVertices(2);
+	}
+	
+
+	
+	virtual int UnloadTexture(int Index)
+	{
+		if(Index == m_InvalidTexture)
+			return 0;
+			
+		if(Index < 0)
+			return 0;
+			
+		glDeleteTextures(1, &m_aTextures[Index].tex);
+		m_aTextures[Index].next = m_FirstFreeTexture;
+		m_TextureMemoryUsage -= m_aTextures[Index].memsize;
+		m_FirstFreeTexture = Index;
+		return 0;
+	}
+
+
+	virtual int LoadTextureRaw(int Width, int Height, int Format, const void *pData, int StoreFormat, int Flags)
+	{
+		int mipmap = 1;
+		unsigned char *texdata = (unsigned char *)pData;
+		unsigned char *tmpdata = 0;
+		int oglformat = 0;
+		int store_oglformat = 0;
+		int tex = 0;
+		
+		/* don't waste memory on texture if we are stress testing */
+		if(config.dbg_stress)
+			return 	m_InvalidTexture;
+		
+		/* grab texture */
+		tex = m_FirstFreeTexture;
+		m_FirstFreeTexture = m_aTextures[tex].next;
+		m_aTextures[tex].next = -1;
+		
+		/* resample if needed */
+		if(!(Flags&TEXLOAD_NORESAMPLE) && config.gfx_texture_quality==0)
+		{
+			if(Width > 16 && Height > 16 && Format == IMG_RGBA)
+			{
+				unsigned char *tmpdata;
+				int c = 0;
+				int x, y;
+
+				tmpdata = (unsigned char *)mem_alloc(Width*Height*4, 1);
+
+				Width/=2;
+				Height/=2;
+
+				for(y = 0; y < Height; y++)
+					for(x = 0; x < Width; x++, c++)
+					{
+						tmpdata[c*4] = sample(Width*2, Height*2, texdata, x*2,y*2, 0);
+						tmpdata[c*4+1] = sample(Width*2, Height*2, texdata, x*2,y*2, 1);
+						tmpdata[c*4+2] = sample(Width*2, Height*2, texdata, x*2,y*2, 2);
+						tmpdata[c*4+3] = sample(Width*2, Height*2, texdata, x*2,y*2, 3);
+					}
+				texdata = tmpdata;
+			}
+		}
+		
+		oglformat = GL_RGBA;
+		if(Format == IMG_RGB)
+			oglformat = GL_RGB;
+		else if(Format == IMG_ALPHA)
+			oglformat = GL_ALPHA;
+		
+		/* upload texture */
+		if(config.gfx_texture_compression)
+		{
+			store_oglformat = GL_COMPRESSED_RGBA_ARB;
+			if(StoreFormat == IMG_RGB)
+				store_oglformat = GL_COMPRESSED_RGB_ARB;
+			else if(StoreFormat == IMG_ALPHA)
+				store_oglformat = GL_COMPRESSED_ALPHA_ARB;
+		}
+		else
+		{
+			store_oglformat = GL_RGBA;
+			if(StoreFormat == IMG_RGB)
+				store_oglformat = GL_RGB;
+			else if(StoreFormat == IMG_ALPHA)
+				store_oglformat = GL_ALPHA;
+		}
+			
+		glGenTextures(1, &m_aTextures[tex].tex);
+		glBindTexture(GL_TEXTURE_2D, m_aTextures[tex].tex);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
+		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_NEAREST);
+		gluBuild2DMipmaps(GL_TEXTURE_2D, store_oglformat, Width, Height, oglformat, GL_UNSIGNED_BYTE, texdata);
+		
+		/* calculate memory usage */
+		{
+			int pixel_size = 4;
+			if(StoreFormat == IMG_RGB)
+				pixel_size = 3;
+			else if(StoreFormat == IMG_ALPHA)
+				pixel_size = 1;
+
+			m_aTextures[tex].memsize = Width*Height*pixel_size;
+			if(mipmap)
+			{
+				while(Width > 2 && Height > 2)
+				{
+					Width>>=1;
+					Height>>=1;
+					m_aTextures[tex].memsize += Width*Height*pixel_size;
+				}
+			}
+		}
+		
+		m_TextureMemoryUsage += m_aTextures[tex].memsize;
+		mem_free(tmpdata);
+		return tex;
+	}
+
+	/* simple uncompressed RGBA loaders */
+	virtual int LoadTexture(const char *pFilename, int StoreFormat, int Flags)
+	{
+		int l = strlen(pFilename);
+		int id;
+		IMAGE_INFO img;
+		
+		if(l < 3)
+			return -1;
+		if(LoadPNG(&img, pFilename))
+		{
+			if (StoreFormat == IMG_AUTO)
+				StoreFormat = img.format;
+
+			id = LoadTextureRaw(img.width, img.height, img.format, img.data, StoreFormat, Flags);
+			mem_free(img.data);
+			return id;
+		}
+		
+		return m_InvalidTexture;
+	}
+
+	virtual int LoadPNG(IMAGE_INFO *pImg, const char *pFilename)
+	{
+		char aCompleteFilename[512];
+		unsigned char *pBuffer;
+		png_t png;
+		
+		/* open file for reading */
+		png_init(0,0);
+
+		engine_getpath(aCompleteFilename, sizeof(aCompleteFilename), pFilename, IOFLAG_READ);
+		
+		if(png_open_file(&png, aCompleteFilename) != PNG_NO_ERROR)
+		{
+			dbg_msg("game/png", "failed to open file. filename='%s'", aCompleteFilename);
+			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'", aCompleteFilename);
+			png_close_file(&png);
+			return 0;
+		}
+			
+		pBuffer = (unsigned char *)mem_alloc(png.width * png.height * png.bpp, 1);
+		png_get_data(&png, pBuffer);
+		png_close_file(&png);
+		
+		pImg->width = png.width;
+		pImg->height = png.height;
+		if(png.color_type == PNG_TRUECOLOR)
+			pImg->format = IMG_RGB;
+		else if(png.color_type == PNG_TRUECOLOR_ALPHA)
+			pImg->format = IMG_RGBA;
+		pImg->data = pBuffer;
+		return 1;
+	}
+
+	void ScreenshotDirect(const char *filename)
+	{
+		/* fetch image data */
+		int y;
+		int w = m_ScreenWidth;
+		int h = m_ScreenHeight;
+		unsigned char *pixel_data = (unsigned char *)mem_alloc(w*(h+1)*4, 1);
+		unsigned char *temp_row = pixel_data+w*h*4;
+		glReadPixels(0,0, w, h, GL_RGBA, GL_UNSIGNED_BYTE, pixel_data);
+		
+		/* flip the pixel because opengl works from bottom left corner */
+		for(y = 0; y < h/2; y++)
+		{
+			mem_copy(temp_row, pixel_data+y*w*4, w*4);
+			mem_copy(pixel_data+y*w*4, pixel_data+(h-y-1)*w*4, w*4);
+			mem_copy(pixel_data+(h-y-1)*w*4, temp_row,w*4);
+		}
+		
+		/* find filename */
+		{
+			char wholepath[1024];
+			png_t png;
+
+			engine_savepath(filename, wholepath, sizeof(wholepath));
+		
+			/* save png */
+			dbg_msg("client", "saved screenshot to '%s'", wholepath);
+			png_open_file_write(&png, wholepath);
+			png_set_data(&png, w, h, 8, PNG_TRUECOLOR_ALPHA, (unsigned char *)pixel_data);
+			png_close_file(&png);
+		}
+
+		/* clean up */
+		mem_free(pixel_data);
+	}
+
+	virtual void TextureSet(int TextureID)
+	{
+		dbg_assert(m_Drawing == 0, "called Graphics()->TextureSet within begin");
+		if(TextureID == -1)
+		{
+			glDisable(GL_TEXTURE_2D);
+		}
+		else
+		{
+			glEnable(GL_TEXTURE_2D);
+			glBindTexture(GL_TEXTURE_2D, m_aTextures[TextureID].tex);
+		}
+	}
+
+	virtual void Clear(float r, float g, float b)
+	{
+		glClearColor(r,g,b,0.0f);
+		glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	}
+
+	virtual void QuadsBegin()
+	{
+		dbg_assert(m_Drawing == 0, "called quads_begin twice");
+		m_Drawing = DRAWING_QUADS;
+		
+		QuadsSetSubset(0,0,1,1);
+		QuadsSetRotation(0);
+		SetColor(1,1,1,1);
+	}
+
+	virtual void QuadsEnd()
+	{
+		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_end without begin");
+		Flush();
+		m_Drawing = 0;
+	}
+
+	virtual void QuadsSetRotation(float Angle)
+	{
+		dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetRotation without begin");
+		m_Rotation = Angle;
+	}
+
+	virtual void SetColorVertex(int i, float r, float g, float b, float a)
+	{
+		dbg_assert(m_Drawing != 0, "called gfx_quads_setcolorvertex without begin");
+		m_aColor[i].r = r;
+		m_aColor[i].g = g;
+		m_aColor[i].b = b;
+		m_aColor[i].a = a;
+	}
+
+	virtual void SetColor(float r, float g, float b, float a)
+	{
+		dbg_assert(m_Drawing != 0, "called gfx_quads_setcolor without begin");
+		SetColorVertex(0, r, g, b, a);
+		SetColorVertex(1, r, g, b, a);
+		SetColorVertex(2, r, g, b, a);
+		SetColorVertex(3, r, g, b, a);
+	}
+
+	virtual void QuadsSetSubset(float tl_u, float tl_v, float br_u, float br_v)
+	{
+		dbg_assert(m_Drawing == DRAWING_QUADS, "called Graphics()->QuadsSetSubset without begin");
+
+		m_aTexture[0].u = tl_u;	m_aTexture[1].u = br_u;
+		m_aTexture[0].v = tl_v;	m_aTexture[1].v = tl_v;
+
+		m_aTexture[3].u = tl_u;	m_aTexture[2].u = br_u;
+		m_aTexture[3].v = br_v;	m_aTexture[2].v = br_v;
+	}
+
+	virtual void QuadsSetSubsetFree(
+		float x0, float y0, float x1, float y1,
+		float x2, float y2, float x3, float y3)
+	{
+		m_aTexture[0].u = x0; m_aTexture[0].v = y0;
+		m_aTexture[1].u = x1; m_aTexture[1].v = y1;
+		m_aTexture[2].u = x2; m_aTexture[2].v = y2;
+		m_aTexture[3].u = x3; m_aTexture[3].v = y3;
+	}
+
+	virtual void QuadsDraw(float x, float y, float w, float h)
+	{
+		QuadsDrawTL(x-w/2, y-h/2,w,h);
+	}
+
+	virtual void QuadsDrawTL(float x, float y, float w, float h)
+	{
+		CPoint Center;
+
+		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw without begin");
+
+		Center.x = x + w/2;
+		Center.y = y + h/2;
+		Center.z = 0;
+		
+		m_aVertices[m_NumVertices].m_Pos.x = x;
+		m_aVertices[m_NumVertices].m_Pos.y = y;
+		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
+		Rotate(&Center, &m_aVertices[m_NumVertices].m_Pos);
+
+		m_aVertices[m_NumVertices + 1].m_Pos.x = x+w;
+		m_aVertices[m_NumVertices + 1].m_Pos.y = y;
+		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
+		Rotate(&Center, &m_aVertices[m_NumVertices + 1].m_Pos);
+
+		m_aVertices[m_NumVertices + 2].m_Pos.x = x + w;
+		m_aVertices[m_NumVertices + 2].m_Pos.y = y+h;
+		m_aVertices[m_NumVertices + 2].m_Tex = m_aTexture[2];
+		m_aVertices[m_NumVertices + 2].m_Color = m_aColor[2];
+		Rotate(&Center, &m_aVertices[m_NumVertices + 2].m_Pos);
+
+		m_aVertices[m_NumVertices + 3].m_Pos.x = x;
+		m_aVertices[m_NumVertices + 3].m_Pos.y = y+h;
+		m_aVertices[m_NumVertices + 3].m_Tex = m_aTexture[3];
+		m_aVertices[m_NumVertices + 3].m_Color = m_aColor[3];
+		Rotate(&Center, &m_aVertices[m_NumVertices + 3].m_Pos);
+		
+		AddVertices(4);
+	}
+
+	void QuadsDrawFreeform(
+		float x0, float y0, float x1, float y1,
+		float x2, float y2, float x3, float y3)
+	{
+		dbg_assert(m_Drawing == DRAWING_QUADS, "called quads_draw_freeform without begin");
+		
+		m_aVertices[m_NumVertices].m_Pos.x = x0;
+		m_aVertices[m_NumVertices].m_Pos.y = y0;
+		m_aVertices[m_NumVertices].m_Tex = m_aTexture[0];
+		m_aVertices[m_NumVertices].m_Color = m_aColor[0];
+
+		m_aVertices[m_NumVertices + 1].m_Pos.x = x1;
+		m_aVertices[m_NumVertices + 1].m_Pos.y = y1;
+		m_aVertices[m_NumVertices + 1].m_Tex = m_aTexture[1];
+		m_aVertices[m_NumVertices + 1].m_Color = m_aColor[1];
+
+		m_aVertices[m_NumVertices + 2].m_Pos.x = x3;
+		m_aVertices[m_NumVertices + 2].m_Pos.y = y3;
+		m_aVertices[m_NumVertices + 2].m_Tex = m_aTexture[3];
+		m_aVertices[m_NumVertices + 2].m_Color = m_aColor[3];
+
+		m_aVertices[m_NumVertices + 3].m_Pos.x = x2;
+		m_aVertices[m_NumVertices + 3].m_Pos.y = y2;
+		m_aVertices[m_NumVertices + 3].m_Tex = m_aTexture[2];
+		m_aVertices[m_NumVertices + 3].m_Color = m_aColor[2];
+		
+		AddVertices(4);
+	}
+
+	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
+	{
+		float startx = x;
+
+		QuadsBegin();
+		SetColor(r,g,b,a);
+
+		while(*pText)
+		{
+			char c = *pText;
+			pText++;
+			
+			if(c == '\n')
+			{
+				x = startx;
+				y += Size;
+			}
+			else
+			{
+				QuadsSetSubset(
+					(c%16)/16.0f,
+					(c/16)/16.0f,
+					(c%16)/16.0f+1.0f/16.0f,
+					(c/16)/16.0f+1.0f/16.0f);
+				
+				QuadsDrawTL(x,y,Size,Size);
+				x += Size/2;
+			}
+		}
+		
+		QuadsEnd();
+	}
+	
+	virtual bool Init()
+	{
+		/* Set all z to -5.0f */
+		for(int i = 0; i < MAX_VERTICES; i++)
+			m_aVertices[i].m_Pos.z = -5.0f;
+
+		/* init textures */
+		m_FirstFreeTexture = 0;
+		for(int i = 0; i < MAX_TEXTURES; i++)
+			m_aTextures[i].next = i+1;
+		m_aTextures[MAX_TEXTURES-1].next = -1;
+
+		/* set some default settings */	
+		glEnable(GL_BLEND);
+		glDisable(GL_CULL_FACE);
+		glDisable(GL_DEPTH_TEST);
+		glMatrixMode(GL_MODELVIEW);
+		glLoadIdentity();
+		
+		glAlphaFunc(GL_GREATER, 0);
+		glEnable(GL_ALPHA_TEST);
+		glDepthMask(0);
+
+		/* create null texture, will get id=0 */
+		static const unsigned char aNullTextureData[] = {
+			0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
+			0xff,0x00,0x00,0xff, 0xff,0x00,0x00,0xff, 0x00,0xff,0x00,0xff, 0x00,0xff,0x00,0xff, 
+			0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
+			0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
+		};
+		
+		m_InvalidTexture = LoadTextureRaw(4,4,IMG_RGBA,aNullTextureData,IMG_RGBA,TEXLOAD_NORESAMPLE);
+		dbg_msg("", "invalid texture id: %d %d", m_InvalidTexture, m_aTextures[m_InvalidTexture].tex);
+		
+		return true;
+	}
+};
+
+class CGraphics_SDL : public CGraphics_OpenGL
+{
+	SDL_Surface *m_pScreenSurface;	
+	
+	int TryInit()
+	{
+		const SDL_VideoInfo *pInfo;
+		int Flags = SDL_OPENGL;
+		
+		m_ScreenWidth = config.gfx_screen_width;
+		m_ScreenHeight = config.gfx_screen_height;
+
+		pInfo = SDL_GetVideoInfo();
+
+		/* set flags */
+		Flags  = SDL_OPENGL;
+		Flags |= SDL_GL_DOUBLEBUFFER;
+		Flags |= SDL_HWPALETTE;
+		if(config.dbg_resizable)
+			Flags |= SDL_RESIZABLE;
+
+		if(pInfo->hw_available)
+			Flags |= SDL_HWSURFACE;
+		else
+			Flags |= SDL_SWSURFACE;
+
+		if(pInfo->blit_hw)
+			Flags |= SDL_HWACCEL;
+
+		if(config.gfx_fullscreen)
+			Flags |= SDL_FULLSCREEN;
+
+		/* set gl attributes */
+		if(config.gfx_fsaa_samples)
+		{
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 1);
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, config.gfx_fsaa_samples);
+		}
+		else
+		{
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLEBUFFERS, 0);
+			SDL_GL_SetAttribute(SDL_GL_MULTISAMPLESAMPLES, 0);
+		}
+
+		SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
+		SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, config.gfx_vsync);
+
+		/* set caption */
+		SDL_WM_SetCaption("Teeworlds", "Teeworlds");
+		
+		/* create window */
+		m_pScreenSurface = SDL_SetVideoMode(m_ScreenWidth, m_ScreenHeight, 0, Flags);
+		if(m_pScreenSurface == NULL)
+		{
+			dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
+			return -1;
+		}
+		
+		return 0;
+	}
+
+
+	int InitWindow()
+	{
+		if(TryInit() == 0)
+			return 0;
+		
+		/* try disabling fsaa */
+		while(config.gfx_fsaa_samples)
+		{
+			config.gfx_fsaa_samples--;
+			
+			if(config.gfx_fsaa_samples)
+				dbg_msg("gfx", "lowering FSAA to %d and trying again", config.gfx_fsaa_samples);
+			else
+				dbg_msg("gfx", "disabling FSAA and trying again");
+
+			if(TryInit() == 0)
+				return 0;
+		}
+
+		/* try lowering the resolution */
+		if(config.gfx_screen_width != 640 || config.gfx_screen_height != 480)
+		{
+			dbg_msg("gfx", "setting resolution to 640x480 and trying again");
+			config.gfx_screen_width = 640;
+			config.gfx_screen_height = 480;
+
+			if(TryInit() == 0)
+				return 0;
+		}
+
+		dbg_msg("gfx", "out of ideas. failed to init graphics");
+						
+		return -1;		
+	}
+
+	
+public:
+	CGraphics_SDL()
+	{
+		m_pScreenSurface = 0;
+	}
+
+	virtual bool Init()
+	{
+		{
+			int Systems = SDL_INIT_VIDEO;
+			
+			if(config.snd_enable)
+				Systems |= SDL_INIT_AUDIO;
+
+			if(config.cl_eventthread)
+				Systems |= SDL_INIT_EVENTTHREAD;
+			
+			if(SDL_Init(Systems) < 0)
+			{
+				dbg_msg("gfx", "unable to init SDL: %s", SDL_GetError());
+				return -1;
+			}
+		}
+		
+		atexit(SDL_Quit);
+
+		#ifdef CONF_FAMILY_WINDOWS
+			if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED"))
+				putenv("SDL_VIDEO_WINDOW_POS=8,27");
+		#endif
+		
+		if(InitWindow() != 0)
+			return -1;
+
+		SDL_ShowCursor(0);
+			
+		CGraphics_OpenGL::Init();
+		
+		MapScreen(0,0,config.gfx_screen_width, config.gfx_screen_height);
+
+		/* init input */
+		inp_init();
+
+		/* font init */
+		gfx_font_init();
+
+		return 0;
+	}
+	
+	virtual void Shutdown()
+	{
+		/* TODO: SDL, is this correct? */
+		SDL_Quit();
+	}
+
+	virtual void Minimize()
+	{
+		SDL_WM_IconifyWindow();
+	}
+
+	virtual void Maximize()
+	{
+		/* TODO: SDL */
+	}
+
+	virtual int WindowActive()
+	{
+		return SDL_GetAppState()&SDL_APPINPUTFOCUS;
+	}
+
+	virtual int WindowOpen()
+	{
+		return SDL_GetAppState()&SDL_APPACTIVE;
+
+	}
+	
+	virtual void TakeScreenshot()
+	{
+		m_DoScreenshot = true;
+	}
+	
+	virtual void Swap()
+	{
+		if(m_DoScreenshot)
+		{
+			/* find filename */
+			char filename[128];
+			static int index = 1;
+
+			for(; index < 1000; index++)
+			{
+				IOHANDLE io;
+				str_format(filename, sizeof(filename), "screenshots/screenshot%04d.png", index);
+				io = engine_openfile(filename, IOFLAG_READ);
+				if(io)
+					io_close(io);
+				else
+					break;
+			}
+
+			ScreenshotDirect(filename);
+			m_DoScreenshot = false;
+		}
+		
+		{
+			static PERFORMACE_INFO pscope = {"glfwSwapBuffers", 0};
+			perf_start(&pscope);
+			SDL_GL_SwapBuffers();
+			perf_end();
+		}
+		
+		if(config.gfx_finish)
+			glFinish();		
+	}
+};
+
+extern IEngineGraphics *CreateEngineGraphics() { return new CGraphics_SDL(); }
diff --git a/src/engine/client/ec_gfx_text.c b/src/engine/client/ec_gfx_text.cpp
index de40e391..d17d1bed 100644
--- a/src/engine/client/ec_gfx_text.c
+++ b/src/engine/client/ec_gfx_text.cpp
@@ -1,7 +1,9 @@
 #include <base/system.h>
 #include <string.h>
 #include <engine/e_client_interface.h>
+#include <engine/client/graphics.h>
 
+extern IEngineGraphics *Graphics();
 
 #ifdef CONF_PLATFORM_MACOSX
 	#include <OpenGL/gl.h>
@@ -138,8 +140,7 @@ typedef struct FONT
 
 static int font_get_index(int pixelsize)
 {
-	int i;
-	for(i = 0; i < NUM_FONT_SIZES; i++)
+	for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
 	{
 		if(font_sizes[i] >= pixelsize)
 			return i;
@@ -150,8 +151,7 @@ static int font_get_index(int pixelsize)
 
 FONT *gfx_font_load(const char *filename)
 {
-	int i;
-	FONT *font = mem_alloc(sizeof(FONT), 1);
+	FONT *font = (FONT *)mem_alloc(sizeof(FONT), 1);
 	
 	mem_zero(font, sizeof(*font));
 	str_copy(font->filename, filename, sizeof(font->filename));
@@ -162,7 +162,7 @@ FONT *gfx_font_load(const char *filename)
 		return NULL;
 	}
 
-	for(i = 0; i < NUM_FONT_SIZES; i++)
+	for(unsigned i = 0; i < NUM_FONT_SIZES; i++)
 		font->sizes[i].font_size = -1;
 		
 	return font;
@@ -484,6 +484,7 @@ static float font_kerning(FONT *font, int left, int right)
 	return (kerning.x>>6);
 }
 
+
 void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
 {
 	FONT *font = cursor->font;
@@ -503,10 +504,10 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
 	float size = cursor->font_size;
 
 	/* to correct coords, convert to screen coords, round, and convert back */
-	gfx_getscreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
+	Graphics()->GetScreen(&screen_x0, &screen_y0, &screen_x1, &screen_y1);
 	
-	fake_to_screen_x = (gfx_screenwidth()/(screen_x1-screen_x0));
-	fake_to_screen_y = (gfx_screenheight()/(screen_y1-screen_y0));
+	fake_to_screen_x = (Graphics()->ScreenWidth()/(screen_x1-screen_x0));
+	fake_to_screen_y = (Graphics()->ScreenHeight()/(screen_y1-screen_y0));
 	actual_x = cursor->x * fake_to_screen_x;
 	actual_y = cursor->y * fake_to_screen_y;
 
@@ -554,11 +555,11 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
 			else
 				glBindTexture(GL_TEXTURE_2D, sizedata->textures[0]);
 
-			gfx_quads_begin();
+			Graphics()->QuadsBegin();
 			if (i == 0)
-				gfx_setcolor(0.0f, 0.0f, 0.0f, 0.3f*text_a);
+				Graphics()->SetColor(0.0f, 0.0f, 0.0f, 0.3f*text_a);
 			else
-				gfx_setcolor(text_r, text_g, text_b, text_a);
+				Graphics()->SetColor(text_r, text_g, text_b, text_a);
 		}
 
 		while(current < end)
@@ -629,8 +630,8 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
 				{
 					if(cursor->flags&TEXTFLAG_RENDER)
 					{
-						gfx_quads_setsubset(chr->uvs[0], chr->uvs[1], chr->uvs[2], chr->uvs[3]);
-						gfx_quads_drawTL(draw_x+chr->offset_x*size, draw_y+chr->offset_y*size, chr->width*size, chr->height*size);
+						Graphics()->QuadsSetSubset(chr->uvs[0], chr->uvs[1], chr->uvs[2], chr->uvs[3]);
+						Graphics()->QuadsDrawTL(draw_x+chr->offset_x*size, draw_y+chr->offset_y*size, chr->width*size, chr->height*size);
 					}
 
 					advance = chr->advance_x + font_kerning(font, character, nextcharacter)/size;
@@ -658,7 +659,7 @@ void gfx_text_ex(TEXT_CURSOR *cursor, const char *text, int length)
 		}
 
 		if(cursor->flags&TEXTFLAG_RENDER)
-			gfx_quads_end();
+			Graphics()->QuadsEnd();
 	}
 
 	cursor->x = draw_x;
diff --git a/src/engine/client/ec_inp.c b/src/engine/client/ec_inp.cpp
index 495614d6..cf956471 100644
--- a/src/engine/client/ec_inp.c
+++ b/src/engine/client/ec_inp.cpp
@@ -5,6 +5,7 @@
 #include <base/system.h>
 #include <engine/e_client_interface.h>
 #include <engine/e_config.h>
+#include <engine/client/graphics.h>
 
 static struct
 {
@@ -20,6 +21,9 @@ static int input_grabbed = 0;
 static unsigned int last_release = 0;
 static unsigned int release_delta = -1;
 
+// TODO: Refactor: Remove this
+extern IEngineGraphics *Graphics();
+
 void inp_mouse_relative(int *x, int *y)
 {
 	int nx = 0, ny = 0;
@@ -32,8 +36,8 @@ void inp_mouse_relative(int *x, int *y)
 		if(input_grabbed)
 		{
 			SDL_GetMouseState(&nx,&ny);
-			SDL_WarpMouse(gfx_screenwidth()/2,gfx_screenheight()/2);
-			nx -= gfx_screenwidth()/2; ny -= gfx_screenheight()/2;
+			SDL_WarpMouse(Graphics()->ScreenWidth()/2,Graphics()->ScreenHeight()/2);
+			nx -= Graphics()->ScreenWidth()/2; ny -= Graphics()->ScreenHeight()/2;
 		}
 	}
 
@@ -138,10 +142,10 @@ void inp_update()
 {
 	int i;
 	
-	if(input_grabbed && !gfx_window_active())
+	if(input_grabbed && !Graphics()->WindowActive())
 		inp_mouse_mode_absolute();
 
-	/*if(!input_grabbed && gfx_window_active())
+	/*if(!input_grabbed && Graphics()->WindowActive())
 		inp_mouse_mode_relative();*/
 	
 	/* clear and begin count on the other one */
diff --git a/src/engine/client/ec_snd.c b/src/engine/client/ec_snd.cpp
index ac41ec59..3baea982 100644
--- a/src/engine/client/ec_snd.c
+++ b/src/engine/client/ec_snd.cpp
@@ -1,12 +1,15 @@
 /* copyright (c) 2007 magnus auvinen, see licence.txt for more info */
 #include <base/system.h>
 #include <engine/e_client_interface.h>
+#include <engine/client/graphics.h>
 #include <engine/e_config.h>
 #include <engine/e_engine.h>
 
 #include "SDL.h"
 
-#include <engine/external/wavpack/wavpack.h>
+extern "C" { // wavpack
+	#include <engine/external/wavpack/wavpack.h>
+}
 #include <stdio.h>
 #include <stdlib.h>
 #include <math.h>
@@ -140,7 +143,6 @@ static int iabs(int i)
 static void mix(short *final_out, unsigned frames)
 {
 	int mix_buffer[MAX_FRAMES*2] = {0};
-	int i, s;
 	int master_vol;
 
 	/* aquire lock while we are mixing */
@@ -148,7 +150,7 @@ static void mix(short *final_out, unsigned frames)
 	
 	master_vol = sound_volume;
 	
-	for(i = 0; i < NUM_VOICES; i++)
+	for(unsigned i = 0; i < NUM_VOICES; i++)
 	{
 		if(voices[i].snd)
 		{
@@ -160,7 +162,7 @@ static void mix(short *final_out, unsigned frames)
 			short *in_l = &v->snd->data[v->tick*step];
 			short *in_r = &v->snd->data[v->tick*step+1];
 			
-			int end = v->snd->num_frames-v->tick;
+			unsigned end = v->snd->num_frames-v->tick;
 
 			int rvol = v->channel->vol;
 			int lvol = v->channel->vol;
@@ -202,7 +204,7 @@ static void mix(short *final_out, unsigned frames)
 			}
 
 			/* process all frames */
-			for(s = 0; s < end; s++)
+			for(unsigned s = 0; s < end; s++)
 			{
 				*out++ += (*in_l)*lvol;
 				*out++ += (*in_r)*rvol;
@@ -225,7 +227,7 @@ static void mix(short *final_out, unsigned frames)
 	{
 		/* clamp accumulated values */
 		/* TODO: this seams slow */
-		for(i = 0; i < frames; i++)
+		for(unsigned i = 0; i < frames; i++)
 		{
 			int j = i<<1;
 			int vl = ((mix_buffer[j]*master_vol)/101)>>8;
@@ -281,12 +283,16 @@ int snd_init()
 	return 0;
 }
 
+// TODO: Refactor: Remove this
+extern IEngineGraphics *Graphics();
+
+
 int snd_update()
 {
 	/* update volume */
 	int wanted_volume = config.snd_volume;
 	
-	if(!gfx_window_active() && config.snd_nonactive_mute)
+	if(!Graphics()->WindowActive() && config.snd_nonactive_mute)
 		wanted_volume = 0;
 	
 	if(wanted_volume != sound_volume)
@@ -332,7 +338,7 @@ static void rate_convert(int sid)
 
 	/* allocate new data */
 	num_frames = (int)((snd->num_frames/(float)snd->rate)*mixing_rate);
-	new_data = mem_alloc(num_frames*snd->channels*sizeof(short), 1);
+	new_data = (short *)mem_alloc(num_frames*snd->channels*sizeof(short), 1);
 	
 	for(i = 0; i < num_frames; i++)
 	{
diff --git a/src/engine/client/ec_srvbrowse.c b/src/engine/client/ec_srvbrowse.cpp
index 4a85e778..1b04937a 100644
--- a/src/engine/client/ec_srvbrowse.c
+++ b/src/engine/client/ec_srvbrowse.cpp
@@ -11,7 +11,7 @@
 #include <string.h>
 #include <stdlib.h>
 
-extern NETCLIENT *net;
+extern CNetClient m_NetClient;
 
 
 /* ------ server browse ---- */
@@ -150,7 +150,7 @@ static void client_serverbrowse_filter()
 		if(sorted_serverlist)
 			mem_free(sorted_serverlist);
 		num_sorted_servers_capacity = num_servers;
-		sorted_serverlist = mem_alloc(num_sorted_servers_capacity*sizeof(int), 1);
+		sorted_serverlist = (int *)mem_alloc(num_sorted_servers_capacity*sizeof(int), 1);
 	}
 	
 	/* filter the servers */
@@ -401,7 +401,7 @@ SERVERENTRY *client_serverbrowse_add(NETADDR *addr)
 	{
 		SERVERENTRY **newlist;
 		num_server_capacity += 100;
-		newlist = mem_alloc(num_server_capacity*sizeof(SERVERENTRY*), 1);
+		newlist = (SERVERENTRY **)mem_alloc(num_server_capacity*sizeof(SERVERENTRY*), 1);
 		mem_copy(newlist, serverlist, num_servers*sizeof(SERVERENTRY*));
 		mem_free(serverlist);
 		serverlist = newlist;
@@ -506,28 +506,28 @@ void client_serverbrowse_refresh(int type)
 
 	if(type == BROWSETYPE_LAN)
 	{
-		unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];
-		NETCHUNK packet;
+		unsigned char Buffer[sizeof(SERVERBROWSE_GETINFO)+1];
+		CNetChunk Packet;
 		int i;
 		
-		mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
-		buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;
+		mem_copy(Buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
+		Buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;
 			
-		packet.client_id = -1;
-		mem_zero(&packet, sizeof(packet));
-		packet.address.ip[0] = 255;
-		packet.address.ip[1] = 255;
-		packet.address.ip[2] = 255;
-		packet.address.ip[3] = 255;
-		packet.flags = NETSENDFLAG_CONNLESS;
-		packet.data_size = sizeof(buffer);
-		packet.data = buffer;
+		Packet.m_ClientID = -1;
+		mem_zero(&Packet, sizeof(Packet));
+		Packet.m_Address.ip[0] = 255;
+		Packet.m_Address.ip[1] = 255;
+		Packet.m_Address.ip[2] = 255;
+		Packet.m_Address.ip[3] = 255;
+		Packet.m_Flags = NETSENDFLAG_CONNLESS;
+		Packet.m_DataSize = sizeof(Buffer);
+		Packet.m_pData = Buffer;
 		broadcast_time = time_get();
 
 		for(i = 8303; i <= 8310; i++)
 		{
-			packet.address.port = i;
-			netclient_send(net, &packet);
+			Packet.m_Address.port = i;
+			m_NetClient.Send(&Packet);
 		}
 
 		if(config.debug)
@@ -537,8 +537,7 @@ void client_serverbrowse_refresh(int type)
 		need_refresh = 1;
 	else if(type == BROWSETYPE_FAVORITES)
 	{
-		int i;
-		for(i = 0; i < num_favorite_servers; i++)
+		for(int i = 0; i < num_favorite_servers; i++)
 			client_serverbrowse_set(&favorite_servers[i], BROWSESET_FAV_ADD, -1, 0);
 	}
 }
@@ -546,7 +545,7 @@ void client_serverbrowse_refresh(int type)
 static void client_serverbrowse_request_impl(NETADDR *addr, SERVERENTRY *entry)
 {
 	/*unsigned char buffer[sizeof(SERVERBROWSE_GETINFO)+1];*/
-	NETCHUNK p;
+	CNetChunk Packet;
 
 	if(config.debug)
 	{
@@ -558,17 +557,17 @@ static void client_serverbrowse_request_impl(NETADDR *addr, SERVERENTRY *entry)
 	/*mem_copy(buffer, SERVERBROWSE_GETINFO, sizeof(SERVERBROWSE_GETINFO));
 	buffer[sizeof(SERVERBROWSE_GETINFO)] = current_token;*/
 	
-	p.client_id = -1;
-	p.address = *addr;
-	p.flags = NETSENDFLAG_CONNLESS;
+	Packet.m_ClientID = -1;
+	Packet.m_Address = *addr;
+	Packet.m_Flags = NETSENDFLAG_CONNLESS;
 	/*p.data_size = sizeof(buffer);
 	p.data = buffer;
 	netclient_send(net, &p);*/
 
 	/* send old requtest style aswell */	
-	p.data_size = sizeof(SERVERBROWSE_OLD_GETINFO);
-	p.data = SERVERBROWSE_OLD_GETINFO;
-	netclient_send(net, &p);
+	Packet.m_DataSize = sizeof(SERVERBROWSE_OLD_GETINFO);
+	Packet.m_pData = SERVERBROWSE_OLD_GETINFO;
+	m_NetClient.Send(&Packet);
 	
 	if(entry)
 		entry->request_time = time_get();
@@ -591,16 +590,16 @@ void client_serverbrowse_update()
 	if(need_refresh && !mastersrv_refreshing())
 	{
 		NETADDR addr;
-		NETCHUNK p;
+		CNetChunk Packet;
 		int i;
 		
 		need_refresh = 0;
 		
-		mem_zero(&p, sizeof(p));
-		p.client_id = -1;
-		p.flags = NETSENDFLAG_CONNLESS;
-		p.data_size = sizeof(SERVERBROWSE_GETLIST);
-		p.data = SERVERBROWSE_GETLIST;
+		mem_zero(&Packet, sizeof(Packet));
+		Packet.m_ClientID = -1;
+		Packet.m_Flags = NETSENDFLAG_CONNLESS;
+		Packet.m_DataSize = sizeof(SERVERBROWSE_GETLIST);
+		Packet.m_pData = SERVERBROWSE_GETLIST;
 		
 		for(i = 0; i < MAX_MASTERSERVERS; i++)
 		{
@@ -608,8 +607,8 @@ void client_serverbrowse_update()
 			if(!addr.ip[0] && !addr.ip[1] && !addr.ip[2] && !addr.ip[3])
 				continue;
 			
-			p.address = addr;
-			netclient_send(net, &p);
+			Packet.m_Address = addr;
+			m_NetClient.Send(&Packet);
 		}
 
 		if(config.debug)