mirror of
https://github.com/coop-deluxe/sm64coopdx.git
synced 2025-10-30 08:01:01 +00:00
189 lines
5.4 KiB
C++
189 lines
5.4 KiB
C++
#include "mod_storage.h"
|
|
|
|
#include <iostream>
|
|
#include <fstream>
|
|
#include <string>
|
|
#include "pc/mini.h"
|
|
|
|
extern "C" {
|
|
#include "pc/platform.h"
|
|
#include "pc/mods/mod.h"
|
|
#include "pc/lua/smlua.h"
|
|
#include "pc/mods/mods_utils.h"
|
|
#include "pc/fs/fs.h"
|
|
#include "pc/debuglog.h"
|
|
}
|
|
|
|
#define C_FIELD extern "C"
|
|
|
|
void strdelete(char* string, const char* substr) {
|
|
// i is used to loop through the string
|
|
u16 i = 0;
|
|
|
|
// store the lengths of the string and substr
|
|
u16 string_length = strlen(string);
|
|
u16 substr_length = strlen(substr);
|
|
|
|
// loop through starting at the first index
|
|
while (i < string_length) {
|
|
// if we find the substr at the current index, delete it
|
|
if (strstr(&string[i], substr) == &string[i]) {
|
|
// determine the string's new length after removing the substr occurrence
|
|
string_length -= substr_length;
|
|
// shift forward the remaining characters in the string after the substr
|
|
// occurrence by the length of substr, effectively removing it!
|
|
for (u16 j = i; j < string_length; j++) {
|
|
string[j] = string[j + substr_length];
|
|
}
|
|
} else {
|
|
i++;
|
|
}
|
|
}
|
|
|
|
string[i] = '\0';
|
|
}
|
|
|
|
bool char_valid(const char* buffer) {
|
|
if (buffer[0] == '\0') { return false; }
|
|
|
|
while (*buffer != '\0') {
|
|
if ((*buffer >= 'a' && *buffer <= 'z') || (*buffer >= 'A' && *buffer <= 'Z') || (*buffer >= '0' && *buffer <= '9') || *buffer == '_' || *buffer == '.' || *buffer == '-') {
|
|
buffer++;
|
|
continue;
|
|
}
|
|
return false;
|
|
}
|
|
|
|
return true;
|
|
}
|
|
|
|
void mod_storage_get_filename(char* dest) {
|
|
const char* path = fs_get_write_path(SAVE_DIRECTORY); // get user path
|
|
snprintf(dest, SYS_MAX_PATH - 1, "%s/%s", path, gLuaActiveMod->relativePath); // append sav folder
|
|
strdelete(dest, ".lua"); // delete ".lua" from sav name
|
|
strcat(dest, SAVE_EXTENSION); // append SAVE_EXTENSION
|
|
normalize_path(dest); // fix any out of place slashes
|
|
}
|
|
|
|
C_FIELD bool mod_storage_save(const char* key, const char* value) {
|
|
if (gLuaActiveMod == NULL) { return false; }
|
|
if (strlen(key) > MAX_KEY_VALUE_LENGTH || strlen(value) > MAX_KEY_VALUE_LENGTH) { return false; }
|
|
if (!char_valid(key) || !char_valid(value)) { return false; }
|
|
|
|
char filename[SYS_MAX_PATH] = { 0 };
|
|
mod_storage_get_filename(filename);
|
|
|
|
// ensure savPath exists
|
|
const char* savPath = fs_get_write_path(SAVE_DIRECTORY);
|
|
if (!fs_sys_dir_exists(savPath)) { fs_sys_mkdir(savPath); }
|
|
|
|
mINI::INIFile file(filename);
|
|
mINI::INIStructure ini;
|
|
file.read(ini);
|
|
|
|
if (ini["storage"].size() > MAX_KEYS) { return false; }
|
|
|
|
ini["storage"][key] = value;
|
|
|
|
file.write(ini);
|
|
file.generate(ini);
|
|
|
|
return true;
|
|
}
|
|
|
|
C_FIELD bool mod_storage_save_number(const char* key, f32 value) {
|
|
// Store string results in a temporary buffer
|
|
// this assumes mod_storage_load will only ever be called by Lua
|
|
static char str[MAX_KEY_VALUE_LENGTH];
|
|
if (floor(value) == value) {
|
|
snprintf(str, MAX_KEY_VALUE_LENGTH, "%d", (s64)value);
|
|
} else {
|
|
snprintf(str, MAX_KEY_VALUE_LENGTH, "%f", value);
|
|
}
|
|
|
|
return mod_storage_save(key, str);
|
|
}
|
|
|
|
C_FIELD bool mod_storage_save_bool(const char* key, bool value) {
|
|
return mod_storage_save(key, value ? "true" : "false");
|
|
}
|
|
|
|
C_FIELD const char* mod_storage_load(const char* key) {
|
|
if (gLuaActiveMod == NULL) { return NULL; }
|
|
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return NULL; }
|
|
if (!char_valid(key)) { return NULL; }
|
|
|
|
char filename[SYS_MAX_PATH] = { 0 };
|
|
mod_storage_get_filename(filename);
|
|
if (!fs_sys_path_exists(filename)) { return NULL; }
|
|
|
|
mINI::INIFile file(filename);
|
|
mINI::INIStructure ini;
|
|
file.read(ini);
|
|
|
|
std::string str = ini["storage"][key];
|
|
if (str.empty()) { return NULL; }
|
|
|
|
// Store string results in a temporary buffer
|
|
// this assumes mod_storage_load will only ever be called by Lua
|
|
static char value[MAX_KEY_VALUE_LENGTH];
|
|
snprintf(value, MAX_KEY_VALUE_LENGTH, "%s", str.c_str());
|
|
return value;
|
|
}
|
|
|
|
C_FIELD f32 mod_storage_load_number(const char* key) {
|
|
const char* value = mod_storage_load(key);
|
|
if (value == NULL) { return 0; }
|
|
|
|
return std::strtof(value, nullptr);
|
|
}
|
|
|
|
C_FIELD bool mod_storage_load_bool(const char* key) {
|
|
const char* value = mod_storage_load(key);
|
|
if (value == NULL) { return false; }
|
|
|
|
return !strcmp(value, "true");
|
|
}
|
|
|
|
C_FIELD bool mod_storage_remove(const char* key) {
|
|
if (gLuaActiveMod == NULL) { return false; }
|
|
if (strlen(key) > MAX_KEY_VALUE_LENGTH) { return false; }
|
|
if (!char_valid((char *)key)) { return false; }
|
|
|
|
char filename[SYS_MAX_PATH] = { 0 };
|
|
mod_storage_get_filename(filename);
|
|
if (!fs_sys_path_exists(filename)) { return false; }
|
|
|
|
mINI::INIFile file(filename);
|
|
mINI::INIStructure ini;
|
|
file.read(ini);
|
|
|
|
if (ini["storage"].remove(key)) {
|
|
file.write(ini);
|
|
file.generate(ini);
|
|
return true;
|
|
}
|
|
|
|
return false;
|
|
}
|
|
|
|
C_FIELD bool mod_storage_clear(void) {
|
|
if (gLuaActiveMod == NULL) { return false; }
|
|
|
|
char filename[SYS_MAX_PATH] = { 0 };
|
|
mod_storage_get_filename(filename);
|
|
if (!fs_sys_path_exists(filename)) { return false; }
|
|
|
|
mINI::INIFile file(filename);
|
|
mINI::INIStructure ini;
|
|
file.read(ini);
|
|
|
|
if (ini["storage"].size() == 0) { return false; }
|
|
|
|
ini["storage"].clear();
|
|
|
|
file.write(ini);
|
|
file.generate(ini);
|
|
|
|
return true;
|
|
}
|