Skip to content

Change log naming convention#12

Open
brysonak wants to merge 115 commits into
EchoTools:mainfrom
brysonak:fix-logging-naming
Open

Change log naming convention#12
brysonak wants to merge 115 commits into
EchoTools:mainfrom
brysonak:fix-logging-naming

Conversation

@brysonak

@brysonak brysonak commented Apr 25, 2026

Copy link
Copy Markdown
Member

Changed log naming from "[r14(server)]-[MM-DD-YYYY]_[HH-MM-SS]_N" to "nevr-server-YYYYMMDD-HHMMSS"

Also added -legacy-log-names flag to allow the old naming convention of logs to be used.

Fixes #5

thesprockee and others added 30 commits March 28, 2026 03:34
Imports 6 non-toy plugins into plugins/ subdirectory:
- log-filter, server-timing, broadcaster-bridge, audio-intercom,
  game-rules-override, session-unlocker

Includes shared plugin headers (address_registry, nevr_common, yaml_config)
and wires into root CMakeLists.txt via add_subdirectory(plugins).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Placeholder for the future standalone Echo VR build targeting
Android ARM64 (Quest 2/3/Pro), pending echovr-reconstruction
reaching a compilable state.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add plugins section to architecture in both docs
- Add standalone stub to CLAUDE.md components
- Remove stale references (quest, dbghooks, supervisor, scripts/)
- Fix build commands (make → just)
- Add miniupnpc to vcpkg dep list
- Update directory tree to reflect current layout

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add Methodology section (planning, review iterations, testing strategy)
- Add Guardrails section (protobuf, legacy, binary patches, hook frequency)
- Fix stale protobuf references (nevr-proto submodule → BSR)
- Fix stale submodule list (add evr-test-harness)
- Add `just proto` to build commands
- Remove hardcoded local paths from cmake/local.cmake and toolchain

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Move PATCH_ANALYSIS.md and docs/investigations/ to extras/ — these
are reference/research docs, not needed for development.

Add .gitignore entries for echovr symlink, .serena/, and _temp/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Create tests/plugins/ with its own go.mod (separate from tests/system/).
Add plugin_helpers_test.go with deploy/cleanup functions for plugin DLLs,
following the same pattern as tests/system/helpers_test.go but targeting
the bin/win10/plugins/ subdirectory. Includes config file deployment
with fallback for both naming conventions.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Verify plugin binary assumptions against reconstruction source:
- Arena hash completeness (10 hashes, set comparison)
- Combat hash validity (in all 3 classifiers)
- VA_CREATE_SESSION identity in cross_binary_map.json
- CreateSession signature param count
- Gametype hash offset 0x6A0
- All VAs above IMAGE_BASE, no duplicates
- SessionApi game_mode_hash in response (expected fail until fix)

9/10 pass. SessionApiModeHashInBuildSessionJson fails as expected
until session_api.cpp is patched to include game_mode_hash.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Four MCP harness tests:
- ArenaGetsCombatWeapons: hash swap verified via session_api /session
- PluginInitSucceeds: both plugins load and respond
- NonArenaModePassthrough: combat mode not incorrectly swapped
- CleanShutdown: game stops cleanly with hooks removed

