Merge branch 'master' into Shader_Save_Load

This commit is contained in:
HyperspaceMadness 2020-11-10 17:05:23 -05:00 committed by GitHub
commit 5008ac6eb0
No known key found for this signature in database
GPG Key ID: 4AEE18F83AFDEB23
44 changed files with 882 additions and 362 deletions

View File

@ -99,8 +99,8 @@ matrix:
android:
components:
- tools
- build-tools-28.0.3
- android-28
- build-tools-29.0.3
- android-29
install:
- echo y | sdkmanager "ndk-bundle"
before_script:

View File

@ -156,8 +156,8 @@ endif
ifeq ($(TARGET), retroarch_3ds)
OBJ += frontend/drivers/platform_ctr.o
endif
# Git Version
ifeq ($(HAVE_GIT_VERSION), 1)
GIT_VERSION_CACHEDIR = $(if $(OBJDIR),$(OBJDIR),$(CURDIR))
GIT_VERSION_CACHEFILE = $(GIT_VERSION_CACHEDIR)/git-version.cache
@ -185,6 +185,7 @@ ifneq ($(GIT_VERSION),) # Enable version_git.o?
DEFINES += -DHAVE_GIT_VERSION -DGIT_VERSION=$(GIT_VERSION)
OBJ += version_git.o
endif
endif
# General object files
ifeq ($(HAVE_DR_MP3), 1)
@ -2260,6 +2261,7 @@ ifeq ($(HAVE_STATIC_VIDEO_FILTERS), 1)
gfx/video_filters/normal2x.o \
gfx/video_filters/normal2x_width.o \
gfx/video_filters/normal2x_height.o \
gfx/video_filters/normal4x.o \
gfx/video_filters/scanline2x.o \
gfx/video_filters/grid2x.o \
gfx/video_filters/grid3x.o \

View File

@ -83,12 +83,12 @@ static void *alsa_init(const char *device, unsigned rate, unsigned latency,
if (snd_pcm_hw_params_malloc(&params) < 0)
goto error;
alsa->has_float = find_float_format(alsa->pcm, params);
format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;
if (snd_pcm_hw_params_any(alsa->pcm, params) < 0)
goto error;
alsa->has_float = find_float_format(alsa->pcm, params);
format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;
if (snd_pcm_hw_params_set_access(
alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED) < 0)
goto error;

View File

@ -173,10 +173,11 @@ static void *alsa_thread_init(const char *device,
TRY_ALSA(snd_pcm_open(&alsa->pcm, alsa_dev, SND_PCM_STREAM_PLAYBACK, 0));
TRY_ALSA(snd_pcm_hw_params_malloc(&params));
TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params));
alsa->has_float = alsathread_find_float_format(alsa->pcm, params);
format = alsa->has_float ? SND_PCM_FORMAT_FLOAT : SND_PCM_FORMAT_S16;
TRY_ALSA(snd_pcm_hw_params_any(alsa->pcm, params));
TRY_ALSA(snd_pcm_hw_params_set_access(
alsa->pcm, params, SND_PCM_ACCESS_RW_INTERLEAVED));
TRY_ALSA(snd_pcm_hw_params_set_format(alsa->pcm, params, format));

View File

