about summary refs log tree commit diff
diff options
context:
space:
mode:
authorTeetime <TeetimeTW@yahoo.de>2013-03-24 04:19:57 +0100
committerTeetime <TeetimeTW@yahoo.de>2013-03-24 04:19:57 +0100
commit4affc155a906b6091aafc3f9635acc3b8b0aed8a (patch)
tree43e4dc20b9c36599571f3caf2e9108a4bb3f5401
parent6e73cd75bf24eb98781c68ae47d6527cc03262c8 (diff)
parent0914490bd994185caef6bfc3038f5cec737e31f3 (diff)
downloadzcatch-4affc155a906b6091aafc3f9635acc3b8b0aed8a.tar.gz
zcatch-4affc155a906b6091aafc3f9635acc3b8b0aed8a.zip
Merge branch 'master0.6' into zCatch
Conflicts:
	data/languages/index.txt
	src/game/server/entities/character.cpp
-rw-r--r--bam.lua68
-rw-r--r--configure.lua4
-rw-r--r--data/languages/index.txt97
-rw-r--r--data/languages/kyrgyz.txt687
-rw-r--r--src/base/system.c56
-rw-r--r--src/base/system.h33
-rw-r--r--src/base/tl/base.h2
-rw-r--r--src/base/tl/range.h10
-rw-r--r--src/base/tl/threading.h24
-rw-r--r--src/engine/client/backend_sdl.cpp153
-rw-r--r--src/engine/client/backend_sdl.h94
-rw-r--r--src/engine/client/client.cpp36
-rw-r--r--src/engine/client/client.h2
-rw-r--r--src/engine/client/graphics.cpp49
-rw-r--r--src/engine/client/graphics.h2
-rw-r--r--src/engine/client/graphics_threaded.cpp136
-rw-r--r--src/engine/client/graphics_threaded.h35
-rw-r--r--src/engine/client/input.cpp13
-rw-r--r--src/engine/client/serverbrowser.cpp2
-rw-r--r--src/engine/client/text.cpp2
-rw-r--r--src/engine/demo.h4
-rw-r--r--src/engine/graphics.h2
-rw-r--r--src/engine/input.h7
-rw-r--r--src/engine/server/server.cpp101
-rw-r--r--src/engine/server/server.h6
-rw-r--r--src/engine/shared/config_variables.h11
-rw-r--r--src/engine/shared/console.cpp8
-rw-r--r--src/engine/shared/demo.cpp30
-rw-r--r--src/engine/shared/demo.h1
-rw-r--r--src/engine/shared/econ.cpp4
-rw-r--r--src/engine/shared/mapchecker.cpp1
-rw-r--r--src/engine/shared/netban.cpp2
-rw-r--r--src/engine/shared/netban.h4
-rw-r--r--src/engine/shared/network.h6
-rw-r--r--src/engine/shared/network_client.cpp2
-rw-r--r--src/engine/shared/network_conn.cpp19
-rw-r--r--src/engine/shared/network_server.cpp10
-rw-r--r--src/engine/shared/snapshot.cpp7
-rw-r--r--src/game/client/components/chat.cpp24
-rw-r--r--src/game/client/components/console.cpp18
-rw-r--r--src/game/client/components/menus.cpp2
-rw-r--r--src/game/client/components/menus_browser.cpp2
-rw-r--r--src/game/client/components/menus_ingame.cpp2
-rw-r--r--src/game/client/components/menus_settings.cpp51
-rw-r--r--src/game/client/components/voting.cpp10
-rw-r--r--src/game/client/gameclient.cpp4
-rw-r--r--src/game/client/render.cpp3
-rw-r--r--src/game/client/render_map.cpp5
-rw-r--r--src/game/editor/editor.cpp196
-rw-r--r--src/game/editor/editor.h4
-rw-r--r--src/game/editor/io.cpp2
-rw-r--r--src/game/editor/layer_quads.cpp5
-rw-r--r--src/game/editor/layer_tiles.cpp12
-rw-r--r--src/game/editor/popups.cpp1
-rw-r--r--src/game/server/entities/character.cpp7
-rw-r--r--src/game/server/entities/character.h1
-rw-r--r--src/game/server/gamecontext.cpp10
-rw-r--r--src/game/server/gamecontroller.cpp4
-rw-r--r--src/game/server/gamemodes/ctf.cpp2
-rw-r--r--src/game/server/player.cpp1
-rw-r--r--src/game/version.h4
-rw-r--r--src/mastersrv/mastersrv.cpp7
-rw-r--r--src/versionsrv/mapversions.h22
-rw-r--r--src/versionsrv/versionsrv.cpp1
-rw-r--r--src/versionsrv/versionsrv.h17
65 files changed, 1669 insertions, 478 deletions
diff --git a/bam.lua b/bam.lua
index 016ba7b6..2216f401 100644
--- a/bam.lua
+++ b/bam.lua
@@ -8,6 +8,8 @@ Import("other/freetype/freetype.lua")
 config = NewConfig()
 config:Add(OptCCompiler("compiler"))
 config:Add(OptTestCompileC("stackprotector", "int main(){return 0;}", "-fstack-protector -fstack-protector-all"))
+config:Add(OptTestCompileC("minmacosxsdk", "int main(){return 0;}", "-mmacosx-version-min=10.5 -isysroot /Developer/SDKs/MacOSX10.5.sdk"))
+config:Add(OptTestCompileC("macosxppc", "int main(){return 0;}", "-arch ppc"))
 config:Add(OptLibrary("zlib", "zlib.h", false))
 config:Add(SDL.OptFind("sdl", true))
 config:Add(FreeType.OptFind("freetype", true))
@@ -149,8 +151,12 @@ function build(settings)
 			-- disable visibility attribute support for gcc on windows
 			settings.cc.defines:Add("NO_VIZ")
 		elseif platform == "macosx" then
-			settings.cc.flags:Add("-mmacosx-version-min=10.5", "-isysroot /Developer/SDKs/MacOSX10.5.sdk")
-			settings.link.flags:Add("-mmacosx-version-min=10.5", "-isysroot /Developer/SDKs/MacOSX10.5.sdk")
+			settings.cc.flags:Add("-mmacosx-version-min=10.5")
+			settings.link.flags:Add("-mmacosx-version-min=10.5")
+			if config.minmacosxsdk.value == 1 then
+				settings.cc.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
+				settings.link.flags:Add("-isysroot /Developer/SDKs/MacOSX10.5.sdk")
+			end
 		elseif config.stackprotector.value == 1 then
 			settings.cc.flags:Add("-fstack-protector", "-fstack-protector-all")
 			settings.link.flags:Add("-fstack-protector", "-fstack-protector-all")
@@ -359,27 +365,45 @@ if platform == "macosx" then
 
 	DefaultTarget("game_debug_x86")
 	
-	if arch == "ia32" then
-		PseudoTarget("release", ppc_r, x86_r)
-		PseudoTarget("debug", ppc_d, x86_d)
-		PseudoTarget("server_release", "server_release_x86", "server_release_ppc")
-		PseudoTarget("server_debug", "server_debug_x86", "server_debug_ppc")
-		PseudoTarget("client_release", "client_release_x86", "client_release_ppc")
-		PseudoTarget("client_debug", "client_debug_x86", "client_debug_ppc")
-	elseif arch == "amd64" then
-		PseudoTarget("release", ppc_r, x86_r, x86_64_r)
-		PseudoTarget("debug", ppc_d, x86_d, x86_64_d)
-		PseudoTarget("server_release", "server_release_x86", "server_release_x86_64", "server_release_ppc")
-		PseudoTarget("server_debug", "server_debug_x86", "server_release_x86_64", "server_debug_ppc")
-		PseudoTarget("client_release", "client_release_x86", "server_release_x86_64", "client_release_ppc")
-		PseudoTarget("client_debug", "client_debug_x86", "server_release_x86_64", "client_debug_ppc")
+	if config.macosxppc.value == 1 then
+		if arch == "ia32" then
+			PseudoTarget("release", ppc_r, x86_r)
+			PseudoTarget("debug", ppc_d, x86_d)
+			PseudoTarget("server_release", "server_release_ppc", "server_release_x86")
+			PseudoTarget("server_debug", "server_debug_ppc", "server_debug_x86")
+			PseudoTarget("client_release", "client_release_ppc", "client_release_x86")
+			PseudoTarget("client_debug", "client_debug_ppc", "client_debug_x86")
+		elseif arch == "amd64" then
+			PseudoTarget("release", ppc_r, x86_r, x86_64_r)
+			PseudoTarget("debug", ppc_d, x86_d, x86_64_d)
+			PseudoTarget("server_release", "server_release_ppc", "server_release_x86", "server_release_x86_64")
+			PseudoTarget("server_debug", "server_debug_ppc", "server_debug_x86", "server_debug_x86_64")
+			PseudoTarget("client_release", "client_release_ppc", "client_release_x86", "client_release_x86_64")
+			PseudoTarget("client_debug", "client_debug_ppc", "client_debug_x86", "client_debug_x86_64")
+		else
+			PseudoTarget("release", ppc_r)
+			PseudoTarget("debug", ppc_d)
+			PseudoTarget("server_release", "server_release_ppc")
+			PseudoTarget("server_debug", "server_debug_ppc")
+			PseudoTarget("client_release", "client_release_ppc")
+			PseudoTarget("client_debug", "client_debug_ppc")
+		end
 	else
-		PseudoTarget("release", ppc_r)
-		PseudoTarget("debug", ppc_d)
-		PseudoTarget("server_release", "server_release_ppc")
-		PseudoTarget("server_debug", "server_debug_ppc")
-		PseudoTarget("client_release", "client_release_ppc")
-		PseudoTarget("client_debug", "client_debug_ppc")
+		if arch == "ia32" then
+			PseudoTarget("release", x86_r)
+			PseudoTarget("debug", x86_d)
+			PseudoTarget("server_release", "server_release_x86")
+			PseudoTarget("server_debug", "server_debug_x86")
+			PseudoTarget("client_release", "client_release_x86")
+			PseudoTarget("client_debug", "client_debug_x86")
+		elseif arch == "amd64" then
+			PseudoTarget("release", x86_r, x86_64_r)
+			PseudoTarget("debug", x86_d, x86_64_d)
+			PseudoTarget("server_release", "server_release_x86", "server_release_x86_64")
+			PseudoTarget("server_debug", "server_debug_x86", "server_debug_x86_64")
+			PseudoTarget("client_release", "client_release_x86", "client_release_x86_64")
+			PseudoTarget("client_debug", "client_debug_x86", "client_debug_x86_64")
+		end
 	end
 else
 	build(debug_settings)
diff --git a/configure.lua b/configure.lua
index 26825b06..2db70cc4 100644
--- a/configure.lua
+++ b/configure.lua
@@ -376,6 +376,8 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
 			SetDriversCL(settings)
 		elseif option.driver == "gcc" then
 			SetDriversGCC(settings)
+		elseif option.driver == "clang" then
+			SetDriversClang(settings)
 		else
 			error(option.driver.." is not a known c/c++ compile driver")
 		end
@@ -393,7 +395,7 @@ function OptCCompiler(name, default_driver, default_c, default_cxx, desc)
 	local printhelp = function(option)
 		local a = ""
 		if option.desc then a = "for "..option.desc end
-		print("\t"..option.name.."=gcc|cl")
+		print("\t"..option.name.."=gcc|cl|clang")
 		print("\t\twhat c/c++ compile driver to use"..a)
 		print("\t"..option.name..".c=FILENAME")
 		print("\t\twhat c compiler executable to use"..a)
diff --git a/data/languages/index.txt b/data/languages/index.txt
new file mode 100644
index 00000000..751c6bfa
--- /dev/null
+++ b/data/languages/index.txt
@@ -0,0 +1,97 @@
+##### language indices #####
+
+belarusian
+== Беларуская
+== 112
+
+bosnian
+== Bosanski
+== 70
+
+brazilian_portuguese
+== Português brasileiro
+== 76
+
+bulgarian
+== Български
+== 100
+
+czech
+== Česky
+== 203
+
+danish
+== Dansk
+== 208
+
+dutch
+== Nederlands
+== 528
+
+finnish
+== Suomi
+== 246
+
+french
+== Français
+== 250
+
+german
+== Deutsch
+== 276
+
+hungarian
+== Magyar
+== 348
+
+italian
+== Italiano
+== 380
+
+kyrgyz
+== Кыргызча
+== 417
+
+norwegian
+== Norsk
+== 578
+
+polish
+== Polski
+== 616
+
+portuguese
+== Português
+== 620
+
+romanian
+== Română
+== 642
+
+russian
+== Русский
+== 643
+
+serbian
+== Srpski
+== 688
+
+slovak
+== Slovensky
+== 703
+
+spanish
+== Español
+== 724
+
+swedish
+== Svenska
+== 752
+
+turkish
+== Türkçe
+== 792
+
+ukrainian
+== Українська
+== 804
diff --git a/data/languages/kyrgyz.txt b/data/languages/kyrgyz.txt
new file mode 100644
index 00000000..48c745eb
--- /dev/null
+++ b/data/languages/kyrgyz.txt
@@ -0,0 +1,687 @@
+
+##### translated strings #####
+
+%d Bytes
+== %d байт
+
+%d of %d servers, %d players
+== %d/%d сервер, %d оюнчу
+
+%d%% loaded
+== %d%% жүктөлдү
+
+%ds left
+== %d сек. калды
+
+%i minute left
+== %i минута калды!
+
+%i minutes left
+== %i минута калды!
+
+%i second left
+== %i секунда калды!
+
+%i seconds left
+== %i секунда калды!
+
+%s wins!
+== %s утту!
+
+-Page %d-
+== -Барак %d-
+
+Abort
+== Жокко чыгаруу
+
+Add
+== Кошуу
+
+Add Friend
+== Досту кошуу
+
+Address
+== Дареги
+
+All
+== Баары
+
+Alpha
+== Тунук.
+
+Always show name plates
+== Оюнчулардын аттарын дайыма көрсөтүү
+
+Are you sure that you want to delete the demo?
+== Сиз анык эле демонун өчүрүлүшүн каалайсызбы?
+
+Are you sure that you want to quit?
+== Сиз анык эле оюндан чыгууну каалайсызбы?
+
+Are you sure that you want to remove the player from your friends list?
+== Сиз анык эле бул оюнчуну достор тизмесинен өчүрүүнү каалайсызбы?
+
+As this is the first time you launch the game, please enter your nick name below. It's recommended that you check the settings to adjust them to your liking before joining a server.
+== Бул оюндун биринчи жүргүзүлүшү болгону үчүн, төмөн жакка такма атыңызды киргизип, жана ырастоолорду текшерип коюңуз.
+
+Automatically record demos
+== Демону автоматтуу түрдө жазуу
+
+Automatically take game over screenshot
+== Оюн натыйжаларын сүрөткө тартуу
+
+Blue team
+== Көктөр
+
+Blue team wins!
+== Көктөр утту!
+
+Body
+== Дене
+
+Call vote
+== Добуш берүү
+
+Change settings
+== Ырастоолорду өзгөртүү
+
+Chat
+== Чат
+
+Clan
+== Кланы
+
+Client
+== Клиент
+
+Close
+== Чыгуу
+
+Compatible version
+== Батышуучу версия
+
+Connect
+== Туташуу
+
+Connecting to
+== Туташтыруу
+
+Connection Problems...
+== Байланыш көйгөйлөрү...
+
+Console
+== Консоль
+
+Controls
+== Башкаруу
+
+Count players only
+== Оюнчуларды гана саноо
+
+Country
+== Өлкө
+
+Crc:
+== Crc:
+
+Created:
+== Жаратылганы:
+
+Current
+== Кезектеги
+
+Current version: %s
+== Кезектеги версиясы: %s
+
+Custom colors
+== Өз түстөр
+
+Delete
+== Өчүрүү
+
+Delete demo
+== Демону өчүрүү
+
+Demo details
+== Демо деталдары
+
+Demofile: %s
+== Демо: %s
+
+Demos
+== Демо
+
+Disconnect
+== Өчүрүү
+
+Disconnected
+== Өчүрүлдү
+
+Display Modes
+== Экран чечими
+
+Downloading map
+== Картаны жүктөө
+
+Draw!
+== Тең!
+
+Dynamic Camera
+== Динамикалык камера
+
+Emoticon
+== Эмоциялар
+
+Enter
+== Кирүү
+
+Error
+== Ката
+
+Error loading demo
+== Демону жүктөө учурундагы ката
+
+FSAA samples
+== FSAA сэмплдери
+
+Favorite
+== Тандалма
+
+Favorites
+== Тандалмалар
+
+Feet
+== Бут
+
+Filter
+== Фильтр
+
+Fire
+== Атуу
+
+Folder
+== Папка
+
+Force vote
+== Тездетүү
+
+Free-View
+== Эркин сереп
+
+Friends
+== Достор
+
+Fullscreen
+== Толук экран режими
+
+Game
+== Оюн
+
+Game info
+== Оюн жөнүндө
+
+Game over
+== Оюн бүттү
+
+Game type
+== Оюн түрү
+
+Game types:
+== Оюн түрү:
+
+General
+== Негизги
+
+Graphics
+== Графика
+
+Grenade
+== Гранатомёт
+
+Hammer
+== Барскан
+
+Has people playing
+== Бош эмес сервер
+
+High Detail
+== Жогорку детализация
+
+Hook
+== Илмек
+
+Host address
+== Сервер дареги
+
+Hue
+== Түсү
+
+Info
+== Маалымат
+
+Internet
+== Интернет
+
+Invalid Demo
+== Жарабаган демо
+
+Join blue
+== Көктөргө
+
+Join game
+== Оюноо
+
+Join red
+== Кызылдарга
+
+Jump
+== Секирүү
+
+Kick player
+== Оюнчуну бан кылуу
+
+LAN
+== LAN
+
+Language
+== Тил
+
+Length:
+== Узун.:
+
+Lht.
+== Ач. түс.
+
+Loading
+== Жүктөө
+
+MOTD
+== Күндүн билдирүүсү
+
+Map
+== Картасы
+
+Map:
+== Картасы:
+
+Max Screenshots
+== Максималдуу сүрөт саны
+
+Max demos
+== Максималдуу демо саны
+
+Maximum ping:
+== Макс. пинги:
+
+Miscellaneous
+== Кошумча
+
+Mouse sens.
+== Чычкан сезгич.
+
+Move left
+== Солго басуу
+
+Move player to spectators
+== Оюнчуну байкоочу кылуу
+
+Move right
+== Оңго басуу
+
+Movement
+== Аракет
+
+Mute when not active
+== Активдүү эмес кезде колдонбоо
+
+Name
+== Аты
+
+Name plates size
+== Өлчөм
+
+Netversion:
+== Версиясы:
+
+New name:
+== Жаңы ат:
+
+News
+== Жаңылыктар
+
+Next weapon
+== Кийин. курал
+
+Nickname
+== Такма ат
+
+No
+== Жок
+
+No password
+== Сырсөзсүз
+
+No servers found
+== Серверлер табылган жок
+
+No servers match your filter criteria
+== Сиздин фильтриңизге жарай турган серверлер жок
+
+Ok
+== ОК
+
+Open
+== Ачуу
+
+Parent Folder
+== Ата-энелик каталог
+
+Password
+== Сырсөзү
+
+Password incorrect
+== Сырсөз
+
+Ping
+== Пинги
+
+Pistol
+== Тапанча
+
+Play
+== Көрүү
+
+Play background music
+== Фон музыкасын ойнотуу
+
+Player
+== Оюнчу
+
+Player country:
+== Өлкөсү:
+
+Player options
+== Оюнчу опциялары
+
+Players
+== Оюнчулары
+
+Please balance teams!
+== Команадаларды баланстаңыз!
+
+Prev. weapon
+== Мурун. курал
+
+Quality Textures
+== Сапаттуу текстуралар
+
+Quick search:
+== Тез издөө:
+
+Quit
+== Чыгуу
+
+Quit anyway?
+== Чыгуу?
+
+REC %3d:%02d
+== ЖАЗУУ %3d:%02d
+
+Reason:
+== Себеп:
+
+Record demo
+== Демо жазуу
+
+Red team
+== Кызылдар
+
+Red team wins!
+== Кызылдар утту!
+
+Refresh
+== Жаңылоо
+
+Refreshing master servers
+== Мастер-серверлер тизмесин жаңылоо
+
+Remote console
+== Сервер консолу
+
+Remove
+== Өчүрүү
+
+Remove friend
+== Досту өчүрүү
+
+Rename
+== Атын өзгөрт.
+
+Rename demo
+== Демо атын өзгөртүү
+
+Reset filter
+== Фильтрлерди түшүрүү
+
+Reset to defaults
+== Ырастоолорду түшүрүү
+
+Rifle
+== Бластер
+
+Round
+== Раунду
+
+Sample rate
+== Жыштыгы
+
+Sat.
+== Канык.
+
+Score
+== Упайы
+
+Score board
+== Табло
+
+Score limit
+== Упай лимити
+
+Scoreboard
+== Табло
+
+Screenshot
+== Сүрөт
+
+Server address:
+== Сервер дареги:
+
+Server details
+== Сервер деталдары
+
+Server filter
+== Сервер фильтри
+
+Server info
+== Маалымат
+
+Server not full
+== Сервер толук эмес
+
+Settings
+== Ырастоолор
+
+Shotgun
+== Мылтык
+
+Show chat
+== Чатты көрсөтүү
+
+Show friends only
+== Достор менен гана
+
+Show ingame HUD
+== Оюн ичиндеги HUD'ни көрсөтүү
+
+Show name plates
+== Оюнчулардын аттарын көрсөтүү
+
+Show only supported
+== Колдолгон чечимдерди гана көрсөтүү
+
+Size:
+== Өлчөмү:
+
+Skins
+== Скиндер
+
+Sound
+== Үн
+
+Sound error
+== Үн катасы
+
+Sound volume
+== Үн катуулугу
+
+Spectate
+== Байкоо
+
+Spectate next
+== Кийин. байкоо
+
+Spectate previous
+== Мурун. байкоо
+
+Spectator mode
+== Байкоочу
+
+Spectators
+== Байкоочулар
+
+Standard gametype
+== Стандарттуу оюн түрү
+
+Standard map
+== Стандарттуу карта
+
+Stop record
+== Токтотуу
+
+Strict gametype filter
+== Оюн түрүнүн так фильтри
+
+Sudden Death
+== Тез өлүм
+
+Switch weapon on pickup
+== Көтөрүлгөн куралга которуу
+
+Team
+== Команда
+
+Team chat
+== Команда чаты
+
+Teeworlds %s is out! Download it at www.teeworlds.com!
+== Teeworlds %s чыкты! www.teeworlds.com сайтынан жүктөп алыңыз!
+
+Texture Compression
+== Текстура кысылышы
+
+The audio device couldn't be initialised.
+== Аудио түзмөгүн инициализациялап алууга мүмкүн эмес.
+
+The server is running a non-standard tuning on a pure game type.
+== Бул сервер стандартту эмес ырастоолор менен таза оюн түрүндө иштеп жатат.
+
+There's an unsaved map in the editor, you might want to save it before you quit the game.
+== Редактордо сакталбаган карта бар, аны оюндан чыгаар алдында сактасаңыз болот.
+
+Time limit
+== Убакыт лимити
+
+Time limit: %d min
+== Убакыт лимити: %d мин.
+
+Try again
+== ОК
+
+Type
+== Түрү
+
+Type:
+== Түрү:
+
+UI Color
+== Интерфейс түсү
+
+Unable to delete the demo
+== Демону өчүрүү мүмкүн эмес
+
+Unable to rename the demo
+== Демо атын өзгөртүү мүмкүн эмес
+
+Use sounds
+== Үндөрдү колдонуу
+
+Use team colors for name plates
+== Аттар үчүн команданын түсүн колдонуу
+
+V-Sync
+== Вертикалдык синхронизация
+
+Version
+== Версиясы
+
+Version:
+== Версиясы:
+
+Vote command:
+== Добуш коммандасы:
+
+Vote description:
+== Добуш баяндамасы:
+
+Vote no
+== Каршы
+
+Vote yes
+== Макул
+
+Voting
+== Добуш берүү
+
+Warmup
+== Даярдануу
+
+Weapon
+== Курал
+
+Welcome to Teeworlds
+== Teeworlds'ко кош келиңиз!
+
+Yes
+== Ооба
+
+You must restart the game for all settings to take effect.
+== Өзгөртүүлөрдү колдонуу үчүн оюнду кайта жүргүзүңүз.
+
+Your skin
+== Скиниңиз
+
+no limit
+== лимитсиз
+
+Game paused
+== Оюн бир азга токтотулду
+
+Respawn
+== Респаун
+
+Show only chat messages from friends
+== Достордун гана чат билдирүүлөрүн көрсөтүү
+
+##### needs translation #####
+
+##### old translations #####
diff --git a/src/base/system.c b/src/base/system.c
index 99fd0380..5c6762ef 100644
--- a/src/base/system.c
+++ b/src/base/system.c
@@ -80,7 +80,7 @@ void dbg_assert_imp(const char *filename, int line, int test, const char *msg)
 
 void dbg_break()
 {
-	*((unsigned*)0) = 0x0;
+	*((volatile unsigned*)0) = 0x0;
 }
 
 void dbg_msg(const char *sys, const char *fmt, ...)
