1
0
Fork 0
forked from suyu/suyu

convert tabs to spaces

This commit is contained in:
bunnei 2014-04-01 18:20:08 -04:00
parent 4860480c36
commit c9b5b89e21
47 changed files with 4913 additions and 4913 deletions

View file

@ -1,18 +1,18 @@
set(SRCS src/break_points.cpp set(SRCS src/break_points.cpp
src/console_listener.cpp src/console_listener.cpp
src/extended_trace.cpp src/extended_trace.cpp
src/file_search.cpp src/file_search.cpp
src/file_util.cpp src/file_util.cpp
src/hash.cpp src/hash.cpp
src/log_manager.cpp src/log_manager.cpp
src/math_util.cpp src/math_util.cpp
src/mem_arena.cpp src/mem_arena.cpp
src/memory_util.cpp src/memory_util.cpp
src/misc.cpp src/misc.cpp
src/msg_handler.cpp src/msg_handler.cpp
src/string_util.cpp src/string_util.cpp
src/thread.cpp src/thread.cpp
src/timer.cpp src/timer.cpp
src/version.cpp) src/version.cpp)
add_library(common STATIC ${SRCS}) add_library(common STATIC ${SRCS})

View file

@ -25,42 +25,42 @@ namespace Common
{ {
inline void AtomicAdd(volatile u32& target, u32 value) { inline void AtomicAdd(volatile u32& target, u32 value) {
__sync_add_and_fetch(&target, value); __sync_add_and_fetch(&target, value);
} }
inline void AtomicAnd(volatile u32& target, u32 value) { inline void AtomicAnd(volatile u32& target, u32 value) {
__sync_and_and_fetch(&target, value); __sync_and_and_fetch(&target, value);
} }
inline void AtomicDecrement(volatile u32& target) { inline void AtomicDecrement(volatile u32& target) {
__sync_add_and_fetch(&target, -1); __sync_add_and_fetch(&target, -1);
} }
inline void AtomicIncrement(volatile u32& target) { inline void AtomicIncrement(volatile u32& target) {
__sync_add_and_fetch(&target, 1); __sync_add_and_fetch(&target, 1);
} }
inline u32 AtomicLoad(volatile u32& src) { inline u32 AtomicLoad(volatile u32& src) {
return src; // 32-bit reads are always atomic. return src; // 32-bit reads are always atomic.
} }
inline u32 AtomicLoadAcquire(volatile u32& src) { inline u32 AtomicLoadAcquire(volatile u32& src) {
//keep the compiler from caching any memory references //keep the compiler from caching any memory references
u32 result = src; // 32-bit reads are always atomic. u32 result = src; // 32-bit reads are always atomic.
//__sync_synchronize(); // TODO: May not be necessary. //__sync_synchronize(); // TODO: May not be necessary.
// Compiler instruction only. x86 loads always have acquire semantics. // Compiler instruction only. x86 loads always have acquire semantics.
__asm__ __volatile__ ( "":::"memory" ); __asm__ __volatile__ ( "":::"memory" );
return result; return result;
} }
inline void AtomicOr(volatile u32& target, u32 value) { inline void AtomicOr(volatile u32& target, u32 value) {
__sync_or_and_fetch(&target, value); __sync_or_and_fetch(&target, value);
} }
inline void AtomicStore(volatile u32& dest, u32 value) { inline void AtomicStore(volatile u32& dest, u32 value) {
dest = value; // 32-bit writes are always atomic. dest = value; // 32-bit writes are always atomic.
} }
inline void AtomicStoreRelease(volatile u32& dest, u32 value) { inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
__sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics. __sync_lock_test_and_set(&dest, value); // TODO: Wrong! This function is has acquire semantics.
} }
} }

View file

@ -31,40 +31,40 @@ namespace Common
{ {
inline void AtomicAdd(volatile u32& target, u32 value) { inline void AtomicAdd(volatile u32& target, u32 value) {
InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value); InterlockedExchangeAdd((volatile LONG*)&target, (LONG)value);
} }
inline void AtomicAnd(volatile u32& target, u32 value) { inline void AtomicAnd(volatile u32& target, u32 value) {
_InterlockedAnd((volatile LONG*)&target, (LONG)value); _InterlockedAnd((volatile LONG*)&target, (LONG)value);
} }
inline void AtomicIncrement(volatile u32& target) { inline void AtomicIncrement(volatile u32& target) {
InterlockedIncrement((volatile LONG*)&target); InterlockedIncrement((volatile LONG*)&target);
} }
inline void AtomicDecrement(volatile u32& target) { inline void AtomicDecrement(volatile u32& target) {
InterlockedDecrement((volatile LONG*)&target); InterlockedDecrement((volatile LONG*)&target);
} }
inline u32 AtomicLoad(volatile u32& src) { inline u32 AtomicLoad(volatile u32& src) {
return src; // 32-bit reads are always atomic. return src; // 32-bit reads are always atomic.
} }
inline u32 AtomicLoadAcquire(volatile u32& src) { inline u32 AtomicLoadAcquire(volatile u32& src) {
u32 result = src; // 32-bit reads are always atomic. u32 result = src; // 32-bit reads are always atomic.
_ReadBarrier(); // Compiler instruction only. x86 loads always have acquire semantics. _ReadBarrier(); // Compiler instruction only. x86 loads always have acquire semantics.
return result; return result;
} }
inline void AtomicOr(volatile u32& target, u32 value) { inline void AtomicOr(volatile u32& target, u32 value) {
_InterlockedOr((volatile LONG*)&target, (LONG)value); _InterlockedOr((volatile LONG*)&target, (LONG)value);
} }
inline void AtomicStore(volatile u32& dest, u32 value) { inline void AtomicStore(volatile u32& dest, u32 value) {
dest = value; // 32-bit writes are always atomic. dest = value; // 32-bit writes are always atomic.
} }
inline void AtomicStoreRelease(volatile u32& dest, u32 value) { inline void AtomicStoreRelease(volatile u32& dest, u32 value) {
_WriteBarrier(); // Compiler instruction only. x86 stores always have release semantics. _WriteBarrier(); // Compiler instruction only. x86 stores always have release semantics.
dest = value; // 32-bit writes are always atomic. dest = value; // 32-bit writes are always atomic.
} }
} }

View file

@ -11,193 +11,193 @@
bool BreakPoints::IsAddressBreakPoint(u32 _iAddress) bool BreakPoints::IsAddressBreakPoint(u32 _iAddress)
{ {
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i) for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
if (i->iAddress == _iAddress) if (i->iAddress == _iAddress)
return true; return true;
return false; return false;
} }
bool BreakPoints::IsTempBreakPoint(u32 _iAddress) bool BreakPoints::IsTempBreakPoint(u32 _iAddress)
{ {
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i) for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
if (i->iAddress == _iAddress && i->bTemporary) if (i->iAddress == _iAddress && i->bTemporary)
return true; return true;
return false; return false;
} }
BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const BreakPoints::TBreakPointsStr BreakPoints::GetStrings() const
{ {
TBreakPointsStr bps; TBreakPointsStr bps;
for (TBreakPoints::const_iterator i = m_BreakPoints.begin(); for (TBreakPoints::const_iterator i = m_BreakPoints.begin();
i != m_BreakPoints.end(); ++i) i != m_BreakPoints.end(); ++i)
{ {
if (!i->bTemporary) if (!i->bTemporary)
{ {
std::stringstream bp; std::stringstream bp;
bp << std::hex << i->iAddress << " " << (i->bOn ? "n" : ""); bp << std::hex << i->iAddress << " " << (i->bOn ? "n" : "");
bps.push_back(bp.str()); bps.push_back(bp.str());
} }
} }
return bps; return bps;
} }
void BreakPoints::AddFromStrings(const TBreakPointsStr& bps) void BreakPoints::AddFromStrings(const TBreakPointsStr& bps)
{ {
for (TBreakPointsStr::const_iterator i = bps.begin(); i != bps.end(); ++i) for (TBreakPointsStr::const_iterator i = bps.begin(); i != bps.end(); ++i)
{ {
TBreakPoint bp; TBreakPoint bp;
std::stringstream bpstr; std::stringstream bpstr;
bpstr << std::hex << *i; bpstr << std::hex << *i;
bpstr >> bp.iAddress; bpstr >> bp.iAddress;
bp.bOn = i->find("n") != i->npos; bp.bOn = i->find("n") != i->npos;
bp.bTemporary = false; bp.bTemporary = false;
Add(bp); Add(bp);
} }
} }
void BreakPoints::Add(const TBreakPoint& bp) void BreakPoints::Add(const TBreakPoint& bp)
{ {
if (!IsAddressBreakPoint(bp.iAddress)) if (!IsAddressBreakPoint(bp.iAddress))
{ {
m_BreakPoints.push_back(bp); m_BreakPoints.push_back(bp);
//if (jit) //if (jit)
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4); // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
} }
} }
void BreakPoints::Add(u32 em_address, bool temp) void BreakPoints::Add(u32 em_address, bool temp)
{ {
if (!IsAddressBreakPoint(em_address)) // only add new addresses if (!IsAddressBreakPoint(em_address)) // only add new addresses
{ {
TBreakPoint pt; // breakpoint settings TBreakPoint pt; // breakpoint settings
pt.bOn = true; pt.bOn = true;
pt.bTemporary = temp; pt.bTemporary = temp;
pt.iAddress = em_address; pt.iAddress = em_address;
m_BreakPoints.push_back(pt); m_BreakPoints.push_back(pt);
//if (jit) //if (jit)
// jit->GetBlockCache()->InvalidateICache(em_address, 4); // jit->GetBlockCache()->InvalidateICache(em_address, 4);
} }
} }
void BreakPoints::Remove(u32 em_address) void BreakPoints::Remove(u32 em_address)
{ {
for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i) for (TBreakPoints::iterator i = m_BreakPoints.begin(); i != m_BreakPoints.end(); ++i)
{ {
if (i->iAddress == em_address) if (i->iAddress == em_address)
{ {
m_BreakPoints.erase(i); m_BreakPoints.erase(i);
//if (jit) //if (jit)
// jit->GetBlockCache()->InvalidateICache(em_address, 4); // jit->GetBlockCache()->InvalidateICache(em_address, 4);
return; return;
} }
} }
} }
void BreakPoints::Clear() void BreakPoints::Clear()
{ {
//if (jit) //if (jit)
//{ //{
// std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(), // std::for_each(m_BreakPoints.begin(), m_BreakPoints.end(),
// [](const TBreakPoint& bp) // [](const TBreakPoint& bp)
// { // {
// jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4); // jit->GetBlockCache()->InvalidateICache(bp.iAddress, 4);
// } // }
// ); // );
//} //}
m_BreakPoints.clear(); m_BreakPoints.clear();
} }
MemChecks::TMemChecksStr MemChecks::GetStrings() const MemChecks::TMemChecksStr MemChecks::GetStrings() const
{ {
TMemChecksStr mcs; TMemChecksStr mcs;
for (TMemChecks::const_iterator i = m_MemChecks.begin(); for (TMemChecks::const_iterator i = m_MemChecks.begin();
i != m_MemChecks.end(); ++i) i != m_MemChecks.end(); ++i)
{ {
std::stringstream mc; std::stringstream mc;
mc << std::hex << i->StartAddress; mc << std::hex << i->StartAddress;
mc << " " << (i->bRange ? i->EndAddress : i->StartAddress) << " " << mc << " " << (i->bRange ? i->EndAddress : i->StartAddress) << " " <<
(i->bRange ? "n" : "") << (i->OnRead ? "r" : "") << (i->bRange ? "n" : "") << (i->OnRead ? "r" : "") <<
(i->OnWrite ? "w" : "") << (i->Log ? "l" : "") << (i->Break ? "p" : ""); (i->OnWrite ? "w" : "") << (i->Log ? "l" : "") << (i->Break ? "p" : "");
mcs.push_back(mc.str()); mcs.push_back(mc.str());
} }
return mcs; return mcs;
} }
void MemChecks::AddFromStrings(const TMemChecksStr& mcs) void MemChecks::AddFromStrings(const TMemChecksStr& mcs)
{ {
for (TMemChecksStr::const_iterator i = mcs.begin(); i != mcs.end(); ++i) for (TMemChecksStr::const_iterator i = mcs.begin(); i != mcs.end(); ++i)
{ {
TMemCheck mc; TMemCheck mc;
std::stringstream mcstr; std::stringstream mcstr;
mcstr << std::hex << *i; mcstr << std::hex << *i;
mcstr >> mc.StartAddress; mcstr >> mc.StartAddress;
mc.bRange = i->find("n") != i->npos; mc.bRange = i->find("n") != i->npos;
mc.OnRead = i->find("r") != i->npos; mc.OnRead = i->find("r") != i->npos;
mc.OnWrite = i->find("w") != i->npos; mc.OnWrite = i->find("w") != i->npos;
mc.Log = i->find("l") != i->npos; mc.Log = i->find("l") != i->npos;
mc.Break = i->find("p") != i->npos; mc.Break = i->find("p") != i->npos;
if (mc.bRange) if (mc.bRange)
mcstr >> mc.EndAddress; mcstr >> mc.EndAddress;
else else
mc.EndAddress = mc.StartAddress; mc.EndAddress = mc.StartAddress;
Add(mc); Add(mc);
} }
} }
void MemChecks::Add(const TMemCheck& _rMemoryCheck) void MemChecks::Add(const TMemCheck& _rMemoryCheck)
{ {
if (GetMemCheck(_rMemoryCheck.StartAddress) == 0) if (GetMemCheck(_rMemoryCheck.StartAddress) == 0)
m_MemChecks.push_back(_rMemoryCheck); m_MemChecks.push_back(_rMemoryCheck);
} }
void MemChecks::Remove(u32 _Address) void MemChecks::Remove(u32 _Address)
{ {
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i) for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
{ {
if (i->StartAddress == _Address) if (i->StartAddress == _Address)
{ {
m_MemChecks.erase(i); m_MemChecks.erase(i);
return; return;
} }
} }
} }
TMemCheck *MemChecks::GetMemCheck(u32 address) TMemCheck *MemChecks::GetMemCheck(u32 address)
{ {
for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i) for (TMemChecks::iterator i = m_MemChecks.begin(); i != m_MemChecks.end(); ++i)
{ {
if (i->bRange) if (i->bRange)
{ {
if (address >= i->StartAddress && address <= i->EndAddress) if (address >= i->StartAddress && address <= i->EndAddress)
return &(*i); return &(*i);
} }
else if (i->StartAddress == address) else if (i->StartAddress == address)
return &(*i); return &(*i);
} }
// none found // none found
return 0; return 0;
} }
void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr, void TMemCheck::Action(DebugInterface *debug_interface, u32 iValue, u32 addr,
bool write, int size, u32 pc) bool write, int size, u32 pc)
{ {
if ((write && OnWrite) || (!write && OnRead)) if ((write && OnWrite) || (!write && OnRead))
{ {
if (Log) if (Log)
{ {
INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)", INFO_LOG(MEMMAP, "CHK %08x (%s) %s%i %0*x at %08x (%s)",
pc, debug_interface->getDescription(pc).c_str(), pc, debug_interface->getDescription(pc).c_str(),
write ? "Write" : "Read", size*8, size*2, iValue, addr, write ? "Write" : "Read", size*8, size*2, iValue, addr,
debug_interface->getDescription(addr).c_str() debug_interface->getDescription(addr).c_str()
); );
} }
if (Break) if (Break)
debug_interface->breakNow(); debug_interface->breakNow();
} }
} }

View file

@ -14,64 +14,64 @@ class DebugInterface;
struct TBreakPoint struct TBreakPoint
{ {
u32 iAddress; u32 iAddress;
bool bOn; bool bOn;
bool bTemporary; bool bTemporary;
}; };
struct TMemCheck struct TMemCheck
{ {
TMemCheck() { TMemCheck() {
numHits = 0; numHits = 0;
StartAddress = EndAddress = 0; StartAddress = EndAddress = 0;
bRange = OnRead = OnWrite = Log = Break = false; bRange = OnRead = OnWrite = Log = Break = false;
} }
u32 StartAddress; u32 StartAddress;
u32 EndAddress; u32 EndAddress;
bool bRange; bool bRange;
bool OnRead; bool OnRead;
bool OnWrite; bool OnWrite;
bool Log; bool Log;
bool Break; bool Break;
u32 numHits; u32 numHits;
void Action(DebugInterface *dbg_interface, u32 _iValue, u32 addr, void Action(DebugInterface *dbg_interface, u32 _iValue, u32 addr,
bool write, int size, u32 pc); bool write, int size, u32 pc);
}; };
// Code breakpoints. // Code breakpoints.
class BreakPoints class BreakPoints
{ {
public: public:
typedef std::vector<TBreakPoint> TBreakPoints; typedef std::vector<TBreakPoint> TBreakPoints;
typedef std::vector<std::string> TBreakPointsStr; typedef std::vector<std::string> TBreakPointsStr;
const TBreakPoints& GetBreakPoints() { return m_BreakPoints; } const TBreakPoints& GetBreakPoints() { return m_BreakPoints; }
TBreakPointsStr GetStrings() const; TBreakPointsStr GetStrings() const;
void AddFromStrings(const TBreakPointsStr& bps); void AddFromStrings(const TBreakPointsStr& bps);
// is address breakpoint // is address breakpoint
bool IsAddressBreakPoint(u32 _iAddress); bool IsAddressBreakPoint(u32 _iAddress);
bool IsTempBreakPoint(u32 _iAddress); bool IsTempBreakPoint(u32 _iAddress);
// Add BreakPoint // Add BreakPoint
void Add(u32 em_address, bool temp=false); void Add(u32 em_address, bool temp=false);
void Add(const TBreakPoint& bp); void Add(const TBreakPoint& bp);
// Remove Breakpoint // Remove Breakpoint
void Remove(u32 _iAddress); void Remove(u32 _iAddress);
void Clear(); void Clear();
void DeleteByAddress(u32 _Address); void DeleteByAddress(u32 _Address);
private: private:
TBreakPoints m_BreakPoints; TBreakPoints m_BreakPoints;
u32 m_iBreakOnCount; u32 m_iBreakOnCount;
}; };
@ -79,23 +79,23 @@ private:
class MemChecks class MemChecks
{ {
public: public:
typedef std::vector<TMemCheck> TMemChecks; typedef std::vector<TMemCheck> TMemChecks;
typedef std::vector<std::string> TMemChecksStr; typedef std::vector<std::string> TMemChecksStr;
TMemChecks m_MemChecks; TMemChecks m_MemChecks;
const TMemChecks& GetMemChecks() { return m_MemChecks; } const TMemChecks& GetMemChecks() { return m_MemChecks; }
TMemChecksStr GetStrings() const; TMemChecksStr GetStrings() const;
void AddFromStrings(const TMemChecksStr& mcs); void AddFromStrings(const TMemChecksStr& mcs);
void Add(const TMemCheck& _rMemoryCheck); void Add(const TMemCheck& _rMemoryCheck);
// memory breakpoint // memory breakpoint
TMemCheck *GetMemCheck(u32 address); TMemCheck *GetMemCheck(u32 address);
void Remove(u32 _Address); void Remove(u32 _Address);
void Clear() { m_MemChecks.clear(); }; void Clear() { m_MemChecks.clear(); };
}; };
#endif #endif

File diff suppressed because it is too large Load diff

View file

@ -34,12 +34,12 @@ extern const char *netplay_dolphin_ver;
class NonCopyable class NonCopyable
{ {
protected: protected:
NonCopyable() {} NonCopyable() {}
NonCopyable(const NonCopyable&&) {} NonCopyable(const NonCopyable&&) {}
void operator=(const NonCopyable&&) {} void operator=(const NonCopyable&&) {}
private: private:
NonCopyable(NonCopyable&); NonCopyable(NonCopyable&);
NonCopyable& operator=(NonCopyable& other); NonCopyable& operator=(NonCopyable& other);
}; };
#endif #endif
@ -61,40 +61,40 @@ private:
#elif defined _WIN32 #elif defined _WIN32
// Check MSC ver // Check MSC ver
#if !defined _MSC_VER || _MSC_VER <= 1000 #if !defined _MSC_VER || _MSC_VER <= 1000
#error needs at least version 1000 of MSC #error needs at least version 1000 of MSC
#endif #endif
#define NOMINMAX #define NOMINMAX
// Memory leak checks // Memory leak checks
#define CHECK_HEAP_INTEGRITY() #define CHECK_HEAP_INTEGRITY()
// Alignment // Alignment
#define MEMORY_ALIGNED16(x) __declspec(align(16)) x #define MEMORY_ALIGNED16(x) __declspec(align(16)) x
#define MEMORY_ALIGNED32(x) __declspec(align(32)) x #define MEMORY_ALIGNED32(x) __declspec(align(32)) x
#define MEMORY_ALIGNED64(x) __declspec(align(64)) x #define MEMORY_ALIGNED64(x) __declspec(align(64)) x
#define MEMORY_ALIGNED128(x) __declspec(align(128)) x #define MEMORY_ALIGNED128(x) __declspec(align(128)) x
#define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x #define MEMORY_ALIGNED16_DECL(x) __declspec(align(16)) x
#define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x #define MEMORY_ALIGNED64_DECL(x) __declspec(align(64)) x
// Since they are always around on windows // Since they are always around on windows
#define HAVE_WX 1 #define HAVE_WX 1
#define HAVE_OPENAL 1 #define HAVE_OPENAL 1
#define HAVE_PORTAUDIO 1 #define HAVE_PORTAUDIO 1
// Debug definitions // Debug definitions
#if defined(_DEBUG) #if defined(_DEBUG)
#include <crtdbg.h> #include <crtdbg.h>
#undef CHECK_HEAP_INTEGRITY #undef CHECK_HEAP_INTEGRITY
#define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");} #define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
// If you want to see how much a pain in the ass singletons are, for example: // If you want to see how much a pain in the ass singletons are, for example:
// {614} normal block at 0x030C5310, 188 bytes long. // {614} normal block at 0x030C5310, 188 bytes long.
// Data: <Master Log > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00 // Data: <Master Log > 4D 61 73 74 65 72 20 4C 6F 67 00 00 00 00 00 00
struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } }; struct CrtDebugBreak { CrtDebugBreak(int spot) { _CrtSetBreakAlloc(spot); } };
//CrtDebugBreak breakAt(614); //CrtDebugBreak breakAt(614);
#endif // end DEBUG/FAST #endif // end DEBUG/FAST
#endif #endif
@ -149,18 +149,18 @@ private:
// Host communication. // Host communication.
enum HOST_COMM enum HOST_COMM
{ {
// Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on // Begin at 10 in case there is already messages with wParam = 0, 1, 2 and so on
WM_USER_STOP = 10, WM_USER_STOP = 10,
WM_USER_CREATE, WM_USER_CREATE,
WM_USER_SETCURSOR, WM_USER_SETCURSOR,
}; };
// Used for notification on emulation state // Used for notification on emulation state
enum EMUSTATE_CHANGE enum EMUSTATE_CHANGE
{ {
EMUSTATE_CHANGE_PLAY = 1, EMUSTATE_CHANGE_PLAY = 1,
EMUSTATE_CHANGE_PAUSE, EMUSTATE_CHANGE_PAUSE,
EMUSTATE_CHANGE_STOP EMUSTATE_CHANGE_STOP
}; };
#endif // _COMMON_H_ #endif // _COMMON_H_

View file

@ -20,7 +20,7 @@ template<> struct CompileTimeAssert<true> {};
#define b8(x) ( b4(x) | ( b4(x) >> 4) ) #define b8(x) ( b4(x) | ( b4(x) >> 4) )
#define b16(x) ( b8(x) | ( b8(x) >> 8) ) #define b16(x) ( b8(x) | ( b8(x) >> 8) )
#define b32(x) (b16(x) | (b16(x) >>16) ) #define b32(x) (b16(x) | (b16(x) >>16) )
#define ROUND_UP_POW2(x) (b32(x - 1) + 1) #define ROUND_UP_POW2(x) (b32(x - 1) + 1)
#define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0])) #define ARRAY_SIZE(a) (sizeof(a) / sizeof(a[0]))
@ -29,11 +29,11 @@ template<> struct CompileTimeAssert<true> {};
static __inline __m128i __attribute__((__always_inline__)) static __inline __m128i __attribute__((__always_inline__))
_mm_shuffle_epi8(__m128i a, __m128i mask) _mm_shuffle_epi8(__m128i a, __m128i mask)
{ {
__m128i result; __m128i result;
__asm__("pshufb %1, %0" __asm__("pshufb %1, %0"
: "=x" (result) : "=x" (result)
: "xm" (mask), "0" (a)); : "xm" (mask), "0" (a));
return result; return result;
} }
#endif #endif
@ -47,103 +47,103 @@ _mm_shuffle_epi8(__m128i a, __m128i mask)
#endif #endif
// go to debugger mode // go to debugger mode
#ifdef GEKKO #ifdef GEKKO
#define Crash() #define Crash()
#elif defined _M_GENERIC #elif defined _M_GENERIC
#define Crash() { exit(1); } #define Crash() { exit(1); }
#else #else
#define Crash() {asm ("int $3");} #define Crash() {asm ("int $3");}
#endif #endif
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0])) #define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
// GCC 4.8 defines all the rotate functions now // GCC 4.8 defines all the rotate functions now
// Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit // Small issue with GCC's lrotl/lrotr intrinsics is they are still 32bit while we require 64bit
#ifndef _rotl #ifndef _rotl
inline u32 _rotl(u32 x, int shift) { inline u32 _rotl(u32 x, int shift) {
shift &= 31; shift &= 31;
if (!shift) return x; if (!shift) return x;
return (x << shift) | (x >> (32 - shift)); return (x << shift) | (x >> (32 - shift));
} }
inline u32 _rotr(u32 x, int shift) { inline u32 _rotr(u32 x, int shift) {
shift &= 31; shift &= 31;
if (!shift) return x; if (!shift) return x;
return (x >> shift) | (x << (32 - shift)); return (x >> shift) | (x << (32 - shift));
} }
#endif #endif
inline u64 _rotl64(u64 x, unsigned int shift){ inline u64 _rotl64(u64 x, unsigned int shift){
unsigned int n = shift % 64; unsigned int n = shift % 64;
return (x << n) | (x >> (64 - n)); return (x << n) | (x >> (64 - n));
} }
inline u64 _rotr64(u64 x, unsigned int shift){ inline u64 _rotr64(u64 x, unsigned int shift){
unsigned int n = shift % 64; unsigned int n = shift % 64;
return (x >> n) | (x << (64 - n)); return (x >> n) | (x << (64 - n));
} }
#else // WIN32 #else // WIN32
// Function Cross-Compatibility // Function Cross-Compatibility
#define strcasecmp _stricmp #define strcasecmp _stricmp
#define strncasecmp _strnicmp #define strncasecmp _strnicmp
#define unlink _unlink #define unlink _unlink
#define snprintf _snprintf #define snprintf _snprintf
#define vscprintf _vscprintf #define vscprintf _vscprintf
// Locale Cross-Compatibility // Locale Cross-Compatibility
#define locale_t _locale_t #define locale_t _locale_t
#define freelocale _free_locale #define freelocale _free_locale
#define newlocale(mask, locale, base) _create_locale(mask, locale) #define newlocale(mask, locale, base) _create_locale(mask, locale)
#define LC_GLOBAL_LOCALE ((locale_t)-1) #define LC_GLOBAL_LOCALE ((locale_t)-1)
#define LC_ALL_MASK LC_ALL #define LC_ALL_MASK LC_ALL
#define LC_COLLATE_MASK LC_COLLATE #define LC_COLLATE_MASK LC_COLLATE
#define LC_CTYPE_MASK LC_CTYPE #define LC_CTYPE_MASK LC_CTYPE
#define LC_MONETARY_MASK LC_MONETARY #define LC_MONETARY_MASK LC_MONETARY
#define LC_NUMERIC_MASK LC_NUMERIC #define LC_NUMERIC_MASK LC_NUMERIC
#define LC_TIME_MASK LC_TIME #define LC_TIME_MASK LC_TIME
inline locale_t uselocale(locale_t new_locale) inline locale_t uselocale(locale_t new_locale)
{ {
// Retrieve the current per thread locale setting // Retrieve the current per thread locale setting
bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE); bool bIsPerThread = (_configthreadlocale(0) == _ENABLE_PER_THREAD_LOCALE);
// Retrieve the current thread-specific locale // Retrieve the current thread-specific locale
locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE; locale_t old_locale = bIsPerThread ? _get_current_locale() : LC_GLOBAL_LOCALE;
if(new_locale == LC_GLOBAL_LOCALE) if(new_locale == LC_GLOBAL_LOCALE)
{ {
// Restore the global locale // Restore the global locale
_configthreadlocale(_DISABLE_PER_THREAD_LOCALE); _configthreadlocale(_DISABLE_PER_THREAD_LOCALE);
} }
else if(new_locale != NULL) else if(new_locale != NULL)
{ {
// Configure the thread to set the locale only for this thread // Configure the thread to set the locale only for this thread
_configthreadlocale(_ENABLE_PER_THREAD_LOCALE); _configthreadlocale(_ENABLE_PER_THREAD_LOCALE);
// Set all locale categories // Set all locale categories
for(int i = LC_MIN; i <= LC_MAX; i++) for(int i = LC_MIN; i <= LC_MAX; i++)
setlocale(i, new_locale->locinfo->lc_category[i].locale); setlocale(i, new_locale->locinfo->lc_category[i].locale);
} }
return old_locale; return old_locale;
} }
// 64 bit offsets for windows // 64 bit offsets for windows
#define fseeko _fseeki64 #define fseeko _fseeki64
#define ftello _ftelli64 #define ftello _ftelli64
#define atoll _atoi64 #define atoll _atoi64
#define stat64 _stat64 #define stat64 _stat64
#define fstat64 _fstat64 #define fstat64 _fstat64
#define fileno _fileno #define fileno _fileno
#if _M_IX86 #if _M_IX86
#define Crash() {__asm int 3} #define Crash() {__asm int 3}
#else #else
extern "C" { extern "C" {
__declspec(dllimport) void __stdcall DebugBreak(void); __declspec(dllimport) void __stdcall DebugBreak(void);
} }
#define Crash() {DebugBreak();} #define Crash() {DebugBreak();}
#endif // M_IX86 #endif // M_IX86
#endif // WIN32 ndef #endif // WIN32 ndef
// Dolphin's min and max functions // Dolphin's min and max functions
@ -186,11 +186,11 @@ inline u32 swap32(u32 _data) {return bswap_32(_data);}
inline u64 swap64(u64 _data) {return bswap_64(_data);} inline u64 swap64(u64 _data) {return bswap_64(_data);}
#elif __APPLE__ #elif __APPLE__
inline __attribute__((always_inline)) u16 swap16(u16 _data) inline __attribute__((always_inline)) u16 swap16(u16 _data)
{return (_data >> 8) | (_data << 8);} {return (_data >> 8) | (_data << 8);}
inline __attribute__((always_inline)) u32 swap32(u32 _data) inline __attribute__((always_inline)) u32 swap32(u32 _data)
{return __builtin_bswap32(_data);} {return __builtin_bswap32(_data);}
inline __attribute__((always_inline)) u64 swap64(u64 _data) inline __attribute__((always_inline)) u64 swap64(u64 _data)
{return __builtin_bswap64(_data);} {return __builtin_bswap64(_data);}
#elif __FreeBSD__ #elif __FreeBSD__
inline u16 swap16(u16 _data) {return bswap16(_data);} inline u16 swap16(u16 _data) {return bswap16(_data);}
inline u32 swap32(u32 _data) {return bswap32(_data);} inline u32 swap32(u32 _data) {return bswap32(_data);}
@ -216,28 +216,28 @@ inline void swap<1>(u8* data)
template <> template <>
inline void swap<2>(u8* data) inline void swap<2>(u8* data)
{ {
*reinterpret_cast<u16*>(data) = swap16(data); *reinterpret_cast<u16*>(data) = swap16(data);
} }
template <> template <>
inline void swap<4>(u8* data) inline void swap<4>(u8* data)
{ {
*reinterpret_cast<u32*>(data) = swap32(data); *reinterpret_cast<u32*>(data) = swap32(data);
} }
template <> template <>
inline void swap<8>(u8* data) inline void swap<8>(u8* data)
{ {
*reinterpret_cast<u64*>(data) = swap64(data); *reinterpret_cast<u64*>(data) = swap64(data);
} }
template <typename T> template <typename T>
inline T FromBigEndian(T data) inline T FromBigEndian(T data)
{ {
//static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types"); //static_assert(std::is_arithmetic<T>::value, "function only makes sense with arithmetic types");
swap<sizeof(data)>(reinterpret_cast<u8*>(&data)); swap<sizeof(data)>(reinterpret_cast<u8*>(&data));
return data; return data;
} }
} // Namespace Common } // Namespace Common

View file

