Skip to content

Commit b3b82e9

Browse files
StarkkuMetadorius
andcommitted
Replace game's CRT function call in floating point number INI parser (#1973)
Attempts to address one of the issues presented in #1970 by working around the changes introduced in 9c8bd9e by replacing calling game's CRT functions. `sscanf(_s)` produces results with different precision from game's `sscanf`. Using `strtod` and casting the result double into float appears to be more accurate but whether or not these results are consistent across different systems I do not know. This merely addresses the floating point number parsing in Phobos (which also replaces game's floating point number INI parser, see hook `INIClass_ReadDouble_Overwrite` in `Misc\Hooks.INIInheritance.cpp`) and does not in any way involve any potential root causes for why calling game's CRT functions is problematic in the first place. --------- Co-authored-by: Kerbiter <crabiter@vivaldi.net>
1 parent e2889c7 commit b3b82e9

File tree

2 files changed

+28
-16
lines changed

2 files changed

+28
-16
lines changed

docs/Whats-New.md

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -326,6 +326,7 @@ Phobos fixes:
326326
- Fixed an issue with `Powered`/`PoweredSpecial` building animation ownership change fix (by Trsdy)
327327
- Fixed `DisplayIncome`, `Transact.Money` etc. display strings showing through shroud and for objects that are supposed to be hidden such as cloaked, undetected enemies (by Starkku)
328328
- Fixed an issue that could cause crashes when `FeedbackWeapon` was used to convert the firer to another TechnoType with less or no weapons (by Starkku)
329+
- Fixed an issue with parsing floating point numbers from INI that may have in some cases contributed to desyncs (by Starkku)
329330
```
330331

331332
### 0.4

src/Utilities/Parser.h

Lines changed: 27 additions & 16 deletions
Original file line numberDiff line numberDiff line change
@@ -35,7 +35,6 @@
3535
#include <type_traits>
3636
#include <Windows.h>
3737
#include <stdio.h>
38-
#include <CRT.h>
3938

4039
//! Parses strings into one or more elements of another type.
4140
/*!
@@ -261,35 +260,47 @@ inline bool Parser<int>::TryParse(const char* pValue, OutType* outValue)
261260
template<>
262261
inline bool Parser<double>::TryParse(const char* pValue, OutType* outValue)
263262
{
263+
errno = 0;
264+
char* end;
264265

265-
// Game doesn't use double precision when parsing, using double here would create inconsistency.
266-
float buffer = 0.0;
266+
// Nov 23, 2025 - Starkku, Kerbiter: strtod() + cast result to float produces
267+
// results more similar to game's CRT functions than using sscanf_s. For some
268+
// reason CnC-DDraw in DirectX mode causes game's CRT function usage here to change
269+
// for some players, causing stably reproducible desyncs when CMIN appears, f.ex.
270+
double value = strtod(pValue, &end);
267271

268-
// Use game's sscanf function, the C library one has different precision/rounding.
269-
if (CRT::sscanf(pValue, "%f", &buffer) == 1)
272+
if (pValue == end || errno == ERANGE)
273+
return false;
274+
275+
float floatValue = static_cast<float>(value);
276+
277+
if (strchr(pValue, '%'))
270278
{
271-
if (strchr(pValue, '%'))
272-
{
273-
buffer *= 0.01f;
274-
}
275-
if (outValue)
276-
{
277-
*outValue = buffer;
278-
}
279-
return true;
279+
floatValue *= 0.01f;
280280
}
281-
return false;
281+
if (outValue)
282+
{
283+
*outValue = floatValue;
284+
}
285+
return true;
282286
};
283287

284288
template<>
285289
inline bool Parser<float>::TryParse(const char* pValue, OutType* outValue)
286290
{
287291
double buffer = 0.0;
292+
288293
if (Parser<double>::TryParse(pValue, &buffer))
289294
{
295+
float floatValue = static_cast<float>(buffer);
296+
297+
if (strchr(pValue, '%'))
298+
{
299+
floatValue *= 0.01f;
300+
}
290301
if (outValue)
291302
{
292-
*outValue = static_cast<float>(buffer);
303+
*outValue = floatValue;
293304
}
294305
return true;
295306
}

0 commit comments

Comments
 (0)