about summary refs log tree commit diff
path: root/src/engine/client
diff options
context:
space:
mode:
authorMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
committerMagnus Auvinen <magnus.auvinen@gmail.com>2007-08-22 07:52:33 +0000
commit8b3c16e6152a527f9aec1a88a9eed74119de7000 (patch)
treef0bde5cea15e696e42cade06a3b12ff6b13acc57 /src/engine/client
parent9899666a7ce6679a3b9667ab09f615f4d0769c16 (diff)
downloadzcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.tar.gz
zcatch-8b3c16e6152a527f9aec1a88a9eed74119de7000.zip
major engine cleanup. dependency on baselib removed. engine is now C code (not ansi tho). some other cruft removed aswell
Diffstat (limited to 'src/engine/client')
-rw-r--r--src/engine/client/client.c (renamed from src/engine/client/client.cpp)288
-rw-r--r--src/engine/client/gfx.c (renamed from src/engine/client/gfx.cpp)322
-rw-r--r--src/engine/client/inp.c95
-rw-r--r--src/engine/client/pnglite/pnglite.c877
-rw-r--r--src/engine/client/pnglite/pnglite.h227
-rw-r--r--src/engine/client/snd.c (renamed from src/engine/client/snd.cpp)446
-rw-r--r--src/engine/client/ui.c (renamed from src/engine/client/ui.cpp)11
-rw-r--r--src/engine/client/ui.h16
8 files changed, 615 insertions, 1667 deletions
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.c
index a4cb4509..ab4b7109 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.c
@@ -1,29 +1,25 @@
-#include <baselib/system.h>
-#include <baselib/config.h>
-#include <baselib/input.h>
-#include <baselib/audio.h>
-#include <baselib/stream/file.h>
 
 #include <string.h>
 #include <stdarg.h>
 #include <stdlib.h>
 #include <stdio.h>
 #include <math.h>
-#include <engine/interface.h>
 
-#include <engine/packet.h>
-#include <engine/snapshot.h>
+#include <engine/system.h>
+#include <engine/interface.h>
 #include "ui.h"
 
+#include <engine/versions.h>
+
+#include <engine/protocol.h>
+#include <engine/snapshot.h>
 #include <engine/compression.h>
 #include <engine/network.h>
-#include <engine/versions.h>
 #include <engine/config.h>
+#include <engine/packer.h>
 
 #include <mastersrv/mastersrv.h>
 
-using namespace baselib;
-
 static int info_request_begin;
 static int info_request_end;
 static int snapshot_part;
@@ -33,42 +29,15 @@ static float latency = 0;
 static int extra_polating = 0;
 static int debug_font;
 static float frametime = 0.0001f;
-static net_client net;
-static netaddr4 master_server;
-static netaddr4 server_address;
+static NETCLIENT *net;
+static NETADDR4 master_server;
+static NETADDR4 server_address;
 static int window_must_refocus = 0;
 static int snaploss = 0;
 
 static int current_tick = 0;
 static float intratick = 0;
 
-
-// --- input wrappers ---
-static int keyboard_state[2][input::last];
-static int keyboard_current = 0;
-static int keyboard_first = 1;
-
-void inp_mouse_relative(int *x, int *y) { input::mouse_position(x, y); }
-int inp_mouse_scroll() { return input::mouse_scroll(); }
-int inp_key_pressed(int key) { return keyboard_state[keyboard_current][key]; }
-int inp_key_was_pressed(int key) { return keyboard_state[keyboard_current^1][key]; }
-int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); }
-int inp_button_pressed(int button) { return input::pressed(button); }
-
-void inp_update()
-{
-	if(keyboard_first)
-	{
-		// make sure to reset
-		keyboard_first = 0;
-		inp_update();
-	}
-	
-	keyboard_current = keyboard_current^1;
-	for(int i = 0; i < input::last; i++)
-		keyboard_state[keyboard_current][i] = input::pressed(i);
-}
-
 // --- input snapping ---
 static int input_data[MAX_INPUT_SIZE] = {0};
 static int input_data_size;
@@ -87,94 +56,31 @@ enum
 	NUM_SNAPSHOT_TYPES=2,
 };
 
-struct snapshot_info
-{
-	snapshot_info *prev;
-	snapshot_info *next;
-	
-	int tick;
-	int64 recvtime;
-	snapshot *snap;
-};
-
-static snapshot_info *first_snapshot = 0;
-static snapshot_info *last_snapshot = 0;
-
-static snapshot_info *client_snapshot_add(int tick, int64 time, void *data, int data_size)
-{
-	snapshot_info *holder = (snapshot_info*)mem_alloc(sizeof(snapshot_info) + data_size, 1);
-	holder->tick = tick;
-	holder->recvtime = time;
-	holder->snap = (snapshot *)(holder+1);
-	mem_copy(holder->snap, data, data_size);
-	
-	holder->next =0x0;
-	holder->prev = last_snapshot;
-	if(last_snapshot)
-		last_snapshot->next = holder;
-	else
-		first_snapshot = holder;
-	last_snapshot = holder;
-	
-	return holder;
-}
-
-static snapshot_info *client_snapshot_find(int tick)
-{
-	snapshot_info *current = first_snapshot;
-	while(current)
-	{
-		if(current->tick == tick)
-			return current;
-		current = current->next;
-	}
-	
-	return 0;
-}
-
-static void client_snapshot_purge_until(int tick)
-{
-	snapshot_info *current = first_snapshot;
-	while(current)
-	{
-		snapshot_info *next = current->next;
-		if(current->tick < tick)
-			mem_free(current);
-		else
-			break;
-		
-		current = next;
-		current->prev = 0;
-		first_snapshot = current;
-	}
-	
-	if(!first_snapshot)
-		last_snapshot = 0;
-}
-
-static snapshot_info *snapshots[NUM_SNAPSHOT_TYPES];
+SNAPSTORAGE snapshot_storage;
+static SNAPSTORAGE_HOLDER *snapshots[NUM_SNAPSHOT_TYPES];
 static int recived_snapshots;
 static char snapshot_incomming_data[MAX_SNAPSHOT_SIZE];
 
 // ---
 
-const void *snap_get_item(int snapid, int index, snap_item *item)
+const void *snap_get_item(int snapid, int index, SNAP_ITEM *item)
 {
 	dbg_assert(snapid >= 0 && snapid < NUM_SNAPSHOT_TYPES, "invalid snapid");
-	snapshot::item *i = snapshots[snapid]->snap->get_item(index);
-	item->type = i->type();
-	item->id = i->id();
-	return (void *)i->data();
+	SNAPSHOT_ITEM *i = snapshot_get_item(snapshots[snapid]->snap, index);
+	item->type = snapitem_type(i);
+	item->id = snapitem_id(i);
+	return (void *)snapitem_data(i);
 }
 
 const void *snap_find_item(int snapid, int type, int id)
 {
 	// TODO: linear search. should be fixed.
-	for(int i = 0; i < snapshots[snapid]->snap->num_items; i++)
+	int i;
+	for(i = 0; i < snapshots[snapid]->snap->num_items; i++)
 	{
-		snapshot::item *itm = snapshots[snapid]->snap->get_item(i);
-		if(itm->type() == type && itm->id() == id)
-			return (void *)itm->data();
+		SNAPSHOT_ITEM *itm = snapshot_get_item(snapshots[snapid]->snap, i);
+		if(snapitem_type(itm) == type && snapitem_id(itm) == id)
+			return (void *)snapitem_data(itm);
 	}
 	return 0x0;
 }
@@ -225,7 +131,7 @@ int menu_loop(); // TODO: what is this?
 // ----- send functions -----
 int client_send_msg()
 {
-	const msg_info *info = msg_get_info();
+	const MSG_INFO *info = msg_get_info();
 	NETPACKET packet;
 	mem_zero(&packet, sizeof(NETPACKET));
 	
@@ -236,7 +142,7 @@ int client_send_msg()
 	if(info->flags&MSGFLAG_VITAL)	
 		packet.flags = PACKETFLAG_VITAL;
 	
-	net.send(&packet);
+	netclient_send(net, &packet);
 	return 0;
 }
 
