diff --git a/thcrap/src/init.cpp b/thcrap/src/init.cpp index 99360eff..b8f01f94 100644 --- a/thcrap/src/init.cpp +++ b/thcrap/src/init.cpp @@ -313,6 +313,9 @@ int thcrap_init(const char *run_cfg) runconfig_load(full_cfg, RUNCONFIG_NO_OVERWRITE); json_decref(full_cfg); + // Game has been positively identified by hash or size, we can safely start pruning the patch stack + stack_prune_patches(runconfig_game_get()); + oldbuild_show(); } diff --git a/thcrap/src/patchfile.cpp b/thcrap/src/patchfile.cpp index 32658edb..0bb025ee 100644 --- a/thcrap/src/patchfile.cpp +++ b/thcrap/src/patchfile.cpp @@ -333,6 +333,19 @@ void patch_show_motd(const patch_t *patch_info) } } +int patch_game_supported(const patch_t *patch_info, const char *game_id) +{ + if (patch_info->supported_games) { + for (size_t i = 0; patch_info->supported_games[i]; i++) { + if (strcmp(game_id, patch_info->supported_games[i]) == 0) { + return 1; + } + } + return 0; + } + return 1; +} + patch_t patch_build(const patch_desc_t *desc) { std::string_view repo_id = desc->repo_id; @@ -449,6 +462,7 @@ patch_t patch_init(const char *patch_path, const json_t *patch_info, size_t leve patch.title = json_object_get_string_copy(patch_js, "title"); patch.servers = json_object_get_string_array_copy(patch_js, "servers"); + patch.supported_games = json_object_get_string_array_copy(patch_js, "supported_games"); patch.ignore = json_object_get_string_array_copy(patch_js, "ignore"); patch.motd = json_object_get_string_copy(patch_js, "motd"); patch.motd_title = json_object_get_string_copy(patch_js, "motd_title"); @@ -504,6 +518,12 @@ void patch_free(patch_t *patch) } free(patch->servers); } + if (patch->supported_games) { + for (size_t i = 0; patch->supported_games[i]; i++) { + free(patch->supported_games[i]); + } + free(patch->supported_games); + } if (patch->ignore) { for (size_t i = 0; patch->ignore[i]; i++) { free(patch->ignore[i]); diff --git a/thcrap/src/patchfile.h b/thcrap/src/patchfile.h index 1f688044..d1260868 100644 --- a/thcrap/src/patchfile.h +++ b/thcrap/src/patchfile.h @@ -76,6 +76,8 @@ typedef struct char *title; // Servers list (NULL-terminated) (from patch.js) char **servers; + // List of supported games (NULL-terminated) (from patch.js) + char **supported_games; // List of dependencies (from patch.js) patch_desc_t *dependencies; // List of font files to load (from patch.js) @@ -199,6 +201,9 @@ THCRAP_API int patch_file_delete(const patch_t *patch_info, const char *fn); /// ----------- // Shows the MOTD of the patch. void patch_show_motd(const patch_t *patch_info); + +// Returns 1 if the game id [game_id] is supported by [patch_info]. +int patch_game_supported(const patch_t *patch_info, const char *game_id); /// ----------- /// Initialization diff --git a/thcrap/src/stack.cpp b/thcrap/src/stack.cpp index 0e62ce60..3e78fcde 100644 --- a/thcrap/src/stack.cpp +++ b/thcrap/src/stack.cpp @@ -381,6 +381,16 @@ void stack_print() log_printf(" '%s'", patch.servers[i]); } } + bool print_supported_games = patch.supported_games != NULL; + log_print(print_supported_games ? + "\n supported games:" : + "\n supported games: all" + ); + if (print_supported_games) { + for (size_t i = 0; patch.supported_games[i]; ++i) { + log_printf(" '%s'", patch.supported_games[i]); + } + } } log_print("\n"); } @@ -429,6 +439,16 @@ int stack_remove_if_unneeded(const char *patch_id) return ret; } +void stack_prune_patches(const char *game_id) +{ + auto game_supported = [game_id](const patch_t &patch) { return patch_game_supported(&patch, game_id); }; + auto removed = std::partition(stack.begin(), stack.end(), game_supported); + for (auto it = removed; it != stack.end(); ++it) { + patch_free(&*it); + } + stack.erase(removed, stack.end()); +} + void stack_free() { for (patch_t &patch : stack) { diff --git a/thcrap/src/stack.h b/thcrap/src/stack.h index 2722ab9a..1cd52dd5 100644 --- a/thcrap/src/stack.h +++ b/thcrap/src/stack.h @@ -151,7 +151,10 @@ THCRAP_API void stack_foreach_cpp(std::function callback) // patch ever as an explicit, upfront dependency of every stack ever. THCRAP_API int stack_remove_if_unneeded(const char *patch_id); -THCRAP_API int stack_check_if_unneeded(const char* patch_id); +THCRAP_API int stack_check_if_unneeded(const char *patch_id); + +// Remove all patches which do not support the current game_id +THCRAP_API void stack_prune_patches(const char *game_id); // Clear the stack and free its patches THCRAP_API void stack_free();