@ -13,34 +13,34 @@
#define DIR_SEP_CHR '/' #define DIR_SEP_CHR '/'
#ifndef MAX_PATH #ifndef MAX_PATH
#define MAX_PATH 260 #define MAX_PATH 260
#endif #endif
// The user data dir // The user data dir
#define ROOT_DIR "." #define ROOT_DIR "."
#ifdef _WIN32 #ifdef _WIN32
#define USERDATA_DIR "user" #define USERDATA_DIR "user"
#define EMU_DATA_DIR "emu" #define EMU_DATA_DIR "emu"
#else #else
#define USERDATA_DIR "user" #define USERDATA_DIR "user"
#ifdef USER_DIR #ifdef USER_DIR
#define EMU_DATA_DIR USER_DIR #define EMU_DATA_DIR USER_DIR
#else #else
#define EMU_DATA_DIR ".emu" #define EMU_DATA_DIR ".emu"
#endif #endif
#endif #endif
// Shared data dirs (Sys and shared User for linux) // Shared data dirs (Sys and shared User for linux)
#ifdef _WIN32 #ifdef _WIN32
#define SYSDATA_DIR "sys" #define SYSDATA_DIR "sys"
#else #else
#ifdef DATA_DIR #ifdef DATA_DIR
#define SYSDATA_DIR DATA_DIR "sys" #define SYSDATA_DIR DATA_DIR "sys"
#define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP #define SHARED_USER_DIR DATA_DIR USERDATA_DIR DIR_SEP
#else #else
#define SYSDATA_DIR "sys" #define SYSDATA_DIR "sys"
#define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP #define SHARED_USER_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
#endif #endif
#endif #endif
// Dirs in both User and Sys // Dirs in both User and Sys
@ -49,31 +49,31 @@
#define JAP_DIR "JAP" #define JAP_DIR "JAP"
// Subdirs in the User dir returned by GetUserPath(D_USER_IDX) // Subdirs in the User dir returned by GetUserPath(D_USER_IDX)
#define CONFIG_DIR "config" #define CONFIG_DIR "config"
#define GAMECONFIG_DIR "game_config" #define GAMECONFIG_DIR "game_config"
#define MAPS_DIR "maps" #define MAPS_DIR "maps"
#define CACHE_DIR "cache" #define CACHE_DIR "cache"
#define SHADERCACHE_DIR "shader_cache" #define SHADERCACHE_DIR "shader_cache"
#define STATESAVES_DIR "state_saves" #define STATESAVES_DIR "state_saves"
#define SCREENSHOTS_DIR "screenShots" #define SCREENSHOTS_DIR "screenShots"
#define DUMP_DIR "dump" #define DUMP_DIR "dump"
#define DUMP_TEXTURES_DIR "textures" #define DUMP_TEXTURES_DIR "textures"
#define DUMP_FRAMES_DIR "frames" #define DUMP_FRAMES_DIR "frames"
#define DUMP_AUDIO_DIR "audio" #define DUMP_AUDIO_DIR "audio"
#define LOGS_DIR "logs" #define LOGS_DIR "logs"
#define SHADERS_DIR "shaders" #define SHADERS_DIR "shaders"
#define SYSCONF_DIR "sysconf" #define SYSCONF_DIR "sysconf"
// Filenames // Filenames
// Files in the directory returned by GetUserPath(D_CONFIG_IDX) // Files in the directory returned by GetUserPath(D_CONFIG_IDX)
#define EMU_CONFIG "emu.ini" #define EMU_CONFIG "emu.ini"
#define DEBUGGER_CONFIG "debugger.ini" #define DEBUGGER_CONFIG "debugger.ini"
#define LOGGER_CONFIG "logger.ini" #define LOGGER_CONFIG "logger.ini"
// Files in the directory returned by GetUserPath(D_LOGS_IDX) // Files in the directory returned by GetUserPath(D_LOGS_IDX)
#define MAIN_LOG "emu.log" #define MAIN_LOG "emu.log"
// Files in the directory returned by GetUserPath(D_SYSCONF_IDX) // Files in the directory returned by GetUserPath(D_SYSCONF_IDX)
#define SYSCONF "SYSCONF" #define SYSCONF "SYSCONF"
#endif // _COMMON_PATHS_H_ #endif // _COMMON_PATHS_H_

View file

@ -20,16 +20,16 @@
ConsoleListener::ConsoleListener() ConsoleListener::ConsoleListener()
{ {
#ifdef _WIN32 #ifdef _WIN32
hConsole = NULL; hConsole = NULL;
bUseColor = true; bUseColor = true;
#else #else
bUseColor = isatty(fileno(stdout)); bUseColor = isatty(fileno(stdout));
#endif #endif
} }
ConsoleListener::~ConsoleListener() ConsoleListener::~ConsoleListener()
{ {
Close(); Close();
} }
// 100, 100, "Dolphin Log Console" // 100, 100, "Dolphin Log Console"
@ -38,31 +38,31 @@ ConsoleListener::~ConsoleListener()
void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title) void ConsoleListener::Open(bool Hidden, int Width, int Height, const char *Title)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (!GetConsoleWindow()) if (!GetConsoleWindow())
{ {
// Open the console window and create the window handle for GetStdHandle() // Open the console window and create the window handle for GetStdHandle()
AllocConsole(); AllocConsole();
// Hide // Hide
if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE); if (Hidden) ShowWindow(GetConsoleWindow(), SW_HIDE);
// Save the window handle that AllocConsole() created // Save the window handle that AllocConsole() created
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Set the console window title // Set the console window title
SetConsoleTitle(UTF8ToTStr(Title).c_str()); SetConsoleTitle(UTF8ToTStr(Title).c_str());
// Set letter space // Set letter space
LetterSpace(80, 4000); LetterSpace(80, 4000);
//MoveWindow(GetConsoleWindow(), 200,200, 800,800, true); //MoveWindow(GetConsoleWindow(), 200,200, 800,800, true);
} }
else else
{ {
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
} }
#endif #endif
} }
void ConsoleListener::UpdateHandle() void ConsoleListener::UpdateHandle()
{ {
#ifdef _WIN32 #ifdef _WIN32
hConsole = GetStdHandle(STD_OUTPUT_HANDLE); hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
#endif #endif
} }
@ -70,267 +70,267 @@ void ConsoleListener::UpdateHandle()
void ConsoleListener::Close() void ConsoleListener::Close()
{ {
#ifdef _WIN32 #ifdef _WIN32
if (hConsole == NULL) if (hConsole == NULL)
return; return;
FreeConsole(); FreeConsole();
hConsole = NULL; hConsole = NULL;
#else #else
fflush(NULL); fflush(NULL);
#endif #endif
} }
bool ConsoleListener::IsOpen() bool ConsoleListener::IsOpen()
{ {
#ifdef _WIN32 #ifdef _WIN32
return (hConsole != NULL); return (hConsole != NULL);
#else #else
return true; return true;
#endif #endif
} }
/* /*
LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are LetterSpace: SetConsoleScreenBufferSize and SetConsoleWindowInfo are
dependent on each other, that's the reason for the additional checks. dependent on each other, that's the reason for the additional checks.
*/ */
void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst) void ConsoleListener::BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst)
{ {
#ifdef _WIN32 #ifdef _WIN32
BOOL SB, SW; BOOL SB, SW;
if (BufferFirst) if (BufferFirst)
{ {
// Change screen buffer size // Change screen buffer size
COORD Co = {BufferWidth, BufferHeight}; COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co); SB = SetConsoleScreenBufferSize(hConsole, Co);
// Change the screen buffer window size // Change the screen buffer window size
SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom SMALL_RECT coo = {0,0,ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
} }
else else
{ {
// Change the screen buffer window size // Change the screen buffer window size
SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom SMALL_RECT coo = {0,0, ScreenWidth, ScreenHeight}; // top, left, right, bottom
SW = SetConsoleWindowInfo(hConsole, TRUE, &coo); SW = SetConsoleWindowInfo(hConsole, TRUE, &coo);
// Change screen buffer size // Change screen buffer size
COORD Co = {BufferWidth, BufferHeight}; COORD Co = {BufferWidth, BufferHeight};
SB = SetConsoleScreenBufferSize(hConsole, Co); SB = SetConsoleScreenBufferSize(hConsole, Co);
} }
#endif #endif
} }
void ConsoleListener::LetterSpace(int Width, int Height) void ConsoleListener::LetterSpace(int Width, int Height)
{ {
#ifdef _WIN32 #ifdef _WIN32
// Get console info // Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo; CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo); GetConsoleScreenBufferInfo(hConsole, &ConInfo);
// //
int OldBufferWidth = ConInfo.dwSize.X; int OldBufferWidth = ConInfo.dwSize.X;
int OldBufferHeight = ConInfo.dwSize.Y; int OldBufferHeight = ConInfo.dwSize.Y;
int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left); int OldScreenWidth = (ConInfo.srWindow.Right - ConInfo.srWindow.Left);
int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top); int OldScreenHeight = (ConInfo.srWindow.Bottom - ConInfo.srWindow.Top);
// //
int NewBufferWidth = Width; int NewBufferWidth = Width;
int NewBufferHeight = Height; int NewBufferHeight = Height;
int NewScreenWidth = NewBufferWidth - 1; int NewScreenWidth = NewBufferWidth - 1;
int NewScreenHeight = OldScreenHeight; int NewScreenHeight = OldScreenHeight;
// Width // Width
BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1)); BufferWidthHeight(NewBufferWidth, OldBufferHeight, NewScreenWidth, OldScreenHeight, (NewBufferWidth > OldScreenWidth-1));
// Height // Height
BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1)); BufferWidthHeight(NewBufferWidth, NewBufferHeight, NewScreenWidth, NewScreenHeight, (NewBufferHeight > OldScreenHeight-1));
// Resize the window too // Resize the window too
//MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true); //MoveWindow(GetConsoleWindow(), 200,200, (Width*8 + 50),(NewScreenHeight*12 + 200), true);
#endif #endif
} }
#ifdef _WIN32 #ifdef _WIN32
COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth) COORD ConsoleListener::GetCoordinates(int BytesRead, int BufferWidth)
{ {
COORD Ret = {0, 0}; COORD Ret = {0, 0};
// Full rows // Full rows
int Step = (int)floor((float)BytesRead / (float)BufferWidth); int Step = (int)floor((float)BytesRead / (float)BufferWidth);
Ret.Y += Step; Ret.Y += Step;
// Partial row // Partial row
Ret.X = BytesRead - (BufferWidth * Step); Ret.X = BytesRead - (BufferWidth * Step);
return Ret; return Ret;
} }
#endif #endif
void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize) void ConsoleListener::PixelSpace(int Left, int Top, int Width, int Height, bool Resize)
{ {
#ifdef _WIN32 #ifdef _WIN32
// Check size // Check size
if (Width < 8 || Height < 12) return; if (Width < 8 || Height < 12) return;
bool DBef = true; bool DBef = true;
bool DAft = true; bool DAft = true;
std::string SLog = ""; std::string SLog = "";
const HWND hWnd = GetConsoleWindow(); const HWND hWnd = GetConsoleWindow();
const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); const HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
// Get console info // Get console info
CONSOLE_SCREEN_BUFFER_INFO ConInfo; CONSOLE_SCREEN_BUFFER_INFO ConInfo;
GetConsoleScreenBufferInfo(hConsole, &ConInfo); GetConsoleScreenBufferInfo(hConsole, &ConInfo);
DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y; DWORD BufferSize = ConInfo.dwSize.X * ConInfo.dwSize.Y;
// --------------------------------------------------------------------- // ---------------------------------------------------------------------
// Save the current text // Save the current text
// ------------------------ // ------------------------
DWORD cCharsRead = 0; DWORD cCharsRead = 0;
COORD coordScreen = { 0, 0 }; COORD coordScreen = { 0, 0 };
static const int MAX_BYTES = 1024 * 16; static const int MAX_BYTES = 1024 * 16;
std::vector<std::array<TCHAR, MAX_BYTES>> Str; std::vector<std::array<TCHAR, MAX_BYTES>> Str;
std::vector<std::array<WORD, MAX_BYTES>> Attr; std::vector<std::array<WORD, MAX_BYTES>> Attr;
// ReadConsoleOutputAttribute seems to have a limit at this level // ReadConsoleOutputAttribute seems to have a limit at this level
static const int ReadBufferSize = MAX_BYTES - 32; static const int ReadBufferSize = MAX_BYTES - 32;
DWORD cAttrRead = ReadBufferSize; DWORD cAttrRead = ReadBufferSize;
DWORD BytesRead = 0; DWORD BytesRead = 0;
while (BytesRead < BufferSize) while (BytesRead < BufferSize)
{ {
Str.resize(Str.size() + 1); Str.resize(Str.size() + 1);
if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead)) if (!ReadConsoleOutputCharacter(hConsole, Str.back().data(), ReadBufferSize, coordScreen, &cCharsRead))
SLog += StringFromFormat("WriteConsoleOutputCharacter error"); SLog += StringFromFormat("WriteConsoleOutputCharacter error");
Attr.resize(Attr.size() + 1); Attr.resize(Attr.size() + 1);
if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead)) if (!ReadConsoleOutputAttribute(hConsole, Attr.back().data(), ReadBufferSize, coordScreen, &cAttrRead))
SLog += StringFromFormat("WriteConsoleOutputAttribute error"); SLog += StringFromFormat("WriteConsoleOutputAttribute error");
// Break on error // Break on error
if (cAttrRead == 0) break; if (cAttrRead == 0) break;
BytesRead += cAttrRead; BytesRead += cAttrRead;
coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X); coordScreen = GetCoordinates(BytesRead, ConInfo.dwSize.X);
} }
// Letter space // Letter space
int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f); int LWidth = (int)(floor((float)Width / 8.0f) - 1.0f);
int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f); int LHeight = (int)(floor((float)Height / 12.0f) - 1.0f);
int LBufWidth = LWidth + 1; int LBufWidth = LWidth + 1;
int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth); int LBufHeight = (int)floor((float)BufferSize / (float)LBufWidth);
// Change screen buffer size // Change screen buffer size
LetterSpace(LBufWidth, LBufHeight); LetterSpace(LBufWidth, LBufHeight);
ClearScreen(true); ClearScreen(true);
coordScreen.Y = 0; coordScreen.Y = 0;
coordScreen.X = 0; coordScreen.X = 0;
DWORD cCharsWritten = 0; DWORD cCharsWritten = 0;
int BytesWritten = 0; int BytesWritten = 0;
DWORD cAttrWritten = 0; DWORD cAttrWritten = 0;
for (size_t i = 0; i < Attr.size(); i++) for (size_t i = 0; i < Attr.size(); i++)
{ {
if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten)) if (!WriteConsoleOutputCharacter(hConsole, Str[i].data(), ReadBufferSize, coordScreen, &cCharsWritten))
SLog += StringFromFormat("WriteConsoleOutputCharacter error"); SLog += StringFromFormat("WriteConsoleOutputCharacter error");
if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten)) if (!WriteConsoleOutputAttribute(hConsole, Attr[i].data(), ReadBufferSize, coordScreen, &cAttrWritten))
SLog += StringFromFormat("WriteConsoleOutputAttribute error"); SLog += StringFromFormat("WriteConsoleOutputAttribute error");
BytesWritten += cAttrWritten; BytesWritten += cAttrWritten;
coordScreen = GetCoordinates(BytesWritten, LBufWidth); coordScreen = GetCoordinates(BytesWritten, LBufWidth);
} }
const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X; const int OldCursor = ConInfo.dwCursorPosition.Y * ConInfo.dwSize.X + ConInfo.dwCursorPosition.X;
COORD Coo = GetCoordinates(OldCursor, LBufWidth); COORD Coo = GetCoordinates(OldCursor, LBufWidth);
SetConsoleCursorPosition(hConsole, Coo); SetConsoleCursorPosition(hConsole, Coo);
if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str()); if (SLog.length() > 0) Log(LogTypes::LNOTICE, SLog.c_str());
// Resize the window too // Resize the window too
if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true); if (Resize) MoveWindow(GetConsoleWindow(), Left,Top, (Width + 100),Height, true);
#endif #endif
} }
void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text) void ConsoleListener::Log(LogTypes::LOG_LEVELS Level, const char *Text)
{ {
#if defined(_WIN32) #if defined(_WIN32)
/* /*
const int MAX_BYTES = 1024*10; const int MAX_BYTES = 1024*10;
char Str[MAX_BYTES]; char Str[MAX_BYTES];
va_list ArgPtr; va_list ArgPtr;
int Cnt; int Cnt;
va_start(ArgPtr, Text); va_start(ArgPtr, Text);
Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr); Cnt = vsnprintf(Str, MAX_BYTES, Text, ArgPtr);
va_end(ArgPtr); va_end(ArgPtr);
*/ */
DWORD cCharsWritten; DWORD cCharsWritten;
WORD Color; WORD Color;
switch (Level) switch (Level)
{ {
case NOTICE_LEVEL: // light green case NOTICE_LEVEL: // light green
Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY; Color = FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break; break;
case ERROR_LEVEL: // light red case ERROR_LEVEL: // light red
Color = FOREGROUND_RED | FOREGROUND_INTENSITY; Color = FOREGROUND_RED | FOREGROUND_INTENSITY;
break; break;
case WARNING_LEVEL: // light yellow case WARNING_LEVEL: // light yellow
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY; Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_INTENSITY;
break; break;
case INFO_LEVEL: // cyan case INFO_LEVEL: // cyan
Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY; Color = FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY;
break; break;
case DEBUG_LEVEL: // gray case DEBUG_LEVEL: // gray
Color = FOREGROUND_INTENSITY; Color = FOREGROUND_INTENSITY;
break; break;
default: // off-white default: // off-white
Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE; Color = FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE;
break; break;
} }
if (strlen(Text) > 10) if (strlen(Text) > 10)
{ {
// First 10 chars white // First 10 chars white
SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY); SetConsoleTextAttribute(hConsole, FOREGROUND_RED | FOREGROUND_GREEN | FOREGROUND_BLUE | FOREGROUND_INTENSITY);
WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL); WriteConsole(hConsole, Text, 10, &cCharsWritten, NULL);
Text += 10; Text += 10;
} }
SetConsoleTextAttribute(hConsole, Color); SetConsoleTextAttribute(hConsole, Color);
WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL); WriteConsole(hConsole, Text, (DWORD)strlen(Text), &cCharsWritten, NULL);
#else #else
char ColorAttr[16] = ""; char ColorAttr[16] = "";
char ResetAttr[16] = ""; char ResetAttr[16] = "";
if (bUseColor) if (bUseColor)
{ {
strcpy(ResetAttr, "\033[0m"); strcpy(ResetAttr, "\033[0m");
switch (Level) switch (Level)
{ {
case NOTICE_LEVEL: // light green case NOTICE_LEVEL: // light green
strcpy(ColorAttr, "\033[92m"); strcpy(ColorAttr, "\033[92m");
break; break;
case ERROR_LEVEL: // light red case ERROR_LEVEL: // light red
strcpy(ColorAttr, "\033[91m"); strcpy(ColorAttr, "\033[91m");
break; break;
case WARNING_LEVEL: // light yellow case WARNING_LEVEL: // light yellow
strcpy(ColorAttr, "\033[93m"); strcpy(ColorAttr, "\033[93m");
break; break;
default: default:
break; break;
} }
} }
fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr); fprintf(stderr, "%s%s%s", ColorAttr, Text, ResetAttr);
#endif #endif
} }
// Clear console screen // Clear console screen
void ConsoleListener::ClearScreen(bool Cursor) void ConsoleListener::ClearScreen(bool Cursor)
{ {
#if defined(_WIN32) #if defined(_WIN32)
COORD coordScreen = { 0, 0 }; COORD coordScreen = { 0, 0 };
DWORD cCharsWritten; DWORD cCharsWritten;
CONSOLE_SCREEN_BUFFER_INFO csbi; CONSOLE_SCREEN_BUFFER_INFO csbi;
DWORD dwConSize; DWORD dwConSize;
HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE); HANDLE hConsole = GetStdHandle(STD_OUTPUT_HANDLE);
GetConsoleScreenBufferInfo(hConsole, &csbi); GetConsoleScreenBufferInfo(hConsole, &csbi);
dwConSize = csbi.dwSize.X * csbi.dwSize.Y; dwConSize = csbi.dwSize.X * csbi.dwSize.Y;
// Write space to the entire console // Write space to the entire console
FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten); FillConsoleOutputCharacter(hConsole, TEXT(' '), dwConSize, coordScreen, &cCharsWritten);
GetConsoleScreenBufferInfo(hConsole, &csbi); GetConsoleScreenBufferInfo(hConsole, &csbi);
FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten); FillConsoleOutputAttribute(hConsole, csbi.wAttributes, dwConSize, coordScreen, &cCharsWritten);
// Reset cursor // Reset cursor
if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen); if (Cursor) SetConsoleCursorPosition(hConsole, coordScreen);
#endif #endif
} }

View file

@ -14,28 +14,28 @@
class ConsoleListener : public LogListener class ConsoleListener : public LogListener
{ {
public: public:
ConsoleListener(); ConsoleListener();
~ConsoleListener(); ~ConsoleListener();
void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console"); void Open(bool Hidden = false, int Width = 100, int Height = 100, const char * Name = "Console");
void UpdateHandle(); void UpdateHandle();
void Close(); void Close();
bool IsOpen(); bool IsOpen();
void LetterSpace(int Width, int Height); void LetterSpace(int Width, int Height);
void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst); void BufferWidthHeight(int BufferWidth, int BufferHeight, int ScreenWidth, int ScreenHeight, bool BufferFirst);
void PixelSpace(int Left, int Top, int Width, int Height, bool); void PixelSpace(int Left, int Top, int Width, int Height, bool);
#ifdef _WIN32 #ifdef _WIN32
COORD GetCoordinates(int BytesRead, int BufferWidth); COORD GetCoordinates(int BytesRead, int BufferWidth);
#endif #endif
void Log(LogTypes::LOG_LEVELS, const char *Text); void Log(LogTypes::LOG_LEVELS, const char *Text);
void ClearScreen(bool Cursor = true); void ClearScreen(bool Cursor = true);
private: private:
#ifdef _WIN32 #ifdef _WIN32
HWND GetHwnd(void); HWND GetHwnd(void);
HANDLE hConsole; HANDLE hConsole;
#endif #endif
bool bUseColor; bool bUseColor;
}; };
#endif // _CONSOLELISTENER_H #endif // _CONSOLELISTENER_H

View file

@ -11,69 +11,69 @@
enum CPUVendor enum CPUVendor
{ {
VENDOR_INTEL = 0, VENDOR_INTEL = 0,
VENDOR_AMD = 1, VENDOR_AMD = 1,
VENDOR_ARM = 2, VENDOR_ARM = 2,
VENDOR_OTHER = 3, VENDOR_OTHER = 3,
}; };
struct CPUInfo struct CPUInfo
{ {
CPUVendor vendor; CPUVendor vendor;
char cpu_string[0x21]; char cpu_string[0x21];
char brand_string[0x41]; char brand_string[0x41];
bool OS64bit; bool OS64bit;
bool CPU64bit; bool CPU64bit;
bool Mode64bit; bool Mode64bit;
bool HTT; bool HTT;
int num_cores; int num_cores;
int logical_cpu_count; int logical_cpu_count;
bool bSSE; bool bSSE;
bool bSSE2; bool bSSE2;
bool bSSE3; bool bSSE3;
bool bSSSE3; bool bSSSE3;
bool bPOPCNT; bool bPOPCNT;
bool bSSE4_1; bool bSSE4_1;
bool bSSE4_2; bool bSSE4_2;
bool bLZCNT; bool bLZCNT;
bool bSSE4A; bool bSSE4A;
bool bAVX; bool bAVX;
bool bAES; bool bAES;
bool bLAHFSAHF64; bool bLAHFSAHF64;
bool bLongMode; bool bLongMode;
// ARM specific CPUInfo // ARM specific CPUInfo
bool bSwp; bool bSwp;
bool bHalf; bool bHalf;
bool bThumb; bool bThumb;
bool bFastMult; bool bFastMult;
bool bVFP; bool bVFP;
bool bEDSP; bool bEDSP;
bool bThumbEE; bool bThumbEE;
bool bNEON; bool bNEON;
bool bVFPv3; bool bVFPv3;
bool bTLS; bool bTLS;
bool bVFPv4; bool bVFPv4;
bool bIDIVa; bool bIDIVa;
bool bIDIVt; bool bIDIVt;
bool bArmV7; // enable MOVT, MOVW etc bool bArmV7; // enable MOVT, MOVW etc
// ARMv8 specific // ARMv8 specific
bool bFP; bool bFP;
bool bASIMD; bool bASIMD;
// Call Detect() // Call Detect()
explicit CPUInfo(); explicit CPUInfo();
// Turn the cpu info into a string we can show // Turn the cpu info into a string we can show
std::string Summarize(); std::string Summarize();
private: private:
// Detects the various cpu features // Detects the various cpu features
void Detect(); void Detect();
}; };
extern CPUInfo cpu_info; extern CPUInfo cpu_info;

View file

@ -7,33 +7,33 @@
class DebugInterface class DebugInterface
{ {
protected: protected:
virtual ~DebugInterface() {} virtual ~DebugInterface() {}
public: public:
virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");} virtual void disasm(unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
virtual void getRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");} virtual void getRawMemoryString(int /*memory*/, unsigned int /*address*/, char *dest, int /*max_size*/) {strcpy(dest, "NODEBUGGER");}
virtual int getInstructionSize(int /*instruction*/) {return 1;} virtual int getInstructionSize(int /*instruction*/) {return 1;}
virtual bool isAlive() {return true;} virtual bool isAlive() {return true;}
virtual bool isBreakpoint(unsigned int /*address*/) {return false;} virtual bool isBreakpoint(unsigned int /*address*/) {return false;}
virtual void setBreakpoint(unsigned int /*address*/){} virtual void setBreakpoint(unsigned int /*address*/){}
virtual void clearBreakpoint(unsigned int /*address*/){} virtual void clearBreakpoint(unsigned int /*address*/){}
virtual void clearAllBreakpoints() {} virtual void clearAllBreakpoints() {}
virtual void toggleBreakpoint(unsigned int /*address*/){} virtual void toggleBreakpoint(unsigned int /*address*/){}
virtual bool isMemCheck(unsigned int /*address*/) {return false;} virtual bool isMemCheck(unsigned int /*address*/) {return false;}
virtual void toggleMemCheck(unsigned int /*address*/){} virtual void toggleMemCheck(unsigned int /*address*/){}
virtual unsigned int readMemory(unsigned int /*address*/){return 0;} virtual unsigned int readMemory(unsigned int /*address*/){return 0;}
virtual void writeExtraMemory(int /*memory*/, unsigned int /*value*/, unsigned int /*address*/) {} virtual void writeExtraMemory(int /*memory*/, unsigned int /*value*/, unsigned int /*address*/) {}
virtual unsigned int readExtraMemory(int /*memory*/, unsigned int /*address*/){return 0;} virtual unsigned int readExtraMemory(int /*memory*/, unsigned int /*address*/){return 0;}
virtual unsigned int readInstruction(unsigned int /*address*/){return 0;} virtual unsigned int readInstruction(unsigned int /*address*/){return 0;}
virtual unsigned int getPC() {return 0;} virtual unsigned int getPC() {return 0;}
virtual void setPC(unsigned int /*address*/) {} virtual void setPC(unsigned int /*address*/) {}
virtual void step() {} virtual void step() {}
virtual void runToBreakpoint() {} virtual void runToBreakpoint() {}
virtual void breakNow() {} virtual void breakNow() {}
virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {} virtual void insertBLR(unsigned int /*address*/, unsigned int /*value*/) {}
virtual void showJitResults(unsigned int /*address*/) {}; virtual void showJitResults(unsigned int /*address*/) {};
virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;} virtual int getColor(unsigned int /*address*/){return 0xFFFFFFFF;}
virtual std::string getDescription(unsigned int /*address*/) = 0; virtual std::string getDescription(unsigned int /*address*/) = 0;
}; };
#endif #endif

View file

@ -48,8 +48,8 @@ public:
/// Swap buffers to display the next frame /// Swap buffers to display the next frame
virtual void SwapBuffers() = 0; virtual void SwapBuffers() = 0;
/// Polls window events /// Polls window events
virtual void PollEvents() = 0; virtual void PollEvents() = 0;
/// Makes the graphics context current for the caller thread /// Makes the graphics context current for the caller thread
virtual void MakeCurrent() = 0; virtual void MakeCurrent() = 0;

View file

