The Mega Change Of Doom - or, fixing Stop. Almost. At least it's better than before. However, the OpenGL plugin seems to lose textures a lot between game restarts :P I think the GL plugin needs to do a lot more cleanup.

This change also includes tons of minor code formatting cleanup. Yeah, should've separated it ... sorry :(

Kills the old CPUCompare support. I'll resurrect it if I need it again, right now it mostly clutters the code.

git-svn-id: https://dolphin-emu.googlecode.com/svn/trunk@2321 8ced0084-cf51-0410-be5f-012b33b47a6e
This commit is contained in:
hrydgard
2009-02-20 22:04:52 +00:00
parent f992dae50d
commit 6cd34b318f
47 changed files with 685 additions and 1088 deletions

View File

@ -15,10 +15,8 @@
// 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
Dolpin is started and stopped.
*/
// All plugins from Core > Plugins are loaded and unloaded with this class when
// Dolphin is started and stopped.
#include <string.h> // System
#ifdef _WIN32
@ -34,7 +32,6 @@
#include "DynamicLibrary.h"
#include "ConsoleWindow.h"
DynamicLibrary::DynamicLibrary()
{
library = 0;
@ -42,33 +39,33 @@ DynamicLibrary::DynamicLibrary()
std::string GetLastErrorAsString()
{
#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
#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
}
/* Function: Loading means loading the dll with LoadLibrary() to get an
@ -81,15 +78,16 @@ std::string GetLastErrorAsString()
Called from: The Dolphin Core */
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");
return 0;
if (!filename || strlen(filename) == 0)
{
LOG(MASTER_LOG, "Missing filename of dynamic library to load");
PanicAlert("Missing filename of dynamic library to load");
return 0;
}
LOG(MASTER_LOG, "Trying to load library %s", filename);
if (IsLoaded()) {
LOG(MASTER_LOG, "Trying to load already loaded library %s", filename);
return 2;
if (IsLoaded())
{
LOG(MASTER_LOG, "Trying to load already loaded library %s", filename);
return 2;
}
Console::Print("LoadLibrary: %s", filename);
@ -99,10 +97,11 @@ int DynamicLibrary::Load(const char* filename)
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());
return 0;
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());
return 0;
}
library_file = filename;
@ -111,28 +110,29 @@ int DynamicLibrary::Load(const char* filename)
int DynamicLibrary::Unload()
{
int retval;
if (!IsLoaded()) {
PanicAlert("Error unloading DLL %s: not loaded", library_file.c_str());
return 0;
}
int retval;
if (!IsLoaded())
{
PanicAlert("Error unloading DLL %s: not loaded", library_file.c_str());
return 0;
}
Console::Print("FreeLibrary: %s %p\n", library_file.c_str(), library);
Console::Print("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)
{
PanicAlert("Error unloading DLL %s: %s", library_file.c_str(),
GetLastErrorAsString().c_str());
}
library = 0;
return retval;
}
void* DynamicLibrary::Get(const char* funcname) const
{
void* retval;
@ -156,5 +156,3 @@ void* DynamicLibrary::Get(const char* funcname) const
return retval;
}

View File

@ -14,17 +14,12 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
//////////////////////////////////////////////////////////////////////////////////////////
// Include
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
File description: This is the common Plugin class that links to the functions that are
common to all plugins. This class is inherited by all plugin classes. But it's only created
directly in PluginManager.cpp when we check if a plugin is valid or not.
///////////////////////////////////////////////*/
////////////////////////////////////////////////
// This is the common Plugin class that links to the functions that are
// common to all plugins. This class is inherited by all plugin classes. But it's only created
// directly in PluginManager.cpp when we check if a plugin is valid or not.
///////////////////////////////////////////////
#include "Plugin.h"
@ -33,21 +28,20 @@ namespace Common
CPlugin::~CPlugin()
{
m_hInstLib.Unload();
m_hInstLib.Unload();
}
CPlugin::CPlugin(const char* _szName) : valid(false)
{
m_GetDllInfo = NULL;
m_DllConfig = NULL;
m_DllDebugger = NULL;
m_SetDllGlobals = NULL;
m_Initialize = NULL;
m_Shutdown = NULL;
m_DoState = NULL;
if (m_hInstLib.Load(_szName))
m_GetDllInfo = NULL;
m_DllConfig = NULL;
m_DllDebugger = NULL;
m_SetDllGlobals = NULL;
m_Initialize = NULL;
m_Shutdown = NULL;
m_DoState = NULL;
if (m_hInstLib.Load(_szName))
{
m_GetDllInfo = reinterpret_cast<TGetDllInfo>
(m_hInstLib.Get("GetDllInfo"));
@ -66,7 +60,7 @@ CPlugin::CPlugin(const char* _szName) : valid(false)
}
// Check if the plugin has all the functions it shold have
if (m_GetDllInfo != 0 &&
if (m_GetDllInfo != 0 &&
m_DllConfig != 0 &&
m_DllDebugger != 0 &&
m_SetDllGlobals != 0 &&
@ -81,63 +75,57 @@ CPlugin::CPlugin(const char* _szName) : valid(false)
void *CPlugin::LoadSymbol(const char *sym)
{
return m_hInstLib.Get(sym);
return m_hInstLib.Get(sym);
}
// GetInfo: Get DLL info
bool CPlugin::GetInfo(PLUGIN_INFO& _pluginInfo)
{
if (m_GetDllInfo != NULL) {
m_GetDllInfo(&_pluginInfo);
return(true);
}
return(false);
if (m_GetDllInfo != NULL) {
m_GetDllInfo(&_pluginInfo);
return(true);
}
return(false);
}
// Config: Open the Config window
void CPlugin::Config(HWND _hwnd)
{
if (m_DllConfig != NULL)
m_DllConfig(_hwnd);
if (m_DllConfig != NULL)
m_DllConfig(_hwnd);
}
// Debug: Open the Debugging window
void CPlugin::Debug(HWND _hwnd, bool Show)
{
if (m_DllDebugger != NULL)
m_DllDebugger(_hwnd, Show);
if (m_DllDebugger != NULL)
m_DllDebugger(_hwnd, Show);
}
void CPlugin::SetGlobals(PLUGIN_GLOBALS* _pluginGlobals) {
if (m_SetDllGlobals != NULL)
m_SetDllGlobals(_pluginGlobals);
if (m_SetDllGlobals != NULL)
m_SetDllGlobals(_pluginGlobals);
}
void CPlugin::DoState(unsigned char **ptr, int mode) {
if (m_DoState != NULL)
m_DoState(ptr, mode);
if (m_DoState != NULL)
m_DoState(ptr, mode);
}
// Run Initialize() in the plugin
void CPlugin::Initialize(void *init)
{
/* We first check that we have found the Initialize() function, but there
is no restriction on running this several times */
if (m_Initialize != NULL)
m_Initialize(init);
/* We first check that we have found the Initialize() function, but there
is no restriction on running this several times */
// Uh, the above comment sounds extremely dubious.
if (m_Initialize != NULL)
m_Initialize(init);
}
void CPlugin::Shutdown()
{
if (m_Shutdown != NULL)
m_Shutdown();
if (m_Shutdown != NULL)
m_Shutdown();
}
} // end of namespace Common

View File

@ -1,36 +1,41 @@
#include "PluginDSP.h"
namespace Common {
PluginDSP::PluginDSP(const char *_Filename) : CPlugin(_Filename), validDSP(false) {
PluginDSP::PluginDSP(const char *_Filename) : CPlugin(_Filename), validDSP(false) {
DSP_ReadMailboxHigh = reinterpret_cast<TDSP_ReadMailBox>
(LoadSymbol("DSP_ReadMailboxHigh"));
DSP_ReadMailboxLow = reinterpret_cast<TDSP_ReadMailBox>
(LoadSymbol("DSP_ReadMailboxLow"));
DSP_WriteMailboxHigh = reinterpret_cast<TDSP_WriteMailBox>
(LoadSymbol("DSP_WriteMailboxHigh"));
DSP_WriteMailboxLow = reinterpret_cast<TDSP_WriteMailBox>
(LoadSymbol("DSP_WriteMailboxLow"));
DSP_ReadControlRegister = reinterpret_cast<TDSP_ReadControlRegister>
(LoadSymbol("DSP_ReadControlRegister"));
DSP_WriteControlRegister = reinterpret_cast<TDSP_WriteControlRegister>
(LoadSymbol("DSP_WriteControlRegister"));
DSP_Update = reinterpret_cast<TDSP_Update>
(LoadSymbol("DSP_Update"));
DSP_SendAIBuffer = reinterpret_cast<TDSP_SendAIBuffer>
(LoadSymbol("DSP_SendAIBuffer"));
(LoadSymbol("DSP_ReadMailboxHigh"));
DSP_ReadMailboxLow = reinterpret_cast<TDSP_ReadMailBox>
(LoadSymbol("DSP_ReadMailboxLow"));
DSP_WriteMailboxHigh = reinterpret_cast<TDSP_WriteMailBox>
(LoadSymbol("DSP_WriteMailboxHigh"));
DSP_WriteMailboxLow = reinterpret_cast<TDSP_WriteMailBox>
(LoadSymbol("DSP_WriteMailboxLow"));
DSP_ReadControlRegister = reinterpret_cast<TDSP_ReadControlRegister>
(LoadSymbol("DSP_ReadControlRegister"));
DSP_WriteControlRegister = reinterpret_cast<TDSP_WriteControlRegister>
(LoadSymbol("DSP_WriteControlRegister"));
DSP_Update = reinterpret_cast<TDSP_Update>
(LoadSymbol("DSP_Update"));
DSP_SendAIBuffer = reinterpret_cast<TDSP_SendAIBuffer>
(LoadSymbol("DSP_SendAIBuffer"));
DSP_StopSoundStream = reinterpret_cast<TDSP_StopSoundStream>
(LoadSymbol("DSP_StopSoundStream"));
if ((DSP_ReadMailboxHigh != 0) &&
(DSP_ReadMailboxLow != 0) &&
(DSP_WriteMailboxHigh != 0) &&
(DSP_WriteMailboxLow != 0) &&
(DSP_ReadControlRegister != 0) &&
(DSP_WriteControlRegister != 0) &&
(DSP_SendAIBuffer != 0) &&
(DSP_Update != 0))
validDSP = true;
}
PluginDSP::~PluginDSP() {
}
(DSP_ReadMailboxLow != 0) &&
(DSP_WriteMailboxHigh != 0) &&
(DSP_WriteMailboxLow != 0) &&
(DSP_ReadControlRegister != 0) &&
(DSP_WriteControlRegister != 0) &&
(DSP_SendAIBuffer != 0) &&
(DSP_Update != 0) &&
(DSP_StopSoundStream != 0))
validDSP = true;
}
PluginDSP::~PluginDSP() {
}
} // namespace

View File

@ -5,33 +5,37 @@
#include "Plugin.h"
namespace Common {
typedef void (__cdecl* TDSP_WriteMailBox)(bool _CPUMailbox, unsigned short);
typedef unsigned short (__cdecl* TDSP_ReadMailBox)(bool _CPUMailbox);
typedef unsigned short (__cdecl* TDSP_ReadControlRegister)();
typedef unsigned short (__cdecl* TDSP_WriteControlRegister)(unsigned short);
typedef void (__cdecl* TDSP_SendAIBuffer)(unsigned int address, int sample_rate);
typedef void (__cdecl* TDSP_Update)(int cycles);
class PluginDSP : public CPlugin
{
public:
typedef void (__cdecl* TDSP_WriteMailBox)(bool _CPUMailbox, unsigned short);
typedef unsigned short (__cdecl* TDSP_ReadMailBox)(bool _CPUMailbox);
typedef unsigned short (__cdecl* TDSP_ReadControlRegister)();
typedef unsigned short (__cdecl* TDSP_WriteControlRegister)(unsigned short);
typedef void (__cdecl* TDSP_SendAIBuffer)(unsigned int address, int sample_rate);
typedef void (__cdecl* TDSP_Update)(int cycles);
typedef void (__cdecl* TDSP_StopSoundStream)();
class PluginDSP : public CPlugin
{
public:
PluginDSP(const char *_Filename);
~PluginDSP();
virtual bool IsValid() {return validDSP;};
TDSP_ReadMailBox DSP_ReadMailboxHigh;
TDSP_ReadMailBox DSP_ReadMailboxLow;
TDSP_WriteMailBox DSP_WriteMailboxHigh;
TDSP_ReadMailBox DSP_ReadMailboxHigh;
TDSP_ReadMailBox DSP_ReadMailboxLow;
TDSP_WriteMailBox DSP_WriteMailboxHigh;
TDSP_WriteMailBox DSP_WriteMailboxLow;
TDSP_ReadControlRegister DSP_ReadControlRegister;
TDSP_WriteControlRegister DSP_WriteControlRegister;
TDSP_SendAIBuffer DSP_SendAIBuffer;
TDSP_SendAIBuffer DSP_SendAIBuffer;
TDSP_Update DSP_Update;
TDSP_StopSoundStream DSP_StopSoundStream;
private:
private:
bool validDSP;
};
}
};
} // namespace
#endif

View File

@ -2,41 +2,42 @@
namespace Common
{
PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo(false)
{
PluginVideo::PluginVideo(const char *_Filename) : CPlugin(_Filename), validVideo(false)
{
Video_Prepare = 0;
Video_SendFifoData = 0;
Video_UpdateXFB = 0;
Video_EnterLoop = 0;
Video_ExitLoop = 0;
Video_Screenshot = 0;
Video_AddMessage = 0;
Video_Stop = 0;
Video_Prepare = reinterpret_cast<TVideo_Prepare>
(LoadSymbol("Video_Prepare"));
Video_Prepare = reinterpret_cast<TVideo_Prepare>
(LoadSymbol("Video_Prepare"));
Video_SendFifoData = reinterpret_cast<TVideo_SendFifoData>
(LoadSymbol("Video_SendFifoData"));
Video_UpdateXFB = reinterpret_cast<TVideo_UpdateXFB>
(LoadSymbol("Video_UpdateXFB"));
Video_Screenshot = reinterpret_cast<TVideo_Screenshot>
(LoadSymbol("Video_Screenshot"));
Video_EnterLoop = reinterpret_cast<TVideo_EnterLoop>
(LoadSymbol("Video_EnterLoop"));
Video_AddMessage = reinterpret_cast<TVideo_AddMessage>
(LoadSymbol("Video_AddMessage"));
Video_Stop = reinterpret_cast<TVideo_Stop>
(LoadSymbol("Video_Stop"));
(LoadSymbol("Video_SendFifoData"));
Video_UpdateXFB = reinterpret_cast<TVideo_UpdateXFB>
(LoadSymbol("Video_UpdateXFB"));
Video_Screenshot = reinterpret_cast<TVideo_Screenshot>
(LoadSymbol("Video_Screenshot"));
Video_EnterLoop = reinterpret_cast<TVideo_EnterLoop>
(LoadSymbol("Video_EnterLoop"));
Video_ExitLoop = reinterpret_cast<TVideo_ExitLoop>
(LoadSymbol("Video_ExitLoop"));
Video_AddMessage = reinterpret_cast<TVideo_AddMessage>
(LoadSymbol("Video_AddMessage"));
if ((Video_Prepare != 0) &&
(Video_SendFifoData != 0) &&
(Video_UpdateXFB != 0) &&
(Video_EnterLoop != 0) &&
(Video_Screenshot != 0) &&
(Video_AddMessage != 0) &&
(Video_Stop != 0))
validVideo = true;
}
PluginVideo::~PluginVideo() {}
if ((Video_Prepare != 0) &&
(Video_SendFifoData != 0) &&
(Video_UpdateXFB != 0) &&
(Video_EnterLoop != 0) &&
(Video_ExitLoop != 0) &&
(Video_Screenshot != 0) &&
(Video_AddMessage != 0))
validVideo = true;
}
PluginVideo::~PluginVideo() {}
} // namespace

View File

@ -10,8 +10,8 @@ namespace Common {
typedef void (__cdecl* TVideo_UpdateXFB)(u8*, u32, u32, s32, bool);
typedef bool (__cdecl* TVideo_Screenshot)(const char* filename);
typedef void (__cdecl* TVideo_EnterLoop)();
typedef void (__cdecl* TVideo_ExitLoop)();
typedef void (__cdecl* TVideo_AddMessage)(const char* pstr, unsigned int milliseconds);
typedef void (__cdecl* TVideo_Stop)();
class PluginVideo : public CPlugin
{
@ -22,15 +22,15 @@ namespace Common {
TVideo_Prepare Video_Prepare;
TVideo_SendFifoData Video_SendFifoData;
TVideo_UpdateXFB Video_UpdateXFB;
TVideo_Screenshot Video_Screenshot;
TVideo_EnterLoop Video_EnterLoop;
TVideo_ExitLoop Video_ExitLoop;
TVideo_UpdateXFB Video_UpdateXFB;
TVideo_AddMessage Video_AddMessage;
TVideo_Stop Video_Stop;
TVideo_Screenshot Video_Screenshot;
private:
bool validVideo;
};
}

View File

@ -15,11 +15,9 @@
// Official SVN repository and contact information can be found at
// http://code.google.com/p/dolphin-emu/
#ifndef __SETUP_h__
#define __SETUP_h__
////////////////////////////////////////////////////////////////////////////////////////
// File description
/* <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
@ -31,18 +29,10 @@
////////////////////////*/
////////////////////////////////////////////////////////////////////////////////////////
// Settings
// <20><><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD><EFBFBD>
// This may fix a problem with Stop and Start that I described in the comments to revision 2,139
//#define SETUP_FREE_PLUGIN_ON_BOOT
// This may fix a semi-frequent hanging that occured when I used single core and render to main frame
//#define SETUP_AVOID_SINGLE_CORE_HANG_ON_STOP
// This may remove sound artifacts in Wario Land Shake It and perhaps other games
//#define SETUP_AVOID_SOUND_ARTIFACTS
@ -54,5 +44,4 @@
///////////////////////////
#endif // __SETUP_h__

View File

@ -22,6 +22,12 @@
namespace Common
{
#ifdef _WIN32
void InitThreading()
{
// Nothing to do in Win32 build.
}
CriticalSection::CriticalSection(int spincount)
{
if (spincount)
@ -34,25 +40,21 @@ CriticalSection::CriticalSection(int spincount)
}
}
CriticalSection::~CriticalSection()
{
DeleteCriticalSection(&section);
}
void CriticalSection::Enter()
{
EnterCriticalSection(&section);
}
bool CriticalSection::TryEnter()
{
return TryEnterCriticalSection(&section) ? true : false;
}
void CriticalSection::Leave()
{
LeaveCriticalSection(&section);
@ -71,13 +73,11 @@ Thread::Thread(ThreadFunc function, void* arg)
&m_threadId);
}
Thread::~Thread()
{
WaitForDeath();
}
void Thread::WaitForDeath()
{
if (m_hThread)
@ -88,13 +88,11 @@ void Thread::WaitForDeath()
}
}
void Thread::SetAffinity(int mask)
{
SetThreadAffinityMask(m_hThread, mask);
}
void Thread::SetCurrentThreadAffinity(int mask)
{
SetThreadAffinityMask(GetCurrentThread(), mask);
@ -106,32 +104,27 @@ 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);
@ -304,12 +297,13 @@ void Thread::SetCurrentThreadAffinity(int mask)
void InitThreading() {
static int thread_init_done = 0;
if (thread_init_done) return;
thread_init_done++;
if (thread_init_done)
return;
if (pthread_key_create(&threadname_key, NULL/*free*/) != 0)
perror("Unable to create thread name key: ");
thread_init_done++;
}
void SleepCurrentThread(int ms)

