mirror of
				https://github.com/PabloMK7/citra.git
				synced 2025-10-31 05:40:04 +00:00 
			
		
		
		
	Merge pull request #588 from archshift/somebranch
Sweeping cleanup of Common
This commit is contained in:
		
						commit
						5f9939070e
					
				
					 19 changed files with 47 additions and 1422 deletions
				
			
		|  | @ -4,8 +4,6 @@ configure_file("${CMAKE_CURRENT_SOURCE_DIR}/scm_rev.cpp.in" "${CMAKE_CURRENT_SOU | |||
| set(SRCS | ||||
|             break_points.cpp | ||||
|             emu_window.cpp | ||||
|             extended_trace.cpp | ||||
|             file_search.cpp | ||||
|             file_util.cpp | ||||
|             hash.cpp | ||||
|             key_map.cpp | ||||
|  | @ -16,13 +14,11 @@ set(SRCS | |||
|             mem_arena.cpp | ||||
|             memory_util.cpp | ||||
|             misc.cpp | ||||
|             msg_handler.cpp | ||||
|             scm_rev.cpp | ||||
|             string_util.cpp | ||||
|             symbols.cpp | ||||
|             thread.cpp | ||||
|             timer.cpp | ||||
|             utf8.cpp | ||||
|             ) | ||||
| 
 | ||||
| set(HEADERS | ||||
|  | @ -38,9 +34,7 @@ set(HEADERS | |||
|             cpu_detect.h | ||||
|             debug_interface.h | ||||
|             emu_window.h | ||||
|             extended_trace.h | ||||
|             fifo_queue.h | ||||
|             file_search.h | ||||
|             file_util.h | ||||
|             hash.h | ||||
|             key_map.h | ||||
|  | @ -53,7 +47,6 @@ set(HEADERS | |||
|             math_util.h | ||||
|             mem_arena.h | ||||
|             memory_util.h | ||||
|             msg_handler.h | ||||
|             platform.h | ||||
|             scm_rev.h | ||||
|             scope_exit.h | ||||
|  | @ -64,7 +57,6 @@ set(HEADERS | |||
|             thread_queue_list.h | ||||
|             thunk.h | ||||
|             timer.h | ||||
|             utf8.h | ||||
|             ) | ||||
| 
 | ||||
| create_directory_groups(${SRCS} ${HEADERS}) | ||||
|  |  | |||
|  | @ -637,7 +637,7 @@ public: | |||
|         Do(cookie); | ||||
|         if(mode == PointerWrap::MODE_READ && cookie != arbitraryNumber) | ||||
|         { | ||||
|             PanicAlertT("Error: After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); | ||||
|             LOG_ERROR(Common, "After \"%s\", found %d (0x%X) instead of save marker %d (0x%X). Aborting savestate load...", prevName, cookie, cookie, arbitraryNumber, arbitraryNumber); | ||||
|             SetError(ERROR_FAILURE); | ||||
|         } | ||||
|     } | ||||
|  |  | |||
|  | @ -28,7 +28,6 @@ private: | |||
| #include "common/assert.h" | ||||
| #include "common/logging/log.h" | ||||
| #include "common/common_types.h" | ||||
| #include "common/msg_handler.h" | ||||
| #include "common/common_funcs.h" | ||||
| #include "common/common_paths.h" | ||||
| #include "common/platform.h" | ||||
|  | @ -40,9 +39,7 @@ private: | |||
|         #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 | ||||
|  | @ -52,9 +49,6 @@ private: | |||
|     #define NOMINMAX | ||||
|     #endif | ||||
| 
 | ||||
| // Memory leak checks
 | ||||
|     #define CHECK_HEAP_INTEGRITY() | ||||
| 
 | ||||
| // Alignment
 | ||||
|     #define MEMORY_ALIGNED16(x) __declspec(align(16)) x | ||||
|     #define MEMORY_ALIGNED32(x) __declspec(align(32)) x | ||||
|  | @ -62,25 +56,6 @@ private: | |||
|     #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 | ||||
| 
 | ||||
| // Since they are always around on windows
 | ||||
|     #define HAVE_WX 1 | ||||
|     #define HAVE_OPENAL 1 | ||||
| 
 | ||||
|     #define HAVE_PORTAUDIO 1 | ||||
| 
 | ||||
| // Debug definitions
 | ||||
|     #if defined(_DEBUG) | ||||
|         #include <crtdbg.h> | ||||
|         #undef CHECK_HEAP_INTEGRITY | ||||
|         #define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");} | ||||
|         // If you want to see how much a pain in the ass singletons are, for example:
 | ||||
|         // {614} normal block at 0x030C5310, 188 bytes long.
 | ||||
|         // Data: <Master Log      > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
 | ||||
|         struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } }; | ||||
|         //CrtDebugBreak breakAt(614);
 | ||||
|     #endif // end DEBUG/FAST
 | ||||
| 
 | ||||
| #endif | ||||
| 
 | ||||
| // Windows compatibility
 | ||||
|  | @ -109,10 +84,6 @@ private: | |||
|     #define __chdir chdir | ||||
| #endif | ||||
| 
 | ||||
| // Dummy macro for marking translatable strings that can not be immediately translated.
 | ||||
| // wxWidgets does not have a true dummy macro for this.
 | ||||
| #define _trans(a) a | ||||
| 
 | ||||
| #if defined _M_GENERIC | ||||
| #  define _M_SSE 0x0 | ||||
| #elif defined __GNUC__ | ||||
|  |  | |||
|  | @ -24,11 +24,6 @@ template<> struct CompileTimeAssert<true> {}; | |||
| #define b32(x)  (b16(x) | (b16(x) >>16) ) | ||||
| #define ROUND_UP_POW2(x)    (b32(x - 1) + 1) | ||||
| 
 | ||||
| #define MIN(a, b)   ((a)<(b)?(a):(b)) | ||||
| #define MAX(a, b)   ((a)>(b)?(a):(b)) | ||||
| 
 | ||||
| #define CLAMP(x, min, max)  (((x) > max) ? max : (((x) < min) ? min : (x))) | ||||
| 
 | ||||
| #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) | ||||
| 
 | ||||
| /// Textually concatenates two tokens. The double-expansion is required by the C preprocessor.
 | ||||
|  | @ -38,9 +33,8 @@ template<> struct CompileTimeAssert<true> {}; | |||
| // helper macro to properly align structure members.
 | ||||
| // Calling INSERT_PADDING_BYTES will add a new member variable with a name like "pad121",
 | ||||
| // depending on the current source line to make sure variable names are unique.
 | ||||
| #define INSERT_PADDING_BYTES_HELPER1(x, y) x ## y | ||||
| #define INSERT_PADDING_BYTES_HELPER2(x, y) INSERT_PADDING_BYTES_HELPER1(x, y) | ||||
| #define INSERT_PADDING_BYTES(num_words) u8 INSERT_PADDING_BYTES_HELPER2(pad, __LINE__)[(num_words)] | ||||
| #define INSERT_PADDING_BYTES(num_bytes) u8 CONCAT2(pad, __LINE__)[(num_bytes)] | ||||
| #define INSERT_PADDING_WORDS(num_words) u32 CONCAT2(pad, __LINE__)[(num_words)] | ||||
| 
 | ||||
| #ifndef _MSC_VER | ||||
| 
 | ||||
|  | @ -148,15 +142,6 @@ inline u64 _rotr64(u64 x, unsigned int shift){ | |||
|     #define Crash() {DebugBreak();} | ||||
| #endif // _MSC_VER ndef
 | ||||
| 
 | ||||
| // Dolphin's min and max functions
 | ||||
| #undef min | ||||
| #undef max | ||||
| 
 | ||||
| template<class T> | ||||
| inline T min(const T& a, const T& b) {return a > b ? b : a;} | ||||
| template<class T> | ||||
| inline T max(const T& a, const T& b) {return a > b ? a : b;} | ||||
| 
 | ||||
| // Generic function to get last error message.
 | ||||
| // Call directly after the command or use the error num.
 | ||||
| // This function might change the error code.
 | ||||
|  | @ -233,13 +218,4 @@ inline void swap<8>(u8* data) | |||
|     *reinterpret_cast<u64*>(data) = swap64(data); | ||||
| } | ||||
| 
 | ||||
| template <typename T> | ||||
| inline T FromBigEndian(T data) | ||||
| { | ||||
|     //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
 | ||||
| 
 | ||||
|     swap<sizeof(data)>(reinterpret_cast<u8*>(&data)); | ||||
|     return data; | ||||
| } | ||||
| 
 | ||||
| }  // Namespace Common
 | ||||
|  |  | |||
|  | @ -1,428 +0,0 @@ | |||
| // --------------------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
 | ||||
| // For companies(Austin,TX): If you would like to get my resume, send an email.
 | ||||
| //
 | ||||
| // The source is free, but if you want to use it, mention my name and e-mail address
 | ||||
| //
 | ||||
| // History:
 | ||||
| //    1.0      Initial version                  Zoltan Csizmadia
 | ||||
| //    1.1      WhineCube version                Masken
 | ||||
| //    1.2      Dolphin version                  Masken
 | ||||
| //
 | ||||
| // --------------------------------------------------------------------------------------
 | ||||
| 
 | ||||
| #if defined(WIN32) | ||||
| #include <cstdio> | ||||
| #include <windows.h> | ||||
| #include "common/extended_trace.h" | ||||
| #include "common/string_util.h" | ||||
| using namespace std; | ||||
| 
 | ||||
| #include <tchar.h> | ||||
| #include <ImageHlp.h> | ||||
| 
 | ||||
| #define BUFFERSIZE   0x200 | ||||
| #pragma warning(disable:4996) | ||||
| 
 | ||||
| // Unicode safe char* -> TCHAR* conversion
 | ||||
| void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) | ||||
| { | ||||
| #if defined(UNICODE)||defined(_UNICODE) | ||||
|     ULONG index = 0; | ||||
|     PCSTR lpAct = lpszIn; | ||||
| 
 | ||||
|     for( ; ; lpAct++ ) | ||||
|     { | ||||
|         lpszOut[index++] = (TCHAR)(*lpAct); | ||||
|         if ( *lpAct == 0 ) | ||||
|             break; | ||||
|     } | ||||
| #else | ||||
|     // This is trivial :)
 | ||||
|     strcpy( lpszOut, lpszIn ); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| // Let's figure out the path for the symbol files
 | ||||
| // Search path= ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;" + lpszIniPath
 | ||||
| // Note: There is no size check for lpszSymbolPath!
 | ||||
| static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath ) | ||||
| { | ||||
|     CHAR lpszPath[BUFFERSIZE]; | ||||
| 
 | ||||
|     // Creating the default path
 | ||||
|     // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
 | ||||
|     strcpy( lpszSymbolPath, "." ); | ||||
| 
 | ||||
|     // environment variable _NT_SYMBOL_PATH
 | ||||
|     if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) | ||||
|     { | ||||
|         strcat( lpszSymbolPath, ";" ); | ||||
|         strcat( lpszSymbolPath, lpszPath ); | ||||
|     } | ||||
| 
 | ||||
|     // environment variable _NT_ALTERNATE_SYMBOL_PATH
 | ||||
|     if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) | ||||
|     { | ||||
|         strcat( lpszSymbolPath, ";" ); | ||||
|         strcat( lpszSymbolPath, lpszPath ); | ||||
|     } | ||||
| 
 | ||||
