Skip to content

Commit 63ecef4

Browse files
authored
Merge pull request #39 from RetroDECK/cooker [skip ci]
Cooker [skip ci]
2 parents 059d510 + a7eabdc commit 63ecef4

6 files changed

Lines changed: 469 additions & 2 deletions

File tree

archive_later/ecwolf/component_launcher.sh

Lines changed: 384 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -12,4 +12,387 @@ log d "QT plugin path is: $QT_PLUGIN_PATH"
1212
log d "QT QPA PLATFORM plugin path is: $QT_QPA_PLATFORM_PLUGIN_PATH"
1313

1414
# Launch
15-
exec "$component_path/bin/ecwolf" --fullscreen --nowait --config /var/config/ecwolf/ecwolf_rd.cfg --savesdir /var/data/ecwolf/saves "$@"
15+
log i "RetroDECK ECWolf Runner"
16+
path="${@: -1}" # getting the last argument as game path
17+
args="${@:1:$#-1}" # getting all the other passed args
18+
19+
append_wolf_data_files() {
20+
local folder="$1"
21+
local ext
22+
local file
23+
24+
[[ -d "$folder" ]] || return 1
25+
26+
for ext in wl6 wl1 sdm sod n3d; do
27+
shopt -s nullglob
28+
for file in "$folder"/*."$ext"; do
29+
[[ -f "$file" ]] || continue
30+
args="$args --file \"$file\""
31+
done
32+
shopt -u nullglob
33+
done
34+
}
35+
36+
# Identify Wolf3D version by core files in folder
37+
# Requests: gamemaps, maphead, vswap with an extension.
38+
# Preference order: wl6, wl1, sdm, sod, sd1, sd2, sd3, n3d.
39+
# Returns version name (wl6/wl1/sdm/sod/sd1/sd2/sd3/n3d) or failure.
40+
detect_wolf3d_version() {
41+
local folder="$1"
42+
[[ -d "$folder" ]] || return 1
43+
44+
local versions=(wl6 wl1 sdm sod sd1 sd2 sd3 n3d)
45+
46+
for version in "${versions[@]}"; do
47+
local gamemaps_file
48+
local maphead_file
49+
local vswap_file
50+
51+
gamemaps_file=$(find "$folder" -maxdepth 1 -type f -iname "gamemaps.$version" -print -quit 2>/dev/null)
52+
maphead_file=$(find "$folder" -maxdepth 1 -type f -iname "maphead.$version" -print -quit 2>/dev/null)
53+
vswap_file=$(find "$folder" -maxdepth 1 -type f -iname "vswap.$version" -print -quit 2>/dev/null)
54+
55+
if [[ -n "$gamemaps_file" && -n "$maphead_file" && -n "$vswap_file" ]]; then
56+
if validate_wolf3d_version_hash "$folder" "$version"; then
57+
printf '%s' "$version"
58+
return 0
59+
else
60+
log d "Version '$version' rejected for '$folder' because hash validation failed"
61+
fi
62+
fi
63+
done
64+
65+
return 1
66+
}
67+
68+
pretty_wolf3d_version() {
69+
local version="${1,,}"
70+
case "$version" in
71+
wl6) echo "Wolfenstein 3D (Full)" ;;
72+
wl1) echo "Wolfenstein 3D (Shareware)" ;;
73+
sdm) echo "Spear of Destiny (Demo)" ;;
74+
sod) echo "Spear of Destiny (Full)" ;;
75+
sd1) echo "Spear of Destiny - Mission Pack 1 - Return to Danger" ;;
76+
sd2) echo "Spear of Destiny - Mission Pack 2 - Return to Danger" ;;
77+
sd3) echo "Spear of Destiny - Mission Pack 3 - Ultimate Challenge" ;;
78+
n3d) echo "Super 3D Noah’s Ark" ;;
79+
*) echo "Unknown Wolf3D version: $version" ;;
80+
esac
81+
}
82+
83+
# Known IWAD hash fixtures for core file trio to avoid false positives in mod folders.
84+
# (Source: ECWolf docs, checked on Wolfenstein 3D / Spear of Destiny / Noah's Ark)
85+
declare -A wolf3d_data_hashes
86+
wolf3d_data_hashes=(
87+
[wl6.gamemaps]="a4e73706e100dc0cadfb02d23de46481"
88+
[wl6.maphead]="b8d2a78bc7c50da7ec9ab1d94f7975e1"
89+
# Support both canonical and alternate WL6 vswap variants observed in field
90+
[wl6.vswap]="b8ff4997461bafa5ef2a94c11f9de001 a6d901dfb455dfac96db5e4705837cdb"
91+
92+
[wl1.gamemaps]="30fecd7cce6bc70402651ec922d2da3d"
93+
[wl1.maphead]="7b6dd4e55c33c33a41d1600be5df3228"
94+
[wl1.vswap]="6efa079414b817c97db779cecfb081c9"
95+
96+
[sdm.gamemaps]="4eb2f538aab6e4061dadbc3b73837762"
97+
[sdm.maphead]="40fa03caf7a1a4dbd22da4321c6e10d4"
98+
[sdm.vswap]="35afda760bea840b547d686a930322dc"
99+
100+
[sod.gamemaps]="04f16534235b4b57fc379d5709f88f4a"
101+
[sod.maphead]="276c79a4a6419db6b23e7699e41cb9fa"
102+
[sod.vswap]="b1dac0a8786c7cdbb09331a4eba00652"
103+
104+
[sd2.gamemaps]="d55508cd58e2e61076ac81b98aeb9269"
105+
[sd2.maphead]="25d92ac0ba012a1e9335c747eb4ab177"
106+
[sd2.vswap]="fa5752c5b1e25ee5c4a9ec0e9d4013a9"
107+
108+
[sd3.gamemaps]="4219d83568d770b1c6ac9c2d4d1dfb9e"
109+
[sd3.maphead]="52fd50245a77e61dc1df91110c186195"
110+
[sd3.vswap]="e3e87518f51414872c454b7d72a45af6"
111+
112+
[sd3-alt.gamemaps]="29860b87c31348e163e10f8aa6f19295"
113+
[sd3-alt.maphead]="a8b24dd3d3271e0b7fc6f2f995915f27"
114+
[sd3-alt.vswap]="94aeef7980ef640c448087f92be16d83"
115+
116+
[n3d.gamemaps]="d35ce2257a4fb56f61529df5f7f77adb"
117+
[n3d.maphead]="2eaab4dd50856abeaebe75a8bcbbab42"
118+
[n3d.vswap]="8c61a9b3bb38a598990ccb743d2679fa"
119+
)
120+
121+
expected_wolf3d_hash() {
122+
local version="$1" file="$2" key
123+
key="$version.$file"
124+
# support alternate sd3 variant too
125+
[[ -n "${wolf3d_data_hashes[$key]:-}" ]] && printf '%s' "${wolf3d_data_hashes[$key]}" && return 0
126+
if [[ "$version" == "sd3" ]]; then
127+
key="sd3-alt.$file"
128+
[[ -n "${wolf3d_data_hashes[$key]:-}" ]] && printf '%s' "${wolf3d_data_hashes[$key]}" && return 0
129+
fi
130+
return 1
131+
}
132+
133+
validate_wolf3d_version_hash() {
134+
local folder="$1" version="$2"
135+
local md5cmd
136+
md5cmd=$(command -v md5sum || true)
137+
if [[ -z "$md5cmd" ]]; then
138+
log w "md5sum not found, version detection will proceed by filenames only"
139+
return 0
140+
fi
141+
142+
for file in gamemaps maphead vswap; do
143+
# case-insensitive path resolution, because actual files may use uppercase extensions/names
144+
local path
145+
path=$(find "$folder" -maxdepth 1 -type f -iname "${file}.${version}" -print -quit 2>/dev/null)
146+
[[ -n "$path" ]] || return 1
147+
148+
local expected
149+
expected=$(expected_wolf3d_hash "$version" "$file")
150+
if [[ -z "$expected" ]]; then
151+
log d "Hash not available for $file.$version, rejecting wildcard match to avoid mod false positive"
152+
return 1
153+
fi
154+
155+
local actual
156+
actual=$($md5cmd "$path" | awk '{print tolower($1)}')
157+
158+
local match=0
159+
for allowed in $expected; do
160+
if [[ "$actual" == "$allowed" ]]; then
161+
match=1
162+
break
163+
fi
164+
done
165+
166+
if (( match == 0 )); then
167+
log d "Hash mismatch for $path ($version): expected one of [$expected], got $actual"
168+
return 1
169+
fi
170+
done
171+
172+
# If we reached here, all three core files matched expected hashes
173+
return 0
174+
}
175+
176+
# Normalize user-provided Wolf3D version keys from .wolf data= values.
177+
normalize_wolf3d_version_key() {
178+
local input="${1,,}"
179+
input="${input//\"/}"
180+
input="${input//\'/}"
181+
input="${input//[[:space:]]/}"
182+
input="${input//[^a-z0-9]/}"
183+
184+
case "$input" in
185+
wl6|wolfenstein3dfull|wolfensteinfull|full) echo wl6 ;;
186+
wl1|shareware|wolfenstein3dshareware|shareware) echo wl1 ;;
187+
sdm|spearofdestinydemo|speardestinydemo) echo sdm ;;
188+
sod|spearofdestinyfull|speardestinyfull) echo sod ;;
189+
sd1|missionpack1|returntodanger) echo sd1 ;;
190+
sd2|missionpack2|returntodanger2) echo sd2 ;;
191+
sd3|missionpack3|ultimatechallenge) echo sd3 ;;
192+
n3d|super3dnoahsark|noahsark) echo n3d ;;
193+
*) return 1 ;;
194+
esac
195+
}
196+
197+
# Find a wolf3d data folder under $root, optionally enforcing a preferred version.
198+
# Mode "default" uses legacy priority: wl6 -> wl1 -> sdm -> sod -> sd1 -> sd2 -> sd3 -> n3d.
199+
# Mode "mod" uses mod-friendly order (full/packs first, shareware last): wl6 -> sod -> sd1 -> sd2 -> sd3 -> n3d -> sdm -> wl1.
200+
find_wolf3d_wolf_folder() {
201+
local root="${1:-${roms_path}/wolf}"
202+
local preferred_version="${2:-}"
203+
local mode="${3:-default}"
204+
205+
[[ -d "$root" ]] || return 1
206+
207+
local -A version_rank
208+
if [[ "$mode" == "mod" ]]; then
209+
version_rank=( [wl6]=1 [sod]=2 [sd1]=3 [sd2]=4 [sd3]=5 [n3d]=6 [sdm]=7 [wl1]=8 )
210+
else
211+
version_rank=( [wl6]=1 [wl1]=2 [sdm]=3 [sod]=4 [sd1]=5 [sd2]=6 [sd3]=7 [n3d]=8 )
212+
fi
213+
214+
local best_path="" best_rank=999
215+
216+
for candidate in "$root"/*.wolf; do
217+
[[ -d "$candidate" ]] || continue
218+
if [[ -n "$preferred_version" ]]; then
219+
version="$(detect_wolf3d_version "$candidate")" || continue
220+
if [[ "$version" != "$preferred_version" ]]; then
221+
continue
222+
fi
223+
wolf3d_data_version="$version"
224+
printf '%s' "$candidate"
225+
return 0
226+
fi
227+
228+
version="$(detect_wolf3d_version "$candidate")" || continue
229+
local rank=${version_rank[$version]:-999}
230+
if (( rank < best_rank )); then
231+
best_rank=$rank
232+
best_path="$candidate"
233+
wolf3d_data_version="$version"
234+
fi
235+
done
236+
237+
if [[ -n "$best_path" ]]; then
238+
printf '%s' "$best_path"
239+
return 0
240+
fi
241+
242+
# last chance: maybe root itself is an IWAD folder
243+
if version="$(detect_wolf3d_version "$root")"; then
244+
if [[ -z "$preferred_version" || "$version" == "$preferred_version" ]]; then
245+
wolf3d_data_version="$version"
246+
printf '%s' "$root"
247+
return 0
248+
fi
249+
fi
250+
251+
return 1
252+
}
253+
254+
# Start launcher mode selection
255+
raw_args=( "${@:1:$#-1}" )
256+
input_path="${@: -1}"
257+
258+
if [[ -z "$input_path" ]]; then
259+
log e "No game path argument provided"
260+
exit 1
261+
fi
262+
263+
if [[ -f "$input_path" && "${input_path##*.}" == "wolf" ]]; then
264+
# mod descriptor path
265+
mod_wolf_file="$input_path"
266+
mod_folder="$(dirname "$mod_wolf_file")"
267+
log i "Mod descriptor provided: $mod_wolf_file"
268+
269+
mod_files=()
270+
mod_data_override=""
271+
while IFS= read -r line || [[ -n "$line" ]]; do
272+
line="${line%%#*}"
273+
line="${line#${line%%[![:space:]]*}}"
274+
line="${line%${line##*[![:space:]]}}"
275+
[[ -z "$line" ]] && continue
276+
277+
if [[ "${line,,}" =~ ^data[[:space:]]*=[[:space:]]*(.+)$ ]]; then
278+
raw_data="${BASH_REMATCH[1]}"
279+
if ! mod_data_override="$(normalize_wolf3d_version_key "$raw_data")"; then
280+
log e "Invalid data= value '$raw_data' in '$mod_wolf_file'"
281+
exit 1
282+
fi
283+
log i "Mod descriptor requests base IWAD '$mod_data_override'"
284+
continue
285+
fi
286+
287+
mod_files+=("$line")
288+
done < "$mod_wolf_file"
289+
290+
if [[ -n "$mod_data_override" ]]; then
291+
iwad_folder="$(find_wolf3d_wolf_folder "$roms_path/wolf" "$mod_data_override" "mod")" || {
292+
log e "Base IWAD '$mod_data_override' specified in '$mod_wolf_file' not found in $roms_path/wolf"
293+
exit 1
294+
}
295+
elif [[ ${#mod_files[@]} -gt 0 ]]; then
296+
iwad_folder="$(find_wolf3d_wolf_folder "$roms_path/wolf" "wl6" "mod")" || {
297+
log e "No default WL6 IWAD found for mod; mod requires at least one valid base IWAD"
298+
exit 1
299+
}
300+
else
301+
iwad_folder="$(find_wolf3d_wolf_folder "$roms_path/wolf" "" "mod")" || {
302+
log e "No IWAD found in $roms_path/wolf"
303+
exit 1
304+
}
305+
fi
306+
307+
version="$(detect_wolf3d_version "$iwad_folder")"
308+
wolf3d_data_version_pretty="$(pretty_wolf3d_version "$version")"
309+
log i "Mod mode: base IWAD set to '$iwad_folder' (found $wolf3d_data_version_pretty)"
310+
311+
requested_mod_files=()
312+
if [[ ${#mod_files[@]} -gt 0 ]]; then
313+
for mod_entry in "${mod_files[@]}"; do
314+
if [[ "$mod_entry" == /* ]]; then
315+
requested_mod_files+=( --file "$mod_entry" )
316+
else
317+
requested_mod_files+=( --file "$mod_folder/$mod_entry" )
318+
fi
319+
done
320+
launch_folder="$iwad_folder"
321+
else
322+
launch_folder="$mod_folder"
323+
fi
324+
325+
elif [[ -d "$input_path" ]]; then
326+
version="$(detect_wolf3d_version "$input_path")" || true
327+
if [[ -n "$version" ]]; then
328+
iwad_folder="$input_path"
329+
wolf3d_data_version_pretty="$(pretty_wolf3d_version "$version")"
330+
log i "IWAD mode: launching '$iwad_folder' (detected $wolf3d_data_version_pretty)"
331+
launch_folder="$iwad_folder"
332+
else
333+
# directory could be a mod container with same-name .wolf file
334+
candidate_mod_file="$input_path/$(basename "$input_path").wolf"
335+
if [[ -f "$candidate_mod_file" ]]; then
336+
input_path="$candidate_mod_file"
337+
# Re-run by calling this script recursively avoids duplication; but to keep it simple, we follow same logic inline.
338+
mod_wolf_file="$candidate_mod_file"
339+
mod_folder="$input_path"
340+
# fallback to using this .wolf logic path
341+
# no recursive here to avoid complexity; if we reach this path we can proceed as mod with input_path set
342+
# (this scenario should be rare in Data layout)
343+
# We don't re-enter the if block, continue with auto-detect using mod_wolf_file below.
344+
else
345+
log i "No IWAD detected in '$input_path', auto-detecting under $roms_path/wolf"
346+
iwad_folder="$(find_wolf3d_wolf_folder "$roms_path/wolf")" || {
347+
log e "No valid Wolf3D data folder found under $roms_path/wolf"
348+
exit 1
349+
}
350+
version="$(detect_wolf3d_version "$iwad_folder")"
351+
wolf3d_data_version_pretty="$(pretty_wolf3d_version "$version")"
352+
log i "Auto-detected IWAD '$iwad_folder' ($wolf3d_data_version_pretty)"
353+
launch_folder="$iwad_folder"
354+
fi
355+
fi
356+
else
357+
log i "Input path '$input_path' not a file or directory; auto-detecting IWAD in $roms_path/wolf"
358+
iwad_folder="$(find_wolf3d_wolf_folder "$roms_path/wolf")" || {
359+
log e "No valid Wolf3D data folder found under $roms_path/wolf"
360+
exit 1
361+
}
362+
version="$(detect_wolf3d_version "$iwad_folder")"
363+
wolf3d_data_version_pretty="$(pretty_wolf3d_version "$version")"
364+
log i "Auto-detected IWAD '$iwad_folder' ($wolf3d_data_version_pretty)"
365+
launch_folder="$iwad_folder"
366+
fi
367+
368+
# If we didn't set launch_folder yet (e.g. mod path without explicit file entries), use iwad_folder
369+
launch_folder="${launch_folder:-$iwad_folder}"
370+
371+
if [[ -z "$launch_folder" || ! -d "$launch_folder" ]]; then
372+
log e "Nessuna cartella di avvio valida trovata"
373+
exit 1
374+
fi
375+
376+
# Always use requested base options and preserved args.
377+
args=( "${raw_args[@]}" )
378+
379+
if [[ ${#requested_mod_files[@]} -gt 0 ]]; then
380+
args+=( "${requested_mod_files[@]}" )
381+
fi
382+
383+
if [[ -n "$main_game" ]]; then
384+
args+=( "$main_game" )
385+
fi
386+
387+
# Log command line internal representation
388+
if [[ ${#args[@]} -gt 0 ]]; then
389+
log i "With args: ${args[*]}"
390+
fi
391+
392+
# Final command
393+
log d "Executing: \"$component_path/bin/ecwolf\" --fullscreen --nowait --config /var/config/ecwolf/ecwolf_rd.cfg --savedir /var/data/ecwolf/saves ${args[*]}"
394+
395+
cd "$launch_folder" || exit 1
396+
log i "Running from $launch_folder"
397+
exec "$component_path/bin/ecwolf" --fullscreen --nowait --config /var/config/ecwolf/ecwolf_rd.cfg --savedir /var/data/ecwolf/saves "${args[@]}"
398+
cd -

0 commit comments

Comments
 (0)