@@ -265,9 +171,6 @@ static void client_send_entergame()
 static void client_send_error(const char *error)
 {
 	/*
-		pack(NETMSG_CLIENT_ERROR, "s", error);
-	*/
-	/*
 	packet p(NETMSG_CLIENT_ERROR);
 	p.write_str(error);
 	send_packet(&p);
@@ -280,7 +183,8 @@ static void client_send_input()
 {
 	msg_pack_start_system(NETMSG_INPUT, 0);
 	msg_pack_int(input_data_size);
-	for(int i = 0; i < input_data_size/4; i++)
+	int i;
+	for(i = 0; i < input_data_size/4; i++)
 		msg_pack_int(input_data[i]);
 	msg_pack_end();
 	client_send_msg();
@@ -290,14 +194,15 @@ static void client_send_input()
 // ------ server browse ----
 static struct 
 {
-	server_info infos[MAX_SERVERS];
+	SERVER_INFO infos[MAX_SERVERS];
 	int64 request_times[MAX_SERVERS];
-	netaddr4 addresses[MAX_SERVERS];
+	NETADDR4 addresses[MAX_SERVERS];
 	int num;
 } servers;
+
 static int serverlist_lan = 1;
 
-int client_serverbrowse_getlist(server_info **serverlist)
+int client_serverbrowse_getlist(SERVER_INFO **serverlist)
 {
 	*serverlist = servers.infos;
 	return servers.num;
@@ -327,7 +232,7 @@ void client_serverbrowse_refresh(int lan)
 		packet.flags = PACKETFLAG_CONNLESS;
 		packet.data_size = sizeof(SERVERBROWSE_GETINFO);
 		packet.data = SERVERBROWSE_GETINFO;
-		net.send(&packet);	
+		netclient_send(net, &packet);	
 		
 		// reset the list
 		servers.num = 0;		
@@ -343,7 +248,7 @@ void client_serverbrowse_refresh(int lan)
 		packet.flags = PACKETFLAG_CONNLESS;
 		packet.data_size = sizeof(SERVERBROWSE_GETLIST);
 		packet.data = SERVERBROWSE_GETLIST;
-		net.send(&packet);	
+		netclient_send(net, &packet);	
 		
 		// reset the list
 		servers.num = 0;
@@ -365,7 +270,7 @@ static void client_serverbrowse_request(int id)
 	packet.flags = PACKETFLAG_CONNLESS;
 	packet.data_size = sizeof(SERVERBROWSE_GETINFO);
 	packet.data = SERVERBROWSE_GETINFO;
-	net.send(&packet);
+	netclient_send(net, &packet);
 	servers.request_times[id] = time_get();
 }
 
@@ -413,7 +318,8 @@ void client_connect(const char *server_address_str)
 	strncpy(buf, server_address_str, 512);
 	
 	const char *port_str = 0;
-	for(int k = 0; buf[k]; k++)
+	int k;
+	for(k = 0; buf[k]; k++)
 	{
 		if(buf[k] == ':')
 		{
@@ -430,7 +336,7 @@ void client_connect(const char *server_address_str)
 	if(net_host_lookup(buf, port, &server_address) != 0)
 		dbg_msg("client", "could not find the address of %s, connecting to localhost", buf);
 	
-	net.connect(&server_address);
+	netclient_connect(net, &server_address);
 	client_set_state(CLIENTSTATE_CONNECTING);	
 	current_tick = 0;
 }
@@ -438,15 +344,15 @@ void client_connect(const char *server_address_str)
 void client_disconnect()
 {
 	client_send_error("disconnected");
-	net.disconnect("disconnected");
+	netclient_disconnect(net, "disconnected");
 	client_set_state(CLIENTSTATE_OFFLINE);
 	map_unload();
 }
 
-static bool client_load_data()
+static int client_load_data()
 {
 	debug_font = gfx_load_texture("data/debug_font.png");
-	return true;
+	return 1;
 }
 
 static void client_debug_render()
@@ -464,7 +370,7 @@ static void client_debug_render()
 	{
 		last_snap = time_get();
 		prev = current;
-		net.stats(&current);
+		netclient_stats(net, &current);
 	}
 	
 	static float frametime_avg = 0;
@@ -488,7 +394,7 @@ void client_quit()
 
 const char *client_error_string()
 {
-	return net.error_string();
+	return netclient_error_string(net);
 }
 
 static void client_render()
@@ -521,7 +427,8 @@ static void client_process_packet(NETPACKET *packet)
 			info_request_begin = 0;
 			info_request_end = 0;
 
-			for(int i = 0; i < servers.num; i++)
+			int i;
+			for(i = 0; i < servers.num; i++)
 			{
 				servers.infos[i].num_players = 0;
 				servers.infos[i].max_players = 0;
@@ -543,18 +450,18 @@ static void client_process_packet(NETPACKET *packet)
 			memcmp(packet->data, SERVERBROWSE_INFO, sizeof(SERVERBROWSE_INFO)) == 0)
 		{
 			// we got ze info
-			data_unpacker unpacker;
-			unpacker.reset((unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO));
+			UNPACKER up;
+			unpacker_reset(&up, (unsigned char*)packet->data+sizeof(SERVERBROWSE_INFO), packet->data_size-sizeof(SERVERBROWSE_INFO));
 			
 			if(serverlist_lan)
 			{
 				if(servers.num != MAX_SERVERS)
 				{
 					int i = servers.num;
-					strncpy(servers.infos[i].name, unpacker.get_string(), 128);
-					strncpy(servers.infos[i].map, unpacker.get_string(), 128);
-					servers.infos[i].max_players = unpacker.get_int();
-					servers.infos[i].num_players = unpacker.get_int();
+					strncpy(servers.infos[i].name, unpacker_get_string(&up), 128);
+					strncpy(servers.infos[i].map, unpacker_get_string(&up), 128);
+					servers.infos[i].max_players = unpacker_get_int(&up);
+					servers.infos[i].num_players = unpacker_get_int(&up);
 					servers.infos[i].latency = 0;
 					
 					sprintf(servers.infos[i].address, "%d.%d.%d.%d:%d",
@@ -569,14 +476,15 @@ static void client_process_packet(NETPACKET *packet)
 			}
 			else
 			{
-				for(int i = 0; i < servers.num; i++)
+				int i;
+				for(i = 0; i < servers.num; i++)
 				{
 					if(net_addr4_cmp(&servers.addresses[i], &packet->address) == 0)
 					{
-						strncpy(servers.infos[i].name, unpacker.get_string(), 128);
-						strncpy(servers.infos[i].map, unpacker.get_string(), 128);
-						servers.infos[i].max_players = unpacker.get_int();
-						servers.infos[i].num_players = unpacker.get_int();
+						strncpy(servers.infos[i].name, unpacker_get_string(&up), 128);
+						strncpy(servers.infos[i].map, unpacker_get_string(&up), 128);
+						servers.infos[i].max_players = unpacker_get_int(&up);
+						servers.infos[i].num_players = unpacker_get_int(&up);
 						servers.infos[i].latency = ((time_get() - servers.request_times[i])*1000)/time_freq();
 						if(config.debug)
 							dbg_msg("client", "got server info");
@@ -637,21 +545,20 @@ static void client_process_packet(NETPACKET *packet)
 						snapshot_part = 0;
 						
 						// find snapshot that we should use as delta 
-						static snapshot emptysnap;
+						static SNAPSHOT emptysnap;
 						emptysnap.data_size = 0;
 						emptysnap.num_items = 0;
 						
-						snapshot *deltashot = &emptysnap;
+						SNAPSHOT *deltashot = &emptysnap;
 						
 						// find delta
 						if(delta_tick >= 0)
 						{
 							//void *delta_data;
-							snapshot_info *delta_info = client_snapshot_find(delta_tick);
-							//deltashot_size = snapshots_new.get(delta_tick, 0, &delta_data);
-							if(delta_info)
-								deltashot = delta_info->snap;
-							else
+							
+							int deltashot_size = snapstorage_get(&snapshot_storage, delta_tick, 0, &deltashot);
+							
+							if(deltashot_size < 0)
 							{
 								// couldn't find the delta snapshots that the server used
 								// to compress this snapshot. force the server to resync
@@ -684,7 +591,7 @@ static void client_process_packet(NETPACKET *packet)
 						//dbg_msg("UNPACK", "%d unpacked with %d", game_tick, delta_tick);
 						
 						unsigned char tmpbuffer3[MAX_SNAPSHOT_SIZE];
-						int snapsize = snapshot_unpack_delta(deltashot, (snapshot*)tmpbuffer3, deltadata, deltasize);
+						int snapsize = snapshot_unpack_delta(deltashot, (SNAPSHOT*)tmpbuffer3, deltadata, deltasize);
 
 						// purge old snapshots				
 						int purgetick = delta_tick;
@@ -692,11 +599,12 @@ static void client_process_packet(NETPACKET *packet)
 							purgetick = snapshots[SNAP_PREV]->tick;
 						if(snapshots[SNAP_CURRENT] && snapshots[SNAP_CURRENT]->tick < purgetick)
 							purgetick = snapshots[SNAP_PREV]->tick;
-						client_snapshot_purge_until(purgetick);
+						snapstorage_purge_until(&snapshot_storage, purgetick);
 						//client_snapshot_purge_until(game_tick-50);
 						
 						// add new
-						snapshot_info *snap = client_snapshot_add(game_tick, time_get(), tmpbuffer3, snapsize);
+						snapstorage_add(&snapshot_storage, game_tick, time_get(), snapsize, (SNAPSHOT*)tmpbuffer3);
+						//SNAPSTORAGE_HOLDER *snap = client_snapshot_add(game_tick, time_get(), tmpbuffer3, snapsize);
 						
 						//int ncrc = snapshot_crc((snapshot*)tmpbuffer3);
 						//if(crc != ncrc)
@@ -708,22 +616,17 @@ static void client_process_packet(NETPACKET *packet)
 
 						if(current_tick > 0)
 							snaploss += game_tick-current_tick-1;
-						
 						current_tick = game_tick;
 						
 						// we got two snapshots until we see us self as connected
-						if(recived_snapshots <= 2)
-						{
-							snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
-							snapshots[SNAP_CURRENT] = snap;
-						}
-						
 						if(recived_snapshots == 2)
 						{
+							snapshots[SNAP_PREV] = snapshot_storage.first;
+							snapshots[SNAP_CURRENT] = snapshot_storage.last;
 							local_start_time = time_get();
 							client_set_state(CLIENTSTATE_ONLINE);
 						}
-						
+
 						int64 now = time_get();
 						int64 t = now - game_tick*time_freq()/50;
 						if(game_start_time == -1 || t < game_start_time)
@@ -762,18 +665,18 @@ static void client_process_packet(NETPACKET *packet)
 
 static void client_pump_network()
 {
-	net.update();
+	netclient_update(net);
 
 	// check for errors		
-	if(client_state() != CLIENTSTATE_OFFLINE && net.state() == NETSTATE_OFFLINE)
+	if(client_state() != CLIENTSTATE_OFFLINE && netclient_state(net) == NETSTATE_OFFLINE)
 	{
 		// TODO: add message to the user there
 		client_set_state(CLIENTSTATE_OFFLINE);
-		dbg_msg("client", "offline error='%s'", net.error_string());
+		dbg_msg("client", "offline error='%s'", netclient_error_string(net));
 	}
 
 	//
-	if(client_state() == CLIENTSTATE_CONNECTING && net.state() == NETSTATE_ONLINE)
+	if(client_state() == CLIENTSTATE_CONNECTING && netclient_state(net) == NETSTATE_ONLINE)
 	{
 		// we switched to online
 		dbg_msg("client", "connected, sending info");
@@ -783,7 +686,7 @@ static void client_pump_network()
 	
 	// process packets
 	NETPACKET packet;
-	while(net.recv(&packet))
+	while(netclient_recv(net, &packet))
 		client_process_packet(&packet);
 }
 
@@ -818,7 +721,7 @@ static void client_run(const char *direct_connect_server)
 	// open socket
 	NETADDR4 bindaddr;
 	mem_zero(&bindaddr, sizeof(bindaddr));
-	net.open(bindaddr, 0);
+	net = netclient_open(bindaddr, 0);
 	
 	//
 	net_host_lookup(config.masterserver, MASTERSERVER_PORT, &master_server);
@@ -827,8 +730,6 @@ static void client_run(const char *direct_connect_server)
 	if(direct_connect_server)
 		client_connect(direct_connect_server);
 		
-	//int64 inputs_per_second = 50;
-	//int64 time_per_input = time_freq()/inputs_per_second;
 	int64 game_starttime = time_get();
 	int64 last_input = game_starttime;
 	
@@ -836,7 +737,7 @@ static void client_run(const char *direct_connect_server)
 	int64 reportinterval = time_freq()*1;
 	int frames = 0;
 	
-	input::set_mouse_mode(input::mode_relative);
+	inp_mouse_mode_relative();
 	
 	while (1)
 	{	
@@ -849,7 +750,7 @@ static void client_run(const char *direct_connect_server)
 			int64 now = time_get();
 			while(1)
 			{
-				snapshot_info *cur = snapshots[SNAP_CURRENT];
+				SNAPSTORAGE_HOLDER *cur = snapshots[SNAP_CURRENT];
 				int64 tickstart = game_start_time + (cur->tick+1)*time_freq()/50;
 				int64 t = tickstart;
 				if(latency > 0)
@@ -857,7 +758,7 @@ static void client_run(const char *direct_connect_server)
 
 				if(t < now)
 				{
-					snapshot_info *next = snapshots[SNAP_CURRENT]->next;
+					SNAPSTORAGE_HOLDER *next = snapshots[SNAP_CURRENT]->next;
 					if(next)
 					{
 						snapshots[SNAP_PREV] = snapshots[SNAP_CURRENT];
@@ -913,12 +814,12 @@ static void client_run(const char *direct_connect_server)
 		inp_update();
 		
 		// refocus
+		// TODO: fixme
+		
 		if(!gfx_window_active())
 		{
 			if(window_must_refocus == 0)
-			{
-				input::set_mouse_mode(input::mode_absolute);
-			}
+				inp_mouse_mode_absolute();
 			window_must_refocus = 1;
 		}
 
@@ -926,13 +827,13 @@ static void client_run(const char *direct_connect_server)
 		{
 			if(window_must_refocus < 3)
 			{
-				input::set_mouse_mode(input::mode_absolute);
+				inp_mouse_mode_absolute();
 				window_must_refocus++;
 			}
 
-			if(inp_button_pressed(input::mouse_1))
+			if(inp_key_pressed(KEY_MOUSE_1))
 			{
-				input::set_mouse_mode(input::mode_relative);
+				inp_mouse_mode_relative();
 				window_must_refocus = 0;
 			}
 		}
@@ -944,15 +845,15 @@ static void client_run(const char *direct_connect_server)
 		// panic button
 		if(config.debug)
 		{
-			if(input::pressed(input::f1))
-				input::set_mouse_mode(input::mode_absolute);
-			if(input::pressed(input::f2))
-				input::set_mouse_mode(input::mode_relative);
+			if(inp_key_pressed(KEY_F1))
+				inp_mouse_mode_absolute();
+			if(inp_key_pressed(KEY_F2))
+				inp_mouse_mode_relative();
 
-			if(input::pressed(input::lctrl) && input::pressed('Q'))
+			if(inp_key_pressed(KEY_LCTRL) && inp_key_pressed('Q'))
 				break;
 		
-			if(input::pressed(input::f5))
+			if(inp_key_pressed(KEY_F5))
 			{
 				// ack snapshot
 				msg_pack_start_system(NETMSG_SNAPACK, 0);
@@ -996,7 +897,7 @@ static void client_run(const char *direct_connect_server)
 			if(config.debug)
 			{
 				dbg_msg("client/report", "fps=%.02f netstate=%d",
-					frames/(float)(reportinterval/time_freq()), net.state());
+					frames/(float)(reportinterval/time_freq()), netclient_state(net));
 			}
 			frames = 0;
 			reporttime += reportinterval;
@@ -1032,7 +933,8 @@ int main(int argc, char **argv)
 	const char *config_filename = "default.cfg";
 #endif
 
-	for(int i = 1; i < argc; i++)
+	int i;
+	for(i = 1; i < argc; i++)
 	{
 		if(argv[i][0] == '-' && argv[i][1] == 'f' && argv[i][2] == 0 && argc - i > 1)
 		{
@@ -1045,13 +947,13 @@ int main(int argc, char **argv)
 
 	const char *direct_connect_server = 0x0;
 	snd_set_master_volume(config.volume / 255.0f);
-	bool editor = false;
+	int editor = 0;
 
 	// init network, need to be done first so we can do lookups
 	net_init();
 
 	// parse arguments
-	for(int i = 1; i < argc; i++)
+	for(i = 1; i < argc; i++)
 	{
 		if(argv[i][0] == '-' && argv[i][1] == 'c' && argv[i][2] == 0 && argc - i > 1)
 		{
@@ -1061,7 +963,7 @@ int main(int argc, char **argv)
 		}
 		else if(argv[i][0] == '-' && argv[i][1] == 'e' && argv[i][2] == 0)
 		{
-			editor = true;
+			editor = 1;
 		}
 		else
 			config_set(argv[i]);
diff --git a/src/engine/client/gfx.cpp b/src/engine/client/gfx.c
index 6a096139..b48740b6 100644
--- a/src/engine/client/gfx.cpp
+++ b/src/engine/client/gfx.c
@@ -1,38 +1,41 @@
-#include <baselib/opengl.h>
-#include <baselib/math.h>
-#include <baselib/vmath.h>
-#include <baselib/stream/file.h>
 
-#include <engine/interface.h>
+#include <engine/external/glfw/include/GL/glfw.h>
+#include <engine/external/pnglite/pnglite.h>
 
-#include "pnglite/pnglite.h"
+#include <engine/system.h>
+#include <engine/interface.h>
+#include <engine/config.h>
+#include <engine/keys.h>
 
 #include <string.h>
 #include <stdio.h>
+#include <math.h>
 
-#include <engine/config.h>
-
+// compressed textures
+#define GL_COMPRESSED_RGB_ARB 0x84ED
+#define GL_COMPRESSED_RGBA_ARB 0x84EE
 
-using namespace baselib;
+//
+typedef struct { float x, y, z; } VEC3;
+typedef struct { float u, v; } TEXCOORD;
+typedef struct { float r, g, b, a; } COLOR;
 
-static opengl::context context;
-
-struct custom_vertex
+typedef struct
 {
-	vec3 pos;
-	vec2 tex;
-	vec4 color;
-};
+	VEC3 pos;
+	TEXCOORD tex;
+	COLOR color;
+} VERTEX;
 
 const int vertex_buffer_size = 32*1024;
-static custom_vertex *vertices = 0;
+static VERTEX *vertices = 0;
 static int num_vertices = 0;
-static vec4 color[4];
-static vec2 texture[4];
+
+static COLOR color[4];
+static TEXCOORD texture[4];
 
 static int do_screenshot = 0;
 
-static opengl::vertex_buffer vertex_buffer;
 static int screen_width = -1;
 static int screen_height = -1;
 static float rotation = 0;
@@ -43,17 +46,21 @@ static float screen_y0 = 0;
 static float screen_x1 = 0;
 static float screen_y1 = 0;
 
-struct texture_holder
+typedef struct
 {
-	opengl::texture tex;
+	GLuint tex;
 	int memsize;
 	int flags;
 	int next;
-};
+} TEXTURE;
 
-static const int MAX_TEXTURES = 128;
 
-static texture_holder textures[MAX_TEXTURES];
+enum
+{
+	MAX_TEXTURES = 128
+};
+
+static TEXTURE textures[MAX_TEXTURES];
 static int first_free_texture;
 static int memory_usage = 0;
 
@@ -64,7 +71,7 @@ static const unsigned char null_texture_data[] = {
 	0x00,0x00,0xff,0xff, 0x00,0x00,0xff,0xff, 0xff,0xff,0x00,0xff, 0xff,0xff,0x00,0xff, 
 };
 
-static void draw_quad(bool _bflush = false)
+static void draw_quad(int _bflush)
 {
 	if (!_bflush && ((num_vertices + 4) < vertex_buffer_size))
 	{
@@ -80,33 +87,15 @@ static void draw_quad(bool _bflush = false)
 		//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 
-		/*
-		if(GLEW_ARB_vertex_buffer_object)
-		{
-			// set the data
-			vertex_buffer.data(vertices, num_vertices * sizeof(custom_vertex), GL_DYNAMIC_DRAW);
-			opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0);
-			opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT,
-					sizeof(custom_vertex),
-					sizeof(vec3));
-			opengl::stream_color(&vertex_buffer, 4, GL_FLOAT,
-					sizeof(custom_vertex),
-					sizeof(vec3)+sizeof(vec2));		
-					
-			//glDrawElements(GL_TRIANGLES, num_vertices, GL_UNSIGNED_SHORT, indecies);
-			opengl::draw_arrays(GL_QUADS, 0, num_vertices);
-		}
-		else
-		{*/
 		glVertexPointer(3, GL_FLOAT,
-				sizeof(custom_vertex),
+				sizeof(VERTEX),
 				(char*)vertices);
 		glTexCoordPointer(2, GL_FLOAT,
-				sizeof(custom_vertex),
-				(char*)vertices + sizeof(vec3));
+				sizeof(VERTEX),
+				(char*)vertices + sizeof(float)*3);
 		glColorPointer(4, GL_FLOAT,
-				sizeof(custom_vertex),
-				(char*)vertices + sizeof(vec3) + sizeof(vec2));
+				sizeof(VERTEX),
+				(char*)vertices + sizeof(float)*5);
 		glEnableClientState(GL_VERTEX_ARRAY);
 		glEnableClientState(GL_TEXTURE_COORD_ARRAY);
 		glEnableClientState(GL_COLOR_ARRAY);