|     // environment variable SYSTEMROOT
 | ||||
|     if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) ) | ||||
|     { | ||||
|         strcat( lpszSymbolPath, ";" ); | ||||
|         strcat( lpszSymbolPath, lpszPath ); | ||||
|         strcat( lpszSymbolPath, ";" ); | ||||
| 
 | ||||
|         // SYSTEMROOT\System32
 | ||||
|         strcat( lpszSymbolPath, lpszPath ); | ||||
|         strcat( lpszSymbolPath, "\\System32" ); | ||||
|     } | ||||
| 
 | ||||
|     // Add user defined path
 | ||||
|     if ( lpszIniPath != nullptr ) | ||||
|         if ( lpszIniPath[0] != '\0' ) | ||||
|         { | ||||
|             strcat( lpszSymbolPath, ";" ); | ||||
|             strcat( lpszSymbolPath, lpszIniPath ); | ||||
|         } | ||||
| } | ||||
| 
 | ||||
| // Uninitialize the loaded symbol files
 | ||||
| BOOL UninitSymInfo() { | ||||
|     return SymCleanup( GetCurrentProcess() ); | ||||
| } | ||||
| 
 | ||||
| // Initializes the symbol files
 | ||||
| BOOL InitSymInfo( PCSTR lpszInitialSymbolPath ) | ||||
| { | ||||
|     CHAR     lpszSymbolPath[BUFFERSIZE]; | ||||
|     DWORD    symOptions = SymGetOptions(); | ||||
| 
 | ||||
|     symOptions |= SYMOPT_LOAD_LINES; | ||||
|     symOptions &= ~SYMOPT_UNDNAME; | ||||
|     SymSetOptions( symOptions ); | ||||
|     InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath ); | ||||
| 
 | ||||
|     return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE); | ||||
| } | ||||
| 
 | ||||
| // Get the module name from a given address
 | ||||
| static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule ) | ||||
| { | ||||
|     BOOL              ret = FALSE; | ||||
|     IMAGEHLP_MODULE   moduleInfo; | ||||
| 
 | ||||
|     ::ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); | ||||
|     moduleInfo.SizeOfStruct = sizeof(moduleInfo); | ||||
| 
 | ||||
|     if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) ) | ||||
|     { | ||||
|         // Got it!
 | ||||
|         PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule ); | ||||
|         ret = TRUE; | ||||
|     } | ||||
|     else | ||||
|         // Not found :(
 | ||||
|         _tcscpy( lpszModule, _T("?") ); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| // Get function prototype and parameter info from ip address and stack address
 | ||||
| static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol ) | ||||
| { | ||||
|     BOOL              ret = FALSE; | ||||
|     DWORD             dwSymSize = 10000; | ||||
|     TCHAR             lpszUnDSymbol[BUFFERSIZE]=_T("?"); | ||||
|     CHAR              lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?"; | ||||
|     LPTSTR            lpszParamSep = nullptr; | ||||
|     LPTSTR            lpszParsed = lpszUnDSymbol; | ||||
|     PIMAGEHLP_SYMBOL  pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize ); | ||||
| 
 | ||||
|     ::ZeroMemory( pSym, dwSymSize ); | ||||
|     pSym->SizeOfStruct = dwSymSize; | ||||
|     pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL); | ||||
| 
 | ||||
|     // Set the default to unknown
 | ||||
|     _tcscpy( lpszSymbol, _T("?") ); | ||||
| 
 | ||||
|     // Get symbol info for IP
 | ||||
| #ifndef _M_X64 | ||||
|     DWORD             dwDisp = 0; | ||||
|     if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) ) | ||||
| #else | ||||
|     //makes it compile but hell im not sure if this works...
 | ||||
|     DWORD64           dwDisp = 0; | ||||
|     if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) | ||||
| #endif | ||||
|     { | ||||
|         // Make the symbol readable for humans
 | ||||
|         UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, | ||||
|             UNDNAME_COMPLETE | | ||||
|             UNDNAME_NO_THISTYPE | | ||||
|             UNDNAME_NO_SPECIAL_SYMS | | ||||
|             UNDNAME_NO_MEMBER_TYPE | | ||||
|             UNDNAME_NO_MS_KEYWORDS | | ||||
|             UNDNAME_NO_ACCESS_SPECIFIERS ); | ||||
| 
 | ||||
|         // Symbol information is ANSI string
 | ||||
|         PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol ); | ||||
| 
 | ||||
|         // I am just smarter than the symbol file :)
 | ||||
|         if (_tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0) | ||||
|             _tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)")); | ||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_main")) == 0) | ||||
|             _tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)")); | ||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0) | ||||
|             _tcscpy(lpszUnDSymbol, _T("mainCRTStartup()")); | ||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_wmain")) == 0) | ||||
|             _tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)")); | ||||
|         else if (_tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0) | ||||
|             _tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()")); | ||||
| 
 | ||||
|         lpszSymbol[0] = _T('\0'); | ||||
| 
 | ||||
|         // Let's go through the stack, and modify the function prototype, and insert the actual
 | ||||
|         // parameter values from the stack
 | ||||
|         if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == nullptr && _tcsstr( lpszUnDSymbol, _T("()") ) == nullptr) | ||||
|         { | ||||
|             ULONG index = 0; | ||||
|             for( ; ; index++ ) | ||||
|             { | ||||
|                 lpszParamSep = _tcschr( lpszParsed, _T(',') ); | ||||
|                 if ( lpszParamSep == nullptr ) | ||||
|                     break; | ||||
| 
 | ||||
|                 *lpszParamSep = _T('\0'); | ||||
| 
 | ||||
|                 _tcscat( lpszSymbol, lpszParsed ); | ||||
|                 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) ); | ||||
| 
 | ||||
|                 lpszParsed = lpszParamSep + 1; | ||||
|             } | ||||
| 
 | ||||
|             lpszParamSep = _tcschr( lpszParsed, _T(')') ); | ||||
|             if ( lpszParamSep != nullptr ) | ||||
|             { | ||||
|                 *lpszParamSep = _T('\0'); | ||||
| 
 | ||||
|                 _tcscat( lpszSymbol, lpszParsed ); | ||||
|                 _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) ); | ||||
| 
 | ||||
|                 lpszParsed = lpszParamSep + 1; | ||||
|             } | ||||
|         } | ||||
| 
 | ||||
|         _tcscat( lpszSymbol, lpszParsed ); | ||||
| 
 | ||||
|         ret = TRUE; | ||||
|     } | ||||
|     GlobalFree( pSym ); | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| // Get source file name and line number from IP address
 | ||||
| // The output format is: "sourcefile(linenumber)" or
 | ||||
