Initial megacommit.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@4 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2008-07-12 17:40:22 +00:00
parent a3be5d89ae
commit 775dc8a9c0
1920 changed files with 734652 additions and 0 deletions

View 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)");
}
}

View 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

View 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);
}*/

View 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

View 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
}

View 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

View 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();
}

View 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

View 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);
}

View 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

View 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 = &sections[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;
}
*/

View 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

View 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

View 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

View 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

View 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

View 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();
}

View 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

View 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
}

View 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

View 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
}

View 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

View 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

View 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

View 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

View 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

View 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)

View 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);*/
}

View 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

View 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);
}

View 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

View 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(&section, spincount);
}
else
{
InitializeCriticalSection(&section);
}
}
CriticalSection::~CriticalSection()
{
// No need to do anything
}
void CriticalSection::Enter()
{
EnterCriticalSection(&section);
}
bool CriticalSection::TryEnter()
{
return(TryEnterCriticalSection(&section) ? true : false);
}
void CriticalSection::Leave()
{
LeaveCriticalSection(&section);
}
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

View 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

View 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(&ltime);
return((u64)ltime);
}
} // end of namespace Common

View 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

View 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"

View 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>

View 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;
}

View 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

File diff suppressed because it is too large Load Diff

View 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 &reg);
void POP(int bits, const OpArg &reg);
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