Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
45 changes: 42 additions & 3 deletions prvm_cmds.c
Original file line number Diff line number Diff line change
Expand Up @@ -17,6 +17,7 @@
#include "mdfour.h"

extern cvar_t prvm_backtraceforwarnings;
extern cvar_t prvm_gameplayfix_rintisround;
#ifdef USEODE
extern dllhandle_t ode_dll;
#endif
Expand Down Expand Up @@ -1511,10 +1512,48 @@ void VM_rint(prvm_prog_t *prog)
VM_SAFEPARMCOUNT(1,VM_rint);

f = PRVM_G_FLOAT(OFS_PARM0);
if (f > 0)
PRVM_G_FLOAT(OFS_RETURN) = floor(f + 0.5);

if (prvm_gameplayfix_rintisround.integer)
{
// Guarantee that integers (including negative zeroes) and
// infinities remain as is. This also guarantees the following
// code doesn't run for zeroes.
if (f == floor(f))
PRVM_G_FLOAT(OFS_RETURN) = f;
// The copysign ensures that output negative zeroes always have
// the same sign as the input. This likely is already the case
// anyway, but I honestly can't find anywhere in the C
// standards which kind of zero floor(0.8) and ceil(-0.8) are
// supposed to be.
else if (f > 0)
PRVM_G_FLOAT(OFS_RETURN) = copysign(floor(f + 0.5), f);
else
PRVM_G_FLOAT(OFS_RETURN) = copysign(ceil(f - 0.5), f);
// NOTE: Technically rint() when rounding to nearest should
// round towards even. Leaving things as is for now, though, as
// it matches Quake.
}
else
PRVM_G_FLOAT(OFS_RETURN) = ceil(f - 0.5);
{
// Known broken implementation of Quake, except with well
// defined overflow behavior.
if (f >= 2147483647.5 || f <= -2147483648.5)
{
// Intel 8087 and SSE2 overflow behavior.
PRVM_G_FLOAT(OFS_RETURN) = -2147483648.0;
}
else
{
// Original code from Quake.
//
// Uses cast to int, and thus truncates and never
// produces negative zeroes.
if (f > 0)
PRVM_G_FLOAT(OFS_RETURN) = (int)(f + 0.5);
else
PRVM_G_FLOAT(OFS_RETURN) = (int)(f - 0.5);
}
}
}

/*
Expand Down
2 changes: 2 additions & 0 deletions prvm_edict.c
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,7 @@ cvar_t prvm_garbagecollection_strings = {CF_CLIENT | CF_SERVER, "prvm_garbagecol
cvar_t prvm_stringdebug = {CF_CLIENT | CF_SERVER, "prvm_stringdebug", "0", "Print debug and warning messages related to strings"};
cvar_t sv_entfields_noescapes = {CF_SERVER, "sv_entfields_noescapes", "wad", "Space-separated list of fields in which backslashes won't be parsed as escapes when loading entities from .bsp or .ent files. This is a workaround for buggy maps with unescaped backslashes used as path separators (only forward slashes are allowed in Quake VFS paths)."};
cvar_t prvm_gameplayfix_div0is0 = {CF_SERVER, "prvm_gameplayfix_div0is0", "0", "When set to 1, floating point division by 0 will return zero instead of returning the IEEE standardized result (likely nan or inf). Other ways of getting non-finite values are not affected, and the warning will still print."};
cvar_t prvm_gameplayfix_rintisround = {CF_SERVER, "prvm_gameplayfix_rintisround", "1", "When set to 1, rint() behaves like C99's round() function. When set to 0, it matches Quake exactly and has the following quirks: if the value doesn't fit into int, it returns -2147483648, and it never returns negative zero, even if the input is negative."}; // TODO: remove if nobody ever has toggle this off.

static double prvm_reuseedicts_always_allow = 0;
qbool prvm_runawaycheck = true;
Expand Down Expand Up @@ -3275,6 +3276,7 @@ void PRVM_Init (void)
Cvar_RegisterVariable (&prvm_stringdebug);
Cvar_RegisterVariable (&sv_entfields_noescapes);
Cvar_RegisterVariable (&prvm_gameplayfix_div0is0);
Cvar_RegisterVariable (&prvm_gameplayfix_rintisround);

// COMMANDLINEOPTION: PRVM: -norunaway disables the runaway loop check (it might be impossible to exit DarkPlaces if used!)
prvm_runawaycheck = !Sys_CheckParm("-norunaway");
Expand Down
Loading