Architecture - poli0981/frameledger GitHub Wiki
The full document is docs/01_ARCHITECTURE.md; the IPC details are in
docs/07_IPC.md.
flowchart LR
subgraph game["Game process (only games the user enabled)"]
G["Game"] -- "present and API calls" --> O["FrameLedger.Overlay.dll: hooks"]
end
O -- "fixed-size frame records" --> R[("shared-memory ring")]
R -- "drained every 100 ms" --> A["FrameLedger.Agent.exe"]
A -- "sessions, frames, sensors" --> DB[("ledger.db (SQLite)")]
DB --> UI["FrameLedger.exe (the App)"]
UI -- "named pipe: commands" --> A
A -- "named pipe: events" --> UI
The processes
| What | Runs | Does |
|---|---|---|
FrameLedger.exe — src/FrameLedger.App |
as the user | The WPF app: library, sessions, charts, settings. Reads SQLite; talks to the agent over the pipe. |
FrameLedger.Agent.exe — src/FrameLedger.Agent |
as the user; as administrator only if the user opts in | Watches for tracked games, runs the anti-cheat guard, injects, drains the ring, reads sensors once a second, writes SQLite. Closing the App never stops it. |
FrameLedger.Overlay.dll — src/native/FrameLedger.Overlay |
inside the game | Hooks presentation (DXGI for Direct3D 11 and 12, and OpenGL) and the upscaler, frame-generation and ray-tracing calls, and writes one record per frame into the ring. A hook never blocks, allocates, logs or throws. It draws nothing on screen. |
FrameLedger.VkLayer.dll — src/native/FrameLedger.VkLayer |
inside a Vulkan game | An implicit Vulkan layer instead of hooks, active only in a game FrameLedger starts. |
FrameLedger.Guard.dll, FrameLedger.NvapiBridge.dll, FrameLedger.ProcessStats.dll |
inside the agent, never a game | The anti-cheat guard (required), NVIDIA's extra sensors (optional), and the game's own memory read from outside it (optional). An optional one missing makes its fields N/A. |
src/FrameLedger.CaptureHost is a developer tool and is never shipped.
Two tiers
- Tier 1 — measured. The user switched hooking on for the game, and the guard found nothing: every frame is recorded.
- Tier 2 — recorded only. No hooking: the session keeps its duration, the PC's sensors, the game's memory, its display mode, and why it was not measured. Every frame figure is N/A, never an estimate.
There is no third rung: without the hook there is no frame measurement at all.
How a frame gets to the screen
- The agent's watcher sees a tracked game's executable start (by full path, once a second).
- Hooking off, or not consented: the session is Tier 2.
- The guard checks the game's process tree, the PC's drivers and services, its title lists and the game's install folder. Any finding, or any doubt, refuses: Tier 2, with the reason.
- On a pass, the guard injects the Overlay with the documented
LoadLibraryW, under its real name. - The Overlay installs its hooks, creates the ring and publishes a handshake; the agent checks the layout version and the build id before it reads anything.
- The agent drains the ring every 100 ms and checks the game again every 30 seconds; a finding unhooks.
- When the game exits, the agent finalizes the session and writes it to SQLite in one transaction; the App reads it.
Where data lives
%LOCALAPPDATA%\FrameLedger: ledger.db (WAL mode), logs\, crashdumps\, and tmp\ for a session in progress
(its .partial file). The App installs separately, in %LOCALAPPDATA%\FrameLedger.App.