snes9x/gtk/src/gtk_file.cpp

227 lines
5.3 KiB
C++

/*****************************************************************************\
Snes9x - Portable Super Nintendo Entertainment System (TM) emulator.
This file is licensed under the Snes9x License.
For further information, consult the LICENSE file in the root directory.
\*****************************************************************************/
#include <sys/stat.h>
#include <errno.h>
#include <string>
#include <filesystem>
#include "gtk_compat.h"
#include "gtk_s9x.h"
#include "display.h"
#include "memmap.h"
#include "snapshot.h"
#include "cheats.h"
namespace fs = std::filesystem;
using namespace std::literals;
std::string S9xGetFilenameInc(std::string e, enum s9x_getdirtype dirtype)
{
fs::path rom_filename(Memory.ROMFilename);
fs::path filename_base(S9xGetDirectory(dirtype));
filename_base /= rom_filename.filename();
fs::path new_filename;
if (e[0] != '.')
e = "." + e;
int i = 0;
do
{
std::string new_extension = std::to_string(i);
while (new_extension.length() < 3)
new_extension = "0"s + new_extension;
new_extension += e;
new_filename = filename_base;
new_filename.replace_extension(new_extension);
i++;
} while (fs::exists(new_filename));
return new_filename;
}
std::string S9xGetDirectory(enum s9x_getdirtype dirtype)
{
std::string dirname;
switch (dirtype)
{
case HOME_DIR:
dirname = get_config_dir();
break;
case SNAPSHOT_DIR:
dirname = gui_config->savestate_directory;
break;
case PATCH_DIR:
dirname = gui_config->patch_directory;
break;
case CHEAT_DIR:
dirname = gui_config->cheat_directory;
break;
case SRAM_DIR:
dirname = gui_config->sram_directory;
break;
case SCREENSHOT_DIR:
case SPC_DIR:
dirname = gui_config->export_directory;
break;
default:
dirname = "";
}
/* Check if directory exists, make it and/or set correct permissions */
if (dirtype != HOME_DIR && dirname != "")
{
fs::path path(dirname);
if (!fs::exists(path))
{
fs::create_directory(path);
}
else if ((fs::status(path).permissions() & fs::perms::owner_write) == fs::perms::none)
{
fs::permissions(path, fs::perms::owner_write, fs::perm_options::add);
}
}
/* Anything else, use ROM filename path */
if (dirname == "" && !Memory.ROMFilename.empty())
{
fs::path path(Memory.ROMFilename);
path.remove_filename();
if (!fs::is_directory(path))
dirname = fs::current_path();
else
dirname = path;
}
return dirname;
}
bool8 S9xOpenSnapshotFile(const char *filename, bool8 read_only, STREAM *file)
{
if (read_only)
{
if ((*file = OPEN_STREAM(filename, "rb")))
return (true);
else
fprintf(stderr, "Failed to open file stream for reading.\n");
}
else
{
if ((*file = OPEN_STREAM(filename, "wb")))
{
return (true);
}
else
{
fprintf(stderr, "Couldn't open stream with zlib.\n");
}
}
fprintf(stderr, "Couldn't open snapshot file:\n%s\n", filename);
return false;
}
void S9xCloseSnapshotFile(STREAM file)
{
CLOSE_STREAM(file);
}
void S9xAutoSaveSRAM()
{
Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR).c_str());
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR).c_str());
}
void S9xLoadState(std::string filename)
{
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR).c_str());
if (S9xUnfreezeGame(filename.c_str()))
{
auto info_string = filename + " loaded"s;
S9xSetInfoString(info_string.c_str());
}
else
{
fprintf(stderr, "Failed to load state file: %s\n", filename.c_str());
}
}
void S9xSaveState(std::string filename)
{
if (S9xFreezeGame(filename.c_str()))
{
auto info_string = filename + " saved"s;
S9xSetInfoString(info_string.c_str());
}
else
{
fprintf(stderr, "Couldn't save state file: %s\n", filename.c_str());
}
}
static fs::path save_slot_path(int slot)
{
std::string extension = std::to_string(slot);
while (extension.length() < 3)
extension = "0"s + extension;
fs::path path(S9xGetDirectory(SNAPSHOT_DIR));
path /= fs::path(Memory.ROMFilename).filename();
path.replace_extension(extension);
return path;
}
/* QuickSave/Load from S9x base controls.cpp */
void S9xQuickSaveSlot(int slot)
{
if (!gui_config->rom_loaded)
return;
auto filename = save_slot_path(slot);
if (S9xFreezeGame(filename.c_str()))
{
auto info_string = filename.filename().string() + " saved";
S9xSetInfoString(info_string.c_str());
}
}
void S9xQuickLoadSlot(int slot)
{
if (!gui_config->rom_loaded)
return;
auto filename = save_slot_path(slot);
if (fs::exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR).c_str());
if (S9xUnfreezeGame(filename.c_str()))
{
auto info_string = filename.filename().string() + " loaded";
S9xSetInfoString(info_string.c_str());
return;
}
S9xMessage(S9X_ERROR,
S9X_FREEZE_FILE_NOT_FOUND,
"Freeze file not found");
}