(svn r2583) Move OS specific code out of misc.c
authorludde
Fri, 15 Jul 2005 20:29:06 +0000
changeset 2073 899419c9b997
parent 2072 c7961c4a74ac
child 2074 f23dcde246da
(svn r2583) Move OS specific code out of misc.c
Added support for Mersenne Twister random number generator (not implemented in network yet)
Wrap player randoms around #ifdef
functions.h
mersenne.c
misc.c
network.c
network_client.c
network_server.c
openttd.c
unix.c
variables.h
win32.c
--- a/functions.h	Fri Jul 15 19:51:54 2005 +0000
+++ b/functions.h	Fri Jul 15 20:29:06 2005 +0000
@@ -93,6 +93,21 @@
 
 //#define RANDOM_DEBUG
 
+
+// Enable this to produce higher quality random numbers.
+// Doesn't work with network yet.
+//#define MERSENNE_TWISTER
+
+// Mersenne twister functions
+void SeedMT(uint32 seed);
+uint32 RandomMT(void);
+
+
+#ifdef MERSENNE_TWISTER
+	static inline uint32 Random(void) { return RandomMT(); }
+	uint RandomRange(uint max);
+#else
+
 #ifdef RANDOM_DEBUG
 	#define Random() DoRandom(__LINE__, __FILE__)
 	uint32 DoRandom(int line, const char *file);
@@ -101,12 +116,18 @@
 #else
 	uint32 Random(void);
 	uint RandomRange(uint max);
+#endif
+#endif // MERSENNE_TWISTER
 
-	static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
-	static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
+static inline TileIndex RandomTileSeed(uint32 r) { return TILE_MASK(r); }
+static inline TileIndex RandomTile(void) { return TILE_MASK(Random()); }
+
+
+#ifdef PLAYER_SEED_RANDOM
+void InitPlayerRandoms(void);
 #endif
 
-void InitPlayerRandoms(void);
+
 
 uint32 InteractiveRandom(void); /* Used for random sequences that are not the same on the other end of the multiplayer link */
 uint InteractiveRandomRange(uint max);
--- /dev/null	Thu Jan 01 00:00:00 1970 +0000
+++ b/mersenne.c	Fri Jul 15 20:29:06 2005 +0000
@@ -0,0 +1,72 @@
+#include "stdafx.h"
+#include "openttd.h"
+
+#ifdef MERSENNE_TWISTER
+
+// Source code for Mersenne Twister.
+// A Random number generator with much higher quality random numbers.
+
+#define N              (624)                 // length of _mt_state vector
+#define M              (397)                 // a period parameter
+#define K              (0x9908B0DFU)         // a magic constant
+#define hiBit(u)       ((u) & 0x80000000U)   // mask all but highest   bit of u
+#define loBit(u)       ((u) & 0x00000001U)   // mask all but lowest    bit of u
+#define loBits(u)      ((u) & 0x7FFFFFFFU)   // mask     the highest   bit of u
+#define mixBits(u, v)  (hiBit(u)|loBits(v))  // move hi bit of u to hi bit of v
+
+static uint32   _mt_state[N+1];     // _mt_state vector + 1 extra to not violate ANSI C
+static uint32   *_mt_next;          // _mt_next random value is computed from here
+static int      _mt_left = -1;      // can *_mt_next++ this many times before reloading
+
+void SeedMT(uint32 seed)
+{
+    register uint32 x = (seed | 1U) & 0xFFFFFFFFU, *s = _mt_state;
+    register int    j;
+
+    for(_mt_left=0, *s++=x, j=N; --j;
+        *s++ = (x*=69069U) & 0xFFFFFFFFU);
+ }
+
+
+static uint32 ReloadMT(void)
+ {
+    register uint32 *p0=_mt_state, *p2=_mt_state+2, *pM=_mt_state+M, s0, s1;
+    register int    j;
+
+    if(_mt_left < -1)
+        SeedMT(4357U);
+
+    _mt_left=N-1, _mt_next=_mt_state+1;
+
+    for(s0=_mt_state[0], s1=_mt_state[1], j=N-M+1; --j; s0=s1, s1=*p2++)
+        *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+    for(pM=_mt_state, j=M; --j; s0=s1, s1=*p2++)
+        *p0++ = *pM++ ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+
+    s1=_mt_state[0], *p0 = *pM ^ (mixBits(s0, s1) >> 1) ^ (loBit(s1) ? K : 0U);
+    s1 ^= (s1 >> 11);
+    s1 ^= (s1 <<  7) & 0x9D2C5680U;
+    s1 ^= (s1 << 15) & 0xEFC60000U;
+    return(s1 ^ (s1 >> 18));
+ }
+
+
+uint32 RandomMT(void)
+{
+	uint32 y;
+
+	if(--_mt_left < 0)
+		return ReloadMT();
+
+	y  = *_mt_next++;
+	y ^= (y >> 11);
+	y ^= (y <<  7) & 0x9D2C5680U;
+	y ^= (y << 15) & 0xEFC60000U;
+	return y ^ (y >> 18);
+}
+#else
+
+void SeedMT(uint32 seed) {}
+
+#endif
\ No newline at end of file
--- a/misc.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/misc.c	Fri Jul 15 20:29:06 2005 +0000
@@ -29,13 +29,14 @@
      it completely! -- TrueLight */
 #undef PLAYER_SEED_RANDOM
 
