Skip to content

Latest commit

 

History

History
103 lines (80 loc) · 5.05 KB

README.md

File metadata and controls

103 lines (80 loc) · 5.05 KB
type Package Documentation
title CorePlay engines — adapters, registry, launch plans
description The Engine interface, package-level registry, nine build-tagged emulator adapters, launch planning, and the sandbox policy that gates every launch
repo core/play
module dappco.re/go/play

Engines — adapters, registry, launch plans

An engine is a runnable STIM runtime adapter. Source: go/engine.go, engine_adapter.go, launch.go, sandbox.go, plus one <engine>.go + <engine>_init.go pair per adapter.

The Engine interface

type Engine interface {
    Name() string
    Platforms() []string
    Run(artefact string, config EngineConfig) error
    Verify() error
}

Optional capabilities are separate interfaces, checked at use:

Interface Method Used by
LaunchPlanner PlanLaunch(bundle) (LaunchPlan, error) Service.PreparePlay, sandbox validation
AccelerationDescriber Acceleration() AccelerationDescriptor Frame pipeline defaults
EngineCodeProvider CodeIdentity() EngineCodeIdentity Shield code-pin verification

EngineConfig carries the runtime context: Core *core.Core, Context, WorkingDirectory, ConfigPath, Profile, SaveRoot, Resources ResourceLimits, NetworkAllowed, Output io.Writer. Execution goes through Core's process primitive — config.Core.Process().RunIn(ctx, dir, executable, args...) — never os/exec.

Registry

registry := play.NewRegistry()
err := registry.Register(engine)          // rejects nil, empty name, duplicates
engine, found := registry.Resolve("fuse")
names := registry.Names()                 // stable sorted order

A package-level default registry backs play.RegisterEngine, play.ResolveEngine, and play.RegisteredEngines. Errors are typed EngineError{Kind, Name, Message} with kinds like engine/duplicate, engine/platform-unsupported, engine/run-failed.

The nine adapters

Each adapter self-registers via an init() behind its own build tag, so binaries opt in per engine:

Engine name Build tag Platforms Notes
dosbox engine_dosbox dos -conf config flag
dosbox-x engine_dosboxx dos, pc-98, windows-3x, windows-9x
fuse engine_fuse zx-spectrum, spectrum, zx-spectrum-48k, zx-spectrum-128k profile 48k/128k → --machine 48/128
mame engine_mame arcade, neo-geo
retroarch engine_retroarch sega-genesis, sega-mega-drive, snes, super-nintendo, nes, game-boy, game-boy-color, … extra CoreDirectory field for libretro cores
scummvm engine_scummvm scummvm, point-and-click
snes9x engine_snes9x snes, super-nintendo
synthetic engine_synthetic (smoke) no external emulator — prints a deterministic success marker for end-to-end tests
vice engine_vice commodore-64, c64, commodore-128, c128, vic-20

Adapters share the helpers in engine_adapter.go: requireEngineBinary (Verify), adapterCodeIdentity (code pin, hashing a virtual identity when no binary hash is set), validateAdapterBundle (runtime/platform match), and adapterLaunchPlan (plan construction from the manifest).

Launch plans

type LaunchPlan struct {
    Engine, Executable   string
    Arguments            []string
    WorkingDirectory     string
    Entrypoint           string   // runtime.entrypoint, falling back to artefact.path
    RuntimeConfig        string
    ReadPaths, WritePaths []string // derived from manifest permissions
    Resources            ResourceLimits
    NetworkAllowed       bool
}

plan, err := play.PlanLaunch(bundle, engine) // EngineError engine/plan-unavailable if not a LaunchPlanner

Sandbox policy

PrepareSandbox(bundle, home, writer) creates the per-bundle layout under home/.core/play/<name>/ — saves/, screenshots/, session.log (paths overridable via manifest save:). The resulting SandboxPolicy then gates the plan:

issues := policy.ValidateLaunch(plan)
// sandbox/network-denied   — plan wants network the policy does not allow
// sandbox/read-denied      — entrypoint, runtime config, or read path outside the allowlist
// sandbox/write-denied     — write path outside saves/screenshots roots
// sandbox/resource-denied  — CPU or memory request above the manifest ceiling

Read paths always include the artefact, runtime config, and entrypoint; write paths default to the save and screenshot roots and reject anything outside them.

File map

File Contents
go/engine.go Engine, EngineConfig, Registry, package-level registry, runLaunchPlan, EngineError
go/engine_adapter.go Shared adapter helpers (binary check, code identity, bundle validation, plan build)
go/launch.go LaunchPlan, LaunchPlanner, PlanLaunch
go/sandbox.go SandboxPolicy, PrepareSandbox, ValidateLaunch, manifest path derivation
go/dosbox.go … go/vice.go One adapter per file
go/*_init.go Build-tagged init() registration per engine