@@ -166,6 +166,8 @@ void *mem_alloc_debug(const char *filename, int line, unsigned size, unsigned al
 	MEMTAIL *tail;
 	MEMHEADER *header = (struct MEMHEADER *)malloc(size+sizeof(MEMHEADER)+sizeof(MEMTAIL));
 	dbg_assert(header != 0, "mem_alloc failure");
+	if(!header)
+		return NULL;
 	tail = (struct MEMTAIL *)(((char*)(header+1))+size);
 	header->size = size;
 	header->filename = filename;
@@ -477,7 +479,7 @@ int lock_try(LOCK lock)
 #if defined(CONF_FAMILY_UNIX)
 	return pthread_mutex_trylock((LOCKINTERNAL *)lock);
 #elif defined(CONF_FAMILY_WINDOWS)
-	return TryEnterCriticalSection((LPCRITICAL_SECTION)lock);
+	return !TryEnterCriticalSection((LPCRITICAL_SECTION)lock);
 #else
 	#error not implemented on this platform
 #endif
@@ -505,18 +507,20 @@ void lock_release(LOCK lock)
 #endif
 }
 
-#if defined(CONF_FAMILY_UNIX)
-void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
-void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
-void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
-void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
-#elif defined(CONF_FAMILY_WINDOWS)
-void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
-void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, 0L); }
-void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
-void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
-#else
-	#error not implemented on this platform
+#if !defined(CONF_PLATFORM_MACOSX)
+	#if defined(CONF_FAMILY_UNIX)
+	void semaphore_init(SEMAPHORE *sem) { sem_init(sem, 0, 0); }
+	void semaphore_wait(SEMAPHORE *sem) { sem_wait(sem); }
+	void semaphore_signal(SEMAPHORE *sem) { sem_post(sem); }
+	void semaphore_destroy(SEMAPHORE *sem) { sem_destroy(sem); }
+	#elif defined(CONF_FAMILY_WINDOWS)
+	void semaphore_init(SEMAPHORE *sem) { *sem = CreateSemaphore(0, 0, 10000, 0); }
+	void semaphore_wait(SEMAPHORE *sem) { WaitForSingleObject((HANDLE)*sem, INFINITE); }
+	void semaphore_signal(SEMAPHORE *sem) { ReleaseSemaphore((HANDLE)*sem, 1, NULL); }
+	void semaphore_destroy(SEMAPHORE *sem) { CloseHandle((HANDLE)*sem); }
+	#else
+		#error not implemented on this platform
+	#endif
 #endif
 
 
@@ -903,6 +907,7 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 	NETSOCKET sock = invalid_socket;
 	NETADDR tmpbindaddr = bindaddr;
 	int broadcast = 1;
+	int recvsize = 65536;
 
 	if(bindaddr.type&NETTYPE_IPV4)
 	{
@@ -917,13 +922,13 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 		{
 			sock.type |= NETTYPE_IPV4;
 			sock.ipv4sock = socket;
-		}
 
-		/* set non-blocking */
-		net_set_non_blocking(sock);
+			/* set boardcast */
+			setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
 
-		/* set boardcast */
-		setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
+			/* set receive buffer size */
+			setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
+		}
 	}
 
 	if(bindaddr.type&NETTYPE_IPV6)
@@ -939,15 +944,18 @@ NETSOCKET net_udp_create(NETADDR bindaddr)
 		{
 			sock.type |= NETTYPE_IPV6;
 			sock.ipv6sock = socket;
-		}
 
-		/* set non-blocking */
-		net_set_non_blocking(sock);
+			/* set boardcast */
+			setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
 
-		/* set boardcast */
-		setsockopt(socket, SOL_SOCKET, SO_BROADCAST, (const char*)&broadcast, sizeof(broadcast));
+			/* set receive buffer size */
+			setsockopt(socket, SOL_SOCKET, SO_RCVBUF, (char*)&recvsize, sizeof(recvsize));
+		}
 	}
 
+	/* set non-blocking */
+	net_set_non_blocking(sock);
+
 	/* return */
 	return sock;
 }
diff --git a/src/base/system.h b/src/base/system.h
index bc4ee734..00c58c10 100644
--- a/src/base/system.h
+++ b/src/base/system.h
@@ -33,6 +33,13 @@ void dbg_assert(int test, const char *msg);
 #define dbg_assert(test,msg) dbg_assert_imp(__FILE__, __LINE__, test, msg)
 void dbg_assert_imp(const char *filename, int line, int test, const char *msg);
 
+
+#ifdef __clang_analyzer__
+#include <assert.h>
+#undef dbg_assert
+#define dbg_assert(test,msg) assert(test)
+#endif
+
 /*
 	Function: dbg_break
 		Breaks into the debugger.
@@ -403,20 +410,22 @@ void lock_release(LOCK lock);
 
 /* Group: Semaphores */
 
-#if defined(CONF_FAMILY_UNIX)
-	#include <semaphore.h>
-	typedef sem_t SEMAPHORE;
-#elif defined(CONF_FAMILY_WINDOWS)
-	typedef void* SEMAPHORE;
-#else
-	#error missing sempahore implementation
+#if !defined(CONF_PLATFORM_MACOSX)
+	#if defined(CONF_FAMILY_UNIX)
+		#include <semaphore.h>
+		typedef sem_t SEMAPHORE;
+	#elif defined(CONF_FAMILY_WINDOWS)
+		typedef void* SEMAPHORE;
+	#else
+		#error missing sempahore implementation
+	#endif
+
+	void semaphore_init(SEMAPHORE *sem);
+	void semaphore_wait(SEMAPHORE *sem);
+	void semaphore_signal(SEMAPHORE *sem);
+	void semaphore_destroy(SEMAPHORE *sem);
 #endif
 
-void semaphore_init(SEMAPHORE *sem);
-void semaphore_wait(SEMAPHORE *sem);
-void semaphore_signal(SEMAPHORE *sem);
-void semaphore_destroy(SEMAPHORE *sem);
-
 /* Group: Timer */
 #ifdef __GNUC__
 /* if compiled with -pedantic-errors it will complain about long
diff --git a/src/base/tl/base.h b/src/base/tl/base.h
index 2fcb14eb..ce77db84 100644
--- a/src/base/tl/base.h
+++ b/src/base/tl/base.h
@@ -5,7 +5,7 @@
 
 #include <base/system.h>
 
-inline void assert(bool statement)
+inline void tl_assert(bool statement)
 {
 	dbg_assert(statement, "assert!");
 }
diff --git a/src/base/tl/range.h b/src/base/tl/range.h
index f05169fa..1d225f49 100644
--- a/src/base/tl/range.h
+++ b/src/base/tl/range.h
@@ -150,11 +150,11 @@ public:
 	}
 
 	bool empty() const { return begin >= end; }
-	void pop_front() { assert(!empty()); begin++; }
-	void pop_back() { assert(!empty()); end--; }
-	T& front() { assert(!empty()); return *begin; }
-	T& back() { assert(!empty()); return *(end-1); }
-	T& index(unsigned i) { assert(i >= 0 && i < (unsigned)(end-begin)); return begin[i]; }
+	void pop_front() { tl_assert(!empty()); begin++; }
+	void pop_back() { tl_assert(!empty()); end--; }
+	T& front() { tl_assert(!empty()); return *begin; }
+	T& back() { tl_assert(!empty()); return *(end-1); }
+	T& index(unsigned i) { tl_assert(i < (unsigned)(end-begin)); return begin[i]; }
 	unsigned size() const { return (unsigned)(end-begin); }
 	plain_range slice(unsigned startindex, unsigned endindex)
 	{
diff --git a/src/base/tl/threading.h b/src/base/tl/threading.h
index dbf788cd..5caf8588 100644
--- a/src/base/tl/threading.h
+++ b/src/base/tl/threading.h
@@ -58,15 +58,21 @@
 	#error missing atomic implementation for this compiler
 #endif
 
-class semaphore
-{
-	SEMAPHORE sem;
-public:
-	semaphore() { semaphore_init(&sem); }
-	~semaphore() { semaphore_destroy(&sem); }
-	void wait() { semaphore_wait(&sem); }
-	void signal() { semaphore_signal(&sem); }
-};
+#if defined(CONF_PLATFORM_MACOSX)
+	/*
+		use semaphore provided by SDL on macosx
+	*/
+#else
+	class semaphore
+	{
+		SEMAPHORE sem;
+	public:
+		semaphore() { semaphore_init(&sem); }
+		~semaphore() { semaphore_destroy(&sem); }
+		void wait() { semaphore_wait(&sem); }
+		void signal() { semaphore_signal(&sem); }
+	};
+#endif
 
 class lock
 {
diff --git a/src/engine/client/backend_sdl.cpp b/src/engine/client/backend_sdl.cpp
index e7975aca..37d1019a 100644
--- a/src/engine/client/backend_sdl.cpp
+++ b/src/engine/client/backend_sdl.cpp
@@ -11,6 +11,9 @@
 
 void CGraphicsBackend_Threaded::ThreadFunc(void *pUser)
 {
+	#ifdef CONF_PLATFORM_MACOSX
+		CAutoreleasePool AutoreleasePool;
+	#endif
 	CGraphicsBackend_Threaded *pThis = (CGraphicsBackend_Threaded *)pUser;
 
 	while(!pThis->m_Shutdown)
@@ -97,6 +100,41 @@ int CCommandProcessorFragment_OpenGL::TexFormatToOpenGLFormat(int TexFormat)
 	return GL_RGBA;
 }
 
+unsigned char CCommandProcessorFragment_OpenGL::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp)
+{
+	int Value = 0;
+	for(int x = 0; x < ScaleW; x++)
+		for(int y = 0; y < ScaleH; y++)
+			Value += pData[((v+y)*w+(u+x))*Bpp+Offset];
+	return Value/(ScaleW*ScaleH);
+}
+
+void *CCommandProcessorFragment_OpenGL::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData)
+{
+	unsigned char *pTmpData;
+	int ScaleW = Width/NewWidth;
+	int ScaleH = Height/NewHeight;
+
+	int Bpp = 3;
+	if(Format == CCommandBuffer::TEXFORMAT_RGBA)
+		Bpp = 4;
+
+	pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1);
+
+	int c = 0;
+	for(int y = 0; y < NewHeight; y++)
+		for(int x = 0; x < NewWidth; x++, c++)
+		{
+			pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp);
+			pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp);
+			pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp);
+			if(Bpp == 4)
+				pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp);
+		}
+
+	return pTmpData;
+}
+
 void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &State)
 {
 	// blend
@@ -130,7 +168,7 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
 	if(State.m_Texture >= 0 && State.m_Texture < CCommandBuffer::MAX_TEXTURES)
 	{
 		glEnable(GL_TEXTURE_2D);
-		glBindTexture(GL_TEXTURE_2D, m_aTextures[State.m_Texture]);
+		glBindTexture(GL_TEXTURE_2D, m_aTextures[State.m_Texture].m_Tex);
 	}
 	else
 		glDisable(GL_TEXTURE_2D);
@@ -155,9 +193,14 @@ void CCommandProcessorFragment_OpenGL::SetState(const CCommandBuffer::SState &St
 	glOrtho(State.m_ScreenTL.x, State.m_ScreenBR.x, State.m_ScreenBR.y, State.m_ScreenTL.y, 1.0f, 10.f);
 }
 
+void CCommandProcessorFragment_OpenGL::Cmd_Init(const SCommand_Init *pCommand)
+{
+	m_pTextureMemoryUsage = pCommand->m_pTextureMemoryUsage;
+}
+
 void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand)
 {
-	glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot]);
+	glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot].m_Tex);
 	glTexSubImage2D(GL_TEXTURE_2D, 0, pCommand->m_X, pCommand->m_Y, pCommand->m_Width, pCommand->m_Height,
 		TexFormatToOpenGLFormat(pCommand->m_Format), GL_UNSIGNED_BYTE, pCommand->m_pData);
 	mem_free(pCommand->m_pData);
@@ -165,31 +208,85 @@ void CCommandProcessorFragment_OpenGL::Cmd_Texture_Update(const CCommandBuffer::
 
 void CCommandProcessorFragment_OpenGL::Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand)
 {
-	glDeleteTextures(1, &m_aTextures[pCommand->m_Slot]);
+	glDeleteTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex);
+	*m_pTextureMemoryUsage -= m_aTextures[pCommand->m_Slot].m_MemSize;
 }
 
 void CCommandProcessorFragment_OpenGL::Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand)
 {
+	int Width = pCommand->m_Width;
+	int Height = pCommand->m_Height;
+	void *pTexData = pCommand->m_pData;
+
+	// resample if needed
+	if(pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGBA || pCommand->m_Format == CCommandBuffer::TEXFORMAT_RGB)
+	{
+		int MaxTexSize;

+		glGetIntegerv(GL_MAX_TEXTURE_SIZE, &MaxTexSize);
+		if(Width > MaxTexSize || Height > MaxTexSize)
+		{
+			do
+			{
+				Width>>=1;
+				Height>>=1;
+			}
+			while(Width > MaxTexSize || Height > MaxTexSize);
+
+			void *pTmpData = Rescale(pCommand->m_Width, pCommand->m_Height, Width, Height, pCommand->m_Format, static_cast<const unsigned char *>(pCommand->m_pData));
+			mem_free(pTexData);
+			pTexData = pTmpData;
+		}
+		else if(Width > 16 && Height > 16 && (pCommand->m_Flags&CCommandBuffer::TEXFLAG_QUALITY) == 0)
+		{
+			Width>>=1;
+			Height>>=1;
+
+			void *pTmpData = Rescale(pCommand->m_Width, pCommand->m_Height, Width, Height, pCommand->m_Format, static_cast<const unsigned char *>(pCommand->m_pData));
+			mem_free(pTexData);
+			pTexData = pTmpData;
+		}
+	}
+
 	int Oglformat = TexFormatToOpenGLFormat(pCommand->m_Format);
 	int StoreOglformat = TexFormatToOpenGLFormat(pCommand->m_StoreFormat);
 
-	glGenTextures(1, &m_aTextures[pCommand->m_Slot]);
-	glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot]);
+	if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_COMPRESSED)
+	{
+		switch(StoreOglformat)
+		{
+			case GL_RGB: StoreOglformat = GL_COMPRESSED_RGB_ARB; break;
+			case GL_ALPHA: StoreOglformat = GL_COMPRESSED_ALPHA_ARB; break;
+			case GL_RGBA: StoreOglformat = GL_COMPRESSED_RGBA_ARB; break;
+			default: StoreOglformat = GL_COMPRESSED_RGBA_ARB;
+		}
+	}
+	glGenTextures(1, &m_aTextures[pCommand->m_Slot].m_Tex);
+	glBindTexture(GL_TEXTURE_2D, m_aTextures[pCommand->m_Slot].m_Tex);
 
 	if(pCommand->m_Flags&CCommandBuffer::TEXFLAG_NOMIPMAPS)
 	{
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MAG_FILTER, GL_LINEAR);
 		glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_MIN_FILTER, GL_LINEAR);
