diff --git a/file_io.cpp b/file_io.cpp index b6fa522..5e68049 100644 --- a/file_io.cpp +++ b/file_io.cpp @@ -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); diff --git a/file_io.h b/file_io.h index 6e8982c..b03fb21 100644 --- a/file_io.h +++ b/file_io.h @@ -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); diff --git a/menu.cpp b/menu.cpp index 91dd97b..33e5c3b 100644 --- a/menu.cpp +++ b/menu.cpp @@ -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; } } } diff --git a/user_io.cpp b/user_io.cpp index bfe41ab..fdceab9 100644 --- a/user_io.cpp +++ b/user_io.cpp @@ -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) diff --git a/user_io.h b/user_io.h index a91a743..728d799 100644 --- a/user_io.h +++ b/user_io.h @@ -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())