Capitalize /Dist, /Game, /Save and /System in libretro builds for consistency

This commit is contained in:
刘皓 2025-05-13 17:53:59 -04:00
parent 36075a5add
commit 28fb36af98
No known key found for this signature in database
GPG key ID: 7901753DB465B711
5 changed files with 51 additions and 50 deletions

View file

@ -71,14 +71,14 @@ sandbox::sandbox() : ruby(new struct w2c_ruby), wasi(new wasi_t(ruby)), bindings
);
// Change the current working directory to the game directory
wasm_ptr_t chdir_buf = sandbox_malloc(sizeof("/game"));
wasi->strcpy(chdir_buf, "/game");
wasm_ptr_t chdir_buf = sandbox_malloc(sizeof("/Game"));
wasi->strcpy(chdir_buf, "/Game");
w2c_ruby_mkxp_sandbox_chdir(RB, chdir_buf);
sandbox_free(chdir_buf);
// Determine Ruby command-line arguments
std::vector<std::string> args{"mkxp-z"};
args.push_back("/dist/bin/mkxp-z");
args.push_back("/Dist/bin/mkxp-z");
// Copy all the command-line arguments into the sandbox (sandboxed code can't access memory that's outside the sandbox!)
wasm_ptr_t argv_buf = sandbox_malloc(args.size() * sizeof(wasm_ptr_t));
@ -152,6 +152,6 @@ const char *sandbox::getcwd() {
if (w2c_ruby_mkxp_sandbox_getcwd(ruby.get())) {
return bindings->str(ruby->w2c_mkxp_sandbox_cwd);
} else {
return "/game";
return "/Game";
}
}

View file

