diff --git a/runtime/include/mod_plugins.h b/runtime/include/mod_plugins.h index a4af918e..78515797 100644 --- a/runtime/include/mod_plugins.h +++ b/runtime/include/mod_plugins.h @@ -390,6 +390,9 @@ int psx_mod_register_option_changed_plugin(const char* id, PSXModOptionChangedCallback callback); int psx_mod_set_option_live(const char* package_id, const char* feature_id, const char* option_id, const char* value); +/* 1 when the committed feature's plugin registered an option-changed callback + * (so a live set can take effect now). Read-only; any thread. */ +int psx_mod_option_live_capable(const char* package_id, const char* feature_id); /* * Read the committed owner-selected path for a resource declared by the * package feature whose trusted plugin is currently running. Returns 0 when diff --git a/runtime/src/mod_runtime.cpp b/runtime/src/mod_runtime.cpp index f1b78fbe..9f4d3bc7 100644 --- a/runtime/src/mod_runtime.cpp +++ b/runtime/src/mod_runtime.cpp @@ -2846,6 +2846,18 @@ extern "C" int psx_mod_register_option_changed_plugin(const char* id, return 1; } +extern "C" int psx_mod_option_live_capable(const char* package_id, const char* feature_id) { + using namespace PSXRecompV4; + if (!package_id || !feature_id) return 0; + RuntimeMods& s = state(); + if (!s.initialized || !s.plan.ok) return 0; + for (const ModResolution::Plugin& plugin : s.plan.plugins) + if (plugin.package_id == package_id && plugin.feature_id == feature_id && + option_changed_plugins().count(plugin.id)) + return 1; + return 0; +} + extern "C" int psx_mod_set_option_live(const char* package_id, const char* feature_id, const char* option_id, const char* value) { using namespace PSXRecompV4; diff --git a/runtime/tests/test_mod_runtime.cpp b/runtime/tests/test_mod_runtime.cpp index e796afc4..d9dc46bb 100644 --- a/runtime/tests/test_mod_runtime.cpp +++ b/runtime/tests/test_mod_runtime.cpp @@ -1101,8 +1101,12 @@ int main(int argc, char** argv) { check(psx_mod_option_value("runtime.ram", "big-ram", "size", value, sizeof(value)) == 1 && std::string(value) == "four", "a live override must answer later reads"); + check(!psx_mod_option_live_capable("runtime.ram", "big-ram"), + "no callback yet: not live-capable"); check(psx_mod_register_option_changed_plugin("runtime.big-ram", test_option_changed), "option-changed hook must register"); + check(psx_mod_option_live_capable("runtime.ram", "big-ram"), + "a registered callback makes the feature live-capable"); check(psx_mod_set_option_live("runtime.ram", "big-ram", "size", "eight") == 1 && option_changed_hits == 1 && option_changed_value == "eight", "the plugin must see the change in its own context");