-		glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, pCommand->m_Width, pCommand->m_Height, 0, Oglformat, GL_UNSIGNED_BYTE, pCommand->m_pData);
+		glTexImage2D(GL_TEXTURE_2D, 0, StoreOglformat, Width, Height, 0, Oglformat, GL_UNSIGNED_BYTE, pTexData);
 	}
 	else
 	{
 		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, StoreOglformat, pCommand->m_Width, pCommand->m_Height, Oglformat, GL_UNSIGNED_BYTE, pCommand->m_pData);
+		gluBuild2DMipmaps(GL_TEXTURE_2D, StoreOglformat, Width, Height, Oglformat, GL_UNSIGNED_BYTE, pTexData);
 	}
 
-	mem_free(pCommand->m_pData);
+	// calculate memory usage
+	m_aTextures[pCommand->m_Slot].m_MemSize = Width*Height*pCommand->m_PixelSize;
+	while(Width > 2 && Height > 2)
+	{
+		Width>>=1;
+		Height>>=1;
+		m_aTextures[pCommand->m_Slot].m_MemSize += Width*Height*pCommand->m_PixelSize;
+	}
+	*m_pTextureMemoryUsage += m_aTextures[pCommand->m_Slot].m_MemSize;
+
+	mem_free(pTexData);
 }
 
 void CCommandProcessorFragment_OpenGL::Cmd_Clear(const CCommandBuffer::SCommand_Clear *pCommand)
@@ -260,12 +357,14 @@ void CCommandProcessorFragment_OpenGL::Cmd_Screenshot(const CCommandBuffer::SCom
 CCommandProcessorFragment_OpenGL::CCommandProcessorFragment_OpenGL()
 {
 	mem_zero(m_aTextures, sizeof(m_aTextures));
+	m_pTextureMemoryUsage = 0;
 }
 
 bool CCommandProcessorFragment_OpenGL::RunCommand(const CCommandBuffer::SCommand * pBaseCommand)
 {
 	switch(pBaseCommand->m_Cmd)
 	{
+	case CMD_INIT: Cmd_Init(static_cast<const SCommand_Init *>(pBaseCommand)); break;
 	case CCommandBuffer::CMD_TEXTURE_CREATE: Cmd_Texture_Create(static_cast<const CCommandBuffer::SCommand_Texture_Create *>(pBaseCommand)); break;
 	case CCommandBuffer::CMD_TEXTURE_DESTROY: Cmd_Texture_Destroy(static_cast<const CCommandBuffer::SCommand_Texture_Destroy *>(pBaseCommand)); break;
 	case CCommandBuffer::CMD_TEXTURE_UPDATE: Cmd_Texture_Update(static_cast<const CCommandBuffer::SCommand_Texture_Update *>(pBaseCommand)); break;
@@ -388,7 +487,7 @@ void CCommandProcessor_SDL_OpenGL::RunBuffer(CCommandBuffer *pBuffer)
 
 // ------------ CGraphicsBackend_SDL_OpenGL
 
-int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags)
+int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags)
 {
 	if(!SDL_WasInit(SDL_INIT_VIDEO))
 	{
@@ -400,13 +499,20 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
 
 		#ifdef CONF_FAMILY_WINDOWS
 			if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
-				putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention
+				putenv("SDL_VIDEO_WINDOW_POS=center"); // ignore_convention
 		#endif
 	}
 
 	const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
 	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
 
+	// use current resolution as default
+	if(*Width == 0 || *Height == 0)
+	{
+		*Width = pInfo->current_w;
+		*Height = pInfo->current_h;
+	}
+
 	// set flags
 	int SdlFlags = SDL_OPENGL;
 	if(Flags&IGraphicsBackend::INITFLAG_RESIZABLE)
@@ -420,6 +526,13 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
 	if(pInfo->blit_hw) // ignore_convention
 		SdlFlags |= SDL_HWACCEL;
 
+	dbg_assert(!(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
+		|| !(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN),
+		"only one of borderless and fullscreen may be activated at the same time");
+
+	if(Flags&IGraphicsBackend::INITFLAG_BORDERLESS)
+		SdlFlags |= SDL_NOFRAME;
+
 	if(Flags&IGraphicsBackend::INITFLAG_FULLSCREEN)
 		SdlFlags |= SDL_FULLSCREEN;
 
@@ -436,13 +549,13 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
 	}
 
 	SDL_GL_SetAttribute(SDL_GL_DOUBLEBUFFER, 1);
-	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&CCommandBuffer::INITFLAG_VSYNC ? 1 : 0);
+	SDL_GL_SetAttribute(SDL_GL_SWAP_CONTROL, Flags&IGraphicsBackend::INITFLAG_VSYNC ? 1 : 0);
 
 	// set caption
 	SDL_WM_SetCaption(pName, pName);
 
 	// create window
-	m_pScreenSurface = SDL_SetVideoMode(Width, Height, 0, SdlFlags);
+	m_pScreenSurface = SDL_SetVideoMode(*Width, *Height, 0, SdlFlags);
 	if(!m_pScreenSurface)
 	{
 		dbg_msg("gfx", "unable to set video mode: %s", SDL_GetError());
@@ -460,11 +573,14 @@ int CGraphicsBackend_SDL_OpenGL::Init(const char *pName, int Width, int Height,
 	m_pProcessor = new CCommandProcessor_SDL_OpenGL;
 	StartProcessor(m_pProcessor);
 
-	// issue a init command
+	// issue init commands for OpenGL and SDL
 	CCommandBuffer CmdBuffer(1024, 512);
-	CCommandProcessorFragment_SDL::SCommand_Init Cmd;
-	Cmd.m_Context = m_GLContext;
-	CmdBuffer.AddCommand(Cmd);
+	CCommandProcessorFragment_OpenGL::SCommand_Init CmdOpenGL;
+	CmdOpenGL.m_pTextureMemoryUsage = &m_TextureMemoryUsage;
+	CmdBuffer.AddCommand(CmdOpenGL);
+	CCommandProcessorFragment_SDL::SCommand_Init CmdSDL;
+	CmdSDL.m_Context = m_GLContext;
+	CmdBuffer.AddCommand(CmdSDL);
 	RunBuffer(&CmdBuffer);
 	WaitForIdle();
 
@@ -490,6 +606,11 @@ int CGraphicsBackend_SDL_OpenGL::Shutdown()
 	return 0;
 }
 
+int CGraphicsBackend_SDL_OpenGL::MemoryUsage() const
+{
+	return m_TextureMemoryUsage;
+}
+
 void CGraphicsBackend_SDL_OpenGL::Minimize()
 {
 	SDL_WM_IconifyWindow();
diff --git a/src/engine/client/backend_sdl.h b/src/engine/client/backend_sdl.h
index c6c2255a..e90f9455 100644
--- a/src/engine/client/backend_sdl.h
+++ b/src/engine/client/backend_sdl.h
@@ -28,24 +28,72 @@
 	static void GL_SwapBuffers(const SGLContext &Context) { SwapBuffers(Context.m_hDC); }
 #elif defined(CONF_PLATFORM_MACOSX)
 
-	#include <AGL/agl.h>
+	#include <objc/objc-runtime.h>
+
+	class semaphore
+	{
+		SDL_sem *sem;
+	public:
+		semaphore() { sem = SDL_CreateSemaphore(0); }
+		~semaphore() { SDL_DestroySemaphore(sem); }
+		void wait() { SDL_SemWait(sem); }
+		void signal() { SDL_SemPost(sem); }
+	};
 
 	struct SGLContext
 	{
-		AGLContext m_Context;
+		id m_Context;
 	};
 
 	static SGLContext GL_GetCurrentContext()
 	{
 		SGLContext Context;
-		Context.m_Context = aglGetCurrentContext();
+		Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
+		SEL selector = sel_registerName("currentContext");
+		Context.m_Context = objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
 		return Context;
 	}
 
-	static void GL_MakeCurrent(const SGLContext &Context) { aglSetCurrentContext(Context.m_Context); }
-	static void GL_ReleaseContext(const SGLContext &Context) { aglSetCurrentContext(NULL); }
-	static void GL_SwapBuffers(const SGLContext &Context) { aglSwapBuffers(Context.m_Context); }
-		
+	static void GL_MakeCurrent(const SGLContext &Context)
+	{
+		SEL selector = sel_registerName("makeCurrentContext");
+		objc_msgSend(Context.m_Context, selector);
+	}
+
+	static void GL_ReleaseContext(const SGLContext &Context)
+	{
+		Class NSOpenGLContextClass = (Class) objc_getClass("NSOpenGLContext");
+		SEL selector = sel_registerName("clearCurrentContext");
+		objc_msgSend((objc_object*) NSOpenGLContextClass, selector);
+	}
+
+	static void GL_SwapBuffers(const SGLContext &Context)
+	{
+		SEL selector = sel_registerName("flushBuffer");
+		objc_msgSend(Context.m_Context, selector);
+	}
+
+	class CAutoreleasePool
+	{
+	private:
+		id m_Pool;
+
+	public:
+		CAutoreleasePool()
+		{
+			Class NSAutoreleasePoolClass = (Class) objc_getClass("NSAutoreleasePool");
+			m_Pool = class_createInstance(NSAutoreleasePoolClass, 0);
+			SEL selector = sel_registerName("init");
+			objc_msgSend(m_Pool, selector);
+		}
+
+		~CAutoreleasePool()
+		{
+			SEL selector = sel_registerName("drain");
+			objc_msgSend(m_Pool, selector);
+		}
+	};							
+
 #elif defined(CONF_FAMILY_UNIX)
 
 	#include <GL/glx.h>
@@ -119,11 +167,34 @@ public:
 // takes care of opengl related rendering
 class CCommandProcessorFragment_OpenGL
 {
-	GLuint m_aTextures[CCommandBuffer::MAX_TEXTURES];
+	struct CTexture
+	{
+		GLuint m_Tex;
+		int m_MemSize;
+	};
+	CTexture m_aTextures[CCommandBuffer::MAX_TEXTURES];
+	volatile int *m_pTextureMemoryUsage;
+
+public:
+	enum
+	{
+		CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_OPENGL,
+	};
+
+	struct SCommand_Init : public CCommandBuffer::SCommand
+	{
+		SCommand_Init() : SCommand(CMD_INIT) {}
+		volatile int *m_pTextureMemoryUsage;
+	};
+
+private:
 	static int TexFormatToOpenGLFormat(int TexFormat);
+	static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
+	static void *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
 
 	void SetState(const CCommandBuffer::SState &State);
 
+	void Cmd_Init(const SCommand_Init *pCommand);
 	void Cmd_Texture_Update(const CCommandBuffer::SCommand_Texture_Update *pCommand);
 	void Cmd_Texture_Destroy(const CCommandBuffer::SCommand_Texture_Destroy *pCommand);
 	void Cmd_Texture_Create(const CCommandBuffer::SCommand_Texture_Create *pCommand);
@@ -145,7 +216,7 @@ class CCommandProcessorFragment_SDL
 public:
 	enum
 	{
-		CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM,
+		CMD_INIT = CCommandBuffer::CMDGROUP_PLATFORM_SDL,
 		CMD_SHUTDOWN,
 	};
 
@@ -187,10 +258,13 @@ class CGraphicsBackend_SDL_OpenGL : public CGraphicsBackend_Threaded
 	SDL_Surface *m_pScreenSurface;
 	ICommandProcessor *m_pProcessor;
 	SGLContext m_GLContext;
+	volatile int m_TextureMemoryUsage;
 public:
-	virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags);
+	virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags);
 	virtual int Shutdown();
 
+	virtual int MemoryUsage() const;
+
 	virtual void Minimize();
 	virtual void Maximize();
 	virtual int WindowActive();
diff --git a/src/engine/client/client.cpp b/src/engine/client/client.cpp
index d5da647b..30f92eb0 100644
--- a/src/engine/client/client.cpp
+++ b/src/engine/client/client.cpp
@@ -137,14 +137,16 @@ void CGraph::Render(IGraphics *pGraphics, int Font, float x, float y, float w, f
 	pGraphics->LinesEnd();
 
 	pGraphics->TextureSet(Font);
-	pGraphics->QuadsText(x+2, y+h-16, 16, 1,1,1,1, pDescription);
+	pGraphics->QuadsBegin();
+	pGraphics->QuadsText(x+2, y+h-16, 16, pDescription);
 
 	char aBuf[32];
 	str_format(aBuf, sizeof(aBuf), "%.2f", m_Max);
-	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+2, 16, 1,1,1,1, aBuf);
+	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+2, 16, aBuf);
 
 	str_format(aBuf, sizeof(aBuf), "%.2f", m_Min);
-	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+h-16, 16, 1,1,1,1, aBuf);
+	pGraphics->QuadsText(x+w-8*str_length(aBuf)-8, y+h-16, 16, aBuf);
+	pGraphics->QuadsEnd();
 }
 
 
@@ -678,6 +680,7 @@ void CClient::DebugRender()
 	//m_pGraphics->BlendNormal();
 	Graphics()->TextureSet(m_DebugFont);
 	Graphics()->MapScreen(0,0,Graphics()->ScreenWidth(),Graphics()->ScreenHeight());
+	Graphics()->QuadsBegin();
 
 	if(time_get()-LastSnap > time_freq())
 	{
@@ -699,7 +702,7 @@ void CClient::DebugRender()
 		mem_stats()->total_allocations,
 		Graphics()->MemoryUsage()/1024,
 		(int)(1.0f/FrameTimeAvg + 0.5f));
-	Graphics()->QuadsText(2, 2, 16, 1,1,1,1, aBuffer);
+	Graphics()->QuadsText(2, 2, 16, aBuffer);
 
 
 	{
@@ -715,7 +718,7 @@ void CClient::DebugRender()
 		str_format(aBuffer, sizeof(aBuffer), "send: %3d %5d+%4d=%5d (%3d kbps) avg: %5d\nrecv: %3d %5d+%4d=%5d (%3d kbps) avg: %5d",
 			SendPackets, SendBytes, SendPackets*42, SendTotal, (SendTotal*8)/1024, SendBytes/SendPackets,
 			RecvPackets, RecvBytes, RecvPackets*42, RecvTotal, (RecvTotal*8)/1024, RecvBytes/RecvPackets);
-		Graphics()->QuadsText(2, 14, 16, 1,1,1,1, aBuffer);
+		Graphics()->QuadsText(2, 14, 16, aBuffer);
 	}
 
 	// render rates
@@ -728,7 +731,7 @@ void CClient::DebugRender()
 			{
 				str_format(aBuffer, sizeof(aBuffer), "%4d %20s: %8d %8d %8d", i, GameClient()->GetItemName(i), m_SnapshotDelta.GetDataRate(i)/8, m_SnapshotDelta.GetDataUpdates(i),
 					(m_SnapshotDelta.GetDataRate(i)/m_SnapshotDelta.GetDataUpdates(i))/8);
-				Graphics()->QuadsText(2, 100+y*12, 16, 1,1,1,1, aBuffer);
+				Graphics()->QuadsText(2, 100+y*12, 16, aBuffer);
 				y++;
 			}
 		}
@@ -736,7 +739,8 @@ void CClient::DebugRender()
 
 	str_format(aBuffer, sizeof(aBuffer), "pred: %d ms",
 		(int)((m_PredictedTime.Get(Now)-m_GameTime.Get(Now))*1000/(float)time_freq()));
-	Graphics()->QuadsText(2, 70, 16, 1,1,1,1, aBuffer);
+	Graphics()->QuadsText(2, 70, 16, aBuffer);
+	Graphics()->QuadsEnd();
 
 	// render graphs
 	if(g_Config.m_DbgGraphs)
@@ -1310,7 +1314,6 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
 					}
 
 					// unpack delta
-					PurgeTick = DeltaTick;
 					SnapSize = m_SnapshotDelta.UnpackDelta(pDeltaShot, pTmpBuffer3, pDeltaData, DeltaSize);
 					if(SnapSize < 0)
 					{
@@ -1349,7 +1352,7 @@ void CClient::ProcessServerPacket(CNetChunk *pPacket)
 					if(m_aSnapshots[SNAP_PREV] && m_aSnapshots[SNAP_PREV]->m_Tick < PurgeTick)
 						PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
 					if(m_aSnapshots[SNAP_CURRENT] && m_aSnapshots[SNAP_CURRENT]->m_Tick < PurgeTick)
-						PurgeTick = m_aSnapshots[SNAP_PREV]->m_Tick;
+						PurgeTick = m_aSnapshots[SNAP_CURRENT]->m_Tick;
 					m_SnapshotStorage.PurgeUntil(PurgeTick);
 
 					// add new
@@ -1746,14 +1749,19 @@ void CClient::Run()
 	// open socket
 	{
 		NETADDR BindAddr;
-		if(g_Config.m_Bindaddr[0] == 0 || net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) != 0)
+		if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
+		{
+			// got bindaddr
+			BindAddr.type = NETTYPE_ALL;
+		}
+		else
 		{
 			mem_zero(&BindAddr, sizeof(BindAddr));
 			BindAddr.type = NETTYPE_ALL;
 		}
 		if(!m_NetClient.Open(BindAddr, 0))
 		{
-			dbg_msg("client", "couldn't start network");
+			dbg_msg("client", "couldn't open socket");
 			return;
 		}
 	}
@@ -1937,10 +1945,10 @@ void CClient::Run()
 			break;
 
 		// beNice
-		if(g_Config.m_DbgStress)
+		if(g_Config.m_ClCpuThrottle)
+			thread_sleep(g_Config.m_ClCpuThrottle);
+		else if(g_Config.m_DbgStress || !m_pGraphics->WindowActive())
 			thread_sleep(5);
-		else if(g_Config.m_ClCpuThrottle || !m_pGraphics->WindowActive())
-			thread_sleep(1);
 
 		if(g_Config.m_DbgHitch)
 		{
diff --git a/src/engine/client/client.h b/src/engine/client/client.h
index d958b49a..87e2bc70 100644
--- a/src/engine/client/client.h
+++ b/src/engine/client/client.h
@@ -175,8 +175,6 @@ class CClient : public IClient, public CDemoPlayer::IListner
 		class CHostLookup m_VersionServeraddr;
 	} m_VersionInfo;
 
-	semaphore m_GfxRenderSemaphore;
-	semaphore m_GfxStateSemaphore;
 	volatile int m_GfxState;
 	static void GraphicsThreadProxy(void *pThis) { ((CClient*)pThis)->GraphicsThread(); }
 	void GraphicsThread();
diff --git a/src/engine/client/graphics.cpp b/src/engine/client/graphics.cpp
index 2111703e..2e8a855d 100644
--- a/src/engine/client/graphics.cpp
+++ b/src/engine/client/graphics.cpp
@@ -22,6 +22,20 @@
 #include "graphics.h"
 
 
+#if defined(CONF_PLATFORM_MACOSX)
+
+	class semaphore
+	{
+		SDL_sem *sem;
+	public:
+		semaphore() { sem = SDL_CreateSemaphore(0); }
+		~semaphore() { SDL_DestroySemaphore(sem); }
+		void wait() { SDL_SemWait(sem); }
+		void signal() { SDL_SemPost(sem); }
+	};
+#endif
+
+
 static CVideoMode g_aFakeModes[] = {
 	{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},
@@ -686,13 +700,10 @@ void CGraphics_OpenGL::QuadsDrawFreeform(const CFreeformItem *pArray, int Num)
 	AddVertices(4*Num);
 }
 
-void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
+void CGraphics_OpenGL::QuadsText(float x, float y, float Size, const char *pText)
 {
 	float StartX = x;
 
-	QuadsBegin();
-	SetColor(r,g,b,a);
-
 	while(*pText)
 	{
 		char c = *pText;
@@ -716,8 +727,6 @@ void CGraphics_OpenGL::QuadsText(float x, float y, float Size, float r, float g,
 			x += Size/2;
 		}
 	}
-
-	QuadsEnd();
 }
 
 int CGraphics_OpenGL::Init()