View File

@ -63,12 +63,11 @@ public:
Thread(ThreadFunc entry, void* arg);
~Thread();
void WaitForDeath();
void SetAffinity(int mask);
static void SetCurrentThreadAffinity(int mask);
private:
void WaitForDeath();
#ifdef _WIN32
HANDLE m_hThread;
@ -81,29 +80,26 @@ private:
class Event
{
public:
public:
Event();
Event();
void Init();
void Shutdown();
void Init();
void Shutdown();
void Set();
void Wait();
private:
void Set();
void Wait();
private:
#ifdef _WIN32
HANDLE m_hEvent;
HANDLE m_hEvent;
#else
bool is_set_;
pthread_cond_t event_;
pthread_mutex_t mutex_;
bool is_set_;
pthread_cond_t event_;
pthread_mutex_t mutex_;
#endif
};
void InitThreading(void);
void InitThreading();
void SleepCurrentThread(int ms);
void SetCurrentThreadName(const char *name);
@ -114,5 +110,4 @@ LONG SyncInterlockedIncrement(LONG *Dest);
} // end of namespace Common
#endif

View File

@ -120,11 +120,12 @@ u64 Timer::GetTimeElapsed(void)
std::string Timer::GetTimeElapsedFormatted(void)
{
// If we have not started yet, return zero
if(m_StartTime == 0) return "00:00:00:000";
if (m_StartTime == 0)
return "00:00:00:000";
// The number of milliseconds since the start, use a different value if the timer is stopped
u32 Milliseconds;
if(m_Running)
if (m_Running)
Milliseconds = timeGetTime() - m_StartTime;
else
Milliseconds = m_LastTime - m_StartTime;

View File

@ -279,7 +279,7 @@
AssemblerListingLocation="$(IntDir)\"
WarningLevel="3"
WarnAsError="false"
DebugInformationFormat="0"
DebugInformationFormat="3"
ForcedIncludeFiles="stdafx.h"
/>
<Tool
@ -655,14 +655,6 @@
RelativePath=".\Src\Hw\CPU.h"
>
</File>
<File
RelativePath=".\Src\Hw\CPUCompare.cpp"
>
</File>
<File
RelativePath=".\Src\Hw\CPUCompare.h"
>
</File>
<File
RelativePath=".\Src\Hw\HW.cpp"
>

View File

@ -42,7 +42,6 @@
#include "HW/PeripheralInterface.h"
#include "HW/GPFifo.h"
#include "HW/CPU.h"
#include "HW/CPUCompare.h"
#include "HW/HW.h"
#include "HW/DSP.h"
#include "HW/GPFifo.h"
@ -105,9 +104,13 @@ void Stop();
bool g_bHwInit = false;
bool g_bRealWiimote = false;
HWND g_pWindowHandle = NULL;
Common::Thread* g_pThread = NULL;
SCoreStartupParameter g_CoreStartupParameter;
Common::Thread* g_EmuThread = NULL;
SCoreStartupParameter g_CoreStartupParameter;
// This event is set when the emuthread starts.
Common::Event emuThreadGoing;
Common::Event cpuRunloopQuit;
//////////////////////////////////////
@ -137,7 +140,7 @@ void Callback_DebuggerBreak()
CCPU::Break();
}
void* GetWindowHandle()
void *GetWindowHandle()
{
return g_pWindowHandle;
}
@ -146,6 +149,7 @@ bool GetRealWiimote()
{
return g_bRealWiimote;
}
// This can occur when the emulator is not running and the nJoy configuration window is opened
void ReconnectPad()
{
@ -154,26 +158,30 @@ void ReconnectPad()
Plugins.GetPad(0)->Config(g_pWindowHandle);
Console::Print("ReconnectPad()\n");
}
// This doesn't work yet, I don't understand how the connection work yet
void ReconnectWiimote()
{
// This seems to be a hack that just sets some IPC registers to zero. Dubious.
HW::InitWiimote();
Console::Print("ReconnectWiimote()\n");
}
/////////////////////////////////////
//////////////////////////////////////////////////////////////////////////////////////////
// This is called from the GUI thread. See the booting call schedule in BootManager.cpp
// -----------------
bool Init()
{
if (g_pThread != NULL)
if (g_EmuThread != NULL)
{
PanicAlert("ERROR: Emu Thread already running. Report this bug.");
return false;
}
Common::InitThreading();
// Get a handle to the current instance of the plugin manager
CPluginManager &pManager = CPluginManager::GetInstance();
SCoreStartupParameter &_CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
@ -181,60 +189,63 @@ bool Init()
g_CoreStartupParameter = _CoreParameter;
LogManager::Init();
Host_SetWaitCursor(true);
// Start the thread again
_dbg_assert_(HLE, g_pThread == NULL);
_dbg_assert_(HLE, g_EmuThread == NULL);
// Check that all plugins exist, potentially call LoadLibrary() for unloaded plugins
if (!pManager.InitPlugins()) return false;
if (!pManager.InitPlugins())
return false;
emuThreadGoing.Init();
// This will execute EmuThread() further down in this file
g_pThread = new Common::Thread(EmuThread, NULL);
g_EmuThread = new Common::Thread(EmuThread, NULL);
emuThreadGoing.Wait();
emuThreadGoing.Shutdown();
// all right ... here we go
// All right, the event is set and killed. We are now running.
Host_SetWaitCursor(false);
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
DisplayMessage(_CoreParameter.m_strFilename, 3000);
//PluginVideo::DllDebugger(NULL);
return true;
}
// Called from GUI thread or VI thread
// Called from GUI thread or VI thread (why VI??? That must be bad. Window close? TODO: Investigate.)
void Stop() // - Hammertime!
{
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
Host_SetWaitCursor(true);
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
return;
// stop the CPU
PowerPC::Stop();
CCPU::StepOpcode(); //kick it if it's waiting
cpuRunloopQuit.Wait();
cpuRunloopQuit.Shutdown();
// At this point, we must be out of the CPU:s runloop.
// Silence audio - stops audio thread.
CPluginManager::GetInstance().GetDSP()->DSP_StopSoundStream();
// If dual core mode, the CPU thread should immediately exit here.
// The quit is to get it out of its message loop
// Should be moved inside the plugin.
#ifdef _WIN32
PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
#else
CPluginManager::GetInstance().GetVideo()->Video_Stop();
#endif
if (_CoreParameter.bUseDualCore)
CPluginManager::GetInstance().GetVideo()->Video_ExitLoop();
#ifdef _WIN32
/* I have to use this to avoid the hangings, it seems harmless and it works so I'm
okay with it */
if (GetParent((HWND)g_pWindowHandle) == NULL)
delete g_pThread; // Wait for emuthread to close
#else
delete g_pThread;
PostMessage((HWND)g_pWindowHandle, WM_QUIT, 0, 0);
#endif
g_pThread = 0;
Core::StopTrace();
LogManager::Shutdown();
Host_SetWaitCursor(false);
delete g_EmuThread; // Wait for emuthread to close.
g_EmuThread = 0;
}
@ -243,31 +254,19 @@ void Stop() // - Hammertime!
// ---------------
THREAD_RETURN CpuThread(void *pArg)
{
Common::SetCurrentThreadName("CPU thread");
Common::SetCurrentThreadName("CPU thread");
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
if (!_CoreParameter.bUseDualCore)
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
if (!_CoreParameter.bUseDualCore)
{
//wglMakeCurrent
CPluginManager::GetInstance().GetVideo()->Video_Prepare();
//wglMakeCurrent
CPluginManager::GetInstance().GetVideo()->Video_Prepare();
}
if (_CoreParameter.bRunCompareServer)
{
CPUCompare::StartServer();
PowerPC::Start();
}
else if (_CoreParameter.bRunCompareClient)
{
PanicAlert("Compare Debug : Press OK when ready.");
CPUCompare::ConnectAsClient();
}
if (_CoreParameter.bLockThreads)
if (_CoreParameter.bLockThreads)
Common::Thread::SetCurrentThreadAffinity(1); // Force to first core
if (_CoreParameter.bUseFastMem)
if (_CoreParameter.bUseFastMem)
{
#ifdef _M_X64
// Let's run under memory watch
@ -279,13 +278,10 @@ THREAD_RETURN CpuThread(void *pArg)
#endif
}
CCPU::Run();
if (_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient)
{
CPUCompare::Stop();
}
return 0;
// Enter CPU run loop. When we leave it - we are done.
CCPU::Run();
cpuRunloopQuit.Set();
return 0;
}
//////////////////////////////////////////
@ -293,10 +289,11 @@ THREAD_RETURN CpuThread(void *pArg)
//////////////////////////////////////////////////////////////////////////////////////////
// Initalize plugins and create emulation thread
// -------------
/* Call browser: Init():g_pThread(). See the BootManager.cpp file description for a complete
call schedule. */
// Call browser: Init():g_EmuThread(). See the BootManager.cpp file description for a complete call schedule.
THREAD_RETURN EmuThread(void *pArg)
{
cpuRunloopQuit.Init();
Common::SetCurrentThreadName("Emuthread - starting");
const SCoreStartupParameter& _CoreParameter = SConfig::GetInstance().m_LocalCoreStartupParameter;
@ -331,10 +328,6 @@ THREAD_RETURN EmuThread(void *pArg)
VideoInitialize.pKeyPress = Callback_KeyPress;
VideoInitialize.bWii = _CoreParameter.bWii;
VideoInitialize.bUseDualCore = _CoreParameter.bUseDualCore;
// Needed for Stop and Start
#ifdef SETUP_FREE_PLUGIN_ON_BOOT
Plugins.FreeVideo();
#endif
Plugins.GetVideo()->Initialize(&VideoInitialize); // Call the dll
// Under linux, this is an X11 Display, not an HWND!
@ -355,10 +348,6 @@ THREAD_RETURN EmuThread(void *pArg)
dspInit.pGetAudioStreaming = AudioInterface::Callback_GetStreaming;
dspInit.pEmulatorState = (int *)PowerPC::GetStatePtr();
dspInit.bWii = _CoreParameter.bWii;
// Needed for Stop and Start
#ifdef SETUP_FREE_PLUGIN_ON_BOOT
Plugins.FreeDSP();
#endif
Plugins.GetDSP()->Initialize((void *)&dspInit);
// Load and Init PadPlugin
@ -400,29 +389,31 @@ THREAD_RETURN EmuThread(void *pArg)
// The hardware is initialized.
g_bHwInit = true;
DisplayMessage("CPU: " + cpu_info.Summarize(), 8000);
DisplayMessage(_CoreParameter.m_strFilename, 3000);
// Load GCM/DOL/ELF whatever ... we boot with the interpreter core
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
CBoot::BootUp();
if( g_pUpdateFPSDisplay != NULL )
g_pUpdateFPSDisplay("Loading...");
if (g_pUpdateFPSDisplay != NULL)
g_pUpdateFPSDisplay(("Loading " + _CoreParameter.m_strFilename).c_str());
// setup our core, but can't use dynarec if we are compare server
// Setup our core, but can't use dynarec if we are compare server
if (_CoreParameter.bUseJIT && (!_CoreParameter.bRunCompareServer || _CoreParameter.bRunCompareClient))
PowerPC::SetMode(PowerPC::MODE_JIT);
else
PowerPC::SetMode(PowerPC::MODE_INTERPRETER);
// update the window again because all stuff is initialized
// Update the window again because all stuff is initialized
Host_UpdateDisasmDialog();
Host_UpdateMainFrame();
//This thread, after creating the EmuWindow, spawns a CPU thread,
//then takes over and becomes the graphics thread
// This thread, after creating the EmuWindow, spawns a CPU thread,
// then takes over and becomes the graphics thread
//In single core mode, the CPU thread does the graphics. In fact, the
//CPU thread should in this case also create the emuwindow...
// In single core mode, this thread is the CPU thread and also does the graphics.
// Spawn the CPU thread
Common::Thread *cpuThread = NULL;
@ -433,34 +424,36 @@ THREAD_RETURN EmuThread(void *pArg)
if (!_CoreParameter.bUseDualCore)
{
#ifdef _WIN32
cpuThread = new Common::Thread(CpuThread, pArg);
//Common::SetCurrentThreadName("Idle thread");
//TODO(ector) : investigate using GetMessage instead .. although
//then we lose the powerdown check. ... unless powerdown sends a message :P
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
if (Callback_PeekMessages)
Callback_PeekMessages();
Common::SleepCurrentThread(20);
}
#else
// In single-core mode, the Emulation main thread is also the CPU thread
CpuThread(pArg);
#endif
#ifdef _WIN32
cpuThread = new Common::Thread(CpuThread, pArg);
// Common::SetCurrentThreadName("Idle thread");
// TODO(ector) : investigate using GetMessage instead .. although
// then we lose the powerdown check. ... unless powerdown sends a message :P
while (PowerPC::GetState() != PowerPC::CPU_POWERDOWN)
{
if (Callback_PeekMessages)
Callback_PeekMessages();
Common::SleepCurrentThread(20);
}
#else
// In single-core mode, the Emulation main thread is also the CPU thread
CpuThread(pArg);
#endif
}
else
{
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
cpuThread = new Common::Thread(CpuThread, pArg);
Common::SetCurrentThreadName("Video thread");
Plugins.GetVideo()->Video_EnterLoop();
Plugins.GetVideo()->Video_Prepare(); // wglMakeCurrent
cpuThread = new Common::Thread(CpuThread, pArg);
Common::SetCurrentThreadName("Video thread");
// I bet that many of our stopping problems come from this loop not properly exiting.
Plugins.GetVideo()->Video_EnterLoop();
}
// We have now exited the Video Loop and will shut down
// does this comment still apply?
/* Check if we are using single core and are rendering to the main window. In that case we must avoid the WaitForSingleObject()
loop in the cpu thread thread, because it will hang on occation, perhaps one time in three or so. I had this problem in the Wiimote plugin, what happened was that if I entered the
WaitForSingleObject loop or any loop at all in the main thread, the separate thread would halt at a place where it called a function in
@ -468,21 +461,14 @@ THREAD_RETURN EmuThread(void *pArg)
Perhaps something like that can be done here to? I just don't exactly how since in single core mode there should only be one
thread right? So how can WaitForSingleObject() hang in it? */
bool bRenderToMainSingleCore = false;
#ifdef SETUP_AVOID_SINGLE_CORE_HANG_ON_STOP
if (GetParent((HWND)g_pWindowHandle) == NULL || _CoreParameter.bUseDualCore) bRenderToMainSingleCore = true;
#endif
/* Wait for CPU thread to exit - it should have been signaled to do so by now. On the other hand this will be called by
delete cpuThread to. So now we call it twice right? */
if(!bRenderToMainSingleCore) if (cpuThread) cpuThread->WaitForDeath();
// Write message
if (g_pUpdateFPSDisplay != NULL) g_pUpdateFPSDisplay("Stopping...");
if (g_pUpdateFPSDisplay != NULL)
g_pUpdateFPSDisplay("Stopping...");
if (cpuThread)
{
// This joins the cpu thread.
if(!bRenderToMainSingleCore) delete cpuThread;
// There is a CPU thread - join it.
delete cpuThread;
// Returns after game exited
cpuThread = NULL;
}
@ -500,7 +486,6 @@ THREAD_RETURN EmuThread(void *pArg)
if (_CoreParameter.hMainWindow == g_pWindowHandle)
Host_UpdateMainFrame();
//Console::Close();
return 0;
}
@ -508,27 +493,23 @@ THREAD_RETURN EmuThread(void *pArg)
//////////////////////////////////////////////////////////////////////////////////////////
// Set or get the running state
// --------------
bool SetState(EState _State)
void SetState(EState _State)
{
switch(_State)
switch (_State)
{
case CORE_UNINITIALIZED:
Stop();
break;
case CORE_PAUSE:
CCPU::EnableStepping(true); // Break
break;
case CORE_RUN:
CCPU::EnableStepping(false);
break;
default:
return false;
PanicAlert("Invalid state");
break;
}
return true;
}
EState GetState()
@ -589,7 +570,7 @@ void Callback_VideoLog(const TCHAR *_szMessage, int _bDoBreak)
// __________________________________________________________________________________________________
// Callback_VideoCopiedToXFB
// WARNING - THIS IS EXECUTED FROM VIDEO THREAD
// We do not touch anything outside this function here
// We do not write to anything outside this function here
void Callback_VideoCopiedToXFB()
{
#ifdef RERECORDING
@ -647,6 +628,8 @@ void Callback_VideoCopiedToXFB()
frames = 0;
Timer.Update();
}
// TODO: hm, are these really safe to call from the video thread?
PatchEngine::ApplyFramePatches();
PatchEngine::ApplyARPatches();
}