@ -30,18 +30,18 @@ using namespace std;
void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut ) void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
{ {
#if defined(UNICODE)||defined(_UNICODE) #if defined(UNICODE)||defined(_UNICODE)
ULONG index = 0; ULONG index = 0;
PCSTR lpAct = lpszIn; PCSTR lpAct = lpszIn;
for( ; ; lpAct++ ) for( ; ; lpAct++ )
{ {
lpszOut[index++] = (TCHAR)(*lpAct); lpszOut[index++] = (TCHAR)(*lpAct);
if ( *lpAct == 0 ) if ( *lpAct == 0 )
break; break;
} }
#else #else
// This is trivial :) // This is trivial :)
strcpy( lpszOut, lpszIn ); strcpy( lpszOut, lpszIn );
#endif #endif
} }
@ -50,184 +50,184 @@ void PCSTR2LPTSTR( PCSTR lpszIn, LPTSTR lpszOut )
// Note: There is no size check for lpszSymbolPath! // Note: There is no size check for lpszSymbolPath!
static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath ) static void InitSymbolPath( PSTR lpszSymbolPath, PCSTR lpszIniPath )
{ {
CHAR lpszPath[BUFFERSIZE]; CHAR lpszPath[BUFFERSIZE];
// Creating the default path // Creating the default path
// ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;" // ".;%_NT_SYMBOL_PATH%;%_NT_ALTERNATE_SYMBOL_PATH%;%SYSTEMROOT%;%SYSTEMROOT%\System32;"
strcpy( lpszSymbolPath, "." ); strcpy( lpszSymbolPath, "." );
// environment variable _NT_SYMBOL_PATH // environment variable _NT_SYMBOL_PATH
if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) if ( GetEnvironmentVariableA( "_NT_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
{ {
strcat( lpszSymbolPath, ";" ); strcat( lpszSymbolPath, ";" );
strcat( lpszSymbolPath, lpszPath ); strcat( lpszSymbolPath, lpszPath );
} }
// environment variable _NT_ALTERNATE_SYMBOL_PATH // environment variable _NT_ALTERNATE_SYMBOL_PATH
if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) ) if ( GetEnvironmentVariableA( "_NT_ALTERNATE_SYMBOL_PATH", lpszPath, BUFFERSIZE ) )
{ {
strcat( lpszSymbolPath, ";" ); strcat( lpszSymbolPath, ";" );
strcat( lpszSymbolPath, lpszPath ); strcat( lpszSymbolPath, lpszPath );
} }
// environment variable SYSTEMROOT // environment variable SYSTEMROOT
if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) ) if ( GetEnvironmentVariableA( "SYSTEMROOT", lpszPath, BUFFERSIZE ) )
{ {
strcat( lpszSymbolPath, ";" ); strcat( lpszSymbolPath, ";" );
strcat( lpszSymbolPath, lpszPath ); strcat( lpszSymbolPath, lpszPath );
strcat( lpszSymbolPath, ";" ); strcat( lpszSymbolPath, ";" );
// SYSTEMROOT\System32 // SYSTEMROOT\System32
strcat( lpszSymbolPath, lpszPath ); strcat( lpszSymbolPath, lpszPath );
strcat( lpszSymbolPath, "\\System32" ); strcat( lpszSymbolPath, "\\System32" );
} }
// Add user defined path // Add user defined path
if ( lpszIniPath != NULL ) if ( lpszIniPath != NULL )
if ( lpszIniPath[0] != '\0' ) if ( lpszIniPath[0] != '\0' )
{ {
strcat( lpszSymbolPath, ";" ); strcat( lpszSymbolPath, ";" );
strcat( lpszSymbolPath, lpszIniPath ); strcat( lpszSymbolPath, lpszIniPath );
} }
} }
// Uninitialize the loaded symbol files // Uninitialize the loaded symbol files
BOOL UninitSymInfo() { BOOL UninitSymInfo() {
return SymCleanup( GetCurrentProcess() ); return SymCleanup( GetCurrentProcess() );
} }
// Initializes the symbol files // Initializes the symbol files
BOOL InitSymInfo( PCSTR lpszInitialSymbolPath ) BOOL InitSymInfo( PCSTR lpszInitialSymbolPath )
{ {
CHAR lpszSymbolPath[BUFFERSIZE]; CHAR lpszSymbolPath[BUFFERSIZE];
DWORD symOptions = SymGetOptions(); DWORD symOptions = SymGetOptions();
symOptions |= SYMOPT_LOAD_LINES; symOptions |= SYMOPT_LOAD_LINES;
symOptions &= ~SYMOPT_UNDNAME; symOptions &= ~SYMOPT_UNDNAME;
SymSetOptions( symOptions ); SymSetOptions( symOptions );
InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath ); InitSymbolPath( lpszSymbolPath, lpszInitialSymbolPath );
return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE); return SymInitialize( GetCurrentProcess(), lpszSymbolPath, TRUE);
} }
// Get the module name from a given address // Get the module name from a given address
static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule ) static BOOL GetModuleNameFromAddress( UINT address, LPTSTR lpszModule )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
IMAGEHLP_MODULE moduleInfo; IMAGEHLP_MODULE moduleInfo;
::ZeroMemory( &moduleInfo, sizeof(moduleInfo) ); ::ZeroMemory( &moduleInfo, sizeof(moduleInfo) );
moduleInfo.SizeOfStruct = sizeof(moduleInfo); moduleInfo.SizeOfStruct = sizeof(moduleInfo);
if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) ) if ( SymGetModuleInfo( GetCurrentProcess(), (DWORD)address, &moduleInfo ) )
{ {
// Got it! // Got it!
PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule ); PCSTR2LPTSTR( moduleInfo.ModuleName, lpszModule );
ret = TRUE; ret = TRUE;
} }
else else
// Not found :( // Not found :(
_tcscpy( lpszModule, _T("?") ); _tcscpy( lpszModule, _T("?") );
return ret; return ret;
} }
// Get function prototype and parameter info from ip address and stack address // Get function prototype and parameter info from ip address and stack address
static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol ) static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, LPTSTR lpszSymbol )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
DWORD dwSymSize = 10000; DWORD dwSymSize = 10000;
TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?"); TCHAR lpszUnDSymbol[BUFFERSIZE]=_T("?");
CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?"; CHAR lpszNonUnicodeUnDSymbol[BUFFERSIZE]="?";
LPTSTR lpszParamSep = NULL; LPTSTR lpszParamSep = NULL;
LPTSTR lpszParsed = lpszUnDSymbol; LPTSTR lpszParsed = lpszUnDSymbol;
PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize ); PIMAGEHLP_SYMBOL pSym = (PIMAGEHLP_SYMBOL)GlobalAlloc( GMEM_FIXED, dwSymSize );
::ZeroMemory( pSym, dwSymSize ); ::ZeroMemory( pSym, dwSymSize );
pSym->SizeOfStruct = dwSymSize; pSym->SizeOfStruct = dwSymSize;
pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL); pSym->MaxNameLength = dwSymSize - sizeof(IMAGEHLP_SYMBOL);
// Set the default to unknown // Set the default to unknown
_tcscpy( lpszSymbol, _T("?") ); _tcscpy( lpszSymbol, _T("?") );
// Get symbol info for IP // Get symbol info for IP
#ifndef _M_X64 #ifndef _M_X64
DWORD dwDisp = 0; DWORD dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) ) if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, &dwDisp, pSym ) )
#else #else
//makes it compile but hell im not sure if this works... //makes it compile but hell im not sure if this works...
DWORD64 dwDisp = 0; DWORD64 dwDisp = 0;
if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) ) if ( SymGetSymFromAddr( GetCurrentProcess(), (ULONG)fnAddress, (PDWORD64)&dwDisp, pSym ) )
#endif #endif
{ {
// Make the symbol readable for humans // Make the symbol readable for humans
UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE, UnDecorateSymbolName( pSym->Name, lpszNonUnicodeUnDSymbol, BUFFERSIZE,
UNDNAME_COMPLETE | UNDNAME_COMPLETE |
UNDNAME_NO_THISTYPE | UNDNAME_NO_THISTYPE |
UNDNAME_NO_SPECIAL_SYMS | UNDNAME_NO_SPECIAL_SYMS |
UNDNAME_NO_MEMBER_TYPE | UNDNAME_NO_MEMBER_TYPE |
UNDNAME_NO_MS_KEYWORDS | UNDNAME_NO_MS_KEYWORDS |
UNDNAME_NO_ACCESS_SPECIFIERS ); UNDNAME_NO_ACCESS_SPECIFIERS );
// Symbol information is ANSI string // Symbol information is ANSI string
PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol ); PCSTR2LPTSTR( lpszNonUnicodeUnDSymbol, lpszUnDSymbol );
// I am just smarter than the symbol file :) // I am just smarter than the symbol file :)
if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 ) if ( _tcscmp(lpszUnDSymbol, _T("_WinMain@16")) == 0 )
_tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)")); _tcscpy(lpszUnDSymbol, _T("WinMain(HINSTANCE,HINSTANCE,LPCTSTR,int)"));
else else
if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 ) if ( _tcscmp(lpszUnDSymbol, _T("_main")) == 0 )
_tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)")); _tcscpy(lpszUnDSymbol, _T("main(int,TCHAR * *)"));
else else
if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 ) if ( _tcscmp(lpszUnDSymbol, _T("_mainCRTStartup")) == 0 )
_tcscpy(lpszUnDSymbol, _T("mainCRTStartup()")); _tcscpy(lpszUnDSymbol, _T("mainCRTStartup()"));
else else
if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 ) if ( _tcscmp(lpszUnDSymbol, _T("_wmain")) == 0 )
_tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)")); _tcscpy(lpszUnDSymbol, _T("wmain(int,TCHAR * *,TCHAR * *)"));
else else
if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 ) if ( _tcscmp(lpszUnDSymbol, _T("_wmainCRTStartup")) == 0 )
_tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()")); _tcscpy(lpszUnDSymbol, _T("wmainCRTStartup()"));
lpszSymbol[0] = _T('\0'); lpszSymbol[0] = _T('\0');
// Let's go through the stack, and modify the function prototype, and insert the actual // Let's go through the stack, and modify the function prototype, and insert the actual
// parameter values from the stack // parameter values from the stack
if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL) if ( _tcsstr( lpszUnDSymbol, _T("(void)") ) == NULL && _tcsstr( lpszUnDSymbol, _T("()") ) == NULL)
{ {
ULONG index = 0; ULONG index = 0;
for( ; ; index++ ) for( ; ; index++ )
{ {
lpszParamSep = _tcschr( lpszParsed, _T(',') ); lpszParamSep = _tcschr( lpszParsed, _T(',') );
if ( lpszParamSep == NULL ) if ( lpszParamSep == NULL )
break; break;
*lpszParamSep = _T('\0'); *lpszParamSep = _T('\0');
_tcscat( lpszSymbol, lpszParsed ); _tcscat( lpszSymbol, lpszParsed );
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) ); _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X,"), *((ULONG*)(stackAddress) + 2 + index) );
lpszParsed = lpszParamSep + 1; lpszParsed = lpszParamSep + 1;
} }
lpszParamSep = _tcschr( lpszParsed, _T(')') ); lpszParamSep = _tcschr( lpszParsed, _T(')') );
if ( lpszParamSep != NULL ) if ( lpszParamSep != NULL )
{ {
*lpszParamSep = _T('\0'); *lpszParamSep = _T('\0');
_tcscat( lpszSymbol, lpszParsed ); _tcscat( lpszSymbol, lpszParsed );
_stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) ); _stprintf( lpszSymbol + _tcslen(lpszSymbol), _T("=0x%08X)"), *((ULONG*)(stackAddress) + 2 + index) );
lpszParsed = lpszParamSep + 1; lpszParsed = lpszParamSep + 1;
} }
} }
_tcscat( lpszSymbol, lpszParsed ); _tcscat( lpszSymbol, lpszParsed );
ret = TRUE; ret = TRUE;
} }
GlobalFree( pSym ); GlobalFree( pSym );
return ret; return ret;
} }
// Get source file name and line number from IP address // Get source file name and line number from IP address
@ -236,198 +236,198 @@ static BOOL GetFunctionInfoFromAddresses( ULONG fnAddress, ULONG stackAddress, L
// "address" // "address"
static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo ) static BOOL GetSourceInfoFromAddress( UINT address, LPTSTR lpszSourceInfo )
{ {
BOOL ret = FALSE; BOOL ret = FALSE;
IMAGEHLP_LINE lineInfo; IMAGEHLP_LINE lineInfo;
DWORD dwDisp; DWORD dwDisp;
TCHAR lpszFileName[BUFFERSIZE] = _T(""); TCHAR lpszFileName[BUFFERSIZE] = _T("");
TCHAR lpModuleInfo[BUFFERSIZE] = _T(""); TCHAR lpModuleInfo[BUFFERSIZE] = _T("");
_tcscpy( lpszSourceInfo, _T("?(?)") ); _tcscpy( lpszSourceInfo, _T("?(?)") );
::ZeroMemory( &lineInfo, sizeof( lineInfo ) ); ::ZeroMemory( &lineInfo, sizeof( lineInfo ) );
lineInfo.SizeOfStruct = sizeof( lineInfo ); lineInfo.SizeOfStruct = sizeof( lineInfo );
if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) ) if ( SymGetLineFromAddr( GetCurrentProcess(), address, &dwDisp, &lineInfo ) )
{ {
// Got it. Let's use "sourcefile(linenumber)" format // Got it. Let's use "sourcefile(linenumber)" format
PCSTR2LPTSTR( lineInfo.FileName, lpszFileName ); PCSTR2LPTSTR( lineInfo.FileName, lpszFileName );
TCHAR fname[_MAX_FNAME]; TCHAR fname[_MAX_FNAME];
TCHAR ext[_MAX_EXT]; TCHAR ext[_MAX_EXT];
_tsplitpath(lpszFileName, NULL, NULL, fname, ext); _tsplitpath(lpszFileName, NULL, NULL, fname, ext);
_stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber ); _stprintf( lpszSourceInfo, _T("%s%s(%d)"), fname, ext, lineInfo.LineNumber );
ret = TRUE; ret = TRUE;
} }
else else
{ {
// There is no source file information. :( // There is no source file information. :(
// Let's use the "modulename!address" format // Let's use the "modulename!address" format
GetModuleNameFromAddress( address, lpModuleInfo ); GetModuleNameFromAddress( address, lpModuleInfo );
if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0')) if ( lpModuleInfo[0] == _T('?') || lpModuleInfo[0] == _T('\0'))
// There is no modulename information. :(( // There is no modulename information. :((
// Let's use the "address" format // Let's use the "address" format
_stprintf( lpszSourceInfo, _T("0x%08X"), address ); _stprintf( lpszSourceInfo, _T("0x%08X"), address );
else else
_stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address ); _stprintf( lpszSourceInfo, _T("%s!0x%08X"), lpModuleInfo, address );
ret = FALSE; ret = FALSE;
} }
return ret; return ret;
} }
void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack) void PrintFunctionAndSourceInfo(FILE* file, const STACKFRAME& callstack)
{ {
TCHAR symInfo[BUFFERSIZE] = _T("?"); TCHAR symInfo[BUFFERSIZE] = _T("?");
TCHAR srcInfo[BUFFERSIZE] = _T("?"); TCHAR srcInfo[BUFFERSIZE] = _T("?");
GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo); GetFunctionInfoFromAddresses((ULONG)callstack.AddrPC.Offset, (ULONG)callstack.AddrFrame.Offset, symInfo);
GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo); GetSourceInfoFromAddress((ULONG)callstack.AddrPC.Offset, srcInfo);
etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n"); etfprint(file, " " + TStrToUTF8(srcInfo) + " : " + TStrToUTF8(symInfo) + "\n");
} }
void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file ) void StackTrace( HANDLE hThread, const char* lpszMessage, FILE *file )
{ {
STACKFRAME callStack; STACKFRAME callStack;
BOOL bResult; BOOL bResult;
CONTEXT context; CONTEXT context;
HANDLE hProcess = GetCurrentProcess(); HANDLE hProcess = GetCurrentProcess();
// If it's not this thread, let's suspend it, and resume it at the end // If it's not this thread, let's suspend it, and resume it at the end
if ( hThread != GetCurrentThread() ) if ( hThread != GetCurrentThread() )
if ( SuspendThread( hThread ) == -1 ) if ( SuspendThread( hThread ) == -1 )
{ {
// whaaat ?! // whaaat ?!
etfprint(file, "Call stack info failed\n"); etfprint(file, "Call stack info failed\n");
return; return;
} }
::ZeroMemory( &context, sizeof(context) ); ::ZeroMemory( &context, sizeof(context) );
context.ContextFlags = CONTEXT_FULL; context.ContextFlags = CONTEXT_FULL;
if ( !GetThreadContext( hThread, &context ) ) if ( !GetThreadContext( hThread, &context ) )
{ {
etfprint(file, "Call stack info failed\n"); etfprint(file, "Call stack info failed\n");
return; return;
} }
::ZeroMemory( &callStack, sizeof(callStack) ); ::ZeroMemory( &callStack, sizeof(callStack) );
#ifndef _M_X64 #ifndef _M_X64
callStack.AddrPC.Offset = context.Eip; callStack.AddrPC.Offset = context.Eip;
callStack.AddrStack.Offset = context.Esp; callStack.AddrStack.Offset = context.Esp;
callStack.AddrFrame.Offset = context.Ebp; callStack.AddrFrame.Offset = context.Ebp;
#else #else
callStack.AddrPC.Offset = context.Rip; callStack.AddrPC.Offset = context.Rip;
callStack.AddrStack.Offset = context.Rsp; callStack.AddrStack.Offset = context.Rsp;
callStack.AddrFrame.Offset = context.Rbp; callStack.AddrFrame.Offset = context.Rbp;
#endif #endif
callStack.AddrPC.Mode = AddrModeFlat; callStack.AddrPC.Mode = AddrModeFlat;
callStack.AddrStack.Mode = AddrModeFlat; callStack.AddrStack.Mode = AddrModeFlat;
callStack.AddrFrame.Mode = AddrModeFlat; callStack.AddrFrame.Mode = AddrModeFlat;
etfprint(file, "Call stack info: \n"); etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage); etfprint(file, lpszMessage);
PrintFunctionAndSourceInfo(file, callStack); PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ ) for( ULONG index = 0; ; index++ )
{ {
bResult = StackWalk( bResult = StackWalk(
IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_I386,
hProcess, hProcess,
hThread, hThread,
&callStack, &callStack,
NULL, NULL,
NULL, NULL,
SymFunctionTableAccess, SymFunctionTableAccess,
SymGetModuleBase, SymGetModuleBase,
NULL); NULL);
if ( index == 0 ) if ( index == 0 )
continue; continue;
if( !bResult || callStack.AddrFrame.Offset == 0 ) if( !bResult || callStack.AddrFrame.Offset == 0 )
break; break;
PrintFunctionAndSourceInfo(file, callStack); PrintFunctionAndSourceInfo(file, callStack);
} }
if ( hThread != GetCurrentThread() ) if ( hThread != GetCurrentThread() )
ResumeThread( hThread ); ResumeThread( hThread );
} }
void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp ) void StackTrace(HANDLE hThread, const char* lpszMessage, FILE *file, DWORD eip, DWORD esp, DWORD ebp )
{ {
STACKFRAME callStack; STACKFRAME callStack;
BOOL bResult; BOOL bResult;
TCHAR symInfo[BUFFERSIZE] = _T("?"); TCHAR symInfo[BUFFERSIZE] = _T("?");
TCHAR srcInfo[BUFFERSIZE] = _T("?"); TCHAR srcInfo[BUFFERSIZE] = _T("?");
HANDLE hProcess = GetCurrentProcess(); HANDLE hProcess = GetCurrentProcess();
// If it's not this thread, let's suspend it, and resume it at the end // If it's not this thread, let's suspend it, and resume it at the end
if ( hThread != GetCurrentThread() ) if ( hThread != GetCurrentThread() )
if ( SuspendThread( hThread ) == -1 ) if ( SuspendThread( hThread ) == -1 )
{ {
// whaaat ?! // whaaat ?!
etfprint(file, "Call stack info failed\n"); etfprint(file, "Call stack info failed\n");
return; return;
} }
::ZeroMemory( &callStack, sizeof(callStack) ); ::ZeroMemory( &callStack, sizeof(callStack) );
callStack.AddrPC.Offset = eip; callStack.AddrPC.Offset = eip;
callStack.AddrStack.Offset = esp; callStack.AddrStack.Offset = esp;
callStack.AddrFrame.Offset = ebp; callStack.AddrFrame.Offset = ebp;
callStack.AddrPC.Mode = AddrModeFlat; callStack.AddrPC.Mode = AddrModeFlat;
callStack.AddrStack.Mode = AddrModeFlat; callStack.AddrStack.Mode = AddrModeFlat;
callStack.AddrFrame.Mode = AddrModeFlat; callStack.AddrFrame.Mode = AddrModeFlat;
etfprint(file, "Call stack info: \n"); etfprint(file, "Call stack info: \n");
etfprint(file, lpszMessage); etfprint(file, lpszMessage);
PrintFunctionAndSourceInfo(file, callStack); PrintFunctionAndSourceInfo(file, callStack);
for( ULONG index = 0; ; index++ ) for( ULONG index = 0; ; index++ )
{ {
bResult = StackWalk( bResult = StackWalk(
IMAGE_FILE_MACHINE_I386, IMAGE_FILE_MACHINE_I386,
hProcess, hProcess,
hThread, hThread,
&callStack, &callStack,
NULL, NULL,
NULL, NULL,
SymFunctionTableAccess, SymFunctionTableAccess,
SymGetModuleBase, SymGetModuleBase,
NULL); NULL);
if ( index == 0 ) if ( index == 0 )
continue; continue;
if( !bResult || callStack.AddrFrame.Offset == 0 ) if( !bResult || callStack.AddrFrame.Offset == 0 )
break; break;
PrintFunctionAndSourceInfo(file, callStack); PrintFunctionAndSourceInfo(file, callStack);
} }
if ( hThread != GetCurrentThread() ) if ( hThread != GetCurrentThread() )
ResumeThread( hThread ); ResumeThread( hThread );
} }
char g_uefbuf[2048]; char g_uefbuf[2048];
void etfprintf(FILE *file, const char *format, ...) void etfprintf(FILE *file, const char *format, ...)
{ {
va_list ap; va_list ap;
va_start(ap, format); va_start(ap, format);
int len = vsprintf(g_uefbuf, format, ap); int len = vsprintf(g_uefbuf, format, ap);
fwrite(g_uefbuf, 1, len, file); fwrite(g_uefbuf, 1, len, file);
va_end(ap); va_end(ap);
} }
void etfprint(FILE *file, const std::string &text) void etfprint(FILE *file, const std::string &text)
{ {
size_t len = text.length(); size_t len = text.length();
fwrite(text.data(), 1, len, file); fwrite(text.data(), 1, len, file);
} }
#endif //WIN32 #endif //WIN32

View file

@ -24,9 +24,9 @@
#pragma comment( lib, "imagehlp.lib" ) #pragma comment( lib, "imagehlp.lib" )
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath ) #define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) InitSymInfo( IniSymbolPath )
#define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo() #define EXTENDEDTRACEUNINITIALIZE() UninitSymInfo()
#define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file) #define STACKTRACE(file) StackTrace( GetCurrentThread(), "", file)
#define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp) #define STACKTRACE2(file, eip, esp, ebp) StackTrace(GetCurrentThread(), "", file, eip, esp, ebp)
// class File; // class File;
@ -41,13 +41,13 @@ void etfprint(FILE *file, const std::string &text);
#define UEFBUFSIZE 2048 #define UEFBUFSIZE 2048
extern char g_uefbuf[UEFBUFSIZE]; extern char g_uefbuf[UEFBUFSIZE];
#else // not WIN32 #else // not WIN32
#define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0) #define EXTENDEDTRACEINITIALIZE( IniSymbolPath ) ((void)0)
#define EXTENDEDTRACEUNINITIALIZE() ((void)0) #define EXTENDEDTRACEUNINITIALIZE() ((void)0)
#define STACKTRACE(file) ((void)0) #define STACKTRACE(file) ((void)0)
#define STACKTRACE2(file, eip, esp, ebp) ((void)0) #define STACKTRACE2(file, eip, esp, ebp) ((void)0)
#endif // WIN32 #endif // WIN32
#endif // _EXTENDEDTRACE_H_INCLUDED_ #endif // _EXTENDEDTRACE_H_INCLUDED_

View file

@ -14,100 +14,100 @@ template <typename T>
class FifoQueue class FifoQueue
{ {
public: public:
FifoQueue() : m_size(0) FifoQueue() : m_size(0)
{ {
m_write_ptr = m_read_ptr = new ElementPtr(); m_write_ptr = m_read_ptr = new ElementPtr();
} }
~FifoQueue() ~FifoQueue()
{ {
// this will empty out the whole queue // this will empty out the whole queue
delete m_read_ptr; delete m_read_ptr;
} }
u32 Size() const u32 Size() const
{ {
return m_size; return m_size;
} }
bool Empty() const bool Empty() const
{ {
//return (m_read_ptr == m_write_ptr); //return (m_read_ptr == m_write_ptr);
return (0 == m_size); return (0 == m_size);
} }
T& Front() const T& Front() const
{ {
return *m_read_ptr->current; return *m_read_ptr->current;
} }
template <typename Arg> template <typename Arg>
void Push(Arg&& t) void Push(Arg&& t)
{ {
// create the element, add it to the queue // create the element, add it to the queue
m_write_ptr->current = new T(std::forward<Arg>(t)); m_write_ptr->current = new T(std::forward<Arg>(t));
// set the next pointer to a new element ptr // set the next pointer to a new element ptr
// then advance the write pointer // then advance the write pointer
m_write_ptr = m_write_ptr->next = new ElementPtr(); m_write_ptr = m_write_ptr->next = new ElementPtr();
Common::AtomicIncrement(m_size); Common::AtomicIncrement(m_size);
} }
void Pop() void Pop()
{ {
Common::AtomicDecrement(m_size); Common::AtomicDecrement(m_size);
ElementPtr *const tmpptr = m_read_ptr; ElementPtr *const tmpptr = m_read_ptr;
// advance the read pointer // advance the read pointer
m_read_ptr = m_read_ptr->next; m_read_ptr = m_read_ptr->next;
// set the next element to NULL to stop the recursive deletion // set the next element to NULL to stop the recursive deletion
tmpptr->next = NULL; tmpptr->next = NULL;
delete tmpptr; // this also deletes the element delete tmpptr; // this also deletes the element
} }
bool Pop(T& t) bool Pop(T& t)
{ {
if (Empty()) if (Empty())
return false; return false;
t = std::move(Front()); t = std::move(Front());
Pop(); Pop();
return true; return true;
} }
// not thread-safe // not thread-safe
void Clear() void Clear()
{ {
m_size = 0; m_size = 0;
delete m_read_ptr; delete m_read_ptr;
m_write_ptr = m_read_ptr = new ElementPtr(); m_write_ptr = m_read_ptr = new ElementPtr();
} }
private: private:
// stores a pointer to element // stores a pointer to element
// and a pointer to the next ElementPtr // and a pointer to the next ElementPtr
class ElementPtr class ElementPtr
{ {
public: public:
ElementPtr() : current(NULL), next(NULL) {} ElementPtr() : current(NULL), next(NULL) {}
~ElementPtr() ~ElementPtr()
{ {
if (current) if (current)
{ {
delete current; delete current;
// recusion ftw // recusion ftw
if (next) if (next)
delete next; delete next;
} }
} }
T *volatile current; T *volatile current;
ElementPtr *volatile next; ElementPtr *volatile next;
}; };
ElementPtr *volatile m_write_ptr; ElementPtr *volatile m_write_ptr;
ElementPtr *volatile m_read_ptr; ElementPtr *volatile m_read_ptr;
volatile u32 m_size; volatile u32 m_size;
}; };
} }

View file

@ -22,85 +22,85 @@
CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories) CFileSearch::CFileSearch(const CFileSearch::XStringVector& _rSearchStrings, const CFileSearch::XStringVector& _rDirectories)
{ {
// Reverse the loop order for speed? // Reverse the loop order for speed?
for (size_t j = 0; j < _rSearchStrings.size(); j++) for (size_t j = 0; j < _rSearchStrings.size(); j++)
{ {
for (size_t i = 0; i < _rDirectories.size(); i++) for (size_t i = 0; i < _rDirectories.size(); i++)
{ {
FindFiles(_rSearchStrings[j], _rDirectories[i]); FindFiles(_rSearchStrings[j], _rDirectories[i]);
} }
} }
} }
void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath) void CFileSearch::FindFiles(const std::string& _searchString, const std::string& _strPath)
{ {
std::string GCMSearchPath; std::string GCMSearchPath;
BuildCompleteFilename(GCMSearchPath, _strPath, _searchString); BuildCompleteFilename(GCMSearchPath, _strPath, _searchString);
#ifdef _WIN32 #ifdef _WIN32
WIN32_FIND_DATA findData; WIN32_FIND_DATA findData;
HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData); HANDLE FindFirst = FindFirstFile(UTF8ToTStr(GCMSearchPath).c_str(), &findData);
if (FindFirst != INVALID_HANDLE_VALUE) if (FindFirst != INVALID_HANDLE_VALUE)
{ {
bool bkeepLooping = true; bool bkeepLooping = true;
while (bkeepLooping) while (bkeepLooping)
{ {
if (findData.cFileName[0] != '.') if (findData.cFileName[0] != '.')
{ {
std::string strFilename; std::string strFilename;
BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName)); BuildCompleteFilename(strFilename, _strPath, TStrToUTF8(findData.cFileName));
m_FileNames.push_back(strFilename); m_FileNames.push_back(strFilename);
} }
bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false; bkeepLooping = FindNextFile(FindFirst, &findData) ? true : false;
} }
} }
FindClose(FindFirst); FindClose(FindFirst);
#else #else
// TODO: super lame/broken // TODO: super lame/broken
auto end_match(_searchString); auto end_match(_searchString);
// assuming we have a "*.blah"-like pattern // assuming we have a "*.blah"-like pattern
if (!end_match.empty() && end_match[0] == '*') if (!end_match.empty() && end_match[0] == '*')
end_match.erase(0, 1); end_match.erase(0, 1);
// ugly // ugly
if (end_match == ".*") if (end_match == ".*")
end_match.clear(); end_match.clear();
DIR* dir = opendir(_strPath.c_str()); DIR* dir = opendir(_strPath.c_str());
if (!dir) if (!dir)
return; return;
while (auto const dp = readdir(dir)) while (auto const dp = readdir(dir))
{ {
std::string found(dp->d_name); std::string found(dp->d_name);
if ((found != ".") && (found != "..") if ((found != ".") && (found != "..")
&& (found.size() >= end_match.size()) && (found.size() >= end_match.size())
&& std::equal(end_match.rbegin(), end_match.rend(), found.rbegin())) && std::equal(end_match.rbegin(), end_match.rend(), found.rbegin()))
{ {
std::string full_name; std::string full_name;
if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR) if (_strPath.c_str()[_strPath.size()-1] == DIR_SEP_CHR)
full_name = _strPath + found; full_name = _strPath + found;
else else
full_name = _strPath + DIR_SEP + found; full_name = _strPath + DIR_SEP + found;
m_FileNames.push_back(full_name); m_FileNames.push_back(full_name);
} }
} }
closedir(dir); closedir(dir);
#endif #endif
} }
const CFileSearch::XStringVector& CFileSearch::GetFileNames() const const CFileSearch::XStringVector& CFileSearch::GetFileNames() const
{ {
return m_FileNames; return m_FileNames;
} }

View file

@ -12,16 +12,16 @@
class CFileSearch class CFileSearch
{ {
public: public:
typedef std::vector<std::string>XStringVector; typedef std::vector<std::string>XStringVector;
CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories); CFileSearch(const XStringVector& _rSearchStrings, const XStringVector& _rDirectories);
const XStringVector& GetFileNames() const; const XStringVector& GetFileNames() const;
private: private:
void FindFiles(const std::string& _searchString, const std::string& _strPath); void FindFiles(const std::string& _searchString, const std::string& _strPath);
XStringVector m_FileNames; XStringVector m_FileNames;
}; };
#endif // _FILESEARCH_H_ #endif // _FILESEARCH_H_

File diff suppressed because it is too large Load diff

View file

@ -16,59 +16,59 @@
template <class T, int N> template <class T, int N>
class fixed_size_queue.h class fixed_size_queue.h
{ {
T *storage; T *storage;
int head; int head;
int tail; int tail;
int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future. int count; // sacrifice 4 bytes for a simpler implementation. may optimize away in the future.
// Make copy constructor private for now. // Make copy constructor private for now.
fixed_size_queue.h(fixed_size_queue.h &other) { } fixed_size_queue.h(fixed_size_queue.h &other) { }
public: public:
fixed_size_queue.h() fixed_size_queue.h()
{ {
storage = new T[N]; storage = new T[N];
clear(); clear();
} }
~fixed_size_queue.h() ~fixed_size_queue.h()
{ {
delete [] storage; delete [] storage;
} }
void clear() { void clear() {
head = 0; head = 0;
tail = 0; tail = 0;
count = 0; count = 0;
} }
void push(T t) { void push(T t) {
storage[tail] = t; storage[tail] = t;
tail++; tail++;
if (tail == N) if (tail == N)
tail = 0; tail = 0;
count++; count++;
} }
void pop() { void pop() {
head++; head++;
if (head == N) if (head == N)
head = 0; head = 0;
count--; count--;
} }
T pop_front() { T pop_front() {
const T &temp = storage[head]; const T &temp = storage[head];
pop(); pop();
return temp; return temp;
} }
T &front() { return storage[head]; } T &front() { return storage[head]; }
const T &front() const { return storage[head]; } const T &front() const { return storage[head]; }
size_t size() const { size_t size() const {
return count; return count;
} }
}; };
#endif // _FIXED_SIZE_QUEUE_H_ #endif // _FIXED_SIZE_QUEUE_H_

View file

