mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-28 02:56:36 -04:00
Live mod option changes (in-game overlay P5)
psx_mod_set_option_live records a session override for a committed feature's option and calls the plugin's new option-changed callback in that plugin's context; psx_mod_option_value answers the override. It returns 1 when applied live, 0 when the change waits for a restart, -1 during netplay (the plan is negotiated between peers). Nothing changes unless an overlay calls it. Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
@@ -2824,6 +2824,51 @@ extern "C" int psx_mod_game_started(void) {
|
||||
return fntrace_is_game_started();
|
||||
}
|
||||
|
||||
/* ---- Live option overrides (in-game overlay P5) ------------------------- */
|
||||
namespace {
|
||||
std::map<std::string, std::string>& live_option_values() {
|
||||
static std::map<std::string, std::string> m;
|
||||
return m;
|
||||
}
|
||||
std::map<std::string, PSXModOptionChangedCallback>& option_changed_plugins() {
|
||||
static std::map<std::string, PSXModOptionChangedCallback> m;
|
||||
return m;
|
||||
}
|
||||
std::string live_option_key(const char* p, const char* f, const char* o) {
|
||||
return std::string(p) + '\x1f' + f + '\x1f' + o;
|
||||
}
|
||||
} // namespace
|
||||
|
||||
extern "C" int psx_mod_register_option_changed_plugin(const char* id,
|
||||
PSXModOptionChangedCallback cb) {
|
||||
if (!id || !*id || !cb) return 0;
|
||||
option_changed_plugins()[id] = cb;
|
||||
return 1;
|
||||
}
|
||||
|
||||
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;
|
||||
if (!package_id || !feature_id || !option_id || !value) return 0;
|
||||
if (psx_netplay_active()) return -1;
|
||||
RuntimeMods& s = state();
|
||||
if (!s.initialized || !s.plan.ok) return 0;
|
||||
bool in_plan = false;
|
||||
for (const ModResolution::Plugin& plugin : s.plan.plugins)
|
||||
if (plugin.package_id == package_id && plugin.feature_id == feature_id) in_plan = true;
|
||||
if (!in_plan) return 0;
|
||||
live_option_values()[live_option_key(package_id, feature_id, option_id)] = value;
|
||||
int live = 0;
|
||||
for (const ModResolution::Plugin& plugin : s.plan.plugins) {
|
||||
if (plugin.package_id != package_id || plugin.feature_id != feature_id) continue;
|
||||
auto it = option_changed_plugins().find(plugin.id);
|
||||
if (it == option_changed_plugins().end()) continue;
|
||||
PluginCallbackScope scope(s, &plugin);
|
||||
if (it->second(option_id, value)) live = 1;
|
||||
}
|
||||
return live;
|
||||
}
|
||||
|
||||
extern "C" int psx_mod_option_value(const char* package_id,
|
||||
const char* feature_id,
|
||||
const char* option_id,
|
||||
@@ -2839,9 +2884,11 @@ extern "C" int psx_mod_option_value(const char* package_id,
|
||||
* treat an empty string as a value. */
|
||||
if (!s.initialized || !s.plan.ok) return 0;
|
||||
/* Read the committed plan's selection, which includes features its
|
||||
* [[requirement]]s activated, not live launcher state. */
|
||||
const std::string value = s.manager.feature_option_value(
|
||||
s.plan, package_id, feature_id, option_id);
|
||||
* [[requirement]]s activated, not live launcher state -- unless the
|
||||
* in-game menu changed it this session (psx_mod_set_option_live). */
|
||||
auto live = live_option_values().find(live_option_key(package_id, feature_id, option_id));
|
||||
const std::string value = live != live_option_values().end() ? live->second :
|
||||
s.manager.feature_option_value(s.plan, package_id, feature_id, option_id);
|
||||
if (value.empty()) return 0;
|
||||
if (value.size() + 1 > (size_t)out_size) return 0;
|
||||
std::memcpy(out, value.c_str(), value.size() + 1);
|
||||
|
||||
Reference in New Issue
Block a user