mirror of
https://github.com/libretro/RetroArch
synced 2025-03-01 07:13:35 +00:00
Merge remote-tracking branch 'refs/remotes/libretro/master'
This commit is contained in:
commit
0da7bdebf8
20
.editorconfig
Normal file
20
.editorconfig
Normal file
@ -0,0 +1,20 @@
|
||||
# EditorConfig: http://EditorConfig.org
|
||||
|
||||
# Top-most EditorConfig file
|
||||
root = true
|
||||
|
||||
# Unix-style newlines with a newline ending every file
|
||||
[*]
|
||||
end_of_line = lf
|
||||
insert_final_newline = true
|
||||
trim_trailing_whitespace = true
|
||||
charset = utf-8
|
||||
|
||||
# 3 space indentation
|
||||
[*.{c,h,js,css,html}]
|
||||
indent_style = space
|
||||
indent_size = 3
|
||||
|
||||
# Tab indentation
|
||||
[Makefile*]
|
||||
indent_style = tab
|
11
.travis.yml
11
.travis.yml
@ -23,6 +23,9 @@ script:
|
||||
- ./configure
|
||||
- make
|
||||
|
||||
env:
|
||||
global:
|
||||
- secure: "qc91ReC3OlzSh2gFaSH6TYzC2qIQvgA2AZff6J13eaH8xijAhuMzttZ0rMQJ0DWCIhPeUb0kIzVyaGoe4MwPALzpw1C1AznIWiZJ53HN+hWCOcS/af7YVPk6HPySnwqrS+Wv3AIIvIKFV2mxv21F/JbT/N+pArlRrp904Xj+KPo="
|
||||
addons:
|
||||
apt:
|
||||
packages:
|
||||
@ -35,3 +38,11 @@ addons:
|
||||
- libsdl-image1.2-dev
|
||||
- libsdl-mixer1.2-dev
|
||||
- libsdl-ttf2.0-dev
|
||||
coverity_scan:
|
||||
project:
|
||||
name: "RetroArch"
|
||||
description: "RetroArch is the official reference frontend for the libretro API."
|
||||
notification_email: libretro@gmail.com
|
||||
build_command_prepend: "./configure; make clean"
|
||||
build_command: "make"
|
||||
branch_pattern: coverity_scan
|
||||
|
@ -5,11 +5,11 @@ ifeq ($(HAVE_GL_CONTEXT),)
|
||||
HAVE_GL_CONTEXT=1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GLES), 1)
|
||||
ifeq ($(HAVE_OPENGLES), 1)
|
||||
HAVE_GL_CONTEXT=1
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GLES3), 1)
|
||||
ifeq ($(HAVE_OPENGLES3), 1)
|
||||
HAVE_GL_CONTEXT=1
|
||||
endif
|
||||
endif
|
||||
@ -132,6 +132,8 @@ OBJ += frontend/frontend.o \
|
||||
ui/drivers/null/ui_null_application.o \
|
||||
core_impl.o \
|
||||
retroarch.o \
|
||||
dirs.o \
|
||||
paths.o \
|
||||
input/input_keyboard.o \
|
||||
command.o \
|
||||
msg_hash.o \
|
||||
@ -140,11 +142,11 @@ OBJ += frontend/frontend.o \
|
||||
libretro-common/algorithms/mismatch.o \
|
||||
libretro-common/queues/task_queue.o \
|
||||
tasks/task_content.o \
|
||||
tasks/task_save_ram.o \
|
||||
tasks/task_save_state.o \
|
||||
tasks/task_save.o \
|
||||
tasks/task_file_transfer.o \
|
||||
tasks/task_image.o \
|
||||
libretro-common/encodings/encoding_utf.o \
|
||||
libretro-common/encodings/encoding_crc32.o \
|
||||
libretro-common/lists/file_list.o \
|
||||
libretro-common/lists/dir_list.o \
|
||||
libretro-common/file/retro_dirent.o \
|
||||
@ -505,12 +507,16 @@ ifeq ($(HAVE_MENU_COMMON), 1)
|
||||
OBJ += menu/menu_driver.o \
|
||||
menu/menu_content.o \
|
||||
menu/menu_input.o \
|
||||
menu/menu_entry.o \
|
||||
menu/menu_event.o \
|
||||
menu/menu_entries.o \
|
||||
menu/menu_navigation.o \
|
||||
menu/menu_setting.o \
|
||||
menu/menu_shader.o \
|
||||
menu/widgets/menu_popup.o \
|
||||
menu/widgets/menu_dialog.o \
|
||||
menu/widgets/menu_input_dialog.o \
|
||||
menu/widgets/menu_input_bind_dialog.o \
|
||||
menu/widgets/menu_entry.o \
|
||||
menu/widgets/menu_list.o \
|
||||
menu/menu_cbs.o \
|
||||
menu/cbs/menu_cbs_ok.o \
|
||||
menu/cbs/menu_cbs_cancel.o \
|
||||
@ -596,7 +602,7 @@ ifeq ($(HAVE_X11), 1)
|
||||
ifeq ($(HAVE_XCB),1)
|
||||
LIBS += -lX11-xcb
|
||||
endif
|
||||
ifneq ($(HAVE_GLES), 1)
|
||||
ifneq ($(HAVE_OPENGLES), 1)
|
||||
OBJ += gfx/drivers_context/x_ctx.o
|
||||
endif
|
||||
endif
|
||||
@ -612,6 +618,11 @@ ifeq ($(HAVE_XKBCOMMON), 1)
|
||||
LIBS += $(XKBCOMMON_LIBS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_DBUS), 1)
|
||||
LIBS += $(DBUS_LIBS)
|
||||
CFLAGS += $(DBUS_CFLAGS)
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_UDEV), 1)
|
||||
DEFINES += $(UDEV_CFLAGS)
|
||||
LIBS += $(UDEV_LIBS)
|
||||
@ -679,6 +690,7 @@ OBJ += gfx/video_context_driver.o \
|
||||
gfx/video_state_tracker.o \
|
||||
libretro-common/gfx/math/vector_2.o \
|
||||
libretro-common/gfx/math/vector_3.o \
|
||||
libretro-common/gfx/math/vector_4.o \
|
||||
libretro-common/gfx/math/matrix_4x4.o \
|
||||
libretro-common/gfx/math/matrix_3x3.o
|
||||
|
||||
@ -743,7 +755,7 @@ ifeq ($(HAVE_GL_CONTEXT), 1)
|
||||
endif
|
||||
ifeq ($(HAVE_FFMPEG), 1)
|
||||
ifneq ($(C89_BUILD), 1)
|
||||
ifneq ($(HAVE_GLES), 1)
|
||||
ifneq ($(HAVE_OPENGLES), 1)
|
||||
OBJ += cores/libretro-ffmpeg/fft/fft.o
|
||||
DEFINES += -Ideps -DHAVE_GL_FFT
|
||||
NEED_CXX_LINKER=1
|
||||
@ -751,10 +763,10 @@ endif
|
||||
endif
|
||||
endif
|
||||
|
||||
ifeq ($(HAVE_GLES), 1)
|
||||
ifeq ($(HAVE_OPENGLES), 1)
|
||||
LIBS += $(GLES_LIBS)
|
||||
DEFINES += $(GLES_CFLAGS) -DHAVE_OPENGLES
|
||||
ifeq ($(HAVE_GLES3), 1)
|
||||
ifeq ($(HAVE_OPENGLES3), 1)
|
||||
DEFINES += -DHAVE_OPENGLES3
|
||||
else
|
||||
DEFINES += -DHAVE_OPENGLES2
|
||||
@ -959,6 +971,8 @@ endif
|
||||
|
||||
# Compression/Archive
|
||||
|
||||
OBJ += libretro-common/file/archive_file.o
|
||||
|
||||
ifeq ($(HAVE_7ZIP),1)
|
||||
CFLAGS += -I./deps/7zip
|
||||
HAVE_COMPRESSION = 1
|
||||
@ -977,14 +991,13 @@ ifeq ($(HAVE_7ZIP),1)
|
||||
deps/7zip/7zCrc.o \
|
||||
deps/7zip/Lzma2Dec.o \
|
||||
deps/7zip/7zBuf.o
|
||||
OBJ += $(7ZOBJ)
|
||||
OBJ += libretro-common/file/archive_file_7z.o \
|
||||
$(7ZOBJ)
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(HAVE_ZLIB), 1)
|
||||
OBJ += libretro-common/file/archive_file.o \
|
||||
libretro-common/file/archive_file_zlib.o \
|
||||
tasks/task_decompress.o
|
||||
OBJ += libretro-common/file/archive_file_zlib.o
|
||||
OBJ += $(ZLIB_OBJS)
|
||||
DEFINES += -DHAVE_ZLIB
|
||||
HAVE_COMPRESSION = 1
|
||||
@ -1133,8 +1146,10 @@ ifeq ($(HAVE_FFMPEG), 1)
|
||||
DEFINES += -Wno-deprecated-declarations -DHAVE_FFMPEG -Iffmpeg
|
||||
endif
|
||||
|
||||
|
||||
ifeq ($(HAVE_COMPRESSION), 1)
|
||||
DEFINES += -DHAVE_COMPRESSION
|
||||
OBJ += tasks/task_decompress.o
|
||||
endif
|
||||
|
||||
#ifeq ($(HAVE_DIRECTX), 1)
|
||||
|
@ -46,6 +46,7 @@ else
|
||||
CFLAGS += -DHAVE_COMPRESSION
|
||||
OBJS += libretro-common/file/archive_file.o
|
||||
OBJS += libretro-common/file/archive_file_zlib.o
|
||||
OBJS += libretro-common/file/archive_file_7z.o
|
||||
OBJS += libretro-common/encodings/encoding_utf.o
|
||||
OBJS += verbosity.o
|
||||
OBJS += performance.o
|
||||
|
@ -9,9 +9,8 @@ DEFINES := -DRARCH_INTERNAL -DHAVE_OVERLAY -DHAVE_MAIN
|
||||
DEFINES += -DHAVE_OPENGL -DHAVE_OPENGLES -DHAVE_OPENGLES2 -DHAVE_EGL -DHAVE_OVERLAY -DHAVE_GLSL -DHAVE_FILTERS_BUILTIN
|
||||
|
||||
HAVE_EGL = 1
|
||||
HAVE_OPENGL = 1
|
||||
HAVE_GLES = 1
|
||||
HAVE_RJPEG = 1
|
||||
HAVE_OPENGLES = 1
|
||||
HAVE_RJPEG = 0
|
||||
HAVE_RPNG = 1
|
||||
HAVE_EMSCRIPTEN = 1
|
||||
HAVE_RGUI = 1
|
||||
@ -84,7 +83,7 @@ else
|
||||
CFLAGS += -O2
|
||||
endif
|
||||
|
||||
CFLAGS += -DHAVE_RPNG -DHAVE_RJPEG -Wall -Wno-unused-result -Wno-unused-variable -I. -Ilibretro-common/include -std=gnu99 -s USE_ZLIB=1 \
|
||||
CFLAGS += -DHAVE_RPNG -Wall -Wno-unused-result -Wno-unused-variable -I. -Ilibretro-common/include -std=gnu99 -s USE_ZLIB=1 \
|
||||
-s EXPORTED_FUNCTIONS="['_main', '_malloc', '_cmd_savefiles', '_cmd_save_state', '_cmd_take_screenshot']"
|
||||
|
||||
all: $(TARGET)
|
||||
|
@ -796,8 +796,10 @@ bool audio_driver_find_driver(void)
|
||||
|
||||
void audio_driver_deinit_resampler(void)
|
||||
{
|
||||
rarch_resampler_freep(&audio_driver_resampler,
|
||||
&audio_driver_resampler_data);
|
||||
if (audio_driver_resampler && audio_driver_resampler_data)
|
||||
audio_driver_resampler->free(audio_driver_resampler_data);
|
||||
audio_driver_resampler = NULL;
|
||||
audio_driver_resampler_data = NULL;
|
||||
}
|
||||
|
||||
bool audio_driver_free_devices_list(void)
|
||||
@ -852,8 +854,8 @@ void audio_driver_process_resampler(void *data)
|
||||
struct resampler_data *resampler = (struct resampler_data*)data;
|
||||
performance_counter_init(&resampler_proc, "resampler_proc");
|
||||
performance_counter_start(&resampler_proc);
|
||||
rarch_resampler_process(audio_driver_resampler,
|
||||
audio_driver_resampler_data, resampler);
|
||||
|
||||
audio_driver_resampler->process(audio_driver_resampler_data, resampler);
|
||||
performance_counter_stop(&resampler_proc);
|
||||
}
|
||||
|
||||
|
@ -19,10 +19,6 @@
|
||||
#include <string/stdstring.h>
|
||||
#include <features/features_cpu.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#include "audio_resampler_driver.h"
|
||||
#include "../config_file_userdata.h"
|
||||
#include "../performance_counters.h"
|
||||
|
@ -181,20 +181,6 @@ const char *audio_resampler_driver_find_ident(int index);
|
||||
bool rarch_resampler_realloc(void **re, const rarch_resampler_t **backend,
|
||||
const char *ident, double bw_ratio);
|
||||
|
||||
/* Convenience macros.
|
||||
* freep makes sure to set handles to NULL to avoid double-free
|
||||
* in rarch_resampler_realloc. */
|
||||
#define rarch_resampler_freep(backend, handle) do { \
|
||||
if (*(backend) && *(handle)) \
|
||||
(*backend)->free(*handle); \
|
||||
*backend = NULL; \
|
||||
*handle = NULL; \
|
||||
} while(0)
|
||||
|
||||
#define rarch_resampler_process(backend, handle, data) do { \
|
||||
(backend)->process(handle, data); \
|
||||
} while(0)
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -87,7 +87,7 @@ int main(int argc, char *argv[])
|
||||
data.input_frames = sizeof(input_f) / (2 * sizeof(float));
|
||||
data.ratio = ratio * rate_mod;
|
||||
|
||||
rarch_resampler_process(resampler, re, &data);
|
||||
resampler->process(re, &data);
|
||||
|
||||
output_samples = data.output_frames * 2;
|
||||
|
||||
@ -97,6 +97,9 @@ int main(int argc, char *argv[])
|
||||
break;
|
||||
}
|
||||
|
||||
rarch_resampler_freep(&resampler, &re);
|
||||
if (resampler && re)
|
||||
resampler->free(re);
|
||||
resampler = NULL;
|
||||
re = NULL;
|
||||
}
|
||||
|
||||
|
@ -327,7 +327,7 @@ int main(int argc, char *argv[])
|
||||
data.input_frames = in_rate * 2;
|
||||
data.ratio = ratio;
|
||||
|
||||
rarch_resampler_process(resampler, re, &data);
|
||||
resampler->process(re, &data);
|
||||
|
||||
/* We generate 2 seconds worth of audio, however,
|
||||
* only the last second is considered so phase has stabilized. */
|
||||
@ -346,7 +346,10 @@ int main(int argc, char *argv[])
|
||||
res.alias_freq[2] / (float)in_rate, res.alias_power[2]);
|
||||
}
|
||||
|
||||
rarch_resampler_freep(&resampler, &re);
|
||||
if (resampler && re)
|
||||
resampler->free(re);
|
||||
resampler = NULL;
|
||||
re = NULL;
|
||||
|
||||
free(input);
|
||||
free(output);
|
||||
|
140
command.c
140
command.c
@ -48,7 +48,7 @@
|
||||
#include "menu/menu_content.h"
|
||||
#include "menu/menu_display.h"
|
||||
#include "menu/menu_shader.h"
|
||||
#include "menu/widgets/menu_popup.h"
|
||||
#include "menu/widgets/menu_dialog.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
@ -74,6 +74,7 @@
|
||||
#include "dynamic.h"
|
||||
#include "content.h"
|
||||
#include "movie.h"
|
||||
#include "paths.h"
|
||||
#include "msg_hash.h"
|
||||
#include "retroarch.h"
|
||||
#include "managers/cheat_manager.h"
|
||||
@ -989,8 +990,8 @@ static bool command_event_disk_control_append_image(const char *path)
|
||||
* If we actually use append_image, we assume that we
|
||||
* started out in a single disk case, and that this way
|
||||
* of doing it makes the most sense. */
|
||||
retroarch_set_pathnames(path);
|
||||
retroarch_fill_pathnames();
|
||||
path_set_names(path);
|
||||
path_fill_names();
|
||||
}
|
||||
|
||||
command_event(CMD_EVENT_AUTOSAVE_INIT, NULL);
|
||||
@ -1202,22 +1203,6 @@ static void command_event_init_cheats(void)
|
||||
/* TODO/FIXME - add some stuff here. */
|
||||
}
|
||||
|
||||
static bool event_load_save_files(void)
|
||||
{
|
||||
unsigned i;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return false;
|
||||
if (!global->savefiles || global->sram.load_disable)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < global->savefiles->size; i++)
|
||||
content_load_ram_file(i);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static void command_event_load_auto_state(void)
|
||||
{
|
||||
bool ret;
|
||||
@ -1327,7 +1312,7 @@ static bool event_init_content(void)
|
||||
return true;
|
||||
|
||||
if (!content_does_not_need_content())
|
||||
retroarch_fill_pathnames();
|
||||
path_fill_names();
|
||||
|
||||
if (!content_init())
|
||||
return false;
|
||||
@ -1479,14 +1464,12 @@ static bool command_event_save_core_config(void)
|
||||
bool found_path = false;
|
||||
bool overrides_active = false;
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
*config_dir = '\0';
|
||||
if (!string_is_empty(settings->directory.menu_config))
|
||||
strlcpy(config_dir, settings->directory.menu_config,
|
||||
sizeof(config_dir));
|
||||
else if (!string_is_empty(global->path.config)) /* Fallback */
|
||||
fill_pathname_basedir(config_dir, global->path.config,
|
||||
else if (!path_is_config_empty()) /* Fallback */
|
||||
fill_pathname_basedir(config_dir, path_get_config(),
|
||||
sizeof(config_dir));
|
||||
else
|
||||
{
|
||||
@ -1496,8 +1479,7 @@ static bool command_event_save_core_config(void)
|
||||
}
|
||||
|
||||
/* Infer file name based on libretro core. */
|
||||
if (!string_is_empty(config_get_active_core_path())
|
||||
&& path_file_exists(config_get_active_core_path()))
|
||||
if (!string_is_empty(path_get_core()) && path_file_exists(path_get_core()))
|
||||
{
|
||||
unsigned i;
|
||||
RARCH_LOG("%s\n", msg_hash_to_str(MSG_USING_CORE_NAME_FOR_NEW_CONFIG));
|
||||
@ -1509,7 +1491,7 @@ static bool command_event_save_core_config(void)
|
||||
|
||||
fill_pathname_base_noext(
|
||||
config_name,
|
||||
config_get_active_core_path(),
|
||||
path_get_core(),
|
||||
sizeof(config_name));
|
||||
|
||||
fill_pathname_join(config_path, config_dir, config_name,
|
||||
@ -1556,8 +1538,7 @@ static bool command_event_save_core_config(void)
|
||||
|
||||
if ((ret = config_save_file(config_path)))
|
||||
{
|
||||
strlcpy(global->path.config, config_path,
|
||||
sizeof(global->path.config));
|
||||
path_set_config(config_path);
|
||||
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
||||
msg_hash_to_str(MSG_SAVED_NEW_CONFIG_TO),
|
||||
config_path);
|
||||
@ -1589,17 +1570,16 @@ static bool command_event_save_core_config(void)
|
||||
**/
|
||||
void command_event_save_current_config(int override_type)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
char msg[128] = {0};
|
||||
|
||||
if (!override_type)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
|
||||
if (settings->config_save_on_exit && !string_is_empty(global->path.config))
|
||||
if (settings->config_save_on_exit && !path_is_config_empty())
|
||||
{
|
||||
bool ret = false;
|
||||
char msg[128] = {0};
|
||||
const char *config_path = config_get_active_path();
|
||||
const char *config_path = path_get_config();
|
||||
|
||||
/* Save last core-specific config to the default config location,
|
||||
* needed on consoles for core switching and reusing last good
|
||||
@ -1614,41 +1594,38 @@ void command_event_save_current_config(int override_type)
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
||||
msg_hash_to_str(MSG_SAVED_NEW_CONFIG_TO),
|
||||
global->path.config);
|
||||
path_get_config());
|
||||
RARCH_LOG("%s\n", msg);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "%s \"%s\".",
|
||||
msg_hash_to_str(MSG_FAILED_SAVING_CONFIG_TO),
|
||||
global->path.config);
|
||||
path_get_config());
|
||||
RARCH_ERR("%s\n", msg);
|
||||
}
|
||||
|
||||
runloop_msg_queue_push(msg, 1, 180, true);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
bool ret = false;
|
||||
char msg[128] = {0};
|
||||
|
||||
ret = config_save_overrides(override_type);
|
||||
|
||||
if (ret)
|
||||
if (config_save_overrides(override_type))
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "Overrides saved successfully");
|
||||
RARCH_LOG("[overrides] %s\n", msg);
|
||||
|
||||
/* set overrides to active so the original config can be
|
||||
restored after closing content */
|
||||
runloop_ctl(RUNLOOP_CTL_SET_OVERRIDES_ACTIVE, NULL);
|
||||
}
|
||||
else
|
||||
{
|
||||
snprintf(msg, sizeof(msg), "Error saving overrides");
|
||||
RARCH_ERR("[overrides] %s\n", msg);
|
||||
}
|
||||
|
||||
runloop_msg_queue_push(msg, 1, 180, true);
|
||||
return;
|
||||
}
|
||||
|
||||
if (!string_is_empty(msg))
|
||||
runloop_msg_queue_push(msg, 1, 180, true);
|
||||
}
|
||||
|
||||
/**
|
||||
@ -1720,6 +1697,10 @@ static void command_event_load_state(const char *path, char *s, size_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_LOAD_SAVESTATE, NULL);
|
||||
#endif
|
||||
|
||||
if (settings->state_slot < 0)
|
||||
snprintf(s, len, "%s #-1 (auto).",
|
||||
msg_hash_to_str(MSG_LOADED_STATE_FROM_SLOT));
|
||||
@ -1747,6 +1728,10 @@ static void command_event_undo_load_state(char *s, size_t len)
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
netplay_driver_ctl(RARCH_NETPLAY_CTL_LOAD_SAVESTATE, NULL);
|
||||
#endif
|
||||
|
||||
strlcpy(s,
|
||||
msg_hash_to_str(MSG_UNDID_LOAD_STATE), len);
|
||||
}
|
||||
@ -1801,7 +1786,7 @@ void handle_quit_event()
|
||||
settings_t *settings = config_get_ptr();
|
||||
#ifdef HAVE_MENU
|
||||
if (settings && settings->confirm_on_exit &&
|
||||
menu_popup_is_active())
|
||||
menu_dialog_is_active())
|
||||
return;
|
||||
#endif
|
||||
|
||||
@ -1884,17 +1869,14 @@ bool command_event(enum event_command cmd, void *data)
|
||||
core_info_ctx_find_t info_find;
|
||||
|
||||
#if defined(HAVE_DYNAMIC)
|
||||
if (string_is_empty(config_get_active_core_path()))
|
||||
if (string_is_empty(path_get_core()))
|
||||
return false;
|
||||
|
||||
#endif
|
||||
libretro_get_system_info(
|
||||
config_get_active_core_path(),
|
||||
path_get_core(),
|
||||
system,
|
||||
ptr);
|
||||
#else
|
||||
libretro_get_system_info_static(system, ptr);
|
||||
#endif
|
||||
info_find.path = config_get_active_core_path();
|
||||
info_find.path = path_get_core();
|
||||
|
||||
if (!core_info_load(&info_find))
|
||||
{
|
||||
@ -1918,11 +1900,6 @@ bool command_event(enum event_command cmd, void *data)
|
||||
if (bsv_movie_ctl(BSV_MOVIE_CTL_IS_INITED, NULL))
|
||||
return false;
|
||||
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL))
|
||||
return false;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_CHEEVOS
|
||||
if (settings->cheevos.hardcore_mode_enable)
|
||||
return false;
|
||||
@ -2026,9 +2003,9 @@ bool command_event(enum event_command cmd, void *data)
|
||||
case CMD_EVENT_QUIT:
|
||||
#ifdef HAVE_MENU
|
||||
if (settings && settings->confirm_on_exit &&
|
||||
!menu_popup_is_active() && !runloop_is_quit_confirm())
|
||||
!menu_dialog_is_active() && !runloop_is_quit_confirm())
|
||||
{
|
||||
menu_popup_show_message(MENU_POPUP_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT);
|
||||
menu_dialog_show_message(MENU_DIALOG_QUIT_CONFIRM, MENU_ENUM_LABEL_CONFIRM_ON_EXIT);
|
||||
break;
|
||||
}
|
||||
#endif
|
||||
@ -2442,45 +2419,6 @@ bool command_event(enum event_command cmd, void *data)
|
||||
if (!runloop_ctl(RUNLOOP_CTL_SHADER_DIR_INIT, NULL))
|
||||
return false;
|
||||
break;
|
||||
case CMD_EVENT_SAVEFILES:
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
if (!global->savefiles || !global->sram.use)
|
||||
return false;
|
||||
|
||||
for (i = 0; i < global->savefiles->size; i++)
|
||||
content_save_ram_file(i);
|
||||
}
|
||||
return true;
|
||||
case CMD_EVENT_SAVEFILES_DEINIT:
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
if (!global)
|
||||
break;
|
||||
|
||||
if (global->savefiles)
|
||||
string_list_free(global->savefiles);
|
||||
global->savefiles = NULL;
|
||||
}
|
||||
break;
|
||||
case CMD_EVENT_SAVEFILES_INIT:
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
global->sram.use = global->sram.use && !global->sram.save_disable;
|
||||
#ifdef HAVE_NETPLAY
|
||||
global->sram.use = global->sram.use &&
|
||||
(!netplay_driver_ctl(RARCH_NETPLAY_CTL_IS_DATA_INITED, NULL)
|
||||
|| !global->netplay.is_client);
|
||||
#endif
|
||||
|
||||
if (!global->sram.use)
|
||||
RARCH_LOG("%s\n",
|
||||
msg_hash_to_str(MSG_SRAM_WILL_NOT_BE_SAVED));
|
||||
|
||||
if (global->sram.use)
|
||||
command_event(CMD_EVENT_AUTOSAVE_INIT, NULL);
|
||||
}
|
||||
break;
|
||||
case CMD_EVENT_BSV_MOVIE_DEINIT:
|
||||
bsv_movie_ctl(BSV_MOVIE_CTL_DEINIT, NULL);
|
||||
break;
|
||||
|
@ -157,11 +157,6 @@ enum event_command
|
||||
CMD_EVENT_SHADER_DIR_DEINIT,
|
||||
/* Initializes controllers. */
|
||||
CMD_EVENT_CONTROLLERS_INIT,
|
||||
CMD_EVENT_SAVEFILES,
|
||||
/* Initializes savefiles. */
|
||||
CMD_EVENT_SAVEFILES_INIT,
|
||||
/* Deinitializes savefiles. */
|
||||
CMD_EVENT_SAVEFILES_DEINIT,
|
||||
/* Initializes cheats. */
|
||||
CMD_EVENT_CHEATS_INIT,
|
||||
/* Deinitializes cheats. */
|
||||
|
@ -650,10 +650,8 @@ static const bool font_enable = true;
|
||||
* disable VSync, and leave this at its default. */
|
||||
#ifdef _3DS
|
||||
static const float refresh_rate = (32730.0 * 8192.0) / 4481134.0 ;
|
||||
#elif defined(RARCH_CONSOLE)
|
||||
static const float refresh_rate = 60/1.001;
|
||||
#else
|
||||
static const float refresh_rate = 59.95;
|
||||
static const float refresh_rate = 60/1.001;
|
||||
#endif
|
||||
|
||||
/* Allow games to set rotation. If false, rotation requests are
|
||||
@ -874,7 +872,7 @@ static char buildbot_assets_server_url[] = "http://buildbot.libretro.com/assets/
|
||||
|
||||
/* User 1 */
|
||||
static const struct retro_keybind retro_keybinds_1[] = {
|
||||
/* | RetroPad button | desc | keyboard key | js btn | js axis | */
|
||||
/* | RetroPad button | desc | keyboard key | js btn | js axis | */
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_B, RETRO_LBL_JOYPAD_B, RETROK_z, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_Y, RETRO_LBL_JOYPAD_Y, RETROK_a, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_LBL_JOYPAD_SELECT, RETROK_RSHIFT, NO_BTN, 0, AXIS_NONE },
|
||||
@ -938,7 +936,7 @@ static const struct retro_keybind retro_keybinds_1[] = {
|
||||
|
||||
/* Users 2 to MAX_USERS */
|
||||
static const struct retro_keybind retro_keybinds_rest[] = {
|
||||
/* | RetroPad button | desc | keyboard key | js btn | js axis | */
|
||||
/* | RetroPad button | desc | keyboard key | js btn | js axis | */
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_B, RETRO_LBL_JOYPAD_B, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_Y, RETRO_LBL_JOYPAD_Y, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
|
||||
{ true, RETRO_DEVICE_ID_JOYPAD_SELECT, RETRO_LBL_JOYPAD_SELECT, RETROK_UNKNOWN, NO_BTN, 0, AXIS_NONE },
|
||||
|
337
configuration.c
337
configuration.c
@ -38,6 +38,8 @@
|
||||
#include "input/input_remapping.h"
|
||||
#include "defaults.h"
|
||||
#include "core.h"
|
||||
#include "dirs.h"
|
||||
#include "paths.h"
|
||||
#include "retroarch.h"
|
||||
#include "runloop.h"
|
||||
#include "verbosity.h"
|
||||
@ -407,38 +409,6 @@ const char *config_get_default_joypad(void)
|
||||
return "null";
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
/**
|
||||
* config_get_default_menu:
|
||||
*
|
||||
* Gets default menu driver.
|
||||
*
|
||||
* Returns: Default menu driver.
|
||||
**/
|
||||
const char *config_get_default_menu(void)
|
||||
{
|
||||
if (!string_is_empty(g_defaults.settings.menu))
|
||||
return g_defaults.settings.menu;
|
||||
|
||||
switch (MENU_DEFAULT_DRIVER)
|
||||
{
|
||||
case MENU_RGUI:
|
||||
return "rgui";
|
||||
case MENU_XUI:
|
||||
return "xui";
|
||||
case MENU_MATERIALUI:
|
||||
return "glui";
|
||||
case MENU_XMB:
|
||||
return "xmb";
|
||||
case MENU_NUKLEAR:
|
||||
return "nuklear";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "null";
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* config_get_default_camera:
|
||||
@ -488,14 +458,38 @@ const char *config_get_default_location(void)
|
||||
return "null";
|
||||
}
|
||||
|
||||
bool config_overlay_enable_default(void)
|
||||
#ifdef HAVE_MENU
|
||||
/**
|
||||
* config_get_default_menu:
|
||||
*
|
||||
* Gets default menu driver.
|
||||
*
|
||||
* Returns: Default menu driver.
|
||||
**/
|
||||
const char *config_get_default_menu(void)
|
||||
{
|
||||
if (g_defaults.overlay.set)
|
||||
return g_defaults.overlay.enable;
|
||||
return true;
|
||||
if (!string_is_empty(g_defaults.settings.menu))
|
||||
return g_defaults.settings.menu;
|
||||
|
||||
switch (MENU_DEFAULT_DRIVER)
|
||||
{
|
||||
case MENU_RGUI:
|
||||
return "rgui";
|
||||
case MENU_XUI:
|
||||
return "xui";
|
||||
case MENU_MATERIALUI:
|
||||
return "glui";
|
||||
case MENU_XMB:
|
||||
return "xmb";
|
||||
case MENU_NUKLEAR:
|
||||
return "nuklear";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
||||
return "null";
|
||||
}
|
||||
|
||||
#ifdef HAVE_MENU
|
||||
static unsigned config_menu_btn_ok_default(void)
|
||||
{
|
||||
if (g_defaults.menu.controls.set)
|
||||
@ -511,6 +505,13 @@ static unsigned config_menu_btn_cancel_default(void)
|
||||
}
|
||||
#endif
|
||||
|
||||
bool config_overlay_enable_default(void)
|
||||
{
|
||||
if (g_defaults.overlay.set)
|
||||
return g_defaults.overlay.enable;
|
||||
return true;
|
||||
}
|
||||
|
||||
static int populate_settings_array(settings_t *settings, struct config_array_setting **out)
|
||||
{
|
||||
unsigned count = 0;
|
||||
@ -636,9 +637,9 @@ static int populate_settings_path(settings_t *settings, struct config_path_setti
|
||||
SETTING_PATH("audio_filter_dir",
|
||||
settings->directory.audio_filter, true, NULL, true);
|
||||
SETTING_PATH("savefile_directory",
|
||||
global->dir.savefile, true, NULL, false);
|
||||
dir_get_savefile_ptr(), true, NULL, false);
|
||||
SETTING_PATH("savestate_directory",
|
||||
global->dir.savestate, true, NULL, false);
|
||||
dir_get_savestate_ptr(), true, NULL, false);
|
||||
#ifdef HAVE_MENU
|
||||
SETTING_PATH("rgui_browser_directory",
|
||||
settings->directory.menu_content, true, NULL, true);
|
||||
@ -651,11 +652,11 @@ static int populate_settings_path(settings_t *settings, struct config_path_setti
|
||||
#endif
|
||||
#ifdef HAVE_OVERLAY
|
||||
SETTING_PATH("osk_overlay_directory",
|
||||
global->dir.osk_overlay, true, NULL, true);
|
||||
dir_get_osk_overlay_ptr(), true, NULL, true);
|
||||
#endif
|
||||
#ifndef HAVE_DYNAMIC
|
||||
SETTING_PATH("libretro_path",
|
||||
config_get_active_core_path_ptr(), false, NULL, false);
|
||||
path_get_core_ptr(), false, NULL, false);
|
||||
#endif
|
||||
SETTING_PATH(
|
||||
"screenshot_directory",
|
||||
@ -911,7 +912,8 @@ static int populate_settings_int(settings_t *settings, struct config_int_setting
|
||||
SETTING_INT("state_slot", (unsigned*)&settings->state_slot, false, 0 /* TODO */, false);
|
||||
#ifdef HAVE_NETPLAY
|
||||
SETTING_INT("netplay_ip_port", &global->netplay.port, false, 0 /* TODO */, false);
|
||||
SETTING_INT("netplay_delay_frames", &global->netplay.sync_frames, false, 0 /* TODO */, false);
|
||||
SETTING_INT("netplay_delay_frames", &global->netplay.sync_frames, false, 16, false);
|
||||
SETTING_INT("netplay_check_frames", &global->netplay.check_frames, false, 0, false);
|
||||
#endif
|
||||
#ifdef HAVE_LANGEXTRA
|
||||
SETTING_INT("user_language", &settings->user_language, true, RETRO_LANGUAGE_ENGLISH, false);
|
||||
@ -1117,9 +1119,9 @@ static void config_set_defaults(void)
|
||||
/* Make sure settings from other configs carry over into defaults
|
||||
* for another config. */
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH))
|
||||
*global->dir.savefile = '\0';
|
||||
dir_clear_savefile();
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH))
|
||||
*global->dir.savestate = '\0';
|
||||
dir_clear_savestate();
|
||||
|
||||
*settings->path.libretro_info = '\0';
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_LIBRETRO_DIRECTORY))
|
||||
@ -1246,20 +1248,30 @@ static void config_set_defaults(void)
|
||||
|
||||
if (!string_is_empty(g_defaults.dir.osk_overlay))
|
||||
{
|
||||
fill_pathname_expand_special(global->dir.osk_overlay,
|
||||
g_defaults.dir.osk_overlay, sizeof(global->dir.osk_overlay));
|
||||
char temp_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
fill_pathname_expand_special(temp_path,
|
||||
g_defaults.dir.osk_overlay, sizeof(temp_path));
|
||||
#ifdef RARCH_MOBILE
|
||||
if (string_is_empty(settings->path.osk_overlay))
|
||||
fill_pathname_join(settings->path.osk_overlay,
|
||||
global->dir.osk_overlay,
|
||||
temp_path,
|
||||
"keyboards/modular-keyboard/opaque/big.cfg",
|
||||
sizeof(settings->path.osk_overlay));
|
||||
#endif
|
||||
|
||||
dir_set_osk_overlay(temp_path);
|
||||
}
|
||||
else
|
||||
strlcpy(global->dir.osk_overlay,
|
||||
{
|
||||
char temp_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
strlcpy(temp_path,
|
||||
settings->directory.overlay,
|
||||
sizeof(global->dir.osk_overlay));
|
||||
sizeof(temp_path));
|
||||
|
||||
dir_set_osk_overlay(temp_path);
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_MENU
|
||||
if (!string_is_empty(g_defaults.dir.menu_config))
|
||||
@ -1278,12 +1290,12 @@ static void config_set_defaults(void)
|
||||
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH) &&
|
||||
!string_is_empty(g_defaults.dir.savestate))
|
||||
strlcpy(global->dir.savestate,
|
||||
g_defaults.dir.savestate, sizeof(global->dir.savestate));
|
||||
dir_set_savestate(g_defaults.dir.savestate);
|
||||
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH) &&
|
||||
!string_is_empty(g_defaults.dir.sram))
|
||||
strlcpy(global->dir.savefile,
|
||||
g_defaults.dir.sram, sizeof(global->dir.savefile));
|
||||
dir_set_savefile(g_defaults.dir.sram);
|
||||
|
||||
if (!string_is_empty(g_defaults.dir.system))
|
||||
strlcpy(settings->directory.system,
|
||||
g_defaults.dir.system, sizeof(settings->directory.system));
|
||||
@ -1301,8 +1313,12 @@ static void config_set_defaults(void)
|
||||
sizeof(settings->directory.content_history));
|
||||
|
||||
if (!string_is_empty(g_defaults.path.config))
|
||||
fill_pathname_expand_special(global->path.config,
|
||||
g_defaults.path.config, sizeof(global->path.config));
|
||||
{
|
||||
char temp_str[PATH_MAX_LENGTH];
|
||||
fill_pathname_expand_special(temp_str,
|
||||
g_defaults.path.config, sizeof(temp_str));
|
||||
path_set_config(temp_str);
|
||||
}
|
||||
|
||||
/* Avoid reloading config on every content load */
|
||||
if (default_block_config_read)
|
||||
@ -1335,7 +1351,6 @@ static config_file_t *open_default_config_file(void)
|
||||
char conf_path[PATH_MAX_LENGTH] = {0};
|
||||
char app_path[PATH_MAX_LENGTH] = {0};
|
||||
config_file_t *conf = NULL;
|
||||
global_t *global = NULL;
|
||||
|
||||
#if defined(_WIN32) && !defined(_XBOX)
|
||||
fill_pathname_application_path(app_path, sizeof(app_path));
|
||||
@ -1500,10 +1515,8 @@ static config_file_t *open_default_config_file(void)
|
||||
if (!conf)
|
||||
return NULL;
|
||||
|
||||
global = global_get_ptr();
|
||||
path_set_config(conf_path);
|
||||
|
||||
if (global)
|
||||
strlcpy(global->path.config, conf_path, sizeof(global->path.config));
|
||||
return conf;
|
||||
}
|
||||
|
||||
@ -1640,9 +1653,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
unsigned i;
|
||||
bool tmp_bool = false;
|
||||
char *save = NULL;
|
||||
const char *extra_path = NULL;
|
||||
char tmp_str[PATH_MAX_LENGTH] = {0};
|
||||
char tmp_append_path[PATH_MAX_LENGTH] = {0}; /* Don't destroy append_config_path. */
|
||||
unsigned msg_color = 0;
|
||||
config_file_t *conf = NULL;
|
||||
struct config_int_setting *int_settings = NULL;
|
||||
@ -1676,20 +1687,29 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
if (set_defaults)
|
||||
config_set_defaults();
|
||||
|
||||
strlcpy(tmp_append_path, global->path.append_config,
|
||||
sizeof(tmp_append_path));
|
||||
extra_path = strtok_r(tmp_append_path, "|", &save);
|
||||
|
||||
while (extra_path)
|
||||
if (!path_is_config_append_empty())
|
||||
{
|
||||
bool ret = config_append_file(conf, extra_path);
|
||||
/* Don't destroy append_config_path, store in temporary
|
||||
* variable. */
|
||||
char tmp_append_path[PATH_MAX_LENGTH] = {0};
|
||||
const char *extra_path = NULL;
|
||||
|
||||
RARCH_LOG("Config: appending config \"%s\"\n", extra_path);
|
||||
strlcpy(tmp_append_path, path_get_config_append(),
|
||||
sizeof(tmp_append_path));
|
||||
extra_path = strtok_r(tmp_append_path, "|", &save);
|
||||
|
||||
if (!ret)
|
||||
RARCH_ERR("Config: failed to append config \"%s\"\n", extra_path);
|
||||
extra_path = strtok_r(NULL, "|", &save);
|
||||
while (extra_path)
|
||||
{
|
||||
bool ret = config_append_file(conf, extra_path);
|
||||
|
||||
RARCH_LOG("Config: appending config \"%s\"\n", extra_path);
|
||||
|
||||
if (!ret)
|
||||
RARCH_ERR("Config: failed to append config \"%s\"\n", extra_path);
|
||||
extra_path = strtok_r(NULL, "|", &save);
|
||||
}
|
||||
}
|
||||
|
||||
#if 0
|
||||
if (verbosity_is_enabled())
|
||||
{
|
||||
@ -1717,6 +1737,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
if (config_get_bool(conf, bool_settings[i].ident, &tmp))
|
||||
*bool_settings[i].ptr = tmp;
|
||||
}
|
||||
|
||||
if (!rarch_ctl(RARCH_CTL_IS_FORCE_FULLSCREEN, NULL))
|
||||
CONFIG_GET_BOOL_BASE(conf, settings, video.fullscreen, "video_fullscreen");
|
||||
|
||||
@ -1788,6 +1809,8 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_NETPLAY_DELAY_FRAMES))
|
||||
CONFIG_GET_INT_BASE(conf, global, netplay.sync_frames, "netplay_delay_frames");
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_NETPLAY_CHECK_FRAMES))
|
||||
CONFIG_GET_INT_BASE(conf, global, netplay.sync_frames, "netplay_check_frames");
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_NETPLAY_IP_PORT))
|
||||
CONFIG_GET_INT_BASE(conf, global, netplay.port, "netplay_ip_port");
|
||||
#endif
|
||||
@ -1865,7 +1888,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
|
||||
#ifndef HAVE_DYNAMIC
|
||||
if (config_get_path(conf, "libretro_path", tmp_str, sizeof(tmp_str)))
|
||||
config_set_active_core_path(tmp_str);
|
||||
path_set_core(tmp_str);
|
||||
#endif
|
||||
|
||||
#ifdef RARCH_CONSOLE
|
||||
@ -1905,7 +1928,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
{
|
||||
fill_pathname_resolve_relative(
|
||||
settings->path.content_history,
|
||||
global->path.config,
|
||||
path_get_config(),
|
||||
file_path_str(FILE_PATH_CONTENT_HISTORY),
|
||||
sizeof(settings->path.content_history));
|
||||
}
|
||||
@ -1924,7 +1947,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
{
|
||||
fill_pathname_resolve_relative(
|
||||
settings->path.content_music_history,
|
||||
global->path.config,
|
||||
path_get_config(),
|
||||
file_path_str(FILE_PATH_CONTENT_MUSIC_HISTORY),
|
||||
sizeof(settings->path.content_music_history));
|
||||
}
|
||||
@ -1943,7 +1966,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
{
|
||||
fill_pathname_resolve_relative(
|
||||
settings->path.content_video_history,
|
||||
global->path.config,
|
||||
path_get_config(),
|
||||
file_path_str(FILE_PATH_CONTENT_VIDEO_HISTORY),
|
||||
sizeof(settings->path.content_video_history));
|
||||
}
|
||||
@ -1962,7 +1985,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
{
|
||||
fill_pathname_resolve_relative(
|
||||
settings->path.content_image_history,
|
||||
global->path.config,
|
||||
path_get_config(),
|
||||
file_path_str(FILE_PATH_CONTENT_IMAGE_HISTORY),
|
||||
sizeof(settings->path.content_image_history));
|
||||
}
|
||||
@ -1988,12 +2011,12 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
}
|
||||
|
||||
/* Safe-guard against older behavior. */
|
||||
if (path_is_directory(config_get_active_core_path()))
|
||||
if (path_is_directory(path_get_core()))
|
||||
{
|
||||
RARCH_WARN("\"libretro_path\" is a directory, using this for \"libretro_directory\" instead.\n");
|
||||
strlcpy(settings->directory.libretro, config_get_active_core_path(),
|
||||
strlcpy(settings->directory.libretro, path_get_core(),
|
||||
sizeof(settings->directory.libretro));
|
||||
config_clear_active_core_path();
|
||||
path_clear_core();
|
||||
}
|
||||
|
||||
if (string_is_equal(settings->path.menu_wallpaper, "default"))
|
||||
@ -2024,8 +2047,8 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
#ifdef HAVE_OVERLAY
|
||||
if (string_is_equal(settings->directory.overlay, "default"))
|
||||
*settings->directory.overlay = '\0';
|
||||
if (string_is_equal(global->dir.osk_overlay, "default"))
|
||||
*global->dir.osk_overlay = '\0';
|
||||
if (string_is_equal(dir_get_osk_overlay(), "default"))
|
||||
dir_clear_osk_overlay();
|
||||
#endif
|
||||
if (string_is_equal(settings->directory.system, "default"))
|
||||
*settings->directory.system = '\0';
|
||||
@ -2048,16 +2071,16 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
config_get_path(conf, "savefile_directory", tmp_str, sizeof(tmp_str)))
|
||||
{
|
||||
if (string_is_equal(tmp_str, "default"))
|
||||
strlcpy(global->dir.savefile, g_defaults.dir.sram,
|
||||
sizeof(global->dir.savefile));
|
||||
dir_set_savefile(g_defaults.dir.sram);
|
||||
|
||||
else if (path_is_directory(tmp_str))
|
||||
{
|
||||
strlcpy(global->dir.savefile, tmp_str,
|
||||
sizeof(global->dir.savefile));
|
||||
dir_set_savefile(tmp_str);
|
||||
|
||||
strlcpy(global->name.savefile, tmp_str,
|
||||
sizeof(global->name.savefile));
|
||||
fill_pathname_dir(global->name.savefile,
|
||||
global->name.base,
|
||||
path_get_basename(),
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION),
|
||||
sizeof(global->name.savefile));
|
||||
}
|
||||
@ -2069,16 +2092,15 @@ static bool config_load_file(const char *path, bool set_defaults,
|
||||
config_get_path(conf, "savestate_directory", tmp_str, sizeof(tmp_str)))
|
||||
{
|
||||
if (string_is_equal(tmp_str, "default"))
|
||||
strlcpy(global->dir.savestate, g_defaults.dir.savestate,
|
||||
sizeof(global->dir.savestate));
|
||||
dir_set_savestate(g_defaults.dir.savestate);
|
||||
else if (path_is_directory(tmp_str))
|
||||
{
|
||||
strlcpy(global->dir.savestate, tmp_str,
|
||||
sizeof(global->dir.savestate));
|
||||
dir_set_savestate(tmp_str);
|
||||
|
||||
strlcpy(global->name.savestate, tmp_str,
|
||||
sizeof(global->name.savestate));
|
||||
fill_pathname_dir(global->name.savestate,
|
||||
global->name.base,
|
||||
path_get_basename(),
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
sizeof(global->name.savestate));
|
||||
}
|
||||
@ -2133,14 +2155,15 @@ bool config_load_override(void)
|
||||
const char *game_name = NULL;
|
||||
bool should_append = false;
|
||||
rarch_system_info_t *system = NULL;
|
||||
#ifdef HAVE_NETPLAY
|
||||
global_t *global = global_get_ptr();
|
||||
#endif
|
||||
|
||||
runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);
|
||||
|
||||
if (system)
|
||||
core_name = system->info.library_name;
|
||||
if (global)
|
||||
game_name = path_basename(global->name.base);
|
||||
game_name = path_basename(path_get_basename());
|
||||
|
||||
if (string_is_empty(core_name) || string_is_empty(game_name))
|
||||
return false;
|
||||
@ -2167,10 +2190,10 @@ bool config_load_override(void)
|
||||
/* If a core override exists, add its location to append_config_path */
|
||||
if (new_conf)
|
||||
{
|
||||
config_file_free(new_conf);
|
||||
|
||||
RARCH_LOG("[overrides] core-specific overrides found at %s.\n", core_path);
|
||||
strlcpy(global->path.append_config, core_path, sizeof(global->path.append_config));
|
||||
|
||||
config_file_free(new_conf);
|
||||
path_set_config_append(core_path);
|
||||
|
||||
should_append = true;
|
||||
}
|
||||
@ -2183,16 +2206,22 @@ bool config_load_override(void)
|
||||
/* If a game override exists, add it's location to append_config_path */
|
||||
if (new_conf)
|
||||
{
|
||||
char temp_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
config_file_free(new_conf);
|
||||
|
||||
RARCH_LOG("[overrides] game-specific overrides found at %s.\n", game_path);
|
||||
|
||||
if (should_append)
|
||||
{
|
||||
strlcat(global->path.append_config, "|", sizeof(global->path.append_config));
|
||||
strlcat(global->path.append_config, game_path, sizeof(global->path.append_config));
|
||||
strlcpy(temp_path, path_get_config_append(), sizeof(temp_path));
|
||||
strlcat(temp_path, "|", sizeof(temp_path));
|
||||
strlcat(temp_path, game_path, sizeof(temp_path));
|
||||
}
|
||||
else
|
||||
strlcpy(global->path.append_config, game_path, sizeof(global->path.append_config));
|
||||
strlcpy(temp_path, game_path, sizeof(temp_path));
|
||||
|
||||
path_set_config_append(temp_path);
|
||||
|
||||
should_append = true;
|
||||
}
|
||||
@ -2204,7 +2233,7 @@ bool config_load_override(void)
|
||||
|
||||
/* Re-load the configuration with any overrides that might have been found */
|
||||
#ifdef HAVE_NETPLAY
|
||||
if (global->netplay.enable)
|
||||
if (global && global->netplay.enable)
|
||||
{
|
||||
RARCH_WARN("[overrides] can't use overrides in conjunction with netplay, disabling overrides.\n");
|
||||
return false;
|
||||
@ -2213,24 +2242,26 @@ bool config_load_override(void)
|
||||
|
||||
/* Store the libretro_path we're using since it will be
|
||||
* overwritten by the override when reloading. */
|
||||
strlcpy(buf, config_get_active_core_path(), sizeof(buf));
|
||||
strlcpy(buf, path_get_core(), sizeof(buf));
|
||||
|
||||
/* Toggle has_save_path to false so it resets */
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH);
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH);
|
||||
|
||||
if (!config_load_file(global->path.config, false, config_get_ptr()))
|
||||
if (!config_load_file(path_get_config(), false, config_get_ptr()))
|
||||
return false;
|
||||
|
||||
/* Restore the libretro_path we're using
|
||||
* since it will be overwritten by the override when reloading. */
|
||||
config_set_active_core_path(buf);
|
||||
path_set_core(buf);
|
||||
runloop_msg_queue_push("Configuration override loaded.", 1, 100, true);
|
||||
|
||||
/* Reset save paths. */
|
||||
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_STATE_PATH);
|
||||
retroarch_override_setting_set(RARCH_OVERRIDE_SETTING_SAVE_PATH);
|
||||
global->path.append_config[0] = '\0';
|
||||
|
||||
path_clear_config_append();
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -2244,18 +2275,13 @@ bool config_load_override(void)
|
||||
*/
|
||||
bool config_unload_override(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return false;
|
||||
|
||||
*global->path.append_config = '\0';
|
||||
path_clear_config_append();
|
||||
|
||||
/* Toggle has_save_path to false so it resets */
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_STATE_PATH);
|
||||
retroarch_override_setting_unset(RARCH_OVERRIDE_SETTING_SAVE_PATH);
|
||||
|
||||
if (config_load_file(global->path.config, false, config_get_ptr()))
|
||||
if (config_load_file(path_get_config(), false, config_get_ptr()))
|
||||
{
|
||||
RARCH_LOG("[overrides] configuration overrides unloaded, original configuration restored.\n");
|
||||
|
||||
@ -2290,7 +2316,6 @@ bool config_load_remap(void)
|
||||
config_file_t *new_conf = NULL;
|
||||
const char *core_name = NULL;
|
||||
const char *game_name = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
rarch_system_info_t *system = NULL;
|
||||
|
||||
@ -2298,8 +2323,8 @@ bool config_load_remap(void)
|
||||
|
||||
if (system)
|
||||
core_name = system->info.library_name;
|
||||
if (global)
|
||||
game_name = path_basename(global->name.base);
|
||||
|
||||
game_name = path_basename(path_get_basename());
|
||||
|
||||
if (string_is_empty(core_name) || string_is_empty(game_name))
|
||||
return false;
|
||||
@ -2408,12 +2433,11 @@ static bool check_shader_compatibility(enum file_path_enum enum_idx)
|
||||
bool config_load_shader_preset(void)
|
||||
{
|
||||
unsigned idx;
|
||||
char shader_directory[PATH_MAX_LENGTH] = {0}; /* path to the directory containing retroarch.cfg (prefix) */
|
||||
char shader_directory[PATH_MAX_LENGTH] = {0}; /* path to the directory containing retroarch.cfg (prefix) */
|
||||
char core_path[PATH_MAX_LENGTH] = {0}; /* final path for core-specific configuration (prefix+suffix) */
|
||||
char game_path[PATH_MAX_LENGTH] = {0}; /* final path for game-specific configuration (prefix+suffix) */
|
||||
const char *core_name = NULL;
|
||||
const char *game_name = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
settings_t *settings = config_get_ptr();
|
||||
rarch_system_info_t *system = NULL;
|
||||
|
||||
@ -2421,8 +2445,8 @@ bool config_load_shader_preset(void)
|
||||
|
||||
if (system)
|
||||
core_name = system->info.library_name;
|
||||
if (global)
|
||||
game_name = path_basename(global->name.base);
|
||||
|
||||
game_name = path_basename(path_get_basename());
|
||||
|
||||
if (string_is_empty(core_name) || string_is_empty(game_name))
|
||||
return false;
|
||||
@ -2507,26 +2531,23 @@ bool config_load_shader_preset(void)
|
||||
|
||||
static void parse_config_file(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
bool ret = config_load_file((*global->path.config)
|
||||
? global->path.config : NULL, false, config_get_ptr());
|
||||
bool ret = config_load_file(path_get_config(), false, config_get_ptr());
|
||||
|
||||
if (!string_is_empty(global->path.config))
|
||||
if (!path_is_config_empty())
|
||||
{
|
||||
RARCH_LOG("Config: loading config from: %s.\n", global->path.config);
|
||||
RARCH_LOG("Config: loading config from: %s.\n", path_get_config());
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_LOG("Loading default config.\n");
|
||||
if (!string_is_empty(global->path.config))
|
||||
RARCH_LOG("Config: found default config: %s.\n", global->path.config);
|
||||
if (!path_is_config_empty())
|
||||
RARCH_LOG("Config: found default config: %s.\n", path_get_config());
|
||||
}
|
||||
|
||||
if (ret)
|
||||
return;
|
||||
|
||||
RARCH_ERR("Config: couldn't find config at path: \"%s\"\n",
|
||||
global->path.config);
|
||||
RARCH_ERR("Config: couldn't find config at path: \"%s\"\n", path_get_config());
|
||||
}
|
||||
|
||||
|
||||
@ -3007,7 +3028,6 @@ bool config_save_overrides(int override_type)
|
||||
const char *game_name = NULL;
|
||||
config_file_t *conf = NULL;
|
||||
settings_t *settings = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
settings_t *overrides = config_get_ptr();
|
||||
rarch_system_info_t *system = NULL;
|
||||
struct config_bool_setting *bool_settings = NULL;
|
||||
@ -3025,8 +3045,8 @@ bool config_save_overrides(int override_type)
|
||||
|
||||
if (system)
|
||||
core_name = system->info.library_name;
|
||||
if (global)
|
||||
game_name = path_basename(global->name.base);
|
||||
|
||||
game_name = path_basename(path_get_basename());
|
||||
|
||||
if (string_is_empty(core_name) || string_is_empty(game_name))
|
||||
return false;
|
||||
@ -3059,7 +3079,7 @@ bool config_save_overrides(int override_type)
|
||||
conf = config_file_new(NULL);
|
||||
|
||||
/* Load the original config file in memory */
|
||||
config_load_file(global->path.config, false, settings);
|
||||
config_load_file(path_get_config(), false, settings);
|
||||
|
||||
bool_settings_size = populate_settings_bool(settings, &bool_settings);
|
||||
populate_settings_bool (overrides, &bool_overrides);
|
||||
@ -3184,25 +3204,24 @@ bool config_replace(char *path)
|
||||
{
|
||||
content_ctx_info_t content_info = {0};
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!path || !global)
|
||||
if (!path)
|
||||
return false;
|
||||
|
||||
/* If config file to be replaced is the same as the
|
||||
* current config file, exit. */
|
||||
if (string_is_equal(path, global->path.config))
|
||||
if (string_is_equal(path, path_get_config()))
|
||||
return false;
|
||||
|
||||
if (settings->config_save_on_exit && !string_is_empty(global->path.config))
|
||||
config_save_file(global->path.config);
|
||||
if (settings->config_save_on_exit && !path_is_config_empty())
|
||||
config_save_file(path_get_config());
|
||||
|
||||
strlcpy(global->path.config, path, sizeof(global->path.config));
|
||||
path_set_config(path);
|
||||
|
||||
rarch_ctl(RARCH_CTL_UNSET_BLOCK_CONFIG_READ, NULL);
|
||||
|
||||
/* Load core in new config. */
|
||||
config_clear_active_core_path();
|
||||
path_clear_core();
|
||||
|
||||
if (!task_push_content_load_default(
|
||||
NULL, NULL,
|
||||
@ -3215,48 +3234,6 @@ bool config_replace(char *path)
|
||||
return true;
|
||||
}
|
||||
|
||||
static char path_libretro[PATH_MAX_LENGTH];
|
||||
|
||||
char *config_get_active_core_path_ptr(void)
|
||||
{
|
||||
return path_libretro;
|
||||
}
|
||||
|
||||
const char *config_get_active_core_path(void)
|
||||
{
|
||||
return path_libretro;
|
||||
}
|
||||
|
||||
bool config_active_core_path_is_empty(void)
|
||||
{
|
||||
return !path_libretro[0];
|
||||
}
|
||||
|
||||
size_t config_get_active_core_path_size(void)
|
||||
{
|
||||
return sizeof(path_libretro);
|
||||
}
|
||||
|
||||
void config_set_active_core_path(const char *path)
|
||||
{
|
||||
strlcpy(path_libretro, path, sizeof(path_libretro));
|
||||
}
|
||||
|
||||
void config_clear_active_core_path(void)
|
||||
{
|
||||
*path_libretro = '\0';
|
||||
}
|
||||
|
||||
const char *config_get_active_path(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!string_is_empty(global->path.config))
|
||||
return global->path.config;
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
void config_free_state(void)
|
||||
{
|
||||
}
|
||||
|
@ -631,20 +631,6 @@ bool config_overlay_enable_default(void);
|
||||
|
||||
void config_free(void);
|
||||
|
||||
const char *config_get_active_path(void);
|
||||
|
||||
const char *config_get_active_core_path(void);
|
||||
|
||||
char *config_get_active_core_path_ptr(void);
|
||||
|
||||
void config_set_active_core_path(const char *path);
|
||||
|
||||
void config_clear_active_core_path(void);
|
||||
|
||||
bool config_active_core_path_is_empty(void);
|
||||
|
||||
size_t config_get_active_core_path_size(void);
|
||||
|
||||
void config_free_state(void);
|
||||
|
||||
settings_t *config_get_ptr(void);
|
||||
|
21
core_impl.c
21
core_impl.c
@ -87,9 +87,6 @@ void core_set_input_state(retro_ctx_input_state_info_t *info)
|
||||
static bool core_init_libretro_cbs(void *data)
|
||||
{
|
||||
struct retro_callbacks *cbs = (struct retro_callbacks*)data;
|
||||
#ifdef HAVE_NETPLAY
|
||||
global_t *global = global_get_ptr();
|
||||
#endif
|
||||
|
||||
if (!cbs)
|
||||
return false;
|
||||
@ -109,20 +106,10 @@ static bool core_init_libretro_cbs(void *data)
|
||||
/* Force normal poll type for netplay. */
|
||||
core_poll_type = POLL_TYPE_NORMAL;
|
||||
|
||||
if (global->netplay.is_spectate)
|
||||
{
|
||||
core.retro_set_input_state(
|
||||
(global->netplay.is_client ?
|
||||
input_state_spectate_client : input_state_spectate)
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
core.retro_set_video_refresh(video_frame_net);
|
||||
core.retro_set_audio_sample(audio_sample_net);
|
||||
core.retro_set_audio_sample_batch(audio_sample_batch_net);
|
||||
core.retro_set_input_state(input_state_net);
|
||||
}
|
||||
core.retro_set_video_refresh(video_frame_net);
|
||||
core.retro_set_audio_sample(audio_sample_net);
|
||||
core.retro_set_audio_sample_batch(audio_sample_batch_net);
|
||||
core.retro_set_input_state(input_state_net);
|
||||
#endif
|
||||
|
||||
return true;
|
||||
|
@ -572,10 +572,9 @@ core_info_t *core_info_get(core_info_list_t *list, size_t i)
|
||||
void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
|
||||
const char *path, const core_info_t **infos, size_t *num_infos)
|
||||
{
|
||||
#ifdef HAVE_ZLIB
|
||||
size_t i;
|
||||
struct string_list *list = NULL;
|
||||
#endif
|
||||
size_t supported = 0, i;
|
||||
size_t supported = 0;
|
||||
|
||||
if (!core_info_list)
|
||||
return;
|
||||
@ -608,10 +607,8 @@ void core_info_list_get_supported_cores(core_info_list_t *core_info_list,
|
||||
break;
|
||||
}
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
if (list)
|
||||
string_list_free(list);
|
||||
#endif
|
||||
|
||||
*infos = core_info_list->list;
|
||||
*num_infos = supported;
|
||||
|
@ -272,10 +272,10 @@ void CORE_PREFIX(retro_set_environment)(retro_environment_t cb)
|
||||
static const struct retro_variable vars[] = {
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES)
|
||||
{ "ffmpeg_temporal_interp", "Temporal Interpolation; enabled|disabled" },
|
||||
#endif
|
||||
#ifdef HAVE_GL_FFT
|
||||
{ "ffmpeg_fft_resolution", "GLFFT Resolution; 1280x720|1920x1080|640x360|320x180" },
|
||||
{ "ffmpeg_fft_multisample", "GLFFT Multisample; 1x|2x|4x" },
|
||||
#endif
|
||||
#endif
|
||||
{ "ffmpeg_color_space", "Colorspace; auto|BT.709|BT.601|FCC|SMPTE240M" },
|
||||
{ NULL, NULL },
|
||||
@ -343,7 +343,6 @@ static void check_variables(void)
|
||||
else if (!strcmp(var.value, "disabled"))
|
||||
temporal_interpolation = false;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_GL_FFT
|
||||
fft_var.key = "ffmpeg_fft_resolution";
|
||||
@ -365,6 +364,7 @@ static void check_variables(void)
|
||||
|
||||
if (CORE_PREFIX(environ_cb)(RETRO_ENVIRONMENT_GET_VARIABLE, &fft_ms_var) && fft_ms_var.value)
|
||||
fft_multisample = strtoul(fft_ms_var.value, NULL, 0);
|
||||
#endif
|
||||
#endif
|
||||
|
||||
color_var.key = "ffmpeg_color_space";
|
||||
@ -436,9 +436,9 @@ void CORE_PREFIX(retro_run)(void)
|
||||
double min_pts;
|
||||
int16_t audio_buffer[2048];
|
||||
bool left, right, up, down, l, r;
|
||||
size_t to_read_frames = 0;
|
||||
int seek_frames = 0;
|
||||
bool updated = false;
|
||||
size_t to_read_frames = 0;
|
||||
int seek_frames = 0;
|
||||
bool updated = false;
|
||||
#ifdef HAVE_GL_FFT
|
||||
unsigned old_fft_width = fft_width;
|
||||
unsigned old_fft_height = fft_height;
|
||||
@ -1172,12 +1172,10 @@ static void decode_thread(void *data)
|
||||
(void)data;
|
||||
|
||||
if (video_stream >= 0)
|
||||
{
|
||||
sws = sws_getCachedContext(NULL,
|
||||
media.width, media.height, vctx->pix_fmt,
|
||||
media.width, media.height, PIX_FMT_RGB32,
|
||||
SWS_POINT, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
for (i = 0; (int)i < audio_streams_num; i++)
|
||||
{
|
||||
|
@ -153,12 +153,6 @@ static GLuint fft_compile_program(glfft_t *fft,
|
||||
|
||||
static void fft_render(glfft_t *fft, GLuint backbuffer, unsigned width, unsigned height)
|
||||
{
|
||||
/* Render scene. */
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fft->ms_fbo ? fft->ms_fbo : backbuffer);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.1f, 0.15f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
vec3 eye = vec3(0, 80, -60);
|
||||
vec3 center = eye + vec3(0.0f, 0.0f, 1.0f);
|
||||
vec3 up = vec3(0.0f, 1.0f, 0.0f);
|
||||
@ -166,6 +160,12 @@ static void fft_render(glfft_t *fft, GLuint backbuffer, unsigned width, unsigned
|
||||
mat4 mvp_lookat = lookAt(eye, center, up);
|
||||
mat4 mvp = mvp_persp * mvp_lookat;
|
||||
|
||||
/* Render scene. */
|
||||
glBindFramebuffer(GL_FRAMEBUFFER, fft->ms_fbo ? fft->ms_fbo : backbuffer);
|
||||
glViewport(0, 0, width, height);
|
||||
glClearColor(0.1f, 0.15f, 0.1f, 1.0f);
|
||||
glClear(GL_COLOR_BUFFER_BIT | GL_DEPTH_BUFFER_BIT | GL_STENCIL_BUFFER_BIT);
|
||||
|
||||
glUseProgram(fft->block.prog);
|
||||
glUniformMatrix4fv(glGetUniformLocation(fft->block.prog, "uMVP"),
|
||||
1, GL_FALSE, value_ptr(mvp));
|
||||
@ -524,12 +524,12 @@ static void fft_init(glfft_t *fft)
|
||||
static void fft_init_block(glfft_t *fft)
|
||||
{
|
||||
unsigned x, y;
|
||||
GLuint *bp;
|
||||
GLushort *block_vertices;
|
||||
GLuint *block_indices;
|
||||
unsigned block_vertices_size;
|
||||
unsigned block_indices_size;
|
||||
int pos = 0;
|
||||
int pos = 0;
|
||||
GLuint *bp = NULL;
|
||||
GLushort *block_vertices = NULL;
|
||||
GLuint *block_indices = NULL;
|
||||
|
||||
fft->block.prog = fft_compile_program(fft,
|
||||
fft_vertex_program_heightmap, fft_fragment_program_heightmap);
|
||||
@ -605,13 +605,13 @@ static bool fft_context_reset(glfft_t *fft, unsigned fft_steps,
|
||||
fft->block_size = fft->size / 4 + 1;
|
||||
|
||||
fft->passes_size = fft_steps;
|
||||
fft->passes = (Pass*)calloc(fft->passes_size, sizeof(Pass));
|
||||
fft->passes = (Pass*)calloc(fft->passes_size, sizeof(Pass));
|
||||
|
||||
if (!fft->passes)
|
||||
return false;
|
||||
|
||||
fft->sliding_size = 2 * fft->size;
|
||||
fft->sliding = (GLshort*)calloc(fft->sliding_size, sizeof(GLshort));
|
||||
fft->sliding = (GLshort*)calloc(fft->sliding_size, sizeof(GLshort));
|
||||
|
||||
if (!fft->sliding)
|
||||
return false;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2013-2015 - Jason Fetters
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -24,10 +24,6 @@
|
||||
#include <file/archive_file.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "libretro-db/libretrodb.h"
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
@ -46,7 +42,7 @@ enum database_type
|
||||
{
|
||||
DATABASE_TYPE_NONE = 0,
|
||||
DATABASE_TYPE_ITERATE,
|
||||
DATABASE_TYPE_ITERATE_ZIP,
|
||||
DATABASE_TYPE_ITERATE_ARCHIVE,
|
||||
DATABASE_TYPE_ITERATE_LUTRO,
|
||||
DATABASE_TYPE_SERIAL_LOOKUP,
|
||||
DATABASE_TYPE_CRC_LOOKUP
|
||||
@ -58,9 +54,7 @@ typedef struct
|
||||
enum database_type type;
|
||||
size_t list_ptr;
|
||||
struct string_list *list;
|
||||
#ifdef HAVE_ZLIB
|
||||
file_archive_transfer_t state;
|
||||
#endif
|
||||
} database_info_handle_t;
|
||||
|
||||
typedef struct
|
||||
|
245
dirs.c
Normal file
245
dirs.c
Normal file
@ -0,0 +1,245 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <compat/strl.h>
|
||||
#include <file/file_path.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <retro_assert.h>
|
||||
#include <retro_stat.h>
|
||||
|
||||
#include "dirs.h"
|
||||
#include "defaults.h"
|
||||
|
||||
static char dir_osk_overlay[PATH_MAX_LENGTH] = {0};
|
||||
static char dir_system[PATH_MAX_LENGTH] = {0};
|
||||
static char dir_savefile[PATH_MAX_LENGTH] = {0};
|
||||
static char dir_savestate[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
/* empty functions */
|
||||
|
||||
bool dir_is_system_empty(void)
|
||||
{
|
||||
return string_is_empty(dir_savefile);
|
||||
}
|
||||
|
||||
bool dir_is_savefile_empty(void)
|
||||
{
|
||||
return string_is_empty(dir_savefile);
|
||||
}
|
||||
|
||||
bool dir_is_savestate_empty(void)
|
||||
{
|
||||
return string_is_empty(dir_savestate);
|
||||
}
|
||||
|
||||
bool dir_is_osk_overlay_empty(void)
|
||||
{
|
||||
return string_is_empty(dir_osk_overlay);
|
||||
}
|
||||
|
||||
/* get size functions */
|
||||
|
||||
size_t dir_get_system_size(void)
|
||||
{
|
||||
return sizeof(dir_system);
|
||||
}
|
||||
|
||||
size_t dir_get_savestate_size(void)
|
||||
{
|
||||
return sizeof(dir_savestate);
|
||||
}
|
||||
|
||||
size_t dir_get_savefile_size(void)
|
||||
{
|
||||
return sizeof(dir_savefile);
|
||||
}
|
||||
|
||||
size_t dir_get_osk_overlay_size(void)
|
||||
{
|
||||
return sizeof(dir_osk_overlay);
|
||||
}
|
||||
|
||||
/* clear functions */
|
||||
|
||||
void dir_clear_system(void)
|
||||
{
|
||||
*dir_system = '\0';
|
||||
}
|
||||
|
||||
void dir_clear_savefile(void)
|
||||
{
|
||||
*dir_savefile = '\0';
|
||||
}
|
||||
|
||||
void dir_clear_savestate(void)
|
||||
{
|
||||
*dir_savestate = '\0';
|
||||
}
|
||||
|
||||
void dir_clear_osk_overlay(void)
|
||||
{
|
||||
*dir_osk_overlay = '\0';
|
||||
}
|
||||
|
||||
void dir_clear_all(void)
|
||||
{
|
||||
dir_clear_system();
|
||||
dir_clear_osk_overlay();
|
||||
dir_clear_savefile();
|
||||
dir_clear_savestate();
|
||||
}
|
||||
|
||||
/* get ptr functions */
|
||||
|
||||
char *dir_get_osk_overlay_ptr(void)
|
||||
{
|
||||
return dir_osk_overlay;
|
||||
}
|
||||
|
||||
char *dir_get_savefile_ptr(void)
|
||||
{
|
||||
return dir_savefile;
|
||||
}
|
||||
|
||||
char *dir_get_system_ptr(void)
|
||||
{
|
||||
return dir_system;
|
||||
}
|
||||
|
||||
char *dir_get_savestate_ptr(void)
|
||||
{
|
||||
return dir_savestate;
|
||||
}
|
||||
|
||||
/* get functions */
|
||||
|
||||
const char *dir_get_osk_overlay(void)
|
||||
{
|
||||
return dir_osk_overlay;
|
||||
}
|
||||
|
||||
const char *dir_get_system(void)
|
||||
{
|
||||
return dir_system;
|
||||
}
|
||||
|
||||
const char *dir_get_savefile(void)
|
||||
{
|
||||
return dir_savefile;
|
||||
}
|
||||
|
||||
const char *dir_get_savestate(void)
|
||||
{
|
||||
return dir_savestate;
|
||||
}
|
||||
|
||||
/* set functions */
|
||||
|
||||
void dir_set_osk_overlay(const char *path)
|
||||
{
|
||||
strlcpy(dir_osk_overlay, path,
|
||||
sizeof(dir_osk_overlay));
|
||||
}
|
||||
|
||||
void dir_set_system(const char *path)
|
||||
{
|
||||
strlcpy(dir_system, path,
|
||||
sizeof(dir_system));
|
||||
}
|
||||
|
||||
void dir_set_savestate(const char *path)
|
||||
{
|
||||
strlcpy(dir_savestate, path,
|
||||
sizeof(dir_savestate));
|
||||
}
|
||||
|
||||
void dir_set_savefile(const char *path)
|
||||
{
|
||||
strlcpy(dir_savefile, path,
|
||||
sizeof(dir_savefile));
|
||||
}
|
||||
|
||||
static void check_defaults_dir_create_dir(const char *path)
|
||||
{
|
||||
char new_path[PATH_MAX_LENGTH] = {0};
|
||||
fill_pathname_expand_special(new_path,
|
||||
path, sizeof(new_path));
|
||||
|
||||
if (path_is_directory(new_path))
|
||||
return;
|
||||
path_mkdir(new_path);
|
||||
}
|
||||
|
||||
void dir_check_defaults(void)
|
||||
{
|
||||
/* early return for people with a custom folder setup
|
||||
so it doesn't create unnecessary directories
|
||||
*/
|
||||
if (path_file_exists("custom.ini"))
|
||||
return;
|
||||
|
||||
if (!string_is_empty(g_defaults.dir.core_assets))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.core_assets);
|
||||
if (!string_is_empty(g_defaults.dir.remap))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.remap);
|
||||
if (!string_is_empty(g_defaults.dir.screenshot))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.screenshot);
|
||||
if (!string_is_empty(g_defaults.dir.core))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.core);
|
||||
if (!string_is_empty(g_defaults.dir.autoconfig))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.autoconfig);
|
||||
if (!string_is_empty(g_defaults.dir.audio_filter))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.audio_filter);
|
||||
if (!string_is_empty(g_defaults.dir.video_filter))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.video_filter);
|
||||
if (!string_is_empty(g_defaults.dir.assets))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.assets);
|
||||
if (!string_is_empty(g_defaults.dir.playlist))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.playlist);
|
||||
if (!string_is_empty(g_defaults.dir.core))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.core);
|
||||
if (!string_is_empty(g_defaults.dir.core_info))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.core_info);
|
||||
if (!string_is_empty(g_defaults.dir.overlay))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.overlay);
|
||||
if (!string_is_empty(g_defaults.dir.port))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.port);
|
||||
if (!string_is_empty(g_defaults.dir.shader))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.shader);
|
||||
if (!string_is_empty(g_defaults.dir.savestate))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.savestate);
|
||||
if (!string_is_empty(g_defaults.dir.sram))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.sram);
|
||||
if (!string_is_empty(g_defaults.dir.system))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.system);
|
||||
if (!string_is_empty(g_defaults.dir.resampler))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.resampler);
|
||||
if (!string_is_empty(g_defaults.dir.menu_config))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.menu_config);
|
||||
if (!string_is_empty(g_defaults.dir.content_history))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.content_history);
|
||||
if (!string_is_empty(g_defaults.dir.cache))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.cache);
|
||||
if (!string_is_empty(g_defaults.dir.database))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.database);
|
||||
if (!string_is_empty(g_defaults.dir.cursor))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.cursor);
|
||||
if (!string_is_empty(g_defaults.dir.cheats))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.cheats);
|
||||
if (!string_is_empty(g_defaults.dir.thumbnails))
|
||||
check_defaults_dir_create_dir(g_defaults.dir.thumbnails);
|
||||
}
|
92
dirs.h
Normal file
92
dirs.h
Normal file
@ -0,0 +1,92 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
*
|
||||
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
|
||||
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
|
||||
* PURPOSE. See the GNU General Public License for more details.
|
||||
*
|
||||
* You should have received a copy of the GNU General Public License along with RetroArch.
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#ifndef __DIRS_H
|
||||
#define __DIRS_H
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/* empty functions */
|
||||
|
||||
bool dir_is_savefile_empty(void);
|
||||
|
||||
bool dir_is_savestate_empty(void);
|
||||
|
||||
bool dir_is_system_empty(void);
|
||||
|
||||
bool dir_is_osk_overlay_empty(void);
|
||||
|
||||
/* clear functions */
|
||||
|
||||
void dir_clear_system(void);
|
||||
|
||||
void dir_clear_savefile(void);
|
||||
|
||||
void dir_clear_savestate(void);
|
||||
|
||||
void dir_clear_osk_overlay(void);
|
||||
|
||||
void dir_clear_all(void);
|
||||
|
||||
/* get size functions */
|
||||
|
||||
size_t dir_get_osk_overlay_size(void);
|
||||
|
||||
size_t dir_get_system_size(void);
|
||||
|
||||
size_t dir_get_savestate_size(void);
|
||||
|
||||
size_t dir_get_savefile_size(void);
|
||||
|
||||
/* get ptr functions */
|
||||
|
||||
char *dir_get_osk_overlay_ptr(void);
|
||||
|
||||
char *dir_get_savefile_ptr(void);
|
||||
|
||||
char *dir_get_savestate_ptr(void);
|
||||
|
||||
char *dir_get_system_ptr(void);
|
||||
|
||||
char *dir_get_osk_overlay_ptr(void);
|
||||
|
||||
/* get functions */
|
||||
|
||||
const char *dir_get_osk_overlay(void);
|
||||
|
||||
const char *dir_get_savefile(void);
|
||||
|
||||
const char *dir_get_savestate(void);
|
||||
|
||||
const char *dir_get_system(void);
|
||||
|
||||
/* set functions */
|
||||
|
||||
void dir_set_osk_overlay(const char *path);
|
||||
|
||||
void dir_set_savefile(const char *path);
|
||||
|
||||
void dir_set_savestate(const char *path);
|
||||
|
||||
void dir_set_system(const char *path);
|
||||
|
||||
void dir_check_defaults(void);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
28
driver.c
28
driver.c
@ -167,15 +167,16 @@ static bool driver_find_first(const char *label, char *s, size_t len)
|
||||
static bool driver_find_prev(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i > 0)
|
||||
find_driver_nonempty(label, i - 1, s, len);
|
||||
else
|
||||
{
|
||||
RARCH_WARN(
|
||||
"Couldn't find any previous driver (current one: \"%s\").\n", s);
|
||||
return false;
|
||||
find_driver_nonempty(label, i - 1, s, len);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
RARCH_WARN(
|
||||
"Couldn't find any previous driver (current one: \"%s\").\n", s);
|
||||
return false;
|
||||
}
|
||||
|
||||
/**
|
||||
@ -189,16 +190,17 @@ static bool driver_find_prev(const char *label, char *s, size_t len)
|
||||
bool driver_find_next(const char *label, char *s, size_t len)
|
||||
{
|
||||
int i = driver_find_index(label, s);
|
||||
|
||||
if (i >= 0 && !string_is_equal(s, "null"))
|
||||
find_driver_nonempty(label, i + 1, s, len);
|
||||
else
|
||||
{
|
||||
RARCH_WARN("%s (current one: \"%s\").\n",
|
||||
msg_hash_to_str(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER),
|
||||
s);
|
||||
return false;
|
||||
find_driver_nonempty(label, i + 1, s, len);
|
||||
return true;
|
||||
}
|
||||
return true;
|
||||
|
||||
RARCH_WARN("%s (current one: \"%s\").\n",
|
||||
msg_hash_to_str(MSG_COULD_NOT_FIND_ANY_NEXT_DRIVER),
|
||||
s);
|
||||
return false;
|
||||
}
|
||||
|
||||
static void driver_adjust_system_rates(void)
|
||||
|
4
driver.h
4
driver.h
@ -24,10 +24,6 @@
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define DRIVERS_CMD_ALL \
|
||||
|
175
dynamic.c
175
dynamic.c
@ -51,6 +51,8 @@
|
||||
#include "cores/internal_cores.h"
|
||||
#include "frontend/frontend_driver.h"
|
||||
#include "content.h"
|
||||
#include "dirs.h"
|
||||
#include "paths.h"
|
||||
#include "retroarch.h"
|
||||
#include "runloop.h"
|
||||
#include "configuration.h"
|
||||
@ -167,41 +169,6 @@ static bool environ_cb_get_system_info(unsigned cmd, void *data)
|
||||
return true;
|
||||
}
|
||||
|
||||
#ifndef HAVE_DYNAMIC
|
||||
bool libretro_get_system_info_static(struct retro_system_info *info,
|
||||
bool *load_no_content)
|
||||
{
|
||||
struct retro_system_info dummy_info = {0};
|
||||
|
||||
if (load_no_content)
|
||||
{
|
||||
load_no_content_hook = load_no_content;
|
||||
|
||||
/* load_no_content gets set in this callback. */
|
||||
retro_set_environment(environ_cb_get_system_info);
|
||||
|
||||
/* It's possible that we just set get_system_info callback
|
||||
* to the currently running core.
|
||||
*
|
||||
* Make sure we reset it to the actual environment callback.
|
||||
* Ignore any environment callbacks here in case we're running
|
||||
* on the non-current core. */
|
||||
ignore_environment_cb = true;
|
||||
retro_set_environment(rarch_environment_cb);
|
||||
ignore_environment_cb = false;
|
||||
}
|
||||
|
||||
retro_get_system_info(&dummy_info);
|
||||
memcpy(info, &dummy_info, sizeof(*info));
|
||||
|
||||
info->library_name = strdup(dummy_info.library_name);
|
||||
info->library_version = strdup(dummy_info.library_version);
|
||||
if (dummy_info.valid_extensions)
|
||||
info->valid_extensions = strdup(dummy_info.valid_extensions);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
/**
|
||||
* libretro_get_environment_info:
|
||||
@ -239,6 +206,48 @@ void libretro_get_environment_info(void (*func)(retro_environment_t),
|
||||
ignore_environment_cb = false;
|
||||
}
|
||||
|
||||
static void load_dynamic_core(void)
|
||||
{
|
||||
function_t sym = dylib_proc(NULL, "retro_init");
|
||||
|
||||
if (sym)
|
||||
{
|
||||
/* Try to verify that -lretro was not linked in from other modules
|
||||
* since loading it dynamically and with -l will fail hard. */
|
||||
RARCH_ERR("Serious problem. RetroArch wants to load libretro cores"
|
||||
"dyamically, but it is already linked.\n");
|
||||
RARCH_ERR("This could happen if other modules RetroArch depends on "
|
||||
"link against libretro directly.\n");
|
||||
RARCH_ERR("Proceeding could cause a crash. Aborting ...\n");
|
||||
retroarch_fail(1, "init_libretro_sym()");
|
||||
}
|
||||
|
||||
if (string_is_empty(path_get_core()))
|
||||
{
|
||||
RARCH_ERR("RetroArch is built for dynamic libretro cores, but "
|
||||
"libretro_path is not set. Cannot continue.\n");
|
||||
retroarch_fail(1, "init_libretro_sym()");
|
||||
}
|
||||
|
||||
/* Need to use absolute path for this setting. It can be
|
||||
* saved to content history, and a relative path would
|
||||
* break in that scenario. */
|
||||
path_resolve_realpath(
|
||||
path_get_core_ptr(),
|
||||
path_get_core_size());
|
||||
|
||||
RARCH_LOG("Loading dynamic libretro core from: \"%s\"\n",
|
||||
path_get_core());
|
||||
lib_handle = dylib_load(path_get_core());
|
||||
if (!lib_handle)
|
||||
{
|
||||
RARCH_ERR("Failed to open libretro core: \"%s\"\n",
|
||||
path_get_core());
|
||||
RARCH_ERR("Error(s): %s\n", dylib_error());
|
||||
retroarch_fail(1, "load_dynamic()");
|
||||
}
|
||||
}
|
||||
|
||||
static dylib_t libretro_get_system_info_lib(const char *path,
|
||||
struct retro_system_info *info, bool *load_no_content)
|
||||
{
|
||||
@ -280,6 +289,40 @@ static dylib_t libretro_get_system_info_lib(const char *path,
|
||||
|
||||
return lib;
|
||||
}
|
||||
#else
|
||||
static bool libretro_get_system_info_static(struct retro_system_info *info,
|
||||
bool *load_no_content)
|
||||
{
|
||||
struct retro_system_info dummy_info = {0};
|
||||
|
||||
if (load_no_content)
|
||||
{
|
||||
load_no_content_hook = load_no_content;
|
||||
|
||||
/* load_no_content gets set in this callback. */
|
||||
retro_set_environment(environ_cb_get_system_info);
|
||||
|
||||
/* It's possible that we just set get_system_info callback
|
||||
* to the currently running core.
|
||||
*
|
||||
* Make sure we reset it to the actual environment callback.
|
||||
* Ignore any environment callbacks here in case we're running
|
||||
* on the non-current core. */
|
||||
ignore_environment_cb = true;
|
||||
retro_set_environment(rarch_environment_cb);
|
||||
ignore_environment_cb = false;
|
||||
}
|
||||
|
||||
retro_get_system_info(&dummy_info);
|
||||
memcpy(info, &dummy_info, sizeof(*info));
|
||||
|
||||
info->library_name = strdup(dummy_info.library_name);
|
||||
info->library_version = strdup(dummy_info.library_version);
|
||||
if (dummy_info.valid_extensions)
|
||||
info->valid_extensions = strdup(dummy_info.valid_extensions);
|
||||
return true;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* libretro_get_system_info:
|
||||
@ -296,6 +339,7 @@ static dylib_t libretro_get_system_info_lib(const char *path,
|
||||
bool libretro_get_system_info(const char *path,
|
||||
struct retro_system_info *info, bool *load_no_content)
|
||||
{
|
||||
#ifdef HAVE_DYNAMIC
|
||||
struct retro_system_info dummy_info = {0};
|
||||
dylib_t lib = libretro_get_system_info_lib(path,
|
||||
&dummy_info, load_no_content);
|
||||
@ -308,51 +352,13 @@ bool libretro_get_system_info(const char *path,
|
||||
if (dummy_info.valid_extensions)
|
||||
info->valid_extensions = strdup(dummy_info.valid_extensions);
|
||||
dylib_close(lib);
|
||||
#else
|
||||
if (!libretro_get_system_info_static(info, load_no_content))
|
||||
return false;
|
||||
#endif
|
||||
return true;
|
||||
}
|
||||
|
||||
static void load_dynamic_core(void)
|
||||
{
|
||||
function_t sym = dylib_proc(NULL, "retro_init");
|
||||
|
||||
if (sym)
|
||||
{
|
||||
/* Try to verify that -lretro was not linked in from other modules
|
||||
* since loading it dynamically and with -l will fail hard. */
|
||||
RARCH_ERR("Serious problem. RetroArch wants to load libretro cores"
|
||||
"dyamically, but it is already linked.\n");
|
||||
RARCH_ERR("This could happen if other modules RetroArch depends on "
|
||||
"link against libretro directly.\n");
|
||||
RARCH_ERR("Proceeding could cause a crash. Aborting ...\n");
|
||||
retroarch_fail(1, "init_libretro_sym()");
|
||||
}
|
||||
|
||||
if (string_is_empty(config_get_active_core_path()))
|
||||
{
|
||||
RARCH_ERR("RetroArch is built for dynamic libretro cores, but "
|
||||
"libretro_path is not set. Cannot continue.\n");
|
||||
retroarch_fail(1, "init_libretro_sym()");
|
||||
}
|
||||
|
||||
/* Need to use absolute path for this setting. It can be
|
||||
* saved to content history, and a relative path would
|
||||
* break in that scenario. */
|
||||
path_resolve_realpath(
|
||||
config_get_active_core_path_ptr(),
|
||||
config_get_active_core_path_size());
|
||||
|
||||
RARCH_LOG("Loading dynamic libretro core from: \"%s\"\n",
|
||||
config_get_active_core_path());
|
||||
lib_handle = dylib_load(config_get_active_core_path());
|
||||
if (!lib_handle)
|
||||
{
|
||||
RARCH_ERR("Failed to open libretro core: \"%s\"\n",
|
||||
config_get_active_core_path());
|
||||
RARCH_ERR("Error(s): %s\n", dylib_error());
|
||||
retroarch_fail(1, "load_dynamic()");
|
||||
}
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* load_symbols:
|
||||
@ -934,7 +940,6 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
{
|
||||
unsigned p;
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
rarch_system_info_t *system = NULL;
|
||||
|
||||
runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);
|
||||
@ -1025,15 +1030,17 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
if (runloop_ctl(RUNLOOP_CTL_GET_CONTENT_PATH, &fullpath) &&
|
||||
fullpath)
|
||||
{
|
||||
char temp_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
RARCH_WARN("SYSTEM DIR is empty, assume CONTENT DIR %s\n",
|
||||
fullpath);
|
||||
fill_pathname_basedir(global->dir.systemdir, fullpath,
|
||||
sizeof(global->dir.systemdir));
|
||||
fill_pathname_basedir(temp_path, fullpath, sizeof(temp_path));
|
||||
dir_set_system(temp_path);
|
||||
}
|
||||
|
||||
*(const char**)data = global->dir.systemdir;
|
||||
*(const char**)data = dir_get_system_ptr();
|
||||
RARCH_LOG("Environ SYSTEM_DIRECTORY: \"%s\".\n",
|
||||
global->dir.systemdir);
|
||||
dir_get_system());
|
||||
}
|
||||
else
|
||||
{
|
||||
@ -1045,7 +1052,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_SAVE_DIRECTORY:
|
||||
*(const char**)data = retroarch_get_current_savefile_dir();
|
||||
*(const char**)data = path_get_current_savefile_dir();
|
||||
break;
|
||||
|
||||
case RETRO_ENVIRONMENT_GET_USERNAME:
|
||||
@ -1259,7 +1266,7 @@ bool rarch_environment_cb(unsigned cmd, void *data)
|
||||
{
|
||||
const char **path = (const char**)data;
|
||||
#ifdef HAVE_DYNAMIC
|
||||
*path = config_get_active_core_path();
|
||||
*path = path_get_core();
|
||||
#else
|
||||
*path = NULL;
|
||||
#endif
|
||||
|
20
dynamic.h
20
dynamic.h
@ -23,10 +23,6 @@
|
||||
|
||||
#include "core_type.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
/**
|
||||
@ -49,7 +45,6 @@ RETRO_BEGIN_DECLS
|
||||
void libretro_get_environment_info(void (*)(retro_environment_t),
|
||||
bool *load_no_content);
|
||||
|
||||
#ifdef HAVE_DYNAMIC
|
||||
/**
|
||||
* libretro_get_system_info:
|
||||
* @path : Path to libretro library.
|
||||
@ -64,21 +59,6 @@ void libretro_get_environment_info(void (*)(retro_environment_t),
|
||||
**/
|
||||
bool libretro_get_system_info(const char *path,
|
||||
struct retro_system_info *info, bool *load_no_content);
|
||||
#else
|
||||
/**
|
||||
* libretro_get_system_info_static:
|
||||
* @info : System info information.
|
||||
* @load_no_content : If true, core should be able to auto-start
|
||||
* without any content loaded.
|
||||
*
|
||||
* Gets system info from the current statically linked libretro library.
|
||||
* The struct returned must be freed as strings are allocated dynamically.
|
||||
*
|
||||
* Returns: true (1) if successful, otherwise false (0).
|
||||
**/
|
||||
bool libretro_get_system_info_static(struct retro_system_info *info,
|
||||
bool *load_no_content);
|
||||
#endif
|
||||
|
||||
/**
|
||||
* libretro_free_system_info:
|
||||
|
@ -75,3 +75,5 @@ fetch_git "https://github.com/libretro/common-overlays.git" "media/overlays"
|
||||
fetch_git "https://github.com/libretro/retroarch-assets.git" "media/assets"
|
||||
fetch_git "https://github.com/libretro/retroarch-joypad-autoconfig.git" "media/autoconfig"
|
||||
fetch_git "https://github.com/libretro/libretro-database.git" "media/libretrodb"
|
||||
|
||||
git submodule update --init --recursive
|
||||
|
@ -45,6 +45,7 @@
|
||||
#include "configuration.h"
|
||||
#include "file_path_special.h"
|
||||
|
||||
#include "paths.h"
|
||||
#include "runloop.h"
|
||||
#include "verbosity.h"
|
||||
|
||||
@ -284,13 +285,13 @@ void fill_pathname_application_special(char *s, size_t len, enum application_spe
|
||||
case APPLICATION_SPECIAL_DIRECTORY_CONFIG:
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
/* Try config directory setting first,
|
||||
* fallback to the location of the current configuration file. */
|
||||
if (!string_is_empty(settings->directory.menu_config))
|
||||
strlcpy(s, settings->directory.menu_config, len);
|
||||
else if (!string_is_empty(global->path.config))
|
||||
fill_pathname_basedir(s, global->path.config, len);
|
||||
else if (!path_is_config_empty())
|
||||
fill_pathname_basedir(s, path_get_config(), len);
|
||||
}
|
||||
break;
|
||||
case APPLICATION_SPECIAL_DIRECTORY_ASSETS_ZARCH_ICONS:
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include <3ds.h>
|
||||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifndef IS_SALAMANDER
|
||||
#include <lists/file_list.h>
|
||||
#endif
|
||||
|
@ -45,6 +45,7 @@
|
||||
#endif
|
||||
|
||||
#include <boolean.h>
|
||||
#include <compat/apple_compat.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <file/file_path.h>
|
||||
#include <rhash.h>
|
||||
@ -105,32 +106,6 @@ typedef enum
|
||||
CFAllDomainsMask = 0x0ffff /* All domains: all of the above and future items */
|
||||
} CFDomainMask;
|
||||
|
||||
#ifndef __has_feature
|
||||
/* Compatibility with non-Clang compilers. */
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef CF_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#else
|
||||
#define CF_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NS_INLINE
|
||||
#define NS_INLINE inline
|
||||
#endif
|
||||
|
||||
NS_INLINE CF_RETURNS_RETAINED CFTypeRef CFBridgingRetainCompat(id X)
|
||||
{
|
||||
#if __has_feature(objc_arc)
|
||||
return (__bridge_retained CFTypeRef)X;
|
||||
#else
|
||||
return X;
|
||||
#endif
|
||||
}
|
||||
|
||||
static NSSearchPathDirectory NSConvertFlagsCF(unsigned flags)
|
||||
{
|
||||
switch (flags)
|
||||
|
@ -39,6 +39,7 @@
|
||||
#include "../../retroarch.h"
|
||||
#include "../../runloop.h"
|
||||
#include "../../command.h"
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../file_path_special.h"
|
||||
|
||||
static void emscripten_mainloop(void)
|
||||
@ -57,7 +58,7 @@ static void emscripten_mainloop(void)
|
||||
|
||||
void cmd_savefiles(void)
|
||||
{
|
||||
command_event(CMD_EVENT_SAVEFILES, NULL);
|
||||
event_save_files();
|
||||
}
|
||||
|
||||
void cmd_save_state(void)
|
||||
@ -126,7 +127,7 @@ static void frontend_emscripten_get_env(int *argc, char *argv[],
|
||||
fill_pathname_join(g_defaults.dir.menu_content, user_path,
|
||||
"content", sizeof(g_defaults.dir.menu_content));
|
||||
fill_pathname_join(g_defaults.dir.core_assets, user_path,
|
||||
"downloads", sizeof(g_defaults.dir.core_assets));
|
||||
"content/downloads", sizeof(g_defaults.dir.core_assets));
|
||||
fill_pathname_join(g_defaults.dir.playlist, user_path,
|
||||
"playlists", sizeof(g_defaults.dir.playlist));
|
||||
fill_pathname_join(g_defaults.dir.remap, g_defaults.dir.menu_config,
|
||||
|
@ -24,6 +24,10 @@
|
||||
#include <gccore.h>
|
||||
#include <ogcsys.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#if defined(HW_RVL) && !defined(IS_SALAMANDER)
|
||||
#include <rthreads/rthreads.h>
|
||||
#include "../../memory/wii/mem2_manager.h"
|
||||
@ -61,6 +65,7 @@ static enum frontend_fork gx_fork_mode = FRONTEND_FORK_NONE;
|
||||
#endif
|
||||
|
||||
#ifndef IS_SALAMANDER
|
||||
#include "../../paths.h"
|
||||
|
||||
enum
|
||||
{
|
||||
@ -410,7 +415,7 @@ static void frontend_gx_process_args(int *argc, char *argv[])
|
||||
/* A big hack: sometimes Salamander doesn't save the new core
|
||||
* it loads on first boot, so we make sure
|
||||
* active core path is set here. */
|
||||
if (config_active_core_path_is_empty() && *argc >= 1 && strrchr(argv[0], '/'))
|
||||
if (path_is_core_empty() && *argc >= 1 && strrchr(argv[0], '/'))
|
||||
{
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
strlcpy(path, strrchr(argv[0], '/') + 1, sizeof(path));
|
||||
|
@ -14,10 +14,9 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include "../frontend_driver.h"
|
||||
|
||||
#include <stdint.h>
|
||||
#include <string.h>
|
||||
|
||||
#include "../frontend_driver.h"
|
||||
|
||||
frontend_ctx_driver_t frontend_ctx_null = {
|
||||
NULL, /* environment_get */
|
||||
|
@ -32,6 +32,7 @@
|
||||
#endif
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <file/file_path.h>
|
||||
#ifndef IS_SALAMANDER
|
||||
#include <lists/file_list.h>
|
||||
@ -125,7 +126,7 @@ static void frontend_ps3_get_environment_settings(int *argc, char *argv[],
|
||||
/* not launched from external launcher, set default path */
|
||||
// second param is multiMAN SELF file
|
||||
if(path_file_exists(argv[2]) && *argc > 1
|
||||
&& (!strcmp(argv[2], EMULATOR_CONTENT_DIR)))
|
||||
&& (string_is_equal(argv[2], EMULATOR_CONTENT_DIR)))
|
||||
{
|
||||
multiman_detected = true;
|
||||
RARCH_LOG("Started from multiMAN, auto-game start enabled.\n");
|
||||
|
@ -18,6 +18,10 @@
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef VITA
|
||||
#include <psp2/moduleinfo.h>
|
||||
#include <psp2/power.h>
|
||||
|
@ -22,6 +22,11 @@
|
||||
#include <xgraphics.h>
|
||||
|
||||
#include <file/file_path.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifndef IS_SALAMANDER
|
||||
#include <lists/file_list.h>
|
||||
#endif
|
||||
|
@ -30,8 +30,8 @@
|
||||
#include "../ui/ui_companion_driver.h"
|
||||
#include "../tasks/tasks_internal.h"
|
||||
|
||||
#include "../configuration.h"
|
||||
#include "../driver.h"
|
||||
#include "../paths.h"
|
||||
#include "../retroarch.h"
|
||||
#include "../runloop.h"
|
||||
|
||||
@ -60,9 +60,7 @@ void main_exit(void *args)
|
||||
#endif
|
||||
|
||||
frontend_driver_deinit(args);
|
||||
frontend_driver_exitspawn(
|
||||
config_get_active_core_path_ptr(),
|
||||
config_get_active_core_path_size());
|
||||
frontend_driver_exitspawn(path_get_core_ptr(), path_get_core_size());
|
||||
|
||||
rarch_ctl(RARCH_CTL_DESTROY, NULL);
|
||||
|
||||
|
@ -17,6 +17,7 @@
|
||||
#include <string.h>
|
||||
|
||||
#include <compat/strl.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
@ -82,7 +83,7 @@ frontend_ctx_driver_t *frontend_ctx_find_driver(const char *ident)
|
||||
|
||||
for (i = 0; frontend_ctx_drivers[i]; i++)
|
||||
{
|
||||
if (!strcmp(frontend_ctx_drivers[i]->ident, ident))
|
||||
if (string_is_equal(frontend_ctx_drivers[i]->ident, ident))
|
||||
return frontend_ctx_drivers[i];
|
||||
}
|
||||
|
||||
|
@ -23,10 +23,6 @@
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
enum frontend_powerstate
|
||||
|
@ -118,12 +118,9 @@ static void find_and_set_first_file(char *s, size_t len,
|
||||
static void salamander_init(char *s, size_t len)
|
||||
{
|
||||
/* normal executable loading path */
|
||||
bool config_file_exists = false;
|
||||
bool config_exists = config_file_exists(g_defaults.path.config);
|
||||
|
||||
if (path_file_exists(g_defaults.path.config))
|
||||
config_file_exists = true;
|
||||
|
||||
if (config_file_exists)
|
||||
if (config_exists)
|
||||
{
|
||||
char tmp_str[PATH_MAX_LENGTH];
|
||||
config_file_t * conf = (config_file_t*)config_file_new(g_defaults.path.config);
|
||||
@ -133,7 +130,7 @@ static void salamander_init(char *s, size_t len)
|
||||
config_get_array(conf, "libretro_path", tmp_str, sizeof(tmp_str));
|
||||
config_file_free(conf);
|
||||
|
||||
if (strcmp(tmp_str, "builtin") != 0)
|
||||
if (!string_is_equal(tmp_str, "builtin"))
|
||||
strlcpy(s, tmp_str, len);
|
||||
}
|
||||
#ifdef GEKKO
|
||||
@ -141,12 +138,12 @@ static void salamander_init(char *s, size_t len)
|
||||
* the file is there when it doesn't. */
|
||||
else
|
||||
{
|
||||
config_file_exists = false;
|
||||
config_exists = false;
|
||||
}
|
||||
#endif
|
||||
}
|
||||
|
||||
if (!config_file_exists || !strcmp(s, ""))
|
||||
if (!config_exists || string_is_equal(s, ""))
|
||||
{
|
||||
char executable_name[PATH_MAX_LENGTH];
|
||||
|
||||
@ -157,7 +154,7 @@ static void salamander_init(char *s, size_t len)
|
||||
else
|
||||
RARCH_LOG("Start [%s] found in retroarch.cfg.\n", s);
|
||||
|
||||
if (!config_file_exists)
|
||||
if (!config_exists)
|
||||
{
|
||||
config_file_t *conf = (config_file_t*)config_file_new(NULL);
|
||||
|
||||
|
@ -25,6 +25,7 @@
|
||||
#include "../../configuration.h"
|
||||
#include "../../verbosity.h"
|
||||
#include "../../driver.h"
|
||||
#include "../../paths.h"
|
||||
#include "../../runloop.h"
|
||||
#include "../../tasks/tasks_internal.h"
|
||||
#include "../../core_info.h"
|
||||
@ -41,7 +42,7 @@
|
||||
#include <commdlg.h>
|
||||
#include "../../retroarch.h"
|
||||
#include "../video_thread_wrapper.h"
|
||||
#include <Shellapi.h>
|
||||
#include <shellapi.h>
|
||||
#ifndef _MSC_VER
|
||||
extern "C" {
|
||||
#endif
|
||||
@ -287,7 +288,7 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam)
|
||||
|
||||
runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH,szFilename);
|
||||
|
||||
if (!string_is_empty(config_get_active_core_path()))
|
||||
if (!path_is_core_empty())
|
||||
{
|
||||
unsigned i;
|
||||
core_info_t *current_core = NULL;
|
||||
@ -301,7 +302,7 @@ static int win32_drag_query_file(HWND hwnd, WPARAM wparam)
|
||||
if(!string_is_equal(info->systemname, current_core->systemname))
|
||||
break;
|
||||
|
||||
if(string_is_equal(config_get_active_core_path(), info->path))
|
||||
if(string_is_equal(path_get_core(), info->path))
|
||||
{
|
||||
/* Our previous core supports the current rom */
|
||||
content_ctx_info_t content_info = {0};
|
||||
|
@ -34,6 +34,15 @@
|
||||
#include "../../verbosity.h"
|
||||
#include "../../runloop.h"
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
#include <dbus/dbus.h>
|
||||
static DBusConnection* dbus_connection = NULL;
|
||||
static unsigned int dbus_screensaver_cookie = 0;
|
||||
#endif
|
||||
|
||||
static bool xdg_screensaver_available = true;
|
||||
static bool xdg_screensaver_running = false;
|
||||
|
||||
Colormap g_x11_cmap;
|
||||
Window g_x11_win;
|
||||
Display *g_x11_dpy;
|
||||
@ -56,6 +65,133 @@ unsigned g_x11_screen;
|
||||
#define MOVERESIZE_X_SHIFT 8
|
||||
#define MOVERESIZE_Y_SHIFT 9
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
static void dbus_ensure_connection(void)
|
||||
{
|
||||
DBusError err;
|
||||
int ret;
|
||||
|
||||
dbus_error_init(&err);
|
||||
|
||||
dbus_connection = dbus_bus_get_private(DBUS_BUS_SESSION, &err);
|
||||
|
||||
if (dbus_error_is_set(&err))
|
||||
{
|
||||
RARCH_LOG("[DBus]: Failed to get DBus connection. Screensaver will not be suspended via DBus.\n");
|
||||
dbus_error_free(&err);
|
||||
}
|
||||
|
||||
if (dbus_connection)
|
||||
dbus_connection_set_exit_on_disconnect(dbus_connection, true);
|
||||
}
|
||||
|
||||
static void dbus_close_connection(void)
|
||||
{
|
||||
if (!dbus_connection)
|
||||
return;
|
||||
|
||||
dbus_connection_close(dbus_connection);
|
||||
dbus_connection_unref(dbus_connection);
|
||||
dbus_connection = NULL;
|
||||
}
|
||||
|
||||
static bool dbus_screensaver_inhibit(void)
|
||||
{
|
||||
const char *app = "RetroArch";
|
||||
const char *reason = "Playing a game";
|
||||
DBusMessage *msg = NULL;
|
||||
DBusMessage *reply = NULL;
|
||||
bool ret = false;
|
||||
|
||||
if (!dbus_connection)
|
||||
return false; /* DBus connection was not obtained */
|
||||
|
||||
if (dbus_screensaver_cookie > 0)
|
||||
return true; /* Already inhibited */
|
||||
|
||||
msg = dbus_message_new_method_call("org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"Inhibit");
|
||||
|
||||
if (!msg)
|
||||
return false;
|
||||
|
||||
if (!dbus_message_append_args(msg,
|
||||
DBUS_TYPE_STRING, &app,
|
||||
DBUS_TYPE_STRING, &reason,
|
||||
DBUS_TYPE_INVALID))
|
||||
{
|
||||
dbus_message_unref(msg);
|
||||
return false;
|
||||
}
|
||||
|
||||
reply = dbus_connection_send_with_reply_and_block(dbus_connection,
|
||||
msg, 300, NULL);
|
||||
|
||||
if (reply != NULL)
|
||||
{
|
||||
if (!dbus_message_get_args(reply, NULL,
|
||||
DBUS_TYPE_UINT32, &dbus_screensaver_cookie,
|
||||
DBUS_TYPE_INVALID))
|
||||
dbus_screensaver_cookie = 0;
|
||||
else
|
||||
ret = true;
|
||||
|
||||
dbus_message_unref(reply);
|
||||
}
|
||||
|
||||
dbus_message_unref(msg);
|
||||
|
||||
if (dbus_screensaver_cookie == 0)
|
||||
{
|
||||
RARCH_ERR("[DBus]: Failed to suspend screensaver via DBus.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
RARCH_LOG("[DBus]: Suspended screensaver via DBus.\n");
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
static void dbus_screensaver_uninhibit(void)
|
||||
{
|
||||
DBusMessage *msg = NULL;
|
||||
|
||||
if (!dbus_connection)
|
||||
return;
|
||||
|
||||
if (dbus_screensaver_cookie == 0)
|
||||
return;
|
||||
|
||||
msg = dbus_message_new_method_call("org.freedesktop.ScreenSaver",
|
||||
"/org/freedesktop/ScreenSaver",
|
||||
"org.freedesktop.ScreenSaver",
|
||||
"UnInhibit");
|
||||
if (!msg)
|
||||
return;
|
||||
|
||||
dbus_message_append_args(msg,
|
||||
DBUS_TYPE_UINT32, &dbus_screensaver_cookie,
|
||||
DBUS_TYPE_INVALID);
|
||||
|
||||
if (dbus_connection_send(dbus_connection, msg, NULL))
|
||||
dbus_connection_flush(dbus_connection);
|
||||
dbus_message_unref(msg);
|
||||
|
||||
dbus_screensaver_cookie = 0;
|
||||
}
|
||||
|
||||
/* Returns false when fallback should be attempted */
|
||||
bool x11_suspend_screensaver_dbus(bool enable)
|
||||
{
|
||||
if (enable) return dbus_screensaver_inhibit();
|
||||
dbus_screensaver_uninhibit();
|
||||
return false;
|
||||
}
|
||||
#endif
|
||||
|
||||
static void x11_hide_mouse(Display *dpy, Window win)
|
||||
{
|
||||
static char bm_no_data[] = {0, 0, 0, 0, 0, 0, 0, 0};
|
||||
@ -94,13 +230,13 @@ void x11_windowed_fullscreen(Display *dpy, Window win)
|
||||
XA_INIT(_NET_WM_STATE);
|
||||
XA_INIT(_NET_WM_STATE_FULLSCREEN);
|
||||
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.type = ClientMessage;
|
||||
xev.xclient.send_event = True;
|
||||
xev.xclient.message_type = XA_NET_WM_STATE;
|
||||
xev.xclient.window = win;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
||||
xev.xclient.data.l[1] = XA_NET_WM_STATE_FULLSCREEN;
|
||||
xev.xclient.window = win;
|
||||
xev.xclient.format = 32;
|
||||
xev.xclient.data.l[0] = _NET_WM_STATE_ADD;
|
||||
xev.xclient.data.l[1] = XA_NET_WM_STATE_FULLSCREEN;
|
||||
|
||||
XSendEvent(dpy, DefaultRootWindow(dpy), False,
|
||||
SubstructureRedirectMask | SubstructureNotifyMask,
|
||||
@ -145,33 +281,81 @@ void x11_set_window_attr(Display *dpy, Window win)
|
||||
x11_set_window_class(dpy, win);
|
||||
}
|
||||
|
||||
void x11_suspend_screensaver(Window wnd, bool enable)
|
||||
static void xdg_screensaver_inhibit(Window wnd)
|
||||
{
|
||||
int ret;
|
||||
char cmd[64] = {0};
|
||||
static bool screensaver_na = false;
|
||||
char cmd[64] = {0};
|
||||
|
||||
if (!enable)
|
||||
return;
|
||||
|
||||
if (screensaver_na)
|
||||
if (!xdg_screensaver_available)
|
||||
return;
|
||||
|
||||
RARCH_LOG("Suspending screensaver (X11).\n");
|
||||
if (xdg_screensaver_running)
|
||||
return;
|
||||
|
||||
RARCH_LOG("Suspending screensaver (X11, xdg-screensaver).\n");
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "xdg-screensaver suspend 0x%x", (int)wnd);
|
||||
|
||||
ret = system(cmd);
|
||||
if (ret == -1)
|
||||
{
|
||||
screensaver_na = true;
|
||||
xdg_screensaver_available = false;
|
||||
RARCH_WARN("Failed to launch xdg-screensaver.\n");
|
||||
}
|
||||
else if (WEXITSTATUS(ret))
|
||||
{
|
||||
screensaver_na = true;
|
||||
xdg_screensaver_available = false;
|
||||
RARCH_WARN("Could not suspend screen saver.\n");
|
||||
}
|
||||
else
|
||||
{
|
||||
xdg_screensaver_running = true;
|
||||
}
|
||||
}
|
||||
|
||||
static void xdg_screensaver_uninhibit(Window wnd)
|
||||
{
|
||||
int ret;
|
||||
char cmd[64] = {0};
|
||||
|
||||
if (!xdg_screensaver_available)
|
||||
return;
|
||||
|
||||
if (!xdg_screensaver_running)
|
||||
return;
|
||||
|
||||
RARCH_LOG("Resuming screensaver (X11, xdg-screensaver).\n");
|
||||
|
||||
snprintf(cmd, sizeof(cmd), "xdg-screensaver resume 0x%x", (int)wnd);
|
||||
|
||||
ret = system(cmd);
|
||||
|
||||
if (ret == -1)
|
||||
{
|
||||
xdg_screensaver_available = false;
|
||||
RARCH_WARN("Failed to launch xdg-screensaver.\n");
|
||||
}
|
||||
else if (WEXITSTATUS(ret))
|
||||
{
|
||||
xdg_screensaver_available = false;
|
||||
RARCH_WARN("Could not suspend screen saver.\n");
|
||||
}
|
||||
}
|
||||
|
||||
void x11_suspend_screensaver_xdg_screensaver(Window wnd, bool enable)
|
||||
{
|
||||
if (enable)
|
||||
xdg_screensaver_inhibit(wnd);
|
||||
xdg_screensaver_uninhibit(wnd);
|
||||
}
|
||||
|
||||
void x11_suspend_screensaver(Window wnd, bool enable)
|
||||
{
|
||||
#ifdef HAVE_DBUS
|
||||
if (x11_suspend_screensaver_dbus(enable))
|
||||
return;
|
||||
#endif
|
||||
x11_suspend_screensaver_xdg_screensaver(wnd, enable);
|
||||
}
|
||||
|
||||
static bool get_video_mode(Display *dpy, unsigned width, unsigned height,
|
||||
@ -293,11 +477,11 @@ bool x11_get_xinerama_coord(Display *dpy, int screen,
|
||||
unsigned x11_get_xinerama_monitor(Display *dpy, int x, int y,
|
||||
int w, int h)
|
||||
{
|
||||
int i, num_screens = 0;
|
||||
unsigned monitor = 0;
|
||||
int largest_area = 0;
|
||||
|
||||
int i, num_screens = 0;
|
||||
unsigned monitor = 0;
|
||||
int largest_area = 0;
|
||||
XineramaScreenInfo *info = x11_query_screens(dpy, &num_screens);
|
||||
|
||||
RARCH_LOG("[X11]: Xinerama screens: %d.\n", num_screens);
|
||||
|
||||
for (i = 0; i < num_screens; i++)
|
||||
@ -308,8 +492,8 @@ unsigned x11_get_xinerama_monitor(Display *dpy, int x, int y,
|
||||
int max_ty = MAX(y, info[i].y_org);
|
||||
int min_by = MIN(y + h, info[i].y_org + info[i].height);
|
||||
|
||||
int len_x = min_rx - max_lx;
|
||||
int len_y = min_by - max_ty;
|
||||
int len_x = min_rx - max_lx;
|
||||
int len_y = min_by - max_ty;
|
||||
|
||||
/* The whole window is outside the screen. */
|
||||
if (len_x < 0 || len_y < 0)
|
||||
@ -374,13 +558,12 @@ void x11_destroy_input_context(XIM *xim, XIC *xic)
|
||||
bool x11_get_metrics(void *data,
|
||||
enum display_metric_types type, float *value)
|
||||
{
|
||||
int pixels_x, pixels_y, physical_width, physical_height;
|
||||
unsigned screen_no = 0;
|
||||
Display *dpy = (Display*)XOpenDisplay(NULL);
|
||||
pixels_x = DisplayWidth(dpy, screen_no);
|
||||
pixels_y = DisplayHeight(dpy, screen_no);
|
||||
physical_width = DisplayWidthMM(dpy, screen_no);
|
||||
physical_height = DisplayHeightMM(dpy, screen_no);
|
||||
int pixels_x = DisplayWidth(dpy, screen_no);
|
||||
int pixels_y = DisplayHeight(dpy, screen_no);
|
||||
int physical_width = DisplayWidthMM(dpy, screen_no);
|
||||
int physical_height = DisplayHeightMM(dpy, screen_no);
|
||||
|
||||
(void)pixels_y;
|
||||
|
||||
@ -533,6 +716,11 @@ bool x11_connect(void)
|
||||
return false;
|
||||
}
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
dbus_ensure_connection();
|
||||
#endif
|
||||
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
@ -573,6 +761,11 @@ void x11_window_destroy(bool fullscreen)
|
||||
if (!fullscreen)
|
||||
XDestroyWindow(g_x11_dpy, g_x11_win);
|
||||
g_x11_win = None;
|
||||
|
||||
#ifdef HAVE_DBUS
|
||||
dbus_screensaver_uninhibit();
|
||||
dbus_close_connection();
|
||||
#endif
|
||||
}
|
||||
|
||||
void x11_colormap_destroy(void)
|
||||
|
120
gfx/drivers/gl.c
120
gfx/drivers/gl.c
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2015 - Michael Lelli
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -104,7 +104,7 @@ static const GLfloat vertexes_flipped[] = {
|
||||
};
|
||||
|
||||
/* Used when rendering to an FBO.
|
||||
* Texture coords have to be aligned
|
||||
* Texture coords have to be aligned
|
||||
* with vertex coordinates. */
|
||||
static const GLfloat vertexes[] = {
|
||||
0, 0,
|
||||
@ -341,8 +341,8 @@ void gl_set_viewport(void *data, unsigned viewport_width,
|
||||
|
||||
if (fabsf(device_aspect - desired_aspect) < 0.0001f)
|
||||
{
|
||||
/* If the aspect ratios of screen and desired aspect
|
||||
* ratio are sufficiently equal (floating point stuff),
|
||||
/* If the aspect ratios of screen and desired aspect
|
||||
* ratio are sufficiently equal (floating point stuff),
|
||||
* assume they are actually equal.
|
||||
*/
|
||||
}
|
||||
@ -401,7 +401,7 @@ static bool gl_shader_init(gl_t *gl)
|
||||
video_shader_ctx_init_t init_data;
|
||||
enum rarch_shader_type type;
|
||||
settings_t *settings = config_get_ptr();
|
||||
const char *shader_path = (settings->video.shader_enable
|
||||
const char *shader_path = (settings->video.shader_enable
|
||||
&& *settings->path.shader) ? settings->path.shader : NULL;
|
||||
|
||||
if (!gl)
|
||||
@ -411,7 +411,7 @@ static bool gl_shader_init(gl_t *gl)
|
||||
}
|
||||
|
||||
type = video_shader_parse_type(shader_path,
|
||||
gl_query_core_context_in_use()
|
||||
gl_query_core_context_in_use()
|
||||
? RARCH_SHADER_GLSL : DEFAULT_SHADER_TYPE);
|
||||
|
||||
switch (type)
|
||||
@ -521,7 +521,7 @@ static void gl_update_input_size(gl_t *gl, unsigned width,
|
||||
bool set_coords = false;
|
||||
|
||||
|
||||
if ((width != gl->last_width[gl->tex_index] ||
|
||||
if ((width != gl->last_width[gl->tex_index] ||
|
||||
height != gl->last_height[gl->tex_index]) && gl->empty_buf)
|
||||
{
|
||||
/* Resolution change. Need to clear out texture. */
|
||||
@ -547,12 +547,12 @@ static void gl_update_input_size(gl_t *gl, unsigned width,
|
||||
|
||||
set_coords = true;
|
||||
}
|
||||
else if ((width !=
|
||||
else if ((width !=
|
||||
gl->last_width[(gl->tex_index + gl->textures - 1) % gl->textures]) ||
|
||||
(height !=
|
||||
(height !=
|
||||
gl->last_height[(gl->tex_index + gl->textures - 1) % gl->textures]))
|
||||
{
|
||||
/* We might have used different texture coordinates
|
||||
/* We might have used different texture coordinates
|
||||
* last frame. Edge case if resolution changes very rapidly. */
|
||||
set_coords = true;
|
||||
}
|
||||
@ -582,7 +582,7 @@ static void gl_init_textures_data(gl_t *gl)
|
||||
gl->prev_info[i].tex_size[0] = gl->tex_w;
|
||||
gl->prev_info[i].input_size[1] = gl->tex_h;
|
||||
gl->prev_info[i].tex_size[1] = gl->tex_h;
|
||||
memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords));
|
||||
memcpy(gl->prev_info[i].coord, tex_coords, sizeof(tex_coords));
|
||||
}
|
||||
}
|
||||
|
||||
@ -598,7 +598,7 @@ static void gl_init_textures_reference(gl_t *gl, unsigned i,
|
||||
|
||||
#ifdef HAVE_PSGL
|
||||
glTextureReferenceSCE(GL_TEXTURE_2D, 1,
|
||||
gl->tex_w, gl->tex_h, 0,
|
||||
gl->tex_w, gl->tex_h, 0,
|
||||
internal_fmt,
|
||||
gl->tex_w * gl->base_size,
|
||||
gl->tex_w * gl->tex_h * i * gl->base_size);
|
||||
@ -632,7 +632,7 @@ static void gl_init_textures(gl_t *gl, const video_info_t *video)
|
||||
|
||||
glBindBuffer(GL_TEXTURE_REFERENCE_BUFFER_SCE, gl->pbo);
|
||||
glBufferData(GL_TEXTURE_REFERENCE_BUFFER_SCE,
|
||||
gl->tex_w * gl->tex_h * gl->base_size * gl->textures,
|
||||
gl->tex_w * gl->tex_h * gl->base_size * gl->textures,
|
||||
NULL, GL_STREAM_DRAW);
|
||||
#endif
|
||||
|
||||
@ -684,7 +684,7 @@ static INLINE void gl_copy_frame(gl_t *gl, const void *frame,
|
||||
#if defined(HAVE_PSGL)
|
||||
{
|
||||
unsigned h;
|
||||
size_t buffer_addr = gl->tex_w * gl->tex_h *
|
||||
size_t buffer_addr = gl->tex_w * gl->tex_h *
|
||||
gl->tex_index * gl->base_size;
|
||||
size_t buffer_stride = gl->tex_w * gl->base_size;
|
||||
const uint8_t *frame_copy = frame;
|
||||
@ -729,7 +729,7 @@ static INLINE void gl_copy_frame(gl_t *gl, const void *frame,
|
||||
{
|
||||
bool use_rgba = video_driver_supports_rgba();
|
||||
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,
|
||||
glPixelStorei(GL_UNPACK_ALIGNMENT,
|
||||
video_pixel_get_alignment(width * gl->base_size));
|
||||
|
||||
/* Fallback for GLES devices without GL_BGRA_EXT. */
|
||||
@ -761,7 +761,7 @@ static INLINE void gl_copy_frame(gl_t *gl, const void *frame,
|
||||
|
||||
if (width != pitch_width)
|
||||
{
|
||||
/* Slow path - conv_buffer is preallocated
|
||||
/* Slow path - conv_buffer is preallocated
|
||||
* just in case we hit this path. */
|
||||
|
||||
unsigned h;
|
||||
@ -777,7 +777,7 @@ static INLINE void gl_copy_frame(gl_t *gl, const void *frame,
|
||||
|
||||
glTexSubImage2D(GL_TEXTURE_2D,
|
||||
0, 0, 0, width, height, gl->texture_type,
|
||||
gl->texture_fmt, data_buf);
|
||||
gl->texture_fmt, data_buf);
|
||||
}
|
||||
}
|
||||
#else
|
||||
@ -790,7 +790,7 @@ static INLINE void gl_copy_frame(gl_t *gl, const void *frame,
|
||||
/* Convert to 32-bit textures on desktop GL.
|
||||
*
|
||||
* It is *much* faster (order of magnitude on my setup)
|
||||
* to use a custom SIMD-optimized conversion routine
|
||||
* to use a custom SIMD-optimized conversion routine
|
||||
* than letting GL do it. */
|
||||
video_frame_convert_rgb16_to_rgb32(
|
||||
&gl->scaler,
|
||||
@ -847,7 +847,7 @@ void gl_load_texture_data(
|
||||
glBindTexture(GL_TEXTURE_2D, id);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_S, wrap);
|
||||
glTexParameteri(GL_TEXTURE_2D, GL_TEXTURE_WRAP_T, wrap);
|
||||
|
||||
|
||||
if (!gl_check_capability(GL_CAPS_MIPMAP))
|
||||
{
|
||||
/* Assume no mipmapping support. */
|
||||
@ -1141,7 +1141,7 @@ static bool gl_frame(void *data, const void *frame,
|
||||
{
|
||||
gl_check_fbo_dimensions(gl);
|
||||
|
||||
/* Go back to what we're supposed to do,
|
||||
/* Go back to what we're supposed to do,
|
||||
* render to FBO #0. */
|
||||
gl_renderchain_start_render(gl);
|
||||
}
|
||||
@ -1156,7 +1156,7 @@ static bool gl_frame(void *data, const void *frame,
|
||||
glBindTexture(GL_TEXTURE_2D, gl->texture[gl->tex_index]);
|
||||
|
||||
/* Can be NULL for frame dupe / NULL render. */
|
||||
if (frame)
|
||||
if (frame)
|
||||
{
|
||||
#ifdef HAVE_FBO
|
||||
if (!gl->hw_render_fbo_init)
|
||||
@ -1166,13 +1166,13 @@ static bool gl_frame(void *data, const void *frame,
|
||||
gl_copy_frame(gl, frame, frame_width, frame_height, pitch);
|
||||
}
|
||||
|
||||
/* No point regenerating mipmaps
|
||||
/* No point regenerating mipmaps
|
||||
* if there are no new frames. */
|
||||
if (gl->tex_mipmap && gl_check_capability(GL_CAPS_MIPMAP))
|
||||
glGenerateMipmap(GL_TEXTURE_2D);
|
||||
}
|
||||
|
||||
/* Have to reset rendering state which libretro core
|
||||
/* Have to reset rendering state which libretro core
|
||||
* could easily have overridden. */
|
||||
#ifdef HAVE_FBO
|
||||
if (gl->hw_render_fbo_init)
|
||||
@ -1345,7 +1345,7 @@ static bool gl_frame(void *data, const void *frame,
|
||||
performance_counter_init(&gl_fence, "gl_fence");
|
||||
performance_counter_start(&gl_fence);
|
||||
glClear(GL_COLOR_BUFFER_BIT);
|
||||
gl->fences[gl->fence_count++] =
|
||||
gl->fences[gl->fence_count++] =
|
||||
glFenceSync(GL_SYNC_GPU_COMMANDS_COMPLETE, 0);
|
||||
|
||||
while (gl->fence_count > settings->video.hard_sync_frames)
|
||||
@ -1491,7 +1491,7 @@ static bool resolve_extensions(gl_t *gl, const char *context_ident)
|
||||
video_driver_get_hw_context();
|
||||
|
||||
gl_query_core_context_set(hwr->context_type == RETRO_HW_CONTEXT_OPENGL_CORE);
|
||||
|
||||
|
||||
if (gl_query_core_context_in_use())
|
||||
{
|
||||
RARCH_LOG("[GL]: Using Core GL context.\n");
|
||||
@ -1504,10 +1504,10 @@ static bool resolve_extensions(gl_t *gl, const char *context_ident)
|
||||
}
|
||||
|
||||
/* GL_RGB565 internal format support.
|
||||
* Even though ES2 support is claimed, the format
|
||||
* Even though ES2 support is claimed, the format
|
||||
* is not supported on older ATI catalyst drivers.
|
||||
*
|
||||
* The speed gain from using GL_RGB565 is worth
|
||||
* The speed gain from using GL_RGB565 is worth
|
||||
* adding some workarounds for.
|
||||
*/
|
||||
gl->have_es2_compat = gl_check_capability(GL_CAPS_ES2_COMPAT);
|
||||
@ -1624,11 +1624,11 @@ static void gl_init_pbo_readback(gl_t *gl)
|
||||
#endif
|
||||
|
||||
/* Only bother with this if we're doing GPU recording.
|
||||
* Check recording_is_enabled() and not
|
||||
* driver.recording_data, because recording is
|
||||
* Check recording_is_enabled() and not
|
||||
* driver.recording_data, because recording is
|
||||
* not initialized yet.
|
||||
*/
|
||||
gl->pbo_readback_enable = settings->video.gpu_record
|
||||
gl->pbo_readback_enable = settings->video.gpu_record
|
||||
&& *recording_enabled;
|
||||
|
||||
if (!gl->pbo_readback_enable)
|
||||
@ -1640,7 +1640,7 @@ static void gl_init_pbo_readback(gl_t *gl)
|
||||
for (i = 0; i < 4; i++)
|
||||
{
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, gl->pbo_readback[i]);
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, gl->vp.width *
|
||||
glBufferData(GL_PIXEL_PACK_BUFFER, gl->vp.width *
|
||||
gl->vp.height * sizeof(uint32_t),
|
||||
NULL, GL_STREAM_READ);
|
||||
}
|
||||
@ -1693,7 +1693,7 @@ static const gfx_ctx_driver_t *gl_get_context(gl_t *gl)
|
||||
api = GFX_CTX_OPENGL_API;
|
||||
api_name = "OpenGL";
|
||||
#endif
|
||||
|
||||
|
||||
(void)api_name;
|
||||
|
||||
gl_shared_context_use = settings->video.shared_context
|
||||
@ -1896,7 +1896,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
goto error;
|
||||
|
||||
/* Clear out potential error flags in case we use cached context. */
|
||||
glGetError();
|
||||
glGetError();
|
||||
|
||||
vendor = (const char*)glGetString(GL_VENDOR);
|
||||
renderer = (const char*)glGetString(GL_RENDERER);
|
||||
@ -1934,7 +1934,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
temp_height = mode.height;
|
||||
mode.width = 0;
|
||||
mode.height = 0;
|
||||
|
||||
|
||||
/* Get real known video size, which might have been altered by context. */
|
||||
|
||||
if (temp_width != 0 && temp_height != 0)
|
||||
@ -1946,7 +1946,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
|
||||
hwr = video_driver_get_hw_context();
|
||||
|
||||
gl->vertex_ptr = hwr->bottom_left_origin
|
||||
gl->vertex_ptr = hwr->bottom_left_origin
|
||||
? vertexes : vertexes_flipped;
|
||||
|
||||
/* Better pipelining with GPU due to synchronous glSubTexImage.
|
||||
@ -2010,7 +2010,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl->tex_w = gl->tex_h = (RARCH_SCALE_BASE * video->input_scale);
|
||||
gl->keep_aspect = video->force_aspect;
|
||||
|
||||
/* Apparently need to set viewport for passes
|
||||
/* Apparently need to set viewport for passes
|
||||
* when we aren't using FBOs. */
|
||||
gl_set_shader_viewport(gl, 0);
|
||||
gl_set_shader_viewport(gl, 1);
|
||||
@ -2021,14 +2021,14 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
shader_filter.smooth = &force_smooth;
|
||||
|
||||
if (video_shader_driver_filter_type(&shader_filter))
|
||||
gl->tex_min_filter = gl->tex_mipmap ? (force_smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
gl->tex_min_filter = gl->tex_mipmap ? (force_smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
: (force_smooth ? GL_LINEAR : GL_NEAREST);
|
||||
else
|
||||
gl->tex_min_filter = gl->tex_mipmap ?
|
||||
(video->smooth ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
gl->tex_min_filter = gl->tex_mipmap ?
|
||||
(video->smooth ? GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
: (video->smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
|
||||
gl->tex_mag_filter = min_filter_to_mag(gl->tex_min_filter);
|
||||
|
||||
wrap_info.idx = 1;
|
||||
@ -2055,7 +2055,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl->coords.lut_tex_coord = tex_coords;
|
||||
gl->coords.vertices = 4;
|
||||
|
||||
/* Empty buffer that we use to clear out
|
||||
/* Empty buffer that we use to clear out
|
||||
* the texture with on res change. */
|
||||
gl->empty_buf = calloc(sizeof(uint32_t), gl->tex_w * gl->tex_h);
|
||||
|
||||
@ -2072,7 +2072,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
#ifdef HAVE_FBO
|
||||
gl_renderchain_init(gl, gl->tex_w, gl->tex_h);
|
||||
|
||||
if (gl->hw_render_use &&
|
||||
if (gl->hw_render_use &&
|
||||
!gl_init_hw_render(gl, gl->tex_w, gl->tex_h))
|
||||
goto error;
|
||||
#endif
|
||||
@ -2081,10 +2081,10 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
inp.input_data = input_data;
|
||||
|
||||
video_context_driver_input_driver(&inp);
|
||||
|
||||
|
||||
if (settings->video.font_enable)
|
||||
{
|
||||
if (!font_driver_init_first(NULL, NULL, gl, *settings->path.font
|
||||
if (!font_driver_init_first(NULL, NULL, gl, *settings->path.font
|
||||
? settings->path.font : NULL, settings->video.font_size, false,
|
||||
FONT_DRIVER_RENDER_OPENGL_API))
|
||||
RARCH_ERR("[GL]: Failed to initialize font renderer.\n");
|
||||
@ -2094,7 +2094,7 @@ static void *gl_init(const video_info_t *video, const input_driver_t **input, vo
|
||||
gl_init_pbo_readback(gl);
|
||||
#endif
|
||||
|
||||
if (!gl_check_error(error_string))
|
||||
if (!gl_check_error(&error_string))
|
||||
{
|
||||
RARCH_ERR("%s\n", error_string);
|
||||
free(error_string);
|
||||
@ -2190,8 +2190,8 @@ static void gl_update_tex_filter_frame(gl_t *gl)
|
||||
gl->tex_mipmap = video_shader_driver_mipmap_input(&mip_level);
|
||||
|
||||
gl->video_info.smooth = smooth;
|
||||
new_filt = gl->tex_mipmap ? (smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
new_filt = gl->tex_mipmap ? (smooth ?
|
||||
GL_LINEAR_MIPMAP_LINEAR : GL_NEAREST_MIPMAP_NEAREST)
|
||||
: (smooth ? GL_LINEAR : GL_NEAREST);
|
||||
|
||||
if (new_filt == gl->tex_min_filter && wrap_mode == gl->wrap_mode)
|
||||
@ -2366,7 +2366,7 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
|
||||
|
||||
/* Don't readback if we're in menu mode.
|
||||
* We haven't buffered up enough frames yet, come back later. */
|
||||
if (!gl->pbo_readback_valid[gl->pbo_readback_index])
|
||||
if (!gl->pbo_readback_valid[gl->pbo_readback_index])
|
||||
goto error;
|
||||
|
||||
gl->pbo_readback_valid[gl->pbo_readback_index] = false;
|
||||
@ -2404,15 +2404,15 @@ static bool gl_read_viewport(void *data, uint8_t *buffer)
|
||||
glUnmapBuffer(GL_PIXEL_PACK_BUFFER);
|
||||
glBindBuffer(GL_PIXEL_PACK_BUFFER, 0);
|
||||
}
|
||||
else /* Use slow synchronous readbacks. Use this with plain screenshots
|
||||
else /* Use slow synchronous readbacks. Use this with plain screenshots
|
||||
as we don't really care about performance in this case. */
|
||||
#endif
|
||||
{
|
||||
/* GLES2 only guarantees GL_RGBA/GL_UNSIGNED_BYTE
|
||||
/* GLES2 only guarantees GL_RGBA/GL_UNSIGNED_BYTE
|
||||
* readbacks so do just that.
|
||||
* GLES2 also doesn't support reading back data
|
||||
* from front buffer, so render a cached frame
|
||||
* and have gl_frame() do the readback while it's
|
||||
* GLES2 also doesn't support reading back data
|
||||
* from front buffer, so render a cached frame
|
||||
* and have gl_frame() do the readback while it's
|
||||
* in the back buffer.
|
||||
*
|
||||
* Keep codepath similar for GLES and desktop GL.
|
||||
@ -2528,12 +2528,12 @@ bool gl_load_luts(const struct video_shader *shader,
|
||||
}
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
static bool gl_overlay_load(void *data,
|
||||
static bool gl_overlay_load(void *data,
|
||||
const void *image_data, unsigned num_images)
|
||||
{
|
||||
unsigned i, j;
|
||||
gl_t *gl = (gl_t*)data;
|
||||
const struct texture_image *images =
|
||||
const struct texture_image *images =
|
||||
(const struct texture_image*)image_data;
|
||||
|
||||
if (!gl)
|
||||
@ -2557,8 +2557,8 @@ static bool gl_overlay_load(void *data,
|
||||
gl->overlay_color_coord = (GLfloat*)
|
||||
calloc(4 * 4 * num_images, sizeof(GLfloat));
|
||||
|
||||
if ( !gl->overlay_vertex_coord
|
||||
|| !gl->overlay_tex_coord
|
||||
if ( !gl->overlay_vertex_coord
|
||||
|| !gl->overlay_tex_coord
|
||||
|| !gl->overlay_color_coord)
|
||||
return false;
|
||||
|
||||
@ -2567,7 +2567,7 @@ static bool gl_overlay_load(void *data,
|
||||
|
||||
for (i = 0; i < num_images; i++)
|
||||
{
|
||||
unsigned alignment = video_pixel_get_alignment(images[i].width
|
||||
unsigned alignment = video_pixel_get_alignment(images[i].width
|
||||
* sizeof(uint32_t));
|
||||
|
||||
gl_load_texture_data(gl->overlay_tex[i],
|
||||
@ -2724,7 +2724,7 @@ static void video_texture_load_gl(
|
||||
{
|
||||
/* Generate the OpenGL texture object */
|
||||
glGenTextures(1, (GLuint*)id);
|
||||
gl_load_texture_data((GLuint)*id,
|
||||
gl_load_texture_data((GLuint)*id,
|
||||
RARCH_WRAP_EDGE, filter_type,
|
||||
4 /* TODO/FIXME - dehardcode */,
|
||||
ti->width, ti->height, ti->pixels,
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2015 - Michael Lelli
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -72,31 +72,29 @@ static bool gl_query_extension(const char *ext)
|
||||
return ret;
|
||||
}
|
||||
|
||||
bool gl_check_error(char *error_string)
|
||||
bool gl_check_error(char **error_string)
|
||||
{
|
||||
int error = glGetError();
|
||||
switch (error)
|
||||
{
|
||||
case GL_INVALID_ENUM:
|
||||
error_string = strdup("GL: Invalid enum.");
|
||||
*error_string = strdup("GL: Invalid enum.");
|
||||
break;
|
||||
case GL_INVALID_VALUE:
|
||||
error_string = strdup("GL: Invalid value.");
|
||||
*error_string = strdup("GL: Invalid value.");
|
||||
break;
|
||||
case GL_INVALID_OPERATION:
|
||||
error_string = strdup("GL: Invalid operation.");
|
||||
*error_string = strdup("GL: Invalid operation.");
|
||||
break;
|
||||
case GL_OUT_OF_MEMORY:
|
||||
error_string = strdup("GL: Out of memory.");
|
||||
*error_string = strdup("GL: Out of memory.");
|
||||
break;
|
||||
case GL_NO_ERROR:
|
||||
return true;
|
||||
default:
|
||||
error_string = strdup("Non specified GL error.");
|
||||
*error_string = strdup("Non specified GL error.");
|
||||
break;
|
||||
}
|
||||
|
||||
(void)error_string;
|
||||
|
||||
return false;
|
||||
}
|
||||
@ -114,7 +112,7 @@ bool gl_check_capability(enum gl_capability_enum enum_idx)
|
||||
if (version && sscanf(version, "%u.%u", &major, &minor) != 2)
|
||||
#endif
|
||||
major = minor = 0;
|
||||
|
||||
|
||||
(void)vendor;
|
||||
|
||||
switch (enum_idx)
|
||||
@ -167,15 +165,15 @@ bool gl_check_capability(enum gl_capability_enum enum_idx)
|
||||
&& !gl_query_extension("EXT_framebuffer_object"))
|
||||
return false;
|
||||
|
||||
if (glGenFramebuffers
|
||||
&& glBindFramebuffer
|
||||
&& glFramebufferTexture2D
|
||||
&& glCheckFramebufferStatus
|
||||
&& glDeleteFramebuffers
|
||||
&& glGenRenderbuffers
|
||||
&& glBindRenderbuffer
|
||||
&& glFramebufferRenderbuffer
|
||||
&& glRenderbufferStorage
|
||||
if (glGenFramebuffers
|
||||
&& glBindFramebuffer
|
||||
&& glFramebufferTexture2D
|
||||
&& glCheckFramebufferStatus
|
||||
&& glDeleteFramebuffers
|
||||
&& glGenRenderbuffers
|
||||
&& glBindRenderbuffer
|
||||
&& glFramebufferRenderbuffer
|
||||
&& glRenderbufferStorage
|
||||
&& glDeleteRenderbuffers)
|
||||
return true;
|
||||
break;
|
||||
@ -205,7 +203,7 @@ bool gl_check_capability(enum gl_capability_enum enum_idx)
|
||||
video_driver_get_hw_context();
|
||||
if (major >= 3)
|
||||
return true;
|
||||
if (hwr->stencil
|
||||
if (hwr->stencil
|
||||
&& !gl_query_extension("OES_packed_depth_stencil")
|
||||
&& !gl_query_extension("EXT_packed_depth_stencil"))
|
||||
return false;
|
||||
@ -273,7 +271,7 @@ bool gl_check_capability(enum gl_capability_enum enum_idx)
|
||||
if (major >= 3 || gl_query_extension("EXT_sRGB"))
|
||||
return true;
|
||||
#elif defined(HAVE_FBO)
|
||||
if (gl_query_core_context_in_use() ||
|
||||
if (gl_query_core_context_in_use() ||
|
||||
(gl_query_extension("EXT_texture_sRGB")
|
||||
&& gl_query_extension("ARB_framebuffer_sRGB")))
|
||||
return true;
|
||||
|
@ -2,7 +2,7 @@
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
* Copyright (C) 2011-2016 - Daniel De Matteis
|
||||
* Copyright (C) 2012-2015 - Michael Lelli
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -138,7 +138,7 @@
|
||||
#define RARCH_GL_FORMAT32 GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
#define RARCH_GL_FORMAT16 GL_UNSIGNED_INT_8_8_8_8_REV
|
||||
|
||||
/* GL_RGB565 internal format isn't in desktop GL
|
||||
/* GL_RGB565 internal format isn't in desktop GL
|
||||
* until 4.1 core (ARB_ES2_compatibility).
|
||||
* Check for this. */
|
||||
#ifndef GL_RGB565
|
||||
@ -202,7 +202,7 @@ enum gl_capability_enum
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
bool gl_check_error(char *error_string);
|
||||
bool gl_check_error(char **error_string);
|
||||
|
||||
bool gl_query_core_context_in_use(void);
|
||||
|
||||
|
@ -15,6 +15,7 @@
|
||||
*/
|
||||
|
||||
#include <math.h>
|
||||
#include <string.h>
|
||||
|
||||
#include <VG/openvg.h>
|
||||
#include <VG/vgext.h>
|
||||
|
@ -36,6 +36,7 @@
|
||||
#endif
|
||||
|
||||
#include <retro_assert.h>
|
||||
#include <compat/apple_compat.h>
|
||||
|
||||
#import "../../ui/drivers/cocoa/cocoa_common.h"
|
||||
#include "../video_context_driver.h"
|
||||
|
@ -112,7 +112,7 @@ static bool font_renderer_create_atlas(ft_font_renderer_t *handle)
|
||||
glyph->draw_offset_x = slot->bitmap_left;
|
||||
glyph->draw_offset_y = -slot->bitmap_top;
|
||||
|
||||
if (buffer[i])
|
||||
if (buffer[i] && slot->bitmap.buffer)
|
||||
memcpy(buffer[i], slot->bitmap.buffer,
|
||||
slot->bitmap.rows * pitches[i]);
|
||||
max_width = MAX(max_width, (unsigned)slot->bitmap.width);
|
||||
|
@ -19,10 +19,11 @@
|
||||
#include <sstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <file/file_path.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
#include "glslang_util.hpp"
|
||||
#include "glslang.hpp"
|
||||
@ -227,7 +228,7 @@ const char *glslang_format_to_string(enum glslang_format fmt)
|
||||
static glslang_format glslang_find_format(const char *fmt)
|
||||
{
|
||||
#undef FMT
|
||||
#define FMT(x) if (!strcmp(fmt, #x)) return SLANG_FORMAT_ ## x
|
||||
#define FMT(x) if (string_is_equal(fmt, #x)) return SLANG_FORMAT_ ## x
|
||||
FMT(R8_UNORM);
|
||||
FMT(R8_UINT);
|
||||
FMT(R8_SINT);
|
||||
@ -309,7 +310,7 @@ static bool glslang_parse_meta(const vector<string> &lines, glslang_meta *meta)
|
||||
* if they are exactly the same. */
|
||||
if (itr != end(meta->parameters))
|
||||
{
|
||||
if (itr->desc != desc ||
|
||||
if ( itr->desc != desc ||
|
||||
itr->initial != initial ||
|
||||
itr->minimum != minimum ||
|
||||
itr->maximum != maximum ||
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* RetroArch - A frontend for libretro.
|
||||
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
|
||||
*
|
||||
*
|
||||
* RetroArch is free software: you can redistribute it and/or modify it under the terms
|
||||
* of the GNU General Public License as published by the Free Software Found-
|
||||
* ation, either version 3 of the License, or (at your option) any later version.
|
||||
@ -93,7 +93,7 @@ struct shader_uniforms
|
||||
int frame_direction;
|
||||
|
||||
int lut_texture[GFX_MAX_TEXTURES];
|
||||
|
||||
|
||||
struct shader_uniforms_frame orig;
|
||||
struct shader_uniforms_frame feedback;
|
||||
struct shader_uniforms_frame pass[GFX_MAX_SHADERS];
|
||||
@ -290,7 +290,7 @@ static bool gl_glsl_compile_shader(glsl_shader_data_t *glsl,
|
||||
static bool gl_glsl_link_program(GLuint prog)
|
||||
{
|
||||
GLint status;
|
||||
|
||||
|
||||
glLinkProgram(prog);
|
||||
|
||||
glGetProgramiv(prog, GL_LINK_STATUS, &status);
|
||||
@ -358,7 +358,7 @@ static bool gl_glsl_compile_program(
|
||||
goto error;
|
||||
|
||||
/* Clean up dead memory. We're not going to relink the program.
|
||||
* Detaching first seems to kill some mobile drivers
|
||||
* Detaching first seems to kill some mobile drivers
|
||||
* (according to the intertubes anyways). */
|
||||
if (program->vprg)
|
||||
glDeleteShader(program->vprg);
|
||||
@ -445,8 +445,8 @@ static bool gl_glsl_compile_programs(
|
||||
shader_prog_info.fragment = fragment;
|
||||
shader_prog_info.is_file = false;
|
||||
|
||||
if (!gl_glsl_compile_program(glsl, i,
|
||||
&program[i],
|
||||
if (!gl_glsl_compile_program(glsl, i,
|
||||
&program[i],
|
||||
&shader_prog_info))
|
||||
{
|
||||
RARCH_ERR("Failed to create GL program #%u.\n", i);
|
||||
@ -472,7 +472,7 @@ static void gl_glsl_reset_attrib(glsl_shader_data_t *glsl)
|
||||
static void gl_glsl_set_vbo(GLfloat **buffer, size_t *buffer_elems,
|
||||
const GLfloat *data, size_t elems)
|
||||
{
|
||||
if (elems != *buffer_elems ||
|
||||
if (elems != *buffer_elems ||
|
||||
memcmp(data, *buffer, elems * sizeof(GLfloat)))
|
||||
{
|
||||
if (elems > *buffer_elems)
|
||||
@ -712,12 +712,12 @@ static void *gl_glsl_init(void *data, const char *path)
|
||||
shader_support = glCreateProgram && glUseProgram && glCreateShader
|
||||
&& glDeleteShader && glShaderSource && glCompileShader && glAttachShader
|
||||
&& glDetachShader && glLinkProgram && glGetUniformLocation
|
||||
&& glUniform1i && glUniform1f && glUniform2fv && glUniform4fv
|
||||
&& glUniform1i && glUniform1f && glUniform2fv && glUniform4fv
|
||||
&& glUniformMatrix4fv
|
||||
&& glGetShaderiv && glGetShaderInfoLog && glGetProgramiv
|
||||
&& glGetProgramInfoLog
|
||||
&& glGetShaderiv && glGetShaderInfoLog && glGetProgramiv
|
||||
&& glGetProgramInfoLog
|
||||
&& glDeleteProgram && glGetAttachedShaders
|
||||
&& glGetAttribLocation && glEnableVertexAttribArray
|
||||
&& glGetAttribLocation && glEnableVertexAttribArray
|
||||
&& glDisableVertexAttribArray
|
||||
&& glVertexAttribPointer
|
||||
&& glGenBuffers && glBufferData && glDeleteBuffers && glBindBuffer;
|
||||
@ -766,9 +766,9 @@ static void *gl_glsl_init(void *data, const char *path)
|
||||
{
|
||||
RARCH_WARN("[GL]: Stock GLSL shaders will be used.\n");
|
||||
glsl->shader->passes = 1;
|
||||
glsl->shader->pass[0].source.string.vertex =
|
||||
glsl->shader->pass[0].source.string.vertex =
|
||||
strdup(glsl_core ? stock_vertex_core : stock_vertex_modern);
|
||||
glsl->shader->pass[0].source.string.fragment =
|
||||
glsl->shader->pass[0].source.string.fragment =
|
||||
strdup(glsl_core ? stock_fragment_core : stock_fragment_modern);
|
||||
glsl->shader->modern = true;
|
||||
}
|
||||
@ -846,7 +846,7 @@ static void *gl_glsl_init(void *data, const char *path)
|
||||
gl_glsl_find_uniforms(glsl, i, glsl->prg[i].id, &glsl->uniforms[i]);
|
||||
|
||||
#ifdef GLSL_DEBUG
|
||||
if (!gl_check_error(error_string))
|
||||
if (!gl_check_error(&error_string))
|
||||
{
|
||||
RARCH_ERR("%s\n", error_string);
|
||||
free(error_string);
|
||||
@ -877,17 +877,17 @@ static void *gl_glsl_init(void *data, const char *path)
|
||||
if (!glsl->state_tracker)
|
||||
RARCH_WARN("Failed to init state tracker.\n");
|
||||
}
|
||||
|
||||
|
||||
glsl->prg[glsl->shader->passes + 1] = glsl->prg[0];
|
||||
glsl->uniforms[glsl->shader->passes + 1] = glsl->uniforms[0];
|
||||
|
||||
if (glsl->shader->modern)
|
||||
{
|
||||
shader_prog_info.vertex =
|
||||
glsl_core ?
|
||||
shader_prog_info.vertex =
|
||||
glsl_core ?
|
||||
stock_vertex_core_blend : stock_vertex_modern_blend;
|
||||
shader_prog_info.fragment =
|
||||
glsl_core ?
|
||||
shader_prog_info.fragment =
|
||||
glsl_core ?
|
||||
stock_fragment_core_blend : stock_fragment_modern_blend;
|
||||
shader_prog_info.is_file = false;
|
||||
|
||||
@ -1011,12 +1011,12 @@ static void gl_glsl_set_uniform_parameter(
|
||||
}
|
||||
|
||||
static void gl_glsl_set_params(void *data, void *shader_data,
|
||||
unsigned width, unsigned height,
|
||||
unsigned tex_width, unsigned tex_height,
|
||||
unsigned width, unsigned height,
|
||||
unsigned tex_width, unsigned tex_height,
|
||||
unsigned out_width, unsigned out_height,
|
||||
unsigned frame_count,
|
||||
const void *_info,
|
||||
const void *_prev_info,
|
||||
const void *_info,
|
||||
const void *_prev_info,
|
||||
const void *_feedback_info,
|
||||
const void *_fbo_info, unsigned fbo_info_cnt)
|
||||
{
|
||||
@ -1186,7 +1186,7 @@ static void gl_glsl_set_params(void *data, void *shader_data,
|
||||
texunit++;
|
||||
}
|
||||
|
||||
|
||||
|
||||
if (uni->prev[i].texture_size >= 0)
|
||||
glUniform2fv(uni->prev[i].texture_size, 1, prev_info[i].tex_size);
|
||||
|
||||
@ -1218,7 +1218,7 @@ static void gl_glsl_set_params(void *data, void *shader_data,
|
||||
/* #pragma parameters. */
|
||||
for (i = 0; i < glsl->shader->num_parameters; i++)
|
||||
{
|
||||
|
||||
|
||||
int location = glGetUniformLocation(
|
||||
glsl->prg[glsl->active_idx].id,
|
||||
glsl->shader->parameters[i].id);
|
||||
@ -1294,7 +1294,7 @@ static bool gl_glsl_set_coords(void *handle_data, void *shader_data, const struc
|
||||
|
||||
buffer = short_buffer;
|
||||
if (coords->vertices > 4)
|
||||
buffer = (GLfloat*)calloc(coords->vertices *
|
||||
buffer = (GLfloat*)calloc(coords->vertices *
|
||||
(2 + 2 + 4 + 2), sizeof(*buffer));
|
||||
|
||||
if (!buffer)
|
||||
@ -1348,7 +1348,7 @@ static void gl_glsl_use(void *data, void *shader_data, unsigned idx, bool set_ac
|
||||
glsl->active_idx = idx;
|
||||
id = glsl->prg[idx].id;
|
||||
}
|
||||
else
|
||||
else
|
||||
id = (GLuint)idx;
|
||||
|
||||
glUseProgram(id);
|
||||
@ -1365,7 +1365,7 @@ static unsigned gl_glsl_num(void *data)
|
||||
static bool gl_glsl_filter_type(void *data, unsigned idx, bool *smooth)
|
||||
{
|
||||
glsl_shader_data_t *glsl = (glsl_shader_data_t*)data;
|
||||
if (glsl && idx
|
||||
if (glsl && idx
|
||||
&& (glsl->shader->pass[idx - 1].filter != RARCH_FILTER_UNSPEC)
|
||||
)
|
||||
{
|
||||
|
@ -44,7 +44,7 @@ static const uint32_t opaque_frag[] =
|
||||
|
||||
static unsigned num_miplevels(unsigned width, unsigned height)
|
||||
{
|
||||
unsigned size = std::max(width, height);
|
||||
unsigned size = std::max(width, height);
|
||||
unsigned levels = 0;
|
||||
while (size)
|
||||
{
|
||||
@ -60,7 +60,7 @@ static void image_layout_transition_levels(
|
||||
VkAccessFlags src_access, VkAccessFlags dst_access,
|
||||
VkPipelineStageFlags src_stages, VkPipelineStageFlags dst_stages)
|
||||
{
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
VkImageMemoryBarrier barrier = { VK_STRUCTURE_TYPE_IMAGE_MEMORY_BARRIER };
|
||||
|
||||
barrier.srcAccessMask = src_access;
|
||||
barrier.dstAccessMask = dst_access;
|
||||
@ -1218,8 +1218,7 @@ void *Buffer::map()
|
||||
{
|
||||
if (vkMapMemory(device, memory, 0, size, 0, &mapped) == VK_SUCCESS)
|
||||
return mapped;
|
||||
else
|
||||
return nullptr;
|
||||
return nullptr;
|
||||
}
|
||||
return mapped;
|
||||
}
|
||||
@ -1614,7 +1613,7 @@ CommonResources::CommonResources(VkDevice device,
|
||||
memcpy(ptr, vbo_data, sizeof(vbo_data));
|
||||
vbo->unmap();
|
||||
|
||||
VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
VkSamplerCreateInfo info = { VK_STRUCTURE_TYPE_SAMPLER_CREATE_INFO };
|
||||
info.mipLodBias = 0.0f;
|
||||
info.maxAnisotropy = 1.0f;
|
||||
info.compareEnable = false;
|
||||
@ -1739,6 +1738,10 @@ bool Pass::init_feedback()
|
||||
|
||||
bool Pass::build()
|
||||
{
|
||||
unordered_map<string, slang_semantic_map> semantic_map;
|
||||
unsigned i;
|
||||
unsigned j = 0;
|
||||
|
||||
framebuffer.reset();
|
||||
framebuffer_feedback.reset();
|
||||
|
||||
@ -1750,8 +1753,6 @@ bool Pass::build()
|
||||
pass_info.rt_format, pass_info.max_levels));
|
||||
}
|
||||
|
||||
unordered_map<string, slang_semantic_map> semantic_map;
|
||||
unsigned j = 0;
|
||||
for (auto ¶m : parameters)
|
||||
{
|
||||
if (!set_unique_map(semantic_map, param.id,
|
||||
@ -1760,24 +1761,23 @@ bool Pass::build()
|
||||
j++;
|
||||
}
|
||||
|
||||
reflection = slang_reflection{};
|
||||
reflection.pass_number = pass_number;
|
||||
reflection.texture_semantic_map = &common->texture_semantic_map;
|
||||
reflection = slang_reflection{};
|
||||
reflection.pass_number = pass_number;
|
||||
reflection.texture_semantic_map = &common->texture_semantic_map;
|
||||
reflection.texture_semantic_uniform_map = &common->texture_semantic_uniform_map;
|
||||
reflection.semantic_map = &semantic_map;
|
||||
reflection.semantic_map = &semantic_map;
|
||||
|
||||
if (!slang_reflect_spirv(vertex_shader, fragment_shader, &reflection))
|
||||
return false;
|
||||
|
||||
// Filter out parameters which we will never use anyways.
|
||||
filtered_parameters.clear();
|
||||
for (unsigned i = 0; i < reflection.semantic_float_parameters.size(); i++)
|
||||
|
||||
for (i = 0; i < reflection.semantic_float_parameters.size(); i++)
|
||||
{
|
||||
if (reflection.semantic_float_parameters[i].uniform ||
|
||||
reflection.semantic_float_parameters[i].push_constant)
|
||||
{
|
||||
filtered_parameters.push_back(parameters[i]);
|
||||
}
|
||||
}
|
||||
|
||||
if (!init_pipeline())
|
||||
@ -1837,9 +1837,7 @@ void Pass::set_semantic_texture_array(VkDescriptorSet set,
|
||||
{
|
||||
if (index < reflection.semantic_textures[semantic].size() &&
|
||||
reflection.semantic_textures[semantic][index].texture)
|
||||
{
|
||||
set_texture(set, reflection.semantic_textures[semantic][index].binding, texture);
|
||||
}
|
||||
}
|
||||
|
||||
void Pass::build_semantic_texture_array_vec4(uint8_t *data, slang_texture_semantic semantic,
|
||||
@ -1850,20 +1848,16 @@ void Pass::build_semantic_texture_array_vec4(uint8_t *data, slang_texture_semant
|
||||
return;
|
||||
|
||||
if (data && refl[index].uniform)
|
||||
{
|
||||
build_vec4(
|
||||
reinterpret_cast<float *>(data + refl[index].ubo_offset),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
if (refl[index].push_constant)
|
||||
{
|
||||
build_vec4(
|
||||
reinterpret_cast<float *>(push.buffer.data() + (refl[index].push_constant_offset >> 2)),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
}
|
||||
|
||||
void Pass::build_semantic_texture_vec4(uint8_t *data, slang_texture_semantic semantic,
|
||||
@ -1876,21 +1870,18 @@ void Pass::build_semantic_vec4(uint8_t *data, slang_semantic semantic,
|
||||
unsigned width, unsigned height)
|
||||
{
|
||||
auto &refl = reflection.semantics[semantic];
|
||||
|
||||
if (data && refl.uniform)
|
||||
{
|
||||
build_vec4(
|
||||
reinterpret_cast<float *>(data + refl.ubo_offset),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
|
||||
if (refl.push_constant)
|
||||
{
|
||||
build_vec4(
|
||||
reinterpret_cast<float *>(push.buffer.data() + (refl.push_constant_offset >> 2)),
|
||||
width,
|
||||
height);
|
||||
}
|
||||
}
|
||||
|
||||
void Pass::build_semantic_parameter(uint8_t *data, unsigned index, float value)
|
||||
|
@ -22,10 +22,6 @@
|
||||
|
||||
#include "video_driver.h"
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#ifndef MAX_EGLIMAGE_TEXTURES
|
||||
|
@ -108,22 +108,23 @@ typedef struct video_pixel_scaler
|
||||
* could potentially make use of this. */
|
||||
static uintptr_t video_driver_display;
|
||||
static uintptr_t video_driver_window;
|
||||
static enum rarch_display_type video_driver_display_type;
|
||||
static char video_driver_title_buf[64];
|
||||
|
||||
static uint64_t video_driver_frame_count;
|
||||
|
||||
static void *video_driver_data = NULL;
|
||||
static video_driver_t *current_video = NULL;
|
||||
|
||||
/* Interface for "poking". */
|
||||
static const video_poke_interface_t *video_driver_poke = NULL;
|
||||
|
||||
static video_driver_state_t video_driver_state;
|
||||
|
||||
static enum rarch_display_type video_driver_display_type = RARCH_DISPLAY_NONE;
|
||||
static char video_driver_title_buf[64] = {0};
|
||||
|
||||
static uint64_t video_driver_frame_count = 0;
|
||||
|
||||
static void *video_driver_data = NULL;
|
||||
static video_driver_t *current_video = NULL;
|
||||
|
||||
/* Interface for "poking". */
|
||||
static const video_poke_interface_t *video_driver_poke = NULL;
|
||||
|
||||
/* Used for 16-bit -> 16-bit conversions that take place before
|
||||
* being passed to video driver. */
|
||||
static video_pixel_scaler_t *video_driver_scaler_ptr = NULL;
|
||||
static video_pixel_scaler_t *video_driver_scaler_ptr = NULL;
|
||||
|
||||
char rotation_lut[4][32] =
|
||||
{
|
||||
@ -1711,8 +1712,7 @@ bool video_driver_is_alive(void)
|
||||
{
|
||||
if (current_video)
|
||||
return current_video->alive(video_driver_data);
|
||||
else
|
||||
return true;
|
||||
return true;
|
||||
}
|
||||
|
||||
bool video_driver_is_focused(void)
|
||||
@ -2152,9 +2152,7 @@ void video_driver_frame(const void *data, unsigned width,
|
||||
video_driver_data, data, width, height,
|
||||
video_driver_frame_count,
|
||||
pitch, video_driver_msg))
|
||||
{
|
||||
video_driver_unset_active();
|
||||
}
|
||||
|
||||
video_driver_frame_count++;
|
||||
}
|
||||
|
@ -24,6 +24,14 @@
|
||||
#include <boolean.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
#include "../input/input_overlay.h"
|
||||
#endif
|
||||
|
||||
#include "font_driver.h"
|
||||
#include "video_filter.h"
|
||||
#include "video_shader_parse.h"
|
||||
|
@ -22,6 +22,7 @@
|
||||
#include <libretro.h>
|
||||
|
||||
#define RARCH_SOFTFILTER_THREADS_AUTO 0
|
||||
|
||||
typedef struct rarch_softfilter rarch_softfilter_t;
|
||||
|
||||
rarch_softfilter_t *rarch_softfilter_new(const char *filter_path,
|
||||
|
@ -13,6 +13,8 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <gfx/scaler/scaler.h>
|
||||
|
||||
#include <libretro.h>
|
||||
|
||||
#include "../performance_counters.h"
|
||||
@ -21,12 +23,14 @@
|
||||
#include "video_frame.h"
|
||||
|
||||
void video_frame_convert_rgb16_to_rgb32(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
int width, int height,
|
||||
int in_pitch)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)data;
|
||||
|
||||
if (width != scaler->in_width || height != scaler->in_height)
|
||||
{
|
||||
scaler->in_width = width;
|
||||
@ -46,7 +50,7 @@ void video_frame_convert_rgb16_to_rgb32(
|
||||
}
|
||||
|
||||
void video_frame_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
enum scaler_pix_fmt format,
|
||||
@ -57,6 +61,8 @@ void video_frame_scale(
|
||||
unsigned height,
|
||||
unsigned pitch)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)data;
|
||||
|
||||
if (
|
||||
width != (unsigned)scaler->in_width
|
||||
|| height != (unsigned)scaler->in_height
|
||||
@ -80,7 +86,7 @@ void video_frame_scale(
|
||||
}
|
||||
|
||||
void video_frame_record_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
unsigned scaler_width,
|
||||
@ -91,6 +97,8 @@ void video_frame_record_scale(
|
||||
unsigned pitch,
|
||||
bool bilinear)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)data;
|
||||
|
||||
if (
|
||||
width != (unsigned)scaler->in_width
|
||||
|| height != (unsigned)scaler->in_height
|
||||
@ -114,10 +122,12 @@ void video_frame_record_scale(
|
||||
}
|
||||
|
||||
void video_frame_convert_argb8888_to_abgr8888(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output, const void *input,
|
||||
int width, int height, int in_pitch)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)data;
|
||||
|
||||
if (width != scaler->in_width || height != scaler->in_height)
|
||||
{
|
||||
scaler->in_width = width;
|
||||
@ -136,11 +146,13 @@ void video_frame_convert_argb8888_to_abgr8888(
|
||||
}
|
||||
|
||||
void video_frame_convert_to_bgr24(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output, const void *input,
|
||||
int width, int height, int in_pitch,
|
||||
bool bgr24)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)data;
|
||||
|
||||
scaler->in_width = width;
|
||||
scaler->in_height = height;
|
||||
scaler->out_width = width;
|
||||
@ -179,11 +191,12 @@ void video_frame_convert_rgba_to_bgr(
|
||||
}
|
||||
|
||||
bool video_pixel_frame_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *scaler_data,
|
||||
void *output, const void *data,
|
||||
unsigned width, unsigned height,
|
||||
size_t pitch)
|
||||
{
|
||||
struct scaler_ctx *scaler = (struct scaler_ctx*)scaler_data;
|
||||
static struct retro_perf_counter video_frame_conv = {0};
|
||||
|
||||
performance_counter_init(&video_frame_conv, "video_frame_conv");
|
||||
|
@ -17,18 +17,19 @@
|
||||
#define _VIDEO_FRAME_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <retro_common_api.h>
|
||||
|
||||
#include <gfx/scaler/scaler.h>
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
void video_frame_convert_rgb16_to_rgb32(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
int width, int height,
|
||||
int in_pitch);
|
||||
|
||||
void video_frame_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
enum scaler_pix_fmt format,
|
||||
@ -40,7 +41,7 @@ void video_frame_scale(
|
||||
unsigned pitch);
|
||||
|
||||
void video_frame_record_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output,
|
||||
const void *input,
|
||||
unsigned scaler_width,
|
||||
@ -52,12 +53,12 @@ void video_frame_record_scale(
|
||||
bool bilinear);
|
||||
|
||||
void video_frame_convert_argb8888_to_abgr8888(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output, const void *input,
|
||||
int width, int height, int in_pitch);
|
||||
|
||||
void video_frame_convert_to_bgr24(
|
||||
struct scaler_ctx *scaler,
|
||||
void *data,
|
||||
void *output, const void *input,
|
||||
int width, int height, int in_pitch,
|
||||
bool bgr24);
|
||||
@ -68,10 +69,12 @@ void video_frame_convert_rgba_to_bgr(
|
||||
unsigned width);
|
||||
|
||||
bool video_pixel_frame_scale(
|
||||
struct scaler_ctx *scaler,
|
||||
void *scaler_data,
|
||||
void *output,
|
||||
const void *data,
|
||||
unsigned width, unsigned height,
|
||||
size_t pitch);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -54,16 +54,21 @@ ALGORITHMS
|
||||
/*============================================================
|
||||
ARCHIVE FILE
|
||||
============================================================ */
|
||||
#include "../libretro-common/file/archive_file.c"
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
#include "../libretro-common/file/archive_file.c"
|
||||
#include "../libretro-common/file/archive_file_zlib.c"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_7ZIP
|
||||
#include "../libretro-common/file/archive_file_7z.c"
|
||||
#endif
|
||||
|
||||
/*============================================================
|
||||
ENCODINGS
|
||||
============================================================ */
|
||||
#include "../libretro-common/encodings/encoding_utf.c"
|
||||
#include "../libretro-common/encodings/encoding_crc32.c"
|
||||
|
||||
/*============================================================
|
||||
PERFORMANCE
|
||||
@ -268,6 +273,7 @@ VIDEO DRIVER
|
||||
#include "../libretro-common/gfx/math/matrix_3x3.c"
|
||||
#include "../libretro-common/gfx/math/vector_2.c"
|
||||
#include "../libretro-common/gfx/math/vector_3.c"
|
||||
#include "../libretro-common/gfx/math/vector_4.c"
|
||||
|
||||
#if defined(GEKKO)
|
||||
#ifdef HW_RVL
|
||||
@ -796,6 +802,8 @@ RETROARCH
|
||||
============================================================ */
|
||||
#include "../core_impl.c"
|
||||
#include "../retroarch.c"
|
||||
#include "../dirs.c"
|
||||
#include "../paths.c"
|
||||
#include "../runloop.c"
|
||||
#include "../libretro-common/queues/task_queue.c"
|
||||
|
||||
@ -860,8 +868,7 @@ NETPLAY
|
||||
DATA RUNLOOP
|
||||
============================================================ */
|
||||
#include "../tasks/task_content.c"
|
||||
#include "../tasks/task_save_ram.c"
|
||||
#include "../tasks/task_save_state.c"
|
||||
#include "../tasks/task_save.c"
|
||||
#include "../tasks/task_image.c"
|
||||
#include "../tasks/task_file_transfer.c"
|
||||
#ifdef HAVE_ZLIB
|
||||
@ -888,12 +895,16 @@ MENU
|
||||
#ifdef HAVE_MENU
|
||||
#include "../menu/menu_driver.c"
|
||||
#include "../menu/menu_input.c"
|
||||
#include "../menu/menu_entry.c"
|
||||
#include "../menu/menu_event.c"
|
||||
#include "../menu/menu_entries.c"
|
||||
#include "../menu/menu_setting.c"
|
||||
#include "../menu/menu_cbs.c"
|
||||
#include "../menu/menu_content.c"
|
||||
#include "../menu/widgets/menu_popup.c"
|
||||
#include "../menu/widgets/menu_entry.c"
|
||||
#include "../menu/widgets/menu_dialog.c"
|
||||
#include "../menu/widgets/menu_input_dialog.c"
|
||||
#include "../menu/widgets/menu_input_bind_dialog.c"
|
||||
#include "../menu/widgets/menu_list.c"
|
||||
#include "../menu/cbs/menu_cbs_ok.c"
|
||||
#include "../menu/cbs/menu_cbs_cancel.c"
|
||||
#include "../menu/cbs/menu_cbs_select.c"
|
||||
@ -1046,7 +1057,7 @@ HTTP SERVER
|
||||
============================================================ */
|
||||
#if defined(HAVE_HTTPSERVER) && defined(HAVE_ZLIB)
|
||||
#include "../deps/civetweb/civetweb.c"
|
||||
#include "httpserver/httpserver.c"
|
||||
#include "network/httpserver/httpserver.c"
|
||||
#endif
|
||||
|
||||
#ifdef __cplusplus
|
||||
|
@ -1,15 +0,0 @@
|
||||
#ifndef __RARCH_HTTPSERVR_H
|
||||
#define __RARCH_HTTPSERVR_H
|
||||
|
||||
#ifdef __cplusplus
|
||||
extern "C" {
|
||||
#endif
|
||||
|
||||
int httpserver_init(unsigned port);
|
||||
void httpserver_destroy(void);
|
||||
|
||||
#ifdef __cplusplus
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif /* __RARCH_HTTPSERVR_H */
|
@ -375,6 +375,9 @@ static void udev_input_poll(void *data)
|
||||
struct epoll_event events[32];
|
||||
udev_input_t *udev = (udev_input_t*)data;
|
||||
|
||||
if (!udev)
|
||||
return;
|
||||
|
||||
udev->mouse_x = udev->mouse_y = 0;
|
||||
udev->mouse_wu = udev->mouse_wd = 0;
|
||||
udev->mouse_whu = udev->mouse_whd = 0;
|
||||
@ -457,9 +460,10 @@ static int16_t udev_lightgun_state(udev_input_t *udev, unsigned id)
|
||||
|
||||
static int16_t udev_analog_pressed(const struct retro_keybind *binds, unsigned idx, unsigned id)
|
||||
{
|
||||
unsigned id_minus = 0;
|
||||
unsigned id_plus = 0;
|
||||
int16_t pressed_minus = 0, pressed_plus = 0;
|
||||
unsigned id_minus = 0;
|
||||
unsigned id_plus = 0;
|
||||
int16_t pressed_minus = 0;
|
||||
int16_t pressed_plus = 0;
|
||||
|
||||
input_conv_analog_id_to_bind_id(idx, id, &id_minus, &id_plus);
|
||||
|
||||
@ -647,7 +651,7 @@ static bool open_devices(udev_input_t *udev, const char *type, device_handle_cb
|
||||
static void *udev_input_init(void)
|
||||
{
|
||||
settings_t *settings = config_get_ptr();
|
||||
udev_input_t *udev = (udev_input_t*)calloc(1, sizeof(*udev));
|
||||
udev_input_t *udev = (udev_input_t*)calloc(1, sizeof(*udev));
|
||||
|
||||
if (!udev)
|
||||
return NULL;
|
||||
|
@ -187,15 +187,17 @@ static void iohidmanager_hid_device_input_callback(void *data, IOReturn result,
|
||||
default:
|
||||
{
|
||||
int i;
|
||||
// +0/-0 => Left Stick Horizontal => 48
|
||||
// +1/-1 => Left Stick Vertical => 49
|
||||
// +2/-2 => Right Stick Horizontal => 51
|
||||
// +3/-3 => Right Stick Vertical => 52
|
||||
// +4/-4 => Left Trigger (if exists) => 50
|
||||
// +5/-5 => Right Trigger (if exists) => 53
|
||||
static const uint32_t axis_use_ids[6] =
|
||||
{ 48, 49, 51, 52, 50, 53 };
|
||||
|
||||
/* +0/-0 => Left Stick Horizontal => 48
|
||||
* +1/-1 => Left Stick Vertical => 49
|
||||
* +2/-2 => Right Stick Horizontal => 51
|
||||
* +3/-3 => Right Stick Vertical => 52
|
||||
* +4/-4 => Left Trigger (if exists) => 50
|
||||
* +5/-5 => Right Trigger (if exists) => 53
|
||||
*/
|
||||
|
||||
for (i = 0; i < 6; i ++)
|
||||
{
|
||||
CFIndex min = IOHIDElementGetPhysicalMin(element);
|
||||
@ -262,13 +264,10 @@ static int32_t iohidmanager_hid_device_get_int_property(
|
||||
int32_t value;
|
||||
CFNumberRef ref = (CFNumberRef)IOHIDDeviceGetProperty(device, key);
|
||||
|
||||
if (ref)
|
||||
if (ref && (CFGetTypeID(ref) == CFNumberGetTypeID()))
|
||||
{
|
||||
if (CFGetTypeID(ref) == CFNumberGetTypeID())
|
||||
{
|
||||
CFNumberGetValue((CFNumberRef)ref, kCFNumberIntType, &value);
|
||||
return value;
|
||||
}
|
||||
CFNumberGetValue((CFNumberRef)ref, kCFNumberIntType, &value);
|
||||
return value;
|
||||
}
|
||||
|
||||
return 0;
|
||||
@ -410,15 +409,13 @@ static int iohidmanager_hid_manager_init(iohidmanager_hid_t *hid)
|
||||
|
||||
hid->ptr = IOHIDManagerCreate(kCFAllocatorDefault, kIOHIDOptionsTypeNone);
|
||||
|
||||
if (hid->ptr)
|
||||
{
|
||||
IOHIDManagerSetDeviceMatching(hid->ptr, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hid->ptr, CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode);
|
||||
return 0;
|
||||
}
|
||||
if (!hid->ptr)
|
||||
return -1;
|
||||
|
||||
return -1;
|
||||
IOHIDManagerSetDeviceMatching(hid->ptr, NULL);
|
||||
IOHIDManagerScheduleWithRunLoop(hid->ptr, CFRunLoopGetCurrent(),
|
||||
kCFRunLoopDefaultMode);
|
||||
return 0;
|
||||
}
|
||||
|
||||
|
||||
@ -469,6 +466,7 @@ static void *iohidmanager_hid_init(void)
|
||||
if (!hid_apple)
|
||||
goto error;
|
||||
hid_apple->slots = pad_connection_init(MAX_USERS);
|
||||
|
||||
if (!hid_apple->slots)
|
||||
goto error;
|
||||
if (iohidmanager_hid_manager_init(hid_apple) == -1)
|
||||
|
@ -21,7 +21,7 @@
|
||||
#include "../../configuration.h"
|
||||
|
||||
#if defined(SN_TARGET_PSP2) || defined(VITA)
|
||||
#define PSP_MAX_PADS 2
|
||||
#define PSP_MAX_PADS 4
|
||||
#else
|
||||
#define PSP_MAX_PADS 1
|
||||
#endif
|
||||
@ -148,7 +148,7 @@ static void psp_joypad_poll(void)
|
||||
* can be 0 or 1 to read the first controller on
|
||||
* a PSTV, but HAS to be 0 for a real VITA and 2
|
||||
* for the 2nd controller on a PSTV */
|
||||
unsigned p = (player == 1) ? 2 : player;
|
||||
unsigned p = (player > 0) ? player+1 : player;
|
||||
int32_t ret = CtrlPeekBufferPositive(p, &state_tmp, 1);
|
||||
|
||||
pad_state[i] = 0;
|
||||
|
@ -13,6 +13,8 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#include "keyboard_event_android.h"
|
||||
|
||||
#define AKEYCODE_ASSIST 219
|
||||
|
@ -13,6 +13,12 @@
|
||||
* If not, see <http://www.gnu.org/licenses/>.
|
||||
*/
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#include "../input_keymaps.h"
|
||||
#include "../input_keyboard.h"
|
||||
#include "../../driver.h"
|
||||
|
@ -18,15 +18,19 @@
|
||||
#include <X11/Xutil.h>
|
||||
#include <X11/extensions/xf86vmode.h>
|
||||
|
||||
#ifdef HAVE_XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
|
||||
#include <boolean.h>
|
||||
#include <retro_inline.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "../../config.h"
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_XINERAMA
|
||||
#include <X11/extensions/Xinerama.h>
|
||||
#endif
|
||||
|
||||
#include "../input_keyboard.h"
|
||||
#include "../input_keymaps.h"
|
||||
|
||||
|
@ -103,23 +103,18 @@ static int input_try_autoconfigure_joypad_from_conf(config_file_t *conf,
|
||||
&& params->pid != 0
|
||||
&& input_vid != 0
|
||||
&& input_pid != 0)
|
||||
{
|
||||
score += 3;
|
||||
}
|
||||
|
||||
/* Check for name match */
|
||||
if (string_is_equal(ident, params->name))
|
||||
{
|
||||
score += 2;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!string_is_empty(ident)
|
||||
&& !strncmp(params->name, ident, strlen(ident)))
|
||||
{
|
||||
score += 1;
|
||||
}
|
||||
}
|
||||
|
||||
return score;
|
||||
}
|
||||
|
||||
@ -225,7 +220,8 @@ static bool input_autoconfigure_joypad_from_conf_dir(
|
||||
for (i = 0; i < list->size; i++)
|
||||
{
|
||||
conf = config_file_new(list->elems[i].data);
|
||||
ret = input_try_autoconfigure_joypad_from_conf(conf, params);
|
||||
ret = input_try_autoconfigure_joypad_from_conf(conf, params);
|
||||
|
||||
if(ret >= current_best)
|
||||
{
|
||||
index = i;
|
||||
|
@ -99,7 +99,7 @@ struct turbo_buttons
|
||||
|
||||
static turbo_buttons_t input_driver_turbo_btns;
|
||||
#ifdef HAVE_COMMAND
|
||||
static command_t *input_driver_command = NULL;
|
||||
static command_t *input_driver_command = NULL;
|
||||
#endif
|
||||
#ifdef HAVE_NETWORKGAMEPAD
|
||||
static input_remote_t *input_driver_remote = NULL;
|
||||
|
@ -27,10 +27,6 @@
|
||||
#include "input_joypad_driver.h"
|
||||
#include "input_defines.h"
|
||||
|
||||
#ifdef HAVE_OVERLAY
|
||||
#include "input_overlay.h"
|
||||
#endif
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
typedef struct retro_input
|
||||
|
@ -1110,12 +1110,18 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
{
|
||||
switch (msg)
|
||||
{
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE:
|
||||
case MENU_ENUM_LABEL_VALUE_PARENT_DIRECTORY:
|
||||
return "Directory precedente";
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_ICADE_ENABLE:
|
||||
return "Abilita mappatura gamepad tastiera";
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_KEYBOARD_GAMEPAD_MAPPING_TYPE:
|
||||
return "Tipologia di mappatura gamepad tastiera";
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_SMALL_KEYBOARD_ENABLE:
|
||||
return "Abilita tastiera ridotta";
|
||||
case MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_CORE:
|
||||
return "Salva override del core";
|
||||
case MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG_OVERRIDE_GAME:
|
||||
return "Salva override di gioco";
|
||||
case MENU_ENUM_LABEL_VALUE_SAVE_CURRENT_CONFIG:
|
||||
return "Salva configurazione attuale";
|
||||
case MENU_ENUM_LABEL_VALUE_STATE_SLOT:
|
||||
@ -1187,7 +1193,7 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
case MENU_ENUM_LABEL_VALUE_UPDATE_CORE_INFO_FILES:
|
||||
return "Aggiorna i files info dei core";
|
||||
case MENU_ENUM_LABEL_VALUE_DOWNLOAD_CORE_CONTENT:
|
||||
return "Contenuto scaricato";
|
||||
return "Scarica contenuto";
|
||||
case MENU_ENUM_LABEL_VALUE_SCAN_THIS_DIRECTORY:
|
||||
return "<Scansiona questa directory>";
|
||||
case MENU_ENUM_LABEL_VALUE_SCAN_FILE:
|
||||
@ -1353,6 +1359,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Directory degli asset";
|
||||
case MENU_ENUM_LABEL_VALUE_DYNAMIC_WALLPAPERS_DIRECTORY:
|
||||
return "Directory degli sfondi dinamici";
|
||||
case MENU_ENUM_LABEL_VALUE_THUMBNAILS_DIRECTORY:
|
||||
return "Directory delle miniature";
|
||||
case MENU_ENUM_LABEL_VALUE_RGUI_BROWSER_DIRECTORY:
|
||||
return "Directory di selezione file";
|
||||
case MENU_ENUM_LABEL_VALUE_RGUI_CONFIG_DIRECTORY:
|
||||
@ -1419,6 +1427,30 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Abilita DPI Override";
|
||||
case MENU_ENUM_LABEL_VALUE_DPI_OVERRIDE_VALUE:
|
||||
return "DPI Override";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SCALE_FACTOR:
|
||||
return "Fattore di scala del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_ALPHA_FACTOR:
|
||||
return "Fattore alpha del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_FONT:
|
||||
return "Carattere del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_THEME:
|
||||
return "Icona a tema del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_MENU_COLOR_THEME:
|
||||
return "Colore tema del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_MATERIALUI_MENU_COLOR_THEME:
|
||||
return "Colore tema del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHADOWS_ENABLE:
|
||||
return "Abilità ombre per l'icona";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHOW_SETTINGS:
|
||||
return "Mostra scheda settaggi";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHOW_IMAGES:
|
||||
return "Mostra scheda immagini";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHOW_MUSIC:
|
||||
return "Mostra scheda musica";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHOW_VIDEO:
|
||||
return "Mostra scheda video";
|
||||
case MENU_ENUM_LABEL_VALUE_XMB_SHOW_HISTORY:
|
||||
return "Mostra scheda storia";
|
||||
case MENU_ENUM_LABEL_VALUE_SUSPEND_SCREENSAVER_ENABLE:
|
||||
return "Spegni salvaschermo";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_DISABLE_COMPOSITION:
|
||||
@ -1445,8 +1477,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Fotogrammi stimati del monitor";
|
||||
case MENU_ENUM_LABEL_VALUE_DUMMY_ON_CORE_SHUTDOWN:
|
||||
return "Valore fittizio sull'arresto del core";
|
||||
case MENU_ENUM_LABEL_VALUE_CORE_SET_SUPPORTS_NO_CONTENT_ENABLE: /* TODO/FIXME */
|
||||
return "Non avviare automaticamente un core";
|
||||
case MENU_ENUM_LABEL_VALUE_CORE_SET_SUPPORTS_NO_CONTENT_ENABLE:
|
||||
return "Avvia automaticamente un core";
|
||||
case MENU_ENUM_LABEL_VALUE_FRAME_THROTTLE_ENABLE:
|
||||
return "Limita la velocità massima di caricamento";
|
||||
case MENU_ENUM_LABEL_VALUE_FASTFORWARD_RATIO:
|
||||
@ -1454,7 +1486,11 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
case MENU_ENUM_LABEL_VALUE_AUTO_REMAPS_ENABLE:
|
||||
return "Carica file di rimappatura automaticamente";
|
||||
case MENU_ENUM_LABEL_VALUE_SLOWMOTION_RATIO:
|
||||
return "Slow-Motion Ratio";
|
||||
return "Rapporto di slow-motion";
|
||||
case MENU_ENUM_LABEL_VALUE_MENU_LINEAR_FILTER:
|
||||
return "Filtro lineare del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_MENU_ENUM_THROTTLE_FRAMERATE:
|
||||
return "Frequenza fotogrammi del menù";
|
||||
case MENU_ENUM_LABEL_VALUE_CORE_SPECIFIC_CONFIG:
|
||||
return "Configurazione per core";
|
||||
case MENU_ENUM_LABEL_VALUE_GAME_SPECIFIC_OPTIONS:
|
||||
@ -1465,6 +1501,10 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Carica file di override automaticamente";
|
||||
case MENU_ENUM_LABEL_VALUE_CONFIG_SAVE_ON_EXIT:
|
||||
return "Salva configurazione all'uscita";
|
||||
case MENU_ENUM_LABEL_VALUE_CONFIRM_ON_EXIT:
|
||||
return "Chiedi conferma all'uscita";
|
||||
case MENU_ENUM_LABEL_VALUE_SHOW_HIDDEN_FILES:
|
||||
return "Mostra files e cartelle nascoste";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_SMOOTH:
|
||||
return "Filtro bilineare hardware";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_GAMMA:
|
||||
@ -1475,6 +1515,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Sincronizza GPU";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_SWAP_INTERVAL:
|
||||
return "Intervallo di swap vsync";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_MAX_SWAPCHAIN_IMAGES:
|
||||
return "Massimo swapchain di immagini";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_VSYNC:
|
||||
return "VSync";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_THREADED:
|
||||
@ -1587,8 +1629,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Collezione";
|
||||
case MENU_ENUM_LABEL_VALUE_DETECT_CORE_LIST:
|
||||
return "Seleziona il file ed intercetta il core";
|
||||
case MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST: /* TODO/FIXME - rewrite */
|
||||
return "Seleziona file scaricati ed intercetta il core";
|
||||
case MENU_ENUM_LABEL_VALUE_DOWNLOADED_FILE_DETECT_CORE_LIST:
|
||||
return "Scarica directories";
|
||||
case MENU_ENUM_LABEL_VALUE_LOAD_CONTENT_HISTORY:
|
||||
return "Carica Recenti";
|
||||
case MENU_ENUM_LABEL_VALUE_AUDIO_ENABLE:
|
||||
@ -1633,6 +1675,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Contatore dei core";
|
||||
case MENU_ENUM_LABEL_VALUE_TAKE_SCREENSHOT:
|
||||
return "Cattura Screenshot";
|
||||
case MENU_ENUM_LABEL_VALUE_DELETE_ENTRY:
|
||||
return "Rimuovi dalla Playlist";
|
||||
case MENU_ENUM_LABEL_VALUE_RESUME:
|
||||
return "Riprendi";
|
||||
case MENU_ENUM_LABEL_VALUE_DISK_INDEX:
|
||||
@ -1682,7 +1726,7 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
case MENU_ENUM_LABEL_VALUE_NAVIGATION_WRAPAROUND:
|
||||
return "Navigazione avvolgente";
|
||||
case MENU_ENUM_LABEL_VALUE_NAVIGATION_BROWSER_FILTER_SUPPORTED_EXTENSIONS_ENABLE:
|
||||
return "Filtra con estensioni supportate"; /* TODO/FIXME - rewrite */
|
||||
return "Filtra estensioni sconosciute";
|
||||
case MENU_ENUM_LABEL_VALUE_CORE_UPDATER_AUTO_EXTRACT_ARCHIVE:
|
||||
return "Estrai automaticamente gli archivi scaricati";
|
||||
case MENU_ENUM_LABEL_VALUE_SYSTEM_INFORMATION:
|
||||
@ -1709,6 +1753,12 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Salva stato";
|
||||
case MENU_ENUM_LABEL_VALUE_LOAD_STATE:
|
||||
return "Carica stato";
|
||||
case MENU_ENUM_LABEL_VALUE_UNDO_LOAD_STATE:
|
||||
return "Annulla carica stato";
|
||||
case MENU_ENUM_LABEL_VALUE_UNDO_SAVE_STATE:
|
||||
return "Annulla salva stato";
|
||||
case MSG_UNDID_LOAD_STATE:
|
||||
return "Annullato carica stato.";
|
||||
case MENU_ENUM_LABEL_VALUE_RESUME_CONTENT:
|
||||
return "Riprendi";
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_DRIVER:
|
||||
@ -1747,7 +1797,9 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Sfondo dinamico";
|
||||
case MENU_ENUM_LABEL_VALUE_CORE_INPUT_REMAPPING_OPTIONS:
|
||||
return "Opzioni di rimappatura degli input del core";
|
||||
case MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS: /* UPDATE/FIXME */
|
||||
case MENU_ENUM_LABEL_VALUE_THUMBNAILS:
|
||||
return "Miniature";
|
||||
case MENU_ENUM_LABEL_VALUE_SHADER_OPTIONS:
|
||||
return "Shaders";
|
||||
case MENU_ENUM_LABEL_VALUE_VIDEO_SHADER_PARAMETERS:
|
||||
return "Antemprima Parametri Shader";
|
||||
@ -2063,6 +2115,8 @@ const char *msg_hash_to_str_it(enum msg_hash_enums msg)
|
||||
return "Avvia Core";
|
||||
case MENU_ENUM_LABEL_VALUE_INPUT_POLL_TYPE_BEHAVIOR:
|
||||
return "Tipo di ritardo";
|
||||
case MENU_ENUM_LABEL_VALUE_MENU_WALLPAPER_OPACITY:
|
||||
return "Opacità dello sfondo";
|
||||
default:
|
||||
break;
|
||||
}
|
||||
|
@ -1558,6 +1558,22 @@ int menu_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
|
||||
"Increasing this value will increase \n"
|
||||
"performance, but introduce more latency.");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_NETPLAY_CHECK_FRAMES:
|
||||
snprintf(s, len,
|
||||
"The frequency in frames with which netplay \n"
|
||||
"will verify that the host and client are in \n"
|
||||
"sync. \n"
|
||||
" \n"
|
||||
"With most cores, this value will have no \n"
|
||||
"visible effect and can be ignored. With \n"
|
||||
"nondeterminstic cores, this value determines \n"
|
||||
"how often the netplay peers will be brought \n"
|
||||
"into sync. With buggy cores, setting this \n"
|
||||
"to any non-zero value will cause severe \n"
|
||||
"performance issues. Set to zero to perform \n"
|
||||
"no checks. This value is only used on the \n"
|
||||
"netplay host. \n");
|
||||
break;
|
||||
case MENU_ENUM_LABEL_VIDEO_MAX_SWAPCHAIN_IMAGES:
|
||||
snprintf(s, len,
|
||||
"Maximum amount of swapchain images. This \n"
|
||||
@ -2424,6 +2440,8 @@ static const char *menu_hash_to_str_us_label_enum(enum msg_hash_enums msg)
|
||||
return "bluetooth_enable";
|
||||
case MENU_ENUM_LABEL_NETPLAY_DELAY_FRAMES:
|
||||
return "netplay_delay_frames";
|
||||
case MENU_ENUM_LABEL_NETPLAY_CHECK_FRAMES:
|
||||
return "netplay_check_frames";
|
||||
case MENU_ENUM_LABEL_NETPLAY_MODE:
|
||||
return "netplay_mode";
|
||||
case MENU_ENUM_LABEL_RGUI_SHOW_START_SCREEN:
|
||||
@ -3747,6 +3765,8 @@ const char *msg_hash_to_str_us(enum msg_hash_enums msg)
|
||||
return "Bluetooth Enable";
|
||||
case MENU_ENUM_LABEL_VALUE_NETPLAY_DELAY_FRAMES:
|
||||
return "Netplay Delay Frames";
|
||||
case MENU_ENUM_LABEL_VALUE_NETPLAY_CHECK_FRAMES:
|
||||
return "Netplay Check Frames";
|
||||
case MENU_ENUM_LABEL_VALUE_NETPLAY_MODE:
|
||||
return "Netplay Client Enable";
|
||||
case MENU_ENUM_LABEL_VALUE_RGUI_SHOW_START_SCREEN:
|
||||
|
89
libretro-common/encodings/encoding_crc32.c
Normal file
89
libretro-common/encodings/encoding_crc32.c
Normal file
@ -0,0 +1,89 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (encoding_crc32.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
static const uint32_t crc32_table[256] = {
|
||||
0x00000000L, 0x77073096L, 0xee0e612cL, 0x990951baL, 0x076dc419L,
|
||||
0x706af48fL, 0xe963a535L, 0x9e6495a3L, 0x0edb8832L, 0x79dcb8a4L,
|
||||
0xe0d5e91eL, 0x97d2d988L, 0x09b64c2bL, 0x7eb17cbdL, 0xe7b82d07L,
|
||||
0x90bf1d91L, 0x1db71064L, 0x6ab020f2L, 0xf3b97148L, 0x84be41deL,
|
||||
0x1adad47dL, 0x6ddde4ebL, 0xf4d4b551L, 0x83d385c7L, 0x136c9856L,
|
||||
0x646ba8c0L, 0xfd62f97aL, 0x8a65c9ecL, 0x14015c4fL, 0x63066cd9L,
|
||||
0xfa0f3d63L, 0x8d080df5L, 0x3b6e20c8L, 0x4c69105eL, 0xd56041e4L,
|
||||
0xa2677172L, 0x3c03e4d1L, 0x4b04d447L, 0xd20d85fdL, 0xa50ab56bL,
|
||||
0x35b5a8faL, 0x42b2986cL, 0xdbbbc9d6L, 0xacbcf940L, 0x32d86ce3L,
|
||||
0x45df5c75L, 0xdcd60dcfL, 0xabd13d59L, 0x26d930acL, 0x51de003aL,
|
||||
0xc8d75180L, 0xbfd06116L, 0x21b4f4b5L, 0x56b3c423L, 0xcfba9599L,
|
||||
0xb8bda50fL, 0x2802b89eL, 0x5f058808L, 0xc60cd9b2L, 0xb10be924L,
|
||||
0x2f6f7c87L, 0x58684c11L, 0xc1611dabL, 0xb6662d3dL, 0x76dc4190L,
|
||||
0x01db7106L, 0x98d220bcL, 0xefd5102aL, 0x71b18589L, 0x06b6b51fL,
|
||||
0x9fbfe4a5L, 0xe8b8d433L, 0x7807c9a2L, 0x0f00f934L, 0x9609a88eL,
|
||||
0xe10e9818L, 0x7f6a0dbbL, 0x086d3d2dL, 0x91646c97L, 0xe6635c01L,
|
||||
0x6b6b51f4L, 0x1c6c6162L, 0x856530d8L, 0xf262004eL, 0x6c0695edL,
|
||||
0x1b01a57bL, 0x8208f4c1L, 0xf50fc457L, 0x65b0d9c6L, 0x12b7e950L,
|
||||
0x8bbeb8eaL, 0xfcb9887cL, 0x62dd1ddfL, 0x15da2d49L, 0x8cd37cf3L,
|
||||
0xfbd44c65L, 0x4db26158L, 0x3ab551ceL, 0xa3bc0074L, 0xd4bb30e2L,
|
||||
0x4adfa541L, 0x3dd895d7L, 0xa4d1c46dL, 0xd3d6f4fbL, 0x4369e96aL,
|
||||
0x346ed9fcL, 0xad678846L, 0xda60b8d0L, 0x44042d73L, 0x33031de5L,
|
||||
0xaa0a4c5fL, 0xdd0d7cc9L, 0x5005713cL, 0x270241aaL, 0xbe0b1010L,
|
||||
0xc90c2086L, 0x5768b525L, 0x206f85b3L, 0xb966d409L, 0xce61e49fL,
|
||||
0x5edef90eL, 0x29d9c998L, 0xb0d09822L, 0xc7d7a8b4L, 0x59b33d17L,
|
||||
0x2eb40d81L, 0xb7bd5c3bL, 0xc0ba6cadL, 0xedb88320L, 0x9abfb3b6L,
|
||||
0x03b6e20cL, 0x74b1d29aL, 0xead54739L, 0x9dd277afL, 0x04db2615L,
|
||||
0x73dc1683L, 0xe3630b12L, 0x94643b84L, 0x0d6d6a3eL, 0x7a6a5aa8L,
|
||||
0xe40ecf0bL, 0x9309ff9dL, 0x0a00ae27L, 0x7d079eb1L, 0xf00f9344L,
|
||||
0x8708a3d2L, 0x1e01f268L, 0x6906c2feL, 0xf762575dL, 0x806567cbL,
|
||||
0x196c3671L, 0x6e6b06e7L, 0xfed41b76L, 0x89d32be0L, 0x10da7a5aL,
|
||||
0x67dd4accL, 0xf9b9df6fL, 0x8ebeeff9L, 0x17b7be43L, 0x60b08ed5L,
|
||||
0xd6d6a3e8L, 0xa1d1937eL, 0x38d8c2c4L, 0x4fdff252L, 0xd1bb67f1L,
|
||||
0xa6bc5767L, 0x3fb506ddL, 0x48b2364bL, 0xd80d2bdaL, 0xaf0a1b4cL,
|
||||
0x36034af6L, 0x41047a60L, 0xdf60efc3L, 0xa867df55L, 0x316e8eefL,
|
||||
0x4669be79L, 0xcb61b38cL, 0xbc66831aL, 0x256fd2a0L, 0x5268e236L,
|
||||
0xcc0c7795L, 0xbb0b4703L, 0x220216b9L, 0x5505262fL, 0xc5ba3bbeL,
|
||||
0xb2bd0b28L, 0x2bb45a92L, 0x5cb36a04L, 0xc2d7ffa7L, 0xb5d0cf31L,
|
||||
0x2cd99e8bL, 0x5bdeae1dL, 0x9b64c2b0L, 0xec63f226L, 0x756aa39cL,
|
||||
0x026d930aL, 0x9c0906a9L, 0xeb0e363fL, 0x72076785L, 0x05005713L,
|
||||
0x95bf4a82L, 0xe2b87a14L, 0x7bb12baeL, 0x0cb61b38L, 0x92d28e9bL,
|
||||
0xe5d5be0dL, 0x7cdcefb7L, 0x0bdbdf21L, 0x86d3d2d4L, 0xf1d4e242L,
|
||||
0x68ddb3f8L, 0x1fda836eL, 0x81be16cdL, 0xf6b9265bL, 0x6fb077e1L,
|
||||
0x18b74777L, 0x88085ae6L, 0xff0f6a70L, 0x66063bcaL, 0x11010b5cL,
|
||||
0x8f659effL, 0xf862ae69L, 0x616bffd3L, 0x166ccf45L, 0xa00ae278L,
|
||||
0xd70dd2eeL, 0x4e048354L, 0x3903b3c2L, 0xa7672661L, 0xd06016f7L,
|
||||
0x4969474dL, 0x3e6e77dbL, 0xaed16a4aL, 0xd9d65adcL, 0x40df0b66L,
|
||||
0x37d83bf0L, 0xa9bcae53L, 0xdebb9ec5L, 0x47b2cf7fL, 0x30b5ffe9L,
|
||||
0xbdbdf21cL, 0xcabac28aL, 0x53b39330L, 0x24b4a3a6L, 0xbad03605L,
|
||||
0xcdd70693L, 0x54de5729L, 0x23d967bfL, 0xb3667a2eL, 0xc4614ab8L,
|
||||
0x5d681b02L, 0x2a6f2b94L, 0xb40bbe37L, 0xc30c8ea1L, 0x5a05df1bL,
|
||||
0x2d02ef8dL
|
||||
};
|
||||
|
||||
uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len)
|
||||
{
|
||||
crc = crc ^ 0xffffffff;
|
||||
|
||||
while (len--)
|
||||
crc = crc32_table[(crc ^ (*buf++)) & 0xff] ^ (crc >> 8);
|
||||
|
||||
return crc ^ 0xffffffff;
|
||||
}
|
@ -1,7 +1,7 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (encodings_utf.c).
|
||||
* The following license statement only applies to this file (encoding_utf.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
@ -21,6 +21,7 @@
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stdlib.h>
|
||||
#include <stddef.h>
|
||||
#include <string.h>
|
||||
|
||||
@ -40,7 +41,7 @@ static INLINE unsigned leading_ones(uint8_t c)
|
||||
return ones;
|
||||
}
|
||||
|
||||
/* Simple implementation. Assumes the sequence is
|
||||
/* Simple implementation. Assumes the sequence is
|
||||
* properly synchronized and terminated. */
|
||||
|
||||
size_t utf8_conv_utf32(uint32_t *out, size_t out_chars,
|
||||
@ -119,14 +120,14 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||
if (value < (((uint32_t)1) << (numAdds * 5 + 6)))
|
||||
break;
|
||||
if (out)
|
||||
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
|
||||
out[out_pos] = (char)(kUtf8Limits[numAdds - 1]
|
||||
+ (value >> (6 * numAdds)));
|
||||
out_pos++;
|
||||
do
|
||||
{
|
||||
numAdds--;
|
||||
if (out)
|
||||
out[out_pos] = (char)(0x80
|
||||
out[out_pos] = (char)(0x80
|
||||
+ ((value >> (6 * numAdds)) & 0x3F));
|
||||
out_pos++;
|
||||
}while (numAdds != 0);
|
||||
@ -136,13 +137,13 @@ bool utf16_conv_utf8(uint8_t *out, size_t *out_chars,
|
||||
return false;
|
||||
}
|
||||
|
||||
/* Acts mostly like strlcpy.
|
||||
/* Acts mostly like strlcpy.
|
||||
*
|
||||
* Copies the given number of UTF-8 characters,
|
||||
* Copies the given number of UTF-8 characters,
|
||||
* but at most d_len bytes.
|
||||
*
|
||||
* Always NULL terminates.
|
||||
* Does not copy half a character.
|
||||
* Always NULL terminates.
|
||||
* Does not copy half a character.
|
||||
*
|
||||
* Returns number of bytes. 's' is assumed valid UTF-8.
|
||||
* Use only if 'chars' is considerably less than 'd_len'. */
|
||||
@ -205,20 +206,55 @@ uint32_t utf8_walk(const char **string)
|
||||
{
|
||||
uint8_t first = utf8_walkbyte(string);
|
||||
uint32_t ret;
|
||||
|
||||
|
||||
if (first<128)
|
||||
return first;
|
||||
|
||||
|
||||
ret = 0;
|
||||
ret = (ret<<6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xE0)
|
||||
ret = (ret<<6) | (utf8_walkbyte(string) & 0x3F);
|
||||
if (first >= 0xF0)
|
||||
ret = (ret<<6) | (utf8_walkbyte(string) & 0x3F);
|
||||
|
||||
|
||||
if (first >= 0xF0)
|
||||
return ret | (first&31)<<18;
|
||||
if (first >= 0xE0)
|
||||
return ret | (first&15)<<12;
|
||||
return ret | (first&7)<<6;
|
||||
}
|
||||
|
||||
static bool utf16_to_char(uint8_t **utf_data,
|
||||
size_t *dest_len, const uint16_t *in)
|
||||
{
|
||||
unsigned len = 0;
|
||||
|
||||
while (in[len] != '\0')
|
||||
len++;
|
||||
|
||||
utf16_conv_utf8(NULL, dest_len, in, len);
|
||||
*dest_len += 1;
|
||||
*utf_data = (uint8_t*)malloc(*dest_len);
|
||||
if (*utf_data == 0)
|
||||
return false;
|
||||
|
||||
return utf16_conv_utf8(*utf_data, dest_len, in, len);
|
||||
}
|
||||
|
||||
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len)
|
||||
{
|
||||
size_t dest_len = 0;
|
||||
uint8_t *utf16_data = NULL;
|
||||
bool ret = utf16_to_char(&utf16_data, &dest_len, in);
|
||||
|
||||
if (ret)
|
||||
{
|
||||
utf16_data[dest_len] = 0;
|
||||
strlcpy(s, (const char*)utf16_data, len);
|
||||
}
|
||||
|
||||
free(utf16_data);
|
||||
utf16_data = NULL;
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
@ -45,30 +45,7 @@
|
||||
#include <retro_stat.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <lists/string_list.h>
|
||||
|
||||
#ifndef CENTRAL_FILE_HEADER_SIGNATURE
|
||||
#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
|
||||
#endif
|
||||
|
||||
#ifndef END_OF_CENTRAL_DIR_SIGNATURE
|
||||
#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50
|
||||
#endif
|
||||
|
||||
struct zip_extract_userdata
|
||||
{
|
||||
char *zip_path;
|
||||
char *first_extracted_file_path;
|
||||
const char *extraction_directory;
|
||||
size_t zip_path_size;
|
||||
struct string_list *ext;
|
||||
bool found_content;
|
||||
};
|
||||
|
||||
enum file_archive_compression_mode
|
||||
{
|
||||
ZLIB_MODE_UNCOMPRESSED = 0,
|
||||
ZLIB_MODE_DEFLATE = 8
|
||||
};
|
||||
#include <string/stdstring.h>
|
||||
|
||||
typedef struct
|
||||
{
|
||||
@ -81,7 +58,7 @@ typedef struct
|
||||
|
||||
#ifdef HAVE_MMAP
|
||||
/* Closes, unmaps and frees. */
|
||||
static void file_archive_free(void *handle)
|
||||
void file_archive_free(void *handle)
|
||||
{
|
||||
file_archive_file_data_t *data = (file_archive_file_data_t*)handle;
|
||||
|
||||
@ -95,7 +72,7 @@ static void file_archive_free(void *handle)
|
||||
free(data);
|
||||
}
|
||||
|
||||
static const uint8_t *file_archive_data(void *handle)
|
||||
const uint8_t *file_archive_data(void *handle)
|
||||
{
|
||||
file_archive_file_data_t *data = (file_archive_file_data_t*)handle;
|
||||
if (!data)
|
||||
@ -146,16 +123,17 @@ error:
|
||||
#else
|
||||
|
||||
/* Closes, unmaps and frees. */
|
||||
static void file_archive_free(void *handle)
|
||||
void file_archive_free(void *handle)
|
||||
{
|
||||
file_archive_file_data_t *data = (file_archive_file_data_t*)handle;
|
||||
if (!data)
|
||||
return;
|
||||
free(data->data);
|
||||
if(data->data)
|
||||
free(data->data);
|
||||
free(data);
|
||||
}
|
||||
|
||||
static const uint8_t *file_archive_data(void *handle)
|
||||
const uint8_t *file_archive_data(void *handle)
|
||||
{
|
||||
file_archive_file_data_t *data = (file_archive_file_data_t*)handle;
|
||||
if (!data)
|
||||
@ -204,12 +182,12 @@ static int file_archive_get_file_list_cb(
|
||||
uint32_t csize,
|
||||
uint32_t size,
|
||||
uint32_t checksum,
|
||||
void *userdata)
|
||||
struct archive_extract_userdata *userdata)
|
||||
{
|
||||
union string_list_elem_attr attr;
|
||||
struct string_list *ext_list = NULL;
|
||||
const char *file_ext = NULL;
|
||||
struct string_list *list = (struct string_list*)userdata;
|
||||
size_t pathLen = strlen(path);
|
||||
|
||||
(void)cdata;
|
||||
(void)cmode;
|
||||
@ -219,13 +197,16 @@ static int file_archive_get_file_list_cb(
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
|
||||
if (!pathLen)
|
||||
return 0;
|
||||
|
||||
if (valid_exts)
|
||||
ext_list = string_split(valid_exts, "|");
|
||||
|
||||
if (ext_list)
|
||||
{
|
||||
/* Checks if this entry is a directory or a file. */
|
||||
char last_char = path[strlen(path)-1];
|
||||
char last_char = path[pathLen-1];
|
||||
|
||||
/* Skip if directory. */
|
||||
if (last_char == '/' || last_char == '\\' )
|
||||
@ -233,7 +214,7 @@ static int file_archive_get_file_list_cb(
|
||||
|
||||
file_ext = path_get_extension(path);
|
||||
|
||||
if (!file_ext ||
|
||||
if (!file_ext ||
|
||||
!string_list_find_elem_prefix(ext_list, ".", file_ext))
|
||||
goto error;
|
||||
|
||||
@ -241,8 +222,8 @@ static int file_archive_get_file_list_cb(
|
||||
string_list_free(ext_list);
|
||||
}
|
||||
|
||||
return string_list_append(list, path, attr);
|
||||
|
||||
return string_list_append(userdata->list, path, attr);
|
||||
|
||||
error:
|
||||
string_list_free(ext_list);
|
||||
return 0;
|
||||
@ -251,155 +232,78 @@ error:
|
||||
static int file_archive_extract_cb(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata,
|
||||
unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t checksum, void *userdata)
|
||||
uint32_t checksum, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
const char *ext = path_get_extension(name);
|
||||
struct zip_extract_userdata *data = (struct zip_extract_userdata*)userdata;
|
||||
|
||||
/* Extract first content that matches our list. */
|
||||
if (ext && string_list_find_elem(data->ext, ext))
|
||||
/* Extract first file that matches our list. */
|
||||
if (ext && string_list_find_elem(userdata->ext, ext))
|
||||
{
|
||||
char new_path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
if (data->extraction_directory)
|
||||
fill_pathname_join(new_path, data->extraction_directory,
|
||||
if (userdata->extraction_directory)
|
||||
fill_pathname_join(new_path, userdata->extraction_directory,
|
||||
path_basename(name), sizeof(new_path));
|
||||
else
|
||||
fill_pathname_resolve_relative(new_path, data->zip_path,
|
||||
fill_pathname_resolve_relative(new_path, userdata->archive_path,
|
||||
path_basename(name), sizeof(new_path));
|
||||
|
||||
data->first_extracted_file_path = strdup(new_path);
|
||||
data->found_content = file_archive_perform_mode(new_path,
|
||||
valid_exts, cdata, cmode, csize, size,
|
||||
0, NULL);
|
||||
userdata->first_extracted_file_path = strdup(new_path);
|
||||
|
||||
char wanted_file[PATH_MAX_LENGTH] = {0};
|
||||
const char *delim = path_get_archive_delim(userdata->archive_path);
|
||||
|
||||
if (delim)
|
||||
strlcpy(wanted_file, delim + 1, strlen(delim) + 1);
|
||||
|
||||
if (!string_is_equal_noncase(userdata->extracted_file_path,
|
||||
wanted_file))
|
||||
return 1; // keep searching for the right file
|
||||
|
||||
if (file_archive_perform_mode(new_path,
|
||||
valid_exts, cdata, cmode, csize, size,
|
||||
0, userdata))
|
||||
userdata->found_file = true;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t read_le(const uint8_t *data, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
uint32_t val = 0;
|
||||
|
||||
size *= 8;
|
||||
for (i = 0; i < size; i += 8)
|
||||
val |= (uint32_t)*data++ << i;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
static int file_archive_parse_file_iterate_step_internal(
|
||||
file_archive_transfer_t *state, char *filename,
|
||||
const uint8_t **cdata,
|
||||
unsigned *cmode, uint32_t *size, uint32_t *csize,
|
||||
uint32_t *checksum, unsigned *payback)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t namelength, extralength, commentlength,
|
||||
offsetNL, offsetEL;
|
||||
uint32_t signature = read_le(state->directory + 0, 4);
|
||||
|
||||
if (signature != CENTRAL_FILE_HEADER_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
*cmode = read_le(state->directory + 10, 2);
|
||||
*checksum = read_le(state->directory + 16, 4);
|
||||
*csize = read_le(state->directory + 20, 4);
|
||||
*size = read_le(state->directory + 24, 4);
|
||||
|
||||
namelength = read_le(state->directory + 28, 2);
|
||||
extralength = read_le(state->directory + 30, 2);
|
||||
commentlength = read_le(state->directory + 32, 2);
|
||||
|
||||
if (namelength >= PATH_MAX_LENGTH)
|
||||
return -1;
|
||||
|
||||
memcpy(filename, state->directory + 46, namelength);
|
||||
|
||||
offset = read_le(state->directory + 42, 4);
|
||||
offsetNL = read_le(state->data + offset + 26, 2);
|
||||
offsetEL = read_le(state->data + offset + 28, 2);
|
||||
|
||||
*cdata = state->data + offset + 30 + offsetNL + offsetEL;
|
||||
|
||||
*payback = 46 + namelength + extralength + commentlength;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_archive_parse_file_iterate_step(file_archive_transfer_t *state,
|
||||
const char *valid_exts, void *userdata, file_archive_file_cb file_cb)
|
||||
{
|
||||
const uint8_t *cdata = NULL;
|
||||
uint32_t checksum = 0;
|
||||
uint32_t size = 0;
|
||||
uint32_t csize = 0;
|
||||
unsigned cmode = 0;
|
||||
unsigned payload = 0;
|
||||
char filename[PATH_MAX_LENGTH] = {0};
|
||||
int ret = file_archive_parse_file_iterate_step_internal(state, filename,
|
||||
&cdata, &cmode, &size, &csize,
|
||||
&checksum, &payload);
|
||||
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
||||
#if 0
|
||||
RARCH_LOG("OFFSET: %u, CSIZE: %u, SIZE: %u.\n", offset + 30 +
|
||||
offsetNL + offsetEL, csize, size);
|
||||
#endif
|
||||
|
||||
if (!file_cb(filename, valid_exts, cdata, cmode,
|
||||
csize, size, checksum, userdata))
|
||||
return 0;
|
||||
|
||||
state->directory += payload;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int file_archive_parse_file_init(file_archive_transfer_t *state,
|
||||
int file_archive_parse_file_init(file_archive_transfer_t *state,
|
||||
const char *file)
|
||||
{
|
||||
state->backend = file_archive_get_default_file_backend();
|
||||
char *last = NULL;
|
||||
char path[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
strlcpy(path, file, sizeof(path));
|
||||
|
||||
last = (char*)path_get_archive_delim(path);
|
||||
|
||||
if (last)
|
||||
*last = '\0';
|
||||
|
||||
state->backend = file_archive_get_file_backend(path);
|
||||
if (!state->backend)
|
||||
return -1;
|
||||
|
||||
state->handle = file_archive_open(file);
|
||||
state->handle = file_archive_open(path);
|
||||
if (!state->handle)
|
||||
return -1;
|
||||
|
||||
state->zip_size = file_archive_size(state->handle);
|
||||
if (state->zip_size < 22)
|
||||
return -1;
|
||||
|
||||
state->archive_size = file_archive_size(state->handle);
|
||||
state->data = file_archive_data(state->handle);
|
||||
state->footer = state->data + state->zip_size - 22;
|
||||
state->footer = 0;
|
||||
state->directory = 0;
|
||||
|
||||
for (;; state->footer--)
|
||||
{
|
||||
if (state->footer <= state->data + 22)
|
||||
return -1;
|
||||
if (read_le(state->footer, 4) == END_OF_CENTRAL_DIR_SIGNATURE)
|
||||
{
|
||||
unsigned comment_len = read_le(state->footer + 20, 2);
|
||||
if (state->footer + 22 + comment_len == state->data + state->zip_size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state->directory = state->data + read_le(state->footer + 16, 4);
|
||||
|
||||
return 0;
|
||||
return state->backend->archive_parse_file_init(state, path);
|
||||
}
|
||||
|
||||
/**
|
||||
* file_archive_decompress_data_to_file:
|
||||
* @path : filename path of archive.
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
* @cdata : input data.
|
||||
* @csize : size of input data.
|
||||
@ -420,26 +324,21 @@ static int file_archive_decompress_data_to_file(
|
||||
uint32_t size,
|
||||
uint32_t checksum)
|
||||
{
|
||||
if (handle)
|
||||
{
|
||||
handle->backend->stream_free(handle->stream);
|
||||
free(handle->stream);
|
||||
}
|
||||
|
||||
if (!handle || ret == -1)
|
||||
{
|
||||
ret = 0;
|
||||
goto end;
|
||||
}
|
||||
|
||||
handle->real_checksum = handle->backend->stream_crc_calculate(
|
||||
0, handle->data, size);
|
||||
handle->backend->stream_free(handle->stream);
|
||||
|
||||
#if 0
|
||||
handle->real_checksum = handle->backend->stream_crc_calculate(
|
||||
0, handle->data, size);
|
||||
if (handle->real_checksum != checksum)
|
||||
{
|
||||
/* File CRC difers from ZIP CRC. */
|
||||
printf("File CRC differs from ZIP CRC. File: 0x%x, ZIP: 0x%x.\n",
|
||||
/* File CRC difers from archive CRC. */
|
||||
printf("File CRC differs from archive CRC. File: 0x%x, Archive: 0x%x.\n",
|
||||
(unsigned)handle->real_checksum, (unsigned)checksum);
|
||||
}
|
||||
#endif
|
||||
@ -456,82 +355,111 @@ end:
|
||||
return ret;
|
||||
}
|
||||
|
||||
void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state)
|
||||
{
|
||||
if (!state || !state->handle)
|
||||
return;
|
||||
|
||||
state->type = ARCHIVE_TRANSFER_DEINIT;
|
||||
file_archive_parse_file_iterate(state, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
int file_archive_parse_file_iterate(
|
||||
file_archive_transfer_t *state,
|
||||
bool *returnerr,
|
||||
const char *file,
|
||||
const char *valid_exts,
|
||||
file_archive_file_cb file_cb,
|
||||
void *userdata)
|
||||
struct archive_extract_userdata *userdata)
|
||||
{
|
||||
if (!state)
|
||||
return -1;
|
||||
|
||||
switch (state->type)
|
||||
{
|
||||
case ZLIB_TRANSFER_NONE:
|
||||
case ARCHIVE_TRANSFER_NONE:
|
||||
break;
|
||||
case ZLIB_TRANSFER_INIT:
|
||||
case ARCHIVE_TRANSFER_INIT:
|
||||
if (file_archive_parse_file_init(state, file) == 0)
|
||||
state->type = ZLIB_TRANSFER_ITERATE;
|
||||
else
|
||||
state->type = ZLIB_TRANSFER_DEINIT_ERROR;
|
||||
break;
|
||||
case ZLIB_TRANSFER_ITERATE:
|
||||
{
|
||||
int ret = file_archive_parse_file_iterate_step(state,
|
||||
valid_exts, userdata, file_cb);
|
||||
if (ret != 1)
|
||||
state->type = ZLIB_TRANSFER_DEINIT;
|
||||
if (ret == -1)
|
||||
state->type = ZLIB_TRANSFER_DEINIT_ERROR;
|
||||
if (userdata)
|
||||
userdata->context = state->stream;
|
||||
state->type = ARCHIVE_TRANSFER_ITERATE;
|
||||
}
|
||||
else
|
||||
state->type = ARCHIVE_TRANSFER_DEINIT_ERROR;
|
||||
break;
|
||||
case ARCHIVE_TRANSFER_ITERATE:
|
||||
{
|
||||
const struct file_archive_file_backend *backend =
|
||||
file_archive_get_file_backend(file);
|
||||
|
||||
if (backend)
|
||||
{
|
||||
int ret = backend->archive_parse_file_iterate_step(state,
|
||||
valid_exts, userdata, file_cb);
|
||||
if (ret != 1)
|
||||
state->type = ARCHIVE_TRANSFER_DEINIT;
|
||||
if (ret == -1)
|
||||
state->type = ARCHIVE_TRANSFER_DEINIT_ERROR;
|
||||
|
||||
/* early return to prevent deinit from never firing */
|
||||
return 0;
|
||||
}
|
||||
else
|
||||
return -1;
|
||||
}
|
||||
break;
|
||||
case ZLIB_TRANSFER_DEINIT_ERROR:
|
||||
case ARCHIVE_TRANSFER_DEINIT_ERROR:
|
||||
*returnerr = false;
|
||||
case ZLIB_TRANSFER_DEINIT:
|
||||
case ARCHIVE_TRANSFER_DEINIT:
|
||||
if (state->handle)
|
||||
{
|
||||
file_archive_free(state->handle);
|
||||
state->handle = NULL;
|
||||
state->handle = NULL;
|
||||
}
|
||||
if (state->stream && state->backend)
|
||||
{
|
||||
state->backend->stream_free(state->stream);
|
||||
|
||||
if (state->stream)
|
||||
free(state->stream);
|
||||
|
||||
state->stream = NULL;
|
||||
|
||||
if (userdata)
|
||||
userdata->context = NULL;
|
||||
}
|
||||
break;
|
||||
}
|
||||
|
||||
if (state->type == ZLIB_TRANSFER_DEINIT ||
|
||||
state->type == ZLIB_TRANSFER_DEINIT_ERROR)
|
||||
if (state->type == ARCHIVE_TRANSFER_DEINIT ||
|
||||
state->type == ARCHIVE_TRANSFER_DEINIT_ERROR)
|
||||
return -1;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state)
|
||||
{
|
||||
if (!state || !state->handle)
|
||||
return;
|
||||
|
||||
state->type = ZLIB_TRANSFER_DEINIT;
|
||||
file_archive_parse_file_iterate(state, NULL, NULL, NULL, NULL, NULL);
|
||||
}
|
||||
|
||||
/**
|
||||
* file_archive_parse_file:
|
||||
* @file : filename path of archive
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
* @file_cb : file_cb function pointer
|
||||
* @userdata : userdata to pass to file_cb function pointer.
|
||||
*
|
||||
* Low-level file parsing. Enumerates over all files and calls
|
||||
* Low-level file parsing. Enumerates over all files and calls
|
||||
* file_cb with userdata.
|
||||
*
|
||||
* Returns: true (1) on success, otherwise false (0).
|
||||
**/
|
||||
static bool file_archive_parse_file(const char *file, const char *valid_exts,
|
||||
file_archive_file_cb file_cb, void *userdata)
|
||||
file_archive_file_cb file_cb, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
file_archive_transfer_t state = {0};
|
||||
bool returnerr = true;
|
||||
|
||||
state.type = ZLIB_TRANSFER_INIT;
|
||||
state.type = ARCHIVE_TRANSFER_INIT;
|
||||
|
||||
for (;;)
|
||||
{
|
||||
@ -547,33 +475,34 @@ int file_archive_parse_file_progress(file_archive_transfer_t *state)
|
||||
{
|
||||
/* FIXME: this estimate is worse than before */
|
||||
ptrdiff_t delta = state->directory - state->data;
|
||||
return delta * 100 / state->zip_size;
|
||||
return delta * 100 / state->archive_size;
|
||||
}
|
||||
|
||||
/**
|
||||
* file_archive_extract_first_content_file:
|
||||
* @zip_path : filename path to ZIP archive.
|
||||
* @zip_path_size : size of ZIP archive.
|
||||
* @valid_exts : valid extensions for a content file.
|
||||
* file_archive_extract_file:
|
||||
* @archive_path : filename path to archive.
|
||||
* @archive_path_size : size of archive.
|
||||
* @valid_exts : valid extensions for the file.
|
||||
* @extraction_directory : the directory to extract temporary
|
||||
* unzipped content to.
|
||||
* file to.
|
||||
*
|
||||
* Extract first content file from archive.
|
||||
* Extract file from archive. If no file inside the archive is
|
||||
* specified, the first file found will be used.
|
||||
*
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool file_archive_extract_first_content_file(
|
||||
char *zip_path,
|
||||
size_t zip_path_size,
|
||||
bool file_archive_extract_file(
|
||||
char *archive_path,
|
||||
size_t archive_path_size,
|
||||
const char *valid_exts,
|
||||
const char *extraction_directory,
|
||||
char *out_path, size_t len)
|
||||
{
|
||||
struct string_list *list = NULL;
|
||||
bool ret = true;
|
||||
struct zip_extract_userdata userdata = {0};
|
||||
struct archive_extract_userdata userdata = {0};
|
||||
|
||||
/* We cannot unzip if the libretro
|
||||
/* We cannot extract if the libretro
|
||||
* implementation does not have any valid extensions. */
|
||||
if (!valid_exts)
|
||||
return false;
|
||||
@ -585,12 +514,15 @@ bool file_archive_extract_first_content_file(
|
||||
goto end;
|
||||
}
|
||||
|
||||
userdata.zip_path = zip_path;
|
||||
userdata.zip_path_size = zip_path_size;
|
||||
userdata.archive_path = archive_path;
|
||||
userdata.archive_path_size = archive_path_size;
|
||||
userdata.extraction_directory = extraction_directory;
|
||||
userdata.ext = list;
|
||||
userdata.list = NULL;
|
||||
userdata.context = NULL;
|
||||
userdata.list_only = false;
|
||||
|
||||
if (!file_archive_parse_file(zip_path, valid_exts,
|
||||
if (!file_archive_parse_file(archive_path, valid_exts,
|
||||
file_archive_extract_cb, &userdata))
|
||||
{
|
||||
/* Parsing file archive failed. */
|
||||
@ -598,9 +530,9 @@ bool file_archive_extract_first_content_file(
|
||||
goto end;
|
||||
}
|
||||
|
||||
if (!userdata.found_content)
|
||||
if (!userdata.found_file)
|
||||
{
|
||||
/* Didn't find any content that matched valid extensions
|
||||
/* Didn't find any file that matched valid extensions
|
||||
* for libretro implementation. */
|
||||
ret = false;
|
||||
goto end;
|
||||
@ -626,39 +558,44 @@ end:
|
||||
struct string_list *file_archive_get_file_list(const char *path,
|
||||
const char *valid_exts)
|
||||
{
|
||||
struct string_list *list = string_list_new();
|
||||
struct archive_extract_userdata userdata = {0};
|
||||
userdata.list_only = true;
|
||||
|
||||
if (!list)
|
||||
userdata.list = string_list_new();
|
||||
|
||||
if (!userdata.list)
|
||||
goto error;
|
||||
|
||||
if (!file_archive_parse_file(path, valid_exts,
|
||||
file_archive_get_file_list_cb, list))
|
||||
file_archive_get_file_list_cb, &userdata))
|
||||
goto error;
|
||||
|
||||
return list;
|
||||
return userdata.list;
|
||||
|
||||
error:
|
||||
if (list)
|
||||
string_list_free(list);
|
||||
if (userdata.list)
|
||||
string_list_free(userdata.list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
bool file_archive_perform_mode(const char *path, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata)
|
||||
uint32_t crc32, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
switch (cmode)
|
||||
{
|
||||
case ZLIB_MODE_UNCOMPRESSED:
|
||||
case ARCHIVE_MODE_UNCOMPRESSED:
|
||||
if (!filestream_write_file(path, cdata, size))
|
||||
goto error;
|
||||
break;
|
||||
|
||||
case ZLIB_MODE_DEFLATE:
|
||||
case ARCHIVE_MODE_COMPRESSED:
|
||||
{
|
||||
int ret = 0;
|
||||
file_archive_file_handle_t handle = {0};
|
||||
handle.backend = file_archive_get_default_file_backend();
|
||||
|
||||
handle.backend = file_archive_get_file_backend(userdata->archive_path);
|
||||
handle.stream = userdata->context;
|
||||
|
||||
if (!handle.backend->stream_decompress_data_to_file_init(&handle,
|
||||
cdata, csize, size))
|
||||
@ -685,7 +622,156 @@ error:
|
||||
return false;
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_default_file_backend(void)
|
||||
/* Generic compressed file loader.
|
||||
* Extracts to buf, unless optional_filename != 0
|
||||
* Then extracts to optional_filename and leaves buf alone.
|
||||
*/
|
||||
int file_archive_compressed_read(
|
||||
const char * path, void **buf,
|
||||
const char* optional_filename, ssize_t *length)
|
||||
{
|
||||
return &zlib_backend;
|
||||
const struct file_archive_file_backend *backend = NULL;
|
||||
int ret = 0;
|
||||
struct string_list *str_list = file_archive_filename_split(path);
|
||||
|
||||
/* 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 && path_file_exists(optional_filename))
|
||||
{
|
||||
*length = 0;
|
||||
string_list_free(str_list);
|
||||
return 1;
|
||||
}
|
||||
|
||||
/* We assure that there is something after the '#' symbol.
|
||||
*
|
||||
* This error condition happens for example, when
|
||||
* path = /path/to/file.7z, or
|
||||
* path = /path/to/file.7z#
|
||||
*/
|
||||
if (str_list->size <= 1)
|
||||
goto error;
|
||||
|
||||
backend = file_archive_get_file_backend(str_list->elems[0].data);
|
||||
|
||||
*length = backend->compressed_file_read(str_list->elems[0].data,
|
||||
str_list->elems[1].data, buf, optional_filename);
|
||||
|
||||
if (*length != -1)
|
||||
ret = 1;
|
||||
|
||||
string_list_free(str_list);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
/* could not extract string and substring. */
|
||||
string_list_free(str_list);
|
||||
*length = 0;
|
||||
return 0;
|
||||
}
|
||||
|
||||
struct string_list *file_archive_file_list_new(const char *path,
|
||||
const char* ext)
|
||||
{
|
||||
#ifdef HAVE_COMPRESSION
|
||||
bool compressed = path_is_compressed_file(path);
|
||||
|
||||
if (compressed)
|
||||
return file_archive_get_file_list(path, ext);
|
||||
#endif
|
||||
return NULL;
|
||||
}
|
||||
|
||||
/**
|
||||
* file_archive_filename_split:
|
||||
* @str : filename to turn into a string list
|
||||
*
|
||||
* Creates a new string list based on filename @path, delimited by a hash (#).
|
||||
*
|
||||
* Returns: new string list if successful, otherwise NULL.
|
||||
*/
|
||||
struct string_list *file_archive_filename_split(const char *path)
|
||||
{
|
||||
union string_list_elem_attr attr;
|
||||
struct string_list *list = string_list_new();
|
||||
const char *delim = NULL;
|
||||
|
||||
memset(&attr, 0, sizeof(attr));
|
||||
|
||||
delim = path_get_archive_delim(path);
|
||||
|
||||
if (delim)
|
||||
{
|
||||
/* add archive path to list first */
|
||||
if (!string_list_append_n(list, path, delim - path, attr))
|
||||
goto error;
|
||||
|
||||
/* now add the path within the archive */
|
||||
delim++;
|
||||
|
||||
if (*delim)
|
||||
{
|
||||
if (!string_list_append(list, delim, attr))
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
else
|
||||
if (!string_list_append(list, path, attr))
|
||||
goto error;
|
||||
|
||||
return list;
|
||||
|
||||
error:
|
||||
string_list_free(list);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_zlib_file_backend(void)
|
||||
{
|
||||
#ifdef HAVE_ZLIB
|
||||
return &zlib_backend;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_7z_file_backend(void)
|
||||
{
|
||||
#ifdef HAVE_7ZIP
|
||||
return &sevenzip_backend;
|
||||
#else
|
||||
return NULL;
|
||||
#endif
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend* file_archive_get_file_backend(const char *path)
|
||||
{
|
||||
const char *file_ext = NULL;
|
||||
char *last = NULL;
|
||||
char newpath[PATH_MAX_LENGTH] = {0};
|
||||
|
||||
strlcpy(newpath, path, sizeof(newpath));
|
||||
|
||||
last = (char*)path_get_archive_delim(newpath);
|
||||
|
||||
if (last)
|
||||
*last = '\0';
|
||||
|
||||
file_ext = path_get_extension(newpath);
|
||||
|
||||
#ifdef HAVE_7ZIP
|
||||
if (string_is_equal_noncase(file_ext, "7z"))
|
||||
return &sevenzip_backend;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
if (string_is_equal_noncase(file_ext, "zip"))
|
||||
return &zlib_backend;
|
||||
#endif
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
420
libretro-common/file/archive_file_7z.c
Normal file
420
libretro-common/file/archive_file_7z.c
Normal file
@ -0,0 +1,420 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (archive_file_sevenzip.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#include <file/archive_file.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/utf.h>
|
||||
#include <encodings/crc32.h>
|
||||
#include <string/stdstring.h>
|
||||
#include <lists/string_list.h>
|
||||
#include <file/file_path.h>
|
||||
#include <compat/strl.h>
|
||||
#include "../../deps/7zip/7z.h"
|
||||
#include "../../deps/7zip/7zAlloc.h"
|
||||
#include "../../deps/7zip/7zCrc.h"
|
||||
#include "../../deps/7zip/7zFile.h"
|
||||
|
||||
#define SEVENZIP_MAGIC "7z\xBC\xAF\x27\x1C"
|
||||
#define SEVENZIP_MAGIC_LEN 6
|
||||
|
||||
struct sevenzip_context_t {
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
size_t temp_size;
|
||||
uint32_t block_index;
|
||||
uint32_t index;
|
||||
uint32_t packIndex;
|
||||
uint8_t *output;
|
||||
file_archive_file_handle_t *handle;
|
||||
};
|
||||
|
||||
static void* sevenzip_stream_new(void)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context =
|
||||
(struct sevenzip_context_t*)calloc(1, sizeof(struct sevenzip_context_t));
|
||||
|
||||
/* These are the allocation routines - currently using
|
||||
* the non-standard 7zip choices. */
|
||||
sevenzip_context->allocImp.Alloc = SzAlloc;
|
||||
sevenzip_context->allocImp.Free = SzFree;
|
||||
sevenzip_context->allocTempImp.Alloc = SzAllocTemp;
|
||||
sevenzip_context->allocTempImp.Free = SzFreeTemp;
|
||||
sevenzip_context->index = 0;
|
||||
sevenzip_context->packIndex = 0;
|
||||
sevenzip_context->temp_size = 0;
|
||||
sevenzip_context->block_index = 0xFFFFFFFF;
|
||||
sevenzip_context->output = NULL;
|
||||
|
||||
return sevenzip_context;
|
||||
}
|
||||
|
||||
static void sevenzip_stream_free(void *data)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)data;
|
||||
|
||||
if (!sevenzip_context)
|
||||
return;
|
||||
|
||||
SzArEx_Free(&sevenzip_context->db, &sevenzip_context->allocImp);
|
||||
File_Close(&sevenzip_context->archiveStream.file);
|
||||
}
|
||||
|
||||
/* Extract the relative path (needle) from a 7z archive
|
||||
* (path) and allocate a buf for it to write it in.
|
||||
* If optional_outfile is set, extract to that instead
|
||||
* and don't allocate buffer.
|
||||
*/
|
||||
static int sevenzip_file_read(
|
||||
const char *path,
|
||||
const char *needle, void **buf,
|
||||
const char *optional_outfile)
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
uint8_t *output = 0;
|
||||
long outsize = -1;
|
||||
|
||||
/*These are the allocation routines.
|
||||
* Currently using the non-standard 7zip choices. */
|
||||
allocImp.Alloc = SzAlloc;
|
||||
allocImp.Free = SzFree;
|
||||
allocTempImp.Alloc = SzAllocTemp;
|
||||
allocTempImp.Free = SzFreeTemp;
|
||||
|
||||
/* Could not open 7zip archive? */
|
||||
if (InFile_Open(&archiveStream.file, path))
|
||||
return -1;
|
||||
|
||||
FileInStream_CreateVTable(&archiveStream);
|
||||
LookToRead_CreateVTable(&lookStream, False);
|
||||
lookStream.realStream = &archiveStream.s;
|
||||
LookToRead_Init(&lookStream);
|
||||
CrcGenerateTable();
|
||||
SzArEx_Init(&db);
|
||||
|
||||
if (SzArEx_Open(&db, &lookStream.s, &allocImp, &allocTempImp) == SZ_OK)
|
||||
{
|
||||
uint32_t i;
|
||||
bool file_found = false;
|
||||
uint16_t *temp = NULL;
|
||||
size_t temp_size = 0;
|
||||
uint32_t block_index = 0xFFFFFFFF;
|
||||
SRes res = SZ_OK;
|
||||
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
size_t len;
|
||||
char infile[PATH_MAX_LENGTH] = {0};
|
||||
size_t offset = 0;
|
||||
size_t outSizeProcessed = 0;
|
||||
const CSzFileItem *f = db.db.Files + i;
|
||||
|
||||
/* We skip over everything which is not a directory.
|
||||
* FIXME: Why continue then if f->IsDir is true?*/
|
||||
if (f->IsDir)
|
||||
continue;
|
||||
|
||||
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||
|
||||
if (len > temp_size)
|
||||
{
|
||||
if (temp)
|
||||
free(temp);
|
||||
temp_size = len;
|
||||
temp = (uint16_t *)malloc(temp_size * sizeof(temp[0]));
|
||||
|
||||
if (temp == 0)
|
||||
{
|
||||
res = SZ_ERROR_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
SzArEx_GetFileNameUtf16(&db, i, temp);
|
||||
res = SZ_ERROR_FAIL;
|
||||
if (temp)
|
||||
res = utf16_to_char_string(temp, infile, sizeof(infile))
|
||||
? SZ_OK : SZ_ERROR_FAIL;
|
||||
|
||||
if (string_is_equal(infile, needle))
|
||||
{
|
||||
size_t output_size = 0;
|
||||
|
||||
/*RARCH_LOG_OUTPUT("Opened archive %s. Now trying to extract %s\n",
|
||||
path, needle);*/
|
||||
|
||||
/* 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, &block_index,
|
||||
&output, &output_size, &offset, &outSizeProcessed,
|
||||
&allocImp, &allocTempImp);
|
||||
|
||||
if (res != SZ_OK)
|
||||
break; /* This goes to the error section. */
|
||||
|
||||
outsize = outSizeProcessed;
|
||||
|
||||
if (optional_outfile != NULL)
|
||||
{
|
||||
const void *ptr = (const void*)(output + offset);
|
||||
|
||||
if (!filestream_write_file(optional_outfile, ptr, outsize))
|
||||
{
|
||||
/*RARCH_ERR("Could not open outfilepath %s.\n",
|
||||
optional_outfile);*/
|
||||
res = SZ_OK;
|
||||
file_found = true;
|
||||
outsize = -1;
|
||||
}
|
||||
}
|
||||
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,output + offset,outsize);
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
if (temp)
|
||||
free(temp);
|
||||
IAlloc_Free(&allocImp, output);
|
||||
|
||||
if (!(file_found && res == SZ_OK))
|
||||
{
|
||||
/* Error handling
|
||||
*
|
||||
* Failed to open compressed file inside 7zip archive.
|
||||
*/
|
||||
|
||||
outsize = -1;
|
||||
}
|
||||
}
|
||||
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
File_Close(&archiveStream.file);
|
||||
|
||||
return outsize;
|
||||
}
|
||||
|
||||
static bool sevenzip_stream_decompress_data_to_file_init(
|
||||
file_archive_file_handle_t *handle,
|
||||
const uint8_t *cdata, uint32_t csize, uint32_t size)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context =
|
||||
(struct sevenzip_context_t*)handle->stream;
|
||||
|
||||
if (!sevenzip_context)
|
||||
return false;
|
||||
|
||||
sevenzip_context->handle = handle;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static int sevenzip_stream_decompress_data_to_file_iterate(void *data)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context =
|
||||
(struct sevenzip_context_t*)data;
|
||||
|
||||
if (sevenzip_context->handle)
|
||||
sevenzip_context->handle->data = sevenzip_context->output;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sevenzip_parse_file_init(file_archive_transfer_t *state,
|
||||
const char *file)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context = NULL;
|
||||
if (state->archive_size < SEVENZIP_MAGIC_LEN)
|
||||
return -1;
|
||||
|
||||
if (memcmp(state->data, SEVENZIP_MAGIC, SEVENZIP_MAGIC_LEN) != 0)
|
||||
return -1;
|
||||
|
||||
sevenzip_context = (struct sevenzip_context_t*)sevenzip_stream_new();
|
||||
|
||||
/* could not open 7zip archive? */
|
||||
if (InFile_Open(&sevenzip_context->archiveStream.file, file))
|
||||
return -1;
|
||||
|
||||
FileInStream_CreateVTable(&sevenzip_context->archiveStream);
|
||||
LookToRead_CreateVTable(&sevenzip_context->lookStream, False);
|
||||
sevenzip_context->lookStream.realStream = &sevenzip_context->archiveStream.s;
|
||||
LookToRead_Init(&sevenzip_context->lookStream);
|
||||
CrcGenerateTable();
|
||||
SzArEx_Init(&sevenzip_context->db);
|
||||
|
||||
SzArEx_Open(&sevenzip_context->db, &sevenzip_context->lookStream.s,
|
||||
&sevenzip_context->allocImp, &sevenzip_context->allocTempImp);
|
||||
|
||||
state->stream = sevenzip_context;
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int sevenzip_parse_file_iterate_step_internal(
|
||||
file_archive_transfer_t *state, char *filename,
|
||||
const uint8_t **cdata, unsigned *cmode,
|
||||
uint32_t *size, uint32_t *csize, uint32_t *checksum,
|
||||
unsigned *payback, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
struct sevenzip_context_t *sevenzip_context = (struct sevenzip_context_t*)state->stream;
|
||||
const CSzFileItem *file = sevenzip_context->db.db.Files + sevenzip_context->index;
|
||||
|
||||
if (sevenzip_context->index < sevenzip_context->db.db.NumFiles)
|
||||
{
|
||||
size_t len = SzArEx_GetFileNameUtf16(&sevenzip_context->db, sevenzip_context->index, NULL);
|
||||
uint64_t compressed_size = 0;
|
||||
|
||||
if (sevenzip_context->packIndex < sevenzip_context->db.db.NumPackStreams)
|
||||
{
|
||||
compressed_size = sevenzip_context->db.db.PackSizes[sevenzip_context->packIndex];
|
||||
sevenzip_context->packIndex++;
|
||||
}
|
||||
|
||||
if (len < PATH_MAX_LENGTH && !file->IsDir)
|
||||
{
|
||||
SRes res = SZ_ERROR_FAIL;
|
||||
char infile[PATH_MAX_LENGTH] = {0};
|
||||
uint16_t *temp = (uint16_t*)malloc(len * sizeof(uint16_t));
|
||||
|
||||
if (!temp)
|
||||
return -1;
|
||||
|
||||
SzArEx_GetFileNameUtf16(&sevenzip_context->db, sevenzip_context->index, temp);
|
||||
|
||||
if (temp)
|
||||
{
|
||||
res = utf16_to_char_string(temp, infile, sizeof(infile))
|
||||
? SZ_OK : SZ_ERROR_FAIL;
|
||||
free(temp);
|
||||
}
|
||||
|
||||
if (res != SZ_OK)
|
||||
return -1;
|
||||
|
||||
strlcpy(filename, infile, PATH_MAX_LENGTH);
|
||||
|
||||
if (!userdata->list_only)
|
||||
{
|
||||
size_t output_size = 0;
|
||||
size_t offset = 0;
|
||||
size_t outSizeProcessed = 0;
|
||||
|
||||
res = SzArEx_Extract(&sevenzip_context->db,
|
||||
&sevenzip_context->lookStream.s, sevenzip_context->index,
|
||||
&sevenzip_context->block_index, &sevenzip_context->output,
|
||||
&output_size, &offset, &outSizeProcessed,
|
||||
&sevenzip_context->allocImp, &sevenzip_context->allocTempImp);
|
||||
}
|
||||
|
||||
if (res != SZ_OK)
|
||||
return -1;
|
||||
|
||||
*cmode = ARCHIVE_MODE_COMPRESSED;
|
||||
*checksum = file->Crc;
|
||||
*size = file->Size;
|
||||
*csize = compressed_size;
|
||||
}
|
||||
}
|
||||
|
||||
*payback = 1;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int sevenzip_parse_file_iterate_step(file_archive_transfer_t *state,
|
||||
const char *valid_exts, struct archive_extract_userdata *userdata, file_archive_file_cb file_cb)
|
||||
{
|
||||
const uint8_t *cdata = NULL;
|
||||
uint32_t checksum = 0;
|
||||
uint32_t size = 0;
|
||||
uint32_t csize = 0;
|
||||
unsigned cmode = 0;
|
||||
unsigned payload = 0;
|
||||
struct sevenzip_context_t *sevenzip_context = NULL;
|
||||
char filename[PATH_MAX_LENGTH] = {0};
|
||||
int ret = sevenzip_parse_file_iterate_step_internal(state, filename,
|
||||
&cdata, &cmode, &size, &csize,
|
||||
&checksum, &payload, userdata);
|
||||
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
||||
userdata->extracted_file_path = filename;
|
||||
|
||||
if (!file_cb(filename, valid_exts, cdata, cmode,
|
||||
csize, size, checksum, userdata))
|
||||
return 0;
|
||||
|
||||
sevenzip_context = (struct sevenzip_context_t*)state->stream;
|
||||
|
||||
sevenzip_context->index += payload;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static uint32_t sevenzip_stream_crc32_calculate(uint32_t crc,
|
||||
const uint8_t *data, size_t length)
|
||||
{
|
||||
return encoding_crc32(crc, data, length);
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend sevenzip_backend = {
|
||||
sevenzip_stream_new,
|
||||
sevenzip_stream_free,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
sevenzip_stream_decompress_data_to_file_init,
|
||||
sevenzip_stream_decompress_data_to_file_iterate,
|
||||
NULL,
|
||||
NULL,
|
||||
NULL,
|
||||
sevenzip_stream_crc32_calculate,
|
||||
sevenzip_file_read,
|
||||
sevenzip_parse_file_init,
|
||||
sevenzip_parse_file_iterate_step,
|
||||
"7z"
|
||||
};
|
@ -25,8 +25,19 @@
|
||||
#include <compat/zlib.h>
|
||||
#include <file/archive_file.h>
|
||||
#include <streams/file_stream.h>
|
||||
#include <string.h>
|
||||
#include <retro_miscellaneous.h>
|
||||
#include <encodings/crc32.h>
|
||||
|
||||
static void *zlib_stream_new(void)
|
||||
#ifndef CENTRAL_FILE_HEADER_SIGNATURE
|
||||
#define CENTRAL_FILE_HEADER_SIGNATURE 0x02014b50
|
||||
#endif
|
||||
|
||||
#ifndef END_OF_CENTRAL_DIR_SIGNATURE
|
||||
#define END_OF_CENTRAL_DIR_SIGNATURE 0x06054b50
|
||||
#endif
|
||||
|
||||
static void* zlib_stream_new(void)
|
||||
{
|
||||
return (z_stream*)calloc(1, sizeof(z_stream));
|
||||
}
|
||||
@ -138,7 +149,7 @@ static bool zlib_stream_decompress_data_to_file_init(
|
||||
|
||||
if (!(handle->stream = (z_stream*)zlib_stream_new()))
|
||||
goto error;
|
||||
|
||||
|
||||
if (inflateInit2((z_streamp)handle->stream, -MAX_WBITS) != Z_OK)
|
||||
goto error;
|
||||
|
||||
@ -194,7 +205,257 @@ static void zlib_stream_compress_init(void *data, int level)
|
||||
static uint32_t zlib_stream_crc32_calculate(uint32_t crc,
|
||||
const uint8_t *data, size_t length)
|
||||
{
|
||||
return crc32(crc, data, length);
|
||||
return encoding_crc32(crc, data, length);
|
||||
}
|
||||
|
||||
static bool zip_file_decompressed_handle(
|
||||
file_archive_file_handle_t *handle,
|
||||
const uint8_t *cdata, uint32_t csize,
|
||||
uint32_t size, uint32_t crc32)
|
||||
{
|
||||
int ret = 0;
|
||||
|
||||
handle->backend = &zlib_backend;
|
||||
|
||||
if (!handle->backend->stream_decompress_data_to_file_init(
|
||||
handle, cdata, csize, size))
|
||||
return false;
|
||||
|
||||
do{
|
||||
ret = handle->backend->stream_decompress_data_to_file_iterate(
|
||||
handle->stream);
|
||||
}while(ret == 0);
|
||||
#if 0
|
||||
handle->real_checksum = handle->backend->stream_crc_calculate(0,
|
||||
handle->data, size);
|
||||
|
||||
if (handle->real_checksum != crc32)
|
||||
goto error;
|
||||
#endif
|
||||
|
||||
if (handle->stream)
|
||||
free(handle->stream);
|
||||
|
||||
return true;
|
||||
#if 0
|
||||
error:
|
||||
if (handle->stream)
|
||||
free(handle->stream);
|
||||
if (handle->data)
|
||||
free(handle->data);
|
||||
|
||||
handle->stream = NULL;
|
||||
handle->data = NULL;
|
||||
return false;
|
||||
#endif
|
||||
}
|
||||
|
||||
/* Extract the relative path (needle) from a
|
||||
* ZIP archive (path) and allocate a buffer for it to write it in.
|
||||
*
|
||||
* optional_outfile if not NULL will be used to extract the file to.
|
||||
* buf will be 0 then.
|
||||
*/
|
||||
|
||||
static int zip_file_decompressed(
|
||||
const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode,
|
||||
uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, struct archive_extract_userdata *userdata)
|
||||
{
|
||||
/* Ignore directories. */
|
||||
if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\')
|
||||
return 1;
|
||||
|
||||
#if 0
|
||||
RARCH_LOG("[deflate] Path: %s, CRC32: 0x%x\n", name, crc32);
|
||||
#endif
|
||||
|
||||
if (strstr(name, userdata->decomp_state.needle))
|
||||
{
|
||||
bool goto_error = false;
|
||||
file_archive_file_handle_t handle = {0};
|
||||
|
||||
userdata->decomp_state.found = true;
|
||||
|
||||
if (zip_file_decompressed_handle(&handle,
|
||||
cdata, csize, size, crc32))
|
||||
{
|
||||
if (userdata->decomp_state.opt_file != 0)
|
||||
{
|
||||
/* Called in case core has need_fullpath enabled. */
|
||||
char *buf = (char*)malloc(size);
|
||||
|
||||
if (buf)
|
||||
{
|
||||
/*RARCH_LOG("%s: %s\n",
|
||||
msg_hash_to_str(MSG_EXTRACTING_FILE),
|
||||
userdata->decomp_state.opt_file);*/
|
||||
memcpy(buf, handle.data, size);
|
||||
|
||||
if (!filestream_write_file(userdata->decomp_state.opt_file, buf, size))
|
||||
goto_error = true;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
userdata->decomp_state.size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Called in case core has need_fullpath disabled.
|
||||
* Will copy decompressed content directly into
|
||||
* RetroArch's ROM buffer. */
|
||||
*userdata->decomp_state.buf = malloc(size);
|
||||
memcpy(*userdata->decomp_state.buf, handle.data, size);
|
||||
|
||||
userdata->decomp_state.size = size;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle.data)
|
||||
free(handle.data);
|
||||
|
||||
if (goto_error)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int zip_file_read(
|
||||
const char *path,
|
||||
const char *needle, void **buf,
|
||||
const char *optional_outfile)
|
||||
{
|
||||
file_archive_transfer_t zlib;
|
||||
bool returnerr = true;
|
||||
int ret = 0;
|
||||
struct archive_extract_userdata userdata = {0};
|
||||
|
||||
zlib.type = ARCHIVE_TRANSFER_INIT;
|
||||
|
||||
userdata.decomp_state.needle = NULL;
|
||||
userdata.decomp_state.opt_file = NULL;
|
||||
userdata.decomp_state.found = false;
|
||||
userdata.decomp_state.buf = buf;
|
||||
|
||||
if (needle)
|
||||
userdata.decomp_state.needle = strdup(needle);
|
||||
if (optional_outfile)
|
||||
userdata.decomp_state.opt_file = strdup(optional_outfile);
|
||||
|
||||
do
|
||||
{
|
||||
ret = file_archive_parse_file_iterate(&zlib, &returnerr, path,
|
||||
"", zip_file_decompressed, &userdata);
|
||||
if (!returnerr)
|
||||
break;
|
||||
}while(ret == 0 && !userdata.decomp_state.found);
|
||||
|
||||
file_archive_parse_file_iterate_stop(&zlib);
|
||||
|
||||
if (userdata.decomp_state.opt_file)
|
||||
free(userdata.decomp_state.opt_file);
|
||||
if (userdata.decomp_state.needle)
|
||||
free(userdata.decomp_state.needle);
|
||||
|
||||
if (!userdata.decomp_state.found)
|
||||
return -1;
|
||||
|
||||
return userdata.decomp_state.size;
|
||||
}
|
||||
|
||||
static int zip_parse_file_init(file_archive_transfer_t *state,
|
||||
const char *file)
|
||||
{
|
||||
if (state->archive_size < 22)
|
||||
return -1;
|
||||
|
||||
state->footer = state->data + state->archive_size - 22;
|
||||
|
||||
for (;; state->footer--)
|
||||
{
|
||||
if (state->footer <= state->data + 22)
|
||||
return -1;
|
||||
if (read_le(state->footer, 4) == END_OF_CENTRAL_DIR_SIGNATURE)
|
||||
{
|
||||
unsigned comment_len = read_le(state->footer + 20, 2);
|
||||
if (state->footer + 22 + comment_len == state->data + state->archive_size)
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
state->directory = state->data + read_le(state->footer + 16, 4);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static int zip_parse_file_iterate_step_internal(
|
||||
file_archive_transfer_t *state, char *filename,
|
||||
const uint8_t **cdata,
|
||||
unsigned *cmode, uint32_t *size, uint32_t *csize,
|
||||
uint32_t *checksum, unsigned *payback)
|
||||
{
|
||||
uint32_t offset;
|
||||
uint32_t namelength, extralength, commentlength,
|
||||
offsetNL, offsetEL;
|
||||
uint32_t signature = read_le(state->directory + 0, 4);
|
||||
|
||||
if (signature != CENTRAL_FILE_HEADER_SIGNATURE)
|
||||
return 0;
|
||||
|
||||
*cmode = read_le(state->directory + 10, 2); /* compression mode, 0 = store, 8 = deflate */
|
||||
*checksum = read_le(state->directory + 16, 4); /* CRC32 */
|
||||
*csize = read_le(state->directory + 20, 4); /* compressed size */
|
||||
*size = read_le(state->directory + 24, 4); /* uncompressed size */
|
||||
|
||||
namelength = read_le(state->directory + 28, 2); /* file name length */
|
||||
extralength = read_le(state->directory + 30, 2); /* extra field length */
|
||||
commentlength = read_le(state->directory + 32, 2); /* file comment length */
|
||||
|
||||
if (namelength >= PATH_MAX_LENGTH)
|
||||
return -1;
|
||||
|
||||
memcpy(filename, state->directory + 46, namelength); /* file name */
|
||||
|
||||
offset = read_le(state->directory + 42, 4); /* relative offset of local file header */
|
||||
offsetNL = read_le(state->data + offset + 26, 2); /* file name length */
|
||||
offsetEL = read_le(state->data + offset + 28, 2); /* extra field length */
|
||||
|
||||
*cdata = state->data + offset + 30 + offsetNL + offsetEL;
|
||||
|
||||
*payback = 46 + namelength + extralength + commentlength;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int zip_parse_file_iterate_step(file_archive_transfer_t *state,
|
||||
const char *valid_exts, struct archive_extract_userdata *userdata, file_archive_file_cb file_cb)
|
||||
{
|
||||
const uint8_t *cdata = NULL;
|
||||
uint32_t checksum = 0;
|
||||
uint32_t size = 0;
|
||||
uint32_t csize = 0;
|
||||
unsigned cmode = 0;
|
||||
unsigned payload = 0;
|
||||
char filename[PATH_MAX_LENGTH] = {0};
|
||||
int ret = zip_parse_file_iterate_step_internal(state, filename,
|
||||
&cdata, &cmode, &size, &csize,
|
||||
&checksum, &payload);
|
||||
|
||||
if (ret != 1)
|
||||
return ret;
|
||||
|
||||
userdata->extracted_file_path = filename;
|
||||
|
||||
if (!file_cb(filename, valid_exts, cdata, cmode,
|
||||
csize, size, checksum, userdata))
|
||||
return 0;
|
||||
|
||||
state->directory += payload;
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
const struct file_archive_file_backend zlib_backend = {
|
||||
@ -212,5 +473,8 @@ const struct file_archive_file_backend zlib_backend = {
|
||||
zlib_stream_compress_free,
|
||||
zlib_stream_compress_data_to_file,
|
||||
zlib_stream_crc32_calculate,
|
||||
zip_file_read,
|
||||
zip_parse_file_init,
|
||||
zip_parse_file_iterate_step,
|
||||
"zlib"
|
||||
};
|
||||
|
@ -948,3 +948,12 @@ bool config_get_entry_list_next(struct config_file_entry *entry)
|
||||
return true;
|
||||
}
|
||||
|
||||
bool config_file_exists(const char *path)
|
||||
{
|
||||
config_file_t *config = config_file_new(path);
|
||||
if (!config)
|
||||
return false;
|
||||
|
||||
config_file_free(config);
|
||||
return true;
|
||||
}
|
||||
|
@ -194,12 +194,12 @@ bool path_is_compressed_file(const char* path)
|
||||
const char *ext = path_get_extension(path);
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
if (strcasestr(ext, "zip"))
|
||||
if (string_is_equal_noncase(ext, "zip"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_7ZIP
|
||||
if (strcasestr(ext, "7z"))
|
||||
if (string_is_equal_noncase(ext, "7z"))
|
||||
return true;
|
||||
#endif
|
||||
|
||||
|
@ -870,7 +870,7 @@ static struct rpng_process *rpng_process_init(rpng_t *rpng, unsigned *width, uns
|
||||
if (!process)
|
||||
return NULL;
|
||||
|
||||
process->stream_backend = file_archive_get_default_file_backend();
|
||||
process->stream_backend = file_archive_get_zlib_file_backend();
|
||||
|
||||
png_pass_geom(&rpng->ihdr, rpng->ihdr.width,
|
||||
rpng->ihdr.height, NULL, NULL, &process->inflate_buf_size);
|
||||
|
@ -48,7 +48,7 @@ static bool png_write_crc(RFILE *file, const uint8_t *data, size_t size)
|
||||
{
|
||||
uint8_t crc_raw[4] = {0};
|
||||
const struct file_archive_file_backend *stream_backend =
|
||||
file_archive_get_default_file_backend();
|
||||
file_archive_get_zlib_file_backend();
|
||||
uint32_t crc = stream_backend->stream_crc_calculate(0, data, size);
|
||||
|
||||
dword_write_be(crc_raw, crc);
|
||||
@ -230,7 +230,7 @@ static bool rpng_save_image(const char *path,
|
||||
if (!file)
|
||||
GOTO_END_ERROR();
|
||||
|
||||
stream_backend = file_archive_get_default_file_backend();
|
||||
stream_backend = file_archive_get_zlib_file_backend();
|
||||
|
||||
if (filestream_write(file, png_magic, sizeof(png_magic)) != sizeof(png_magic))
|
||||
GOTO_END_ERROR();
|
||||
|
@ -24,6 +24,7 @@
|
||||
#include <math.h>
|
||||
|
||||
#include <gfx/math/matrix_4x4.h>
|
||||
#include <gfx/math/vector_3.h>
|
||||
|
||||
void matrix_4x4_copy(math_matrix_4x4 *dst, const math_matrix_4x4 *src)
|
||||
{
|
||||
@ -160,17 +161,60 @@ void matrix_4x4_translate(math_matrix_4x4 *out, float x,
|
||||
/*
|
||||
* Creates a perspective projection matrix.
|
||||
*/
|
||||
void matrix_4x4_projection(math_matrix_4x4 *out, float znear,
|
||||
void matrix_4x4_projection(math_matrix_4x4 *out,
|
||||
float y_fov,
|
||||
float aspect,
|
||||
float znear,
|
||||
float zfar)
|
||||
{
|
||||
float const a = 1.f / tan(y_fov / 2.f);
|
||||
float delta_z = zfar - znear;
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
MAT_ELEM_4X4(*out, 0, 0) = znear;
|
||||
MAT_ELEM_4X4(*out, 1, 1) = zfar;
|
||||
MAT_ELEM_4X4(*out, 2, 2) = (zfar + znear) / delta_z;
|
||||
MAT_ELEM_4X4(*out, 2, 3) = -2.0f * zfar * znear / delta_z;
|
||||
MAT_ELEM_4X4(*out, 3, 2) = -1.0f;
|
||||
MAT_ELEM_4X4(*out, 0, 0) = a / aspect;
|
||||
MAT_ELEM_4X4(*out, 1, 1) = a;
|
||||
MAT_ELEM_4X4(*out, 2, 2) = -((zfar + znear) / delta_z);
|
||||
MAT_ELEM_4X4(*out, 2, 3) = -1.f;
|
||||
MAT_ELEM_4X4(*out, 3, 2) = -((2.f * zfar * znear) / delta_z);
|
||||
}
|
||||
|
||||
/* TODO/FIXME - finish */
|
||||
void matrix_4x4_lookat(math_matrix_4x4 *out,
|
||||
vec3_t eye,
|
||||
vec3_t center,
|
||||
vec3_t up)
|
||||
{
|
||||
vec3_t s, t, f;
|
||||
|
||||
vec3_copy(&f[0], center);
|
||||
vec3_subtract(&f[0], eye);
|
||||
vec3_normalize(&f[0]);
|
||||
|
||||
vec3_cross(&s[0], &f[0], up);
|
||||
vec3_normalize(&s[0]);
|
||||
|
||||
vec3_cross(&t[0], &s[0], f);
|
||||
|
||||
memset(out, 0, sizeof(*out));
|
||||
|
||||
MAT_ELEM_4X4(*out, 0, 0) = s[0];
|
||||
MAT_ELEM_4X4(*out, 0, 1) = t[0];
|
||||
MAT_ELEM_4X4(*out, 0, 2) = -f[0];
|
||||
|
||||
MAT_ELEM_4X4(*out, 1, 0) = s[1];
|
||||
MAT_ELEM_4X4(*out, 1, 1) = t[1];
|
||||
MAT_ELEM_4X4(*out, 1, 2) = -f[1];
|
||||
|
||||
MAT_ELEM_4X4(*out, 2, 0) = s[2];
|
||||
MAT_ELEM_4X4(*out, 2, 1) = t[2];
|
||||
MAT_ELEM_4X4(*out, 2, 2) = -f[2];
|
||||
|
||||
MAT_ELEM_4X4(*out, 3, 3) = 1.f;
|
||||
|
||||
#if 0
|
||||
mat4x4_translate_in_place(m, -eye[0], -eye[1], -eye[2]);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
@ -37,18 +37,27 @@ float vec2_cross(const float *a, const float *b)
|
||||
|
||||
void vec2_add(float *dst, const float *src)
|
||||
{
|
||||
dst[0] += src[0];
|
||||
dst[1] += src[1];
|
||||
unsigned i;
|
||||
unsigned n = 2;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] += src[i];
|
||||
}
|
||||
|
||||
void vec2_subtract(float *dst, const float *src)
|
||||
{
|
||||
dst[0] -= src[0];
|
||||
dst[1] -= src[1];
|
||||
unsigned i;
|
||||
unsigned n = 2;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] -= src[i];
|
||||
}
|
||||
|
||||
void vec2_copy(float *dst, const float *src)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
unsigned i;
|
||||
unsigned n = 2;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
@ -46,30 +46,38 @@ float vec3_length(const float *a)
|
||||
|
||||
void vec3_add(float *dst, const float *src)
|
||||
{
|
||||
dst[0] += src[0];
|
||||
dst[1] += src[1];
|
||||
dst[2] += src[2];
|
||||
unsigned i;
|
||||
unsigned n = 3;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] += src[i];
|
||||
}
|
||||
|
||||
void vec3_subtract(float *dst, const float *src)
|
||||
{
|
||||
dst[0] -= src[0];
|
||||
dst[1] -= src[1];
|
||||
dst[2] -= src[2];
|
||||
unsigned i;
|
||||
unsigned n = 3;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] -= src[i];
|
||||
}
|
||||
|
||||
void vec3_scale(float *dst, const float scale)
|
||||
{
|
||||
dst[0] *= scale;
|
||||
dst[1] *= scale;
|
||||
dst[2] *= scale;
|
||||
unsigned i;
|
||||
unsigned n = 3;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] *= scale;
|
||||
}
|
||||
|
||||
void vec3_copy(float *dst, const float *src)
|
||||
{
|
||||
dst[0] = src[0];
|
||||
dst[1] = src[1];
|
||||
dst[2] = src[2];
|
||||
unsigned i;
|
||||
unsigned n = 3;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
||||
|
||||
void vec3_normalize(float *dst)
|
||||
|
62
libretro-common/gfx/math/vector_4.c
Normal file
62
libretro-common/gfx/math/vector_4.c
Normal file
@ -0,0 +1,62 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vector_4.c).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#include <stdint.h>
|
||||
#include <math.h>
|
||||
|
||||
#include <gfx/math/vector_4.h>
|
||||
|
||||
void vec4_add(float *dst, const float *src)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned n = 4;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] += src[i];
|
||||
}
|
||||
|
||||
void vec4_subtract(float *dst, const float *src)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned n = 4;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] -= src[i];
|
||||
}
|
||||
|
||||
void vec4_scale(float *dst, const float scale)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned n = 4;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] *= scale;
|
||||
}
|
||||
|
||||
void vec4_copy(float *dst, const float *src)
|
||||
{
|
||||
unsigned i;
|
||||
unsigned n = 4;
|
||||
|
||||
for (i = 0; i < n; i++)
|
||||
dst[i] = src[i];
|
||||
}
|
@ -30,6 +30,8 @@
|
||||
#include <retro_inline.h>
|
||||
#include <filters.h>
|
||||
|
||||
#define FILTER_UNITY (1 << 14)
|
||||
|
||||
static bool allocate_filters(struct scaler_ctx *ctx)
|
||||
{
|
||||
ctx->horiz.filter = (int16_t*)scaler_alloc(sizeof(int16_t), ctx->horiz.filter_stride * ctx->out_width);
|
||||
|
@ -38,6 +38,16 @@ struct gl_cached_state
|
||||
GLuint *ids;
|
||||
} bind_textures;
|
||||
|
||||
struct
|
||||
{
|
||||
bool used[MAX_ATTRIB];
|
||||
GLint size[MAX_ATTRIB];
|
||||
GLenum type[MAX_ATTRIB];
|
||||
GLboolean normalized[MAX_ATTRIB];
|
||||
GLsizei stride[MAX_ATTRIB];
|
||||
const GLvoid *pointer[MAX_ATTRIB];
|
||||
} attrib_pointer;
|
||||
|
||||
#ifndef HAVE_OPENGLES
|
||||
GLenum colorlogicop;
|
||||
#endif
|
||||
@ -1212,6 +1222,12 @@ void rglVertexAttribPointer(GLuint name, GLint size,
|
||||
GLenum type, GLboolean normalized, GLsizei stride,
|
||||
const GLvoid* pointer)
|
||||
{
|
||||
gl_state.attrib_pointer.used[name] = 1;
|
||||
gl_state.attrib_pointer.size[name] = size;
|
||||
gl_state.attrib_pointer.type[name] = type;
|
||||
gl_state.attrib_pointer.normalized[name] = normalized;
|
||||
gl_state.attrib_pointer.stride[name] = stride;
|
||||
gl_state.attrib_pointer.pointer[name] = pointer;
|
||||
glVertexAttribPointer(name, size, type, normalized, stride, pointer);
|
||||
}
|
||||
|
||||
@ -1835,6 +1851,18 @@ void *rglFenceSync(GLenum condition, GLbitfield flags)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
* OpenGL : 3.2
|
||||
* OpenGLES : 3.0
|
||||
*/
|
||||
void rglDeleteSync(GLsync sync) {
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3)
|
||||
glDeleteSync(sync);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
@ -1848,6 +1876,56 @@ void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout)
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
* OpenGL : 4.4
|
||||
* OpenGLES : Not available
|
||||
*/
|
||||
void rglBufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, GLbitfield flags) {
|
||||
#if defined(HAVE_OPENGL)
|
||||
glBufferStorage(target, size, data, flags);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
* OpenGL : 3.0
|
||||
* OpenGLES : 3.0
|
||||
*/
|
||||
void rglFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length) {
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3)
|
||||
glFlushMappedBufferRange(target, offset, length);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
* OpenGL : 3.2
|
||||
* OpenGLES : 3.0
|
||||
*/
|
||||
GLenum rglClientWaitSync(void *sync, GLbitfield flags, uint64_t timeout)
|
||||
{
|
||||
#if defined(HAVE_OPENGL) || defined(HAVE_OPENGLES) && defined(HAVE_OPENGLES3)
|
||||
return glClientWaitSync((GLsync)sync, flags, (GLuint64)timeout);
|
||||
#endif
|
||||
}
|
||||
|
||||
/*
|
||||
*
|
||||
* Core in:
|
||||
* OpenGL : 3.2
|
||||
* OpenGLES : Not available
|
||||
*/
|
||||
void rglDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
|
||||
GLvoid *indices, GLint basevertex) {
|
||||
#if defined(HAVE_OPENGL)
|
||||
glDrawElementsBaseVertex(mode, count, type, indices, basevertex);
|
||||
#endif
|
||||
}
|
||||
|
||||
/* GLSM-side */
|
||||
|
||||
static void glsm_state_setup(void)
|
||||
@ -1870,7 +1948,10 @@ static void glsm_state_setup(void)
|
||||
#endif
|
||||
|
||||
for (i = 0; i < MAX_ATTRIB; i++)
|
||||
{
|
||||
gl_state.vertex_attrib_pointer.enabled[i] = 0;
|
||||
gl_state.attrib_pointer.used[i] = 0;
|
||||
}
|
||||
|
||||
glGetIntegerv(GL_MAX_COMBINED_TEXTURE_IMAGE_UNITS, &glsm_max_textures);
|
||||
|
||||
@ -1917,6 +1998,17 @@ static void glsm_state_bind(void)
|
||||
glEnableVertexAttribArray(i);
|
||||
else
|
||||
glDisableVertexAttribArray(i);
|
||||
|
||||
if (gl_state.attrib_pointer.used[i])
|
||||
{
|
||||
glVertexAttribPointer(
|
||||
i,
|
||||
gl_state.attrib_pointer.size[i],
|
||||
gl_state.attrib_pointer.type[i],
|
||||
gl_state.attrib_pointer.normalized[i],
|
||||
gl_state.attrib_pointer.stride[i],
|
||||
gl_state.attrib_pointer.pointer[i]);
|
||||
}
|
||||
}
|
||||
|
||||
glBindFramebuffer(RARCH_GL_FRAMEBUFFER, hw_render.get_current_framebuffer());
|
||||
@ -2076,6 +2168,8 @@ static bool glsm_state_ctx_destroy(void *data)
|
||||
if (gl_state.bind_textures.ids)
|
||||
free(gl_state.bind_textures.ids);
|
||||
gl_state.bind_textures.ids = NULL;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
static bool glsm_state_ctx_init(void *data)
|
||||
|
@ -20,6 +20,9 @@
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __APPLE_COMPAT_H
|
||||
#define __APPLE_COMPAT_H
|
||||
|
||||
#ifdef __APPLE__
|
||||
#include <AvailabilityMacros.h>
|
||||
#endif
|
||||
@ -32,6 +35,32 @@ typedef unsigned NSUInteger;
|
||||
typedef float CGFloat;
|
||||
#endif
|
||||
|
||||
#ifndef __has_feature
|
||||
/* Compatibility with non-Clang compilers. */
|
||||
#define __has_feature(x) 0
|
||||
#endif
|
||||
|
||||
#ifndef CF_RETURNS_RETAINED
|
||||
#if __has_feature(attribute_cf_returns_retained)
|
||||
#define CF_RETURNS_RETAINED __attribute__((cf_returns_retained))
|
||||
#else
|
||||
#define CF_RETURNS_RETAINED
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#ifndef NS_INLINE
|
||||
#define NS_INLINE inline
|
||||
#endif
|
||||
|
||||
NS_INLINE CF_RETURNS_RETAINED CFTypeRef CFBridgingRetainCompat(id X)
|
||||
{
|
||||
#if __has_feature(objc_arc)
|
||||
return (__bridge_retained CFTypeRef)X;
|
||||
#else
|
||||
return X;
|
||||
#endif
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef IOS
|
||||
@ -43,7 +72,13 @@ typedef float CGFloat;
|
||||
#import <UIKit/UIKit.h>
|
||||
#import <GLKit/GLKit.h>
|
||||
#import <Foundation/Foundation.h>
|
||||
#endif
|
||||
|
||||
#else
|
||||
|
||||
#ifdef __OBJC__
|
||||
#include <objc/objc-runtime.h>
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
31
libretro-common/include/encodings/crc32.h
Normal file
31
libretro-common/include/encodings/crc32.h
Normal file
@ -0,0 +1,31 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (crc32.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef _LIBRETRO_ENCODINGS_CRC32_H
|
||||
#define _LIBRETRO_ENCODINGS_CRC32_H
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
uint32_t encoding_crc32(uint32_t crc, const uint8_t *buf, size_t len);
|
||||
|
||||
#endif
|
@ -42,4 +42,6 @@ const char *utf8skip(const char *str, size_t chars);
|
||||
|
||||
uint32_t utf8_walk(const char **string);
|
||||
|
||||
bool utf16_to_char_string(const uint16_t *in, char *s, size_t len);
|
||||
|
||||
#endif
|
||||
|
@ -25,26 +25,90 @@
|
||||
|
||||
#include <stdint.h>
|
||||
#include <stddef.h>
|
||||
|
||||
#include <boolean.h>
|
||||
|
||||
#include <retro_miscellaneous.h>
|
||||
|
||||
enum file_archive_transfer_type
|
||||
{
|
||||
ZLIB_TRANSFER_NONE = 0,
|
||||
ZLIB_TRANSFER_INIT,
|
||||
ZLIB_TRANSFER_ITERATE,
|
||||
ZLIB_TRANSFER_DEINIT,
|
||||
ZLIB_TRANSFER_DEINIT_ERROR
|
||||
ARCHIVE_TRANSFER_NONE = 0,
|
||||
ARCHIVE_TRANSFER_INIT,
|
||||
ARCHIVE_TRANSFER_ITERATE,
|
||||
ARCHIVE_TRANSFER_DEINIT,
|
||||
ARCHIVE_TRANSFER_DEINIT_ERROR
|
||||
};
|
||||
|
||||
typedef struct file_archive_handle
|
||||
{
|
||||
void *stream;
|
||||
uint8_t *data;
|
||||
uint8_t *data;
|
||||
uint32_t real_checksum;
|
||||
const struct file_archive_file_backend *backend;
|
||||
} file_archive_file_handle_t;
|
||||
|
||||
typedef struct file_archive_transfer
|
||||
{
|
||||
void *handle;
|
||||
void *stream;
|
||||
const uint8_t *footer;
|
||||
const uint8_t *directory;
|
||||
const uint8_t *data;
|
||||
int32_t archive_size;
|
||||
enum file_archive_transfer_type type;
|
||||
const struct file_archive_file_backend *backend;
|
||||
} file_archive_transfer_t;
|
||||
|
||||
enum file_archive_compression_mode
|
||||
{
|
||||
ARCHIVE_MODE_UNCOMPRESSED = 0,
|
||||
ARCHIVE_MODE_COMPRESSED = 8
|
||||
};
|
||||
|
||||
struct decomp_state_t
|
||||
{
|
||||
char *opt_file;
|
||||
char *needle;
|
||||
void **buf;
|
||||
size_t size;
|
||||
bool found;
|
||||
};
|
||||
|
||||
typedef struct
|
||||
{
|
||||
char *source_file;
|
||||
char *subdir;
|
||||
char *target_dir;
|
||||
char *target_file;
|
||||
char *valid_ext;
|
||||
|
||||
char *callback_error;
|
||||
|
||||
file_archive_transfer_t archive;
|
||||
} decompress_state_t;
|
||||
|
||||
struct archive_extract_userdata
|
||||
{
|
||||
char *archive_path;
|
||||
char *first_extracted_file_path;
|
||||
char *extracted_file_path;
|
||||
const char *extraction_directory;
|
||||
size_t archive_path_size;
|
||||
struct string_list *ext;
|
||||
struct string_list *list;
|
||||
bool found_file;
|
||||
bool list_only;
|
||||
void *context;
|
||||
char archive_name[PATH_MAX_LENGTH];
|
||||
uint32_t crc;
|
||||
struct decomp_state_t decomp_state;
|
||||
decompress_state_t *dec;
|
||||
};
|
||||
|
||||
/* Returns true when parsing should continue. False to stop. */
|
||||
typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, struct archive_extract_userdata *userdata);
|
||||
|
||||
struct file_archive_file_backend
|
||||
{
|
||||
void *(*stream_new)(void);
|
||||
@ -63,76 +127,87 @@ struct file_archive_file_backend
|
||||
void (*stream_compress_free)(void *);
|
||||
int (*stream_compress_data_to_file)(void *);
|
||||
uint32_t (*stream_crc_calculate)(uint32_t, const uint8_t *, size_t);
|
||||
int (*compressed_file_read)(const char *path, const char *needle, void **buf,
|
||||
const char *optional_outfile);
|
||||
int (*archive_parse_file_init)(
|
||||
file_archive_transfer_t *state,
|
||||
const char *file);
|
||||
int (*archive_parse_file_iterate_step)(
|
||||
file_archive_transfer_t *state,
|
||||
const char *valid_exts,
|
||||
struct archive_extract_userdata *userdata,
|
||||
file_archive_file_cb file_cb);
|
||||
const char *ident;
|
||||
};
|
||||
|
||||
typedef struct file_archive_transfer
|
||||
{
|
||||
void *handle;
|
||||
const uint8_t *footer;
|
||||
const uint8_t *directory;
|
||||
const uint8_t *data;
|
||||
int32_t zip_size;
|
||||
enum file_archive_transfer_type type;
|
||||
const struct file_archive_file_backend *backend;
|
||||
} file_archive_transfer_t;
|
||||
|
||||
|
||||
/* Returns true when parsing should continue. False to stop. */
|
||||
typedef int (*file_archive_file_cb)(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
int file_archive_parse_file_iterate(
|
||||
file_archive_transfer_t *state,
|
||||
bool *returnerr,
|
||||
const char *file,
|
||||
const char *valid_exts,
|
||||
file_archive_file_cb file_cb,
|
||||
void *userdata);
|
||||
struct archive_extract_userdata *userdata);
|
||||
|
||||
void file_archive_parse_file_iterate_stop(file_archive_transfer_t *state);
|
||||
|
||||
int file_archive_parse_file_progress(file_archive_transfer_t *state);
|
||||
|
||||
/**
|
||||
* file_archive_extract_first_content_file:
|
||||
* file_archive_extract_file:
|
||||
* @zip_path : filename path to ZIP archive.
|
||||
* @zip_path_size : size of ZIP archive.
|
||||
* @valid_exts : valid extensions for a content file.
|
||||
* @valid_exts : valid extensions for a file.
|
||||
* @extraction_directory : the directory to extract temporary
|
||||
* unzipped content to.
|
||||
* unzipped file to.
|
||||
*
|
||||
* Extract first content file from archive.
|
||||
* Extract file from archive. If no file inside the archive is
|
||||
* specified, the first file found will be used.
|
||||
*
|
||||
* Returns : true (1) on success, otherwise false (0).
|
||||
**/
|
||||
bool file_archive_extract_first_content_file(char *zip_path, size_t zip_path_size,
|
||||
bool file_archive_extract_file(char *zip_path, size_t zip_path_size,
|
||||
const char *valid_exts, const char *extraction_dir,
|
||||
char *out_path, size_t len);
|
||||
|
||||
/**
|
||||
* file_archive_get_file_list:
|
||||
* @path : filename path of archive
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* @valid_exts : Valid extensions of archive to be parsed.
|
||||
* If NULL, allow all.
|
||||
*
|
||||
* Returns: string listing of files from archive on success, otherwise NULL.
|
||||
**/
|
||||
struct string_list *file_archive_get_file_list(const char *path, const char *valid_exts);
|
||||
struct string_list* file_archive_get_file_list(const char *path, const char *valid_exts);
|
||||
|
||||
bool file_archive_perform_mode(const char *name, const char *valid_exts,
|
||||
const uint8_t *cdata, unsigned cmode, uint32_t csize, uint32_t size,
|
||||
uint32_t crc32, void *userdata);
|
||||
|
||||
struct string_list *compressed_file_list_new(const char *filename,
|
||||
const char* ext);
|
||||
uint32_t crc32, struct archive_extract_userdata *userdata);
|
||||
|
||||
void file_archive_deflate_init(void *data, int level);
|
||||
|
||||
const struct file_archive_file_backend *file_archive_get_default_file_backend(void);
|
||||
int file_archive_compressed_read(
|
||||
const char* path, void **buf,
|
||||
const char* optional_filename, ssize_t *length);
|
||||
|
||||
struct string_list* file_archive_file_list_new(const char *path,
|
||||
const char *ext);
|
||||
|
||||
struct string_list* file_archive_filename_split(const char *path);
|
||||
|
||||
const uint8_t* file_archive_data(void *handle);
|
||||
|
||||
int file_archive_parse_file_init(file_archive_transfer_t *state,
|
||||
const char *file);
|
||||
|
||||
void file_archive_free(void *handle);
|
||||
|
||||
const struct file_archive_file_backend* file_archive_get_zlib_file_backend(void);
|
||||
const struct file_archive_file_backend* file_archive_get_7z_file_backend(void);
|
||||
|
||||
const struct file_archive_file_backend* file_archive_get_file_backend(const char *path);
|
||||
|
||||
extern const struct file_archive_file_backend zlib_backend;
|
||||
extern const struct file_archive_file_backend sevenzip_backend;
|
||||
|
||||
#endif
|
||||
|
||||
|
@ -158,6 +158,8 @@ bool config_file_write(config_file_t *conf, const char *path);
|
||||
* Does not close the file. */
|
||||
void config_file_dump(config_file_t *conf, FILE *file);
|
||||
|
||||
bool config_file_exists(const char *path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
#endif
|
||||
|
@ -52,7 +52,7 @@ void matrix_4x4_multiply(math_matrix_4x4 *out, const math_matrix_4x4 *a, const m
|
||||
|
||||
void matrix_4x4_scale(math_matrix_4x4 *out, float x, float y, float z);
|
||||
void matrix_4x4_translate(math_matrix_4x4 *out, float x, float y, float z);
|
||||
void matrix_4x4_projection(math_matrix_4x4 *out, float znear, float zfar);
|
||||
void matrix_4x4_projection(math_matrix_4x4 *out, float y_fov, float aspect, float znear, float zfar);
|
||||
|
||||
#endif
|
||||
|
||||
|
39
libretro-common/include/gfx/math/vector_4.h
Normal file
39
libretro-common/include/gfx/math/vector_4.h
Normal file
@ -0,0 +1,39 @@
|
||||
/* Copyright (C) 2010-2016 The RetroArch team
|
||||
*
|
||||
* ---------------------------------------------------------------------------------------
|
||||
* The following license statement only applies to this file (vector_4.h).
|
||||
* ---------------------------------------------------------------------------------------
|
||||
*
|
||||
* Permission is hereby granted, free of charge,
|
||||
* to any person obtaining a copy of this software and associated documentation files (the "Software"),
|
||||
* to deal in the Software without restriction, including without limitation the rights to
|
||||
* use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software,
|
||||
* and to permit persons to whom the Software is furnished to do so, subject to the following conditions:
|
||||
*
|
||||
* The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software.
|
||||
*
|
||||
* THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED,
|
||||
* INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
|
||||
* FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT.
|
||||
* IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
|
||||
* WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
|
||||
* OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
||||
*/
|
||||
|
||||
#ifndef __LIBRETRO_SDK_GFX_MATH_VECTOR_4_H__
|
||||
#define __LIBRETRO_SDK_GFX_MATH_VECTOR_4_H__
|
||||
|
||||
#include <stdint.h>
|
||||
|
||||
typedef float vec4_t[4];
|
||||
|
||||
void vec4_add(float *dst, const float *src);
|
||||
|
||||
void vec4_subtract(float *dst, const float *src);
|
||||
|
||||
void vec4_scale(float *dst, const float scale);
|
||||
|
||||
void vec4_copy(float *dst, const float *src);
|
||||
|
||||
#endif
|
||||
|
@ -32,8 +32,6 @@
|
||||
|
||||
RETRO_BEGIN_DECLS
|
||||
|
||||
#define FILTER_UNITY (1 << 14)
|
||||
|
||||
enum scaler_pix_fmt
|
||||
{
|
||||
SCALER_FMT_ARGB8888 = 0,
|
||||
|
@ -161,6 +161,11 @@ RETRO_BEGIN_DECLS
|
||||
#define glClearBufferfi rglClearBufferfi
|
||||
#define glWaitSync rglWaitSync
|
||||
#define glFenceSync rglFenceSync
|
||||
#define glDeleteSync rglDeleteSync
|
||||
#define glBufferStorage rglBufferStorage
|
||||
#define glFlushMappedBufferRange rglFlushMappedBufferRange
|
||||
#define glClientWaitSync rglClientWaitSync
|
||||
#define glDrawElementsBaseVertex rglDrawElementsBaseVertex
|
||||
|
||||
const GLubyte* rglGetStringi(GLenum name, GLuint index);
|
||||
void rglTexBuffer(GLenum target, GLenum internalFormat, GLuint buffer);
|
||||
@ -396,7 +401,13 @@ void rglTexSubImage2D( GLenum target,
|
||||
const GLvoid * pixels);
|
||||
void rglDeleteVertexArrays(GLsizei n, const GLuint *arrays);
|
||||
void *rglFenceSync(GLenum condition, GLbitfield flags);
|
||||
void rglDeleteSync(GLsync sync);
|
||||
void rglWaitSync(void *sync, GLbitfield flags, uint64_t timeout);
|
||||
void rglBufferStorage(GLenum target, GLsizeiptr size, const GLvoid *data, GLbitfield flags);
|
||||
void rglFlushMappedBufferRange(GLenum target, GLintptr offset, GLsizeiptr length);
|
||||
GLenum rglClientWaitSync(void *sync, GLbitfield flags, uint64_t timeout);
|
||||
void rglDrawElementsBaseVertex(GLenum mode, GLsizei count, GLenum type,
|
||||
GLvoid *indices, GLint basevertex);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
|
@ -138,7 +138,7 @@ void string_list_free(struct string_list *list);
|
||||
* @list : pointer to string list.
|
||||
* @delim : delimiter character for @list.
|
||||
*
|
||||
* A string list will be joined/concatenated as a
|
||||
* A string list will be joined/concatenated as a
|
||||
* string to @buffer, delimited by @delim.
|
||||
*/
|
||||
void string_list_join_concat(char *buffer, size_t size,
|
||||
|
@ -33,7 +33,7 @@
|
||||
#elif defined(GEKKO) || defined(__PSL1GHT__) || defined(__QNX__)
|
||||
#include <unistd.h>
|
||||
#elif defined(PSP)
|
||||
#include <pspthreadman.h>
|
||||
#include <pspthreadman.h>
|
||||
#elif defined(VITA)
|
||||
#include <psp2/kernel/threadmgr.h>
|
||||
#elif defined(_3DS)
|
||||
@ -159,6 +159,18 @@ static INLINE float db_to_gain(float db)
|
||||
return powf(10.0f, db / 20.0f);
|
||||
}
|
||||
|
||||
static INLINE uint32_t read_le(const uint8_t *data, unsigned size)
|
||||
{
|
||||
unsigned i;
|
||||
uint32_t val = 0;
|
||||
|
||||
size *= 8;
|
||||
for (i = 0; i < size; i += 8)
|
||||
val |= (uint32_t)*data++ << i;
|
||||
|
||||
return val;
|
||||
}
|
||||
|
||||
/* Helper macros and struct to keep track of many booleans.
|
||||
* To check for multiple bits, use &&, not &.
|
||||
* For OR, | can be used. */
|
||||
|
@ -186,7 +186,7 @@ void string_list_set(struct string_list *list,
|
||||
* @list : pointer to string list.
|
||||
* @delim : delimiter character for @list.
|
||||
*
|
||||
* A string list will be joined/concatenated as a
|
||||
* A string list will be joined/concatenated as a
|
||||
* string to @buffer, delimited by @delim.
|
||||
*/
|
||||
void string_list_join_concat(char *buffer, size_t size,
|
||||
|
@ -28,6 +28,7 @@
|
||||
#include <net/net_compat.h>
|
||||
#include <net/net_socket.h>
|
||||
#include <compat/strl.h>
|
||||
#include <string/stdstring.h>
|
||||
|
||||
enum
|
||||
{
|
||||
@ -350,7 +351,7 @@ bool net_http_update(struct http_t *state, size_t* progress, size_t* total)
|
||||
state->len = strtol(state->data +
|
||||
strlen("Content-Length: "), NULL, 10);
|
||||
}
|
||||
if (!strcmp(state->data, "Transfer-Encoding: chunked"))
|
||||
if (string_is_equal(state->data, "Transfer-Encoding: chunked"))
|
||||
state->bodytype = T_CHUNK;
|
||||
|
||||
/* TODO: save headers somewhere */
|
||||
|
@ -13,9 +13,10 @@ CFLAGS += -Wall -pedantic -std=gnu99
|
||||
|
||||
HTTP_TEST_C = \
|
||||
$(LIBRETRO_COMM_DIR)/net/net_http.c \
|
||||
net_http_test.c \
|
||||
$(LIBRETRO_COMM_DIR)/net/net_compat.c \
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c
|
||||
$(LIBRETRO_COMM_DIR)/compat/compat_strl.c \
|
||||
$(LIBRETRO_COMM_DIR)/string/stdstring.c \
|
||||
net_http_test.c
|
||||
|
||||
HTTP_TEST_OBJS := $(HTTP_TEST_C:.c=.o)
|
||||
|
||||
|
Some files were not shown because too many files have changed in this diff Show More
Loading…
x
Reference in New Issue
Block a user