Skip to content

Instantly share code, notes, and snippets.

@Langerz82
Last active March 27, 2021 06:35
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save Langerz82/7925a54e75685b1f4aad17782616f207 to your computer and use it in GitHub Desktop.
Save Langerz82/7925a54e75685b1f4aad17782616f207 to your computer and use it in GitHub Desktop.
Flycast - Zip Support for CDI/GDI files - Some initial changes (7-zip not yet implemented).
diff --git a/core/archive/7zArchive.cpp b/core/archive/7zArchive.cpp
index 8ae6bba3..28fd97a8 100644
--- a/core/archive/7zArchive.cpp
+++ b/core/archive/7zArchive.cpp
@@ -105,6 +105,14 @@ ArchiveFile* SzArchive::OpenFileByCrc(u32 crc)
return NULL;
}
+
+// TODO
+void SzArchive::Extract(const char *path, char* gamefile,
+ std::vector<string> &zipped_files)
+{
+ return;
+}
+
SzArchive::~SzArchive()
{
if (lookStream.buf != NULL)
diff --git a/core/archive/7zArchive.h b/core/archive/7zArchive.h
index 7cdf3515..97fcc160 100644
--- a/core/archive/7zArchive.h
+++ b/core/archive/7zArchive.h
@@ -38,6 +38,9 @@ public:
virtual ArchiveFile* OpenFile(const char* name) override;
virtual ArchiveFile *OpenFileByCrc(u32 crc) override;
+ virtual void Extract(const char *path, char* gamefile,
+ std::vector<string> &zipped_files) override;
+
private:
virtual bool Open(const char* path) override;
diff --git a/core/archive/ZipArchive.cpp b/core/archive/ZipArchive.cpp
index aca16614..2a728d2f 100644
--- a/core/archive/ZipArchive.cpp
+++ b/core/archive/ZipArchive.cpp
@@ -19,6 +19,7 @@
along with reicast. If not, see <https://www.gnu.org/licenses/>.
*/
#include "ZipArchive.h"
+#include "../log/LogManager.h"
ZipArchive::~ZipArchive()
{
@@ -78,3 +79,45 @@ u32 ZipArchiveFile::Read(void* buffer, u32 length)
{
return zip_fread(zip_file, buffer, length);
}
+
+void ZipArchive::Extract(const char *path, char* gamefile,
+ std::vector<string> &zipped_files)
+{
+ struct zip_stat sb;
+ struct zip_file *zf;
+ char buf[1024*8];
+ FILE* fd;
+ u32 sum, len;
+ int num = zip_get_num_files(zip);
+ INFO_LOG(COMMON, "num: %d", num);
+ for (u32 i = 0; i < num; i++) {
+ if (zip_stat_index(zip, i, 0, &sb) == 0) {
+ INFO_LOG(COMMON, "sb.name: %s", sb.name);
+ INFO_LOG(COMMON, "sb.size: %d", (int) sb.size);
+
+ zf = zip_fopen_index(zip, i, 0);
+ string z_file = (string) path + "/" + sb.name;
+ zipped_files.push_back(z_file);
+ fd = fopen(z_file.c_str(), "wb");
+ INFO_LOG(COMMON, "filename: %s", z_file.c_str());
+ sum = 0;
+ while (sum != sb.size) {
+ len = zip_fread(zf, buf, 1024*8);
+ if (len < 0) {
+ ERROR_LOG(COMMON, "zip_fread: %d ", len);
+ }
+ fwrite(buf, sizeof(char), len, fd);
+ sum += len;
+ }
+ char *ext = strrchr((char*)z_file.c_str(), '.');
+ if (!strcmp(".cdi", ext) || !strcmp(".CDI", ext) ||
+ !strcmp(".gdi", ext) || !strcmp(".GDI", ext))
+ {
+ strncpy(gamefile, z_file.c_str(), strlen(gamefile));
+ INFO_LOG(COMMON, "gamefile: %s", gamefile);
+ }
+ fclose(fd);
+ zip_fclose(zf);
+ }
+ }
+}
diff --git a/core/archive/ZipArchive.h b/core/archive/ZipArchive.h
index d63e5756..ab2eda2a 100644
--- a/core/archive/ZipArchive.h
+++ b/core/archive/ZipArchive.h
@@ -32,6 +32,8 @@ public:
virtual ArchiveFile* OpenFile(const char* name) override;
virtual ArchiveFile* OpenFileByCrc(u32 crc) override;
+ virtual void Extract(const char *path, char* gamefile,
+ std::vector<string> &zipped_files) override;
private:
virtual bool Open(const char* path) override;
diff --git a/core/archive/archive.h b/core/archive/archive.h
index 54b84c56..8d413355 100644
--- a/core/archive/archive.h
+++ b/core/archive/archive.h
@@ -39,6 +39,8 @@ public:
virtual ArchiveFile *OpenFileByCrc(u32 crc) = 0;
friend Archive *OpenArchive(const char *path);
+ virtual void Extract(const char *path, char* gamefile,
+ std::vector<string> &zipped_files) = 0;
private:
virtual bool Open(const char *name) = 0;
diff --git a/core/hw/naomi/naomi_cart.cpp b/core/hw/naomi/naomi_cart.cpp
index 3eea93ce..56cf7524 100644
--- a/core/hw/naomi/naomi_cart.cpp
+++ b/core/hw/naomi/naomi_cart.cpp
@@ -386,6 +386,26 @@ error:
return false;
}
+bool naomi_is_cart(const char* file)
+{
+ const char *ext = path_get_extension(file);
+
+ char game_name[128];
+ strncpy(game_name, path_basename(file), sizeof(game_name) - 1);
+ game_name[sizeof(game_name) - 1] = '\0';
+ path_remove_extension(game_name);
+
+ int gameid = 0;
+ for (; Games[gameid].name != NULL; gameid++)
+ if (!stricmp(Games[gameid].name, game_name))
+ break;
+ if (Games[gameid].name == NULL)
+ // Not found. Will fail later
+ return false;
+
+ return true;
+}
+
int naomi_cart_GetSystemType(const char* file)
{
const char *ext = path_get_extension(file);
diff --git a/core/hw/naomi/naomi_cart.h b/core/hw/naomi/naomi_cart.h
index 8309c45c..0801061a 100644
--- a/core/hw/naomi/naomi_cart.h
+++ b/core/hw/naomi/naomi_cart.h
@@ -86,6 +86,7 @@ private:
};
bool naomi_cart_SelectFile();
+bool naomi_is_cart(const char* file);
int naomi_cart_GetSystemType(const char* file);
int naomi_cart_GetRotation();
void naomi_cart_Close();
diff --git a/core/libretro-common/include/libretro.h b/core/libretro-common/include/libretro.h
index 4ddb6e89..67876f7b 100644
--- a/core/libretro-common/include/libretro.h
+++ b/core/libretro-common/include/libretro.h
@@ -2681,7 +2681,7 @@ struct retro_core_options_intl
struct retro_game_info
{
- const char *path; /* Path to game, UTF-8 encoded.
+ char *path; /* Path to game, UTF-8 encoded.
* Sometimes used as a reference for building other paths.
* May be NULL if game was loaded from stdin or similar,
* but in this case some cores will be unable to load `data`.
@@ -2854,7 +2854,7 @@ RETRO_API void retro_cheat_set(unsigned index, bool enabled, const char *code);
/* Loads a game.
* Return true to indicate successful loading and false to indicate load failure.
*/
-RETRO_API bool retro_load_game(const struct retro_game_info *game);
+RETRO_API bool retro_load_game(struct retro_game_info *game);
/* Loads a "special" kind of game. Should not be used,
* except in extreme cases. */
diff --git a/core/libretro/libretro.cpp b/core/libretro/libretro.cpp
index f5f41ac3..1828ec45 100644
--- a/core/libretro/libretro.cpp
+++ b/core/libretro/libretro.cpp
@@ -53,6 +53,7 @@ char* strdup(const char *str)
#include "log/LogManager.h"
#include "cheats.h"
#include "rend/CustomTexture.h"
+#include "../archive/archive.h"
#if defined(_XBOX) || defined(_WIN32)
char slash = '\\';
@@ -184,6 +185,9 @@ static void init_disk_control_interface(void);
static bool read_m3u(const char *file);
char *game_data;
+
+std::vector<string> zipped_files;
+
char g_base_name[128];
char game_dir[1024];
char game_dir_no_slash[1024];
@@ -1826,8 +1830,22 @@ static bool set_opengl_hw_render(u32 preferred)
#endif
}
+
+static void LoadZipFile(char* filename)
+{
+ Archive *archive = OpenArchive(filename);
+ if (archive != NULL)
+ INFO_LOG(COMMON, "Opened Archive %s", filename);
+
+ archive->Extract(game_dir, filename, zipped_files);
+
+ if (archive != NULL)
+ delete archive;
+
+}
+
// Loading/unloading games
-bool retro_load_game(const struct retro_game_info *game)
+bool retro_load_game(struct retro_game_info *game)
{
const char *dir = NULL;
const char *vmu_dir = NULL;
@@ -1840,6 +1858,15 @@ bool retro_load_game(const struct retro_game_info *game)
extract_basename(g_base_name, game->path, sizeof(g_base_name));
extract_directory(game_dir, game->path, sizeof(game_dir));
+ char *ext = strrchr(g_base_name, '.');
+ if (!naomi_is_cart(game->path) &&
+ (!strcmp(".zip", ext) || !strcmp(".ZIP", ext) ||
+ !strcmp(".7z", ext) || !strcmp(".7Z", ext)))
+ {
+ LoadZipFile(game->path);
+ log_cb(RETRO_LOG_INFO, "LoadZipFile: %s\n", game->path);
+ }
+
// Storing rom dir for later use
snprintf(g_roms_dir, sizeof(g_roms_dir), "%s%c", game_dir, slash);
@@ -1869,19 +1896,19 @@ bool retro_load_game(const struct retro_game_info *game)
settings.dreamcast.cable = 3;
update_variables(true);
- char *ext = strrchr(g_base_name, '.');
-
+ settings.System = DC_PLATFORM_DREAMCAST;
{
/* Check for extension .lst, .bin, .dat or .zip. If found, we will set the system type
* automatically to Naomi or AtomisWave. */
if (ext)
{
log_cb(RETRO_LOG_INFO, "File extension is: %s\n", ext);
- if (!strcmp(".lst", ext)
+ if ((!strcmp(".lst", ext)
|| !strcmp(".bin", ext) || !strcmp(".BIN", ext)
|| !strcmp(".dat", ext) || !strcmp(".DAT", ext)
|| !strcmp(".zip", ext) || !strcmp(".ZIP", ext)
|| !strcmp(".7z", ext) || !strcmp(".7Z", ext))
+ && naomi_is_cart(game->path))
{
settings.System = naomi_cart_GetSystemType(game->path);
/* System may have changed - have to update
@@ -2048,6 +2075,14 @@ bool retro_load_game_special(unsigned game_type, const struct retro_game_info *i
void retro_unload_game(void)
{
+ INFO_LOG(COMMON, "Flycast deleting tmp rom");
+ for (std::vector<string>::iterator it = zipped_files.begin();
+ it != zipped_files.end(); ++it)
+ {
+ remove(it->c_str());
+ log_cb(RETRO_LOG_INFO, "removed: %s\n", it->c_str());
+ }
+
INFO_LOG(COMMON, "Flycast unloading game");
if (game_data)
free(game_data);
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment