Skip to content
Merged
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
16 changes: 16 additions & 0 deletions Core/GameEngine/Source/Common/INI/INI.cpp
Original file line number Diff line number Diff line change
Expand Up @@ -442,6 +442,9 @@ UnsignedInt INI::load( AsciiString filename, INILoadType loadType, Xfer *pXfer )
try {
(*parse)( this );

// GeneralsX @bugfix Copilot 20/09/2026 Preserve the innermost INI field diagnostic.
} catch (const INIException&) {
throw;
} catch (...) {
DEBUG_CRASH(("Error parsing block '%s' in INI file '%s'", token, m_filename.str()) );
char buff[1024];
Expand Down Expand Up @@ -1585,6 +1588,9 @@ void INI::initFromINIMulti( void *what, const MultiIniFieldParse& parseTableList

(*parse)( this, what, (char *)what + offset + parseTableList.getNthExtraOffset(ptIdx), userData );

// GeneralsX @bugfix Copilot 20/09/2026 Do not replace nested field errors with an enclosing module.
} catch (const INIException&) {
throw;
} catch (...) {
DEBUG_CRASH( ("[LINE: %d - FILE: '%s'] Error reading field '%s' of block '%s'",
INI::getLineNum(), INI::getFilename().str(), field, m_curBlockStart) );
Expand Down Expand Up @@ -1683,6 +1689,11 @@ Type scanType(std::string_view token)

if (ec != std::errc{})
{
// GeneralsX @bugfix Copilot 20/09/2026 Keep numeric conversion failures visible in release builds.
fprintf(stderr, "[INI] Cannot parse numeric token '%.*s': %s\n",
static_cast<int>(token.size()), token.data(),
ec == std::errc::result_out_of_range ? "out of range" : "invalid number");
fflush(stderr);
throw INI_INVALID_DATA;
}

Expand All @@ -1696,6 +1707,11 @@ Type scanType(std::string_view token)

if (ec != std::errc{})
{
// GeneralsX @bugfix Copilot 20/09/2026 Identify overflowing mod values without changing their interpretation.
fprintf(stderr, "[INI] Cannot parse numeric token '%.*s': %s\n",
static_cast<int>(token.size()), token.data(),
ec == std::errc::result_out_of_range ? "out of range" : "invalid number");
fflush(stderr);
throw INI_INVALID_DATA;
}

Expand Down
7 changes: 7 additions & 0 deletions docs/WORKLOG/2026-09-DIARY.md
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,13 @@
- This addresses the misleading wording only; it does not explain or suppress the reported frame-zero divergence. The original replay and, if applicable, its custom map are still needed to investigate that.
- Compiled both affected Recorder.cpp objects with the native macOS configuration and checked the diff for whitespace errors. No installed game or user settings were changed.

### Preserve Nested INI Error Details (#297)
- Kept an existing `INIException` intact when it passes through nested module and outer-block handlers, rather than replacing the useful field/file/line details with an enclosing `Object` header.
- Added release-visible numeric conversion diagnostics for `std::from_chars` failures, including the token and whether it is invalid or out of range. Parsing rules and failure behavior are unchanged.
- The supplied Shockwave INIs contain delay values beyond the signed 64-bit intermediate used by the Linux unsigned-number parser. These are concrete rejection points, not proof of the first failure in the reporter's complete mod installation; this is a diagnostics fix, not a compatibility fix.
- Exercised parser-function extracts with both game variants' exception headers, both numeric parsing paths, and address/undefined-behavior sanitizers. The baseline lost nested context; the patch retained it without changing valid/sentinel/suffix handling or cleanup.
- Syntax-checked the actual patched INI.cpp with each game's generated native macOS compiler configuration. No full mod run or installed-game changes were made.

## 19/09/2026
### Fix NGMP Statistics Synchronization & Session Token Expiry Handling
- **Context**: Welcome screen (`WOLWelcomeMenu`) statistics ("Players online", Daily Stats "Wins/Losses 0% (0/0)", and personal player stats) were not reflecting real-time game activity or active matches. Investigation traced three root causes:
Expand Down
Loading