Support for savestate.

This commit is contained in:
sorgelig
2020-01-01 10:39:52 +08:00
parent 75a3621d8e
commit 1cb1e5b899
5 changed files with 200 additions and 18 deletions

View File

@@ -695,6 +695,36 @@ void FileGenerateSavePath(const char *name, char* out_name)
printf("SavePath=%s\n", out_name);
}
void FileGenerateSavestatePath(const char *name, char* out_name)
{
create_path(SAVESTATE_DIR, CoreName);
sprintf(out_name, "%s/%s/", SAVESTATE_DIR, CoreName);
char *fname = out_name + strlen(out_name);
const char *p = strrchr(name, '/');
if (p)
{
strcat(fname, p + 1);
}
else
{
strcat(fname, name);
}
char *e = strrchr(fname, '.');
if (e)
{
strcpy(e, ".ss");
}
else
{
strcat(fname, ".ss");
}
printf("SavestatePath=%s\n", out_name);
}
uint32_t getFileType(const char *name)
{
sprintf(full_path, "%s/%s", getRootDir(), name);

View File

@@ -81,6 +81,9 @@ int PathIsDir(const char *name);
#define SAVE_DIR "saves"
void FileGenerateSavePath(const char *name, char* out_name);
#define SAVESTATE_DIR "savestates"
void FileGenerateSavestatePath(const char *name, char* out_name);
#define SCREENSHOT_DIR "screenshots"
#define SCREENSHOT_DEFAULT "screen"
void FileGenerateScreenshotName(const char *name, char *out_name, int buflen);

View File

@@ -1550,7 +1550,7 @@ void HandleUI(void)
if (p[idx] >= '0' && p[idx] <= '9') ioctl_index = p[idx] - '0';
substrcpy(ext, p, 1);
if (!strcasecmp(user_io_get_core_name(), "GBA") && FileExists(user_io_make_filepath(HomeDir, "goomba.rom"))) strcat(ext, "GB GBC");
if (is_gba_core() && FileExists(user_io_make_filepath(HomeDir, "goomba.rom"))) strcat(ext, "GB GBC");
while (strlen(ext) % 3) strcat(ext, " ");
fs_Options = SCANO_DIR | (is_neogeo_core() ? SCANO_NEOGEO | SCANO_NOENTER : 0);
@@ -1636,7 +1636,7 @@ void HandleUI(void)
user_io_8bit_set_status(status ^ mask, mask, ex);
user_io_8bit_set_status(status, mask, ex);
menustate = MENU_8BIT_MAIN1;
if (p[0] == 'R') menustate = MENU_NONE1;
if (p[0] == 'R' || p[0] == 'r') menustate = MENU_NONE1;
}
}
}

View File

