merge with master
This commit is contained in:
commit
73dde435f7
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
|
||||
|
|
|
@ -1713,6 +1713,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));
|
||||
|
@ -1740,6 +1744,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);
|
||||
}
|
||||
|
|
|
@ -652,7 +652,7 @@ 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",
|
||||
|
@ -1248,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))
|
||||
|
@ -2037,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';
|
||||
|
@ -2070,7 +2080,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
|||
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));
|
||||
}
|
||||
|
@ -2090,7 +2100,7 @@ static bool config_load_file(const char *path, bool set_defaults,
|
|||
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));
|
||||
}
|
||||
|
@ -2145,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;
|
||||
|
@ -2222,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;
|
||||
|
@ -2305,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;
|
||||
|
||||
|
@ -2313,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;
|
||||
|
@ -2428,7 +2438,6 @@ bool config_load_shader_preset(void)
|
|||
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;
|
||||
|
||||
|
@ -2436,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;
|
||||
|
@ -3019,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;
|
||||
|
@ -3037,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;
|
||||
|
|
197
dirs.c
197
dirs.c
|
@ -21,102 +21,153 @@
|
|||
#include <retro_assert.h>
|
||||
#include <retro_stat.h>
|
||||
|
||||
#ifdef HAVE_CONFIG_H
|
||||
#include "config.h"
|
||||
#endif
|
||||
|
||||
#include "dirs.h"
|
||||
|
||||
#include "runloop.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)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return false;
|
||||
return string_is_empty(global->dir.savefile);
|
||||
return string_is_empty(dir_savefile);
|
||||
}
|
||||
|
||||
bool dir_is_savestate_empty(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
return string_is_empty(dir_savestate);
|
||||
}
|
||||
|
||||
if (!global)
|
||||
return false;
|
||||
return string_is_empty(global->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)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global)
|
||||
*global->dir.savefile = '\0';
|
||||
*dir_savefile = '\0';
|
||||
}
|
||||
|
||||
void dir_clear_savestate(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global)
|
||||
*global->dir.savestate = '\0';
|
||||
*dir_savestate = '\0';
|
||||
}
|
||||
|
||||
char *dir_get_savefile_ptr(void)
|
||||
void dir_clear_osk_overlay(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return NULL;
|
||||
return global->dir.savefile;
|
||||
}
|
||||
|
||||
const char *dir_get_savefile(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return NULL;
|
||||
return global->dir.savefile;
|
||||
}
|
||||
|
||||
char *dir_get_savestate_ptr(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return NULL;
|
||||
return global->dir.savestate;
|
||||
}
|
||||
|
||||
const char *dir_get_savestate(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (!global)
|
||||
return NULL;
|
||||
return global->dir.savestate;
|
||||
}
|
||||
|
||||
void dir_set_savestate(const char *path)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global)
|
||||
strlcpy(global->dir.savestate, global->name.savefile,
|
||||
sizeof(global->dir.savestate));
|
||||
}
|
||||
|
||||
void dir_set_savefile(const char *path)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
if (global)
|
||||
strlcpy(global->dir.savefile, global->name.savefile,
|
||||
sizeof(global->dir.savefile));
|
||||
*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));
|
||||
}
|
||||
|
|
48
dirs.h
48
dirs.h
|
@ -21,27 +21,69 @@
|
|||
|
||||
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);
|
||||
|
||||
char *dir_get_savefile_ptr(void);
|
||||
void dir_clear_osk_overlay(void);
|
||||
|
||||
const char *dir_get_savefile(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_clear_all(void);
|
||||
void dir_set_system(const char *path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
||||
|
|
12
dynamic.c
12
dynamic.c
|
@ -51,6 +51,7 @@
|
|||
#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"
|
||||
|
@ -939,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);
|
||||
|
@ -1030,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
|
||||
{
|
||||
|
|
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);
|
||||
|
||||
|
|
|
@ -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)
|
||||
)
|
||||
{
|
||||
|
|
|
@ -1851,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:
|
||||
|
|
|
@ -161,6 +161,7 @@ RETRO_BEGIN_DECLS
|
|||
#define glClearBufferfi rglClearBufferfi
|
||||
#define glWaitSync rglWaitSync
|
||||
#define glFenceSync rglFenceSync
|
||||
#define glDeleteSync rglDeleteSync
|
||||
#define glBufferStorage rglBufferStorage
|
||||
#define glFlushMappedBufferRange rglFlushMappedBufferRange
|
||||
#define glClientWaitSync rglClientWaitSync
|
||||
|
@ -400,6 +401,7 @@ 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);
|
||||
|
|
|
@ -122,7 +122,7 @@ int rmsgpack_write_array_header(RFILE *fd, uint32_t size)
|
|||
|
||||
if (filestream_write(fd, &MPF_ARRAY32, sizeof(MPF_ARRAY32)) == -1)
|
||||
goto error;
|
||||
|
||||
|
||||
tmp_i32 = swap_if_little32(size);
|
||||
|
||||
if (filestream_write(fd, (void *)(&tmp_i32), sizeof(uint32_t)) == -1)
|
||||
|
@ -247,7 +247,7 @@ int rmsgpack_write_bin(RFILE *fd, const void *s, uint32_t len)
|
|||
if (filestream_write(fd, &tmp_i32, sizeof(uint32_t)) == -1)
|
||||
goto error;
|
||||
}
|
||||
|
||||
|
||||
if (filestream_write(fd, s, len) == -1)
|
||||
goto error;
|
||||
|
||||
|
@ -482,6 +482,7 @@ static int read_buff(RFILE *fd, size_t size, char **pbuff, uint64_t *len)
|
|||
|
||||
error:
|
||||
free(*pbuff);
|
||||
*pbuff = NULL;
|
||||
return -errno;
|
||||
}
|
||||
|
||||
|
|
|
@ -1324,7 +1324,6 @@ static void menu_action_setting_disp_set_label_core_option_create(
|
|||
char *s2, size_t len2)
|
||||
{
|
||||
rarch_system_info_t *system = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
runloop_ctl(RUNLOOP_CTL_SYSTEM_INFO_GET, &system);
|
||||
if (!system)
|
||||
|
@ -1335,8 +1334,8 @@ static void menu_action_setting_disp_set_label_core_option_create(
|
|||
|
||||
strlcpy(s, "", len);
|
||||
|
||||
if (!string_is_empty(global->name.base))
|
||||
strlcpy(s, path_basename(global->name.base), len);
|
||||
if (!string_is_empty(path_get_basename()))
|
||||
strlcpy(s, path_basename(path_get_basename()), len);
|
||||
|
||||
strlcpy(s2, path, len2);
|
||||
}
|
||||
|
|
|
@ -1590,8 +1590,7 @@ static int generic_action_ok_shader_preset_save(const char *path,
|
|||
break;
|
||||
case ACTION_OK_SHADER_PRESET_SAVE_GAME:
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
const char *game_name = path_basename(global->name.base);
|
||||
const char *game_name = path_basename(path_get_basename());
|
||||
fill_pathname_join(file, directory, game_name, sizeof(file));
|
||||
}
|
||||
break;
|
||||
|
@ -1699,8 +1698,7 @@ static int generic_action_ok_remap_file_save(const char *path,
|
|||
break;
|
||||
case ACTION_OK_REMAP_FILE_SAVE_GAME:
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
const char *game_name = path_basename(global->name.base);
|
||||
const char *game_name = path_basename(path_get_basename());
|
||||
fill_pathname_join(file, core_name, game_name, sizeof(file));
|
||||
}
|
||||
break;
|
||||
|
|
|
@ -4760,7 +4760,7 @@ static bool setting_append_list(
|
|||
sizeof(settings->path.osk_overlay),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_KEYBOARD_OVERLAY_PRESET),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_KEYBOARD_OVERLAY_PRESET),
|
||||
global->dir.osk_overlay,
|
||||
dir_get_osk_overlay_ptr(),
|
||||
&group_info,
|
||||
&subgroup_info,
|
||||
parent_group,
|
||||
|
@ -6469,8 +6469,8 @@ static bool setting_append_list(
|
|||
|
||||
CONFIG_DIR(
|
||||
list, list_info,
|
||||
global->dir.osk_overlay,
|
||||
sizeof(global->dir.osk_overlay),
|
||||
dir_get_osk_overlay_ptr(),
|
||||
dir_get_osk_overlay_size(),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_OSK_OVERLAY_DIRECTORY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_OSK_OVERLAY_DIRECTORY),
|
||||
g_defaults.dir.osk_overlay,
|
||||
|
@ -6546,7 +6546,7 @@ static bool setting_append_list(
|
|||
CONFIG_DIR(
|
||||
list, list_info,
|
||||
dir_get_savefile_ptr(),
|
||||
sizeof(global->dir.savefile),
|
||||
dir_get_savefile_size(),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_SAVEFILE_DIRECTORY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVEFILE_DIRECTORY),
|
||||
"",
|
||||
|
@ -6561,7 +6561,7 @@ static bool setting_append_list(
|
|||
CONFIG_DIR(
|
||||
list, list_info,
|
||||
dir_get_savestate_ptr(),
|
||||
sizeof(global->dir.savestate),
|
||||
dir_get_savestate_size(),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_SAVESTATE_DIRECTORY),
|
||||
msg_hash_to_str(MENU_ENUM_LABEL_VALUE_SAVESTATE_DIRECTORY),
|
||||
"",
|
||||
|
|
|
@ -45,7 +45,7 @@ enum
|
|||
CMD_OPT_REQUIRE_SYNC = 0x10
|
||||
};
|
||||
|
||||
void *netplay_data;
|
||||
static void *netplay_data = NULL;
|
||||
|
||||
/**
|
||||
* warn_hangup:
|
||||
|
@ -58,7 +58,8 @@ static void warn_hangup(void)
|
|||
runloop_msg_queue_push("Netplay has disconnected. Will continue without connection.", 0, 480, false);
|
||||
}
|
||||
|
||||
static bool netplay_info_cb(netplay_t* netplay, unsigned frames) {
|
||||
static bool netplay_info_cb(netplay_t* netplay, unsigned frames)
|
||||
{
|
||||
return netplay->net_cbs->info_cb(netplay, frames);
|
||||
}
|
||||
|
||||
|
@ -97,7 +98,7 @@ static bool netplay_can_poll(netplay_t *netplay)
|
|||
static bool get_self_input_state(netplay_t *netplay)
|
||||
{
|
||||
uint32_t state[WORDS_PER_FRAME - 1] = {0, 0, 0};
|
||||
struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr];
|
||||
struct delta_frame *ptr = &netplay->buffer[netplay->self_ptr];
|
||||
|
||||
if (!netplay_delta_frame_ready(netplay, ptr, netplay->self_frame_count))
|
||||
return false;
|
||||
|
@ -159,7 +160,8 @@ static bool get_self_input_state(netplay_t *netplay)
|
|||
|
||||
if (!netplay->spectate.enabled) /* Spectate sends in its own way */
|
||||
{
|
||||
if (!socket_send_all_blocking(netplay->fd, netplay->packet_buffer, sizeof(netplay->packet_buffer), false))
|
||||
if (!socket_send_all_blocking(netplay->fd,
|
||||
netplay->packet_buffer, sizeof(netplay->packet_buffer), false))
|
||||
{
|
||||
warn_hangup();
|
||||
netplay->has_connection = false;
|
||||
|
@ -274,7 +276,8 @@ static bool netplay_get_cmd(netplay_t *netplay)
|
|||
|
||||
/* The data's good! */
|
||||
netplay->buffer[netplay->read_ptr].have_remote = true;
|
||||
memcpy(netplay->buffer[netplay->read_ptr].real_input_state, buffer + 1, sizeof(buffer) - sizeof(uint32_t));
|
||||
memcpy(netplay->buffer[netplay->read_ptr].real_input_state,
|
||||
buffer + 1, sizeof(buffer) - sizeof(uint32_t));
|
||||
netplay->read_ptr = NEXT_PTR(netplay->read_ptr);
|
||||
netplay->read_frame_count++;
|
||||
return true;
|
||||
|
@ -348,7 +351,8 @@ static bool netplay_get_cmd(netplay_t *netplay)
|
|||
/* Received a CRC for some frame. If we still have it, check if it
|
||||
* matched. This approach could be improved with some quick modular
|
||||
* arithmetic. */
|
||||
do {
|
||||
do
|
||||
{
|
||||
if (netplay->buffer[tmp_ptr].frame == buffer[0])
|
||||
{
|
||||
found = true;
|
||||
|
@ -792,7 +796,7 @@ static int init_tcp_connection(const struct addrinfo *res,
|
|||
#if defined(IPPROTO_TCP) && defined(TCP_NODELAY)
|
||||
{
|
||||
int flag = 1;
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, &flag, sizeof(int));
|
||||
setsockopt(fd, IPPROTO_TCP, TCP_NODELAY, (void*)&flag, sizeof(int));
|
||||
}
|
||||
#endif
|
||||
|
||||
|
@ -1063,9 +1067,9 @@ error:
|
|||
static void netplay_flip_users(netplay_t *netplay)
|
||||
{
|
||||
/* Must be in the future because we may have already sent this frame's data */
|
||||
uint32_t flip_frame = netplay->self_frame_count + 1;
|
||||
uint32_t flip_frame = netplay->self_frame_count + 1;
|
||||
uint32_t flip_frame_net = htonl(flip_frame);
|
||||
bool command = netplay_command(
|
||||
bool command = netplay_command(
|
||||
netplay, NETPLAY_CMD_FLIP_PLAYERS,
|
||||
&flip_frame_net, sizeof flip_frame_net,
|
||||
CMD_OPT_HOST_ONLY | CMD_OPT_REQUIRE_SYNC,
|
||||
|
@ -1125,13 +1129,14 @@ void netplay_free(netplay_t *netplay)
|
|||
bool netplay_pre_frame(netplay_t *netplay)
|
||||
{
|
||||
retro_assert(netplay && netplay->net_cbs->pre_frame);
|
||||
|
||||
/* FIXME: This is an ugly way to learn we're not paused anymore */
|
||||
if (netplay->local_paused)
|
||||
{
|
||||
/* FIXME: This is an ugly way to learn we're not paused anymore */
|
||||
netplay_frontend_paused(netplay, false);
|
||||
}
|
||||
|
||||
if (!netplay->net_cbs->pre_frame(netplay))
|
||||
return false;
|
||||
|
||||
return (!netplay->has_connection || (!netplay->stall && !netplay->remote_paused));
|
||||
}
|
||||
|
||||
|
@ -1164,13 +1169,14 @@ void netplay_frontend_paused(netplay_t *netplay, bool paused)
|
|||
|
||||
netplay->local_paused = paused;
|
||||
if (netplay->has_connection && !netplay->spectate.enabled)
|
||||
netplay_send_raw_cmd(netplay, paused ? NETPLAY_CMD_PAUSE : NETPLAY_CMD_RESUME, NULL, 0);
|
||||
netplay_send_raw_cmd(netplay, paused
|
||||
? NETPLAY_CMD_PAUSE : NETPLAY_CMD_RESUME, NULL, 0);
|
||||
}
|
||||
|
||||
/**
|
||||
* netplay_load_savestate
|
||||
* @netplay : pointer to netplay object
|
||||
* @serial_info : the savestate being loaded
|
||||
* @serial_info : the savestate being loaded, NULL means "load it yourself"
|
||||
* @save : whether to save the provided serial_info into the frame buffer
|
||||
*
|
||||
* Inform Netplay of a savestate load and send it to the other side
|
||||
|
@ -1178,17 +1184,34 @@ void netplay_frontend_paused(netplay_t *netplay, bool paused)
|
|||
void netplay_load_savestate(netplay_t *netplay, retro_ctx_serialize_info_t *serial_info, bool save)
|
||||
{
|
||||
uint32_t header[3];
|
||||
retro_ctx_serialize_info_t tmp_serial_info;
|
||||
|
||||
if (!netplay->has_connection)
|
||||
return;
|
||||
|
||||
/* Record it in our own buffer */
|
||||
if (save && netplay_delta_frame_ready(netplay, &netplay->buffer[netplay->self_ptr], netplay->self_frame_count))
|
||||
if (save || !serial_info)
|
||||
{
|
||||
if (serial_info->size <= netplay->state_size)
|
||||
if (netplay_delta_frame_ready(netplay,
|
||||
&netplay->buffer[netplay->self_ptr], netplay->self_frame_count))
|
||||
{
|
||||
memcpy(netplay->buffer[netplay->self_ptr].state,
|
||||
serial_info->data_const, serial_info->size);
|
||||
if (!serial_info)
|
||||
{
|
||||
tmp_serial_info.size = netplay->state_size;
|
||||
tmp_serial_info.data = netplay->buffer[netplay->self_ptr].state;
|
||||
if (!core_serialize(&tmp_serial_info))
|
||||
return;
|
||||
tmp_serial_info.data_const = tmp_serial_info.data;
|
||||
serial_info = &tmp_serial_info;
|
||||
}
|
||||
else
|
||||
{
|
||||
if (serial_info->size <= netplay->state_size)
|
||||
{
|
||||
memcpy(netplay->buffer[netplay->self_ptr].state,
|
||||
serial_info->data_const, serial_info->size);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
@ -1208,6 +1231,7 @@ void netplay_load_savestate(netplay_t *netplay, retro_ctx_serialize_info_t *seri
|
|||
header[0] = htonl(NETPLAY_CMD_LOAD_SAVESTATE);
|
||||
header[1] = htonl(serial_info->size + sizeof(uint32_t));
|
||||
header[2] = htonl(netplay->self_frame_count);
|
||||
|
||||
if (!socket_send_all_blocking(netplay->fd, header, sizeof(header), false))
|
||||
{
|
||||
warn_hangup();
|
||||
|
|
|
@ -187,7 +187,7 @@ void netplay_frontend_paused(netplay_t *netplay, bool paused);
|
|||
/**
|
||||
* netplay_load_savestate
|
||||
* @netplay : pointer to netplay object
|
||||
* @serial_info : the savestate being loaded
|
||||
* @serial_info : the savestate being loaded, NULL means "load it yourself"
|
||||
* @save : whether to save the provided serial_info into the frame buffer
|
||||
*
|
||||
* Inform Netplay of a savestate load and send it to the other side
|
||||
|
|
|
@ -167,8 +167,6 @@ struct netplay
|
|||
struct netplay_callbacks* net_cbs;
|
||||
};
|
||||
|
||||
extern void *netplay_data;
|
||||
|
||||
struct netplay_callbacks* netplay_get_cbs_net(void);
|
||||
|
||||
struct netplay_callbacks* netplay_get_cbs_spectate(void);
|
||||
|
|
53
paths.c
53
paths.c
|
@ -43,6 +43,8 @@
|
|||
|
||||
#define MENU_VALUE_NO_CORE 0x7d5472cbU
|
||||
|
||||
static char path_main_basename[PATH_MAX_LENGTH] = {0}
|
||||
;
|
||||
static char current_savefile_dir[PATH_MAX_LENGTH] = {0};
|
||||
static char path_libretro[PATH_MAX_LENGTH] = {0};
|
||||
static char path_config_file[PATH_MAX_LENGTH] = {0};
|
||||
|
@ -152,7 +154,7 @@ void path_set_redirect(void)
|
|||
/* Set savefile directory if empty based on content directory */
|
||||
if (string_is_empty(current_savefile_dir))
|
||||
{
|
||||
strlcpy(current_savefile_dir, global->name.base,
|
||||
strlcpy(current_savefile_dir, path_main_basename,
|
||||
sizeof(current_savefile_dir));
|
||||
path_basedir(current_savefile_dir);
|
||||
}
|
||||
|
@ -167,7 +169,7 @@ void path_set_redirect(void)
|
|||
|
||||
if (path_is_directory(global->name.savefile))
|
||||
{
|
||||
fill_pathname_dir(global->name.savefile, global->name.base,
|
||||
fill_pathname_dir(global->name.savefile, path_main_basename,
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION),
|
||||
sizeof(global->name.savefile));
|
||||
RARCH_LOG("%s \"%s\".\n",
|
||||
|
@ -177,7 +179,7 @@ void path_set_redirect(void)
|
|||
|
||||
if (path_is_directory(global->name.savestate))
|
||||
{
|
||||
fill_pathname_dir(global->name.savestate, global->name.base,
|
||||
fill_pathname_dir(global->name.savestate, path_main_basename,
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
sizeof(global->name.savestate));
|
||||
RARCH_LOG("%s \"%s\".\n",
|
||||
|
@ -187,7 +189,7 @@ void path_set_redirect(void)
|
|||
|
||||
if (path_is_directory(global->name.cheatfile))
|
||||
{
|
||||
fill_pathname_dir(global->name.cheatfile, global->name.base,
|
||||
fill_pathname_dir(global->name.cheatfile, path_main_basename,
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
sizeof(global->name.cheatfile));
|
||||
RARCH_LOG("%s \"%s\".\n",
|
||||
|
@ -199,10 +201,9 @@ void path_set_redirect(void)
|
|||
void path_set_basename(const char *path)
|
||||
{
|
||||
char *dst = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
runloop_ctl(RUNLOOP_CTL_SET_CONTENT_PATH, (void*)path);
|
||||
strlcpy(global->name.base, path, sizeof(global->name.base));
|
||||
strlcpy(path_main_basename, path, sizeof(path_main_basename));
|
||||
|
||||
#ifdef HAVE_COMPRESSION
|
||||
/* Removing extension is a bit tricky for compressed files.
|
||||
|
@ -224,11 +225,11 @@ void path_set_basename(const char *path)
|
|||
* directory then and the name of srm and states are meaningful.
|
||||
*
|
||||
*/
|
||||
path_basedir(global->name.base);
|
||||
fill_pathname_dir(global->name.base, path, "", sizeof(global->name.base));
|
||||
path_basedir(path_main_basename);
|
||||
fill_pathname_dir(path_main_basename, path, "", sizeof(path_main_basename));
|
||||
#endif
|
||||
|
||||
if ((dst = strrchr(global->name.base, '.')))
|
||||
if ((dst = strrchr(path_main_basename, '.')))
|
||||
*dst = '\0';
|
||||
}
|
||||
|
||||
|
@ -265,13 +266,13 @@ void path_set_special(char **argv, unsigned num_content)
|
|||
* It is more complicated for special content types. */
|
||||
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH))
|
||||
fill_pathname_noext(global->name.savestate, global->name.base,
|
||||
fill_pathname_noext(global->name.savestate, path_main_basename,
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
sizeof(global->name.savestate));
|
||||
|
||||
if (path_is_directory(global->name.savestate))
|
||||
{
|
||||
fill_pathname_dir(global->name.savestate, global->name.base,
|
||||
fill_pathname_dir(global->name.savestate, path_main_basename,
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION),
|
||||
sizeof(global->name.savestate));
|
||||
RARCH_LOG("%s \"%s\".\n",
|
||||
|
@ -345,14 +346,14 @@ void path_init_savefile(void)
|
|||
/* Let other relevant paths be inferred from the main SRAM location. */
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH))
|
||||
fill_pathname_noext(global->name.savefile,
|
||||
global->name.base,
|
||||
path_main_basename,
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION),
|
||||
sizeof(global->name.savefile));
|
||||
|
||||
if (path_is_directory(global->name.savefile))
|
||||
{
|
||||
fill_pathname_dir(global->name.savefile,
|
||||
global->name.base,
|
||||
path_main_basename,
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION),
|
||||
sizeof(global->name.savefile));
|
||||
RARCH_LOG("%s \"%s\".\n",
|
||||
|
@ -385,14 +386,14 @@ void path_set_names(const char *path)
|
|||
path_set_basename(path);
|
||||
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_SAVE_PATH))
|
||||
fill_pathname_noext(global->name.savefile, global->name.base,
|
||||
fill_pathname_noext(global->name.savefile, path_main_basename,
|
||||
file_path_str(FILE_PATH_SRM_EXTENSION), sizeof(global->name.savefile));
|
||||
|
||||
if (!retroarch_override_setting_is_set(RARCH_OVERRIDE_SETTING_STATE_PATH))
|
||||
fill_pathname_noext(global->name.savestate, global->name.base,
|
||||
fill_pathname_noext(global->name.savestate, path_main_basename,
|
||||
file_path_str(FILE_PATH_STATE_EXTENSION), sizeof(global->name.savestate));
|
||||
|
||||
fill_pathname_noext(global->name.cheatfile, global->name.base,
|
||||
fill_pathname_noext(global->name.cheatfile, path_main_basename,
|
||||
file_path_str(FILE_PATH_CHT_EXTENSION), sizeof(global->name.cheatfile));
|
||||
|
||||
path_set_redirect();
|
||||
|
@ -405,27 +406,32 @@ void path_fill_names(void)
|
|||
path_init_savefile();
|
||||
bsv_movie_set_path(global->name.savefile);
|
||||
|
||||
if (string_is_empty(global->name.base))
|
||||
if (string_is_empty(path_main_basename))
|
||||
return;
|
||||
|
||||
if (string_is_empty(global->name.ups))
|
||||
fill_pathname_noext(global->name.ups, global->name.base,
|
||||
fill_pathname_noext(global->name.ups, path_main_basename,
|
||||
file_path_str(FILE_PATH_UPS_EXTENSION),
|
||||
sizeof(global->name.ups));
|
||||
|
||||
if (string_is_empty(global->name.bps))
|
||||
fill_pathname_noext(global->name.bps, global->name.base,
|
||||
fill_pathname_noext(global->name.bps, path_main_basename,
|
||||
file_path_str(FILE_PATH_BPS_EXTENSION),
|
||||
sizeof(global->name.bps));
|
||||
|
||||
if (string_is_empty(global->name.ips))
|
||||
fill_pathname_noext(global->name.ips, global->name.base,
|
||||
fill_pathname_noext(global->name.ips, path_main_basename,
|
||||
file_path_str(FILE_PATH_IPS_EXTENSION),
|
||||
sizeof(global->name.ips));
|
||||
}
|
||||
|
||||
/* Core file path */
|
||||
|
||||
const char *path_get_basename(void)
|
||||
{
|
||||
return path_main_basename;
|
||||
}
|
||||
|
||||
char *path_get_core_ptr(void)
|
||||
{
|
||||
return path_libretro;
|
||||
|
@ -484,6 +490,11 @@ void path_clear_config(void)
|
|||
*path_config_file = '\0';
|
||||
}
|
||||
|
||||
void path_clear_basename(void)
|
||||
{
|
||||
*path_main_basename = '\0';
|
||||
}
|
||||
|
||||
/* Core options file path */
|
||||
|
||||
bool path_is_core_options_empty(void)
|
||||
|
@ -545,6 +556,8 @@ void path_clear_all(void)
|
|||
path_clear_config();
|
||||
path_clear_config_append();
|
||||
path_clear_core_options();
|
||||
|
||||
path_clear_basename();
|
||||
}
|
||||
|
||||
enum rarch_content_type path_is_media_type(const char *path)
|
||||
|
|
36
paths.h
36
paths.h
|
@ -29,10 +29,16 @@ enum rarch_content_type
|
|||
RARCH_CONTENT_IMAGE
|
||||
};
|
||||
|
||||
/* init functions */
|
||||
|
||||
void path_init_savefile(void);
|
||||
|
||||
/* fill functions */
|
||||
|
||||
void path_fill_names(void);
|
||||
|
||||
/* set functions */
|
||||
|
||||
void path_set_redirect(void);
|
||||
|
||||
void path_set_names(const char *path);
|
||||
|
@ -49,10 +55,20 @@ void path_set_config(const char *path);
|
|||
|
||||
void path_set_config_append(const char *path);
|
||||
|
||||
/* get size functions */
|
||||
|
||||
size_t path_get_core_size(void);
|
||||
|
||||
/* get ptr functions */
|
||||
|
||||
char *path_get_core_ptr(void);
|
||||
|
||||
/* get functions */
|
||||
|
||||
const char *path_get_current_savefile_dir(void);
|
||||
|
||||
const char *path_get_basename(void);
|
||||
|
||||
const char *path_get_core(void);
|
||||
|
||||
const char *path_get_core_options(void);
|
||||
|
@ -61,15 +77,9 @@ const char *path_get_config(void);
|
|||
|
||||
const char *path_get_config_append(void);
|
||||
|
||||
size_t path_get_core_size(void);
|
||||
/* clear functions */
|
||||
|
||||
bool path_is_core_empty(void);
|
||||
|
||||
bool path_is_config_empty(void);
|
||||
|
||||
bool path_is_core_options_empty(void);
|
||||
|
||||
bool path_is_config_append_empty(void);
|
||||
void path_clear_basename(void);
|
||||
|
||||
void path_clear_core(void);
|
||||
|
||||
|
@ -81,6 +91,16 @@ void path_clear_config_append(void);
|
|||
|
||||
void path_clear_all(void);
|
||||
|
||||
/* is functions */
|
||||
|
||||
bool path_is_core_empty(void);
|
||||
|
||||
bool path_is_config_empty(void);
|
||||
|
||||
bool path_is_core_options_empty(void);
|
||||
|
||||
bool path_is_config_append_empty(void);
|
||||
|
||||
enum rarch_content_type path_is_media_type(const char *path);
|
||||
|
||||
RETRO_END_DECLS
|
||||
|
|
|
@ -3,6 +3,8 @@
|
|||
*
|
||||
* This provides the basic JavaScript for the RetroArch web player.
|
||||
*/
|
||||
|
||||
/* setup your key for dropbox support */
|
||||
var client = new Dropbox.Client({ key: "--your-api-key--" });
|
||||
var BrowserFS = browserfs;
|
||||
var afs;
|
||||
|
@ -45,12 +47,18 @@ var showError = function(error) {
|
|||
}
|
||||
};
|
||||
|
||||
function cleanupStorage()
|
||||
{
|
||||
localStorage.clear();
|
||||
document.getElementById('btnClean').disabled = true;
|
||||
}
|
||||
|
||||
function dropboxInit()
|
||||
{
|
||||
document.getElementById('btnRun').disabled = true;
|
||||
document.getElementById('btnDrop').disabled = true;
|
||||
$('#icnDrop').removeClass('fa-dropbox');
|
||||
$('#icnDrop').addClass('fa-spinner fa-spin');
|
||||
//document.getElementById('btnDrop').disabled = true;
|
||||
//$('#icnDrop').removeClass('fa-dropbox');
|
||||
//$('#icnDrop').addClass('fa-spinner fa-spin');
|
||||
|
||||
|
||||
client.authDriver(new Dropbox.AuthDriver.Redirect());
|
||||
|
@ -67,8 +75,8 @@ function dropboxInit()
|
|||
function dropboxSyncComplete()
|
||||
{
|
||||
document.getElementById('btnRun').disabled = false;
|
||||
$('#icnDrop').removeClass('fa-spinner').removeClass('fa-spin');
|
||||
$('#icnDrop').addClass('fa-check');
|
||||
//$('#icnDrop').removeClass('fa-spinner').removeClass('fa-spin');
|
||||
//$('#icnDrop').addClass('fa-check');
|
||||
console.log("WEBPLAYER: Sync successful");
|
||||
|
||||
setupFileSystem("dropbox");
|
||||
|
@ -106,6 +114,9 @@ function setupFileSystem(backend)
|
|||
mountpoint for browserfs */
|
||||
var mfs = new BrowserFS.FileSystem.MountableFileSystem();
|
||||
|
||||
/* setup this if you setup your server to serve assets or core assets,
|
||||
you can find more information in the included README */
|
||||
|
||||
/* create an XmlHttpRequest filesystem for the bundled data
|
||||
uncomment this section if you want XMB assets, Overlays, Shaders, etc.
|
||||
var xfs1 = new BrowserFS.FileSystem.XmlHttpRequest
|
||||
|
@ -126,11 +137,6 @@ function setupFileSystem(backend)
|
|||
/* mount the filesystems onto mfs */
|
||||
mfs.mount('/home/web_user/retroarch/userdata', lsfs);
|
||||
|
||||
/* create a memory filesystem for content only
|
||||
var imfs = new BrowserFS.FileSystem.InMemory();*/
|
||||
|
||||
/* mount the filesystems onto mfs
|
||||
mfs.mount('/home/web_user/retroarch/userdata/content/', imfs);*/
|
||||
}
|
||||
else
|
||||
{
|
||||
|
@ -138,6 +144,8 @@ function setupFileSystem(backend)
|
|||
mfs.mount('/home/web_user/retroarch/userdata', afs);
|
||||
}
|
||||
|
||||
/* setup this if you setup your server to serve assets or core assets,
|
||||
you can find more information in the included README */
|
||||
/*
|
||||
mfs.mount('/home/web_user/retroarch/bundle', xfs1);
|
||||
mfs.mount('/home/web_user/retroarch/userdata/content/', xfs2);
|
||||
|
@ -162,7 +170,7 @@ function startRetroArch()
|
|||
{
|
||||
$('.webplayer').show();
|
||||
$('.webplayer-preview').hide();
|
||||
document.getElementById('btnDrop').disabled = true;
|
||||
//document.getElementById('btnDrop').disabled = true;
|
||||
document.getElementById('btnRun').disabled = true;
|
||||
|
||||
$('#btnFullscreen').removeClass('disabled');
|
||||
|
|
|
@ -17,18 +17,9 @@
|
|||
<body>
|
||||
<!--Navbar-->
|
||||
<nav class="navbar navbar-dark bg-warning">
|
||||
|
||||
<!-- Collapse button-->
|
||||
<button class="navbar-toggler hidden-sm-up" type="button" data-toggle="collapse" data-target="#collapseEx2">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!--Collapse content-->
|
||||
<div class="collapse navbar-toggleable-xs" id="collapseEx2">
|
||||
<!--Navbar Brand-->
|
||||
<a class="navbar-brand" href="#">RetroArch</a>
|
||||
<!--Links-->
|
||||
<ul class="nav navbar-nav">
|
||||
<div class="dropdown">
|
||||
|
@ -89,6 +80,9 @@
|
|||
<button class="btn btn-warning disabled" id="btnAdd" onclick="document.getElementById('btnRom').click()" disabled>
|
||||
<span class="fa fa-plus" id="icnAdd"></span> Add Content
|
||||
</button>
|
||||
<button class="btn btn-warning" id="btnClean" onclick="cleanupStorage();" title="Cleanup">
|
||||
<span class="fa fa-trash-o" id="icnClean"></span> <span class="sr-only">Cleanup</span>
|
||||
</button>
|
||||
<input class="btn btn-warning disabled" style="display: none" type="file" id="btnRom" name="upload" onclick="document.getElementById('btnAdd').click();" onchange="selectFiles(event.target.files)" multiple />
|
||||
<button class="btn btn-warning disabled" id="btnFullscreen" onclick="Module.requestFullScreen()" title="Fullscreen" disabled>
|
||||
<span class="fa fa-desktop" id="icnAdd"></span> <span class="sr-only">Fullscreen</span>
|
||||
|
@ -120,11 +114,12 @@
|
|||
<span class="fa fa-chrome" id="icnLocal"></span> Browser
|
||||
</input>
|
||||
</label>
|
||||
<!--uncomment for dropbox support
|
||||
<label class="btn btn-warning" id="lblDrop" onclick=switchStorage("dropbox")>
|
||||
<input type="radio" name="options" id="btnDrop" autocomplete="off">
|
||||
<span class="fa fa-dropbox" id="icnDrop"></span> Dropbox
|
||||
</input>
|
||||
</label>
|
||||
</label>-->
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -18,14 +18,7 @@
|
|||
<body>
|
||||
<!--Navbar-->
|
||||
<nav class="navbar navbar-dark bg-danger">
|
||||
|
||||
<!-- Collapse button-->
|
||||
<button class="navbar-toggler hidden-sm-up" type="button" data-toggle="collapse" data-target="#collapseEx2">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<!--Collapse content-->
|
||||
<div class="collapse navbar-toggleable-xs" id="collapseEx2">
|
||||
<!--Navbar Brand-->
|
||||
|
@ -48,15 +41,15 @@
|
|||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="fbalpha2012_neo">FB Alpha 2012 NeoGeo</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="fceumm">FCEUmm</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="ffmpeg">FFmpeg</a>-->
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="gambatte">Gambatte (Gameboy / Gameboy Color)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="genesis_plus_gx">Genesis Plus GX (Megadrive / Game Gear / Master System)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="gambatte">Gambatte (GB/GBC)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="genesis_plus_gx">Genesis Plus GX (MD / GG / SMS)</a>
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="gme">Game Music Emu</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="gpsp">gPSP</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="handy">Handy</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mame2000">MAME 2000</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_lynx">Mednafen Lynx</a>-->
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_ngp">Mednafen NeoPop (NeoGeo Pocket)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_pce_fast">Mednafen PCE-Fast (PC Engine / TurboGrafx-16)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_ngp">Mednafen NeoPop (NGP)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_pce_fast">Mednafen PCE-Fast (PC-E/TG-16)</a>
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_pcfx">Mednafen/Beetle PCFX</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_psx">Mednafen/Beetle PSX</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_saturn">Mednafen/Beetle Saturn</a>-->
|
||||
|
@ -64,7 +57,7 @@
|
|||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_vb">Mednafen/Beetle Virtual Boy</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mednafen_wswan">Mednafen/Beetle WonderSwan</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="mupen64plus">Mupen64 Plus</a>-->
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="nestopia">Nestopia (Nintendo Entertainment System)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="nestopia">Nestopia (NES)</a>
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="nxengine">NX Engine</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="o2em">O2em</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="picodrive">PicoDrive</a>-->
|
||||
|
@ -72,7 +65,7 @@
|
|||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="quicknes">QuickNES</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="snes9x2002">Snes9x 2002</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="snes9x2005">Snes9x 2005</a>-->
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="snes9x2010">Snes9x 2010 (Super Nintendo Entertainment System)</a>
|
||||
<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="snes9x2010">Snes9x 2010 (SNES)</a>
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="snes9x">Snes9x</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="stella">Stella</a>-->
|
||||
<!--<a class="dropdown-item" href="https://libretro.itch.io/retroarch" data-core="tgbdual">TGB Dual</a>-->
|
||||
|
@ -88,6 +81,9 @@
|
|||
<button class="btn btn-danger disabled" id="btnAdd" onclick="document.getElementById('btnRom').click()" title="Add Games" disabled>
|
||||
<span class="fa fa-plus" id="icnAdd"></span> </span> <span class="sr-only"></span>
|
||||
</button>
|
||||
<button class="btn btn-danger" id="btnClean" onclick="cleanupStorage();" title="Cleanup">
|
||||
<span class="fa fa-trash-o" id="icnClean"></span> <span class="sr-only">Cleanup</span>
|
||||
</button>
|
||||
<input class="btn btn-danger disabled" style="display: none" type="file" id="btnRom" name="upload" onclick="document.getElementById('btnAdd').click();" onchange="selectFiles(event.target.files)" multiple />
|
||||
<button class="btn btn-danger disabled" id="btnFullscreen" onclick="Module.requestFullScreen()" title="Fullscreen" disabled>
|
||||
<span class="fa fa-desktop" id="icnAdd"></span> <span class="sr-only">Fullscreen</span>
|
||||
|
|
|
@ -45,9 +45,10 @@ var showError = function(error) {
|
|||
}
|
||||
};
|
||||
|
||||
function reload()
|
||||
function cleanupStorage()
|
||||
{
|
||||
window.top.location.reload();
|
||||
localStorage.clear();
|
||||
document.getElementById('btnClean').disabled = true;
|
||||
}
|
||||
|
||||
function dropboxInit()
|
||||
|
|
|
@ -18,85 +18,78 @@
|
|||
<body>
|
||||
<!--Navbar-->
|
||||
<nav class="navbar navbar-dark bg-primary">
|
||||
|
||||
<!-- Collapse button-->
|
||||
<button class="navbar-toggler hidden-sm-up" type="button" data-toggle="collapse" data-target="#collapseEx2">
|
||||
<i class="fa fa-bars"></i>
|
||||
</button>
|
||||
|
||||
<div class="container">
|
||||
|
||||
<div class="container">
|
||||
<!--Collapse content-->
|
||||
<div class="collapse navbar-toggleable-xs" id="collapseEx2">
|
||||
<!--Navbar Brand-->
|
||||
<a class="navbar-brand" href="#">RetroArch</a>
|
||||
<!--Links-->
|
||||
<ul class="nav navbar-nav">
|
||||
<div class="dropdown">
|
||||
<li class="nav-item dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Core Selection</button>
|
||||
<div class="dropdown-menu dropdown-primary" aria-labelledby="dropdownMenu1" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut" id="core-selector">
|
||||
<a class="dropdown-item" href="." data-core="2048">2048</a>
|
||||
<a class="dropdown-item" href="." data-core="4do">4DO</a>
|
||||
<a class="dropdown-item" href="." data-core="bluemsx">BlueMSX</a>
|
||||
<a class="dropdown-item" href="." data-core="craft">Craft</a>
|
||||
<a class="dropdown-item" href="." data-core="desmume">DeSmuME</a>
|
||||
<a class="dropdown-item" href="." data-core="dosbox">DOSBox</a>
|
||||
<a class="dropdown-item" href="." data-core="easyrpg">EasyRPG</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012">FB Alpha 2012</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_cps1">FB Alpha 2012 CPS1</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_cps2">FB Alpha 2012 CPS2</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_neo">FB Alpha 2012 NeoGeo</a>
|
||||
<a class="dropdown-item" href="." data-core="fceumm">FCEUmm</a>
|
||||
<a class="dropdown-item" href="." data-core="ffmpeg">FFmpeg</a>
|
||||
<a class="dropdown-item" href="." data-core="gambatte">Gambatte</a>
|
||||
<a class="dropdown-item" href="." data-core="genesis_plus_gx">Genesis Plus GX</a>
|
||||
<a class="dropdown-item" href="." data-core="gme">Game Music Emu</a>
|
||||
<a class="dropdown-item" href="." data-core="gpsp">gPSP</a>
|
||||
<a class="dropdown-item" href="." data-core="handy">Handy</a>
|
||||
<a class="dropdown-item" href="." data-core="mame2000">MAME 2000</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_lynx">Mednafen Lynx</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_ngp">Mednafen Neo Geo Pocket</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_pce_fast">Mednafen PC Engine Fast</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_pcfx">Mednafen/Beetle PCFX</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_psx">Mednafen/Beetle PSX</a>
|
||||
<!--<a class="dropdown-item" href="." data-core="mednafen_saturn">Mednafen/Beetle Saturn</a>-->
|
||||
<a class="dropdown-item" href="." data-core="mednafen_snes">Mednafen/Beetle SNES</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_vb">Mednafen/Beetle Virtual Boy</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_wswan">Mednafen/Beetle WonderSwan</a>
|
||||
<a class="dropdown-item" href="." data-core="mupen64plus">Mupen64 Plus</a>
|
||||
<a class="dropdown-item" href="." data-core="nestopia">Nestopia</a>
|
||||
<a class="dropdown-item" href="." data-core="nxengine">NX Engine</a>
|
||||
<a class="dropdown-item" href="." data-core="o2em">O2em</a>
|
||||
<a class="dropdown-item" href="." data-core="picodrive">PicoDrive</a>
|
||||
<a class="dropdown-item" href="." data-core="prboom">PrBoom</a>
|
||||
<a class="dropdown-item" href="." data-core="quicknes">QuickNES</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2002">Snes9x 2002</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2005">Snes9x 2005</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2010">Snes9x 2010</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x">Snes9x</a>
|
||||
<a class="dropdown-item" href="." data-core="stella">Stella</a>
|
||||
<a class="dropdown-item" href="." data-core="tgbdual">TGB Dual</a>
|
||||
<a class="dropdown-item" href="." data-core="tyrquake">TyrQuake</a>
|
||||
<a class="dropdown-item" href="." data-core="vba_next">VBA Next</a>
|
||||
<a class="dropdown-item" href="." data-core="vecx">Vecx</a>
|
||||
<a class="dropdown-item" href="." data-core="virtualjaguar">Virtual Jaguar</a>
|
||||
<a class="dropdown-item" href="." data-core="yabause">Yabause</a>
|
||||
</div>
|
||||
|
||||
<button class="btn btn-primary disabled" id="btnRun" onclick="startRetroArch()" disabled>
|
||||
<span class="fa fa-spinner fa-spin" id="icnRun"></span> Run
|
||||
</button>
|
||||
<button class="btn btn-primary disabled" id="btnAdd" onclick="document.getElementById('btnRom').click()" disabled>
|
||||
<span class="fa fa-plus" id="icnAdd"></span> Add Content
|
||||
</button>
|
||||
<input class="btn btn-primary disabled" style="display: none" type="file" id="btnRom" name="upload" onclick="document.getElementById('btnAdd').click();" onchange="selectFiles(event.target.files)" multiple />
|
||||
<button class="btn btn-primary disabled" id="btnFullscreen" onclick="Module.requestFullScreen()" title="Fullscreen" disabled>
|
||||
<span class="fa fa-desktop" id="icnAdd"></span> <span class="sr-only">Fullscreen</span>
|
||||
</button>
|
||||
<button class="btn btn-primary disabled" id="btnMenu" onclick="keyPress(112);" title="Menu toggle" disabled>
|
||||
<span class="fa fa-bars" id="btnMenu"></span> <span class="sr-only">Menu</span>
|
||||
</button>
|
||||
<li class="nav-item dropdown">
|
||||
<button class="btn btn-primary dropdown-toggle" type="button" id="dropdownMenu1" data-toggle="dropdown" aria-haspopup="true" aria-expanded="false">Core Selection</button>
|
||||
<div class="dropdown-menu dropdown-primary" aria-labelledby="dropdownMenu1" data-dropdown-in="fadeIn" data-dropdown-out="fadeOut" id="core-selector">
|
||||
<a class="dropdown-item" href="." data-core="2048">2048</a>
|
||||
<a class="dropdown-item" href="." data-core="4do">4DO</a>
|
||||
<a class="dropdown-item" href="." data-core="bluemsx">BlueMSX</a>
|
||||
<a class="dropdown-item" href="." data-core="craft">Craft</a>
|
||||
<a class="dropdown-item" href="." data-core="desmume">DeSmuME</a>
|
||||
<a class="dropdown-item" href="." data-core="dosbox">DOSBox</a>
|
||||
<a class="dropdown-item" href="." data-core="easyrpg">EasyRPG</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012">FB Alpha 2012</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_cps1">FB Alpha 2012 CPS1</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_cps2">FB Alpha 2012 CPS2</a>
|
||||
<a class="dropdown-item" href="." data-core="fbalpha2012_neo">FB Alpha 2012 NeoGeo</a>
|
||||
<a class="dropdown-item" href="." data-core="fceumm">FCEUmm</a>
|
||||
<a class="dropdown-item" href="." data-core="ffmpeg">FFmpeg</a>
|
||||
<a class="dropdown-item" href="." data-core="gambatte">Gambatte</a>
|
||||
<a class="dropdown-item" href="." data-core="genesis_plus_gx">Genesis Plus GX</a>
|
||||
<a class="dropdown-item" href="." data-core="gme">Game Music Emu</a>
|
||||
<a class="dropdown-item" href="." data-core="gpsp">gPSP</a>
|
||||
<a class="dropdown-item" href="." data-core="handy">Handy</a>
|
||||
<a class="dropdown-item" href="." data-core="mame2000">MAME 2000</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_lynx">Mednafen Lynx</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_ngp">Mednafen Neo Geo Pocket</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_pce_fast">Mednafen PC Engine Fast</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_pcfx">Mednafen/Beetle PCFX</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_psx">Mednafen/Beetle PSX</a>
|
||||
<!--<a class="dropdown-item" href="." data-core="mednafen_saturn">Mednafen/Beetle Saturn</a>-->
|
||||
<a class="dropdown-item" href="." data-core="mednafen_snes">Mednafen/Beetle SNES</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_vb">Mednafen/Beetle Virtual Boy</a>
|
||||
<a class="dropdown-item" href="." data-core="mednafen_wswan">Mednafen/Beetle WonderSwan</a>
|
||||
<a class="dropdown-item" href="." data-core="mupen64plus">Mupen64 Plus</a>
|
||||
<a class="dropdown-item" href="." data-core="nestopia">Nestopia</a>
|
||||
<a class="dropdown-item" href="." data-core="nxengine">NX Engine</a>
|
||||
<a class="dropdown-item" href="." data-core="o2em">O2em</a>
|
||||
<a class="dropdown-item" href="." data-core="picodrive">PicoDrive</a>
|
||||
<a class="dropdown-item" href="." data-core="prboom">PrBoom</a>
|
||||
<a class="dropdown-item" href="." data-core="quicknes">QuickNES</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2002">Snes9x 2002</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2005">Snes9x 2005</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x2010">Snes9x 2010</a>
|
||||
<a class="dropdown-item" href="." data-core="snes9x">Snes9x</a>
|
||||
<a class="dropdown-item" href="." data-core="stella">Stella</a>
|
||||
<a class="dropdown-item" href="." data-core="tgbdual">TGB Dual</a>
|
||||
<a class="dropdown-item" href="." data-core="tyrquake">TyrQuake</a>
|
||||
<a class="dropdown-item" href="." data-core="vba_next">VBA Next</a>
|
||||
<a class="dropdown-item" href="." data-core="vecx">Vecx</a>
|
||||
<a class="dropdown-item" href="." data-core="virtualjaguar">Virtual Jaguar</a>
|
||||
<a class="dropdown-item" href="." data-core="yabause">Yabause</a>
|
||||
</div>
|
||||
<button class="btn btn-primary disabled" id="btnRun" onclick="startRetroArch()" disabled>
|
||||
<span class="fa fa-spinner fa-spin" id="icnRun"></span> Run
|
||||
</button>
|
||||
<button class="btn btn-primary disabled" id="btnAdd" onclick="document.getElementById('btnRom').click()" disabled>
|
||||
<span class="fa fa-plus" id="icnAdd"></span> Add Content
|
||||
</button>
|
||||
<button class="btn btn-primary" id="btnClean" onclick="cleanupStorage();" title="Cleanup">
|
||||
<span class="fa fa-trash-o" id="icnClean"></span> <span class="sr-only">Cleanup</span>
|
||||
</button>
|
||||
<input class="btn btn-primary disabled" style="display: none" type="file" id="btnRom" name="upload" onclick="document.getElementById('btnAdd').click();" onchange="selectFiles(event.target.files)" multiple />
|
||||
<button class="btn btn-primary disabled" id="btnMenu" onclick="keyPress(112);" title="Menu toggle" disabled>
|
||||
<span class="fa fa-bars" id="btnMenu"></span> <span class="sr-only">Menu</span>
|
||||
</button>
|
||||
<button class="btn btn-primary disabled" id="btnFullscreen" onclick="Module.requestFullScreen()" title="Fullscreen" disabled>
|
||||
<span class="fa fa-desktop" id="icnAdd"></span> <span class="sr-only">Fullscreen</span>
|
||||
</button>
|
||||
</li>
|
||||
</div>
|
||||
</ul>
|
||||
|
@ -114,18 +107,18 @@
|
|||
</div>
|
||||
<div class="container">
|
||||
<div class="row">
|
||||
<div class="col-sm-12 form-group btn-group text-xs-center p-t-2">
|
||||
<div class="col-sm-12 form-group btn-group text-xs-left p-t-2">
|
||||
<div class="btn-group" data-toggle="buttons">
|
||||
<label class="btn btn-primary" id="lblLocal" onclick=switchStorage("browser")>
|
||||
<input type="radio" name="options" id="btnLocal" autocomplete="off" checked>
|
||||
<span class="fa fa-chrome" id="icnLocal"></span> Browser
|
||||
<span class="fa fa-globe" id="icnLocal"></span> Browser
|
||||
</input>
|
||||
</label>
|
||||
<label class="btn btn-primary" id="lblDrop" onclick=switchStorage("dropbox")>
|
||||
<label class="btn btn-primary" id="lblDrop" onclick=switchStorage("dropbox")>
|
||||
<input type="radio" name="options" id="btnDrop" autocomplete="off">
|
||||
<span class="fa fa-dropbox" id="icnDrop"></span> Dropbox
|
||||
</input>
|
||||
</label>
|
||||
</label>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
@ -136,7 +129,6 @@
|
|||
<textarea id="output" rows="15"></textarea>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
|
|
@ -45,6 +45,12 @@ var showError = function(error) {
|
|||
}
|
||||
};
|
||||
|
||||
function cleanupStorage()
|
||||
{
|
||||
localStorage.clear();
|
||||
document.getElementById("btnClean").disabled = true;
|
||||
}
|
||||
|
||||
function dropboxInit()
|
||||
{
|
||||
document.getElementById('btnRun').disabled = true;
|
||||
|
|
|
@ -882,14 +882,13 @@ bool retroarch_validate_game_options(char *s, size_t len, bool mkdir)
|
|||
const char *core_name = NULL;
|
||||
const char *game_name = NULL;
|
||||
rarch_system_info_t *system = NULL;
|
||||
global_t *global = global_get_ptr();
|
||||
|
||||
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;
|
||||
|
|
14
runloop.h
14
runloop.h
|
@ -140,17 +140,6 @@ enum runloop_ctl_state
|
|||
RUNLOOP_CTL_HTTPSERVER_DESTROY
|
||||
};
|
||||
|
||||
typedef struct rarch_dir
|
||||
{
|
||||
/* Used on reentrancy to use a savestate dir. */
|
||||
char savefile[PATH_MAX_LENGTH];
|
||||
char savestate[PATH_MAX_LENGTH];
|
||||
char systemdir[PATH_MAX_LENGTH];
|
||||
#ifdef HAVE_OVERLAY
|
||||
char osk_overlay[PATH_MAX_LENGTH];
|
||||
#endif
|
||||
} rarch_dir_t;
|
||||
|
||||
typedef struct rarch_resolution
|
||||
{
|
||||
unsigned idx;
|
||||
|
@ -161,8 +150,6 @@ typedef struct rarch_resolution
|
|||
|
||||
typedef struct global
|
||||
{
|
||||
rarch_dir_t dir;
|
||||
|
||||
struct
|
||||
{
|
||||
bool libretro_device[MAX_USERS];
|
||||
|
@ -170,7 +157,6 @@ typedef struct global
|
|||
|
||||
struct
|
||||
{
|
||||
char base[PATH_MAX_LENGTH];
|
||||
char savefile[PATH_MAX_LENGTH];
|
||||
char savestate[PATH_MAX_LENGTH];
|
||||
char cheatfile[PATH_MAX_LENGTH];
|
||||
|
|
|
@ -108,6 +108,610 @@ static bool _content_is_inited = false;
|
|||
static bool core_does_not_need_content = false;
|
||||
static uint32_t content_crc = 0;
|
||||
|
||||
#ifdef HAVE_COMPRESSION
|
||||
/**
|
||||
* filename_split_archive:
|
||||
* @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.
|
||||
*/
|
||||
static struct string_list *filename_split_archive(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;
|
||||
}
|
||||
|
||||
#ifdef HAVE_7ZIP
|
||||
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);
|
||||
}
|
||||
|
||||
static 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;
|
||||
}
|
||||
|
||||
/* 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 content_7zip_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;
|
||||
|
||||
if (InFile_Open(&archiveStream.file, path))
|
||||
{
|
||||
RARCH_ERR("Could not open %s as 7z archive\n.", 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)
|
||||
{
|
||||
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;
|
||||
}
|
||||
}
|
||||
|
||||
free(temp);
|
||||
IAlloc_Free(&allocImp, output);
|
||||
|
||||
if (!(file_found && res == SZ_OK))
|
||||
{
|
||||
/* Error handling */
|
||||
if (!file_found)
|
||||
RARCH_ERR("%s: %s in %s.\n",
|
||||
msg_hash_to_str(MSG_FILE_NOT_FOUND),
|
||||
needle, path);
|
||||
|
||||
RARCH_ERR("Failed to open compressed file inside 7zip archive.\n");
|
||||
|
||||
outsize = -1;
|
||||
}
|
||||
}
|
||||
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
File_Close(&archiveStream.file);
|
||||
|
||||
return outsize;
|
||||
}
|
||||
|
||||
static struct string_list *compressed_7zip_file_list_new(
|
||||
const char *path, const char* ext)
|
||||
{
|
||||
CFileInStream archiveStream;
|
||||
CLookToRead lookStream;
|
||||
ISzAlloc allocImp;
|
||||
ISzAlloc allocTempImp;
|
||||
CSzArEx db;
|
||||
size_t temp_size = 0;
|
||||
struct string_list *list = NULL;
|
||||
|
||||
/* These are the allocation routines - currently using
|
||||
* the non-standard 7zip choices. */
|
||||
allocImp.Alloc = SzAlloc;
|
||||
allocImp.Free = SzFree;
|
||||
allocTempImp.Alloc = SzAllocTemp;
|
||||
allocTempImp.Free = SzFreeTemp;
|
||||
|
||||
if (InFile_Open(&archiveStream.file, path))
|
||||
{
|
||||
RARCH_ERR("Could not open as 7zip archive: %s.\n",path);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
list = string_list_new();
|
||||
|
||||
if (!list)
|
||||
{
|
||||
File_Close(&archiveStream.file);
|
||||
return NULL;
|
||||
}
|
||||
|
||||
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;
|
||||
struct string_list *ext_list = ext ? string_split(ext, "|"): NULL;
|
||||
SRes res = SZ_OK;
|
||||
uint16_t *temp = NULL;
|
||||
|
||||
for (i = 0; i < db.db.NumFiles; i++)
|
||||
{
|
||||
union string_list_elem_attr attr;
|
||||
char infile[PATH_MAX_LENGTH] = {0};
|
||||
const char *file_ext = NULL;
|
||||
size_t len = 0;
|
||||
bool supported_by_core = false;
|
||||
const CSzFileItem *f = db.db.Files + i;
|
||||
|
||||
/* we skip over everything, which is a directory. */
|
||||
if (f->IsDir)
|
||||
continue;
|
||||
|
||||
len = SzArEx_GetFileNameUtf16(&db, i, NULL);
|
||||
|
||||
if (len > temp_size)
|
||||
{
|
||||
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;
|
||||
|
||||
file_ext = path_get_extension(infile);
|
||||
|
||||
if (string_list_find_elem_prefix(ext_list, ".", file_ext))
|
||||
supported_by_core = true;
|
||||
|
||||
/*
|
||||
* Currently we only support files without subdirs in the archives.
|
||||
* Folders are not supported (differences between win and lin.
|
||||
* Archives within archives should imho never be supported.
|
||||
*/
|
||||
|
||||
if (!supported_by_core)
|
||||
continue;
|
||||
|
||||
attr.i = RARCH_COMPRESSED_FILE_IN_ARCHIVE;
|
||||
|
||||
if (!string_list_append(list, infile, attr))
|
||||
{
|
||||
res = SZ_ERROR_MEM;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
string_list_free(ext_list);
|
||||
free(temp);
|
||||
|
||||
if (res != SZ_OK)
|
||||
{
|
||||
/* Error handling */
|
||||
RARCH_ERR("Failed to open compressed_file: \"%s\"\n", path);
|
||||
|
||||
string_list_free(list);
|
||||
list = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
SzArEx_Free(&db, &allocImp);
|
||||
File_Close(&archiveStream.file);
|
||||
|
||||
return list;
|
||||
}
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_ZLIB
|
||||
struct decomp_state
|
||||
{
|
||||
char *opt_file;
|
||||
char *needle;
|
||||
void **buf;
|
||||
size_t size;
|
||||
bool found;
|
||||
};
|
||||
|
||||
static bool content_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 = file_archive_get_default_file_backend();
|
||||
|
||||
if (!handle->backend)
|
||||
goto error;
|
||||
|
||||
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);
|
||||
|
||||
handle->real_checksum = handle->backend->stream_crc_calculate(0,
|
||||
handle->data, size);
|
||||
|
||||
if (handle->real_checksum != crc32)
|
||||
{
|
||||
RARCH_ERR("%s\n",
|
||||
msg_hash_to_str(MSG_INFLATED_CHECKSUM_DID_NOT_MATCH_CRC32));
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (handle->stream)
|
||||
free(handle->stream);
|
||||
|
||||
return true;
|
||||
|
||||
error:
|
||||
if (handle->stream)
|
||||
free(handle->stream);
|
||||
if (handle->data)
|
||||
free(handle->data);
|
||||
|
||||
handle->stream = NULL;
|
||||
handle->data = NULL;
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
/* 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 content_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, void *userdata)
|
||||
{
|
||||
struct decomp_state *st = (struct decomp_state*)userdata;
|
||||
|
||||
/* Ignore directories. */
|
||||
if (name[strlen(name) - 1] == '/' || name[strlen(name) - 1] == '\\')
|
||||
return 1;
|
||||
|
||||
RARCH_LOG("[deflate] Path: %s, CRC32: 0x%x\n", name, crc32);
|
||||
|
||||
if (strstr(name, st->needle))
|
||||
{
|
||||
bool goto_error = false;
|
||||
file_archive_file_handle_t handle = {0};
|
||||
|
||||
st->found = true;
|
||||
|
||||
if (content_zip_file_decompressed_handle(&handle,
|
||||
cdata, csize, size, crc32))
|
||||
{
|
||||
if (st->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),
|
||||
st->opt_file);
|
||||
memcpy(buf, handle.data, size);
|
||||
|
||||
if (!filestream_write_file(st->opt_file, buf, size))
|
||||
goto_error = true;
|
||||
}
|
||||
|
||||
free(buf);
|
||||
|
||||
st->size = 0;
|
||||
}
|
||||
else
|
||||
{
|
||||
/* Called in case core has need_fullpath disabled.
|
||||
* Will copy decompressed content directly into
|
||||
* RetroArch's ROM buffer. */
|
||||
*st->buf = malloc(size);
|
||||
memcpy(*st->buf, handle.data, size);
|
||||
|
||||
st->size = size;
|
||||
}
|
||||
}
|
||||
|
||||
if (handle.data)
|
||||
free(handle.data);
|
||||
|
||||
if (goto_error)
|
||||
return 0;
|
||||
}
|
||||
|
||||
return 1;
|
||||
}
|
||||
|
||||
static int content_zip_file_read(
|
||||
const char *path,
|
||||
const char *needle, void **buf,
|
||||
const char* optional_outfile)
|
||||
{
|
||||
file_archive_transfer_t zlib;
|
||||
struct decomp_state st;
|
||||
bool returnerr = true;
|
||||
int ret = 0;
|
||||
|
||||
zlib.type = ZLIB_TRANSFER_INIT;
|
||||
|
||||
st.needle = NULL;
|
||||
st.opt_file = NULL;
|
||||
st.found = false;
|
||||
st.buf = buf;
|
||||
|
||||
if (needle)
|
||||
st.needle = strdup(needle);
|
||||
if (optional_outfile)
|
||||
st.opt_file = strdup(optional_outfile);
|
||||
|
||||
do
|
||||
{
|
||||
ret = file_archive_parse_file_iterate(&zlib, &returnerr, path,
|
||||
"", content_zip_file_decompressed, &st);
|
||||
if (!returnerr)
|
||||
break;
|
||||
}while(ret == 0 && !st.found);
|
||||
|
||||
file_archive_parse_file_iterate_stop(&zlib);
|
||||
|
||||
if (st.opt_file)
|
||||
free(st.opt_file);
|
||||
if (st.needle)
|
||||
free(st.needle);
|
||||
|
||||
if (!st.found)
|
||||
return -1;
|
||||
|
||||
return st.size;
|
||||
}
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_COMPRESSION
|
||||
/* Generic compressed file loader.
|
||||
* Extracts to buf, unless optional_filename != 0
|
||||
* Then extracts to optional_filename and leaves buf alone.
|
||||
*/
|
||||
static int content_file_compressed_read(
|
||||
const char * path, void **buf,
|
||||
const char* optional_filename, ssize_t *length)
|
||||
{
|
||||
int ret = 0;
|
||||
const char* file_ext = NULL;
|
||||
struct string_list *str_list = filename_split_archive(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;
|
||||
|
||||
#if defined(HAVE_7ZIP) || defined(HAVE_ZLIB)
|
||||
file_ext = path_get_extension(str_list->elems[0].data);
|
||||
#endif
|
||||
|
||||
#ifdef HAVE_7ZIP
|
||||
if (string_is_equal_noncase(file_ext, "7z"))
|
||||
{
|
||||
*length = content_7zip_file_read(str_list->elems[0].data,
|
||||
str_list->elems[1].data, buf, optional_filename);
|
||||
if (*length != -1)
|
||||
ret = 1;
|
||||
}
|
||||
#endif
|
||||
#ifdef HAVE_ZLIB
|
||||
if (string_is_equal_noncase(file_ext, "zip"))
|
||||
{
|
||||
*length = content_zip_file_read(str_list->elems[0].data,
|
||||
str_list->elems[1].data, buf, optional_filename);
|
||||
if (*length != -1)
|
||||
ret = 1;
|
||||
}
|
||||
#endif
|
||||
|
||||
string_list_free(str_list);
|
||||
return ret;
|
||||
|
||||
error:
|
||||
RARCH_ERR("Could not extract string and substring from "
|
||||
": %s.\n", path);
|
||||
string_list_free(str_list);
|
||||
*length = 0;
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
/**
|
||||
* content_file_read:
|
||||
* @path : path to file.
|
||||
|
@ -956,7 +1560,7 @@ static void menu_content_environment_get(int *argc, char *argv[],
|
|||
{
|
||||
char *fullpath = NULL;
|
||||
struct rarch_main_wrap *wrap_args = (struct rarch_main_wrap*)params_data;
|
||||
|
||||
|
||||
if (!wrap_args)
|
||||
return;
|
||||
|
||||
|
|
|
@ -47,6 +47,7 @@
|
|||
#include "../defaults.h"
|
||||
#include "../configuration.h"
|
||||
#include "../runloop.h"
|
||||
#include "../paths.h"
|
||||
#include "../msg_hash.h"
|
||||
|
||||
#include "../gfx/video_driver.h"
|
||||
|
@ -281,8 +282,7 @@ static bool take_screenshot_choice(const char *global_name_base)
|
|||
**/
|
||||
bool take_screenshot(void)
|
||||
{
|
||||
global_t *global = global_get_ptr();
|
||||
char *name_base = strdup(global->name.base);
|
||||
char *name_base = strdup(path_get_basename());
|
||||
bool is_paused = runloop_ctl(RUNLOOP_CTL_IS_PAUSED, NULL);
|
||||
bool ret = take_screenshot_choice(name_base);
|
||||
const char *msg_screenshot = ret
|
||||
|
|
Loading…
Reference in New Issue