@ -49,9 +49,10 @@ wasi_t::w2c_wasi__snapshot__preview1(std::shared_ptr<struct w2c_ruby> ruby) : ru
fdtable.push_back({.type = wasi_fd_type::STDIN});
fdtable.push_back({.type = wasi_fd_type::STDOUT});
fdtable.push_back({.type = wasi_fd_type::STDERR});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/game"), .writable = true}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/save"), .writable = true}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/dist"), .writable = false}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Game"), .writable = true}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Save"), .writable = true}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/System"), .writable = false}});
fdtable.push_back({.type = wasi_fd_type::FS, .handle = new fs_dir {.root = nullptr, .path = std::string("/Dist"), .writable = false}});
}
wasi_t::~w2c_wasi__snapshot__preview1() {

View file

@ -65,9 +65,9 @@ clean-ruby-bindings:
# Cross Ruby (targets WASI)
$(OUTDIR)/ruby/mkxp-sandbox-ruby.h $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h $(OUTDIR)/ruby/mkxp-sandbox-ruby_0.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_1.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_2.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_3.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_4.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_5.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_6.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_7.c &: $(WASM2C) $(LIBDIR)/dist/bin/ruby
$(OUTDIR)/ruby/mkxp-sandbox-ruby.h $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h $(OUTDIR)/ruby/mkxp-sandbox-ruby_0.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_1.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_2.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_3.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_4.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_5.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_6.c $(OUTDIR)/ruby/mkxp-sandbox-ruby_7.c &: $(WASM2C) $(LIBDIR)/Dist/bin/ruby
mkdir -p $(OUTDIR)/ruby
$(WASM2C) $(LIBDIR)/dist/bin/ruby -n ruby --num-outputs=8 -o $(OUTDIR)/ruby/mkxp-sandbox-ruby.c
$(WASM2C) $(LIBDIR)/Dist/bin/ruby -n ruby --num-outputs=8 -o $(OUTDIR)/ruby/mkxp-sandbox-ruby.c
# Find all the function types declared using `FUNC_TYPE_DECL_EXTERN_T` and redeclare them as macros to fix the "initializer element is not constant" compilation error that occurs when using GCC versions earlier than 8.1.0
rm -f $(OUTDIR)/ruby/mkxp-sandbox-ruby-func-types.h
for func_type in $$($(GREP) -r 'FUNC_TYPE_DECL_EXTERN_T *([^()]*)' $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h | $(GREP) -v '# *define' | $(SED) -e 's/FUNC_TYPE_DECL_EXTERN_T *( *\(.*\) *).*/\1/'); do \
@ -79,26 +79,26 @@ $(OUTDIR)/ruby/mkxp-sandbox-ruby.h $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h $(OUT
$(SED) -i 's/__has_builtin *([^()]*)/0/g' $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h
$(SED) -i 's/#error "Missing implementation of __builtin_add_overflow or _addcarry_u64"/return __builtin_add_overflow(a, b, resptr);/g' $(OUTDIR)/ruby/mkxp-sandbox-ruby-impl.h
$(OUTDIR)/dist.zip: $(LIBDIR)/dist/bin/ruby $(RUBY) $(DOWNLOADS)/crossruby/BSDL $(DOWNLOADS)/crossruby/COPYING $(DOWNLOADS)/crossruby/COPYING.ja
rm -rf $(LIBDIR)/_dist
cp -r $(LIBDIR)/dist $(LIBDIR)/_dist
rm $(LIBDIR)/_dist/bin/ruby
rm $(LIBDIR)/_dist/lib/libruby-static.a
rm -r $(LIBDIR)/_dist/include
rm -r $(LIBDIR)/_dist/share
rm -r $(LIBDIR)/_dist/lib/ruby/gems
rm -r $(LIBDIR)/_dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/bundler
rm -r $(LIBDIR)/_dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/rdoc
rm -r $(LIBDIR)/_dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/rubygems
echo '# This is a Ruby script that does nothing. We make Ruby load this file on startup just because Ruby needs to load a script on startup for some reason.' > $(LIBDIR)/_dist/bin/mkxp-z
cp $(DOWNLOADS)/crossruby/BSDL $(LIBDIR)/_dist/lib/ruby
cp $(DOWNLOADS)/crossruby/COPYING $(LIBDIR)/_dist/lib/ruby
cp $(DOWNLOADS)/crossruby/COPYING.ja $(LIBDIR)/_dist/lib/ruby
$(OUTDIR)/dist.zip: $(LIBDIR)/Dist/bin/ruby $(RUBY) $(DOWNLOADS)/crossruby/BSDL $(DOWNLOADS)/crossruby/COPYING $(DOWNLOADS)/crossruby/COPYING.ja
rm -rf $(LIBDIR)/_Dist
cp -r $(LIBDIR)/Dist $(LIBDIR)/_Dist
rm $(LIBDIR)/_Dist/bin/ruby
rm $(LIBDIR)/_Dist/lib/libruby-static.a
rm -r $(LIBDIR)/_Dist/include
rm -r $(LIBDIR)/_Dist/share
rm -r $(LIBDIR)/_Dist/lib/ruby/gems
rm -r $(LIBDIR)/_Dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/bundler
rm -r $(LIBDIR)/_Dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/rdoc
rm -r $(LIBDIR)/_Dist/lib/ruby/$(shell $(RUBY) -e 'puts RUBY_VERSION.split(".")[..1].join(".")').0/rubygems
echo '# This is a Ruby script that does nothing. We make Ruby load this file on startup just because Ruby needs to load a script on startup for some reason.' > $(LIBDIR)/_Dist/bin/mkxp-z
cp $(DOWNLOADS)/crossruby/BSDL $(LIBDIR)/_Dist/lib/ruby
cp $(DOWNLOADS)/crossruby/COPYING $(LIBDIR)/_Dist/lib/ruby
cp $(DOWNLOADS)/crossruby/COPYING.ja $(LIBDIR)/_Dist/lib/ruby
rm -f $(OUTDIR)/dist.zip
cd $(LIBDIR)/_dist && $(ZIP) -r $(OUTDIR)/dist.zip *
rm -r $(LIBDIR)/_dist
cd $(LIBDIR)/_Dist && $(ZIP) -r $(OUTDIR)/dist.zip *
rm -r $(LIBDIR)/_Dist
$(LIBDIR)/dist/bin/ruby: $(DOWNLOADS)/crossruby/Makefile ruby-bindings.h
$(LIBDIR)/Dist/bin/ruby: $(DOWNLOADS)/crossruby/Makefile ruby-bindings.h
cd $(DOWNLOADS)/crossruby && $(MAKE) install DESTDIR=$(LIBDIR)
$(OUTDIR)/sandbox-bindgen/mkxp-sandbox-bindgen.cpp $(OUTDIR)/sandbox-bindgen/mkxp-sandbox-bindgen.h &: sandbox-bindgen.rb $(LIBDIR)/tags $(RUBY)
@ -116,7 +116,7 @@ $(LIBDIR)/tags.c: $(DOWNLOADS)/crossruby/.ext/include/$(TARGET)/ruby/config.h
$(DOWNLOADS)/crossruby/Makefile $(DOWNLOADS)/crossruby/.ext/include/$(TARGET)/ruby/config.h $(DOWNLOADS)/crossruby/BSDL $(DOWNLOADS)/crossruby/COPYING $(DOWNLOADS)/crossruby/COPYING.ja &: $(DOWNLOADS)/crossruby/configure $(RUBY) $(LIBDIR)/usr/local/lib/libyaml.a $(LIBDIR)/usr/local/lib/libz.a
cd $(DOWNLOADS)/crossruby && ./configure \
--prefix=/dist \
--prefix=/Dist \
--host $(TARGET) \
--build $(shell $(RUBY) -e 'puts(RbConfig::CONFIG["host"])') \
--with-static-linked-ext \

View file

@ -647,7 +647,7 @@ static bool init_sandbox() {
parsed_game_path = parsed_game_path.substr(0, last_slash_index);
}
fs->addPath(parsed_game_path.c_str(), "/game");
fs->addPath(parsed_game_path.c_str(), "/Game");
conf.emplace();
{
@ -737,15 +737,15 @@ static bool init_sandbox() {
thread_data.emplace(nullptr, nullptr, nullptr, nullptr, 60, 1, *conf);
PHYSFS_File *rgssad;
if ((rgssad = PHYSFS_openRead(("/game/" + conf->execName + ".rgssad").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgssad").c_str(), "/game", 1);
} else if ((rgssad = PHYSFS_openRead(("/game/" + conf->execName + ".rgss2a").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgss2a").c_str(), "/game", 1);
} else if ((rgssad = PHYSFS_openRead(("/game/" + conf->execName + ".rgss3a").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgss3a").c_str(), "/game", 1);
if ((rgssad = PHYSFS_openRead(("/Game/" + conf->execName + ".rgssad").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgssad").c_str(), "/Game", 1);
} else if ((rgssad = PHYSFS_openRead(("/Game/" + conf->execName + ".rgss2a").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgss2a").c_str(), "/Game", 1);
} else if ((rgssad = PHYSFS_openRead(("/Game/" + conf->execName + ".rgss3a").c_str())) != nullptr) {
PHYSFS_mountHandle(rgssad, ('/' + conf->execName + ".rgss3a").c_str(), "/Game", 1);
}
PHYSFS_mountMemory(dist_zip, dist_zip_len, nullptr, "/dist.zip", "/dist", 1);
PHYSFS_mountMemory(dist_zip, dist_zip_len, nullptr, "/dist.zip", "/Dist", 1);
}
{
@ -773,11 +773,11 @@ static bool init_sandbox() {
return false;
}
PHYSFS_mount(system_root_path.c_str(), "/system", true);
PHYSFS_mount(system_root_path.c_str(), "/System", true);
// Mount each RTP declared in mkxp.json to the game directory
for (const std::string &rtp : conf->rtps) {
std::string path("/system" + fs->normalize(rtp.c_str(), false, true, "/RTP"));
std::string path("/System" + fs->normalize(rtp.c_str(), false, true, "/RTP"));
std::string rtp_path(system_root_path.c_str());
#ifdef _WIN32
@ -785,7 +785,7 @@ static bool init_sandbox() {
#else
rtp_path.push_back('/');
#endif // _WIN32
rtp_path.append(path.c_str() + sizeof "/system/" - 1);
rtp_path.append(path.c_str() + sizeof "/System/" - 1);
// Check if this is a file or directory
PHYSFS_Stat stat;
@ -795,7 +795,7 @@ static bool init_sandbox() {
if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY) {
// If it's a directory, just mount the path directly
if (!PHYSFS_mount(rtp_path.c_str(), "/game", true)) {
if (!PHYSFS_mount(rtp_path.c_str(), "/Game", true)) {
goto fail;
}
} else {
@ -804,7 +804,7 @@ static bool init_sandbox() {
if (file == nullptr) {
goto fail;
}
if (!PHYSFS_mountHandle(file, path.c_str(), "/game", true)) {
if (!PHYSFS_mountHandle(file, path.c_str(), "/Game", true)) {
PHYSFS_close(file);
goto fail;
}
@ -835,7 +835,7 @@ static bool init_sandbox() {
c = std::tolower(c);
}
PHYSFS_enumerate("/system/RTP", [](void *data_, const char *origdir, const char *fname) {
PHYSFS_enumerate("/System/RTP", [](void *data_, const char *origdir, const char *fname) {
struct data &data = *(struct data *)data_;
std::string rtp(fname);
for (char &c : rtp) {
@ -866,7 +866,7 @@ static bool init_sandbox() {
if (stat.filetype == PHYSFS_FILETYPE_DIRECTORY) {
// If it's a directory, just mount the path directly
if (!PHYSFS_mount(rtp_path.c_str(), "/game", true)) {
if (!PHYSFS_mount(rtp_path.c_str(), "/Game", true)) {
return PHYSFS_ENUM_OK;
}
} else {
@ -878,7 +878,7 @@ static bool init_sandbox() {
if (file == nullptr) {
return PHYSFS_ENUM_OK;
}
if (!PHYSFS_mountHandle(file, path.c_str(), "/game", true)) {
if (!PHYSFS_mountHandle(file, path.c_str(), "/Game", true)) {
PHYSFS_close(file);
return PHYSFS_ENUM_OK;
}
@ -955,12 +955,12 @@ static bool init_sandbox() {
// Mount the subdirectory
PHYSFS_setWriteDir(save_path_subdir.c_str());
fs->addPath(save_path_subdir.c_str(), "/save");
fs->addPath(save_path_subdir.c_str(), "/Save");
{
// PhysFS won't normally allow us to mount the save directory in two locations at once,
// so we temporarily disable the duplicate detection here
struct physfs_allow_duplicates_guard guard;
fs->addPath(save_path_subdir.c_str(), "/game");
fs->addPath(save_path_subdir.c_str(), "/Game");
}
}
}

View file

@ -421,8 +421,8 @@ static PHYSFS_EnumerateCallbackResult cacheEnumCB(void *d, const char *origdir,
throw Exception(Exception::MKXPError, "Game close requested. Aborting path cache enumeration.");
#ifdef MKXPZ_RETRO
// Don't cache the /dist or /system directories because the game doesn't need to access them
if (!*origdir && (!strcmp(fname, "dist") || !strcmp(fname, "system")))
// Don't cache the /Dist or /System directories because the game doesn't need to access them
if (!*origdir && (!strcmp(fname, "Dist") || !strcmp(fname, "System")))
return PHYSFS_ENUM_OK;
#endif // MKXPZ_RETRO
@ -800,9 +800,9 @@ static std::string normalizePath(const char *path, bool absolute, const char *cu
// If path doesn't start with a forward slash, prepend the current working directory before normalizing
if (path_str.empty()) {
path_str = current_working_directory != nullptr ? current_working_directory : mkxp_retro::sandbox.has_value() ? mkxp_retro::sandbox->getcwd() : "/game";
path_str = current_working_directory != nullptr ? current_working_directory : mkxp_retro::sandbox.has_value() ? mkxp_retro::sandbox->getcwd() : "/Game";
} else if (path_str.front() != '/') {
path_str = std::string(current_working_directory != nullptr ? current_working_directory : mkxp_retro::sandbox.has_value() ? mkxp_retro::sandbox->getcwd() : "/game") + '/' + path_str;
path_str = std::string(current_working_directory != nullptr ? current_working_directory : mkxp_retro::sandbox.has_value() ? mkxp_retro::sandbox->getcwd() : "/Game") + '/' + path_str;
}
// Lexically normalize the path