Index: Makefile
===================================================================
--- Makefile	(revision 7507)
+++ Makefile	(working copy)
@@ -334,6 +334,7 @@
 SOURCES += gui/trafficlight_info.cc
 SOURCES += gui/obj_info.cc
 SOURCES += gui/welt.cc
+SOURCES += ifc/sync_steppable.cc
 SOURCES += network/checksum.cc
 SOURCES += network/memory_rw.cc
 SOURCES += network/network.cc
Index: dataobj/freelist.cc
===================================================================
--- dataobj/freelist.cc	(revision 7507)
+++ dataobj/freelist.cc	(working copy)
@@ -2,8 +2,6 @@
 #include <stdlib.h>
 #include <assert.h>
 
-#include "../simtypes.h"
-#include "../simmem.h"
 #include "freelist.h"
 
 // define USE_VALGRIND_MEMCHECK to make
@@ -12,21 +10,12 @@
 #include <valgrind/memcheck.h>
 #endif
 
-struct nodelist_node_t
-{
-#ifdef DEBUG_FREELIST
-	unsigned magic : 16;
-	unsigned free : 1;
-	unsigned size : 15;
-#endif
-	nodelist_node_t* next;
-};
-
+/*
 #ifdef MULTI_THREAD
 #include "../utils/simthread.h"
 static pthread_mutex_t freelist_mutex = PTHREAD_MUTEX_INITIALIZER;
 #endif
-
+*/
 // list of all allocated memory
 static nodelist_node_t *chunk_list = NULL;
 
@@ -39,12 +28,7 @@
 // (the few request for larger ones are satisfied with xmalloc otherwise)
 
 
-// for 64 bit, set this to 128
-#define MAX_LIST_INDEX (128)
 
-// list for nodes size 8...64
-#define NUM_LIST ((MAX_LIST_INDEX/4)+1)
-
 static nodelist_node_t *all_lists[NUM_LIST] = {
 	NULL, NULL, NULL, NULL,
 	NULL, NULL, NULL, NULL,
@@ -58,8 +42,6 @@
 };
 
 
-// to have this working, we need chunks at least the size of a pointer
-const size_t min_size = sizeof(void *);
 
 
 void *freelist_t::gimme_node(size_t size)
Index: dataobj/freelist.h
===================================================================
--- dataobj/freelist.h	(revision 7507)
+++ dataobj/freelist.h	(working copy)
@@ -1,6 +1,32 @@
 #ifndef freelist_t_h
 #define freelist_t_h
 
+#include "../simtypes.h"
+#include "../simmem.h"
+#include <stdlib.h>
+
+
+#ifdef MULTI_THREAD
+#include "../utils/simthread.h"
+static pthread_mutex_t freelist_mutex = PTHREAD_MUTEX_INITIALIZER;
+#endif
+
+
+struct nodelist_node_t
+{
+	nodelist_node_t* next;
+};
+
+// for 64 bit, set this to 128
+#define MAX_LIST_INDEX (128)
+
+// list for nodes size 8...64
+#define NUM_LIST ((MAX_LIST_INDEX/4)+1)
+
+// to have this working, we need chunks at least the size of a pointer
+const size_t min_size = sizeof(void *);
+
+
 /**
  * Helper class to organize small memory objects i.e. nodes for linked lists
  * and such.
@@ -17,4 +43,148 @@
 	static void free_all_nodes();
 };
 
+
+template<class T> class freelist_tpl
+{
+	static nodelist_node_t *chunk_list;
+	static nodelist_node_t *all_lists[NUM_LIST];
+
+public:
+	static void *gimme_node( size_t size );
+	static void putback_node( size_t size, void *p );
+
+	// clears all list memories
+//	static void free_all_nodes();
+};
+
+
+template<class T> void *freelist_tpl<T>::gimme_node(size_t size)
+{
+	nodelist_node_t ** list = NULL;
+	if(  size == 0  ) {
+		return NULL;
+	}
+
+	// all sizes should be dividable by 4 and at least as large as a pointer
+	size = max( min_size, size );
+	size = (size+3)>>2;
+	size <<= 2;
+
+#ifdef MULTI_THREAD
+	pthread_mutex_lock( &freelist_mutex );
 #endif
+
+	// hold return value
+	nodelist_node_t *tmp;
+	if(  size > MAX_LIST_INDEX  ) {
+		// too large: just use malloc anyway
+		void* tmp2 = xmalloc(size);
+#ifdef MULTI_THREAD
+		pthread_mutex_unlock( &freelist_mutex );
+#endif
+		return tmp2;
+	}
+
+
+	list = &(all_lists[size/4]);
+	// need new memory?
+	if(  *list == NULL  ) {
+//		int num_elements = 32764/(int)size;
+		int num_elements = 1048572/(int)size;
+		char* p = (char*)xmalloc(num_elements * size + sizeof(p));
+
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we still cannot access the pool p
+		VALGRIND_MAKE_MEM_NOACCESS(p, num_elements * size + sizeof(p));
+#endif // valgrind
+
+		// put the memory into the chunklist for free it
+		nodelist_node_t *chunk = (nodelist_node_t *)p;
+
+#ifdef USE_VALGRIND_MEMCHECK
+		// tell valgrind that we reserved space for one nodelist_node_t
+		VALGRIND_CREATE_MEMPOOL(chunk, 0, false);
+		VALGRIND_MEMPOOL_ALLOC(chunk, chunk, sizeof(*chunk));
+		VALGRIND_MAKE_MEM_UNDEFINED(chunk, sizeof(*chunk));
+#endif // valgrind
+
+		chunk->next = chunk_list;
+		chunk_list = chunk;
+		p += sizeof(p);
+		// then enter nodes into nodelist
+		for(  int i=0;  i<num_elements;  i++  ) {
+			nodelist_node_t *tmp = (nodelist_node_t *)(p+i*size);
+
+#ifdef USE_VALGRIND_MEMCHECK
+			// tell valgrind that we reserved space for one nodelist_node_t
+			VALGRIND_CREATE_MEMPOOL(tmp, 0, false);
+			VALGRIND_MEMPOOL_ALLOC(tmp, tmp, sizeof(*tmp));
+			VALGRIND_MAKE_MEM_UNDEFINED(tmp, sizeof(*tmp));
+#endif // valgrind
+			tmp->next = *list;
+			*list = tmp;
+		}
+	}
+	// return first node
+	tmp = *list;
+	*list = tmp->next;
+
+#ifdef USE_VALGRIND_MEMCHECK
+	// tell valgrind that we now have access to a chunk of size bytes
+	VALGRIND_MEMPOOL_CHANGE(tmp, tmp, tmp, size);
+	VALGRIND_MAKE_MEM_UNDEFINED(tmp, size);
+#endif // valgrind
+
+#ifdef MULTI_THREAD
+	pthread_mutex_unlock( &freelist_mutex );
+#endif
+
+	return (void *)tmp;
+}
+
+template<class T> void freelist_tpl<T>::putback_node( size_t size, void *p )
+{
+	nodelist_node_t ** list = NULL;
+	if(  size==0  ||  p==NULL  ) {
+		return;
+	}
+
+	// all sizes should be dividable by 4
+	size = max( min_size, size );
+	size = ((size+3)>>2);
+	size <<= 2;
+
+#ifdef MULTI_THREAD
+	pthread_mutex_lock( &freelist_mutex );
+#endif
+
+	if(  size > MAX_LIST_INDEX  ) {
+		free(p);
+#ifdef MULTI_THREAD
+		pthread_mutex_unlock( &freelist_mutex );
+#endif
+		return;
+	}
+
+	list = &(all_lists[size/4]);
+
+#ifdef USE_VALGRIND_MEMCHECK
+	// tell valgrind that we keep access to a nodelist_node_t within the memory chunk
+	VALGRIND_MEMPOOL_CHANGE(p, p, p, sizeof(nodelist_node_t));
+	VALGRIND_MAKE_MEM_NOACCESS(p, size);
+	VALGRIND_MAKE_MEM_UNDEFINED(p, sizeof(nodelist_node_t));
+#endif // valgrind
+
+	// putback to first node
+	nodelist_node_t *tmp = (nodelist_node_t *)p;
+	tmp->next = *list;
+	*list = tmp;
+
+#ifdef MULTI_THREAD
+	pthread_mutex_unlock( &freelist_mutex );
+#endif
+}
+
+
+
+#endif
Index: gui/depot_frame.cc
===================================================================
--- gui/depot_frame.cc	(revision 7507)
+++ gui/depot_frame.cc	(working copy)
@@ -1346,7 +1346,7 @@
 			}
 
 			const sint32 convoi_length = (cnv->get_vehikel_anzahl()) * CARUNITS_PER_TILE / 2 - 1;
-			convoi_tile_length_sb = convoi_length + (cnv->get_tile_length() * CARUNITS_PER_TILE - cnv->get_length());
+			convoi_tile_length_sb = convoi_length + (cnv->get_tile_length() * CARUNITS_PER_TILE - cnv->get_cnv_sync()->get_length());
 
 			txt_convoi_count.clear();
 			txt_convoi_count.printf("%s %i",translator::translate("Station tiles:"), cnv->get_tile_length() );
Index: gui/karte.cc
===================================================================
--- gui/karte.cc	(revision 7507)
+++ gui/karte.cc	(working copy)
@@ -1242,8 +1242,7 @@
 						for(  uint32 k = 0;  k < linee[j]->count_convoys();  k++  ) {
 							convoihandle_t test_cnv = linee[j]->get_convoy(k);
 							if(  test_cnv.is_bound()  ) {
-								int state = test_cnv->get_state();
-								if( state != convoi_t::INITIAL  &&  state != convoi_t::ENTERING_DEPOT  &&  state != convoi_t::SELF_DESTRUCT  ) {
+								if(  test_cnv->is_running()  ) {
 									cnv = test_cnv;
 									break;
 								}
@@ -1252,8 +1251,7 @@
 						if(  !cnv.is_bound()  ) {
 							continue;
 						}
-						int state = cnv->get_state();
-						if( state != convoi_t::INITIAL  &&  state != convoi_t::ENTERING_DEPOT  &&  state != convoi_t::SELF_DESTRUCT  ) {
+						if(  cnv->is_running()  ) {
 							add_to_schedule_cache( cnv, false );
 						}
 					}
@@ -1278,8 +1276,7 @@
 						continue;
 					}
 				}
-				int state = cnv->get_state();
-				if(  state != convoi_t::INITIAL  &&  state != convoi_t::ENTERING_DEPOT  &&  state != convoi_t::SELF_DESTRUCT  ) {
+				if(  cnv->is_running()  ) {
 					if(  !is_matching_freight_catg(cnv->get_goods_catg_index())  ) {
 						continue;
 					}
Index: ifc/sync_steppable.cc
===================================================================
--- ifc/sync_steppable.cc	(revision 0)
+++ ifc/sync_steppable.cc	(working copy)
@@ -0,0 +1,565 @@
+#include "sync_steppable.h"
+#include "../utils/simrandom.h"
+
+#include <algorithm>
+
+
+int sync_steppable_vector_t::sync_step_all(const uint32 delta_t)
+{
+	LARGE_INTEGER li1,li2;
+	QueryPerformanceCounter(&li1);
+
+	sync_step_running = true;
+
+	int q = 0;
+	unsigned j = 0;
+	for( vector_tpl<sync_steppable*>::iterator i=sync_list.begin();  i != sync_list.end();  j++  ) {
+		// if false, then remove
+		sync_steppable* ss = *i;
+
+		int r = ss->sync_step(delta_t);
+		switch(  r  ) {
+			case sync_steppable::SYNC_OK: {
+				++i;
+				break;
+			}
+			case sync_steppable::SYNC_REM_DEL: {
+//				num_del3++;
+				delete ss;
+				// fallthrough
+			}
+			case sync_steppable::SYNC_REM: {
+				i = sync_list.swap_erase(i);
+				break;
+			}
+		}
+	}
+	sync_step_running = false;
+
+	QueryPerformanceCounter(&li2);
+	usecs += (li2.QuadPart-li1.QuadPart);
+	return q;
+}
+
+
+void sync_steppable_vector_t::sync_remove_all()
+{
+	while(!sync_list.empty()) {
+		delete sync_list.back();
+	}
+	sync_list.clear();
+}
+
+
+bool sync_steppable_vector_t::compare_address(sync_steppable* const one, sync_steppable* const two) {
+	return one < two;
+}
+
+
+void sync_steppable_vector_t::sort_lists(const uint32 ticks, const char* caller) {
+	if(  adds * 5 > get_count()  ||  (adds > 0  &&  last_sort_time + 10000 < ticks)  ) {
+//	if(  adds > 0  &&  last_sort_time + 10000 < ticks  ) {
+//			printf("vector_t %s timed_sort - %d\n", caller, ticks);
+//	}
+		std::sort( sync_list.begin(), sync_list.end(), compare_address );
+		adds=0;
+		last_sort_time = ticks;
+/*
+		for(  int j=0;  j < sync_list.get_count();  j++  ) {
+			printf(" %p\n", sync_list[j]);
+		}
+		printf("sync_steppable_vector_t \n");
+*/
+	}
+}
+
+
+#ifdef MULTI_THREAD
+sint64 sync_steppable_vector_mt_t::sync_step_btd()
+{
+	sync_step_running = true;
+	return 0;
+}
+
+
+int sync_steppable_vector_mt_t::sync_step_all(const uint8 num, const uint32 delta_t)
+{
+	LARGE_INTEGER li1;
+	QueryPerformanceCounter(&li1);
+
+	int q = 0;
+	unsigned j = 0;
+	for(  vector_tpl<sync_steppable*>::iterator i=sync_list[num].begin();  i != sync_list[num].end();  j++  ) {
+		// if false, then remove
+		sync_steppable* ss = *i;
+		int r = ss->sync_step(delta_t);
+		switch(  r  ) {
+			case sync_steppable::SYNC_OK: {
+				++i;
+				break;
+			}
+			case sync_steppable::SYNC_REM_DEL: {
+//				num_del3++;
+				pthread_spin_lock(&del_spin);
+				delete ss;
+				pthread_spin_unlock(&del_spin);
+				// fallthrough
+			}
+			case sync_steppable::SYNC_REM: {
+				i = sync_list[num].swap_erase(i);
+				break;
+			}
+		}
+	}
+	LARGE_INTEGER li2;
+	QueryPerformanceCounter(&li2);
+	usecs[num] += (li2.QuadPart-li1.QuadPart);
+	start_li[num] = li1;
+	finish_li[num] = li2;
+	return q;
+}
+
+
+void sync_steppable_vector_mt_t::sync_step_ftd(sint64 start)
+{
+	sync_step_running = false;
+}
+
+
+void sync_steppable_vector_mt_t::sync_remove_all()
+{
+	for(  int i=0;  i < env_t::num_threads;  i++  ) {
+		while(!sync_list[i].empty()) {
+			delete sync_list[i].back();
+		}
+		sync_list[i].clear();
+	}
+}
+
+
+bool sync_steppable_vector_mt_t::compare_address(sync_steppable* const one, sync_steppable* const two) {
+	return one > two; // splitting list for threads reverses order!
+}
+
+
+void sync_steppable_vector_mt_t::sort_lists(const uint32 ticks, const char* caller) {
+	static vector_tpl<sync_steppable*> sync_sort;
+
+	if(  adds * 5 > get_count()  ||  (adds > 0  &&  last_sort_time + 10000 < ticks)  ) {
+//	if(  adds > 0  &&  last_sort_time + 10000 < ticks  ) {
+//			printf("vector_mt_t %s timed_sort - %d\n", caller, ticks);
+//	}
+		sync_sort.clear();
+		uint32 total_count = 0;
+		for(  int i=0;  i < env_t::num_threads;  i++  ) {
+			total_count += sync_list[i].get_count();
+		}
+		sync_sort.resize( total_count );
+
+		for(  int i=0;  i < env_t::num_threads;  i++  ) {
+			while(!sync_list[i].empty()) {
+				sync_steppable* ss = sync_list[i].pop_back();
+				if(  ss  ) {
+					sync_sort.append( ss );
+				}
+			}
+			sync_list[i].clear();
+		}
+
+		std::sort( sync_sort.begin(), sync_sort.end(), compare_address );
+
+		total_count = (sync_sort.get_count() + env_t::num_threads - 1) / env_t::num_threads;
+		for(  int i=0;  i<env_t::num_threads-1;  i++  ) {
+			uint32 j=0;
+			while(  !sync_sort.empty()  &&  j<total_count ) {
+				j++;
+				sync_list[i].append( sync_sort.pop_back() );
+			}
+		}
+		while(  !sync_sort.empty() ) {
+			sync_list[env_t::num_threads-1].append( sync_sort.pop_back() );
+		}
+		adds=0;
+		last_sort_time=ticks;
+/*
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			printf("List %d:\n",i);
+			for(  int j=0;  j < sync_list[i].get_count();  j++  ) {
+				printf(" %p\n", sync_list[i][j]);
+			}
+		}
+		printf("\n");
+*/
+	}
+}
+#endif
+
+
+void sync_steppable_vector_copy_t::sync_step_all(const uint32 delta_t)
+{
+	LARGE_INTEGER li1,li2;
+	QueryPerformanceCounter(&li1);
+
+	sync_step_running = true;
+	sync_list_copy.resize( sync_list.get_count()*91/81 );
+	FOR(vector_tpl<sync_steppable*>, const ss, sync_list) {
+		const int r = ss->sync_step(delta_t);
+		switch(  r  ) {
+			case sync_steppable::SYNC_OK: {
+				sync_list_copy.append( ss );
+				break;
+			}
+			case sync_steppable::SYNC_REM_DEL: {
+//				num_weyec_del3++;
+				delete ss;
+				// fallthrough
+			}
+			case sync_steppable::SYNC_REM: {
+				// nothing
+				break;
+			}
+		}
+	}
+	swap( sync_list_copy, sync_list );
+	sync_list_copy.clear();
+	sync_step_running = false;
+
+	QueryPerformanceCounter(&li2);
+	usecs+= (li2.QuadPart-li1.QuadPart);
+}
+
+
+void sync_steppable_vector_copy_t::sync_remove_all()
+{
+	while(!sync_list.empty()) {
+		delete sync_list.back();
+	}
+	sync_list.clear();
+}
+
+
+bool sync_steppable_vector_copy_t::compare_address(sync_steppable* const one, sync_steppable* const two) {
+	return one < two;
+}
+
+
+void sync_steppable_vector_copy_t::sort_lists(const uint32 ticks, const char* caller) {
+	if(  adds * 5 > get_count()  ||  (adds > 0  &&  last_sort_time + 10000 < ticks)  ) {
+//	if(  adds > 0  &&  last_sort_time + 10000 < ticks  ) {
+//			printf(" vector_copy_t %s timed_sort - %d\n", caller, ticks);
+//	}
+		std::sort( sync_list.begin(), sync_list.end(), compare_address );
+		adds=0;
+		last_sort_time=ticks;
+/*
+		for(  int j=0;  j < sync_list.get_count();  j++  ) {
+			printf(" %p\n", sync_list[j]);
+		}
+		printf("sync_steppable_vector_copy_t\n");
+*/
+	}
+}
+
+
+#ifdef MULTI_THREAD
+sint64 sync_steppable_vector_copy_mt_t::sync_step_btd()
+{
+	sync_step_running = true;
+	return 0;
+}
+
+
+void sync_steppable_vector_copy_mt_t::sync_step_all(const uint8 num, const uint32 delta_t)
+{
+	LARGE_INTEGER li1;
+	QueryPerformanceCounter(&li1);
+
+	sync_list_copy[num].resize( sync_list[num].get_count()*91/81 );
+	FOR(vector_tpl<sync_steppable*>, const ss, sync_list[num]) {
+		const int r = ss->sync_step(delta_t);
+		switch(  r  ) {
+			case sync_steppable::SYNC_OK: {
+				sync_list_copy[num].append( ss );
+				break;
+			}
+			case sync_steppable::SYNC_REM_DEL: {
+//				num_del3++;
+				pthread_spin_lock(&del_spin);
+				delete ss;
+				pthread_spin_unlock(&del_spin);
+				// fallthrough
+			}
+			case sync_steppable::SYNC_REM: {
+				// nothing
+				break;
+			}
+		}
+	}
+	swap( sync_list_copy[num], sync_list[num] );
+	sync_list_copy[num].clear();
+
+	LARGE_INTEGER li2;
+	QueryPerformanceCounter(&li2);
+	usecs[num] += (li2.QuadPart-li1.QuadPart);
+	start_li[num] = li1;
+	finish_li[num] = li2;
+}
+
+
+void sync_steppable_vector_copy_mt_t::sync_step_ftd(sint64 start)
+{
+	sync_step_running = false;
+}
+
+
+void sync_steppable_vector_copy_mt_t::sync_remove_all()
+{
+	for(  int i=0;  i<env_t::num_threads;  i++  ) {
+		while(  !sync_list[i].empty()  ) {
+			delete sync_list[i].pop_back();
+		}
+		sync_list[i].clear();
+	}
+}
+
+
+bool sync_steppable_vector_copy_mt_t::compare_address(sync_steppable* const one, sync_steppable* const two) {
+	return one > two;
+}
+
+
+void sync_steppable_vector_copy_mt_t::sort_lists(const uint32 ticks, const char* caller) {
+	static vector_tpl<sync_steppable*> sync_sort;
+
+	if(  adds * 5 > get_count()  ||  (adds > 0  &&  last_sort_time + 10000 < ticks)  ) {
+//	if(  adds > 0  &&  last_sort_time + 10000 < ticks  ) {
+//			printf("%s timed_sort - %d\n", caller, ticks);
+//	}
+		sync_sort.clear();
+		uint32 total_count = 0;
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			total_count += sync_list[i].get_count();
+		}
+		sync_sort.resize( total_count );
+
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			while(!sync_list[i].empty()) {
+				sync_steppable* ss = sync_list[i].pop_back();
+				if(  ss  ) {
+					sync_sort.append( ss );
+				}
+			}
+			sync_list[i].clear();
+		}
+
+		std::sort( sync_sort.begin(), sync_sort.end(), compare_address );
+
+		total_count = (sync_sort.get_count() + env_t::num_threads - 1) / env_t::num_threads;
+		for(  int i=0;  i<env_t::num_threads-1;  i++  ) {
+			uint32 j=0;
+			while(  !sync_sort.empty()  &&  j<total_count ) {
+				j++;
+				sync_list[i].append( sync_sort.pop_back() );
+			}
+		}
+		while(  !sync_sort.empty() ) {
+			sync_list[env_t::num_threads-1].append( sync_sort.pop_back() );
+		}
+		adds=0;
+		last_sort_time=ticks;
+/*
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			printf("List %d:\n",i);
+			for(  int j=0;  j < sync_list[i].get_count();  j++  ) {
+				printf(" %p\n", sync_list[i][j]);
+			}
+		}
+		printf("\n");
+*/
+	}
+}
+
+sint64 sync_steppable_vector_hole_mt_t::sync_step_btd()
+{
+	sync_step_running = true;
+	return 0;
+}
+
+
+void sync_steppable_vector_hole_mt_t::sync_step_all(const uint8 num, const uint32 delta_t)
+{
+	LARGE_INTEGER li1;
+	QueryPerformanceCounter(&li1);
+
+	for(  uint32 i=0;  i < sync_list[num].get_count(); i++) {
+//	for(  vector_tpl<sync_steppable*>::iterator i=sync_list[num].begin();  i != sync_list[num].end();  ) {
+		// if false, then remove
+		sync_steppable* ss = sync_list[num][i];
+		if(  ss  ) {
+			int r = ss->sync_step(delta_t);
+			switch(  r  ) {
+				case sync_steppable::SYNC_OK: {
+					break;
+				}
+				case sync_steppable::SYNC_REM_DEL: {
+//					num_del3++;
+					pthread_spin_lock(&del_spin);
+					delete ss;
+					pthread_spin_unlock(&del_spin);
+					// fallthrough
+				}
+				case sync_steppable::SYNC_REM: {
+					sync_list[num][i] = NULL;
+					hole[num]++;
+					break;
+				}
+			}
+		}
+	}
+
+	LARGE_INTEGER li2;
+	QueryPerformanceCounter(&li2);
+	usecs[num] += (li2.QuadPart-li1.QuadPart);
+	start_li[num] = li1;
+	finish_li[num] = li2;
+}
+
+
+void sync_steppable_vector_hole_mt_t::sync_step_ftd(sint64 start)
+{
+	sync_step_running = false;
+}
+
+
+void sync_steppable_vector_hole_mt_t::sync_remove_all()
+{
+	for(  int i=0;  i<env_t::num_threads;  i++  ) {
+		while(!sync_list[i].empty()) {
+			sync_steppable* ss = sync_list[i].pop_back();
+			if(  ss  ) delete ss;
+		}
+		sync_list[i].clear();
+		hole[i]=0;
+	}
+}
+
+
+bool sync_steppable_vector_hole_mt_t::compare_address(sync_steppable* const one, sync_steppable* const two) {
+	return one > two;
+}
+
+
+void sync_steppable_vector_hole_mt_t::sort_lists(const uint32 ticks, const char* caller) {
+	static vector_tpl<sync_steppable*> sync_sort;
+
+	if(  adds * 5 > get_count()  ||  (adds > 0  &&  last_sort_time + 10000 < ticks)  ) {
+//	if(  adds > 0  &&  last_sort_time + 10000 < ticks  ) {
+//			printf("%s timed_sort - %d\n", caller, ticks);
+//	}
+		sync_sort.clear();
+		uint32 total_count = 0;
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			total_count += sync_list[i].get_count();
+		}
+		sync_sort.resize( total_count );
+
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			while(!sync_list[i].empty()) {
+				sync_steppable* ss = sync_list[i].pop_back();
+				if(  ss  ) {
+					sync_sort.append( ss );
+				}
+			}
+			sync_list[i].clear();
+			hole[i]=0;
+		}
+
+		std::sort( sync_sort.begin(), sync_sort.end(), compare_address );
+
+		total_count = (sync_sort.get_count() + env_t::num_threads - 1) / env_t::num_threads;
+		for(  int i=0;  i<env_t::num_threads-1;  i++  ) {
+			uint32 j=0;
+			while(  !sync_sort.empty()  &&  j<total_count ) {
+				j++;
+				sync_list[i].append( sync_sort.pop_back() );
+			}
+		}
+		while(  !sync_sort.empty() ) {
+			sync_list[env_t::num_threads-1].append( sync_sort.pop_back() );
+		}
+		adds=0;
+		last_sort_time=ticks;
+/*
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			printf("List %d:\n",i);
+			for(  int j=0;  j < sync_list[i].get_count();  j++  ) {
+				printf(" %p\n", sync_list[i][j]);
+			}
+		}
+		printf("\n");
+*/
+	}
+}
+#endif
+
+
+void sync_step_random_t::refresh_list( uint32 num ) {
+//	printf("Refresh rand: %d, %d, %d/%d, %d", next_rand, last_rand, rand_list.get_count(), num, overflown);
+//	const uint32 aaa = last_rand;
+	if(  overflown  ) {
+		// must refresh entire list
+		last_rand = 0;
+		while(  last_rand < rand_list.get_count()  ) {
+			rand_list[last_rand++] = simrand_plain();
+		}
+		// expand list
+		while(  rand_list.get_count() < num  ) {
+			rand_list.append( simrand_plain() );
+		}
+		// new full list ready
+		next_rand = 0;
+		last_rand = rand_list.get_count()-1;
+		overflown = false;
+	}
+	else {
+		if(  next_rand < last_rand  ) {
+			// refresh to end
+			while(  last_rand < rand_list.get_count()  ) {
+				rand_list[last_rand++] = simrand_plain();
+			}
+			// expand list
+			while(  rand_list.get_count() < num  ) {
+				rand_list.append( simrand_plain() );
+			}
+			// refresh beginning
+			if(  next_rand > 0  ) {
+				last_rand = 0;
+				while(  last_rand < next_rand  ) {
+					rand_list[last_rand++] = simrand_plain();
+				}
+				last_rand--;
+			}
+			else {
+				last_rand = rand_list.get_count()-1;
+			}
+		}
+		else {
+			if(  next_rand > 0  ) {
+				// refresh to next
+				while(  last_rand < next_rand  ) {
+					rand_list[last_rand++] = simrand_plain();
+				}
+				last_rand--;
+			}
+			else {
+				last_rand = rand_list.get_count()-1;
+			}
+			// expand list
+			while(  rand_list.get_count() < num  ) {
+				rand_list.append( simrand_plain() );
+			}
+
+		}
+	}
+//	printf("   Now: %d, %d, %d/%d, %d ref\n", next_rand, last_rand, rand_list.get_count(), num, last_rand-aaa);
+}
Index: ifc/sync_steppable.h
===================================================================
--- ifc/sync_steppable.h	(revision 7507)
+++ ifc/sync_steppable.h	(working copy)
@@ -1,8 +1,20 @@
 #ifndef sync_steppable_h
 #define sync_steppable_h
 
+#define NOMINMAX 1
+#include <windows.h>
+
+#ifdef MULTI_THREAD
+#include "../utils/simthread.h"
+#include "../dataobj/environment.h"
+#endif
+
+#include "../tpl/vector_tpl.h"
+#include "../tpl/slist_tpl.h"
+
 #include "../simtypes.h"
 
+
 /**
  * All synchronously moving things must implement this interface.
  *
@@ -11,15 +23,353 @@
 class sync_steppable
 {
 public:
+	enum { SYNC_OK=0, SYNC_REM, SYNC_REM_DEL }; // no change, remove, remove & delete
+
     /**
      * Method for real-time features of an object.
      * @return false when object is part of synchronous list
      * Objekte entfernt werden sol
      * @author Hj. Malthaner
      */
-    virtual bool sync_step(uint32 delta_t) = 0;
+    virtual int sync_step(const uint32 delta_t) = 0;
 
     virtual ~sync_steppable() {}
 };
 
+
+class sync_steppable_vector_t
+{
+	uint64 usecs;
+	uint32 adds;
+	uint32 last_sort_time;
+	vector_tpl<sync_steppable*> sync_list;
+	bool sync_step_running;
+
+	static bool compare_address(sync_steppable* const one, sync_steppable* const two);
+//protected:
+public:
+	void sync_add( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		sync_list.append( obj );
+		adds++;
+	}
+	bool sync_remove( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		return sync_list.remove(obj);
+	}
+	uint32 get_count() const { return sync_list.get_count(); }
+	uint32 get_adds() const { return adds; }
+	uint64 get_usecs() const { return usecs; }
+public:
+	void sort_lists(const uint32 ticks, const char* caller);
+	int sync_step_all(const uint32 delta_t);
+	void sync_remove_all();
+
+	sync_steppable_vector_t( uint64 init_usecs=0 ) : usecs(init_usecs) { adds=0; last_sort_time=0; }
+};
+
+
+#ifdef MULTI_THREAD
+class sync_steppable_vector_mt_t
+{
+	uint64 usecs[MAX_THREADS];
+	uint32 adds;
+	uint32 last_sort_time;
+	LARGE_INTEGER start_li[MAX_THREADS];
+	LARGE_INTEGER finish_li[MAX_THREADS];
+	pthread_spinlock_t del_spin;
+	vector_tpl<sync_steppable*> sync_list[MAX_THREADS];
+	int next_list;
+	bool sync_step_running;
+
+	static bool compare_address(sync_steppable* const one, sync_steppable* const two);
+//protected:
+public:
+	void sync_add( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		const int next_next = (next_list+1)%env_t::num_threads;
+
+		sync_list[next_list].append( obj );
+		if(  sync_list[next_list].get_count() > sync_list[next_next].get_count()+31  ) {
+			next_list = next_next;
+		}
+		adds++;
+/*
+		if(  sync_list[next_list].get_count() < sync_list[next_next].get_count()  ) {
+			sync_list[next_list].append( obj );
+		}
+		else {
+			sync_list[next_next].append( obj );
+		}
+		next_list = next_next;
+*/
+	}
+	bool sync_remove( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			if(  sync_list[i].remove(obj)  ) {
+				return true;
+			}
+		}
+		return false;
+	}
+	uint32 get_count() const {
+		uint32 count = 0;
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			count += sync_list[i].get_count();
+		}
+		return count;
+	}
+	uint32 get_count(uint8 num) const { return sync_list[num].get_count(); }
+	uint32 get_adds() const { return adds; }
+	LARGE_INTEGER get_start(uint8 num) const { return start_li[num]; }
+	LARGE_INTEGER get_finish(uint8 num) const { return finish_li[num]; }
+	uint64 get_usecs() const {
+		uint64 usecss = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) usecss+=usecs[i];
+		return usecss;
+	}
+public:
+	void sort_lists(const uint32 ticks, const char* caller);
+	sint64 sync_step_btd();
+	int sync_step_all(const uint8 num, const uint32 delta_t);
+	void sync_step_ftd(sint64 start);
+	void sync_remove_all();
+
+	sync_steppable_vector_mt_t()
+	{
+		pthread_spin_init(&del_spin, PTHREAD_PROCESS_PRIVATE);
+		next_list = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) usecs[i]=0;
+		adds=0;
+		last_sort_time=0;
+	}
+};
 #endif
