mirror of https://github.com/snes9xgit/snes9x.git
227 lines
5.3 KiB
C++
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");
|
|
}
|