diff options
Diffstat (limited to 'src/common')
37 files changed, 192 insertions, 1883 deletions
diff --git a/src/common/CMakeLists.txt b/src/common/CMakeLists.txt index daa2d59de..f8fc6450f 100644 --- a/src/common/CMakeLists.txt +++ b/src/common/CMakeLists.txt @@ -5,13 +5,10 @@ set(SRCS break_points.cpp emu_window.cpp file_util.cpp - hash.cpp key_map.cpp logging/filter.cpp logging/text_formatter.cpp logging/backend.cpp - math_util.cpp - mem_arena.cpp memory_util.cpp misc.cpp profiler.cpp @@ -27,7 +24,6 @@ set(HEADERS bit_field.h break_points.h chunk_file.h - common.h common_funcs.h common_paths.h common_types.h @@ -37,7 +33,6 @@ set(HEADERS emu_window.h fifo_queue.h file_util.h - hash.h key_map.h linear_disk_cache.h logging/text_formatter.h @@ -46,7 +41,6 @@ set(HEADERS logging/backend.h make_unique.h math_util.h - mem_arena.h memory_util.h platform.h profiler.h diff --git a/src/common/assert.h b/src/common/assert.h index 9ca7adb15..4f26c63e9 100644 --- a/src/common/assert.h +++ b/src/common/assert.h @@ -4,6 +4,7 @@ #pragma once +#include <cstdio> #include <cstdlib> #include "common/common_funcs.h" diff --git a/src/common/bit_field.h b/src/common/bit_field.h index 8eab054b8..1f3ecf844 100644 --- a/src/common/bit_field.h +++ b/src/common/bit_field.h @@ -35,7 +35,7 @@ #include <limits> #include <type_traits> -#include "common/common.h" +#include "common/common_funcs.h" /* * Abstract bitfield class diff --git a/src/common/break_points.cpp b/src/common/break_points.cpp index 2655d3ce9..023a485a4 100644 --- a/src/common/break_points.cpp +++ b/src/common/break_points.cpp @@ -2,7 +2,6 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/common.h" #include "common/debug_interface.h" #include "common/break_points.h" #include "common/logging/log.h" @@ -10,14 +9,14 @@ #include <sstream> #include <algorithm> -bool BreakPoints::IsAddressBreakPoint(u32 iAddress) +bool BreakPoints::IsAddressBreakPoint(u32 iAddress) const { auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress; }; auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); return it != m_BreakPoints.end(); } -bool BreakPoints::IsTempBreakPoint(u32 iAddress) +bool BreakPoints::IsTempBreakPoint(u32 iAddress) const { auto cond = [&iAddress](const TBreakPoint& bp) { return bp.iAddress == iAddress && bp.bTemporary; }; auto it = std::find_if(m_BreakPoints.begin(), m_BreakPoints.end(), cond); diff --git a/src/common/break_points.h b/src/common/break_points.h index 5557cd50e..f0a55e7b1 100644 --- a/src/common/break_points.h +++ b/src/common/break_points.h @@ -7,7 +7,7 @@ #include <vector> #include <string> -#include "common/common.h" +#include "common/common_types.h" class DebugInterface; @@ -56,8 +56,8 @@ public: void AddFromStrings(const TBreakPointsStr& bps); // is address breakpoint - bool IsAddressBreakPoint(u32 iAddress); - bool IsTempBreakPoint(u32 iAddress); + bool IsAddressBreakPoint(u32 iAddress) const; + bool IsTempBreakPoint(u32 iAddress) const; // Add BreakPoint void Add(u32 em_address, bool temp=false); diff --git a/src/common/chunk_file.h b/src/common/chunk_file.h index 3f97d56bf..dcd80525e 100644 --- a/src/common/chunk_file.h +++ b/src/common/chunk_file.h @@ -34,8 +34,9 @@ #include <set> #include <type_traits> -#include "common/common.h" +#include "common/common_types.h" #include "common/file_util.h" +#include "common/logging/log.h" template <class T> struct LinkedListItem : public T diff --git a/src/common/common.h b/src/common/common.h deleted file mode 100644 index f7d0f55c5..000000000 --- a/src/common/common.h +++ /dev/null @@ -1,120 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -// DO NOT EVER INCLUDE <windows.h> directly _or indirectly_ from this file -// since it slows down the build a lot. - -#include <cstdlib> -#include <cstdio> -#include <cstring> - -#define STACKALIGN - -// An inheritable class to disallow the copy constructor and operator= functions -class NonCopyable -{ -protected: - NonCopyable() {} - NonCopyable(const NonCopyable&&) {} - void operator=(const NonCopyable&&) {} -private: - NonCopyable(NonCopyable&); - NonCopyable& operator=(NonCopyable& other); -}; - -#include "common/assert.h" -#include "common/logging/log.h" -#include "common/common_types.h" -#include "common/common_funcs.h" -#include "common/common_paths.h" -#include "common/platform.h" - -#ifdef __APPLE__ -// The Darwin ABI requires that stack frames be aligned to 16-byte boundaries. -// This is only needed on i386 gcc - x86_64 already aligns to 16 bytes. - #if defined __i386__ && defined __GNUC__ - #undef STACKALIGN - #define STACKALIGN __attribute__((__force_align_arg_pointer__)) - #endif -#elif defined _WIN32 -// Check MSC ver - #if defined _MSC_VER && _MSC_VER <= 1000 - #error needs at least version 1000 of MSC - #endif - - #ifndef NOMINMAX - #define NOMINMAX - #endif - -// Alignment - #define MEMORY_ALIGNED16(x) __declspec(align(16)) x - #define MEMORY_ALIGNED32(x) __declspec(align(32)) x - #define MEMORY_ALIGNED64(x) __declspec(align(64)) x - #define MEMORY_ALIGNED128(x) __declspec(align(128)) x - #define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x - #define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x -#endif - -// Windows compatibility -#ifndef _WIN32 - #ifdef _LP64 - #define _M_X64 1 - #else - #define _M_IX86 1 - #endif - #define __forceinline inline __attribute__((always_inline)) - #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x - #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x - #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x - #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x - #define MEMORY_ALIGNED16_DECL(x) __attribute__((aligned(16))) x - #define MEMORY_ALIGNED64_DECL(x) __attribute__((aligned(64))) x -#endif - -#ifdef _MSC_VER - #define __strdup _strdup - #define __getcwd _getcwd - #define __chdir _chdir -#else - #define __strdup strdup - #define __getcwd getcwd - #define __chdir chdir -#endif - -#if defined _M_GENERIC -# define _M_SSE 0x0 -#elif defined __GNUC__ -# if defined __SSE4_2__ -# define _M_SSE 0x402 -# elif defined __SSE4_1__ -# define _M_SSE 0x401 -# elif defined __SSSE3__ -# define _M_SSE 0x301 -# elif defined __SSE3__ -# define _M_SSE 0x300 -# endif -#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008 -# define _M_SSE 0x402 -#endif - -// Host communication. -enum HOST_COMM -{ - // Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on - WM_USER_STOP = 10, - WM_USER_CREATE, - WM_USER_SETCURSOR, -}; - -// Used for notification on emulation state -enum EMUSTATE_CHANGE -{ - EMUSTATE_CHANGE_PLAY = 1, - EMUSTATE_CHANGE_PAUSE, - EMUSTATE_CHANGE_STOP -}; - -#include "swap.h" diff --git a/src/common/common_funcs.h b/src/common/common_funcs.h index e76cb7d68..91b74c6bc 100644 --- a/src/common/common_funcs.h +++ b/src/common/common_funcs.h @@ -7,13 +7,6 @@ #include "common_types.h" #include <cstdlib> -#ifdef _WIN32 -#define SLEEP(x) Sleep(x) -#else -#include <unistd.h> -#define SLEEP(x) usleep(x*1000) -#endif - #define b2(x) ( (x) | ( (x) >> 1) ) #define b4(x) ( b2(x) | ( b2(x) >> 2) ) @@ -34,6 +27,20 @@ #define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] #define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)] +#ifdef _WIN32 + // Alignment + #define MEMORY_ALIGNED16(x) __declspec(align(16)) x + #define MEMORY_ALIGNED32(x) __declspec(align(32)) x + #define MEMORY_ALIGNED64(x) __declspec(align(64)) x + #define MEMORY_ALIGNED128(x) __declspec(align(128)) x +#else + #define __forceinline inline __attribute__((always_inline)) + #define MEMORY_ALIGNED16(x) __attribute__((aligned(16))) x + #define MEMORY_ALIGNED32(x) __attribute__((aligned(32))) x + #define MEMORY_ALIGNED64(x) __attribute__((aligned(64))) x + #define MEMORY_ALIGNED128(x) __attribute__((aligned(128))) x +#endif + #ifndef _MSC_VER #include <errno.h> @@ -73,61 +80,11 @@ inline u64 _rotr64(u64 x, unsigned int shift){ } #else // _MSC_VER -#include <locale.h> - -// Function Cross-Compatibility - #define strcasecmp _stricmp - #define strncasecmp _strnicmp - #define unlink _unlink + // Function Cross-Compatibility #define snprintf _snprintf - #define vscprintf _vscprintf -// Locale Cross-Compatibility + // Locale Cross-Compatibility #define locale_t _locale_t - #define freelocale _free_locale - #define newlocale(mask, locale, base) _create_locale(mask, locale) - - #define LC_GLOBAL_LOCALE ((locale_t)-1) - #define LC_ALL_MASK LC_ALL - #define LC_COLLATE_MASK LC_COLLATE - #define LC_CTYPE_MASK LC_CTYPE - #define LC_MONETARY_MASK LC_MONETARY - #define LC_NUMERIC_MASK LC_NUMERIC - #define LC_TIME_MASK LC_TIME - - inline locale_t uselocale(locale_t new_locale) - { - // Retrieve the current per thread locale setting - bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE); - - // Retrieve the current thread-specific locale - locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE; - - if(new_locale == LC_GLOBAL_LOCALE) - { - // Restore the global locale - _configthreadlocale(_DISABLE_PER_THREAD_LOCALE); - } - else if(new_locale != nullptr) - { - // Configure the thread to set the locale only for this thread - _configthreadlocale(_ENABLE_PER_THREAD_LOCALE); - - // Set all locale categories - for(int i = LC_MIN; i <= LC_MAX; i++) - setlocale(i, new_locale->locinfo->lc_category[i].locale); - } - - return old_locale; - } - -// 64 bit offsets for windows - #define fseeko _fseeki64 - #define ftello _ftelli64 - #define atoll _atoi64 - #define stat64 _stat64 - #define fstat64 _fstat64 - #define fileno _fileno extern "C" { __declspec(dllimport) void __stdcall DebugBreak(void); diff --git a/src/common/common_paths.h b/src/common/common_paths.h index 440b06060..2903f2cf2 100644 --- a/src/common/common_paths.h +++ b/src/common/common_paths.h @@ -4,9 +4,6 @@ #pragma once -// Make sure we pick up USER_DIR if set in config.h -#include "common/common.h" - // Directory separators, do we need this? #define DIR_SEP "/" #define DIR_SEP_CHR '/' diff --git a/src/common/common_types.h b/src/common/common_types.h index 1b453e7f5..f6de0adfc 100644 --- a/src/common/common_types.h +++ b/src/common/common_types.h @@ -47,6 +47,11 @@ typedef std::int64_t s64; ///< 64-bit signed int typedef float f32; ///< 32-bit floating point typedef double f64; ///< 64-bit floating point +// TODO: It would be nice to eventually replace these with strong types that prevent accidental +// conversion between each other. +typedef u32 VAddr; ///< Represents a pointer in the userspace virtual address space. +typedef u32 PAddr; ///< Represents a pointer in the ARM11 physical address space. + /// Union for fast 16-bit type casting union t16 { u8 _u8[2]; ///< 8-bit unsigned char(s) @@ -73,28 +78,12 @@ union t64 { u8 _u8[8]; ///< 8-bit unsigned char(s) }; -namespace Common { -/// Rectangle data structure -class Rect { -public: - Rect(int x0=0, int y0=0, int x1=0, int y1=0) { - x0_ = x0; - y0_ = y0; - x1_ = x1; - y1_ = y1; - } - ~Rect() { } - - int x0_; ///< Rect top left X-coordinate - int y0_; ///< Rect top left Y-coordinate - int x1_; ///< Rect bottom left X-coordinate - int y1_; ///< Rect bottom right Y-coordinate - - inline u32 width() const { return std::abs(x1_ - x0_); } - inline u32 height() const { return std::abs(y1_ - y0_); } +// An inheritable class to disallow the copy constructor and operator= functions +class NonCopyable { +protected: + NonCopyable() = default; + ~NonCopyable() = default; - inline bool operator == (const Rect& val) const { - return (x0_ == val.x0_ && y0_ == val.y0_ && x1_ == val.x1_ && y1_ == val.y1_); - } + NonCopyable(NonCopyable&) = delete; + NonCopyable& operator=(NonCopyable&) = delete; }; -} diff --git a/src/common/concurrent_ring_buffer.h b/src/common/concurrent_ring_buffer.h index fc18e6c86..c5889513a 100644 --- a/src/common/concurrent_ring_buffer.h +++ b/src/common/concurrent_ring_buffer.h @@ -10,7 +10,7 @@ #include <mutex> #include <thread> -#include "common/common.h" // for NonCopyable +#include "common/common_types.h" // for NonCopyable namespace Common { diff --git a/src/common/emu_window.cpp b/src/common/emu_window.cpp index 6516fc633..f5b6c7301 100644 --- a/src/common/emu_window.cpp +++ b/src/common/emu_window.cpp @@ -28,6 +28,17 @@ static bool IsWithinTouchscreen(const EmuWindow::FramebufferLayout& layout, unsi framebuffer_x < layout.bottom_screen.right); } +std::tuple<unsigned,unsigned> EmuWindow::ClipToTouchScreen(unsigned new_x, unsigned new_y) { + + new_x = std::max(new_x, framebuffer_layout.bottom_screen.left); + new_x = std::min(new_x, framebuffer_layout.bottom_screen.right-1); + + new_y = std::max(new_y, framebuffer_layout.bottom_screen.top); + new_y = std::min(new_y, framebuffer_layout.bottom_screen.bottom-1); + + return std::make_tuple(new_x, new_y); +} + void EmuWindow::TouchPressed(unsigned framebuffer_x, unsigned framebuffer_y) { if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) return; @@ -52,14 +63,13 @@ void EmuWindow::TouchMoved(unsigned framebuffer_x, unsigned framebuffer_y) { if (!touch_pressed) return; - if (IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) - TouchPressed(framebuffer_x, framebuffer_y); - else - TouchReleased(); + if (!IsWithinTouchscreen(framebuffer_layout, framebuffer_x, framebuffer_y)) + std::tie(framebuffer_x, framebuffer_y) = ClipToTouchScreen(framebuffer_x, framebuffer_y); + + TouchPressed(framebuffer_x, framebuffer_y); } -EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, - unsigned height) { +EmuWindow::FramebufferLayout EmuWindow::FramebufferLayout::DefaultScreenLayout(unsigned width, unsigned height) { ASSERT(width > 0); ASSERT(height > 0); diff --git a/src/common/emu_window.h b/src/common/emu_window.h index c8e2de04a..8eca6b5d5 100644 --- a/src/common/emu_window.h +++ b/src/common/emu_window.h @@ -4,11 +4,11 @@ #pragma once -#include "common/common.h" -#include "common/scm_rev.h" -#include "common/string_util.h" +#include "common/common_types.h" #include "common/key_map.h" #include "common/math_util.h" +#include "common/scm_rev.h" +#include "common/string_util.h" /** * Abstraction class used to provide an interface between emulation code and the frontend @@ -206,5 +206,10 @@ private: u16 touch_x; ///< Touchpad X-position in native 3DS pixel coordinates (0-320) u16 touch_y; ///< Touchpad Y-position in native 3DS pixel coordinates (0-240) + /** + * Clip the provided coordinates to be inside the touchscreen area. + */ + std::tuple<unsigned,unsigned> ClipToTouchScreen(unsigned new_x, unsigned new_y); + Service::HID::PadState pad_state; }; diff --git a/src/common/file_util.cpp b/src/common/file_util.cpp index 4ef4918d7..7cdd1484f 100644 --- a/src/common/file_util.cpp +++ b/src/common/file_util.cpp @@ -2,42 +2,52 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. - -#include "common/common.h" +#include "common/assert.h" +#include "common/common_funcs.h" +#include "common/common_paths.h" #include "common/file_util.h" +#include "common/logging/log.h" #ifdef _WIN32 -#include <windows.h> -#include <shlobj.h> // for SHGetFolderPath -#include <shellapi.h> -#include <commdlg.h> // for GetSaveFileName -#include <io.h> -#include <direct.h> // getcwd -#include <tchar.h> + #include <windows.h> + #include <shlobj.h> // for SHGetFolderPath + #include <shellapi.h> + #include <commdlg.h> // for GetSaveFileName + #include <io.h> + #include <direct.h> // getcwd + #include <tchar.h> + + // 64 bit offsets for windows + #define fseeko _fseeki64 + #define ftello _ftelli64 + #define atoll _atoi64 + #define stat64 _stat64 + #define fstat64 _fstat64 + #define fileno _fileno #else -#include <sys/param.h> -#include <sys/types.h> -#include <dirent.h> -#include <pwd.h> -#include <unistd.h> + #include <sys/param.h> + #include <sys/types.h> + #include <dirent.h> + #include <pwd.h> + #include <unistd.h> #endif #if defined(__APPLE__) -#include <CoreFoundation/CFString.h> -#include <CoreFoundation/CFURL.h> -#include <CoreFoundation/CFBundle.h> + #include <CoreFoundation/CFString.h> + #include <CoreFoundation/CFURL.h> + #include <CoreFoundation/CFBundle.h> #endif #include <algorithm> #include <sys/stat.h> #ifndef S_ISDIR -#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) + #define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR) #endif #ifdef BSD4_4 -#define stat64 stat -#define fstat64 fstat + #define stat64 stat + #define fstat64 fstat #endif // This namespace has various generic functions related to files and paths. @@ -589,7 +599,7 @@ std::string GetCurrentDir() { char *dir; // Get the current working directory (getcwd uses malloc) - if (!(dir = __getcwd(nullptr, 0))) { + if (!(dir = getcwd(nullptr, 0))) { LOG_ERROR(Common_Filesystem, "GetCurrentDirectory failed: %s", GetLastErrorMsg()); @@ -603,7 +613,7 @@ std::string GetCurrentDir() // Sets the current directory to the given directory bool SetCurrentDir(const std::string &directory) { - return __chdir(directory.c_str()) == 0; + return chdir(directory.c_str()) == 0; } #if defined(__APPLE__) diff --git a/src/common/file_util.h b/src/common/file_util.h index 86aab2e3d..b65829291 100644 --- a/src/common/file_util.h +++ b/src/common/file_util.h @@ -11,7 +11,7 @@ #include <string> #include <vector> -#include "common/common.h" +#include "common/common_types.h" #include "common/string_util.h" // User directory indices for GetUserPath diff --git a/src/common/hash.cpp b/src/common/hash.cpp deleted file mode 100644 index 0624dab8d..000000000 --- a/src/common/hash.cpp +++ /dev/null @@ -1,521 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#include <algorithm> - -#include "common/hash.h" -#if _M_SSE >= 0x402 -#include "common/cpu_detect.h" -#include <nmmintrin.h> -#endif - -static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurHash3; - -// uint32_t -// WARNING - may read one more byte! -// Implementation from Wikipedia. -u32 HashFletcher(const u8* data_u8, size_t length) -{ - const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */ - size_t len = (length + 1) / 2; /* Length in 16-bit words */ - u32 sum1 = 0xffff, sum2 = 0xffff; - - while (len) - { - size_t tlen = len > 360 ? 360 : len; - len -= tlen; - - do { - sum1 += *data++; - sum2 += sum1; - } - while (--tlen); - - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - } - - // Second reduction step to reduce sums to 16 bits - sum1 = (sum1 & 0xffff) + (sum1 >> 16); - sum2 = (sum2 & 0xffff) + (sum2 >> 16); - return(sum2 << 16 | sum1); -} - - -// Implementation from Wikipedia -// Slightly slower than Fletcher above, but slightly more reliable. -#define MOD_ADLER 65521 -// data: Pointer to the data to be summed; len is in bytes -u32 HashAdler32(const u8* data, size_t len) -{ - u32 a = 1, b = 0; - - while (len) - { - size_t tlen = len > 5550 ? 5550 : len; - len -= tlen; - - do - { - a += *data++; - b += a; - } - while (--tlen); - - a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); - b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); - } - - // It can be shown that a <= 0x1013a here, so a single subtract will do. - if (a >= MOD_ADLER) - { - a -= MOD_ADLER; - } - - // It can be shown that b can reach 0xfff87 here. - b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); - - if (b >= MOD_ADLER) - { - b -= MOD_ADLER; - } - - return((b << 16) | a); -} - -// Stupid hash - but can't go back now :) -// Don't use for new things. At least it's reasonably fast. -u32 HashEctor(const u8* ptr, int length) -{ - u32 crc = 0; - - for (int i = 0; i < length; i++) - { - crc ^= ptr[i]; - crc = (crc << 3) | (crc >> 29); - } - - return(crc); -} - - -#ifdef _M_X64 - -//----------------------------------------------------------------------------- -// Block read - if your platform needs to do endian-swapping or can only -// handle aligned reads, do the conversion here - -inline u64 getblock(const u64 * p, int i) -{ - return p[i]; -} - -//---------- -// Block mix - combine the key bits with the hash bits and scramble everything - -inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) -{ - k1 *= c1; - k1 = _rotl64(k1,23); - k1 *= c2; - h1 ^= k1; - h1 += h2; - - h2 = _rotl64(h2,41); - - k2 *= c2; - k2 = _rotl64(k2,23); - k2 *= c1; - h2 ^= k2; - h2 += h1; - - h1 = h1*3+0x52dce729; - h2 = h2*3+0x38495ab5; - - c1 = c1*5+0x7b7d159c; - c2 = c2*5+0x6bce6396; -} - -//---------- -// Finalization mix - avalanches all bits to within 0.05% bias - -inline u64 fmix64(u64 k) -{ - k ^= k >> 33; - k *= 0xff51afd7ed558ccd; - k ^= k >> 33; - k *= 0xc4ceb9fe1a85ec53; - k ^= k >> 33; - - return k; -} - -u64 GetMurmurHash3(const u8 *src, int len, u32 samples) -{ - const u8 * data = (const u8*)src; - const int nblocks = len / 16; - u32 Step = (len / 8); - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - - u64 h1 = 0x9368e53c2f6af274; - u64 h2 = 0x586dcd208f7cd3fd; - - u64 c1 = 0x87c37b91114253d5; - u64 c2 = 0x4cf5ad432745937f; - - - //---------- - // body - - const u64 * blocks = (const u64 *)(data); - - for(int i = 0; i < nblocks; i+=Step) - { - u64 k1 = getblock(blocks,i*2+0); - u64 k2 = getblock(blocks,i*2+1); - - bmix64(h1,h2,k1,k2,c1,c2); - } - - //---------- - // tail - - const u8 * tail = (const u8*)(data + nblocks*16); - - u64 k1 = 0; - u64 k2 = 0; - - switch(len & 15) - { - case 15: k2 ^= u64(tail[14]) << 48; - case 14: k2 ^= u64(tail[13]) << 40; - case 13: k2 ^= u64(tail[12]) << 32; - case 12: k2 ^= u64(tail[11]) << 24; - case 11: k2 ^= u64(tail[10]) << 16; - case 10: k2 ^= u64(tail[ 9]) << 8; - case 9: k2 ^= u64(tail[ 8]) << 0; - - case 8: k1 ^= u64(tail[ 7]) << 56; - case 7: k1 ^= u64(tail[ 6]) << 48; - case 6: k1 ^= u64(tail[ 5]) << 40; - case 5: k1 ^= u64(tail[ 4]) << 32; - case 4: k1 ^= u64(tail[ 3]) << 24; - case 3: k1 ^= u64(tail[ 2]) << 16; - case 2: k1 ^= u64(tail[ 1]) << 8; - case 1: k1 ^= u64(tail[ 0]) << 0; - bmix64(h1,h2,k1,k2,c1,c2); - }; - - //---------- - // finalization - - h2 ^= len; - - h1 += h2; - h2 += h1; - - h1 = fmix64(h1); - h2 = fmix64(h2); - - h1 += h2; - - return h1; -} - - -// CRC32 hash using the SSE4.2 instruction -u64 GetCRC32(const u8 *src, int len, u32 samples) -{ -#if _M_SSE >= 0x402 - u64 h = len; - u32 Step = (len / 8); - const u64 *data = (const u64 *)src; - const u64 *end = data + Step; - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) - { - h = _mm_crc32_u64(h, data[0]); - data += Step; - } - - const u8 *data2 = (const u8*)end; - return _mm_crc32_u64(h, u64(data2[0])); -#else - return 0; -#endif -} - - -/* - * NOTE: This hash function is used for custom texture loading/dumping, so - * it should not be changed, which would require all custom textures to be - * recalculated for their new hash values. If the hashing function is - * changed, make sure this one is still used when the legacy parameter is - * true. - */ -u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) -{ - const u64 m = 0xc6a4a7935bd1e995; - u64 h = len * m; - const int r = 47; - u32 Step = (len / 8); - const u64 *data = (const u64 *)src; - const u64 *end = data + Step; - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) - { - u64 k = data[0]; - data+=Step; - k *= m; - k ^= k >> r; - k *= m; - h ^= k; - h *= m; - } - - const u8 * data2 = (const u8*)end; - - switch(len & 7) - { - case 7: h ^= u64(data2[6]) << 48; - case 6: h ^= u64(data2[5]) << 40; - case 5: h ^= u64(data2[4]) << 32; - case 4: h ^= u64(data2[3]) << 24; - case 3: h ^= u64(data2[2]) << 16; - case 2: h ^= u64(data2[1]) << 8; - case 1: h ^= u64(data2[0]); - h *= m; - }; - - h ^= h >> r; - h *= m; - h ^= h >> r; - - return h; -} -#else -// CRC32 hash using the SSE4.2 instruction -u64 GetCRC32(const u8 *src, int len, u32 samples) -{ -#if _M_SSE >= 0x402 - u32 h = len; - u32 Step = (len/4); - const u32 *data = (const u32 *)src; - const u32 *end = data + Step; - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) - { - h = _mm_crc32_u32(h, data[0]); - data += Step; - } - - const u8 *data2 = (const u8*)end; - return (u64)_mm_crc32_u32(h, u32(data2[0])); -#else - return 0; -#endif -} - -//----------------------------------------------------------------------------- -// Block read - if your platform needs to do endian-swapping or can only -// handle aligned reads, do the conversion here - -inline u32 getblock(const u32 * p, int i) -{ - return p[i]; -} - -//---------- -// Finalization mix - force all bits of a hash block to avalanche - -// avalanches all bits to within 0.25% bias - -inline u32 fmix32(u32 h) -{ - h ^= h >> 16; - h *= 0x85ebca6b; - h ^= h >> 13; - h *= 0xc2b2ae35; - h ^= h >> 16; - - return h; -} - -inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) -{ - k1 *= c1; - k1 = _rotl(k1,11); - k1 *= c2; - h1 ^= k1; - h1 += h2; - - h2 = _rotl(h2,17); - - k2 *= c2; - k2 = _rotl(k2,11); - k2 *= c1; - h2 ^= k2; - h2 += h1; - - h1 = h1*3+0x52dce729; - h2 = h2*3+0x38495ab5; - - c1 = c1*5+0x7b7d159c; - c2 = c2*5+0x6bce6396; -} - -//---------- - -u64 GetMurmurHash3(const u8* src, int len, u32 samples) -{ - const u8 * data = (const u8*)src; - u32 out[2]; - const int nblocks = len / 8; - u32 Step = (len / 4); - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - - u32 h1 = 0x8de1c3ac; - u32 h2 = 0xbab98226; - - u32 c1 = 0x95543787; - u32 c2 = 0x2ad7eb25; - - //---------- - // body - - const u32 * blocks = (const u32 *)(data + nblocks*8); - - for(int i = -nblocks; i < 0; i+=Step) - { - u32 k1 = getblock(blocks,i*2+0); - u32 k2 = getblock(blocks,i*2+1); - - bmix32(h1,h2,k1,k2,c1,c2); - } - - //---------- - // tail - - const u8 * tail = (const u8*)(data + nblocks*8); - - u32 k1 = 0; - u32 k2 = 0; - - switch(len & 7) - { - case 7: k2 ^= tail[6] << 16; - case 6: k2 ^= tail[5] << 8; - case 5: k2 ^= tail[4] << 0; - case 4: k1 ^= tail[3] << 24; - case 3: k1 ^= tail[2] << 16; - case 2: k1 ^= tail[1] << 8; - case 1: k1 ^= tail[0] << 0; - bmix32(h1,h2,k1,k2,c1,c2); - }; - - //---------- - // finalization - - h2 ^= len; - - h1 += h2; - h2 += h1; - - h1 = fmix32(h1); - h2 = fmix32(h2); - - h1 += h2; - h2 += h1; - - out[0] = h1; - out[1] = h2; - - return *((u64 *)&out); -} - -/* - * FIXME: The old 32-bit version of this hash made different hashes than the - * 64-bit version. Until someone can make a new version of the 32-bit one that - * makes identical hashes, this is just a c/p of the 64-bit one. - */ -u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) -{ - const u64 m = 0xc6a4a7935bd1e995ULL; - u64 h = len * m; - const int r = 47; - u32 Step = (len / 8); - const u64 *data = (const u64 *)src; - const u64 *end = data + Step; - if(samples == 0) samples = std::max(Step, 1u); - Step = Step / samples; - if(Step < 1) Step = 1; - while(data < end) - { - u64 k = data[0]; - data+=Step; - k *= m; - k ^= k >> r; - k *= m; - h ^= k; - h *= m; - } - - const u8 * data2 = (const u8*)end; - - switch(len & 7) - { - case 7: h ^= u64(data2[6]) << 48; - case 6: h ^= u64(data2[5]) << 40; - case 5: h ^= u64(data2[4]) << 32; - case 4: h ^= u64(data2[3]) << 24; - case 3: h ^= u64(data2[2]) << 16; - case 2: h ^= u64(data2[1]) << 8; - case 1: h ^= u64(data2[0]); - h *= m; - }; - - h ^= h >> r; - h *= m; - h ^= h >> r; - - return h; -} -#endif - -u64 GetHash64(const u8 *src, int len, u32 samples) -{ - return ptrHashFunction(src, len, samples); -} - -// sets the hash function used for the texture cache -void SetHash64Function(bool useHiresTextures) -{ - if (useHiresTextures) - { - ptrHashFunction = &GetHashHiresTexture; - } -#if _M_SSE >= 0x402 - else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version - { - ptrHashFunction = &GetCRC32; - } -#endif - else - { - ptrHashFunction = &GetMurmurHash3; - } -} - - - diff --git a/src/common/hash.h b/src/common/hash.h deleted file mode 100644 index 3ac42bc44..000000000 --- a/src/common/hash.h +++ /dev/null @@ -1,17 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - -#pragma once - -#include "common/common.h" - -u32 HashFletcher(const u8* data_u8, size_t length); // FAST. Length & 1 == 0. -u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower -u32 HashFNV(const u8* ptr, int length); // Another fast and decent hash -u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS -u64 GetCRC32(const u8 *src, int len, u32 samples); // SSE4.2 version of CRC32 -u64 GetHashHiresTexture(const u8 *src, int len, u32 samples); -u64 GetMurmurHash3(const u8 *src, int len, u32 samples); -u64 GetHash64(const u8 *src, int len, u32 samples); -void SetHash64Function(bool useHiresTextures); diff --git a/src/common/linear_disk_cache.h b/src/common/linear_disk_cache.h index 74ce74aba..48529cf42 100644 --- a/src/common/linear_disk_cache.h +++ b/src/common/linear_disk_cache.h @@ -4,7 +4,7 @@ #pragma once -#include "common/common.h" +#include "common/common_types.h" #include <fstream> // defined in Version.cpp diff --git a/src/common/logging/backend.cpp b/src/common/logging/backend.cpp index 649640e72..7d3534a43 100644 --- a/src/common/logging/backend.cpp +++ b/src/common/logging/backend.cpp @@ -39,6 +39,8 @@ static std::shared_ptr<Logger> global_logger; SUB(Service, AC) \ SUB(Service, PTM) \ SUB(Service, LDR) \ + SUB(Service, NIM) \ + SUB(Service, NWM) \ SUB(Service, CFG) \ SUB(Service, DSP) \ SUB(Service, HID) \ diff --git a/src/common/logging/log.h b/src/common/logging/log.h index 83d64145b..123641cb4 100644 --- a/src/common/logging/log.h +++ b/src/common/logging/log.h @@ -59,6 +59,8 @@ enum class Class : ClassType { Service_AC, ///< The AC (WiFi status) service Service_PTM, ///< The PTM (Power status & misc.) service Service_LDR, ///< The LDR (3ds dll loader) service + Service_NIM, ///< The NIM (Network interface manager) service + Service_NWM, ///< The NWM (Network manager) service Service_CFG, ///< The CFG (Configuration) service Service_DSP, ///< The DSP (DSP control) service Service_HID, ///< The HID (User input) service diff --git a/src/common/logging/text_formatter.cpp b/src/common/logging/text_formatter.cpp index 36c91c4f6..45be6d0a1 100644 --- a/src/common/logging/text_formatter.cpp +++ b/src/common/logging/text_formatter.cpp @@ -14,6 +14,7 @@ #include "common/logging/log.h" #include "common/logging/text_formatter.h" +#include "common/common_funcs.h" #include "common/string_util.h" namespace Log { diff --git a/src/common/math_util.cpp b/src/common/math_util.cpp deleted file mode 100644 index a83592dd2..000000000 --- a/src/common/math_util.cpp +++ /dev/null @@ -1,211 +0,0 @@ -// Copyright 2013 Dolphin Emulator Project / 2014 Citra Emulator Project -// Licensed under GPLv2 or any later version -// Refer to the license.txt file included. - - -#include "common/common.h" -#include "common/math_util.h" - -#include <numeric> // Necessary on OS X, but not Linux - -namespace MathUtil -{ - -u32 ClassifyDouble(double dvalue) -{ - // TODO: Optimize the below to be as fast as possible. - IntDouble value; - value.d = dvalue; - u64 sign = value.i & DOUBLE_SIGN; - u64 exp = value.i & DOUBLE_EXP; - if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP) - { - // Nice normalized number. - return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; - } - else - { - u64 mantissa = value.i & DOUBLE_FRAC; - if (mantissa) - { - if (exp) - { - return PPC_FPCLASS_QNAN; - } - else - { - // Denormalized number. - return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; - } - } - else if (exp) - { - //Infinite - return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; - } - else - { - //Zero - return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; - } - } -} - -u32 ClassifyFloat(float fvalue) -{ - // TODO: Optimize the below to be as fast as possible. - IntFloat value; - value.f = fvalue; - u32 sign = value.i & FLOAT_SIGN; - u32 exp = value.i & FLOAT_EXP; - if (exp > FLOAT_ZERO && exp < FLOAT_EXP) - { - // Nice normalized number. - return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; - } - else - { - u32 mantissa = value.i & FLOAT_FRAC; - if (mantissa) - { - if (exp) - { - return PPC_FPCLASS_QNAN; // Quiet NAN - } - else - { - // Denormalized number. - return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; - } - } - else if (exp) - { - // Infinite - return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; - } - else - { - //Zero - return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; - } - } -} - - -} // namespace - -inline void MatrixMul(int n, const float *a, const float *b, float *result) -{ - for (int i = 0; i < n; ++i) - { - for (int j = 0; j < n; ++j) - { - float temp = 0; - for (int k = 0; k < n; ++k) - { - temp += a[i * n + k] * b[k * n + j]; - } - result[i * n + j] = temp; - } - } -} - -// Calculate sum of a float list -float MathFloatVectorSum(const std::vector<float>& Vec) -{ - return std::accumulate(Vec.begin(), Vec.end(), 0.0f); -} - -void Matrix33::LoadIdentity(Matrix33 &mtx) -{ - memset(mtx.data, 0, sizeof(mtx.data)); - mtx.data[0] = 1.0f; - mtx.data[4] = 1.0f; - mtx.data[8] = 1.0f; -} - -void Matrix33::RotateX(Matrix33 &mtx, float rad) -{ - float s = sin(rad); - float c = cos(rad); - memset(mtx.data, 0, sizeof(mtx.data)); - mtx.data[0] = 1; - mtx.data[4] = c; - mtx.data[5] = -s; - mtx.data[7] = s; - mtx.data[8] = c; -} -void Matrix33::RotateY(Matrix33 &mtx, float rad) -{ - float s = sin(rad); - float c = cos(rad); - memset(mtx.data, 0, sizeof(mtx.data)); - mtx.data[0] = c; - mtx.data[2] = s; - mtx.data[4] = 1; - mtx.data[6] = -s; - mtx.data[8] = c; -} - -void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result) -{ - MatrixMul(3, a.data, b.data, result.data); -} - -void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3]) -{ - for (int i = 0; i < 3; ++i) { - result[i] = 0; - for (int k = 0; k < 3; ++k) { - result[i] += a.data[i * 3 + k] * vec[k]; - } - } -} - -void Matrix44::LoadIdentity(Matrix44 &mtx) -{ - memset(mtx.data, 0, sizeof(mtx.data)); - mtx.data[0] = 1.0f; - mtx.data[5] = 1.0f; - mtx.data[10] = 1.0f; - mtx.data[15] = 1.0f; -} - -void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33) -{ - for (int i = 0; i < 3; ++i) - { - for (int j = 0; j < 3; ++j) - { - mtx.data[i * 4 + j] = m33.data[i * 3 + j]; - } - } - - for (int i = 0; i < 3; ++i) - { - mtx.data[i * 4 + 3] = 0; - mtx.data[i + 12] = 0; - } - mtx.data[15] = 1.0f; -} - -void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16]) -{ - for(int i = 0; i < 16; ++i) { - mtx.data[i] = mtxArray[i]; - } -} - -void Matrix44::Translate(Matrix44 &mtx, const float vec[3]) -{ - LoadIdentity(mtx); - mtx.data[3] = vec[0]; - mtx.data[7] = vec[1]; - mtx.data[11] = vec[2]; -} - -void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result) -{ - MatrixMul(4, a.data, b.data, result.data); -} - diff --git a/src/common/math_util.h b/src/common/math_util.h index 43b0e0dc3..0b1400b41 100644 --- a/src/common/math_util.h +++ b/src/common/math_util.h @@ -4,11 +4,9 @@ #pragma once -#include "common/common.h" - #include <algorithm> +#include <cstdlib> #include <type_traits> -#include <vector> namespace MathUtil { @@ -19,83 +17,6 @@ inline T Clamp(const T val, const T& min, const T& max) return std::max(min, std::min(max, val)); } -static const u64 DOUBLE_SIGN = 0x8000000000000000ULL, - DOUBLE_EXP = 0x7FF0000000000000ULL, - DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL, - DOUBLE_ZERO = 0x0000000000000000ULL; - -static const u32 FLOAT_SIGN = 0x80000000, - FLOAT_EXP = 0x7F800000, - FLOAT_FRAC = 0x007FFFFF, - FLOAT_ZERO = 0x00000000; - -union IntDouble { - double d; - u64 i; -}; -union IntFloat { - float f; - u32 i; -}; - -inline bool IsNAN(double d) -{ - IntDouble x; x.d = d; - return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) ); -} - -inline bool IsQNAN(double d) -{ - IntDouble x; x.d = d; - return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) && - ((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) ); -} - -inline bool IsSNAN(double d) -{ - IntDouble x; x.d = d; - return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && - ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) && - ((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) ); -} - -inline float FlushToZero(float f) -{ - IntFloat x; x.f = f; - if ((x.i & FLOAT_EXP) == 0) - x.i &= FLOAT_SIGN; // turn into signed zero - return x.f; -} - -inline double FlushToZeroAsFloat(double d) -{ - IntDouble x; x.d = d; - if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) - x.i &= DOUBLE_SIGN; // turn into signed zero - return x.d; -} - -enum PPCFpClass -{ - PPC_FPCLASS_QNAN = 0x11, - PPC_FPCLASS_NINF = 0x9, - PPC_FPCLASS_NN = 0x8, - PPC_FPCLASS_ND = 0x18, - PPC_FPCLASS_NZ = 0x12, - PPC_FPCLASS_PZ = 0x2, - PPC_FPCLASS_PD = 0x14, - PPC_FPCLASS_PN = 0x4, - PPC_FPCLASS_PINF = 0x5, -}; - -// Uses PowerPC conventions for the return value, so it can be easily -// used directly in CPU emulation. -u32 ClassifyDouble(double dvalue); -// More efficient float version. -u32 ClassifyFloat(float fvalue); - template<class T> struct Rectangle { @@ -104,101 +25,12 @@ struct Rectangle T right; T bottom; - Rectangle() - { } + Rectangle() {} - Rectangle(T theLeft, T theTop, T theRight, T theBottom) - : left(theLeft), top(theTop), right(theRight), bottom(theBottom) - { } - - bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } + Rectangle(T left, T top, T right, T bottom) : left(left), top(top), right(right), bottom(bottom) {} T GetWidth() const { return std::abs(static_cast<typename std::make_signed<T>::type>(right - left)); } T GetHeight() const { return std::abs(static_cast<typename std::make_signed<T>::type>(bottom - top)); } - - // If the rectangle is in a coordinate system with a lower-left origin, use - // this Clamp. - void ClampLL(T x1, T y1, T x2, T y2) - { - if (left < x1) left = x1; - if (right > x2) right = x2; - if (top > y1) top = y1; - if (bottom < y2) bottom = y2; - } - - // If the rectangle is in a coordinate system with an upper-left origin, - // use this Clamp. - void ClampUL(T x1, T y1, T x2, T y2) - { - if (left < x1) left = x1; - if (right > x2) right = x2; - if (top < y1) top = y1; - if (bottom > y2) bottom = y2; - } }; } // namespace MathUtil - -inline float pow2f(float x) {return x * x;} -inline double pow2(double x) {return x * x;} - -float MathFloatVectorSum(const std::vector<float>&); - -#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) -#define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) - -// Rounds down. 0 -> undefined -inline u64 Log2(u64 val) -{ -#if defined(__GNUC__) - return 63 - __builtin_clzll(val); - -#elif defined(_MSC_VER) && defined(_M_X64) - unsigned long result = -1; - _BitScanReverse64(&result, val); - return result; - -#else - u64 result = -1; - while (val != 0) - { - val >>= 1; - ++result; - } - return result; -#endif -} - -// Tiny matrix/vector library. -// Used for things like Free-Look in the gfx backend. - -class Matrix33 -{ -public: - static void LoadIdentity(Matrix33 &mtx); - - // set mtx to be a rotation matrix around the x axis - static void RotateX(Matrix33 &mtx, float rad); - // set mtx to be a rotation matrix around the y axis - static void RotateY(Matrix33 &mtx, float rad); - - // set result = a x b - static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result); - static void Multiply(const Matrix33 &a, const float vec[3], float result[3]); - - float data[9]; -}; - -class Matrix44 -{ -public: - static void LoadIdentity(Matrix44 &mtx); - static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33); - static void Set(Matrix44 &mtx, const float mtxArray[16]); - - static void Translate(Matrix44 &mtx, const float vec[3]); - - static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result); - - float data[16]; -}; diff --git a/src/common/mem_arena.cpp b/src/common/mem_arena.cpp deleted file mode 100644 index 76c70701d..000000000 --- a/src/common/mem_arena.cpp +++ /dev/null @@ -1,389 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program 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 Foundation, version 2.0 or later versions. - -// This program 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 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#include <string> - -#include "common/memory_util.h" -#include "common/mem_arena.h" -#include "common/string_util.h" - -#ifndef _WIN32 -#include <fcntl.h> -#ifdef ANDROID -#include <sys/ioctl.h> -#include <linux/ashmem.h> -#endif -#endif - -#ifdef ANDROID - -// Hopefully this ABI will never change... - - -#define ASHMEM_DEVICE "/dev/ashmem" - -/* -* ashmem_create_region - creates a new ashmem region and returns the file -* descriptor, or <0 on error -* -* `name' is an optional label to give the region (visible in /proc/pid/maps) -* `size' is the size of the region, in page-aligned bytes -*/ -int ashmem_create_region(const char *name, size_t size) -{ - int fd, ret; - - fd = open(ASHMEM_DEVICE, O_RDWR); - if (fd < 0) - return fd; - - if (name) { - char buf[ASHMEM_NAME_LEN]; - - strncpy(buf, name, sizeof(buf)); - ret = ioctl(fd, ASHMEM_SET_NAME, buf); - if (ret < 0) - goto error; - } - - ret = ioctl(fd, ASHMEM_SET_SIZE, size); - if (ret < 0) - goto error; - - return fd; - -error: - LOG_ERROR(Common_Memory, "NASTY ASHMEM ERROR: ret = %08x", ret); - close(fd); - return ret; -} - -int ashmem_set_prot_region(int fd, int prot) -{ - return ioctl(fd, ASHMEM_SET_PROT_MASK, prot); -} - -int ashmem_pin_region(int fd, size_t offset, size_t len) -{ - struct ashmem_pin pin = { offset, len }; - return ioctl(fd, ASHMEM_PIN, &pin); -} - -int ashmem_unpin_region(int fd, size_t offset, size_t len) -{ - struct ashmem_pin pin = { offset, len }; - return ioctl(fd, ASHMEM_UNPIN, &pin); -} -#endif // Android - - -#if defined(_WIN32) -SYSTEM_INFO sysInfo; -#endif - - -// Windows mappings need to be on 64K boundaries, due to Alpha legacy. -#ifdef _WIN32 -size_t roundup(size_t x) { - int gran = sysInfo.dwAllocationGranularity ? sysInfo.dwAllocationGranularity : 0x10000; - return (x + gran - 1) & ~(gran - 1); -} -#else -size_t roundup(size_t x) { - return x; -} -#endif - - -void MemArena::GrabLowMemSpace(size_t size) -{ -#ifdef _WIN32 - hMemoryMapping = CreateFileMapping(INVALID_HANDLE_VALUE, nullptr, PAGE_READWRITE, 0, (DWORD)(size), nullptr); - GetSystemInfo(&sysInfo); -#elif defined(ANDROID) - // Use ashmem so we don't have to allocate a file on disk! - fd = ashmem_create_region("Citra_RAM", size); - // Note that it appears that ashmem is pinned by default, so no need to pin. - if (fd < 0) - { - LOG_ERROR(Common_Memory, "Failed to grab ashmem space of size: %08x errno: %d", (int)size, (int)(errno)); - return; - } -#else - // Try to find a non-existing filename for our shared memory. - // In most cases the first one will be available, but it's nicer to search - // a bit more. - for (int i = 0; i < 10000; i++) - { - std::string file_name = Common::StringFromFormat("/citramem.%d", i); - fd = shm_open(file_name.c_str(), O_RDWR | O_CREAT | O_EXCL, 0600); - if (fd != -1) - { - shm_unlink(file_name.c_str()); - break; - } - else if (errno != EEXIST) - { - LOG_ERROR(Common_Memory, "shm_open failed: %s", strerror(errno)); - return; - } - } - if (ftruncate(fd, size) < 0) - LOG_ERROR(Common_Memory, "Failed to allocate low memory space"); -#endif -} - - -void MemArena::ReleaseSpace() -{ -#ifdef _WIN32 - CloseHandle(hMemoryMapping); - hMemoryMapping = 0; -#else - close(fd); -#endif -} - - -void *MemArena::CreateView(s64 offset, size_t size, void *base) -{ -#ifdef _WIN32 - size = roundup(size); - void *ptr = MapViewOfFileEx(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size, base); - return ptr; -#else - void *retval = mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | - // Do not sync memory to underlying file. Linux has this by default. -#ifdef __FreeBSD__ - MAP_NOSYNC | -#endif - ((base == nullptr) ? 0 : MAP_FIXED), fd, offset); - - if (retval == MAP_FAILED) - { - LOG_ERROR(Common_Memory, "mmap failed"); - return nullptr; - } - return retval; -#endif -} - - -void MemArena::ReleaseView(void* view, size_t size) -{ -#ifdef _WIN32 - UnmapViewOfFile(view); -#else - munmap(view, size); -#endif -} - -u8* MemArena::Find4GBBase() -{ -#ifdef _M_X64 -#ifdef _WIN32 - // 64 bit - u8* base = (u8*)VirtualAlloc(0, 0xE1000000, MEM_RESERVE, PAGE_READWRITE); - VirtualFree(base, 0, MEM_RELEASE); - return base; -#else - // Very precarious - mmap cannot return an error when trying to map already used pages. - // This makes the Windows approach above unusable on Linux, so we will simply pray... - return reinterpret_cast<u8*>(0x2300000000ULL); -#endif - -#else // 32 bit - -#ifdef _WIN32 - u8* base = (u8*)VirtualAlloc(0, 0x10000000, MEM_RESERVE, PAGE_READWRITE); - if (base) { - VirtualFree(base, 0, MEM_RELEASE); - } - return base; -#else - void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE, - MAP_ANON | MAP_SHARED, -1, 0); - if (base == MAP_FAILED) { - LOG_ERROR(Common_Memory, "Failed to map 256 MB of memory space: %s", strerror(errno)); - return 0; - } - munmap(base, 0x10000000); - return static_cast<u8*>(base); -#endif -#endif -} - - -// yeah, this could also be done in like two bitwise ops... -#define SKIP(a_flags, b_flags) -//if (!(a_flags & MV_WII_ONLY) && (b_flags & MV_WII_ONLY)) -// continue; -//if (!(a_flags & MV_FAKE_VMEM) && (b_flags & MV_FAKE_VMEM)) -// continue; - -static bool Memory_TryBase(u8 *base, const MemoryView *views, int num_views, u32 flags, MemArena *arena) { - // OK, we know where to find free space. Now grab it! - // We just mimic the popular BAT setup. - size_t position = 0; - size_t last_position = 0; - - // Zero all the pointers to be sure. - for (int i = 0; i < num_views; i++) - { - if (views[i].out_ptr_low) - *views[i].out_ptr_low = 0; - if (views[i].out_ptr) - *views[i].out_ptr = 0; - } - - int i; - for (i = 0; i < num_views; i++) - { - const MemoryView &view = views[i]; - if (view.size == 0) - continue; - SKIP(flags, view.flags); - if (view.flags & MV_MIRROR_PREVIOUS) { - position = last_position; - } - else { - *(view.out_ptr_low) = (u8*)arena->CreateView(position, view.size); - if (!*view.out_ptr_low) - goto bail; - } -#ifdef _M_X64 - *view.out_ptr = (u8*)arena->CreateView( - position, view.size, base + view.virtual_address); -#else - if (view.flags & MV_MIRROR_PREVIOUS) { // TODO: should check if the two & 0x3FFFFFFF are identical. - // No need to create multiple identical views. - *view.out_ptr = *views[i - 1].out_ptr; - } - else { - *view.out_ptr = (u8*)arena->CreateView( - position, view.size, base + (view.virtual_address & 0x3FFFFFFF)); - if (!*view.out_ptr) - goto bail; - } -#endif - - last_position = position; - position += roundup(view.size); - } - - return true; - -bail: - // Argh! ERROR! Free what we grabbed so far so we can try again. - for (int j = 0; j <= i; j++) - { - if (views[i].size == 0) - continue; - SKIP(flags, views[i].flags); - if (views[j].out_ptr_low && *views[j].out_ptr_low) - { - arena->ReleaseView(*views[j].out_ptr_low, views[j].size); - *views[j].out_ptr_low = nullptr; - } - if (*views[j].out_ptr) - { -#ifdef _M_X64 - arena->ReleaseView(*views[j].out_ptr, views[j].size); -#else - if (!(views[j].flags & MV_MIRROR_PREVIOUS)) - { - arena->ReleaseView(*views[j].out_ptr, views[j].size); - } -#endif - *views[j].out_ptr = nullptr; - } - } - return false; -} - -u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena) -{ - size_t total_mem = 0; - int base_attempts = 0; - - for (int i = 0; i < num_views; i++) - { - if (views[i].size == 0) - continue; - SKIP(flags, views[i].flags); - if ((views[i].flags & MV_MIRROR_PREVIOUS) == 0) - total_mem += roundup(views[i].size); - } - // Grab some pagefile backed memory out of the void ... - arena->GrabLowMemSpace(total_mem); - - // Now, create views in high memory where there's plenty of space. -#ifdef _M_X64 - u8 *base = MemArena::Find4GBBase(); - // This really shouldn't fail - in 64-bit, there will always be enough - // address space. - if (!Memory_TryBase(base, views, num_views, flags, arena)) - { - LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); - return 0; - } -#elif defined(_WIN32) - // Try a whole range of possible bases. Return once we got a valid one. - u32 max_base_addr = 0x7FFF0000 - 0x10000000; - u8 *base = nullptr; - - for (u32 base_addr = 0x01000000; base_addr < max_base_addr; base_addr += 0x400000) - { - base_attempts++; - base = (u8 *)base_addr; - if (Memory_TryBase(base, views, num_views, flags, arena)) - { - LOG_DEBUG(Common_Memory, "Found valid memory base at %p after %i tries.", base, base_attempts); - base_attempts = 0; - break; - } - } -#else - // Linux32 is fine with the x64 method, although limited to 32-bit with no automirrors. - u8 *base = MemArena::Find4GBBase(); - if (!Memory_TryBase(base, views, num_views, flags, arena)) - { - LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); - return 0; - } -#endif - if (base_attempts) - LOG_ERROR(Common_Memory, "No possible memory base pointer found!"); - return base; -} - -void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena) -{ - for (int i = 0; i < num_views; i++) - { - if (views[i].size == 0) - continue; - SKIP(flags, views[i].flags); - if (views[i].out_ptr_low && *views[i].out_ptr_low) - arena->ReleaseView(*views[i].out_ptr_low, views[i].size); - if (*views[i].out_ptr && (views[i].out_ptr_low && *views[i].out_ptr != *views[i].out_ptr_low)) - arena->ReleaseView(*views[i].out_ptr, views[i].size); - *views[i].out_ptr = nullptr; - if (views[i].out_ptr_low) - *views[i].out_ptr_low = nullptr; - } -} diff --git a/src/common/mem_arena.h b/src/common/mem_arena.h deleted file mode 100644 index 3379d2529..000000000 --- a/src/common/mem_arena.h +++ /dev/null @@ -1,70 +0,0 @@ -// Copyright (C) 2003 Dolphin Project. - -// This program 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 Foundation, version 2.0 or later versions. - -// This program 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 2.0 for more details. - -// A copy of the GPL 2.0 should have been included with the program. -// If not, see http://www.gnu.org/licenses/ - -// Official SVN repository and contact information can be found at -// http://code.google.com/p/dolphin-emu/ - -#pragma once - -#ifdef _WIN32 -#include <windows.h> -#endif - -#include "common/common.h" - -// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it. -// Multiple views can mirror the same section of the block, which makes it very convient for emulating -// memory mirrors. - -class MemArena -{ -public: - void GrabLowMemSpace(size_t size); - void ReleaseSpace(); - void *CreateView(s64 offset, size_t size, void *base = 0); - void ReleaseView(void *view, size_t size); - - // This only finds 1 GB in 32-bit - static u8 *Find4GBBase(); -private: - -#ifdef _WIN32 - HANDLE hMemoryMapping; -#else - int fd; -#endif -}; - -enum { - MV_MIRROR_PREVIOUS = 1, - // MV_FAKE_VMEM = 2, - // MV_WII_ONLY = 4, - MV_IS_PRIMARY_RAM = 0x100, - MV_IS_EXTRA1_RAM = 0x200, - MV_IS_EXTRA2_RAM = 0x400, -}; - -struct MemoryView -{ - u8 **out_ptr_low; - u8 **out_ptr; - u32 virtual_address; - u32 size; - u32 flags; -}; - -// Uses a memory arena to set up an emulator-friendly memory map according to -// a passed-in list of MemoryView structures. -u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena *arena); -void MemoryMap_Shutdown(const MemoryView *views, int num_views, u32 flags, MemArena *arena); diff --git a/src/common/memory_util.cpp b/src/common/memory_util.cpp index 7e69d31cb..20b791a10 100644 --- a/src/common/memory_util.cpp +++ b/src/common/memory_util.cpp @@ -3,7 +3,8 @@ // Refer to the license.txt file included. -#include "common/common.h" +#include "common/common_funcs.h" +#include "common/logging/log.h" #include "common/memory_util.h" #include "common/string_util.h" @@ -70,7 +71,7 @@ void* AllocateExecutableMemory(size_t size, bool low) } #endif -#if defined(_M_X64) +#if EMU_ARCH_BITS == 64 if ((u64)ptr >= 0x80000000 && low == true) LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!"); #endif diff --git a/src/common/misc.cpp b/src/common/misc.cpp index e33055d10..53cacf37c 100644 --- a/src/common/misc.cpp +++ b/src/common/misc.cpp @@ -2,10 +2,12 @@ // Licensed under GPLv2 or any later version // Refer to the license.txt file included. -#include "common/common.h" +#include "common/common_funcs.h" #ifdef _WIN32 #include <windows.h> +#else +#include <string.h> #endif // Neither Android nor OS X support TLS diff --git a/src/common/platform.h b/src/common/platform.h index e27d6e31f..df780ac6f 100644 --- a/src/common/platform.h +++ b/src/common/platform.h @@ -57,54 +57,33 @@ #endif -#if defined(__x86_64__) || defined(_M_X64) || defined(__alpha__) || defined(__ia64__) -#define EMU_ARCHITECTURE_X64 -#else -#define EMU_ARCHITECTURE_X86 +#if defined(__x86_64__) || defined(_M_X64) || defined(__aarch64__) + #define EMU_ARCH_BITS 64 +#elif defined(__i386) || defined(_M_IX86) || defined(__arm__) || defined(_M_ARM) + #define EMU_ARCH_BITS 32 #endif //////////////////////////////////////////////////////////////////////////////////////////////////// -// Compiler-Specific Definitions - -#if EMU_PLATFORM == PLATFORM_WINDOWS - -#include <time.h> - -#ifndef NOMINMAX -#define NOMINMAX +// Feature detection + +#if defined _M_GENERIC +# define _M_SSE 0x0 +#elif defined __GNUC__ +# if defined __SSE4_2__ +# define _M_SSE 0x402 +# elif defined __SSE4_1__ +# define _M_SSE 0x401 +# elif defined __SSSE3__ +# define _M_SSE 0x301 +# elif defined __SSE3__ +# define _M_SSE 0x300 +# endif +#elif (_MSC_VER >= 1500) || __INTEL_COMPILER // Visual Studio 2008 +# define _M_SSE 0x402 #endif -#define EMU_FASTCALL __fastcall - -#ifdef _MSC_VER -inline struct tm* localtime_r(const time_t *clock, struct tm *result) { - if (localtime_s(result, clock) == 0) - return result; - return nullptr; -} -#endif - -#else // EMU_PLATFORM != PLATFORM_WINDOWS - -#define EMU_FASTCALL __attribute__((fastcall)) -#define __stdcall -#define __cdecl -#define BOOL bool -#define DWORD u32 - -// TODO: Hacks.. -#include <limits.h> - -#include <strings.h> -#define stricmp(str1, str2) strcasecmp(str1, str2) -#define _stricmp(str1, str2) strcasecmp(str1, str2) -#define _snprintf snprintf -#define _getcwd getcwd -#define _tzset tzset - -typedef void EXCEPTION_POINTERS; - -#endif +//////////////////////////////////////////////////////////////////////////////////////////////////// +// Compiler-Specific Definitions #define GCC_VERSION_AVAILABLE(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || \ (__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))) diff --git a/src/common/profiler.cpp b/src/common/profiler.cpp index 65c3df167..cf6b6b258 100644 --- a/src/common/profiler.cpp +++ b/src/common/profiler.cpp @@ -7,7 +7,6 @@ #include "common/assert.h" #if defined(_MSC_VER) && _MSC_VER <= 1800 // MSVC 2013. -#define NOMINMAX #define WIN32_LEAN_AND_MEAN #include <Windows.h> // For QueryPerformanceCounter/Frequency #endif @@ -127,10 +126,9 @@ void TimingResultsAggregator::AddFrame(const ProfilingFrameResult& frame_result) static AggregatedDuration AggregateField(const std::vector<Duration>& v, size_t len) { AggregatedDuration result; result.avg = Duration::zero(); - result.min = result.max = (len == 0 ? Duration::zero() : v[0]); - for (size_t i = 1; i < len; ++i) { + for (size_t i = 0; i < len; ++i) { Duration value = v[i]; result.avg += value; result.min = std::min(result.min, value); diff --git a/src/common/string_util.cpp b/src/common/string_util.cpp index 3264dd51a..7dc0ba7ba 100644 --- a/src/common/string_util.cpp +++ b/src/common/string_util.cpp @@ -4,7 +4,9 @@ #include <boost/range/algorithm.hpp> -#include "common/common.h" +#include "common/common_funcs.h" +#include "common/common_paths.h" +#include "common/logging/log.h" #include "common/string_util.h" #ifdef _MSC_VER @@ -285,131 +287,6 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st return result; } -// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759 -// by jinq0123 (November 2, 2006) - -// Uri encode and decode. -// RFC1630, RFC1738, RFC2396 - -//#include <string> -//#include <assert.h> - -const char HEX2DEC[256] = -{ - /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16, - - /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, - /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, - /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - - /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - - /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, - /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16 -}; - -std::string UriDecode(const std::string & sSrc) -{ - // Note from RFC1630: "Sequences which start with a percent sign - // but are not followed by two hexadecimal characters (0-9, A-F) are reserved - // for future extension" - - const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); - const size_t SRC_LEN = sSrc.length(); - const unsigned char * const SRC_END = pSrc + SRC_LEN; - const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' - - char * const pStart = new char[SRC_LEN]; - char * pEnd = pStart; - - while (pSrc < SRC_LAST_DEC) - { - if (*pSrc == '%') - { - char dec1, dec2; - if (16 != (dec1 = HEX2DEC[*(pSrc + 1)]) - && 16 != (dec2 = HEX2DEC[*(pSrc + 2)])) - { - *pEnd++ = (dec1 << 4) + dec2; - pSrc += 3; - continue; - } - } - - *pEnd++ = *pSrc++; - } - - // the last 2- chars - while (pSrc < SRC_END) - *pEnd++ = *pSrc++; - - std::string sResult(pStart, pEnd); - delete [] pStart; - return sResult; -} - -// Only alphanum is safe. -const char SAFE[256] = -{ - /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ - /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, - - /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, - /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, - /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, - /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, - - /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - - /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, - /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 -}; - -std::string UriEncode(const std::string & sSrc) -{ - const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; - const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); - const size_t SRC_LEN = sSrc.length(); - unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; - unsigned char * pEnd = pStart; - const unsigned char * const SRC_END = pSrc + SRC_LEN; - - for (; pSrc < SRC_END; ++pSrc) - { - if (SAFE[*pSrc]) - *pEnd++ = *pSrc; - else - { - // escape this char - *pEnd++ = '%'; - *pEnd++ = DEC2HEX[*pSrc >> 4]; - *pEnd++ = DEC2HEX[*pSrc & 0x0F]; - } - } - - std::string sResult((char *)pStart, (char *)pEnd); - delete [] pStart; - return sResult; -} - #ifdef _MSC_VER std::string UTF16ToUTF8(const std::u16string& input) @@ -600,4 +477,12 @@ std::string SHIFTJISToUTF8(const std::string& input) #endif +std::string StringFromFixedZeroTerminatedBuffer(const char * buffer, size_t max_len) { + size_t len = 0; + while (len < max_len && buffer[len] != '\0') + ++len; + + return std::string(buffer, len); +} + } diff --git a/src/common/string_util.h b/src/common/string_util.h index 74974263f..fdc410499 100644 --- a/src/common/string_util.h +++ b/src/common/string_util.h @@ -10,7 +10,7 @@ #include <sstream> #include <vector> -#include "common/common.h" +#include "common/common_types.h" namespace Common { @@ -86,8 +86,6 @@ bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _ void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename); std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest); -std::string UriDecode(const std::string & sSrc); -std::string UriEncode(const std::string & sSrc); std::string UTF16ToUTF8(const std::u16string& input); std::u16string UTF8ToUTF16(const std::string& input); @@ -130,4 +128,10 @@ bool ComparePartialString(InIt begin, InIt end, const char* other) { return (begin == end) == (*other == '\0'); } +/** + * Creates a std::string from a fixed-size NUL-terminated char buffer. If the buffer isn't + * NUL-terminated then the string ends at max_len characters. + */ +std::string StringFromFixedZeroTerminatedBuffer(const char* buffer, size_t max_len); + } diff --git a/src/common/symbols.h b/src/common/symbols.h index f76cb6b1e..6b62b011e 100644 --- a/src/common/symbols.h +++ b/src/common/symbols.h @@ -5,8 +5,10 @@ #pragma once #include <map> +#include <string> +#include <utility> -#include "common/common.h" +#include "common/common_types.h" struct TSymbol { diff --git a/src/common/thread.h b/src/common/thread.h index a45728e1e..7bc419497 100644 --- a/src/common/thread.h +++ b/src/common/thread.h @@ -4,7 +4,6 @@ #pragma once -// Don't include common.h here as it will break LogManager #include "common/common_types.h" #include <cstdio> #include <cstring> @@ -51,109 +50,60 @@ int CurrentThreadId(); void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask); void SetCurrentThreadAffinity(u32 mask); -class Event -{ +class Event { public: - Event() - : is_set(false) - {} + Event() : is_set(false) {} - void Set() - { + void Set() { std::lock_guard<std::mutex> lk(m_mutex); - if (!is_set) - { + if (!is_set) { is_set = true; m_condvar.notify_one(); } } - void Wait() - { + void Wait() { std::unique_lock<std::mutex> lk(m_mutex); - m_condvar.wait(lk, IsSet(this)); + m_condvar.wait(lk, [&]{ return is_set; }); is_set = false; } - void Reset() - { + void Reset() { std::unique_lock<std::mutex> lk(m_mutex); // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration is_set = false; } private: - class IsSet - { - public: - IsSet(const Event* ev) - : m_event(ev) - {} - - bool operator()() - { - return m_event->is_set; - } - - private: - const Event* const m_event; - }; - - volatile bool is_set; + bool is_set; std::condition_variable m_condvar; std::mutex m_mutex; }; -// TODO: doesn't work on windows with (count > 2) -class Barrier -{ +class Barrier { public: - Barrier(size_t count) - : m_count(count), m_waiting(0) - {} + Barrier(size_t count) : m_count(count), m_waiting(0) {} - // block until "count" threads call Sync() - bool Sync() - { + /// Blocks until all "count" threads have called Sync() + void Sync() { std::unique_lock<std::mutex> lk(m_mutex); // TODO: broken when next round of Sync()s // is entered before all waiting threads return from the notify_all - if (m_count == ++m_waiting) - { + if (++m_waiting == m_count) { m_waiting = 0; m_condvar.notify_all(); - return true; - } - else - { - m_condvar.wait(lk, IsDoneWating(this)); - return false; + } else { + m_condvar.wait(lk, [&]{ return m_waiting == 0; }); } } private: - class IsDoneWating - { - public: - IsDoneWating(const Barrier* bar) - : m_bar(bar) - {} - - bool operator()() - { - return (0 == m_bar->m_waiting); - } - - private: - const Barrier* const m_bar; - }; - std::condition_variable m_condvar; std::mutex m_mutex; const size_t m_count; - volatile size_t m_waiting; + size_t m_waiting; }; void SleepCurrentThread(int ms); diff --git a/src/common/thread_queue_list.h b/src/common/thread_queue_list.h index 444abf115..12455d7c4 100644 --- a/src/common/thread_queue_list.h +++ b/src/common/thread_queue_list.h @@ -9,8 +9,6 @@ #include <boost/range/algorithm_ext/erase.hpp> -#include "common/common.h" - namespace Common { template<class T, unsigned int N> @@ -40,6 +38,18 @@ struct ThreadQueueList { return -1; } + T get_first() { + Queue *cur = first; + while (cur != nullptr) { + if (!cur->data.empty()) { + return cur->data.front(); + } + cur = cur->next_nonempty; + } + + return T(); + } + T pop_first() { Queue *cur = first; while (cur != nullptr) { @@ -79,6 +89,12 @@ struct ThreadQueueList { cur->data.push_back(thread_id); } + void move(const T& thread_id, Priority old_priority, Priority new_priority) { + remove(old_priority, thread_id); + prepare(new_priority); + push_back(new_priority, thread_id); + } + void remove(Priority priority, const T& thread_id) { Queue *cur = &queues[priority]; boost::remove_erase(cur->data, thread_id); diff --git a/src/common/thunk.h b/src/common/thunk.h index 4fb7c98e1..533480056 100644 --- a/src/common/thunk.h +++ b/src/common/thunk.h @@ -6,7 +6,7 @@ #include <map> -#include "common/common.h" +#include "common/common_types.h" // This simple class creates a wrapper around a C/C++ function that saves all fp state // before entering it, and restores it upon exit. This is required to be able to selectively diff --git a/src/common/timer.cpp b/src/common/timer.cpp index a6682ea19..b99835ac7 100644 --- a/src/common/timer.cpp +++ b/src/common/timer.cpp @@ -12,9 +12,9 @@ #include <sys/time.h> #endif -#include "common/common.h" -#include "common/timer.h" +#include "common/common_types.h" #include "common/string_util.h" +#include "common/timer.h" namespace Common { diff --git a/src/common/timer.h b/src/common/timer.h index 4b44c33a0..b5f0f2585 100644 --- a/src/common/timer.h +++ b/src/common/timer.h @@ -4,7 +4,7 @@ #pragma once -#include "common/common.h" +#include "common/common_types.h" #include <string> namespace Common |