+
+
+class sync_steppable_vector_copy_t
+{
+	uint64 usecs;
+	uint32 adds;
+	uint32 last_sort_time;
+	vector_tpl<sync_steppable *> sync_list;
+	vector_tpl<sync_steppable *> sync_list_copy;
+	bool sync_step_running;
+
+	static bool compare_address(sync_steppable* const one, sync_steppable* const two);
+//protected:
+public:
+	void sync_add( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		sync_list.append( obj );
+		adds++;
+	}
+	bool sync_remove( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		return sync_list.remove(obj);
+	}
+	uint32 get_count() const { return sync_list.get_count(); }
+	uint32 get_adds() const { return adds; }
+	uint64 get_usecs() const { return usecs; }
+public:
+	void sort_lists(const uint32 ticks, const char* caller);
+	void sync_step_all(const uint32 delta_t);
+	void sync_remove_all();
+
+	sync_steppable_vector_copy_t( uint64 init_usecs=0 ) : usecs(init_usecs) { adds=0; last_sort_time=0; }
+};
+
+
+#ifdef MULTI_THREAD
+class sync_steppable_vector_copy_mt_t
+{
+	uint64 usecs[MAX_THREADS];
+	uint32 adds;
+	uint32 last_sort_time;
+	LARGE_INTEGER start_li[MAX_THREADS];
+	LARGE_INTEGER finish_li[MAX_THREADS];
+	pthread_spinlock_t del_spin;
+	vector_tpl<sync_steppable*> sync_list[MAX_THREADS];
+	vector_tpl<sync_steppable *> sync_list_copy[MAX_THREADS];
+	int next_list;
+	bool sync_step_running;
+
+	static bool compare_address(sync_steppable* const one, sync_steppable* const two);
+//protected:
+public:
+	void sync_add( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		const int next_next = (next_list+1)%env_t::num_threads;
+
+		sync_list[next_list].append( obj );
+		if(  sync_list[next_list].get_count() > sync_list[next_next].get_count()+31  ) {
+			next_list = next_next;
+		}
+/*
+		if(  sync_list[next_list].get_count() < sync_list[next_next].get_count()  ) {
+			sync_list[next_list].append( obj );
+		}
+		else {
+			sync_list[next_next].append( obj );
+		}
+		next_list = next_next;
+*/
+	}
+	bool sync_remove( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			if(  sync_list[i].remove(obj)  ) {
+				return true;
+			}
+		}
+		return false;
+	}
+	uint32 get_count() const {
+		uint32 count = 0;
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			count += sync_list[i].get_count();
+		}
+		return count;
+	}
+	uint32 get_count(uint8 num) const { return sync_list[num].get_count(); }
+	LARGE_INTEGER get_start(uint8 num) const { return start_li[num]; }
+	LARGE_INTEGER get_finish(uint8 num) const { return finish_li[num]; }
+	uint64 get_usecs() const {
+		uint64 usecss = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) usecss+=usecs[i];
+		return usecss;
+	}
+public:
+	void sort_lists(const uint32 ticks, const char* caller);
+	sint64 sync_step_btd();
+	void sync_step_all(const uint8 num, const uint32 delta_t);
+	void sync_step_ftd(sint64 start);
+	void sync_remove_all();
+
+	sync_steppable_vector_copy_mt_t()
+	{
+		pthread_spin_init(&del_spin, PTHREAD_PROCESS_PRIVATE);
+		next_list = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) usecs[i]=0;
+		adds=0;
+		last_sort_time=0;
+	}
+};
+
+
+class sync_steppable_vector_hole_mt_t
+{
+	uint64 usecs[MAX_THREADS];
+	uint32 adds;
+	uint32 last_sort_time;
+	LARGE_INTEGER start_li[MAX_THREADS];
+	LARGE_INTEGER finish_li[MAX_THREADS];
+	pthread_spinlock_t del_spin;
+	vector_tpl<sync_steppable*> sync_list[MAX_THREADS];
+	int next_list;
+	uint32 hole[MAX_THREADS];
+	bool sync_step_running;
+
+	static bool compare_address(sync_steppable* const one, sync_steppable* const two);
+//protected:
+public:
+	void sync_add( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		const int next_next = (next_list+1)%env_t::num_threads;
+
+		sync_list[next_list].append( obj );
+		if(  sync_list[next_list].get_count() > sync_list[next_next].get_count()+31  ) {
+			next_list = next_next;
+		}
+		adds++;
+/*
+		if(  sync_list[next_list].get_count() < sync_list[next_next].get_count()  ) {
+			sync_list[next_list].append( obj );
+		}
+		else {
+			sync_list[next_next].append( obj );
+		}
+		next_list = next_next;
+*/
+	}
+	bool sync_remove( sync_steppable* obj ) {
+		assert(!sync_step_running);
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			if(  sync_list[i].remove(obj)  ) {
+				return true;
+			}
+		}
+		return false;
+	}
+	uint32 get_count() const {
+		uint32 count = 0;
+		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+			count += sync_list[i].get_count();
+		}
+		return count;
+	}
+	uint32 get_count(uint8 num) const { return sync_list[num].get_count(); }
+	uint32 get_hole(uint8 num) const { return hole[num]; }
+	LARGE_INTEGER get_start(uint8 num) const { return start_li[num]; }
+	LARGE_INTEGER get_finish(uint8 num) const { return finish_li[num]; }
+	uint64 get_usecs() const {
+		uint64 usecss = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) usecss+=usecs[i];
+		return usecss;
+	}
+public:
+	void sort_lists(const uint32 ticks, const char* caller);
+	sint64 sync_step_btd();
+	void sync_step_all(const uint8 num, const uint32 delta_t);
+	void sync_step_ftd(sint64 start);
+	void sync_remove_all();
+
+	sync_steppable_vector_hole_mt_t()
+	{
+		pthread_spin_init(&del_spin, PTHREAD_PROCESS_PRIVATE);
+		next_list = 0;
+		for( int i = 0; i < env_t::num_threads; i++ ) {
+			usecs[i]=0;
+			hole[i]=0;
+		}
+		adds=0;
+		last_sort_time=0;
+	}
+};
+#endif
+
+
+class sync_step_random_t
+{
+	vector_tpl<uint32> rand_list;
+	uint32 last_rand, next_rand;
+	bool overflown;
+
+public:
+	uint32 get_rand( uint32 max ) {
+		if(  max<=1  ) {	// may rather assert this?
+			return 0;
+		}
+
+		if(  next_rand == last_rand ) {
+			overflown = true;
+			// wrap around to reusing rands until list can be refreshed.
+		}
+
+		const uint32 r = rand_list[next_rand++] % max;
+
+		if(   next_rand >= rand_list.get_count()  ) {
+			next_rand = 0;
+		}
+
+		return r;
+	}
+
+	void refresh_list( uint32 num );
+
+	sync_step_random_t() { next_rand = 0; last_rand = 0; overflown = true; }
+};
+
+
+#endif
Index: obj/gebaeude.cc
===================================================================
--- obj/gebaeude.cc	(revision 7507)
+++ obj/gebaeude.cc	(working copy)
@@ -51,6 +51,24 @@
 #include "gebaeude.h"
 
 
+//sync_steppable_vector_mt_t gebaeude_t::gebaeude_sync;
+sync_steppable_vector_t gebaeude_t::gebaeude_sync;
+
+/*  //using freelist with gebaeude crashes on map loading. reason not investigated
+template <typename gebaeude_t> nodelist_node_t* freelist_tpl<gebaeude_t>::chunk_list = NULL;
+template <typename gebaeude_t> nodelist_node_t* freelist_tpl<gebaeude_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+*/
+
 /**
  * Initializes all variables with save, usable values
  * @author Hj. Malthaner
@@ -85,7 +103,7 @@
 		set_yoff(0);
 	}
 	if(tile  &&  tile->get_phasen()>1) {
-		welt->sync_eyecandy_add( this );
+		gebaeude_sync.sync_add(this);
 		sync = true;
 	}
 }
@@ -123,7 +141,7 @@
 
 	if(sync) {
 		sync = false;
-		welt->sync_eyecandy_remove(this);
+		gebaeude_sync.sync_remove(this);
 	}
 
 	// tiles might be invalid, if no description is found during loading
@@ -249,7 +267,7 @@
 #ifdef MULTI_THREAD
 			pthread_mutex_lock( &sync_mutex );
 #endif
-			welt->sync_eyecandy_remove(this);
+			gebaeude_sync.sync_remove(this);
 			sync = false;
 			anim_frame = 0;
 #ifdef MULTI_THREAD
@@ -264,7 +282,7 @@
 #endif
 		anim_frame = sim_async_rand( new_tile->get_phasen() );
 		anim_time = 0;
-		welt->sync_eyecandy_add(this);
+		gebaeude_sync.sync_add(this);
 		sync = true;
 #ifdef MULTI_THREAD
 		pthread_mutex_unlock( &sync_mutex );
@@ -282,7 +300,7 @@
  * Objekte entfernt werden sol
  * @author Hj. Malthaner
  */
-bool gebaeude_t::sync_step(uint32 delta_t)
+int gebaeude_t::sync_step(const uint32 delta_t)
 {
 	if(  zeige_baugrube  ) {
 		// still under construction?
@@ -291,8 +309,9 @@
 			mark_image_dirty( get_image(), 0 );
 			zeige_baugrube = false;
 			if(  tile->get_phasen() <= 1  ) {
-				welt->sync_eyecandy_remove( this );
 				sync = false;
+				return SYNC_REM;
+
 			}
 		}
 	}
@@ -325,7 +344,7 @@
 			}
  		}
  	}
-	return true;
+	return SYNC_OK;
 }
 
 
@@ -979,3 +998,16 @@
 		mark_image_dirty( img, -(i*get_tile_raster_width()) );
 	}
 }
+
+/*
+void *gebaeude_t::operator new(size_t )
+{
+	return freelist_tpl<gebaeude_t>::gimme_node(sizeof(gebaeude_t));
+}
+
+
+void gebaeude_t::operator delete(void *p)
+{
+	freelist_tpl<gebaeude_t>::putback_node(sizeof(gebaeude_t),p);
+}
+*/
Index: obj/gebaeude.h
===================================================================
--- obj/gebaeude.h	(revision 7507)
+++ obj/gebaeude.h	(working copy)
@@ -23,6 +23,9 @@
 class gebaeude_t : public obj_t, sync_steppable
 {
 public:
+//	static sync_steppable_vector_mt_t gebaeude_sync;
+	static sync_steppable_vector_t gebaeude_sync;
+
 	/**
 	 * Vom typ "unbekannt" sind auch spezielle gebaeude z.B. das Rathaus
 	 * @author Hj. Malthaner
@@ -161,7 +164,7 @@
 	 * @return true
 	 * @author Hj. Malthaner
 	 */
-	bool sync_step(uint32 delta_t);
+	int sync_step(const uint32 delta_t);
 
 	/**
 	 * @return Den level (die Ausbaustufe) des Gebaudes
@@ -190,6 +193,9 @@
 	 * @returns true if both building tiles are part of one (multi-tile) building.
 	 */
 	bool is_same_building(gebaeude_t* other);
+
+//	void * operator new(size_t s);
+//	void operator delete(void *p);
 };
 
 
Index: obj/leitung2.cc
===================================================================
--- obj/leitung2.cc	(revision 7507)
+++ obj/leitung2.cc	(working copy)
@@ -570,8 +570,24 @@
 /************************************ From here on drain stuff ********************************************/
 
 slist_tpl<senke_t *> senke_t::senke_list;
+//sync_steppable_vector_mt_t senke_t::senke_sync;
+sync_steppable_vector_t senke_t::senke_sync;
 
 
+template <typename senke_t> nodelist_node_t* freelist_tpl<senke_t>::chunk_list = NULL;
+template <typename senke_t> nodelist_node_t* freelist_tpl<senke_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 void senke_t::neue_karte()
 {
 	senke_list.clear();
@@ -589,37 +605,38 @@
 senke_t::senke_t(loadsave_t *file) : leitung_t( koord3d::invalid, NULL )
 {
 	fab = NULL;
-	einkommen = 0;
-	max_einkommen = 1;
+	delta_sum = 0;
 	next_t = 0;
-	delta_sum = 0;
 	last_power_demand = 0;
 	power_load = 0;
+	max_einkommen = 1;
+	einkommen = 0;
 	rdwr( file );
-	welt->sync_add(this);
+	senke_sync.sync_add(this);
 }
 
 
 senke_t::senke_t(koord3d pos, player_t *player) : leitung_t(pos, player)
 {
 	fab = NULL;
-	einkommen = 0;
-	max_einkommen = 1;
+	delta_sum = 0;
 	next_t = 0;
-	delta_sum = 0;
 	last_power_demand = 0;
 	power_load = 0;
+	max_einkommen = 1;
+	einkommen = 0;
 	player_t::book_construction_costs(player, welt->get_settings().cst_transformer, get_pos().get_2d(), powerline_wt);
-	welt->sync_add(this);
+	senke_sync.sync_add(this);
 }
 
 
 senke_t::~senke_t()
 {
-	welt->sync_remove( this );
+	senke_sync.sync_remove(this); // this needs to be handled ************************************************************************************** when allowing deletes during sync_step instead of del list
+
 	if(fab!=NULL) {
 		fab->set_transformer_connected( false );
-		fab = NULL;
+//		fab = NULL;
 	}
 	senke_list.remove( this );
 	player_t::add_maintenance(get_owner(), (sint32)welt->get_settings().cst_maintain_transformer, powerline_wt);
@@ -678,10 +695,10 @@
 }
 
 
-bool senke_t::sync_step(uint32 delta_t)
+int senke_t::sync_step(const uint32 delta_t)
 {
 	if(fab==NULL) {
-		return false;
+		return SYNC_REM_DEL;
 	}
 
 	delta_sum += delta_t;
@@ -729,7 +746,7 @@
 			set_bild( new_bild );
 		}
 	}
-	return true;
+	return SYNC_OK;
 }
 
 
@@ -779,3 +796,16 @@
 	buf.printf( translator::translate("Supplied: %u %%"), (100*power_load)/(last_power_demand>0?last_power_demand:1) );
 	buf.printf("\n\n"); // pad for consistent dialog size
 }
+
+
+void *senke_t::operator new(size_t )
+{
+	return freelist_tpl<senke_t>::gimme_node(sizeof(senke_t));
+}
+
+
+void senke_t::operator delete(void *p)
+{
+	freelist_tpl<senke_t>::putback_node(sizeof(senke_t),p);
+}
+
Index: obj/leitung2.h
===================================================================
--- obj/leitung2.h	(revision 7507)
+++ obj/leitung2.h	(working copy)
@@ -133,7 +133,6 @@
 };
 
 
-
 class pumpe_t : public leitung_t
 {
 public:
@@ -167,23 +166,24 @@
 };
 
 
-
 class senke_t : public leitung_t, public sync_steppable
 {
 public:
 	static void neue_karte();
 	static void step_all(uint32 delta_t);
+//	static sync_steppable_vector_mt_t senke_sync;
+	static sync_steppable_vector_t senke_sync;
 
 private:
 	static slist_tpl<senke_t *> senke_list;
 
-	sint32 einkommen;
-	sint32 max_einkommen;
 	fabrik_t *fab;
-	sint32 delta_sum;
-	sint32 next_t;
+	sint16 delta_sum;
+	sint16 next_t;
 	uint32 last_power_demand;
 	uint32 power_load;
+	sint32 max_einkommen;
+	sint32 einkommen;
 
 	void step(uint32 delta_t);
 
@@ -196,7 +196,7 @@
 
 	// used to alternate between displaying power on and power off images at a frequency determined by the percentage of power supplied
 	// gives players a visual indication of a power network with insufficient generation
-	bool sync_step(uint32 delta_t);
+	int sync_step(const uint32 delta_t);
 
 	const char *get_name() const {return "Abspanntransformator";}
 
@@ -207,6 +207,9 @@
 	void calc_image() {}	// otherwise it will change to leitung
 
 	const fabrik_t* get_factory() const { return fab; }
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 
Index: obj/roadsign.cc
===================================================================
--- obj/roadsign.cc	(revision 7507)
+++ obj/roadsign.cc	(working copy)
@@ -46,7 +46,23 @@
 
 stringhashtable_tpl<const roadsign_besch_t *> roadsign_t::table;
 
+//sync_steppable_vector_mt_t roadsign_t::roadsign_sync;
+sync_steppable_vector_t roadsign_t::roadsign_sync;
 
+template <typename roadsign_t> nodelist_node_t* freelist_tpl<roadsign_t>::chunk_list = NULL;
+template <typename roadsign_t> nodelist_node_t* freelist_tpl<roadsign_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 roadsign_t::roadsign_t(loadsave_t *file) : obj_t ()
 {
 	bild = after_bild = IMG_LEER;
@@ -67,7 +83,7 @@
 	}
 	// only traffic light need switches
 	if(  automatic  ) {
-		welt->sync_add(this);
+		roadsign_sync.sync_add(this);
 	}
 }
 
@@ -75,12 +91,12 @@
 roadsign_t::roadsign_t(player_t *player, koord3d pos, ribi_t::ribi dir, const roadsign_besch_t *besch, bool preview) : obj_t(pos)
 {
 	this->besch = besch;
+	ticks_offset = 0;
+	ticks_ns = ticks_ow = 16;
+	zustand = 0;
 	this->dir = dir;
 	this->preview = preview;
 	bild = after_bild = IMG_LEER;
-	zustand = 0;
-	ticks_ns = ticks_ow = 16;
-	ticks_offset = 0;
 	set_owner( player );
 	if(  besch->is_private_way()  ) {
 		// init ownership of private ways
@@ -92,13 +108,11 @@
 			ticks_ns = 1 << player->get_player_nr();
 		}
 	}
-	/* if more than one state, we will switch direction and phase for traffic lights
-	 * however also gate signs need indications
-	 */
+
+	// if more than one state, we will switch direction and phase for traffic lights. also gate signs need indications
 	automatic = (besch->get_bild_anzahl()>4  &&  besch->get_wtyp()==road_wt)  ||  (besch->get_bild_anzahl()>2  &&  besch->is_private_way());
-	// only traffic light need switches
 	if(  automatic  ) {
-		welt->sync_add(this);
+		roadsign_sync.sync_add(this);
 	}
 }
 
@@ -124,7 +138,7 @@
 		}
 	}
 	if(automatic) {
-		welt->sync_remove(this);
+		roadsign_sync.sync_remove(this); // never deleted during sync_step. OK.
 	}
 }
 
@@ -450,9 +464,9 @@
 
 
 // only used for traffic light: change the current state
-bool roadsign_t::sync_step(uint32 /*delta_t*/)
+int roadsign_t::sync_step(const uint32 /*delta_t*/)
 {
-	if(  besch->is_private_way()  ) {
+	if(  besch->is_private_way()  ) {  // cache last player number to avoid marking image dirty every ss. room for uint8 in class without growing ///////////////////////////////////////
 		uint8 image = 1-(dir&1);
 		if(  (1<<welt->get_active_player_nr()) & get_player_mask()  ) {
 			// gate open
@@ -473,7 +487,7 @@
 			calc_image();
 		}
 	}
-	return true;
+	return SYNC_OK;
 }
 
 
@@ -728,3 +742,16 @@
 	}
 	return NULL;
 }