| //                       "modulename!address" or
 | ||||
| //                       "address"
 | ||||
| static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) | ||||
| { | ||||
|     BOOL           ret = FALSE; | ||||
|     IMAGEHLP_LINE  lineInfo; | ||||
|     DWORD          dwDisp; | ||||
|     TCHAR          lpszFileName[BUFFERSIZE] = _T(""); | ||||
|     TCHAR          lpModuleInfo[BUFFERSIZE] = _T(""); | ||||
| 
 | ||||
|     _tcscpy( lpszSourceInfo, _T("?(?)") ); | ||||
| 
 | ||||
|     ::ZeroMemory( &lineInfo, sizeof( lineInfo ) ); | ||||
|     lineInfo.SizeOfStruct = sizeof( lineInfo ); | ||||
| 
 | ||||
|     if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) ) | ||||
|     { | ||||
|         // Got it. Let's use "sourcefile(linenumber)" format
 | ||||
|         PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); | ||||
|         TCHAR fname[_MAX_FNAME]; | ||||
|         TCHAR ext[_MAX_EXT]; | ||||
|         _tsplitpath(lpszFileName, nullptr, nullptr, fname, ext); | ||||
|         _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); | ||||
|         ret = TRUE; | ||||
|     } | ||||
|     else | ||||
|     { | ||||
|         // There is no source file information. :(
 | ||||
|         // Let's use the "modulename!address" format
 | ||||
|         GetModuleNameFromAddress( address, lpModuleInfo ); | ||||
| 
 | ||||
|         if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) | ||||
|             // There is no modulename information. :((
 | ||||
|             // Let's use the "address" format
 | ||||
|             _stprintf( lpszSourceInfo, _T("0x%08X"), address ); | ||||
|         else | ||||
|             _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address ); | ||||
| 
 | ||||
|         ret = FALSE; | ||||
|     } | ||||
| 
 | ||||
|     return ret; | ||||
| } | ||||
| 
 | ||||
| void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) | ||||
| { | ||||
|     TCHAR symInfo[BUFFERSIZE] = _T("?"); | ||||
|     TCHAR srcInfo[BUFFERSIZE] = _T("?"); | ||||
| 
 | ||||
|     GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); | ||||
|     GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); | ||||
|     etfprint(file, "     " + Common::TStrToUTF8(srcInfo) + " : " + Common::TStrToUTF8(symInfo) + "\n"); | ||||
| } | ||||
| 
 | ||||
