mirror of
https://github.com/RetroPortingToolKit/psxrecomp
synced 2026-10-25 18:05:12 -04:00
Resolve relative bezel artwork paths against the exe directory
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -603,6 +603,13 @@ remain black. Enabling the feature without choosing artwork is also a no-op.
|
||||
The package supplies only the declaration and trusted plugin selection; archives
|
||||
still cannot load native code.
|
||||
|
||||
A title's own trusted plugin can call `psx_mod_set_bezel_artwork(path)` directly
|
||||
to ship its artwork. An absolute path (such as the built-in package's selected
|
||||
resource) is used as-is; a relative path like `"bezels/qirex.png"` is resolved
|
||||
against the executable's directory when the artwork loads, never the current
|
||||
working directory, so artwork the title stages beside its binary is found
|
||||
however the game was launched.
|
||||
|
||||
### Retained-scene loading presentation (native-wide opt-in)
|
||||
|
||||
A trusted game plugin can register
|
||||
|
||||
@@ -231,6 +231,10 @@ int psx_mod_set_auto_skip_fmv(int enabled);
|
||||
* Draw still artwork behind the game image in OpenGL letterbox/pillarbox
|
||||
* margins. The image path is an owner-selected mod resource; with no enabled
|
||||
* mod/resource path, the margins remain the historical black clear.
|
||||
* An absolute path is used unchanged. A relative path (e.g. "bezels/x.png"
|
||||
* for artwork a title stages beside its binary) is resolved against the
|
||||
* executable's directory, never the current working directory, when the
|
||||
* artwork is loaded.
|
||||
*/
|
||||
int psx_mod_set_bezel_artwork(const char* path);
|
||||
|
||||
|
||||
+15
-7
@@ -15240,18 +15240,26 @@ session_reboot:
|
||||
|
||||
/* Bezel artwork (Mods): load after the GL context exists. */
|
||||
if (!g_bezel_path.empty() && g_gl_active) {
|
||||
std::filesystem::path bp(g_bezel_path);
|
||||
/* A relative artwork path names a file shipped beside the
|
||||
* executable (e.g. a title's staged bezels/), so anchor it on the
|
||||
* exe directory -- never cwd (see exe_dir_from_argv). An absolute
|
||||
* path, such as the builtin bezel's owner-selected resource, is
|
||||
* used unchanged. */
|
||||
const std::filesystem::path bp = PSXRecompV4::host_resolve(
|
||||
exe_dir_from_argv(argv[0]), std::filesystem::path(g_bezel_path));
|
||||
std::vector<unsigned char> file;
|
||||
if (FILE *bf = std::fopen(bp.string().c_str(), "rb")) {
|
||||
std::fseek(bf, 0, SEEK_END);
|
||||
const long len = std::ftell(bf);
|
||||
std::fseek(bf, 0, SEEK_SET);
|
||||
/* fs::path stream: the exe directory is a wide Windows path, which
|
||||
* a narrow fopen() of bp.string() cannot open when it is non-ASCII. */
|
||||
std::ifstream bf(bp, std::ios::binary | std::ios::ate);
|
||||
if (bf.is_open()) {
|
||||
const std::streamoff len = bf.tellg();
|
||||
if (len > 0) {
|
||||
file.resize((size_t)len);
|
||||
if (std::fread(file.data(), 1, file.size(), bf) != file.size())
|
||||
bf.seekg(0, std::ios::beg);
|
||||
if (!bf.read(reinterpret_cast<char*>(file.data()),
|
||||
(std::streamsize)file.size()))
|
||||
file.clear();
|
||||
}
|
||||
std::fclose(bf);
|
||||
}
|
||||
int bw = 0, bh = 0, bc = 0;
|
||||
unsigned char *px = file.empty() ? nullptr
|
||||
|
||||
@@ -9,7 +9,8 @@ MAIN = (ROOT / "runtime/src/main.cpp").read_text(encoding="utf-8")
|
||||
HEADER = (ROOT / "runtime/include/mod_plugins.h").read_text(encoding="utf-8")
|
||||
MOD_RUNTIME = (ROOT / "runtime/src/mod_runtime.cpp").read_text(encoding="utf-8")
|
||||
BUILTIN = (ROOT / "runtime/src/mod_builtin_bezel.c").read_text(encoding="utf-8")
|
||||
CONFIG_H = (ROOT / "recompiler/src/config_loader.h").read_text(encoding="utf-8")
|
||||
HOST_PATH = (ROOT / "recompiler/include/host_path.h").read_text(encoding="utf-8")
|
||||
CONFIG_H =(ROOT / "recompiler/src/config_loader.h").read_text(encoding="utf-8")
|
||||
CONFIG_CPP = (ROOT / "recompiler/src/config_loader.cpp").read_text(
|
||||
encoding="utf-8"
|
||||
)
|
||||
@@ -26,6 +27,18 @@ assert "psx_mod_current_resource_path" in HEADER
|
||||
assert "psx_mod_set_bezel_artwork" in MAIN
|
||||
assert "g_video_renderer = 1;" in MAIN
|
||||
assert "mod-owned OpenGL margin artwork" in MAIN
|
||||
# Relative artwork paths resolve against the exe directory at load time, never
|
||||
# cwd; absolute paths (the builtin resource) pass through host_resolve as-is.
|
||||
LOADER = MAIN[MAIN.index("/* Bezel artwork (Mods): load after the GL context exists. */"):]
|
||||
LOADER = LOADER[: LOADER.index("gl_renderer_set_bezel(")]
|
||||
assert (
|
||||
"PSXRecompV4::host_resolve(\n"
|
||||
" exe_dir_from_argv(argv[0]), std::filesystem::path(g_bezel_path));"
|
||||
) in LOADER
|
||||
assert "host_path_is_absolute(path) ? path : root / path" in HOST_PATH
|
||||
assert "std::fopen" not in LOADER
|
||||
assert "std::filesystem::path bp(g_bezel_path)" not in MAIN
|
||||
assert "resolved against the\n * executable's directory, never the current working directory" in HEADER
|
||||
assert "current_plugin" in MOD_RUNTIME
|
||||
assert 'psx_mod_current_resource_path("artwork"' in BUILTIN
|
||||
assert 'psx_mod_register_activation_plugin("psx.bezel"' in BUILTIN
|
||||
|
||||
Reference in New Issue
Block a user