Architecture¶
The dotnet-6502 codebase is organized into four tiers with a strict dependency rule. A host app can run any emulated system without holding a compile-time reference to it — systems are discovered as plugins at runtime.
This page is the single overview of that model. Per-library reference lives under
Libraries; the full plugin contract and discovery flow live in
Systems.Plugins.
The four tiers¶
┌──────────────────────────────────────────────────────┐
│ Tier 4 — Apps + shell plugins (not libraries) │ App.<Tech> · App.<Tech>.Core
│ Composition root + per-system UI shells │ App.<Tech>.Shell.<System>
└────────────────────┬─────────────────────────────────┘
│
┌────────────────────▼─────────────────────────────────┐
│ Tier 3 — Implementation libraries │ Highbyte.DotNet6502.Impl.<Tech>
│ Render / Input / Audio for specific UI tech │ Highbyte.DotNet6502.Impl.<Tech>.<System>
│ · Impl.<Tech> — host-tech glue (agnostic) │
│ · Impl.<Tech>.<System> — per-system engine plugins │
└────────────────────┬─────────────────────────────────┘
│
┌────────────────────▼─────────────────────────────────┐
│ Tier 2 — System-specific core libraries │ Highbyte.DotNet6502.Systems.<System>
│ Computer logic — CPU wiring, video chip, I/O │ e.g. .Commodore64 · .Apple2 · .Oric
└────────────────────┬─────────────────────────────────┘
│
┌────────────────────▼─────────────────────────────────┐
│ Tier 1 — Core libraries │ Highbyte.DotNet6502
│ CPU, abstractions, plugin contracts, monitor, │ Highbyte.DotNet6502.Systems
│ scripting, debug adapter, remoting, AI │ Highbyte.DotNet6502.Systems.Plugins
└──────────────────────────────────────────────────────┘ Highbyte.DotNet6502.Monitor
Highbyte.DotNet6502.DebugAdapter
Highbyte.DotNet6502.Remoting
Highbyte.DotNet6502.Scripting.MoonSharp
Highbyte.DotNet6502.AI
| Tier | What it is | Project name patterns | May reference |
|---|---|---|---|
| 1 — Core | 6502 CPU, system abstractions, plugin contracts, tooling. UI- and system-agnostic. | Highbyte.DotNet6502, Highbyte.DotNet6502.Systems, Highbyte.DotNet6502.Systems.Plugins, Highbyte.DotNet6502.Monitor, …DebugAdapter, …Remoting, …Scripting.MoonSharp, …AI |
— |
| 2 — System core | An emulated computer's logic (CPU wiring, video chip, I/O). UI-agnostic. | Highbyte.DotNet6502.Systems.<System> |
Tier 1 |
| 3 — Implementation | Render / input / audio bound to a host technology. Split into system-agnostic glue and per-system engine plugins. | Highbyte.DotNet6502.Impl.<Tech>, Highbyte.DotNet6502.Impl.<Tech>.<System> |
Tiers 1, 2 |
| 4 — Apps + shells | Entry exes and per-system UI shell plugins. | Highbyte.DotNet6502.App.<Tech>, Highbyte.DotNet6502.App.<Tech>.Shell.<System> |
Tiers 1, 3 |
The dependency rule¶
Each tier may reference only tiers below it. On top of that, three rules govern how system-specific projects are referenced:
- A host app holds no compile-time reference to a system. Entry exes have no
ProjectReferenceto, and nousingof, any…Systems.<System>or…Impl.<Tech>.<System>project. Adding or removing a system never edits an existing app. - Shell plugins reference exactly one engine plugin. Each
App.<Tech>.Shell.<System>project references the matchingImpl.<Tech>.<System>so the engine assembly flows into the app's output. - Entry exes discover shells via a glob. Each entry exe has a convention
ProjectReferenceglob (e.g.App.Avalonia.Shell.*\*.csproj) so new shell projects are picked up automatically without editing the exe.
The combined effect: adding a new emulated system, or a new host technology, is project addition only — no existing app, library, or csproj is edited.
Plugin contracts¶
Two interfaces, both defined in
Highbyte.DotNet6502.Systems.Plugins, are
what each plugin assembly carries:
ISystemEnginePlugin— engine-side composition. Ships inImpl.<Tech>.<System>. Registers the system'sISystemConfigurerand host config into the host app's DI container.ISystemShellPlugin— shell-side composition. Ships inApp.<Tech>.Shell.<System>. Contributes per-system UI pieces (menu, info panel, config dialog) to the host app's shell. ItsCreate*Contributionmethods returnobject, so the contract is UI-framework-agnostic — each host app casts to its own ViewModel / component type.
A plugin assembly marks itself with [assembly: SystemPlugin(typeof(<PluginType>))].
Discovery instantiates the type via Activator.CreateInstance and the host app wires
it in.
Plugin discovery¶
At startup, a host app calls SystemPluginDiscovery.Discover<ISystemEnginePlugin>()
(and Discover<ISystemShellPlugin>() for GUI hosts). Discovery reads every
[assembly: SystemPlugin] in the current AppDomain and instantiates the plugins.
Because .NET lazy-loads referenced assemblies, discovery first ensures candidate plugin assemblies are loaded, using three strategies in order:
- Build-emitted manifest —
[assembly: AssemblyMetadata("Highbyte.DotNet6502.PluginAssembly", "<name>")]items emitted by theEmitPluginAssemblyManifestMSBuild target in each entry exe. This is the only strategy that works on browser WASM and on single-file desktop publishes, where the relevant DLLs cannot be enumerated from disk. - Transitive reference walk from the entry assembly.
- Filesystem fallback — probe the app base directory for
Highbyte.DotNet6502.*DLLs not yet loaded (the C# compiler prunesProjectReferences whose types are never statically used — exactly the case for attribute-only plugin assemblies).
For the per-method contract and the full discovery flow, see
Systems.Plugins.
Glossary¶
- System core — a Tier-2
Highbyte.DotNet6502.Systems.<System>project implementingISystem,ISystemConfig,ISystemConfigurer. UI-agnostic. - Engine plugin — a Tier-3
Highbyte.DotNet6502.Impl.<Tech>.<System>project carrying anISystemEnginePlugin. Registers one system for one host technology. - Shell plugin — a Tier-4
Highbyte.DotNet6502.App.<Tech>.Shell.<System>project carrying anISystemShellPlugin. Per-host UI pieces (menu, info panel, config dialog) for one system. - Host technology ("host tech") — a UI / rendering / input / audio stack:
Avalonia (Desktop and Browser), SilkNet (Native), SadConsole, Blazor WASM,
Terminal (TUI), Headless. Each host tech has an
Impl.<Tech>glue library and anApp.<Tech>entry exe. - Entry exe — the
App.<Tech>(orApp.<Tech>.Core) project that boots the host app. Holds the conventionProjectReferenceglob that picks up shell plugins, and theEmitPluginAssemblyManifestMSBuild target that emits the discovery manifest. - Composition root — the place in the entry exe where the DI container is configured and plugin discovery runs.
See also¶
- Libraries overview — per-library reference, organized by tier.
- Implementation libraries overview — app-by-library matrix.
Highbyte.DotNet6502.Systems.Plugins— plugin contracts and discovery in full detail.- Adding a new emulated system — step-by-step walkthrough for adding a new computer (VIC-20, NES, …) on top of this model.