28 changed files with 0 additions and 4543 deletions
-
36src/common/src/atomic.h
-
72src/common/src/atomic_gcc.h
-
76src/common/src/atomic_win32.h
-
246src/common/src/common.h
-
118src/common/src/config.cpp
-
345src/common/src/config.h
-
86src/common/src/crc.cpp
-
81src/common/src/crc.h
-
451src/common/src/file_utils.cpp
-
90src/common/src/file_utils.h
-
241src/common/src/hash.cpp
-
46src/common/src/hash.h
-
116src/common/src/hash_container.h
-
152src/common/src/log.cpp
-
216src/common/src/log.h
-
91src/common/src/misc_utils.cpp
-
58src/common/src/misc_utils.h
-
135src/common/src/platform.h
-
152src/common/src/std_condition_variable.h
-
354src/common/src/std_mutex.h
-
309src/common/src/std_thread.h
-
46src/common/src/timer.cpp
-
51src/common/src/timer.h
-
119src/common/src/types.h
-
236src/common/src/x86_utils.cpp
-
92src/common/src/x86_utils.h
-
487src/common/src/xml.cpp
-
41src/common/src/xml.h
@ -1,36 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file atomic.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Cross-platform atomic operations |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_ATOMIC_H_ |
|
||||
#define COMMON_ATOMIC_H_ |
|
||||
|
|
||||
#include "platform.h" |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
#include "atomic_win32.h" |
|
||||
#else |
|
||||
#include "atomic_gcc.h" |
|
||||
#endif |
|
||||
|
|
||||
#endif // COMMON_ATOMIC_H_ |
|
||||
@ -1,72 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file atomic_gcc.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-06-28 |
|
||||
* @brief Cross-platform atomic operations - GCC |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_ATOMIC_GCC_H_ |
|
||||
#define COMMON_ATOMIC_GCC_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
inline void AtomicAdd(volatile u32& target, u32 value) { |
|
||||
__sync_add_and_fetch(&target, value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicAnd(volatile u32& target, u32 value) { |
|
||||
__sync_and_and_fetch(&target, value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicDecrement(volatile u32& target) { |
|
||||
__sync_add_and_fetch(&target, -1); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicIncrement(volatile u32& target) { |
|
||||
__sync_add_and_fetch(&target, 1); |
|
||||
} |
|
||||
|
|
||||
inline u32 AtomicLoad(volatile u32& src) { |
|
||||
return src; |
|
||||
} |
|
||||
|
|
||||
inline u32 AtomicLoadAcquire(volatile u32& src) { |
|
||||
u32 result = src; |
|
||||
__asm__ __volatile__ ( "":::"memory" ); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
inline void AtomicOr(volatile u32& target, u32 value) { |
|
||||
__sync_or_and_fetch(&target, value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicStore(volatile u32& dest, u32 value) { |
|
||||
dest = value; |
|
||||
} |
|
||||
|
|
||||
inline void AtomicStoreRelease(volatile u32& dest, u32 value) { |
|
||||
__sync_lock_test_and_set(&dest, value); |
|
||||
} |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
#endif // COMMON_ATOMIC_GCC_H_ |
|
||||
@ -1,76 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file atomic_win32.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-06-28 |
|
||||
* @brief Cross-platform atomic operations - Windows/Visual C++ |
|
||||
* @remark Taken from Dolphin Emulator (http://code.google.com/p/dolphin-emu/) |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_ATOMIC_WIN32_H_ |
|
||||
#define COMMON_ATOMIC_WIN32_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
|
|
||||
#include <intrin.h> |
|
||||
#include <Windows.h> |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
inline void AtomicAdd(volatile u32& target, u32 value) { |
|
||||
InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicAnd(volatile u32& target, u32 value) { |
|
||||
_InterlockedAnd((volatile LONG*)&target, (LONG)value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicIncrement(volatile u32& target) { |
|
||||
InterlockedIncrement((volatile LONG*)&target); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicDecrement(volatile u32& target) { |
|
||||
InterlockedDecrement((volatile LONG*)&target); |
|
||||
} |
|
||||
|
|
||||
inline u32 AtomicLoad(volatile u32& src) { |
|
||||
return src; |
|
||||
} |
|
||||
|
|
||||
inline u32 AtomicLoadAcquire(volatile u32& src) { |
|
||||
u32 result = src; |
|
||||
_ReadBarrier(); |
|
||||
return result; |
|
||||
} |
|
||||
|
|
||||
inline void AtomicOr(volatile u32& target, u32 value) { |
|
||||
_InterlockedOr((volatile LONG*)&target, (LONG)value); |
|
||||
} |
|
||||
|
|
||||
inline void AtomicStore(volatile u32& dest, u32 value) { |
|
||||
dest = value; |
|
||||
} |
|
||||
inline void AtomicStoreRelease(volatile u32& dest, u32 value) { |
|
||||
_WriteBarrier(); |
|
||||
dest = value; |
|
||||
} |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
#endif // COMMON_ATOMIC_WIN32_H_ |
|
||||
@ -1,246 +0,0 @@ |
|||||
/*! |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* \file common.h |
|
||||
* \author ShizZy <shizzy247@gmail.com> |
|
||||
* \date 2012-02-04 |
|
||||
* \brief Common header for using the common library |
|
||||
* |
|
||||
* \section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_COMMON_H_ |
|
||||
#define COMMON_COMMON_H_ |
|
||||
|
|
||||
#include "platform.h" |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// Preprocessor stuff |
|
||||
|
|
||||
#define GEKKO_QUOTE_INPLACE(x) # x |
|
||||
#define GEKKO_QUOTE(x) GEKKO_QUOTE_INPLACE(x) |
|
||||
#define __FILE__LINE__ __FILE__ "(" GEKKO_QUOTE(__LINE__) ") : " |
|
||||
#define GEKKO_TODO(x) __FILE__LINE__ x "\n" |
|
||||
|
|
||||
#if EMU_PLATFORM == PLATFORM_WINDOWS |
|
||||
|
|
||||
// All inline assembly is x86 right now! |
|
||||
#ifdef EMU_ARCHITECTURE_X86 |
|
||||
#define USE_INLINE_ASM_X86 |
|
||||
#endif // EMU_ARCHITECTURE_X86 |
|
||||
|
|
||||
#pragma warning( disable : 4786 ) //disable the truncated 255 character limit warning for debug identifiers |
|
||||
|
|
||||
#ifdef LEAK_DETECT |
|
||||
#define _CRTDBG_MAP_ALLOC |
|
||||
#define _INC_MALLOC |
|
||||
#include <stdlib.h> |
|
||||
#include <crtdbg.h> |
|
||||
#endif // LEAK_DETECT |
|
||||
|
|
||||
#define TODO( x ) message( __FILE__LINE__" TODO : " #x "\n" ) |
|
||||
#define todo( x ) message( __FILE__LINE__" TODO : " #x "\n" ) |
|
||||
|
|
||||
#endif // PLATFORM_WINDOWS |
|
||||
|
|
||||
#define E_OK 0 |
|
||||
#define E_ERR 1 |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// Includes |
|
||||
#include <xmmintrin.h> |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// C Includes |
|
||||
#include <cmath> |
|
||||
#include <cstdarg> |
|
||||
#include <cstdio> |
|
||||
#include <cstdlib> |
|
||||
#include <ctime> |
|
||||
#include <csignal> |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// C++ Includes |
|
||||
#include <algorithm> |
|
||||
#include <fstream> |
|
||||
#include <iostream> |
|
||||
#include <map> |
|
||||
#include <sstream> |
|
||||
#include <string> |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// OS-Specific Includes |
|
||||
#if EMU_PLATFORM == PLATFORM_WINDOWS |
|
||||
#include <direct.h> |
|
||||
#include <windows.h> |
|
||||
#include <commctrl.h> |
|
||||
#include <commdlg.h> |
|
||||
#include <shlwapi.h> |
|
||||
#include <shlobj.h> |
|
||||
#endif |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// Big Endian bit Access (Bits numbered ascending from leftmost to rightmost) |
|
||||
#define BIT_0 0x80000000 |
|
||||
#define BIT_1 0x40000000 |
|
||||
#define BIT_2 0x20000000 |
|
||||
#define BIT_3 0x10000000 |
|
||||
#define BIT_4 0x8000000 |
|
||||
#define BIT_5 0x4000000 |
|
||||
#define BIT_6 0x2000000 |
|
||||
#define BIT_7 0x1000000 |
|
||||
#define BIT_8 0x800000 |
|
||||
#define BIT_9 0x400000 |
|
||||
#define BIT_10 0x200000 |
|
||||
#define BIT_11 0x100000 |
|
||||
#define BIT_12 0x80000 |
|
||||
#define BIT_13 0x40000 |
|
||||
#define BIT_14 0x20000 |
|
||||
#define BIT_15 0x10000 |
|
||||
#define BIT_16 0x8000 |
|
||||
#define BIT_17 0x4000 |
|
||||
#define BIT_18 0x2000 |
|
||||
#define BIT_19 0x1000 |
|
||||
#define BIT_20 0x800 |
|
||||
#define BIT_21 0x400 |
|
||||
#define BIT_22 0x200 |
|
||||
#define BIT_23 0x100 |
|
||||
#define BIT_24 0x80 |
|
||||
#define BIT_25 0x40 |
|
||||
#define BIT_26 0x20 |
|
||||
#define BIT_27 0x10 |
|
||||
#define BIT_28 0x8 |
|
||||
#define BIT_29 0x4 |
|
||||
#define BIT_30 0x2 |
|
||||
#define BIT_31 0x1 |
|
||||
|
|
||||
#define SIGNED_BIT8 ((u8) 1 << 7) |
|
||||
#define SIGNED_BIT16 ((u16) 1 << 15) |
|
||||
#define SIGNED_BIT32 ((u32) 1 << 31) |
|
||||
#define SIGNED_BIT64 ((u64) 1 << 63) |
|
||||
|
|
||||
// A macro to disallow the copy constructor and operator= functions |
|
||||
// This should be used in the private: declarations for a class |
|
||||
#define DISALLOW_COPY_AND_ASSIGN(TypeName) \ |
|
||||
TypeName(const TypeName&); \ |
|
||||
void operator=(const TypeName&) |
|
||||
|
|
||||
#ifdef _DEBUG |
|
||||
#ifndef _DEBUGSPEED |
|
||||
#define DEBUG_EMU |
|
||||
#define DEBUG_GX |
|
||||
#endif |
|
||||
#endif |
|
||||
|
|
||||
#ifdef DEBUG_EMU |
|
||||
#define ASSERT_T(cond,str) if((cond)) printf("#!\tERROR: ASSERTION FAILED: %s !\n", str); |
|
||||
#define ASSERT_F(cond,str) if(!(cond)) printf("#!\tERROR: ASSERTION FAILED: %s !\n", str); |
|
||||
#else |
|
||||
#define ASSERT_T(cond,str) |
|
||||
#define ASSERT_F(cond,str) |
|
||||
#endif |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
void DisplayError (char * Message, ...); |
|
||||
|
|
||||
#ifdef _MSC_VER |
|
||||
# ifdef LEAK_DETECT |
|
||||
# undef malloc |
|
||||
# define DEBUG_NEW new(_NORMAL_BLOCK,__FILE__, __LINE__) |
|
||||
# define new DEBUG_NEW |
|
||||
# define malloc(s) _malloc_dbg(s,_NORMAL_BLOCK,__FILE__,__LINE__) |
|
||||
# define realloc(p, s) _realloc_dbg(p, s, _NORMAL_BLOCK, __FILE__, __LINE__) |
|
||||
# define free(p) _free_dbg(p, _NORMAL_BLOCK) |
|
||||
# endif |
|
||||
# define U64(a) a ## ui64 |
|
||||
# define S64(a) a ## si64 |
|
||||
#else //gcc |
|
||||
# define U64(a) a ## ull |
|
||||
# define S64(a) a ## sll |
|
||||
#endif |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
#include "types.h" |
|
||||
#include "log.h" |
|
||||
#include "atomic.h" |
|
||||
#include "misc_utils.h" |
|
||||
#include "x86_utils.h" |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
|
|
||||
__inline static s16 toSHORT(u16 x) |
|
||||
{ |
|
||||
return *(s16*)&x; |
|
||||
} |
|
||||
|
|
||||
__inline static f32 toFLOAT(u32 x) |
|
||||
{ |
|
||||
return *(f32*)&x; |
|
||||
} |
|
||||
|
|
||||
__inline static f32 toFLOATS(s32 x) |
|
||||
{ |
|
||||
return *(f32*)&x; |
|
||||
} |
|
||||
|
|
||||
__inline static f64 toDOUBLE(u64 x) |
|
||||
{ |
|
||||
return *(f64*)&x; |
|
||||
} |
|
||||
|
|
||||
typedef void(*optable)(void); |
|
||||
typedef void(EMU_FASTCALL *hwtable)(u32, u32*); |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////// |
|
||||
// Fast Macros |
|
||||
|
|
||||
#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))) |
|
||||
|
|
||||
__inline static u32 BSWAP24(u32 x) |
|
||||
{ |
|
||||
return (((x & 0xff0000) >> 16) | (x & 0xff00) | ((x & 0xff) << 16)); |
|
||||
} |
|
||||
|
|
||||
#if _MSC_VER > 1200 |
|
||||
|
|
||||
#define BSWAP16(x) _byteswap_ushort(x) |
|
||||
#define BSWAP32(x) _byteswap_ulong(x) |
|
||||
#define BSWAP64(x) _byteswap_uint64(x) |
|
||||
|
|
||||
#else |
|
||||
__inline static u16 BSWAP16(u16 x) |
|
||||
{ |
|
||||
return ((x)>>8) | ((x)<<8); |
|
||||
} |
|
||||
|
|
||||
__inline static u32 BSWAP32(u32 x) |
|
||||
{ |
|
||||
return (BSWAP16((x)&0xffff)<<16) | (BSWAP16((x)>>16)); |
|
||||
} |
|
||||
|
|
||||
__inline static u64 BSWAP64(u64 x) |
|
||||
{ |
|
||||
return (u64)(((u64)BSWAP32((u32)(x&0xffffffff)))<<32) | (BSWAP32((u32)(x>>32))); |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
|
|
||||
#endif // COMMON_COMMON_H_ |
|
||||
@ -1,118 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file config.cpp |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-19 |
|
||||
* @brief Emulator configuration class - all config settings stored here |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "common.h"
|
|
||||
#include "config.h"
|
|
||||
#include "xml.h"
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
Config* g_config; |
|
||||
|
|
||||
Config::Config() { |
|
||||
ResolutionType default_res; |
|
||||
RendererConfig default_renderer_config; |
|
||||
|
|
||||
default_renderer_config.enable_wireframe = false; |
|
||||
default_renderer_config.enable_shaders = true; |
|
||||
default_renderer_config.enable_texture_dumping = false; |
|
||||
default_renderer_config.enable_textures = true; |
|
||||
default_renderer_config.anti_aliasing_mode = 0; |
|
||||
default_renderer_config.anistropic_filtering_mode = 0; |
|
||||
|
|
||||
default_res.width = 640; |
|
||||
default_res.height = 480; |
|
||||
|
|
||||
set_program_dir("", MAX_PATH); |
|
||||
set_enable_multicore(true); |
|
||||
set_enable_idle_skipping(false); |
|
||||
set_enable_hle(true); |
|
||||
set_enable_auto_boot(true); |
|
||||
set_enable_cheats(false); |
|
||||
set_default_boot_file("", MAX_PATH); |
|
||||
memset(dvd_image_paths_, 0, sizeof(dvd_image_paths_)); |
|
||||
set_enable_show_fps(true); |
|
||||
set_enable_dump_opcode0(false); |
|
||||
set_enable_pause_on_unknown_opcode(true); |
|
||||
set_enable_dump_gcm_reads(false); |
|
||||
set_enable_ipl(false); |
|
||||
set_powerpc_core(CPU_INTERPRETER); |
|
||||
set_powerpc_frequency(486); |
|
||||
|
|
||||
memset(renderer_config_, 0, sizeof(renderer_config_)); |
|
||||
set_renderer_config(RENDERER_OPENGL_3, default_renderer_config); |
|
||||
set_current_renderer(RENDERER_OPENGL_3); |
|
||||
|
|
||||
set_enable_fullscreen(false); |
|
||||
set_window_resolution(default_res); |
|
||||
set_fullscreen_resolution(default_res); |
|
||||
|
|
||||
memset(controller_ports_, 0, sizeof(controller_ports_)); |
|
||||
memset(mem_slots_, 0, sizeof(mem_slots_)); |
|
||||
|
|
||||
memset(patches_, 0, sizeof(patches_)); |
|
||||
memset(cheats_, 0, sizeof(patches_)); |
|
||||
} |
|
||||
|
|
||||
Config::~Config() { |
|
||||
} |
|
||||
|
|
||||
ConfigManager::ConfigManager() { |
|
||||
set_program_dir("", MAX_PATH); |
|
||||
} |
|
||||
|
|
||||
ConfigManager::~ConfigManager() { |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Reload a game-specific configuration |
|
||||
* @param id Game id (to load game specific configuration) |
|
||||
*/ |
|
||||
void ConfigManager::ReloadGameConfig(const char* id) { |
|
||||
char full_filename[MAX_PATH]; |
|
||||
sprintf(full_filename, "user/games/%s.xml", id); |
|
||||
common::LoadXMLConfig(*g_config, full_filename); |
|
||||
} |
|
||||
|
|
||||
/// Reload the userconfig file
|
|
||||
void ConfigManager::ReloadUserConfig() { |
|
||||
common::LoadXMLConfig(*g_config, "userconf.xml"); |
|
||||
} |
|
||||
|
|
||||
/// Reload the sysconfig file
|
|
||||
void ConfigManager::ReloadSysConfig() { |
|
||||
common::LoadXMLConfig(*g_config, "sysconf.xml"); |
|
||||
} |
|
||||
|
|
||||
/// Reload all configurations
|
|
||||
void ConfigManager::ReloadConfig(const char* game_id) { |
|
||||
delete g_config; |
|
||||
g_config = new Config(); |
|
||||
g_config->set_program_dir(program_dir_, MAX_PATH); |
|
||||
ReloadSysConfig(); |
|
||||
ReloadUserConfig(); |
|
||||
ReloadGameConfig(game_id); |
|
||||
} |
|
||||
|
|
||||
} // namspace
|
|
||||
@ -1,345 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file config.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Emulator configuration class - all config settings stored here |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_CONFIG_H_ |
|
||||
#define COMMON_CONFIG_H_ |
|
||||
|
|
||||
#include "common.h" |
|
||||
|
|
||||
#define MAX_SEARCH_PATHS 16 ///< Maximum paths to search for files in |
|
||||
|
|
||||
/// If you need more than this... you're just lazy ;-) |
|
||||
#define MAX_PATCHES_PER_GAME 128 ///< Maximum patches allowed per game |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/// Class for storing emulator configuration(s) |
|
||||
class Config { |
|
||||
public: |
|
||||
Config(); |
|
||||
~Config(); |
|
||||
|
|
||||
/// Struct used for defining game-specific patches |
|
||||
struct Patch { |
|
||||
u32 address; ///< Address to patch |
|
||||
u32 data; ///< Data to write at the specified address |
|
||||
}; |
|
||||
|
|
||||
/// Struct used for configuring what is inserted in a memory slot |
|
||||
struct MemSlot { |
|
||||
u8 device; ///< Memory slot device (0 - memcard) |
|
||||
bool enable; ///< Enable (plugged in?) |
|
||||
}; |
|
||||
|
|
||||
enum Control { |
|
||||
BUTTON_A = 0, |
|
||||
BUTTON_B, |
|
||||
BUTTON_X, |
|
||||
BUTTON_Y, |
|
||||
TRIGGER_L, |
|
||||
TRIGGER_R, |
|
||||
BUTTON_Z, |
|
||||
BUTTON_START, |
|
||||
ANALOG_UP, |
|
||||
ANALOG_DOWN, |
|
||||
ANALOG_LEFT, |
|
||||
ANALOG_RIGHT, |
|
||||
C_UP, |
|
||||
C_DOWN, |
|
||||
C_LEFT, |
|
||||
C_RIGHT, |
|
||||
DPAD_UP, |
|
||||
DPAD_DOWN, |
|
||||
DPAD_LEFT, |
|
||||
DPAD_RIGHT, |
|
||||
NUM_CONTROLS |
|
||||
}; |
|
||||
|
|
||||
/// Struct used for defining a keyboard configuration for a GameCube controller |
|
||||
/// Reads/Writes from/to members should be atomic |
|
||||
struct KeyboardController { |
|
||||
bool enable; ///< Is the keyboard configation enabled? |
|
||||
int key_code[NUM_CONTROLS]; |
|
||||
}; |
|
||||
|
|
||||
/// Struct used for defining a joypad configuration for a GameCube controller |
|
||||
/// We'll make another struct in case the user wants seperate joypad config |
|
||||
struct JoypadController { |
|
||||
bool enable; ///< Is the joypad configation enabled? |
|
||||
int key_code[NUM_CONTROLS]; |
|
||||
}; |
|
||||
|
|
||||
/// Struct used for configuring what is inserted in a controller port |
|
||||
typedef struct { |
|
||||
u8 device; ///< Controller port device (0 - controller) |
|
||||
bool enable; ///< Enable (plugged in?) |
|
||||
KeyboardController keys; ///< Keyboard configuration for controller (if used) |
|
||||
JoypadController pads; ///< Joypad configuration for controller (if used) |
|
||||
} ControllerPort; |
|
||||
|
|
||||
/// Enum for supported CPU types |
|
||||
enum CPUCoreType { |
|
||||
CPU_NULL = 0, ///< No CPU core |
|
||||
CPU_INTERPRETER, ///< Interpreter CPU core |
|
||||
CPU_DYNAREC, ///< Dynamic recompiler CPU core |
|
||||
NUMBER_OF_CPU_CONFIGS |
|
||||
}; |
|
||||
|
|
||||
/// Struct used for defining a renderer configuration |
|
||||
struct RendererConfig { |
|
||||
bool enable_wireframe; |
|
||||
bool enable_shaders; |
|
||||
bool enable_texture_dumping; |
|
||||
bool enable_textures; |
|
||||
int anti_aliasing_mode; |
|
||||
int anistropic_filtering_mode; |
|
||||
} ; |
|
||||
|
|
||||
/// Struct used for configuring a screen resolution |
|
||||
struct ResolutionType { |
|
||||
int width; |
|
||||
int height; |
|
||||
}; |
|
||||
|
|
||||
/// Enum for supported video cores |
|
||||
enum RendererType { |
|
||||
RENDERER_NULL, ///< No video core |
|
||||
RENDERER_OPENGL_2, ///< OpenGL 2.0 core |
|
||||
RENDERER_OPENGL_3, ///< OpenGL 3.0 core (not implemented) |
|
||||
RENDERER_DIRECTX9, ///< DirectX9 core (not implemented) |
|
||||
RENDERER_DIRECTX10, ///< DirectX10 core (not implemented) |
|
||||
RENDERER_DIRECTX11, ///< DirectX11 core (not implemented) |
|
||||
RENDERER_SOFTWARE, ///< Software core (not implemented) |
|
||||
RENDERER_HARDWARE, ///< Hardware core (not implemented- this would be a driver) |
|
||||
NUMBER_OF_VIDEO_CONFIGS |
|
||||
}; |
|
||||
|
|
||||
char* program_dir() { return program_dir_; } |
|
||||
void set_program_dir(const char* val, size_t size) { strcpy(program_dir_, val); } |
|
||||
|
|
||||
bool enable_multicore() { return enable_multicore_; } |
|
||||
bool enable_idle_skipping() {return enable_idle_skipping_; } |
|
||||
bool enable_hle() { return enable_hle_; } |
|
||||
bool enable_auto_boot() { return enable_auto_boot_; } |
|
||||
bool enable_cheats() { return enable_cheats_; } |
|
||||
void set_enable_multicore(bool val) { enable_multicore_ = val; } |
|
||||
void set_enable_idle_skipping(bool val) {enable_idle_skipping_ = val; } |
|
||||
void set_enable_hle(bool val) { enable_hle_ = val; } |
|
||||
void set_enable_auto_boot(bool val) { enable_auto_boot_ = val; } |
|
||||
void set_enable_cheats(bool val) { enable_cheats_ = val; } |
|
||||
|
|
||||
char* default_boot_file() { return default_boot_file_; } |
|
||||
char* dvd_image_path(int path) { return dvd_image_paths_[path]; } |
|
||||
void set_default_boot_file(const char* val, size_t size) { strcpy(default_boot_file_, val); } |
|
||||
void set_dvd_image_path(int path, char* val, size_t size) { strcpy(dvd_image_paths_[path], val); } |
|
||||
|
|
||||
bool enable_show_fps() { return enable_show_fps_; } |
|
||||
bool enable_dump_opcode0() { return enable_dump_opcode0_; } |
|
||||
bool enable_pause_on_unknown_opcode() { return enable_pause_on_unknown_opcode_; } |
|
||||
bool enable_dump_gcm_reads() { return enable_dump_gcm_reads_; } |
|
||||
void set_enable_show_fps(bool val) { enable_show_fps_ = val; } |
|
||||
void set_enable_dump_opcode0(bool val) { enable_dump_opcode0_ = val; } |
|
||||
void set_enable_pause_on_unknown_opcode(bool val) { enable_pause_on_unknown_opcode_ = val; } |
|
||||
void set_enable_dump_gcm_reads(bool val) { enable_dump_gcm_reads_ = val; } |
|
||||
|
|
||||
bool enable_ipl() { return enable_ipl_; } |
|
||||
void set_enable_ipl(bool val) { enable_ipl_ = val; } |
|
||||
|
|
||||
Patch patches(int patch) { return patches_[patch]; } |
|
||||
Patch cheats(int cheat) { return cheats_[cheat]; } |
|
||||
void set_patches(int patch, Patch val) { patches_[patch] = val; } |
|
||||
void set_cheats(int cheat, Patch val) { cheats_[cheat] = val; } |
|
||||
|
|
||||
CPUCoreType powerpc_core() { return powerpc_core_; } |
|
||||
void set_powerpc_core(CPUCoreType val) { powerpc_core_ = val; } |
|
||||
|
|
||||
int powerpc_frequency() { return powerpc_frequency_; } |
|
||||
void set_powerpc_frequency(int val) { powerpc_frequency_ = val; } |
|
||||
|
|
||||
RendererType current_renderer() { return current_renderer_; } |
|
||||
void set_current_renderer(RendererType val) { current_renderer_ = val; } |
|
||||
|
|
||||
RendererConfig renderer_config(RendererType val) { return renderer_config_[val]; } |
|
||||
RendererConfig current_renderer_config() { return renderer_config_[current_renderer_]; } |
|
||||
void set_renderer_config(RendererType renderer, RendererConfig config) { |
|
||||
renderer_config_[renderer] = config; |
|
||||
} |
|
||||
|
|
||||
bool enable_fullscreen() { return enable_fullscreen_; } |
|
||||
void set_enable_fullscreen(bool val) { enable_fullscreen_ = val; } |
|
||||
|
|
||||
ResolutionType window_resolution() { return window_resolution_; } |
|
||||
ResolutionType fullscreen_resolution() { return fullscreen_resolution_; } |
|
||||
void set_window_resolution(ResolutionType val) { window_resolution_ = val; } |
|
||||
void set_fullscreen_resolution(ResolutionType val) { fullscreen_resolution_ = val; } |
|
||||
|
|
||||
// TODO: Should be const, but pending removal of some gekko_qt hacks |
|
||||
/*const */ControllerPort& controller_ports(int port) { return controller_ports_[port]; } |
|
||||
void set_controller_ports(int port, ControllerPort val) { controller_ports_[port] = val; } |
|
||||
|
|
||||
MemSlot mem_slots(int slot) { return mem_slots_[slot]; } |
|
||||
void set_mem_slots(int slot, MemSlot val) { mem_slots_[slot] = val; } |
|
||||
|
|
||||
/** |
|
||||
* @brief Gets a RenderType from a string (used from XML) |
|
||||
* @param renderer_str Renderer name string, see XML schema for list |
|
||||
* @return Corresponding RenderType |
|
||||
*/ |
|
||||
static inline RendererType StringToRenderType(const char* renderer_str) { |
|
||||
if (E_OK == _stricmp(renderer_str, "opengl2")) { |
|
||||
return RENDERER_OPENGL_2; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "opengl3")) { |
|
||||
return RENDERER_OPENGL_3; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "directx9")) { |
|
||||
return RENDERER_DIRECTX9; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "directx10")) { |
|
||||
return RENDERER_DIRECTX10; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "directx11")) { |
|
||||
return RENDERER_DIRECTX11; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "software")) { |
|
||||
return RENDERER_SOFTWARE; |
|
||||
} else if (E_OK == _stricmp(renderer_str, "hardware")) { |
|
||||
return RENDERER_HARDWARE; |
|
||||
} else { |
|
||||
return RENDERER_NULL; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @brief Gets the renderer string from the type |
|
||||
* @param renderer Renderer to get string for |
|
||||
* @return Renderer string name |
|
||||
*/ |
|
||||
static std::string RenderTypeToString(RendererType renderer) { |
|
||||
switch (renderer) { |
|
||||
case RENDERER_OPENGL_2: |
|
||||
return "opengl2"; |
|
||||
case RENDERER_OPENGL_3: |
|
||||
return "opengl3"; |
|
||||
case RENDERER_DIRECTX9: |
|
||||
return "directx9"; |
|
||||
case RENDERER_DIRECTX10: |
|
||||
return "directx10"; |
|
||||
case RENDERER_DIRECTX11: |
|
||||
return "directx11"; |
|
||||
case RENDERER_SOFTWARE: |
|
||||
return "software"; |
|
||||
case RENDERER_HARDWARE: |
|
||||
return "hardware"; |
|
||||
} |
|
||||
return "null"; |
|
||||
} |
|
||||
|
|
||||
/** |
|
||||
* @brief Gets the CPU string from the type |
|
||||
* @param cpu CPU to get string for |
|
||||
* @param cpu_str String result |
|
||||
* @param size Max size to write to string |
|
||||
*/ |
|
||||
static std::string CPUCoreTypeToString(CPUCoreType cpu) { |
|
||||
switch (cpu) { |
|
||||
case CPU_INTERPRETER: |
|
||||
return "interpreter"; |
|
||||
case CPU_DYNAREC: |
|
||||
return "dynarec"; |
|
||||
} |
|
||||
return "null"; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
char program_dir_[MAX_PATH]; |
|
||||
|
|
||||
bool enable_multicore_; |
|
||||
bool enable_idle_skipping_; |
|
||||
bool enable_hle_; |
|
||||
bool enable_auto_boot_; |
|
||||
bool enable_cheats_; |
|
||||
|
|
||||
char default_boot_file_[MAX_PATH]; |
|
||||
char dvd_image_paths_[MAX_SEARCH_PATHS][MAX_PATH]; |
|
||||
|
|
||||
bool enable_show_fps_; |
|
||||
bool enable_dump_opcode0_; |
|
||||
bool enable_pause_on_unknown_opcode_; |
|
||||
bool enable_dump_gcm_reads_; |
|
||||
|
|
||||
bool enable_ipl_; |
|
||||
|
|
||||
Patch patches_[MAX_PATCHES_PER_GAME]; |
|
||||
Patch cheats_[MAX_PATCHES_PER_GAME]; |
|
||||
|
|
||||
CPUCoreType powerpc_core_; |
|
||||
|
|
||||
int powerpc_frequency_; |
|
||||
|
|
||||
bool enable_fullscreen_; |
|
||||
|
|
||||
RendererType current_renderer_; |
|
||||
|
|
||||
ResolutionType window_resolution_; |
|
||||
ResolutionType fullscreen_resolution_; |
|
||||
|
|
||||
RendererConfig renderer_config_[NUMBER_OF_VIDEO_CONFIGS]; |
|
||||
|
|
||||
MemSlot mem_slots_[2]; |
|
||||
ControllerPort controller_ports_[4]; |
|
||||
|
|
||||
DISALLOW_COPY_AND_ASSIGN(Config); |
|
||||
}; |
|
||||
|
|
||||
class ConfigManager { |
|
||||
public: |
|
||||
ConfigManager(); |
|
||||
~ConfigManager(); |
|
||||
|
|
||||
/** |
|
||||
* @brief Reload a game-specific configuration |
|
||||
* @param id Game id (to load game specific configuration) |
|
||||
*/ |
|
||||
void ReloadGameConfig(const char* id); |
|
||||
|
|
||||
/// Reload the userconfig file |
|
||||
void ReloadUserConfig(); |
|
||||
|
|
||||
// Reload the sysconfig file |
|
||||
void ReloadSysConfig(); |
|
||||
|
|
||||
/// Reload all configurations |
|
||||
void ReloadConfig(const char* game_id); |
|
||||
|
|
||||
char* program_dir() { return program_dir_; } |
|
||||
|
|
||||
void set_program_dir(const char* val, size_t size) { strcpy(program_dir_, val); } |
|
||||
|
|
||||
private: |
|
||||
char program_dir_[MAX_PATH]; ///< Program directory, used for loading config files |
|
||||
|
|
||||
DISALLOW_COPY_AND_ASSIGN(ConfigManager); |
|
||||
}; |
|
||||
|
|
||||
extern Config* g_config; ///< Global configuration for emulator |
|
||||
|
|
||||
} // namspace |
|
||||
|
|
||||
#endif // COMMON_CONFIG_H_ |
|
||||
@ -1,86 +0,0 @@ |
|||||
#include "common.h"
|
|
||||
#include "crc.h"
|
|
||||
|
|
||||
u32 crc32_table[4][256]; |
|
||||
|
|
||||
u32 Reflect(u32 ref, u8 Count) |
|
||||
{ |
|
||||
u32 value = 0; |
|
||||
|
|
||||
// Swap bit 0 for bit 7
|
|
||||
// bit 1 for bit 6, etc.
|
|
||||
for(int i = 1; i < (Count + 1); i++) |
|
||||
{ |
|
||||
if(ref & 1) |
|
||||
value |= 1 << (Count - i); |
|
||||
ref >>= 1; |
|
||||
} |
|
||||
return value; |
|
||||
} |
|
||||
|
|
||||
void Init_CRC32_Table() |
|
||||
{ |
|
||||
// This is the official polynomial used by CRC-32
|
|
||||
// in PKZip, WinZip and Ethernet.
|
|
||||
u32 ulPolynomial = 0x04c11db7; |
|
||||
|
|
||||
// 256 values representing ASCII character codes.
|
|
||||
for(int x = 0; x < 4; x++) |
|
||||
{ |
|
||||
for(int i = 0; i <= 0xFF; i++) |
|
||||
{ |
|
||||
crc32_table[x][i]=Reflect(i, 8) << 24; |
|
||||
for (int j = 0; j < 8; j++) |
|
||||
crc32_table[x][i] = (crc32_table[x][i] << 1) ^ (crc32_table[x][i] & (1 << 31) ? (ulPolynomial + (x * 8)) : 0); |
|
||||
crc32_table[x][i] = Reflect(crc32_table[x][i], 32); |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
u32 GenerateCRC(u8 *StartAddr, u32 len) |
|
||||
{ |
|
||||
u32 ulCRC = -1; |
|
||||
|
|
||||
// Perform the algorithm on each character
|
|
||||
// in the string, using the lookup table values.
|
|
||||
for(; len > 7; len-=8) |
|
||||
{ |
|
||||
ulCRC ^= *(u32 *)StartAddr; |
|
||||
ulCRC = crc32_table[3][((ulCRC) & 0xFF)] ^ |
|
||||
crc32_table[2][((ulCRC >> 8) & 0xFF)] ^ |
|
||||
crc32_table[1][((ulCRC >> 16) & 0xFF)] ^ |
|
||||
crc32_table[0][((ulCRC >> 24))]; |
|
||||
ulCRC ^= *(u32 *)(StartAddr + 4); |
|
||||
ulCRC = crc32_table[3][((ulCRC) & 0xFF)] ^ |
|
||||
crc32_table[2][((ulCRC >> 8) & 0xFF)] ^ |
|
||||
crc32_table[1][((ulCRC >> 16) & 0xFF)] ^ |
|
||||
crc32_table[0][((ulCRC >> 24))]; |
|
||||
StartAddr+=8; |
|
||||
} |
|
||||
|
|
||||
if(len > 3) |
|
||||
{ |
|
||||
ulCRC ^= *(u32 *)StartAddr; |
|
||||
ulCRC = crc32_table[3][((ulCRC) & 0xFF)] ^ |
|
||||
crc32_table[2][((ulCRC >> 8) & 0xFF)] ^ |
|
||||
crc32_table[1][((ulCRC >> 16) & 0xFF)] ^ |
|
||||
crc32_table[0][((ulCRC >> 24))]; |
|
||||
StartAddr+=4; |
|
||||
len -= 4; |
|
||||
} |
|
||||
|
|
||||
switch(len) |
|
||||
{ |
|
||||
case 3: |
|
||||
ulCRC = crc32_table[0][(ulCRC & 0xFF) ^ *StartAddr] ^ (ulCRC >> 8); |
|
||||
StartAddr++; |
|
||||
case 2: |
|
||||
ulCRC = crc32_table[0][(ulCRC & 0xFF) ^ *StartAddr] ^ (ulCRC >> 8); |
|
||||
StartAddr++; |
|
||||
case 1: |
|
||||
ulCRC = crc32_table[0][(ulCRC & 0xFF) ^ *StartAddr] ^ (ulCRC >> 8); |
|
||||
StartAddr++; |
|
||||
} |
|
||||
|
|
||||
return ulCRC; |
|
||||
} |
|
||||
@ -1,81 +0,0 @@ |
|||||
#ifndef COMMON_CRC_H_ |
|
||||
#define COMMON_CRC_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
#include "platform.h" |
|
||||
|
|
||||
#define CRC_ROTL(crc) crc32_table[3][((crc) & 0xFF)] ^ crc32_table[2][((crc >> 8) & 0xFF)] ^ \ |
|
||||
crc32_table[1][((crc >> 16) & 0xFF)] ^ crc32_table[0][((crc >> 24))] |
|
||||
|
|
||||
// Some definitions for using the X86 CRC32 instruction on different platforms. Keep in mind, you |
|
||||
// should check for X86/X64 architecture support before using these, as well as for SSE 4.2 (see the |
|
||||
// x86_utils module). |
|
||||
|
|
||||
#if defined(EMU_ARCHITECTURE_X86) || defined(EMU_ARCHITECTURE_X64) |
|
||||
|
|
||||
#if EMU_PLATFORM == PLATFORM_WINDOWS |
|
||||
|
|
||||
#include <nmmintrin.h> |
|
||||
|
|
||||
#ifdef EMU_ARCHITECTURE_X64 |
|
||||
static inline u64 InlineCrc32_U64(u64 crc, u64 value) { |
|
||||
return _mm_crc32_u64(crc, value); |
|
||||
} |
|
||||
#endif |
|
||||
static inline u32 InlineCrc32_U32(u32 crc, u64 value) { |
|
||||
return _mm_crc32_u32(crc, static_cast<u32>(value)); |
|
||||
} |
|
||||
|
|
||||
static inline u32 InlineCrc32_U8(u32 crc, u8 value) { |
|
||||
return _mm_crc32_u8(crc, value); |
|
||||
} |
|
||||
|
|
||||
#elif GCC_VERSION_AVAILABLE(4, 5) && defined(__SSE4_2__) |
|
||||
|
|
||||
extern inline unsigned int __attribute__(( |
|
||||
__gnu_inline__, __always_inline__, __artificial__)) |
|
||||
InlineCrc32_U8(unsigned int __C, unsigned char __V) { |
|
||||
return __builtin_ia32_crc32qi(__C, __V); |
|
||||
} |
|
||||
#ifdef EMU_ARCHITECTURE_X64 |
|
||||
extern inline unsigned long long __attribute__(( |
|
||||
__gnu_inline__, __always_inline__, __artificial__)) |
|
||||
InlineCrc32_U64(unsigned long long __C, unsigned long long __V) { |
|
||||
return __builtin_ia32_crc32di(__C, __V); |
|
||||
} |
|
||||
#else |
|
||||
extern inline unsigned int __attribute__(( |
|
||||
__gnu_inline__, __always_inline__, __artificial__)) |
|
||||
InlineCrc32_U32(unsigned int __C, unsigned int __V) { |
|
||||
return __builtin_ia32_crc32si (__C, __V); |
|
||||
} |
|
||||
#endif // EMU_ARCHITECTURE_X64 |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
// GCC 4.4.x and earlier: use inline asm, or msse4.2 flag not set |
|
||||
|
|
||||
static inline u64 InlineCrc32_U64(u64 crc, u64 value) { |
|
||||
asm("crc32q %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value)); |
|
||||
return crc; |
|
||||
} |
|
||||
|
|
||||
static inline u32 InlineCrc32_U32(u32 crc, u64 value) { |
|
||||
asm("crc32l %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value)); |
|
||||
return crc; |
|
||||
} |
|
||||
|
|
||||
static inline u32 InlineCrc32_U8(u32 crc, u8 value) { |
|
||||
asm("crc32b %[value], %[crc]\n" : [crc] "+r" (crc) : [value] "rm" (value)); |
|
||||
return crc; |
|
||||
} |
|
||||
#endif |
|
||||
|
|
||||
#endif // EMU_ARCHITECTURE_X86 or EMU_ARCHITECTURE_X64 |
|
||||
|
|
||||
extern u32 crc32_table[4][256]; |
|
||||
|
|
||||
void Init_CRC32_Table(); |
|
||||
u32 GenerateCRC(u8 *StartAddr, u32 Len); |
|
||||
|
|
||||
#endif // COMMON_CRC_H_ |
|
||||
@ -1,451 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2013 Gekko Emulator |
|
||||
* |
|
||||
* @file file_utils.cpp |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2013-01-27 |
|
||||
* @brief Crossplatform file utility functions |
|
||||
* @remark Borrowed from Dolphin Emulator |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "types.h"
|
|
||||
#include "file_utils.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
|
|
||||
#else
|
|
||||
#include <sys/param.h>
|
|
||||
#include <sys/types.h>
|
|
||||
#include <dirent.h>
|
|
||||
#include <errno.h>
|
|
||||
#include <stdlib.h>
|
|
||||
#include <unistd.h>
|
|
||||
#endif
|
|
||||
|
|
||||
#if defined(__APPLE__)
|
|
||||
#include <CoreFoundation/CFString.h>
|
|
||||
#include <CoreFoundation/CFURL.h>
|
|
||||
#include <CoreFoundation/CFBundle.h>
|
|
||||
#endif
|
|
||||
|
|
||||
#include <fstream>
|
|
||||
#include <sys/stat.h>
|
|
||||
|
|
||||
#ifndef S_ISDIR
|
|
||||
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
|
|
||||
#endif
|
|
||||
|
|
||||
#ifdef BSD4_4
|
|
||||
#define stat64 stat
|
|
||||
#define fstat64 fstat
|
|
||||
#endif
|
|
||||
|
|
||||
#ifdef _MSC_VER
|
|
||||
#define __strdup _strdup
|
|
||||
#define __getcwd _getcwd
|
|
||||
#define __chdir _chdir
|
|
||||
|
|
||||
#define fseeko _fseeki64
|
|
||||
#define ftello _ftelli64
|
|
||||
#define atoll _atoi64
|
|
||||
#define stat64 _stat64
|
|
||||
#define fstat64 _fstat64
|
|
||||
#define fileno _fileno
|
|
||||
|
|
||||
#else
|
|
||||
#define __strdup strdup
|
|
||||
#define __getcwd getcwd
|
|
||||
#define __chdir chdir
|
|
||||
#endif
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
// Remove any ending forward slashes from directory paths
|
|
||||
// Modifies argument.
|
|
||||
static void StripTailDirSlashes(std::string &fname) { |
|
||||
if (fname.length() > 1) { |
|
||||
size_t i = fname.length() - 1; |
|
||||
while (fname[i] == '/') { |
|
||||
fname[i--] = '\0'; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Returns true if file filename exists
|
|
||||
bool FileExists(const std::string &filename) { |
|
||||
struct stat64 file_info; |
|
||||
std::string copy(filename); |
|
||||
StripTailDirSlashes(copy); |
|
||||
return (stat64(copy.c_str(), &file_info) == 0); |
|
||||
} |
|
||||
|
|
||||
// Returns true if filename is a directory
|
|
||||
bool IsDirectory(const std::string &filename) { |
|
||||
struct stat64 file_info; |
|
||||
std::string copy(filename); |
|
||||
StripTailDirSlashes(copy); |
|
||||
if (stat64(copy.c_str(), &file_info) < 0) { |
|
||||
LOG_WARNING(TCOMMON, "IsDirectory: stat failed on %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
return S_ISDIR(file_info.st_mode); |
|
||||
} |
|
||||
|
|
||||
// Deletes a given filename, return true on success
|
|
||||
// Doesn't supports deleting a directory
|
|
||||
bool DeleteFile(const std::string &filename) { |
|
||||
LOG_INFO(TCOMMON, "Delete: file %s", filename.c_str()); |
|
||||
// Return true because we care about the file no
|
|
||||
// being there, not the actual delete.
|
|
||||
if (!FileExists(filename)) { |
|
||||
LOG_WARNING(TCOMMON, "Delete: %s does not exists", filename.c_str()); |
|
||||
return true; |
|
||||
} |
|
||||
// We can't delete a directory
|
|
||||
if (IsDirectory(filename)) { |
|
||||
LOG_WARNING(TCOMMON, "Delete failed: %s is a directory", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
#ifdef _WIN32
|
|
||||
if (!DeleteFile(filename.c_str())) { |
|
||||
LOG_WARNING(TCOMMON, "Delete: DeleteFile failed on %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
#else
|
|
||||
if (unlink(filename.c_str()) == -1) { |
|
||||
LOG_WARNING(TCOMMON, "Delete: unlink failed on %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
#endif
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// Returns true if successful, or path already exists.
|
|
||||
bool CreateDir(const std::string &path) { |
|
||||
LOG_INFO(TCOMMON, "CreateDir: directory %s", path.c_str()); |
|
||||
#ifdef _WIN32
|
|
||||
if (::CreateDirectory(path.c_str(), NULL)) { |
|
||||
return true; |
|
||||
} |
|
||||
DWORD error = GetLastError(); |
|
||||
if (error == ERROR_ALREADY_EXISTS) |
|
||||
{ |
|
||||
LOG_WARNING(TCOMMON, "CreateDir: CreateDirectory failed on %s: already exists", path.c_str()); |
|
||||
return true; |
|
||||
} |
|
||||
LOG_ERROR(TCOMMON, "CreateDir: CreateDirectory failed on %s: %i", path.c_str(), error); |
|
||||
return false; |
|
||||
#else
|
|
||||
if (mkdir(path.c_str(), 0755) == 0) { |
|
||||
return true; |
|
||||
} |
|
||||
int err = errno; |
|
||||
if (err == EEXIST) { |
|
||||
LOG_WARNING(TCOMMON, "CreateDir: mkdir failed on %s: already exists", path.c_str()); |
|
||||
return true; |
|
||||
} |
|
||||
LOG_ERROR(TCOMMON, "CreateDir: mkdir failed on %s: %s", path.c_str(), strerror(err)); |
|
||||
return false; |
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
// Creates the full path of fullPath returns true on success
|
|
||||
bool CreateFullPath(const std::string &fullPath) { |
|
||||
int panicCounter = 100; |
|
||||
LOG_INFO(TCOMMON, "CreateFullPath: path %s", fullPath.c_str()); |
|
||||
|
|
||||
if (FileExists(fullPath)) { |
|
||||
LOG_INFO(TCOMMON, "CreateFullPath: path exists %s", fullPath.c_str()); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
size_t position = 0; |
|
||||
while (1) { |
|
||||
// Find next sub path
|
|
||||
position = fullPath.find('/', position); |
|
||||
|
|
||||
// we're done, yay!
|
|
||||
if (position == fullPath.npos) { |
|
||||
return true; |
|
||||
} |
|
||||
std::string subPath = fullPath.substr(0, position); |
|
||||
if (!IsDirectory(subPath)) CreateDir(subPath); |
|
||||
|
|
||||
// A safety check
|
|
||||
panicCounter--; |
|
||||
if (panicCounter <= 0) { |
|
||||
LOG_ERROR(TCOMMON, "CreateFullPath: directory structure too deep"); |
|
||||
return false; |
|
||||
} |
|
||||
position++; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
// Deletes a directory filename, returns true on success
|
|
||||
bool DeleteDir(const std::string &filename) { |
|
||||
LOG_INFO(TCOMMON, "DeleteDir: directory %s", filename.c_str()); |
|
||||
// check if a directory
|
|
||||
if (!IsDirectory(filename)) { |
|
||||
LOG_ERROR(TCOMMON, "DeleteDir: Not a directory %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
#ifdef _WIN32
|
|
||||
if (::RemoveDirectory(filename.c_str())) |
|
||||
return true; |
|
||||
#else
|
|
||||
if (rmdir(filename.c_str()) == 0) |
|
||||
return true; |
|
||||
#endif
|
|
||||
LOG_ERROR(TCOMMON, "DeleteDir: %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// renames file srcFilename to destFilename, returns true on success
|
|
||||
bool RenameFile(const std::string &srcFilename, const std::string &destFilename) { |
|
||||
LOG_INFO(TCOMMON, "Rename: %s --> %s", |
|
||||
srcFilename.c_str(), destFilename.c_str()); |
|
||||
if (rename(srcFilename.c_str(), destFilename.c_str()) == 0) |
|
||||
return true; |
|
||||
LOG_ERROR(TCOMMON, "Rename: failed %s --> %s", srcFilename.c_str(), destFilename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// copies file srcFilename to destFilename, returns true on success
|
|
||||
bool CopyFile(const std::string &srcFilename, const std::string &destFilename) { |
|
||||
LOG_INFO(TCOMMON, "Copy: %s --> %s", |
|
||||
srcFilename.c_str(), destFilename.c_str()); |
|
||||
#ifdef _WIN32
|
|
||||
if (::CopyFile(srcFilename.c_str(), destFilename.c_str(), FALSE)) |
|
||||
return true; |
|
||||
|
|
||||
LOG_ERROR(TCOMMON, "Copy: failed %s --> %s", srcFilename.c_str(), destFilename.c_str()); |
|
||||
return false; |
|
||||
#else
|
|
||||
char buffer[1024]; |
|
||||
|
|
||||
// Open input file
|
|
||||
FILE *input = fopen(srcFilename.c_str(), "rb"); |
|
||||
if (!input) { |
|
||||
LOG_ERROR(TCOMMON, "Copy: input failed %s --> %s", srcFilename.c_str(), |
|
||||
destFilename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
// open output file
|
|
||||
FILE *output = fopen(destFilename.c_str(), "wb"); |
|
||||
if (!output) { |
|
||||
fclose(input); |
|
||||
LOG_ERROR(TCOMMON, "Copy: output failed %s --> %s", srcFilename.c_str(), |
|
||||
destFilename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
// copy loop
|
|
||||
while (!feof(input)) { |
|
||||
// read input
|
|
||||
int rnum = fread(buffer, sizeof(char), 1024, input); |
|
||||
if (rnum != 1024) { |
|
||||
if (ferror(input) != 0) { |
|
||||
LOG_ERROR(TCOMMON, "Copy: failed reading from source, %s --> %s", |
|
||||
srcFilename.c_str(), destFilename.c_str()); |
|
||||
goto bail; |
|
||||
} |
|
||||
} |
|
||||
// write output
|
|
||||
int wnum = fwrite(buffer, sizeof(char), rnum, output); |
|
||||
if (wnum != rnum) { |
|
||||
LOG_ERROR(TCOMMON, "Copy: failed writing to output, %s --> %s", |
|
||||
srcFilename.c_str(), destFilename.c_str()); |
|
||||
goto bail; |
|
||||
} |
|
||||
} |
|
||||
// close flushs
|
|
||||
fclose(input); |
|
||||
fclose(output); |
|
||||
return true; |
|
||||
bail: |
|
||||
if (input) |
|
||||
fclose(input); |
|
||||
if (output) |
|
||||
fclose(output); |
|
||||
return false; |
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
// Returns the size of filename (64bit)
|
|
||||
u64 GetFileSize(const std::string &filename) { |
|
||||
if (!FileExists(filename)) { |
|
||||
LOG_WARNING(TCOMMON, "GetSize: failed %s: No such file", filename.c_str()); |
|
||||
return 0; |
|
||||
} |
|
||||
if (IsDirectory(filename)) { |
|
||||
LOG_WARNING(TCOMMON, "GetSize: failed %s: is a directory", filename.c_str()); |
|
||||
return 0; |
|
||||
} |
|
||||
struct stat64 buf; |
|
||||
if (stat64(filename.c_str(), &buf) == 0) { |
|
||||
LOG_DEBUG(TCOMMON, "GetSize: %s: %lld", filename.c_str(), (long long)buf.st_size); |
|
||||
return buf.st_size; |
|
||||
} |
|
||||
LOG_ERROR(TCOMMON, "GetSize: Stat failed %s", filename.c_str()); |
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
// Overloaded GetSize, accepts file descriptor
|
|
||||
u64 GetFileSize(const int fd) { |
|
||||
struct stat64 buf; |
|
||||
if (fstat64(fd, &buf) != 0) { |
|
||||
LOG_ERROR(TCOMMON, "GetSize: stat failed %i", fd); |
|
||||
return 0; |
|
||||
} |
|
||||
return buf.st_size; |
|
||||
} |
|
||||
|
|
||||
// Overloaded GetSize, accepts FILE*
|
|
||||
u64 GetFileSize(FILE *f) { |
|
||||
// can't use off_t here because it can be 32-bit
|
|
||||
u64 pos = ftello(f); |
|
||||
if (fseeko(f, 0, SEEK_END) != 0) { |
|
||||
LOG_ERROR(TCOMMON, "GetSize: seek failed %p", f); |
|
||||
return 0; |
|
||||
} |
|
||||
u64 size = ftello(f); |
|
||||
if ((size != pos) && (fseeko(f, pos, SEEK_SET) != 0)) { |
|
||||
LOG_ERROR(TCOMMON, "GetSize: seek failed %p", f); |
|
||||
return 0; |
|
||||
} |
|
||||
return size; |
|
||||
} |
|
||||
|
|
||||
// creates an empty file filename, returns true on success
|
|
||||
bool CreateEmptyFile(const std::string &filename) { |
|
||||
LOG_INFO(TCOMMON, "CreateEmptyFile: %s", filename.c_str()); |
|
||||
|
|
||||
FILE *pFile = fopen(filename.c_str(), "wb"); |
|
||||
if (!pFile) { |
|
||||
LOG_ERROR(TCOMMON, "CreateEmptyFile: failed %s", filename.c_str()); |
|
||||
return false; |
|
||||
} |
|
||||
fclose(pFile); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// Deletes the given directory and anything under it. Returns true on success.
|
|
||||
bool DeleteDirRecursively(const std::string &directory) { |
|
||||
LOG_INFO(TCOMMON, "DeleteDirRecursively: %s", directory.c_str()); |
|
||||
#ifdef _WIN32
|
|
||||
// Find the first file in the directory.
|
|
||||
WIN32_FIND_DATA ffd; |
|
||||
HANDLE hFind = FindFirstFile((directory + "\\*").c_str(), &ffd); |
|
||||
|
|
||||
if (hFind == INVALID_HANDLE_VALUE) { |
|
||||
FindClose(hFind); |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
// windows loop
|
|
||||
do { |
|
||||
const std::string virtualName = ffd.cFileName; |
|
||||
#else
|
|
||||
struct dirent dirent, *result = NULL; |
|
||||
DIR *dirp = opendir(directory.c_str()); |
|
||||
if (!dirp) { |
|
||||
return false; |
|
||||
} |
|
||||
// non windows loop
|
|
||||
while (!readdir_r(dirp, &dirent, &result) && result) { |
|
||||
const std::string virtualName = result->d_name; |
|
||||
#endif
|
|
||||
// check for "." and ".."
|
|
||||
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) || |
|
||||
((virtualName[0] == '.') && (virtualName[1] == '.') && |
|
||||
(virtualName[2] == '\0'))) { |
|
||||
continue; |
|
||||
} |
|
||||
std::string newPath = directory + '/' + virtualName; |
|
||||
if (IsDirectory(newPath)) { |
|
||||
if (!DeleteDirRecursively(newPath)) |
|
||||
return false; |
|
||||
} else { |
|
||||
if (!DeleteFile(newPath)) |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
#ifdef _WIN32
|
|
||||
} while (FindNextFile(hFind, &ffd) != 0); |
|
||||
FindClose(hFind); |
|
||||
#else
|
|
||||
} |
|
||||
closedir(dirp); |
|
||||
#endif
|
|
||||
DeleteDir(directory); |
|
||||
|
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
// Returns the current directory
|
|
||||
std::string GetCurrentDir() { |
|
||||
char *dir; |
|
||||
// Get the current working directory (getcwd uses malloc)
|
|
||||
if (!(dir = __getcwd(NULL, 0))) { |
|
||||
|
|
||||
LOG_ERROR(TCOMMON, "GetCurrentDirectory failed:"); |
|
||||
return NULL; |
|
||||
} |
|
||||
std::string strDir = dir; |
|
||||
free(dir); |
|
||||
return strDir; |
|
||||
} |
|
||||
|
|
||||
// Sets the current directory to the given directory
|
|
||||
bool SetCurrentDir(const std::string &directory) { |
|
||||
return __chdir(directory.c_str()) == 0; |
|
||||
} |
|
||||
|
|
||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename) { |
|
||||
FILE *f = fopen(filename, text_file ? "w" : "wb"); |
|
||||
if (!f) { |
|
||||
return false; |
|
||||
} |
|
||||
size_t len = str.size(); |
|
||||
if (len != fwrite(str.data(), 1, str.size(), f)) { |
|
||||
fclose(f); |
|
||||
return false; |
|
||||
} |
|
||||
fclose(f); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string &str) { |
|
||||
FILE *f = fopen(filename, text_file ? "r" : "rb"); |
|
||||
if (!f) { |
|
||||
return false; |
|
||||
} |
|
||||
size_t len = (size_t)GetFileSize(f); |
|
||||
char *buf = new char[len + 1]; |
|
||||
buf[fread(buf, 1, len, f)] = 0; |
|
||||
str = std::string(buf, len); |
|
||||
fclose(f); |
|
||||
delete [] buf; |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,90 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2013 Gekko Emulator |
|
||||
* |
|
||||
* @file file_utils.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2013-01-27 |
|
||||
* @brief Crossplatform file utility functions |
|
||||
* @remark Borrowed from Dolphin Emulator |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_FILE_UTILS_H_ |
|
||||
#define COMMON_FILE_UTILS_H_ |
|
||||
|
|
||||
#include <fstream> |
|
||||
#include <cstdio> |
|
||||
#include <string> |
|
||||
#include <vector> |
|
||||
#include <string.h> |
|
||||
|
|
||||
#include "common.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
// Returns true if file filename exists |
|
||||
bool FileExists(const std::string &filename); |
|
||||
|
|
||||
// Returns true if filename is a directory |
|
||||
bool IsDirectory(const std::string &filename); |
|
||||
|
|
||||
// Returns the size of filename (64bit) |
|
||||
u64 GetFileSize(const std::string &filename); |
|
||||
|
|
||||
// Overloaded GetSize, accepts file descriptor |
|
||||
u64 GetFileSize(const int fd); |
|
||||
|
|
||||
// Overloaded GetSize, accepts FILE* |
|
||||
u64 GetFileSize(FILE *f); |
|
||||
|
|
||||
// Returns true if successful, or path already exists. |
|
||||
bool CreateDir(const std::string &filename); |
|
||||
|
|
||||
// Creates the full path of fullPath returns true on success |
|
||||
bool CreateFullPath(const std::string &fullPath); |
|
||||
|
|
||||
// Deletes a given filename, return true on success |
|
||||
// Doesn't supports deleting a directory |
|
||||
bool DeleteFile(const std::string &filename); |
|
||||
|
|
||||
// Deletes a directory filename, returns true on success |
|
||||
bool DeleteDir(const std::string &filename); |
|
||||
|
|
||||
// renames file srcFilename to destFilename, returns true on success |
|
||||
bool RenameFile(const std::string &srcFilename, const std::string &destFilename); |
|
||||
|
|
||||
// copies file srcFilename to destFilename, returns true on success |
|
||||
bool CopyFile(const std::string &srcFilename, const std::string &destFilename); |
|
||||
|
|
||||
// creates an empty file filename, returns true on success |
|
||||
bool CreateEmptyFile(const std::string &filename); |
|
||||
|
|
||||
// deletes the given directory and anything under it. Returns true on success. |
|
||||
bool DeleteDirRecursively(const std::string &directory); |
|
||||
|
|
||||
// Returns the current directory |
|
||||
std::string GetCurrentDir(); |
|
||||
|
|
||||
// Set the current directory to given directory |
|
||||
bool SetCurrentDir(const std::string &directory); |
|
||||
|
|
||||
bool WriteStringToFile(bool text_file, const std::string &str, const char *filename); |
|
||||
bool ReadFileToString(bool text_file, const char *filename, std::string &str); |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
#endif // COMMON_FILE_UTILS_H_ |
|
||||
@ -1,241 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file hash.cpp |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-12-05 |
|
||||
* @brief General purpose hash function |
|
||||
* @remark Some functions borrowed from Dolphin Emulator |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "crc.h"
|
|
||||
#include "hash.h"
|
|
||||
#include "common.h"
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/// 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; |
|
||||
} |
|
||||
|
|
||||
#define ROTL32(x,y) rotl32(x,y)
|
|
||||
|
|
||||
inline uint32_t fmix ( uint32_t h ) |
|
||||
{ |
|
||||
h ^= h >> 16; |
|
||||
h *= 0x85ebca6b; |
|
||||
h ^= h >> 13; |
|
||||
h *= 0xc2b2ae35; |
|
||||
h ^= h >> 16; |
|
||||
|
|
||||
return h; |
|
||||
} |
|
||||
|
|
||||
u32 __compute_murmur_hash3_32(const u8 *src, int len, u32 samples) { |
|
||||
u32 h = len; |
|
||||
u32 step = (len >> 2); |
|
||||
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; |
|
||||
} |
|
||||
u32 h1 = 0x2f6af274; |
|
||||
const u32 c1 = 0xcc9e2d51; |
|
||||
const u32 c2 = 0x1b873593; |
|
||||
|
|
||||
while (data < end) { |
|
||||
u32 k1 = data[0]; |
|
||||
|
|
||||
k1 *= c1; |
|
||||
k1 = (k1 << 15) | (k1 >> (32 - 15)); |
|
||||
k1 *= c2; |
|
||||
|
|
||||
h1 ^= k1; |
|
||||
h1 = (h1 << 15) | (h1 >> (32 - 13)); |
|
||||
h1 = h1*5+0xe6546b64; |
|
||||
|
|
||||
data += step; |
|
||||
} |
|
||||
const u8 * tail = (const u8*)(data); |
|
||||
|
|
||||
u32 k1 = 0; |
|
||||
|
|
||||
switch(len & 3) { |
|
||||
case 3: |
|
||||
k1 ^= tail[2] << 16; |
|
||||
case 2: |
|
||||
k1 ^= tail[1] << 8; |
|
||||
case 1: |
|
||||
k1 ^= tail[0]; |
|
||||
k1 *= c1; |
|
||||
k1 = (k1 << 15) | (k1 >> (32 - 15)); |
|
||||
k1 *= c2; |
|
||||
h1 ^= k1; |
|
||||
}; |
|
||||
h1 ^= len; |
|
||||
h1 = fmix(h1); |
|
||||
|
|
||||
return h1; |
|
||||
} |
|
||||
|
|
||||
|
|
||||
/// MurmurHash is a non-cryptographic hash function suitable for general hash-based lookup
|
|
||||
u64 __compute_murmur_hash3_64(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; |
|
||||
|
|
||||
const u64* blocks = (const u64*)(data); |
|
||||
|
|
||||
for (int i = 0; i < nblocks; i+=step) { |
|
||||
u64 k1 = blocks[(i * 2) + 0]; |
|
||||
u64 k2 = blocks[(i * 2) + 1]; |
|
||||
|
|
||||
bmix64(h1,h2,k1,k2,c1,c2); |
|
||||
} |
|
||||
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); |
|
||||
}; |
|
||||
h2 ^= len; |
|
||||
|
|
||||
h1 += h2; |
|
||||
h2 += h1; |
|
||||
|
|
||||
h1 = fmix64(h1); |
|
||||
h2 = fmix64(h2); |
|
||||
|
|
||||
h1 += h2; |
|
||||
|
|
||||
return h1; |
|
||||
} |
|
||||
|
|
||||
/// CRC32 hash using the SSE4.2 instruction
|
|
||||
u64 __compute_crc32_sse4(const u8 *src, int len, u32 samples) { |
|
||||
u32 h = len; |
|
||||
u32 step = (len >> 2); |
|
||||
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 = InlineCrc32_U32(h, data[0]); |
|
||||
data += step; |
|
||||
} |
|
||||
const u8 *data2 = (const u8*)end; |
|
||||
return (u64)InlineCrc32_U32(h, u32(data2[0])); |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* Compute an efficient 64-bit hash (optimized for Intel hardware) |
|
||||
* @param src Source data buffer to compute hash for |
|
||||
* @param len Length of data buffer to compute hash for |
|
||||
* @param samples Number of samples to compute hash for |
|
||||
* @remark Borrowed from Dolphin Emulator |
|
||||
*/ |
|
||||
Hash64 GetHash64(const u8 *src, int len, u32 samples) { |
|
||||
#if defined(EMU_ARCHITECTURE_X86) || defined(EMU_ARCHITECTURE_X64)
|
|
||||
// TODO(ShizZy): Move somewhere common so we dont need to instantiate this more than once
|
|
||||
static X86Utils x86_utils; |
|
||||
if (x86_utils.IsExtensionSupported(X86Utils::kExtensionX86_SSE4_2)) { |
|
||||
return __compute_crc32_sse4(src, len, samples); |
|
||||
} else { |
|
||||
|
|
||||
#ifdef EMU_ARCHITECTURE_X64
|
|
||||
return __compute_murmur_hash3_64(src, len, samples); |
|
||||
#else
|
|
||||
return __compute_murmur_hash3_32(src, len, samples); |
|
||||
#endif
|
|
||||
} |
|
||||
#else
|
|
||||
return __compute_murmur_hash3_32(src, len, samples); |
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,46 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file hash.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-12-05 |
|
||||
* @brief General purpose hash function |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_HASH_H_ |
|
||||
#define COMMON_HASH_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
typedef u64 Hash64; |
|
||||
|
|
||||
/** |
|
||||
* Compute an efficient 64-bit hash (optimized for Intel hardware) |
|
||||
* @param src Source data buffer to compute hash for |
|
||||
* @param len Length of data buffer to compute hash for |
|
||||
* @param samples Number of samples to compute hash for |
|
||||
* @remark Borrowed from Dolphin Emulator |
|
||||
*/ |
|
||||
Hash64 GetHash64(const u8 *src, int len, u32 samples); |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
|
|
||||
#endif // COMMON_HASH_H_ |
|
||||
@ -1,116 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file hash_container.h |
|
||||
* @author ShizZy <shizzy@6bit.net> |
|
||||
* @date 2012-11-29 |
|
||||
* @brief Container object for storing a hash lookup |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_HASH_CONTAINER_H_ |
|
||||
#define COMMON_HASH_CONTAINER_H_ |
|
||||
|
|
||||
#include <map> |
|
||||
#include "common.h" |
|
||||
|
|
||||
/// Hash container generic interface - Don't use directly, use a derived class |
|
||||
template <class HashType, class ValueType> class HashContainer { |
|
||||
/** |
|
||||
* Add (or update if already exists) a value at the specified hash in the container |
|
||||
* @param hash Hash to use |
|
||||
* @param value Value to update at given hash in the container |
|
||||
*/ |
|
||||
ValueType* Update(HashType hash, ValueType value); |
|
||||
|
|
||||
/** |
|
||||
* Remove a hash entry in the hash container |
|
||||
* @param hash Hash value of entry to remove |
|
||||
*/ |
|
||||
void Remove(HashType hash); |
|
||||
|
|
||||
/** |
|
||||
* Fetch the value at at the given hash from the hash container |
|
||||
* @param hash Hash value of entry to fetch |
|
||||
* @return Pointer to value stored at hash location on success (index was found), otherwise NULL |
|
||||
*/ |
|
||||
ValueType* FetchFromHash(HashType hash); |
|
||||
|
|
||||
/** |
|
||||
* Fetch the value at at the given integer index from the hash container |
|
||||
* @param hash Hash value of entry to fetch |
|
||||
* @return Pointer to value stored at hash location on success (index was found), otherwise NULL |
|
||||
*/ |
|
||||
ValueType* FetchFromIndex(int index); |
|
||||
|
|
||||
/** |
|
||||
* Get the size of the hash container |
|
||||
* @return Number of elements in the hash container |
|
||||
*/ |
|
||||
int Size(); |
|
||||
}; |
|
||||
|
|
||||
/// Hash container implemented using STL map |
|
||||
template <class HashType, class ValueType> class HashContainer_STLMap : |
|
||||
public HashContainer<HashType, ValueType> { |
|
||||
|
|
||||
public: |
|
||||
HashContainer_STLMap() { |
|
||||
} |
|
||||
~HashContainer_STLMap() { |
|
||||
} |
|
||||
|
|
||||
ValueType* Update(HashType hash, ValueType value) { |
|
||||
map_[hash] = value; |
|
||||
return &map_[hash]; |
|
||||
} |
|
||||
|
|
||||
void Remove(HashType hash) { |
|
||||
map_.erase(hash); |
|
||||
} |
|
||||
|
|
||||
ValueType* FetchFromHash(HashType hash) { |
|
||||
typename std::map<HashType, ValueType>::iterator itr = map_.find(hash); |
|
||||
if (itr == map_.end()) { |
|
||||
return NULL; |
|
||||
} |
|
||||
return &itr->second; |
|
||||
} |
|
||||
|
|
||||
ValueType* FetchFromIndex(int index) { |
|
||||
typename std::map<HashType, ValueType>::iterator itr = map_.begin(); |
|
||||
int i = 0; |
|
||||
for (; i < index; ++i) { |
|
||||
++itr; |
|
||||
} |
|
||||
if (i < index) { |
|
||||
return NULL; |
|
||||
} |
|
||||
return &itr->second; |
|
||||
} |
|
||||
|
|
||||
int Size() { |
|
||||
return static_cast<int>(map_.size()); |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
std::map<HashType, ValueType> map_; |
|
||||
|
|
||||
DISALLOW_COPY_AND_ASSIGN(HashContainer_STLMap); |
|
||||
}; |
|
||||
|
|
||||
#endif // COMMON_HASH_CONTAINER_H_ |
|
||||
@ -1,152 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file log.cpp |
|
||||
* @author ShizZy <shizzy@6bit.net> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Common logging routines used throughout the project |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include <stdarg.h>
|
|
||||
#include <stdlib.h>
|
|
||||
|
|
||||
#include "common.h"
|
|
||||
#include "timer.h"
|
|
||||
|
|
||||
namespace logger { |
|
||||
|
|
||||
LogContainer* g_logs[NUMBER_OF_LOGS]; ///< List of pointers to all logs
|
|
||||
|
|
||||
/// LogContainer constructor
|
|
||||
LogContainer::LogContainer(const char* name, const char* desc, bool enable = false) { |
|
||||
strncpy(name_, name, 128); |
|
||||
strncpy(desc_, desc, 32); |
|
||||
level_ = LWARNING; |
|
||||
} |
|
||||
|
|
||||
/// Asks the user a yes or no question
|
|
||||
SysUserResponse AskYesNo(const char* fmt, ...) { |
|
||||
char c; |
|
||||
va_list arg; |
|
||||
|
|
||||
va_start(arg, fmt); |
|
||||
printf("\n** Question **\n"); |
|
||||
vprintf(fmt, arg); |
|
||||
va_end(arg); |
|
||||
|
|
||||
printf(" Response? (y/n) "); |
|
||||
while (1) { |
|
||||
c = getchar(); |
|
||||
if (c == 'y' || c == 'Y') { |
|
||||
return SYS_USER_YES; |
|
||||
} |
|
||||
if (c == 'n' || c == 'N') { |
|
||||
return SYS_USER_NO; |
|
||||
} |
|
||||
} |
|
||||
return SYS_USER_NO; |
|
||||
} |
|
||||
|
|
||||
//// Log routine used by everything
|
|
||||
void LogGeneric(LogLevel level, LogType type, const char *file, int line, bool append, const char* fmt, ...) |
|
||||
{ |
|
||||
char msg[kMaxMsgLength]; |
|
||||
static const char level_to_char[8] = "-NECWID"; |
|
||||
static char last_char = '\n'; |
|
||||
static LogType last_type; |
|
||||
|
|
||||
va_list arg; |
|
||||
va_start(arg, fmt); |
|
||||
|
|
||||
if (type >= NUMBER_OF_LOGS) { |
|
||||
LOG_ERROR(TCOMMON, "Unknown logger type %d", type); |
|
||||
return; |
|
||||
} |
|
||||
|
|
||||
// Format the log message
|
|
||||
if (append) { |
|
||||
sprintf(msg, "%s", fmt); |
|
||||
} else { |
|
||||
// char time_str[16];
|
|
||||
// u32 time_elapsed = common::GetTimeElapsed();
|
|
||||
// common::TicksToFormattedString(time_elapsed, time_str);
|
|
||||
sprintf(msg, "%c[%s] %s", level_to_char[(int)level], g_logs[type]->name(), fmt); |
|
||||
} |
|
||||
|
|
||||
// If the last message didn't have a line break, print one
|
|
||||
if ('\n' != last_char && '\r' != last_char && !append && last_type != TOS_REPORT && |
|
||||
last_type != TOS_HLE) { |
|
||||
printf("\n"); |
|
||||
} |
|
||||
last_char = msg[strlen(msg)-1]; |
|
||||
last_type = type; |
|
||||
|
|
||||
// Print the log message to stdout
|
|
||||
vprintf(msg, arg); |
|
||||
va_end(arg); |
|
||||
} |
|
||||
|
|
||||
/// Forces a controlled system crash rather before it catches fire (debug)
|
|
||||
void Crash() { |
|
||||
LOG_CRASH(TCOMMON, "*** SYSTEM CRASHED ***\n"); |
|
||||
LOG_CRASH(TCOMMON, "Fatal error, system could not recover.\n"); |
|
||||
#ifdef _MSC_VER
|
|
||||
#ifdef USE_INLINE_ASM_X86
|
|
||||
__asm int 3 |
|
||||
#endif
|
|
||||
#elif defined(__GNUC__)
|
|
||||
asm("int $3"); |
|
||||
#else
|
|
||||
LOG_CRASH(TCOMMON, "Exiting...\n"); |
|
||||
exit(0); |
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
/// Initialize the logging system
|
|
||||
void Init() { |
|
||||
g_logs[TNULL] = new LogContainer("NULL", "Null"); |
|
||||
g_logs[TAI] = new LogContainer("AI", "AudioInterface"); |
|
||||
g_logs[TBOOT] = new LogContainer("BOOT", "Boot"); |
|
||||
g_logs[TCOMMON] = new LogContainer("COMMON", "Common"); |
|
||||
g_logs[TCONFIG] = new LogContainer("CONFIG", "Configuration"); |
|
||||
g_logs[TCORE] = new LogContainer("CORE", "SysCore"); |
|
||||
g_logs[TCP] = new LogContainer("CP", "CommandProcessor"); |
|
||||
g_logs[TDI] = new LogContainer("DI", "DVDInterface"); |
|
||||
g_logs[TDSP] = new LogContainer("DSP", "DSP"); |
|
||||
g_logs[TDVD] = new LogContainer("DVD", "GCM/ISO"); |
|
||||
g_logs[TEXI] = new LogContainer("EXI", "ExternalInterface"); |
|
||||
g_logs[TGP] = new LogContainer("GP", "GraphicsProcessor"); |
|
||||
g_logs[THLE] = new LogContainer("HLE", "HLE"); |
|
||||
g_logs[THW] = new LogContainer("HW", "Hardware"); |
|
||||
g_logs[TJOYPAD] = new LogContainer("JOYPAD", "Joypad"); |
|
||||
g_logs[TMASTER] = new LogContainer("*", "Master Log"); |
|
||||
g_logs[TMEM] = new LogContainer("MEM", "Memory"); |
|
||||
g_logs[TMI] = new LogContainer("MI", "MemoryInterface"); |
|
||||
g_logs[TOS_HLE] = new LogContainer("OSHLE", "OSHLE"); |
|
||||
g_logs[TOS_REPORT] = new LogContainer("OSREPORT", "OSREPORT"); |
|
||||
g_logs[TPE] = new LogContainer("PE", "PixelEngine"); |
|
||||
g_logs[TPI] = new LogContainer("PI", "ProcessorInterface"); |
|
||||
g_logs[TPOWERPC] = new LogContainer("PPC", "PowerPC"); |
|
||||
g_logs[TSI] = new LogContainer("SI", "SerialInterface"); |
|
||||
g_logs[TVI] = new LogContainer("VI", "VideoInterface"); |
|
||||
g_logs[TVIDEO] = new LogContainer("VIDEO", "VideoCore"); |
|
||||
|
|
||||
LOG_NOTICE(TCOMMON, "%d logger(s) initalized ok", NUMBER_OF_LOGS); |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,216 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file log.h |
|
||||
* @author ShizZy <shizzy@6bit.net> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Common logging routines used throughout the project |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_LOG_H_ |
|
||||
#define COMMON_LOG_H_ |
|
||||
|
|
||||
#include "SDL.h" // Used for threading/mutexes |
|
||||
|
|
||||
#include "common.h" |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Logging Macros |
|
||||
|
|
||||
#if defined(_DEBUG) || defined(DEBUG) || defined(LOGGING) |
|
||||
/// Debug mode, show all logs |
|
||||
#define MAX_LOG_LEVEL logger::LDEBUG |
|
||||
#else |
|
||||
/// Non debug mode, only show critical logs |
|
||||
#define MAX_LOG_LEVEL logger::LWARNING |
|
||||
#endif |
|
||||
|
|
||||
/// Logs a message ** Don't use directly ** |
|
||||
#define _LOG_GENERIC(level, type, ...) \ |
|
||||
if (level <= MAX_LOG_LEVEL) { \ |
|
||||
LogGeneric(level, type, __FILE__, __LINE__, false, __VA_ARGS__); \ |
|
||||
} |
|
||||
|
|
||||
/// Used for appending to the last logged message |
|
||||
#define LOG_APPEND(level, type, ...) \ |
|
||||
if (logger::level <= MAX_LOG_LEVEL) { \ |
|
||||
logger::LogGeneric(logger::level, logger::type, __FILE__, __LINE__, true, __VA_ARGS__); \ |
|
||||
} |
|
||||
|
|
||||
/// Use this for printing an IMPORTANT notice to the logger |
|
||||
#define LOG_NOTICE(type, ...) _LOG_GENERIC(logger::LNOTICE, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
/// Use this for printing an error message to the logger |
|
||||
#define LOG_ERROR(type, ...) _LOG_GENERIC(logger::LERROR, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
/// Use this for printing a crash report to the logger |
|
||||
#define LOG_CRASH(type, ...) _LOG_GENERIC(logger::LCRASH, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
/// Use this for printing a warning to the logger |
|
||||
#define LOG_WARNING(type, ...) _LOG_GENERIC(logger::LWARNING, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
/// Use this for printing general information to the logger |
|
||||
#define LOG_INFO(type, ...) _LOG_GENERIC(logger::LINFO, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
#if defined(_DEBUG) || defined(DEBUG) || defined(LOGGING) |
|
||||
|
|
||||
/// Use this for printing a debug message to the logger |
|
||||
#define LOG_DEBUG(type, ...) _LOG_GENERIC(logger::LDEBUG, logger::type, __VA_ARGS__) |
|
||||
|
|
||||
/// Used for debug-mode assertions |
|
||||
#define _ASSERT_DBG(_type_, _cond_) \ |
|
||||
if (!(_cond_)) { \ |
|
||||
LOG_ERROR(_type_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n", \ |
|
||||
__LINE__, __FILE__, __TIME__); \ |
|
||||
if (!logger::AskYesNo("*** Assertion (see log)***\n")) logger::Crash(); \ |
|
||||
} |
|
||||
|
|
||||
/// Used for message-specified debug-mode assertions |
|
||||
#define _ASSERT_DBG_MSG(_type_, _cond_, ...) \ |
|
||||
if (!(_cond_)) { \ |
|
||||
LOG_ERROR(_type_, __VA_ARGS__); \ |
|
||||
if (!logger::AskYesNo(__VA_ARGS__)) logger::Crash(); \ |
|
||||
} |
|
||||
#else |
|
||||
#define _ASSERT_DBG(_type_, _cond_, ...) |
|
||||
#define _ASSERT_DBG_MSG(_type_, _cond_, ...) |
|
||||
#define LOG_DEBUG(type, ...) |
|
||||
#endif |
|
||||
|
|
||||
/// Used for general purpose assertions, CRITICAL operations only |
|
||||
#define _ASSERT_MSG(_type_, _cond_, ...) \ |
|
||||
if (!(_cond_)) { \ |
|
||||
if (!logger::AskYesNo(__VA_ARGS__)) logger::Crash(); \ |
|
||||
} |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Logger |
|
||||
|
|
||||
namespace logger { |
|
||||
|
|
||||
const int kMaxMsgLength = 1024; ///< Maximum message length |
|
||||
|
|
||||
/// Used for handling responses to system functions that require them |
|
||||
typedef enum { |
|
||||
SYS_USER_NO = 0, ///< User response for 'No' |
|
||||
SYS_USER_YES, ///< User response for 'Yes' |
|
||||
SYS_USER_OK, ///< User response for 'Okay' |
|
||||
SYS_USER_ABORT, ///< User response for 'Abort' |
|
||||
SYS_USER_RETRY, ///< User response for 'Retry' |
|
||||
SYS_USER_CANCEL, ///< User response for 'Cancel' |
|
||||
} SysUserResponse; |
|
||||
|
|
||||
/// Level of logging |
|
||||
typedef enum { |
|
||||
LNULL = 0, ///< Logs with this level won't get logged |
|
||||
LNOTICE, ///< Notice: A general message to the user |
|
||||
LERROR, ///< Error: For failure messages |
|
||||
LCRASH, ///< Crash: Used for crash reports |
|
||||
LWARNING, ///< Warning: For potentially bad things, but not fatal |
|
||||
LINFO, ///< Info: Information message |
|
||||
LDEBUG ///< Debug: Debug-only information |
|
||||
} LogLevel; |
|
||||
|
|
||||
/// Type of logging |
|
||||
typedef enum { |
|
||||
TNULL = 0, |
|
||||
TAI, |
|
||||
TBOOT, |
|
||||
TCOMMON, |
|
||||
TCONFIG, |
|
||||
TCORE, |
|
||||
TCP, |
|
||||
TDI, |
|
||||
TDSP, |
|
||||
TDVD, |
|
||||
TEXI, |
|
||||
TGP, |
|
||||
THLE, |
|
||||
THW, |
|
||||
TJOYPAD, |
|
||||
TMASTER, |
|
||||
TMEM, |
|
||||
TMI, |
|
||||
TOS_HLE, |
|
||||
TOS_REPORT, |
|
||||
TPE, |
|
||||
TPI, |
|
||||
TPOWERPC, |
|
||||
TSI, |
|
||||
TVI, |
|
||||
TVIDEO, |
|
||||
NUMBER_OF_LOGS ///< Number of logs - must be last |
|
||||
} LogType; |
|
||||
|
|
||||
/// Used for implementing a logger for a subsystem |
|
||||
class LogContainer |
|
||||
{ |
|
||||
public: |
|
||||
LogContainer(const char* name, const char* desc, bool enable); |
|
||||
~LogContainer() {} |
|
||||
|
|
||||
const char* name() const { return name_; } |
|
||||
const char* desc() const { return desc_; } |
|
||||
|
|
||||
bool enabled() const { return enabled_; } |
|
||||
void set_enabled(bool enabled) { enabled_ = enabled; } |
|
||||
|
|
||||
LogLevel level() const { return level_; } |
|
||||
void set_level(LogLevel level) { level_ = level; } |
|
||||
|
|
||||
private: |
|
||||
char name_[32]; ///< Name of the logger (e.g. "SI") |
|
||||
char desc_[128]; ///< Description of the logger (e.g. "Serial Interface") |
|
||||
bool enabled_; ///< Whether or not the logger is enabled |
|
||||
|
|
||||
LogLevel level_; ///< Level of the logger (e.g. Notice, Error, Warning, etc.) |
|
||||
|
|
||||
SDL_mutex* listener_lock_; ///< Mutex for multithreaded access |
|
||||
|
|
||||
DISALLOW_COPY_AND_ASSIGN(LogContainer); |
|
||||
}; |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Function Prototypes |
|
||||
|
|
||||
/*! |
|
||||
* \brief Log routine used by everything |
|
||||
* \param level Log level to use |
|
||||
* \param type Log type to use |
|
||||
* \param file Filename of file where error occured |
|
||||
* \param line Linenumber of file where error occured |
|
||||
* \param fmt Formatted message |
|
||||
*/ |
|
||||
void LogGeneric(LogLevel level, LogType type, const char *file, int line, bool append, const char* fmt, ...); |
|
||||
|
|
||||
/// Forces a controlled system crash rather before it catches fire (debug) |
|
||||
void Crash(); |
|
||||
|
|
||||
/*! |
|
||||
* \brief Asks the user a yes or no question |
|
||||
* \param fmt Question formatted message |
|
||||
* \return SysUserResponse response |
|
||||
*/ |
|
||||
SysUserResponse AskYesNo(const char* fmt, ...); |
|
||||
|
|
||||
/// Initialize the logging system |
|
||||
void Init(); |
|
||||
|
|
||||
} // namespace log |
|
||||
|
|
||||
#endif // COMMON_LOG_H |
|
||||
@ -1,91 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file misc_utils.cpp |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-03-06 |
|
||||
* @brief Miscellaneous functions/utilities that are used everywhere |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "misc_utils.h"
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/// Make a string lowercase
|
|
||||
void LowerStr(char* str) { |
|
||||
for (int i = 0; str[i]; i++) { |
|
||||
str[i] = tolower(str[ i ]); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// Make a string uppercase
|
|
||||
void UpperStr(char* str) { |
|
||||
for (int i=0; i < strlen(str); i++) { |
|
||||
if(str[i] >= 'a' && str[i] <= 'z') { |
|
||||
str[i] &= 0xDF; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// Format a std::string using C-style sprintf formatting
|
|
||||
std::string FormatStr(const char* format, ...) { |
|
||||
va_list args; |
|
||||
char *buf = NULL; |
|
||||
#if EMU_PLATFORM == PLATFORM_WINDOWS
|
|
||||
int required = 0; |
|
||||
|
|
||||
va_start(args, format); |
|
||||
required = _vscprintf(format, args); |
|
||||
buf = new char[required + 1]; |
|
||||
vsnprintf(buf, required, format, args); |
|
||||
va_end(args); |
|
||||
|
|
||||
buf[required] = '\0'; |
|
||||
std::string temp = buf; |
|
||||
delete[] buf; |
|
||||
#else
|
|
||||
va_start(args, format); |
|
||||
vasprintf(&buf, format, args); |
|
||||
va_end(args); |
|
||||
|
|
||||
std::string temp = buf; |
|
||||
free(buf); |
|
||||
#endif
|
|
||||
return temp; |
|
||||
} |
|
||||
|
|
||||
/// Check if a file exists
|
|
||||
bool FileExists(char* filename) { |
|
||||
std::ifstream ifile(filename); |
|
||||
if (!ifile) { |
|
||||
return false; |
|
||||
} |
|
||||
ifile.close(); |
|
||||
return true; |
|
||||
} |
|
||||
|
|
||||
/// Gets the size of a file
|
|
||||
size_t FileSize(FILE* file) { |
|
||||
size_t pos = ftell(file); |
|
||||
fseek(file, 0L, SEEK_END); |
|
||||
size_t res = ftell(file); |
|
||||
fseek(file, pos, SEEK_SET); |
|
||||
return res; |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,58 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file misc_utils.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-03-06 |
|
||||
* @brief Miscellaneous functions/utilities that are used everywhere |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#include "common.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/** |
|
||||
* @brief Make a string lowercase |
|
||||
* @param str String to make lowercase |
|
||||
*/ |
|
||||
void LowerStr(char* str); |
|
||||
|
|
||||
/** |
|
||||
* @brief Make a string uppercase |
|
||||
* @param str String to make uppercase |
|
||||
*/ |
|
||||
void UpperStr(char* str); |
|
||||
|
|
||||
/// Format a std::string using C-style sprintf formatting |
|
||||
std::string FormatStr(const char* format, ...); |
|
||||
|
|
||||
/** |
|
||||
* @brief Check if a file exists on the users computer |
|
||||
* @param filename Filename of file to check for |
|
||||
* @return true on exists, false otherwise |
|
||||
*/ |
|
||||
bool FileExists(char* filename); |
|
||||
|
|
||||
/** |
|
||||
* @brief Gets the size of a file |
|
||||
* @param file Pointer to file to get size of |
|
||||
* @return true Size of file, in bytes |
|
||||
*/ |
|
||||
size_t FileSize(FILE* file); |
|
||||
|
|
||||
} // namespace |
|
||||
@ -1,135 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file platform.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Platform detection macros for portable compilation |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_PLATFORM_H_ |
|
||||
#define COMMON_PLATFORM_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Platform definitions |
|
||||
|
|
||||
/// Enumeration for defining the supported platforms |
|
||||
#define PLATFORM_NULL 0 |
|
||||
#define PLATFORM_WINDOWS 1 |
|
||||
#define PLATFORM_MACOSX 2 |
|
||||
#define PLATFORM_LINUX 3 |
|
||||
#define PLATFORM_ANDROID 4 |
|
||||
#define PLATFORM_IOS 5 |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Platform detection |
|
||||
extern char *kGekkoOS; |
|
||||
|
|
||||
#ifndef EMU_PLATFORM |
|
||||
|
|
||||
#if defined( __WIN32__ ) || defined( _WIN32 ) |
|
||||
#define EMU_PLATFORM PLATFORM_WINDOWS |
|
||||
|
|
||||
#elif defined( __APPLE__ ) || defined( __APPLE_CC__ ) |
|
||||
#define EMU_PLATFORM PLATFORM_MAXOSX |
|
||||
|
|
||||
#elif defined(__linux__) |
|
||||
#define EMU_PLATFORM PLATFORM_LINUX |
|
||||
|
|
||||
#else // Assume linux otherwise |
|
||||
#define EMU_PLATFORM PLATFORM_LINUX |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#if defined(__x86_64__) || defined(_M_X64) || defined(__alpha__) || defined(__ia64__) |
|
||||
#define EMU_ARCHITECTURE_X64 |
|
||||
#else |
|
||||
#define EMU_ARCHITECTURE_X86 |
|
||||
#endif |
|
||||
|
|
||||
//////////////////////////////////////////////////////////////////////////////////////////////////// |
|
||||
// Compiler-Specific Definitions |
|
||||
|
|
||||
#if EMU_PLATFORM == PLATFORM_WINDOWS |
|
||||
|
|
||||
#define NOMINMAX |
|
||||
#define EMU_FASTCALL __fastcall |
|
||||
|
|
||||
#else |
|
||||
|
|
||||
#define EMU_FASTCALL __attribute__((fastcall)) |
|
||||
#define __stdcall |
|
||||
#define __cdecl |
|
||||
|
|
||||
#define LONG long |
|
||||
#define BOOL bool |
|
||||
#define DWORD u32 |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#if EMU_PLATFORM != PLATFORM_WINDOWS |
|
||||
|
|
||||
// TODO: Hacks.. |
|
||||
#include <limits.h> |
|
||||
#define MAX_PATH PATH_MAX |
|
||||
|
|
||||
#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; |
|
||||
|
|
||||
inline u32 _rotl(u32 x, int shift) { |
|
||||
shift &= 31; |
|
||||
if (0 == shift) { |
|
||||
return x; |
|
||||
} |
|
||||
return (x << shift) | (x >> (32 - shift)); |
|
||||
} |
|
||||
|
|
||||
inline u64 _rotl64(u64 x, u32 shift){ |
|
||||
u32 n = shift % 64; |
|
||||
return (x << n) | (x >> (64 - n)); |
|
||||
} |
|
||||
|
|
||||
inline u32 _rotr(u32 x, int shift) { |
|
||||
shift &= 31; |
|
||||
if (0 == shift) { |
|
||||
return x; |
|
||||
} |
|
||||
return (x >> shift) | (x << (32 - shift)); |
|
||||
} |
|
||||
|
|
||||
inline u64 _rotr64(u64 x, u32 shift){ |
|
||||
u32 n = shift % 64; |
|
||||
return (x >> n) | (x << (64 - n)); |
|
||||
} |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#define GCC_VERSION_AVAILABLE(major, minor) (defined(__GNUC__) && (__GNUC__ > (major) || \ |
|
||||
(__GNUC__ == (major) && __GNUC_MINOR__ >= (minor)))) |
|
||||
|
|
||||
#endif // COMMON_PLATFORM_H_ |
|
||||
@ -1,152 +0,0 @@ |
|||||
#ifndef CONDITION_VARIABLE_H_ |
|
||||
#define CONDITION_VARIABLE_H_ |
|
||||
|
|
||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) |
|
||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) |
|
||||
|
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ |
|
||||
// GCC 4.4 provides <condition_variable> |
|
||||
#include <condition_variable> |
|
||||
#else |
|
||||
|
|
||||
// partial std::condition_variable implementation for win32/pthread |
|
||||
|
|
||||
#include "std_mutex.h" |
|
||||
|
|
||||
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) |
|
||||
#define USE_RVALUE_REFERENCES |
|
||||
#endif |
|
||||
|
|
||||
#if defined(_WIN32) && defined(_M_X64) |
|
||||
#define USE_CONDITION_VARIABLES |
|
||||
#elif defined(_WIN32) |
|
||||
#define USE_EVENTS |
|
||||
#endif |
|
||||
|
|
||||
namespace std |
|
||||
{ |
|
||||
|
|
||||
class condition_variable |
|
||||
{ |
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) |
|
||||
typedef CONDITION_VARIABLE native_type; |
|
||||
#elif defined(_WIN32) |
|
||||
typedef HANDLE native_type; |
|
||||
#else |
|
||||
typedef pthread_cond_t native_type; |
|
||||
#endif |
|
||||
|
|
||||
public: |
|
||||
|
|
||||
#ifdef USE_EVENTS |
|
||||
typedef native_type native_handle_type; |
|
||||
#else |
|
||||
typedef native_type* native_handle_type; |
|
||||
#endif |
|
||||
|
|
||||
condition_variable() |
|
||||
{ |
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) |
|
||||
InitializeConditionVariable(&m_handle); |
|
||||
#elif defined(_WIN32) |
|
||||
m_handle = CreateEvent(NULL, false, false, NULL); |
|
||||
#else |
|
||||
pthread_cond_init(&m_handle, NULL); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
~condition_variable() |
|
||||
{ |
|
||||
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES) |
|
||||
CloseHandle(m_handle); |
|
||||
#elif !defined(_WIN32) |
|
||||
pthread_cond_destroy(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
condition_variable(const condition_variable&) /*= delete*/; |
|
||||
condition_variable& operator=(const condition_variable&) /*= delete*/; |
|
||||
|
|
||||
void notify_one() |
|
||||
{ |
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) |
|
||||
WakeConditionVariable(&m_handle); |
|
||||
#elif defined(_WIN32) |
|
||||
SetEvent(m_handle); |
|
||||
#else |
|
||||
pthread_cond_signal(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void notify_all() |
|
||||
{ |
|
||||
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) |
|
||||
WakeAllConditionVariable(&m_handle); |
|
||||
#elif defined(_WIN32) |
|
||||
// TODO: broken |
|
||||
SetEvent(m_handle); |
|
||||
#else |
|
||||
pthread_cond_broadcast(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void wait(unique_lock<mutex>& lock) |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
#ifdef USE_SRWLOCKS |
|
||||
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); |
|
||||
#elif defined(USE_CONDITION_VARIABLES) |
|
||||
SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE); |
|
||||
#else |
|
||||
// TODO: broken, the unlock and wait need to be atomic |
|
||||
lock.unlock(); |
|
||||
WaitForSingleObject(m_handle, INFINITE); |
|
||||
lock.lock(); |
|
||||
#endif |
|
||||
#else |
|
||||
pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
template <class Predicate> |
|
||||
void wait(unique_lock<mutex>& lock, Predicate pred) |
|
||||
{ |
|
||||
while (!pred()) |
|
||||
wait(lock); |
|
||||
} |
|
||||
|
|
||||
//template <class Clock, class Duration> |
|
||||
//cv_status wait_until(unique_lock<mutex>& lock, |
|
||||
// const chrono::time_point<Clock, Duration>& abs_time); |
|
||||
|
|
||||
//template <class Clock, class Duration, class Predicate> |
|
||||
// bool wait_until(unique_lock<mutex>& lock, |
|
||||
// const chrono::time_point<Clock, Duration>& abs_time, |
|
||||
// Predicate pred); |
|
||||
|
|
||||
//template <class Rep, class Period> |
|
||||
//cv_status wait_for(unique_lock<mutex>& lock, |
|
||||
// const chrono::duration<Rep, Period>& rel_time); |
|
||||
|
|
||||
//template <class Rep, class Period, class Predicate> |
|
||||
// bool wait_for(unique_lock<mutex>& lock, |
|
||||
// const chrono::duration<Rep, Period>& rel_time, |
|
||||
// Predicate pred); |
|
||||
|
|
||||
native_handle_type native_handle() |
|
||||
{ |
|
||||
#ifdef USE_EVENTS |
|
||||
return m_handle; |
|
||||
#else |
|
||||
return &m_handle; |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
native_type m_handle; |
|
||||
}; |
|
||||
|
|
||||
} |
|
||||
|
|
||||
#endif |
|
||||
#endif |
|
||||
@ -1,354 +0,0 @@ |
|||||
#ifndef MUTEX_H_ |
|
||||
#define MUTEX_H_ |
|
||||
|
|
||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) |
|
||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) |
|
||||
|
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ |
|
||||
// GCC 4.4 provides <mutex> |
|
||||
#include <mutex> |
|
||||
#else |
|
||||
|
|
||||
// partial <mutex> implementation for win32/pthread |
|
||||
|
|
||||
#include <algorithm> |
|
||||
|
|
||||
#if defined(_WIN32) |
|
||||
// WIN32 |
|
||||
#define WIN32_LEAN_AND_MEAN |
|
||||
#include <Windows.h> |
|
||||
|
|
||||
#else |
|
||||
// POSIX |
|
||||
#include <pthread.h> |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) |
|
||||
#define USE_RVALUE_REFERENCES |
|
||||
#endif |
|
||||
|
|
||||
#if defined(_WIN32) && defined(_M_X64) |
|
||||
#define USE_SRWLOCKS |
|
||||
#endif |
|
||||
|
|
||||
namespace std |
|
||||
{ |
|
||||
|
|
||||
class recursive_mutex |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
typedef CRITICAL_SECTION native_type; |
|
||||
#else |
|
||||
typedef pthread_mutex_t native_type; |
|
||||
#endif |
|
||||
|
|
||||
public: |
|
||||
typedef native_type* native_handle_type; |
|
||||
|
|
||||
recursive_mutex(const recursive_mutex&) /*= delete*/; |
|
||||
recursive_mutex& operator=(const recursive_mutex&) /*= delete*/; |
|
||||
|
|
||||
recursive_mutex() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
InitializeCriticalSection(&m_handle); |
|
||||
#else |
|
||||
pthread_mutexattr_t attr; |
|
||||
pthread_mutexattr_init(&attr); |
|
||||
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); |
|
||||
pthread_mutex_init(&m_handle, &attr); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
~recursive_mutex() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
DeleteCriticalSection(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_destroy(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void lock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
EnterCriticalSection(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_lock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void unlock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
LeaveCriticalSection(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_unlock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
bool try_lock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
return (0 != TryEnterCriticalSection(&m_handle)); |
|
||||
#else |
|
||||
return !pthread_mutex_trylock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
native_handle_type native_handle() |
|
||||
{ |
|
||||
return &m_handle; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
native_type m_handle; |
|
||||
}; |
|
||||
|
|
||||
#if !defined(_WIN32) || defined(USE_SRWLOCKS) |
|
||||
|
|
||||
class mutex |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
typedef SRWLOCK native_type; |
|
||||
#else |
|
||||
typedef pthread_mutex_t native_type; |
|
||||
#endif |
|
||||
|
|
||||
public: |
|
||||
typedef native_type* native_handle_type; |
|
||||
|
|
||||
mutex(const mutex&) /*= delete*/; |
|
||||
mutex& operator=(const mutex&) /*= delete*/; |
|
||||
|
|
||||
mutex() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
InitializeSRWLock(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_init(&m_handle, NULL); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
~mutex() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
#else |
|
||||
pthread_mutex_destroy(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void lock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
AcquireSRWLockExclusive(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_lock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void unlock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
ReleaseSRWLockExclusive(&m_handle); |
|
||||
#else |
|
||||
pthread_mutex_unlock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
bool try_lock() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
// XXX TryAcquireSRWLockExclusive requires Windows 7! |
|
||||
// return (0 != TryAcquireSRWLockExclusive(&m_handle)); |
|
||||
return false; |
|
||||
#else |
|
||||
return !pthread_mutex_trylock(&m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
native_handle_type native_handle() |
|
||||
{ |
|
||||
return &m_handle; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
native_type m_handle; |
|
||||
}; |
|
||||
|
|
||||
#else |
|
||||
typedef recursive_mutex mutex; // just use CriticalSections |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
enum defer_lock_t { defer_lock }; |
|
||||
enum try_to_lock_t { try_to_lock }; |
|
||||
enum adopt_lock_t { adopt_lock }; |
|
||||
|
|
||||
template <class Mutex> |
|
||||
class lock_guard |
|
||||
{ |
|
||||
public: |
|
||||
typedef Mutex mutex_type; |
|
||||
|
|
||||
explicit lock_guard(mutex_type& m) |
|
||||
: pm(m) |
|
||||
{ |
|
||||
m.lock(); |
|
||||
} |
|
||||
|
|
||||
lock_guard(mutex_type& m, adopt_lock_t) |
|
||||
: pm(m) |
|
||||
{ |
|
||||
} |
|
||||
|
|
||||
~lock_guard() |
|
||||
{ |
|
||||
pm.unlock(); |
|
||||
} |
|
||||
|
|
||||
lock_guard(lock_guard const&) /*= delete*/; |
|
||||
lock_guard& operator=(lock_guard const&) /*= delete*/; |
|
||||
|
|
||||
private: |
|
||||
mutex_type& pm; |
|
||||
}; |
|
||||
|
|
||||
template <class Mutex> |
|
||||
class unique_lock |
|
||||
{ |
|
||||
public: |
|
||||
typedef Mutex mutex_type; |
|
||||
|
|
||||
unique_lock() |
|
||||
: pm(NULL), owns(false) |
|
||||
{} |
|
||||
|
|
||||
/*explicit*/ unique_lock(mutex_type& m) |
|
||||
: pm(&m), owns(true) |
|
||||
{ |
|
||||
m.lock(); |
|
||||
} |
|
||||
|
|
||||
unique_lock(mutex_type& m, defer_lock_t) |
|
||||
: pm(&m), owns(false) |
|
||||
{} |
|
||||
|
|
||||
unique_lock(mutex_type& m, try_to_lock_t) |
|
||||
: pm(&m), owns(m.try_lock()) |
|
||||
{} |
|
||||
|
|
||||
unique_lock(mutex_type& m, adopt_lock_t) |
|
||||
: pm(&m), owns(true) |
|
||||
{} |
|
||||
|
|
||||
//template <class Clock, class Duration> |
|
||||
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); |
|
||||
|
|
||||
//template <class Rep, class Period> |
|
||||
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); |
|
||||
|
|
||||
~unique_lock() |
|
||||
{ |
|
||||
if (owns_lock()) |
|
||||
mutex()->unlock(); |
|
||||
} |
|
||||
|
|
||||
#ifdef USE_RVALUE_REFERENCES |
|
||||
unique_lock& operator=(const unique_lock&) /*= delete*/; |
|
||||
|
|
||||
unique_lock& operator=(unique_lock&& other) |
|
||||
{ |
|
||||
#else |
|
||||
unique_lock& operator=(const unique_lock& u) |
|
||||
{ |
|
||||
// ugly const_cast to get around lack of rvalue references |
|
||||
unique_lock& other = const_cast<unique_lock&>(u); |
|
||||
#endif |
|
||||
swap(other); |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
#ifdef USE_RVALUE_REFERENCES |
|
||||
unique_lock(const unique_lock&) /*= delete*/; |
|
||||
|
|
||||
unique_lock(unique_lock&& other) |
|
||||
: pm(NULL), owns(false) |
|
||||
{ |
|
||||
#else |
|
||||
unique_lock(const unique_lock& u) |
|
||||
: pm(NULL), owns(false) |
|
||||
{ |
|
||||
// ugly const_cast to get around lack of rvalue references |
|
||||
unique_lock& other = const_cast<unique_lock&>(u); |
|
||||
#endif |
|
||||
swap(other); |
|
||||
} |
|
||||
|
|
||||
void lock() |
|
||||
{ |
|
||||
mutex()->lock(); |
|
||||
owns = true; |
|
||||
} |
|
||||
|
|
||||
bool try_lock() |
|
||||
{ |
|
||||
owns = mutex()->try_lock(); |
|
||||
return owns; |
|
||||
} |
|
||||
|
|
||||
//template <class Rep, class Period> |
|
||||
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); |
|
||||
//template <class Clock, class Duration> |
|
||||
//bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); |
|
||||
|
|
||||
void unlock() |
|
||||
{ |
|
||||
mutex()->unlock(); |
|
||||
owns = false; |
|
||||
} |
|
||||
|
|
||||
void swap(unique_lock& u) |
|
||||
{ |
|
||||
std::swap(pm, u.pm); |
|
||||
std::swap(owns, u.owns); |
|
||||
} |
|
||||
|
|
||||
mutex_type* release() |
|
||||
{ |
|
||||
return mutex(); |
|
||||
pm = NULL; |
|
||||
owns = false; |
|
||||
} |
|
||||
|
|
||||
bool owns_lock() const |
|
||||
{ |
|
||||
return owns; |
|
||||
} |
|
||||
|
|
||||
//explicit operator bool () const |
|
||||
//{ |
|
||||
// return owns_lock(); |
|
||||
//} |
|
||||
|
|
||||
mutex_type* mutex() const |
|
||||
{ |
|
||||
return pm; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
mutex_type* pm; |
|
||||
bool owns; |
|
||||
}; |
|
||||
|
|
||||
template <class Mutex> |
|
||||
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) |
|
||||
{ |
|
||||
x.swap(y); |
|
||||
} |
|
||||
|
|
||||
} |
|
||||
|
|
||||
#endif |
|
||||
#endif |
|
||||
@ -1,309 +0,0 @@ |
|||||
#ifndef STD_THREAD_H_ |
|
||||
#define STD_THREAD_H_ |
|
||||
|
|
||||
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) |
|
||||
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) |
|
||||
|
|
||||
#if GCC_VERSION >= GCC_VER(4,4,0) && __GXX_EXPERIMENTAL_CXX0X__ |
|
||||
// GCC 4.4 provides <thread> |
|
||||
#ifndef _GLIBCXX_USE_SCHED_YIELD |
|
||||
#define _GLIBCXX_USE_SCHED_YIELD |
|
||||
#endif |
|
||||
#include <thread> |
|
||||
#else |
|
||||
|
|
||||
// partial std::thread implementation for win32/pthread |
|
||||
|
|
||||
#include <algorithm> |
|
||||
|
|
||||
#if (_MSC_VER >= 1600) || (GCC_VERSION >= GCC_VER(4,3,0) && __GXX_EXPERIMENTAL_CXX0X__) |
|
||||
#define USE_RVALUE_REFERENCES |
|
||||
#endif |
|
||||
|
|
||||
#ifdef __APPLE__ |
|
||||
#import <Foundation/NSAutoreleasePool.h> |
|
||||
#endif |
|
||||
|
|
||||
#if defined(_WIN32) |
|
||||
// WIN32 |
|
||||
|
|
||||
#define WIN32_LEAN_AND_MEAN |
|
||||
#include <Windows.h> |
|
||||
|
|
||||
#if defined(_MSC_VER) && defined(_MT) |
|
||||
// When linking with LIBCMT (the multithreaded C library), Microsoft recommends |
|
||||
// using _beginthreadex instead of CreateThread. |
|
||||
#define USE_BEGINTHREADEX |
|
||||
#include <process.h> |
|
||||
#endif |
|
||||
|
|
||||
#ifdef USE_BEGINTHREADEX |
|
||||
#define THREAD_ID unsigned |
|
||||
#define THREAD_RETURN unsigned __stdcall |
|
||||
#else |
|
||||
#define THREAD_ID DWORD |
|
||||
#define THREAD_RETURN DWORD WINAPI |
|
||||
#endif |
|
||||
#define THREAD_HANDLE HANDLE |
|
||||
|
|
||||
#else |
|
||||
// PTHREAD |
|
||||
|
|
||||
#include <unistd.h> |
|
||||
|
|
||||
#ifndef _POSIX_THREADS |
|
||||
#error unsupported platform (no pthreads?) |
|
||||
#endif |
|
||||
|
|
||||
#include <pthread.h> |
|
||||
|
|
||||
#define THREAD_ID pthread_t |
|
||||
#define THREAD_HANDLE pthread_t |
|
||||
#define THREAD_RETURN void* |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
namespace std |
|
||||
{ |
|
||||
|
|
||||
class thread |
|
||||
{ |
|
||||
public: |
|
||||
typedef THREAD_HANDLE native_handle_type; |
|
||||
|
|
||||
class id |
|
||||
{ |
|
||||
friend class thread; |
|
||||
public: |
|
||||
id() : m_thread(0) {} |
|
||||
id(THREAD_ID _id) : m_thread(_id) {} |
|
||||
|
|
||||
bool operator==(const id& rhs) const |
|
||||
{ |
|
||||
return m_thread == rhs.m_thread; |
|
||||
} |
|
||||
|
|
||||
bool operator!=(const id& rhs) const |
|
||||
{ |
|
||||
return !(*this == rhs); |
|
||||
} |
|
||||
|
|
||||
bool operator<(const id& rhs) const |
|
||||
{ |
|
||||
return m_thread < rhs.m_thread; |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
THREAD_ID m_thread; |
|
||||
}; |
|
||||
|
|
||||
// no variadic template support in msvc |
|
||||
//template <typename C, typename... A> |
|
||||
//thread(C&& func, A&&... args); |
|
||||
|
|
||||
template <typename C> |
|
||||
thread(C func) |
|
||||
{ |
|
||||
StartThread(new Func<C>(func)); |
|
||||
} |
|
||||
|
|
||||
template <typename C, typename A> |
|
||||
thread(C func, A arg) |
|
||||
{ |
|
||||
StartThread(new FuncArg<C, A>(func, arg)); |
|
||||
} |
|
||||
|
|
||||
thread() /*= default;*/ {} |
|
||||
|
|
||||
#ifdef USE_RVALUE_REFERENCES |
|
||||
thread(const thread&) /*= delete*/; |
|
||||
|
|
||||
thread(thread&& other) |
|
||||
{ |
|
||||
#else |
|
||||
thread(const thread& t) |
|
||||
{ |
|
||||
// ugly const_cast to get around lack of rvalue references |
|
||||
thread& other = const_cast<thread&>(t); |
|
||||
#endif |
|
||||
swap(other); |
|
||||
} |
|
||||
|
|
||||
#ifdef USE_RVALUE_REFERENCES |
|
||||
thread& operator=(const thread&) /*= delete*/; |
|
||||
|
|
||||
thread& operator=(thread&& other) |
|
||||
{ |
|
||||
#else |
|
||||
thread& operator=(const thread& t) |
|
||||
{ |
|
||||
// ugly const_cast to get around lack of rvalue references |
|
||||
thread& other = const_cast<thread&>(t); |
|
||||
#endif |
|
||||
if (joinable()) |
|
||||
detach(); |
|
||||
swap(other); |
|
||||
return *this; |
|
||||
} |
|
||||
|
|
||||
~thread() |
|
||||
{ |
|
||||
if (joinable()) |
|
||||
detach(); |
|
||||
} |
|
||||
|
|
||||
bool joinable() const |
|
||||
{ |
|
||||
return m_id != id(); |
|
||||
} |
|
||||
|
|
||||
id get_id() const |
|
||||
{ |
|
||||
return m_id; |
|
||||
} |
|
||||
|
|
||||
native_handle_type native_handle() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
return m_handle; |
|
||||
#else |
|
||||
return m_id.m_thread; |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void join() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
WaitForSingleObject(m_handle, INFINITE); |
|
||||
detach(); |
|
||||
#else |
|
||||
pthread_join(m_id.m_thread, NULL); |
|
||||
m_id = id(); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
void detach() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
CloseHandle(m_handle); |
|
||||
#else |
|
||||
pthread_detach(m_id.m_thread); |
|
||||
#endif |
|
||||
m_id = id(); |
|
||||
} |
|
||||
|
|
||||
void swap(thread& other) |
|
||||
{ |
|
||||
std::swap(m_id, other.m_id); |
|
||||
#ifdef _WIN32 |
|
||||
std::swap(m_handle, other.m_handle); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
static unsigned hardware_concurrency() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
SYSTEM_INFO sysinfo; |
|
||||
GetSystemInfo(&sysinfo); |
|
||||
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors); |
|
||||
#else |
|
||||
return 0; |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
private: |
|
||||
id m_id; |
|
||||
|
|
||||
#ifdef _WIN32 |
|
||||
native_handle_type m_handle; |
|
||||
#endif |
|
||||
|
|
||||
template <typename F> |
|
||||
void StartThread(F* param) |
|
||||
{ |
|
||||
#ifdef USE_BEGINTHREADEX |
|
||||
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread); |
|
||||
#elif defined(_WIN32) |
|
||||
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread); |
|
||||
#else |
|
||||
pthread_attr_t attr; |
|
||||
pthread_attr_init(&attr); |
|
||||
pthread_attr_setstacksize(&attr, 1024 * 1024); |
|
||||
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param)) |
|
||||
m_id = id(); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
template <typename C> |
|
||||
class Func |
|
||||
{ |
|
||||
public: |
|
||||
Func(C _func) : func(_func) {} |
|
||||
|
|
||||
void Run() { func(); } |
|
||||
|
|
||||
private: |
|
||||
C const func; |
|
||||
}; |
|
||||
|
|
||||
template <typename C, typename A> |
|
||||
class FuncArg |
|
||||
{ |
|
||||
public: |
|
||||
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {} |
|
||||
|
|
||||
void Run() { func(arg); } |
|
||||
|
|
||||
private: |
|
||||
C const func; |
|
||||
A arg; |
|
||||
}; |
|
||||
|
|
||||
template <typename F> |
|
||||
static THREAD_RETURN RunAndDelete(void* param) |
|
||||
{ |
|
||||
#ifdef __APPLE__ |
|
||||
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; |
|
||||
#endif |
|
||||
static_cast<F*>(param)->Run(); |
|
||||
delete static_cast<F*>(param); |
|
||||
#ifdef __APPLE__ |
|
||||
[pool release]; |
|
||||
#endif |
|
||||
return 0; |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
namespace this_thread |
|
||||
{ |
|
||||
|
|
||||
inline void yield() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
SwitchToThread(); |
|
||||
#else |
|
||||
sleep(0); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
inline thread::id get_id() |
|
||||
{ |
|
||||
#ifdef _WIN32 |
|
||||
return GetCurrentThreadId(); |
|
||||
#else |
|
||||
return pthread_self(); |
|
||||
#endif |
|
||||
} |
|
||||
|
|
||||
} // namespace this_thread |
|
||||
|
|
||||
} // namespace std |
|
||||
|
|
||||
#undef USE_RVALUE_REFERENCES |
|
||||
#undef USE_BEGINTHREADEX |
|
||||
#undef THREAD_ID |
|
||||
#undef THREAD_RETURN |
|
||||
#undef THREAD_HANDLE |
|
||||
|
|
||||
#endif |
|
||||
#endif |
|
||||
@ -1,46 +0,0 @@ |
|||||
/*!
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* \file timer.h |
|
||||
* \author ShizZy <shizzy247@gmail.com> |
|
||||
* \date 2012-02-11 |
|
||||
* \brief Common time and timer routines |
|
||||
* |
|
||||
* \section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "SDL.h"
|
|
||||
|
|
||||
#include "common.h"
|
|
||||
#include "timer.h"
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/// Converts a ticks (miliseconds) u64 to a formatted string
|
|
||||
void TicksToFormattedString(u32 ticks, char* formatted_string) { |
|
||||
u32 hh = ticks / (1000 * 60 * 60); |
|
||||
ticks -= hh * (1000 * 60 * 60); |
|
||||
|
|
||||
u32 mm = ticks / (1000 * 60); |
|
||||
ticks -= mm * (1000 * 60); |
|
||||
|
|
||||
u32 ss = ticks / 1000; |
|
||||
ticks -= ss * 1000; |
|
||||
|
|
||||
sprintf(formatted_string, "%02d:%02d:%03d", mm, ss, ticks); |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,51 +0,0 @@ |
|||||
/*! |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* \file timer.h |
|
||||
* \author ShizZy <shizzy247@gmail.com> |
|
||||
* \date 2012-02-11 |
|
||||
* \brief Common time and timer routines |
|
||||
* |
|
||||
* \section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_TIMER_H_ |
|
||||
#define COMMON_TIMER_H_ |
|
||||
|
|
||||
#include "types.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/*! |
|
||||
* \brief Gets Get the number of milliseconds since initialization |
|
||||
* \return Unsigned integer of ticks since software initialization |
|
||||
*/ |
|
||||
static inline u32 GetTimeElapsed() { |
|
||||
return SDL_GetTicks(); |
|
||||
} |
|
||||
|
|
||||
/*! |
|
||||
* \brief Converts a ticks (miliseconds) u32 to a formatted string |
|
||||
* \param ticks Ticks (32-bit unsigned integer) |
|
||||
* \param formatted_string Pointer to formatted string result |
|
||||
*/ |
|
||||
void TicksToFormattedString(u32 ticks, char* formatted_string); |
|
||||
|
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
|
|
||||
#endif // COMMON_TIMER_H_ |
|
||||
@ -1,119 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file types.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Common types used throughout the project |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_TYPES_H_ |
|
||||
#define COMMON_TYPES_H_ |
|
||||
|
|
||||
#include <math.h> |
|
||||
#include <xmmintrin.h> // data_types__m128.cpp |
|
||||
|
|
||||
typedef unsigned char u8; ///< 8-bit unsigned byte |
|
||||
typedef unsigned short u16; ///< 16-bit unsigned short |
|
||||
typedef unsigned int u32; ///< 32-bit unsigned word |
|
||||
|
|
||||
typedef signed char s8; ///< 8-bit signed byte |
|
||||
typedef signed short s16; ///< 16-bit signed short |
|
||||
typedef signed int s32; ///< 32-bit signed word |
|
||||
|
|
||||
typedef signed int x32; ///< S15.16 fixed point int |
|
||||
|
|
||||
typedef float f32; ///< 32-bit floating point |
|
||||
typedef double f64; ///< 64-bit floating point |
|
||||
|
|
||||
#ifdef _MSC_VER |
|
||||
|
|
||||
typedef unsigned __int64 u64; ///< 64-bit unsigned int |
|
||||
typedef signed __int64 s64; ///< 64-bit signed int |
|
||||
|
|
||||
#elif defined(__GNUC__) |
|
||||
|
|
||||
typedef signed long long s64; ///< 64-bit unsigned int |
|
||||
typedef unsigned long long u64; ///< 64-bit signed int |
|
||||
|
|
||||
#define U64(a) a ## ull |
|
||||
#define S64(a) a ## sll |
|
||||
|
|
||||
#endif |
|
||||
|
|
||||
/// Union for fast 16-bit type casting |
|
||||
union t16 { |
|
||||
u8 _u8[2]; ///< 8-bit unsigned char(s) |
|
||||
u16 _u16; ///< 16-bit unsigned shorts(s) |
|
||||
}; |
|
||||
|
|
||||
/// Union for fast 32-bit type casting |
|
||||
union t32 { |
|
||||
f32 _f32; ///< 32-bit floating point(s) |
|
||||
u32 _u32; ///< 32-bit unsigned int(s) |
|
||||
x32 _x32; ///< 32-bit fixed point(s) |
|
||||
u16 _u16[2]; ///< 16-bit unsigned shorts(s) |
|
||||
u8 _u8[4]; ///< 8-bit unsigned char(s) |
|
||||
}; |
|
||||
|
|
||||
/// Union for fast 64-bit type casting |
|
||||
union t64 { |
|
||||
f64 _f64; ///< 64-bit floating point |
|
||||
u64 _u64; ///< 64-bit unsigned long |
|
||||
f32 _f32[2]; ///< 32-bit floating point(s) |
|
||||
u32 _u32[2]; ///< 32-bit unsigned int(s) |
|
||||
x32 _x32[2]; ///< 32-bit fixed point(s) |
|
||||
u16 _u16[4]; ///< 16-bit unsigned shorts(s) |
|
||||
u8 _u8[8]; ///< 8-bit unsigned char(s) |
|
||||
}; |
|
||||
|
|
||||
/// Union for fast 128-bit type casting |
|
||||
union t128 { |
|
||||
struct |
|
||||
{ |
|
||||
t64 ps0; ///< 64-bit paired single 0 |
|
||||
t64 ps1; ///< 64-bit paired single 1 |
|
||||
}; |
|
||||
__m128 a; ///< 128-bit floating point (__m128 maps to the XMM[0-7] registers) |
|
||||
}; |
|
||||
|
|
||||
/// 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 abs(x1_ - x0_); } |
|
||||
inline u32 height() const { return abs(y1_ - y0_); } |
|
||||
|
|
||||
inline bool operator == (const Rect& val) const { |
|
||||
return (x0_ == val.x0_ && y0_ == val.y0_ && x1_ == val.x1_ && y1_ == val.y1_); |
|
||||
} |
|
||||
}; |
|
||||
|
|
||||
#endif // COMMON_TYPES_H_ |
|
||||
@ -1,236 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file x86_utils.cpp |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-12-23 |
|
||||
* @brief Utilities for the x86 architecture |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include "common.h"
|
|
||||
#include "x86_utils.h"
|
|
||||
|
|
||||
#ifdef _WIN32
|
|
||||
#define _interlockedbittestandset workaround_ms_header_bug_platform_sdk6_set
|
|
||||
#define _interlockedbittestandreset workaround_ms_header_bug_platform_sdk6_reset
|
|
||||
#define _interlockedbittestandset64 workaround_ms_header_bug_platform_sdk6_set64
|
|
||||
#define _interlockedbittestandreset64 workaround_ms_header_bug_platform_sdk6_reset64
|
|
||||
#include <intrin.h>
|
|
||||
#undef _interlockedbittestandset
|
|
||||
#undef _interlockedbittestandreset
|
|
||||
#undef _interlockedbittestandset64
|
|
||||
#undef _interlockedbittestandreset64
|
|
||||
#else
|
|
||||
|
|
||||
//#include <config/i386/cpuid.h>
|
|
||||
#include <xmmintrin.h>
|
|
||||
|
|
||||
#if defined __FreeBSD__
|
|
||||
#include <sys/types.h>
|
|
||||
#include <machine/cpufunc.h>
|
|
||||
#else
|
|
||||
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx, |
|
||||
unsigned int *ecx, unsigned int *edx) |
|
||||
{ |
|
||||
#ifdef _LP64
|
|
||||
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to
|
|
||||
// restored at the end of the asm block.
|
|
||||
__asm__ ( |
|
||||
"cpuid;" |
|
||||
"movl %%ebx,%1;" |
|
||||
: "=a" (*eax), |
|
||||
"=S" (*ebx), |
|
||||
"=c" (*ecx), |
|
||||
"=d" (*edx) |
|
||||
: "a" (*eax) |
|
||||
: "rbx" |
|
||||
); |
|
||||
#else
|
|
||||
__asm__ ( |
|
||||
"cpuid;" |
|
||||
"movl %%ebx,%1;" |
|
||||
: "=a" (*eax), |
|
||||
"=S" (*ebx), |
|
||||
"=c" (*ecx), |
|
||||
"=d" (*edx) |
|
||||
: "a" (*eax) |
|
||||
: "ebx" |
|
||||
); |
|
||||
#endif
|
|
||||
} |
|
||||
#endif
|
|
||||
|
|
||||
static void __cpuid(int info[4], int x) |
|
||||
{ |
|
||||
#if defined __FreeBSD__
|
|
||||
do_cpuid((unsigned int)x, (unsigned int*)info); |
|
||||
#else
|
|
||||
unsigned int eax = x, ebx = 0, ecx = 0, edx = 0; |
|
||||
do_cpuid(&eax, &ebx, &ecx, &edx); |
|
||||
info[0] = eax; |
|
||||
info[1] = ebx; |
|
||||
info[2] = ecx; |
|
||||
info[3] = edx; |
|
||||
#endif
|
|
||||
} |
|
||||
|
|
||||
#endif
|
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
X86Utils::X86Utils() { |
|
||||
memset(this, 0, sizeof(*this)); |
|
||||
#ifdef _M_IX86
|
|
||||
|
|
||||
#elif defined (_M_X64)
|
|
||||
support_x64_os_ = true; |
|
||||
support_sse_ = true; |
|
||||
support_sse2_ = true; |
|
||||
#endif
|
|
||||
num_cores_ = 1; |
|
||||
#ifdef _WIN32
|
|
||||
#ifdef _M_IX86
|
|
||||
int f64 = 0; |
|
||||
IsWow64Process(GetCurrentProcess(), &f64); |
|
||||
support_x64_os_ = (f64 == 1) ? true : false; |
|
||||
#endif
|
|
||||
#endif
|
|
||||
// Assume CPU supports the CPUID instruction. Those that don't can barely
|
|
||||
// boot modern OS:es anyway.
|
|
||||
int cpu_id[4]; |
|
||||
char cpu_string[32]; |
|
||||
memset(cpu_string, 0, sizeof(cpu_string)); |
|
||||
|
|
||||
// Detect CPU's CPUID capabilities, and grab cpu string
|
|
||||
__cpuid(cpu_id, 0x00000000); |
|
||||
u32 max_std_fn = cpu_id[0]; // EAX
|
|
||||
*((int *)cpu_string) = cpu_id[1]; |
|
||||
*((int *)(cpu_string + 4)) = cpu_id[3]; |
|
||||
*((int *)(cpu_string + 8)) = cpu_id[2]; |
|
||||
__cpuid(cpu_id, 0x80000000); |
|
||||
u32 max_ex_fn = cpu_id[0]; |
|
||||
if (!strcmp(cpu_string, "GenuineIntel")) { |
|
||||
cpu_vendor_ = kVendorX86_Intel; |
|
||||
} else if (!strcmp(cpu_string, "AuthenticAMD")) { |
|
||||
cpu_vendor_ = kVendorX86_AMD; |
|
||||
} else { |
|
||||
cpu_vendor_ = kVendorX86_None; |
|
||||
} |
|
||||
|
|
||||
// Detect family and other misc stuff.
|
|
||||
bool ht = false; |
|
||||
support_hyper_threading_ = ht; |
|
||||
logical_cpu_count_ = 1; |
|
||||
if (max_std_fn >= 1) { |
|
||||
__cpuid(cpu_id, 0x00000001); |
|
||||
logical_cpu_count_ = (cpu_id[1] >> 16) & 0xFF; |
|
||||
ht = (cpu_id[3] >> 28) & 1; |
|
||||
|
|
||||
if ((cpu_id[3] >> 25) & 1) support_sse_ = true; |
|
||||
if ((cpu_id[3] >> 26) & 1) support_sse2_ = true; |
|
||||
if ((cpu_id[2]) & 1) support_sse3_ = true; |
|
||||
if ((cpu_id[2] >> 9) & 1) support_ssse3_ = true; |
|
||||
if ((cpu_id[2] >> 19) & 1) support_sse4_1_ = true; |
|
||||
if ((cpu_id[2] >> 20) & 1) support_sse4_2_ = true; |
|
||||
} |
|
||||
if (max_ex_fn >= 0x80000004) { |
|
||||
// Extract brand string
|
|
||||
__cpuid(cpu_id, 0x80000002); |
|
||||
// memcpy(brand_string, cpu_id, sizeof(cpu_id));
|
|
||||
__cpuid(cpu_id, 0x80000003); |
|
||||
// memcpy(brand_string + 16, cpu_id, sizeof(cpu_id));
|
|
||||
__cpuid(cpu_id, 0x80000004); |
|
||||
// memcpy(brand_string + 32, cpu_id, sizeof(cpu_id));
|
|
||||
} |
|
||||
num_cores_ = (logical_cpu_count_ == 0) ? 1 : logical_cpu_count_; |
|
||||
|
|
||||
if (max_ex_fn >= 0x80000008) { |
|
||||
// Get number of cores. This is a bit complicated. Following AMD manual here.
|
|
||||
__cpuid(cpu_id, 0x80000008); |
|
||||
int apic_id_core_id_size = (cpu_id[2] >> 12) & 0xF; |
|
||||
if (apic_id_core_id_size == 0) { |
|
||||
if (ht) { |
|
||||
// New mechanism for modern Intel CPUs.
|
|
||||
if (cpu_vendor_ == kVendorX86_Intel) { |
|
||||
__cpuid(cpu_id, 0x00000004); |
|
||||
int cores_x_package = ((cpu_id[0] >> 26) & 0x3F) + 1; |
|
||||
support_hyper_threading_ = (cores_x_package < logical_cpu_count_); |
|
||||
cores_x_package = ((logical_cpu_count_ % cores_x_package) == 0) ? cores_x_package : 1; |
|
||||
num_cores_ = (cores_x_package > 1) ? cores_x_package : num_cores_; |
|
||||
logical_cpu_count_ /= cores_x_package; |
|
||||
} |
|
||||
} |
|
||||
} else { |
|
||||
// Use AMD's new method.
|
|
||||
num_cores_ = (cpu_id[2] & 0xFF) + 1; |
|
||||
} |
|
||||
} |
|
||||
LOG_NOTICE(TCOMMON, "CPU detected (%s)", this->Summary().c_str()); |
|
||||
} |
|
||||
|
|
||||
X86Utils::~X86Utils() { |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* Check if an X86 extension is supported by the current architecture |
|
||||
* @param extension ExtensionX86 extension support to check for |
|
||||
* @return True if the extension is supported, otherwise false |
|
||||
*/ |
|
||||
bool X86Utils::IsExtensionSupported(X86Utils::ExtensionX86 extension) { |
|
||||
switch (extension) { |
|
||||
case kExtensionX86_SSE: |
|
||||
return support_sse_; |
|
||||
case kExtensionX86_SSE2: |
|
||||
return support_sse2_; |
|
||||
case kExtensionX86_SSE3: |
|
||||
return support_sse3_; |
|
||||
case kExtensionX86_SSSE3: |
|
||||
return support_ssse3_; |
|
||||
case kExtensionX86_SSE4_1: |
|
||||
return support_sse4_1_; |
|
||||
case kExtensionX86_SSE4_2: |
|
||||
return support_sse4_2_; |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* Gets a string summary of the X86 CPU information, suitable for printing |
|
||||
* @return String summary |
|
||||
*/ |
|
||||
std::string X86Utils::Summary() { |
|
||||
const char* cpu_vendors[] = { |
|
||||
"Unknown", "Intel", "AMD" |
|
||||
}; |
|
||||
std::string res; |
|
||||
res = FormatStr("%s, %d core%s", cpu_vendors[cpu_vendor_], num_cores_, (num_cores_ > 1) ? "s" : ""); |
|
||||
if (support_sse4_2_) { |
|
||||
res += FormatStr(" (%i logical threads per physical core)", logical_cpu_count_); |
|
||||
} |
|
||||
if (support_sse_) res += ", SSE"; |
|
||||
if (support_sse2_) res += ", SSE2"; |
|
||||
if (support_sse3_) res += ", SSE3"; |
|
||||
if (support_ssse3_) res += ", SSSE3"; |
|
||||
if (support_sse4_1_) res += ", SSE4.1"; |
|
||||
if (support_sse4_2_) res += ", SSE4.2"; |
|
||||
if (support_hyper_threading_) res += ", HTT"; |
|
||||
//if (bLongMode) res += ", 64-bit support";
|
|
||||
return res; |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,92 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file x86_utils.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-11 |
|
||||
* @brief Utilities for the x86 architecture |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_X86_UTILS_ |
|
||||
#define COMMON_X86_UTILS_ |
|
||||
|
|
||||
#include <string> |
|
||||
#include "types.h" |
|
||||
|
|
||||
// Common namespace |
|
||||
namespace common { |
|
||||
|
|
||||
class X86Utils { |
|
||||
public: |
|
||||
/// Enumeration of X86 vendors |
|
||||
enum VendorX86 { |
|
||||
kVendorX86_None = 0, |
|
||||
kVendorX86_Intel, |
|
||||
kVendorX86_AMD, |
|
||||
kVendorX86_NumberOf |
|
||||
}; |
|
||||
|
|
||||
/// Enumeration of X86 extensions |
|
||||
enum ExtensionX86 { |
|
||||
kExtensionX86_None = 0, |
|
||||
kExtensionX86_SSE, |
|
||||
kExtensionX86_SSE2, |
|
||||
kExtensionX86_SSE3, |
|
||||
kExtensionX86_SSSE3, |
|
||||
kExtensionX86_SSE4_1, |
|
||||
kExtensionX86_SSE4_2, |
|
||||
kExtensionX86_NumberOf |
|
||||
}; |
|
||||
|
|
||||
X86Utils(); |
|
||||
~X86Utils(); |
|
||||
|
|
||||
/** |
|
||||
* Check if an X86 extension is supported by the current architecture |
|
||||
* @param extension ExtensionX86 extension support to check for |
|
||||
* @return True if the extension is supported, otherwise false |
|
||||
*/ |
|
||||
bool IsExtensionSupported(ExtensionX86 extension); |
|
||||
|
|
||||
/** |
|
||||
* Gets a string summary of the X86 CPU information, suitable for printing |
|
||||
* @return String summary |
|
||||
*/ |
|
||||
std::string Summary(); |
|
||||
|
|
||||
private: |
|
||||
bool support_x64_os_; |
|
||||
bool support_x64_cpu_; |
|
||||
bool support_hyper_threading_; |
|
||||
|
|
||||
int num_cores_; |
|
||||
int logical_cpu_count_; |
|
||||
|
|
||||
bool support_sse_; |
|
||||
bool support_sse2_; |
|
||||
bool support_sse3_; |
|
||||
bool support_ssse3_; |
|
||||
bool support_sse4_1_; |
|
||||
bool support_sse4_2_; |
|
||||
|
|
||||
VendorX86 cpu_vendor_; |
|
||||
}; |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
#endif |
|
||||
@ -1,487 +0,0 @@ |
|||||
/**
|
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file xml.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-12 |
|
||||
* @brief Used for parsing XML configurations |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html
|
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/
|
|
||||
*/ |
|
||||
|
|
||||
#include <iostream>
|
|
||||
#include <fstream>
|
|
||||
|
|
||||
#include <rapidxml.hpp>
|
|
||||
|
|
||||
#include "common.h"
|
|
||||
#include "misc_utils.h"
|
|
||||
#include "config.h"
|
|
||||
#include "log.h"
|
|
||||
|
|
||||
/// Gets a RapidXML boolean element value
|
|
||||
static bool GetXMLElementAsBool(rapidxml::xml_node<> *node, const char* element_name) { |
|
||||
rapidxml::xml_node<> *sub_node = node->first_node(element_name); |
|
||||
if (sub_node) { |
|
||||
return (E_OK == _stricmp(sub_node->value(), "true")) ? true : false; |
|
||||
} |
|
||||
return false; |
|
||||
} |
|
||||
|
|
||||
/// Gets a RapidXML string element value
|
|
||||
static char* GetXMLElementAsString(rapidxml::xml_node<> *node, const char* element_name, |
|
||||
char* element_value) { |
|
||||
rapidxml::xml_node<> *sub_node = node->first_node(element_name); |
|
||||
if (sub_node) { |
|
||||
strcpy(element_value, sub_node->value()); |
|
||||
return element_value; |
|
||||
} |
|
||||
return NULL; |
|
||||
} |
|
||||
|
|
||||
/// Gets a RapidXML integer element value
|
|
||||
static int GetXMLElementAsInt(rapidxml::xml_node<> *node, const char* element_name) { |
|
||||
rapidxml::xml_node<> *sub_node = node->first_node(element_name); |
|
||||
if (sub_node) { |
|
||||
return atoi(sub_node->value()); |
|
||||
} |
|
||||
return 0; |
|
||||
} |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "General" XML group |
|
||||
* @param node RapidXML node for the "General" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParseGeneralNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
// Don't parse the node if it doesn't exist!
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
char temp_str[MAX_PATH]; |
|
||||
config.set_enable_multicore(GetXMLElementAsBool(node, "EnableMultiCore")); |
|
||||
config.set_enable_idle_skipping(GetXMLElementAsBool(node, "EnableIdleSkipping")); |
|
||||
config.set_enable_hle(GetXMLElementAsBool(node, "EnableHLE")); |
|
||||
config.set_enable_auto_boot(GetXMLElementAsBool(node, "EnableAutoBoot")); |
|
||||
config.set_enable_cheats(GetXMLElementAsBool(node, "EnableCheats")); |
|
||||
config.set_default_boot_file(GetXMLElementAsString(node, "DefaultBootFile", temp_str), MAX_PATH); |
|
||||
|
|
||||
// Parse all search paths in the DVDImagePaths node
|
|
||||
rapidxml::xml_node<> *sub_node = node->first_node("DVDImagePaths"); |
|
||||
if (sub_node) { |
|
||||
int i = 0; |
|
||||
for (rapidxml::xml_node<> *elem = sub_node->first_node("Path"); elem; |
|
||||
elem = elem->next_sibling()) { |
|
||||
|
|
||||
config.set_dvd_image_path(i, elem->value(), MAX_PATH); |
|
||||
LOG_NOTICE(TCONFIG, "Adding %s to DVD image search paths...\n", |
|
||||
config.dvd_image_path(i)); |
|
||||
i++; |
|
||||
// Stop if we have parsed the maximum paths
|
|
||||
if (MAX_SEARCH_PATHS < i) { |
|
||||
LOG_WARNING(TCONFIG, "Maximum number of DVDImagePath search paths is %d, not parsing" |
|
||||
" any more!", MAX_SEARCH_PATHS); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Debug" XML group |
|
||||
* @param node RapidXML node for the "Debug" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParseDebugNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
// Don't parse the node if it doesn't exist!
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
config.set_enable_show_fps(GetXMLElementAsBool(node, "EnableShowFPS")); |
|
||||
config.set_enable_dump_opcode0(GetXMLElementAsBool(node, "EnableDumpOpcode0")); |
|
||||
config.set_enable_pause_on_unknown_opcode(GetXMLElementAsBool(node, |
|
||||
"EnablePauseOnUnknownOpcode")); |
|
||||
config.set_enable_dump_gcm_reads(GetXMLElementAsBool(node, "EnableDumpGCMReads")); |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Patches" and "Cheats" XML group |
|
||||
* @param node RapidXML node for the "Patches" or "Cheats" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParsePatchesNode(rapidxml::xml_node<> *node, Config& config, const char* node_name) { |
|
||||
int i = 0; |
|
||||
char node_name_str[8]; |
|
||||
|
|
||||
// Get lowercase section name
|
|
||||
strcpy(node_name_str, node_name); |
|
||||
|
|
||||
// TODO: not available on Unix
|
|
||||
common::LowerStr(node_name_str); |
|
||||
|
|
||||
// Parse all search patches in the Patches node
|
|
||||
rapidxml::xml_node<> *sub_node = node->first_node(node_name); |
|
||||
if (sub_node) { |
|
||||
for (rapidxml::xml_node<> *elem = sub_node->first_node("Patch"); elem; |
|
||||
elem = elem->next_sibling()) { |
|
||||
|
|
||||
// Get enable attribute (note: defaults to true)
|
|
||||
rapidxml::xml_attribute<> *attr = elem->first_attribute("enable"); |
|
||||
if (attr) { |
|
||||
if (E_OK == _stricmp(attr->value(), "false")) { |
|
||||
continue; // Patch is disabled, skip it
|
|
||||
} |
|
||||
} |
|
||||
// Get address attribute
|
|
||||
attr = elem->first_attribute("address"); |
|
||||
if (!attr) { |
|
||||
LOG_ERROR(TCONFIG, "Patch without 'address' attribute illegal!"); |
|
||||
continue; |
|
||||
} else { |
|
||||
u32 data = 0; |
|
||||
u32 address = 0; |
|
||||
{ |
|
||||
// Convert address hexstring to unsigned int
|
|
||||
std::stringstream ss; |
|
||||
ss << std::hex << attr->value(); |
|
||||
ss >> address; |
|
||||
} |
|
||||
attr = elem->first_attribute("instr"); |
|
||||
|
|
||||
// Get "data" attribute if no "instr" attribute
|
|
||||
if (!attr) { |
|
||||
attr = elem->first_attribute("data"); |
|
||||
// Neither found - error
|
|
||||
if (!attr) { |
|
||||
LOG_ERROR(TCONFIG, "Patch without 'instr' or 'data' attributes " |
|
||||
"illegal!"); |
|
||||
continue; |
|
||||
} else { |
|
||||
// Found data, convert hexstring to unsigned int
|
|
||||
std::stringstream ss; |
|
||||
ss << std::hex << attr->value(); |
|
||||
ss >> data; |
|
||||
} |
|
||||
} else { |
|
||||
// Found instr
|
|
||||
char instr_str[4]; |
|
||||
|
|
||||
// Convert to lowercase
|
|
||||
strcpy(instr_str, attr->value()); |
|
||||
// TODO: not available on Unix
|
|
||||
common::LowerStr(instr_str); |
|
||||
|
|
||||
// Convert instruction to equivalent PPC bytecode
|
|
||||
// TODO(ShizZy): Pull this out to the PowerPC modules at some point
|
|
||||
if (E_OK == _stricmp(instr_str, "blr")) { |
|
||||
data = 0x4E800020; // PowerPC BLR instruction bytecode
|
|
||||
} else if (E_OK == _stricmp(instr_str, "nop")) { |
|
||||
data = 0x60000000; // PowerPC NOP instruction bytecode
|
|
||||
} else { |
|
||||
LOG_ERROR(TCONFIG, "Patch with invalid 'instr' attribute illegal!"); |
|
||||
continue; |
|
||||
} |
|
||||
} |
|
||||
Config::Patch patch = { address, data }; |
|
||||
|
|
||||
if (E_OK == _stricmp(node_name_str, "patches")) { |
|
||||
LOG_NOTICE(TCONFIG, "Adding patch addr=0x%08x data=0x%08x to patches...\n", |
|
||||
address, data, node_name_str); |
|
||||
config.set_patches(i, patch); |
|
||||
} else if (E_OK == _stricmp(node_name_str, "cheats")) { |
|
||||
LOG_NOTICE(TCONFIG, "Adding cheat addr=0x%08x data=0x%08x to cheats...\n", |
|
||||
address, data, node_name_str); |
|
||||
config.set_cheats(i, patch); |
|
||||
} else { |
|
||||
LOG_ERROR(TCONFIG, "Unexpected patch type %s, ignoring...", node_name_str); |
|
||||
} |
|
||||
|
|
||||
// Stop if we have parsed the maximum patches
|
|
||||
if (MAX_PATCHES_PER_GAME < ++i) { |
|
||||
LOG_WARNING(TCONFIG, "Maximum number of patches search paths is %d, not parsing" |
|
||||
" any more!", MAX_PATCHES_PER_GAME); |
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Boot" XML group |
|
||||
* @param node RapidXML node for the "Boot" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParseBootNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
// Don't parse the node if it doesn't exist!
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
config.set_enable_ipl(GetXMLElementAsBool(node, "EnableIPL")); |
|
||||
|
|
||||
ParsePatchesNode(node, config, "Patches"); |
|
||||
ParsePatchesNode(node, config, "Cheats"); |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Video" XML group |
|
||||
* @param node RapidXML node for the "Video" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParsePowerPCNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
// Don't parse the node if it doesn't exist!
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
rapidxml::xml_attribute<> *attr = node->first_attribute("core"); |
|
||||
|
|
||||
// Attribute not found - error
|
|
||||
if (!attr) { |
|
||||
LOG_ERROR(TCONFIG, "PowerPC without 'core' attribute illegal!"); |
|
||||
} else { |
|
||||
char core_str[12] = "null"; |
|
||||
|
|
||||
// Convert to lowercase
|
|
||||
strcpy(core_str, attr->value()); |
|
||||
// TODO: not available on Unix
|
|
||||
common::LowerStr(core_str); |
|
||||
|
|
||||
// Use interpreter core
|
|
||||
if (E_OK == _stricmp(core_str, "interpreter")) { |
|
||||
config.set_powerpc_core(Config::CPU_INTERPRETER); // Interpreter selected
|
|
||||
// Use dynarec core
|
|
||||
} else if (E_OK == _stricmp(core_str, "dynarec")) { |
|
||||
config.set_powerpc_core(Config::CPU_DYNAREC); // Dynarec selected
|
|
||||
// Unsupported type
|
|
||||
} else { |
|
||||
LOG_ERROR(TCONFIG, "Invalid PowerPC type %s for attribute 'core' selected!", |
|
||||
core_str); |
|
||||
} |
|
||||
// Set frequency
|
|
||||
attr = node->first_attribute("freq"); |
|
||||
if (attr) { |
|
||||
config.set_powerpc_frequency(atoi(attr->value())); |
|
||||
} |
|
||||
LOG_NOTICE(TCONFIG, "Configured core=%s freq=%d", core_str, config.powerpc_frequency()); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Video" XML group |
|
||||
* @param node RapidXML node for the "Video" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParseVideoNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
char res_str[512]; |
|
||||
Config::ResolutionType res; |
|
||||
|
|
||||
// Don't parse the node if it doesn't exist!
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
config.set_enable_fullscreen(GetXMLElementAsBool(node, "EnableFullscreen")); |
|
||||
|
|
||||
// Set resolutions
|
|
||||
GetXMLElementAsString(node, "WindowResolution", res_str); |
|
||||
sscanf(res_str, "%d_%d", &res.width, &res.height); |
|
||||
config.set_window_resolution(res); |
|
||||
GetXMLElementAsString(node, "FullscreenResolution", res_str); |
|
||||
sscanf(res_str, "%d_%d", &res.width, &res.height); |
|
||||
config.set_fullscreen_resolution(res); |
|
||||
|
|
||||
// Parse all search renderer nodes
|
|
||||
for (rapidxml::xml_node<> *elem = node->first_node("Renderer"); 1; ) { |
|
||||
Config::RendererConfig renderer_config; |
|
||||
|
|
||||
rapidxml::xml_attribute<> *attr = elem->first_attribute("name"); |
|
||||
|
|
||||
Config::RendererType type = Config::StringToRenderType(attr->value()); |
|
||||
|
|
||||
renderer_config.enable_wireframe = GetXMLElementAsBool(elem, "EnableWireframe"); |
|
||||
renderer_config.enable_shaders = GetXMLElementAsBool(elem, "EnableShaders"); |
|
||||
renderer_config.enable_textures = GetXMLElementAsBool(elem, "EnableTextures"); |
|
||||
renderer_config.enable_texture_dumping = GetXMLElementAsBool(elem, "EnableTextureDumping"); |
|
||||
renderer_config.anti_aliasing_mode = GetXMLElementAsInt(elem, "AntiAliasingMode"); |
|
||||
renderer_config.anistropic_filtering_mode = GetXMLElementAsInt(elem, "AnistropicFilteringMode"); |
|
||||
|
|
||||
config.set_renderer_config(type, renderer_config); |
|
||||
|
|
||||
LOG_NOTICE(TCONFIG, "Renderer %s configured", attr->value()); |
|
||||
|
|
||||
break; |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/**
|
|
||||
* @brief Parse the "Devices" XML group |
|
||||
* @param node RapidXML node for the "Devices" XML group |
|
||||
* @param config Config class object to parse data into |
|
||||
*/ |
|
||||
void ParseDevicesNode(rapidxml::xml_node<> *node, Config& config) { |
|
||||
// Don't parse the node if it doesn't exist!c
|
|
||||
if (!node) { |
|
||||
return; |
|
||||
} |
|
||||
// Parse GameCube section
|
|
||||
rapidxml::xml_node<> *gamecube_node = node->first_node("GameCube"); |
|
||||
if (!gamecube_node) { |
|
||||
return; |
|
||||
} |
|
||||
// Parse all MemSlot nodes
|
|
||||
for (rapidxml::xml_node<> *elem = gamecube_node->first_node("MemSlot"); elem; |
|
||||
elem = elem->next_sibling("MemSlot")) { |
|
||||
Config::MemSlot slot_config; |
|
||||
|
|
||||
// Select MemSlot a or b
|
|
||||
rapidxml::xml_attribute<> *attr = elem->first_attribute("slot"); |
|
||||
int slot = (E_OK == _stricmp(attr->value(), "a")) ? 0 : 1; |
|
||||
|
|
||||
// Enable
|
|
||||
attr = elem->first_attribute("enable"); |
|
||||
slot_config.enable = (E_OK == _stricmp(attr->value(), "true")) ? true : false; |
|
||||
|
|
||||
// Select device
|
|
||||
attr = elem->first_attribute("device"); |
|
||||
slot_config.device = 0; // Only support memcards right now
|
|
||||
|
|
||||
LOG_NOTICE(TCONFIG, "Configured MemSlot[%d]=%s enabled=%s", slot, attr->value(), |
|
||||
slot_config.enable ? "true" : "false"); |
|
||||
|
|
||||
config.set_mem_slots(slot, slot_config); |
|
||||
} |
|
||||
// Parse all ControlerPort nodes
|
|
||||
for (rapidxml::xml_node<> *elem = gamecube_node->first_node("ControllerPort"); elem; |
|
||||
elem = elem->next_sibling("ControllerPort")) { |
|
||||
Config::ControllerPort port_config; |
|
||||
|
|
||||
// Select MemSlot a or b
|
|
||||
rapidxml::xml_attribute<> *attr = elem->first_attribute("port"); |
|
||||
int port = atoi(attr->value()); |
|
||||
|
|
||||
// Enable
|
|
||||
attr = elem->first_attribute("enable"); |
|
||||
port_config.enable = (E_OK == _stricmp(attr->value(), "true")) ? true : false; |
|
||||
|
|
||||
// Select device
|
|
||||
attr = elem->first_attribute("device"); |
|
||||
port_config.device = 0; // Only support memcards right now
|
|
||||
|
|
||||
LOG_NOTICE(TCONFIG, "Configured ControllerPort[%d]=%s enabled=%s", port, attr->value(), |
|
||||
port_config.enable ? "true" : "false"); |
|
||||
|
|
||||
// Parse keyboard configuration - TODO: Move to EmuWindow (?)
|
|
||||
rapidxml::xml_node<> *keyboard_node = elem->first_node("KeyboardController"); |
|
||||
if (keyboard_node) { |
|
||||
attr = keyboard_node->first_attribute("enable"); |
|
||||
port_config.keys.enable = (E_OK == _stricmp(attr->value(), "true")) ? true : false; |
|
||||
port_config.keys.key_code[Config::BUTTON_A] = GetXMLElementAsInt(keyboard_node, "AKey"); |
|
||||
port_config.keys.key_code[Config::BUTTON_B] = GetXMLElementAsInt(keyboard_node, "BKey"); |
|
||||
port_config.keys.key_code[Config::BUTTON_X] = GetXMLElementAsInt(keyboard_node, "XKey"); |
|
||||
port_config.keys.key_code[Config::BUTTON_Y] = GetXMLElementAsInt(keyboard_node, "YKey"); |
|
||||
port_config.keys.key_code[Config::TRIGGER_L] = GetXMLElementAsInt(keyboard_node, "LKey"); |
|
||||
port_config.keys.key_code[Config::TRIGGER_R] = GetXMLElementAsInt(keyboard_node, "RKey"); |
|
||||
port_config.keys.key_code[Config::BUTTON_Z] = GetXMLElementAsInt(keyboard_node, "ZKey"); |
|
||||
port_config.keys.key_code[Config::BUTTON_START] = GetXMLElementAsInt(keyboard_node, "StartKey"); |
|
||||
port_config.keys.key_code[Config::ANALOG_UP] = GetXMLElementAsInt(keyboard_node, "AnalogUpKey"); |
|
||||
port_config.keys.key_code[Config::ANALOG_DOWN] = GetXMLElementAsInt(keyboard_node, "AnalogDownKey"); |
|
||||
port_config.keys.key_code[Config::ANALOG_LEFT] = GetXMLElementAsInt(keyboard_node, "AnalogLeftKey"); |
|
||||
port_config.keys.key_code[Config::ANALOG_RIGHT] = GetXMLElementAsInt(keyboard_node, "AnalogRightKey"); |
|
||||
port_config.keys.key_code[Config::C_UP] = GetXMLElementAsInt(keyboard_node, "CUpKey"); |
|
||||
port_config.keys.key_code[Config::C_DOWN] = GetXMLElementAsInt(keyboard_node, "CDownKey"); |
|
||||
port_config.keys.key_code[Config::C_LEFT] = GetXMLElementAsInt(keyboard_node, "CLeftKey"); |
|
||||
port_config.keys.key_code[Config::C_RIGHT] = GetXMLElementAsInt(keyboard_node, "CRightKey"); |
|
||||
port_config.keys.key_code[Config::DPAD_UP] = GetXMLElementAsInt(keyboard_node, "DPadUpKey"); |
|
||||
port_config.keys.key_code[Config::DPAD_DOWN] = GetXMLElementAsInt(keyboard_node, "DPadDownKey"); |
|
||||
port_config.keys.key_code[Config::DPAD_LEFT] = GetXMLElementAsInt(keyboard_node, "DPadLeftKey"); |
|
||||
port_config.keys.key_code[Config::DPAD_RIGHT] = GetXMLElementAsInt(keyboard_node, "DPadRightKey"); |
|
||||
} |
|
||||
|
|
||||
// Parse joypad configuration
|
|
||||
rapidxml::xml_node<> *joypad_node = elem->first_node("JoypadController"); |
|
||||
if (joypad_node) { |
|
||||
attr = joypad_node->first_attribute("enable"); |
|
||||
port_config.pads.enable = (E_OK == _stricmp(attr->value(), "true")) ? true : false; |
|
||||
port_config.pads.key_code[Config::BUTTON_A] = GetXMLElementAsInt(joypad_node, "AKey"); |
|
||||
port_config.pads.key_code[Config::BUTTON_B] = GetXMLElementAsInt(joypad_node, "BKey"); |
|
||||
port_config.pads.key_code[Config::BUTTON_X] = GetXMLElementAsInt(joypad_node, "XKey"); |
|
||||
port_config.pads.key_code[Config::BUTTON_Y] = GetXMLElementAsInt(joypad_node, "YKey"); |
|
||||
port_config.pads.key_code[Config::TRIGGER_L] = GetXMLElementAsInt(joypad_node, "LKey"); |
|
||||
port_config.pads.key_code[Config::TRIGGER_R] = GetXMLElementAsInt(joypad_node, "RKey"); |
|
||||
port_config.pads.key_code[Config::BUTTON_Z] = GetXMLElementAsInt(joypad_node, "ZKey"); |
|
||||
port_config.pads.key_code[Config::BUTTON_START] = GetXMLElementAsInt(joypad_node, "StartKey"); |
|
||||
port_config.pads.key_code[Config::ANALOG_UP] = GetXMLElementAsInt(joypad_node, "AnalogUpKey"); |
|
||||
port_config.pads.key_code[Config::ANALOG_DOWN] = GetXMLElementAsInt(joypad_node, "AnalogDownKey"); |
|
||||
port_config.pads.key_code[Config::ANALOG_LEFT] = GetXMLElementAsInt(joypad_node, "AnalogLeftKey"); |
|
||||
port_config.pads.key_code[Config::ANALOG_RIGHT] = GetXMLElementAsInt(joypad_node, "AnalogRightKey"); |
|
||||
port_config.pads.key_code[Config::C_UP] = GetXMLElementAsInt(joypad_node, "CUpKey"); |
|
||||
port_config.pads.key_code[Config::C_DOWN] = GetXMLElementAsInt(joypad_node, "CDownKey"); |
|
||||
port_config.pads.key_code[Config::C_LEFT] = GetXMLElementAsInt(joypad_node, "CLeftKey"); |
|
||||
port_config.pads.key_code[Config::C_RIGHT] = GetXMLElementAsInt(joypad_node, "CRightKey"); |
|
||||
port_config.pads.key_code[Config::DPAD_UP] = GetXMLElementAsInt(joypad_node, "DPadUpKey"); |
|
||||
port_config.pads.key_code[Config::DPAD_DOWN] = GetXMLElementAsInt(joypad_node, "DPadDownKey"); |
|
||||
port_config.pads.key_code[Config::DPAD_LEFT] = GetXMLElementAsInt(joypad_node, "DPadLeftKey"); |
|
||||
port_config.pads.key_code[Config::DPAD_RIGHT] = GetXMLElementAsInt(joypad_node, "DPadRightKey"); |
|
||||
} |
|
||||
config.set_controller_ports(port, port_config); |
|
||||
} |
|
||||
} |
|
||||
|
|
||||
/// Loads/parses an XML configuration file
|
|
||||
void LoadXMLConfig(Config& config, const char* filename) { |
|
||||
// Open the XML file
|
|
||||
char full_filename[MAX_PATH]; |
|
||||
strcpy(full_filename, config.program_dir()); |
|
||||
strcat(full_filename, filename); |
|
||||
std::ifstream ifs(full_filename); |
|
||||
|
|
||||
// Check that the file is valid
|
|
||||
if (ifs.fail()) { |
|
||||
LOG_ERROR(TCONFIG, "XML configuration file %s failed to open!", filename); |
|
||||
return; |
|
||||
} |
|
||||
// Read and parse XML string
|
|
||||
std::string xml_str((std::istreambuf_iterator<char>(ifs)), std::istreambuf_iterator<char>()); |
|
||||
rapidxml::xml_document<> doc; |
|
||||
doc.parse<0>(const_cast<char *>(xml_str.c_str())); |
|
||||
|
|
||||
// Try to load a system configuration
|
|
||||
rapidxml::xml_node<> *node = doc.first_node("SysConfig"); |
|
||||
|
|
||||
// Try to load a game configuation
|
|
||||
if (!node) { |
|
||||
node = doc.first_node("GameConfig"); |
|
||||
} |
|
||||
// Try to load a user configuation
|
|
||||
if (!node) { |
|
||||
node = doc.first_node("UserConfig"); |
|
||||
} |
|
||||
// Not proper XML format
|
|
||||
if (!node) { |
|
||||
LOG_ERROR(TCONFIG, "XML configuration file incorrect format %s!", filename) |
|
||||
return; |
|
||||
} |
|
||||
// Parse all sub nodes into the config
|
|
||||
ParseGeneralNode(node->first_node("General"), config); |
|
||||
ParseDebugNode(node->first_node("Debug"), config); |
|
||||
ParseBootNode(node->first_node("Boot"), config); |
|
||||
ParsePowerPCNode(node->first_node("PowerPC"), config); |
|
||||
ParseVideoNode(node->first_node("Video"), config); |
|
||||
ParseDevicesNode(node->first_node("Devices"), config); |
|
||||
} |
|
||||
|
|
||||
} // namespace
|
|
||||
@ -1,41 +0,0 @@ |
|||||
/** |
|
||||
* Copyright (C) 2005-2012 Gekko Emulator |
|
||||
* |
|
||||
* @file xml.h |
|
||||
* @author ShizZy <shizzy247@gmail.com> |
|
||||
* @date 2012-02-12 |
|
||||
* @brief Used for parsing XML configurations |
|
||||
* |
|
||||
* @section LICENSE |
|
||||
* 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; either version 2 of |
|
||||
* the License, or (at your option) any later version. |
|
||||
* |
|
||||
* 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 for more details at |
|
||||
* http://www.gnu.org/copyleft/gpl.html |
|
||||
* |
|
||||
* Official project repository can be found at: |
|
||||
* http://code.google.com/p/gekko-gc-emu/ |
|
||||
*/ |
|
||||
|
|
||||
#ifndef COMMON_XML_H_ |
|
||||
#define COMMON_XML_H_ |
|
||||
|
|
||||
#include "common.h" |
|
||||
|
|
||||
namespace common { |
|
||||
|
|
||||
/** |
|
||||
* @brief Loads/parses an XML configuration file |
|
||||
* @param config Reference to configuration object to populate |
|
||||
* @param filename Filename of XMl file to load |
|
||||
*/ |
|
||||
void LoadXMLConfig(Config& config, const char* filename); |
|
||||
|
|
||||
} // namespace |
|
||||
|
|
||||
#endif // COMMON_XML_H_ |
|
||||
Write
Preview
Loading…
Cancel
Save
Reference in new issue