View File

@ -44,7 +44,7 @@ namespace Core
bool Init();
void Stop();
bool SetState(EState _State);
void SetState(EState _State);
EState GetState();
// Save/Load state

View File

@ -174,16 +174,16 @@ void FrameAdvance()
WriteStatus();
// If a game is not started, return
if(Core::GetState() == Core::CORE_UNINITIALIZED) return;
if (Core::GetState() == Core::CORE_UNINITIALIZED) return;
// Play to the next frame
if(g_FrameStep)
if (g_FrameStep)
{
Run();
Core::SetState(Core::CORE_RUN);
}
}
// Turn on frame stepping
void FrameStepOnOff()
{

View File

@ -22,7 +22,6 @@
#include "../Host.h"
#include "../Core.h"
#include "CPU.h"
#include "CPUCompare.h"
#include "../Debugger/Debugger_BreakPoints.h"
@ -59,6 +58,8 @@ reswitch:
case PowerPC::CPU_RUNNING:
//1: enter a fast runloop
PowerPC::RunLoop();
if (PowerPC::GetState() == PowerPC::CPU_POWERDOWN)
return;
break;
case PowerPC::CPU_STEPPING:
@ -69,13 +70,6 @@ reswitch:
if (PowerPC::GetState() != PowerPC::CPU_STEPPING)
goto reswitch;
//2: check for cpu compare
if (CPUCompare::IsEnabled() && g_Branch)
{
g_Branch = false;
CPUCompare::Sync();
}
//3: do a step
PowerPC::SingleStep();

View File

@ -1,246 +0,0 @@
// 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>
#endif
#include "Common.h"
#include "../Core.h"
#include "CPUCompare.h"
#include "../PowerPC/PowerPC.h"
#include "CommandProcessor.h"
#include "../Host.h"
#ifdef _WIN32
namespace CPUCompare
{
HANDLE m_hPipe;
bool m_bIsServer;
bool m_bEnabled;
u32 m_BlockStart;
#define PIPENAME "\\\\.\\pipe\\cpucompare"
int stateSize = 32*4 + 32*16 + 6*4;
void SetBlockStart(u32 addr)
{
m_BlockStart = addr;
}
void StartServer()
{
_assert_msg_(GEKKO, Core::GetStartupParameter().bUseDualCore != true, "Don't use multithreading together with CPU-compare.");
if (m_bEnabled)
return;
//TODO: error checking
m_hPipe = CreateNamedPipe(
PIPENAME,
PIPE_ACCESS_OUTBOUND,
PIPE_WAIT | PIPE_TYPE_MESSAGE | PIPE_READMODE_MESSAGE,
1, //maxinst
0x1000, //outbufsize
0x1000, //inbufsize
INFINITE, //timeout
0);
_assert_msg_(GEKKO, m_hPipe != INVALID_HANDLE_VALUE, "Failed to create pipe.");
//_assert_msg_(GEKKO, 0, "Pipe %s created.", PIPENAME);
m_bIsServer = true;
m_bEnabled = true;
}
void ConnectAsClient()
{
_assert_msg_(GEKKO, Core::GetStartupParameter().bUseDualCore != true, "Don't use multithreading together with CPU-compare.");
if (m_bEnabled)
return;
//TODO: error checking
m_hPipe = CreateFile(
PIPENAME,
GENERIC_READ,
0, //share
NULL,
OPEN_EXISTING,
0,
NULL);
_assert_msg_(GEKKO, m_hPipe != INVALID_HANDLE_VALUE, "Failed to connect to pipe. %08x (2 = file not found)", GetLastError());
m_bEnabled = true;
m_bIsServer = false;
}
void Stop()
{
if (m_bEnabled)
{
if (m_bIsServer)
{
DisconnectNamedPipe(m_hPipe);
CloseHandle(m_hPipe);
}
else
{
CloseHandle(m_hPipe); //both for server and client i guess
}
m_bEnabled=false;
}
}
int Sync()
{
_assert_msg_(GEKKO,0,"Sync - PC = %08x", PC);
PowerPC::PowerPCState state;
if (!m_bEnabled)
return 0;
if (m_bIsServer) // This should be interpreter
{
//write cpu state to m_hPipe
HRESULT result;
u32 written;
// LogManager::Redraw();
result = WriteFile(m_hPipe, &PowerPC::ppcState, stateSize, (LPDWORD)&written,FALSE);
//_assert_msg_(GEKKO, 0, "Server Wrote!");
if (FAILED(result))
{
_assert_msg_(GEKKO,0,"Failed to write cpu state to named pipe");
Stop();
}
// LogManager::Redraw();
}
else // This should be JIT
{
u32 read;
memset(&state,0xcc,stateSize);
BOOL res = ReadFile(m_hPipe, &state, stateSize, (LPDWORD)&read, FALSE);
//_assert_msg_(GEKKO, 0, "Client got data!");
//read cpu state to m_hPipe and compare
//if any errors, print report
if (!res || read != stateSize)
{
_assert_msg_(GEKKO,0,"Failed to read cpu state from named pipe");
Stop();
}
else
{
bool difference = false;
for (int i=0; i<32; i++)
{
if (PowerPC::ppcState.gpr[i] != state.gpr[i])
{
LOG(GEKKO, "DIFFERENCE - r%i (local %08x, remote %08x)", i, PowerPC::ppcState.gpr[i], state.gpr[i]);
difference = true;
}
}
for (int i=0; i<32; i++)
{
for (int j=0; j<2; j++)
{
if (PowerPC::ppcState.ps[i][j] != state.ps[i][j])
{
LOG(GEKKO, "DIFFERENCE - ps%i_%i (local %f, remote %f)", i, j, PowerPC::ppcState.ps[i][j], state.ps[i][j]);
difference = true;
}
}
}
if (GetCR() != state.cr)
{
LOG(GEKKO, "DIFFERENCE - CR (local %08x, remote %08x)", PowerPC::ppcState.cr, state.cr);
difference = true;
}
if (PowerPC::ppcState.pc != state.pc)
{
LOG(GEKKO, "DIFFERENCE - PC (local %08x, remote %08x)", PowerPC::ppcState.pc, state.pc);
difference = true;
}
//if (PowerPC::ppcState.npc != state.npc)
///{
// LOG(GEKKO, "DIFFERENCE - NPC (local %08x, remote %08x)", PowerPC::ppcState.npc, state.npc);
// difference = true;
//}
if (PowerPC::ppcState.msr != state.msr)
{
LOG(GEKKO, "DIFFERENCE - MSR (local %08x, remote %08x)", PowerPC::ppcState.msr, state.msr);
difference = true;
}
if (PowerPC::ppcState.fpscr != state.fpscr)
{
LOG(GEKKO, "DIFFERENCE - FPSCR (local %08x, remote %08x)", PowerPC::ppcState.fpscr, state.fpscr);
difference = true;
}
if (difference)
{
Host_UpdateLogDisplay();
//Also show drec compare window here
//CDynaViewDlg::Show(true);
//CDynaViewDlg::ViewAddr(m_BlockStart);
//CDynaViewDlg::Show(true);
//Sleep(INFINITE);
return false;
}
else
{
return true;
//LOG(GEKKO, "No difference!");
}
}
}
return 0;
}
bool IsEnabled()
{
return m_bEnabled;
}
bool IsServer()
{
return m_bIsServer;
}
}
#else
namespace CPUCompare
{
void StartServer() { }
void ConnectAsClient() { }
void Stop() { }
int Sync() { return 0; }
bool IsEnabled() { return false; }
bool IsServer() { return false; }
}
// #error Provide a CPUCompare implementation or dummy it out, please
#endif

View File

@ -1,50 +0,0 @@
// 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/
// Sets up and maintains interprocess communication to make it possible
// to easily compare any two cpu cores by running two instances of DolphinHLE and
// comparing them to each other.
//
#ifndef _CPUCOMPARE_H
#define _CPUCOMPARE_H
#include "Common.h"
namespace CPUCompare
{
// start the server
void StartServer();
// connect as client
void ConnectAsClient();
// stop
void Stop();
// sync
int Sync();
// IsEnabled
bool IsEnabled();
// IsServer
bool IsServer();
void SetBlockStart(u32 addr);
}
#endif

View File

@ -459,10 +459,10 @@ void Write16(const u16 _Value, const u32 _Address)
// This happens at 4 khz, since 32 bytes at 4khz = 4 bytes at 32 khz (16bit stereo pcm)
void UpdateAudioDMA()
{
Common::PluginDSP *dsp = CPluginManager::GetInstance().GetDSP();
if (g_audioDMA.AudioDMAControl.Enabled && g_audioDMA.BlocksLeft) {
// Read audio at g_audioDMA.ReadAddress in RAM and push onto an external audio fifo in the emulator,
// to be mixed with the disc streaming output. If that audio queue fills up, we delay the emulator.
Common::PluginDSP *dsp = CPluginManager::GetInstance().GetDSP();
// TO RESTORE OLD BEHAVIOUR, COMMENT OUT THIS LINE
dsp->DSP_SendAIBuffer(g_audioDMA.ReadAddress, AudioInterface::GetDSPSampleRate());
@ -479,7 +479,7 @@ void UpdateAudioDMA()
} else {
// Send silence. Yeah, it's a bit of a waste to sample rate convert silence.
// or hm. Maybe we shouldn't do this :)
// PluginDSP::DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
dsp->DSP_SendAIBuffer(0, AudioInterface::GetDSPSampleRate());
}
}

View File

@ -196,4 +196,5 @@ void ApplyARPatches()
{
ActionReplay::RunAllActive();
}
} // namespace

View File

@ -27,7 +27,7 @@
When plugins are freed and loaded:
In an attempt to avoid the crash that occurs when the use LoadLibrary() and FreeLibrary() often
(every tiem a game is stopped and started) these functions will only be used when
(every time a game is stopped and started) these functions will only be used when
1. Dolphin is started
2. A plugin is changed
3. Dolphin is closed
@ -90,8 +90,10 @@ CPluginManager::CPluginManager() :
// Set initial values to NULL, this is only done when Dolphin is started
m_video = NULL;
m_dsp = NULL;
for (int i = 0; i < MAXPADS; i++) m_pad[i] = NULL;
for (int i = 0; i < MAXWIIMOTES; i++) m_wiimote[i] = NULL;
for (int i = 0; i < MAXPADS; i++)
m_pad[i] = NULL;
for (int i = 0; i < MAXWIIMOTES; i++)
m_wiimote[i] = NULL;
}
// This will call FreeLibrary() for all plugins
@ -100,7 +102,6 @@ CPluginManager::~CPluginManager()
Console::Print("Delete CPluginManager\n");
delete m_PluginGlobals;
delete m_dsp;
for (int i = 0; i < MAXPADS; i++) {
@ -112,10 +113,10 @@ CPluginManager::~CPluginManager()
}
for (int i = 0; i < MAXWIIMOTES; i++)
if (m_wiimote[i]) delete m_wiimote[i];
delete m_video;
if (m_wiimote[i])
delete m_wiimote[i];
delete m_video;
}
//////////////////////////////////////////////
@ -126,13 +127,13 @@ CPluginManager::~CPluginManager()
// Function: Point the m_pad[] and other variables to a certain plugin
bool CPluginManager::InitPlugins()
{
if (! GetDSP()) {
if (!GetDSP()) {
PanicAlert("Can't init DSP Plugin");
return false;
}
Console::Print("Before GetVideo\n");
if (! GetVideo()) {
if (!GetVideo()) {
PanicAlert("Can't init Video Plugin");
return false;
}
@ -146,11 +147,13 @@ bool CPluginManager::InitPlugins()
for (int i = 0; i < MAXPADS; i++)
{
// Check that the plugin has a name
if (! m_params.m_strPadPlugin[i].empty()) GetPad(i);
if (!m_params.m_strPadPlugin[i].empty())
GetPad(i);
// Check that GetPad succeeded
if (m_pad[i] != NULL) pad = true;
if (m_pad[i] != NULL)
pad = true;
}
if (! pad)
if (!pad)
{
PanicAlert("Can't init any PAD Plugins");
return false;
@ -159,13 +162,13 @@ bool CPluginManager::InitPlugins()
// Init wiimote
if (m_params.bWii) {
for (int i = 0; i < MAXWIIMOTES; i++) {
if (! m_params.m_strWiimotePlugin[i].empty())
if (!m_params.m_strWiimotePlugin[i].empty())
GetWiimote(i);
if (m_wiimote[i] != NULL)
wiimote = true;
}
if (! wiimote) {
if (!wiimote) {
PanicAlert("Can't init any Wiimote Plugins");
return false;
}
@ -189,7 +192,8 @@ void CPluginManager::ShutdownPlugins()
for (int i = 0; i < MAXWIIMOTES; i++)
{
if (m_wiimote[i]) m_wiimote[i]->Shutdown();
if (m_wiimote[i])
m_wiimote[i]->Shutdown();
//delete m_wiimote[i];
//m_wiimote[i] = NULL;
}
@ -284,7 +288,8 @@ void *CPluginManager::LoadPlugin(const char *_rFilename, int Number)
Common::CPlugin *plugin = NULL;
// Check again that the file exists, the first check is when CPluginInfo info is created
if (! File::Exists(_rFilename)) return NULL;
if (!File::Exists(_rFilename))
return NULL;
switch (type)
{
@ -452,11 +457,13 @@ void CPluginManager::FreeVideo()
delete m_video;
m_video = NULL;
}
void CPluginManager::FreeDSP()
{
delete m_dsp;
m_dsp = NULL;
}
void CPluginManager::FreePad(u32 Pad)
{
if (Pad < MAXPADS) {
@ -464,6 +471,7 @@ void CPluginManager::FreePad(u32 Pad)
m_pad[Pad] = NULL;
}
}
void CPluginManager::FreeWiimote(u32 Wiimote)
{
if (Wiimote < MAXWIIMOTES)
@ -509,7 +517,7 @@ void CPluginManager::OpenConfig(void* _Parent, const char *_rFilename, PLUGIN_TY
// Open debugging window. Type = Video or DSP. Show = Show or hide window.
void CPluginManager::OpenDebug(void* _Parent, const char *_rFilename, PLUGIN_TYPE Type, bool Show)
{
if (! File::Exists(_rFilename))
if (!File::Exists(_rFilename))
{
PanicAlert("Can't find plugin %s", _rFilename);
return;

View File

@ -28,7 +28,6 @@
#include "Jit.h"
#include "JitCache.h"
#include "../../HW/CPUCompare.h"
#include "../../HW/GPFifo.h"
#include "../../Core.h"
#include "JitAsm.h"

View File

@ -231,7 +231,7 @@ void CheckExceptions()
SRR1 = MSR & 0x0780FF77;
NPC = 0x80000C00;
LOGV(GEKKO, 1, "EXCEPTION_SYSCALL (PC=%08x)",PC);
LOGV(GEKKO, 1, "EXCEPTION_SYSCALL (PC=%08x)", PC);
ppcState.Exceptions &= ~EXCEPTION_SYSCALL;
SRR1 |= 0x02; //recoverable
}

View File

@ -30,7 +30,6 @@ files = ["Console.cpp",
"HW/AudioInterface.cpp",
"HW/CommandProcessor.cpp",
"HW/CPU.cpp",
"HW/CPUCompare.cpp",
"HW/DSP.cpp",
"HW/DVDInterface.cpp",
"HW/EXI.cpp",

View File

@ -26,6 +26,7 @@
#include "PowerPC/PowerPC.h"
namespace Core {
FILE *tracefile;
bool bReadTrace = false;
@ -56,8 +57,8 @@ void StopTrace()
}
}
int stateSize = 32*4;// + 32*16 + 6*4;
u64 tb;
static int stateSize = 32*4;// + 32*16 + 6*4;
static u64 tb;
int SyncTrace()
{

View File

@ -245,7 +245,7 @@ bool DolphinApp::OnInit()
ini.Get("MainWindow", "w", &w, 800);
ini.Get("MainWindow", "h", &h, 600);
// -------------------
if(UseDebugger)
if (UseDebugger)
{
main_frame = new CFrame((wxFrame*) NULL, wxID_ANY, wxString::FromAscii(title),
wxPoint(x, y), wxSize(w, h));

View File

@ -23,24 +23,26 @@
#include "Fifo.h"
extern u8* g_pVideoData;
// TODO (mb2): move/rm this global
volatile u32 g_XFBUpdateRequested = FALSE;
extern u8* g_pVideoData;
#ifndef _WIN32
static bool fifoStateRun = true;
#endif
namespace {
// STATE_TO_SAVE
static bool fifoStateRun = false;
static u8 *videoBuffer;
static Common::Event fifo_exit_event;
// STATE_TO_SAVE
static int size = 0;
} // namespace
void Fifo_DoState(PointerWrap &p)
{
p.DoArray(videoBuffer, FIFO_SIZE);
p.Do(size);
int pos = (int)(g_pVideoData-videoBuffer); // get offset
int pos = (int)(g_pVideoData - videoBuffer); // get offset
p.Do(pos); // read or write offset (depends on the mode afaik)
g_pVideoData = &videoBuffer[pos]; // overwrite g_pVideoData -> expected no change when load ss and change when save ss
}
@ -48,25 +50,16 @@ void Fifo_DoState(PointerWrap &p)
void Fifo_Init()
{
videoBuffer = (u8*)AllocateMemoryPages(FIFO_SIZE);
#ifndef _WIN32
fifo_exit_event.Init();
fifoStateRun = true;
#endif
g_XFBUpdateRequested = FALSE;
}
void Fifo_Shutdown()
{
if (fifoStateRun)
PanicAlert("Fifo shutting down while active");
FreeMemoryPages(videoBuffer, FIFO_SIZE);
#ifndef _WIN32
fifoStateRun = false;
#endif
}
void Fifo_Stop()
{
#ifndef _WIN32
fifoStateRun = false;
#endif
}
u8* FAKE_GetFifoStartPtr()
@ -79,16 +72,18 @@ u8* FAKE_GetFifoEndPtr()
return &videoBuffer[size];
}
// The loop in EnterLoop sends data through this function.
// TODO: Possibly inline it? This one is exported so it will likely not be inlined at all.
void Video_SendFifoData(u8* _uData, u32 len)
{
if (size + len >= FIFO_SIZE)
{
int pos = (int)(g_pVideoData-videoBuffer);
if (size-pos > pos)
int pos = (int)(g_pVideoData - videoBuffer);
if (size - pos > pos)
{
PanicAlert("FIFO out of bounds (sz = %i, at %08x)", size, pos);
}
memmove(&videoBuffer[0], &videoBuffer[pos], size - pos );
memmove(&videoBuffer[0], &videoBuffer[pos], size - pos);
size -= pos;
g_pVideoData = FAKE_GetFifoStartPtr();
}
@ -97,18 +92,23 @@ void Video_SendFifoData(u8* _uData, u32 len)
OpcodeDecoder_Run();
}
void Fifo_ExitLoop()
{
fifoStateRun = false;
fifo_exit_event.Wait();
fifo_exit_event.Shutdown();
}
void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
{
SCPFifoStruct &_fifo = *video_initialize.pCPFifo;
s32 distToSend;
#ifdef _WIN32
// TODO(ector): Don't peek so often!
while (video_initialize.pPeekMessages())
#else
while (fifoStateRun)
#endif
{
#ifdef _WIN32
video_initialize.pPeekMessages();
#endif
if (_fifo.CPReadWriteDistance == 0)
Common::SleepCurrentThread(1);
@ -156,16 +156,18 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
else
{
#if 0 // ugly random GP slowdown for testing DC robustness... TODO: remove when completly sure DC is ok
int r=rand();if ((r&0xF)==r) Common::SleepCurrentThread(r);
distToSend = 32;
readPtr += 32;
if ( readPtr >= _fifo.CPEnd)
readPtr = _fifo.CPBase;
int r = rand();
if ((r & 0xF) == r)
Common::SleepCurrentThread(r);
distToSend = 32;
readPtr += 32;
if (readPtr >= _fifo.CPEnd)
readPtr = _fifo.CPBase;
#else
distToSend = _fifo.CPReadWriteDistance;
// send 1024B chunk max lenght to have better control over PeekMessages' period
// send 1024B chunk max length to have better control over PeekMessages' period
distToSend = distToSend > 1024 ? 1024 : distToSend;
if ( (distToSend+readPtr) >= _fifo.CPEnd) // TODO: better?
if ((distToSend + readPtr) >= _fifo.CPEnd) // TODO: better?
{
distToSend =_fifo.CPEnd - readPtr;
readPtr = _fifo.CPBase;
@ -182,5 +184,5 @@ void Fifo_EnterLoop(const SVideoInitialize &video_initialize)
Common::SyncInterlockedExchange((LONG*)&_fifo.CPReadIdle, 1);
}
}
fifo_exit_event.Set();
}

View File

@ -27,9 +27,13 @@
void Fifo_Init();
void Fifo_Shutdown();
/* void Video_SendFifoData(); */ // defined in plugin spec - implemented in Fifo.cpp
// These two are for dual core mode only.
void Fifo_EnterLoop(const SVideoInitialize &video_initialize);
void Fifo_ExitLoop();
void Fifo_DoState(PointerWrap &f);
void Fifo_Stop();
#endif