Design Principles

Inject Only What's Necessary

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.

Process Externally

Video decoding, audio playback, multiplayer networking, and all heavy computation run in separate daemon and overlay processes outside the target game.

Communicate via IPC

Components exchange data through named pipes (Windows) or Unix sockets (Linux) for commands, and lock-free seqlock shared memory for high-throughput frame data.

Fail Gracefully

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.

System Overview

The launcher orchestrates three independent processes that communicate through IPC and shared memory.

Launcher orchestration Daemon video decode, audio, IPC server Injector Vulkan hooks, state extraction Overlay egui + wgpu, desktop rendering Shared Memory (seqlock) IPC write read read Target Game Process

Component Responsibilities

Each component has a clear, bounded role. Here's what each does — and what it deliberately does not.

Injector

DOES

  • Hook Vulkan/OpenVR calls
  • Extract minimal game state
  • Send state updates via IPC
  • Render textured quads
  • Read frames from shared memory

DOES NOT

  • Decode video or audio
  • Make network requests
  • Perform complex computation
  • Block the render thread

Daemon

DOES

  • Decode video (hw accelerated)
  • Play audio via cpal
  • Write frames to shared memory
  • Serve IPC commands
  • Handle multiplayer sync

DOES NOT

  • Inject code into games
  • Render graphics
  • Touch the target process
  • Require elevated privileges

Overlay

DOES

  • Render content via wgpu
  • Provide egui controls
  • Read frames from shared memory
  • Handle click-through

DOES NOT

  • Inject code
  • Decode video/audio
  • Do heavy computation
  • Affect game stability

Data Flow

State Extraction Flow

Injector hooks Vulkan call
Extract camera matrix + game state
Serialize via itk-protocol
Send over IPC to Daemon
Daemon validates + aggregates

Frame Data Flow

Daemon decodes video frame
Scale to 1280×720 RGBA
Write to triple buffer (seqlock)
Injector/Overlay reads latest
Upload to GPU texture + render

Wire Protocol

Every IPC message uses a 20-byte header followed by a bitcode-serialized payload. CRC32 covers the entire payload for integrity.

Magic
4 bytes · "ITKP"
Version
4 bytes · u32
MsgType
4 bytes · u32
PayloadLen
4 bytes · u32
CRC32
4 bytes · u32

Message Types

IDNameDirectionDescription
0-1Ping / PongBidirectionalHealth check and latency measurement
10-12ScreenRect / WindowState / OverlayUpdateInjector → DaemonWindow geometry and overlay positioning
20-23StateSnapshot / Event / Query / ResponseBidirectionalGame state exchange and queries
30-32SyncState / ClockPing / ClockPongP2PClock synchronization and playback sync
40-46Video*VariousVideo load, play, pause, seek, state, metadata, error
255ErrorAnyError response with code and message

Seqlock Shared Memory

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.

Writer
seq++ write seq++
seq++ write seq++
Reader
retry (torn)
read OK
read OK

Odd sequence = write in progress. Reader spins until two consecutive even reads match.

Memory Layout

[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)

Platform Abstraction

ITK uses cfg_if! blocks to abstract platform differences behind unified traits.

SubsystemWindowsLinux
IPC TransportNamed Pipes (\\.\pipe\itk_*)Unix Domain Sockets (/tmp/itk_*.sock)
Shared MemoryCreateFileMappingW + MapViewOfFileshm_open + mmap
InjectionNative DLL (retour detours)LD_PRELOAD shared object
Overlay Click-ThroughWS_EX_TRANSPARENTX11 SHAPE extension / Wayland layer-shell

Security Model

The injector runs inside an untrusted process. All data from it is treated as potentially malicious.

Trust Boundaries

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.

Defense in Depth

  • Magic bytes verification ("ITKP")
  • Protocol version check
  • CRC32 integrity on all payloads
  • Payload size limit: 1 MB max
  • String length cap: 256 bytes
  • Data size cap: 64 KB
  • NaN/Inf float rejection
  • Process isolation (crash containment)

Graceful Degradation

FailureDetectionBehavior
Daemon unreachableIPC errorInjector continues without state export
Injector disconnectsIPC timeoutDaemon serves stale state
Overlay crashProcess exitTarget game unaffected
Target game crashProcess exitAll other components survive

Performance Budgets

Hard limits enforced across the system to keep the target game running at full speed.

ComponentMemory BudgetLatency 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