mirror of
https://github.com/N64Recomp/N64ModernRuntime.git
synced 2025-10-30 08:02:29 +00:00
Use file backup system for config files (#29)
This commit is contained in:
parent
e0769a223b
commit
53072cb289
4 changed files with 79 additions and 31 deletions
|
|
@ -8,6 +8,7 @@ add_library(librecomp STATIC
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/dp.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/dp.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/eep.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/eep.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/euc-jp.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/euc-jp.cpp"
|
||||||
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/files.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/flash.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/flash.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/math_routines.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/math_routines.cpp"
|
||||||
"${CMAKE_CURRENT_SOURCE_DIR}/src/overlays.cpp"
|
"${CMAKE_CURRENT_SOURCE_DIR}/src/overlays.cpp"
|
||||||
|
|
|
||||||
14
librecomp/include/librecomp/recomp_files.h
Normal file
14
librecomp/include/librecomp/recomp_files.h
Normal file
|
|
@ -0,0 +1,14 @@
|
||||||
|
#ifndef __RECOMP_FILES_H__
|
||||||
|
#define __RECOMP_FILES_H__
|
||||||
|
|
||||||
|
#include <filesystem>
|
||||||
|
#include <fstream>
|
||||||
|
|
||||||
|
namespace recomp {
|
||||||
|
std::ifstream open_input_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::in);
|
||||||
|
std::ifstream open_input_backup_file(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::in);
|
||||||
|
std::ofstream open_output_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode = std::ios_base::out);
|
||||||
|
bool finalize_output_file_with_backup(const std::filesystem::path& filepath);
|
||||||
|
};
|
||||||
|
|
||||||
|
#endif
|
||||||
51
librecomp/src/files.cpp
Normal file
51
librecomp/src/files.cpp
Normal file
|
|
@ -0,0 +1,51 @@
|
||||||
|
#include "recomp_files.h"
|
||||||
|
|
||||||
|
constexpr std::u8string_view backup_suffix = u8".bak";
|
||||||
|
constexpr std::u8string_view temp_suffix = u8".temp";
|
||||||
|
|
||||||
|
std::ifstream recomp::open_input_backup_file(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||||
|
std::filesystem::path backup_path{filepath};
|
||||||
|
backup_path += backup_suffix;
|
||||||
|
return std::ifstream{backup_path, mode};
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ifstream recomp::open_input_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||||
|
std::ifstream ret{filepath, mode};
|
||||||
|
|
||||||
|
// Check if the file failed to open and open the corresponding backup file instead if so.
|
||||||
|
if (!ret.good()) {
|
||||||
|
return open_input_backup_file(filepath, mode);
|
||||||
|
}
|
||||||
|
|
||||||
|
return ret;
|
||||||
|
}
|
||||||
|
|
||||||
|
std::ofstream recomp::open_output_file_with_backup(const std::filesystem::path& filepath, std::ios_base::openmode mode) {
|
||||||
|
std::filesystem::path temp_path{filepath};
|
||||||
|
temp_path += temp_suffix;
|
||||||
|
std::ofstream temp_file_out{ temp_path, mode };
|
||||||
|
|
||||||
|
return temp_file_out;
|
||||||
|
}
|
||||||
|
|
||||||
|
bool recomp::finalize_output_file_with_backup(const std::filesystem::path& filepath) {
|
||||||
|
std::filesystem::path backup_path{filepath};
|
||||||
|
backup_path += backup_suffix;
|
||||||
|
|
||||||
|
std::filesystem::path temp_path{filepath};
|
||||||
|
temp_path += temp_suffix;
|
||||||
|
|
||||||
|
std::error_code ec;
|
||||||
|
if (std::filesystem::exists(filepath, ec)) {
|
||||||
|
std::filesystem::copy_file(filepath, backup_path, std::filesystem::copy_options::overwrite_existing, ec);
|
||||||
|
if (ec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
std::filesystem::copy_file(temp_path, filepath, std::filesystem::copy_options::overwrite_existing, ec);
|
||||||
|
if (ec) {
|
||||||
|
return false;
|
||||||
|
}
|
||||||
|
std::filesystem::remove(temp_path, ec);
|
||||||
|
return true;
|
||||||
|
}
|
||||||
|
|
@ -6,6 +6,7 @@
|
||||||
#include <mutex>
|
#include <mutex>
|
||||||
#include "recomp.h"
|
#include "recomp.h"
|
||||||
#include "recomp_game.h"
|
#include "recomp_game.h"
|
||||||
|
#include "recomp_files.h"
|
||||||
#include <ultramodern/ultra64.h>
|
#include <ultramodern/ultra64.h>
|
||||||
#include <ultramodern/ultramodern.hpp>
|
#include <ultramodern/ultramodern.hpp>
|
||||||
|
|
||||||
|
|
@ -101,37 +102,24 @@ std::filesystem::path get_save_file_path() {
|
||||||
return config_path / save_folder / (std::u8string{recomp::current_game_id()} + u8".bin");
|
return config_path / save_folder / (std::u8string{recomp::current_game_id()} + u8".bin");
|
||||||
}
|
}
|
||||||
|
|
||||||
std::filesystem::path get_save_file_path_temp() {
|
|
||||||
return config_path / save_folder / (recomp::current_game_id() + u8".bin.temp");
|
|
||||||
}
|
|
||||||
|
|
||||||
std::filesystem::path get_save_file_path_backup() {
|
|
||||||
return config_path / save_folder / (recomp::current_game_id() + u8".bin.bak");
|
|
||||||
}
|
|
||||||
|
|
||||||
void update_save_file() {
|
void update_save_file() {
|
||||||
|
bool saving_failed = false;
|
||||||
{
|
{
|
||||||
std::ofstream save_file{ get_save_file_path_temp(), std::ios_base::binary };
|
std::ofstream save_file = recomp::open_output_file_with_backup(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 };
|
||||||
save_file.write(save_context.save_buffer.data(), save_context.save_buffer.size());
|
save_file.write(save_context.save_buffer.data(), save_context.save_buffer.size());
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions. If you have moved your appdata folder to Dropbox or similar, this can cause issues.");
|
saving_failed = false;
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
if (!saving_failed) {
|
||||||
std::error_code ec;
|
saving_failed = !recomp::finalize_output_file_with_backup(get_save_file_path());
|
||||||
if (std::filesystem::exists(get_save_file_path(), ec)) {
|
|
||||||
std::filesystem::copy_file(get_save_file_path(), get_save_file_path_backup(), std::filesystem::copy_options::overwrite_existing, ec);
|
|
||||||
if (ec) {
|
|
||||||
printf("[ERROR] Failed to copy save file backup\n");
|
|
||||||
}
|
}
|
||||||
}
|
if (saving_failed) {
|
||||||
std::filesystem::copy_file(get_save_file_path_temp(), get_save_file_path(), std::filesystem::copy_options::overwrite_existing, ec);
|
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.");
|
||||||
if (ec) {
|
|
||||||
ultramodern::error_handling::message_box("Failed to write to the save file. Check your file permissions. If you have moved your appdata folder to Dropbox or similar, this can cause issues.");
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
@ -198,25 +186,19 @@ void save_clear(uint32_t start, uint32_t size, char value) {
|
||||||
|
|
||||||
void ultramodern::init_saving(RDRAM_ARG1) {
|
void ultramodern::init_saving(RDRAM_ARG1) {
|
||||||
std::filesystem::path save_file_path = get_save_file_path();
|
std::filesystem::path save_file_path = get_save_file_path();
|
||||||
std::filesystem::path save_file_path_backup = get_save_file_path_backup();
|
|
||||||
|
|
||||||
// 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());
|
||||||
|
|
||||||
// Read the save file if it exists.
|
// Read the save file if it exists.
|
||||||
std::ifstream save_file{ save_file_path, std::ios_base::binary };
|
std::ifstream save_file = recomp::open_input_file_with_backup(save_file_path, std::ios_base::binary);
|
||||||
if (save_file.good()) {
|
if (save_file.good()) {
|
||||||
save_file.read(save_context.save_buffer.data(), save_context.save_buffer.size());
|
save_file.read(save_context.save_buffer.data(), save_context.save_buffer.size());
|
||||||
} else {
|
}
|
||||||
// Reading the save file faield, so try to read the backup save file.
|
else {
|
||||||
std::ifstream save_file_backup{ save_file_path_backup, std::ios_base::binary };
|
|
||||||
if (save_file_backup.good()) {
|
|
||||||
save_file_backup.read(save_context.save_buffer.data(), save_context.save_buffer.size());
|
|
||||||
} else {
|
|
||||||
// Otherwise clear the save file to all zeroes.
|
// Otherwise clear the save file to all zeroes.
|
||||||
save_context.save_buffer.fill(0);
|
save_context.save_buffer.fill(0);
|
||||||
}
|
}
|
||||||
}
|
|
||||||
|
|
||||||
save_context.saving_thread = std::thread{saving_thread_func, PASS_RDRAM};
|
save_context.saving_thread = std::thread{saving_thread_func, PASS_RDRAM};
|
||||||
}
|
}
|
||||||
|
|
|
||||||
Loading…
Add table
Reference in a new issue