Merge large parts of nakeee's "Soap" branch into trunk, after fixing a few crash bugs in FileUtil.cpp.

Not really anything interesting, just some better comments, some slightly more portable/cleaner code in places.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2459 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2009-02-28 01:26:56 +00:00
parent 2783f24cfe
commit 4bdb4aa0d1
77 changed files with 1610 additions and 1479 deletions

View File

@ -22,7 +22,6 @@
using namespace Gen;
// Shared code between Win64 and Unix64
// ====================================
// Sets up a __cdecl function.
void XEmitter::ABI_EmitPrologue(int maxCallParams)
@ -53,14 +52,14 @@ void XEmitter::ABI_EmitEpilogue(int maxCallParams)
RET();
#else
#error Arch not supported
#endif
}
#ifdef _M_IX86 // All32
// Shared code between Win32 and Unix32
// ====================================
void XEmitter::ABI_CallFunction(void *func) {
ABI_AlignStack(0);
CALL(func);
@ -160,8 +159,9 @@ void XEmitter::ABI_RestoreStack(unsigned int frameSize) {
}
}
#else
#else //64bit
// Common functions
void XEmitter::ABI_CallFunction(void *func) {
CALL(func);
}
@ -221,7 +221,6 @@ void XEmitter::ABI_RestoreStack(unsigned int /*frameSize*/) {
#ifdef _WIN32
// Win64 Specific Code
// ====================================
void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
//we only want to do this once
PUSH(RBX);
@ -249,7 +248,6 @@ void XEmitter::ABI_PopAllCalleeSavedRegsAndAdjustStack() {
}
// Win64 Specific Code
// ====================================
void XEmitter::ABI_PushAllCallerSavedRegsAndAdjustStack() {
PUSH(RCX);
PUSH(RDX);
@ -277,7 +275,6 @@ void XEmitter::ABI_PopAllCallerSavedRegsAndAdjustStack() {
#else
// Unix64 Specific Code
// ====================================
void XEmitter::ABI_PushAllCalleeSavedRegsAndAdjustStack() {
PUSH(RBX);
PUSH(RBP);
@ -322,7 +319,8 @@ void XEmitter::ABI_PopAllCallerSavedRegsAndAdjustStack() {
POP(RCX);
}
#endif
#endif // WIN32
#endif // 32bit
#endif

View File

@ -45,8 +45,7 @@
// Callee-save: RBX RBP R12 R13 R14 R15
// Parameters: RDI RSI RDX RCX R8 R9
#ifdef _M_IX86
// 32 bit calling convention, shared by all
#ifdef _M_IX86 // 32 bit calling convention, shared by all
// 32-bit don't pass parameters in regs, but these are convenient to have anyway when we have to
// choose regs to put stuff in.
@ -54,21 +53,19 @@
#define ABI_PARAM2 RDX
// There are no ABI_PARAM* here, since args are pushed.
// === 32-bit bog standard cdecl, shared between linux and windows ============================
// 32-bit bog standard cdecl, shared between linux and windows
// MacOSX 32-bit is same as System V with a few exceptions that we probably don't care much about.
#else
// 64 bit calling convention
#ifdef _WIN32
// === 64-bit Windows - the really exotic calling convention ==================================
#else // 64 bit calling convention
#ifdef _WIN32 // 64-bit Windows - the really exotic calling convention
#define ABI_PARAM1 RCX
#define ABI_PARAM2 RDX
#define ABI_PARAM3 R8
#define ABI_PARAM4 R9
#else
// === 64-bit Unix (hopefully MacOSX too) =====================================================
#else //64-bit Unix (hopefully MacOSX too)
#define ABI_PARAM1 RDI
#define ABI_PARAM2 RSI
@ -83,3 +80,4 @@
#endif // _JIT_ABI_H

View File

@ -35,29 +35,29 @@
static inline void do_cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
{
#ifdef _LP64
#ifdef _LP64
__asm__("cpuid"
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
);
#else
: "=a" (*eax),
"=b" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
);
#else
// Note: EBX is reserved on Mac OS X and in PIC on Linux, so it has to be
// restored at the end of the asm block.
__asm__(
"pushl %%ebx;"
"cpuid;"
"movl %%ebx,%1;"
"popl %%ebx;"
: "=a" (*eax),
"=r" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
);
#endif
"pushl %%ebx;"
"cpuid;"
"movl %%ebx,%1;"
"popl %%ebx;"
: "=a" (*eax),
"=r" (*ebx),
"=c" (*ecx),
"=d" (*edx)
: "a" (*eax)
);
#endif
}
void __cpuid(int info[4], int x)
@ -78,6 +78,7 @@ void __cpuid(int info[4], int x)
CPUInfo cpu_info;
// Detects the various cpu features
void CPUInfo::Detect()
{
memset(this, 0, sizeof(*this));
@ -88,26 +89,26 @@ void CPUInfo::Detect()
OS64bit = true;
#endif
num_cores = 1;
#ifdef _WIN32
#ifdef _M_IX86
BOOL f64 = FALSE;
OS64bit = IsWow64Process(GetCurrentProcess(), &f64) && f64;
bool f64 = false;
OS64bit = IsWow64Process(GetCurrentProcess(), (PBOOL)(&f64)) && f64;
#endif
#endif
// Set obvious defaults, for extra safety
if (Mode64bit)
{
if (Mode64bit) {
bSSE = true;
bSSE2 = true;
bLongMode = true;
}
// Assume CPU supports the CPUID instruction. Those that don't can barely boot modern OS:es anyway.
// Assume CPU supports the CPUID instruction. Those that don't can barely
// boot modern OS:es anyway.
int cpu_id[4];
memset(cpu_string, 0, sizeof(cpu_string));
// Detect CPU's CPUID capabilities, and grab cpu string
__cpuid(cpu_id, 0x00000000);
u32 max_std_fn = cpu_id[0]; // EAX
@ -122,10 +123,10 @@ void CPUInfo::Detect()
vendor = VENDOR_AMD;
else
vendor = VENDOR_OTHER;
// Set reasonable default brand string even if brand string not available.
strcpy(brand_string, cpu_string);
// Detect family and other misc stuff.
bool HTT = false;
int logical_cpu_count = 1;
@ -182,6 +183,7 @@ void CPUInfo::Detect()
}
}
// Turn the cpu info into a string we can show
std::string CPUInfo::Summarize()
{
std::string sum;

View File

@ -15,6 +15,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// Detect the cpu, so we'll know which optimizations to use
#ifndef _CPUDETECT_H
#define _CPUDETECT_H
@ -30,13 +31,13 @@ enum CPUVendor
struct CPUInfo
{
CPUVendor vendor;
char cpu_string[0x21];
char brand_string[0x41];
bool OS64bit;
bool CPU64bit;
bool Mode64bit;
bool hyper_threaded;
int num_cores;
@ -51,8 +52,11 @@ struct CPUInfo
bool bSSE4A;
bool bLAHFSAHF64;
bool bLongMode;
// Detects the various cpu features
void Detect();
// Turn the cpu info into a string we can show
std::string Summarize();
};

View File

@ -34,6 +34,7 @@
#include <string>
#include "Common.h"
#include "FileUtil.h"
template <class T>
struct LinkedListItem : public T
@ -41,15 +42,11 @@ struct LinkedListItem : public T
LinkedListItem<T> *next;
};
// Wrapper class
class PointerWrap
{
public:
/* READ is when we read from the save state file, WRITE is when we write to the
save state file. This enumareted list is also defined in pluginspecs.h. Didn't
want to couple them. */
enum Mode
{
enum Mode {
MODE_READ = 1,
MODE_WRITE,
MODE_MEASURE,
@ -68,8 +65,7 @@ public:
void DoVoid(void *data, int size)
{
switch (mode)
{
switch (mode) {
case MODE_READ: memcpy(data, *ptr, size); break;
case MODE_WRITE: memcpy(*ptr, data, size); break;
case MODE_MEASURE: break; // MODE_MEASURE - don't need to do anything
@ -84,22 +80,21 @@ public:
// TODO
PanicAlert("Do(map<>) does not yet work.");
}
// Store vectors.
template<class T>
void Do(std::vector<T> &x) {
// TODO
PanicAlert("Do(vector<>) does not yet work.");
}
// Store strings.
void Do(std::string &x)
{
int stringLen = (int)x.length() + 1;
Do(stringLen);
switch (mode)
{
switch (mode) {
case MODE_READ: x = (char*)*ptr; break;
case MODE_WRITE: memcpy(*ptr, x.c_str(), stringLen); break;
case MODE_MEASURE: break;
@ -110,33 +105,29 @@ public:
void DoBuffer(u8** pBuffer, u32& _Size)
{
Do(_Size);
if (_Size > 0)
{
switch (mode)
{
if (_Size > 0) {
switch (mode) {
case MODE_READ: *pBuffer = new u8[_Size]; memcpy(*pBuffer, *ptr, _Size); break;
case MODE_WRITE: memcpy(*ptr, *pBuffer, _Size); break;
case MODE_MEASURE: break;
}
}
else
{
} else {
*pBuffer = NULL;
}
(*ptr) += _Size;
}
template<class T>
void DoArray(T *x, int count) {
void DoArray(T *x, int count) {
DoVoid((void *)x, sizeof(T) * count);
}
template<class T>
void Do(T &x) {
DoVoid((void *)&x, sizeof(x));
}
template<class T>
void DoLinkedList(LinkedListItem<T> **list_start) {
// TODO
@ -148,85 +139,129 @@ public:
class CChunkFileReader
{
public:
// Load file template
template<class T>
static bool Load(const std::string& _rFilename, int _Revision, T& _class)
static bool Load(const std::string& _rFilename, int _Revision, T& _class)
{
FILE* pFile = fopen(_rFilename.c_str(), "rb");
if (pFile)
{
// get size
fseek(pFile, 0, SEEK_END);
size_t FileSize = ftell(pFile);
fseek(pFile, 0, SEEK_SET);
INFO_LOG(COMMON, "ChunkReader: Loading %s" , _rFilename.c_str());
if (FileSize < sizeof(SChunkHeader))
{
fclose(pFile);
return false;
}
// read the header
SChunkHeader Header;
fread(&Header, sizeof(SChunkHeader), 1, pFile);
if (Header.Revision != _Revision)
{
fclose(pFile);
return false;
}
// get size
int sz = (int)(FileSize - sizeof(SChunkHeader));
if (Header.ExpectedSize != sz)
{
fclose(pFile);
return false;
}
// read the state
u8* buffer = new u8[sz];
fread(buffer, 1, sz, pFile);
fclose(pFile);
u8 *ptr = buffer;
PointerWrap p(&ptr, PointerWrap::MODE_READ);
_class.DoState(p);
delete [] buffer;
return true;
if (! File::Exists(_rFilename.c_str()))
return false;
// Check file size
u64 fileSize = File::GetSize(_rFilename.c_str());
u64 headerSize = sizeof(SChunkHeader);
if (fileSize < headerSize) {
ERROR_LOG(COMMON,"ChunkReader: File too small");
return false;
}
return false;
}
FILE* pFile;
if (! (pFile = fopen(_rFilename.c_str(), "rb"))) {
ERROR_LOG(COMMON,"ChunkReader: Can't open file for reading");
return false;
}
// read the header
SChunkHeader header;
if (fread(&header, 1, headerSize, pFile) != headerSize) {
fclose(pFile);
ERROR_LOG(COMMON,"ChunkReader: Bad header size");
return false;
}
// Check revision
if (header.Revision != _Revision) {
fclose(pFile);
ERROR_LOG(COMMON,"ChunkReader: Wrong file revision, got %d expected %d",
header.Revision, _Revision);
return false;
}
// get size
int sz = (int)(fileSize - headerSize);
if (header.ExpectedSize != sz) {
fclose(pFile);
ERROR_LOG(COMMON,"ChunkReader: Bad file size, got %d expected %d",
sz, header.ExpectedSize);
return false;
}
// read the state
u8* buffer = new u8[sz];
if ((int)fread(buffer, 1, sz, pFile) != sz) {
fclose(pFile);
ERROR_LOG(COMMON,"ChunkReader: Error reading file");
return false;
}
// done reading
if (fclose(pFile)) {
ERROR_LOG(COMMON,"ChunkReader: Error closing file! might be corrupted!");
// should never happen!
return false;
}
u8 *ptr = buffer;
PointerWrap p(&ptr, PointerWrap::MODE_READ);
_class.DoState(p);
delete [] buffer;
INFO_LOG(COMMON, "ChunkReader: Done loading %s" , _rFilename.c_str());
return true;
}
// Save file template
template<class T>
static bool Save(const std::string& _rFilename, int _Revision, T& _class)
{
FILE* pFile = fopen(_rFilename.c_str(), "wb");
if (pFile)
{
u8 *ptr = 0;
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
_class.DoState(p);
size_t sz = (size_t)ptr;
u8 *buffer = new u8[sz];
ptr = buffer;
p.SetMode(PointerWrap::MODE_WRITE);
_class.DoState(p);
FILE* pFile;
SChunkHeader Header;
Header.Compress = 0;
Header.Revision = _Revision;
Header.ExpectedSize = (int)sz;
fwrite(&Header, sizeof(SChunkHeader), 1, pFile);
fwrite(buffer, sz, 1, pFile);
fclose(pFile);
return true;
INFO_LOG(COMMON, "ChunkReader: Writing %s" , _rFilename.c_str());
if (! (pFile = fopen(_rFilename.c_str(), "wb"))) {
ERROR_LOG(COMMON,"ChunkReader: Error opening file for write");
return false;
}
return false;
// Get data
u8 *ptr = 0;
PointerWrap p(&ptr, PointerWrap::MODE_MEASURE);
_class.DoState(p);
size_t sz = (size_t)ptr;
u8 *buffer = new u8[sz];
ptr = buffer;
p.SetMode(PointerWrap::MODE_WRITE);
_class.DoState(p);
// Create header
SChunkHeader header;
header.Compress = 0;
header.Revision = _Revision;
header.ExpectedSize = (int)sz;
// Write to file
if (fwrite(&header, sizeof(SChunkHeader), 1, pFile) != 1) {
ERROR_LOG(COMMON,"ChunkReader: Failed writing header");
return false;
}
if (fwrite(buffer, sz, 1, pFile) != 1) {
ERROR_LOG(COMMON,"ChunkReader: Failed writing data");
return false;
}
if (fclose(pFile)) {
ERROR_LOG(COMMON,"ChunkReader: Error closing file! might be corrupted!");
return false;
}
INFO_LOG(COMMON,"ChunkReader: Done writing %s",
_rFilename.c_str());
return true;
}
private:
struct SChunkHeader
{

View File

@ -18,51 +18,28 @@
#ifndef _COMMON_H
#define _COMMON_H
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// -----------------
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#define CHECK_HEAP_INTEGRITY()
//////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Include
// -----------------
#ifdef _WIN32
#ifdef _DEBUG
#include <crtdbg.h>
#undef CHECK_HEAP_INTEGRITY
#define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
#endif
/* Turn on logging with debugging, _DEBUG and DEBUGFAST are still added through
preprocessor definitions only */
#if defined(_DEBUG) || defined(DEBUGFAST)
#define LOGGING
#endif
#include "../../../PluginSpecs/CommonTypes.h"
#define HAVE_WIIUSE 1
#define HAVE_WX 1
#else
#include "CommonTypes.h"
#include "Config.h"
#endif
#include <stdlib.h>
#include <stdio.h>
#include <string.h>
#include "Paths.h"
///////////////////////////////////
// Force enable logging in the right modes. For some reason, something had changed
// so that debugfast no longer logged.
#ifdef _DEBUG
#undef LOGGING
#define LOGGING 1
#endif
#ifdef DEBUGFAST
#undef LOGGING
#define LOGGING 1
#endif
#include "Log.h"
#include "CommonTypes.h"
#include "MsgHandler.h"
#include "CommonPaths.h"
#include "CommonFuncs.h"
//////////////////////////////////////////////////////////////////////////////////////////
// Settings
// -----------------
// Darwin ABI requires that stack frames be aligned to 16-byte boundaries.
// This probably wouldn't break anyone either, but hey
@ -72,325 +49,73 @@
#define STACKALIGN
#endif
// Function Cross-Compatibility
#ifdef _WIN32
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define unlink _unlink
#define snprintf _snprintf
#else
#define _stricmp strcasecmp
#define _strnicmp strncasecmp
#define _unlink unlink
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
#endif
// Check MSC ver
#if !defined _MSC_VER || _MSC_VER <= 1000
#error needs at least version 1000 of MSC
#endif
#ifdef _WIN32
// By default, MS' stdio implementation does not support 64-bit offsets.
// This little hack fixes that, keeping the code portable to linux where fseek and fread
// do support 64-bit offsets in modern distributions.
#define fseek _fseeki64
#define ftell _ftelli64
// Memory leak check defines
#define _CRTDBG_MAP_ALLOC
#define _CRTDBG_MAP_ALLOC_NEW
#define CHECK_HEAP_INTEGRITY()
#define atoll _atoi64
#define POSIX 0
#define NOMINMAX
#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 POSIX 1
#define MAX_PATH 260
#define stricmp strcasecmp
#define Crash() {asm ("int $3");}
#ifdef _LP64
#define _M_X64 1
#else
#define _M_IX86 1
#endif
#endif
#define POSIX 0
#define NOMINMAX
// Alignment
#define GC_ALIGNED16(x) __declspec(align(16)) x
#define GC_ALIGNED32(x) __declspec(align(32)) x
#define GC_ALIGNED64(x) __declspec(align(64)) x
#define GC_ALIGNED16_DECL(x) __declspec(align(16)) x
#define GC_ALIGNED64_DECL(x) __declspec(align(64)) x
#if defined(_MSC_VER)
// Since they are always around on windows
#define HAVE_WIIUSE 1
#define HAVE_WX 1
#define GC_ALIGNED16(x) __declspec(align(16)) x
#define GC_ALIGNED32(x) __declspec(align(32)) x
#define GC_ALIGNED64(x) __declspec(align(64)) x
#define GC_ALIGNED16_DECL(x) __declspec(align(16)) x
#define GC_ALIGNED64_DECL(x) __declspec(align(64)) x
#else
#define GC_ALIGNED16(x) __attribute((aligned(16))) x
#define GC_ALIGNED32(x) __attribute((aligned(16))) x
#define GC_ALIGNED64(x) __attribute((aligned(64))) x
#define GC_ALIGNED16_DECL(x) __attribute((aligned(16))) x
#define GC_ALIGNED64_DECL(x) __attribute((aligned(64))) x
#endif
// Various Windows compatibility
#if !defined(_WIN32)
inline u32 _rotl(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x << shift) | (x >> (32 - shift));
}
inline u32 _rotr(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x >> shift) | (x << (32 - shift));
}
#define LONG int
#ifndef __forceinline
#define __forceinline inline
#endif
#endif
#if defined (_M_IX86) && defined (_WIN32)
#define HWCALL __cdecl
#else
#define HWCALL
#endif
#undef min
#undef max
template<class T>
inline T min(const T& a, const T& b) {return a > b ? b : a;}
template<class T>
inline T max(const T& a, const T& b) {return a > b ? a : b;}
///////////////////////////////////
// **************************************************************************************
// Utility functions
// **************************************************************************************
//////////////////////////////////////////////////////////////////////////////////////////
// Byte ordering
// -----------------
namespace Common
namespace
{
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
inline u16 swap16(u8* _pData) {return(swap16(*(u16*)_pData));}
inline u32 swap32(u8* _pData) {return(swap32(*(u32*)_pData));}
inline u64 swap64(u8* _pData) {return(swap64(*(u64*)_pData));}
} // end of namespace Common
///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Message alerts
// -----------------
enum MSG_TYPE
{
INFORMATION,
QUESTION,
WARNING,
};
typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
bool yes_no, int Style);
void RegisterMsgAlertHandler(MsgAlertHandler handler);
extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...);
#ifdef _WIN32
#define SuccessAlert(format, ...) MsgAlert("Information", false, INFORMATION, format, __VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert("Warning", false, WARNING, format, __VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert("Warning", true, WARNING, format, __VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert("Question", true, QUESTION, format, __VA_ARGS__)
#else
#define SuccessAlert(format, ...) MsgAlert("SUCCESS", false, INFORMATION, format, ##__VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert("PANIC", false, WARNING, format, ##__VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__)
#endif
///////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Logging
// -----------------
// 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,
CONSOLE,
OSREPORT,
WII_IOB,
WII_IPC,
WII_IPC_HLE,
WII_IPC_DVD,
WII_IPC_ES,
WII_IPC_FILEIO,
WII_IPC_SD,
WII_IPC_NET,
WII_IPC_WIIMOTE,
ACTIONREPLAY,
NUMBER_OF_LOGS
};
};
#ifdef LOGGING
extern void __Log(int logNumber, const char* text, ...);
extern void __Logv(int log, int v, const char *format, ...);
void Host_UpdateLogDisplay();
// Logging macros. LOGGING is turned on from earlier in this file
#ifdef _WIN32
#define LOG(t, ...) __Log(LogTypes::t, __VA_ARGS__);
#define LOGV(t,v, ...) __Log(LogTypes::t + (v)*100, __VA_ARGS__);
#define LOGP(t, ...) __Log(t, __VA_ARGS__);
#define LOGVP(t,v, ...) __Log(t + (v)*100, __VA_ARGS__);
#else
#define LOG(t, ...) __Log(LogTypes::t, ##__VA_ARGS__);
#define LOGV(t,v, ...) __Log(LogTypes::t + (v)*100, ##__VA_ARGS__);
#define LOGP(t, ...) __Log(t, ##__VA_ARGS__);
#define LOGVP(t,v, ...) __Log(t + (v)*100, ##__VA_ARGS__);
#endif
#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 LOGV(_t_,_v_, ...)
#define LOGP(_t_, ...)
#define LOGVP(_t_,_v_, ...)
#define _dbg_clear_()
#ifndef _dbg_assert_
#define _dbg_assert_(_t_, _a_) ;
#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ;
#endif
#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
///////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// Compile time asserts
// -----------------
namespace
{
// it is very risky to mix _SECURE_SCL=0 and _SECURE_SCL=1 compiled libraries
// it is possible that you overwrite memory if you do it
#ifdef _WIN32
// it is VERY DANGEROUS to mix _SECURE_SCL=0 and _SECURE_SCL=1 compiled libraries.
// You will get bizarre crash bugs whenever you use STL.
#ifndef _SECURE_SCL
#error Please define _SECURE_SCL=0 in the project settings
#error Please define _SECURE_SCL=0 in the project settings
#else
template <bool> struct CompileTimeAssert;
template<> struct CompileTimeAssert<true> {};
CompileTimeAssert<_SECURE_SCL==0> x;
#endif
#endif
}
///////////////////////////////////////
// Debug definions
#if defined(_DEBUG)
#include <crtdbg.h>
#undef CHECK_HEAP_INTEGRITY
#define CHECK_HEAP_INTEGRITY() {if (!_CrtCheckMemory()) PanicAlert("memory corruption detected. see log.");}
#endif // end DEBUG/FAST
#ifdef _WIN32
#define SLEEP(x) Sleep(x)
#else
#define SLEEP(x) usleep(x*1000)
#endif
#else // Not windows
#endif // _COMMON_H
#include "Config.h" // Scons defines
// General defines
#define POSIX 1
#define MAX_PATH 260
// Windows compatibility
#define __forceinline inline
#ifdef _LP64
#define _M_X64 1
#else
#define _M_IX86 1
#endif
// Alignment
#define GC_ALIGNED16(x) __attribute((aligned(16))) x
#define GC_ALIGNED32(x) __attribute((aligned(16))) x
#define GC_ALIGNED64(x) __attribute((aligned(64))) x
#define GC_ALIGNED16_DECL(x) __attribute((aligned(16))) x
#define GC_ALIGNED64_DECL(x) __attribute((aligned(64))) x
#endif // WIN32
#endif // COMMON_H

View File

@ -0,0 +1,110 @@
// 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 COMMONFUNCS_H
#define COMMONFUNCS_H
#ifdef _WIN32
#define SLEEP(x) Sleep(x)
#else
#define SLEEP(x) usleep(x*1000)
#endif
#ifndef _WIN32
#include <errno.h>
#include <byteswap.h>
// go to debugger mode
#define Crash() {asm ("int $3");}
#define ARRAYSIZE(A) (sizeof(A)/sizeof((A)[0]))
inline u32 _rotl(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x << shift) | (x >> (32 - shift));
}
inline u32 _rotr(u32 x, int shift) {
shift &= 31;
if (!shift) return x;
return (x >> shift) | (x << (32 - shift));
}
#define SLEEP(x) usleep(x*1000)
#else // WIN32
// Function Cross-Compatibility
#define strcasecmp _stricmp
#define strncasecmp _strnicmp
#define unlink _unlink
#define snprintf _snprintf
char* strndup (char const *s, size_t n);
// 64 bit offsets for windows
#define fseek _fseeki64
#define ftell _ftelli64
#define atoll _atoi64
#define stat64 _stat64
#define SLEEP(x) Sleep(x)
#if _M_IX86
#define Crash() {__asm int 3}
#else
extern "C" {
__declspec(dllimport) void __stdcall DebugBreak(void);
}
#define Crash() {DebugBreak();}
#endif // M_IX86
#endif // WIN32 ndef
// Dolphin's min and max functions
#undef min
#undef max
template<class T>
inline T min(const T& a, const T& b) {return a > b ? b : a;}
template<class T>
inline T max(const T& a, const T& b) {return a > b ? a : b;}
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.
// Defined in Misc.cpp.
const char* GetLastErrorMsg();
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__
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
// Slow generic implementation.
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
inline u16 swap16(const u8* _pData) {return swap16(*(const u16*)_pData);}
inline u32 swap32(const u8* _pData) {return swap32(*(const u32*)_pData);}
inline u64 swap64(const u8* _pData) {return swap64(*(const u64*)_pData);}
} // namespace Common
#endif // COMMONFUNCS

View File

@ -1,130 +1,159 @@
#ifndef PATHS_H
#define PATHS_H
#ifdef _WIN32
#define PLUGIN_PREFIX ""
#define PLUGIN_SUFFIX ".dll"
#else
#ifdef __APPLE__
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".dylib"
#else
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".so"
#endif
#endif
#define DIR_SEP "/"
#define DIR_SEP_CHR '/'
#define PLUGINS_DIR "Plugins"
#define ROOT_DIR "."
#define USERDATA_DIR "User"
#define SYSDATA_DIR "Sys"
// Dirs in both User and Sys
#define EUR_DIR "EUR"
#define USA_DIR "USA"
#define JAP_DIR "JAP"
// Dirs in User
#define GC_USER_DIR "GC"
#define WII_USER_DIR "Wii"
#define WII_SYSCONF_DIR "shared2/sys"
#define CONFIG_DIR "Config"
#define GAMECONFIG_DIR "GameConfig"
#define MAPS_DIR "Maps"
#define CACHE_DIR "Cache"
#define STATESAVES_DIR "StateSaves"
#define SCREENSHOTS_DIR "ScreenShots"
#define DUMP_DIR "Dump"
#define LOGS_DIR "Logs"
#define MAIL_LOGS_DIR "Mail"
// Dirs in Sys
#define GC_SYS_DIR "GC"
#define WII_SYS_DIR "Wii"
// Filenames
#define DOLPHIN_CONFIG "Dolphin.ini"
#define DEBUGGER_CONFIG "Debugger.ini"
#define TOTALDB "totaldb.dsy"
#define DEFAULT_GFX_PLUGIN PLUGIN_PREFIX "Plugin_VideoOGL" PLUGIN_SUFFIX
#define DEFAULT_DSP_PLUGIN PLUGIN_PREFIX "Plugin_DSP_HLE" PLUGIN_SUFFIX
#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_PadSimple" PLUGIN_SUFFIX
#define DEFAULT_WIIMOTE_PLUGIN PLUGIN_PREFIX "Plugin_Wiimote" PLUGIN_SUFFIX
#define FONT_ANSI "font_ansi.bin"
#define FONT_SJIS "font_sjis.bin"
#define DSP_ROM "dsp_rom.bin"
#define DSP_COEF "dsp_coef.bin"
#define GC_IPL "IPL.bin"
#define GC_SRAM "SRAM.raw"
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
#define WII_EUR_SETTING "setting-eur.txt"
#define WII_USA_SETTING "setting-usa.txt"
#define WII_JAP_SETTING "setting-jpn.txt"
#define WII_SYSCONF "SYSCONF"
#define MEMORY_DUMP_FILE "mainram.dump"
// Shorts - dirs
// User dirs
#define FULL_USERDATA_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
#define FULL_GC_USER_DIR FULL_USERDATA_DIR GC_USER_DIR DIR_SEP
//#define GC_USER_EUR_DIR FULL_GC_USER_DIR EUR_DIR
//#define GC_USER_USA_DIR FULL_GC_USER_DIR USA_DIR
//#define GC_USER_JAP_DIR FULL_GC_USER_DIR JAP_DIR
#define FULL_WII_USER_DIR FULL_USERDATA_DIR WII_USER_DIR DIR_SEP
#define FULL_WII_ROOT_DIR FULL_USERDATA_DIR WII_USER_DIR // This is the "root" for Wii fs, so that it may be used with created devices
#define FULL_GAMECONFIG_DIR FULL_USERDATA_DIR GAMECONFIG_DIR DIR_SEP
#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP
#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP
#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
#define FULL_DUMP_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP
#define FULL_LOGS_DIR FULL_USERDATA_DIR LOGS_DIR DIR_SEP
#define FULL_MAIL_LOGS_DIR FULL_LOGS_DIR MAIL_LOGS_DIR DIR_SEP
#define FULL_MAPS_DIR FULL_USERDATA_DIR MAPS_DIR DIR_SEP
// Sys dirs
#define FULL_SYSDATA_DIR ROOT_DIR DIR_SEP SYSDATA_DIR DIR_SEP
#define FULL_GC_SYS_DIR FULL_SYSDATA_DIR GC_SYS_DIR DIR_SEP
//#define GC_SYS_EUR_DIR FULL_GC_SYS_DIR EUR_DIR
//#define GC_SYS_USA_DIR FULL_GC_SYS_DIR USA_DIR
//#define GC_SYS_JAP_DIR FULL_GC_SYS_DIR JAP_DIR
#define FULL_WII_SYS_DIR FULL_SYSDATA_DIR WII_SYS_DIR DIR_SEP
// Shorts - files
// User files
#define CONFIG_FILE FULL_CONFIG_DIR DOLPHIN_CONFIG
#define DEBUGGER_CONFIG_FILE FULL_CONFIG_DIR DEBUGGER_CONFIG
#define TOTALDB_FILE FULL_SYSDATA_DIR TOTALDB
#define MAINRAM_DUMP_FILE FULL_DUMP_DIR MEMORY_DUMP_FILE
#define GC_SRAM_FILE FULL_USERDATA_DIR GC_USER_DIR DIR_SEP GC_SRAM
// Sys files
#define FONT_ANSI_FILE FULL_GC_SYS_DIR FONT_ANSI
#define FONT_SJIS_FILE FULL_GC_SYS_DIR FONT_SJIS
#define DSP_ROM_FILE FULL_GC_SYS_DIR DSP_ROM
#define DSP_COEF_FILE FULL_GC_SYS_DIR DSP_COEF
#define WII_EUR_SETTING_FILE FULL_WII_SYS_DIR WII_EUR_SETTING
#define WII_USA_SETTING_FILE FULL_WII_SYS_DIR WII_USA_SETTING
#define WII_JAP_SETTING_FILE FULL_WII_SYS_DIR WII_JAP_SETTING
#define WII_SYSCONF_FILE FULL_WII_USER_DIR WII_SYSCONF_DIR DIR_SEP WII_SYSCONF
#define FULL_WII_MENU_DIR FULL_WII_USER_DIR "title" DIR_SEP "00000001" DIR_SEP "00000002" DIR_SEP "content"
#endif // PATHS_H
// 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_PATHS_H
#define COMMON_PATHS_H
// Library suffix/prefix
#ifdef _WIN32
#define PLUGIN_PREFIX ""
#define PLUGIN_SUFFIX ".dll"
#elif defined __APPLE__
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".dylib"
#else
#define PLUGIN_PREFIX "lib"
#define PLUGIN_SUFFIX ".so"
#endif
// Directory seperators, do we need this?
#define DIR_SEP "/"
#define DIR_SEP_CHR '/'
#define PLUGINS_DIR "Plugins"
#define ROOT_DIR "."
#define USERDATA_DIR "User"
#define SYSDATA_DIR "Sys"
// Where data directory is
#ifdef _WIN32
#define DOLPHIN_DATA_DIR "Dolphin"
#elif defined __APPLE__
#define DOLPHIN_DATA_DIR "Library/Application Support/Dolphin"
#else
#define DOLPHIN_DATA_DIR ".dolphin"
#endif
// Dirs in both User and Sys
#define EUR_DIR "EUR"
#define USA_DIR "USA"
#define JAP_DIR "JAP"
// Dirs in User
#define GC_USER_DIR "GC"
#define WII_USER_DIR "Wii"
#define WII_SYSCONF_DIR "shared2/sys"
#define CONFIG_DIR "Config"
#define GAMECONFIG_DIR "GameConfig"
#define MAPS_DIR "Maps"
#define CACHE_DIR "Cache"
#define STATESAVES_DIR "StateSaves"
#define SCREENSHOTS_DIR "ScreenShots"
#define DUMP_DIR "Dump"
#define LOGS_DIR "Logs"
#define MAIL_LOGS_DIR "Mail"
// Dirs in Sys
#define GC_SYS_DIR "GC"
#define WII_SYS_DIR "Wii"
// Filenames
#define DOLPHIN_CONFIG "Dolphin.ini"
#define DEBUGGER_CONFIG "Debugger.ini"
#define LOGGER_CONFIG "Logger.ini"
#define TOTALDB "totaldb.dsy"
#define DEFAULT_GFX_PLUGIN PLUGIN_PREFIX "Plugin_VideoOGL" PLUGIN_SUFFIX
#define DEFAULT_DSP_PLUGIN PLUGIN_PREFIX "Plugin_DSP_HLE" PLUGIN_SUFFIX
#define DEFAULT_PAD_PLUGIN PLUGIN_PREFIX "Plugin_PadSimple" PLUGIN_SUFFIX
#define DEFAULT_WIIMOTE_PLUGIN PLUGIN_PREFIX "Plugin_Wiimote" PLUGIN_SUFFIX
#define FONT_ANSI "font_ansi.bin"
#define FONT_SJIS "font_sjis.bin"
#define DSP_ROM "dsp_rom.bin"
#define DSP_COEF "dsp_coef.bin"
#define GC_IPL "IPL.bin"
#define GC_SRAM "SRAM.raw"
#define GC_MEMCARDA "MemoryCardA"
#define GC_MEMCARDB "MemoryCardB"
#define WII_EUR_SETTING "setting-eur.txt"
#define WII_USA_SETTING "setting-usa.txt"
#define WII_JAP_SETTING "setting-jpn.txt"
#define WII_SYSCONF "SYSCONF"
#define MEMORY_DUMP_FILE "mainram.dump"
// Shorts - dirs
// User dirs
#define FULL_USERDATA_DIR ROOT_DIR DIR_SEP USERDATA_DIR DIR_SEP
#define FULL_GC_USER_DIR FULL_USERDATA_DIR GC_USER_DIR DIR_SEP
//#define GC_USER_EUR_DIR FULL_GC_USER_DIR EUR_DIR
//#define GC_USER_USA_DIR FULL_GC_USER_DIR USA_DIR
//#define GC_USER_JAP_DIR FULL_GC_USER_DIR JAP_DIR
#define FULL_WII_USER_DIR FULL_USERDATA_DIR WII_USER_DIR DIR_SEP
#define FULL_WII_ROOT_DIR FULL_USERDATA_DIR WII_USER_DIR // This is the "root" for Wii fs, so that it may be used with created devices
#define FULL_GAMECONFIG_DIR FULL_USERDATA_DIR GAMECONFIG_DIR DIR_SEP
#define FULL_CONFIG_DIR FULL_USERDATA_DIR CONFIG_DIR DIR_SEP
#define FULL_CACHE_DIR FULL_USERDATA_DIR CACHE_DIR DIR_SEP
#define FULL_STATESAVES_DIR FULL_USERDATA_DIR STATESAVES_DIR DIR_SEP
#define FULL_SCREENSHOTS_DIR FULL_USERDATA_DIR SCREENSHOTS_DIR DIR_SEP
#define FULL_DUMP_DIR FULL_USERDATA_DIR DUMP_DIR DIR_SEP
#define FULL_LOGS_DIR FULL_USERDATA_DIR LOGS_DIR DIR_SEP
#define FULL_MAIL_LOGS_DIR FULL_LOGS_DIR MAIL_LOGS_DIR DIR_SEP
#define FULL_MAPS_DIR FULL_USERDATA_DIR MAPS_DIR DIR_SEP
// Sys dirs
#define FULL_SYSDATA_DIR ROOT_DIR DIR_SEP SYSDATA_DIR DIR_SEP
#define FULL_GC_SYS_DIR FULL_SYSDATA_DIR GC_SYS_DIR DIR_SEP
//#define GC_SYS_EUR_DIR FULL_GC_SYS_DIR EUR_DIR
//#define GC_SYS_USA_DIR FULL_GC_SYS_DIR USA_DIR
//#define GC_SYS_JAP_DIR FULL_GC_SYS_DIR JAP_DIR
#define FULL_WII_SYS_DIR FULL_SYSDATA_DIR WII_SYS_DIR DIR_SEP
// Shorts - files
// User files
#define CONFIG_FILE FULL_CONFIG_DIR DOLPHIN_CONFIG
#define DEBUGGER_CONFIG_FILE FULL_CONFIG_DIR DEBUGGER_CONFIG
#define LOGGER_CONFIG_FILE FULL_CONFIG_DIR LOGGER_CONFIG
#define TOTALDB_FILE FULL_SYSDATA_DIR TOTALDB
#define MAINRAM_DUMP_FILE FULL_DUMP_DIR MEMORY_DUMP_FILE
#define GC_SRAM_FILE FULL_USERDATA_DIR GC_USER_DIR DIR_SEP GC_SRAM
// Sys files
#define FONT_ANSI_FILE FULL_GC_SYS_DIR FONT_ANSI
#define FONT_SJIS_FILE FULL_GC_SYS_DIR FONT_SJIS
#define DSP_ROM_FILE FULL_GC_SYS_DIR DSP_ROM
#define DSP_COEF_FILE FULL_GC_SYS_DIR DSP_COEF
#define WII_EUR_SETTING_FILE FULL_WII_SYS_DIR WII_EUR_SETTING
#define WII_USA_SETTING_FILE FULL_WII_SYS_DIR WII_USA_SETTING
#define WII_JAP_SETTING_FILE FULL_WII_SYS_DIR WII_JAP_SETTING
#define WII_SYSCONF_FILE FULL_WII_USER_DIR WII_SYSCONF_DIR DIR_SEP WII_SYSCONF
#define FULL_WII_MENU_DIR FULL_WII_USER_DIR "title" DIR_SEP "00000001" DIR_SEP "00000002" DIR_SEP "content"
#endif // COMMON_PATHS_H

View File

@ -0,0 +1,58 @@
// 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/
// This header contains type definitions that are shared between the Dolphin
// core and the plugin specs. Any definitions that are only used by the core
// should be placed in "Common.h" instead.
#ifndef _COMMONTYPES_H
#define _COMMONTYPES_H
#ifdef _WIN32
#include <tchar.h>
typedef unsigned __int8 u8;
typedef unsigned __int16 u16;
typedef unsigned __int32 u32;
typedef unsigned __int64 u64;
typedef signed __int8 s8;
typedef signed __int16 s16;
typedef signed __int32 s32;
typedef signed __int64 s64;
#else
typedef unsigned char u8;
typedef unsigned short u16;
typedef unsigned int u32;
typedef unsigned long long u64;
typedef char s8;
typedef short s16;
typedef int s32;
typedef long long s64;
// For using windows lock code
#define TCHAR char
#define LONG int
#endif // _WIN32
#endif // _COMMONTYPES_H

View File

@ -15,8 +15,10 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
// All plugins from Core > Plugins are loaded and unloaded with this class when
// Dolphin is started and stopped.
/*
All plugins from Core > Plugins are loaded and unloaded with this class when
Dolpin is started and stopped.
*/
#include <string.h> // System
#ifdef _WIN32
@ -32,113 +34,116 @@
#include "DynamicLibrary.h"
#include "ConsoleWindow.h"
DynamicLibrary::DynamicLibrary()
{
library = 0;
}
std::string GetLastErrorAsString()
// Gets the last dll error as string
const char *DllGetLastError()
{
#ifdef _WIN32
LPVOID lpMsgBuf = 0;
DWORD error = GetLastError();
FormatMessage(
FORMAT_MESSAGE_ALLOCATE_BUFFER | FORMAT_MESSAGE_FROM_SYSTEM,
NULL,
error,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT), // Default language
(LPTSTR) &lpMsgBuf,
0, NULL);
std::string s;
if (lpMsgBuf)
{
s = ((char *)lpMsgBuf);
LocalFree(lpMsgBuf);
} else {
s = StringFromFormat("(unknown error %08x)", error);
}
return s;
#else
static std::string errstr;
char *tmp = dlerror();
if (tmp)
errstr = tmp;
return errstr;
#endif
return GetLastErrorMsg();
#else // not win32
return dlerror();
#endif // WIN32
}
/* Function: Loading means loading the dll with LoadLibrary() to get an
instance to the dll. This is done when Dolphin is started to determine
which dlls are good, and before opening the Config and Debugging windows
from Plugin.cpp and before opening the dll for running the emulation in
Video_...cpp in Core. Since this is fairly slow, TODO: think about
implementing some sort of cache.
Called from: The Dolphin Core */
/* Loads the dll with LoadLibrary() or dlopen. This function is called on
start to scan for plugin, and before opening the Config and Debugging
windows. It is also called from core to load the plugins when the
emulation starts.
Returns 0 on failure and 1 on success
TODO: think about implementing some sort of cache for the plugin info.
*/
int DynamicLibrary::Load(const char* filename)
{
if (!filename || strlen(filename) == 0)
{
LOG(MASTER_LOG, "Missing filename of dynamic library to load");
PanicAlert("Missing filename of dynamic library to load");
INFO_LOG(COMMON, "DL: Loading dynamic library %s", filename);
if (!filename || strlen(filename) == 0) {
ERROR_LOG(COMMON, "DL: Missing filename to load");
return 0;
}
if (IsLoaded())
{
LOG(MASTER_LOG, "Trying to load already loaded library %s", filename);
return 2;
if (IsLoaded()) {
INFO_LOG(COMMON, "DL: library %s already loaded", filename);
return 1;
}
Console::Print("LoadLibrary: %s", filename);
#ifdef _WIN32
library = LoadLibrary(filename);
#else
// RTLD_NOW: resolve all symbols on load
// RTLD_LOCAL: don't resolve symbols for other libraries
library = dlopen(filename, RTLD_NOW | RTLD_LOCAL);
#endif
Console::Print(" %p\n", library);
if (!library)
{
LOG(MASTER_LOG, "Error loading DLL %s: %s", filename, GetLastErrorAsString().c_str());
PanicAlert("Error loading DLL %s: %s\n", filename, GetLastErrorAsString().c_str());
DEBUG_LOG(COMMON, "DL: LoadLibrary: %s(%p)", filename, library);
if (!library) {
ERROR_LOG(COMMON, "DL: Error loading DLL %s: %s", filename,
DllGetLastError());
return 0;
}
library_file = filename;
INFO_LOG(COMMON, "DL: Done loading dynamic library %s", filename);
return 1;
}
/* Frees one instances of the dynamic library. Note that on most systems use
reference count to decide when to actually remove the library from memory.
Return 0 on failure and 1 on success
*/
int DynamicLibrary::Unload()
{
int retval;
if (!IsLoaded())
{
PanicAlert("Error unloading DLL %s: not loaded", library_file.c_str());
return 0;
}
INFO_LOG(COMMON, "DL: Unloading dynamic library %s", library_file.c_str());
int retval;
if (!IsLoaded()) { // library != null
ERROR_LOG(COMMON, "DL: Unload failed for %s: not loaded",
library_file.c_str());
PanicAlert("DL: Unload failed %s: not loaded",
library_file.c_str());
return 0;
}
Console::Print("FreeLibrary: %s %p\n", library_file.c_str(), library);
DEBUG_LOG(COMMON, "DL: FreeLibrary: %s %p\n",
library_file.c_str(), library);
#ifdef _WIN32
retval = FreeLibrary(library);
retval = FreeLibrary(library);
#else
retval = dlclose(library) ? 0 : 1;
retval = dlclose(library)?0:1;
#endif
if (!retval)
{
PanicAlert("Error unloading DLL %s: %s", library_file.c_str(),
GetLastErrorAsString().c_str());
}
library = 0;
return retval;
if (! retval) {
ERROR_LOG(COMMON, "DL: Unload failed %s: %s",
library_file.c_str(),
DllGetLastError());
}
library = 0;
INFO_LOG(COMMON, "DL: Done unloading dynamic library %s",
library_file.c_str());
return retval;
}
// Returns the address where symbol funcname is loaded or NULL on failure
void* DynamicLibrary::Get(const char* funcname) const
{
void* retval;
INFO_LOG(COMMON, "DL: Getting symbol %s: %s", library_file.c_str(),
funcname);
if (!library)
{
PanicAlert("Can't find function %s - Library not loaded.");
ERROR_LOG(COMMON, "DL: Get failed %s - Library not loaded");
return NULL;
}
@ -150,9 +155,14 @@ void* DynamicLibrary::Get(const char* funcname) const
if (!retval)
{
LOG(MASTER_LOG, "Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
PanicAlert("Symbol %s missing in %s (error: %s)\n", funcname, library_file.c_str(), GetLastErrorAsString().c_str());
ERROR_LOG(COMMON, "DL: Symbol %s missing in %s (error: %s)\n",
funcname, library_file.c_str(),
DllGetLastError());
}
INFO_LOG(COMMON, "DL: Done getting symbol %s: %s", library_file.c_str(),
funcname);
return retval;
}

View File

@ -24,19 +24,31 @@
#include <string>
// Abstracts the (few) differences between dynamically loading DLLs under Windows
// and .so / .dylib under Linux/MacOSX.
/* Abstracts the (few) differences between dynamically loading DLLs under
Windows and .so / .dylib under Linux/MacOSX. */
class DynamicLibrary
{
public:
DynamicLibrary();
// Loads the library filename
int Load(const char *filename);
// Unload the current library
int Unload();
// Gets a pointer to the function symbol of funcname by getting it from the
// share object
void *Get(const char *funcname) const;
// Returns true is the library is loaded
bool IsLoaded() const { return library != 0; }
private:
// name of the library file
std::string library_file;
// Library handle
#ifdef _WIN32
HINSTANCE library;
#else
@ -44,4 +56,4 @@ private:
#endif
};
#endif
#endif // DYNAMICLIBRARY

View File

@ -32,106 +32,118 @@
#include <stdlib.h>
#endif
#if defined(__APPLE__)
#include <CoreFoundation/CFString.h>
#include <CoreFoundation/CFUrl.h>
#include <CoreFoundation/CFBundle.h>
#include <sys/param.h>
#endif
#include <fstream>
#include <sys/stat.h>
#ifndef S_ISDIR
#define S_ISDIR(m) (((m)&S_IFMT) == S_IFDIR)
#endif
/*
This namespace has various generic functions related to files and paths.
The code still needs a ton of cleanup.
REMEMBER: strdup considered harmful!
*/
namespace File
{
// =======================================================
// Remove any ending forward slashes from directory paths
// -------------
inline void StripTailDirSlashes(std::string& fname)
// Modifies argument.
inline char *StripTailDirSlashes(char *fname)
{
// Make sure it's not a blank string
if(fname.length() > 0)
{
while(fname.at(fname.length() - 1) == DIR_SEP_CHR)
fname.resize(fname.length() - 1);
}
int len = (int)strlen(fname);
int i = len - 1;
if (len > 1)
while (fname[i] == DIR_SEP_CHR)
fname[i--] = '\0';
return fname;
}
// =============
// Returns true if file filename exists
bool Exists(const char *filename)
{
struct stat file_info;
char *copy = StripTailDirSlashes(strdup(filename));
int result = stat(copy, &file_info);
std::string copy = filename;
StripTailDirSlashes(copy);
if (result < 0)
{
WARN_LOG(COMMON, "Exist: stat failed on %s: %s", filename,
GetLastErrorMsg());
}
free(copy);
int result = stat(copy.c_str(), &file_info);
return (result == 0);
}
// Returns true if filename is a directory
bool IsDirectory(const char *filename)
{
struct stat file_info;
std::string copy = filename;
StripTailDirSlashes(copy);
int result = stat(copy.c_str(), &file_info);
if (result == 0)
return S_ISDIR(file_info.st_mode);
else
char *copy = StripTailDirSlashes(strdup(filename));
int result = stat(copy, &file_info);
free(copy);
if (result < 0) {
WARN_LOG(COMMON, "IsDirectory: stat failed on %s: %s",
filename, GetLastErrorMsg());
return false;
}
return S_ISDIR(file_info.st_mode);
}
// Deletes a given filename, return true on success
// Doesn't supports deleting a directory
bool Delete(const char *filename)
{
if (!Exists(filename))
return false;
if (IsDirectory(filename))
INFO_LOG(COMMON, "Delete: file %s\n", filename);
// Return true because we care about the file no
// being there, not the actual delete.
if (!Exists(filename)) {
WARN_LOG(COMMON, "Delete: %s does not exists", filename);
return true;
}
// We can't delete a directory
if (IsDirectory(filename)) {
WARN_LOG(COMMON, "Delete: %s is a directory", filename);
return false;
}
#ifdef _WIN32
DeleteFile(filename);
if (!DeleteFile(filename)) {
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename, GetLastErrorMsg());
return false;
}
#else
unlink(filename);
if (unlink(filename) == -1) {
WARN_LOG(COMMON, "Delete: DeleteFile failed on %s: %s",
filename, GetLastErrorMsg());
return false;
}
#endif
return true;
}
std::string SanitizePath(const char *filename)
{
std::string copy = filename;
#ifdef _WIN32
for (size_t i = 0; i < copy.size(); i++)
if (copy[i] == '/')
copy[i] = '\\';
#else
// Should we do the otherway around?
#endif
return copy;
}
// Returns true if successful, or path already exists.
bool CreateDir(const char *path)
{
INFO_LOG(COMMON, "CreateDir: directory %s\n", path);
#ifdef _WIN32
if (::CreateDirectory(path, NULL))
return true;
DWORD error = GetLastError();
if (error == ERROR_ALREADY_EXISTS)
{
// PanicAlert("%s already exists", path);
if (error == ERROR_ALREADY_EXISTS) {
WARN_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: already exists", path);
return true;
}
PanicAlert("Error creating directory %s: %i", path, error);
ERROR_LOG(COMMON, "CreateDir: CreateDirectory failed on %s: %i", path, error);
return false;
#else
if (mkdir(path, 0755) == 0)
@ -139,434 +151,374 @@ bool CreateDir(const char *path)
int err = errno;
if (err == EEXIST)
{
// PanicAlert("%s already exists", path);
if (err == EEXIST) {
WARN_LOG(COMMON, "CreateDir: mkdir failed on %s: already exists", path);
return true;
}
PanicAlert("Error creating directory %s: %s", path, strerror(err));
ERROR_LOG(COMMON, "CreateDir: mkdir failed on %s: %s", path, strerror(err));
return false;
#endif
}
// Create several dirs
bool CreateDirectoryStructure(const std::string& _rFullPath)
// Creates the full path of fullPath returns true on success
bool CreateFullPath(const char *fullPath)
{
int PanicCounter = 10;
size_t Position = 0;
while(true)
{
int panicCounter = 100;
INFO_LOG(COMMON, "CreateFullPath: path %s\n", fullPath);
const char *position = fullPath;
while (true) {
// Find next sub path, support both \ and / directory separators
{
size_t nextPosition = _rFullPath.find(DIR_SEP_CHR, Position);
Position = nextPosition;
position = strchr(position, DIR_SEP_CHR);
if (Position == std::string::npos)
return true;
Position++;
}
// we're done, yay!
if (! position)
return true;
position++;
// Create next sub path
std::string SubPath = _rFullPath.substr(0, Position);
if (!SubPath.empty())
{
if (!File::IsDirectory(SubPath.c_str()))
{
File::CreateDir(SubPath.c_str());
LOG(WII_IPC_FILEIO, " CreateSubDir %s", SubPath.c_str());
int sLen = (int)(position - fullPath);
if (sLen > 0) {
char *subPath = strndup(fullPath, sLen);
if (!File::IsDirectory(subPath)) {
File::CreateDir(subPath);
}
free(subPath);
}
// A safety check
PanicCounter--;
if (PanicCounter <= 0)
{
PanicAlert("CreateDirectoryStruct creates way to much dirs...");
panicCounter--;
if (panicCounter <= 0) {
ERROR_LOG(COMMON, "CreateFullPath: directory stracture too deep");
return false;
}
}
}
// Deletes a directory filename, returns true on success
bool DeleteDir(const char *filename)
{
INFO_LOG(COMMON, "DeleteDir: directory %s", filename);
if (!File::IsDirectory(filename))
// check if a directory
if (!File::IsDirectory(filename)) {
ERROR_LOG(COMMON, "DeleteDir: Not a directory %s",
filename);
return false;
}
#ifdef _WIN32
return ::RemoveDirectory (filename) ? true : false;
if (::RemoveDirectory(filename))
return true;
#else
if (rmdir(filename) == 0)
return true;
int err = errno;
PanicAlert("Error removing directory %s",strerror(err));
return false;
if (rmdir(filename) == 0)
return true;
#endif
ERROR_LOG(COMMON, "DeleteDir: %s: %s",
filename, GetLastErrorMsg());
return false;
}
// renames file srcFilename to destFilename, returns true on success
bool Rename(const char *srcFilename, const char *destFilename)
{
return (rename(srcFilename, destFilename) == 0);
INFO_LOG(COMMON, "Rename: %s --> %s",
srcFilename, destFilename);
if (rename(srcFilename, destFilename) == 0)
return true;
ERROR_LOG(COMMON, "Rename: failed %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
}
// copies file srcFilename to destFilename, returns true on success
bool Copy(const char *srcFilename, const char *destFilename)
{
INFO_LOG(COMMON, "Copy: %s --> %s",
srcFilename, destFilename);
#ifdef _WIN32
return (CopyFile(srcFilename, destFilename, FALSE) == TRUE) ? true : false;
if (CopyFile(srcFilename, destFilename, FALSE))
return true;
ERROR_LOG(COMMON, "Copy: failed %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
#else
// buffer size
#define BSIZE 1024
int rnum, wnum, err;
char buffer[BSIZE];
FILE *output, *input;
if (! (input = fopen(srcFilename, "r"))) {
err = errno;
PanicAlert("Error copying from %s: %s", srcFilename, strerror(err));
return false;
}
char buffer[BSIZE];
if (! (output = fopen(destFilename, "w"))) {
err = errno;
PanicAlert("Error copying to %s: %s", destFilename, strerror(err));
return false;
}
while(! feof(input)) {
if((rnum = fread(buffer, sizeof(char), BSIZE, input)) != BSIZE) {
if(ferror(input) != 0){
PanicAlert("can't read source file\n");
return false;
}
}
if((wnum = fwrite(buffer, sizeof(char), rnum, output))!= rnum){
PanicAlert("can't write output file\n");
// Open input file
FILE *input = fopen(srcFilename, "rb");
if (!input)
{
ERROR_LOG(COMMON, "Copy: input failed %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
}
}
fclose(input);
fclose(output);
return true;
/*
std::ifstream ifs(srcFilename, std::ios::binary);
std::ofstream ofs(destFilename, std::ios::binary);
ofs << ifs.rdbuf();
// open output file
FILE *output = fopen(destFilename, "wb");
if (!output)
{
fclose(input);
ERROR_LOG(COMMON, "Copy: output failed %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
}
ifs.close();
ofs.close();
return true;*/
// copy loop
while (!feof(input))
{
// read input
int rnum = fread(buffer, sizeof(char), BSIZE, input);
if (rnum != BSIZE)
{
if (ferror(input) != 0) {
ERROR_LOG(COMMON,
"Copy: failed reading from source, %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
}
}
// write output
int wnum = fwrite(buffer, sizeof(char), rnum, output)
if (wnum != rnum)
{
ERROR_LOG(COMMON,
"Copy: failed writing to output, %s --> %s: %s",
srcFilename, destFilename, GetLastErrorMsg());
return false;
}
}
// close flushs
fclose(input);
fclose(output);
return true;
#endif
}
std::string GetUserDirectory()
// Returns a pointer to a string with a Dolphin data dir in the user's home directory.
// To be used in "multi-user" mode (that is, installed).
const char *GetUserDirectory()
{
char path[MAX_PATH];
#ifdef _WIN32
if (SUCCEEDED(SHGetFolderPath(NULL, CSIDL_COMMON_APPDATA, NULL, 0, path)))
{
//return std::string(path);
// Make sure we only need to do it once
static char path[MAX_PATH] = {0};
if (strlen(path) > 0)
return path;
/* I dont understand this, I got "E:\Documents and Settings\All Users\Application Data"
from this */
return std::string("");
}
return std::string("");
#ifdef WIN32
char homedir[MAX_PATH];
if (!SUCCEEDED(SHGetFolderPath(NULL, CSIDL_APPDATA, NULL, 0, path)))
return NULL;
#else
char *homedir = getenv("HOME");
if (!homedir)
return std::string("");
#ifdef __APPLE__
snprintf(path, sizeof(path), "%s/Library/Application Support/Dolphin", homedir);
#else
snprintf(path, sizeof(path), "%s/.dolphin", homedir); // XXX changeme as appropriate
return NULL;
#endif
#endif
return std::string(path);
snprintf(path, sizeof(path), "%s" DIR_SEP DOLPHIN_DATA_DIR, homedir);
INFO_LOG(COMMON, "GetUserDirectory: Setting to %s:", path);
return path;
}
//osx specific functions
#if defined(__APPLE__)
std::string GetBundleDirectory()
{
// Plugin path will be Dolphin.app/Contents/PlugIns
CFURLRef BundleRef;
char AppBundlePath[MAXPATHLEN];
// Get the main bundle for the app
BundleRef = CFBundleCopyBundleURL(CFBundleGetMainBundle());
CFStringRef BundlePath = CFURLCopyFileSystemPath(BundleRef, kCFURLPOSIXPathStyle);
CFStringGetFileSystemRepresentation(BundlePath, AppBundlePath, sizeof(AppBundlePath));
CFRelease(BundleRef);
CFRelease(BundlePath);
return AppBundlePath;
}
std::string GetPluginsDirectory()
{
CFURLRef PluginDirRef;
char PluginPath[MAXPATHLEN];
PluginDirRef = CFBundleCopyBuiltInPlugInsURL(CFBundleGetMainBundle());
CFStringRef PluginDirPath = CFURLCopyFileSystemPath(PluginDirRef, kCFURLPOSIXPathStyle);
CFStringGetFileSystemRepresentation(PluginDirPath, PluginPath, sizeof(PluginPath));
CFRelease(PluginDirRef);
CFRelease(PluginDirPath);
std::string PluginsDir = GetBundleDirectory();
PluginsDir += DIR_SEP;
PluginsDir += PluginPath;
return PluginsDir;
}
#endif
// Returns the size of filename (64bit)
u64 GetSize(const char *filename)
{
if (!Exists(filename))
if (!Exists(filename)) {
WARN_LOG(COMMON, "GetSize: failed %s: No such file"
,filename);
return 0;
#ifdef _WIN32
// stat doesn't support 64-bit file sizes on Win32.
FILE *pFile = fopen(filename, "rb");
if (pFile)
{
fseek(pFile, 0, SEEK_END);
u64 pos = ftell(pFile);
fclose(pFile);
return pos;
}
#else
struct stat buf;
if (stat(filename, &buf) == 0) {
return buf.st_size;
}
int err = errno;
PanicAlert("Error accessing %s: %s", filename, strerror(err));
#endif
return 0;
if (IsDirectory(filename)) {
WARN_LOG(COMMON, "GetSize: failed %s: is a directory"
,filename);
return 0;
}
// on windows it's actually _stat64 defined in commonFuncs
struct stat64 buf;
if (stat64(filename, &buf) == 0) {
return buf.st_size;
}
ERROR_LOG(COMMON, "GetSize: Stat failed %s: %s",
filename, GetLastErrorMsg());
return 0;
}
#ifdef _WIN32
static bool ReadFoundFile(const WIN32_FIND_DATA& ffd, FSTEntry& entry)
{
// ignore files starting with a .
if(strncmp(ffd.cFileName, ".", 1) == 0)
return false;
entry.virtualName = ffd.cFileName;
if(ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
entry.isDirectory = true;
}
else
{
entry.isDirectory = false;
entry.size = ffd.nFileSizeLow;
}
return true;
}
u32 ScanDirectoryTree(const std::string& _Directory, FSTEntry& parentEntry)
{
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
std::string searchName = _Directory + "\\*";
HANDLE hFind = FindFirstFile(searchName.c_str(), &ffd);
u32 foundEntries = 0;
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
FSTEntry entry;
if(ReadFoundFile(ffd, entry))
{
entry.physicalName = _Directory + "\\" + entry.virtualName;
if(entry.isDirectory)
{
u32 childEntries = ScanDirectoryTree(entry.physicalName, entry);
entry.size = childEntries;
foundEntries += childEntries;
}
++foundEntries;
parentEntry.children.push_back(entry);
}
} while (FindNextFile(hFind, &ffd) != 0);
}
FindClose(hFind);
return foundEntries;
}
#else
u32 ScanDirectoryTree(const std::string& _Directory, FSTEntry& parentEntry)
{
u32 foundEntries = 0;
struct dirent dirent, *result = NULL;
// Find the first file in the directory.
DIR *dirp = opendir(_Directory.c_str());
while (!readdir_r(dirp, &dirent, &result) && result) {
FSTEntry entry;
if (result->d_name[0]=='.') continue;
entry.virtualName = result->d_name;
entry.physicalName = _Directory + "/" + entry.virtualName;
if (IsDirectory(entry.physicalName.c_str())) {
entry.isDirectory = true;
entry.size = ScanDirectoryTree(entry.physicalName, entry);
foundEntries += entry.size;
} else {
entry.isDirectory = false;
entry.size = GetSize(entry.physicalName.c_str());
}
++foundEntries;
parentEntry.children.push_back(entry);
}
closedir(dirp);
return foundEntries;
}
#endif
// creates an empty file filename, returns true on success
bool CreateEmptyFile(const char *filename)
{
FILE* pFile = fopen(filename, "wb");
if (pFile == NULL)
return false;
INFO_LOG(COMMON, "CreateEmptyFile: %s", filename);
FILE *pFile = fopen(filename, "wb");
if (!pFile) {
ERROR_LOG(COMMON, "CreateEmptyFile: failed %s: %s",
filename, GetLastErrorMsg());
return false;
}
fclose(pFile);
return true;
}
bool DeleteDirRecursively(const std::string& _Directory)
// Scans the directory tree gets, starting from _Directory and adds the
// results into parentEntry. Returns the number of files+directories found
u32 ScanDirectoryTree(const char *directory, FSTEntry& parentEntry)
{
INFO_LOG(COMMON, "ScanDirectoryTree: directory %s", directory);
// How many files + directories we found
u32 foundEntries = 0;
char *virtualName;
#ifdef _WIN32
bool Result = false;
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
std::string searchName = _Directory + "\\*";
HANDLE hFind = FindFirstFile(searchName.c_str(), &ffd);
char searchName[MAX_PATH + 3];
strncpy(searchName, directory, MAX_PATH);
strcat(searchName, "\\*");
if (hFind != INVALID_HANDLE_VALUE)
{
do
{
// check for "." and ".."
if (((ffd.cFileName[0] == '.') && (ffd.cFileName[1] == 0x00)) ||
((ffd.cFileName[0] == '.') && (ffd.cFileName[1] == '.') && (ffd.cFileName[2] == 0x00)))
continue;
// build path
std::string newPath(_Directory);
newPath += '\\';
newPath += ffd.cFileName;
if (ffd.dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY)
{
if (!File::DeleteDirRecursively(newPath))
goto error_jmp;
}
else
{
if (!File::Delete(newPath.c_str()))
goto error_jmp;
}
} while (FindNextFile(hFind, &ffd) != 0);
HANDLE hFind = FindFirstFile(searchName, &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
FindClose(hFind);
return foundEntries;
}
if (!File::DeleteDir(_Directory.c_str()))
goto error_jmp;
Result = true;
error_jmp:
FindClose(hFind);
return Result;
// windows loop
do {
FSTEntry entry;
virtualName = ffd.cFileName;
#else
// taken from http://www.dreamincode.net/code/snippet2700.htm
DIR *pdir = NULL;
pdir = opendir (_Directory.c_str());
struct dirent *pent = NULL;
if (pdir == NULL) {
return false;
}
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory);
if (!dirp)
return 0;
char file[256];
int counter = 1;
while ((pent = readdir(pdir))) {
if (counter > 2) {
for (int i = 0; i < 256; i++) file[i] = '\0';
strcat(file, _Directory.c_str());
if (pent == NULL) {
return false;
}
strcat(file, pent->d_name);
if (IsDirectory(file) == true) {
DeleteDir(file);
} else {
remove(file);
}
}
counter++;
}
return DeleteDir(_Directory.c_str());
// non windows loop
while (!readdir_r(dirp, &dirent, &result) && result) {
FSTEntry entry;
virtualName = result->d_name;
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
entry.virtualName = virtualName;
entry.physicalName = directory;
entry.physicalName += DIR_SEP + entry.virtualName;
if (IsDirectory(entry.physicalName.c_str())) {
entry.isDirectory = true;
// is a directory, lets go inside
entry.size = ScanDirectoryTree(entry.physicalName.c_str(), entry);
foundEntries += (u32)entry.size;
} else { // is a file
entry.isDirectory = false;
entry.size = GetSize(entry.physicalName.c_str());
}
++foundEntries;
// Push into the tree
parentEntry.children.push_back(entry);
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
#else
}
closedir(dirp);
#endif
// Return number of entries found.
return foundEntries;
}
void GetCurrentDirectory(std::string& _rDirectory)
// deletes the given directory and anything under it. Returns true on
// success.
bool DeleteDirRecursively(const char *directory)
{
char tmpBuffer[MAX_PATH+1];
_rDirectory = getcwd(tmpBuffer, MAX_PATH);
INFO_LOG(COMMON, "DeleteDirRecursively: %s", directory);
#ifdef _WIN32
// Find the first file in the directory.
WIN32_FIND_DATA ffd;
char searchName[MAX_PATH + 3] = {0};
strncpy(searchName, directory, MAX_PATH);
strcat(searchName, "\\*");
HANDLE hFind = FindFirstFile(searchName, &ffd);
if (hFind == INVALID_HANDLE_VALUE) {
FindClose(hFind);
return false;
}
// windows loop
do {
char *virtualName = ffd.cFileName;
#else
struct dirent dirent, *result = NULL;
DIR *dirp = opendir(directory);
if (!dirp)
return false;
// non windows loop
while (!readdir_r(dirp, &dirent, &result) && result) {
char *virtualName = result->d_name;
#endif
// check for "." and ".."
if (((virtualName[0] == '.') && (virtualName[1] == '\0')) ||
((virtualName[0] == '.') && (virtualName[1] == '.') &&
(virtualName[2] == '\0')))
continue;
char newPath[MAX_PATH];
sprintf(newPath, "%s%c%s", directory, DIR_SEP_CHR, virtualName);
if (IsDirectory(newPath)) {
if (!DeleteDirRecursively(newPath))
return false;
} else {
if (!File::Delete(newPath))
return false;
}
#ifdef _WIN32
} while (FindNextFile(hFind, &ffd) != 0);
FindClose(hFind);
#else
}
#endif
File::DeleteDir(directory);
return true;
}
bool SetCurrentDirectory(const std::string& _rDirectory)
// Returns the current directory, caller should free
const char *GetCurrentDirectory()
{
return chdir(_rDirectory.c_str()) == 0;
const char *dir;
// Get the current working directory (getcwd uses malloc)
if (!(dir = getcwd(NULL, 0))) {
ERROR_LOG(COMMON, "GetCurrentDirectory failed: %s",
GetLastErrorMsg());
return NULL;
}
return dir;
}
// Sets the current directory to the given directory
bool SetCurrentDirectory(const char *_rDirectory)
{
return chdir(_rDirectory) == 0;
}
} // namespace

View File

@ -20,45 +20,73 @@
#include <string>
#include <vector>
#include <string.h>
#include "Common.h"
/*
This namespace has various generic functions related to files and paths.
*/
namespace File
{
// FileSystem tree node/
struct FSTEntry
{
bool isDirectory;
u32 size; // file length or number of entries from children
u64 size; // file length or number of entries from children
std::string physicalName; // name on disk
std::string virtualName; // name in FST names table
std::vector<FSTEntry> children;
};
std::string SanitizePath(const char *filename);
// Returns true if file filename exists
bool Exists(const char *filename);
// Returns true if filename is a directory
bool IsDirectory(const char *filename);
bool IsDisk(const char *filename);
bool CreateDir(const char *filename);
bool CreateDirectoryStructure(const std::string& _rFullPath);
bool Delete(const char *filename);
bool DeleteDir(const char *filename);
bool Rename(const char *srcFilename, const char *destFilename);
bool Copy(const char *srcFilename, const char *destFilename);
// Returns the size of filename (64bit)
u64 GetSize(const char *filename);
std::string GetUserDirectory();
// Returns true if successful, or path already exists.
bool CreateDir(const char *filename);
// Creates the full path of fullPath returns true on success
bool CreateFullPath(const char *fullPath);
// Deletes a given filename, return true on success
// Doesn't supports deleting a directory
bool Delete(const char *filename);
// Deletes a directory filename, returns true on success
bool DeleteDir(const char *filename);
// renames file srcFilename to destFilename, returns true on success
bool Rename(const char *srcFilename, const char *destFilename);
// copies file srcFilename to destFilename, returns true on success
bool Copy(const char *srcFilename, const char *destFilename);
// creates an empty file filename, returns true on success
bool CreateEmptyFile(const char *filename);
u32 ScanDirectoryTree(const std::string& _Directory, FSTEntry& parentEntry);
bool DeleteDirRecursively(const std::string& _Directory);
void GetCurrentDirectory(std::string& _rDirectory);
bool SetCurrentDirectory(const std::string& _rDirectory);
#if defined(__APPLE__)
std::string GetPluginsDirectory();
#endif
// Scans the directory tree gets, starting from _Directory and adds the
// results into parentEntry. Returns the number of files+directories found
u32 ScanDirectoryTree(const char *directory, FSTEntry& parentEntry);
// deletes the given directory and anything under it. Returns true on success.
bool DeleteDirRecursively(const char *directory);
// Returns the current directory, caller should free
const char *GetCurrentDirectory();
// Set the current directory to given directory
bool SetCurrentDirectory(const char *directory);
// Returns a pointer to a string with the dolphin data dir
const char *GetUserDirectory();
} // namespace
#endif

View File

@ -14,6 +14,7 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef _HASH_H
#define _HASH_H
@ -24,5 +25,4 @@ u32 HashAdler32(const u8* data, size_t len); // Fairly accurate, slightl
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

@ -459,10 +459,10 @@ bool IniFile::Get(const char* sectionName, const char* key, std::vector<std::str
return false;
}
u32 subEnd;
// ignore starting , if any
u32 subStart = temp.find_first_not_of(",");
size_t subStart = temp.find_first_not_of(",");
size_t subEnd;
// split by ,
while (subStart != std::string::npos) {

View File

@ -0,0 +1,147 @@
// 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 _LOG_H
#define _LOG_H
namespace LogTypes
{
enum LOG_TYPE {
ACTIONREPLAY,
AUDIO,
AUDIO_INTERFACE,
BOOT,
COMMANDPROCESSOR,
COMMON,
CONSOLE,
DSPHLE,
DSPINTERFACE,
DVDINTERFACE,
DYNA_REC,
EXPANSIONINTERFACE,
GEKKO,
GPFIFO,
HLE,
MASTER_LOG,
MEMMAP,
OSREPORT,
PERIPHERALINTERFACE,
PIXELENGINE,
SERIALINTERFACE,
STREAMINGINTERFACE,
VIDEO,
VIDEOINTERFACE,
WII_IOB,
WII_IPC,
WII_IPC_DVD,
WII_IPC_ES,
WII_IPC_FILEIO,
WII_IPC_HLE,
WII_IPC_NET,
WII_IPC_SD,
WII_IPC_WIIMOTE,
NUMBER_OF_LOGS // Must be last
};
enum LOG_LEVELS {
LERROR, // Bad errors - that still don't deserve a PanicAlert.
LWARNING, // Something is suspicious.
LINFO, // General information.
LDEBUG, // Strictly for detailed debugging - might make things slow.
};
} // namespace
#ifdef LOGGING
extern void __Log(int logNumber, const char* text, ...);
extern void __Logv(int log, int v, const char *format, ...);
#ifdef _WIN32
#define LOG(t, ...) __Log(LogTypes::t, __VA_ARGS__);
#define LOGV(t, v, ...) __Log(LogTypes::t + (v)*100, __VA_ARGS__);
#define LOGP(t, ...) __Log(t, __VA_ARGS__);
#define LOGVP(t, v, ...) __Log(t + (v)*100, __VA_ARGS__);
#define ERROR_LOG(t, ...) {LOGV(t, LogTypes::LERROR, __VA_ARGS__)}
#define WARN_LOG(t, ...) {LOGV(t, LogTypes::LINFO, __VA_ARGS__)}
#define INFO_LOG(t, ...) {LOGV(t, LogTypes::LWARNING, __VA_ARGS__)}
#define DEBUG_LOG(t ,...) {LOGV(t, LogTypes::LDEBUG, __VA_ARGS__)}
#else
#define LOG(t, ...) __Log(LogTypes::t, ##__VA_ARGS__);
#define LOGV(t,v, ...) __Log(LogTypes::t + (v)*100, ##__VA_ARGS__);
#define LOGP(t, ...) __Log(t, ##__VA_ARGS__);
#define LOGVP(t,v, ...) __Log(t + (v)*100, ##__VA_ARGS__);
#define ERROR_LOG(t,...) {LOGV(t, LogTypes::LERROR, ##__VA_ARGS__)}
#define WARN_LOG(t,...) {LOGV(t, LogTypes::LINFO, ##__VA_ARGS__)}
#define INFO_LOG(t,...) {LOGV(t, LogTypes::LWARNING, ##__VA_ARGS__)}
#define DEBUG_LOG(t,...) {LOGV(t, LogTypes::LDEBUG, ##__VA_ARGS__)}
#endif // WIN32
#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 LOGV(_t_, _v_, ...)
#define LOGP(_t_, ...)
#define LOGVP(_t_, _v_, ...)
#define _dbg_clear_()
#define _dbg_update_() ;
#ifndef _dbg_assert_
#define _dbg_assert_(_t_, _a_) ;
#define _dbg_assert_msg_(_t_, _a_, _desc_, ...) ;
#endif
#define ERROR_LOG(t, ...) ;
#define WARN_LOG(t, ...) ;
#define INFO_LOG(t ,...) ;
#define DEBUG_LOG(t, ...) ;
#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 // LOG_H

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/
#include "Common.h"
// Generic function to get last error message.
// Call directly after the command or use the error num.
// This function might change the error code.
const char *GetLastErrorMsg()
{
// FIXME : not thread safe.
// Caused by sloppy use in logging in FileUtil.cpp, primarily. What to do, what to do ...
static char errStr[255] = {0};
#ifdef _WIN32
DWORD dw = GetLastError();
FormatMessage(FORMAT_MESSAGE_FROM_SYSTEM, NULL, dw,
MAKELANGID(LANG_NEUTRAL, SUBLANG_DEFAULT),
(LPTSTR) errStr, 254, NULL );
#else
// Thread safe (XSI-compliant)
strerror_r(errno, errStr, 255);
#endif
return errStr;
}
char *strndup (char const *s, size_t n)
{
size_t len = strnlen(s, n);
char *dup = (char *)malloc(len + 1);
if (dup == NULL)
return NULL;
dup[len] = '\0';
return (char *)memcpy(dup, s, len);
}

View File

@ -0,0 +1,45 @@
// 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 MSGHANDLER_H
#define MSGHANDLER_H
// Message alerts
enum MSG_TYPE
{
INFORMATION,
QUESTION,
WARNING,
};
typedef bool (*MsgAlertHandler)(const char* caption, const char* text,
bool yes_no, int Style);
void RegisterMsgAlertHandler(MsgAlertHandler handler);
extern bool MsgAlert(const char* caption, bool yes_no, int Style, const char* format, ...);
#ifdef _WIN32
#define SuccessAlert(format, ...) MsgAlert("Information", false, INFORMATION, format, __VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert("Warning", false, WARNING, format, __VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert("Warning", true, WARNING, format, __VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert("Question", true, QUESTION, format, __VA_ARGS__)
#else
#define SuccessAlert(format, ...) MsgAlert("SUCCESS", false, INFORMATION, format, ##__VA_ARGS__)
#define PanicAlert(format, ...) MsgAlert("PANIC", false, WARNING, format, ##__VA_ARGS__)
#define PanicYesNo(format, ...) MsgAlert("PANIC", true, WARNING, format, ##__VA_ARGS__)
#define AskYesNo(format, ...) MsgAlert("ASK", true, QUESTION, format, ##__VA_ARGS__)
#endif
#endif //MSGHANDLER

View File

@ -17,6 +17,7 @@ files = [
"FileUtil.cpp",
"MappedFile.cpp",
"MathUtil.cpp",
"Misc.cpp",
"MemArena.cpp",
"MemoryUtil.cpp",
"Plugin.cpp",

View File

@ -80,10 +80,10 @@ u32 Ascii2Hex(std::string _Text)
if (Length > 4)
Length = 4;
for (int i = 0; i < Length; i++)
for (int i = 0; i < (int)Length; i++)
{
// Add up the values, for example RSPE becomes, 0x52000000, then 0x52530000 and so on
Result += _Text.c_str()[i] << (Length - 1 - i)*8;
Result += _Text.c_str()[i] << ((Length - 1 - i) * 8);
}
// Return the value
return Result;