Non-ASCII Windows Paths Break First-Run Setup
Summary
On Windows, a user account whose profile folder contains a non-ASCII character
(e.g. C:\Users\André\) makes the first-run setup unusable. The failure shows
up three separate times, each with a message that points somewhere other than
the real cause, so the problem is very hard to diagnose from the UI alone.
Everything works after logging into a second Windows account whose username is
pure ASCII, building there once, and then running the produced
build-release/<game>.exe back from the original account.
Non-ASCII characters in Windows usernames are common, particularly in localized
Windows installations, so this is likely to affect a fair number of users whose
paths fall outside those assumptions.
Environment
- Windows 10, pt-BR locale (console OEM code page 850, ANSI code page 1252)
- Username:
André → profile at C:\Users\André\
- Game folder relocated to
D:\ValkyrieRecomp-1.0.1-windows-x64\ (pure ASCII)
- Setup-host release build (game/BIOS code not yet linked)
Note that moving the game folder to D:\ is not enough: the toolchain cache
lives under %LOCALAPPDATA%, which stays inside the accented profile path.
Symptom 1 — browsing for a disc makes it disappear from the UI
Before browsing, the disc rows show 2 of 2 located (green). The paths at that
point come from game.toml and are relative (disc/Disc1/....cue), so they
resolve against the process CWD and never carry the accented prefix.
Clicking Browse and picking the same .cue stores the absolute path, and
the row immediately goes back to "not located".
Root cause — recomp-ui/src/common/launcher_model.c:
static int lm_path_exists(const char* path) {
FILE* f;
if (!path || !path[0]) return 0;
f = fopen(path, "rb"); /* narrow char* */
if (!f) return 0;
fclose(f);
return 1;
}
The stored path comes back from the file picker as a narrow string, even though
Windows filesystem paths are natively represented as UTF-16. In this case,
passing that representation through the narrow fopen path fails to open the
existing file, so the file is reported as missing. (In the built-in picker the
value is entry.path.string(); I have not checked which picker this build uses,
but both the built-in and native Windows path handling ultimately pass a narrow
char* to this code path.)
The exact conversion performed by path.string() is implementation-dependent,
so the immediate issue appears to be the narrow-string path handling rather than
the file itself.
Symptom 2 — "Generate & rebuild" stays disabled with a misleading tooltip
The tooltip reads "Select a verified Disc first", which sends the user off to
investigate their dump. In my case that cost a lot of time: I went looking for
missing CD-DA tracks that this game does not even have
(game.toml declares required_tracks = 1).
The actual gate does not check the verification verdict at all —
recomp-ui/src/common/backends/imgui/launcher_imgui.cpp (~line 8746):
const bool use_selected = m->prepare_use_selected_rom;
const bool can_prep_selected = use_selected && m->rom_present &&
m->rom_full[0] &&
strcmp(m->rom_size, "--") != 0;
if (use_selected && !can_prep_selected) ImGui::BeginDisabled();
rom_size becomes "--" when the same narrow fopen fails, so this is
Symptom 1 surfacing as a disabled button with unrelated wording.
Suggested fix, independent of the encoding work: word the tooltip after the
condition it actually tests (e.g. "Disc file could not be opened.").
Symptom 3 — the rebuild helper cannot find Python
recomp_deferred_rebuild.cmd is generated with absolute paths:
set "PYTHON=C:\Users\André\AppData\Local/retcomm/toolchains/cmake-clang-v1/latest/python/python.exe"
set "TC_BIN=C:\Users\André\AppData\Local/retcomm/toolchains/cmake-clang-v1/latest/bin"
Running it produces:
Ensuring toolchain...
O sistema não pode encontrar o caminho especificado.
Toolchain missing. Download cmake-clang-v1 or set
RETCOMM_TOOLCHAIN_DIR / pass --toolchain-zip on rebuild.
The first line is cmd.exe failing to launch the interpreter. The
"Toolchain missing" text below it is just the generic if errorlevel 1 branch,
and it misattributes the failure — the toolchain was present and correct.
Root cause — the file is written as raw bytes in
psxrecomp/host/psxrecomp_codegen_host.c:
FILE* f = fopen(g_helper_path, "wb");
...
bat_write_set(f, "PYTHON", g_python);
Inspecting the emitted file, é is stored as the single byte 0xE9
(Windows-1252). cmd.exe interprets batch files using the console OEM code
page (850 here), where 0xE9 represents a different character, so the path no
longer matches anything on disk.
Why the documented workarounds did not help
RETCOMM_TOOLCHAIN_DIR — this should work in principle: find_python()
falls through to find_toolchain_python() → resolve_toolchain_bin(), which
reads that variable. It did not take effect in my case, but I never confirmed
the variable was actually visible to the launcher process, so treat this as
unverified rather than as a second defect.
- Hand-editing the
.cmd — the launcher regenerates the file on the next
Generate run and the edit is lost. (Confirmed: a regenerated file came back
with the original path and a new PARENT_PID.)
- Moving the game folder to a non-accented drive — the toolchain cache still
resolves under %LOCALAPPDATA%.
Working workaround
- Create a second Windows account with an ASCII-only username.
- Log into it (creating it is not sufficient —
%LOCALAPPDATA% follows the
logged-in profile).
- Run the setup host and complete Generate & rebuild there. Expect the
toolchain to be fetched again, since the cache is per-user.
- Log back into the original account and run
build-release/<game>.exe directly.
Step 4 works because the runtime resolves overlay_toolchain/ and cache/
relative to exe_dir_from_argv(argv[0]), so nothing in the built game refers
back to the build-time profile. One consequence: without a gcc on PATH in the
original account, the overlay compiler falls back to the tcc tier.
Minimal reproduction (expected, not tested)
An accented username should not be required to reproduce this. Extracting the
release into a folder whose own path contains a non-ASCII character ought to be
enough, and is much quicker to set up:
D:\Ação\ValkyrieRecomp-1.0.1-windows-x64\
I have not run this exact scenario — my own case went through the profile path —
so the steps below are derived from the code, not observed:
- Launch the setup host. The disc rows read
2 of 2 located, because the
paths from game.toml are relative and never carry the accented prefix.
- Click
Browse on the selected disc row and pick the same .cue. The row
flips to "not located", and Generate & rebuild stays disabled with
"Select a verified Disc first" (Symptoms 1 and 2).
- If Generate is reached, the emitted
recomp_deferred_rebuild.cmd also has
ROOT, CLI and CONFIG written with the mangled byte, so even
cd /d "%ROOT%" fails (Symptom 3).
The accented-username case is the same underlying path/encoding problem reached
through %LOCALAPPDATA%, which is why relocating the game to an ASCII drive
does not help on its own.
Suggested fixes
Path handling
Route Windows file access through Unicode-aware APIs, using UTF-16 paths and
_wfopen where appropriate. At minimum, this should be considered for
lm_path_exists() and the rom_size probe in launcher_model.c.
Another possible approach would be to opt the process into UTF-8 via an
application manifest (activeCodePage = UTF-8, on supported Windows versions),
but that would need to be verified against all of the narrow-string call sites
involved here rather than assumed to fix every path-related failure.
Generated batch file
The generated batch file should avoid relying on an ANSI/OEM code-page
conversion for paths.
One option is to resolve paths to their 8.3 short-name representation with
GetShortPathNameW where available, producing ASCII-only paths for the batch
file. This avoids the code-page mismatch, although availability of short names
should be accounted for.
Another option is to generate the batch file in a deliberately chosen encoding
and invoke it in an environment where that encoding is explicitly supported.
Simply emitting chcp at the top is less dependable, since the interpreter has
already begun parsing the file.
Error messages
The "Toolchain missing" branch fires for any non-zero exit, including failure
to launch the interpreter. Distinguishing:
- "Could not run Python at
<path>"
- "Toolchain not found"
would make this considerably easier to diagnose.
More generally, the UI messages should reflect the conditions that actually
disable the relevant operation. In particular, a failed fopen should not be
presented as a disc verification failure.
Happy to provide additional testing or verify a proposed fix on a Windows
installation with a non-ASCII profile path.
Non-ASCII Windows Paths Break First-Run Setup
Summary
On Windows, a user account whose profile folder contains a non-ASCII character
(e.g.
C:\Users\André\) makes the first-run setup unusable. The failure showsup three separate times, each with a message that points somewhere other than
the real cause, so the problem is very hard to diagnose from the UI alone.
Everything works after logging into a second Windows account whose username is
pure ASCII, building there once, and then running the produced
build-release/<game>.exeback from the original account.Non-ASCII characters in Windows usernames are common, particularly in localized
Windows installations, so this is likely to affect a fair number of users whose
paths fall outside those assumptions.
Environment
André→ profile atC:\Users\André\D:\ValkyrieRecomp-1.0.1-windows-x64\(pure ASCII)Note that moving the game folder to
D:\is not enough: the toolchain cachelives under
%LOCALAPPDATA%, which stays inside the accented profile path.Symptom 1 — browsing for a disc makes it disappear from the UI
Before browsing, the disc rows show
2 of 2 located(green). The paths at thatpoint come from
game.tomland are relative (disc/Disc1/....cue), so theyresolve against the process CWD and never carry the accented prefix.
Clicking
Browseand picking the same.cuestores the absolute path, andthe row immediately goes back to "not located".
Root cause —
recomp-ui/src/common/launcher_model.c:The stored path comes back from the file picker as a narrow string, even though
Windows filesystem paths are natively represented as UTF-16. In this case,
passing that representation through the narrow
fopenpath fails to open theexisting file, so the file is reported as missing. (In the built-in picker the
value is
entry.path.string(); I have not checked which picker this build uses,but both the built-in and native Windows path handling ultimately pass a narrow
char*to this code path.)The exact conversion performed by
path.string()is implementation-dependent,so the immediate issue appears to be the narrow-string path handling rather than
the file itself.
Symptom 2 — "Generate & rebuild" stays disabled with a misleading tooltip
The tooltip reads "Select a verified Disc first", which sends the user off to
investigate their dump. In my case that cost a lot of time: I went looking for
missing CD-DA tracks that this game does not even have
(
game.tomldeclaresrequired_tracks = 1).The actual gate does not check the verification verdict at all —
recomp-ui/src/common/backends/imgui/launcher_imgui.cpp(~line 8746):rom_sizebecomes"--"when the same narrowfopenfails, so this isSymptom 1 surfacing as a disabled button with unrelated wording.
Suggested fix, independent of the encoding work: word the tooltip after the
condition it actually tests (e.g. "Disc file could not be opened.").
Symptom 3 — the rebuild helper cannot find Python
recomp_deferred_rebuild.cmdis generated with absolute paths:Running it produces:
The first line is
cmd.exefailing to launch the interpreter. The"Toolchain missing" text below it is just the generic
if errorlevel 1branch,and it misattributes the failure — the toolchain was present and correct.
Root cause — the file is written as raw bytes in
psxrecomp/host/psxrecomp_codegen_host.c:Inspecting the emitted file,
éis stored as the single byte0xE9(Windows-1252).
cmd.exeinterprets batch files using the console OEM codepage (850 here), where
0xE9represents a different character, so the path nolonger matches anything on disk.
Why the documented workarounds did not help
RETCOMM_TOOLCHAIN_DIR— this should work in principle:find_python()falls through to
find_toolchain_python()→resolve_toolchain_bin(), whichreads that variable. It did not take effect in my case, but I never confirmed
the variable was actually visible to the launcher process, so treat this as
unverified rather than as a second defect.
.cmd— the launcher regenerates the file on the nextGenerate run and the edit is lost. (Confirmed: a regenerated file came back
with the original path and a new
PARENT_PID.)resolves under
%LOCALAPPDATA%.Working workaround
%LOCALAPPDATA%follows thelogged-in profile).
toolchain to be fetched again, since the cache is per-user.
build-release/<game>.exedirectly.Step 4 works because the runtime resolves
overlay_toolchain/andcache/relative to
exe_dir_from_argv(argv[0]), so nothing in the built game refersback to the build-time profile. One consequence: without a
gccon PATH in theoriginal account, the overlay compiler falls back to the tcc tier.
Minimal reproduction (expected, not tested)
An accented username should not be required to reproduce this. Extracting the
release into a folder whose own path contains a non-ASCII character ought to be
enough, and is much quicker to set up:
I have not run this exact scenario — my own case went through the profile path —
so the steps below are derived from the code, not observed:
2 of 2 located, because thepaths from
game.tomlare relative and never carry the accented prefix.Browseon the selected disc row and pick the same.cue. The rowflips to "not located", and
Generate & rebuildstays disabled with"Select a verified Disc first" (Symptoms 1 and 2).
recomp_deferred_rebuild.cmdalso hasROOT,CLIandCONFIGwritten with the mangled byte, so evencd /d "%ROOT%"fails (Symptom 3).The accented-username case is the same underlying path/encoding problem reached
through
%LOCALAPPDATA%, which is why relocating the game to an ASCII drivedoes not help on its own.
Suggested fixes
Path handling
Route Windows file access through Unicode-aware APIs, using UTF-16 paths and
_wfopenwhere appropriate. At minimum, this should be considered forlm_path_exists()and therom_sizeprobe inlauncher_model.c.Another possible approach would be to opt the process into UTF-8 via an
application manifest (
activeCodePage = UTF-8, on supported Windows versions),but that would need to be verified against all of the narrow-string call sites
involved here rather than assumed to fix every path-related failure.
Generated batch file
The generated batch file should avoid relying on an ANSI/OEM code-page
conversion for paths.
One option is to resolve paths to their 8.3 short-name representation with
GetShortPathNameWwhere available, producing ASCII-only paths for the batchfile. This avoids the code-page mismatch, although availability of short names
should be accounted for.
Another option is to generate the batch file in a deliberately chosen encoding
and invoke it in an environment where that encoding is explicitly supported.
Simply emitting
chcpat the top is less dependable, since the interpreter hasalready begun parsing the file.
Error messages
The "Toolchain missing" branch fires for any non-zero exit, including failure
to launch the interpreter. Distinguishing:
<path>"would make this considerably easier to diagnose.
More generally, the UI messages should reflect the conditions that actually
disable the relevant operation. In particular, a failed
fopenshould not bepresented as a disc verification failure.
Happy to provide additional testing or verify a proposed fix on a Windows
installation with a non-ASCII profile path.