+#ifndef MERSENNE_TWISTER
+
 #ifdef RANDOM_DEBUG
 #include "network_data.h"
-
 uint32 DoRandom(int line, const char *file)
-#else
+#else // RANDOM_DEBUG
 uint32 Random(void)
-#endif
+#endif // RANDOM_DEBUG
 {
 
 uint32 s;
@@ -66,8 +67,9 @@
 	return _random_seeds[0][1] = ROR(s, 3) - 1;
 #endif
 }
+#endif // MERSENNE_TWISTER
 
-#ifdef RANDOM_DEBUG
+#if defined(RANDOM_DEBUG) && !defined(MERSENNE_TWISTER)
 uint DoRandomRange(uint max, int line, const char *file)
 {
 	return (uint16)DoRandom(line, file) * max >> 16;
@@ -79,6 +81,7 @@
 }
 #endif
 
+
 uint32 InteractiveRandom(void)
 {
 	uint32 t = _random_seeds[1][1];
@@ -92,6 +95,8 @@
 	return (uint16)InteractiveRandom() * max >> 16;
 }
 
+
+#ifdef PLAYER_SEED_RANDOM
 void InitPlayerRandoms(void)
 {
 	int i;
@@ -100,6 +105,7 @@
 		_player_seeds[i][1]=InteractiveRandom();
 	}
 }
+#endif
 
 void SetDate(uint date)
 {
@@ -112,55 +118,6 @@
 #endif /* ENABLE_NETWORK */
 }
 
-
-#ifdef ENABLE_NETWORK
-
-// multi os compatible sleep function
-
-#ifdef __AMIGA__
-// usleep() implementation
-#	include <devices/timer.h>
-#	include <dos/dos.h>
-
-	extern struct Device      *TimerBase    = NULL;
-	extern struct MsgPort     *TimerPort    = NULL;
-	extern struct timerequest *TimerRequest = NULL;
-#endif // __AMIGA__
-
-void CSleep(int milliseconds)
-{
-	#if defined(WIN32)
-		Sleep(milliseconds);
-	#endif
-	#if defined(UNIX)
-		#if !defined(__BEOS__) && !defined(__AMIGA__)
-			usleep(milliseconds * 1000);
-		#endif
-		#ifdef __BEOS__
-			snooze(milliseconds * 1000);
-		#endif
-		#if defined(__AMIGA__)
-		{
-			ULONG signals;
-			ULONG TimerSigBit = 1 << TimerPort->mp_SigBit;
-
-			// send IORequest
-			TimerRequest->tr_node.io_Command = TR_ADDREQUEST;
-			TimerRequest->tr_time.tv_secs    = (milliseconds * 1000) / 1000000;
-			TimerRequest->tr_time.tv_micro   = (milliseconds * 1000) % 1000000;
-			SendIO((struct IORequest *)TimerRequest);
-
-			if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) {
-				AbortIO((struct IORequest *)TimerRequest);
-			}
-			WaitIO((struct IORequest *)TimerRequest);
-		}
-		#endif // __AMIGA__
-	#endif
-}
-
-#endif /* ENABLE_NETWORK */
-
 void InitializeVehicles(void);
 void InitializeWaypoints(void);
 void InitializeDepot(void);
--- a/network.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/network.c	Fri Jul 15 20:29:06 2005 +0000
@@ -773,7 +773,9 @@
 
 	_network_reconnect = 0;
 
+#ifdef PLAYER_SEED_RANDOM
 	InitPlayerRandoms();
+#endif
 
 	NetworkUDPInitialize();
 }
