Skip to content

Plugin rows, runner variants, and one sectioned grammar for both - #239

Open
natbro wants to merge 4 commits into
NotProtonNot:natbro-pluginfrom
natbro:plugin-rows
Open

natbro wants to merge 4 commits into
NotProtonNot:natbro-pluginfrom
natbro:plugin-rows

Conversation

@natbro

@natbro natbro commented Oct 22, 2026 •

Copy link
Copy Markdown
Contributor

Adds three things to natbro-plugin: a file
format that can hold more than one row, row types that are not toggles, and runner
variants. Plus examples/ so the whole thing can be looked at and tested without needing actual variants and plugins.


1. Runner variants

A variant is an APFS-clone of the chosen CrossOver runner with custom dual-sided (native .dylib/.so + windows .dll) files laid over it. Unlike the two types of plugins already existing (a. WINEDLLOVERRIDES in normal plugins which can only handle windows .dll additions, b. native .dylib's injected by NotProton into the Wine process), variants can touch the base runner, like a Wine Trick.
Variants are assembled the first time a game asks for one and reused after that, so they try to save space if e.g. you have many games using a custom DXMT. Descriptors of variants live in
~/Library/Application Support/notproton/variants, and the Developer section offers one
dropdown per variant-type.

[dxmt-mine]
variant = DXMT
label = v0.80-266-g186a232
src = code/dxmt/build/artifacts
dst = lib/wine
[dxmt-upstream]
variant = DXMT
label   = Upstream DXMT
src     = /opt/dxmt/artifacts
dst     = lib/wine
  • The chosen variants are written to launch options as NOTPROTON_RUNNER_VARIANT,
    +-separated by the variant-name and sorted, so groups combine.
  • Only the architecture the runner runs is taken from src: an x86_64-windows folder is
    skipped for an aarch64 runner and the other way round, so one build tree can serve both
    and a picker never offers a tree the runner cannot load.
  • A tree is only overlaid if what it holds is Wine-builtin-marked, since Wine refuses a
    builtin-marked PE under a native override and a unixlib only binds when builtin.
  • Building takes a lock and assembles into a scratch directory that is moved into place, so
    two games starting at once cannot race and a runner in use is never rewritten.

2. Rows that are not toggles

type decides what a row is; leaving it out leaves the row exactly as it is today.

[NOTPROTON_ENV_FRAMESCOPE_POSITION]
label   = HUD position
type    = choice
depends = NOTPROTON_FRAMESCOPE
choice  = tl = Top left
choice  = tr = Top right
[NOTPROTON_ENV_FRAMESCOPE_HZ]
label   = Frame pacing target
type    = slider
default = off
choice  = off = Off
choice  = 30 = 30 Hz
choice  = 60 = 60 Hz
type with is
(none) a toggle writing on or off
choice at least one choice a dropdown of Default plus each value
slider min and max a slider over that range, with optional step, default, suffix
slider two or more choice a slider that snaps to those values, a labelled tick each

Note:

  • Default stays reachable. A dropdown's Default writes no launch option. A slider has no
    empty position, so default is where the handle sits while the option is unset, and
    sliding back onto it clears the option again.
  • Only finished values are written. Sliders write on onChangeComplete, not onChange
    and values round to 4 decimals.

Two smaller changes came with them. depends now also accepts a parent that holds a
value
— a toggle parent is satisfied by its on value as before, a dropdown or slider
parent by holding any value rather than sitting on Default — which is what lets a
sub-option hang off a dropdown. And rows indent by how deep the depends chain runs, so a
sub-option of a sub-option indents twice; on1 already walked the chain, this walks it for
the indent too.

New field description_on: repeatable lines that appear under the description only while
the row is on, for what a feature offers once it is actually running.

3. One sectioned grammar for both

A [header] opens a record and is its id — for a plugin the launch option it reads and
writes, for a variant the name used in NOTPROTON_RUNNER_VARIANT. A file holds as many
records as it likes, so a feature and its settings live together:

[NOTPROTON_FRAMESCOPE]
label    = FrameScope
inject   = 1
requires = code/github/framescope/build/libframescope.dylib

[NOTPROTON_ENV_FRAMESCOPE_POSITION]
label   = HUD position
type    = choice
depends = NOTPROTON_FRAMESCOPE
choice  = tl = Top left

dylib/feats/conf-format.md is the specification: grammar, both schema tables with
cardinality stated once per field, and the error codes.

4. Examples

examples/ holds droppable files and a README of the whole grammar. They are the real
descriptors behind three tools rather than invented ones, so requires points at a build
you probably do not have — which is the point of one of them: a row whose files are missing
still appears, greyed out as "(not installed)".

file shows
plugins/10-framescope.conf a feature and its seven settings in one file: a toggle that injects a dylib, a dropdown, a range slider, a snapping slider with labelled ticks, a sub-option of a sub-option, and description_on
plugins/20-renderdoc.conf a toggle with one sub-option, writing 0 when switched off rather than clearing the option
plugins/30-kosmickrisp.conf one toggle that injects a dylib and sets two environment variables
variants/dxmt-example.conf a runner variant

The toggles work as they are. The dropdowns and sliders write their value into the game's
launch options, and that reaches the game once #219 lands; until then they show the UI
without changing the game.

Testing

conf-fixtures, confcheck, featcheck, featstagecheck, runnervariantcheck,
panel-behavior, scriptcheck, runcheck, envcheck, compatcheck, settingscheck,
webpatch-fixtures, gamedrivecheck, launchercheck, routecheck, and the dylib builds.

@natbro

natbro commented Oct 22, 2026

Copy link
Copy Markdown
Contributor Author

example of various types of rows in the developer section.
image

@natbro natbro changed the title Plugin rows that can be dropdowns and sliders, and runner variants Plugin rows, runner variants, and one sectioned grammar for both Oct 23, 2026
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant