Add mod API export to get the save file path (#102)

This commit is contained in:
Wiseguy 2025-04-09 01:15:10 -04:00 committed by GitHub
parent 1f2a5838ab
commit bb6b3b1645
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
3 changed files with 36 additions and 23 deletions

View file

@ -28,29 +28,40 @@ void recomp_get_config_double(uint8_t* rdram, recomp_context* ctx, size_t mod_in
} }
} }
template <typename StringType>
void return_string(uint8_t* rdram, recomp_context* ctx, const StringType& str) {
// Allocate space in the recomp heap to hold the string, including the null terminator.
size_t alloc_size = (str.size() + 1 + 15) & ~15;
gpr offset = reinterpret_cast<uint8_t*>(recomp::alloc(rdram, alloc_size)) - rdram;
gpr addr = offset + 0xFFFFFFFF80000000ULL;
// Copy the string's data into the allocated memory and null terminate it.
for (size_t i = 0; i < str.size(); i++) {
MEM_B(i, addr) = str[i];
}
MEM_B(str.size(), addr) = 0;
// Return the allocated memory.
ctx->r2 = addr;
}
void recomp_get_config_string(uint8_t* rdram, recomp_context* ctx, size_t mod_index) { void recomp_get_config_string(uint8_t* rdram, recomp_context* ctx, size_t mod_index) {
recomp::mods::ConfigValueVariant val = recomp::mods::get_mod_config_value(mod_index, _arg_string<0>(rdram, ctx)); recomp::mods::ConfigValueVariant val = recomp::mods::get_mod_config_value(mod_index, _arg_string<0>(rdram, ctx));
if (std::string* as_string = std::get_if<std::string>(&val)) { if (std::string* as_string = std::get_if<std::string>(&val)) {
const std::string& str = *as_string; return_string(rdram, ctx, *as_string);
// Allocate space in the recomp heap to hold the string, including the null terminator.
size_t alloc_size = (str.size() + 1 + 15) & ~15;
gpr offset = reinterpret_cast<uint8_t*>(recomp::alloc(rdram, alloc_size)) - rdram;
gpr addr = offset + 0xFFFFFFFF80000000ULL;
// Copy the string's data into the allocated memory and null terminate it.
for (size_t i = 0; i < str.size(); i++) {
MEM_B(i, addr) = str[i];
}
MEM_B(str.size(), addr) = 0;
// Return the allocated memory.
ctx->r2 = addr;
} }
else { else {
_return(ctx, NULLPTR); _return(ctx, NULLPTR);
} }
} }
void recomp_free_config_string(uint8_t* rdram, recomp_context* ctx) {
gpr str_rdram = (gpr)_arg<0, PTR(char)>(rdram, ctx);
gpr offset = str_rdram - 0xFFFFFFFF80000000ULL;
recomp::free(rdram, rdram + offset);
}
void recomp_get_mod_version(uint8_t* rdram, recomp_context* ctx, size_t mod_index) { void recomp_get_mod_version(uint8_t* rdram, recomp_context* ctx, size_t mod_index) {
uint32_t* major_out = _arg<0, uint32_t*>(rdram, ctx); uint32_t* major_out = _arg<0, uint32_t*>(rdram, ctx);
uint32_t* minor_out = _arg<1, uint32_t*>(rdram, ctx); uint32_t* minor_out = _arg<1, uint32_t*>(rdram, ctx);
@ -73,18 +84,18 @@ void recomp_change_save_file(uint8_t* rdram, recomp_context* ctx, size_t mod_ind
ultramodern::change_save_file(mod_id_u8, name_u8); ultramodern::change_save_file(mod_id_u8, name_u8);
} }
void recomp_free_config_string(uint8_t* rdram, recomp_context* ctx) { void recomp_get_save_file_path(uint8_t* rdram, recomp_context* ctx) {
gpr str_rdram = (gpr)_arg<0, PTR(char)>(rdram, ctx); std::filesystem::path save_file_path = ultramodern::get_save_file_path();
gpr offset = str_rdram - 0xFFFFFFFF80000000ULL;
recomp::free(rdram, rdram + offset); return_string(rdram, ctx, std::filesystem::absolute(save_file_path).u8string());
} }
void recomp::mods::register_config_exports() { void recomp::mods::register_config_exports() {
recomp::overlays::register_ext_base_export("recomp_get_config_u32", recomp_get_config_u32); recomp::overlays::register_ext_base_export("recomp_get_config_u32", recomp_get_config_u32);
recomp::overlays::register_ext_base_export("recomp_get_config_double", recomp_get_config_double); recomp::overlays::register_ext_base_export("recomp_get_config_double", recomp_get_config_double);
recomp::overlays::register_ext_base_export("recomp_get_config_string", recomp_get_config_string); recomp::overlays::register_ext_base_export("recomp_get_config_string", recomp_get_config_string);
recomp::overlays::register_base_export("recomp_free_config_string", recomp_free_config_string);
recomp::overlays::register_ext_base_export("recomp_get_mod_version", recomp_get_mod_version); recomp::overlays::register_ext_base_export("recomp_get_mod_version", recomp_get_mod_version);
recomp::overlays::register_ext_base_export("recomp_change_save_file", recomp_change_save_file); recomp::overlays::register_ext_base_export("recomp_change_save_file", recomp_change_save_file);
recomp::overlays::register_base_export("recomp_free_config_string", recomp_free_config_string); recomp::overlays::register_base_export("recomp_get_save_file_path", recomp_get_save_file_path);
} }

View file

@ -101,7 +101,7 @@ const std::u8string save_folder = u8"saves";
extern std::filesystem::path config_path; extern std::filesystem::path config_path;
std::filesystem::path get_save_file_path() { std::filesystem::path ultramodern::get_save_file_path() {
return save_context.save_file_path; return save_context.save_file_path;
} }
@ -116,7 +116,7 @@ void set_save_file_path(const std::u8string& subfolder, const std::u8string& nam
void update_save_file() { void update_save_file() {
bool saving_failed = false; bool saving_failed = false;
{ {
std::ofstream save_file = recomp::open_output_file_with_backup(get_save_file_path(), std::ios_base::binary); std::ofstream save_file = recomp::open_output_file_with_backup(ultramodern::get_save_file_path(), std::ios_base::binary);
if (save_file.good()) { if (save_file.good()) {
std::lock_guard lock{ save_context.save_buffer_mutex }; std::lock_guard lock{ save_context.save_buffer_mutex };
@ -127,7 +127,7 @@ void update_save_file() {
} }
} }
if (!saving_failed) { if (!saving_failed) {
saving_failed = !recomp::finalize_output_file_with_backup(get_save_file_path()); saving_failed = !recomp::finalize_output_file_with_backup(ultramodern::get_save_file_path());
} }
if (saving_failed) { if (saving_failed) {
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions and whether the save folder has been moved to Dropbox or similar, as this can cause issues."); ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions and whether the save folder has been moved to Dropbox or similar, as this can cause issues.");
@ -225,7 +225,7 @@ size_t get_save_size(recomp::SaveType save_type) {
} }
void read_save_file() { void read_save_file() {
std::filesystem::path save_file_path = get_save_file_path(); std::filesystem::path save_file_path = ultramodern::get_save_file_path();
// Ensure the save file directory exists. // Ensure the save file directory exists.
std::filesystem::create_directories(save_file_path.parent_path()); std::filesystem::create_directories(save_file_path.parent_path());

View file

@ -6,6 +6,7 @@
#include <stdexcept> #include <stdexcept>
#include <span> #include <span>
#include <chrono> #include <chrono>
#include <filesystem>
#undef MOODYCAMEL_DELETE_FUNCTION #undef MOODYCAMEL_DELETE_FUNCTION
#define MOODYCAMEL_DELETE_FUNCTION = delete #define MOODYCAMEL_DELETE_FUNCTION = delete
@ -39,6 +40,7 @@ void init_thread_cleanup();
// Saving // Saving
void change_save_file(const std::u8string& subfolder, const std::u8string& name); void change_save_file(const std::u8string& subfolder, const std::u8string& name);
std::filesystem::path get_save_file_path();
// Thread queues. // Thread queues.
constexpr PTR(PTR(OSThread)) running_queue = (PTR(PTR(OSThread)))-1; constexpr PTR(PTR(OSThread)) running_queue = (PTR(PTR(OSThread)))-1;