@@ -306,6 +306,13 @@ char is_archie_core()
return (is_archie_type == 1);
}
static int is_gba_type = 0;
char is_gba_core()
{
if (!is_gba_type) is_gba_type = strcasecmp(core_name, "GBA") ? 2 : 1;
return (is_gba_type == 1);
}
static int is_no_type = 0;
static int disable_osd = 0;
char has_menu()
@@ -326,6 +333,9 @@ static void user_io_read_core_name()
is_zx81_type = 0;
is_neogeo_type = 0;
is_minimig_type = 0;
is_megacd_type = 0;
is_archie_type = 0;
is_gba_type = 0;
core_name[0] = 0;
// get core name
@@ -1631,6 +1641,136 @@ void user_io_file_tx_write(const uint8_t *addr, uint16_t len)
DisableFpga();
}
static int process_ss(const char *rom_name)
{
static char ss_name[1024] = {};
static uint32_t ss_cnt = 0;
static int memfd = -1;
uint32_t map_addr = 0x3E000000;
if (rom_name)
{
FileGenerateSavestatePath(rom_name, ss_name);
if (memfd < 0)
{
memfd = open("/dev/mem", O_RDWR | O_SYNC);
if (memfd == -1)
{
printf("Unable to open /dev/mem!\n");
return 0;
}
}
ss_cnt = 0;
uint32_t len = 1024 * 1024;
uint32_t clr_addr = map_addr;
for (int i = 0; i < 16; i++)
{
void *base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, clr_addr);
if (base == (void *)-1)
{
printf("Unable to mmap (0x%X, %d)!\n", clr_addr, len);
close(memfd);
memfd = -1;
return 0;
}
memset(base, 0, len);
munmap(base, len);
clr_addr += len;
}
if (ss_name[0] && FileExists(ss_name))
{
void *base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, map_addr);
if (base == (void *)-1)
{
printf("Unable to mmap (0x%X, %d)!\n", map_addr, len);
return 0;
}
fileTYPE f = {};
if (!FileOpen(&f, ss_name))
{
printf("Unable to open file: %s\n", ss_name);
munmap(base, len);
}
else
{
int ret = FileReadAdv(&f, base, len);
FileClose(&f);
*(uint32_t*)base = 1;
ss_cnt = 1;
munmap(base, len);
printf("process_ss: read %d bytes from file: %s\n", ret, ss_name);
return 1;
}
}
return 1;
}
if (!ss_name[0]) return 0;
static unsigned long ss_timer = 0;
if (ss_timer && !CheckTimer(ss_timer)) return 0;
ss_timer = GetTimer(1000);
if (memfd >= 0)
{
uint32_t len = 4 * 1024;
void *base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, map_addr);
if (base == (void *)-1)
{
printf("Unable to mmap (0x%X, %d)!\n", map_addr, len);
return 0;
}
uint32_t curcnt = ((uint32_t*)base)[0];
uint32_t size = ((uint32_t*)base)[1];
munmap(base, len);
if (curcnt > ss_cnt)
{
ss_cnt = curcnt;
len = 512 * 1024;
if (size) size = (size + 2) * 4;
if (size > 0 && size <= len)
{
OsdDisable();
Info("Saving the state", 500);
void *base = mmap(0, len, PROT_READ | PROT_WRITE, MAP_SHARED, memfd, map_addr);
if (base == (void *)-1)
{
printf("Unable to mmap (0x%X, %d)!\n", map_addr, len);
return 0;
}
fileTYPE f = {};
if (!FileOpenEx(&f, ss_name, O_CREAT | O_TRUNC | O_RDWR | O_SYNC))
{
printf("Unable to create file: %s\n", ss_name);
munmap(base, len);
return 0;
}
int ret = FileWriteAdv(&f, base, size);
FileClose(&f);
munmap(base, len);
printf("Wrote %d bytes to file: %s\n", ret, ss_name);
}
}
}
return 1;
}
int user_io_file_tx(const char* name, unsigned char index, char opensave, char mute, char composite)
{
fileTYPE f = {};
@@ -1692,26 +1832,31 @@ int user_io_file_tx(const char* name, unsigned char index, char opensave, char m
if (use_progress) MenuHide();
int dosend = 1;
if (!strcasecmp(core_name, "GBA") && ((index >> 6) == 1 || (index >> 6) == 2))
if (is_gba_core())
{
fileTYPE fg = {};
if (!FileOpen(&fg, user_io_make_filepath(HomeDir, "goomba.rom")))
process_ss(name);
if ((index >> 6) == 1 || (index >> 6) == 2)
{
dosend = 0;
Info("Cannot open goomba.rom!");
sleep(1);
}
else
{
uint32_t sz = fg.size;
while (sz)
fileTYPE fg = {};
if (!FileOpen(&fg, user_io_make_filepath(HomeDir, "goomba.rom")))
{
uint16_t chunk = (sz > sizeof(buf)) ? sizeof(buf) : sz;
FileReadAdv(&fg, buf, chunk);
user_io_file_tx_write(buf, chunk);
sz -= chunk;
dosend = 0;
Info("Cannot open goomba.rom!");
sleep(1);
}
else
{
uint32_t sz = fg.size;
while (sz)
{
uint16_t chunk = (sz > sizeof(buf)) ? sizeof(buf) : sz;
FileReadAdv(&fg, buf, chunk);
user_io_file_tx_write(buf, chunk);
sz -= chunk;
}
FileClose(&fg);
}
FileClose(&fg);
}
}
@@ -2859,6 +3004,8 @@ void user_io_poll()
set_kbdled(HID_LED_SCROLL_LOCK, (leds & KBD_LED_SCRL_CONTROL) ? leds & KBD_LED_SCRL_STATUS : scrl_status);
keyboard_leds = leds;
}
if (!res_timer)
@@ -2936,6 +3083,7 @@ void user_io_poll()
}
if (is_megacd_core()) mcd_poll();
process_ss(0);
}
static void send_keycode(unsigned short key, int press)

View File

@@ -286,6 +286,7 @@ char is_snes_core();
char is_neogeo_core();
char is_megacd_core();
char is_archie_core();
char is_gba_core();
#define HomeDir (is_menu_core() ? "Scripts" : user_io_get_core_path())
#define CoreName (is_menu_core() ? "Scripts" : user_io_get_core_name())