@ -16,29 +16,29 @@ static u64 (*ptrHashFunction)(const u8 *src, int len, u32 samples) = &GetMurmurH
// Implementation from Wikipedia. // Implementation from Wikipedia.
u32 HashFletcher(const u8* data_u8, size_t length) u32 HashFletcher(const u8* data_u8, size_t length)
{ {
const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */ const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */
size_t len = (length + 1) / 2; /* Length in 16-bit words */ size_t len = (length + 1) / 2; /* Length in 16-bit words */
u32 sum1 = 0xffff, sum2 = 0xffff; u32 sum1 = 0xffff, sum2 = 0xffff;
while (len) while (len)
{ {
size_t tlen = len > 360 ? 360 : len; size_t tlen = len > 360 ? 360 : len;
len -= tlen; len -= tlen;
do { do {
sum1 += *data++; sum1 += *data++;
sum2 += sum1; sum2 += sum1;
} }
while (--tlen); while (--tlen);
sum1 = (sum1 & 0xffff) + (sum1 >> 16); sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16); sum2 = (sum2 & 0xffff) + (sum2 >> 16);
} }
// Second reduction step to reduce sums to 16 bits // Second reduction step to reduce sums to 16 bits
sum1 = (sum1 & 0xffff) + (sum1 >> 16); sum1 = (sum1 & 0xffff) + (sum1 >> 16);
sum2 = (sum2 & 0xffff) + (sum2 >> 16); sum2 = (sum2 & 0xffff) + (sum2 >> 16);
return(sum2 << 16 | sum1); return(sum2 << 16 | sum1);
} }
@ -48,54 +48,54 @@ u32 HashFletcher(const u8* data_u8, size_t length)
// data: Pointer to the data to be summed; len is in bytes // data: Pointer to the data to be summed; len is in bytes
u32 HashAdler32(const u8* data, size_t len) u32 HashAdler32(const u8* data, size_t len)
{ {
u32 a = 1, b = 0; u32 a = 1, b = 0;
while (len) while (len)
{ {
size_t tlen = len > 5550 ? 5550 : len; size_t tlen = len > 5550 ? 5550 : len;
len -= tlen; len -= tlen;
do do
{ {
a += *data++; a += *data++;
b += a; b += a;
} }
while (--tlen); while (--tlen);
a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER); a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
} }
// It can be shown that a <= 0x1013a here, so a single subtract will do. // It can be shown that a <= 0x1013a here, so a single subtract will do.
if (a >= MOD_ADLER) if (a >= MOD_ADLER)
{ {
a -= MOD_ADLER; a -= MOD_ADLER;
} }
// It can be shown that b can reach 0xfff87 here. // It can be shown that b can reach 0xfff87 here.
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER); b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
if (b >= MOD_ADLER) if (b >= MOD_ADLER)
{ {
b -= MOD_ADLER; b -= MOD_ADLER;
} }
return((b << 16) | a); return((b << 16) | a);
} }
// Stupid hash - but can't go back now :) // Stupid hash - but can't go back now :)
// Don't use for new things. At least it's reasonably fast. // Don't use for new things. At least it's reasonably fast.
u32 HashEctor(const u8* ptr, int length) u32 HashEctor(const u8* ptr, int length)
{ {
u32 crc = 0; u32 crc = 0;
for (int i = 0; i < length; i++) for (int i = 0; i < length; i++)
{ {
crc ^= ptr[i]; crc ^= ptr[i];
crc = (crc << 3) | (crc >> 29); crc = (crc << 3) | (crc >> 29);
} }
return(crc); return(crc);
} }
@ -107,7 +107,7 @@ u32 HashEctor(const u8* ptr, int length)
inline u64 getblock(const u64 * p, int i) inline u64 getblock(const u64 * p, int i)
{ {
return p[i]; return p[i];
} }
//---------- //----------
@ -115,25 +115,25 @@ inline u64 getblock(const u64 * p, int i)
inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2) inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
{ {
k1 *= c1; k1 *= c1;
k1 = _rotl64(k1,23); k1 = _rotl64(k1,23);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
h1 += h2; h1 += h2;
h2 = _rotl64(h2,41); h2 = _rotl64(h2,41);
k2 *= c2; k2 *= c2;
k2 = _rotl64(k2,23); k2 = _rotl64(k2,23);
k2 *= c1; k2 *= c1;
h2 ^= k2; h2 ^= k2;
h2 += h1; h2 += h1;
h1 = h1*3+0x52dce729; h1 = h1*3+0x52dce729;
h2 = h2*3+0x38495ab5; h2 = h2*3+0x38495ab5;
c1 = c1*5+0x7b7d159c; c1 = c1*5+0x7b7d159c;
c2 = c2*5+0x6bce6396; c2 = c2*5+0x6bce6396;
} }
//---------- //----------
@ -141,87 +141,87 @@ inline void bmix64(u64 & h1, u64 & h2, u64 & k1, u64 & k2, u64 & c1, u64 & c2)
inline u64 fmix64(u64 k) inline u64 fmix64(u64 k)
{ {
k ^= k >> 33; k ^= k >> 33;
k *= 0xff51afd7ed558ccd; k *= 0xff51afd7ed558ccd;
k ^= k >> 33; k ^= k >> 33;
k *= 0xc4ceb9fe1a85ec53; k *= 0xc4ceb9fe1a85ec53;
k ^= k >> 33; k ^= k >> 33;
return k; return k;
} }
u64 GetMurmurHash3(const u8 *src, int len, u32 samples) u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
{ {
const u8 * data = (const u8*)src; const u8 * data = (const u8*)src;
const int nblocks = len / 16; const int nblocks = len / 16;
u32 Step = (len / 8); u32 Step = (len / 8);
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
u64 h1 = 0x9368e53c2f6af274; u64 h1 = 0x9368e53c2f6af274;
u64 h2 = 0x586dcd208f7cd3fd; u64 h2 = 0x586dcd208f7cd3fd;
u64 c1 = 0x87c37b91114253d5; u64 c1 = 0x87c37b91114253d5;
u64 c2 = 0x4cf5ad432745937f; u64 c2 = 0x4cf5ad432745937f;
//---------- //----------
// body // body
const u64 * blocks = (const u64 *)(data); const u64 * blocks = (const u64 *)(data);
for(int i = 0; i < nblocks; i+=Step) for(int i = 0; i < nblocks; i+=Step)
{ {
u64 k1 = getblock(blocks,i*2+0); u64 k1 = getblock(blocks,i*2+0);
u64 k2 = getblock(blocks,i*2+1); u64 k2 = getblock(blocks,i*2+1);
bmix64(h1,h2,k1,k2,c1,c2); bmix64(h1,h2,k1,k2,c1,c2);
} }
//---------- //----------
// tail // tail
const u8 * tail = (const u8*)(data + nblocks*16); const u8 * tail = (const u8*)(data + nblocks*16);
u64 k1 = 0; u64 k1 = 0;
u64 k2 = 0; u64 k2 = 0;
switch(len & 15) switch(len & 15)
{ {
case 15: k2 ^= u64(tail[14]) << 48; case 15: k2 ^= u64(tail[14]) << 48;
case 14: k2 ^= u64(tail[13]) << 40; case 14: k2 ^= u64(tail[13]) << 40;
case 13: k2 ^= u64(tail[12]) << 32; case 13: k2 ^= u64(tail[12]) << 32;
case 12: k2 ^= u64(tail[11]) << 24; case 12: k2 ^= u64(tail[11]) << 24;
case 11: k2 ^= u64(tail[10]) << 16; case 11: k2 ^= u64(tail[10]) << 16;
case 10: k2 ^= u64(tail[ 9]) << 8; case 10: k2 ^= u64(tail[ 9]) << 8;
case 9: k2 ^= u64(tail[ 8]) << 0; case 9: k2 ^= u64(tail[ 8]) << 0;
case 8: k1 ^= u64(tail[ 7]) << 56; case 8: k1 ^= u64(tail[ 7]) << 56;
case 7: k1 ^= u64(tail[ 6]) << 48; case 7: k1 ^= u64(tail[ 6]) << 48;
case 6: k1 ^= u64(tail[ 5]) << 40; case 6: k1 ^= u64(tail[ 5]) << 40;
case 5: k1 ^= u64(tail[ 4]) << 32; case 5: k1 ^= u64(tail[ 4]) << 32;
case 4: k1 ^= u64(tail[ 3]) << 24; case 4: k1 ^= u64(tail[ 3]) << 24;
case 3: k1 ^= u64(tail[ 2]) << 16; case 3: k1 ^= u64(tail[ 2]) << 16;
case 2: k1 ^= u64(tail[ 1]) << 8; case 2: k1 ^= u64(tail[ 1]) << 8;
case 1: k1 ^= u64(tail[ 0]) << 0; case 1: k1 ^= u64(tail[ 0]) << 0;
bmix64(h1,h2,k1,k2,c1,c2); bmix64(h1,h2,k1,k2,c1,c2);
}; };
//---------- //----------
// finalization // finalization
h2 ^= len; h2 ^= len;
h1 += h2; h1 += h2;
h2 += h1; h2 += h1;
h1 = fmix64(h1); h1 = fmix64(h1);
h2 = fmix64(h2); h2 = fmix64(h2);
h1 += h2; h1 += h2;
return h1; return h1;
} }
@ -229,23 +229,23 @@ u64 GetMurmurHash3(const u8 *src, int len, u32 samples)
u64 GetCRC32(const u8 *src, int len, u32 samples) u64 GetCRC32(const u8 *src, int len, u32 samples)
{ {
#if _M_SSE >= 0x402 #if _M_SSE >= 0x402
u64 h = len; u64 h = len;
u32 Step = (len / 8); u32 Step = (len / 8);
const u64 *data = (const u64 *)src; const u64 *data = (const u64 *)src;
const u64 *end = data + Step; const u64 *end = data + Step;
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
while(data < end) while(data < end)
{ {
h = _mm_crc32_u64(h, data[0]); h = _mm_crc32_u64(h, data[0]);
data += Step; data += Step;
} }
const u8 *data2 = (const u8*)end; const u8 *data2 = (const u8*)end;
return _mm_crc32_u64(h, u64(data2[0])); return _mm_crc32_u64(h, u64(data2[0]));
#else #else
return 0; return 0;
#endif #endif
} }
@ -259,68 +259,68 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
*/ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{ {
const u64 m = 0xc6a4a7935bd1e995; const u64 m = 0xc6a4a7935bd1e995;
u64 h = len * m; u64 h = len * m;
const int r = 47; const int r = 47;
u32 Step = (len / 8); u32 Step = (len / 8);
const u64 *data = (const u64 *)src; const u64 *data = (const u64 *)src;
const u64 *end = data + Step; const u64 *end = data + Step;
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
while(data < end) while(data < end)
{ {
u64 k = data[0]; u64 k = data[0];
data+=Step; data+=Step;
k *= m; k *= m;
k ^= k >> r; k ^= k >> r;
k *= m; k *= m;
h ^= k; h ^= k;
h *= m; h *= m;
} }
const u8 * data2 = (const u8*)end; const u8 * data2 = (const u8*)end;
switch(len & 7) switch(len & 7)
{ {
case 7: h ^= u64(data2[6]) << 48; case 7: h ^= u64(data2[6]) << 48;
case 6: h ^= u64(data2[5]) << 40; case 6: h ^= u64(data2[5]) << 40;
case 5: h ^= u64(data2[4]) << 32; case 5: h ^= u64(data2[4]) << 32;
case 4: h ^= u64(data2[3]) << 24; case 4: h ^= u64(data2[3]) << 24;
case 3: h ^= u64(data2[2]) << 16; case 3: h ^= u64(data2[2]) << 16;
case 2: h ^= u64(data2[1]) << 8; case 2: h ^= u64(data2[1]) << 8;
case 1: h ^= u64(data2[0]); case 1: h ^= u64(data2[0]);
h *= m; h *= m;
}; };
h ^= h >> r; h ^= h >> r;
h *= m; h *= m;
h ^= h >> r; h ^= h >> r;
return h; return h;
} }
#else #else
// CRC32 hash using the SSE4.2 instruction // CRC32 hash using the SSE4.2 instruction
u64 GetCRC32(const u8 *src, int len, u32 samples) u64 GetCRC32(const u8 *src, int len, u32 samples)
{ {
#if _M_SSE >= 0x402 #if _M_SSE >= 0x402
u32 h = len; u32 h = len;
u32 Step = (len/4); u32 Step = (len/4);
const u32 *data = (const u32 *)src; const u32 *data = (const u32 *)src;
const u32 *end = data + Step; const u32 *end = data + Step;
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
while(data < end) while(data < end)
{ {
h = _mm_crc32_u32(h, data[0]); h = _mm_crc32_u32(h, data[0]);
data += Step; data += Step;
} }
const u8 *data2 = (const u8*)end; const u8 *data2 = (const u8*)end;
return (u64)_mm_crc32_u32(h, u32(data2[0])); return (u64)_mm_crc32_u32(h, u32(data2[0]));
#else #else
return 0; return 0;
#endif #endif
} }
@ -330,7 +330,7 @@ u64 GetCRC32(const u8 *src, int len, u32 samples)
inline u32 getblock(const u32 * p, int i) inline u32 getblock(const u32 * p, int i)
{ {
return p[i]; return p[i];
} }
//---------- //----------
@ -340,107 +340,107 @@ inline u32 getblock(const u32 * p, int i)
inline u32 fmix32(u32 h) inline u32 fmix32(u32 h)
{ {
h ^= h >> 16; h ^= h >> 16;
h *= 0x85ebca6b; h *= 0x85ebca6b;
h ^= h >> 13; h ^= h >> 13;
h *= 0xc2b2ae35; h *= 0xc2b2ae35;
h ^= h >> 16; h ^= h >> 16;
return h; return h;
} }
inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2) inline void bmix32(u32 & h1, u32 & h2, u32 & k1, u32 & k2, u32 & c1, u32 & c2)
{ {
k1 *= c1; k1 *= c1;
k1 = _rotl(k1,11); k1 = _rotl(k1,11);
k1 *= c2; k1 *= c2;
h1 ^= k1; h1 ^= k1;
h1 += h2; h1 += h2;
h2 = _rotl(h2,17); h2 = _rotl(h2,17);
k2 *= c2; k2 *= c2;
k2 = _rotl(k2,11); k2 = _rotl(k2,11);
k2 *= c1; k2 *= c1;
h2 ^= k2; h2 ^= k2;
h2 += h1; h2 += h1;
h1 = h1*3+0x52dce729; h1 = h1*3+0x52dce729;
h2 = h2*3+0x38495ab5; h2 = h2*3+0x38495ab5;
c1 = c1*5+0x7b7d159c; c1 = c1*5+0x7b7d159c;
c2 = c2*5+0x6bce6396; c2 = c2*5+0x6bce6396;
} }
//---------- //----------
u64 GetMurmurHash3(const u8* src, int len, u32 samples) u64 GetMurmurHash3(const u8* src, int len, u32 samples)
{ {
const u8 * data = (const u8*)src; const u8 * data = (const u8*)src;
u32 out[2]; u32 out[2];
const int nblocks = len / 8; const int nblocks = len / 8;
u32 Step = (len / 4); u32 Step = (len / 4);
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
u32 h1 = 0x8de1c3ac; u32 h1 = 0x8de1c3ac;
u32 h2 = 0xbab98226; u32 h2 = 0xbab98226;
u32 c1 = 0x95543787; u32 c1 = 0x95543787;
u32 c2 = 0x2ad7eb25; u32 c2 = 0x2ad7eb25;
//---------- //----------
// body // body
const u32 * blocks = (const u32 *)(data + nblocks*8); const u32 * blocks = (const u32 *)(data + nblocks*8);
for(int i = -nblocks; i < 0; i+=Step) for(int i = -nblocks; i < 0; i+=Step)
{ {
u32 k1 = getblock(blocks,i*2+0); u32 k1 = getblock(blocks,i*2+0);
u32 k2 = getblock(blocks,i*2+1); u32 k2 = getblock(blocks,i*2+1);
bmix32(h1,h2,k1,k2,c1,c2); bmix32(h1,h2,k1,k2,c1,c2);
} }
//---------- //----------
// tail // tail
const u8 * tail = (const u8*)(data + nblocks*8); const u8 * tail = (const u8*)(data + nblocks*8);
u32 k1 = 0; u32 k1 = 0;
u32 k2 = 0; u32 k2 = 0;
switch(len & 7) switch(len & 7)
{ {
case 7: k2 ^= tail[6] << 16; case 7: k2 ^= tail[6] << 16;
case 6: k2 ^= tail[5] << 8; case 6: k2 ^= tail[5] << 8;
case 5: k2 ^= tail[4] << 0; case 5: k2 ^= tail[4] << 0;
case 4: k1 ^= tail[3] << 24; case 4: k1 ^= tail[3] << 24;
case 3: k1 ^= tail[2] << 16; case 3: k1 ^= tail[2] << 16;
case 2: k1 ^= tail[1] << 8; case 2: k1 ^= tail[1] << 8;
case 1: k1 ^= tail[0] << 0; case 1: k1 ^= tail[0] << 0;
bmix32(h1,h2,k1,k2,c1,c2); bmix32(h1,h2,k1,k2,c1,c2);
}; };
//---------- //----------
// finalization // finalization
h2 ^= len; h2 ^= len;
h1 += h2; h1 += h2;
h2 += h1; h2 += h1;
h1 = fmix32(h1); h1 = fmix32(h1);
h2 = fmix32(h2); h2 = fmix32(h2);
h1 += h2; h1 += h2;
h2 += h1; h2 += h1;
out[0] = h1; out[0] = h1;
out[1] = h2; out[1] = h2;
return *((u64 *)&out); return *((u64 *)&out);
} }
/* /*
@ -450,70 +450,70 @@ u64 GetMurmurHash3(const u8* src, int len, u32 samples)
*/ */
u64 GetHashHiresTexture(const u8 *src, int len, u32 samples) u64 GetHashHiresTexture(const u8 *src, int len, u32 samples)
{ {
const u64 m = 0xc6a4a7935bd1e995ULL; const u64 m = 0xc6a4a7935bd1e995ULL;
u64 h = len * m; u64 h = len * m;
const int r = 47; const int r = 47;
u32 Step = (len / 8); u32 Step = (len / 8);
const u64 *data = (const u64 *)src; const u64 *data = (const u64 *)src;
const u64 *end = data + Step; const u64 *end = data + Step;
if(samples == 0) samples = max(Step, 1u); if(samples == 0) samples = max(Step, 1u);
Step = Step / samples; Step = Step / samples;
if(Step < 1) Step = 1; if(Step < 1) Step = 1;
while(data < end) while(data < end)
{ {
u64 k = data[0]; u64 k = data[0];
data+=Step; data+=Step;
k *= m; k *= m;
k ^= k >> r; k ^= k >> r;
k *= m; k *= m;
h ^= k; h ^= k;
h *= m; h *= m;
} }
const u8 * data2 = (const u8*)end; const u8 * data2 = (const u8*)end;
switch(len & 7) switch(len & 7)
{ {
case 7: h ^= u64(data2[6]) << 48; case 7: h ^= u64(data2[6]) << 48;
case 6: h ^= u64(data2[5]) << 40; case 6: h ^= u64(data2[5]) << 40;
case 5: h ^= u64(data2[4]) << 32; case 5: h ^= u64(data2[4]) << 32;
case 4: h ^= u64(data2[3]) << 24; case 4: h ^= u64(data2[3]) << 24;
case 3: h ^= u64(data2[2]) << 16; case 3: h ^= u64(data2[2]) << 16;
case 2: h ^= u64(data2[1]) << 8; case 2: h ^= u64(data2[1]) << 8;
case 1: h ^= u64(data2[0]); case 1: h ^= u64(data2[0]);
h *= m; h *= m;
}; };
h ^= h >> r; h ^= h >> r;
h *= m; h *= m;
h ^= h >> r; h ^= h >> r;
return h; return h;
} }
#endif #endif
u64 GetHash64(const u8 *src, int len, u32 samples) u64 GetHash64(const u8 *src, int len, u32 samples)
{ {
return ptrHashFunction(src, len, samples); return ptrHashFunction(src, len, samples);
} }
// sets the hash function used for the texture cache // sets the hash function used for the texture cache
void SetHash64Function(bool useHiresTextures) void SetHash64Function(bool useHiresTextures)
{ {
if (useHiresTextures) if (useHiresTextures)
{ {
ptrHashFunction = &GetHashHiresTexture; ptrHashFunction = &GetHashHiresTexture;
} }
#if _M_SSE >= 0x402 #if _M_SSE >= 0x402
else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version else if (cpu_info.bSSE4_2 && !useHiresTextures) // sse crc32 version
{ {
ptrHashFunction = &GetCRC32; ptrHashFunction = &GetCRC32;
} }
#endif #endif
else else
{ {
ptrHashFunction = &GetMurmurHash3; ptrHashFunction = &GetMurmurHash3;
} }
} }

View file

@ -30,7 +30,7 @@ template <typename K, typename V>
class LinearDiskCacheReader class LinearDiskCacheReader
{ {
public: public:
virtual void Read(const K &key, const V *value, u32 value_size) = 0; virtual void Read(const K &key, const V *value, u32 value_size) = 0;
}; };
// Dead simple unsorted key-value store with append functionality. // Dead simple unsorted key-value store with append functionality.
@ -49,143 +49,143 @@ template <typename K, typename V>
class LinearDiskCache class LinearDiskCache
{ {
public: public:
// return number of read entries // return number of read entries
u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader) u32 OpenAndRead(const char *filename, LinearDiskCacheReader<K, V> &reader)
{ {
using std::ios_base; using std::ios_base;
// close any currently opened file // close any currently opened file
Close(); Close();
m_num_entries = 0; m_num_entries = 0;
// try opening for reading/writing // try opening for reading/writing
OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary); OpenFStream(m_file, filename, ios_base::in | ios_base::out | ios_base::binary);
m_file.seekg(0, std::ios::end); m_file.seekg(0, std::ios::end);
std::fstream::pos_type end_pos = m_file.tellg(); std::fstream::pos_type end_pos = m_file.tellg();
m_file.seekg(0, std::ios::beg); m_file.seekg(0, std::ios::beg);
std::fstream::pos_type start_pos = m_file.tellg(); std::fstream::pos_type start_pos = m_file.tellg();
std::streamoff file_size = end_pos - start_pos; std::streamoff file_size = end_pos - start_pos;
if (m_file.is_open() && ValidateHeader()) if (m_file.is_open() && ValidateHeader())
{ {
// good header, read some key/value pairs // good header, read some key/value pairs
K key; K key;
V *value = NULL; V *value = NULL;
u32 value_size; u32 value_size;
u32 entry_number; u32 entry_number;
std::fstream::pos_type last_pos = m_file.tellg(); std::fstream::pos_type last_pos = m_file.tellg();
while (Read(&value_size)) while (Read(&value_size))
{ {
std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size; std::streamoff next_extent = (last_pos - start_pos) + sizeof(value_size) + value_size;
if (next_extent > file_size) if (next_extent > file_size)
break; break;
delete[] value; delete[] value;
value = new V[value_size]; value = new V[value_size];
// read key/value and pass to reader // read key/value and pass to reader
if (Read(&key) && if (Read(&key) &&
Read(value, value_size) && Read(value, value_size) &&
Read(&entry_number) && Read(&entry_number) &&
entry_number == m_num_entries+1) entry_number == m_num_entries+1)
{ {
reader.Read(key, value, value_size); reader.Read(key, value, value_size);
} }
else else
{ {
break; break;
} }
m_num_entries++; m_num_entries++;
last_pos = m_file.tellg(); last_pos = m_file.tellg();
} }
m_file.seekp(last_pos); m_file.seekp(last_pos);
m_file.clear(); m_file.clear();
delete[] value; delete[] value;
return m_num_entries; return m_num_entries;
} }
// failed to open file for reading or bad header // failed to open file for reading or bad header
// close and recreate file // close and recreate file
Close(); Close();
m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary); m_file.open(filename, ios_base::out | ios_base::trunc | ios_base::binary);
WriteHeader(); WriteHeader();
return 0; return 0;
} }
void Sync() void Sync()
{ {
m_file.flush(); m_file.flush();
} }
void Close() void Close()
{ {
if (m_file.is_open()) if (m_file.is_open())
m_file.close(); m_file.close();
// clear any error flags // clear any error flags
m_file.clear(); m_file.clear();
} }
// Appends a key-value pair to the store. // Appends a key-value pair to the store.
void Append(const K &key, const V *value, u32 value_size) void Append(const K &key, const V *value, u32 value_size)
{ {
// TODO: Should do a check that we don't already have "key"? (I think each caller does that already.) // TODO: Should do a check that we don't already have "key"? (I think each caller does that already.)
Write(&value_size); Write(&value_size);
Write(&key); Write(&key);
Write(value, value_size); Write(value, value_size);
m_num_entries++; m_num_entries++;
Write(&m_num_entries); Write(&m_num_entries);
} }
private: private:
void WriteHeader() void WriteHeader()
{ {
Write(&m_header); Write(&m_header);
} }
bool ValidateHeader() bool ValidateHeader()
{ {
char file_header[sizeof(Header)]; char file_header[sizeof(Header)];
return (Read(file_header, sizeof(Header)) return (Read(file_header, sizeof(Header))
&& !memcmp((const char*)&m_header, file_header, sizeof(Header))); && !memcmp((const char*)&m_header, file_header, sizeof(Header)));
} }
template <typename D> template <typename D>
bool Write(const D *data, u32 count = 1) bool Write(const D *data, u32 count = 1)
{ {
return m_file.write((const char*)data, count * sizeof(D)).good(); return m_file.write((const char*)data, count * sizeof(D)).good();
} }
template <typename D> template <typename D>
bool Read(const D *data, u32 count = 1) bool Read(const D *data, u32 count = 1)
{ {
return m_file.read((char*)data, count * sizeof(D)).good(); return m_file.read((char*)data, count * sizeof(D)).good();
} }
struct Header struct Header
{ {
Header() Header()
: id(*(u32*)"DCAC") : id(*(u32*)"DCAC")
, key_t_size(sizeof(K)) , key_t_size(sizeof(K))
, value_t_size(sizeof(V)) , value_t_size(sizeof(V))
{ {
memcpy(ver, scm_rev_git_str, 40); memcpy(ver, scm_rev_git_str, 40);
} }
const u32 id; const u32 id;
const u16 key_t_size, value_t_size; const u16 key_t_size, value_t_size;
char ver[40]; char ver[40];
} m_header; } m_header;
std::fstream m_file; std::fstream m_file;
u32 m_num_entries; u32 m_num_entries;
}; };
#endif // _LINEAR_DISKCACHE #endif // _LINEAR_DISKCACHE

View file

@ -5,74 +5,74 @@
#ifndef _LOG_H_ #ifndef _LOG_H_
#define _LOG_H_ #define _LOG_H_
#define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports. #define NOTICE_LEVEL 1 // VERY important information that is NOT errors. Like startup and OSReports.
#define ERROR_LEVEL 2 // Critical errors #define ERROR_LEVEL 2 // Critical errors
#define WARNING_LEVEL 3 // Something is suspicious. #define WARNING_LEVEL 3 // Something is suspicious.
#define INFO_LEVEL 4 // General information. #define INFO_LEVEL 4 // General information.
#define DEBUG_LEVEL 5 // Detailed debugging - might make things slow. #define DEBUG_LEVEL 5 // Detailed debugging - might make things slow.
namespace LogTypes namespace LogTypes
{ {
enum LOG_TYPE { enum LOG_TYPE {
ACTIONREPLAY, ACTIONREPLAY,
AUDIO, AUDIO,
AUDIO_INTERFACE, AUDIO_INTERFACE,
BOOT, BOOT,
COMMANDPROCESSOR, COMMANDPROCESSOR,
COMMON, COMMON,
CONSOLE, CONSOLE,
DISCIO, DISCIO,
FILEMON, FILEMON,
DSPHLE, DSPHLE,
DSPLLE, DSPLLE,
DSP_MAIL, DSP_MAIL,
DSPINTERFACE, DSPINTERFACE,
DVDINTERFACE, DVDINTERFACE,
DYNA_REC, DYNA_REC,
EXPANSIONINTERFACE, EXPANSIONINTERFACE,
GDB_STUB, GDB_STUB,
ARM11, ARM11,
GPFIFO, GPFIFO,
OSHLE, OSHLE,
MASTER_LOG, MASTER_LOG,
MEMMAP, MEMMAP,
MEMCARD_MANAGER, MEMCARD_MANAGER,
OSREPORT, OSREPORT,
PAD, PAD,
PROCESSORINTERFACE, PROCESSORINTERFACE,
PIXELENGINE, PIXELENGINE,
SERIALINTERFACE, SERIALINTERFACE,
SP1, SP1,
STREAMINGINTERFACE, STREAMINGINTERFACE,
VIDEO, VIDEO,
VIDEOINTERFACE, VIDEOINTERFACE,
LOADER, LOADER,
FILESYS, FILESYS,
WII_IPC_DVD, WII_IPC_DVD,
WII_IPC_ES, WII_IPC_ES,
WII_IPC_FILEIO, WII_IPC_FILEIO,
WII_IPC_HID, WII_IPC_HID,
WII_IPC_HLE, WII_IPC_HLE,
WII_IPC_NET, WII_IPC_NET,
WII_IPC_WC24, WII_IPC_WC24,
WII_IPC_SSL, WII_IPC_SSL,
WII_IPC_SD, WII_IPC_SD,
WII_IPC_STM, WII_IPC_STM,
WII_IPC_WIIMOTE, WII_IPC_WIIMOTE,
TIME, TIME,
NETPLAY, NETPLAY,
NUMBER_OF_LOGS // Must be last NUMBER_OF_LOGS // Must be last
}; };
// FIXME: should this be removed? // FIXME: should this be removed?
enum LOG_LEVELS { enum LOG_LEVELS {
LNOTICE = NOTICE_LEVEL, LNOTICE = NOTICE_LEVEL,
LERROR = ERROR_LEVEL, LERROR = ERROR_LEVEL,
LWARNING = WARNING_LEVEL, LWARNING = WARNING_LEVEL,
LINFO = INFO_LEVEL, LINFO = INFO_LEVEL,
LDEBUG = DEBUG_LEVEL, LDEBUG = DEBUG_LEVEL,
}; };
#define LOGTYPES_LEVELS LogTypes::LOG_LEVELS #define LOGTYPES_LEVELS LogTypes::LOG_LEVELS
@ -81,11 +81,11 @@ enum LOG_LEVELS {
} // namespace } // namespace
void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type, void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
const char *file, int line, const char *fmt, ...) const char *file, int line, const char *fmt, ...)
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 5, 6))) __attribute__((format(printf, 5, 6)))
#endif #endif
; ;
#if defined LOGGING || defined _DEBUG || defined DEBUGFAST #if defined LOGGING || defined _DEBUG || defined DEBUGFAST
#define MAX_LOGLEVEL DEBUG_LEVEL #define MAX_LOGLEVEL DEBUG_LEVEL
@ -100,9 +100,9 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
#else #else
// Let the compiler optimize this out // Let the compiler optimize this out
#define GENERIC_LOG(t, v, ...) { \ #define GENERIC_LOG(t, v, ...) { \
if (v <= MAX_LOGLEVEL) \ if (v <= MAX_LOGLEVEL) \
GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \ GenericLog(v, t, __FILE__, __LINE__, __VA_ARGS__); \
} }
#endif #endif
#define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0) #define ERROR_LOG(t,...) do { GENERIC_LOG(LogTypes::t, LogTypes::LERROR, __VA_ARGS__) } while (0)
@ -113,16 +113,16 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
#if MAX_LOGLEVEL >= DEBUG_LEVEL #if MAX_LOGLEVEL >= DEBUG_LEVEL
#define _dbg_assert_(_t_, _a_) \ #define _dbg_assert_(_t_, _a_) \
if (!(_a_)) {\ if (!(_a_)) {\
ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \ ERROR_LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
__LINE__, __FILE__, __TIME__); \ __LINE__, __FILE__, __TIME__); \
if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \ if (!PanicYesNo("*** Assertion (see log)***\n")) {Crash();} \
} }
#define _dbg_assert_msg_(_t_, _a_, ...)\ #define _dbg_assert_msg_(_t_, _a_, ...)\
if (!(_a_)) {\ if (!(_a_)) {\
ERROR_LOG(_t_, __VA_ARGS__); \ ERROR_LOG(_t_, __VA_ARGS__); \
if (!PanicYesNo(__VA_ARGS__)) {Crash();} \ if (!PanicYesNo(__VA_ARGS__)) {Crash();} \
} }
#define _dbg_update_() Host_UpdateLogDisplay(); #define _dbg_update_() Host_UpdateLogDisplay();
#else // not debug #else // not debug
@ -138,15 +138,15 @@ void GenericLog(LOGTYPES_LEVELS level, LOGTYPES_TYPE type,
#ifndef GEKKO #ifndef GEKKO
#ifdef _WIN32 #ifdef _WIN32
#define _assert_msg_(_t_, _a_, _fmt_, ...) \ #define _assert_msg_(_t_, _a_, _fmt_, ...) \
if (!(_a_)) {\ if (!(_a_)) {\
if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \ if (!PanicYesNo(_fmt_, __VA_ARGS__)) {Crash();} \
} }
#else // not win32 #else // not win32
#define _assert_msg_(_t_, _a_, _fmt_, ...) \ #define _assert_msg_(_t_, _a_, _fmt_, ...) \
if (!(_a_)) {\ if (!(_a_)) {\
if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \ if (!PanicYesNo(_fmt_, ##__VA_ARGS__)) {Crash();} \
} }
#endif // WIN32 #endif // WIN32
#else // GEKKO #else // GEKKO
#define _assert_msg_(_t_, _a_, _fmt_, ...) #define _assert_msg_(_t_, _a_, _fmt_, ...)

View file

@ -14,187 +14,187 @@
#include "file_util.h" #include "file_util.h"
void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, void GenericLog(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
const char *file, int line, const char* fmt, ...) const char *file, int line, const char* fmt, ...)
{ {
va_list args; va_list args;
va_start(args, fmt); va_start(args, fmt);
if (LogManager::GetInstance()) if (LogManager::GetInstance())
LogManager::GetInstance()->Log(level, type, LogManager::GetInstance()->Log(level, type,
file, line, fmt, args); file, line, fmt, args);
va_end(args); va_end(args);
} }
LogManager *LogManager::m_logManager = NULL; LogManager *LogManager::m_logManager = NULL;
LogManager::LogManager() LogManager::LogManager()
{ {
// create log files // create log files
m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log"); m_Log[LogTypes::MASTER_LOG] = new LogContainer("*", "Master Log");
m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot"); m_Log[LogTypes::BOOT] = new LogContainer("BOOT", "Boot");
m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common"); m_Log[LogTypes::COMMON] = new LogContainer("COMMON", "Common");
m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO"); m_Log[LogTypes::DISCIO] = new LogContainer("DIO", "Disc IO");
m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor"); m_Log[LogTypes::FILEMON] = new LogContainer("FileMon", "File Monitor");
m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad"); m_Log[LogTypes::PAD] = new LogContainer("PAD", "Pad");
m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine"); m_Log[LogTypes::PIXELENGINE] = new LogContainer("PE", "PixelEngine");
m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc"); m_Log[LogTypes::COMMANDPROCESSOR] = new LogContainer("CP", "CommandProc");
m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt"); m_Log[LogTypes::VIDEOINTERFACE] = new LogContainer("VI", "VideoInt");
m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt"); m_Log[LogTypes::SERIALINTERFACE] = new LogContainer("SI", "SerialInt");
m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt"); m_Log[LogTypes::PROCESSORINTERFACE] = new LogContainer("PI", "ProcessorInt");
m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap"); m_Log[LogTypes::MEMMAP] = new LogContainer("MI", "MI & memmap");
m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1"); m_Log[LogTypes::SP1] = new LogContainer("SP1", "Serial Port 1");
m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt"); m_Log[LogTypes::STREAMINGINTERFACE] = new LogContainer("Stream", "StreamingInt");
m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface"); m_Log[LogTypes::DSPINTERFACE] = new LogContainer("DSP", "DSPInterface");
m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface"); m_Log[LogTypes::DVDINTERFACE] = new LogContainer("DVD", "DVDInterface");
m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo"); m_Log[LogTypes::GPFIFO] = new LogContainer("GP", "GPFifo");
m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt"); m_Log[LogTypes::EXPANSIONINTERFACE] = new LogContainer("EXI", "ExpansionInt");
m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub"); m_Log[LogTypes::GDB_STUB] = new LogContainer("GDB_STUB", "GDB Stub");
m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt"); m_Log[LogTypes::AUDIO_INTERFACE] = new LogContainer("AI", "AudioInt");
m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11"); m_Log[LogTypes::ARM11] = new LogContainer("ARM11", "ARM11");
m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE"); m_Log[LogTypes::OSHLE] = new LogContainer("HLE", "HLE");
m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE"); m_Log[LogTypes::DSPHLE] = new LogContainer("DSPHLE", "DSP HLE");
m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE"); m_Log[LogTypes::DSPLLE] = new LogContainer("DSPLLE", "DSP LLE");
m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails"); m_Log[LogTypes::DSP_MAIL] = new LogContainer("DSPMails", "DSP Mails");
m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend"); m_Log[LogTypes::VIDEO] = new LogContainer("Video", "Video Backend");
m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator"); m_Log[LogTypes::AUDIO] = new LogContainer("Audio", "Audio Emulator");
m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler"); m_Log[LogTypes::DYNA_REC] = new LogContainer("JIT", "Dynamic Recompiler");
m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console"); m_Log[LogTypes::CONSOLE] = new LogContainer("CONSOLE", "Dolphin Console");
m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport"); m_Log[LogTypes::OSREPORT] = new LogContainer("OSREPORT", "OSReport");
m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing"); m_Log[LogTypes::TIME] = new LogContainer("Time", "Core Timing");
m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader"); m_Log[LogTypes::LOADER] = new LogContainer("Loader", "Loader");
m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System"); m_Log[LogTypes::FILESYS] = new LogContainer("FileSys", "File System");
m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID"); m_Log[LogTypes::WII_IPC_HID] = new LogContainer("WII_IPC_HID", "WII IPC HID");
m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE"); m_Log[LogTypes::WII_IPC_HLE] = new LogContainer("WII_IPC_HLE", "WII IPC HLE");
m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD"); m_Log[LogTypes::WII_IPC_DVD] = new LogContainer("WII_IPC_DVD", "WII IPC DVD");
m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES"); m_Log[LogTypes::WII_IPC_ES] = new LogContainer("WII_IPC_ES", "WII IPC ES");
m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO"); m_Log[LogTypes::WII_IPC_FILEIO] = new LogContainer("WII_IPC_FILEIO","WII IPC FILEIO");
m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD"); m_Log[LogTypes::WII_IPC_SD] = new LogContainer("WII_IPC_SD", "WII IPC SD");
m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM"); m_Log[LogTypes::WII_IPC_STM] = new LogContainer("WII_IPC_STM", "WII IPC STM");
m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET"); m_Log[LogTypes::WII_IPC_NET] = new LogContainer("WII_IPC_NET", "WII IPC NET");
m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24"); m_Log[LogTypes::WII_IPC_WC24] = new LogContainer("WII_IPC_WC24", "WII IPC WC24");
m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL"); m_Log[LogTypes::WII_IPC_SSL] = new LogContainer("WII_IPC_SSL", "WII IPC SSL");
m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE"); m_Log[LogTypes::WII_IPC_WIIMOTE] = new LogContainer("WII_IPC_WIIMOTE","WII IPC WIIMOTE");
m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay"); m_Log[LogTypes::ACTIONREPLAY] = new LogContainer("ActionReplay", "ActionReplay");
m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager"); m_Log[LogTypes::MEMCARD_MANAGER] = new LogContainer("MemCard Manager", "MemCard Manager");
m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay"); m_Log[LogTypes::NETPLAY] = new LogContainer("NETPLAY", "Netplay");
m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str()); m_fileLog = new FileLogListener(File::GetUserPath(F_MAINLOG_IDX).c_str());
m_consoleLog = new ConsoleListener(); m_consoleLog = new ConsoleListener();
m_debuggerLog = new DebuggerLogListener(); m_debuggerLog = new DebuggerLogListener();
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{ {
m_Log[i]->SetEnable(true); m_Log[i]->SetEnable(true);
m_Log[i]->AddListener(m_fileLog); m_Log[i]->AddListener(m_fileLog);
m_Log[i]->AddListener(m_consoleLog); m_Log[i]->AddListener(m_consoleLog);
#ifdef _MSC_VER #ifdef _MSC_VER
if (IsDebuggerPresent()) if (IsDebuggerPresent())
m_Log[i]->AddListener(m_debuggerLog); m_Log[i]->AddListener(m_debuggerLog);
#endif #endif
} }
} }
LogManager::~LogManager() LogManager::~LogManager()
{ {
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
{ {
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_fileLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_consoleLog);
m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog); m_logManager->RemoveListener((LogTypes::LOG_TYPE)i, m_debuggerLog);
} }
for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i) for (int i = 0; i < LogTypes::NUMBER_OF_LOGS; ++i)
delete m_Log[i]; delete m_Log[i];
delete m_fileLog; delete m_fileLog;
delete m_consoleLog; delete m_consoleLog;
delete m_debuggerLog; delete m_debuggerLog;
} }
void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, void LogManager::Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
const char *file, int line, const char *format, va_list args) const char *file, int line, const char *format, va_list args)
{ {
char temp[MAX_MSGLEN]; char temp[MAX_MSGLEN];
char msg[MAX_MSGLEN * 2]; char msg[MAX_MSGLEN * 2];
LogContainer *log = m_Log[type]; LogContainer *log = m_Log[type];
if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners()) if (!log->IsEnabled() || level > log->GetLevel() || ! log->HasListeners())
return; return;
CharArrayFromFormatV(temp, MAX_MSGLEN, format, args); CharArrayFromFormatV(temp, MAX_MSGLEN, format, args);
static const char level_to_char[7] = "-NEWID"; static const char level_to_char[7] = "-NEWID";
sprintf(msg, "%s %s:%u %c[%s]: %s\n", sprintf(msg, "%s %s:%u %c[%s]: %s\n",
Common::Timer::GetTimeFormatted().c_str(), Common::Timer::GetTimeFormatted().c_str(),
file, line, level_to_char[(int)level], file, line, level_to_char[(int)level],
log->GetShortName(), temp); log->GetShortName(), temp);
#ifdef ANDROID #ifdef ANDROID
Host_SysMessage(msg); Host_SysMessage(msg);
#endif #endif
printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this printf(msg); // TODO(ShizZy): RemoveMe when I no longer need this
log->Trigger(level, msg); log->Trigger(level, msg);
} }
void LogManager::Init() void LogManager::Init()
{ {
m_logManager = new LogManager(); m_logManager = new LogManager();
} }
void LogManager::Shutdown() void LogManager::Shutdown()
{ {
delete m_logManager; delete m_logManager;
m_logManager = NULL; m_logManager = NULL;
} }
LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable) LogContainer::LogContainer(const char* shortName, const char* fullName, bool enable)
: m_enable(enable) : m_enable(enable)
{ {
strncpy(m_fullName, fullName, 128); strncpy(m_fullName, fullName, 128);
strncpy(m_shortName, shortName, 32); strncpy(m_shortName, shortName, 32);
m_level = LogTypes::LWARNING; m_level = LogTypes::LWARNING;
} }
// LogContainer // LogContainer
void LogContainer::AddListener(LogListener *listener) void LogContainer::AddListener(LogListener *listener)
{ {
std::lock_guard<std::mutex> lk(m_listeners_lock); std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.insert(listener); m_listeners.insert(listener);
} }
void LogContainer::RemoveListener(LogListener *listener) void LogContainer::RemoveListener(LogListener *listener)
{ {
std::lock_guard<std::mutex> lk(m_listeners_lock); std::lock_guard<std::mutex> lk(m_listeners_lock);
m_listeners.erase(listener); m_listeners.erase(listener);
} }
void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg) void LogContainer::Trigger(LogTypes::LOG_LEVELS level, const char *msg)
{ {
std::lock_guard<std::mutex> lk(m_listeners_lock); std::lock_guard<std::mutex> lk(m_listeners_lock);
std::set<LogListener*>::const_iterator i; std::set<LogListener*>::const_iterator i;
for (i = m_listeners.begin(); i != m_listeners.end(); ++i) for (i = m_listeners.begin(); i != m_listeners.end(); ++i)
{ {
(*i)->Log(level, msg); (*i)->Log(level, msg);
} }
} }
FileLogListener::FileLogListener(const char *filename) FileLogListener::FileLogListener(const char *filename)
{ {
OpenFStream(m_logfile, filename, std::ios::app); OpenFStream(m_logfile, filename, std::ios::app);
SetEnable(true); SetEnable(true);
} }
void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) void FileLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{ {
if (!IsEnabled() || !IsValid()) if (!IsEnabled() || !IsValid())
return; return;
std::lock_guard<std::mutex> lk(m_log_lock); std::lock_guard<std::mutex> lk(m_log_lock);
m_logfile << msg << std::flush; m_logfile << msg << std::flush;
} }
void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg) void DebuggerLogListener::Log(LogTypes::LOG_LEVELS, const char *msg)
{ {
#if _MSC_VER #if _MSC_VER
::OutputDebugStringA(msg); ::OutputDebugStringA(msg);
#endif #endif
} }