@@ -761,12 +770,19 @@ int CGraphics_OpenGL::Init()
 
 int CGraphics_SDL::TryInit()
 {
-	m_ScreenWidth = g_Config.m_GfxScreenWidth;
-	m_ScreenHeight = g_Config.m_GfxScreenHeight;
-
 	const SDL_VideoInfo *pInfo = SDL_GetVideoInfo();
 	SDL_EventState(SDL_MOUSEMOTION, SDL_IGNORE); // prevent stuck mouse cursor sdl-bug when loosing fullscreen focus in windows
 
+	// use current resolution as default
+	if(g_Config.m_GfxScreenWidth == 0 || g_Config.m_GfxScreenHeight == 0)
+	{
+		g_Config.m_GfxScreenWidth = pInfo->current_w;
+		g_Config.m_GfxScreenHeight = pInfo->current_h;
+	}
+
+	m_ScreenWidth = g_Config.m_GfxScreenWidth;
+	m_ScreenHeight = g_Config.m_GfxScreenHeight;
+
 	// set flags
 	int Flags = SDL_OPENGL;
 	if(g_Config.m_DbgResizable)
@@ -780,7 +796,15 @@ int CGraphics_SDL::TryInit()
 	if(pInfo->blit_hw) // ignore_convention
 		Flags |= SDL_HWACCEL;
 
-	if(g_Config.m_GfxFullscreen)
+	if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+	{
+		dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
+		g_Config.m_GfxBorderless = 0;
+	}
+
+	if(g_Config.m_GfxBorderless)
+		Flags |= SDL_NOFRAME;
+	else if(g_Config.m_GfxFullscreen)
 		Flags |= SDL_FULLSCREEN;
 
 	// set gl attributes
@@ -876,7 +900,7 @@ int CGraphics_SDL::Init()
 
 	#ifdef CONF_FAMILY_WINDOWS
 		if(!getenv("SDL_VIDEO_WINDOW_POS") && !getenv("SDL_VIDEO_CENTERED")) // ignore_convention
-			putenv("SDL_VIDEO_WINDOW_POS=8,27"); // ignore_convention
+			putenv("SDL_VIDEO_WINDOW_POS=center"); // ignore_convention
 	#endif
 
 	if(InitWindow() != 0)
@@ -929,7 +953,8 @@ void CGraphics_SDL::Swap()
 {
 	if(m_DoScreenshot)
 	{
-		ScreenshotDirect(m_aScreenshotName);
+		if(WindowActive())
+			ScreenshotDirect(m_aScreenshotName);
 		m_DoScreenshot = false;
 	}
 
diff --git a/src/engine/client/graphics.h b/src/engine/client/graphics.h
index fdd83aa7..670c22b4 100644
--- a/src/engine/client/graphics.h
+++ b/src/engine/client/graphics.h
@@ -119,7 +119,7 @@ public:
 	virtual void QuadsDraw(CQuadItem *pArray, int Num);
 	virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
 	virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
-	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
+	virtual void QuadsText(float x, float y, float Size, const char *pText);
 
 	virtual int Init();
 };
diff --git a/src/engine/client/graphics_threaded.cpp b/src/engine/client/graphics_threaded.cpp
index b19e8a83..e34b7259 100644
--- a/src/engine/client/graphics_threaded.cpp
+++ b/src/engine/client/graphics_threaded.cpp
@@ -80,8 +80,27 @@ void CGraphics_Threaded::FlushVertices()
 		}
 	}
 
+	// check if we have enough free memory in the commandbuffer
+	if(!m_pCommandBuffer->AddCommand(Cmd))
+	{
+		// kick command buffer and try again
+		KickCommandBuffer();
+		
+		Cmd.m_pVertices = (CCommandBuffer::SVertex *)m_pCommandBuffer->AllocData(sizeof(CCommandBuffer::SVertex)*NumVerts);
+		if(Cmd.m_pVertices == 0x0)
+		{
+			dbg_msg("graphics", "failed to allocate data for vertices");
+			return;
+		}
+
+		if(!m_pCommandBuffer->AddCommand(Cmd))
+		{
+			dbg_msg("graphics", "failed to allocate memory for render command");
+			return;
+		}
+	}
+
 	mem_copy(Cmd.m_pVertices, m_aVertices, sizeof(CCommandBuffer::SVertex)*NumVerts);
-	m_pCommandBuffer->AddCommand(Cmd);
 }
 
 void CGraphics_Threaded::AddVertices(int Count)
@@ -107,41 +126,6 @@ void CGraphics_Threaded::Rotate4(const CCommandBuffer::SPoint &rCenter, CCommand
 	}
 }
 
-unsigned char CGraphics_Threaded::Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp)
-{
-	int Value = 0;
-	for(int x = 0; x < ScaleW; x++)
-		for(int y = 0; y < ScaleH; y++)
-			Value += pData[((v+y)*w+(u+x))*Bpp+Offset];
-	return Value/(ScaleW*ScaleH);
-}
-
-unsigned char *CGraphics_Threaded::Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData)
-{
-	unsigned char *pTmpData;
-	int ScaleW = Width/NewWidth;
-	int ScaleH = Height/NewHeight;
-
-	int Bpp = 3;
-	if(Format == CImageInfo::FORMAT_RGBA)
-		Bpp = 4;
-
-	pTmpData = (unsigned char *)mem_alloc(NewWidth*NewHeight*Bpp, 1);
-
-	int c = 0;
-	for(int y = 0; y < NewHeight; y++)
-		for(int x = 0; x < NewWidth; x++, c++)
-		{
-			pTmpData[c*Bpp] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 0, ScaleW, ScaleH, Bpp);
-			pTmpData[c*Bpp+1] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 1, ScaleW, ScaleH, Bpp);
-			pTmpData[c*Bpp+2] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 2, ScaleW, ScaleH, Bpp);
-			if(Bpp == 4)
-				pTmpData[c*Bpp+3] = Sample(Width, Height, pData, x*ScaleW, y*ScaleH, 3, ScaleW, ScaleH, Bpp);
-		}
-
-	return pTmpData;
-}
-
 CGraphics_Threaded::CGraphics_Threaded()
 {
 	m_State.m_ScreenTL.x = 0;
@@ -228,7 +212,7 @@ void CGraphics_Threaded::WrapClamp()
 
 int CGraphics_Threaded::MemoryUsage() const
 {
-	return m_TextureMemoryUsage;
+	return m_pBackend->MemoryUsage();
 }
 
 void CGraphics_Threaded::MapScreen(float TopLeftX, float TopLeftY, float BottomRightX, float BottomRightY)
@@ -293,8 +277,7 @@ int CGraphics_Threaded::UnloadTexture(int Index)
 	Cmd.m_Slot = Index;
 	m_pCommandBuffer->AddCommand(Cmd);
 
-	m_aTextures[Index].m_Next = m_FirstFreeTexture;
-	m_TextureMemoryUsage -= m_aTextures[Index].m_MemSize;
+	m_aTextureIndices[Index] = m_FirstFreeTexture;
 	m_FirstFreeTexture = Index;
 	return 0;
 }
@@ -307,6 +290,16 @@ static int ImageFormatToTexFormat(int Format)
 	return CCommandBuffer::TEXFORMAT_RGBA;
 }
 
+static int ImageFormatToPixelSize(int Format)
+{
+	switch(Format)
+	{
+	case CImageInfo::FORMAT_RGB: return 3;
+	case CImageInfo::FORMAT_ALPHA: return 1;
+	default: return 4;
+	}
+}
+
 
 int CGraphics_Threaded::LoadTextureRawSub(int TextureID, int x, int y, int Width, int Height, int Format, const void *pData)
 {
@@ -319,13 +312,7 @@ int CGraphics_Threaded::LoadTextureRawSub(int TextureID, int x, int y, int Width
 	Cmd.m_Format = ImageFormatToTexFormat(Format);
 
 	// calculate memory usage
-	int PixelSize = 4;
-	if(Format == CImageInfo::FORMAT_RGB)
-		PixelSize = 3;
-	else if(Format == CImageInfo::FORMAT_ALPHA)
-		PixelSize = 1;
-
-	int MemSize = Width*Height*PixelSize;
+	int MemSize = Width*Height*ImageFormatToPixelSize(Format);
 
 	// copy texture data
 	void *pTmpData = mem_alloc(MemSize, sizeof(void*));
@@ -345,13 +332,14 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
 
 	// grab texture
 	int Tex = m_FirstFreeTexture;
-	m_FirstFreeTexture = m_aTextures[Tex].m_Next;
-	m_aTextures[Tex].m_Next = -1;
+	m_FirstFreeTexture = m_aTextureIndices[Tex];
+	m_aTextureIndices[Tex] = -1;
 
 	CCommandBuffer::SCommand_Texture_Create Cmd;
 	Cmd.m_Slot = Tex;
 	Cmd.m_Width = Width;
 	Cmd.m_Height = Height;
+	Cmd.m_PixelSize = ImageFormatToPixelSize(Format);
 	Cmd.m_Format = ImageFormatToTexFormat(Format);
 	Cmd.m_StoreFormat = ImageFormatToTexFormat(StoreFormat);
 
@@ -359,17 +347,13 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
 	Cmd.m_Flags = 0;
 	if(Flags&IGraphics::TEXLOAD_NOMIPMAPS)
 		Cmd.m_Flags |= CCommandBuffer::TEXFLAG_NOMIPMAPS;
-
-	// calculate memory usage
-	int PixelSize = 4;
-	if(Format == CImageInfo::FORMAT_RGB)
-		PixelSize = 3;
-	else if(Format == CImageInfo::FORMAT_ALPHA)
-		PixelSize = 1;
-
-	int MemSize = Width*Height*PixelSize;
+	if(g_Config.m_GfxTextureCompression)
+		Cmd.m_Flags |= CCommandBuffer::TEXFLAG_COMPRESSED;
+	if(g_Config.m_GfxTextureQuality || Flags&TEXLOAD_NORESAMPLE)
+		Cmd.m_Flags |= CCommandBuffer::TEXFLAG_QUALITY;
 
 	// copy texture data
+	int MemSize = Width*Height*Cmd.m_PixelSize;
 	void *pTmpData = mem_alloc(MemSize, sizeof(void*));
 	mem_copy(pTmpData, pData, MemSize);
 	Cmd.m_pData = pTmpData;
@@ -377,17 +361,6 @@ int CGraphics_Threaded::LoadTextureRaw(int Width, int Height, int Format, const
 	//
 	m_pCommandBuffer->AddCommand(Cmd);
 
-	// calculate memory usage
-	int MemUsage = MemSize;
-	while(Width > 2 && Height > 2)
-	{
-		Width>>=1;
-		Height>>=1;
-		MemUsage += Width*Height*PixelSize;
-	}
-
-	m_TextureMemoryUsage += MemUsage;
-	//mem_free(pTmpData);
 	return Tex;
 }
 
@@ -675,13 +648,10 @@ void CGraphics_Threaded::QuadsDrawFreeform(const CFreeformItem *pArray, int Num)
 	AddVertices(4*Num);
 }
 
-void CGraphics_Threaded::QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText)
+void CGraphics_Threaded::QuadsText(float x, float y, float Size, const char *pText)
 {
 	float StartX = x;
 
-	QuadsBegin();
-	SetColor(r,g,b,a);
-
 	while(*pText)
 	{
 		char c = *pText;
@@ -705,18 +675,23 @@ void CGraphics_Threaded::QuadsText(float x, float y, float Size, float r, float
 			x += Size/2;
 		}
 	}
-
-	QuadsEnd();
 }
 
 int CGraphics_Threaded::IssueInit()
 {
 	int Flags = 0;
-	if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
+	if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+	{
+		dbg_msg("gfx", "both borderless and fullscreen activated, disabling borderless");
+		g_Config.m_GfxBorderless = 0;
+	}
+
+	if(g_Config.m_GfxBorderless) Flags |= IGraphicsBackend::INITFLAG_BORDERLESS;
+	else if(g_Config.m_GfxFullscreen) Flags |= IGraphicsBackend::INITFLAG_FULLSCREEN;
 	if(g_Config.m_GfxVsync) Flags |= IGraphicsBackend::INITFLAG_VSYNC;
 	if(g_Config.m_DbgResizable) Flags |= IGraphicsBackend::INITFLAG_RESIZABLE;
 
-	return m_pBackend->Init("Teeworlds", g_Config.m_GfxScreenWidth, g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
+	return m_pBackend->Init("Teeworlds", &g_Config.m_GfxScreenWidth, &g_Config.m_GfxScreenHeight, g_Config.m_GfxFsaaSamples, Flags);
 }
 
 int CGraphics_Threaded::InitWindow()
@@ -766,9 +741,9 @@ int CGraphics_Threaded::Init()
 
 	// init textures
 	m_FirstFreeTexture = 0;
-	for(int i = 0; i < MAX_TEXTURES; i++)
-		m_aTextures[i].m_Next = i+1;
-	m_aTextures[MAX_TEXTURES-1].m_Next = -1;
+	for(int i = 0; i < MAX_TEXTURES-1; i++)
+		m_aTextureIndices[i] = i+1;
+	m_aTextureIndices[MAX_TEXTURES-1] = -1;
 
 	m_pBackend = CreateGraphicsBackend();
 	if(InitWindow() != 0)
@@ -843,7 +818,8 @@ void CGraphics_Threaded::Swap()
 	// TODO: screenshot support
 	if(m_DoScreenshot)
 	{
-		ScreenshotDirect(m_aScreenshotName);
+		if(WindowActive())
+			ScreenshotDirect(m_aScreenshotName);
 		m_DoScreenshot = false;
 	}
 
diff --git a/src/engine/client/graphics_threaded.h b/src/engine/client/graphics_threaded.h
index f90f818d..ff03c6bb 100644
--- a/src/engine/client/graphics_threaded.h
+++ b/src/engine/client/graphics_threaded.h
@@ -57,7 +57,8 @@ public:
 	{
 		// commadn groups
 		CMDGROUP_CORE = 0, // commands that everyone has to implement
-		CMDGROUP_PLATFORM = 10000, // commands specific to a platform
+		CMDGROUP_PLATFORM_OPENGL = 10000, // commands specific to a platform
+		CMDGROUP_PLATFORM_SDL = 20000,
 
 		//
 		CMD_NOP = CMDGROUP_CORE,
@@ -94,13 +95,8 @@ public:
 		TEXFORMAT_ALPHA,
 
 		TEXFLAG_NOMIPMAPS = 1,
-	};
-
-	enum
-	{
-		INITFLAG_FULLSCREEN = 1,
-		INITFLAG_VSYNC = 2,
-		INITFLAG_RESIZABLE = 4,
+		TEXFLAG_COMPRESSED = 2,
+		TEXFLAG_QUALITY = 4,
 	};
 
 	enum
@@ -217,6 +213,7 @@ public:
 
 		int m_Width;
 		int m_Height;
+		int m_PixelSize;
 		int m_Format;
 		int m_StoreFormat;
 		int m_Flags;
@@ -300,11 +297,16 @@ public:
 		INITFLAG_FULLSCREEN = 1,
 		INITFLAG_VSYNC = 2,
 		INITFLAG_RESIZABLE = 4,
+		INITFLAG_BORDERLESS = 8,
 	};
 
-	virtual int Init(const char *pName, int Width, int Height, int FsaaSamples, int Flags) = 0;
+	virtual ~IGraphicsBackend() {}
+
+	virtual int Init(const char *pName, int *Width, int *Height, int FsaaSamples, int Flags) = 0;
 	virtual int Shutdown() = 0;
 
+	virtual int MemoryUsage() const = 0;
+
 	virtual void Minimize() = 0;
 	virtual void Maximize() = 0;
 	virtual int WindowActive() = 0;
@@ -354,15 +356,7 @@ class CGraphics_Threaded : public IEngineGraphics
 
 	int m_InvalidTexture;
 
-	struct CTexture
-	{
-		int m_State;
-		int m_MemSize;
-		int m_Flags;
-		int m_Next;
-	};
-
-	CTexture m_aTextures[MAX_TEXTURES];
+	int m_aTextureIndices[MAX_TEXTURES];
 	int m_FirstFreeTexture;
 	int m_TextureMemoryUsage;
 
@@ -370,9 +364,6 @@ class CGraphics_Threaded : public IEngineGraphics
 	void AddVertices(int Count);
 	void Rotate4(const CCommandBuffer::SPoint &rCenter, CCommandBuffer::SVertex *pPoints);
 
-	static unsigned char Sample(int w, int h, const unsigned char *pData, int u, int v, int Offset, int ScaleW, int ScaleH, int Bpp);
-	static unsigned char *Rescale(int Width, int Height, int NewWidth, int NewHeight, int Format, const unsigned char *pData);
-
 	void KickCommandBuffer();
 
 	int IssueInit();
@@ -428,7 +419,7 @@ public:
 	virtual void QuadsDraw(CQuadItem *pArray, int Num);
 	virtual void QuadsDrawTL(const CQuadItem *pArray, int Num);
 	virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num);
-	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText);
+	virtual void QuadsText(float x, float y, float Size, const char *pText);
 
 	virtual void Minimize();
 	virtual void Maximize();
diff --git a/src/engine/client/input.cpp b/src/engine/client/input.cpp
index 0b4a44a4..7ff8d6fe 100644
--- a/src/engine/client/input.cpp
+++ b/src/engine/client/input.cpp
@@ -35,6 +35,7 @@ CInput::CInput()
 
 	m_InputCurrent = 0;
 	m_InputGrabbed = 0;
+	m_InputDispatched = false;
 
 	m_LastRelease = 0;
 	m_ReleaseDelta = -1;
@@ -116,10 +117,14 @@ int CInput::Update()
 	/*if(!input_grabbed && Graphics()->WindowActive())
 		Input()->MouseModeRelative();*/
 
-	// clear and begin count on the other one
-	m_InputCurrent^=1;
-	mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
-	mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+	if(m_InputDispatched)
+	{
+		// clear and begin count on the other one
+		m_InputCurrent^=1;
+		mem_zero(&m_aInputCount[m_InputCurrent], sizeof(m_aInputCount[m_InputCurrent]));
+		mem_zero(&m_aInputState[m_InputCurrent], sizeof(m_aInputState[m_InputCurrent]));
+		m_InputDispatched = false;
+	}
 
 	{
 		int i;
diff --git a/src/engine/client/serverbrowser.cpp b/src/engine/client/serverbrowser.cpp
index 4dda9da9..588194ea 100644
--- a/src/engine/client/serverbrowser.cpp
+++ b/src/engine/client/serverbrowser.cpp
@@ -495,7 +495,7 @@ void CServerBrowser::Refresh(int Type)
 		/* do the broadcast version */
 		Packet.m_ClientID = -1;
 		mem_zero(&Packet, sizeof(Packet));
-		Packet.m_Address.type = NETTYPE_ALL|NETTYPE_LINK_BROADCAST;
+		Packet.m_Address.type = m_pNetClient->NetType()|NETTYPE_LINK_BROADCAST;
 		Packet.m_Flags = NETSENDFLAG_CONNLESS;
 		Packet.m_DataSize = sizeof(Buffer);
 		Packet.m_pData = Buffer;
diff --git a/src/engine/client/text.cpp b/src/engine/client/text.cpp
index af06fc11..d838ef29 100644
--- a/src/engine/client/text.cpp
+++ b/src/engine/client/text.cpp
@@ -639,7 +639,7 @@ public:
 					Compare.m_Y = DrawY;
 					Compare.m_Flags &= ~TEXTFLAG_RENDER;
 					Compare.m_LineWidth = -1;
-					TextEx(&Compare, pText, Wlen);
+					TextEx(&Compare, pCurrent, Wlen);
 
 					if(Compare.m_X-DrawX > pCursor->m_LineWidth)
 					{
diff --git a/src/engine/demo.h b/src/engine/demo.h
index 7b7365c7..bd4a307a 100644
--- a/src/engine/demo.h
+++ b/src/engine/demo.h
@@ -21,6 +21,10 @@ struct CDemoHeader
 	char m_aType[8];
 	char m_aLength[4];
 	char m_aTimestamp[20];
+};
+
+struct CTimelineMarkers
+{
 	char m_aNumTimelineMarkers[4];
 	char m_aTimelineMarkers[MAX_TIMELINE_MARKERS][4];
 };
diff --git a/src/engine/graphics.h b/src/engine/graphics.h
index 7f272497..a2fe4741 100644
--- a/src/engine/graphics.h
+++ b/src/engine/graphics.h
@@ -120,7 +120,7 @@ public:
 			: m_X0(x0), m_Y0(y0), m_X1(x1), m_Y1(y1), m_X2(x2), m_Y2(y2), m_X3(x3), m_Y3(y3) {}
 	};
 	virtual void QuadsDrawFreeform(const CFreeformItem *pArray, int Num) = 0;