@@ -117,11 +106,13 @@ static void draw_quad(bool _bflush = false)
 	}
 }
 
-bool gfx_init()
+int gfx_init()
 {
 	screen_width = config.gfx_screen_width;
 	screen_height = config.gfx_screen_height;
 
+	glfwInit();
+
 	if(config.stress)
 	{
 		screen_width = 320;
@@ -130,31 +121,33 @@ bool gfx_init()
 	
 	if(config.gfx_fullscreen)
 	{
-		if(!context.create(screen_width, screen_height, 24, 0, 0, 0, opengl::context::FLAG_FULLSCREEN))
+		int result = glfwOpenWindow(screen_width, screen_height, 8, 8, 8, 0, 0, 0, GLFW_FULLSCREEN);
+		if(result != GL_TRUE)
 		{
 			dbg_msg("game", "failed to create gl context");
-			return false;
+			return 0;
 		}
 	}
 	else
 	{
-		if(!context.create(screen_width, screen_height, 0, 0, 0, 0, 0))
+		int result = glfwOpenWindow(screen_width, screen_height, 0, 0, 0, 0, 0, 0, GLFW_WINDOW);
+		if(result != GL_TRUE)
 		{
 			dbg_msg("game", "failed to create gl context");
-			return false;
+			return 0;
 		}
 	}
 	
-	context.set_title("Teewars");
+	glfwSetWindowTitle("Teewars");
 	
 	// We don't want to see the window when we run the stress testing
 	if(config.stress)
-		context.iconify();
+		glfwIconifyWindow();
 	
 	// Init vertices
 	if (vertices)
 		mem_free(vertices);
-	vertices = (custom_vertex*)mem_alloc(sizeof(custom_vertex) * vertex_buffer_size, 1);
+	vertices = (VERTEX*)mem_alloc(sizeof(VERTEX) * vertex_buffer_size, 1);
 	num_vertices = 0;
 
 
@@ -169,49 +162,26 @@ bool gfx_init()
 	glEnable(GL_BLEND);
 	
 	// model
-	mat4 mat = mat4::identity;
-	opengl::matrix_modelview(&mat);
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
 	
 	// Set all z to -5.0f
-	for (int i = 0; i < vertex_buffer_size; i++)
+	int i;
+	for (i = 0; i < vertex_buffer_size; i++)
 		vertices[i].pos.z = -5.0f;
 
-/*
-	if(GLEW_ARB_vertex_buffer_object)
-	{
-		// set the streams
-		vertex_buffer.data(vertices, sizeof(vertex_buffer_size), GL_DYNAMIC_DRAW);
-		opengl::stream_vertex(&vertex_buffer, 3, GL_FLOAT, sizeof(custom_vertex), 0);
-		opengl::stream_texcoord(&vertex_buffer, 0, 2, GL_FLOAT,
-				sizeof(custom_vertex),
-				sizeof(vec3));
-		opengl::stream_color(&vertex_buffer, 4, GL_FLOAT,
-				sizeof(custom_vertex),
-				sizeof(vec3)+sizeof(vec2));		
-	}*/
-
 	// init textures
 	first_free_texture = 0;
-	for(int i = 0; i < MAX_TEXTURES; i++)
+	for(i = 0; i < MAX_TEXTURES; i++)
 		textures[i].next = i+1;
 	textures[MAX_TEXTURES-1].next = -1;
 	
-	// init indecies
-	/*
-	for(int i = 0; i < vertex_buffer_size; i++)
-	{
-		indecies[i*6 + 0] = i+0;
-		indecies[i*6 + 1] = i+1;
-		indecies[i*6 + 2] = i+2;
-		
-		indecies[i*6 + 3] = i+1;
-		indecies[i*6 + 4] = i+3;
-		indecies[i*6 + 5] = i+2;
-	}*/
-	
 	//glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR_MIPMAP_LINEAR);
 	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
 	gfx_load_texture_raw(4,4,IMG_RGBA,null_texture_data);
@@ -219,17 +189,17 @@ bool gfx_init()
 	// set vsync as needed
 	gfx_set_vsync(config.gfx_vsync);
 
-	return true;
+	return 1;
 }
 
 
 int gfx_window_active()
 {
-	return context.active()?1:0;
+	return glfwGetWindowParam(GLFW_ACTIVE) == GL_TRUE ? 1 : 0;
 }
 
 
-video_mode fakemodes[] = {
+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},
@@ -253,25 +223,28 @@ video_mode fakemodes[] = {
 	{2048,1536,5,6,5}
 };
 
-int gfx_get_video_modes(video_mode *list, int maxcount)
+int gfx_get_video_modes(VIDEO_MODE *list, int maxcount)
 {
 	if(config.gfx_display_all_modes)
 	{
 		mem_copy(list, fakemodes, sizeof(fakemodes));
-		return min((int)(sizeof(fakemodes)/sizeof(video_mode)), maxcount);
+		int count = sizeof(fakemodes)/sizeof(VIDEO_MODE);
+		if(maxcount < count)
+			count = maxcount;
+		return count;
 	}
 	
-	return context.getvideomodes((opengl::videomode *)list, maxcount);
+	return glfwGetVideoModes((GLFWvidmode *)list, maxcount);
 }
 
 void gfx_set_vsync(int val)
 {
-	context.set_vsync(val);
+	glfwSwapInterval(val);
 }
 
 int gfx_unload_texture(int index)
 {
-	textures[index].tex.clear();
+	glDeleteTextures(1, &textures[index].tex);
 	textures[index].next = first_free_texture;
 	memory_usage -= textures[index].memsize;
 	first_free_texture = index;
@@ -302,7 +275,7 @@ static unsigned char sample(int w, int h, const unsigned char *data, int u, int
 
 int gfx_load_texture_raw(int w, int h, int format, const void *data)
 {
-	bool mipmap = true;
+	int mipmap = 1;
 	
 	// grab texture
 	int tex = first_free_texture;
@@ -320,8 +293,9 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data)
 			h/=2;
 			unsigned char *tmpdata = (unsigned char *)mem_alloc(w*h*4, 1);
 			int c = 0;
-			for(int y = 0; y < h; y++)
-				for(int x = 0; x < w; x++, c++)
+			int x, y;
+			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);
@@ -335,22 +309,28 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data)
 	if(config.debug)
 		dbg_msg("gfx", "%d = %dx%d", tex, w, h);
 	
-	// set data and return
-	if(config.gfx_texture_compression && GLEW_ARB_texture_compression)
+	// upload texture
+	int oglformat = 0;
+	if(config.gfx_texture_compression)
 	{
+		oglformat = GL_COMPRESSED_RGBA_ARB;
 		if(format == IMG_RGB)
-			textures[tex].tex.data2d(w, h, GL_COMPRESSED_RGB_ARB, GL_RGB, GL_UNSIGNED_BYTE, texdata);
-		else if(format == IMG_RGBA)
-			textures[tex].tex.data2d(w, h, GL_COMPRESSED_RGBA_ARB, GL_RGBA, GL_UNSIGNED_BYTE, texdata);
+			oglformat = GL_COMPRESSED_RGB_ARB;
 	}
 	else
 	{
+		oglformat = GL_RGBA;
 		if(format == IMG_RGB)
-			textures[tex].tex.data2d(w, h, GL_RGB, GL_RGB, GL_UNSIGNED_BYTE, texdata);
-		else if(format == IMG_RGBA)
-			textures[tex].tex.data2d(w, h, GL_RGBA, GL_RGBA, GL_UNSIGNED_BYTE, texdata);
+			oglformat = GL_RGB;
 	}
+		
+	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_LINEAR);
+	gluBuild2DMipmaps(GL_TEXTURE_2D, oglformat, w, h, oglformat, GL_UNSIGNED_BYTE, texdata);
 	
