mirror of
https://github.com/libretro/RetroArch
synced 2025-02-07 03:40:24 +00:00
commit
a26c934572
@ -30,7 +30,10 @@
|
||||
#include "../deps/7zip/7zFile.h"
|
||||
#include "../deps/7zip/7zVersion.h"
|
||||
|
||||
|
||||
/* Undefined at the end of the file
|
||||
* Don't use outside of this file
|
||||
*/
|
||||
#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
|
||||
|
||||
static ISzAlloc g_Alloc = { SzAlloc, SzFree };
|
||||
|
||||
@ -164,9 +167,11 @@ static SRes ConvertUtf16toCharString(const UInt16 *s, char *outstring)
|
||||
}
|
||||
|
||||
/* Extract the relative path relative_path from a 7z archive
|
||||
* archive_path and allocate a buf for it to write it in. */
|
||||
* archive_path and allocate a buf for it to write it in.
|
||||
* If optional_outfile is set, extract to that instead and don't alloc buffer.
|
||||
*/
|
||||
int read_7zip_file(const char * archive_path,
|
||||
const char *relative_path, void **buf)
|
||||
const char *relative_path, void **buf, const char* optional_outfile)
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
@ -245,6 +250,9 @@ int read_7zip_file(const char * archive_path,
|
||||
|
||||
if (strcmp(infile,relative_path) == 0)
|
||||
{
|
||||
/* C LZMA SDK does not support chunked extraction - see here:
|
||||
* sourceforge.net/p/sevenzip/discussion/45798/thread/6fb59aaf/
|
||||
* */
|
||||
file_found = true;
|
||||
res = SzArEx_Extract(&db, &lookStream.s, i,&blockIndex,
|
||||
&outBuffer, &outBufferSize,&offset, &outSizeProcessed,
|
||||
@ -254,17 +262,33 @@ int read_7zip_file(const char * archive_path,
|
||||
break; /* This goes to the error section. */
|
||||
}
|
||||
outsize = outSizeProcessed;
|
||||
*buf = outBuffer+offset;
|
||||
|
||||
/*We could either use the 7Zip allocated buffer,
|
||||
* or create our own and use it.
|
||||
* We would however need to realloc anyways, because RetroArch
|
||||
* expects a \0 at the end, therefore we allocate new,
|
||||
* copy and free the old one. */
|
||||
*buf = malloc(outsize + 1);
|
||||
|
||||
((char*)(*buf))[outsize] = '\0';
|
||||
memcpy(*buf,outBuffer+offset,outsize);
|
||||
if (optional_outfile != NULL)
|
||||
{
|
||||
FILE* outsink = fopen(optional_outfile,"wb");
|
||||
if (outsink == NULL)
|
||||
{
|
||||
RARCH_ERR("Could not open outfilepath %s in 7zip_extract.\n",
|
||||
optional_outfile);
|
||||
IAlloc_Free(&allocImp, outBuffer);
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
SzFree(NULL, temp);
|
||||
File_Close(&archiveStream.file);
|
||||
return -1;
|
||||
}
|
||||
fwrite(outBuffer+offset,1,outsize,outsink);
|
||||
fclose(outsink);
|
||||
}
|
||||
else
|
||||
{
|
||||
/*We could either use the 7Zip allocated buffer,
|
||||
* or create our own and use it.
|
||||
* We would however need to realloc anyways, because RetroArch
|
||||
* expects a \0 at the end, therefore we allocate new,
|
||||
* copy and free the old one. */
|
||||
*buf = malloc(outsize + 1);
|
||||
((char*)(*buf))[outsize] = '\0';
|
||||
memcpy(*buf,outBuffer+offset,outsize);
|
||||
}
|
||||
IAlloc_Free(&allocImp, outBuffer);
|
||||
break;
|
||||
}
|
||||
@ -437,3 +461,5 @@ error:
|
||||
string_list_free(ext_list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
|
||||
|
@ -21,7 +21,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
int read_7zip_file(const char * archive_path,
|
||||
const char *relative_path, void **buf);
|
||||
const char *relative_path, void **buf, char const* optional_outfileq);
|
||||
|
||||
struct string_list *compressed_7zip_file_list_new(const char *path,
|
||||
const char* ext);
|
||||
|
@ -26,15 +26,22 @@
|
||||
|
||||
#include "../deps/rzlib/unzip.h"
|
||||
|
||||
/* Undefined at the end of the file
|
||||
* Don't use outside of this file
|
||||
*/
|
||||
#define RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX 16384
|
||||
|
||||
/* Extract the relative path relative_path from a
|
||||
* zip archive archive_path and allocate a buf for it to write it in. */
|
||||
/* This code is inspired by:
|
||||
* stackoverflow.com/questions/10440113/simple-way-to-unzip-a-zip-file-using-zlib
|
||||
*
|
||||
* optional_outfile if not NULL will be used to extract the file. buf will be 0
|
||||
* then.
|
||||
*/
|
||||
|
||||
int read_zip_file(const char * archive_path,
|
||||
const char *relative_path, void **buf)
|
||||
const char *relative_path, void **buf, const char* optional_outfile)
|
||||
{
|
||||
ssize_t bytes_read = -1;
|
||||
bool finished_reading = false;
|
||||
@ -94,22 +101,55 @@ int read_zip_file(const char * archive_path,
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Allocate outbuffer */
|
||||
*buf = malloc(file_info.uncompressed_size + 1 );
|
||||
|
||||
bytes_read = unzReadCurrentFile( zipfile, *buf, file_info.uncompressed_size );
|
||||
if (bytes_read != file_info.uncompressed_size)
|
||||
if (optional_outfile != 0)
|
||||
{
|
||||
RARCH_ERR(
|
||||
char read_buffer[RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX];
|
||||
FILE* outsink = fopen(optional_outfile,"wb");
|
||||
if (outsink == NULL)
|
||||
{
|
||||
RARCH_ERR("Could not open outfilepath %s in zip_extract.\n",
|
||||
optional_outfile);
|
||||
unzCloseCurrentFile( zipfile );
|
||||
unzClose( zipfile );
|
||||
return -1;
|
||||
}
|
||||
bytes_read = 0;
|
||||
do
|
||||
{
|
||||
bytes_read = unzReadCurrentFile( zipfile, read_buffer,
|
||||
RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX );
|
||||
ssize_t fwrite_bytes = fwrite(read_buffer,1,bytes_read,outsink);
|
||||
if (fwrite_bytes != bytes_read)
|
||||
{
|
||||
/* couldn't write all bytes */
|
||||
RARCH_ERR("Error writing to %s.\n",optional_outfile);
|
||||
fclose(outsink);
|
||||
unzCloseCurrentFile( zipfile );
|
||||
unzClose( zipfile );
|
||||
return -1;
|
||||
}
|
||||
} while(bytes_read > 0) ;
|
||||
fclose(outsink);
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Allocate outbuffer */
|
||||
*buf = malloc(file_info.uncompressed_size + 1 );
|
||||
|
||||
bytes_read = unzReadCurrentFile( zipfile, *buf, file_info.uncompressed_size );
|
||||
if (bytes_read != file_info.uncompressed_size)
|
||||
{
|
||||
RARCH_ERR(
|
||||
"We tried to read %d bytes, but only got %d of file %s in zip %s.\n",
|
||||
(unsigned int) file_info.uncompressed_size, (int)bytes_read,
|
||||
relative_path, archive_path);
|
||||
free(*buf);
|
||||
unzCloseCurrentFile( zipfile );
|
||||
unzClose( zipfile );
|
||||
return -1;
|
||||
free(*buf);
|
||||
unzCloseCurrentFile( zipfile );
|
||||
unzClose( zipfile );
|
||||
return -1;
|
||||
}
|
||||
((char*)(*buf))[file_info.uncompressed_size] = '\0';
|
||||
}
|
||||
((char*)(*buf))[file_info.uncompressed_size] = '\0';
|
||||
finished_reading = true;
|
||||
}
|
||||
unzCloseCurrentFile( zipfile );
|
||||
@ -238,3 +278,5 @@ struct string_list *compressed_zip_file_list_new(const char *path,
|
||||
unzClose( zipfile );
|
||||
return list;
|
||||
}
|
||||
|
||||
#undef RARCH_ZIP_SUPPORT_BUFFER_SIZE_MAX
|
||||
|
@ -21,7 +21,7 @@ extern "C" {
|
||||
#endif
|
||||
|
||||
int read_zip_file(const char * archive_path,
|
||||
const char *relative_path, void **buf);
|
||||
const char *relative_path, void **buf, const char* optional_outfile);
|
||||
|
||||
struct string_list *compressed_zip_file_list_new(const char *path,
|
||||
const char* ext);
|
||||
|
19
file.c
19
file.c
@ -387,9 +387,22 @@ static bool load_content(const struct retro_subsystem_info *special,
|
||||
" load it on its own.\n");
|
||||
if (need_fullpath && path_contains_compressed_file(path))
|
||||
{
|
||||
RARCH_ERR("Compressed files are only supported for drivers,"
|
||||
" where need_fullpath is set to false. Exiting.\n");
|
||||
rarch_assert(false);
|
||||
RARCH_LOG("Compressed file in case of need_fullpath."
|
||||
"Now extracting to temporary directory.\n");
|
||||
|
||||
if ((!strcmp(g_settings.extraction_directory,"")) ||
|
||||
!path_is_directory(g_settings.extraction_directory))
|
||||
{
|
||||
RARCH_ERR("Tried extracting to extraction directory, but "
|
||||
"extraction directory was not set or found. Exiting.\n");
|
||||
rarch_assert(false);
|
||||
}
|
||||
|
||||
char new_path[PATH_MAX];
|
||||
fill_pathname_join(new_path,g_settings.extraction_directory,
|
||||
path_basename(path),sizeof(new_path));
|
||||
read_compressed_file(path,NULL,new_path);
|
||||
info[i].path = strdup(new_path);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
22
file_path.c
22
file_path.c
@ -92,10 +92,22 @@ bool write_empty_file(const char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
/* Generic compressed file loader. */
|
||||
/* Generic compressed file loader.
|
||||
* Extracts to buf, unless optional_filename != 0
|
||||
* Then extracts to optional_filename and leaves buf alone.
|
||||
*/
|
||||
#ifdef HAVE_COMPRESSION
|
||||
long read_compressed_file(const char * path, void **buf)
|
||||
long read_compressed_file(const char * path, void **buf,
|
||||
const char* optional_filename)
|
||||
{
|
||||
/* Safety check.
|
||||
* If optional_filename and optional_filename exists, we simply return 0,
|
||||
* hoping that optional_filename is the same as requested.
|
||||
*/
|
||||
if (optional_filename)
|
||||
if(path_file_exists(optional_filename))
|
||||
return 0;
|
||||
|
||||
//We split carchive path and relative path:
|
||||
char archive_path[PATH_MAX];
|
||||
strlcpy(archive_path,path,sizeof(archive_path));
|
||||
@ -123,11 +135,11 @@ long read_compressed_file(const char * path, void **buf)
|
||||
const char* file_ext = path_get_extension(archive_path);
|
||||
#ifdef HAVE_7ZIP
|
||||
if (strcasecmp(file_ext,"7z") == 0)
|
||||
return read_7zip_file(archive_path,archive_found,buf);
|
||||
return read_7zip_file(archive_path,archive_found,buf,optional_filename);
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
if (strcasecmp(file_ext,"zip") == 0)
|
||||
return read_zip_file(archive_path,archive_found,buf);
|
||||
return read_zip_file(archive_path,archive_found,buf,optional_filename);
|
||||
#endif
|
||||
return -1;
|
||||
}
|
||||
@ -187,7 +199,7 @@ long read_file(const char *path, void **buf)
|
||||
* */
|
||||
#ifdef HAVE_COMPRESSION
|
||||
if (path_contains_compressed_file(path))
|
||||
return read_compressed_file(path,buf);
|
||||
return read_compressed_file(path,buf,0);
|
||||
#endif
|
||||
return read_generic_file(path,buf);
|
||||
}
|
||||
|
@ -43,7 +43,8 @@ enum
|
||||
|
||||
|
||||
#ifdef HAVE_COMPRESSION
|
||||
long read_compressed_file(const char * path, void **buf);
|
||||
long read_compressed_file(const char * path, void **buf,
|
||||
const char* optional_filename);
|
||||
#endif
|
||||
|
||||
long read_file(const char *path, void **buf);
|
||||
|
@ -56,6 +56,19 @@ static void *get_last_setting(const file_list_t *list, int index,
|
||||
return NULL;
|
||||
}
|
||||
|
||||
static int menu_message_toggle(unsigned action)
|
||||
{
|
||||
if (driver.video_data && driver.menu_ctx
|
||||
&& driver.menu_ctx->render_messagebox)
|
||||
{
|
||||
driver.menu_ctx->render_messagebox(driver.menu->message_contents);
|
||||
}
|
||||
if (action == MENU_ACTION_OK)
|
||||
menu_entries_pop(driver.menu->menu_stack);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int menu_info_screen_iterate(unsigned action)
|
||||
{
|
||||
char msg[PATH_MAX];
|
||||
@ -1632,6 +1645,84 @@ static void menu_common_load_content(void)
|
||||
driver.menu->msg_force = true;
|
||||
}
|
||||
|
||||
static int menu_load_or_open_zip_iterate(unsigned action)
|
||||
{
|
||||
char msg[PATH_MAX];
|
||||
snprintf(msg, sizeof(msg), "Opening compressed file\n"
|
||||
" \n"
|
||||
|
||||
" - OK to open as Folder\n"
|
||||
" - Cancel/Back to Load \n");
|
||||
|
||||
if (driver.video_data && driver.menu_ctx
|
||||
&& driver.menu_ctx->render_messagebox)
|
||||
{
|
||||
if (*msg && msg[0] != '\0')
|
||||
driver.menu_ctx->render_messagebox(msg);
|
||||
}
|
||||
|
||||
if (action == MENU_ACTION_OK)
|
||||
{
|
||||
menu_entries_pop(driver.menu->menu_stack);
|
||||
|
||||
const char *menu_path;
|
||||
const char *menu_label;
|
||||
unsigned int menu_type;
|
||||
char const* path;
|
||||
char const* label;
|
||||
unsigned int type;
|
||||
|
||||
file_list_get_last(driver.menu->menu_stack, &menu_path, &menu_label,
|
||||
&menu_type);
|
||||
|
||||
if (file_list_get_size(driver.menu->selection_buf) == 0)
|
||||
return 0;
|
||||
|
||||
file_list_get_at_offset(driver.menu->selection_buf,
|
||||
driver.menu->selection_ptr, &path, &label, &type);
|
||||
|
||||
char cat_path[PATH_MAX];
|
||||
fill_pathname_join(cat_path, menu_path, path, sizeof(cat_path));
|
||||
menu_entries_push(driver.menu->menu_stack, cat_path, menu_label, type,
|
||||
driver.menu->selection_ptr);
|
||||
}
|
||||
else if (action == MENU_ACTION_CANCEL)
|
||||
{
|
||||
menu_entries_pop(driver.menu->menu_stack);
|
||||
|
||||
const char *menu_path;
|
||||
const char *menu_label;
|
||||
unsigned int menu_type;
|
||||
char const* path;
|
||||
char const* label;
|
||||
unsigned int type;
|
||||
|
||||
file_list_get_last(driver.menu->menu_stack, &menu_path, &menu_label,
|
||||
&menu_type);
|
||||
|
||||
if (file_list_get_size(driver.menu->selection_buf) == 0)
|
||||
return 0;
|
||||
|
||||
file_list_get_at_offset(driver.menu->selection_buf,
|
||||
driver.menu->selection_ptr, &path, &label, &type);
|
||||
|
||||
int ret = rarch_defer_core(g_extern.core_info, menu_path, path,
|
||||
driver.menu->deferred_path, sizeof(driver.menu->deferred_path));
|
||||
if (ret == -1)
|
||||
{
|
||||
rarch_main_command(RARCH_CMD_LOAD_CORE);
|
||||
menu_common_load_content();
|
||||
return -1;
|
||||
}
|
||||
else if (ret == 0)
|
||||
menu_entries_push(driver.menu->menu_stack,
|
||||
g_settings.libretro_directory, "deferred_core_list", 0,
|
||||
driver.menu->selection_ptr);
|
||||
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int menu_action_ok(const char *menu_path,
|
||||
const char *menu_label, unsigned menu_type)
|
||||
{
|
||||
@ -1656,9 +1747,10 @@ static int menu_action_ok(const char *menu_path,
|
||||
RARCH_LOG("type : %d\n", type == MENU_FILE_USE_DIRECTORY);
|
||||
RARCH_LOG("type id : %d\n", type);
|
||||
#endif
|
||||
|
||||
switch (type)
|
||||
while (true)
|
||||
{
|
||||
switch (type)
|
||||
{
|
||||
case MENU_FILE_PLAYLIST_ENTRY:
|
||||
|
||||
rarch_playlist_load_content(g_extern.history,
|
||||
@ -1670,13 +1762,13 @@ static int menu_action_ok(const char *menu_path,
|
||||
case MENU_FILE_IN_CARCHIVE:
|
||||
#endif
|
||||
case MENU_FILE_PLAIN:
|
||||
|
||||
if (!strcmp(menu_label, "detect_core_list"))
|
||||
{
|
||||
int ret = rarch_defer_core(g_extern.core_info,
|
||||
menu_path, path, driver.menu->deferred_path,
|
||||
sizeof(driver.menu->deferred_path));
|
||||
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
|
||||
@ -1836,6 +1928,12 @@ static int menu_action_ok(const char *menu_path,
|
||||
case MENU_FILE_CARCHIVE:
|
||||
|
||||
{
|
||||
if (type == MENU_FILE_CARCHIVE && !strcmp(menu_label, "detect_core_list"))
|
||||
{
|
||||
file_list_push(driver.menu->menu_stack, path, "load_open_zip",
|
||||
0, driver.menu->selection_ptr);
|
||||
return 0;
|
||||
}
|
||||
char cat_path[PATH_MAX];
|
||||
fill_pathname_join(cat_path, menu_path, path, sizeof(cat_path));
|
||||
menu_entries_push(driver.menu->menu_stack,
|
||||
@ -1843,7 +1941,9 @@ static int menu_action_ok(const char *menu_path,
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (menu_parse_check(label, type) == 0)
|
||||
@ -1872,6 +1972,10 @@ static int menu_common_iterate(unsigned action)
|
||||
|
||||
if (!strcmp(menu_label, "help"))
|
||||
return menu_start_screen_iterate(action);
|
||||
else if (!strcmp(menu_label, "message"))
|
||||
return menu_message_toggle(action);
|
||||
else if (!strcmp(menu_label, "load_open_zip"))
|
||||
return menu_load_or_open_zip_iterate(action);
|
||||
else if (!strcmp(menu_label, "info_screen"))
|
||||
return menu_info_screen_iterate(action);
|
||||
else if (menu_common_type_is(menu_label, menu_type) == MENU_SETTINGS)
|
||||
|
@ -290,6 +290,8 @@ static unsigned input_frame(uint64_t trigger_state)
|
||||
return MENU_ACTION_CANCEL;
|
||||
if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_A))
|
||||
return MENU_ACTION_OK;
|
||||
if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_Y))
|
||||
return MENU_ACTION_Y;
|
||||
if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_START))
|
||||
return MENU_ACTION_START;
|
||||
if (trigger_state & (1ULL << RETRO_DEVICE_ID_JOYPAD_SELECT))
|
||||
|
@ -87,6 +87,7 @@ typedef enum
|
||||
MENU_ACTION_LEFT,
|
||||
MENU_ACTION_RIGHT,
|
||||
MENU_ACTION_OK,
|
||||
MENU_ACTION_Y,
|
||||
MENU_ACTION_CANCEL,
|
||||
MENU_ACTION_REFRESH,
|
||||
MENU_ACTION_SELECT,
|
||||
|
@ -90,6 +90,12 @@ typedef struct
|
||||
bool defer_core;
|
||||
char deferred_path[PATH_MAX];
|
||||
|
||||
/* This buffer can be used to display generic OK messages to the user.
|
||||
* Fill it and call
|
||||
* file_list_push(driver.menu->menu_stack, "", "message", 0, 0);
|
||||
*/
|
||||
char message_contents[PATH_MAX];
|
||||
|
||||
/* Quick jumping indices with L/R.
|
||||
* Rebuilt when parsing directory. */
|
||||
size_t scroll_indices[2 * (26 + 2) + 1];
|
||||
|
@ -759,6 +759,17 @@ int menu_parse_and_resolve(file_list_t *list, file_list_t *menu_list)
|
||||
break;
|
||||
case RARCH_PLAIN_FILE:
|
||||
default:
|
||||
if (!strcmp(label, "detect_core_list"))
|
||||
{
|
||||
if (path_is_compressed_file(str_list->elems[i].data))
|
||||
{
|
||||
/* in case of deferred_core_list we have to interpret
|
||||
* every archive as an archive to disallow instant loading
|
||||
*/
|
||||
file_type = MENU_FILE_CARCHIVE;
|
||||
break;
|
||||
}
|
||||
}
|
||||
file_type = (menu_file_type_t)default_type_plain;
|
||||
break;
|
||||
}
|
||||
|
16
general.c
16
general.c
@ -121,6 +121,14 @@ int rarch_defer_core(core_info_list_t *core_info, const char *dir,
|
||||
|
||||
fill_pathname_join(deferred_path, dir, path, sizeof_deferred_path);
|
||||
|
||||
if (path_is_compressed_file(dir))
|
||||
{
|
||||
/* In case of a compressed archive, we have to join with a hash */
|
||||
/* We are going to write at the position of dir: */
|
||||
rarch_assert(strlen(dir) < strlen(deferred_path));
|
||||
deferred_path[strlen(dir)] = '#';
|
||||
}
|
||||
|
||||
if (core_info)
|
||||
core_info_list_get_supported_cores(core_info, deferred_path, &info,
|
||||
&supported);
|
||||
@ -130,14 +138,6 @@ int rarch_defer_core(core_info_list_t *core_info, const char *dir,
|
||||
{
|
||||
strlcpy(g_extern.fullpath, deferred_path,
|
||||
sizeof(g_extern.fullpath));
|
||||
if (path_is_compressed_file(dir))
|
||||
{
|
||||
/* In case of a compressed archive, we have to join with a hash.
|
||||
* We are going to write at the position of dir: */
|
||||
rarch_assert(strlen(dir) < strlen(g_extern.fullpath));
|
||||
g_extern.fullpath[strlen(dir)] = '#';
|
||||
}
|
||||
|
||||
if (path_file_exists(info->path))
|
||||
strlcpy(g_settings.libretro, info->path,
|
||||
sizeof(g_settings.libretro));
|
||||
|
Loading…
x
Reference in New Issue
Block a user