Safe game modding, powered by Rust. Every design decision optimizes for safety, isolation, and performance.
The injected DLL/SO contains only Vulkan hooks and minimal state extraction. No complex processing, no blocking operations, no network communication. Under 5 MB memory budget.
Video decoding, audio playback, multiplayer networking, and all heavy computation run in separate daemon and overlay processes outside the target game.
Components exchange data through named pipes (Windows) or Unix sockets (Linux) for commands, and lock-free seqlock shared memory for high-throughput frame data.
Process isolation means crashes are contained. An overlay crash doesn't affect the game. A daemon failure lets the injector continue. Components detect failures and degrade to stale state.
The launcher orchestrates three independent processes that communicate through IPC and shared memory.
Each component has a clear, bounded role. Here's what each does — and what it deliberately does not.
Every IPC message uses a 20-byte header followed by a bitcode-serialized payload. CRC32 covers the entire payload for integrity.
| ID | Name | Direction | Description |
|---|---|---|---|
| 0-1 | Ping / Pong | Bidirectional | Health check and latency measurement |
| 10-12 | ScreenRect / WindowState / OverlayUpdate | Injector → Daemon | Window geometry and overlay positioning |
| 20-23 | StateSnapshot / Event / Query / Response | Bidirectional | Game state exchange and queries |
| 30-32 | SyncState / ClockPing / ClockPong | P2P | Clock synchronization and playback sync |
| 40-46 | Video* | Various | Video load, play, pause, seek, state, metadata, error |
| 255 | Error | Any | Error response with code and message |
A single-writer, multi-reader lock-free synchronization primitive. The writer increments a sequence counter before and after writes; readers retry if the counter changed during their read.
Odd sequence = write in progress. Reader spins until two consecutive even reads match.
[SeqlockHeader: 64 bytes][Buffer 0: W*H*4][Buffer 1: W*H*4][Buffer 2: W*H*4]
SeqlockHeader (64 bytes, cache-line aligned):
seq: AtomicU32 // odd = writing, even = consistent
read_idx: AtomicU32 // current read buffer (0-2)
pts_ms: AtomicU64 // presentation timestamp
frame_width: AtomicU32
frame_height: AtomicU32
is_playing: AtomicU32
content_id_hash: AtomicU64
duration_ms: AtomicU64
writer_count: AtomicU32 // multi-writer detection
_padding: [u8; 8]
Known sizes:
720p = 64 + 11,059,200 bytes (~11 MB)
1080p = 64 + 24,883,200 bytes (~24 MB)
4K = 64 + 99,532,800 bytes (~95 MB)
ITK uses cfg_if! blocks to abstract platform differences behind unified traits.
| Subsystem | Windows | Linux |
|---|---|---|
| IPC Transport | Named Pipes (\\.\pipe\itk_*) | Unix Domain Sockets (/tmp/itk_*.sock) |
| Shared Memory | CreateFileMappingW + MapViewOfFile | shm_open + mmap |
| Injection | Native DLL (retour detours) | LD_PRELOAD shared object |
| Overlay Click-Through | WS_EX_TRANSPARENT | X11 SHAPE extension / Wayland layer-shell |
The injector runs inside an untrusted process. All data from it is treated as potentially malicious.
Untrusted: Injector (runs inside target game process)
Trusted: Daemon and Overlay (separate processes under our control)
All IPC messages from the injector pass through validation before processing.
| Failure | Detection | Behavior |
|---|---|---|
| Daemon unreachable | IPC error | Injector continues without state export |
| Injector disconnects | IPC timeout | Daemon serves stale state |
| Overlay crash | Process exit | Target game unaffected |
| Target game crash | Process exit | All other components survive |
Hard limits enforced across the system to keep the target game running at full speed.
| Component | Memory Budget | Latency Target |
|---|---|---|
| Injector | < 5 MB | — |
| Daemon | < 30 MB | — |
| Overlay | < 20 MB | — |
| Shared Memory | ~10 MB (720p) | — |
| State update (IPC) | — | < 1 ms |
| Frame copy (shmem) | — | < 1 ms |
| Overlay render | — | < 5 ms |