packaging: gate overlay_cache = true and report it from --setup-selfcheck

78 of 105 published releases lack the key, and the runtime never initialises
the overlay loader without it. The packager now refuses a staged game.toml
without it unless --ship-without-overlay-cache-because states why, and the
setup host's self-check reports overlay_cache_configured so CI can assert it.

(cherry picked from commit a030f4843d8e55eafed4cb42eafc6d74bb89c086)
This commit is contained in:
Alexandros Mandravillis
2026-09-16 17:44:36 +03:00
parent 193a60b805
commit 68ff52c14a
2 changed files with 44 additions and 0 deletions
+28
View File
@@ -4353,6 +4353,34 @@ static void host_selfcheck_or_return(const PsxrecompCodegenHostConfig* cfg,
printf(",\n \"game_dispatch_present\": %s", game_ok ? "true" : "false");
printf(",\n \"bios_backends_present\": %s", bios_ok ? "true" : "false");
printf(",\n \"sources_missing\": %s", missing ? "true" : "false");
/* Wave-5 F4: overlay_cache is the switch that makes the runtime initialise the
* overlay loader at all; without it every streamed overlay is interpreted. CI
* asserts this field so a title cannot ship silently without it again. */
{
char toml_abs[1200];
int overlay_cache = 0;
if (join_path(toml_abs, sizeof(toml_abs), g_project_root, "game.toml")) {
FILE* tf = fopen(toml_abs, "rb");
if (tf) {
char line[512];
while (fgets(line, sizeof(line), tf)) {
const char* p = line;
while (*p == ' ' || *p == '\t') ++p;
if (strncmp(p, "overlay_cache", 13) == 0) {
p += 13;
while (*p == ' ' || *p == '\t') ++p;
if (*p == '=') {
++p;
while (*p == ' ' || *p == '\t') ++p;
overlay_cache = strncmp(p, "true", 4) == 0;
}
}
}
fclose(tf);
}
}
printf(",\n \"overlay_cache_configured\": %s", overlay_cache ? "true" : "false");
}
printf("\n}\n");
fflush(stdout);
exit(missing ? 2 : 0);
+16
View File
@@ -64,6 +64,10 @@ DISPLAY_NAME=""
RECOMPILER_BUILD="build-recompiler"
VERSION_ENV="RELEASE_VERSION"
DISC_HINT="your legally owned game disc"
# Wave-5 F4: a packaged game.toml without `overlay_cache = true` ships a runtime that never
# initialises the overlay loader, so every streamed overlay runs on the interpreter (78 of
# 105 releases measured 2026-09-16). Refuse unless the caller states why.
SHIP_WITHOUT_OVERLAY_CACHE_BECAUSE=""
PROJECT_FILES=()
PROJECT_DIRS=()
RUNTIME_DIRS=()
@@ -115,6 +119,7 @@ while [[ $# -gt 0 ]]; do
--root) ROOT="${2:?}"; shift 2 ;;
--embed-toolchain) EMBED_TOOLCHAIN=1; shift ;;
--no-embed-toolchain) EMBED_TOOLCHAIN=0; shift ;;
--ship-without-overlay-cache-because) SHIP_WITHOUT_OVERLAY_CACHE_BECAUSE="${2:?}"; shift 2 ;;
*)
echo "error: unknown arg: $1" >&2
usage 2
@@ -484,6 +489,17 @@ fi
bash "${STAGE_SDK}" "${stage_args[@]}"
if ! grep -qE '^[[:space:]]*overlay_cache[[:space:]]*=[[:space:]]*true' "${STAGE}/game.toml"; then
if [[ -z "${SHIP_WITHOUT_OVERLAY_CACHE_BECAUSE}" ]]; then
echo "error: REFUSING TO PACKAGE: ${STAGE}/game.toml has no '[runtime] overlay_cache = true'." >&2
echo " The runtime never initialises the overlay loader without it, so every streamed" >&2
echo " overlay runs on the dirty-RAM interpreter for every player. Add the key, or pass" >&2
echo " --ship-without-overlay-cache-because '<reason>' to record why this title ships without it." >&2
exit 1
fi
echo "warning: packaging without overlay_cache = true (reason: ${SHIP_WITHOUT_OVERLAY_CACHE_BECAUSE})" >&2
fi
cat >"${STAGE}/README-SETUP.txt" <<EOF
${DISPLAY_NAME} ${VERSION} — setup package
Platform: ${ARTIFACT}