View file

@ -21,65 +21,65 @@
class LogListener class LogListener
{ {
public: public:
virtual ~LogListener() {} virtual ~LogListener() {}
virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0; virtual void Log(LogTypes::LOG_LEVELS, const char *msg) = 0;
}; };
class FileLogListener : public LogListener class FileLogListener : public LogListener
{ {
public: public:
FileLogListener(const char *filename); FileLogListener(const char *filename);
void Log(LogTypes::LOG_LEVELS, const char *msg); void Log(LogTypes::LOG_LEVELS, const char *msg);
bool IsValid() { return !m_logfile.fail(); } bool IsValid() { return !m_logfile.fail(); }
bool IsEnabled() const { return m_enable; } bool IsEnabled() const { return m_enable; }
void SetEnable(bool enable) { m_enable = enable; } void SetEnable(bool enable) { m_enable = enable; }
const char* GetName() const { return "file"; } const char* GetName() const { return "file"; }
private: private:
std::mutex m_log_lock; std::mutex m_log_lock;
std::ofstream m_logfile; std::ofstream m_logfile;
bool m_enable; bool m_enable;
}; };
class DebuggerLogListener : public LogListener class DebuggerLogListener : public LogListener
{ {
public: public:
void Log(LogTypes::LOG_LEVELS, const char *msg); void Log(LogTypes::LOG_LEVELS, const char *msg);
}; };
class LogContainer class LogContainer
{ {
public: public:
LogContainer(const char* shortName, const char* fullName, bool enable = false); LogContainer(const char* shortName, const char* fullName, bool enable = false);
const char* GetShortName() const { return m_shortName; } const char* GetShortName() const { return m_shortName; }
const char* GetFullName() const { return m_fullName; } const char* GetFullName() const { return m_fullName; }
void AddListener(LogListener* listener); void AddListener(LogListener* listener);
void RemoveListener(LogListener* listener); void RemoveListener(LogListener* listener);
void Trigger(LogTypes::LOG_LEVELS, const char *msg); void Trigger(LogTypes::LOG_LEVELS, const char *msg);
bool IsEnabled() const { return m_enable; } bool IsEnabled() const { return m_enable; }
void SetEnable(bool enable) { m_enable = enable; } void SetEnable(bool enable) { m_enable = enable; }
LogTypes::LOG_LEVELS GetLevel() const { return m_level; } LogTypes::LOG_LEVELS GetLevel() const { return m_level; }
void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; } void SetLevel(LogTypes::LOG_LEVELS level) { m_level = level; }
bool HasListeners() const { return !m_listeners.empty(); } bool HasListeners() const { return !m_listeners.empty(); }
private: private:
char m_fullName[128]; char m_fullName[128];
char m_shortName[32]; char m_shortName[32];
bool m_enable; bool m_enable;
LogTypes::LOG_LEVELS m_level; LogTypes::LOG_LEVELS m_level;
std::mutex m_listeners_lock; std::mutex m_listeners_lock;
std::set<LogListener*> m_listeners; std::set<LogListener*> m_listeners;
}; };
class ConsoleListener; class ConsoleListener;
@ -87,83 +87,83 @@ class ConsoleListener;
class LogManager : NonCopyable class LogManager : NonCopyable
{ {
private: private:
LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS]; LogContainer* m_Log[LogTypes::NUMBER_OF_LOGS];
FileLogListener *m_fileLog; FileLogListener *m_fileLog;
ConsoleListener *m_consoleLog; ConsoleListener *m_consoleLog;
DebuggerLogListener *m_debuggerLog; DebuggerLogListener *m_debuggerLog;
static LogManager *m_logManager; // Singleton. Ugh. static LogManager *m_logManager; // Singleton. Ugh.
LogManager(); LogManager();
~LogManager(); ~LogManager();
public: public:
static u32 GetMaxLevel() { return MAX_LOGLEVEL; } static u32 GetMaxLevel() { return MAX_LOGLEVEL; }
void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type, void Log(LogTypes::LOG_LEVELS level, LogTypes::LOG_TYPE type,
const char *file, int line, const char *fmt, va_list args); const char *file, int line, const char *fmt, va_list args);
void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level) void SetLogLevel(LogTypes::LOG_TYPE type, LogTypes::LOG_LEVELS level)
{ {
m_Log[type]->SetLevel(level); m_Log[type]->SetLevel(level);
} }
void SetEnable(LogTypes::LOG_TYPE type, bool enable) void SetEnable(LogTypes::LOG_TYPE type, bool enable)
{ {
m_Log[type]->SetEnable(enable); m_Log[type]->SetEnable(enable);
} }
bool IsEnabled(LogTypes::LOG_TYPE type) const bool IsEnabled(LogTypes::LOG_TYPE type) const
{ {
return m_Log[type]->IsEnabled(); return m_Log[type]->IsEnabled();
} }
const char* GetShortName(LogTypes::LOG_TYPE type) const const char* GetShortName(LogTypes::LOG_TYPE type) const
{ {
return m_Log[type]->GetShortName(); return m_Log[type]->GetShortName();
} }
const char* GetFullName(LogTypes::LOG_TYPE type) const const char* GetFullName(LogTypes::LOG_TYPE type) const
{ {
return m_Log[type]->GetFullName(); return m_Log[type]->GetFullName();
} }
void AddListener(LogTypes::LOG_TYPE type, LogListener *listener) void AddListener(LogTypes::LOG_TYPE type, LogListener *listener)
{ {
m_Log[type]->AddListener(listener); m_Log[type]->AddListener(listener);
} }
void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener) void RemoveListener(LogTypes::LOG_TYPE type, LogListener *listener)
{ {
m_Log[type]->RemoveListener(listener); m_Log[type]->RemoveListener(listener);
} }
FileLogListener *GetFileListener() const FileLogListener *GetFileListener() const
{ {
return m_fileLog; return m_fileLog;
} }
ConsoleListener *GetConsoleListener() const ConsoleListener *GetConsoleListener() const
{ {
return m_consoleLog; return m_consoleLog;
} }
DebuggerLogListener *GetDebuggerListener() const DebuggerLogListener *GetDebuggerListener() const
{ {
return m_debuggerLog; return m_debuggerLog;
} }
static LogManager* GetInstance() static LogManager* GetInstance()
{ {
return m_logManager; return m_logManager;
} }
static void SetInstance(LogManager *logManager) static void SetInstance(LogManager *logManager)
{ {
m_logManager = logManager; m_logManager = logManager;
} }
static void Init(); static void Init();
static void Shutdown(); static void Shutdown();
}; };
#endif // _LOGMANAGER_H_ #endif // _LOGMANAGER_H_

View file

@ -14,82 +14,82 @@ namespace MathUtil
u32 ClassifyDouble(double dvalue) u32 ClassifyDouble(double dvalue)
{ {
// TODO: Optimize the below to be as fast as possible. // TODO: Optimize the below to be as fast as possible.
IntDouble value; IntDouble value;
value.d = dvalue; value.d = dvalue;
u64 sign = value.i & DOUBLE_SIGN; u64 sign = value.i & DOUBLE_SIGN;
u64 exp = value.i & DOUBLE_EXP; u64 exp = value.i & DOUBLE_EXP;
if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP) if (exp > DOUBLE_ZERO && exp < DOUBLE_EXP)
{ {
// Nice normalized number. // Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
} }
else else
{ {
u64 mantissa = value.i & DOUBLE_FRAC; u64 mantissa = value.i & DOUBLE_FRAC;
if (mantissa) if (mantissa)
{ {
if (exp) if (exp)
{ {
return PPC_FPCLASS_QNAN; return PPC_FPCLASS_QNAN;
} }
else else
{ {
// Denormalized number. // Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
} }
} }
else if (exp) else if (exp)
{ {
//Infinite //Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
} }
else else
{ {
//Zero //Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
} }
} }
} }
u32 ClassifyFloat(float fvalue) u32 ClassifyFloat(float fvalue)
{ {
// TODO: Optimize the below to be as fast as possible. // TODO: Optimize the below to be as fast as possible.
IntFloat value; IntFloat value;
value.f = fvalue; value.f = fvalue;
u32 sign = value.i & FLOAT_SIGN; u32 sign = value.i & FLOAT_SIGN;
u32 exp = value.i & FLOAT_EXP; u32 exp = value.i & FLOAT_EXP;
if (exp > FLOAT_ZERO && exp < FLOAT_EXP) if (exp > FLOAT_ZERO && exp < FLOAT_EXP)
{ {
// Nice normalized number. // Nice normalized number.
return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN; return sign ? PPC_FPCLASS_NN : PPC_FPCLASS_PN;
} }
else else
{ {
u32 mantissa = value.i & FLOAT_FRAC; u32 mantissa = value.i & FLOAT_FRAC;
if (mantissa) if (mantissa)
{ {
if (exp) if (exp)
{ {
return PPC_FPCLASS_QNAN; // Quiet NAN return PPC_FPCLASS_QNAN; // Quiet NAN
} }
else else
{ {
// Denormalized number. // Denormalized number.
return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD; return sign ? PPC_FPCLASS_ND : PPC_FPCLASS_PD;
} }
} }
else if (exp) else if (exp)
{ {
// Infinite // Infinite
return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF; return sign ? PPC_FPCLASS_NINF : PPC_FPCLASS_PINF;
} }
else else
{ {
//Zero //Zero
return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ; return sign ? PPC_FPCLASS_NZ : PPC_FPCLASS_PZ;
} }
} }
} }
@ -97,116 +97,116 @@ u32 ClassifyFloat(float fvalue)
inline void MatrixMul(int n, const float *a, const float *b, float *result) inline void MatrixMul(int n, const float *a, const float *b, float *result)
{ {
for (int i = 0; i < n; ++i) for (int i = 0; i < n; ++i)
{ {
for (int j = 0; j < n; ++j) for (int j = 0; j < n; ++j)
{ {
float temp = 0; float temp = 0;
for (int k = 0; k < n; ++k) for (int k = 0; k < n; ++k)
{ {
temp += a[i * n + k] * b[k * n + j]; temp += a[i * n + k] * b[k * n + j];
} }
result[i * n + j] = temp; result[i * n + j] = temp;
} }
} }
} }
// Calculate sum of a float list // Calculate sum of a float list
float MathFloatVectorSum(const std::vector<float>& Vec) float MathFloatVectorSum(const std::vector<float>& Vec)
{ {
return std::accumulate(Vec.begin(), Vec.end(), 0.0f); return std::accumulate(Vec.begin(), Vec.end(), 0.0f);
} }
void Matrix33::LoadIdentity(Matrix33 &mtx) void Matrix33::LoadIdentity(Matrix33 &mtx)
{ {
memset(mtx.data, 0, sizeof(mtx.data)); memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f; mtx.data[0] = 1.0f;
mtx.data[4] = 1.0f; mtx.data[4] = 1.0f;
mtx.data[8] = 1.0f; mtx.data[8] = 1.0f;
} }
void Matrix33::RotateX(Matrix33 &mtx, float rad) void Matrix33::RotateX(Matrix33 &mtx, float rad)
{ {
float s = sin(rad); float s = sin(rad);
float c = cos(rad); float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data)); memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1; mtx.data[0] = 1;
mtx.data[4] = c; mtx.data[4] = c;
mtx.data[5] = -s; mtx.data[5] = -s;
mtx.data[7] = s; mtx.data[7] = s;
mtx.data[8] = c; mtx.data[8] = c;
} }
void Matrix33::RotateY(Matrix33 &mtx, float rad) void Matrix33::RotateY(Matrix33 &mtx, float rad)
{ {
float s = sin(rad); float s = sin(rad);
float c = cos(rad); float c = cos(rad);
memset(mtx.data, 0, sizeof(mtx.data)); memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = c; mtx.data[0] = c;
mtx.data[2] = s; mtx.data[2] = s;
mtx.data[4] = 1; mtx.data[4] = 1;
mtx.data[6] = -s; mtx.data[6] = -s;
mtx.data[8] = c; mtx.data[8] = c;
} }
void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result) void Matrix33::Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result)
{ {
MatrixMul(3, a.data, b.data, result.data); MatrixMul(3, a.data, b.data, result.data);
} }
void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3]) void Matrix33::Multiply(const Matrix33 &a, const float vec[3], float result[3])
{ {
for (int i = 0; i < 3; ++i) { for (int i = 0; i < 3; ++i) {
result[i] = 0; result[i] = 0;
for (int k = 0; k < 3; ++k) { for (int k = 0; k < 3; ++k) {
result[i] += a.data[i * 3 + k] * vec[k]; result[i] += a.data[i * 3 + k] * vec[k];
} }
} }
} }
void Matrix44::LoadIdentity(Matrix44 &mtx) void Matrix44::LoadIdentity(Matrix44 &mtx)
{ {
memset(mtx.data, 0, sizeof(mtx.data)); memset(mtx.data, 0, sizeof(mtx.data));
mtx.data[0] = 1.0f; mtx.data[0] = 1.0f;
mtx.data[5] = 1.0f; mtx.data[5] = 1.0f;
mtx.data[10] = 1.0f; mtx.data[10] = 1.0f;
mtx.data[15] = 1.0f; mtx.data[15] = 1.0f;
} }
void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33) void Matrix44::LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33)
{ {
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
for (int j = 0; j < 3; ++j) for (int j = 0; j < 3; ++j)
{ {
mtx.data[i * 4 + j] = m33.data[i * 3 + j]; mtx.data[i * 4 + j] = m33.data[i * 3 + j];
} }
} }
for (int i = 0; i < 3; ++i) for (int i = 0; i < 3; ++i)
{ {
mtx.data[i * 4 + 3] = 0; mtx.data[i * 4 + 3] = 0;
mtx.data[i + 12] = 0; mtx.data[i + 12] = 0;
} }
mtx.data[15] = 1.0f; mtx.data[15] = 1.0f;
} }
void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16]) void Matrix44::Set(Matrix44 &mtx, const float mtxArray[16])
{ {
for(int i = 0; i < 16; ++i) { for(int i = 0; i < 16; ++i) {
mtx.data[i] = mtxArray[i]; mtx.data[i] = mtxArray[i];
} }
} }
void Matrix44::Translate(Matrix44 &mtx, const float vec[3]) void Matrix44::Translate(Matrix44 &mtx, const float vec[3])
{ {
LoadIdentity(mtx); LoadIdentity(mtx);
mtx.data[3] = vec[0]; mtx.data[3] = vec[0];
mtx.data[7] = vec[1]; mtx.data[7] = vec[1];
mtx.data[11] = vec[2]; mtx.data[11] = vec[2];
} }
void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result) void Matrix44::Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result)
{ {
MatrixMul(4, a.data, b.data, result.data); MatrixMul(4, a.data, b.data, result.data);
} }

View file

@ -14,74 +14,74 @@ namespace MathUtil
{ {
static const u64 DOUBLE_SIGN = 0x8000000000000000ULL, static const u64 DOUBLE_SIGN = 0x8000000000000000ULL,
DOUBLE_EXP = 0x7FF0000000000000ULL, DOUBLE_EXP = 0x7FF0000000000000ULL,
DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL, DOUBLE_FRAC = 0x000FFFFFFFFFFFFFULL,
DOUBLE_ZERO = 0x0000000000000000ULL; DOUBLE_ZERO = 0x0000000000000000ULL;
static const u32 FLOAT_SIGN = 0x80000000, static const u32 FLOAT_SIGN = 0x80000000,
FLOAT_EXP = 0x7F800000, FLOAT_EXP = 0x7F800000,
FLOAT_FRAC = 0x007FFFFF, FLOAT_FRAC = 0x007FFFFF,
FLOAT_ZERO = 0x00000000; FLOAT_ZERO = 0x00000000;
union IntDouble { union IntDouble {
double d; double d;
u64 i; u64 i;
}; };
union IntFloat { union IntFloat {
float f; float f;
u32 i; u32 i;
}; };
inline bool IsNAN(double d) inline bool IsNAN(double d)
{ {
IntDouble x; x.d = d; IntDouble x; x.d = d;
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) ); ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) );
} }
inline bool IsQNAN(double d) inline bool IsQNAN(double d)
{ {
IntDouble x; x.d = d; IntDouble x; x.d = d;
return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && return ( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) && ((x.i & 0x0007fffffffffffULL) == 0x000000000000000ULL) &&
((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) ); ((x.i & 0x000800000000000ULL) == 0x000800000000000ULL) );
} }
inline bool IsSNAN(double d) inline bool IsSNAN(double d)
{ {
IntDouble x; x.d = d; IntDouble x; x.d = d;
return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) && return( ((x.i & DOUBLE_EXP) == DOUBLE_EXP) &&
((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) && ((x.i & DOUBLE_FRAC) != DOUBLE_ZERO) &&
((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) ); ((x.i & 0x0008000000000000ULL) == DOUBLE_ZERO) );
} }
inline float FlushToZero(float f) inline float FlushToZero(float f)
{ {
IntFloat x; x.f = f; IntFloat x; x.f = f;
if ((x.i & FLOAT_EXP) == 0) if ((x.i & FLOAT_EXP) == 0)
x.i &= FLOAT_SIGN; // turn into signed zero x.i &= FLOAT_SIGN; // turn into signed zero
return x.f; return x.f;
} }
inline double FlushToZeroAsFloat(double d) inline double FlushToZeroAsFloat(double d)
{ {
IntDouble x; x.d = d; IntDouble x; x.d = d;
if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL) if ((x.i & DOUBLE_EXP) < 0x3800000000000000ULL)
x.i &= DOUBLE_SIGN; // turn into signed zero x.i &= DOUBLE_SIGN; // turn into signed zero
return x.d; return x.d;
} }
enum PPCFpClass enum PPCFpClass
{ {
PPC_FPCLASS_QNAN = 0x11, PPC_FPCLASS_QNAN = 0x11,
PPC_FPCLASS_NINF = 0x9, PPC_FPCLASS_NINF = 0x9,
PPC_FPCLASS_NN = 0x8, PPC_FPCLASS_NN = 0x8,
PPC_FPCLASS_ND = 0x18, PPC_FPCLASS_ND = 0x18,
PPC_FPCLASS_NZ = 0x12, PPC_FPCLASS_NZ = 0x12,
PPC_FPCLASS_PZ = 0x2, PPC_FPCLASS_PZ = 0x2,
PPC_FPCLASS_PD = 0x14, PPC_FPCLASS_PD = 0x14,
PPC_FPCLASS_PN = 0x4, PPC_FPCLASS_PN = 0x4,
PPC_FPCLASS_PINF = 0x5, PPC_FPCLASS_PINF = 0x5,
}; };
// Uses PowerPC conventions for the return value, so it can be easily // Uses PowerPC conventions for the return value, so it can be easily
@ -93,42 +93,42 @@ u32 ClassifyFloat(float fvalue);
template<class T> template<class T>
struct Rectangle struct Rectangle
{ {
T left; T left;
T top; T top;
T right; T right;
T bottom; T bottom;
Rectangle() Rectangle()
{ } { }
Rectangle(T theLeft, T theTop, T theRight, T theBottom) Rectangle(T theLeft, T theTop, T theRight, T theBottom)
: left(theLeft), top(theTop), right(theRight), bottom(theBottom) : left(theLeft), top(theTop), right(theRight), bottom(theBottom)
{ } { }
bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; } bool operator==(const Rectangle& r) { return left==r.left && top==r.top && right==r.right && bottom==r.bottom; }
T GetWidth() const { return abs(right - left); } T GetWidth() const { return abs(right - left); }
T GetHeight() const { return abs(bottom - top); } T GetHeight() const { return abs(bottom - top); }
// If the rectangle is in a coordinate system with a lower-left origin, use // If the rectangle is in a coordinate system with a lower-left origin, use
// this Clamp. // this Clamp.
void ClampLL(T x1, T y1, T x2, T y2) void ClampLL(T x1, T y1, T x2, T y2)
{ {
if (left < x1) left = x1; if (left < x1) left = x1;
if (right > x2) right = x2; if (right > x2) right = x2;
if (top > y1) top = y1; if (top > y1) top = y1;
if (bottom < y2) bottom = y2; if (bottom < y2) bottom = y2;
} }
// If the rectangle is in a coordinate system with an upper-left origin, // If the rectangle is in a coordinate system with an upper-left origin,
// use this Clamp. // use this Clamp.
void ClampUL(T x1, T y1, T x2, T y2) void ClampUL(T x1, T y1, T x2, T y2)
{ {
if (left < x1) left = x1; if (left < x1) left = x1;
if (right > x2) right = x2; if (right > x2) right = x2;
if (top < y1) top = y1; if (top < y1) top = y1;
if (bottom > y2) bottom = y2; if (bottom > y2) bottom = y2;
} }
}; };
} // namespace MathUtil } // namespace MathUtil
@ -138,28 +138,28 @@ inline double pow2(double x) {return x * x;}
float MathFloatVectorSum(const std::vector<float>&); float MathFloatVectorSum(const std::vector<float>&);
#define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1)) #define ROUND_UP(x, a) (((x) + (a) - 1) & ~((a) - 1))
#define ROUND_DOWN(x, a) ((x) & ~((a) - 1)) #define ROUND_DOWN(x, a) ((x) & ~((a) - 1))
// Rounds down. 0 -> undefined // Rounds down. 0 -> undefined
inline u64 Log2(u64 val) inline u64 Log2(u64 val)
{ {
#if defined(__GNUC__) #if defined(__GNUC__)
return 63 - __builtin_clzll(val); return 63 - __builtin_clzll(val);
#elif defined(_MSC_VER) && defined(_M_X64) #elif defined(_MSC_VER) && defined(_M_X64)
unsigned long result = -1; unsigned long result = -1;
_BitScanReverse64(&result, val); _BitScanReverse64(&result, val);
return result; return result;
#else #else
u64 result = -1; u64 result = -1;
while (val != 0) while (val != 0)
{ {
val >>= 1; val >>= 1;
++result; ++result;
} }
return result; return result;
#endif #endif
} }
@ -169,32 +169,32 @@ inline u64 Log2(u64 val)
class Matrix33 class Matrix33
{ {
public: public:
static void LoadIdentity(Matrix33 &mtx); static void LoadIdentity(Matrix33 &mtx);
// set mtx to be a rotation matrix around the x axis // set mtx to be a rotation matrix around the x axis
static void RotateX(Matrix33 &mtx, float rad); static void RotateX(Matrix33 &mtx, float rad);
// set mtx to be a rotation matrix around the y axis // set mtx to be a rotation matrix around the y axis
static void RotateY(Matrix33 &mtx, float rad); static void RotateY(Matrix33 &mtx, float rad);
// set result = a x b // set result = a x b
static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result); static void Multiply(const Matrix33 &a, const Matrix33 &b, Matrix33 &result);
static void Multiply(const Matrix33 &a, const float vec[3], float result[3]); static void Multiply(const Matrix33 &a, const float vec[3], float result[3]);
float data[9]; float data[9];
}; };
class Matrix44 class Matrix44
{ {
public: public:
static void LoadIdentity(Matrix44 &mtx); static void LoadIdentity(Matrix44 &mtx);
static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33); static void LoadMatrix33(Matrix44 &mtx, const Matrix33 &m33);
static void Set(Matrix44 &mtx, const float mtxArray[16]); static void Set(Matrix44 &mtx, const float mtxArray[16]);
static void Translate(Matrix44 &mtx, const float vec[3]); static void Translate(Matrix44 &mtx, const float vec[3]);
static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result); static void Multiply(const Matrix44 &a, const Matrix44 &b, Matrix44 &result);
float data[16]; float data[16];
}; };
#endif // _MATH_UTIL_H_ #endif // _MATH_UTIL_H_

View file

@ -27,148 +27,148 @@
void* AllocateExecutableMemory(size_t size, bool low) void* AllocateExecutableMemory(size_t size, bool low)
{ {
#if defined(_WIN32) #if defined(_WIN32)
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE); void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
#else #else
static char *map_hint = 0; static char *map_hint = 0;
#if defined(__x86_64__) && !defined(MAP_32BIT) #if defined(__x86_64__) && !defined(MAP_32BIT)
// This OS has no flag to enforce allocation below the 4 GB boundary, // This OS has no flag to enforce allocation below the 4 GB boundary,
// but if we hint that we want a low address it is very likely we will // but if we hint that we want a low address it is very likely we will
// get one. // get one.
// An older version of this code used MAP_FIXED, but that has the side // An older version of this code used MAP_FIXED, but that has the side
// effect of discarding already mapped pages that happen to be in the // effect of discarding already mapped pages that happen to be in the
// requested virtual memory range (such as the emulated RAM, sometimes). // requested virtual memory range (such as the emulated RAM, sometimes).
if (low && (!map_hint)) if (low && (!map_hint))
map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */ map_hint = (char*)round_page(512*1024*1024); /* 0.5 GB rounded up to the next page */
#endif #endif
void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC, void* ptr = mmap(map_hint, size, PROT_READ | PROT_WRITE | PROT_EXEC,
MAP_ANON | MAP_PRIVATE MAP_ANON | MAP_PRIVATE
#if defined(__x86_64__) && defined(MAP_32BIT) #if defined(__x86_64__) && defined(MAP_32BIT)
| (low ? MAP_32BIT : 0) | (low ? MAP_32BIT : 0)
#endif #endif
, -1, 0); , -1, 0);
#endif /* defined(_WIN32) */ #endif /* defined(_WIN32) */
// printf("Mapped executable memory at %p (size %ld)\n", ptr, // printf("Mapped executable memory at %p (size %ld)\n", ptr,
// (unsigned long)size); // (unsigned long)size);
#if defined(__FreeBSD__) #if defined(__FreeBSD__)
if (ptr == MAP_FAILED) if (ptr == MAP_FAILED)
{ {
ptr = NULL; ptr = NULL;
#else #else
if (ptr == NULL) if (ptr == NULL)
{ {
#endif #endif
PanicAlert("Failed to allocate executable memory"); PanicAlert("Failed to allocate executable memory");
} }
#if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT) #if !defined(_WIN32) && defined(__x86_64__) && !defined(MAP_32BIT)
else else
{ {
if (low) if (low)
{ {
map_hint += size; map_hint += size;
map_hint = (char*)round_page(map_hint); /* round up to the next page */ map_hint = (char*)round_page(map_hint); /* round up to the next page */
// printf("Next map will (hopefully) be at %p\n", map_hint); // printf("Next map will (hopefully) be at %p\n", map_hint);
} }
} }
#endif #endif
#if defined(_M_X64) #if defined(_M_X64)
if ((u64)ptr >= 0x80000000 && low == true) if ((u64)ptr >= 0x80000000 && low == true)
PanicAlert("Executable memory ended up above 2GB!"); PanicAlert("Executable memory ended up above 2GB!");
#endif #endif
return ptr; return ptr;
} }
void* AllocateMemoryPages(size_t size) void* AllocateMemoryPages(size_t size)
{ {
#ifdef _WIN32 #ifdef _WIN32
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE); void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
#else #else
void* ptr = mmap(0, size, PROT_READ | PROT_WRITE, void* ptr = mmap(0, size, PROT_READ | PROT_WRITE,
MAP_ANON | MAP_PRIVATE, -1, 0); MAP_ANON | MAP_PRIVATE, -1, 0);
#endif #endif
// printf("Mapped memory at %p (size %ld)\n", ptr, // printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size); // (unsigned long)size);
if (ptr == NULL) if (ptr == NULL)
PanicAlert("Failed to allocate raw memory"); PanicAlert("Failed to allocate raw memory");
return ptr; return ptr;
} }
void* AllocateAlignedMemory(size_t size,size_t alignment) void* AllocateAlignedMemory(size_t size,size_t alignment)
{ {
#ifdef _WIN32 #ifdef _WIN32
void* ptr = _aligned_malloc(size,alignment); void* ptr = _aligned_malloc(size,alignment);
#else #else
void* ptr = NULL; void* ptr = NULL;
#ifdef ANDROID #ifdef ANDROID
ptr = memalign(alignment, size); ptr = memalign(alignment, size);
#else #else
if (posix_memalign(&ptr, alignment, size) != 0) if (posix_memalign(&ptr, alignment, size) != 0)
ERROR_LOG(MEMMAP, "Failed to allocate aligned memory"); ERROR_LOG(MEMMAP, "Failed to allocate aligned memory");
#endif #endif
#endif #endif
// printf("Mapped memory at %p (size %ld)\n", ptr, // printf("Mapped memory at %p (size %ld)\n", ptr,
// (unsigned long)size); // (unsigned long)size);
if (ptr == NULL) if (ptr == NULL)
PanicAlert("Failed to allocate aligned memory"); PanicAlert("Failed to allocate aligned memory");
return ptr; return ptr;
} }
void FreeMemoryPages(void* ptr, size_t size) void FreeMemoryPages(void* ptr, size_t size)
{ {
if (ptr) if (ptr)
{ {
#ifdef _WIN32 #ifdef _WIN32
if (!VirtualFree(ptr, 0, MEM_RELEASE)) if (!VirtualFree(ptr, 0, MEM_RELEASE))
PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg()); PanicAlert("FreeMemoryPages failed!\n%s", GetLastErrorMsg());
ptr = NULL; // Is this our responsibility? ptr = NULL; // Is this our responsibility?
#else #else
munmap(ptr, size); munmap(ptr, size);
#endif #endif
} }
} }
void FreeAlignedMemory(void* ptr) void FreeAlignedMemory(void* ptr)
{ {
if (ptr) if (ptr)
{ {
#ifdef _WIN32 #ifdef _WIN32
_aligned_free(ptr); _aligned_free(ptr);
#else #else
free(ptr); free(ptr);
#endif #endif
} }
} }
void WriteProtectMemory(void* ptr, size_t size, bool allowExecute) void WriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{ {
#ifdef _WIN32 #ifdef _WIN32
DWORD oldValue; DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue)) if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, &oldValue))
PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg()); PanicAlert("WriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else #else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ); mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
#endif #endif
} }
void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute) void UnWriteProtectMemory(void* ptr, size_t size, bool allowExecute)
{ {
#ifdef _WIN32 #ifdef _WIN32
DWORD oldValue; DWORD oldValue;
if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue)) if (!VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READWRITE, &oldValue))
PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg()); PanicAlert("UnWriteProtectMemory failed!\n%s", GetLastErrorMsg());
#else #else
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ); mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
#endif #endif
} }
@ -176,22 +176,22 @@ std::string MemUsage()
{ {
#ifdef _WIN32 #ifdef _WIN32
#pragma comment(lib, "psapi") #pragma comment(lib, "psapi")
DWORD processID = GetCurrentProcessId(); DWORD processID = GetCurrentProcessId();
HANDLE hProcess; HANDLE hProcess;
PROCESS_MEMORY_COUNTERS pmc; PROCESS_MEMORY_COUNTERS pmc;
std::string Ret; std::string Ret;
// Print information about the memory usage of the process. // Print information about the memory usage of the process.
hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID); hProcess = OpenProcess(PROCESS_QUERY_INFORMATION | PROCESS_VM_READ, FALSE, processID);
if (NULL == hProcess) return "MemUsage Error"; if (NULL == hProcess) return "MemUsage Error";
if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc))) if (GetProcessMemoryInfo(hProcess, &pmc, sizeof(pmc)))
Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str()); Ret = StringFromFormat("%s K", ThousandSeparate(pmc.WorkingSetSize / 1024, 7).c_str());
CloseHandle(hProcess); CloseHandle(hProcess);
return Ret; return Ret;
#else #else
return ""; return "";
#endif #endif
} }