-	virtual void QuadsText(float x, float y, float Size, float r, float g, float b, float a, const char *pText) = 0;
+	virtual void QuadsText(float x, float y, float Size, const char *pText) = 0;
 
 	struct CColorVertex
 	{
diff --git a/src/engine/input.h b/src/engine/input.h
index 7d28be10..93ceccd2 100644
--- a/src/engine/input.h
+++ b/src/engine/input.h
@@ -38,6 +38,7 @@ protected:
 
 	unsigned char m_aInputState[2][1024];
 	int m_InputCurrent;
+	bool m_InputDispatched;
 
 	int KeyWasPressed(int Key) { return m_aInputState[m_InputCurrent^1][Key]; }
 
@@ -51,7 +52,11 @@ public:
 
 	// events
 	int NumEvents() const { return m_NumEvents; }
-	void ClearEvents() { m_NumEvents = 0; }
+	void ClearEvents() 
+	{ 
+		m_NumEvents = 0;
+		m_InputDispatched = true;
+	}
 	CEvent GetEvent(int Index) const
 	{
 		if(Index < 0 || Index >= m_NumEvents)
diff --git a/src/engine/server/server.cpp b/src/engine/server/server.cpp
index 577c040f..4fa872eb 100644
--- a/src/engine/server/server.cpp
+++ b/src/engine/server/server.cpp
@@ -36,45 +36,23 @@
 	#include <windows.h>
 #endif
 
-static const char *StrUTF8Ltrim(const char *pStr)
+static const char *StrLtrim(const char *pStr)
 {
-	while(*pStr)
-	{
-		const char *pStrOld = pStr;
-		int Code = str_utf8_decode(&pStr);
-
-		// check if unicode is not empty
-		if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
-			(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
-			Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
-		{
-			return pStrOld;
-		}
-	}
+	while(*pStr && *pStr >= 0 && *pStr <= 32)
+		pStr++;
 	return pStr;
 }
 
-static void StrUTF8Rtrim(char *pStr)
+static void StrRtrim(char *pStr)
 {
-	const char *p = pStr;
-	const char *pEnd = 0;
-	while(*p)
+	int i = str_length(pStr);
+	while(i >= 0)
 	{
-		const char *pStrOld = p;
-		int Code = str_utf8_decode(&p);
-
-		// check if unicode is not empty
-		if(Code > 0x20 && Code != 0xA0 && Code != 0x034F && (Code < 0x2000 || Code > 0x200F) && (Code < 0x2028 || Code > 0x202F) &&
-			(Code < 0x205F || Code > 0x2064) && (Code < 0x206A || Code > 0x206F) && (Code < 0xFE00 || Code > 0xFE0F) &&
-			Code != 0xFEFF && (Code < 0xFFF9 || Code > 0xFFFC))
-		{
-			pEnd = 0;
-		}
-		else if(pEnd == 0)
-			pEnd = pStrOld;
+		if(pStr[i] < 0 || pStr[i] > 32)
+			break;
+		pStr[i] = 0;
+		i--;
 	}
-	if(pEnd != 0)
-		*(const_cast<char *>(pEnd)) = 0;
 }
 
 
@@ -167,7 +145,7 @@ void CSnapIDPool::FreeID(int ID)
 }
 
 
-void CServerBan::Init(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
+void CServerBan::InitServerBan(IConsole *pConsole, IStorage *pStorage, CServer* pServer)
 {
 	CNetBan::Init(pConsole, pStorage);
 
@@ -331,8 +309,12 @@ int CServer::TrySetClientName(int ClientID, const char *pName)
 	char aTrimmedName[64];
 
 	// trim the name
-	str_copy(aTrimmedName, StrUTF8Ltrim(pName), sizeof(aTrimmedName));
-	StrUTF8Rtrim(aTrimmedName);
+	str_copy(aTrimmedName, StrLtrim(pName), sizeof(aTrimmedName));
+	StrRtrim(aTrimmedName);
+
+	// check for empty names
+	if(!aTrimmedName[0])
+		return -1;
 
 	// check if new and old name are the same
 	if(m_aClients[ClientID].m_aName[0] && str_comp(m_aClients[ClientID].m_aName, aTrimmedName) == 0)
@@ -343,11 +325,6 @@ int CServer::TrySetClientName(int ClientID, const char *pName)
 	Console()->Print(IConsole::OUTPUT_LEVEL_ADDINFO, "server", aBuf);
 	pName = aTrimmedName;
 
-
-	// check for empty names
-	if(!pName[0])
-		return -1;
-
 	// make sure that two clients doesn't have the same name
 	for(int i = 0; i < MAX_CLIENTS; i++)
 		if(i != ClientID && m_aClients[i].m_State >= CClient::STATE_READY)
@@ -371,14 +348,23 @@ void CServer::SetClientName(int ClientID, const char *pName)
 	if(!pName)
 		return;
 
-	char aNameTry[MAX_NAME_LENGTH];
-	str_copy(aNameTry, pName, MAX_NAME_LENGTH);
-	if(TrySetClientName(ClientID, aNameTry))
+	char aCleanName[MAX_NAME_LENGTH];
+	str_copy(aCleanName, pName, sizeof(aCleanName));
+
+	// clear name
+	for(char *p = aCleanName; *p; ++p)
+	{
+		if(*p < 32)
+			*p = ' ';
+	}
+
+	if(TrySetClientName(ClientID, aCleanName))
 	{
 		// auto rename
 		for(int i = 1;; i++)
 		{
-			str_format(aNameTry, MAX_NAME_LENGTH, "(%d)%s", i, pName);
+			char aNameTry[MAX_NAME_LENGTH];
+			str_format(aNameTry, sizeof(aCleanName), "(%d)%s", i, aCleanName);
 			if(TrySetClientName(ClientID, aNameTry) == 0)
 				break;
 		}
@@ -870,6 +856,9 @@ void CServer::ProcessClientPacket(CNetChunk *pPacket)
 		}
 		else if(Msg == NETMSG_REQUEST_MAP_DATA)
 		{
+			if(m_aClients[ClientID].m_State < CClient::STATE_CONNECTING)
+				return;
+
 			int Chunk = Unpacker.GetInt();
 			int ChunkSize = 1024-128;
 			int Offset = Chunk * ChunkSize;
@@ -1270,10 +1259,6 @@ void CServer::InitRegister(CNetServer *pNetServer, IEngineMasterServer *pMasterS
 
 int CServer::Run()
 {
-	m_pGameServer = Kernel()->RequestInterface<IGameServer>();
-	m_pMap = Kernel()->RequestInterface<IEngineMap>();
-	m_pStorage = Kernel()->RequestInterface<IStorage>();
-
 	//
 	m_PrintCBIndex = Console()->RegisterPrintCallback(g_Config.m_ConsoleOutputLevel, SendRconLineAuthed, this);
 
@@ -1289,6 +1274,7 @@ int CServer::Run()
 	if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
 	{
 		// sweet!
+		BindAddr.type = NETTYPE_ALL;
 		BindAddr.port = g_Config.m_SvPort;
 	}
 	else
@@ -1306,7 +1292,6 @@ int CServer::Run()
 
 	m_NetServer.SetCallbacks(NewClientCallback, DelClientCallback, this);
 
-	m_ServerBan.Init(Console(), Storage(), this);
 	m_Econ.Init(Console(), &m_ServerBan);
 
 	char aBuf[256];
@@ -1482,8 +1467,12 @@ void CServer::ConStatus(IConsole::IResult *pResult, void *pUser)
 		{
 			net_addr_str(pThis->m_NetServer.ClientAddr(i), aAddrStr, sizeof(aAddrStr), true);
 			if(pThis->m_aClients[i].m_State == CClient::STATE_INGAME)
-				str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d", i, aAddrStr,
-					pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score);
+			{
+				const char *pAuthStr = pThis->m_aClients[i].m_Authed == CServer::AUTHED_ADMIN ? "(Admin)" :
+										pThis->m_aClients[i].m_Authed == CServer::AUTHED_MOD ? "(Mod)" : "";
+				str_format(aBuf, sizeof(aBuf), "id=%d addr=%s name='%s' score=%d %s", i, aAddrStr,
+					pThis->m_aClients[i].m_aName, pThis->m_aClients[i].m_Score, pAuthStr);
+			}
 			else
 				str_format(aBuf, sizeof(aBuf), "id=%d addr=%s connecting", i, aAddrStr);
 			pThis->Console()->Print(IConsole::OUTPUT_LEVEL_STANDARD, "Server", aBuf);
@@ -1564,6 +1553,7 @@ void CServer::ConLogout(IConsole::IResult *pResult, void *pUser)
 		pServer->SendMsgEx(&Msg, MSGFLAG_VITAL, pServer->m_RconClientID, true);
 
 		pServer->m_aClients[pServer->m_RconClientID].m_Authed = AUTHED_NO;
+		pServer->m_aClients[pServer->m_RconClientID].m_AuthTries = 0;
 		pServer->m_aClients[pServer->m_RconClientID].m_pRconCmdToSend = 0;
 		pServer->SendRconLine(pServer->m_RconClientID, "Logout successful.");
 		char aBuf[32];
@@ -1628,7 +1618,11 @@ void CServer::ConchainConsoleOutputLevelUpdate(IConsole::IResult *pResult, void
 void CServer::RegisterCommands()
 {
 	m_pConsole = Kernel()->RequestInterface<IConsole>();
+	m_pGameServer = Kernel()->RequestInterface<IGameServer>();
+	m_pMap = Kernel()->RequestInterface<IEngineMap>();
+	m_pStorage = Kernel()->RequestInterface<IStorage>();
 
+	// register console commands
 	Console()->Register("kick", "i?r", CFGFLAG_SERVER, ConKick, this, "Kick player with specified id for any reason");
 	Console()->Register("status", "", CFGFLAG_SERVER, ConStatus, this, "List players");
 	Console()->Register("shutdown", "", CFGFLAG_SERVER, ConShutdown, this, "Shut down");
@@ -1645,6 +1639,10 @@ void CServer::RegisterCommands()
 	Console()->Chain("sv_max_clients_per_ip", ConchainMaxclientsperipUpdate, this);
 	Console()->Chain("mod_command", ConchainModCommandUpdate, this);
 	Console()->Chain("console_output_level", ConchainConsoleOutputLevelUpdate, this);
+
+	// register console commands in sub parts
+	m_ServerBan.InitServerBan(Console(), Storage(), this);
+	m_pGameServer->OnConsoleInit();
 }
 
 
@@ -1725,7 +1723,6 @@ int main(int argc, const char **argv) // ignore_convention
 
 	// register all console commands
 	pServer->RegisterCommands();
-	pGameServer->OnConsoleInit();
 
 	/* This banmaster is added into the source of the server that i'm able to ban players even if no banmaster.cfg is used.
 	 * Often serverhoster doesn't add this file because they don't know what it is for and remove it, not
diff --git a/src/engine/server/server.h b/src/engine/server/server.h
index 27991746..4a1f7344 100644
--- a/src/engine/server/server.h
+++ b/src/engine/server/server.h
@@ -50,10 +50,10 @@ class CServerBan : public CNetBan
 public:
 	class CServer *Server() const { return m_pServer; }
 
-	void Init(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer);
+	void InitServerBan(class IConsole *pConsole, class IStorage *pStorage, class CServer* pServer);
 
-	int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
-	int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
+	virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
+	virtual int BanRange(const CNetRange *pRange, int Seconds, const char *pReason);
 
 	static void ConBanExt(class IConsole::IResult *pResult, void *pUser);
 };
diff --git a/src/engine/shared/config_variables.h b/src/engine/shared/config_variables.h
index 76e4ccd3..c588be5c 100644
--- a/src/engine/shared/config_variables.h
+++ b/src/engine/shared/config_variables.h
@@ -15,7 +15,7 @@ MACRO_CONFIG_STR(Password, password, 32, "", CFGFLAG_CLIENT|CFGFLAG_SERVER, "Pas
 MACRO_CONFIG_STR(Logfile, logfile, 128, "", CFGFLAG_SAVE|CFGFLAG_CLIENT|CFGFLAG_SERVER, "Filename to log all output to")
 MACRO_CONFIG_INT(ConsoleOutputLevel, console_output_level, 0, 0, 2, CFGFLAG_CLIENT|CFGFLAG_SERVER, "Adjusts the amount of information in the console")
 
-MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
+MACRO_CONFIG_INT(ClCpuThrottle, cl_cpu_throttle, 0, 0, 100, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
 MACRO_CONFIG_INT(ClEditor, cl_editor, 0, 0, 1, CFGFLAG_CLIENT, "")
 MACRO_CONFIG_INT(ClLoadCountryFlags, cl_load_country_flags, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Load and show country flags")
 
@@ -57,8 +57,9 @@ MACRO_CONFIG_INT(SndDevice, snd_device, -1, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "
 
 MACRO_CONFIG_INT(SndNonactiveMute, snd_nonactive_mute, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
 
-MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 800, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
-MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 600, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
+MACRO_CONFIG_INT(GfxScreenWidth, gfx_screen_width, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution width")
+MACRO_CONFIG_INT(GfxScreenHeight, gfx_screen_height, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen resolution height")
+MACRO_CONFIG_INT(GfxBorderless, gfx_borderless, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Borderless window (not to be used with fullscreen)")
 MACRO_CONFIG_INT(GfxFullscreen, gfx_fullscreen, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Fullscreen")
 MACRO_CONFIG_INT(GfxAlphabits, gfx_alphabits, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Alpha bits for framebuffer (fullscreen only)")
 MACRO_CONFIG_INT(GfxColorDepth, gfx_color_depth, 24, 16, 24, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Colors bits for framebuffer (fullscreen only)")
@@ -71,9 +72,9 @@ MACRO_CONFIG_INT(GfxTextureQuality, gfx_texture_quality, 1, 0, 1, CFGFLAG_SAVE|C
 MACRO_CONFIG_INT(GfxFsaaSamples, gfx_fsaa_samples, 0, 0, 16, CFGFLAG_SAVE|CFGFLAG_CLIENT, "FSAA Samples")
 MACRO_CONFIG_INT(GfxRefreshRate, gfx_refresh_rate, 0, 0, 0, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Screen refresh rate")
 MACRO_CONFIG_INT(GfxFinish, gfx_finish, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "")
-MACRO_CONFIG_INT(GfxAsyncRender, gfx_asyncrender, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Do rendering async from the the update")
+MACRO_CONFIG_INT(GfxAsyncRender, gfx_asyncrender, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Do rendering async from the the update")
 
-MACRO_CONFIG_INT(GfxThreaded, gfx_threaded, 1, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use the threaded graphics backend")
+MACRO_CONFIG_INT(GfxThreaded, gfx_threaded, 0, 0, 1, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Use the threaded graphics backend")
 
 MACRO_CONFIG_INT(InpMousesens, inp_mousesens, 100, 5, 100000, CFGFLAG_SAVE|CFGFLAG_CLIENT, "Mouse sensitivity")
 
diff --git a/src/engine/shared/console.cpp b/src/engine/shared/console.cpp
index 443c5904..399f5323 100644
--- a/src/engine/shared/console.cpp
+++ b/src/engine/shared/console.cpp
@@ -16,21 +16,21 @@
 
 const char *CConsole::CResult::GetString(unsigned Index)
 {
-	if (Index < 0 || Index >= m_NumArgs)
+	if (Index >= m_NumArgs)
 		return "";
 	return m_apArgs[Index];
 }
 
 int CConsole::CResult::GetInteger(unsigned Index)
 {
-	if (Index < 0 || Index >= m_NumArgs)
+	if (Index >= m_NumArgs)
 		return 0;
 	return str_toint(m_apArgs[Index]);
 }
 
 float CConsole::CResult::GetFloat(unsigned Index)
 {
-	if (Index < 0 || Index >= m_NumArgs)
+	if (Index >= m_NumArgs)
 		return 0.0f;
 	return str_tofloat(m_apArgs[Index]);
 }
@@ -68,7 +68,7 @@ int CConsole::ParseStart(CResult *pResult, const char *pString, int Length)
 	if(Length < Len)
 		Len = Length;
 
-	str_copy(pResult->m_aStringStorage, pString, Length);
+	str_copy(pResult->m_aStringStorage, pString, Len);
 	pStr = pResult->m_aStringStorage;
 
 	// get command
diff --git a/src/engine/shared/demo.cpp b/src/engine/shared/demo.cpp
index 37c82cce..953d8b56 100644
--- a/src/engine/shared/demo.cpp
+++ b/src/engine/shared/demo.cpp
@@ -14,6 +14,7 @@
 
 static const unsigned char gs_aHeaderMarker[7] = {'T', 'W', 'D', 'E', 'M', 'O', 0};
 static const unsigned char gs_ActVersion = 4;
+static const unsigned char gs_OldVersion = 3;
 static const int gs_LengthOffset = 152;
 static const int gs_NumMarkersOffset = 176;
 
@@ -29,6 +30,7 @@ CDemoRecorder::CDemoRecorder(class CSnapshotDelta *pSnapshotDelta)
 int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, const char *pFilename, const char *pNetVersion, const char *pMap, unsigned Crc, const char *pType)
 {
 	CDemoHeader Header;
+	CTimelineMarkers TimelineMarkers;
 	if(m_File)
 		return -1;
 
@@ -90,9 +92,8 @@ int CDemoRecorder::Start(class IStorage *pStorage, class IConsole *pConsole, con
 	str_copy(Header.m_aType, pType, sizeof(Header.m_aType));
 	// Header.m_Length - add this on stop
 	str_timestamp(Header.m_aTimestamp, sizeof(Header.m_aTimestamp));
-	// Header.m_aNumTimelineMarkers - add this on stop
-	// Header.m_aTimelineMarkers - add this on stop
 	io_write(DemoFile, &Header, sizeof(Header));
+	io_write(DemoFile, &TimelineMarkers, sizeof(TimelineMarkers)); // fill this on stop
 
 	// write map data
 	while(1)
@@ -615,7 +616,7 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
 		return -1;
 	}
 
-	if(m_Info.m_Header.m_Version < gs_ActVersion)
+	if(m_Info.m_Header.m_Version < gs_OldVersion)
 	{
 		char aBuf[256];
 		str_format(aBuf, sizeof(aBuf), "demo version %d is not supported", m_Info.m_Header.m_Version);
@@ -624,6 +625,8 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
 		m_File = 0;
 		return -1;
 	}
+	else if(m_Info.m_Header.m_Version > gs_OldVersion)
+		io_read(m_File, &m_Info.m_TimelineMarkers, sizeof(m_Info.m_TimelineMarkers));
 
 	// get demo type
 	if(!str_comp(m_Info.m_Header.m_aType, "client"))
@@ -663,15 +666,18 @@ int CDemoPlayer::Load(class IStorage *pStorage, class IConsole *pConsole, const
 		mem_free(pMapData);
 	}
 
-	// get timeline markers
-	int Num = ((m_Info.m_Header.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_Header.m_aNumTimelineMarkers[1]<<16)&0xFF0000) |
-				((m_Info.m_Header.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_Header.m_aNumTimelineMarkers[3]&0xFF);
-	m_Info.m_Info.m_NumTimelineMarkers = Num;
-	for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++)
+	if(m_Info.m_Header.m_Version > gs_OldVersion)
 	{
-		char *pTimelineMarker = m_Info.m_Header.m_aTimelineMarkers[i];
-		m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) |
-												((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF);
+		// get timeline markers
+		int Num = ((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[0]<<24)&0xFF000000) | ((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[1]<<16)&0xFF0000) |
+					((m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[2]<<8)&0xFF00) | (m_Info.m_TimelineMarkers.m_aNumTimelineMarkers[3]&0xFF);
+		m_Info.m_Info.m_NumTimelineMarkers = Num;
+		for(int i = 0; i < Num && i < MAX_TIMELINE_MARKERS; i++)
+		{
+			char *pTimelineMarker = m_Info.m_TimelineMarkers.m_aTimelineMarkers[i];
+			m_Info.m_Info.m_aTimelineMarkers[i] = ((pTimelineMarker[0]<<24)&0xFF000000) | ((pTimelineMarker[1]<<16)&0xFF0000) |
+													((pTimelineMarker[2]<<8)&0xFF00) | (pTimelineMarker[3]&0xFF);
+		}
 	}
 
 	// scan the file for interessting points
@@ -843,7 +849,7 @@ bool CDemoPlayer::GetDemoInfo(class IStorage *pStorage, const char *pFilename, i
 		return false;
 
 	io_read(File, pDemoHeader, sizeof(CDemoHeader));
-	if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_ActVersion)
+	if(mem_comp(pDemoHeader->m_aMarker, gs_aHeaderMarker, sizeof(gs_aHeaderMarker)) || pDemoHeader->m_Version < gs_OldVersion)
 	{
 		io_close(File);
 		return false;
diff --git a/src/engine/shared/demo.h b/src/engine/shared/demo.h
index 760e7256..d27f4ab6 100644
--- a/src/engine/shared/demo.h
+++ b/src/engine/shared/demo.h
@@ -51,6 +51,7 @@ public:
 	struct CPlaybackInfo
 	{
 		CDemoHeader m_Header;
+		CTimelineMarkers m_TimelineMarkers;
 
 		IDemoPlayer::CInfo m_Info;
 
diff --git a/src/engine/shared/econ.cpp b/src/engine/shared/econ.cpp
index eb7df872..e0df8635 100644
--- a/src/engine/shared/econ.cpp
+++ b/src/engine/shared/econ.cpp
@@ -75,7 +75,11 @@ void CEcon::Init(IConsole *pConsole, CNetBan *pNetBan)
 
 	NETADDR BindAddr;
 	if(g_Config.m_EcBindaddr[0] && net_host_lookup(g_Config.m_EcBindaddr, &BindAddr, NETTYPE_ALL) == 0)
+	{
+		// got bindaddr
+		BindAddr.type = NETTYPE_ALL;
 		BindAddr.port = g_Config.m_EcPort;
+	}
 	else
 	{
 		mem_zero(&BindAddr, sizeof(BindAddr));
diff --git a/src/engine/shared/mapchecker.cpp b/src/engine/shared/mapchecker.cpp
index f8ba30ae..5a7d062f 100644
--- a/src/engine/shared/mapchecker.cpp
+++ b/src/engine/shared/mapchecker.cpp
@@ -6,6 +6,7 @@
 #include <engine/storage.h>
 
 #include <versionsrv/versionsrv.h>
+#include <versionsrv/mapversions.h>
 
 #include "datafile.h"
 #include "memheap.h"
diff --git a/src/engine/shared/netban.cpp b/src/engine/shared/netban.cpp
index d26d64d4..707b709b 100644
--- a/src/engine/shared/netban.cpp
+++ b/src/engine/shared/netban.cpp
@@ -243,7 +243,7 @@ typename CNetBan::CBan<T> *CNetBan::CBanPool<T, HashCount>::Get(int Index) const
 template<class T>
 void CNetBan::MakeBanInfo(const CBan<T> *pBan, char *pBuf, unsigned BuffSize, int Type) const
 {
-	if(pBan == 0)
+	if(pBan == 0 || pBuf == 0)
 	{
 		if(BuffSize > 0)
 			pBuf[0] = 0;
diff --git a/src/engine/shared/netban.h b/src/engine/shared/netban.h
index 447a838d..70164832 100644
--- a/src/engine/shared/netban.h
+++ b/src/engine/shared/netban.h
@@ -34,7 +34,7 @@ protected:
 
 	bool NetMatch(const CNetRange *pRange, const NETADDR *pAddr, int Start, int Length) const
 	{
-		return pRange->m_LB.type == pAddr->type &&
+		return pRange->m_LB.type == pAddr->type && (Start == 0 || mem_comp(&pRange->m_LB.ip[0], &pAddr->ip[0], Start) == 0) &&
 			mem_comp(&pRange->m_LB.ip[Start], &pAddr->ip[Start], Length-Start) <= 0 && mem_comp(&pRange->m_UB.ip[Start], &pAddr->ip[Start], Length-Start) >= 0;
 	}
 
@@ -170,7 +170,7 @@ public:
 	class IStorage *Storage() const { return m_pStorage; }
 
 	virtual ~CNetBan() {}
-	virtual void Init(class IConsole *pConsole, class IStorage *pStorage);
+	void Init(class IConsole *pConsole, class IStorage *pStorage);
 	void Update();
 
 	virtual int BanAddr(const NETADDR *pAddr, int Seconds, const char *pReason);
diff --git a/src/engine/shared/network.h b/src/engine/shared/network.h
index dd43389e..259d600f 100644
--- a/src/engine/shared/network.h
+++ b/src/engine/shared/network.h
@@ -140,6 +140,7 @@ private:
 
 	int m_Token;
 	int m_RemoteClosed;
+	bool m_BlockCloseMsg;
 
 	TStaticRingBuffer<CNetChunkResend, NET_CONN_BUFFERSIZE> m_Buffer;
 
@@ -167,7 +168,7 @@ private:
 	void Resend();
 
 public:
-	void Init(NETSOCKET Socket);
+	void Init(NETSOCKET Socket, bool BlockCloseMsg);
 	int Connect(NETADDR *pAddr);
 	void Disconnect(const char *pReason);
 
@@ -187,6 +188,7 @@ public:
 
 	// Needed for GotProblems in NetClient
 	int64 LastRecvTime() const { return m_LastRecvTime; }
+	int64 ConnectTime() const { return m_LastUpdateTime; }
 
 	int AckSequence() const { return m_Ack; }
 };
@@ -353,7 +355,7 @@ public:
 	int ResetErrorString();
 
 	// error and state
-	int NetType() { return m_Socket.type; }
+	int NetType() const { return m_Socket.type; }
 	int State();
 	int GotProblems();
 	const char *ErrorString();
diff --git a/src/engine/shared/network_client.cpp b/src/engine/shared/network_client.cpp
index 2c035606..8e0e2910 100644
--- a/src/engine/shared/network_client.cpp
+++ b/src/engine/shared/network_client.cpp
@@ -16,7 +16,7 @@ bool CNetClient::Open(NETADDR BindAddr, int Flags)
 
 	// init
 	m_Socket = Socket;
-	m_Connection.Init(m_Socket);
+	m_Connection.Init(m_Socket, false);
 	return true;
 }
 
diff --git a/src/engine/shared/network_conn.cpp b/src/engine/shared/network_conn.cpp
index 6531f5aa..cd2df048 100644
--- a/src/engine/shared/network_conn.cpp
+++ b/src/engine/shared/network_conn.cpp
@@ -37,12 +37,13 @@ void CNetConnection::SetError(const char *pString)
 	str_copy(m_ErrorString, pString, sizeof(m_ErrorString));
 }
 
-void CNetConnection::Init(NETSOCKET Socket)
+void CNetConnection::Init(NETSOCKET Socket, bool BlockCloseMsg)
 {
 	Reset();
 	ResetStats();
 
 	m_Socket = Socket;
+	m_BlockCloseMsg = BlockCloseMsg;
 	mem_zero(m_ErrorString, sizeof(m_ErrorString));
 }
 
@@ -213,24 +214,25 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 				m_State = NET_CONNSTATE_ERROR;
 				m_RemoteClosed = 1;
 
-				if(pPacket->m_DataSize)
+				char Str[128] = {0};
+				if(pPacket->m_DataSize > 1)
 				{
 					// make sure to sanitize the error string form the other party
-					char Str[128];
 					if(pPacket->m_DataSize < 128)
-						str_copy(Str, (char *)pPacket->m_aChunkData, pPacket->m_DataSize);
+						str_copy(Str, (char *)&pPacket->m_aChunkData[1], pPacket->m_DataSize);
 					else
-						str_copy(Str, (char *)pPacket->m_aChunkData, sizeof(Str));
+						str_copy(Str, (char *)&pPacket->m_aChunkData[1], sizeof(Str));
 					str_sanitize_strong(Str);
+				}
 
+				if(!m_BlockCloseMsg)
+				{
 					// set the error string
 					SetError(Str);
 				}
-				else
-					SetError("No reason given");
 
 				if(g_Config.m_Debug)
-					dbg_msg("conn", "closed reason='%s'", ErrorString());
+					dbg_msg("conn", "closed reason='%s'", Str);
 			}
 			return 0;
 		}
@@ -244,6 +246,7 @@ int CNetConnection::Feed(CNetPacketConstruct *pPacket, NETADDR *pAddr)
 					Reset();
 					m_State = NET_CONNSTATE_PENDING;
 					m_PeerAddr = *pAddr;
+					mem_zero(m_ErrorString, sizeof(m_ErrorString));
 					m_LastSendTime = Now;
 					m_LastRecvTime = Now;
 					m_LastUpdateTime = Now;
diff --git a/src/engine/shared/network_server.cpp b/src/engine/shared/network_server.cpp
index b693b667..e97a8eba 100644
--- a/src/engine/shared/network_server.cpp
+++ b/src/engine/shared/network_server.cpp
@@ -30,7 +30,7 @@ bool CNetServer::Open(NETADDR BindAddr, CNetBan *pNetBan, int MaxClients, int Ma
 	m_MaxClientsPerIP = MaxClientsPerIP;
 
 	for(int i = 0; i < NET_MAX_CLIENTS; i++)
-		m_aSlots[i].m_Connection.Init(m_Socket);
+		m_aSlots[i].m_Connection.Init(m_Socket, true);
 
 	return true;
 }
@@ -69,11 +69,17 @@ int CNetServer::Drop(int ClientID, const char *pReason)
 
 int CNetServer::Update()
 {
+	int64 Now = time_get();
 	for(int i = 0; i < MaxClients(); i++)
 	{
 		m_aSlots[i].m_Connection.Update();
 		if(m_aSlots[i].m_Connection.State() == NET_CONNSTATE_ERROR)
-			Drop(i, m_aSlots[i].m_Connection.ErrorString());
+		{
+			if(Now - m_aSlots[i].m_Connection.ConnectTime() < time_freq()/2 && NetBan())
+				NetBan()->BanAddr(ClientAddr(i), 60, "Stressing network");
+			else
+				Drop(i, m_aSlots[i].m_Connection.ErrorString());
+		}
 	}
 
 	return 0;
diff --git a/src/engine/shared/snapshot.cpp b/src/engine/shared/snapshot.cpp
index 9ef8fdc3..1514278b 100644
--- a/src/engine/shared/snapshot.cpp
+++ b/src/engine/shared/snapshot.cpp
@@ -195,13 +195,14 @@ int CSnapshotDelta::CreateDelta(CSnapshot *pFrom, CSnapshot *pTo, void *pDstData
 
 	// fetch previous indices
 	// we do this as a separate pass because it helps the cache
-	for(i = 0; i < pTo->NumItems(); i++)
+	const int NumItems = pTo->NumItems();
+	for(i = 0; i < NumItems; i++)
 	{
 		pCurItem = pTo->GetItem(i); // O(1) .. O(n)
 		aPastIndecies[i] = GetItemIndexHashed(pCurItem->Key(), Hashlist); // O(n) .. O(n^n)
 	}
 
-	for(i = 0; i < pTo->NumItems(); i++)
+	for(i = 0; i < NumItems; i++)
 	{
 		// do delta
 		ItemSize = pTo->GetItemSize(i); // O(1) .. O(n)
@@ -474,7 +475,7 @@ int CSnapshotStorage::Get(int Tick, int64 *pTagtime, CSnapshot **ppData, CSnapsh
 			if(ppData)
 				*ppData = pHolder->m_pSnap;
 			if(ppAltData)
-				*ppData = pHolder->m_pAltSnap;
+				*ppAltData = pHolder->m_pAltSnap;
 			return pHolder->m_SnapSize;
 		}
 
diff --git a/src/game/client/components/chat.cpp b/src/game/client/components/chat.cpp
index 340b9da1..f3370f94 100644
--- a/src/game/client/components/chat.cpp
+++ b/src/game/client/components/chat.cpp
@@ -112,13 +112,25 @@ bool CChat::OnInput(IInput::CEvent Event)
 	{
 		if(m_Input.GetString()[0])
 		{
+			bool AddEntry = false;
+
 			if(m_LastChatSend+time_freq() < time_get())
+			{
 				Say(m_Mode == MODE_ALL ? 0 : 1, m_Input.GetString());
-			else
+				AddEntry = true;
+			}
+			else if(m_PendingChatCounter < 3)
+			{
 				++m_PendingChatCounter;
-			CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
-			pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
-			mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
+				AddEntry = true;
+			}
+
+			if(AddEntry)
+			{
+				CHistoryEntry *pEntry = m_History.Allocate(sizeof(CHistoryEntry)+m_Input.GetLength());
+				pEntry->m_Team = m_Mode == MODE_ALL ? 0 : 1;
+				mem_copy(pEntry->m_aText, m_Input.GetString(), m_Input.GetLength()+1);
+			}
 		}
 		m_pHistoryEntry = 0x0;
 		m_Mode = MODE_NONE;
@@ -265,9 +277,9 @@ void CChat::OnMessage(int MsgType, void *pRawMsg)
 
 void CChat::AddLine(int ClientID, int Team, const char *pLine)
 {
-	if(ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
+	if(*pLine == 0 || (ClientID != -1 && (m_pClient->m_aClients[ClientID].m_aName[0] == '\0' || // unknown client
 		m_pClient->m_aClients[ClientID].m_ChatIgnore ||
-		(m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend)))
+		(m_pClient->m_Snap.m_LocalClientID != ClientID && g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[ClientID].m_Friend))))
 		return;
 
 	bool Highlighted = false;
diff --git a/src/game/client/components/console.cpp b/src/game/client/components/console.cpp
index d16d56cd..01bf5351 100644
--- a/src/game/client/components/console.cpp
+++ b/src/game/client/components/console.cpp
@@ -434,12 +434,6 @@ void CGameConsole::OnRender()
 
 		x = Cursor.m_X;
 
-		// render console input (wrap line)
-		int Lines = TextRender()->TextLineCount(0, FontSize, pConsole->m_Input.GetString(), Screen.w - 10.0f - x);
-		y -= (Lines - 1) * FontSize;
-		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
-		Cursor.m_LineWidth = Screen.w - 10.0f - x;
-
 		//hide rcon password
 		char aInputString[256];
 		str_copy(aInputString, pConsole->m_Input.GetString(), sizeof(aInputString));
@@ -449,10 +443,22 @@ void CGameConsole::OnRender()
 				aInputString[i] = '*';
 		}
 
+		// render console input (wrap line)
+		TextRender()->SetCursor(&Cursor, x, y, FontSize, 0);
+		Cursor.m_LineWidth = Screen.w - 10.0f - x;
+		TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
+		TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
+		int Lines = Cursor.m_LineCount;
+		
+		y -= (Lines - 1) * FontSize;
+		TextRender()->SetCursor(&Cursor, x, y, FontSize, TEXTFLAG_RENDER);
+		Cursor.m_LineWidth = Screen.w - 10.0f - x;
+		
 		TextRender()->TextEx(&Cursor, aInputString, pConsole->m_Input.GetCursorOffset());
 		static float MarkerOffset = TextRender()->TextWidth(0, FontSize, "|", -1)/3;
 		CTextCursor Marker = Cursor;
 		Marker.m_X -= MarkerOffset;
+		Marker.m_LineWidth = -1;
 		TextRender()->TextEx(&Marker, "|", -1);
 		TextRender()->TextEx(&Cursor, aInputString+pConsole->m_Input.GetCursorOffset(), -1);
 
diff --git a/src/game/client/components/menus.cpp b/src/game/client/components/menus.cpp
index d27307f4..8d0bdb16 100644
--- a/src/game/client/components/menus.cpp
+++ b/src/game/client/components/menus.cpp
@@ -1045,7 +1045,7 @@ int CMenus::Render()
 					}
 
 					// update download speed
-					float Diff = Client()->MapDownloadAmount()-m_DownloadLastCheckSize;
+					float Diff = (Client()->MapDownloadAmount()-m_DownloadLastCheckSize)/((int)((Now-m_DownloadLastCheckTime)/time_freq()));
 					float StartDiff = m_DownloadLastCheckSize-0.0f;
 					if(StartDiff+Diff > 0.0f)
 						m_DownloadSpeed = (Diff/(StartDiff+Diff))*(Diff/1.0f) + (StartDiff/(Diff+StartDiff))*m_DownloadSpeed;
diff --git a/src/game/client/components/menus_browser.cpp b/src/game/client/components/menus_browser.cpp
index a9c434b3..b560b8cd 100644
--- a/src/game/client/components/menus_browser.cpp
+++ b/src/game/client/components/menus_browser.cpp
@@ -225,7 +225,7 @@ void CMenus::RenderServerbrowserServerList(CUIRect View)
 	{
 		int ItemIndex = i;
 		const CServerInfo *pItem = ServerBrowser()->SortedGet(ItemIndex);
-		NumPlayers += pItem->m_NumPlayers;
+		NumPlayers += g_Config.m_BrFilterSpectators ? pItem->m_NumPlayers : pItem->m_NumClients;
 		CUIRect Row;
 		CUIRect SelectHitBox;
 
diff --git a/src/game/client/components/menus_ingame.cpp b/src/game/client/components/menus_ingame.cpp
index a9cf35e9..084520d9 100644
--- a/src/game/client/components/menus_ingame.cpp
+++ b/src/game/client/components/menus_ingame.cpp
@@ -183,7 +183,7 @@ void CMenus::RenderPlayers(CUIRect MainView)
 		ButtonBar.VSplitLeft(Width, &Button, &ButtonBar);
 		Button.VSplitLeft((Width-Button.h)/4.0f, 0, &Button);
 		Button.VSplitLeft(Button.h, &Button, 0);
-		if(&g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
+		if(g_Config.m_ClShowChatFriends && !m_pClient->m_aClients[Index].m_Friend)
 			DoButton_Toggle(&s_aPlayerIDs[Index][0], 1, &Button, false);
 		else
 			if(DoButton_Toggle(&s_aPlayerIDs[Index][0], m_pClient->m_aClients[Index].m_ChatIgnore, &Button, true))
diff --git a/src/game/client/components/menus_settings.cpp b/src/game/client/components/menus_settings.cpp
index 553195b1..b2434d91 100644
--- a/src/game/client/components/menus_settings.cpp
+++ b/src/game/client/components/menus_settings.cpp
@@ -613,11 +613,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
 	static int s_GfxScreenWidth = g_Config.m_GfxScreenWidth;
 	static int s_GfxScreenHeight = g_Config.m_GfxScreenHeight;
 	static int s_GfxColorDepth = g_Config.m_GfxColorDepth;
+	static int s_GfxBorderless = g_Config.m_GfxBorderless;
 	static int s_GfxFullscreen = g_Config.m_GfxFullscreen;
 	static int s_GfxVsync = g_Config.m_GfxVsync;
 	static int s_GfxFsaaSamples = g_Config.m_GfxFsaaSamples;
 	static int s_GfxTextureQuality = g_Config.m_GfxTextureQuality;
 	static int s_GfxTextureCompression = g_Config.m_GfxTextureCompression;
+	static int s_GfxThreaded = g_Config.m_GfxThreaded;
 
 	CUIRect ModeList;
 	MainView.VSplitLeft(300.0f, &MainView, &ModeList);
@@ -668,9 +670,20 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
 
 	// switches
 	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxBorderless, Localize("Borderless window"), g_Config.m_GfxBorderless, &Button))
+	{
+		g_Config.m_GfxBorderless ^= 1;
+		if(g_Config.m_GfxBorderless && g_Config.m_GfxFullscreen)
+			g_Config.m_GfxFullscreen = 0;
+		CheckSettings = true;
+	}
+
+	MainView.HSplitTop(20.0f, &Button, &MainView);
 	if(DoButton_CheckBox(&g_Config.m_GfxFullscreen, Localize("Fullscreen"), g_Config.m_GfxFullscreen, &Button))
 	{
 		g_Config.m_GfxFullscreen ^= 1;
+		if(g_Config.m_GfxFullscreen && g_Config.m_GfxBorderless)
+			g_Config.m_GfxBorderless = 0;
 		CheckSettings = true;
 	}
 
@@ -687,8 +700,25 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
 		g_Config.m_GfxFsaaSamples = (g_Config.m_GfxFsaaSamples+1)%17;
 		CheckSettings = true;
 	}
+	
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_GfxThreaded, Localize("Threaded rendering"), g_Config.m_GfxThreaded, &Button))
+	{
+		g_Config.m_GfxThreaded ^= 1;
+		CheckSettings = true;
+	}
 
-	MainView.HSplitTop(40.0f, &Button, &MainView);
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(g_Config.m_GfxThreaded)
+	{
+		Button.VSplitLeft(20.0f, 0, &Button);
+		if(DoButton_CheckBox(&g_Config.m_GfxAsyncRender, Localize("Handle rendering async from updates"), g_Config.m_GfxAsyncRender, &Button))
+		{
+			g_Config.m_GfxAsyncRender ^= 1;
+			CheckSettings = true;
+		}
+	}
+		
 	MainView.HSplitTop(20.0f, &Button, &MainView);
 	if(DoButton_CheckBox(&g_Config.m_GfxTextureQuality, Localize("Quality Textures"), g_Config.m_GfxTextureQuality, &Button))
 	{
@@ -713,11 +743,13 @@ void CMenus::RenderSettingsGraphics(CUIRect MainView)
 		if(s_GfxScreenWidth == g_Config.m_GfxScreenWidth &&
 			s_GfxScreenHeight == g_Config.m_GfxScreenHeight &&
 			s_GfxColorDepth == g_Config.m_GfxColorDepth &&
+			s_GfxBorderless == g_Config.m_GfxBorderless &&
 			s_GfxFullscreen == g_Config.m_GfxFullscreen &&
 			s_GfxVsync == g_Config.m_GfxVsync &&
 			s_GfxFsaaSamples == g_Config.m_GfxFsaaSamples &&
 			s_GfxTextureQuality == g_Config.m_GfxTextureQuality &&
-			s_GfxTextureCompression == g_Config.m_GfxTextureCompression)
+			s_GfxTextureCompression == g_Config.m_GfxTextureCompression &&
+			s_GfxThreaded == g_Config.m_GfxThreaded)
 			m_NeedRestartGraphics = false;
 		else
 			m_NeedRestartGraphics = true;
@@ -781,16 +813,23 @@ void CMenus::RenderSettingsSound(CUIRect MainView)
 	if(DoButton_CheckBox(&g_Config.m_SndMusic, Localize("Play background music"), g_Config.m_SndMusic, &Button))
 	{
 		g_Config.m_SndMusic ^= 1;
-		if(g_Config.m_SndMusic)
-			m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
-		else
-			m_pClient->m_pSounds->Stop(SOUND_MENU);
+		if(Client()->State() == IClient::STATE_OFFLINE)
+		{
+			if(g_Config.m_SndMusic)
+				m_pClient->m_pSounds->Play(CSounds::CHN_MUSIC, SOUND_MENU, 1.0f);
+			else
+				m_pClient->m_pSounds->Stop(SOUND_MENU);
+		}
 	}
 
 	MainView.HSplitTop(20.0f, &Button, &MainView);
 	if(DoButton_CheckBox(&g_Config.m_SndNonactiveMute, Localize("Mute when not active"), g_Config.m_SndNonactiveMute, &Button))
 		g_Config.m_SndNonactiveMute ^= 1;
 
+	MainView.HSplitTop(20.0f, &Button, &MainView);
+	if(DoButton_CheckBox(&g_Config.m_ClThreadsoundloading, Localize("Threaded sound loading"), g_Config.m_ClThreadsoundloading, &Button))
+		g_Config.m_ClThreadsoundloading ^= 1;
+
 	// sample rate box
 	{
 		char aBuf[64];
diff --git a/src/game/client/components/voting.cpp b/src/game/client/components/voting.cpp
index 675d6770..13dbc8a2 100644
--- a/src/game/client/components/voting.cpp
+++ b/src/game/client/components/voting.cpp
@@ -120,7 +120,12 @@ void CVoting::Vote(int v)
 CVoting::CVoting()
 {
 	ClearOptions();
-	OnReset();
+	
+	m_Closetime = 0;
+	m_aDescription[0] = 0;
+	m_aReason[0] = 0;
+	m_Yes = m_No = m_Pass = m_Total = 0;
+	m_Voted = 0;
 }
 
 void CVoting::AddOption(const char *pDescription)
@@ -164,6 +169,9 @@ void CVoting::ClearOptions()
 
 void CVoting::OnReset()
 {
+	if(Client()->State() == IClient::STATE_LOADING)	// do not reset active vote while connecting
+		return;
+
 	m_Closetime = 0;
 	m_aDescription[0] = 0;
 	m_aReason[0] = 0;
diff --git a/src/game/client/gameclient.cpp b/src/game/client/gameclient.cpp
index 86fb5ad0..f9b8b671 100644
--- a/src/game/client/gameclient.cpp
+++ b/src/game/client/gameclient.cpp
@@ -449,7 +449,7 @@ void CGameClient::OnRender()
 	m_NewPredictedTick = false;
 
 	// check if client info has to be resent
-	if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*5 < time_get())
+	if(m_LastSendInfo && Client()->State() == IClient::STATE_ONLINE && m_Snap.m_LocalClientID >= 0 && !m_pMenus->IsActive() && m_LastSendInfo+time_freq()*6 < time_get())
 	{
 		// resend if client info differs
 		if(str_comp(g_Config.m_PlayerName, m_aClients[m_Snap.m_LocalClientID].m_aName) ||
@@ -571,7 +571,7 @@ void CGameClient::OnEnterGame() {}
 
 void CGameClient::OnGameOver()
 {
-	if(Client()->State() != IClient::STATE_DEMOPLAYBACK)
+	if(Client()->State() != IClient::STATE_DEMOPLAYBACK && g_Config.m_ClEditor == 0)
 		Client()->AutoScreenshot_Start();
 }
 
diff --git a/src/game/client/render.cpp b/src/game/client/render.cpp
index 278ed51a..71589191 100644
--- a/src/game/client/render.cpp
+++ b/src/game/client/render.cpp
@@ -314,7 +314,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers)
 				CTile *pTiles = (CTile *)pLayers->Map()->GetData(pTmap->m_Data);
 				for(int y = 0; y < pTmap->m_Height; y++)
 				{
-					for(int x = 1; x < pTmap->m_Width; x++)
+					for(int x = 1; x < pTmap->m_Width;)
 					{
 						int sx;
 						for(sx = 1; x+sx < pTmap->m_Width && sx < 255; sx++)
@@ -324,6 +324,7 @@ void CRenderTools::RenderTilemapGenerateSkip(class CLayers *pLayers)
 						}
 
 						pTiles[y*pTmap->m_Width+x].m_Skip = sx-1;
+						x += sx;
 					}
 				}
 			}
diff --git a/src/game/client/render_map.cpp b/src/game/client/render_map.cpp
index 23fa42e0..a854b4a7 100644
--- a/src/game/client/render_map.cpp
+++ b/src/game/client/render_map.cpp
@@ -99,9 +99,10 @@ void CRenderTools::RenderQuads(CQuad *pQuads, int NumQuads, int RenderFlags, ENV
 		}
 
 		bool Opaque = false;
+		/* TODO: Analyze quadtexture
 		if(a < 0.01f || (q->m_aColors[0].a < 0.01f && q->m_aColors[1].a < 0.01f && q->m_aColors[2].a < 0.01f && q->m_aColors[3].a < 0.01f))
 			Opaque = true;
-
+		*/
 		if(Opaque && !(RenderFlags&LAYERRENDERFLAG_OPAQUE))
 			continue;
 		if(!Opaque && !(RenderFlags&LAYERRENDERFLAG_TRANSPARENT))
@@ -236,7 +237,7 @@ void CRenderTools::RenderTilemap(CTile *pTiles, int w, int h, float Scale, vec4
 				unsigned char Flags = pTiles[c].m_Flags;
 
 				bool Render = false;
-				if(Flags&TILEFLAG_OPAQUE)
+				if(Flags&TILEFLAG_OPAQUE && Color.a*a > 254.0f/255.0f)
 				{
 					if(RenderFlags&LAYERRENDERFLAG_OPAQUE)
 						Render = true;
diff --git a/src/game/editor/editor.cpp b/src/game/editor/editor.cpp
index fa1024e0..28a4eda9 100644
--- a/src/game/editor/editor.cpp
+++ b/src/game/editor/editor.cpp
@@ -37,6 +37,11 @@ enum
 CEditorImage::~CEditorImage()
 {
 	m_pEditor->Graphics()->UnloadTexture(m_TexID);
+	if(m_pData)
+	{
+		mem_free(m_pData);
+		m_pData = 0;
+	}
 }
 
 CLayerGroup::CLayerGroup()
@@ -1013,7 +1018,7 @@ void CEditor::DoToolbar(CUIRect ToolBar)
 	}
 }
 
-static void Rotate(CPoint *pCenter, CPoint *pPoint, float Rotation)
+static void Rotate(const CPoint *pCenter, CPoint *pPoint, float Rotation)
 {
 	int x = pPoint->x - pCenter->x;
 	int y = pPoint->y - pCenter->y;
@@ -1403,99 +1408,126 @@ void CEditor::DoQuadPoint(CQuad *pQuad, int QuadIndex, int V)
 	Graphics()->QuadsDraw(&QuadItem, 1);
 }
 
-void CEditor::DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID)
+void CEditor::DoQuadEnvelopes(const array<CQuad> &lQuads, int TexID)
 {
-	CEnvelope *pEnvelope = 0x0;
-	if(pQuad->m_PosEnv >= 0 && pQuad->m_PosEnv < m_Map.m_lEnvelopes.size())
-		pEnvelope = m_Map.m_lEnvelopes[pQuad->m_PosEnv];
-	if (!pEnvelope)
-		return;
-
-	//QuadParams
-	CPoint *pPoints = pQuad->m_aPoints;
+	int Num = lQuads.size();
+	CEnvelope **apEnvelope = new CEnvelope*[Num];
+	mem_zero(apEnvelope, sizeof(CEnvelope*)*Num);
+	for(int i = 0; i < Num; i++)
+	{
+		if((m_ShowEnvelopePreview == 1 && lQuads[i].m_PosEnv == m_SelectedEnvelope) || m_ShowEnvelopePreview == 2)
+			if(lQuads[i].m_PosEnv >= 0 && lQuads[i].m_PosEnv < m_Map.m_lEnvelopes.size())
+				apEnvelope[i] = m_Map.m_lEnvelopes[lQuads[i].m_PosEnv];
+	}
 
 	//Draw Lines
 	Graphics()->TextureSet(-1);
 	Graphics()->LinesBegin();
-		Graphics()->SetColor(80.0f/255, 150.0f/255, 230.f/255, 0.5f);
-		for(int i = 0; i < pEnvelope->m_lPoints.size()-1; i++)
+	Graphics()->SetColor(80.0f/255, 150.0f/255, 230.f/255, 0.5f);
+	for(int j = 0; j < Num; j++)
+	{
+		if(!apEnvelope[j])
+			continue;
+
+		//QuadParams
+		const CPoint *pPoints = lQuads[j].m_aPoints;
+		for(int i = 0; i < apEnvelope[j]->m_lPoints.size()-1; i++)
 		{
-			float OffsetX =  fx2f(pEnvelope->m_lPoints[i].m_aValues[0]);
-			float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]);
+			float OffsetX =  fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[0]);
+			float OffsetY = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[1]);
 			vec2 Pos0 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY);
 
-			OffsetX = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[0]);
-			OffsetY = fx2f(pEnvelope->m_lPoints[i+1].m_aValues[1]);
+			OffsetX = fx2f(apEnvelope[j]->m_lPoints[i+1].m_aValues[0]);
+			OffsetY = fx2f(apEnvelope[j]->m_lPoints[i+1].m_aValues[1]);
 			vec2 Pos1 = vec2(fx2f(pPoints[4].x)+OffsetX, fx2f(pPoints[4].y)+OffsetY);
 
 			IGraphics::CLineItem Line = IGraphics::CLineItem(Pos0.x, Pos0.y, Pos1.x, Pos1.y);
 			Graphics()->LinesDraw(&Line, 1);
 		}
-		Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
+	}
+	Graphics()->SetColor(1.0f, 1.0f, 1.0f, 1.0f);
 	Graphics()->LinesEnd();
 
 	//Draw Quads
-	for(int i = 0; i < pEnvelope->m_lPoints.size(); i++)
+	Graphics()->TextureSet(TexID);
+	Graphics()->QuadsBegin();
+	
+	for(int j = 0; j < Num; j++)
 	{
-		Graphics()->TextureSet(TexID);
-		Graphics()->QuadsBegin();
-		
-		//Calc Env Position
-		float OffsetX =  fx2f(pEnvelope->m_lPoints[i].m_aValues[0]);
-		float OffsetY = fx2f(pEnvelope->m_lPoints[i].m_aValues[1]);
-		float Rot = fx2f(pEnvelope->m_lPoints[i].m_aValues[2])/360.0f*pi*2;
-
-		//Set Colours
-		float Alpha = (m_SelectedQuadEnvelope == pQuad->m_PosEnv && m_SelectedEnvelopePoint == i) ? 0.65f : 0.35f;
-		IGraphics::CColorVertex aArray[4] = {
-			IGraphics::CColorVertex(0, pQuad->m_aColors[0].r, pQuad->m_aColors[0].g, pQuad->m_aColors[0].b, Alpha),
-			IGraphics::CColorVertex(1, pQuad->m_aColors[1].r, pQuad->m_aColors[1].g, pQuad->m_aColors[1].b, Alpha),
-			IGraphics::CColorVertex(2, pQuad->m_aColors[2].r, pQuad->m_aColors[2].g, pQuad->m_aColors[2].b, Alpha),
-			IGraphics::CColorVertex(3, pQuad->m_aColors[3].r, pQuad->m_aColors[3].g, pQuad->m_aColors[3].b, Alpha)};
-		Graphics()->SetColorVertex(aArray, 4);
-
-		//Rotation
-		if(Rot != 0)
-		{
-			static CPoint aRotated[4];
-			aRotated[0] = pQuad->m_aPoints[0];
-			aRotated[1] = pQuad->m_aPoints[1];
-			aRotated[2] = pQuad->m_aPoints[2];
-			aRotated[3] = pQuad->m_aPoints[3];
-			pPoints = aRotated;
-
-			Rotate(&pQuad->m_aPoints[4], &aRotated[0], Rot);
-			Rotate(&pQuad->m_aPoints[4], &aRotated[1], Rot);
-			Rotate(&pQuad->m_aPoints[4], &aRotated[2], Rot);
-			Rotate(&pQuad->m_aPoints[4], &aRotated[3], Rot);
-		}
-
-		//Set Texture Coords
-		Graphics()->QuadsSetSubsetFree(
-			fx2f(pQuad->m_aTexcoords[0].x), fx2f(pQuad->m_aTexcoords[0].y),
-			fx2f(pQuad->m_aTexcoords[1].x), fx2f(pQuad->m_aTexcoords[1].y),
-			fx2f(pQuad->m_aTexcoords[2].x), fx2f(pQuad->m_aTexcoords[2].y),
-			fx2f(pQuad->m_aTexcoords[3].x), fx2f(pQuad->m_aTexcoords[3].y)
-		);
-
-		//Set Quad Coords & Draw
-		IGraphics::CFreeformItem Freeform(
-			fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY,
-			fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY,
-			fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY,
-			fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY);
-		Graphics()->QuadsDrawFreeform(&Freeform, 1);
+		if(!apEnvelope[j])
+			continue;
 
-		Graphics()->QuadsEnd();
-		
-		Graphics()->TextureSet(-1);
-		Graphics()->QuadsBegin();
-		DoQuadEnvPoint(pQuad, Index, i);
-		Graphics()->QuadsEnd();
+		//QuadParams
+		const CPoint *pPoints = lQuads[j].m_aPoints;
+
+		for(int i = 0; i < apEnvelope[j]->m_lPoints.size(); i++)
+		{
+			//Calc Env Position
+			float OffsetX =  fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[0]);
+			float OffsetY = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[1]);
+			float Rot = fx2f(apEnvelope[j]->m_lPoints[i].m_aValues[2])/360.0f*pi*2;
+
+			//Set Colours
+			float Alpha = (m_SelectedQuadEnvelope == lQuads[j].m_PosEnv && m_SelectedEnvelopePoint == i) ? 0.65f : 0.35f;
+			IGraphics::CColorVertex aArray[4] = {
+				IGraphics::CColorVertex(0, lQuads[j].m_aColors[0].r, lQuads[j].m_aColors[0].g, lQuads[j].m_aColors[0].b, Alpha),
+				IGraphics::CColorVertex(1, lQuads[j].m_aColors[1].r, lQuads[j].m_aColors[1].g, lQuads[j].m_aColors[1].b, Alpha),
+				IGraphics::CColorVertex(2, lQuads[j].m_aColors[2].r, lQuads[j].m_aColors[2].g, lQuads[j].m_aColors[2].b, Alpha),
+				IGraphics::CColorVertex(3, lQuads[j].m_aColors[3].r, lQuads[j].m_aColors[3].g, lQuads[j].m_aColors[3].b, Alpha)};
+			Graphics()->SetColorVertex(aArray, 4);
+
+			//Rotation
+			if(Rot != 0)
+			{
+				static CPoint aRotated[4];
+				aRotated[0] = lQuads[j].m_aPoints[0];
+				aRotated[1] = lQuads[j].m_aPoints[1];
+				aRotated[2] = lQuads[j].m_aPoints[2];
+				aRotated[3] = lQuads[j].m_aPoints[3];
+				pPoints = aRotated;
+
+				Rotate(&lQuads[j].m_aPoints[4], &aRotated[0], Rot);
+				Rotate(&lQuads[j].m_aPoints[4], &aRotated[1], Rot);
+				Rotate(&lQuads[j].m_aPoints[4], &aRotated[2], Rot);
+				Rotate(&lQuads[j].m_aPoints[4], &aRotated[3], Rot);
+			}
+
+			//Set Texture Coords
+			Graphics()->QuadsSetSubsetFree(
+				fx2f(lQuads[j].m_aTexcoords[0].x), fx2f(lQuads[j].m_aTexcoords[0].y),
+				fx2f(lQuads[j].m_aTexcoords[1].x), fx2f(lQuads[j].m_aTexcoords[1].y),
+				fx2f(lQuads[j].m_aTexcoords[2].x), fx2f(lQuads[j].m_aTexcoords[2].y),
+				fx2f(lQuads[j].m_aTexcoords[3].x), fx2f(lQuads[j].m_aTexcoords[3].y)
+			);
+
+			//Set Quad Coords & Draw
+			IGraphics::CFreeformItem Freeform(
+				fx2f(pPoints[0].x)+OffsetX, fx2f(pPoints[0].y)+OffsetY,
+				fx2f(pPoints[1].x)+OffsetX, fx2f(pPoints[1].y)+OffsetY,
+				fx2f(pPoints[2].x)+OffsetX, fx2f(pPoints[2].y)+OffsetY,
+				fx2f(pPoints[3].x)+OffsetX, fx2f(pPoints[3].y)+OffsetY);
+			Graphics()->QuadsDrawFreeform(&Freeform, 1);
+		}
 	}