| void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) | ||||
| { | ||||
|     STACKFRAME     callStack; | ||||
|     BOOL           bResult; | ||||
|     CONTEXT        context; | ||||
|     HANDLE         hProcess = GetCurrentProcess(); | ||||
| 
 | ||||
|     // If it's not this thread, let's suspend it, and resume it at the end
 | ||||
|     if ( hThread != GetCurrentThread() ) | ||||
|         if ( SuspendThread( hThread ) == -1 ) | ||||
|         { | ||||
|             // whaaat ?!
 | ||||
|             etfprint(file, "Call stack info failed\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         ::ZeroMemory( &context, sizeof(context) ); | ||||
|         context.ContextFlags = CONTEXT_FULL; | ||||
| 
 | ||||
|         if ( !GetThreadContext( hThread, &context ) ) | ||||
|         { | ||||
|             etfprint(file, "Call stack info failed\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         ::ZeroMemory( &callStack, sizeof(callStack) ); | ||||
| #ifndef _M_X64 | ||||
|         callStack.AddrPC.Offset    = context.Eip; | ||||
|         callStack.AddrStack.Offset = context.Esp; | ||||
|         callStack.AddrFrame.Offset = context.Ebp; | ||||
| #else | ||||
|         callStack.AddrPC.Offset    = context.Rip; | ||||
|         callStack.AddrStack.Offset = context.Rsp; | ||||
|         callStack.AddrFrame.Offset = context.Rbp; | ||||
| #endif | ||||
|         callStack.AddrPC.Mode      = AddrModeFlat; | ||||
|         callStack.AddrStack.Mode   = AddrModeFlat; | ||||
|         callStack.AddrFrame.Mode   = AddrModeFlat; | ||||
| 
 | ||||
|         etfprint(file, "Call stack info: \n"); | ||||
|         etfprint(file, lpszMessage); | ||||
| 
 | ||||
|         PrintFunctionAndSourceInfo(file, callStack); | ||||
| 
 | ||||
|         for( ULONG index = 0; ; index++ ) | ||||
|         { | ||||
|             bResult = StackWalk( | ||||
|                 IMAGE_FILE_MACHINE_I386, | ||||
|                 hProcess, | ||||
|                 hThread, | ||||
|                 &callStack, | ||||
|                 nullptr, | ||||
|                 nullptr, | ||||
|                 SymFunctionTableAccess, | ||||
|                 SymGetModuleBase, | ||||
|                 nullptr); | ||||
| 
 | ||||
|             if ( index == 0 ) | ||||
|                 continue; | ||||
| 
 | ||||
|             if( !bResult || callStack.AddrFrame.Offset == 0 ) | ||||
|                 break; | ||||
| 
 | ||||
|             PrintFunctionAndSourceInfo(file, callStack); | ||||
| 
 | ||||
|         } | ||||
| 
 | ||||
|         if ( hThread != GetCurrentThread() ) | ||||
|             ResumeThread( hThread ); | ||||
| } | ||||
| 
 | ||||
| void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) | ||||
| { | ||||
|     STACKFRAME     callStack; | ||||
|     BOOL           bResult; | ||||
|     TCHAR          symInfo[BUFFERSIZE] = _T("?"); | ||||
|     TCHAR          srcInfo[BUFFERSIZE] = _T("?"); | ||||
|     HANDLE         hProcess = GetCurrentProcess(); | ||||
| 
 | ||||
|     // If it's not this thread, let's suspend it, and resume it at the end
 | ||||
|     if ( hThread != GetCurrentThread() ) | ||||
|         if ( SuspendThread( hThread ) == -1 ) | ||||
|         { | ||||
|             // whaaat ?!
 | ||||
|             etfprint(file, "Call stack info failed\n"); | ||||
|             return; | ||||
|         } | ||||
| 
 | ||||
|         ::ZeroMemory( &callStack, sizeof(callStack) ); | ||||
|         callStack.AddrPC.Offset    = eip; | ||||
|         callStack.AddrStack.Offset = esp; | ||||
|         callStack.AddrFrame.Offset = ebp; | ||||
|         callStack.AddrPC.Mode      = AddrModeFlat; | ||||
|         callStack.AddrStack.Mode   = AddrModeFlat; | ||||
|         callStack.AddrFrame.Mode   = AddrModeFlat; | ||||
| 
 | ||||
|         etfprint(file, "Call stack info: \n"); | ||||
|         etfprint(file, lpszMessage); | ||||
| 
 | ||||
|         PrintFunctionAndSourceInfo(file, callStack); | ||||
| 
 | ||||
|         for( ULONG index = 0; ; index++ ) | ||||
|         { | ||||
|             bResult = StackWalk( | ||||
|                 IMAGE_FILE_MACHINE_I386, | ||||
|                 hProcess, | ||||
|                 hThread, | ||||
|                 &callStack, | ||||
|                 nullptr, | ||||
|                 nullptr, | ||||
|                 SymFunctionTableAccess, | ||||
|                 SymGetModuleBase, | ||||
|                 nullptr); | ||||
| 
 | ||||
|             if ( index == 0 ) | ||||
|                 continue; | ||||
| 
 | ||||
|             if( !bResult || callStack.AddrFrame.Offset == 0 ) | ||||
|                 break; | ||||
| 
 | ||||
|             PrintFunctionAndSourceInfo(file, callStack); | ||||
|         } | ||||
| 
 | ||||
|         if ( hThread != GetCurrentThread() ) | ||||
|             ResumeThread( hThread ); | ||||
| } | ||||
| 
 | ||||
| char g_uefbuf[2048]; | ||||
| 
 | ||||
| void etfprintf(FILE *file, const char *format, ...) | ||||
| { | ||||
|     va_list ap; | ||||
|     va_start(ap, format); | ||||
|     int len = vsprintf(g_uefbuf, format, ap); | ||||
|     fwrite(g_uefbuf, 1, len, file); | ||||
|     va_end(ap); | ||||
| } | ||||
| 
 | ||||
| void etfprint(FILE *file, const std::string &text) | ||||
| { | ||||
|     size_t len = text.length(); | ||||
|     fwrite(text.data(), 1, len, file); | ||||
| } | ||||
| 
 | ||||
| #endif //WIN32
 | ||||
|  | @ -1,50 +0,0 @@ | |||
| // -----------------------------------------------------------------------------------------
 | ||||
| //
 | ||||
| // Written by Zoltan Csizmadia, zoltan_csizmadia@yahoo.com
 | ||||
| // For companies(Austin,TX): If you would like to get my resume, send an email.
 | ||||
| //
 | ||||
| // The source is free, but if you want to use it, mention my name and e-mail address
 | ||||
| //
 | ||||
| // History:
 | ||||
| //    1.0      Initial version                  Zoltan Csizmadia
 | ||||
| //    1.1      WhineCube version                Masken
 | ||||
| //    1.2      Dolphin version                  Masken
 | ||||
| //
 | ||||
| // ----------------------------------------------------------------------------------------
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #if defined(WIN32) | ||||
| 
 | ||||
| #include <windows.h> | ||||
| #include <tchar.h> | ||||
| 
 | ||||
| #include <string> | ||||
| 
 | ||||
| #pragma comment( lib, "imagehlp.lib" ) | ||||
| 
 | ||||
| #define EXTENDEDTRACEINITIALIZE( IniSymbolPath )    InitSymInfo( IniSymbolPath ) | ||||
| #define EXTENDEDTRACEUNINITIALIZE()                    UninitSymInfo() | ||||
| #define STACKTRACE(file)                            StackTrace( GetCurrentThread(), "", file) | ||||
| #define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp) | ||||
| // class File;
 | ||||
| 
 | ||||
| BOOL InitSymInfo( PCSTR ); | ||||
| BOOL UninitSymInfo(); | ||||
| void StackTrace(HANDLE, char const* msg, FILE *file); | ||||
| void StackTrace(HANDLE, char const* msg, FILE *file, DWORD eip, DWORD esp, DWORD ebp); | ||||
| 
 | ||||
| // functions by Masken
 | ||||
| void etfprintf(FILE *file, const char *format, ...); | ||||
| void etfprint(FILE *file, const std::string &text); | ||||
| #define UEFBUFSIZE 2048 | ||||
| extern char g_uefbuf[UEFBUFSIZE]; | ||||
| 
 | ||||
| #else    // not WIN32
 | ||||
| 
 | ||||
| #define EXTENDEDTRACEINITIALIZE( IniSymbolPath )    ((void)0) | ||||
| #define EXTENDEDTRACEUNINITIALIZE()                    ((void)0) | ||||
| #define STACKTRACE(file)                            ((void)0) | ||||
| #define STACKTRACE2(file, eip, esp, ebp)            ((void)0) | ||||
| 
 | ||||
| #endif    // WIN32
 | ||||
|  | @ -1,103 +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" | ||||
| 
 | ||||
| #ifndef _WIN32 | ||||
| #include <dirent.h> | ||||
| #else | ||||
| #include <windows.h> | ||||
| #endif | ||||
| 
 | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "common/file_search.h" | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| 
 | ||||
| CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories) | ||||
| { | ||||
|     // Reverse the loop order for speed?
 | ||||
|     for (size_t j = 0; j < _rSearchStrings.size(); j++) | ||||
|     { | ||||
|         for (size_t i = 0; i < _rDirectories.size(); i++) | ||||
|         { | ||||
|             FindFiles(_rSearchStrings[j], _rDirectories[i]); | ||||
|         } | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| 
 | ||||
| void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath) | ||||
| { | ||||
|     std::string GCMSearchPath; | ||||
|     Common::BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); | ||||
| #ifdef _WIN32 | ||||
|     WIN32_FIND_DATA findData; | ||||
|     HANDLE FindFirst = FindFirstFile(Common::UTF8ToTStr(GCMSearchPath).c_str(), &findData); | ||||
| 
 | ||||
|     if (FindFirst != INVALID_HANDLE_VALUE) | ||||
|     { | ||||
|         bool bkeepLooping = true; | ||||
| 
 | ||||
|         while (bkeepLooping) | ||||
|         { | ||||
|             if (findData.cFileName[0] != '.') | ||||
|             { | ||||
|                 std::string strFilename; | ||||
|                 Common::BuildCompleteFilename(strFilename, _strPath, Common::TStrToUTF8(findData.cFileName)); | ||||
|                 m_FileNames.push_back(strFilename); | ||||
|             } | ||||
| 
 | ||||
|             bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false; | ||||
|         } | ||||
|     } | ||||
|     FindClose(FindFirst); | ||||
| 
 | ||||
| 
 | ||||
| #else | ||||
|     // TODO: super lame/broken
 | ||||
| 
 | ||||
|     auto end_match(_searchString); | ||||
| 
 | ||||
|     // assuming we have a "*.blah"-like pattern
 | ||||
|     if (!end_match.empty() && end_match[0] == '*') | ||||
|         end_match.erase(0, 1); | ||||
| 
 | ||||
|     // ugly
 | ||||
|     if (end_match == ".*") | ||||
|         end_match.clear(); | ||||
| 
 | ||||
|     DIR* dir = opendir(_strPath.c_str()); | ||||
| 
 | ||||
|     if (!dir) | ||||
|         return; | ||||
| 
 | ||||
|     while (auto const dp = readdir(dir)) | ||||
|     { | ||||
|         std::string found(dp->d_name); | ||||
| 
 | ||||
|         if ((found != ".") && (found != "..") | ||||
|             && (found.size() >= end_match.size()) | ||||
|             && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin())) | ||||
|         { | ||||
|             std::string full_name; | ||||
|             if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR) | ||||
|                 full_name = _strPath + found; | ||||
|             else | ||||
|                 full_name = _strPath + DIR_SEP + found; | ||||
| 
 | ||||
|             m_FileNames.push_back(full_name); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     closedir(dir); | ||||
| #endif | ||||
| } | ||||
| 
 | ||||
| const CFileSearch::XStringVector& CFileSearch::GetFileNames() const | ||||
| { | ||||
|     return m_FileNames; | ||||
| } | ||||
|  | @ -1,23 +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 <string> | ||||
| #include <vector> | ||||
| 
 | ||||
| class CFileSearch | ||||
| { | ||||
| public: | ||||
|     typedef std::vector<std::string>XStringVector; | ||||
| 
 | ||||
|     CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories); | ||||
|     const XStringVector& GetFileNames() const; | ||||
| 
 | ||||
| private: | ||||
| 
 | ||||
|     void FindFiles(const std::string& _searchString, const std::string& _strPath); | ||||
| 
 | ||||
|     XStringVector m_FileNames; | ||||
| }; | ||||
|  | @ -2,6 +2,7 @@ | |||
| // Licensed under GPLv2 or any later version
 | ||||
| // Refer to the license.txt file included.
 | ||||
| 
 | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "common/hash.h" | ||||
| #if _M_SSE >= 0x402 | ||||
|  | @ -155,7 +156,7 @@ 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 = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
| 
 | ||||
|  | @ -233,7 +234,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) | |||
|     u32 Step = (len / 8); | ||||
|     const u64 *data = (const u64 *)src; | ||||
|     const u64 *end = data + Step; | ||||
|     if(samples == 0) samples = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
|     while(data < end) | ||||
|  | @ -265,7 +266,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
|     u32 Step = (len / 8); | ||||
|     const u64 *data = (const u64 *)src; | ||||
|     const u64 *end = data + Step; | ||||
|     if(samples == 0) samples = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
|     while(data < end) | ||||
|  | @ -308,7 +309,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples) | |||
|     u32 Step = (len/4); | ||||
|     const u32 *data = (const u32 *)src; | ||||
|     const u32 *end = data + Step; | ||||
|     if(samples == 0) samples = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step  = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
|     while(data < end) | ||||
|  | @ -380,7 +381,7 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples) | |||
|     u32 out[2]; | ||||
|     const int nblocks = len / 8; | ||||
|     u32 Step = (len / 4); | ||||
|     if(samples == 0) samples = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
| 
 | ||||
|  | @ -456,7 +457,7 @@ u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) | |||
|     u32 Step = (len / 8); | ||||
|     const u64 *data = (const u64 *)src; | ||||
|     const u64 *end = data + Step; | ||||
|     if(samples == 0) samples = max(Step, 1u); | ||||
|     if(samples == 0) samples = std::max(Step, 1u); | ||||
|     Step = Step / samples; | ||||
|     if(Step < 1) Step = 1; | ||||
|     while(data < end) | ||||
|  |  | |||
|  | @ -218,7 +218,7 @@ u8* MemArena::Find4GBBase() | |||
|     void* base = mmap(0, 0x10000000, PROT_READ | PROT_WRITE, | ||||
|         MAP_ANON | MAP_SHARED, -1, 0); | ||||
|     if (base == MAP_FAILED) { | ||||
|         PanicAlert("Failed to map 256 MB of memory space: %s", strerror(errno)); | ||||
|         LOG_ERROR(Common_Memory, "Failed to map 256 MB of memory space: %s", strerror(errno)); | ||||
|         return 0; | ||||
|     } | ||||
|     munmap(base, 0x10000000); | ||||
|  | @ -338,7 +338,7 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena | |||
|     // address space.
 | ||||
