Skip to content

Setup/rebuild fails when a path contains non-ASCII characters (e.g. accented Windows username) #3

Description

@CanalAndreTavares

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

  1. Create a second Windows account with an ASCII-only username.
  2. Log into it (creating it is not sufficient — %LOCALAPPDATA% follows the
    logged-in profile).
  3. Run the setup host and complete Generate & rebuild there. Expect the
    toolchain to be fetched again, since the cache is per-user.
  4. 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:

  1. 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.
  2. 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).
  3. 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.

Activity

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Metadata

Metadata

Assignees

No one assigned

    Labels

    No labels
    No labels

    Projects

    No projects

      Milestone

      No milestone

      Relationships

      None yet

      Development

      No branches or pull requests

      Issue actions