+	Graphics()->QuadsEnd();
+	Graphics()->TextureSet(-1);
+	Graphics()->QuadsBegin();
+
+	// Draw QuadPoints
+	for(int j = 0; j < Num; j++)
+	{
+		if(!apEnvelope[j])
+			continue;
+
+		//QuadParams
+		for(int i = 0; i < apEnvelope[j]->m_lPoints.size()-1; i++)
+			DoQuadEnvPoint(&lQuads[j], j, i);
+	}
+	Graphics()->QuadsEnd();
+	delete[] apEnvelope;
 }
 
-void CEditor::DoQuadEnvPoint(CQuad *pQuad, int QIndex, int PIndex)
+void CEditor::DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int PIndex)
 {
 	enum
 	{
@@ -2088,12 +2120,7 @@ void CEditor::DoMapEditor(CUIRect View, CUIRect ToolBar)
 		if(pLayer->m_Image >= 0 && pLayer->m_Image < m_Map.m_lImages.size())
 			TexID = m_Map.m_lImages[pLayer->m_Image]->m_TexID;
 
-		for(int i = 0; i < pLayer->m_lQuads.size(); i++)
-		{
-			if((m_ShowEnvelopePreview == 1 && pLayer->m_lQuads[i].m_PosEnv == m_SelectedEnvelope) || m_ShowEnvelopePreview == 2)
-				DoQuadEnvelopes(&pLayer->m_lQuads[i], i, TexID);
-		}
-
+		DoQuadEnvelopes(pLayer->m_lQuads, TexID);
 		m_ShowEnvelopePreview = 0;
     }
 
@@ -2287,8 +2314,6 @@ void CEditor::RenderLayers(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 				if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
 					s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f);
 			}