View file

@ -18,20 +18,20 @@
// This function might change the error code. // This function might change the error code.
const char* GetLastErrorMsg() const char* GetLastErrorMsg()
{ {
static const size_t buff_size = 255; static const size_t buff_size = 255;
#ifdef _WIN32 #ifdef _WIN32
static __declspec(thread) char err_str[buff_size] = {}; static __declspec(thread) char err_str[buff_size] = {};
FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(), FormatMessageA(FORMAT_MESSAGE_FROM_SYSTEM, NULL, GetLastError(),
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
err_str, buff_size, NULL); err_str, buff_size, NULL);
#else #else
static __thread char err_str[buff_size] = {}; static __thread char err_str[buff_size] = {};
// Thread safe (XSI-compliant) // Thread safe (XSI-compliant)
strerror_r(errno, err_str, buff_size); strerror_r(errno, err_str, buff_size);
#endif #endif
return err_str; return err_str;
} }

View file

@ -18,90 +18,90 @@ static StringTranslator str_translator = DefaultStringTranslator;
// wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp // wxWidgets is enabled we will use wxMsgAlert() that is defined in Main.cpp
void RegisterMsgAlertHandler(MsgAlertHandler handler) void RegisterMsgAlertHandler(MsgAlertHandler handler)
{ {
msg_handler = handler; msg_handler = handler;
} }
// Select translation function. For wxWidgets use wxStringTranslator in Main.cpp // Select translation function. For wxWidgets use wxStringTranslator in Main.cpp
void RegisterStringTranslator(StringTranslator translator) void RegisterStringTranslator(StringTranslator translator)
{ {
str_translator = translator; str_translator = translator;
} }
// enable/disable the alert handler // enable/disable the alert handler
void SetEnableAlert(bool enable) void SetEnableAlert(bool enable)
{ {
AlertEnabled = enable; AlertEnabled = enable;
} }
// This is the first stop for gui alerts where the log is updated and the // This is the first stop for gui alerts where the log is updated and the
// correct window is shown // correct window is shown
bool MsgAlert(bool yes_no, int Style, const char* format, ...) bool MsgAlert(bool yes_no, int Style, const char* format, ...)
{ {
// Read message and write it to the log // Read message and write it to the log
std::string caption; std::string caption;
char buffer[2048]; char buffer[2048];
static std::string info_caption; static std::string info_caption;
static std::string warn_caption; static std::string warn_caption;
static std::string ques_caption; static std::string ques_caption;
static std::string crit_caption; static std::string crit_caption;
if (!info_caption.length()) if (!info_caption.length())
{ {
info_caption = str_translator(_trans("Information")); info_caption = str_translator(_trans("Information"));
ques_caption = str_translator(_trans("Question")); ques_caption = str_translator(_trans("Question"));
warn_caption = str_translator(_trans("Warning")); warn_caption = str_translator(_trans("Warning"));
crit_caption = str_translator(_trans("Critical")); crit_caption = str_translator(_trans("Critical"));
} }
switch(Style) switch(Style)
{ {
case INFORMATION: case INFORMATION:
caption = info_caption; caption = info_caption;
break; break;
case QUESTION: case QUESTION:
caption = ques_caption; caption = ques_caption;
break; break;
case WARNING: case WARNING:
caption = warn_caption; caption = warn_caption;
break; break;
case CRITICAL: case CRITICAL:
caption = crit_caption; caption = crit_caption;
break; break;
} }
va_list args; va_list args;
va_start(args, format); va_start(args, format);
CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args); CharArrayFromFormatV(buffer, sizeof(buffer)-1, str_translator(format).c_str(), args);
va_end(args); va_end(args);
ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer); ERROR_LOG(MASTER_LOG, "%s: %s", caption.c_str(), buffer);
// Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored // Don't ignore questions, especially AskYesNo, PanicYesNo could be ignored
if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL)) if (msg_handler && (AlertEnabled || Style == QUESTION || Style == CRITICAL))
return msg_handler(caption.c_str(), buffer, yes_no, Style); return msg_handler(caption.c_str(), buffer, yes_no, Style);
return true; return true;
} }
// Default non library dependent panic alert // Default non library dependent panic alert
bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style) bool DefaultMsgHandler(const char* caption, const char* text, bool yes_no, int Style)
{ {
//#ifdef _WIN32 //#ifdef _WIN32
// int STYLE = MB_ICONINFORMATION; // int STYLE = MB_ICONINFORMATION;
// if (Style == QUESTION) STYLE = MB_ICONQUESTION; // if (Style == QUESTION) STYLE = MB_ICONQUESTION;
// if (Style == WARNING) STYLE = MB_ICONWARNING; // if (Style == WARNING) STYLE = MB_ICONWARNING;
// //
// return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK)); // return IDYES == MessageBox(0, UTF8ToTStr(text).c_str(), UTF8ToTStr(caption).c_str(), STYLE | (yes_no ? MB_YESNO : MB_OK));
//#else //#else
printf("%s\n", text); printf("%s\n", text);
return true; return true;
//#endif //#endif
} }
// Default (non) translator // Default (non) translator
std::string DefaultStringTranslator(const char* text) std::string DefaultStringTranslator(const char* text)
{ {
return text; return text;
} }

View file

@ -10,10 +10,10 @@
// Message alerts // Message alerts
enum MSG_TYPE enum MSG_TYPE
{ {
INFORMATION, INFORMATION,
QUESTION, QUESTION,
WARNING, WARNING,
CRITICAL CRITICAL
}; };
typedef bool (*MsgAlertHandler)(const char* caption, const char* text, typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
@ -25,49 +25,49 @@ void RegisterStringTranslator(StringTranslator translator);
extern bool MsgAlert(bool yes_no, int Style, const char* format, ...) extern bool MsgAlert(bool yes_no, int Style, const char* format, ...)
#ifdef __GNUC__ #ifdef __GNUC__
__attribute__((format(printf, 3, 4))) __attribute__((format(printf, 3, 4)))
#endif #endif
; ;
void SetEnableAlert(bool enable); void SetEnableAlert(bool enable);
#ifndef GEKKO #ifndef GEKKO
#ifdef _WIN32 #ifdef _WIN32
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
// Use these macros (that do the same thing) if the message should be translated. // Use these macros (that do the same thing) if the message should be translated.
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__) #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, __VA_ARGS__)
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__) #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, __VA_ARGS__)
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__) #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, __VA_ARGS__)
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__) #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, __VA_ARGS__)
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__) #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, __VA_ARGS__)
#else #else
#define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) #define SuccessAlert(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) #define PanicAlert(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) #define PanicYesNo(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) #define AskYesNo(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
#define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) #define CriticalAlert(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
// Use these macros (that do the same thing) if the message should be translated. // Use these macros (that do the same thing) if the message should be translated.
#define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__) #define SuccessAlertT(format, ...) MsgAlert(false, INFORMATION, format, ##__VA_ARGS__)
#define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__) #define PanicAlertT(format, ...) MsgAlert(false, WARNING, format, ##__VA_ARGS__)
#define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__) #define PanicYesNoT(format, ...) MsgAlert(true, WARNING, format, ##__VA_ARGS__)
#define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__) #define AskYesNoT(format, ...) MsgAlert(true, QUESTION, format, ##__VA_ARGS__)
#define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__) #define CriticalAlertT(format, ...) MsgAlert(false, CRITICAL, format, ##__VA_ARGS__)
#endif #endif
#else #else
// GEKKO // GEKKO
#define SuccessAlert(format, ...) ; #define SuccessAlert(format, ...) ;
#define PanicAlert(format, ...) ; #define PanicAlert(format, ...) ;
#define PanicYesNo(format, ...) ; #define PanicYesNo(format, ...) ;
#define AskYesNo(format, ...) ; #define AskYesNo(format, ...) ;
#define CriticalAlert(format, ...) ; #define CriticalAlert(format, ...) ;
#define SuccessAlertT(format, ...) ; #define SuccessAlertT(format, ...) ;
#define PanicAlertT(format, ...) ; #define PanicAlertT(format, ...) ;
#define PanicYesNoT(format, ...) ; #define PanicYesNoT(format, ...) ;
#define AskYesNoT(format, ...) ; #define AskYesNoT(format, ...) ;
#define CriticalAlertT(format, ...) ; #define CriticalAlertT(format, ...) ;
#endif #endif
#endif // _MSGHANDLER_H_ #endif // _MSGHANDLER_H_

View file

@ -76,9 +76,9 @@
#define EMU_FASTCALL __fastcall #define EMU_FASTCALL __fastcall
inline struct tm* localtime_r(const time_t *clock, struct tm *result) { inline struct tm* localtime_r(const time_t *clock, struct tm *result) {
if (localtime_s(result, clock) == 0) if (localtime_s(result, clock) == 0)
return result; return result;
return NULL; return NULL;
} }
#else #else

View file

@ -2,7 +2,7 @@
#ifndef CONDITION_VARIABLE_H_ #ifndef CONDITION_VARIABLE_H_
#define CONDITION_VARIABLE_H_ #define CONDITION_VARIABLE_H_
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include #ifndef __has_include
@ -47,121 +47,121 @@ namespace std
class condition_variable class condition_variable
{ {
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
typedef CONDITION_VARIABLE native_type; typedef CONDITION_VARIABLE native_type;
#elif defined(_WIN32) #elif defined(_WIN32)
typedef HANDLE native_type; typedef HANDLE native_type;
#else #else
typedef pthread_cond_t native_type; typedef pthread_cond_t native_type;
#endif #endif
public: public:
#ifdef USE_EVENTS #ifdef USE_EVENTS
typedef native_type native_handle_type; typedef native_type native_handle_type;
#else #else
typedef native_type* native_handle_type; typedef native_type* native_handle_type;
#endif #endif
condition_variable() condition_variable()
{ {
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
InitializeConditionVariable(&m_handle); InitializeConditionVariable(&m_handle);
#elif defined(_WIN32) #elif defined(_WIN32)
m_handle = CreateEvent(NULL, false, false, NULL); m_handle = CreateEvent(NULL, false, false, NULL);
#else #else
pthread_cond_init(&m_handle, NULL); pthread_cond_init(&m_handle, NULL);
#endif #endif
} }
~condition_variable() ~condition_variable()
{ {
#if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES) #if defined(_WIN32) && !defined(USE_CONDITION_VARIABLES)
CloseHandle(m_handle); CloseHandle(m_handle);
#elif !defined(_WIN32) #elif !defined(_WIN32)
pthread_cond_destroy(&m_handle); pthread_cond_destroy(&m_handle);
#endif #endif
} }
condition_variable(const condition_variable&) /*= delete*/; condition_variable(const condition_variable&) /*= delete*/;
condition_variable& operator=(const condition_variable&) /*= delete*/; condition_variable& operator=(const condition_variable&) /*= delete*/;
void notify_one() void notify_one()
{ {
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
WakeConditionVariable(&m_handle); WakeConditionVariable(&m_handle);
#elif defined(_WIN32) #elif defined(_WIN32)
SetEvent(m_handle); SetEvent(m_handle);
#else #else
pthread_cond_signal(&m_handle); pthread_cond_signal(&m_handle);
#endif #endif
} }
void notify_all() void notify_all()
{ {
#if defined(_WIN32) && defined(USE_CONDITION_VARIABLES) #if defined(_WIN32) && defined(USE_CONDITION_VARIABLES)
WakeAllConditionVariable(&m_handle); WakeAllConditionVariable(&m_handle);
#elif defined(_WIN32) #elif defined(_WIN32)
// TODO: broken // TODO: broken
SetEvent(m_handle); SetEvent(m_handle);
#else #else
pthread_cond_broadcast(&m_handle); pthread_cond_broadcast(&m_handle);
#endif #endif
} }
void wait(unique_lock<mutex>& lock) void wait(unique_lock<mutex>& lock)
{ {
#ifdef _WIN32 #ifdef _WIN32
#ifdef USE_SRWLOCKS #ifdef USE_SRWLOCKS
SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0); SleepConditionVariableSRW(&m_handle, lock.mutex()->native_handle(), INFINITE, 0);
#elif defined(USE_CONDITION_VARIABLES) #elif defined(USE_CONDITION_VARIABLES)
SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE); SleepConditionVariableCS(&m_handle, lock.mutex()->native_handle(), INFINITE);
#else #else
// TODO: broken, the unlock and wait need to be atomic // TODO: broken, the unlock and wait need to be atomic
lock.unlock(); lock.unlock();
WaitForSingleObject(m_handle, INFINITE); WaitForSingleObject(m_handle, INFINITE);
lock.lock(); lock.lock();
#endif #endif
#else #else
pthread_cond_wait(&m_handle, lock.mutex()->native_handle()); pthread_cond_wait(&m_handle, lock.mutex()->native_handle());
#endif #endif
} }
template <class Predicate> template <class Predicate>
void wait(unique_lock<mutex>& lock, Predicate pred) void wait(unique_lock<mutex>& lock, Predicate pred)
{ {
while (!pred()) while (!pred())
wait(lock); wait(lock);
} }
//template <class Clock, class Duration> //template <class Clock, class Duration>
//cv_status wait_until(unique_lock<mutex>& lock, //cv_status wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time); // const chrono::time_point<Clock, Duration>& abs_time);
//template <class Clock, class Duration, class Predicate> //template <class Clock, class Duration, class Predicate>
// bool wait_until(unique_lock<mutex>& lock, // bool wait_until(unique_lock<mutex>& lock,
// const chrono::time_point<Clock, Duration>& abs_time, // const chrono::time_point<Clock, Duration>& abs_time,
// Predicate pred); // Predicate pred);
//template <class Rep, class Period> //template <class Rep, class Period>
//cv_status wait_for(unique_lock<mutex>& lock, //cv_status wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time); // const chrono::duration<Rep, Period>& rel_time);
//template <class Rep, class Period, class Predicate> //template <class Rep, class Period, class Predicate>
// bool wait_for(unique_lock<mutex>& lock, // bool wait_for(unique_lock<mutex>& lock,
// const chrono::duration<Rep, Period>& rel_time, // const chrono::duration<Rep, Period>& rel_time,
// Predicate pred); // Predicate pred);
native_handle_type native_handle() native_handle_type native_handle()
{ {
#ifdef USE_EVENTS #ifdef USE_EVENTS
return m_handle; return m_handle;
#else #else
return &m_handle; return &m_handle;
#endif #endif
} }
private: private:
native_type m_handle; native_type m_handle;
}; };
} }

View file

@ -2,7 +2,7 @@
#ifndef MUTEX_H_ #ifndef MUTEX_H_
#define MUTEX_H_ #define MUTEX_H_
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include #ifndef __has_include
@ -46,72 +46,72 @@ namespace std
class recursive_mutex class recursive_mutex
{ {
#ifdef _WIN32 #ifdef _WIN32
typedef CRITICAL_SECTION native_type; typedef CRITICAL_SECTION native_type;
#else #else
typedef pthread_mutex_t native_type; typedef pthread_mutex_t native_type;
#endif #endif
public: public:
typedef native_type* native_handle_type; typedef native_type* native_handle_type;
recursive_mutex(const recursive_mutex&) /*= delete*/; recursive_mutex(const recursive_mutex&) /*= delete*/;
recursive_mutex& operator=(const recursive_mutex&) /*= delete*/; recursive_mutex& operator=(const recursive_mutex&) /*= delete*/;
recursive_mutex() recursive_mutex()
{ {
#ifdef _WIN32 #ifdef _WIN32
InitializeCriticalSection(&m_handle); InitializeCriticalSection(&m_handle);
#else #else
pthread_mutexattr_t attr; pthread_mutexattr_t attr;
pthread_mutexattr_init(&attr); pthread_mutexattr_init(&attr);
pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE); pthread_mutexattr_settype(&attr, PTHREAD_MUTEX_RECURSIVE);
pthread_mutex_init(&m_handle, &attr); pthread_mutex_init(&m_handle, &attr);
#endif #endif
} }
~recursive_mutex() ~recursive_mutex()
{ {
#ifdef _WIN32 #ifdef _WIN32
DeleteCriticalSection(&m_handle); DeleteCriticalSection(&m_handle);
#else #else
pthread_mutex_destroy(&m_handle); pthread_mutex_destroy(&m_handle);
#endif #endif
} }
void lock() void lock()
{ {
#ifdef _WIN32 #ifdef _WIN32
EnterCriticalSection(&m_handle); EnterCriticalSection(&m_handle);
#else #else
pthread_mutex_lock(&m_handle); pthread_mutex_lock(&m_handle);
#endif #endif
} }
void unlock() void unlock()
{ {
#ifdef _WIN32 #ifdef _WIN32
LeaveCriticalSection(&m_handle); LeaveCriticalSection(&m_handle);
#else #else
pthread_mutex_unlock(&m_handle); pthread_mutex_unlock(&m_handle);
#endif #endif
} }
bool try_lock() bool try_lock()
{ {
#ifdef _WIN32 #ifdef _WIN32
return (0 != TryEnterCriticalSection(&m_handle)); return (0 != TryEnterCriticalSection(&m_handle));
#else #else
return !pthread_mutex_trylock(&m_handle); return !pthread_mutex_trylock(&m_handle);
#endif #endif
} }
native_handle_type native_handle() native_handle_type native_handle()
{ {
return &m_handle; return &m_handle;
} }
private: private:
native_type m_handle; native_type m_handle;
}; };
#if !defined(_WIN32) || defined(USE_SRWLOCKS) #if !defined(_WIN32) || defined(USE_SRWLOCKS)
@ -119,74 +119,74 @@ private:
class mutex class mutex
{ {
#ifdef _WIN32 #ifdef _WIN32
typedef SRWLOCK native_type; typedef SRWLOCK native_type;
#else #else
typedef pthread_mutex_t native_type; typedef pthread_mutex_t native_type;
#endif #endif
public: public:
typedef native_type* native_handle_type; typedef native_type* native_handle_type;
mutex(const mutex&) /*= delete*/; mutex(const mutex&) /*= delete*/;
mutex& operator=(const mutex&) /*= delete*/; mutex& operator=(const mutex&) /*= delete*/;
mutex() mutex()
{ {
#ifdef _WIN32 #ifdef _WIN32
InitializeSRWLock(&m_handle); InitializeSRWLock(&m_handle);
#else #else
pthread_mutex_init(&m_handle, NULL); pthread_mutex_init(&m_handle, NULL);
#endif #endif
} }
~mutex() ~mutex()
{ {
#ifdef _WIN32 #ifdef _WIN32
#else #else
pthread_mutex_destroy(&m_handle); pthread_mutex_destroy(&m_handle);
#endif #endif
} }
void lock() void lock()
{ {
#ifdef _WIN32 #ifdef _WIN32
AcquireSRWLockExclusive(&m_handle); AcquireSRWLockExclusive(&m_handle);
#else #else
pthread_mutex_lock(&m_handle); pthread_mutex_lock(&m_handle);
#endif #endif
} }
void unlock() void unlock()
{ {
#ifdef _WIN32 #ifdef _WIN32
ReleaseSRWLockExclusive(&m_handle); ReleaseSRWLockExclusive(&m_handle);
#else #else
pthread_mutex_unlock(&m_handle); pthread_mutex_unlock(&m_handle);
#endif #endif
} }
bool try_lock() bool try_lock()
{ {
#ifdef _WIN32 #ifdef _WIN32
// XXX TryAcquireSRWLockExclusive requires Windows 7! // XXX TryAcquireSRWLockExclusive requires Windows 7!
// return (0 != TryAcquireSRWLockExclusive(&m_handle)); // return (0 != TryAcquireSRWLockExclusive(&m_handle));
return false; return false;
#else #else
return !pthread_mutex_trylock(&m_handle); return !pthread_mutex_trylock(&m_handle);
#endif #endif
} }
native_handle_type native_handle() native_handle_type native_handle()
{ {
return &m_handle; return &m_handle;
} }
private: private:
native_type m_handle; native_type m_handle;
}; };
#else #else
typedef recursive_mutex mutex; // just use CriticalSections typedef recursive_mutex mutex; // just use CriticalSections
#endif #endif
@ -198,165 +198,165 @@ template <class Mutex>
class lock_guard class lock_guard
{ {
public: public:
typedef Mutex mutex_type; typedef Mutex mutex_type;
explicit lock_guard(mutex_type& m) explicit lock_guard(mutex_type& m)
: pm(m) : pm(m)
{ {
m.lock(); m.lock();
} }
lock_guard(mutex_type& m, adopt_lock_t) lock_guard(mutex_type& m, adopt_lock_t)
: pm(m) : pm(m)
{ {
} }
~lock_guard() ~lock_guard()
{ {
pm.unlock(); pm.unlock();
} }
lock_guard(lock_guard const&) /*= delete*/; lock_guard(lock_guard const&) /*= delete*/;
lock_guard& operator=(lock_guard const&) /*= delete*/; lock_guard& operator=(lock_guard const&) /*= delete*/;
private: private:
mutex_type& pm; mutex_type& pm;
}; };
template <class Mutex> template <class Mutex>
class unique_lock class unique_lock
{ {
public: public:
typedef Mutex mutex_type; typedef Mutex mutex_type;
unique_lock() unique_lock()
: pm(NULL), owns(false) : pm(NULL), owns(false)
{} {}
/*explicit*/ unique_lock(mutex_type& m) /*explicit*/ unique_lock(mutex_type& m)
: pm(&m), owns(true) : pm(&m), owns(true)
{ {
m.lock(); m.lock();
} }
unique_lock(mutex_type& m, defer_lock_t) unique_lock(mutex_type& m, defer_lock_t)
: pm(&m), owns(false) : pm(&m), owns(false)
{} {}
unique_lock(mutex_type& m, try_to_lock_t) unique_lock(mutex_type& m, try_to_lock_t)
: pm(&m), owns(m.try_lock()) : pm(&m), owns(m.try_lock())
{} {}
unique_lock(mutex_type& m, adopt_lock_t) unique_lock(mutex_type& m, adopt_lock_t)
: pm(&m), owns(true) : pm(&m), owns(true)
{} {}
//template <class Clock, class Duration> //template <class Clock, class Duration>
//unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time); //unique_lock(mutex_type& m, const chrono::time_point<Clock, Duration>& abs_time);
//template <class Rep, class Period> //template <class Rep, class Period>
//unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time); //unique_lock(mutex_type& m, const chrono::duration<Rep, Period>& rel_time);
~unique_lock() ~unique_lock()
{ {
if (owns_lock()) if (owns_lock())
mutex()->unlock(); mutex()->unlock();
} }
#ifdef USE_RVALUE_REFERENCES #ifdef USE_RVALUE_REFERENCES
unique_lock& operator=(const unique_lock&) /*= delete*/; unique_lock& operator=(const unique_lock&) /*= delete*/;
unique_lock& operator=(unique_lock&& other) unique_lock& operator=(unique_lock&& other)
{ {
#else #else
unique_lock& operator=(const unique_lock& u) unique_lock& operator=(const unique_lock& u)
{ {
// ugly const_cast to get around lack of rvalue references // ugly const_cast to get around lack of rvalue references
unique_lock& other = const_cast<unique_lock&>(u); unique_lock& other = const_cast<unique_lock&>(u);
#endif #endif
swap(other); swap(other);
return *this; return *this;
} }
#ifdef USE_RVALUE_REFERENCES #ifdef USE_RVALUE_REFERENCES
unique_lock(const unique_lock&) /*= delete*/; unique_lock(const unique_lock&) /*= delete*/;
unique_lock(unique_lock&& other) unique_lock(unique_lock&& other)
: pm(NULL), owns(false) : pm(NULL), owns(false)
{ {
#else #else
unique_lock(const unique_lock& u) unique_lock(const unique_lock& u)
: pm(NULL), owns(false) : pm(NULL), owns(false)
{ {
// ugly const_cast to get around lack of rvalue references // ugly const_cast to get around lack of rvalue references
unique_lock& other = const_cast<unique_lock&>(u); unique_lock& other = const_cast<unique_lock&>(u);
#endif #endif
swap(other); swap(other);
} }
void lock() void lock()
{ {
mutex()->lock(); mutex()->lock();
owns = true; owns = true;
} }
bool try_lock() bool try_lock()
{ {
owns = mutex()->try_lock(); owns = mutex()->try_lock();
return owns; return owns;
} }
//template <class Rep, class Period> //template <class Rep, class Period>
//bool try_lock_for(const chrono::duration<Rep, Period>& rel_time); //bool try_lock_for(const chrono::duration<Rep, Period>& rel_time);
//template <class Clock, class Duration> //template <class Clock, class Duration>
//bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time); //bool try_lock_until(const chrono::time_point<Clock, Duration>& abs_time);
void unlock() void unlock()
{ {
mutex()->unlock(); mutex()->unlock();
owns = false; owns = false;
} }
void swap(unique_lock& u) void swap(unique_lock& u)
{ {
std::swap(pm, u.pm); std::swap(pm, u.pm);
std::swap(owns, u.owns); std::swap(owns, u.owns);
} }
mutex_type* release() mutex_type* release()
{ {
auto const ret = mutex(); auto const ret = mutex();
pm = NULL; pm = NULL;
owns = false; owns = false;
return ret; return ret;
} }
bool owns_lock() const bool owns_lock() const
{ {
return owns; return owns;
} }
//explicit operator bool () const //explicit operator bool () const
//{ //{
// return owns_lock(); // return owns_lock();
//} //}
mutex_type* mutex() const mutex_type* mutex() const
{ {
return pm; return pm;
} }
private: private:
mutex_type* pm; mutex_type* pm;
bool owns; bool owns;
}; };
template <class Mutex> template <class Mutex>
void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y) void swap(unique_lock<Mutex>& x, unique_lock<Mutex>& y)
{ {
x.swap(y); x.swap(y);
} }
} }

View file

@ -2,7 +2,7 @@
#ifndef STD_THREAD_H_ #ifndef STD_THREAD_H_
#define STD_THREAD_H_ #define STD_THREAD_H_
#define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z)) #define GCC_VER(x,y,z) ((x) * 10000 + (y) * 100 + (z))
#define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__) #define GCC_VERSION GCC_VER(__GNUC__, __GNUC_MINOR__, __GNUC_PATCHLEVEL__)
#ifndef __has_include #ifndef __has_include
@ -77,209 +77,209 @@ namespace std
class thread class thread
{ {
public: public:
typedef THREAD_HANDLE native_handle_type; typedef THREAD_HANDLE native_handle_type;
class id class id
{ {
friend class thread; friend class thread;
public: public:
id() : m_thread(0) {} id() : m_thread(0) {}
id(THREAD_ID _id) : m_thread(_id) {} id(THREAD_ID _id) : m_thread(_id) {}
bool operator==(const id& rhs) const bool operator==(const id& rhs) const
{ {
return m_thread == rhs.m_thread; return m_thread == rhs.m_thread;
} }
bool operator!=(const id& rhs) const bool operator!=(const id& rhs) const
{ {
return !(*this == rhs); return !(*this == rhs);
} }
bool operator<(const id& rhs) const bool operator<(const id& rhs) const
{ {
return m_thread < rhs.m_thread; return m_thread < rhs.m_thread;
} }
private: private:
THREAD_ID m_thread; THREAD_ID m_thread;
}; };
// no variadic template support in msvc // no variadic template support in msvc
//template <typename C, typename... A> //template <typename C, typename... A>
//thread(C&& func, A&&... args); //thread(C&& func, A&&... args);
template <typename C> template <typename C>
thread(C func) thread(C func)
{ {
StartThread(new Func<C>(func)); StartThread(new Func<C>(func));
} }
template <typename C, typename A> template <typename C, typename A>
thread(C func, A arg) thread(C func, A arg)
{ {
StartThread(new FuncArg<C, A>(func, arg)); StartThread(new FuncArg<C, A>(func, arg));
} }
thread() /*= default;*/ {} thread() /*= default;*/ {}
#ifdef USE_RVALUE_REFERENCES #ifdef USE_RVALUE_REFERENCES
thread(const thread&) /*= delete*/; thread(const thread&) /*= delete*/;
thread(thread&& other) thread(thread&& other)
{ {
#else #else
thread(const thread& t) thread(const thread& t)
{ {
// ugly const_cast to get around lack of rvalue references // ugly const_cast to get around lack of rvalue references
thread& other = const_cast<thread&>(t); thread& other = const_cast<thread&>(t);
#endif #endif
swap(other); swap(other);
} }
#ifdef USE_RVALUE_REFERENCES #ifdef USE_RVALUE_REFERENCES
thread& operator=(const thread&) /*= delete*/; thread& operator=(const thread&) /*= delete*/;
thread& operator=(thread&& other) thread& operator=(thread&& other)
{ {
#else #else
thread& operator=(const thread& t) thread& operator=(const thread& t)
{ {
// ugly const_cast to get around lack of rvalue references // ugly const_cast to get around lack of rvalue references
thread& other = const_cast<thread&>(t); thread& other = const_cast<thread&>(t);
#endif #endif
if (joinable()) if (joinable())
detach(); detach();
swap(other); swap(other);
return *this; return *this;
} }
~thread() ~thread()
{ {
if (joinable()) if (joinable())
detach(); detach();
} }
bool joinable() const bool joinable() const
{ {
return m_id != id(); return m_id != id();
} }
id get_id() const id get_id() const
{ {
return m_id; return m_id;
} }
native_handle_type native_handle() native_handle_type native_handle()
{ {
#ifdef _WIN32 #ifdef _WIN32
return m_handle; return m_handle;
#else #else
return m_id.m_thread; return m_id.m_thread;
#endif #endif
} }
void join() void join()
{ {
#ifdef _WIN32 #ifdef _WIN32
WaitForSingleObject(m_handle, INFINITE); WaitForSingleObject(m_handle, INFINITE);
detach(); detach();
#else #else
pthread_join(m_id.m_thread, NULL); pthread_join(m_id.m_thread, NULL);
m_id = id(); m_id = id();
#endif #endif
} }
void detach() void detach()
{ {
#ifdef _WIN32 #ifdef _WIN32
CloseHandle(m_handle); CloseHandle(m_handle);
#else #else
pthread_detach(m_id.m_thread); pthread_detach(m_id.m_thread);
#endif #endif
m_id = id(); m_id = id();
} }
void swap(thread& other) void swap(thread& other)
{ {
std::swap(m_id, other.m_id); std::swap(m_id, other.m_id);
#ifdef _WIN32 #ifdef _WIN32
std::swap(m_handle, other.m_handle); std::swap(m_handle, other.m_handle);
#endif #endif
} }
static unsigned hardware_concurrency() static unsigned hardware_concurrency()
{ {
#ifdef _WIN32 #ifdef _WIN32
SYSTEM_INFO sysinfo; SYSTEM_INFO sysinfo;
GetSystemInfo(&sysinfo); GetSystemInfo(&sysinfo);
return static_cast<unsigned>(sysinfo.dwNumberOfProcessors); return static_cast<unsigned>(sysinfo.dwNumberOfProcessors);
#else #else
return 0; return 0;
#endif #endif
} }
private: private:
id m_id; id m_id;
#ifdef _WIN32 #ifdef _WIN32
native_handle_type m_handle; native_handle_type m_handle;
#endif #endif
template <typename F> template <typename F>
void StartThread(F* param) void StartThread(F* param)
{ {
#ifdef USE_BEGINTHREADEX #ifdef USE_BEGINTHREADEX
m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread); m_handle = (HANDLE)_beginthreadex(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
#elif defined(_WIN32) #elif defined(_WIN32)
m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread); m_handle = CreateThread(NULL, 0, &RunAndDelete<F>, param, 0, &m_id.m_thread);
#else #else
pthread_attr_t attr; pthread_attr_t attr;
pthread_attr_init(&attr); pthread_attr_init(&attr);
pthread_attr_setstacksize(&attr, 1024 * 1024); pthread_attr_setstacksize(&attr, 1024 * 1024);
if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param)) if (pthread_create(&m_id.m_thread, &attr, &RunAndDelete<F>, param))
m_id = id(); m_id = id();
#endif #endif
} }
template <typename C> template <typename C>
class Func class Func
{ {
public: public:
Func(C _func) : func(_func) {} Func(C _func) : func(_func) {}
void Run() { func(); } void Run() { func(); }
private: private:
C const func; C const func;
}; };
template <typename C, typename A> template <typename C, typename A>
class FuncArg class FuncArg
{ {
public: public:
FuncArg(C _func, A _arg) : func(_func), arg(_arg) {} FuncArg(C _func, A _arg) : func(_func), arg(_arg) {}
void Run() { func(arg); } void Run() { func(arg); }
private: private:
C const func; C const func;
A arg; A arg;
}; };
template <typename F> template <typename F>
static THREAD_RETURN RunAndDelete(void* param) static THREAD_RETURN RunAndDelete(void* param)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init]; NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];
#endif #endif
static_cast<F*>(param)->Run(); static_cast<F*>(param)->Run();
delete static_cast<F*>(param); delete static_cast<F*>(param);
#ifdef __APPLE__ #ifdef __APPLE__
[pool release]; [pool release];
#endif #endif
return 0; return 0;
} }
}; };
namespace this_thread namespace this_thread
@ -288,24 +288,24 @@ namespace this_thread
inline void yield() inline void yield()
{ {
#ifdef _WIN32 #ifdef _WIN32
SwitchToThread(); SwitchToThread();
#else #else
sleep(0); sleep(0);
#endif #endif
} }
inline thread::id get_id() inline thread::id get_id()
{ {
#ifdef _WIN32 #ifdef _WIN32
return GetCurrentThreadId(); return GetCurrentThreadId();
#else #else
return pthread_self(); return pthread_self();
#endif #endif
} }
} // namespace this_thread } // namespace this_thread
} // namespace std } // namespace std
#undef USE_RVALUE_REFERENCES #undef USE_RVALUE_REFERENCES
#undef USE_BEGINTHREADEX #undef USE_BEGINTHREADEX

