From 3af15759757a6d5583230a882aa93ca683553212 Mon Sep 17 00:00:00 2001 From: Zacharias Xenakis Date: Tue, 10 Nov 2026 23:36:06 +0200 Subject: [PATCH 1/4] Add --progress-lines for launchers that read setup progress An opt-in output mode for the setup install: `--silent ... --progress-lines` on Windows and `install ... --progress-lines` on Linux print `progress <0-1> ` lines on stdout, with diagnostics on stderr, and report the outcome in the exit code. This is the line format RecompLauncher reads from a windowless setup step. Without the flag, setup behaves exactly as before. --- .../InstallProgress.cs | 34 +++++++++++++++++++ Launcher/WiiCompiled.Setup.Linux/Program.cs | 13 +++++-- .../WiiCompiled.Setup.Windows/CommandLine.cs | 8 ++++- .../ConsoleCommands.cs | 5 ++- .../WiiCompiled.Setup.Windows/SelfTests.cs | 10 ++++++ 5 files changed, 66 insertions(+), 4 deletions(-) diff --git a/Launcher/WiiCompiled.Setup.Common/InstallProgress.cs b/Launcher/WiiCompiled.Setup.Common/InstallProgress.cs index 1650d98df..84895ff23 100644 --- a/Launcher/WiiCompiled.Setup.Common/InstallProgress.cs +++ b/Launcher/WiiCompiled.Setup.Common/InstallProgress.cs @@ -95,6 +95,40 @@ private static void WriteLine(object value) } } +/// +/// The --progress-lines format RecompLauncher reads from a setup step: one +/// progress <0 to 1> <text> line per update on stdout, diagnostics on stderr. The +/// outcome is the exit code. +/// +public sealed class LauncherProgressInstallReporter : IInstallReporter +{ + private readonly Action? _log; + private readonly object _gate = new(); + private int _lastPercent; + + public LauncherProgressInstallReporter(Action? log = null) => _log = log; + + public void Progress(string stage, string message, int percent) + { + lock (_gate) + { + // Monotonic, like the NDJSON reporter: the bar never walks backwards. + _lastPercent = Math.Clamp(Math.Max(percent, _lastPercent), 0, 99); + var text = message.ReplaceLineEndings(" ").Trim(); + Console.Out.WriteLine(string.Create(System.Globalization.CultureInfo.InvariantCulture, + $"progress {_lastPercent / 100.0:0.00} {text}")); + Console.Out.Flush(); + } + _log?.Invoke(message); + } + + public void Diagnostic(string line) + { + Console.Error.WriteLine(line); + _log?.Invoke(line); + } +} + /// Plain-text console reporting for a run without --progress-json. public sealed class ConsoleInstallReporter : IInstallReporter { diff --git a/Launcher/WiiCompiled.Setup.Linux/Program.cs b/Launcher/WiiCompiled.Setup.Linux/Program.cs index 3eea85ba5..efe7ff825 100644 --- a/Launcher/WiiCompiled.Setup.Linux/Program.cs +++ b/Launcher/WiiCompiled.Setup.Linux/Program.cs @@ -31,7 +31,15 @@ private static async Task RunAsync(string[] args, CancellationTokenSource c var (command, flags) = ParseArgs(args); if (command is null) { PrintUsage(); return 1; } var progressJson = flags.ContainsKey("progress-json"); - IInstallReporter reporter = progressJson ? new NdjsonInstallReporter(ProductInfo.Version) : new ConsoleInstallReporter(); + var progressLines = flags.ContainsKey("progress-lines"); + if (progressJson && progressLines) + { + Console.Error.WriteLine("error: Choose only one of --progress-json and --progress-lines."); + return 1; + } + IInstallReporter reporter = progressJson ? new NdjsonInstallReporter(ProductInfo.Version) + : progressLines ? (IInstallReporter)new LauncherProgressInstallReporter() + : new ConsoleInstallReporter(); try { @@ -361,7 +369,8 @@ install [--game ISO_PATH] [--install-dir DIR] [--retro-dir DIR {--download-retro-wfc-payload | --skip-retro-wfc-payload}] [--force-clean-build] [--translator-bin PATH] [--disc-tool-bin PATH] [--cc PATH] [--cxx PATH] [--fuse-ld NAME_OR_PATH] [--cmake PATH] [--ninja PATH] - [--native-prebuilt-dir DIR] [--sysroot PATH] [--progress-json] [--workspace DIR] + [--native-prebuilt-dir DIR] [--sysroot PATH] [--workspace DIR] + [--progress-json | --progress-lines] uninstall launch-base launch-retro diff --git a/Launcher/WiiCompiled.Setup.Windows/CommandLine.cs b/Launcher/WiiCompiled.Setup.Windows/CommandLine.cs index 14cd66409..4352a3e78 100644 --- a/Launcher/WiiCompiled.Setup.Windows/CommandLine.cs +++ b/Launcher/WiiCompiled.Setup.Windows/CommandLine.cs @@ -25,6 +25,7 @@ internal sealed record ModeRules { public string Flag { get; init; } = "this command"; public bool AcceptsProgressJson { get; init; } + public bool AcceptsProgressLines { get; init; } public bool AcceptsGame { get; init; } public bool RequiresGame { get; init; } public bool AcceptsRetroDirectory { get; init; } @@ -44,6 +45,7 @@ internal sealed class CommandLine public string? InstallDirectory { get; private set; } public bool Quiet { get; private set; } public bool ProgressJson { get; private set; } + public bool ProgressLines { get; private set; } public string? PayloadRootPath { get; private set; } public bool Portable { get; private set; } @@ -73,6 +75,7 @@ public static CommandLine Parse(string[] args) case "--payload-root": result.PayloadRootPath = RequireValue(args, ref i); break; case "--quiet": result.Quiet = true; break; case "--progress-json": result.ProgressJson = true; break; + case "--progress-lines": result.ProgressLines = true; break; case "--game": result.GamePath = RequireValue(args, ref i); break; case "--retro-dir": result.RetroDirectoryPath = RequireValue(args, ref i); break; case "--download-retro-wfc-payload": @@ -100,7 +103,7 @@ public static CommandLine Parse(string[] args) [AppMode.SilentInstall] = new ModeRules { Flag = "--silent", - AcceptsProgressJson = true, AcceptsGame = true, RequiresGame = true, + AcceptsProgressJson = true, AcceptsProgressLines = true, AcceptsGame = true, RequiresGame = true, AcceptsRetroDirectory = true, AcceptsPayloadMode = true, AcceptsPortable = true }, @@ -149,6 +152,9 @@ void Reject(bool present, string option) Reject(GamePath is not null && !rules.AcceptsGame, "--game"); Reject(RetroDirectoryPath is not null && !rules.AcceptsRetroDirectory, "--retro-dir"); Reject(ProgressJson && !rules.AcceptsProgressJson, "--progress-json"); + Reject(ProgressLines && !rules.AcceptsProgressLines, "--progress-lines"); + if (ProgressJson && ProgressLines) + throw new ArgumentException("Choose only one of --progress-json and --progress-lines."); Reject(PayloadRootPath is not null && !rules.RequiresPayloadRoot, "--payload-root"); Reject(Portable && !rules.AcceptsPortable, "--portable"); Reject(RetroWfcPayloadMode != RetroWfcPayloadMode.NotApplicable && !rules.AcceptsPayloadMode, diff --git a/Launcher/WiiCompiled.Setup.Windows/ConsoleCommands.cs b/Launcher/WiiCompiled.Setup.Windows/ConsoleCommands.cs index 02ab9a2a2..6fd00d0c0 100644 --- a/Launcher/WiiCompiled.Setup.Windows/ConsoleCommands.cs +++ b/Launcher/WiiCompiled.Setup.Windows/ConsoleCommands.cs @@ -12,6 +12,7 @@ public static int Help() Console.Out.WriteLine(); Console.Out.WriteLine("Commands:"); Console.Out.WriteLine(" --silent --game --install-dir [--retro-dir ] [--portable]"); + Console.Out.WriteLine(" [--progress-json | --progress-lines]"); Console.Out.WriteLine(" --verify-inputs --game [--retro-dir ]"); Console.Out.WriteLine(" --check-products [--install-dir ] [--retro-dir ] [--progress-json]"); Console.Out.WriteLine(" --repair-products --install-dir --retro-dir " + @@ -106,7 +107,9 @@ void Log(string message) File.WriteAllText(logPath, $"{ProductInfo.Name} setup {ProductInfo.Version}{Environment.NewLine}"); var ndjson = command.ProgressJson ? new NdjsonInstallReporter(ProductInfo.Version, Log) : null; - IInstallReporter reporter = ndjson ?? (IInstallReporter)new ConsoleInstallReporter(Log); + IInstallReporter reporter = ndjson ?? (command.ProgressLines + ? (IInstallReporter)new LauncherProgressInstallReporter(Log) + : new ConsoleInstallReporter(Log)); var installDirectory = Path.GetFullPath(command.InstallDirectory!); try { diff --git a/Launcher/WiiCompiled.Setup.Windows/SelfTests.cs b/Launcher/WiiCompiled.Setup.Windows/SelfTests.cs index f688a8acd..dcffe7ed4 100644 --- a/Launcher/WiiCompiled.Setup.Windows/SelfTests.cs +++ b/Launcher/WiiCompiled.Setup.Windows/SelfTests.cs @@ -543,6 +543,16 @@ void Rejects(string description, params string[] args) if (portable.Mode != AppMode.SilentInstall || !portable.Portable) throw new Exception("The portable install contract did not parse."); + var lines = CommandLine.Parse([ + "--silent", "--game", "game.iso", "--install-dir", "D:\\Games\\Recomp\\Install", + "--portable", "--progress-lines" + ]); + if (lines.Mode != AppMode.SilentInstall || !lines.ProgressLines || lines.ProgressJson) + throw new Exception("The progress-lines install contract did not parse."); + Rejects("--progress-lines with --progress-json", "--silent", "--game", "g.iso", + "--progress-lines", "--progress-json"); + Rejects("--progress-lines outside an install", "--check-products", "--progress-lines"); + Rejects("--portable without an install directory", "--silent", "--game", "g.iso", "--portable"); Rejects("--portable outside an install", "--check-products", "--install-dir", "fixed", "--portable"); // The config verbs are gone: WheelWizard reads and writes Config.toml directly now. From 9205e65dfb9634282397850429523f088d375d14 Mon Sep 17 00:00:00 2001 From: Zacharias Xenakis Date: Tue, 10 Nov 2026 23:38:39 +0200 Subject: [PATCH 2/4] Add recomplauncher.json and ship it in the releases RecompLauncher can set this recomp up from the player's own disc image, show its video and audio settings and start it, using the existing setup CLI. - Launcher/recomplauncher/windows.json and linux.json describe the setup step (--silent / install with --progress-lines), the launch (--launch-base / launch-base), the Config.toml settings, saves and logs. - Windows: the release also carries WiiCompiled-Setup-windows-x64.zip, with WiiCompiled-Setup.exe and recomplauncher.json at the top. The .exe asset is unchanged. - Linux: build-appimage.sh puts recomplauncher.json at the AppImage root. --- .github/workflows/package.yml | 20 ++++- Launcher/build-appimage.sh | 3 + Launcher/recomplauncher/linux.json | 118 +++++++++++++++++++++++++++ Launcher/recomplauncher/windows.json | 118 +++++++++++++++++++++++++++ 4 files changed, 258 insertions(+), 1 deletion(-) create mode 100644 Launcher/recomplauncher/linux.json create mode 100644 Launcher/recomplauncher/windows.json diff --git a/.github/workflows/package.yml b/.github/workflows/package.yml index 1acefe9d4..f6a8daa63 100644 --- a/.github/workflows/package.yml +++ b/.github/workflows/package.yml @@ -97,6 +97,24 @@ jobs: if-no-files-found: error archive: false + # The same setup, zipped with the recomplauncher.json RecompLauncher reads, so it unpacks into + # its own folder instead of being run as an installer. WiiCompiled-Setup.exe stays as it is. + - name: Zip for RecompLauncher + shell: pwsh + run: | + $stage = Join-Path $env:RUNNER_TEMP 'recomplauncher-zip' + New-Item -ItemType Directory -Force -Path $stage | Out-Null + Copy-Item Launcher/dist/WiiCompiled-Setup.exe $stage + Copy-Item Launcher/recomplauncher/windows.json (Join-Path $stage 'recomplauncher.json') + Compress-Archive -Path (Join-Path $stage '*') -DestinationPath Launcher/dist/WiiCompiled-Setup-windows-x64.zip + + - uses: actions/upload-artifact@v7 + with: + name: WiiCompiled-Setup-windows-x64-zip + path: Launcher/dist/WiiCompiled-Setup-windows-x64.zip + if-no-files-found: error + archive: false + macos-setup-package: name: macOS (universal Setup.pkg) runs-on: macos-15 @@ -307,7 +325,7 @@ jobs: set -euo pipefail ls -lR artifacts assets=() - for name in WiiCompiled-Setup.exe WiiCompiled-Setup-x86_64.AppImage WiiCompiled-Setup-aarch64.AppImage WiiCompiled-Setup.pkg WiiCompiled-Setup-macos.run; do + for name in WiiCompiled-Setup.exe WiiCompiled-Setup-windows-x64.zip WiiCompiled-Setup-x86_64.AppImage WiiCompiled-Setup-aarch64.AppImage WiiCompiled-Setup.pkg WiiCompiled-Setup-macos.run; do found="$(find artifacts -type f -name "$name" | head -n 1)" [ -n "$found" ] && [ -s "$found" ] || { echo "::error::missing release asset $name"; exit 1; } assets+=("$found") diff --git a/Launcher/build-appimage.sh b/Launcher/build-appimage.sh index 2f6b2bbaa..cf5df2d17 100755 --- a/Launcher/build-appimage.sh +++ b/Launcher/build-appimage.sh @@ -263,6 +263,9 @@ exec "$HERE/usr/bin/wiicompiled-setup" --workspace "$CACHE" \ APPRUN chmod +x "$appdir/AppRun" +# RecompLauncher reads this straight out of the AppImage to set the game up and start it. +cp "$script_dir/recomplauncher/linux.json" "$appdir/recomplauncher.json" + echo "Writing desktop entry and icon..." cat > "$appdir/wiicompiled-setup.desktop" <<'DESKTOP' [Desktop Entry] diff --git a/Launcher/recomplauncher/linux.json b/Launcher/recomplauncher/linux.json new file mode 100644 index 000000000..8a6e8c899 --- /dev/null +++ b/Launcher/recomplauncher/linux.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://recomplauncher.com/schema/recomplauncher.json", + "format": 1, + "name": "Mario Kart WiiCompiled", + "repo": "patchzyy/Wiicompiled", + "game": { + "kind": "iso", + "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz." + }, + "prepare": { + "program": ["WiiCompiled-Setup-x86_64.AppImage", "WiiCompiled-Setup-aarch64.AppImage"], + "args": ["install", "--game", "{game}", "--progress-lines"], + "label": "Translating and compiling the game from your disc. This takes a while, and only happens once", + "timeout": 10800 + }, + "start": { + "program": ["WiiCompiled-Setup-x86_64.AppImage", "WiiCompiled-Setup-aarch64.AppImage"], + "args": ["launch-base"] + }, + "config": [ + { + "id": "main", + "format": "toml", + "file": [{ "path": "{local}/WiiCompiled/Config.toml" }] + } + ], + "saves": ["{local}/WiiCompiled/NAND"], + "folders": { + "saves": [{ "path": "{local}/WiiCompiled/NAND" }], + "logs": [{ "path": "{local}/WiiCompiled/Logs" }] + }, + "settings": [ + { + "id": "display_mode", "label": "Window", + "help": "Windowed, borderless fullscreen, or exclusive fullscreen, which asks your screen for the closest mode to the game's frame rate.", + "choices": [ + { "label": "Windowed", "set": { "video/display_mode": "\"windowed\"" } }, + { "label": "Borderless", "set": { "video/display_mode": "\"borderless\"" } }, + { "label": "Exclusive", "set": { "video/display_mode": "\"exclusive\"" } } + ], + "defaults": { "video/display_mode": "\"windowed\"" } + }, + { + "id": "resolution", "label": "Resolution", + "help": "What the game draws at. Native is the Wii's own. Auto follows the size of the window. Higher is sharper and needs a faster graphics card.", + "choices": [ + { "label": "Auto", "set": { "video/resolution_multiplier": "0.0" } }, + { "label": "Native", "set": { "video/resolution_multiplier": "1.0" } }, + { "label": "1.5x", "set": { "video/resolution_multiplier": "1.5" } }, + { "label": "2x", "set": { "video/resolution_multiplier": "2.0" } }, + { "label": "3x", "set": { "video/resolution_multiplier": "3.0" } }, + { "label": "4x", "set": { "video/resolution_multiplier": "4.0" } }, + { "label": "6x", "set": { "video/resolution_multiplier": "6.0" } }, + { "label": "8x", "set": { "video/resolution_multiplier": "8.0" } } + ], + "defaults": { "video/resolution_multiplier": "1.0" } + }, + { + "id": "aspect", "label": "Aspect ratio", + "help": "16:9 for widescreen screens, 4:3 for the original shape. Takes effect the next time the game starts.", + "choices": [ + { "label": "16:9", "set": { "video/widescreen": "true" } }, + { "label": "4:3", "set": { "video/widescreen": "false" } } + ], + "defaults": { "video/widescreen": "true" } + }, + { + "id": "interpolation", "label": "Race frame rate", + "help": "The game runs at 60 FPS. Interpolation adds frames in between during races for 120 or 144 Hz screens. It is experimental and can show artifacts.", + "choices": [ + { "label": "60 FPS", "set": { "video/frame_interpolation_fps": "0" } }, + { "label": "120 FPS", "set": { "video/frame_interpolation_fps": "120" } }, + { "label": "180 FPS", "set": { "video/frame_interpolation_fps": "180" } } + ], + "defaults": { "video/frame_interpolation_fps": "0" } + }, + { + "id": "vsync", "label": "V-Sync", + "help": "Waits for the screen's refresh. Turn it on if frame interpolation looks uneven on your screen.", + "choices": [ + { "label": "Off", "set": { "video/vsync": "false" } }, + { "label": "On", "set": { "video/vsync": "true" } } + ], + "defaults": { "video/vsync": "false" } + }, + { + "id": "fps", "label": "Show FPS", + "help": "The frame rate in a corner of the game.", + "choices": [ + { "label": "On", "set": { "video/show_fps": "true" } }, + { "label": "Off", "set": { "video/show_fps": "false" } } + ], + "defaults": { "video/show_fps": "true" } + }, + { + "id": "mute", "label": "Sound", + "help": "Turn all of the game's sound off or on.", + "choices": [ + { "label": "On", "set": { "audio/muted": "false" } }, + { "label": "Muted", "set": { "audio/muted": "true" } } + ], + "defaults": { "audio/muted": "false" } + }, + { + "id": "ducking", "label": "Music while other audio plays", + "help": "Mutes the game's music while another app, like a video or a music player, is playing sound.", + "choices": [ + { "label": "Keep playing", "set": { "audio/attenuate_music_when_media_plays": "false" } }, + { "label": "Mute music", "set": { "audio/attenuate_music_when_media_plays": "true" } } + ], + "defaults": { "audio/attenuate_music_when_media_plays": "false" } + } + ], + "actions": [ + { "id": "saves", "label": "Saves", "help": "Your Mario Kart Wii save data.", "open": "saves" }, + { "id": "logs", "label": "Logs", "help": "The log of each run, for bug reports.", "open": "logs" } + ] +} diff --git a/Launcher/recomplauncher/windows.json b/Launcher/recomplauncher/windows.json new file mode 100644 index 000000000..b06374fda --- /dev/null +++ b/Launcher/recomplauncher/windows.json @@ -0,0 +1,118 @@ +{ + "$schema": "https://recomplauncher.com/schema/recomplauncher.json", + "format": 1, + "name": "Mario Kart WiiCompiled", + "repo": "patchzyy/Wiicompiled", + "game": { + "kind": "iso", + "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz." + }, + "prepare": { + "program": ["WiiCompiled-Setup.exe"], + "args": ["--silent", "--game", "{game}", "--install-dir", "{install}/WiiCompiled/Install", "--portable", "--progress-lines"], + "label": "Translating and compiling the game from your disc. This takes a while, and only happens once", + "timeout": 10800 + }, + "start": { + "program": ["WiiCompiled/Install/WiiCompiled-Setup.exe"], + "args": ["--launch-base"] + }, + "config": [ + { + "id": "main", + "format": "toml", + "file": [{ "path": "{install}/WiiCompiled/UserData/Config.toml" }] + } + ], + "saves": ["{install}/WiiCompiled/UserData/NAND"], + "folders": { + "saves": [{ "path": "{install}/WiiCompiled/UserData/NAND" }], + "logs": [{ "path": "{install}/WiiCompiled/UserData/Logs" }] + }, + "settings": [ + { + "id": "display_mode", "label": "Window", + "help": "Windowed, borderless fullscreen, or exclusive fullscreen, which asks your screen for the closest mode to the game's frame rate.", + "choices": [ + { "label": "Windowed", "set": { "video/display_mode": "\"windowed\"" } }, + { "label": "Borderless", "set": { "video/display_mode": "\"borderless\"" } }, + { "label": "Exclusive", "set": { "video/display_mode": "\"exclusive\"" } } + ], + "defaults": { "video/display_mode": "\"windowed\"" } + }, + { + "id": "resolution", "label": "Resolution", + "help": "What the game draws at. Native is the Wii's own. Auto follows the size of the window. Higher is sharper and needs a faster graphics card.", + "choices": [ + { "label": "Auto", "set": { "video/resolution_multiplier": "0.0" } }, + { "label": "Native", "set": { "video/resolution_multiplier": "1.0" } }, + { "label": "1.5x", "set": { "video/resolution_multiplier": "1.5" } }, + { "label": "2x", "set": { "video/resolution_multiplier": "2.0" } }, + { "label": "3x", "set": { "video/resolution_multiplier": "3.0" } }, + { "label": "4x", "set": { "video/resolution_multiplier": "4.0" } }, + { "label": "6x", "set": { "video/resolution_multiplier": "6.0" } }, + { "label": "8x", "set": { "video/resolution_multiplier": "8.0" } } + ], + "defaults": { "video/resolution_multiplier": "1.0" } + }, + { + "id": "aspect", "label": "Aspect ratio", + "help": "16:9 for widescreen screens, 4:3 for the original shape. Takes effect the next time the game starts.", + "choices": [ + { "label": "16:9", "set": { "video/widescreen": "true" } }, + { "label": "4:3", "set": { "video/widescreen": "false" } } + ], + "defaults": { "video/widescreen": "true" } + }, + { + "id": "interpolation", "label": "Race frame rate", + "help": "The game runs at 60 FPS. Interpolation adds frames in between during races for 120 or 144 Hz screens. It is experimental and can show artifacts.", + "choices": [ + { "label": "60 FPS", "set": { "video/frame_interpolation_fps": "0" } }, + { "label": "120 FPS", "set": { "video/frame_interpolation_fps": "120" } }, + { "label": "180 FPS", "set": { "video/frame_interpolation_fps": "180" } } + ], + "defaults": { "video/frame_interpolation_fps": "0" } + }, + { + "id": "vsync", "label": "V-Sync", + "help": "Waits for the screen's refresh. Turn it on if frame interpolation looks uneven on your screen.", + "choices": [ + { "label": "Off", "set": { "video/vsync": "false" } }, + { "label": "On", "set": { "video/vsync": "true" } } + ], + "defaults": { "video/vsync": "false" } + }, + { + "id": "fps", "label": "Show FPS", + "help": "The frame rate in a corner of the game.", + "choices": [ + { "label": "On", "set": { "video/show_fps": "true" } }, + { "label": "Off", "set": { "video/show_fps": "false" } } + ], + "defaults": { "video/show_fps": "true" } + }, + { + "id": "mute", "label": "Sound", + "help": "Turn all of the game's sound off or on.", + "choices": [ + { "label": "On", "set": { "audio/muted": "false" } }, + { "label": "Muted", "set": { "audio/muted": "true" } } + ], + "defaults": { "audio/muted": "false" } + }, + { + "id": "ducking", "label": "Music while other audio plays", + "help": "Mutes the game's music while another app, like a video or a music player, is playing sound.", + "choices": [ + { "label": "Keep playing", "set": { "audio/attenuate_music_when_media_plays": "false" } }, + { "label": "Mute music", "set": { "audio/attenuate_music_when_media_plays": "true" } } + ], + "defaults": { "audio/attenuate_music_when_media_plays": "false" } + } + ], + "actions": [ + { "id": "saves", "label": "Saves", "help": "Your Mario Kart Wii save data.", "open": "saves" }, + { "id": "logs", "label": "Logs", "help": "The log of each run, for bug reports.", "open": "logs" } + ] +} From 992e7fed1396242ceefac2acc79bfb0fa1147431 Mon Sep 17 00:00:00 2001 From: Zacharias Xenakis Date: Tue, 10 Nov 2026 23:38:39 +0200 Subject: [PATCH 3/4] README: add the Get it on RecompLauncher badge --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index 7c31b9029..d54b7df0b 100644 --- a/README.md +++ b/README.md @@ -14,6 +14,9 @@ Total downloads License: GPLv3

