Skip to content

libretro: expose the standalone build's settings as core options - #61

Merged
hunterk merged 1 commit into
libretro:libretrofrom
WizzardSK:core-options
Aug 13, 2026
Merged

libretro: expose the standalone build's settings as core options#61
hunterk merged 1 commit into
libretro:libretrofrom
WizzardSK:core-options

Conversation

@WizzardSK

Copy link
Copy Markdown
Contributor

The core advertised exactly one option, blastem_system_type. Everything else the standalone build lets a user change - the model, the region, RAM fill, the clock divider, every audio gain - lives in the same config tree the emulation code reads while it builds a machine, and nothing was writing to it. This adds the rest of what the standalone's settings menus offer and the emulator actually reads.

System: Mega Drive model, Master System model, default region, force region, initial RAM value, 68000 clock divider, MegaWiFi.
Input: port 1 and port 2 device.
Audio: overall / FM / PSG / RF5C164 / CD audio gain, FM DAC, low pass cutoff.
Video: overscan cropped at each edge, with auto keeping the frontend's own crop overscan setting.

Advertised through SET_CORE_OPTIONS_V2 with categories, falling back to the original flat variables when the frontend predates it. Every default is the value the core already behaved as, so a fresh config changes nothing: same geometry, same timing, and a 60 frame run of Sonic 1 produces an audio peak of 435 before and after.

Left out on purpose: window size, shaders, scaling, vsync, audio device rate and buffer size, key bindings, sync source, save paths, the file picker - a libretro frontend owns all of those. BIOS paths are settings too, but a core takes them from the system directory instead of asking; the TMSS ROM now joins the ones already handled that way, since without it a model with TMSS could not be used at all.

Two things turned up while matching the standalone's menus against what the code reads:

  • The model lists need systems.cfg, which a libretro core has no copy of. get_systems_config() was returning nothing, so get_model() returned nothing and every model property - TMSS, VSRAM size, which FM chip, TAS behaviour - silently fell back to its built-in default. It is compiled into the core now, the same way rom.db already is. Defaults are picked to preserve exactly that fallback behaviour: md1va3 for Mega Drive, and a real Master System for Master System software rather than the standalone's md1va3, which would put it on the Mega Drive VDP.
  • audio.cdd_gain is a dead setting. The standalone's CD audio slider writes it, but set_audio_config() reads audio.cdda_gain, so moving that slider does nothing. The option here is spelled the way the emulator reads it. Worth fixing in the nuklear UI too, though that is upstream's code and not this PR.

Gains, the FM DAC and the port devices are re-read while a game runs, through the same config_updated hook the standalone uses when its settings change, so they take effect immediately. The model, region, RAM fill and clock divider are only read while a machine is built and wait for the next load.

The controller port options offer the pad types the input glue can actually drive - 6-button, 3-button, none. The standalone's list also has multitaps, mice and keyboards, which need more ports and device handling than process_events() implements today.

Testing. With a small libretro host that prints what a core advertises and answers GET_VARIABLE from the environment: the v2 list and the v0 fallback both come out as intended, with the model lists built from systems.cfg and the defaults first. Then, checking that the values actually reach the emulator rather than just being advertised - region E with force on turns 320x224 at 59.92 fps into 320x240 at 49.70, model md2va1 fails the load with "Configured to use a model with TMSS, but failed to load the TMSS ROM from .../tmss.md" (the model reached genesis.c, the path reached the system directory, and the failure unwinds cleanly instead of taking the frontend with it), overscan options change the frame the core hands over to 331x243, and -24 dB of gain takes the audio peak from 435 to 27, which is the factor of 0.063 that asks for. Master System model choices are advertised but untested for want of a Master System ROM here.

@hunterk

hunterk commented Aug 13, 2026

Copy link
Copy Markdown
Collaborator

ditto for this one

Everything the standalone lets a user change lives in one config tree that the
emulation code reads as it builds a machine, and the libretro core was writing
nothing into it but file paths and its own system type override. So a frontend
could pick the machine to emulate and nothing else: not the model, not the
region, not a single audio gain.

Add the rest of what the standalone's settings menus offer and the emulator
actually reads: model for both Mega Drive and Master System, default region and
whether to force it, initial RAM contents, the 68000 clock divider, MegaWiFi,
what is in the two controller ports, the overall, FM, PSG, RF5C164 and CD audio
gains, the FM DAC and the low pass cutoff, plus how much overscan to crop.

Settings that belong to the frontend rather than the emulator are left out -
window size, shaders, scaling, vsync, audio device rate and buffer, key
bindings, sync source, save paths. So are the BIOS paths, which a core takes
from the system directory; the TMSS ROM now joins them, since a model with TMSS
was unusable without it.

Two things came out of matching the menus up with what the code reads:

- The model lists have to come from systems.cfg, which a libretro core has no
  copy of - get_systems_config() was returning nothing, so every model property
  fell back to its built-in default. It is now compiled in the way rom.db
  already is. The defaults are chosen to keep that fallback behaviour: md1va3
  for Mega Drive, and a real Master System for Master System software rather
  than the standalone's md1va3.
- The standalone's CD audio slider writes audio.cdd_gain, but set_audio_config()
  reads audio.cdda_gain, so that slider does nothing. The option here uses the
  key the emulator reads.

Gains, the DAC and the port devices are re-read while a game runs, like the
standalone does when its settings change. The model, region, RAM fill and clock
divider are only read while a machine is built, so they wait for the next load.

Options are advertised through SET_CORE_OPTIONS_V2 with categories, falling back
to the original flat variables for frontends that predate it.
@hunterk
hunterk merged commit aeb16cd into libretro:libretro Aug 13, 2026
@WizzardSK
WizzardSK deleted the core-options branch August 13, 2026 18:06
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.

2 participants