View file

@ -11,131 +11,131 @@
#include "string_util.h" #include "string_util.h"
#ifdef _WIN32 #ifdef _WIN32
#include <Windows.h> #include <Windows.h>
#else #else
#include <iconv.h> #include <iconv.h>
#include <errno.h> #include <errno.h>
#endif #endif
// faster than sscanf // faster than sscanf
bool AsciiToHex(const char* _szValue, u32& result) bool AsciiToHex(const char* _szValue, u32& result)
{ {
char *endptr = NULL; char *endptr = NULL;
const u32 value = strtoul(_szValue, &endptr, 16); const u32 value = strtoul(_szValue, &endptr, 16);
if (!endptr || *endptr) if (!endptr || *endptr)
return false; return false;
result = value; result = value;
return true; return true;
} }
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args) bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
{ {
int writtenCount; int writtenCount;
#ifdef _WIN32 #ifdef _WIN32
// You would think *printf are simple, right? Iterate on each character, // You would think *printf are simple, right? Iterate on each character,
// if it's a format specifier handle it properly, etc. // if it's a format specifier handle it properly, etc.
// //
// Nooooo. Not according to the C standard. // Nooooo. Not according to the C standard.
// //
// According to the C99 standard (7.19.6.1 "The fprintf function") // According to the C99 standard (7.19.6.1 "The fprintf function")
// The format shall be a multibyte character sequence // The format shall be a multibyte character sequence
// //
// Because some character encodings might have '%' signs in the middle of // Because some character encodings might have '%' signs in the middle of
// a multibyte sequence (SJIS for example only specifies that the first // a multibyte sequence (SJIS for example only specifies that the first
// byte of a 2 byte sequence is "high", the second byte can be anything), // byte of a 2 byte sequence is "high", the second byte can be anything),
// printf functions have to decode the multibyte sequences and try their // printf functions have to decode the multibyte sequences and try their
// best to not screw up. // best to not screw up.
// //
// Unfortunately, on Windows, the locale for most languages is not UTF-8 // Unfortunately, on Windows, the locale for most languages is not UTF-8
// as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the // as we would need. Notably, for zh_TW, Windows chooses EUC-CN as the
// locale, and completely fails when trying to decode UTF-8 as EUC-CN. // locale, and completely fails when trying to decode UTF-8 as EUC-CN.
// //
// On the other hand, the fix is simple: because we use UTF-8, no such // On the other hand, the fix is simple: because we use UTF-8, no such
// multibyte handling is required as we can simply assume that no '%' char // multibyte handling is required as we can simply assume that no '%' char
// will be present in the middle of a multibyte sequence. // will be present in the middle of a multibyte sequence.
// //
// This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l. // This is why we lookup an ANSI (cp1252) locale here and use _vsnprintf_l.
static locale_t c_locale = NULL; static locale_t c_locale = NULL;
if (!c_locale) if (!c_locale)
c_locale = _create_locale(LC_ALL, ".1252"); c_locale = _create_locale(LC_ALL, ".1252");
writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args); writtenCount = _vsnprintf_l(out, outsize, format, c_locale, args);
#else #else
writtenCount = vsnprintf(out, outsize, format, args); writtenCount = vsnprintf(out, outsize, format, args);
#endif #endif
if (writtenCount > 0 && writtenCount < outsize) if (writtenCount > 0 && writtenCount < outsize)
{ {
out[writtenCount] = '\0'; out[writtenCount] = '\0';
return true; return true;
} }
else else
{ {
out[outsize - 1] = '\0'; out[outsize - 1] = '\0';
return false; return false;
} }
} }
std::string StringFromFormat(const char* format, ...) std::string StringFromFormat(const char* format, ...)
{ {
va_list args; va_list args;
char *buf = NULL; char *buf = NULL;
#ifdef _WIN32 #ifdef _WIN32
int required = 0; int required = 0;
va_start(args, format); va_start(args, format);
required = _vscprintf(format, args); required = _vscprintf(format, args);
buf = new char[required + 1]; buf = new char[required + 1];
CharArrayFromFormatV(buf, required + 1, format, args); CharArrayFromFormatV(buf, required + 1, format, args);
va_end(args); va_end(args);
std::string temp = buf; std::string temp = buf;
delete[] buf; delete[] buf;
#else #else
va_start(args, format); va_start(args, format);
if (vasprintf(&buf, format, args) < 0) if (vasprintf(&buf, format, args) < 0)
ERROR_LOG(COMMON, "Unable to allocate memory for string"); ERROR_LOG(COMMON, "Unable to allocate memory for string");
va_end(args); va_end(args);
std::string temp = buf; std::string temp = buf;
free(buf); free(buf);
#endif #endif
return temp; return temp;
} }
// For Debugging. Read out an u8 array. // For Debugging. Read out an u8 array.
std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces) std::string ArrayToString(const u8 *data, u32 size, int line_len, bool spaces)
{ {
std::ostringstream oss; std::ostringstream oss;
oss << std::setfill('0') << std::hex; oss << std::setfill('0') << std::hex;
for (int line = 0; size; ++data, --size) for (int line = 0; size; ++data, --size)
{ {
oss << std::setw(2) << (int)*data; oss << std::setw(2) << (int)*data;
if (line_len == ++line) if (line_len == ++line)
{ {
oss << '\n'; oss << '\n';
line = 0; line = 0;
} }
else if (spaces) else if (spaces)
oss << ' '; oss << ' ';
} }
return oss.str(); return oss.str();
} }
// Turns " hej " into "hej". Also handles tabs. // Turns " hej " into "hej". Also handles tabs.
std::string StripSpaces(const std::string &str) std::string StripSpaces(const std::string &str)
{ {
const size_t s = str.find_first_not_of(" \t\r\n"); const size_t s = str.find_first_not_of(" \t\r\n");
if (str.npos != s) if (str.npos != s)
return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1); return str.substr(s, str.find_last_not_of(" \t\r\n") - s + 1);
else else
return ""; return "";
} }
// "\"hello\"" is turned to "hello" // "\"hello\"" is turned to "hello"
@ -143,137 +143,137 @@ std::string StripSpaces(const std::string &str)
// ends, as done by StripSpaces above, for example. // ends, as done by StripSpaces above, for example.
std::string StripQuotes(const std::string& s) std::string StripQuotes(const std::string& s)
{ {
if (s.size() && '\"' == s[0] && '\"' == *s.rbegin()) if (s.size() && '\"' == s[0] && '\"' == *s.rbegin())
return s.substr(1, s.size() - 2); return s.substr(1, s.size() - 2);
else else
return s; return s;
} }
bool TryParse(const std::string &str, u32 *const output) bool TryParse(const std::string &str, u32 *const output)
{ {
char *endptr = NULL; char *endptr = NULL;
// Reset errno to a value other than ERANGE // Reset errno to a value other than ERANGE
errno = 0; errno = 0;
unsigned long value = strtoul(str.c_str(), &endptr, 0); unsigned long value = strtoul(str.c_str(), &endptr, 0);
if (!endptr || *endptr) if (!endptr || *endptr)
return false; return false;
if (errno == ERANGE) if (errno == ERANGE)
return false; return false;
#if ULONG_MAX > UINT_MAX #if ULONG_MAX > UINT_MAX
if (value >= 0x100000000ull if (value >= 0x100000000ull
&& value <= 0xFFFFFFFF00000000ull) && value <= 0xFFFFFFFF00000000ull)
return false; return false;
#endif #endif
*output = static_cast<u32>(value); *output = static_cast<u32>(value);
return true; return true;
} }
bool TryParse(const std::string &str, bool *const output) bool TryParse(const std::string &str, bool *const output)
{ {
if ("1" == str || !strcasecmp("true", str.c_str())) if ("1" == str || !strcasecmp("true", str.c_str()))
*output = true; *output = true;
else if ("0" == str || !strcasecmp("false", str.c_str())) else if ("0" == str || !strcasecmp("false", str.c_str()))
*output = false; *output = false;
else else
return false; return false;
return true; return true;
} }
std::string StringFromInt(int value) std::string StringFromInt(int value)
{ {
char temp[16]; char temp[16];
sprintf(temp, "%i", value); sprintf(temp, "%i", value);
return temp; return temp;
} }
std::string StringFromBool(bool value) std::string StringFromBool(bool value)
{ {
return value ? "True" : "False"; return value ? "True" : "False";
} }
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension) bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
{ {
if (full_path.empty()) if (full_path.empty())
return false; return false;
size_t dir_end = full_path.find_last_of("/" size_t dir_end = full_path.find_last_of("/"
// windows needs the : included for something like just "C:" to be considered a directory // windows needs the : included for something like just "C:" to be considered a directory
#ifdef _WIN32 #ifdef _WIN32
":" ":"
#endif #endif
); );
if (std::string::npos == dir_end) if (std::string::npos == dir_end)
dir_end = 0; dir_end = 0;
else else
dir_end += 1; dir_end += 1;
size_t fname_end = full_path.rfind('.'); size_t fname_end = full_path.rfind('.');
if (fname_end < dir_end || std::string::npos == fname_end) if (fname_end < dir_end || std::string::npos == fname_end)
fname_end = full_path.size(); fname_end = full_path.size();
if (_pPath) if (_pPath)
*_pPath = full_path.substr(0, dir_end); *_pPath = full_path.substr(0, dir_end);
if (_pFilename) if (_pFilename)
*_pFilename = full_path.substr(dir_end, fname_end - dir_end); *_pFilename = full_path.substr(dir_end, fname_end - dir_end);
if (_pExtension) if (_pExtension)
*_pExtension = full_path.substr(fname_end); *_pExtension = full_path.substr(fname_end);
return true; return true;
} }
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename) void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
{ {
_CompleteFilename = _Path; _CompleteFilename = _Path;
// check for seperator // check for seperator
if (DIR_SEP_CHR != *_CompleteFilename.rbegin()) if (DIR_SEP_CHR != *_CompleteFilename.rbegin())
_CompleteFilename += DIR_SEP_CHR; _CompleteFilename += DIR_SEP_CHR;
// add the filename // add the filename
_CompleteFilename += _Filename; _CompleteFilename += _Filename;
} }
void SplitString(const std::string& str, const char delim, std::vector<std::string>& output) void SplitString(const std::string& str, const char delim, std::vector<std::string>& output)
{ {
std::istringstream iss(str); std::istringstream iss(str);
output.resize(1); output.resize(1);
while (std::getline(iss, *output.rbegin(), delim)) while (std::getline(iss, *output.rbegin(), delim))
output.push_back(""); output.push_back("");
output.pop_back(); output.pop_back();
} }
std::string TabsToSpaces(int tab_size, const std::string &in) std::string TabsToSpaces(int tab_size, const std::string &in)
{ {
const std::string spaces(tab_size, ' '); const std::string spaces(tab_size, ' ');
std::string out(in); std::string out(in);
size_t i = 0; size_t i = 0;
while (out.npos != (i = out.find('\t'))) while (out.npos != (i = out.find('\t')))
out.replace(i, 1, spaces); out.replace(i, 1, spaces);
return out; return out;
} }
std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest) std::string ReplaceAll(std::string result, const std::string& src, const std::string& dest)
{ {
while(1) while(1)
{ {
size_t pos = result.find(src); size_t pos = result.find(src);
if (pos == std::string::npos) break; if (pos == std::string::npos) break;
result.replace(pos, src.size(), dest); result.replace(pos, src.size(), dest);
} }
return result; return result;
} }
// UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759 // UriDecode and UriEncode are from http://www.codeguru.com/cpp/cpp/string/conversions/print.php/c12759
@ -287,161 +287,161 @@ std::string ReplaceAll(std::string result, const std::string& src, const std::st
const char HEX2DEC[256] = const char HEX2DEC[256] =
{ {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 0 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 1 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 2 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16, /* 3 */ 0, 1, 2, 3, 4, 5, 6, 7, 8, 9,16,16, 16,16,16,16,
/* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, /* 4 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
/* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 5 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16, /* 6 */ 16,10,11,12, 13,14,15,16, 16,16,16,16, 16,16,16,16,
/* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 7 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 8 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* 9 */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* A */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* B */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* C */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* D */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16, /* E */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16,
/* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16 /* F */ 16,16,16,16, 16,16,16,16, 16,16,16,16, 16,16,16,16
}; };
std::string UriDecode(const std::string & sSrc) std::string UriDecode(const std::string & sSrc)
{ {
// Note from RFC1630: "Sequences which start with a percent sign // Note from RFC1630: "Sequences which start with a percent sign
// but are not followed by two hexadecimal characters (0-9, A-F) are reserved // but are not followed by two hexadecimal characters (0-9, A-F) are reserved
// for future extension" // for future extension"
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const size_t SRC_LEN = sSrc.length(); const size_t SRC_LEN = sSrc.length();
const unsigned char * const SRC_END = pSrc + SRC_LEN; const unsigned char * const SRC_END = pSrc + SRC_LEN;
const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%' const unsigned char * const SRC_LAST_DEC = SRC_END - 2; // last decodable '%'
char * const pStart = new char[SRC_LEN]; char * const pStart = new char[SRC_LEN];
char * pEnd = pStart; char * pEnd = pStart;
while (pSrc < SRC_LAST_DEC) while (pSrc < SRC_LAST_DEC)
{ {
if (*pSrc == '%') if (*pSrc == '%')
{ {
char dec1, dec2; char dec1, dec2;
if (16 != (dec1 = HEX2DEC[*(pSrc + 1)]) if (16 != (dec1 = HEX2DEC[*(pSrc + 1)])
&& 16 != (dec2 = HEX2DEC[*(pSrc + 2)])) && 16 != (dec2 = HEX2DEC[*(pSrc + 2)]))
{ {
*pEnd++ = (dec1 << 4) + dec2; *pEnd++ = (dec1 << 4) + dec2;
pSrc += 3; pSrc += 3;
continue; continue;
} }
} }
*pEnd++ = *pSrc++; *pEnd++ = *pSrc++;
} }
// the last 2- chars // the last 2- chars
while (pSrc < SRC_END) while (pSrc < SRC_END)
*pEnd++ = *pSrc++; *pEnd++ = *pSrc++;
std::string sResult(pStart, pEnd); std::string sResult(pStart, pEnd);
delete [] pStart; delete [] pStart;
return sResult; return sResult;
} }
// Only alphanum is safe. // Only alphanum is safe.
const char SAFE[256] = const char SAFE[256] =
{ {
/* 0 1 2 3 4 5 6 7 8 9 A B C D E F */ /* 0 1 2 3 4 5 6 7 8 9 A B C D E F */
/* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 0 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 1 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 2 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0, /* 3 */ 1,1,1,1, 1,1,1,1, 1,1,0,0, 0,0,0,0,
/* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* 4 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
/* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, /* 5 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
/* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1, /* 6 */ 0,1,1,1, 1,1,1,1, 1,1,1,1, 1,1,1,1,
/* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0, /* 7 */ 1,1,1,1, 1,1,1,1, 1,1,1,0, 0,0,0,0,
/* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 8 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* 9 */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* A */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* B */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* C */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* D */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0, /* E */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0,
/* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0 /* F */ 0,0,0,0, 0,0,0,0, 0,0,0,0, 0,0,0,0
}; };
std::string UriEncode(const std::string & sSrc) std::string UriEncode(const std::string & sSrc)
{ {
const char DEC2HEX[16 + 1] = "0123456789ABCDEF"; const char DEC2HEX[16 + 1] = "0123456789ABCDEF";
const unsigned char * pSrc = (const unsigned char *)sSrc.c_str(); const unsigned char * pSrc = (const unsigned char *)sSrc.c_str();
const size_t SRC_LEN = sSrc.length(); const size_t SRC_LEN = sSrc.length();
unsigned char * const pStart = new unsigned char[SRC_LEN * 3]; unsigned char * const pStart = new unsigned char[SRC_LEN * 3];
unsigned char * pEnd = pStart; unsigned char * pEnd = pStart;
const unsigned char * const SRC_END = pSrc + SRC_LEN; const unsigned char * const SRC_END = pSrc + SRC_LEN;
for (; pSrc < SRC_END; ++pSrc) for (; pSrc < SRC_END; ++pSrc)
{ {
if (SAFE[*pSrc]) if (SAFE[*pSrc])
*pEnd++ = *pSrc; *pEnd++ = *pSrc;
else else
{ {
// escape this char // escape this char
*pEnd++ = '%'; *pEnd++ = '%';
*pEnd++ = DEC2HEX[*pSrc >> 4]; *pEnd++ = DEC2HEX[*pSrc >> 4];
*pEnd++ = DEC2HEX[*pSrc & 0x0F]; *pEnd++ = DEC2HEX[*pSrc & 0x0F];
} }
} }
std::string sResult((char *)pStart, (char *)pEnd); std::string sResult((char *)pStart, (char *)pEnd);
delete [] pStart; delete [] pStart;
return sResult; return sResult;
} }
#ifdef _WIN32 #ifdef _WIN32
std::string UTF16ToUTF8(const std::wstring& input) std::string UTF16ToUTF8(const std::wstring& input)
{ {
auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr); auto const size = WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), nullptr, 0, nullptr, nullptr);
std::string output; std::string output;
output.resize(size); output.resize(size);
if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr)) if (size == 0 || size != WideCharToMultiByte(CP_UTF8, 0, input.data(), input.size(), &output[0], output.size(), nullptr, nullptr))
output.clear(); output.clear();
return output; return output;
} }
std::wstring CPToUTF16(u32 code_page, const std::string& input) std::wstring CPToUTF16(u32 code_page, const std::string& input)
{ {
auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0); auto const size = MultiByteToWideChar(code_page, 0, input.data(), input.size(), nullptr, 0);
std::wstring output; std::wstring output;
output.resize(size); output.resize(size);
if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size())) if (size == 0 || size != MultiByteToWideChar(code_page, 0, input.data(), input.size(), &output[0], output.size()))
output.clear(); output.clear();
return output; return output;
} }
std::wstring UTF8ToUTF16(const std::string& input) std::wstring UTF8ToUTF16(const std::string& input)
{ {
return CPToUTF16(CP_UTF8, input); return CPToUTF16(CP_UTF8, input);
} }
std::string SHIFTJISToUTF8(const std::string& input) std::string SHIFTJISToUTF8(const std::string& input)
{ {
return UTF16ToUTF8(CPToUTF16(932, input)); return UTF16ToUTF8(CPToUTF16(932, input));
} }
std::string CP1252ToUTF8(const std::string& input) std::string CP1252ToUTF8(const std::string& input)
{ {
return UTF16ToUTF8(CPToUTF16(1252, input)); return UTF16ToUTF8(CPToUTF16(1252, input));
} }
#else #else
@ -449,83 +449,83 @@ std::string CP1252ToUTF8(const std::string& input)
template <typename T> template <typename T>
std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input) std::string CodeToUTF8(const char* fromcode, const std::basic_string<T>& input)
{ {
std::string result; std::string result;
iconv_t const conv_desc = iconv_open("UTF-8", fromcode); iconv_t const conv_desc = iconv_open("UTF-8", fromcode);
if ((iconv_t)-1 == conv_desc) if ((iconv_t)-1 == conv_desc)
{ {
ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno)); ERROR_LOG(COMMON, "Iconv initialization failure [%s]: %s", fromcode, strerror(errno));
} }
else else
{ {
size_t const in_bytes = sizeof(T) * input.size(); size_t const in_bytes = sizeof(T) * input.size();
size_t const out_buffer_size = 4 * in_bytes; size_t const out_buffer_size = 4 * in_bytes;
std::string out_buffer; std::string out_buffer;
out_buffer.resize(out_buffer_size); out_buffer.resize(out_buffer_size);
auto src_buffer = &input[0]; auto src_buffer = &input[0];
size_t src_bytes = in_bytes; size_t src_bytes = in_bytes;
auto dst_buffer = &out_buffer[0]; auto dst_buffer = &out_buffer[0];
size_t dst_bytes = out_buffer.size(); size_t dst_bytes = out_buffer.size();
while (src_bytes != 0) while (src_bytes != 0)
{ {
size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes, size_t const iconv_result = iconv(conv_desc, (char**)(&src_buffer), &src_bytes,
&dst_buffer, &dst_bytes); &dst_buffer, &dst_bytes);
if ((size_t)-1 == iconv_result) if ((size_t)-1 == iconv_result)
{ {
if (EILSEQ == errno || EINVAL == errno) if (EILSEQ == errno || EINVAL == errno)
{ {
// Try to skip the bad character // Try to skip the bad character
if (src_bytes != 0) if (src_bytes != 0)
{ {
--src_bytes; --src_bytes;
++src_buffer; ++src_buffer;
} }
} }
else else
{ {
ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno)); ERROR_LOG(COMMON, "iconv failure [%s]: %s", fromcode, strerror(errno));
break; break;
} }
} }
} }
out_buffer.resize(out_buffer_size - dst_bytes); out_buffer.resize(out_buffer_size - dst_bytes);
out_buffer.swap(result); out_buffer.swap(result);
iconv_close(conv_desc); iconv_close(conv_desc);
} }
return result; return result;
} }
std::string CP1252ToUTF8(const std::string& input) std::string CP1252ToUTF8(const std::string& input)
{ {
//return CodeToUTF8("CP1252//TRANSLIT", input); //return CodeToUTF8("CP1252//TRANSLIT", input);
//return CodeToUTF8("CP1252//IGNORE", input); //return CodeToUTF8("CP1252//IGNORE", input);
return CodeToUTF8("CP1252", input); return CodeToUTF8("CP1252", input);
} }
std::string SHIFTJISToUTF8(const std::string& input) std::string SHIFTJISToUTF8(const std::string& input)
{ {
//return CodeToUTF8("CP932", input); //return CodeToUTF8("CP932", input);
return CodeToUTF8("SJIS", input); return CodeToUTF8("SJIS", input);
} }
std::string UTF16ToUTF8(const std::wstring& input) std::string UTF16ToUTF8(const std::wstring& input)
{ {
std::string result = std::string result =
// CodeToUTF8("UCS-2", input); // CodeToUTF8("UCS-2", input);
// CodeToUTF8("UCS-2LE", input); // CodeToUTF8("UCS-2LE", input);
// CodeToUTF8("UTF-16", input); // CodeToUTF8("UTF-16", input);
CodeToUTF8("UTF-16LE", input); CodeToUTF8("UTF-16LE", input);
// TODO: why is this needed? // TODO: why is this needed?
result.erase(std::remove(result.begin(), result.end(), 0x00), result.end()); result.erase(std::remove(result.begin(), result.end(), 0x00), result.end());
return result; return result;
} }
#endif #endif

View file

@ -21,10 +21,10 @@ bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list ar
template<size_t Count> template<size_t Count>
inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...) inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
{ {
va_list args; va_list args;
va_start(args, format); va_start(args, format);
CharArrayFromFormatV(out, Count, format, args); CharArrayFromFormatV(out, Count, format, args);
va_end(args); va_end(args);
} }
// Good // Good
@ -37,15 +37,15 @@ std::string StripQuotes(const std::string &s);
template <typename I> template <typename I>
std::string ThousandSeparate(I value, int spaces = 0) std::string ThousandSeparate(I value, int spaces = 0)
{ {
std::ostringstream oss; std::ostringstream oss;
// std::locale("") seems to be broken on many platforms // std::locale("") seems to be broken on many platforms
#if defined _WIN32 || (defined __linux__ && !defined __clang__) #if defined _WIN32 || (defined __linux__ && !defined __clang__)
oss.imbue(std::locale("")); oss.imbue(std::locale(""));
#endif #endif
oss << std::setw(spaces) << value; oss << std::setw(spaces) << value;
return oss.str(); return oss.str();
} }
std::string StringFromInt(int value); std::string StringFromInt(int value);
@ -57,16 +57,16 @@ bool TryParse(const std::string &str, u32 *output);
template <typename N> template <typename N>
static bool TryParse(const std::string &str, N *const output) static bool TryParse(const std::string &str, N *const output)
{ {
std::istringstream iss(str); std::istringstream iss(str);
N tmp = 0; N tmp = 0;
if (iss >> tmp) if (iss >> tmp)
{ {
*output = tmp; *output = tmp;
return true; return true;
} }
else else
return false; return false;
} }
// TODO: kill this // TODO: kill this

View file