+	// calculate memory usage
 	textures[tex].memsize = w*h*4;
 	if(mipmap)
 	{
@@ -363,9 +343,7 @@ int gfx_load_texture_raw(int w, int h, int format, const void *data)
 	}
 	
 	memory_usage += textures[tex].memsize;
-	
 	mem_free(tmpdata);
-	
 	return tex;
 }
 /*
@@ -403,7 +381,7 @@ int gfx_load_texture(const char *filename)
 	int l = strlen(filename);
 	if(l < 3)
 		return 0;
-	image_info img;
+	IMAGE_INFO img;
 	if(gfx_load_png(&img, filename))
 	{
 		int id = gfx_load_texture_raw(img.width, img.height, img.format, img.data);
@@ -414,7 +392,7 @@ int gfx_load_texture(const char *filename)
 	return 0;
 }
 
-int gfx_load_png(image_info *img, const char *filename)
+int gfx_load_png(IMAGE_INFO *img, const char *filename)
 {
 	// open file for reading
 	png_init(0,0);
@@ -450,7 +428,8 @@ void gfx_shutdown()
 {
 	if (vertices)
 		mem_free(vertices);
-	context.destroy();
+	glfwCloseWindow();
+	glfwTerminate();
 }
 
 void gfx_screenshot()
@@ -470,7 +449,8 @@ void gfx_swap()
 		glReadPixels(0,0, w, h, GL_RGB, GL_UNSIGNED_BYTE, pixel_data);
 		
 		// flip the pixel because opengl works from bottom left corner
-		for(int y = 0; y < h/2; y++)
+		int y;
+		for(y = 0; y < h/2; y++)
 		{
 			mem_copy(temp_row, pixel_data+y*w*3, w*3);
 			mem_copy(pixel_data+y*w*3, pixel_data+(h-y-1)*w*3, w*3);
@@ -503,7 +483,8 @@ void gfx_swap()
 		do_screenshot = 0;
 	}
 	
-	context.swap();
+	glfwSwapBuffers();
+	glfwPollEvents();
 }
 
 int gfx_screenwidth()
@@ -520,15 +501,18 @@ void gfx_texture_set(int slot)
 {
 	dbg_assert(quads_drawing == 0, "called gfx_texture_set within quads_begin");
 	if(slot == -1)
-		opengl::texture_disable(0);
+		glDisable(GL_TEXTURE_2D);
 	else
-		opengl::texture_2d(0, &textures[slot].tex);
+	{
+		glEnable(GL_TEXTURE_2D);
+		glBindTexture(GL_TEXTURE_2D, textures[slot].tex);
+	}
 }
 
 void gfx_clear(float r, float g, float b)
 {
 	glClearColor(r,g,b,1.0f);
-	opengl::clear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
+	glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT);
 }
 
 void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y)
@@ -537,9 +521,9 @@ void gfx_mapscreen(float tl_x, float tl_y, float br_x, float br_y)
 	screen_y0 = tl_y;
 	screen_x1 = br_x;
 	screen_y1 = br_y;
-	mat4 mat;
-	mat.ortho(tl_x, br_x, br_y, tl_y, 1.0f, 10.f);
-	opengl::matrix_projection(&mat);
+	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)
@@ -552,20 +536,19 @@ void gfx_getscreen(float *tl_x, float *tl_y, float *br_x, float *br_y)
 
 void gfx_setoffset(float x, float y)
 {
-	//const float scale = 0.75f;
-	const float scale = 1.0f;
-	mat4 mat = mat4::identity;
-	mat.m[0] = scale;
-	mat.m[5] = scale;
-	mat.m[10] = scale;
-	mat.m[12] = x*scale;
-	mat.m[13] = y*scale;
-	opengl::matrix_modelview(&mat);
+	//const float scale = 1.0f;
+	//mat4 mat = mat4::identity;
+	//mat.m[0] = scale;
+	//mat.m[5] = scale;
+	//mat.m[10] = scale;
+	//mat.m[12] = x*scale;
+	//mat.m[13] = y*scale;
+	glMatrixMode(GL_MODELVIEW);
+	glLoadIdentity();
+	glTranslatef(x, y, 0);
 }
 
 
-
-
 void gfx_quads_begin()
 {
 	dbg_assert(quads_drawing == 0, "called quads_begin twice");
@@ -579,7 +562,7 @@ void gfx_quads_begin()
 void gfx_quads_end()
 {
 	dbg_assert(quads_drawing == 1, "called quads_end without quads_begin");
-	draw_quad(true);
+	draw_quad(1);
 	quads_drawing--;
 }
 
@@ -602,42 +585,43 @@ void gfx_quads_setcolorvertex(int i, float r, float g, float b, float a)
 void gfx_quads_setcolor(float r, float g, float b, float a)
 {
 	dbg_assert(quads_drawing == 1, "called gfx_quads_setcolor without quads_begin");
-	color[0] = vec4(r,g,b,a);
-	color[1] = vec4(r,g,b,a);
-	color[2] = vec4(r,g,b,a);
-	color[3] = vec4(r,g,b,a);
+	gfx_quads_setcolorvertex(0, r, g, b, a);
+	gfx_quads_setcolorvertex(1, r, g, b, a);
+	gfx_quads_setcolorvertex(2, r, g, b, a);
+	gfx_quads_setcolorvertex(3, r, g, b, a);
 }
 
 void gfx_quads_setsubset(float tl_u, float tl_v, float br_u, float br_v)
 {
 	dbg_assert(quads_drawing == 1, "called gfx_quads_setsubset without quads_begin");
 
-	texture[0].x = tl_u;
-	texture[0].y = tl_v;
+	texture[0].u = tl_u;
+	texture[0].v = tl_v;
 	//g_pVertices[g_iVertexEnd].tex.u = tl_u;
 	//g_pVertices[g_iVertexEnd].tex.v = tl_v;
 
-	texture[1].x = br_u;
-	texture[1].y = tl_v;
+	texture[1].u = br_u;
+	texture[1].v = tl_v;
 	//g_pVertices[g_iVertexEnd + 2].tex.u = br_u;
 	//g_pVertices[g_iVertexEnd + 2].tex.v = tl_v;
 
-	texture[2].x = br_u;
-	texture[2].y = br_v;
+	texture[2].u = br_u;
+	texture[2].v = br_v;
 	//g_pVertices[g_iVertexEnd + 1].tex.u = tl_u;
 	//g_pVertices[g_iVertexEnd + 1].tex.v = br_v;
 
-	texture[3].x = tl_u;
-	texture[3].y = br_v;
+	texture[3].u = tl_u;
+	texture[3].v = br_v;
 	//g_pVertices[g_iVertexEnd + 3].tex.u = br_u;
 	//g_pVertices[g_iVertexEnd + 3].tex.v = br_v;
 }
 
-static void rotate(vec3 &center, vec3 &point)
+static void rotate(VEC3 *center, VEC3 *point)
 {
-	vec3 p = point-center;
-	point.x = p.x * cosf(rotation) - p.y * sinf(rotation) + center.x;
-	point.y = p.x * sinf(rotation) + p.y * cosf(rotation) + center.y;
+	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)
@@ -649,40 +633,36 @@ void gfx_quads_drawTL(float x, float y, float width, float height)
 {
 	dbg_assert(quads_drawing == 1, "called quads_draw without quads_begin");
 	
-	vec3 center;
+	VEC3 center;
 	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.u = texture[0].x;
-	vertices[num_vertices].tex.v = texture[0].y;
+	vertices[num_vertices].tex = texture[0];
 	vertices[num_vertices].color = color[0];
-	rotate(center, vertices[num_vertices].pos);
+	rotate(&center, &vertices[num_vertices].pos);
 
 	vertices[num_vertices + 1].pos.x = x+width;
 	vertices[num_vertices + 1].pos.y = y;
-	vertices[num_vertices + 1].tex.u = texture[1].x;
-	vertices[num_vertices + 1].tex.v = texture[1].y;
+	vertices[num_vertices + 1].tex = texture[1];
 	vertices[num_vertices + 1].color = color[1];
-	rotate(center, vertices[num_vertices + 1].pos);
+	rotate(&center, &vertices[num_vertices + 1].pos);
 
 	vertices[num_vertices + 2].pos.x = x + width;
 	vertices[num_vertices + 2].pos.y = y+height;
-	vertices[num_vertices + 2].tex.u = texture[2].x;
-	vertices[num_vertices + 2].tex.v = texture[2].y;
+	vertices[num_vertices + 2].tex = texture[2];
 	vertices[num_vertices + 2].color = color[2];
-	rotate(center, vertices[num_vertices + 2].pos);
+	rotate(&center, &vertices[num_vertices + 2].pos);
 
 	vertices[num_vertices + 3].pos.x = x;
 	vertices[num_vertices + 3].pos.y = y+height;
-	vertices[num_vertices + 3].tex.u = texture[3].x;
-	vertices[num_vertices + 3].tex.v = texture[3].y;
+	vertices[num_vertices + 3].tex = texture[3];
 	vertices[num_vertices + 3].color = color[3];
-	rotate(center, vertices[num_vertices + 3].pos);
+	rotate(&center, &vertices[num_vertices + 3].pos);
 	
-	draw_quad();
+	draw_quad(0);
 }
 
 void gfx_quads_draw_freeform(
@@ -695,29 +675,25 @@ void gfx_quads_draw_freeform(
 	
 	vertices[num_vertices].pos.x = x0;
 	vertices[num_vertices].pos.y = y0;
-	vertices[num_vertices].tex.u = texture[0].x;
-	vertices[num_vertices].tex.v = texture[0].y;
+	vertices[num_vertices].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.u = texture[1].x;
-	vertices[num_vertices + 1].tex.v = texture[1].y;
+	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.u = texture[2].x;
-	vertices[num_vertices + 2].tex.v = texture[2].y;
+	vertices[num_vertices + 2].tex = texture[2];
 	vertices[num_vertices + 2].color = color[2];
 
 	vertices[num_vertices + 3].pos.x = x2;
 	vertices[num_vertices + 3].pos.y = y2;
-	vertices[num_vertices + 3].tex.u = texture[3].x;
-	vertices[num_vertices + 3].tex.v = texture[3].y;
+	vertices[num_vertices + 3].tex = texture[3];
 	vertices[num_vertices + 3].color = color[3];
 	
-	draw_quad();
+	draw_quad(0);
 }
 
 void gfx_quads_text(float x, float y, float size, const char *text)
@@ -750,12 +726,12 @@ void gfx_quads_text(float x, float y, float size, const char *text)
 	gfx_quads_end();
 }
 
-struct pretty_font
+typedef struct
 {
 	float m_CharStartTable[256];
 	float m_CharEndTable[256];
 	int font_texture;
-};
+} pretty_font;
 
 pretty_font default_font = 
 {
diff --git a/src/engine/client/inp.c b/src/engine/client/inp.c
new file mode 100644
index 00000000..6583c53f
--- /dev/null
+++ b/src/engine/client/inp.c
@@ -0,0 +1,95 @@
+#include <engine/external/glfw/include/GL/glfw.h>
+
+#include <engine/system.h>
+#include <engine/interface.h>
+
+static int keyboard_state[2][1024]; // TODO: fix this!!
+static int keyboard_current = 0;
+static int keyboard_first = 1;
+
+void inp_mouse_relative(int *x, int *y)
+{
+	static int last_x = 0, last_y = 0;
+	int nx, ny;
+	glfwGetMousePos(&nx, &ny);
+	*x = nx-last_x;
+	*y = ny-last_y;
+	last_x = nx;
+	last_y = ny;
+}
+
+static char last_c = 0;
+static int last_k = 0;
+
+static void char_callback(int character, int action)
+{
+	if(action == GLFW_PRESS && character < 256)
+	last_c = (char)character;
+}
+
+static void key_callback(int key, int action)
+{
+    if(action == GLFW_PRESS)
+	    last_k = key;
+}
+
+void inp_init()
+{
+	glfwEnable(GLFW_KEY_REPEAT);
+	glfwSetCharCallback(char_callback);
+	glfwSetKeyCallback(key_callback);
+}
+
+char inp_last_char()
+{
+	return last_c;
+}
+
+int inp_last_key()
+{
+	return last_k;
+}
+
+void inp_clear()
+{
+	last_k = 0;
+	last_c = 0;
+}
+
+void inp_mouse_mode_absolute()
+{
+	glfwEnable(GLFW_MOUSE_CURSOR);
+}
+
+void inp_mouse_mode_relative()
+{
+	glfwDisable(GLFW_MOUSE_CURSOR);
+}
+
+//int inp_mouse_scroll() { return input::mouse_scroll(); }
+int inp_key_pressed(int key) { return keyboard_state[keyboard_current][key]; }
+int inp_key_was_pressed(int key) { return keyboard_state[keyboard_current^1][key]; }
+int inp_key_down(int key) { return inp_key_pressed(key)&&!inp_key_was_pressed(key); }
+int inp_button_pressed(int button) { return keyboard_state[keyboard_current][button]; }
+
+void inp_update()
+{
+    if(keyboard_first)
+    {
+        // make sure to reset
+        keyboard_first = 0;
+        inp_update();
+    }
+
+    keyboard_current = keyboard_current^1;
+    int i, v;
+    for(i = 0; i < KEY_LAST; i++)
+    {
+	    if (i >= KEY_MOUSE_FIRST)
+			v = glfwGetMouseButton(i-KEY_MOUSE_FIRST) == GLFW_PRESS ? 1 : 0;
+		else
+			v = glfwGetKey(i) == GLFW_PRESS ? 1 : 0;
+        keyboard_state[keyboard_current][i] = v;
+    }
+
+}
diff --git a/src/engine/client/pnglite/pnglite.c b/src/engine/client/pnglite/pnglite.c
deleted file mode 100644
index b33f60ba..00000000
--- a/src/engine/client/pnglite/pnglite.c
+++ /dev/null
@@ -1,877 +0,0 @@
-/*  pnglite.c - pnglite library

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

-*/

-#define DO_CRC_CHECKS 1

-#define USE_ZLIB 1

-

-#if USE_ZLIB

-#include <zlib.h>

-#else

-#include "zlite.h"

-#endif

-

-#include <stdio.h>

-#include <stdlib.h>

-#include <string.h>

-#include "pnglite.h"

-

-

-

-static png_alloc_t png_alloc;

-static png_free_t png_free;

-

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

-{

-	size_t result;

-	if(png->read_fun)

-	{

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

-	}

-	else

-	{

-		if(!out)

-		{

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

-		}

-		else

-		{

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

-		}

-	}

-

-	return result;

-}

-

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

-{

-	size_t result;

-

-	if(png->write_fun)

-	{

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

-	}

-	else

-	{

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

-	}

-

-	return result;

-}

-

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

-{

-	unsigned char buf[4];

-

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

-		return PNG_FILE_ERROR;

-

-	*out = (buf[0]<<24) | (buf[1]<<16) | (buf[2]<<8) | buf[3];

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	unsigned char buf[4];

-

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

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

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

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

-

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

-		return PNG_FILE_ERROR;

-

-	return PNG_NO_ERROR;

-}

-	

-

-static unsigned get_ul(unsigned char* buf)

-{

-	unsigned result;

-	unsigned char foo[4];

-

-	memcpy(foo, buf, 4);

-

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

-

-	return result;

-}

-

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

-{

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

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

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

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

-

-	return PNG_NO_ERROR;

-}

-

-int png_init(png_alloc_t pngalloc, png_free_t pngfree)

-{

-	if(pngalloc)

-		png_alloc = pngalloc;

-	else

-		png_alloc = &malloc;

-

-	if(pngfree)

-		png_free = pngfree;

-	else

-		png_free = &free;

-

-	return PNG_NO_ERROR;

-}

-

-static int png_get_bpp(png_t* png)

-{

-	int bpp;

-

-	switch(png->color_type)

-	{

-	case PNG_GREYSCALE:

-		bpp = 1; break;

-	case PNG_TRUECOLOR:

-		bpp = 3; break;

-	case PNG_INDEXED:

-		bpp = 1; break;

-	case PNG_GREYSCALE_ALPHA:

-		bpp = 2; break;

-	case PNG_TRUECOLOR_ALPHA:

-		bpp = 4; break;

-	default:

-		return PNG_FILE_ERROR;

-	}

-

-	bpp *= png->depth/8;

-

-	return bpp;

-}

-

-static int png_read_ihdr(png_t* png)

-{

-	unsigned length;

-#if DO_CRC_CHECKS

-	unsigned orig_crc;

-	unsigned calc_crc;

-#endif

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

-

-	file_read_ul(png, &length);

-

-	if(length != 13)

-	{

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

-		return PNG_CRC_ERROR;

-	}

-

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

-		return PNG_EOF_ERROR;

-#if DO_CRC_CHECKS

-	file_read_ul(png, &orig_crc);

-

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

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

-

-	if(orig_crc != calc_crc)

-		return PNG_CRC_ERROR;

-#else

-	file_read_ul(png);

-#endif

-

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

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

-	png->depth = ihdr[12];

-	png->color_type = ihdr[13];

-	png->compression_method = ihdr[14];

-	png->filter_method = ihdr[15];

-	png->interlace_method = ihdr[16];

-

-	if(png->color_type == PNG_INDEXED)

-		return PNG_NOT_SUPPORTED;

-

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

-		return PNG_NOT_SUPPORTED;

-

-	if(png->interlace_method)

-		return PNG_NOT_SUPPORTED;

-	

-	return PNG_NO_ERROR;

-}

-

-static int png_write_ihdr(png_t* png)

-{

-	unsigned char ihdr[13+4];

-	unsigned char *p = ihdr;

-	unsigned crc;

-	

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

-

-	file_write_ul(png, 13);

-    

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

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

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

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

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

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

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

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

-	*p = 0;				p++;

-	*p = 0;				p++;

-	*p = 0;				p++;

-

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

-

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

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

-

-	file_write_ul(png, crc);

-

-	return PNG_NO_ERROR;

-}

-

-void png_print_info(png_t* png)

-{

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

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

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

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

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

-

-	switch(png->color_type)

-	{

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

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

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

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

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

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

-	}

-

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

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

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

-}

-

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

-{

-	char header[8];

-	int result;

-

-	png->read_fun = read_fun;

-	png->write_fun = 0;

-	png->user_pointer = user_pointer;

-

-	if(!read_fun && !user_pointer)

-		return PNG_WRONG_ARGUMENTS;

-

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

-		return PNG_EOF_ERROR;

-

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

-		return PNG_HEADER_ERROR;

-

-	result = png_read_ihdr(png);

-

-	png->bpp = (unsigned char)png_get_bpp(png);

-

-	return result;

-}

-

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

-{

-	png->write_fun = write_fun;

-	png->read_fun = 0;

-	png->user_pointer = user_pointer;

-

-	if(!write_fun && !user_pointer)

-		return PNG_WRONG_ARGUMENTS;

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	return png_open_read(png, read_fun, user_pointer);

-}

-

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

-{

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

-

-	if(!fp)

-		return PNG_FILE_ERROR;

-

-	return png_open_read(png, 0, fp);

-}

-

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

-{

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

-

-	if(!fp)

-		return PNG_FILE_ERROR;

-

-	return png_open_write(png, 0, fp);

-}

-

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

-{

-	return png_open_file_read(png, filename);

-}

-

-int png_close_file(png_t* png)

-{

-	fclose(png->user_pointer);

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	z_stream *stream;

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

-

-	stream = png->zs;

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

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

-

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

-		return PNG_ZLIB_ERROR;

-

-	stream->next_in = data;

-	stream->avail_in = datalen;

-

-	return PNG_NO_ERROR;

-}

-

-static int png_init_inflate(png_t* png)

-{

-#if USE_ZLIB

-	z_stream *stream;

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

-#else

-	zl_stream *stream;

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

-#endif

-

-	stream = png->zs;

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

-	

-

-#if USE_ZLIB

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

-	if(inflateInit(stream) != Z_OK)

-		return PNG_ZLIB_ERROR;

-#else

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

-	if(z_inflateInit(stream) != Z_OK)

-		return PNG_ZLIB_ERROR;

-#endif

-

-	stream->next_out = png->png_data;

-	stream->avail_out = png->png_datalen;

-

-	return PNG_NO_ERROR;

-}

-

-static int png_end_deflate(png_t* png)

-{

-	z_stream *stream = png->zs;

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

-	deflateEnd(stream);

-

-	png_free(png->zs);

-

-	return PNG_NO_ERROR;

-}

-

-static int png_end_inflate(png_t* png)

-{

-#if USE_ZLIB

-	z_stream *stream = png->zs;

-#else

-	zl_stream *stream = png->zs;

-#endif

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

-#if USE_ZLIB

-	if(inflateEnd(stream) != Z_OK)

-#else

-	if(z_inflateEnd(stream) != Z_OK)

-#endif

-	{

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

-		return PNG_ZLIB_ERROR;

-	}

-

-	png_free(png->zs);

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	int result;

-#if USE_ZLIB

-	z_stream *stream = png->zs;

-#else

-	zl_stream *stream = png->zs;

-#endif

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

-	stream->next_in = (unsigned char*)data;

-	stream->avail_in = len;

-	

-#if USE_ZLIB

-	result = inflate(stream, Z_SYNC_FLUSH);

-#else

-	result = z_inflate(stream);

-#endif

-

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

-	{

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

-		return PNG_ZLIB_ERROR;

-	}

-

-	if(stream->avail_in != 0)

-		return PNG_ZLIB_ERROR;

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	int result;

-

-	z_stream *stream = png->zs;

-

-

-	if(!stream)

-		return PNG_MEMORY_ERROR;

-

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

-	stream->avail_out = outlen;

-

-	result = deflate(stream, Z_SYNC_FLUSH);

-

-	*outwritten = outlen - stream->avail_out;

-

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

-	{

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

-		return PNG_ZLIB_ERROR;

-	}

-

-	return result;

-}

-

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