+
+
+void *roadsign_t::operator new(size_t )
+{
+	return freelist_tpl<roadsign_t>::gimme_node(sizeof(roadsign_t));
+}
+
+
+void roadsign_t::operator delete(void *p)
+{
+	freelist_tpl<roadsign_t>::putback_node(sizeof(roadsign_t),p);
+}
+
Index: obj/roadsign.h
===================================================================
--- obj/roadsign.h	(revision 7507)
+++ obj/roadsign.h	(working copy)
@@ -24,24 +24,24 @@
 class roadsign_t : public obj_t, public sync_steppable
 {
 protected:
-	image_id bild;
-	image_id after_bild;
-
 	enum { SHOW_FONT=1, SHOW_BACK=2, SWITCH_AUTOMATIC=16 };
 
+	const roadsign_besch_t *besch;
+
+	uint8 ticks_offset;
+	uint8 ticks_ns;
+	uint8 ticks_ow;
+
 	uint8 zustand:2;	// counter for steps ...
 	uint8 dir:4;
-
 	uint8 automatic:1;
 	uint8 preview:1;
-	uint8 ticks_ns;
-	uint8 ticks_ow;
-	uint8 ticks_offset;
 
+	image_id bild;
+	image_id after_bild;
+
 	sint8 after_yoffset, after_xoffset;
 
-	const roadsign_besch_t *besch;
-
 	ribi_t::ribi calc_mask() const { return ribi_t::ist_einfach(dir) ? dir : (ribi_t::ribi)ribi_t::keine; }
 public:
 	enum signalzustand {rot=0, gruen=1, naechste_rot=2 };
@@ -102,7 +102,7 @@
 	bool is_free_route(uint8 check_dir) const { return besch->is_choose_sign() &&  check_dir == dir; }
 
 	// changes the state of a traffic light
-	bool sync_step(uint32);
+	int sync_step(const uint32);
 
 	// change the phases of the traffic lights
 	uint8 get_ticks_ns() const { return ticks_ns; }
@@ -151,6 +151,8 @@
 	static const roadsign_besch_t *default_signal;
 
 public:
+//	static sync_steppable_vector_mt_t roadsign_sync;
+	static sync_steppable_vector_t roadsign_sync;
 	static bool register_besch(roadsign_besch_t *besch);
 	static bool alles_geladen();
 
@@ -163,6 +165,9 @@
 	static const roadsign_besch_t *roadsign_search(roadsign_besch_t::types flag, const waytype_t wt, const uint16 time);
 
 	static const roadsign_besch_t *find_besch(const char *name) { return table.get(name); }
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 #endif
Index: obj/wolke.cc
===================================================================
--- obj/wolke.cc	(revision 7507)
+++ obj/wolke.cc	(working copy)
@@ -18,6 +18,28 @@
 #include "../tpl/vector_tpl.h"
 
 
+//sync_steppable_vector_copy_mt_t wolke_t::wolke_sync;
+//sync_steppable_vector_hole_mt_t wolke_t::wolke_sync;
+//sync_steppable_vector_mt_t wolke_t::wolke_sync;
+//sync_steppable_vector_t wolke_t::wolke_sync;
+sync_steppable_vector_copy_t wolke_t::wolke_sync;
+
+
+template <typename wolke_t> nodelist_node_t* freelist_tpl<wolke_t>::chunk_list = NULL;
+template <typename wolke_t> nodelist_node_t* freelist_tpl<wolke_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
+
 vector_tpl<const skin_besch_t *>wolke_t::all_clouds(0);
 
 bool wolke_t::register_besch(const skin_besch_t* besch)
@@ -37,11 +59,13 @@
 wolke_t::wolke_t(koord3d pos, sint8 x_off, sint8 y_off, const skin_besch_t* besch ) :
 	obj_no_info_t(pos)
 {
-	cloud_nr = all_clouds.index_of(besch);
+	insta_zeit = 0;
 	base_y_off = clamp( (sint16)y_off - 8, -128, 127 );
+	cloud_nr = all_clouds.index_of( besch );
+
 	set_xoff( x_off );
 	set_yoff( base_y_off );
-	insta_zeit = 0;
+	wolke_sync.sync_add(this);
 }
 
 
@@ -50,9 +74,7 @@
 {
 	mark_image_dirty( get_image(), 0 );
 	if(  insta_zeit != 2499  ) {
-		if(  !welt->sync_way_eyecandy_remove( this )  ) {
-			dbg->error( "wolke_t::~wolke_t()", "wolke not in the correct sync list" );
-		}
+		wolke_sync.sync_remove(this);
 	}
 }
 
@@ -95,25 +117,26 @@
 
 
 
-bool wolke_t::sync_step(uint32 delta_t)
+int wolke_t::sync_step(const uint32 delta_t)
 {
 	insta_zeit += delta_t;
-	if(insta_zeit>=2499) {
+	if(  insta_zeit >= 2499  ) {
 		// delete wolke ...
 		insta_zeit = 2499;
-		return false;
+		return SYNC_REM_DEL;
 	}
-	// move cloud up
-	sint8 ymove = ((insta_zeit*OBJECT_OFFSET_STEPS) >> 12);
-	if(  base_y_off-ymove!=get_yoff()  ) {
+
+ 	// move cloud up
+	const sint8 new_yoff = base_y_off - ((insta_zeit * OBJECT_OFFSET_STEPS) >> 12);
+	if(  new_yoff != get_yoff()  ) {
 		// move/change cloud ... (happens much more often than image change => image change will be always done when drawing)
-		if(!get_flag(obj_t::dirty)) {
-			mark_image_dirty(get_image(),0);
+		if(  !get_flag( obj_t::dirty )  ) {
+			set_flag( obj_t::dirty );
+			mark_image_dirty( get_image(), 0 );
 		}
-		set_yoff(  base_y_off - ymove  );
-		set_flag(obj_t::dirty);
+		set_yoff( new_yoff );
 	}
-	return true;
+	return SYNC_OK;
 }
 
 
@@ -128,6 +151,19 @@
 	set_yoff( base_y_off - ((insta_zeit*OBJECT_OFFSET_STEPS) >> 12) );
 }
 
+
+void *wolke_t::operator new(size_t )
+{
+	return freelist_tpl<wolke_t>::gimme_node(sizeof(wolke_t));
+}
+
+
+void wolke_t::operator delete(void *p)
+{
+	freelist_tpl<wolke_t>::putback_node(sizeof(wolke_t),p);
+}
+
+
 /***************************** just for compatibility, the old raucher and smoke clouds *********************************/
 
 raucher_t::raucher_t(loadsave_t *file) : obj_t()
Index: obj/wolke.h
===================================================================
--- obj/wolke.h	(revision 7507)
+++ obj/wolke.h	(working copy)
@@ -28,7 +28,12 @@
 	wolke_t(koord3d pos, sint8 xoff, sint8 yoff, const skin_besch_t *cloud );
 	~wolke_t();
 
-	bool sync_step(uint32 delta_t);
+//	static sync_steppable_vector_copy_mt_t wolke_sync;
+//	static sync_steppable_vector_hole_mt_t wolke_sync;
+//	static sync_steppable_vector_mt_t wolke_sync;
+//	static sync_steppable_vector_t wolke_sync;
+	static sync_steppable_vector_copy_t wolke_sync;
+	int sync_step(const uint32 delta_t);
 
 	const char* get_name() const { return "Wolke"; }
 	typ get_typ() const { return sync_wolke; }
@@ -38,6 +43,9 @@
 	void rdwr(loadsave_t *file);
 
 	virtual void rotate90();
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 
Index: player/ai_goods.cc
===================================================================
--- player/ai_goods.cc	(revision 7507)
+++ player/ai_goods.cc	(working copy)
@@ -1157,7 +1157,7 @@
 								convoihandle_t cnv = line->get_convoy(0);
 								cnv->self_destruct();
 								if(cnv.is_bound()) {
-									cnv->step();
+									cnv->step(0);
 								}
 							}
 							simlinemgmt.delete_line( line );
@@ -1258,7 +1258,7 @@
 
 					cnv->self_destruct();
 					if(cnv.is_bound()) {
-						cnv->step();	// to really get rid of it
+						cnv->step(0);	// to really get rid of it
 					}
 
 					// last vehicle on that connection (no line => railroad)
@@ -1278,7 +1278,7 @@
 										convoihandle_t cnv = line->get_convoy(0);
 										cnv->self_destruct();
 										if(cnv.is_bound()) {
-											cnv->step();
+											cnv->step(0);
 										}
 									}
 									simlinemgmt.delete_line( line );
Index: player/simplay.cc
===================================================================
--- player/simplay.cc	(revision 7507)
+++ player/simplay.cc	(working copy)
@@ -451,9 +451,9 @@
 
 		linehandle_t line = cnv->get_line();
 
-		if(  cnv->get_state() != convoi_t::INITIAL  ) {
+		if(  !cnv->in_depot()  ) {
 			cnv->self_destruct();
-			cnv->step();	// to really get rid of it
+			cnv->step(0);	// to really get rid of it
 		}
 		else {
 			// convois in depots are directly destroyed
Index: simcity.cc
===================================================================
--- simcity.cc	(revision 7507)
+++ simcity.cc	(working copy)
@@ -1557,7 +1557,6 @@
 				if (gr != NULL && gr->get_weg(road_wt) && ribi_t::is_twoway(gr->get_weg_ribi_unmasked(road_wt)) && gr->find<private_car_t>() == NULL) {
 					private_car_t* vt = new private_car_t(gr, koord::invalid);
 					gr->obj_add(vt);
-					welt->sync_add(vt);
 					number_of_cars--;
 				}
 			}
@@ -2752,7 +2751,6 @@
 						if (!private_car_t::list_empty()) {
 							private_car_t* vt = new private_car_t(gr, target);
 							gr->obj_add(vt);
-							welt->sync_add(vt);
 						}
 						return;
 					}
Index: simconst.h
===================================================================
--- simconst.h	(revision 7507)
+++ simconst.h	(working copy)
@@ -45,13 +45,6 @@
 // define this for automaticcally joining stations next to a public stop with it
 //#define AUTOJOIN_PUBLIC
 
-// vector_tpl can be faster for sync_lists
-#define SYNC_VECTOR
-
-// stuff often deleted may be even faster with a hastable, but order is lost and iteration is slower
-// #define SYNC_WAY_HASHTABLE
-// #define SYNC_WAY_LIST
-
 // allow minspeed and private way signs on waterways (imho pointless)
 //#define ENABLE_WATERWAY_SIGNS
 
Index: simconvoi.cc
===================================================================
--- simconvoi.cc	(revision 7507)
+++ simconvoi.cc	(working copy)
@@ -64,6 +64,22 @@
 
 karte_ptr_t convoi_t::welt;
 
+sync_steppable_vector_t convoi_sync_t::convoi_sync;
+
+template <typename convoi_sync_t> nodelist_node_t* freelist_tpl<convoi_sync_t>::chunk_list = NULL;
+template <typename convoi_sync_t> nodelist_node_t* freelist_tpl<convoi_sync_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 /*
  * Debugging helper - translate state value to human readable name
  * @author Hj- Malthaner
@@ -104,80 +120,115 @@
 }
 
 
+convoi_sync_t::convoi_sync_t() : fahr( convoi_t::max_vehicle, NULL )
+{
+
+	wait_lock = 0;
+	next_wolke = 0; // *** init with simrand to spread out smoke??? *** //
+
+	state = convoi_t::INITIAL;
+
+	speed_limit = 0; // not in convoi_init???
+	min_top_speed = SPEED_UNLIMITED;
+
+	sum_gesamtgewicht = 0;
+	sum_friction_weight = 0; // not in convoi_init???
+
+	withdraw = false;
+	no_load = false;
+	freight_info_resort = true;
+	has_obsolete = false;
+	is_electric = false;
+	recalc_data_front = true;
+	recalc_data = true;
+
+	anz_vehikel = 0;
+	next_stop_index = 65535u;
+	brake_speed_soll = SPEED_UNLIMITED;
+	distance_since_last_stop = 0;
+	sum_speed_limit = 0;
+	akt_speed_soll = 0;            // Sollgeschwindigkeit
+	akt_speed = 0;                 // momentane Geschwindigkeit
+	sum_gear_und_leistung = 0;
+	previous_delta_v = 0;
+	max_record_speed = 0;
+	sp_soll = 0;
+	arrived_time = 0; // newly added - not in place yet
+
+}
+
+
+convoi_sync_t::~convoi_sync_t()
+{
+
+}
+
+
+void *convoi_sync_t::operator new(size_t )
+{
+	return freelist_tpl<convoi_sync_t>::gimme_node(sizeof(convoi_sync_t));
+}
+
+
+void convoi_sync_t::operator delete(void *p)
+{
+	freelist_tpl<convoi_sync_t>::putback_node(sizeof(convoi_sync_t),p);
+}
+
+
 void convoi_t::init(player_t *player)
 {
 	owner_p = player;
 
-	is_electric = false;
-	sum_gesamtgewicht = sum_gewicht = 0;
-	sum_running_costs = sum_gear_und_leistung = previous_delta_v = 0;
+	cnv_sync = new convoi_sync_t();
+
+	sum_gewicht = 0;
+	sum_running_costs = 0;
 	sum_leistung = 0;
-	min_top_speed = SPEED_UNLIMITED;
 	speedbonus_kmh = SPEED_UNLIMITED; // speed_to_kmh() not needed
 
 	fpl = NULL;
 	fpl_target = koord3d::invalid;
 	line = linehandle_t();
 
-	anz_vehikel = 0;
 	steps_driven = -1;
-	withdraw = false;
-	has_obsolete = false;
-	no_load = false;
-	wait_lock = 0;
-	arrived_time = 0;
 
 	jahresgewinn = 0;
 	total_distance_traveled = 0;
 
-	distance_since_last_stop = 0;
-	sum_speed_limit = 0;
 	maxspeed_average_count = 0;
 	next_reservation_index = 0;
 
 	alte_richtung = ribi_t::keine;
-	next_wolke = 0;
 
-	state = INITIAL;
-
 	*name_and_id = 0;
 	name_offset = 0;
 
-	freight_info_resort = true;
 	freight_info_order = 0;
 	loading_level = 0;
 	loading_limit = 0;
 
-	max_record_speed = 0;
-	brake_speed_soll = SPEED_UNLIMITED;
-	akt_speed_soll = 0;            // target speed
-	akt_speed = 0;                 // current speed
-	sp_soll = 0;
-
-	next_stop_index = 65535;
-
 	line_update_pending = linehandle_t();
 
 	home_depot = koord3d::invalid;
-
-	recalc_data_front = true;
-	recalc_data = true;
 }
 
 
-convoi_t::convoi_t(loadsave_t* file) : fahr(max_vehicle, NULL)
+convoi_t::convoi_t(loadsave_t* file)
 {
 	self = convoihandle_t();
 	init(0);
 	rdwr(file);
+	cnv_sync->cnv = self;
 }
 
 
-convoi_t::convoi_t(player_t* player_) : fahr(max_vehicle, NULL)
+convoi_t::convoi_t(player_t* player_)
 {
 	self = convoihandle_t(this);
 	player_->book_convoi_number(1);
 	init(player_);
+	cnv_sync->cnv = self;
 	set_name( "Unnamed" );
 	welt->add_convoi( self );
 	init_financial_history();
@@ -189,7 +240,7 @@
 	owner_p->book_convoi_number( -1);
 
 	assert(self.is_bound());
-	assert(anz_vehikel==0);
+	assert(cnv_sync->anz_vehikel==0);
 
 	// close windows
 	destroy_win( magic_convoi_info+self.get_id() );
@@ -201,7 +252,7 @@
 		welt->get_viewport()->set_follow_convoi( convoihandle_t() );
 	}
 
-	welt->sync_remove( this );
+	cnv_sync->convoi_sync.sync_remove(cnv_sync);
 	welt->rem_convoi( self );
 
 	// Knightly : if lineless convoy -> unregister from stops
@@ -223,6 +274,8 @@
 	// @author hsiegeln - deregister from line (again) ...
 	unset_line();
 
+	delete cnv_sync;
+
 	self.detach();
 }
 
@@ -230,7 +283,7 @@
 // waypoint: no stop, resp. for airplanes in air (i.e. no air strip below)
 bool convoi_t::is_waypoint( koord3d ziel ) const
 {
-	if(  fahr[0]->get_waytype() == air_wt  ) {
+	if(  front()->get_waytype() == air_wt  ) {
 		// separate logic for airplanes, since the can have waypoints over stops etc.
 		grund_t *gr = welt->lookup_kartenboden(ziel.get_2d());
 		if(  gr == NULL  ||  gr->get_weg(air_wt) == NULL  ) {
@@ -254,8 +307,8 @@
 {
 	// need a route, vehicles, and vehicles must belong to this convoi
 	// (otherwise crash during loading when fahr[0]->convoi is not initialized yet
-	if(  !route.empty()  &&  anz_vehikel>0  &&  fahr[0]->get_convoi() == this  ) {
-		rail_vehicle_t* lok = dynamic_cast<rail_vehicle_t*>(fahr[0]);
+	if(  !route.empty()  &&  cnv_sync->anz_vehikel>0  &&  front()->get_convoi() == this  ) {
+		rail_vehicle_t* lok = dynamic_cast<rail_vehicle_t*>(front());
 		if (lok) {
 			// free all reserved blocks
 			uint16 dummy;
@@ -270,7 +323,7 @@
  */
 void convoi_t::reserve_route()
 {
-	if(  !route.empty()  &&  anz_vehikel>0  &&  (is_waiting()  ||  state==DRIVING  ||  state==LEAVING_DEPOT)  ) {
+	if(  !route.empty()  &&  cnv_sync->anz_vehikel > 0  &&  (is_waiting()  ||  get_state() == DRIVING  ||  get_state() == LEAVING_DEPOT)  ) {
 		for(  int idx = back()->get_route_index();  idx < next_reservation_index  /*&&  idx < route.get_count()*/;  idx++  ) {
 			if(  grund_t *gr = welt->lookup( route.position_bei(idx) )  ) {
 				if(  schiene_t *sch = (schiene_t *)gr->get_weg( front()->get_waytype() )  ) {
@@ -294,8 +347,8 @@
 	grund_t* gr = welt->lookup(k);
 
 	uint32 train_length = 0;
-	for (unsigned i = 0; i != anz_vehikel; ++i) {
-		vehicle_t& v = *fahr[i];
+	for (unsigned i = 0; i != cnv_sync->anz_vehikel; ++i) {
+		vehicle_t& v = *(cnv_sync->fahr[i]);
 
 		if(  grund_t const* gr = welt->lookup(v.get_pos())  ) {
 			v.mark_image_dirty(v.get_image(), 0);
@@ -312,7 +365,7 @@
 			v.enter_tile(gr);
 		}
 
-		if (i != anz_vehikel - 1U) {
+		if (i != cnv_sync->anz_vehikel - 1U) {
 			train_length += v.get_besch()->get_length();
 		}
 	}
@@ -323,29 +376,29 @@
 void convoi_t::finish_rd()
 {
 	if(fpl==NULL) {
-		if(  state!=INITIAL  ) {
+		if(  get_state() != INITIAL  ) {
 			grund_t *gr = welt->lookup(home_depot);
 			if(gr  &&  gr->get_depot()) {
 				dbg->warning( "convoi_t::finish_rd()","No schedule during loading convoi %i: State will be initial!", self.get_id() );
-				for( uint8 i=0;  i<anz_vehikel;  i++ ) {
-					fahr[i]->set_pos(home_depot);
+				for( uint8 i=0;  i<cnv_sync->anz_vehikel;  i++ ) {
+					cnv_sync->fahr[i]->set_pos( home_depot );
 				}
-				state = INITIAL;
+				cnv_sync->state = INITIAL;
 			}
 			else {
 				dbg->error( "convoi_t::finish_rd()","No schedule during loading convoi %i: Convoi will be destroyed!", self.get_id() );
-				for( uint8 i=0;  i<anz_vehikel;  i++ ) {
-					fahr[i]->set_pos(koord3d::invalid);
+				for( uint8 i=0;  i<cnv_sync->anz_vehikel;  i++ ) {
+					cnv_sync->fahr[i]->set_pos( koord3d::invalid );
 				}
 				destroy();
 				return;
 			}
 		}
 		// anyway reassign convoi pointer ...
-		for( uint8 i=0;  i<anz_vehikel;  i++ ) {
-			vehicle_t* v = fahr[i];
+		for( uint8 i=0;  i<cnv_sync->anz_vehikel;  i++ ) {
+			vehicle_t* v = cnv_sync->fahr[i];
 			v->set_convoi(this);
-			if(  state!=INITIAL  &&  welt->lookup(v->get_pos())  ) {
+			if(  cnv_sync->state!=INITIAL  &&  welt->lookup(v->get_pos())  ) {
 				// mark vehicle as used
 				v->set_driven();
 			}
@@ -355,20 +408,20 @@
 	else {
 		// restore next schedule target for non-stop waypoint handling
 		const koord3d ziel = fpl->get_current_eintrag().pos;
-		if(  anz_vehikel>0  &&  is_waypoint(ziel)  ) {
+		if(  cnv_sync->anz_vehikel>0  &&  is_waypoint(ziel)  ) {
 			fpl_target = ziel;
 		}
 	}
 
 	bool realing_position = false;
-	if(  anz_vehikel>0  ) {
-DBG_MESSAGE("convoi_t::finish_rd()","state=%s, next_stop_index=%d", state_names[state] );
+	if(  cnv_sync->anz_vehikel>0  ) {
+DBG_MESSAGE("convoi_t::finish_rd()","state=%s, next_stop_index=%d", state_names[cnv_sync->state], cnv_sync->next_stop_index );
 		// only realign convois not leaving depot to avoid jumps through signals
 		if(  steps_driven!=-1  ) {
-			for( uint8 i=0;  i<anz_vehikel;  i++ ) {
-				vehicle_t* v = fahr[i];
+			for( uint8 i=0;  i<cnv_sync->anz_vehikel;  i++ ) {
+				vehicle_t* v = cnv_sync->fahr[i];
 				v->set_leading( i==0 );
-				v->set_last( i+1==anz_vehikel );
+				v->set_last( i+1==cnv_sync->anz_vehikel );
 				v->calc_height();
 				// this sets the convoi and will renew the block reservation, if needed!
 				v->set_convoi(this);
@@ -379,10 +432,10 @@
 			sint16 step_pos = 0;
 			koord3d drive_pos;
 			uint8 const diagonal_vehicle_steps_per_tile = (uint8)(130560U / welt->get_settings().get_pak_diagonal_multiplier());
-			for( uint8 i=0;  i<anz_vehikel;  i++ ) {
-				vehicle_t* v = fahr[i];
+			for( uint8 i=0;  i<cnv_sync->anz_vehikel;  i++ ) {
+				vehicle_t* v = cnv_sync->fahr[i];
 				v->set_leading( i==0 );
-				v->set_last( i+1==anz_vehikel );
+				v->set_last( i+1==cnv_sync->anz_vehikel );
 				v->calc_height();
 				// this sets the convoi and will renew the block reservation, if needed!
 				v->set_convoi(this);
@@ -390,10 +443,10 @@
 				// wrong alignment here => must relocate
 				if(v->need_realignment()) {
 					// diagonal => convoi must restart
-					realing_position |= ribi_t::ist_kurve(v->get_direction())  &&  (state==DRIVING  ||  is_waiting());
+					realing_position |= ribi_t::ist_kurve(v->get_direction())  &&  (cnv_sync->state==DRIVING  ||  is_waiting());
 				}
 				// if version is 99.17 or lower, some convois are broken, i.e. had too large gaps between vehicles
-				if(  !realing_position  &&  state!=INITIAL  &&  state!=LEAVING_DEPOT  ) {
+				if(  !realing_position  &&  cnv_sync->state!=INITIAL  &&  cnv_sync->state!=LEAVING_DEPOT  ) {
 					if(  i==0  ) {
 						step_pos = v->get_steps();
 					}
@@ -419,7 +472,7 @@
 				}
 			}
 		}
-DBG_MESSAGE("convoi_t::finish_rd()","next_stop_index=%d", next_stop_index );
+DBG_MESSAGE("convoi_t::finish_rd()","next_stop_index=%d", cnv_sync->next_stop_index );
 
 		linehandle_t new_line  = line;
 		if(  !new_line.is_bound()  ) {
@@ -458,62 +511,62 @@
 		return;
 	}
 	// put convoi again right on track?
-	if(realing_position  &&  anz_vehikel>1) {
+	if(realing_position  &&  cnv_sync->anz_vehikel>1) {
 		// display just a warning
 		dbg->warning("convoi_t::finish_rd()","cnv %i is currently too long.",self.get_id());
 
 		if (route.empty()) {
 			// realigning needs a route
-			state = NO_ROUTE;
+			cnv_sync->state = NO_ROUTE;
 			owner_p->report_vehicle_problem( self, koord3d::invalid );
-			dbg->error( "convoi_t::finish_rd()", "No valid route, but needs realignment at (%s)!", fahr[0]->get_pos().get_str() );
+			dbg->error( "convoi_t::finish_rd()", "No valid route, but needs realignment at (%s)!", front()->get_pos().get_str() );
 		}
 		else {
 			// since start may have been changed
-			uint16 start_index = max(1,fahr[anz_vehikel-1]->get_route_index())-1;
+			uint16 start_index = max(1,back()->get_route_index())-1;
 
 			uint32 train_length = move_to(start_index) + 1;
-			const koord3d last_start = fahr[0]->get_pos();
+			const koord3d last_start = front()->get_pos();
 
 			// now advance all convoi until it is completely on the track
-			fahr[0]->set_leading(false); // switches off signal checks ...
-			for(unsigned i=0; i<anz_vehikel; i++) {
-				vehicle_t* v = fahr[i];
+			front()->set_leading(false); // switches off signal checks ...
+			for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+				vehicle_t* v = cnv_sync->fahr[i];
 
 				v->get_smoke(false);
-				fahr[i]->do_drive( (VEHICLE_STEPS_PER_CARUNIT*train_length)<<YARDS_PER_VEHICLE_STEP_SHIFT );
+				cnv_sync->fahr[i]->do_drive( (VEHICLE_STEPS_PER_CARUNIT*train_length)<<YARDS_PER_VEHICLE_STEP_SHIFT );
 				train_length -= v->get_besch()->get_length();
 				v->get_smoke(true);
 
 				// eventually reserve this again
 				grund_t *gr=welt->lookup(v->get_pos());
 				// airplanes may have no ground ...
-				if (schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(fahr[i]->get_waytype()))) {
+				if (schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(cnv_sync->fahr[i]->get_waytype()))) {
 					sch0->reserve(self,ribi_t::keine);
 				}
 			}
-			fahr[0]->set_leading(true);
-			if(  state != INITIAL  &&  state != FAHRPLANEINGABE  &&  fahr[0]->get_pos() != last_start  ) {
-				state = WAITING_FOR_CLEARANCE;
+			front()->set_leading(true);
+			if(  cnv_sync->state != INITIAL  &&  cnv_sync->state != FAHRPLANEINGABE  &&  front()->get_pos() != last_start  ) {
+				cnv_sync->state = WAITING_FOR_CLEARANCE;
 			}
 		}
 	}
-	if(  state==LOADING  ) {
+	if(  cnv_sync->state==LOADING  ) {
 		// the fully the shorter => register again as older convoi
-		wait_lock = 2000-loading_level*20;
+		cnv_sync->wait_lock = 2000-loading_level*20;
 	}
 	// when saving with open window, this can happen
-	if(  state==FAHRPLANEINGABE  ) {
+	if(  cnv_sync->state==FAHRPLANEINGABE  ) {
 		if (env_t::networkmode) {
-			wait_lock = 30000; // 60s to drive on, if the client in question had left
+			cnv_sync->wait_lock = 30000; // 30s to drive on, if the client in question had left
 		}
 		fpl->eingabe_abschliessen();
 	}
 	// remove wrong freight
 	check_freight();
 	// some convois had wrong old direction in them
-	if(  state<DRIVING  ||  state==LOADING  ) {
-		alte_richtung = fahr[0]->get_direction();
+	if(  cnv_sync->state<DRIVING  ||  cnv_sync->state==LOADING  ) {
+		alte_richtung = front()->get_direction();
 	}
 	// Knightly : if lineless convoy -> register itself with stops
 	if(  !line.is_bound()  ) {
@@ -542,7 +595,7 @@
 
 void convoi_t::rotate90( const sint16 y_size )
 {
-	record_pos.rotate90( y_size );
+	cnv_sync->record_pos.rotate90( y_size );
 	home_depot.rotate90( y_size );
 	route.rotate90( y_size );
 	if(  fpl_target!=koord3d::invalid  ) {
@@ -551,8 +604,8 @@
 	if(fpl) {
 		fpl->rotate90( y_size );
 	}
-	for(  int i=0;  i<anz_vehikel;  i++  ) {
-		fahr[i]->rotate90_freight_destinations( y_size );
+	for(  int i=0;  i<cnv_sync->anz_vehikel;  i++  ) {
+		cnv_sync->fahr[i]->rotate90_freight_destinations( y_size );
 	}
 	// eventually correct freight destinations (and remove all stale freight)
 	check_freight();
@@ -566,8 +619,8 @@
  */
 koord3d convoi_t::get_pos() const
 {
-	if(anz_vehikel > 0 && fahr[0]) {
-		return state==INITIAL ? home_depot : fahr[0]->get_pos();
+	if(cnv_sync->anz_vehikel > 0 && front()) {
+		return cnv_sync->state==INITIAL ? home_depot : front()->get_pos();
 	}
 	else {
 		return koord3d::invalid;
@@ -622,7 +675,7 @@
 
 
 // length of convoi (16 is one tile)
-uint32 convoi_t::get_length() const
+uint32 convoi_sync_t::get_length() const
 {
 	uint32 len = 0;
 	for( uint8 i=0; i<anz_vehikel; i++ ) {
@@ -671,9 +724,9 @@
 	book( sum_running_costs, CONVOI_PROFIT );
 
 	total_distance_traveled ++;
-	distance_since_last_stop++;
+	cnv_sync->distance_since_last_stop++;
 
-	sum_speed_limit += speed_to_kmh( min( min_top_speed, speed_limit ));
+	cnv_sync->sum_speed_limit += speed_to_kmh( min( cnv_sync->min_top_speed, cnv_sync->speed_limit ));
 	book( 1, CONVOI_DISTANCE );
 }
 
@@ -695,7 +748,7 @@
 /* Calculates (and sets) new akt_speed
  * needed for driving, entering and leaving a depot)
  */
-void convoi_t::calc_acceleration(uint32 delta_t)
+void convoi_sync_t::calc_acceleration(uint32 delta_t)
 {
 	if(  !recalc_data  &&  !recalc_speed_limit  &&  (
 		(sum_friction_weight == sum_gesamtgewicht  &&  akt_speed_soll <= akt_speed  &&  akt_speed_soll+24 >= akt_speed)  ||
@@ -710,7 +763,7 @@
 	// Dwachs: only compute this if a vehicle in the convoi hopped
 	if(  recalc_data  ||  recalc_speed_limit  ) {
 		// calculate total friction and lowest speed limit
-		const vehicle_t* v = front();
+		const vehicle_t* v = fahr[0];
 		speed_limit = min( min_top_speed, v->get_speed_limit() );
 		if (recalc_data) {
 			sum_gesamtgewicht   = v->get_total_weight();
@@ -733,7 +786,7 @@
 
 	if(  recalc_data_front  ) {
 		// brake at the end of stations/in front of signals and crossings
-		const uint32 tiles_left = 1 + get_next_stop_index() - front()->get_route_index();
+		const uint32 tiles_left = 1 + next_stop_index - fahr[0]->get_route_index();
 		brake_speed_soll = SPEED_UNLIMITED;
 		if(  tiles_left < 4  ) {
 			static sint32 brake_speed_countdown[4] = {
@@ -855,7 +908,7 @@
 }
 
 
-int convoi_t::get_vehicle_at_length(uint16 length)
+int convoi_sync_t::get_vehicle_at_length(uint16 length)
 {
 	int current_length = 0;
 	for( int i=0;  i<anz_vehikel;  i++  ) {
@@ -869,36 +922,36 @@
 
 
 // moves all vehicles of a convoi
-bool convoi_t::sync_step(uint32 delta_t)
+int convoi_sync_t::sync_step(const uint32 delta_t)
 {
 	// still have to wait before next action?
 	wait_lock -= delta_t;
 	if(wait_lock > 0) {
-		return true;
+		return SYNC_OK;
 	}
 	wait_lock = 0;
 
 	switch(state) {
-		case INITIAL:
+		case convoi_t::INITIAL:
 			// someone must start calling, so the convoi goes from
 			// INITIAL to ROUTING_1, it can't go automatically
 			break;
 
-		case FAHRPLANEINGABE:
-		case ROUTING_1:
-		case DUMMY4:
-		case DUMMY5:
-		case NO_ROUTE:
-		case CAN_START:
-		case CAN_START_ONE_MONTH:
-		case CAN_START_TWO_MONTHS:
+		case convoi_t::FAHRPLANEINGABE:
+		case convoi_t::ROUTING_1:
+		case convoi_t::DUMMY4:
+		case convoi_t::DUMMY5:
+		case convoi_t::NO_ROUTE:
+		case convoi_t::CAN_START:
+		case convoi_t::CAN_START_ONE_MONTH:
+		case convoi_t::CAN_START_TWO_MONTHS:
 			// Hajo: this is an async task, see step()
 			break;
 
-		case ENTERING_DEPOT:
+		case convoi_t::ENTERING_DEPOT:
 			break;
 
-		case LEAVING_DEPOT:
+		case convoi_t::LEAVING_DEPOT:
 			{
 				// ok, so we will accelerate
 				akt_speed_soll = max( akt_speed_soll, kmh_to_speed(30) );
@@ -909,16 +962,16 @@
 				while(sp_soll>>12) {
 					// Attempt to move one step.
 					uint32 sp_hat = fahr[0]->do_drive(1<<YARDS_PER_VEHICLE_STEP_SHIFT);
-					int v_nr = get_vehicle_at_length((++steps_driven)>>4);
+					int v_nr = get_vehicle_at_length((++cnv->steps_driven)>>4);
 					// stop when depot reached
-					if(state==INITIAL  ||  state==ROUTING_1) {
+					if(state==convoi_t::INITIAL  ||  state==convoi_t::ROUTING_1) {
 						break;
 					}
 					// until all are moving or something went wrong (sp_hat==0)
 					if(sp_hat==0  ||  v_nr==anz_vehikel) {
-						steps_driven = -1;
-						state = DRIVING;
-						return true;
+						cnv->steps_driven = -1;
+						state = convoi_t::DRIVING;
+						return SYNC_OK;
 					}
 					// now only the right numbers
 					for(int i=1; i<=v_nr; i++) {
@@ -937,7 +990,7 @@
 			}
 			break;	// LEAVING_DEPOT
 
-		case DRIVING:
+		case convoi_t::DRIVING:
 			{
 				calc_acceleration(delta_t);
 
@@ -945,7 +998,7 @@
 				sp_soll += (akt_speed*delta_t);
 				uint32 sp_hat = fahr[0]->do_drive(sp_soll);
 				// stop when depot reached ...
-				if(state==INITIAL) {
+				if(state==convoi_t::INITIAL) {
 					break;
 				}
 				// now move the rest (so all vehikel are moving synchronously)
@@ -966,17 +1019,17 @@
 			}
 			break;	// DRIVING
 
-		case LOADING:
+		case convoi_t::LOADING:
 			// Hajo: loading is an async task, see laden()
 			break;
 
-		case WAITING_FOR_CLEARANCE:
-		case WAITING_FOR_CLEARANCE_ONE_MONTH:
-		case WAITING_FOR_CLEARANCE_TWO_MONTHS:
+		case convoi_t::WAITING_FOR_CLEARANCE:
+		case convoi_t::WAITING_FOR_CLEARANCE_ONE_MONTH:
+		case convoi_t::WAITING_FOR_CLEARANCE_TWO_MONTHS:
 			// Hajo: waiting is asynchronous => fixed waiting order and route search
 			break;
 
-		case SELF_DESTRUCT:
+		case convoi_t::SELF_DESTRUCT:
 			// see step, since destruction during a screen update may give strange effects
 			break;
 
@@ -985,7 +1038,7 @@
 			break;
 	}
 
-	return true;
+	return SYNC_OK;
 }
 
 
@@ -995,8 +1048,8 @@
  */
 bool convoi_t::drive_to()
 {
-	if(  anz_vehikel>0  ) {
-		koord3d start = fahr[0]->get_pos();
+	if(  cnv_sync->anz_vehikel>0  ) {
+		koord3d start = front()->get_pos();
 		koord3d ziel = fpl->get_current_eintrag().pos;
 
 		// avoid stopping mid-halt
@@ -1015,19 +1068,19 @@
 			}
 		}
 
-		if(  !fahr[0]->calc_route( start, ziel, speed_to_kmh(min_top_speed), &route )  ) {
-			if(  state != NO_ROUTE  ) {
-				state = NO_ROUTE;
+		if(  !front()->calc_route( start, ziel, speed_to_kmh(cnv_sync->min_top_speed), &route )  ) {
+			if(  cnv_sync->state != NO_ROUTE  ) {
+				cnv_sync->state = NO_ROUTE;
 				get_owner()->report_vehicle_problem( self, ziel );
 			}
 			// wait 25s before next attempt
-			wait_lock = 25000;
+			cnv_sync->wait_lock = 25000;
 		}
 		else {
 			bool route_ok = true;
 			const uint8 aktuell = fpl->get_aktuell();
-			if(  fahr[0]->get_waytype() != water_wt  ) {
-				air_vehicle_t *const plane = dynamic_cast<air_vehicle_t *>(fahr[0]);
+			if(  front()->get_waytype() != water_wt  ) {
+				air_vehicle_t *const plane = dynamic_cast<air_vehicle_t *>(front());
 				uint32 takeoff, search, landing;
 				air_vehicle_t::flight_state plane_state;
 				if(  plane  ) {
@@ -1052,24 +1105,24 @@
 					}
 
 					route_t next_segment;
-					if(  !fahr[0]->calc_route( start, ziel, speed_to_kmh(min_top_speed), &next_segment )  ) {
+					if(  !front()->calc_route( start, ziel, speed_to_kmh(cnv_sync->min_top_speed), &next_segment )  ) {
 						// do we still have a valid route to proceed => then go until there
 						if(  route.get_count()>1  ) {
 							break;
 						}
 						// we are stuck on our first routing attempt => give up
-						if(  state != NO_ROUTE  ) {
-							state = NO_ROUTE;
+						if(  cnv_sync->state != NO_ROUTE  ) {
+							cnv_sync->state = NO_ROUTE;
 							get_owner()->report_vehicle_problem( self, ziel );
 						}
 						// wait 25s before next attempt
-						wait_lock = 25000;
+						cnv_sync->wait_lock = 25000;
 						route_ok = false;
 						break;
 					}
 					else {
 						bool looped = false;
-						if(  fahr[0]->get_waytype() != air_wt  ) {
+						if(  front()->get_waytype() != air_wt  ) {
 							 // check if the route circles back on itself (only check the first tile, should be enough)
 							looped = route.is_contained(next_segment.position_bei(1));
 #if 0
@@ -1134,8 +1187,8 @@
  */
 void convoi_t::suche_neue_route()
 {
-	state = ROUTING_1;
-	wait_lock = 0;
+	cnv_sync->state = ROUTING_1;
+	cnv_sync->wait_lock = 0;
 }
 
 
@@ -1143,26 +1196,53 @@
  * Asynchrne step methode des Convois
  * @author Hj. Malthaner
  */
-void convoi_t::step()
+void convoi_t::step(const uint32 )//delta_t)
 {
-	if(  wait_lock > 0  ) {
-		return;
-	}
+//	static uint64 line_sum = 0;
+//	static uint64 loading_sum = 0;
+//	static uint64 routing_sum = 0;
+//	static uint64 waiting_sum = 0;
+//	static uint64 canstart_sum = 0;
+//	static uint64 other_sum = 0;
+//	static uint64 total_sum = 0;
+//	static unsigned long stepss = 0;
+//	static long next_ticks = 0;
+//	static long tickss = 0;
+//	static uint32 counts[10] = {0,0,0,0,0,0,0,0,0,0};
+//	LARGE_INTEGER li1, li2, li3;
 
+
+	if(cnv_sync->wait_lock<=0) {
+//QueryPerformanceCounter(&li1);
+//	if(cnv_sync->wait_lock>0) {
+//		return;
+//	}
+
+
 	// moved check to here, as this will apply the same update
 	// logic/constraints convois have for manual schedule manipulation
 	if (line_update_pending.is_bound()) {
+//printf("pending\n");
 		check_pending_updates();
 	}
 
-	switch(state) {
 
+//QueryPerformanceCounter(&li2);
+//line_sum += li2.QuadPart - li1.QuadPart;
+	if(  cnv_sync->state != DRIVING  ) { // driving and wait_lock==0, skip
+	switch(cnv_sync->state) {
 		case LOADING:
 			laden();
+//QueryPerformanceCounter(&li3);
+//loading_sum += li3.QuadPart - li2.QuadPart;
+//counts[0]++;
 			break;
 
 		case DUMMY4:
 		case DUMMY5:
+//QueryPerformanceCounter(&li3);
+//other_sum += li3.QuadPart - li2.QuadPart;
+//counts[1]++;
 			break;
 
 		case FAHRPLANEINGABE:
@@ -1174,7 +1254,7 @@
 
 				if(  fpl->empty()  ) {
 					// no entry => no route ...
-					state = NO_ROUTE;
+					cnv_sync->state = NO_ROUTE;
 					owner_p->report_vehicle_problem( self, koord3d::invalid );
 				}
 				else {
@@ -1185,13 +1265,13 @@
 						if (route.get_count() > 0) {
 							koord3d const& pos = route.back();
 							if (h == haltestelle_t::get_halt(pos, get_owner())) {
-								state = get_pos() == pos ? LOADING : DRIVING;
+								cnv_sync->state = get_pos() == pos ? LOADING : DRIVING;
 								break;
 							}
 						}
 						else {
 							if(  drive_to()  ) {
-								state = DRIVING;
+								cnv_sync->state = DRIVING;
 								break;
 							}
 						}
@@ -1204,23 +1284,26 @@
 							betrete_depot( gr->get_depot() );
 						}
 						else {
-							state = ROUTING_1;
+							cnv_sync->state = ROUTING_1;
 						}
 					}
 					else {
 						// go to next
-						state = ROUTING_1;
+						cnv_sync->state = ROUTING_1;
 					}
 				}
 			}
+//QueryPerformanceCounter(&li3);
+//other_sum += li3.QuadPart - li2.QuadPart;
+//counts[2]++;
 			break;
 
 		case ROUTING_1:
 			{
-				vehicle_t* v = fahr[0];
+				vehicle_t* v = front();
 
 				if(  fpl->empty()  ) {
-					state = NO_ROUTE;
+					cnv_sync->state = NO_ROUTE;
 					owner_p->report_vehicle_problem( self, koord3d::invalid );
 				}
 				else {
@@ -1232,11 +1315,14 @@
 					// Hajo: now calculate a new route
 					drive_to();
 					// finally, was there a record last time?
-					if(max_record_speed>welt->get_record_speed(fahr[0]->get_waytype())) {
-						welt->notify_record(self, max_record_speed, record_pos);
+					if(cnv_sync->max_record_speed>welt->get_record_speed(front()->get_waytype())) {
+						welt->notify_record(self, cnv_sync->max_record_speed, cnv_sync->record_pos);
 					}
 				}
 			}
+//QueryPerformanceCounter(&li3);
+//routing_sum += li3.QuadPart - li2.QuadPart;
+//counts[3]++;
 			break;
 
 		case NO_ROUTE:
@@ -1248,68 +1334,89 @@
 				// Hajo: now calculate a new route
 				drive_to();
 			}
+//QueryPerformanceCounter(&li3);
+//routing_sum += li3.QuadPart - li2.QuadPart;
+//counts[4]++;
 			break;
 
 		case CAN_START:
 		case CAN_START_ONE_MONTH:
 		case CAN_START_TWO_MONTHS:
 			{
-				vehicle_t* v = fahr[0];
+				vehicle_t* v = front();
 
 				int restart_speed=-1;
 				if (v->can_enter_tile(restart_speed,false)) {
 					// can reserve new block => drive on
-					state = (steps_driven>=0) ? LEAVING_DEPOT : DRIVING;
+					cnv_sync->state = (steps_driven>=0) ? LEAVING_DEPOT : DRIVING;
 					if(haltestelle_t::get_halt(v->get_pos(),owner_p).is_bound()) {
 						v->play_sound();
 					}
 				}
 				else if(  steps_driven==0  ) {
 					// on rail depot tile, do not reserve this
-					if(  grund_t *gr = welt->lookup(fahr[0]->get_pos())  ) {
-						if (schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(fahr[0]->get_waytype()))) {
-							sch0->unreserve(fahr[0]);
+					if(  grund_t *gr = welt->lookup(front()->get_pos())  ) {
+						if (schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(front()->get_waytype()))) {
+							sch0->unreserve(front());
 						}
 					}
 				}
 				if(restart_speed>=0) {
-					akt_speed = restart_speed;
+					cnv_sync->akt_speed = restart_speed;
 				}
-				if(state==CAN_START  ||  state==CAN_START_ONE_MONTH) {
-					set_tiles_overtaking( 0 );
+				if(cnv_sync->state==CAN_START  ||  cnv_sync->state==CAN_START_ONE_MONTH) {
+					cnv_sync->set_tiles_overtaking( 0 );
 				}
 			}
+//QueryPerformanceCounter(&li3);
+//canstart_sum += li3.QuadPart - li2.QuadPart;
+//counts[5]++;
 			break;
 
+		case WAITING_FOR_CLEARANCE:
 		case WAITING_FOR_CLEARANCE_ONE_MONTH:
 		case WAITING_FOR_CLEARANCE_TWO_MONTHS:
-		case WAITING_FOR_CLEARANCE:
 			{
 				int restart_speed=-1;
-				if (fahr[0]->can_enter_tile(restart_speed,false)) {
-					state = (steps_driven>=0) ? LEAVING_DEPOT : DRIVING;
+				if (front()->can_enter_tile(restart_speed,false)) {
+					cnv_sync->state = (steps_driven>=0) ? LEAVING_DEPOT : DRIVING;
 				}
 				if(restart_speed>=0) {
-					akt_speed = restart_speed;
+					cnv_sync->akt_speed = restart_speed;
 				}
-				if(state!=DRIVING) {
-					set_tiles_overtaking( 0 );
+				if(cnv_sync->state!=DRIVING) {
+					cnv_sync->set_tiles_overtaking( 0 );
 				}
 			}
+//QueryPerformanceCounter(&li3);
+//waiting_sum += li3.QuadPart - li2.QuadPart;
+//counts[6]++;
 			break;
 
 		// must be here; may otherwise confuse window management
 		case SELF_DESTRUCT:
 			welt->set_dirty();
 			destroy();
+//QueryPerformanceCounter(&li3);
+//other_sum += li3.QuadPart - li2.QuadPart;
+//counts[7]++;
 			return; // must not continue method after deleting this object
 
+		case DRIVING: // skipped by if above
+//QueryPerformanceCounter(&li3);
+//other_sum += li3.QuadPart - li2.QuadPart;
+//counts[9]++;
+			break;
+
 		default:	/* keeps compiler silent*/
+//QueryPerformanceCounter(&li3);
+//other_sum += li3.QuadPart - li2.QuadPart;
+//counts[8]++;
 			break;
 	}
 
 	// calculate new waiting time
-	switch( state ) {
+	switch( cnv_sync->state ) {
 		// handled by routine
 		case LOADING:
 			break;
@@ -1321,21 +1428,21 @@
 		case DRIVING:
 		case DUMMY4:
 		case DUMMY5:
-			wait_lock = 0;
+			cnv_sync->wait_lock = 0;
 			break;
 
 		// just waiting for action here
 		case INITIAL:
 		case FAHRPLANEINGABE:
 		case NO_ROUTE:
-			wait_lock = max( wait_lock, 25000 );
+			cnv_sync->wait_lock = max( cnv_sync->wait_lock, 25000 );
 			break;
 
 		// action soon needed
 		case ROUTING_1:
 		case CAN_START:
 		case WAITING_FOR_CLEARANCE:
-			wait_lock = max( wait_lock, 500 );
+			cnv_sync->wait_lock = max( cnv_sync->wait_lock, 500 );
 			break;
 
 		// waiting for free way, not too heavy, not to slow
@@ -1343,13 +1450,37 @@
 		case WAITING_FOR_CLEARANCE_ONE_MONTH:
 		case CAN_START_TWO_MONTHS:
 		case WAITING_FOR_CLEARANCE_TWO_MONTHS:
-			wait_lock = 2500;
+			cnv_sync->wait_lock = 2500;
 			break;
 		default: ;
 	}
+	}
+//QueryPerformanceCounter(&li2);
+//total_sum += li2.QuadPart - li1.QuadPart;
+	}
+/*
+if( delta_t > 0) {
+	stepss++;
+	tickss+=delta_t;
+	next_ticks+=delta_t;
 }
+if( next_ticks > 10000 ) {
+	next_ticks -= 10000;
 
+	QueryPerformanceFrequency(&li1);
+	const double freqscale = li1.QuadPart/1000.0;
 
+	printf("cnv: %lu, %ld, ld: %.1f, rout: %.1f, wait:%.1f, strt: %.1f, oth: %.1f, line: %.1f, tot: %.1f", tickss, stepss,
+		(double)loading_sum/freqscale, (double)routing_sum/freqscale, (double)waiting_sum/freqscale,
+		(double)canstart_sum/freqscale, (double)other_sum/freqscale, (double)line_sum/freqscale, (double)total_sum/freqscale );
+	printf("    %d, %d, %d, %d, %d, %d, %d, %d, %d, %d",counts[0],counts[1],counts[2],counts[3],counts[4],counts[5],counts[6],counts[7],counts[8],counts[9]);
+	printf("\n");
+}
+
+*/
+}
+
+
 void convoi_t::neues_jahr()
 {
     jahresgewinn = 0;
@@ -1359,14 +1490,14 @@
 void convoi_t::new_month()
 {
 	// should not happen: leftover convoi without vehicles ...
-	if(anz_vehikel==0) {
+	if(cnv_sync->anz_vehikel==0) {
 		DBG_DEBUG("convoi_t::new_month()","no vehicles => self destruct!");
 		self_destruct();
 		return;
 	}
 	// update statistics of average speed
 	if(  maxspeed_average_count==0  ) {
-		financial_history[0][CONVOI_MAXSPEED] = distance_since_last_stop>0 ? get_speedbonus_kmh() : 0;
+		financial_history[0][CONVOI_MAXSPEED] = cnv_sync->distance_since_last_stop>0 ? get_speedbonus_kmh() : 0;
 	}
 	maxspeed_average_count = 0;
 	// everything normal: update histroy
@@ -1377,23 +1508,23 @@
 		financial_history[0][j] = 0;
 	}
 	// remind every new month again
-	if(  state==NO_ROUTE  ) {
+	if(  cnv_sync->state==NO_ROUTE  ) {
 		get_owner()->report_vehicle_problem( self, get_pos() );
 	}
 	// check for traffic jam
-	if(state==WAITING_FOR_CLEARANCE) {
-		state = WAITING_FOR_CLEARANCE_ONE_MONTH;
+	if(cnv_sync->state==WAITING_FOR_CLEARANCE) {
+		cnv_sync->state = WAITING_FOR_CLEARANCE_ONE_MONTH;
 		// check, if now free ...
 		// might also reset the state!
 		int restart_speed=-1;
-		if (fahr[0]->can_enter_tile(restart_speed,false)) {
-			state = DRIVING;
+		if (front()->can_enter_tile(restart_speed,false)) {
+			cnv_sync->state = DRIVING;
 		}
 		if(restart_speed>=0) {
-			akt_speed = restart_speed;
+			cnv_sync->akt_speed = restart_speed;
 		}
 	}
-	else if(state==WAITING_FOR_CLEARANCE_ONE_MONTH) {
+	else if(cnv_sync->state==WAITING_FOR_CLEARANCE_ONE_MONTH) {
 		// make sure, not another vehicle with same line is loading in front
 		bool notify = true;
 		// check, if we are not waiting for load
@@ -1410,24 +1541,24 @@
 		if(  notify  ) {
 			get_owner()->report_vehicle_problem( self, koord3d::invalid );
 		}
-		state = WAITING_FOR_CLEARANCE_TWO_MONTHS;
+		cnv_sync->state = WAITING_FOR_CLEARANCE_TWO_MONTHS;
 	}
 	// check for traffic jam
-	if(state==CAN_START) {
-		state = CAN_START_ONE_MONTH;
+	if(cnv_sync->state==CAN_START) {
+		cnv_sync->state = CAN_START_ONE_MONTH;
 	}
-	else if(state==CAN_START_ONE_MONTH  ||  state==CAN_START_TWO_MONTHS  ) {
+	else if(cnv_sync->state==CAN_START_ONE_MONTH  ||  cnv_sync->state==CAN_START_TWO_MONTHS  ) {
 		get_owner()->report_vehicle_problem( self, koord3d::invalid );
-		state = CAN_START_TWO_MONTHS;
+		cnv_sync->state = CAN_START_TWO_MONTHS;
 	}
 	// check for obsolete vehicles in the convoi
-	if(!has_obsolete  &&  welt->use_timeline()) {
+	if(!cnv_sync->has_obsolete  &&  welt->use_timeline()) {
 		// convoi has obsolete vehicles?
 		const int month_now = welt->get_timeline_year_month();
-		has_obsolete = false;
+		cnv_sync->has_obsolete = false;
 		for(unsigned j=0;  j<get_vehikel_anzahl();  j++ ) {
-			if (fahr[j]->get_besch()->is_retired(month_now)) {
-				has_obsolete = true;
+			if (cnv_sync->fahr[j]->get_besch()->is_retired(month_now)) {
+				cnv_sync->has_obsolete = true;
 				break;
 			}
 		}
@@ -1441,8 +1572,8 @@
 	unreserve_route();
 
 	// Hajo: remove vehicles from world data structure
-	for(unsigned i=0; i<anz_vehikel; i++) {
-		vehicle_t* v = fahr[i];
+	for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+		vehicle_t* v = cnv_sync->fahr[i];
 
 		grund_t* gr = welt->lookup(v->get_pos());
 		if(gr) {
@@ -1461,54 +1592,54 @@
 	// Hajo: since 0.81.5exp it's safe to
 	// remove the current sync object from
 	// the sync list from inside sync_step()
-	welt->sync_remove(this);
+	cnv_sync->convoi_sync.sync_remove(cnv_sync);
 	maxspeed_average_count = 0;
-	state = INITIAL;
+	cnv_sync->state = INITIAL;
 }
 
 
 void convoi_t::start()
 {
-	if(state == INITIAL || state == ROUTING_1) {
+	if(cnv_sync->state == INITIAL || cnv_sync->state == ROUTING_1) {
 
 		// set home depot to location of depot convoi is leaving
 		if(route.empty()) {
-			home_depot = fahr[0]->get_pos();
+			home_depot = front()->get_pos();
 		}
 		else {
 			home_depot = route.front();
-			fahr[0]->set_pos( home_depot );
+			front()->set_pos( home_depot );
 		}
 		// put the convoi on the depot ground, to get automatic rotation
 		// (vorfahren() will remove it anyway again.)
 		grund_t *gr = welt->lookup( home_depot );
 		assert(gr);
-		gr->obj_add( fahr[0] );
+		gr->obj_add( front() );
 
 		// put into sync list
-		welt->sync_add(this);
+		cnv_sync->convoi_sync.sync_add(cnv_sync);
 
 		alte_richtung = ribi_t::keine;
-		no_load = false;
+		cnv_sync->no_load = false;
 
-		state = ROUTING_1;
+		cnv_sync->state = ROUTING_1;
 
 		// recalc weight and image
 		// also for any vehicle entered a depot, set_letztes is true! => reset it correctly
 		sint64 restwert_delta = 0;
-		for(unsigned i=0; i<anz_vehikel; i++) {
-			fahr[i]->set_leading( false );
-			fahr[i]->set_last( false );
-			restwert_delta -= fahr[i]->calc_sale_value();
-			fahr[i]->set_driven();
-			restwert_delta += fahr[i]->calc_sale_value();
-			fahr[i]->clear_flag( obj_t::not_on_map );
-			fahr[i]->load_cargo( halthandle_t() );
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+			cnv_sync->fahr[i]->set_leading( false );
+			cnv_sync->fahr[i]->set_last( false );
+			restwert_delta -= cnv_sync->fahr[i]->calc_sale_value();
+			cnv_sync->fahr[i]->set_driven();
+			restwert_delta += cnv_sync->fahr[i]->calc_sale_value();
+			cnv_sync->fahr[i]->clear_flag( obj_t::not_on_map );
+			cnv_sync->fahr[i]->load_cargo( halthandle_t() );
 		}
-		fahr[0]->set_leading( true );
-		fahr[anz_vehikel-1]->set_last( true );
+		front()->set_leading( true );
+		back()->set_last( true );
 		// do not show the vehicle - it will be wrong positioned -vorfahren() will correct this
-		fahr[0]->set_bild(IMG_LEER);
+		front()->set_bild(IMG_LEER);
 
 		// update finances for used vehicle reduction when first driven
 		owner_p->update_assets( restwert_delta, get_schedule()->get_waytype());
@@ -1525,12 +1656,12 @@
 		else {
 			welt->set_schedule_counter();
 		}
-		wait_lock = 0;
+		cnv_sync->wait_lock = 0;
 
 		DBG_MESSAGE("convoi_t::start()","Convoi %s wechselt von INITIAL nach ROUTING_1", name_and_id);
 	}
 	else {
-		dbg->warning("convoi_t::start()","called with state=%s\n",state_names[state]);
+		dbg->warning("convoi_t::start()","called with state=%s\n",state_names[cnv_sync->state]);
 	}
 }
 
@@ -1540,7 +1671,7 @@
  * called from the first vehicle_t of a convoi */
 void convoi_t::ziel_erreicht()
 {
-	const vehicle_t* v = fahr[0];
+	const vehicle_t* v = front();
 	alte_richtung = v->get_direction();
 
 	// check, what is at destination!
@@ -1554,7 +1685,7 @@
 		// we still book the money for the trip; however, the freight will be deleted (by the vehicle in the depot itself)
 		calc_gewinn();
 
-		akt_speed = 0;
+		cnv_sync->akt_speed = 0;
 		buf.printf( translator::translate("%s has entered a depot."), get_name() );
 		welt->get_message()->add_message(buf, v->get_pos().get_2d(),message_t::warnings, PLAYER_FLAG|get_owner()->get_player_nr(), IMG_LEER);
 
@@ -1565,18 +1696,18 @@
 		halthandle_t halt = haltestelle_t::get_halt(v->get_pos(),owner_p);
 		if(  halt.is_bound() &&  gr->get_weg_ribi(v->get_waytype())!=0  ) {
 			// seems to be a stop, so book the money for the trip
-			akt_speed = 0;
+			cnv_sync->akt_speed = 0;
 			halt->book(1, HALT_CONVOIS_ARRIVED);
-			state = LOADING;
-			arrived_time = welt->get_zeit_ms();
+			cnv_sync->state = LOADING;
+			cnv_sync->arrived_time = welt->get_zeit_ms();
 		}
 		else {
 			// Neither depot nor station: waypoint
 			fpl->advance();
-			state = ROUTING_1;
+			cnv_sync->state = ROUTING_1;
 		}
 	}
-	wait_lock = 0;
+	cnv_sync->wait_lock = 0;
 }
 
 
@@ -1587,50 +1718,50 @@
 void convoi_t::warten_bis_weg_frei(int restart_speed)
 {
 	if(!is_waiting()) {
-		state = WAITING_FOR_CLEARANCE;
-		wait_lock = 0;
+		cnv_sync->state = WAITING_FOR_CLEARANCE;
+		cnv_sync->wait_lock = 0;
 	}
 	if(restart_speed>=0) {
 		// langsam anfahren
-		akt_speed = restart_speed;
+		cnv_sync->akt_speed = restart_speed;
 	}
 }
 
 
 bool convoi_t::add_vehikel(vehicle_t *v, bool infront)
 {
-DBG_MESSAGE("convoi_t::add_vehikel()","at pos %i of %i totals.",anz_vehikel,max_vehicle);
+DBG_MESSAGE("convoi_t::add_vehikel()","at pos %i of %i totals.",cnv_sync->anz_vehikel,max_vehicle);
 	// extend array if requested (only needed for trains)
-	if(anz_vehikel == max_vehicle) {
+	if(cnv_sync->anz_vehikel == max_vehicle) {
 DBG_MESSAGE("convoi_t::add_vehikel()","extend array_tpl to %i totals.",max_rail_vehicle);
-		fahr.resize(max_rail_vehicle, NULL);
+		cnv_sync->fahr.resize(max_rail_vehicle, NULL);
 	}
 	// now append
-	if (anz_vehikel < fahr.get_count()) {
+	if (cnv_sync->anz_vehikel < cnv_sync->fahr.get_count()) {
 		v->set_convoi(this);
 
 		if(infront) {
-			for(unsigned i = anz_vehikel; i > 0; i--) {
-				fahr[i] = fahr[i - 1];
+			for(unsigned i = cnv_sync->anz_vehikel; i > 0; i--) {
+				cnv_sync->fahr[i] = cnv_sync->fahr[i - 1];
 			}
-			fahr[0] = v;
+			cnv_sync->fahr[0] = v;
 		} else {
-			fahr[anz_vehikel] = v;
+			cnv_sync->fahr[cnv_sync->anz_vehikel] = v;
 		}
-		anz_vehikel ++;
+		cnv_sync->anz_vehikel ++;
 
 		const vehikel_besch_t *info = v->get_besch();
 		if(info->get_leistung()) {
-			is_electric |= info->get_engine_type()==vehikel_besch_t::electric;
+			cnv_sync->is_electric |= info->get_engine_type()==vehikel_besch_t::electric;
 		}
 		sum_leistung += info->get_leistung();
-		sum_gear_und_leistung += info->get_leistung()*info->get_gear();
+		cnv_sync->sum_gear_und_leistung += info->get_leistung()*info->get_gear();
 		sum_gewicht += info->get_gewicht();
 		sum_running_costs -= info->get_betriebskosten();
-		min_top_speed = min( min_top_speed, kmh_to_speed( v->get_besch()->get_geschw() ) );
-		sum_gesamtgewicht = sum_gewicht;
+		cnv_sync->min_top_speed = min( cnv_sync->min_top_speed, kmh_to_speed( v->get_besch()->get_geschw() ) );
+		cnv_sync->sum_gesamtgewicht = sum_gewicht;
 		calc_loading();
-		freight_info_resort = true;
+		cnv_sync->freight_info_resort = true;
 		// Add good_catg_index:
 		if(v->get_cargo_max() != 0) {
 			const ware_besch_t *ware=v->get_cargo_type();
@@ -1639,8 +1770,8 @@
 			}
 		}
 		// check for obsolete
-		if(!has_obsolete  &&  welt->use_timeline()) {
-			has_obsolete = info->is_retired( welt->get_timeline_year_month() );
+		if(!cnv_sync->has_obsolete  &&  welt->use_timeline()) {
+			cnv_sync->has_obsolete = info->is_retired( welt->get_timeline_year_month() );
 		}
 		player_t::add_maintenance( get_owner(), info->get_maintenance(), info->get_waytype() );
 	}
@@ -1651,7 +1782,7 @@
 	// der convoi hat jetzt ein neues ende
 	set_erstes_letztes();
 
-DBG_MESSAGE("convoi_t::add_vehikel()","now %i of %i total vehikels.",anz_vehikel,max_vehicle);
+DBG_MESSAGE("convoi_t::add_vehikel()","now %i of %i total vehikels.",cnv_sync->anz_vehikel,max_vehicle);
 	return true;
 }
 
@@ -1659,54 +1790,54 @@
 vehicle_t *convoi_t::remove_vehikel_bei(uint16 i)
 {
 	vehicle_t *v = NULL;
-	if(i<anz_vehikel) {
-		v = fahr[i];
+	if(i<cnv_sync->anz_vehikel) {
+		v = cnv_sync->fahr[i];
 		if(v != NULL) {
-			for(unsigned j=i; j<anz_vehikel-1u; j++) {
-				fahr[j] = fahr[j + 1];
+			for(unsigned j=i; j<cnv_sync->anz_vehikel-1u; j++) {
+				cnv_sync->fahr[j] = cnv_sync->fahr[j + 1];
 			}
 
 			v->set_convoi(NULL);
 
-			--anz_vehikel;
-			fahr[anz_vehikel] = NULL;
+			cnv_sync->anz_vehikel--;
+			cnv_sync->fahr[cnv_sync->anz_vehikel] = NULL;
 
 			const vehikel_besch_t *info = v->get_besch();
 			sum_leistung -= info->get_leistung();
-			sum_gear_und_leistung -= info->get_leistung()*info->get_gear();
+			cnv_sync->sum_gear_und_leistung -= info->get_leistung()*info->get_gear();
 			sum_gewicht -= info->get_gewicht();
 			sum_running_costs += info->get_betriebskosten();
 			player_t::add_maintenance( get_owner(), -info->get_maintenance(), info->get_waytype() );
 		}
-		sum_gesamtgewicht = sum_gewicht;
+		cnv_sync->sum_gesamtgewicht = sum_gewicht;
 		calc_loading();
-		freight_info_resort = true;
+		cnv_sync->freight_info_resort = true;
 
 		// der convoi hat jetzt ein neues ende
-		if(anz_vehikel > 0) {
+		if(cnv_sync->anz_vehikel > 0) {
 			set_erstes_letztes();
 		}
 
 		// Hajo: calculate new minimum top speed
-		min_top_speed = calc_min_top_speed(fahr, anz_vehikel);
+		cnv_sync->min_top_speed = calc_min_top_speed(cnv_sync->fahr, cnv_sync->anz_vehikel);
 
 		// check for obsolete
-		if(has_obsolete) {
-			has_obsolete = false;
+		if(cnv_sync->has_obsolete) {
+			cnv_sync->has_obsolete = false;
 			const int month_now = welt->get_timeline_year_month();
-			for(unsigned i=0; i<anz_vehikel; i++) {
-				has_obsolete |= fahr[i]->get_besch()->is_retired(month_now);
+			for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+				cnv_sync->has_obsolete |= cnv_sync->fahr[i]->get_besch()->is_retired(month_now);
 			}
 		}
 
 		recalc_catg_index();
 
 		// still requires electrifications?
-		if(is_electric) {
-			is_electric = false;
-			for(unsigned i=0; i<anz_vehikel; i++) {
-				if(fahr[i]->get_besch()->get_leistung()) {
-					is_electric |= fahr[i]->get_besch()->get_engine_type()==vehikel_besch_t::electric;
+		if(cnv_sync->is_electric) {
+			cnv_sync->is_electric = false;
+			for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+				if(cnv_sync->fahr[i]->get_besch()->get_leistung()) {
+					cnv_sync->is_electric |= cnv_sync->fahr[i]->get_besch()->get_engine_type()==vehikel_besch_t::electric;
 				}
 			}
 		}
@@ -1741,13 +1872,13 @@
 void convoi_t::set_erstes_letztes()
 {
 	// anz_vehikel muss korrekt init sein
-	if(anz_vehikel>0) {
-		fahr[0]->set_leading(true);
-		for(unsigned i=1; i<anz_vehikel; i++) {
-			fahr[i]->set_leading(false);
-			fahr[i - 1]->set_last(false);
+	if(cnv_sync->anz_vehikel>0) {
+		front()->set_leading(true);
+		for(unsigned i=1; i<cnv_sync->anz_vehikel; i++) {
+			cnv_sync->fahr[i]->set_leading(false);
+			cnv_sync->fahr[i - 1]->set_last(false);
 		}
-		fahr[anz_vehikel - 1]->set_last(true);
+		back()->set_last(true);
 	}
 	else {
 		dbg->warning("convoi_t::set_erstes_letzes()", "called with anz_vehikel==0!");
@@ -1758,22 +1889,22 @@
 // remove wrong freight when schedule changes etc.
 void convoi_t::check_freight()
 {
-	for(unsigned i=0; i<anz_vehikel; i++) {
-		fahr[i]->remove_stale_cargo();
+	for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+		cnv_sync->fahr[i]->remove_stale_cargo();
 	}
 	calc_loading();
-	freight_info_resort = true;
+	cnv_sync->freight_info_resort = true;
 }
 
 
 bool convoi_t::set_schedule(schedule_t * f)
 {
-	if(  state==SELF_DESTRUCT  ) {
+	if(  cnv_sync->state==SELF_DESTRUCT  ) {
 		return false;
 	}
 
-	states old_state = state;
-	state = INITIAL;	// because during a sync-step we might be called twice ...
+	uint16 old_state = cnv_sync->state;
+	cnv_sync->state = INITIAL;	// because during a sync-step we might be called twice ...
 
 	DBG_DEBUG("convoi_t::set_schedule()", "new=%p, old=%p", f, fpl);
 	assert(f != NULL);
@@ -1817,11 +1948,11 @@
 
 	// ok, now we have a schedule
 	if(old_state!=INITIAL) {
-		state = FAHRPLANEINGABE;
+		cnv_sync->state = FAHRPLANEINGABE;
 	}
 	// to avoid jumping trains
-	alte_richtung = fahr[0]->get_direction();
-	wait_lock = 0;
+	alte_richtung = front()->get_direction();
+	cnv_sync->wait_lock = 0;
 	return true;
 }
 
@@ -1829,7 +1960,7 @@
 schedule_t *convoi_t::create_schedule()
 {
 	if(fpl == NULL) {
-		const vehicle_t* v = fahr[0];
+		const vehicle_t* v = front();
 
 		if (v != NULL) {
 			fpl = v->generate_new_schedule();
@@ -1854,10 +1985,10 @@
 	}
 
 	// going backwards? then recalculate all
-	ribi_t::ribi neue_richtung_rwr = ribi_t::rueckwaerts(fahr[0]->calc_direction(route.front(), route.position_bei(min(2, route.get_count() - 1))));
+	ribi_t::ribi neue_richtung_rwr = ribi_t::rueckwaerts(front()->calc_direction(route.front(), route.position_bei(min(2, route.get_count() - 1))));
 //	DBG_MESSAGE("convoi_t::go_alte_richtung()","neu=%i,rwr_neu=%i,alt=%i",neue_richtung_rwr,ribi_t::rueckwaerts(neue_richtung_rwr),alte_richtung);
 	if(neue_richtung_rwr&alte_richtung) {
-		akt_speed = 8;
+		cnv_sync->akt_speed = 8;
 		return false;
 	}
 
@@ -1866,13 +1997,13 @@
 	uint16 tile_length = 24;
 	unsigned i;	// for visual C++
 	const vehicle_t* pred = NULL;
-	for(i=0; i<anz_vehikel; i++) {
-		const vehicle_t* v = fahr[i];
+	for(i=0; i<cnv_sync->anz_vehikel; i++) {
+		const vehicle_t* v = cnv_sync->fahr[i];
 		grund_t *gr = welt->lookup(v->get_pos());
 
 		// not last vehicle?
 		// the length of last vehicle does not matter when it comes to positioning of vehicles
-		if ( i+1 < anz_vehikel) {
+		if ( i+1 < cnv_sync->anz_vehikel) {
 			convoi_length += v->get_besch()->get_length();
 		}
 
@@ -1880,7 +2011,7 @@
 			// ending here is an error!
 			// this is an already broken train => restart
 			dbg->warning("convoi_t::go_alte_richtung()","broken convoy (id %i) found => fixing!",self.get_id());
-			akt_speed = 8;
+			cnv_sync->akt_speed = 8;
 			return false;
 		}
 
@@ -1888,7 +2019,7 @@
 		ribi_t::ribi weg_ribi = gr->get_weg_ribi_unmasked(v->get_waytype());
 		if(ribi_t::ist_gerade(weg_ribi)  &&  (weg_ribi|v->get_direction())!=weg_ribi) {
 			dbg->warning("convoi_t::go_alte_richtung()","convoy with wrong vehicle directions (id %i) found => fixing!",self.get_id());
-			akt_speed = 8;
+			cnv_sync->akt_speed = 8;
 			return false;
 		}
 
@@ -1899,10 +2030,10 @@
 		pred = v;
 	}
 	// check if convoi is way too short (even for diagonal tracks)
-	tile_length += (ribi_t::ist_gerade(welt->lookup(fahr[anz_vehikel-1]->get_pos())->get_weg_ribi_unmasked(fahr[anz_vehikel-1]->get_waytype())) ? 16 : 8192/vehicle_t::get_diagonal_multiplier());
+	tile_length += (ribi_t::ist_gerade(welt->lookup(back()->get_pos())->get_weg_ribi_unmasked(back()->get_waytype())) ? 16 : 8192/vehicle_t::get_diagonal_multiplier());
 	if(  convoi_length>tile_length  ) {
 		dbg->warning("convoi_t::go_alte_richtung()","convoy too short (id %i) => fixing!",self.get_id());
-		akt_speed = 8;
+		cnv_sync->akt_speed = 8;
 		return false;
 	}
 
@@ -1912,10 +2043,10 @@
 	for( int index=1;  index<length;  index++ ) {
 		grund_t *gr=welt->lookup(route.position_bei(index));
 		// now check, if we are already here ...
-		for(unsigned i=0; i<anz_vehikel; i++) {
-			if (gr->obj_ist_da(fahr[i])) {
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+			if (gr->obj_ist_da(cnv_sync->fahr[i])) {
 				// we are turning around => start slowly and rebuilt train
-				akt_speed = 8;
+				cnv_sync->akt_speed = 8;
 				return false;
 			}
 		}
@@ -1925,14 +2056,14 @@
 
 	// we continue our journey; however later cars need also a correct route entry
 	// eventually we need to add their positions to the convois route
-	koord3d pos = fahr[0]->get_pos();
+	koord3d pos = front()->get_pos();
 	assert(pos == route.front());
 	if(welt->lookup(pos)->get_depot()) {
 		return false;
 	}
 	else {
-		for(i=0; i<anz_vehikel; i++) {
-			vehicle_t* v = fahr[i];
+		for(i=0; i<cnv_sync->anz_vehikel; i++) {
+			vehicle_t* v = cnv_sync->fahr[i];
 			// eventually add current position to the route
 			if (route.front() != v->get_pos() && route.position_bei(1) != v->get_pos()) {
 				route.insert(v->get_pos());
@@ -1944,8 +2075,8 @@
 	// we must set the current route index (instead assuming 1)
 	length = min((convoi_length/8u),route.get_count()-1);	// maximum length in tiles to check
 	bool ok=false;
-	for(i=0; i<anz_vehikel; i++) {
-		vehicle_t* v = fahr[i];
+	for(i=0; i<cnv_sync->anz_vehikel; i++) {
+		vehicle_t* v = cnv_sync->fahr[i];
 
 		// this is such awkward, since it takes into account different vehicle length
 		const koord3d vehicle_start_pos = v->get_pos();
@@ -1959,7 +2090,7 @@
 				uint8 richtung = v->get_direction();
 				uint8 neu_richtung = v->calc_direction( route.position_bei(max(idx-1,0)), v->get_pos_next());
 				// we need to move to this place ...
-				if(neu_richtung!=richtung  &&  (i!=0  ||  anz_vehikel==1  ||  ribi_t::ist_kurve(neu_richtung)) ) {
+				if(neu_richtung!=richtung  &&  (i!=0  ||  cnv_sync->anz_vehikel==1  ||  ribi_t::ist_kurve(neu_richtung)) ) {
 					// 90 deg bend!
 					return false;
 				}
@@ -1981,18 +2112,18 @@
 void convoi_t::vorfahren()
 {
 	// Hajo: init speed settings
-	sp_soll = 0;
-	set_tiles_overtaking( 0 );
-	recalc_data_front = true;
-	recalc_data = true;
+	cnv_sync->sp_soll = 0;
+	cnv_sync->set_tiles_overtaking( 0 );
+	cnv_sync->recalc_data_front = true;
+	cnv_sync->recalc_data = true;
 
 	koord3d k0 = route.front();
 	grund_t *gr = welt->lookup(k0);
 	bool at_dest = false;
 	if(gr  &&  gr->get_depot()) {
 		// start in depot
-		for(unsigned i=0; i<anz_vehikel; i++) {
-			vehicle_t* v = fahr[i];
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+			vehicle_t* v = cnv_sync->fahr[i];
 
 			// remove from old position
 			grund_t* gr = welt->lookup(v->get_pos());
@@ -2003,7 +2134,7 @@
 					cr->release_crossing(v);
 				}
 				// eventually unreserve this
-				if(  schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(fahr[i]->get_waytype()))  ) {
+				if(  schiene_t* const sch0 = obj_cast<schiene_t>(gr->get_weg(cnv_sync->fahr[i]->get_waytype()))  ) {
 					sch0->unreserve(v);
 				}
 			}
@@ -2015,19 +2146,19 @@
 		}
 
 		// just advances the first vehicle
-		vehicle_t* v0 = fahr[0];
+		vehicle_t* v0 = front();
 		v0->set_leading(false); // switches off signal checks ...
 		v0->get_smoke(false);
 		steps_driven = 0;
 		// drive half a tile:
-		for(int i=0; i<anz_vehikel; i++) {
-			fahr[i]->do_drive( (VEHICLE_STEPS_PER_TILE/2)<<YARDS_PER_VEHICLE_STEP_SHIFT );
+		for(int i=0; i<cnv_sync->anz_vehikel; i++) {
+			cnv_sync->fahr[i]->do_drive( (VEHICLE_STEPS_PER_TILE/2)<<YARDS_PER_VEHICLE_STEP_SHIFT );
 		}
 		v0->get_smoke(true);
 		v0->set_leading(true); // switches on signal checks to reserve the next route
 
 		// until all other are on the track
-		state = CAN_START;
+		cnv_sync->state = CAN_START;
 	}
 	else {
 		// still leaving depot (steps_driven!=0) or going in other direction or misalignment?
@@ -2038,16 +2169,16 @@
 
 			// move one train length to the start position ...
 			// in north/west direction, we leave the vehicle away to start as much back as possible
-			ribi_t::ribi neue_richtung = fahr[0]->get_direction();
+			ribi_t::ribi neue_richtung = front()->get_direction();
 			if(neue_richtung==ribi_t::sued  ||  neue_richtung==ribi_t::ost) {
 				// drive the convoi to the same position, but do not hop into next tile!
 				if(  train_length%16==0  ) {
 					// any space we need => just add
-					train_length += fahr[anz_vehikel-1]->get_besch()->get_length();
+					train_length += back()->get_besch()->get_length();
 				}
 				else {
 					// limit train to front of tile
-					train_length += min( (train_length%CARUNITS_PER_TILE)-1, fahr[anz_vehikel-1]->get_besch()->get_length() );
+					train_length += min( (train_length%CARUNITS_PER_TILE)-1, back()->get_besch()->get_length() );
 				}
 			}
 			else {
@@ -2056,13 +2187,13 @@
 			train_length = max(1,train_length);
 
 			// now advance all convoi until it is completely on the track
-			fahr[0]->set_leading(false); // switches off signal checks ...
+			front()->set_leading(false); // switches off signal checks ...
 			uint32 dist = VEHICLE_STEPS_PER_CARUNIT*train_length<<YARDS_PER_VEHICLE_STEP_SHIFT;
-			for(unsigned i=0; i<anz_vehikel; i++) {
-				vehicle_t* v = fahr[i];
+			for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+				vehicle_t* v = cnv_sync->fahr[i];
 
 				v->get_smoke(false);
-				uint32 const driven = fahr[i]->do_drive( dist );
+				uint32 const driven = cnv_sync->fahr[i]->do_drive( dist );
 				if (i==0  &&  driven < dist) {
 					// we are already at our destination
 					at_dest = true;
@@ -2076,19 +2207,19 @@
 				}
 				dist = driven - vlen;
 			}
-			fahr[0]->set_leading(true);
+			front()->set_leading(true);
 		}
 		if (!at_dest) {
-			state = CAN_START;
+			cnv_sync->state = CAN_START;
 
 			// to advance more smoothly
 			int restart_speed=-1;
-			if(fahr[0]->can_enter_tile(restart_speed,false)) {
+			if(front()->can_enter_tile(restart_speed,false)) {
 				// can reserve new block => drive on
 				if(haltestelle_t::get_halt(k0,owner_p).is_bound()) {
-					fahr[0]->play_sound();
+					front()->play_sound();
 				}
-				state = DRIVING;
+				cnv_sync->state = DRIVING;
 			}
 		}
 		else {
@@ -2097,11 +2228,11 @@
 	}
 
 	// finally reserve route (if needed)
-	if(  fahr[0]->get_waytype()!=air_wt  &&  !at_dest  ) {
+	if(  front()->get_waytype()!=air_wt  &&  !at_dest  ) {
 		// do not pre-reserve for airplanes
-		for(unsigned i=0; i<anz_vehikel; i++) {
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
 			// eventually reserve this
-			vehicle_t const& v = *fahr[i];
+			vehicle_t const& v = *(cnv_sync->fahr[i]);
 			if (schiene_t* const sch0 = obj_cast<schiene_t>(welt->lookup(v.get_pos())->get_weg(v.get_waytype()))) {
 				sch0->reserve(self,ribi_t::keine);
 			}
@@ -2111,7 +2242,7 @@
 		}
 	}
 
-	wait_lock = 0;
+	cnv_sync->wait_lock = 0;
 	INT_CHECK("simconvoi 711");
 }
 
@@ -2165,29 +2296,31 @@
 		file->rdwr_short( id );
 	}
 
-	dummy = anz_vehikel;
+	dummy = cnv_sync->anz_vehikel;
 	file->rdwr_long(dummy);
-	anz_vehikel = (uint8)dummy;
+	cnv_sync->anz_vehikel = (uint8)dummy;
 
 	if(file->get_version()<99014) {
 		// was anz_ready
 		file->rdwr_long(dummy);
 	}
 
-	file->rdwr_long(wait_lock);
+	sint32 wl = cnv_sync->wait_lock;
+	file->rdwr_long(wl);
+	cnv_sync->wait_lock = wl;
 	// some versions may produce broken safegames apparently
-	if(wait_lock > 60000) {
-		dbg->warning("convoi_t::sync_prepre()","Convoi %d: wait lock out of bounds: wait_lock = %d, setting to 60000",self.get_id(), wait_lock);
-		wait_lock = 60000;
+	if(cnv_sync->wait_lock > 30000) {
+		dbg->warning("convoi_t::sync_prepre()","Convoi %d: wait lock out of bounds: wait_lock = %d, setting to 30000",self.get_id(), cnv_sync->wait_lock);
+		cnv_sync->wait_lock = 30000;
 	}
 
 	bool dummy_bool=false;
 	file->rdwr_bool(dummy_bool);
 	file->rdwr_long(owner_n);
-	file->rdwr_long(akt_speed);
-	file->rdwr_long(akt_speed_soll);
-	file->rdwr_long(sp_soll);
-	file->rdwr_enum(state);
+	file->rdwr_long(cnv_sync->akt_speed);
+	file->rdwr_long(cnv_sync->akt_speed_soll);
+	file->rdwr_long(cnv_sync->sp_soll);
+	file->rdwr_enum(cnv_sync->state);
 	file->rdwr_enum(alte_richtung);
 
 	// read the yearly income (which has since then become a 64 bit value)
@@ -2200,14 +2333,14 @@
 
 	if(file->is_loading()) {
 		// extend array if requested (only needed for trains)
-		if(anz_vehikel > max_vehicle) {
-			fahr.resize(max_rail_vehicle, NULL);
+		if(cnv_sync->anz_vehikel > max_vehicle) {
+			cnv_sync->fahr.resize(max_rail_vehicle, NULL);
 		}
 		owner_p = welt->get_player( owner_n );
 
 		// Hajo: sanity check for values ... plus correction
-		if(sp_soll < 0) {
-			sp_soll = 0;
+		if(cnv_sync->sp_soll < 0) {
+			cnv_sync->sp_soll = 0;
 		}
 	}
 
@@ -2218,20 +2351,20 @@
 
 	koord3d dummy_pos;
 	if(file->is_saving()) {
-		for(unsigned i=0; i<anz_vehikel; i++) {
-			file->wr_obj_id( fahr[i]->get_typ() );
-			fahr[i]->rdwr_from_convoi(file);
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+			file->wr_obj_id( cnv_sync->fahr[i]->get_typ() );
+			cnv_sync->fahr[i]->rdwr_from_convoi(file);
 		}
 	}
 	else {
 		bool override_monorail = false;
-		is_electric = false;
-		for(  uint8 i=0;  i<anz_vehikel;  i++  ) {
+		cnv_sync->is_electric = false;
+		for(  uint8 i=0;  i<cnv_sync->anz_vehikel;  i++  ) {
 			obj_t::typ typ = (obj_t::typ)file->rd_obj_id();
 			vehicle_t *v = 0;
 
 			const bool first = (i==0);
-			const bool last = (i==anz_vehikel-1u);
+			const bool last = (i==cnv_sync->anz_vehikel-1u);
 			if(override_monorail) {
 				// ignore type for ancient monorails
 				v = new monorail_vehicle_t(file, first, last);
@@ -2260,7 +2393,7 @@
 				// will create orphan object, but better than crashing at deletion ...
 				dbg->error("convoi_t::convoi_t()","Can't load vehicle and no replacement found!");
 				i --;
-				anz_vehikel --;
+				cnv_sync->anz_vehikel --;
 				continue;
 			}
 
@@ -2287,31 +2420,31 @@
 			// info
 			if(info) {
 				sum_leistung += info->get_leistung();
-				sum_gear_und_leistung += info->get_leistung()*info->get_gear();
+				cnv_sync->sum_gear_und_leistung += info->get_leistung()*info->get_gear();
 				sum_gewicht += info->get_gewicht();
 				sum_running_costs -= info->get_betriebskosten();
-				is_electric |= info->get_engine_type()==vehikel_besch_t::electric;
+				cnv_sync->is_electric |= info->get_engine_type()==vehikel_besch_t::electric;
 				player_t::add_maintenance( get_owner(), info->get_maintenance(), info->get_waytype() );
 			}
 
 			// some versions save vehicles after leaving depot with koord3d::invalid
 			if(v->get_pos()==koord3d::invalid) {
-				state = INITIAL;
+				cnv_sync->state = INITIAL;
 			}
 
-			if(state!=INITIAL) {
+			if(cnv_sync->state!=INITIAL) {
 				grund_t *gr;
 				gr = welt->lookup(v->get_pos());
 				if(!gr) {
 					gr = welt->lookup_kartenboden(v->get_pos().get_2d());
 					if(gr) {
-						dbg->error("convoi_t::rdwr()", "invalid position %s for vehicle %s in state %d (setting to %i,%i,%i)", v->get_pos().get_str(), v->get_name(), state, gr->get_pos().x, gr->get_pos().y, gr->get_pos().z );
+						dbg->error("convoi_t::rdwr()", "invalid position %s for vehicle %s in state %d (setting to %i,%i,%i)", v->get_pos().get_str(), v->get_name(), cnv_sync->state, gr->get_pos().x, gr->get_pos().y, gr->get_pos().z );
 						v->set_pos( gr->get_pos() );
 					}
 					else {
-						dbg->fatal("convoi_t::rdwr()", "invalid position %s for vehicle %s in state %d", v->get_pos().get_str(), v->get_name(), state);
+						dbg->fatal("convoi_t::rdwr()", "invalid position %s for vehicle %s in state %d", v->get_pos().get_str(), v->get_name(), cnv_sync->state);
 					}
-					state = INITIAL;
+					cnv_sync->state = INITIAL;
 				}
 				// add to blockstrecke
 				if(v->get_waytype()==track_wt  ||  v->get_waytype()==monorail_wt  ||  v->get_waytype()==maglev_wt  ||  v->get_waytype()==narrowgauge_wt) {
@@ -2335,16 +2468,16 @@
 			}
 
 			// add to convoi
-			fahr[i] = v;
+			cnv_sync->fahr[i] = v;
 		}
-		sum_gesamtgewicht = sum_gewicht;
+		cnv_sync->sum_gesamtgewicht = sum_gewicht;
 	}
 
 	bool has_fpl = (fpl != NULL);
 	file->rdwr_bool(has_fpl);
 	if(has_fpl) {
-		//DBG_MESSAGE("convoi_t::rdwr()","convoi has a schedule, state %s!",state_names[state]);
-		const vehicle_t* v = fahr[0];
+		//DBG_MESSAGE("convoi_t::rdwr()","convoi has a schedule, state %s!",state_names[cnv_sync->state]);
+		const vehicle_t* v = front();
 		if(file->is_loading() && v) {
 			fpl = v->generate_new_schedule();
 		}
@@ -2362,15 +2495,15 @@
 	}
 
 	if(file->is_loading()) {
-		next_wolke = 0;
+		cnv_sync->next_wolke = 0; // *** init with simrand to spread out smoke??? *** //
 		calc_loading();
 	}
 
 	// Hajo: calculate new minimum top speed
-	min_top_speed = calc_min_top_speed(fahr, anz_vehikel);
+	cnv_sync->min_top_speed = calc_min_top_speed(cnv_sync->fahr, cnv_sync->anz_vehikel);
 
 	// Hajo: since sp_ist became obsolete, sp_soll is used modulo 65536
-	sp_soll &= 65535;
+	cnv_sync->sp_soll &= 65535;
 
 	if(file->get_version()<=88003) {
 		// load statistics
@@ -2465,8 +2598,8 @@
 
 	// Old versions recorded last_stop_pos in convoi, not in vehicle
 	koord3d last_stop_pos_convoi = koord3d(0,0,0);
-	if (anz_vehikel !=0) {
-		last_stop_pos_convoi = fahr[0]->last_stop_pos;
+	if (cnv_sync->anz_vehikel !=0) {
+		last_stop_pos_convoi = front()->last_stop_pos;
 	}
 	if(file->get_version()>=87001) {
 		last_stop_pos_convoi.rdwr(file);
@@ -2474,7 +2607,7 @@
 	else {
 		last_stop_pos_convoi =
 		!route.empty()   ? route.front()      :
-		anz_vehikel != 0 ? fahr[0]->get_pos() :
+		cnv_sync->anz_vehikel != 0 ? front()->get_pos() :
 		koord3d(0, 0, 0);
 	}
 
@@ -2490,7 +2623,7 @@
 	if(file->get_version()>=99017) {
 		if(file->is_saving()) {
 			if(  has_fpl  &&  fpl->get_current_eintrag().waiting_time_shift > 0  ) {
-				uint32 diff_ticks = arrived_time + (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) - welt->get_zeit_ms();
+				uint32 diff_ticks = cnv_sync->arrived_time + (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) - welt->get_zeit_ms();
 				file->rdwr_long(diff_ticks);
 			}
 			else {
@@ -2501,38 +2634,42 @@
 		else {
 			uint32 diff_ticks = 0;
 			file->rdwr_long(diff_ticks);
-			arrived_time = has_fpl ? welt->get_zeit_ms() - (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) + diff_ticks : 0;
+			cnv_sync->arrived_time = has_fpl ? welt->get_zeit_ms() - (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) + diff_ticks : 0;
 		}
 	}
 
 	// since 99015, the last stop will be maintained by the vehikels themselves
 	if(file->get_version()<99015) {
-		for(unsigned i=0; i<anz_vehikel; i++) {
-			fahr[i]->last_stop_pos = last_stop_pos_convoi;
+		for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+			cnv_sync->fahr[i]->last_stop_pos = last_stop_pos_convoi;
 		}
 	}
 
 	// overtaking status
 	if(file->get_version()<100001) {
-		set_tiles_overtaking( 0 );
+		cnv_sync->set_tiles_overtaking( 0 );
 	}
 	else {
-		file->rdwr_byte(tiles_overtaking);
-		set_tiles_overtaking( tiles_overtaking );
+		file->rdwr_byte(cnv_sync->tiles_overtaking);
+		cnv_sync->set_tiles_overtaking( cnv_sync->tiles_overtaking );
 	}
 	// no_load, withdraw
 	if(file->get_version()<102001) {
-		no_load = false;
-		withdraw = false;
+		cnv_sync->no_load = false;
+		cnv_sync->withdraw = false;
 	}
 	else {
-		file->rdwr_bool(no_load);
-		file->rdwr_bool(withdraw);
+		bool tmp = cnv_sync->no_load;
+		file->rdwr_bool(tmp);
+		cnv_sync->no_load = tmp;
+		tmp = cnv_sync->withdraw;
+		file->rdwr_bool(tmp);
+		cnv_sync->withdraw = tmp;
 	}
 
 	if(file->get_version()>=111001) {
-		file->rdwr_long( distance_since_last_stop );
-		file->rdwr_long( sum_speed_limit );
+		file->rdwr_long( cnv_sync->distance_since_last_stop );
+		file->rdwr_long( cnv_sync->sum_speed_limit );
 	}
 
 	if(  file->get_version()>=111002  ) {
@@ -2540,7 +2677,7 @@
 	}
 
 	if(  file->get_version()>=111003  ) {
-		file->rdwr_short( next_stop_index );
+		file->rdwr_short( cnv_sync->next_stop_index );
 		file->rdwr_short( next_reservation_index );
 	}
 
@@ -2581,13 +2718,13 @@
 
 void convoi_t::info(cbuffer_t & buf) const
 {
-	const vehicle_t* v = fahr[0];
+	const vehicle_t* v = front();
 	if (v != NULL) {
 		char tmp[128];
 
-		buf.printf("\n %d/%dkm/h (%1.2f$/km)\n", speed_to_kmh(min_top_speed), v->get_besch()->get_geschw(), get_running_cost() / 100.0);
+		buf.printf("\n %d/%dkm/h (%1.2f$/km)\n", speed_to_kmh(cnv_sync->min_top_speed), v->get_besch()->get_geschw(), get_running_cost() / 100.0);
 		buf.printf(" %s: %ikW\n", translator::translate("Leistung"), sum_leistung);
-		buf.printf(" %s: %i (%i) t\n", translator::translate("Gewicht"), sum_gewicht, sum_gesamtgewicht - sum_gewicht);
+		buf.printf(" %s: %i (%i) t\n", translator::translate("Gewicht"), sum_gewicht, cnv_sync->sum_gesamtgewicht - sum_gewicht);
 		buf.printf(" %s: ", translator::translate("Gewinn"));
 		money_to_string(tmp, (double)jahresgewinn);
 		buf.append(tmp);
@@ -2600,15 +2737,15 @@
 void convoi_t::set_sortby(uint8 sort_order)
 {
 	freight_info_order = sort_order;
-	freight_info_resort = true;
+	cnv_sync->freight_info_resort = true;
 }
 
 
 // caches the last info; resorts only when needed
 void convoi_t::get_freight_info(cbuffer_t & buf)
 {
-	if(freight_info_resort) {
-		freight_info_resort = false;
+	if(cnv_sync->freight_info_resort) {
+		cnv_sync->freight_info_resort = false;
 		// rebuilt the list with goods ...
 		vector_tpl<ware_t> total_fracht;
 
@@ -2616,8 +2753,8 @@
 		ALLOCA(uint32, max_loaded_waren, n);
 		MEMZERON(max_loaded_waren, n);
 
-		for(  uint32 i = 0;  i != anz_vehikel;  ++i  ) {
-			const vehicle_t* v = fahr[i];
+		for(  uint32 i = 0;  i != cnv_sync->anz_vehikel;  ++i  ) {
+			const vehicle_t* v = cnv_sync->fahr[i];
 
 			// first add to capacity indicator
 			const ware_besch_t* ware_besch = v->get_besch()->get_ware();
@@ -2677,29 +2814,29 @@
 
 void convoi_t::open_schedule_window( bool show )
 {
-	DBG_MESSAGE("convoi_t::open_schedule_window()","Id = %ld, State = %d, Lock = %d",self.get_id(), state, wait_lock);
+	DBG_MESSAGE("convoi_t::open_schedule_window()","Id = %ld, State = %d, Lock = %d", self.get_id(), cnv_sync->state, cnv_sync->wait_lock);
 
 	// manipulation of schedule not allowed while:
 	// - just starting
 	// - a line update is pending
-	if(  (state==FAHRPLANEINGABE  ||  line_update_pending.is_bound())  &&  get_owner()==welt->get_active_player()  ) {
+	if(  (cnv_sync->state==FAHRPLANEINGABE  ||  line_update_pending.is_bound())  &&  get_owner()==welt->get_active_player()  ) {
 		if (show) {
 			create_win( new news_img("Not allowed!\nThe convoi's schedule can\nnot be changed currently.\nTry again later!"), w_time_delete, magic_none );
 		}
 		return;
 	}
 
-	if(state==DRIVING) {
+	if(cnv_sync->state==DRIVING) {
 		// book the current value of goods
 		calc_gewinn();
 	}
 
-	akt_speed = 0;	// stop the train ...
-	if(state!=INITIAL) {
-		state = FAHRPLANEINGABE;
+	cnv_sync->akt_speed = 0;	// stop
+	if(cnv_sync->state!=INITIAL) {
+		cnv_sync->state = FAHRPLANEINGABE;
 	}
-	wait_lock = 25000;
-	alte_richtung = fahr[0]->get_direction();
+	cnv_sync->wait_lock = 25000;
+	alte_richtung = front()->get_direction();
 
 	if(  show  ) {
 		// Open schedule dialog
@@ -2715,12 +2852,12 @@
  */
 bool convoi_t::pruefe_alle()
 {
-	bool ok = anz_vehikel == 0  ||  fahr[0]->get_besch()->can_follow(NULL);
+	bool ok = cnv_sync->anz_vehikel == 0  ||  front()->get_besch()->can_follow(NULL);
 	unsigned i;
 
-	const vehicle_t* pred = fahr[0];
-	for(i = 1; ok && i < anz_vehikel; i++) {
-		const vehicle_t* v = fahr[i];
+	const vehicle_t* pred = front();
+	for(i = 1; ok && i < cnv_sync->anz_vehikel; i++) {
+		const vehicle_t* v = cnv_sync->fahr[i];
 		ok = pred->get_besch()->can_lead(v->get_besch())  &&
 				 v->get_besch()->can_follow(pred->get_besch());
 		pred = v;
@@ -2741,12 +2878,12 @@
  */
 void convoi_t::laden()
 {
-	if(  state == FAHRPLANEINGABE  ) {
+	if(  cnv_sync->state == FAHRPLANEINGABE  ) {
 		return;
 	}
 
 	// just wait a little longer if this is a non-bound halt
-	wait_lock = (WTT_LOADING*2)+(self.get_id())%1024;
+	cnv_sync->wait_lock = (WTT_LOADING*2)+(self.get_id())%1024;
 
 	halthandle_t halt = haltestelle_t::get_halt(fpl->get_current_eintrag().pos,owner_p);
 	// eigene haltestelle ?
@@ -2768,24 +2905,24 @@
 {
 	sint64 gewinn = 0;
 
-	for(unsigned i=0; i<anz_vehikel; i++) {
-		vehicle_t* v = fahr[i];
+	for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+		vehicle_t* v = cnv_sync->fahr[i];
 		sint64 tmp;
 		gewinn += tmp = v->calc_revenue(v->last_stop_pos.get_2d(), v->get_pos().get_2d() );
 		// get_schedule is needed as v->get_waytype() returns track_wt for trams (instead of tram_wt
-		owner_p->book_revenue(tmp, fahr[0]->get_pos().get_2d(), get_schedule()->get_waytype(), v->get_cargo_type()->get_index() );
+		owner_p->book_revenue(tmp, front()->get_pos().get_2d(), get_schedule()->get_waytype(), v->get_cargo_type()->get_index() );
 		v->last_stop_pos = v->get_pos();
 	}
 
 	// update statistics of average speed
-	if(  distance_since_last_stop  ) {
+	if(  cnv_sync->distance_since_last_stop  ) {
 		financial_history[0][CONVOI_MAXSPEED] *= maxspeed_average_count;
 		financial_history[0][CONVOI_MAXSPEED] += get_speedbonus_kmh();
 		maxspeed_average_count ++;
 		financial_history[0][CONVOI_MAXSPEED] /= maxspeed_average_count;
 	}
-	distance_since_last_stop = 0;
-	sum_speed_limit = 0;
+	cnv_sync->distance_since_last_stop = 0;
+	cnv_sync->sum_speed_limit = 0;
 
 	if(gewinn) {
 		jahresgewinn += gewinn;
@@ -2804,31 +2941,31 @@
  */
 void convoi_t::hat_gehalten(halthandle_t halt)
 {
-	grund_t *gr=welt->lookup(fahr[0]->get_pos());
+	grund_t *gr=welt->lookup(front()->get_pos());
 
 	// now find out station length
 	uint16 vehicles_loading = 0;
 	if(  gr->ist_wasser()  ) {
 		// harbour has any size
-		vehicles_loading = anz_vehikel;
+		vehicles_loading = cnv_sync->anz_vehikel;
 	}
 	else {
 		// calculate real station length
 		// and numbers of vehicles that can be (un)loaded
-		koord zv = koord( ribi_t::rueckwaerts(fahr[0]->get_direction()) );
-		koord3d pos = fahr[0]->get_pos();
+		koord zv = koord( ribi_t::rueckwaerts(front()->get_direction()) );
+		koord3d pos = front()->get_pos();
 		// start on bridge?
 		pos.z += gr->get_weg_yoff() / TILE_HEIGHT_STEP;
 		// difference between actual station length and vehicle lenghts
-		sint16 station_length = -fahr[vehicles_loading]->get_besch()->get_length();
+		sint16 station_length = -cnv_sync->fahr[vehicles_loading]->get_besch()->get_length();
 		do {
 			// advance one station tile
 			station_length += CARUNITS_PER_TILE;
 
 			while(station_length >= 0) {
 				vehicles_loading++;
-				if (vehicles_loading < anz_vehikel) {
-					station_length -= fahr[vehicles_loading]->get_besch()->get_length();
+				if (vehicles_loading < cnv_sync->anz_vehikel) {
+					station_length -= cnv_sync->fahr[vehicles_loading]->get_besch()->get_length();
 				}
 				else {
 					// all vehicles fit into station
@@ -2861,19 +2998,19 @@
 	uint32 time = WTT_LOADING;	// min time for loading/unloading
 	sint64 gewinn = 0;
 	for(unsigned i=0; i<vehicles_loading; i++) {
-		vehicle_t* v = fahr[i];
+		vehicle_t* v = cnv_sync->fahr[i];
 
 		// we need not to call this on the same position
 		if(  v->last_stop_pos != v->get_pos()  ) {
 			sint64 tmp;
 			// calc_revenue
 			gewinn += tmp = v->calc_revenue(v->last_stop_pos.get_2d(), v->get_pos().get_2d() );
-			owner_p->book_revenue(tmp, fahr[0]->get_pos().get_2d(), get_schedule()->get_waytype(), v->get_cargo_type()->get_index());
+			owner_p->book_revenue(tmp, front()->get_pos().get_2d(), get_schedule()->get_waytype(), v->get_cargo_type()->get_index());
 			v->last_stop_pos = v->get_pos();
 		}
 
 		uint16 amount = v->unload_cargo(halt);
-		if(  !no_load  ) {
+		if(  !cnv_sync->no_load  ) {
 			// load
 			amount += v->load_cargo(halt);
 		}
@@ -2883,7 +3020,7 @@
 			changed_loading_level = true;
 		}
 	}
-	freight_info_resort |= changed_loading_level;
+	cnv_sync->freight_info_resort |= changed_loading_level;
 	if(  changed_loading_level  ) {
 		halt->recalc_status();
 	}
@@ -2895,14 +3032,14 @@
 	loading_limit = fpl->get_current_eintrag().ladegrad;
 
 	// update statistics of average speed
-	if(  distance_since_last_stop  ) {
+	if(  cnv_sync->distance_since_last_stop  ) {
 		financial_history[0][CONVOI_MAXSPEED] *= maxspeed_average_count;
 		financial_history[0][CONVOI_MAXSPEED] += get_speedbonus_kmh();
 		maxspeed_average_count ++;
 		financial_history[0][CONVOI_MAXSPEED] /= maxspeed_average_count;
 	}
-	distance_since_last_stop = 0;
-	sum_speed_limit = 0;
+	cnv_sync->distance_since_last_stop = 0;
+	cnv_sync->sum_speed_limit = 0;
 
 	if(gewinn) {
 		jahresgewinn += gewinn;
@@ -2912,10 +3049,10 @@
 	}
 
 	// loading is finished => maybe drive on
-	if(  loading_level >= loading_limit  ||  no_load
-		||  (fpl->get_current_eintrag().waiting_time_shift > 0  &&  welt->get_zeit_ms() - arrived_time > (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) ) ) {
+	if(  loading_level >= loading_limit  ||  cnv_sync->no_load
+		||  (fpl->get_current_eintrag().waiting_time_shift > 0  &&  welt->get_zeit_ms() - cnv_sync->arrived_time > (welt->ticks_per_world_month >> (16 - fpl->get_current_eintrag().waiting_time_shift)) ) ) {
 
-		if(  withdraw  &&  (loading_level == 0  ||  goods_catg_index.empty())  ) {
+		if(  cnv_sync->withdraw  &&  (loading_level == 0  ||  goods_catg_index.empty())  ) {
 			// destroy when empty
 			self_destruct();
 			return;
@@ -2924,19 +3061,19 @@
 		calc_speedbonus_kmh();
 
 		// add available capacity after loading(!) to statistics
-		for (unsigned i = 0; i<anz_vehikel; i++) {
+		for (unsigned i = 0; i<cnv_sync->anz_vehikel; i++) {
 			book(get_vehikel(i)->get_cargo_max()-get_vehikel(i)->get_total_cargo(), CONVOI_CAPACITY);
 		}
 
 		// Advance schedule
 		fpl->advance();
-		state = ROUTING_1;
+		cnv_sync->state = ROUTING_1;
 	}
 
 	INT_CHECK( "convoi_t::hat_gehalten" );
 
 	// at least wait the minimum time for loading
-	wait_lock = time;
+	cnv_sync->wait_lock = time;
 }
 
 
@@ -2944,8 +3081,8 @@
 {
 	sint64 result = 0;
 
-	for(uint i=0; i<anz_vehikel; i++) {
-		result += fahr[i]->calc_sale_value();
+	for(uint i=0; i<cnv_sync->anz_vehikel; i++) {
+		result += cnv_sync->fahr[i]->calc_sale_value();
 	}
 	return result;
 }
@@ -2960,8 +3097,8 @@
 {
 	int fracht_max = 0;
 	int fracht_menge = 0;
-	for(unsigned i=0; i<anz_vehikel; i++) {
-		const vehicle_t* v = fahr[i];
+	for(unsigned i=0; i<cnv_sync->anz_vehikel; i++) {
+		const vehicle_t* v = cnv_sync->fahr[i];
 		fracht_max += v->get_cargo_max();
 		fracht_menge += v->get_total_cargo();
 	}
@@ -2969,23 +3106,23 @@
 	loading_limit = 0;	// will be set correctly from hat_gehalten() routine
 
 	// since weight has changed
-	recalc_data=true;
+	cnv_sync->recalc_data=true;
 }
 
 
 void convoi_t::calc_speedbonus_kmh()
 {
 	// init with default
-	const sint32 cnv_min_top_kmh = speed_to_kmh( min_top_speed );
+	const sint32 cnv_min_top_kmh = speed_to_kmh( cnv_sync->min_top_speed );
 	speedbonus_kmh = cnv_min_top_kmh;
 	// flying aircraft have 0 friction --> speed not limited by power, so just use top_speed
 	if(  front()!=NULL  &&  front()->get_waytype() != air_wt  ) {
 		sint32 total_max_weight = 0;
 		sint32 total_weight = 0;
-		for(  unsigned i=0;  i<anz_vehikel;  i++  ) {
-			const vehikel_besch_t* const besch = fahr[i]->get_besch();
+		for(  unsigned i=0;  i<cnv_sync->anz_vehikel;  i++  ) {
+			const vehikel_besch_t* const besch = cnv_sync->fahr[i]->get_besch();
 			total_max_weight += besch->get_gewicht();
-			total_weight += fahr[i]->get_total_weight(); // convoi_t::sum_gesamgewicht may not be updated yet when this method is called...
+			total_weight += cnv_sync->fahr[i]->get_total_weight(); // convoi_t::sum_gesamgewicht may not be updated yet when this method is called...
 			if(  besch->get_ware() == warenbauer_t::nichts  ) {
 				; // nothing
 			}
@@ -2995,17 +3132,16 @@
 			}
 			else {
 				// use actual weight for regular goods
-				total_max_weight += fahr[i]->get_cargo_weight();
+				total_max_weight += cnv_sync->fahr[i]->get_cargo_weight();
 			}
 		}
 		// very old vehicles have zero weight ...
 		if(  total_weight>0  ) {
+			speedbonus_kmh = speed_to_kmh( calc_max_speed( cnv_sync->sum_gear_und_leistung, total_max_weight, cnv_sync->min_top_speed ) );
 
-			speedbonus_kmh = speed_to_kmh( calc_max_speed(sum_gear_und_leistung, total_max_weight, min_top_speed) );
-
 			// convoi overtakers use current actual weight for achievable speed
 			if(  front()->get_overtaker()  ) {
-				max_power_speed = calc_max_speed(sum_gear_und_leistung, total_weight, min_top_speed);
+				cnv_sync->max_power_speed = calc_max_speed( cnv_sync->sum_gear_und_leistung, total_weight, cnv_sync->min_top_speed );
 			}
 		}
 	}
@@ -3015,8 +3151,8 @@
 // return the current bonus speed
 sint32 convoi_t::get_speedbonus_kmh() const
 {
-	if(  distance_since_last_stop > 0  &&  front()!=NULL  &&  front()->get_waytype() != air_wt  ) {
-		return min( speedbonus_kmh, (sint32)(sum_speed_limit / distance_since_last_stop) );
+	if(  cnv_sync->distance_since_last_stop > 0  &&  front()!=NULL  &&  front()->get_waytype() != air_wt  ) {
+		return min( speedbonus_kmh, (sint32)(cnv_sync->sum_speed_limit / cnv_sync->distance_since_last_stop) );
 	}
 	return speedbonus_kmh;
 }
@@ -3025,8 +3161,8 @@
 // return the current bonus speed
 uint32 convoi_t::get_average_kmh() const
 {
-	if(  distance_since_last_stop > 0  ) {
-		return sum_speed_limit / distance_since_last_stop;
+	if(  cnv_sync->distance_since_last_stop > 0  ) {
+		return cnv_sync->sum_speed_limit / cnv_sync->distance_since_last_stop;
 	}
 	return speedbonus_kmh;
 }
@@ -3041,12 +3177,12 @@
 {
 	line_update_pending = linehandle_t();	// does not bother to add it to a new line anyway ...
 	// convois in depot are not contained in the map array!
-	if(state==INITIAL) {
+	if(cnv_sync->state==INITIAL) {
 		destroy();
 	}
 	else {
-		state = SELF_DESTRUCT;
-		wait_lock = 0;
+		cnv_sync->state = SELF_DESTRUCT;
+		cnv_sync->wait_lock = 0;
 	}
 }
 
@@ -3061,17 +3197,17 @@
 void convoi_t::destroy()
 {
 	// can be only done here, with a valid convoihandle ...
-	if(fahr[0]) {
-		fahr[0]->set_convoi(NULL);
+	if(front()) {
+		front()->set_convoi(NULL);
 	}
 
-	if(  state == INITIAL  ) {
+	if(  cnv_sync->state == INITIAL  ) {
 		// in depot => not on map
-		for(  uint8 i = anz_vehikel;  i-- != 0;  ) {
-			fahr[i]->set_flag( obj_t::not_on_map );
+		for(  uint8 i = cnv_sync->anz_vehikel;  i-- != 0;  ) {
+			cnv_sync->fahr[i]->set_flag( obj_t::not_on_map );
 		}
 	}
-	state = SELF_DESTRUCT;
+	cnv_sync->state = SELF_DESTRUCT;
 
 	if(fpl!=NULL  &&  !fpl->ist_abgeschlossen()) {
 		destroy_win((ptrdiff_t)fpl);
@@ -3085,25 +3221,25 @@
 	}
 
 	// pay the current value
-	owner_p->book_new_vehicle( calc_restwert(), get_pos().get_2d(), fahr[0] ? fahr[0]->get_besch()->get_waytype() : ignore_wt );
+	owner_p->book_new_vehicle( calc_restwert(), get_pos().get_2d(), front() ? front()->get_besch()->get_waytype() : ignore_wt );
 
-	for(  uint8 i = anz_vehikel;  i-- != 0;  ) {
-		if(  !fahr[i]->get_flag( obj_t::not_on_map )  ) {
+	for(  uint8 i = cnv_sync->anz_vehikel;  i-- != 0;  ) {
+		if(  !cnv_sync->fahr[i]->get_flag( obj_t::not_on_map )  ) {
 			// remove from rails/roads/crossings
-			grund_t *gr = welt->lookup(fahr[i]->get_pos());
-			fahr[i]->set_last( true );
-			fahr[i]->leave_tile();
+			grund_t *gr = welt->lookup(cnv_sync->fahr[i]->get_pos());
+			cnv_sync->fahr[i]->set_last( true );
+			cnv_sync->fahr[i]->leave_tile();
 			if(  gr  &&  gr->ist_uebergang()  ) {
-				gr->find<crossing_t>()->release_crossing(fahr[i]);
+				gr->find<crossing_t>()->release_crossing(cnv_sync->fahr[i]);
 			}
-			fahr[i]->set_flag( obj_t::not_on_map );
+			cnv_sync->fahr[i]->set_flag( obj_t::not_on_map );
 
 		}
-		fahr[i]->discard_cargo();
-		fahr[i]->cleanup(owner_p);
-		delete fahr[i];
+		cnv_sync->fahr[i]->discard_cargo();
+		cnv_sync->fahr[i]->cleanup(owner_p);
+		delete cnv_sync->fahr[i];
 	}
-	anz_vehikel = 0;
+	cnv_sync->anz_vehikel = 0;
 
 	delete this;
 }
@@ -3130,14 +3266,14 @@
 		"name = '%s'\n"
 		"line_id = '%d'\n"
 		"fpl = '%p'",
-		(int)anz_vehikel,
-		(int)wait_lock,
+		(int)cnv_sync->anz_vehikel,
+		(int)cnv_sync->wait_lock,
 		(int)welt->sp2num(owner_p),
-		(int)akt_speed,
-		(int)akt_speed_soll,
-		(int)sp_soll,
-		(int)state,
-		(const char *)(state_names[state]),
+		(int)cnv_sync->akt_speed,
+		(int)cnv_sync->akt_speed_soll,
+		(int)cnv_sync->sp_soll,
+		(int)cnv_sync->state,
+		(const char *)(state_names[cnv_sync->state]),
 		(int)alte_richtung,
 		(long)(jahresgewinn/100),
 		(const char *)name_and_id,
@@ -3171,7 +3307,7 @@
 {
 	sint32 running_cost = 0;
 	for(  unsigned i = 0;  i < get_vehikel_anzahl();  i++  ) {
-		running_cost += fahr[i]->get_besch()->get_maintenance();
+		running_cost += cnv_sync->fahr[i]->get_besch()->get_maintenance();
 	}
 	return running_cost;
 }
@@ -3181,7 +3317,7 @@
 {
 	sint32 running_cost = 0;
 	for(  unsigned i = 0;  i < get_vehikel_anzahl();  i++  ) {
-		running_cost += fahr[i]->get_operating_cost();
+		running_cost += cnv_sync->fahr[i]->get_operating_cost();
 	}
 	return running_cost;
 }
@@ -3191,7 +3327,7 @@
 {
 	sint64 purchase_cost = 0;
 	for(  unsigned i = 0;  i < get_vehikel_anzahl();  i++  ) {
-		purchase_cost += fahr[i]->get_besch()->get_preis();
+		purchase_cost += cnv_sync->fahr[i]->get_besch()->get_preis();
 	}
 	return purchase_cost;
 }
@@ -3356,7 +3492,7 @@
 			fpl->set_aktuell( (fpl->get_aktuell()+fpl->get_count()-1)%fpl->get_count() );
 		}
 
-		if (state != INITIAL) {
+		if (cnv_sync->state != INITIAL) {
 			// remove wrong freight
 			check_freight();
 
@@ -3367,11 +3503,11 @@
 			}
 			else {
 				// need re-routing
-				state = FAHRPLANEINGABE;
+				cnv_sync->state = FAHRPLANEINGABE;
 			}
 			// make this change immediately
-			if(  state!=LOADING  ) {
-				wait_lock = 0;
+			if(  cnv_sync->state!=LOADING  ) {
+				cnv_sync->wait_lock = 0;
 			}
 		}
 	}
@@ -3424,7 +3560,7 @@
 			n = route.get_count()-1-1; // extra -1 to brake 1 tile earlier when entering station
 		}
 	}
-	next_stop_index = n+1;
+	cnv_sync->next_stop_index = n + 1;
 }
 
 
@@ -3447,11 +3583,11 @@
  */
 COLOR_VAL convoi_t::get_status_color() const
 {
-	if(state==INITIAL) {
+	if(  cnv_sync->state == INITIAL  ) {
 		// in depot/under assembly
 		return SYSCOL_TEXT_HIGHLIGHT;
 	}
-	else if (state == WAITING_FOR_CLEARANCE_ONE_MONTH || state == CAN_START_ONE_MONTH || get_state() == NO_ROUTE) {
+	else if(  cnv_sync->state == WAITING_FOR_CLEARANCE_ONE_MONTH  ||  cnv_sync->state == CAN_START_ONE_MONTH  ||  get_state() == NO_ROUTE  ) {
 		// stuck or no route
 		return COL_ORANGE;
 	}
@@ -3463,7 +3599,7 @@
 		// nothing moved
 		return COL_YELLOW;
 	}
-	else if(has_obsolete) {
+	else if(cnv_sync->has_obsolete) {
 		return COL_BLUE;
 	}
 	// normal state
@@ -3475,15 +3611,15 @@
 uint16 convoi_t::get_tile_length() const
 {
 	uint16 carunits=0;
-	for(sint8 i=0;  i<anz_vehikel-1;  i++) {
-		carunits += fahr[i]->get_besch()->get_length();
+	for(sint8 i=0;  i<cnv_sync->anz_vehikel-1;  i++) {
+		carunits += cnv_sync->fahr[i]->get_besch()->get_length();
 	}
 	// the last vehicle counts differently in stations and for reserving track
 	// (1) add 8 = 127/256 tile to account for the driving in stations in north/west direction
 	//     see at the end of vehicle_t::hop()
 	// (2) for length of convoi for loading in stations the length of the last vehicle matters
 	//     see convoi_t::hat_gehalten
-	carunits += max(CARUNITS_PER_TILE/2, fahr[anz_vehikel-1]->get_besch()->get_length());
+	carunits += max(CARUNITS_PER_TILE/2, back()->get_besch()->get_length());
 
 	uint16 tiles = (carunits + CARUNITS_PER_TILE - 1) / CARUNITS_PER_TILE;
 	return tiles;
@@ -3493,15 +3629,15 @@
 // if withdraw and empty, then self destruct
 void convoi_t::set_withdraw(bool new_withdraw)
 {
-	withdraw = new_withdraw;
-	if(  withdraw  &&  (loading_level==0  ||  goods_catg_index.empty())) {
+	cnv_sync->withdraw = new_withdraw;
+	if(  cnv_sync->withdraw  &&  (loading_level==0  ||  goods_catg_index.empty())) {
 		// test if convoi in depot and not driving
 		grund_t *gr = welt->lookup( get_pos());
-		if(  gr  &&  gr->get_depot()  &&  state == INITIAL  ) {
+		if(  gr  &&  gr->get_depot()  &&  cnv_sync->state == INITIAL  ) {
 #if 1
 			// do not touch line bound convois in depots
-			withdraw = false;
-			no_load = false;
+			cnv_sync->withdraw = false;
+			cnv_sync->no_load = false;
 #else
 			// disassemble also line bound convois in depots
 			gr->get_depot()->disassemble_convoi(self, true);
@@ -3519,7 +3655,7 @@
  * The city car is not overtaking/being overtaken.
  * @author isidoro
  */
-bool convoi_t::can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other)
+bool convoi_sync_t::can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other)
 {
 	if(fahr[0]->get_waytype()!=road_wt) {
 		return false;
@@ -3533,7 +3669,7 @@
 		/* overtaking a loading convoi
 		 * => we can do a lazy check, since halts are always straight
 		 */
-		grund_t *gr = welt->lookup(get_pos());
+		grund_t *gr = cnv->welt->lookup(cnv->get_pos());
 		if(  gr==NULL  ) {
 			// should never happen, since there is a vehicle in front of us ...
 			return false;
@@ -3545,14 +3681,14 @@
 		}
 
 		uint16 idx = fahr[0]->get_route_index();
-		const sint32 tiles = (steps_other-1)/(CARUNITS_PER_TILE*VEHICLE_STEPS_PER_CARUNIT) + get_tile_length() + 1;
-		if(  tiles > 0  &&  idx+(uint32)tiles >= route.get_count()  ) {
+		const sint32 tiles = (steps_other-1)/(CARUNITS_PER_TILE*VEHICLE_STEPS_PER_CARUNIT) + cnv->get_tile_length() + 1;
+		if(  tiles > 0  &&  idx+(uint32)tiles >= cnv->route.get_count()  ) {
 			// needs more space than there
 			return false;
 		}
 
 		for(  sint32 i=0;  i<tiles;  i++  ) {
-			grund_t *gr = welt->lookup( route.position_bei( idx+i ) );
+			grund_t *gr = cnv->welt->lookup( cnv->route.position_bei( idx+i ) );
 			if(  gr==NULL  ) {
 				return false;
 			}
@@ -3584,7 +3720,7 @@
 				}
 			}
 		}
-		convoi_t *ocnv = dynamic_cast<convoi_t *>(other_overtaker);
+		convoi_sync_t *ocnv = dynamic_cast<convoi_sync_t *>(other_overtaker);
 		set_tiles_overtaking( 2 + ocnv->get_length()/CARUNITS_PER_TILE + get_length()/CARUNITS_PER_TILE );
 		return true;
 	}
@@ -3608,17 +3744,17 @@
 	// First phase: no traffic except me and my overtaken car in the dangerous zone
 	unsigned int route_index = fahr[0]->get_route_index()+1;
 	koord3d pos = fahr[0]->get_pos();
-	koord3d pos_prev = route_index > 2 ? route.position_bei(route_index-2) : pos;
+	koord3d pos_prev = route_index > 2 ? cnv->route.position_bei(route_index-2) : pos;
 	koord3d pos_next;
 
 	while( distance > 0 ) {
 
-		if(  route_index >= route.get_count()  ) {
+		if(  route_index >= cnv->route.get_count()  ) {
 			return false;
 		}
 
-		pos_next = route.position_bei(route_index++);
-		grund_t *gr = welt->lookup(pos);
+		pos_next = cnv->route.position_bei(route_index++);
+		grund_t *gr = cnv->welt->lookup(pos);
 		// no ground, or slope => about
 		if(  gr==NULL  ||  gr->get_weg_hang()!=hang_t::flach  ) {
 			return false;
@@ -3683,12 +3819,12 @@
 	time_overtaking = (time_overtaking << 16)/akt_speed;
 	while(  time_overtaking > 0  ) {
 
-		if(  route_index >= route.get_count()  ) {
+		if(  route_index >= cnv->route.get_count()  ) {
 			return false;
 		}
 
-		pos_next = route.position_bei(route_index++);
-		grund_t *gr= welt->lookup(pos);
+		pos_next = cnv->route.position_bei(route_index++);
+		grund_t *gr= cnv->welt->lookup(pos);
 		if(  gr==NULL  ) {
 			// will cause a route search, but is ok
 			break;
Index: simconvoi.h
===================================================================
--- simconvoi.h	(revision 7507)
+++ simconvoi.h	(working copy)
@@ -31,32 +31,170 @@
 class vehikel_besch_t;
 class schedule_t;
 class cbuffer_t;
+class convoi_t;
 
+
+class convoi_sync_t : public sync_steppable, public overtaker_t
+{
+public:
+	friend class convoi_t;
+
+private:
+	convoihandle_t cnv;
+
+	sint16 wait_lock;
+
+	uint16 next_wolke;	// time to next smoke  // should be ordered last, but here filling hole
+
+	uint16 state;
+
+	// cached values
+	// will be recalculated if
+	// recalc_data is true
+	sint32 speed_limit;
+
+	/**
+	* Lowest top speed of all vehicles. Doesn't get saved, but calculated
+	* from the vehicles data
+	* @author Hj. Malthaner
+	*/
+	sint32 min_top_speed;
+
+	sint64 sum_gesamtgewicht;
+	sint64 sum_friction_weight;
+
+	/**
+	* the convoi is being withdrawn from service
+	* @author kierongreen
+	*/
+	uint8 withdraw:1;
+
+	/**
+	* nothing will be loaded onto this convoi
+	* @author kierongreen
+	*/
+	uint8 no_load:1;
+
+	/**
+	* the convoi caches its freight info; it is only recalculation after loading or resorting
+	* @author prissi
+	*/
+	uint8 freight_info_resort:1;
+
+	// true, if at least one vehicle of a convoi is obsolete
+	uint8 has_obsolete:1;
+
+	// ture, if there is at least one engine that requires catenary
+	uint8 is_electric:1;
+
+	uint8 recalc_data_front:1; // true when front vehicle in convoi hops
+	uint8 recalc_data:1; // true when any vehicle in convoi hops
+	uint8 recalc_speed_limit:1; ///< true, when convoy has to recalculate speed limits  /////////////////////////// not in place
+
+	/**
+	* Number of vehicles in this convoi.
+	* @author Hj. Malthaner
+	*/
+	uint8 anz_vehikel;
+
+	/**
+	 * this give the index of the next signal or the end of the route
+	 * convois will slow down before it, if this is not a waypoint or the cannot pass
+	 * The slowdown ist done by the vehicle routines
+	 * @author prissi
+	 */
+	uint16 next_stop_index;
+
+	// needed for speed control/calculation
+	sint32 brake_speed_soll;    // brake target speed
+
+	uint32 distance_since_last_stop; // number of tiles entered since last stop
+	uint32 sum_speed_limit; // sum of the speed limits encountered since the last stop
+
+	sint32 akt_speed_soll;    // target speed
+	sint32 akt_speed;	        // current speed
+
+	/**
+	* Overall performance with Gear.
+	* Is not stored, but is calculated from individual functions
+	* @author prissi
+	*/
+	sint32 sum_gear_und_leistung;
+
+	sint32 previous_delta_v;  // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelrate
+
+	// things for the world record
+	sint32 max_record_speed; // current convois fastest speed ever
+
+	// things for the world record
+	koord record_pos;
+
+	// needed for speed control/calculation
+	sint32 sp_soll;           // steps to go
+
+	/**
+	 * Time when convoi arrived at the current stop
+	 * Used to calculate when it should depart due to the 'month wait time'
+	 */
+/////////////////////////////////////// NEWLY ADDED /////////////////////////////////// not in right place for access order
+	uint32 arrived_time;
+/////////////////////////////////////// NEWLY ADDED /////////////////////////////////// not in right place for access order
+
+	/**
+	* The vehicles of this convoi
+	*
+	* @author Hj. Malthaner
+	*/
+	array_tpl<vehicle_t*> fahr;
+
+
+
+	/* Calculates (and sets) akt_speed
+	 * needed for driving, entering and leaving a depot)
+	 */
+	void calc_acceleration(uint32 delta_t);
+
+
+public:
+	convoi_sync_t();
+	~convoi_sync_t();
+
+	static sync_steppable_vector_t convoi_sync;
+	int sync_step(const uint32 delta_t);
+
+	void sync_add_self() { convoi_sync.sync_add(this); }
+
+	// Overtaking for convois
+	virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other);
+
+	/**
+	 * @return length of convoi in the correct units for movement
+	 * @author neroden
+	 */
+	uint32 get_length_in_steps() const { return get_length() * VEHICLE_STEPS_PER_CARUNIT; }
+
+	// returns the index of the vehikel at position length (16=1 tile)
+	int get_vehicle_at_length(uint16);
+	uint32 get_length() const;
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
+};
+
+
 /**
  * Base class for all vehicle consists. Convoys can be referenced by handles, see halthandle_t.
  *
  * @author Hj. Malthaner
  */
-class convoi_t : public sync_steppable, public overtaker_t
+class convoi_t// : public sync_steppable, public overtaker_t
 {
 public:
-	enum {
-		CONVOI_CAPACITY = 0,       // the amount of ware that could be transported, theoretically
-		CONVOI_TRANSPORTED_GOODS,  // the amount of ware that has been transported
-		CONVOI_REVENUE,            // the income this CONVOI generated
-		CONVOI_OPERATIONS,         // the cost of operations this CONVOI generated
-		CONVOI_PROFIT,             // total profit of this convoi
-		CONVOI_DISTANCE,           // total distance traveled this month
-		CONVOI_MAXSPEED,           // average max. possible speed
-		CONVOI_WAYTOLL,
-		MAX_CONVOI_COST            // Total number of cost items
-	};
+	friend class convoi_sync_t;
 
 	/* Constants
 	 * @author prissi
 	 */
-	enum { max_vehicle=4, max_rail_vehicle = 24 };
-
 	enum states {INITIAL,
 		FAHRPLANEINGABE,
 		ROUTING_1,
@@ -77,8 +215,129 @@
 		MAX_STATES
 	};
 
+	enum {
+		CONVOI_CAPACITY = 0,       // the amount of ware that could be transported, theoretically
+		CONVOI_TRANSPORTED_GOODS,  // the amount of ware that has been transported
+		CONVOI_REVENUE,            // the income this CONVOI generated
+		CONVOI_OPERATIONS,         // the cost of operations this CONVOI generated
+		CONVOI_PROFIT,             // total profit of this convoi
+		CONVOI_DISTANCE,           // total distance traveled this month
+		CONVOI_MAXSPEED,           // average max. possible speed
+		CONVOI_WAYTOLL,
+		MAX_CONVOI_COST            // Total number of cost items
+	};
+
+	/* Konstanten
+	 * @author prissi
+	 */
+	enum { max_vehicle=4, max_rail_vehicle = 24 };
+
 private:
+	convoi_sync_t *cnv_sync;
+
 	/**
+	 * The coinvoi is not processed every sync step for various actions
+	 * (like waiting before signals, loading etc.) Such action will only
+	 * continue after a waiting time larger than wait_lock
+	 * @author Hanjsörg Malthaner
+	 */
+//	sint16 wait_lock;
+
+//	uint16 next_wolke;	// time to next smoke  // should be ordered last, but here filling hole
+
+//	states state;
+
+	// cached values
+	// will be recalculated if
+	// recalc_data is true
+//	sint32 speed_limit;
+
+	/**
+	* Lowest top speed of all vehicles. Doesn't get saved, but calculated
+	* from the vehicles data
+	* @author Hj. Malthaner
+	*/
+//	sint32 min_top_speed;
+
+//	sint64 sum_gesamtgewicht;
+//	sint64 sum_friction_weight;
+
+	/**
+	* the convoi is being withdrawn from service
+	* @author kierongreen
+	*/
+//	uint8 withdraw:1;
+
+	/**
+	* nothing will be loaded onto this convoi
+	* @author kierongreen
+	*/
+//	uint8 no_load:1;
+
+	/**
+	* the convoi caches its freight info; it is only recalculation after loading or resorting
+	* @author prissi
+	*/
+//	uint8 freight_info_resort:1;
+
+	// true, if at least one vehicle of a convoi is obsolete
+//	uint8 has_obsolete:1;
+
+	// ture, if there is at least one engine that requires catenary
+//	uint8 is_electric:1;
+
+//	uint8 recalc_data_front:1; // true when front vehicle in convoi hops
+//	uint8 recalc_data:1; // true when any vehicle in convoi hops
+
+	/**
+	* Number of vehicles in this convoi.
+	* @author Hj. Malthaner
+	*/
+//	uint8 anz_vehikel;
+
+	/**
+	 * this give the index of the next signal or the end of the route
+	 * convois will slow down before it, if this is not a waypoint or the cannot pass
+	 * The slowdown ist done by the vehicle routines
+	 * @author prissi
+	 */
+//	uint16 next_stop_index;
+
+	// needed for speed control/calculation
+//	sint32 brake_speed_soll;    // brake target speed
+
+//	uint32 distance_since_last_stop; // number of tiles entered since last stop
+//	uint32 sum_speed_limit; // sum of the speed limits encountered since the last stop
+
+//	sint32 akt_speed_soll;    // target speed
+//	sint32 akt_speed;	        // current speed
+
+	/**
+	* Gesamtleistung mit Gear. Wird nicht gespeichert, sondern aus den Einzelleistungen
+	* errechnet.
+	* @author prissi
+	*/
+//	sint32 sum_gear_und_leistung;
+
+//	sint32 previous_delta_v;  // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelrate
+
+	// things for the world record
+//	sint32 max_record_speed; // current convois fastest speed ever
+
+	// needed for speed control/calculation
+//	sint32 sp_soll;           // steps to go
+
+
+
+	/**
+	* The vehicles of this convoi
+	*
+	* @author Hj. Malthaner
+	*/
+//	array_tpl<vehikel_t*> fahr;
+
+
+	/**
 	* Route of this convoi - a sequence of coordinates. Actually
 	* the path of the first vehicle
 	* @author Hj. Malthaner
@@ -98,6 +357,14 @@
 	*/
 	linehandle_t line_update_pending;
 
+	/*
+	 * a list of all catg_index, which can be transported by this convoy.
+	 */
+	minivec_tpl<uint8> goods_catg_index;
+
+	// things for the world record
+//	koord record_pos;
+
 	/**
 	* Name of the convoi.
 	* @see set_name
@@ -131,18 +398,6 @@
 	sint32 loading_limit;
 
 	/**
-	* The vehicles of this convoi
-	*
-	* @author Hj. Malthaner
-	*/
-	array_tpl<vehicle_t*> fahr;
-
-	/*
-	 * a list of all catg_index, which can be transported by this convoy.
-	 */
-	minivec_tpl<uint8> goods_catg_index;
-
-	/**
 	* Convoi owner
 	* @author Hj. Malthaner
 	*/
@@ -155,47 +410,20 @@
 	static karte_ptr_t welt;
 
 	/**
-	* the convoi is being withdrawn from service
-	* @author kierongreen
-	*/
-	bool withdraw;
-
-	/**
-	* nothing will be loaded onto this convoi
-	* @author kierongreen
-	*/
-	bool no_load;
-
-	/**
 	* the convoi caches its freight info; it is only recalculation after loading or resorting
 	* @author prissi
 	*/
-	bool freight_info_resort;
+	uint8 freight_info_order;
 
-	// true, if at least one vehicle of a convoi is obsolete
-	bool has_obsolete;
+	ribi_t::ribi alte_richtung;
 
-	// true, if there is at least one engine that requires catenary
-	bool is_electric;
-
 	/**
-	* the convoi caches its freight info; it is only recalculation after loading or resorting
-	* @author prissi
-	*/
-	uint8 freight_info_order;
-
-	/**
-	* Number of vehicles in this convoi.
-	* @author Hj. Malthaner
-	*/
-	uint8 anz_vehikel;
-
-	/* Number of steps the current convoi did already
+	 * Number of steps the current convoi did already
 	 * (only needed for leaving/entering depot)
 	 */
 	sint16 steps_driven;
 
-	/*
+	/**
 	 * caches the running costs
 	 */
 	sint32 sum_running_costs;
@@ -207,13 +435,6 @@
 	*/
 	uint32 sum_leistung;
 
-	/**
-	* Overall performance with Gear.
-	* Is not stored, but is calculated from individual functions
-	* @author prissi
-	*/
-	sint32 sum_gear_und_leistung;
-
 	/* sum_gewicht: unloaded weight of all vehicles *
 	* sum_gesamtgewicht: total weight of all vehicles *
 	* Are not stored, but are calculated from individual weights
@@ -221,52 +442,8 @@
 	* @author Hj. Malthaner, prissi
 	*/
 	sint64 sum_gewicht;
-	sint64 sum_gesamtgewicht;
 
-	bool recalc_data_front;  ///< true, when front vehicle has to recalculate braking
-	bool recalc_data;        ///< true, when convoy has to recalculate weights and speed limits
-	bool recalc_speed_limit; ///< true, when convoy has to recalculate speed limits
-
-	sint64 sum_friction_weight;
-	sint32 speed_limit;
-
 	/**
-	* Lowest top speed of all vehicles. Doesn't get saved, but calculated
-	* from the vehicles data
-	* @author Hj. Malthaner
-	*/
-	sint32 min_top_speed;
-
-	/**
-	 * this give the index of the next signal or the end of the route
-	 * convois will slow down before it, if this is not a waypoint or the cannot pass
-	 * The slowdown is done by the vehicle routines
-	 * @author prissi
-	 */
-	uint16 next_stop_index;
-
-	/**
-	 * this give the index until which the route has been reserved. It is used for
-	 * restoring reservations after loading a game.
-	 * @author prissi
-	 */
-	uint16 next_reservation_index;
-
-	/**
-	 * The convoi is not processed every sync step for various actions
-	 * (like waiting before signals, loading etc.) Such action will only
-	 * continue after a waiting time larger than wait_lock
-	 * @author Hanjsörg Malthaner
-	 */
-	sint32 wait_lock;
-
-	/**
-	 * Time when convoi arrived at the current stop
-	 * Used to calculate when it should depart due to the 'month wait time'
-	 */
-	uint32 arrived_time;
-
-	/**
 	* accumulated profit over a year
 	* @author Hanjsörg Malthaner
 	*/
@@ -275,29 +452,16 @@
 	/* the odometer */
 	sint64 total_distance_traveled;
 
-	uint32 distance_since_last_stop; // number of tiles entered since last stop
-	uint32 sum_speed_limit; // sum of the speed limits encountered since the last stop
-
 	sint32 speedbonus_kmh; // speed used for speedbonus calculation in km/h
 	sint32 maxspeed_average_count;	// just a simple count to average for statistics
 
-	// things for the world record
-	sint32 max_record_speed; // current convois fastest speed ever
-	koord record_pos;
+	/**
+	 * this give the index until which the route has been reserved. It is used for
+	 * restoring reservations after loading a game.
+	 * @author prissi
+	 */
+	uint16 next_reservation_index;
 
-	// needed for speed control/calculation
-	sint32 brake_speed_soll;    // brake target speed
-	sint32 akt_speed_soll;    // target speed
-	sint32 akt_speed;	        // current speed
-	sint32 sp_soll;           // steps to go
-	sint32 previous_delta_v;  // Stores the previous delta_v value; otherwise these digits are lost during calculation and vehicle do not accelerate
-
-	uint32 next_wolke;	// time to next smoke
-
-	states state;
-
-	ribi_t::ribi alte_richtung;
-
 	/**
 	* Initialize all variables with default values.
 	* Each constructor must call this method first!
@@ -332,9 +496,6 @@
 	*/
 	void set_erstes_letztes();
 
-	// returns the index of the vehikel at position length (16=1 tile)
-	int get_vehicle_at_length(uint16);
-
 	/**
 	* calculate income for last hop
 	* only used for entering depot or recalculating routes when a schedule window is opened
@@ -350,11 +511,6 @@
 	*/
 	void calc_loading();
 
-	/* Calculates (and sets) akt_speed
-	 * needed for driving, entering and leaving a depot)
-	 */
-	void calc_acceleration(uint32 delta_t);
-
 	/*
 	* struct holds new financial history for convoi
 	* @author hsiegeln
@@ -417,7 +573,7 @@
 	linehandle_t get_line() const {return line;}
 
 	/* true, if electrification needed for this convoi */
-	bool needs_electrification() const { return is_electric; }
+	bool needs_electrification() const { return cnv_sync->is_electric; }
 
 	/**
 	* set line
@@ -439,25 +595,29 @@
 	/**
 	 * set state: only use by tool_t::tool_change_convoi_t
 	 */
-	void set_state( uint16 new_state ) { assert(new_state<MAX_STATES); state = (states)new_state; }
+	void set_state( uint16 new_state ) { assert(new_state<MAX_STATES); cnv_sync->state = new_state; }
 
 	/**
 	* get state
 	* @author hsiegeln
 	*/
-	int get_state() const { return state; }
+	uint16 get_state() const { return cnv_sync->state; }
 
 	/**
 	* true if in waiting state (maybe also due to starting)
 	* @author hsiegeln
 	*/
-	bool is_waiting() { return (state>=WAITING_FOR_CLEARANCE  &&  state<=CAN_START_TWO_MONTHS)  &&  state!=SELF_DESTRUCT; }
+	bool is_waiting() const { return (cnv_sync->state>=WAITING_FOR_CLEARANCE  &&  cnv_sync->state<=CAN_START_TWO_MONTHS)  &&  cnv_sync->state!=SELF_DESTRUCT; }
 
+	bool is_running() const { return (cnv_sync->state != INITIAL  &&  cnv_sync->state != ENTERING_DEPOT  &&  cnv_sync->state != SELF_DESTRUCT); }
+	bool is_loading() const { return (cnv_sync->state == LOADING); }
+	bool can_start() const { return (cnv_sync->state == CAN_START  ||  cnv_sync->state == CAN_START_ONE_MONTH  ||  cnv_sync->state == CAN_START_TWO_MONTHS); }
+
 	/**
 	* reset state to no error message
 	* @author prissi
 	*/
-	void reset_waiting() { state=WAITING_FOR_CLEARANCE; }
+	void reset_waiting() { cnv_sync->state=WAITING_FOR_CLEARANCE; }
 
 	/**
 	* The handle for ourselves. In Anlehnung an 'this' aber mit
@@ -560,39 +720,31 @@
 	 *         actual currently set speed.
 	 * @author Hj. Malthaner
 	 */
-	const sint32& get_akt_speed() const { return akt_speed; }
+	const sint32& get_akt_speed() const { return cnv_sync->akt_speed; }
 
 	/**
 	 * @return total power of this convoi
 	 * @author Hj. Malthaner
 	 */
 	const uint32 & get_sum_leistung() const {return sum_leistung;}
-	const sint32 & get_min_top_speed() const {return min_top_speed;}
-	const sint32 & get_speed_limit() const {return speed_limit;}
+	const sint32 & get_min_top_speed() const {return cnv_sync->min_top_speed;}
 
-	void set_speed_limit(sint32 s) { speed_limit = s;}
+	const sint32 & get_speed_limit() const {return cnv_sync->speed_limit;}
+	void set_speed_limit(sint32 s) { cnv_sync->speed_limit = s;}
 
 	/// @returns weight of the convoy's vehicles (excluding freight)
 	const sint64 & get_sum_gewicht() const {return sum_gewicht;}
 
 	/// @returns weight of convoy including freight
-	const sint64 & get_sum_gesamtgewicht() const {return sum_gesamtgewicht;}
+	const sint64 & get_sum_gesamtgewicht() const {return cnv_sync->sum_gesamtgewicht;}
 
 	/// changes sum_friction_weight, called when vehicle changed tile and friction changes as well.
-	void update_friction_weight(sint64 delta_friction_weight) { sum_friction_weight += delta_friction_weight; }
+	void update_friction_weight(sint64 delta_friction_weight) { cnv_sync->sum_friction_weight += delta_friction_weight; }
 
 	/// @returns theoretical max speed of a convoy with given @p total_power and @p total_weight
 	static sint32 calc_max_speed(uint64 total_power, uint64 total_weight, sint32 speed_limit);
 
-	uint32 get_length() const;
-
 	/**
-	 * @return length of convoi in the correct units for movement
-	 * @author neroden
-	 */
-	uint32 get_length_in_steps() const { return get_length() * VEHICLE_STEPS_PER_CARUNIT; }
-
-	/**
 	 * Add the costs for travelling one tile
 	 * @author Hj. Malthaner
 	 */
@@ -603,13 +755,16 @@
 	 * all other stuff => convoi_t::step()
 	 * @author Hj. Malthaner
 	 */
-	bool sync_step(uint32 delta_t);
+//	static sync_steppable_vector_t convoi_sync;
+//	int sync_step(const uint32 delta_t);
 
+//	void sync_add_self() { convoi_sync.sync_add(this); }
+
 	/**
 	 * All things like route search or loading, that may take a little
 	 * @author Hj. Malthaner
 	 */
-	void step();
+	void step(const uint32 delta_t);
 
 	/**
 	* sets a new convoi in route
@@ -637,16 +792,16 @@
 	* @return Vehicle count
 	* @author Hj. Malthaner
 	*/
-	uint8 get_vehikel_anzahl() const { return anz_vehikel; }
+	uint8 get_vehikel_anzahl() const { return cnv_sync->anz_vehikel; }
 
 	/**
 	 * @return Vehicle at position i
 	 */
-	vehicle_t* get_vehikel(uint16 i) const { return fahr[i]; }
+	vehicle_t* get_vehikel(uint16 i) const { return cnv_sync->fahr[i]; }
 
-	vehicle_t* front() const { return fahr[0]; }
+	vehicle_t* front() const { return cnv_sync->fahr[0]; }
 
-	vehicle_t* back() const { return fahr[anz_vehikel - 1]; }
+	vehicle_t* back() const { return cnv_sync->fahr[cnv_sync->anz_vehikel - 1]; }
 
 	/**
 	* Adds a vehicle at the start or end of the convoi.
@@ -755,7 +910,7 @@
 	* @author Volker Meyer
 	* @date  09.06.2003
 	*/
-	bool in_depot() const { return state == INITIAL; }
+	bool in_depot() const { return cnv_sync->state == INITIAL; }
 
 	/**
 	* loading_level was ladegrad before. Actual percentage loaded of loadable
@@ -839,7 +994,7 @@
 	 * The slowdown is done by the vehicle routines
 	 * @author prissi
 	 */
-	uint16 get_next_stop_index() const {return next_stop_index;}
+	uint16 get_next_stop_index() const {return cnv_sync->next_stop_index;}
 	void set_next_stop_index(uint16 n);
 
 	/* including this route_index, the route was reserved the last time
@@ -854,19 +1009,19 @@
 	// returns tiles needed for this convoi
 	uint16 get_tile_length() const;
 
-	bool has_obsolete_vehicles() const { return has_obsolete; }
+	bool has_obsolete_vehicles() const { return cnv_sync->has_obsolete; }
 
-	bool get_withdraw() const { return withdraw; }
+	bool get_withdraw() const { return cnv_sync->withdraw; }
 
 	void set_withdraw(bool new_withdraw);
 
-	bool get_no_load() const { return no_load; }
+	bool get_no_load() const { return cnv_sync->no_load; }
 
-	void set_no_load(bool new_no_load) { no_load = new_no_load; }
+	void set_no_load(bool new_no_load) { cnv_sync->no_load = new_no_load; }
 
-	void must_recalc_data() { recalc_data = true; }
-	void must_recalc_data_front() { recalc_data_front = true; }
-	void must_recalc_speed_limit() { recalc_speed_limit = true; }
+	void must_recalc_data() { cnv_sync->recalc_data = true; }
+	void must_recalc_data_front() { cnv_sync->recalc_data_front = true; }
+	void must_recalc_speed_limit() { cnv_sync->recalc_speed_limit = true; }
 
 	// calculates the speed used for the speedbonus base, and the max achievable speed at current power/weight for overtakers
 	void calc_speedbonus_kmh();
@@ -875,8 +1030,11 @@
 	// just a guess of the speed
 	uint32 get_average_kmh() const;
 
+	convoi_sync_t* get_cnv_sync() const { return cnv_sync; }
+
 	// Overtaking for convois
-	virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other);
+//	virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other);
 };
 
+
 #endif
Index: simfab.cc
===================================================================
--- simfab.cc	(revision 7507)
+++ simfab.cc	(working copy)
@@ -1459,7 +1459,6 @@
 		const sint8 offsety =  ((rada->get_xy_off(rot).y+sim_async_rand(7)-3)*OBJECT_OFFSET_STEPS)/16;
 		wolke_t *smoke =  new wolke_t(gr->get_pos(), offsetx, offsety, rada->get_bilder() );
 		gr->obj_add(smoke);
-		welt->sync_way_eyecandy_add( smoke );
 	}
 }
 
Index: simhalt.cc
===================================================================
--- simhalt.cc	(revision 7507)
+++ simhalt.cc	(working copy)
@@ -859,11 +859,11 @@
 		// now iterate over all convois
 		for(  slist_tpl<convoihandle_t>::iterator i = loading_here.begin(), end = loading_here.end();  i != end;  ) {
 			convoihandle_t const c = *i;
-			if (c.is_bound() && c->get_state() == convoi_t::LOADING) {
+			if(  c.is_bound()  &&  c->is_loading()  ) {
 				// now we load into convoi
 				c->hat_gehalten(self);
 			}
-			if (c.is_bound() && c->get_state() == convoi_t::LOADING) {
+			if(  c.is_bound()  &&  c->is_loading()  ) {
 				++i;
 			}
 			else {
Index: simline.cc
===================================================================
--- simline.cc	(revision 7507)
+++ simline.cc	(working copy)
@@ -148,7 +148,7 @@
 
 	// what goods can this line transport?
 	bool update_schedules = false;
-	if(  cnv->get_state()!=convoi_t::INITIAL  ) {
+	if(  !cnv->in_depot()  ) {
 		FOR(minivec_tpl<uint8>, const catg_index, cnv->get_goods_catg_index()) {
 			if(  !goods_catg_index.is_contained( catg_index )  ) {
 				goods_catg_index.append( catg_index, 1 );
Index: simmain.cc
===================================================================
--- simmain.cc	(revision 7507)
+++ simmain.cc	(working copy)
@@ -53,6 +53,25 @@
 
 #include "obj/baum.h"
 
+#include "obj/leitung2.h"
+#include "obj/roadsign.h"
+#include "vehicle/simpeople.h"
+#include "dataobj/fahrplan.h"
+#include "obj/wolke.h"
+#include "vehicle/movingobj.h"
+#include "simfab.h"
+#include "player/finance.h"
+#include "simconvoi.h"
+
+#ifdef DEBUG
+#include "obj/wolke.h"
+#include "obj/leitung2.h"
+#include "obj/roadsign.h"
+#include "vehicle/movingobj.h"
+#include "vehicle/simpeople.h"
+#include "dataobj/fahrplan.h"
+#endif
+
 #include "utils/simstring.h"
 #include "utils/searchfolder.h"
 
@@ -86,34 +105,57 @@
  */
 static void show_sizes()
 {
-	DBG_MESSAGE("Debug", "size of structures");
+	dbg->important("Debug:  size of structures");
 
-	DBG_MESSAGE("sizes", "koord: %d", sizeof(koord));
-	DBG_MESSAGE("sizes", "koord3d: %d", sizeof(koord3d));
-	DBG_MESSAGE("sizes", "ribi_t::ribi: %d", sizeof(ribi_t::ribi));
-	DBG_MESSAGE("sizes", "halthandle_t: %d\n", sizeof(halthandle_t));
+	dbg->important("sizes:  koord: %d", sizeof(koord));
+	dbg->important("sizes:  koord3d: %d", sizeof(koord3d));
+	dbg->important("sizes:  ribi_t::ribi: %d\n", sizeof(ribi_t::ribi));
 
-	DBG_MESSAGE("sizes", "obj_t: %d", sizeof(obj_t));
-	DBG_MESSAGE("sizes", "gebaeude_t: %d", sizeof(gebaeude_t));
-	DBG_MESSAGE("sizes", "baum_t: %d", sizeof(baum_t));
-	DBG_MESSAGE("sizes", "weg_t: %d", sizeof(weg_t));
-	DBG_MESSAGE("sizes", "private_car_t: %d\n", sizeof(private_car_t));
+ 	dbg->important("sizes:  karte_t: %d", sizeof(karte_t));
+	dbg->important("sizes:  planquadrat_t: %d", sizeof(planquadrat_t));
+	dbg->important("sizes:  grund_t: %d", sizeof(grund_t));
+	dbg->important("sizes:  boden_t: %d", sizeof(boden_t));
+	dbg->important("sizes:  wasser_t: %d\n", sizeof(wasser_t));
 
-	DBG_MESSAGE("sizes", "grund_t: %d", sizeof(grund_t));
-	DBG_MESSAGE("sizes", "boden_t: %d", sizeof(boden_t));
-	DBG_MESSAGE("sizes", "wasser_t: %d", sizeof(wasser_t));
-	DBG_MESSAGE("sizes", "planquadrat_t: %d\n", sizeof(planquadrat_t));
+	dbg->important("sizes:  obj_t: %d", sizeof(obj_t));
+	dbg->important("sizes:  baum_t: %d", sizeof(baum_t));
+	dbg->important("sizes:  gebaeude_t: %d", sizeof(gebaeude_t));
+	dbg->important("sizes:  senke_t: %d", sizeof(senke_t));
+	dbg->important("sizes:  private_car_t: %d", sizeof(private_car_t));
+	dbg->important("sizes:  roadsign_t: %d", sizeof(roadsign_t));
+	dbg->important("sizes:  wolke_t: %d", sizeof(wolke_t));
+	dbg->important("sizes:  movingobj_t: %d", sizeof(movingobj_t));
+	dbg->important("sizes:  pedestrian_t: %d", sizeof(pedestrian_t));
+	dbg->important("sizes:  weg_t: %d\n", sizeof(weg_t));
 
-	DBG_MESSAGE("sizes", "ware_t: %d", sizeof(ware_t));
-	DBG_MESSAGE("sizes", "vehicle_t: %d", sizeof(vehicle_t));
-	DBG_MESSAGE("sizes", "haltestelle_t: %d\n", sizeof(haltestelle_t));
+	dbg->important("sizes:  convoihandle_t: %d", sizeof(convoihandle_t));
+	dbg->important("sizes:  convoi_t: %d", sizeof(convoi_t));
+	dbg->important("sizes:  convoi_sync_t: %d", sizeof(convoi_sync_t));
+	dbg->important("sizes:  vehicle_base_t: %d", sizeof(vehicle_base_t));
+ 	dbg->important("sizes:  vehicle_t: %d", sizeof(vehicle_t));
+ 	dbg->important("sizes:  road_vehicle_t: %d", sizeof(road_vehicle_t));
+ 	dbg->important("sizes:  rail_vehicle_t: %d", sizeof(rail_vehicle_t));
+ 	dbg->important("sizes:  monorail_vehicle_t: %d", sizeof(monorail_vehicle_t));
+ 	dbg->important("sizes:  maglev_vehicle_t: %d", sizeof(maglev_vehicle_t));
+ 	dbg->important("sizes:  narrowgauge_vehicle_t: %d", sizeof(narrowgauge_vehicle_t));
+ 	dbg->important("sizes:  water_vehicle_t: %d", sizeof(water_vehicle_t));
+ 	dbg->important("sizes:  air_vehicle_t: %d\n", sizeof(air_vehicle_t));
 
-	DBG_MESSAGE("sizes", "karte_t: %d", sizeof(karte_t));
-	DBG_MESSAGE("sizes", "player_t: %d\n", sizeof(player_t));
+ 	dbg->important("sizes:  fabrik_t: %d", sizeof(fabrik_t));
+ 	dbg->important("sizes:  ware_t: %d\n", sizeof(ware_t));
+
+ 	dbg->important("sizes:  haltestelle_t: %d", sizeof(haltestelle_t));
+	dbg->important("sizes:  halthandle_t: %d", sizeof(halthandle_t));
+
+	dbg->important("sizes:  route_t: %d", sizeof(route_t));
+	dbg->important("sizes:  linehandle_t: %d", sizeof(linehandle_t));
+	dbg->important("sizes:  schedule_t: %d\n", sizeof(schedule_t));
+
+	dbg->important("sizes:  player_t: %d", sizeof(player_t));
+	dbg->important("sizes:  finance_t: %d\n", sizeof(finance_t));
 }
 
 
-
 // render tests ...
 static void show_times(karte_t *welt, karte_ansicht_t *view)
 {
@@ -939,6 +981,7 @@
 		dbg->important("Multithreading not enabled: threads = %d ignored.", env_t::num_threads );
 	}
 #endif
+	printf("THREADS = %d.\n", env_t::num_threads );
 
 	// just check before loading objects
 	if (!gimme_arg(argc, argv, "-nosound", 0)  &&  dr_init_sound()) {
@@ -1154,7 +1197,8 @@
 	chdir(env_t::user_dir);
 
 	// reset random counter to true randomness
-	setsimrand(dr_time(), dr_time());
+//	setsimrand(dr_time(), dr_time());
+	setsimrand(0,0);
 	clear_random_mode( 7 );	// allow all
 
 	if(  loadgame==""  ||  !welt->load(loadgame.c_str())  ) {
@@ -1292,7 +1336,8 @@
 		welt->get_message()->get_message_flags(&env_t::message_flags[0], &env_t::message_flags[1], &env_t::message_flags[2], &env_t::message_flags[3]);
 		welt->set_fast_forward(false);
 		welt->set_pause(false);
-		setsimrand(dr_time(), dr_time());
+//		setsimrand(dr_time(), dr_time());
+		setsimrand(0,0);
 
 		dbg->important( "World finished ..." );
 	}
Index: simsys_s.cc
===================================================================
--- simsys_s.cc	(revision 7507)
+++ simsys_s.cc	(working copy)
@@ -90,7 +90,7 @@
 static SDL_Cursor* hourglass;
 static SDL_Cursor* blank;
 
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 #include "utils/simthread.h"
 
 static simthread_barrier_t redraw_barrier;
@@ -182,7 +182,7 @@
 // open the window
 int dr_os_open(int w, int const h, int const fullscreen)
 {
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	// init barrier
 	simthread_barrier_init( &redraw_barrier, NULL, 2);
 
@@ -254,7 +254,7 @@
 // shut down SDL
 void dr_os_close()
 {
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	// make sure redraw thread is waiting before closing
 	pthread_mutex_lock( &redraw_mutex );
 #endif
@@ -269,7 +269,7 @@
 // resizes screen
 int dr_textur_resize(unsigned short** const textur, int w, int const h)
 {
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	pthread_mutex_lock( &redraw_mutex );
 #endif
 	if(  use_hw  ) {
@@ -302,7 +302,7 @@
 		fflush(NULL);
 	}
 	*textur = (unsigned short*)screen->pixels;
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	pthread_mutex_unlock( &redraw_mutex );
 #endif
 	return w;
@@ -331,7 +331,7 @@
 
 void dr_prepare_flush()
 {
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	pthread_mutex_lock( &redraw_mutex );
 #endif
 	return;
@@ -340,7 +340,7 @@
 
 void dr_flush()
 {
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 	pthread_mutex_unlock( &redraw_mutex );
 	simthread_barrier_wait( &redraw_barrier );	// start thread
 #else
@@ -381,7 +381,7 @@
 		if(  w*h > 0  )
 #endif
 		{
-#ifdef MULTI_THREAD
+#ifdef mMULTI_THREAD
 			SDL_UpdateRect( screen, xp, yp, w, h );
 #else
 			if(  num_SDL_Rects < MAX_SDL_RECTS  ) {
Index: simtool.cc
===================================================================
--- simtool.cc	(revision 7507)
+++ simtool.cc	(working copy)
@@ -5438,7 +5438,6 @@
 		// add citycar
 		private_car_t* vt = new private_car_t(gr, koord::invalid);
 		gr->obj_add(vt);
-		welt->sync_add(vt);
 		return NULL;
 	}
 	return "";
Index: simworld.cc
===================================================================
--- simworld.cc	(revision 7507)
+++ simworld.cc	(working copy)
@@ -54,6 +54,7 @@
 #include "boden/wasser.h"
 
 #include "old_blockmanager.h"
+#include "vehicle/simpeople.h"
 #include "vehicle/simvehicle.h"
 #include "vehicle/simroadtraffic.h"
 #include "vehicle/movingobj.h"
@@ -67,6 +68,7 @@
 #include "obj/groundobj.h"
 #include "obj/gebaeude.h"
 #include "obj/leitung2.h"
+#include "obj/wolke.h"
 
 #include "gui/password_frame.h"
 #include "gui/messagebox.h"
@@ -132,6 +134,110 @@
 static simthread_barrier_t world_barrier_end;
 
 
+// new sync_step thread stuff here
+
+bool world_spawned_threads2 = false; // global job indicator array
+static pthread_barrier_t world_barrier_start2;
+static pthread_barrier_t world_barrier_end2;
+//static pthread_spinlock_t world_spin;
+//static pthread_spinlock_t world_spin2;
+//static pthread_mutex_t world_mutex = PTHREAD_MUTEX_INITIALIZER;
+//static pthread_mutex_t world_mutex2 = PTHREAD_MUTEX_INITIALIZER;
+
+enum world_job_t { job_none = -1, job_new_month_cities = 1, job_check_season, job_sync_step };
+
+typedef struct {
+	uint32 delta_t;
+	karte_t* welt;
+	world_job_t job;
+	pthread_t thread;
+	uint8 number;
+	bool need_locality_update;
+} world_step_thread_param_t2;
+
+static world_step_thread_param_t2 world_thread_param2[MAX_THREADS-1];
+
+void *world_thread( void *ptr )
+{
+	world_step_thread_param_t2 *param = reinterpret_cast<world_step_thread_param_t2 *>(ptr);
+
+//	pthread_spin_lock( &world_spin2 );
+//	pthread_mutex_lock( &world_mutex2 );
+//	pthread_barrier_wait( &world_barrier_start );	// wait for all to start
+
+
+	while(true) {
+		pthread_barrier_wait( &world_barrier_start2 );	// wait for all to start
+//		pthread_spin_unlock( &world_spin2 );
+//		pthread_spin_lock( &world_spin );
+//		pthread_mutex_unlock( &world_mutex2 );
+//		pthread_mutex_lock( &world_mutex );
+		switch(  param->job  ) {
+			case job_new_month_cities: {
+//				param->welt->new_month_cities( param->number, param->need_locality_update );
+				break;
+			}
+			case job_check_season: {
+//				param->welt->check_season( param->number );
+				break;
+			}
+			case job_sync_step: {
+//printf("%d ", param->number);
+//				gebaeude_t::gebaeude_sync.sync_step_all( param->number, param->delta_t );
+//				pthread_barrier_wait( &world_barrier_end );	// wait for all to finish
+//				pthread_barrier_wait( &world_barrier_start );	// wait for all to start
+//				senke_t::senke_sync.sync_step_all( param->number, param->delta_t );
+//				pthread_barrier_wait( &world_barrier_end );	// wait for all to finish
+//				pthread_barrier_wait( &world_barrier_start );	// wait for all to start
+//				roadsign_t::roadsign_sync.sync_step_all( param->number, param->delta_t );
+//				pthread_barrier_wait( &world_barrier_end );	// wait for all to finish
+//				pthread_barrier_wait( &world_barrier_start );	// wait for all to start
+//				wolke_t::wolke_sync.sync_step_all( param->number, param->delta_t );
+				break;
+			}
+			default: {
+				break;
+			}
+		}
+		param->job = job_none;
+		pthread_barrier_wait( &world_barrier_end2 );	// wait for all to finish
+//		pthread_spin_unlock( &world_spin );
+//		pthread_spin_lock( &world_spin2 );
+//		pthread_mutex_unlock( &world_mutex );
+//		pthread_mutex_lock( &world_mutex2 );
+	}
+	return ptr;
+}
+
+
+void spawn_world_threads2() {
+	// init barrier
+	pthread_barrier_init( &world_barrier_start2, NULL, env_t::num_threads );
+	pthread_barrier_init( &world_barrier_end2, NULL, env_t::num_threads );
+//	pthread_spin_init(&world_spin, PTHREAD_PROCESS_PRIVATE);
+//	pthread_spin_init(&world_spin2, PTHREAD_PROCESS_PRIVATE);
+
+	// Initialize and set thread detached attribute
+	pthread_attr_t attr;
+	pthread_attr_init(&attr);
+	pthread_attr_setdetachstate(&attr, PTHREAD_CREATE_DETACHED);
+
+	for(  int t=0;  t<env_t::num_threads-1;  t++  ) {
+		world_thread_param2[t].job = job_none;
+		world_thread_param2[t].number = t;
+		if(  pthread_create(&(world_thread_param2[t].thread), &attr, world_thread, (void *)&world_thread_param2[t])  ) {
+			dbg->fatal( "spawn_world_threads2()", "cannot multithread, error at thread #%i", t+1 );
+			return;
+		}
+	}
+	pthread_attr_destroy(&attr);
+
+	world_spawned_threads2 = true;
+}
+
+
+// xy thread stuff here //////////////////////////////////////////////////////////////////////
+
 // to start a thread
 typedef struct{
 	karte_t *welt;
@@ -754,31 +860,15 @@
 	old_progress += cached_size.x*cached_size.y;
 
 	// removes all moving stuff from the sync_step
-	while(!sync_list.empty()) {
-#ifndef SYNC_VECTOR
-		sync_steppable *ss = sync_list.remove_first();
-		delete ss;
-#else
-		delete sync_list.back();
-#endif
-	}
-	sync_list.clear();
+	gebaeude_t::gebaeude_sync.sync_remove_all();
+	senke_t::senke_sync.sync_remove_all();
+	roadsign_t::roadsign_sync.sync_remove_all();
+	convoi_sync_t::convoi_sync.sync_remove_all();
+	wolke_t::wolke_sync.sync_remove_all();
+	movingobj_t::movingobj_sync.sync_remove_all();
+	private_car_t::private_car_sync.sync_remove_all();
+	pedestrian_t::pedestrian_sync.sync_remove_all();
 
-	// now remove all pedestrians too ...
-	while(!sync_eyecandy_list.empty()) {
-		sync_steppable *ss = sync_eyecandy_list.remove_first();
-		delete ss;
-	}
-
-	while(!sync_way_eyecandy_list.empty()) {
-#if !defined(SYNC_WAY_LIST)  &&  !defined(SYNC_WAY_HASHTABLE)
-		delete sync_way_eyecandy_list.back();
-#else
-		sync_steppable *ss = sync_way_eyecandy_list.remove_first();
-		delete ss;
-#endif
-	}
-
 	ls.set_progress( old_progress );
 DBG_MESSAGE("karte_t::destroy()", "sync list cleared");
 
@@ -827,6 +917,8 @@
 
 DBG_MESSAGE("karte_t::destroy()", "world destroyed");
 	dbg->important("World destroyed.");
+
+	fflush(NULL);
 }
 
 
@@ -3666,200 +3758,7 @@
 
 // -------- Verwaltung von synchronen Objekten ------------------
 
-static volatile bool sync_step_running = false;
-static volatile bool sync_step_eyecandy_running = false;
-static volatile bool sync_way_eyecandy_running = false;
 
-// handling animations and the like
-bool karte_t::sync_eyecandy_add(sync_steppable *obj)
-{
-	if(  sync_step_eyecandy_running  ) {
-		sync_eyecandy_add_list.insert( obj );
-	}
-	else {
-		sync_eyecandy_list.put( obj, obj );
-	}
-	return true;
-}
-
-
-bool karte_t::sync_eyecandy_remove(sync_steppable *obj)	// entfernt alle dinge == obj aus der Liste
-{
-	if(  sync_step_eyecandy_running  ) {
-		sync_eyecandy_remove_list.append(obj);
-	}
-	else {
-		if(  sync_eyecandy_add_list.remove(obj)  ) {
-			return true;
-		}
-		return sync_eyecandy_list.remove(obj)!=NULL;
-	}
-	return false;
-}
-
-
-void karte_t::sync_eyecandy_step(uint32 delta_t)
-{
-	sync_step_eyecandy_running = true;
-	// first add everything
-	while(  !sync_eyecandy_add_list.empty()  ) {
-		sync_steppable *obj = sync_eyecandy_add_list.remove_first();
-		sync_eyecandy_list.put( obj, obj );
-	}
-	// now remove everything from last time
-	sync_step_eyecandy_running = false;
-	while(  !sync_eyecandy_remove_list.empty()  ) {
-		sync_eyecandy_list.remove( sync_eyecandy_remove_list.remove_first() );
-	}
-	// now step ...
-	sync_step_eyecandy_running = true;
-	for(  ptrhashtable_tpl<sync_steppable*,sync_steppable*>::iterator iter = sync_eyecandy_list.begin();  iter != sync_eyecandy_list.end();  ) {
-		// if false, then remove
-		sync_steppable *ss = iter->key;
-		if(!ss->sync_step(delta_t)) {
-			iter = sync_eyecandy_list.erase(iter);
-			delete ss;
-		}
-		else {
-			++iter;
-		}
-	}
-	// now remove everything from last time
-	sync_step_eyecandy_running = false;
-	while(  !sync_eyecandy_remove_list.empty()  ) {
-		sync_eyecandy_list.remove( sync_eyecandy_remove_list.remove_first() );
-	}
-	sync_step_eyecandy_running = false;
-}
-
-
-// and now the same for pedestrians
-bool karte_t::sync_way_eyecandy_add(sync_steppable *obj)
-{
-	if(  sync_way_eyecandy_running  ) {
-		sync_way_eyecandy_add_list.insert( obj );
-	}
-	else {
-#ifdef SYNC_WAY_HASHTABLE
-		sync_way_eyecandy_list.put( obj, obj );
-#else
-		sync_way_eyecandy_list.append( obj );
-#endif
-	}
-	return true;
-}
-
-
-bool karte_t::sync_way_eyecandy_remove(sync_steppable *obj)	// entfernt alle dinge == obj aus der Liste
-{
-	if(  sync_way_eyecandy_running  ) {
-		sync_way_eyecandy_remove_list.append(obj);
-	}
-	else {
-		if(  sync_way_eyecandy_add_list.remove(obj)  ) {
-			return true;
-		}
-		return sync_way_eyecandy_list.remove(obj);
-	}
-	return false;
-}
-
-
-void karte_t::sync_way_eyecandy_step(uint32 delta_t)
-{
-	sync_way_eyecandy_running = true;
-	// first add everything
-	while(  !sync_way_eyecandy_add_list.empty()  ) {
-		sync_steppable *obj = sync_way_eyecandy_add_list.remove_first();
-#ifdef SYNC_WAY_HASHTABLE
-		sync_way_eyecandy_list.put( obj, obj );
-#else
-		sync_way_eyecandy_list.append( obj );
-#endif
-	}
-	// now remove everything from last time
-	sync_way_eyecandy_running = false;
-	while(  !sync_way_eyecandy_remove_list.empty()  ) {
-		sync_way_eyecandy_list.remove( sync_way_eyecandy_remove_list.remove_first() );
-	}
-	// now the actualy stepping
-	sync_way_eyecandy_running = true;
-#ifdef SYNC_WAY_HASHTABLE
-	for(  ptrhashtable_tpl<sync_steppable*,sync_steppable*>::iterator iter = sync_way_eyecandy_list.begin();  iter != sync_way_eyecandy_list.end();  ) {
-		// if false, then remove
-		sync_steppable *ss = iter->key;
-		if(!ss->sync_step(delta_t)) {
-			iter = sync_way_eyecandy_list.erase(iter);
-			delete ss;
-		}
-		else {
-			++iter;
-		}
-	}
-#elif SYNC_WAY_LIST
-	for(  slist_tpl<sync_steppable*>::iterator i=sync_way_eyecandy_list.begin();  !i.end();  ) {
-		// if false, then remove
-		sync_steppable *ss = *i;
-		if(!ss->sync_step(delta_t)) {
-			i = sync_way_eyecandy_list.erase(i);
-			delete ss;
-		}
-		else {
-			++i;
-		}
-	}
-#else
-	static vector_tpl<sync_steppable *> sync_way_eyecandy_list_copy;
-	sync_way_eyecandy_list_copy.resize( (uint32) (sync_way_eyecandy_list.get_count()*1.1) );
-	FOR(vector_tpl<sync_steppable*>, const ss, sync_way_eyecandy_list) {
-		// if false, then remove
-		if(!ss->sync_step(delta_t)) {
-			delete ss;
-		}
-		else {
-			sync_way_eyecandy_list_copy.append( ss );
-		}
-	}
-	swap( sync_way_eyecandy_list_copy, sync_way_eyecandy_list );
-	sync_way_eyecandy_list_copy.clear();
-#endif
-	// now remove everything from last time
-	sync_way_eyecandy_running = false;
-	while(  !sync_way_eyecandy_remove_list.empty()  ) {
-		sync_way_eyecandy_list.remove( sync_way_eyecandy_remove_list.remove_first() );
-	}
-}
-
-
-// ... and now all regular stuff, which needs to are in the same order on any plattform
-// Thus we are using (slower) lists/vectors and no pointerhashtables
-bool karte_t::sync_add(sync_steppable *obj)
-{
-	if(  sync_step_running  ) {
-		sync_add_list.insert( obj );
-	}
-	else {
-		sync_list.append( obj );
-	}
-	return true;
-}
-
-
-bool karte_t::sync_remove(sync_steppable *obj)	// entfernt alle dinge == obj aus der Liste
-{
-	if(  sync_step_running  ) {
-		sync_remove_list.append(obj);
-	}
-	else {
-		if(sync_add_list.remove(obj)) {
-			return true;
-		}
-		return sync_list.remove(obj);
-	}
-	return false;
-}
-
-
 /*
  * this routine is called before an image is displayed
  * it moves vehicles and pedestrians
@@ -3868,7 +3767,29 @@
  */
 void karte_t::sync_step(uint32 delta_t, bool sync, bool display )
 {
+static uint64 ddd=0;
+static uint64 eee=0;
+static unsigned long tickss=0;
+static unsigned long next_tickss=0;
+static unsigned long syncss=0;
+static unsigned long gebaeude_count=0;
+static sint64 gebaeude_cum=0;
+static unsigned long senke_count=0;
+static sint64 senke_cum=0;
+static unsigned long roadsign_count=0;
+static sint64 roadsign_cum=0;
+static unsigned long convoi_count=0;
+static unsigned long wolke_count=0;
+static unsigned long wolke_hole_count=0;
+static sint64 wolke_cum=0;
+static unsigned long movingobj_count=0;
+static unsigned long private_car_count=0;
+static unsigned long pedestrian_count=0;
+LARGE_INTEGER li1, li2, li3;
+
 	set_random_mode( SYNC_STEP_RANDOM );
+
+QueryPerformanceCounter(&li1);
 	if(sync) {
 		// only omitted, when called to display a new frame during fast forward
 
@@ -3879,78 +3800,104 @@
 		}
 		ticks += delta_t;
 
-		set_random_mode( INTERACTIVE_RANDOM );
+		movingobj_t::movingobj_rand.refresh_list(max(4,movingobj_t::movingobj_sync.get_count()>>5)); // /32 from testing
+		private_car_t::private_car_rand.refresh_list(max(4,private_car_t::private_car_sync.get_count()>>5)); // /32 from testing
+		pedestrian_t::pedestrian_rand.refresh_list(max(4,pedestrian_t::pedestrian_sync.get_count()>>7)); // /128 from testing shows unlikely to overflow.
 
-		/* animations do not require exact sync
-		 * foundations etc are added removed freuently during city growth
-		 * => they are now in a hastable!
-		 */
-		sync_eyecandy_step( delta_t );
+//#ifdef MULTI_THREAD
+		if(  !world_spawned_threads2  ) {
+			spawn_world_threads2();
+//			pthread_spin_lock( &world_spin );
+//			pthread_mutex_lock( &world_mutex );
+//			pthread_barrier_wait( &world_barrier_start );
+ 		}
 
-		/* pedestrians do not require exact sync and are added/removed frequently
-		 * => they are now in a hastable!
-		 */
-		sync_way_eyecandy_step( delta_t );
+		// set parameter for each thread (here because welt could change)
+		for(  int t=0;  t<env_t::num_threads-1;  t++  ) {
+			world_thread_param2[t].delta_t = delta_t;
+			world_thread_param2[t].welt = this;
+			world_thread_param2[t].job = job_sync_step;
+ 		}
 
-		clear_random_mode( INTERACTIVE_RANDOM );
+//		gebaeude_t::gebaeude_sync.sort_lists( ticks, "gebaeude_t" );
+//		senke_t::senke_sync.sort_lists( ticks, "senke_t" );
+//		roadsign_t::roadsign_sync.sort_lists( ticks, "roadsign_t" );
+//		wolke_t::wolke_sync.sort_lists( ticks, "wolke_t" );
 
-		/* and now the rest for the other moving stuff */
-		sync_step_running = true;
-#ifndef SYNC_VECTOR
-		// insert new objects created during last sync_step (eg vehicle smoke)
-		if(!sync_add_list.empty()) {
-			sync_list.append_list(sync_add_list);
-		}
-#else
-		while(  !sync_add_list.empty()  ) {
-			sync_list.append( sync_add_list.remove_first() );
-		}
-#endif
+//		sint64 start, start2, start3, start4;
+//		start = gebaeude_t::gebaeude_sync.sync_step_btd();
+//		start2 = senke_t::senke_sync.sync_step_btd();
+//		start3 = roadsign_t::roadsign_sync.sync_step_btd();
+//		start4 = wolke_t::wolke_sync.sync_step_btd();
 
-		// now remove everything from last time
-		sync_step_running = false;
-		while(  !sync_remove_list.empty()  ) {
-			sync_list.remove( sync_remove_list.remove_first() );
-		}
+// MT
+//		pthread_spin_unlock( &world_spin );
+//		pthread_spin_lock( &world_spin2 );
+//		pthread_mutex_unlock( &world_mutex );
+//		pthread_mutex_lock( &world_mutex2 );
+//		pthread_barrier_wait( &world_barrier_start );
 
-		sync_step_running = true;
-#ifndef SYNC_VECTOR
-		for(  slist_tpl<sync_steppable*>::iterator i=sync_list.begin();  !i.end();  ) {
-			// if false, then remove
-			sync_steppable *ss = *i;
-			if(!ss->sync_step(delta_t)) {
-				i = sync_list.erase(i);
-				delete ss;
-			}
-			else {
-				++i;
-			}
-		}
-#else
-		static vector_tpl<sync_steppable *> sync_list_copy;
-		sync_list_copy.resize( sync_list.get_count() );
-		FOR(vector_tpl<sync_steppable*>, const ss, sync_list) {
-			// if false, then remove
-			if(!ss->sync_step(delta_t)) {
-				delete ss;
-			}
-			else {
-				sync_list_copy.append( ss );
-			}
-		}
-		swap( sync_list_copy, sync_list );
-		sync_list_copy.clear();
-#endif
+// ST but with MULTI_Defined
+//		gebaeude_t::gebaeude_sync.sort_lists( ticks, "gebaeude_t" );
+//		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+//			gebaeude_t::gebaeude_sync.sync_step_all( i, delta_t );
+//		}
+//		senke_t::senke_sync.sort_lists( ticks, "senke_t" );
+//		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+//			senke_t::senke_sync.sync_step_all( i, delta_t );
+//		}
+//		roadsign_t::roadsign_sync.sort_lists( ticks, "roadsign_t" );
+//		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+//			roadsign_t::roadsign_sync.sync_step_all( i, delta_t );
+//		wolke_t::wolke_sync.sort_lists( ticks, "wolke_t" );
+//		}
+//		for(  int i=0;  i<env_t::num_threads;  i++  ) {
+//			wolke_t::wolke_sync.sync_step_all( i, delta_t );
+//		}
 
-		// now remove everything from this time
-		sync_step_running = false;
-		while(!sync_remove_list.empty()) {
-			sync_list.remove( sync_remove_list.remove_first() );
-		}
+//		gebaeude_t::gebaeude_sync.sync_step_all( env_t::num_threads-1, delta_t );
+//		pthread_barrier_wait( &world_barrier_end );
+//		senke_t::senke_sync.sync_step_all( env_t::num_threads-1, delta_t );
+//		pthread_barrier_wait( &world_barrier_end );
+//		roadsign_t::roadsign_sync.sync_step_all( env_t::num_threads-1, delta_t );
+//		pthread_barrier_wait( &world_barrier_end );
+//		wolke_t::wolke_sync.sync_step_all( env_t::num_threads-1, delta_t );
 
-		sync_step_running = false;
-	}
+//		pthread_spin_unlock( &world_spin2 );
+//		pthread_spin_lock( &world_spin );
+//		pthread_mutex_unlock( &world_mutex2 );
+//		pthread_mutex_lock( &world_mutex );
+//		pthread_barrier_wait( &world_barrier_end );
 
+//		gebaeude_t::gebaeude_sync.sync_step_ftd( start );
+//		senke_t::senke_sync.sync_step_ftd( start2 );
+//		roadsign_t::roadsign_sync.sync_step_ftd( start3 );
+//		wolke_t::wolke_sync.sync_step_ftd( start4 );
+//#else
+		// single threaded
+		gebaeude_t::gebaeude_sync.sort_lists( ticks, "gebaeude_t" );
+		gebaeude_t::gebaeude_sync.sync_step_all( delta_t );
+		senke_t::senke_sync.sort_lists( ticks, "senke_t" );
+		senke_t::senke_sync.sync_step_all( delta_t );
+		roadsign_t::roadsign_sync.sort_lists( ticks, "roadsign_t" );
+		roadsign_t::roadsign_sync.sync_step_all( delta_t );
+		wolke_t::wolke_sync.sort_lists( ticks, "wolke_t" );
+		wolke_t::wolke_sync.sync_step_all( delta_t );
+//#endif
+
+		convoi_sync_t::convoi_sync.sort_lists( ticks, "convoi_t" );
+		convoi_sync_t::convoi_sync.sync_step_all( delta_t );
+		movingobj_t::movingobj_sync.sort_lists( ticks, "movingobj_t" );
+		movingobj_t::movingobj_sync.sync_step_all( delta_t );
+		private_car_t::private_car_sync.sort_lists( ticks, "private_car_t" );
+		private_car_t::private_car_sync.sync_step_all( delta_t );
+		pedestrian_t::pedestrian_sync.sort_lists( ticks, "pedestrian_t" );
+		pedestrian_t::pedestrian_sync.sync_step_all( delta_t );
+
+		clear_random_mode( INTERACTIVE_RANDOM );
+ 	}
+
+QueryPerformanceCounter(&li2);
 	if(display) {
 		// only omitted in fast forward mode for the magic steps
 
@@ -3980,6 +3927,104 @@
 		intr_refresh_display( false );
 		update_frame_sleep_time();
 	}
+
+QueryPerformanceCounter(&li3);
+if(sync) {
+	ddd+=(li3.QuadPart-li2.QuadPart);
+	eee+=(li3.QuadPart-li1.QuadPart);
+	tickss+=delta_t;
+	next_tickss+=delta_t;
+	syncss++;
+
+	gebaeude_count+=gebaeude_t::gebaeude_sync.get_count();
+	senke_count+=senke_t::senke_sync.get_count();
+	roadsign_count+=roadsign_t::roadsign_sync.get_count();
+	convoi_count+=convoi_sync_t::convoi_sync.get_count();
+	wolke_count+=wolke_t::wolke_sync.get_count();
+	movingobj_count+=movingobj_t::movingobj_sync.get_count();
+	private_car_count+=private_car_t::private_car_sync.get_count();
+	pedestrian_count+=pedestrian_t::pedestrian_sync.get_count();
+
+
+	QueryPerformanceFrequency(&li1);
+	const double freqscale = li1.QuadPart/1000.0;
+/*
+//	printf("  geb:");
+	for(  int i=0; i < env_t::num_threads;  i++) {
+		sint64 sm = 0x0FFFFFFFFFFFFFFF;
+		sint64 bg = 0;
+		if(  gebaeude_t::gebaeude_sync.get_finish(i).QuadPart > bg  ) bg = gebaeude_t::gebaeude_sync.get_finish(i).QuadPart;
+		if(  gebaeude_t::gebaeude_sync.get_start(i).QuadPart < sm  ) sm = gebaeude_t::gebaeude_sync.get_start(i).QuadPart;
+		gebaeude_cum+=bg-sm;
+//		printf(" %I64d %I64d %.3f", gebaeude_t::gebaeude_sync.get_start(i).QuadPart, gebaeude_t::gebaeude_sync.get_finish(i).QuadPart, (double)(bg-sm)/freqscale );
+	}
+//	printf("  senke:");
+	for(  int i=0; i < env_t::num_threads;  i++) {
+		sint64 sm = 0x0FFFFFFFFFFFFFFF;
+		sint64 bg = 0;
+		if(  senke_t::senke_sync.get_finish(i).QuadPart > bg  ) bg = senke_t::senke_sync.get_finish(i).QuadPart;
+		if(  senke_t::senke_sync.get_start(i).QuadPart < sm  ) sm = senke_t::senke_sync.get_start(i).QuadPart;
+		senke_cum+=bg-sm;
+//		printf(" %I64d %I64d %.3f", senke_t::senke_sync.get_start(i).QuadPart, senke_t::senke_sync.get_finish(i).QuadPart, (double)(bg-sm)/freqscale );
+	}
+//	printf("  rs:");
+	for(  int i=0; i < env_t::num_threads;  i++) {
+		sint64 sm = 0x0FFFFFFFFFFFFFFF;
+		sint64 bg = 0;
+		if(  roadsign_t::roadsign_sync.get_finish(i).QuadPart > bg  ) bg = roadsign_t::roadsign_sync.get_finish(i).QuadPart;
+		if(  roadsign_t::roadsign_sync.get_start(i).QuadPart < sm  ) sm = roadsign_t::roadsign_sync.get_start(i).QuadPart;
+		roadsign_cum+=bg-sm;
+//		printf(" %I64d %I64d %.3f", roadsign_t::roadsign_sync.get_start(i).QuadPart, roadsign_t::roadsign_sync.get_finish(i).QuadPart, (double)(bg-sm)/freqscale  );
+	}
+//	printf("  wolke:");
+	for(  int i=0; i < env_t::num_threads;  i++) {
+		sint64 sm = 0x0FFFFFFFFFFFFFFF;
+		sint64 bg = 0;
+		if(  wolke_t::wolke_sync.get_finish(i).QuadPart > bg  ) bg = wolke_t::wolke_sync.get_finish(i).QuadPart;
+		if(  wolke_t::wolke_sync.get_start(i).QuadPart < sm  ) sm = wolke_t::wolke_sync.get_start(i).QuadPart;
+		wolke_cum+=bg-sm;
+//		wolke_hole_count+=wolke_t::wolke_sync.get_hole(i);
+//		printf(" %I64d %I64d %.3f", wolke_t::wolke_sync.get_start(i).QuadPart, wolke_t::wolke_sync.get_finish(i).QuadPart, (double)(bg-sm)/freqscale  );
+	}
+//	printf("\n");
+*/
+
+	if(next_tickss>10000) {
+		next_tickss-=10000;
+//		QueryPerformanceFrequency(&li1);
+//		const double freqscale = li1.QuadPart/1000.0;
+		//printf("cum: %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu", tickss, syncss, aaa, aaa2, aaa3, bbb, bbb2, ccc, ccc2, ccc3, ddd, eee);
+//		printf("cum: %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu, %lu", tickss, syncss,
+//				gebaeude_t::gebaeude_sync.get_usecs(), senke_t::senke_sync.get_usecs(),
+//				roadsign_t::roadsign_sync.get_usecs(), convoi_t::convoi_sync.get_usecs(),
+//				wolke_t::wolke_sync.get_usecs(), movingobj_t::movingobj_sync.get_usecs(),
+//				stadtauto_t::stadtauto_sync.get_usecs(), fussgaenger_t::fussgaenger_sync.get_usecs(),
+//				ddd, eee);
+		printf("cum: %lu, %lu, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f, %.1f", tickss, syncss,
+				(double)gebaeude_t::gebaeude_sync.get_usecs()/freqscale, (double)senke_t::senke_sync.get_usecs()/freqscale,
+//				(double)gebaeude_cum/freqscale, (double)senke_cum/freqscale,
+				(double)roadsign_t::roadsign_sync.get_usecs()/freqscale, (double)convoi_sync_t::convoi_sync.get_usecs()/freqscale,
+//				(double)roadsign_cum/freqscale, (double)convoi_t::convoi_sync.get_usecs()/freqscale,
+				(double)wolke_t::wolke_sync.get_usecs()/freqscale, (double)movingobj_t::movingobj_sync.get_usecs()/freqscale,
+//				(double)wolke_cum/freqscale, (double)movingobj_t::movingobj_sync.get_usecs()/freqscale,
+				(double)private_car_t::private_car_sync.get_usecs()/freqscale, (double)pedestrian_t::pedestrian_sync.get_usecs()/freqscale,
+				(double)ddd/freqscale, (double)eee/freqscale);
+		printf("       %lu, %lu, %lu, %lu, %lu[%lu], %lu, %lu, %lu", gebaeude_count/syncss, senke_count/syncss, roadsign_count/syncss, convoi_count/syncss, wolke_count/syncss, wolke_hole_count/syncss, movingobj_count/syncss, private_car_count/syncss, pedestrian_count/syncss );
+
+		printf("  geb");
+//		for( int i=0; i<env_t::num_threads; i++){
+//			printf(", [%d]:%u", i, gebaeude_t::gebaeude_sync.get_count(i));
+//		}
+//		printf("  wolke");
+//		for( int i=0; i<env_t::num_threads; i++){
+//			printf(", [%d]:%u", i, wolke_t::wolke_sync.get_count(i));
+//		}
+//		printf("       +%u,+%u,-%u,-%u,-%u: %lu", num_eyec_add, num_eyec_add2, num_eyec_del, num_eyec_del2, num_eyec_del3, sync_eyec_count/syncss );
+//		printf("       +%u,+%u,-%u,-%u,-%u: %lu", num_weyec_add, num_weyec_add2, num_weyec_del, num_weyec_del2, num_weyec_del3, sync_weyec_count/syncss);
+//		printf("       +%u,+%u,-%u,-%u,-%u: %lu", num_add, num_add2, num_del, num_del2, num_del3, sync_count/syncss);
+		printf("\n");
+	}
+}
 	clear_random_mode( SYNC_STEP_RANDOM );
 }
 
@@ -4138,7 +4183,7 @@
 		need_locality_update = (old_locality_factor != koord::locality_factor);
 	}
 	DBG_MESSAGE("karte_t::neuer_monat()","Month (%d/%d) has started", (last_month%12)+1, last_month/12 );
-	DBG_MESSAGE("karte_t::neuer_monat()","sync_step %u objects", sync_list.get_count() );
+//	DBG_MESSAGE("karte_t::neuer_monat()","sync_step %u objects", sync_list.get_count() );
 
 	// this should be done before a map update, since the map may want an update of the way usage
 //	DBG_MESSAGE("karte_t::neuer_monat()","ways");
@@ -4375,12 +4420,29 @@
 
 void karte_t::step()
 {
+static uint64 new_month_sum = 0, new_month_min = 0xFFFFFFFF, new_month_max = 0;
+static uint64 time_calc_sum = 0, time_calc_min = 0xFFFFFFFF, time_calc_max = 0;
+static uint64 pend_season_sum = 0, pend_season_min = 0xFFFFFFFF, pend_season_max = 0;
+static uint64 convoi_sum = 0, convoi_min = 0xFFFFFFFF, convoi_max = 0;
+static uint64 city_sum = 0, city_min = 0xFFFFFFFF, city_max = 0;
+static uint64 fab_sum = 0, fab_min = 0xFFFFFFFF, fab_max = 0;
+static uint64 powerline_sum = 0, powerline_min = 0xFFFFFFFF, powerline_max = 0;
+static uint64 player_sum = 0, player_min = 0xFFFFFFFF, player_max = 0;
+static uint64 halt_sum = 0, halt_min = 0xFFFFFFFF, halt_max = 0;
+static uint64 total_sum = 0;
+static unsigned long tickss = 0;
+static unsigned long next_deltat = 0;
+LARGE_INTEGER li1, li2, li3;
+
+intr_disable();
+
 	DBG_DEBUG4("karte_t::step", "start step");
 	uint32 time = dr_time();
 
 	// calculate delta_t before handling overflow in ticks
 	uint32 delta_t = ticks - last_step_ticks;
 
+QueryPerformanceCounter(&li1);
 	// first: check for new month
 	if(ticks > next_month_ticks) {
 
@@ -4395,7 +4457,13 @@
 		DBG_DEBUG4("karte_t::step", "calling neuer_monat");
 		new_month();
 	}
-
+{
+QueryPerformanceCounter(&li2);
+const uint64 diff = li2.QuadPart - li1.QuadPart;
+new_month_sum += diff;
+if(  diff < new_month_min  )  new_month_min = diff;
+if(  diff > new_month_max  )  new_month_max = diff;
+}
 	DBG_DEBUG4("karte_t::step", "time calculations");
 	if(  step_mode==NORMAL  ) {
 		/* Try to maintain a decent pause, with a step every 170-250 ms (~5,5 simloops/s)
@@ -4450,6 +4518,13 @@
 
 	// to make sure the tick counter will be updated
 	INT_CHECK("karte_t::step");
+{
+QueryPerformanceCounter(&li3);
+const uint64 diff = li3.QuadPart - li2.QuadPart;
+time_calc_sum += diff;
+if(  diff < time_calc_min  )  time_calc_min = diff;
+if(  diff > time_calc_max  )  time_calc_max = diff;
+}
 
 	// check for pending seasons change
 	const bool season_change = pending_season_change > 0;
@@ -4479,16 +4554,31 @@
 
 	// to make sure the tick counter will be updated
 	INT_CHECK("karte_t::step");
+{
+QueryPerformanceCounter(&li2);
+const uint64 diff = li2.QuadPart - li3.QuadPart;
+pend_season_sum += diff;
+if(  diff < pend_season_min  )  pend_season_min = diff;
+if(  diff > pend_season_max  )  pend_season_max = diff;
+}
 
 	DBG_DEBUG4("karte_t::step", "step convois");
 	// since convois will be deleted during stepping, we need to step backwards
 	for (size_t i = convoi_array.get_count(); i-- != 0;) {
 		convoihandle_t cnv = convoi_array[i];
-		cnv->step();
-		if((i&7)==0) {
-			INT_CHECK("simworld 1947");
-		}
+		if( i == 0 ) cnv->step(delta_t);
+		else cnv->step(0);
+//		if((i&7)==0) {
+//			INT_CHECK("simworld 1947");
+//		}
 	}
+{
+QueryPerformanceCounter(&li3);
+const uint64 diff = li3.QuadPart - li2.QuadPart;
+convoi_sum += diff;
+if(  diff < convoi_min  )  convoi_min = diff;
+if(  diff > convoi_max  )  convoi_max = diff;
+}
 
 	// now step all towns (to generate passengers)
 	DBG_DEBUG4("karte_t::step", "step cities");
@@ -4500,12 +4590,26 @@
 
 	// the inhabitants stuff
 	finance_history_month[0][WORLD_CITICENS] = bev;
+{
+QueryPerformanceCounter(&li2);
+const uint64 diff = li2.QuadPart - li3.QuadPart;
+city_sum += diff;
+if(  diff < city_min  )  city_min = diff;
+if(  diff > city_max  )  city_max = diff;
+}
 
 	DBG_DEBUG4("karte_t::step", "step factories");
 	FOR(slist_tpl<fabrik_t*>, const f, fab_list) {
 		f->step(delta_t);
 	}
 	finance_history_year[0][WORLD_FACTORIES] = finance_history_month[0][WORLD_FACTORIES] = fab_list.get_count();
+{
+QueryPerformanceCounter(&li3);
+const uint64 diff = li3.QuadPart - li2.QuadPart;
+fab_sum += diff;
+if(  diff < fab_min  )  fab_min = diff;
+if(  diff > fab_max  )  fab_max = diff;
+}
 
 	// step powerlines - required order: pumpe, senke, then powernet
 	DBG_DEBUG4("karte_t::step", "step poweline stuff");
@@ -4513,6 +4617,14 @@
 	senke_t::step_all( delta_t );
 	powernet_t::step_all( delta_t );
 
+{
+QueryPerformanceCounter(&li2);
+const uint64 diff = li2.QuadPart - li3.QuadPart;
+powerline_sum += diff;
+if(  diff < powerline_min  )  powerline_min = diff;
+if(  diff > powerline_max  )  powerline_max = diff;
+}
+
 	DBG_DEBUG4("karte_t::step", "step players");
 	// then step all players
 	for(  int i=0;  i<MAX_PLAYER_COUNT;  i++  ) {
@@ -4520,12 +4632,26 @@
 			players[i]->step();
 		}
 	}
+{
+QueryPerformanceCounter(&li3);
+const uint64 diff = li3.QuadPart - li2.QuadPart;
+player_sum += diff;
+if(  diff < player_min  )  player_min = diff;
+if(  diff > player_max  )  player_max = diff;
+}
 
 	DBG_DEBUG4("karte_t::step", "step halts");
 	haltestelle_t::step_all();
 
 	// ok, next step
 	INT_CHECK("simworld 1975");
+{
+QueryPerformanceCounter(&li2);
+const uint64 diff = li2.QuadPart - li3.QuadPart;
+halt_sum += diff;
+if(  diff < halt_min  )  halt_min = diff;
+if(  diff > halt_max  )  halt_max = diff;
+}
 
 	if((steps%8)==0) {
 		DBG_DEBUG4("karte_t::step", "checkmidi");
@@ -4563,6 +4689,37 @@
 	if(  get_scenario()->is_scripted() ) {
 		get_scenario()->step();
 	}
+
+QueryPerformanceCounter(&li3);
+total_sum += li3.QuadPart - li1.QuadPart;
+
+tickss += delta_t;
+next_deltat += delta_t;
+if( next_deltat > 10000 ) {
+	next_deltat -= 10000;
+
+	QueryPerformanceFrequency(&li1);
+	const double freqscale = li1.QuadPart/1000.0;
+
+	printf("step: %lu, %ld, mnth:%.1f/%.1f/%.1f, time:%.1f/%.1f/%.1f, pend:%.1f/%.1f/%.1f, cnv:%.1f/%.1f/%.1f, city:%.1f/%.1f/%.1f, fab:%.1f/%.1f/%.1f, pwr:%.1f/%.1f/%.1f, plr:%.1f/%.1f/%.1f, hlt:%.1f/%.1f/%.1f, tot:%.1f\n", tickss, steps,
+		(double) new_month_min/freqscale, (double)new_month_sum/freqscale, (double) new_month_max/freqscale,
+		(double) time_calc_min/freqscale, (double)time_calc_sum/freqscale, (double) time_calc_max/freqscale,
+		(double) pend_season_min/freqscale, (double)pend_season_sum/freqscale, (double) pend_season_max/freqscale,
+		(double) convoi_min/freqscale, (double)convoi_sum/freqscale, (double) convoi_max/freqscale,
+		(double) city_min/freqscale, (double)city_sum/freqscale, (double) city_max/freqscale,
+		(double) fab_min/freqscale, (double)fab_sum/freqscale, (double) fab_max/freqscale,
+		(double) powerline_min/freqscale, (double)powerline_sum/freqscale, (double) powerline_max/freqscale,
+		(double) player_min/freqscale, (double)player_sum/freqscale, (double) player_max/freqscale,
+		(double) halt_min/freqscale, (double)halt_sum/freqscale, (double) halt_max/freqscale,
+		(double)total_sum/freqscale
+	);
+
+}
+
+intr_enable();
+
+
+
 	DBG_DEBUG4("karte_t::step", "end");
 }
 
@@ -5824,7 +5981,7 @@
 			}
 		}
 		else {
-			sync_add( cnv );
+			cnv->get_cnv_sync()->sync_add_self();
 		}
 		if(  (convoi_array.get_count()&7) == 0  ) {
 			ls.set_progress( get_size().y+(get_size().y*convoi_array.get_count())/(2*max_convoi)+128 );
Index: simworld.h
===================================================================
--- simworld.h	(revision 7507)
+++ simworld.h	(working copy)
@@ -91,6 +91,7 @@
 {
 	friend karte_t* world();  // to access the single instance
 	friend class karte_ptr_t; // to access the single instance
+//	friend class sync_steppable;
 
 	static karte_t* world; ///< static single instance
 
@@ -267,61 +268,6 @@
 	uint8 height_to_climate[32];
 
 	/**
-	 * These objects will be added to the sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_add_list;
-
-	/**
-	 * These objects will be removed from the sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_remove_list;
-
-	/**
-	 * Sync list.
-	 */
-#ifndef SYNC_VECTOR
-	slist_tpl<sync_steppable *> sync_list;
-#else
-	vector_tpl<sync_steppable *> sync_list;
-#endif
-
-	/**
-	 * These objects will be added to the eyecandy sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_eyecandy_add_list;
-
-	/**
-	 * These objects will be removed to the eyecandy sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_eyecandy_remove_list;
-
-	/**
-	 * Sync list for eyecandy objects.
-	 */
-	ptrhashtable_tpl<sync_steppable *,sync_steppable *> sync_eyecandy_list;
-
-	/**
-	 * These objects will be added to the eyecandy way objects (smoke) sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_way_eyecandy_add_list;
-
-	/**
-	 * These objects will be removed to the eyecandy way objects (smoke) sync_list (but before next sync step, so they do not interfere!)
-	 */
-	slist_tpl<sync_steppable *> sync_way_eyecandy_remove_list;
-
-	/**
-	 * Sync list for eyecandy way objects (smoke).
-	 */
-#ifdef SYNC_WAY_HASHTABLE
-	ptrhashtable_tpl<sync_steppable *,sync_steppable *> sync_way_eyecandy_list;
-#elif SYNC_WAY_LIST
-	slist_tpl<sync_steppable *> sync_way_eyecandy_list;
-#else
-	vector_tpl<sync_steppable *> sync_way_eyecandy_list;
-#endif
-
-	/**
 	 * Array containing the convois.
 	 */
 	vector_tpl<convoihandle_t> convoi_array;
Index: tpl/vector_tpl.h
===================================================================
--- tpl/vector_tpl.h	(revision 7507)
+++ tpl/vector_tpl.h	(working copy)
@@ -251,6 +251,19 @@
 		const_iterator begin() const { return data; }
 		const_iterator end() const { return data + count; }
 
+	iterator swap_erase(iterator pos)
+	{
+		if(  pos == end()  ) {
+			--count;
+			return pos;
+		}
+		else {
+			*pos = back();
+			--count;
+			return pos;
+		}
+	}
+
 		/** Get the number of elements in the vector */
 		uint32 get_count() const { return count; }
 
Index: vehicle/movingobj.cc
===================================================================
--- vehicle/movingobj.cc	(revision 7507)
+++ vehicle/movingobj.cc	(working copy)
@@ -112,8 +112,24 @@
 
 /******************************* end of static ******************************************/
 
+sync_steppable_vector_t movingobj_t::movingobj_sync;
+sync_step_random_t movingobj_t::movingobj_rand;
 
 
+template <typename movingobj_t> nodelist_node_t* freelist_tpl<movingobj_t>::chunk_list = NULL;
+template <typename movingobj_t> nodelist_node_t* freelist_tpl<movingobj_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 // recalculates only the seasonal image
 void movingobj_t::calc_image()
 {
@@ -154,7 +170,7 @@
 {
 	rdwr(file);
 	if(get_besch()) {
-		welt->sync_add( this );
+		movingobj_sync.sync_add(this);
 	}
 }
 
@@ -162,17 +178,17 @@
 movingobj_t::movingobj_t(koord3d pos, const groundobj_besch_t *b ) : vehicle_base_t(pos)
 {
 	movingobjtype = movingobj_typen.index_of(b);
-	weg_next = 0;
+	weg_next = get_besch()->get_speed() * simrand(6144); // spread out the hops
 	timetochange = 0;	// will do random direct change anyway during next step
 	direction = calc_set_direction( koord3d(0,0,0), koord3d(koord::west,0) );
 	calc_image();
-	welt->sync_add( this );
+	movingobj_sync.sync_add(this);
 }
 
 
 movingobj_t::~movingobj_t()
 {
-	welt->sync_remove( this );
+	movingobj_sync.sync_remove(this);
 }
 
 
@@ -233,11 +249,10 @@
 
 		use_calc_height = true;
 	}
-	weg_next = 0;
+	weg_next = get_besch()->get_speed() * simrand(6144); // spread out the hops
 }
 
 
-
 /**
  * Open a new observation window for the object.
  * @author Hj. Malthaner
@@ -250,7 +265,6 @@
 }
 
 
-
 /**
  * @return Einen Beschreibungsstring für das Objekt, der z.B. in einem
  * Beobachtungsfenster angezeigt wird.
@@ -273,26 +287,22 @@
 }
 
 
-
 void movingobj_t::cleanup(player_t *player)
 {
 	player_t::book_construction_costs(player, -get_besch()->get_preis(), get_pos().get_2d(), ignore_wt);
 	mark_image_dirty( get_image(), 0 );
-	welt->sync_remove( this );
+	movingobj_sync.sync_remove(this);
 }
 
 
-
-
-bool movingobj_t::sync_step(uint32 delta_t)
+int movingobj_t::sync_step(const uint32 delta_t)
 {
 	weg_next += get_besch()->get_speed() * delta_t;
 	weg_next -= do_drive( weg_next );
-	return true;
+	return SYNC_OK;
 }
 
 
-
 /* essential to find out about next step
  * returns true, if we can go here
  * (identical to fahrer)
@@ -344,7 +354,6 @@
 }
 
 
-
 grund_t* movingobj_t::hop_check()
 {
 	/* since we may be going diagonal without any road
@@ -373,7 +382,7 @@
 
 	if (timetochange==0) {
 		// direction change needed
-		timetochange = simrand(speed_to_kmh(get_besch()->get_speed())/3);
+		timetochange = movingobj_rand.get_rand(speed_to_kmh(get_besch()->get_speed())/3);
 		const koord pos=pos_next.get_2d();
 		const grund_t *to[4];
 		uint8 until=0;
@@ -391,7 +400,7 @@
 		}
 		else {
 			// else prepare for direction change
-			const grund_t *next = to[simrand(until)];
+			const grund_t *next = to[movingobj_rand.get_rand(until)];
 			pos_next_next = next->get_pos();
 		}
 	}
@@ -403,7 +412,6 @@
 }
 
 
-
 void movingobj_t::hop(grund_t* gr)
 {
 	leave_tile();
@@ -430,15 +438,26 @@
 }
 
 
+void *movingobj_t::operator new(size_t )
+{
+	return freelist_tpl<movingobj_t>::gimme_node(sizeof(movingobj_t));
+}
 
-void *movingobj_t::operator new(size_t /*s*/)
+
+void movingobj_t::operator delete(void *p)
 {
+	freelist_tpl<movingobj_t>::putback_node(sizeof(movingobj_t),p);
+}
+
+
+//void *movingobj_t::operator new(size_t /*s*/)
+/*{
 	return freelist_t::gimme_node(sizeof(movingobj_t));
 }
 
 
-
 void movingobj_t::operator delete(void *p)
 {
 	freelist_t::putback_node(sizeof(movingobj_t),p);
 }
+*/
Index: vehicle/movingobj.h
===================================================================
--- vehicle/movingobj.h	(revision 7507)
+++ vehicle/movingobj.h	(working copy)
@@ -47,6 +47,8 @@
 	void calc_image();
 
 public:
+	static sync_steppable_vector_t movingobj_sync;
+	static sync_step_random_t movingobj_rand;
 	static bool register_besch(groundobj_besch_t *besch);
 	static bool alles_geladen();
 
@@ -56,7 +58,7 @@
 	movingobj_t(koord3d pos, const groundobj_besch_t *);
 	~movingobj_t();
 
-	bool sync_step(uint32 delta_t);
+	int sync_step(const uint32 delta_t);
 
 	// prissi: always free
 	virtual bool check_next_tile(const grund_t *) const;
Index: vehicle/overtaker.h
===================================================================
--- vehicle/overtaker.h	(revision 7507)
+++ vehicle/overtaker.h	(working copy)
@@ -19,6 +19,8 @@
 class overtaker_t
 {
 protected:
+	sint32 max_power_speed; // max achievable speed at current power/weight
+
 	/* if >0, number of tiles for overtaking left
 	 * if <0, number of tiles that is prevented being overtaken
 	 *        (other vehicle is overtaking us)
@@ -26,9 +28,8 @@
 	sint8 tiles_overtaking;
 	sint8 diff;
 
-	sint32 max_power_speed; // max achievable speed at current power/weight
 public:
-	overtaker_t():tiles_overtaking(0), diff(0), max_power_speed(SPEED_UNLIMITED) {}
+	overtaker_t() : max_power_speed(SPEED_UNLIMITED), tiles_overtaking(0), diff(0) {}
 	virtual ~overtaker_t() {}
 
 	bool is_overtaking() const { return diff < 0; }
Index: vehicle/simpeople.cc
===================================================================
--- vehicle/simpeople.cc	(revision 7507)
+++ vehicle/simpeople.cc	(working copy)
@@ -23,7 +23,25 @@
 static weighted_vector_tpl<const fussgaenger_besch_t*> liste;
 stringhashtable_tpl<const fussgaenger_besch_t *> pedestrian_t::table;
 
+sync_steppable_vector_copy_t pedestrian_t::pedestrian_sync;
+//sync_steppable_vector_t fussgaenger_t::fussgaenger_sync;
+sync_step_random_t pedestrian_t::pedestrian_rand;
 
+
+template <typename pedestrian_t> nodelist_node_t* freelist_tpl<pedestrian_t>::chunk_list = NULL;
+template <typename pedestrian_t> nodelist_node_t* freelist_tpl<pedestrian_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 static bool compare_fussgaenger_besch(const fussgaenger_besch_t* a, const fussgaenger_besch_t* b)
 {
 	// sort pedestrian objects descriptors by their name
@@ -66,11 +84,12 @@
 {
 	rdwr(file);
 	if(besch) {
-		welt->sync_add(this);
+		pedestrian_sync.sync_add(this);
 	}
 }
 
 
+// simrand ok here, new peds never created in sync_step
 pedestrian_t::pedestrian_t(grund_t *gr) :
 	road_user_t(gr, simrand(65535)),
 	besch(pick_any_weighted(liste))
@@ -83,7 +102,7 @@
 pedestrian_t::~pedestrian_t()
 {
 	if(  time_to_life>0  ) {
-		welt->sync_remove( this );
+		pedestrian_sync.sync_remove(this);
 	}
 }
 
@@ -143,9 +162,10 @@
 					fg->calc_height(bd);
 					if (i > 0) {
 						// walk a little
-						fg->sync_step( (i & 3) * 64 * 24);
+//						fg->sync_step( (i & 3) * 64 * 24);
+						fg->scatter( (i & 3) * 64 * 24);
 					}
-					welt->sync_add(fg);
+					fg->sync_add_self();
 					anzahl--;
 				}
 				else {
@@ -162,16 +182,22 @@
 }
 
 
-bool pedestrian_t::sync_step(uint32 delta_t)
+void pedestrian_t::scatter(const uint32 dist)
 {
+	time_to_life -= dist;
+	weg_next += 128 * dist;
+}
+
+
+int pedestrian_t::sync_step(const uint32 delta_t)
+{
 	time_to_life -= delta_t;
 
 	if (time_to_life>0) {
-		weg_next += 128*delta_t;
+		weg_next += 128 * delta_t;
 		weg_next -= do_drive( weg_next );
-		return time_to_life>0;
 	}
-	return false;
+	return time_to_life>0 ? SYNC_OK : SYNC_REM_DEL;
 }
 
 
@@ -210,7 +236,7 @@
 	// all possible directions
 	ribi_t::ribi ribi = weg->get_ribi_unmasked() & (~gegenrichtung);
 	// randomized offset
-	const uint8 offset = (ribi > 0  &&  ribi_t::ist_einfach(ribi)) ? 0 : simrand(4);
+	const uint8 offset = (ribi > 0  &&  ribi_t::ist_einfach(ribi)) ? 0 : pedestrian_rand.get_rand(4);
 
 	for(uint r = 0; r < 4; r++) {
 		ribi_t::ribi const test_ribi = ribi_t::nsow[ (r+offset) & 3];
@@ -235,3 +261,16 @@
 		time_to_life = 0;
 	}
 }
+
+
+void *pedestrian_t::operator new(size_t )
+{
+	return freelist_tpl<pedestrian_t>::gimme_node(sizeof(pedestrian_t));
+}
+
+
+void pedestrian_t::operator delete(void *p)
+{
+	freelist_tpl<pedestrian_t>::putback_node(sizeof(pedestrian_t),p);
+}
+
Index: vehicle/simpeople.h
===================================================================
--- vehicle/simpeople.h	(revision 7507)
+++ vehicle/simpeople.h	(working copy)
@@ -11,7 +11,7 @@
  * @author Hj. Malthaner
  * @see road_user_t
  */
-class pedestrian_t : public road_user_t
+class pedestrian_t : public road_user_t, public sync_steppable
 {
 private:
 	static stringhashtable_tpl<const fussgaenger_besch_t *> table;
@@ -40,8 +40,15 @@
 	const char *get_name() const {return "Fussgaenger";}
 	typ get_typ() const { return pedestrian; }
 
-	bool sync_step(uint32 delta_t);
+	static sync_steppable_vector_copy_t pedestrian_sync;
+//	static sync_steppable_vector_t pedestrian_sync;
+	static sync_step_random_t pedestrian_rand;
+	int sync_step(const uint32 delta_t);
 
+	void sync_add_self() { pedestrian_sync.sync_add(this); }
+
+	void scatter(const uint32 dist);
+
 	// prissi: always free
 	virtual bool ist_weg_frei() { return true; }
 	virtual grund_t* hop_check();
@@ -52,6 +59,9 @@
 	static bool alles_geladen();
 
 	static void generate_pedestrians_at(koord3d k, int &anzahl);
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 #endif
Index: vehicle/simroadtraffic.cc
===================================================================
--- vehicle/simroadtraffic.cc	(revision 7507)
+++ vehicle/simroadtraffic.cc	(working copy)
@@ -147,7 +147,9 @@
 		sint32 l;
 		file->rdwr_long(l);
 		file->rdwr_long(l);
-		file->rdwr_long(weg_next);
+		uint32 jjj = weg_next;
+		file->rdwr_long(jjj);
+		weg_next=(uint16)jjj;
 		file->rdwr_long(l);
 		dx = (sint8)l;
 		file->rdwr_long(l);
@@ -161,7 +163,10 @@
 			sint32 dummy32;
 			file->rdwr_long(dummy32);
 		}
-		file->rdwr_long(weg_next);
+//////////////
+		uint32 jjj = weg_next;
+		file->rdwr_long(jjj);
+		weg_next=(uint16)jjj;
 		if(file->get_version()<99018) {
 			file->rdwr_byte(dx);
 			file->rdwr_byte(dy);
@@ -231,7 +236,25 @@
 /**********************************************************************************************************************/
 /* statsauto_t (city cars) from here on */
 
+//sync_steppable_vector_t private_car_t::private_car_sync;
+sync_steppable_vector_copy_t private_car_t::private_car_sync;
+sync_step_random_t private_car_t::private_car_rand;
 
+
+template <typename private_car_t> nodelist_node_t* freelist_tpl<private_car_t>::chunk_list = NULL;
+template <typename private_car_t> nodelist_node_t* freelist_tpl<private_car_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
+
+
 static weighted_vector_tpl<const stadtauto_besch_t*> liste_timeline;
 stringhashtable_tpl<const stadtauto_besch_t *> private_car_t::table;
 
@@ -315,7 +338,7 @@
 
 	// just to be sure we are removed from this list!
 	if(time_to_life>0) {
-		welt->sync_remove(this);
+		private_car_sync.sync_remove(this);
 	}
 	welt->buche( -1, karte_t::WORLD_CITYCARS );
 }
@@ -327,7 +350,7 @@
 	rdwr(file);
 	ms_traffic_jam = 0;
 	if(besch) {
-		welt->sync_add(this);
+		private_car_sync.sync_add(this);
 	}
 	welt->buche( +1, karte_t::WORLD_CITYCARS );
 }
@@ -341,6 +364,7 @@
 	time_to_life = welt->get_settings().get_stadtauto_duration() << welt->ticks_per_world_month_shift;
 	current_speed = 48;
 	ms_traffic_jam = 0;
+	private_car_sync.sync_add(this);
 #ifdef DESTINATION_CITYCARS
 	this->target = target;
 #else
@@ -351,11 +375,11 @@
 }
 
 
-bool private_car_t::sync_step(uint32 delta_t)
+int private_car_t::sync_step(const uint32 delta_t)
 {
 	time_to_life -= delta_t;
 	if(  time_to_life<=0  ) {
-		return false;
+		return SYNC_REM_DEL;
 	}
 
 	if(  current_speed==0  ) {
@@ -390,7 +414,7 @@
 		}
 	}
 
-	return time_to_life>0;
+	return time_to_life>0 ? SYNC_OK : SYNC_REM_DEL;
 }
 
 
@@ -533,7 +557,7 @@
 								// otherwise the overtaken car would stop for us ...
 								if(  road_vehicle_t const* const car = obj_cast<road_vehicle_t>(dt)  ) {
 									convoi_t* const ocnv = car->get_convoi();
-									if(  ocnv==NULL  ||  !can_overtake( ocnv, (ocnv->get_state()==convoi_t::LOADING ? 0 : over->get_max_power_speed()), ocnv->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps())  ) {
+									if(  ocnv==NULL  ||  !can_overtake( ocnv->get_cnv_sync(), (ocnv->is_loading() ? 0 : over->get_max_power_speed()), ocnv->get_cnv_sync()->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps())  ) {
 										frei = false;
 									}
 								} else if(  private_car_t* const caut = obj_cast<private_car_t>(dt)  ) {
@@ -680,13 +704,13 @@
 #ifdef DESTINATION_CITYCARS
 		static weighted_vector_tpl<koord3d> posliste(4);
 		posliste.clear();
-		const uint8 offset = ribi_t::ist_einfach(ribi) ? 0 : simrand(4);
+		const uint8 offset = ribi_t::ist_einfach(ribi) ? 0 : stadtauto_rand.get_rand(4);
 		for(uint8 r = 0; r < 4; r++) {
 			if(  get_pos().get_2d()==koord::nsow[r]+pos_next.get_2d()  ) {
 				continue;
 			}
 #else
-		const uint8 offset = ribi_t::ist_einfach(ribi) ? 0 : simrand(4);
+		const uint8 offset = ribi_t::ist_einfach(ribi) ? 0 : private_car_rand.get_rand(4);
 		for(uint8 i = 0; i < 4; i++) {
 			const uint8 r = (i+offset)&3;
 #endif
@@ -1116,3 +1140,16 @@
 
 	return true;
 }
+
+
+void *private_car_t::operator new(size_t )
+{
+	return freelist_tpl<private_car_t>::gimme_node(sizeof(private_car_t));
+}
+
+
+void private_car_t::operator delete(void *p)
+{
+	freelist_tpl<private_car_t>::putback_node(sizeof(private_car_t),p);
+}
+
Index: vehicle/simroadtraffic.h
===================================================================
--- vehicle/simroadtraffic.h	(revision 7507)
+++ vehicle/simroadtraffic.h	(working copy)
@@ -25,14 +25,15 @@
  * Base class for traffic participants with random movement
  * @author Hj. Malthaner
  */
-class road_user_t : public vehicle_base_t, public sync_steppable
+class road_user_t : public vehicle_base_t
 {
 protected:
 	/**
 	 * Distance count
 	 * @author Hj. Malthaner
 	 */
-	uint32 weg_next;
+//	uint32 weg_next;
+	uint16 weg_next;
 
 	/* ms until destruction
 	 */
@@ -72,7 +73,7 @@
 };
 
 
-class private_car_t : public road_user_t, public overtaker_t
+class private_car_t : public road_user_t, public overtaker_t, public sync_steppable
 {
 private:
 	static stringhashtable_tpl<const stadtauto_besch_t *> table;
@@ -113,7 +114,10 @@
 
 	const stadtauto_besch_t *get_besch() const { return besch; }
 
-	bool sync_step(uint32 delta_t);
+//	static sync_steppable_vector_t private_car_sync;
+	static sync_steppable_vector_copy_t private_car_sync;
+	static sync_step_random_t private_car_rand;
+	int sync_step(const uint32 delta_t);
 
 	void hop(grund_t *gr);
 	bool ist_weg_frei(grund_t *gr);
@@ -154,6 +158,9 @@
 
 	// Overtaking for city cars
 	virtual bool can_overtake(overtaker_t *other_overtaker, sint32 other_speed, sint16 steps_other);
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 #endif
Index: vehicle/simvehicle.cc
===================================================================
--- vehicle/simvehicle.cc	(revision 7507)
+++ vehicle/simvehicle.cc	(working copy)
@@ -994,7 +994,7 @@
 		if(check_for_finish) {
 			// so we are there yet?
 			cnv->ziel_erreicht();
-			if(cnv->get_state()==convoi_t::INITIAL) {
+			if(  cnv->in_depot()  ) {
 				// to avoid crashes with airplanes
 				use_calc_height = false;
 			}
@@ -1227,19 +1227,31 @@
 void vehicle_t::make_smoke() const
 {
 	// does it smoke at all?
-	if(  smoke  &&  besch->get_rauch()  ) {
-		// Hajo: only produce smoke when heavily accelerating or steam engine
-		if(  cnv->get_akt_speed() < (sint32)((cnv->get_speed_limit() * 7u) >> 3)  ||  besch->get_engine_type() == vehikel_besch_t::steam  ) {
-			grund_t* const gr = welt->lookup( get_pos() );
-			if(  gr  ) {
-				wolke_t* const abgas =  new wolke_t( get_pos(), get_xoff() + ((dx * (sint16)((uint16)steps * OBJECT_OFFSET_STEPS)) >> 8), get_yoff() + ((dy * (sint16)((uint16)steps * OBJECT_OFFSET_STEPS)) >> 8) + get_hoff(), besch->get_rauch() );
-				if(  !gr->obj_add( abgas )  ) {
+///
+/// *********** OLD smoke routine to create more smoke for profiling purposed. Revert to new routine when done ******** ///
+///
+	if(smoke  &&  besch->get_rauch()) {
+		bool smokee = besch->get_engine_type()==vehikel_besch_t::steam;
+
+		if(!smokee) {
+			// Hajo: only produce smoke when heavily accelerating
+			//       or steam engine
+			sint32 akt_speed = kmh_to_speed(besch->get_geschw());
+			if(akt_speed > speed_limit) {
+				akt_speed = speed_limit;
+			}
+
+			smokee = (cnv->get_akt_speed() < (sint32)((akt_speed*7u)>>3));
+		}
+
+		if(smokee) {
+			grund_t * gr = welt->lookup( get_pos() );
+			if(gr) {
+				wolke_t *abgas =  new wolke_t( get_pos(), get_xoff()+((dx*(sint16)((uint16)steps*OBJECT_OFFSET_STEPS))>>8), get_yoff()+((dy*(sint16)((uint16)steps*OBJECT_OFFSET_STEPS))>>8)+get_hoff(), besch->get_rauch() );
+				if(  !gr->obj_add(abgas)  ) {
 					abgas->set_flag( obj_t::not_on_map );
-					delete abgas;
-				}
-				else {
-					welt->sync_way_eyecandy_add( abgas );
-				}
+ 					delete abgas;
+ 				}
 			}
 		}
 	}
@@ -1798,7 +1810,20 @@
 }
 
 
+template <typename vehikel_basis_t> nodelist_node_t* freelist_tpl<vehikel_basis_t>::chunk_list = NULL;
+template <typename vehikel_basis_t> nodelist_node_t* freelist_tpl<vehikel_basis_t>::all_lists[NUM_LIST] = {
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL, NULL, NULL, NULL,
+	NULL
+};
 
+
 road_vehicle_t::road_vehicle_t(koord3d pos, const vehikel_besch_t* besch, player_t* player_, convoi_t* cn) :
 	vehicle_t(pos, besch, player_)
 {
@@ -1966,11 +1991,11 @@
 
 	// eventually shift position to take care of overtaking
 	if(cnv) {
-		if(  cnv->is_overtaking()  ) {
+		if(  cnv->get_cnv_sync()->is_overtaking()  ) {
 			xoff += tile_raster_scale_x(overtaking_base_offsets[ribi_t::get_dir(get_direction())][0], raster_width);
 			yoff += tile_raster_scale_x(overtaking_base_offsets[ribi_t::get_dir(get_direction())][1], raster_width);
 		}
-		else if(  cnv->is_overtaken()  ) {
+		else if(  cnv->get_cnv_sync()->is_overtaken()  ) {
 			xoff -= tile_raster_scale_x(overtaking_base_offsets[ribi_t::get_dir(get_direction())][0], raster_width)/5;
 			yoff -= tile_raster_scale_x(overtaking_base_offsets[ribi_t::get_dir(get_direction())][1], raster_width)/5;
 		}
@@ -2109,7 +2134,7 @@
 		uint32 test_index = route_index + 1u;
 
 		// way should be clear for overtaking: we checked previously
-		if(  !cnv->is_overtaking()  ) {
+		if(  !cnv->get_cnv_sync()->is_overtaking()  ) {
 			// calculate new direction
 			route_t const& r = *cnv->get_route();
 			koord3d next = route_index < r.get_count() - 1u ? r.position_bei(route_index + 1u) : pos_next;
@@ -2217,7 +2242,7 @@
 			if(  obj->is_stuck()  ) {
 				// end of traffic jam, but no stuck message, because previous vehicle is stuck too
 				restart_speed = 0;
-				cnv->set_tiles_overtaking(0);
+				cnv->get_cnv_sync()->set_tiles_overtaking(0);
 				cnv->reset_waiting();
 			}
 			else {
@@ -2232,12 +2257,12 @@
 						// not overtaking/being overtake: we need to make a more thought test!
 						if(  road_vehicle_t const* const car = obj_cast<road_vehicle_t>(obj)  ) {
 							convoi_t* const ocnv = car->get_convoi();
-							if(  cnv->can_overtake( ocnv, (ocnv->get_state()==convoi_t::LOADING ? 0 : over->get_max_power_speed()), ocnv->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps())  ) {
+							if(  cnv->get_cnv_sync()->can_overtake( ocnv->get_cnv_sync(), (ocnv->is_loading() ? 0 : over->get_max_power_speed()), ocnv->get_cnv_sync()->get_length_in_steps()+ocnv->get_vehikel(0)->get_steps())  ) {
 								return true;
 							}
 						}
 						else if(  private_car_t* const caut = obj_cast<private_car_t>(obj)  ) {
-							if(  cnv->can_overtake(caut, caut->get_besch()->get_geschw(), VEHICLE_STEPS_PER_TILE)  ) {
+							if(  cnv->get_cnv_sync()->can_overtake(caut, caut->get_besch()->get_geschw(), VEHICLE_STEPS_PER_TILE)  ) {
 								return true;
 							}
 						}
@@ -2245,7 +2270,7 @@
 				}
 				// we have to wait ...
 				restart_speed = (cnv->get_akt_speed()*3)/4;
-				cnv->set_tiles_overtaking(0);
+				cnv->get_cnv_sync()->set_tiles_overtaking(0);
 			}
 		}
 
@@ -2258,7 +2283,7 @@
 
 overtaker_t* road_vehicle_t::get_overtaker()
 {
-	return cnv;
+	return cnv->get_cnv_sync();;
 }
 
 
@@ -2271,7 +2296,7 @@
 	str->book(cargo, WAY_STAT_GOODS);
 	if (leading)  {
 		str->book(1, WAY_STAT_CONVOIS);
-		cnv->update_tiles_overtaking();
+		cnv->get_cnv_sync()->update_tiles_overtaking();
 	}
 	drives_on_left = welt->get_settings().is_drive_left();	// reset driving settings
 }
@@ -2313,7 +2338,21 @@
 }
 
 
+void *road_vehicle_t::operator new(size_t )
+{
+	return freelist_tpl<vehicle_base_t>::gimme_node(sizeof(road_vehicle_t));
+}
+
+
+void road_vehicle_t::operator delete(void *p)
+{
+	freelist_tpl<vehicle_base_t>::putback_node(sizeof(road_vehicle_t),p);
+}
+
+
 /* from now on rail vehicles (and other vehicles using blocks) */
+
+
 rail_vehicle_t::rail_vehicle_t(loadsave_t *file, bool is_first, bool is_last) : vehicle_t()
 {
 	vehicle_t::rdwr_from_convoi(file);
@@ -2402,14 +2441,14 @@
 				assert(c!=NULL);
 				// eventually search new route
 				route_t const& r = *c->get_route();
-				if(  (r.get_count()<=route_index  ||  r.empty()  ||  get_pos()==r.back())  &&  c->get_state()!=convoi_t::INITIAL  &&  c->get_state()!=convoi_t::LOADING  &&  c->get_state()!=convoi_t::SELF_DESTRUCT  ) {
+				if(  (r.get_count()<=route_index  ||  r.empty()  ||  get_pos()==r.back())  &&  c->get_state() != convoi_t::INITIAL  &&  c->get_state() != convoi_t::LOADING  &&  c->get_state() != convoi_t::SELF_DESTRUCT  ) {
 					check_for_finish = true;
 					dbg->warning("rail_vehicle_t::set_convoi()", "convoi %i had a too high route index! (%i of max %i)", c->self.get_id(), route_index, r.get_count() - 1);
 				}
 				// set default next stop index
 				c->set_next_stop_index( max(route_index,1)-1 );
 				// need to reserve new route?
-				if(  !check_for_finish  &&  c->get_state()!=convoi_t::SELF_DESTRUCT  &&  (c->get_state()==convoi_t::DRIVING  ||  c->get_state()>=convoi_t::LEAVING_DEPOT)  ) {
+				if(  !check_for_finish  &&  c->get_state() != convoi_t::SELF_DESTRUCT  &&  (c->get_state() == convoi_t::DRIVING  ||  c->get_state() >= convoi_t::LEAVING_DEPOT)  ) {
 					long num_index = cnv==(convoi_t *)1 ? 1001 : 0; 	// only during loadtype: cnv==1 indicates, that the convoi did reserve a stop
 					uint16 next_signal, next_crossing;
 					cnv = c;
@@ -2830,7 +2869,7 @@
 {
 	assert(leading);
 	uint16 next_signal, next_crossing;
-	if(  cnv->get_state()==convoi_t::CAN_START  ||  cnv->get_state()==convoi_t::CAN_START_ONE_MONTH  ||  cnv->get_state()==convoi_t::CAN_START_TWO_MONTHS  ) {
+	if(  cnv->can_start()  ) {
 		// reserve first block at the start until the next signal
 		grund_t *gr_current = welt->lookup( get_pos() );
 		weg_t *w = gr_current ? gr_current->get_weg(get_waytype()) : NULL;
@@ -3095,6 +3134,18 @@
 }
 
 
+void *rail_vehicle_t::operator new(size_t )
+{
+	return freelist_tpl<vehicle_base_t>::gimme_node(sizeof(rail_vehicle_t));
+}
+
+
+void rail_vehicle_t::operator delete(void *p)
+{
+	freelist_tpl<vehicle_base_t>::putback_node(sizeof(rail_vehicle_t),p);
+}
+
+
 schedule_t * rail_vehicle_t::generate_new_schedule() const
 {
 	return besch->get_waytype()==tram_wt ? new tramfahrplan_t() : new zugfahrplan_t();
@@ -3245,6 +3296,18 @@
 }
 
 
+void *water_vehicle_t::operator new(size_t )
+{
+	return freelist_tpl<vehicle_base_t>::gimme_node(sizeof(water_vehicle_t));
+}
+
+
+void water_vehicle_t::operator delete(void *p)
+{
+	freelist_tpl<vehicle_base_t>::putback_node(sizeof(water_vehicle_t),p);
+}
+
+
 /**** from here on planes ***/
 
 
Index: vehicle/simvehicle.h
===================================================================
--- vehicle/simvehicle.h	(revision 7507)
+++ vehicle/simvehicle.h	(working copy)
@@ -51,23 +51,27 @@
 	// [0]=xoff [1]=yoff
 	static sint8 overtaking_base_offsets[8][2];
 
-	/**
-	 * Actual travel direction in screen coordinates
-	 * @author Hj. Malthaner
-	 */
-	ribi_t::ribi direction;
-
 	// true on slope (make calc_height much faster)
 	uint8 use_calc_height:1;
 
 	// if true, use offsets to emulate driving on other side
 	uint8 drives_on_left:1;
 
+	/**
+	 * Offsets for uphill/downhill.
+	 * Have to be multiplied with -TILE_HEIGHT_STEP/2.
+	 * To obtain real z-offset, interpolate using steps, steps_next.
+	 */
+	uint8 zoff_start:4, zoff_end:4;
+
 	sint8 dx, dy;
 
 	// number of steps in this tile (255 per tile)
 	uint8 steps, steps_next;
 
+	// cached image
+	image_id image;
+
 	/**
 	 * Next position on our path
 	 * @author Hj. Malthaner
@@ -75,15 +79,11 @@
 	koord3d pos_next;
 
 	/**
-	 * Offsets for uphill/downhill.
-	 * Have to be multiplied with -TILE_HEIGHT_STEP/2.
-	 * To obtain real z-offset, interpolate using steps, steps_next.
+	 * Actual travel direction in screen coordinates
+	 * @author Hj. Malthaner
 	 */
-	uint8 zoff_start:4, zoff_end:4;
+	ribi_t::ribi direction;
 
-	// cached image
-	image_id image;
-
 	/**
 	 * Vehicle movement: check whether this vehicle can enter the next tile (pos_next).
 	 * @returns NULL if check fails, otherwise pointer to the next tile
@@ -506,6 +506,9 @@
 	schedule_t * generate_new_schedule() const;
 
 	virtual overtaker_t* get_overtaker();
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 
@@ -562,6 +565,9 @@
 	virtual void set_convoi(convoi_t *c);
 
 	virtual schedule_t * generate_new_schedule() const;
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 
@@ -662,6 +668,9 @@
 	obj_t::typ get_typ() const { return water_vehicle; }
 
 	schedule_t * generate_new_schedule() const;
+
+	void * operator new(size_t s);
+	void operator delete(void *p);
 };
 
 
