Skip to content
Open
Show file tree
Hide file tree
Changes from 1 commit
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
2 changes: 1 addition & 1 deletion src/Makefile.common
Original file line number Diff line number Diff line change
Expand Up @@ -102,7 +102,7 @@ else ifeq ($(BUILD), c99)
CFLAGS += -std=c99
else ifeq ($(BUILD), retroarch)
# RetroArch builds with gcc8 and gnu99 which adds some extra warning validations
SRC_CFLAGS += -std=gnu99 -D_GNU_SOURCE -Wall -Warray-bounds=2 -Wincompatible-pointer-types
SRC_CFLAGS += -std=gnu99 -D_GNU_SOURCE -Wall -Warray-bounds=2 -Wincompatible-pointer-types -ffast-math
# Also include the RC_CLIENT_SUPPORTS_EXTERNAL flag to ensure we do the full level of validation on the
# most code. The c89 build will ensure things still build without the RC_CLIENT_SUPPORTS_EXTERNAL flag.
CFLAGS += -DRC_CLIENT_SUPPORTS_EXTERNAL
Expand Down
2 changes: 1 addition & 1 deletion src/api/rc_api_user.c
Original file line number Diff line number Diff line change
Expand Up @@ -471,7 +471,7 @@ int rc_api_process_fetch_all_user_progress_server_response(rc_api_fetch_all_user
entry = response->entries;
while (rc_json_get_next_object_field(&iterator, &field))
{
entry->game_id = (uint32_t)strtol(field.name, &end, 10);
entry->game_id = (uint32_t)strtoul(field.name, &end, 10);

field.name = "";
if (!rc_json_get_required_object(entry_fields, sizeof(entry_fields) / sizeof(entry_fields[0]),
Expand Down
2 changes: 1 addition & 1 deletion src/libretro/rc_libretro.c
Original file line number Diff line number Diff line change
Expand Up @@ -633,7 +633,7 @@ static void rc_libretro_memory_init_from_memory_map(rc_libretro_memory_regions_t
/* if we need to extract a disconnect bit, the largest block we can read is up to
* the next time that bit flips */
/* https://stackoverflow.com/questions/12247186/find-the-lowest-set-bit */
disconnect_size = (uint32_t)(desc->disconnect & -((int)desc->disconnect));
disconnect_size = (uint32_t)(desc->disconnect & ((size_t)0 - desc->disconnect));
desc_size = disconnect_size - (real_address & (disconnect_size - 1));
}

Expand Down
37 changes: 22 additions & 15 deletions src/runtime/rc_memref.c
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,9 @@
#include <stdlib.h> /* malloc/realloc */
#include <string.h> /* memcpy */
#include <math.h> /* INFINITY/NAN */
#include <float.h> /* FLT_RADIX/FLT_MANT_DIG/FLT_MAX_EXP */

#include <stdio.h>

#define MEMREF_PLACEHOLDER_ADDRESS 0xFFFFFFFF

Expand Down Expand Up @@ -344,23 +347,27 @@ static float rc_build_float(uint32_t mantissa_bits, int32_t exponent, int sign)
double dbl = ((double)mantissa) / ((double)implied_bit);

if (exponent > 127) {
/* exponent above 127 is a special number */
if (mantissa_bits == 0) {
/* infinity */
#ifdef INFINITY /* INFINITY and NAN #defines require C99 */
dbl = (double)INFINITY;
#else
dbl = -log(0.0);
#endif
}
else {
/* NaN */
#ifdef NAN
dbl = NAN;
/* An exponent above 127 is a special number: infinity when the mantissa is zero, NaN otherwise. */

#if FLT_RADIX == 2 && FLT_MANT_DIG == 24 && FLT_MAX_EXP == 128

Copy link
Copy Markdown
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

-ffast_math doesn't prevent defining INFINITY or NAN, so we can't detect when it's being applied. Instead, look for the definition of the deconstruction of a float (which also works in c89) and define the constants ourself, avoiding the real constants which would trigger the compiler warning.

/* The system is IEEE754 capable. Use a memcpy to shuffle an IEEE754 constant into the variable to
* avoid a warning when compiling with -ffast-math. -ffast-math optimizes out special logic for NaN
* and infinity to provide a small performance boost. As such, actually using the values may result
* in undefined behavior - hence the warning. But consumers want to be able to use that flag, so this
* is the easiest way to support it. */
const uint32_t ieee754_inf = 0x7F800000;
const uint32_t ieee754_nan = 0x7FC00000;
float f;
memcpy(&f, (mantissa_bits == 0) ? &ieee754_inf : &ieee754_nan, sizeof(float));
dbl = (double)f;
#elif defined(INFINITY) && defined(NAN)
/* If we're not on an IEEE754 system, rely on the constants provided by the compiler. */
dbl = (double)(mantissa_bits == 0 ? INFINITY : NAN);
#else
dbl = -sqrt(-1);
/* C89 doesn't define INFINITY or NAN. Fallback to FLT_MAX and hope all achievement logic uses full
* range checking as non-float data could appear as >X or <Y whereas NaN would be neither >X nor <Y */
dbl = (double)FLT_MAX;
#endif
}
}
else if (exponent > 0) {
/* exponent from 1 to 127 is a number greater than 1 */
Expand Down
Loading