Reconcile current master with validated X4 co-op support for PR23 playtest

This commit is contained in:
Matthew Stanley
2026-10-10 20:49:35 -07:00
115 changed files with 6508 additions and 312 deletions
+175 -1
View File
@@ -1,4 +1,5 @@
#include "mod_runtime.h"
#include "mod_netplay.h"
#include "host_launch_timing.h"
#include "host_file_identity.h"
#include "mod_packages.h"
@@ -30,6 +31,8 @@ static int failures;
static int activation_calls;
static int plugin_calls;
static int restore_calls;
static int option_renderer_activations;
static void option_renderer_activate(void) { ++option_renderer_activations; }
static PsxLobbyMatchCaps test_match_caps;
extern "C" const PsxLobbyMatchCaps* psx_lobby_match_caps(void) {
return &test_match_caps;
@@ -403,7 +406,7 @@ static uint64_t startup_counter(const char* requested) {
return 0;
}
int main() {
int main(int argc, char** argv) {
#if defined(PSX_LAUNCHER_MOD_COMMIT_WORKER_SAFE)
const fs::path root = fs::temp_directory_path() / "psxrecomp-mod-runtime-cache-test";
const auto isolated_cache = root / "test-cache";
@@ -478,6 +481,10 @@ int main() {
"[[feature]]\n"
"id = \"vblank-plugin\"\n"
"name = \"VBlank Plugin\"\n"
"[[option]]\nfeature = \"vblank-plugin\"\nid = \"cameras\"\n"
"label = \"Cameras\"\ntype = \"choice\"\ndefault = \"unified\"\n"
"[[option.choice]]\nvalue = \"unified\"\nlabel = \"Unified\"\n"
"[[option.choice]]\nvalue = \"split\"\nlabel = \"Split\"\n"
"[[option]]\n"
"feature = \"dynamic-main\"\n"
"id = \"count\"\n"
@@ -1780,6 +1787,173 @@ int main() {
check(!PSXRecompV4::mod_runtime_try_prepare_cached(iso_path), "default runtime does not opt into cached startup");
}
#endif
/* The executable-owned profile forces its trusted plugin, including hooks,
* without applying/saving any player's offline patches or selections. */
test_match_caps = {};
const bool missing_profile = argc > 1 && std::string(argv[1]) == "--missing-profile";
const bool missing_renderer = argc > 1 && std::string(argv[1]) == "--missing-renderer";
const bool option_renderer_missing = argc > 1 && std::string(argv[1]) == "--option-renderer-missing";
const bool profile_options = option_renderer_missing ||
(argc > 1 && std::string(argv[1]) == "--profile-options");
static const PSXModNetplayProfile profile = {
missing_profile ? "runtime.missing-simulation" : "runtime.test-vblank",
"runtime-coop-delay-v1", 0, 0, 1, 3u,
profile_options ? "runtime.option-renderer" : "runtime.missing-renderer", nullptr, 0,
profile_options ? "runtime.test" : nullptr,
profile_options ? "vblank-plugin" : nullptr,
profile_options ? "cameras" : nullptr,
profile_options ? "split" : nullptr
};
if (profile_options && !option_renderer_missing)
check(psx_mod_register_activation_plugin("runtime.option-renderer", option_renderer_activate),
"profile option renderer registration");
check(psx_mod_register_netplay_profile(&profile), "trusted profile registration");
check(PSXRecompV4::mod_runtime_initialize(root, "SLUS-RUNTIME", 0x80002000, {}, &error),
"profile reinitialize offline catalog");
if (missing_profile || missing_renderer || option_renderer_missing) {
if (missing_renderer) check(psx_mod_netplay_set_aspect(1), "select profile renderer");
if (option_renderer_missing) {
test_match_caps.valid = 1;
test_match_caps.mod_count = 1;
std::strcpy(test_match_caps.mods[0].id, "runtime.test");
std::strcpy(test_match_caps.mods[0].ver, "1.0.0");
std::strcpy(test_match_caps.mods[0].feats, "vblank-plugin=cameras~split");
std::string fingerprint;
check(PSXRecompV4::mod_runtime_netplay_settings_fingerprint(test_match_caps, fingerprint, &error),
"missing renderer offer still has a valid settings identity");
std::strcpy(test_match_caps.mod_plan_fp, fingerprint.c_str());
}
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error) &&
!psx_mod_netplay_is_active() && !error.empty(),
"missing trusted plugin refuses profile activation with a reason");
check(psx_mod_netplay_savestates_supported(), "failed profile cannot latch snapshot policy");
const auto before_failed_activation = activation_calls;
mod_runtime_activate_plugins();
check(activation_calls == before_failed_activation, "failed profile cannot activate stale offline plugin");
fs::remove_all(root, ec);
return failures ? 1 : 0;
}
const auto selection_path = root / "state.toml";
auto read_selection = [&]() {
std::ifstream file(selection_path, std::ios::binary);
return std::string(std::istreambuf_iterator<char>(file), {});
};
std::string offline_selection = read_selection();
check(PSXRecompV4::mod_runtime_commit_for_direct_netplay(iso_path, &error), error.c_str());
check(psx_mod_netplay_is_active() && !psx_mod_netplay_savestates_supported(),
"profile activates host-state snapshot policy");
const int activations_before = activation_calls;
mod_runtime_activate_plugins();
check(activation_calls == activations_before + 1, "profile forces native plugin activation");
ram[0x1000] = 0x5a;
mod_runtime_on_dispatch(0x80002000);
check(ram[0x1000] == 0x5a, "profile excludes offline executable writes");
check(psx_mod_read_disc_file("S0/LEVEL.NSF", result.data(), 3000, &bytes) && bytes == 3000,
"profile retains original-disc reads");
check(read_selection() == offline_selection, "profile does not save temporary selections");
check(PSXRecompV4::mod_runtime_commit_netplay_view(iso_path, &error), "profile rematch commit");
mod_runtime_activate_plugins();
check(activation_calls == activations_before + 2, "profile rematch activates exactly once");
CPUState profile_cpu{};
test_netplay_active = 1;
filter_handles = true;
check(psx_mod_function_entry(&profile_cpu, 0x80003008) && profile_cpu.gpr[2] == 42u,
"profile retains modern trusted function filters");
test_netplay_active = 0;
test_match_caps.valid = 1;
test_match_caps.mod_count = 1;
check(!PSXRecompV4::mod_runtime_commit_for_netplay(iso_path, &error) &&
!psx_mod_netplay_is_active(), "profile rejects imported package plans");
test_match_caps = {};
check(PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "profile restores after rejected plan");
if (profile_options) {
char value[32], unified_identity[65], split_identity[65];
check(psx_mod_option_value("runtime.test", "vblank-plugin", "cameras", value, sizeof(value)) &&
std::string(value) == "unified", "profile includes default camera option");
check(psx_mod_netplay_content_identity("", unified_identity), "default profile content identity");
test_match_caps.valid = 1;
test_match_caps.mod_count = 1;
std::strcpy(test_match_caps.mods[0].id, "runtime.test");
std::strcpy(test_match_caps.mods[0].ver, "1.0.0");
std::strcpy(test_match_caps.mods[0].feats, "vblank-plugin=cameras~split");
std::string fingerprint;
check(PSXRecompV4::mod_runtime_netplay_settings_fingerprint(test_match_caps, fingerprint, &error) &&
fingerprint == "24a3aeaf6034d1a59df3ac27334227343237550d4938b7b00c6ae77dfec21367",
"published settings fingerprint matches the canonical codec fixture");
char preview_identity[65];
check(psx_mod_netplay_content_identity("", preview_identity) &&
std::string(preview_identity) == unified_identity && read_selection() == offline_selection,
"offer preview does not mutate the active profile or preferences");
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "missing settings fingerprint rejected");
std::strcpy(test_match_caps.mod_plan_fp, fingerprint.c_str());
test_match_caps.mod_plan_fp[0] = '0';
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "tampered settings fingerprint rejected");
std::strcpy(test_match_caps.mod_plan_fp, fingerprint.c_str());
check(PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), error.c_str());
mod_runtime_activate_plugins();
check(psx_mod_option_value("runtime.test", "vblank-plugin", "cameras", value, sizeof(value)) &&
std::string(value) == "split", "profile adopts host split camera option");
check(option_renderer_activations == 1, "split activates the declared renderer at native aspect");
check(psx_mod_netplay_content_identity("", split_identity) &&
std::string(split_identity) != unified_identity, "different camera policies cannot handshake");
check(read_selection() == offline_selection, "host options do not persist over offline choices");
std::strcpy(test_match_caps.mods[0].feats, "vblank-plugin=cameras~unified");
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "changed options with stale fingerprint rejected");
check(PSXRecompV4::mod_runtime_netplay_settings_fingerprint(test_match_caps, fingerprint, &error),
"unified offer fingerprint");
std::strcpy(test_match_caps.mod_plan_fp, fingerprint.c_str());
check(PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), error.c_str());
mod_runtime_activate_plugins();
check(option_renderer_activations == 1, "unified does not activate the option renderer");
const char* rejected[] = {"dynamic-main", "vblank-plugin,dynamic-main",
"vblank-plugin=cameras~invalid", "vblank-plugin=unknown~split"};
for (const char* token : rejected) {
std::strcpy(test_match_caps.mods[0].feats, token);
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error) &&
!psx_mod_netplay_is_active(), "profile rejects undeclared host policy");
}
std::strcpy(test_match_caps.mods[0].feats, "vblank-plugin=cameras~split");
test_match_caps.mod_count = 2;
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "profile rejects extra packages");
test_match_caps.mod_count = 1;
std::strcpy(test_match_caps.mods[0].ver, "different-version");
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "profile rejects different package versions");
std::strcpy(test_match_caps.mods[0].ver, "1.0.0");
std::strcpy(test_match_caps.mods[0].id, "different-package");
check(!PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "profile rejects unrelated settings packages");
test_match_caps = {};
check(PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), "profile recovers after rejected options");
check(read_selection() == offline_selection, "all settings commits preserve offline state");
PSXRecompV4::mod_runtime_end_netplay();
PSXRecompV4::ModPackageManager preferences(root);
check(preferences.scan(&error) && preferences.load_state(&error) &&
preferences.set_feature_option("runtime.test", "vblank-plugin", "cameras", "split", &error) &&
preferences.save_state(&error), "explicit local split preference");
offline_selection = read_selection();
check(PSXRecompV4::mod_runtime_initialize(root, "SLUS-RUNTIME", 0x80002000, {}, &error),
"profile reloads the explicit local preference");
check(PSXRecompV4::mod_runtime_commit_for_direct_netplay(iso_path, &error), error.c_str());
check(psx_mod_option_value("runtime.test", "vblank-plugin", "cameras", value, sizeof(value)) &&
std::string(value) == "split", "direct sessions use the local agreed preference");
check(psx_mod_netplay_content_identity("", split_identity) &&
std::string(split_identity) != unified_identity, "direct option identity covers camera policy");
test_match_caps.valid = 1;
test_match_caps.mod_count = 1;
std::strcpy(test_match_caps.mods[0].id, "runtime.test");
std::strcpy(test_match_caps.mods[0].ver, "1.0.0");
std::strcpy(test_match_caps.mods[0].feats, "vblank-plugin");
check(PSXRecompV4::mod_runtime_netplay_settings_fingerprint(test_match_caps, fingerprint, &error),
"default host offer fingerprint");
std::strcpy(test_match_caps.mod_plan_fp, fingerprint.c_str());
check(PSXRecompV4::mod_runtime_commit_netplay(iso_path, &error), error.c_str());
check(psx_mod_option_value("runtime.test", "vblank-plugin", "cameras", value, sizeof(value)) &&
std::string(value) == "unified", "omitted host options use defaults rather than guest preferences");
check(read_selection() == offline_selection, "host defaults preserve the guest's split preference");
}
PSXRecompV4::mod_runtime_end_netplay();
check(!psx_mod_netplay_is_active() && psx_mod_netplay_savestates_supported() &&
PSXRecompV4::mod_runtime_fingerprint().empty(), "profile end clears hooks and snapshot policy");
check(read_selection() == offline_selection, "profile end preserves offline selection file");
fs::remove_all(root, ec);
if (failures) return 1;
std::cout << "mod runtime tests passed\n";