summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--blastem.c57
-rw-r--r--romdb.h1
-rw-r--r--util.c70
-rw-r--r--util.h6
4 files changed, 102 insertions, 32 deletions
diff --git a/blastem.c b/blastem.c
index 02dd3cb..7825b87 100644
--- a/blastem.c
+++ b/blastem.c
@@ -192,6 +192,7 @@ void adjust_int_cycle(m68k_context * context, vdp_context * v_context)
int break_on_sync = 0;
int save_state = 0;
+char *save_state_path;
//#define DO_DEBUG_PRINT
#ifdef DO_DEBUG_PRINT
@@ -309,8 +310,8 @@ m68k_context * sync_components(m68k_context * context, uint32_t address)
{
sync_z80(z_context, z_context->current_cycle + MCLKS_PER_Z80);
}
- save_gst(gen, "savestate.gst", address);
- puts("Saved state to savestate.gst");
+ save_gst(gen, save_state_path, address);
+ printf("Saved state to %s\n", save_state_path);
} else if(save_state) {
context->sync_cycle = context->current_cycle + 1;
}
@@ -974,6 +975,25 @@ void set_region(rom_info *info, uint8_t region)
}
}
+void setup_saves(char *fname, rom_info *info)
+{
+ char * barename = basename_no_extension(fname);
+ char const * parts[3] = {get_save_dir(), "/", barename};
+ char *save_dir = alloc_concat_m(3, parts);
+ if (!ensure_dir_exists(save_dir)) {
+ warning("Failed to create save directory %s\n", save_dir);
+ }
+ parts[0] = save_dir;
+ parts[2] = info->save_type == SAVE_I2C ? "save.eeprom" : "save.sram";
+ free(save_filename);
+ save_filename = alloc_concat_m(3, parts);
+ parts[2] = "quicksave.gst";
+ free(save_state_path);
+ save_state_path = alloc_concat_m(3, parts);
+ info->save_dir = save_dir;
+ free(barename);
+}
+
int main(int argc, char ** argv)
{
set_exe_str(argv[0]);
@@ -1150,21 +1170,7 @@ int main(int argc, char ** argv)
if (!headless) {
render_init(width, height, title, fps, fullscreen);
}
- int fname_size = strlen(romfname);
- char * ext = info.save_type == SAVE_I2C ? "eeprom" : "sram";
- save_filename = malloc(fname_size+strlen(ext) + 2);
- memcpy(save_filename, romfname, fname_size);
- int i;
- for (i = fname_size-1; fname_size >= 0; --i) {
- if (save_filename[i] == '.') {
- strcpy(save_filename + i + 1, ext);
- break;
- }
- }
- if (i < 0) {
- save_filename[fname_size] = '.';
- strcpy(save_filename + fname_size + 1, ext);
- }
+ setup_saves(romfname, &info);
genesis = alloc_init_genesis(&info, fps, (ym_log && !menu) ? YM_OPT_WAVE_LOG : 0);
if (menu) {
@@ -1189,7 +1195,7 @@ int main(int argc, char ** argv)
genesis = menu_context;
}
free(game_context->cart);
- free(save_filename);
+ free(info.save_dir);
base_map[0].buffer = ram = game_context->work_ram;
} else {
base_map[0].buffer = ram = malloc(RAM_WORDS * sizeof(uint16_t));
@@ -1202,20 +1208,7 @@ int main(int argc, char ** argv)
byteswap_rom(rom_size);
set_region(&info, force_version);
update_title(info.name);
- fname_size = strlen(menu_context->next_rom);
- ext = info.save_type == SAVE_I2C ? "eeprom" : "sram";
- save_filename = malloc(fname_size+strlen(ext) + 2);
- memcpy(save_filename, menu_context->next_rom, fname_size);
- for (i = fname_size-1; fname_size >= 0; --i) {
- if (save_filename[i] == '.') {
- strcpy(save_filename + i + 1, ext);
- break;
- }
- }
- if (i < 0) {
- save_filename[fname_size] = '.';
- strcpy(save_filename + fname_size + 1, ext);
- }
+ setup_saves(menu_context->next_rom, &info);
if (!game_context) {
//start a new arena and save old one in suspended genesis context
genesis->arena = start_new_arena();
diff --git a/romdb.h b/romdb.h
index 724335e..c7ef1a8 100644
--- a/romdb.h
+++ b/romdb.h
@@ -37,6 +37,7 @@ typedef struct {
typedef struct {
char *name;
+ char *save_dir;
memmap_chunk *map;
uint8_t *save_buffer;
eeprom_map *eeprom_map;
diff --git a/util.c b/util.c
index 57a59a2..9094223 100644
--- a/util.c
+++ b/util.c
@@ -8,6 +8,7 @@
#include <sys/types.h>
#include <sys/stat.h>
#include <unistd.h>
+#include <errno.h>
#ifdef __ANDROID__
#include <android/log.h>
@@ -93,6 +94,32 @@ char * split_keyval(char * text)
return text+1;
}
+char * basename_no_extension(char *path)
+{
+ char *lastdot = NULL;
+ char *lastslash = NULL;
+ char *cur;
+ for (cur = path; *cur; cur++)
+ {
+ if (*cur == '.') {
+ lastdot = cur;
+ } else if (*cur == '/') {
+ lastslash = cur + 1;
+ }
+ }
+ if (!lastdot) {
+ lastdot = cur;
+ }
+ if (!lastslash) {
+ lastslash = path;
+ }
+ char *barename = malloc(lastdot-lastslash+1);
+ memcpy(barename, lastslash, lastdot-lastslash);
+ barename[lastdot-lastslash] = 0;
+
+ return barename;
+}
+
uint32_t nearest_pow2(uint32_t val)
{
uint32_t ret = 1;
@@ -339,6 +366,32 @@ void free_dir_list(dir_entry *list, size_t numentries)
free(list);
}
+int ensure_dir_exists(char *path)
+{
+ struct stat st;
+ if (stat(path, &st)) {
+ if (errno == ENOENT) {
+ char *parent = strdup(path);
+ char *sep = strrchr(parent, '/');
+ if (sep && sep != parent) {
+ *sep = 0;
+ if (!ensure_dir_exists(parent)) {
+ free(parent);
+ return 0;
+ }
+ free(parent);
+ }
+ return mkdir(path, 0777) == 0;
+ } else {
+ char buf[80];
+ strerror_r(errno, buf, sizeof(buf));
+ warning("stat failed with error: %s", buf);
+ return 0;
+ }
+ }
+ return S_ISDIR(st.st_mode);
+}
+
#endif
#ifdef __ANDROID__
@@ -377,6 +430,11 @@ char const *get_config_dir()
return SDL_AndroidGetInternalStoragePath();
}
+char const *get_save_dir()
+{
+ return SDL_AndroidGetInternalStoragePath();
+}
+
#else
char *read_bundled_file(char *name, long *sizeret)
@@ -430,4 +488,16 @@ char const *get_config_dir()
return confdir;
}
+char const *get_save_dir()
+{
+ static char* savedir;
+ if (!savedir) {
+ char *homedir = get_home_dir();
+ if (homedir) {
+ savedir = alloc_concat(homedir, "/.local/share/blastem");
+ }
+ }
+ return savedir;
+}
+
#endif
diff --git a/util.h b/util.h
index c6eef76..b9d271e 100644
--- a/util.h
+++ b/util.h
@@ -20,6 +20,8 @@ long file_size(FILE * f);
char * strip_ws(char * text);
//Inserts a null after the first word, returns a pointer to the second word
char * split_keyval(char * text);
+//Returns the basename of a path with th extension (if any) stripped
+char * basename_no_extension(char *path);
//Gets the smallest power of two that is >= a certain value, won't work for values > 0x80000000
uint32_t nearest_pow2(uint32_t val);
//Should be called by main with the value of argv[0] for use by get_exe_dir
@@ -30,12 +32,16 @@ char * get_exe_dir();
char * get_home_dir();
//Returns an appropriate path for storing config files
char const *get_config_dir();
+//Returns an appropriate path for saving non-config data like savestates
+char const *get_save_dir();
//Reads a file bundled with the executable
char *read_bundled_file(char *name, long *sizeret);
//Retunrs an array of normal files and directories residing in a directory
dir_entry *get_dir_list(char *path, size_t *numret);
//Frees a dir list returned by get_dir_list
void free_dir_list(dir_entry *list, size_t numentries);
+//Recusrively creates a directory if it does not exist
+int ensure_dir_exists(char *path);
//Returns the contents of a symlink in a newly allocated string
char * readlink_alloc(char * path);
//Prints an error message to stderr and to a message box if not in headless mode and then exits