mirror of
https://github.com/Droid-Deck/DroidDeck.git
synced 2026-11-12 19:41:10 +00:00
fix: seed redist markers again when the registry lost them (#793)
* fix: redist markers a replaced registry lost are seeded again droiddeck-seed-redists recorded what it seeded in .droiddeck-redists and trusted that record from then on. A Proton update replaces its default_pfx system.reg but leaves our record beside it, and every new prefix copies both, so new games got a record of markers their registry never had: Steam then ran their install scripts for real. Batman: Arkham City's AMD Dual-Core Optimizer installer hangs there, leaving the game on "Running install script" on every launch. Each recorded marker is now looked up in the registry, in both views where both were written, and seeded again when it is gone; a record of markers nobody wants any more is rewritten without them. * Check every VC runtime architecture before keeping the vcrt marker vcrt writes Installed for x86, x64 and arm64 in both registry views, but present() only looked at x86. If only an x64 or arm64 value was gone the runtime would not be seeded again. Require all six values and test the loss of the arm64 Wow6432Node one.
This commit is contained in:
1 parent
6528a7ed64
commit
2e65efcfa7
2 files changed
+103
No files matched your search
@@ -139,6 +139,51 @@ unseed() {
|
||||
return 1
|
||||
}
|
||||
|
||||
# The ledger lines whose values the registry still holds, in both views where we wrote both. A Proton
|
||||
# update replaces its default_pfx system.reg but not our ledger beside it, and new prefixes copy both.
|
||||
present() { awk -F'\t' '
|
||||
NR == FNR {
|
||||
path = $1
|
||||
if (path != "vcrt") {
|
||||
sub(/^HKEY_LOCAL_MACHINE\\\\/, "", path)
|
||||
if (path == $1)
|
||||
next
|
||||
}
|
||||
n++
|
||||
line[n] = $0
|
||||
need[n] = 0
|
||||
if (path == "vcrt") {
|
||||
for (a = split("x86 x64 arm64", arch, " "); a > 0; a--) {
|
||||
runtime = "microsoft\\\\visualstudio\\\\14.0\\\\vc\\\\runtimes\\\\" arch[a]
|
||||
key[n, ++need[n]] = "[software\\\\" runtime "]" SUBSEP "installed"
|
||||
key[n, ++need[n]] = "[software\\\\wow6432node\\\\" runtime "]" SUBSEP "installed"
|
||||
}
|
||||
} else {
|
||||
both = substr(path, 1, 10) == "Software\\\\"
|
||||
path = tolower(path)
|
||||
key[n, ++need[n]] = "[" path "]" SUBSEP tolower($2)
|
||||
if (both)
|
||||
key[n, ++need[n]] = "[software\\\\wow6432node\\\\" substr(path, 11) "]" SUBSEP tolower($2)
|
||||
}
|
||||
for (j = 1; j <= need[n]; j++) wanted[key[n, j]] = 1
|
||||
next
|
||||
}
|
||||
/^\[/ { section = tolower(substr($0, 1, index($0, "]"))) }
|
||||
/^"/ {
|
||||
value = substr($0, 2)
|
||||
value = tolower(substr(value, 1, index(value, "\"=") - 1))
|
||||
if ((section SUBSEP value) in wanted)
|
||||
seen[section SUBSEP value] = 1
|
||||
}
|
||||
END {
|
||||
for (i = 1; i <= n; i++) {
|
||||
ok = 1
|
||||
for (j = 1; j <= need[i]; j++) if (!(key[i, j] in seen)) ok = 0
|
||||
if (ok) print line[i]
|
||||
}
|
||||
}
|
||||
' - "$1"; }
|
||||
|
||||
for reg in "$steam_root"/steamapps/common/Proton*/files/share/default_pfx*/system.reg \
|
||||
/mnt/droiddeck-sd/steamapps/common/Proton*/files/share/default_pfx*/system.reg \
|
||||
/root/Games/*/steamapps/common/Proton*/files/share/default_pfx*/system.reg \
|
||||
@@ -166,6 +211,17 @@ for reg in "$steam_root"/steamapps/common/Proton*/files/share/default_pfx*/syste
|
||||
printf '%s\n' "${kept[@]}" >"$seeded"
|
||||
echo "== took Vulkan runtime markers out of $reg"
|
||||
fi
|
||||
if [ ${#had[@]} -gt 0 ]; then
|
||||
declare -A held=()
|
||||
while IFS= read -r line; do [[ $line == *$'\t'* ]] && held[$line]=1; done < <(printf '%s\n' "${!had[@]}" | present "$reg")
|
||||
if [ ${#held[@]} -lt ${#had[@]} ]; then
|
||||
echo "== $((${#had[@]} - ${#held[@]})) recorded redist markers are gone from $reg"
|
||||
had=()
|
||||
for line in "${!held[@]}"; do had[$line]=1; done
|
||||
printf '%s\n' "${!had[@]}" >"$seeded"
|
||||
fi
|
||||
unset held
|
||||
fi
|
||||
missing=()
|
||||
for line in "${want[@]}"; do [ -n "${had[$line]:-}" ] || missing+=("$line"); done
|
||||
[ ${#missing[@]} -eq 0 ] && continue
|
||||
|
||||
@@ -100,6 +100,53 @@ class SeedRedistsTest(unittest.TestCase):
|
||||
self.run_seed()
|
||||
self.assertIn('"VCRedist2022"=dword:00000001', self.reg.read_text())
|
||||
|
||||
def test_markers_a_replaced_registry_lost_are_seeded_again(self):
|
||||
self.game()
|
||||
stock = self.reg.read_text()
|
||||
self.run_seed()
|
||||
ledger = (self.reg.parent / ".droiddeck-redists").read_text()
|
||||
self.assertIn("VCRedist2022", ledger)
|
||||
self.reg.write_text(stock)
|
||||
self.run_seed()
|
||||
reg = self.reg.read_text()
|
||||
self.assertEqual(reg.count('"VCRedist2022"=dword:00000001'), 2, "both views again")
|
||||
self.assertIn("[Software\\\\Microsoft\\\\VisualStudio\\\\14.0\\\\VC\\\\Runtimes\\\\x86]", reg)
|
||||
self.assertEqual(sorted((self.reg.parent / ".droiddeck-redists").read_text().splitlines()), sorted(ledger.splitlines()))
|
||||
self.run_seed()
|
||||
self.assertEqual(reg, self.reg.read_text())
|
||||
|
||||
def test_a_marker_kept_in_only_one_view_is_seeded_again(self):
|
||||
self.game()
|
||||
self.run_seed()
|
||||
wow = "[Software\\\\Wow6432Node\\\\Valve\\\\Steam\\\\Apps\\\\CommonRedist\\\\vcredist\\\\2022]"
|
||||
blocks = self.reg.read_text().split("\n\n")
|
||||
self.reg.write_text("\n\n".join(b for b in blocks if not (b.startswith(wow) and '"VCRedist2022"' in b)))
|
||||
self.assertEqual(self.reg.read_text().count('"VCRedist2022"'), 1)
|
||||
self.run_seed()
|
||||
reg = self.reg.read_text()
|
||||
self.assertEqual(reg.count('"VCRedist2022"'), 3, "the one left plus both views again")
|
||||
self.assertTrue(any(b.startswith(wow) and '"VCRedist2022"' in b for b in reg.split("\n\n")))
|
||||
|
||||
def test_a_vc_runtime_another_architecture_lost_is_seeded_again(self):
|
||||
self.run_seed()
|
||||
arm64 = "[Software\\\\Wow6432Node\\\\Microsoft\\\\VisualStudio\\\\14.0\\\\VC\\\\Runtimes\\\\arm64]"
|
||||
blocks = self.reg.read_text().split("\n\n")
|
||||
self.reg.write_text("\n\n".join(b for b in blocks if not b.startswith(arm64)))
|
||||
self.assertNotIn(arm64, self.reg.read_text())
|
||||
self.run_seed()
|
||||
reg = self.reg.read_text()
|
||||
self.assertIn(arm64, reg)
|
||||
self.assertEqual(reg.count("[Software\\\\Microsoft\\\\VisualStudio\\\\14.0\\\\VC\\\\Runtimes\\\\x86]"), 2)
|
||||
|
||||
def test_a_marker_written_in_one_view_only_is_kept_as_it_is(self):
|
||||
self.game(script=GAME_SCRIPT.replace("Software\\\\Valve\\\\Steam\\\\Apps\\\\CommonRedist\\\\vcredist\\\\2022", "SOFTWARE\\\\AGEIA Technologies").replace("VCRedist2022", "PhysX Version"))
|
||||
self.run_seed()
|
||||
once = self.reg.read_text()
|
||||
self.assertEqual(once.count('"PhysX Version"=dword:00000001'), 1)
|
||||
result = self.run_seed()
|
||||
self.assertEqual(once, self.reg.read_text())
|
||||
self.assertNotIn("gone", result.stdout)
|
||||
|
||||
def test_an_evaluator_script_nested_deeper_is_read(self):
|
||||
script = self.tmp / "legacycompat/evaluatorscript_409710.vdf"
|
||||
script.parent.mkdir(parents=True)
|
||||
|
||||
Reference in new issue
Block a user