As noted in #567, a filesystem path that contains non-ascii will break a
lot if using a clang toolchain.
Luckily, fmtlib has a lossy utf8 convert when you use it to print a path
(after including `fmt/std.h`). The vast majority of this diff is just
removing `.string()` from paths inside loggings calls.
There are some callsites I _didn't_ touch, mainly the options, because
it would be an ABI break to change those to be wide strings and I cbf
looking into settings upgrades. There are also some spots (avs mountpath
remapping, for example) where the path is guaranteed to be ascii, so I
didn't modify them.
ImGui doesn't appear to easily support wide strings (I mean, surely it
does, but I'm not gonna look too far into it) so I mostly just left
those alone too, with a few spots modified to re-use fmtlib's lossy
utf8.
Some of the changes are basically never gonna be hit IRL, like who would
put a file with a non-ascii _extension_ along with their modules? But
the diff is (I hope) pretty easy to validate as OK.
Testing has been somewhat minimal, I fired up the GCC build of spice2x
in a dodgy folder name, got mojibake (running via wine in linux so take
that as you will), ran the unmodified clang spice and crashed the same
way the reporter did. After modification, I get the exact same mojibake
so I assume if the terminal enjoys utf8 it'll display OK.
Claude (only used for review) thinks the commit is fine but is annoyed
that I use `fmt::detail` in the appdata censoring, which is part of the
private API; personally I don't care because it's pretty stable.
## Link to GitHub Issue or related Pull Request, if one exists
#592
## Description of change
* when custom DLLs are detected (`d3d9.dll`) print out some basic data
from the PE header
* for our own NVIDIA DLL stubs, add manifest files to identify ourselves
* as a bonus, when DLL hooks are loaded from `-k`, print DLL info there
as well
This is mainly to detect when DXVK is in use.
## Link to GitHub Issue, if one exists
#410
## Description of change
When raising fatal errors via `log_fatal`, also show a modal popup.
Update instances of `log_fatal` where the message was too long to fit.
## Testing
Tested various failure conditions.
## Description of change
When the game library fails to load, recursively iterate its import
table to narrow down the missing library.
If the dependency is a commonly missing one, give the user a hint on
where to find it.
## Testing
System with an AMD GPU and LDJ-010 IIDX:
```
[2025/10/01 00:32:41] M:dependencies: bm2dx.dll
[2025/10/01 00:32:41] M:dependencies: |-- nvEncodeAPI64.dll
[2025/10/01 00:32:41] W:dependencies: | |-- [!] NVIDIA Graphics Driver
[2025/10/01 00:32:41] W:dependencies: | |-- For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.
[2025/10/01 00:32:41] F:libutils: DLL failed to load - this is a common error. Please carefully read ALL of the following steps for a fix:
```
Same system, but with SDVX:
```
[2025/10/01 00:33:53] M:dependencies: soundvoltex.dll
[2025/10/01 00:33:53] M:dependencies: |-- nvcuda.dll
[2025/10/01 00:33:53] W:dependencies: | |-- [!] NVIDIA Graphics Driver
[2025/10/01 00:33:53] W:dependencies: | |-- For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.
[2025/10/01 00:33:53] M:dependencies: |-- nvcuvid.dll
[2025/10/01 00:33:53] W:dependencies: | |-- [!] NVIDIA Graphics Driver
[2025/10/01 00:33:53] W:dependencies: | |-- For non-NVIDIA GPUs, copy the stub file from the spice2x release .zip.
[2025/10/01 00:33:53] F:libutils: DLL failed to load - this is a common error. Please carefully read ALL of the following steps for a fix:
```
Contrived example of a missing dependency of a dependency:
```
[2025/10/01 00:30:59] M:dependencies: bm2dx.dll
[2025/10/01 00:30:59] M:dependencies: |-- libaio.dll
[2025/10/01 00:30:59] W:dependencies: | |-- [!] The library could not be loaded. (126)
[2025/10/01 00:30:59] M:dependencies: |-- libaio-iob.dll
[2025/10/01 00:30:59] M:dependencies: | |-- libaio.dll
[2025/10/01 00:30:59] M:dependencies: |-- libaio-iob2_video.dll
[2025/10/01 00:30:59] M:dependencies: | |-- libaio.dll
[2025/10/01 00:30:59] M:dependencies: | |-- libaio-iob.dll
[2025/10/01 00:30:59] F:libutils: DLL failed to load - this is a common error. Please carefully read ALL of the following steps for a fix:
```
Another example of a missing file, but with 32-bit IIDX 24:
```
[2025/10/01 00:42:13] M:dependencies: bm2dx.dll
[2025/10/01 00:42:13] M:dependencies: |-- libafp-win32.dll
[2025/10/01 00:42:13] W:dependencies: | |-- [!] The library could not be loaded. (126)
[2025/10/01 00:42:13] M:dependencies: |-- libafputils-win32.dll
[2025/10/01 00:42:13] M:dependencies: | |-- libafp-win32.dll
[2025/10/01 00:42:13] F:libutils: DLL failed to load - this is a common error. Please carefully read ALL of the following steps for a fix:
```
---------
Co-authored-by: aixxe <me@aixxe.net>
## Link to GitHub Issue, if one exists
n/a
## Description of change
Log a message if d3d9.dll (and friends) are found in the game root or
the modules directory.
This is to help with troubleshooting in cases where the user is unaware
that d3d9 is being used to inject other DLLs (e.g., ifs_layeredfs), or
when DX9 reimplementation is causing issues / crashes (e.g., dxvk).
## Testing
Observed the new messages being logged in both modules / root directory.
## Link to GitHub Issue, if one exists
#304
## Description of change
Complain loudly about DLL conflicts. Show warnings for each DLL that
exists in both modules directory and the root.
This is not based on LoadLibrary hooks, just enumerating DLLs via
filesystem access.
Deliberately not using `log_fatal` since these are not necessarily going
to crash the game. Some people just love to have messy installs and if
the game booted fine before, it should continue to boot.
## Testing
Tested with/without `-modules`, with/without duplicate DLLs.