--- a/network_client.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/network_client.c	Fri Jul 15 20:29:06 2005 +0000
@@ -488,11 +488,13 @@
 	// Check if this was the last packet
 	if (maptype == MAP_PACKET_END) {
 		// We also get, very nice, the player_seeds in this packet
+#ifdef PLAYER_SEED_RANDOM
 		int i;
 		for (i = 0; i < MAX_PLAYERS; i++) {
 			_player_seeds[i][0] = NetworkRecv_uint32(MY_CLIENT, p);
 			_player_seeds[i][1] = NetworkRecv_uint32(MY_CLIENT, p);
 		}
+#endif
 
 		fclose(file_pointer);
 
--- a/network_server.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/network_server.c	Fri Jul 15 20:29:06 2005 +0000
@@ -323,7 +323,9 @@
 			NetworkSend_Packet(p, cs);
 			if (feof(file_pointer)) {
 				// Done reading!
+#ifdef PLAYER_SEED_RANDOM
 				int i;
+#endif
 				Packet *p;
 
 				// XXX - Delete this when patch-settings are saved in-game
@@ -331,11 +333,13 @@
 
 				p = NetworkSend_Init(PACKET_SERVER_MAP);
 				NetworkSend_uint8(p, MAP_PACKET_END);
+#ifdef PLAYER_SEED_RANDOM
 				// Send the player_seeds in this packet
 				for (i = 0; i < MAX_PLAYERS; i++) {
 					NetworkSend_uint32(p, _player_seeds[i][0]);
 					NetworkSend_uint32(p, _player_seeds[i][1]);
 				}
+#endif
 				NetworkSend_Packet(p, cs);
 
 				// Set the status to DONE_MAP, no we will wait for the client
--- a/openttd.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/openttd.c	Fri Jul 15 20:29:06 2005 +0000
@@ -676,7 +676,9 @@
 	InitializeGUI();
 	IConsoleCmdExec("exec scripts/autoexec.scr 0");
 
+#ifdef PLAYER_SEED_RANDOM
 	InitPlayerRandoms();
+#endif
 
 	GenerateWorld(1, 64, 64); // Make the viewport initialization happy
 
--- a/unix.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/unix.c	Fri Jul 15 20:29:06 2005 +0000
@@ -474,6 +474,7 @@
 #endif
 
 	_random_seeds[0][1] = _random_seeds[0][0] = time(NULL);
+	SeedMT(_random_seeds[0][1]);
 
 	signal(SIGPIPE, SIG_IGN);
 
@@ -581,3 +582,49 @@
 
 	pthread_join(thread1, NULL);
 }
+
+
+
+#ifdef ENABLE_NETWORK
+
+// multi os compatible sleep function
+
+#ifdef __AMIGA__
+// usleep() implementation
+#	include <devices/timer.h>
+#	include <dos/dos.h>
+
+	extern struct Device      *TimerBase    = NULL;
+	extern struct MsgPort     *TimerPort    = NULL;
+	extern struct timerequest *TimerRequest = NULL;
+#endif // __AMIGA__
+
+void CSleep(int milliseconds)
+{
+	#if !defined(__BEOS__) && !defined(__AMIGA__)
+		usleep(milliseconds * 1000);
+	#endif
+	#ifdef __BEOS__
+		snooze(milliseconds * 1000);
+	#endif
+	#if defined(__AMIGA__)
+	{
+		ULONG signals;
+		ULONG TimerSigBit = 1 << TimerPort->mp_SigBit;
+
+		// send IORequest
+		TimerRequest->tr_node.io_Command = TR_ADDREQUEST;
+		TimerRequest->tr_time.tv_secs    = (milliseconds * 1000) / 1000000;
+		TimerRequest->tr_time.tv_micro   = (milliseconds * 1000) % 1000000;
+		SendIO((struct IORequest *)TimerRequest);
+
+		if (!((signals = Wait(TimerSigBit | SIGBREAKF_CTRL_C)) & TimerSigBit) ) {
+			AbortIO((struct IORequest *)TimerRequest);
+		}
+		WaitIO((struct IORequest *)TimerRequest);
+	}
+	#endif // __AMIGA__
+}
+
+#endif /* ENABLE_NETWORK */
+
--- a/variables.h	Fri Jul 15 19:51:54 2005 +0000
+++ b/variables.h	Fri Jul 15 20:29:06 2005 +0000
@@ -82,7 +82,10 @@
 VARDEF uint16 _station_tick_ctr;
 
 VARDEF uint32 _random_seeds[2][2];
+
+#ifdef PLAYER_SEED_RANDOM
 VARDEF uint32 _player_seeds[MAX_PLAYERS][2];
+#endif
 
 // Iterator through all towns in OnTick_Town
 VARDEF uint32 _cur_town_ctr;
--- a/win32.c	Fri Jul 15 19:51:54 2005 +0000
+++ b/win32.c	Fri Jul 15 20:29:06 2005 +0000
@@ -2124,6 +2124,7 @@
 	_random_seeds[0][0] = GetTickCount();
 	_random_seeds[0][1] = _random_seeds[0][0] * 0x1234567;
 #endif
+	SeedMT(_random_seeds[0][0]);
 
 	argc = ParseCommandLine(GetCommandLine(), argv, lengthof(argv));
 
@@ -2263,3 +2264,9 @@
 
 	WaitForSingleObject(hThread, INFINITE);
 }
+
+
+void CSleep(int milliseconds)
+{
+	Sleep(milliseconds);
+}
\ No newline at end of file