mods: make bezel artwork user-selected

This commit is contained in:
Matthew Stanley
2026-08-24 17:03:52 -07:00
parent 001af57c7f
commit 84a901289d
13 changed files with 421 additions and 45 deletions
+83 -17
View File
@@ -838,6 +838,69 @@ int provider_feature_set_option(void*, const char* package_id,
});
}
int provider_feature_resource_count(void*, const char* package_id,
const char* feature_id) {
if (!package_id || !feature_id) return 0;
const ModPackage* package = selected_package(package_id);
if (!package) return 0;
return (int)std::count_if(
package->resources.begin(), package->resources.end(),
[&](const ModResource& resource) {
return resource.feature_id == feature_id;
});
}
int provider_feature_resource_get(void*, const char* package_id,
const char* feature_id, int index,
RecompLauncherCModResource* out) {
if (!package_id || !feature_id || !out || index < 0) return 0;
const ModPackage* package = selected_package(package_id);
if (!package) return 0;
for (const ModResource& resource : package->resources) {
if (resource.feature_id != feature_id) continue;
if (index-- != 0) continue;
const std::filesystem::path path =
state().manager.feature_resource_path(
package_id, feature_id, resource.id);
std::error_code ec;
const bool directory =
resource.format == "directory" || resource.format == "folder";
const bool verified = !path.empty() &&
(directory ? std::filesystem::is_directory(path, ec)
: std::filesystem::is_regular_file(path, ec));
std::memset(out, 0, sizeof(*out));
copy_text(out->id, sizeof(out->id), resource.id);
copy_text(out->label, sizeof(out->label), resource.label);
copy_text(out->description, sizeof(out->description),
resource.description);
copy_text(out->path, sizeof(out->path), path.string());
copy_text(out->status, sizeof(out->status),
path.empty() ? "Not selected" :
(verified ? "Selected" : "Selected path is missing"));
copy_text(out->file_patterns, sizeof(out->file_patterns),
resource.file_patterns);
copy_text(out->file_description, sizeof(out->file_description),
resource.file_description);
out->required = resource.required ? 1 : 0;
out->verified = verified ? 1 : 0;
copy_text(out->format, sizeof(out->format), resource.format);
return 1;
}
return 0;
}
int provider_feature_resource_set_path(void*, const char* package_id,
const char* feature_id,
const char* resource_id,
const char* path) {
if (!package_id || !feature_id || !resource_id || !path) return 0;
return mutate([&](std::string& error) {
return state().manager.set_feature_resource_path(
package_id, feature_id, resource_id,
std::filesystem::path(path), &error);
});
}
int provider_diagnostic_count(void*, const char* package_id,
const char* feature_id) {
if (!package_id || !feature_id) return 0;
@@ -1003,6 +1066,9 @@ RecompLauncherCModProvider provider = {
nullptr, /* archive_extension — PSX defaults */
nullptr, /* archive_description */
provider_commit_netplay,
provider_feature_resource_count,
provider_feature_resource_get,
provider_feature_resource_set_path,
};
#endif
@@ -1219,8 +1285,11 @@ extern "C" void mod_runtime_on_vblank(void) {
using namespace PSXRecompV4;
RuntimeMods& s = state();
if (!s.initialized || !s.plan.ok) return;
for (const ModResolution::Plugin& plugin : s.plan.plugins)
for (const ModResolution::Plugin& plugin : s.plan.plugins) {
s.current_plugin = &plugin;
mod_invoke_vblank_plugin(plugin.id);
s.current_plugin = nullptr;
}
}
extern "C" int psx_mod_game_started(void) {
@@ -1249,28 +1318,25 @@ extern "C" int psx_mod_option_value(const char* package_id,
return 1;
}
extern "C" int psx_mod_current_package_file(const char* relative_path,
char* out, uint32_t out_size) {
extern "C" int psx_mod_current_resource_path(const char* resource_id,
char* out, uint32_t out_size) {
using namespace PSXRecompV4;
if (out && out_size) out[0] = '\0';
if (!relative_path || !relative_path[0] || !out || out_size == 0)
if (!resource_id || !resource_id[0] || !out || out_size == 0)
return 0;
RuntimeMods& s = state();
if (!s.initialized || !s.plan.ok || !s.current_plugin) return 0;
const ModPackage* package =
s.manager.selected_package(s.current_plugin->package_id);
if (!package) return 0;
std::filesystem::path rel(relative_path);
if (rel.is_absolute()) return 0;
for (const auto& part : rel) {
if (part == "." || part == "..") return 0;
for (const ModResolution::Resource& resource : s.plan.resources) {
if (resource.package_id != s.current_plugin->package_id ||
resource.feature_id != s.current_plugin->feature_id ||
resource.id != resource_id)
continue;
const std::string text = resource.path.string();
if (text.empty() || text.size() + 1 > (size_t)out_size) return 0;
std::memcpy(out, text.c_str(), text.size() + 1);
return 1;
}
const std::filesystem::path path =
(package->root / rel).lexically_normal();
const std::string text = path.string();
if (text.size() + 1 > (size_t)out_size) return 0;
std::memcpy(out, text.c_str(), text.size() + 1);
return 1;
return 0;
}
extern "C" uint8_t psx_mod_read_byte(uint32_t address) {