-			else
-				ScrollNum = 0;
 		}
 	}
 
@@ -2423,11 +2448,17 @@ void CEditor::ReplaceImage(const char *pFileName, int StorageType, void *pUser)
 	CEditorImage *pImg = pEditor->m_Map.m_lImages[pEditor->m_SelectedImage];
 	int External = pImg->m_External;
 	pEditor->Graphics()->UnloadTexture(pImg->m_TexID);
+	if(pImg->m_pData)
+	{
+		mem_free(pImg->m_pData);
+		pImg->m_pData = 0;
+	}
 	*pImg = ImgInfo;
 	pImg->m_External = External;
 	pEditor->ExtractName(pFileName, pImg->m_aName, sizeof(pImg->m_aName));
 	pImg->m_AutoMapper.Load(pImg->m_aName);
 	pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+	ImgInfo.m_pData = 0;
 	pEditor->SortImages();
 	for(int i = 0; i < pEditor->m_Map.m_lImages.size(); ++i)
 	{
@@ -2456,6 +2487,7 @@ void CEditor::AddImage(const char *pFileName, int StorageType, void *pUser)
 	CEditorImage *pImg = new CEditorImage(pEditor);
 	*pImg = ImgInfo;
 	pImg->m_TexID = pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+	ImgInfo.m_pData = 0;
 	pImg->m_External = 1;	// external by default
 	str_copy(pImg->m_aName, aBuf, sizeof(pImg->m_aName));
 	pImg->m_AutoMapper.Load(pImg->m_aName);
@@ -2603,8 +2635,6 @@ void CEditor::RenderImages(CUIRect ToolBox, CUIRect ToolBar, CUIRect View)
 				if(Input()->KeyPresses(KEY_MOUSE_WHEEL_DOWN))
 					s_ScrollValue = clamp(s_ScrollValue + 1.0f/ScrollNum, 0.0f, 1.0f);
 			}