-{

-	unsigned char *chunk;

-	unsigned long written;

-	unsigned long crc;

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

-	

-	(void)png_init_deflate;

-	(void)png_end_deflate;

-	(void)png_deflate;

-

-	chunk = png_alloc(size);

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

-	

-	written = size;

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

-	

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

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

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

-	file_write_ul(png, written);

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

-	png_free(chunk);

-

-	file_write_ul(png, 0);

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

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

-	file_write_ul(png, crc);

-	

-	return PNG_NO_ERROR;

-}

-

-static int png_read_idat(png_t* png, unsigned firstlen) 

-{

-	unsigned type = 0;

-	char *chunk;

-	int result;

-	unsigned length = firstlen;

-	unsigned old_len = length;

-

-#if DO_CRC_CHECKS

-	unsigned orig_crc;

-	unsigned calc_crc;

-#endif

-

-	chunk = png_alloc(firstlen); 

-

-	result = png_init_inflate(png);

-

-	if(result != PNG_NO_ERROR)

-	{

-		png_end_inflate(png);

-		png_free(chunk); 

-		return result;

-	}

-

-	do

-	{

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

-		{

-			png_end_inflate(png);

-			png_free(chunk); 

-			return PNG_FILE_ERROR;

-		}

-

-#if DO_CRC_CHECKS

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

-		calc_crc = crc32(calc_crc, (unsigned char*)"IDAT", 4);

-		calc_crc = crc32(calc_crc, (unsigned char*)chunk, length);

-

-		file_read_ul(png, &orig_crc);

-

-		if(orig_crc != calc_crc)

-		{

-			result = PNG_CRC_ERROR;

-			break;

-		}

-#else

-		file_read_ul(png);

-#endif

-

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

-

-		if(result != PNG_NO_ERROR) break;

-		

-		file_read_ul(png, &length);

-

-		if(length > old_len)

-		{

-			png_free(chunk); 

-			chunk = png_alloc(length); 

-			old_len = length;

-		}

-

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

-		{

-			result = PNG_FILE_ERROR;

-			break;

-		}

-

-	}while(type == *(unsigned int*)"IDAT");

-

-	if(type == *(unsigned int*)"IEND")

-		result = PNG_DONE;

-

-	png_free(chunk);

-	png_end_inflate(png);

-

-	return result;

-}

-

-static int png_process_chunk(png_t* png)

-{

-	int result = PNG_NO_ERROR;

-	unsigned type;

-	unsigned length;

-

-	file_read_ul(png, &length);

-

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

-		return PNG_FILE_ERROR;

-

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

-	{

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

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

-		

-		if(!png->png_data)

-			return PNG_MEMORY_ERROR;

-

-		return png_read_idat(png, length);

-	}

-	else if(type == *(unsigned int*)"IEND")

-	{

-		return PNG_DONE;

-	}

-	else

-	{

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

-	}

-

-	return result;

-}

-

-static void png_filter_sub(int stride, unsigned char* in, unsigned char* out, int len)

-{

-	int i;

-	unsigned char a = 0;

-

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

-	{

-		if(i >= stride)

-			a = out[i - stride];

-		

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

-	}

-}

-

