snes9x/gtk/src/gtk_file.cpp

382 lines
8.5 KiB
C++
Raw Normal View History

/*****************************************************************************\
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.
\*****************************************************************************/
2010-09-25 17:46:12 +02:00
#include <sys/stat.h>
2010-09-26 11:19:15 +02:00
#include <errno.h>
2010-09-25 17:46:12 +02:00
#include "gtk_compat.h"
2010-09-25 17:46:12 +02:00
#include "gtk_s9x.h"
#include "display.h"
#include "memmap.h"
#include "snapshot.h"
#include "cheats.h"
2010-09-25 17:46:12 +02:00
2018-05-14 03:17:02 +02:00
static char buf[PATH_MAX];
2010-09-25 17:46:12 +02:00
const char *S9xGetFilenameInc(const char *e, enum s9x_getdirtype dirtype)
2010-09-25 17:46:12 +02:00
{
static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
2010-09-25 17:46:12 +02:00
unsigned int i = 0;
struct stat buf;
const char *d;
2010-09-25 17:46:12 +02:00
_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
d = S9xGetDirectory(dirtype);
2010-09-25 17:46:12 +02:00
do
{
snprintf(filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e);
2010-09-25 17:46:12 +02:00
i++;
} while (stat(filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */
2010-09-25 17:46:12 +02:00
return (filename);
}
const char *S9xGetDirectory(enum s9x_getdirtype dirtype)
2010-09-25 17:46:12 +02:00
{
static char path[PATH_MAX + 1];
switch (dirtype)
{
case HOME_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", get_config_dir().c_str());
break;
2010-09-25 17:46:12 +02:00
case SNAPSHOT_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", gui_config->savestate_directory.c_str());
break;
2010-09-25 17:46:12 +02:00
case PATCH_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", gui_config->patch_directory.c_str());
break;
2010-09-26 11:19:15 +02:00
case CHEAT_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", gui_config->cheat_directory.c_str());
break;
2010-09-26 11:19:15 +02:00
case SRAM_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", gui_config->sram_directory.c_str());
break;
2010-09-25 17:46:12 +02:00
case SCREENSHOT_DIR:
case SPC_DIR:
2020-06-21 22:25:54 +02:00
snprintf(path, PATH_MAX + 1, "%s", gui_config->export_directory.c_str());
break;
2010-09-25 17:46:12 +02:00
default:
path[0] = '\0';
2010-09-26 11:19:15 +02:00
}
2010-09-25 17:46:12 +02:00
/* Check if directory exists, make it and/or set correct permissions */
2010-09-26 11:19:15 +02:00
if (dirtype != HOME_DIR && path[0] != '\0')
{
struct stat file_info;
if (stat(path, &file_info) == -1)
{
mkdir(path, 0755);
chmod(path, 0755);
}
else if (!(file_info.st_mode & 0700))
chmod(path, file_info.st_mode | 0700);
2010-09-26 11:19:15 +02:00
}
2010-09-25 17:46:12 +02:00
2010-09-26 11:19:15 +02:00
/* Anything else, use ROM filename path */
if (path[0] == '\0')
{
char *loc;
2010-09-25 17:46:12 +02:00
strcpy(path, Memory.ROMFilename);
2010-09-25 17:46:12 +02:00
loc = strrchr(path, SLASH_CHAR);
2010-09-25 17:46:12 +02:00
2010-09-26 11:19:15 +02:00
if (loc == NULL)
{
if (getcwd(path, PATH_MAX + 1) == NULL)
2010-09-26 11:19:15 +02:00
{
strcpy(path, getenv("HOME"));
2010-09-26 11:19:15 +02:00
}
}
else
{
path[loc - path] = '\0';
}
2010-09-25 17:46:12 +02:00
}
return path;
}
const char *S9xGetFilename(const char *ex, enum s9x_getdirtype dirtype)
2010-09-25 17:46:12 +02:00
{
static char filename[PATH_MAX + 1];
char dir[_MAX_DIR + 1];
char drive[_MAX_DRIVE + 1];
char fname[_MAX_FNAME + 1];
char ext[_MAX_EXT + 1];
2010-09-25 17:46:12 +02:00
_splitpath(Memory.ROMFilename, drive, dir, fname, ext);
2010-09-25 17:46:12 +02:00
snprintf(filename, sizeof(filename), "%s" SLASH_STR "%s%s",
S9xGetDirectory(dirtype), fname, ex);
2010-09-25 17:46:12 +02:00
return (filename);
}
const char *S9xBasename(const char *f)
2010-09-25 17:46:12 +02:00
{
const char *p;
if ((p = strrchr(f, '/')) != NULL || (p = strrchr(f, '\\')) != NULL)
2010-09-25 17:46:12 +02:00
return (p + 1);
return f;
}
const char *S9xBasenameNoExt(const char *f)
2010-09-25 17:46:12 +02:00
{
static char filename[PATH_MAX];
2010-09-25 17:46:12 +02:00
const char *base, *ext;
if (!(base = strrchr(f, SLASH_CHAR)))
2010-09-25 17:46:12 +02:00
base = f;
else
base += 1;
ext = strrchr(f, '.');
2010-09-25 17:46:12 +02:00
if (!ext)
snprintf(filename, PATH_MAX, "%s", base);
2010-09-25 17:46:12 +02:00
else
{
int len = ext - base;
strncpy(filename, base, len);
2010-09-25 17:46:12 +02:00
filename[len] = '\0';
}
return filename;
}
static int file_exists(const char *name)
2010-09-25 17:46:12 +02:00
{
FILE *f = NULL;
f = fopen(name, "r");
2010-09-25 17:46:12 +02:00
if (!f)
return 0;
else
{
fclose(f);
2010-09-25 17:46:12 +02:00
return 1;
}
}
bool8 S9xOpenSnapshotFile(const char *fname, bool8 read_only, STREAM *file)
2010-09-25 17:46:12 +02:00
{
char filename[PATH_MAX + 1];
char drive[_MAX_DRIVE + 1];
char dir[_MAX_DIR + 1];
char ext[_MAX_EXT + 1];
2010-09-25 17:46:12 +02:00
_splitpath(fname, drive, dir, filename, ext);
2010-09-25 17:46:12 +02:00
if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/')))
{
snprintf(filename, PATH_MAX + 1, "%s", fname);
2010-09-25 17:46:12 +02:00
if (!file_exists(filename))
2010-09-25 17:46:12 +02:00
{
if (!*ext)
strcat(filename, ".s9x");
2010-09-25 17:46:12 +02:00
}
}
else
{
strcpy(filename, S9xGetDirectory(SNAPSHOT_DIR));
strcat(filename, SLASH_STR);
strcat(filename, fname);
2010-09-25 17:46:12 +02:00
if (!file_exists(filename))
2010-09-25 17:46:12 +02:00
{
if (!*ext)
strcat(filename, ".s9x");
2010-09-25 17:46:12 +02:00
}
}
#ifdef ZLIB
if (read_only)
{
if ((*file = OPEN_STREAM(filename, "rb")))
return (true);
2010-09-26 11:19:15 +02:00
else
fprintf(stderr,
"Failed to open file stream for reading. (%s)\n",
zError(errno));
2010-09-25 17:46:12 +02:00
}
else
{
if ((*file = OPEN_STREAM(filename, "wb")))
2010-09-25 17:46:12 +02:00
{
return (true);
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
else
{
fprintf(stderr,
"Couldn't open stream with zlib. (%s)\n",
zError(errno));
2010-09-26 11:19:15 +02:00
}
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
fprintf(stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename);
2010-09-26 11:19:15 +02:00
2010-09-25 17:46:12 +02:00
#else
char command[PATH_MAX];
2010-09-25 17:46:12 +02:00
if (read_only)
{
sprintf(command, "gzip -d <\"%s\"", filename);
if (*file = popen(command, "r"))
return (true);
2010-09-25 17:46:12 +02:00
}
else
{
sprintf(command, "gzip --best >\"%s\"", filename);
if (*file = popen(command, "wb"))
return (true);
2010-09-25 17:46:12 +02:00
}
2010-09-26 11:19:15 +02:00
fprintf(stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename);
2010-09-26 11:19:15 +02:00
2010-09-25 17:46:12 +02:00
#endif
2010-09-26 11:19:15 +02:00
return (false);
2010-09-25 17:46:12 +02:00
}
void S9xCloseSnapshotFile(STREAM file)
2010-09-25 17:46:12 +02:00
{
#ifdef ZLIB
CLOSE_STREAM(file);
2010-09-25 17:46:12 +02:00
#else
pclose(file);
2010-09-25 17:46:12 +02:00
#endif
}
void S9xAutoSaveSRAM()
2010-09-25 17:46:12 +02:00
{
Memory.SaveSRAM(S9xGetFilename(".srm", SRAM_DIR));
S9xSaveCheatFile(S9xGetFilename(".cht", CHEAT_DIR));
2010-09-25 17:46:12 +02:00
}
void S9xLoadState(const char *filename)
2010-09-25 17:46:12 +02:00
{
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
2010-09-25 17:46:12 +02:00
if (S9xUnfreezeGame(filename))
2010-09-26 11:19:15 +02:00
{
sprintf(buf, "%s loaded", filename);
S9xSetInfoString(buf);
2010-09-26 11:19:15 +02:00
}
else
{
fprintf(stderr, "Failed to load state file: %s\n", filename);
2010-09-26 11:19:15 +02:00
}
2010-09-25 17:46:12 +02:00
}
void S9xSaveState(const char *filename)
2010-09-25 17:46:12 +02:00
{
if (S9xFreezeGame(filename))
2010-09-25 17:46:12 +02:00
{
sprintf(buf, "%s saved", filename);
S9xSetInfoString(buf);
2010-09-25 17:46:12 +02:00
}
else
{
fprintf(stderr, "Couldn't save state file: %s\n", filename);
2010-09-25 17:46:12 +02:00
}
}
/* QuickSave/Load from S9x base controls.cpp */
void S9xQuickSaveSlot(int slot)
2010-09-25 17:46:12 +02:00
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
2018-11-06 23:30:50 +01:00
if (!gui_config->rom_loaded)
return;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
2010-09-25 17:46:12 +02:00
snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
2010-09-25 17:46:12 +02:00
slot);
if (S9xFreezeGame(filename))
2010-09-26 11:19:15 +02:00
{
snprintf(buf, PATH_MAX, "%s.%03d saved", def, slot);
2010-09-25 17:46:12 +02:00
S9xSetInfoString(buf);
2010-09-26 11:19:15 +02:00
}
2010-09-25 17:46:12 +02:00
}
void S9xQuickLoadSlot(int slot)
2010-09-25 17:46:12 +02:00
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
2018-11-06 23:30:50 +01:00
if (!gui_config->rom_loaded)
return;
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
2010-09-25 17:46:12 +02:00
snprintf(filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR, def,
2010-09-25 17:46:12 +02:00
slot);
if (file_exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame(filename))
2010-09-25 17:46:12 +02:00
{
snprintf(buf, PATH_MAX, "%s.%03d loaded", def, slot);
S9xSetInfoString(buf);
2018-06-09 17:23:26 +02:00
return;
2010-09-25 17:46:12 +02:00
}
2018-06-09 17:23:26 +02:00
static const char *digits = "t123456789";
2010-09-25 17:46:12 +02:00
_splitpath(Memory.ROMFilename, drive, dir, def, ext);
2010-09-25 17:46:12 +02:00
snprintf(filename, PATH_MAX, "%s%s%s.zs%c",
S9xGetDirectory(SNAPSHOT_DIR), SLASH_STR,
def, digits[slot]);
2018-06-09 17:23:26 +02:00
if (file_exists(filename))
S9xFreezeGame(S9xGetFilename(".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame(filename))
2018-06-09 17:23:26 +02:00
{
snprintf(buf, PATH_MAX,
"Loaded ZSNES freeze file %s.zs%c",
def, digits[slot]);
S9xSetInfoString(buf);
2018-06-09 17:23:26 +02:00
return;
2010-09-25 17:46:12 +02:00
}
S9xMessage(S9X_ERROR,
S9X_FREEZE_FILE_NOT_FOUND,
"Freeze file not found");
2010-09-25 17:46:12 +02:00
}