|     if (!Memory_TryBase(base, views, num_views, flags, arena)) | ||||
|     { | ||||
|         PanicAlert("MemoryMap_Setup: Failed finding a memory base."); | ||||
|         LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); | ||||
|         return 0; | ||||
|     } | ||||
| #elif defined(_WIN32) | ||||
|  | @ -363,12 +363,11 @@ u8 *MemoryMap_Setup(const MemoryView *views, int num_views, u32 flags, MemArena | |||
|     if (!Memory_TryBase(base, views, num_views, flags, arena)) | ||||
|     { | ||||
|         LOG_ERROR(Common_Memory, "MemoryMap_Setup: Failed finding a memory base."); | ||||
|         PanicAlert("MemoryMap_Setup: Failed finding a memory base."); | ||||
|         return 0; | ||||
|     } | ||||
| #endif | ||||
|     if (base_attempts) | ||||
|         PanicAlert("No possible memory base pointer found!"); | ||||
|         LOG_ERROR(Common_Memory, "No possible memory base pointer found!"); | ||||
|     return base; | ||||
| } | ||||
| 
 | ||||
|  |  | |||
|  | @ -56,7 +56,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | |||
|     { | ||||
|         ptr = nullptr; | ||||
| #endif | ||||
|         PanicAlert("Failed to allocate executable memory"); | ||||
|         LOG_ERROR(Common_Memory, "Failed to allocate executable memory"); | ||||
|     } | ||||
| #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) | ||||
|     else | ||||
|  | @ -72,7 +72,7 @@ void* AllocateExecutableMemory(size_t size, bool low) | |||
| 
 | ||||
| #if defined(_M_X64) | ||||
|     if ((u64)ptr >= 0x80000000 && low == true) | ||||
|         PanicAlert("Executable memory ended up above 2GB!"); | ||||
|         LOG_ERROR(Common_Memory, "Executable memory ended up above 2GB!"); | ||||
| #endif | ||||
| 
 | ||||
|     return ptr; | ||||
|  | @ -94,7 +94,7 @@ void* AllocateMemoryPages(size_t size) | |||
|     //    (unsigned long)size);
 | ||||
| 
 | ||||
|     if (ptr == nullptr) | ||||
|         PanicAlert("Failed to allocate raw memory"); | ||||
|         LOG_ERROR(Common_Memory, "Failed to allocate raw memory"); | ||||
| 
 | ||||
|     return ptr; | ||||
| } | ||||
|  | @ -117,7 +117,7 @@ void* AllocateAlignedMemory(size_t size,size_t alignment) | |||
|     //    (unsigned long)size);
 | ||||
| 
 | ||||
|     if (ptr == nullptr) | ||||
|         PanicAlert("Failed to allocate aligned memory"); | ||||
|         LOG_ERROR(Common_Memory, "Failed to allocate aligned memory"); | ||||
| 
 | ||||
|     return ptr; | ||||
| } | ||||
|  | @ -129,7 +129,7 @@ void FreeMemoryPages(void* ptr, size_t size) | |||
| #ifdef _WIN32 | ||||
| 
 | ||||
|         if (!VirtualFree(ptr, 0, MEM_RELEASE)) | ||||
|             PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); | ||||
|             LOG_ERROR(Common_Memory, "FreeMemoryPages failed!\n%s", GetLastErrorMsg()); | ||||
|         ptr = nullptr; // Is this our responsibility?
 | ||||
| 
 | ||||
| #else | ||||
|  | @ -155,7 +155,7 @@ void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) | |||
| #ifdef _WIN32 | ||||
|     DWORD oldValue; | ||||
|     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) | ||||
|         PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||
|         LOG_ERROR(Common_Memory, "WriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||
| #else | ||||
|     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); | ||||
| #endif | ||||
|  | @ -166,7 +166,7 @@ void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) | |||
| #ifdef _WIN32 | ||||
|     DWORD oldValue; | ||||
|     if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue)) | ||||
|         PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||
|         LOG_ERROR(Common_Memory, "UnWriteProtectMemory failed!\n%s", GetLastErrorMsg()); | ||||
| #else | ||||
|     mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); | ||||
| #endif | ||||
|  |  | |||
|  | @ -1,107 +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 <cstdio> | ||||
| 
 | ||||
| #include "common/common.h" // Local
 | ||||
| #include "common/string_util.h" | ||||
| 
 | ||||
| bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style); | ||||
| static MsgAlertHandler msg_handler = DefaultMsgHandler; | ||||
| static bool AlertEnabled = true; | ||||
| 
 | ||||
| std::string DefaultStringTranslator(const char* text); | ||||
| static StringTranslator str_translator = DefaultStringTranslator; | ||||
| 
 | ||||
| // Select which of these functions that are used for message boxes. If
 | ||||
| // wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
 | ||||
| void RegisterMsgAlertHandler(MsgAlertHandler handler) | ||||
| { | ||||
|     msg_handler = handler; | ||||
| } | ||||
| 
 | ||||
| // Select translation function.  For wxWidgets use wxStringTranslator in Main.cpp
 | ||||
| void RegisterStringTranslator(StringTranslator translator) | ||||
| { | ||||
|     str_translator = translator; | ||||
| } | ||||
| 
 | ||||
| // enable/disable the alert handler
 | ||||
| void SetEnableAlert(bool enable) | ||||
| { | ||||
|     AlertEnabled = enable; | ||||
| } | ||||
| 
 | ||||
| // This is the first stop for gui alerts where the log is updated and the
 | ||||
| // correct window is shown
 | ||||
| bool MsgAlert(bool yes_no, int Style, const char* format, ...) | ||||
| { | ||||
|     // Read message and write it to the log
 | ||||
|     std::string caption; | ||||
|     char buffer[2048]; | ||||
| 
 | ||||
|     static std::string info_caption; | ||||
|     static std::string warn_caption; | ||||
|     static std::string ques_caption; | ||||
|     static std::string crit_caption; | ||||
| 
 | ||||
|     if (!info_caption.length()) | ||||
|     { | ||||
|         info_caption = str_translator(_trans("Information")); | ||||
|         ques_caption = str_translator(_trans("Question")); | ||||
|         warn_caption = str_translator(_trans("Warning")); | ||||
|         crit_caption = str_translator(_trans("Critical")); | ||||
|     } | ||||
| 
 | ||||
|     switch(Style) | ||||
|     { | ||||
|         case INFORMATION: | ||||
|             caption = info_caption; | ||||
|             break; | ||||
|         case QUESTION: | ||||
|             caption = ques_caption; | ||||
|             break; | ||||
|         case WARNING: | ||||
|             caption = warn_caption; | ||||
|             break; | ||||
|         case CRITICAL: | ||||
|             caption = crit_caption; | ||||
|             break; | ||||
|     } | ||||
| 
 | ||||
|     va_list args; | ||||
|     va_start(args, format); | ||||
|     Common::CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args); | ||||
|     va_end(args); | ||||
| 
 | ||||
|     LOG_INFO(Common, "%s: %s", caption.c_str(), buffer); | ||||
| 
 | ||||
|     // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
 | ||||
|     if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL)) | ||||
|         return msg_handler(caption.c_str(), buffer, yes_no, Style); | ||||
| 
 | ||||
|     return true; | ||||
| } | ||||
| 
 | ||||
| // Default non library dependent panic alert
 | ||||
| bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style) | ||||
| { | ||||
| //#ifdef _WIN32
 | ||||
| //    int STYLE = MB_ICONINFORMATION;
 | ||||
| //    if (Style == QUESTION) STYLE = MB_ICONQUESTION;
 | ||||
| //    if (Style == WARNING) STYLE = MB_ICONWARNING;
 | ||||
| //
 | ||||
| //    return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
 | ||||
| //#else
 | ||||
|     printf("%s\n", text); | ||||
|     return true; | ||||
| //#endif
 | ||||
| } | ||||
| 
 | ||||
| // Default (non) translator
 | ||||
| std::string DefaultStringTranslator(const char* text) | ||||
| { | ||||
|     return text; | ||||
| } | ||||
| 
 | ||||
|  | @ -1,56 +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 <string> | ||||
| 
 | ||||
| // Message alerts
 | ||||
| enum MSG_TYPE | ||||
| { | ||||
|     INFORMATION, | ||||
|     QUESTION, | ||||
|     WARNING, | ||||
|     CRITICAL | ||||
| }; | ||||
| 
 | ||||
| typedef bool (*MsgAlertHandler)(const char* caption, const char* text, | ||||
|                                 bool yes_no, int Style); | ||||
| typedef std::string (*StringTranslator)(const char* text); | ||||
| 
 | ||||
| void RegisterMsgAlertHandler(MsgAlertHandler handler); | ||||
| void RegisterStringTranslator(StringTranslator translator); | ||||
| 
 | ||||
| extern bool MsgAlert(bool yes_no, int Style, const char* format, ...) | ||||
| #ifdef __GNUC__ | ||||
|     __attribute__((format(printf, 3, 4))) | ||||
| #endif | ||||
|     ; | ||||
| void SetEnableAlert(bool enable); | ||||
| 
 | ||||
| #ifdef _MSC_VER | ||||
|     #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) | ||||
|     #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) | ||||
|     #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) | ||||
|     #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) | ||||
|     #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) | ||||
|     // Use these macros (that do the same thing) if the message should be translated.
 | ||||
