(svn r13381) [NoAI] -Sync with trunk r13325:13380 noai
authorglx
Wed, 04 Jun 2008 22:34:45 +0000
branchnoai
changeset 10829 8a0ec0f0f928
parent 10804 a02ab0ca5ae9
child 10831 f7e17819358b
(svn r13381) [NoAI] -Sync with trunk r13325:13380
Makefile.src.in
bin/data/openttdd.grf
bin/data/openttdw.grf
config.lib
projects/determineversion.vbs
projects/openttd_vs80.vcproj
projects/openttd_vs90.vcproj
readme.txt
source.list
src/blitter/8bpp_optimized.cpp
src/blitter/factory.hpp
src/cheat_gui.cpp
src/console.cpp
src/console_cmds.cpp
src/console_func.h
src/console_internal.h
src/date.cpp
src/debug.cpp
src/debug.h
src/driver.cpp
src/economy.cpp
src/economy_type.h
src/effectvehicle.cpp
src/engine.cpp
src/fios.cpp
src/fios.h
src/gamelog.cpp
src/gamelog.h
src/gfxinit.cpp
src/industry_cmd.cpp
src/main_gui.cpp
src/map.cpp
src/map_func.h
src/misc.cpp
src/misc/smallvec.h
src/misc_gui.cpp
src/network/core/config.h
src/network/core/core.h
src/network/core/game.h
src/network/core/tcp.cpp
src/network/network.cpp
src/network/network.h
src/network/network_client.cpp
src/network/network_data.cpp
src/network/network_data.h
src/network/network_func.h
src/network/network_gamelist.cpp
src/network/network_gamelist.h
src/network/network_gui.cpp
src/network/network_gui.h
src/network/network_internal.h
src/network/network_server.cpp
src/network/network_server.h
src/network/network_type.h
src/network/network_udp.cpp
src/newgrf.cpp
src/newgrf_config.cpp
src/newgrf_engine.cpp
src/newgrf_gui.cpp
src/news_gui.cpp
src/news_type.h
src/openttd.cpp
src/openttd.h
src/order_cmd.cpp
src/os2.cpp
src/ottdres.rc.in
src/player_gui.cpp
src/players.cpp
src/rail_gui.cpp
src/rev.cpp.in
src/rev.h
src/road_cmd.cpp
src/saveload.cpp
src/saveload.h
src/settings.cpp
src/settings_func.h
src/settings_gui.cpp
src/settings_internal.h
src/settings_type.h
src/sortlist_type.h
src/subsidy_gui.cpp
src/table/files.h
src/table/sprites.h
src/table/town_land.h
src/toolbar_gui.cpp
src/town.h
src/town_cmd.cpp
src/variables.h
src/vehicle.cpp
src/win32.cpp
src/window.cpp
src/yapf/follow_track.hpp
src/yapf/yapf.h
src/yapf/yapf_base.hpp
src/yapf/yapf_costrail.hpp
src/yapf/yapf_destrail.hpp
src/yapf/yapf_rail.cpp
src/yapf/yapf_road.cpp
src/yapf/yapf_ship.cpp
--- a/Makefile.src.in	Mon Jun 02 01:46:03 2008 +0000
+++ b/Makefile.src.in	Wed Jun 04 22:34:45 2008 +0000
@@ -89,6 +89,32 @@
 $(LANG_OBJS_DIR)/table/strings.h: $(LANG_DIR)/english.txt $(LANG_OBJS_DIR)/$(STRGEN)
 	$(MAKE) -C $(LANG_OBJS_DIR) table/strings.h
 
+
+# Determine if we are using a modified version
+ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
+REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
+else
+# Are we a git dir?
+ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1)
+REV_MODIFIED := $(shell if cd "$(SRC_DIR)/.." && git diff-index HEAD src | read dummy; then echo M; fi)
+else
+# Are we a hg (Mercurial) dir?
+ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1)
+REV_MODIFIED := $(shell if hg status $(SRC_DIR) | grep -v '^?' | read dummy; then echo M; fi)
+else
+MODIFIED="1"
+endif
+endif
+endif
+
+ifneq ($(MODIFIED),"1")
+ifeq ($(REV_MODIFIED),)
+MODIFIED="0"
+else
+MODIFIED="2"
+endif
+endif
+
 # Make the revision number
 ifdef REVISION
 REV := $(REVISION)
@@ -97,7 +123,6 @@
 # Are we a SVN dir?
 ifeq ($(shell if test -d $(SRC_DIR)/.svn; then echo 1; fi), 1)
 # Find if the local source if modified
-REV_MODIFIED := $(shell svnversion $(SRC_DIR) | sed -n 's/.*\(M\).*/\1/p' )
 # Find the revision like: rXXXX-branch
 REV := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^URL:.*branch/ { split($$2, a, "/"); BRANCH="-"a[5] } /^Last Changed Rev:/ { REV="r"$$4"$(REV_MODIFIED)" } END { print REV BRANCH }')
 REV_NR := $(shell LC_ALL=C svn info $(SRC_DIR) | $(AWK) '/^Last Changed Rev:/ { print $$4 }')
@@ -105,13 +130,13 @@
 # Are we a git dir?
 ifeq ($(shell if test -d $(SRC_DIR)/../.git; then echo 1; fi), 1)
 # Find the revision like: gXXXXM-branch
-REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(shell if cd "$(SRC_DIR)/.." && git diff-index HEAD src | read dummy; then echo M; fi)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//')
+REV := g$(shell if head=`LC_ALL=C git rev-parse --verify HEAD 2>/dev/null`; then echo "$$head" | cut -c1-8; fi)$(REV_MODIFIED)$(shell git branch|grep '[*]' | sed 's/\* /-/;s/^-master$$//')
 REV_NR := $(shell LC_ALL=C cd "$(SRC_DIR)/.." && git log --pretty=format:%s src | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
 else
 # Are we a hg (Mercurial) dir?
 ifeq ($(shell if test -d $(SRC_DIR)/../.hg; then echo 1; fi), 1)
 # Find the revision like: hXXXXM-branch
-REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(shell if hg status $(SRC_DIR) | grep -v '^?' | read dummy; then echo M; fi)$(shell hg branch | sed 's/^/-/;s/^-default$$//')
+REV := h$(shell if head=`LC_ALL=C hg tip 2>/dev/null`; then echo "$$head" | head -n 1 | cut -c19-26; fi)$(REV_MODIFIED)$(shell hg branch | sed 's/^/-/;s/^-default$$//')
 REV_NR := $(shell LC_ALL=C hg log -k "svn" -l 1 --template "{desc}\n" $(SRC_DIR) | grep -m 1 "^(svn r[0-9]*)" | sed "s/.*(svn r\([0-9]*\)).*/\1/" )
 endif
 endif
@@ -287,7 +312,7 @@
 # Revision files
 
 $(SRC_DIR)/rev.cpp: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/rev.cpp.in
-	$(Q)cat $(SRC_DIR)/rev.cpp.in      | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/rev.cpp
+	$(Q)cat $(SRC_DIR)/rev.cpp.in      | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@MODIFIED@@#$(MODIFIED)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/rev.cpp
 
 $(SRC_DIR)/ottdres.rc: $(CONFIG_CACHE_VERSION) $(SRC_DIR)/ottdres.rc.in
 	$(Q)cat $(SRC_DIR)/ottdres.rc.in | sed "s#@@REVISION@@#$(REV_NR)#g;s#@@VERSION@@#$(REV)#g;s#@@DATE@@#`date +%d.%m.%y`#g" > $(SRC_DIR)/ottdres.rc
Binary file bin/data/openttdd.grf has changed
Binary file bin/data/openttdw.grf has changed
--- a/config.lib	Mon Jun 02 01:46:03 2008 +0000
+++ b/config.lib	Wed Jun 04 22:34:45 2008 +0000
@@ -936,6 +936,10 @@
 		if [ $cc_version -ge 30 ]; then
 			CFLAGS="$CFLAGS -W -Wno-unused-parameter -Wformat=2"
 			CFLAGS="$CFLAGS -Wredundant-decls"
+			# Do not warn about unused variables when building without asserts
+			if [ $enable_assert -eq 0 ]; then
+				CFLAGS="$CFLAGS -Wno-unused-variable"
+			fi
 		fi
 
 		if [ $cc_version -ge 34 ]; then
--- a/projects/determineversion.vbs	Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/determineversion.vbs	Wed Jun 04 22:34:45 2008 +0000
@@ -14,23 +14,28 @@
 	file.Close
 End Sub
 
-Sub UpdateFile(revision, version, cur_date, filename)
+Sub UpdateFile(modified, revision, version, cur_date, filename)
 	FSO.CopyFile filename & ".in", filename
+	FindReplaceInFile filename, "@@MODIFIED@@", modified
 	FindReplaceInFile filename, "@@REVISION@@", revision
 	FindReplaceInFile filename, "@@VERSION@@", version
 	FindReplaceInFile filename, "@@DATE@@", cur_date
 End Sub
 
 Sub UpdateFiles(version)
-	Dim WshShell, cur_date, revision, oExec
+	Dim WshShell, cur_date, modified, revision, oExec
 	Set WshShell = CreateObject("WScript.Shell")
 	cur_date = DatePart("D", Date) & "." & DatePart("M", Date) & "." & DatePart("YYYY", Date)
 	revision = 0
+	modified = 1
 	Select Case Mid(version, 1, 1)
 		Case "r" ' svn
 			revision = Mid(version, 2)
 			If InStr(revision, "M") Then
 				revision = Mid(revision, 1, InStr(revision, "M") - 1)
+				modified = 2
+			Else
+				modified = 0
 			End If
 			If InStr(revision, "-") Then
 				revision = Mid(revision, 1, InStr(revision, "-") - 1)
@@ -49,8 +54,8 @@
 			End If
 	End Select
 
-	UpdateFile revision, version, cur_date, "../src/rev.cpp"
-	UpdateFile revision, version, cur_date, "../src/ottdres.rc"
+	UpdateFile modified, revision, version, cur_date, "../src/rev.cpp"
+	UpdateFile modified, revision, version, cur_date, "../src/ottdres.rc"
 End Sub
 
 Function ReadRegistryKey(shive, subkey, valuename, architecture)
--- a/projects/openttd_vs80.vcproj	Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/openttd_vs80.vcproj	Wed Jun 04 22:34:45 2008 +0000
@@ -568,6 +568,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\gamelog.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\genworld.cpp"
 				>
 			</File>
@@ -1036,6 +1040,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\gamelog.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\genworld.h"
 				>
 			</File>
@@ -1140,7 +1148,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\network\network_data.h"
+				RelativePath=".\..\src\network\network_func.h"
 				>
 			</File>
 			<File
@@ -1160,6 +1168,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\network\network_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\network\network_udp.h"
 				>
 			</File>
--- a/projects/openttd_vs90.vcproj	Mon Jun 02 01:46:03 2008 +0000
+++ b/projects/openttd_vs90.vcproj	Wed Jun 04 22:34:45 2008 +0000
@@ -565,6 +565,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\gamelog.cpp"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\genworld.cpp"
 				>
 			</File>
@@ -1033,6 +1037,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\gamelog.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\genworld.h"
 				>
 			</File>
@@ -1137,7 +1145,7 @@
 				>
 			</File>
 			<File
-				RelativePath=".\..\src\network\network_data.h"
+				RelativePath=".\..\src\network\network_func.h"
 				>
 			</File>
 			<File
@@ -1157,6 +1165,10 @@
 				>
 			</File>
 			<File
+				RelativePath=".\..\src\network\network_type.h"
+				>
+			</File>
+			<File
 				RelativePath=".\..\src\network\network_udp.h"
 				>
 			</File>
--- a/readme.txt	Mon Jun 02 01:46:03 2008 +0000
+++ b/readme.txt	Wed Jun 04 22:34:45 2008 +0000
@@ -203,6 +203,35 @@
   http://wiki.openttd.org/index.php/Console
 
 
+5.1) Logging of potentially dangerous actions:
+---- ----------------------------------------
+
+OpenTTD is a complex program, and together with NewGRF, it may show a buggy
+behaviour. But not only bugs in code can cause problems. There are several
+ways to affect game state possibly resulting in program crash or multiplayer
+desyncs.
+Easier way would be to forbid all these unsafe actions, but that would affect
+game usability for many players. We certainly do not want that.
+However, we receive bugreports because of this. To reduce time spent with
+solving these problems, these potentially unsafe actions are logged in
+the savegame (including crash.sav). Log is stored in crash logs, too.
+
+Information logged:
+
+* Adding / removing / changing order of NewGRFs
+* Changing NewGRF parameters, loading compatible NewGRF
+* Changing game mode (scenario editor <-> normal game)
+* Loading game saved in a different OTTD / TTDPatch / TTD version
+* Running a modified OTTD build
+* Changing patch settings affecting NewGRF behaviour (non-networksafe patches)
+* Changing landscape (by cheat)
+
+No personal information is stored.
+
+You can show the gamelog by typing 'gamelog' in the console or by running
+OpenTTD in debug mode.
+
+
 6.0) Configuration File:
 ---- -------------------
 The configuration file for OpenTTD (openttd.cfg) is in a simple Windows-like
--- a/source.list	Mon Jun 02 01:46:03 2008 +0000
+++ b/source.list	Wed Jun 04 22:34:45 2008 +0000
@@ -28,6 +28,7 @@
 fileio.cpp
 fios.cpp
 fontcache.cpp
+gamelog.cpp
 genworld.cpp
 gfx.cpp
 gfxinit.cpp
@@ -184,6 +185,7 @@
 fios.h
 fontcache.h
 functions.h
+gamelog.h
 genworld.h
 core/geometry_type.hpp
 gfx_func.h
@@ -210,11 +212,12 @@
 namegen_func.h
 network/network.h
 network/network_client.h
-network/network_data.h
+network/network_func.h
 network/network_gamelist.h
 network/network_gui.h
 network/network_internal.h
 network/network_server.h
+network/network_type.h
 network/network_udp.h
 newgrf.h
 newgrf_callbacks.h
--- a/src/blitter/8bpp_optimized.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/blitter/8bpp_optimized.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -6,38 +6,34 @@
 #include "../zoom_func.h"
 #include "../debug.h"
 #include "../core/alloc_func.hpp"
+#include "../core/math_func.hpp"
 #include "8bpp_optimized.hpp"
 
 static FBlitter_8bppOptimized iFBlitter_8bppOptimized;
 
 void Blitter_8bppOptimized::Draw(Blitter::BlitterParams *bp, BlitterMode mode, ZoomLevel zoom)
 {
-	const uint8 *src, *src_next;
-	uint8 *dst, *dst_line;
-	uint offset = 0;
-
 	/* Find the offset of this zoom-level */
-	offset = ((const uint8 *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2] | ((const byte *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2 + 1] << 8;
+	uint offset = ((const uint8 *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2] | ((const byte *)bp->sprite)[(int)(zoom - ZOOM_LVL_BEGIN) * 2 + 1] << 8;
 
 	/* Find where to start reading in the source sprite */
-	src = (const uint8 *)bp->sprite + offset;
-	dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
+	const uint8 *src = (const uint8 *)bp->sprite + offset;
+	uint8 *dst_line = (uint8 *)bp->dst + bp->top * bp->pitch + bp->left;
 
 	/* Skip over the top lines in the source image */
 	for (int y = 0; y < bp->skip_top; y++) {
-		uint trans, pixels;
 		for (;;) {
-			trans = *src++;
-			pixels = *src++;
+			uint trans = *src++;
+			uint pixels = *src++;
 			if (trans == 0 && pixels == 0) break;
 			src += pixels;
 		}
 	}
 
-	src_next = src;
+	const uint8 *src_next = src;
 
 	for (int y = 0; y < bp->height; y++) {
-		dst = dst_line;
+		uint8 *dst = dst_line;
 		dst_line += bp->pitch;
 
 		uint skip_left = bp->skip_left;
@@ -45,8 +41,8 @@
 
 		for (;;) {
 			src = src_next;
-			uint8 trans = *src++;
-			uint8 pixels = *src++;
+			uint trans = *src++;
+			uint pixels = *src++;
 			src_next = src + pixels;
 			if (trans == 0 && pixels == 0) break;
 			if (width <= 0) continue;
@@ -75,7 +71,7 @@
 			dst += trans;
 			width -= trans;
 			if (width <= 0) continue;
-			if (pixels > width) pixels = width;
+			pixels = min<uint>(pixels, (uint)width);
 			width -= pixels;
 
 			switch (mode) {
@@ -104,99 +100,98 @@
 
 Sprite *Blitter_8bppOptimized::Encode(SpriteLoader::Sprite *sprite, Blitter::AllocatorProc *allocator)
 {
-	Sprite *dest_sprite;
-	byte *temp_dst;
-	uint memory = 0;
-	uint index = 0;
+	/* Make memory for all zoom-levels */
+	uint memory = (int)(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * sizeof(uint16);
 
-	/* Make memory for all zoom-levels */
-	memory += (int)(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * sizeof(uint16);
 	for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
 		memory += UnScaleByZoom(sprite->height, i) * UnScaleByZoom(sprite->width, i);
-		index += 2;
 	}
 
 	/* We have no idea how much memory we really need, so just guess something */
 	memory *= 5;
-	temp_dst = MallocT<byte>(memory);
+	byte *temp_dst = MallocT<byte>(memory);
+	byte *dst = &temp_dst[(ZOOM_LVL_END - ZOOM_LVL_BEGIN) * 2];
 
 	/* Make the sprites per zoom-level */
 	for (ZoomLevel i = ZOOM_LVL_BEGIN; i < ZOOM_LVL_END; i++) {
-		/* Store the scaled image */
-		const SpriteLoader::CommonPixel *src;
-
 		/* Store the index table */
+		uint index = dst - temp_dst;
 		temp_dst[i * 2] = index & 0xFF;
 		temp_dst[i * 2 + 1] = (index >> 8) & 0xFF;
 
-		byte *dst = &temp_dst[index];
+		/* cache values, because compiler can't cache it */
+		int scaled_height = UnScaleByZoom(sprite->height, i);
+		int scaled_width  = UnScaleByZoom(sprite->width,  i);
+		int scaled_1      =   ScaleByZoom(1,              i);
 
-		for (int y = 0; y < UnScaleByZoom(sprite->height, i); y++) {
+		for (int y = 0; y < scaled_height; y++) {
 			uint trans = 0;
 			uint pixels = 0;
-			uint last_color = 0;
-			uint count_index = 0;
-			uint rx = 0;
-			src = &sprite->data[ScaleByZoom(y, i) * sprite->width];
+			uint last_colour = 0;
+			byte *count_dst = NULL;
 
-			for (int x = 0; x < UnScaleByZoom(sprite->width, i); x++) {
-				uint color = 0;
+			/* Store the scaled image */
+			const SpriteLoader::CommonPixel *src = &sprite->data[ScaleByZoom(y, i) * sprite->width];
+			const SpriteLoader::CommonPixel *src_end = &src[sprite->width];
+
+			for (int x = 0; x < scaled_width; x++) {
+				uint colour = 0;
 
 				/* Get the color keeping in mind the zoom-level */
-				for (int j = 0; j < ScaleByZoom(1, i); j++) {
-					if (src->m != 0) color = src->m;
-					src++;
-					rx++;
+				for (int j = 0; j < scaled_1; j++) {
+					if (src->m != 0) colour = src->m;
 					/* Because of the scaling it might happen we read outside the buffer. Avoid that. */
-					if (rx == sprite->width) break;
+					if (++src == src_end) break;
 				}
 
-				if (last_color == 0 || color == 0 || pixels == 255) {
-					if (count_index != 0) {
+				if (last_colour == 0 || colour == 0 || pixels == 255) {
+					if (count_dst != NULL) {
 						/* Write how many non-transparent bytes we get */
-						temp_dst[count_index] = pixels;
+						*count_dst = pixels;
 						pixels = 0;
-						count_index = 0;
+						count_dst = NULL;
 					}
 					/* As long as we find transparency bytes, keep counting */
-					if (color == 0) {
-						last_color = 0;
+					if (colour == 0) {
+						last_colour = 0;
 						trans++;
 						continue;
 					}
 					/* No longer transparency, so write the amount of transparent bytes */
 					*dst = trans;
-					dst++; index++;
+					dst++;
 					trans = 0;
 					/* Reserve a byte for the pixel counter */
-					count_index = index;
-					dst++; index++;
+					count_dst = dst;
+					dst++;
 				}
-				last_color = color;
+				last_colour = colour;
 				pixels++;
-				*dst = color;
-				dst++; index++;
+				*dst = colour;
+				dst++;
 			}
 
-			if (count_index != 0) temp_dst[count_index] = pixels;
+			if (count_dst != NULL) *count_dst = pixels;
 
 			/* Write line-ending */
-			*dst = 0; dst++; index++;
-			*dst = 0; dst++; index++;
+			*dst = 0; dst++;
+			*dst = 0; dst++;
 		}
 	}
 
+	uint size = dst - temp_dst;
+
 	/* Safety check, to make sure we guessed the size correctly */
-	assert(index < memory);
+	assert(size < memory);
 
 	/* Allocate the exact amount of memory we need */
-	dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + index);
+	Sprite *dest_sprite = (Sprite *)allocator(sizeof(*dest_sprite) + size);
 
 	dest_sprite->height = sprite->height;
 	dest_sprite->width  = sprite->width;
 	dest_sprite->x_offs = sprite->x_offs;
 	dest_sprite->y_offs = sprite->y_offs;
-	memcpy(dest_sprite->data, temp_dst, index);
+	memcpy(dest_sprite->data, temp_dst, size);
 	free(temp_dst);
 
 	return dest_sprite;
--- a/src/blitter/factory.hpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/blitter/factory.hpp	Wed Jun 04 22:34:45 2008 +0000
@@ -43,11 +43,8 @@
 		if (name == NULL) return;
 
 		this->name = strdup(name);
-#if !defined(NDEBUG) || defined(WITH_ASSERT)
-		/* NDEBUG disables asserts and gives a warning: unused variable 'P' */
-		std::pair<Blitters::iterator, bool> P =
-#endif /* !NDEBUG */
-		GetBlitters().insert(Blitters::value_type(name, this));
+
+		std::pair<Blitters::iterator, bool> P = GetBlitters().insert(Blitters::value_type(name, this));
 		assert(P.second);
 	}
 
--- a/src/cheat_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/cheat_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -19,6 +19,7 @@
 #include "rail_gui.h"
 #include "gui.h"
 #include "player_gui.h"
+#include "gamelog.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -65,7 +66,12 @@
 	if (p1 == -1) p1 = 3;
 	if (p1 ==  4) p1 = 0;
 	_settings_game.game_creation.landscape = p1;
+
+	GamelogStartAction(GLAT_CHEAT);
+	GamelogTestMode();
 	ReloadNewGRFData();
+	GamelogStopAction();
+
 	return _settings_game.game_creation.landscape;
 }
 
--- a/src/console.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -3,11 +3,13 @@
 /** @file console.cpp Handling of the in-game console. */
 
 #include "stdafx.h"
-#include "console_internal.h"
-#include "network/network_data.h"
-#include "network/network_server.h"
 #include "core/alloc_func.hpp"
 #include "string_func.h"
+#include "strings_type.h"
+#include "core/math_func.hpp"
+#include "console_internal.h"
+#include "network/network.h"
+#include "network/network_func.h"
 #include "rev.h"
 
 #include <stdarg.h>
@@ -90,7 +92,7 @@
 #ifdef ENABLE_NETWORK
 	if (_redirect_console_to_client != 0) {
 		/* Redirect the string to the client */
-		SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(_redirect_console_to_client), color_code, string);
+		NetworkServerSendRcon(_redirect_console_to_client, color_code, string);
 		return;
 	}
 #endif
--- a/src/console_cmds.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_cmds.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -10,17 +10,14 @@
 #include "landscape.h"
 #include "saveload.h"
 #include "variables.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_server.h"
-#include "network/network_udp.h"
+#include "network/network.h"
+#include "network/network_func.h"
 #include "command_func.h"
 #include "settings_func.h"
 #include "fios.h"
 #include "fileio.h"
 #include "screenshot.h"
 #include "genworld.h"
-#include "network/network.h"
 #include "strings_func.h"
 #include "viewport_func.h"
 #include "window_func.h"
@@ -32,6 +29,7 @@
 #include "player_func.h"
 #include "player_base.h"
 #include "settings_type.h"
+#include "gamelog.h"
 #include "ai/ai.h"
 
 #ifdef ENABLE_NETWORK
@@ -219,32 +217,25 @@
 
 static const FiosItem* GetFiosItem(const char* file)
 {
-	int i;
-
 	_saveload_mode = SLD_LOAD_GAME;
 	BuildFileList();
 
-	for (i = 0; i < _fios_num; i++) {
-		if (strcmp(file, _fios_list[i].name) == 0) break;
-		if (strcmp(file, _fios_list[i].title) == 0) break;
+	for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
+		if (strcmp(file, item->name) == 0) return item;
+		if (strcmp(file, item->title) == 0) return item;
 	}
 
-	if (i == _fios_num) { // If no name matches, try to parse it as number
-		char* endptr;
+	/* If no name matches, try to parse it as number */
+	char *endptr;
+	int i = strtol(file, &endptr, 10);
+	if (file == endptr || *endptr != '\0') i = -1;
 
-		i = strtol(file, &endptr, 10);
-		if (file == endptr || *endptr != '\0') i = -1;
-	}
-
-	return IsInsideMM(i, 0, _fios_num) ? &_fios_list[i] : NULL;
+	return IsInsideMM(i, 0, _fios_items.Length()) ? _fios_items.Get(i) : NULL;
 }
 
 
 DEF_CONSOLE_CMD(ConLoad)
 {
-	const FiosItem *item;
-	const char *file;
-
 	if (argc == 0) {
 		IConsoleHelp("Load a game by name or index. Usage: 'load <file | number>'");
 		return true;
@@ -252,8 +243,8 @@
 
 	if (argc != 2) return false;
 
-	file = argv[1];
-	item = GetFiosItem(file);
+	const char *file = argv[1];
+	const FiosItem *item = GetFiosItem(file);
 	if (item != NULL) {
 		switch (item->type) {
 			case FIOS_TYPE_FILE: case FIOS_TYPE_OLDFILE: {
@@ -276,9 +267,6 @@
 
 DEF_CONSOLE_CMD(ConRemove)
 {
-	const FiosItem* item;
-	const char* file;
-
 	if (argc == 0) {
 		IConsoleHelp("Remove a savegame by name or index. Usage: 'rm <file | number>'");
 		return true;
@@ -286,8 +274,8 @@
 
 	if (argc != 2) return false;
 
-	file = argv[1];
-	item = GetFiosItem(file);
+	const char *file = argv[1];
+	const FiosItem *item = GetFiosItem(file);
 	if (item != NULL) {
 		if (!FiosDelete(item->name))
 			IConsolePrintF(CC_ERROR, "%s: Failed to delete file", file);
@@ -303,8 +291,6 @@
 /* List all the files in the current dir via console */
 DEF_CONSOLE_CMD(ConListFiles)
 {
-	int i;
-
 	if (argc == 0) {
 		IConsoleHelp("List all loadable savegames and directories in the current dir via console. Usage: 'ls | dir'");
 		return true;
@@ -312,9 +298,8 @@
 
 	BuildFileList();
 
-	for (i = 0; i < _fios_num; i++) {
-		const FiosItem *item = &_fios_list[i];
-		IConsolePrintF(CC_DEFAULT, "%d) %s", i, item->title);
+	for (uint i = 0; i < _fios_items.Length(); i++) {
+		IConsolePrintF(CC_DEFAULT, "%d) %s", i, _fios_items[i].title);
 	}
 
 	FiosFreeSavegameList();
@@ -324,9 +309,6 @@
 /* Change the dir via console */
 DEF_CONSOLE_CMD(ConChangeDirectory)
 {
-	const FiosItem *item;
-	const char *file;
-
 	if (argc == 0) {
 		IConsoleHelp("Change the dir via console. Usage: 'cd <directory | number>'");
 		return true;
@@ -334,8 +316,8 @@
 
 	if (argc != 2) return false;
 
-	file = argv[1];
-	item = GetFiosItem(file);
+	const char *file = argv[1];
+	const FiosItem *item = GetFiosItem(file);
 	if (item != NULL) {
 		switch (item->type) {
 			case FIOS_TYPE_DIR: case FIOS_TYPE_DRIVE: case FIOS_TYPE_PARENT:
@@ -426,8 +408,8 @@
 	}
 
 	if (ci != NULL) {
-		banip = inet_ntoa(*(struct in_addr *)&ci->client_ip);
-		SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+		banip = GetPlayerIP(ci);
+		NetworkServerSendError(index, NETWORK_ERROR_KICKED);
 		IConsolePrint(CC_DEFAULT, "Client banned");
 	} else {
 		IConsolePrint(CC_DEFAULT, "Client not online, banned IP");
@@ -540,98 +522,34 @@
 	if (_network_server) {
 		IConsoleCmdExec(argv[2]);
 	} else {
-		SEND_COMMAND(PACKET_CLIENT_RCON)(argv[1], argv[2]);
+		NetworkClientSendRcon(argv[1], argv[2]);
 	}
 	return true;
 }
 
 DEF_CONSOLE_CMD(ConStatus)
 {
-	static const char* const stat_str[] = {
-		"inactive",
-		"authorizing",
-		"authorized",
-		"waiting",
-		"loading map",
-		"map done",
-		"ready",
-		"active"
-	};
-
-	NetworkTCPSocketHandler *cs;
-
 	if (argc == 0) {
 		IConsoleHelp("List the status of all clients connected to the server. Usage 'status'");
 		return true;
 	}
 
-	FOR_ALL_CLIENTS(cs) {
-		int lag = NetworkCalculateLag(cs);
-		const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
-		const char* status;
-
-		status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
-		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
-			cs->index, ci->client_name, status, lag,
-			ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
-			GetPlayerIP(ci), ci->unique_id);
-	}
-
+	NetworkServerShowStatusToConsole();
 	return true;
 }
 
 DEF_CONSOLE_CMD(ConServerInfo)
 {
-	const NetworkGameInfo *gi;
-
 	if (argc == 0) {
 		IConsoleHelp("List current and maximum client/player limits. Usage 'server_info'");
 		IConsoleHelp("You can change these values by setting the variables 'max_clients', 'max_companies' and 'max_spectators'");
 		return true;
 	}
 
-	gi = &_network_game_info;
-	IConsolePrintF(CC_DEFAULT, "Current/maximum clients:    %2d/%2d", gi->clients_on, gi->clients_max);
-	IConsolePrintF(CC_DEFAULT, "Current/maximum companies:  %2d/%2d", ActivePlayerCount(), gi->companies_max);
-	IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), gi->spectators_max);
-
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookValidateMaxClientsCount)
-{
-	if (_network_game_info.clients_max > MAX_CLIENTS) {
-		_network_game_info.clients_max = MAX_CLIENTS;
-		IConsoleError("Maximum clients out of bounds, truncating to limit.");
-	}
-
-	return true;
-}
+	IConsolePrintF(CC_DEFAULT, "Current/maximum clients:    %2d/%2d", _network_game_info.clients_on, _settings_client.network.max_clients);
+	IConsolePrintF(CC_DEFAULT, "Current/maximum companies:  %2d/%2d", ActivePlayerCount(), _settings_client.network.max_companies);
+	IConsolePrintF(CC_DEFAULT, "Current/maximum spectators: %2d/%2d", NetworkSpectatorCount(), _settings_client.network.max_spectators);
 
-DEF_CONSOLE_HOOK(ConHookValidateMaxCompaniesCount)
-{
-	if (_network_game_info.companies_max > MAX_PLAYERS) {
-		_network_game_info.companies_max = MAX_PLAYERS;
-		IConsoleError("Maximum companies out of bounds, truncating to limit.");
-	}
-
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookValidateMaxSpectatorsCount)
-{
-	/* XXX see ConHookValidateMaxClientsCount */
-	if (_network_game_info.spectators_max > 10) {
-		_network_game_info.spectators_max = 10;
-		IConsoleError("Maximum spectators out of bounds, truncating to limit.");
-	}
-
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookCheckMinPlayers)
-{
-	CheckMinPlayers();
 	return true;
 }
 
@@ -667,7 +585,7 @@
 	}
 
 	if (ci != NULL) {
-		SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(index), NETWORK_ERROR_KICKED);
+		NetworkServerSendError(index, NETWORK_ERROR_KICKED);
 	} else {
 		IConsoleError("Client not found");
 	}
@@ -678,8 +596,6 @@
 DEF_CONSOLE_CMD(ConResetCompany)
 {
 	const Player *p;
-	NetworkTCPSocketHandler *cs;
-	const NetworkClientInfo *ci;
 	PlayerID index;
 
 	if (argc == 0) {
@@ -710,15 +626,11 @@
 		return true;
 	}
 
-	/* Check if the company has active players */
-	FOR_ALL_CLIENTS(cs) {
-		ci = DEREF_CLIENT_INFO(cs);
-		if (ci->client_playas == index) {
-			IConsoleError("Cannot remove company: a client is connected to that company.");
-			return true;
-		}
+	if (NetworkCompanyHasPlayers(index)) {
+		IConsoleError("Cannot remove company: a client is connected to that company.");
+		return false;
 	}
-	ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+	const NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
 	if (ci->client_playas == index) {
 		IConsoleError("Cannot remove company: the server is connected to that company.");
 		return true;
@@ -1274,9 +1186,9 @@
 	if (argc != 2) return false;
 
 	if (!_network_server) {
-		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
+		NetworkClientSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0 /* param does not matter */, argv[1]);
 	} else {
-		NetworkServer_HandleChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_CHAT, DESTTYPE_BROADCAST, 0, argv[1], NETWORK_SERVER_INDEX);
 	}
 
 	return true;
@@ -1328,9 +1240,9 @@
 	}
 
 	if (!_network_server) {
-		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
+		NetworkClientSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2]);
 	} else {
-		NetworkServer_HandleChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_CHAT_COMPANY, DESTTYPE_TEAM, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
 	}
 
 	return true;
@@ -1347,37 +1259,14 @@
 	if (argc != 3) return false;
 
 	if (!_network_server) {
-		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
+		NetworkClientSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2]);
 	} else {
-		NetworkServer_HandleChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_CHAT_CLIENT, DESTTYPE_CLIENT, atoi(argv[1]), argv[2], NETWORK_SERVER_INDEX);
 	}
 
 	return true;
 }
 
-DEF_CONSOLE_HOOK(ConHookServerPW)
-{
-	if (strcmp(_network_server_password, "*") == 0) {
-		_network_server_password[0] = '\0';
-		_network_game_info.use_password = 0;
-	} else {
-		ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
-		_network_game_info.use_password = 1;
-	}
-
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookRconPW)
-{
-	if (strcmp(_network_rcon_password, "*") == 0)
-		_network_rcon_password[0] = '\0';
-
-	ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_game_info.rcon_password));
-
-	return true;
-}
-
 extern void HashCurrentCompanyPassword();
 
 /* Also use from within player_gui to change the password graphically */
@@ -1401,7 +1290,7 @@
 	ttd_strlcpy(_network_player_info[_local_player].password, argv[0], sizeof(_network_player_info[_local_player].password));
 
 	if (!_network_server) {
-		SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
+		NetworkClientSetPassword();
 	} else {
 		HashCurrentCompanyPassword();
 	}
@@ -1411,56 +1300,6 @@
 	return true;
 }
 
-DEF_CONSOLE_HOOK(ConProcPlayerName)
-{
-	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
-
-	if (ci == NULL) return false;
-
-	/* Don't change the name if it is the same as the old name */
-	if (strcmp(ci->client_name, _network_player_name) != 0) {
-		if (!_network_server) {
-			SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_network_player_name);
-		} else {
-			if (NetworkFindName(_network_player_name)) {
-				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _network_player_name);
-				ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
-				NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
-			}
-		}
-	}
-
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookServerName)
-{
-	ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
-	return true;
-}
-
-DEF_CONSOLE_HOOK(ConHookServerAdvertise)
-{
-	if (!_network_advertise) // remove us from advertising
-		NetworkUDPRemoveAdvertise();
-
-	return true;
-}
-
-DEF_CONSOLE_CMD(ConProcServerIP)
-{
-	if (argc == 0) {
-		IConsolePrintF(CC_WARNING, "Current value for 'server_ip': %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-		return true;
-	}
-
-	if (argc != 1) return false;
-
-	_network_server_bind_ip = (strcmp(argv[0], "all") == 0) ? inet_addr("0.0.0.0") : inet_addr(argv[0]);
-	snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-	IConsolePrintF(CC_WARNING, "'server_ip' changed to:  %s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
-	return true;
-}
 #endif /* ENABLE_NETWORK */
 
 DEF_CONSOLE_CMD(ConPatch)
@@ -1476,17 +1315,7 @@
 	if (argc == 2) {
 		IConsoleGetPatchSetting(argv[1]);
 	} else {
-		uint32 val;
-
-		if (GetArgumentInteger(&val, argv[2])) {
-			if (!IConsoleSetPatchSetting(argv[1], val)) {
-				if (_network_server) {
-					IConsoleError("This command/variable is not available during network games.");
-				} else {
-					IConsoleError("This command/variable is only available to a network server.");
-				}
-			}
-		}
+		IConsoleSetPatchSetting(argv[1], argv[2]);
 	}
 
 	return true;
@@ -1525,6 +1354,11 @@
 	return true;
 }
 
+DEF_CONSOLE_CMD(ConGamelogPrint)
+{
+	GamelogPrintConsole();
+	return true;
+}
 
 #ifdef _DEBUG
 /* ****************************************** */
@@ -1590,6 +1424,7 @@
 	IConsoleCmdRegister("clear",        ConClearBuffer);
 	IConsoleCmdRegister("patch",        ConPatch);
 	IConsoleCmdRegister("list_patches", ConListPatches);
+	IConsoleCmdRegister("gamelog",      ConGamelogPrint);
 
 	IConsoleAliasRegister("dir",      "ls");
 	IConsoleAliasRegister("del",      "rm %+");
@@ -1646,71 +1481,36 @@
 	IConsoleCmdHookAdd("unpause",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
 
 	/*** Networking variables ***/
-	IConsoleVarRegister("net_frame_freq",        &_network_frame_freq, ICONSOLE_VAR_BYTE, "The amount of frames before a command will be (visibly) executed. Default value: 1");
-	IConsoleVarHookAdd("net_frame_freq",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarRegister("net_sync_freq",         &_network_sync_freq,  ICONSOLE_VAR_UINT16, "The amount of frames to check if the game is still in sync. Default value: 100");
-	IConsoleVarHookAdd("net_sync_freq",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
-	IConsoleVarStringRegister("server_pw",       &_network_server_password, sizeof(_network_server_password), "Set the server password to protect your server. Use '*' to clear the password");
-	IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("server_pw",              ICONSOLE_HOOK_POST_ACTION, ConHookServerPW);
-	IConsoleAliasRegister("server_password",     "server_pw %+");
-	IConsoleVarStringRegister("rcon_pw",         &_network_rcon_password, sizeof(_network_rcon_password), "Set the rcon-password to change server behaviour. Use '*' to disable rcon");
-	IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("rcon_pw",                ICONSOLE_HOOK_POST_ACTION, ConHookRconPW);
-	IConsoleAliasRegister("rcon_password",       "rcon_pw %+");
 	IConsoleVarStringRegister("company_pw",      NULL, 0, "Set a password for your company, so no one without the correct password can join. Use '*' to clear the password");
 	IConsoleVarHookAdd("company_pw",             ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
 	IConsoleVarProcAdd("company_pw",             NetworkChangeCompanyPassword);
 	IConsoleAliasRegister("company_password",    "company_pw %+");
 
-	IConsoleVarStringRegister("name",            &_network_player_name, sizeof(_network_player_name), "Set your name for multiplayer");
-	IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_ACCESS, ConHookNeedNetwork);
-	IConsoleVarHookAdd("name",                   ICONSOLE_HOOK_POST_ACTION, ConProcPlayerName);
-	IConsoleVarStringRegister("server_name",     &_network_server_name, sizeof(_network_server_name), "Set the name of the server for multiplayer");
-	IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("server_name",            ICONSOLE_HOOK_POST_ACTION, ConHookServerName);
-
-	IConsoleVarRegister("server_port",           &_network_server_port, ICONSOLE_VAR_UINT32, "Set the server port. Changes take effect the next time you start a server");
-	IConsoleVarRegister("server_ip",             &_network_server_bind_ip, ICONSOLE_VAR_UINT32, "Set the IP the server binds to. Changes take effect the next time you start a server. Use 'all' to bind to any IP.");
-	IConsoleVarProcAdd("server_ip",              ConProcServerIP);
-	IConsoleAliasRegister("server_bind_ip",      "server_ip %+");
-	IConsoleAliasRegister("server_ip_bind",      "server_ip %+");
-	IConsoleAliasRegister("server_bind",         "server_ip %+");
-	IConsoleVarRegister("server_advertise",      &_network_advertise, ICONSOLE_VAR_BOOLEAN, "Set if the server will advertise to the master server and show up there");
-	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("server_advertise",       ICONSOLE_HOOK_POST_ACTION, ConHookServerAdvertise);
-
-	IConsoleVarRegister("max_clients",           &_network_game_info.clients_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of connected players during runtime. Default value: 10");
-	IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("max_clients",            ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxClientsCount);
-	IConsoleVarRegister("max_companies",         &_network_game_info.companies_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active companies during runtime. Default value: 8");
-	IConsoleVarHookAdd("max_companies",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("max_companies",          ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxCompaniesCount);
-	IConsoleVarRegister("max_spectators",        &_network_game_info.spectators_max, ICONSOLE_VAR_BYTE, "Control the maximum amount of active spectators during runtime. Default value: 9");
-	IConsoleVarHookAdd("max_spectators",         ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("max_spectators",         ICONSOLE_HOOK_POST_ACTION, ConHookValidateMaxSpectatorsCount);
-
-	IConsoleVarRegister("max_join_time",         &_network_max_join_time, ICONSOLE_VAR_UINT16, "Set the maximum amount of time (ticks) a client is allowed to join. Default value: 500");
-
-	IConsoleVarRegister("pause_on_join",         &_network_pause_on_join, ICONSOLE_VAR_BOOLEAN, "Set if the server should pause gameplay while a client is joining. This might help slow users");
-	IConsoleVarHookAdd("pause_on_join",          ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
-	IConsoleVarRegister("autoclean_companies",   &_network_autoclean_companies, ICONSOLE_VAR_BOOLEAN, "Automatically shut down inactive companies to free them up for other players. Customize with 'autoclean_(un)protected'");
-	IConsoleVarHookAdd("autoclean_companies",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarRegister("autoclean_protected",   &_network_autoclean_protected, ICONSOLE_VAR_BYTE, "Automatically remove the password from an inactive company after the given amount of months");
-	IConsoleVarHookAdd("autoclean_protected",    ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarRegister("autoclean_unprotected", &_network_autoclean_unprotected, ICONSOLE_VAR_BYTE, "Automatically shut down inactive companies after the given amount of months");
-	IConsoleVarHookAdd("autoclean_unprotected",  ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarRegister("restart_game_year",     &_network_restart_game_year, ICONSOLE_VAR_UINT16, "Auto-restart the server when Jan 1st of the set year is reached. Use '0' to disable this");
-	IConsoleVarHookAdd("restart_game_year",      ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
-	IConsoleVarRegister("min_players",           &_network_min_players, ICONSOLE_VAR_BYTE, "Automatically pause the game when the number of active players passes below the given amount");
-	IConsoleVarHookAdd("min_players",            ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-	IConsoleVarHookAdd("min_players",            ICONSOLE_HOOK_POST_ACTION, ConHookCheckMinPlayers);
-	IConsoleVarRegister("reload_cfg",            &_network_reload_cfg, ICONSOLE_VAR_BOOLEAN, "reload the entire config file between the end of this game, and starting the next new game - dedicated servers");
-	IConsoleVarHookAdd("reload_cfg",             ICONSOLE_HOOK_ACCESS, ConHookServerOnly);
-
+	IConsoleAliasRegister("net_frame_freq",        "patch frame_freq %+");
+	IConsoleAliasRegister("net_sync_freq",         "patch sync_freq %+");
+	IConsoleAliasRegister("server_pw",             "patch server_password %+");
+	IConsoleAliasRegister("server_password",       "patch server_password %+");
+	IConsoleAliasRegister("rcon_pw",               "patch rcon_password %+");
+	IConsoleAliasRegister("rcon_password",         "patch rcon_password %+");
+	IConsoleAliasRegister("name",                  "patch player_name %+");
+	IConsoleAliasRegister("server_name",           "patch server_name %+");
+	IConsoleAliasRegister("server_port",           "patch server_port %+");
+	IConsoleAliasRegister("server_ip",             "patch server_bind_ip %+");
+	IConsoleAliasRegister("server_bind_ip",        "patch server_bind_ip %+");
+	IConsoleAliasRegister("server_ip_bind",        "patch server_bind_ip %+");
+	IConsoleAliasRegister("server_bind",           "patch server_bind_ip %+");
+	IConsoleAliasRegister("server_advertise",      "patch server_advertise %+");
+	IConsoleAliasRegister("max_clients",           "patch max_clients %+");
+	IConsoleAliasRegister("max_companies",         "patch max_companies %+");
+	IConsoleAliasRegister("max_spectators",        "patch max_spectators %+");
+	IConsoleAliasRegister("max_join_time",         "patch max_join_time %+");
+	IConsoleAliasRegister("pause_on_join",         "patch pause_on_join %+");
+	IConsoleAliasRegister("autoclean_companies",   "patch autoclean_companies %+");
+	IConsoleAliasRegister("autoclean_protected",   "patch autoclean_protected %+");
+	IConsoleAliasRegister("autoclean_unprotected", "patch autoclean_unprotected %+");
+	IConsoleAliasRegister("restart_game_year",     "patch restart_game_year %+");
+	IConsoleAliasRegister("min_players",           "patch min_players %+");
+	IConsoleAliasRegister("reload_cfg",            "patch reload_cfg %+");
 #endif /* ENABLE_NETWORK */
 
 	// debugging stuff
--- a/src/console_func.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_func.h	Wed Jun 04 22:34:45 2008 +0000
@@ -19,6 +19,8 @@
 void IConsolePrint(ConsoleColour color_code, const char *string);
 void CDECL IConsolePrintF(ConsoleColour color_code, const char *s, ...);
 void IConsoleDebug(const char *dbg, const char *string);
+void IConsoleWarning(const char *string);
+void IConsoleError(const char *string);
 
 /* Parser */
 void IConsoleCmdExec(const char *cmdstr);
--- a/src/console_internal.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/console_internal.h	Wed Jun 04 22:34:45 2008 +0000
@@ -105,10 +105,6 @@
 void IConsoleClearBuffer();
 void IConsoleOpen();
 
-/* console output */
-void IConsoleWarning(const char *string);
-void IConsoleError(const char *string);
-
 /* Commands */
 void IConsoleCmdRegister(const char *name, IConsoleCmdProc *proc);
 void IConsoleAliasRegister(const char *name, const char *cmd);
--- a/src/date.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/date.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -7,8 +7,7 @@
 #include "variables.h"
 #include "settings_type.h"
 #include "network/network.h"
-#include "network/network_data.h"
-#include "network/network_server.h"
+#include "network/network_func.h"
 #include "currency.h"
 #include "window_func.h"
 #include "functions.h"
@@ -268,7 +267,9 @@
 		TownsMonthlyLoop();
 		IndustryMonthlyLoop();
 		StationMonthlyLoop();
+#ifdef ENABLE_NETWORK
 		if (_network_server) NetworkServerMonthlyLoop();
+#endif /* ENABLE_NETWORK */
 	}
 
 	/* check if we entered a new year? */
@@ -281,7 +282,9 @@
 	RoadVehiclesYearlyLoop();
 	AircraftYearlyLoop();
 	ShipsYearlyLoop();
+#ifdef ENABLE_NETWORK
 	if (_network_server) NetworkServerYearlyLoop();
+#endif /* ENABLE_NETWORK */
 
 	if (_cur_year == _settings_client.gui.semaphore_build_before) ResetSignalVariant();
 
--- a/src/debug.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/debug.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -30,6 +30,7 @@
 int _debug_freetype_level;
 int _debug_sl_level;
 int _debug_station_level;
+int _debug_gamelog_level;
 
 
 struct DebugLevel {
@@ -54,24 +55,17 @@
 	DEBUG_LEVEL(freetype),
 	DEBUG_LEVEL(sl),
 	DEBUG_LEVEL(station),
+	DEBUG_LEVEL(gamelog),
 	};
 #undef DEBUG_LEVEL
 
 #if !defined(NO_DEBUG_MESSAGES)
 
-void CDECL debug(const char *dbg, ...)
+void CDECL debug_print(const char *dbg, const char *buf)
 {
-	va_list va;
-	va_start(va, dbg);
-	const char *s;
-	char buf[1024];
-
-	s = va_arg(va, const char*);
-	vsnprintf(buf, lengthof(buf), s, va);
-	va_end(va);
 #if defined(ENABLE_NETWORK)
 	if (_debug_socket != INVALID_SOCKET) {
-		char buf2[lengthof(buf) + 32];
+		char buf2[1024 + 32];
 
 		snprintf(buf2, lengthof(buf2), "dbg: [%s] %s\n", dbg, buf);
 		send(_debug_socket, buf2, (int)strlen(buf2), 0);
@@ -89,6 +83,20 @@
 		IConsoleDebug(dbg, buf);
 	}
 }
+
+void CDECL debug(const char *dbg, ...)
+{
+	va_list va;
+	va_start(va, dbg);
+	const char *s;
+	char buf[1024];
+
+	s = va_arg(va, const char*);
+	vsnprintf(buf, lengthof(buf), s, va);
+	va_end(va);
+
+	debug_print(dbg, buf);
+}
 #endif /* NO_DEBUG_MESSAGES */
 
 void SetDebugString(const char *s)
--- a/src/debug.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/debug.h	Wed Jun 04 22:34:45 2008 +0000
@@ -47,8 +47,10 @@
 	extern int _debug_freetype_level;
 	extern int _debug_sl_level;
 	extern int _debug_station_level;
+	extern int _debug_gamelog_level;
 
 	void CDECL debug(const char *dbg, ...);
+	void CDECL debug_print(const char *dbg, const char *buf);
 #endif /* NO_DEBUG_MESSAGES */
 
 void SetDebugString(const char *s);
--- a/src/driver.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/driver.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -156,11 +156,7 @@
 	strecpy(buf, GetDriverTypeName(type), lastof(buf));
 	strecpy(buf + 5, name, lastof(buf));
 
-#if !defined(NDEBUG) || defined(WITH_ASSERT)
-	/* NDEBUG disables asserts and gives a warning: unused variable 'P' */
-	std::pair<Drivers::iterator, bool> P =
-#endif /* !NDEBUG */
-	GetDrivers().insert(Drivers::value_type(buf, this));
+	std::pair<Drivers::iterator, bool> P = GetDrivers().insert(Drivers::value_type(buf, this));
 	assert(P.second);
 }
 
--- a/src/economy.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/economy.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -14,7 +14,7 @@
 #include "town.h"
 #include "news_func.h"
 #include "network/network.h"
-#include "network/network_data.h"
+#include "network/network_func.h"
 #include "variables.h"
 #include "vehicle_gui.h"
 #include "ai/ai.h"
@@ -489,25 +489,7 @@
 
 	if (!_network_server) return;
 
-	/* The server has to handle all administrative issues, for example
-	* updating and notifying all clients of what has happened */
-	NetworkTCPSocketHandler *cs;
-	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
-
-	/* The server has just changed from player */
-	if (current_player == ci->client_playas) {
-		ci->client_playas = new_player;
-		NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
-	}
-
-	/* Find all clients that were in control of this company, and mark them as new_player */
-	FOR_ALL_CLIENTS(cs) {
-		ci = DEREF_CLIENT_INFO(cs);
-		if (current_player == ci->client_playas) {
-			ci->client_playas = new_player;
-			NetworkUpdateClientInfo(ci->client_index);
-		}
-	}
+	NetworkServerChangeOwner(current_player, new_player);
 #endif /* ENABLE_NETWORK */
 }
 
@@ -670,7 +652,7 @@
 	 * 12 -> months per year
 	 * This is only a good approxiamtion for small values
 	 */
-	Money inf = _economy.infl_amount * 54;
+	int32 inf = _economy.infl_amount * 54;
 
 	for (uint i = 0; i != NUM_PRICES; i++) {
 		AddSingleInflation((Money*)&_price + i, _price_frac + i, inf);
--- a/src/economy_type.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/economy_type.h	Wed Jun 04 22:34:45 2008 +0000
@@ -18,7 +18,7 @@
 	int fluct;
 	byte interest_rate;     ///< Interest
 	byte infl_amount;       ///< inflation amount
-	byte infl_amount_pr;    ///< "floating" portion of inflation
+	byte infl_amount_pr;    ///< inflation rate for payment rates
 };
 
 struct Subsidy {
--- a/src/effectvehicle.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/effectvehicle.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,6 @@
 #include "industry_map.h"
 #include "station_map.h"
 #include "water_map.h"
-#include "network/network.h"
 #include "yapf/yapf.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_engine.h"
--- a/src/engine.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/engine.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -29,7 +29,7 @@
 #include "ai/ai.h"
 #include "core/alloc_func.hpp"
 #include "vehicle_func.h"
-#include "map"
+#include <map>
 
 #include "table/strings.h"
 #include "table/engines.h"
--- a/src/fios.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/fios.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -10,7 +10,6 @@
 #include "heightmap.h"
 #include "fios.h"
 #include "fileio.h"
-#include "core/alloc_func.hpp"
 #include "functions.h"
 #include "string_func.h"
 #include <sys/types.h>
@@ -30,12 +29,9 @@
 #include "table/strings.h"
 
 /* Variables to display file lists */
-int _fios_num;
-
+SmallVector<FiosItem, 32> _fios_items;
 static char *_fios_path;
-static FiosItem *_fios_items;
 SmallFiosItem _file_to_saveload;
-static int _fios_count, _fios_alloc;
 
 /* OS-specific functions are taken from their respective files (win32/unix/os2 .c) */
 extern bool FiosIsRoot(const char *path);
@@ -48,19 +44,6 @@
 extern void GetOldSaveGameName(char *title, const char *path, const char *file);
 
 /**
- * Allocate a new FiosItem.
- * @return A pointer to the newly allocated FiosItem.
- */
-FiosItem *FiosAlloc()
-{
-	if (_fios_count == _fios_alloc) {
-		_fios_alloc += 256;
-		_fios_items = ReallocT(_fios_items, _fios_alloc);
-	}
-	return &_fios_items[_fios_count++];
-}
-
-/**
  * Compare two FiosItem's. Used with qsort when sorting the file list.
  * @param a A pointer to the first FiosItem to compare.
  * @param b A pointer to the second FiosItem to compare.
@@ -82,15 +65,12 @@
 	return r;
 }
 
-/**
- * Free the list of savegames
- */
+/** Clear the list */
 void FiosFreeSavegameList()
 {
-	free(_fios_items);
-	_fios_items = NULL;
-	_fios_alloc = _fios_count = 0;
-}
+	_fios_items.Clear();
+	_fios_items.Compact();
+};
 
 /**
  * Get descriptive texts. Returns the path and free space
@@ -229,9 +209,11 @@
 	int sort_start;
 	char d_name[sizeof(fios->name)];
 
+	_fios_items.Clear();
+
 	/* A parent directory link exists if we are not in the root directory */
 	if (!FiosIsRoot(_fios_path) && mode != SLD_NEW_GAME) {
-		fios = FiosAlloc();
+		fios = _fios_items.Append();
 		fios->type = FIOS_TYPE_PARENT;
 		fios->mtime = 0;
 		ttd_strlcpy(fios->name, "..", lengthof(fios->name));
@@ -247,7 +229,7 @@
 			if (FiosIsValidFile(_fios_path, dirent, &sb) && (sb.st_mode & S_IFDIR) &&
 					(!FiosIsHiddenFile(dirent) || strncasecmp(d_name, PERSONAL_DIR, strlen(d_name)) == 0) &&
 					strcmp(d_name, ".") != 0 && strcmp(d_name, "..") != 0) {
-				fios = FiosAlloc();
+				fios = _fios_items.Append();
 				fios->type = FIOS_TYPE_DIR;
 				fios->mtime = 0;
 				ttd_strlcpy(fios->name, d_name, lengthof(fios->name));
@@ -262,12 +244,12 @@
 	{
 		byte order = _savegame_sort_order;
 		_savegame_sort_order = SORT_BY_NAME | SORT_ASCENDING;
-		qsort(_fios_items, _fios_count, sizeof(FiosItem), compare_FiosItems);
+		qsort(_fios_items.Begin(), _fios_items.Length(), sizeof(FiosItem), compare_FiosItems);
 		_savegame_sort_order = order;
 	}
 
 	/* This is where to start sorting for the filenames */
-	sort_start = _fios_count;
+	sort_start = _fios_items.Length();
 
 	/* Show files */
 	dir = ttd_opendir(_fios_path);
@@ -285,7 +267,7 @@
 
 			FiosType type = callback_proc(mode, d_name, t, fios_title);
 			if (type != FIOS_TYPE_INVALID) {
-				fios = FiosAlloc();
+				fios = _fios_items.Append();
 				fios->mtime = sb.st_mtime;
 				fios->type = type;
 				ttd_strlcpy(fios->name, d_name, lengthof(fios->name));
@@ -300,13 +282,14 @@
 		closedir(dir);
 	}
 
-	qsort(_fios_items + sort_start, _fios_count - sort_start, sizeof(FiosItem), compare_FiosItems);
+	qsort(_fios_items.Get(sort_start), _fios_items.Length() - sort_start, sizeof(FiosItem), compare_FiosItems);
 
 	/* Show drives */
 	if (mode != SLD_NEW_GAME) FiosGetDrives();
 
-	_fios_num = _fios_count;
-	return _fios_items;
+	_fios_items.Compact();
+
+	return _fios_items.Begin();
 }
 
 /**
@@ -345,7 +328,7 @@
  * @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
  * @see FiosGetFileList
  */
-FiosItem *FiosGetSavegameList(SaveLoadDialogMode mode)
+void FiosGetSavegameList(SaveLoadDialogMode mode)
 {
 	static char *fios_save_path = NULL;
 
@@ -356,7 +339,7 @@
 
 	_fios_path = fios_save_path;
 
-	return FiosGetFileList(mode, &FiosGetSavegameListCallback);
+	FiosGetFileList(mode, &FiosGetSavegameListCallback);
 }
 
 /**
@@ -393,7 +376,7 @@
  * @return A pointer to an array of FiosItem representing all the files to be shown in the save/load dialog.
  * @see FiosGetFileList
  */
-FiosItem *FiosGetScenarioList(SaveLoadDialogMode mode)
+void FiosGetScenarioList(SaveLoadDialogMode mode)
 {
 	static char *fios_scn_path = NULL;
 
@@ -405,7 +388,7 @@
 
 	_fios_path = fios_scn_path;
 
-	return FiosGetFileList(mode, &FiosGetScenarioListCallback);
+	FiosGetFileList(mode, &FiosGetScenarioListCallback);
 }
 
 static FiosType FiosGetHeightmapListCallback(SaveLoadDialogMode mode, const char *file, const char *ext, char *title)
@@ -425,7 +408,7 @@
 }
 
 /* Get a list of Heightmaps */
-FiosItem *FiosGetHeightmapList(SaveLoadDialogMode mode)
+void FiosGetHeightmapList(SaveLoadDialogMode mode)
 {
 	static char *fios_hmap_path = NULL;
 
@@ -436,5 +419,5 @@
 
 	_fios_path = fios_hmap_path;
 
-	return FiosGetFileList(mode, &FiosGetHeightmapListCallback);
+	FiosGetFileList(mode, &FiosGetHeightmapListCallback);
 }
--- a/src/fios.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/fios.h	Wed Jun 04 22:34:45 2008 +0000
@@ -6,6 +6,7 @@
 #define FIOS_H
 
 #include "strings_type.h"
+#include "misc/smallvec.h"
 
 enum {
 	/**
@@ -80,8 +81,7 @@
 };
 
 /* Variables to display file lists */
-extern FiosItem *_fios_list; ///< defined in misc_gui.cpp
-extern int _fios_num;        ///< defined in fios.cpp, read_only version of _fios_count
+extern SmallVector<FiosItem, 32> _fios_items; ///< defined in fios.cpp
 extern SmallFiosItem _file_to_saveload;
 extern SaveLoadDialogMode _saveload_mode;   ///< defined in misc_gui.cpp
 extern byte _savegame_sort_order;
@@ -90,11 +90,11 @@
 void ShowSaveLoadDialog(SaveLoadDialogMode mode);
 
 /* Get a list of savegames */
-FiosItem *FiosGetSavegameList(SaveLoadDialogMode mode);
+void FiosGetSavegameList(SaveLoadDialogMode mode);
 /* Get a list of scenarios */
-FiosItem *FiosGetScenarioList(SaveLoadDialogMode mode);
+void FiosGetScenarioList(SaveLoadDialogMode mode);
 /* Get a list of Heightmaps */
-FiosItem *FiosGetHeightmapList(SaveLoadDialogMode mode);
+void FiosGetHeightmapList(SaveLoadDialogMode mode);
 /* Free the list of savegames */
 void FiosFreeSavegameList();
 /* Browse to. Returns a filename w/path if we reached a file. */
@@ -105,8 +105,6 @@
 bool FiosDelete(const char *name);
 /* Make a filename from a name */
 void FiosMakeSavegameName(char *buf, const char *name, size_t size);
-/* Allocate a new FiosItem */
-FiosItem *FiosAlloc();
 
 int CDECL compare_FiosItems(const void *a, const void *b);
 
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gamelog.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,801 @@
+/* $Id$ */
+
+/** @file gamelog.cpp Definition of functions used for logging of important changes in the game */
+
+#include "stdafx.h"
+#include "openttd.h"
+#include "saveload.h"
+#include "core/alloc_func.hpp"
+#include "core/bitmath_func.hpp"
+#include "core/math_func.hpp"
+#include "network/core/config.h"
+#include "variables.h"
+#include "string_func.h"
+#include "settings_type.h"
+#include "newgrf_config.h"
+#include <string.h>
+#include <stdarg.h>
+#include "gamelog.h"
+#include "console_func.h"
+#include "debug.h"
+#include "rev.h"
+
+extern const uint16 SAVEGAME_VERSION;  ///< current savegame version
+
+extern SavegameType _savegame_type; ///< type of savegame we are loading
+
+extern uint32 _ttdp_version;     ///< version of TTDP savegame (if applicable)
+extern uint16 _sl_version;       ///< the major savegame version identifier
+extern byte   _sl_minor_version; ///< the minor savegame version, DO NOT USE!
+
+/** Type of logged change */
+enum GamelogChangeType {
+	GLCT_MODE,        ///< Scenario editor x Game, different landscape
+	GLCT_REVISION,    ///< Changed game revision string
+	GLCT_OLDVER,      ///< Loaded from savegame without logged data
+	GLCT_PATCH,       ///< Non-networksafe patch value changed
+	GLCT_GRFADD,      ///< Removed GRF
+	GLCT_GRFREM,      ///< Added GRF
+	GLCT_GRFCOMPAT,   ///< Loading compatible GRF
+	GLCT_GRFPARAM,    ///< GRF parameter changed
+	GLCT_GRFMOVE,     ///< GRF order changed
+	GLCT_END,         ///< So we know how many GLCTs are there
+	GLCT_NONE = 0xFF, ///< In savegames, end of list
+};
+
+
+/** Contains information about one logged change */
+struct LoggedChange {
+	GamelogChangeType ct; ///< Type of change logged in this struct
+	union {
+		struct {
+			byte mode;       ///< new game mode - Editor x Game
+			byte landscape;  ///< landscape (temperate, arctic, ...)
+		} mode;
+		struct {
+			char text[NETWORK_REVISION_LENGTH]; ///< revision string, _openttd_revision
+			uint32 newgrf;   ///< _openttd_newgrf_version
+			uint16 slver;    ///< _sl_version
+			byte modified;   ///< _openttd_revision_modified
+		} revision;
+		struct {
+			uint32 type;     ///< type of savegame, @see SavegameType
+			uint32 version;  ///< major and minor version OR ttdp version
+		} oldver;
+		GRFIdentifier grfadd;    ///< ID and md5sum of added GRF
+		struct {
+			uint32 grfid;    ///< ID of removed GRF
+		} grfrem;
+		GRFIdentifier grfcompat; ///< ID and new md5sum of changed GRF
+		struct {
+			uint32 grfid;    ///< ID of GRF with changed parameters
+		} grfparam;
+		struct {
+			uint32 grfid;    ///< ID of moved GRF
+			int32 offset;    ///< offset, positive = move down
+		} grfmove;
+		struct {
+			char *name;      ///< name of the patch
+			int32 oldval;    ///< old value
+			int32 newval;    ///< new value
+		} patch;
+	};
+};
+
+
+/** Contains information about one logged action that caused at least one logged change */
+struct LoggedAction {
+	LoggedChange *change; ///< First logged change in this action
+	uint32 changes;       ///< Number of changes in this action
+	GamelogActionType at; ///< Type of action
+	uint16 tick;          ///< Tick when it happened
+};
+
+static GamelogActionType _gamelog_action_type = GLAT_NONE; ///< action to record if anything changes
+
+static LoggedAction *_gamelog_action = NULL; ///< first logged action
+static uint _gamelog_actions         = 0;    ///< number of actions
+static LoggedAction *_current_action = NULL; ///< current action we are logging, NULL when there is no action active
+
+
+/** Stores information about new action, but doesn't allocate it
+ * Action is allocated only when there is at least one change
+ * @param at type of action
+ */
+void GamelogStartAction(GamelogActionType at)
+{
+	assert(_gamelog_action_type == GLAT_NONE); // do not allow starting new action without stopping the previous first
+	_gamelog_action_type = at;
+}
+
+/** Stops logging of any changes
+ */
+void GamelogStopAction()
+{
+	assert(_gamelog_action_type != GLAT_NONE); // nobody should try to stop if there is no action in progress
+
+	_current_action = NULL;
+	_gamelog_action_type = GLAT_NONE;
+
+	if (_debug_gamelog_level > 4) GamelogPrintDebug();
+}
+
+/** Resets and frees all memory allocated - used before loading or starting a new game
+ */
+void GamelogReset()
+{
+	assert(_gamelog_action_type == GLAT_NONE);
+
+	for (uint i = 0; i < _gamelog_actions; i++) {
+		const LoggedAction *la = &_gamelog_action[i];
+		for (uint j = 0; j < la->changes; j++) {
+			const LoggedChange *lc = &la->change[j];
+			if (lc->ct == GLCT_PATCH) free(lc->patch.name);
+		}
+		free(la->change);
+	}
+
+	free(_gamelog_action);
+
+	_gamelog_action  = NULL;
+	_gamelog_actions = 0;
+	_current_action  = NULL;
+}
+
+enum {
+	GAMELOG_BUF_LEN = 1024 ///< length of buffer for one line of text
+};
+
+static int _dbgofs = 0; ///< offset in current output buffer
+
+static void AddDebugText(char *buf, const char *s, ...)
+{
+	if (GAMELOG_BUF_LEN <= _dbgofs) return;
+
+	va_list va;
+
+	va_start(va, s);
+	_dbgofs += vsnprintf(buf + _dbgofs, GAMELOG_BUF_LEN - _dbgofs, s, va);
+	va_end(va);
+}
+
+
+/** Prints GRF filename if found
+ * @param grfid GRF which filename to print
+ */
+static void PrintGrfFilename(char *buf, uint grfid)
+{
+	const GRFConfig *gc = FindGRFConfig(grfid);
+
+	if (gc == NULL) return;
+
+	AddDebugText(buf, ", filename: %s", gc->filename);
+}
+
+/** Prints GRF ID, checksum and filename if found
+ * @param grfid GRF ID
+ * @param md5sum array of md5sum to print
+ */
+static void PrintGrfInfo(char *buf, uint grfid, const uint8 *md5sum)
+{
+	char txt[40];
+
+	md5sumToString(txt, lastof(txt), md5sum);
+
+	AddDebugText(buf, "GRF ID %08X, checksum %s", BSWAP32(grfid), txt);
+
+	PrintGrfFilename(buf, grfid);
+
+	return;
+}
+
+
+/** Text messages for various logged actions */
+static const char *la_text[] = {
+	"new game started",
+	"game loaded",
+	"GRF config changed",
+	"cheat was used",
+	"patch settings changed"
+};
+
+assert_compile(lengthof(la_text) == GLAT_END);
+
+
+/** Prints active gamelog */
+void GamelogPrint(GamelogPrintProc *proc)
+{
+	char buf[GAMELOG_BUF_LEN];
+
+	proc("---- gamelog start ----");
+
+	const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+
+	for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+		assert((uint)la->at < GLAT_END);
+
+		snprintf(buf, GAMELOG_BUF_LEN, "Tick %u: %s", (uint)la->tick, la_text[(uint)la->at]);
+		proc(buf);
+
+		const LoggedChange *lcend = &la->change[la->changes];
+
+		for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+			_dbgofs = 0;
+			AddDebugText(buf, "     ");
+
+			switch (lc->ct) {
+				default: NOT_REACHED();
+				case GLCT_MODE:
+					AddDebugText(buf, "New game mode: %u landscape: %u",
+						(uint)lc->mode.mode, (uint)lc->mode.landscape);
+					break;
+
+				case GLCT_REVISION:
+					AddDebugText(buf, "Revision text changed to %s, savegame version %u, ",
+						lc->revision.text, lc->revision.slver);
+
+					switch (lc->revision.modified) {
+						case 0: AddDebugText(buf, "not "); break;
+						case 1: AddDebugText(buf, "maybe "); break;
+						default: break;
+					}
+
+					AddDebugText(buf, "modified, _openttd_newgrf_version = 0x%08x", lc->revision.newgrf);
+					break;
+
+				case GLCT_OLDVER:
+					AddDebugText(buf, "Conversion from ");
+					switch (lc->oldver.type) {
+						default: NOT_REACHED();
+						case SGT_OTTD:
+							AddDebugText(buf, "OTTD savegame without gamelog: version %u, %u",
+								GB(lc->oldver.version, 8, 16), GB(lc->oldver.version, 0, 8));
+							break;
+
+						case SGT_TTD:
+							AddDebugText(buf, "TTD savegame");
+							break;
+
+						case SGT_TTDP1:
+						case SGT_TTDP2:
+							AddDebugText(buf, "TTDP savegame, %s format",
+								lc->oldver.type == SGT_TTDP1 ? "old" : "new");
+							if (lc->oldver.version != 0) {
+								AddDebugText(buf, ", TTDP version %u.%u.%u.%u",
+									GB(lc->oldver.version, 24, 8), GB(lc->oldver.version, 20, 4),
+									GB(lc->oldver.version, 16, 4), GB(lc->oldver.version, 0, 16));
+							}
+							break;
+					}
+					break;
+
+				case GLCT_PATCH:
+					AddDebugText(buf, "Patch setting changed: %s : %d -> %d", lc->patch.name, lc->patch.oldval, lc->patch.newval);
+					break;
+
+				case GLCT_GRFADD:
+					AddDebugText(buf, "Added NewGRF: ");
+					PrintGrfInfo(buf, lc->grfadd.grfid, lc->grfadd.md5sum);
+					break;
+
+				case GLCT_GRFREM:
+					AddDebugText(buf, "Removed NewGRF: %08X", BSWAP32(lc->grfrem.grfid));
+					PrintGrfFilename(buf, lc->grfrem.grfid);
+					break;
+
+				case GLCT_GRFCOMPAT:
+					AddDebugText(buf, "Compatible NewGRF loaded: ");
+					PrintGrfInfo(buf, lc->grfcompat.grfid, lc->grfcompat.md5sum);
+					break;
+
+				case GLCT_GRFPARAM:
+					AddDebugText(buf, "GRF parameter changed: %08X", BSWAP32(lc->grfparam.grfid));
+					PrintGrfFilename(buf, lc->grfparam.grfid);
+					break;
+
+				case GLCT_GRFMOVE:
+					AddDebugText(buf, "GRF order changed: %08X moved %d places %s",
+						BSWAP32(lc->grfmove.grfid), abs(lc->grfmove.offset), lc->grfmove.offset >= 0 ? "down" : "up" );
+					PrintGrfFilename(buf, lc->grfmove.grfid);
+					break;
+			}
+
+			proc(buf);
+		}
+	}
+
+	proc("---- gamelog end ----");
+}
+
+
+static void GamelogPrintConsoleProc(const char *s)
+{
+	IConsolePrint(CC_WARNING, s);
+}
+
+void GamelogPrintConsole()
+{
+	GamelogPrint(&GamelogPrintConsoleProc);
+}
+
+
+static void GamelogPrintDebugProc(const char *s)
+{
+	debug_print("gamelog", s);
+}
+
+void GamelogPrintDebug()
+{
+	GamelogPrint(&GamelogPrintDebugProc);
+}
+
+
+/** Allocates new LoggedChange and new LoggedAction if needed.
+ * If there is no action active, NULL is returned.
+ * @param ct type of change
+ * @return new LoggedChange, or NULL if there is no action active
+ */
+static LoggedChange *GamelogChange(GamelogChangeType ct)
+{
+	if (_current_action == NULL) {
+		if (_gamelog_action_type == GLAT_NONE) return NULL;
+
+		_gamelog_action  = ReallocT(_gamelog_action, _gamelog_actions + 1);
+		_current_action  = &_gamelog_action[_gamelog_actions++];
+
+		_current_action->at      = _gamelog_action_type;
+		_current_action->tick    = _tick_counter;
+		_current_action->change  = NULL;
+		_current_action->changes = 0;
+	}
+
+	_current_action->change = ReallocT(_current_action->change, _current_action->changes + 1);
+
+	LoggedChange *lc = &_current_action->change[_current_action->changes++];
+	lc->ct = ct;
+
+	return lc;
+}
+
+
+/** Logs a change in game revision
+ * @param revision new revision string
+ */
+void GamelogRevision()
+{
+	assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
+
+	LoggedChange *lc = GamelogChange(GLCT_REVISION);
+	if (lc == NULL) return;
+
+	strncpy(lc->revision.text, _openttd_revision, lengthof(lc->revision.text));
+	lc->revision.slver = SAVEGAME_VERSION;
+	lc->revision.modified = _openttd_revision_modified;
+	lc->revision.newgrf = _openttd_newgrf_version;
+}
+
+/** Logs a change in game mode (scenario editor or game)
+ */
+void GamelogMode()
+{
+	assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_CHEAT);
+
+	LoggedChange *lc = GamelogChange(GLCT_MODE);
+	if (lc == NULL) return;
+
+	lc->mode.mode      = _game_mode;
+	lc->mode.landscape = _settings_game.game_creation.landscape;
+}
+
+/** Logs loading from savegame without gamelog
+ */
+void GamelogOldver()
+{
+	assert(_gamelog_action_type == GLAT_LOAD);
+
+	LoggedChange *lc = GamelogChange(GLCT_OLDVER);
+	if (lc == NULL) return;
+
+	lc->oldver.type = _savegame_type;
+	lc->oldver.version = (_savegame_type == SGT_OTTD ? ((uint32)_sl_version << 8 | _sl_minor_version) : _ttdp_version);
+}
+
+/** Logs change in game patches. Only non-networksafe patches are logged
+ * @param name patch name
+ * @param oldval old patch value
+ * @param newval new patch value
+ */
+void GamelogPatch(const char *name, int32 oldval, int32 newval)
+{
+	assert(_gamelog_action_type == GLAT_PATCH);
+
+	LoggedChange *lc = GamelogChange(GLCT_PATCH);
+	if (lc == NULL) return;
+
+	lc->patch.name = strdup(name);
+	lc->patch.oldval = oldval;
+	lc->patch.newval = newval;
+}
+
+
+/** Finds out if current revision is different than last revision stored in the savegame.
+ * Appends GLCT_REVISION when the revision string changed
+ */
+void GamelogTestRevision()
+{
+	const LoggedChange *rev = NULL;
+
+	const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+	for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+		const LoggedChange *lcend = &la->change[la->changes];
+		for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+			if (lc->ct == GLCT_REVISION) rev = lc;
+		}
+	}
+
+	if (rev == NULL || strcmp(rev->revision.text, _openttd_revision) != 0 ||
+			rev->revision.modified != _openttd_revision_modified ||
+			rev->revision.newgrf != _openttd_newgrf_version) {
+		GamelogRevision();
+	}
+}
+
+/** Finds last stored game mode or landscape.
+ * Any change is logged
+ */
+void GamelogTestMode()
+{
+	const LoggedChange *mode = NULL;
+
+	const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+	for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+		const LoggedChange *lcend = &la->change[la->changes];
+		for (const LoggedChange *lc = la->change; lc != lcend; lc++) {
+			if (lc->ct == GLCT_MODE) mode = lc;
+		}
+	}
+
+	if (mode == NULL || mode->mode.mode != _game_mode || mode->mode.landscape != _settings_game.game_creation.landscape) GamelogMode();
+}
+
+
+/** Decides if GRF should be logged
+ * @param g grf to determine
+ * @return true iff GRF is not static and is loaded
+ */
+static inline bool IsLoggableGrfConfig(const GRFConfig *g)
+{
+	return !HasBit(g->flags, GCF_STATIC) && g->status != GCS_NOT_FOUND;
+}
+
+/** Logs removal of a GRF
+ * @param grfid ID of removed GRF
+ */
+void GamelogGRFRemove(uint32 grfid)
+{
+	assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_GRF);
+
+	LoggedChange *lc = GamelogChange(GLCT_GRFREM);
+	if (lc == NULL) return;
+
+	lc->grfrem.grfid = grfid;
+}
+
+/** Logs adding of a GRF
+ * @param newg added GRF
+ */
+void GamelogGRFAdd(const GRFConfig *newg)
+{
+	assert(_gamelog_action_type == GLAT_LOAD || _gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_GRF);
+
+	if (!IsLoggableGrfConfig(newg)) return;
+
+	LoggedChange *lc = GamelogChange(GLCT_GRFADD);
+	if (lc == NULL) return;
+
+	memcpy(&lc->grfadd, newg, sizeof(GRFIdentifier));
+}
+
+/** Logs loading compatible GRF
+ * (the same ID, but different MD5 hash)
+ * @param newg new (updated) GRF
+ */
+void GamelogGRFCompatible(const GRFIdentifier *newg)
+{
+	assert(_gamelog_action_type == GLAT_LOAD);
+
+	LoggedChange *lc = GamelogChange(GLCT_GRFCOMPAT);
+	if (lc == NULL) return;
+
+	memcpy(&lc->grfcompat, newg, sizeof(GRFIdentifier));
+}
+
+/** Logs changing GRF order
+ * @param grfid GRF that is moved
+ * @param offset how far it is moved, positive = moved down
+ */
+static void GamelogGRFMove(uint32 grfid, int32 offset)
+{
+	assert(_gamelog_action_type == GLAT_GRF);
+
+	LoggedChange *lc = GamelogChange(GLCT_GRFMOVE);
+	if (lc == NULL) return;
+
+	lc->grfmove.grfid  = grfid;
+	lc->grfmove.offset = offset;
+}
+
+/** Logs change in GRF parameters.
+ * Details about parameters changed are not stored
+ * @param grfid ID of GRF to store
+ */
+static void GamelogGRFParameters(uint32 grfid)
+{
+	assert(_gamelog_action_type == GLAT_GRF);
+
+	LoggedChange *lc = GamelogChange(GLCT_GRFPARAM);
+	if (lc == NULL) return;
+
+	lc->grfparam.grfid = grfid;
+}
+
+/** Logs adding of list of GRFs.
+ * Useful when old savegame is loaded or when new game is started
+ * @param newg head of GRF linked list
+ */
+void GamelogGRFAddList(const GRFConfig *newg)
+{
+	assert(_gamelog_action_type == GLAT_START || _gamelog_action_type == GLAT_LOAD);
+
+	for (; newg != NULL; newg = newg->next) {
+		GamelogGRFAdd(newg);
+	}
+}
+
+/** List of GRFs using array of pointers instead of linked list */
+struct GRFList {
+	uint n;
+	const GRFConfig *grf[VARARRAY_SIZE];
+};
+
+/** Generates GRFList
+ * @param grfc head of GRF linked list
+ */
+static GRFList *GenerateGRFList(const GRFConfig *grfc)
+{
+	uint n = 0;
+	for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
+		if (IsLoggableGrfConfig(g)) n++;
+	}
+
+	GRFList *list = (GRFList*)MallocT<byte>(sizeof(GRFList) + n * sizeof(GRFConfig*));
+
+	list->n = 0;
+	for (const GRFConfig *g = grfc; g != NULL; g = g->next) {
+		if (IsLoggableGrfConfig(g)) list->grf[list->n++] = g;
+	}
+
+	return list;
+}
+
+/** Compares two NewGRF lists and logs any change
+ * @param oldc original GRF list
+ * @param newc new GRF list
+ */
+void GamelogGRFUpdate(const GRFConfig *oldc, const GRFConfig *newc)
+{
+	GRFList *ol = GenerateGRFList(oldc);
+	GRFList *nl = GenerateGRFList(newc);
+
+	uint o = 0, n = 0;
+
+	while (o < ol->n && n < nl->n) {
+		const GRFConfig *og = ol->grf[o];
+		const GRFConfig *ng = nl->grf[n];
+
+		if (og->grfid != ng->grfid) {
+			uint oi, ni;
+			for (oi = 0; oi < ol->n; oi++) {
+				if (ol->grf[oi]->grfid == nl->grf[n]->grfid) break;
+			}
+			if (oi < o) {
+				/* GRF was moved, this change has been logged already */
+				n++;
+				continue;
+			}
+			if (oi == ol->n) {
+				/* GRF couldn't be found in the OLD list, GRF was ADDED */
+				GamelogGRFAdd(nl->grf[n++]);
+				continue;
+			}
+			for (ni = 0; ni < nl->n; ni++) {
+				if (nl->grf[ni]->grfid == ol->grf[o]->grfid) break;
+			}
+			if (ni < n) {
+				/* GRF was moved, this change has been logged already */
+				o++;
+				continue;
+			}
+			if (ni == nl->n) {
+				/* GRF couldn't be found in the NEW list, GRF was REMOVED */
+				GamelogGRFRemove(ol->grf[o++]->grfid);
+				continue;
+			}
+
+			/* o < oi < ol->n
+			 * n < ni < nl->n */
+			assert(ni > n && ni < nl->n);
+			assert(oi > o && oi < ol->n);
+
+			ni -= n; // number of GRFs it was moved downwards
+			oi -= o; // number of GRFs it was moved upwards
+
+			if (ni >= oi) { // prefer the one that is moved further
+				/* GRF was moved down */
+				GamelogGRFMove(ol->grf[o++]->grfid, ni);
+			} else {
+				GamelogGRFMove(nl->grf[n++]->grfid, -(int)oi);
+			}
+		} else {
+			if (memcmp(og->md5sum, ng->md5sum, sizeof(og->md5sum)) != 0) {
+				/* md5sum changed, probably loading 'compatible' GRF */
+				GamelogGRFCompatible(nl->grf[n]);
+			}
+
+			if (og->num_params != ng->num_params || memcmp(og->param, ng->param, og->num_params * sizeof(og->param[0])) != 0) {
+				GamelogGRFParameters(ol->grf[o]->grfid);
+			}
+
+			o++;
+			n++;
+		}
+	}
+
+	while (o < ol->n) GamelogGRFRemove(ol->grf[o++]->grfid); // remaining GRFs were removed ...
+	while (n < nl->n) GamelogGRFAdd   (nl->grf[n++]);    // ... or added
+
+	free(ol);
+	free(nl);
+}
+
+
+static const SaveLoad _glog_action_desc[] = {
+	SLE_VAR(LoggedAction, tick,              SLE_UINT16),
+	SLE_END()
+};
+
+static const SaveLoad _glog_mode_desc[] = {
+	SLE_VAR(LoggedChange, mode.mode,         SLE_UINT8),
+	SLE_VAR(LoggedChange, mode.landscape,    SLE_UINT8),
+	SLE_END()
+};
+
+static const SaveLoad _glog_revision_desc[] = {
+	SLE_ARR(LoggedChange, revision.text,     SLE_UINT8,  NETWORK_REVISION_LENGTH),
+	SLE_VAR(LoggedChange, revision.newgrf,   SLE_UINT32),
+	SLE_VAR(LoggedChange, revision.slver,    SLE_UINT16),
+	SLE_VAR(LoggedChange, revision.modified, SLE_UINT8),
+	SLE_END()
+};
+
+static const SaveLoad _glog_oldver_desc[] = {
+	SLE_VAR(LoggedChange, oldver.type,       SLE_UINT32),
+	SLE_VAR(LoggedChange, oldver.version,    SLE_UINT32),
+	SLE_END()
+};
+
+static const SaveLoad _glog_patch_desc[] = {
+	SLE_STR(LoggedChange, patch.name,        SLE_STR,    128),
+	SLE_VAR(LoggedChange, patch.oldval,      SLE_INT32),
+	SLE_VAR(LoggedChange, patch.newval,      SLE_INT32),
+	SLE_END()
+};
+
+static const SaveLoad _glog_grfadd_desc[] = {
+	SLE_VAR(LoggedChange, grfadd.grfid,      SLE_UINT32    ),
+	SLE_ARR(LoggedChange, grfadd.md5sum,     SLE_UINT8,  16),
+	SLE_END()
+};
+
+static const SaveLoad _glog_grfrem_desc[] = {
+	SLE_VAR(LoggedChange, grfrem.grfid,      SLE_UINT32),
+	SLE_END()
+};
+
+static const SaveLoad _glog_grfcompat_desc[] = {
+	SLE_VAR(LoggedChange, grfcompat.grfid,   SLE_UINT32    ),
+	SLE_ARR(LoggedChange, grfcompat.md5sum,  SLE_UINT8,  16),
+	SLE_END()
+};
+
+static const SaveLoad _glog_grfparam_desc[] = {
+	SLE_VAR(LoggedChange, grfparam.grfid,    SLE_UINT32),
+	SLE_END()
+};
+
+static const SaveLoad _glog_grfmove_desc[] = {
+	SLE_VAR(LoggedChange, grfmove.grfid,    SLE_UINT32),
+	SLE_VAR(LoggedChange, grfmove.offset,   SLE_INT32),
+	SLE_END()
+};
+
+static const SaveLoad *_glog_desc[] = {
+	_glog_mode_desc,
+	_glog_revision_desc,
+	_glog_oldver_desc,
+	_glog_patch_desc,
+	_glog_grfadd_desc,
+	_glog_grfrem_desc,
+	_glog_grfcompat_desc,
+	_glog_grfparam_desc,
+	_glog_grfmove_desc
+};
+
+assert_compile(lengthof(_glog_desc) == GLCT_END);
+
+static void Load_GLOG()
+{
+	assert(_gamelog_action == NULL);
+	assert(_gamelog_actions == 0);
+
+	GamelogActionType at;
+	while ((at = (GamelogActionType)SlReadByte()) != GLAT_NONE) {
+		_gamelog_action = ReallocT(_gamelog_action, _gamelog_actions + 1);
+		LoggedAction *la = &_gamelog_action[_gamelog_actions++];
+
+		la->at = at;
+
+		SlObject(la, _glog_action_desc); // has to be saved after 'DATE'!
+		la->change = NULL;
+		la->changes = 0;
+
+		GamelogChangeType ct;
+		while ((ct = (GamelogChangeType)SlReadByte()) != GLCT_NONE) {
+			la->change = ReallocT(la->change, la->changes + 1);
+
+			LoggedChange *lc = &la->change[la->changes++];
+			lc->ct = ct;
+
+			assert((uint)ct < GLCT_END);
+
+			SlObject(lc, _glog_desc[ct]);
+		}
+	}
+}
+
+static void Save_GLOG()
+{
+	const LoggedAction *laend = &_gamelog_action[_gamelog_actions];
+	size_t length = 0;
+
+	for (const LoggedAction *la = _gamelog_action; la != laend; la++) {
+		const LoggedChange *lcend = &la->change[la->changes];
+		for (LoggedChange *lc = la->change; lc != lcend; lc++) {
+			assert((uint)lc->ct < lengthof(_glog_desc));
+			length += SlCalcObjLength(lc, _glog_desc[lc->ct]) + 1;
+		}
+		length += 4;
+	}
+	length++;
+
+	SlSetLength(length);
+
+	for (LoggedAction *la = _gamelog_action; la != laend; la++) {
+		SlWriteByte(la->at);
+		SlObject(la, _glog_action_desc);
+
+		const LoggedChange *lcend = &la->change[la->changes];
+		for (LoggedChange *lc = la->change; lc != lcend; lc++) {
+			SlWriteByte(lc->ct);
+			assert((uint)lc->ct < GLCT_END);
+			SlObject(lc, _glog_desc[lc->ct]);
+		}
+		SlWriteByte(GLCT_NONE);
+	}
+	SlWriteByte(GLAT_NONE);
+}
+
+
+extern const ChunkHandler _gamelog_chunk_handlers[] = {
+	{ 'GLOG', Save_GLOG, Load_GLOG, CH_RIFF | CH_LAST }
+};
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/gamelog.h	Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,46 @@
+/* $Id$ */
+
+/** @file gamelog.h Functions to be called to log possibly unsafe game events */
+
+#ifndef GAMELOG_H
+#define GAMELOG_H
+
+#include "newgrf_config.h"
+
+enum GamelogActionType {
+	GLAT_START,        ///< Game created
+	GLAT_LOAD,         ///< Game loaded
+	GLAT_GRF,          ///< GRF changed
+	GLAT_CHEAT,        ///< Cheat was used
+	GLAT_PATCH,        ///< Patches setting changed
+	GLAT_END,          ///< So we know how many GLATs are there
+	GLAT_NONE  = 0xFF, ///< No logging active; in savegames, end of list
+};
+
+void GamelogStartAction(GamelogActionType at);
+void GamelogStopAction();
+
+void GamelogReset();
+
+typedef void GamelogPrintProc(const char *s);
+void GamelogPrint(GamelogPrintProc *proc); // needed for WIN32 / WINCE crash.log
+
+void GamelogPrintDebug();
+void GamelogPrintConsole();
+
+void GamelogRevision();
+void GamelogMode();
+void GamelogOldver();
+void GamelogPatch(const char *name, int32 oldval, int32 newval);
+
+void GamelogGRFUpdate(const GRFConfig *oldg, const GRFConfig *newg);
+void GamelogGRFAddList(const GRFConfig *newg);
+void GamelogGRFRemove(uint32 grfid);
+void GamelogGRFAdd(const GRFConfig *newg);
+void GamelogGRFCompatible(const GRFIdentifier *newg);
+
+void GamelogTestRevision();
+void GamelogTestMode();
+void GamelogTestGRF();
+
+#endif /* GAMELOG_H */
--- a/src/gfxinit.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/gfxinit.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -71,12 +71,8 @@
 		uint end = *index_tbl++;
 
 		do {
-		#ifdef NDEBUG
-			LoadNextSprite(start, file_index, *sprite_id);
-		#else
 			bool b = LoadNextSprite(start, file_index, *sprite_id);
 			assert(b);
-		#endif
 			(*sprite_id)++;
 		} while (++start <= end);
 	}
--- a/src/industry_cmd.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/industry_cmd.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -334,6 +334,20 @@
 
 static Foundation GetFoundation_Industry(TileIndex tile, Slope tileh)
 {
+	IndustryGfx gfx = GetIndustryGfx(tile);
+
+	/* For NewGRF industry tiles we might not be drawing a foundation. We need to
+	 * account for this, otherwise we might be applying a FOUNDATION_LEVELED
+	 * on a steep slope which is not allowed. Furthermore other structures should
+	 * draw the wall of the foundation in this case.
+	 */
+	if (gfx >= NEW_INDUSTRYTILEOFFSET) {
+		const IndustryTileSpec *indts = GetIndustryTileSpec(gfx);
+		if (indts->grf_prop.spritegroup != NULL && HasBit(indts->callback_flags, CBM_INDT_DRAW_FOUNDATIONS)) {
+			uint32 callback_res = GetIndustryTileCallback(CBID_INDUSTRY_DRAW_FOUNDATIONS, 0, 0, gfx, GetIndustryByTile(tile), tile);
+			if (callback_res == 0) return FOUNDATION_NONE;
+		}
+	}
 	return FlatteningFoundation(tileh);
 }
 
@@ -981,7 +995,7 @@
 
 	if (!IsIndustryCompleted(tile)) return;  ///< Can't proceed if not completed
 
-	if (CircularTileSearch(tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles  to search
+	if (CircularTileSearch(&tile, 40, SearchLumberMillTrees, 0)) ///< 40x40 tiles  to search
 		i->produced_cargo_waiting[0] = min(0xffff, i->produced_cargo_waiting[0] + 45); ///< Found a tree, add according value to waiting cargo
 }
 
--- a/src/main_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/main_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -35,9 +35,7 @@
 #include "tilehighlight_func.h"
 
 #include "network/network.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_server.h"
+#include "network/network_func.h"
 #include "network/network_gui.h"
 
 #include "table/sprites.h"
@@ -56,9 +54,9 @@
 	snprintf(msg, sizeof(msg), "%d", p1);
 
 	if (!_network_server) {
-		SEND_COMMAND(PACKET_CLIENT_CHAT)(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
+		NetworkClientSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg);
 	} else {
-		NetworkServer_HandleChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_GIVE_MONEY, DESTTYPE_TEAM, p2, msg, NETWORK_SERVER_INDEX);
 	}
 #endif /* ENABLE_NETWORK */
 }
--- a/src/map.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/map.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -258,7 +258,7 @@
  * Although it really is a square search...
  * Every tile will be tested by means of the callback function proc,
  * which will determine if yes or no the given tile meets criteria of search.
- * @param tile to start the search from
+ * @param tile to start the search from. Upon completion, it will return the tile matching the search
  * @param size: number of tiles per side of the desired search area
  * @param proc: callback testing function pointer.
  * @param data to be passed to the callback function. Depends on the implementation
@@ -266,7 +266,7 @@
  * @pre proc != NULL
  * @pre size > 0
  */
-bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data)
+bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, uint32 data)
 {
 	uint n, x, y;
 	DiagDirection dir;
@@ -274,14 +274,17 @@
 	assert(proc != NULL);
 	assert(size > 0);
 
-	x = TileX(tile);
-	y = TileY(tile);
+	x = TileX(*tile);
+	y = TileY(*tile);
 
 	if (size % 2 == 1) {
 		/* If the length of the side is uneven, the center has to be checked
 		 * separately, as the pattern of uneven sides requires to go around the center */
 		n = 2;
-		if (proc(TileXY(x, y), data)) return true;
+		if (proc(TileXY(x, y), data)) {
+			*tile = TileXY(x, y);
+			return true;
+		}
 
 		/* If tile test is not successful, get one tile down and left,
 		 * ready for a test in first circle around center tile */
@@ -302,6 +305,7 @@
 			for (j = n; j != 0; j--) {
 				if (x <= MapMaxX() && y <= MapMaxY() && ///< Is the tile within the map?
 						proc(TileXY(x, y), data)) {     ///< Is the callback successful?
+					*tile = TileXY(x, y);
 					return true;                        ///< then stop the search
 				}
 
@@ -314,5 +318,7 @@
 		x += _tileoffs_by_dir[DIR_W].x;
 		y += _tileoffs_by_dir[DIR_W].y;
 	}
+
+	*tile = INVALID_TILE;
 	return false;
 }
--- a/src/map_func.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/map_func.h	Wed Jun 04 22:34:45 2008 +0000
@@ -391,7 +391,7 @@
 /**
  * Searches for some cirumstances of a tile around a given tile with a helper function.
  */
-bool CircularTileSearch(TileIndex tile, uint size, TestTileOnSearchProc proc, uint32 data);
+bool CircularTileSearch(TileIndex *tile, uint size, TestTileOnSearchProc proc, uint32 data);
 
 /**
  * Get a random tile out of a given seed.
--- a/src/misc.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -25,6 +25,7 @@
 #include "texteff.hpp"
 #include "gfx_func.h"
 #include "core/alloc_type.hpp"
+#include "gamelog.h"
 #include "animated_tile_func.h"
 #include "settings_type.h"
 #include "tilehighlight_func.h"
@@ -110,6 +111,13 @@
 	InitializeLandscapeVariables(false);
 
 	ResetObjectToPlace();
+
+	GamelogReset();
+	GamelogStartAction(GLAT_START);
+	GamelogRevision();
+	GamelogMode();
+	GamelogGRFAddList(_grfconfig);
+	GamelogStopAction();
 }
 
 
--- a/src/misc/smallvec.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc/smallvec.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,9 @@
 #ifndef SMALLVEC_H
 #define SMALLVEC_H
 
+#include "../core/alloc_func.hpp"
+#include "../core/math_func.hpp"
+
 template <typename T, uint S>
 struct SmallVector {
 	T *data;
--- a/src/misc_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/misc_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -50,7 +50,6 @@
 #include "table/strings.h"
 
 /* Variables to display file lists */
-FiosItem *_fios_list;
 SaveLoadDialogMode _saveload_mode;
 
 
@@ -1300,11 +1299,11 @@
 		case SLD_NEW_GAME:
 		case SLD_LOAD_SCENARIO:
 		case SLD_SAVE_SCENARIO:
-			_fios_list = FiosGetScenarioList(_saveload_mode); break;
+			FiosGetScenarioList(_saveload_mode); break;
 		case SLD_LOAD_HEIGHTMAP:
-			_fios_list = FiosGetHeightmapList(_saveload_mode); break;
+			FiosGetHeightmapList(_saveload_mode); break;
 
-		default: _fios_list = FiosGetSavegameList(_saveload_mode); break;
+		default: FiosGetSavegameList(_saveload_mode); break;
 	}
 }
 
@@ -1333,8 +1332,8 @@
 	 * Drives (A:\ (windows only) are always under the files (FIOS_TYPE_DRIVE)
 	 * Only sort savegames/scenarios, not directories
 	 */
-	for (int i = 0; i < _fios_num; i++) {
-		switch (_fios_list[i].type) {
+	for (const FiosItem *item = _fios_items.Begin(); item != _fios_items.End(); item++) {
+		switch (item->type) {
 			case FIOS_TYPE_DIR:    sort_start++; break;
 			case FIOS_TYPE_PARENT: sort_start++; break;
 			case FIOS_TYPE_DRIVE:  sort_end++;   break;
@@ -1342,9 +1341,9 @@
 		}
 	}
 
-	uint s_amount = _fios_num - sort_start - sort_end;
+	uint s_amount = _fios_items.Length() - sort_start - sort_end;
 	if (s_amount > 0) {
-		qsort(_fios_list + sort_start, s_amount, sizeof(FiosItem), compare_FiosItems);
+		qsort(_fios_items.Get(sort_start), s_amount, sizeof(FiosItem), compare_FiosItems);
 	}
 }
 
@@ -1443,10 +1442,9 @@
 
 	virtual void OnPaint()
 	{
-		int pos;
 		int y;
 
-		SetVScrollCount(this, _fios_num);
+		SetVScrollCount(this, _fios_items.Length());
 		this->DrawWidgets();
 		DrawFiosTexts(this->width);
 
@@ -1459,8 +1457,8 @@
 		this->DrawSortButtonState(_savegame_sort_order & SORT_BY_NAME ? 2 : 3, _savegame_sort_order & SORT_DESCENDING ? SBS_DOWN : SBS_UP);
 
 		y = this->widget[7].top + 1;
-		for (pos = this->vscroll.pos; pos < _fios_num; pos++) {
-			const FiosItem *item = _fios_list + pos;
+		for (uint pos = this->vscroll.pos; pos < _fios_items.Length(); pos++) {
+			const FiosItem *item = _fios_items.Get(pos);
 
 			DoDrawStringTruncated(item->title, 4, y, _fios_colors[item->type], this->width - 18);
 			y += 10;
@@ -1497,14 +1495,12 @@
 
 			case 7: { // Click the listbox
 				int y = (pt.y - this->widget[widget].top - 1) / 10;
-				char *name;
-				const FiosItem *file;
 
 				if (y < 0 || (y += this->vscroll.pos) >= this->vscroll.count) return;
 
-				file = _fios_list + y;
+				const FiosItem *file = _fios_items.Get(y);
 
-				name = FiosBrowseTo(file);
+				char *name = FiosBrowseTo(file);
 				if (name != NULL) {
 					if (_saveload_mode == SLD_LOAD_GAME || _saveload_mode == SLD_LOAD_SCENARIO) {
 						_switch_mode = (_game_mode == GM_EDITOR) ? SM_LOAD_SCENARIO : SM_LOAD;
--- a/src/network/core/config.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/config.h	Wed Jun 04 22:34:45 2008 +0000
@@ -1,14 +1,12 @@
 /* $Id$ */
 
 /**
- * @file config.h Configuration options of the network stuff
+ * @file config.h Configuration options of the network stuff. It is used even when compiling without network support.
  */
 
 #ifndef NETWORK_CORE_CONFIG_H
 #define NETWORK_CORE_CONFIG_H
 
-#ifdef ENABLE_NETWORK
-
 /** DNS hostname of the masterserver */
 #define NETWORK_MASTER_SERVER_HOST "master.openttd.org"
 /** Message sent to the masterserver to 'identify' this client as OpenTTD */
@@ -54,6 +52,4 @@
 	NETWORK_NUM_LANDSCAPES        =    4,
 };
 
-#endif /* ENABLE_NETWORK */
-
 #endif /* NETWORK_CORE_CONFIG_H */
--- a/src/network/core/core.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/core.h	Wed Jun 04 22:34:45 2008 +0000
@@ -62,7 +62,7 @@
 	 * Whether this socket is currently bound to a socket.
 	 * @return true when the socket is bound, false otherwise
 	 */
-	bool IsConnected() { return this->sock != INVALID_SOCKET; }
+	bool IsConnected() const { return this->sock != INVALID_SOCKET; }
 
 	/**
 	 * Whether the current client connected to the socket has quit.
@@ -70,7 +70,7 @@
 	 * data), the socket in not closed; only the packet is dropped.
 	 * @return true when the current client has quit, false otherwise
 	 */
-	bool HasClientQuit() { return this->has_quit; }
+	bool HasClientQuit() const { return this->has_quit; }
 
 	void Send_GRFIdentifier(Packet *p, const GRFIdentifier *grf);
 	void Recv_GRFIdentifier(Packet *p, GRFIdentifier *grf);
--- a/src/network/core/game.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/game.h	Wed Jun 04 22:34:45 2008 +0000
@@ -19,7 +19,13 @@
  * some fields will be empty on the client (like game_password) by default
  * and only filled with data a player enters.
  */
-struct NetworkGameInfo {
+struct NetworkServerGameInfo {
+	byte clients_on;                                ///< Current count of clients on server
+	Date start_date;                                ///< When the game started
+	char map_name[NETWORK_NAME_LENGTH];             ///< Map which is played ["random" for a randomized map]
+};
+
+struct NetworkGameInfo : NetworkServerGameInfo {
 	byte game_info_version;                         ///< Version of the game info
 	char server_name[NETWORK_NAME_LENGTH];          ///< Server name
 	char hostname[NETWORK_HOSTNAME_LENGTH];         ///< Hostname of the server (if any)
@@ -28,21 +34,16 @@
 	bool compatible;                                ///< Can we connect to this server or not? (based on server_revision _and_ grf_match
 	byte server_lang;                               ///< Language of the server (we should make a nice table for this)
 	bool use_password;                              ///< Is this server passworded?
-	char server_password[NETWORK_PASSWORD_LENGTH];  ///< On the server: the game password, on the client: != "" if server has password
 	byte clients_max;                               ///< Max clients allowed on server
-	byte clients_on;                                ///< Current count of clients on server
-	byte companies_max;                             ///< Max companies allowed on server
 	byte companies_on;                              ///< How many started companies do we have
-	byte spectators_max;                            ///< Max spectators allowed on server
+	byte companies_max;                             ///< Max companies allowed on server
 	byte spectators_on;                             ///< How many spectators do we have?
+	byte spectators_max;                            ///< Max spectators allowed on server
 	Date game_date;                                 ///< Current date
-	Date start_date;                                ///< When the game started
-	char map_name[NETWORK_NAME_LENGTH];             ///< Map which is played ["random" for a randomized map]
 	uint16 map_width;                               ///< Map width
 	uint16 map_height;                              ///< Map height
 	byte map_set;                                   ///< Graphical set
 	bool dedicated;                                 ///< Is this a dedicated server?
-	char rcon_password[NETWORK_PASSWORD_LENGTH];    ///< RCon password for the server. "" if rcon is disabled
 	GRFConfig *grfconfig;                           ///< List of NewGRF files used
 };
 
--- a/src/network/core/tcp.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/core/tcp.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -11,7 +11,7 @@
 #include "../../openttd.h"
 #include "../../variables.h"
 
-#include "../network_data.h"
+#include "../network_internal.h"
 #include "packet.h"
 #include "tcp.h"
 
--- a/src/network/network.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -3,7 +3,7 @@
 /** @file network.cpp Base functions for networking support. */
 
 #include "../stdafx.h"
-#include "network_data.h"
+#include "../player_type.h"
 
 #ifdef ENABLE_NETWORK
 
@@ -15,6 +15,7 @@
 #include "../variables.h"
 #include "../date_func.h"
 #include "../newgrf_config.h"
+#include "network_internal.h"
 #include "network_client.h"
 #include "network_server.h"
 #include "network_udp.h"
@@ -38,7 +39,6 @@
 #ifdef DEBUG_DUMP_COMMANDS
 	#include "../core/alloc_func.hpp"
 #endif /* DEBUG_DUMP_COMMANDS */
-
 #include "table/strings.h"
 
 bool _network_reload_cfg;
@@ -46,6 +46,29 @@
 bool _network_available;  ///< is network mode available?
 bool _network_dedicated;  ///< are we a dedicated server?
 bool _network_advertise;  ///< is the server advertising to the master server?
+bool _is_network_server;  ///< Does this client wants to be a network-server?
+NetworkServerGameInfo _network_game_info;
+NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
+NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
+uint16 _network_own_client_index;
+uint16 _redirect_console_to_client;
+bool _network_need_advertise;
+uint32 _network_last_advertise_frame;
+uint8 _network_reconnect;
+char *_network_host_list[10];
+char *_network_ban_list[25];
+uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
+uint32 _frame_counter_max; // To where we may go with our clients
+uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
+uint32 _broadcast_list[MAX_INTERFACES + 1];
+uint32 _network_server_bind_ip;
+uint32 _sync_seed_1, _sync_seed_2;
+uint32 _sync_frame;
+bool _network_first_time;
+uint32 _network_last_host_ip;
+bool _network_udp_server;
+uint16 _network_udp_broadcast;
+uint8 _network_advertise_retries;
 
 /* Check whether NETWORK_NUM_LANDSCAPES is still in sync with NUM_LANDSCAPE */
 assert_compile((int)NETWORK_NUM_LANDSCAPES == (int)NUM_LANDSCAPE);
@@ -216,8 +239,8 @@
 	// This client has missed his ACK packet after 1 DAY_TICKS..
 	//  so we increase his lag for every frame that passes!
 	// The packet can be out by a max of _net_frame_freq
-	if (cs->last_frame_server + DAY_TICKS + _network_frame_freq < _frame_counter)
-		lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _network_frame_freq);
+	if (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq < _frame_counter)
+		lag += _frame_counter - (cs->last_frame_server + DAY_TICKS + _settings_client.network.frame_freq);
 
 	return lag;
 }
@@ -332,18 +355,18 @@
 {
 	if (!_network_dedicated) return;
 
-	if (NetworkCountPlayers() < _network_min_players) {
+	if (NetworkCountPlayers() < _settings_client.network.min_players) {
 		if (_min_players_paused) return;
 
 		_min_players_paused = true;
 		DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
-		NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (not enough players)", NETWORK_SERVER_INDEX);
 	} else {
 		if (!_min_players_paused) return;
 
 		_min_players_paused = false;
 		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
-		NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (enough players)", NETWORK_SERVER_INDEX);
 	}
 }
 
@@ -601,7 +624,7 @@
 	if (_network_server) {
 		// Can we handle a new client?
 		if (_network_clients_connected >= MAX_CLIENTS) return NULL;
-		if (_network_game_info.clients_on >= _network_game_info.clients_max) return NULL;
+		if (_network_game_info.clients_on >= _settings_client.network.max_clients) return NULL;
 
 		// Register the login
 		client_no = _network_clients_connected++;
@@ -662,9 +685,9 @@
 	}
 
 	/* When the client was PRE_ACTIVE, the server was in pause mode, so unpause */
-	if (cs->status == STATUS_PRE_ACTIVE && _network_pause_on_join) {
+	if (cs->status == STATUS_PRE_ACTIVE && _settings_client.network.pause_on_join) {
 		DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
-		NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
+		NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused", NETWORK_SERVER_INDEX);
 	}
 
 	cs->Destroy();
@@ -802,7 +825,7 @@
 	SOCKET ls;
 	struct sockaddr_in sin;
 
-	DEBUG(net, 1, "Listening on %s:%d", _network_server_bind_ip_host, _network_server_port);
+	DEBUG(net, 1, "Listening on %s:%d", _settings_client.network.server_bind_ip, _settings_client.network.server_port);
 
 	ls = socket(AF_INET, SOCK_STREAM, 0);
 	if (ls == INVALID_SOCKET) {
@@ -823,7 +846,7 @@
 
 	sin.sin_family = AF_INET;
 	sin.sin_addr.s_addr = _network_server_bind_ip;
-	sin.sin_port = htons(_network_server_port);
+	sin.sin_port = htons(_settings_client.network.server_port);
 
 	if (bind(ls, (struct sockaddr*)&sin, sizeof(sin)) != 0) {
 		ServerStartError("bind() failed");
@@ -854,12 +877,22 @@
 	}
 
 	if (_network_server) {
-		// We are a server, also close the listensocket
+		/* We are a server, also close the listensocket */
 		closesocket(_listensocket);
 		_listensocket = INVALID_SOCKET;
 		DEBUG(net, 1, "Closed listener");
-		NetworkUDPCloseAll();
 	}
+	NetworkUDPCloseAll();
+
+	/* Free all queued commands */
+	while (_local_command_queue != NULL) {
+		CommandPacket *p = _local_command_queue;
+		_local_command_queue = _local_command_queue->next;
+		free(p);
+	}
+
+	_networking = false;
+	_network_server = false;
 }
 
 // Inits the network (cleans sockets and stuff)
@@ -923,7 +956,7 @@
 
 		ttd_strlcpy(host, b, lengthof(host));
 
-		ttd_strlcpy(_network_default_ip, b, lengthof(_network_default_ip));
+		ttd_strlcpy(_settings_client.network.connect_to_ip, b, lengthof(_settings_client.network.connect_to_ip));
 		rport = NETWORK_DEFAULT_PORT;
 
 		ParseConnectionString(&player, &port, host);
@@ -961,11 +994,10 @@
 
 	if (port == 0) return false;
 
-	ttd_strlcpy(_network_last_host, host, sizeof(_network_last_host));
-	_network_last_port = port;
+	ttd_strlcpy(_settings_client.network.last_host, host, sizeof(_settings_client.network.last_host));
+	_settings_client.network.last_port = port;
 
 	NetworkDisconnect();
-	NetworkUDPCloseAll();
 	NetworkInitialize();
 
 	// Try to connect
@@ -987,34 +1019,13 @@
 {
 	NetworkClientInfo *ci;
 
-	ttd_strlcpy(_network_game_info.server_name, _network_server_name, sizeof(_network_game_info.server_name));
-	ttd_strlcpy(_network_game_info.server_password, _network_server_password, sizeof(_network_server_password));
-	ttd_strlcpy(_network_game_info.rcon_password, _network_rcon_password, sizeof(_network_rcon_password));
-	if (_network_game_info.server_name[0] == '\0')
-		snprintf(_network_game_info.server_name, sizeof(_network_game_info.server_name), "Unnamed Server");
-
-	ttd_strlcpy(_network_game_info.server_revision, _openttd_revision, sizeof(_network_game_info.server_revision));
-
-	// The server is a client too ;)
-	if (_network_dedicated) {
-		_network_game_info.clients_on = 0;
-		_network_game_info.companies_on = 0;
-		_network_game_info.dedicated = true;
-	} else {
-		_network_game_info.clients_on = 1;
-		_network_game_info.companies_on = 1;
-		_network_game_info.dedicated = false;
+	if (StrEmpty(_settings_client.network.server_name)) {
+		snprintf(_settings_client.network.server_name, sizeof(_settings_client.network.server_name), "Unnamed Server");
 	}
 
-	_network_game_info.spectators_on = 0;
-
-	_network_game_info.game_date = _date;
+	/* The server is a client too */
+	_network_game_info.clients_on = _network_dedicated ? 0 : 1;
 	_network_game_info.start_date = ConvertYMDToDate(_settings_game.game_creation.starting_year, 0, 1);
-	_network_game_info.map_width = MapSizeX();
-	_network_game_info.map_height = MapSizeY();
-	_network_game_info.map_set = _settings_game.game_creation.landscape;
-
-	_network_game_info.use_password = (_network_server_password[0] != '\0');
 
 	// We use _network_client_info[MAX_CLIENT_INFO - 1] to store the server-data in it
 	//  The index is NETWORK_SERVER_INDEX ( = 1)
@@ -1024,8 +1035,8 @@
 	ci->client_index = NETWORK_SERVER_INDEX;
 	ci->client_playas = _network_dedicated ? PLAYER_SPECTATOR : _local_player;
 
-	ttd_strlcpy(ci->client_name, _network_player_name, sizeof(ci->client_name));
-	ttd_strlcpy(ci->unique_id, _network_unique_id, sizeof(ci->unique_id));
+	ttd_strlcpy(ci->client_name, _settings_client.network.player_name, sizeof(ci->client_name));
+	ttd_strlcpy(ci->unique_id, _settings_client.network.network_id, sizeof(ci->unique_id));
 }
 
 bool NetworkServerStart()
@@ -1041,7 +1052,7 @@
 
 	// Try to start UDP-server
 	_network_udp_server = true;
-	_network_udp_server = _udp_server_socket->Listen(_network_server_bind_ip, _network_server_port, false);
+	_network_udp_server = _udp_server_socket->Listen(_network_server_bind_ip, _settings_client.network.server_port, false);
 
 	_network_server = true;
 	_networking = true;
@@ -1086,16 +1097,6 @@
 	}
 
 	NetworkClose();
-
-	// Free all queued commands
-	while (_local_command_queue != NULL) {
-		CommandPacket *p = _local_command_queue;
-		_local_command_queue = _local_command_queue->next;
-		free(p);
-	}
-
-	_networking = false;
-	_network_server = false;
 }
 
 // We want to disconnect from the host/clients
@@ -1114,16 +1115,6 @@
 	DeleteWindowById(WC_NETWORK_STATUS_WINDOW, 0);
 
 	NetworkClose();
-
-	// Free all queued commands
-	while (_local_command_queue != NULL) {
-		CommandPacket *p = _local_command_queue;
-		_local_command_queue = _local_command_queue->next;
-		free(p);
-	}
-
-	_networking = false;
-	_network_server = false;
 }
 
 // Receives something from the network
@@ -1332,7 +1323,7 @@
 		_frame_counter++;
 		// Update max-frame-counter
 		if (_frame_counter > _frame_counter_max) {
-			_frame_counter_max = _frame_counter + _network_frame_freq;
+			_frame_counter_max = _frame_counter + _settings_client.network.frame_freq;
 			send_frame = true;
 		}
 
@@ -1382,7 +1373,7 @@
 		sprintf(hex_output + di * 2, "%02x", digest[di]);
 
 	/* _network_unique_id is our id */
-	snprintf(_network_unique_id, sizeof(_network_unique_id), "%s", hex_output);
+	snprintf(_settings_client.network.network_id, sizeof(_settings_client.network.network_id), "%s", hex_output);
 }
 
 void NetworkStartDebugLog(const char *hostname, uint16 port)
@@ -1429,26 +1420,14 @@
 	_network_advertise_retries = 0;
 
 	/* Load the ip from the openttd.cfg */
-	_network_server_bind_ip = inet_addr(_network_server_bind_ip_host);
+	_network_server_bind_ip = inet_addr(_settings_client.network.server_bind_ip);
 	/* And put the data back in it in case it was an invalid ip */
-	snprintf(_network_server_bind_ip_host, sizeof(_network_server_bind_ip_host), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
+	snprintf(_settings_client.network.server_bind_ip, sizeof(_settings_client.network.server_bind_ip), "%s", inet_ntoa(*(struct in_addr *)&_network_server_bind_ip));
 
 	/* Generate an unique id when there is none yet */
-	if (_network_unique_id[0] == '\0') NetworkGenerateUniqueId();
+	if (StrEmpty(_settings_client.network.network_id)) NetworkGenerateUniqueId();
 
-	{
-		byte cl_max = _network_game_info.clients_max;
-		byte cp_max = _network_game_info.companies_max;
-		byte sp_max = _network_game_info.spectators_max;
-		byte s_lang = _network_game_info.server_lang;
-
-		memset(&_network_game_info, 0, sizeof(_network_game_info));
-		_network_game_info.clients_max = cl_max;
-		_network_game_info.companies_max = cp_max;
-		_network_game_info.spectators_max = sp_max;
-		_network_game_info.server_lang = s_lang;
-	}
-
+	memset(&_network_game_info, 0, sizeof(_network_game_info));
 
 	NetworkInitialize();
 	DEBUG(net, 3, "[core] network online, multiplayer available");
--- a/src/network/network.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network.h	Wed Jun 04 22:34:45 2008 +0000
@@ -17,7 +17,7 @@
 extern bool _network_available;  ///< is network mode available?
 extern bool _network_dedicated;  ///< are we a dedicated server?
 extern bool _network_advertise;  ///< is the server advertising to the master server?
-extern bool _network_reload_cfg; ///< will we reload the entire config for the next game?
+extern bool _is_network_server;  ///< Does this client wants to be a network-server?
 
 #else /* ENABLE_NETWORK */
 /* Network function stubs when networking is disabled */
@@ -30,6 +30,7 @@
 #define _network_available 0
 #define _network_dedicated 0
 #define _network_advertise 0
+#define _is_network_server 0
 
 #endif /* ENABLE_NETWORK */
 
--- a/src/network/network_client.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_client.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -7,7 +7,7 @@
 #include "../stdafx.h"
 #include "../debug.h"
 #include "../openttd.h"
-#include "network_data.h"
+#include "network_internal.h"
 #include "core/tcp.h"
 #include "network_client.h"
 #include "network_gamelist.h"
@@ -84,7 +84,7 @@
 	if (StrEmpty(_network_player_info[_local_player].password)) return;
 
 	_password_game_seed = _settings_game.game_creation.generation_seed;
-	ttd_strlcpy(_password_server_unique_id, _network_unique_id, sizeof(_password_server_unique_id));
+	ttd_strlcpy(_password_server_unique_id, _settings_client.network.network_id, sizeof(_password_server_unique_id));
 
 	const char *new_pw = GenerateCompanyPasswordHash(_network_player_info[_local_player].password);
 	ttd_strlcpy(_network_player_info[_local_player].password, new_pw, sizeof(_network_player_info[_local_player].password));
@@ -131,10 +131,10 @@
 
 	p = NetworkSend_Init(PACKET_CLIENT_JOIN);
 	p->Send_string(_openttd_revision);
-	p->Send_string(_network_player_name); // Player name
+	p->Send_string(_settings_client.network.player_name); // Player name
 	p->Send_uint8 (_network_playas);      // PlayAs
 	p->Send_uint8 (NETLANG_ANY);          // Language
-	p->Send_string(_network_unique_id);
+	p->Send_string(_settings_client.network.network_id);
 	MY_CLIENT->Send_Packet(p);
 }
 
@@ -938,4 +938,39 @@
 	return res;
 }
 
+void NetworkClientSendRcon(const char *password, const char *command)
+{
+	SEND_COMMAND(PACKET_CLIENT_RCON)(password, command);
+}
+
+void NetworkUpdatePlayerName()
+{
+	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(_network_own_client_index);
+
+	if (ci == NULL) return;
+
+	/* Don't change the name if it is the same as the old name */
+	if (strcmp(ci->client_name, _settings_client.network.player_name) != 0) {
+		if (!_network_server) {
+			SEND_COMMAND(PACKET_CLIENT_SET_NAME)(_settings_client.network.player_name);
+		} else {
+			if (NetworkFindName(_settings_client.network.player_name)) {
+				NetworkTextMessage(NETWORK_ACTION_NAME_CHANGE, CC_DEFAULT, false, ci->client_name, "%s", _settings_client.network.player_name);
+				ttd_strlcpy(ci->client_name, _settings_client.network.player_name, sizeof(ci->client_name));
+				NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+			}
+		}
+	}
+}
+
+void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg)
+{
+	SEND_COMMAND(PACKET_CLIENT_CHAT)(action, type, dest, msg);
+}
+
+void NetworkClientSetPassword()
+{
+	SEND_COMMAND(PACKET_CLIENT_SET_PASSWORD)(_network_player_info[_local_player].password);
+}
+
 #endif /* ENABLE_NETWORK */
--- a/src/network/network_data.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_data.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -6,7 +6,7 @@
 
 #include "../stdafx.h"
 #include "../debug.h"
-#include "network_data.h"
+#include "network_internal.h"
 #include "network_client.h"
 #include "../command_func.h"
 #include "../callback_table.h"
--- a/src/network/network_data.h	Mon Jun 02 01:46:03 2008 +0000
+++ /dev/null	Thu Jan 01 00:00:00 1970 +0000
@@ -1,121 +0,0 @@
-/* $Id$ */
-
-/** @file network_data.h Internal functions. */
-
-#ifndef NETWORK_DATA_H
-#define NETWORK_DATA_H
-
-#include "../openttd.h"
-#include "../console_type.h"
-#include "network.h"
-#include "network_internal.h"
-
-// Is the network enabled?
-#ifdef ENABLE_NETWORK
-
-#include "core/os_abstraction.h"
-#include "core/core.h"
-#include "core/config.h"
-#include "core/packet.h"
-#include "core/tcp.h"
-
-#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
-
-// The client-info-server-index is always 1
-#define NETWORK_SERVER_INDEX 1
-#define NETWORK_EMPTY_INDEX 0
-
-enum MapPacket {
-	MAP_PACKET_START,
-	MAP_PACKET_NORMAL,
-	MAP_PACKET_END,
-};
-
-enum NetworkErrorCode {
-	NETWORK_ERROR_GENERAL, // Try to use thisone like never
-
-	// Signals from clients
-	NETWORK_ERROR_DESYNC,
-	NETWORK_ERROR_SAVEGAME_FAILED,
-	NETWORK_ERROR_CONNECTION_LOST,
-	NETWORK_ERROR_ILLEGAL_PACKET,
-	NETWORK_ERROR_NEWGRF_MISMATCH,
-
-	// Signals from servers
-	NETWORK_ERROR_NOT_AUTHORIZED,
-	NETWORK_ERROR_NOT_EXPECTED,
-	NETWORK_ERROR_WRONG_REVISION,
-	NETWORK_ERROR_NAME_IN_USE,
-	NETWORK_ERROR_WRONG_PASSWORD,
-	NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
-	NETWORK_ERROR_KICKED,
-	NETWORK_ERROR_CHEATER,
-	NETWORK_ERROR_FULL,
-};
-
-// Actions that can be used for NetworkTextMessage
-enum NetworkAction {
-	NETWORK_ACTION_JOIN,
-	NETWORK_ACTION_LEAVE,
-	NETWORK_ACTION_SERVER_MESSAGE,
-	NETWORK_ACTION_CHAT,
-	NETWORK_ACTION_CHAT_COMPANY,
-	NETWORK_ACTION_CHAT_CLIENT,
-	NETWORK_ACTION_GIVE_MONEY,
-	NETWORK_ACTION_NAME_CHANGE,
-};
-
-enum NetworkPasswordType {
-	NETWORK_GAME_PASSWORD,
-	NETWORK_COMPANY_PASSWORD,
-};
-
-enum DestType {
-	DESTTYPE_BROADCAST, ///< Send message/notice to all players (All)
-	DESTTYPE_TEAM,    ///< Send message/notice to everyone playing the same company (Team)
-	DESTTYPE_CLIENT,    ///< Send message/notice to only a certain player (Private)
-};
-
-// following externs are instantiated at network.cpp
-extern CommandPacket *_local_command_queue;
-
-// Here we keep track of the clients
-//  (and the client uses [0] for his own communication)
-extern NetworkTCPSocketHandler _clients[MAX_CLIENTS];
-
-#define DEREF_CLIENT(i) (&_clients[i])
-// This returns the NetworkClientInfo from a NetworkClientState
-#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
-
-// Macros to make life a bit more easier
-#define DEF_CLIENT_RECEIVE_COMMAND(type) NetworkRecvStatus NetworkPacketReceive_ ## type ## _command(Packet *p)
-#define DEF_CLIENT_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command()
-#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkTCPSocketHandler *cs, Packet *p)
-#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkTCPSocketHandler *cs)
-#define DEF_SERVER_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
-
-#define SEND_COMMAND(type) NetworkPacketSend_ ## type ## _command
-#define RECEIVE_COMMAND(type) NetworkPacketReceive_ ## type ## _command
-
-#define FOR_ALL_CLIENTS(cs) for (cs = _clients; cs != endof(_clients) && cs->IsConnected(); cs++)
-#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
-
-void NetworkExecuteCommand(CommandPacket *cp);
-void NetworkAddCommandQueue(NetworkTCPSocketHandler *cs, CommandPacket *cp);
-
-// from network.c
-void NetworkCloseClient(NetworkTCPSocketHandler *cs);
-void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
-void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
-uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
-byte NetworkGetCurrentLanguageIndex();
-NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
-NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
-NetworkTCPSocketHandler *NetworkFindClientStateFromIndex(uint16 client_index);
-unsigned long NetworkResolveHost(const char *hostname);
-char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
-
-#endif /* ENABLE_NETWORK */
-
-#endif /* NETWORK_DATA_H */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/network_func.h	Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,63 @@
+/* $Id$ */
+
+/** @file network_internal.h Variables and function used internally. */
+
+#ifndef NETWORK_FUNC_H
+#define NETWORK_FUNC_H
+
+#ifdef ENABLE_NETWORK
+
+#include "network_type.h"
+#include "../console_type.h"
+
+extern NetworkServerGameInfo _network_game_info;
+extern NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
+extern NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
+
+extern uint16 _network_own_client_index;
+extern uint16 _redirect_console_to_client;
+extern bool _network_need_advertise;
+extern uint32 _network_last_advertise_frame;
+extern uint8 _network_reconnect;
+extern char *_network_host_list[10];
+extern char *_network_ban_list[25];
+
+byte NetworkSpectatorCount();
+void CheckMinPlayers();
+void NetworkUpdatePlayerName();
+bool NetworkCompanyHasPlayers(PlayerID company);
+bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
+void NetworkReboot();
+void NetworkDisconnect();
+void NetworkGameLoop();
+void NetworkUDPGameLoop();
+void NetworkUDPCloseAll();
+void ParseConnectionString(const char **player, const char **port, char *connection_string);
+void NetworkStartDebugLog(const char *hostname, uint16 port);
+void NetworkPopulateCompanyInfo();
+
+void NetworkUpdateClientInfo(uint16 client_index);
+bool NetworkClientConnectGame(const char *host, uint16 port);
+void NetworkClientSendRcon(const char *password, const char *command);
+void NetworkClientSendChat(NetworkAction action, DestType type, int dest, const char *msg);
+void NetworkClientSetPassword();
+
+/*** Commands ran by the server ***/
+void NetworkServerMonthlyLoop();
+void NetworkServerYearlyLoop();
+void NetworkServerChangeOwner(PlayerID current_player, PlayerID new_player);
+void NetworkServerShowStatusToConsole();
+bool NetworkServerStart();
+
+NetworkClientInfo *NetworkFindClientInfoFromIndex(uint16 client_index);
+NetworkClientInfo *NetworkFindClientInfoFromIP(const char *ip);
+const char* GetPlayerIP(const NetworkClientInfo *ci);
+
+void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string);
+void NetworkServerSendError(uint16 client_index, NetworkErrorCode error);
+void NetworkServerSendChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
+
+#define FOR_ALL_ACTIVE_CLIENT_INFOS(ci) for (ci = _network_client_info; ci != endof(_network_client_info); ci++) if (ci->client_index != NETWORK_EMPTY_INDEX)
+
+#endif /* ENABLE_NETWORK */
+#endif /* NETWORK_FUNC_H */
--- a/src/network/network_gamelist.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gamelist.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -11,6 +11,7 @@
 #include "../debug.h"
 #include "../newgrf_config.h"
 #include "../core/alloc_func.hpp"
+#include "network_internal.h"
 #include "core/game.h"
 #include "network_udp.h"
 #include "network_gamelist.h"
--- a/src/network/network_gamelist.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gamelist.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,8 @@
 #ifndef NETWORK_GAMELIST_H
 #define NETWORK_GAMELIST_H
 
+#include "network_type.h"
+
 /** Structure with information shown in the game list (GUI) */
 struct NetworkGameList {
 	NetworkGameInfo info;  ///< The game information of this server
--- a/src/network/network_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -9,7 +9,7 @@
 #include "network.h"
 #include "../date_func.h"
 #include "../fios.h"
-#include "network_data.h"
+#include "network_internal.h"
 #include "network_client.h"
 #include "network_gui.h"
 #include "network_gamelist.h"
@@ -38,9 +38,6 @@
 #define BGC 5
 #define BTC 15
 
-/* Global to remember sorting after window has been closed */
-static Listing _ng_sorting;
-
 static bool _chat_tab_completion_active;
 
 static void ShowNetworkStartServerWindow();
@@ -87,57 +84,6 @@
 	InvalidateWindowData(WC_NETWORK_WINDOW, 0, unselect);
 }
 
-static bool _internal_sort_order; // Used for Qsort order-flipping
-typedef int CDECL NGameNameSortFunction(const void*, const void*);
-
-/** Qsort function to sort by name. */
-static int CDECL NGameNameSorter(const void *a, const void *b)
-{
-	const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
-	const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
-	int r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
-	return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by the amount of clients online on a
- * server. If the two servers have the same amount, the one with the
- * higher maximum is preferred. */
-static int CDECL NGameClientSorter(const void *a, const void *b)
-{
-	const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
-	const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
-	/* Reverse as per default we are interested in most-clients first */
-	int r = cmp1->info.clients_on - cmp2->info.clients_on;
-
-	if (r == 0) r = cmp1->info.clients_max - cmp2->info.clients_max;
-	if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
-	return _internal_sort_order ? -r : r;
-}
-
-/** Qsort function to sort by joinability. If both servers are the
- * same, prefer the non-passworded server first. */
-static int CDECL NGameAllowedSorter(const void *a, const void *b)
-{
-	const NetworkGameList *cmp1 = *(const NetworkGameList**)a;
-	const NetworkGameList *cmp2 = *(const NetworkGameList**)b;
-
-	/* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
-	int r = StrEmpty(cmp1->info.server_revision) - StrEmpty(cmp2->info.server_revision);
-
-	/* Reverse default as we are interested in version-compatible clients first */
-	if (r == 0) r = cmp2->info.version_compatible - cmp1->info.version_compatible;
-	/* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
-	if (r == 0) r = cmp2->info.compatible - cmp1->info.compatible;
-	/* Passworded servers should be below unpassworded servers */
-	if (r == 0) r = cmp1->info.use_password - cmp2->info.use_password;
-	/* Finally sort on the name of the server */
-	if (r == 0) r = strcasecmp(cmp1->info.server_name, cmp2->info.server_name);
-
-	return _internal_sort_order ? -r : r;
-}
-
 /** Enum for NetworkGameWindow, referring to _network_game_window_widgets */
 enum NetworkGameWindowWidgets {
 	NGWW_CLOSE,         ///< Close 'X' button
@@ -171,42 +117,25 @@
 
 typedef GUIList<NetworkGameList*> GUIGameServerList;
 
-struct NetworkGameWindow : public QueryStringBaseWindow {
+class NetworkGameWindow : public QueryStringBaseWindow {
+protected:
+	/* Runtime saved values */
+	static Listing last_sorting;
+
+	/* Constants for sorting servers */
+	static GUIGameServerList::SortFunction *const sorter_funcs[];
+
 	byte field;                  ///< selected text-field
 	NetworkGameList *server;     ///< selected server
 	GUIGameServerList servers;   ///< list with game servers.
 
-	NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
-	{
-		ttd_strlcpy(this->edit_str_buf, _network_player_name, lengthof(this->edit_str_buf));
-		this->afilter = CS_ALPHANUMERAL;
-		InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
-
-		UpdateNetworkGameWindow(true);
-
-		this->vscroll.cap = 11;
-		this->resize.step_height = NET_PRC__SIZE_OF_ROW;
-
-		this->field = NGWW_PLAYER;
-		this->server = NULL;
-
-		this->servers.flags = VL_REBUILD | (_ng_sorting.order ? VL_DESC : VL_NONE);
-		this->servers.sort_type = _ng_sorting.criteria;
-
-		this->FindWindowPlacementAndResize(desc);
-	}
-
-	~NetworkGameWindow()
-	{
-	}
-
 	/**
 	 * (Re)build the network game list as its amount has changed because
 	 * an item has been added or deleted for example
 	 */
 	void BuildNetworkGameList()
 	{
-		if (!(this->servers.flags & VL_REBUILD)) return;
+		if (!this->servers.NeedRebuild()) return;
 
 		/* Create temporary array of games to use for listing */
 		this->servers.Clear();
@@ -216,40 +145,63 @@
 		}
 
 		this->servers.Compact();
-
-		/* Force resort */
-		this->servers.flags &= ~VL_REBUILD;
-		this->servers.flags |= VL_RESORT;
+		this->servers.RebuildDone();
 	}
 
+	/** Sort servers by name. */
+	static int CDECL NGameNameSorter(NetworkGameList* const *a, NetworkGameList* const *b)
+	{
+		return strcasecmp((*a)->info.server_name, (*b)->info.server_name);
+	}
+
+	/** Sort servers by the amount of clients online on a
+	 * server. If the two servers have the same amount, the one with the
+	 * higher maximum is preferred. */
+	static int CDECL NGameClientSorter(NetworkGameList* const *a, NetworkGameList* const *b)
+	{
+		/* Reverse as per default we are interested in most-clients first */
+		int r = (*a)->info.clients_on - (*b)->info.clients_on;
+
+		if (r == 0) r = (*a)->info.clients_max - (*b)->info.clients_max;
+		if (r == 0) r = NGameNameSorter(a, b);
+
+		return r;
+	}
+
+	/** Sort servers by joinability. If both servers are the
+	 * same, prefer the non-passworded server first. */
+	static int CDECL NGameAllowedSorter(NetworkGameList* const *a, NetworkGameList* const *b)
+	{
+		/* The servers we do not know anything about (the ones that did not reply) should be at the bottom) */
+		int r = StrEmpty((*a)->info.server_revision) - StrEmpty((*b)->info.server_revision);
+
+		/* Reverse default as we are interested in version-compatible clients first */
+		if (r == 0) r = (*b)->info.version_compatible - (*a)->info.version_compatible;
+		/* The version-compatible ones are then sorted with NewGRF compatible first, incompatible last */
+		if (r == 0) r = (*b)->info.compatible - (*a)->info.compatible;
+		/* Passworded servers should be below unpassworded servers */
+		if (r == 0) r = (*a)->info.use_password - (*b)->info.use_password;
+		/* Finally sort on the name of the server */
+		if (r == 0) r = NGameNameSorter(a, b);
+
+		return r;
+	}
+
+	/** Sort the server list */
 	void SortNetworkGameList()
 	{
-		static NGameNameSortFunction * const ngame_sorter[] = {
-			&NGameNameSorter,
-			&NGameClientSorter,
-			&NGameAllowedSorter
-		};
-
-		NetworkGameList *item;
-		uint i;
-
-		if (!(this->servers.flags & VL_RESORT)) return;
-		if (this->servers.Length() == 0) return;
-
-		_internal_sort_order = !!(this->servers.flags & VL_DESC);
-		qsort(this->servers.Begin(), this->servers.Length(), sizeof(*this->servers.Begin()), ngame_sorter[this->servers.sort_type]);
+		if (!this->servers.Sort()) return;
 
 		/* After sorting ngl->sort_list contains the sorted items. Put these back
 		 * into the original list. Basically nothing has changed, we are only
 		 * shuffling the ->next pointers */
 		_network_game_list = this->servers[0];
-		for (item = _network_game_list, i = 1; i != this->servers.Length(); i++) {
+		NetworkGameList *item = _network_game_list;
+		for (uint i = 1; i != this->servers.Length(); i++) {
 			item->next = this->servers[i];
 			item = item->next;
 		}
 		item->next = NULL;
-
-		this->servers.flags &= ~VL_RESORT;
 	}
 
 	/**
@@ -285,16 +237,44 @@
 		}
 	}
 
+public:
+	NetworkGameWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
+	{
+		ttd_strlcpy(this->edit_str_buf, _settings_client.network.player_name, lengthof(this->edit_str_buf));
+		this->afilter = CS_ALPHANUMERAL;
+		InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 120);
+
+		UpdateNetworkGameWindow(true);
+
+		this->vscroll.cap = 11;
+		this->resize.step_height = NET_PRC__SIZE_OF_ROW;
+
+		this->field = NGWW_PLAYER;
+		this->server = NULL;
+
+		this->servers.SetListing(this->last_sorting);
+		this->servers.SetSortFuncs(this->sorter_funcs);
+		this->servers.ForceRebuild();
+		this->SortNetworkGameList();
+
+		this->FindWindowPlacementAndResize(desc);
+	}
+
+	~NetworkGameWindow()
+	{
+		this->last_sorting = this->servers.GetListing();
+	}
+
 	virtual void OnPaint()
 	{
 		const NetworkGameList *sel = this->server;
-		const SortButtonState arrow = (this->servers.flags & VL_DESC) ? SBS_DOWN : SBS_UP;
+		const SortButtonState arrow = this->servers.IsDescSortOrder() ? SBS_DOWN : SBS_UP;
 
-		if (this->servers.flags & VL_REBUILD) {
+		if (this->servers.NeedRebuild()) {
 			this->BuildNetworkGameList();
 			SetVScrollCount(this, this->servers.Length());
 		}
-		if (this->servers.flags & VL_RESORT) this->SortNetworkGameList();
+		this->SortNetworkGameList();
 
 		/* 'Refresh' button invisible if no server selected */
 		this->SetWidgetDisabledState(NGWW_REFRESH, sel == NULL);
@@ -310,7 +290,7 @@
 				sel->info.grfconfig == NULL);
 
 		SetDParam(0, 0x00);
-		SetDParam(1, _lan_internet_types_dropdown[_network_lan_internet]);
+		SetDParam(1, _lan_internet_types_dropdown[_settings_client.network.lan_internet]);
 		this->DrawWidgets();
 
 		/* Edit box to set player name */
@@ -319,31 +299,23 @@
 		DrawString(this->widget[NGWW_PLAYER].left - 100, 23, STR_NETWORK_PLAYER_NAME, TC_GOLD);
 
 		/* Sort based on widgets: name, clients, compatibility */
-		switch (this->servers.sort_type) {
+		switch (this->servers.SortType()) {
 			case NGWW_NAME    - NGWW_NAME: this->DrawSortButtonState(NGWW_NAME,    arrow); break;
 			case NGWW_CLIENTS - NGWW_NAME: this->DrawSortButtonState(NGWW_CLIENTS, arrow); break;
 			case NGWW_INFO    - NGWW_NAME: this->DrawSortButtonState(NGWW_INFO,    arrow); break;
 		}
 
 		uint16 y = NET_PRC__OFFSET_TOP_WIDGET + 3;
-		int32 n = 0;
-		int32 pos = this->vscroll.pos;
-		const NetworkGameList *cur_item = _network_game_list;
 
-		while (pos > 0 && cur_item != NULL) {
-			pos--;
-			cur_item = cur_item->next;
+		const int max = min(this->vscroll.pos + this->vscroll.cap, (int)this->servers.Length());
+
+		for (int i = this->vscroll.pos; i < max; ++i) {
+			const NetworkGameList *ngl = this->servers[i];
+			this->DrawServerLine(ngl, y, ngl == sel);
+			y += NET_PRC__SIZE_OF_ROW;
 		}
 
-		while (cur_item != NULL) {
-			this->DrawServerLine(cur_item, y, cur_item == sel);
-
-			cur_item = cur_item->next;
-			y += NET_PRC__SIZE_OF_ROW;
-			if (++n == this->vscroll.cap) break; // max number of games in the window
-		}
-
-		const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+		const NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_settings_client.network.last_host), _settings_client.network.last_port);
 		/* Draw the last joined server, if any */
 		if (last_joined != NULL) this->DrawServerLine(last_joined, y = this->widget[NGWW_LASTJOINED].top + 3, last_joined == sel);
 
@@ -411,7 +383,7 @@
 			if (!sel->info.compatible) {
 				DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, sel->info.version_compatible ? STR_NETWORK_GRF_MISMATCH : STR_NETWORK_VERSION_MISMATCH, TC_FROMSTRING); // server mismatch
 			} else if (sel->info.clients_on == sel->info.clients_max) {
-				/* Show: server full, when clients_on == clients_max */
+				/* Show: server full, when clients_on == max_clients */
 				DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_SERVER_FULL, TC_FROMSTRING); // server full
 			} else if (sel->info.use_password) {
 				DrawStringCentered(this->widget[NGWW_DETAILS].left + 115, y, STR_NETWORK_PASSWORD, TC_FROMSTRING); // password warning
@@ -434,37 +406,33 @@
 				break;
 
 			case NGWW_CONN_BTN: // 'Connection' droplist
-				ShowDropDownMenu(this, _lan_internet_types_dropdown, _network_lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
+				ShowDropDownMenu(this, _lan_internet_types_dropdown, _settings_client.network.lan_internet, NGWW_CONN_BTN, 0, 0); // do it for widget NSSW_CONN_BTN
 				break;
 
 			case NGWW_NAME: // Sort by name
 			case NGWW_CLIENTS: // Sort by connected clients
 			case NGWW_INFO: // Connectivity (green dot)
-				if (this->servers.sort_type == widget - NGWW_NAME) this->servers.flags ^= VL_DESC;
-				this->servers.flags |= VL_RESORT;
-				this->servers.sort_type = widget - NGWW_NAME;
-
-				_ng_sorting.order = !!(this->servers.flags & VL_DESC);
-				_ng_sorting.criteria = this->servers.sort_type;
+				if (this->servers.SortType() == widget - NGWW_NAME) {
+					this->servers.ToggleSortOrder();
+				} else {
+					this->servers.SetSortType(widget - NGWW_NAME);
+					this->servers.ForceResort();
+				}
 				this->SetDirty();
 				break;
 
 			case NGWW_MATRIX: { // Matrix to show networkgames
-				NetworkGameList *cur_item;
 				uint32 id_v = (pt.y - NET_PRC__OFFSET_TOP_WIDGET) / NET_PRC__SIZE_OF_ROW;
 
 				if (id_v >= this->vscroll.cap) return; // click out of bounds
 				id_v += this->vscroll.pos;
 
-				cur_item = _network_game_list;
-				for (; id_v > 0 && cur_item != NULL; id_v--) cur_item = cur_item->next;
-
-				this->server = cur_item;
+				this->server = (id_v < this->servers.Length()) ? this->servers[id_v] : NULL;
 				this->SetDirty();
 			} break;
 
 			case NGWW_LASTJOINED: {
-				NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_network_last_host), _network_last_port);
+				NetworkGameList *last_joined = NetworkGameListAddItem(inet_addr(_settings_client.network.last_host), _settings_client.network.last_port);
 				if (last_joined != NULL) {
 					this->server = last_joined;
 					this->SetDirty();
@@ -472,7 +440,7 @@
 			} break;
 
 			case NGWW_FIND: // Find server automatically
-				switch (_network_lan_internet) {
+				switch (_settings_client.network.lan_internet) {
 					case 0: NetworkUDPSearchGame(); break;
 					case 1: NetworkUDPQueryMasterServer(); break;
 				}
@@ -480,7 +448,7 @@
 
 			case NGWW_ADD: // Add a server
 				ShowQueryString(
-					BindCString(_network_default_ip),
+					BindCString(_settings_client.network.connect_to_ip),
 					STR_NETWORK_ENTER_IP,
 					31 | 0x1000,  // maximum number of characters OR
 					250, // characters up to this width pixels, whichever is satisfied first
@@ -493,8 +461,8 @@
 
 			case NGWW_JOIN: // Join Game
 				if (this->server != NULL) {
-					snprintf(_network_last_host, sizeof(_network_last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
-					_network_last_port = this->server->port;
+					snprintf(_settings_client.network.last_host, sizeof(_settings_client.network.last_host), "%s", inet_ntoa(*(struct in_addr *)&this->server->ip));
+					_settings_client.network.last_port = this->server->port;
 					ShowNetworkLobbyWindow(this->server);
 				}
 				break;
@@ -513,7 +481,7 @@
 	{
 		switch (widget) {
 			case NGWW_CONN_BTN:
-				_network_lan_internet = index;
+				_settings_client.network.lan_internet = index;
 				break;
 
 			default:
@@ -531,7 +499,7 @@
 	virtual void OnInvalidateData(int data)
 	{
 		if (data != 0) this->server = NULL;
-		this->servers.flags |= VL_REBUILD;
+		this->servers.ForceRebuild();
 		this->SetDirty();
 	}
 
@@ -549,13 +517,13 @@
 			return state;
 		}
 
-		if (this->HandleEditBoxKey(NGWW_PLAYER, keycode, key, state) == 1) return state; // enter pressed
+		if (this->HandleEditBoxKey(NGWW_PLAYER, key, keycode, state) == 1) return state; // enter pressed
 
 		/* The name is only allowed when it starts with a letter! */
-		if (StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
-			ttd_strlcpy(_network_player_name, this->edit_str_buf, lengthof(_network_player_name));
+		if (!StrEmpty(this->edit_str_buf) && this->edit_str_buf[0] != ' ') {
+			ttd_strlcpy(_settings_client.network.player_name, this->edit_str_buf, lengthof(_settings_client.network.player_name));
 		} else {
-			ttd_strlcpy(_network_player_name, "Player", lengthof(_network_player_name));
+			ttd_strlcpy(_settings_client.network.player_name, "Player", lengthof(_settings_client.network.player_name));
 		}
 		return state;
 	}
@@ -589,6 +557,14 @@
 	}
 };
 
+Listing NetworkGameWindow::last_sorting = {false, 2};
+GUIGameServerList::SortFunction *const NetworkGameWindow::sorter_funcs[] = {
+	&NGameNameSorter,
+	&NGameClientSorter,
+	&NGameAllowedSorter
+};
+
+
 static const Widget _network_game_window_widgets[] = {
 /* TOP */
 {   WWT_CLOSEBOX,   RESIZE_NONE,   BGC,     0,    10,     0,    13, STR_00C5,                         STR_018B_CLOSE_WINDOW},            // NGWW_CLOSE
@@ -650,9 +626,6 @@
 		for (srv = &_network_host_list[0]; srv != endof(_network_host_list) && *srv != NULL; srv++) {
 			NetworkAddServer(*srv);
 		}
-
-		_ng_sorting.criteria = 2; // sort default by collectivity (green-dots on top)
-		_ng_sorting.order = 0;    // sort ascending by default
 	}
 
 	new NetworkGameWindow(&_network_game_window_desc);
@@ -692,47 +665,45 @@
 
 	NetworkStartServerWindow(const WindowDesc *desc) : QueryStringBaseWindow(desc)
 	{
-		ttd_strlcpy(this->edit_str_buf, _network_server_name, lengthof(this->edit_str_buf));
+		ttd_strlcpy(this->edit_str_buf, _settings_client.network.server_name, lengthof(this->edit_str_buf));
 
 		_saveload_mode = SLD_NEW_GAME;
 		BuildFileList();
 		this->vscroll.cap = 12;
-		this->vscroll.count = _fios_num + 1;
+		this->vscroll.count = _fios_items.Length();
 
 		this->afilter = CS_ALPHANUMERAL;
 		InitializeTextBuffer(&this->text, this->edit_str_buf, lengthof(this->edit_str_buf), 160);
 
 		this->field = NSSW_GAMENAME;
-		_network_game_info.use_password = !StrEmpty(_network_server_password);
 
 		this->FindWindowPlacementAndResize(desc);
 	}
 
 	virtual void OnPaint()
 	{
-		int y = NSSWND_START, pos;
+		int y = NSSWND_START;
 		const FiosItem *item;
 
 		/* draw basic widgets */
 		SetDParam(1, _connection_types_dropdown[_network_advertise]);
-		SetDParam(2, _network_game_info.clients_max);
-		SetDParam(3, _network_game_info.companies_max);
-		SetDParam(4, _network_game_info.spectators_max);
-		SetDParam(5, STR_NETWORK_LANG_ANY + _network_game_info.server_lang);
+		SetDParam(2, _settings_client.network.max_clients);
+		SetDParam(3, _settings_client.network.max_companies);
+		SetDParam(4, _settings_client.network.max_spectators);
+		SetDParam(5, STR_NETWORK_LANG_ANY + _settings_client.network.server_lang);
 		this->DrawWidgets();
 
 		/* editbox to set game name */
 		this->DrawEditBox(NSSW_GAMENAME);
 
 		/* if password is set, draw red '*' next to 'Set password' button */
-		if (_network_game_info.use_password) DoDrawString("*", 408, 23, TC_RED);
+		if (!StrEmpty(_settings_client.network.server_password)) DoDrawString("*", 408, 23, TC_RED);
 
 		/* draw list of maps */
 		GfxFillRect(11, 63, 258, 215, 0xD7);  // black background of maps list
 
-		pos = this->vscroll.pos;
-		while (pos < _fios_num + 1) {
-			item = _fios_list + pos - 1;
+		for (uint pos = this->vscroll.pos; pos < _fios_items.Length() + 1; pos++) {
+			item = _fios_items.Get(pos - 1);
 			if (item == this->map || (pos == 0 && this->map == NULL))
 				GfxFillRect(11, y - 1, 258, y + 10, 155); // show highlighted item with a different colour
 
@@ -741,7 +712,6 @@
 			} else {
 				DoDrawString(item->title, 14, y, _fios_colors[item->type] );
 			}
-			pos++;
 			y += NSSWND_ROWSIZE;
 
 			if (y >= this->vscroll.cap * NSSWND_ROWSIZE + NSSWND_START) break;
@@ -764,7 +734,7 @@
 
 			case NSSW_SETPWD: // Set password button
 				this->widget_id = NSSW_SETPWD;
-				ShowQueryString(BindCString(_network_server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
+				ShowQueryString(BindCString(_settings_client.network.server_password), STR_NETWORK_SET_PASSWORD, 20, 250, this, CS_ALPHANUMERAL);
 				break;
 
 			case NSSW_SELMAP: { // Select map
@@ -773,7 +743,7 @@
 				y += this->vscroll.pos;
 				if (y >= this->vscroll.count) return;
 
-				this->map = (y == 0) ? NULL : _fios_list + y - 1;
+				this->map = (y == 0) ? NULL : _fios_items.Get(y - 1);
 				this->SetDirty();
 			} break;
 
@@ -791,13 +761,13 @@
 					switch (widget) {
 						default: NOT_REACHED();
 						case NSSW_CLIENTS_BTND: case NSSW_CLIENTS_BTNU:
-							_network_game_info.clients_max    = Clamp(_network_game_info.clients_max    + widget - NSSW_CLIENTS_TXT,    2, MAX_CLIENTS);
+							_settings_client.network.max_clients    = Clamp(_settings_client.network.max_clients    + widget - NSSW_CLIENTS_TXT,    2, MAX_CLIENTS);
 							break;
 						case NSSW_COMPANIES_BTND: case NSSW_COMPANIES_BTNU:
-							_network_game_info.companies_max  = Clamp(_network_game_info.companies_max  + widget - NSSW_COMPANIES_TXT,  1, MAX_PLAYERS);
+							_settings_client.network.max_companies  = Clamp(_settings_client.network.max_companies  + widget - NSSW_COMPANIES_TXT,  1, MAX_PLAYERS);
 							break;
 						case NSSW_SPECTATORS_BTND: case NSSW_SPECTATORS_BTNU:
-							_network_game_info.spectators_max = Clamp(_network_game_info.spectators_max + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
+							_settings_client.network.max_spectators = Clamp(_settings_client.network.max_spectators + widget - NSSW_SPECTATORS_TXT, 0, MAX_CLIENTS);
 							break;
 					}
 				}
@@ -806,26 +776,26 @@
 
 			case NSSW_CLIENTS_TXT:    // Click on number of players
 				this->widget_id = NSSW_CLIENTS_TXT;
-				SetDParam(0, _network_game_info.clients_max);
+				SetDParam(0, _settings_client.network.max_clients);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_CLIENTS,    3, 50, this, CS_NUMERAL);
 				break;
 
 			case NSSW_COMPANIES_TXT:  // Click on number of companies
 				this->widget_id = NSSW_COMPANIES_TXT;
-				SetDParam(0, _network_game_info.companies_max);
+				SetDParam(0, _settings_client.network.max_companies);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_COMPANIES,  3, 50, this, CS_NUMERAL);
 				break;
 
 			case NSSW_SPECTATORS_TXT: // Click on number of spectators
 				this->widget_id = NSSW_SPECTATORS_TXT;
-				SetDParam(0, _network_game_info.spectators_max);
+				SetDParam(0, _settings_client.network.max_spectators);
 				ShowQueryString(STR_CONFIG_PATCHES_INT32, STR_NETWORK_NUMBER_OF_SPECTATORS, 3, 50, this, CS_NUMERAL);
 				break;
 
 			case NSSW_LANGUAGE_BTN: { // Language
 				uint sel = 0;
 				for (uint i = 0; i < lengthof(_language_dropdown) - 1; i++) {
-					if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _network_game_info.server_lang) {
+					if (_language_dropdown[i] == STR_NETWORK_LANG_ANY + _settings_client.network.server_lang) {
 						sel = i;
 						break;
 					}
@@ -869,7 +839,7 @@
 				_network_advertise = (index != 0);
 				break;
 			case NSSW_LANGUAGE_BTN:
-				_network_game_info.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
+				_settings_client.network.server_lang = _language_dropdown[index] - STR_NETWORK_LANG_ANY;
 				break;
 			default:
 				NOT_REACHED();
@@ -889,7 +859,7 @@
 		if (this->field == NSSW_GAMENAME) {
 			if (this->HandleEditBoxKey(NSSW_GAMENAME, key, keycode, state) == 1) return state; // enter pressed
 
-			ttd_strlcpy(_network_server_name, this->text.buf, sizeof(_network_server_name));
+			ttd_strlcpy(_settings_client.network.server_name, this->text.buf, sizeof(_settings_client.network.server_name));
 		}
 
 		return state;
@@ -900,16 +870,15 @@
 		if (str == NULL) return;
 
 		if (this->widget_id == NSSW_SETPWD) {
-			ttd_strlcpy(_network_server_password, str, lengthof(_network_server_password));
-			_network_game_info.use_password = !StrEmpty(_network_server_password);
+			ttd_strlcpy(_settings_client.network.server_password, str, lengthof(_settings_client.network.server_password));
 		} else {
 			int32 value = atoi(str);
 			this->InvalidateWidget(this->widget_id);
 			switch (this->widget_id) {
 				default: NOT_REACHED();
-				case NSSW_CLIENTS_TXT:    _network_game_info.clients_max    = Clamp(value, 2, MAX_CLIENTS); break;
-				case NSSW_COMPANIES_TXT:  _network_game_info.companies_max  = Clamp(value, 1, MAX_PLAYERS); break;
-				case NSSW_SPECTATORS_TXT: _network_game_info.spectators_max = Clamp(value, 0, MAX_CLIENTS); break;
+				case NSSW_CLIENTS_TXT:    _settings_client.network.max_clients    = Clamp(value, 2, MAX_CLIENTS); break;
+				case NSSW_COMPANIES_TXT:  _settings_client.network.max_companies  = Clamp(value, 1, MAX_PLAYERS); break;
+				case NSSW_SPECTATORS_TXT: _settings_client.network.max_spectators = Clamp(value, 0, MAX_CLIENTS); break;
 			}
 		}
 
@@ -1131,22 +1100,22 @@
 			case NLWW_JOIN:     // Join company
 				/* Button can be clicked only when it is enabled */
 				_network_playas = this->company;
-				NetworkClientConnectGame(_network_last_host, _network_last_port);
+				NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
 				break;
 
 			case NLWW_NEW:      // New company
 				_network_playas = PLAYER_NEW_COMPANY;
-				NetworkClientConnectGame(_network_last_host, _network_last_port);
+				NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
 				break;
 
 			case NLWW_SPECTATE: // Spectate game
 				_network_playas = PLAYER_SPECTATOR;
-				NetworkClientConnectGame(_network_last_host, _network_last_port);
+				NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
 				break;
 
 			case NLWW_REFRESH:  // Refresh
-				NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
-				NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+				NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info
+				NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data
 				break;
 		}
 	}
@@ -1189,8 +1158,8 @@
 {
 	DeleteWindowById(WC_NETWORK_WINDOW, 0);
 
-	NetworkTCPQueryServer(_network_last_host, _network_last_port); // company info
-	NetworkUDPQueryServer(_network_last_host, _network_last_port); // general data
+	NetworkTCPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // company info
+	NetworkUDPQueryServer(_settings_client.network.last_host, _settings_client.network.last_port); // general data
 
 	new NetworkLobbyWindow(&_network_lobby_window_desc, ngl);
 }
@@ -1586,6 +1555,12 @@
 	ShowQueryString(STR_EMPTY, caption, 20, 180, FindWindowById(WC_NETWORK_STATUS_WINDOW, 0), CS_ALPHANUMERAL);
 }
 
+// Vars needed for the join-GUI
+NetworkJoinStatus _network_join_status;
+uint8 _network_join_waiting;
+uint16 _network_join_kbytes;
+uint16 _network_join_kbytes_total;
+
 struct NetworkJoinStatusWindow : Window {
 	NetworkJoinStatusWindow(const WindowDesc *desc) : Window(desc)
 	{
@@ -1667,7 +1642,7 @@
 	if (!_network_server) {
 		SEND_COMMAND(PACKET_CLIENT_CHAT)((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf);
 	} else {
-		NetworkServer_HandleChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, NETWORK_SERVER_INDEX);
+		NetworkServerSendChat((NetworkAction)(NETWORK_ACTION_CHAT + type), type, dest, buf, NETWORK_SERVER_INDEX);
 	}
 }
 
@@ -1921,7 +1896,7 @@
 	{
 		this->parent = parent;
 		this->afilter = CS_ALPHANUMERAL;
-		InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_network_default_company_pass), lengthof(this->edit_str_buf)), 0);
+		InitializeTextBuffer(&this->text, this->edit_str_buf, min(lengthof(_settings_client.network.default_company_pass), lengthof(this->edit_str_buf)), 0);
 
 		this->FindWindowPlacementAndResize(desc);
 	}
@@ -1929,7 +1904,7 @@
 	void OnOk()
 	{
 		if (this->IsWidgetLowered(NCPWW_SAVE_AS_DEFAULT_PASSWORD)) {
-			snprintf(_network_default_company_pass, lengthof(_network_default_company_pass), "%s", this->edit_str_buf);
+			snprintf(_settings_client.network.default_company_pass, lengthof(_settings_client.network.default_company_pass), "%s", this->edit_str_buf);
 		}
 
 		/* empty password is a '*' because of console argument */
--- a/src/network/network_gui.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_gui.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,11 +5,10 @@
 #ifndef NETWORK_GUI_H
 #define NETWORK_GUI_H
 
-#include "../window_type.h"
-
 #ifdef ENABLE_NETWORK
 
-#include "network_data.h"
+#include "../window_type.h"
+#include "network_type.h"
 
 void ShowNetworkNeedPassword(NetworkPasswordType npt);
 void ShowNetworkGiveMoneyWindow(PlayerID player); // PlayerID
--- a/src/network/network_internal.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_internal.h	Wed Jun 04 22:34:45 2008 +0000
@@ -7,10 +7,13 @@
 
 #ifdef ENABLE_NETWORK
 
-#include "../player_type.h"
-#include "../economy_type.h"
+#include "network.h"
+#include "network_func.h"
+#include "core/os_abstraction.h"
+#include "core/core.h"
 #include "core/config.h"
-#include "core/game.h"
+#include "core/packet.h"
+#include "core/tcp.h"
 
 /**
  * If this line is enable, every frame will have a sync test
@@ -29,50 +32,14 @@
  */
 //#define NETWORK_SEND_DOUBLE_SEED
 
-
-enum {
-	/**
-	 * How many clients can we have? Like.. MAX_PLAYERS - 1 is the amount of
-	 *  players that can really play.. so.. a max of 4 spectators.. gives us..
-	 *  MAX_PLAYERS + 3
-	 */
-	MAX_CLIENTS = MAX_PLAYERS + 3,
+#define MAX_TEXT_MSG_LEN 1024 /* long long long long sentences :-) */
 
-	/** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
-	MAX_CLIENT_INFO = MAX_CLIENTS + 1,
-
-	/** Maximum number of internet interfaces supported. */
-	MAX_INTERFACES = 9,
-
-	/** How many vehicle/station types we put over the network */
-	NETWORK_VEHICLE_TYPES = 5,
-	NETWORK_STATION_TYPES = 5,
+enum MapPacket {
+	MAP_PACKET_START,
+	MAP_PACKET_NORMAL,
+	MAP_PACKET_END,
 };
 
-struct NetworkPlayerInfo {
-	char company_name[NETWORK_NAME_LENGTH];         ///< Company name
-	char password[NETWORK_PASSWORD_LENGTH];         ///< The password for the player
-	Year inaugurated_year;                          ///< What year the company started in
-	Money company_value;                            ///< The company value
-	Money money;                                    ///< The amount of money the company has
-	Money income;                                   ///< How much did the company earned last year
-	uint16 performance;                             ///< What was his performance last month?
-	bool use_password;                              ///< Is there a password
-	uint16 num_vehicle[NETWORK_VEHICLE_TYPES];      ///< How many vehicles are there of this type?
-	uint16 num_station[NETWORK_STATION_TYPES];      ///< How many stations are there of this type?
-	char players[NETWORK_PLAYERS_LENGTH];           ///< The players that control this company (Name1, name2, ..)
-	uint16 months_empty;                            ///< How many months the company is empty
-};
-
-struct NetworkClientInfo {
-	uint16 client_index;                            ///< Index of the client (same as ClientState->index)
-	char client_name[NETWORK_CLIENT_NAME_LENGTH];   ///< Name of the client
-	byte client_lang;                               ///< The language of the client
-	PlayerID client_playas;                         ///< As which player is this client playing (PlayerID)
-	uint32 client_ip;                               ///< IP-address of the client (so he can be banned)
-	Date join_date;                                 ///< Gamedate the player has joined
-	char unique_id[NETWORK_UNIQUE_ID_LENGTH];       ///< Every play sends an unique id so we can indentify him
-};
 
 enum NetworkJoinStatus {
 	NETWORK_JOIN_STATUS_CONNECTING,
@@ -126,100 +93,80 @@
 	NETLANG_COUNT
 };
 
-VARDEF NetworkGameInfo _network_game_info;
-VARDEF NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
-VARDEF NetworkClientInfo _network_client_info[MAX_CLIENT_INFO];
-
-VARDEF char _network_player_name[NETWORK_CLIENT_NAME_LENGTH];
-VARDEF char _network_default_ip[NETWORK_HOSTNAME_LENGTH];
+extern NetworkPlayerInfo _network_player_info[MAX_PLAYERS];
 
-VARDEF uint16 _network_own_client_index;
-VARDEF char _network_unique_id[NETWORK_UNIQUE_ID_LENGTH]; // Our own unique ID
+extern uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
+extern uint32 _frame_counter_max; // To where we may go with our clients
 
-VARDEF uint32 _frame_counter_server; // The frame_counter of the server, if in network-mode
-VARDEF uint32 _frame_counter_max; // To where we may go with our clients
-
-VARDEF uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
+extern uint32 _last_sync_frame; // Used in the server to store the last time a sync packet was sent to clients.
 
 // networking settings
-VARDEF uint32 _broadcast_list[MAX_INTERFACES + 1];
-
-VARDEF uint16 _network_server_port;
-/* We use bind_ip and bind_ip_host, where bind_ip_host is the readable form of
-    bind_ip_host, and bind_ip the numeric value, because we want a nice number
-    in the openttd.cfg, but we wants to use the uint32 internally.. */
-VARDEF uint32 _network_server_bind_ip;
-VARDEF char _network_server_bind_ip_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF bool _is_network_server; // Does this client wants to be a network-server?
-VARDEF char _network_server_name[NETWORK_NAME_LENGTH];
-VARDEF char _network_server_password[NETWORK_PASSWORD_LENGTH];
-VARDEF char _network_rcon_password[NETWORK_PASSWORD_LENGTH];
-VARDEF char _network_default_company_pass[NETWORK_PASSWORD_LENGTH];
-
-VARDEF uint16 _network_max_join_time;             ///< Time a client can max take to join
-VARDEF bool _network_pause_on_join;               ///< Pause the game when a client tries to join (more chance of succeeding join)
-
-VARDEF uint16 _redirect_console_to_client;
-
-VARDEF uint16 _network_sync_freq;
-VARDEF uint8 _network_frame_freq;
+extern uint32 _broadcast_list[MAX_INTERFACES + 1];
 
-VARDEF uint32 _sync_seed_1, _sync_seed_2;
-VARDEF uint32 _sync_frame;
-VARDEF bool _network_first_time;
-// Vars needed for the join-GUI
-VARDEF NetworkJoinStatus _network_join_status;
-VARDEF uint8 _network_join_waiting;
-VARDEF uint16 _network_join_kbytes;
-VARDEF uint16 _network_join_kbytes_total;
-
-VARDEF char _network_last_host[NETWORK_HOSTNAME_LENGTH];
-VARDEF short _network_last_port;
-VARDEF uint32 _network_last_host_ip;
-VARDEF uint8 _network_reconnect;
+extern uint32 _network_server_bind_ip;
 
-VARDEF bool _network_udp_server;
-VARDEF uint16 _network_udp_broadcast;
-
-VARDEF byte _network_lan_internet;
+extern uint32 _sync_seed_1, _sync_seed_2;
+extern uint32 _sync_frame;
+extern bool _network_first_time;
+// Vars needed for the join-GUI
+extern NetworkJoinStatus _network_join_status;
+extern uint8 _network_join_waiting;
+extern uint16 _network_join_kbytes;
+extern uint16 _network_join_kbytes_total;
 
-VARDEF bool _network_need_advertise;
-VARDEF uint32 _network_last_advertise_frame;
-VARDEF uint8 _network_advertise_retries;
+extern uint32 _network_last_host_ip;
+extern uint8 _network_reconnect;
 
-VARDEF bool _network_autoclean_companies;
-VARDEF uint8 _network_autoclean_unprotected; // Remove a company after X months
-VARDEF uint8 _network_autoclean_protected;   // Unprotect a company after X months
+extern bool _network_udp_server;
+extern uint16 _network_udp_broadcast;
 
-VARDEF Year _network_restart_game_year;      // If this year is reached, the server automaticly restarts
-VARDEF uint8 _network_min_players;           // Minimum number of players for game to unpause
+extern uint8 _network_advertise_retries;
+
+// following externs are instantiated at network.cpp
+extern CommandPacket *_local_command_queue;
+
+// Here we keep track of the clients
+//  (and the client uses [0] for his own communication)
+extern NetworkTCPSocketHandler _clients[MAX_CLIENTS];
 
 void NetworkTCPQueryServer(const char* host, unsigned short port);
 
-byte NetworkSpectatorCount();
-
-VARDEF char *_network_host_list[10];
-VARDEF char *_network_ban_list[25];
-
-void ParseConnectionString(const char **player, const char **port, char *connection_string);
-void NetworkUpdateClientInfo(uint16 client_index);
 void NetworkAddServer(const char *b);
 void NetworkRebuildHostList();
-bool NetworkChangeCompanyPassword(byte argc, char *argv[]);
-void NetworkPopulateCompanyInfo();
 void UpdateNetworkGameWindow(bool unselect);
-void CheckMinPlayers();
-void NetworkStartDebugLog(const char *hostname, uint16 port);
-
-void NetworkUDPCloseAll();
-void NetworkGameLoop();
-void NetworkUDPGameLoop();
-bool NetworkServerStart();
-bool NetworkClientConnectGame(const char *host, uint16 port);
-void NetworkReboot();
-void NetworkDisconnect();
 
 bool IsNetworkCompatibleVersion(const char *version);
 
+void NetworkExecuteCommand(CommandPacket *cp);
+void NetworkAddCommandQueue(NetworkTCPSocketHandler *cs, CommandPacket *cp);
+
+// from network.c
+void NetworkCloseClient(NetworkTCPSocketHandler *cs);
+void CDECL NetworkTextMessage(NetworkAction action, ConsoleColour color, bool self_send, const char *name, const char *str, ...);
+void NetworkGetClientName(char *clientname, size_t size, const NetworkTCPSocketHandler *cs);
+uint NetworkCalculateLag(const NetworkTCPSocketHandler *cs);
+byte NetworkGetCurrentLanguageIndex();
+NetworkTCPSocketHandler *NetworkFindClientStateFromIndex(uint16 client_index);
+unsigned long NetworkResolveHost(const char *hostname);
+char* GetNetworkErrorMsg(char* buf, NetworkErrorCode err, const char* last);
+bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
+
+#define DEREF_CLIENT(i) (&_clients[i])
+// This returns the NetworkClientInfo from a NetworkClientState
+#define DEREF_CLIENT_INFO(cs) (&_network_client_info[cs - _clients])
+
+// Macros to make life a bit more easier
+#define DEF_CLIENT_RECEIVE_COMMAND(type) NetworkRecvStatus NetworkPacketReceive_ ## type ## _command(Packet *p)
+#define DEF_CLIENT_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command()
+#define DEF_CLIENT_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
+#define DEF_SERVER_RECEIVE_COMMAND(type) void NetworkPacketReceive_ ## type ## _command(NetworkTCPSocketHandler *cs, Packet *p)
+#define DEF_SERVER_SEND_COMMAND(type) void NetworkPacketSend_ ## type ## _command(NetworkTCPSocketHandler *cs)
+#define DEF_SERVER_SEND_COMMAND_PARAM(type) void NetworkPacketSend_ ## type ## _command
+
+#define SEND_COMMAND(type) NetworkPacketSend_ ## type ## _command
+#define RECEIVE_COMMAND(type) NetworkPacketReceive_ ## type ## _command
+
+#define FOR_ALL_CLIENTS(cs) for (cs = _clients; cs != endof(_clients) && cs->IsConnected(); cs++)
+
 #endif /* ENABLE_NETWORK */
 #endif /* NETWORK_INTERNAL_H */
--- a/src/network/network_server.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_server.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -8,7 +8,7 @@
 #include "../openttd.h" // XXX StringID
 #include "../debug.h"
 #include "../strings_func.h"
-#include "network_data.h"
+#include "network_internal.h"
 #include "core/tcp.h"
 #include "../vehicle_base.h"
 #include "../vehicle_func.h"
@@ -230,7 +230,7 @@
 	Packet *p = NetworkSend_Init(PACKET_SERVER_NEED_PASSWORD);
 	p->Send_uint8(type);
 	p->Send_uint32(_settings_game.game_creation.generation_seed);
-	p->Send_string(_network_unique_id);
+	p->Send_string(_settings_client.network.network_id);
 	cs->Send_Packet(p);
 }
 
@@ -255,7 +255,7 @@
 	p = NetworkSend_Init(PACKET_SERVER_WELCOME);
 	p->Send_uint16(cs->index);
 	p->Send_uint32(_settings_game.game_creation.generation_seed);
-	p->Send_string(_network_unique_id);
+	p->Send_string(_settings_client.network.network_id);
 	cs->Send_Packet(p);
 
 		// Transmit info about all the active clients
@@ -614,7 +614,7 @@
 	NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
 
 	/* We now want a password from the client else we do not allow him in! */
-	if (_network_game_info.use_password) {
+	if (!StrEmpty(_settings_client.network.server_password)) {
 		SEND_COMMAND(PACKET_SERVER_NEED_PASSWORD)(cs, NETWORK_GAME_PASSWORD);
 	} else {
 		if (IsValidPlayer(ci->client_playas) && _network_player_info[ci->client_playas].password[0] != '\0') {
@@ -655,13 +655,13 @@
 	// join another company does not affect these values
 	switch (playas) {
 		case PLAYER_NEW_COMPANY: /* New company */
-			if (ActivePlayerCount() >= _network_game_info.companies_max) {
+			if (ActivePlayerCount() >= _settings_client.network.max_companies) {
 				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 				return;
 			}
 			break;
 		case PLAYER_SPECTATOR: /* Spectator */
-			if (NetworkSpectatorCount() >= _network_game_info.spectators_max) {
+			if (NetworkSpectatorCount() >= _settings_client.network.max_spectators) {
 				SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_FULL);
 				return;
 			}
@@ -711,7 +711,7 @@
 
 	if (cs->status == STATUS_AUTHORIZING && type == NETWORK_GAME_PASSWORD) {
 		// Check game-password
-		if (strcmp(password, _network_game_info.server_password) != 0) {
+		if (strcmp(password, _settings_client.network.server_password) != 0) {
 			// Password is invalid
 			SEND_COMMAND(PACKET_SERVER_ERROR)(cs, NETWORK_ERROR_WRONG_PASSWORD);
 			return;
@@ -800,11 +800,11 @@
 			}
 		}
 
-		if (_network_pause_on_join) {
+		if (_settings_client.network.pause_on_join) {
 			/* Now pause the game till the client is in sync */
 			DoCommandP(0, 1, 0, NULL, CMD_PAUSE);
 
-			NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
+			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game paused (incoming client)", NETWORK_SERVER_INDEX);
 		}
 	} else {
 		// Wrong status for this packet, give a warning to client, and close connection
@@ -1021,9 +1021,9 @@
 		/* Now he is! Unpause the game */
 		cs->status = STATUS_ACTIVE;
 
-		if (_network_pause_on_join) {
+		if (_settings_client.network.pause_on_join) {
 			DoCommandP(0, 0, 0, NULL, CMD_PAUSE);
-			NetworkServer_HandleChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
+			NetworkServerSendChat(NETWORK_ACTION_SERVER_MESSAGE, DESTTYPE_BROADCAST, 0, "Game unpaused (client connected)", NETWORK_SERVER_INDEX);
 		}
 
 		CheckMinPlayers();
@@ -1040,7 +1040,7 @@
 
 
 
-void NetworkServer_HandleChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
+void NetworkServerSendChat(NetworkAction action, DestType desttype, int dest, const char *msg, uint16 from_index)
 {
 	NetworkTCPSocketHandler *cs;
 	const NetworkClientInfo *ci, *ci_own, *ci_to;
@@ -1146,7 +1146,7 @@
 
 	p->Recv_string(msg, MAX_TEXT_MSG_LEN);
 
-	NetworkServer_HandleChat(action, desttype, dest, msg, cs->index);
+	NetworkServerSendChat(action, desttype, dest, msg, cs->index);
 }
 
 DEF_SERVER_RECEIVE_COMMAND(PACKET_CLIENT_SET_PASSWORD)
@@ -1187,12 +1187,12 @@
 	char pass[NETWORK_PASSWORD_LENGTH];
 	char command[NETWORK_RCONCOMMAND_LENGTH];
 
-	if (_network_game_info.rcon_password[0] == '\0') return;
+	if (StrEmpty(_settings_client.network.rcon_password)) return;
 
 	p->Recv_string(pass, sizeof(pass));
 	p->Recv_string(command, sizeof(command));
 
-	if (strcmp(pass, _network_game_info.rcon_password) != 0) {
+	if (strcmp(pass, _settings_client.network.rcon_password) != 0) {
 		DEBUG(net, 0, "[rcon] wrong password from client-id %d", cs->index);
 		return;
 	}
@@ -1365,7 +1365,7 @@
 /* Check if we want to restart the map */
 static void NetworkCheckRestartMap()
 {
-	if (_network_restart_game_year != 0 && _cur_year >= _network_restart_game_year) {
+	if (_settings_client.network.restart_game_year != 0 && _cur_year >= _settings_client.network.restart_game_year) {
 		DEBUG(net, 0, "Auto-restarting map. Year %d reached", _cur_year);
 
 		StartNewGameWithoutGUI(GENERATE_NEW_SEED);
@@ -1384,7 +1384,7 @@
 	const Player *p;
 	bool clients_in_company[MAX_PLAYERS];
 
-	if (!_network_autoclean_companies) return;
+	if (!_settings_client.network.autoclean_companies) return;
 
 	memset(clients_in_company, 0, sizeof(clients_in_company));
 
@@ -1409,13 +1409,13 @@
 			_network_player_info[p->index].months_empty++;
 
 			/* Is the company empty for autoclean_unprotected-months, and is there no protection? */
-			if (_network_player_info[p->index].months_empty > _network_autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
+			if (_network_player_info[p->index].months_empty > _settings_client.network.autoclean_unprotected && _network_player_info[p->index].password[0] == '\0') {
 				/* Shut the company down */
 				DoCommandP(0, 2, p->index, NULL, CMD_PLAYER_CTRL);
 				IConsolePrintF(CC_DEFAULT, "Auto-cleaned company #%d", p->index + 1);
 			}
 			/* Is the compnay empty for autoclean_protected-months, and there is a protection? */
-			if (_network_player_info[p->index].months_empty > _network_autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
+			if (_network_player_info[p->index].months_empty > _settings_client.network.autoclean_protected && _network_player_info[p->index].password[0] != '\0') {
 				/* Unprotect the company */
 				_network_player_info[p->index].password[0] = '\0';
 				IConsolePrintF(CC_DEFAULT, "Auto-removed protection from company #%d", p->index+1);
@@ -1510,7 +1510,7 @@
 #endif
 
 #ifndef ENABLE_NETWORK_SYNC_EVERY_FRAME
-	if (_frame_counter >= _last_sync_frame + _network_sync_freq) {
+	if (_frame_counter >= _last_sync_frame + _settings_client.network.sync_freq) {
 		_last_sync_frame = _frame_counter;
 		send_sync = true;
 	}
@@ -1542,8 +1542,8 @@
 			}
 		} else if (cs->status == STATUS_PRE_ACTIVE) {
 			int lag = NetworkCalculateLag(cs);
-			if (lag > _network_max_join_time) {
-				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _network_max_join_time);
+			if (lag > _settings_client.network.max_join_time) {
+				IConsolePrintF(CC_ERROR,"Client #%d is dropped because it took longer than %d ticks for him to join", cs->index, _settings_client.network.max_join_time);
 				NetworkCloseClient(cs);
 			}
 		} else if (cs->status == STATUS_INACTIVE) {
@@ -1582,4 +1582,82 @@
 	NetworkAutoCleanCompanies();
 }
 
+void NetworkServerChangeOwner(PlayerID current_player, PlayerID new_player)
+{
+	/* The server has to handle all administrative issues, for example
+	 * updating and notifying all clients of what has happened */
+	NetworkTCPSocketHandler *cs;
+	NetworkClientInfo *ci = NetworkFindClientInfoFromIndex(NETWORK_SERVER_INDEX);
+
+	/* The server has just changed from player */
+	if (current_player == ci->client_playas) {
+		ci->client_playas = new_player;
+		NetworkUpdateClientInfo(NETWORK_SERVER_INDEX);
+	}
+
+	/* Find all clients that were in control of this company, and mark them as new_player */
+	FOR_ALL_CLIENTS(cs) {
+		ci = DEREF_CLIENT_INFO(cs);
+		if (current_player == ci->client_playas) {
+			ci->client_playas = new_player;
+			NetworkUpdateClientInfo(ci->client_index);
+		}
+	}
+}
+
+const char* GetPlayerIP(const NetworkClientInfo* ci)
+{
+	struct in_addr addr;
+
+	addr.s_addr = ci->client_ip;
+	return inet_ntoa(addr);
+}
+
+void NetworkServerShowStatusToConsole()
+{
+	static const char* const stat_str[] = {
+		"inactive",
+		"authorizing",
+		"authorized",
+		"waiting",
+		"loading map",
+		"map done",
+		"ready",
+		"active"
+	};
+
+	NetworkTCPSocketHandler *cs;
+	FOR_ALL_CLIENTS(cs) {
+		int lag = NetworkCalculateLag(cs);
+		const NetworkClientInfo *ci = DEREF_CLIENT_INFO(cs);
+		const char* status;
+
+		status = (cs->status < (ptrdiff_t)lengthof(stat_str) ? stat_str[cs->status] : "unknown");
+		IConsolePrintF(CC_INFO, "Client #%1d  name: '%s'  status: '%s'  frame-lag: %3d  company: %1d  IP: %s  unique-id: '%s'",
+			cs->index, ci->client_name, status, lag,
+			ci->client_playas + (IsValidPlayer(ci->client_playas) ? 1 : 0),
+			GetPlayerIP(ci), ci->unique_id);
+	}
+}
+
+void NetworkServerSendRcon(uint16 client_index, ConsoleColour colour_code, const char *string)
+{
+	SEND_COMMAND(PACKET_SERVER_RCON)(NetworkFindClientStateFromIndex(client_index), colour_code, string);
+}
+
+void NetworkServerSendError(uint16 client_index, NetworkErrorCode error)
+{
+	SEND_COMMAND(PACKET_SERVER_ERROR)(NetworkFindClientStateFromIndex(client_index), error);
+}
+
+bool NetworkCompanyHasPlayers(PlayerID company)
+{
+	const NetworkTCPSocketHandler *cs;
+	const NetworkClientInfo *ci;
+	FOR_ALL_CLIENTS(cs) {
+		ci = DEREF_CLIENT_INFO(cs);
+		if (ci->client_playas == company) return true;
+	}
+	return false;
+}
 #endif /* ENABLE_NETWORK */
--- a/src/network/network_server.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_server.h	Wed Jun 04 22:34:45 2008 +0000
@@ -14,21 +14,8 @@
 DEF_SERVER_SEND_COMMAND(PACKET_SERVER_NEWGAME);
 DEF_SERVER_SEND_COMMAND_PARAM(PACKET_SERVER_RCON)(NetworkTCPSocketHandler *cs, uint16 color, const char *command);
 
-bool NetworkFindName(char new_name[NETWORK_CLIENT_NAME_LENGTH]);
-void NetworkServer_HandleChat(NetworkAction action, DestType type, int dest, const char *msg, uint16 from_index);
-
 bool NetworkServer_ReadPackets(NetworkTCPSocketHandler *cs);
 void NetworkServer_Tick(bool send_frame);
-void NetworkServerMonthlyLoop();
-void NetworkServerYearlyLoop();
-
-static inline const char* GetPlayerIP(const NetworkClientInfo* ci)
-{
-	struct in_addr addr;
-
-	addr.s_addr = ci->client_ip;
-	return inet_ntoa(addr);
-}
 
 #else /* ENABLE_NETWORK */
 /* Network function stubs when networking is disabled */
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/src/network/network_type.h	Wed Jun 04 22:34:45 2008 +0000
@@ -0,0 +1,108 @@
+/* $Id$ */
+
+/** @file network_internal.h Variables and function used internally. */
+
+#ifndef NETWORK_TYPE_H
+#define NETWORK_TYPE_H
+
+#ifdef ENABLE_NETWORK
+
+#include "../player_type.h"
+#include "../economy_type.h"
+#include "core/config.h"
+#include "core/game.h"
+
+enum {
+	/**
+	 * How many clients can we have? Like.. MAX_PLAYERS - 1 is the amount of
+	 *  players that can really play.. so.. a max of 4 spectators.. gives us..
+	 *  MAX_PLAYERS + 3
+	 */
+	MAX_CLIENTS = MAX_PLAYERS + 3,
+
+	/** Do not change this next line. It should _ALWAYS_ be MAX_CLIENTS + 1 */
+	MAX_CLIENT_INFO = MAX_CLIENTS + 1,
+
+	/** Maximum number of internet interfaces supported. */
+	MAX_INTERFACES = 9,
+
+	/** How many vehicle/station types we put over the network */
+	NETWORK_VEHICLE_TYPES = 5,
+	NETWORK_STATION_TYPES = 5,
+
+	NETWORK_SERVER_INDEX = 1,
+	NETWORK_EMPTY_INDEX  = 0,
+};
+
+struct NetworkPlayerInfo {
+	char company_name[NETWORK_NAME_LENGTH];         ///< Company name
+	char password[NETWORK_PASSWORD_LENGTH];         ///< The password for the player
+	Year inaugurated_year;                          ///< What year the company started in
+	Money company_value;                            ///< The company value
+	Money money;                                    ///< The amount of money the company has
+	Money income;                                   ///< How much did the company earned last year
+	uint16 performance;                             ///< What was his performance last month?
+	bool use_password;                              ///< Is there a password
+	uint16 num_vehicle[NETWORK_VEHICLE_TYPES];      ///< How many vehicles are there of this type?
+	uint16 num_station[NETWORK_STATION_TYPES];      ///< How many stations are there of this type?
+	char players[NETWORK_PLAYERS_LENGTH];           ///< The players that control this company (Name1, name2, ..)
+	uint16 months_empty;                            ///< How many months the company is empty
+};
+
+struct NetworkClientInfo {
+	uint16 client_index;                            ///< Index of the client (same as ClientState->index)
+	char client_name[NETWORK_CLIENT_NAME_LENGTH];   ///< Name of the client
+	byte client_lang;                               ///< The language of the client
+	PlayerID client_playas;                         ///< As which player is this client playing (PlayerID)
+	uint32 client_ip;                               ///< IP-address of the client (so he can be banned)
+	Date join_date;                                 ///< Gamedate the player has joined
+	char unique_id[NETWORK_UNIQUE_ID_LENGTH];       ///< Every play sends an unique id so we can indentify him
+};
+
+enum NetworkPasswordType {
+	NETWORK_GAME_PASSWORD,
+	NETWORK_COMPANY_PASSWORD,
+};
+
+enum DestType {
+	DESTTYPE_BROADCAST, ///< Send message/notice to all players (All)
+	DESTTYPE_TEAM,      ///< Send message/notice to everyone playing the same company (Team)
+	DESTTYPE_CLIENT,    ///< Send message/notice to only a certain player (Private)
+};
+
+/** Actions that can be used for NetworkTextMessage */
+enum NetworkAction {
+	NETWORK_ACTION_JOIN,
+	NETWORK_ACTION_LEAVE,
+	NETWORK_ACTION_SERVER_MESSAGE,
+	NETWORK_ACTION_CHAT,
+	NETWORK_ACTION_CHAT_COMPANY,
+	NETWORK_ACTION_CHAT_CLIENT,
+	NETWORK_ACTION_GIVE_MONEY,
+	NETWORK_ACTION_NAME_CHANGE,
+};
+
+enum NetworkErrorCode {
+	NETWORK_ERROR_GENERAL, // Try to use this one like never
+
+	/* Signals from clients */
+	NETWORK_ERROR_DESYNC,
+	NETWORK_ERROR_SAVEGAME_FAILED,
+	NETWORK_ERROR_CONNECTION_LOST,
+	NETWORK_ERROR_ILLEGAL_PACKET,
+	NETWORK_ERROR_NEWGRF_MISMATCH,
+
+	/* Signals from servers */
+	NETWORK_ERROR_NOT_AUTHORIZED,
+	NETWORK_ERROR_NOT_EXPECTED,
+	NETWORK_ERROR_WRONG_REVISION,
+	NETWORK_ERROR_NAME_IN_USE,
+	NETWORK_ERROR_WRONG_PASSWORD,
+	NETWORK_ERROR_PLAYER_MISMATCH, // Happens in CLIENT_COMMAND
+	NETWORK_ERROR_KICKED,
+	NETWORK_ERROR_CHEATER,
+	NETWORK_ERROR_FULL,
+};
+
+#endif /* ENABLE_NETWORK */
+#endif /* NETWORK_TYPE_H */
--- a/src/network/network_udp.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/network/network_udp.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -11,11 +11,11 @@
 
 #include "../stdafx.h"
 #include "../debug.h"
-#include "network_data.h"
 #include "../date_func.h"
 #include "../map_func.h"
 #include "network_gamelist.h"
 #include "network_udp.h"
+#include "network_internal.h"
 #include "../variables.h"
 #include "../newgrf_config.h"
 #include "../core/endian_func.hpp"
@@ -23,6 +23,7 @@
 #include "../player_base.h"
 #include "../player_func.h"
 #include "../settings_type.h"
+#include "../rev.h"
 
 #include "core/udp.h"
 
@@ -68,21 +69,36 @@
 DEF_UDP_RECEIVE_COMMAND(Server, PACKET_UDP_CLIENT_FIND_SERVER)
 {
 	// Just a fail-safe.. should never happen
-	if (!_network_udp_server)
+	if (!_network_udp_server) {
 		return;
+	}
+
+	NetworkGameInfo ngi;
+
+	/* Update some game_info */
+	ngi.clients_on     = _network_game_info.clients_on;
+	ngi.start_date     = _network_game_info.start_date;
+
+	ngi.server_lang    = _settings_client.network.server_lang;
+	ngi.use_password   = !StrEmpty(_settings_client.network.server_password);
+	ngi.clients_max    = _settings_client.network.max_clients;
+	ngi.companies_on   = ActivePlayerCount();
+	ngi.companies_max  = _settings_client.network.max_companies;
+	ngi.spectators_on  = NetworkSpectatorCount();
+	ngi.spectators_max = _settings_client.network.max_spectators;
+	ngi.game_date      = _date;
+	ngi.map_width      = MapSizeX();
+	ngi.map_height     = MapSizeY();
+	ngi.map_set        = _settings_game.game_creation.landscape;
+	ngi.dedicated      = _network_dedicated;
+	ngi.grfconfig      = _grfconfig;
+
+	ttd_strlcpy(ngi.map_name, _network_game_info.map_name, lengthof(ngi.map_name));
+	ttd_strlcpy(ngi.server_name, _settings_client.network.server_name, lengthof(ngi.server_name));
+	ttd_strlcpy(ngi.server_revision, _openttd_revision, lengthof(ngi.server_revision));
 
 	Packet packet(PACKET_UDP_SERVER_RESPONSE);
-
-	// Update some game_info
-	_network_game_info.game_date     = _date;
-	_network_game_info.map_width     = MapSizeX();
-	_network_game_info.map_height    = MapSizeY();
-	_network_game_info.map_set       = _settings_game.game_creation.landscape;
-	_network_game_info.companies_on  = ActivePlayerCount();
-	_network_game_info.spectators_on = NetworkSpectatorCount();
-	_network_game_info.grfconfig     = _grfconfig;
-
-	this->Send_NetworkGameInfo(&packet, &_network_game_info);
+	this->Send_NetworkGameInfo(&packet, &ngi);
 
 	// Let the client know that we are here
 	this->SendPacket(&packet, client_addr);
@@ -428,7 +444,7 @@
 		struct sockaddr_in out_addr;
 
 		out_addr.sin_family = AF_INET;
-		out_addr.sin_port = htons(_network_server_port);
+		out_addr.sin_port = htons(_settings_client.network.server_port);
 		out_addr.sin_addr.s_addr = _broadcast_list[i];
 
 		DEBUG(net, 4, "[udp] broadcasting to %s", inet_ntoa(out_addr.sin_addr));
@@ -535,7 +551,7 @@
 	Packet p(PACKET_UDP_SERVER_UNREGISTER);
 	/* Packet is: Version, server_port */
 	p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
-	p.Send_uint16(_network_server_port);
+	p.Send_uint16(_settings_client.network.server_port);
 	_udp_master_socket->SendPacket(&p, &out_addr);
 }
 
@@ -584,7 +600,7 @@
 	/* Packet is: WELCOME_MESSAGE, Version, server_port */
 	p.Send_string(NETWORK_MASTER_SERVER_WELCOME_MESSAGE);
 	p.Send_uint8 (NETWORK_MASTER_SERVER_VERSION);
-	p.Send_uint16(_network_server_port);
+	p.Send_uint16(_settings_client.network.server_port);
 	_udp_master_socket->SendPacket(&p, &out_addr);
 }
 
--- a/src/newgrf.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -1404,7 +1404,7 @@
 				 * date before 1930, as this breaks the build date stuff.
 				 * @see FinaliseHouseArray() for more details.
 				 */
-				if (housespec->min_date < 1930) housespec->min_date = 1930;
+				if (housespec->min_year < 1930) housespec->min_year = 1930;
 
 				_loaded_newgrf_features.has_newhouses = true;
 			} break;
@@ -1415,8 +1415,8 @@
 
 			case 0x0A: { // Availability years
 				uint16 years = grf_load_word(&buf);
-				housespec->min_date = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
-				housespec->max_date = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
+				housespec->min_year = GB(years, 0, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 0, 8);
+				housespec->max_year = GB(years, 8, 8) > 150 ? MAX_YEAR : ORIGINAL_BASE_YEAR + GB(years, 8, 8);
 			} break;
 
 			case 0x0B: // Population
@@ -2906,17 +2906,28 @@
 }
 
 
-static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount, uint8 cidcount, bool wagover)
+static bool IsValidGroupID(uint16 groupid, const char *function)
+{
+	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
+		grfmsg(1, "%s: Spriteset 0x%04X out of range (maximum 0x%02X) or empty, skipping.", function, groupid, _cur_grffile->spritegroups_count - 1);
+		return false;
+	}
+
+	return true;
+}
+
+static void VehicleMapSpriteGroup(byte *buf, byte feature, uint8 idcount)
 {
 	static EngineID *last_engines;
 	static uint last_engines_count;
-
-	if (!wagover) {
-		if (last_engines_count != idcount) {
-			last_engines = ReallocT(last_engines, idcount);
-			last_engines_count = idcount;
-		}
-	} else {
+	bool wagover = false;
+
+	/* Test for 'wagon override' flag */
+	if (HasBit(idcount, 7)) {
+		wagover = true;
+		/* Strip off the flag */
+		idcount = GB(idcount, 0, 7);
+
 		if (last_engines_count == 0) {
 			grfmsg(0, "VehicleMapSpriteGroup: WagonOverride: No engine to do override with");
 			return;
@@ -2924,79 +2935,76 @@
 
 		grfmsg(6, "VehicleMapSpriteGroup: WagonOverride: %u engines, %u wagons",
 				last_engines_count, idcount);
+	} else {
+		if (last_engines_count != idcount) {
+			last_engines = ReallocT(last_engines, idcount);
+			last_engines_count = idcount;
+		}
 	}
 
+	EngineID *engines = (EngineID*)alloca(idcount * sizeof(*engines));
 	for (uint i = 0; i < idcount; i++) {
-		uint8 engine_id = buf[3 + i];
-		EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, engine_id)->index;
-		byte *bp = &buf[4 + idcount];
-
-		grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
-
-		for (uint c = 0; c < cidcount; c++) {
-			uint8 ctype = grf_load_byte(&bp);
-			uint16 groupid = grf_load_word(&bp);
-
-			grfmsg(8, "VehicleMapSpriteGroup: * [%d] Cargo type 0x%X, group id 0x%02X", c, ctype, groupid);
-
-			if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-				grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping", groupid, _cur_grffile->spritegroups_count);
-				continue;
-			}
-
-			ctype = TranslateCargo(feature, ctype);
-			if (ctype == CT_INVALID) continue;
+		engines[i] = GetNewEngine(_cur_grffile, (VehicleType)feature, grf_load_byte(&buf))->index;
+		if (!wagover) last_engines[i] = engines[i];
+	}
+
+	uint8 cidcount = grf_load_byte(&buf);
+	for (uint c = 0; c < cidcount; c++) {
+		uint8 ctype = grf_load_byte(&buf);
+		uint16 groupid = grf_load_word(&buf);
+		if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) continue;
+
+		grfmsg(8, "VehicleMapSpriteGroup: * [%d] Cargo type 0x%X, group id 0x%02X", c, ctype, groupid);
+
+		ctype = TranslateCargo(feature, ctype);
+		if (ctype == CT_INVALID) continue;
+
+		for (uint i = 0; i < idcount; i++) {
+			EngineID engine = engines[i];
+
+			grfmsg(7, "VehicleMapSpriteGroup: [%d] Engine %d...", i, engine);
 
 			if (wagover) {
 				SetWagonOverrideSprites(engine, ctype, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
 			} else {
 				SetCustomEngineSprites(engine, ctype, _cur_grffile->spritegroups[groupid]);
-				last_engines[i] = engine;
 			}
 		}
 	}
 
-	{
-		byte *bp = &buf[4 + idcount + cidcount * 3];
-		uint16 groupid = grf_load_word(&bp);
-
-		grfmsg(8, "-- Default group id 0x%04X", groupid);
-
-		for (uint i = 0; i < idcount; i++) {
-			EngineID engine = GetNewEngine(_cur_grffile, (VehicleType)feature, buf[3 + i])->index;
-
-			/* Don't tell me you don't love duplicated code! */
-			if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-				grfmsg(1, "VehicleMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
-				       groupid, _cur_grffile->spritegroups_count);
-				continue;
-			}
-
-			if (wagover) {
-				SetWagonOverrideSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
-			} else {
-				SetCustomEngineSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid]);
-				SetEngineGRF(engine, _cur_grffile);
-				last_engines[i] = engine;
-			}
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "VehicleMapSpriteGroup")) return;
+
+	grfmsg(8, "-- Default group id 0x%04X", groupid);
+
+	for (uint i = 0; i < idcount; i++) {
+		EngineID engine = engines[i];
+
+		if (wagover) {
+			SetWagonOverrideSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid], last_engines, last_engines_count);
+		} else {
+			SetCustomEngineSprites(engine, CT_DEFAULT, _cur_grffile->spritegroups[groupid]);
+			SetEngineGRF(engine, _cur_grffile);
 		}
 	}
 }
 
 
-static void CanalMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void CanalMapSpriteGroup(byte *buf, uint8 idcount)
 {
-	byte *bp = &buf[4 + idcount + cidcount * 3];
-	uint16 groupid = grf_load_word(&bp);
-
-	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-		grfmsg(1, "CanalMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
-		       groupid, _cur_grffile->spritegroups_count);
-		return;
+	CanalFeature *cfs = (CanalFeature*)alloca(idcount * sizeof(*cfs));
+	for (uint i = 0; i < idcount; i++) {
+		cfs[i] = (CanalFeature)grf_load_byte(&buf);
 	}
 
+	uint8 cidcount = grf_load_byte(&buf);
+	buf += cidcount * 3;
+
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "CanalMapSpriteGroup")) return;
+
 	for (uint i = 0; i < idcount; i++) {
-		CanalFeature cf = (CanalFeature)buf[3 + i];
+		CanalFeature cf = cfs[i];
 
 		if (cf >= CF_END) {
 			grfmsg(1, "CanalMapSpriteGroup: Canal subset %d out of range, skipping", cf);
@@ -3008,77 +3016,69 @@
 }
 
 
-static void StationMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void StationMapSpriteGroup(byte *buf, uint8 idcount)
 {
+	uint8 *stations = (uint8*)alloca(idcount * sizeof(*stations));
 	for (uint i = 0; i < idcount; i++) {
-		uint8 stid = buf[3 + i];
-		StationSpec *statspec = _cur_grffile->stations[stid];
-
-		if (statspec == NULL) {
-			grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stid);
-			return;
-		}
-
-		byte *bp = &buf[4 + idcount];
-
-		for (uint c = 0; c < cidcount; c++) {
-			uint8 ctype = grf_load_byte(&bp);
-			uint16 groupid = grf_load_word(&bp);
-
-			if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-				grfmsg(1, "StationMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
-				       groupid, _cur_grffile->spritegroups_count);
-				continue;
+		stations[i] = grf_load_byte(&buf);
+	}
+
+	uint8 cidcount = grf_load_byte(&buf);
+	for (uint c = 0; c < cidcount; c++) {
+		uint8 ctype = grf_load_byte(&buf);
+		uint16 groupid = grf_load_word(&buf);
+		if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) continue;
+
+		ctype = TranslateCargo(GSF_STATION, ctype);
+		if (ctype == CT_INVALID) continue;
+
+		for (uint i = 0; i < idcount; i++) {
+			StationSpec *statspec = _cur_grffile->stations[stations[i]];
+
+			if (statspec == NULL) {
+				grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
+				return;
 			}
 
-			ctype = TranslateCargo(GSF_STATION, ctype);
-			if (ctype == CT_INVALID) continue;
-
 			statspec->spritegroup[ctype] = _cur_grffile->spritegroups[groupid];
 		}
 	}
 
-	{
-		byte *bp = &buf[4 + idcount + cidcount * 3];
-		uint16 groupid = grf_load_word(&bp);
-
-		if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-			grfmsg(1, "StationMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping",
-			       groupid, _cur_grffile->spritegroups_count);
-			return;
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "StationMapSpriteGroup")) return;
+
+	for (uint i = 0; i < idcount; i++) {
+		StationSpec *statspec = _cur_grffile->stations[stations[i]];
+
+		if (statspec == NULL) {
+			grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stations[i]);
+			continue;
 		}
 
-		for (uint i = 0; i < idcount; i++) {
-			uint8 stid = buf[3 + i];
-			StationSpec *statspec = _cur_grffile->stations[stid];
-			if (statspec == NULL) {
-				grfmsg(1, "StationMapSpriteGroup: Station with ID 0x%02X does not exist, skipping", stid);
-				continue;
-			}
-
-			statspec->spritegroup[CT_DEFAULT] = _cur_grffile->spritegroups[groupid];
-			statspec->grffile = _cur_grffile;
-			statspec->localidx = stid;
-			SetCustomStationSpec(statspec);
-		}
+		statspec->spritegroup[CT_DEFAULT] = _cur_grffile->spritegroups[groupid];
+		statspec->grffile = _cur_grffile;
+		statspec->localidx = stations[i];
+		SetCustomStationSpec(statspec);
 	}
 }
 
 
-static void TownHouseMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void TownHouseMapSpriteGroup(byte *buf, uint8 idcount)
 {
-	byte *bp = &buf[4 + idcount + cidcount * 3];
-	uint16 groupid = grf_load_word(&bp);
-
-	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-		grfmsg(1, "TownHouseMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
-		       groupid, _cur_grffile->spritegroups_count);
-		return;
+	uint8 *houses = (uint8*)alloca(idcount * sizeof(*houses));
+	for (uint i = 0; i < idcount; i++) {
+		houses[i] = grf_load_byte(&buf);
 	}
 
+	/* Skip the cargo type section, we only care about the default group */
+	uint8 cidcount = grf_load_byte(&buf);
+	buf += cidcount * 3;
+
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "TownHouseMapSpriteGroup")) return;
+
 	for (uint i = 0; i < idcount; i++) {
-		uint8 hid = buf[3 + i];
-		HouseSpec *hs = _cur_grffile->housespec[hid];
+		HouseSpec *hs = _cur_grffile->housespec[houses[i]];
 
 		if (hs == NULL) {
 			grfmsg(1, "TownHouseMapSpriteGroup: Too many houses defined, skipping");
@@ -3089,20 +3089,22 @@
 	}
 }
 
-static void IndustryMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void IndustryMapSpriteGroup(byte *buf, uint8 idcount)
 {
-	byte *bp = &buf[4 + idcount + cidcount * 3];
-	uint16 groupid = grf_load_word(&bp);
-
-	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-		grfmsg(1, "IndustryMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
-		       groupid, _cur_grffile->spritegroups_count);
-		return;
+	uint8 *industries = (uint8*)alloca(idcount * sizeof(*industries));
+	for (uint i = 0; i < idcount; i++) {
+		industries[i] = grf_load_byte(&buf);
 	}
 
+	/* Skip the cargo type section, we only care about the default group */
+	uint8 cidcount = grf_load_byte(&buf);
+	buf += cidcount * 3;
+
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "IndustryMapSpriteGroup")) return;
+
 	for (uint i = 0; i < idcount; i++) {
-		uint8 id = buf[3 + i];
-		IndustrySpec *indsp = _cur_grffile->industryspec[id];
+		IndustrySpec *indsp = _cur_grffile->industryspec[industries[i]];
 
 		if (indsp == NULL) {
 			grfmsg(1, "IndustryMapSpriteGroup: Too many industries defined, skipping");
@@ -3113,20 +3115,22 @@
 	}
 }
 
-static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void IndustrytileMapSpriteGroup(byte *buf, uint8 idcount)
 {
-	byte *bp = &buf[4 + idcount + cidcount * 3];
-	uint16 groupid = grf_load_word(&bp);
-
-	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-		grfmsg(1, "IndustrytileMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
-		       groupid, _cur_grffile->spritegroups_count);
-		return;
+	uint8 *indtiles = (uint8*)alloca(idcount * sizeof(*indtiles));
+	for (uint i = 0; i < idcount; i++) {
+		indtiles[i] = grf_load_byte(&buf);
 	}
 
+	/* Skip the cargo type section, we only care about the default group */
+	uint8 cidcount = grf_load_byte(&buf);
+	buf += cidcount * 3;
+
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "IndustrytileMapSpriteGroup")) return;
+
 	for (uint i = 0; i < idcount; i++) {
-		uint8 id = buf[3 + i];
-		IndustryTileSpec *indtsp = _cur_grffile->indtspec[id];
+		IndustryTileSpec *indtsp = _cur_grffile->indtspec[indtiles[i]];
 
 		if (indtsp == NULL) {
 			grfmsg(1, "IndustrytileMapSpriteGroup: Too many industry tiles defined, skipping");
@@ -3137,22 +3141,25 @@
 	}
 }
 
-static void CargoMapSpriteGroup(byte *buf, uint8 idcount, uint8 cidcount)
+static void CargoMapSpriteGroup(byte *buf, uint8 idcount)
 {
-	byte *bp = &buf[4 + idcount + cidcount * 3];
-	uint16 groupid = grf_load_word(&bp);
-
-	if (groupid >= _cur_grffile->spritegroups_count || _cur_grffile->spritegroups[groupid] == NULL) {
-		grfmsg(1, "CargoMapSpriteGroup: Spriteset 0x%04X out of range 0x%X or empty, skipping.",
-		       groupid, _cur_grffile->spritegroups_count);
-		return;
+	CargoID *cargos = (CargoID*)alloca(idcount * sizeof(*cargos));
+	for (uint i = 0; i < idcount; i++) {
+		cargos[i] = grf_load_byte(&buf);
 	}
 
+	/* Skip the cargo type section, we only care about the default group */
+	uint8 cidcount = grf_load_byte(&buf);
+	buf += cidcount * 3;
+
+	uint16 groupid = grf_load_word(&buf);
+	if (!IsValidGroupID(groupid, "CargoMapSpriteGroup")) return;
+
 	for (uint i = 0; i < idcount; i++) {
-		CargoID cid = buf[3 + i];
+		CargoID cid = cargos[i];
 
 		if (cid >= NUM_CARGO) {
-			grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping");
+			grfmsg(1, "CargoMapSpriteGroup: Cargo ID %d out of range, skipping", cid);
 			continue;
 		}
 
@@ -3187,16 +3194,15 @@
 
 	if (!check_length(len, 6, "FeatureMapSpriteGroup")) return;
 
-	uint8 feature = buf[1];
-	uint8 idcount = buf[2] & 0x7F;
-	bool wagover = (buf[2] & 0x80) == 0x80;
-
-	if (!check_length(len, 3 + idcount, "FeatureMapSpriteGroup")) return;
+	buf++;
+	uint8 feature = grf_load_byte(&buf);
+	uint8 idcount = grf_load_byte(&buf);
 
 	/* If idcount is zero, this is a feature callback */
 	if (idcount == 0) {
-		byte *bp = &buf[4];
-		uint16 groupid = grf_load_word(&bp);
+		/* Skip number of cargo ids? */
+		grf_load_byte(&buf);
+		uint16 groupid = grf_load_word(&buf);
 
 		grfmsg(6, "FeatureMapSpriteGroup: Adding generic feature callback for feature %d", feature);
 
@@ -3204,42 +3210,38 @@
 		return;
 	}
 
-	uint8 cidcount = buf[3 + idcount];
-	if (!check_length(len, 4 + idcount + cidcount * 3, "FeatureMapSpriteGroup")) return;
-
-	grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids, %d cids, wagon override %d",
-			feature, idcount, cidcount, wagover);
+	grfmsg(6, "FeatureMapSpriteGroup: Feature %d, %d ids", feature, idcount);
 
 	switch (feature) {
 		case GSF_TRAIN:
 		case GSF_ROAD:
 		case GSF_SHIP:
 		case GSF_AIRCRAFT:
-			VehicleMapSpriteGroup(buf, feature, idcount, cidcount, wagover);
+			VehicleMapSpriteGroup(buf, feature, idcount);
 			return;
 
 		case GSF_CANAL:
-			CanalMapSpriteGroup(buf, idcount, cidcount);
+			CanalMapSpriteGroup(buf, idcount);
 			return;
 
 		case GSF_STATION:
-			StationMapSpriteGroup(buf, idcount, cidcount);
+			StationMapSpriteGroup(buf, idcount);
 			return;
 
 		case GSF_TOWNHOUSE:
-			TownHouseMapSpriteGroup(buf, idcount, cidcount);
+			TownHouseMapSpriteGroup(buf, idcount);
 			return;
 
 		case GSF_INDUSTRIES:
-			IndustryMapSpriteGroup(buf, idcount, cidcount);
+			IndustryMapSpriteGroup(buf, idcount);
 			return;
 
 		case GSF_INDUSTRYTILES:
-			IndustrytileMapSpriteGroup(buf, idcount, cidcount);
+			IndustrytileMapSpriteGroup(buf, idcount);
 			return;
 
 		case GSF_CARGOS:
-			CargoMapSpriteGroup(buf, idcount, cidcount);
+			CargoMapSpriteGroup(buf, idcount);
 			return;
 
 		default:
@@ -3299,7 +3301,7 @@
 			case GSF_ROAD:
 			case GSF_SHIP:
 			case GSF_AIRCRAFT:
-				if (id < GetEnginePoolSize()) {
+				if (!generic) {
 					Engine *e = GetNewEngine(_cur_grffile, (VehicleType)feature, id);
 					StringID string = AddGRFString(_cur_grffile->grfid, e->index, lang, new_scheme, name, e->info.string_id);
 					e->info.string_id = string;
@@ -3462,16 +3464,16 @@
 		/* Special not-TTDP-compatible case used in openttd(d/w).grf
 		 * Missing shore sprites and initialisation of SPR_SHORE_BASE */
 		grfmsg(2, "GraphicsNew: Loading 10 missing shore sprites from openttd(d/w).grf.");
-		LoadNextSprite(       SPR_SHORE_BASE          +  0, _file_index, _nfo_line++); // SLOPE_STEEP_S
-		LoadNextSprite(       SPR_SHORE_BASE          +  5, _file_index, _nfo_line++); // SLOPE_STEEP_W
-		LoadNextSprite(       SPR_SHORE_BASE          +  7, _file_index, _nfo_line++); // SLOPE_WSE
-		LoadNextSprite(       SPR_SHORE_BASE          + 10, _file_index, _nfo_line++); // SLOPE_STEEP_N
-		LoadNextSprite(       SPR_SHORE_BASE          + 11, _file_index, _nfo_line++); // SLOPE_NWS
-		LoadNextSprite(       SPR_SHORE_BASE          + 13, _file_index, _nfo_line++); // SLOPE_ENW
-		LoadNextSprite(       SPR_SHORE_BASE          + 14, _file_index, _nfo_line++); // SLOPE_SEN
-		LoadNextSprite(       SPR_SHORE_BASE          + 15, _file_index, _nfo_line++); // SLOPE_STEEP_E
-		LoadNextSprite(       SPR_SHORE_BASE          + 16, _file_index, _nfo_line++); // SLOPE_EW
-		LoadNextSprite(       SPR_SHORE_BASE          + 17, _file_index, _nfo_line++); // SLOPE_NS
+		LoadNextSprite(SPR_SHORE_BASE +  0, _file_index, _nfo_line++); // SLOPE_STEEP_S
+		LoadNextSprite(SPR_SHORE_BASE +  5, _file_index, _nfo_line++); // SLOPE_STEEP_W
+		LoadNextSprite(SPR_SHORE_BASE +  7, _file_index, _nfo_line++); // SLOPE_WSE
+		LoadNextSprite(SPR_SHORE_BASE + 10, _file_index, _nfo_line++); // SLOPE_STEEP_N
+		LoadNextSprite(SPR_SHORE_BASE + 11, _file_index, _nfo_line++); // SLOPE_NWS
+		LoadNextSprite(SPR_SHORE_BASE + 13, _file_index, _nfo_line++); // SLOPE_ENW
+		LoadNextSprite(SPR_SHORE_BASE + 14, _file_index, _nfo_line++); // SLOPE_SEN
+		LoadNextSprite(SPR_SHORE_BASE + 15, _file_index, _nfo_line++); // SLOPE_STEEP_E
+		LoadNextSprite(SPR_SHORE_BASE + 16, _file_index, _nfo_line++); // SLOPE_EW
+		LoadNextSprite(SPR_SHORE_BASE + 17, _file_index, _nfo_line++); // SLOPE_NS
 		if (_loaded_newgrf_features.shore == SHORE_REPLACE_NONE) _loaded_newgrf_features.shore = SHORE_REPLACE_ONLY_NEW;
 		return;
 	}
@@ -3646,6 +3648,14 @@
 			*value = _settings_game.difficulty.diff_level;
 			return true;
 
+		case 0x23: // long format date
+			*value = _date;
+			return true;
+
+		case 0x24: // long format year
+			*value = _cur_year;
+			return true;
+
 		default: return false;
 	}
 }
@@ -5582,7 +5592,7 @@
 	 * On the other hand, why 1930? Just 'fix' the houses with the lowest
 	 * minimum introduction date to 0.
 	 */
-	Year min_date = MAX_YEAR;
+	Year min_year = MAX_YEAR;
 
 	for (GRFFile *file = _first_grffile; file != NULL; file = file->next) {
 		if (file->housespec == NULL) continue;
@@ -5591,16 +5601,16 @@
 			HouseSpec *hs = file->housespec[i];
 			if (hs != NULL) {
 				_house_mngr.SetEntitySpec(hs);
-				if (hs->min_date < min_date) min_date = hs->min_date;
+				if (hs->min_year < min_year) min_year = hs->min_year;
 			}
 		}
 	}
 
-	if (min_date != 0) {
+	if (min_year != 0) {
 		for (int i = 0; i < HOUSE_MAX; i++) {
 			HouseSpec *hs = GetHouseSpecs(i);
 
-			if (hs->enabled && hs->min_date == min_date) hs->min_date = 0;
+			if (hs->enabled && hs->min_year == min_year) hs->min_year = 0;
 		}
 	}
 }
--- a/src/newgrf_config.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_config.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -8,11 +8,12 @@
 #include "variables.h"
 #include "saveload.h"
 #include "md5.h"
-#include "network/network_data.h"
 #include "newgrf.h"
 #include "newgrf_config.h"
 #include "core/alloc_func.hpp"
 #include "string_func.h"
+#include "gamelog.h"
+#include "network/network_type.h"
 
 #include "fileio.h"
 #include "fios.h"
@@ -231,6 +232,7 @@
 
 				/* Non-found has precedence over compatibility load */
 				if (res != GLC_NOT_FOUND) res = GLC_COMPATIBLE;
+				GamelogGRFCompatible(f);
 				goto compatible_grf;
 			}
 
@@ -238,6 +240,8 @@
 			md5sumToString(buf, lastof(buf), c->md5sum);
 			DEBUG(grf, 0, "NewGRF %08X (%s) not found; checksum %s", BSWAP32(c->grfid), c->filename, buf);
 
+			GamelogGRFRemove(c->grfid);
+
 			c->status = GCS_NOT_FOUND;
 			res = GLC_NOT_FOUND;
 		} else {
--- a/src/newgrf_engine.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_engine.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -476,6 +476,7 @@
 			case 0x43: return _current_player | (LiveryHelper(object->u.vehicle.self_type, NULL) << 24); // Owner information
 			case 0x46: return 0;               // Motion counter
 			case 0x48: return GetEngine(object->u.vehicle.self_type)->flags; // Vehicle Type Info
+			case 0x49: return _cur_year; // 'Long' format build year
 			case 0xC4: return Clamp(_cur_year, ORIGINAL_BASE_YEAR, ORIGINAL_MAX_YEAR) - ORIGINAL_BASE_YEAR; // Build year
 			case 0xDA: return INVALID_VEHICLE; // Next vehicle
 			case 0x7F: return GetGRFParameter(object->u.vehicle.self_type, parameter); // Read GRF parameter
@@ -616,6 +617,7 @@
 		}
 
 		case 0x48: return GetEngine(v->engine_type)->flags; // Vehicle Type Info
+		case 0x49: return v->build_year;
 
 		/* Variables which use the parameter */
 		case 0x60: // Count consist's engine ID occurance
@@ -886,23 +888,19 @@
 
 SpriteID GetRotorOverrideSprite(EngineID engine, const Vehicle *v, bool info_view)
 {
-	#if !defined(NDEBUG) || defined(WITH_ASSERT)
 	const Engine *e = GetEngine(engine);
-	#endif /* !defined(NDEBUG) || defined(WITH_ASSERT) */
-
-	const SpriteGroup *group;
-	ResolverObject object;
-
-	assert(e->type == VEH_AIRCRAFT);
 
 	/* Only valid for helicopters */
+	assert(e->type == VEH_AIRCRAFT);
 	assert(!(e->u.air.subtype & AIR_CTOL));
 
+	ResolverObject object;
+
 	NewVehicleResolver(&object, engine, v);
 
 	object.info_view = info_view;
 
-	group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
+	const SpriteGroup *group = GetWagonOverrideSpriteSet(engine, CT_DEFAULT, engine);
 	group = Resolve(group, &object);
 
 	if (group == NULL || group->type != SGT_RESULT) return 0;
--- a/src/newgrf_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/newgrf_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -15,6 +15,7 @@
 #include "core/alloc_func.hpp"
 #include "string_func.h"
 #include "gfx_func.h"
+#include "gamelog.h"
 
 #include "table/strings.h"
 #include "table/sprites.h"
@@ -564,8 +565,11 @@
 		GRFConfig *c;
 		int i = 0;
 
+		GamelogStartAction(GLAT_GRF);
+		GamelogGRFUpdate(_grfconfig, nw->list); // log GRF changes
 		CopyGRFConfigList(nw->orig_list, nw->list, false);
 		ReloadNewGRFData();
+		GamelogStopAction();
 
 		/* Show new, updated list */
 		for (c = nw->list; c != NULL && c != nw->sel; c = c->next, i++) {}
--- a/src/news_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/news_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -168,9 +168,11 @@
 struct NewsWindow : Window {
 	uint16 chat_height;
 	NewsItem *ni;
+	static uint duration;
 
 	NewsWindow(const WindowDesc *desc, NewsItem *ni) : Window(desc), ni(ni)
 	{
+		NewsWindow::duration = 555;
 		const Window *w = FindWindowById(WC_SEND_NETWORK_MSG, 0);
 		this->chat_height = (w != NULL) ? w->height : 0;
 
@@ -258,7 +260,7 @@
 	{
 		switch (widget) {
 			case 1:
-				this->ni->duration = 0;
+				NewsWindow::duration = 0;
 				delete this;
 				_forced_news = NULL;
 				break;
@@ -314,6 +316,8 @@
 	}
 };
 
+/* static */ uint NewsWindow::duration; ///< Remaining time for showing current news message
+
 
 static const Widget _news_type13_widgets[] = {
 {      WWT_PANEL,   RESIZE_NONE,    15,     0,   429,     0,   169, 0x0, STR_NULL},
@@ -360,9 +364,6 @@
 /** Open up an own newspaper window for the news item */
 static void ShowNewspaper(NewsItem *ni)
 {
-	ni->flags &= ~NF_FORCE_BIG;
-	ni->duration = 555;
-
 	SoundFx sound = _news_type_data[_news_subtype_data[ni->subtype].type].sound;
 	if (sound != 0) SndPlayFx(sound);
 
@@ -438,10 +439,10 @@
 	if (IsNewsTickerShown()) return false;
 
 	/* Newspaper message, decrement duration counter */
-	if (ni->duration != 0) ni->duration--;
+	if (NewsWindow::duration != 0) NewsWindow::duration--;
 
 	/* neither newsticker nor newspaper are running */
-	return (ni->duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
+	return (NewsWindow::duration == 0 || FindWindowById(WC_NEWS_WINDOW, 0) == NULL);
 }
 
 /** Move to the next news item */
@@ -465,12 +466,9 @@
 				InvalidateWindowData(WC_STATUS_BAR, 0, SBI_SHOW_REMINDER);
 				break;
 
-			case ND_SUMMARY: // Summary - show ticker, but if forced big, cascade to full
-				if (!(ni->flags & NF_FORCE_BIG)) {
-					ShowTicker(ni);
-					break;
-				}
-				/* Fallthrough */
+			case ND_SUMMARY: // Summary - show ticker
+				ShowTicker(ni);
+				break;
 
 			case ND_FULL: // Full - show newspaper
 				ShowNewspaper(ni);
@@ -613,8 +611,6 @@
 	_forced_news = ni;
 
 	if (_forced_news != NULL) {
-		ni->duration = 555;
-		ni->flags |= NF_FORCE_BIG;
 		DeleteWindowById(WC_NEWS_WINDOW, 0);
 		ShowNewspaper(ni);
 	}
--- a/src/news_type.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/news_type.h	Wed Jun 04 22:34:45 2008 +0000
@@ -74,7 +74,6 @@
 	NF_VIEWPORT  = (1 << 1), ///< Does the news message have a viewport? (ingame picture of happening)
 	NF_TILE      = (1 << 2), ///< When clicked on the news message scroll to a given tile? Tile is in data_a
 	NF_VEHICLE   = (1 << 3), ///< When clicked on the message scroll to the vehicle? VehicleID is in data_a
-	NF_FORCE_BIG = (1 << 4), ///< Force the appearance of a news message if it has already been shown (internal)
 	NF_INCOLOR   = (1 << 5), ///< Show the newsmessage in colour, otherwise it defaults to black & white
 	NF_TILE2     = (1 << 6), ///< There is a second tile to scroll to; tile is in data_b
 };
@@ -104,7 +103,6 @@
 	NewsItem *prev;        ///< Previous news item
 	NewsItem *next;        ///< Next news item
 	StringID string_id;    ///< Message text
-	uint16 duration;       ///< Remaining time for showing this news message
 	Date date;             ///< Date of the news
 	NewsSubtype subtype;   ///< News subtype @see NewsSubtype
 	NewsFlag flags;        ///< NewsFlags bits @see NewsFlag
--- a/src/openttd.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/openttd.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -6,7 +6,6 @@
 
 #define VARDEF
 #include "variables.h"
-#include "network/network_internal.h"
 #undef VARDEF
 
 #include "openttd.h"
@@ -41,6 +40,7 @@
 #include "console_func.h"
 #include "screenshot.h"
 #include "network/network.h"
+#include "network/network_func.h"
 #include "signs_base.h"
 #include "signs_func.h"
 #include "waypoint.h"
@@ -54,6 +54,7 @@
 #include "strings_func.h"
 #include "date_func.h"
 #include "vehicle_func.h"
+#include "gamelog.h"
 #include "cheat_func.h"
 #include "animated_tile_func.h"
 #include "functions.h"
@@ -311,6 +312,7 @@
 	UnInitializeAirports();
 
 	/* Uninitialize variables that are allocated dynamically */
+	GamelogReset();
 	_Town_pool.CleanPool();
 	_Industry_pool.CleanPool();
 	_Station_pool.CleanPool();
@@ -495,8 +497,8 @@
 	if (_cur_resolution[1] == 0) _cur_resolution[1] = 1;
 
 #if defined(ENABLE_NETWORK)
-	if (dedicated_host) snprintf(_network_server_bind_ip_host, NETWORK_HOSTNAME_LENGTH, "%s", dedicated_host);
-	if (dedicated_port) _network_server_port = dedicated_port;
+	if (dedicated_host) snprintf(_settings_client.network.server_bind_ip, sizeof(_settings_client.network.server_bind_ip), "%s", dedicated_host);
+	if (dedicated_port) _settings_client.network.server_port = dedicated_port;
 	if (_dedicated_forks && !dedicated) _dedicated_forks = false;
 #endif /* ENABLE_NETWORK */
 
@@ -690,8 +692,8 @@
 #ifdef ENABLE_NETWORK
 	/* We are the server, we start a new player (not dedicated),
 	 * so set the default password *if* needed. */
-	if (_network_server && !StrEmpty(_network_default_company_pass)) {
-		char *password = _network_default_company_pass;
+	if (_network_server && !StrEmpty(_settings_client.network.default_company_pass)) {
+		char *password = _settings_client.network.default_company_pass;
 		NetworkChangeCompanyPassword(1, &password);
 	}
 #endif /* ENABLE_NETWORK */
@@ -820,10 +822,8 @@
 		if (_networking) {
 			if (_network_server && (new_mode == SM_LOAD || new_mode == SM_NEWGAME)) {
 				NetworkReboot();
-				NetworkUDPCloseAll();
 			} else {
 				NetworkDisconnect();
-				NetworkUDPCloseAll();
 			}
 		}
 
@@ -832,7 +832,7 @@
 			/* But not if we are going to the menu */
 			if (new_mode != SM_MENU) {
 				/* check if we should reload the config */
-				if (_network_reload_cfg) {
+				if (_settings_client.network.reload_cfg) {
 					LoadFromConfig();
 					_settings_game = _settings_newgame;
 					ResetGRFConfig(false);
@@ -1113,7 +1113,7 @@
 		if (_network_reconnect > 0 && --_network_reconnect == 0) {
 			/* This means that we want to reconnect to the last host
 			 * We do this here, because it means that the network is really closed */
-			NetworkClientConnectGame(_network_last_host, _network_last_port);
+			NetworkClientConnectGame(_settings_client.network.last_host, _settings_client.network.last_port);
 		}
 		/* Singleplayer */
 		StateGameLoop();
@@ -1270,6 +1270,13 @@
 	TileIndex map_size = MapSize();
 	Player *p;
 
+	if (CheckSavegameVersion(98)) GamelogOldver();
+
+	GamelogTestRevision();
+	GamelogTestMode();
+
+	if (CheckSavegameVersion(98)) GamelogGRFAddList(_grfconfig);
+
 	/* in version 2.1 of the savegame, town owner was unified. */
 	if (CheckSavegameVersionOldStyle(2, 1)) ConvertTownOwner();
 
@@ -2433,6 +2440,8 @@
 		}
 	}
 
+	if (_debug_gamelog_level > 0) GamelogPrintDebug();
+
 	return InitializeWindowsAndCaches();
 }
 
--- a/src/openttd.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/openttd.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,10 +5,6 @@
 #ifndef OPENTTD_H
 #define OPENTTD_H
 
-#ifndef VARDEF
-#define VARDEF extern
-#endif
-
 enum GameModes {
 	GM_MENU,
 	GM_NORMAL,
--- a/src/order_cmd.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/order_cmd.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -1613,6 +1613,95 @@
 }
 
 /**
+ * Process a conditional order and determine the next order.
+ * @param order the order the vehicle currently has
+ * @param v the vehicle to update
+ * @return index of next order to jump to, or INVALID_VEH_ORDER_ID to use the next order
+ */
+static VehicleOrderID ProcessConditionalOrder(const Order *order, const Vehicle *v)
+{
+	if (order->GetType() != OT_CONDITIONAL) return INVALID_VEH_ORDER_ID;
+
+	bool skip_order = false;
+	OrderConditionComparator occ = order->GetConditionComparator();
+	uint16 value = order->GetConditionValue();
+
+	switch (order->GetConditionVariable()) {
+		case OCV_LOAD_PERCENTAGE:  skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
+		case OCV_RELIABILITY:      skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16,        value); break;
+		case OCV_MAX_SPEED:        skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(),           value); break;
+		case OCV_AGE:              skip_order = OrderConditionCompare(occ, v->age / 366,                      value); break;
+		case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(),               value); break;
+		case OCV_UNCONDITIONALLY:  skip_order = true; break;
+		default: NOT_REACHED();
+	}
+
+	return skip_order ? order->GetConditionSkipToOrder() : (VehicleOrderID)INVALID_VEH_ORDER_ID;
+}
+
+/**
+ * Update the vehicle's destination tile from an order.
+ * @param order the order the vehicle currently has
+ * @param v the vehicle to update
+ */
+static bool UpdateOrderDest(Vehicle *v, const Order *order)
+{
+	switch (order->GetType()) {
+		case OT_GOTO_STATION:
+			v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
+			break;
+
+		case OT_GOTO_DEPOT:
+			if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
+				/* We need to search for the nearest depot (hangar). */
+				TileIndex location;
+				DestinationID destination;
+				bool reverse;
+
+				if (v->FindClosestDepot(&location, &destination, &reverse)) {
+					v->dest_tile = location;
+					v->current_order.MakeGoToDepot(destination, ODTFB_PART_OF_ORDERS);
+
+					/* If there is no depot in front, reverse automatically (trains only) */
+					if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
+
+					if (v->type == VEH_AIRCRAFT && v->u.air.state == FLYING && v->u.air.targetairport != destination) {
+						/* The aircraft is now heading for a different hangar than the next in the orders */
+						extern void AircraftNextAirportPos_and_Order(Vehicle *v);
+						AircraftNextAirportPos_and_Order(v);
+					}
+				} else {
+					UpdateVehicleTimetable(v, true);
+					v->cur_order_index++;
+				}
+			} else if (v->type != VEH_AIRCRAFT) {
+				v->dest_tile = GetDepot(order->GetDestination())->xy;
+			}
+			break;
+
+		case OT_GOTO_WAYPOINT:
+			v->dest_tile = GetWaypoint(order->GetDestination())->xy;
+			break;
+
+		case OT_CONDITIONAL: {
+			VehicleOrderID next_order = ProcessConditionalOrder(order, v);
+			UpdateVehicleTimetable(v, true);
+			if (next_order != INVALID_VEH_ORDER_ID) {
+				v->cur_order_index = next_order;
+			} else {
+				v->cur_order_index++;
+			}
+			return false;
+		}
+
+		default:
+			v->dest_tile = 0;
+			return false;
+	}
+	return true;
+}
+
+/**
  * Handle the orders of a vehicle and determine the next place
  * to go to if needed.
  * @param v the vehicle to do this for.
@@ -1710,71 +1799,7 @@
 			break;
 	}
 
-	switch (order->GetType()) {
-		case OT_GOTO_STATION:
-			v->dest_tile = v->GetOrderStationLocation(order->GetDestination());
-			break;
-
-		case OT_GOTO_DEPOT:
-			if (v->current_order.GetDepotActionType() & ODATFB_NEAREST_DEPOT) {
-				/* We need to search for the nearest depot (hangar). */
-				TileIndex location;
-				DestinationID destination;
-				bool reverse;
-
-				if (v->FindClosestDepot(&location, &destination, &reverse)) {
-					v->dest_tile = location;
-					v->current_order.MakeGoToDepot(destination, ODTFB_PART_OF_ORDERS);
-
-					/* If there is no depot in front, reverse automatically (trains only) */
-					if (v->type == VEH_TRAIN && reverse) DoCommand(v->tile, v->index, 0, DC_EXEC, CMD_REVERSE_TRAIN_DIRECTION);
-
-					if (v->type == VEH_AIRCRAFT && v->u.air.state == FLYING && v->u.air.targetairport != destination) {
-						/* The aircraft is now heading for a different hangar than the next in the orders */
-						extern void AircraftNextAirportPos_and_Order(Vehicle *v);
-						AircraftNextAirportPos_and_Order(v);
-					}
-				} else {
-					UpdateVehicleTimetable(v, true);
-					v->cur_order_index++;
-				}
-			} else if (v->type != VEH_AIRCRAFT) {
-				v->dest_tile = GetDepot(order->GetDestination())->xy;
-			}
-			break;
-
-		case OT_GOTO_WAYPOINT:
-			v->dest_tile = GetWaypoint(order->GetDestination())->xy;
-			break;
-
-		case OT_CONDITIONAL: {
-			bool skip_order = false;
-			OrderConditionComparator occ = order->GetConditionComparator();
-			uint16 value = order->GetConditionValue();
-
-			switch (order->GetConditionVariable()) {
-				case OCV_LOAD_PERCENTAGE:  skip_order = OrderConditionCompare(occ, CalcPercentVehicleFilled(v, NULL), value); break;
-				case OCV_RELIABILITY:      skip_order = OrderConditionCompare(occ, v->reliability * 100 >> 16,        value); break;
-				case OCV_MAX_SPEED:        skip_order = OrderConditionCompare(occ, v->GetDisplayMaxSpeed(),           value); break;
-				case OCV_AGE:              skip_order = OrderConditionCompare(occ, v->age / 366,                      value); break;
-				case OCV_REQUIRES_SERVICE: skip_order = OrderConditionCompare(occ, v->NeedsServicing(),               value); break;
-				case OCV_UNCONDITIONALLY:  skip_order = true; break;
-				default: NOT_REACHED();
-			}
-			UpdateVehicleTimetable(v, true);
-			if (skip_order) {
-				v->cur_order_index = order->GetConditionSkipToOrder();
-			} else {
-				v->cur_order_index++;
-			}
-		} return false;
-
-		default:
-			v->dest_tile = 0;
-			return false;
-	}
-
-	return may_reverse;
+	return UpdateOrderDest(v, order) && may_reverse;
 }
 
 /**
--- a/src/os2.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/os2.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -67,7 +67,7 @@
 #endif
 
 		if (disk == disk2) {
-			FiosItem *fios = FiosAlloc();
+			FiosItem *fios = _fios_items.Append();
 			fios->type = FIOS_TYPE_DRIVE;
 			fios->mtime = 0;
 #ifndef __INNOTEK_LIBC__
--- a/src/ottdres.rc.in	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/ottdres.rc.in	Wed Jun 04 22:34:45 2008 +0000
@@ -65,8 +65,8 @@
 //
 
 VS_VERSION_INFO VERSIONINFO
- FILEVERSION 0,6,0,@@REVISION@@
- PRODUCTVERSION 0,6,0,@@REVISION@@
+ FILEVERSION 0,7,0,@@REVISION@@
+ PRODUCTVERSION 0,7,0,@@REVISION@@
  FILEFLAGSMASK 0x3fL
 #ifdef _DEBUG
  FILEFLAGS 0x1L
--- a/src/player_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/player_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -13,14 +13,12 @@
 #include "player_base.h"
 #include "command_func.h"
 #include "network/network.h"
+#include "network/network_gui.h"
 #include "variables.h"
 #include "roadveh.h"
 #include "train.h"
 #include "aircraft.h"
 #include "newgrf.h"
-#include "network/network_data.h"
-#include "network/network_client.h"
-#include "network/network_gui.h"
 #include "player_face.h"
 #include "strings_func.h"
 #include "functions.h"
--- a/src/players.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/players.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -13,7 +13,7 @@
 #include "saveload.h"
 #include "command_func.h"
 #include "network/network.h"
-#include "network/network_internal.h"
+#include "network/network_func.h"
 #include "variables.h"
 #include "cheat_func.h"
 #include "ai/ai.h"
@@ -863,8 +863,8 @@
 			assert(_local_player == PLAYER_SPECTATOR);
 			SetLocalPlayer(p->index);
 #ifdef ENABLE_NETWORK
-			if (!StrEmpty(_network_default_company_pass)) {
-				char *password = _network_default_company_pass;
+			if (!StrEmpty(_settings_client.network.default_company_pass)) {
+				char *password = _settings_client.network.default_company_pass;
 				NetworkChangeCompanyPassword(1, &password);
 			}
 #endif /* ENABLE_NETWORK */
--- a/src/rail_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rail_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -1649,7 +1649,7 @@
 {      WWT_PANEL,   RESIZE_NONE,     7,   207,   272,    17,    76, 0x0,          STR_WAYPOINT_GRAPHICS_TIP},        // BRWW_WAYPOINT_4
 {      WWT_PANEL,   RESIZE_NONE,     7,   275,   340,    17,    76, 0x0,          STR_WAYPOINT_GRAPHICS_TIP},        // BRWW_WAYPOINT_5
 
-{ WWT_HSCROLLBAR,   RESIZE_NONE,    7,     1,   343,     80,    91, 0x0,          STR_0190_SCROLL_BAR_SCROLLS_LIST}, // BRWW_SCROLL
+{ WWT_HSCROLLBAR,   RESIZE_NONE,    7,     1,   343,     80,    91, 0x0,          STR_HSCROLL_BAR_SCROLLS_LIST},     // BRWW_SCROLL
 {    WIDGETS_END},
 };
 
--- a/src/rev.cpp.in	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rev.cpp.in	Wed Jun 04 22:34:45 2008 +0000
@@ -23,6 +23,16 @@
 const char _openttd_revision[] = "@@VERSION@@";
 
 /**
+ * Let us know if current build was modified. This detection
+ * works even in the case when revision string is overriden by
+ * --revision argument.
+ * Value 0 means no modification, 1 is for unknown state
+ * (compiling from sources without any version control software)
+ * and 2 is for modified revision.
+ */
+const byte _openttd_revision_modified = @@MODIFIED@@;
+
+/**
  * The NewGRF revision of OTTD:
  * bits  meaning.
  * 28-31 major version
--- a/src/rev.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/rev.h	Wed Jun 04 22:34:45 2008 +0000
@@ -6,6 +6,7 @@
 #define REV_H
 
 extern const char _openttd_revision[];
+extern const byte _openttd_revision_modified;
 extern const uint32 _openttd_newgrf_version;
 
 #endif /* REV_H */
--- a/src/road_cmd.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/road_cmd.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -69,7 +69,7 @@
 
 	if (flags & DC_EXEC) {
 		if (_game_mode == GM_MENU) {
-			_settings_game.vehicle.road_side = p1;
+			_settings_newgame.vehicle.road_side = p1;
 		} else {
 			_settings_game.vehicle.road_side = p1;
 		}
--- a/src/saveload.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/saveload.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -32,10 +32,11 @@
 #include "autoreplace_base.h"
 #include "statusbar_gui.h"
 #include <list>
+#include "gamelog.h"
 
 #include "table/strings.h"
 
-extern const uint16 SAVEGAME_VERSION = 97;
+extern const uint16 SAVEGAME_VERSION = 98;
 
 SavegameType _savegame_type; ///< type of savegame we are loading
 
@@ -651,10 +652,18 @@
 	/* NOTICE - handle some buggy stuff, in really old versions everything was saved
 	 * as a byte-type. So detect this, and adjust array size accordingly */
 	if (!_sl.save && _sl_version == 0) {
+		/* all arrays except difficulty settings */
 		if (conv == SLE_INT16 || conv == SLE_UINT16 || conv == SLE_STRINGID ||
 				conv == SLE_INT32 || conv == SLE_UINT32) {
-			length *= SlCalcConvFileLen(conv);
-			conv = SLE_INT8;
+			SlCopyBytes(array, length * SlCalcConvFileLen(conv));
+			return;
+		}
+		/* used for conversion of Money 32bit->64bit */
+		if (conv == (SLE_FILE_I32 | SLE_VAR_I64)) {
+			for (uint i = 0; i < length; i++) {
+				((int64*)array)[i] = (int32)BSWAP32(SlReadUint32());
+			}
+			return;
 		}
 	}
 
@@ -757,7 +766,7 @@
  * @param sld The SaveLoad description of the object so we know how to manipulate it
  * @return size of given objetc
  */
-static size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
+size_t SlCalcObjLength(const void *object, const SaveLoad *sld)
 {
 	size_t length = 0;
 
@@ -1278,6 +1287,7 @@
  *******************************************/
 
 /* these define the chunks */
+extern const ChunkHandler _gamelog_chunk_handlers[];
 extern const ChunkHandler _misc_chunk_handlers[];
 extern const ChunkHandler _name_chunk_handlers[];
 extern const ChunkHandler _cheat_chunk_handlers[] ;
@@ -1299,6 +1309,7 @@
 extern const ChunkHandler _cargopacket_chunk_handlers[];
 
 static const ChunkHandler * const _chunk_handlers[] = {
+	_gamelog_chunk_handlers,
 	_misc_chunk_handlers,
 	_name_chunk_handlers,
 	_cheat_chunk_handlers,
@@ -1635,10 +1646,16 @@
 	/* Load a TTDLX or TTDPatch game */
 	if (mode == SL_OLD_LOAD) {
 		InitializeGame(256, 256, true); // set a mapsize of 256x256 for TTDPatch games or it might get confused
+		GamelogReset();
 		if (!LoadOldSaveGame(filename)) return SL_REINIT;
 		_sl_version = 0;
 		_sl_minor_version = 0;
-		if (!AfterLoadGame()) return SL_REINIT;
+		GamelogStartAction(GLAT_LOAD);
+		if (!AfterLoadGame()) {
+			GamelogStopAction();
+			return SL_REINIT;
+		}
+		GamelogStopAction();
 		return SL_OK;
 	}
 
@@ -1749,15 +1766,24 @@
 			 * confuse old games */
 			InitializeGame(256, 256, true);
 
+			GamelogReset();
+
 			SlLoadChunks();
 			fmt->uninit_read();
 			fclose(_sl.fh);
 
+			GamelogStartAction(GLAT_LOAD);
+
 			_savegame_type = SGT_OTTD;
 
 			/* After loading fix up savegame for any internal changes that
 			 * might've occured since then. If it fails, load back the old game */
-			if (!AfterLoadGame()) return SL_REINIT;
+			if (!AfterLoadGame()) {
+				GamelogStopAction();
+				return SL_REINIT;
+			}
+
+			GamelogStopAction();
 		}
 
 		return SL_OK;
--- a/src/saveload.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/saveload.h	Wed Jun 04 22:34:45 2008 +0000
@@ -318,6 +318,7 @@
 size_t SlGetFieldLength();
 void SlSetLength(size_t length);
 size_t SlCalcObjMemberLength(const void *object, const SaveLoad *sld);
+size_t SlCalcObjLength(const void *object, const SaveLoad *sld);
 
 byte SlReadByte();
 void SlWriteByte(byte b);
--- a/src/settings.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,7 @@
 #include "screenshot.h"
 #include "variables.h"
 #include "network/network.h"
-#include "network/network_internal.h"
+#include "network/network_func.h"
 #include "settings_internal.h"
 #include "command_func.h"
 #include "console_func.h"
@@ -60,6 +60,7 @@
 #include "sound/sound_driver.hpp"
 #include "music/music_driver.hpp"
 #include "blitter/factory.hpp"
+#include "gamelog.h"
 #include "station_func.h"
 
 #include "table/strings.h"
@@ -1124,27 +1125,27 @@
 
 
 #define SDTC_CONDVAR(var, type, from, to, flags, guiflags, def, min, max, interval, str, proc)\
-	SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 0, def, min, max, interval, NULL, str, proc, from, to)
+	SDTG_GENERAL(#var, SDT_NUMX, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, min, max, interval, NULL, str, proc, from, to)
 #define SDTC_VAR(var, type, flags, guiflags, def, min, max, interval, str, proc)\
 	SDTC_CONDVAR(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, min, max, interval, str, proc)
 
 #define SDTC_CONDBOOL(var, from, to, flags, guiflags, def, str, proc)\
-	SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 0, def, 0, 1, 0, NULL, str, proc, from, to)
+	SDTG_GENERAL(#var, SDT_BOOLX, SL_VAR, SLE_BOOL, flags, guiflags, _settings_client.var, 1, def, 0, 1, 0, NULL, str, proc, from, to)
 #define SDTC_BOOL(var, flags, guiflags, def, str, proc)\
 	SDTC_CONDBOOL(var, 0, SL_MAX_VERSION, flags, guiflags, def, str, proc)
 
 #define SDTC_CONDLIST(var, type, length, flags, guiflags, def, str, proc, from, to)\
 	SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
 #define SDTC_LIST(var, type, flags, guiflags, def, str, proc)\
-	SDTG_GENERAL(var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+	SDTG_GENERAL(#var, SDT_INTLIST, SL_ARR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
 
 #define SDTC_CONDSTR(var, type, length, flags, guiflags, def, str, proc, from, to)\
 	SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, length, def, 0, 0, 0, NULL, str, proc, from, to)
 #define SDTC_STR(var, type, flags, guiflags, def, str, proc)\
-	SDTG_GENERAL(var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
+	SDTG_GENERAL(#var, SDT_STRING, SL_STR, type, flags, guiflags, _settings_client.var, lengthof(_settings_client.var), def, 0, 0, 0, NULL, str, proc, 0, SL_MAX_VERSION)
 
 #define SDTC_CONDOMANY(var, type, from, to, flags, guiflags, def, max, full, str, proc)\
-	SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 0, def, 0, max, 0, full, str, proc, from, to)
+	SDTG_GENERAL(#var, SDT_ONEOFMANY, SL_VAR, type, flags, guiflags, _settings_client.var, 1, def, 0, max, 0, full, str, proc, from, to)
 #define SDTC_OMANY(var, type, flags, guiflags, def, max, full, str, proc)\
 	SDTC_CONDOMANY(var, type, 0, SL_MAX_VERSION, flags, guiflags, def, max, full, str, proc)
 
@@ -1427,6 +1428,41 @@
 	return 0;
 }
 
+#ifdef ENABLE_NETWORK
+
+static int32 UpdateMinPlayers(int32 p1)
+{
+	CheckMinPlayers();
+	return 0;
+}
+
+static int32 UpdatePlayerName(int32 p1)
+{
+	NetworkUpdatePlayerName();
+	return 0;
+}
+
+static int32 UpdateServerPassword(int32 p1)
+{
+	if (strcmp(_settings_client.network.server_password, "*") == 0) {
+		_settings_client.network.server_password[0] = '\0';
+	}
+
+	return 0;
+}
+
+static int32 UpdateRconPassword(int32 p1)
+{
+	if (strcmp(_settings_client.network.rcon_password, "*") == 0) {
+		_settings_client.network.rcon_password[0] = '\0';
+	}
+
+	return 0;
+}
+
+#endif /* ENABLE_NETWORK */
+
+
 /* End - Callback Functions */
 
 #ifndef EXTERNAL_PLAYER
@@ -1493,39 +1529,6 @@
 	  SDTG_END()
 };
 
-#ifdef ENABLE_NETWORK
-static const SettingDescGlobVarList _network_settings[] = {
-	  SDTG_VAR("sync_freq",           SLE_UINT16,C|S,0, _network_sync_freq,            100, 0,   100,   0, STR_NULL, NULL),
-	  SDTG_VAR("frame_freq",           SLE_UINT8,C|S,0, _network_frame_freq,             0, 0,   100,   0, STR_NULL, NULL),
-	  SDTG_VAR("max_join_time",       SLE_UINT16, S, 0, _network_max_join_time,        500, 0, 32000,   0, STR_NULL, NULL),
-	 SDTG_BOOL("pause_on_join",                   S, 0, _network_pause_on_join,        true,               STR_NULL, NULL),
-	  SDTG_STR("server_bind_ip",        SLE_STRB, S, 0, _network_server_bind_ip_host,  "0.0.0.0",          STR_NULL, NULL),
-	  SDTG_VAR("server_port",         SLE_UINT16, S, 0, _network_server_port,          NETWORK_DEFAULT_PORT, 0, 65535, 0, STR_NULL, NULL),
-	 SDTG_BOOL("server_advertise",                S, 0, _network_advertise,            false,              STR_NULL, NULL),
-	  SDTG_VAR("lan_internet",         SLE_UINT8, S, 0, _network_lan_internet,           0, 0,     1,   0, STR_NULL, NULL),
-	  SDTG_STR("player_name",           SLE_STRB, S, 0, _network_player_name,          NULL,               STR_NULL, NULL),
-	  SDTG_STR("server_password",       SLE_STRB, S, 0, _network_server_password,      NULL,               STR_NULL, NULL),
-	  SDTG_STR("rcon_password",         SLE_STRB, S, 0, _network_rcon_password,        NULL,               STR_NULL, NULL),
-	  SDTG_STR("default_company_pass",  SLE_STRB, S, 0, _network_default_company_pass, NULL,               STR_NULL, NULL),
-	  SDTG_STR("server_name",           SLE_STRB, S, 0, _network_server_name,          NULL,               STR_NULL, NULL),
-	  SDTG_STR("connect_to_ip",         SLE_STRB, S, 0, _network_default_ip,           NULL,               STR_NULL, NULL),
-	  SDTG_STR("network_id",            SLE_STRB, S, 0, _network_unique_id,            NULL,               STR_NULL, NULL),
-	 SDTG_BOOL("autoclean_companies",             S, 0, _network_autoclean_companies,  false,              STR_NULL, NULL),
-	  SDTG_VAR("autoclean_unprotected",SLE_UINT8, S, 0, _network_autoclean_unprotected,12, 0,     60,   0, STR_NULL, NULL),
-	  SDTG_VAR("autoclean_protected",  SLE_UINT8, S, 0, _network_autoclean_protected,  36, 0,    180,   0, STR_NULL, NULL),
-	  SDTG_VAR("max_companies",        SLE_UINT8, S, 0, _network_game_info.companies_max,   8, 1, MAX_PLAYERS, 0, STR_NULL, NULL),
-	  SDTG_VAR("max_clients",          SLE_UINT8, S, 0, _network_game_info.clients_max,    10, 2, MAX_CLIENTS, 0, STR_NULL, NULL),
-	  SDTG_VAR("max_spectators",       SLE_UINT8, S, 0, _network_game_info.spectators_max, 10, 0, MAX_CLIENTS, 0, STR_NULL, NULL),
-	  SDTG_VAR("restart_game_year",    SLE_INT32, S,D0, _network_restart_game_year,    0, MIN_YEAR, MAX_YEAR, 1, STR_NULL, NULL),
-	  SDTG_VAR("min_players",          SLE_UINT8, S, 0, _network_min_players,               0, 0, 10,   0, STR_NULL, NULL),
-	SDTG_OMANY("server_lang",          SLE_UINT8, S, 0, _network_game_info.server_lang,     0, 35, "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN", STR_NULL, NULL),
-	 SDTG_BOOL("reload_cfg",                      S, 0, _network_reload_cfg,           false,              STR_NULL, NULL),
-	  SDTG_STR("last_host",             SLE_STRB, S, 0, _network_last_host,            "0.0.0.0",          STR_NULL, NULL),
-	  SDTG_VAR("last_port",           SLE_UINT16, S, 0, _network_last_port,            0, 0, UINT16_MAX, 0, STR_NULL ,NULL),
-	  SDTG_END()
-};
-#endif /* ENABLE_NETWORK */
-
 static const uint GAME_DIFFICULTY_NUM = 18;
 uint16 _old_diff_custom[GAME_DIFFICULTY_NUM];
 
@@ -1549,7 +1552,7 @@
 	    SDT_OMANY(GameSettings, game_creation.town_name,  SLE_UINT8,                     0, 0, 0, 255, "english|french|german|american|latin|silly|swedish|dutch|finnish|polish|slovakish|norwegian|hungarian|austrian|romanian|czech|swiss|danish|turkish|italian|catalan", STR_NULL, NULL, NULL),
 	    SDT_OMANY(GameSettings, game_creation.landscape,  SLE_UINT8,                     0, 0, 0, 3, "temperate|arctic|tropic|toyland", STR_NULL, NULL, ConvertLandscape),
 	      SDT_VAR(GameSettings, game_creation.snow_line,  SLE_UINT8,                     0, 0, 7 * TILE_HEIGHT, 2 * TILE_HEIGHT, 13 * TILE_HEIGHT, 0, STR_NULL, NULL),
- SDTC_CONDOMANY(              gui.autosave,             SLE_UINT8,  0, 22,             N, 0, 0, 0, "", STR_NULL, NULL),
+	 SDT_CONDNULL(                                                1,  0, 22),
  SDTC_CONDOMANY(              gui.autosave,             SLE_UINT8, 23, SL_MAX_VERSION, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL, NULL),
 	    SDT_OMANY(GameSettings, vehicle.road_side,        SLE_UINT8,                     0, 0, 1, 1, "left|right", STR_NULL, NULL, NULL),
 	    SDT_END()
@@ -1740,45 +1743,75 @@
 
 	/***************************************************************************/
 	/* Unsaved patch variables. */
-	SDTC_OMANY(gui.autosave,               SLE_UINT8, S, 0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL,                     NULL),
-	 SDTC_BOOL(gui.vehicle_speed,                     S, 0,  true,                        STR_CONFIG_PATCHES_VEHICLESPEED,                NULL),
-	 SDTC_BOOL(gui.status_long_date,                  S, 0,  true,                        STR_CONFIG_PATCHES_LONGDATE,                    NULL),
-	 SDTC_BOOL(gui.show_finances,                     S, 0,  true,                        STR_CONFIG_PATCHES_SHOWFINANCES,                NULL),
-	 SDTC_BOOL(gui.autoscroll,                        S, 0, false,                        STR_CONFIG_PATCHES_AUTOSCROLL,                  NULL),
-	 SDTC_BOOL(gui.reverse_scroll,                    S, 0, false,                        STR_CONFIG_PATCHES_REVERSE_SCROLLING,           NULL),
-	 SDTC_BOOL(gui.smooth_scroll,                     S, 0, false,                        STR_CONFIG_PATCHES_SMOOTH_SCROLLING,            NULL),
-	 SDTC_BOOL(gui.measure_tooltip,                   S, 0, false,                        STR_CONFIG_PATCHES_MEASURE_TOOLTIP,             NULL),
-	  SDTC_VAR(gui.errmsg_duration,        SLE_UINT8, S, 0,     5,        0,       20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION,             NULL),
-	  SDTC_VAR(gui.toolbar_pos,            SLE_UINT8, S,MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS,                 v_PositionMainToolbar),
-	  SDTC_VAR(gui.window_snap_radius,     SLE_UINT8, S,D0,    10,        1,       32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS,                 NULL),
-	 SDTC_BOOL(gui.population_in_label,               S, 0,  true,                        STR_CONFIG_PATCHES_POPULATION_IN_LABEL,         PopulationInLabelActive),
-	 SDTC_BOOL(gui.link_terraform_toolbar,            S, 0, false,                        STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,      NULL),
-	  SDTC_VAR(gui.liveries,               SLE_UINT8, S,MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_LIVERIES,                    RedrawScreen),
-	 SDTC_BOOL(gui.prefer_teamchat,                   S, 0, false,                        STR_CONFIG_PATCHES_PREFER_TEAMCHAT,             NULL),
-	  SDTC_VAR(gui.scrollwheel_scrolling,  SLE_UINT8, S,MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING,       NULL),
-	  SDTC_VAR(gui.scrollwheel_multiplier, SLE_UINT8, S, 0,     5,        1,       15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,      NULL),
-	 SDTC_BOOL(gui.pause_on_newgame,                  S, 0, false,                        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,           NULL),
-	  SDTC_VAR(gui.advanced_vehicle_list,  SLE_UINT8, S,MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,      NULL),
-	 SDTC_BOOL(gui.timetable_in_ticks,                S, 0, false,                        STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS,          NULL),
-	  SDTC_VAR(gui.loading_indicators,     SLE_UINT8, S,MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS,          RedrawScreen),
-	  SDTC_VAR(gui.default_rail_type,      SLE_UINT8, S,MS,     4,        0,        6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE,           NULL),
-	 SDTC_BOOL(gui.enable_signal_gui,                 S, 0, false,                        STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI,           CloseSignalGUI),
-	  SDTC_VAR(gui.drag_signals_density,   SLE_UINT8, S, 0,     4,        1,       20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,        DragSignalsDensityChanged),
-	  SDTC_VAR(gui.semaphore_build_before, SLE_INT32, S, NC, 1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
-	 SDTC_BOOL(gui.train_income_warn,                 S, 0,  true,                        STR_CONFIG_PATCHES_WARN_INCOME_LESS,            NULL),
-	  SDTC_VAR(gui.order_review_system,    SLE_UINT8, S,MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW,                NULL),
-	 SDTC_BOOL(gui.lost_train_warn,                   S, 0,  true,                        STR_CONFIG_PATCHES_WARN_LOST_TRAIN,             NULL),
-	 SDTC_BOOL(gui.autorenew,                         S, 0, false,                        STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,           EngineRenewUpdate),
-	  SDTC_VAR(gui.autorenew_months,       SLE_INT16, S, 0,     6,      -12,       12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS,            EngineRenewMonthsUpdate),
-	  SDTC_VAR(gui.autorenew_money,         SLE_UINT, S,CR,100000,        0,  2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY,             EngineRenewMoneyUpdate),
-	 SDTC_BOOL(gui.always_build_infrastructure,       S, 0, false,                        STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
-	 SDTC_BOOL(gui.new_nonstop,                       S, 0, false,                        STR_CONFIG_PATCHES_NEW_NONSTOP,                 NULL),
-	 SDTC_BOOL(gui.keep_all_autosave,                 S, 0, false,                        STR_NULL,                                       NULL),
-	 SDTC_BOOL(gui.autosave_on_exit,                  S, 0, false,                        STR_NULL,                                       NULL),
-	  SDTC_VAR(gui.max_num_autosaves,      SLE_UINT8, S, 0,    16,        0,      255, 0, STR_NULL,                                       NULL),
-	 SDTC_BOOL(gui.bridge_pillars,                    S, 0,  true,                        STR_NULL,                                       NULL),
-	 SDTC_BOOL(gui.auto_euro,                         S, 0,  true,                        STR_NULL,                                       NULL),
-	  SDTC_VAR(gui.news_message_timeout,   SLE_UINT8, S, 0,     2,        1,      255, 0, STR_NULL,                                       NULL),
+	SDTC_OMANY(gui.autosave,                  SLE_UINT8, S,  0, 1, 4, "off|monthly|quarterly|half year|yearly", STR_NULL,                     NULL),
+	 SDTC_BOOL(gui.vehicle_speed,                        S,  0,  true,                        STR_CONFIG_PATCHES_VEHICLESPEED,                NULL),
+	 SDTC_BOOL(gui.status_long_date,                     S,  0,  true,                        STR_CONFIG_PATCHES_LONGDATE,                    NULL),
+	 SDTC_BOOL(gui.show_finances,                        S,  0,  true,                        STR_CONFIG_PATCHES_SHOWFINANCES,                NULL),
+	 SDTC_BOOL(gui.autoscroll,                           S,  0, false,                        STR_CONFIG_PATCHES_AUTOSCROLL,                  NULL),
+	 SDTC_BOOL(gui.reverse_scroll,                       S,  0, false,                        STR_CONFIG_PATCHES_REVERSE_SCROLLING,           NULL),
+	 SDTC_BOOL(gui.smooth_scroll,                        S,  0, false,                        STR_CONFIG_PATCHES_SMOOTH_SCROLLING,            NULL),
+	 SDTC_BOOL(gui.measure_tooltip,                      S,  0, false,                        STR_CONFIG_PATCHES_MEASURE_TOOLTIP,             NULL),
+	  SDTC_VAR(gui.errmsg_duration,           SLE_UINT8, S,  0,     5,        0,       20, 0, STR_CONFIG_PATCHES_ERRMSG_DURATION,             NULL),
+	  SDTC_VAR(gui.toolbar_pos,               SLE_UINT8, S, MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_TOOLBAR_POS,                 v_PositionMainToolbar),
+	  SDTC_VAR(gui.window_snap_radius,        SLE_UINT8, S, D0,    10,        1,       32, 0, STR_CONFIG_PATCHES_SNAP_RADIUS,                 NULL),
+	 SDTC_BOOL(gui.population_in_label,                  S,  0,  true,                        STR_CONFIG_PATCHES_POPULATION_IN_LABEL,         PopulationInLabelActive),
+	 SDTC_BOOL(gui.link_terraform_toolbar,               S,  0, false,                        STR_CONFIG_PATCHES_LINK_TERRAFORM_TOOLBAR,      NULL),
+	  SDTC_VAR(gui.liveries,                  SLE_UINT8, S, MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_LIVERIES,                    RedrawScreen),
+	 SDTC_BOOL(gui.prefer_teamchat,                      S,  0, false,                        STR_CONFIG_PATCHES_PREFER_TEAMCHAT,             NULL),
+	  SDTC_VAR(gui.scrollwheel_scrolling,     SLE_UINT8, S, MS,     0,        0,        2, 0, STR_CONFIG_PATCHES_SCROLLWHEEL_SCROLLING,       NULL),
+	  SDTC_VAR(gui.scrollwheel_multiplier,    SLE_UINT8, S,  0,     5,        1,       15, 1, STR_CONFIG_PATCHES_SCROLLWHEEL_MULTIPLIER,      NULL),
+	 SDTC_BOOL(gui.pause_on_newgame,                     S,  0, false,                        STR_CONFIG_PATCHES_PAUSE_ON_NEW_GAME,           NULL),
+	  SDTC_VAR(gui.advanced_vehicle_list,     SLE_UINT8, S, MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_ADVANCED_VEHICLE_LISTS,      NULL),
+	 SDTC_BOOL(gui.timetable_in_ticks,                   S,  0, false,                        STR_CONFIG_PATCHES_TIMETABLE_IN_TICKS,          NULL),
+	  SDTC_VAR(gui.loading_indicators,        SLE_UINT8, S, MS,     1,        0,        2, 0, STR_CONFIG_PATCHES_LOADING_INDICATORS,          RedrawScreen),
+	  SDTC_VAR(gui.default_rail_type,         SLE_UINT8, S, MS,     4,        0,        6, 0, STR_CONFIG_PATCHES_DEFAULT_RAIL_TYPE,           NULL),
+	 SDTC_BOOL(gui.enable_signal_gui,                    S,  0, false,                        STR_CONFIG_PATCHES_ENABLE_SIGNAL_GUI,           CloseSignalGUI),
+	  SDTC_VAR(gui.drag_signals_density,      SLE_UINT8, S,  0,     4,        1,       20, 0, STR_CONFIG_PATCHES_DRAG_SIGNALS_DENSITY,        DragSignalsDensityChanged),
+	  SDTC_VAR(gui.semaphore_build_before,    SLE_INT32, S, NC,  1975, MIN_YEAR, MAX_YEAR, 1, STR_CONFIG_PATCHES_SEMAPHORE_BUILD_BEFORE_DATE, ResetSignalVariant),
+	 SDTC_BOOL(gui.train_income_warn,                    S,  0,  true,                        STR_CONFIG_PATCHES_WARN_INCOME_LESS,            NULL),
+	  SDTC_VAR(gui.order_review_system,       SLE_UINT8, S, MS,     2,        0,        2, 0, STR_CONFIG_PATCHES_ORDER_REVIEW,                NULL),
+	 SDTC_BOOL(gui.lost_train_warn,                      S,  0,  true,                        STR_CONFIG_PATCHES_WARN_LOST_TRAIN,             NULL),
+	 SDTC_BOOL(gui.autorenew,                            S,  0, false,                        STR_CONFIG_PATCHES_AUTORENEW_VEHICLE,           EngineRenewUpdate),
+	  SDTC_VAR(gui.autorenew_months,          SLE_INT16, S,  0,     6,      -12,       12, 0, STR_CONFIG_PATCHES_AUTORENEW_MONTHS,            EngineRenewMonthsUpdate),
+	  SDTC_VAR(gui.autorenew_money,            SLE_UINT, S, CR,100000,        0,  2000000, 0, STR_CONFIG_PATCHES_AUTORENEW_MONEY,             EngineRenewMoneyUpdate),
+	 SDTC_BOOL(gui.always_build_infrastructure,          S,  0, false,                        STR_CONFIG_PATCHES_ALWAYS_BUILD_INFRASTRUCTURE, RedrawScreen),
+	 SDTC_BOOL(gui.new_nonstop,                          S,  0, false,                        STR_CONFIG_PATCHES_NEW_NONSTOP,                 NULL),
+	 SDTC_BOOL(gui.keep_all_autosave,                    S,  0, false,                        STR_NULL,                                       NULL),
+	 SDTC_BOOL(gui.autosave_on_exit,                     S,  0, false,                        STR_NULL,                                       NULL),
+	  SDTC_VAR(gui.max_num_autosaves,         SLE_UINT8, S,  0,    16,        0,      255, 0, STR_NULL,                                       NULL),
+	 SDTC_BOOL(gui.bridge_pillars,                       S,  0,  true,                        STR_NULL,                                       NULL),
+	 SDTC_BOOL(gui.auto_euro,                            S,  0,  true,                        STR_NULL,                                       NULL),
+	  SDTC_VAR(gui.news_message_timeout,      SLE_UINT8, S,  0,     2,        1,      255, 0, STR_NULL,                                       NULL),
+
+#ifdef ENABLE_NETWORK
+	  SDTC_VAR(network.sync_freq,            SLE_UINT16,C|S,NO,   100,        0,      100, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.frame_freq,            SLE_UINT8,C|S,NO,     0,        0,      100, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.max_join_time,        SLE_UINT16, S, NO,   500,        0,    32000, 0, STR_NULL,                                       NULL),
+	 SDTC_BOOL(network.pause_on_join,                    S, NO,  true,                        STR_NULL,                                       NULL),
+	  SDTC_STR(network.server_bind_ip,         SLE_STRB, S, NO, "0.0.0.0",                    STR_NULL,                                       NULL),
+	  SDTC_VAR(network.server_port,          SLE_UINT16, S, NO,NETWORK_DEFAULT_PORT,0,65535,0,STR_NULL,                                       NULL),
+	 SDTC_BOOL(network.server_advertise,                 S, NO, false,                        STR_NULL,                                       NULL),
+	  SDTC_VAR(network.lan_internet,          SLE_UINT8, S, NO,     0,        0,        1, 0, STR_NULL,                                       NULL),
+	  SDTC_STR(network.player_name,            SLE_STRB, S,  0,  NULL,                        STR_NULL,                                       UpdatePlayerName),
+	  SDTC_STR(network.server_password,        SLE_STRB, S, NO,  NULL,                        STR_NULL,                                       UpdateServerPassword),
+	  SDTC_STR(network.rcon_password,          SLE_STRB, S, NO,  NULL,                        STR_NULL,                                       UpdateRconPassword),
+	  SDTC_STR(network.default_company_pass,   SLE_STRB, S,  0,  NULL,                        STR_NULL,                                       NULL),
+	  SDTC_STR(network.server_name,            SLE_STRB, S, NO,  NULL,                        STR_NULL,                                       NULL),
+	  SDTC_STR(network.connect_to_ip,          SLE_STRB, S,  0,  NULL,                        STR_NULL,                                       NULL),
+	  SDTC_STR(network.network_id,             SLE_STRB, S, NO,  NULL,                        STR_NULL,                                       NULL),
+	 SDTC_BOOL(network.autoclean_companies,              S, NO, false,                        STR_NULL,                                       NULL),
+	  SDTC_VAR(network.autoclean_unprotected, SLE_UINT8, S, NO,    12,     0,          60, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.autoclean_protected,   SLE_UINT8, S, NO,    36,     0,         180, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.max_companies,         SLE_UINT8, S, NO,     8,     1, MAX_PLAYERS, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.max_clients,           SLE_UINT8, S, NO,    10,     2, MAX_CLIENTS, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.max_spectators,        SLE_UINT8, S, NO,    10,     0, MAX_CLIENTS, 0, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.restart_game_year,     SLE_INT32, S,D0|NO|NC,0, MIN_YEAR, MAX_YEAR, 1, STR_NULL,                                       NULL),
+	  SDTC_VAR(network.min_players,           SLE_UINT8, S, NO,     0,     0,        10,   0, STR_NULL,                                       UpdateMinPlayers),
+	SDTC_OMANY(network.server_lang,           SLE_UINT8, S, NO,     0,    35, "ANY|ENGLISH|GERMAN|FRENCH|BRAZILIAN|BULGARIAN|CHINESE|CZECH|DANISH|DUTCH|ESPERANTO|FINNISH|HUNGARIAN|ICELANDIC|ITALIAN|JAPANESE|KOREAN|LITHUANIAN|NORWEGIAN|POLISH|PORTUGUESE|ROMANIAN|RUSSIAN|SLOVAK|SLOVENIAN|SPANISH|SWEDISH|TURKISH|UKRAINIAN|AFRIKAANS|CROATIAN|CATALAN|ESTONIAN|GALICIAN|GREEK|LATVIAN", STR_NULL, NULL),
+	 SDTC_BOOL(network.reload_cfg,                       S, NO, false,                        STR_NULL,                                       NULL),
+	  SDTC_STR(network.last_host,              SLE_STRB, S,  0, "0.0.0.0",                    STR_NULL,                                       NULL),
+	  SDTC_VAR(network.last_port,            SLE_UINT16, S,  0,     0,     0,  UINT16_MAX, 0, STR_NULL,                                       NULL),
+#endif /* ENABLE_NETWORK */
 
 	/*
 	 * Since the network code (CmdChangePatchSetting and friends) use the index in this array to decide
@@ -2020,7 +2053,6 @@
 	proc(ini, _currency_settings,"currency", &_custom_currency);
 
 #ifdef ENABLE_NETWORK
-	proc(ini, (const SettingDesc*)_network_settings, "network", NULL);
 	proc_list(ini, "servers", _network_host_list, lengthof(_network_host_list), NULL);
 	proc_list(ini, "bans",    _network_ban_list,  lengthof(_network_ban_list), NULL);
 #endif /* ENABLE_NETWORK */
@@ -2084,15 +2116,27 @@
 	if (sd == NULL) return CMD_ERROR;
 	if (!SlIsObjectCurrentlyValid(sd->save.version_from, sd->save.version_to)) return CMD_ERROR;
 
-	if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking) return CMD_ERROR;
+	if ((sd->desc.flags & SGF_NETWORK_ONLY) && !_networking && _game_mode != GM_MENU) return CMD_ERROR;
 	if ((sd->desc.flags & SGF_NO_NETWORK) && _networking) return CMD_ERROR;
 	if ((sd->desc.flags & SGF_NEWGAME_ONLY) && _game_mode != GM_MENU) return CMD_ERROR;
 
 	if (flags & DC_EXEC) {
 		GameSettings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game;
 		void *var = GetVariableAddress(s, &sd->save);
-		Write_ValidateSetting(var, sd, (int32)p2);
-		if (sd->desc.proc != NULL) sd->desc.proc((int32)ReadValue(var, sd->save.conv));
+
+		int32 oldval = (int32)ReadValue(var, sd->save.conv);
+		int32 newval = (int32)p2;
+
+		Write_ValidateSetting(var, sd, newval);
+		newval = (int32)ReadValue(var, sd->save.conv);
+
+		if (sd->desc.proc != NULL) sd->desc.proc(newval);
+
+		if ((sd->desc.flags & SGF_NO_NETWORK) && oldval != newval) {
+			GamelogStartAction(GLAT_PATCH);
+			GamelogPatch(sd->desc.name, oldval, newval);
+			GamelogStopAction();
+		}
 
 		InvalidateWindow(WC_GAME_OPTIONS, 0);
 	}
@@ -2134,6 +2178,24 @@
 	return false;
 }
 
+/**
+ * Set a patch value with a string.
+ * @param index the patch settings index.
+ * @param value the value to write
+ * @note CANNOT BE SAVED IN THE SAVEGAME.
+ */
+bool SetPatchValue(uint index, const char *value)
+{
+	const SettingDesc *sd = &_patch_settings[index];
+	assert(sd->save.conv & SLF_NETWORK_NO);
+
+	char *var = (char*)GetVariableAddress(NULL, &sd->save);
+	ttd_strlcpy(var, value, sd->save.length);
+	if (sd->desc.proc != NULL) sd->desc.proc(0);
+
+	return true;
+}
+
 const SettingDesc *GetPatchFromName(const char *name, uint *i)
 {
 	const SettingDesc *sd;
@@ -2159,23 +2221,41 @@
 
 /* Those 2 functions need to be here, else we have to make some stuff non-static
  * and besides, it is also better to keep stuff like this at the same place */
-bool IConsoleSetPatchSetting(const char *name, int32 value)
+void IConsoleSetPatchSetting(const char *name, const char *value)
 {
-	bool success;
 	uint index;
 	const SettingDesc *sd = GetPatchFromName(name, &index);
-	void *ptr;
 
 	if (sd == NULL) {
 		IConsolePrintF(CC_WARNING, "'%s' is an unknown patch setting.", name);
-		return true;
+		return;
 	}
 
-	GameSettings *s = (_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game;
-	ptr = GetVariableAddress(s, &sd->save);
+	bool success;
+	if (sd->desc.cmd == SDT_STRING) {
+		success = SetPatchValue(index, value);
+	} else {
+		uint32 val;
+		extern bool GetArgumentInteger(uint32 *value, const char *arg);
+		success = GetArgumentInteger(&val, value);
+		if (success) success = SetPatchValue(index, val);
+	}
 
-	success = SetPatchValue(index, value);
-	return success;
+	if (!success) {
+		if (_network_server) {
+			IConsoleError("This command/variable is not available during network games.");
+		} else {
+			IConsoleError("This command/variable is only available to a network server.");
+		}
+	}
+}
+
+void IConsoleSetPatchSetting(const char *name, int value)
+{
+	uint index;
+	const SettingDesc *sd = GetPatchFromName(name, &index);
+	assert(sd != NULL);
+	SetPatchValue(index, value);
 }
 
 void IConsoleGetPatchSetting(const char *name)
@@ -2192,14 +2272,18 @@
 
 	ptr = GetVariableAddress((_game_mode == GM_MENU) ? &_settings_newgame : &_settings_game, &sd->save);
 
-	if (sd->desc.cmd == SDT_BOOLX) {
-		snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off");
+	if (sd->desc.cmd == SDT_STRING) {
+		IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s'", name, (const char *)ptr);
 	} else {
-		snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv));
+		if (sd->desc.cmd == SDT_BOOLX) {
+			snprintf(value, sizeof(value), (*(bool*)ptr == 1) ? "on" : "off");
+		} else {
+			snprintf(value, sizeof(value), "%d", (int32)ReadValue(ptr, sd->save.conv));
+		}
+
+		IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
+			name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
 	}
-
-	IConsolePrintF(CC_WARNING, "Current value for '%s' is: '%s' (min: %s%d, max: %d)",
-		name, value, (sd->desc.flags & SGF_0ISDISABLED) ? "(0) " : "", sd->desc.min, sd->desc.max);
 }
 
 void IConsoleListPatches()
@@ -2212,6 +2296,8 @@
 
 		if (sd->desc.cmd == SDT_BOOLX) {
 			snprintf(value, lengthof(value), (*(bool*)ptr == 1) ? "on" : "off");
+		} else if (sd->desc.cmd == SDT_STRING) {
+			snprintf(value, sizeof(value), "%s", (const char *)ptr);
 		} else {
 			snprintf(value, lengthof(value), "%d", (uint32)ReadValue(ptr, sd->save.conv));
 		}
--- a/src/settings_func.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_func.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,7 +5,8 @@
 #ifndef SETTINGS_FUNC_H
 #define SETTINGS_FUNC_H
 
-bool IConsoleSetPatchSetting(const char *name, int32 value);
+void IConsoleSetPatchSetting(const char *name, const char *value);
+void IConsoleSetPatchSetting(const char *name, int32 value);
 void IConsoleGetPatchSetting(const char *name);
 void IConsoleListPatches();
 
--- a/src/settings_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -761,7 +761,6 @@
 				page->entries = MallocT<PatchEntry>(page->num);
 				for (i = 0; i != page->num; i++) {
 					uint index;
-					printf("%s\n", page->names[i]);
 					const SettingDesc *sd = GetPatchFromName(page->names[i], &index);
 					assert(sd != NULL);
 
--- a/src/settings_internal.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_internal.h	Wed Jun 04 22:34:45 2008 +0000
@@ -85,5 +85,6 @@
 
 const SettingDesc *GetPatchFromName(const char *name, uint *i);
 bool SetPatchValue(uint index, int32 value);
+bool SetPatchValue(uint index, const char *value);
 
 #endif /* SETTINGS_H */
--- a/src/settings_type.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/settings_type.h	Wed Jun 04 22:34:45 2008 +0000
@@ -8,6 +8,7 @@
 #include "date_type.h"
 #include "town_type.h"
 #include "transport_type.h"
+#include "network/core/config.h"
 
 /** Settings related to the difficulty of the game */
 struct DifficultySettings {
@@ -82,6 +83,40 @@
 	byte   news_message_timeout;             ///< how much longer than the news message "age" should we keep the message in the history
 };
 
+/** All settings related to the network. */
+struct NetworkSettings {
+#ifdef ENABLE_NETWORK
+	uint16 sync_freq;                                     ///< how often do we check whether we are still in-sync
+	uint8  frame_freq;                                    ///< how often do we send commands to the clients
+	uint16 max_join_time;                                 ///< maximum amount of time, in game ticks, a client may take to join
+	bool   pause_on_join;                                 ///< pause the game when people join
+	char   server_bind_ip[NETWORK_HOSTNAME_LENGTH];       ///< IP address the server binds to
+	uint16 server_port;                                   ///< port the server listens on
+	char   server_name[NETWORK_NAME_LENGTH];              ///< name of the server
+	char   server_password[NETWORK_PASSWORD_LENGTH];      ///< passowrd for joining this server
+	char   rcon_password[NETWORK_PASSWORD_LENGTH];        ///< passowrd for rconsole (server side)
+	bool   server_advertise;                              ///< advertise the server to the masterserver
+	uint8  lan_internet;                                  ///< search on the LAN or internet for servers
+	char   player_name[NETWORK_NAME_LENGTH];              ///< name of the player
+	char   default_company_pass[NETWORK_PASSWORD_LENGTH]; ///< default password for new companies in encrypted form
+	char   connect_to_ip[NETWORK_HOSTNAME_LENGTH];        ///< default for the "Add server" query
+	char   network_id[NETWORK_UNIQUE_ID_LENGTH];          ///< semi-unique ID of the client
+	bool   autoclean_companies;                           ///< automatically remove companies that are not in use
+	uint8  autoclean_unprotected;                         ///< remove passwordless companies after this many months
+	uint8  autoclean_protected;                           ///< remove the password from passworded companies after this many months
+	uint8  max_companies;                                 ///< maximum amount of companies
+	uint8  max_clients;                                   ///< maximum amount of clients
+	uint8  max_spectators;                                ///< maximum amount of spectators
+	Year   restart_game_year;                             ///< year the server restarts
+	uint8  min_players;                                   ///< minimum amount of players to unpause the game
+	uint8  server_lang;                                   ///< language of the server
+	bool   reload_cfg;                                    ///< reload the config file before restarting
+	char   last_host[NETWORK_HOSTNAME_LENGTH];            ///< IP address of the last joined server
+	uint16 last_port;                                     ///< port of the last joined server
+#else /* ENABLE_NETWORK */
+#endif
+};
+
 /** Settings related to the creation of games. */
 struct GameCreationSettings {
 	uint32 generation_seed;                  ///< noise seed for world generation
@@ -280,6 +315,7 @@
 /** All settings that are only important for the local client. */
 struct ClientSettings {
 	GUISettings          gui;                ///< settings related to the GUI
+	NetworkSettings      network;            ///< settings related to the network
 };
 
 /** The current settings for this game. */
--- a/src/sortlist_type.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/sortlist_type.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,8 @@
 #ifndef SORTLIST_TYPE_H
 #define SORTLIST_TYPE_H
 
+#include "core/enum_type.hpp"
+#include "core/bitmath_func.hpp"
 #include "misc/smallvec.h"
 #include "date_type.h"
 
--- a/src/subsidy_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/subsidy_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -37,23 +37,29 @@
 		for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
 			if (s->cargo_type != CT_INVALID && s->age < 12) {
 				y -= 10;
-				if (y < 0) this->HandleClick(s);
+				if (y < 0) {
+					this->HandleClick(s);
+					return;
+				}
 				num++;
 			}
 		}
 
 		if (num == 0) {
-			y -= 10;
+			y -= 10; // "None"
 			if (y < 0) return;
 		}
 
-		y -= 11;
+		y -= 11; // "Services already subsidised:"
 		if (y < 0) return;
 
 		for (const Subsidy *s = _subsidies; s != endof(_subsidies); s++) {
 			if (s->cargo_type != CT_INVALID && s->age >= 12) {
 				y -= 10;
-				if (y < 0) this->HandleClick(s);
+				if (y < 0) {
+					this->HandleClick(s);
+					return;
+				}
 			}
 		}
 	}
--- a/src/table/files.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/files.h	Wed Jun 04 22:34:45 2008 +0000
@@ -35,7 +35,7 @@
 		{ "TRGT.GRF",      {0xfc, 0xde, 0x1d, 0x7e, 0x8a, 0x74, 0x19, 0x7d, 0x72, 0xa6, 0x26, 0x95, 0x88, 0x4b, 0x90, 0x9e} }
 	},
 	{ "SAMPLE.CAT",    {0x42, 0x2e, 0xa3, 0xdd, 0x07, 0x4d, 0x28, 0x59, 0xbb, 0x51, 0x63, 0x9a, 0x6e, 0x0e, 0x85, 0xda} },
-	{ "OPENTTDD.GRF",  {0xb2, 0xbd, 0xd2, 0xa4, 0x1b, 0xfa, 0x2c, 0x60, 0x4f, 0xd5, 0x5e, 0x4c, 0xb5, 0xba, 0x37, 0x73} }
+	{ "OPENTTDD.GRF",  {0xb6, 0xed, 0x9a, 0x20, 0x89, 0xad, 0x6e, 0xa1, 0x55, 0x10, 0xad, 0x00, 0x53, 0xa3, 0xd5, 0xbc} }
 };
 
 
@@ -49,5 +49,5 @@
 		{ "TRGTR.GRF",     {0xde, 0x53, 0x65, 0x05, 0x17, 0xfe, 0x66, 0x1c, 0xea, 0xa3, 0x13, 0x8c, 0x6e, 0xdb, 0x0e, 0xb8} }
 	},
 	{ "SAMPLE.CAT",    {0x92, 0x12, 0xe8, 0x1e, 0x72, 0xba, 0xdd, 0x4b, 0xbe, 0x1e, 0xae, 0xae, 0x66, 0x45, 0x8e, 0x10} },
-	{ "OPENTTDW.GRF",  {0x3b, 0x1a, 0x0d, 0x8c, 0x2d, 0x01, 0x0e, 0xee, 0x47, 0x7f, 0x5d, 0x70, 0x8f, 0xb2, 0xe4, 0xfb} }
+	{ "OPENTTDW.GRF",  {0x41, 0x1e, 0xb6, 0xb2, 0xd2, 0xc4, 0x30, 0x6e, 0x7b, 0xc7, 0xdc, 0x39, 0xd4, 0x40, 0x46, 0xfb} }
 };
--- a/src/table/sprites.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/sprites.h	Wed Jun 04 22:34:45 2008 +0000
@@ -49,7 +49,7 @@
 
 	/* Extra graphic spritenumbers */
 	SPR_OPENTTD_BASE     = 4896,
-	OPENTTD_SPRITE_COUNT = 144,
+	OPENTTD_SPRITE_COUNT = 145,
 
 	/* Halftile-selection sprites */
 	SPR_HALFTILE_SELECTION_FLAT = SPR_OPENTTD_BASE,
@@ -122,6 +122,8 @@
 	SPR_GROUP_REPLACE_OFF_SHIP     = SPR_OPENTTD_BASE + 132,
 	SPR_GROUP_REPLACE_OFF_AIRCRAFT = SPR_OPENTTD_BASE + 133,
 
+	SPR_SWITCH_TOOLBAR = SPR_OPENTTD_BASE + 144,
+
 	SPR_SIGNALS_BASE  = SPR_OPENTTD_BASE + OPENTTD_SPRITE_COUNT,
 	PRESIGNAL_SPRITE_COUNT                   =  48,
 	PRESIGNAL_AND_SEMAPHORE_SPRITE_COUNT     = 112,
--- a/src/table/town_land.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/table/town_land.h	Wed Jun 04 22:34:45 2008 +0000
@@ -1809,8 +1809,8 @@
 	/**
 	 *                                                              remove_rating_decrease
 	 *                                                               |    mail_generation
-	 *     min_date                                                  |    |    1st CargoID acceptance
-	 *     |         max_date                                        |    |    |    2nd CargoID acceptance
+	 *     min_year                                                  |    |    1st CargoID acceptance
+	 *     |         max_year                                        |    |    |    2nd CargoID acceptance
 	 *     |         |    population                                 |    |    |    |    3th CargoID acceptance
 	 *     |         |    |    removal_cost                          |    |    |    |    |
 	 *     |         |    |    |    building_name                    |    |    |    |    |
--- a/src/toolbar_gui.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/toolbar_gui.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -48,10 +48,19 @@
 
 static void PopupMainToolbMenu(Window *parent, uint16 parent_button, StringID base_string, byte item_count, byte disabled_mask = 0, int sel_index = 0, int checked_items = 0);
 static void PopupMainPlayerToolbMenu(Window *parent, int main_button, int gray);
+static void SplitToolbar(Window *w);
 
 RailType _last_built_railtype;
 RoadType _last_built_roadtype;
 
+enum ToolbarMode {
+	TB_NORMAL,
+	TB_UPPER,
+	TB_LOWER
+};
+
+static ToolbarMode _toolbar_mode;
+
 static void SelectSignTool()
 {
 	if (_cursor.sprite == SPR_CURSOR_SIGN) {
@@ -283,7 +292,7 @@
 
 static void ToolbarGraphsClick(Window *w)
 {
-	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, 6);
+	PopupMainToolbMenu(w, 10, STR_0154_OPERATING_PROFIT_GRAPH, (_toolbar_mode == TB_NORMAL) ? 6 : 8);
 }
 
 static void MenuClickGraphs(int index)
@@ -295,6 +304,9 @@
 		case 3: ShowPerformanceHistoryGraph(); break;
 		case 4: ShowCompanyValueGraph();       break;
 		case 5: ShowCargoPaymentRates();       break;
+		/* functions for combined graphs/league button */
+		case 6: ShowCompanyLeagueTable();      break;
+		case 7: ShowPerformanceRatingDetail(); break;
 	}
 }
 
@@ -535,6 +547,22 @@
 	}
 }
 
+/* --- Switch toolbar button --- */
+
+static void ToolbarSwitchClick(Window *w)
+{
+	if (_toolbar_mode != TB_LOWER) {
+		_toolbar_mode = TB_LOWER;
+	} else {
+		_toolbar_mode = TB_UPPER;
+	}
+
+	SplitToolbar(w);
+	w->HandleButtonClick(27);
+	SetWindowDirty(w);
+	SndPlayFx(SND_15_BEEP);
+}
+
 /* --- Scenario editor specific handlers. */
 
 static void ToolbarScenDateBackward(Window *w)
@@ -633,6 +661,90 @@
 {
 }
 
+/* --- Resizing the toolbar */
+
+static void ResizeToolbar(Window *w)
+{
+	/* There are 27 buttons plus some spacings if the space allows it */
+	uint button_width;
+	uint spacing;
+	if (w->width >= 27 * 22) {
+		button_width = 22;
+		spacing = w->width - (27 * button_width);
+	} else {
+		button_width = w->width / 27;
+		spacing = 0;
+	}
+	uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
+
+	for (uint i = 0, x = 0, j = 0; i < 27; i++) {
+		if (extra_spacing_at[j] == i) {
+			j++;
+			uint add = spacing / (lengthof(extra_spacing_at) - j);
+			spacing -= add;
+			x += add;
+		}
+
+		w->widget[i].type = WWT_IMGBTN;
+		w->widget[i].left = x;
+		x += (spacing != 0) ? button_width : (w->width - x) / (27 - i);
+		w->widget[i].right = x - 1;
+	}
+
+	w->widget[27].type = WWT_EMPTY;
+	_toolbar_mode = TB_NORMAL;
+}
+
+/* --- Split the toolbar */
+
+static void SplitToolbar(Window *w)
+{
+	static const byte arrange14[] = {
+		0,  1, 13, 14, 15, 16, 17, 18, 19, 20, 21, 22, 23, 27,
+		2,  3,  4,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 27,
+	};
+	static const byte arrange15[] = {
+		0,  1,  4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+		0,  2,  4,  3,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 27,
+	};
+	static const byte arrange16[] = {
+		0,  1,  2,  4, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+		0,  1,  3,  5,  6,  7,  8,  9, 10, 12, 24, 25, 26, 17, 18, 27,
+	};
+	static const byte arrange17[] = {
+		0,  1,  2,  4,  6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 17, 18, 27,
+		0,  1,  3,  4,  6,  5,  7,  8,  9, 10, 12, 24, 25, 26, 17, 18, 27,
+	};
+	static const byte arrange18[] = {
+		0,  1,  2,  4,  5,  6,  7,  8,  9, 12, 19, 20, 21, 22, 23, 17, 18, 27,
+		0,  1,  3,  4,  5,  6,  7, 10, 13, 14, 15, 16, 24, 25, 26, 17, 18, 27,
+	};
+	static const byte arrange19[] = {
+		0,  1,  2,  4,  5,  6, 13, 14, 15, 16, 19, 20, 21, 22, 23, 24, 17, 18, 27,
+		0,  1,  3,  4,  7,  8,  9, 10, 12, 25, 19, 20, 21, 22, 23, 26, 17, 18, 27,
+	};
+
+	static const byte *arrangements[] = { arrange14, arrange15, arrange16, arrange17, arrange18, arrange19 };
+
+	static const uint icon_size = 22;
+	uint max_icons = max(14U, (w->width + icon_size / 2) / icon_size);
+
+	assert(max_icons >= 14 && max_icons <= 19);
+
+	/* first hide all icons */
+	for (uint i = 0; i < 27; i++) {
+		w->widget[i].type = WWT_EMPTY;
+	}
+
+	/* now activate them all on their proper positions */
+	for (uint i = 0, x = 0, n = max_icons - 14; i < max_icons; i++) {
+		uint icon = arrangements[n][i + ((_toolbar_mode == TB_LOWER) ? max_icons : 0)];
+		w->widget[icon].type = WWT_IMGBTN;
+		w->widget[icon].left = x;
+		x += (w->width - x) / (max_icons - i);
+		w->widget[icon].right = x - 1;
+	}
+}
 
 /* --- Toolbar handling for the 'normal' case */
 
@@ -666,6 +778,7 @@
 	ToolbarMusicClick,
 	ToolbarNewspaperClick,
 	ToolbarHelpClick,
+	ToolbarSwitchClick,
 };
 
 struct MainToolbarWindow : Window {
@@ -776,29 +889,10 @@
 
 	virtual void OnResize(Point new_size, Point delta)
 	{
-		/* There are 27 buttons plus some spacings if the space allows it */
-		uint button_width;
-		uint spacing;
-		if (this->width >= 27 * 22) {
-			button_width = 22;
-			spacing = this->width - (27 * button_width);
+		if (this->width <= 19 * 22) {
+			SplitToolbar(this);
 		} else {
-			button_width = this->width / 27;
-			spacing = 0;
-		}
-		uint extra_spacing_at[] = { 4, 8, 13, 17, 19, 24, 0 };
-
-		for (uint i = 0, x = 0, j = 0; i < 27; i++) {
-			if (extra_spacing_at[j] == i) {
-				j++;
-				uint add = spacing / (lengthof(extra_spacing_at) - j);
-				spacing -= add;
-				x += add;
-			}
-
-			this->widget[i].left = x;
-			x += (spacing != 0) ? button_width : (this->width - x) / (27 - i);
-			this->widget[i].right = x - 1;
+			ResizeToolbar(this);
 		}
 	}
 
@@ -852,6 +946,7 @@
 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_MUSIC,           STR_01D4_SHOW_SOUND_MUSIC_WINDOW},
 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_MESSAGES,        STR_0203_SHOW_LAST_MESSAGE_NEWS},
 {     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_IMG_QUERY,           STR_0186_LAND_BLOCK_INFORMATION},
+{     WWT_IMGBTN,   RESIZE_NONE,    14,     0,     0,     0,    21, SPR_SWITCH_TOOLBAR,      STR_EMPTY}, // switch toolbar button. only active when toolbar has been split
 {   WIDGETS_END},
 };
 
--- a/src/town.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/town.h	Wed Jun 04 22:34:45 2008 +0000
@@ -212,8 +212,8 @@
 
 struct HouseSpec {
 	/* Standard properties */
-	Year min_date;                     ///< introduction year of the house
-	Year max_date;                     ///< last year it can be built
+	Year min_year;                     ///< introduction year of the house
+	Year max_year;                     ///< last year it can be built
 	byte population;                   ///< population (Zero on other tiles in multi tile house.)
 	byte removal_cost;                 ///< cost multiplier for removing it
 	StringID building_name;            ///< building name
--- a/src/town_cmd.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/town_cmd.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -1639,11 +1639,7 @@
  */
 static inline void ClearMakeHouseTile(TileIndex tile, TownID tid, byte counter, byte stage, HouseID type, byte random_bits)
 {
-	#if !defined(NDEBUG) || defined(WITH_ASSERT)
-		CommandCost cc =
-	#endif /* !defined(NDEBUG) || defined(WITH_ASSERT) */
-
-	DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
+	CommandCost cc = DoCommand(tile, 0, 0, DC_EXEC | DC_AUTO | DC_NO_WATER, CMD_LANDSCAPE_CLEAR);
 
 	assert(CmdSucceeded(cc));
 
@@ -1935,7 +1931,7 @@
 			}
 		}
 
-		if (_cur_year < hs->min_date || _cur_year > hs->max_date) continue;
+		if (_cur_year < hs->min_year || _cur_year > hs->max_year) continue;
 
 		/* Special houses that there can be only one of. */
 		uint oneof = 0;
@@ -2197,7 +2193,7 @@
 {
 	TileIndex tile = t->xy;
 
-	if (CircularTileSearch(tile, 9, SearchTileForStatue, t->index)) {
+	if (CircularTileSearch(&tile, 9, SearchTileForStatue, t->index)) {
 		SetBit(t->statues, _current_player); // Once found and built, "inform" the Town
 	}
 }
@@ -2247,6 +2243,7 @@
 		 */
 		if (t->ratings[_current_player] > RATING_BRIBE_DOWN_TO) {
 			t->ratings[_current_player] = RATING_BRIBE_DOWN_TO;
+			InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
 		}
 	} else {
 		ChangeTownRating(t, RATING_BRIBE_UP_STEP, RATING_BRIBE_MAXIMUM);
@@ -2328,6 +2325,8 @@
 		t->ratings[i] = Clamp(t->ratings[i], RATING_MINIMUM, RATING_MAXIMUM);
 	}
 
+	InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
+
 	ClrBit(t->flags12, TOWN_IS_FUNDED);
 	if (_settings_game.economy.town_growth_rate == 0 && t->fund_buildings_months == 0) return;
 
@@ -2499,6 +2498,7 @@
 		_town_test_ratings[t] = rating;
 	} else {
 		t->ratings[_current_player] = rating;
+		InvalidateWindow(WC_TOWN_AUTHORITY, t->index);
 	}
 }
 
--- a/src/variables.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/variables.h	Wed Jun 04 22:34:45 2008 +0000
@@ -5,6 +5,10 @@
 #ifndef VARIABLES_H
 #define VARIABLES_H
 
+#ifndef VARDEF
+#define VARDEF extern
+#endif
+
 /* Amount of game ticks */
 VARDEF uint16 _tick_counter;
 
--- a/src/vehicle.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/vehicle.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -25,7 +25,6 @@
 #include "industry_map.h"
 #include "station_map.h"
 #include "water_map.h"
-#include "network/network.h"
 #include "yapf/yapf.h"
 #include "newgrf_callbacks.h"
 #include "newgrf_engine.h"
--- a/src/win32.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/win32.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -25,6 +25,7 @@
 #include "core/random_func.hpp"
 #include "core/bitmath_func.hpp"
 #include "string_func.h"
+#include "gamelog.h"
 #include <ctype.h>
 #include <tchar.h>
 #include <errno.h>
@@ -454,6 +455,15 @@
 
 extern bool CloseConsoleLogIfActive();
 
+static HANDLE _file_crash_log;
+
+static void GamelogPrintCrashLogProc(const char *s)
+{
+	DWORD num_written;
+	WriteFile(_file_crash_log, s, strlen(s), &num_written, NULL);
+	WriteFile(_file_crash_log, "\r\n", strlen("\r\n"), &num_written, NULL);
+}
+
 static LONG WINAPI ExceptionHandler(EXCEPTION_POINTERS *ep)
 {
 	char *output;
@@ -588,17 +598,15 @@
 		os.dwOSVersionInfoSize = sizeof(os);
 		GetVersionEx(&os);
 		output += sprintf(output, "\r\nSystem information:\r\n"
-			" Windows version %d.%d %d %s\r\n",
+			" Windows version %d.%d %d %s\r\n\r\n",
 			os.dwMajorVersion, os.dwMinorVersion, os.dwBuildNumber, os.szCSDVersion);
 	}
 
-	{
-		HANDLE file = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+	_file_crash_log = CreateFile(_T("crash.log"), GENERIC_WRITE, 0, NULL, CREATE_ALWAYS, 0, 0);
+
+	if (_file_crash_log != INVALID_HANDLE_VALUE) {
 		DWORD num_written;
-		if (file != INVALID_HANDLE_VALUE) {
-			WriteFile(file, _crash_msg, output - _crash_msg, &num_written, NULL);
-			CloseHandle(file);
-		}
+		WriteFile(_file_crash_log, _crash_msg, output - _crash_msg, &num_written, NULL);
 	}
 
 #if !defined(_DEBUG)
@@ -636,6 +644,11 @@
 	}
 #endif
 
+	if (_file_crash_log != INVALID_HANDLE_VALUE) {
+		GamelogPrint(&GamelogPrintCrashLogProc);
+		CloseHandle(_file_crash_log);
+	}
+
 	/* Close any possible log files */
 	CloseConsoleLogIfActive();
 
@@ -780,7 +793,7 @@
 {
 #if defined(WINCE)
 	/* WinCE only knows one drive: / */
-	FiosItem *fios = FiosAlloc();
+	FiosItem *fios = _fios_items.Append();
 	fios->type = FIOS_TYPE_DRIVE;
 	fios->mtime = 0;
 	snprintf(fios->name, lengthof(fios->name), PATHSEP "");
@@ -791,7 +804,7 @@
 
 	GetLogicalDriveStrings(sizeof(drives), drives);
 	for (s = drives; *s != '\0';) {
-		FiosItem *fios = FiosAlloc();
+		FiosItem *fios = _fios_items.Append();
 		fios->type = FIOS_TYPE_DRIVE;
 		fios->mtime = 0;
 		snprintf(fios->name, lengthof(fios->name),  "%c:", s[0] & 0xFF);
--- a/src/window.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/window.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -721,9 +721,14 @@
 }
 
 /**
- * Find a nice spot for this window and resize it towards the default size.
+ * Resize window towards the default size.
+ * Prior to construction, a position for the new window (for its default size)
+ * has been found with LocalGetWindowPlacement(). Initially, the window is
+ * constructed with minimal size. Resizing the window to its default size is
+ * done here.
  * @param def_width default width in pixels of the window
  * @param def_height default height in pixels of the window
+ * @see Window::Window(), Window::Initialize()
  */
 void Window::FindWindowPlacementAndResize(int def_width, int def_height)
 {
@@ -802,7 +807,17 @@
 	this->Initialize(x, y, width, height, cls, widget, 0);
 }
 
-
+/**
+ * Decide whether a given rectangle is a good place to open a completely visible new window.
+ * The new window should be within screen borders, and not overlap with another already
+ * existing window (except for the main window in the background).
+ * @param left    Left edge of the rectangle
+ * @param top     Top edge of the rectangle
+ * @param width   Width of the rectangle
+ * @param height  Height of the rectangle
+ * @param pos     If rectangle is good, use this parameter to return the top-left corner of the new window
+ * @return Boolean indication that the rectangle is a good place for the new window
+ */
 static bool IsGoodAutoPlace1(int left, int top, int width, int height, Point &pos)
 {
 	Window* const *wz;
@@ -830,11 +845,26 @@
 	return true;
 }
 
+/**
+ * Decide whether a given rectangle is a good place to open a mostly visible new window.
+ * The new window should be mostly within screen borders, and not overlap with another already
+ * existing window (except for the main window in the background).
+ * @param left    Left edge of the rectangle
+ * @param top     Top edge of the rectangle
+ * @param width   Width of the rectangle
+ * @param height  Height of the rectangle
+ * @param pos     If rectangle is good, use this parameter to return the top-left corner of the new window
+ * @return Boolean indication that the rectangle is a good place for the new window
+ */
 static bool IsGoodAutoPlace2(int left, int top, int width, int height, Point &pos)
 {
 	Window* const *wz;
 
+	/* Left part of the rectangle may be at most 1/4 off-screen,
+	 * right part of the rectangle may be at most 1/2 off-screen
+	 */
 	if (left < -(width>>2) || left > _screen.width - (width>>1)) return false;
+	/* Bottom part of the rectangle may be at most 1/4 off-screen */
 	if (top < 22 || top > _screen.height - (height>>2)) return false;
 
 	/* Make sure it is not obscured by any window. */
@@ -855,13 +885,24 @@
 	return true;
 }
 
+/**
+ * Find a good place for opening a new window of a given width and height.
+ * @param width  Width of the new window
+ * @param height Height of the new window
+ * @return Top-left coordinate of the new window
+ */
 static Point GetAutoPlacePosition(int width, int height)
 {
 	Window* const *wz;
 	Point pt;
 
+	/* First attempt, try top-left of the screen */
 	if (IsGoodAutoPlace1(0, 24, width, height, pt)) return pt;
 
+	/* Second attempt, try around all existing windows with a distance of 2 pixels.
+	 * The new window must be entirely on-screen, and not overlap with an existing window.
+	 * Eight starting points are tried, two at each corner.
+	 */
 	FOR_ALL_WINDOWS(wz) {
 		const Window *w = *wz;
 		if (w->window_class == WC_MAIN_WINDOW) continue;
@@ -876,6 +917,10 @@
 		if (IsGoodAutoPlace1(w->left + w->width - width, w->top - height - 2,    width, height, pt)) return pt;
 	}
 
+	/* Third attempt, try around all existing windows with a distance of 2 pixels.
+	 * The new window may be partly off-screen, and must not overlap with an existing window.
+	 * Only four starting points are tried.
+	 */
 	FOR_ALL_WINDOWS(wz) {
 		const Window *w = *wz;
 		if (w->window_class == WC_MAIN_WINDOW) continue;
@@ -886,6 +931,9 @@
 		if (IsGoodAutoPlace2(w->left, w->top - height - 2,    width, height, pt)) return pt;
 	}
 
+	/* Fourth and final attempt, put window at diagonal starting from (0, 24), try multiples
+	 * of (+5, +5)
+	 */
 	{
 		int left = 0, top = 24;
 
@@ -1748,14 +1796,12 @@
 	{ 0,  0}, ///< 15 : left  + up    +  right + down  = nothing
 };
 
-static bool HandleKeyScrolling()
+static void HandleKeyScrolling()
 {
 	if (_dirkeys && !_no_scroll) {
 		int factor = _shift_pressed ? 50 : 10;
 		ScrollMainViewport(scrollamt[_dirkeys][0] * factor, scrollamt[_dirkeys][1] * factor);
-		return false;
 	}
-	return true;
 }
 
 void MouseLoop(MouseClick click, int mousewheel)
@@ -1763,13 +1809,14 @@
 	DecreaseWindowCounters();
 	HandlePlacePresize();
 	UpdateTileSelection();
+	HandleKeyScrolling();
+
 	if (!VpHandlePlaceSizingDrag())  return;
 	if (!HandleDragDrop())           return;
 	if (!HandleWindowDragging())     return;
 	if (!HandleScrollbarScrolling()) return;
 	if (!HandleViewportScroll())     return;
 	if (!HandleMouseOver())          return;
-	if (!HandleKeyScrolling())       return;
 
 	bool scrollwheel_scrolling = _settings_client.gui.scrollwheel_scrolling == 1 && (_cursor.v_wheel != 0 || _cursor.h_wheel != 0);
 	if (click == MC_NONE && mousewheel == 0 && !scrollwheel_scrolling) return;
--- a/src/yapf/follow_track.hpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/follow_track.hpp	Wed Jun 04 22:34:45 2008 +0000
@@ -22,7 +22,7 @@
 		EC_NO_WAY,
 	};
 
-	const Vehicle*      m_veh;           ///< moving vehicle
+	const Vehicle      *m_veh;           ///< moving vehicle
 	TileIndex           m_old_tile;      ///< the origin (vehicle moved from) before move
 	Trackdir            m_old_td;        ///< the trackdir (the vehicle was on) before move
 	TileIndex           m_new_tile;      ///< the new tile (the vehicle has entered)
@@ -33,14 +33,14 @@
 	bool                m_is_station;    ///< last turn passed station
 	int                 m_tiles_skipped; ///< number of skipped tunnel or station tiles
 	ErrorCode           m_err;
-	CPerformanceTimer* m_pPerf;
+	CPerformanceTimer  *m_pPerf;
 
-	FORCEINLINE CFollowTrackT(const Vehicle* v = NULL, CPerformanceTimer* pPerf = NULL)
+	FORCEINLINE CFollowTrackT(const Vehicle *v = NULL, CPerformanceTimer* pPerf = NULL)
 	{
 		Init(v, pPerf);
 	}
 
-	FORCEINLINE void Init(const Vehicle* v, CPerformanceTimer* pPerf)
+	FORCEINLINE void Init(const Vehicle *v, CPerformanceTimer* pPerf)
 	{
 		assert(!IsRailTT() || (v != NULL && v->type == VEH_TRAIN));
 		m_veh = v;
--- a/src/yapf/yapf.h	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf.h	Wed Jun 04 22:34:45 2008 +0000
@@ -16,7 +16,7 @@
  * @param tracks   available tracks on the new tile (to choose from)
  * @return         the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
  */
-Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks);
+Trackdir YapfChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks);
 
 /** Finds the best path for given road vehicle.
  * @param v        the RV that needs to find a path
@@ -24,7 +24,7 @@
  * @param enterdir diagonal direction which the RV will enter this new tile from
  * @return         the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
  */
-Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir);
+Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir);
 
 /** Finds the best path for given train.
  * @param v        the train that needs to find a path
@@ -34,7 +34,7 @@
  * @param path_not_found [out] true is returned if no path can be found (returned Trackdir is only a 'guess')
  * @return         the best trackdir for next turn or INVALID_TRACKDIR if the path could not be found
  */
-Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found);
+Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found);
 
 /** Used by RV multistop feature to find the nearest road stop that has a free slot.
  * @param v      RV (its current tile will be the origin)
@@ -58,17 +58,17 @@
  * @param reversed     receives true if train needs to reversed first
  * @return       the true if depot was found.
  */
-bool YapfFindNearestRailDepotTwoWay(Vehicle *v, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed);
+bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed);
 
 /** Returns true if it is better to reverse the train before leaving station */
-bool YapfCheckReverseTrain(Vehicle* v);
+bool YapfCheckReverseTrain(const Vehicle* v);
 
 /** Use this function to notify YAPF that track layout (or signal configuration) has change */
 void YapfNotifyTrackLayoutChange(TileIndex tile, Track track);
 
 /** performance measurement helpers */
 void* NpfBeginInterval();
-int NpfEndInterval(void* perf);
+int NpfEndInterval(void *perf);
 
 
 extern int _aystar_stats_open_size;
--- a/src/yapf/yapf_base.hpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_base.hpp	Wed Jun 04 22:34:45 2008 +0000
@@ -51,11 +51,11 @@
 
 	NodeList             m_nodes;              ///< node list multi-container
 protected:
-	Node*                m_pBestDestNode;      ///< pointer to the destination node found at last round
-	Node*                m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found
+	Node                *m_pBestDestNode;      ///< pointer to the destination node found at last round
+	Node                *m_pBestIntermediateNode; ///< here should be node closest to the destination if path not found
 	const YAPFSettings  *m_settings;           ///< current settings (_settings_game.yapf)
 	int                  m_max_search_nodes;   ///< maximum number of nodes we are allowed to visit before we give up
-	const Vehicle*       m_veh;                ///< vehicle that we are trying to drive
+	const Vehicle       *m_veh;                ///< vehicle that we are trying to drive
 
 	int                  m_stats_cost_calcs;   ///< stats - how many node's costs were calculated
 	int                  m_stats_cache_hits;   ///< stats - how many node's costs were reused from cache
@@ -281,7 +281,7 @@
 		m_nodes.InsertOpenNode(n);
 	}
 
-	const Vehicle* GetVehicle() const {return m_veh;}
+	const Vehicle * GetVehicle() const {return m_veh;}
 
 	void DumpBase(DumpTarget &dmp) const
 	{
--- a/src/yapf/yapf_costrail.hpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_costrail.hpp	Wed Jun 04 22:34:45 2008 +0000
@@ -191,7 +191,7 @@
 	FORCEINLINE int PlatformLengthPenalty(int platform_length)
 	{
 		int cost = 0;
-		const Vehicle* v = Yapf().GetVehicle();
+		const Vehicle *v = Yapf().GetVehicle();
 		assert(v != NULL);
 		assert(v->type == VEH_TRAIN);
 		assert(v->u.rail.cached_total_length != 0);
@@ -261,7 +261,7 @@
 		int segment_entry_cost = 0;
 		int segment_cost = 0;
 
-		const Vehicle* v = Yapf().GetVehicle();
+		const Vehicle *v = Yapf().GetVehicle();
 
 		// start at n.m_key.m_tile / n.m_key.m_td and walk to the end of segment
 		TILE cur(n.m_key.m_tile, n.m_key.m_td);
--- a/src/yapf/yapf_destrail.hpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_destrail.hpp	Wed Jun 04 22:34:45 2008 +0000
@@ -11,7 +11,7 @@
 	RailTypes m_compatible_railtypes;
 
 public:
-	void SetDestination(Vehicle* v)
+	void SetDestination(const Vehicle* v)
 	{
 		m_compatible_railtypes = v->u.rail.compatible_railtypes;
 	}
@@ -84,7 +84,7 @@
 	}
 
 public:
-	void SetDestination(Vehicle* v)
+	void SetDestination(const Vehicle* v)
 	{
 		switch (v->current_order.GetType()) {
 			case OT_GOTO_STATION:
--- a/src/yapf/yapf_rail.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_rail.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -45,7 +45,7 @@
 	/// return debug report character to identify the transportation type
 	FORCEINLINE char TransportTypeChar() const {return 't';}
 
-	static bool stFindNearestDepotTwoWay(Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+	static bool stFindNearestDepotTwoWay(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
 	{
 		Tpf pf1;
 		bool result1 = pf1.FindNearestDepotTwoWay(v, t1, td1, t2, td2, max_distance, reverse_penalty, depot_tile, reversed);
@@ -64,7 +64,7 @@
 		return result1;
 	}
 
-	FORCEINLINE bool FindNearestDepotTwoWay(Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+	FORCEINLINE bool FindNearestDepotTwoWay(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
 	{
 		// set origin and destination nodes
 		Yapf().SetOrigin(t1, td1, t2, td2, reverse_penalty, true);
@@ -121,7 +121,7 @@
 	/// return debug report character to identify the transportation type
 	FORCEINLINE char TransportTypeChar() const {return 't';}
 
-	static Trackdir stChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+	static Trackdir stChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
 	{
 		// create pathfinder instance
 		Tpf pf1;
@@ -148,7 +148,7 @@
 		return result1;
 	}
 
-	FORCEINLINE Trackdir ChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+	FORCEINLINE Trackdir ChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
 	{
 		// set origin and destination nodes
 		Yapf().SetOrigin(v->tile, GetVehicleTrackdir(v), INVALID_TILE, INVALID_TRACKDIR, 1, true);
@@ -181,7 +181,7 @@
 		return next_trackdir;
 	}
 
-	static bool stCheckReverseTrain(Vehicle* v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
+	static bool stCheckReverseTrain(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
 	{
 		Tpf pf1;
 		bool result1 = pf1.CheckReverseTrain(v, t1, td1, t2, td2, reverse_penalty);
@@ -198,7 +198,7 @@
 		return result1;
 	}
 
-	FORCEINLINE bool CheckReverseTrain(Vehicle* v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
+	FORCEINLINE bool CheckReverseTrain(const Vehicle *v, TileIndex t1, Trackdir td1, TileIndex t2, Trackdir td2, int reverse_penalty)
 	{
 		// create pathfinder instance
 		// set origin and destination nodes
@@ -247,10 +247,10 @@
 struct CYapfAnyDepotRail2 : CYapfT<CYapfRail_TypesT<CYapfAnyDepotRail2, CFollowTrackRailNo90, CRailNodeListTrackDir, CYapfDestinationAnyDepotRailT     , CYapfFollowAnyDepotRailT> > {};
 
 
-Trackdir YapfChooseRailTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
+Trackdir YapfChooseRailTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks, bool *path_not_found)
 {
 	// default is YAPF type 2
-	typedef Trackdir (*PfnChooseRailTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits, bool*);
+	typedef Trackdir (*PfnChooseRailTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits, bool*);
 	PfnChooseRailTrack pfnChooseRailTrack = &CYapfRail1::stChooseRailTrack;
 
 	// check if non-default YAPF type needed
@@ -263,10 +263,10 @@
 	return td_ret;
 }
 
-bool YapfCheckReverseTrain(Vehicle* v)
+bool YapfCheckReverseTrain(const Vehicle* v)
 {
 	/* last wagon */
-	Vehicle* last_veh = GetLastVehicleInChain(v);
+	const Vehicle *last_veh = GetLastVehicleInChain(v);
 
 	// get trackdirs of both ends
 	Trackdir td = GetVehicleTrackdir(v);
@@ -307,7 +307,7 @@
 		reverse_penalty += DistanceManhattan(cur_tile, tile_rev) * YAPF_TILE_LENGTH;
 	}
 
-	typedef bool (*PfnCheckReverseTrain)(Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int);
+	typedef bool (*PfnCheckReverseTrain)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int);
 	PfnCheckReverseTrain pfnCheckReverseTrain = CYapfRail1::stCheckReverseTrain;
 
 	// check if non-default YAPF type needed
@@ -323,12 +323,12 @@
 	return reverse;
 }
 
-bool YapfFindNearestRailDepotTwoWay(Vehicle *v, int max_distance, int reverse_penalty, TileIndex* depot_tile, bool* reversed)
+bool YapfFindNearestRailDepotTwoWay(const Vehicle *v, int max_distance, int reverse_penalty, TileIndex *depot_tile, bool *reversed)
 {
 	*depot_tile = INVALID_TILE;
 	*reversed = false;
 
-	Vehicle* last_veh = GetLastVehicleInChain(v);
+	const Vehicle *last_veh = GetLastVehicleInChain(v);
 
 	TileIndex tile = v->tile;
 	TileIndex last_tile = last_veh->tile;
@@ -337,7 +337,7 @@
 	Trackdir td = GetVehicleTrackdir(v);
 	Trackdir td_rev = ReverseTrackdir(GetVehicleTrackdir(last_veh));
 
-	typedef bool (*PfnFindNearestDepotTwoWay)(Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
+	typedef bool (*PfnFindNearestDepotTwoWay)(const Vehicle*, TileIndex, Trackdir, TileIndex, Trackdir, int, int, TileIndex*, bool*);
 	PfnFindNearestDepotTwoWay pfnFindNearestDepotTwoWay = &CYapfAnyDepotRail1::stFindNearestDepotTwoWay;
 
 	// check if non-default YAPF type needed
--- a/src/yapf/yapf_road.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_road.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -83,7 +83,7 @@
 			// base tile cost depending on distance between edges
 			segment_cost += Yapf().OneTileCost(tile, trackdir);
 
-			const Vehicle* v = Yapf().GetVehicle();
+			const Vehicle *v = Yapf().GetVehicle();
 			// we have reached the vehicle's destination - segment should end here to avoid target skipping
 			if (v->current_order.IsType(OT_GOTO_STATION) && tile == v->dest_tile) break;
 
@@ -253,13 +253,13 @@
 	/// return debug report character to identify the transportation type
 	FORCEINLINE char TransportTypeChar() const {return 'r';}
 
-	static Trackdir stChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+	static Trackdir stChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
 	{
 		Tpf pf;
 		return pf.ChooseRoadTrack(v, tile, enterdir);
 	}
 
-	FORCEINLINE Trackdir ChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+	FORCEINLINE Trackdir ChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
 	{
 		// handle special case - when next tile is destination tile
 		if (tile == v->dest_tile) {
@@ -400,21 +400,22 @@
 struct CYapfRoadAnyDepot2 : CYapfT<CYapfRoad_TypesT<CYapfRoadAnyDepot2, CRoadNodeListExitDir , CYapfDestinationAnyDepotRoadT> > {};
 
 
-Trackdir YapfChooseRoadTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir)
+Trackdir YapfChooseRoadTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir)
 {
 	// default is YAPF type 2
-	typedef Trackdir (*PfnChooseRoadTrack)(Vehicle*, TileIndex, DiagDirection);
+	typedef Trackdir (*PfnChooseRoadTrack)(const Vehicle*, TileIndex, DiagDirection);
 	PfnChooseRoadTrack pfnChooseRoadTrack = &CYapfRoad2::stChooseRoadTrack; // default: ExitDir, allow 90-deg
 
 	// check if non-default YAPF type should be used
-	if (_settings_game.pf.yapf.disable_node_optimization)
+	if (_settings_game.pf.yapf.disable_node_optimization) {
 		pfnChooseRoadTrack = &CYapfRoad1::stChooseRoadTrack; // Trackdir, allow 90-deg
+	}
 
 	Trackdir td_ret = pfnChooseRoadTrack(v, tile, enterdir);
 	return td_ret;
 }
 
-uint YapfRoadVehDistanceToTile(const Vehicle* v, TileIndex tile)
+uint YapfRoadVehDistanceToTile(const Vehicle *v, TileIndex tile)
 {
 	// default is YAPF type 2
 	typedef uint (*PfnDistanceToTile)(const Vehicle*, TileIndex);
--- a/src/yapf/yapf_ship.cpp	Mon Jun 02 01:46:03 2008 +0000
+++ b/src/yapf/yapf_ship.cpp	Wed Jun 04 22:34:45 2008 +0000
@@ -34,7 +34,7 @@
 	/// return debug report character to identify the transportation type
 	FORCEINLINE char TransportTypeChar() const {return 'w';}
 
-	static Trackdir ChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
+	static Trackdir ChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
 	{
 		// handle special case - when next tile is destination tile
 		if (tile == v->dest_tile) {
@@ -147,24 +147,25 @@
 struct CYapfShip3 : CYapfT<CYapfShip_TypesT<CYapfShip3, CFollowTrackWaterNo90, CShipNodeListTrackDir> > {};
 
 /** Ship controller helper - path finder invoker */
-Trackdir YapfChooseShipTrack(Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
+Trackdir YapfChooseShipTrack(const Vehicle *v, TileIndex tile, DiagDirection enterdir, TrackBits tracks)
 {
 	// default is YAPF type 2
-	typedef Trackdir (*PfnChooseShipTrack)(Vehicle*, TileIndex, DiagDirection, TrackBits);
+	typedef Trackdir (*PfnChooseShipTrack)(const Vehicle*, TileIndex, DiagDirection, TrackBits);
 	PfnChooseShipTrack pfnChooseShipTrack = CYapfShip2::ChooseShipTrack; // default: ExitDir, allow 90-deg
 
 	// check if non-default YAPF type needed
-	if (_settings_game.pf.forbid_90_deg)
+	if (_settings_game.pf.forbid_90_deg) {
 		pfnChooseShipTrack = &CYapfShip3::ChooseShipTrack; // Trackdir, forbid 90-deg
-	else if (_settings_game.pf.yapf.disable_node_optimization)
+	} else if (_settings_game.pf.yapf.disable_node_optimization) {
 		pfnChooseShipTrack = &CYapfShip1::ChooseShipTrack; // Trackdir, allow 90-deg
+	}
 
 	Trackdir td_ret = pfnChooseShipTrack(v, tile, enterdir, tracks);
 	return td_ret;
 }
 
 /** performance measurement helper */
-void* NpfBeginInterval()
+void * NpfBeginInterval()
 {
 	CPerformanceTimer& perf = *new CPerformanceTimer;
 	perf.Start();
@@ -172,7 +173,7 @@
 }
 
 /** performance measurement helper */
-int NpfEndInterval(void* vperf)
+int NpfEndInterval(void *vperf)
 {
 	CPerformanceTimer& perf = *(CPerformanceTimer*)vperf;
 	perf.Stop();