+

+ Get it on RecompLauncher +

A native PC port of Mario Kart Wii, made with static recompilation. From 9f2a220520f211dbabcc130b36fafafd68b14818 Mon Sep 17 00:00:00 2001 From: Zacharias Xenakis Date: Wed, 11 Nov 2026 00:41:52 +0200 Subject: [PATCH 4/4] RecompLauncher: check the disc ID and group the settings --- Launcher/recomplauncher/linux.json | 19 ++++++++++--------- Launcher/recomplauncher/windows.json | 19 ++++++++++--------- 2 files changed, 20 insertions(+), 18 deletions(-) diff --git a/Launcher/recomplauncher/linux.json b/Launcher/recomplauncher/linux.json index 8a6e8c899..8ebab1476 100644 --- a/Launcher/recomplauncher/linux.json +++ b/Launcher/recomplauncher/linux.json @@ -5,7 +5,8 @@ "repo": "patchzyy/Wiicompiled", "game": { "kind": "iso", - "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz." + "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz.", + "check": { "ids": ["RMCP01", "RMCE01", "RMCJ01"] } }, "prepare": { "program": ["WiiCompiled-Setup-x86_64.AppImage", "WiiCompiled-Setup-aarch64.AppImage"], @@ -31,7 +32,7 @@ }, "settings": [ { - "id": "display_mode", "label": "Window", + "id": "display_mode", "label": "Window", "group": "Video", "help": "Windowed, borderless fullscreen, or exclusive fullscreen, which asks your screen for the closest mode to the game's frame rate.", "choices": [ { "label": "Windowed", "set": { "video/display_mode": "\"windowed\"" } }, @@ -41,7 +42,7 @@ "defaults": { "video/display_mode": "\"windowed\"" } }, { - "id": "resolution", "label": "Resolution", + "id": "resolution", "label": "Resolution", "group": "Video", "help": "What the game draws at. Native is the Wii's own. Auto follows the size of the window. Higher is sharper and needs a faster graphics card.", "choices": [ { "label": "Auto", "set": { "video/resolution_multiplier": "0.0" } }, @@ -56,7 +57,7 @@ "defaults": { "video/resolution_multiplier": "1.0" } }, { - "id": "aspect", "label": "Aspect ratio", + "id": "aspect", "label": "Aspect ratio", "group": "Video", "help": "16:9 for widescreen screens, 4:3 for the original shape. Takes effect the next time the game starts.", "choices": [ { "label": "16:9", "set": { "video/widescreen": "true" } }, @@ -65,7 +66,7 @@ "defaults": { "video/widescreen": "true" } }, { - "id": "interpolation", "label": "Race frame rate", + "id": "interpolation", "label": "Race frame rate", "group": "Video", "help": "The game runs at 60 FPS. Interpolation adds frames in between during races for 120 or 144 Hz screens. It is experimental and can show artifacts.", "choices": [ { "label": "60 FPS", "set": { "video/frame_interpolation_fps": "0" } }, @@ -75,7 +76,7 @@ "defaults": { "video/frame_interpolation_fps": "0" } }, { - "id": "vsync", "label": "V-Sync", + "id": "vsync", "label": "V-Sync", "group": "Video", "help": "Waits for the screen's refresh. Turn it on if frame interpolation looks uneven on your screen.", "choices": [ { "label": "Off", "set": { "video/vsync": "false" } }, @@ -84,7 +85,7 @@ "defaults": { "video/vsync": "false" } }, { - "id": "fps", "label": "Show FPS", + "id": "fps", "label": "Show FPS", "group": "Video", "help": "The frame rate in a corner of the game.", "choices": [ { "label": "On", "set": { "video/show_fps": "true" } }, @@ -93,7 +94,7 @@ "defaults": { "video/show_fps": "true" } }, { - "id": "mute", "label": "Sound", + "id": "mute", "label": "Sound", "group": "Audio", "help": "Turn all of the game's sound off or on.", "choices": [ { "label": "On", "set": { "audio/muted": "false" } }, @@ -102,7 +103,7 @@ "defaults": { "audio/muted": "false" } }, { - "id": "ducking", "label": "Music while other audio plays", + "id": "ducking", "label": "Music while other audio plays", "group": "Audio", "help": "Mutes the game's music while another app, like a video or a music player, is playing sound.", "choices": [ { "label": "Keep playing", "set": { "audio/attenuate_music_when_media_plays": "false" } }, diff --git a/Launcher/recomplauncher/windows.json b/Launcher/recomplauncher/windows.json index b06374fda..43fb64dd0 100644 --- a/Launcher/recomplauncher/windows.json +++ b/Launcher/recomplauncher/windows.json @@ -5,7 +5,8 @@ "repo": "patchzyy/Wiicompiled", "game": { "kind": "iso", - "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz." + "label": "Your own disc image of Mario Kart Wii: the PAL (RMCP01), USA (RMCE01) or Japan (RMCJ01) release, a clean dump as .iso, .gcm, .gcz, .ciso, .wbfs, .wia or .rvz.", + "check": { "ids": ["RMCP01", "RMCE01", "RMCJ01"] } }, "prepare": { "program": ["WiiCompiled-Setup.exe"], @@ -31,7 +32,7 @@ }, "settings": [ { - "id": "display_mode", "label": "Window", + "id": "display_mode", "label": "Window", "group": "Video", "help": "Windowed, borderless fullscreen, or exclusive fullscreen, which asks your screen for the closest mode to the game's frame rate.", "choices": [ { "label": "Windowed", "set": { "video/display_mode": "\"windowed\"" } }, @@ -41,7 +42,7 @@ "defaults": { "video/display_mode": "\"windowed\"" } }, { - "id": "resolution", "label": "Resolution", + "id": "resolution", "label": "Resolution", "group": "Video", "help": "What the game draws at. Native is the Wii's own. Auto follows the size of the window. Higher is sharper and needs a faster graphics card.", "choices": [ { "label": "Auto", "set": { "video/resolution_multiplier": "0.0" } }, @@ -56,7 +57,7 @@ "defaults": { "video/resolution_multiplier": "1.0" } }, { - "id": "aspect", "label": "Aspect ratio", + "id": "aspect", "label": "Aspect ratio", "group": "Video", "help": "16:9 for widescreen screens, 4:3 for the original shape. Takes effect the next time the game starts.", "choices": [ { "label": "16:9", "set": { "video/widescreen": "true" } }, @@ -65,7 +66,7 @@ "defaults": { "video/widescreen": "true" } }, { - "id": "interpolation", "label": "Race frame rate", + "id": "interpolation", "label": "Race frame rate", "group": "Video", "help": "The game runs at 60 FPS. Interpolation adds frames in between during races for 120 or 144 Hz screens. It is experimental and can show artifacts.", "choices": [ { "label": "60 FPS", "set": { "video/frame_interpolation_fps": "0" } }, @@ -75,7 +76,7 @@ "defaults": { "video/frame_interpolation_fps": "0" } }, { - "id": "vsync", "label": "V-Sync", + "id": "vsync", "label": "V-Sync", "group": "Video", "help": "Waits for the screen's refresh. Turn it on if frame interpolation looks uneven on your screen.", "choices": [ { "label": "Off", "set": { "video/vsync": "false" } }, @@ -84,7 +85,7 @@ "defaults": { "video/vsync": "false" } }, { - "id": "fps", "label": "Show FPS", + "id": "fps", "label": "Show FPS", "group": "Video", "help": "The frame rate in a corner of the game.", "choices": [ { "label": "On", "set": { "video/show_fps": "true" } }, @@ -93,7 +94,7 @@ "defaults": { "video/show_fps": "true" } }, { - "id": "mute", "label": "Sound", + "id": "mute", "label": "Sound", "group": "Audio", "help": "Turn all of the game's sound off or on.", "choices": [ { "label": "On", "set": { "audio/muted": "false" } }, @@ -102,7 +103,7 @@ "defaults": { "audio/muted": "false" } }, { - "id": "ducking", "label": "Music while other audio plays", + "id": "ducking", "label": "Music while other audio plays", "group": "Audio", "help": "Mutes the game's music while another app, like a video or a music player, is playing sound.", "choices": [ { "label": "Keep playing", "set": { "audio/attenuate_music_when_media_plays": "false" } },