mirror of
https://github.com/dolphin-emu/dolphin.git
synced 2025-07-23 14:19:46 -06:00
Initial megacommit.
git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
246
Source/Core/Common/Src/CPUDetect.cpp
Normal file
246
Source/Core/Common/Src/CPUDetect.cpp
Normal file
@ -0,0 +1,246 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <intrin.h>
|
||||
#endif
|
||||
|
||||
#ifdef __linux__
|
||||
//#include <config/i386/cpuid.h>
|
||||
#include <xmmintrin.h>
|
||||
void __cpuid(int info[4], int x) {}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#include <memory.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "CPUDetect.h"
|
||||
|
||||
// This code was adapted from an example in MSDN:
|
||||
CPUInfoStruct cpu_info;
|
||||
|
||||
void CPUInfoStruct::Detect()
|
||||
{
|
||||
#ifdef _M_IX86
|
||||
Mode64bit = false;
|
||||
#elif defined (_M_X64)
|
||||
Mode64bit = true;
|
||||
OS64bit = true;
|
||||
#endif
|
||||
numCores = 1;
|
||||
|
||||
#ifdef _WIN32
|
||||
#ifdef _M_IX86
|
||||
BOOL f64 = FALSE;
|
||||
OS64bit = IsWow64Process(GetCurrentProcess(), &f64) && f64;
|
||||
#endif
|
||||
#endif
|
||||
|
||||
// __cpuid with an InfoType argument of 0 returns the number of
|
||||
// valid Ids in CPUInfo[0] and the CPU identification string in
|
||||
// the other three array elements. The CPU identification string is
|
||||
// not in linear order. The code below arranges the information
|
||||
// in a human readable form.
|
||||
__cpuid(CPUInfo, 0);
|
||||
nIds = CPUInfo[0];
|
||||
memset(CPUString, 0, sizeof(CPUString));
|
||||
*((int*)CPUString) = CPUInfo[1];
|
||||
*((int*)(CPUString + 4)) = CPUInfo[3];
|
||||
*((int*)(CPUString + 8)) = CPUInfo[2];
|
||||
|
||||
// Assume that everything non-intel is AMD
|
||||
if (memcmp(CPUString, "GenuineIntel", 12) == 0)
|
||||
{
|
||||
isAMD = false;
|
||||
}
|
||||
else
|
||||
{
|
||||
isAMD = true;
|
||||
}
|
||||
|
||||
// Get the information associated with each valid Id
|
||||
for (unsigned int i = 0; i <= nIds; ++i)
|
||||
{
|
||||
__cpuid(CPUInfo, i);
|
||||
|
||||
// Interpret CPU feature information.
|
||||
if (i == 1)
|
||||
{
|
||||
nSteppingID = CPUInfo[0] & 0xf;
|
||||
nModel = (CPUInfo[0] >> 4) & 0xf;
|
||||
nFamily = (CPUInfo[0] >> 8) & 0xf;
|
||||
nProcessorType = (CPUInfo[0] >> 12) & 0x3;
|
||||
nExtendedmodel = (CPUInfo[0] >> 16) & 0xf;
|
||||
nExtendedfamily = (CPUInfo[0] >> 20) & 0xff;
|
||||
nBrandIndex = CPUInfo[1] & 0xff;
|
||||
nCLFLUSHcachelinesize = ((CPUInfo[1] >> 8) & 0xff) * 8;
|
||||
nAPICPhysicalID = (CPUInfo[1] >> 24) & 0xff;
|
||||
bSSE3NewInstructions = (CPUInfo[2] & 0x1) || false;
|
||||
bMONITOR_MWAIT = (CPUInfo[2] & 0x8) || false;
|
||||
bCPLQualifiedDebugStore = (CPUInfo[2] & 0x10) || false;
|
||||
bThermalMonitor2 = (CPUInfo[2] & 0x100) || false;
|
||||
nFeatureInfo = CPUInfo[3];
|
||||
|
||||
if (CPUInfo[2] & (1 << 23))
|
||||
{
|
||||
bPOPCNT = true;
|
||||
}
|
||||
|
||||
if (CPUInfo[2] & (1 << 19))
|
||||
{
|
||||
bSSE4_1 = true;
|
||||
}
|
||||
|
||||
if (CPUInfo[2] & (1 << 20))
|
||||
{
|
||||
bSSE4_2 = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// Calling __cpuid with 0x80000000 as the InfoType argument
|
||||
// gets the number of valid extended IDs.
|
||||
__cpuid(CPUInfo, 0x80000000);
|
||||
nExIds = CPUInfo[0];
|
||||
memset(CPUBrandString, 0, sizeof(CPUBrandString));
|
||||
|
||||
// Get the information associated with each extended ID.
|
||||
for (unsigned int i = 0x80000000; i <= nExIds; ++i)
|
||||
{
|
||||
__cpuid(CPUInfo, i);
|
||||
|
||||
// Interpret CPU brand string and cache information.
|
||||
if (i == 0x80000001)
|
||||
{
|
||||
nFeatureInfo2 = CPUInfo[1]; // ECX
|
||||
bSSE5 = (nFeatureInfo2 & (1 << 11)) ? true : false;
|
||||
bLZCNT = (nFeatureInfo2 & (1 << 5)) ? true : false;
|
||||
bSSE4A = (nFeatureInfo2 & (1 << 6)) ? true : false;
|
||||
bLAHFSAHF64 = (nFeatureInfo2 & (1 << 0)) ? true : false;
|
||||
|
||||
CPU64bit = (CPUInfo[2] & (1 << 29)) ? true : false;
|
||||
}
|
||||
else if (i == 0x80000002)
|
||||
{
|
||||
memcpy(CPUBrandString, CPUInfo, sizeof(CPUInfo));
|
||||
}
|
||||
else if (i == 0x80000003)
|
||||
{
|
||||
memcpy(CPUBrandString + 16, CPUInfo, sizeof(CPUInfo));
|
||||
}
|
||||
else if (i == 0x80000004)
|
||||
{
|
||||
memcpy(CPUBrandString + 32, CPUInfo, sizeof(CPUInfo));
|
||||
}
|
||||
else if (i == 0x80000006)
|
||||
{
|
||||
nCacheLineSize = CPUInfo[2] & 0xff;
|
||||
nL2Associativity = (CPUInfo[2] >> 12) & 0xf;
|
||||
nCacheSizeK = (CPUInfo[2] >> 16) & 0xffff;
|
||||
}
|
||||
else if (i == 0x80000008)
|
||||
{
|
||||
int numLSB = (CPUInfo[2] >> 12) & 0xF;
|
||||
numCores = 1 << numLSB;
|
||||
//int coresPerDie = CPUInfo[2] & 0xFF;
|
||||
// numCores = coresPerDie;
|
||||
}
|
||||
}
|
||||
|
||||
// Display all the information in user-friendly format.
|
||||
// printf_s("\n\nCPU String: %s\n", CPUString);
|
||||
|
||||
if (nIds < 1)
|
||||
{
|
||||
bOldCPU = true;
|
||||
}
|
||||
|
||||
nIds = 1;
|
||||
bx87FPUOnChip = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bVirtual_8086ModeEnhancement = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bDebuggingExtensions = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPageSizeExtensions = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bTimeStampCounter = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bRDMSRandWRMSRSupport = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPhysicalAddressExtensions = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bMachineCheckException = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bCMPXCHG8BInstruction = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bAPICOnChip = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bUnknown1 = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bSYSENTERandSYSEXIT = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bMemoryTypeRangeRegisters = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPTEGlobalBit = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bMachineCheckArchitecture = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bConditionalMove_CompareInstruction = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPageAttributeTable = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPageSizeExtension = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bProcessorSerialNumber = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bCFLUSHExtension = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bUnknown2 = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bDebugStore = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bThermalMonitorandClockCtrl = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bMMXTechnology = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bFXSAVE_FXRSTOR = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bSSEExtensions = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bSSE2Extensions = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bSelfSnoop = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bHyper_threadingTechnology = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bThermalMonitor = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bUnknown4 = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
bPendBrkEN = (nFeatureInfo & nIds) ? true : false;
|
||||
nIds <<= 1;
|
||||
|
||||
if (nExIds < 0x80000004)
|
||||
{
|
||||
strcpy(CPUBrandString, "(unknown)");
|
||||
}
|
||||
}
|
||||
|
||||
|
107
Source/Core/Common/Src/CPUDetect.h
Normal file
107
Source/Core/Common/Src/CPUDetect.h
Normal file
@ -0,0 +1,107 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _CPUDETECT_H
|
||||
#define _CPUDETECT_H
|
||||
|
||||
struct CPUInfoStruct
|
||||
{
|
||||
bool isAMD;
|
||||
|
||||
bool OS64bit;
|
||||
bool CPU64bit;
|
||||
bool Mode64bit;
|
||||
int numCores;
|
||||
|
||||
char CPUString[0x20];
|
||||
char CPUBrandString[0x40];
|
||||
int CPUInfo[4];
|
||||
int nSteppingID;
|
||||
int nModel;
|
||||
int nFamily;
|
||||
int nProcessorType;
|
||||
int nExtendedmodel;
|
||||
int nExtendedfamily;
|
||||
int nBrandIndex;
|
||||
int nCLFLUSHcachelinesize;
|
||||
int nAPICPhysicalID;
|
||||
int nFeatureInfo;
|
||||
int nFeatureInfo2;
|
||||
int nCacheLineSize;
|
||||
int nL2Associativity;
|
||||
int nCacheSizeK;
|
||||
int nRet;
|
||||
unsigned int nIds, nExIds;
|
||||
|
||||
bool bMONITOR_MWAIT;
|
||||
bool bCPLQualifiedDebugStore;
|
||||
bool bThermalMonitor2;
|
||||
|
||||
bool bOldCPU;
|
||||
bool bx87FPUOnChip;
|
||||
bool bVirtual_8086ModeEnhancement;
|
||||
bool bDebuggingExtensions;
|
||||
bool bPageSizeExtensions;
|
||||
bool bTimeStampCounter;
|
||||
bool bRDMSRandWRMSRSupport;
|
||||
bool bPhysicalAddressExtensions;
|
||||
bool bMachineCheckException;
|
||||
bool bCMPXCHG8BInstruction;
|
||||
bool bAPICOnChip;
|
||||
bool bUnknown1;
|
||||
bool bSYSENTERandSYSEXIT;
|
||||
bool bMemoryTypeRangeRegisters;
|
||||
bool bPTEGlobalBit;
|
||||
bool bMachineCheckArchitecture;
|
||||
bool bConditionalMove_CompareInstruction;
|
||||
bool bPageAttributeTable;
|
||||
bool bPageSizeExtension;
|
||||
bool bProcessorSerialNumber;
|
||||
bool bCFLUSHExtension;
|
||||
bool bUnknown2;
|
||||
bool bDebugStore;
|
||||
bool bThermalMonitorandClockCtrl;
|
||||
bool bMMXTechnology;
|
||||
bool bFXSAVE_FXRSTOR;
|
||||
bool bSSEExtensions;
|
||||
bool bSSE2Extensions;
|
||||
bool bSSE3NewInstructions;
|
||||
bool bSelfSnoop;
|
||||
bool bHyper_threadingTechnology;
|
||||
bool bThermalMonitor;
|
||||
bool bUnknown4;
|
||||
bool bPendBrkEN;
|
||||
|
||||
bool bPOPCNT;
|
||||
bool bSSE4_1;
|
||||
bool bSSE4_2;
|
||||
bool bSSE5;
|
||||
bool bLZCNT;
|
||||
bool bSSE4A;
|
||||
bool bLAHFSAHF64;
|
||||
|
||||
void Detect();
|
||||
};
|
||||
|
||||
|
||||
extern CPUInfoStruct cpu_info;
|
||||
|
||||
inline void DetectCPU() {cpu_info.Detect();}
|
||||
|
||||
|
||||
#endif
|
||||
|
90
Source/Core/Common/Src/Common.cpp
Normal file
90
Source/Core/Common/Src/Common.cpp
Normal file
@ -0,0 +1,90 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdio.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "StringUtil.h"
|
||||
|
||||
namespace
|
||||
{
|
||||
PanicAlertHandler panic_handler = 0;
|
||||
}
|
||||
|
||||
void RegisterPanicAlertHandler(PanicAlertHandler handler)
|
||||
{
|
||||
panic_handler = handler;
|
||||
}
|
||||
|
||||
|
||||
void PanicAlert(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
|
||||
if (panic_handler)
|
||||
{
|
||||
std::string msg;
|
||||
StringFromFormatV(&msg, format, args);
|
||||
panic_handler(msg.c_str(), false);
|
||||
}
|
||||
else
|
||||
{
|
||||
#ifdef _WIN32
|
||||
std::string msg;
|
||||
StringFromFormatV(&msg, format, args);
|
||||
MessageBox(0, msg.c_str(), "PANIC!", MB_ICONWARNING);
|
||||
#elif __GNUC__
|
||||
//#error Do a messagebox!
|
||||
vprintf(format, args);
|
||||
printf("\n");
|
||||
#endif
|
||||
}
|
||||
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
bool PanicYesNo(const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
bool retval;
|
||||
#ifdef _WIN32
|
||||
std::string msg;
|
||||
StringFromFormatV(&msg, format, args);
|
||||
retval = IDYES == MessageBox(0, msg.c_str(), "PANIC! Continue?", MB_ICONQUESTION | MB_YESNO);
|
||||
#elif __GNUC__
|
||||
//vprintf(format, args);
|
||||
return(true); //#error Do a messagebox!
|
||||
#endif
|
||||
|
||||
va_end(args);
|
||||
return(retval);
|
||||
}
|
||||
|
||||
|
||||
// Standard implementation of logging - simply print to standard output.
|
||||
// Programs are welcome to override this.
|
||||
/*
|
||||
void __Log(int logNumber, const char *text, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, text);
|
||||
vprintf(text, args);
|
||||
va_end(args);
|
||||
}*/
|
306
Source/Core/Common/Src/Common.h
Normal file
306
Source/Core/Common/Src/Common.h
Normal file
@ -0,0 +1,306 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _COMMON_H
|
||||
#define _COMMON_H
|
||||
|
||||
#include <stdlib.h>
|
||||
|
||||
#ifdef _WIN32
|
||||
#define POSIX 0
|
||||
#define NOMINMAX
|
||||
#define WEAK_SYMBOL __declspec(selectany)
|
||||
|
||||
#if _M_IX86
|
||||
#define Crash() {__asm int 3}
|
||||
#else
|
||||
#if _MSC_VER > 1000
|
||||
extern "C" {
|
||||
__declspec(dllimport) void __stdcall DebugBreak(void);
|
||||
}
|
||||
#define Crash() {DebugBreak();}
|
||||
#else
|
||||
#error fixme
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#elif __GNUC__
|
||||
#define TCHAR char
|
||||
#define POSIX 1
|
||||
#define MAX_PATH 260
|
||||
#define WEAK_SYMBOL __attribute__((weak))
|
||||
#define stricmp strcasecmp
|
||||
#define Crash() {__builtin_trap();}
|
||||
// #ifdef 64bit
|
||||
// #define _M_IX86
|
||||
// #else
|
||||
#define _M_X64
|
||||
// #endf
|
||||
#endif
|
||||
|
||||
// Types
|
||||
|
||||
#ifdef _WIN32
|
||||
|
||||
#include <tchar.h>
|
||||
|
||||
typedef unsigned __int64 u64;
|
||||
typedef unsigned __int32 u32;
|
||||
typedef unsigned __int16 u16;
|
||||
typedef unsigned __int8 u8;
|
||||
|
||||
typedef signed __int64 s64;
|
||||
typedef signed __int32 s32;
|
||||
typedef signed __int16 s16;
|
||||
typedef signed __int8 s8;
|
||||
|
||||
#define GC_ALIGNED16(x) __declspec(align(16)) x
|
||||
#define GC_ALIGNED16_DECL(x) __declspec(align(16)) x
|
||||
|
||||
#else
|
||||
|
||||
typedef char s8;
|
||||
typedef short s16;
|
||||
#define __int16 short
|
||||
typedef int s32;
|
||||
#define __int32 int
|
||||
typedef long long s64;
|
||||
#define __int64 long long
|
||||
|
||||
typedef unsigned char u8;
|
||||
typedef unsigned char BYTE;
|
||||
typedef unsigned short u16;
|
||||
typedef unsigned int u32;
|
||||
typedef unsigned int BOOL;
|
||||
typedef unsigned int DWORD;
|
||||
typedef unsigned long long u64;
|
||||
|
||||
#ifdef __LINUX__
|
||||
typedef union _LARGE_INTEGER
|
||||
{
|
||||
long long QuadPart;
|
||||
} LARGE_INTEGER;
|
||||
#endif
|
||||
|
||||
#if defined (__MINGW32__) || defined (_WIN32)
|
||||
#define GC_ALIGNED16(x) __declspec(align(16)) x
|
||||
#define GC_ALIGNED16_DECL(x) x
|
||||
#else
|
||||
#define GC_ALIGNED16(x) x
|
||||
#define GC_ALIGNED16_DECL(x) x __attribute((aligned(16)))
|
||||
#endif
|
||||
|
||||
#ifndef __forceinline
|
||||
#define __forceinline inline
|
||||
#endif
|
||||
|
||||
#ifndef _T
|
||||
#define _T(a) a
|
||||
#endif
|
||||
|
||||
#endif
|
||||
|
||||
#if !defined (_MSC_VER) && !defined (HAVE_ALIGNED_MALLOC)
|
||||
|
||||
// declare linux equivalents
|
||||
extern __forceinline void* gc_aligned_malloc(size_t size, size_t align)
|
||||
{
|
||||
char* p = (char*)malloc(size + align);
|
||||
int off = 2 + align - ((s64)(p + 2) % align);
|
||||
|
||||
p += off;
|
||||
*(u16*)(p - 2) = off;
|
||||
|
||||
return(p);
|
||||
}
|
||||
|
||||
|
||||
extern __forceinline void gc_aligned_free(void* pmem)
|
||||
{
|
||||
if (pmem != NULL)
|
||||
{
|
||||
char* p = (char*)pmem;
|
||||
free(p - (int)*(u16*)(p - 2));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
#define _aligned_malloc gc_aligned_malloc
|
||||
#define _aligned_free gc_aligned_free
|
||||
|
||||
#endif
|
||||
|
||||
#if defined (_M_IX86) && defined (_WIN32)
|
||||
#define HWCALL __cdecl
|
||||
#else
|
||||
#define HWCALL
|
||||
#endif
|
||||
|
||||
|
||||
// Hacks
|
||||
#ifndef SAFE_DELETE
|
||||
#define SAFE_DELETE(ptr) if (ptr){delete ptr; ptr = 0;}
|
||||
#endif
|
||||
|
||||
// Common defines
|
||||
// TODO(ector,fires): turn into inline function?
|
||||
#undef min
|
||||
#undef max
|
||||
|
||||
template<class T>
|
||||
T min(const T& a, const T& b) {return(a > b ? b : a);}
|
||||
|
||||
|
||||
template<class T>
|
||||
T max(const T& a, const T& b) {return(a > b ? a : b);}
|
||||
|
||||
|
||||
|
||||
|
||||
// Byte ordering
|
||||
|
||||
namespace Common
|
||||
{
|
||||
inline u8 swap8(u8 _data) {return(_data);}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
inline u16 swap16(u16 _data) {return(_byteswap_ushort(_data));}
|
||||
|
||||
|
||||
inline u32 swap32(u32 _data) {return(_byteswap_ulong(_data));}
|
||||
|
||||
|
||||
inline u64 swap64(u64 _data) {return(_byteswap_uint64(_data));}
|
||||
|
||||
|
||||
#elif __linux__
|
||||
}
|
||||
#include <byteswap.h>
|
||||
namespace Common
|
||||
{
|
||||
inline u16 swap16(u16 _data) {return(bswap_16(_data));}
|
||||
|
||||
|
||||
inline u32 swap32(u32 _data) {return(bswap_32(_data));}
|
||||
|
||||
|
||||
inline u64 swap64(u64 _data) {return(bswap_64(_data));}
|
||||
|
||||
|
||||
#else
|
||||
inline u16 swap16(u16 data) {return((data >> 8) | (data << 8));}
|
||||
|
||||
|
||||
inline u32 swap32(u32 data) {return((swap16(data) << 16) | swap16(data >> 16));}
|
||||
|
||||
|
||||
inline u64 swap64(u64 data) {return(((u64)swap32(data) << 32) | swap32(data >> 32));}
|
||||
#endif
|
||||
|
||||
|
||||
} // end of namespace Common
|
||||
|
||||
// Utility functions
|
||||
|
||||
void PanicAlert(const char* text, ...);
|
||||
bool PanicYesNo(const char* text, ...);
|
||||
extern void __Log(int logNumber, const char* text, ...);
|
||||
|
||||
|
||||
// dummy class
|
||||
class LogTypes
|
||||
{
|
||||
public:
|
||||
|
||||
enum LOG_TYPE
|
||||
{
|
||||
MASTER_LOG,
|
||||
BOOT,
|
||||
PIXELENGINE,
|
||||
COMMANDPROCESSOR,
|
||||
VIDEOINTERFACE,
|
||||
SERIALINTERFACE,
|
||||
PERIPHERALINTERFACE,
|
||||
MEMMAP,
|
||||
DSPINTERFACE,
|
||||
STREAMINGINTERFACE,
|
||||
DVDINTERFACE,
|
||||
GPFIFO,
|
||||
EXPANSIONINTERFACE,
|
||||
AUDIO_INTERFACE,
|
||||
GEKKO,
|
||||
HLE,
|
||||
DSPHLE,
|
||||
VIDEO,
|
||||
AUDIO,
|
||||
DYNA_REC,
|
||||
OSREPORT,
|
||||
CONSOLE,
|
||||
WII_IOB,
|
||||
WII_IPC,
|
||||
WII_IPC_HLE,
|
||||
NUMBER_OF_LOGS
|
||||
};
|
||||
};
|
||||
|
||||
typedef bool (*PanicAlertHandler)(const char* text, bool yes_no);
|
||||
void RegisterPanicAlertHandler(PanicAlertHandler handler);
|
||||
|
||||
void Host_UpdateLogDisplay();
|
||||
|
||||
|
||||
// Logging macros
|
||||
#ifdef LOGGING
|
||||
|
||||
#define LOG(t, ...) __Log(LogTypes::t, __VA_ARGS__);
|
||||
|
||||
#define _dbg_assert_(_t_, _a_) \
|
||||
if (!(_a_)){\
|
||||
LOG(_t_, "Error...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", \
|
||||
__LINE__, __FILE__, __TIME__); \
|
||||
if (!PanicYesNo("*** Assertion (see log)***\n")){Crash();} \
|
||||
}
|
||||
#define _dbg_assert_msg_(_t_, _a_, ...)\
|
||||
if (!(_a_)){\
|
||||
LOG(_t_, __VA_ARGS__); \
|
||||
if (!PanicYesNo(__VA_ARGS__)){Crash();} \
|
||||
}
|
||||
#define _dbg_update_() Host_UpdateLogDisplay();
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(_t_, ...)
|
||||
#define _dbg_clear_()
|
||||
#define _dbg_assert_(_t_, _a_) ;
|
||||
#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ;
|
||||
#define _dbg_update_() ;
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
#define _assert_(_a_) _dbg_assert_(MASTER_LOG, _a_)
|
||||
#define _assert_msg_(_t_, _a_, _fmt_, ...)\
|
||||
if (!(_a_)){\
|
||||
if (!PanicYesNo(_fmt_, __VA_ARGS__)){Crash();} \
|
||||
}
|
||||
#else
|
||||
#define _assert_(a)
|
||||
#define _assert_msg_(...)
|
||||
#endif
|
||||
#endif
|
109
Source/Core/Common/Src/DynamicLibrary.cpp
Normal file
109
Source/Core/Common/Src/DynamicLibrary.cpp
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <string.h>
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <dlfcn.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "DynamicLibrary.h"
|
||||
|
||||
DynamicLibrary::DynamicLibrary()
|
||||
{
|
||||
library = 0;
|
||||
}
|
||||
|
||||
|
||||
bool DynamicLibrary::Load(const char* filename)
|
||||
{
|
||||
if (strlen(filename) == 0)
|
||||
{
|
||||
PanicAlert("DynamicLibrary : Missing filename");
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (IsLoaded())
|
||||
{
|
||||
PanicAlert("Trying to load already loaded library %s", filename);
|
||||
return(false);
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
library = LoadLibrary(filename);
|
||||
#else
|
||||
library = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
|
||||
|
||||
if (!library)
|
||||
{
|
||||
PanicAlert(dlerror());
|
||||
}
|
||||
else
|
||||
{
|
||||
printf("Successfully loaded %s", filename);
|
||||
}
|
||||
#endif
|
||||
|
||||
return(library != 0);
|
||||
}
|
||||
|
||||
|
||||
void DynamicLibrary::Unload()
|
||||
{
|
||||
if (!IsLoaded())
|
||||
{
|
||||
PanicAlert("Trying to unload non-loaded library");
|
||||
return;
|
||||
}
|
||||
|
||||
#ifdef _WIN32
|
||||
FreeLibrary(library);
|
||||
#else
|
||||
dlclose(library);
|
||||
#endif
|
||||
library = 0;
|
||||
}
|
||||
|
||||
|
||||
void* DynamicLibrary::Get(const char* funcname) const
|
||||
{
|
||||
void* retval;
|
||||
#ifdef _WIN32
|
||||
retval = GetProcAddress(library, funcname);
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
// PanicAlert("Did not find function %s in DLL", funcname);
|
||||
}
|
||||
|
||||
return(retval);
|
||||
|
||||
#else
|
||||
retval = dlsym(library, funcname);
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
printf("%s\n", dlerror());
|
||||
}
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
46
Source/Core/Common/Src/DynamicLibrary.h
Normal file
46
Source/Core/Common/Src/DynamicLibrary.h
Normal file
@ -0,0 +1,46 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _DYNAMICLIBRARY_H
|
||||
#define _DYNAMICLIBRARY_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
class DynamicLibrary
|
||||
{
|
||||
public:
|
||||
|
||||
DynamicLibrary();
|
||||
bool Load(const char* filename);
|
||||
void Unload();
|
||||
void* Get(const char* funcname) const;
|
||||
|
||||
|
||||
bool IsLoaded() const {return(library != 0);}
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
HINSTANCE library;
|
||||
#else
|
||||
void* library;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
309
Source/Core/Common/Src/HTTP.cpp
Normal file
309
Source/Core/Common/Src/HTTP.cpp
Normal file
@ -0,0 +1,309 @@
|
||||
// Under MIT licence from http://www.mindcontrol.org/~hplus/http-get.html
|
||||
|
||||
#if defined(WIN32)
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
#include <time.h>
|
||||
#else
|
||||
#include <unistd.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
#include <assert.h>
|
||||
#include <stdio.h>
|
||||
#include <string.h>
|
||||
#include <stdlib.h>
|
||||
|
||||
#include "HTTP.h"
|
||||
#include "PortableSockets.h"
|
||||
|
||||
#if !defined(WIN32)
|
||||
static int strnicmp( char const * a, char const * b, int n) {
|
||||
return strncasecmp( a, b, n );
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
struct Chunk {
|
||||
Chunk() {
|
||||
next_ = 0;
|
||||
size_ = 0;
|
||||
}
|
||||
Chunk * next_;
|
||||
size_t size_;
|
||||
char data_[ 30000 ];
|
||||
};
|
||||
|
||||
class HTTPQuery : public I_HTTPRequest {
|
||||
public:
|
||||
HTTPQuery() {
|
||||
head_ = 0;
|
||||
curRd_ = 0;
|
||||
curWr_ = 0;
|
||||
curOffset_ = 0;
|
||||
toRead_ = 0;
|
||||
complete_ = false;
|
||||
gotLength_ = false;
|
||||
socket_ = BAD_SOCKET_FD;
|
||||
}
|
||||
~HTTPQuery() {
|
||||
if (socket_ != BAD_SOCKET_FD) {
|
||||
::closesocket( socket_ );
|
||||
}
|
||||
Chunk * ch = head_;
|
||||
while( ch != 0) {
|
||||
Chunk * d = ch;
|
||||
ch = ch->next_;
|
||||
::free( d );
|
||||
}
|
||||
}
|
||||
|
||||
void setQuery( char const * host, unsigned short port, char const * url) {
|
||||
if (strlen( url ) > 1536 || strlen( host ) > 256) {
|
||||
return;
|
||||
}
|
||||
struct hostent * hent = gethostbyname( host );
|
||||
if (hent == 0) {
|
||||
complete_ = true;
|
||||
return;
|
||||
}
|
||||
addr_.sin_family = AF_INET;
|
||||
addr_.sin_addr = *(in_addr *)hent->h_addr_list[0];
|
||||
addr_.sin_port = htons( port );
|
||||
socket_ = ::socket( AF_INET, SOCK_STREAM, getprotobyname("tcp")->p_proto );
|
||||
if (socket_ == BAD_SOCKET_FD) {
|
||||
complete_ = true;
|
||||
return;
|
||||
}
|
||||
int r;
|
||||
r = ::connect( socket_, (sockaddr *)&addr_, sizeof( addr_ ) );
|
||||
if (r < 0) {
|
||||
complete_ = true;
|
||||
return;
|
||||
}
|
||||
MAKE_SOCKET_NONBLOCKING( socket_, r );
|
||||
if (r < 0) {
|
||||
complete_ = true;
|
||||
return;
|
||||
}
|
||||
char buf[2048];
|
||||
sprintf( buf, "GET %s HTTP/1.0\r\nUser-Agent: Dolphin2.0\r\nAccept: */*\r\nHost: %s\r\nConnection: close\r\n\r\n",
|
||||
url, host );
|
||||
r = ::send( socket_, buf, int(strlen( buf )), NONBLOCK_MSG_SEND );
|
||||
if (r != (int)strlen( buf )) {
|
||||
complete_ = true;
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
void dispose() {
|
||||
delete this;
|
||||
}
|
||||
void step() {
|
||||
if (!complete_) {
|
||||
if (!curWr_ || (curWr_->size_ == sizeof( curWr_->data_ ))) {
|
||||
Chunk * c = new Chunk;
|
||||
if (!head_) {
|
||||
head_ = c;
|
||||
curWr_ = c;
|
||||
}
|
||||
else {
|
||||
curWr_->next_ = c;
|
||||
curWr_ = c;
|
||||
}
|
||||
}
|
||||
assert( curWr_ && (curWr_->size_ < sizeof( curWr_->data_ )) );
|
||||
int r = ::recv( socket_, &curWr_->data_[curWr_->size_], int(sizeof(curWr_->data_)-curWr_->size_),
|
||||
NONBLOCK_MSG_SEND );
|
||||
if (r > 0) {
|
||||
curWr_->size_ += r;
|
||||
assert( curWr_->size_ <= sizeof( curWr_->data_ ) );
|
||||
if (gotLength_) {
|
||||
if (toRead_ <= size_t(r)) {
|
||||
toRead_ = 0;
|
||||
complete_ = true;
|
||||
}
|
||||
else {
|
||||
toRead_ -= r;
|
||||
}
|
||||
}
|
||||
if (!gotLength_) {
|
||||
char const * end = &head_->data_[head_->size_];
|
||||
char const * ptr = &head_->data_[1];
|
||||
while( ptr < end-1) {
|
||||
if (ptr[-1] == '\n') {
|
||||
if (!strnicmp( ptr, "content-length:", 15 )) {
|
||||
ptr += 15;
|
||||
toRead_ = strtol( ptr, (char **)&ptr, 10 );
|
||||
gotLength_ = true;
|
||||
}
|
||||
else if (ptr[0] == '\r' && ptr[1] == '\n') {
|
||||
size_t haveRead = end-ptr-2;
|
||||
if (haveRead > toRead_) {
|
||||
toRead_ = 0;
|
||||
}
|
||||
else {
|
||||
toRead_ -= haveRead;
|
||||
}
|
||||
if (toRead_ == 0) {
|
||||
complete_ = true;
|
||||
}
|
||||
break;
|
||||
}
|
||||
}
|
||||
++ptr;
|
||||
}
|
||||
}
|
||||
}
|
||||
else if (r < 0) {
|
||||
if (!SOCKET_WOULDBLOCK_ERROR( SOCKET_ERRNO )) {
|
||||
complete_ = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
bool complete() {
|
||||
step();
|
||||
return complete_;
|
||||
}
|
||||
void rewind() {
|
||||
curRd_ = head_;
|
||||
curOffset_ = 0;
|
||||
}
|
||||
size_t read( void * ptr, size_t size) {
|
||||
step();
|
||||
if (!head_) {
|
||||
return 0;
|
||||
}
|
||||
if (!curRd_) {
|
||||
curRd_ = head_;
|
||||
assert( curOffset_ == 0 );
|
||||
}
|
||||
size_t copied = 0;
|
||||
while( size > 0) {
|
||||
assert( curRd_->size_ <= sizeof( curRd_->data_ ) );
|
||||
size_t toCopy = curRd_->size_ - curOffset_;
|
||||
if (toCopy > size) {
|
||||
toCopy = size;
|
||||
}
|
||||
memcpy( ptr, &curRd_->data_[curOffset_], toCopy );
|
||||
curOffset_ += toCopy;
|
||||
assert( curOffset_ <= sizeof(curRd_->data_) );
|
||||
ptr = ((char *)ptr)+toCopy;
|
||||
size -= toCopy;
|
||||
copied += toCopy;
|
||||
if (curOffset_ == curRd_->size_) {
|
||||
if (curRd_->next_ != 0) {
|
||||
curRd_ = curRd_->next_;
|
||||
curOffset_ = 0;
|
||||
}
|
||||
else {
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return copied;
|
||||
}
|
||||
|
||||
Chunk * head_;
|
||||
Chunk * curRd_;
|
||||
Chunk * curWr_;
|
||||
size_t curOffset_;
|
||||
size_t toRead_;
|
||||
bool complete_;
|
||||
bool gotLength_;
|
||||
SOCKET socket_;
|
||||
sockaddr_in addr_;
|
||||
};
|
||||
|
||||
};
|
||||
|
||||
I_HTTPRequest * NewHTTPRequest( char const * url )
|
||||
{
|
||||
static bool socketsInited;
|
||||
if (!socketsInited) {
|
||||
socketsInited = true;
|
||||
INIT_SOCKET_LIBRARY();
|
||||
}
|
||||
if (strncmp( url, "http://", 7 )) {
|
||||
return 0;
|
||||
}
|
||||
url += 7;
|
||||
char const * path = strchr( url, '/' );
|
||||
if (!path) {
|
||||
return 0;
|
||||
}
|
||||
char name[ 256 ];
|
||||
if (path-url > 255) {
|
||||
return 0;
|
||||
}
|
||||
strncpy( name, url, path-url );
|
||||
name[path-url] = 0;
|
||||
char * port = strrchr( name, ':' );
|
||||
unsigned short iport = 80;
|
||||
if (port) {
|
||||
*port = 0;
|
||||
iport = (unsigned short)( strtol( port+1, &port, 10 ) );
|
||||
}
|
||||
HTTPQuery * q = new HTTPQuery;
|
||||
q->setQuery( name, iport, path );
|
||||
return q;
|
||||
}
|
||||
|
||||
// TODO(ector):
|
||||
// Currently extremely bad implementation - busy waits!
|
||||
std::string HTTPDownloadText(const char *url)
|
||||
{
|
||||
I_HTTPRequest *r = NewHTTPRequest(url);
|
||||
int timeout = 10;
|
||||
std::string text = "";
|
||||
time_t t;
|
||||
t = 0;
|
||||
char buf[4096];
|
||||
while (true)
|
||||
{
|
||||
r->step();
|
||||
size_t rd = r->read(buf, 4096);
|
||||
if (rd > 0)
|
||||
{
|
||||
buf[rd] = 0;
|
||||
text += buf;
|
||||
}
|
||||
else {
|
||||
if (r->complete())
|
||||
goto next;
|
||||
|
||||
if (!t) {
|
||||
time(&t);
|
||||
}
|
||||
else {
|
||||
time_t t2;
|
||||
time(&t2);
|
||||
if (t2 > t + timeout) {
|
||||
fprintf( stderr, "timeout\n");
|
||||
goto next;
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
next:
|
||||
r->dispose();
|
||||
return text;
|
||||
}
|
||||
|
||||
void UnittestMyNetwork()
|
||||
{
|
||||
I_HTTPRequest * r = NewHTTPRequest( "http://www.cisco.com/" );
|
||||
char buf[1024];
|
||||
while( !r->complete()) {
|
||||
r->step();
|
||||
while( r->read( buf, sizeof( buf ) ) )
|
||||
;
|
||||
}
|
||||
char buf2[100000];
|
||||
r->rewind();
|
||||
while( r->read( buf2, sizeof( buf2 ) ) )
|
||||
;
|
||||
r->dispose();
|
||||
}
|
34
Source/Core/Common/Src/HTTP.h
Normal file
34
Source/Core/Common/Src/HTTP.h
Normal file
@ -0,0 +1,34 @@
|
||||
// Under MIT licence from http://www.mindcontrol.org/~hplus/http-get.html
|
||||
|
||||
#if !defined( mynetwork_h )
|
||||
#define mynetwork_h
|
||||
|
||||
#include <string>
|
||||
|
||||
// I_HTTPRequest will run until it's received all available data
|
||||
// from the query. You can rewind and read the data received just
|
||||
// like a regular stream. Reading will return 0 bytes when at the
|
||||
// end, even if the query isn't yet complete. Test for completeness
|
||||
// with complete(). You need to step() the query every so often to
|
||||
// retrieve more data. Calling complete() and rewind() may step
|
||||
// the query.
|
||||
class I_HTTPRequest {
|
||||
public:
|
||||
virtual ~I_HTTPRequest() {}
|
||||
virtual void dispose() = 0;
|
||||
virtual void step() = 0;
|
||||
virtual bool complete() = 0;
|
||||
virtual void rewind() = 0;
|
||||
virtual size_t read(void * ptr, size_t data) = 0;
|
||||
};
|
||||
|
||||
// The format of "url" is "http://host:port/path". Name resolution
|
||||
// will be done synchronously, which can be a problem.
|
||||
// This request will NOT deal with user names and passwords. You
|
||||
// have been warned!
|
||||
I_HTTPRequest * NewHTTPRequest(char const * url);
|
||||
|
||||
std::string HTTPDownloadText(const char *url);
|
||||
|
||||
#endif
|
||||
|
138
Source/Core/Common/Src/Hash.cpp
Normal file
138
Source/Core/Common/Src/Hash.cpp
Normal file
@ -0,0 +1,138 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Hash.h"
|
||||
|
||||
// uint32_t
|
||||
// WARNING - may read one more byte!
|
||||
// Implementation from Wikipedia.
|
||||
u32 HashFletcher(const u8* data_u8, size_t length)
|
||||
{
|
||||
const u16* data = (const u16*)data_u8; /* Pointer to the data to be summed */
|
||||
size_t len = (length + 1) / 2; /* Length in 16-bit words */
|
||||
u32 sum1 = 0xffff, sum2 = 0xffff;
|
||||
|
||||
while (len)
|
||||
{
|
||||
size_t tlen = len > 360 ? 360 : len;
|
||||
len -= tlen;
|
||||
|
||||
do {
|
||||
sum1 += *data++;
|
||||
sum2 += sum1;
|
||||
}
|
||||
while (--tlen);
|
||||
|
||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
}
|
||||
|
||||
/* Second reduction step to reduce sums to 16 bits */
|
||||
sum1 = (sum1 & 0xffff) + (sum1 >> 16);
|
||||
sum2 = (sum2 & 0xffff) + (sum2 >> 16);
|
||||
return(sum2 << 16 | sum1);
|
||||
}
|
||||
|
||||
|
||||
// Implementation from Wikipedia
|
||||
// Slightly slower than Fletcher above, but slighly more reliable.
|
||||
#define MOD_ADLER 65521
|
||||
// data: Pointer to the data to be summed; len is in bytes
|
||||
u32 HashAdler32(const u8* data, size_t len)
|
||||
{
|
||||
u32 a = 1, b = 0;
|
||||
|
||||
while (len)
|
||||
{
|
||||
size_t tlen = len > 5550 ? 5550 : len;
|
||||
len -= tlen;
|
||||
|
||||
do
|
||||
{
|
||||
a += *data++;
|
||||
b += a;
|
||||
}
|
||||
while (--tlen);
|
||||
|
||||
a = (a & 0xffff) + (a >> 16) * (65536 - MOD_ADLER);
|
||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
||||
}
|
||||
|
||||
// It can be shown that a <= 0x1013a here, so a single subtract will do.
|
||||
if (a >= MOD_ADLER)
|
||||
{
|
||||
a -= MOD_ADLER;
|
||||
}
|
||||
|
||||
// It can be shown that b can reach 0xfff87 here.
|
||||
b = (b & 0xffff) + (b >> 16) * (65536 - MOD_ADLER);
|
||||
|
||||
if (b >= MOD_ADLER)
|
||||
{
|
||||
b -= MOD_ADLER;
|
||||
}
|
||||
|
||||
return((b << 16) | a);
|
||||
}
|
||||
|
||||
|
||||
// Another fast and decent hash
|
||||
u32 HashFNV(const u8* ptr, int length)
|
||||
{
|
||||
u32 hash = 0x811c9dc5;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
hash *= 1677761;
|
||||
hash ^= ptr[i];
|
||||
}
|
||||
|
||||
return(hash);
|
||||
}
|
||||
|
||||
|
||||
// Another fast and decent hash
|
||||
u32 HashFNV1(const u8* ptr, int length)
|
||||
{
|
||||
u32 hash = 0x811c9dc5;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
hash *= 1677761;
|
||||
hash ^= ptr[i];
|
||||
}
|
||||
|
||||
return(hash);
|
||||
}
|
||||
|
||||
|
||||
// Terribly stupid hash - but can't go back now :)
|
||||
// Don't use for new things. At least it's fast.
|
||||
u32 HashEctor(const u8* ptr, int length)
|
||||
{
|
||||
u32 crc = 0;
|
||||
|
||||
for (int i = 0; i < length; i++)
|
||||
{
|
||||
crc ^= ptr[i];
|
||||
crc = (crc << 3) | (crc >> 29);
|
||||
}
|
||||
|
||||
return(crc);
|
||||
}
|
||||
|
||||
|
28
Source/Core/Common/Src/Hash.h
Normal file
28
Source/Core/Common/Src/Hash.h
Normal file
@ -0,0 +1,28 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _HASH_H
|
||||
#define _HASH_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
u32 HashFletcher(const u8* data_u8, size_t length); // FAST
|
||||
u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightly slower
|
||||
u32 HashFNV(const u8* ptr, int length); // Another fast and decent hash
|
||||
u32 HashEctor(const u8* ptr, int length); // JUNK. DO NOT USE FOR NEW THINGS
|
||||
|
||||
|
||||
#endif
|
464
Source/Core/Common/Src/IniFile.cpp
Normal file
464
Source/Core/Common/Src/IniFile.cpp
Normal file
@ -0,0 +1,464 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
// see IniFile.h
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
#include <iostream>
|
||||
#include <fstream>
|
||||
#include <algorithm>
|
||||
|
||||
#include "StringUtil.h"
|
||||
#include "IniFile.h"
|
||||
|
||||
IniFile::IniFile()
|
||||
{}
|
||||
|
||||
|
||||
IniFile::~IniFile()
|
||||
{}
|
||||
|
||||
|
||||
Section::Section()
|
||||
: name(""), comment(""), lines() {}
|
||||
|
||||
|
||||
Section::Section(const std::string& _name)
|
||||
: name(_name), comment(""), lines() {}
|
||||
|
||||
|
||||
Section::Section(const Section& other)
|
||||
{
|
||||
name = other.name;
|
||||
comment = other.comment;
|
||||
lines = other.lines;
|
||||
}
|
||||
|
||||
|
||||
Section* IniFile::GetSection(const char* sectionName)
|
||||
{
|
||||
for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||
{
|
||||
if (!strcmp(iter->name.c_str(), sectionName))
|
||||
{
|
||||
return(&(*iter));
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
Section* IniFile::GetOrCreateSection(const char* sectionName)
|
||||
{
|
||||
Section* section = GetSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
{
|
||||
sections.push_back(Section(sectionName));
|
||||
section = §ions[sections.size() - 1];
|
||||
}
|
||||
|
||||
return(section);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::DeleteSection(const char* sectionName)
|
||||
{
|
||||
Section* s = GetSection(sectionName);
|
||||
|
||||
if (!s)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
for (std::vector<Section>::iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||
{
|
||||
if (&(*iter) == s)
|
||||
{
|
||||
sections.erase(iter);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
void IniFile::ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut)
|
||||
{
|
||||
// allow many types of commenting
|
||||
// These MUST be signed! Do not change to size_t
|
||||
int firstEquals = (int)line.find("=", 0);
|
||||
int firstCommentChar = (int)line.find(";", 0);
|
||||
|
||||
if (firstCommentChar < 0){firstCommentChar = (int)line.find("#", firstEquals > 0 ? firstEquals : 0);}
|
||||
|
||||
if (firstCommentChar < 0){firstCommentChar = (int)line.find("//", firstEquals > 0 ? firstEquals : 0);}
|
||||
|
||||
// allow preserval of spacing before comment
|
||||
if (firstCommentChar > 0)
|
||||
{
|
||||
while (line[firstCommentChar - 1] == ' ' || line[firstCommentChar - 1] == 9) // 9 == tab
|
||||
{
|
||||
firstCommentChar--;
|
||||
}
|
||||
}
|
||||
|
||||
if ((firstEquals >= 0) && ((firstCommentChar < 0) || (firstEquals < firstCommentChar)))
|
||||
{
|
||||
// Yes, a valid line!
|
||||
*keyOut = StripSpaces(line.substr(0, firstEquals));
|
||||
|
||||
if (commentOut)
|
||||
{
|
||||
*commentOut = firstCommentChar > 0 ? line.substr(firstCommentChar) : std::string("");
|
||||
}
|
||||
|
||||
if (valueOut)
|
||||
{
|
||||
*valueOut = StripQuotes(StripSpaces(line.substr(firstEquals + 1, firstCommentChar - firstEquals - 1)));
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
std::string* IniFile::GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut)
|
||||
{
|
||||
for (std::vector<std::string>::iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||
{
|
||||
std::string& line = *iter;
|
||||
std::string lineKey;
|
||||
ParseLine(line, &lineKey, valueOut, commentOut);
|
||||
|
||||
if (!stricmp(lineKey.c_str(), key))
|
||||
{
|
||||
return(&line);
|
||||
}
|
||||
}
|
||||
|
||||
return(0);
|
||||
}
|
||||
|
||||
|
||||
void IniFile::Set(const char* sectionName, const char* key, const char* newValue)
|
||||
{
|
||||
Section* section = GetOrCreateSection(sectionName);
|
||||
std::string value, comment;
|
||||
std::string* line = GetLine(section, key, &value, &comment);
|
||||
|
||||
if (line)
|
||||
{
|
||||
// Change the value - keep the key and comment
|
||||
*line = StripSpaces(key) + " = " + newValue + comment;
|
||||
}
|
||||
else
|
||||
{
|
||||
// The key did not already exist in this section - let's add it.
|
||||
section->lines.push_back(std::string(key) + " = " + newValue);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void IniFile::Set(const char* sectionName, const char* key, u32 newValue)
|
||||
{
|
||||
Set(sectionName, key, StringFromFormat("0x%08x", newValue).c_str());
|
||||
}
|
||||
|
||||
|
||||
void IniFile::Set(const char* sectionName, const char* key, int newValue)
|
||||
{
|
||||
Set(sectionName, key, StringFromInt(newValue).c_str());
|
||||
}
|
||||
|
||||
|
||||
void IniFile::Set(const char* sectionName, const char* key, bool newValue)
|
||||
{
|
||||
Set(sectionName, key, StringFromBool(newValue).c_str());
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue)
|
||||
{
|
||||
Section* section = GetSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
{
|
||||
if (defaultValue)
|
||||
{
|
||||
*value = defaultValue;
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
std::string* line = GetLine(section, key, value, 0);
|
||||
|
||||
if (!line)
|
||||
{
|
||||
if (defaultValue)
|
||||
{
|
||||
*value = defaultValue;
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Get(const char* sectionName, const char* key, int* value, int defaultValue)
|
||||
{
|
||||
std::string temp;
|
||||
bool retval = Get(sectionName, key, &temp, 0);
|
||||
|
||||
if (retval && TryParseInt(temp.c_str(), value))
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
*value = defaultValue;
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Get(const char* sectionName, const char* key, u32* value, u32 defaultValue)
|
||||
{
|
||||
std::string temp;
|
||||
bool retval = Get(sectionName, key, &temp, 0);
|
||||
|
||||
if (retval && TryParseUInt(temp.c_str(), value))
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
*value = defaultValue;
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Get(const char* sectionName, const char* key, bool* value, bool defaultValue)
|
||||
{
|
||||
std::string temp;
|
||||
bool retval = Get(sectionName, key, &temp, 0);
|
||||
|
||||
if (retval && TryParseBool(temp.c_str(), value))
|
||||
{
|
||||
return(true);
|
||||
}
|
||||
|
||||
*value = defaultValue;
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::DeleteKey(const char* sectionName, const char* key)
|
||||
{
|
||||
Section* section = GetSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
std::string* line = GetLine(section, key, 0, 0);
|
||||
|
||||
for (std::vector<std::string>::iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
|
||||
{
|
||||
if (line == &(*liter))
|
||||
{
|
||||
section->lines.erase(liter);
|
||||
return(true);
|
||||
}
|
||||
}
|
||||
|
||||
return(false); //shouldn't happen
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Load(const char* filename)
|
||||
{
|
||||
sections.clear();
|
||||
sections.push_back(Section(""));
|
||||
//first section consists of the comments before the first real section
|
||||
|
||||
std::ifstream in;
|
||||
in.open(filename, std::ios::in);
|
||||
|
||||
if (in.fail())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
while (!in.eof())
|
||||
{
|
||||
char templine[512];
|
||||
in.getline(templine, 512);
|
||||
std::string line = templine;
|
||||
|
||||
if (in.eof())
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
if (line.size() > 0)
|
||||
{
|
||||
if (line[0] == '[')
|
||||
{
|
||||
int endpos = (int)line.find("]");
|
||||
|
||||
if (endpos != std::string::npos)
|
||||
{
|
||||
// New section!
|
||||
std::string sub = line.substr(1, endpos - 1);
|
||||
sections.push_back(Section(sub));
|
||||
|
||||
if (endpos + 1 < line.size())
|
||||
{
|
||||
sections[sections.size() - 1].comment = line.substr(endpos + 1);
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
sections[sections.size() - 1].lines.push_back(line);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
in.close();
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::Save(const char* filename)
|
||||
{
|
||||
std::ofstream out;
|
||||
out.open(filename, std::ios::out);
|
||||
|
||||
if (out.fail())
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
for (std::vector<Section>::const_iterator iter = sections.begin(); iter != sections.end(); ++iter)
|
||||
{
|
||||
const Section& section = *iter;
|
||||
|
||||
if (section.name != "")
|
||||
{
|
||||
out << "[" << section.name << "]" << section.comment << std::endl;
|
||||
}
|
||||
|
||||
for (std::vector<std::string>::const_iterator liter = section.lines.begin(); liter != section.lines.end(); ++liter)
|
||||
{
|
||||
std::string s = *liter;
|
||||
out << s << std::endl;
|
||||
}
|
||||
}
|
||||
|
||||
out.close();
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::GetKeys(const char* sectionName, std::vector<std::string>& keys)
|
||||
{
|
||||
Section* section = GetSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
keys.clear();
|
||||
|
||||
for (std::vector<std::string>::const_iterator liter = section->lines.begin(); liter != section->lines.end(); ++liter)
|
||||
{
|
||||
std::string key;
|
||||
ParseLine(*liter, &key, 0, 0);
|
||||
keys.push_back(key);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool IniFile::GetLines(const char* sectionName, std::vector<std::string>& lines)
|
||||
{
|
||||
Section* section = GetSection(sectionName);
|
||||
|
||||
if (!section)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
lines.clear();
|
||||
|
||||
for (std::vector<std::string>::const_iterator iter = section->lines.begin(); iter != section->lines.end(); ++iter)
|
||||
{
|
||||
std::string line = StripSpaces(*iter);
|
||||
int commentPos = (int)line.find('#');
|
||||
|
||||
if (commentPos == 0)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
if (commentPos != (int)std::string::npos)
|
||||
{
|
||||
line = StripSpaces(line.substr(0, commentPos));
|
||||
}
|
||||
|
||||
lines.push_back(line);
|
||||
}
|
||||
|
||||
lines = section->lines;
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
void IniFile::SortSections()
|
||||
{
|
||||
std::sort(sections.begin(), sections.end());
|
||||
}
|
||||
|
||||
|
||||
/*
|
||||
int main()
|
||||
{
|
||||
IniFile ini;
|
||||
ini.Load("my.ini");
|
||||
ini.Set("Hej", "A", "amaskdfl");
|
||||
ini.Set("Mossa", "A", "amaskdfl");
|
||||
ini.Set("Aissa", "A", "amaskdfl");
|
||||
//ini.Read("my.ini");
|
||||
std::string x;
|
||||
ini.Get("Hej", "B", &x, "boo");
|
||||
ini.DeleteKey("Mossa", "A");
|
||||
ini.DeleteSection("Mossa");
|
||||
ini.SortSections();
|
||||
ini.Save("my.ini");
|
||||
//UpdateVars(ini);
|
||||
return 0;
|
||||
}
|
||||
*/
|
||||
|
92
Source/Core/Common/Src/IniFile.h
Normal file
92
Source/Core/Common/Src/IniFile.h
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _INIFILE_H
|
||||
#define _INIFILE_H
|
||||
|
||||
#include <string>
|
||||
#include <vector>
|
||||
|
||||
#include "StringUtil.h"
|
||||
|
||||
class Section
|
||||
{
|
||||
public:
|
||||
|
||||
Section();
|
||||
Section(const std::string& _name);
|
||||
Section(const Section& other);
|
||||
std::vector<std::string>lines;
|
||||
std::string name;
|
||||
std::string comment;
|
||||
|
||||
bool operator<(const Section& other) const
|
||||
{
|
||||
return(name < other.name);
|
||||
}
|
||||
};
|
||||
|
||||
class IniFile
|
||||
{
|
||||
public:
|
||||
|
||||
IniFile();
|
||||
~IniFile();
|
||||
|
||||
bool Load(const char* filename);
|
||||
bool Save(const char* filename);
|
||||
|
||||
void Set(const char* sectionName, const char* key, const char* newValue);
|
||||
void Set(const char* sectionName, const char* key, int newValue);
|
||||
void Set(const char* sectionName, const char* key, u32 newValue);
|
||||
void Set(const char* sectionName, const char* key, bool newValue);
|
||||
|
||||
|
||||
void Set(const char* sectionName, const char* key, const std::string& newValue) {Set(sectionName, key, newValue.c_str());}
|
||||
|
||||
|
||||
void Set(const char* sectionName, const char* key, const std::vector<std::string>& newValues);
|
||||
|
||||
bool Get(const char* sectionName, const char* key, std::string* value, const char* defaultValue = "");
|
||||
bool Get(const char* sectionName, const char* key, int* value, int defaultValue = 0);
|
||||
bool Get(const char* sectionName, const char* key, u32* value, u32 defaultValue = 0);
|
||||
bool Get(const char* sectionName, const char* key, bool* value, bool defaultValue = false);
|
||||
bool Get(const char* sectionName, const char* key, std::vector<std::string>& values);
|
||||
|
||||
bool GetKeys(const char* sectionName, std::vector<std::string>& keys);
|
||||
bool GetLines(const char* sectionName, std::vector<std::string>& lines);
|
||||
|
||||
bool DeleteKey(const char* sectionName, const char* key);
|
||||
bool DeleteSection(const char* sectionName);
|
||||
|
||||
void SortSections();
|
||||
|
||||
void ParseLine(const std::string& line, std::string* keyOut, std::string* valueOut, std::string* commentOut);
|
||||
std::string* GetLine(Section* section, const char* key, std::string* valueOut, std::string* commentOut);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
std::vector<Section>sections;
|
||||
|
||||
Section* GetSection(const char* section);
|
||||
Section* GetOrCreateSection(const char* section);
|
||||
std::string* GetLine(const char* section, const char* key);
|
||||
void CreateSection(const char* section);
|
||||
};
|
||||
|
||||
#endif
|
95
Source/Core/Common/Src/Logging.cpp
Normal file
95
Source/Core/Common/Src/Logging.cpp
Normal file
@ -0,0 +1,95 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#if 0
|
||||
|
||||
#include "Logging.h"
|
||||
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// constructor
|
||||
//
|
||||
CDebugger_Log::CDebugger_Log(const char* _szShortName, const char* _szName)
|
||||
: m_pFile(NULL),
|
||||
m_bLogToFile(false),
|
||||
m_bShowInLog(false),
|
||||
m_bEnable(false)
|
||||
{
|
||||
strcpy((char*)m_szName, _szName);
|
||||
strcpy((char*)m_szShortName, _szShortName);
|
||||
sprintf((char*)m_szFilename, "logs\\%s.txt", _szShortName);
|
||||
|
||||
_unlink(m_szFilename);
|
||||
}
|
||||
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// destructor
|
||||
//
|
||||
CDebugger_Log::~CDebugger_Log(void)
|
||||
{
|
||||
if (m_pFile)
|
||||
{
|
||||
fclose(m_pFile);
|
||||
m_pFile = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CDebugger_Log::LoadSettings(IniFile& ini)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp, "%s_LogToFile", m_szShortName);
|
||||
ini.Get("Logging", temp, &m_bLogToFile, false);
|
||||
|
||||
sprintf(temp, "%s_ShowInLog", m_szShortName);
|
||||
ini.Get("Logging", temp, &m_bShowInLog, true);
|
||||
|
||||
sprintf(temp, "%s_Enable", m_szShortName);
|
||||
ini.Get("Logging", temp, &m_bEnable, true);
|
||||
}
|
||||
|
||||
|
||||
void CDebugger_Log::SaveSettings(IniFile& ini)
|
||||
{
|
||||
char temp[256];
|
||||
sprintf(temp, "%s_LogToFile", m_szShortName);
|
||||
ini.Set("Logging", temp, m_bLogToFile);
|
||||
sprintf(temp, "%s_ShowInLog", m_szShortName);
|
||||
ini.Set("Logging", temp, m_bShowInLog);
|
||||
sprintf(temp, "%s_Enable", m_szShortName);
|
||||
ini.Set("Logging", temp, m_bEnable);
|
||||
}
|
||||
|
||||
|
||||
// __________________________________________________________________________________________________
|
||||
// Init
|
||||
//
|
||||
void
|
||||
CDebugger_Log::Init(void)
|
||||
{
|
||||
if (m_pFile != NULL)
|
||||
{
|
||||
fclose(m_pFile);
|
||||
m_pFile = NULL;
|
||||
}
|
||||
|
||||
// reopen the file and rewrite it
|
||||
m_pFile = fopen(m_szFilename, "wt");
|
||||
}
|
||||
|
||||
|
||||
#endif
|
92
Source/Core/Common/Src/Logging.h
Normal file
92
Source/Core/Common/Src/Logging.h
Normal file
@ -0,0 +1,92 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#if 0
|
||||
|
||||
// THESE WILL BE REPLACED WITH A CLEANED UP LOGGING SYSTEM
|
||||
|
||||
#ifndef _LOGGING_H
|
||||
#define _LOGGING_H
|
||||
|
||||
class IniFile;
|
||||
|
||||
// should be inside the LogManager ...
|
||||
struct CDebugger_Log
|
||||
{
|
||||
char m_szName[128];
|
||||
char m_szShortName[10];
|
||||
char m_szFilename[256];
|
||||
bool m_bLogToFile;
|
||||
bool m_bShowInLog;
|
||||
bool m_bEnable;
|
||||
FILE* m_pFile;
|
||||
|
||||
void Init(void);
|
||||
|
||||
|
||||
// constructor
|
||||
CDebugger_Log(const char* _szShortName, const char* _szName);
|
||||
|
||||
// destructor
|
||||
~CDebugger_Log(void);
|
||||
};
|
||||
|
||||
|
||||
#ifdef LOGGING
|
||||
|
||||
#define LOG(_t_, ...) LogManager::Log(LogManager::_t_, __VA_ARGS__);
|
||||
|
||||
#define _dbg_assert_(_t_, _a_)\
|
||||
if (!(_a_)){\
|
||||
char szError[512]; \
|
||||
sprintf_s(szError, 512, "Error localized at...\n\n Line: %d\n File: %s\n Time: %s\n\nIgnore and continue?", __LINE__, __FILE__, __TIMESTAMP__); \
|
||||
LOG(_t_, szError); \
|
||||
if (MessageBox(NULL, szError, "*** Assertion Report ***", MB_YESNO | MB_ICONERROR) == IDNO){Crash();} \
|
||||
}
|
||||
#define _dbg_assert_msg_(_t_, _a_, _fmt_, ...)\
|
||||
if (!(_a_)){\
|
||||
char szError[582], szError2[512]; \
|
||||
sprintf_s(szError2, 512, _fmt_, __VA_ARGS__); \
|
||||
sprintf_s(szError, 582, "Desc.: %s\n\nIgnore and continue?", szError2); \
|
||||
LOG(_t_, szError); \
|
||||
if (MessageBox(NULL, szError, "*** Fatal Error ***", MB_YESNO | MB_ICONERROR) == IDNO){Crash();} \
|
||||
}
|
||||
|
||||
#else
|
||||
|
||||
#define LOG(_t_, ...)
|
||||
#define _dbg_clear_()
|
||||
#define _dbg_assert_(_t_, _a_) ;
|
||||
#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ;
|
||||
#define _dbg_update_() ;
|
||||
|
||||
#endif
|
||||
|
||||
#define _assert_msg_(_t_, _a_, _fmt_, ...)\
|
||||
if (!(_a_)){\
|
||||
char szError[582], szError2[512]; \
|
||||
sprintf_s(szError2, 512, _fmt_, __VA_ARGS__); \
|
||||
sprintf_s(szError, 582, "Desc.: %s\n\nIgnore and continue?", szError2); \
|
||||
LOG(_t_, szError); \
|
||||
if (MessageBox(NULL, szError, "*** Fatal Error ***", MB_YESNO | MB_ICONERROR) == IDNO){Crash();} \
|
||||
}
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
#endif
|
232
Source/Core/Common/Src/MappedFile.cpp
Normal file
232
Source/Core/Common/Src/MappedFile.cpp
Normal file
@ -0,0 +1,232 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif __linux__
|
||||
#include <unistd.h>
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "MappedFile.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class CMappedFile
|
||||
: public IMappedFile
|
||||
{
|
||||
public:
|
||||
|
||||
CMappedFile(void);
|
||||
~CMappedFile(void);
|
||||
bool Open(const char* _szFilename);
|
||||
bool IsOpen(void);
|
||||
void Close(void);
|
||||
u64 GetSize(void);
|
||||
u8* Lock(u64 _offset, u64 _size);
|
||||
void Unlock(u8* ptr);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
u64 size;
|
||||
|
||||
typedef std::map<u8*, u8*>Lockmap;
|
||||
Lockmap lockMap;
|
||||
#ifdef _WIN32
|
||||
HANDLE hFile;
|
||||
HANDLE hFileMapping;
|
||||
#elif POSIX
|
||||
int fd;
|
||||
typedef std::map<u8*, size_t>Sizemap;
|
||||
Sizemap sizeMap;
|
||||
#endif
|
||||
|
||||
int granularity;
|
||||
};
|
||||
|
||||
|
||||
CMappedFile::CMappedFile()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
SYSTEM_INFO info;
|
||||
GetSystemInfo(&info);
|
||||
granularity = (int)info.dwAllocationGranularity;
|
||||
#elif POSIX
|
||||
fd = -1;
|
||||
granularity = getpagesize(); //sysconf(_SC_PAGE_SIZE);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
CMappedFile::~CMappedFile()
|
||||
{
|
||||
Close();
|
||||
}
|
||||
|
||||
|
||||
bool CMappedFile::Open(const char* filename)
|
||||
{
|
||||
Close();
|
||||
#ifdef _WIN32
|
||||
hFile = CreateFile(filename, GENERIC_READ, FILE_SHARE_READ, 0, OPEN_EXISTING, FILE_ATTRIBUTE_NORMAL, 0);
|
||||
|
||||
if (hFile == INVALID_HANDLE_VALUE)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
hFileMapping = CreateFileMapping(hFile, 0, PAGE_READONLY, 0, 0, NULL);
|
||||
|
||||
if (hFileMapping == NULL)
|
||||
{
|
||||
CloseHandle(hFile);
|
||||
hFile = 0;
|
||||
return(false);
|
||||
}
|
||||
|
||||
u32 high = 0;
|
||||
u32 low = GetFileSize(hFile, (LPDWORD)&high);
|
||||
size = (u64)low | ((u64)high << 32);
|
||||
#elif POSIX
|
||||
fd = open(filename, O_RDONLY);
|
||||
size = 0; //TODO
|
||||
#endif
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool CMappedFile::IsOpen()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(hFile != INVALID_HANDLE_VALUE);
|
||||
|
||||
#elif POSIX
|
||||
return(fd != -1);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
u64 CMappedFile::GetSize()
|
||||
{
|
||||
return(size);
|
||||
}
|
||||
|
||||
|
||||
void CMappedFile::Close()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
{
|
||||
CloseHandle(hFileMapping);
|
||||
CloseHandle(hFile);
|
||||
lockMap.clear();
|
||||
hFile = INVALID_HANDLE_VALUE;
|
||||
}
|
||||
|
||||
#elif POSIX
|
||||
if (fd != -1)
|
||||
{
|
||||
lockMap.clear();
|
||||
sizeMap.clear();
|
||||
close(fd);
|
||||
}
|
||||
|
||||
fd = -1;
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u8* CMappedFile::Lock(u64 offset, u64 size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
if (hFile != INVALID_HANDLE_VALUE)
|
||||
#elif POSIX
|
||||
if (fd != -1)
|
||||
#endif
|
||||
{
|
||||
u64 realOffset = offset & ~(granularity - 1);
|
||||
s64 difference = offset - realOffset;
|
||||
u64 fake_size = ((offset & 4095) + size + 4095) & 4095;
|
||||
#ifdef _WIN32
|
||||
u8* realPtr = (u8*)MapViewOfFile(hFileMapping, FILE_MAP_READ, (DWORD)(realOffset >> 32), (DWORD)realOffset, (SIZE_T)(size));
|
||||
|
||||
if (realPtr == NULL)
|
||||
{
|
||||
return(NULL);
|
||||
}
|
||||
|
||||
#elif POSIX
|
||||
// TODO
|
||||
u8* realPtr = (u8*)mmap(0, fake_size, PROT_READ, MAP_PRIVATE, fd, (off_t)realOffset);
|
||||
|
||||
if (!realPtr)
|
||||
{
|
||||
PanicAlert("Map Failed");
|
||||
exit(0);
|
||||
}
|
||||
#endif
|
||||
|
||||
u8* fakePtr = realPtr + difference;
|
||||
//add to map
|
||||
lockMap[fakePtr] = realPtr;
|
||||
#ifndef _WIN32
|
||||
sizeMap[fakePtr] = size + difference;
|
||||
#endif
|
||||
return(fakePtr);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void CMappedFile::Unlock(u8* ptr)
|
||||
{
|
||||
if (ptr != 0)
|
||||
{
|
||||
Lockmap::iterator iter = lockMap.find(ptr);
|
||||
|
||||
if (iter != lockMap.end())
|
||||
{
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile((*iter).second);
|
||||
#else
|
||||
munmap((*iter).second, sizeMap[ptr]);
|
||||
#endif
|
||||
lockMap.erase(iter);
|
||||
}
|
||||
else
|
||||
{
|
||||
PanicAlert("CMappedFile : Unlock failed");
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
IMappedFile* IMappedFile::CreateMappedFile(void)
|
||||
{
|
||||
return(new CMappedFile);
|
||||
}
|
||||
} // end of namespace Common
|
51
Source/Core/Common/Src/MappedFile.h
Normal file
51
Source/Core/Common/Src/MappedFile.h
Normal file
@ -0,0 +1,51 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
// Handles giant memory mapped files
|
||||
// Through some trickery, allows lock on byte boundaries
|
||||
// instead of allocation granularity boundaries
|
||||
// for ease of use
|
||||
//
|
||||
|
||||
#ifndef _MAPPED_FILE_H
|
||||
#define _MAPPED_FILE_H
|
||||
|
||||
// #pragma warning (disable: 4786)
|
||||
|
||||
#include <map>
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class IMappedFile
|
||||
{
|
||||
public:
|
||||
|
||||
virtual ~IMappedFile() {}
|
||||
|
||||
|
||||
virtual bool Open(const char* _szFilename) = 0;
|
||||
virtual bool IsOpen(void) = 0;
|
||||
virtual void Close(void) = 0;
|
||||
virtual u64 GetSize(void) = 0;
|
||||
virtual u8* Lock(u64 _offset, u64 _size) = 0;
|
||||
virtual void Unlock(u8* ptr) = 0;
|
||||
|
||||
static IMappedFile* CreateMappedFile();
|
||||
};
|
||||
} // end of namespace DiscIO
|
||||
|
||||
#endif
|
||||
|
44
Source/Core/Common/Src/MathUtil.cpp
Normal file
44
Source/Core/Common/Src/MathUtil.cpp
Normal file
@ -0,0 +1,44 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "MathUtil.h"
|
||||
|
||||
static u32 saved_sse_state = _mm_getcsr();
|
||||
static const u32 default_sse_state = _mm_getcsr();
|
||||
|
||||
|
||||
void LoadDefaultSSEState()
|
||||
{
|
||||
_mm_setcsr(default_sse_state);
|
||||
}
|
||||
|
||||
|
||||
void LoadSSEState()
|
||||
{
|
||||
_mm_setcsr(saved_sse_state);
|
||||
}
|
||||
|
||||
|
||||
void SaveSSEState()
|
||||
{
|
||||
saved_sse_state = _mm_getcsr();
|
||||
}
|
||||
|
||||
|
35
Source/Core/Common/Src/MathUtil.h
Normal file
35
Source/Core/Common/Src/MathUtil.h
Normal file
@ -0,0 +1,35 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _MATH_UTIL_H
|
||||
#define _MATH_UTIL_H
|
||||
|
||||
#include <xmmintrin.h>
|
||||
|
||||
/*
|
||||
There are two different flavors of float to int conversion:
|
||||
_mm_cvtps_epi32() and _mm_cvttps_epi32(). The first rounds
|
||||
according to the MXCSR rounding bits. The second one always
|
||||
uses round towards zero.
|
||||
*/
|
||||
|
||||
void SaveSSEState();
|
||||
void LoadSSEState();
|
||||
void LoadDefaultSSEState();
|
||||
|
||||
|
||||
#endif
|
126
Source/Core/Common/Src/MemArena.cpp
Normal file
126
Source/Core/Common/Src/MemArena.cpp
Normal file
@ -0,0 +1,126 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#else
|
||||
#include <sys/mman.h>
|
||||
#include <sys/stat.h>
|
||||
#include <fcntl.h>
|
||||
#include <unistd.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
#include "MemArena.h"
|
||||
|
||||
|
||||
const char* ram_temp_file = "/tmp/gc_mem.tmp";
|
||||
|
||||
void MemArena::GrabLowMemSpace(size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
hMemoryMapping = CreateFileMapping(NULL, NULL, PAGE_READWRITE, 0, (DWORD)(size), _T("All GC Memory"));
|
||||
#else
|
||||
mode_t mode = S_IRUSR | S_IWUSR | S_IRGRP | S_IROTH;
|
||||
fd = open(ram_temp_file, O_RDWR | O_CREAT, mode);
|
||||
ftruncate(fd, size);
|
||||
return;
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MemArena::ReleaseSpace()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CloseHandle(hMemoryMapping);
|
||||
hMemoryMapping = 0;
|
||||
#else
|
||||
close(fd);
|
||||
unlink(ram_temp_file);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void* MemArena::CreateView(s64 offset, size_t size, bool ensure_low_mem)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(MapViewOfFile(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size));
|
||||
|
||||
#else
|
||||
void* ptr = mmap(0, size,
|
||||
PROT_READ | PROT_WRITE,
|
||||
MAP_SHARED | (ensure_low_mem ? MAP_32BIT : 0),
|
||||
fd, offset);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
PanicAlert("Failed to create view");
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void* MemArena::CreateViewAt(s64 offset, size_t size, void* base)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
return(MapViewOfFileEx(hMemoryMapping, FILE_MAP_ALL_ACCESS, 0, (DWORD)((u64)offset), size, base));
|
||||
|
||||
#else
|
||||
return(mmap(base, size, PROT_READ | PROT_WRITE, MAP_SHARED | MAP_FIXED, fd, offset));
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void MemArena::ReleaseView(void* view, size_t size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
UnmapViewOfFile(view);
|
||||
#else
|
||||
munmap(view, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
u64 MemArena::Find4GBBase()
|
||||
{
|
||||
#ifdef _M_X64
|
||||
#ifdef _WIN32
|
||||
u8* base = (u8*)VirtualAlloc(0, 0x100000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
return((u64)base);
|
||||
|
||||
#else
|
||||
// Very precarious - mmap cannot return an error when trying to map already used pages.
|
||||
// This makes the Windows approach above unusable on Linux, so we will simply pray...
|
||||
return(0x2300000000ULL);
|
||||
#endif
|
||||
|
||||
#else
|
||||
// Only grab a bit less than 1GB
|
||||
u8* base = (u8*)VirtualAlloc(0, 0x31000000, MEM_RESERVE, PAGE_READWRITE);
|
||||
VirtualFree(base, 0, MEM_RELEASE);
|
||||
return((u64)base);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
56
Source/Core/Common/Src/MemArena.h
Normal file
56
Source/Core/Common/Src/MemArena.h
Normal file
@ -0,0 +1,56 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _MEMARENA_H
|
||||
#define _MEMARENA_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
// This class lets you create a block of anonymous RAM, and then arbitrarily map views into it.
|
||||
// Multiple views can mirror the same section of the block, which makes it very convient for emulating
|
||||
// memory mirrors.
|
||||
// Pass ensure_low_mem = true to CreateView if you want arbitrarily positioned views to end up in the low 2GB.
|
||||
|
||||
class MemArena
|
||||
{
|
||||
public:
|
||||
|
||||
void GrabLowMemSpace(size_t size);
|
||||
void ReleaseSpace();
|
||||
void* CreateView(s64 offset, size_t size, bool ensure_low_mem = false);
|
||||
void* CreateViewAt(s64 offset, size_t size, void* base);
|
||||
void ReleaseView(void* view, size_t size);
|
||||
|
||||
|
||||
// This only finds 1 GB in 32-bit
|
||||
static u64 Find4GBBase();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE hMemoryMapping;
|
||||
#else
|
||||
int fd;
|
||||
#endif
|
||||
};
|
||||
|
||||
#endif
|
123
Source/Core/Common/Src/MemoryUtil.cpp
Normal file
123
Source/Core/Common/Src/MemoryUtil.cpp
Normal file
@ -0,0 +1,123 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
#include "MemoryUtil.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif __GNUC__
|
||||
#include <sys/mman.h>
|
||||
#include <errno.h>
|
||||
#include <stdio.h>
|
||||
#endif
|
||||
|
||||
// MacOSX does not support MAP_VARIABLE
|
||||
#ifndef MAP_VARIABLE
|
||||
#define MAP_VARIABLE 0
|
||||
#endif
|
||||
|
||||
// This is purposedely not a full wrapper for virtualalloc/mmap, but it
|
||||
// provides exactly the primitive operations that Dolphin needs.
|
||||
|
||||
void* AllocateExecutableMemory(int size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_EXECUTE_READWRITE);
|
||||
|
||||
if ((u64)ptr >= 0x80000000)
|
||||
{
|
||||
PanicAlert("Executable memory ended up above 2GB! WTF!");
|
||||
// If this happens, we have to implement a free ram search scheme. ector knows how.
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
|
||||
#else
|
||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE | PROT_EXEC,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // | MAP_FIXED
|
||||
printf("mappah exe %p %i\n", retval, size);
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
PanicAlert("Failed to allocate executable memory, errno=%i", errno);
|
||||
}
|
||||
|
||||
return(retval);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void* AllocateMemoryPages(int size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
void* ptr = VirtualAlloc(0, size, MEM_COMMIT, PAGE_READWRITE);
|
||||
|
||||
if (!ptr)
|
||||
{
|
||||
PanicAlert("Failed to allocate raw memory");
|
||||
}
|
||||
|
||||
return(ptr);
|
||||
|
||||
#else
|
||||
void* retval = mmap(0, size, PROT_READ | PROT_WRITE,
|
||||
MAP_ANONYMOUS | MAP_PRIVATE, -1, 0); // | MAP_FIXED
|
||||
printf("mappah %p %i\n", retval, size);
|
||||
|
||||
if (!retval)
|
||||
{
|
||||
PanicAlert("Failed to allocate raw memory, errno=%i", errno);
|
||||
}
|
||||
|
||||
return(retval);
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
|
||||
void FreeMemoryPages(void* ptr, int size)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
VirtualFree(ptr, size, MEM_RELEASE);
|
||||
#else
|
||||
munmap(ptr, size);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void WriteProtectMemory(void* ptr, int size, bool allowExecute)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READ : PAGE_READONLY, 0);
|
||||
#else
|
||||
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_EXEC) : PROT_READ);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void UnWriteProtectMemory(void* ptr, int size, bool allowExecute)
|
||||
{
|
||||
#ifdef _WIN32
|
||||
VirtualProtect(ptr, size, allowExecute ? PAGE_EXECUTE_READWRITE : PAGE_READONLY, 0);
|
||||
#else
|
||||
mprotect(ptr, size, allowExecute ? (PROT_READ | PROT_WRITE | PROT_EXEC) : PROT_WRITE | PROT_READ);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
31
Source/Core/Common/Src/MemoryUtil.h
Normal file
31
Source/Core/Common/Src/MemoryUtil.h
Normal file
@ -0,0 +1,31 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _MEMORYUTIL_H
|
||||
#define _MEMORYUTIL_H
|
||||
|
||||
void* AllocateExecutableMemory(int size);
|
||||
void* AllocateMemoryPages(int size);
|
||||
void FreeMemoryPages(void* ptr, int size);
|
||||
void WriteProtectMemory(void* ptr, int size, bool executable = false);
|
||||
void UnWriteProtectMemory(void* ptr, int size, bool allowExecute);
|
||||
|
||||
|
||||
inline int GetPageSize() {return(4096);}
|
||||
|
||||
|
||||
#endif
|
80
Source/Core/Common/Src/Plugin.cpp
Normal file
80
Source/Core/Common/Src/Plugin.cpp
Normal file
@ -0,0 +1,80 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "plugin.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
DynamicLibrary CPlugin::m_hInstLib;
|
||||
|
||||
void(__cdecl * CPlugin::m_GetDllInfo) (PLUGIN_INFO * _PluginInfo) = 0;
|
||||
void(__cdecl * CPlugin::m_DllAbout) (HWND _hParent) = 0;
|
||||
void(__cdecl * CPlugin::m_DllConfig) (HWND _hParent) = 0;
|
||||
|
||||
void
|
||||
CPlugin::Release(void)
|
||||
{
|
||||
m_GetDllInfo = 0;
|
||||
m_DllAbout = 0;
|
||||
m_DllConfig = 0;
|
||||
|
||||
m_hInstLib.Unload();
|
||||
}
|
||||
|
||||
bool
|
||||
CPlugin::Load(const char* _szName)
|
||||
{
|
||||
if (m_hInstLib.Load(_szName))
|
||||
{
|
||||
m_GetDllInfo = (void (__cdecl*)(PLUGIN_INFO*))m_hInstLib.Get("GetDllInfo");
|
||||
m_DllAbout = (void (__cdecl*)(HWND))m_hInstLib.Get("DllAbout");
|
||||
m_DllConfig = (void (__cdecl*)(HWND))m_hInstLib.Get("DllConfig");
|
||||
return(true);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
bool CPlugin::GetInfo(PLUGIN_INFO& _pluginInfo)
|
||||
{
|
||||
if (m_GetDllInfo != 0)
|
||||
{
|
||||
m_GetDllInfo(&_pluginInfo);
|
||||
return(true);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
void CPlugin::Config(HWND _hwnd)
|
||||
{
|
||||
if (m_DllConfig != 0)
|
||||
{
|
||||
m_DllConfig(_hwnd);
|
||||
}
|
||||
}
|
||||
|
||||
void CPlugin::About(HWND _hwnd)
|
||||
{
|
||||
if (m_DllAbout != 0)
|
||||
{
|
||||
m_DllAbout(_hwnd);
|
||||
}
|
||||
}
|
||||
} // end of namespace Common
|
50
Source/Core/Common/Src/Plugin.h
Normal file
50
Source/Core/Common/Src/Plugin.h
Normal file
@ -0,0 +1,50 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _PLUGIN_H
|
||||
#define _PLUGIN_H
|
||||
|
||||
#include "Common.h"
|
||||
#include "../../../PluginSpecs/PluginSpecs.h"
|
||||
#include "DynamicLibrary.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class CPlugin
|
||||
{
|
||||
public:
|
||||
|
||||
static void Release(void);
|
||||
static bool Load(const char* _szName);
|
||||
|
||||
static bool GetInfo(PLUGIN_INFO& _pluginInfo);
|
||||
|
||||
static void Config(HWND _hwnd);
|
||||
static void About(HWND _hwnd);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
static DynamicLibrary m_hInstLib;
|
||||
|
||||
static void (__cdecl * m_GetDllInfo)(PLUGIN_INFO* _PluginInfo);
|
||||
static void (__cdecl * m_DllAbout)(HWND _hParent);
|
||||
static void (__cdecl * m_DllConfig)(HWND _hParent);
|
||||
};
|
||||
} // end of namespace Common
|
||||
|
||||
#endif
|
550
Source/Core/Common/Src/PortableSockets.cpp
Normal file
550
Source/Core/Common/Src/PortableSockets.cpp
Normal file
@ -0,0 +1,550 @@
|
||||
// Under MIT licence from http://www.mindcontrol.org/~hplus/http-get.html
|
||||
|
||||
#include "PortableSockets.h"
|
||||
|
||||
#if NEED_GETTIMEOFDAY
|
||||
#if defined( _WIN32 )
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <sys/timeb.h>
|
||||
#include <math.h>
|
||||
#include <assert.h>
|
||||
#include <mmsystem.h>
|
||||
|
||||
#pragma comment( lib, "winmm.lib" )
|
||||
//#pragma comment( lib, "ws2_32.lib" )
|
||||
|
||||
|
||||
namespace {
|
||||
|
||||
// This class could be made cheaper using RDTSC for short-term
|
||||
// measurement. But, whatever.
|
||||
class init_gettimeofday
|
||||
{
|
||||
public:
|
||||
init_gettimeofday()
|
||||
{
|
||||
timeBeginPeriod( 2 );
|
||||
__int64 rr;
|
||||
QueryPerformanceFrequency( (LARGE_INTEGER *)&rr );
|
||||
ticksPerSecInv_ = 1.0 / (double)((DWORD)rr & 0xffffffff);
|
||||
int watchdog = 0;
|
||||
again:
|
||||
lastTicks_ = timeGetTime();
|
||||
QueryPerformanceCounter( (LARGE_INTEGER *)&lastRead_ );
|
||||
timeb tb;
|
||||
ftime( &tb );
|
||||
timeOffset_ = tb.time + tb.millitm * 0.001 - lastRead_ * ticksPerSecInv_;
|
||||
lastTime_ = timeOffset_;
|
||||
// make sure it didn't take too long
|
||||
if( watchdog++ < 10 && (timeGetTime() != lastTicks_) ) {
|
||||
goto again;
|
||||
}
|
||||
}
|
||||
~init_gettimeofday()
|
||||
{
|
||||
timeEndPeriod( 2 );
|
||||
}
|
||||
|
||||
void get( timeval * tv )
|
||||
{
|
||||
__int64 nu;
|
||||
int watchdog = 0;
|
||||
again:
|
||||
DWORD m = timeGetTime();
|
||||
QueryPerformanceCounter( (LARGE_INTEGER *)&nu );
|
||||
DWORD n = timeGetTime();
|
||||
// guard against pre-emption
|
||||
if( (watchdog++ < 10) && (n != m) ) {
|
||||
goto again;
|
||||
}
|
||||
double nuTime = nu * ticksPerSecInv_ + timeOffset_;
|
||||
if( (nu - lastRead_) & 0x7fffffff80000000ULL ) {
|
||||
// there's a chance that we're seeing a jump-ahead
|
||||
double adjust = (nuTime - lastTime_ - (n - lastTicks_) * 0.001);
|
||||
if( adjust > 0.1f ) {
|
||||
timeOffset_ -= adjust;
|
||||
nuTime -= adjust;
|
||||
assert( nuTime >= lastTime_ );
|
||||
}
|
||||
}
|
||||
lastRead_ = nu;
|
||||
lastTicks_ = n;
|
||||
lastTime_ = nuTime;
|
||||
tv->tv_sec = (ulong)floor( nuTime );
|
||||
tv->tv_usec = (ulong)(1000000 * (nuTime - tv->tv_sec));
|
||||
}
|
||||
|
||||
double ticksPerSecInv_;
|
||||
double timeOffset_;
|
||||
double lastTime_;
|
||||
__int64 lastRead_;
|
||||
DWORD lastTicks_;
|
||||
};
|
||||
|
||||
}
|
||||
|
||||
void gettimeofday( timeval * tv, int )
|
||||
{
|
||||
static init_gettimeofday data;
|
||||
data.get( tv );
|
||||
}
|
||||
|
||||
#else
|
||||
#error "don't know how to do this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
#if NEED_WINDOWS_POLL
|
||||
#if defined( WIN32 )
|
||||
|
||||
#include <assert.h>
|
||||
#include <winsock2.h>
|
||||
#include <windows.h>
|
||||
|
||||
// This is somewhat less than ideal -- better would be if we could
|
||||
// abstract pollfd enough that it's non-copying on Windows.
|
||||
int poll( pollfd * iofds, size_t count, int ms )
|
||||
{
|
||||
FD_SET rd, wr, ex;
|
||||
FD_ZERO( &rd );
|
||||
FD_ZERO( &wr );
|
||||
FD_ZERO( &ex );
|
||||
SOCKET m = 0;
|
||||
for( size_t ix = 0; ix < count; ++ix ) {
|
||||
iofds[ix].revents = 0;
|
||||
if( iofds[ix].fd >= m ) {
|
||||
m = iofds[ix].fd + 1;
|
||||
}
|
||||
if( iofds[ix].events & (POLLIN | POLLPRI) ) {
|
||||
assert( rd.fd_count < FD_SETSIZE );
|
||||
rd.fd_array[ rd.fd_count++ ] = iofds[ix].fd;
|
||||
}
|
||||
if( iofds[ix].events & (POLLOUT) ) {
|
||||
assert( wr.fd_count < FD_SETSIZE );
|
||||
wr.fd_array[ wr.fd_count++ ] = iofds[ix].fd;
|
||||
}
|
||||
assert( ex.fd_count < FD_SETSIZE );
|
||||
ex.fd_array[ ex.fd_count++ ] = iofds[ix].fd;
|
||||
}
|
||||
timeval tv;
|
||||
tv.tv_sec = ms/1000;
|
||||
tv.tv_usec = (ms - (tv.tv_sec * 1000)) * 1000;
|
||||
int r = 0;
|
||||
if( m == 0 ) {
|
||||
::Sleep( ms );
|
||||
}
|
||||
else {
|
||||
r = ::select( (int)m, (rd.fd_count ? &rd : 0), (wr.fd_count ? &wr : 0), (ex.fd_count ? &ex : 0), &tv );
|
||||
}
|
||||
if( r < 0 ) {
|
||||
int err = WSAGetLastError();
|
||||
errno = err;
|
||||
return r;
|
||||
}
|
||||
r = 0;
|
||||
for( size_t ix = 0; ix < count; ++ix ) {
|
||||
for( size_t iy = 0; iy < rd.fd_count; ++iy ) {
|
||||
if( rd.fd_array[ iy ] == iofds[ix].fd ) {
|
||||
iofds[ix].revents |= POLLIN;
|
||||
++r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for( size_t iy = 0; iy < wr.fd_count; ++iy ) {
|
||||
if( wr.fd_array[ iy ] == iofds[ix].fd ) {
|
||||
iofds[ix].revents |= POLLOUT;
|
||||
++r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
for( size_t iy = 0; iy < ex.fd_count; ++iy ) {
|
||||
if( ex.fd_array[ iy ] == iofds[ix].fd ) {
|
||||
iofds[ix].revents |= POLLERR;
|
||||
++r;
|
||||
break;
|
||||
}
|
||||
}
|
||||
}
|
||||
return r;
|
||||
}
|
||||
|
||||
#else
|
||||
#error "don't know how to do this"
|
||||
#endif
|
||||
#endif
|
||||
|
||||
|
||||
#if NEED_FIREWALL_ENABLE
|
||||
#if defined( WIN32 )
|
||||
|
||||
#undef _WIN32_WINNT
|
||||
#define _WIN32_WINNT 0x500
|
||||
|
||||
#include <objbase.h>
|
||||
#include <oleauto.h>
|
||||
//#include <netfw.h>
|
||||
|
||||
/*
|
||||
#define _ASSERT assert
|
||||
|
||||
namespace {
|
||||
|
||||
HRESULT WindowsFirewallInitialize(OUT INetFwProfile** fwProfile)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
INetFwMgr* fwMgr = NULL;
|
||||
INetFwPolicy* fwPolicy = NULL;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
|
||||
*fwProfile = NULL;
|
||||
|
||||
// Create an instance of the firewall settings manager.
|
||||
hr = CoCreateInstance(
|
||||
__uuidof(NetFwMgr),
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(INetFwMgr),
|
||||
(void**)&fwMgr
|
||||
);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("CoCreateInstance failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Retrieve the local firewall policy.
|
||||
hr = fwMgr->get_LocalPolicy(&fwPolicy);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("get_LocalPolicy failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Retrieve the firewall profile currently in effect.
|
||||
hr = fwPolicy->get_CurrentProfile(fwProfile);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("get_CurrentProfile failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
// Release the local firewall policy.
|
||||
if (fwPolicy != NULL)
|
||||
{
|
||||
fwPolicy->Release();
|
||||
}
|
||||
|
||||
// Release the firewall settings manager.
|
||||
if (fwMgr != NULL)
|
||||
{
|
||||
fwMgr->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
void WindowsFirewallCleanup(IN INetFwProfile* fwProfile)
|
||||
{
|
||||
// Release the firewall profile.
|
||||
if (fwProfile != NULL)
|
||||
{
|
||||
fwProfile->Release();
|
||||
}
|
||||
}
|
||||
|
||||
HRESULT WindowsFirewallAppIsEnabled(
|
||||
IN INetFwProfile* fwProfile,
|
||||
IN const wchar_t* fwProcessImageFileName,
|
||||
OUT BOOL* fwAppEnabled
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BSTR fwBstrProcessImageFileName = NULL;
|
||||
VARIANT_BOOL fwEnabled;
|
||||
INetFwAuthorizedApplication* fwApp = NULL;
|
||||
INetFwAuthorizedApplications* fwApps = NULL;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
_ASSERT(fwProcessImageFileName != NULL);
|
||||
_ASSERT(fwAppEnabled != NULL);
|
||||
|
||||
*fwAppEnabled = FALSE;
|
||||
|
||||
// Retrieve the authorized application collection.
|
||||
hr = fwProfile->get_AuthorizedApplications(&fwApps);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("get_AuthorizedApplications failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Allocate a BSTR for the process image file name.
|
||||
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
|
||||
if (SysStringLen(fwBstrProcessImageFileName) == 0)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
printf("SysAllocString failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Attempt to retrieve the authorized application.
|
||||
hr = fwApps->Item(fwBstrProcessImageFileName, &fwApp);
|
||||
if (SUCCEEDED(hr))
|
||||
{
|
||||
// Find out if the authorized application is enabled.
|
||||
hr = fwApp->get_Enabled(&fwEnabled);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("get_Enabled failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
if (fwEnabled != VARIANT_FALSE)
|
||||
{
|
||||
// The authorized application is enabled.
|
||||
*fwAppEnabled = TRUE;
|
||||
|
||||
printf(
|
||||
"Authorized application %lS is enabled in the firewall.\n",
|
||||
fwProcessImageFileName
|
||||
);
|
||||
}
|
||||
else
|
||||
{
|
||||
printf(
|
||||
"Authorized application %lS is disabled in the firewall.\n",
|
||||
fwProcessImageFileName
|
||||
);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// The authorized application was not in the collection.
|
||||
hr = S_OK;
|
||||
|
||||
printf(
|
||||
"Authorized application %lS is disabled in the firewall.\n",
|
||||
fwProcessImageFileName
|
||||
);
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
// Free the BSTR.
|
||||
SysFreeString(fwBstrProcessImageFileName);
|
||||
|
||||
// Release the authorized application instance.
|
||||
if (fwApp != NULL)
|
||||
{
|
||||
fwApp->Release();
|
||||
}
|
||||
|
||||
// Release the authorized application collection.
|
||||
if (fwApps != NULL)
|
||||
{
|
||||
fwApps->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
|
||||
HRESULT WindowsFirewallAddApp(
|
||||
IN INetFwProfile* fwProfile,
|
||||
IN const wchar_t* fwProcessImageFileName,
|
||||
IN const wchar_t* fwName
|
||||
)
|
||||
{
|
||||
HRESULT hr = S_OK;
|
||||
BOOL fwAppEnabled;
|
||||
BSTR fwBstrName = NULL;
|
||||
BSTR fwBstrProcessImageFileName = NULL;
|
||||
INetFwAuthorizedApplication* fwApp = NULL;
|
||||
INetFwAuthorizedApplications* fwApps = NULL;
|
||||
|
||||
_ASSERT(fwProfile != NULL);
|
||||
_ASSERT(fwProcessImageFileName != NULL);
|
||||
_ASSERT(fwName != NULL);
|
||||
|
||||
// First check to see if the application is already authorized.
|
||||
hr = WindowsFirewallAppIsEnabled(
|
||||
fwProfile,
|
||||
fwProcessImageFileName,
|
||||
&fwAppEnabled
|
||||
);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("WindowsFirewallAppIsEnabled failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Only add the application if it isn't already authorized.
|
||||
if (!fwAppEnabled)
|
||||
{
|
||||
// Retrieve the authorized application collection.
|
||||
hr = fwProfile->get_AuthorizedApplications(&fwApps);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("get_AuthorizedApplications failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Create an instance of an authorized application.
|
||||
hr = CoCreateInstance(
|
||||
__uuidof(NetFwAuthorizedApplication),
|
||||
NULL,
|
||||
CLSCTX_INPROC_SERVER,
|
||||
__uuidof(INetFwAuthorizedApplication),
|
||||
(void**)&fwApp
|
||||
);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("CoCreateInstance failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Allocate a BSTR for the process image file name.
|
||||
fwBstrProcessImageFileName = SysAllocString(fwProcessImageFileName);
|
||||
if (SysStringLen(fwBstrProcessImageFileName) == 0)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
printf("SysAllocString failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set the process image file name.
|
||||
hr = fwApp->put_ProcessImageFileName(fwBstrProcessImageFileName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("put_ProcessImageFileName failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Allocate a BSTR for the application friendly name.
|
||||
fwBstrName = SysAllocString(fwName);
|
||||
if (SysStringLen(fwBstrName) == 0)
|
||||
{
|
||||
hr = E_OUTOFMEMORY;
|
||||
printf("SysAllocString failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Set the application friendly name.
|
||||
hr = fwApp->put_Name(fwBstrName);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("put_Name failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Add the application to the collection.
|
||||
hr = fwApps->Add(fwApp);
|
||||
if (FAILED(hr))
|
||||
{
|
||||
printf("Add failed: 0x%08lx\n", hr);
|
||||
goto error;
|
||||
}
|
||||
|
||||
printf(
|
||||
"Authorized application %lS is now enabled in the firewall.\n",
|
||||
fwProcessImageFileName
|
||||
);
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
// Free the BSTRs.
|
||||
SysFreeString(fwBstrName);
|
||||
SysFreeString(fwBstrProcessImageFileName);
|
||||
|
||||
// Release the authorized application instance.
|
||||
if (fwApp != NULL)
|
||||
{
|
||||
fwApp->Release();
|
||||
}
|
||||
|
||||
// Release the authorized application collection.
|
||||
if (fwApps != NULL)
|
||||
{
|
||||
fwApps->Release();
|
||||
}
|
||||
|
||||
return hr;
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
bool ENABLE_FIREWALL()
|
||||
{
|
||||
BOOL couldEnable = false;
|
||||
HRESULT hr = S_OK;
|
||||
HRESULT comInit = E_FAIL;
|
||||
INetFwProfile* fwProfile = NULL;
|
||||
|
||||
// Initialize COM.
|
||||
#if 1
|
||||
comInit = CoInitialize( 0 );
|
||||
#else
|
||||
comInit = CoInitializeEx(
|
||||
0,
|
||||
COINIT_APARTMENTTHREADED //| COINIT_DISABLE_OLE1DDE
|
||||
);
|
||||
#endif
|
||||
|
||||
// Ignore RPC_E_CHANGED_MODE; this just means that COM has already been
|
||||
// initialized with a different mode. Since we don't care what the mode is,
|
||||
// we'll just use the existing mode.
|
||||
if (comInit != RPC_E_CHANGED_MODE) {
|
||||
hr = comInit;
|
||||
if (FAILED(hr)) {
|
||||
fprintf( stderr, "CoInitializeEx failed: 0x%08lx\n", hr );
|
||||
goto error;
|
||||
}
|
||||
}
|
||||
|
||||
// Retrieve the firewall profile currently in effect.
|
||||
hr = WindowsFirewallInitialize(&fwProfile);
|
||||
if (FAILED(hr)) {
|
||||
fprintf( stderr, "WindowsFirewallInitialize failed: 0x%08lx\n", hr );
|
||||
goto error;
|
||||
}
|
||||
|
||||
HMODULE hm = GetModuleHandle( 0 );
|
||||
wchar_t path[512];
|
||||
if( !GetModuleFileNameW( hm, path, sizeof(path)/sizeof(wchar_t) ) ) {
|
||||
fprintf( stderr, "GetModuleFileName() failed: 0x%lx\n", GetLastError() );
|
||||
goto error;
|
||||
}
|
||||
|
||||
// Add the application to the authorized application collection.
|
||||
hr = WindowsFirewallAddApp(
|
||||
fwProfile,
|
||||
path,
|
||||
L"Introduction Library User"
|
||||
);
|
||||
if (FAILED(hr)) {
|
||||
fprintf( stderr, "WindowsFirewallAddApp failed: 0x%08lx\n", hr );
|
||||
goto error;
|
||||
}
|
||||
|
||||
error:
|
||||
|
||||
WindowsFirewallCleanup(fwProfile);
|
||||
|
||||
if (SUCCEEDED(comInit)) {
|
||||
CoUninitialize();
|
||||
}
|
||||
|
||||
return couldEnable != FALSE;
|
||||
}
|
||||
*/
|
||||
|
||||
#else
|
||||
#error "don't know how to do this"
|
||||
#endif
|
||||
|
||||
#endif
|
189
Source/Core/Common/Src/PortableSockets.h
Normal file
189
Source/Core/Common/Src/PortableSockets.h
Normal file
@ -0,0 +1,189 @@
|
||||
// Under MIT licence from http://www.mindcontrol.org/~hplus/http-get.html
|
||||
|
||||
#if !defined( sock_port_h )
|
||||
#define sock_port_h
|
||||
|
||||
// There are differences between Linux/Berkeley sockets and WinSock2
|
||||
// This file wraps some of the more common ones (as used by this library).
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#if defined( WIN32 )
|
||||
|
||||
// Windows features go here
|
||||
#include <Winsock2.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#if !defined( NEED_SHORT_TYPES )
|
||||
#define NEED_SHORT_TYPES 1
|
||||
#endif
|
||||
#if !defined( NEED_WINDOWS_POLL )
|
||||
#define NEED_WINDOWS_POLL 1
|
||||
#endif
|
||||
#if !defined( NEED_GETTIMEOFDAY )
|
||||
#define NEED_GETTIMEOFDAY 1
|
||||
#endif
|
||||
#if !defined( NEED_SNPRINTF )
|
||||
#define NEED_SNPRINTF 1
|
||||
#endif
|
||||
#if !defined( NEED_HSTRERROR )
|
||||
#define NEED_HSTRERROR 1
|
||||
#endif
|
||||
#if !defined( NEED_GETLASTERROR )
|
||||
#define NEED_GETLASTERROR 1
|
||||
#endif
|
||||
#if !defined( NEED_FIREWALL_ENABLE )
|
||||
#define NEED_FIREWALL_ENABLE 1
|
||||
#endif
|
||||
|
||||
typedef int socklen_t;
|
||||
#define MSG_NOSIGNAL 0
|
||||
#define MAKE_SOCKET_NONBLOCKING(x,r) \
|
||||
do { u_long _x = 1; (r) = ioctlsocket( (x), FIONBIO, &_x ); } while(0)
|
||||
#define NONBLOCK_MSG_SEND 0
|
||||
#define INIT_SOCKET_LIBRARY() \
|
||||
do { WSADATA wsaData; WSAStartup( MAKEWORD(2,2), &wsaData ); } while(0)
|
||||
|
||||
#pragma warning( disable: 4250 )
|
||||
|
||||
#define SIN_ADDR_UINT(x) \
|
||||
((uint&)(x).S_un.S_addr)
|
||||
#define BAD_SOCKET_FD 0xffffffffU
|
||||
|
||||
#else
|
||||
|
||||
// Linux features go here
|
||||
#include <sys/types.h>
|
||||
#include <sys/socket.h>
|
||||
#include <netdb.h>
|
||||
#include <sys/time.h>
|
||||
#include <sys/poll.h>
|
||||
|
||||
#if !defined( NEED_CLOSESOCKET )
|
||||
#define NEED_CLOSESOCKET 1
|
||||
#endif
|
||||
#if !defined( NEED_IOCTLSOCKET )
|
||||
#define NEED_IOCTLSOCKET 1
|
||||
#endif
|
||||
#if !defined( NEED_SHORT_TYPES )
|
||||
#define NEED_SHORT_TYPES 1
|
||||
#endif
|
||||
#if !defined( NEED_ERRNO )
|
||||
#define NEED_ERRNO 1
|
||||
#endif
|
||||
|
||||
extern int h_errno;
|
||||
// hack -- I don't make it non-blocking; instead, I pass
|
||||
// NONBLOCK_MSG_SEND for each call to sendto()
|
||||
#define MAKE_SOCKET_NONBLOCKING(x,r) do { (r) = 0; } while(0)
|
||||
#define NONBLOCK_MSG_SEND MSG_DONTWAIT
|
||||
#define INIT_SOCKET_LIBRARY() do {} while(0)
|
||||
|
||||
#if !defined( SOCKET )
|
||||
#define SOCKET int
|
||||
#endif
|
||||
#define SIN_ADDR_UINT(x) \
|
||||
((uint&)(x).s_addr)
|
||||
#define BAD_SOCKET_FD -1
|
||||
|
||||
#endif
|
||||
|
||||
#if NEED_CLOSESOCKET
|
||||
#define closesocket close
|
||||
#endif
|
||||
|
||||
#if NEED_PROTOENT
|
||||
struct protoent {
|
||||
int p_proto;
|
||||
};
|
||||
#endif
|
||||
#if NEED_GETPROTOBYNAME
|
||||
inline protoent * getprotobyname( char const * s ) {
|
||||
static protoent p;
|
||||
if( !strcmp( s, "udp" ) ) {
|
||||
p.p_proto = IPPROTO_UDP;
|
||||
return &p;
|
||||
}
|
||||
if( !strcmp( s, "tcp" ) ) {
|
||||
p.p_proto = IPPROTO_TCP;
|
||||
return &p;
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NEED_SHORT_TYPES
|
||||
typedef unsigned long ulong;
|
||||
typedef unsigned int uint;
|
||||
typedef unsigned short ushort;
|
||||
typedef unsigned char uchar;
|
||||
#endif
|
||||
|
||||
#if NEED_WINDOWS_POLL
|
||||
struct pollfd {
|
||||
SOCKET fd;
|
||||
unsigned short events;
|
||||
unsigned short revents;
|
||||
};
|
||||
#define POLLIN 0x1
|
||||
#define POLLPRI 0x2
|
||||
#define POLLOUT 0x4
|
||||
#define POLLERR 0x100
|
||||
#define POLLHUP 0x200
|
||||
#define POLLNVAL 0x8000
|
||||
int poll( pollfd * iofds, size_t count, int ms );
|
||||
#endif
|
||||
|
||||
#if NEED_GETTIMEOFDAY
|
||||
// this is not thread safe!
|
||||
void gettimeofday( timeval * otv, int );
|
||||
#endif
|
||||
|
||||
#if NEED_SNPRINTF
|
||||
inline int vsnprintf( char * buf, int size, char const * fmt, va_list vl ) {
|
||||
int r = _vsnprintf( buf, size, fmt, vl );
|
||||
if( r < 0 ) {
|
||||
buf[size-1] = 0;
|
||||
r = size-1;
|
||||
}
|
||||
return r;
|
||||
}
|
||||
inline int snprintf( char * buf, int size, char const * fmt, ... ) {
|
||||
va_list vl;
|
||||
va_start( vl, fmt );
|
||||
int r = vsnprintf( buf, size, fmt, vl );
|
||||
va_end( vl );
|
||||
return r;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NEED_HSTRERROR
|
||||
// NOT thread safe!
|
||||
inline char const * hstrerror( ulong ec ) {
|
||||
static char err[ 128 ];
|
||||
snprintf( err, 128, "host error 0x%lx", ec );
|
||||
return err;
|
||||
}
|
||||
#endif
|
||||
|
||||
#if NEED_GETLASTERROR
|
||||
#define SOCKET_ERRNO WSAGetLastError()
|
||||
inline bool SOCKET_WOULDBLOCK_ERROR( int e ) { return e == WSAEWOULDBLOCK; }
|
||||
inline bool SOCKET_NEED_REOPEN( int e ) { return e == WSAECONNRESET; }
|
||||
#endif
|
||||
|
||||
#if NEED_ERRNO
|
||||
#include <errno.h>
|
||||
#define SOCKET_ERRNO errno
|
||||
inline bool SOCKET_WOULDBLOCK_ERROR( int e ) { return e == EWOULDBLOCK; }
|
||||
inline bool SOCKET_NEED_REOPEN( int e ) { return false; }
|
||||
#endif
|
||||
|
||||
#if NEED_FIREWALL_ENABLE
|
||||
extern bool ENABLE_FIREWALL();
|
||||
#else
|
||||
#define ENABLE_FIREWALL() true
|
||||
#endif
|
||||
|
||||
#endif // sock_port_h
|
||||
|
25
Source/Core/Common/Src/SConscript
Normal file
25
Source/Core/Common/Src/SConscript
Normal file
@ -0,0 +1,25 @@
|
||||
Import('env')
|
||||
|
||||
files = ["Common.cpp",
|
||||
"CPUDetect.cpp",
|
||||
"DynamicLibrary.cpp",
|
||||
"Hash.cpp",
|
||||
"HTTP.cpp",
|
||||
"IniFile.cpp",
|
||||
"Logging.cpp",
|
||||
"MappedFile.cpp",
|
||||
"MathUtil.cpp",
|
||||
"MemArena.cpp",
|
||||
"MemoryUtil.cpp",
|
||||
"Plugin.cpp",
|
||||
"PortableSockets.cpp",
|
||||
"StringUtil.cpp",
|
||||
"TestFramework.cpp",
|
||||
"Timer.cpp",
|
||||
"Thread.cpp",
|
||||
"x64Emitter.cpp",
|
||||
"x64Analyzer.cpp",
|
||||
]
|
||||
|
||||
env_common = env.Copy(CXXFLAGS = " -fPIC ")
|
||||
env_common.StaticLibrary("common", files)
|
449
Source/Core/Common/Src/StringUtil.cpp
Normal file
449
Source/Core/Common/Src/StringUtil.cpp
Normal file
@ -0,0 +1,449 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include <stdlib.h>
|
||||
#include <stdio.h>
|
||||
|
||||
#include "StringUtil.h"
|
||||
#include "TestFramework.h"
|
||||
|
||||
// faster than sscanf
|
||||
u32 AsciiToHex(const char* _szValue)
|
||||
{
|
||||
u32 value = 0;
|
||||
size_t finish = strlen(_szValue);
|
||||
|
||||
if (finish > 8)
|
||||
{
|
||||
finish = 8;
|
||||
}
|
||||
|
||||
for (size_t count = 0; count < finish; count++)
|
||||
{
|
||||
value <<= 4;
|
||||
|
||||
switch (_szValue[count])
|
||||
{
|
||||
case '0':
|
||||
break;
|
||||
|
||||
case '1':
|
||||
value += 1;
|
||||
break;
|
||||
|
||||
case '2':
|
||||
value += 2;
|
||||
break;
|
||||
|
||||
case '3':
|
||||
value += 3;
|
||||
break;
|
||||
|
||||
case '4':
|
||||
value += 4;
|
||||
break;
|
||||
|
||||
case '5':
|
||||
value += 5;
|
||||
break;
|
||||
|
||||
case '6':
|
||||
value += 6;
|
||||
break;
|
||||
|
||||
case '7':
|
||||
value += 7;
|
||||
break;
|
||||
|
||||
case '8':
|
||||
value += 8;
|
||||
break;
|
||||
|
||||
case '9':
|
||||
value += 9;
|
||||
break;
|
||||
|
||||
case 'A':
|
||||
value += 10;
|
||||
break;
|
||||
|
||||
case 'a':
|
||||
value += 10;
|
||||
break;
|
||||
|
||||
case 'B':
|
||||
value += 11;
|
||||
break;
|
||||
|
||||
case 'b':
|
||||
value += 11;
|
||||
break;
|
||||
|
||||
case 'C':
|
||||
value += 12;
|
||||
break;
|
||||
|
||||
case 'c':
|
||||
value += 12;
|
||||
break;
|
||||
|
||||
case 'D':
|
||||
value += 13;
|
||||
break;
|
||||
|
||||
case 'd':
|
||||
value += 13;
|
||||
break;
|
||||
|
||||
case 'E':
|
||||
value += 14;
|
||||
break;
|
||||
|
||||
case 'e':
|
||||
value += 14;
|
||||
break;
|
||||
|
||||
case 'F':
|
||||
value += 15;
|
||||
break;
|
||||
|
||||
case 'f':
|
||||
value += 15;
|
||||
break;
|
||||
|
||||
default:
|
||||
value >>= 4;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(value);
|
||||
}
|
||||
|
||||
|
||||
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args)
|
||||
{
|
||||
int writtenCount = vsnprintf(out, outsize, format, args);
|
||||
|
||||
if (writtenCount > 0)
|
||||
{
|
||||
out[writtenCount] = '\0';
|
||||
return(true);
|
||||
}
|
||||
else
|
||||
{
|
||||
out[outsize - 1] = '\0';
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
// Expensive!
|
||||
void StringFromFormatV(std::string* out, const char* format, va_list args)
|
||||
{
|
||||
int writtenCount = -1;
|
||||
size_t newSize = strlen(format) + 16;
|
||||
char* buf = 0;
|
||||
|
||||
while (writtenCount < 0)
|
||||
{
|
||||
delete[] buf;
|
||||
buf = new char[newSize + 1];
|
||||
writtenCount = vsnprintf(buf, newSize, format, args);
|
||||
newSize *= 2;
|
||||
}
|
||||
|
||||
buf[writtenCount] = '\0';
|
||||
*out = buf;
|
||||
delete[] buf;
|
||||
}
|
||||
|
||||
|
||||
std::string StringFromFormat(const char* format, ...)
|
||||
{
|
||||
std::string temp;
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
StringFromFormatV(&temp, format, args);
|
||||
va_end(args);
|
||||
return(temp);
|
||||
}
|
||||
|
||||
|
||||
void ToStringFromFormat(std::string* out, const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
StringFromFormatV(out, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
// Turns " hej " into "hej". Also handles tabs.
|
||||
std::string StripSpaces(std::string s)
|
||||
{
|
||||
int i;
|
||||
|
||||
for (i = 0; i < (int)s.size(); i++)
|
||||
{
|
||||
if ((s[i] != ' ') && (s[i] != 9))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
s = s.substr(i);
|
||||
|
||||
for (i = (int)s.size() - 1; i > 0; i--)
|
||||
{
|
||||
if ((s[i] != ' ') && (s[i] != 9))
|
||||
{
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
return(s.substr(0, i + 1));
|
||||
}
|
||||
|
||||
|
||||
// "\"hello\"" is turned to "hello"
|
||||
// This one assumes that the string has already been space stripped in both
|
||||
// ends, as done by StripSpaces above, for example.
|
||||
std::string StripQuotes(const std::string& s)
|
||||
{
|
||||
if ((s[0] == '\"') && (s[s.size() - 1] == '\"'))
|
||||
{
|
||||
return(s.substr(1, s.size() - 2));
|
||||
}
|
||||
else
|
||||
{
|
||||
return(s);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
bool TryParseInt(const char* str, int* outVal)
|
||||
{
|
||||
const char* s = str;
|
||||
int value = 0;
|
||||
|
||||
while (*s)
|
||||
{
|
||||
char c = *s++;
|
||||
|
||||
if ((c < '0') || (c > '9'))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
value = value * 10 + (c - '0');
|
||||
}
|
||||
|
||||
*outVal = value;
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
bool TryParseBool(const char* str, bool* output)
|
||||
{
|
||||
if ((str[0] == '1') || !strcmp(str, "true") || !strcmp(str, "True") || !strcmp(str, "TRUE"))
|
||||
{
|
||||
*output = true;
|
||||
return(true);
|
||||
}
|
||||
else if (str[0] == '0' || !strcmp(str, "false") || !strcmp(str, "False") || !strcmp(str, "FALSE"))
|
||||
{
|
||||
*output = false;
|
||||
return(true);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
std::string StringFromInt(int value)
|
||||
{
|
||||
char temp[16];
|
||||
sprintf(temp, "%i", value);
|
||||
return(std::string(temp));
|
||||
}
|
||||
|
||||
|
||||
std::string StringFromBool(bool value)
|
||||
{
|
||||
return(value ? "True" : "False");
|
||||
}
|
||||
|
||||
|
||||
#ifdef _WIN32
|
||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||
{
|
||||
char drive[_MAX_DRIVE];
|
||||
char dir[_MAX_DIR];
|
||||
char fname[_MAX_FNAME];
|
||||
char ext[_MAX_EXT];
|
||||
|
||||
if (_splitpath_s(full_path.c_str(), drive, _MAX_DRIVE, dir, _MAX_DIR, fname, _MAX_FNAME, ext, _MAX_EXT) == 0)
|
||||
{
|
||||
if (_pPath)
|
||||
{
|
||||
*_pPath = std::string(drive) + std::string(dir);
|
||||
}
|
||||
|
||||
if (_pFilename != 0)
|
||||
{
|
||||
*_pFilename = fname;
|
||||
}
|
||||
|
||||
if (_pExtension != 0)
|
||||
{
|
||||
*_pExtension = ext;
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
return(false);
|
||||
}
|
||||
|
||||
|
||||
#else
|
||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension)
|
||||
{
|
||||
int last_slash = full_path.rfind('/');
|
||||
|
||||
if (last_slash == std::string::npos)
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
int last_dot = full_path.rfind('.');
|
||||
|
||||
if ((last_dot == std::string::npos) || (last_dot < last_slash))
|
||||
{
|
||||
return(false);
|
||||
}
|
||||
|
||||
if (_pPath)
|
||||
{
|
||||
*_pPath = full_path.substr(0, last_slash + 1);
|
||||
}
|
||||
|
||||
if (_pFilename)
|
||||
{
|
||||
*_pFilename = full_path.substr(last_slash + 1, last_dot - (last_slash + 1));
|
||||
}
|
||||
|
||||
if (_pExtension)
|
||||
{
|
||||
*_pExtension = full_path.substr(last_dot + 1);
|
||||
}
|
||||
else if (_pFilename)
|
||||
{
|
||||
*_pFilename += full_path.substr(last_dot);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename)
|
||||
{
|
||||
_CompleteFilename = _Path;
|
||||
|
||||
// check for seperator
|
||||
if (_CompleteFilename[_CompleteFilename.size() - 1] != '\\')
|
||||
{
|
||||
_CompleteFilename += _T("\\");
|
||||
}
|
||||
|
||||
// add the filename
|
||||
_CompleteFilename += _Filename;
|
||||
}
|
||||
|
||||
|
||||
void SplitString(const std::string& str, const std::string& delim, std::vector<std::string>& output)
|
||||
{
|
||||
output.clear();
|
||||
|
||||
size_t offset = 0;
|
||||
size_t delimIndex = 0;
|
||||
|
||||
delimIndex = str.find(delim, offset);
|
||||
|
||||
while (delimIndex != std::string::npos)
|
||||
{
|
||||
output.push_back(str.substr(offset, delimIndex - offset));
|
||||
offset += delimIndex - offset + delim.length();
|
||||
delimIndex = str.find(delim, offset);
|
||||
}
|
||||
|
||||
output.push_back(str.substr(offset));
|
||||
}
|
||||
|
||||
|
||||
bool TryParseUInt(const std::string& str, u32* output)
|
||||
{
|
||||
if (!strcmp(str.substr(0, 2).c_str(), "0x") || !strcmp(str.substr(0, 2).c_str(), "0X"))
|
||||
{
|
||||
return(sscanf(str.c_str() + 2, "%x", output) > 0);
|
||||
}
|
||||
else
|
||||
{
|
||||
return(sscanf(str.c_str(), "%d", output) > 0);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
int ChooseStringFrom(const char* str, const char* * items)
|
||||
{
|
||||
int i = 0;
|
||||
|
||||
while (items[i] != 0)
|
||||
{
|
||||
if (!strcmp(str, items[i]))
|
||||
{
|
||||
return(i);
|
||||
}
|
||||
|
||||
i++;
|
||||
}
|
||||
|
||||
return(-1);
|
||||
}
|
||||
|
||||
|
||||
// Hmm, sometimes this test doesn't get run :P
|
||||
TEST(splitStringTest)
|
||||
{
|
||||
/*
|
||||
std::string orig = "abc:def";
|
||||
std::vector<std::string> split;
|
||||
SplitString(orig, std::string(":"), split);
|
||||
CHECK(split.size() == 2);
|
||||
CHECK(!strcmp(split[0].c_str(), "abc"));
|
||||
CHECK(!strcmp(split[1].c_str(), "def"));
|
||||
|
||||
orig = "abc";
|
||||
SplitString(orig, std::string(":"), split);
|
||||
CHECK(split.size() == 1);
|
||||
orig = ":";
|
||||
SplitString(orig, std::string(":"), split);
|
||||
CHECK(split.size() == 2);*/
|
||||
}
|
75
Source/Core/Common/Src/StringUtil.h
Normal file
75
Source/Core/Common/Src/StringUtil.h
Normal file
@ -0,0 +1,75 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _STRINGUTIL_H
|
||||
#define _STRINGUTIL_H
|
||||
|
||||
#include <stdarg.h>
|
||||
|
||||
#include <vector>
|
||||
#include <string>
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
std::string StringFromFormat(const char* format, ...);
|
||||
void ToStringFromFormat(std::string* out, const char* format, ...);
|
||||
|
||||
|
||||
// Expensive!
|
||||
void StringFromFormatV(std::string* out, const char* format, va_list args);
|
||||
|
||||
|
||||
// Cheap!
|
||||
bool CharArrayFromFormatV(char* out, int outsize, const char* format, va_list args);
|
||||
|
||||
|
||||
template<size_t Count>
|
||||
inline void CharArrayFromFormat(char (& out)[Count], const char* format, ...)
|
||||
{
|
||||
va_list args;
|
||||
va_start(args, format);
|
||||
CharArrayFromFormatV(out, Count, format, args);
|
||||
va_end(args);
|
||||
}
|
||||
|
||||
|
||||
std::string StripSpaces(std::string s);
|
||||
std::string StripQuotes(const std::string& s);
|
||||
|
||||
|
||||
std::string StringFromInt(int value);
|
||||
std::string StringFromBool(bool value);
|
||||
|
||||
bool TryParseInt(const char* str, int* outVal);
|
||||
bool TryParseBool(const char* str, bool* output);
|
||||
bool TryParseUInt(const std::string& str, u32* output);
|
||||
|
||||
|
||||
// TODO: kill this
|
||||
u32 AsciiToHex(const char* ascii);
|
||||
|
||||
void SplitString(const std::string& str, const std::string& delim, std::vector<std::string>& output);
|
||||
int ChooseStringFrom(const char* str, const char* * items);
|
||||
|
||||
|
||||
// filehelper
|
||||
bool SplitPath(const std::string& full_path, std::string* _pPath, std::string* _pFilename, std::string* _pExtension);
|
||||
void BuildCompleteFilename(std::string& _CompleteFilename, const std::string& _Path, const std::string& _Filename);
|
||||
|
||||
|
||||
#endif
|
||||
|
38
Source/Core/Common/Src/TestFramework.cpp
Normal file
38
Source/Core/Common/Src/TestFramework.cpp
Normal file
@ -0,0 +1,38 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "TestFramework.h"
|
||||
|
||||
namespace __test
|
||||
{
|
||||
int numTests;
|
||||
int numTestsFailed;
|
||||
}
|
||||
|
||||
|
||||
int GetNumTests()
|
||||
{
|
||||
return(__test::numTests);
|
||||
}
|
||||
|
||||
|
||||
int GetNumTestsFailed()
|
||||
{
|
||||
return(__test::numTestsFailed);
|
||||
}
|
||||
|
||||
|
100
Source/Core/Common/Src/TestFramework.h
Normal file
100
Source/Core/Common/Src/TestFramework.h
Normal file
@ -0,0 +1,100 @@
|
||||
// Stupidly simple automated testing framework
|
||||
// by ector
|
||||
|
||||
// licence: Public Domain
|
||||
|
||||
// If TESTING_ENABLE is true, all tests across the project will run before main().
|
||||
// If it's false, all tests will be destroyed by the linker, hopefully.
|
||||
|
||||
// Unfortunately, MSVC:s library linker seems to kill off unreferenced objects, even if the
|
||||
// initialization has side effects. This makes this framework not work properly :(
|
||||
// TODO(ector): Find solution.
|
||||
|
||||
// TODO(ector): make sure tests are destroyed and that things compile without TESTING_ENABLE :P
|
||||
|
||||
#define TESTING_ENABLE
|
||||
|
||||
#ifndef _TEST_FRAMEWORK_H
|
||||
#define _TEST_FRAMEWORK_H
|
||||
|
||||
#include "Common.h"
|
||||
#include <stdio.h>
|
||||
|
||||
#ifdef TESTING_ENABLE
|
||||
|
||||
namespace __test
|
||||
{
|
||||
extern int numTests;
|
||||
extern int numTestsFailed;
|
||||
}
|
||||
|
||||
struct TestRunnah
|
||||
{
|
||||
const char* filename;
|
||||
const char* function;
|
||||
TestRunnah(const char* _filename, const char* _function)
|
||||
: filename(_filename), function(_function) {}
|
||||
|
||||
|
||||
bool AssertTrue(bool value, int line)
|
||||
{
|
||||
if (!value)
|
||||
{
|
||||
char string[256];
|
||||
sprintf(string, "%s:%s:%i: %s", filename, function, line, "failed");
|
||||
PanicAlert("Test Results: %s", string);
|
||||
TestFailed();
|
||||
return(false);
|
||||
}
|
||||
|
||||
return(true);
|
||||
}
|
||||
|
||||
|
||||
template<class T>
|
||||
bool AssertEqual(T a, T b, int line)
|
||||
{
|
||||
if (!(a == b))
|
||||
{
|
||||
// TODO(ector) : better output
|
||||
char string[256];
|
||||
sprintf(string, "%s:%s:%i: %s", filename, function, line, "failed");
|
||||
PanicAlert("Test Results: %s", string);
|
||||
TestFailed();
|
||||
return(false);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void TestFailed()
|
||||
{
|
||||
__test::numTestsFailed++;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
#define TEST(a) \
|
||||
void TEST_ ## a(TestRunnah * __tr); \
|
||||
struct DUMMY_ ## a \
|
||||
: public TestRunnah { \
|
||||
DUMMY_ ## a() \
|
||||
: TestRunnah(__FILE__, # a) {\
|
||||
TEST_ ## a(this); __test::numTests++;} }; \
|
||||
DUMMY_ ## a ddummy_ ## a; \
|
||||
void TEST_ ## a(TestRunnah * __tr)
|
||||
|
||||
#else // TESTING_ENABLE
|
||||
|
||||
#define TEST(a) \
|
||||
void TEST_ ## a(TestRunnah * __tr) \
|
||||
|
||||
#endif
|
||||
|
||||
#define CHECK(a) if (!__tr->AssertTrue(a, __LINE__)){return;}
|
||||
#define CHECK_EQ(a, b) if (!__tr->AssertEqual(a, b, __LINE__)){return;}
|
||||
|
||||
int GetNumTests();
|
||||
int GetNumTestsFailed();
|
||||
|
||||
|
||||
#endif
|
346
Source/Core/Common/Src/Thread.cpp
Normal file
346
Source/Core/Common/Src/Thread.cpp
Normal file
@ -0,0 +1,346 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#elif __GNUC__
|
||||
#include <unistd.h>
|
||||
#include <pthread.h>
|
||||
#else
|
||||
#error unsupported platform
|
||||
#endif
|
||||
|
||||
#include "Thread.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CriticalSection::CriticalSection(int spincount)
|
||||
{
|
||||
if (spincount)
|
||||
{
|
||||
InitializeCriticalSectionAndSpinCount(§ion, spincount);
|
||||
}
|
||||
else
|
||||
{
|
||||
InitializeCriticalSection(§ion);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
CriticalSection::~CriticalSection()
|
||||
{
|
||||
// No need to do anything
|
||||
}
|
||||
|
||||
|
||||
void CriticalSection::Enter()
|
||||
{
|
||||
EnterCriticalSection(§ion);
|
||||
}
|
||||
|
||||
|
||||
bool CriticalSection::TryEnter()
|
||||
{
|
||||
return(TryEnterCriticalSection(§ion) ? true : false);
|
||||
}
|
||||
|
||||
|
||||
void CriticalSection::Leave()
|
||||
{
|
||||
LeaveCriticalSection(§ion);
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread(ThreadFunc function, void* arg)
|
||||
: m_hThread(NULL), m_threadId(0)
|
||||
{
|
||||
m_hThread = CreateThread(
|
||||
0, // Security attributes
|
||||
0, // Stack size
|
||||
function,
|
||||
arg,
|
||||
0,
|
||||
&m_threadId);
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
WaitForDeath();
|
||||
}
|
||||
|
||||
|
||||
void Thread::WaitForDeath()
|
||||
{
|
||||
if (m_hThread)
|
||||
{
|
||||
WaitForSingleObject(m_hThread, INFINITE);
|
||||
CloseHandle(m_hThread);
|
||||
m_hThread = NULL;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Thread::SetAffinity(int mask)
|
||||
{
|
||||
SetThreadAffinityMask(m_hThread, mask);
|
||||
}
|
||||
|
||||
|
||||
void Thread::SetCurrentThreadAffinity(int mask)
|
||||
{
|
||||
SetThreadAffinityMask(GetCurrentThread(), mask);
|
||||
}
|
||||
|
||||
|
||||
Event::Event()
|
||||
{
|
||||
m_hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
void Event::Init()
|
||||
{
|
||||
m_hEvent = CreateEvent(NULL, FALSE, FALSE, NULL);
|
||||
}
|
||||
|
||||
|
||||
void Event::Shutdown()
|
||||
{
|
||||
CloseHandle(m_hEvent);
|
||||
m_hEvent = 0;
|
||||
}
|
||||
|
||||
|
||||
void Event::Set()
|
||||
{
|
||||
SetEvent(m_hEvent);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
WaitForSingleObject(m_hEvent, INFINITE);
|
||||
}
|
||||
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
Sleep(ms);
|
||||
}
|
||||
|
||||
|
||||
typedef struct tagTHREADNAME_INFO
|
||||
{
|
||||
DWORD dwType; // must be 0x1000
|
||||
LPCSTR szName; // pointer to name (in user addr space)
|
||||
DWORD dwThreadID; // thread ID (-1=caller thread)
|
||||
DWORD dwFlags; // reserved for future use, must be zero
|
||||
} THREADNAME_INFO;
|
||||
// Usage: SetThreadName (-1, "MainThread");
|
||||
//
|
||||
// Sets the debugger-visible name of the current thread.
|
||||
// Uses undocumented (actually, it is now documented) trick.
|
||||
// http://msdn.microsoft.com/library/default.asp?url=/library/en-us/vsdebug/html/vxtsksettingthreadname.asp
|
||||
|
||||
void SetCurrentThreadName(const TCHAR* szThreadName)
|
||||
{
|
||||
THREADNAME_INFO info;
|
||||
info.dwType = 0x1000;
|
||||
#ifdef UNICODE
|
||||
//TODO: Find the proper way to do this.
|
||||
char tname[256];
|
||||
unsigned int i;
|
||||
|
||||
for (i = 0; i < _tcslen(szThreadName); i++)
|
||||
{
|
||||
tname[i] = (char)szThreadName[i]; //poor man's unicode->ansi, TODO: fix
|
||||
}
|
||||
|
||||
tname[i] = 0;
|
||||
info.szName = tname;
|
||||
#else
|
||||
info.szName = szThreadName;
|
||||
#endif
|
||||
|
||||
info.dwThreadID = -1; //dwThreadID;
|
||||
info.dwFlags = 0;
|
||||
__try
|
||||
{
|
||||
RaiseException(0x406D1388, 0, sizeof(info) / sizeof(DWORD), (ULONG_PTR*)&info);
|
||||
}
|
||||
__except(EXCEPTION_CONTINUE_EXECUTION)
|
||||
{}
|
||||
}
|
||||
|
||||
|
||||
#elif __GNUC__
|
||||
CriticalSection::CriticalSection(int spincount_unused)
|
||||
{
|
||||
pthread_mutex_init(&mutex, 0);
|
||||
}
|
||||
|
||||
|
||||
CriticalSection::~CriticalSection()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex);
|
||||
}
|
||||
|
||||
|
||||
void CriticalSection::Enter()
|
||||
{
|
||||
pthread_mutex_lock(&mutex);
|
||||
}
|
||||
|
||||
|
||||
bool CriticalSection::TryEnter()
|
||||
{
|
||||
return(!pthread_mutex_trylock(&mutex));
|
||||
}
|
||||
|
||||
|
||||
void CriticalSection::Leave()
|
||||
{
|
||||
pthread_mutex_unlock(&mutex);
|
||||
}
|
||||
|
||||
|
||||
Thread::Thread(ThreadFunc function, void* arg)
|
||||
: thread_id(0)
|
||||
{
|
||||
pthread_attr_t attr;
|
||||
pthread_attr_init(&attr);
|
||||
pthread_attr_setstacksize(&attr, 1024 * 1024);
|
||||
pthread_create(&thread_id, &attr, function, arg);
|
||||
}
|
||||
|
||||
|
||||
Thread::~Thread()
|
||||
{
|
||||
WaitForDeath();
|
||||
}
|
||||
|
||||
|
||||
void Thread::WaitForDeath()
|
||||
{
|
||||
if (thread_id)
|
||||
{
|
||||
void* exit_status;
|
||||
pthread_join(thread_id, &exit_status);
|
||||
thread_id = 0;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
void Thread::SetAffinity(int mask)
|
||||
{
|
||||
// This is non-standard
|
||||
#ifdef __linux__
|
||||
cpu_set_t cpu_set;
|
||||
CPU_ZERO(&cpu_set);
|
||||
|
||||
for (int i = 0; i < sizeof(mask) * 8; i++)
|
||||
{
|
||||
if ((mask >> i) & 1){CPU_SET(i, &cpu_set);}
|
||||
}
|
||||
|
||||
pthread_setaffinity_np(thread_id, sizeof(cpu_set), &cpu_set);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Thread::SetCurrentThreadAffinity(int mask)
|
||||
{
|
||||
#ifdef __linux__
|
||||
cpu_set_t cpu_set;
|
||||
CPU_ZERO(&cpu_set);
|
||||
|
||||
for (size_t i = 0; i < sizeof(mask) * 8; i++)
|
||||
{
|
||||
if ((mask >> i) & 1){CPU_SET(i, &cpu_set);}
|
||||
}
|
||||
|
||||
pthread_setaffinity_np(pthread_self(), sizeof(cpu_set), &cpu_set);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void SleepCurrentThread(int ms)
|
||||
{
|
||||
usleep(1000 * ms);
|
||||
}
|
||||
|
||||
|
||||
void SetCurrentThreadName(const TCHAR* szThreadName)
|
||||
{
|
||||
// noop
|
||||
}
|
||||
|
||||
|
||||
Event::Event()
|
||||
{
|
||||
is_set_ = false;
|
||||
}
|
||||
|
||||
|
||||
void Event::Init()
|
||||
{
|
||||
pthread_cond_init(&event_, 0);
|
||||
pthread_mutex_init(&mutex_, 0);
|
||||
}
|
||||
|
||||
|
||||
void Event::Shutdown()
|
||||
{
|
||||
pthread_mutex_destroy(&mutex_);
|
||||
pthread_cond_destroy(&event_);
|
||||
}
|
||||
|
||||
|
||||
void Event::Set()
|
||||
{
|
||||
pthread_mutex_lock(&mutex_);
|
||||
|
||||
if (!is_set_)
|
||||
{
|
||||
is_set_ = true;
|
||||
pthread_cond_signal(&event_);
|
||||
}
|
||||
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
}
|
||||
|
||||
|
||||
void Event::Wait()
|
||||
{
|
||||
pthread_mutex_lock(&mutex_);
|
||||
|
||||
while (!is_set_)
|
||||
{
|
||||
pthread_cond_wait(&event_, &mutex_);
|
||||
}
|
||||
|
||||
is_set_ = false;
|
||||
pthread_mutex_unlock(&mutex_);
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
} // end of namespace Common
|
109
Source/Core/Common/Src/Thread.h
Normal file
109
Source/Core/Common/Src/Thread.h
Normal file
@ -0,0 +1,109 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _THREAD_H
|
||||
#define _THREAD_H
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#endif
|
||||
|
||||
#ifdef _WIN32
|
||||
#define THREAD_RETURN DWORD WINAPI
|
||||
#else
|
||||
#define THREAD_RETURN void*
|
||||
#endif
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class CriticalSection
|
||||
{
|
||||
#ifdef _WIN32
|
||||
CRITICAL_SECTION section;
|
||||
#elif __GNUC__
|
||||
pthread_mutex_t mutex;
|
||||
#endif
|
||||
public:
|
||||
|
||||
CriticalSection(int spincount = 1000);
|
||||
~CriticalSection();
|
||||
void Enter();
|
||||
bool TryEnter();
|
||||
void Leave();
|
||||
};
|
||||
|
||||
#ifdef _WIN32
|
||||
typedef DWORD (WINAPI * ThreadFunc)(void* arg);
|
||||
#elif __GNUC__
|
||||
typedef void* (*ThreadFunc)(void* arg);
|
||||
#endif
|
||||
|
||||
class Thread
|
||||
{
|
||||
public:
|
||||
|
||||
Thread(ThreadFunc entry, void* arg);
|
||||
~Thread();
|
||||
|
||||
void WaitForDeath();
|
||||
void SetAffinity(int mask);
|
||||
static void SetCurrentThreadAffinity(int mask);
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE m_hThread;
|
||||
DWORD m_threadId;
|
||||
#elif __GNUC__
|
||||
pthread_t thread_id;
|
||||
#endif
|
||||
};
|
||||
|
||||
|
||||
class Event
|
||||
{
|
||||
public:
|
||||
|
||||
Event();
|
||||
|
||||
void Init();
|
||||
void Shutdown();
|
||||
|
||||
void Set();
|
||||
void Wait();
|
||||
|
||||
|
||||
private:
|
||||
|
||||
#ifdef _WIN32
|
||||
HANDLE m_hEvent;
|
||||
#elif __GNUC__
|
||||
bool is_set_;
|
||||
pthread_cond_t event_;
|
||||
pthread_mutex_t mutex_;
|
||||
#endif
|
||||
};
|
||||
|
||||
void SleepCurrentThread(int ms);
|
||||
|
||||
void SetCurrentThreadName(const char* name);
|
||||
} // end of namespace Common
|
||||
|
||||
#endif
|
99
Source/Core/Common/Src/Timer.cpp
Normal file
99
Source/Core/Common/Src/Timer.cpp
Normal file
@ -0,0 +1,99 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifdef _WIN32
|
||||
#include <windows.h>
|
||||
#include <mmsystem.h>
|
||||
#endif
|
||||
|
||||
#include <time.h>
|
||||
|
||||
#include "Common.h"
|
||||
#include "Timer.H"
|
||||
|
||||
#ifdef __GNUC__
|
||||
#include <sys/timeb.h>
|
||||
|
||||
u32 timeGetTime()
|
||||
{
|
||||
struct timeb t;
|
||||
ftime(&t);
|
||||
return((u32)(t.time * 1000 + t.millitm));
|
||||
}
|
||||
|
||||
|
||||
#endif
|
||||
|
||||
|
||||
namespace Common
|
||||
{
|
||||
Timer::Timer(void)
|
||||
: m_LastTime(0)
|
||||
{
|
||||
Update();
|
||||
|
||||
#ifdef _WIN32
|
||||
QueryPerformanceFrequency((LARGE_INTEGER*)&m_frequency);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Timer::Update(void)
|
||||
{
|
||||
m_LastTime = timeGetTime();
|
||||
//TODO(ector) - QPF
|
||||
}
|
||||
|
||||
|
||||
s64 Timer::GetTimeDifference(void)
|
||||
{
|
||||
return(timeGetTime() - m_LastTime);
|
||||
}
|
||||
|
||||
|
||||
void Timer::IncreaseResolution()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
timeBeginPeriod(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
void Timer::RestoreResolution()
|
||||
{
|
||||
#ifdef _WIN32
|
||||
timeEndPeriod(1);
|
||||
#endif
|
||||
}
|
||||
|
||||
|
||||
#ifdef __GNUC__
|
||||
void _time64(u64* t)
|
||||
{
|
||||
*t = 0; //TODO
|
||||
}
|
||||
#endif
|
||||
|
||||
|
||||
|
||||
u64 Timer::GetTimeSinceJan1970(void)
|
||||
{
|
||||
time_t ltime;
|
||||
time(<ime);
|
||||
return((u64)ltime);
|
||||
}
|
||||
} // end of namespace Common
|
49
Source/Core/Common/Src/Timer.h
Normal file
49
Source/Core/Common/Src/Timer.h
Normal file
@ -0,0 +1,49 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#ifndef _TIMER_H
|
||||
#define _TIMER_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace Common
|
||||
{
|
||||
class Timer
|
||||
{
|
||||
public:
|
||||
|
||||
Timer();
|
||||
|
||||
void Update();
|
||||
|
||||
|
||||
// Always in milliseconds, regardless of alternative internal representation
|
||||
s64 GetTimeDifference(void);
|
||||
|
||||
static void IncreaseResolution();
|
||||
static void RestoreResolution();
|
||||
static u64 GetTimeSinceJan1970();
|
||||
|
||||
|
||||
public:
|
||||
|
||||
u64 m_LastTime;
|
||||
u64 m_frequency;
|
||||
};
|
||||
} // end of namespace Common
|
||||
|
||||
#endif
|
18
Source/Core/Common/Src/stdafx.cpp
Normal file
18
Source/Core/Common/Src/stdafx.cpp
Normal file
@ -0,0 +1,18 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#include "stdafx.h"
|
33
Source/Core/Common/Src/stdafx.h
Normal file
33
Source/Core/Common/Src/stdafx.h
Normal file
@ -0,0 +1,33 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
|
||||
#pragma once
|
||||
|
||||
#define _WIN32_WINNT 0x501
|
||||
#ifndef _WIN32_IE
|
||||
#define _WIN32_IE 0x0500 // Default value is 0x0400
|
||||
#endif
|
||||
|
||||
#define WIN32_LEAN_AND_MEAN // Exclude rarely-used stuff from Windows headers
|
||||
|
||||
#define _CRT_SECURE_NO_DEPRECATE 1
|
||||
#define _CRT_NONSTDC_NO_DEPRECATE 1
|
||||
|
||||
#include <windows.h>
|
||||
#include <tchar.h>
|
||||
#include <vector>
|
||||
|
219
Source/Core/Common/Src/x64Analyzer.cpp
Normal file
219
Source/Core/Common/Src/x64Analyzer.cpp
Normal file
@ -0,0 +1,219 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#include "x64Analyzer.h"
|
||||
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int accessType)
|
||||
{
|
||||
unsigned const char *startCodePtr = codePtr;
|
||||
u8 rex = 0;
|
||||
u8 codeByte = 0;
|
||||
u8 codeByte2 = 0;
|
||||
|
||||
//Check for regular prefix
|
||||
info.operandSize = 4;
|
||||
info.zeroExtend = false;
|
||||
|
||||
int addressSize = 8;
|
||||
u8 modRMbyte = 0;
|
||||
u8 sibByte = 0;
|
||||
bool hasModRM = false;
|
||||
bool hasSIBbyte = false;
|
||||
bool hasDisplacement = false;
|
||||
info.hasImmediate = false;
|
||||
|
||||
int displacementSize = 0;
|
||||
|
||||
if (*codePtr == 0x66)
|
||||
{
|
||||
info.operandSize = 2;
|
||||
codePtr++;
|
||||
}
|
||||
else if (*codePtr == 0x67)
|
||||
{
|
||||
addressSize = 4;
|
||||
codePtr++;
|
||||
}
|
||||
|
||||
//Check for REX prefix
|
||||
if ((*codePtr & 0xF0) == 0x40)
|
||||
{
|
||||
rex = *codePtr;
|
||||
if (rex & 8) //REX.W
|
||||
{
|
||||
info.operandSize = 8;
|
||||
}
|
||||
codePtr++;
|
||||
}
|
||||
|
||||
codeByte = *codePtr++;
|
||||
|
||||
// Skip two-byte opcode byte
|
||||
bool twoByte = false;
|
||||
if(codeByte == 0x0F)
|
||||
{
|
||||
twoByte = true;
|
||||
codeByte2 = *codePtr++;
|
||||
}
|
||||
|
||||
if (!twoByte)
|
||||
{
|
||||
if ((codeByte & 0xF0) == 0x80 ||
|
||||
(codeByte & 0xF8) == 0xC0 && (codeByte & 0x0E) != 0x02)
|
||||
{
|
||||
modRMbyte = *codePtr++;
|
||||
hasModRM = true;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if ((codeByte2 & 0xF0) == 0x00 && (codeByte2 & 0x0F) >= 0x04 && (codeByte2 & 0x0D) != 0x0D ||
|
||||
(codeByte2 & 0xF0) == 0x30 ||
|
||||
codeByte2 == 0x77 ||
|
||||
(codeByte2 & 0xF0) == 0x80 ||
|
||||
(codeByte2 & 0xF0) == 0xA0 && (codeByte2 & 0x07) <= 0x02 ||
|
||||
(codeByte2 & 0xF8) == 0xC8)
|
||||
{
|
||||
// No mod R/M byte
|
||||
}
|
||||
else
|
||||
{
|
||||
modRMbyte = *codePtr++;
|
||||
hasModRM = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (hasModRM)
|
||||
{
|
||||
ModRM mrm(modRMbyte, rex);
|
||||
info.regOperandReg = mrm.reg;
|
||||
if (mrm.mod < 3)
|
||||
{
|
||||
if (mrm.rm == 4)
|
||||
{
|
||||
//SIB byte
|
||||
sibByte = *codePtr++;
|
||||
info.scaledReg = (sibByte >> 3) & 7;
|
||||
info.otherReg = (sibByte & 7);
|
||||
if (rex & 2) info.scaledReg += 8;
|
||||
if (rex & 1) info.otherReg += 8;
|
||||
hasSIBbyte = true;
|
||||
}
|
||||
else
|
||||
{
|
||||
//info.scaledReg =
|
||||
}
|
||||
}
|
||||
if (mrm.mod == 1 || mrm.mod == 2)
|
||||
{
|
||||
hasDisplacement = true;
|
||||
if (mrm.mod == 1)
|
||||
displacementSize = 1;
|
||||
else
|
||||
displacementSize = 4;
|
||||
}
|
||||
}
|
||||
|
||||
if (displacementSize == 1)
|
||||
info.displacement = (s32)(s8)*codePtr;
|
||||
else
|
||||
info.displacement = *((s32 *)codePtr);
|
||||
codePtr += displacementSize;
|
||||
|
||||
|
||||
if (accessType == 1)
|
||||
{
|
||||
//Write access
|
||||
switch (codeByte)
|
||||
{
|
||||
case 0xC6: //move 8-bit immediate
|
||||
{
|
||||
info.hasImmediate = true;
|
||||
info.immediate = *codePtr;
|
||||
codePtr++; //move past immediate
|
||||
}
|
||||
break;
|
||||
|
||||
case 0xC7: //move 16 or 32-bit immediate, easiest case for writes
|
||||
{
|
||||
if (info.operandSize == 2)
|
||||
{
|
||||
info.hasImmediate = true;
|
||||
info.immediate = *(u16*)codePtr;
|
||||
codePtr += 2;
|
||||
}
|
||||
else if (info.operandSize == 4)
|
||||
{
|
||||
info.hasImmediate = true;
|
||||
info.immediate = *(u32*)codePtr;
|
||||
codePtr += 4;
|
||||
}
|
||||
else if (info.operandSize == 8)
|
||||
{
|
||||
info.zeroExtend = true;
|
||||
info.immediate = *(u32*)codePtr;
|
||||
codePtr += 4;
|
||||
}
|
||||
}
|
||||
break;
|
||||
case 0x89: //move reg to memory
|
||||
break;
|
||||
|
||||
default:
|
||||
PanicAlert("Unhandled disasm case in write handler!\n\nPlease implement or avoid.");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
//mov eax,dword ptr [rax] == 8b 00
|
||||
switch (codeByte)
|
||||
{
|
||||
case 0x0F:
|
||||
switch (codeByte2)
|
||||
{
|
||||
case 0xB6: //movzx on byte
|
||||
info.zeroExtend = true;
|
||||
info.operandSize = 1;
|
||||
break;
|
||||
case 0xB7: //movzx on short
|
||||
info.zeroExtend = true;
|
||||
info.operandSize = 2;
|
||||
break;
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
break;
|
||||
case 0x8a:
|
||||
if (info.operandSize == 4)
|
||||
{
|
||||
info.operandSize = 1;
|
||||
break;
|
||||
}
|
||||
else
|
||||
return false;
|
||||
case 0x8b:
|
||||
break; //it's OK don't need to do anything
|
||||
default:
|
||||
return false;
|
||||
}
|
||||
}
|
||||
info.instructionSize = (int)(codePtr - startCodePtr);
|
||||
return true;
|
||||
}
|
||||
|
||||
|
||||
|
54
Source/Core/Common/Src/x64Analyzer.h
Normal file
54
Source/Core/Common/Src/x64Analyzer.h
Normal file
@ -0,0 +1,54 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _X64ANALYZER_H
|
||||
#define _X64ANALYZER_H
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
struct InstructionInfo
|
||||
{
|
||||
int operandSize; //8, 16, 32, 64
|
||||
int instructionSize;
|
||||
int regOperandReg;
|
||||
int otherReg;
|
||||
int scaledReg;
|
||||
bool zeroExtend;
|
||||
bool hasImmediate;
|
||||
u64 immediate;
|
||||
s32 displacement;
|
||||
};
|
||||
|
||||
struct ModRM
|
||||
{
|
||||
int mod, reg, rm;
|
||||
ModRM(u8 modRM, u8 rex)
|
||||
{
|
||||
mod = modRM >> 6;
|
||||
reg = ((modRM >> 3) & 7) | ((rex & 4)?8:0);
|
||||
rm = modRM & 7;
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
enum AccessType{
|
||||
OP_ACCESS_READ = 0,
|
||||
OP_ACCESS_WRITE = 1
|
||||
};
|
||||
|
||||
bool DisassembleMov(const unsigned char *codePtr, InstructionInfo &info, int accessType);
|
||||
|
||||
#endif
|
1406
Source/Core/Common/Src/x64Emitter.cpp
Normal file
1406
Source/Core/Common/Src/x64Emitter.cpp
Normal file
File diff suppressed because it is too large
Load Diff
542
Source/Core/Common/Src/x64Emitter.h
Normal file
542
Source/Core/Common/Src/x64Emitter.h
Normal file
@ -0,0 +1,542 @@
|
||||
// Copyright (C) 2003-2008 Dolphin Project.
|
||||
|
||||
// This program is free software: you can redistribute it and/or modify
|
||||
// it under the terms of the GNU General Public License as published by
|
||||
// the Free Software Foundation, version 2.0.
|
||||
|
||||
// This program is distributed in the hope that it will be useful,
|
||||
// but WITHOUT ANY WARRANTY; without even the implied warranty of
|
||||
// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
|
||||
// GNU General Public License 2.0 for more details.
|
||||
|
||||
// A copy of the GPL 2.0 should have been included with the program.
|
||||
// If not, see http://www.gnu.org/licenses/
|
||||
|
||||
// Official SVN repository and contact information can be found at
|
||||
// http://code.google.com/p/dolphin-emu/
|
||||
#ifndef _DOLPHIN_INTEL_CODEGEN
|
||||
#define _DOLPHIN_INTEL_CODEGEN
|
||||
|
||||
#include "Common.h"
|
||||
|
||||
namespace Gen
|
||||
{
|
||||
enum X64Reg
|
||||
{
|
||||
EAX = 0, EBX = 3, ECX = 1, EDX = 2,
|
||||
ESI = 6, EDI = 7, EBP = 5, ESP = 4,
|
||||
|
||||
RAX = 0, RBX = 3, RCX = 1, RDX = 2,
|
||||
RSI = 6, RDI = 7, RBP = 5, RSP = 4,
|
||||
R8 = 8, R9 = 9, R10 = 10,R11 = 11,
|
||||
R12 = 12,R13 = 13,R14 = 14,R15 = 15,
|
||||
|
||||
AL = 0, BL = 3, CL = 1, DL = 2,
|
||||
AH = 4, BH = 7, CH = 5, DH = 6,
|
||||
|
||||
AX = 0, BX = 3, CX = 1, DX = 2,
|
||||
SI = 6, DI = 7, BP = 5, SP = 4,
|
||||
|
||||
XMM0=0, XMM1, XMM2, XMM3, XMM4, XMM5, XMM6, XMM7,
|
||||
XMM8, XMM9, XMM10, XMM11, XMM12, XMM13, XMM14, XMM15,
|
||||
|
||||
INVALID_REG = 0xFFFFFFFF
|
||||
};
|
||||
|
||||
enum CCFlags
|
||||
{
|
||||
CC_O = 0,
|
||||
CC_NO = 1,
|
||||
CC_B = 2, CC_C = 2, CC_NAE = 2,
|
||||
CC_NB = 3, CC_NC = 3, CC_AE = 3,
|
||||
CC_Z = 4, CC_E = 4,
|
||||
CC_NZ = 5, CC_NE = 5,
|
||||
CC_BE = 6, CC_NA = 6,
|
||||
CC_NBE = 7, CC_A = 7,
|
||||
CC_S = 8,
|
||||
CC_NS = 9,
|
||||
CC_P = 0xA, CC_PE = 0xA,
|
||||
CC_NP = 0xB, CC_PO = 0xB,
|
||||
CC_L = 0xC, CC_NGE = 0xC,
|
||||
CC_NL = 0xD, CC_GE = 0xD,
|
||||
CC_LE = 0xE, CC_NG = 0xE,
|
||||
CC_NLE = 0xF, CC_G = 0xF
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
NUMGPRs = 16,
|
||||
NUMXMMs = 16,
|
||||
};
|
||||
|
||||
enum
|
||||
{
|
||||
SCALE_NONE = 0,
|
||||
SCALE_1 = 1,
|
||||
SCALE_2 = 2,
|
||||
SCALE_4 = 4,
|
||||
SCALE_8 = 8,
|
||||
SCALE_ATREG = 16,
|
||||
SCALE_RIP = 0xFF,
|
||||
SCALE_IMM8 = 0xF0,
|
||||
SCALE_IMM16 = 0xF1,
|
||||
SCALE_IMM32 = 0xF2,
|
||||
SCALE_IMM64 = 0xF3,
|
||||
};
|
||||
|
||||
void SetCodePtr(u8 *ptr);
|
||||
void ReserveCodeSpace(int bytes);
|
||||
const u8 *AlignCode4();
|
||||
const u8 *AlignCode16();
|
||||
const u8 *AlignCodePage();
|
||||
const u8 *GetCodePtr();
|
||||
u8 *GetWritableCodePtr();
|
||||
|
||||
enum NormalOp {
|
||||
nrmADD,
|
||||
nrmADC,
|
||||
nrmSUB,
|
||||
nrmSBB,
|
||||
nrmAND,
|
||||
nrmOR ,
|
||||
nrmXOR,
|
||||
nrmMOV,
|
||||
nrmTEST,
|
||||
nrmCMP,
|
||||
nrmXCHG,
|
||||
};
|
||||
|
||||
// Make the generation routine examine which direction to go
|
||||
// probably has to be a static
|
||||
|
||||
// RIP addressing does not benefit from micro op fusion on Core arch
|
||||
struct OpArg
|
||||
{
|
||||
OpArg() {} //dummy op arg, used for storage
|
||||
OpArg(u64 _offset, int _scale, X64Reg rmReg = RAX, X64Reg scaledReg = RAX)
|
||||
{
|
||||
operandReg = 0;
|
||||
scale = (u8)_scale;
|
||||
offsetOrBaseReg = (u8)rmReg;
|
||||
indexReg = (u8)scaledReg;
|
||||
//if scale == 0 never mind offseting
|
||||
offset = _offset;
|
||||
}
|
||||
void WriteRex(bool op64, int customOp = -1) const;
|
||||
void WriteRest(int extraBytes=0, X64Reg operandReg=(X64Reg)0xFF) const;
|
||||
void WriteSingleByteOp(u8 op, X64Reg operandReg, int bits);
|
||||
//This one is public - must be written to
|
||||
u64 offset; //use RIP-relative as much as possible - avoid 64-bit immediates at all costs
|
||||
u8 operandReg;
|
||||
|
||||
void WriteNormalOp(bool toRM, NormalOp op, const OpArg &operand, int bits) const;
|
||||
bool IsImm() const {return scale == SCALE_IMM8 || scale == SCALE_IMM16 || scale == SCALE_IMM32 || scale == SCALE_IMM64;}
|
||||
bool IsSimpleReg() const {return scale == SCALE_NONE;}
|
||||
|
||||
bool CanDoOpWith(OpArg &other) const
|
||||
{
|
||||
if (IsSimpleReg()) return true;
|
||||
if (!IsSimpleReg() && !other.IsSimpleReg() && !other.IsImm()) return false;
|
||||
return true;
|
||||
}
|
||||
|
||||
int GetImmBits() const
|
||||
{
|
||||
switch (scale)
|
||||
{
|
||||
case SCALE_IMM8: return 8;
|
||||
case SCALE_IMM16: return 16;
|
||||
case SCALE_IMM32: return 32;
|
||||
case SCALE_IMM64: return 64;
|
||||
default: return -1;
|
||||
}
|
||||
}
|
||||
X64Reg GetSimpleReg() const
|
||||
{
|
||||
if (scale == SCALE_NONE)
|
||||
return (X64Reg)offsetOrBaseReg;
|
||||
else
|
||||
return INVALID_REG;
|
||||
}
|
||||
private:
|
||||
u8 scale;
|
||||
u8 offsetOrBaseReg;
|
||||
u8 indexReg;
|
||||
};
|
||||
|
||||
inline OpArg M(void *ptr) {return OpArg((u64)ptr, (int)SCALE_RIP);}
|
||||
inline OpArg R(X64Reg value) {return OpArg(0, SCALE_NONE, value);}
|
||||
inline OpArg MatR(X64Reg value) {return OpArg(0, SCALE_ATREG, value);}
|
||||
inline OpArg MDisp(X64Reg value, int offset) {
|
||||
return OpArg((u32)offset, SCALE_ATREG, value); }
|
||||
inline OpArg MComplex(X64Reg base, X64Reg scaled, int scale, int offset)
|
||||
{
|
||||
return OpArg(offset, scale, base, scaled);
|
||||
}
|
||||
inline OpArg Imm8 (u8 imm) {return OpArg(imm, SCALE_IMM8);}
|
||||
inline OpArg Imm16(u16 imm) {return OpArg(imm, SCALE_IMM16);} //rarely used
|
||||
inline OpArg Imm32(u32 imm) {return OpArg(imm, SCALE_IMM32);}
|
||||
inline OpArg Imm64(u64 imm) {return OpArg(imm, SCALE_IMM64);}
|
||||
#ifdef _M_X64
|
||||
inline OpArg ImmPtr(void* imm) {return Imm64((u64)imm);}
|
||||
#else
|
||||
inline OpArg ImmPtr(void* imm) {return Imm32((u32)imm);}
|
||||
#endif
|
||||
|
||||
void INT3();
|
||||
void NOP(int count = 1); //nop padding - TODO: fast nop slides, for amd and intel (check their manuals)
|
||||
void PAUSE();
|
||||
void RET();
|
||||
void STC();
|
||||
void CLC();
|
||||
void CMC();
|
||||
void PUSH(X64Reg reg);
|
||||
void POP(X64Reg reg);
|
||||
void PUSH(int bits, const OpArg ®);
|
||||
void POP(int bits, const OpArg ®);
|
||||
void PUSHF();
|
||||
void POPF();
|
||||
|
||||
typedef const u8* JumpTarget;
|
||||
|
||||
struct FixupBranch
|
||||
{
|
||||
u8 *ptr;
|
||||
int type; //0 = 8bit 1 = 32bit
|
||||
};
|
||||
|
||||
FixupBranch J(bool force5bytes = false);
|
||||
|
||||
void JMP(const u8 * addr, bool force5Bytes = false);
|
||||
void JMP(OpArg arg);
|
||||
void JMPptr(const OpArg &arg);
|
||||
void JMPself(); //infinite loop!
|
||||
|
||||
void CALL(void *fnptr);
|
||||
void CALLptr(OpArg arg);
|
||||
|
||||
FixupBranch J_CC(CCFlags conditionCode, bool force5bytes = false);
|
||||
void J_CC(CCFlags conditionCode, JumpTarget target);
|
||||
void J_CC(CCFlags conditionCode, const u8 * addr, bool force5Bytes = false);
|
||||
|
||||
void SetJumpTarget(const FixupBranch &branch);
|
||||
|
||||
//WARNING - INC and DEC slow on Intel Core, but not on AMD, since it creates
|
||||
//false flags dependencies because they only update a subset of the flags
|
||||
|
||||
// ector - I hereby BAN inc and dec due to their horribleness :P
|
||||
// void INC(int bits, OpArg arg);
|
||||
// void DEC(int bits, OpArg arg);
|
||||
|
||||
void SETcc(CCFlags flag, OpArg dest);
|
||||
// Note: CMOV brings small if any benefit on current cpus, unfortunately.
|
||||
void CMOVcc(int bits, X64Reg dest, OpArg src, CCFlags flag);
|
||||
|
||||
void LFENCE();
|
||||
void MFENCE();
|
||||
void SFENCE();
|
||||
|
||||
void BSF(int bits, X64Reg dest, OpArg src); //bottom bit to top bit
|
||||
void BSR(int bits, X64Reg dest, OpArg src); //top bit to bottom bit
|
||||
|
||||
//These two can not be executed on early Intel 64-bit CPU:s, only on AMD!
|
||||
|
||||
void LAHF(); // 3 cycle vector path
|
||||
void SAHF(); // direct path fast
|
||||
|
||||
//Looking for one of these? It's BANNED!! Some instructions are slow on modern CPU
|
||||
//LOOP, LOOPNE, LOOPE, ENTER, LEAVE, XLAT, REP MOVSB/MOVSD, REP SCASD + other string instr.,
|
||||
|
||||
//Actually REP MOVSD could be useful :P
|
||||
|
||||
void MOVNTI(int bits, OpArg dest, X64Reg src);
|
||||
|
||||
void MUL(int bits, OpArg src); //UNSIGNED
|
||||
void DIV(int bits, OpArg src);
|
||||
void IMUL(int bits, OpArg src); //SIGNED
|
||||
void IDIV(int bits, OpArg src);
|
||||
//TODO: alternate IMUL forms
|
||||
|
||||
void NEG(int bits, OpArg src);
|
||||
void NOT(int bits, OpArg src);
|
||||
|
||||
void ROL(int bits, OpArg dest, OpArg shift);
|
||||
void ROR(int bits, OpArg dest, OpArg shift);
|
||||
void RCL(int bits, OpArg dest, OpArg shift);
|
||||
void RCR(int bits, OpArg dest, OpArg shift);
|
||||
void SHL(int bits, OpArg dest, OpArg shift);
|
||||
void SHR(int bits, OpArg dest, OpArg shift);
|
||||
void SAR(int bits, OpArg dest, OpArg shift);
|
||||
|
||||
|
||||
void CWD(int bits = 16);
|
||||
inline void CDQ() {CWD(32);}
|
||||
inline void CQO() {CWD(64);}
|
||||
void CBW(int bits = 8);
|
||||
inline void CWDE() {CBW(16);}
|
||||
inline void CDQE() {CBW(32);}
|
||||
|
||||
void LEA(int bits, X64Reg dest, OpArg src);
|
||||
|
||||
|
||||
enum PrefetchLevel
|
||||
{
|
||||
PF_NTA, //Non-temporal (data used once and only once)
|
||||
PF_T0, //All cache levels
|
||||
PF_T1, //Levels 2+ (aliased to T0 on AMD)
|
||||
PF_T2, //Levels 3+ (aliased to T0 on AMD)
|
||||
};
|
||||
void PREFETCH(PrefetchLevel level, OpArg arg);
|
||||
|
||||
|
||||
void ADD (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void ADC (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void SUB (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void SBB (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void AND (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void OR (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void XOR (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void MOV (int bits, const OpArg &a1, const OpArg &a2);
|
||||
void TEST(int bits, const OpArg &a1, const OpArg &a2);
|
||||
void CMP (int bits, const OpArg &a1, const OpArg &a2);
|
||||
|
||||
// XCHG is SLOW and should be avoided.
|
||||
//void XCHG(int bits, const OpArg &a1, const OpArg &a2);
|
||||
|
||||
void XCHG_AHAL();
|
||||
void BSWAP(int bits, X64Reg reg);
|
||||
void MOVSX(int dbits, int sbits, X64Reg dest, OpArg src); //auto uses MOVSXD if necessary
|
||||
void MOVZX(int dbits, int sbits, X64Reg dest, OpArg src);
|
||||
|
||||
enum SSECompare
|
||||
{
|
||||
EQ = 0,
|
||||
LT,
|
||||
LE,
|
||||
UNORD,
|
||||
NEQ,
|
||||
NLT,
|
||||
NLE,
|
||||
ORD,
|
||||
};
|
||||
|
||||
|
||||
//SSE2
|
||||
// WARNING - These two take 11-13 cycles and are VectorPath! (AMD64)
|
||||
void STMXCSR(OpArg memloc);
|
||||
void LDMXCSR(OpArg memloc);
|
||||
|
||||
//Regular SSE instructions
|
||||
void ADDSS(X64Reg regOp, OpArg arg);
|
||||
void ADDSD(X64Reg regOp, OpArg arg);
|
||||
void SUBSS(X64Reg regOp, OpArg arg);
|
||||
void SUBSD(X64Reg regOp, OpArg arg);
|
||||
void CMPSS(X64Reg regOp, OpArg arg, u8 compare);
|
||||
void CMPSD(X64Reg regOp, OpArg arg, u8 compare);
|
||||
void ANDSS(X64Reg regOp, OpArg arg);
|
||||
void ANDSD(X64Reg regOp, OpArg arg);
|
||||
void ANDNSS(X64Reg regOp, OpArg arg);
|
||||
void ANDNSD(X64Reg regOp, OpArg arg);
|
||||
void ORSS(X64Reg regOp, OpArg arg);
|
||||
void ORSD(X64Reg regOp, OpArg arg);
|
||||
void XORSS(X64Reg regOp, OpArg arg);
|
||||
void XORSD(X64Reg regOp, OpArg arg);
|
||||
void MULSS(X64Reg regOp, OpArg arg);
|
||||
void MULSD(X64Reg regOp, OpArg arg);
|
||||
void DIVSS(X64Reg regOp, OpArg arg);
|
||||
void DIVSD(X64Reg regOp, OpArg arg);
|
||||
void MINSS(X64Reg regOp, OpArg arg);
|
||||
void MINSD(X64Reg regOp, OpArg arg);
|
||||
void MAXSS(X64Reg regOp, OpArg arg);
|
||||
void MAXSD(X64Reg regOp, OpArg arg);
|
||||
void SQRTSS(X64Reg regOp, OpArg arg);
|
||||
void SQRTSD(X64Reg regOp, OpArg arg);
|
||||
void RSQRTSS(X64Reg regOp, OpArg arg);
|
||||
void RSQRTSD(X64Reg regOp, OpArg arg);
|
||||
|
||||
void COMISS(X64Reg regOp, OpArg arg);
|
||||
void COMISD(X64Reg regOp, OpArg arg);
|
||||
|
||||
void ADDPS(X64Reg regOp, OpArg arg);
|
||||
void ADDPD(X64Reg regOp, OpArg arg);
|
||||
void SUBPS(X64Reg regOp, OpArg arg);
|
||||
void SUBPD(X64Reg regOp, OpArg arg);
|
||||
void CMPPS(X64Reg regOp, OpArg arg, u8 compare);
|
||||
void CMPPD(X64Reg regOp, OpArg arg, u8 compare);
|
||||
void ANDPS(X64Reg regOp, OpArg arg);
|
||||
void ANDPD(X64Reg regOp, OpArg arg);
|
||||
void ANDNPS(X64Reg regOp, OpArg arg);
|
||||
void ANDNPD(X64Reg regOp, OpArg arg);
|
||||
void ORPS(X64Reg regOp, OpArg arg);
|
||||
void ORPD(X64Reg regOp, OpArg arg);
|
||||
void XORPS(X64Reg regOp, OpArg arg);
|
||||
void XORPD(X64Reg regOp, OpArg arg);
|
||||
void MULPS(X64Reg regOp, OpArg arg);
|
||||
void MULPD(X64Reg regOp, OpArg arg);
|
||||
void DIVPS(X64Reg regOp, OpArg arg);
|
||||
void DIVPD(X64Reg regOp, OpArg arg);
|
||||
void MINPS(X64Reg regOp, OpArg arg);
|
||||
void MINPD(X64Reg regOp, OpArg arg);
|
||||
void MAXPS(X64Reg regOp, OpArg arg);
|
||||
void MAXPD(X64Reg regOp, OpArg arg);
|
||||
void SQRTPS(X64Reg regOp, OpArg arg);
|
||||
void SQRTPD(X64Reg regOp, OpArg arg);
|
||||
void RSQRTPS(X64Reg regOp, OpArg arg);
|
||||
void RSQRTPD(X64Reg regOp, OpArg arg);
|
||||
void SHUFPS(X64Reg regOp, OpArg arg, u8 shuffle);
|
||||
void SHUFPD(X64Reg regOp, OpArg arg, u8 shuffle);
|
||||
|
||||
void MOVDDUP(X64Reg regOp, OpArg arg);
|
||||
|
||||
void COMISS(X64Reg regOp, OpArg arg);
|
||||
void COMISD(X64Reg regOp, OpArg arg);
|
||||
void UCOMISS(X64Reg regOp, OpArg arg);
|
||||
void UCOMISD(X64Reg regOp, OpArg arg);
|
||||
|
||||
void MOVAPS(X64Reg regOp, OpArg arg);
|
||||
void MOVAPD(X64Reg regOp, OpArg arg);
|
||||
void MOVAPS(OpArg arg, X64Reg regOp);
|
||||
void MOVAPD(OpArg arg, X64Reg regOp);
|
||||
|
||||
void MOVUPS(X64Reg regOp, OpArg arg);
|
||||
void MOVUPD(X64Reg regOp, OpArg arg);
|
||||
void MOVUPS(OpArg arg, X64Reg regOp);
|
||||
void MOVUPD(OpArg arg, X64Reg regOp);
|
||||
|
||||
void MOVSS(X64Reg regOp, OpArg arg);
|
||||
void MOVSD(X64Reg regOp, OpArg arg);
|
||||
void MOVSS(OpArg arg, X64Reg regOp);
|
||||
void MOVSD(OpArg arg, X64Reg regOp);
|
||||
|
||||
void MOVMSKPS(X64Reg dest, OpArg arg);
|
||||
void MOVMSKPD(X64Reg dest, OpArg arg);
|
||||
|
||||
void MOVD_xmm(X64Reg dest, const OpArg &arg);
|
||||
void MOVQ_xmm(X64Reg dest, const OpArg &arg);
|
||||
void MOVD_xmm(const OpArg &arg, X64Reg src);
|
||||
void MOVQ_xmm(const OpArg &arg, X64Reg src);
|
||||
|
||||
void MASKMOVDQU(X64Reg dest, X64Reg src);
|
||||
void LDDQU(X64Reg dest, OpArg src);
|
||||
|
||||
void UNPCKLPD(X64Reg dest, OpArg src);
|
||||
void UNPCKHPD(X64Reg dest, OpArg src);
|
||||
|
||||
void CVTPS2PD(X64Reg dest, OpArg src);
|
||||
void CVTPD2PS(X64Reg dest, OpArg src);
|
||||
void CVTSS2SD(X64Reg dest, OpArg src);
|
||||
void CVTSD2SS(X64Reg dest, OpArg src);
|
||||
void CVTSD2SI(X64Reg dest, OpArg src);
|
||||
void CVTDQ2PD(X64Reg regOp, OpArg arg);
|
||||
void CVTPD2DQ(X64Reg regOp, OpArg arg);
|
||||
void CVTDQ2PS(X64Reg regOp, const OpArg &arg);
|
||||
|
||||
//Integer SSE instructions
|
||||
void PACKSSDW(X64Reg dest, OpArg arg);
|
||||
void PACKSSWB(X64Reg dest, OpArg arg);
|
||||
//void PACKUSDW(X64Reg dest, OpArg arg);
|
||||
void PACKUSWB(X64Reg dest, OpArg arg);
|
||||
|
||||
void PUNPCKLBW(X64Reg dest, const OpArg &arg);
|
||||
void PUNPCKLWD(X64Reg dest, const OpArg &arg);
|
||||
void PUNPCKLDQ(X64Reg dest, const OpArg &arg);
|
||||
|
||||
void PSRAD(X64Reg dest, int shift);
|
||||
|
||||
void PAND(X64Reg dest, OpArg arg);
|
||||
void PANDN(X64Reg dest, OpArg arg);
|
||||
void PXOR(X64Reg dest, OpArg arg);
|
||||
void POR(X64Reg dest, OpArg arg);
|
||||
|
||||
void PADDB(X64Reg dest, OpArg arg);
|
||||
void PADDW(X64Reg dest, OpArg arg);
|
||||
void PADDD(X64Reg dest, OpArg arg);
|
||||
void PADDQ(X64Reg dest, OpArg arg);
|
||||
|
||||
void PADDSB(X64Reg dest, OpArg arg);
|
||||
void PADDSW(X64Reg dest, OpArg arg);
|
||||
void PADDUSB(X64Reg dest, OpArg arg);
|
||||
void PADDUSW(X64Reg dest, OpArg arg);
|
||||
|
||||
void PSUBB(X64Reg dest, OpArg arg);
|
||||
void PSUBW(X64Reg dest, OpArg arg);
|
||||
void PSUBD(X64Reg dest, OpArg arg);
|
||||
void PSUBQ(X64Reg dest, OpArg arg);
|
||||
|
||||
void PSUBSB(X64Reg dest, OpArg arg);
|
||||
void PSUBSW(X64Reg dest, OpArg arg);
|
||||
void PSUBUSB(X64Reg dest, OpArg arg);
|
||||
void PSUBUSW(X64Reg dest, OpArg arg);
|
||||
|
||||
void PAVGB(X64Reg dest, OpArg arg);
|
||||
void PAVGW(X64Reg dest, OpArg arg);
|
||||
|
||||
void PCMPEQB(X64Reg dest, OpArg arg);
|
||||
void PCMPEQW(X64Reg dest, OpArg arg);
|
||||
void PCMPEQD(X64Reg dest, OpArg arg);
|
||||
|
||||
void PCMPGTB(X64Reg dest, OpArg arg);
|
||||
void PCMPGTW(X64Reg dest, OpArg arg);
|
||||
void PCMPGTD(X64Reg dest, OpArg arg);
|
||||
|
||||
void PEXTRW(X64Reg dest, OpArg arg, u8 subreg);
|
||||
void PINSRW(X64Reg dest, OpArg arg, u8 subreg);
|
||||
|
||||
void PMADDWD(X64Reg dest, OpArg arg);
|
||||
void PSADBW(X64Reg dest, OpArg arg);
|
||||
|
||||
void PMAXSW(X64Reg dest, OpArg arg);
|
||||
void PMAXUB(X64Reg dest, OpArg arg);
|
||||
void PMINSW(X64Reg dest, OpArg arg);
|
||||
void PMINUB(X64Reg dest, OpArg arg);
|
||||
|
||||
void PMOVMSKB(X64Reg dest, OpArg arg);
|
||||
|
||||
|
||||
namespace Util
|
||||
{
|
||||
// Sets up a __cdecl function.
|
||||
// Only x64 really needs the parameter.
|
||||
void EmitPrologue(int maxCallParams);
|
||||
void EmitEpilogue(int maxCallParams);
|
||||
}
|
||||
|
||||
void CallCdeclFunction3(void* fnptr, u32 arg0, u32 arg1, u32 arg2);
|
||||
void CallCdeclFunction4(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3);
|
||||
void CallCdeclFunction5(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
void CallCdeclFunction6(void* fnptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5);
|
||||
|
||||
#if defined(_M_IX86) || !defined(_WIN32)
|
||||
|
||||
#define CallCdeclFunction3_I(a,b,c,d) CallCdeclFunction3((void *)(a), (b), (c), (d))
|
||||
#define CallCdeclFunction4_I(a,b,c,d,e) CallCdeclFunction4((void *)(a), (b), (c), (d), (e))
|
||||
#define CallCdeclFunction5_I(a,b,c,d,e,f) CallCdeclFunction5((void *)(a), (b), (c), (d), (e), (f))
|
||||
#define CallCdeclFunction6_I(a,b,c,d,e,f,g) CallCdeclFunction6((void *)(a), (b), (c), (d), (e), (f), (g))
|
||||
|
||||
#define DECLARE_IMPORT(x)
|
||||
|
||||
#else
|
||||
|
||||
// Comments from VertexLoader.cpp about these horrors:
|
||||
|
||||
// This is a horrible hack that is necessary in 64-bit mode because Opengl32.dll is based way, way above the 32-bit
|
||||
// address space that is within reach of a CALL, and just doing &fn gives us these high uncallable addresses. So we
|
||||
// want to grab the function pointers from the import table instead.
|
||||
|
||||
void ___CallCdeclImport3(void* impptr, u32 arg0, u32 arg1, u32 arg2);
|
||||
void ___CallCdeclImport4(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3);
|
||||
void ___CallCdeclImport5(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4);
|
||||
void ___CallCdeclImport6(void* impptr, u32 arg0, u32 arg1, u32 arg2, u32 arg3, u32 arg4, u32 arg5);
|
||||
|
||||
#define CallCdeclFunction3_I(a,b,c,d) ___CallCdeclImport3(&__imp_##a,b,c,d)
|
||||
#define CallCdeclFunction4_I(a,b,c,d,e) ___CallCdeclImport4(&__imp_##a,b,c,d,e)
|
||||
#define CallCdeclFunction5_I(a,b,c,d,e,f) ___CallCdeclImport5(&__imp_##a,b,c,d,e,f)
|
||||
#define CallCdeclFunction6_I(a,b,c,d,e,f,g) ___CallCdeclImport6(&__imp_##a,b,c,d,e,f,g)
|
||||
|
||||
#define DECLARE_IMPORT(x) extern "C" void *__imp_##x
|
||||
|
||||
#endif
|
||||
|
||||
}
|
||||
|
||||
#endif
|
Reference in New Issue
Block a user