diff --git a/components/retro-go/rg_storage.c b/components/retro-go/rg_storage.c index 4d48722fa..1f669f4a2 100644 --- a/components/retro-go/rg_storage.c +++ b/components/retro-go/rg_storage.c @@ -413,6 +413,49 @@ bool rg_storage_scandir(const char *path, rg_scandir_cb_t *callback, void *arg, return true; } +bool rg_storage_read_file(const char *path, void **data_out, size_t *data_len) +{ + RG_ASSERT(data_out && data_len, "Bad param"); + CHECK_PATH(path); + + FILE *fp = fopen(path, "rb"); + if (!fp) + { + RG_LOGE("Fopen failed"); + return false; + } + + size_t data_align = 0x4000; + size_t file_size; + void *file_data; + + fseek(fp, 0, SEEK_END); + file_size = ftell(fp); + fseek(fp, 0, SEEK_SET); + + file_data = malloc(((file_size & ~data_align) + data_align)); + if (!file_data) + { + RG_LOGE("Memory allocation failed"); + fclose(fp); + return false; + } + + if (!fread(file_data, file_size, 1, fp)) + { + RG_LOGE("File read failed"); + free(file_data); + fclose(fp); + return false; + } + + fclose(fp); + + *data_out = file_data; + *data_len = file_size; + return true; +} + #if RG_HAVE_MINIZ /** * This is a minimal UNZIP implementation that utilizes only the miniz primitives found in ESP32's ROM. @@ -443,10 +486,6 @@ bool rg_storage_unzip_file(const char *zip_path, const char *filter, void **data RG_ASSERT(data_out && data_len, "Bad param"); CHECK_PATH(zip_path); - zip_header_t header = {0}; - size_t data_align = 0x2000; - int header_pos = 0; - FILE *fp = fopen(zip_path, "rb"); if (!fp) { @@ -454,6 +493,10 @@ bool rg_storage_unzip_file(const char *zip_path, const char *filter, void **data return false; } + zip_header_t header = {0}; + size_t data_align = 0x4000; + int header_pos = 0; + // Very inefficient, we should read a block at a time and search it for a header. But I'm lazy. // Thankfully the header is usually found on the very first read :) for (header_pos = 0; !feof(fp); ++header_pos) diff --git a/gwenesis/main/main.c b/gwenesis/main/main.c index cbf9db3f3..74d241fa2 100644 --- a/gwenesis/main/main.c +++ b/gwenesis/main/main.c @@ -233,15 +233,19 @@ void app_main(void) RG_LOGI("Genesis start\n"); - FILE *fp = fopen(app->romPath, "rb"); - if (!fp) - RG_PANIC("Rom load failed"); - fseek(fp, 0, SEEK_END); - size_t rom_size = ftell(fp); - void *rom_data = malloc((rom_size & ~0xFFFF) + 0x10000); - fseek(fp, 0, SEEK_SET); - fread(rom_data, 1, rom_size, fp); - fclose(fp); + size_t rom_size; + void *rom_data; + + if (rg_extension_match(app->romPath, "zip")) + { + if (!rg_storage_unzip_file(app->romPath, NULL, &rom_data, &rom_size)) + RG_PANIC("ROM file unzipping failed!"); + } + else + { + if (!rg_storage_read_file(app->romPath, &rom_data, &rom_size)) + RG_PANIC("ROM load failed!"); + } RG_LOGI("load_cartridge(%p, %d)\n", rom_data, rom_size); load_cartridge(rom_data, rom_size); diff --git a/launcher/main/applications.c b/launcher/main/applications.c index 5f8ed97da..01a4f5915 100644 --- a/launcher/main/applications.c +++ b/launcher/main/applications.c @@ -673,18 +673,18 @@ static void application(const char *desc, const char *name, const char *exts, co void applications_init(void) { - application("Nintendo Entertainment System", "nes", "nes fc fds nsf", "retro-core", 16); - application("Super Nintendo", "snes", "smc sfc", "retro-core", 0); - application("Nintendo Gameboy", "gb", "gb gbc", "retro-core", 0); - application("Nintendo Gameboy Color", "gbc", "gbc gb", "retro-core", 0); + application("Nintendo Entertainment System", "nes", "nes fc fds nsf zip", "retro-core", 16); + application("Super Nintendo", "snes", "smc sfc zip", "retro-core", 0); + application("Nintendo Gameboy", "gb", "gb gbc zip", "retro-core", 0); + application("Nintendo Gameboy Color", "gbc", "gbc gb zip", "retro-core", 0); application("Nintendo Game & Watch", "gw", "gw", "retro-core", 0); // application("Sega SG-1000", "sg1", "sms sg sg1", "retro-core", 0); - application("Sega Master System", "sms", "sms sg", "retro-core", 0); - application("Sega Game Gear", "gg", "gg", "retro-core", 0); - application("Sega Mega Drive", "md", "md gen bin", "gwenesis", 0); - application("Coleco ColecoVision", "col", "col rom", "retro-core", 0); - application("NEC PC Engine", "pce", "pce", "retro-core", 0); - application("Atari Lynx", "lnx", "lnx", "retro-core", 64); + application("Sega Master System", "sms", "sms sg zip", "retro-core", 0); + application("Sega Game Gear", "gg", "gg zip", "retro-core", 0); + application("Sega Mega Drive", "md", "md gen bin zip", "gwenesis", 0); + application("Coleco ColecoVision", "col", "col rom zip", "retro-core", 0); + application("NEC PC Engine", "pce", "pce zip", "retro-core", 0); + application("Atari Lynx", "lnx", "lnx zip", "retro-core", 64); // application("Atari 2600", "a26", "a26", "stella-go", 0); // application("Neo Geo Pocket Color", "ngp", "ngp ngc", "ngpocket-go", 0); application("DOOM", "doom", "wad", "prboom-go", 0); diff --git a/retro-core/main/main_gbc.c b/retro-core/main/main_gbc.c index b46bb91b5..ff9203cc6 100644 --- a/retro-core/main/main_gbc.c +++ b/retro-core/main/main_gbc.c @@ -270,8 +270,19 @@ void gbc_main(void) gnuboy_set_soundbuffer((void *)audioBuffer, sizeof(audioBuffer) / 2); // Load ROM - if (gnuboy_load_rom_file(app->romPath) < 0) + if (rg_extension_match(app->romPath, "zip")) + { + void *data; + size_t size; + if (!rg_storage_unzip_file(app->romPath, NULL, &data, &size)) + RG_PANIC("ROM file unzipping failed!"); + if (gnuboy_load_rom(data, size) < 0) + RG_PANIC("ROM Loading failed!"); + } + else if (gnuboy_load_rom_file(app->romPath) < 0) + { RG_PANIC("ROM Loading failed!"); + } // Load BIOS if (loadBIOSFile) diff --git a/retro-core/main/main_lynx.cpp b/retro-core/main/main_lynx.cpp index 26c3fce9b..f8a0570a5 100644 --- a/retro-core/main/main_lynx.cpp +++ b/retro-core/main/main_lynx.cpp @@ -190,7 +190,18 @@ extern "C" void lynx_main(void) app->tickRate = 60; // Init emulator - lynx = new CSystem(app->romPath, MIKIE_PIXEL_FORMAT_16BPP_565_BE, app->sampleRate); + if (rg_extension_match(app->romPath, "zip")) + { + void *data; + size_t size; + if (!rg_storage_unzip_file(app->romPath, NULL, &data, &size)) + RG_PANIC("ROM file unzipping failed!"); + lynx = new CSystem((UBYTE*)data, size, MIKIE_PIXEL_FORMAT_16BPP_565_BE, app->sampleRate); + } + else + { + lynx = new CSystem(app->romPath, MIKIE_PIXEL_FORMAT_16BPP_565_BE, app->sampleRate); + } if (lynx->mFileType == HANDY_FILETYPE_ILLEGAL) { diff --git a/retro-core/main/main_nes.c b/retro-core/main/main_nes.c index a4b35e3a5..9002353ba 100644 --- a/retro-core/main/main_nes.c +++ b/retro-core/main/main_nes.c @@ -208,11 +208,23 @@ void nes_main(void) nes = nes_init(SYS_DETECT, app->sampleRate, true, RG_BASE_PATH_BIOS "/fds_bios.bin"); if (!nes) - { RG_PANIC("Init failed."); + + int ret = -1; + + if (rg_extension_match(app->romPath, "zip")) + { + void *data; + size_t size; + if (!rg_storage_unzip_file(app->romPath, NULL, &data, &size)) + RG_PANIC("ROM file unzipping failed!"); + ret = nes_insertcart(rom_loadmem(data, size)); + } + else + { + ret = nes_loadfile(app->romPath); } - int ret = nes_loadfile(app->romPath); if (ret == -1) RG_PANIC("ROM load failed."); else if (ret == -2) diff --git a/retro-core/main/main_pce.c b/retro-core/main/main_pce.c index 4dcebbdbf..7df6f6d82 100644 --- a/retro-core/main/main_pce.c +++ b/retro-core/main/main_pce.c @@ -219,7 +219,16 @@ void pce_main(void) InitPCE(app->sampleRate, true); - if (LoadFile(app->romPath) != 0) + if (rg_extension_match(app->romPath, "zip")) + { + void *data; + size_t size; + if (!rg_storage_unzip_file(app->romPath, NULL, &data, &size)) + RG_PANIC("ROM file unzipping failed!"); + if (LoadCard(data, size) != 0) + RG_PANIC("ROM loading failed"); + } + else if (LoadFile(app->romPath) != 0) { RG_PANIC("ROM loading failed"); } diff --git a/retro-core/main/main_sms.c b/retro-core/main/main_sms.c index f1e72bed0..80fcaa2a3 100644 --- a/retro-core/main/main_sms.c +++ b/retro-core/main/main_sms.c @@ -125,7 +125,16 @@ void sms_main(void) else option.console = 0; - if (!load_rom_file(app->romPath)) + if (rg_extension_match(app->romPath, "zip")) + { + void *data; + size_t size; + if (!rg_storage_unzip_file(app->romPath, NULL, &data, &size)) + RG_PANIC("ROM file unzipping failed!"); + if (!load_rom(data, RG_MAX(0x4000, size), size)) + RG_PANIC("ROM file loading failed!"); + } + else if (!load_rom_file(app->romPath)) RG_PANIC("ROM file loading failed!"); bitmap.width = SMS_WIDTH; diff --git a/retro-core/main/main_snes.c b/retro-core/main/main_snes.c index f136be95e..50ad0577c 100644 --- a/retro-core/main/main_snes.c +++ b/retro-core/main/main_snes.c @@ -289,7 +289,17 @@ void snes_main(void) if (!S9xInitGFX()) RG_PANIC("Graphics init failed!"); - if (!LoadROM(app->romPath)) + const char *filename = app->romPath; + + if (rg_extension_match(filename, "zip")) + { + free(Memory.ROM); // Would be nice to reuse it directly... + if (!rg_storage_unzip_file(filename, NULL, (void **)&Memory.ROM, &Memory.ROM_Size)) + RG_PANIC("ROM file unzipping failed!"); + filename = NULL; + } + + if (!LoadROM(filename)) RG_PANIC("ROM loading failed!"); #ifdef USE_BLARGG_APU