@ -1597,7 +1597,8 @@ static int rcheevos_match_value(const char* val, const char* match)
void rcheevos_validate_config_settings(void)
{
const rc_disallowed_core_settings_t* core_filter = rc_disallowed_core_settings;
const rc_disallowed_core_settings_t
*core_filter = rc_disallowed_core_settings;
struct retro_system_info* system = runloop_get_libretro_system_info();
if (!system->library_name || !rcheevos_hardcore_active())
return;
@ -1610,29 +1611,36 @@ void rcheevos_validate_config_settings(void)
if (rarch_ctl(RARCH_CTL_CORE_OPTIONS_LIST_GET, &coreopts))
{
const rc_disallowed_setting_t* disallowed_setting = core_filter->disallowed_settings;
const char* key;
const char* val;
int i;
int allowed = 1;
size_t key_len;
const char *key = NULL;
const char *val = NULL;
const rc_disallowed_setting_t
*disallowed_setting = core_filter->disallowed_settings;
int allowed = 1;
for (; disallowed_setting->setting; ++disallowed_setting)
{
key = disallowed_setting->setting;
key_len = strlen(key);
size_t key_len;
key = disallowed_setting->setting;
key_len = strlen(key);
if (key[key_len - 1] == '*')
{
for (i = 0; i < coreopts->size; i++)
{
if (string_starts_with_size(coreopts->opts[i].key, key, key_len - 1))
if (string_starts_with_size(
coreopts->opts[i].key, key, key_len - 1))
{
val = core_option_manager_get_val(coreopts, i);
if (rcheevos_match_value(val, disallowed_setting->value))
const char* val =core_option_manager_get_val(coreopts, i);
if (val)
{
key = coreopts->opts[i].key;
allowed = 0;
break;
if (rcheevos_match_value(
val, disallowed_setting->value))
{
key = coreopts->opts[i].key;
allowed = 0;
break;
}
}
}
}

View File

@ -196,6 +196,7 @@ enum event_command
CMD_EVENT_OSK_TOGGLE,
CMD_EVENT_RECORDING_TOGGLE,
CMD_EVENT_STREAMING_TOGGLE,
CMD_EVENT_RUNAHEAD_TOGGLE,
CMD_EVENT_AI_SERVICE_TOGGLE,
CMD_EVENT_BSV_RECORDING_TOGGLE,
CMD_EVENT_SHADER_NEXT,

View File

@ -1146,7 +1146,11 @@ static const int default_content_favorites_size = 200;
/* Default scale factor for non-frambuffer-based display
* drivers and display widgets */
#if defined(VITA)
#define DEFAULT_MENU_SCALE_FACTOR 1.5f
#else
#define DEFAULT_MENU_SCALE_FACTOR 1.0f
#endif
/* Specifies whether display widgets should be scaled
* automatically using the default menu scale factor */
#define DEFAULT_MENU_WIDGET_SCALE_AUTO true

View File

@ -563,6 +563,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_STREAMING_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE, RETROK_UNKNOWN,
RARCH_RUNAHEAD_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,
@ -1110,6 +1117,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_STREAMING_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE, RETROK_UNKNOWN,
RARCH_RUNAHEAD_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,
@ -1667,6 +1681,13 @@ static const struct retro_keybind retro_keybinds_1[] = {
RARCH_STREAMING_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,
MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE, RETROK_UNKNOWN,
RARCH_RUNAHEAD_TOGGLE, NO_BTN, NO_BTN, 0,
true
},
{
NULL, NULL,
AXIS_NONE, AXIS_NONE, AXIS_NONE,

View File

@ -10,31 +10,26 @@ struct Backoff
int64_t minAmount;
int64_t maxAmount;
int64_t current;
int fails;
std::mt19937_64 randGenerator;
std::uniform_real_distribution<> randDistribution;
double rand01() { return randDistribution(randGenerator); }
Backoff(int64_t min, int64_t max)
: minAmount(min)
, maxAmount(max)
, current(min)
, fails(0)
, randGenerator((uint64_t)time(0))
{
}
void reset()
{
fails = 0;
current = minAmount;
}
int64_t nextDelay()
{
++fails;
int64_t delay = (int64_t)((double)current * 2.0 * rand01());
int64_t delay = (int64_t)((double)current * 2.0 *
randDistribution(randGenerator));
current = std::min(current + delay, maxAmount);
return current;
}

View File

@ -10,22 +10,10 @@
#include <chrono>
#include <mutex>
#ifndef DISCORD_DISABLE_IO_THREAD
#include <condition_variable>
#include <thread>
#endif
struct QueuedMessage
{
size_t length;
char buffer[16384];
void Copy(const QueuedMessage& other)
{
length = other.length;
if (length)
memcpy(buffer, other.buffer, length);
}
};
struct User
@ -80,66 +68,13 @@ static User connectedUser;
static Backoff ReconnectTimeMs(500, 60 * 1000);
static auto NextConnect = std::chrono::system_clock::now();
#ifndef DISCORD_DISABLE_IO_THREAD
static void Discord_UpdateConnection(void);
class IoThreadHolder
{
private:
std::atomic_bool keepRunning{true};
std::mutex waitForIOMutex;
std::condition_variable waitForIOActivity;
std::thread ioThread;
public:
void Start()
{
keepRunning.store(true);
ioThread = std::thread([&]() {
const std::chrono::duration<int64_t, std::milli> maxWait{500LL};
Discord_UpdateConnection();
while (keepRunning.load()) {
std::unique_lock<std::mutex> lock(waitForIOMutex);
waitForIOActivity.wait_for(lock, maxWait);
Discord_UpdateConnection();
}
});
}
void Notify() { waitForIOActivity.notify_all(); }
void Stop()
{
keepRunning.exchange(false);
Notify();
if (ioThread.joinable())
ioThread.join();
}
~IoThreadHolder() { Stop(); }
};
#else
class IoThreadHolder
{
public:
void Start() {}
void Stop() {}
void Notify() {}
};
#endif /* DISCORD_DISABLE_IO_THREAD */
static IoThreadHolder* IoThread{nullptr};
static void UpdateReconnectTime(void)
static void update_reconnect_time(void)
{
NextConnect = std::chrono::system_clock::now() +
std::chrono::duration<int64_t, std::milli>{ReconnectTimeMs.nextDelay()};
}
#ifdef DISCORD_DISABLE_IO_THREAD
extern "C" void Discord_UpdateConnection(void)
#else
static void Discord_UpdateConnection(void)
#endif
{
if (!Connection)
return;
@ -148,7 +83,7 @@ static void Discord_UpdateConnection(void)
{
if (std::chrono::system_clock::now() >= NextConnect)
{
UpdateReconnectTime();
update_reconnect_time();
Connection->Open();
}
}
@ -268,16 +203,19 @@ static void Discord_UpdateConnection(void)
if (QueuedPresence.length)
{
QueuedMessage local;
{
std::lock_guard<std::mutex> guard(PresenceMutex);
local.Copy(QueuedPresence);
QueuedPresence.length = 0;
}
std::lock_guard<std::mutex> guard(PresenceMutex);
local.length = QueuedPresence.length;
if (local.length)
memcpy(local.buffer, QueuedPresence.buffer, local.length);
QueuedPresence.length = 0;
if (!Connection->Write(local.buffer, local.length))
{
/* if we fail to send, requeue */
std::lock_guard<std::mutex> guard(PresenceMutex);
QueuedPresence.Copy(local);
QueuedPresence.length = local.length;
if (QueuedPresence.length)
memcpy(QueuedPresence.buffer, local.buffer, QueuedPresence.length);
}
}
@ -298,8 +236,6 @@ static bool RegisterForEvent(const char* evtName)
qmessage->length =
JsonWriteSubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
SendQueue.CommitAdd();
if (IoThread)
IoThread->Notify();
return true;
}
return false;
@ -313,8 +249,6 @@ static bool DeregisterForEvent(const char* evtName)
qmessage->length =
JsonWriteUnsubscribeCommand(qmessage->buffer, sizeof(qmessage->buffer), Nonce++, evtName);
SendQueue.CommitAdd();
if (IoThread)
IoThread->Notify();
return true;
}
return false;
@ -326,10 +260,6 @@ extern "C" void Discord_Initialize(
int autoRegister,
const char* optionalSteamId)
{
IoThread = new (std::nothrow) IoThreadHolder();
if (!IoThread)
return;
if (autoRegister)
{
if (optionalSteamId && optionalSteamId[0])
@ -354,34 +284,38 @@ extern "C" void Discord_Initialize(
if (Connection)
return;
Connection = RpcConnection::Create(applicationId);
Connection = RpcConnection::Create(applicationId);
Connection->onConnect = [](JsonDocument& readyMessage)
{
Discord_UpdateHandlers(&QueuedHandlers);
char *userId = NULL;
char *username = NULL;
char *avatar = NULL;
char *discriminator = NULL;
bool in_data = false;
bool in_user = false;
Discord_UpdateHandlers(&QueuedHandlers);
bool in_data = false, in_user = false;
for (JsonReader r(readyMessage); r.NextKey();)
{
if (r.depth == 1)
{
in_data = !strcmp(r.key,"data");
in_user = false;
}
else if (r.depth == 2 && in_data)
{
in_user = !strcmp(r.key, "user");
}
else if (r.depth == 3 && in_user)
{
if (!strcmp(r.key, "id" )) r.NextStrDup(&userId);
else if (!strcmp(r.key, "username" )) r.NextStrDup(&username);
else if (!strcmp(r.key, "avatar" )) r.NextStrDup(&avatar);
else if (!strcmp(r.key, "discriminator")) r.NextStrDup(&discriminator);
}
if (r.depth == 1)
{
in_data = !strcmp(r.key,"data");
in_user = false;
}
else if (r.depth == 2 && in_data)
in_user = !strcmp(r.key, "user");
else if (r.depth == 3 && in_user)
{
if (!strcmp(r.key, "id" ))
r.NextStrDup(&userId);
else if (!strcmp(r.key, "username" ))
r.NextStrDup(&username);
else if (!strcmp(r.key, "avatar" ))
r.NextStrDup(&avatar);
else if (!strcmp(r.key, "discriminator"))
r.NextStrDup(&discriminator);
}
}
if (userId && username)
@ -398,10 +332,14 @@ extern "C" void Discord_Initialize(
WasJustConnected.exchange(true);
ReconnectTimeMs.reset();
if (userId ) free(userId );
if (username ) free(username );
if (avatar ) free(avatar );
if (discriminator) free(discriminator);
if (userId)
free(userId);
if (username)
free(username);
if (avatar)
free(avatar);
if (discriminator)
free(discriminator);
};
Connection->onDisconnect = [](int err, const char* message)
{
@ -412,10 +350,8 @@ extern "C" void Discord_Initialize(
Handlers = {};
}
WasJustDisconnected.exchange(true);
UpdateReconnectTime();
update_reconnect_time();
};
IoThread->Start();
}
extern "C" void Discord_Shutdown(void)
@ -424,26 +360,17 @@ extern "C" void Discord_Shutdown(void)
return;
Connection->onConnect = nullptr;
Connection->onDisconnect = nullptr;
Handlers = {};
if (IoThread)
{
IoThread->Stop();
delete IoThread;
IoThread = nullptr;
}
Handlers = {};
RpcConnection::Destroy(Connection);
}
extern "C" void Discord_UpdatePresence(const DiscordRichPresence* presence)
{
{
std::lock_guard<std::mutex> guard(PresenceMutex);
QueuedPresence.length = JsonWriteRichPresenceObj(
QueuedPresence.buffer, sizeof(QueuedPresence.buffer), Nonce++, Pid, presence);
}
if (IoThread)
IoThread->Notify();
std::lock_guard<std::mutex> guard(PresenceMutex);
QueuedPresence.length = JsonWriteRichPresenceObj(
QueuedPresence.buffer, sizeof(QueuedPresence.buffer),
Nonce++, Pid, presence);
}
extern "C" void Discord_ClearPresence(void)
@ -451,7 +378,8 @@ extern "C" void Discord_ClearPresence(void)
Discord_UpdatePresence(nullptr);
}
extern "C" void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int reply)
extern "C" void Discord_Respond(const char* userId,
/* DISCORD_REPLY_ */ int reply)
{
/* if we are not connected, let's not batch up stale messages for later */
if (!Connection || !Connection->IsOpen())
@ -462,8 +390,6 @@ extern "C" void Discord_Respond(const char* userId, /* DISCORD_REPLY_ */ int rep
qmessage->length =
JsonWriteJoinReply(qmessage->buffer, sizeof(qmessage->buffer), userId, reply, Nonce++);
SendQueue.CommitAdd();
if (IoThread)
IoThread->Notify();
}
}
@ -530,16 +456,14 @@ extern "C" void Discord_RunCallbacks(void)
*/
while (JoinAskQueue.HavePendingSends())
{
auto req = JoinAskQueue.GetNextSendMessage();
{
std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.joinRequest)
{
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
Handlers.joinRequest(&du);
}
}
JoinAskQueue.CommitSend();
auto req = JoinAskQueue.GetNextSendMessage();
std::lock_guard<std::mutex> guard(HandlerMutex);
if (Handlers.joinRequest)
{
DiscordUser du{req->userId, req->username, req->discriminator, req->avatar};
Handlers.joinRequest(&du);
}
JoinAskQueue.CommitSend();
}
if (!isConnected)

View File

@ -324,6 +324,7 @@ static void frontend_psp_exec(const char *path, bool should_load_game)
#endif
char argp[512] = {0};
SceSize args = 0;
int ret;
#if !defined(VITA)
strlcpy(argp, eboot_path, sizeof(argp));
@ -346,21 +347,25 @@ static void frontend_psp_exec(const char *path, bool should_load_game)
sceAppMgrGetAppParam(boot_params);
if (strstr(boot_params,"psgm:play"))
{
int ret;
char *param1 = strstr(boot_params, "&param=")+7;
char *param1 = strstr(boot_params, "&param=");
char *param2 = strstr(boot_params, "&param2=");
memcpy(core_name, param1, param2 - param1);
core_name[param2-param1] = 0;
sprintf(argp, param2 + 8);
ret = sceAppMgrLoadExec(core_name, (char * const*)((const char*[]){argp, 0}), NULL);
RARCH_LOG("Attempt to load executable: [%d].\n", ret);
if (param1 != NULL && param2 != NULL)
{
param1 += 7;
memcpy(core_name, param1, param2 - param1);
core_name[param2-param1] = 0;
sprintf(argp, param2 + 8);
ret = sceAppMgrLoadExec(core_name, (char * const*)((const char*[]){argp, 0}), NULL);
RARCH_LOG("Attempt to load executable: [%d].\n", ret);
goto exit;
}
RARCH_LOG("Required boot params missing. Continue nornal boot.");
}
else
#endif
{
int ret = sceAppMgrLoadExec(path, args == 0 ? NULL : (char * const*)((const char*[]){argp, 0}), NULL);
RARCH_LOG("Attempt to load executable: [%d].\n", ret);
}
ret = sceAppMgrLoadExec(path, args == 0 ? NULL : (char * const*)((const char*[]){argp, 0}), NULL);
RARCH_LOG("Attempt to load executable: [%d].\n", ret);
exit:
return;
#else
exitspawn_kernel(path, args, argp);
#endif

View File

@ -1054,6 +1054,13 @@ static LRESULT CALLBACK wnd_proc_common_dinput_internal(HWND hwnd,
keysym |= 0x80;
keycode = input_keymaps_translate_keysym_to_rk(keysym);
switch (keycode)
{
/* L+R Shift handling done in dinput_poll */
case RETROK_LSHIFT:
case RETROK_RSHIFT:
return 0;
}
input_keyboard_event(keydown, keycode,
0, mod, RETRO_DEVICE_KEYBOARD);

View File

@ -600,8 +600,10 @@ bool slang_reflect(
}
else if (index == SLANG_INVALID_TEXTURE_SEMANTIC)
{
RARCH_ERR("[slang]: Non-semantic textures not supported yet, "
"Probably a texture name or pass alias is not found. \n");
RARCH_ERR("[slang]: Texture name '%s' not found in semantic map, "
"Probably the texture name or pass alias is not defined "
"in the preset (Non-semantic textures not supported yet)\n",
fragment.sampled_images[i].name.c_str());
return false;
}

View File

@ -802,22 +802,30 @@ static bool font_init_first(
* Neutral :
* 0020 - 002F : 001xxxxx (c & 0xE0) == 0x20
* Arabic:
* 0600 - 07FF : 11011xxx (c & 0xF8) == 0xD8 (2 bytes)
* 0800 - 08FF : 11100000 101000xx c == 0xE0 && (c1 & 0xAC) == 0xA0 (3 bytes) */
* 0600 - 06FF : 110110xx (c & 0xFC) == 0xD8 (2 bytes) */
/* clang-format off */
#define IS_ASCII(p) ((*(p)&0x80) == 0x00)
#define IS_MBSTART(p) ((*(p)&0xC0) == 0xC0)
#define IS_MBCONT(p) ((*(p)&0xC0) == 0x80)
#define IS_DIR_NEUTRAL(p) ((*(p)&0xE0) == 0x20)
#define IS_ARABIC0(p) ((*(p)&0xF8) == 0xD8)
#define IS_ARABIC1(p) ((*(p) == 0xE0) && ((*((p) + 1) & 0xAC) == 0xA0))
#define IS_ARABIC(p) (IS_ARABIC0(p) || IS_ARABIC1(p))
#define IS_ARABIC(p) ((*(p)&0xFC) == 0xD8)
#define IS_RTL(p) IS_ARABIC(p)
#define GET_ID_ARABIC(p) (((unsigned char)(p)[0] << 6) | ((unsigned char)(p)[1] & 0x3F))
/* 0x0620 to 0x064F */
static const unsigned arabic_shape_map[0x50 - 0x20][0x4] = {
{ 0 }, /* 0x0620 */
static const unsigned arabic_shape_map[0x100][0x4] = {
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0600 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0610 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, /* 0x0620 */
{ 0xFE80 },
{ 0xFE81, 0xFE82 },
{ 0xFE83, 0xFE84 },
@ -843,99 +851,189 @@ static const unsigned arabic_shape_map[0x50 - 0x20][0x4] = {
{ 0xFEB9, 0xFEBA, 0xFEBB, 0xFEBC },
{ 0xFEBD, 0xFEBE, 0xFEBF, 0xFEC0 },
{ 0xFEC1, 0xFEC2, 0xFEC3, 0xFEC4 },
{ 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8 },
{ 0xFEC5, 0xFEC6, 0xFEC7, 0xFEC8 },
{ 0xFEC9, 0xFECA, 0xFECB, 0xFECC },
{ 0xFECD, 0xFECE, 0xFECF, 0xFED0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0xFED1, 0xFED2, 0xFED3, 0xFED4 }, /* 0x0640 */
{ 0 }, /* 0x0640 */
{ 0xFED1, 0xFED2, 0xFED3, 0xFED4 },
{ 0xFED5, 0xFED6, 0xFED7, 0xFED8 },
{ 0xFED9, 0xFEDA, 0xFEDB, 0xFEDC },
{ 0xFEDD, 0xFEDE, 0xFEDF, 0xFEE0 },
{ 0xFEE1, 0xFEE2, 0xFEE3, 0xFEE4 },
{ 0xFEE5, 0xFEE6, 0xFEE7, 0xFEE8 },
{ 0xFEE9, 0xFEEA, 0xFEEB, 0xFEEC },
{ 0xFEED, 0xFEEE },
{ 0xFEED, 0xFEEE },
{ 0xFEEF, 0xFEF0, 0xFBE8, 0xFBE9 },
{ 0xFEF1, 0xFEF2, 0xFEF3, 0xFEF4 },
{ 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0650 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0660 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0670 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 },
{ 0xFB56, 0xFB57, 0xFB58, 0xFB59 },
{ 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0680 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x0690 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06A0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 },
{ 0xFB8E, 0xFB8F, 0xFB90, 0xFB91 },
{ 0 }, { 0 },
{ 0 }, { 0 }, { 0 },
{ 0xFB92, 0xFB93, 0xFB94, 0xFB95 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06B0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06C0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0xFBFC, 0xFBFD, 0xFBFE, 0xFBFF },
{ 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06D0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06E0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 }, /* 0x06F0 */
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
{ 0 }, { 0 }, { 0 }, { 0 },
};
/* clang-format on */
static INLINE unsigned font_get_replacement(const char* src, const char* start)
{
if ((*src & 0xFC) == 0xD8) /* 0x0600 to 0x06FF */
if (IS_ARABIC(src)) /* 0x0600 to 0x06FF */
{
unsigned result = 0;
bool prev_connected = false;
bool next_connected = false;
unsigned char id = ((unsigned char)src[0] << 6) | ((unsigned char)src[1] & 0x3F);
const char* prev1 = src - 2;
const char* prev2 = src - 4;
unsigned char id = GET_ID_ARABIC(src);
const char* prev = src - 2;
const char* next = src + 2;
if (id < 0x21 || id > 0x4A)
return 0;
if (prev2 < start)
if ((prev >= start) && IS_ARABIC(prev))
{
prev2 = NULL;
if (prev1 < start)
prev1 = NULL;
}
unsigned char prev_id = GET_ID_ARABIC(prev);
if (prev1 && (*prev1 & 0xFC) == 0xD8)
{
unsigned char prev1_id = 0;
/* nonspacing diacritics 0x4b -- 0x5f */
while (prev_id > 0x4A && prev_id < 0x60)
{
prev -= 2;
if ((prev >= start) && IS_ARABIC(prev))
prev_id = GET_ID_ARABIC(prev);
else
break;
}
if (prev1)
prev1_id = ((unsigned char)prev1[0] << 6) | ((unsigned char)prev1[1] & 0x3F);
if (prev1_id == 0x44)
if (prev_id == 0x44) /* Arabic Letter Lam */
{
unsigned char prev2_id = 0;
const char* prev2 = prev - 2;
if (prev2)
if (prev2 >= start)
prev2_id = (prev2[0] << 6) | (prev2[1] & 0x3F);
if (prev2_id > 0x20 || prev2_id < 0x50)
prev_connected = !!arabic_shape_map[prev2_id - 0x20][2];
/* nonspacing diacritics 0x4b -- 0x5f */
while (prev2_id > 0x4A && prev2_id < 0x60)
{
prev2 -= 2;
if ((prev2 >= start) && IS_ARABIC(prev2))
prev2_id = GET_ID_ARABIC(prev2);
else
break;
}
prev_connected = !!arabic_shape_map[prev2_id][2];
switch (id)
{
case 0x22:
case 0x22: /* Arabic Letter Alef with Madda Above */
return 0xFEF5 + prev_connected;
case 0x23:
case 0x23: /* Arabic Letter Alef with Hamza Above */
return 0xFEF7 + prev_connected;
case 0x25:
case 0x25: /* Arabic Letter Alef with Hamza Below */
return 0xFEF9 + prev_connected;
case 0x27:
case 0x27: /* Arabic Letter Alef */
return 0xFEFB + prev_connected;
}
}
if (prev1_id > 0x20 || prev1_id < 0x50)
prev_connected = !!arabic_shape_map[prev1_id - 0x20][2];
prev_connected = !!arabic_shape_map[prev_id][2];
}
if ((src[2] & 0xFC) == 0xD8)
if (IS_ARABIC(next))
{
unsigned char next_id = ((unsigned char)src[2] << 6) | ((unsigned char)src[3] & 0x3F);
unsigned char next_id = GET_ID_ARABIC(next);
if (next_id > 0x20 || next_id < 0x50)
next_connected = true;
/* nonspacing diacritics 0x4b -- 0x5f */
while (next_id > 0x4A && next_id < 0x60)
{
next += 2;
if (IS_ARABIC(next))
next_id = GET_ID_ARABIC(next);
else
break;
}
next_connected = !!arabic_shape_map[next_id][1];
}
result = arabic_shape_map[id - 0x20][prev_connected | (next_connected << 1)];
result = arabic_shape_map[id][prev_connected | (next_connected << 1)];
if (result)
return result;
return arabic_shape_map[id - 0x20][prev_connected];
return arabic_shape_map[id][prev_connected];
}
return 0;
@ -961,22 +1059,17 @@ static char* font_driver_reshape_msg(const char* msg, unsigned char *buffer, siz
if (reverse)
{
src--;
while (IS_MBCONT(src))
{
while (src > (const unsigned char*)msg && IS_MBCONT(src))
src--;
if (src == (const unsigned char*)msg)
goto end;
}
if (IS_RTL(src) || IS_DIR_NEUTRAL(src))
if (src >= (const unsigned char*)msg && (IS_RTL(src) || IS_DIR_NEUTRAL(src)))
{
unsigned replacement = font_get_replacement((const char*)src, msg);
if (replacement)
{
if (replacement < 0x80)
*dst++ = replacement;
else if (replacement < 0x8000)
else if (replacement < 0x800)
{
*dst++ = 0xC0 | (replacement >> 6);
*dst++ = 0x80 | (replacement & 0x3F);
@ -1030,7 +1123,7 @@ static char* font_driver_reshape_msg(const char* msg, unsigned char *buffer, siz
*dst++ = *src++;
}
}
end:
*dst = '\0';
return (char*)dst_buffer;

View File

@ -282,6 +282,7 @@ extern const struct softfilter_implementation *scale2x_get_implementation(softfi
extern const struct softfilter_implementation *normal2x_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *normal2x_width_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *normal2x_height_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *normal4x_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *scanline2x_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *grid2x_get_implementation(softfilter_simd_mask_t simd);
extern const struct softfilter_implementation *grid3x_get_implementation(softfilter_simd_mask_t simd);
@ -304,6 +305,7 @@ static const softfilter_get_implementation_t soft_plugs_builtin[] = {
normal2x_get_implementation,
normal2x_width_get_implementation,
normal2x_height_get_implementation,
normal4x_get_implementation,
scanline2x_get_implementation,
grid2x_get_implementation,
grid3x_get_implementation,

View File

@ -70,7 +70,7 @@ endif
objects += blargg_ntsc_snes.$(DYLIB) phosphor2x.$(DYLIB) epx.$(DYLIB) lq2x.$(DYLIB) \
2xsai.$(DYLIB) super2xsai.$(DYLIB) supereagle.$(DYLIB) 2xbr.$(DYLIB) \
darken.$(DYLIB) scale2x.$(DYLIB) normal2x.$(DYLIB) \
normal2x_width.$(DYLIB) normal2x_height.$(DYLIB) \
normal2x_width.$(DYLIB) normal2x_height.$(DYLIB) normal4x.$(DYLIB) \
scanline2x.$(DYLIB) grid2x.$(DYLIB) grid3x.$(DYLIB) \
gameboy3x.$(DYLIB) gameboy4x.$(DYLIB) \
dot_matrix_3x.$(DYLIB) dot_matrix_4x.$(DYLIB)

View File

@ -0,0 +1 @@
filter = normal4x

View File

@ -0,0 +1,255 @@
/* RetroArch - A frontend for libretro.
* Copyright (C) 2010-2014 - Hans-Kristian Arntzen
* Copyright (C) 2011-2018 - Daniel De Matteis
*
* RetroArch is free software: you can redistribute it and/or modify it under the terms
* of the GNU General Public License as published by the Free Software Found-
* ation, either version 3 of the License, or (at your option) any later version.
*
* RetroArch is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY;
* without even the implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR
* PURPOSE. See the GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License along with RetroArch.
* If not, see <http://www.gnu.org/licenses/>.
*/
/* Compile: gcc -o normal4x.so -shared normal4x.c -std=c99 -O3 -Wall -pedantic -fPIC */
#include "softfilter.h"
#include <stdlib.h>
#include <string.h>
#ifdef RARCH_INTERNAL
#define softfilter_get_implementation normal4x_get_implementation
#define softfilter_thread_data normal4x_softfilter_thread_data
#define filter_data normal4x_filter_data
#endif
struct softfilter_thread_data
{
void *out_data;
const void *in_data;
size_t out_pitch;
size_t in_pitch;
unsigned colfmt;
unsigned width;
unsigned height;
int first;
int last;
};
struct filter_data
{
unsigned threads;
struct softfilter_thread_data *workers;
unsigned in_fmt;
};
static unsigned normal4x_generic_input_fmts(void)
{
return SOFTFILTER_FMT_XRGB8888 | SOFTFILTER_FMT_RGB565;
}
static unsigned normal4x_generic_output_fmts(unsigned input_fmts)
{
return input_fmts;
}
static unsigned normal4x_generic_threads(void *data)
{
struct filter_data *filt = (struct filter_data*)data;
return filt->threads;
}
static void *normal4x_generic_create(const struct softfilter_config *config,
unsigned in_fmt, unsigned out_fmt,
unsigned max_width, unsigned max_height,
unsigned threads, softfilter_simd_mask_t simd, void *userdata)
{
struct filter_data *filt = (struct filter_data*)calloc(1, sizeof(*filt));
(void)simd;
(void)config;
(void)userdata;
if (!filt) {
return NULL;
}
/* Apparently the code is not thread-safe,
* so force single threaded operation... */
filt->workers = (struct softfilter_thread_data*)calloc(1, sizeof(struct softfilter_thread_data));
filt->threads = 1;
filt->in_fmt = in_fmt;
if (!filt->workers) {
free(filt);
return NULL;
}
return filt;
}
static void normal4x_generic_output(void *data,
unsigned *out_width, unsigned *out_height,
unsigned width, unsigned height)
{
*out_width = width << 2;
*out_height = height << 2;
}
static void normal4x_generic_destroy(void *data)
{
struct filter_data *filt = (struct filter_data*)data;
if (!filt) {
return;
}
free(filt->workers);
free(filt);
}
static void normal4x_work_cb_xrgb8888(void *data, void *thread_data)
{
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
const uint32_t *input = (const uint32_t*)thr->in_data;
uint32_t *output = (uint32_t*)thr->out_data;
uint32_t in_stride = (uint32_t)(thr->in_pitch >> 2);
uint32_t out_stride = (uint32_t)(thr->out_pitch >> 2);
uint32_t x, y;
for (y = 0; y < thr->height; ++y)
{
uint32_t *out_ptr = output;
for (x = 0; x < thr->width; ++x)
{
uint32_t *out_line_ptr = out_ptr;
uint32_t color = *(input + x);
uint32_t row_color[4];
row_color[0] = color;
row_color[1] = color;
row_color[2] = color;
row_color[3] = color;
/* Row 1 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 2 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 3 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 4 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_ptr += 4;
}
input += in_stride;
output += out_stride << 2;
}
}
static void normal4x_work_cb_rgb565(void *data, void *thread_data)
{
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)thread_data;
const uint16_t *input = (const uint16_t*)thr->in_data;
uint16_t *output = (uint16_t*)thr->out_data;
uint16_t in_stride = (uint16_t)(thr->in_pitch >> 1);
uint16_t out_stride = (uint16_t)(thr->out_pitch >> 1);
uint16_t x, y;
for (y = 0; y < thr->height; ++y)
{
uint16_t *out_ptr = output;
for (x = 0; x < thr->width; ++x)
{
uint16_t *out_line_ptr = out_ptr;
uint16_t color = *(input + x);
uint16_t row_color[4];
row_color[0] = color;
row_color[1] = color;
row_color[2] = color;
row_color[3] = color;
/* Row 1 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 2 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 3 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_line_ptr += out_stride;
/* Row 4 */
memcpy(out_line_ptr, row_color, sizeof(row_color));
out_ptr += 4;
}
input += in_stride;
output += out_stride << 2;
}
}
static void normal4x_generic_packets(void *data,
struct softfilter_work_packet *packets,
void *output, size_t output_stride,
const void *input, unsigned width, unsigned height, size_t input_stride)
{
/* We are guaranteed single threaded operation
* (filt->threads = 1) so we don't need to loop
* over threads and can cull some code. This only
* makes the tiniest performance difference, but
* every little helps when running on an o3DS... */
struct filter_data *filt = (struct filter_data*)data;
struct softfilter_thread_data *thr = (struct softfilter_thread_data*)&filt->workers[0];
thr->out_data = (uint8_t*)output;
thr->in_data = (const uint8_t*)input;
thr->out_pitch = output_stride;
thr->in_pitch = input_stride;
thr->width = width;
thr->height = height;
if (filt->in_fmt == SOFTFILTER_FMT_XRGB8888) {
packets[0].work = normal4x_work_cb_xrgb8888;
} else if (filt->in_fmt == SOFTFILTER_FMT_RGB565) {
packets[0].work = normal4x_work_cb_rgb565;
}
packets[0].thread_data = thr;
}
static const struct softfilter_implementation normal4x_generic = {
normal4x_generic_input_fmts,
normal4x_generic_output_fmts,
normal4x_generic_create,
normal4x_generic_destroy,
normal4x_generic_threads,
normal4x_generic_output,
normal4x_generic_packets,
SOFTFILTER_API_VERSION,
"Normal4x",
"normal4x",
};
const struct softfilter_implementation *softfilter_get_implementation(
softfilter_simd_mask_t simd)
{
(void)simd;
return &normal4x_generic;
}
#ifdef RARCH_INTERNAL
#undef softfilter_get_implementation
#undef softfilter_thread_data
#undef filter_data
#endif

View File

@ -38,7 +38,7 @@ RETRO_BEGIN_DECLS
#endif
#ifndef GFX_MAX_PARAMETERS
#define GFX_MAX_PARAMETERS 256
#define GFX_MAX_PARAMETERS 512
#endif
#ifndef GFX_MAX_FRAME_HISTORY

View File

@ -1003,6 +1003,7 @@ FILTERS
#include "../gfx/video_filters/normal2x.c"
#include "../gfx/video_filters/normal2x_width.c"
#include "../gfx/video_filters/normal2x_height.c"
#include "../gfx/video_filters/normal4x.c"
#include "../gfx/video_filters/scanline2x.c"
#include "../gfx/video_filters/grid2x.c"
#include "../gfx/video_filters/grid3x.c"

View File

@ -81,6 +81,7 @@ struct dinput_input
int mouse_x;
int mouse_y;
uint8_t state[256];
bool shift_l, shift_r, alt_l;
bool doubleclick_on_titlebar;
bool mouse_l, mouse_r, mouse_m, mouse_b4, mouse_b5, mouse_wu, mouse_wd, mouse_hwu, mouse_hwd;
};
@ -160,7 +161,7 @@ static void *dinput_init(const char *joypad_driver)
{
IDirectInputDevice8_SetDataFormat(di->keyboard, &c_dfDIKeyboard);
IDirectInputDevice8_SetCooperativeLevel(di->keyboard,
(HWND)video_driver_window_get(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND);
(HWND)video_driver_window_get(), DISCL_NONEXCLUSIVE | DISCL_FOREGROUND | DISCL_NOWINKEY);
IDirectInputDevice8_Acquire(di->keyboard);
}
@ -181,6 +182,50 @@ static void *dinput_init(const char *joypad_driver)
return di;
}
static void dinput_keyboard_mods(struct dinput_input *di, int mod)
{
switch (mod)
{
case RETROKMOD_SHIFT:
{
unsigned vk_shift_l = GetAsyncKeyState(VK_LSHIFT) >> 1;
unsigned vk_shift_r = GetAsyncKeyState(VK_RSHIFT) >> 1;
if ( (vk_shift_l && !di->shift_l) ||
(!vk_shift_l && di->shift_l))
{
input_keyboard_event(vk_shift_l, RETROK_LSHIFT,
0, RETROKMOD_SHIFT, RETRO_DEVICE_KEYBOARD);
di->shift_l = !di->shift_l;
}
if ( (vk_shift_r && !di->shift_r) ||
(!vk_shift_r && di->shift_r))
{
input_keyboard_event(vk_shift_r, RETROK_RSHIFT,
0, RETROKMOD_SHIFT, RETRO_DEVICE_KEYBOARD);
di->shift_r = !di->shift_r;
}
}
break;
case RETROKMOD_ALT:
{
unsigned vk_alt_l = GetAsyncKeyState(VK_LMENU) >> 1;
if (vk_alt_l && !di->alt_l)
di->alt_l = !di->alt_l;
else if (!vk_alt_l && di->alt_l)
{
input_keyboard_event(vk_alt_l, RETROK_LALT,
0, RETROKMOD_ALT, RETRO_DEVICE_KEYBOARD);
di->alt_l = !di->alt_l;
}
}
break;
}
}
static void dinput_poll(void *data)
{
struct dinput_input *di = (struct dinput_input*)data;
@ -211,6 +256,12 @@ static void dinput_poll(void *data)
*kb_state = 0;
}
}
else
/* Shifts only when window focused */
dinput_keyboard_mods(di, RETROKMOD_SHIFT);
/* Left alt keyup when unfocused, to prevent alt-tab sticky */
dinput_keyboard_mods(di, RETROKMOD_ALT);
}
if (di->mouse)

View File

@ -117,6 +117,7 @@ enum
RARCH_RECORDING_TOGGLE,
RARCH_STREAMING_TOGGLE,
RARCH_RUNAHEAD_TOGGLE,
RARCH_AI_SERVICE,

View File

@ -225,6 +225,10 @@ int msg_hash_get_help_us_enum(enum msg_hash_enums msg, char *s, size_t len)
snprintf(s, len,
"Toggle between recording and not.");
break;
case RARCH_RUNAHEAD_TOGGLE:
snprintf(s, len,
"Toggles Run-Ahead mode on/off.");
break;
default:
if (string_is_empty(s))
strlcpy(s, msg_hash_to_str(MENU_ENUM_LABEL_VALUE_NO_INFORMATION_AVAILABLE), len);

View File

@ -2555,6 +2555,14 @@ MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_META_STREAMING_TOGGLE,
"Starts/stops streaming of the current session to an online video platform."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE,
"Run-Ahead (Toggle)"
)
MSG_HASH(
MENU_ENUM_SUBLABEL_INPUT_META_RUNAHEAD_TOGGLE,
"Switches Run-Ahead on/off."
)
MSG_HASH(
MENU_ENUM_LABEL_VALUE_INPUT_META_AI_SERVICE,
"AI Service"
@ -11276,6 +11284,18 @@ MSG_HASH(
MSG_CORE_REMAP_FILE_LOADED,
"Core remap file loaded."
)
MSG_HASH(
MSG_RUNAHEAD_ENABLED,
"Run-Ahead enabled. Latency frames removed: %u."
)
MSG_HASH(
MSG_RUNAHEAD_ENABLED_WITH_SECOND_INSTANCE,
"Run-Ahead enabled with Secondary Instance. Latency frames removed: %u."
)
MSG_HASH(
MSG_RUNAHEAD_DISABLED,
"Run-Ahead disabled."
)
MSG_HASH(
MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES,
"Run-Ahead has been disabled because this core does not support save states."

View File

@ -1104,11 +1104,7 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
if (entry)
{
/* An entry corresponding to 'key' already exists
* > Check if it's read only */
if (entry->readonly)
return;
/* Check whether value is currently set */
* > Check whether value is currently set */
if (entry->value)
{
/* Do nothing if value is unchanged */
@ -1120,9 +1116,12 @@ void config_set_string(config_file_t *conf, const char *key, const char *val)
free(entry->value);
}
/* Update value */
entry->value = strdup(val);
conf->modified = true;
/* Update value
* > Note that once a value is set, it
* is no longer considered 'read only' */
entry->value = strdup(val);
entry->readonly = false;
conf->modified = true;
return;
}
}
@ -1296,18 +1295,10 @@ void config_file_dump_orbis(config_file_t *conf, int fd)
{
struct config_entry_list *list = NULL;
struct config_include_list *includes = conf->includes;
if (conf->reference)
fprintf(file, "#reference \"%s\"\n", conf->reference);
while (includes)
{
char cad[256];
snprintf(cad, sizeof(cad),
"#include %s\n", includes->path);
orbisWrite(fd, cad, strlen(cad));
includes = includes->next;
}
list = config_file_merge_sort_linked_list(
(struct config_entry_list*)conf->entries,
@ -1325,6 +1316,21 @@ void config_file_dump_orbis(config_file_t *conf, int fd)
}
list = list->next;
}
/* Config files are read from the top down - if
* duplicate entries are found then the topmost
* one in the list takes precedence. This means
* '#include' directives must go *after* individual
* config entries, otherwise they will override
* any custom-set values */
while (includes)
{
char cad[256];
snprintf(cad, sizeof(cad),
"#include %s\n", includes->path);
orbisWrite(fd, cad, strlen(cad));
includes = includes->next;
}
}
#endif
@ -1336,12 +1342,6 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
if (conf->reference)
fprintf(file, "#reference \"%s\"\n", conf->reference);
while (includes)
{
fprintf(file, "#include \"%s\"\n", includes->path);
includes = includes->next;
}
if (sort)
list = config_file_merge_sort_linked_list(
(struct config_entry_list*)conf->entries,
@ -1357,6 +1357,18 @@ void config_file_dump(config_file_t *conf, FILE *file, bool sort)
fprintf(file, "%s = \"%s\"\n", list->key, list->value);
list = list->next;
}
/* Config files are read from the top down - if
* duplicate entries are found then the topmost
* one in the list takes precedence. This means
* '#include' directives must go *after* individual
* config entries, otherwise they will override
* any custom-set values */
while (includes)
{
fprintf(file, "#include \"%s\"\n", includes->path);
includes = includes->next;
}
}
bool config_entry_exists(config_file_t *conf, const char *entry)

View File

@ -66,11 +66,16 @@
*-------------------------------------------------
*/
/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
#define LZMA_MIN_ALIGNMENT_BITS 512
#define LZMA_MIN_ALIGNMENT_BYTES (LZMA_MIN_ALIGNMENT_BITS / 8)
static void *lzma_fast_alloc(void *p, size_t size)
{
int scan;
uint32_t *addr = NULL;
uint32_t *addr = NULL;
lzma_allocator *codec = (lzma_allocator *)(p);
uintptr_t vaddr = 0;
/* compute the size, rounding to the nearest 1k */
size = (size + 0x3ff) & ~0x3ff;
@ -83,27 +88,36 @@ static void *lzma_fast_alloc(void *p, size_t size)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
/* return aligned address of the block */
return codec->allocptr2[scan];
}
}
/* alloc a new one and put it into the list */
addr = (uint32_t *)malloc(sizeof(uint32_t) * size + sizeof(uintptr_t));
if (!addr)
addr = (uint32_t *)malloc(size + sizeof(uint32_t) + LZMA_MIN_ALIGNMENT_BYTES);
if (addr==NULL)
return NULL;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (codec->allocptr[scan] == NULL)
{
/* store block address */
codec->allocptr[scan] = addr;
/* compute aligned address, store it */
vaddr = (uintptr_t)addr;
vaddr = (vaddr + sizeof(uint32_t) + (LZMA_MIN_ALIGNMENT_BYTES-1)) & (~(LZMA_MIN_ALIGNMENT_BYTES-1));
codec->allocptr2[scan] = (uint32_t*)vaddr;
break;
}
}
/* set the low bit of the size so we don't match next time */
*addr = (uint32_t)(size | 1);
return addr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
*addr = size | 1;
/* return aligned address */
return (void*)vaddr;
}
/*-------------------------------------------------
@ -114,21 +128,22 @@ static void *lzma_fast_alloc(void *p, size_t size)
static void lzma_fast_free(void *p, void *address)
{
int scan;
uint32_t *ptr;
lzma_allocator *codec;
uint32_t *ptr = NULL;
lzma_allocator *codec = NULL;
if (address == NULL)
return;
codec = (lzma_allocator *)(p);
/* find the hunk */
ptr = (uint32_t *)(address) - 1;
ptr = (uint32_t *)address;
for (scan = 0; scan < MAX_LZMA_ALLOCS; scan++)
{
if (ptr == codec->allocptr[scan])
if (ptr == codec->allocptr2[scan])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
*codec->allocptr[scan] &= ~1;
return;
}
}

View File

@ -241,9 +241,14 @@ chd_error zlib_codec_decompress(void *codec, const uint8_t *src, uint32_t comple
allocates and frees memory frequently
-------------------------------------------------*/
/* Huge alignment values for possible SIMD optimization by compiler (NEON, SSE, AVX) */
#define ZLIB_MIN_ALIGNMENT_BITS 512
#define ZLIB_MIN_ALIGNMENT_BYTES (ZLIB_MIN_ALIGNMENT_BITS / 8)
voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
uintptr_t paddr = 0;
UINT32 *ptr;
int i;
@ -258,12 +263,14 @@ voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
{
/* set the low bit of the size so we don't match next time */
*ptr |= 1;
return ptr + 1;
/* return aligned block address */
return (voidpf)(alloc->allocptr2[i]);
}
}
/* alloc a new one */
ptr = (UINT32 *)malloc(size + sizeof(uintptr_t));
ptr = (UINT32 *)malloc(size + sizeof(UINT32) + ZLIB_MIN_ALIGNMENT_BYTES);
if (!ptr)
return NULL;
@ -272,12 +279,16 @@ voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
if (!alloc->allocptr[i])
{
alloc->allocptr[i] = ptr;
paddr = (((uintptr_t)ptr) + sizeof(UINT32) + (ZLIB_MIN_ALIGNMENT_BYTES-1)) & (~(ZLIB_MIN_ALIGNMENT_BYTES-1));
alloc->allocptr2[i] = (uint32_t*)paddr;
break;
}
/* set the low bit of the size so we don't match next time */
*ptr = size | 1;
return ptr + (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
/* return aligned block address */
return (voidpf)paddr;
}
/*-------------------------------------------------
@ -288,15 +299,15 @@ voidpf zlib_fast_alloc(voidpf opaque, uInt items, uInt size)
void zlib_fast_free(voidpf opaque, voidpf address)
{
zlib_allocator *alloc = (zlib_allocator *)opaque;
UINT32 *ptr = (UINT32 *)address - (sizeof(uint32_t) == sizeof(uintptr_t) ? 1 : 2);
UINT32 *ptr = (UINT32 *)address;
int i;
/* find the hunk */
for (i = 0; i < MAX_ZLIB_ALLOCS; i++)
if (ptr == alloc->allocptr[i])
if (ptr == alloc->allocptr2[i])
{
/* clear the low bit of the size to allow matches */
*ptr &= ~1;
*(alloc->allocptr[i]) &= ~1;
return;
}
}

View File

@ -143,16 +143,6 @@ rxml_document_t *rxml_load_document_string(const char *str)
if (!doc)
goto error;
doc->root_node = (struct rxml_node *)malloc(
sizeof(*doc->root_node));
doc->root_node->name = NULL;
doc->root_node->data = NULL;
doc->root_node->attrib = NULL;
doc->root_node->children = NULL;
doc->root_node->next = NULL;
yxml_init(&x, buf->xml, BUFSIZE);
for (; *str; ++str)
@ -256,30 +246,14 @@ rxml_document_t *rxml_load_document_string(const char *str)
case YXML_ATTRSTART:
if (attr)
{
struct rxml_attrib_node
*new_node = (struct rxml_attrib_node*)
calloc(1, sizeof(*attr));
attr = new_node;
attr->next = new_node ;
}
attr = attr->next = (struct rxml_attrib_node*)
calloc(1, sizeof(*attr));
else
{
struct rxml_attrib_node
*new_node = (struct rxml_attrib_node*)
calloc(1, sizeof(*attr));
attr = new_node;
if (node)
node->attrib = new_node;
}
attr = node->attrib = (struct rxml_attrib_node*)calloc(1, sizeof(*attr));
if (attr)
{
if (attr->attrib)
free(attr->attrib);
attr->attrib = strdup(x.attr);
}
if (attr->attrib)
free(attr->attrib);
attr->attrib = strdup(x.attr);
valptr = buf->val;
break;

View File

@ -27,6 +27,7 @@ typedef struct _zlib_allocator zlib_allocator;
struct _zlib_allocator
{
UINT32 * allocptr[MAX_ZLIB_ALLOCS];
UINT32 * allocptr2[MAX_ZLIB_ALLOCS];
};
typedef struct _zlib_codec_data zlib_codec_data;

View File

@ -30,6 +30,7 @@ struct _lzma_allocator
void (*Free)(void *p, void *address); /* address can be 0 */
void (*FreeSz)(void *p, void *address, size_t size); /* address can be 0 */
uint32_t* allocptr[MAX_LZMA_ALLOCS];
uint32_t* allocptr2[MAX_LZMA_ALLOCS];
};
typedef struct _lzma_codec_data lzma_codec_data;

View File

@ -269,6 +269,7 @@ DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_game_focus_toggle, ME
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_ui_companion_toggle, MENU_ENUM_SUBLABEL_INPUT_META_UI_COMPANION_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_recording_toggle, MENU_ENUM_SUBLABEL_INPUT_META_RECORDING_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_streaming_toggle, MENU_ENUM_SUBLABEL_INPUT_META_STREAMING_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_runahead_toggle, MENU_ENUM_SUBLABEL_INPUT_META_RUNAHEAD_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_ai_service, MENU_ENUM_SUBLABEL_INPUT_META_AI_SERVICE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_meta_menu_toggle, MENU_ENUM_SUBLABEL_INPUT_META_MENU_TOGGLE)
DEFAULT_SUBLABEL_MACRO(action_bind_sublabel_input_hotkey_block_delay, MENU_ENUM_SUBLABEL_INPUT_HOTKEY_BLOCK_DELAY)
@ -1694,6 +1695,9 @@ int menu_cbs_init_bind_sublabel(menu_file_list_cbs_t *cbs,
case RARCH_STREAMING_TOGGLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_streaming_toggle);
return 0;
case RARCH_RUNAHEAD_TOGGLE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_runahead_toggle);
return 0;
case RARCH_AI_SERVICE:
BIND_ACTION_SUBLABEL(cbs, action_bind_sublabel_input_meta_ai_service);
return 0;

View File

@ -459,6 +459,9 @@ enum msg_hash_enums
MSG_GAME_REMAP_FILE_LOADED,
MSG_DIRECTORY_REMAP_FILE_LOADED,
MSG_CORE_REMAP_FILE_LOADED,
MSG_RUNAHEAD_ENABLED,
MSG_RUNAHEAD_ENABLED_WITH_SECOND_INSTANCE,
MSG_RUNAHEAD_DISABLED,
MSG_RUNAHEAD_CORE_DOES_NOT_SUPPORT_SAVESTATES,
MSG_RUNAHEAD_FAILED_TO_SAVE_STATE,
MSG_RUNAHEAD_FAILED_TO_LOAD_STATE,
@ -851,6 +854,7 @@ enum msg_hash_enums
MENU_ENUM_LABEL_VALUE_INPUT_META_UI_COMPANION_TOGGLE,
MENU_ENUM_LABEL_VALUE_INPUT_META_RECORDING_TOGGLE,
MENU_ENUM_LABEL_VALUE_INPUT_META_STREAMING_TOGGLE,
MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE,
MENU_ENUM_LABEL_VALUE_INPUT_META_AI_SERVICE,
MENU_ENUM_LABEL_VALUE_INPUT_META_MENU_TOGGLE,
@ -903,6 +907,7 @@ enum msg_hash_enums
MENU_ENUM_SUBLABEL_INPUT_META_UI_COMPANION_TOGGLE,
MENU_ENUM_SUBLABEL_INPUT_META_RECORDING_TOGGLE,
MENU_ENUM_SUBLABEL_INPUT_META_STREAMING_TOGGLE,
MENU_ENUM_SUBLABEL_INPUT_META_RUNAHEAD_TOGGLE,
MENU_ENUM_SUBLABEL_INPUT_META_AI_SERVICE,
MENU_ENUM_SUBLABEL_INPUT_META_MENU_TOGGLE,

View File

@ -24,6 +24,7 @@
android:isGame="true"
android:banner="@drawable/banner"
android:extractNativeLibs="true"
android:requestLegacyExternalStorage="true"
tools:ignore="UnusedAttribute">
<activity android:name="com.retroarch.browser.mainmenu.MainMenuActivity" android:exported="true" android:launchMode="singleInstance">
<intent-filter>

View File

@ -25,8 +25,8 @@ allprojects {
apply plugin: 'com.android.application'
android {
compileSdkVersion 28
buildToolsVersion "28.0.3"
compileSdkVersion 29
buildToolsVersion "29.0.3"
flavorDimensions "variant"
@ -37,7 +37,7 @@ android {
arguments "-j${Runtime.runtime.availableProcessors()}"
}
}
targetSdkVersion 28
targetSdkVersion 29
}
productFlavors {

View File

@ -1,10 +1,10 @@
apply plugin: 'com.android.dynamic-feature'
android {
compileSdkVersion 28
compileSdkVersion 29
defaultConfig {
minSdkVersion 21
targetSdkVersion 28
targetSdkVersion 29
}
flavorDimensions "variant"

View File

@ -85,6 +85,8 @@ HAVE_VIVANTE_FBDEV=no # Vivante fbdev context support
HAVE_OPENDINGUX_FBDEV=no # Opendingux fbdev context support
HAVE_OPENGLES=no # Use GLESv2 instead of desktop GL
HAVE_OPENGLES3=no # OpenGLES3 support
HAVE_OPENGLES3_1=no # OpenGLES3.1 support
HAVE_OPENGLES3_2=no # OpenGLES3.2 support
HAVE_X11=auto # everything X11.
HAVE_XRANDR=auto # Xrandr support.
HAVE_OMAP=no # OMAP video support
@ -187,3 +189,4 @@ C89_METAL=no
HAVE_NETWORK_VIDEO=no
HAVE_STEAM=no # Enable Steam build
HAVE_ODROIDGO2=no # ODROID-GO Advance rotation support (requires librga)
HAVE_GIT_VERSION=yes # Git version support

View File

@ -2730,6 +2730,7 @@ static const struct input_bind_map input_config_bind_map[RARCH_BIND_LIST_END_NUL
#endif
DECLARE_META_BIND(2, recording_toggle, RARCH_RECORDING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RECORDING_TOGGLE),
DECLARE_META_BIND(2, streaming_toggle, RARCH_STREAMING_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_STREAMING_TOGGLE),
DECLARE_META_BIND(2, runahead_toggle, RARCH_RUNAHEAD_TOGGLE, MENU_ENUM_LABEL_VALUE_INPUT_META_RUNAHEAD_TOGGLE),
DECLARE_META_BIND(2, ai_service, RARCH_AI_SERVICE, MENU_ENUM_LABEL_VALUE_INPUT_META_AI_SERVICE),
};
@ -12982,6 +12983,7 @@ static const struct cmd_map map[] = {
{ "MENU_TOGGLE", RARCH_MENU_TOGGLE },
{ "RECORDING_TOGGLE", RARCH_RECORDING_TOGGLE },
{ "STREAMING_TOGGLE", RARCH_STREAMING_TOGGLE },
{ "RUNAHEAD_TOGGLE", RARCH_RUNAHEAD_TOGGLE },
{ "MENU_UP", RETRO_DEVICE_ID_JOYPAD_UP },
{ "MENU_DOWN", RETRO_DEVICE_ID_JOYPAD_DOWN },
{ "MENU_LEFT", RETRO_DEVICE_ID_JOYPAD_LEFT },
@ -15993,6 +15995,37 @@ bool command_event(enum event_command cmd, void *data)
command_event(CMD_EVENT_RECORD_INIT, NULL);
}
break;
case CMD_EVENT_RUNAHEAD_TOGGLE:
settings->bools.run_ahead_enabled = !(settings->bools.run_ahead_enabled);
char msg[256];
msg[0] = '\0';
if (!settings->bools.run_ahead_enabled)
{
runloop_msg_queue_push(msg_hash_to_str(MSG_RUNAHEAD_DISABLED),
1, 100, false,
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
else if (!settings->bools.run_ahead_secondary_instance)
{
snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_RUNAHEAD_ENABLED),
settings->uints.run_ahead_frames);
runloop_msg_queue_push(
msg, 1, 100, false,
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
else
{
snprintf(msg, sizeof(msg), msg_hash_to_str(MSG_RUNAHEAD_ENABLED_WITH_SECOND_INSTANCE),
settings->uints.run_ahead_frames);
runloop_msg_queue_push(
msg, 1, 100, false,
NULL, MESSAGE_QUEUE_ICON_DEFAULT, MESSAGE_QUEUE_CATEGORY_INFO);
}
break;
case CMD_EVENT_RECORDING_TOGGLE:
if (recording_is_enabled())
command_event(CMD_EVENT_RECORD_DEINIT, NULL);
@ -18846,6 +18879,22 @@ static bool dynamic_request_hw_context(enum retro_hw_context_type type,
#if defined(HAVE_OPENGLES3)
case RETRO_HW_CONTEXT_OPENGLES_VERSION:
#ifndef HAVE_OPENGLES3_2
if (major == 3 && minor == 2)
{
RARCH_ERR("Requesting OpenGLES%u.%u context, but RetroArch is compiled against a lesser version. Cannot use HW context.\n",
major, minor);
return false;
}
#endif
#if !defined(HAVE_OPENGLES3_2) && !defined(HAVE_OPENGLES3_1)
if (major == 3 && minor == 1)
{
RARCH_ERR("Requesting OpenGLES%u.%u context, but RetroArch is compiled against a lesser version. Cannot use HW context.\n",
major, minor);
return false;
}
#endif
RARCH_LOG("Requesting OpenGLES%u.%u context.\n",
major, minor);
break;
@ -24503,41 +24552,43 @@ static void input_driver_poll(void)
{
unsigned remap_button =
settings->uints.input_keymapper_ids[i][j];
bool remap_valid =
remap_button != RETROK_UNKNOWN;
if (remap_valid)
{
unsigned current_button_value =
BIT256_GET_PTR(p_new_state, j);
bool remap_valid =
remap_button != RETROK_UNKNOWN &&
!handle->keys[remap_button / 32];
if (!remap_valid)
continue;
unsigned current_button_value =
BIT256_GET_PTR(p_new_state, j);
#ifdef HAVE_OVERLAY
if (poll_overlay && i == 0)
{
input_overlay_state_t *ol_state =
overlay_pointer
? &overlay_pointer->overlay_state
: NULL;
if (ol_state)
current_button_value |=
BIT256_GET(ol_state->buttons, j);
}
if (poll_overlay && i == 0)
{
input_overlay_state_t *ol_state =
overlay_pointer
? &overlay_pointer->overlay_state
: NULL;
if (ol_state)
current_button_value |=
BIT256_GET(ol_state->buttons, j);
}
#endif
if ((current_button_value == 1)
&& (j != remap_button))
{
MAPPER_SET_KEY (handle,
remap_button);
input_keyboard_event(true,
remap_button,
0, 0, RETRO_DEVICE_KEYBOARD);
continue;
}
/* Release keyboard event*/
input_keyboard_event(false,
if ((current_button_value == 1)
&& (j != remap_button))
{
MAPPER_SET_KEY (handle,
remap_button);
input_keyboard_event(true,
remap_button,
0, 0, RETRO_DEVICE_KEYBOARD);
continue;
}
/* Release keyboard event*/
input_keyboard_event(false,
remap_button,
0, 0, RETRO_DEVICE_KEYBOARD);
}
break;
@ -39679,12 +39730,15 @@ static enum runloop_state runloop_check_state(
/* Check if we have pressed the recording toggle button */
HOTKEY_CHECK(RARCH_RECORDING_TOGGLE, CMD_EVENT_RECORDING_TOGGLE, true, NULL);
/* Check if we have pressed the AI Service toggle button */
HOTKEY_CHECK(RARCH_AI_SERVICE, CMD_EVENT_AI_SERVICE_TOGGLE, true, NULL);
/* Check if we have pressed the streaming toggle button */
HOTKEY_CHECK(RARCH_STREAMING_TOGGLE, CMD_EVENT_STREAMING_TOGGLE, true, NULL);
/* Check if we have pressed the Run-Ahead toggle button */
HOTKEY_CHECK(RARCH_RUNAHEAD_TOGGLE, CMD_EVENT_RUNAHEAD_TOGGLE, true, NULL);
/* Check if we have pressed the AI Service toggle button */
HOTKEY_CHECK(RARCH_AI_SERVICE, CMD_EVENT_AI_SERVICE_TOGGLE, true, NULL);
if (BIT256_GET(current_bits, RARCH_VOLUME_UP))
command_event(CMD_EVENT_VOLUME_UP, NULL);
else if (BIT256_GET(current_bits, RARCH_VOLUME_DOWN))

View File

@ -708,10 +708,15 @@ static int database_info_list_iterate_found_match(
const char *archive_name
)
{
char db_crc[PATH_MAX_LENGTH];
char db_playlist_base_str[PATH_MAX_LENGTH];
char db_playlist_path[PATH_MAX_LENGTH];
char entry_path_str[PATH_MAX_LENGTH];
/* TODO/FIXME - heap allocations are done here to avoid
* running out of stack space on systems with a limited stack size.
* We should use less fullsize paths in the future so that we don't
* need to have all these big char arrays here */
size_t str_len = PATH_MAX_LENGTH * sizeof(char);
char* db_crc = (char*)malloc(str_len);
char* db_playlist_base_str = (char*)malloc(str_len);
char* db_playlist_path = (char*)malloc(str_len);
char* entry_path_str = (char*)malloc(str_len);
char *hash = NULL;
playlist_t *playlist = NULL;
const char *db_path =
@ -727,25 +732,25 @@ static int database_info_list_iterate_found_match(
entry_path_str[0] = '\0';
fill_short_pathname_representation_noext(db_playlist_base_str,
db_path, sizeof(db_playlist_base_str));
db_path, str_len);
strlcat(db_playlist_base_str, ".lpl", sizeof(db_playlist_base_str));
strlcat(db_playlist_base_str, ".lpl", str_len);
if (!string_is_empty(_db->playlist_directory))
fill_pathname_join(db_playlist_path, _db->playlist_directory,
db_playlist_base_str, sizeof(db_playlist_path));
db_playlist_base_str, str_len);
playlist_config_set_path(&_db->playlist_config, db_playlist_path);
playlist = playlist_init(&_db->playlist_config);
snprintf(db_crc, sizeof(db_crc), "%08X|crc", db_info_entry->crc32);
snprintf(db_crc, str_len, "%08X|crc", db_info_entry->crc32);
if (entry_path)
strlcpy(entry_path_str, entry_path, sizeof(entry_path_str));
strlcpy(entry_path_str, entry_path, str_len);
if (!string_is_empty(archive_name))
fill_pathname_join_delim(entry_path_str,
entry_path_str, archive_name, '#', sizeof(entry_path_str));
entry_path_str, archive_name, '#', str_len);
if (core_info_database_match_archive_member(
db_state->list->elems[db_state->list_index].data) &&
@ -826,6 +831,10 @@ static int database_info_list_iterate_found_match(
db_state->list->elems[0] = entry;
}
free(db_crc);
free(db_playlist_base_str);
free(db_playlist_path);
free(entry_path_str);
return 0;
}

View File

@ -860,7 +860,11 @@ static void task_load_handler(retro_task_t *task)
{
if (state->autoload)
{
#ifdef __CELLOS_LV2__
char *msg = (char*)malloc(8192 * sizeof(char));
#else
char msg[8192];
#endif
msg[0] = '\0';
@ -871,6 +875,9 @@ static void task_load_handler(retro_task_t *task)
state->path,
msg_hash_to_str(MSG_FAILED));
task_set_error(task, strdup(msg));
#ifdef __CELLOS_LV2__
free(msg);
#endif
}
else
task_set_error(task, strdup(msg_hash_to_str(MSG_FAILED_TO_LOAD_STATE)));

View File

@ -141,7 +141,7 @@ void PlaylistEntryDialog::loadPlaylistOptions()
QString ui_display_name;
QHash<QString, QString> hash;
const core_info_t *core = &core_info_list->list[i];
QStringList databases = QString(core->databases).split("|");
QStringList databases = string_split_to_qt(QString(core->databases), '|');
hash["core_name"] = core->core_name;
hash["core_display_name"] = core->display_name;
@ -278,8 +278,7 @@ const QStringList PlaylistEntryDialog::getSelectedExtensions()
/* Otherwise it would create a QStringList with a single blank entry... */
if (!text.isEmpty())
list = text.split(' ');
list = string_split_to_qt(text, ' ');
return list;
}

View File

@ -8,6 +8,7 @@
#include <QButtonGroup>
#include "settingswidgets.h"
#include "../ui_qt.h"
#include <math.h>
@ -442,7 +443,7 @@ StringComboBox::StringComboBox(rarch_setting_t *setting, QWidget *parent) :
,m_setting(setting)
,m_value(setting->value.target.string)
{
addItems(QString(setting->values).split("|"));
addItems(string_split_to_qt(QString(setting->values), '|'));
connect(this, SIGNAL(currentTextChanged(const QString&)), this, SLOT(onCurrentTextChanged(const QString&)));

View File

@ -16,6 +16,7 @@
*/
#include "ui_qt_load_core_window.h"
#include "../ui_qt.h"
#include <QFileDialog>
#include <QDesktopWidget>
@ -235,8 +236,7 @@ void LoadCoreWindow::initCoreList(const QStringList &extensionFilters)
name_item = new QTableWidgetItem(name);
hash["path"] = core->path;
hash["extensions"] = QString(
core->supported_extensions).split("|");
hash["extensions"] = string_split_to_qt(QString(core->supported_extensions), '|');
name_item->setData(Qt::UserRole, hash);
name_item->setFlags(name_item->flags() & ~Qt::ItemIsEditable);

View File

@ -764,3 +764,26 @@ ui_companion_driver_t ui_companion_qt = {
&ui_application_qt,
"qt",
};
QStringList string_split_to_qt(QString str, char delim)
{
int at;
QStringList list = QStringList();
for (at = 0;;)
{
/* Find next split */
int spl = str.indexOf(delim, at);
/* Store split into list of extensions */
list << str.mid(at, (spl < 0 ? -1 : spl - at));
/* No more splits */
if (spl < 0)
break;
at = spl + 1;
}
return list;
}

View File

@ -678,6 +678,8 @@ typedef struct ui_window_qt
MainWindow *qtWindow;
} ui_window_qt_t;
QStringList string_split_to_qt(QString str, char delim);
RETRO_END_DECLS
#endif