Tests query session_api on port 6721 (NOT the game's HTTP API).
All skip in -short mode.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- test-plugins-groundtruth: cross-reference tests, no game binary needed
- test-plugins: full suite including integration tests
- test-plugins-short: ground truth only (skips integration)
- test-plugins-verbose: no-cache full suite

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Moves crash reporter suppression (CreateProcess/ExitProcess/TerminateProcess
hooks) and crash dump logging (VEH with register dump + RVA stack scan) into
a standalone plugin using the NvrPluginInterface lifecycle.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Break the 2400-line patches.cpp into focused compilation units:
- cli.cpp: CLI flag parsing and globals
- boot.cpp: early init, headless/noovr setup
- config.cpp: config.json loading and service endpoint override
- mode_patches.cpp: headless/combat/noovr memory patches
- crash_recovery.cpp: crash reporter suppression and VEH
- platform_compat.cpp: Wine compat, CreateDirectory hooks
- state_machine.cpp: game main wrapper and state hooks
- initialize.cpp: top-level init orchestration

Also removes nevr_client.cpp/h and social_messages.h (moved to
social-bridge plugin), removes hash discovery addresses from
patch_addresses.h, makes ProcessMemcpy/ProcessMemset inline,
and drops --allow-multiple-definition linker workaround.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Self-contained copy of the monolithic gamepatches before the
module split, preserved as reference for diffing and rollback.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Extracts social lobby messaging (friend requests, party invites,
ghost/mute/block) from gamepatches into a standalone plugin.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
JWT-based authentication plugin that injects auth tokens into
game login requests for verified player identity.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Copies plugin DLLs into plugins/ subdirectory for both dist and
dist-lite targets, and signs them alongside main binaries.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace jsoncpp dependency with nlohmann-json across the entire codebase.
nlohmann-json is header-only, has better ergonomics, and is already
required by the CDN asset loading feature branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Document ReVault CLI usage for binary analysis lookups and add
continuity guidelines for multi-session agent workflows.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Log access violations, illegal instructions, stack overflows, and
divide-by-zero in the VEH before returning EXCEPTION_CONTINUE_SEARCH.
Rate-limited to 3 dumps to avoid log spam during cascading failures.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Support nested directory layouts where the game binary isn't in the
same directory as _local/. Both LoadEarlyConfig and LoadLocalConfigHook
now walk up to 2 parent directories. Plugin LoadConfigFile helper also
searches parent dirs with both Windows and Unix separators.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add VA constants for resource loading (Resource_InitFromBuffers),
combat system (IsCombatGameType, PlayerInit, EquipmentInit, weapon
guards, loadout), filesystem loader, and social plugin DLL selection.
All addresses verified against PC binary analysis.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…ion modes

- Hook CBroadcaster_ReceiveLocal with correct uint64_t return signature
- Mirror receive-direction packets with 0x80000000 flag
- Add experimental chassis swap via injection mode 2
- Add loadout read, body component enable, actor data dump, and weapon
  dump injection modes (3-6)
- Add OnFrame() lifecycle for periodic processing
- Enable mirror_receive in default config

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- resource_override: hook Resource_InitFromBuffers to intercept and
  replace game resources from disk before deserialization
- combat_mode: stub for combat-specific game mode initialization
- initialize: install resource override early (before resource loading)
  and optionally load combatpatch.dll if present alongside the binary

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…r plugins

- skip-splash: bypass game splash screen for faster startup
- filesystem-loader: hook Resource_InitFromBuffers to load replacement
  assets from disk (meshes, textures, configs)
- combat-patch: enable combat game mode — patches type checks, weapon
  guards, chassis equipment, and entity symbol registration
- pnsrad-enabler: force all social platform DLL paths to load pnsrad.dll

All plugins implement NvrPluginInterface and are loaded by gamepatches
plugin_loader at startup.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Reconstructed source for the RAD social platform plugin including:
- Core: CHashMap, TLSMemory, CBaseErr, CJson parser/traversal,
  serialization framework (json, text, stream, profile)
- Social: CNSRADUsers, CNSRADParty, CNSRADFriends, CNSRADActivities
- Network: CSocket, CUri
- VoIP: VoIPManager (Opus-based)
- Plugin: RadPluginAPI, module_loader, config, logging

~300 internal symbols remain unresolved. Built as OBJECT library to
verify compilation; switch to SHARED once stubs exist for all symbols.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Add src/pnsrad subdirectory (object-only reconstruction)
- Disable src/server (echovr_server.exe signing fails)
- Add filesystem_loader.dll and combat_patch.dll to dist/dist-lite
- Add pnsrad.dll to dist/dist-lite (when available)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Superseded by cdn-asset-loading plan on the feature branch.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Kill ExtractJsonString (4 copies), ExtractJsonBool, ExtractJsonInt,
ExtractJsonUint64, ExtractUint32, ExtractInt, ExtractBool, ExtractString,
ExtractStringArray, ExtractTruncateRules, and ~35 inline json.find()
patterns across token-auth, social-bridge, broadcaster-bridge, and
log-filter plugins.

Create plugins/common/include/nevr_curl.h with shared CurlWriteCallback,
removing 2 local copies.

Add nlohmann-json dependency to all 4 plugin CMakeLists.
Symlink src/NRadEngine -> echovr-reconstruction (was deleted as duplicate).

Net: -195 lines, zero hand-rolled JSON parsers remaining in plugins/.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
thesprockee and others added 23 commits April 11, 2026 05:00
The WS bridge injects LoginRequest on all connections after config
(conn > 0), but the CNSUser state manipulation (setting login state
to kLoggingIn) must only happen on the actual login connection (conn=1).
Resetting CNSUser state on later connections (matchmaker, etc.) breaks
the game's logged-in status during lobby join. Also add conn= to the
LoginRequest injection log for debugging.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Route conn>=2 (matchmaker) through the login remote WS so all traffic
shares the same Nakama session. Swap g_activeGameWs when matchmaker
connects so server responses reach the correct game-side WS peer.
Eliminates "non-matchmaker peer" warnings.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The WS bridge injects a LoginRequest but never set the game's internal
CNSUser identity to match. The PlayerSessionRequest was built from
uninitialized fields (provider=2/STM, account_id=1), causing lobby join
to fail.

- Set account_id at +0x88 to discord ID from JWT
- Set provider enum at +0x90 low nibble to 3 (PSN/DSC in binary)
- Set LoginRequest platformCode to 2 (PSN/DSC in Nakama enum)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…e on Windows

PatchDisableServerRendering duplicated PatchEnableHeadless without console
allocation. Since -server forces g_isHeadless, PatchEnableHeadless already
runs and covers renderer/audio/effects patches plus console (unless -noconsole).

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
The plugin's OnFrame and OnGameStateChange only checked g_initialized,
which could allow patches to fire on clients if init logic is rearranged.
Add a separate g_server_mode flag set only after NEVR_HOST_IS_SERVER
passes, checked independently in both callbacks.

Add regression test (TestPlugin_ServerTimingSkipsClientMode) that starts
the game in client mode with the plugin deployed and verifies process
stability — if the guard breaks, timing patches would crash the client.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Replace Sleep(ms) with WSAPoll(broadcaster_socket, ms) in the server
timing hook. The game now wakes immediately on incoming UDP data instead
of sleeping through it, eliminating 100ms+ ping latency at 6Hz idle.

- Hook ioctlsocket to capture the broadcaster UDP socket handle
- Use WSAPoll for frame pacing when socket is available (falls back to Sleep)
- New config option: event_driven_recv (default true)
- Move server-timing from plugin to gamepatches builtin (safer for main loop)
- Remove plugins/server-timing/ (consolidated into server_timing.cpp)
- Add ping latency validation and regression tests

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
- Move pnsrad_enabler from plugins/ to src/gamepatches/ (always-on)
- Remove server_timing.dll and pnsrad_enabler.dll from dist targets
- Comment out combat_2d and combat_mod from dist (disabled)
- Dist now ships: BugSplat64.dll, pnsradgameserver.dll, broadcaster_bridge.dll, log_filter.dll

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Set up a root CA → intermediate CA → code signing cert chain with
osslsigncode Authenticode signing. Root CA key stored in pass.
Updated cmake/codesign/sign.sh to use new certs/ hierarchy as
fallback. Added GitHub Actions workflow for AI-driven semantic
version tagging via GitHub Models API.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add wave0_instrumentation.cpp with 4 MinHook logging hooks:
- GetTimeMicroseconds: overflow detection near 10.68-day QPC limit
- CTimer_GetMilliSeconds: overflow detection (conservative threshold)
- EndMultiplayer: null deref at +0x2DA0 crash prevention
- HandleDXError: HRESULT logging for all DX error paths

BUGS.md documents 55 verified bugs in the original echovr.exe binary
across timing, rendering, networking, threading, audio, and crash
handling systems. Each bug includes VA, decompiled evidence, severity
rating, and user-visible impact.

FIXPLAN.md defines a 7-wave systematic fix sequence with risk ratings,
testing protocol, and bisectable commit strategy. Wave 0 spec passed
3-iteration review.

Note: Wave 0 hooks are not yet wired into boot.cpp/CMakeLists.txt —
the source files are added but build integration is in a follow-up.
Code review fixes (17 issues across src/) also pending.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Without globstar, bash treats ** as * so plugin DLLs in
dist/*/plugins/ were silently skipped during signing.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
…kaging

Add anim-debugger plugin that hooks three points in the animation loading
pipeline to diagnose "no root animation evaluator" DATA:ERROR failures:
- InitRootEvaluator: dumps CI/CD entries, actor name, physics body state
- CAnimTree::Create: logs tree/animset/rig names on lookup failure
- CAnimationCRI init: logs resource hash on load/bind failure

Auto-relay matchingservice_host and serverdb_host through the WebSocket
bridge when no explicit config.json override exists, removing the need
to manually set matchingservice_host in config.json.

Fix dist packaging: add anim_debugger.dll to both dist and dist-lite
targets, add missing log_filter.dll to dist-lite.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Call Wave0::Init() at the end of Initialize() and Wave0::Shutdown()
at the start of DLL_PROCESS_DETACH. The source was already compiled
but never called.

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Critical fixes:
- EchoTools#1: GetTimeMicroseconds overflow-safe replacement using quotient+remainder
  split. Eliminates INT64_MAX overflow after ~10.7 days. Caches QPF (#37).
- EchoTools#2: CleanupPeers mass disconnect prevented (root cause eliminated by EchoTools#1)

High fixes:
- EchoTools#7: HandleDXError recovers from transient DEVICE_HUNG/WAS_STILL_DRAWING
  instead of crashing. Fatal errors still pass through.
- EchoTools#11/EchoTools#12: CPrecisionSleep::Wait uses persistent high-res waitable timer
  (CREATE_WAITABLE_TIMER_HIGH_RESOLUTION on Win10 1803+, fallback to
  standard). Eliminates 180 kernel transitions/sec at 90fps.
- #13: CPrecisionSleep::BusyWait patched to RET unconditionally (was
  server-only). Eliminates HT-starving spin loop.
- #14: CSpinWait::WaitForValue backoff corrected from decreasing (10→0ms)
  to increasing (0→10ms). Adds YieldProcessor() for HT friendliness.

Unchanged:
- EchoTools#6: EndMultiplayer null deref prevention (already in wave0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Add 6 new bugs found via Haiku-powered ReVault scan:
- #56: COM IMMDeviceEnumerator conditional Release (Medium)
- #57: GetUserName player index no bounds check (Medium)
- #58: Stun duration sign-bit masking bypass (Medium)
- #59: Allocator vtable call before non-returning error (Medium)
- #60: Crash metadata StrLen cap mismatch (Medium)
- #61: AdvanceBodies frame counter int32 wraparound (Low)

Update fix statuses for 9 bugs now patched by wave0:
- Critical: EchoTools#1 (GetTimeMicroseconds), EchoTools#2 (CleanupPeers cascade)
- High: EchoTools#6 (EndMultiplayer), EchoTools#7 (HandleDXError), EchoTools#11 (frame pacer),
  EchoTools#12 (timer per frame), #13 (BusyWait), #14 (inverted backoff)
- Medium: #37 (QPF caching, side effect of EchoTools#1)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
* feat/loader-modules:
  docs: update binary bug audit — 61 total, 9 fixed
  fix: upgrade wave0 from observation to bug fixes for 9 binary bugs
  fix: wire wave0 instrumentation into gamepatches init/shutdown
  feat: anim-debugger plugin, auto-relay matching service, fix dist packaging
  fix: enable globstar in just sign to recurse into plugins/ subdirectory
  feat: Wave 0 instrumentation hooks, binary bug audit, fix plan
  feat: add code signing CA hierarchy and AI semantic release workflow
  refactor: move pnsrad-enabler to gamepatches builtin, clean up dist
  feat: event-driven server networking via WSAPoll
  fix: add explicit server-mode guard to server_timing plugin
  fix: let PatchEnableHeadless handle server rendering — enables console on Windows
  fix: set CNSUser XPID identity to DSC provider with discord account ID
  fix: skip Bearer when URL has credentials on /spr endpoint
  fix: shared login session for matchmaker, no extra LoginRequest
  fix: give matchmaker its own WS without format=evr, revert sharing
  debug: hex dump PlayerSessionRequest payload for join analysis
  feat: share login WS session for matchmaker connections
  fix: only reset CNSUser login state on conn=1, not all connections
  fix: Nakama RPC unwrap and LoadLibraryA fallbacks for hook install
Changed log naming from "[r14(server)]-[MM-DD-YYYY]_[HH-MM-SS]_N"
to "nevr-server-YYYYMMDD-HHMMSS"
@metis-sprock

Copy link
Copy Markdown

Clean approach — hooking CreateFileA to intercept the log path is clever. The sortable timestamp format will make log analysis way easier. Good call including the legacy flag for backwards compat.

@brysonak

Copy link
Copy Markdown
Member Author

note a possible edge case for any future problems: if multiple logs open in the same second, one may overwrite or fail depending on dwCreationDisposition

@brysonak

brysonak commented May 7, 2026

Copy link
Copy Markdown
Member Author

@metis-sprock can you merge this PR into main?

thesprockee added a commit that referenced this pull request Jul 12, 2026
Critical fixes:
- #1: GetTimeMicroseconds overflow-safe replacement using quotient+remainder
  split. Eliminates INT64_MAX overflow after ~10.7 days. Caches QPF (#37).
- #2: CleanupPeers mass disconnect prevented (root cause eliminated by #1)

High fixes:
- #7: HandleDXError recovers from transient DEVICE_HUNG/WAS_STILL_DRAWING
  instead of crashing. Fatal errors still pass through.
- #11/#12: CPrecisionSleep::Wait uses persistent high-res waitable timer
  (CREATE_WAITABLE_TIMER_HIGH_RESOLUTION on Win10 1803+, fallback to
  standard). Eliminates 180 kernel transitions/sec at 90fps.
- #13: CPrecisionSleep::BusyWait patched to RET unconditionally (was
  server-only). Eliminates HT-starving spin loop.
- #14: CSpinWait::WaitForValue backoff corrected from decreasing (10→0ms)
  to increasing (0→10ms). Adds YieldProcessor() for HT friendliness.

Unchanged:
- #6: EndMultiplayer null deref prevention (already in wave0)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
thesprockee added a commit that referenced this pull request Jul 12, 2026
Add 6 new bugs found via Haiku-powered ReVault scan:
- #56: COM IMMDeviceEnumerator conditional Release (Medium)
- #57: GetUserName player index no bounds check (Medium)
- #58: Stun duration sign-bit masking bypass (Medium)
- #59: Allocator vtable call before non-returning error (Medium)
- #60: Crash metadata StrLen cap mismatch (Medium)
- #61: AdvanceBodies frame counter int32 wraparound (Low)

Update fix statuses for 9 bugs now patched by wave0:
- Critical: #1 (GetTimeMicroseconds), #2 (CleanupPeers cascade)
- High: #6 (EndMultiplayer), #7 (HandleDXError), #11 (frame pacer),
  #12 (timer per frame), #13 (BusyWait), #14 (inverted backoff)
- Medium: #37 (QPF caching, side effect of #1)

Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Replace non-idiomatic log file naming and allow toggling with CLI flag

3 participants