|     #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) | ||||
|     #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) | ||||
|     #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) | ||||
|     #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) | ||||
|     #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) | ||||
| #else | ||||
|     #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) | ||||
|     #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) | ||||
|     #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) | ||||
|     #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) | ||||
|     #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) | ||||
|     // Use these macros (that do the same thing) if the message should be translated.
 | ||||
|     #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) | ||||
|     #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) | ||||
|     #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) | ||||
|     #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) | ||||
|     #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) | ||||
| #endif | ||||
|  | @ -1,459 +0,0 @@ | |||
| /*
 | ||||
|   Basic UTF-8 manipulation routines | ||||
|   by Jeff Bezanson | ||||
|   placed in the public domain Fall 2005 | ||||
| 
 | ||||
|   This code is designed to provide the utilities you need to manipulate | ||||
|   UTF-8 as an internal string encoding. These functions do not perform the | ||||
|   error checking normally needed when handling UTF-8 data, so if you happen | ||||
|   to be from the Unicode Consortium you will want to flay me alive. | ||||
|   I do this because error checking can be performed at the boundaries (I/O), | ||||
|   with these routines reserved for higher performance on data known to be | ||||
|   valid. | ||||
| */ | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| #include <windows.h> | ||||
| #undef min | ||||
| #undef max | ||||
| #endif | ||||
| 
 | ||||
| #include <cstdlib> | ||||
| #include <cstring> | ||||
| #include <algorithm> | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include "common/utf8.h" | ||||
| 
 | ||||
| // is start of UTF sequence
 | ||||
| inline bool isutf(char c) { | ||||
|     return (c & 0xC0) != 0x80; | ||||
| } | ||||
| 
 | ||||
| static const u32 offsetsFromUTF8[6] = { | ||||
|   0x00000000UL, 0x00003080UL, 0x000E2080UL, | ||||
|   0x03C82080UL, 0xFA082080UL, 0x82082080UL | ||||
| }; | ||||
| 
 | ||||
| static const u8 trailingBytesForUTF8[256] = { | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, | ||||
|   1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, | ||||
|         2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5, | ||||
| }; | ||||
| 
 | ||||
| /* returns length of next utf-8 sequence */ | ||||
| int u8_seqlen(const char *s) | ||||
| { | ||||
|   return trailingBytesForUTF8[(unsigned int)(unsigned char)s[0]] + 1; | ||||
| } | ||||
| 
 | ||||