-			else
-				ScrollNum = 0;
 		}
 	}
 
diff --git a/src/game/editor/editor.h b/src/game/editor/editor.h
index a81474d9..19a8752e 100644
--- a/src/game/editor/editor.h
+++ b/src/game/editor/editor.h
@@ -761,8 +761,8 @@ public:
 
 	vec4 ButtonColorMul(const void *pID);
 
-	void DoQuadEnvelopes(CQuad *pQuad, int Index, int TexID = -1);
-	void DoQuadEnvPoint(CQuad *pQuad, int QIndex, int pIndex);
+	void DoQuadEnvelopes(const array<CQuad> &m_lQuads, int TexID = -1);
+	void DoQuadEnvPoint(const CQuad *pQuad, int QIndex, int pIndex);
 	void DoQuadPoint(CQuad *pQuad, int QuadIndex, int v);
 
 	void DoMapEditor(CUIRect View, CUIRect Toolbar);
diff --git a/src/game/editor/io.cpp b/src/game/editor/io.cpp
index 463147e1..529638cf 100644
--- a/src/game/editor/io.cpp
+++ b/src/game/editor/io.cpp
@@ -391,6 +391,7 @@ int CEditorMap::Save(class IStorage *pStorage, const char *pFileName)
 	}
 
 	df.AddItem(MAPITEMTYPE_ENVPOINTS, 0, TotalSize, pPoints);
+	mem_free(pPoints);
 
 	// finish the data file
 	df.Finish();
@@ -479,6 +480,7 @@ int CEditorMap::Load(class IStorage *pStorage, const char *pFileName, int Storag
 					{
 						*pImg = ImgInfo;
 						pImg->m_TexID = m_pEditor->Graphics()->LoadTextureRaw(ImgInfo.m_Width, ImgInfo.m_Height, ImgInfo.m_Format, ImgInfo.m_pData, CImageInfo::FORMAT_AUTO, 0);
+						ImgInfo.m_pData = 0;
 						pImg->m_External = 1;
 					}
 				}
diff --git a/src/game/editor/layer_quads.cpp b/src/game/editor/layer_quads.cpp
index d0b66405..321a28f8 100644
--- a/src/game/editor/layer_quads.cpp
+++ b/src/game/editor/layer_quads.cpp
@@ -27,7 +27,10 @@ void CLayerQuads::Render()
 	if(m_Image >= 0 && m_Image < m_pEditor->m_Map.m_lImages.size())
 		Graphics()->TextureSet(m_pEditor->m_Map.m_lImages[m_Image]->m_TexID);
 
-	m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor);
+	Graphics()->BlendNone();
+	m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_OPAQUE, m_pEditor->EnvelopeEval, m_pEditor);
+	Graphics()->BlendNormal();
+	m_pEditor->RenderTools()->RenderQuads(m_lQuads.base_ptr(), m_lQuads.size(), LAYERRENDERFLAG_TRANSPARENT, m_pEditor->EnvelopeEval, m_pEditor);
 }
 
 CQuad *CLayerQuads::NewQuad()
diff --git a/src/game/editor/layer_tiles.cpp b/src/game/editor/layer_tiles.cpp
index 9a21e5ce..032f391f 100644
--- a/src/game/editor/layer_tiles.cpp
+++ b/src/game/editor/layer_tiles.cpp
@@ -64,7 +64,11 @@ void CLayerTiles::Render()
 		m_TexID = m_pEditor->m_Map.m_lImages[m_Image]->m_TexID;
 	Graphics()->TextureSet(m_TexID);
 	vec4 Color = vec4(m_Color.r/255.0f, m_Color.g/255.0f, m_Color.b/255.0f, m_Color.a/255.0f);
-	m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE|LAYERRENDERFLAG_TRANSPARENT,
+	Graphics()->BlendNone();
+	m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_OPAQUE,
+												m_pEditor->EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset);
+	Graphics()->BlendNormal();
+	m_pEditor->RenderTools()->RenderTilemap(m_pTiles, m_Width, m_Height, 32.0f, Color, LAYERRENDERFLAG_TRANSPARENT,
 												m_pEditor->EnvelopeEval, m_pEditor, m_ColorEnv, m_ColorEnvOffset);
 }
 
@@ -334,6 +338,7 @@ void CLayerTiles::ShowInfo()
 	float ScreenX0, ScreenY0, ScreenX1, ScreenY1;
 	Graphics()->GetScreen(&ScreenX0, &ScreenY0, &ScreenX1, &ScreenY1);
 	Graphics()->TextureSet(m_pEditor->Client()->GetDebugFont());
+	Graphics()->QuadsBegin();
 
 	int StartY = max(0, (int)(ScreenY0/32.0f)-1);
 	int StartX = max(0, (int)(ScreenX0/32.0f)-1);
@@ -348,17 +353,18 @@ void CLayerTiles::ShowInfo()
 			{
 				char aBuf[64];
 				str_format(aBuf, sizeof(aBuf), "%i", m_pTiles[c].m_Index);
-				m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, 1,1,1,1, aBuf);
+				m_pEditor->Graphics()->QuadsText(x*32, y*32, 16.0f, aBuf);
 
 				char aFlags[4] = {	m_pTiles[c].m_Flags&TILEFLAG_VFLIP ? 'V' : ' ',
 									m_pTiles[c].m_Flags&TILEFLAG_HFLIP ? 'H' : ' ',
 									m_pTiles[c].m_Flags&TILEFLAG_ROTATE? 'R' : ' ',
 									0};
-				m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, 1,1,1,1, aFlags);
+				m_pEditor->Graphics()->QuadsText(x*32, y*32+16, 16.0f, aFlags);
 			}
 			x += m_pTiles[c].m_Skip;
 		}
 
+	Graphics()->QuadsEnd();
 	Graphics()->MapScreen(ScreenX0, ScreenY0, ScreenX1, ScreenY1);
 }
 
diff --git a/src/game/editor/popups.cpp b/src/game/editor/popups.cpp
index 2382823d..f281c6aa 100644
--- a/src/game/editor/popups.cpp
+++ b/src/game/editor/popups.cpp
@@ -554,7 +554,6 @@ int CEditor::PopupPoint(CEditor *pEditor, CUIRect View)
 		{
 			if(pEditor->m_SelectedPoints&(1<<v))
 			{
-				Color = 0;
 				pQuad->m_aColors[v].r = (NewVal>>24)&0xff;
 				pQuad->m_aColors[v].g = (NewVal>>16)&0xff;
 				pQuad->m_aColors[v].b = (NewVal>>8)&0xff;
diff --git a/src/game/server/entities/character.cpp b/src/game/server/entities/character.cpp
index dc70641a..d7da2498 100644
--- a/src/game/server/entities/character.cpp
+++ b/src/game/server/entities/character.cpp
@@ -79,6 +79,7 @@ bool CCharacter::Spawn(CPlayer *pPlayer, vec2 Pos)
 	}
     /* end zCatch */
 	
+	m_LastNoAmmoSound = -1;
 	m_QueuedWeapon = -1;
 
 	m_pPlayer = pPlayer;
@@ -293,7 +294,11 @@ void CCharacter::FireWeapon()
 	{
 		// 125ms is a magical limit of how fast a human can click
 		m_ReloadTimer = 125 * Server()->TickSpeed() / 1000;
-		GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);
+		if(m_LastNoAmmoSound+Server()->TickSpeed() <= Server()->Tick())
+		{
+			GameServer()->CreateSound(m_Pos, SOUND_WEAPON_NOAMMO);
+			m_LastNoAmmoSound = Server()->Tick();
+		}
 		return;
 	}
 
diff --git a/src/game/server/entities/character.h b/src/game/server/entities/character.h
index dae01bd4..8bd1d3da 100644
--- a/src/game/server/entities/character.h
+++ b/src/game/server/entities/character.h
@@ -100,6 +100,7 @@ private:
 
 	// last tick that the player took any action ie some input
 	int m_LastAction;
+	int m_LastNoAmmoSound;
 
 	// these are non-heldback inputs
 	CNetObj_PlayerInput m_LatestPrevInput;
diff --git a/src/game/server/gamecontext.cpp b/src/game/server/gamecontext.cpp
index e08f1b44..66829db2 100644
--- a/src/game/server/gamecontext.cpp
+++ b/src/game/server/gamecontext.cpp
@@ -682,9 +682,12 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 
 	if(!pRawMsg)
 	{
-		char aBuf[256];
-		str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgID), MsgID, m_NetObjHandler.FailedMsgOn());
-		Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
+		if(g_Config.m_Debug)
+		{
+			char aBuf[256];
+			str_format(aBuf, sizeof(aBuf), "dropped weird message '%s' (%d), failed on '%s'", m_NetObjHandler.GetMsgName(MsgID), MsgID, m_NetObjHandler.FailedMsgOn());
+			Console()->Print(IConsole::OUTPUT_LEVEL_DEBUG, "server", aBuf);
+		}
 		return;
 	}
 
@@ -1076,7 +1079,6 @@ void CGameContext::OnMessage(int MsgID, CUnpacker *pUnpacker, int ClientID)
 		{
 			OptionMsg.m_NumOptions = NumOptions;
 			Server()->SendPackMsg(&OptionMsg, MSGFLAG_VITAL, ClientID);
-			NumOptions = 0;
 		}
 
 		// send tuning parameters to client
diff --git a/src/game/server/gamecontroller.cpp b/src/game/server/gamecontroller.cpp
index 7001ca32..0ee250e8 100644
--- a/src/game/server/gamecontroller.cpp
+++ b/src/game/server/gamecontroller.cpp
@@ -281,8 +281,8 @@ void IGameController::CycleMap()
 		pNextMap = pMapRotation;
 
 	// cut out the next map
-	char aBuf[512];
-	for(int i = 0; i < 512; i++)
+	char aBuf[512] = {0};
+	for(int i = 0; i < 511; i++)
 	{
 		aBuf[i] = pNextMap[i];
 		if(IsSeparator(pNextMap[i]) || pNextMap[i] == 0)
diff --git a/src/game/server/gamemodes/ctf.cpp b/src/game/server/gamemodes/ctf.cpp
index 9e45c1fe..140dadf9 100644
--- a/src/game/server/gamemodes/ctf.cpp
+++ b/src/game/server/gamemodes/ctf.cpp
@@ -98,7 +98,7 @@ bool CGameControllerCTF::CanBeMovedOnBalance(int ClientID)
 		for(int fi = 0; fi < 2; fi++)
 		{
 			CFlag *F = m_apFlags[fi];
-			if(F->m_pCarryingCharacter == Character)
+			if(F && F->m_pCarryingCharacter == Character)
 				return false;
 		}
 	}
diff --git a/src/game/server/player.cpp b/src/game/server/player.cpp
index 993f9182..7e07c07f 100644
--- a/src/game/server/player.cpp
+++ b/src/game/server/player.cpp
@@ -289,6 +289,7 @@ void CPlayer::SetTeam(int Team, bool DoChatMsg)
 
 	m_Team = Team;
 	m_LastActionTick = Server()->Tick();
+	m_SpectatorID = SPEC_FREEVIEW;
 	// we got to wait 0.5 secs before respawning
 	m_RespawnTick = Server()->Tick()+Server()->TickSpeed()/2;
 	str_format(aBuf, sizeof(aBuf), "team_join player='%d:%s' m_Team=%d", m_ClientID, Server()->ClientName(m_ClientID), m_Team);
diff --git a/src/game/version.h b/src/game/version.h
index 3d909e36..76d95dd0 100644
--- a/src/game/version.h
+++ b/src/game/version.h
@@ -3,7 +3,7 @@
 #ifndef GAME_VERSION_H
 #define GAME_VERSION_H
 #include "generated/nethash.cpp"
-#define GAME_VERSION "0.6 trunk"
+#define GAME_VERSION "0.6.2"
 #define GAME_NETVERSION "0.6 " GAME_NETVERSION_HASH
-static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '1', 0};
+static const char GAME_RELEASE_VERSION[8] = {'0', '.', '6', '.', '2', 0};
 #endif
diff --git a/src/mastersrv/mastersrv.cpp b/src/mastersrv/mastersrv.cpp
index c88a9e78..1098123b 100644
--- a/src/mastersrv/mastersrv.cpp
+++ b/src/mastersrv/mastersrv.cpp
@@ -348,7 +348,11 @@ int main(int argc, const char **argv) // ignore_convention
 		m_pConsole->ParseArguments(argc-1, &argv[1]); // ignore_convention
 
 	if(g_Config.m_Bindaddr[0] && net_host_lookup(g_Config.m_Bindaddr, &BindAddr, NETTYPE_ALL) == 0)
+	{
+		// got bindaddr
+		BindAddr.type = NETTYPE_ALL;
 		BindAddr.port = MASTERSERVER_PORT;
+	}
 	else
 	{
 		mem_zero(&BindAddr, sizeof(BindAddr));
@@ -368,6 +372,9 @@ int main(int argc, const char **argv) // ignore_convention
 		return -1;
 	}
 
+	// process pending commands
+	m_pConsole->StoreCommands(false);
+
 	dbg_msg("mastersrv", "started");
 
 	while(1)
diff --git a/src/versionsrv/mapversions.h b/src/versionsrv/mapversions.h
new file mode 100644
index 00000000..fe9e4229
--- /dev/null
+++ b/src/versionsrv/mapversions.h
@@ -0,0 +1,22 @@
+/* (c) Magnus Auvinen. See licence.txt in the root of the distribution for more information. */
+/* If you are missing that file, acquire a complete release at teeworlds.com.                */
+#ifndef VERSIONSRV_MAPVERSIONS_H
+#define VERSIONSRV_MAPVERSIONS_H
+
+static CMapVersion s_aMapVersionList[] = {
+	{"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}},
+	{"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}},
+	{"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}},
+	{"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}},
+	{"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}},
+	{"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}},
+	{"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}},
+	{"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}},
+	{"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}},
+	{"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}},
+	{"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}},
+	{"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}},
+	{"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}},
+};
+static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion);
+#endif
diff --git a/src/versionsrv/versionsrv.cpp b/src/versionsrv/versionsrv.cpp
index da55e717..9d6e2960 100644
--- a/src/versionsrv/versionsrv.cpp
+++ b/src/versionsrv/versionsrv.cpp
@@ -7,6 +7,7 @@
 #include <game/version.h>
 
 #include "versionsrv.h"
+#include "mapversions.h"
 
 enum {
 	MAX_MAPS_PER_PACKET=48,
diff --git a/src/versionsrv/versionsrv.h b/src/versionsrv/versionsrv.h
index 383f1ac4..46f64251 100644
--- a/src/versionsrv/versionsrv.h
+++ b/src/versionsrv/versionsrv.h
@@ -11,23 +11,6 @@ struct CMapVersion
 	unsigned char m_aSize[4];
 };
 
-static CMapVersion s_aMapVersionList[] = {
-	{"ctf1", {0x06, 0xb5, 0xf1, 0x17}, {0x00, 0x00, 0x12, 0x38}},
-	{"ctf2", {0x27, 0xbc, 0x5e, 0xac}, {0x00, 0x00, 0x64, 0x1a}},
-	{"ctf3", {0xa3, 0x73, 0x9d, 0x41}, {0x00, 0x00, 0x17, 0x0f}},
-	{"ctf4", {0xbe, 0x7c, 0x4d, 0xb9}, {0x00, 0x00, 0x2e, 0xfe}},
-	{"ctf5", {0xd9, 0x21, 0x29, 0xa0}, {0x00, 0x00, 0x2f, 0x4c}},
-	{"ctf6", {0x28, 0xc8, 0x43, 0x51}, {0x00, 0x00, 0x69, 0x2f}},
-	{"ctf7", {0x1d, 0x35, 0x98, 0x72}, {0x00, 0x00, 0x15, 0x87}},
-	{"dm1", {0xf2, 0x15, 0x9e, 0x6e}, {0x00, 0x00, 0x16, 0xad}},
-	{"dm2", {0x71, 0x83, 0x98, 0x78}, {0x00, 0x00, 0x21, 0xdf}},
-	{"dm6", {0x47, 0x4d, 0xa2, 0x35}, {0x00, 0x00, 0x1e, 0x95}},
-	{"dm7", {0x42, 0x6d, 0xa1, 0x67}, {0x00, 0x00, 0x27, 0x2a}},
-	{"dm8", {0x85, 0xf1, 0x1e, 0xd6}, {0x00, 0x00, 0x9e, 0xbd}},
-	{"dm9", {0x42, 0xd4, 0x77, 0x7e}, {0x00, 0x00, 0x20, 0x11}},
-};
-static const int s_NumMapVersionItems = sizeof(s_aMapVersionList)/sizeof(CMapVersion);
-
 static const unsigned char VERSIONSRV_GETVERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 'g'};
 static const unsigned char VERSIONSRV_VERSION[] = {255, 255, 255, 255, 'v', 'e', 'r', 's'};