snes9x/gtk/src/gtk_file.cpp
Brandon Wright 5c3fbf6740 Fix some warnings.
Removed sstrncpy function.
Changed bindings in GTK port to std::array and fixed packing nonsense.
2020-06-20 10:44:11 -05:00

559 lines
12 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 "gtk_2_3_compat.h"
#include "gtk_s9x.h"
static char buf[PATH_MAX];
const char *
S9xChooseMovieFilename (bool8 read_only)
{
static char path[PATH_MAX];
if (!gui_config->rom_loaded)
return "";
const char *str = top_level->open_movie_dialog (read_only);
strcpy (path, str);
return path;
}
const char *
S9xChooseFilename (bool8 read_only)
{
return "";
}
/* _splitpath/_makepath: Modified from unix.cpp. See file for credits. */
#ifndef SLASH_CHAR
#define SLASH_CHAR '/'
#endif
void
_splitpath (const char *path, char *drive, char *dir, char *fname, char *ext)
{
char *slash = strrchr ((char *) path, SLASH_CHAR);
char *dot = strrchr ((char *) path, '.');
*drive = '\0';
if (dot && slash && dot < slash)
{
dot = 0;
}
if (!slash)
{
*dir = '\0';
strcpy (fname, path);
if (dot)
{
fname[dot - path] = '\0';
strcpy (ext, dot + 1);
}
else
{
*ext = '\0';
}
}
else
{
strcpy (dir, path);
dir[slash - path] = '\0';
strcpy (fname, slash + 1);
if (dot)
{
fname[(dot - slash) - 1] = '\0';
strcpy (ext, dot + 1);
}
else
{
*ext = '\0';
}
}
}
void
_makepath (char *path,
const char *drive,
const char *dir,
const char *fname,
const char *ext)
{
if (dir && *dir)
{
strcpy (path, dir);
strcat (path, "/");
}
else
*path = '\0';
strcat (path, fname);
if (ext && *ext)
{
strcat (path, ".");
strcat (path, ext);
}
}
const char *
S9xGetFilenameInc (const char *e, enum s9x_getdirtype dirtype)
{
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];
unsigned int i = 0;
struct stat buf;
const char *d;
_splitpath (Memory.ROMFilename, drive, dir, fname, ext);
d = S9xGetDirectory (dirtype);
do
{
snprintf (filename, PATH_MAX, "%s" SLASH_STR "%s%03d%s", d, fname, i, e);
i++;
}
while (stat (filename, &buf) == 0 && i != 0); /* Overflow? ...riiight :-) */
return (filename);
}
const char *
S9xGetDirectory (enum s9x_getdirtype dirtype)
{
static char path[PATH_MAX + 1];
switch (dirtype)
{
case HOME_DIR:
snprintf(path, PATH_MAX + 1, get_config_dir().c_str());
break;
case SNAPSHOT_DIR:
snprintf(path, PATH_MAX + 1, gui_config->savestate_directory.c_str());
break;
case PATCH_DIR:
snprintf(path, PATH_MAX + 1, gui_config->patch_directory.c_str());
break;
case CHEAT_DIR:
snprintf(path, PATH_MAX + 1, gui_config->cheat_directory.c_str());
break;
case SRAM_DIR:
snprintf(path, PATH_MAX + 1, gui_config->sram_directory.c_str());
break;
case SCREENSHOT_DIR:
case SPC_DIR:
snprintf(path, PATH_MAX + 1, gui_config->export_directory.c_str());
break;
default:
path[0] = '\0';
}
/* Check if directory exists, make it and/or set correct permissions */
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);
}
/* Anything else, use ROM filename path */
if (path[0] == '\0')
{
char *loc;
strcpy (path, Memory.ROMFilename);
loc = strrchr (path, SLASH_CHAR);
if (loc == NULL)
{
if (getcwd (path, PATH_MAX + 1) == NULL)
{
strcpy (path, getenv ("HOME"));
}
}
else
{
path[loc - path] = '\0';
}
}
return path;
}
const char *
S9xGetFilename (const char *ex, enum s9x_getdirtype dirtype)
{
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];
_splitpath (Memory.ROMFilename, drive, dir, fname, ext);
snprintf (filename, sizeof (filename), "%s" SLASH_STR "%s%s",
S9xGetDirectory (dirtype), fname, ex);
return (filename);
}
const char *
S9xBasename (const char *f)
{
const char *p;
if ((p = strrchr (f, '/')) != NULL || (p = strrchr (f, '\\')) != NULL)
return (p + 1);
return f;
}
const char *
S9xBasenameNoExt (const char *f)
{
static char filename[PATH_MAX];
const char *base, *ext;
if (!(base = strrchr (f, SLASH_CHAR)))
base = f;
else
base += 1;
ext = strrchr (f, '.');
if (!ext)
snprintf (filename, PATH_MAX, base);
else
{
int len = ext - base;
strncpy (filename, base, len);
filename[len] = '\0';
}
return filename;
}
static int
file_exists (const char *name)
{
FILE *f = NULL;
f = fopen (name, "r");
if (!f)
return 0;
else
{
fclose (f);
return 1;
}
}
bool8
S9xOpenSnapshotFile (const char *fname, bool8 read_only, STREAM *file)
{
char filename [PATH_MAX + 1];
char drive [_MAX_DRIVE + 1];
char dir [_MAX_DIR + 1];
char ext [_MAX_EXT + 1];
_splitpath (fname, drive, dir, filename, ext);
if (*drive || *dir == '/' || (*dir == '.' && (*(dir + 1) == '/')))
{
snprintf (filename, PATH_MAX + 1, fname);
if (!file_exists (filename))
{
if (!*ext)
strcat (filename, ".s9x");
}
}
else
{
strcpy (filename, S9xGetDirectory (SNAPSHOT_DIR));
strcat (filename, SLASH_STR);
strcat (filename, fname);
if (!file_exists (filename))
{
if (!*ext)
strcat (filename, ".s9x");
}
}
#ifdef ZLIB
if (read_only)
{
if ((*file = OPEN_STREAM (filename, "rb")))
return (true);
else
fprintf (stderr,
"Failed to open file stream for reading. (%s)\n",
zError (errno));
}
else
{
if ((*file = OPEN_STREAM (filename, "wb")))
{
return (true);
}
else
{
fprintf (stderr,
"Couldn't open stream with zlib. (%s)\n",
zError (errno));
}
}
fprintf (stderr, "zlib: Couldn't open snapshot file:\n%s\n", filename);
#else
char command [PATH_MAX];
if (read_only)
{
sprintf (command, "gzip -d <\"%s\"", filename);
if (*file = popen (command, "r"))
return (true);
}
else
{
sprintf (command, "gzip --best >\"%s\"", filename);
if (*file = popen (command, "wb"))
return (true);
}
fprintf (stderr, "gzip: Couldn't open snapshot file:\n%s\n", filename);
#endif
return (false);
}
void S9xCloseSnapshotFile (STREAM file)
{
#ifdef ZLIB
CLOSE_STREAM (file);
#else
pclose (file);
#endif
}
void
S9xAutoSaveSRAM ()
{
Memory.SaveSRAM (S9xGetFilename (".srm", SRAM_DIR));
S9xSaveCheatFile (S9xGetFilename (".cht", CHEAT_DIR));
}
void
S9xLoadState (const char *filename)
{
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename))
{
sprintf (buf, "%s loaded", filename);
S9xSetInfoString (buf);
}
else
{
fprintf (stderr, "Failed to load state file: %s\n", filename);
}
}
void
S9xSaveState (const char *filename)
{
if (S9xFreezeGame (filename))
{
sprintf (buf, "%s saved", filename);
S9xSetInfoString (buf);
}
else
{
fprintf (stderr, "Couldn't save state file: %s\n", filename);
}
}
char *
S9xOpenROMDialog ()
{
GtkWidget *dialog;
GtkFileFilter *filter;
char *filename = NULL;
gint result;
const char *extensions[] =
{
"*.smc", "*.SMC", "*.fig", "*.FIG", "*.sfc", "*.SFC",
"*.jma", "*.JMA", "*.zip", "*.ZIP", "*.gd3", "*.GD3",
"*.swc", "*.SWC", "*.gz" , "*.GZ", "*.bs", "*.BS",
NULL
};
top_level->pause_from_focus_change ();
dialog = gtk_file_chooser_dialog_new (_("Open SNES ROM Image"),
top_level->get_window (),
GTK_FILE_CHOOSER_ACTION_OPEN,
"gtk-cancel", GTK_RESPONSE_CANCEL,
"gtk-open", GTK_RESPONSE_ACCEPT,
NULL);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("SNES ROM Images"));
for (int i = 0; extensions[i]; i++)
{
gtk_file_filter_add_pattern (filter, extensions[i]);
}
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
filter = gtk_file_filter_new ();
gtk_file_filter_set_name (filter, _("All Files"));
gtk_file_filter_add_pattern (filter, "*.*");
gtk_file_filter_add_pattern (filter, "*");
gtk_file_chooser_add_filter (GTK_FILE_CHOOSER (dialog), filter);
if (!gui_config->last_directory.empty ())
{
gtk_file_chooser_set_current_folder (GTK_FILE_CHOOSER (dialog),
gui_config->last_directory.c_str ());
}
result = gtk_dialog_run (GTK_DIALOG (dialog));
gtk_widget_hide (dialog);
if (result == GTK_RESPONSE_ACCEPT)
{
char *directory;
filename = gtk_file_chooser_get_filename (GTK_FILE_CHOOSER (dialog));
directory =
gtk_file_chooser_get_current_folder (GTK_FILE_CHOOSER (dialog));
if (directory)
{
gui_config->last_directory = directory;
g_free (directory);
}
}
else
{
filename = NULL;
}
gtk_widget_destroy (dialog);
top_level->unpause_from_focus_change ();
return filename;
}
/* QuickSave/Load from S9x base controls.cpp */
void
S9xQuickSaveSlot (int slot)
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
if (!gui_config->rom_loaded)
return;
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def,
slot);
if (S9xFreezeGame (filename))
{
snprintf (buf, PATH_MAX, "%s.%03d saved", def, slot);
S9xSetInfoString (buf);
}
}
void S9xQuickLoadSlot (int slot)
{
char def[PATH_MAX];
char filename[PATH_MAX];
char drive[_MAX_DRIVE];
char dir[_MAX_DIR];
char ext[_MAX_EXT];
if (!gui_config->rom_loaded)
return;
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.%03d",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR, def,
slot);
if (file_exists (filename))
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename))
{
snprintf (buf, PATH_MAX, "%s.%03d loaded", def, slot);
S9xSetInfoString (buf);
return;
}
static const char *digits = "t123456789";
_splitpath (Memory.ROMFilename, drive, dir, def, ext);
snprintf (filename, PATH_MAX, "%s%s%s.zs%c",
S9xGetDirectory (SNAPSHOT_DIR), SLASH_STR,
def, digits[slot]);
if (file_exists (filename))
S9xFreezeGame (S9xGetFilename (".undo", SNAPSHOT_DIR));
if (S9xUnfreezeGame (filename))
{
snprintf (buf, PATH_MAX,
"Loaded ZSNES freeze file %s.zs%c",
def, digits [slot]);
S9xSetInfoString (buf);
return;
}
S9xMessage (S9X_ERROR,
S9X_FREEZE_FILE_NOT_FOUND,
"Freeze file not found");
}