diff --git a/CMakeLists.txt b/CMakeLists.txt index 48e6d49..b5d30ca 100644 --- a/CMakeLists.txt +++ b/CMakeLists.txt @@ -326,6 +326,7 @@ set(BINDING_SOURCE binding-mri/gamepad-binding.cpp binding-mri/profiler-binding.cpp binding-mri/audioplayback-binding.cpp + binding-mri/physfs-binding.cpp ) source_group("Binding Source" FILES ${BINDING_SOURCE} ${BINDING_HEADERS}) diff --git a/binding-mri/binding-mri.cpp b/binding-mri/binding-mri.cpp index 4aa1e9a..b6eedc3 100644 --- a/binding-mri/binding-mri.cpp +++ b/binding-mri/binding-mri.cpp @@ -95,6 +95,7 @@ void shaderBindingInit(); void keybindingsBindingInit(); void lightmapBindingInit(); void ProfilerInit(); +void PhysFS_binding_init(); RB_METHOD(mriPrint); RB_METHOD(mriP); @@ -150,6 +151,7 @@ static void mriBindingInit(){ keybindingsBindingInit(); lightmapBindingInit(); ProfilerInit(); + PhysFS_binding_init(); _rb_define_module_function(rb_mKernel, "rgss_main", mriRgssMain); _rb_define_module_function(rb_mKernel, "rgss_stop", mriRgssStop); diff --git a/binding-mri/modloader-binding.cpp b/binding-mri/modloader-binding.cpp index c79c137..58f25c7 100644 --- a/binding-mri/modloader-binding.cpp +++ b/binding-mri/modloader-binding.cpp @@ -1,25 +1,14 @@ //https://silverhammermba.github.io/emberb/c/ //https://docs.ruby-lang.org/capi/en/master/d8/d68/include_2ruby_2internal_2intern_2string_8h.html #include "binding-util.h" -#include "sharedstate.h" -#include "filesystem.h" #include "util.h" #include "debugwriter.h" -#include "ruby/encoding.h" -#include "ruby/intern.h" -#include "ruby/thread.h" #include "modloader.h" #include "config.h" #include -#include -#include -#include -#include -#include +#include #include - -namespace fs = std::filesystem; - +#include VALUE meow(const std::vector vec){ VALUE ary = rb_ary_new_capa((long)vec.size()); for (const std::string &s : vec) { @@ -29,7 +18,7 @@ VALUE meow(const std::vector vec){ return ary; } -static VALUE hooks(int argc, VALUE *argv, VALUE self) { +static VALUE hooks(int argc, VALUE *argv, VALUE self){ VALUE v_path = Qnil; rb_scan_args(argc, argv, "01", &v_path); std::string hook_path = "hooks"; @@ -38,23 +27,54 @@ static VALUE hooks(int argc, VALUE *argv, VALUE self) { hook_path = StringValueCStr(v_path); } - std::vector files = {}; - if(!std::filesystem::exists(hook_path)){ - return meow(files); - } - for (const auto &entry : std::filesystem::directory_iterator(hook_path, std::filesystem::directory_options::skip_permission_denied)) { - std::error_code ec; - auto p = entry.path(); - if (!std::filesystem::is_regular_file(p, ec) || ec) continue; - - auto ext = p.extension().string(); - if (ext != ".rb") continue; - - std::string full = p.string(); - Debug() << "[MODLOADER] Executing hook: " << full; - files.push_back(full); - } - return meow(files); + std::vector files; + if (!PHYSFS_exists(hook_path.c_str())) { + return meow(files); + } + + PHYSFS_Stat dir_stat{}; + + if ( + PHYSFS_stat(hook_path.c_str(), &dir_stat) == 0 || + dir_stat.filetype != PHYSFS_FILETYPE_DIRECTORY + ) { + return meow(files); + } + + char **list = PHYSFS_enumerateFiles(hook_path.c_str()); + + if (list == nullptr) { + return meow(files); + } + + for (char **entry = list; *entry != nullptr; ++entry) { + std::string name = *entry; + std::string full_path = hook_path; + + if (!full_path.empty() && full_path.back() != '/') { + full_path += '/'; + } + + full_path += name; + PHYSFS_Stat file_stat{}; + if (PHYSFS_stat(full_path.c_str(), &file_stat) == 0) { + continue; + } + + if (file_stat.filetype != PHYSFS_FILETYPE_REGULAR) { + continue; + } + + if (name.size() < 3 || + name.compare(name.size() - 3, 3, ".rb") != 0) { + continue; + } + + Debug() << "[MODLOADER] Executing hook: " << full_path; + files.push_back(full_path); + } + PHYSFS_freeList(list); + return meow(files); } void ModLoaderBindingInit(){ diff --git a/binding-mri/module_rpg1.rb b/binding-mri/module_rpg1.rb index e378211..05d0bed 100644 --- a/binding-mri/module_rpg1.rb +++ b/binding-mri/module_rpg1.rb @@ -1,6 +1,5 @@ module Kernel alias_method :original_puts, :puts - def puts(*args) string = "" args.each do |arg| @@ -9,7 +8,6 @@ module Kernel MKXP.puts string return nil end - module_function :puts end @@ -17,15 +15,7 @@ module RPG module Cache @cache = {} def self.load_bitmap(folder_name, filename, hue = 0) - if ModLoader::IS_ENABLED - if File.exist?("/mod-storage/" + folder_name + filename) - path = Graphics.adapted_file("/mod-storage/" + folder_name + filename) - else - path = Graphics.adapted_file(folder_name + filename) - end - else - path = Graphics.adapted_file(folder_name + filename) - end + path = Graphics.adapted_file(folder_name + filename) if not @cache.include?(path) or @cache[path].disposed? if filename != "" @cache[path] = Bitmap.new(path) @@ -1323,7 +1313,7 @@ module RPG return unless ModLoader::IS_ENABLED return unless path.is_a?(String) ModLoader.hooks(path).each do |item| - eval(File.read(item), b) + eval(PhysFS.read(item), b) end end end diff --git a/binding-mri/physfs-binding.cpp b/binding-mri/physfs-binding.cpp new file mode 100644 index 0000000..b84e643 --- /dev/null +++ b/binding-mri/physfs-binding.cpp @@ -0,0 +1,70 @@ +#include +#include "binding-util.h" +#include "sharedstate.h" +#include "filesystem.h" +#include "util.h" +#include +#include +#include +VALUE module = Qnil; +VALUE rb_ePhysFSError = Qnil; + +std::string toStdString(VALUE v) { + Check_Type(v, T_STRING); + return std::string{ RSTRING_PTR(v), static_cast(RSTRING_LEN(v)) }; +} + +static VALUE rb_PhysFS_Exist(VALUE, VALUE path) { + if(PHYSFS_exists(StringValuePtr(path)) > 0){ + return Qtrue; + }else{ + return Qfalse; + } +} + +static VALUE rb_PhysFS_Directory(VALUE, VALUE path) { + if(PHYSFS_isDirectory(StringValuePtr(path)) > 0){ + return Qtrue; + }else{ + return Qfalse; + } +} + +std::vector loadFully(const char* path) { + PHYSFS_File* file = PHYSFS_openRead(path); + if (!file){ + WarnMsg("Failed to load PhysFS file %s", path); + return {}; + } + const auto length = PHYSFS_fileLength(file); + std::vector buffer; + if (length > 0) { + buffer.resize(static_cast(length)); + const auto got = PHYSFS_readBytes(file, buffer.data(), static_cast(length)); + if (got != length && !PHYSFS_eof(file)) { + PHYSFS_close(file); + WarnMsg("PhysFS readBytes failed for '%s'", path); + } + buffer.resize(static_cast(got)); + } + PHYSFS_close(file); + return buffer; +} + +static VALUE rb_PhysFS_Read(VALUE, VALUE path) { + try { + const auto buf = loadFully(StringValuePtr(path)); + return rb_str_new(buf.data(), static_cast(buf.size())); + } catch (const std::exception& e) { + rb_raise(rb_ePhysFSError, "%s", e.what()); + } + return Qnil; +} + +void PhysFS_binding_init(){ + VALUE module = rb_define_module("PhysFS"); + rb_ePhysFSError = rb_define_class_under(module, "Error", rb_eStandardError); + rb_define_module_function(module, "exist?", rb_PhysFS_Exist, 1); + rb_define_module_function(module, "directory?", rb_PhysFS_Directory, 1); + rb_define_module_function(module, "read", rb_PhysFS_Read, 1); +} diff --git a/scripts/Dynamic_Resolution.rb b/scripts/Dynamic_Resolution.rb index 083bae7..8cb6ade 100644 --- a/scripts/Dynamic_Resolution.rb +++ b/scripts/Dynamic_Resolution.rb @@ -40,9 +40,13 @@ module Graphics def self.adapted_file(path, extention = ".png") file_tag = RESOLUTIONS[Settings[:resolution] || 999]&.[](:file_tag) || "" - if File.exist?(path + file_tag + extention) - return path + file_tag + if PhysFS.exist?(path + file_tag + extention) + return path + file_tag + else + if File.exist?(path + file_tag + extention) + return path + file_tag + end end path end -end \ No newline at end of file +end diff --git a/scripts/Graphics.rb b/scripts/Graphics.rb new file mode 100644 index 0000000..e69de29 diff --git a/scripts/Main.rb b/scripts/Main.rb index d35a355..de3f1f5 100644 --- a/scripts/Main.rb +++ b/scripts/Main.rb @@ -17,6 +17,7 @@ end begin RPG::Mod.exec_hooks("hooks/Main/start", binding) + print PhysFS.exist?("gaysex") $console = Graphics.fullscreen Graphics.frame_rate = 60 Font.default_size = 20 diff --git a/src/modloader.cpp b/src/modloader.cpp index 9a6d695..e839e3a 100644 --- a/src/modloader.cpp +++ b/src/modloader.cpp @@ -15,11 +15,12 @@ #include #include #include - +#include +#include +#include +#include #include "the_modded_machine.png.xxd" - namespace fs = std::filesystem; - static bool stop_render = false; const static std::size_t N = 46; @@ -94,7 +95,7 @@ void ModLoader(Config conf, SDL_Window* win){ std::string full = p.string(); if (ext == ".zip") { - int ok = PHYSFS_mount(full.c_str(), "/mod-storage", 0); + int ok = PHYSFS_mount(full.c_str(), "", 0); mod_list.emplace_back(full); modloader_add_to_log("Added mod " + full); mods_count++;