| /* conversions without error checking
 | ||||
|    only works for valid UTF-8, i.e. no 5- or 6-byte sequences | ||||
|    srcsz = source size in bytes, or -1 if 0-terminated | ||||
|    sz = dest size in # of wide characters | ||||
| 
 | ||||
|    returns # characters converted | ||||
|    dest will always be L'\0'-terminated, even if there isn't enough room | ||||
|    for all the characters. | ||||
|    if sz = srcsz+1 (i.e. 4*srcsz+4 bytes), there will always be enough space. | ||||
| */ | ||||
| int u8_toucs(u32 *dest, int sz, const char *src, int srcsz) | ||||
| { | ||||
|   u32 ch; | ||||
|   const char *src_end = src + srcsz; | ||||
|   int nb; | ||||
|   int i=0; | ||||
| 
 | ||||
|   while (i < sz-1) { | ||||
|     nb = trailingBytesForUTF8[(unsigned char)*src]; | ||||
|     if (srcsz == -1) { | ||||
|       if (*src == 0) | ||||
|         goto done_toucs; | ||||
|     } | ||||
|     else { | ||||
|       if (src + nb >= src_end) | ||||
|         goto done_toucs; | ||||
|     } | ||||
|     ch = 0; | ||||
|     switch (nb) { | ||||
|       /* these fall through deliberately */ | ||||
|     case 3: ch += (unsigned char)*src++; ch <<= 6; | ||||
|     case 2: ch += (unsigned char)*src++; ch <<= 6; | ||||
|     case 1: ch += (unsigned char)*src++; ch <<= 6; | ||||
|     case 0: ch += (unsigned char)*src++; | ||||
|     } | ||||
|     ch -= offsetsFromUTF8[nb]; | ||||
|     dest[i++] = ch; | ||||
|   } | ||||
|  done_toucs: | ||||
|   dest[i] = 0; | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| /* srcsz = number of source characters, or -1 if 0-terminated
 | ||||
|    sz = size of dest buffer in bytes | ||||
| 
 | ||||
|    returns # characters converted | ||||
|    dest will only be '\0'-terminated if there is enough space. this is | ||||
|    for consistency; imagine there are 2 bytes of space left, but the next | ||||
|    character requires 3 bytes. in this case we could NUL-terminate, but in | ||||
|    general we can't when there's insufficient space. therefore this function | ||||
|    only NUL-terminates if all the characters fit, and there's space for | ||||
|    the NUL as well. | ||||
|    the destination string will never be bigger than the source string. | ||||
| */ | ||||
| int u8_toutf8(char *dest, int sz, u32 *src, int srcsz) | ||||
| { | ||||
|   u32 ch; | ||||
|   int i = 0; | ||||
|   char *dest_end = dest + sz; | ||||
| 
 | ||||
|   while (srcsz<0 ? src[i]!=0 : i < srcsz) { | ||||
|     ch = src[i]; | ||||
|     if (ch < 0x80) { | ||||
|       if (dest >= dest_end) | ||||
|         return i; | ||||
|       *dest++ = (char)ch; | ||||
|     } | ||||
|     else if (ch < 0x800) { | ||||
|       if (dest >= dest_end-1) | ||||
|         return i; | ||||
|       *dest++ = (ch>>6) | 0xC0; | ||||
|       *dest++ = (ch & 0x3F) | 0x80; | ||||
|     } | ||||
|     else if (ch < 0x10000) { | ||||
|       if (dest >= dest_end-2) | ||||
|         return i; | ||||
|       *dest++ = (ch>>12) | 0xE0; | ||||
|       *dest++ = ((ch>>6) & 0x3F) | 0x80; | ||||
|       *dest++ = (ch & 0x3F) | 0x80; | ||||
|     } | ||||
|     else if (ch < 0x110000) { | ||||
|       if (dest >= dest_end-3) | ||||
|         return i; | ||||
|       *dest++ = (ch>>18) | 0xF0; | ||||
|       *dest++ = ((ch>>12) & 0x3F) | 0x80; | ||||
|       *dest++ = ((ch>>6) & 0x3F) | 0x80; | ||||
|       *dest++ = (ch & 0x3F) | 0x80; | ||||
|     } | ||||
|     i++; | ||||
|   } | ||||
|   if (dest < dest_end) | ||||
|     *dest = '\0'; | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| int u8_wc_toutf8(char *dest, u32 ch) | ||||
| { | ||||
|   if (ch < 0x80) { | ||||
|     dest[0] = (char)ch; | ||||
|     return 1; | ||||
|   } | ||||
|   if (ch < 0x800) { | ||||
|     dest[0] = (ch>>6) | 0xC0; | ||||
|     dest[1] = (ch & 0x3F) | 0x80; | ||||
|     return 2; | ||||
|   } | ||||
|   if (ch < 0x10000) { | ||||
|     dest[0] = (ch>>12) | 0xE0; | ||||
|     dest[1] = ((ch>>6) & 0x3F) | 0x80; | ||||
|     dest[2] = (ch & 0x3F) | 0x80; | ||||
|     return 3; | ||||
|   } | ||||
|   if (ch < 0x110000) { | ||||
|     dest[0] = (ch>>18) | 0xF0; | ||||
|     dest[1] = ((ch>>12) & 0x3F) | 0x80; | ||||
|     dest[2] = ((ch>>6) & 0x3F) | 0x80; | ||||
|     dest[3] = (ch & 0x3F) | 0x80; | ||||
|     return 4; | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| /* charnum => byte offset */ | ||||
| int u8_offset(const char *str, int charnum) | ||||
| { | ||||
|   int offs=0; | ||||
| 
 | ||||
|   while (charnum > 0 && str[offs]) { | ||||
|     (void)(isutf(str[++offs]) || isutf(str[++offs]) || | ||||
|          isutf(str[++offs]) || ++offs); | ||||
|     charnum--; | ||||
|   } | ||||
|   return offs; | ||||
| } | ||||
| 
 | ||||
| /* byte offset => charnum */ | ||||
| int u8_charnum(const char *s, int offset) | ||||
| { | ||||
|   int charnum = 0, offs=0; | ||||
| 
 | ||||
|   while (offs < offset && s[offs]) { | ||||
|     (void)(isutf(s[++offs]) || isutf(s[++offs]) || | ||||
|          isutf(s[++offs]) || ++offs); | ||||
|     charnum++; | ||||
|   } | ||||
|   return charnum; | ||||
| } | ||||
| 
 | ||||
| /* number of characters */ | ||||
| int u8_strlen(const char *s) | ||||
| { | ||||
|   int count = 0; | ||||
|   int i = 0; | ||||
| 
 | ||||
|   while (u8_nextchar(s, &i) != 0) | ||||
|     count++; | ||||
| 
 | ||||
|   return count; | ||||
| } | ||||
| 
 | ||||
| /* reads the next utf-8 sequence out of a string, updating an index */ | ||||
| u32 u8_nextchar(const char *s, int *i) | ||||
| { | ||||
|   u32 ch = 0; | ||||
|   int sz = 0; | ||||
| 
 | ||||
|   do { | ||||
|     ch <<= 6; | ||||
|     ch += (unsigned char)s[(*i)++]; | ||||
|     sz++; | ||||
|   } while (s[*i] && !isutf(s[*i])); | ||||
|   ch -= offsetsFromUTF8[sz-1]; | ||||
| 
 | ||||
|   return ch; | ||||
| } | ||||
| 
 | ||||
| void u8_inc(const char *s, int *i) | ||||
| { | ||||
|   (void)(isutf(s[++(*i)]) || isutf(s[++(*i)]) || | ||||
|        isutf(s[++(*i)]) || ++(*i)); | ||||
| } | ||||
| 
 | ||||
| void u8_dec(const char *s, int *i) | ||||
| { | ||||
|   (void)(isutf(s[--(*i)]) || isutf(s[--(*i)]) || | ||||
|        isutf(s[--(*i)]) || --(*i)); | ||||
| } | ||||
| 
 | ||||
| int octal_digit(char c) | ||||
| { | ||||
|   return (c >= '0' && c <= '7'); | ||||
| } | ||||
| 
 | ||||
| int hex_digit(char c) | ||||
| { | ||||
|   return ((c >= '0' && c <= '9') || | ||||
|       (c >= 'A' && c <= 'F') || | ||||
|       (c >= 'a' && c <= 'f')); | ||||
| } | ||||
| 
 | ||||
| /* assumes that src points to the character after a backslash
 | ||||
|    returns number of input characters processed */ | ||||
| int u8_read_escape_sequence(const char *str, u32 *dest) | ||||
| { | ||||
|   u32 ch; | ||||
|   char digs[9]="\0\0\0\0\0\0\0\0"; | ||||
|   int dno=0, i=1; | ||||
| 
 | ||||
|   ch = (u32)str[0];  /* take literal character */ | ||||
|   if (str[0] == 'n') | ||||
|     ch = L'\n'; | ||||
|   else if (str[0] == 't') | ||||
|     ch = L'\t'; | ||||
|   else if (str[0] == 'r') | ||||
|     ch = L'\r'; | ||||
|   else if (str[0] == 'b') | ||||
|     ch = L'\b'; | ||||
|   else if (str[0] == 'f') | ||||
|     ch = L'\f'; | ||||
|   else if (str[0] == 'v') | ||||
|     ch = L'\v'; | ||||
|   else if (str[0] == 'a') | ||||
|     ch = L'\a'; | ||||
|   else if (octal_digit(str[0])) { | ||||
|     i = 0; | ||||
|     do { | ||||
|       digs[dno++] = str[i++]; | ||||
|     } while (octal_digit(str[i]) && dno < 3); | ||||
|     ch = strtol(digs, nullptr, 8); | ||||
|   } | ||||
|   else if (str[0] == 'x') { | ||||
|     while (hex_digit(str[i]) && dno < 2) { | ||||
|       digs[dno++] = str[i++]; | ||||
|     } | ||||
|     if (dno > 0) | ||||
|       ch = strtol(digs, nullptr, 16); | ||||
|   } | ||||
|   else if (str[0] == 'u') { | ||||
|     while (hex_digit(str[i]) && dno < 4) { | ||||
|       digs[dno++] = str[i++]; | ||||
|     } | ||||
|     if (dno > 0) | ||||
|       ch = strtol(digs, nullptr, 16); | ||||
|   } | ||||
|   else if (str[0] == 'U') { | ||||
|     while (hex_digit(str[i]) && dno < 8) { | ||||
|       digs[dno++] = str[i++]; | ||||
|     } | ||||
|     if (dno > 0) | ||||
|       ch = strtol(digs, nullptr, 16); | ||||
|   } | ||||
|   *dest = ch; | ||||
| 
 | ||||
|   return i; | ||||
| } | ||||
| 
 | ||||
| /* convert a string with literal \uxxxx or \Uxxxxxxxx characters to UTF-8
 | ||||
|    example: u8_unescape(mybuf, 256, "hello\\u220e") | ||||
|    note the double backslash is needed if called on a C string literal */ | ||||
| int u8_unescape(char *buf, int sz, char *src) | ||||
| { | ||||
|   int c=0, amt; | ||||
|   u32 ch; | ||||
|   char temp[4]; | ||||
| 
 | ||||
|   while (*src && c < sz) { | ||||
|     if (*src == '\\') { | ||||
|       src++; | ||||
|       amt = u8_read_escape_sequence(src, &ch); | ||||
|     } | ||||
|     else { | ||||
|       ch = (u32)*src; | ||||
|       amt = 1; | ||||
|     } | ||||
|     src += amt; | ||||
|     amt = u8_wc_toutf8(temp, ch); | ||||
|     if (amt > sz-c) | ||||
|       break; | ||||
|     memcpy(&buf[c], temp, amt); | ||||
|     c += amt; | ||||
|   } | ||||
|   if (c < sz) | ||||
|     buf[c] = '\0'; | ||||
|   return c; | ||||
| } | ||||
| 
 | ||||
| const char *u8_strchr(const char *s, u32 ch, int *charn) | ||||
| { | ||||
|   int i = 0, lasti=0; | ||||
|   u32 c; | ||||
| 
 | ||||
|   *charn = 0; | ||||
|   while (s[i]) { | ||||
|     c = u8_nextchar(s, &i); | ||||
|     if (c == ch) { | ||||
|       return &s[lasti]; | ||||
|     } | ||||
|     lasti = i; | ||||
|     (*charn)++; | ||||
|   } | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| const char *u8_memchr(const char *s, u32 ch, size_t sz, int *charn) | ||||
| { | ||||
|   u32 i = 0, lasti=0; | ||||
|   u32 c; | ||||
|   int csz; | ||||
| 
 | ||||
|   *charn = 0; | ||||
|   while (i < sz) { | ||||
|     c = csz = 0; | ||||
|     do { | ||||
|       c <<= 6; | ||||
|       c += (unsigned char)s[i++]; | ||||
|       csz++; | ||||
|     } while (i < sz && !isutf(s[i])); | ||||
|     c -= offsetsFromUTF8[csz-1]; | ||||
| 
 | ||||
|     if (c == ch) { | ||||
|       return &s[lasti]; | ||||
|     } | ||||
|     lasti = i; | ||||
|     (*charn)++; | ||||
|   } | ||||
|   return nullptr; | ||||
| } | ||||
| 
 | ||||
| int u8_is_locale_utf8(const char *locale) | ||||
| { | ||||
|   /* this code based on libutf8 */ | ||||
|   const char* cp = locale; | ||||
| 
 | ||||
|   for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) { | ||||
|     if (*cp == '.') { | ||||
|       const char* encoding = ++cp; | ||||
|       for (; *cp != '\0' && *cp != '@' && *cp != '+' && *cp != ','; cp++) | ||||
|         ; | ||||
|       if ((cp-encoding == 5 && !strncmp(encoding, "UTF-8", 5)) | ||||
|         || (cp-encoding == 4 && !strncmp(encoding, "utf8", 4))) | ||||
|         return 1; /* it's UTF-8 */ | ||||
|       break; | ||||
|     } | ||||
|   } | ||||
|   return 0; | ||||
| } | ||||
| 
 | ||||
| int UTF8StringNonASCIICount(const char *utf8string) { | ||||
|     UTF8 utf(utf8string); | ||||
|     int count = 0; | ||||
|     while (!utf.end()) { | ||||
|         int c = utf.next(); | ||||
|         if (c > 127) | ||||
|             ++count; | ||||
|     } | ||||
|     return count; | ||||
| } | ||||
| 
 | ||||
| bool UTF8StringHasNonASCII(const char *utf8string) { | ||||
|     return UTF8StringNonASCIICount(utf8string) > 0; | ||||
| } | ||||
| 
 | ||||
| #ifdef _WIN32 | ||||
| 
 | ||||
| std::string ConvertWStringToUTF8(const wchar_t *wstr) { | ||||
|     int len = (int)wcslen(wstr); | ||||
|     int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, nullptr, nullptr); | ||||
|     std::string s; | ||||
|     s.resize(size); | ||||
|     if (size > 0) { | ||||
|         WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, nullptr, nullptr); | ||||
|     } | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| std::string ConvertWStringToUTF8(const std::wstring &wstr) { | ||||
|     int len = (int)wstr.size(); | ||||
|     int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, nullptr, nullptr); | ||||
|     std::string s; | ||||
|     s.resize(size); | ||||
|     if (size > 0) { | ||||
|         WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, nullptr, nullptr); | ||||
|     } | ||||
|     return s; | ||||
| } | ||||
| 
 | ||||
| void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { | ||||
|     int len = (int)source.size(); | ||||
|     int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0); | ||||
|     MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size)); | ||||
| } | ||||
| 
 | ||||
