summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--build/common.mk3
-rw-r--r--src/cl_pred.c7
-rw-r--r--src/cl_ref.c2
-rw-r--r--src/common.c5
-rw-r--r--src/fpu.c44
-rw-r--r--src/fpu.h56
-rw-r--r--src/sv_game.c2
-rw-r--r--src/sv_init.c5
-rw-r--r--src/sv_local.h1
-rw-r--r--src/sv_main.c6
-rw-r--r--src/sv_user.c5
-rw-r--r--src/sys_public.h2
-rw-r--r--src/sys_unix.c23
-rw-r--r--src/sys_win.c7
14 files changed, 130 insertions, 38 deletions
diff --git a/build/common.mk b/build/common.mk
index 09a1587..cb30fcc 100644
--- a/build/common.mk
+++ b/build/common.mk
@@ -31,7 +31,8 @@ SRCFILES+=cmd.c \
q_shared.c \
q_field.c \
io_sleep.c \
- error.c
+ error.c \
+ fpu.c
ifdef USE_ZLIB
LDFLAGS+=$(ZLIB_LDFLAGS)
diff --git a/src/cl_pred.c b/src/cl_pred.c
index 744eb33..2a87b08 100644
--- a/src/cl_pred.c
+++ b/src/cl_pred.c
@@ -19,7 +19,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
*/
#include "cl_local.h"
-
+#include "fpu.h"
/*
===================
@@ -213,6 +213,9 @@ void CL_PredictMovement( void ) {
return;
}
+ X86_PUSH_FPCW;
+ X86_SINGLE_FPCW;
+
// copy current state to pmove
memset( &pm, 0, sizeof( pm ) );
pm.trace = CL_Trace;
@@ -246,6 +249,8 @@ void CL_PredictMovement( void ) {
} else {
frame = current - 1;
}
+
+ X86_POP_FPCW;
oldz = cl.predicted_origins[cl.predicted_step_frame & CMD_MASK][2];
step = pm.s.origin[2] - oldz;
diff --git a/src/cl_ref.c b/src/cl_ref.c
index 771ca99..c51beb9 100644
--- a/src/cl_ref.c
+++ b/src/cl_ref.c
@@ -273,7 +273,7 @@ void CL_InitRefresh( void ) {
SCR_RegisterMedia();
Con_RegisterMedia();
-
+
cvar_modified &= ~(CVAR_FILES|CVAR_REFRESH);
}
diff --git a/src/common.c b/src/common.c
index 84e144c..086a6b9 100644
--- a/src/common.c
+++ b/src/common.c
@@ -38,6 +38,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "q_field.h"
#include "prompt.h"
#include "io_sleep.h"
+#include "fpu.h"
#include <setjmp.h>
#if USE_ZLIB
#include <zlib.h>
@@ -472,6 +473,8 @@ void Com_Error( error_type_t code, const char *fmt, ... ) {
// abort any console redirects
Com_AbortRedirect();
+
+ X86_POP_FPCW;
if( code == ERR_DISCONNECT || code == ERR_SILENT ) {
Com_WPrintf( "%s\n", com_errorMsg );
@@ -1832,6 +1835,8 @@ void Qcommon_Init( int argc, char **argv ) {
Com_SetLastError( NULL );
+ X86_SetFPCW();
+
// prepare enough of the subsystems to handle
// cvar and command buffer management
Z_Init();
diff --git a/src/fpu.c b/src/fpu.c
new file mode 100644
index 0000000..9e21130
--- /dev/null
+++ b/src/fpu.c
@@ -0,0 +1,44 @@
+/*
+Copyright (C) 2011 skuller.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#include "common.h"
+#include "fpu.h"
+
+#if (defined __i386__) || (defined _M_IX86)
+
+uint16_t pushed_cw, single_cw, full_cw, chop_cw, ceil_cw;
+
+void X86_SetFPCW( void ) {
+ uint16_t cw;
+
+ // save the control word into pushed_cw
+ X86_PUSH_FPCW;
+
+ // mask off RC and PC bits
+ cw = pushed_cw & 0xf0ff;
+
+ single_cw = cw; // round mode, 24-bit precision
+ full_cw = cw | 0x300; // round mode, 64-bit precision
+ chop_cw = cw | 0xc00; // chop mode, 24-bit precision
+ ceil_cw = cw | 0x800; // ceil mode, 24-bit precision
+}
+
+#endif
+
diff --git a/src/fpu.h b/src/fpu.h
new file mode 100644
index 0000000..62125bc
--- /dev/null
+++ b/src/fpu.h
@@ -0,0 +1,56 @@
+/*
+Copyright (C) 2011 skuller.net
+
+This program is free software; you can redistribute it and/or
+modify it under the terms of the GNU General Public License
+as published by the Free Software Foundation; either version 2
+of the License, or (at your option) any later version.
+
+This program is distributed in the hope that it will be useful,
+but WITHOUT ANY WARRANTY; without even the implied warranty of
+MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.
+
+See the GNU General Public License for more details.
+
+You should have received a copy of the GNU General Public License
+along with this program; if not, write to the Free Software
+Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
+
+*/
+
+#if (defined __i386__) || (defined _M_IX86)
+
+#ifdef _MSC_VER
+#define X86_STORE_FPCW(x) __asm fnstcw x
+#define X86_LOAD_FPCW(x) __asm fldcw x
+#else
+#define X86_STORE_FPCW(x) __asm__ __volatile__( "fnstcw %0" : "=m" (x) )
+#define X86_LOAD_FPCW(x) __asm__ __volatile__( "fldcw %0" : : "m" (x) )
+#endif
+
+#define X86_PUSH_FPCW X86_STORE_FPCW(pushed_cw)
+#define X86_POP_FPCW X86_LOAD_FPCW(pushed_cw)
+
+#define X86_SINGLE_FPCW X86_LOAD_FPCW(single_cw)
+#define X86_FULL_FPCW X86_LOAD_FPCW(full_cw)
+#define X86_CHOP_FPCW X86_LOAD_FPCW(chop_cw)
+#define X86_CEIL_FPCW X86_LOAD_FPCW(ceil_cw)
+
+extern uint16_t pushed_cw, single_cw, full_cw, chop_cw, ceil_cw;
+
+void X86_SetFPCW( void );
+
+#else
+
+#define X86_PUSH_FPCW
+#define X86_POP_FPCW
+
+#define X86_SINGLE_FPCW
+#define X86_FULL_FPCW
+#define X86_CHOP_FPCW
+#define X86_CEIL_FPCW
+
+#define X86_SetFPCW()
+
+#endif
+
diff --git a/src/sv_game.c b/src/sv_game.c
index 04f4642..2408942 100644
--- a/src/sv_game.c
+++ b/src/sv_game.c
@@ -882,7 +882,5 @@ void SV_InitGameProgs ( void ) {
if( ge->max_edicts <= sv_maxclients->integer || ge->max_edicts > MAX_EDICTS ) {
Com_Error (ERR_DROP, "Game DLL returned bad number of max_edicts");
}
-
- Sys_FixFPCW();
}
diff --git a/src/sv_init.c b/src/sv_init.c
index fbe7740..033b3dd 100644
--- a/src/sv_init.c
+++ b/src/sv_init.c
@@ -149,6 +149,9 @@ static void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint
// map initialization
sv.state = ss_loading;
+ X86_PUSH_FPCW;
+ X86_SINGLE_FPCW;
+
// load and spawn all other entities
ge->SpawnEntities ( sv.name, cm->cache->entitystring, spawnpoint );
@@ -156,6 +159,8 @@ static void SV_SpawnServer( cm_t *cm, const char *server, const char *spawnpoint
ge->RunFrame ();
ge->RunFrame ();
+ X86_POP_FPCW;
+
// make sure maxclients string is correct
sprintf( sv.configstrings[CS_MAXCLIENTS], "%d", sv_maxclients->integer );
diff --git a/src/sv_local.h b/src/sv_local.h
index 9289d4f..5e7ea79 100644
--- a/src/sv_local.h
+++ b/src/sv_local.h
@@ -40,6 +40,7 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#include "mvd_public.h"
#endif
#include "io_sleep.h"
+#include "fpu.h"
#if USE_ZLIB
#include <zlib.h>
#endif
diff --git a/src/sv_main.c b/src/sv_main.c
index d6ff9b2..fbbcdde 100644
--- a/src/sv_main.c
+++ b/src/sv_main.c
@@ -1499,8 +1499,13 @@ static void SV_RunGameFrame( void ) {
time_before_game = Sys_Milliseconds();
#endif
+ X86_PUSH_FPCW;
+ X86_SINGLE_FPCW;
+
ge->RunFrame();
+ X86_POP_FPCW;
+
#if USE_CLIENT
if( host_speeds->integer )
time_after_game = Sys_Milliseconds();
@@ -1517,7 +1522,6 @@ static void SV_RunGameFrame( void ) {
// save the entire world state if recording a serverdemo
SV_MvdEndFrame();
#endif
-
}
/*
diff --git a/src/sv_user.c b/src/sv_user.c
index b4ba1be..31ee6e6 100644
--- a/src/sv_user.c
+++ b/src/sv_user.c
@@ -1193,6 +1193,9 @@ void SV_ExecuteClientMessage( client_t *client ) {
int net_drop;
size_t len;
+ X86_PUSH_FPCW;
+ X86_SINGLE_FPCW;
+
sv_client = client;
sv_player = sv_client->edict;
@@ -1358,5 +1361,7 @@ void SV_ExecuteClientMessage( client_t *client ) {
sv_client = NULL;
sv_player = NULL;
+
+ X86_POP_FPCW;
}
diff --git a/src/sys_public.h b/src/sys_public.h
index 0122b11..6b9b507 100644
--- a/src/sys_public.h
+++ b/src/sys_public.h
@@ -63,8 +63,6 @@ char *Sys_GetCurrentDirectory( void );
void Sys_DebugBreak( void );
-void Sys_FixFPCW( void );
-
#if USE_AC_CLIENT
qboolean Sys_GetAntiCheatAPI( void );
#endif
diff --git a/src/sys_unix.c b/src/sys_unix.c
index 1ff2370..4d3ab0c 100644
--- a/src/sys_unix.c
+++ b/src/sys_unix.c
@@ -604,27 +604,6 @@ qboolean Sys_GetAntiCheatAPI( void ) {
}
#endif
-void Sys_FixFPCW( void ) {
-#ifdef __i386__
- uint16_t cw;
-
- __asm__ __volatile__( "fnstcw %0" : "=m" (cw) );
-
- Com_DPrintf( "FPU control word: %x\n", cw );
-
- if( cw & 0x300 ) {
- Com_DPrintf( "Setting FPU to single precision mode\n" );
- cw &= ~0x300;
- }
- if( cw & 0xC00 ) {
- Com_DPrintf( "Setting FPU to round to nearest mode\n" );
- cw &= ~0xC00;
- }
-
- __asm__ __volatile__( "fldcw %0" : : "m" (cw) );
-#endif
-}
-
static void hup_handler( int signum ) {
Com_FlushLogs();
}
@@ -726,8 +705,6 @@ void Sys_Init( void ) {
signal( SIGFPE, kill_handler );
signal( SIGTRAP, kill_handler );
}
-
- Sys_FixFPCW();
}
#if USE_SYSCON
diff --git a/src/sys_win.c b/src/sys_win.c
index 4ca0a6c..6630dca 100644
--- a/src/sys_win.c
+++ b/src/sys_win.c
@@ -26,7 +26,6 @@ Foundation, Inc., 59 Temple Place - Suite 330, Boston, MA 02111-1307, USA.
#if USE_WINSVC
#include <winsvc.h>
#endif
-#include <float.h>
HINSTANCE hGlobalInstance;
@@ -674,12 +673,6 @@ unsigned Sys_Milliseconds( void ) {
void Sys_AddDefaultConfig( void ) {
}
-void Sys_FixFPCW( void ) {
-#ifdef __i386__ // FIXME: MSVC?
- _controlfp( _PC_24|_RC_NEAR, _MCW_PC|_MCW_RC );
-#endif
-}
-
void Sys_Sleep( int msec ) {
Sleep( msec );
}