@ -63,426 +63,426 @@
template <typename T, typename F> template <typename T, typename F>
struct swap_struct_t { struct swap_struct_t {
typedef swap_struct_t<T, F> swapped_t; typedef swap_struct_t<T, F> swapped_t;
protected: protected:
T value; T value;
static T swap(T v) { static T swap(T v) {
return F::swap(v); return F::swap(v);
} }
public: public:
T const swap() const { T const swap() const {
return swap(value); return swap(value);
} }
swap_struct_t() : value((T)0) {} swap_struct_t() : value((T)0) {}
swap_struct_t(const T &v): value(swap(v)) {} swap_struct_t(const T &v): value(swap(v)) {}
template <typename S> template <typename S>
swapped_t& operator=(const S &source) { swapped_t& operator=(const S &source) {
value = swap((T)source); value = swap((T)source);
return *this; return *this;
} }
operator long() const { return (long)swap(); } operator long() const { return (long)swap(); }
operator s8() const { return (s8)swap(); } operator s8() const { return (s8)swap(); }
operator u8() const { return (u8)swap(); } operator u8() const { return (u8)swap(); }
operator s16() const { return (s16)swap(); } operator s16() const { return (s16)swap(); }
operator u16() const { return (u16)swap(); } operator u16() const { return (u16)swap(); }
operator s32() const { return (s32)swap(); } operator s32() const { return (s32)swap(); }
operator u32() const { return (u32)swap(); } operator u32() const { return (u32)swap(); }
operator s64() const { return (s64)swap(); } operator s64() const { return (s64)swap(); }
operator u64() const { return (u64)swap(); } operator u64() const { return (u64)swap(); }
operator float() const { return (float)swap(); } operator float() const { return (float)swap(); }
operator double() const { return (double)swap(); } operator double() const { return (double)swap(); }
// +v // +v
swapped_t operator +() const { swapped_t operator +() const {
return +swap(); return +swap();
} }
// -v // -v
swapped_t operator -() const { swapped_t operator -() const {
return -swap(); return -swap();
} }
// v / 5 // v / 5
swapped_t operator/(const swapped_t &i) const { swapped_t operator/(const swapped_t &i) const {
return swap() / i.swap(); return swap() / i.swap();
} }
template <typename S> template <typename S>
swapped_t operator/(const S &i) const { swapped_t operator/(const S &i) const {
return swap() / i; return swap() / i;
} }
// v * 5 // v * 5
swapped_t operator*(const swapped_t &i) const { swapped_t operator*(const swapped_t &i) const {
return swap() * i.swap(); return swap() * i.swap();
} }
template <typename S> template <typename S>
swapped_t operator*(const S &i) const { swapped_t operator*(const S &i) const {
return swap() * i; return swap() * i;
} }
// v + 5 // v + 5
swapped_t operator+(const swapped_t &i) const { swapped_t operator+(const swapped_t &i) const {
return swap() + i.swap(); return swap() + i.swap();
} }
template <typename S> template <typename S>
swapped_t operator+(const S &i) const { swapped_t operator+(const S &i) const {
return swap() + (T)i; return swap() + (T)i;
} }
// v - 5 // v - 5
swapped_t operator-(const swapped_t &i) const { swapped_t operator-(const swapped_t &i) const {
return swap() - i.swap(); return swap() - i.swap();
} }
template <typename S> template <typename S>
swapped_t operator-(const S &i) const { swapped_t operator-(const S &i) const {
return swap() - (T)i; return swap() - (T)i;
} }
// v += 5 // v += 5
swapped_t& operator+=(const swapped_t &i) { swapped_t& operator+=(const swapped_t &i) {
value = swap(swap() + i.swap()); value = swap(swap() + i.swap());
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t& operator+=(const S &i) { swapped_t& operator+=(const S &i) {
value = swap(swap() + (T)i); value = swap(swap() + (T)i);
return *this; return *this;
} }
// v -= 5 // v -= 5
swapped_t& operator-=(const swapped_t &i) { swapped_t& operator-=(const swapped_t &i) {
value = swap(swap() - i.swap()); value = swap(swap() - i.swap());
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t& operator-=(const S &i) { swapped_t& operator-=(const S &i) {
value = swap(swap() - (T)i); value = swap(swap() - (T)i);
return *this; return *this;
} }
// ++v // ++v
swapped_t& operator++() { swapped_t& operator++() {
value = swap(swap()+1); value = swap(swap()+1);
return *this; return *this;
} }
// --v // --v
swapped_t& operator--() { swapped_t& operator--() {
value = swap(swap()-1); value = swap(swap()-1);
return *this; return *this;
} }
// v++ // v++
swapped_t operator++(int) { swapped_t operator++(int) {
swapped_t old = *this; swapped_t old = *this;
value = swap(swap()+1); value = swap(swap()+1);
return old; return old;
} }
// v-- // v--
swapped_t operator--(int) { swapped_t operator--(int) {
swapped_t old = *this; swapped_t old = *this;
value = swap(swap()-1); value = swap(swap()-1);
return old; return old;
} }
// Comparaison // Comparaison
// v == i // v == i
bool operator==(const swapped_t &i) const { bool operator==(const swapped_t &i) const {
return swap() == i.swap(); return swap() == i.swap();
} }
template <typename S> template <typename S>
bool operator==(const S &i) const { bool operator==(const S &i) const {
return swap() == i; return swap() == i;
} }
// v != i // v != i
bool operator!=(const swapped_t &i) const { bool operator!=(const swapped_t &i) const {
return swap() != i.swap(); return swap() != i.swap();
} }
template <typename S> template <typename S>
bool operator!=(const S &i) const { bool operator!=(const S &i) const {
return swap() != i; return swap() != i;
} }
// v > i // v > i
bool operator>(const swapped_t &i) const { bool operator>(const swapped_t &i) const {
return swap() > i.swap(); return swap() > i.swap();
} }
template <typename S> template <typename S>
bool operator>(const S &i) const { bool operator>(const S &i) const {
return swap() > i; return swap() > i;
} }
// v < i // v < i
bool operator<(const swapped_t &i) const { bool operator<(const swapped_t &i) const {
return swap() < i.swap(); return swap() < i.swap();
} }
template <typename S> template <typename S>
bool operator<(const S &i) const { bool operator<(const S &i) const {
return swap() < i; return swap() < i;
} }
// v >= i // v >= i
bool operator>=(const swapped_t &i) const { bool operator>=(const swapped_t &i) const {
return swap() >= i.swap(); return swap() >= i.swap();
} }
template <typename S> template <typename S>
bool operator>=(const S &i) const { bool operator>=(const S &i) const {
return swap() >= i; return swap() >= i;
} }
// v <= i // v <= i
bool operator<=(const swapped_t &i) const { bool operator<=(const swapped_t &i) const {
return swap() <= i.swap(); return swap() <= i.swap();
} }
template <typename S> template <typename S>
bool operator<=(const S &i) const { bool operator<=(const S &i) const {
return swap() <= i; return swap() <= i;
} }
// logical // logical
swapped_t operator !() const { swapped_t operator !() const {
return !swap(); return !swap();
} }
// bitmath // bitmath
swapped_t operator ~() const { swapped_t operator ~() const {
return ~swap(); return ~swap();
} }
swapped_t operator &(const swapped_t &b) const { swapped_t operator &(const swapped_t &b) const {
return swap() & b.swap(); return swap() & b.swap();
} }
template <typename S> template <typename S>
swapped_t operator &(const S &b) const { swapped_t operator &(const S &b) const {
return swap() & b; return swap() & b;
} }
swapped_t& operator &=(const swapped_t &b) { swapped_t& operator &=(const swapped_t &b) {
value = swap(swap() & b.swap()); value = swap(swap() & b.swap());
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t& operator &=(const S b) { swapped_t& operator &=(const S b) {
value = swap(swap() & b); value = swap(swap() & b);
return *this; return *this;
} }
swapped_t operator |(const swapped_t &b) const { swapped_t operator |(const swapped_t &b) const {
return swap() | b.swap(); return swap() | b.swap();
} }
template <typename S> template <typename S>
swapped_t operator |(const S &b) const { swapped_t operator |(const S &b) const {
return swap() | b; return swap() | b;
} }
swapped_t& operator |=(const swapped_t &b) { swapped_t& operator |=(const swapped_t &b) {
value = swap(swap() | b.swap()); value = swap(swap() | b.swap());
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t& operator |=(const S &b) { swapped_t& operator |=(const S &b) {
value = swap(swap() | b); value = swap(swap() | b);
return *this; return *this;
} }
swapped_t operator ^(const swapped_t &b) const { swapped_t operator ^(const swapped_t &b) const {
return swap() ^ b.swap(); return swap() ^ b.swap();
} }
template <typename S> template <typename S>
swapped_t operator ^(const S &b) const { swapped_t operator ^(const S &b) const {
return swap() ^ b; return swap() ^ b;
} }
swapped_t& operator ^=(const swapped_t &b) { swapped_t& operator ^=(const swapped_t &b) {
value = swap(swap() ^ b.swap()); value = swap(swap() ^ b.swap());
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t& operator ^=(const S &b) { swapped_t& operator ^=(const S &b) {
value = swap(swap() ^ b); value = swap(swap() ^ b);
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t operator <<(const S &b) const { swapped_t operator <<(const S &b) const {
return swap() << b; return swap() << b;
} }
template <typename S> template <typename S>
swapped_t& operator <<=(const S &b) const { swapped_t& operator <<=(const S &b) const {
value = swap(swap() << b); value = swap(swap() << b);
return *this; return *this;
} }
template <typename S> template <typename S>
swapped_t operator >>(const S &b) const { swapped_t operator >>(const S &b) const {
return swap() >> b; return swap() >> b;
} }
template <typename S> template <typename S>
swapped_t& operator >>=(const S &b) const { swapped_t& operator >>=(const S &b) const {
value = swap(swap() >> b); value = swap(swap() >> b);
return *this; return *this;
} }
// Member // Member
/** todo **/ /** todo **/
// Arithmetics // Arithmetics
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator+(const S &p, const swapped_t v); friend S operator+(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator-(const S &p, const swapped_t v); friend S operator-(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator/(const S &p, const swapped_t v); friend S operator/(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator*(const S &p, const swapped_t v); friend S operator*(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator%(const S &p, const swapped_t v); friend S operator%(const S &p, const swapped_t v);
// Arithmetics + assignements // Arithmetics + assignements
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator+=(const S &p, const swapped_t v); friend S operator+=(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator-=(const S &p, const swapped_t v); friend S operator-=(const S &p, const swapped_t v);
// Bitmath // Bitmath
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend S operator&(const S &p, const swapped_t v); friend S operator&(const S &p, const swapped_t v);
// Comparison // Comparison
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator<(const S &p, const swapped_t v); friend bool operator<(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator>(const S &p, const swapped_t v); friend bool operator>(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator<=(const S &p, const swapped_t v); friend bool operator<=(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator>=(const S &p, const swapped_t v); friend bool operator>=(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator!=(const S &p, const swapped_t v); friend bool operator!=(const S &p, const swapped_t v);
template <typename S, typename T2, typename F2> template <typename S, typename T2, typename F2>
friend bool operator==(const S &p, const swapped_t v); friend bool operator==(const S &p, const swapped_t v);
}; };
// Arithmetics // Arithmetics
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator+(const S &i, const swap_struct_t<T, F> v) { S operator+(const S &i, const swap_struct_t<T, F> v) {
return i + v.swap(); return i + v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator-(const S &i, const swap_struct_t<T, F> v) { S operator-(const S &i, const swap_struct_t<T, F> v) {
return i - v.swap(); return i - v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator/(const S &i, const swap_struct_t<T, F> v) { S operator/(const S &i, const swap_struct_t<T, F> v) {
return i / v.swap(); return i / v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator*(const S &i, const swap_struct_t<T, F> v) { S operator*(const S &i, const swap_struct_t<T, F> v) {
return i * v.swap(); return i * v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator%(const S &i, const swap_struct_t<T, F> v) { S operator%(const S &i, const swap_struct_t<T, F> v) {
return i % v.swap(); return i % v.swap();
} }
// Arithmetics + assignements // Arithmetics + assignements
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S &operator+=(S &i, const swap_struct_t<T, F> v) { S &operator+=(S &i, const swap_struct_t<T, F> v) {
i += v.swap(); i += v.swap();
return i; return i;
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S &operator-=(S &i, const swap_struct_t<T, F> v) { S &operator-=(S &i, const swap_struct_t<T, F> v) {
i -= v.swap(); i -= v.swap();
return i; return i;
} }
// Logical // Logical
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator&(const S &i, const swap_struct_t<T, F> v) { S operator&(const S &i, const swap_struct_t<T, F> v) {
return i & v.swap(); return i & v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
S operator&(const swap_struct_t<T, F> v, const S &i) { S operator&(const swap_struct_t<T, F> v, const S &i) {
return (S)(v.swap() & i); return (S)(v.swap() & i);
} }
// Comparaison // Comparaison
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator<(const S &p, const swap_struct_t<T, F> v) { bool operator<(const S &p, const swap_struct_t<T, F> v) {
return p < v.swap(); return p < v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator>(const S &p, const swap_struct_t<T, F> v) { bool operator>(const S &p, const swap_struct_t<T, F> v) {
return p > v.swap(); return p > v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator<=(const S &p, const swap_struct_t<T, F> v) { bool operator<=(const S &p, const swap_struct_t<T, F> v) {
return p <= v.swap(); return p <= v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator>=(const S &p, const swap_struct_t<T, F> v) { bool operator>=(const S &p, const swap_struct_t<T, F> v) {
return p >= v.swap(); return p >= v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator!=(const S &p, const swap_struct_t<T, F> v) { bool operator!=(const S &p, const swap_struct_t<T, F> v) {
return p != v.swap(); return p != v.swap();
} }
template <typename S, typename T, typename F> template <typename S, typename T, typename F>
bool operator==(const S &p, const swap_struct_t<T, F> v) { bool operator==(const S &p, const swap_struct_t<T, F> v) {
return p == v.swap(); return p == v.swap();
} }
template <typename T> template <typename T>
struct swap_64_t { struct swap_64_t {
static T swap(T x) { static T swap(T x) {
return (T)bswap64(*(u64 *)&x); return (T)bswap64(*(u64 *)&x);
} }
}; };
template <typename T> template <typename T>
struct swap_32_t { struct swap_32_t {
static T swap(T x) { static T swap(T x) {
return (T)bswap32(*(u32 *)&x); return (T)bswap32(*(u32 *)&x);
} }
}; };
template <typename T> template <typename T>
struct swap_16_t { struct swap_16_t {
static T swap(T x) { static T swap(T x) {
return (T)bswap16(*(u16 *)&x); return (T)bswap16(*(u16 *)&x);
} }
}; };
template <typename T> template <typename T>
struct swap_float_t { struct swap_float_t {
static T swap(T x) { static T swap(T x) {
return (T)bswapf(*(float *)&x); return (T)bswapf(*(float *)&x);
} }
}; };
template <typename T> template <typename T>
struct swap_double_t { struct swap_double_t {
static T swap(T x) { static T swap(T x) {
return (T)bswapd(*(double *)&x); return (T)bswapd(*(double *)&x);
} }
}; };
#if COMMON_LITTLE_ENDIAN #if COMMON_LITTLE_ENDIAN

View file

@ -21,11 +21,11 @@ namespace Common
int CurrentThreadId() int CurrentThreadId()
{ {
#ifdef _WIN32 #ifdef _WIN32
return GetCurrentThreadId(); return GetCurrentThreadId();
#elif defined __APPLE__ #elif defined __APPLE__
return mach_thread_self(); return mach_thread_self();
#else #else
return 0; return 0;
#endif #endif
} }
@ -33,23 +33,23 @@ int CurrentThreadId()
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
{ {
SetThreadAffinityMask(thread, mask); SetThreadAffinityMask(thread, mask);
} }
void SetCurrentThreadAffinity(u32 mask) void SetCurrentThreadAffinity(u32 mask)
{ {
SetThreadAffinityMask(GetCurrentThread(), mask); SetThreadAffinityMask(GetCurrentThread(), mask);
} }
// Supporting functions // Supporting functions
void SleepCurrentThread(int ms) void SleepCurrentThread(int ms)
{ {
Sleep(ms); Sleep(ms);
} }
void SwitchCurrentThread() void SwitchCurrentThread()
{ {
SwitchToThread(); SwitchToThread();
} }
// Sets the debugger-visible name of the current thread. // Sets the debugger-visible name of the current thread.
@ -60,29 +60,29 @@ void SwitchCurrentThread()
// http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx // http://msdn.microsoft.com/en-us/library/xcb2z8hs(VS.100).aspx
void SetCurrentThreadName(const char* szThreadName) void SetCurrentThreadName(const char* szThreadName)
{ {
static const DWORD MS_VC_EXCEPTION = 0x406D1388; static const DWORD MS_VC_EXCEPTION = 0x406D1388;
#pragma pack(push,8) #pragma pack(push,8)
struct THREADNAME_INFO struct THREADNAME_INFO
{ {
DWORD dwType; // must be 0x1000 DWORD dwType; // must be 0x1000
LPCSTR szName; // pointer to name (in user addr space) LPCSTR szName; // pointer to name (in user addr space)
DWORD dwThreadID; // thread ID (-1=caller thread) DWORD dwThreadID; // thread ID (-1=caller thread)
DWORD dwFlags; // reserved for future use, must be zero DWORD dwFlags; // reserved for future use, must be zero
} info; } info;
#pragma pack(pop) #pragma pack(pop)
info.dwType = 0x1000; info.dwType = 0x1000;
info.szName = szThreadName; info.szName = szThreadName;
info.dwThreadID = -1; //dwThreadID; info.dwThreadID = -1; //dwThreadID;
info.dwFlags = 0; info.dwFlags = 0;
__try __try
{ {
RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info); RaiseException(MS_VC_EXCEPTION, 0, sizeof(info)/sizeof(ULONG_PTR), (ULONG_PTR*)&info);
} }
__except(EXCEPTION_CONTINUE_EXECUTION) __except(EXCEPTION_CONTINUE_EXECUTION)
{} {}
} }
#else // !WIN32, so must be POSIX threads #else // !WIN32, so must be POSIX threads
@ -90,41 +90,41 @@ void SetCurrentThreadName(const char* szThreadName)
void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask) void SetThreadAffinity(std::thread::native_handle_type thread, u32 mask)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
thread_policy_set(pthread_mach_thread_np(thread), thread_policy_set(pthread_mach_thread_np(thread),
THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1); THREAD_AFFINITY_POLICY, (integer_t *)&mask, 1);
#elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID) #elif (defined __linux__ || defined BSD4_4) && !(defined ANDROID)
cpu_set_t cpu_set; cpu_set_t cpu_set;
CPU_ZERO(&cpu_set); CPU_ZERO(&cpu_set);
for (int i = 0; i != sizeof(mask) * 8; ++i) for (int i = 0; i != sizeof(mask) * 8; ++i)
if ((mask >> i) & 1) if ((mask >> i) & 1)
CPU_SET(i, &cpu_set); CPU_SET(i, &cpu_set);
pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set); pthread_setaffinity_np(thread, sizeof(cpu_set), &cpu_set);
#endif #endif
} }
void SetCurrentThreadAffinity(u32 mask) void SetCurrentThreadAffinity(u32 mask)
{ {
SetThreadAffinity(pthread_self(), mask); SetThreadAffinity(pthread_self(), mask);
} }
void SleepCurrentThread(int ms) void SleepCurrentThread(int ms)
{ {
usleep(1000 * ms); usleep(1000 * ms);
} }
void SwitchCurrentThread() void SwitchCurrentThread()
{ {
usleep(1000 * 1); usleep(1000 * 1);
} }
void SetCurrentThreadName(const char* szThreadName) void SetCurrentThreadName(const char* szThreadName)
{ {
#ifdef __APPLE__ #ifdef __APPLE__
pthread_setname_np(szThreadName); pthread_setname_np(szThreadName);
#else #else
pthread_setname_np(pthread_self(), szThreadName); pthread_setname_np(pthread_self(), szThreadName);
#endif #endif
} }

View file

@ -36,117 +36,117 @@ void SetCurrentThreadAffinity(u32 mask);
class Event class Event
{ {
public: public:
Event() Event()
: is_set(false) : is_set(false)
{}; {};
void Set() void Set()
{ {
std::lock_guard<std::mutex> lk(m_mutex); std::lock_guard<std::mutex> lk(m_mutex);
if (!is_set) if (!is_set)
{ {
is_set = true; is_set = true;
m_condvar.notify_one(); m_condvar.notify_one();
} }
} }
void Wait() void Wait()
{ {
std::unique_lock<std::mutex> lk(m_mutex); std::unique_lock<std::mutex> lk(m_mutex);
m_condvar.wait(lk, IsSet(this)); m_condvar.wait(lk, IsSet(this));
is_set = false; is_set = false;
} }
void Reset() void Reset()
{ {
std::unique_lock<std::mutex> lk(m_mutex); std::unique_lock<std::mutex> lk(m_mutex);
// no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration // no other action required, since wait loops on the predicate and any lingering signal will get cleared on the first iteration
is_set = false; is_set = false;
} }
private: private:
class IsSet class IsSet
{ {
public: public:
IsSet(const Event* ev) IsSet(const Event* ev)
: m_event(ev) : m_event(ev)
{} {}
bool operator()() bool operator()()
{ {
return m_event->is_set; return m_event->is_set;
} }
private: private:
const Event* const m_event; const Event* const m_event;
}; };
volatile bool is_set; volatile bool is_set;
std::condition_variable m_condvar; std::condition_variable m_condvar;
std::mutex m_mutex; std::mutex m_mutex;
}; };
// TODO: doesn't work on windows with (count > 2) // TODO: doesn't work on windows with (count > 2)
class Barrier class Barrier
{ {
public: public:
Barrier(size_t count) Barrier(size_t count)
: m_count(count), m_waiting(0) : m_count(count), m_waiting(0)
{} {}
// block until "count" threads call Sync() // block until "count" threads call Sync()
bool Sync() bool Sync()
{ {
std::unique_lock<std::mutex> lk(m_mutex); std::unique_lock<std::mutex> lk(m_mutex);
// TODO: broken when next round of Sync()s // TODO: broken when next round of Sync()s
// is entered before all waiting threads return from the notify_all // is entered before all waiting threads return from the notify_all
if (m_count == ++m_waiting) if (m_count == ++m_waiting)
{ {
m_waiting = 0; m_waiting = 0;
m_condvar.notify_all(); m_condvar.notify_all();
return true; return true;
} }
else else
{ {
m_condvar.wait(lk, IsDoneWating(this)); m_condvar.wait(lk, IsDoneWating(this));
return false; return false;
} }
} }
private: private:
class IsDoneWating class IsDoneWating
{ {
public: public:
IsDoneWating(const Barrier* bar) IsDoneWating(const Barrier* bar)
: m_bar(bar) : m_bar(bar)
{} {}
bool operator()() bool operator()()
{ {
return (0 == m_bar->m_waiting); return (0 == m_bar->m_waiting);
} }
private: private:
const Barrier* const m_bar; const Barrier* const m_bar;
}; };
std::condition_variable m_condvar; std::condition_variable m_condvar;
std::mutex m_mutex; std::mutex m_mutex;
const size_t m_count; const size_t m_count;
volatile size_t m_waiting; volatile size_t m_waiting;
}; };
void SleepCurrentThread(int ms); void SleepCurrentThread(int ms);
void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms void SwitchCurrentThread(); // On Linux, this is equal to sleep 1ms
// Use this function during a spin-wait to make the current thread // Use this function during a spin-wait to make the current thread
// relax while another thread is working. This may be more efficient // relax while another thread is working. This may be more efficient
// than using events because event functions use kernel calls. // than using events because event functions use kernel calls.
inline void YieldCPU() inline void YieldCPU()
{ {
std::this_thread::yield(); std::this_thread::yield();
} }
void SetCurrentThreadName(const char *name); void SetCurrentThreadName(const char *name);

View file

@ -24,23 +24,23 @@
class ThunkManager : public Gen::XCodeBlock class ThunkManager : public Gen::XCodeBlock
{ {
std::map<void *, const u8 *> thunks; std::map<void *, const u8 *> thunks;
const u8 *save_regs; const u8 *save_regs;
const u8 *load_regs; const u8 *load_regs;
public: public:
ThunkManager() { ThunkManager() {
Init(); Init();
} }
~ThunkManager() { ~ThunkManager() {
Shutdown(); Shutdown();
} }
void *ProtectFunction(void *function, int num_params); void *ProtectFunction(void *function, int num_params);
private: private:
void Init(); void Init();
void Shutdown(); void Shutdown();
void Reset(); void Reset();
}; };
#endif // _THUNK_H_ #endif // _THUNK_H_

View file

@ -22,11 +22,11 @@ namespace Common
u32 Timer::GetTimeMs() u32 Timer::GetTimeMs()
{ {
#ifdef _WIN32 #ifdef _WIN32
return timeGetTime(); return timeGetTime();
#else #else
struct timeval t; struct timeval t;
(void)gettimeofday(&t, NULL); (void)gettimeofday(&t, NULL);
return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000)); return ((u32)(t.tv_sec * 1000 + t.tv_usec / 1000));
#endif #endif
} }
@ -36,31 +36,31 @@ u32 Timer::GetTimeMs()
// Set initial values for the class // Set initial values for the class
Timer::Timer() Timer::Timer()
: m_LastTime(0), m_StartTime(0), m_Running(false) : m_LastTime(0), m_StartTime(0), m_Running(false)
{ {
Update(); Update();
} }
// Write the starting time // Write the starting time
void Timer::Start() void Timer::Start()
{ {
m_StartTime = GetTimeMs(); m_StartTime = GetTimeMs();
m_Running = true; m_Running = true;
} }
// Stop the timer // Stop the timer
void Timer::Stop() void Timer::Stop()
{ {
// Write the final time // Write the final time
m_LastTime = GetTimeMs(); m_LastTime = GetTimeMs();
m_Running = false; m_Running = false;
} }
// Update the last time variable // Update the last time variable
void Timer::Update() void Timer::Update()
{ {
m_LastTime = GetTimeMs(); m_LastTime = GetTimeMs();
//TODO(ector) - QPF //TODO(ector) - QPF
} }
// ------------------------------------- // -------------------------------------
@ -70,125 +70,125 @@ void Timer::Update()
// Get the number of milliseconds since the last Update() // Get the number of milliseconds since the last Update()
u64 Timer::GetTimeDifference() u64 Timer::GetTimeDifference()
{ {
return GetTimeMs() - m_LastTime; return GetTimeMs() - m_LastTime;
} }
// Add the time difference since the last Update() to the starting time. // Add the time difference since the last Update() to the starting time.
// This is used to compensate for a paused game. // This is used to compensate for a paused game.
void Timer::AddTimeDifference() void Timer::AddTimeDifference()
{ {
m_StartTime += GetTimeDifference(); m_StartTime += GetTimeDifference();
} }
// Get the time elapsed since the Start() // Get the time elapsed since the Start()
u64 Timer::GetTimeElapsed() u64 Timer::GetTimeElapsed()
{ {
// If we have not started yet, return 1 (because then I don't // If we have not started yet, return 1 (because then I don't
// have to change the FPS calculation in CoreRerecording.cpp . // have to change the FPS calculation in CoreRerecording.cpp .
if (m_StartTime == 0) return 1; if (m_StartTime == 0) return 1;
// Return the final timer time if the timer is stopped // Return the final timer time if the timer is stopped
if (!m_Running) return (m_LastTime - m_StartTime); if (!m_Running) return (m_LastTime - m_StartTime);
return (GetTimeMs() - m_StartTime); return (GetTimeMs() - m_StartTime);
} }
// Get the formatted time elapsed since the Start() // Get the formatted time elapsed since the Start()
std::string Timer::GetTimeElapsedFormatted() const std::string Timer::GetTimeElapsedFormatted() const
{ {
// If we have not started yet, return zero // If we have not started yet, return zero
if (m_StartTime == 0) if (m_StartTime == 0)
return "00:00:00:000"; return "00:00:00:000";
// The number of milliseconds since the start. // The number of milliseconds since the start.
// Use a different value if the timer is stopped. // Use a different value if the timer is stopped.
u64 Milliseconds; u64 Milliseconds;
if (m_Running) if (m_Running)
Milliseconds = GetTimeMs() - m_StartTime; Milliseconds = GetTimeMs() - m_StartTime;
else else
Milliseconds = m_LastTime - m_StartTime; Milliseconds = m_LastTime - m_StartTime;
// Seconds // Seconds
u32 Seconds = (u32)(Milliseconds / 1000); u32 Seconds = (u32)(Milliseconds / 1000);
// Minutes // Minutes
u32 Minutes = Seconds / 60; u32 Minutes = Seconds / 60;
// Hours // Hours
u32 Hours = Minutes / 60; u32 Hours = Minutes / 60;
std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i", std::string TmpStr = StringFromFormat("%02i:%02i:%02i:%03i",
Hours, Minutes % 60, Seconds % 60, Milliseconds % 1000); Hours, Minutes % 60, Seconds % 60, Milliseconds % 1000);
return TmpStr; return TmpStr;
} }
// Get current time // Get current time
void Timer::IncreaseResolution() void Timer::IncreaseResolution()
{ {
#ifdef _WIN32 #ifdef _WIN32
timeBeginPeriod(1); timeBeginPeriod(1);
#endif #endif
} }
void Timer::RestoreResolution() void Timer::RestoreResolution()
{ {
#ifdef _WIN32 #ifdef _WIN32
timeEndPeriod(1); timeEndPeriod(1);
#endif #endif
} }
// Get the number of seconds since January 1 1970 // Get the number of seconds since January 1 1970
u64 Timer::GetTimeSinceJan1970() u64 Timer::GetTimeSinceJan1970()
{ {
time_t ltime; time_t ltime;
time(&ltime); time(&ltime);
return((u64)ltime); return((u64)ltime);
} }
u64 Timer::GetLocalTimeSinceJan1970() u64 Timer::GetLocalTimeSinceJan1970()
{ {
time_t sysTime, tzDiff, tzDST; time_t sysTime, tzDiff, tzDST;
struct tm * gmTime; struct tm * gmTime;
time(&sysTime); time(&sysTime);
// Account for DST where needed // Account for DST where needed
gmTime = localtime(&sysTime); gmTime = localtime(&sysTime);
if(gmTime->tm_isdst == 1) if(gmTime->tm_isdst == 1)
tzDST = 3600; tzDST = 3600;
else else
tzDST = 0; tzDST = 0;
// Lazy way to get local time in sec // Lazy way to get local time in sec
gmTime = gmtime(&sysTime); gmTime = gmtime(&sysTime);
tzDiff = sysTime - mktime(gmTime); tzDiff = sysTime - mktime(gmTime);
return (u64)(sysTime + tzDiff + tzDST); return (u64)(sysTime + tzDiff + tzDST);
} }
// Return the current time formatted as Minutes:Seconds:Milliseconds // Return the current time formatted as Minutes:Seconds:Milliseconds
// in the form 00:00:000. // in the form 00:00:000.
std::string Timer::GetTimeFormatted() std::string Timer::GetTimeFormatted()
{ {
time_t sysTime; time_t sysTime;
struct tm * gmTime; struct tm * gmTime;
char formattedTime[13]; char formattedTime[13];
char tmp[13]; char tmp[13];
time(&sysTime); time(&sysTime);
gmTime = localtime(&sysTime); gmTime = localtime(&sysTime);
strftime(tmp, 6, "%M:%S", gmTime); strftime(tmp, 6, "%M:%S", gmTime);
// Now tack on the milliseconds // Now tack on the milliseconds
#ifdef _WIN32 #ifdef _WIN32
struct timeb tp; struct timeb tp;
(void)::ftime(&tp); (void)::ftime(&tp);
sprintf(formattedTime, "%s:%03i", tmp, tp.millitm); sprintf(formattedTime, "%s:%03i", tmp, tp.millitm);
#else #else
struct timeval t; struct timeval t;
(void)gettimeofday(&t, NULL); (void)gettimeofday(&t, NULL);
sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000)); sprintf(formattedTime, "%s:%03d", tmp, (int)(t.tv_usec / 1000));
#endif #endif
return std::string(formattedTime); return std::string(formattedTime);
} }
// Returns a timestamp with decimals for precise time comparisons // Returns a timestamp with decimals for precise time comparisons
@ -196,31 +196,31 @@ std::string Timer::GetTimeFormatted()
double Timer::GetDoubleTime() double Timer::GetDoubleTime()
{ {
#ifdef _WIN32 #ifdef _WIN32
struct timeb tp; struct timeb tp;
(void)::ftime(&tp); (void)::ftime(&tp);
#else #else
struct timeval t; struct timeval t;
(void)gettimeofday(&t, NULL); (void)gettimeofday(&t, NULL);
#endif #endif
// Get continuous timestamp // Get continuous timestamp
u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970(); u64 TmpSeconds = Common::Timer::GetTimeSinceJan1970();
// Remove a few years. We only really want enough seconds to make // Remove a few years. We only really want enough seconds to make
// sure that we are detecting actual actions, perhaps 60 seconds is // sure that we are detecting actual actions, perhaps 60 seconds is
// enough really, but I leave a year of seconds anyway, in case the // enough really, but I leave a year of seconds anyway, in case the
// user's clock is incorrect or something like that. // user's clock is incorrect or something like that.
TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60); TmpSeconds = TmpSeconds - (38 * 365 * 24 * 60 * 60);
// Make a smaller integer that fits in the double // Make a smaller integer that fits in the double
u32 Seconds = (u32)TmpSeconds; u32 Seconds = (u32)TmpSeconds;
#ifdef _WIN32 #ifdef _WIN32
double ms = tp.millitm / 1000.0 / 1000.0; double ms = tp.millitm / 1000.0 / 1000.0;
#else #else
double ms = t.tv_usec / 1000000.0; double ms = t.tv_usec / 1000000.0;
#endif #endif
double TmpTime = Seconds + ms; double TmpTime = Seconds + ms;
return TmpTime; return TmpTime;
} }
} // Namespace Common } // Namespace Common

View file

@ -13,32 +13,32 @@ namespace Common
class Timer class Timer
{ {
public: public:
Timer(); Timer();
void Start(); void Start();
void Stop(); void Stop();
void Update(); void Update();
// The time difference is always returned in milliseconds, regardless of alternative internal representation // The time difference is always returned in milliseconds, regardless of alternative internal representation
u64 GetTimeDifference(); u64 GetTimeDifference();
void AddTimeDifference(); void AddTimeDifference();
static void IncreaseResolution(); static void IncreaseResolution();
static void RestoreResolution(); static void RestoreResolution();
static u64 GetTimeSinceJan1970(); static u64 GetTimeSinceJan1970();
static u64 GetLocalTimeSinceJan1970(); static u64 GetLocalTimeSinceJan1970();
static double GetDoubleTime(); static double GetDoubleTime();
static std::string GetTimeFormatted(); static std::string GetTimeFormatted();
std::string GetTimeElapsedFormatted() const; std::string GetTimeElapsedFormatted() const;
u64 GetTimeElapsed(); u64 GetTimeElapsed();
static u32 GetTimeMs(); static u32 GetTimeMs();
private: private:
u64 m_LastTime; u64 m_LastTime;
u64 m_StartTime; u64 m_StartTime;
bool m_Running; bool m_Running;
}; };
} // Namespace Common } // Namespace Common

View file

@ -31,7 +31,7 @@
// is start of UTF sequence // is start of UTF sequence
inline bool isutf(char c) { inline bool isutf(char c) {
return (c & 0xC0) != 0x80; return (c & 0xC0) != 0x80;
} }
static const u32 offsetsFromUTF8[6] = { static const u32 offsetsFromUTF8[6] = {
@ -47,7 +47,7 @@ static const u8 trailingBytesForUTF8[256] = {
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0, 0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,0,
1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1, 1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,1,
2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5, 2,2,2,2,2,2,2,2,2,2,2,2,2,2,2,2, 3,3,3,3,3,3,3,3,4,4,4,4,5,5,5,5,
}; };
/* returns length of next utf-8 sequence */ /* returns length of next utf-8 sequence */
@ -405,59 +405,59 @@ int u8_is_locale_utf8(const char *locale)
} }
int UTF8StringNonASCIICount(const char *utf8string) { int UTF8StringNonASCIICount(const char *utf8string) {
UTF8 utf(utf8string); UTF8 utf(utf8string);
int count = 0; int count = 0;
while (!utf.end()) { while (!utf.end()) {
int c = utf.next(); int c = utf.next();
if (c > 127) if (c > 127)
++count; ++count;
} }
return count; return count;
} }
bool UTF8StringHasNonASCII(const char *utf8string) { bool UTF8StringHasNonASCII(const char *utf8string) {
return UTF8StringNonASCIICount(utf8string) > 0; return UTF8StringNonASCIICount(utf8string) > 0;
} }
#ifdef _WIN32 #ifdef _WIN32
std::string ConvertWStringToUTF8(const wchar_t *wstr) { std::string ConvertWStringToUTF8(const wchar_t *wstr) {
int len = (int)wcslen(wstr); int len = (int)wcslen(wstr);
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL); int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr, len, 0, 0, NULL, NULL);
std::string s; std::string s;
s.resize(size); s.resize(size);
if (size > 0) { if (size > 0) {
WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, wstr, len, &s[0], size, NULL, NULL);
} }
return s; return s;
} }
std::string ConvertWStringToUTF8(const std::wstring &wstr) { std::string ConvertWStringToUTF8(const std::wstring &wstr) {
int len = (int)wstr.size(); int len = (int)wstr.size();
int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL); int size = (int)WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, 0, 0, NULL, NULL);
std::string s; std::string s;
s.resize(size); s.resize(size);
if (size > 0) { if (size > 0) {
WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL); WideCharToMultiByte(CP_UTF8, 0, wstr.c_str(), len, &s[0], size, NULL, NULL);
} }
return s; return s;
} }
void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) { void ConvertUTF8ToWString(wchar_t *dest, size_t destSize, const std::string &source) {
int len = (int)source.size(); int len = (int)source.size();
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size)); MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, dest, std::min((int)destSize, size));
} }
std::wstring ConvertUTF8ToWString(const std::string &source) { std::wstring ConvertUTF8ToWString(const std::string &source) {
int len = (int)source.size(); int len = (int)source.size();
int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0); int size = (int)MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, NULL, 0);
std::wstring str; std::wstring str;
str.resize(size); str.resize(size);
if (size > 0) { if (size > 0) {
MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size); MultiByteToWideChar(CP_UTF8, 0, source.c_str(), len, &str[0], size);
} }
return str; return str;
} }
#endif #endif

View file

@ -25,29 +25,29 @@ int u8_strlen(const char *s);
class UTF8 { class UTF8 {
public: public:
static const u32 INVALID = (u32)-1; static const u32 INVALID = (u32)-1;
UTF8(const char *c) : c_(c), index_(0) {} UTF8(const char *c) : c_(c), index_(0) {}
bool end() const { return c_[index_] == 0; } bool end() const { return c_[index_] == 0; }
u32 next() { u32 next() {
return u8_nextchar(c_, &index_); return u8_nextchar(c_, &index_);
} }
u32 peek() { u32 peek() {
int tempIndex = index_; int tempIndex = index_;
return u8_nextchar(c_, &tempIndex); return u8_nextchar(c_, &tempIndex);
} }
int length() const { int length() const {
return u8_strlen(c_); return u8_strlen(c_);
} }
int byteIndex() const { int byteIndex() const {
return index_; return index_;
} }
static int encode(char *dest, u32 ch) { static int encode(char *dest, u32 ch) {
return u8_wc_toutf8(dest, ch); return u8_wc_toutf8(dest, ch);
} }
private: private:
const char *c_; const char *c_;
int index_; int index_;
}; };
int UTF8StringNonASCIICount(const char *utf8string); int UTF8StringNonASCIICount(const char *utf8string);

View file

@ -6,22 +6,22 @@
#include "scm_rev.h" #include "scm_rev.h"
#ifdef _DEBUG #ifdef _DEBUG
#define BUILD_TYPE_STR "Debug " #define BUILD_TYPE_STR "Debug "
#elif defined DEBUGFAST #elif defined DEBUGFAST
#define BUILD_TYPE_STR "DebugFast " #define BUILD_TYPE_STR "DebugFast "
#else #else
#define BUILD_TYPE_STR "" #define BUILD_TYPE_STR ""
#endif #endif
const char *scm_rev_str = "emu " const char *scm_rev_str = "emu "
#if !SCM_IS_MASTER #if !SCM_IS_MASTER
"[" SCM_BRANCH_STR "] " "[" SCM_BRANCH_STR "] "
#endif #endif
#ifdef __INTEL_COMPILER #ifdef __INTEL_COMPILER
BUILD_TYPE_STR SCM_DESC_STR "-ICC"; BUILD_TYPE_STR SCM_DESC_STR "-ICC";
#else #else
BUILD_TYPE_STR SCM_DESC_STR; BUILD_TYPE_STR SCM_DESC_STR;
#endif #endif
#ifdef _M_X64 #ifdef _M_X64