| std::wstring ConvertUTF8ToWString(const std::string &source) { | ||||
|     int len = (int)source.size(); | ||||
|     int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, nullptr, 0); | ||||
|     std::wstring str; | ||||
|     str.resize(size); | ||||
|     if (size > 0) { | ||||
|         MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size); | ||||
|     } | ||||
|     return str; | ||||
| } | ||||
| 
 | ||||
| #endif | ||||
|  | @ -1,67 +0,0 @@ | |||
| /*
 | ||||
|   Basic UTF-8 manipulation routines | ||||
|   by Jeff Bezanson | ||||
|   placed in the public domain Fall 2005 | ||||
| 
 | ||||
|   This code is designed to provide the utilities you need to manipulate | ||||
|   UTF-8 as an internal string encoding. These functions do not perform the | ||||
|   error checking normally needed when handling UTF-8 data, so if you happen | ||||
|   to be from the Unicode Consortium you will want to flay me alive. | ||||
|   I do this because error checking can be performed at the boundaries (I/O), | ||||
|   with these routines reserved for higher performance on data known to be | ||||
|   valid. | ||||
| */ | ||||
| 
 | ||||
| // Further modified, and C++ stuff added, by hrydgard@gmail.com.
 | ||||
| 
 | ||||
| #pragma once | ||||
| 
 | ||||
| #include "common/common_types.h" | ||||
| #include <string> | ||||
| 
 | ||||
| u32 u8_nextchar(const char *s, int *i); | ||||
| int u8_wc_toutf8(char *dest, u32 ch); | ||||
| int u8_strlen(const char *s); | ||||
| 
 | ||||
| class UTF8 { | ||||
| public: | ||||
|     static const u32 INVALID = (u32)-1; | ||||
|     UTF8(const char *c) : c_(c), index_(0) {} | ||||
|     bool end() const { return c_[index_] == 0; } | ||||
|     u32 next() { | ||||
|         return u8_nextchar(c_, &index_); | ||||
|     } | ||||
|     u32 peek() { | ||||
|         int tempIndex = index_; | ||||
|         return u8_nextchar(c_, &tempIndex); | ||||
|     } | ||||
|     int length() const { | ||||
|         return u8_strlen(c_); | ||||
|     } | ||||
|     int byteIndex() const { | ||||
|         return index_; | ||||
|     } | ||||
|     static int encode(char *dest, u32 ch) { | ||||
|         return u8_wc_toutf8(dest, ch); | ||||
|     } | ||||
| 
 | ||||
| private: | ||||
|     const char *c_; | ||||
|     int index_; | ||||
| }; | ||||
| 
 | ||||
| int UTF8StringNonASCIICount(const char *utf8string); | ||||
| 
 | ||||
| bool UTF8StringHasNonASCII(const char *utf8string); | ||||
| 
 | ||||
| 
 | ||||
| // UTF8 to Win32 UTF-16
 | ||||
| // Should be used when calling Win32 api calls
 | ||||
| #ifdef _WIN32 | ||||
| 
 | ||||
| std::string ConvertWStringToUTF8(const std::wstring &wstr); | ||||
| std::string ConvertWStringToUTF8(const wchar_t *wstr); | ||||
| void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source); | ||||
| std::wstring ConvertUTF8ToWString(const std::string &source); | ||||
| 
 | ||||
| #endif | ||||
|  | @ -147,7 +147,7 @@ void RestoreRegisterEvent(int event_type, const char* name, TimedCallback callba | |||
| 
 | ||||
| void UnregisterAllEvents() { | ||||
|     if (first) | ||||
|         PanicAlert("Cannot unregister events with events pending"); | ||||
|         LOG_ERROR(Core_Timing, "Cannot unregister events with events pending"); | ||||
|     event_types.clear(); | ||||
| } | ||||
| 
 | ||||
|  | @ -535,7 +535,7 @@ std::string GetScheduledEventsSummary() { | |||
|     while (event) { | ||||
|         unsigned int t = event->type; | ||||
|         if (t >= event_types.size()) | ||||
|             PanicAlert("Invalid event type"); // %i", t);
 | ||||
|             LOG_ERROR(Core_Timing, "Invalid event type"); // %i", t);
 | ||||
|         const char* name = event_types[event->type].name; | ||||
|         if (!name) | ||||
|             name = "[unknown]"; | ||||
|  |  | |||
|  | @ -7,6 +7,7 @@ | |||
| #include <vector> | ||||
| 
 | ||||
| #include "common/common.h" | ||||
| #include "common/math_util.h" | ||||
| #include "common/thread_queue_list.h" | ||||
| 
 | ||||
| #include "core/arm/arm_interface.h" | ||||
|  | @ -339,7 +340,7 @@ static void DebugThreadQueue() { | |||
| ResultVal<SharedPtr<Thread>> Thread::Create(std::string name, VAddr entry_point, s32 priority, | ||||
|         u32 arg, s32 processor_id, VAddr stack_top) { | ||||
|     if (priority < THREADPRIO_HIGHEST || priority > THREADPRIO_LOWEST) { | ||||
|         s32 new_priority = CLAMP(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         s32 new_priority = MathUtil::Clamp<s32>(priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | ||||
|             name.c_str(), priority, new_priority); | ||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||
|  | @ -387,7 +388,7 @@ static void ClampPriority(const Thread* thread, s32* priority) { | |||
|     if (*priority < THREADPRIO_HIGHEST || *priority > THREADPRIO_LOWEST) { | ||||
|         DEBUG_ASSERT_MSG(false, "Application passed an out of range priority. An error should be returned."); | ||||
| 
 | ||||
|         s32 new_priority = CLAMP(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         s32 new_priority = MathUtil::Clamp<s32>(*priority, THREADPRIO_HIGHEST, THREADPRIO_LOWEST); | ||||
|         LOG_WARNING(Kernel_SVC, "(name=%s): invalid priority=%d, clamping to %d", | ||||
|                     thread->name.c_str(), *priority, new_priority); | ||||
|         // TODO(bunnei): Clamping to a valid priority is not necessarily correct behavior... Confirm
 | ||||
|  |  | |||
|  | @ -34,13 +34,6 @@ namespace GPU { | |||
| // MMIO region 0x1EFxxxxx
 | ||||
| struct Regs { | ||||
| 
 | ||||
| // helper macro to properly align structure members.
 | ||||
| // Calling INSERT_PADDING_WORDS will add a new member variable with a name like "pad121",
 | ||||
| // depending on the current source line to make sure variable names are unique.
 | ||||
| #define INSERT_PADDING_WORDS_HELPER1(x, y) x ## y | ||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | ||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)] | ||||
| 
 | ||||
| // helper macro to make sure the defined structures are of the expected size.
 | ||||
| #if defined(_MSC_VER) | ||||
| // TODO: MSVC does not support using sizeof() on non-static data members even though this
 | ||||
|  | @ -238,10 +231,6 @@ struct Regs { | |||
| 
 | ||||
|     INSERT_PADDING_WORDS(0x9c3); | ||||
| 
 | ||||
| #undef INSERT_PADDING_WORDS_HELPER1 | ||||
| #undef INSERT_PADDING_WORDS_HELPER2 | ||||
| #undef INSERT_PADDING_WORDS | ||||
| 
 | ||||
|     static inline size_t NumIds() { | ||||
|         return sizeof(Regs) / sizeof(u32); | ||||
|     } | ||||
|  |  | |||
|  | @ -39,13 +39,6 @@ namespace Pica { | |||
| 
 | ||||
| struct Regs { | ||||
| 
 | ||||
| // helper macro to properly align structure members.
 | ||||
| // Calling INSERT_PADDING_WORDS will add a new member variable with a name like "pad121",
 | ||||
| // depending on the current source line to make sure variable names are unique.
 | ||||
| #define INSERT_PADDING_WORDS_HELPER1(x, y) x ## y | ||||
| #define INSERT_PADDING_WORDS_HELPER2(x, y) INSERT_PADDING_WORDS_HELPER1(x, y) | ||||
| #define INSERT_PADDING_WORDS(num_words) u32 INSERT_PADDING_WORDS_HELPER2(pad, __LINE__)[(num_words)]; | ||||
| 
 | ||||
|     INSERT_PADDING_WORDS(0x10); | ||||
| 
 | ||||
|     u32 trigger_irq; | ||||
|  | @ -709,10 +702,6 @@ struct Regs { | |||
| 
 | ||||
|     INSERT_PADDING_WORDS(0x22); | ||||
| 
 | ||||
| #undef INSERT_PADDING_WORDS_HELPER1 | ||||
| #undef INSERT_PADDING_WORDS_HELPER2 | ||||
| #undef INSERT_PADDING_WORDS | ||||
| 
 | ||||
|     // Map register indices to names readable by humans
 | ||||
|     // Used for debugging purposes, so performance is not an issue here
 | ||||
|     static std::string GetCommandName(int index) { | ||||
|  |  | |||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue