diff --git a/Makefile.common b/Makefile.common index 65db082a1c..f2f60b092a 100644 --- a/Makefile.common +++ b/Makefile.common @@ -161,7 +161,6 @@ OBJ += frontend/frontend.o \ msg_hash.o \ intl/msg_hash_us.o \ runloop.o \ - $(LIBRETRO_COMM_DIR)/algorithms/mismatch.o \ $(LIBRETRO_COMM_DIR)/queues/task_queue.o \ tasks/task_content.o \ tasks/task_save.o \ diff --git a/griffin/griffin.c b/griffin/griffin.c index c24ac256a9..80bcf2049c 100644 --- a/griffin/griffin.c +++ b/griffin/griffin.c @@ -49,8 +49,6 @@ CONSOLE EXTENSIONS ALGORITHMS ============================================================ */ -#include "../libretro-common/algorithms/mismatch.c" - /*============================================================ ARCHIVE FILE ============================================================ */ diff --git a/libretro-common/algorithms/mismatch.c b/libretro-common/algorithms/mismatch.c deleted file mode 100644 index 2f733bf618..0000000000 --- a/libretro-common/algorithms/mismatch.c +++ /dev/null @@ -1,139 +0,0 @@ -/* Copyright (C) 2010-2017 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (mismatch.c). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#include -#include -#include - -#include -#include -#include - -#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__) -#define CPU_X86 -#endif - -/* Other arches SIGBUS (usually) on unaligned accesses. */ -#ifndef CPU_X86 -#define NO_UNALIGNED_MEM -#endif - -#if __SSE2__ -#include -#endif - -/* There's no equivalent in libc, you'd think so ... - * std::mismatch exists, but it's not optimized at all. */ -size_t find_change(const uint16_t *a, const uint16_t *b) -{ -#if __SSE2__ - const __m128i *a128 = (const __m128i*)a; - const __m128i *b128 = (const __m128i*)b; - - for (;;) - { - __m128i v0 = _mm_loadu_si128(a128); - __m128i v1 = _mm_loadu_si128(b128); - __m128i c = _mm_cmpeq_epi32(v0, v1); - uint32_t mask = _mm_movemask_epi8(c); - - if (mask != 0xffff) /* Something has changed, figure out where. */ - { - size_t ret = (((uint8_t*)a128 - (uint8_t*)a) | - (compat_ctz(~mask))) >> 1; - return ret | (a[ret] == b[ret]); - } - - a128++; - b128++; - } -#else - const uint16_t *a_org = a; -#ifdef NO_UNALIGNED_MEM - while (((uintptr_t)a & (sizeof(size_t) - 1)) && *a == *b) - { - a++; - b++; - } - if (*a == *b) -#endif - { - const size_t *a_big = (const size_t*)a; - const size_t *b_big = (const size_t*)b; - - while (*a_big == *b_big) - { - a_big++; - b_big++; - } - a = (const uint16_t*)a_big; - b = (const uint16_t*)b_big; - - while (*a == *b) - { - a++; - b++; - } - } - return a - a_org; -#endif -} - -size_t find_same(const uint16_t *a, const uint16_t *b) -{ - const uint16_t *a_org = a; -#ifdef NO_UNALIGNED_MEM - if (((uintptr_t)a & (sizeof(uint32_t) - 1)) && *a != *b) - { - a++; - b++; - } - if (*a != *b) -#endif - { - /* With this, it's random whether two consecutive identical - * words are caught. - * - * Luckily, compression rate is the same for both cases, and - * three is always caught. - * - * (We prefer to miss two-word blocks, anyways; fewer iterations - * of the outer loop, as well as in the decompressor.) */ - const uint32_t *a_big = (const uint32_t*)a; - const uint32_t *b_big = (const uint32_t*)b; - - while (*a_big != *b_big) - { - a_big++; - b_big++; - } - a = (const uint16_t*)a_big; - b = (const uint16_t*)b_big; - - if (a != a_org && a[-1] == b[-1]) - { - a--; - b--; - } - } - return a - a_org; -} diff --git a/libretro-common/include/algorithms/mismatch.h b/libretro-common/include/algorithms/mismatch.h deleted file mode 100644 index bfcde4af19..0000000000 --- a/libretro-common/include/algorithms/mismatch.h +++ /dev/null @@ -1,40 +0,0 @@ -/* Copyright (C) 2010-2017 The RetroArch team - * - * --------------------------------------------------------------------------------------- - * The following license statement only applies to this file (mismatch.h). - * --------------------------------------------------------------------------------------- - * - * Permission is hereby granted, free of charge, - * to any person obtaining a copy of this software and associated documentation files (the "Software"), - * to deal in the Software without restriction, including without limitation the rights to - * use, copy, modify, merge, publish, distribute, sublicense, and/or sell copies of the Software, - * and to permit persons to whom the Software is furnished to do so, subject to the following conditions: - * - * The above copyright notice and this permission notice shall be included in all copies or substantial portions of the Software. - * - * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR IMPLIED, - * INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, - * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. - * IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, - * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, - * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE. - */ - -#ifndef __LIBRETRO_SDK_ALGORITHMS_MISMATCH_H__ -#define __LIBRETRO_SDK_ALGORITHMS_MISMATCH_H__ - -#include -#include - -#include -#include - -RETRO_BEGIN_DECLS - -size_t find_change(const uint16_t *a, const uint16_t *b); - -size_t find_same(const uint16_t *a, const uint16_t *b); - -RETRO_END_DECLS - -#endif diff --git a/managers/state_manager.c b/managers/state_manager.c index d3a00a6dba..731f9f83ee 100644 --- a/managers/state_manager.c +++ b/managers/state_manager.c @@ -16,12 +16,13 @@ */ #define __STDC_LIMIT_MACROS +#include #include #include #include #include -#include +#include #include "state_manager.h" #include "../msg_hash.h" @@ -43,6 +44,116 @@ #define UINT32_MAX 0xffffffffu #endif +#if defined(__x86_64__) || defined(__i386__) || defined(__i486__) || defined(__i686__) +#define CPU_X86 +#endif + +/* Other arches SIGBUS (usually) on unaligned accesses. */ +#ifndef CPU_X86 +#define NO_UNALIGNED_MEM +#endif + +#if __SSE2__ +#include +#endif + +/* There's no equivalent in libc, you'd think so ... + * std::mismatch exists, but it's not optimized at all. */ +static size_t find_change(const uint16_t *a, const uint16_t *b) +{ +#if __SSE2__ + const __m128i *a128 = (const __m128i*)a; + const __m128i *b128 = (const __m128i*)b; + + for (;;) + { + __m128i v0 = _mm_loadu_si128(a128); + __m128i v1 = _mm_loadu_si128(b128); + __m128i c = _mm_cmpeq_epi32(v0, v1); + uint32_t mask = _mm_movemask_epi8(c); + + if (mask != 0xffff) /* Something has changed, figure out where. */ + { + size_t ret = (((uint8_t*)a128 - (uint8_t*)a) | + (compat_ctz(~mask))) >> 1; + return ret | (a[ret] == b[ret]); + } + + a128++; + b128++; + } +#else + const uint16_t *a_org = a; +#ifdef NO_UNALIGNED_MEM + while (((uintptr_t)a & (sizeof(size_t) - 1)) && *a == *b) + { + a++; + b++; + } + if (*a == *b) +#endif + { + const size_t *a_big = (const size_t*)a; + const size_t *b_big = (const size_t*)b; + + while (*a_big == *b_big) + { + a_big++; + b_big++; + } + a = (const uint16_t*)a_big; + b = (const uint16_t*)b_big; + + while (*a == *b) + { + a++; + b++; + } + } + return a - a_org; +#endif +} + +static size_t find_same(const uint16_t *a, const uint16_t *b) +{ + const uint16_t *a_org = a; +#ifdef NO_UNALIGNED_MEM + if (((uintptr_t)a & (sizeof(uint32_t) - 1)) && *a != *b) + { + a++; + b++; + } + if (*a != *b) +#endif + { + /* With this, it's random whether two consecutive identical + * words are caught. + * + * Luckily, compression rate is the same for both cases, and + * three is always caught. + * + * (We prefer to miss two-word blocks, anyways; fewer iterations + * of the outer loop, as well as in the decompressor.) */ + const uint32_t *a_big = (const uint32_t*)a; + const uint32_t *b_big = (const uint32_t*)b; + + while (*a_big != *b_big) + { + a_big++; + b_big++; + } + a = (const uint16_t*)a_big; + b = (const uint16_t*)b_big; + + if (a != a_org && a[-1] == b[-1]) + { + a--; + b--; + } + } + return a - a_org; +} + struct state_manager { uint8_t *data; @@ -99,7 +210,7 @@ struct state_manager_rewind_state }; static struct state_manager_rewind_state rewind_state; -static bool frame_is_reversed; +static bool frame_is_reversed = false; /* Returns the maximum compressed size of a savestate. * It is very likely to compress to far less. */