-static void png_filter_up(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

-{

-	int i;

-

-	if(prev_line) 

-    { 

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

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

-    } 

-    else 

-        memcpy(out, in, len);

-}

-

-static void png_filter_average(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

-{

-	int i;

-	unsigned char a = 0;

-	unsigned char b = 0;

-	unsigned int sum = 0;

-

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

-	{

-		if(prev_line)

-			b = prev_line[i];

-

-		if(i >= stride)

-			a = out[i - stride];

-

-		sum = a;

-		sum += b;

-

-		out[i] = (char)(in[i] + sum/2);

-	}

-}

-

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

-{

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

-	int pa = abs(p - a);

-	int pb = abs(p - b);

-	int pc = abs(p - c);

-

-	int pr;

-

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

-		pr = a;

-	else if(pb <= pc)

-		pr = b;

-	else

-		pr = c;

-

-	return (char)pr;

-}

-

-static void png_filter_paeth(int stride, unsigned char* in, unsigned char* out, unsigned char* prev_line, int len)

-{

-	int i;

-	unsigned char a;

-	unsigned char b;

-	unsigned char c;

-

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

-	{

-		if(prev_line && i >= stride)

-		{

-			a = out[i - stride];

-			b = prev_line[i];

-			c = prev_line[i - stride];

-		}

-		else

-		{

-			if(prev_line)

-				b = prev_line[i];

-			else

-				b = 0;

-	

-			if(i >= stride)

-				a = out[i - stride];

-			else

-				a = 0;

-

-			c = 0;

-		}

-

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

-	}

-}

-

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

-{

-

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	unsigned i;

-	unsigned pos = 0;

-	unsigned outpos = 0;

-	unsigned char *filtered = png->png_data;

-

-	int stride = png->bpp;

-

-	while(pos < png->png_datalen)

-	{

-		unsigned char filter = filtered[pos];

-

-		pos++;

-

-		if(png->depth == 16)

-		{

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

-			{

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

-			}

-		}

-

-		switch(filter)

-		{

-		case 0: /* none */

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

-			break;

-		case 1: /* sub */

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

-			break;

-		case 2: /* up */

-			if(outpos)

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

-			else

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

-			break;

-		case 3: /* average */

-			if(outpos)

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

-			else

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

-			break;

-		case 4: /* paeth */

-			if(outpos)

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

-			else

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

-			break;

-		default:

-			return PNG_UNKNOWN_FILTER;

-		}

-

-		outpos += png->width * stride;

-		pos += png->width * stride;

-	}

-

-	return PNG_NO_ERROR;

-}

-

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

-{

-	int result = PNG_NO_ERROR;

-

-	while(result == PNG_NO_ERROR)

-	{

-		result = png_process_chunk(png);

-	}

-

-	if(result != PNG_DONE)

-	{

-		png_free(png->png_data); 

-		return result;

-	}

-

-	result = png_unfilter(png, data);

-

-	png_free(png->png_data); 

-

-	return result;

-}

-

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

-{

-	int i;

-	unsigned char *filtered;

-	png->width = width;

-	png->height = height;

-	png->depth = depth;

-	png->color_type = color;

-	png->bpp = png_get_bpp(png);

-

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

-

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

-	{

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

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

-	}

-

-	png_filter(png, filtered);

-	png_write_ihdr(png);

-	png_write_idats(png, filtered);

-	

-	png_free(filtered);

-	return PNG_NO_ERROR;

-}

-

-

-char* png_error_string(int error)

-{

-	switch(error)

-	{

-	case PNG_NO_ERROR:

-		return "No error";

-	case PNG_FILE_ERROR:

-		return "Unknown file error.";

-	case PNG_HEADER_ERROR:

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

-	case PNG_IO_ERROR:

-		return "Failure while reading file.";

-	case PNG_EOF_ERROR:

-		return "Reached end of file.";

-	case PNG_CRC_ERROR:

-		return "CRC or chunk length error.";

-	case PNG_MEMORY_ERROR:

-		return "Could not allocate memory.";

-	case PNG_ZLIB_ERROR:

-		return "zlib reported an error.";

-	case PNG_UNKNOWN_FILTER:

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

-	case PNG_DONE:

-		return "PNG done";

-	case PNG_NOT_SUPPORTED:

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

-	case PNG_WRONG_ARGUMENTS:

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

-	default:

-		return "Unknown error.";

-	};

-}

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

-	Copyright (c) 2007 Daniel Karling

-

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

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

-	arising from the use of this software.

-

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

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

-	freely, subject to the following restrictions:

-

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

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

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

-	   appreciated but is not required.  

-

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

-	   misrepresented as being the original software.

-

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

-	   distribution.

-

-	Daniel Karling

-	daniel.karling@gmail.com

- */

-

-

-#ifndef _PNGLITE_H_

-#define _PNGLITE_H_

-

-#ifdef __cplusplus

-extern "C"{

-#endif

-

-/*

-	Enumerations for pnglite.

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

-*/

-

-enum

-{

-	PNG_DONE				= 1,

-	PNG_NO_ERROR			= 0,

-	PNG_FILE_ERROR			= -1,

-	PNG_HEADER_ERROR		= -2,

-	PNG_IO_ERROR			= -3,

-	PNG_EOF_ERROR			= -4,

-	PNG_CRC_ERROR			= -5,

-	PNG_MEMORY_ERROR		= -6,

-	PNG_ZLIB_ERROR			= -7,

-	PNG_UNKNOWN_FILTER		= -8,

-	PNG_NOT_SUPPORTED		= -9,

-	PNG_WRONG_ARGUMENTS		= -10

-};

-

-/*

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

-*/

-

-enum

-{

-	PNG_GREYSCALE			= 0,

-	PNG_TRUECOLOR			= 2,

-	PNG_INDEXED				= 3,

-	PNG_GREYSCALE_ALPHA		= 4,

-	PNG_TRUECOLOR_ALPHA		= 6

-};

-

-/*

-	Typedefs for callbacks.

-*/

-

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

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

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

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

-

-typedef struct

-{

-	void*					zs;				/* pointer to z_stream */

-	png_read_callback_t		read_fun;

-	png_write_callback_t	write_fun;

-	void*					user_pointer;

-

-	unsigned char*			png_data;

-	unsigned				png_datalen;

-

-	unsigned				width;

-	unsigned				height;

-	unsigned char			depth;

-	unsigned char			color_type;

-	unsigned char			compression_method;

-	unsigned char			filter_method;

-	unsigned char			interlace_method;

-	unsigned char			bpp;

-}png_t;

-

-/*

-	Function: png_init

-

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

-

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

-	> void (*custom_free)(void* p)

-	Parameters:

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

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

-

-	Returns:

-		Always returns PNG_NO_ERROR.

-*/

-

-int png_init(png_alloc_t pngalloc, png_free_t pngfree);

-

-/*

-	Function: png_open_file

-

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

-	png_open if no custom read function is used.

-

-	Parameters:

-		png - Empty png_t struct.

-		filename - Filename of the file to be opened.

-

-	Returns:

-		PNG_NO_ERROR on success, otherwise an error code.

-*/

-

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

-

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

-int png_open_file_write(png_t *png, const char* filename);

-

-/*

-	Function: png_open

-

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

-

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

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

-

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

-

-	Writing:

-	The callback will be called like fwrite.

-

-	Reading:

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

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

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

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

-

-	Parameters:

-		png - png_t struct

-		read_fun - Callback function for reading.

-		user_pointer - User pointer to be passed to read_fun.

-

-	Returns:

-		PNG_NO_ERROR on success, otherwise an error code.

-*/

-

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

-

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

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

-

-/*

-	Function: png_print_info

-

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

-

-	Parameters:

-		png - png struct to get info from.

-*/

-

-void png_print_info(png_t* png);

-

-/*

-	Function: png_error_string

-

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

-

-	Parameters:

-		error - Error code.

-

-	Returns:

-		Pointer to string.

-*/

-

-char* png_error_string(int error);

-

-/*

-	Function: png_get_data

-

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

-	

-	> width*height*(bytes per pixel)

-

-	Parameters:

-		data - Where to store result.

-

-	Returns:

-		PNG_NO_ERROR on success, otherwise an error code.

-*/

-

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

-

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

-

-/*

-	Function: png_close_file

-

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

-

-	Parameters:

-		png - png to close.

-	

-	Returns:

-		PNG_NO_ERROR

-*/

-

-int png_close_file(png_t* png);

-

-#ifdef __cplusplus

-}

-#endif

-#endif

diff --git a/src/engine/client/snd.cpp b/src/engine/client/snd.c
index 2fefd6f2..6b490f72 100644
--- a/src/engine/client/snd.cpp
+++ b/src/engine/client/snd.c
@@ -1,19 +1,17 @@
-#include <baselib/system.h>
-#include <baselib/audio.h>
-#include <baselib/stream/file.h>
-
+#include <engine/system.h>
 #include <engine/interface.h>
 #include <engine/config.h>
 
-extern "C" {
-#include "../../wavpack/wavpack.h"
-}
+#include <engine/external/portaudio/portaudio.h>
+#include <engine/external/wavpack/wavpack.h>
 
-using namespace baselib;
+enum
+{
+	NUM_FRAMES_STOP = 512,
+	NUM_FRAMES_LERP = 512,
+};
 
-static const int NUM_FRAMES_STOP = 512;
 static const float NUM_FRAMES_STOP_INV = 1.0f/(float)NUM_FRAMES_STOP;
-static const int NUM_FRAMES_LERP = 512;
 static const float NUM_FRAMES_LERP_INV = 1.0f/(float)NUM_FRAMES_LERP;
 
 static const float GLOBAL_VOLUME_SCALE = 0.75f;
@@ -22,8 +20,9 @@ static float master_volume = 1.0f;
 static const float GLOBAL_SOUND_DELAY = 0.05f;
 
 // --- sound ---
-class sound_data
+typedef struct
 {
+	/*
 public:
 	sound_data() :
 		data(0x0),
@@ -33,7 +32,7 @@ public:
 		sustain_start(-1),
 		sustain_end(-1),
 		last_played(0)
-	{ }
+	{ }*/
 
 	short *data;
 	int num_samples;
@@ -42,8 +41,28 @@ public:
 	int sustain_start;
 	int sustain_end;
 	int64 last_played;
-};
+} SOUND_DATA;
+
+
+static float clampf(float val, float lower, float upper)
+{
+	if(val > upper)
+		return upper;
+	if(val < lower)
+		return lower;
+	return val;
+}
+
 
+static int clampi(int val, int lower, int upper)
+{
+	if(val > upper)
+		return upper;
+	if(val < lower)
+		return lower;
+	return val;
+}
+/*
 template<typename T>
 inline const T clamp(const T val, const T lower, const T upper)
 {
@@ -52,201 +71,264 @@ inline const T clamp(const T val, const T lower, const T upper)
 	if(val < lower)
 		return lower;
 	return val;
-}
+}*/
 
-static class mixer : public audio_stream
+
+typedef struct
 {
+/*
 public:
-	class channel
-	{
-	public:
-		channel()
-		{ data = 0; lerp = -1; stop = -1; }
-		
-		sound_data *data;
-		int tick;
-		int loop;
-		float pan;
-		float vol;
-		float old_vol;
-		float new_vol;
-		int lerp;
-		int stop;
-	};
+	channel()
+	{ data = 0; lerp = -1; stop = -1; }
+*/
 	
-	enum
-	{
-		MAX_CHANNELS=32,
-		MAX_FILL_FRAMES=256,
-	};
+	SOUND_DATA *data;
+	int tick;
+	int loop;
+	float pan;
+	float vol;
+	float old_vol;
+	float new_vol;
+	int lerp;
+	int stop;
+} MIXER_CHANNEL;
+
+enum
+{
+	MAX_CHANNELS=32,
+	MAX_FILL_FRAMES=256,
+};
 
-	channel channels[MAX_CHANNELS];
-	int buffer[MAX_FILL_FRAMES*2];
+static MIXER_CHANNEL channels[MAX_CHANNELS];
+static int buffer[MAX_FILL_FRAMES*2];
 
-	void fill_mono(int *out, unsigned long frames, channel *c, float dv = 0.0f)
-	{
-		float pl = clamp(1.0f - c->pan, 0.0f, 1.0f);
-		float pr = clamp(1.0f + c->pan, 0.0f, 1.0f);
+static void mixer_fill_mono(int *out, unsigned long frames, MIXER_CHANNEL *c, float dv)
+{
+	float pl = clampf(1.0f - c->pan, 0.0f, 1.0f);
+	float pr = clampf(1.0f + c->pan, 0.0f, 1.0f);
+	unsigned long i;
 
-		for(unsigned long i = 0; i < frames; i++)
-		{
-			float val = c->vol * master_volume * c->data->data[c->tick];
+	for(i = 0; i < frames; i++)
+	{
+		float val = c->vol * master_volume * c->data->data[c->tick];
 
-			out[i<<1] += (int)(pl*val);
-			out[(i<<1)+1] += (int)(pr*val);
-			c->tick++;
-			c->vol += dv;
-			if(c->vol < 0.0f) c->vol = 0.0f;
-		}
+		out[i<<1] += (int)(pl*val);
+		out[(i<<1)+1] += (int)(pr*val);
+		c->tick++;
+		c->vol += dv;
+		if(c->vol < 0.0f) c->vol = 0.0f;
 	}
+}
 
-	void fill_stereo(int *out, unsigned long frames, channel *c, float dv = 0.0f)
-	{
-		float pl = clamp(1.0f - c->pan, 0.0f, 1.0f);
-		float pr = clamp(1.0f + c->pan, 0.0f, 1.0f);
+static void mixer_fill_stereo(int *out, unsigned long frames, MIXER_CHANNEL *c, float dv)
+{
+	float pl = clampf(1.0f - c->pan, 0.0f, 1.0f);
+	float pr = clampf(1.0f + c->pan, 0.0f, 1.0f);
+	unsigned long i;
 
-		for(unsigned long i = 0; i < frames; i++)
-		{
-			int vl = (int)(pl*c->vol * master_volume * c->data->data[c->tick]);
-			int vr = (int)(pr*c->vol * master_volume * c->data->data[c->tick + 1]);
-			out[i<<1] += vl;
-			out[(i<<1)+1] += vr;
-			c->tick += 2;
-			c->vol += dv;
-			if(c->vol < 0.0f) c->vol = 0.0f;
-		}
+	for(i = 0; i < frames; i++)
+	{
+		int vl = (int)(pl*c->vol * master_volume * c->data->data[c->tick]);
+		int vr = (int)(pr*c->vol * master_volume * c->data->data[c->tick + 1]);
+		out[i<<1] += vl;
+		out[(i<<1)+1] += vr;
+		c->tick += 2;
+		c->vol += dv;
+		if(c->vol < 0.0f) c->vol = 0.0f;
 	}
+}
 
-	virtual void fill(void *output, unsigned long frames)
-	{
-		short *out = (short*)output;
+static void mixer_fill(void *output, unsigned long frames)
+{
+	short *out = (short*)output;
 
-		dbg_assert(frames <= MAX_FILL_FRAMES, "not enough fill frames in buffer");
+	dbg_assert(frames <= MAX_FILL_FRAMES, "not enough fill frames in buffer");
+	unsigned long i;
+	int c;
 
-		for(unsigned long i = 0; i < frames; i++)
-		{
-			buffer[i<<1] = 0;
-			buffer[(i<<1)+1] = 0;
-		}
+	for(i = 0; i < frames; i++)
+	{
+		buffer[i<<1] = 0;
+		buffer[(i<<1)+1] = 0;
+	}
 
-		for(int c = 0; c < MAX_CHANNELS; c++)
+	for(c = 0; c < MAX_CHANNELS; c++)
+	{
+		unsigned long filled = 0;
+		while(channels[c].data && filled < frames)
 		{
-			unsigned long filled = 0;
-			while(channels[c].data && filled < frames)
+			unsigned long frames_left = (channels[c].data->num_samples - channels[c].tick) >> (channels[c].data->channels-1);
+			unsigned long to_fill = frames>frames_left?frames_left:frames;
+			float dv = 0.0f;
+
+			if(channels[c].stop >= 0)
+				to_fill = (unsigned)channels[c].stop>frames_left?frames:channels[c].stop;
+			if(channels[c].loop >= 0 &&
+					channels[c].data->sustain_start >= 0)
 			{
-				unsigned long frames_left = (channels[c].data->num_samples - channels[c].tick) >> (channels[c].data->channels-1);
-				unsigned long to_fill = frames>frames_left?frames_left:frames;
-				float dv = 0.0f;
-
-				if(channels[c].stop >= 0)
-					to_fill = (unsigned)channels[c].stop>frames_left?frames:channels[c].stop;
-				if(channels[c].loop >= 0 &&
-						channels[c].data->sustain_start >= 0)
-				{
-					unsigned long tmp = channels[c].data->sustain_end - channels[c].tick;
-					to_fill = tmp>frames?frames:tmp;
-				}
-
-				if(channels[c].lerp >= 0)
-				{
-						dv = (channels[c].new_vol - channels[c].old_vol) * NUM_FRAMES_LERP_INV;
-				}
+				unsigned long tmp = channels[c].data->sustain_end - channels[c].tick;
+				to_fill = tmp>frames?frames:tmp;
+			}
 
-				if(channels[c].data->channels == 1)
-					fill_mono(buffer, to_fill, &channels[c], dv);
-				else
-					fill_stereo(buffer, to_fill, &channels[c], dv);
+			if(channels[c].lerp >= 0)
+			{
+					dv = (channels[c].new_vol - channels[c].old_vol) * NUM_FRAMES_LERP_INV;
+			}
 
-				if(channels[c].loop >= 0 &&
-						channels[c].data->sustain_start >= 0 &&
-						channels[c].tick >= channels[c].data->sustain_end)
-					channels[c].tick = channels[c].data->sustain_start;
+			if(channels[c].data->channels == 1)
+				mixer_fill_mono(buffer, to_fill, &channels[c], dv);
+			else
+				mixer_fill_stereo(buffer, to_fill, &channels[c], dv);
 
-				if(channels[c].stop >= 0)
-					channels[c].stop -=  to_fill;
-				if(channels[c].tick >= channels[c].data->num_samples ||
-						channels[c].stop == 0)
-					channels[c].data = 0;
+			if(channels[c].loop >= 0 &&
+					channels[c].data->sustain_start >= 0 &&
+					channels[c].tick >= channels[c].data->sustain_end)
+				channels[c].tick = channels[c].data->sustain_start;
 
-				channels[c].lerp -= to_fill;
-				if(channels[c].lerp < 0)
-					channels[c].lerp = -1;
+			if(channels[c].stop >= 0)
+				channels[c].stop -=  to_fill;
+			if(channels[c].tick >= channels[c].data->num_samples ||
+					channels[c].stop == 0)
+				channels[c].data = 0;
 
+			channels[c].lerp -= to_fill;
+			if(channels[c].lerp < 0)
+				channels[c].lerp = -1;
 
-				filled += to_fill;
-			}
-		}
 
-		for(unsigned long i = 0; i < frames; i++)
-		{
-			out[i<<1] = (short)clamp(buffer[i<<1], -0x7fff, 0x7fff);
-			out[(i<<1)+1] = (short)clamp(buffer[(i<<1)+1], -0x7fff, 0x7fff);
+			filled += to_fill;
 		}
 	}
-	
-	int play(sound_data *sound, unsigned loop, float vol, float pan)
-	{
-		if(time_get() - sound->last_played < (int64)(time_freq()*GLOBAL_SOUND_DELAY))
-			return -1;
 
-		for(int c = 0; c < MAX_CHANNELS; c++)
-		{
-			if(channels[c].data == 0)
-			{
-				channels[c].data = sound;
-				channels[c].tick = 0;
-				channels[c].loop = loop;
-				channels[c].vol = vol * GLOBAL_VOLUME_SCALE;
-				channels[c].pan = pan;
-				channels[c].stop = -1;
-				channels[c].lerp = -1;
-				sound->last_played = time_get();
-				return c;
-			}
-		}
+	for(i = 0; i < frames; i++)
+	{
+		out[i<<1] = (short)clampi(buffer[i<<1], -0x7fff, 0x7fff);
+		out[(i<<1)+1] = (short)clampi(buffer[(i<<1)+1], -0x7fff, 0x7fff);
+	}
+}
 
+int mixer_play(SOUND_DATA *sound, unsigned loop, float vol, float pan)
+{
+	if(time_get() - sound->last_played < (int64)(time_freq()*GLOBAL_SOUND_DELAY))
 		return -1;
-	}
 
-	void stop(int id)
+	int c;
+	for(c = 0; c < MAX_CHANNELS; c++)
 	{
-		dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds");
-		channels[id].old_vol = channels[id].vol;
-		channels[id].stop = NUM_FRAMES_STOP;
+		if(channels[c].data == 0)
+		{
+			channels[c].data = sound;
+			channels[c].tick = 0;
+			channels[c].loop = loop;
+			channels[c].vol = vol * GLOBAL_VOLUME_SCALE;
+			channels[c].pan = pan;
+			channels[c].stop = -1;
+			channels[c].lerp = -1;
+			sound->last_played = time_get();
+			return c;
+		}
 	}
 
-	void set_vol(int id, float vol)
-	{
-		dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds");
-		channels[id].new_vol = vol * GLOBAL_VOLUME_SCALE;
-		channels[id].old_vol = channels[id].vol;
-		channels[id].lerp = NUM_FRAMES_LERP;
-	}
-} mixer;
+	return -1;
+}
+
+static void mixer_stop(int id)
+{
+	dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds");
+	channels[id].old_vol = channels[id].vol;
+	channels[id].stop = NUM_FRAMES_STOP;
+}
+
+static void mixer_set_vol(int id, float vol)
+{
+	dbg_assert(id >= 0 && id < MAX_CHANNELS, "id out of bounds");
+	channels[id].new_vol = vol * GLOBAL_VOLUME_SCALE;
+	channels[id].old_vol = channels[id].vol;
+	channels[id].lerp = NUM_FRAMES_LERP;
+}
 
-struct sound_holder
+typedef struct
 {
-	sound_data sound;
+	SOUND_DATA sound;
 	int next;
+} SOUND;
+
+enum
+{
+	MAX_SOUNDS = 1024,
 };
 
-static const int MAX_SOUNDS = 1024;
-static sound_holder sounds[MAX_SOUNDS];
+static SOUND sounds[MAX_SOUNDS];
 static int first_free_sound;
 
-bool snd_init()
+static PaStream *stream = 0;
+
+static int pacallback(const void *in, void *out, unsigned long frames, const PaStreamCallbackTimeInfo* time, PaStreamCallbackFlags status, void *user)
+{
+	mixer_fill(out, frames);
+	return 0;
+}
+
+int snd_init()
 {
+	int i;
 	first_free_sound = 0;
-	for(int i = 0; i < MAX_SOUNDS; i++)
+	for(i = 0; i < MAX_SOUNDS; i++)
 		sounds[i].next = i+1;
 	sounds[MAX_SOUNDS-1].next = -1;
-	return mixer.create();
+	
+	// init PA
+	PaStreamParameters params;
+	PaError err = Pa_Initialize();
+	if(err != paNoError)
+	{
+		dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err));
+		return 0;
+	}
+
+	params.device = Pa_GetDefaultOutputDevice();
+	if(params.device == -1)
+	{
+		dbg_msg("audio_stream", "no default output device");
+		return 0;
+	}
+	params.channelCount = 2;
+	params.sampleFormat = paInt16;
+	params.suggestedLatency = Pa_GetDeviceInfo(params.device)->defaultLowOutputLatency;
+	params.hostApiSpecificStreamInfo = 0x0;
+
+	err = Pa_OpenStream(
+		&stream,        /* passes back stream pointer */
+		0,              /* no input channels */
+		&params,		/* pointer to parameters */
+		44100,          /* sample rate */
+		128,            /* frames per buffer */
+		paClipOff,		/* no clamping */
+		pacallback,		/* specify our custom callback */
+		0); /* pass our data through to callback */	
+
+	if(err != paNoError)
+	{
+		dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err));
+		return 0;
+	}
+	
+	err = Pa_StartStream(stream);
+	if(err != paNoError)
+	{
+		dbg_msg("audio_stream", "portaudio error: %s", Pa_GetErrorText(err));
+		return 0;
+	}
+	
+	return 1;	
 }
 
