Skip to content

architecture

Cyber Official edited this page May 31, 2026 · 1 revision

System Architecture

High-Level Design

User Input (CLI)
    |
patch-gen (cmd/generator/)          patch-apply (cmd/applier/)
    |                                     |
Version Manager (version/)            Patcher.Applier (patcher/)
    |  register, scan, cache               |  verify, backup, apply, rollback
Scanner (scanner/)
    |  walk tree, hash files
Manifest Manager (manifest/)
    |  create, compare, detect changes
    v
patcher.Generator -> streaming JSON + compression -> .patch file

Component Responsibilities

CLI Tools (cmd/)

  • generator/main.go: flag parsing, version registration, patch generation, self-contained EXE creation
  • applier/main.go: flag parsing, patch loading, embedded patch detection, interactive/silent/simple mode dispatch

Core Logic (internal/core/)

Version (version/): Manages version registry. RegisterVersion() scans directories, creates manifests, integrates scan cache. Supports parallel scanning via SetWorkerThreads(). Key file auto-detection (program.exe > game.exe > app.exe > main.exe) is handled by the CLI layer in cmd/generator/main.go before calling RegisterVersion().

Patcher (patcher/): generator.go — compares manifests, reads all added/modified files into memory as full replacements (no bsdiff), builds Patch struct. applier.go — pre-verification, selective backup, operation application, post-verification, automatic rollback on failure. multipart.go — splits large patches into parts, chunk sidecar system.

Scanner (scanner/): Recursive directory traversal, SHA-256 hashing, .cyberignore pattern matching, backup folder exclusion. Supports parallel checksum computation via worker pool.

Manifest (manifest/): Creates JSON manifests from scanned directories, loads/saves/compares manifests. Overall checksum via concatenation of sorted file checksums.

Cache (cache/): Scan result caching to .data/ JSON files. Key file hash validation prevents stale cache usage. Location-based hashing for isolation.

Config (config/): Application configuration load/save with platform-specific paths.

  • The differ package was removed in v1.0.17 — the generator uses full file replacement for all files.

Utilities (pkg/utils/)

  • types.go: All shared data structures (Version, Patch, PatchOperation, Manifest, FileEntry, Config, etc.)
  • checksum.go: SHA-256 file/data/string hashing and verification
  • fileops.go: CopyFile, EnsureDir, RemoveDir, CopyDir, FileExists, IsExecutable
  • compress.go: zstd/gzip compression/decompression (in-memory and streaming)
  • patch_io.go: SavePatch/LoadPatch with streaming JSON encoding and auto-compression detection

Data Flow

Patch Generation

1. Scan source directory -> build manifest with file hashes
2. Scan target directory -> build manifest with file hashes
3. Compare manifests -> identify added/modified/deleted files and directories
4. For each modified/added file: read full content via os.ReadFile
5. Package everything into Patch struct with operations
6. Stream JSON encode -> compress -> write .patch file

Patch Application

1. Load patch file (auto-detect compression)
2. Pre-verify: key file hash matches + all required files match
3. Create selective backup to backup.cyberpatcher/
4. Apply operations in order (add dirs first, delete files, delete dirs deepest-first, add files, modify files last)
5. Post-verify: modified files match target hashes
6. On failure: automatic rollback from backup
7. On success: preserve backup for manual rollback

Self-Contained Executable Format

patch-gen --create-exe writes: [patch-apply.exe] [patch data] [sidecar blob] [128-byte header]

128-byte header at end of file (little-endian):

  • Bytes 0-7: Magic CPMPATCH
  • Bytes 8-11: Version uint32 (currently 1)
  • Bytes 12-19: StubSize uint64
  • Bytes 20-27: DataOffset uint64 (== StubSize)
  • Bytes 28-35: DataSize uint64
  • Bytes 36-51: Compression type string
  • Bytes 52-83: SHA-256 checksum of patch data
  • Byte 84: Flags (bit 0 = silent mode embedded)
  • Bytes 85-127: Reserved

Applier detects by reading last 128 bytes of its own file, validating magic, version, bounds, and checksum.

External Dependencies

  • github.com/klauspost/compress — zstd compression

Clone this wiki locally