-bool snd_shutdown()
+int snd_shutdown()
 {
-	mixer.destroy();
-	return true;
+	Pa_StopStream(stream);
+	stream = NULL;
+	Pa_Terminate();	
+	return 1;
 }
 
 float snd_get_master_volume()
@@ -283,12 +365,12 @@ static int read_data(void *buffer, int size)
 
 int snd_load_wv(const char *filename)
 {
-	sound_data snd;
+	SOUND_DATA snd;
 	int id = -1;
 
 	char error[100];
 
-	file = fopen(filename, "rb");
+	file = fopen(filename, "rb"); // TODO: use system.h stuff for this
 
 	WavpackContext *context = WavpackOpenFileInput(read_data, error);
 	if (context)
@@ -326,7 +408,8 @@ int snd_load_wv(const char *filename)
 		snd.data = (short *)mem_alloc(2*samples*channels, 1);
 		short *dst = snd.data;
 
-		for (int i = 0; i < samples*channels; i++)
+		int i;
+		for (i = 0; i < samples*channels; i++)
 			*dst++ = (short)*src++;
 
 		mem_free(data);
@@ -361,11 +444,12 @@ int snd_load_wv(const char *filename)
 
 int snd_load_wav(const char *filename)
 {
-	sound_data snd;
+	SOUND_DATA snd;
 	
 	// open file for reading
-	file_stream file;
-	if(!file.open_r(filename))
+	IOHANDLE file;
+	file = io_open(filename, IOFLAG_READ);
+	if(!file)
 	{
 		dbg_msg("sound/wav", "failed to open file. filename='%s'", filename);
 		return -1;
@@ -377,7 +461,7 @@ int snd_load_wav(const char *filename)
 	{
 		// read chunk header
 		unsigned char head[8];
-		if(file.read(head, sizeof(head)) != 8)
+		if(io_read(file, head, sizeof(head)) != 8)
 		{
 			break;
 		}
@@ -395,7 +479,7 @@ int snd_load_wav(const char *filename)
 			}
 			
 			unsigned char type[4];
-			file.read(type, 4);
+			io_read(file, type, 4);
 
 			if(type[0] != 'W' || type[1] != 'A' || type[2] != 'V' || type[3] != 'E')
 			{
@@ -411,7 +495,7 @@ int snd_load_wav(const char *filename)
 			if(head[0] == 'f' && head[1] == 'm' && head[2] == 't' && head[3] == ' ')
 			{
 				unsigned char fmt[16];
-				if(file.read(fmt, sizeof(fmt)) !=  sizeof(fmt))
+				if(io_read(file, fmt, sizeof(fmt)) !=  sizeof(fmt))
 				{
 					dbg_msg("sound/wav", "failed to read format. filename='%s'", filename);
 					return -1;
@@ -451,7 +535,7 @@ int snd_load_wav(const char *filename)
 				state++;
 			}
 			else
-				file.skip(chunk_size);
+				io_skip(file, chunk_size);
 		}
 		else if(state == 2)
 		{
@@ -459,7 +543,7 @@ int snd_load_wav(const char *filename)
 			if(head[0] == 'd' && head[1] == 'a' && head[2] == 't' && head[3] == 'a')
 			{
 				snd.data = (short*)mem_alloc(chunk_size, 1);
-				file.read(snd.data, chunk_size);
+				io_read(file, snd.data, chunk_size);
 				snd.num_samples = chunk_size/(2);
 #if defined(CONF_ARCH_ENDIAN_BIG)
 				for(unsigned i = 0; i < (unsigned)snd.num_samples; i++)
@@ -476,7 +560,7 @@ int snd_load_wav(const char *filename)
 				state++;
 			}
 			else
-				file.skip(chunk_size);
+				io_skip(file, chunk_size);
 		}
 		else if(state == 3)
 		{
@@ -487,13 +571,13 @@ int snd_load_wav(const char *filename)
 				if(config.debug)
 					dbg_msg("sound/wav", "got sustain");
 
-				file.read(smpl, sizeof(smpl));
+				io_read(file, smpl, sizeof(smpl));
 				unsigned num_loops = (smpl[28] | (smpl[29]<<8) | (smpl[30]<<16) | (smpl[31]<<24));
 				unsigned skip = (smpl[32] | (smpl[33]<<8) | (smpl[34]<<16) | (smpl[35]<<24));
 
 				if(num_loops > 0)
 				{
-					file.read(loop, sizeof(loop));
+					io_read(file, loop, sizeof(loop));
 					unsigned start = (loop[8] | (loop[9]<<8) | (loop[10]<<16) | (loop[11]<<24));
 					unsigned end = (loop[12] | (loop[13]<<8) | (loop[14]<<16) | (loop[15]<<24));
 					sounds[id].sound.sustain_start = start * sounds[id].sound.channels;
@@ -501,16 +585,16 @@ int snd_load_wav(const char *filename)
 				}
 
 				if(num_loops > 1)
-					file.skip((num_loops-1) * sizeof(loop));
+					io_skip(file, (num_loops-1) * sizeof(loop));
 
-				file.skip(skip);
+				io_skip(file, skip);
 				state++;
 			}
 			else
-				file.skip(chunk_size);
+				io_skip(file, chunk_size);
 		}
 		else
-			file.skip(chunk_size);
+			io_skip(file, chunk_size);
 	}
 
 	if(id >= 0)
@@ -534,17 +618,17 @@ int snd_play(int id, int loop, float vol, float pan)
 
 	dbg_assert(sounds[id].sound.data != 0, "null sound");
 	dbg_assert(sounds[id].next == -1, "sound isn't allocated");
-	return mixer.play(&sounds[id].sound, loop, vol, pan);
+	return mixer_play(&sounds[id].sound, loop, vol, pan);
 }
 
 void snd_stop(int id)
 {
 	if(id >= 0)
-		mixer.stop(id);
+		mixer_stop(id);
 }
 
 void snd_set_vol(int id, float vol)
 {
 	if(id >= 0)
-		mixer.set_vol(id, vol);
+		mixer_set_vol(id, vol);
 }
diff --git a/src/engine/client/ui.cpp b/src/engine/client/ui.c
index 7b309539..c67b1b13 100644
--- a/src/engine/client/ui.cpp
+++ b/src/engine/client/ui.c
@@ -1,4 +1,4 @@
-#include <baselib/system.h>
+#include <engine/system.h>
 #include <engine/interface.h>
 #include "ui.h"
 
@@ -14,7 +14,7 @@ struct pretty_font
 	int font_texture;
 };
 
-extern pretty_font *current_font;
+extern struct pretty_font *current_font;
 
 static void *hot_item = 0;
 static void *active_item = 0;
@@ -84,7 +84,7 @@ void ui_do_label(float x, float y, const char *text, float size)
 {
     gfx_blend_normal();
     gfx_texture_set(current_font->font_texture);
-    gfx_pretty_text(x, y, size, text);
+    gfx_pretty_text(x, y, size, text, -1);
 }
 
 int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func, void *extra)
@@ -115,8 +115,3 @@ int ui_do_button(void *id, const char *text, int checked, float x, float y, floa
     return r;
 }
 
-int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func)
-{
-	return ui_do_button(id, text, checked, x, y, w, h, draw_func, 0x0);
-}
-
diff --git a/src/engine/client/ui.h b/src/engine/client/ui.h
index fb9208c1..31757b3b 100644
--- a/src/engine/client/ui.h
+++ b/src/engine/client/ui.h
@@ -1,12 +1,9 @@
 #ifndef _UI_H
 #define _UI_H
-/*
-extern void *hot_item;
-extern void *active_item;
-extern void *becomming_hot_item;
-extern float mouse_x, mouse_y; // in gui space
-extern float mouse_wx, mouse_wy; // in world space
-extern unsigned mouse_buttons;*/
+
+#ifdef __cplusplus
+extern "C" {
+#endif
 
 int ui_update(float mx, float my, float mwx, float mwy, int buttons);
 
@@ -30,6 +27,9 @@ typedef void (*draw_button_callback)(void *id, const char *text, int checked, fl
 void ui_do_image(int texture, float x, float y, float w, float h);
 void ui_do_label(float x, float y, const char *text, float size);
 int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func, void *extra);
-int ui_do_button(void *id, const char *text, int checked, float x, float y, float w, float h, draw_button_callback draw_func);
+
+#ifdef __cplusplus
+}
+#endif
 
 #endif